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