OMXCapture.cpp revision fc8ab094473901857ee382396eebc5d52ac4c6c6
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 33namespace android { 34 35status_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 283status_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 321status_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 381status_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 474status_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 527status_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 576status_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 617status_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 698status_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 723status_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 862EXIT: 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 871status_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 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 // Disable image capture 928 // Capturing command is not needed when capturing in video mode 929 if (mCapMode != VIDEO_MODE) { 930 OMX_INIT_STRUCT_PTR (&bOMX, OMX_CONFIG_BOOLEANTYPE); 931 bOMX.bEnabled = OMX_FALSE; 932 imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex]; 933 eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp, 934 OMX_IndexConfigCapturing, 935 &bOMX); 936 if ( OMX_ErrorNone != eError ) { 937 CAMHAL_LOGDB("Error during SetConfig- 0x%x", eError); 938 ret = -1; 939 goto EXIT; 940 } 941 } 942 CAMHAL_LOGDB("Capture set - 0x%x", eError); 943 944 mCaptureSignalled = true; //set this to true if we exited because of timeout 945 946 { 947 Mutex::Autolock lock(mFrameCountMutex); 948 mFrameCount = 0; 949 mFirstFrameCondition.broadcast(); 950 } 951 952 return (ret | ErrorUtils::omxToAndroidError(eError)); 953 954EXIT: 955 CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError); 956 //Release image buffers 957 if ( NULL != mReleaseImageBuffersCallback ) { 958 mReleaseImageBuffersCallback(mReleaseData); 959 } 960 961 { 962 Mutex::Autolock lock(mFrameCountMutex); 963 mFrameCount = 0; 964 mFirstFrameCondition.broadcast(); 965 } 966 967 performCleanupAfterError(); 968 LOG_FUNCTION_NAME_EXIT; 969 return (ret | ErrorUtils::omxToAndroidError(eError)); 970} 971 972status_t OMXCameraAdapter::disableImagePort(){ 973 status_t ret = NO_ERROR; 974 OMX_ERRORTYPE eError = OMX_ErrorNone; 975 OMXCameraPortParameters *imgCaptureData = NULL; 976 977 if (!mCaptureConfigured) { 978 return NO_ERROR; 979 } 980 981 mCaptureConfigured = false; 982 imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex]; 983 984 ///Register for Image port Disable event 985 ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp, 986 OMX_EventCmdComplete, 987 OMX_CommandPortDisable, 988 mCameraAdapterParameters.mImagePortIndex, 989 mStopCaptureSem); 990 ///Disable Capture Port 991 eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp, 992 OMX_CommandPortDisable, 993 mCameraAdapterParameters.mImagePortIndex, 994 NULL); 995 996 ///Free all the buffers on capture port 997 if (imgCaptureData) { 998 CAMHAL_LOGDB("Freeing buffer on Capture port - %d", imgCaptureData->mNumBufs); 999 for ( int index = 0 ; index < imgCaptureData->mNumBufs ; index++) { 1000 CAMHAL_LOGDB("Freeing buffer on Capture port - 0x%x", 1001 ( unsigned int ) imgCaptureData->mBufferHeader[index]->pBuffer); 1002 eError = OMX_FreeBuffer(mCameraAdapterParameters.mHandleComp, 1003 mCameraAdapterParameters.mImagePortIndex, 1004 (OMX_BUFFERHEADERTYPE*)imgCaptureData->mBufferHeader[index]); 1005 1006 GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError); 1007 } 1008 } 1009 CAMHAL_LOGDA("Waiting for port disable"); 1010 //Wait for the image port enable event 1011 ret = mStopCaptureSem.WaitTimeout(OMX_CMD_TIMEOUT); 1012 1013 //If somethiing bad happened while we wait 1014 if (mComponentState == OMX_StateInvalid) 1015 { 1016 CAMHAL_LOGEA("Invalid State after Disable Image Port Exitting!!!"); 1017 goto EXIT; 1018 } 1019 1020 if ( NO_ERROR == ret ) { 1021 CAMHAL_LOGDA("Port disabled"); 1022 } else { 1023 ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp, 1024 OMX_EventCmdComplete, 1025 OMX_CommandPortDisable, 1026 mCameraAdapterParameters.mImagePortIndex, 1027 NULL); 1028 CAMHAL_LOGDA("Timeout expired on port disable"); 1029 goto EXIT; 1030 } 1031 1032 EXIT: 1033 return (ret | ErrorUtils::omxToAndroidError(eError)); 1034} 1035 1036 1037status_t OMXCameraAdapter::UseBuffersCapture(void* bufArr, int num) 1038{ 1039 LOG_FUNCTION_NAME; 1040 1041 status_t ret = NO_ERROR; 1042 OMX_ERRORTYPE eError = OMX_ErrorNone; 1043 OMXCameraPortParameters * imgCaptureData = NULL; 1044 uint32_t *buffers = (uint32_t*)bufArr; 1045 OMXCameraPortParameters cap; 1046 1047 imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex]; 1048 1049 if ( 0 != mUseCaptureSem.Count() ) 1050 { 1051 CAMHAL_LOGEB("Error mUseCaptureSem semaphore count %d", mUseCaptureSem.Count()); 1052 return BAD_VALUE; 1053 } 1054 1055 // capture is already configured...we can skip this step 1056 if (mCaptureConfigured) { 1057 1058 if ( NO_ERROR == ret ) 1059 { 1060 ret = setupEXIF(); 1061 if ( NO_ERROR != ret ) 1062 { 1063 CAMHAL_LOGEB("Error configuring EXIF Buffer %x", ret); 1064 } 1065 } 1066 1067 mCapturedFrames = mBurstFrames; 1068 return NO_ERROR; 1069 } 1070 1071 imgCaptureData->mNumBufs = num; 1072 1073 //TODO: Support more pixelformats 1074 1075 CAMHAL_LOGDB("Params Width = %d", (int)imgCaptureData->mWidth); 1076 CAMHAL_LOGDB("Params Height = %d", (int)imgCaptureData->mWidth); 1077 1078 if (mPendingCaptureSettings & SetFormat) { 1079 mPendingCaptureSettings &= ~SetFormat; 1080 ret = setFormat(OMX_CAMERA_PORT_IMAGE_OUT_IMAGE, *imgCaptureData); 1081 if ( ret != NO_ERROR ) { 1082 CAMHAL_LOGEB("setFormat() failed %d", ret); 1083 LOG_FUNCTION_NAME_EXIT; 1084 return ret; 1085 } 1086 } 1087 1088 if (mPendingCaptureSettings & SetThumb) { 1089 mPendingCaptureSettings &= ~SetThumb; 1090 ret = setThumbnailParams(mThumbWidth, mThumbHeight, mThumbQuality); 1091 if ( NO_ERROR != ret) { 1092 CAMHAL_LOGEB("Error configuring thumbnail size %x", ret); 1093 return ret; 1094 } 1095 } 1096 1097 if (mPendingCaptureSettings & SetExpBracket) { 1098 mPendingCaptureSettings &= ~SetExpBracket; 1099 ret = setExposureBracketing( mExposureBracketingValues, 1100 mExposureBracketingValidEntries, mBurstFrames); 1101 if ( ret != NO_ERROR ) { 1102 CAMHAL_LOGEB("setExposureBracketing() failed %d", ret); 1103 goto EXIT; 1104 } 1105 } 1106 1107 if (mPendingCaptureSettings & SetQuality) { 1108 mPendingCaptureSettings &= ~SetQuality; 1109 ret = setImageQuality(mPictureQuality); 1110 if ( NO_ERROR != ret) { 1111 CAMHAL_LOGEB("Error configuring image quality %x", ret); 1112 goto EXIT; 1113 } 1114 } 1115 1116 ///Register for Image port ENABLE event 1117 ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp, 1118 OMX_EventCmdComplete, 1119 OMX_CommandPortEnable, 1120 mCameraAdapterParameters.mImagePortIndex, 1121 mUseCaptureSem); 1122 1123 ///Enable Capture Port 1124 eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp, 1125 OMX_CommandPortEnable, 1126 mCameraAdapterParameters.mImagePortIndex, 1127 NULL); 1128 1129 CAMHAL_LOGDB("OMX_UseBuffer = 0x%x", eError); 1130 GOTO_EXIT_IF(( eError != OMX_ErrorNone ), eError); 1131 1132 for ( int index = 0 ; index < imgCaptureData->mNumBufs ; index++ ) 1133 { 1134 OMX_BUFFERHEADERTYPE *pBufferHdr; 1135 CAMHAL_LOGDB("OMX_UseBuffer Capture address: 0x%x, size = %d", 1136 (unsigned int)buffers[index], 1137 (int)imgCaptureData->mBufSize); 1138 1139 eError = OMX_UseBuffer(mCameraAdapterParameters.mHandleComp, 1140 &pBufferHdr, 1141 mCameraAdapterParameters.mImagePortIndex, 1142 0, 1143 mCaptureBuffersLength, 1144 (OMX_U8*)buffers[index]); 1145 1146 CAMHAL_LOGDB("OMX_UseBuffer = 0x%x", eError); 1147 GOTO_EXIT_IF(( eError != OMX_ErrorNone ), eError); 1148 1149 pBufferHdr->pAppPrivate = (OMX_PTR) index; 1150 pBufferHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE); 1151 pBufferHdr->nVersion.s.nVersionMajor = 1 ; 1152 pBufferHdr->nVersion.s.nVersionMinor = 1 ; 1153 pBufferHdr->nVersion.s.nRevision = 0; 1154 pBufferHdr->nVersion.s.nStep = 0; 1155 imgCaptureData->mBufferHeader[index] = pBufferHdr; 1156 } 1157 1158 //Wait for the image port enable event 1159 CAMHAL_LOGDA("Waiting for port enable"); 1160 ret = mUseCaptureSem.WaitTimeout(OMX_CMD_TIMEOUT); 1161 1162 //If somethiing bad happened while we wait 1163 if (mComponentState == OMX_StateInvalid) 1164 { 1165 CAMHAL_LOGEA("Invalid State after Enable Image Port Exitting!!!"); 1166 goto EXIT; 1167 } 1168 1169 if ( ret == NO_ERROR ) 1170 { 1171 CAMHAL_LOGDA("Port enabled"); 1172 } 1173 else 1174 { 1175 ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp, 1176 OMX_EventCmdComplete, 1177 OMX_CommandPortEnable, 1178 mCameraAdapterParameters.mImagePortIndex, 1179 NULL); 1180 CAMHAL_LOGDA("Timeout expired on port enable"); 1181 goto EXIT; 1182 } 1183 1184 if ( NO_ERROR == ret ) 1185 { 1186 ret = setupEXIF(); 1187 if ( NO_ERROR != ret ) 1188 { 1189 CAMHAL_LOGEB("Error configuring EXIF Buffer %x", ret); 1190 } 1191 } 1192 1193 mCapturedFrames = mBurstFrames; 1194 mCaptureConfigured = true; 1195 1196 return (ret | ErrorUtils::omxToAndroidError(eError)); 1197 1198EXIT: 1199 CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError); 1200 //Release image buffers 1201 if ( NULL != mReleaseImageBuffersCallback ) { 1202 mReleaseImageBuffersCallback(mReleaseData); 1203 } 1204 performCleanupAfterError(); 1205 LOG_FUNCTION_NAME_EXIT; 1206 return (ret | ErrorUtils::omxToAndroidError(eError)); 1207 1208} 1209 1210}; 1211