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