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
setParametersCapture(const CameraParameters & params,BaseCameraAdapter::AdapterState state)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
getPictureBufferSize(size_t & length,size_t bufferCount)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
parseExpRange(const char * rangeStr,int * expRange,size_t count,size_t & validEntries)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
setExposureBracketing(int * evValues,size_t evCount,size_t frameCount)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
setShutterCallback(bool enabled)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
doBracketing(OMX_BUFFERHEADERTYPE * pBuffHeader,CameraFrame::FrameType typeOfFrame)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
sendBracketFrames()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
startBracketing(int range)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
stopBracketing()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
startImageCapture()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
stopImageCapture()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
disableImagePort()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
UseBuffersCapture(void * bufArr,int num)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