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 if ((getNextState() & (CAPTURE_ACTIVE|BRACKETING_ACTIVE)) == 0) { 745 CAMHAL_LOGDA("trying starting capture when already canceled"); 746 return NO_ERROR; 747 } 748 749 // Camera framework doesn't expect face callbacks once capture is triggered 750 pauseFaceDetection(true); 751 752 //During bracketing image capture is already active 753 { 754 Mutex::Autolock lock(mBracketingLock); 755 if ( mBracketingEnabled ) 756 { 757 //Stop bracketing, activate normal burst for the remaining images 758 mBracketingEnabled = false; 759 mCapturedFrames = mBracketingRange; 760 ret = sendBracketFrames(); 761 if(ret != NO_ERROR) 762 goto EXIT; 763 else 764 return ret; 765 } 766 } 767 768 if ( NO_ERROR == ret ) { 769 if (mPendingCaptureSettings & SetRotation) { 770 mPendingCaptureSettings &= ~SetRotation; 771 ret = setPictureRotation(mPictureRotation); 772 if ( NO_ERROR != ret ) { 773 CAMHAL_LOGEB("Error configuring image rotation %x", ret); 774 } 775 } 776 } 777 778 //OMX shutter callback events are only available in hq mode 779 if ( (HIGH_QUALITY == mCapMode) || (HIGH_QUALITY_ZSL== mCapMode)) 780 { 781 782 if ( NO_ERROR == ret ) 783 { 784 ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp, 785 (OMX_EVENTTYPE) OMX_EventIndexSettingChanged, 786 OMX_ALL, 787 OMX_TI_IndexConfigShutterCallback, 788 mStartCaptureSem); 789 } 790 791 if ( NO_ERROR == ret ) 792 { 793 ret = setShutterCallback(true); 794 } 795 796 } 797 798 if ( NO_ERROR == ret ) { 799 capData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex]; 800 801 ///Queue all the buffers on capture port 802 for ( int index = 0 ; index < capData->mNumBufs ; index++ ) { 803 CAMHAL_LOGDB("Queuing buffer on Capture port - 0x%x", 804 ( unsigned int ) capData->mBufferHeader[index]->pBuffer); 805 eError = OMX_FillThisBuffer(mCameraAdapterParameters.mHandleComp, 806 (OMX_BUFFERHEADERTYPE*)capData->mBufferHeader[index]); 807 808 GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError); 809 } 810 811 mWaitingForSnapshot = true; 812 mCaptureSignalled = false; 813 814 // Capturing command is not needed when capturing in video mode 815 // Only need to queue buffers on image ports 816 if (mCapMode != VIDEO_MODE) { 817 OMX_INIT_STRUCT_PTR (&bOMX, OMX_CONFIG_BOOLEANTYPE); 818 bOMX.bEnabled = OMX_TRUE; 819 820 /// sending Capturing Command to the component 821 eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, 822 OMX_IndexConfigCapturing, 823 &bOMX); 824 825 CAMHAL_LOGDB("Capture set - 0x%x", eError); 826 827 GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError); 828 } 829 } 830 831 //OMX shutter callback events are only available in hq mode 832 if ( (HIGH_QUALITY == mCapMode) || (HIGH_QUALITY_ZSL== mCapMode)) 833 { 834 835 if ( NO_ERROR == ret ) 836 { 837 ret = mStartCaptureSem.WaitTimeout(OMX_CAPTURE_TIMEOUT); 838 } 839 840 //If something bad happened while we wait 841 if (mComponentState != OMX_StateExecuting) 842 { 843 CAMHAL_LOGEA("Invalid State after Image Capture Exitting!!!"); 844 goto EXIT; 845 } 846 847 if ( NO_ERROR == ret ) 848 { 849 CAMHAL_LOGDA("Shutter callback received"); 850 notifyShutterSubscribers(); 851 } 852 else 853 { 854 ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp, 855 (OMX_EVENTTYPE) OMX_EventIndexSettingChanged, 856 OMX_ALL, 857 OMX_TI_IndexConfigShutterCallback, 858 NULL); 859 CAMHAL_LOGEA("Timeout expired on shutter callback"); 860 goto EXIT; 861 } 862 863 } 864 865 return (ret | ErrorUtils::omxToAndroidError(eError)); 866 867 EXIT: 868 CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError); 869 mWaitingForSnapshot = false; 870 mCaptureSignalled = false; 871 performCleanupAfterError(); 872 LOG_FUNCTION_NAME_EXIT; 873 return (ret | ErrorUtils::omxToAndroidError(eError)); 874 } 875 876 status_t OMXCameraAdapter::stopImageCapture() 877 { 878 status_t ret = NO_ERROR; 879 OMX_ERRORTYPE eError = OMX_ErrorNone; 880 OMX_CONFIG_BOOLEANTYPE bOMX; 881 OMXCameraPortParameters *imgCaptureData = NULL; 882 883 LOG_FUNCTION_NAME; 884 885 if (!mCaptureConfigured) { 886 //Capture is not ongoing, return from here 887 return NO_ERROR; 888 } 889 890 if ( 0 != mStopCaptureSem.Count() ) { 891 CAMHAL_LOGEB("Error mStopCaptureSem semaphore count %d", mStopCaptureSem.Count()); 892 goto EXIT; 893 } 894 895 //Disable the callback first 896 mWaitingForSnapshot = false; 897 mSnapshotCount = 0; 898 899 // OMX shutter callback events are only available in hq mode 900 if ((HIGH_QUALITY == mCapMode) || (HIGH_QUALITY_ZSL== mCapMode)) { 901 //Disable the callback first 902 ret = setShutterCallback(false); 903 904 // if anybody is waiting on the shutter callback 905 // signal them and then recreate the semaphore 906 if ( 0 != mStartCaptureSem.Count() ) { 907 908 for (int i = mStartCaptureSem.Count(); i < 0; i++) { 909 ret |= SignalEvent(mCameraAdapterParameters.mHandleComp, 910 (OMX_EVENTTYPE) OMX_EventIndexSettingChanged, 911 OMX_ALL, 912 OMX_TI_IndexConfigShutterCallback, 913 NULL ); 914 } 915 mStartCaptureSem.Create(0); 916 } 917 } 918 919 // After capture, face detection should be disabled 920 // and application needs to restart face detection 921 stopFaceDetection(); 922 923 //Wait here for the capture to be done, in worst case timeout and proceed with cleanup 924 mCaptureSem.WaitTimeout(OMX_CAPTURE_TIMEOUT); 925 926 //If somethiing bad happened while we wait 927 if (mComponentState == OMX_StateInvalid) 928 { 929 CAMHAL_LOGEA("Invalid State Image Capture Stop Exitting!!!"); 930 goto EXIT; 931 } 932 933 // Disable image capture 934 // Capturing command is not needed when capturing in video mode 935 if (mCapMode != VIDEO_MODE) { 936 OMX_INIT_STRUCT_PTR (&bOMX, OMX_CONFIG_BOOLEANTYPE); 937 bOMX.bEnabled = OMX_FALSE; 938 imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex]; 939 eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, 940 OMX_IndexConfigCapturing, 941 &bOMX); 942 if ( OMX_ErrorNone != eError ) { 943 CAMHAL_LOGDB("Error during SetConfig- 0x%x", eError); 944 ret = -1; 945 goto EXIT; 946 } 947 } 948 CAMHAL_LOGDB("Capture set - 0x%x", eError); 949 950 mCaptureSignalled = true; //set this to true if we exited because of timeout 951 952 { 953 Mutex::Autolock lock(mFrameCountMutex); 954 mFrameCount = 0; 955 mFirstFrameCondition.broadcast(); 956 } 957 958 return (ret | ErrorUtils::omxToAndroidError(eError)); 959 960 EXIT: 961 CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError); 962 //Release image buffers 963 if ( NULL != mReleaseImageBuffersCallback ) { 964 mReleaseImageBuffersCallback(mReleaseData); 965 } 966 967 { 968 Mutex::Autolock lock(mFrameCountMutex); 969 mFrameCount = 0; 970 mFirstFrameCondition.broadcast(); 971 } 972 973 performCleanupAfterError(); 974 LOG_FUNCTION_NAME_EXIT; 975 return (ret | ErrorUtils::omxToAndroidError(eError)); 976 } 977 978 status_t OMXCameraAdapter::disableImagePort(){ 979 status_t ret = NO_ERROR; 980 OMX_ERRORTYPE eError = OMX_ErrorNone; 981 OMXCameraPortParameters *imgCaptureData = NULL; 982 983 if (!mCaptureConfigured) { 984 return NO_ERROR; 985 } 986 987 mCaptureConfigured = false; 988 imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex]; 989 990 ///Register for Image port Disable event 991 ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp, 992 OMX_EventCmdComplete, 993 OMX_CommandPortDisable, 994 mCameraAdapterParameters.mImagePortIndex, 995 mStopCaptureSem); 996 ///Disable Capture Port 997 eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp, 998 OMX_CommandPortDisable, 999 mCameraAdapterParameters.mImagePortIndex, 1000 NULL); 1001 1002 ///Free all the buffers on capture port 1003 if (imgCaptureData) { 1004 CAMHAL_LOGDB("Freeing buffer on Capture port - %d", imgCaptureData->mNumBufs); 1005 for ( int index = 0 ; index < imgCaptureData->mNumBufs ; index++) { 1006 CAMHAL_LOGDB("Freeing buffer on Capture port - 0x%x", 1007 ( unsigned int ) imgCaptureData->mBufferHeader[index]->pBuffer); 1008 eError = OMX_FreeBuffer(mCameraAdapterParameters.mHandleComp, 1009 mCameraAdapterParameters.mImagePortIndex, 1010 (OMX_BUFFERHEADERTYPE*)imgCaptureData->mBufferHeader[index]); 1011 1012 GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError); 1013 } 1014 } 1015 CAMHAL_LOGDA("Waiting for port disable"); 1016 //Wait for the image port enable event 1017 ret = mStopCaptureSem.WaitTimeout(OMX_CMD_TIMEOUT); 1018 1019 //If somethiing bad happened while we wait 1020 if (mComponentState == OMX_StateInvalid) 1021 { 1022 CAMHAL_LOGEA("Invalid State after Disable Image Port Exitting!!!"); 1023 goto EXIT; 1024 } 1025 1026 if ( NO_ERROR == ret ) { 1027 CAMHAL_LOGDA("Port disabled"); 1028 } else { 1029 ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp, 1030 OMX_EventCmdComplete, 1031 OMX_CommandPortDisable, 1032 mCameraAdapterParameters.mImagePortIndex, 1033 NULL); 1034 CAMHAL_LOGDA("Timeout expired on port disable"); 1035 goto EXIT; 1036 } 1037 1038 EXIT: 1039 return (ret | ErrorUtils::omxToAndroidError(eError)); 1040 } 1041 1042 1043 status_t OMXCameraAdapter::UseBuffersCapture(void* bufArr, int num) 1044 { 1045 LOG_FUNCTION_NAME; 1046 1047 status_t ret = NO_ERROR; 1048 OMX_ERRORTYPE eError = OMX_ErrorNone; 1049 OMXCameraPortParameters * imgCaptureData = NULL; 1050 uint32_t *buffers = (uint32_t*)bufArr; 1051 OMXCameraPortParameters cap; 1052 1053 imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex]; 1054 1055 if ( 0 != mUseCaptureSem.Count() ) 1056 { 1057 CAMHAL_LOGEB("Error mUseCaptureSem semaphore count %d", mUseCaptureSem.Count()); 1058 return BAD_VALUE; 1059 } 1060 1061 // capture is already configured...we can skip this step 1062 if (mCaptureConfigured) { 1063 1064 if ( NO_ERROR == ret ) 1065 { 1066 ret = setupEXIF(); 1067 if ( NO_ERROR != ret ) 1068 { 1069 CAMHAL_LOGEB("Error configuring EXIF Buffer %x", ret); 1070 } 1071 } 1072 1073 mCapturedFrames = mBurstFrames; 1074 return NO_ERROR; 1075 } 1076 1077 imgCaptureData->mNumBufs = num; 1078 1079 //TODO: Support more pixelformats 1080 1081 CAMHAL_LOGDB("Params Width = %d", (int)imgCaptureData->mWidth); 1082 CAMHAL_LOGDB("Params Height = %d", (int)imgCaptureData->mWidth); 1083 1084 if (mPendingCaptureSettings & SetFormat) { 1085 mPendingCaptureSettings &= ~SetFormat; 1086 ret = setFormat(OMX_CAMERA_PORT_IMAGE_OUT_IMAGE, *imgCaptureData); 1087 if ( ret != NO_ERROR ) { 1088 CAMHAL_LOGEB("setFormat() failed %d", ret); 1089 LOG_FUNCTION_NAME_EXIT; 1090 return ret; 1091 } 1092 } 1093 1094 if (mPendingCaptureSettings & SetThumb) { 1095 mPendingCaptureSettings &= ~SetThumb; 1096 ret = setThumbnailParams(mThumbWidth, mThumbHeight, mThumbQuality); 1097 if ( NO_ERROR != ret) { 1098 CAMHAL_LOGEB("Error configuring thumbnail size %x", ret); 1099 return ret; 1100 } 1101 } 1102 1103 if (mPendingCaptureSettings & SetExpBracket) { 1104 mPendingCaptureSettings &= ~SetExpBracket; 1105 ret = setExposureBracketing( mExposureBracketingValues, 1106 mExposureBracketingValidEntries, mBurstFrames); 1107 if ( ret != NO_ERROR ) { 1108 CAMHAL_LOGEB("setExposureBracketing() failed %d", ret); 1109 goto EXIT; 1110 } 1111 } 1112 1113 if (mPendingCaptureSettings & SetQuality) { 1114 mPendingCaptureSettings &= ~SetQuality; 1115 ret = setImageQuality(mPictureQuality); 1116 if ( NO_ERROR != ret) { 1117 CAMHAL_LOGEB("Error configuring image quality %x", ret); 1118 goto EXIT; 1119 } 1120 } 1121 1122 ///Register for Image port ENABLE event 1123 ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp, 1124 OMX_EventCmdComplete, 1125 OMX_CommandPortEnable, 1126 mCameraAdapterParameters.mImagePortIndex, 1127 mUseCaptureSem); 1128 1129 ///Enable Capture Port 1130 eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp, 1131 OMX_CommandPortEnable, 1132 mCameraAdapterParameters.mImagePortIndex, 1133 NULL); 1134 1135 CAMHAL_LOGDB("OMX_UseBuffer = 0x%x", eError); 1136 GOTO_EXIT_IF(( eError != OMX_ErrorNone ), eError); 1137 1138 for ( int index = 0 ; index < imgCaptureData->mNumBufs ; index++ ) 1139 { 1140 OMX_BUFFERHEADERTYPE *pBufferHdr; 1141 CAMHAL_LOGDB("OMX_UseBuffer Capture address: 0x%x, size = %d", 1142 (unsigned int)buffers[index], 1143 (int)imgCaptureData->mBufSize); 1144 1145 eError = OMX_UseBuffer(mCameraAdapterParameters.mHandleComp, 1146 &pBufferHdr, 1147 mCameraAdapterParameters.mImagePortIndex, 1148 0, 1149 mCaptureBuffersLength, 1150 (OMX_U8*)buffers[index]); 1151 1152 CAMHAL_LOGDB("OMX_UseBuffer = 0x%x", eError); 1153 GOTO_EXIT_IF(( eError != OMX_ErrorNone ), eError); 1154 1155 pBufferHdr->pAppPrivate = (OMX_PTR) index; 1156 pBufferHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); 1157 pBufferHdr->nVersion.s.nVersionMajor = 1 ; 1158 pBufferHdr->nVersion.s.nVersionMinor = 1 ; 1159 pBufferHdr->nVersion.s.nRevision = 0; 1160 pBufferHdr->nVersion.s.nStep = 0; 1161 imgCaptureData->mBufferHeader[index] = pBufferHdr; 1162 } 1163 1164 //Wait for the image port enable event 1165 CAMHAL_LOGDA("Waiting for port enable"); 1166 ret = mUseCaptureSem.WaitTimeout(OMX_CMD_TIMEOUT); 1167 1168 //If somethiing bad happened while we wait 1169 if (mComponentState == OMX_StateInvalid) 1170 { 1171 CAMHAL_LOGEA("Invalid State after Enable Image Port Exitting!!!"); 1172 goto EXIT; 1173 } 1174 1175 if ( ret == NO_ERROR ) 1176 { 1177 CAMHAL_LOGDA("Port enabled"); 1178 } 1179 else 1180 { 1181 ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp, 1182 OMX_EventCmdComplete, 1183 OMX_CommandPortEnable, 1184 mCameraAdapterParameters.mImagePortIndex, 1185 NULL); 1186 CAMHAL_LOGDA("Timeout expired on port enable"); 1187 goto EXIT; 1188 } 1189 1190 if ( NO_ERROR == ret ) 1191 { 1192 ret = setupEXIF(); 1193 if ( NO_ERROR != ret ) 1194 { 1195 CAMHAL_LOGEB("Error configuring EXIF Buffer %x", ret); 1196 } 1197 } 1198 1199 mCapturedFrames = mBurstFrames; 1200 mCaptureConfigured = true; 1201 1202 return (ret | ErrorUtils::omxToAndroidError(eError)); 1203 1204 EXIT: 1205 CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError); 1206 //Release image buffers 1207 if ( NULL != mReleaseImageBuffersCallback ) { 1208 mReleaseImageBuffersCallback(mReleaseData); 1209 } 1210 performCleanupAfterError(); 1211 LOG_FUNCTION_NAME_EXIT; 1212 return (ret | ErrorUtils::omxToAndroidError(eError)); 1213 1214 } 1215 1216 }; 1217