• 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 <signal.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <fcntl.h>
33 #include <unistd.h>
34 #include <errno.h>
35 #include <sys/ioctl.h>
36 #include <sys/mman.h>
37 #include <sys/select.h>
38 #include <linux/videodev.h>
39 
40 
41 #include <cutils/properties.h>
42 #define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
43 static int mDebugFps = 0;
44 
45 #define Q16_OFFSET 16
46 
47 #define HERE(Msg) {CAMHAL_LOGEB("--===line %d, %s===--\n", __LINE__, Msg);}
48 
49 namespace android {
50 
51 #undef LOG_TAG
52 ///Maintain a separate tag for V4LCameraAdapter logs to isolate issues OMX specific
53 #define LOG_TAG "CameraHAL"
54 
55 //frames skipped before recalculating the framerate
56 #define FPS_PERIOD 30
57 
58 Mutex gAdapterLock;
59 const char *device = DEVICE;
60 
61 
62 /*--------------------Camera Adapter Class STARTS here-----------------------------*/
63 
initialize(CameraProperties::Properties * caps)64 status_t V4LCameraAdapter::initialize(CameraProperties::Properties* caps)
65 {
66     LOG_FUNCTION_NAME;
67 
68     char value[PROPERTY_VALUE_MAX];
69     property_get("debug.camera.showfps", value, "0");
70     mDebugFps = atoi(value);
71 
72     int ret = NO_ERROR;
73 
74     // Allocate memory for video info structure
75     mVideoInfo = (struct VideoInfo *) calloc (1, sizeof (struct VideoInfo));
76     if(!mVideoInfo)
77         {
78         return NO_MEMORY;
79         }
80 
81     if ((mCameraHandle = open(device, O_RDWR)) == -1)
82         {
83         CAMHAL_LOGEB("Error while opening handle to V4L2 Camera: %s", strerror(errno));
84         return -EINVAL;
85         }
86 
87     ret = ioctl (mCameraHandle, VIDIOC_QUERYCAP, &mVideoInfo->cap);
88     if (ret < 0)
89         {
90         CAMHAL_LOGEA("Error when querying the capabilities of the V4L Camera");
91         return -EINVAL;
92         }
93 
94     if ((mVideoInfo->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0)
95         {
96         CAMHAL_LOGEA("Error while adapter initialization: video capture not supported.");
97         return -EINVAL;
98         }
99 
100     if (!(mVideoInfo->cap.capabilities & V4L2_CAP_STREAMING))
101         {
102         CAMHAL_LOGEA("Error while adapter initialization: Capture device does not support streaming i/o");
103         return -EINVAL;
104         }
105 
106     // Initialize flags
107     mPreviewing = false;
108     mVideoInfo->isStreaming = false;
109     mRecording = false;
110 
111     LOG_FUNCTION_NAME_EXIT;
112 
113     return ret;
114 }
115 
fillThisBuffer(void * frameBuf,CameraFrame::FrameType frameType)116 status_t V4LCameraAdapter::fillThisBuffer(void* frameBuf, CameraFrame::FrameType frameType)
117 {
118 
119     status_t ret = NO_ERROR;
120 
121     if ( !mVideoInfo->isStreaming )
122         {
123         return NO_ERROR;
124         }
125 
126     int i = mPreviewBufs.valueFor(( unsigned int )frameBuf);
127     if(i<0)
128         {
129         return BAD_VALUE;
130         }
131 
132     mVideoInfo->buf.index = i;
133     mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
134     mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;
135 
136     ret = ioctl(mCameraHandle, VIDIOC_QBUF, &mVideoInfo->buf);
137     if (ret < 0) {
138        CAMHAL_LOGEA("Init: VIDIOC_QBUF Failed");
139        return -1;
140     }
141 
142      nQueued++;
143 
144     return ret;
145 
146 }
147 
setParameters(const CameraParameters & params)148 status_t V4LCameraAdapter::setParameters(const CameraParameters &params)
149 {
150     LOG_FUNCTION_NAME;
151 
152     status_t ret = NO_ERROR;
153 
154     int width, height;
155 
156     params.getPreviewSize(&width, &height);
157 
158     CAMHAL_LOGDB("Width * Height %d x %d format 0x%x", width, height, DEFAULT_PIXEL_FORMAT);
159 
160     mVideoInfo->width = width;
161     mVideoInfo->height = height;
162     mVideoInfo->framesizeIn = (width * height << 1);
163     mVideoInfo->formatIn = DEFAULT_PIXEL_FORMAT;
164 
165     mVideoInfo->format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
166     mVideoInfo->format.fmt.pix.width = width;
167     mVideoInfo->format.fmt.pix.height = height;
168     mVideoInfo->format.fmt.pix.pixelformat = DEFAULT_PIXEL_FORMAT;
169 
170     ret = ioctl(mCameraHandle, VIDIOC_S_FMT, &mVideoInfo->format);
171     if (ret < 0) {
172         CAMHAL_LOGEB("Open: VIDIOC_S_FMT Failed: %s", strerror(errno));
173         return ret;
174     }
175 
176     // Udpate the current parameter set
177     mParams = params;
178 
179     LOG_FUNCTION_NAME_EXIT;
180     return ret;
181 }
182 
183 
getParameters(CameraParameters & params)184 void V4LCameraAdapter::getParameters(CameraParameters& params)
185 {
186     LOG_FUNCTION_NAME;
187 
188     // Return the current parameter set
189     params = mParams;
190 
191     LOG_FUNCTION_NAME_EXIT;
192 }
193 
194 
195 ///API to give the buffers to Adapter
useBuffers(CameraMode mode,void * bufArr,int num,size_t length,unsigned int queueable)196 status_t V4LCameraAdapter::useBuffers(CameraMode mode, void* bufArr, int num, size_t length, unsigned int queueable)
197 {
198     status_t ret = NO_ERROR;
199 
200     LOG_FUNCTION_NAME;
201 
202     Mutex::Autolock lock(mLock);
203 
204     switch(mode)
205         {
206         case CAMERA_PREVIEW:
207             ret = UseBuffersPreview(bufArr, num);
208             break;
209 
210         //@todo Insert Image capture case here
211 
212         case CAMERA_VIDEO:
213             //@warn Video capture is not fully supported yet
214             ret = UseBuffersPreview(bufArr, num);
215             break;
216 
217         }
218 
219     LOG_FUNCTION_NAME_EXIT;
220 
221     return ret;
222 }
223 
UseBuffersPreview(void * bufArr,int num)224 status_t V4LCameraAdapter::UseBuffersPreview(void* bufArr, int num)
225 {
226     int ret = NO_ERROR;
227 
228     if(NULL == bufArr)
229         {
230         return BAD_VALUE;
231         }
232 
233     //First allocate adapter internal buffers at V4L level for USB Cam
234     //These are the buffers from which we will copy the data into overlay buffers
235     /* Check if camera can handle NB_BUFFER buffers */
236     mVideoInfo->rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
237     mVideoInfo->rb.memory = V4L2_MEMORY_MMAP;
238     mVideoInfo->rb.count = num;
239 
240     ret = ioctl(mCameraHandle, VIDIOC_REQBUFS, &mVideoInfo->rb);
241     if (ret < 0) {
242         CAMHAL_LOGEB("VIDIOC_REQBUFS failed: %s", strerror(errno));
243         return ret;
244     }
245 
246     for (int i = 0; i < num; i++) {
247 
248         memset (&mVideoInfo->buf, 0, sizeof (struct v4l2_buffer));
249 
250         mVideoInfo->buf.index = i;
251         mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
252         mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;
253 
254         ret = ioctl (mCameraHandle, VIDIOC_QUERYBUF, &mVideoInfo->buf);
255         if (ret < 0) {
256             CAMHAL_LOGEB("Unable to query buffer (%s)", strerror(errno));
257             return ret;
258         }
259 
260         mVideoInfo->mem[i] = mmap (0,
261                mVideoInfo->buf.length,
262                PROT_READ | PROT_WRITE,
263                MAP_SHARED,
264                mCameraHandle,
265                mVideoInfo->buf.m.offset);
266 
267         if (mVideoInfo->mem[i] == MAP_FAILED) {
268             CAMHAL_LOGEB("Unable to map buffer (%s)", strerror(errno));
269             return -1;
270         }
271 
272         uint32_t *ptr = (uint32_t*) bufArr;
273 
274         //Associate each Camera internal buffer with the one from Overlay
275         mPreviewBufs.add((int)ptr[i], i);
276 
277     }
278 
279     // Update the preview buffer count
280     mPreviewBufferCount = num;
281 
282     return ret;
283 }
284 
startPreview()285 status_t V4LCameraAdapter::startPreview()
286 {
287     status_t ret = NO_ERROR;
288 
289   Mutex::Autolock lock(mPreviewBufsLock);
290 
291   if(mPreviewing)
292     {
293     return BAD_VALUE;
294     }
295 
296    for (int i = 0; i < mPreviewBufferCount; i++) {
297 
298        mVideoInfo->buf.index = i;
299        mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
300        mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;
301 
302        ret = ioctl(mCameraHandle, VIDIOC_QBUF, &mVideoInfo->buf);
303        if (ret < 0) {
304            CAMHAL_LOGEA("VIDIOC_QBUF Failed");
305            return -EINVAL;
306        }
307 
308        nQueued++;
309    }
310 
311     enum v4l2_buf_type bufType;
312    if (!mVideoInfo->isStreaming) {
313        bufType = V4L2_BUF_TYPE_VIDEO_CAPTURE;
314 
315        ret = ioctl (mCameraHandle, VIDIOC_STREAMON, &bufType);
316        if (ret < 0) {
317            CAMHAL_LOGEB("StartStreaming: Unable to start capture: %s", strerror(errno));
318            return ret;
319        }
320 
321        mVideoInfo->isStreaming = true;
322    }
323 
324    // Create and start preview thread for receiving buffers from V4L Camera
325    mPreviewThread = new PreviewThread(this);
326 
327    CAMHAL_LOGDA("Created preview thread");
328 
329 
330    //Update the flag to indicate we are previewing
331    mPreviewing = true;
332 
333    return ret;
334 
335 }
336 
stopPreview()337 status_t V4LCameraAdapter::stopPreview()
338 {
339     enum v4l2_buf_type bufType;
340     int ret = NO_ERROR;
341 
342     Mutex::Autolock lock(mPreviewBufsLock);
343 
344     if(!mPreviewing)
345         {
346         return NO_INIT;
347         }
348 
349     if (mVideoInfo->isStreaming) {
350         bufType = V4L2_BUF_TYPE_VIDEO_CAPTURE;
351 
352         ret = ioctl (mCameraHandle, VIDIOC_STREAMOFF, &bufType);
353         if (ret < 0) {
354             CAMHAL_LOGEB("StopStreaming: Unable to stop capture: %s", strerror(errno));
355             return ret;
356         }
357 
358         mVideoInfo->isStreaming = false;
359     }
360 
361     mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
362     mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;
363 
364     nQueued = 0;
365     nDequeued = 0;
366 
367     /* Unmap buffers */
368     for (int i = 0; i < mPreviewBufferCount; i++)
369         if (munmap(mVideoInfo->mem[i], mVideoInfo->buf.length) < 0)
370             CAMHAL_LOGEA("Unmap failed");
371 
372     mPreviewBufs.clear();
373 
374     mPreviewThread->requestExitAndWait();
375     mPreviewThread.clear();
376 
377     return ret;
378 
379 }
380 
GetFrame(int & index)381 char * V4LCameraAdapter::GetFrame(int &index)
382 {
383     int ret;
384 
385     mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
386     mVideoInfo->buf.memory = V4L2_MEMORY_MMAP;
387 
388     /* DQ */
389     ret = ioctl(mCameraHandle, VIDIOC_DQBUF, &mVideoInfo->buf);
390     if (ret < 0) {
391         CAMHAL_LOGEA("GetFrame: VIDIOC_DQBUF Failed");
392         return NULL;
393     }
394     nDequeued++;
395 
396     index = mVideoInfo->buf.index;
397 
398     return (char *)mVideoInfo->mem[mVideoInfo->buf.index];
399 }
400 
401 //API to get the frame size required to be allocated. This size is used to override the size passed
402 //by camera service when VSTAB/VNF is turned ON for example
getFrameSize(size_t & width,size_t & height)403 status_t V4LCameraAdapter::getFrameSize(size_t &width, size_t &height)
404 {
405     status_t ret = NO_ERROR;
406 
407     // Just return the current preview size, nothing more to do here.
408     mParams.getPreviewSize(( int * ) &width,
409                            ( int * ) &height);
410 
411     LOG_FUNCTION_NAME_EXIT;
412 
413     return ret;
414 }
415 
getFrameDataSize(size_t & dataFrameSize,size_t bufferCount)416 status_t V4LCameraAdapter::getFrameDataSize(size_t &dataFrameSize, size_t bufferCount)
417 {
418     // We don't support meta data, so simply return
419     return NO_ERROR;
420 }
421 
getPictureBufferSize(size_t & length,size_t bufferCount)422 status_t V4LCameraAdapter::getPictureBufferSize(size_t &length, size_t bufferCount)
423 {
424     // We don't support image capture yet, safely return from here without messing up
425     return NO_ERROR;
426 }
427 
debugShowFPS()428 static void debugShowFPS()
429 {
430     static int mFrameCount = 0;
431     static int mLastFrameCount = 0;
432     static nsecs_t mLastFpsTime = 0;
433     static float mFps = 0;
434     mFrameCount++;
435     if (!(mFrameCount & 0x1F)) {
436         nsecs_t now = systemTime();
437         nsecs_t diff = now - mLastFpsTime;
438         mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
439         mLastFpsTime = now;
440         mLastFrameCount = mFrameCount;
441         ALOGD("Camera %d Frames, %f FPS", mFrameCount, mFps);
442     }
443     // XXX: mFPS has the value we want
444 }
445 
recalculateFPS()446 status_t V4LCameraAdapter::recalculateFPS()
447 {
448     float currentFPS;
449 
450     mFrameCount++;
451 
452     if ( ( mFrameCount % FPS_PERIOD ) == 0 )
453         {
454         nsecs_t now = systemTime();
455         nsecs_t diff = now - mLastFPSTime;
456         currentFPS =  ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
457         mLastFPSTime = now;
458         mLastFrameCount = mFrameCount;
459 
460         if ( 1 == mIter )
461             {
462             mFPS = currentFPS;
463             }
464         else
465             {
466             //cumulative moving average
467             mFPS = mLastFPS + (currentFPS - mLastFPS)/mIter;
468             }
469 
470         mLastFPS = mFPS;
471         mIter++;
472         }
473 
474     return NO_ERROR;
475 }
476 
onOrientationEvent(uint32_t orientation,uint32_t tilt)477 void V4LCameraAdapter::onOrientationEvent(uint32_t orientation, uint32_t tilt)
478 {
479     LOG_FUNCTION_NAME;
480 
481     LOG_FUNCTION_NAME_EXIT;
482 }
483 
484 
V4LCameraAdapter(size_t sensor_index)485 V4LCameraAdapter::V4LCameraAdapter(size_t sensor_index)
486 {
487     LOG_FUNCTION_NAME;
488 
489     // Nothing useful to do in the constructor
490 
491     LOG_FUNCTION_NAME_EXIT;
492 }
493 
~V4LCameraAdapter()494 V4LCameraAdapter::~V4LCameraAdapter()
495 {
496     LOG_FUNCTION_NAME;
497 
498     // Close the camera handle and free the video info structure
499     close(mCameraHandle);
500 
501     if (mVideoInfo)
502       {
503         free(mVideoInfo);
504         mVideoInfo = NULL;
505       }
506 
507     LOG_FUNCTION_NAME_EXIT;
508 }
509 
510 /* Preview Thread */
511 // ---------------------------------------------------------------------------
512 
previewThread()513 int V4LCameraAdapter::previewThread()
514 {
515     status_t ret = NO_ERROR;
516     int width, height;
517     CameraFrame frame;
518 
519     if (mPreviewing)
520         {
521         int index = 0;
522         char *fp = this->GetFrame(index);
523         if(!fp)
524             {
525             return BAD_VALUE;
526             }
527 
528         uint8_t* ptr = (uint8_t*) mPreviewBufs.keyAt(index);
529 
530         int width, height;
531         uint16_t* dest = (uint16_t*)ptr;
532         uint16_t* src = (uint16_t*) fp;
533         mParams.getPreviewSize(&width, &height);
534         for(int i=0;i<height;i++)
535             {
536             for(int j=0;j<width;j++)
537                 {
538                 //*dest = *src;
539                 //convert from YUYV to UYVY supported in Camera service
540                 *dest = (((*src & 0xFF000000)>>24)<<16)|(((*src & 0x00FF0000)>>16)<<24) |
541                         (((*src & 0xFF00)>>8)<<0)|(((*src & 0x00FF)>>0)<<8);
542                 src++;
543                 dest++;
544                 }
545                 dest += 4096/2-width;
546             }
547 
548         mParams.getPreviewSize(&width, &height);
549         frame.mFrameType = CameraFrame::PREVIEW_FRAME_SYNC;
550         frame.mBuffer = ptr;
551         frame.mLength = width*height*2;
552         frame.mAlignment = width*2;
553         frame.mOffset = 0;
554         frame.mTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);;
555 
556         ret = sendFrameToSubscribers(&frame);
557 
558         }
559 
560     return ret;
561 }
562 
CameraAdapter_Factory()563 extern "C" CameraAdapter* CameraAdapter_Factory()
564 {
565     CameraAdapter *adapter = NULL;
566     Mutex::Autolock lock(gAdapterLock);
567 
568     LOG_FUNCTION_NAME;
569 
570     adapter = new V4LCameraAdapter(sensor_index);
571     if ( adapter ) {
572         CAMHAL_LOGDB("New OMX Camera adapter instance created for sensor %d",sensor_index);
573     } else {
574         CAMHAL_LOGEA("Camera adapter create failed!");
575     }
576 
577     LOG_FUNCTION_NAME_EXIT;
578 
579     return adapter;
580 }
581 
CameraAdapter_Capabilities(CameraProperties::Properties * properties_array,const unsigned int starting_camera,const unsigned int max_camera)582 extern "C" int CameraAdapter_Capabilities(CameraProperties::Properties* properties_array,
583                                           const unsigned int starting_camera,
584                                           const unsigned int max_camera) {
585     int num_cameras_supported = 0;
586     CameraProperties::Properties* properties = NULL;
587 
588     LOG_FUNCTION_NAME;
589 
590     if(!properties_array)
591     {
592         return -EINVAL;
593     }
594 
595     // TODO: Need to tell camera properties what other cameras we can support
596     if (starting_camera + num_cameras_supported < max_camera) {
597         num_cameras_supported++;
598         properties = properties_array + starting_camera;
599         properties->set(CameraProperties::CAMERA_NAME, "USBCamera");
600     }
601 
602     LOG_FUNCTION_NAME_EXIT;
603 
604     return num_cameras_supported;
605 }
606 
607 };
608 
609 
610 /*--------------------Camera Adapter Class ENDS here-----------------------------*/
611 
612