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 ))
43static int mDebugFps = 0;
44
45#define Q16_OFFSET 16
46
47#define HERE(Msg) {CAMHAL_LOGEB("--===line %d, %s===--\n", __LINE__, Msg);}
48
49namespace 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
58Mutex gAdapterLock;
59const char *device = DEVICE;
60
61
62/*--------------------Camera Adapter Class STARTS here-----------------------------*/
63
64status_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
116status_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
148status_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
184void 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
196status_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
224status_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
285status_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
337status_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
381char * 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
403status_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
416status_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
422status_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
428static 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
446status_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
477void V4LCameraAdapter::onOrientationEvent(uint32_t orientation, uint32_t tilt)
478{
479    LOG_FUNCTION_NAME;
480
481    LOG_FUNCTION_NAME_EXIT;
482}
483
484
485V4LCameraAdapter::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
494V4LCameraAdapter::~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
513int 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
563extern "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
582extern "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