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