• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) Texas Instruments - http://www.ti.com/
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /**
18 * @file V4LCameraAdapter.cpp
19 *
20 * This file maps the Camera Hardware Interface to V4L2.
21 *
22 */
23 
24 
25 #include "V4LCameraAdapter.h"
26 #include "CameraHal.h"
27 #include "TICameraParameters.h"
28 #include "DebugUtils.h"
29 #include <signal.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <fcntl.h>
34 #include <unistd.h>
35 #include <errno.h>
36 #include <sys/ioctl.h>
37 #include <sys/mman.h>
38 #include <sys/select.h>
39 #include <linux/videodev.h>
40 
41 #include <ui/GraphicBuffer.h>
42 #include <ui/GraphicBufferMapper.h>
43 
44 #include <cutils/properties.h>
45 #define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
46 static int mDebugFps = 0;
47 
48 #define Q16_OFFSET 16
49 
50 #define HERE(Msg) {CAMHAL_LOGEB("--=== %s===--\n", Msg);}
51 
52 namespace Ti {
53 namespace Camera {
54 
55 //frames skipped before recalculating the framerate
56 #define FPS_PERIOD 30
57 
58 //define this macro to save first few raw frames when starting the preview.
59 //#define SAVE_RAW_FRAMES 1
60 //#define DUMP_CAPTURE_FRAME 1
61 //#define PPM_PER_FRAME_CONVERSION 1
62 
63 //Proto Types
64 static void convertYUV422i_yuyvTouyvy(uint8_t *src, uint8_t *dest, size_t size );
65 static void convertYUV422ToNV12Tiler(unsigned char *src, unsigned char *dest, int width, int height );
66 static void convertYUV422ToNV12(unsigned char *src, unsigned char *dest, int width, int height );
67 
68 android::Mutex gV4LAdapterLock;
69 char device[15];
70 
71 
72 /*--------------------Camera Adapter Class STARTS here-----------------------------*/
73 
74 /*--------------------V4L wrapper functions -------------------------------*/
v4lIoctl(int fd,int req,void * argp)75 status_t V4LCameraAdapter::v4lIoctl (int fd, int req, void* argp) {
76     status_t ret = NO_ERROR;
77     errno = 0;
78 
79     do {
80         ret = ioctl (fd, req, argp);
81     }while (-1 == ret && EINTR == errno);
82 
83     return ret;
84 }
85 
v4lInitMmap(int & count)86 status_t V4LCameraAdapter::v4lInitMmap(int& count) {
87     status_t ret = NO_ERROR;
88 
89     //First allocate adapter internal buffers at V4L level for USB Cam
90     //These are the buffers from which we will copy the data into overlay buffers
91     /* Check if camera can handle NB_BUFFER buffers */
92     mVideoInfo->rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
93     mVideoInfo->rb.memory = V4L2_MEMORY_MMAP;
94     mVideoInfo->rb.count = count;
95 
96     ret = v4lIoctl(mCameraHandle, VIDIOC_REQBUFS, &mVideoInfo->rb);
97     if (ret < 0) {
98         CAMHAL_LOGEB("VIDIOC_REQBUFS failed: %s", strerror(errno));
99         return ret;
100     }
101 
102     count = mVideoInfo->rb.count;
103     for (int i = 0; i < count; i++) {
104 
105         memset (&mVideoInfo->buf, 0, sizeof (struct v4l2_buffer));
106 
107         mVideoInfo->buf.index = i;
108         mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
109         mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;
110 
111         ret = v4lIoctl (mCameraHandle, VIDIOC_QUERYBUF, &mVideoInfo->buf);
112         if (ret < 0) {
113             CAMHAL_LOGEB("Unable to query buffer (%s)", strerror(errno));
114             return ret;
115         }
116 
117         mVideoInfo->mem[i] = mmap (NULL,
118                mVideoInfo->buf.length,
119                PROT_READ | PROT_WRITE,
120                MAP_SHARED,
121                mCameraHandle,
122                mVideoInfo->buf.m.offset);
123 
124         CAMHAL_LOGVB(" mVideoInfo->mem[%d]=%p ; mVideoInfo->buf.length = %d", i, mVideoInfo->mem[i], mVideoInfo->buf.length);
125         if (mVideoInfo->mem[i] == MAP_FAILED) {
126             CAMHAL_LOGEB("Unable to map buffer [%d]. (%s)", i, strerror(errno));
127             return -1;
128         }
129     }
130     return ret;
131 }
132 
v4lInitUsrPtr(int & count)133 status_t V4LCameraAdapter::v4lInitUsrPtr(int& count) {
134     status_t ret = NO_ERROR;
135 
136     mVideoInfo->rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
137     mVideoInfo->rb.memory = V4L2_MEMORY_USERPTR;
138     mVideoInfo->rb.count = count;
139 
140     ret = v4lIoctl(mCameraHandle, VIDIOC_REQBUFS, &mVideoInfo->rb);
141     if (ret < 0) {
142         CAMHAL_LOGEB("VIDIOC_REQBUFS failed for USERPTR: %s", strerror(errno));
143         return ret;
144     }
145 
146     count = mVideoInfo->rb.count;
147     return ret;
148 }
149 
v4lStartStreaming()150 status_t V4LCameraAdapter::v4lStartStreaming () {
151     status_t ret = NO_ERROR;
152     enum v4l2_buf_type bufType;
153 
154     if (!mVideoInfo->isStreaming) {
155         bufType = V4L2_BUF_TYPE_VIDEO_CAPTURE;
156 
157         ret = v4lIoctl (mCameraHandle, VIDIOC_STREAMON, &bufType);
158         if (ret < 0) {
159             CAMHAL_LOGEB("StartStreaming: Unable to start capture: %s", strerror(errno));
160             return ret;
161         }
162         mVideoInfo->isStreaming = true;
163     }
164     return ret;
165 }
166 
v4lStopStreaming(int nBufferCount)167 status_t V4LCameraAdapter::v4lStopStreaming (int nBufferCount) {
168     status_t ret = NO_ERROR;
169     enum v4l2_buf_type bufType;
170 
171     if (mVideoInfo->isStreaming) {
172         bufType = V4L2_BUF_TYPE_VIDEO_CAPTURE;
173 
174         ret = v4lIoctl (mCameraHandle, VIDIOC_STREAMOFF, &bufType);
175         if (ret < 0) {
176             CAMHAL_LOGEB("StopStreaming: Unable to stop capture: %s", strerror(errno));
177             goto EXIT;
178         }
179         mVideoInfo->isStreaming = false;
180 
181         /* Unmap buffers */
182         mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
183         mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;
184         for (int i = 0; i < nBufferCount; i++) {
185             if (munmap(mVideoInfo->mem[i], mVideoInfo->buf.length) < 0) {
186                 CAMHAL_LOGEA("munmap() failed");
187             }
188         }
189 
190         //free the memory allocated during REQBUFS, by setting the count=0
191         mVideoInfo->rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
192         mVideoInfo->rb.memory = V4L2_MEMORY_MMAP;
193         mVideoInfo->rb.count = 0;
194 
195         ret = v4lIoctl(mCameraHandle, VIDIOC_REQBUFS, &mVideoInfo->rb);
196         if (ret < 0) {
197             CAMHAL_LOGEB("VIDIOC_REQBUFS failed: %s", strerror(errno));
198             goto EXIT;
199         }
200     }
201 EXIT:
202     return ret;
203 }
204 
v4lSetFormat(int width,int height,uint32_t pix_format)205 status_t V4LCameraAdapter::v4lSetFormat (int width, int height, uint32_t pix_format) {
206     status_t ret = NO_ERROR;
207 
208     mVideoInfo->format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
209     ret = v4lIoctl(mCameraHandle, VIDIOC_G_FMT, &mVideoInfo->format);
210     if (ret < 0) {
211         CAMHAL_LOGEB("VIDIOC_G_FMT Failed: %s", strerror(errno));
212     }
213 
214     mVideoInfo->width = width;
215     mVideoInfo->height = height;
216     mVideoInfo->framesizeIn = (width * height << 1);
217     mVideoInfo->formatIn = DEFAULT_PIXEL_FORMAT;
218 
219     mVideoInfo->format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
220     mVideoInfo->format.fmt.pix.width = width;
221     mVideoInfo->format.fmt.pix.height = height;
222     mVideoInfo->format.fmt.pix.pixelformat = pix_format;
223 
224     ret = v4lIoctl(mCameraHandle, VIDIOC_S_FMT, &mVideoInfo->format);
225     if (ret < 0) {
226         CAMHAL_LOGEB("VIDIOC_S_FMT Failed: %s", strerror(errno));
227         return ret;
228     }
229     v4lIoctl(mCameraHandle, VIDIOC_G_FMT, &mVideoInfo->format);
230     CAMHAL_LOGDB("VIDIOC_G_FMT : WxH = %dx%d", mVideoInfo->format.fmt.pix.width, mVideoInfo->format.fmt.pix.height);
231     return ret;
232 }
233 
restartPreview()234 status_t V4LCameraAdapter::restartPreview ()
235 {
236     status_t ret = NO_ERROR;
237     int width = 0;
238     int height = 0;
239     struct v4l2_streamparm streamParams;
240 
241     //configure for preview size and pixel format.
242     mParams.getPreviewSize(&width, &height);
243 
244     ret = v4lSetFormat (width, height, DEFAULT_PIXEL_FORMAT);
245     if (ret < 0) {
246         CAMHAL_LOGEB("v4lSetFormat Failed: %s", strerror(errno));
247         goto EXIT;
248     }
249 
250     ret = v4lInitMmap(mPreviewBufferCount);
251     if (ret < 0) {
252         CAMHAL_LOGEB("v4lInitMmap Failed: %s", strerror(errno));
253         goto EXIT;
254     }
255 
256     //set frame rate
257     streamParams.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
258     streamParams.parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
259     streamParams.parm.capture.capturemode = V4L2_MODE_HIGHQUALITY;
260     streamParams.parm.capture.timeperframe.denominator = FPS_PERIOD;
261     streamParams.parm.capture.timeperframe.numerator= 1;
262     ret = v4lIoctl(mCameraHandle, VIDIOC_S_PARM, &streamParams);
263     if (ret < 0) {
264         CAMHAL_LOGEB("VIDIOC_S_PARM Failed: %s", strerror(errno));
265         goto EXIT;
266     }
267 
268     for (int i = 0; i < mPreviewBufferCountQueueable; i++) {
269 
270         mVideoInfo->buf.index = i;
271         mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
272         mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;
273 
274         ret = v4lIoctl(mCameraHandle, VIDIOC_QBUF, &mVideoInfo->buf);
275         if (ret < 0) {
276             CAMHAL_LOGEA("VIDIOC_QBUF Failed");
277             goto EXIT;
278         }
279         nQueued++;
280     }
281 
282     ret = v4lStartStreaming();
283     CAMHAL_LOGDA("Ready for preview....");
284 EXIT:
285     return ret;
286 }
287 
288 /*--------------------Camera Adapter Functions-----------------------------*/
initialize(CameraProperties::Properties * caps)289 status_t V4LCameraAdapter::initialize(CameraProperties::Properties* caps)
290 {
291     char value[PROPERTY_VALUE_MAX];
292 
293     LOG_FUNCTION_NAME;
294     property_get("debug.camera.showfps", value, "0");
295     mDebugFps = atoi(value);
296 
297     int ret = NO_ERROR;
298 
299     // Allocate memory for video info structure
300     mVideoInfo = (struct VideoInfo *) calloc (1, sizeof (struct VideoInfo));
301     if(!mVideoInfo) {
302         ret = NO_MEMORY;
303         goto EXIT;
304     }
305 
306     if ((mCameraHandle = open(device, O_RDWR | O_NONBLOCK) ) == -1) {
307         CAMHAL_LOGEB("Error while opening handle to V4L2 Camera: %s", strerror(errno));
308         ret = BAD_VALUE;
309         goto EXIT;
310     }
311 
312     ret = v4lIoctl (mCameraHandle, VIDIOC_QUERYCAP, &mVideoInfo->cap);
313     if (ret < 0) {
314         CAMHAL_LOGEA("Error when querying the capabilities of the V4L Camera");
315         ret = BAD_VALUE;
316         goto EXIT;
317     }
318 
319     if ((mVideoInfo->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
320         CAMHAL_LOGEA("Error while adapter initialization: video capture not supported.");
321         ret = BAD_VALUE;
322         goto EXIT;
323     }
324 
325     if (!(mVideoInfo->cap.capabilities & V4L2_CAP_STREAMING)) {
326         CAMHAL_LOGEA("Error while adapter initialization: Capture device does not support streaming i/o");
327         ret = BAD_VALUE;
328         goto EXIT;
329     }
330 
331     // Initialize flags
332     mPreviewing = false;
333     mVideoInfo->isStreaming = false;
334     mRecording = false;
335     mCapturing = false;
336 EXIT:
337     LOG_FUNCTION_NAME_EXIT;
338     return ret;
339 }
340 
fillThisBuffer(CameraBuffer * frameBuf,CameraFrame::FrameType frameType)341 status_t V4LCameraAdapter::fillThisBuffer(CameraBuffer *frameBuf, CameraFrame::FrameType frameType)
342 {
343     status_t ret = NO_ERROR;
344     int idx = 0;
345     LOG_FUNCTION_NAME;
346 
347     if ( frameType == CameraFrame::IMAGE_FRAME) { //(1 > mCapturedFrames)
348         // Signal end of image capture
349         if ( NULL != mEndImageCaptureCallback) {
350             CAMHAL_LOGDB("===========Signal End Image Capture==========");
351             mEndImageCaptureCallback(mEndCaptureData);
352         }
353         goto EXIT;
354     }
355     if ( !mVideoInfo->isStreaming ) {
356         goto EXIT;
357     }
358 
359     idx = mPreviewBufs.valueFor(frameBuf);
360     if(idx < 0) {
361         CAMHAL_LOGEB("Wrong index  = %d",idx);
362         goto EXIT;
363     }
364 
365     mVideoInfo->buf.index = idx;
366     mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
367     mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;
368 
369     ret = v4lIoctl(mCameraHandle, VIDIOC_QBUF, &mVideoInfo->buf);
370     if (ret < 0) {
371        CAMHAL_LOGEA("VIDIOC_QBUF Failed");
372        goto EXIT;
373     }
374      nQueued++;
375 EXIT:
376     LOG_FUNCTION_NAME_EXIT;
377     return ret;
378 
379 }
380 
setParameters(const android::CameraParameters & params)381 status_t V4LCameraAdapter::setParameters(const android::CameraParameters &params)
382 {
383     status_t ret = NO_ERROR;
384     int width, height;
385     struct v4l2_streamparm streamParams;
386 
387     LOG_FUNCTION_NAME;
388 
389     if(!mPreviewing && !mCapturing) {
390         params.getPreviewSize(&width, &height);
391         CAMHAL_LOGDB("Width * Height %d x %d format 0x%x", width, height, DEFAULT_PIXEL_FORMAT);
392 
393         ret = v4lSetFormat( width, height, DEFAULT_PIXEL_FORMAT);
394         if (ret < 0) {
395             CAMHAL_LOGEB(" VIDIOC_S_FMT Failed: %s", strerror(errno));
396             goto EXIT;
397         }
398         //set frame rate
399         // Now its fixed to 30 FPS
400         streamParams.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
401         streamParams.parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
402         streamParams.parm.capture.capturemode = V4L2_MODE_HIGHQUALITY;
403         streamParams.parm.capture.timeperframe.denominator = FPS_PERIOD;
404         streamParams.parm.capture.timeperframe.numerator= 1;
405         ret = v4lIoctl(mCameraHandle, VIDIOC_S_PARM, &streamParams);
406         if (ret < 0) {
407             CAMHAL_LOGEB(" VIDIOC_S_PARM Failed: %s", strerror(errno));
408             goto EXIT;
409         }
410         int actualFps = streamParams.parm.capture.timeperframe.denominator / streamParams.parm.capture.timeperframe.numerator;
411         CAMHAL_LOGDB("Actual FPS set is : %d.", actualFps);
412     }
413 
414     // Udpate the current parameter set
415     mParams = params;
416 
417 EXIT:
418     LOG_FUNCTION_NAME_EXIT;
419     return ret;
420 }
421 
422 
getParameters(android::CameraParameters & params)423 void V4LCameraAdapter::getParameters(android::CameraParameters& params)
424 {
425     LOG_FUNCTION_NAME;
426 
427     // Return the current parameter set
428     params = mParams;
429 
430     LOG_FUNCTION_NAME_EXIT;
431 }
432 
433 
434 ///API to give the buffers to Adapter
useBuffers(CameraMode mode,CameraBuffer * bufArr,int num,size_t length,unsigned int queueable)435 status_t V4LCameraAdapter::useBuffers(CameraMode mode, CameraBuffer *bufArr, int num, size_t length, unsigned int queueable)
436 {
437     status_t ret = NO_ERROR;
438 
439     LOG_FUNCTION_NAME;
440 
441     android::AutoMutex lock(mLock);
442 
443     switch(mode)
444         {
445         case CAMERA_PREVIEW:
446             mPreviewBufferCountQueueable = queueable;
447             ret = UseBuffersPreview(bufArr, num);
448             break;
449 
450         case CAMERA_IMAGE_CAPTURE:
451             mCaptureBufferCountQueueable = queueable;
452             ret = UseBuffersCapture(bufArr, num);
453             break;
454 
455         case CAMERA_VIDEO:
456             //@warn Video capture is not fully supported yet
457             mPreviewBufferCountQueueable = queueable;
458             ret = UseBuffersPreview(bufArr, num);
459             break;
460 
461         case CAMERA_MEASUREMENT:
462             break;
463 
464         default:
465             break;
466         }
467 
468     LOG_FUNCTION_NAME_EXIT;
469 
470     return ret;
471 }
472 
UseBuffersCapture(CameraBuffer * bufArr,int num)473 status_t V4LCameraAdapter::UseBuffersCapture(CameraBuffer *bufArr, int num) {
474     int ret = NO_ERROR;
475 
476     LOG_FUNCTION_NAME;
477     if(NULL == bufArr) {
478         ret = BAD_VALUE;
479         goto EXIT;
480     }
481 
482     for (int i = 0; i < num; i++) {
483         //Associate each Camera internal buffer with the one from Overlay
484         mCaptureBufs.add(&bufArr[i], i);
485         CAMHAL_LOGDB("capture- buff [%d] = 0x%x ",i, mCaptureBufs.keyAt(i));
486     }
487 
488     mCaptureBuffersAvailable.clear();
489     for (int i = 0; i < mCaptureBufferCountQueueable; i++ ) {
490         mCaptureBuffersAvailable.add(&mCaptureBuffers[i], 0);
491     }
492 
493     // initial ref count for undeqeueued buffers is 1 since buffer provider
494     // is still holding on to it
495     for (int i = mCaptureBufferCountQueueable; i < num; i++ ) {
496         mCaptureBuffersAvailable.add(&mCaptureBuffers[i], 1);
497     }
498 
499     // Update the preview buffer count
500     mCaptureBufferCount = num;
501 EXIT:
502     LOG_FUNCTION_NAME_EXIT;
503     return ret;
504 
505 }
506 
UseBuffersPreview(CameraBuffer * bufArr,int num)507 status_t V4LCameraAdapter::UseBuffersPreview(CameraBuffer *bufArr, int num)
508 {
509     int ret = NO_ERROR;
510     LOG_FUNCTION_NAME;
511 
512     if(NULL == bufArr) {
513         ret = BAD_VALUE;
514         goto EXIT;
515     }
516 
517     ret = v4lInitMmap(num);
518     if (ret == NO_ERROR) {
519         for (int i = 0; i < num; i++) {
520             //Associate each Camera internal buffer with the one from Overlay
521             mPreviewBufs.add(&bufArr[i], i);
522             CAMHAL_LOGDB("Preview- buff [%d] = 0x%x ",i, mPreviewBufs.keyAt(i));
523         }
524 
525         // Update the preview buffer count
526         mPreviewBufferCount = num;
527     }
528 EXIT:
529     LOG_FUNCTION_NAME_EXIT;
530     return ret;
531 }
532 
takePicture()533 status_t V4LCameraAdapter::takePicture() {
534     status_t ret = NO_ERROR;
535     int width = 0;
536     int height = 0;
537     size_t yuv422i_buff_size = 0;
538     int index = 0;
539     char *fp = NULL;
540     CameraBuffer *buffer = NULL;
541     CameraFrame frame;
542 
543     LOG_FUNCTION_NAME;
544 
545     android::AutoMutex lock(mCaptureBufsLock);
546 
547     if(mCapturing) {
548         CAMHAL_LOGEA("Already Capture in Progress...");
549         ret = BAD_VALUE;
550         goto EXIT;
551     }
552 
553     mCapturing = true;
554     mPreviewing = false;
555 
556     // Stop preview streaming
557     ret = v4lStopStreaming(mPreviewBufferCount);
558     if (ret < 0 ) {
559         CAMHAL_LOGEB("v4lStopStreaming Failed: %s", strerror(errno));
560         goto EXIT;
561     }
562 
563     //configure for capture image size and pixel format.
564     mParams.getPictureSize(&width, &height);
565     CAMHAL_LOGDB("Image Capture Size WxH = %dx%d",width,height);
566     yuv422i_buff_size = width * height * 2;
567 
568     ret = v4lSetFormat (width, height, DEFAULT_PIXEL_FORMAT);
569     if (ret < 0) {
570         CAMHAL_LOGEB("v4lSetFormat Failed: %s", strerror(errno));
571         goto EXIT;
572     }
573 
574     ret = v4lInitMmap(mCaptureBufferCount);
575     if (ret < 0) {
576         CAMHAL_LOGEB("v4lInitMmap Failed: %s", strerror(errno));
577         goto EXIT;
578     }
579 
580     for (int i = 0; i < mCaptureBufferCountQueueable; i++) {
581 
582        mVideoInfo->buf.index = i;
583        mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
584        mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;
585 
586        ret = v4lIoctl(mCameraHandle, VIDIOC_QBUF, &mVideoInfo->buf);
587        if (ret < 0) {
588            CAMHAL_LOGEA("VIDIOC_QBUF Failed");
589            ret = BAD_VALUE;
590            goto EXIT;
591        }
592        nQueued++;
593     }
594 
595     ret = v4lStartStreaming();
596     if (ret < 0) {
597         CAMHAL_LOGEB("v4lStartStreaming Failed: %s", strerror(errno));
598         goto EXIT;
599     }
600 
601     CAMHAL_LOGDA("Streaming started for Image Capture");
602 
603     //get the frame and send to encode as JPG
604     fp = this->GetFrame(index);
605     if(!fp) {
606         CAMHAL_LOGEA("!!! Captured frame is NULL !!!!");
607         ret = BAD_VALUE;
608         goto EXIT;
609     }
610 
611     CAMHAL_LOGDA("::Capture Frame received from V4L::");
612     buffer = mCaptureBufs.keyAt(index);
613     CAMHAL_LOGVB("## captureBuf[%d] = 0x%x, yuv422i_buff_size=%d", index, buffer->opaque, yuv422i_buff_size);
614 
615     //copy the yuv422i data to the image buffer.
616     memcpy(buffer->opaque, fp, yuv422i_buff_size);
617 
618 #ifdef DUMP_CAPTURE_FRAME
619     //dump the YUV422 buffer in to a file
620     //a folder should have been created at /data/misc/camera/raw/
621     {
622         int fd =-1;
623         fd = open("/data/misc/camera/raw/captured_yuv422i_dump.yuv", O_CREAT | O_WRONLY | O_SYNC | O_TRUNC, 0777);
624         if(fd < 0) {
625             CAMHAL_LOGEB("Unable to open file: %s",  strerror(fd));
626         }
627         else {
628             write(fd, fp, yuv422i_buff_size );
629             close(fd);
630             CAMHAL_LOGDB("::Captured Frame dumped at /data/misc/camera/raw/captured_yuv422i_dump.yuv::");
631         }
632     }
633 #endif
634 
635     CAMHAL_LOGDA("::sending capture frame to encoder::");
636     frame.mFrameType = CameraFrame::IMAGE_FRAME;
637     frame.mBuffer = buffer;
638     frame.mLength = yuv422i_buff_size;
639     frame.mWidth = width;
640     frame.mHeight = height;
641     frame.mAlignment = width*2;
642     frame.mOffset = 0;
643     frame.mTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);
644     frame.mFrameMask = (unsigned int)CameraFrame::IMAGE_FRAME;
645     frame.mQuirks |= CameraFrame::ENCODE_RAW_YUV422I_TO_JPEG;
646     frame.mQuirks |= CameraFrame::FORMAT_YUV422I_YUYV;
647 
648     ret = setInitFrameRefCount(frame.mBuffer, frame.mFrameMask);
649     if (ret != NO_ERROR) {
650         CAMHAL_LOGDB("Error in setInitFrameRefCount %d", ret);
651     } else {
652         ret = sendFrameToSubscribers(&frame);
653     }
654 
655     // Stop streaming after image capture
656     ret = v4lStopStreaming(mCaptureBufferCount);
657     if (ret < 0 ) {
658         CAMHAL_LOGEB("v4lStopStreaming Failed: %s", strerror(errno));
659         goto EXIT;
660     }
661 
662     ret = restartPreview();
663 EXIT:
664     LOG_FUNCTION_NAME_EXIT;
665     return ret;
666 }
667 
stopImageCapture()668 status_t V4LCameraAdapter::stopImageCapture()
669 {
670     status_t ret = NO_ERROR;
671     LOG_FUNCTION_NAME;
672 
673     //Release image buffers
674     if ( NULL != mReleaseImageBuffersCallback ) {
675         mReleaseImageBuffersCallback(mReleaseData);
676     }
677     mCaptureBufs.clear();
678 
679     mCapturing = false;
680     mPreviewing = true;
681     LOG_FUNCTION_NAME_EXIT;
682     return ret;
683 }
684 
autoFocus()685 status_t V4LCameraAdapter::autoFocus()
686 {
687     status_t ret = NO_ERROR;
688     LOG_FUNCTION_NAME;
689 
690     //autoFocus is not implemented. Just return.
691     LOG_FUNCTION_NAME_EXIT;
692     return ret;
693 }
694 
startPreview()695 status_t V4LCameraAdapter::startPreview()
696 {
697     status_t ret = NO_ERROR;
698 
699     LOG_FUNCTION_NAME;
700     android::AutoMutex lock(mPreviewBufsLock);
701 
702     if(mPreviewing) {
703         ret = BAD_VALUE;
704         goto EXIT;
705     }
706 
707     for (int i = 0; i < mPreviewBufferCountQueueable; i++) {
708 
709         mVideoInfo->buf.index = i;
710         mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
711         mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;
712 
713         ret = v4lIoctl(mCameraHandle, VIDIOC_QBUF, &mVideoInfo->buf);
714         if (ret < 0) {
715             CAMHAL_LOGEA("VIDIOC_QBUF Failed");
716             goto EXIT;
717         }
718         nQueued++;
719     }
720 
721     ret = v4lStartStreaming();
722 
723     // Create and start preview thread for receiving buffers from V4L Camera
724     if(!mCapturing) {
725         mPreviewThread = new PreviewThread(this);
726         CAMHAL_LOGDA("Created preview thread");
727     }
728 
729     //Update the flag to indicate we are previewing
730     mPreviewing = true;
731     mCapturing = false;
732 
733 EXIT:
734     LOG_FUNCTION_NAME_EXIT;
735     return ret;
736 }
737 
stopPreview()738 status_t V4LCameraAdapter::stopPreview()
739 {
740     enum v4l2_buf_type bufType;
741     int ret = NO_ERROR;
742 
743     LOG_FUNCTION_NAME;
744     android::AutoMutex lock(mStopPreviewLock);
745 
746     if(!mPreviewing) {
747         return NO_INIT;
748     }
749     mPreviewing = false;
750 
751     ret = v4lStopStreaming(mPreviewBufferCount);
752     if (ret < 0) {
753         CAMHAL_LOGEB("StopStreaming: FAILED: %s", strerror(errno));
754     }
755 
756     nQueued = 0;
757     nDequeued = 0;
758     mFramesWithEncoder = 0;
759 
760     mPreviewBufs.clear();
761 
762     mPreviewThread->requestExitAndWait();
763     mPreviewThread.clear();
764 
765     LOG_FUNCTION_NAME_EXIT;
766     return ret;
767 }
768 
GetFrame(int & index)769 char * V4LCameraAdapter::GetFrame(int &index)
770 {
771     int ret = NO_ERROR;
772     LOG_FUNCTION_NAME;
773 
774     mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
775     mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;
776 
777     /* DQ */
778     // Some V4L drivers, notably uvc, protect each incoming call with
779     // a driver-wide mutex.  If we use poll() or blocking VIDIOC_DQBUF ioctl
780     // here then we sometimes would run into a deadlock on VIDIO_QBUF ioctl.
781     while(true) {
782       if(!mVideoInfo->isStreaming) {
783         return NULL;
784       }
785 
786       ret = v4lIoctl(mCameraHandle, VIDIOC_DQBUF, &mVideoInfo->buf);
787       if((ret == 0) || (errno != EAGAIN)) {
788         break;
789       }
790     }
791 
792     if (ret < 0) {
793         CAMHAL_LOGEA("GetFrame: VIDIOC_DQBUF Failed");
794         return NULL;
795     }
796     nDequeued++;
797 
798     index = mVideoInfo->buf.index;
799 
800     LOG_FUNCTION_NAME_EXIT;
801     return (char *)mVideoInfo->mem[mVideoInfo->buf.index];
802 }
803 
804 //API to get the frame size required to be allocated. This size is used to override the size passed
805 //by camera service when VSTAB/VNF is turned ON for example
getFrameSize(size_t & width,size_t & height)806 status_t V4LCameraAdapter::getFrameSize(size_t &width, size_t &height)
807 {
808     status_t ret = NO_ERROR;
809     LOG_FUNCTION_NAME;
810 
811     // Just return the current preview size, nothing more to do here.
812     mParams.getPreviewSize(( int * ) &width,
813                            ( int * ) &height);
814 
815     LOG_FUNCTION_NAME_EXIT;
816 
817     return ret;
818 }
819 
getFrameDataSize(size_t & dataFrameSize,size_t bufferCount)820 status_t V4LCameraAdapter::getFrameDataSize(size_t &dataFrameSize, size_t bufferCount)
821 {
822     // We don't support meta data, so simply return
823     return NO_ERROR;
824 }
825 
getPictureBufferSize(CameraFrame & frame,size_t bufferCount)826 status_t V4LCameraAdapter::getPictureBufferSize(CameraFrame &frame, size_t bufferCount)
827 {
828     int width = 0;
829     int height = 0;
830     int bytesPerPixel = 2; // for YUV422i; default pixel format
831 
832     LOG_FUNCTION_NAME;
833 
834     mParams.getPictureSize( &width, &height );
835     frame.mLength = width * height * bytesPerPixel;
836     frame.mWidth = width;
837     frame.mHeight = height;
838     frame.mAlignment = width * bytesPerPixel;
839 
840     CAMHAL_LOGDB("Picture size: W x H = %u x %u (size=%u bytes, alignment=%u bytes)",
841                  frame.mWidth, frame.mHeight, frame.mLength, frame.mAlignment);
842     LOG_FUNCTION_NAME_EXIT;
843     return NO_ERROR;
844 }
845 
debugShowFPS()846 static void debugShowFPS()
847 {
848     static int mFrameCount = 0;
849     static int mLastFrameCount = 0;
850     static nsecs_t mLastFpsTime = 0;
851     static float mFps = 0;
852     if(mDebugFps) {
853         mFrameCount++;
854         if (!(mFrameCount & 0x1F)) {
855             nsecs_t now = systemTime();
856             nsecs_t diff = now - mLastFpsTime;
857             mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
858             mLastFpsTime = now;
859             mLastFrameCount = mFrameCount;
860             CAMHAL_LOGI("Camera %d Frames, %f FPS", mFrameCount, mFps);
861         }
862     }
863 }
864 
recalculateFPS()865 status_t V4LCameraAdapter::recalculateFPS()
866 {
867     float currentFPS;
868 
869     mFrameCount++;
870 
871     if ( ( mFrameCount % FPS_PERIOD ) == 0 )
872         {
873         nsecs_t now = systemTime();
874         nsecs_t diff = now - mLastFPSTime;
875         currentFPS =  ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
876         mLastFPSTime = now;
877         mLastFrameCount = mFrameCount;
878 
879         if ( 1 == mIter )
880             {
881             mFPS = currentFPS;
882             }
883         else
884             {
885             //cumulative moving average
886             mFPS = mLastFPS + (currentFPS - mLastFPS)/mIter;
887             }
888 
889         mLastFPS = mFPS;
890         mIter++;
891         }
892 
893     return NO_ERROR;
894 }
895 
onOrientationEvent(uint32_t orientation,uint32_t tilt)896 void V4LCameraAdapter::onOrientationEvent(uint32_t orientation, uint32_t tilt)
897 {
898     LOG_FUNCTION_NAME;
899 
900     LOG_FUNCTION_NAME_EXIT;
901 }
902 
903 
V4LCameraAdapter(size_t sensor_index)904 V4LCameraAdapter::V4LCameraAdapter(size_t sensor_index)
905 {
906     LOG_FUNCTION_NAME;
907 
908     // Nothing useful to do in the constructor
909     mFramesWithEncoder = 0;
910 
911     LOG_FUNCTION_NAME_EXIT;
912 }
913 
~V4LCameraAdapter()914 V4LCameraAdapter::~V4LCameraAdapter()
915 {
916     LOG_FUNCTION_NAME;
917 
918     // Close the camera handle and free the video info structure
919     close(mCameraHandle);
920 
921     if (mVideoInfo)
922       {
923         free(mVideoInfo);
924         mVideoInfo = NULL;
925       }
926 
927     LOG_FUNCTION_NAME_EXIT;
928 }
929 
convertYUV422i_yuyvTouyvy(uint8_t * src,uint8_t * dest,size_t size)930 static void convertYUV422i_yuyvTouyvy(uint8_t *src, uint8_t *dest, size_t size ) {
931     //convert YUV422I yuyv to uyvy format.
932     uint32_t *bf = (uint32_t*)src;
933     uint32_t *dst = (uint32_t*)dest;
934 
935     LOG_FUNCTION_NAME;
936 
937     if (!src || !dest) {
938         return;
939     }
940 
941     for(size_t i = 0; i < size; i = i+4)
942     {
943         dst[0] = ((bf[0] & 0x00FF00FF) << 8) | ((bf[0] & 0xFF00FF00) >> 8);
944         bf++;
945         dst++;
946     }
947 
948     LOG_FUNCTION_NAME_EXIT;
949 }
950 
convertYUV422ToNV12Tiler(unsigned char * src,unsigned char * dest,int width,int height)951 static void convertYUV422ToNV12Tiler(unsigned char *src, unsigned char *dest, int width, int height ) {
952     //convert YUV422I to YUV420 NV12 format and copies directly to preview buffers (Tiler memory).
953     int stride = 4096;
954     unsigned char *bf = src;
955     unsigned char *dst_y = dest;
956     unsigned char *dst_uv = dest + ( height * stride);
957 #ifdef PPM_PER_FRAME_CONVERSION
958     static int frameCount = 0;
959     static nsecs_t ppm_diff = 0;
960     nsecs_t ppm_start  = systemTime();
961 #endif
962 
963     LOG_FUNCTION_NAME;
964 
965     if (width % 16 ) {
966         for(int i = 0; i < height; i++) {
967             for(int j = 0; j < width; j++) {
968                 *dst_y = *bf;
969                 dst_y++;
970                 bf = bf + 2;
971             }
972             dst_y += (stride - width);
973         }
974 
975         bf = src;
976         bf++;  //UV sample
977         for(int i = 0; i < height/2; i++) {
978             for(int j=0; j<width; j++) {
979                 *dst_uv = *bf;
980                 dst_uv++;
981                 bf = bf + 2;
982             }
983             bf = bf + width*2;
984             dst_uv = dst_uv + (stride - width);
985         }
986     } else {
987         //neon conversion
988         for(int i = 0; i < height; i++) {
989             int n = width;
990             int skip = i & 0x1;       // skip uv elements for the odd rows
991             asm volatile (
992                 "   pld [%[src], %[src_stride], lsl #2]                         \n\t"
993                 "   cmp %[n], #16                                               \n\t"
994                 "   blt 5f                                                      \n\t"
995                 "0: @ 16 pixel copy                                             \n\t"
996                 "   vld2.8  {q0, q1} , [%[src]]! @ q0 = yyyy.. q1 = uvuv..      \n\t"
997                 "                                @ now q0 = y q1 = uv           \n\t"
998                 "   vst1.32   {d0,d1}, [%[dst_y]]!                              \n\t"
999                 "   cmp    %[skip], #0                                          \n\t"
1000                 "   bne 1f                                                      \n\t"
1001                 "   vst1.32  {d2,d3},[%[dst_uv]]!                               \n\t"
1002                 "1: @ skip odd rows for UV                                      \n\t"
1003                 "   sub %[n], %[n], #16                                         \n\t"
1004                 "   cmp %[n], #16                                               \n\t"
1005                 "   bge 0b                                                      \n\t"
1006                 "5: @ end                                                       \n\t"
1007 #ifdef NEEDS_ARM_ERRATA_754319_754320
1008                 "   vmov s0,s0  @ add noop for errata item                      \n\t"
1009 #endif
1010                 : [dst_y] "+r" (dst_y), [dst_uv] "+r" (dst_uv), [src] "+r" (src), [n] "+r" (n)
1011                 : [src_stride] "r" (width), [skip] "r" (skip)
1012                 : "cc", "memory", "q0", "q1", "q2", "d0", "d1", "d2", "d3"
1013             );
1014             dst_y = dst_y + (stride - width);
1015             if (skip == 0) {
1016                 dst_uv = dst_uv + (stride - width);
1017             }
1018         } //end of for()
1019     }
1020 
1021 #ifdef PPM_PER_FRAME_CONVERSION
1022     ppm_diff += (systemTime() - ppm_start);
1023     frameCount++;
1024 
1025     if (frameCount >= 30) {
1026         ppm_diff = ppm_diff / frameCount;
1027         LOGD("PPM: YUV422i to NV12 Conversion(%d x %d): %llu us ( %llu ms )", width, height,
1028                 ns2us(ppm_diff), ns2ms(ppm_diff) );
1029         ppm_diff = 0;
1030         frameCount = 0;
1031     }
1032 #endif
1033 
1034     LOG_FUNCTION_NAME_EXIT;
1035 }
1036 
convertYUV422ToNV12(unsigned char * src,unsigned char * dest,int width,int height)1037 static void convertYUV422ToNV12(unsigned char *src, unsigned char *dest, int width, int height ) {
1038     //convert YUV422I to YUV420 NV12 format.
1039     unsigned char *bf = src;
1040     unsigned char *dst_y = dest;
1041     unsigned char *dst_uv = dest + (width * height);
1042 
1043     LOG_FUNCTION_NAME;
1044 
1045     if (width % 16 ) {
1046         for(int i = 0; i < height; i++) {
1047             for(int j = 0; j < width; j++) {
1048                 *dst_y = *bf;
1049                 dst_y++;
1050                 bf = bf + 2;
1051             }
1052         }
1053 
1054         bf = src;
1055         bf++;  //UV sample
1056         for(int i = 0; i < height/2; i++) {
1057             for(int j=0; j<width; j++) {
1058                 *dst_uv = *bf;
1059                 dst_uv++;
1060                 bf = bf + 2;
1061             }
1062             bf = bf + width*2;
1063         }
1064     } else {
1065         //neon conversion
1066         for(int i = 0; i < height; i++) {
1067             int n = width;
1068             int skip = i & 0x1;       // skip uv elements for the odd rows
1069             asm volatile (
1070                 "   pld [%[src], %[src_stride], lsl #2]                         \n\t"
1071                 "   cmp %[n], #16                                               \n\t"
1072                 "   blt 5f                                                      \n\t"
1073                 "0: @ 16 pixel copy                                             \n\t"
1074                 "   vld2.8  {q0, q1} , [%[src]]! @ q0 = yyyy.. q1 = uvuv..      \n\t"
1075                 "                                @ now q0 = y q1 = uv           \n\t"
1076                 "   vst1.32   {d0,d1}, [%[dst_y]]!                              \n\t"
1077                 "   cmp    %[skip], #0                                          \n\t"
1078                 "   bne 1f                                                      \n\t"
1079                 "   vst1.32  {d2,d3},[%[dst_uv]]!                               \n\t"
1080                 "1: @ skip odd rows for UV                                      \n\t"
1081                 "   sub %[n], %[n], #16                                         \n\t"
1082                 "   cmp %[n], #16                                               \n\t"
1083                 "   bge 0b                                                      \n\t"
1084                 "5: @ end                                                       \n\t"
1085 #ifdef NEEDS_ARM_ERRATA_754319_754320
1086                 "   vmov s0,s0  @ add noop for errata item                      \n\t"
1087 #endif
1088                 : [dst_y] "+r" (dst_y), [dst_uv] "+r" (dst_uv), [src] "+r" (src), [n] "+r" (n)
1089                 : [src_stride] "r" (width), [skip] "r" (skip)
1090                 : "cc", "memory", "q0", "q1", "q2", "d0", "d1", "d2", "d3"
1091             );
1092         }
1093     }
1094 
1095     LOG_FUNCTION_NAME_EXIT;
1096 }
1097 
1098 #ifdef SAVE_RAW_FRAMES
saveFile(unsigned char * buff,int buff_size)1099 void saveFile(unsigned char* buff, int buff_size) {
1100     static int      counter = 1;
1101     int             fd = -1;
1102     char            fn[256];
1103 
1104     LOG_FUNCTION_NAME;
1105     if (counter > 3) {
1106         return;
1107     }
1108     //dump nv12 buffer
1109     counter++;
1110     sprintf(fn, "/data/misc/camera/raw/nv12_dump_%03d.yuv", counter);
1111     CAMHAL_LOGEB("Dumping nv12 frame to a file : %s.", fn);
1112 
1113     fd = open(fn, O_CREAT | O_WRONLY | O_SYNC | O_TRUNC, 0777);
1114     if(fd < 0) {
1115         CAMHAL_LOGE("Unable to open file %s: %s", fn, strerror(fd));
1116         return;
1117     }
1118 
1119     write(fd, buff, buff_size );
1120     close(fd);
1121 
1122     LOG_FUNCTION_NAME_EXIT;
1123 }
1124 #endif
1125 
1126 /* Preview Thread */
1127 // ---------------------------------------------------------------------------
1128 
previewThread()1129 int V4LCameraAdapter::previewThread()
1130 {
1131     status_t ret = NO_ERROR;
1132     int width, height;
1133     CameraFrame frame;
1134     void *y_uv[2];
1135     int index = 0;
1136     int stride = 4096;
1137     char *fp = NULL;
1138 
1139     mParams.getPreviewSize(&width, &height);
1140 
1141     if (mPreviewing) {
1142 
1143         fp = this->GetFrame(index);
1144         if(!fp) {
1145             ret = BAD_VALUE;
1146             goto EXIT;
1147         }
1148         CameraBuffer *buffer = mPreviewBufs.keyAt(index);
1149         CameraFrame *lframe = (CameraFrame *)mFrameQueue.valueFor(buffer);
1150         if (!lframe) {
1151             ret = BAD_VALUE;
1152             goto EXIT;
1153         }
1154 
1155         debugShowFPS();
1156 
1157         if ( mFrameSubscribers.size() == 0 ) {
1158             ret = BAD_VALUE;
1159             goto EXIT;
1160         }
1161         y_uv[0] = (void*) lframe->mYuv[0];
1162         //y_uv[1] = (void*) lframe->mYuv[1];
1163         //y_uv[1] = (void*) (lframe->mYuv[0] + height*stride);
1164         convertYUV422ToNV12Tiler ( (unsigned char*)fp, (unsigned char*)y_uv[0], width, height);
1165         CAMHAL_LOGVB("##...index= %d.;camera buffer= 0x%x; y= 0x%x; UV= 0x%x.",index, buffer, y_uv[0], y_uv[1] );
1166 
1167 #ifdef SAVE_RAW_FRAMES
1168         unsigned char* nv12_buff = (unsigned char*) malloc(width*height*3/2);
1169         //Convert yuv422i to yuv420sp(NV12) & dump the frame to a file
1170         convertYUV422ToNV12 ( (unsigned char*)fp, nv12_buff, width, height);
1171         saveFile( nv12_buff, ((width*height)*3/2) );
1172         free (nv12_buff);
1173 #endif
1174 
1175         frame.mFrameType = CameraFrame::PREVIEW_FRAME_SYNC;
1176         frame.mBuffer = buffer;
1177         frame.mLength = width*height*3/2;
1178         frame.mAlignment = stride;
1179         frame.mOffset = 0;
1180         frame.mTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);
1181         frame.mFrameMask = (unsigned int)CameraFrame::PREVIEW_FRAME_SYNC;
1182 
1183         if (mRecording)
1184         {
1185             frame.mFrameMask |= (unsigned int)CameraFrame::VIDEO_FRAME_SYNC;
1186             mFramesWithEncoder++;
1187         }
1188 
1189         ret = setInitFrameRefCount(frame.mBuffer, frame.mFrameMask);
1190         if (ret != NO_ERROR) {
1191             CAMHAL_LOGDB("Error in setInitFrameRefCount %d", ret);
1192         } else {
1193             ret = sendFrameToSubscribers(&frame);
1194         }
1195     }
1196 EXIT:
1197 
1198     return ret;
1199 }
1200 
1201 //scan for video devices
detectVideoDevice(char ** video_device_list,int & num_device)1202 void detectVideoDevice(char** video_device_list, int& num_device) {
1203     char dir_path[20];
1204     char* filename;
1205     char** dev_list = video_device_list;
1206     DIR *d;
1207     struct dirent *dir;
1208     int index = 0;
1209 
1210     strcpy(dir_path, DEVICE_PATH);
1211     d = opendir(dir_path);
1212     if(d) {
1213         //read each entry in the /dev/ and find if there is videox entry.
1214         while ((dir = readdir(d)) != NULL) {
1215             filename = dir->d_name;
1216             if (strncmp(filename, DEVICE_NAME, 5) == 0) {
1217                 strcpy(dev_list[index],DEVICE_PATH);
1218                 strncat(dev_list[index],filename,sizeof(DEVICE_NAME));
1219                 index++;
1220             }
1221        } //end of while()
1222        closedir(d);
1223        num_device = index;
1224 
1225        for(int i=0; i<index; i++){
1226            CAMHAL_LOGDB("Video device list::dev_list[%d]= %s",i,dev_list[i]);
1227        }
1228     }
1229 }
1230 
V4LCameraAdapter_Factory(size_t sensor_index)1231 extern "C" CameraAdapter* V4LCameraAdapter_Factory(size_t sensor_index)
1232 {
1233     CameraAdapter *adapter = NULL;
1234     android::AutoMutex lock(gV4LAdapterLock);
1235 
1236     LOG_FUNCTION_NAME;
1237 
1238     adapter = new V4LCameraAdapter(sensor_index);
1239     if ( adapter ) {
1240         CAMHAL_LOGDB("New V4L Camera adapter instance created for sensor %d",sensor_index);
1241     } else {
1242         CAMHAL_LOGEA("V4L Camera adapter create failed for sensor index = %d!",sensor_index);
1243     }
1244 
1245     LOG_FUNCTION_NAME_EXIT;
1246 
1247     return adapter;
1248 }
1249 
V4LCameraAdapter_Capabilities(CameraProperties::Properties * const properties_array,const int starting_camera,const int max_camera,int & supportedCameras)1250 extern "C" status_t V4LCameraAdapter_Capabilities(
1251         CameraProperties::Properties * const properties_array,
1252         const int starting_camera, const int max_camera, int & supportedCameras)
1253 {
1254     status_t ret = NO_ERROR;
1255     struct v4l2_capability cap;
1256     int tempHandle = NULL;
1257     int num_cameras_supported = 0;
1258     char device_list[5][15];
1259     char* video_device_list[5];
1260     int num_v4l_devices = 0;
1261     int sensorId = 0;
1262     CameraProperties::Properties* properties = NULL;
1263 
1264     LOG_FUNCTION_NAME;
1265 
1266     supportedCameras = 0;
1267     memset((void*)&cap, 0, sizeof(v4l2_capability));
1268 
1269     if (!properties_array) {
1270         CAMHAL_LOGEB("invalid param: properties = 0x%p", properties_array);
1271         LOG_FUNCTION_NAME_EXIT;
1272         return BAD_VALUE;
1273     }
1274 
1275     for (int i = 0; i < 5; i++) {
1276         video_device_list[i] = device_list[i];
1277     }
1278     //look for the connected video devices
1279     detectVideoDevice(video_device_list, num_v4l_devices);
1280 
1281     for (int i = 0; i < num_v4l_devices; i++) {
1282         if ( (starting_camera + num_cameras_supported) < max_camera) {
1283             sensorId = starting_camera + num_cameras_supported;
1284 
1285             CAMHAL_LOGDB("Opening device[%d] = %s..",i, video_device_list[i]);
1286             if ((tempHandle = open(video_device_list[i], O_RDWR)) == -1) {
1287                 CAMHAL_LOGEB("Error while opening handle to V4L2 Camera(%s): %s",video_device_list[i], strerror(errno));
1288                 continue;
1289             }
1290 
1291             ret = ioctl (tempHandle, VIDIOC_QUERYCAP, &cap);
1292             if (ret < 0) {
1293                 CAMHAL_LOGEA("Error when querying the capabilities of the V4L Camera");
1294                 close(tempHandle);
1295                 continue;
1296             }
1297 
1298             //check for video capture devices
1299             if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
1300                 CAMHAL_LOGEA("Error while adapter initialization: video capture not supported.");
1301                 close(tempHandle);
1302                 continue;
1303             }
1304 
1305             strcpy(device, video_device_list[i]);
1306             properties = properties_array + starting_camera + num_cameras_supported;
1307 
1308             //fetch capabilities for this camera
1309             ret = V4LCameraAdapter::getCaps( sensorId, properties, tempHandle );
1310             if (ret < 0) {
1311                 CAMHAL_LOGEA("Error while getting capabilities.");
1312                 close(tempHandle);
1313                 continue;
1314             }
1315 
1316             num_cameras_supported++;
1317 
1318         }
1319         //For now exit this loop once a valid video capture device is found.
1320         //TODO: find all V4L capture devices and it capabilities
1321         break;
1322     }//end of for() loop
1323 
1324     supportedCameras = num_cameras_supported;
1325     CAMHAL_LOGDB("Number of V4L cameras detected =%d", num_cameras_supported);
1326 
1327 EXIT:
1328     LOG_FUNCTION_NAME_EXIT;
1329     close(tempHandle);
1330     return NO_ERROR;
1331 }
1332 
1333 } // namespace Camera
1334 } // namespace Ti
1335 
1336 
1337 /*--------------------Camera Adapter Class ENDS here-----------------------------*/
1338 
1339