Home | History | Annotate | Download | only in mm-camera-interface
      1 /* Copyright (c) 2012, The Linux Foundation. All rights reserved.
      2  *
      3  * Redistribution and use in source and binary forms, with or without
      4  * modification, are permitted provided that the following conditions are
      5  * met:
      6  *     * Redistributions of source code must retain the above copyright
      7  *       notice, this list of conditions and the following disclaimer.
      8  *     * Redistributions in binary form must reproduce the above
      9  *       copyright notice, this list of conditions and the following
     10  *       disclaimer in the documentation and/or other materials provided
     11  *       with the distribution.
     12  *     * Neither the name of The Linux Foundation nor the names of its
     13  *       contributors may be used to endorse or promote products derived
     14  *       from this software without specific prior written permission.
     15  *
     16  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     23  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     25  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     26  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 #include <sys/types.h>
     30 #include <stdbool.h>
     31 #include <fcntl.h>
     32 #include <dlfcn.h>
     33 #include "OMX_Types.h"
     34 #include "OMX_Index.h"
     35 #include "OMX_Core.h"
     36 #include "OMX_Component.h"
     37 #include "omx_debug.h"
     38 #include "omx_jpeg_ext.h"
     39 #include "mm_omx_jpeg_encoder.h"
     40 
     41 static uint8_t hw_encode = true;
     42 static int jpegRotation = 0;
     43 static int isZSLMode = 0;
     44 static int jpegThumbnailQuality = 75;
     45 static int jpegMainimageQuality = 85;
     46 static uint32_t phy_offset;
     47 void *user_data;
     48 
     49 static int encoding = 0;
     50 pthread_mutex_t jpege_mutex = PTHREAD_MUTEX_INITIALIZER;
     51 pthread_mutex_t jpegcb_mutex = PTHREAD_MUTEX_INITIALIZER;
     52 
     53 jpegfragment_callback_t mmcamera_jpegfragment_callback;
     54 jpeg_callback_t mmcamera_jpeg_callback;
     55 
     56 
     57 #define INPUT_PORT 0
     58 #define OUTPUT_PORT 1
     59 #define INPUT_PORT1 2
     60 #define DEFAULT_COLOR_FORMAT YCRCBLP_H2V2
     61 
     62 typedef struct {
     63   cam_format_t         isp_format;
     64   jpeg_color_format_t  jpg_format;
     65 } color_format_map_t;
     66 
     67 
     68 static const color_format_map_t color_format_map[] = {
     69   {CAMERA_YUV_420_NV21, YCRCBLP_H2V2}, /*default*/
     70   {CAMERA_YUV_420_NV21_ADRENO, YCRCBLP_H2V2},
     71   {CAMERA_YUV_420_NV12, YCBCRLP_H2V2},
     72   {CAMERA_YUV_420_YV12, YCBCRLP_H2V2},
     73   {CAMERA_YUV_422_NV61, YCRCBLP_H2V1},
     74   {CAMERA_YUV_422_NV16, YCBCRLP_H2V1},
     75 };
     76 
     77 static OMX_HANDLETYPE pHandle;
     78 static OMX_CALLBACKTYPE callbacks;
     79 static OMX_INDEXTYPE type;
     80 static OMX_CONFIG_ROTATIONTYPE rotType;
     81 static omx_jpeg_thumbnail thumbnail;
     82 static OMX_CONFIG_RECTTYPE recttype;
     83 static OMX_PARAM_PORTDEFINITIONTYPE * inputPort;
     84 static OMX_PARAM_PORTDEFINITIONTYPE * outputPort;
     85 static OMX_PARAM_PORTDEFINITIONTYPE * inputPort1;
     86 static OMX_BUFFERHEADERTYPE* pInBuffers;
     87 static OMX_BUFFERHEADERTYPE* pOutBuffers;
     88 static OMX_BUFFERHEADERTYPE* pInBuffers1;
     89 OMX_INDEXTYPE user_preferences;
     90 omx_jpeg_user_preferences userpreferences;
     91 OMX_INDEXTYPE exif;
     92 static omx_jpeg_exif_info_tag tag;
     93 
     94 static void *libmmstillomx;
     95 OMX_ERRORTYPE OMX_APIENTRY (*pOMX_GetHandle)(
     96     OMX_OUT OMX_HANDLETYPE* pHandle,
     97     OMX_IN  OMX_STRING cComponentName,
     98     OMX_IN  OMX_PTR pAppData,
     99     OMX_IN  OMX_CALLBACKTYPE* pCallBacks);
    100 OMX_ERRORTYPE OMX_APIENTRY (*pOMX_Init)(void);
    101 OMX_ERRORTYPE OMX_APIENTRY (*pOMX_Deinit)(void);
    102 
    103 static pthread_mutex_t lock;
    104 static pthread_cond_t cond;
    105 static int expectedEvent = 0;
    106 static int expectedValue1 = 0;
    107 static int expectedValue2 = 0;
    108 static omx_jpeg_pmem_info pmem_info;
    109 static omx_jpeg_pmem_info pmem_info1;
    110 static OMX_IMAGE_PARAM_QFACTORTYPE qFactor;
    111 static omx_jpeg_thumbnail_quality thumbnailQuality;
    112 static OMX_INDEXTYPE thumbnailQualityType;
    113 static void *out_buffer;
    114 static int * out_buffer_size;
    115 static OMX_INDEXTYPE buffer_offset;
    116 static omx_jpeg_buffer_offset bufferoffset;
    117 
    118 static jpeg_color_format_t get_jpeg_format_from_cam_format(
    119   cam_format_t cam_format )
    120 {
    121   jpeg_color_format_t jpg_format = DEFAULT_COLOR_FORMAT;
    122   int i, j;
    123   j = sizeof (color_format_map) / sizeof(color_format_map_t);
    124   ALOGV("%s: j =%d, cam_format =%d", __func__, j, cam_format);
    125   for(i =0; i< j; i++) {
    126     if (color_format_map[i].isp_format == cam_format){
    127       jpg_format = color_format_map[i].jpg_format;
    128       break;
    129     }
    130   }
    131   ALOGV("%s x: i =%d, jpg_format=%d", __func__, i, jpg_format);
    132 
    133   return jpg_format;
    134 }
    135 static omx_jpeg_buffer_offset bufferoffset1;
    136 void set_callbacks(
    137     jpegfragment_callback_t fragcallback,
    138     jpeg_callback_t eventcallback, void* userdata,
    139     void* output_buffer,
    140     int * outBufferSize) {
    141     pthread_mutex_lock(&jpegcb_mutex);
    142     mmcamera_jpegfragment_callback = fragcallback;
    143     mmcamera_jpeg_callback = eventcallback;
    144     user_data = userdata;
    145     out_buffer = output_buffer;
    146     out_buffer_size = outBufferSize;
    147     pthread_mutex_unlock(&jpegcb_mutex);
    148 }
    149 
    150 
    151 OMX_ERRORTYPE etbdone(OMX_OUT OMX_HANDLETYPE hComponent,
    152                       OMX_OUT OMX_PTR pAppData,
    153                       OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer)
    154 {
    155     pthread_mutex_lock(&lock);
    156     expectedEvent = OMX_EVENT_ETB_DONE;
    157     expectedValue1 = 0;
    158     expectedValue2 = 0;
    159     pthread_cond_signal(&cond);
    160     pthread_mutex_unlock(&lock);
    161     return 0;
    162 }
    163 
    164 OMX_ERRORTYPE ftbdone(OMX_OUT OMX_HANDLETYPE hComponent,
    165                       OMX_OUT OMX_PTR pAppData,
    166                       OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer)
    167 {
    168     ALOGV("%s", __func__);
    169     *out_buffer_size = pBuffer->nFilledLen;
    170     pthread_mutex_lock(&lock);
    171     expectedEvent = OMX_EVENT_FTB_DONE;
    172     expectedValue1 = 0;
    173     expectedValue2 = 0;
    174     pthread_cond_signal(&cond);
    175     pthread_mutex_unlock(&lock);
    176     ALOGV("%s:filled len = %u", __func__, (uint32_t)pBuffer->nFilledLen);
    177     if (mmcamera_jpeg_callback && encoding)
    178         mmcamera_jpeg_callback(0, user_data);
    179     return 0;
    180 }
    181 
    182 OMX_ERRORTYPE handleError(OMX_IN OMX_EVENTTYPE eEvent, OMX_IN OMX_U32 error)
    183 {
    184     ALOGV("%s", __func__);
    185     if (error == OMX_EVENT_JPEG_ERROR) {
    186         if (mmcamera_jpeg_callback && encoding) {
    187             ALOGV("%s:OMX_EVENT_JPEG_ERROR\n", __func__);
    188             mmcamera_jpeg_callback(JPEG_EVENT_ERROR, user_data);
    189         }
    190     } else if (error == OMX_EVENT_THUMBNAIL_DROPPED) {
    191         if (mmcamera_jpeg_callback && encoding) {
    192             ALOGV("%s:(OMX_EVENT_THUMBNAIL_DROPPED\n", __func__);
    193             mmcamera_jpeg_callback(JPEG_EVENT_THUMBNAIL_DROPPED, user_data);
    194         }
    195     }
    196     return 0;
    197 }
    198 
    199 OMX_ERRORTYPE eventHandler( OMX_IN OMX_HANDLETYPE hComponent,
    200                             OMX_IN OMX_PTR pAppData, OMX_IN OMX_EVENTTYPE eEvent,
    201                             OMX_IN OMX_U32 nData1, OMX_IN OMX_U32 nData2,
    202                             OMX_IN OMX_PTR pEventData)
    203 {
    204     ALOGV("%s", __func__);
    205     ALOGV("%s:got event %d ndata1 %u ndata2 %u", __func__,
    206       eEvent, nData1, nData2);
    207     pthread_mutex_lock(&lock);
    208     expectedEvent = eEvent;
    209     expectedValue1 = nData1;
    210     expectedValue2 = nData2;
    211     pthread_cond_signal(&cond);
    212     pthread_mutex_unlock(&lock);
    213     if ((nData1== OMX_EVENT_JPEG_ERROR)||(nData1== OMX_EVENT_THUMBNAIL_DROPPED))
    214         handleError(eEvent,nData1);
    215     return 0;
    216 }
    217 
    218 void waitForEvent(int event, int value1, int value2 ){
    219     pthread_mutex_lock(&lock);
    220     ALOGV("%s:Waiting for:event=%d, value1=%d, value2=%d",
    221       __func__, event, value1, value2);
    222     while (! (expectedEvent == event &&
    223     expectedValue1 == value1 && expectedValue2 == value2)) {
    224         pthread_cond_wait(&cond, &lock);
    225         ALOGV("%s:After cond_wait:expectedEvent=%d, expectedValue1=%d, expectedValue2=%d",
    226           __func__, expectedEvent, expectedValue1, expectedValue2);
    227         ALOGV("%s:After cond_wait:event=%d, value1=%d, value2=%d",
    228           __func__, event, value1, value2);
    229     }
    230     ALOGV("%s:done:expectedEvent=%d, expectedValue1=%d, expectedValue2=%d",
    231       __func__, expectedEvent, expectedValue1, expectedValue2);
    232     pthread_mutex_unlock(&lock);
    233 }
    234 
    235 int8_t mm_jpeg_encoder_get_buffer_offset(uint32_t width, uint32_t height,
    236     uint32_t* p_y_offset, uint32_t* p_cbcr_offset, uint32_t* p_buf_size,
    237     uint8_t *num_planes, uint32_t planes[])
    238 {
    239     ALOGV("%s:", __func__);
    240     if ((NULL == p_y_offset) || (NULL == p_cbcr_offset)) {
    241         return false;
    242     }
    243     *num_planes = 2;
    244     if (hw_encode ) {
    245         int cbcr_offset = 0;
    246         uint32_t actual_size = width*height;
    247         uint32_t padded_size = width * CEILING16(height);
    248         *p_y_offset = 0;
    249         *p_cbcr_offset = 0;
    250         //if(!isZSLMode){
    251         if ((jpegRotation == 90) || (jpegRotation == 180)) {
    252             *p_y_offset = padded_size - actual_size;
    253             *p_cbcr_offset = ((padded_size - actual_size) >> 1);
    254           }
    255         *p_buf_size = (padded_size + (padded_size - actual_size)) * 3/2;
    256         planes[0] = width * CEILING16(height);
    257         planes[1] = width * CEILING16(height)/2;
    258     } else {
    259         *p_y_offset = 0;
    260         *p_cbcr_offset = PAD_TO_WORD(width*height);
    261         *p_buf_size = *p_cbcr_offset * 3/2;
    262         planes[0] = PAD_TO_WORD(width*CEILING16(height));
    263         planes[1] = PAD_TO_WORD(width*CEILING16(height)/2);
    264     }
    265     return true;
    266 }
    267 
    268 int8_t omxJpegOpen()
    269 {
    270     ALOGV("%s", __func__);
    271     pthread_mutex_lock(&jpege_mutex);
    272     libmmstillomx = dlopen("libmmstillomx.so", RTLD_NOW);
    273     if (!libmmstillomx) {
    274         ALOGE("%s: dlopen failed", __func__);
    275         pthread_mutex_unlock(&jpege_mutex);
    276         return false;
    277     }
    278     *(void **)(&pOMX_GetHandle) = dlsym(libmmstillomx, "OMX_GetHandle");
    279     *(void **)(&pOMX_Init) = dlsym(libmmstillomx, "OMX_Init");
    280     *(void **)(&pOMX_Deinit) = dlsym(libmmstillomx, "OMX_Deinit");
    281     if (!pOMX_GetHandle || !pOMX_Init || !pOMX_Deinit) {
    282         ALOGE("%s: dlsym failed", __func__);
    283         dlclose(libmmstillomx);
    284         pthread_mutex_unlock(&jpege_mutex);
    285         return false;
    286     }
    287     OMX_ERRORTYPE ret = (*pOMX_GetHandle)(&pHandle, "OMX.qcom.image.jpeg.encoder",
    288       NULL, &callbacks);
    289     pthread_mutex_unlock(&jpege_mutex);
    290     return true;
    291 }
    292 
    293 int8_t omxJpegStart(uint8_t hw_encode_enable)
    294 {
    295     int rc = 0;
    296     ALOGV("%s", __func__);
    297     pthread_mutex_lock(&jpege_mutex);
    298     hw_encode = hw_encode_enable;
    299     callbacks.EmptyBufferDone = etbdone;
    300     callbacks.FillBufferDone = ftbdone;
    301     callbacks.EventHandler = eventHandler;
    302     pthread_mutex_init(&lock, NULL);
    303     pthread_cond_init(&cond, NULL);
    304     rc = (*pOMX_Init)();
    305     pthread_mutex_unlock(&jpege_mutex);
    306     return rc;
    307 }
    308 
    309 static omx_jpeg_color_format format_cam2jpeg(cam_format_t fmt)
    310 {
    311     omx_jpeg_color_format jpeg_fmt = OMX_YCRCBLP_H2V2;
    312     switch (fmt) {
    313     case CAMERA_YUV_420_NV12:
    314         jpeg_fmt = OMX_YCBCRLP_H2V2;
    315         break;
    316     case CAMERA_YUV_420_NV21:
    317     case CAMERA_YUV_420_NV21_ADRENO:
    318         jpeg_fmt = OMX_YCRCBLP_H2V2;
    319         break;
    320     default:
    321         ALOGV("Camera format %d not supported", fmt);
    322         break;
    323     }
    324     return jpeg_fmt;
    325 }
    326 
    327 int8_t omxJpegEncodeNext(omx_jpeg_encode_params *encode_params)
    328 {
    329     ALOGV("%s:E", __func__);
    330     pthread_mutex_lock(&jpege_mutex);
    331     encoding = 1;
    332     int orientation;
    333     if(inputPort == NULL || inputPort1 == NULL || outputPort == NULL) {
    334       ALOGV("%s:pointer is null: X", __func__);
    335       pthread_mutex_unlock(&jpege_mutex);
    336       return -1;
    337     }
    338     inputPort->nPortIndex = INPUT_PORT;
    339     outputPort->nPortIndex = OUTPUT_PORT;
    340     inputPort1->nPortIndex = INPUT_PORT1;
    341     OMX_GetParameter(pHandle, OMX_IndexParamPortDefinition, inputPort);
    342     OMX_GetParameter(pHandle, OMX_IndexParamPortDefinition, outputPort);
    343 
    344     ALOGV("%s:nFrameWidth=%d nFrameHeight=%d nBufferSize=%d w=%d h=%d",
    345       __func__, inputPort->format.image.nFrameWidth,
    346       inputPort->format.image.nFrameHeight, inputPort->nBufferSize,
    347       bufferoffset.width, bufferoffset.height);
    348     OMX_GetExtensionIndex(pHandle,"omx.qcom.jpeg.exttype.buffer_offset",
    349       &buffer_offset);
    350     ALOGV("%s:Buffer w %d h %d yOffset %d cbcrOffset %d totalSize %d\n",
    351       __func__, bufferoffset.width, bufferoffset.height, bufferoffset.yOffset,
    352       bufferoffset.cbcrOffset,bufferoffset.totalSize);
    353     OMX_SetParameter(pHandle, buffer_offset, &bufferoffset);
    354     OMX_SetParameter(pHandle, OMX_IndexParamPortDefinition, inputPort1);
    355     OMX_GetParameter(pHandle, OMX_IndexParamPortDefinition, inputPort1);
    356     ALOGV("%s: thumbnail widht %d height %d", __func__,
    357       thumbnail.width, thumbnail.height);
    358 
    359     userpreferences.color_format =
    360         format_cam2jpeg(encode_params->dimension->main_img_format);
    361     userpreferences.thumbnail_color_format =
    362         format_cam2jpeg(encode_params->dimension->thumb_format);
    363 
    364 
    365     pmem_info.fd = encode_params->snapshot_fd;
    366     pmem_info.offset = 0;
    367 
    368     //Release previously allocated buffers before doing UseBuffer in burst mode
    369     OMX_FreeBuffer(pHandle, 2, pInBuffers1);
    370     OMX_FreeBuffer(pHandle, 0, pInBuffers);
    371     OMX_FreeBuffer(pHandle, 1, pOutBuffers);
    372 
    373     OMX_UseBuffer(pHandle, &pInBuffers, 0, &pmem_info, inputPort->nBufferSize,
    374     (void *) encode_params->snapshot_buf);
    375     OMX_GetExtensionIndex(pHandle, "omx.qcom.jpeg.exttype.exif", &exif);
    376     /*temporarily set rotation in EXIF data. This is done to avoid
    377       image corruption issues in ZSL mode since roation is known
    378       before hand. The orientation is set in the exif tag and
    379       decoder will decode it will the right orientation. need to add double
    380       padding to fix the issue */
    381     if (isZSLMode) {
    382         /*Get the orientation tag values depending on rotation*/
    383         switch (jpegRotation) {
    384         case 0:
    385             orientation = 1; /*Normal*/
    386             break;
    387         case 90:
    388             orientation = 6; /*Rotated 90 CCW*/
    389             break;
    390         case 180:
    391             orientation =  3; /*Rotated 180*/
    392             break;
    393         case 270:
    394             orientation = 8; /*Rotated 90 CW*/
    395             break;
    396         default:
    397             orientation = 1;
    398             break;
    399       }
    400       tag.tag_id = EXIFTAGID_ORIENTATION;
    401       tag.tag_entry.type = EXIFTAGTYPE_ORIENTATION;
    402       tag.tag_entry.count = 1;
    403       tag.tag_entry.copy = 1;
    404       tag.tag_entry.data._short = orientation;
    405       ALOGV("%s jpegRotation = %d , orientation value =%d\n", __func__,
    406            jpegRotation, orientation);
    407       OMX_SetParameter(pHandle, exif, &tag);
    408     }
    409 
    410     /*Set omx parameter for all exif tags*/
    411     int i;
    412     for (i = 0; i < encode_params->exif_numEntries; i++) {
    413         memcpy(&tag, encode_params->exif_data + i,
    414                sizeof(omx_jpeg_exif_info_tag));
    415         OMX_SetParameter(pHandle, exif, &tag);
    416     }
    417 
    418     pmem_info1.fd = encode_params->thumbnail_fd;
    419     pmem_info1.offset = 0;
    420 
    421     ALOGV("%s: input1 buff size %d", __func__, inputPort1->nBufferSize);
    422     OMX_UseBuffer(pHandle, &pInBuffers1, 2, &pmem_info1,
    423       inputPort1->nBufferSize, (void *) encode_params->thumbnail_buf);
    424     OMX_UseBuffer(pHandle, &pOutBuffers, 1, NULL, inputPort->nBufferSize,
    425       (void *) out_buffer);
    426     OMX_EmptyThisBuffer(pHandle, pInBuffers);
    427     OMX_EmptyThisBuffer(pHandle, pInBuffers1);
    428     OMX_FillThisBuffer(pHandle, pOutBuffers);
    429     pthread_mutex_unlock(&jpege_mutex);
    430     ALOGV("%s:X", __func__);
    431     return true;
    432 }
    433 
    434 int8_t omxJpegEncode(omx_jpeg_encode_params *encode_params)
    435 {
    436     int size = 0;
    437     uint8_t num_planes;
    438     uint32_t planes[10];
    439     int orientation;
    440     ALOGV("%s:E", __func__);
    441 
    442     inputPort = malloc(sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
    443     outputPort = malloc(sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
    444     inputPort1 = malloc(sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
    445 
    446     pthread_mutex_lock(&jpege_mutex);
    447     encoding = 1;
    448     inputPort->nPortIndex = INPUT_PORT;
    449     outputPort->nPortIndex = OUTPUT_PORT;
    450     inputPort1->nPortIndex = INPUT_PORT1;
    451     OMX_GetParameter(pHandle, OMX_IndexParamPortDefinition, inputPort);
    452     OMX_GetParameter(pHandle, OMX_IndexParamPortDefinition, outputPort);
    453 
    454     bufferoffset.width = encode_params->dimension->orig_picture_dx;
    455     bufferoffset.height = encode_params->dimension->orig_picture_dy;
    456 
    457     if (hw_encode)
    458         userpreferences.preference = OMX_JPEG_PREF_HW_ACCELERATED_PREFERRED;
    459     else
    460         userpreferences.preference = OMX_JPEG_PREF_SOFTWARE_ONLY;
    461     if (encode_params->a_cbcroffset > 0) {
    462         userpreferences.preference = OMX_JPEG_PREF_SOFTWARE_ONLY;
    463         hw_encode = 0;
    464     }
    465     mm_jpeg_encoder_get_buffer_offset(bufferoffset.width, bufferoffset.height,
    466                     &bufferoffset.yOffset,
    467                     &bufferoffset.cbcrOffset,
    468                     &bufferoffset.totalSize, &num_planes, planes);
    469     if (encode_params->a_cbcroffset > 0) {
    470         bufferoffset.totalSize = encode_params->a_cbcroffset * 1.5;
    471     }
    472     OMX_GetExtensionIndex(pHandle,"omx.qcom.jpeg.exttype.buffer_offset",&buffer_offset);
    473     ALOGV(" Buffer width = %d, Buffer  height = %d, yOffset =%d, cbcrOffset =%d, totalSize = %d\n",
    474                  bufferoffset.width, bufferoffset.height, bufferoffset.yOffset,
    475                  bufferoffset.cbcrOffset,bufferoffset.totalSize);
    476     OMX_SetParameter(pHandle, buffer_offset, &bufferoffset);
    477 
    478 
    479     if (encode_params->a_cbcroffset > 0) {
    480         ALOGV("Using acbcroffset\n");
    481         bufferoffset1.cbcrOffset = encode_params->a_cbcroffset;
    482         OMX_GetExtensionIndex(pHandle,"omx.qcom.jpeg.exttype.acbcr_offset",&buffer_offset);
    483         OMX_SetParameter(pHandle, buffer_offset, &bufferoffset1);
    484     }
    485 
    486     inputPort->format.image.nFrameWidth = encode_params->dimension->orig_picture_dx;
    487     inputPort->format.image.nFrameHeight = encode_params->dimension->orig_picture_dy;
    488     inputPort->format.image.nStride = encode_params->dimension->orig_picture_dx;
    489     inputPort->format.image.nSliceHeight = encode_params->dimension->orig_picture_dy;
    490     inputPort->nBufferSize = bufferoffset.totalSize;
    491 
    492     inputPort1->format.image.nFrameWidth =
    493       encode_params->dimension->thumbnail_width;
    494     inputPort1->format.image.nFrameHeight =
    495       encode_params->dimension->thumbnail_height;
    496     inputPort1->format.image.nStride =
    497       encode_params->dimension->thumbnail_width;
    498     inputPort1->format.image.nSliceHeight =
    499       encode_params->dimension->thumbnail_height;
    500 
    501     OMX_SetParameter(pHandle, OMX_IndexParamPortDefinition, inputPort);
    502     OMX_GetParameter(pHandle, OMX_IndexParamPortDefinition, inputPort);
    503     size = inputPort->nBufferSize;
    504     thumbnail.width = encode_params->dimension->thumbnail_width;
    505     thumbnail.height = encode_params->dimension->thumbnail_height;
    506 
    507     OMX_SetParameter(pHandle, OMX_IndexParamPortDefinition, inputPort1);
    508     OMX_GetParameter(pHandle, OMX_IndexParamPortDefinition, inputPort1);
    509     ALOGV("%s: thumbnail width %d height %d", __func__,
    510       encode_params->dimension->thumbnail_width,
    511       encode_params->dimension->thumbnail_height);
    512 
    513     if(encode_params->a_cbcroffset > 0)
    514         inputPort1->nBufferSize = inputPort->nBufferSize;
    515 
    516     userpreferences.color_format =
    517       get_jpeg_format_from_cam_format(encode_params->main_format);
    518     userpreferences.thumbnail_color_format =
    519       get_jpeg_format_from_cam_format(encode_params->thumbnail_format);
    520 
    521 
    522 
    523 
    524       ALOGV("%s:Scaling params in1_w %d in1_h %d out1_w %d out1_h %d"
    525                   "main_img in2_w %d in2_h %d out2_w %d out2_h %d\n", __func__,
    526       encode_params->scaling_params->in1_w,
    527       encode_params->scaling_params->in1_h,
    528       encode_params->scaling_params->out1_w,
    529       encode_params->scaling_params->out1_h,
    530       encode_params->scaling_params->in2_w,
    531       encode_params->scaling_params->in2_h,
    532       encode_params->scaling_params->out2_w,
    533       encode_params->scaling_params->out2_h);
    534    /*Main image scaling*/
    535     ALOGV("%s:%d/n",__func__,__LINE__);
    536 
    537 
    538     if (encode_params->scaling_params->in2_w &&
    539         encode_params->scaling_params->in2_h) {
    540 
    541       /* Scaler information  for main image */
    542         recttype.nWidth = CEILING2(encode_params->scaling_params->in2_w);
    543         recttype.nHeight = CEILING2(encode_params->scaling_params->in2_h);
    544         ALOGV("%s:%d/n",__func__,__LINE__);
    545 
    546         if (encode_params->main_crop_offset) {
    547             recttype.nLeft = encode_params->main_crop_offset->x;
    548             recttype.nTop = encode_params->main_crop_offset->y;
    549             ALOGV("%s:%d/n",__func__,__LINE__);
    550 
    551         } else {
    552             recttype.nLeft = 0;
    553             recttype.nTop = 0;
    554             ALOGV("%s:%d/n",__func__,__LINE__);
    555 
    556         }
    557         ALOGV("%s:%d/n",__func__,__LINE__);
    558 
    559         recttype.nPortIndex = 1;
    560         OMX_SetConfig(pHandle, OMX_IndexConfigCommonInputCrop, &recttype);
    561         ALOGV("%s:%d/n",__func__,__LINE__);
    562 
    563         if (encode_params->scaling_params->out2_w &&
    564             encode_params->scaling_params->out2_h) {
    565             recttype.nWidth = (encode_params->scaling_params->out2_w);
    566             recttype.nHeight = (encode_params->scaling_params->out2_h);
    567             ALOGV("%s:%d/n",__func__,__LINE__);
    568 
    569 
    570             recttype.nPortIndex = 1;
    571             OMX_SetConfig(pHandle, OMX_IndexConfigCommonOutputCrop, &recttype);
    572             ALOGV("%s:%d/n",__func__,__LINE__);
    573 
    574         }
    575 
    576     } else {
    577         ALOGV("%s: There is no main image scaling information",
    578           __func__);
    579     }
    580   /*case of thumbnail*/
    581 
    582     if ((encode_params->scaling_params->in1_w &&
    583         encode_params->scaling_params->in1_h) ||
    584         ((encode_params->scaling_params->out1_w !=
    585         encode_params->dimension->thumbnail_width) &&
    586         (encode_params->scaling_params->out1_h !=
    587         encode_params->dimension->thumbnail_height))) {
    588 
    589         thumbnail.scaling = 0;
    590 
    591         if ((encode_params->scaling_params->out1_w !=
    592             encode_params->dimension->thumbnail_width)&&
    593             (encode_params->scaling_params->out1_h !=
    594             encode_params->dimension->thumbnail_height)) {
    595 
    596             ALOGV("%s:%d/n",__func__,__LINE__);
    597             thumbnail.cropWidth = CEILING2(encode_params->dimension->thumbnail_width);
    598             thumbnail.cropHeight = CEILING2(encode_params->dimension->thumbnail_height);
    599         }
    600         if (encode_params->scaling_params->in1_w &&
    601             encode_params->scaling_params->in1_h) {
    602             ALOGV("%s:%d/n",__func__,__LINE__);
    603             thumbnail.cropWidth = CEILING2(encode_params->scaling_params->in1_w);
    604             thumbnail.cropHeight = CEILING2(encode_params->scaling_params->in1_h);
    605         }
    606         thumbnail.width  = encode_params->scaling_params->out1_w;
    607         thumbnail.height = encode_params->scaling_params->out1_h;
    608 
    609         if (encode_params->thumb_crop_offset) {
    610             ALOGV("%s:%d/n",__func__,__LINE__);
    611 
    612             thumbnail.left = encode_params->thumb_crop_offset->x;
    613             thumbnail.top = encode_params->thumb_crop_offset->y;
    614             thumbnail.scaling = 1;
    615         } else {
    616             thumbnail.left = 0;
    617             thumbnail.top = 0;
    618         }
    619     } else {
    620         thumbnail.scaling = 0;
    621         ALOGV("%s: There is no thumbnail scaling information",
    622           __func__);
    623     }
    624     OMX_GetExtensionIndex(pHandle,"omx.qcom.jpeg.exttype.user_preferences",
    625       &user_preferences);
    626     ALOGV("%s:User Preferences: color_format %d"
    627       "thumbnail_color_format = %d encoder preference =%d\n", __func__,
    628       userpreferences.color_format,userpreferences.thumbnail_color_format,
    629       userpreferences.preference);
    630     OMX_SetParameter(pHandle,user_preferences,&userpreferences);
    631 
    632     ALOGV("%s Thumbnail present? : %d ", __func__,
    633                  encode_params->hasThumbnail);
    634     if (encode_params->hasThumbnail) {
    635     OMX_GetExtensionIndex(pHandle, "omx.qcom.jpeg.exttype.thumbnail", &type);
    636     OMX_SetParameter(pHandle, type, &thumbnail);
    637     }
    638     qFactor.nPortIndex = INPUT_PORT;
    639     OMX_GetParameter(pHandle, OMX_IndexParamQFactor, &qFactor);
    640     qFactor.nQFactor = jpegMainimageQuality;
    641     OMX_SetParameter(pHandle, OMX_IndexParamQFactor, &qFactor);
    642 
    643     OMX_GetExtensionIndex(pHandle, "omx.qcom.jpeg.exttype.thumbnail_quality",
    644     &thumbnailQualityType);
    645 
    646     ALOGV("%s: thumbnail quality %u %d",
    647       __func__, thumbnailQualityType, jpegThumbnailQuality);
    648     OMX_GetParameter(pHandle, thumbnailQualityType, &thumbnailQuality);
    649     thumbnailQuality.nQFactor = jpegThumbnailQuality;
    650     OMX_SetParameter(pHandle, thumbnailQualityType, &thumbnailQuality);
    651     rotType.nPortIndex = OUTPUT_PORT;
    652     rotType.nRotation = jpegRotation;
    653     OMX_SetConfig(pHandle, OMX_IndexConfigCommonRotate, &rotType);
    654     ALOGV("Set rotation to %d\n",jpegRotation);
    655     OMX_GetExtensionIndex(pHandle, "omx.qcom.jpeg.exttype.exif", &exif);
    656 
    657     //Set omx parameter for all exif tags
    658     int i;
    659     for(i=0; i<encode_params->exif_numEntries; i++) {
    660         memcpy(&tag, encode_params->exif_data + i, sizeof(omx_jpeg_exif_info_tag));
    661         OMX_SetParameter(pHandle, exif, &tag);
    662     }
    663 
    664     pmem_info.fd = encode_params->snapshot_fd;
    665     pmem_info.offset = 0;
    666 
    667     ALOGV("input buffer size is %d",size);
    668     OMX_UseBuffer(pHandle, &pInBuffers, 0, &pmem_info, size,
    669     (void *) encode_params->snapshot_buf);
    670 
    671     pmem_info1.fd = encode_params->thumbnail_fd;
    672     pmem_info1.offset = 0;
    673 
    674     ALOGV("%s: input1 buff size %d", __func__, inputPort1->nBufferSize);
    675     OMX_UseBuffer(pHandle, &pInBuffers1, 2, &pmem_info1,
    676       inputPort1->nBufferSize, (void *) encode_params->thumbnail_buf);
    677 
    678 
    679     OMX_UseBuffer(pHandle, &pOutBuffers, 1, NULL, size, (void *) out_buffer);
    680 
    681     waitForEvent(OMX_EventCmdComplete, OMX_CommandStateSet, OMX_StateIdle);
    682     ALOGV("%s:State changed to OMX_StateIdle\n", __func__);
    683     OMX_SendCommand(pHandle, OMX_CommandStateSet, OMX_StateExecuting, NULL);
    684     waitForEvent(OMX_EventCmdComplete, OMX_CommandStateSet, OMX_StateExecuting);
    685 
    686     OMX_EmptyThisBuffer(pHandle, pInBuffers);
    687     OMX_EmptyThisBuffer(pHandle, pInBuffers1);
    688     OMX_FillThisBuffer(pHandle, pOutBuffers);
    689     pthread_mutex_unlock(&jpege_mutex);
    690     ALOGV("%s:X", __func__);
    691     return true;
    692 }
    693 
    694 void omxJpegFinish()
    695 {
    696     pthread_mutex_lock(&jpege_mutex);
    697     ALOGV("%s:encoding=%d", __func__, encoding);
    698     if (encoding) {
    699         encoding = 0;
    700         OMX_SendCommand(pHandle, OMX_CommandStateSet, OMX_StateIdle, NULL);
    701         OMX_SendCommand(pHandle, OMX_CommandStateSet, OMX_StateLoaded, NULL);
    702         OMX_FreeBuffer(pHandle, 0, pInBuffers);
    703         OMX_FreeBuffer(pHandle, 2, pInBuffers1);
    704         OMX_FreeBuffer(pHandle, 1, pOutBuffers);
    705         (*pOMX_Deinit)();
    706     }
    707     pthread_mutex_unlock(&jpege_mutex);
    708 }
    709 
    710 void omxJpegClose()
    711 {
    712     ALOGV("%s:", __func__);
    713     dlclose(libmmstillomx);
    714 }
    715 
    716 void omxJpegAbort()
    717 {
    718     pthread_mutex_lock(&jpegcb_mutex);
    719     mmcamera_jpegfragment_callback = NULL;
    720     mmcamera_jpeg_callback = NULL;
    721     user_data = NULL;
    722     pthread_mutex_unlock(&jpegcb_mutex);
    723     pthread_mutex_lock(&jpege_mutex);
    724     ALOGV("%s: encoding=%d", __func__, encoding);
    725     if (encoding) {
    726       encoding = 0;
    727       OMX_SendCommand(pHandle, OMX_CommandFlush, NULL, NULL);
    728       ALOGV("%s:waitForEvent: OMX_CommandFlush", __func__);
    729       waitForEvent(OMX_EVENT_JPEG_ABORT, 0, 0);
    730       ALOGV("%s:waitForEvent: OMX_CommandFlush: DONE", __func__);
    731       OMX_SendCommand(pHandle, OMX_CommandStateSet, OMX_StateIdle, NULL);
    732       OMX_SendCommand(pHandle, OMX_CommandStateSet, OMX_StateLoaded, NULL);
    733       OMX_FreeBuffer(pHandle, 0, pInBuffers);
    734       OMX_FreeBuffer(pHandle, 2, pInBuffers1);
    735       OMX_FreeBuffer(pHandle, 1, pOutBuffers);
    736       (*pOMX_Deinit)();
    737     }
    738     pthread_mutex_unlock(&jpege_mutex);
    739 }
    740 
    741 
    742 int8_t mm_jpeg_encoder_setMainImageQuality(uint32_t quality)
    743 {
    744     pthread_mutex_lock(&jpege_mutex);
    745     ALOGV("%s: current main inage quality %d ," \
    746     " new quality : %d\n", __func__, jpegMainimageQuality, quality);
    747     if (quality <= 100)
    748         jpegMainimageQuality = quality;
    749     pthread_mutex_unlock(&jpege_mutex);
    750     return true;
    751 }
    752 
    753 int8_t mm_jpeg_encoder_setThumbnailQuality(uint32_t quality)
    754 {
    755     pthread_mutex_lock(&jpege_mutex);
    756     ALOGV("%s: current thumbnail quality %d ," \
    757     " new quality : %d\n", __func__, jpegThumbnailQuality, quality);
    758     if (quality <= 100)
    759         jpegThumbnailQuality = quality;
    760     pthread_mutex_unlock(&jpege_mutex);
    761     return true;
    762 }
    763 
    764 int8_t mm_jpeg_encoder_setRotation(int rotation, int isZSL)
    765 {
    766     pthread_mutex_lock(&jpege_mutex);
    767 
    768     /*Set ZSL Mode*/
    769     isZSLMode = isZSL;
    770     ALOGV("%s: Setting ZSL Mode to %d Rotation = %d\n",__func__,isZSLMode,rotation);
    771     /* Set rotation configuration */
    772     switch (rotation) {
    773     case 0:
    774     case 90:
    775     case 180:
    776     case 270:
    777         jpegRotation = rotation;
    778         break;
    779     default:
    780         /* Invalid rotation mode, set to default */
    781         ALOGV("%s:Setting Default rotation mode", __func__);
    782         jpegRotation = 0;
    783         break;
    784     }
    785     pthread_mutex_unlock(&jpege_mutex);
    786     return true;
    787 }
    788 
    789 /*===========================================================================
    790 FUNCTION      mm_jpege_set_phy_offset
    791 
    792 DESCRIPTION   Set physical offset for the buffer
    793 ===========================================================================*/
    794 void mm_jpege_set_phy_offset(uint32_t a_phy_offset)
    795 {
    796     phy_offset = a_phy_offset;
    797 }
    798