OMXCapture.cpp revision 7ce015866d4be66a147e9cacbe70a376dd1e6360
1/*
2 * Copyright (C) Texas Instruments - http://www.ti.com/
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/**
18* @file OMXCapture.cpp
19*
20* This file contains functionality for handling image capture.
21*
22*/
23
24#undef LOG_TAG
25
26#define LOG_TAG "CameraHAL"
27
28#include "CameraHal.h"
29#include "OMXCameraAdapter.h"
30#include "ErrorUtils.h"
31
32
33namespace android {
34
35status_t OMXCameraAdapter::setParametersCapture(const CameraParameters &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
44    LOG_FUNCTION_NAME;
45
46    OMXCameraPortParameters *cap;
47    cap = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
48
49    params.getPictureSize(&w, &h);
50
51    if ( ( w != ( int ) cap->mWidth ) ||
52          ( h != ( int ) cap->mHeight ) )
53        {
54        mPendingCaptureSettings |= SetFormat;
55        }
56
57    cap->mWidth = w;
58    cap->mHeight = h;
59    //TODO: Support more pixelformats
60    //cap->mStride = 2;
61
62    CAMHAL_LOGVB("Image: cap.mWidth = %d", (int)cap->mWidth);
63    CAMHAL_LOGVB("Image: cap.mHeight = %d", (int)cap->mHeight);
64
65    if ( (valstr = params.getPictureFormat()) != NULL )
66        {
67        if (strcmp(valstr, (const char *) CameraParameters::PIXEL_FORMAT_YUV422I) == 0)
68            {
69            CAMHAL_LOGDA("CbYCrY format selected");
70            pixFormat = OMX_COLOR_FormatCbYCrY;
71            }
72        else if(strcmp(valstr, (const char *) CameraParameters::PIXEL_FORMAT_YUV420SP) == 0)
73            {
74            CAMHAL_LOGDA("YUV420SP format selected");
75            pixFormat = OMX_COLOR_FormatYUV420SemiPlanar;
76            }
77        else if(strcmp(valstr, (const char *) CameraParameters::PIXEL_FORMAT_RGB565) == 0)
78            {
79            CAMHAL_LOGDA("RGB565 format selected");
80            pixFormat = OMX_COLOR_Format16bitRGB565;
81            }
82        else if(strcmp(valstr, (const char *) CameraParameters::PIXEL_FORMAT_JPEG) == 0)
83            {
84            CAMHAL_LOGDA("JPEG format selected");
85            pixFormat = OMX_COLOR_FormatUnused;
86            mCodingMode = CodingNone;
87            }
88        else if(strcmp(valstr, (const char *) TICameraParameters::PIXEL_FORMAT_JPS) == 0)
89            {
90            CAMHAL_LOGDA("JPS format selected");
91            pixFormat = OMX_COLOR_FormatUnused;
92            mCodingMode = CodingJPS;
93            }
94        else if(strcmp(valstr, (const char *) TICameraParameters::PIXEL_FORMAT_MPO) == 0)
95            {
96            CAMHAL_LOGDA("MPO format selected");
97            pixFormat = OMX_COLOR_FormatUnused;
98            mCodingMode = CodingMPO;
99            }
100        else if(strcmp(valstr, (const char *) TICameraParameters::PIXEL_FORMAT_RAW_JPEG) == 0)
101            {
102            CAMHAL_LOGDA("RAW + JPEG format selected");
103            pixFormat = OMX_COLOR_FormatUnused;
104            mCodingMode = CodingRAWJPEG;
105            }
106        else if(strcmp(valstr, (const char *) TICameraParameters::PIXEL_FORMAT_RAW_MPO) == 0)
107            {
108            CAMHAL_LOGDA("RAW + MPO format selected");
109            pixFormat = OMX_COLOR_FormatUnused;
110            mCodingMode = CodingRAWMPO;
111            }
112        else if(strcmp(valstr, (const char *) TICameraParameters::PIXEL_FORMAT_RAW) == 0)
113            {
114            CAMHAL_LOGDA("RAW Picture format selected");
115            pixFormat = OMX_COLOR_FormatRawBayer10bit;
116            }
117        else
118            {
119            CAMHAL_LOGEA("Invalid format, JPEG format selected as default");
120            pixFormat = OMX_COLOR_FormatUnused;
121            }
122        }
123    else
124        {
125        CAMHAL_LOGEA("Picture format is NULL, defaulting to JPEG");
126        pixFormat = OMX_COLOR_FormatUnused;
127        }
128
129    // JPEG capture is not supported in video mode by OMX Camera
130    // Set capture format to yuv422i...jpeg encode will
131    // be done on A9
132    valstr = params.get(TICameraParameters::KEY_CAP_MODE);
133    if ( (valstr && !strcmp(valstr, (const char *) TICameraParameters::VIDEO_MODE)) &&
134         (pixFormat == OMX_COLOR_FormatUnused) ) {
135        CAMHAL_LOGDA("Capturing in video mode...selecting yuv422i");
136        pixFormat = OMX_COLOR_FormatCbYCrY;
137    }
138
139    if ( pixFormat != cap->mColorFormat )
140        {
141        mPendingCaptureSettings |= SetFormat;
142        cap->mColorFormat = pixFormat;
143        }
144
145    str = params.get(TICameraParameters::KEY_EXP_BRACKETING_RANGE);
146    if ( NULL != str ) {
147        parseExpRange(str, mExposureBracketingValues, EXP_BRACKET_RANGE, mExposureBracketingValidEntries);
148    } else {
149        // if bracketing was previously set...we set again before capturing to clear
150        if (mExposureBracketingValidEntries) mPendingCaptureSettings |= SetExpBracket;
151        mExposureBracketingValidEntries = 0;
152    }
153
154    if ( params.getInt(CameraParameters::KEY_ROTATION) != -1 )
155        {
156        if (params.getInt(CameraParameters::KEY_ROTATION) != mPictureRotation) {
157            mPendingCaptureSettings |= SetRotation;
158        }
159        mPictureRotation = params.getInt(CameraParameters::KEY_ROTATION);
160        }
161    else
162        {
163        if (mPictureRotation) mPendingCaptureSettings |= SetRotation;
164        mPictureRotation = 0;
165        }
166
167    CAMHAL_LOGVB("Picture Rotation set %d", mPictureRotation);
168
169    // Read Sensor Orientation and set it based on perating mode
170
171     if (( params.getInt(TICameraParameters::KEY_SENSOR_ORIENTATION) != -1 ) && (mCapMode == OMXCameraAdapter::VIDEO_MODE))
172        {
173         mSensorOrientation = params.getInt(TICameraParameters::KEY_SENSOR_ORIENTATION);
174         if (mSensorOrientation == 270 ||mSensorOrientation==90)
175             {
176             CAMHAL_LOGEA(" Orientation is 270/90. So setting counter rotation  to Ducati");
177             mSensorOrientation +=180;
178             mSensorOrientation%=360;
179              }
180         }
181     else
182        {
183         mSensorOrientation = 0;
184        }
185
186     CAMHAL_LOGVB("Sensor Orientation  set : %d", mSensorOrientation);
187
188    if ( params.getInt(TICameraParameters::KEY_BURST)  >= 1 )
189        {
190        if (params.getInt(TICameraParameters::KEY_BURST) != mBurstFrames) {
191            mPendingCaptureSettings |= SetExpBracket;
192        }
193        mBurstFrames = params.getInt(TICameraParameters::KEY_BURST);
194        }
195    else
196        {
197        if (mBurstFrames != 1) mPendingCaptureSettings |= SetExpBracket;
198        mBurstFrames = 1;
199        }
200
201    CAMHAL_LOGVB("Burst Frames set %d", mBurstFrames);
202
203    if ( ( params.getInt(CameraParameters::KEY_JPEG_QUALITY)  >= MIN_JPEG_QUALITY ) &&
204         ( params.getInt(CameraParameters::KEY_JPEG_QUALITY)  <= MAX_JPEG_QUALITY ) )
205        {
206        if (params.getInt(CameraParameters::KEY_JPEG_QUALITY) != mPictureQuality) {
207            mPendingCaptureSettings |= SetQuality;
208        }
209        mPictureQuality = params.getInt(CameraParameters::KEY_JPEG_QUALITY);
210        }
211    else
212        {
213        if (mPictureQuality != MAX_JPEG_QUALITY) mPendingCaptureSettings |= SetQuality;
214        mPictureQuality = MAX_JPEG_QUALITY;
215        }
216
217    CAMHAL_LOGVB("Picture Quality set %d", mPictureQuality);
218
219    if ( params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH)  >= 0 )
220        {
221        if (params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH) != mThumbWidth) {
222            mPendingCaptureSettings |= SetThumb;
223        }
224        mThumbWidth = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH);
225        }
226    else
227        {
228        if (mThumbWidth != DEFAULT_THUMB_WIDTH) mPendingCaptureSettings |= SetThumb;
229        mThumbWidth = DEFAULT_THUMB_WIDTH;
230        }
231
232
233    CAMHAL_LOGVB("Picture Thumb width set %d", mThumbWidth);
234
235    if ( params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT)  >= 0 )
236        {
237        if (params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT) != mThumbHeight) {
238            mPendingCaptureSettings |= SetThumb;
239        }
240        mThumbHeight = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT);
241        }
242    else
243        {
244        if (mThumbHeight != DEFAULT_THUMB_HEIGHT) mPendingCaptureSettings |= SetThumb;
245        mThumbHeight = DEFAULT_THUMB_HEIGHT;
246        }
247
248
249    CAMHAL_LOGVB("Picture Thumb height set %d", mThumbHeight);
250
251    if ( ( params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY)  >= MIN_JPEG_QUALITY ) &&
252         ( params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY)  <= MAX_JPEG_QUALITY ) )
253        {
254        if (params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY) != mThumbQuality) {
255            mPendingCaptureSettings |= SetThumb;
256        }
257        mThumbQuality = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
258        }
259    else
260        {
261        if (mThumbQuality != MAX_JPEG_QUALITY) mPendingCaptureSettings |= SetThumb;
262        mThumbQuality = MAX_JPEG_QUALITY;
263        }
264
265    CAMHAL_LOGDB("Thumbnail Quality set %d", mThumbQuality);
266
267    if (mFirstTimeInit) {
268        mPendingCaptureSettings = ECapturesettingsAll;
269    }
270
271    if (mPendingCaptureSettings) {
272        disableImagePort();
273        if ( NULL != mReleaseImageBuffersCallback ) {
274            mReleaseImageBuffersCallback(mReleaseData);
275        }
276    }
277
278    LOG_FUNCTION_NAME_EXIT;
279
280    return ret;
281}
282
283status_t OMXCameraAdapter::getPictureBufferSize(size_t &length, size_t bufferCount)
284{
285    status_t ret = NO_ERROR;
286    OMXCameraPortParameters *imgCaptureData = NULL;
287    OMX_ERRORTYPE eError = OMX_ErrorNone;
288
289    LOG_FUNCTION_NAME;
290
291    if ( NO_ERROR == ret )
292        {
293        imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
294
295        imgCaptureData->mNumBufs = bufferCount;
296
297        // check if image port is already configured...
298        // if it already configured then we don't have to query again
299        if (!mCaptureConfigured) {
300            ret = setFormat(OMX_CAMERA_PORT_IMAGE_OUT_IMAGE, *imgCaptureData);
301        }
302
303        if ( ret == NO_ERROR )
304            {
305            length = imgCaptureData->mBufSize;
306            }
307        else
308            {
309            CAMHAL_LOGEB("setFormat() failed 0x%x", ret);
310            length = 0;
311            }
312        }
313
314    CAMHAL_LOGDB("getPictureBufferSize %d", length);
315
316    LOG_FUNCTION_NAME_EXIT;
317
318    return ret;
319}
320
321status_t OMXCameraAdapter::parseExpRange(const char *rangeStr,
322                                         int * expRange,
323                                         size_t count,
324                                         size_t &validEntries)
325{
326    status_t ret = NO_ERROR;
327    char *ctx, *expVal;
328    char *tmp = NULL;
329    size_t i = 0;
330
331    LOG_FUNCTION_NAME;
332
333    if ( NULL == rangeStr )
334        {
335        return -EINVAL;
336        }
337
338    if ( NULL == expRange )
339        {
340        return -EINVAL;
341        }
342
343    if ( NO_ERROR == ret )
344        {
345        tmp = ( char * ) malloc( strlen(rangeStr) + 1 );
346
347        if ( NULL == tmp )
348            {
349            CAMHAL_LOGEA("No resources for temporary buffer");
350            return -1;
351            }
352        memset(tmp, '\0', strlen(rangeStr) + 1);
353
354        }
355
356    if ( NO_ERROR == ret )
357        {
358        strncpy(tmp, rangeStr, strlen(rangeStr) );
359        expVal = strtok_r( (char *) tmp, CameraHal::PARAMS_DELIMITER, &ctx);
360
361        i = 0;
362        while ( ( NULL != expVal ) && ( i < count ) )
363            {
364            expRange[i] = atoi(expVal);
365            expVal = strtok_r(NULL, CameraHal::PARAMS_DELIMITER, &ctx);
366            i++;
367            }
368        validEntries = i;
369        }
370
371    if ( NULL != tmp )
372        {
373        free(tmp);
374        }
375
376    LOG_FUNCTION_NAME_EXIT;
377
378    return ret;
379}
380
381status_t OMXCameraAdapter::setExposureBracketing(int *evValues,
382                                                 size_t evCount,
383                                                 size_t frameCount)
384{
385    status_t ret = NO_ERROR;
386    OMX_ERRORTYPE eError = OMX_ErrorNone;
387    OMX_CONFIG_CAPTUREMODETYPE expCapMode;
388    OMX_CONFIG_EXTCAPTUREMODETYPE extExpCapMode;
389
390    LOG_FUNCTION_NAME;
391
392    if ( OMX_StateInvalid == mComponentState )
393        {
394        CAMHAL_LOGEA("OMX component is in invalid state");
395        ret = -EINVAL;
396        }
397
398    if ( NULL == evValues )
399        {
400        CAMHAL_LOGEA("Exposure compensation values pointer is invalid");
401        ret = -EINVAL;
402        }
403
404    if ( NO_ERROR == ret )
405        {
406        OMX_INIT_STRUCT_PTR (&expCapMode, OMX_CONFIG_CAPTUREMODETYPE);
407        expCapMode.nPortIndex = mCameraAdapterParameters.mImagePortIndex;
408
409        /// If frameCount>0 but evCount<=0, then this is the case of HQ burst.
410        //Otherwise, it is normal HQ capture
411        ///If frameCount>0 and evCount>0 then this is the cause of HQ Exposure bracketing.
412        if ( 0 == evCount && 0 == frameCount )
413            {
414            expCapMode.bFrameLimited = OMX_FALSE;
415            }
416        else
417            {
418            expCapMode.bFrameLimited = OMX_TRUE;
419            expCapMode.nFrameLimit = frameCount;
420            }
421
422        eError =  OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
423                                OMX_IndexConfigCaptureMode,
424                                &expCapMode);
425        if ( OMX_ErrorNone != eError )
426            {
427            CAMHAL_LOGEB("Error while configuring capture mode 0x%x", eError);
428            }
429        else
430            {
431            CAMHAL_LOGDA("Camera capture mode configured successfully");
432            }
433        }
434
435    if ( NO_ERROR == ret )
436        {
437        OMX_INIT_STRUCT_PTR (&extExpCapMode, OMX_CONFIG_EXTCAPTUREMODETYPE);
438        extExpCapMode.nPortIndex = mCameraAdapterParameters.mImagePortIndex;
439
440        if ( 0 == evCount )
441            {
442            extExpCapMode.bEnableBracketing = OMX_FALSE;
443            }
444        else
445            {
446            extExpCapMode.bEnableBracketing = OMX_TRUE;
447            extExpCapMode.tBracketConfigType.eBracketMode = OMX_BracketExposureRelativeInEV;
448            extExpCapMode.tBracketConfigType.nNbrBracketingValues = evCount - 1;
449            }
450
451        for ( unsigned int i = 0 ; i < evCount ; i++ )
452            {
453            extExpCapMode.tBracketConfigType.nBracketValues[i]  =  ( evValues[i] * ( 1 << Q16_OFFSET ) )  / 10;
454            }
455
456        eError =  OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
457                                ( OMX_INDEXTYPE ) OMX_IndexConfigExtCaptureMode,
458                                &extExpCapMode);
459        if ( OMX_ErrorNone != eError )
460            {
461            CAMHAL_LOGEB("Error while configuring extended capture mode 0x%x", eError);
462            }
463        else
464            {
465            CAMHAL_LOGDA("Extended camera capture mode configured successfully");
466            }
467        }
468
469    LOG_FUNCTION_NAME_EXIT;
470
471    return ret;
472}
473
474status_t OMXCameraAdapter::setShutterCallback(bool enabled)
475{
476    status_t ret = NO_ERROR;
477    OMX_ERRORTYPE eError = OMX_ErrorNone;
478    OMX_CONFIG_CALLBACKREQUESTTYPE shutterRequstCallback;
479
480    LOG_FUNCTION_NAME;
481
482    if ( OMX_StateExecuting != mComponentState )
483        {
484        CAMHAL_LOGEA("OMX component not in executing state");
485        ret = -1;
486        }
487
488    if ( NO_ERROR == ret )
489        {
490
491        OMX_INIT_STRUCT_PTR (&shutterRequstCallback, OMX_CONFIG_CALLBACKREQUESTTYPE);
492        shutterRequstCallback.nPortIndex = OMX_ALL;
493
494        if ( enabled )
495            {
496            shutterRequstCallback.bEnable = OMX_TRUE;
497            shutterRequstCallback.nIndex = ( OMX_INDEXTYPE ) OMX_TI_IndexConfigShutterCallback;
498            CAMHAL_LOGDA("Enabling shutter callback");
499            }
500        else
501            {
502            shutterRequstCallback.bEnable = OMX_FALSE;
503            shutterRequstCallback.nIndex = ( OMX_INDEXTYPE ) OMX_TI_IndexConfigShutterCallback;
504            CAMHAL_LOGDA("Disabling shutter callback");
505            }
506
507        eError =  OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
508                                ( OMX_INDEXTYPE ) OMX_IndexConfigCallbackRequest,
509                                &shutterRequstCallback);
510        if ( OMX_ErrorNone != eError )
511            {
512            CAMHAL_LOGEB("Error registering shutter callback 0x%x", eError);
513            ret = -1;
514            }
515        else
516            {
517            CAMHAL_LOGDB("Shutter callback for index 0x%x registered successfully",
518                         OMX_TI_IndexConfigShutterCallback);
519            }
520        }
521
522    LOG_FUNCTION_NAME_EXIT;
523
524    return ret;
525}
526
527status_t OMXCameraAdapter::doBracketing(OMX_BUFFERHEADERTYPE *pBuffHeader,
528                                        CameraFrame::FrameType typeOfFrame)
529{
530    status_t ret = NO_ERROR;
531    int currentBufferIdx, nextBufferIdx;
532    OMXCameraPortParameters * imgCaptureData = NULL;
533
534    LOG_FUNCTION_NAME;
535
536    imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
537
538    if ( OMX_StateExecuting != mComponentState )
539        {
540        CAMHAL_LOGEA("OMX component is not in executing state");
541        ret = -EINVAL;
542        }
543
544    if ( NO_ERROR == ret )
545        {
546        currentBufferIdx = ( unsigned int ) pBuffHeader->pAppPrivate;
547
548        if ( currentBufferIdx >= imgCaptureData->mNumBufs)
549            {
550            CAMHAL_LOGEB("Invalid bracketing buffer index 0x%x", currentBufferIdx);
551            ret = -EINVAL;
552            }
553        }
554
555    if ( NO_ERROR == ret )
556        {
557        mBracketingBuffersQueued[currentBufferIdx] = false;
558        mBracketingBuffersQueuedCount--;
559
560        if ( 0 >= mBracketingBuffersQueuedCount )
561            {
562            nextBufferIdx = ( currentBufferIdx + 1 ) % imgCaptureData->mNumBufs;
563            mBracketingBuffersQueued[nextBufferIdx] = true;
564            mBracketingBuffersQueuedCount++;
565            mLastBracetingBufferIdx = nextBufferIdx;
566            setFrameRefCount(imgCaptureData->mBufferHeader[nextBufferIdx]->pBuffer, typeOfFrame, 1);
567            returnFrame(imgCaptureData->mBufferHeader[nextBufferIdx]->pBuffer, typeOfFrame);
568            }
569        }
570
571    LOG_FUNCTION_NAME_EXIT;
572
573    return ret;
574}
575
576status_t OMXCameraAdapter::sendBracketFrames()
577{
578    status_t ret = NO_ERROR;
579    int currentBufferIdx;
580    OMXCameraPortParameters * imgCaptureData = NULL;
581
582    LOG_FUNCTION_NAME;
583
584    imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
585
586    if ( OMX_StateExecuting != mComponentState )
587        {
588        CAMHAL_LOGEA("OMX component is not in executing state");
589        ret = -EINVAL;
590        }
591
592    if ( NO_ERROR == ret )
593        {
594
595        currentBufferIdx = mLastBracetingBufferIdx;
596        do
597            {
598            currentBufferIdx++;
599            currentBufferIdx %= imgCaptureData->mNumBufs;
600            if (!mBracketingBuffersQueued[currentBufferIdx] )
601                {
602                CameraFrame cameraFrame;
603                sendCallBacks(cameraFrame,
604                              imgCaptureData->mBufferHeader[currentBufferIdx],
605                              imgCaptureData->mImageType,
606                              imgCaptureData);
607                }
608            } while ( currentBufferIdx != mLastBracetingBufferIdx );
609
610        }
611
612    LOG_FUNCTION_NAME_EXIT;
613
614    return ret;
615}
616
617status_t OMXCameraAdapter::startBracketing(int range)
618{
619    status_t ret = NO_ERROR;
620    OMXCameraPortParameters * imgCaptureData = NULL;
621
622    LOG_FUNCTION_NAME;
623
624    imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
625
626    if ( OMX_StateExecuting != mComponentState )
627        {
628        CAMHAL_LOGEA("OMX component is not in executing state");
629        ret = -EINVAL;
630        }
631
632        {
633        Mutex::Autolock lock(mBracketingLock);
634
635        if ( mBracketingEnabled )
636            {
637            return ret;
638            }
639        }
640
641    if ( 0 == imgCaptureData->mNumBufs )
642        {
643        CAMHAL_LOGEB("Image capture buffers set to %d", imgCaptureData->mNumBufs);
644        ret = -EINVAL;
645        }
646
647    if ( mPending3Asettings )
648        apply3Asettings(mParameters3A);
649
650    if ( NO_ERROR == ret )
651        {
652        Mutex::Autolock lock(mBracketingLock);
653
654        mBracketingRange = range;
655        mBracketingBuffersQueued = new bool[imgCaptureData->mNumBufs];
656        if ( NULL == mBracketingBuffersQueued )
657            {
658            CAMHAL_LOGEA("Unable to allocate bracketing management structures");
659            ret = -1;
660            }
661
662        if ( NO_ERROR == ret )
663            {
664            mBracketingBuffersQueuedCount = imgCaptureData->mNumBufs;
665            mLastBracetingBufferIdx = mBracketingBuffersQueuedCount - 1;
666
667            for ( int i = 0 ; i  < imgCaptureData->mNumBufs ; i++ )
668                {
669                mBracketingBuffersQueued[i] = true;
670                }
671
672            }
673        }
674
675    if ( NO_ERROR == ret )
676        {
677
678        ret = startImageCapture();
679            {
680            Mutex::Autolock lock(mBracketingLock);
681
682            if ( NO_ERROR == ret )
683                {
684                mBracketingEnabled = true;
685                }
686            else
687                {
688                mBracketingEnabled = false;
689                }
690            }
691        }
692
693    LOG_FUNCTION_NAME_EXIT;
694
695    return ret;
696}
697
698status_t OMXCameraAdapter::stopBracketing()
699{
700  status_t ret = NO_ERROR;
701
702    LOG_FUNCTION_NAME;
703
704    Mutex::Autolock lock(mBracketingLock);
705
706    if ( NULL != mBracketingBuffersQueued )
707    {
708        delete [] mBracketingBuffersQueued;
709    }
710
711    ret = stopImageCapture();
712
713    mBracketingBuffersQueued = NULL;
714    mBracketingEnabled = false;
715    mBracketingBuffersQueuedCount = 0;
716    mLastBracetingBufferIdx = 0;
717
718    LOG_FUNCTION_NAME_EXIT;
719
720    return ret;
721}
722
723status_t OMXCameraAdapter::startImageCapture()
724{
725    status_t ret = NO_ERROR;
726    OMX_ERRORTYPE eError = OMX_ErrorNone;
727    OMXCameraPortParameters * capData = NULL;
728    OMX_CONFIG_BOOLEANTYPE bOMX;
729
730    LOG_FUNCTION_NAME;
731
732    if(!mCaptureConfigured)
733        {
734        ///Image capture was cancelled before we could start
735        return NO_ERROR;
736        }
737
738    if ( 0 != mStartCaptureSem.Count() )
739        {
740        CAMHAL_LOGEB("Error mStartCaptureSem semaphore count %d", mStartCaptureSem.Count());
741        return NO_INIT;
742        }
743
744    if ((getNextState() & (CAPTURE_ACTIVE|BRACKETING_ACTIVE)) == 0) {
745        CAMHAL_LOGDA("trying starting capture when already canceled");
746        return NO_ERROR;
747    }
748
749    // Camera framework doesn't expect face callbacks once capture is triggered
750    pauseFaceDetection(true);
751
752    //During bracketing image capture is already active
753    {
754    Mutex::Autolock lock(mBracketingLock);
755    if ( mBracketingEnabled )
756        {
757        //Stop bracketing, activate normal burst for the remaining images
758        mBracketingEnabled = false;
759        mCapturedFrames = mBracketingRange;
760        ret = sendBracketFrames();
761        if(ret != NO_ERROR)
762            goto EXIT;
763        else
764            return ret;
765        }
766    }
767
768    if ( NO_ERROR == ret ) {
769        if (mPendingCaptureSettings & SetRotation) {
770            mPendingCaptureSettings &= ~SetRotation;
771            ret = setPictureRotation(mPictureRotation);
772            if ( NO_ERROR != ret ) {
773                CAMHAL_LOGEB("Error configuring image rotation %x", ret);
774            }
775        }
776    }
777
778    // need to enable wb data for video snapshot to fill in exif data
779    if ((ret == NO_ERROR) && (mCapMode == VIDEO_MODE)) {
780        // video snapshot uses wb data from snapshot frame
781        ret = setExtraData(true, mCameraAdapterParameters.mPrevPortIndex, OMX_WhiteBalance);
782    }
783
784    //OMX shutter callback events are only available in hq mode
785    if ( (HIGH_QUALITY == mCapMode) || (HIGH_QUALITY_ZSL== mCapMode))
786        {
787
788        if ( NO_ERROR == ret )
789            {
790            ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
791                                        (OMX_EVENTTYPE) OMX_EventIndexSettingChanged,
792                                        OMX_ALL,
793                                        OMX_TI_IndexConfigShutterCallback,
794                                        mStartCaptureSem);
795            }
796
797        if ( NO_ERROR == ret )
798            {
799            ret = setShutterCallback(true);
800            }
801
802        }
803
804    if ( NO_ERROR == ret ) {
805        capData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
806
807        ///Queue all the buffers on capture port
808        for ( int index = 0 ; index < capData->mNumBufs ; index++ ) {
809            CAMHAL_LOGDB("Queuing buffer on Capture port - 0x%x",
810                         ( unsigned int ) capData->mBufferHeader[index]->pBuffer);
811            eError = OMX_FillThisBuffer(mCameraAdapterParameters.mHandleComp,
812                        (OMX_BUFFERHEADERTYPE*)capData->mBufferHeader[index]);
813
814            GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
815        }
816
817        mWaitingForSnapshot = true;
818        mCaptureSignalled = false;
819
820        // Capturing command is not needed when capturing in video mode
821        // Only need to queue buffers on image ports
822        if (mCapMode != VIDEO_MODE) {
823            OMX_INIT_STRUCT_PTR (&bOMX, OMX_CONFIG_BOOLEANTYPE);
824            bOMX.bEnabled = OMX_TRUE;
825
826            /// sending Capturing Command to the component
827            eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
828                                   OMX_IndexConfigCapturing,
829                                   &bOMX);
830
831            CAMHAL_LOGDB("Capture set - 0x%x", eError);
832
833            GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
834        }
835    }
836
837    //OMX shutter callback events are only available in hq mode
838    if ( (HIGH_QUALITY == mCapMode) || (HIGH_QUALITY_ZSL== mCapMode))
839        {
840
841        if ( NO_ERROR == ret )
842            {
843            ret = mStartCaptureSem.WaitTimeout(OMX_CAPTURE_TIMEOUT);
844            }
845
846        //If somethiing bad happened while we wait
847        if (mComponentState == OMX_StateInvalid)
848          {
849            CAMHAL_LOGEA("Invalid State after Image Capture Exitting!!!");
850            goto EXIT;
851          }
852
853        if ( NO_ERROR == ret )
854            {
855            CAMHAL_LOGDA("Shutter callback received");
856            notifyShutterSubscribers();
857            }
858        else
859            {
860            ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp,
861                               (OMX_EVENTTYPE) OMX_EventIndexSettingChanged,
862                               OMX_ALL,
863                               OMX_TI_IndexConfigShutterCallback,
864                               NULL);
865            CAMHAL_LOGEA("Timeout expired on shutter callback");
866            goto EXIT;
867            }
868
869        }
870
871    return (ret | ErrorUtils::omxToAndroidError(eError));
872
873EXIT:
874    CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
875    setExtraData(false, mCameraAdapterParameters.mPrevPortIndex, OMX_WhiteBalance);
876    mWaitingForSnapshot = false;
877    mCaptureSignalled = false;
878    performCleanupAfterError();
879    LOG_FUNCTION_NAME_EXIT;
880    return (ret | ErrorUtils::omxToAndroidError(eError));
881}
882
883status_t OMXCameraAdapter::stopImageCapture()
884{
885    status_t ret = NO_ERROR;
886    OMX_ERRORTYPE eError = OMX_ErrorNone;
887    OMX_CONFIG_BOOLEANTYPE bOMX;
888    OMXCameraPortParameters *imgCaptureData = NULL;
889
890    LOG_FUNCTION_NAME;
891
892    if (!mCaptureConfigured) {
893        //Capture is not ongoing, return from here
894        return NO_ERROR;
895    }
896
897    if ( 0 != mStopCaptureSem.Count() ) {
898        CAMHAL_LOGEB("Error mStopCaptureSem semaphore count %d", mStopCaptureSem.Count());
899        goto EXIT;
900    }
901
902    //Disable the callback first
903    mWaitingForSnapshot = false;
904    mSnapshotCount = 0;
905
906    // OMX shutter callback events are only available in hq mode
907    if ((HIGH_QUALITY == mCapMode) || (HIGH_QUALITY_ZSL== mCapMode)) {
908        //Disable the callback first
909        ret = setShutterCallback(false);
910
911        // if anybody is waiting on the shutter callback
912        // signal them and then recreate the semaphore
913        if ( 0 != mStartCaptureSem.Count() ) {
914
915            for (int i = mStartCaptureSem.Count(); i < 0; i++) {
916            ret |= SignalEvent(mCameraAdapterParameters.mHandleComp,
917                               (OMX_EVENTTYPE) OMX_EventIndexSettingChanged,
918                               OMX_ALL,
919                               OMX_TI_IndexConfigShutterCallback,
920                               NULL );
921            }
922            mStartCaptureSem.Create(0);
923        }
924    }
925
926    // After capture, face detection should be disabled
927    // and application needs to restart face detection
928    stopFaceDetection();
929
930    //Wait here for the capture to be done, in worst case timeout and proceed with cleanup
931    mCaptureSem.WaitTimeout(OMX_CAPTURE_TIMEOUT);
932
933    //If somethiing bad happened while we wait
934    if (mComponentState == OMX_StateInvalid)
935      {
936        CAMHAL_LOGEA("Invalid State Image Capture Stop Exitting!!!");
937        goto EXIT;
938      }
939
940    // Disable image capture
941    // Capturing command is not needed when capturing in video mode
942    if (mCapMode != VIDEO_MODE) {
943        OMX_INIT_STRUCT_PTR (&bOMX, OMX_CONFIG_BOOLEANTYPE);
944        bOMX.bEnabled = OMX_FALSE;
945        imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
946        eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
947                               OMX_IndexConfigCapturing,
948                               &bOMX);
949        if ( OMX_ErrorNone != eError ) {
950            CAMHAL_LOGDB("Error during SetConfig- 0x%x", eError);
951            ret = -1;
952            goto EXIT;
953        }
954    }
955
956    // had to enable wb data for video snapshot to fill in exif data
957    // now that we are done...disable
958    if ((ret == NO_ERROR) && (mCapMode == VIDEO_MODE)) {
959        ret = setExtraData(false, mCameraAdapterParameters.mPrevPortIndex, OMX_WhiteBalance);
960    }
961
962    CAMHAL_LOGDB("Capture set - 0x%x", eError);
963
964    mCaptureSignalled = true; //set this to true if we exited because of timeout
965
966    {
967        Mutex::Autolock lock(mFrameCountMutex);
968        mFrameCount = 0;
969        mFirstFrameCondition.broadcast();
970    }
971
972    return (ret | ErrorUtils::omxToAndroidError(eError));
973
974EXIT:
975    CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
976    //Release image buffers
977    if ( NULL != mReleaseImageBuffersCallback ) {
978        mReleaseImageBuffersCallback(mReleaseData);
979    }
980
981    {
982        Mutex::Autolock lock(mFrameCountMutex);
983        mFrameCount = 0;
984        mFirstFrameCondition.broadcast();
985    }
986
987    performCleanupAfterError();
988    LOG_FUNCTION_NAME_EXIT;
989    return (ret | ErrorUtils::omxToAndroidError(eError));
990}
991
992status_t OMXCameraAdapter::disableImagePort(){
993    status_t ret = NO_ERROR;
994    OMX_ERRORTYPE eError = OMX_ErrorNone;
995    OMXCameraPortParameters *imgCaptureData = NULL;
996
997    if (!mCaptureConfigured) {
998        return NO_ERROR;
999    }
1000
1001    mCaptureConfigured = false;
1002    imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
1003
1004    ///Register for Image port Disable event
1005    ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
1006                                OMX_EventCmdComplete,
1007                                OMX_CommandPortDisable,
1008                                mCameraAdapterParameters.mImagePortIndex,
1009                                mStopCaptureSem);
1010    ///Disable Capture Port
1011    eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp,
1012                                OMX_CommandPortDisable,
1013                                mCameraAdapterParameters.mImagePortIndex,
1014                                NULL);
1015
1016    ///Free all the buffers on capture port
1017    if (imgCaptureData) {
1018        CAMHAL_LOGDB("Freeing buffer on Capture port - %d", imgCaptureData->mNumBufs);
1019        for ( int index = 0 ; index < imgCaptureData->mNumBufs ; index++) {
1020            CAMHAL_LOGDB("Freeing buffer on Capture port - 0x%x",
1021                         ( unsigned int ) imgCaptureData->mBufferHeader[index]->pBuffer);
1022            eError = OMX_FreeBuffer(mCameraAdapterParameters.mHandleComp,
1023                                    mCameraAdapterParameters.mImagePortIndex,
1024                                    (OMX_BUFFERHEADERTYPE*)imgCaptureData->mBufferHeader[index]);
1025
1026            GOTO_EXIT_IF((eError!=OMX_ErrorNone), eError);
1027        }
1028    }
1029    CAMHAL_LOGDA("Waiting for port disable");
1030    //Wait for the image port enable event
1031    ret = mStopCaptureSem.WaitTimeout(OMX_CMD_TIMEOUT);
1032
1033    //If somethiing bad happened while we wait
1034    if (mComponentState == OMX_StateInvalid)
1035      {
1036        CAMHAL_LOGEA("Invalid State after Disable Image Port Exitting!!!");
1037        goto EXIT;
1038      }
1039
1040    if ( NO_ERROR == ret ) {
1041        CAMHAL_LOGDA("Port disabled");
1042    } else {
1043        ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp,
1044                           OMX_EventCmdComplete,
1045                           OMX_CommandPortDisable,
1046                           mCameraAdapterParameters.mImagePortIndex,
1047                           NULL);
1048        CAMHAL_LOGDA("Timeout expired on port disable");
1049        goto EXIT;
1050    }
1051
1052 EXIT:
1053    return (ret | ErrorUtils::omxToAndroidError(eError));
1054}
1055
1056
1057status_t OMXCameraAdapter::UseBuffersCapture(void* bufArr, int num)
1058{
1059    LOG_FUNCTION_NAME;
1060
1061    status_t ret = NO_ERROR;
1062    OMX_ERRORTYPE eError = OMX_ErrorNone;
1063    OMXCameraPortParameters * imgCaptureData = NULL;
1064    uint32_t *buffers = (uint32_t*)bufArr;
1065    OMXCameraPortParameters cap;
1066
1067    imgCaptureData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mImagePortIndex];
1068
1069    if ( 0 != mUseCaptureSem.Count() )
1070        {
1071        CAMHAL_LOGEB("Error mUseCaptureSem semaphore count %d", mUseCaptureSem.Count());
1072        return BAD_VALUE;
1073        }
1074
1075    // capture is already configured...we can skip this step
1076    if (mCaptureConfigured) {
1077
1078        if ( NO_ERROR == ret )
1079            {
1080            ret = setupEXIF();
1081            if ( NO_ERROR != ret )
1082                {
1083                CAMHAL_LOGEB("Error configuring EXIF Buffer %x", ret);
1084                }
1085            }
1086
1087        mCapturedFrames = mBurstFrames;
1088        return NO_ERROR;
1089    }
1090
1091    imgCaptureData->mNumBufs = num;
1092
1093    //TODO: Support more pixelformats
1094
1095    CAMHAL_LOGDB("Params Width = %d", (int)imgCaptureData->mWidth);
1096    CAMHAL_LOGDB("Params Height = %d", (int)imgCaptureData->mWidth);
1097
1098    if (mPendingCaptureSettings & SetFormat) {
1099        mPendingCaptureSettings &= ~SetFormat;
1100        ret = setFormat(OMX_CAMERA_PORT_IMAGE_OUT_IMAGE, *imgCaptureData);
1101        if ( ret != NO_ERROR ) {
1102            CAMHAL_LOGEB("setFormat() failed %d", ret);
1103            LOG_FUNCTION_NAME_EXIT;
1104            return ret;
1105        }
1106    }
1107
1108    if (mPendingCaptureSettings & SetThumb) {
1109        mPendingCaptureSettings &= ~SetThumb;
1110        ret = setThumbnailParams(mThumbWidth, mThumbHeight, mThumbQuality);
1111        if ( NO_ERROR != ret) {
1112            CAMHAL_LOGEB("Error configuring thumbnail size %x", ret);
1113            return ret;
1114        }
1115    }
1116
1117    if (mPendingCaptureSettings & SetExpBracket) {
1118        mPendingCaptureSettings &= ~SetExpBracket;
1119        ret = setExposureBracketing( mExposureBracketingValues,
1120                                     mExposureBracketingValidEntries, mBurstFrames);
1121        if ( ret != NO_ERROR ) {
1122            CAMHAL_LOGEB("setExposureBracketing() failed %d", ret);
1123            goto EXIT;
1124        }
1125    }
1126
1127    if (mPendingCaptureSettings & SetQuality) {
1128        mPendingCaptureSettings &= ~SetQuality;
1129        ret = setImageQuality(mPictureQuality);
1130        if ( NO_ERROR != ret) {
1131            CAMHAL_LOGEB("Error configuring image quality %x", ret);
1132            goto EXIT;
1133        }
1134    }
1135
1136    ///Register for Image port ENABLE event
1137    ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
1138                           OMX_EventCmdComplete,
1139                           OMX_CommandPortEnable,
1140                           mCameraAdapterParameters.mImagePortIndex,
1141                           mUseCaptureSem);
1142
1143    ///Enable Capture Port
1144    eError = OMX_SendCommand(mCameraAdapterParameters.mHandleComp,
1145                             OMX_CommandPortEnable,
1146                             mCameraAdapterParameters.mImagePortIndex,
1147                             NULL);
1148
1149    CAMHAL_LOGDB("OMX_UseBuffer = 0x%x", eError);
1150    GOTO_EXIT_IF(( eError != OMX_ErrorNone ), eError);
1151
1152    for ( int index = 0 ; index < imgCaptureData->mNumBufs ; index++ )
1153    {
1154        OMX_BUFFERHEADERTYPE *pBufferHdr;
1155        CAMHAL_LOGDB("OMX_UseBuffer Capture address: 0x%x, size = %d",
1156                     (unsigned int)buffers[index],
1157                     (int)imgCaptureData->mBufSize);
1158
1159        eError = OMX_UseBuffer(mCameraAdapterParameters.mHandleComp,
1160                               &pBufferHdr,
1161                               mCameraAdapterParameters.mImagePortIndex,
1162                               0,
1163                               mCaptureBuffersLength,
1164                               (OMX_U8*)buffers[index]);
1165
1166        CAMHAL_LOGDB("OMX_UseBuffer = 0x%x", eError);
1167        GOTO_EXIT_IF(( eError != OMX_ErrorNone ), eError);
1168
1169        pBufferHdr->pAppPrivate = (OMX_PTR) index;
1170        pBufferHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
1171        pBufferHdr->nVersion.s.nVersionMajor = 1 ;
1172        pBufferHdr->nVersion.s.nVersionMinor = 1 ;
1173        pBufferHdr->nVersion.s.nRevision = 0;
1174        pBufferHdr->nVersion.s.nStep =  0;
1175        imgCaptureData->mBufferHeader[index] = pBufferHdr;
1176    }
1177
1178    //Wait for the image port enable event
1179    CAMHAL_LOGDA("Waiting for port enable");
1180    ret = mUseCaptureSem.WaitTimeout(OMX_CMD_TIMEOUT);
1181
1182    //If somethiing bad happened while we wait
1183    if (mComponentState == OMX_StateInvalid)
1184      {
1185        CAMHAL_LOGEA("Invalid State after Enable Image Port Exitting!!!");
1186        goto EXIT;
1187      }
1188
1189    if ( ret == NO_ERROR )
1190        {
1191        CAMHAL_LOGDA("Port enabled");
1192        }
1193    else
1194        {
1195        ret |= RemoveEvent(mCameraAdapterParameters.mHandleComp,
1196                           OMX_EventCmdComplete,
1197                           OMX_CommandPortEnable,
1198                           mCameraAdapterParameters.mImagePortIndex,
1199                           NULL);
1200        CAMHAL_LOGDA("Timeout expired on port enable");
1201        goto EXIT;
1202        }
1203
1204    if ( NO_ERROR == ret )
1205        {
1206        ret = setupEXIF();
1207        if ( NO_ERROR != ret )
1208            {
1209            CAMHAL_LOGEB("Error configuring EXIF Buffer %x", ret);
1210            }
1211        }
1212
1213    mCapturedFrames = mBurstFrames;
1214    mCaptureConfigured = true;
1215
1216    return (ret | ErrorUtils::omxToAndroidError(eError));
1217
1218EXIT:
1219    CAMHAL_LOGEB("Exiting function %s because of ret %d eError=%x", __FUNCTION__, ret, eError);
1220    //Release image buffers
1221    if ( NULL != mReleaseImageBuffersCallback ) {
1222        mReleaseImageBuffersCallback(mReleaseData);
1223    }
1224    performCleanupAfterError();
1225    LOG_FUNCTION_NAME_EXIT;
1226    return (ret | ErrorUtils::omxToAndroidError(eError));
1227
1228}
1229
1230};
1231