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 OMXCapture.cpp 19 * 20 * This file contains functionality for handling image capture. 21 * 22 */ 23 24 #undef LOG_TAG 25 26 #define LOG_TAG "CameraHAL" 27 28 #include "CameraHal.h" 29 #include "OMXCameraAdapter.h" 30 #include "ErrorUtils.h" 31 32 33 namespace android { 34 35 status_t OMXCameraAdapter::setParametersCapture(const CameraParameters ¶ms, 36 BaseCameraAdapter::AdapterState state) 37 { 38 status_t ret = NO_ERROR; 39 const char *str = NULL; 40 int w, h; 41 OMX_COLOR_FORMATTYPE pixFormat; 42 const char *valstr = NULL; 43 44 LOG_FUNCTION_NAME; 45 46 OMXCameraPortParameters *cap; 47 cap = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex]; 48 49 params.getPictureSize(&w, &h); 50 51 if ( ( w != ( int ) cap->mWidth ) || 52 ( h != ( int ) cap->mHeight ) ) 53 { 54 mPendingCaptureSettings |= SetFormat; 55 } 56 57 cap->mWidth = w; 58 cap->mHeight = h; 59 //TODO: Support more pixelformats 60 cap->mStride = 2; 61 62 CAMHAL_LOGVB("Image: cap.mWidth = %d", (int)cap->mWidth); 63 CAMHAL_LOGVB("Image: cap.mHeight = %d", (int)cap->mHeight); 64 65 if ( (valstr = params.getPictureFormat()) != NULL ) 66 { 67 if (strcmp(valstr, (const char *) CameraParameters::PIXEL_FORMAT_YUV422I) == 0) 68 { 69 CAMHAL_LOGDA("CbYCrY format selected"); 70 pixFormat = OMX_COLOR_FormatCbYCrY; 71 } 72 else if(strcmp(valstr, (const char *) CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) 73 { 74 CAMHAL_LOGDA("YUV420SP format selected"); 75 pixFormat = OMX_COLOR_FormatYUV420SemiPlanar; 76 } 77 else if(strcmp(valstr, (const char *) CameraParameters::PIXEL_FORMAT_RGB565) == 0) 78 { 79 CAMHAL_LOGDA("RGB565 format selected"); 80 pixFormat = OMX_COLOR_Format16bitRGB565; 81 } 82 else if(strcmp(valstr, (const char *) CameraParameters::PIXEL_FORMAT_JPEG) == 0) 83 { 84 CAMHAL_LOGDA("JPEG format selected"); 85 pixFormat = OMX_COLOR_FormatUnused; 86 mCodingMode = CodingNone; 87 } 88 else if(strcmp(valstr, (const char *) TICameraParameters::PIXEL_FORMAT_JPS) == 0) 89 { 90 CAMHAL_LOGDA("JPS format selected"); 91 pixFormat = OMX_COLOR_FormatUnused; 92 mCodingMode = CodingJPS; 93 } 94 else if(strcmp(valstr, (const char *) TICameraParameters::PIXEL_FORMAT_MPO) == 0) 95 { 96 CAMHAL_LOGDA("MPO format selected"); 97 pixFormat = OMX_COLOR_FormatUnused; 98 mCodingMode = CodingMPO; 99 } 100 else if(strcmp(valstr, (const char *) TICameraParameters::PIXEL_FORMAT_RAW_JPEG) == 0) 101 { 102 CAMHAL_LOGDA("RAW + JPEG format selected"); 103 pixFormat = OMX_COLOR_FormatUnused; 104 mCodingMode = CodingRAWJPEG; 105 } 106 else if(strcmp(valstr, (const char *) TICameraParameters::PIXEL_FORMAT_RAW_MPO) == 0) 107 { 108 CAMHAL_LOGDA("RAW + MPO format selected"); 109 pixFormat = OMX_COLOR_FormatUnused; 110 mCodingMode = CodingRAWMPO; 111 } 112 else if(strcmp(valstr, (const char *) TICameraParameters::PIXEL_FORMAT_RAW) == 0) 113 { 114 CAMHAL_LOGDA("RAW Picture format selected"); 115 pixFormat = OMX_COLOR_FormatRawBayer10bit; 116 } 117 else 118 { 119 CAMHAL_LOGEA("Invalid format, JPEG format selected as default"); 120 pixFormat = OMX_COLOR_FormatUnused; 121 } 122 } 123 else 124 { 125 CAMHAL_LOGEA("Picture format is NULL, defaulting to JPEG"); 126 pixFormat = OMX_COLOR_FormatUnused; 127 } 128 129 // JPEG capture is not supported in video mode by OMX Camera 130 // Set capture format to yuv422i...jpeg encode will 131 // be done on A9 132 valstr = params.get(TICameraParameters::KEY_CAP_MODE); 133 if ( (valstr && !strcmp(valstr, (const char *) TICameraParameters::VIDEO_MODE)) && 134 (pixFormat == OMX_COLOR_FormatUnused) ) { 135 CAMHAL_LOGDA("Capturing in video mode...selecting yuv422i"); 136 pixFormat = OMX_COLOR_FormatCbYCrY; 137 } 138 139 if ( pixFormat != cap->mColorFormat ) 140 { 141 mPendingCaptureSettings |= SetFormat; 142 cap->mColorFormat = pixFormat; 143 } 144 145 str = params.get(TICameraParameters::KEY_EXP_BRACKETING_RANGE); 146 if ( NULL != str ) { 147 parseExpRange(str, mExposureBracketingValues, EXP_BRACKET_RANGE, mExposureBracketingValidEntries); 148 } else { 149 // if bracketing was previously set...we set again before capturing to clear 150 if (mExposureBracketingValidEntries) mPendingCaptureSettings |= SetExpBracket; 151 mExposureBracketingValidEntries = 0; 152 } 153 154 if ( params.getInt(CameraParameters::KEY_ROTATION) != -1 ) 155 { 156 if (params.getInt(CameraParameters::KEY_ROTATION) != mPictureRotation) { 157 mPendingCaptureSettings |= SetRotation; 158 } 159 mPictureRotation = params.getInt(CameraParameters::KEY_ROTATION); 160 } 161 else 162 { 163 if (mPictureRotation) mPendingCaptureSettings |= SetRotation; 164 mPictureRotation = 0; 165 } 166 167 CAMHAL_LOGVB("Picture Rotation set %d", mPictureRotation); 168 169 // Read Sensor Orientation and set it based on perating mode 170 171 if (( params.getInt(TICameraParameters::KEY_SENSOR_ORIENTATION) != -1 ) && (mCapMode == OMXCameraAdapter::VIDEO_MODE)) 172 { 173 mSensorOrientation = params.getInt(TICameraParameters::KEY_SENSOR_ORIENTATION); 174 if (mSensorOrientation == 270 ||mSensorOrientation==90) 175 { 176 CAMHAL_LOGEA(" Orientation is 270/90. So setting counter rotation to Ducati"); 177 mSensorOrientation +=180; 178 mSensorOrientation%=360; 179 } 180 } 181 else 182 { 183 mSensorOrientation = 0; 184 } 185 186 CAMHAL_LOGVB("Sensor Orientation set : %d", mSensorOrientation); 187 188 if ( params.getInt(TICameraParameters::KEY_BURST) >= 1 ) 189 { 190 if (params.getInt(TICameraParameters::KEY_BURST) != mBurstFrames) { 191 mPendingCaptureSettings |= SetExpBracket; 192 } 193 mBurstFrames = params.getInt(TICameraParameters::KEY_BURST); 194 } 195 else 196 { 197 if (mBurstFrames != 1) mPendingCaptureSettings |= SetExpBracket; 198 mBurstFrames = 1; 199 } 200 201 CAMHAL_LOGVB("Burst Frames set %d", mBurstFrames); 202 203 if ( ( params.getInt(CameraParameters::KEY_JPEG_QUALITY) >= MIN_JPEG_QUALITY ) && 204 ( params.getInt(CameraParameters::KEY_JPEG_QUALITY) <= MAX_JPEG_QUALITY ) ) 205 { 206 if (params.getInt(CameraParameters::KEY_JPEG_QUALITY) != mPictureQuality) { 207 mPendingCaptureSettings |= SetQuality; 208 } 209 mPictureQuality = params.getInt(CameraParameters::KEY_JPEG_QUALITY); 210 } 211 else 212 { 213 if (mPictureQuality != MAX_JPEG_QUALITY) mPendingCaptureSettings |= SetQuality; 214 mPictureQuality = MAX_JPEG_QUALITY; 215 } 216 217 CAMHAL_LOGVB("Picture Quality set %d", mPictureQuality); 218 219 if ( params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH) >= 0 ) 220 { 221 if (params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH) != mThumbWidth) { 222 mPendingCaptureSettings |= SetThumb; 223 } 224 mThumbWidth = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH); 225 } 226 else 227 { 228 if (mThumbWidth != DEFAULT_THUMB_WIDTH) mPendingCaptureSettings |= SetThumb; 229 mThumbWidth = DEFAULT_THUMB_WIDTH; 230 } 231 232 233 CAMHAL_LOGVB("Picture Thumb width set %d", mThumbWidth); 234 235 if ( params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT) >= 0 ) 236 { 237 if (params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT) != mThumbHeight) { 238 mPendingCaptureSettings |= SetThumb; 239 } 240 mThumbHeight = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT); 241 } 242 else 243 { 244 if (mThumbHeight != DEFAULT_THUMB_HEIGHT) mPendingCaptureSettings |= SetThumb; 245 mThumbHeight = DEFAULT_THUMB_HEIGHT; 246 } 247 248 249 CAMHAL_LOGVB("Picture Thumb height set %d", mThumbHeight); 250 251 if ( ( params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY) >= MIN_JPEG_QUALITY ) && 252 ( params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY) <= MAX_JPEG_QUALITY ) ) 253 { 254 if (params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY) != mThumbQuality) { 255 mPendingCaptureSettings |= SetThumb; 256 } 257 mThumbQuality = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY); 258 } 259 else 260 { 261 if (mThumbQuality != MAX_JPEG_QUALITY) mPendingCaptureSettings |= SetThumb; 262 mThumbQuality = MAX_JPEG_QUALITY; 263 } 264 265 CAMHAL_LOGDB("Thumbnail Quality set %d", mThumbQuality); 266 267 if (mFirstTimeInit) { 268 mPendingCaptureSettings = ECapturesettingsAll; 269 } 270 271 if (mPendingCaptureSettings) { 272 disableImagePort(); 273 if ( NULL != mReleaseImageBuffersCallback ) { 274 mReleaseImageBuffersCallback(mReleaseData); 275 } 276 } 277 278 LOG_FUNCTION_NAME_EXIT; 279 280 return ret; 281 } 282 283 status_t OMXCameraAdapter::getPictureBufferSize(size_t &length, size_t bufferCount) 284 { 285 status_t ret = NO_ERROR; 286 OMXCameraPortParameters *imgCaptureData = NULL; 287 OMX_ERRORTYPE eError = OMX_ErrorNone; 288 289 LOG_FUNCTION_NAME; 290 291 if ( NO_ERROR == ret ) 292 { 293 imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex]; 294 295 imgCaptureData->mNumBufs = bufferCount; 296 297 // check if image port is already configured... 298 // if it already configured then we don't have to query again 299 if (!mCaptureConfigured) { 300 ret = setFormat(OMX_CAMERA_PORT_IMAGE_OUT_IMAGE, *imgCaptureData); 301 } 302 303 if ( ret == NO_ERROR ) 304 { 305 length = imgCaptureData->mBufSize; 306 } 307 else 308 { 309 CAMHAL_LOGEB("setFormat() failed 0x%x", ret); 310 length = 0; 311 } 312 } 313 314 CAMHAL_LOGDB("getPictureBufferSize %d", length); 315 316 LOG_FUNCTION_NAME_EXIT; 317 318 return ret; 319 } 320 321 status_t OMXCameraAdapter::parseExpRange(const char *rangeStr, 322 int * expRange, 323 size_t count, 324 size_t &validEntries) 325 { 326 status_t ret = NO_ERROR; 327 char *ctx, *expVal; 328 char *tmp = NULL; 329 size_t i = 0; 330 331 LOG_FUNCTION_NAME; 332 333 if ( NULL == rangeStr ) 334 { 335 return -EINVAL; 336 } 337 338 if ( NULL == expRange ) 339 { 340 return -EINVAL; 341 } 342 343 if ( NO_ERROR == ret ) 344 { 345 tmp = ( char * ) malloc( strlen(rangeStr) + 1 ); 346 347 if ( NULL == tmp ) 348 { 349 CAMHAL_LOGEA("No resources for temporary buffer"); 350 return -1; 351 } 352 memset(tmp, '\0', strlen(rangeStr) + 1); 353 354 } 355 356 if ( NO_ERROR == ret ) 357 { 358 strncpy(tmp, rangeStr, strlen(rangeStr) ); 359 expVal = strtok_r( (char *) tmp, CameraHal::PARAMS_DELIMITER, &ctx); 360 361 i = 0; 362 while ( ( NULL != expVal ) && ( i < count ) ) 363 { 364 expRange[i] = atoi(expVal); 365 expVal = strtok_r(NULL, CameraHal::PARAMS_DELIMITER, &ctx); 366 i++; 367 } 368 validEntries = i; 369 } 370 371 if ( NULL != tmp ) 372 { 373 free(tmp); 374 } 375 376 LOG_FUNCTION_NAME_EXIT; 377 378 return ret; 379 } 380 381 status_t OMXCameraAdapter::setExposureBracketing(int *evValues, 382 size_t evCount, 383 size_t frameCount) 384 { 385 status_t ret = NO_ERROR; 386 OMX_ERRORTYPE eError = OMX_ErrorNone; 387 OMX_CONFIG_CAPTUREMODETYPE expCapMode; 388 OMX_CONFIG_EXTCAPTUREMODETYPE extExpCapMode; 389 390 LOG_FUNCTION_NAME; 391 392 if ( OMX_StateInvalid == mComponentState ) 393 { 394 CAMHAL_LOGEA("OMX component is in invalid state"); 395 ret = -EINVAL; 396 } 397 398 if ( NULL == evValues ) 399 { 400 CAMHAL_LOGEA("Exposure compensation values pointer is invalid"); 401 ret = -EINVAL; 402 } 403 404 if ( NO_ERROR == ret ) 405 { 406 OMX_INIT_STRUCT_PTR (&expCapMode, OMX_CONFIG_CAPTUREMODETYPE); 407 expCapMode.nPortIndex = mCameraAdapterParameters.mImagePortIndex; 408 409 /// If frameCount>0 but evCount<=0, then this is the case of HQ burst. 410 //Otherwise, it is normal HQ capture 411 ///If frameCount>0 and evCount>0 then this is the cause of HQ Exposure bracketing. 412 if ( 0 == evCount && 0 == frameCount ) 413 { 414 expCapMode.bFrameLimited = OMX_FALSE; 415 } 416 else 417 { 418 expCapMode.bFrameLimited = OMX_TRUE; 419 expCapMode.nFrameLimit = frameCount; 420 } 421 422 eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, 423 OMX_IndexConfigCaptureMode, 424 &expCapMode); 425 if ( OMX_ErrorNone != eError ) 426 { 427 CAMHAL_LOGEB("Error while configuring capture mode 0x%x", eError); 428 } 429 else 430 { 431 CAMHAL_LOGDA("Camera capture mode configured successfully"); 432 } 433 } 434 435 if ( NO_ERROR == ret ) 436 { 437 OMX_INIT_STRUCT_PTR (&extExpCapMode, OMX_CONFIG_EXTCAPTUREMODETYPE); 438 extExpCapMode.nPortIndex = mCameraAdapterParameters.mImagePortIndex; 439 440 if ( 0 == evCount ) 441 { 442 extExpCapMode.bEnableBracketing = OMX_FALSE; 443 } 444 else 445 { 446 extExpCapMode.bEnableBracketing = OMX_TRUE; 447 extExpCapMode.tBracketConfigType.eBracketMode = OMX_BracketExposureRelativeInEV; 448 extExpCapMode.tBracketConfigType.nNbrBracketingValues = evCount - 1; 449 } 450 451 for ( unsigned int i = 0 ; i < evCount ; i++ ) 452 { 453 extExpCapMode.tBracketConfigType.nBracketValues[i] = ( evValues[i] * ( 1 << Q16_OFFSET ) ) / 10; 454 } 455 456 eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, 457 ( OMX_INDEXTYPE ) OMX_IndexConfigExtCaptureMode, 458 &extExpCapMode); 459 if ( OMX_ErrorNone != eError ) 460 { 461 CAMHAL_LOGEB("Error while configuring extended capture mode 0x%x", eError); 462 } 463 else 464 { 465 CAMHAL_LOGDA("Extended camera capture mode configured successfully"); 466 } 467 } 468 469 LOG_FUNCTION_NAME_EXIT; 470 471 return ret; 472 } 473 474 status_t OMXCameraAdapter::setShutterCallback(bool enabled) 475 { 476 status_t ret = NO_ERROR; 477 OMX_ERRORTYPE eError = OMX_ErrorNone; 478 OMX_CONFIG_CALLBACKREQUESTTYPE shutterRequstCallback; 479 480 LOG_FUNCTION_NAME; 481 482 if ( OMX_StateExecuting != mComponentState ) 483 { 484 CAMHAL_LOGEA("OMX component not in executing state"); 485 ret = -1; 486 } 487 488 if ( NO_ERROR == ret ) 489 { 490 491 OMX_INIT_STRUCT_PTR (&shutterRequstCallback, OMX_CONFIG_CALLBACKREQUESTTYPE); 492 shutterRequstCallback.nPortIndex = OMX_ALL; 493 494 if ( enabled ) 495 { 496 shutterRequstCallback.bEnable = OMX_TRUE; 497 shutterRequstCallback.nIndex = ( OMX_INDEXTYPE ) OMX_TI_IndexConfigShutterCallback; 498 CAMHAL_LOGDA("Enabling shutter callback"); 499 } 500 else 501 { 502 shutterRequstCallback.bEnable = OMX_FALSE; 503 shutterRequstCallback.nIndex = ( OMX_INDEXTYPE ) OMX_TI_IndexConfigShutterCallback; 504 CAMHAL_LOGDA("Disabling shutter callback"); 505 } 506 507 eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, 508 ( OMX_INDEXTYPE ) OMX_IndexConfigCallbackRequest, 509 &shutterRequstCallback); 510 if ( OMX_ErrorNone != eError ) 511 { 512 CAMHAL_LOGEB("Error registering shutter callback 0x%x", eError); 513 ret = -1; 514 } 515 else 516 { 517 CAMHAL_LOGDB("Shutter callback for index 0x%x registered successfully", 518 OMX_TI_IndexConfigShutterCallback); 519 } 520 } 521 522 LOG_FUNCTION_NAME_EXIT; 523 524 return ret; 525 } 526 527 status_t OMXCameraAdapter::doBracketing(OMX_BUFFERHEADERTYPE *pBuffHeader, 528 CameraFrame::FrameType typeOfFrame) 529 { 530 status_t ret = NO_ERROR; 531 int currentBufferIdx, nextBufferIdx; 532 OMXCameraPortParameters * imgCaptureData = NULL; 533 534 LOG_FUNCTION_NAME; 535 536 imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex]; 537 538 if ( OMX_StateExecuting != mComponentState ) 539 { 540 CAMHAL_LOGEA("OMX component is not in executing state"); 541 ret = -EINVAL; 542 } 543 544 if ( NO_ERROR == ret ) 545 { 546 currentBufferIdx = ( unsigned int ) pBuffHeader->pAppPrivate; 547 548 if ( currentBufferIdx >= imgCaptureData->mNumBufs) 549 { 550 CAMHAL_LOGEB("Invalid bracketing buffer index 0x%x", currentBufferIdx); 551 ret = -EINVAL; 552 } 553 } 554 555 if ( NO_ERROR == ret ) 556 { 557 mBracketingBuffersQueued[currentBufferIdx] = false; 558 mBracketingBuffersQueuedCount--; 559 560 if ( 0 >= mBracketingBuffersQueuedCount ) 561 { 562 nextBufferIdx = ( currentBufferIdx + 1 ) % imgCaptureData->mNumBufs; 563 mBracketingBuffersQueued[nextBufferIdx] = true; 564 mBracketingBuffersQueuedCount++; 565 mLastBracetingBufferIdx = nextBufferIdx; 566 setFrameRefCount(imgCaptureData->mBufferHeader[nextBufferIdx]->pBuffer, typeOfFrame, 1); 567 returnFrame(imgCaptureData->mBufferHeader[nextBufferIdx]->pBuffer, typeOfFrame); 568 } 569 } 570 571 LOG_FUNCTION_NAME_EXIT; 572 573 return ret; 574 } 575 576 status_t OMXCameraAdapter::sendBracketFrames() 577 { 578 status_t ret = NO_ERROR; 579 int currentBufferIdx; 580 OMXCameraPortParameters * imgCaptureData = NULL; 581 582 LOG_FUNCTION_NAME; 583 584 imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex]; 585 586 if ( OMX_StateExecuting != mComponentState ) 587 { 588 CAMHAL_LOGEA("OMX component is not in executing state"); 589 ret = -EINVAL; 590 } 591 592 if ( NO_ERROR == ret ) 593 { 594 595 currentBufferIdx = mLastBracetingBufferIdx; 596 do 597 { 598 currentBufferIdx++; 599 currentBufferIdx %= imgCaptureData->mNumBufs; 600 if (!mBracketingBuffersQueued[currentBufferIdx] ) 601 { 602 CameraFrame cameraFrame; 603 sendCallBacks(cameraFrame, 604 imgCaptureData->mBufferHeader[currentBufferIdx], 605 imgCaptureData->mImageType, 606 imgCaptureData); 607 } 608 } while ( currentBufferIdx != mLastBracetingBufferIdx ); 609 610 } 611 612 LOG_FUNCTION_NAME_EXIT; 613 614 return ret; 615 } 616 617 status_t OMXCameraAdapter::startBracketing(int range) 618 { 619 status_t ret = NO_ERROR; 620 OMXCameraPortParameters * imgCaptureData = NULL; 621 622 LOG_FUNCTION_NAME; 623 624 imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex]; 625 626 if ( OMX_StateExecuting != mComponentState ) 627 { 628 CAMHAL_LOGEA("OMX component is not in executing state"); 629 ret = -EINVAL; 630 } 631 632 { 633 Mutex::Autolock lock(mBracketingLock); 634 635 if ( mBracketingEnabled ) 636 { 637 return ret; 638 } 639 } 640 641 if ( 0 == imgCaptureData->mNumBufs ) 642 { 643 CAMHAL_LOGEB("Image capture buffers set to %d", imgCaptureData->mNumBufs); 644 ret = -EINVAL; 645 } 646 647 if ( mPending3Asettings ) 648 apply3Asettings(mParameters3A); 649 650 if ( NO_ERROR == ret ) 651 { 652 Mutex::Autolock lock(mBracketingLock); 653 654 mBracketingRange = range; 655 mBracketingBuffersQueued = new bool[imgCaptureData->mNumBufs]; 656 if ( NULL == mBracketingBuffersQueued ) 657 { 658 CAMHAL_LOGEA("Unable to allocate bracketing management structures"); 659 ret = -1; 660 } 661 662 if ( NO_ERROR == ret ) 663 { 664 mBracketingBuffersQueuedCount = imgCaptureData->mNumBufs; 665 mLastBracetingBufferIdx = mBracketingBuffersQueuedCount - 1; 666 667 for ( int i = 0 ; i < imgCaptureData->mNumBufs ; i++ ) 668 { 669 mBracketingBuffersQueued[i] = true; 670 } 671 672 } 673 } 674 675 if ( NO_ERROR == ret ) 676 { 677 678 ret = startImageCapture(); 679 { 680 Mutex::Autolock lock(mBracketingLock); 681 682 if ( NO_ERROR == ret ) 683 { 684 mBracketingEnabled = true; 685 } 686 else 687 { 688 mBracketingEnabled = false; 689 } 690 } 691 } 692 693 LOG_FUNCTION_NAME_EXIT; 694 695 return ret; 696 } 697 698 status_t OMXCameraAdapter::stopBracketing() 699 { 700 status_t ret = NO_ERROR; 701 702 LOG_FUNCTION_NAME; 703 704 Mutex::Autolock lock(mBracketingLock); 705 706 if ( NULL != mBracketingBuffersQueued ) 707 { 708 delete [] mBracketingBuffersQueued; 709 } 710 711 ret = stopImageCapture(); 712 713 mBracketingBuffersQueued = NULL; 714 mBracketingEnabled = false; 715 mBracketingBuffersQueuedCount = 0; 716 mLastBracetingBufferIdx = 0; 717 718 LOG_FUNCTION_NAME_EXIT; 719 720 return ret; 721 } 722 723 status_t OMXCameraAdapter::startImageCapture() 724 { 725 status_t ret = NO_ERROR; 726 OMX_ERRORTYPE eError = OMX_ErrorNone; 727 OMXCameraPortParameters * capData = NULL; 728 OMX_CONFIG_BOOLEANTYPE bOMX; 729 730 LOG_FUNCTION_NAME; 731 732 if(!mCaptureConfigured) 733 { 734 ///Image capture was cancelled before we could start 735 return NO_ERROR; 736 } 737 738 if ( 0 != mStartCaptureSem.Count() ) 739 { 740 CAMHAL_LOGEB("Error mStartCaptureSem semaphore count %d", mStartCaptureSem.Count()); 741 return NO_INIT; 742 } 743 744 // Camera framework doesn't expect face callbacks once capture is triggered 745 pauseFaceDetection(true); 746 747 //During bracketing image capture is already active 748 { 749 Mutex::Autolock lock(mBracketingLock); 750 if ( mBracketingEnabled ) 751 { 752 //Stop bracketing, activate normal burst for the remaining images 753 mBracketingEnabled = false; 754 mCapturedFrames = mBracketingRange; 755 ret = sendBracketFrames(); 756 if(ret != NO_ERROR) 757 goto EXIT; 758 else 759 return ret; 760 } 761 } 762 763 if ( NO_ERROR == ret ) { 764 if (mPendingCaptureSettings & SetRotation) { 765 mPendingCaptureSettings &= ~SetRotation; 766 ret = setPictureRotation(mPictureRotation); 767 if ( NO_ERROR != ret ) { 768 CAMHAL_LOGEB("Error configuring image rotation %x", ret); 769 } 770 } 771 } 772 773 //OMX shutter callback events are only available in hq mode 774 if ( (HIGH_QUALITY == mCapMode) || (HIGH_QUALITY_ZSL== mCapMode)) 775 { 776 777 if ( NO_ERROR == ret ) 778 { 779 ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp, 780 (OMX_EVENTTYPE) OMX_EventIndexSettingChanged, 781 OMX_ALL, 782 OMX_TI_IndexConfigShutterCallback, 783 mStartCaptureSem); 784 } 785 786 if ( NO_ERROR == ret ) 787 { 788 ret = setShutterCallback(true); 789 } 790 791 } 792 793 if ( NO_ERROR == ret ) { 794 capData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex]; 795 796 ///Queue all the buffers on capture port 797 for ( int index = 0 ; index < capData->mNumBufs ; index++ ) { 798 CAMHAL_LOGDB("Queuing buffer on Capture port - 0x%x", 799 ( unsigned int ) capData->mBufferHeader[index]->pBuffer); 800 eError = OMX_FillThisBuffer(mCameraAdapterParameters.mHandleComp, 801 (OMX_BUFFERHEADERTYPE*)capData->mBufferHeader[index]); 802 803 GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError); 804 } 805 806 mWaitingForSnapshot = true; 807 mCaptureSignalled = false; 808 809 // Capturing command is not needed when capturing in video mode 810 // Only need to queue buffers on image ports 811 if (mCapMode != VIDEO_MODE) { 812 OMX_INIT_STRUCT_PTR (&bOMX, OMX_CONFIG_BOOLEANTYPE); 813 bOMX.bEnabled = OMX_TRUE; 814 815 /// sending Capturing Command to the component 816 eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, 817 OMX_IndexConfigCapturing, 818 &bOMX); 819 820 CAMHAL_LOGDB("Capture set - 0x%x", eError); 821 822 GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError); 823 } 824 } 825 826 //OMX shutter callback events are only available in hq mode 827 if ( (HIGH_QUALITY == mCapMode) || (HIGH_QUALITY_ZSL== mCapMode)) 828 { 829 830 if ( NO_ERROR == ret ) 831 { 832 ret = mStartCaptureSem.WaitTimeout(OMX_CAPTURE_TIMEOUT); 833 } 834 835 //If somethiing bad happened while we wait 836 if (mComponentState == OMX_StateInvalid) 837 { 838 CAMHAL_LOGEA("Invalid State after Image Capture Exitting!!!"); 839 goto EXIT; 840 } 841 842 if ( NO_ERROR == ret ) 843 { 844 CAMHAL_LOGDA("Shutter callback received"); 845 notifyShutterSubscribers(); 846 } 847 else 848 { 849 ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp, 850 (OMX_EVENTTYPE) OMX_EventIndexSettingChanged, 851 OMX_ALL, 852 OMX_TI_IndexConfigShutterCallback, 853 NULL); 854 CAMHAL_LOGEA("Timeout expired on shutter callback"); 855 goto EXIT; 856 } 857 858 } 859 860 return (ret | ErrorUtils::omxToAndroidError(eError)); 861 862 EXIT: 863 CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError); 864 mWaitingForSnapshot = false; 865 mCaptureSignalled = false; 866 performCleanupAfterError(); 867 LOG_FUNCTION_NAME_EXIT; 868 return (ret | ErrorUtils::omxToAndroidError(eError)); 869 } 870 871 status_t OMXCameraAdapter::stopImageCapture() 872 { 873 status_t ret = NO_ERROR; 874 OMX_ERRORTYPE eError = OMX_ErrorNone; 875 OMX_CONFIG_BOOLEANTYPE bOMX; 876 OMXCameraPortParameters *imgCaptureData = NULL; 877 878 LOG_FUNCTION_NAME; 879 880 if (!mCaptureConfigured) { 881 //Capture is not ongoing, return from here 882 return NO_ERROR; 883 } 884 885 if ( 0 != mStopCaptureSem.Count() ) { 886 CAMHAL_LOGEB("Error mStopCaptureSem semaphore count %d", mStopCaptureSem.Count()); 887 goto EXIT; 888 } 889 890 //Disable the callback first 891 mWaitingForSnapshot = false; 892 mSnapshotCount = 0; 893 894 // OMX shutter callback events are only available in hq mode 895 if ((HIGH_QUALITY == mCapMode) || (HIGH_QUALITY_ZSL== mCapMode)) { 896 //Disable the callback first 897 ret = setShutterCallback(false); 898 899 // if anybody is waiting on the shutter callback 900 // signal them and then recreate the semaphore 901 if ( 0 != mStartCaptureSem.Count() ) { 902 for (int i = mStopCaptureSem.Count(); i > 0; i--) { 903 ret |= SignalEvent(mCameraAdapterParameters.mHandleComp, 904 (OMX_EVENTTYPE) OMX_EventIndexSettingChanged, 905 OMX_ALL, 906 OMX_TI_IndexConfigShutterCallback, 907 NULL ); 908 } 909 mStartCaptureSem.Create(0); 910 } 911 } 912 913 // After capture, face detection should be disabled 914 // and application needs to restart face detection 915 stopFaceDetection(); 916 917 //Wait here for the capture to be done, in worst case timeout and proceed with cleanup 918 ret = mCaptureSem.WaitTimeout(OMX_CAPTURE_TIMEOUT); 919 920 //If somethiing bad happened while we wait 921 if (mComponentState == OMX_StateInvalid) 922 { 923 CAMHAL_LOGEA("Invalid State Image Capture Stop Exitting!!!"); 924 goto EXIT; 925 } 926 927 if ( NO_ERROR != ret ) { 928 ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp, 929 (OMX_EVENTTYPE) OMX_EventIndexSettingChanged, 930 OMX_ALL, 931 OMX_TI_IndexConfigShutterCallback, 932 NULL); 933 CAMHAL_LOGEA("Timeout expired on capture sem"); 934 goto EXIT; 935 } 936 937 // Disable image capture 938 // Capturing command is not needed when capturing in video mode 939 if (mCapMode != VIDEO_MODE) { 940 OMX_INIT_STRUCT_PTR (&bOMX, OMX_CONFIG_BOOLEANTYPE); 941 bOMX.bEnabled = OMX_FALSE; 942 imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex]; 943 eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, 944 OMX_IndexConfigCapturing, 945 &bOMX); 946 if ( OMX_ErrorNone != eError ) { 947 CAMHAL_LOGDB("Error during SetConfig- 0x%x", eError); 948 ret = -1; 949 goto EXIT; 950 } 951 } 952 CAMHAL_LOGDB("Capture set - 0x%x", eError); 953 954 mCaptureSignalled = true; //set this to true if we exited because of timeout 955 956 { 957 Mutex::Autolock lock(mFrameCountMutex); 958 mFrameCount = 0; 959 mFirstFrameCondition.broadcast(); 960 } 961 962 return (ret | ErrorUtils::omxToAndroidError(eError)); 963 964 EXIT: 965 CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError); 966 //Release image buffers 967 if ( NULL != mReleaseImageBuffersCallback ) { 968 mReleaseImageBuffersCallback(mReleaseData); 969 } 970 971 { 972 Mutex::Autolock lock(mFrameCountMutex); 973 mFrameCount = 0; 974 mFirstFrameCondition.broadcast(); 975 } 976 977 performCleanupAfterError(); 978 LOG_FUNCTION_NAME_EXIT; 979 return (ret | ErrorUtils::omxToAndroidError(eError)); 980 } 981 982 status_t OMXCameraAdapter::disableImagePort(){ 983 status_t ret = NO_ERROR; 984 OMX_ERRORTYPE eError = OMX_ErrorNone; 985 OMXCameraPortParameters *imgCaptureData = NULL; 986 987 if (!mCaptureConfigured) { 988 return NO_ERROR; 989 } 990 991 mCaptureConfigured = false; 992 imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex]; 993 994 ///Register for Image port Disable event 995 ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp, 996 OMX_EventCmdComplete, 997 OMX_CommandPortDisable, 998 mCameraAdapterParameters.mImagePortIndex, 999 mStopCaptureSem); 1000 ///Disable Capture Port 1001 eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp, 1002 OMX_CommandPortDisable, 1003 mCameraAdapterParameters.mImagePortIndex, 1004 NULL); 1005 1006 ///Free all the buffers on capture port 1007 if (imgCaptureData) { 1008 CAMHAL_LOGDB("Freeing buffer on Capture port - %d", imgCaptureData->mNumBufs); 1009 for ( int index = 0 ; index < imgCaptureData->mNumBufs ; index++) { 1010 CAMHAL_LOGDB("Freeing buffer on Capture port - 0x%x", 1011 ( unsigned int ) imgCaptureData->mBufferHeader[index]->pBuffer); 1012 eError = OMX_FreeBuffer(mCameraAdapterParameters.mHandleComp, 1013 mCameraAdapterParameters.mImagePortIndex, 1014 (OMX_BUFFERHEADERTYPE*)imgCaptureData->mBufferHeader[index]); 1015 1016 GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError); 1017 } 1018 } 1019 CAMHAL_LOGDA("Waiting for port disable"); 1020 //Wait for the image port enable event 1021 ret = mStopCaptureSem.WaitTimeout(OMX_CMD_TIMEOUT); 1022 1023 //If somethiing bad happened while we wait 1024 if (mComponentState == OMX_StateInvalid) 1025 { 1026 CAMHAL_LOGEA("Invalid State after Disable Image Port Exitting!!!"); 1027 goto EXIT; 1028 } 1029 1030 if ( NO_ERROR == ret ) { 1031 CAMHAL_LOGDA("Port disabled"); 1032 } else { 1033 ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp, 1034 OMX_EventCmdComplete, 1035 OMX_CommandPortDisable, 1036 mCameraAdapterParameters.mImagePortIndex, 1037 NULL); 1038 CAMHAL_LOGDA("Timeout expired on port disable"); 1039 goto EXIT; 1040 } 1041 1042 EXIT: 1043 return (ret | ErrorUtils::omxToAndroidError(eError)); 1044 } 1045 1046 1047 status_t OMXCameraAdapter::UseBuffersCapture(void* bufArr, int num) 1048 { 1049 LOG_FUNCTION_NAME; 1050 1051 status_t ret = NO_ERROR; 1052 OMX_ERRORTYPE eError = OMX_ErrorNone; 1053 OMXCameraPortParameters * imgCaptureData = NULL; 1054 uint32_t *buffers = (uint32_t*)bufArr; 1055 OMXCameraPortParameters cap; 1056 1057 imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex]; 1058 1059 if ( 0 != mUseCaptureSem.Count() ) 1060 { 1061 CAMHAL_LOGEB("Error mUseCaptureSem semaphore count %d", mUseCaptureSem.Count()); 1062 return BAD_VALUE; 1063 } 1064 1065 // capture is already configured...we can skip this step 1066 if (mCaptureConfigured) { 1067 1068 if ( NO_ERROR == ret ) 1069 { 1070 ret = setupEXIF(); 1071 if ( NO_ERROR != ret ) 1072 { 1073 CAMHAL_LOGEB("Error configuring EXIF Buffer %x", ret); 1074 } 1075 } 1076 1077 mCapturedFrames = mBurstFrames; 1078 return NO_ERROR; 1079 } 1080 1081 imgCaptureData->mNumBufs = num; 1082 1083 //TODO: Support more pixelformats 1084 1085 CAMHAL_LOGDB("Params Width = %d", (int)imgCaptureData->mWidth); 1086 CAMHAL_LOGDB("Params Height = %d", (int)imgCaptureData->mWidth); 1087 1088 if (mPendingCaptureSettings & SetFormat) { 1089 mPendingCaptureSettings &= ~SetFormat; 1090 ret = setFormat(OMX_CAMERA_PORT_IMAGE_OUT_IMAGE, *imgCaptureData); 1091 if ( ret != NO_ERROR ) { 1092 CAMHAL_LOGEB("setFormat() failed %d", ret); 1093 LOG_FUNCTION_NAME_EXIT; 1094 return ret; 1095 } 1096 } 1097 1098 if (mPendingCaptureSettings & SetThumb) { 1099 mPendingCaptureSettings &= ~SetThumb; 1100 ret = setThumbnailParams(mThumbWidth, mThumbHeight, mThumbQuality); 1101 if ( NO_ERROR != ret) { 1102 CAMHAL_LOGEB("Error configuring thumbnail size %x", ret); 1103 return ret; 1104 } 1105 } 1106 1107 if (mPendingCaptureSettings & SetExpBracket) { 1108 mPendingCaptureSettings &= ~SetExpBracket; 1109 ret = setExposureBracketing( mExposureBracketingValues, 1110 mExposureBracketingValidEntries, mBurstFrames); 1111 if ( ret != NO_ERROR ) { 1112 CAMHAL_LOGEB("setExposureBracketing() failed %d", ret); 1113 goto EXIT; 1114 } 1115 } 1116 1117 if (mPendingCaptureSettings & SetQuality) { 1118 mPendingCaptureSettings &= ~SetQuality; 1119 ret = setImageQuality(mPictureQuality); 1120 if ( NO_ERROR != ret) { 1121 CAMHAL_LOGEB("Error configuring image quality %x", ret); 1122 goto EXIT; 1123 } 1124 } 1125 1126 ///Register for Image port ENABLE event 1127 ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp, 1128 OMX_EventCmdComplete, 1129 OMX_CommandPortEnable, 1130 mCameraAdapterParameters.mImagePortIndex, 1131 mUseCaptureSem); 1132 1133 ///Enable Capture Port 1134 eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp, 1135 OMX_CommandPortEnable, 1136 mCameraAdapterParameters.mImagePortIndex, 1137 NULL); 1138 1139 CAMHAL_LOGDB("OMX_UseBuffer = 0x%x", eError); 1140 GOTO_EXIT_IF(( eError != OMX_ErrorNone ), eError); 1141 1142 for ( int index = 0 ; index < imgCaptureData->mNumBufs ; index++ ) 1143 { 1144 OMX_BUFFERHEADERTYPE *pBufferHdr; 1145 CAMHAL_LOGDB("OMX_UseBuffer Capture address: 0x%x, size = %d", 1146 (unsigned int)buffers[index], 1147 (int)imgCaptureData->mBufSize); 1148 1149 eError = OMX_UseBuffer(mCameraAdapterParameters.mHandleComp, 1150 &pBufferHdr, 1151 mCameraAdapterParameters.mImagePortIndex, 1152 0, 1153 mCaptureBuffersLength, 1154 (OMX_U8*)buffers[index]); 1155 1156 CAMHAL_LOGDB("OMX_UseBuffer = 0x%x", eError); 1157 GOTO_EXIT_IF(( eError != OMX_ErrorNone ), eError); 1158 1159 pBufferHdr->pAppPrivate = (OMX_PTR) index; 1160 pBufferHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); 1161 pBufferHdr->nVersion.s.nVersionMajor = 1 ; 1162 pBufferHdr->nVersion.s.nVersionMinor = 1 ; 1163 pBufferHdr->nVersion.s.nRevision = 0; 1164 pBufferHdr->nVersion.s.nStep = 0; 1165 imgCaptureData->mBufferHeader[index] = pBufferHdr; 1166 } 1167 1168 //Wait for the image port enable event 1169 CAMHAL_LOGDA("Waiting for port enable"); 1170 ret = mUseCaptureSem.WaitTimeout(OMX_CMD_TIMEOUT); 1171 1172 //If somethiing bad happened while we wait 1173 if (mComponentState == OMX_StateInvalid) 1174 { 1175 CAMHAL_LOGEA("Invalid State after Enable Image Port Exitting!!!"); 1176 goto EXIT; 1177 } 1178 1179 if ( ret == NO_ERROR ) 1180 { 1181 CAMHAL_LOGDA("Port enabled"); 1182 } 1183 else 1184 { 1185 ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp, 1186 OMX_EventCmdComplete, 1187 OMX_CommandPortEnable, 1188 mCameraAdapterParameters.mImagePortIndex, 1189 NULL); 1190 CAMHAL_LOGDA("Timeout expired on port enable"); 1191 goto EXIT; 1192 } 1193 1194 if ( NO_ERROR == ret ) 1195 { 1196 ret = setupEXIF(); 1197 if ( NO_ERROR != ret ) 1198 { 1199 CAMHAL_LOGEB("Error configuring EXIF Buffer %x", ret); 1200 } 1201 } 1202 1203 mCapturedFrames = mBurstFrames; 1204 mCaptureConfigured = true; 1205 1206 return (ret | ErrorUtils::omxToAndroidError(eError)); 1207 1208 EXIT: 1209 CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError); 1210 //Release image buffers 1211 if ( NULL != mReleaseImageBuffersCallback ) { 1212 mReleaseImageBuffersCallback(mReleaseData); 1213 } 1214 performCleanupAfterError(); 1215 LOG_FUNCTION_NAME_EXIT; 1216 return (ret | ErrorUtils::omxToAndroidError(eError)); 1217 1218 } 1219 1220 }; 1221