Home | History | Annotate | Download | only in V4LCameraAdapter
      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 
     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 
    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 
    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 
    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
    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 
    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 
    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 
    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 
    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
    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 
    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 
    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 
    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         LOGD("Camera %d Frames, %f FPS", mFrameCount, mFps);
    442     }
    443     // XXX: mFPS has the value we want
    444 }
    445 
    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 
    477 void V4LCameraAdapter::onOrientationEvent(uint32_t orientation, uint32_t tilt)
    478 {
    479     LOG_FUNCTION_NAME;
    480 
    481     LOG_FUNCTION_NAME_EXIT;
    482 }
    483 
    484 
    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 
    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 
    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 
    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 
    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