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
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
getPictureBufferSize(size_t & length,size_t bufferCount)283 status_t OMXCameraAdapter::getPictureBufferSize(size_t &length, size_t bufferCount)
284 {
285 status_t ret = NO_ERROR;
286 OMXCameraPortParameters *imgCaptureData = NULL;
287 OMX_ERRORTYPE eError = OMX_ErrorNone;
288
289 LOG_FUNCTION_NAME;
290
291 if ( NO_ERROR == ret )
292 {
293 imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
294
295 imgCaptureData->mNumBufs = bufferCount;
296
297 // check if image port is already configured...
298 // if it already configured then we don't have to query again
299 if (!mCaptureConfigured) {
300 ret = setFormat(OMX_CAMERA_PORT_IMAGE_OUT_IMAGE, *imgCaptureData);
301 }
302
303 if ( ret == NO_ERROR )
304 {
305 length = imgCaptureData->mBufSize;
306 }
307 else
308 {
309 CAMHAL_LOGEB("setFormat() failed 0x%x", ret);
310 length = 0;
311 }
312 }
313
314 CAMHAL_LOGDB("getPictureBufferSize %d", length);
315
316 LOG_FUNCTION_NAME_EXIT;
317
318 return ret;
319 }
320
parseExpRange(const char * rangeStr,int * expRange,size_t count,size_t & validEntries)321 status_t OMXCameraAdapter::parseExpRange(const char *rangeStr,
322 int * expRange,
323 size_t count,
324 size_t &validEntries)
325 {
326 status_t ret = NO_ERROR;
327 char *ctx, *expVal;
328 char *tmp = NULL;
329 size_t i = 0;
330
331 LOG_FUNCTION_NAME;
332
333 if ( NULL == rangeStr )
334 {
335 return -EINVAL;
336 }
337
338 if ( NULL == expRange )
339 {
340 return -EINVAL;
341 }
342
343 if ( NO_ERROR == ret )
344 {
345 tmp = ( char * ) malloc( strlen(rangeStr) + 1 );
346
347 if ( NULL == tmp )
348 {
349 CAMHAL_LOGEA("No resources for temporary buffer");
350 return -1;
351 }
352 memset(tmp, '\0', strlen(rangeStr) + 1);
353
354 }
355
356 if ( NO_ERROR == ret )
357 {
358 strncpy(tmp, rangeStr, strlen(rangeStr) );
359 expVal = strtok_r( (char *) tmp, CameraHal::PARAMS_DELIMITER, &ctx);
360
361 i = 0;
362 while ( ( NULL != expVal ) && ( i < count ) )
363 {
364 expRange[i] = atoi(expVal);
365 expVal = strtok_r(NULL, CameraHal::PARAMS_DELIMITER, &ctx);
366 i++;
367 }
368 validEntries = i;
369 }
370
371 if ( NULL != tmp )
372 {
373 free(tmp);
374 }
375
376 LOG_FUNCTION_NAME_EXIT;
377
378 return ret;
379 }
380
setExposureBracketing(int * evValues,size_t evCount,size_t frameCount)381 status_t OMXCameraAdapter::setExposureBracketing(int *evValues,
382 size_t evCount,
383 size_t frameCount)
384 {
385 status_t ret = NO_ERROR;
386 OMX_ERRORTYPE eError = OMX_ErrorNone;
387 OMX_CONFIG_CAPTUREMODETYPE expCapMode;
388 OMX_CONFIG_EXTCAPTUREMODETYPE extExpCapMode;
389
390 LOG_FUNCTION_NAME;
391
392 if ( OMX_StateInvalid == mComponentState )
393 {
394 CAMHAL_LOGEA("OMX component is in invalid state");
395 ret = -EINVAL;
396 }
397
398 if ( NULL == evValues )
399 {
400 CAMHAL_LOGEA("Exposure compensation values pointer is invalid");
401 ret = -EINVAL;
402 }
403
404 if ( NO_ERROR == ret )
405 {
406 OMX_INIT_STRUCT_PTR (&expCapMode, OMX_CONFIG_CAPTUREMODETYPE);
407 expCapMode.nPortIndex = mCameraAdapterParameters.mImagePortIndex;
408
409 /// If frameCount>0 but evCount<=0, then this is the case of HQ burst.
410 //Otherwise, it is normal HQ capture
411 ///If frameCount>0 and evCount>0 then this is the cause of HQ Exposure bracketing.
412 if ( 0 == evCount && 0 == frameCount )
413 {
414 expCapMode.bFrameLimited = OMX_FALSE;
415 }
416 else
417 {
418 expCapMode.bFrameLimited = OMX_TRUE;
419 expCapMode.nFrameLimit = frameCount;
420 }
421
422 eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
423 OMX_IndexConfigCaptureMode,
424 &expCapMode);
425 if ( OMX_ErrorNone != eError )
426 {
427 CAMHAL_LOGEB("Error while configuring capture mode 0x%x", eError);
428 }
429 else
430 {
431 CAMHAL_LOGDA("Camera capture mode configured successfully");
432 }
433 }
434
435 if ( NO_ERROR == ret )
436 {
437 OMX_INIT_STRUCT_PTR (&extExpCapMode, OMX_CONFIG_EXTCAPTUREMODETYPE);
438 extExpCapMode.nPortIndex = mCameraAdapterParameters.mImagePortIndex;
439
440 if ( 0 == evCount )
441 {
442 extExpCapMode.bEnableBracketing = OMX_FALSE;
443 }
444 else
445 {
446 extExpCapMode.bEnableBracketing = OMX_TRUE;
447 extExpCapMode.tBracketConfigType.eBracketMode = OMX_BracketExposureRelativeInEV;
448 extExpCapMode.tBracketConfigType.nNbrBracketingValues = evCount - 1;
449 }
450
451 for ( unsigned int i = 0 ; i < evCount ; i++ )
452 {
453 extExpCapMode.tBracketConfigType.nBracketValues[i] = ( evValues[i] * ( 1 << Q16_OFFSET ) ) / 10;
454 }
455
456 eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
457 ( OMX_INDEXTYPE ) OMX_IndexConfigExtCaptureMode,
458 &extExpCapMode);
459 if ( OMX_ErrorNone != eError )
460 {
461 CAMHAL_LOGEB("Error while configuring extended capture mode 0x%x", eError);
462 }
463 else
464 {
465 CAMHAL_LOGDA("Extended camera capture mode configured successfully");
466 }
467 }
468
469 LOG_FUNCTION_NAME_EXIT;
470
471 return ret;
472 }
473
setShutterCallback(bool enabled)474 status_t OMXCameraAdapter::setShutterCallback(bool enabled)
475 {
476 status_t ret = NO_ERROR;
477 OMX_ERRORTYPE eError = OMX_ErrorNone;
478 OMX_CONFIG_CALLBACKREQUESTTYPE shutterRequstCallback;
479
480 LOG_FUNCTION_NAME;
481
482 if ( OMX_StateExecuting != mComponentState )
483 {
484 CAMHAL_LOGEA("OMX component not in executing state");
485 ret = -1;
486 }
487
488 if ( NO_ERROR == ret )
489 {
490
491 OMX_INIT_STRUCT_PTR (&shutterRequstCallback, OMX_CONFIG_CALLBACKREQUESTTYPE);
492 shutterRequstCallback.nPortIndex = OMX_ALL;
493
494 if ( enabled )
495 {
496 shutterRequstCallback.bEnable = OMX_TRUE;
497 shutterRequstCallback.nIndex = ( OMX_INDEXTYPE ) OMX_TI_IndexConfigShutterCallback;
498 CAMHAL_LOGDA("Enabling shutter callback");
499 }
500 else
501 {
502 shutterRequstCallback.bEnable = OMX_FALSE;
503 shutterRequstCallback.nIndex = ( OMX_INDEXTYPE ) OMX_TI_IndexConfigShutterCallback;
504 CAMHAL_LOGDA("Disabling shutter callback");
505 }
506
507 eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
508 ( OMX_INDEXTYPE ) OMX_IndexConfigCallbackRequest,
509 &shutterRequstCallback);
510 if ( OMX_ErrorNone != eError )
511 {
512 CAMHAL_LOGEB("Error registering shutter callback 0x%x", eError);
513 ret = -1;
514 }
515 else
516 {
517 CAMHAL_LOGDB("Shutter callback for index 0x%x registered successfully",
518 OMX_TI_IndexConfigShutterCallback);
519 }
520 }
521
522 LOG_FUNCTION_NAME_EXIT;
523
524 return ret;
525 }
526
doBracketing(OMX_BUFFERHEADERTYPE * pBuffHeader,CameraFrame::FrameType typeOfFrame)527 status_t OMXCameraAdapter::doBracketing(OMX_BUFFERHEADERTYPE *pBuffHeader,
528 CameraFrame::FrameType typeOfFrame)
529 {
530 status_t ret = NO_ERROR;
531 int currentBufferIdx, nextBufferIdx;
532 OMXCameraPortParameters * imgCaptureData = NULL;
533
534 LOG_FUNCTION_NAME;
535
536 imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
537
538 if ( OMX_StateExecuting != mComponentState )
539 {
540 CAMHAL_LOGEA("OMX component is not in executing state");
541 ret = -EINVAL;
542 }
543
544 if ( NO_ERROR == ret )
545 {
546 currentBufferIdx = ( unsigned int ) pBuffHeader->pAppPrivate;
547
548 if ( currentBufferIdx >= imgCaptureData->mNumBufs)
549 {
550 CAMHAL_LOGEB("Invalid bracketing buffer index 0x%x", currentBufferIdx);
551 ret = -EINVAL;
552 }
553 }
554
555 if ( NO_ERROR == ret )
556 {
557 mBracketingBuffersQueued[currentBufferIdx] = false;
558 mBracketingBuffersQueuedCount--;
559
560 if ( 0 >= mBracketingBuffersQueuedCount )
561 {
562 nextBufferIdx = ( currentBufferIdx + 1 ) % imgCaptureData->mNumBufs;
563 mBracketingBuffersQueued[nextBufferIdx] = true;
564 mBracketingBuffersQueuedCount++;
565 mLastBracetingBufferIdx = nextBufferIdx;
566 setFrameRefCount(imgCaptureData->mBufferHeader[nextBufferIdx]->pBuffer, typeOfFrame, 1);
567 returnFrame(imgCaptureData->mBufferHeader[nextBufferIdx]->pBuffer, typeOfFrame);
568 }
569 }
570
571 LOG_FUNCTION_NAME_EXIT;
572
573 return ret;
574 }
575
sendBracketFrames()576 status_t OMXCameraAdapter::sendBracketFrames()
577 {
578 status_t ret = NO_ERROR;
579 int currentBufferIdx;
580 OMXCameraPortParameters * imgCaptureData = NULL;
581
582 LOG_FUNCTION_NAME;
583
584 imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
585
586 if ( OMX_StateExecuting != mComponentState )
587 {
588 CAMHAL_LOGEA("OMX component is not in executing state");
589 ret = -EINVAL;
590 }
591
592 if ( NO_ERROR == ret )
593 {
594
595 currentBufferIdx = mLastBracetingBufferIdx;
596 do
597 {
598 currentBufferIdx++;
599 currentBufferIdx %= imgCaptureData->mNumBufs;
600 if (!mBracketingBuffersQueued[currentBufferIdx] )
601 {
602 CameraFrame cameraFrame;
603 sendCallBacks(cameraFrame,
604 imgCaptureData->mBufferHeader[currentBufferIdx],
605 imgCaptureData->mImageType,
606 imgCaptureData);
607 }
608 } while ( currentBufferIdx != mLastBracetingBufferIdx );
609
610 }
611
612 LOG_FUNCTION_NAME_EXIT;
613
614 return ret;
615 }
616
startBracketing(int range)617 status_t OMXCameraAdapter::startBracketing(int range)
618 {
619 status_t ret = NO_ERROR;
620 OMXCameraPortParameters * imgCaptureData = NULL;
621
622 LOG_FUNCTION_NAME;
623
624 imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
625
626 if ( OMX_StateExecuting != mComponentState )
627 {
628 CAMHAL_LOGEA("OMX component is not in executing state");
629 ret = -EINVAL;
630 }
631
632 {
633 Mutex::Autolock lock(mBracketingLock);
634
635 if ( mBracketingEnabled )
636 {
637 return ret;
638 }
639 }
640
641 if ( 0 == imgCaptureData->mNumBufs )
642 {
643 CAMHAL_LOGEB("Image capture buffers set to %d", imgCaptureData->mNumBufs);
644 ret = -EINVAL;
645 }
646
647 if ( mPending3Asettings )
648 apply3Asettings(mParameters3A);
649
650 if ( NO_ERROR == ret )
651 {
652 Mutex::Autolock lock(mBracketingLock);
653
654 mBracketingRange = range;
655 mBracketingBuffersQueued = new bool[imgCaptureData->mNumBufs];
656 if ( NULL == mBracketingBuffersQueued )
657 {
658 CAMHAL_LOGEA("Unable to allocate bracketing management structures");
659 ret = -1;
660 }
661
662 if ( NO_ERROR == ret )
663 {
664 mBracketingBuffersQueuedCount = imgCaptureData->mNumBufs;
665 mLastBracetingBufferIdx = mBracketingBuffersQueuedCount - 1;
666
667 for ( int i = 0 ; i < imgCaptureData->mNumBufs ; i++ )
668 {
669 mBracketingBuffersQueued[i] = true;
670 }
671
672 }
673 }
674
675 if ( NO_ERROR == ret )
676 {
677
678 ret = startImageCapture();
679 {
680 Mutex::Autolock lock(mBracketingLock);
681
682 if ( NO_ERROR == ret )
683 {
684 mBracketingEnabled = true;
685 }
686 else
687 {
688 mBracketingEnabled = false;
689 }
690 }
691 }
692
693 LOG_FUNCTION_NAME_EXIT;
694
695 return ret;
696 }
697
stopBracketing()698 status_t OMXCameraAdapter::stopBracketing()
699 {
700 status_t ret = NO_ERROR;
701
702 LOG_FUNCTION_NAME;
703
704 Mutex::Autolock lock(mBracketingLock);
705
706 if ( NULL != mBracketingBuffersQueued )
707 {
708 delete [] mBracketingBuffersQueued;
709 }
710
711 ret = stopImageCapture();
712
713 mBracketingBuffersQueued = NULL;
714 mBracketingEnabled = false;
715 mBracketingBuffersQueuedCount = 0;
716 mLastBracetingBufferIdx = 0;
717
718 LOG_FUNCTION_NAME_EXIT;
719
720 return ret;
721 }
722
startImageCapture()723 status_t OMXCameraAdapter::startImageCapture()
724 {
725 status_t ret = NO_ERROR;
726 OMX_ERRORTYPE eError = OMX_ErrorNone;
727 OMXCameraPortParameters * capData = NULL;
728 OMX_CONFIG_BOOLEANTYPE bOMX;
729
730 LOG_FUNCTION_NAME;
731
732 if(!mCaptureConfigured)
733 {
734 ///Image capture was cancelled before we could start
735 return NO_ERROR;
736 }
737
738 if ( 0 != mStartCaptureSem.Count() )
739 {
740 CAMHAL_LOGEB("Error mStartCaptureSem semaphore count %d", mStartCaptureSem.Count());
741 return NO_INIT;
742 }
743
744 // 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
862 EXIT:
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
stopImageCapture()871 status_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 ret = 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 if ( NO_ERROR != ret ) {
928 ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp,
929 (OMX_EVENTTYPE) OMX_EventIndexSettingChanged,
930 OMX_ALL,
931 OMX_TI_IndexConfigShutterCallback,
932 NULL);
933 CAMHAL_LOGEA("Timeout expired on capture sem");
934 goto EXIT;
935 }
936
937 // Disable image capture
938 // Capturing command is not needed when capturing in video mode
939 if (mCapMode != VIDEO_MODE) {
940 OMX_INIT_STRUCT_PTR (&bOMX, OMX_CONFIG_BOOLEANTYPE);
941 bOMX.bEnabled = OMX_FALSE;
942 imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
943 eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
944 OMX_IndexConfigCapturing,
945 &bOMX);
946 if ( OMX_ErrorNone != eError ) {
947 CAMHAL_LOGDB("Error during SetConfig- 0x%x", eError);
948 ret = -1;
949 goto EXIT;
950 }
951 }
952 CAMHAL_LOGDB("Capture set - 0x%x", eError);
953
954 mCaptureSignalled = true; //set this to true if we exited because of timeout
955
956 {
957 Mutex::Autolock lock(mFrameCountMutex);
958 mFrameCount = 0;
959 mFirstFrameCondition.broadcast();
960 }
961
962 return (ret | ErrorUtils::omxToAndroidError(eError));
963
964 EXIT:
965 CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
966 //Release image buffers
967 if ( NULL != mReleaseImageBuffersCallback ) {
968 mReleaseImageBuffersCallback(mReleaseData);
969 }
970
971 {
972 Mutex::Autolock lock(mFrameCountMutex);
973 mFrameCount = 0;
974 mFirstFrameCondition.broadcast();
975 }
976
977 performCleanupAfterError();
978 LOG_FUNCTION_NAME_EXIT;
979 return (ret | ErrorUtils::omxToAndroidError(eError));
980 }
981
disableImagePort()982 status_t OMXCameraAdapter::disableImagePort(){
983 status_t ret = NO_ERROR;
984 OMX_ERRORTYPE eError = OMX_ErrorNone;
985 OMXCameraPortParameters *imgCaptureData = NULL;
986
987 if (!mCaptureConfigured) {
988 return NO_ERROR;
989 }
990
991 mCaptureConfigured = false;
992 imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
993
994 ///Register for Image port Disable event
995 ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
996 OMX_EventCmdComplete,
997 OMX_CommandPortDisable,
998 mCameraAdapterParameters.mImagePortIndex,
999 mStopCaptureSem);
1000 ///Disable Capture Port
1001 eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp,
1002 OMX_CommandPortDisable,
1003 mCameraAdapterParameters.mImagePortIndex,
1004 NULL);
1005
1006 ///Free all the buffers on capture port
1007 if (imgCaptureData) {
1008 CAMHAL_LOGDB("Freeing buffer on Capture port - %d", imgCaptureData->mNumBufs);
1009 for ( int index = 0 ; index < imgCaptureData->mNumBufs ; index++) {
1010 CAMHAL_LOGDB("Freeing buffer on Capture port - 0x%x",
1011 ( unsigned int ) imgCaptureData->mBufferHeader[index]->pBuffer);
1012 eError = OMX_FreeBuffer(mCameraAdapterParameters.mHandleComp,
1013 mCameraAdapterParameters.mImagePortIndex,
1014 (OMX_BUFFERHEADERTYPE*)imgCaptureData->mBufferHeader[index]);
1015
1016 GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
1017 }
1018 }
1019 CAMHAL_LOGDA("Waiting for port disable");
1020 //Wait for the image port enable event
1021 ret = mStopCaptureSem.WaitTimeout(OMX_CMD_TIMEOUT);
1022
1023 //If somethiing bad happened while we wait
1024 if (mComponentState == OMX_StateInvalid)
1025 {
1026 CAMHAL_LOGEA("Invalid State after Disable Image Port Exitting!!!");
1027 goto EXIT;
1028 }
1029
1030 if ( NO_ERROR == ret ) {
1031 CAMHAL_LOGDA("Port disabled");
1032 } else {
1033 ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp,
1034 OMX_EventCmdComplete,
1035 OMX_CommandPortDisable,
1036 mCameraAdapterParameters.mImagePortIndex,
1037 NULL);
1038 CAMHAL_LOGDA("Timeout expired on port disable");
1039 goto EXIT;
1040 }
1041
1042 EXIT:
1043 return (ret | ErrorUtils::omxToAndroidError(eError));
1044 }
1045
1046
UseBuffersCapture(void * bufArr,int num)1047 status_t OMXCameraAdapter::UseBuffersCapture(void* bufArr, int num)
1048 {
1049 LOG_FUNCTION_NAME;
1050
1051 status_t ret = NO_ERROR;
1052 OMX_ERRORTYPE eError = OMX_ErrorNone;
1053 OMXCameraPortParameters * imgCaptureData = NULL;
1054 uint32_t *buffers = (uint32_t*)bufArr;
1055 OMXCameraPortParameters cap;
1056
1057 imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
1058
1059 if ( 0 != mUseCaptureSem.Count() )
1060 {
1061 CAMHAL_LOGEB("Error mUseCaptureSem semaphore count %d", mUseCaptureSem.Count());
1062 return BAD_VALUE;
1063 }
1064
1065 // capture is already configured...we can skip this step
1066 if (mCaptureConfigured) {
1067
1068 if ( NO_ERROR == ret )
1069 {
1070 ret = setupEXIF();
1071 if ( NO_ERROR != ret )
1072 {
1073 CAMHAL_LOGEB("Error configuring EXIF Buffer %x", ret);
1074 }
1075 }
1076
1077 mCapturedFrames = mBurstFrames;
1078 return NO_ERROR;
1079 }
1080
1081 imgCaptureData->mNumBufs = num;
1082
1083 //TODO: Support more pixelformats
1084
1085 CAMHAL_LOGDB("Params Width = %d", (int)imgCaptureData->mWidth);
1086 CAMHAL_LOGDB("Params Height = %d", (int)imgCaptureData->mWidth);
1087
1088 if (mPendingCaptureSettings & SetFormat) {
1089 mPendingCaptureSettings &= ~SetFormat;
1090 ret = setFormat(OMX_CAMERA_PORT_IMAGE_OUT_IMAGE, *imgCaptureData);
1091 if ( ret != NO_ERROR ) {
1092 CAMHAL_LOGEB("setFormat() failed %d", ret);
1093 LOG_FUNCTION_NAME_EXIT;
1094 return ret;
1095 }
1096 }
1097
1098 if (mPendingCaptureSettings & SetThumb) {
1099 mPendingCaptureSettings &= ~SetThumb;
1100 ret = setThumbnailParams(mThumbWidth, mThumbHeight, mThumbQuality);
1101 if ( NO_ERROR != ret) {
1102 CAMHAL_LOGEB("Error configuring thumbnail size %x", ret);
1103 return ret;
1104 }
1105 }
1106
1107 if (mPendingCaptureSettings & SetExpBracket) {
1108 mPendingCaptureSettings &= ~SetExpBracket;
1109 ret = setExposureBracketing( mExposureBracketingValues,
1110 mExposureBracketingValidEntries, mBurstFrames);
1111 if ( ret != NO_ERROR ) {
1112 CAMHAL_LOGEB("setExposureBracketing() failed %d", ret);
1113 goto EXIT;
1114 }
1115 }
1116
1117 if (mPendingCaptureSettings & SetQuality) {
1118 mPendingCaptureSettings &= ~SetQuality;
1119 ret = setImageQuality(mPictureQuality);
1120 if ( NO_ERROR != ret) {
1121 CAMHAL_LOGEB("Error configuring image quality %x", ret);
1122 goto EXIT;
1123 }
1124 }
1125
1126 ///Register for Image port ENABLE event
1127 ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
1128 OMX_EventCmdComplete,
1129 OMX_CommandPortEnable,
1130 mCameraAdapterParameters.mImagePortIndex,
1131 mUseCaptureSem);
1132
1133 ///Enable Capture Port
1134 eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp,
1135 OMX_CommandPortEnable,
1136 mCameraAdapterParameters.mImagePortIndex,
1137 NULL);
1138
1139 CAMHAL_LOGDB("OMX_UseBuffer = 0x%x", eError);
1140 GOTO_EXIT_IF(( eError != OMX_ErrorNone ), eError);
1141
1142 for ( int index = 0 ; index < imgCaptureData->mNumBufs ; index++ )
1143 {
1144 OMX_BUFFERHEADERTYPE *pBufferHdr;
1145 CAMHAL_LOGDB("OMX_UseBuffer Capture address: 0x%x, size = %d",
1146 (unsigned int)buffers[index],
1147 (int)imgCaptureData->mBufSize);
1148
1149 eError = OMX_UseBuffer(mCameraAdapterParameters.mHandleComp,
1150 &pBufferHdr,
1151 mCameraAdapterParameters.mImagePortIndex,
1152 0,
1153 mCaptureBuffersLength,
1154 (OMX_U8*)buffers[index]);
1155
1156 CAMHAL_LOGDB("OMX_UseBuffer = 0x%x", eError);
1157 GOTO_EXIT_IF(( eError != OMX_ErrorNone ), eError);
1158
1159 pBufferHdr->pAppPrivate = (OMX_PTR) index;
1160 pBufferHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
1161 pBufferHdr->nVersion.s.nVersionMajor = 1 ;
1162 pBufferHdr->nVersion.s.nVersionMinor = 1 ;
1163 pBufferHdr->nVersion.s.nRevision = 0;
1164 pBufferHdr->nVersion.s.nStep = 0;
1165 imgCaptureData->mBufferHeader[index] = pBufferHdr;
1166 }
1167
1168 //Wait for the image port enable event
1169 CAMHAL_LOGDA("Waiting for port enable");
1170 ret = mUseCaptureSem.WaitTimeout(OMX_CMD_TIMEOUT);
1171
1172 //If somethiing bad happened while we wait
1173 if (mComponentState == OMX_StateInvalid)
1174 {
1175 CAMHAL_LOGEA("Invalid State after Enable Image Port Exitting!!!");
1176 goto EXIT;
1177 }
1178
1179 if ( ret == NO_ERROR )
1180 {
1181 CAMHAL_LOGDA("Port enabled");
1182 }
1183 else
1184 {
1185 ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp,
1186 OMX_EventCmdComplete,
1187 OMX_CommandPortEnable,
1188 mCameraAdapterParameters.mImagePortIndex,
1189 NULL);
1190 CAMHAL_LOGDA("Timeout expired on port enable");
1191 goto EXIT;
1192 }
1193
1194 if ( NO_ERROR == ret )
1195 {
1196 ret = setupEXIF();
1197 if ( NO_ERROR != ret )
1198 {
1199 CAMHAL_LOGEB("Error configuring EXIF Buffer %x", ret);
1200 }
1201 }
1202
1203 mCapturedFrames = mBurstFrames;
1204 mCaptureConfigured = true;
1205
1206 return (ret | ErrorUtils::omxToAndroidError(eError));
1207
1208 EXIT:
1209 CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
1210 //Release image buffers
1211 if ( NULL != mReleaseImageBuffersCallback ) {
1212 mReleaseImageBuffersCallback(mReleaseData);
1213 }
1214 performCleanupAfterError();
1215 LOG_FUNCTION_NAME_EXIT;
1216 return (ret | ErrorUtils::omxToAndroidError(eError));
1217
1218 }
1219
1220 };
1221