| /* Copyright (c) 2012, Code Aurora Forum. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following |
| * disclaimer in the documentation and/or other materials provided |
| * with the distribution. |
| * * Neither the name of Code Aurora Forum, Inc. nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
| * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
| * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
| * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include <sys/types.h> |
| #include <stdbool.h> |
| #include <fcntl.h> |
| #include <dlfcn.h> |
| #include "OMX_Types.h" |
| #include "OMX_Index.h" |
| #include "OMX_Core.h" |
| #include "OMX_Component.h" |
| #include "omx_debug.h" |
| #include "omx_jpeg_ext.h" |
| #include "mm_omx_jpeg_encoder.h" |
| |
| static uint8_t hw_encode = true; |
| static int jpegRotation = 0; |
| static int isZSLMode = 0; |
| static int jpegThumbnailQuality = 75; |
| static int jpegMainimageQuality = 85; |
| static uint32_t phy_offset; |
| void *user_data; |
| |
| static int encoding = 0; |
| pthread_mutex_t jpege_mutex = PTHREAD_MUTEX_INITIALIZER; |
| pthread_mutex_t jpegcb_mutex = PTHREAD_MUTEX_INITIALIZER; |
| |
| jpegfragment_callback_t mmcamera_jpegfragment_callback; |
| jpeg_callback_t mmcamera_jpeg_callback; |
| |
| |
| #define INPUT_PORT 0 |
| #define OUTPUT_PORT 1 |
| #define INPUT_PORT1 2 |
| #define DEFAULT_COLOR_FORMAT YCRCBLP_H2V2 |
| |
| typedef struct { |
| cam_format_t isp_format; |
| jpeg_color_format_t jpg_format; |
| } color_format_map_t; |
| |
| |
| static const color_format_map_t color_format_map[] = { |
| {CAMERA_YUV_420_NV21, YCRCBLP_H2V2}, /*default*/ |
| {CAMERA_YUV_420_NV21_ADRENO, YCRCBLP_H2V2}, |
| {CAMERA_YUV_420_NV12, YCBCRLP_H2V2}, |
| {CAMERA_YUV_420_YV12, YCBCRLP_H2V2}, |
| {CAMERA_YUV_422_NV61, YCRCBLP_H2V1}, |
| {CAMERA_YUV_422_NV16, YCBCRLP_H2V1}, |
| }; |
| |
| static OMX_HANDLETYPE pHandle; |
| static OMX_CALLBACKTYPE callbacks; |
| static OMX_INDEXTYPE type; |
| static OMX_CONFIG_ROTATIONTYPE rotType; |
| static omx_jpeg_thumbnail thumbnail; |
| static OMX_CONFIG_RECTTYPE recttype; |
| static OMX_PARAM_PORTDEFINITIONTYPE * inputPort; |
| static OMX_PARAM_PORTDEFINITIONTYPE * outputPort; |
| static OMX_PARAM_PORTDEFINITIONTYPE * inputPort1; |
| static OMX_BUFFERHEADERTYPE* pInBuffers; |
| static OMX_BUFFERHEADERTYPE* pOutBuffers; |
| static OMX_BUFFERHEADERTYPE* pInBuffers1; |
| OMX_INDEXTYPE user_preferences; |
| omx_jpeg_user_preferences userpreferences; |
| OMX_INDEXTYPE exif; |
| static omx_jpeg_exif_info_tag tag; |
| |
| static void *libmmstillomx; |
| OMX_ERRORTYPE OMX_APIENTRY (*pOMX_GetHandle)( |
| OMX_OUT OMX_HANDLETYPE* pHandle, |
| OMX_IN OMX_STRING cComponentName, |
| OMX_IN OMX_PTR pAppData, |
| OMX_IN OMX_CALLBACKTYPE* pCallBacks); |
| OMX_ERRORTYPE OMX_APIENTRY (*pOMX_Init)(void); |
| OMX_ERRORTYPE OMX_APIENTRY (*pOMX_Deinit)(void); |
| |
| static pthread_mutex_t lock; |
| static pthread_cond_t cond; |
| static int expectedEvent = 0; |
| static int expectedValue1 = 0; |
| static int expectedValue2 = 0; |
| static omx_jpeg_pmem_info pmem_info; |
| static omx_jpeg_pmem_info pmem_info1; |
| static OMX_IMAGE_PARAM_QFACTORTYPE qFactor; |
| static omx_jpeg_thumbnail_quality thumbnailQuality; |
| static OMX_INDEXTYPE thumbnailQualityType; |
| static void *out_buffer; |
| static int * out_buffer_size; |
| static OMX_INDEXTYPE buffer_offset; |
| static omx_jpeg_buffer_offset bufferoffset; |
| |
| static jpeg_color_format_t get_jpeg_format_from_cam_format( |
| cam_format_t cam_format ) |
| { |
| jpeg_color_format_t jpg_format = DEFAULT_COLOR_FORMAT; |
| int i, j; |
| j = sizeof (color_format_map) / sizeof(color_format_map_t); |
| ALOGV("%s: j =%d, cam_format =%d", __func__, j, cam_format); |
| for(i =0; i< j; i++) { |
| if (color_format_map[i].isp_format == cam_format){ |
| jpg_format = color_format_map[i].jpg_format; |
| break; |
| } |
| } |
| ALOGV("%s x: i =%d, jpg_format=%d", __func__, i, jpg_format); |
| |
| return jpg_format; |
| } |
| static omx_jpeg_buffer_offset bufferoffset1; |
| void set_callbacks( |
| jpegfragment_callback_t fragcallback, |
| jpeg_callback_t eventcallback, void* userdata, |
| void* output_buffer, |
| int * outBufferSize) { |
| pthread_mutex_lock(&jpegcb_mutex); |
| mmcamera_jpegfragment_callback = fragcallback; |
| mmcamera_jpeg_callback = eventcallback; |
| user_data = userdata; |
| out_buffer = output_buffer; |
| out_buffer_size = outBufferSize; |
| pthread_mutex_unlock(&jpegcb_mutex); |
| } |
| |
| |
| OMX_ERRORTYPE etbdone(OMX_OUT OMX_HANDLETYPE hComponent, |
| OMX_OUT OMX_PTR pAppData, |
| OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer) |
| { |
| pthread_mutex_lock(&lock); |
| expectedEvent = OMX_EVENT_ETB_DONE; |
| expectedValue1 = 0; |
| expectedValue2 = 0; |
| pthread_cond_signal(&cond); |
| pthread_mutex_unlock(&lock); |
| return 0; |
| } |
| |
| OMX_ERRORTYPE ftbdone(OMX_OUT OMX_HANDLETYPE hComponent, |
| OMX_OUT OMX_PTR pAppData, |
| OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer) |
| { |
| ALOGV("%s", __func__); |
| *out_buffer_size = pBuffer->nFilledLen; |
| pthread_mutex_lock(&lock); |
| expectedEvent = OMX_EVENT_FTB_DONE; |
| expectedValue1 = 0; |
| expectedValue2 = 0; |
| pthread_cond_signal(&cond); |
| pthread_mutex_unlock(&lock); |
| ALOGV("%s:filled len = %u", __func__, (uint32_t)pBuffer->nFilledLen); |
| if (mmcamera_jpeg_callback && encoding) |
| mmcamera_jpeg_callback(0, user_data); |
| return 0; |
| } |
| |
| OMX_ERRORTYPE handleError(OMX_IN OMX_EVENTTYPE eEvent, OMX_IN OMX_U32 error) |
| { |
| ALOGV("%s", __func__); |
| if (error == OMX_EVENT_JPEG_ERROR) { |
| if (mmcamera_jpeg_callback && encoding) { |
| ALOGV("%s:OMX_EVENT_JPEG_ERROR\n", __func__); |
| mmcamera_jpeg_callback(JPEG_EVENT_ERROR, user_data); |
| } |
| } else if (error == OMX_EVENT_THUMBNAIL_DROPPED) { |
| if (mmcamera_jpeg_callback && encoding) { |
| ALOGV("%s:(OMX_EVENT_THUMBNAIL_DROPPED\n", __func__); |
| mmcamera_jpeg_callback(JPEG_EVENT_THUMBNAIL_DROPPED, user_data); |
| } |
| } |
| return 0; |
| } |
| |
| OMX_ERRORTYPE eventHandler( OMX_IN OMX_HANDLETYPE hComponent, |
| OMX_IN OMX_PTR pAppData, OMX_IN OMX_EVENTTYPE eEvent, |
| OMX_IN OMX_U32 nData1, OMX_IN OMX_U32 nData2, |
| OMX_IN OMX_PTR pEventData) |
| { |
| ALOGV("%s", __func__); |
| ALOGV("%s:got event %d ndata1 %u ndata2 %u", __func__, |
| eEvent, nData1, nData2); |
| pthread_mutex_lock(&lock); |
| expectedEvent = eEvent; |
| expectedValue1 = nData1; |
| expectedValue2 = nData2; |
| pthread_cond_signal(&cond); |
| pthread_mutex_unlock(&lock); |
| if ((nData1== OMX_EVENT_JPEG_ERROR)||(nData1== OMX_EVENT_THUMBNAIL_DROPPED)) |
| handleError(eEvent,nData1); |
| return 0; |
| } |
| |
| void waitForEvent(int event, int value1, int value2 ){ |
| pthread_mutex_lock(&lock); |
| ALOGV("%s:Waiting for:event=%d, value1=%d, value2=%d", |
| __func__, event, value1, value2); |
| while (! (expectedEvent == event && |
| expectedValue1 == value1 && expectedValue2 == value2)) { |
| pthread_cond_wait(&cond, &lock); |
| ALOGV("%s:After cond_wait:expectedEvent=%d, expectedValue1=%d, expectedValue2=%d", |
| __func__, expectedEvent, expectedValue1, expectedValue2); |
| ALOGV("%s:After cond_wait:event=%d, value1=%d, value2=%d", |
| __func__, event, value1, value2); |
| } |
| ALOGV("%s:done:expectedEvent=%d, expectedValue1=%d, expectedValue2=%d", |
| __func__, expectedEvent, expectedValue1, expectedValue2); |
| pthread_mutex_unlock(&lock); |
| } |
| |
| int8_t mm_jpeg_encoder_get_buffer_offset(uint32_t width, uint32_t height, |
| uint32_t* p_y_offset, uint32_t* p_cbcr_offset, uint32_t* p_buf_size, |
| uint8_t *num_planes, uint32_t planes[]) |
| { |
| ALOGV("%s:", __func__); |
| if ((NULL == p_y_offset) || (NULL == p_cbcr_offset)) { |
| return false; |
| } |
| *num_planes = 2; |
| if (hw_encode ) { |
| int cbcr_offset = 0; |
| uint32_t actual_size = width*height; |
| uint32_t padded_size = width * CEILING16(height); |
| *p_y_offset = 0; |
| *p_cbcr_offset = 0; |
| //if(!isZSLMode){ |
| if ((jpegRotation == 90) || (jpegRotation == 180)) { |
| *p_y_offset = padded_size - actual_size; |
| *p_cbcr_offset = ((padded_size - actual_size) >> 1); |
| } |
| *p_buf_size = (padded_size + (padded_size - actual_size)) * 3/2; |
| planes[0] = width * CEILING16(height); |
| planes[1] = width * CEILING16(height)/2; |
| } else { |
| *p_y_offset = 0; |
| *p_cbcr_offset = PAD_TO_WORD(width*height); |
| *p_buf_size = *p_cbcr_offset * 3/2; |
| planes[0] = PAD_TO_WORD(width*CEILING16(height)); |
| planes[1] = PAD_TO_WORD(width*CEILING16(height)/2); |
| } |
| return true; |
| } |
| |
| int8_t omxJpegOpen() |
| { |
| ALOGV("%s", __func__); |
| pthread_mutex_lock(&jpege_mutex); |
| libmmstillomx = dlopen("libmmstillomx.so", RTLD_NOW); |
| if (!libmmstillomx) { |
| ALOGE("%s: dlopen failed", __func__); |
| pthread_mutex_unlock(&jpege_mutex); |
| return false; |
| } |
| *(void **)(&pOMX_GetHandle) = dlsym(libmmstillomx, "OMX_GetHandle"); |
| *(void **)(&pOMX_Init) = dlsym(libmmstillomx, "OMX_Init"); |
| *(void **)(&pOMX_Deinit) = dlsym(libmmstillomx, "OMX_Deinit"); |
| if (!pOMX_GetHandle || !pOMX_Init || !pOMX_Deinit) { |
| ALOGE("%s: dlsym failed", __func__); |
| dlclose(libmmstillomx); |
| pthread_mutex_unlock(&jpege_mutex); |
| return false; |
| } |
| OMX_ERRORTYPE ret = (*pOMX_GetHandle)(&pHandle, "OMX.qcom.image.jpeg.encoder", |
| NULL, &callbacks); |
| pthread_mutex_unlock(&jpege_mutex); |
| return true; |
| } |
| |
| int8_t omxJpegStart(uint8_t hw_encode_enable) |
| { |
| int rc = 0; |
| ALOGV("%s", __func__); |
| pthread_mutex_lock(&jpege_mutex); |
| hw_encode = hw_encode_enable; |
| callbacks.EmptyBufferDone = etbdone; |
| callbacks.FillBufferDone = ftbdone; |
| callbacks.EventHandler = eventHandler; |
| pthread_mutex_init(&lock, NULL); |
| pthread_cond_init(&cond, NULL); |
| rc = (*pOMX_Init)(); |
| pthread_mutex_unlock(&jpege_mutex); |
| return rc; |
| } |
| |
| static omx_jpeg_color_format format_cam2jpeg(cam_format_t fmt) |
| { |
| omx_jpeg_color_format jpeg_fmt = OMX_YCRCBLP_H2V2; |
| switch (fmt) { |
| case CAMERA_YUV_420_NV12: |
| jpeg_fmt = OMX_YCBCRLP_H2V2; |
| break; |
| case CAMERA_YUV_420_NV21: |
| case CAMERA_YUV_420_NV21_ADRENO: |
| jpeg_fmt = OMX_YCRCBLP_H2V2; |
| break; |
| default: |
| ALOGV("Camera format %d not supported", fmt); |
| break; |
| } |
| return jpeg_fmt; |
| } |
| |
| int8_t omxJpegEncodeNext(omx_jpeg_encode_params *encode_params) |
| { |
| ALOGV("%s:E", __func__); |
| pthread_mutex_lock(&jpege_mutex); |
| encoding = 1; |
| int orientation; |
| if(inputPort == NULL || inputPort1 == NULL || outputPort == NULL) { |
| ALOGV("%s:pointer is null: X", __func__); |
| pthread_mutex_unlock(&jpege_mutex); |
| return -1; |
| } |
| inputPort->nPortIndex = INPUT_PORT; |
| outputPort->nPortIndex = OUTPUT_PORT; |
| inputPort1->nPortIndex = INPUT_PORT1; |
| OMX_GetParameter(pHandle, OMX_IndexParamPortDefinition, inputPort); |
| OMX_GetParameter(pHandle, OMX_IndexParamPortDefinition, outputPort); |
| |
| ALOGV("%s:nFrameWidth=%d nFrameHeight=%d nBufferSize=%d w=%d h=%d", |
| __func__, inputPort->format.image.nFrameWidth, |
| inputPort->format.image.nFrameHeight, inputPort->nBufferSize, |
| bufferoffset.width, bufferoffset.height); |
| OMX_GetExtensionIndex(pHandle,"omx.qcom.jpeg.exttype.buffer_offset", |
| &buffer_offset); |
| ALOGV("%s:Buffer w %d h %d yOffset %d cbcrOffset %d totalSize %d\n", |
| __func__, bufferoffset.width, bufferoffset.height, bufferoffset.yOffset, |
| bufferoffset.cbcrOffset,bufferoffset.totalSize); |
| OMX_SetParameter(pHandle, buffer_offset, &bufferoffset); |
| OMX_SetParameter(pHandle, OMX_IndexParamPortDefinition, inputPort1); |
| OMX_GetParameter(pHandle, OMX_IndexParamPortDefinition, inputPort1); |
| ALOGV("%s: thumbnail widht %d height %d", __func__, |
| thumbnail.width, thumbnail.height); |
| |
| userpreferences.color_format = |
| format_cam2jpeg(encode_params->dimension->main_img_format); |
| userpreferences.thumbnail_color_format = |
| format_cam2jpeg(encode_params->dimension->thumb_format); |
| |
| |
| pmem_info.fd = encode_params->snapshot_fd; |
| pmem_info.offset = 0; |
| |
| //Release previously allocated buffers before doing UseBuffer in burst mode |
| OMX_FreeBuffer(pHandle, 2, pInBuffers1); |
| OMX_FreeBuffer(pHandle, 0, pInBuffers); |
| OMX_FreeBuffer(pHandle, 1, pOutBuffers); |
| |
| OMX_UseBuffer(pHandle, &pInBuffers, 0, &pmem_info, inputPort->nBufferSize, |
| (void *) encode_params->snapshot_buf); |
| OMX_GetExtensionIndex(pHandle, "omx.qcom.jpeg.exttype.exif", &exif); |
| /*temporarily set rotation in EXIF data. This is done to avoid |
| image corruption issues in ZSL mode since roation is known |
| before hand. The orientation is set in the exif tag and |
| decoder will decode it will the right orientation. need to add double |
| padding to fix the issue */ |
| if (isZSLMode) { |
| /*Get the orientation tag values depending on rotation*/ |
| switch (jpegRotation) { |
| case 0: |
| orientation = 1; /*Normal*/ |
| break; |
| case 90: |
| orientation = 6; /*Rotated 90 CCW*/ |
| break; |
| case 180: |
| orientation = 3; /*Rotated 180*/ |
| break; |
| case 270: |
| orientation = 8; /*Rotated 90 CW*/ |
| break; |
| default: |
| orientation = 1; |
| break; |
| } |
| tag.tag_id = EXIFTAGID_ORIENTATION; |
| tag.tag_entry.type = EXIFTAGTYPE_ORIENTATION; |
| tag.tag_entry.count = 1; |
| tag.tag_entry.copy = 1; |
| tag.tag_entry.data._short = orientation; |
| ALOGV("%s jpegRotation = %d , orientation value =%d\n", __func__, |
| jpegRotation, orientation); |
| OMX_SetParameter(pHandle, exif, &tag); |
| } |
| |
| /*Set omx parameter for all exif tags*/ |
| int i; |
| for (i = 0; i < encode_params->exif_numEntries; i++) { |
| memcpy(&tag, encode_params->exif_data + i, |
| sizeof(omx_jpeg_exif_info_tag)); |
| OMX_SetParameter(pHandle, exif, &tag); |
| } |
| |
| pmem_info1.fd = encode_params->thumbnail_fd; |
| pmem_info1.offset = 0; |
| |
| ALOGV("%s: input1 buff size %d", __func__, inputPort1->nBufferSize); |
| OMX_UseBuffer(pHandle, &pInBuffers1, 2, &pmem_info1, |
| inputPort1->nBufferSize, (void *) encode_params->thumbnail_buf); |
| OMX_UseBuffer(pHandle, &pOutBuffers, 1, NULL, inputPort->nBufferSize, |
| (void *) out_buffer); |
| OMX_EmptyThisBuffer(pHandle, pInBuffers); |
| OMX_EmptyThisBuffer(pHandle, pInBuffers1); |
| OMX_FillThisBuffer(pHandle, pOutBuffers); |
| pthread_mutex_unlock(&jpege_mutex); |
| ALOGV("%s:X", __func__); |
| return true; |
| } |
| |
| int8_t omxJpegEncode(omx_jpeg_encode_params *encode_params) |
| { |
| int size = 0; |
| uint8_t num_planes; |
| uint32_t planes[10]; |
| int orientation; |
| ALOGV("%s:E", __func__); |
| |
| inputPort = malloc(sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); |
| outputPort = malloc(sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); |
| inputPort1 = malloc(sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); |
| |
| pthread_mutex_lock(&jpege_mutex); |
| encoding = 1; |
| inputPort->nPortIndex = INPUT_PORT; |
| outputPort->nPortIndex = OUTPUT_PORT; |
| inputPort1->nPortIndex = INPUT_PORT1; |
| OMX_GetParameter(pHandle, OMX_IndexParamPortDefinition, inputPort); |
| OMX_GetParameter(pHandle, OMX_IndexParamPortDefinition, outputPort); |
| |
| bufferoffset.width = encode_params->dimension->orig_picture_dx; |
| bufferoffset.height = encode_params->dimension->orig_picture_dy; |
| |
| if (hw_encode) |
| userpreferences.preference = OMX_JPEG_PREF_HW_ACCELERATED_PREFERRED; |
| else |
| userpreferences.preference = OMX_JPEG_PREF_SOFTWARE_ONLY; |
| if (encode_params->a_cbcroffset > 0) { |
| userpreferences.preference = OMX_JPEG_PREF_SOFTWARE_ONLY; |
| hw_encode = 0; |
| } |
| if (encode_params->scaling_params->in2_w && |
| encode_params->scaling_params->in2_h) { |
| if (jpegRotation) { |
| userpreferences.preference = OMX_JPEG_PREF_SOFTWARE_ONLY; |
| ALOGV("%s:Scaling and roation true: setting pref to sw\n", |
| __func__); |
| hw_encode = 0; |
| } |
| } |
| mm_jpeg_encoder_get_buffer_offset(bufferoffset.width, bufferoffset.height, |
| &bufferoffset.yOffset, |
| &bufferoffset.cbcrOffset, |
| &bufferoffset.totalSize, &num_planes, planes); |
| if (encode_params->a_cbcroffset > 0) { |
| bufferoffset.totalSize = encode_params->a_cbcroffset * 1.5; |
| } |
| OMX_GetExtensionIndex(pHandle,"omx.qcom.jpeg.exttype.buffer_offset",&buffer_offset); |
| ALOGV(" Buffer width = %d, Buffer height = %d, yOffset =%d, cbcrOffset =%d, totalSize = %d\n", |
| bufferoffset.width, bufferoffset.height, bufferoffset.yOffset, |
| bufferoffset.cbcrOffset,bufferoffset.totalSize); |
| OMX_SetParameter(pHandle, buffer_offset, &bufferoffset); |
| |
| |
| if (encode_params->a_cbcroffset > 0) { |
| ALOGV("Using acbcroffset\n"); |
| bufferoffset1.cbcrOffset = encode_params->a_cbcroffset; |
| OMX_GetExtensionIndex(pHandle,"omx.qcom.jpeg.exttype.acbcr_offset",&buffer_offset); |
| OMX_SetParameter(pHandle, buffer_offset, &bufferoffset1); |
| } |
| |
| inputPort->format.image.nFrameWidth = encode_params->dimension->orig_picture_dx; |
| inputPort->format.image.nFrameHeight = encode_params->dimension->orig_picture_dy; |
| inputPort->format.image.nStride = encode_params->dimension->orig_picture_dx; |
| inputPort->format.image.nSliceHeight = encode_params->dimension->orig_picture_dy; |
| inputPort->nBufferSize = bufferoffset.totalSize; |
| |
| inputPort1->format.image.nFrameWidth = |
| encode_params->dimension->thumbnail_width; |
| inputPort1->format.image.nFrameHeight = |
| encode_params->dimension->thumbnail_height; |
| inputPort1->format.image.nStride = |
| encode_params->dimension->thumbnail_width; |
| inputPort1->format.image.nSliceHeight = |
| encode_params->dimension->thumbnail_height; |
| |
| OMX_SetParameter(pHandle, OMX_IndexParamPortDefinition, inputPort); |
| OMX_GetParameter(pHandle, OMX_IndexParamPortDefinition, inputPort); |
| size = inputPort->nBufferSize; |
| thumbnail.width = encode_params->dimension->thumbnail_width; |
| thumbnail.height = encode_params->dimension->thumbnail_height; |
| |
| OMX_SetParameter(pHandle, OMX_IndexParamPortDefinition, inputPort1); |
| OMX_GetParameter(pHandle, OMX_IndexParamPortDefinition, inputPort1); |
| ALOGV("%s: thumbnail width %d height %d", __func__, |
| encode_params->dimension->thumbnail_width, |
| encode_params->dimension->thumbnail_height); |
| |
| if(encode_params->a_cbcroffset > 0) |
| inputPort1->nBufferSize = inputPort->nBufferSize; |
| |
| userpreferences.color_format = |
| get_jpeg_format_from_cam_format(encode_params->main_format); |
| userpreferences.thumbnail_color_format = |
| get_jpeg_format_from_cam_format(encode_params->thumbnail_format); |
| |
| |
| |
| |
| ALOGV("%s:Scaling params in1_w %d in1_h %d out1_w %d out1_h %d" |
| "main_img in2_w %d in2_h %d out2_w %d out2_h %d\n", __func__, |
| encode_params->scaling_params->in1_w, |
| encode_params->scaling_params->in1_h, |
| encode_params->scaling_params->out1_w, |
| encode_params->scaling_params->out1_h, |
| encode_params->scaling_params->in2_w, |
| encode_params->scaling_params->in2_h, |
| encode_params->scaling_params->out2_w, |
| encode_params->scaling_params->out2_h); |
| /*Main image scaling*/ |
| ALOGV("%s:%d/n",__func__,__LINE__); |
| |
| |
| if (encode_params->scaling_params->in2_w && |
| encode_params->scaling_params->in2_h) { |
| |
| /* Scaler information for main image */ |
| recttype.nWidth = CEILING2(encode_params->scaling_params->in2_w); |
| recttype.nHeight = CEILING2(encode_params->scaling_params->in2_h); |
| ALOGV("%s:%d/n",__func__,__LINE__); |
| |
| if (encode_params->main_crop_offset) { |
| recttype.nLeft = encode_params->main_crop_offset->x; |
| recttype.nTop = encode_params->main_crop_offset->y; |
| ALOGV("%s:%d/n",__func__,__LINE__); |
| |
| } else { |
| recttype.nLeft = 0; |
| recttype.nTop = 0; |
| ALOGV("%s:%d/n",__func__,__LINE__); |
| |
| } |
| ALOGV("%s:%d/n",__func__,__LINE__); |
| |
| recttype.nPortIndex = 1; |
| OMX_SetConfig(pHandle, OMX_IndexConfigCommonInputCrop, &recttype); |
| ALOGV("%s:%d/n",__func__,__LINE__); |
| |
| if (encode_params->scaling_params->out2_w && |
| encode_params->scaling_params->out2_h) { |
| recttype.nWidth = (encode_params->scaling_params->out2_w); |
| recttype.nHeight = (encode_params->scaling_params->out2_h); |
| ALOGV("%s:%d/n",__func__,__LINE__); |
| |
| |
| recttype.nPortIndex = 1; |
| OMX_SetConfig(pHandle, OMX_IndexConfigCommonOutputCrop, &recttype); |
| ALOGV("%s:%d/n",__func__,__LINE__); |
| |
| } |
| |
| } else { |
| ALOGV("%s: There is no main image scaling information", |
| __func__); |
| } |
| /*case of thumbnail*/ |
| |
| if ((encode_params->scaling_params->in1_w && |
| encode_params->scaling_params->in1_h) || |
| ((encode_params->scaling_params->out1_w != |
| encode_params->dimension->thumbnail_width) && |
| (encode_params->scaling_params->out1_h != |
| encode_params->dimension->thumbnail_height))) { |
| |
| thumbnail.scaling = 0; |
| |
| if ((encode_params->scaling_params->out1_w != |
| encode_params->dimension->thumbnail_width)&& |
| (encode_params->scaling_params->out1_h != |
| encode_params->dimension->thumbnail_height)) { |
| |
| ALOGV("%s:%d/n",__func__,__LINE__); |
| thumbnail.cropWidth = CEILING2(encode_params->dimension->thumbnail_width); |
| thumbnail.cropHeight = CEILING2(encode_params->dimension->thumbnail_height); |
| } |
| if (encode_params->scaling_params->in1_w && |
| encode_params->scaling_params->in1_h) { |
| ALOGV("%s:%d/n",__func__,__LINE__); |
| thumbnail.cropWidth = CEILING2(encode_params->scaling_params->in1_w); |
| thumbnail.cropHeight = CEILING2(encode_params->scaling_params->in1_h); |
| } |
| thumbnail.width = encode_params->scaling_params->out1_w; |
| thumbnail.height = encode_params->scaling_params->out1_h; |
| |
| if (encode_params->thumb_crop_offset) { |
| ALOGV("%s:%d/n",__func__,__LINE__); |
| |
| thumbnail.left = encode_params->thumb_crop_offset->x; |
| thumbnail.top = encode_params->thumb_crop_offset->y; |
| thumbnail.scaling = 1; |
| } else { |
| thumbnail.left = 0; |
| thumbnail.top = 0; |
| } |
| } else { |
| thumbnail.scaling = 0; |
| ALOGV("%s: There is no thumbnail scaling information", |
| __func__); |
| } |
| OMX_GetExtensionIndex(pHandle,"omx.qcom.jpeg.exttype.user_preferences", |
| &user_preferences); |
| ALOGV("%s:User Preferences: color_format %d" |
| "thumbnail_color_format = %d encoder preference =%d\n", __func__, |
| userpreferences.color_format,userpreferences.thumbnail_color_format, |
| userpreferences.preference); |
| OMX_SetParameter(pHandle,user_preferences,&userpreferences); |
| |
| ALOGV("%s Thumbnail present? : %d ", __func__, |
| encode_params->hasThumbnail); |
| if (encode_params->hasThumbnail) { |
| OMX_GetExtensionIndex(pHandle, "omx.qcom.jpeg.exttype.thumbnail", &type); |
| OMX_SetParameter(pHandle, type, &thumbnail); |
| } |
| qFactor.nPortIndex = INPUT_PORT; |
| OMX_GetParameter(pHandle, OMX_IndexParamQFactor, &qFactor); |
| qFactor.nQFactor = jpegMainimageQuality; |
| OMX_SetParameter(pHandle, OMX_IndexParamQFactor, &qFactor); |
| |
| OMX_GetExtensionIndex(pHandle, "omx.qcom.jpeg.exttype.thumbnail_quality", |
| &thumbnailQualityType); |
| |
| ALOGV("%s: thumbnail quality %u %d", |
| __func__, thumbnailQualityType, jpegThumbnailQuality); |
| OMX_GetParameter(pHandle, thumbnailQualityType, &thumbnailQuality); |
| thumbnailQuality.nQFactor = jpegThumbnailQuality; |
| OMX_SetParameter(pHandle, thumbnailQualityType, &thumbnailQuality); |
| rotType.nPortIndex = OUTPUT_PORT; |
| rotType.nRotation = jpegRotation; |
| OMX_SetConfig(pHandle, OMX_IndexConfigCommonRotate, &rotType); |
| ALOGV("Set rotation to %d\n",jpegRotation); |
| OMX_GetExtensionIndex(pHandle, "omx.qcom.jpeg.exttype.exif", &exif); |
| |
| //Set omx parameter for all exif tags |
| int i; |
| for(i=0; i<encode_params->exif_numEntries; i++) { |
| memcpy(&tag, encode_params->exif_data + i, sizeof(omx_jpeg_exif_info_tag)); |
| OMX_SetParameter(pHandle, exif, &tag); |
| } |
| |
| pmem_info.fd = encode_params->snapshot_fd; |
| pmem_info.offset = 0; |
| |
| ALOGV("input buffer size is %d",size); |
| OMX_UseBuffer(pHandle, &pInBuffers, 0, &pmem_info, size, |
| (void *) encode_params->snapshot_buf); |
| |
| pmem_info1.fd = encode_params->thumbnail_fd; |
| pmem_info1.offset = 0; |
| |
| ALOGV("%s: input1 buff size %d", __func__, inputPort1->nBufferSize); |
| OMX_UseBuffer(pHandle, &pInBuffers1, 2, &pmem_info1, |
| inputPort1->nBufferSize, (void *) encode_params->thumbnail_buf); |
| |
| |
| OMX_UseBuffer(pHandle, &pOutBuffers, 1, NULL, size, (void *) out_buffer); |
| |
| waitForEvent(OMX_EventCmdComplete, OMX_CommandStateSet, OMX_StateIdle); |
| ALOGV("%s:State changed to OMX_StateIdle\n", __func__); |
| OMX_SendCommand(pHandle, OMX_CommandStateSet, OMX_StateExecuting, NULL); |
| waitForEvent(OMX_EventCmdComplete, OMX_CommandStateSet, OMX_StateExecuting); |
| |
| OMX_EmptyThisBuffer(pHandle, pInBuffers); |
| OMX_EmptyThisBuffer(pHandle, pInBuffers1); |
| OMX_FillThisBuffer(pHandle, pOutBuffers); |
| pthread_mutex_unlock(&jpege_mutex); |
| ALOGV("%s:X", __func__); |
| return true; |
| } |
| |
| void omxJpegFinish() |
| { |
| pthread_mutex_lock(&jpege_mutex); |
| ALOGV("%s:encoding=%d", __func__, encoding); |
| if (encoding) { |
| encoding = 0; |
| OMX_SendCommand(pHandle, OMX_CommandStateSet, OMX_StateIdle, NULL); |
| OMX_SendCommand(pHandle, OMX_CommandStateSet, OMX_StateLoaded, NULL); |
| OMX_FreeBuffer(pHandle, 0, pInBuffers); |
| OMX_FreeBuffer(pHandle, 2, pInBuffers1); |
| OMX_FreeBuffer(pHandle, 1, pOutBuffers); |
| (*pOMX_Deinit)(); |
| } |
| pthread_mutex_unlock(&jpege_mutex); |
| } |
| |
| void omxJpegClose() |
| { |
| ALOGV("%s:", __func__); |
| dlclose(libmmstillomx); |
| } |
| |
| void omxJpegAbort() |
| { |
| pthread_mutex_lock(&jpegcb_mutex); |
| mmcamera_jpegfragment_callback = NULL; |
| mmcamera_jpeg_callback = NULL; |
| user_data = NULL; |
| pthread_mutex_unlock(&jpegcb_mutex); |
| pthread_mutex_lock(&jpege_mutex); |
| ALOGV("%s: encoding=%d", __func__, encoding); |
| if (encoding) { |
| encoding = 0; |
| OMX_SendCommand(pHandle, OMX_CommandFlush, NULL, NULL); |
| ALOGV("%s:waitForEvent: OMX_CommandFlush", __func__); |
| waitForEvent(OMX_EVENT_JPEG_ABORT, 0, 0); |
| ALOGV("%s:waitForEvent: OMX_CommandFlush: DONE", __func__); |
| OMX_SendCommand(pHandle, OMX_CommandStateSet, OMX_StateIdle, NULL); |
| OMX_SendCommand(pHandle, OMX_CommandStateSet, OMX_StateLoaded, NULL); |
| OMX_FreeBuffer(pHandle, 0, pInBuffers); |
| OMX_FreeBuffer(pHandle, 2, pInBuffers1); |
| OMX_FreeBuffer(pHandle, 1, pOutBuffers); |
| (*pOMX_Deinit)(); |
| } |
| pthread_mutex_unlock(&jpege_mutex); |
| } |
| |
| |
| int8_t mm_jpeg_encoder_setMainImageQuality(uint32_t quality) |
| { |
| pthread_mutex_lock(&jpege_mutex); |
| ALOGV("%s: current main inage quality %d ," \ |
| " new quality : %d\n", __func__, jpegMainimageQuality, quality); |
| if (quality <= 100) |
| jpegMainimageQuality = quality; |
| pthread_mutex_unlock(&jpege_mutex); |
| return true; |
| } |
| |
| int8_t mm_jpeg_encoder_setThumbnailQuality(uint32_t quality) |
| { |
| pthread_mutex_lock(&jpege_mutex); |
| ALOGV("%s: current thumbnail quality %d ," \ |
| " new quality : %d\n", __func__, jpegThumbnailQuality, quality); |
| if (quality <= 100) |
| jpegThumbnailQuality = quality; |
| pthread_mutex_unlock(&jpege_mutex); |
| return true; |
| } |
| |
| int8_t mm_jpeg_encoder_setRotation(int rotation, int isZSL) |
| { |
| pthread_mutex_lock(&jpege_mutex); |
| |
| /*Set ZSL Mode*/ |
| isZSLMode = isZSL; |
| ALOGV("%s: Setting ZSL Mode to %d Rotation = %d\n",__func__,isZSLMode,rotation); |
| /* Set rotation configuration */ |
| switch (rotation) { |
| case 0: |
| case 90: |
| case 180: |
| case 270: |
| jpegRotation = rotation; |
| break; |
| default: |
| /* Invalid rotation mode, set to default */ |
| ALOGV("%s:Setting Default rotation mode", __func__); |
| jpegRotation = 0; |
| break; |
| } |
| pthread_mutex_unlock(&jpege_mutex); |
| return true; |
| } |
| |
| /*=========================================================================== |
| FUNCTION mm_jpege_set_phy_offset |
| |
| DESCRIPTION Set physical offset for the buffer |
| ===========================================================================*/ |
| void mm_jpege_set_phy_offset(uint32_t a_phy_offset) |
| { |
| phy_offset = a_phy_offset; |
| } |