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