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 ¶ms)
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