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 &params,
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
278status_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
316status_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
376status_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
469status_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
522status_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
571status_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
612status_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
693status_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
718status_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
868EXIT:
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
878status_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
969EXIT:
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
987status_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
1052status_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
1213EXIT:
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