1 /* Copyright (c) 2012-2014, 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 30 #define ATRACE_TAG ATRACE_TAG_CAMERA 31 32 #include <pthread.h> 33 #include <errno.h> 34 #include <sys/ioctl.h> 35 #include <sys/types.h> 36 #include <sys/stat.h> 37 #include <sys/prctl.h> 38 #include <fcntl.h> 39 #include <poll.h> 40 #include <cutils/trace.h> 41 #include <math.h> 42 43 #include "mm_jpeg_dbg.h" 44 #include "mm_jpeg_interface.h" 45 #include "mm_jpeg.h" 46 #include "mm_jpeg_inlines.h" 47 48 #ifdef LOAD_ADSP_RPC_LIB 49 #include <dlfcn.h> 50 #include <stdlib.h> 51 #endif 52 53 #define ENCODING_MODE_PARALLEL 1 54 55 #define META_KEYFILE QCAMERA_DUMP_FRM_LOCATION"metadata.key" 56 57 /** 58 * minimal resolution needed for normal mode of ops 59 */ 60 #define MM_JPEG_MIN_NOM_RESOLUTION 7680000 /*8MP*/ 61 62 OMX_ERRORTYPE mm_jpeg_ebd(OMX_HANDLETYPE hComponent, 63 OMX_PTR pAppData, 64 OMX_BUFFERHEADERTYPE* pBuffer); 65 OMX_ERRORTYPE mm_jpeg_fbd(OMX_HANDLETYPE hComponent, 66 OMX_PTR pAppData, 67 OMX_BUFFERHEADERTYPE* pBuffer); 68 OMX_ERRORTYPE mm_jpeg_event_handler(OMX_HANDLETYPE hComponent, 69 OMX_PTR pAppData, 70 OMX_EVENTTYPE eEvent, 71 OMX_U32 nData1, 72 OMX_U32 nData2, 73 OMX_PTR pEventData); 74 75 static int32_t mm_jpegenc_destroy_job(mm_jpeg_job_session_t *p_session); 76 static void mm_jpegenc_job_done(mm_jpeg_job_session_t *p_session); 77 mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_dst_ptr( 78 mm_jpeg_queue_t* queue, void * dst_ptr); 79 static OMX_ERRORTYPE mm_jpeg_session_configure(mm_jpeg_job_session_t *p_session); 80 81 /** mm_jpeg_session_send_buffers: 82 * 83 * Arguments: 84 * @data: job session 85 * 86 * Return: 87 * OMX error values 88 * 89 * Description: 90 * Send the buffers to OMX layer 91 * 92 **/ 93 OMX_ERRORTYPE mm_jpeg_session_send_buffers(void *data) 94 { 95 uint32_t i = 0; 96 mm_jpeg_job_session_t* p_session = (mm_jpeg_job_session_t *)data; 97 OMX_ERRORTYPE ret = OMX_ErrorNone; 98 QOMX_BUFFER_INFO lbuffer_info; 99 mm_jpeg_encode_params_t *p_params = &p_session->params; 100 101 memset(&lbuffer_info, 0x0, sizeof(QOMX_BUFFER_INFO)); 102 for (i = 0; i < p_params->num_src_bufs; i++) { 103 CDBG("%s:%d] Source buffer %d", __func__, __LINE__, i); 104 lbuffer_info.fd = (OMX_U32)p_params->src_main_buf[i].fd; 105 ret = OMX_UseBuffer(p_session->omx_handle, &(p_session->p_in_omx_buf[i]), 0, 106 &lbuffer_info, p_params->src_main_buf[i].buf_size, 107 p_params->src_main_buf[i].buf_vaddr); 108 if (ret) { 109 CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret); 110 return ret; 111 } 112 } 113 114 for (i = 0; i < p_params->num_tmb_bufs; i++) { 115 CDBG("%s:%d] Source buffer %d", __func__, __LINE__, i); 116 lbuffer_info.fd = (OMX_U32)p_params->src_thumb_buf[i].fd; 117 ret = OMX_UseBuffer(p_session->omx_handle, 118 &(p_session->p_in_omx_thumb_buf[i]), 2, 119 &lbuffer_info, p_params->src_thumb_buf[i].buf_size, 120 p_params->src_thumb_buf[i].buf_vaddr); 121 if (ret) { 122 CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret); 123 return ret; 124 } 125 } 126 127 for (i = 0; i < p_params->num_dst_bufs; i++) { 128 CDBG("%s:%d] Dest buffer %d", __func__, __LINE__, i); 129 ret = OMX_UseBuffer(p_session->omx_handle, &(p_session->p_out_omx_buf[i]), 130 1, NULL, p_params->dest_buf[i].buf_size, 131 p_params->dest_buf[i].buf_vaddr); 132 if (ret) { 133 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 134 return ret; 135 } 136 } 137 CDBG("%s:%d]", __func__, __LINE__); 138 return ret; 139 } 140 141 142 /** mm_jpeg_session_free_buffers: 143 * 144 * Arguments: 145 * @data: job session 146 * 147 * Return: 148 * OMX error values 149 * 150 * Description: 151 * Free the buffers from OMX layer 152 * 153 **/ 154 OMX_ERRORTYPE mm_jpeg_session_free_buffers(void *data) 155 { 156 OMX_ERRORTYPE ret = OMX_ErrorNone; 157 uint32_t i = 0; 158 mm_jpeg_job_session_t* p_session = (mm_jpeg_job_session_t *)data; 159 mm_jpeg_encode_params_t *p_params = &p_session->params; 160 161 for (i = 0; i < p_params->num_src_bufs; i++) { 162 CDBG("%s:%d] Source buffer %d", __func__, __LINE__, i); 163 ret = OMX_FreeBuffer(p_session->omx_handle, 0, p_session->p_in_omx_buf[i]); 164 if (ret) { 165 CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret); 166 return ret; 167 } 168 } 169 170 for (i = 0; i < p_params->num_tmb_bufs; i++) { 171 CDBG("%s:%d] Source buffer %d", __func__, __LINE__, i); 172 ret = OMX_FreeBuffer(p_session->omx_handle, 2, p_session->p_in_omx_thumb_buf[i]); 173 if (ret) { 174 CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret); 175 return ret; 176 } 177 } 178 179 for (i = 0; i < p_params->num_dst_bufs; i++) { 180 CDBG("%s:%d] Dest buffer %d", __func__, __LINE__, i); 181 ret = OMX_FreeBuffer(p_session->omx_handle, 1, p_session->p_out_omx_buf[i]); 182 if (ret) { 183 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 184 return ret; 185 } 186 } 187 CDBG("%s:%d]", __func__, __LINE__); 188 return ret; 189 } 190 191 192 193 194 /** mm_jpeg_session_change_state: 195 * 196 * Arguments: 197 * @p_session: job session 198 * @new_state: new state to be transitioned to 199 * @p_exec: transition function 200 * 201 * Return: 202 * OMX error values 203 * 204 * Description: 205 * This method is used for state transition 206 * 207 **/ 208 OMX_ERRORTYPE mm_jpeg_session_change_state(mm_jpeg_job_session_t* p_session, 209 OMX_STATETYPE new_state, 210 mm_jpeg_transition_func_t p_exec) 211 { 212 OMX_ERRORTYPE ret = OMX_ErrorNone; 213 OMX_STATETYPE current_state; 214 CDBG("%s:%d] new_state %d p_exec %p", __func__, __LINE__, 215 new_state, p_exec); 216 217 218 pthread_mutex_lock(&p_session->lock); 219 220 ret = OMX_GetState(p_session->omx_handle, ¤t_state); 221 222 if (ret) { 223 pthread_mutex_unlock(&p_session->lock); 224 return ret; 225 } 226 227 if (current_state == new_state) { 228 pthread_mutex_unlock(&p_session->lock); 229 return OMX_ErrorNone; 230 } 231 232 p_session->state_change_pending = OMX_TRUE; 233 pthread_mutex_unlock(&p_session->lock); 234 ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandStateSet, 235 new_state, NULL); 236 pthread_mutex_lock(&p_session->lock); 237 if (ret) { 238 CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret); 239 pthread_mutex_unlock(&p_session->lock); 240 return OMX_ErrorIncorrectStateTransition; 241 } 242 CDBG("%s:%d] ", __func__, __LINE__); 243 if ((OMX_ErrorNone != p_session->error_flag) && 244 (OMX_ErrorOverflow != p_session->error_flag)) { 245 CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, p_session->error_flag); 246 pthread_mutex_unlock(&p_session->lock); 247 return p_session->error_flag; 248 } 249 if (p_exec) { 250 ret = p_exec(p_session); 251 if (ret) { 252 CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret); 253 pthread_mutex_unlock(&p_session->lock); 254 return ret; 255 } 256 } 257 CDBG("%s:%d] ", __func__, __LINE__); 258 if (p_session->state_change_pending) { 259 CDBG("%s:%d] before wait", __func__, __LINE__); 260 pthread_cond_wait(&p_session->cond, &p_session->lock); 261 CDBG("%s:%d] after wait", __func__, __LINE__); 262 } 263 pthread_mutex_unlock(&p_session->lock); 264 CDBG("%s:%d] ", __func__, __LINE__); 265 return ret; 266 } 267 268 /** mm_jpeg_session_create: 269 * 270 * Arguments: 271 * @p_session: job session 272 * 273 * Return: 274 * OMX error types 275 * 276 * Description: 277 * Create a jpeg encode session 278 * 279 **/ 280 OMX_ERRORTYPE mm_jpeg_session_create(mm_jpeg_job_session_t* p_session) 281 { 282 OMX_ERRORTYPE rc = OMX_ErrorNone; 283 mm_jpeg_obj *my_obj = (mm_jpeg_obj *) p_session->jpeg_obj; 284 char *omx_lib = "OMX.qcom.image.jpeg.encoder"; 285 286 pthread_mutex_init(&p_session->lock, NULL); 287 pthread_cond_init(&p_session->cond, NULL); 288 cirq_reset(&p_session->cb_q); 289 p_session->state_change_pending = OMX_FALSE; 290 p_session->abort_state = MM_JPEG_ABORT_NONE; 291 p_session->error_flag = OMX_ErrorNone; 292 p_session->ebd_count = 0; 293 p_session->fbd_count = 0; 294 p_session->encode_pid = -1; 295 p_session->config = OMX_FALSE; 296 p_session->exif_count_local = 0; 297 p_session->auto_out_buf = OMX_FALSE; 298 299 p_session->omx_callbacks.EmptyBufferDone = mm_jpeg_ebd; 300 p_session->omx_callbacks.FillBufferDone = mm_jpeg_fbd; 301 p_session->omx_callbacks.EventHandler = mm_jpeg_event_handler; 302 303 p_session->thumb_from_main = 0; 304 #ifdef MM_JPEG_USE_PIPELINE 305 p_session->thumb_from_main = 1; 306 omx_lib = "OMX.qcom.image.jpeg.encoder_pipeline"; 307 #endif 308 309 rc = OMX_GetHandle(&p_session->omx_handle, 310 omx_lib, 311 (void *)p_session, 312 &p_session->omx_callbacks); 313 if (OMX_ErrorNone != rc) { 314 CDBG_ERROR("%s:%d] OMX_GetHandle failed (%d)", __func__, __LINE__, rc); 315 return rc; 316 } 317 318 my_obj->num_sessions++; 319 320 return rc; 321 } 322 323 324 325 /** mm_jpeg_session_destroy: 326 * 327 * Arguments: 328 * @p_session: job session 329 * 330 * Return: 331 * none 332 * 333 * Description: 334 * Destroy a jpeg encode session 335 * 336 **/ 337 void mm_jpeg_session_destroy(mm_jpeg_job_session_t* p_session) 338 { 339 OMX_ERRORTYPE rc = OMX_ErrorNone; 340 OMX_STATETYPE state; 341 mm_jpeg_obj *my_obj = (mm_jpeg_obj *) p_session->jpeg_obj; 342 343 CDBG("%s:%d] E", __func__, __LINE__); 344 if (NULL == p_session->omx_handle) { 345 CDBG_ERROR("%s:%d] invalid handle", __func__, __LINE__); 346 return; 347 } 348 349 rc = OMX_GetState(p_session->omx_handle, &state); 350 351 //Check state before state transition 352 if ((state == OMX_StateExecuting) || (state == OMX_StatePause)) { 353 rc = mm_jpeg_session_change_state(p_session, OMX_StateIdle, NULL); 354 if (rc) { 355 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 356 } 357 } 358 359 rc = OMX_GetState(p_session->omx_handle, &state); 360 361 if (state == OMX_StateIdle) { 362 rc = mm_jpeg_session_change_state(p_session, OMX_StateLoaded, 363 mm_jpeg_session_free_buffers); 364 if (rc) { 365 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 366 } 367 } 368 369 rc = OMX_FreeHandle(p_session->omx_handle); 370 if (0 != rc) { 371 CDBG_ERROR("%s:%d] OMX_FreeHandle failed (%d)", __func__, __LINE__, rc); 372 } 373 p_session->omx_handle = NULL; 374 375 pthread_mutex_destroy(&p_session->lock); 376 pthread_cond_destroy(&p_session->cond); 377 378 if (NULL != p_session->meta_enc_key) { 379 free(p_session->meta_enc_key); 380 p_session->meta_enc_key = NULL; 381 } 382 383 my_obj->num_sessions--; 384 385 // Destroy next session 386 if (p_session->next_session) { 387 mm_jpeg_session_destroy(p_session->next_session); 388 } 389 390 CDBG_HIGH("%s:%d] Session destroy successful. X", __func__, __LINE__); 391 } 392 393 394 395 /** mm_jpeg_session_config_main_buffer_offset: 396 * 397 * Arguments: 398 * @p_session: job session 399 * 400 * Return: 401 * OMX error values 402 * 403 * Description: 404 * Configure the buffer offsets 405 * 406 **/ 407 OMX_ERRORTYPE mm_jpeg_session_config_main_buffer_offset( 408 mm_jpeg_job_session_t* p_session) 409 { 410 OMX_ERRORTYPE rc = 0; 411 OMX_INDEXTYPE buffer_index; 412 QOMX_YUV_FRAME_INFO frame_info; 413 size_t totalSize = 0; 414 mm_jpeg_encode_params_t *p_params = &p_session->params; 415 416 mm_jpeg_buf_t *p_src_buf = 417 &p_params->src_main_buf[0]; 418 419 memset(&frame_info, 0x0, sizeof(QOMX_YUV_FRAME_INFO)); 420 421 frame_info.cbcrStartOffset[0] = p_src_buf->offset.mp[0].len; 422 frame_info.cbcrStartOffset[1] = p_src_buf->offset.mp[1].len; 423 frame_info.yOffset = p_src_buf->offset.mp[0].offset; 424 frame_info.cbcrOffset[0] = p_src_buf->offset.mp[1].offset; 425 frame_info.cbcrOffset[1] = p_src_buf->offset.mp[2].offset; 426 totalSize = p_src_buf->buf_size; 427 428 rc = OMX_GetExtensionIndex(p_session->omx_handle, 429 QOMX_IMAGE_EXT_BUFFER_OFFSET_NAME, &buffer_index); 430 if (rc != OMX_ErrorNone) { 431 CDBG_ERROR("%s:%d] Failed", __func__, __LINE__); 432 return rc; 433 } 434 435 CDBG_HIGH("%s:%d] yOffset = %d, cbcrOffset = (%d %d), totalSize = %zd," 436 "cbcrStartOffset = (%d %d)", __func__, __LINE__, 437 (int)frame_info.yOffset, 438 (int)frame_info.cbcrOffset[0], 439 (int)frame_info.cbcrOffset[1], 440 totalSize, 441 (int)frame_info.cbcrStartOffset[0], 442 (int)frame_info.cbcrStartOffset[1]); 443 444 rc = OMX_SetParameter(p_session->omx_handle, buffer_index, &frame_info); 445 if (rc != OMX_ErrorNone) { 446 CDBG_ERROR("%s:%d] Failed", __func__, __LINE__); 447 return rc; 448 } 449 return rc; 450 } 451 452 /** mm_jpeg_encoding_mode: 453 * 454 * Arguments: 455 * @p_session: job session 456 * 457 * Return: 458 * OMX error values 459 * 460 * Description: 461 * Configure the serial or parallel encoding 462 * mode 463 * 464 **/ 465 OMX_ERRORTYPE mm_jpeg_encoding_mode( 466 mm_jpeg_job_session_t* p_session) 467 { 468 OMX_ERRORTYPE rc = 0; 469 OMX_INDEXTYPE indextype; 470 QOMX_ENCODING_MODE encoding_mode; 471 472 rc = OMX_GetExtensionIndex(p_session->omx_handle, 473 QOMX_IMAGE_EXT_ENCODING_MODE_NAME, &indextype); 474 if (rc != OMX_ErrorNone) { 475 CDBG_ERROR("%s:%d] Failed", __func__, __LINE__); 476 return rc; 477 } 478 479 if (ENCODING_MODE_PARALLEL) { 480 encoding_mode = OMX_Parallel_Encoding; 481 } else { 482 encoding_mode = OMX_Serial_Encoding; 483 } 484 CDBG("%s:%d] encoding mode = %d ", __func__, __LINE__, 485 (int)encoding_mode); 486 rc = OMX_SetParameter(p_session->omx_handle, indextype, &encoding_mode); 487 if (rc != OMX_ErrorNone) { 488 CDBG_ERROR("%s:%d] Failed", __func__, __LINE__); 489 return rc; 490 } 491 return rc; 492 } 493 494 /** mm_jpeg_get_speed: 495 * 496 * Arguments: 497 * @p_session: job session 498 * 499 * Return: 500 * ops speed type for jpeg 501 * 502 * Description: 503 * Configure normal or high speed jpeg 504 * 505 **/ 506 QOMX_JPEG_SPEED_MODE mm_jpeg_get_speed( 507 mm_jpeg_job_session_t* p_session) 508 { 509 mm_jpeg_encode_params_t *p_params = &p_session->params; 510 cam_dimension_t *p_dim = &p_params->main_dim.src_dim; 511 if (p_params->burst_mode || 512 (MM_JPEG_MIN_NOM_RESOLUTION < (p_dim->width * p_dim->height))) { 513 return QOMX_JPEG_SPEED_MODE_HIGH; 514 } 515 return QOMX_JPEG_SPEED_MODE_NORMAL; 516 } 517 518 /** mm_jpeg_speed_mode: 519 * 520 * Arguments: 521 * @p_session: job session 522 * 523 * Return: 524 * OMX error values 525 * 526 * Description: 527 * Configure normal or high speed jpeg 528 * 529 **/ 530 OMX_ERRORTYPE mm_jpeg_speed_mode( 531 mm_jpeg_job_session_t* p_session) 532 { 533 OMX_ERRORTYPE rc = 0; 534 OMX_INDEXTYPE indextype; 535 QOMX_JPEG_SPEED jpeg_speed; 536 537 rc = OMX_GetExtensionIndex(p_session->omx_handle, 538 QOMX_IMAGE_EXT_JPEG_SPEED_NAME, &indextype); 539 if (rc != OMX_ErrorNone) { 540 CDBG_ERROR("%s:%d] Failed", __func__, __LINE__); 541 return rc; 542 } 543 544 jpeg_speed.speedMode = mm_jpeg_get_speed(p_session); 545 CDBG_HIGH("%s:%d] speed %d", __func__, __LINE__, jpeg_speed.speedMode); 546 547 rc = OMX_SetParameter(p_session->omx_handle, indextype, &jpeg_speed); 548 if (rc != OMX_ErrorNone) { 549 CDBG_ERROR("%s:%d] Failed", __func__, __LINE__); 550 return rc; 551 } 552 return rc; 553 } 554 555 556 /** mm_jpeg_mem_ops: 557 * 558 * Arguments: 559 * @p_session: job session 560 * 561 * Return: 562 * OMX error values 563 * 564 * Description: 565 * Configure the serial or parallel encoding 566 * mode 567 * 568 **/ 569 OMX_ERRORTYPE mm_jpeg_mem_ops( 570 mm_jpeg_job_session_t* p_session) 571 { 572 OMX_ERRORTYPE rc = 0; 573 OMX_INDEXTYPE indextype; 574 QOMX_MEM_OPS mem_ops; 575 mm_jpeg_encode_params_t *p_params = &p_session->params; 576 577 mem_ops.get_memory = p_params->get_memory; 578 579 rc = OMX_GetExtensionIndex(p_session->omx_handle, 580 QOMX_IMAGE_EXT_MEM_OPS_NAME, &indextype); 581 if (rc != OMX_ErrorNone) { 582 CDBG_ERROR("%s:%d] Failed", __func__, __LINE__); 583 return rc; 584 } 585 586 rc = OMX_SetParameter(p_session->omx_handle, indextype, &mem_ops); 587 if (rc != OMX_ErrorNone) { 588 CDBG_ERROR("%s:%d] Failed", __func__, __LINE__); 589 return rc; 590 } 591 return rc; 592 } 593 594 /** mm_jpeg_metadata: 595 * 596 * Arguments: 597 * @p_session: job session 598 * 599 * Return: 600 * OMX error values 601 * 602 * Description: 603 * Pass meta data 604 * 605 **/ 606 OMX_ERRORTYPE mm_jpeg_metadata( 607 mm_jpeg_job_session_t* p_session) 608 { 609 OMX_ERRORTYPE rc = OMX_ErrorNone; 610 OMX_INDEXTYPE indexType; 611 mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job; 612 QOMX_METADATA lMeta; 613 614 rc = OMX_GetExtensionIndex(p_session->omx_handle, 615 QOMX_IMAGE_EXT_METADATA_NAME, &indexType); 616 617 if (rc != OMX_ErrorNone) { 618 CDBG_ERROR("%s:%d] Failed", __func__, __LINE__); 619 return rc; 620 } 621 622 lMeta.metadata = (OMX_U8 *)p_jobparams->p_metadata; 623 lMeta.metaPayloadSize = sizeof(*p_jobparams->p_metadata); 624 lMeta.mobicat_mask = p_jobparams->mobicat_mask; 625 626 rc = OMX_SetConfig(p_session->omx_handle, indexType, &lMeta); 627 if (rc != OMX_ErrorNone) { 628 CDBG_ERROR("%s:%d] Failed", __func__, __LINE__); 629 return rc; 630 } 631 return OMX_ErrorNone; 632 } 633 634 /** mm_jpeg_meta_enc_key: 635 * 636 * Arguments: 637 * @p_session: job session 638 * 639 * Return: 640 * OMX error values 641 * 642 * Description: 643 * Pass metadata encrypt key 644 * 645 **/ 646 OMX_ERRORTYPE mm_jpeg_meta_enc_key( 647 mm_jpeg_job_session_t* p_session) 648 { 649 OMX_ERRORTYPE rc = OMX_ErrorNone; 650 OMX_INDEXTYPE indexType; 651 QOMX_META_ENC_KEY lKey; 652 653 lKey.metaKey = p_session->meta_enc_key; 654 lKey.keyLen = p_session->meta_enc_keylen; 655 656 if ((!lKey.metaKey) || (!lKey.keyLen)){ 657 CDBG_ERROR("%s:%d] Key is invalid", __func__, __LINE__); 658 return OMX_ErrorNone; 659 } 660 661 rc = OMX_GetExtensionIndex(p_session->omx_handle, 662 QOMX_IMAGE_EXT_META_ENC_KEY_NAME, &indexType); 663 664 if (rc != OMX_ErrorNone) { 665 CDBG_ERROR("%s:%d] Failed", __func__, __LINE__); 666 return rc; 667 } 668 669 rc = OMX_SetConfig(p_session->omx_handle, indexType, &lKey); 670 if (rc != OMX_ErrorNone) { 671 CDBG_ERROR("%s:%d] Failed", __func__, __LINE__); 672 return rc; 673 } 674 return OMX_ErrorNone; 675 } 676 677 /** map_jpeg_format: 678 * 679 * Arguments: 680 * @color_fmt: color format 681 * 682 * Return: 683 * OMX color format 684 * 685 * Description: 686 * Map mmjpeg color format to OMX color format 687 * 688 **/ 689 int map_jpeg_format(mm_jpeg_color_format color_fmt) 690 { 691 switch (color_fmt) { 692 case MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2: 693 return (int)OMX_QCOM_IMG_COLOR_FormatYVU420SemiPlanar; 694 case MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2: 695 return (int)OMX_COLOR_FormatYUV420SemiPlanar; 696 case MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V1: 697 return (int)OMX_QCOM_IMG_COLOR_FormatYVU422SemiPlanar; 698 case MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V1: 699 return (int)OMX_COLOR_FormatYUV422SemiPlanar; 700 case MM_JPEG_COLOR_FORMAT_YCRCBLP_H1V2: 701 return (int)OMX_QCOM_IMG_COLOR_FormatYVU422SemiPlanar_h1v2; 702 case MM_JPEG_COLOR_FORMAT_YCBCRLP_H1V2: 703 return (int)OMX_QCOM_IMG_COLOR_FormatYUV422SemiPlanar_h1v2; 704 case MM_JPEG_COLOR_FORMAT_YCRCBLP_H1V1: 705 return (int)OMX_QCOM_IMG_COLOR_FormatYVU444SemiPlanar; 706 case MM_JPEG_COLOR_FORMAT_YCBCRLP_H1V1: 707 return (int)OMX_QCOM_IMG_COLOR_FormatYUV444SemiPlanar; 708 case MM_JPEG_COLOR_FORMAT_MONOCHROME: 709 return (int)OMX_COLOR_FormatMonochrome; 710 default: 711 CDBG_ERROR("%s:%d] invalid format %d", __func__, __LINE__, color_fmt); 712 return (int)OMX_QCOM_IMG_COLOR_FormatYVU420SemiPlanar; 713 } 714 } 715 716 /** mm_jpeg_session_config_port: 717 * 718 * Arguments: 719 * @p_session: job session 720 * 721 * Return: 722 * OMX error values 723 * 724 * Description: 725 * Configure OMX ports 726 * 727 **/ 728 OMX_ERRORTYPE mm_jpeg_session_config_ports(mm_jpeg_job_session_t* p_session) 729 { 730 OMX_ERRORTYPE ret = OMX_ErrorNone; 731 mm_jpeg_encode_params_t *p_params = &p_session->params; 732 OMX_CONFIG_ROTATIONTYPE rotate; 733 734 mm_jpeg_buf_t *p_src_buf = 735 &p_params->src_main_buf[0]; 736 737 p_session->inputPort.nPortIndex = 0; 738 p_session->outputPort.nPortIndex = 1; 739 p_session->inputTmbPort.nPortIndex = 2; 740 741 ret = OMX_GetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition, 742 &p_session->inputPort); 743 if (ret) { 744 CDBG_ERROR("%s:%d] failed", __func__, __LINE__); 745 return ret; 746 } 747 748 ret = OMX_GetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition, 749 &p_session->inputTmbPort); 750 if (ret) { 751 CDBG_ERROR("%s:%d] failed", __func__, __LINE__); 752 return ret; 753 } 754 755 ret = OMX_GetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition, 756 &p_session->outputPort); 757 if (ret) { 758 CDBG_ERROR("%s:%d] failed", __func__, __LINE__); 759 return ret; 760 } 761 762 p_session->inputPort.format.image.nFrameWidth = 763 (OMX_U32)p_params->main_dim.src_dim.width; 764 p_session->inputPort.format.image.nFrameHeight = 765 (OMX_U32)p_params->main_dim.src_dim.height; 766 p_session->inputPort.format.image.nStride = 767 p_src_buf->offset.mp[0].stride; 768 p_session->inputPort.format.image.nSliceHeight = 769 (OMX_U32)p_src_buf->offset.mp[0].scanline; 770 p_session->inputPort.format.image.eColorFormat = 771 map_jpeg_format(p_params->color_format); 772 p_session->inputPort.nBufferSize = 773 p_params->src_main_buf[0/*p_jobparams->src_index*/].buf_size; 774 p_session->inputPort.nBufferCountActual = (OMX_U32)p_params->num_src_bufs; 775 ret = OMX_SetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition, 776 &p_session->inputPort); 777 if (ret) { 778 CDBG_ERROR("%s:%d] failed", __func__, __LINE__); 779 return ret; 780 } 781 782 if (p_session->params.encode_thumbnail) { 783 mm_jpeg_buf_t *p_tmb_buf = 784 &p_params->src_thumb_buf[0]; 785 p_session->inputTmbPort.format.image.nFrameWidth = 786 (OMX_U32)p_params->thumb_dim.src_dim.width; 787 p_session->inputTmbPort.format.image.nFrameHeight = 788 (OMX_U32)p_params->thumb_dim.src_dim.height; 789 p_session->inputTmbPort.format.image.nStride = 790 p_tmb_buf->offset.mp[0].stride; 791 p_session->inputTmbPort.format.image.nSliceHeight = 792 (OMX_U32)p_tmb_buf->offset.mp[0].scanline; 793 p_session->inputTmbPort.format.image.eColorFormat = 794 map_jpeg_format(p_params->thumb_color_format); 795 p_session->inputTmbPort.nBufferSize = 796 p_params->src_thumb_buf[0].buf_size; 797 p_session->inputTmbPort.nBufferCountActual = (OMX_U32)p_params->num_tmb_bufs; 798 799 ret = OMX_SetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition, 800 &p_session->inputTmbPort); 801 802 if (ret) { 803 CDBG_ERROR("%s:%d] failed", __func__, __LINE__); 804 return ret; 805 } 806 807 // Enable thumbnail port 808 ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandPortEnable, 809 p_session->inputTmbPort.nPortIndex, NULL); 810 811 if (ret) { 812 CDBG_ERROR("%s:%d] failed", __func__, __LINE__); 813 return ret; 814 } 815 } else { 816 // Disable thumbnail port 817 ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandPortDisable, 818 p_session->inputTmbPort.nPortIndex, NULL); 819 820 if (ret) { 821 CDBG_ERROR("%s:%d] failed", __func__, __LINE__); 822 return ret; 823 } 824 } 825 826 p_session->outputPort.nBufferSize = 827 p_params->dest_buf[0].buf_size; 828 p_session->outputPort.nBufferCountActual = (OMX_U32)p_params->num_dst_bufs; 829 ret = OMX_SetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition, 830 &p_session->outputPort); 831 if (ret) { 832 CDBG_ERROR("%s:%d] failed", __func__, __LINE__); 833 return ret; 834 } 835 836 /* set rotation */ 837 memset(&rotate, 0, sizeof(rotate)); 838 rotate.nPortIndex = 1; 839 rotate.nRotation = (OMX_S32)p_params->rotation; 840 ret = OMX_SetConfig(p_session->omx_handle, OMX_IndexConfigCommonRotate, 841 &rotate); 842 if (OMX_ErrorNone != ret) { 843 CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret); 844 return ret; 845 } 846 CDBG("%s:%d] Set rotation to %d at port_idx = %d", __func__, __LINE__, 847 (int)p_params->rotation, (int)rotate.nPortIndex); 848 849 return ret; 850 } 851 852 /** mm_jpeg_get_thumbnail_crop 853 * 854 * Arguments: 855 * @p_thumb_dim: thumbnail dimension 856 * @p_main_dim: main image dimension 857 * @crop_width : flag indicating if width needs to be cropped 858 * 859 * Return: 860 * OMX error values 861 * 862 * Description: 863 * If the main image and thumbnail ascpect ratios are differnt, 864 * re-calculate the thumbnail crop info to prevent distortion 865 * 866 */ 867 OMX_ERRORTYPE mm_jpeg_get_thumbnail_crop(mm_jpeg_dim_t *p_thumb_dim, 868 mm_jpeg_dim_t *p_main_dim, uint8_t crop_width) { 869 OMX_ERRORTYPE ret = OMX_ErrorNone; 870 int cropped_width = 0, cropped_height = 0; 871 872 if (crop_width) { 873 //Keep height constant 874 cropped_height = p_thumb_dim->src_dim.height; 875 cropped_width = floor((cropped_height * p_thumb_dim->dst_dim.width) / 876 p_thumb_dim->dst_dim.height); 877 } else { 878 //Keep width constant 879 cropped_width = p_thumb_dim->src_dim.width; 880 cropped_height = floor((cropped_width * p_thumb_dim->dst_dim.height) / 881 p_thumb_dim->dst_dim.width); 882 } 883 p_thumb_dim->crop.left = floor(p_thumb_dim->src_dim.width - cropped_width) / 2; 884 p_thumb_dim->crop.top = floor(p_thumb_dim->src_dim.height - cropped_height) / 2; 885 p_thumb_dim->crop.width = cropped_width; 886 p_thumb_dim->crop.height = cropped_height; 887 888 CDBG_HIGH("%s %d New thumbnail crop: left %d, top %d, crop width %d, crop height %d", 889 __func__, __LINE__, p_thumb_dim->crop.left, p_thumb_dim->crop.top, 890 p_thumb_dim->crop.width, p_thumb_dim->crop.height); 891 892 return ret; 893 } 894 895 /** mm_jpeg_omx_config_thumbnail: 896 * 897 * Arguments: 898 * @p_session: job session 899 * 900 * Return: 901 * OMX error values 902 * 903 * Description: 904 * Configure OMX ports 905 * 906 **/ 907 OMX_ERRORTYPE mm_jpeg_session_config_thumbnail(mm_jpeg_job_session_t* p_session) 908 { 909 OMX_ERRORTYPE ret = OMX_ErrorNone; 910 QOMX_THUMBNAIL_INFO thumbnail_info; 911 OMX_INDEXTYPE thumb_indextype; 912 mm_jpeg_encode_params_t *p_params = &p_session->params; 913 mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job; 914 mm_jpeg_dim_t *p_thumb_dim = &p_jobparams->thumb_dim; 915 mm_jpeg_dim_t *p_main_dim = &p_jobparams->main_dim; 916 QOMX_YUV_FRAME_INFO *p_frame_info = &thumbnail_info.tmbOffset; 917 mm_jpeg_buf_t *p_tmb_buf = &p_params->src_thumb_buf[p_jobparams->thumb_index]; 918 919 CDBG_HIGH("%s:%d] encode_thumbnail %u", __func__, __LINE__, 920 p_params->encode_thumbnail); 921 if (OMX_FALSE == p_params->encode_thumbnail) { 922 return ret; 923 } 924 925 if ((p_thumb_dim->dst_dim.width == 0) || (p_thumb_dim->dst_dim.height == 0)) { 926 CDBG_ERROR("%s:%d] Error invalid output dim for thumbnail", 927 __func__, __LINE__); 928 return OMX_ErrorBadParameter; 929 } 930 931 if ((p_thumb_dim->src_dim.width == 0) || (p_thumb_dim->src_dim.height == 0)) { 932 CDBG_ERROR("%s:%d] Error invalid input dim for thumbnail", 933 __func__, __LINE__); 934 return OMX_ErrorBadParameter; 935 } 936 937 if ((p_thumb_dim->crop.width == 0) || (p_thumb_dim->crop.height == 0)) { 938 p_thumb_dim->crop.width = p_thumb_dim->src_dim.width; 939 p_thumb_dim->crop.height = p_thumb_dim->src_dim.height; 940 } 941 942 /* check crop boundary */ 943 if ((p_thumb_dim->crop.width + p_thumb_dim->crop.left > p_thumb_dim->src_dim.width) || 944 (p_thumb_dim->crop.height + p_thumb_dim->crop.top > p_thumb_dim->src_dim.height)) { 945 CDBG_ERROR("%s:%d] invalid crop boundary (%d, %d) offset (%d, %d) out of (%d, %d)", 946 __func__, __LINE__, 947 p_thumb_dim->crop.width, 948 p_thumb_dim->crop.height, 949 p_thumb_dim->crop.left, 950 p_thumb_dim->crop.top, 951 p_thumb_dim->src_dim.width, 952 p_thumb_dim->src_dim.height); 953 return OMX_ErrorBadParameter; 954 } 955 956 memset(&thumbnail_info, 0x0, sizeof(QOMX_THUMBNAIL_INFO)); 957 ret = OMX_GetExtensionIndex(p_session->omx_handle, 958 QOMX_IMAGE_EXT_THUMBNAIL_NAME, 959 &thumb_indextype); 960 if (ret) { 961 CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret); 962 return ret; 963 } 964 965 /* fill thumbnail info */ 966 thumbnail_info.scaling_enabled = 1; 967 thumbnail_info.input_width = (OMX_U32)p_thumb_dim->src_dim.width; 968 thumbnail_info.input_height = (OMX_U32)p_thumb_dim->src_dim.height; 969 thumbnail_info.rotation = (OMX_U32)p_params->thumb_rotation; 970 thumbnail_info.quality = (OMX_U32)p_params->thumb_quality; 971 thumbnail_info.output_width = (OMX_U32)p_thumb_dim->dst_dim.width; 972 thumbnail_info.output_height = (OMX_U32)p_thumb_dim->dst_dim.height; 973 974 if (p_session->thumb_from_main) { 975 if ((p_session->params.thumb_rotation == 90 || 976 p_session->params.thumb_rotation == 270) && 977 (p_session->params.rotation == 0 || 978 p_session->params.rotation == 180)) { 979 980 thumbnail_info.output_width = (OMX_U32)p_thumb_dim->dst_dim.height; 981 thumbnail_info.output_height = (OMX_U32)p_thumb_dim->dst_dim.width; 982 thumbnail_info.rotation = p_session->params.rotation; 983 } 984 } else if ((p_thumb_dim->dst_dim.width > p_thumb_dim->src_dim.width) || 985 (p_thumb_dim->dst_dim.height > p_thumb_dim->src_dim.height)) { 986 CDBG_ERROR("%s:%d] Incorrect thumbnail dim %dx%d resetting to %dx%d", 987 __func__, __LINE__, p_thumb_dim->dst_dim.width, 988 p_thumb_dim->dst_dim.height, p_thumb_dim->src_dim.width, 989 p_thumb_dim->src_dim.height); 990 thumbnail_info.output_width = (OMX_U32)p_thumb_dim->src_dim.width; 991 thumbnail_info.output_height = (OMX_U32)p_thumb_dim->src_dim.height; 992 } 993 994 //If the main image and thumbnail aspect ratio are different, reset the 995 // thumbnail crop info to avoid distortion 996 double main_aspect_ratio = (double)p_main_dim->dst_dim.width / 997 (double)p_main_dim->dst_dim.height; 998 double thumb_aspect_ratio = (double)thumbnail_info.output_width / 999 (double)thumbnail_info.output_height; 1000 1001 if ((thumb_aspect_ratio - main_aspect_ratio) > ASPECT_TOLERANCE) { 1002 mm_jpeg_get_thumbnail_crop(p_thumb_dim, p_main_dim, 0); 1003 } else if((main_aspect_ratio - thumb_aspect_ratio) > ASPECT_TOLERANCE){ 1004 mm_jpeg_get_thumbnail_crop(p_thumb_dim, p_main_dim, 1); 1005 } 1006 1007 //Fill thumbnail crop info 1008 thumbnail_info.crop_info.nWidth = (OMX_U32)p_thumb_dim->crop.width; 1009 thumbnail_info.crop_info.nHeight = (OMX_U32)p_thumb_dim->crop.height; 1010 thumbnail_info.crop_info.nLeft = p_thumb_dim->crop.left; 1011 thumbnail_info.crop_info.nTop = p_thumb_dim->crop.top; 1012 1013 //If main image cropping/scaling is enabled, thumb FOV should be within 1014 //main image FOV 1015 if ((p_main_dim->crop.width != p_main_dim->src_dim.width) || 1016 (p_main_dim->crop.height != p_main_dim->src_dim.height)) { 1017 if ((p_thumb_dim->crop.left < p_main_dim->crop.left) || 1018 ((p_thumb_dim->crop.left + p_thumb_dim->crop.width) > 1019 (p_main_dim->crop.left + p_main_dim->crop.width)) || 1020 (p_thumb_dim->crop.top < p_main_dim->crop.top) || 1021 ((p_thumb_dim->crop.top + p_thumb_dim->crop.height) > 1022 (p_main_dim->crop.top + p_main_dim->crop.height))) { 1023 //Reset the FOV for the thumbnail 1024 CDBG_HIGH("%s:%d] Resetting the thumbnail FOV wrt main image", 1025 __func__, __LINE__); 1026 thumbnail_info.crop_info.nLeft = p_main_dim->crop.left; 1027 thumbnail_info.crop_info.nTop = p_main_dim->crop.height; 1028 if ((p_thumb_dim->crop.width > p_main_dim->crop.width) || 1029 (p_thumb_dim->crop.height > p_main_dim->crop.height)) { 1030 thumbnail_info.crop_info.nWidth = p_main_dim->crop.width; 1031 thumbnail_info.crop_info.nHeight = p_main_dim->crop.height; 1032 } 1033 } 1034 } 1035 1036 memset(p_frame_info, 0x0, sizeof(*p_frame_info)); 1037 1038 p_frame_info->cbcrStartOffset[0] = p_tmb_buf->offset.mp[0].len; 1039 p_frame_info->cbcrStartOffset[1] = p_tmb_buf->offset.mp[1].len; 1040 p_frame_info->yOffset = p_tmb_buf->offset.mp[0].offset; 1041 p_frame_info->cbcrOffset[0] = p_tmb_buf->offset.mp[1].offset; 1042 p_frame_info->cbcrOffset[1] = p_tmb_buf->offset.mp[2].offset; 1043 1044 ret = OMX_SetConfig(p_session->omx_handle, thumb_indextype, 1045 &thumbnail_info); 1046 if (ret) { 1047 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 1048 return ret; 1049 } 1050 1051 return ret; 1052 } 1053 1054 /** mm_jpeg_session_config_main_crop: 1055 * 1056 * Arguments: 1057 * @p_session: job session 1058 * 1059 * Return: 1060 * OMX error values 1061 * 1062 * Description: 1063 * Configure main image crop 1064 * 1065 **/ 1066 OMX_ERRORTYPE mm_jpeg_session_config_main_crop(mm_jpeg_job_session_t *p_session) 1067 { 1068 OMX_CONFIG_RECTTYPE rect_type_in, rect_type_out; 1069 OMX_ERRORTYPE ret = OMX_ErrorNone; 1070 mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job; 1071 mm_jpeg_dim_t *dim = &p_jobparams->main_dim; 1072 1073 if ((dim->crop.width == 0) || (dim->crop.height == 0)) { 1074 dim->crop.width = dim->src_dim.width; 1075 dim->crop.height = dim->src_dim.height; 1076 } 1077 /* error check first */ 1078 if ((dim->crop.width + dim->crop.left > dim->src_dim.width) || 1079 (dim->crop.height + dim->crop.top > dim->src_dim.height)) { 1080 CDBG_ERROR("%s:%d] invalid crop boundary (%d, %d) out of (%d, %d)", 1081 __func__, __LINE__, 1082 dim->crop.width + dim->crop.left, 1083 dim->crop.height + dim->crop.top, 1084 dim->src_dim.width, 1085 dim->src_dim.height); 1086 return OMX_ErrorBadParameter; 1087 } 1088 1089 memset(&rect_type_in, 0, sizeof(rect_type_in)); 1090 memset(&rect_type_out, 0, sizeof(rect_type_out)); 1091 rect_type_in.nPortIndex = 0; 1092 rect_type_out.nPortIndex = 0; 1093 1094 if ((dim->src_dim.width != dim->crop.width) || 1095 (dim->src_dim.height != dim->crop.height) || 1096 (dim->src_dim.width != dim->dst_dim.width) || 1097 (dim->src_dim.height != dim->dst_dim.height)) { 1098 /* Scaler information */ 1099 rect_type_in.nWidth = CEILING2(dim->crop.width); 1100 rect_type_in.nHeight = CEILING2(dim->crop.height); 1101 rect_type_in.nLeft = dim->crop.left; 1102 rect_type_in.nTop = dim->crop.top; 1103 1104 if (dim->dst_dim.width && dim->dst_dim.height) { 1105 rect_type_out.nWidth = (OMX_U32)dim->dst_dim.width; 1106 rect_type_out.nHeight = (OMX_U32)dim->dst_dim.height; 1107 } 1108 } 1109 1110 ret = OMX_SetConfig(p_session->omx_handle, OMX_IndexConfigCommonInputCrop, 1111 &rect_type_in); 1112 if (OMX_ErrorNone != ret) { 1113 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 1114 return ret; 1115 } 1116 1117 CDBG_HIGH("%s:%d] OMX_IndexConfigCommonInputCrop w = %d, h = %d, l = %d, t = %d," 1118 " port_idx = %d", __func__, __LINE__, 1119 (int)rect_type_in.nWidth, (int)rect_type_in.nHeight, 1120 (int)rect_type_in.nLeft, (int)rect_type_in.nTop, 1121 (int)rect_type_in.nPortIndex); 1122 1123 ret = OMX_SetConfig(p_session->omx_handle, OMX_IndexConfigCommonOutputCrop, 1124 &rect_type_out); 1125 if (OMX_ErrorNone != ret) { 1126 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 1127 return ret; 1128 } 1129 CDBG("%s:%d] OMX_IndexConfigCommonOutputCrop w = %d, h = %d," 1130 " port_idx = %d", __func__, __LINE__, 1131 (int)rect_type_out.nWidth, (int)rect_type_out.nHeight, 1132 (int)rect_type_out.nPortIndex); 1133 1134 return ret; 1135 } 1136 1137 /** mm_jpeg_session_config_main: 1138 * 1139 * Arguments: 1140 * @p_session: job session 1141 * 1142 * Return: 1143 * OMX error values 1144 * 1145 * Description: 1146 * Configure main image 1147 * 1148 **/ 1149 OMX_ERRORTYPE mm_jpeg_session_config_main(mm_jpeg_job_session_t *p_session) 1150 { 1151 OMX_ERRORTYPE rc = OMX_ErrorNone; 1152 1153 /* config port */ 1154 CDBG_HIGH("%s:%d] config port", __func__, __LINE__); 1155 rc = mm_jpeg_session_config_ports(p_session); 1156 if (OMX_ErrorNone != rc) { 1157 CDBG_ERROR("%s: config port failed", __func__); 1158 return rc; 1159 } 1160 1161 /* config buffer offset */ 1162 CDBG("%s:%d] config main buf offset", __func__, __LINE__); 1163 rc = mm_jpeg_session_config_main_buffer_offset(p_session); 1164 if (OMX_ErrorNone != rc) { 1165 CDBG_ERROR("%s: config buffer offset failed", __func__); 1166 return rc; 1167 } 1168 1169 /* set the encoding mode */ 1170 rc = mm_jpeg_encoding_mode(p_session); 1171 if (OMX_ErrorNone != rc) { 1172 CDBG_ERROR("%s: config encoding mode failed", __func__); 1173 return rc; 1174 } 1175 1176 /* set the metadata encrypt key */ 1177 rc = mm_jpeg_meta_enc_key(p_session); 1178 if (OMX_ErrorNone != rc) { 1179 CDBG_ERROR("%s: config session failed", __func__); 1180 return rc; 1181 } 1182 1183 /* set the mem ops */ 1184 rc = mm_jpeg_mem_ops(p_session); 1185 if (OMX_ErrorNone != rc) { 1186 CDBG_ERROR("%s: config mem ops failed", __func__); 1187 return rc; 1188 } 1189 /* set the jpeg speed mode */ 1190 rc = mm_jpeg_speed_mode(p_session); 1191 if (OMX_ErrorNone != rc) { 1192 CDBG_ERROR("%s: config speed mode failed", __func__); 1193 return rc; 1194 } 1195 1196 return rc; 1197 } 1198 1199 /** mm_jpeg_session_config_common: 1200 * 1201 * Arguments: 1202 * @p_session: job session 1203 * 1204 * Return: 1205 * OMX error values 1206 * 1207 * Description: 1208 * Configure common parameters 1209 * 1210 **/ 1211 OMX_ERRORTYPE mm_jpeg_session_config_common(mm_jpeg_job_session_t *p_session) 1212 { 1213 OMX_ERRORTYPE rc = OMX_ErrorNone; 1214 OMX_INDEXTYPE exif_idx; 1215 OMX_CONFIG_ROTATIONTYPE rotate; 1216 mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job; 1217 QOMX_EXIF_INFO exif_info; 1218 1219 /* set rotation */ 1220 memset(&rotate, 0, sizeof(rotate)); 1221 rotate.nPortIndex = 1; 1222 rotate.nRotation = (OMX_S32)p_jobparams->rotation; 1223 rc = OMX_SetConfig(p_session->omx_handle, OMX_IndexConfigCommonRotate, 1224 &rotate); 1225 if (OMX_ErrorNone != rc) { 1226 CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, rc); 1227 return rc; 1228 } 1229 CDBG("%s:%d] Set rotation to %d at port_idx = %d", __func__, __LINE__, 1230 (int)p_jobparams->rotation, (int)rotate.nPortIndex); 1231 1232 /* Set Exif data*/ 1233 memset(&p_session->exif_info_local[0], 0, sizeof(p_session->exif_info_local)); 1234 rc = OMX_GetExtensionIndex(p_session->omx_handle, QOMX_IMAGE_EXT_EXIF_NAME, 1235 &exif_idx); 1236 if (OMX_ErrorNone != rc) { 1237 CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, rc); 1238 return rc; 1239 } 1240 1241 CDBG("%s:%d] Num of exif entries passed from HAL: %d", __func__, __LINE__, 1242 (int)p_jobparams->exif_info.numOfEntries); 1243 if (p_jobparams->exif_info.numOfEntries > 0) { 1244 rc = OMX_SetConfig(p_session->omx_handle, exif_idx, 1245 &p_jobparams->exif_info); 1246 if (OMX_ErrorNone != rc) { 1247 CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, rc); 1248 return rc; 1249 } 1250 } 1251 /*parse aditional exif data from the metadata*/ 1252 exif_info.numOfEntries = 0; 1253 exif_info.exif_data = &p_session->exif_info_local[0]; 1254 process_meta_data(p_jobparams->p_metadata, &exif_info, 1255 &p_jobparams->cam_exif_params, p_jobparams->hal_version); 1256 /* After Parse metadata */ 1257 p_session->exif_count_local = (int)exif_info.numOfEntries; 1258 1259 if (exif_info.numOfEntries > 0) { 1260 /* set exif tags */ 1261 CDBG("%s:%d] exif tags from metadata count %d", __func__, __LINE__, 1262 (int)exif_info.numOfEntries); 1263 1264 rc = OMX_SetConfig(p_session->omx_handle, exif_idx, 1265 &exif_info); 1266 if (OMX_ErrorNone != rc) { 1267 CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, rc); 1268 return rc; 1269 } 1270 } 1271 1272 return rc; 1273 } 1274 1275 1276 1277 1278 /** mm_jpeg_session_abort: 1279 * 1280 * Arguments: 1281 * @p_session: jpeg session 1282 * 1283 * Return: 1284 * OMX_BOOL 1285 * 1286 * Description: 1287 * Abort ongoing job 1288 * 1289 **/ 1290 OMX_BOOL mm_jpeg_session_abort(mm_jpeg_job_session_t *p_session) 1291 { 1292 OMX_ERRORTYPE ret = OMX_ErrorNone; 1293 int rc = 0; 1294 1295 CDBG("%s:%d] E", __func__, __LINE__); 1296 pthread_mutex_lock(&p_session->lock); 1297 if (MM_JPEG_ABORT_NONE != p_session->abort_state) { 1298 pthread_mutex_unlock(&p_session->lock); 1299 CDBG_HIGH("%s:%d] **** ALREADY ABORTED", __func__, __LINE__); 1300 return 0; 1301 } 1302 p_session->abort_state = MM_JPEG_ABORT_INIT; 1303 if (OMX_TRUE == p_session->encoding) { 1304 p_session->state_change_pending = OMX_TRUE; 1305 1306 CDBG_HIGH("%s:%d] **** ABORTING", __func__, __LINE__); 1307 pthread_mutex_unlock(&p_session->lock); 1308 1309 ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandStateSet, 1310 OMX_StateIdle, NULL); 1311 1312 if (ret != OMX_ErrorNone) { 1313 CDBG_ERROR("%s:%d] OMX_SendCommand returned error %d", __func__, __LINE__, ret); 1314 return 1; 1315 } 1316 rc = mm_jpegenc_destroy_job(p_session); 1317 if (rc != 0) { 1318 CDBG_ERROR("%s:%d] Destroy job returned error %d", __func__, __LINE__, rc); 1319 } 1320 1321 pthread_mutex_lock(&p_session->lock); 1322 if (MM_JPEG_ABORT_INIT == p_session->abort_state) { 1323 CDBG("%s:%d] before wait", __func__, __LINE__); 1324 pthread_cond_wait(&p_session->cond, &p_session->lock); 1325 } 1326 CDBG("%s:%d] after wait", __func__, __LINE__); 1327 } 1328 p_session->abort_state = MM_JPEG_ABORT_DONE; 1329 pthread_mutex_unlock(&p_session->lock); 1330 1331 1332 // Abort next session 1333 if (p_session->next_session) { 1334 mm_jpeg_session_abort(p_session->next_session); 1335 } 1336 1337 CDBG("%s:%d] X", __func__, __LINE__); 1338 return 0; 1339 } 1340 1341 1342 /** mm_jpeg_configure_params 1343 * 1344 * Arguments: 1345 * @p_session: encode session 1346 * 1347 * Return: 1348 * none 1349 * 1350 * Description: 1351 * Configure the job specific params 1352 * 1353 **/ 1354 static OMX_ERRORTYPE mm_jpeg_configure_job_params( 1355 mm_jpeg_job_session_t *p_session) 1356 { 1357 OMX_ERRORTYPE ret = OMX_ErrorNone; 1358 OMX_IMAGE_PARAM_QFACTORTYPE q_factor; 1359 QOMX_WORK_BUFFER work_buffer; 1360 OMX_INDEXTYPE work_buffer_index; 1361 mm_jpeg_encode_params_t *p_params = &p_session->params; 1362 mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job; 1363 int i; 1364 1365 /* common config */ 1366 ret = mm_jpeg_session_config_common(p_session); 1367 if (OMX_ErrorNone != ret) { 1368 CDBG_ERROR("%s:%d] config common failed", __func__, __LINE__); 1369 1370 } 1371 1372 /* config Main Image crop */ 1373 CDBG("%s:%d] config main crop", __func__, __LINE__); 1374 ret = mm_jpeg_session_config_main_crop(p_session); 1375 if (OMX_ErrorNone != ret) { 1376 CDBG_ERROR("%s: config crop failed", __func__); 1377 return ret; 1378 } 1379 1380 /* set quality */ 1381 memset(&q_factor, 0, sizeof(q_factor)); 1382 q_factor.nPortIndex = 0; 1383 q_factor.nQFactor = p_params->quality; 1384 ret = OMX_SetConfig(p_session->omx_handle, OMX_IndexParamQFactor, &q_factor); 1385 CDBG("%s:%d] config QFactor: %d", __func__, __LINE__, (int)q_factor.nQFactor); 1386 if (OMX_ErrorNone != ret) { 1387 CDBG_ERROR("%s:%d] Error setting Q factor %d", __func__, __LINE__, ret); 1388 return ret; 1389 } 1390 1391 /* config thumbnail */ 1392 ret = mm_jpeg_session_config_thumbnail(p_session); 1393 if (OMX_ErrorNone != ret) { 1394 CDBG_ERROR("%s:%d] config thumbnail img failed", __func__, __LINE__); 1395 return ret; 1396 } 1397 1398 //Pass the ION buffer to be used as o/p for HW 1399 memset(&work_buffer, 0x0, sizeof(QOMX_WORK_BUFFER)); 1400 ret = OMX_GetExtensionIndex(p_session->omx_handle, 1401 QOMX_IMAGE_EXT_WORK_BUFFER_NAME, 1402 &work_buffer_index); 1403 if (ret) { 1404 CDBG_ERROR("%s:%d] Error getting work buffer index %d", 1405 __func__, __LINE__, ret); 1406 return ret; 1407 } 1408 work_buffer.fd = p_session->work_buffer.p_pmem_fd; 1409 work_buffer.vaddr = p_session->work_buffer.addr; 1410 work_buffer.length = (uint32_t)p_session->work_buffer.size; 1411 CDBG_ERROR("%s:%d] Work buffer %d %p WorkBufSize: %d", __func__, __LINE__, 1412 work_buffer.fd, work_buffer.vaddr, work_buffer.length); 1413 1414 ret = OMX_SetConfig(p_session->omx_handle, work_buffer_index, 1415 &work_buffer); 1416 if (ret) { 1417 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 1418 return ret; 1419 } 1420 1421 /* set metadata */ 1422 ret = mm_jpeg_metadata(p_session); 1423 if (OMX_ErrorNone != ret) { 1424 CDBG_ERROR("%s: config makernote data failed", __func__); 1425 return ret; 1426 } 1427 1428 /* set QTable */ 1429 for (i = 0; i < QTABLE_MAX; i++) { 1430 if (p_jobparams->qtable_set[i]) { 1431 ret = OMX_SetConfig(p_session->omx_handle, 1432 OMX_IndexParamQuantizationTable, &p_jobparams->qtable[i]); 1433 if (OMX_ErrorNone != ret) { 1434 CDBG_ERROR("%s:%d] set QTable Error", __func__, __LINE__); 1435 return ret; 1436 } 1437 } 1438 } 1439 1440 return ret; 1441 } 1442 1443 /** mm_jpeg_session_configure: 1444 * 1445 * Arguments: 1446 * @data: encode session 1447 * 1448 * Return: 1449 * none 1450 * 1451 * Description: 1452 * Configure the session 1453 * 1454 **/ 1455 static OMX_ERRORTYPE mm_jpeg_session_configure(mm_jpeg_job_session_t *p_session) 1456 { 1457 OMX_ERRORTYPE ret = OMX_ErrorNone; 1458 1459 CDBG("%s:%d] E ", __func__, __LINE__); 1460 1461 MM_JPEG_CHK_ABORT(p_session, ret, error); 1462 1463 /* config main img */ 1464 ret = mm_jpeg_session_config_main(p_session); 1465 if (OMX_ErrorNone != ret) { 1466 CDBG_ERROR("%s:%d] config main img failed", __func__, __LINE__); 1467 goto error; 1468 } 1469 ret = mm_jpeg_session_change_state(p_session, OMX_StateIdle, 1470 mm_jpeg_session_send_buffers); 1471 if (ret) { 1472 CDBG_ERROR("%s:%d] change state to idle failed %d", 1473 __func__, __LINE__, ret); 1474 goto error; 1475 } 1476 1477 ret = mm_jpeg_session_change_state(p_session, OMX_StateExecuting, 1478 NULL); 1479 if (ret) { 1480 CDBG_ERROR("%s:%d] change state to executing failed %d", 1481 __func__, __LINE__, ret); 1482 goto error; 1483 } 1484 1485 error: 1486 CDBG("%s:%d] X ret %d", __func__, __LINE__, ret); 1487 return ret; 1488 } 1489 1490 1491 1492 1493 1494 1495 /** mm_jpeg_session_encode: 1496 * 1497 * Arguments: 1498 * @p_session: encode session 1499 * 1500 * Return: 1501 * OMX_ERRORTYPE 1502 * 1503 * Description: 1504 * Start the encoding 1505 * 1506 **/ 1507 static OMX_ERRORTYPE mm_jpeg_session_encode(mm_jpeg_job_session_t *p_session) 1508 { 1509 OMX_ERRORTYPE ret = OMX_ErrorNone; 1510 mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job; 1511 1512 pthread_mutex_lock(&p_session->lock); 1513 p_session->abort_state = MM_JPEG_ABORT_NONE; 1514 p_session->encoding = OMX_FALSE; 1515 pthread_mutex_unlock(&p_session->lock); 1516 1517 if (p_session->thumb_from_main) { 1518 if (0 > p_jobparams->src_index) { 1519 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 1520 ret = OMX_ErrorUnsupportedIndex; 1521 goto error; 1522 } 1523 p_jobparams->thumb_index = (uint32_t)p_jobparams->src_index; 1524 p_jobparams->thumb_dim.crop = p_jobparams->main_dim.crop; 1525 } 1526 1527 if (OMX_FALSE == p_session->config) { 1528 ret = mm_jpeg_session_configure(p_session); 1529 if (ret) { 1530 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 1531 goto error; 1532 } 1533 p_session->config = OMX_TRUE; 1534 } 1535 1536 ret = mm_jpeg_configure_job_params(p_session); 1537 if (ret) { 1538 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 1539 goto error; 1540 } 1541 pthread_mutex_lock(&p_session->lock); 1542 p_session->encoding = OMX_TRUE; 1543 pthread_mutex_unlock(&p_session->lock); 1544 1545 MM_JPEG_CHK_ABORT(p_session, ret, error); 1546 1547 #ifdef MM_JPEG_DUMP_INPUT 1548 char filename[256]; 1549 snprintf(filename, sizeof(filename), 1550 QCAMERA_DUMP_FRM_LOCATION"jpeg/mm_jpeg_int%d.yuv", p_session->ebd_count); 1551 DUMP_TO_FILE(filename, 1552 p_session->p_in_omx_buf[p_jobparams->src_index]->pBuffer, 1553 (size_t)p_session->p_in_omx_buf[p_jobparams->src_index]->nAllocLen); 1554 #endif 1555 1556 ret = OMX_EmptyThisBuffer(p_session->omx_handle, 1557 p_session->p_in_omx_buf[p_jobparams->src_index]); 1558 if (ret) { 1559 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 1560 goto error; 1561 } 1562 1563 if (p_session->params.encode_thumbnail) { 1564 #ifdef MM_JPEG_DUMP_INPUT 1565 char thumb_filename[FILENAME_MAX]; 1566 snprintf(thumb_filename, sizeof(thumb_filename), 1567 QCAMERA_DUMP_FRM_LOCATION"jpeg/mm_jpeg_int_t%d.yuv", p_session->ebd_count); 1568 DUMP_TO_FILE(filename, 1569 p_session->p_in_omx_thumb_buf[p_jobparams->thumb_index]->pBuffer, 1570 (size_t)p_session->p_in_omx_thumb_buf[p_jobparams->thumb_index]->nAllocLen); 1571 #endif 1572 ret = OMX_EmptyThisBuffer(p_session->omx_handle, 1573 p_session->p_in_omx_thumb_buf[p_jobparams->thumb_index]); 1574 if (ret) { 1575 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 1576 goto error; 1577 } 1578 } 1579 1580 ret = OMX_FillThisBuffer(p_session->omx_handle, 1581 p_session->p_out_omx_buf[p_jobparams->dst_index]); 1582 if (ret) { 1583 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 1584 goto error; 1585 } 1586 1587 MM_JPEG_CHK_ABORT(p_session, ret, error); 1588 1589 error: 1590 1591 CDBG("%s:%d] X ", __func__, __LINE__); 1592 return ret; 1593 } 1594 1595 /** mm_jpeg_process_encoding_job: 1596 * 1597 * Arguments: 1598 * @my_obj: jpeg client 1599 * @job_node: job node 1600 * 1601 * Return: 1602 * 0 for success -1 otherwise 1603 * 1604 * Description: 1605 * Start the encoding job 1606 * 1607 **/ 1608 int32_t mm_jpeg_process_encoding_job(mm_jpeg_obj *my_obj, mm_jpeg_job_q_node_t* job_node) 1609 { 1610 mm_jpeg_q_data_t qdata; 1611 int32_t rc = 0; 1612 OMX_ERRORTYPE ret = OMX_ErrorNone; 1613 mm_jpeg_job_session_t *p_session = NULL; 1614 uint32_t buf_idx; 1615 1616 /* check if valid session */ 1617 p_session = mm_jpeg_get_session(my_obj, job_node->enc_info.job_id); 1618 if (NULL == p_session) { 1619 CDBG_ERROR("%s:%d] invalid job id %x", __func__, __LINE__, 1620 job_node->enc_info.job_id); 1621 return -1; 1622 } 1623 1624 CDBG("%s:%d] before dequeue session %d", 1625 __func__, __LINE__, ret); 1626 1627 /* dequeue available omx handle */ 1628 qdata = mm_jpeg_queue_deq(p_session->session_handle_q); 1629 p_session = qdata.p; 1630 1631 if (NULL == p_session) { 1632 CDBG_HIGH("%s:%d] No available sessions %d", 1633 __func__, __LINE__, ret); 1634 /* No available handles */ 1635 qdata.p = job_node; 1636 mm_jpeg_queue_enq_head(&my_obj->job_mgr.job_queue, qdata); 1637 1638 CDBG_HIGH("%s:%d]end enqueue %d", 1639 __func__, __LINE__, ret); 1640 return rc; 1641 1642 } 1643 1644 p_session->auto_out_buf = OMX_FALSE; 1645 if (job_node->enc_info.encode_job.dst_index < 0) { 1646 /* dequeue available output buffer idx */ 1647 qdata = mm_jpeg_queue_deq(p_session->out_buf_q); 1648 buf_idx = qdata.u32; 1649 1650 if (0U == buf_idx) { 1651 CDBG_ERROR("%s:%d] No available output buffers %d", 1652 __func__, __LINE__, ret); 1653 return OMX_ErrorUndefined; 1654 } 1655 1656 buf_idx--; 1657 1658 job_node->enc_info.encode_job.dst_index = (int32_t)buf_idx; 1659 p_session->auto_out_buf = OMX_TRUE; 1660 } 1661 1662 /* sent encode cmd to OMX, queue job into ongoing queue */ 1663 qdata.p = job_node; 1664 rc = mm_jpeg_queue_enq(&my_obj->ongoing_job_q, qdata); 1665 if (rc) { 1666 CDBG_ERROR("%s:%d] jpeg enqueue failed %d", 1667 __func__, __LINE__, ret); 1668 goto error; 1669 } 1670 1671 p_session->encode_job = job_node->enc_info.encode_job; 1672 p_session->jobId = job_node->enc_info.job_id; 1673 ret = mm_jpeg_session_encode(p_session); 1674 if (ret) { 1675 CDBG_ERROR("%s:%d] encode session failed", __func__, __LINE__); 1676 goto error; 1677 } 1678 1679 CDBG_HIGH("%s:%d] Success X ", __func__, __LINE__); 1680 return rc; 1681 1682 error: 1683 1684 if ((OMX_ErrorNone != ret) && 1685 (NULL != p_session->params.jpeg_cb)) { 1686 p_session->job_status = JPEG_JOB_STATUS_ERROR; 1687 CDBG_ERROR("%s:%d] send jpeg error callback %d", __func__, __LINE__, 1688 p_session->job_status); 1689 p_session->params.jpeg_cb(p_session->job_status, 1690 p_session->client_hdl, 1691 p_session->jobId, 1692 NULL, 1693 p_session->params.userdata); 1694 } 1695 1696 /*remove the job*/ 1697 mm_jpegenc_job_done(p_session); 1698 CDBG("%s:%d] Error X ", __func__, __LINE__); 1699 1700 return rc; 1701 } 1702 1703 1704 1705 /** mm_jpeg_jobmgr_thread: 1706 * 1707 * Arguments: 1708 * @my_obj: jpeg object 1709 * 1710 * Return: 1711 * 0 for success else failure 1712 * 1713 * Description: 1714 * job manager thread main function 1715 * 1716 **/ 1717 static void *mm_jpeg_jobmgr_thread(void *data) 1718 { 1719 mm_jpeg_q_data_t qdata; 1720 int rc = 0; 1721 int running = 1; 1722 uint32_t num_ongoing_jobs = 0; 1723 mm_jpeg_obj *my_obj = (mm_jpeg_obj*)data; 1724 mm_jpeg_job_cmd_thread_t *cmd_thread = &my_obj->job_mgr; 1725 mm_jpeg_job_q_node_t* node = NULL; 1726 prctl(PR_SET_NAME, (unsigned long)"mm_jpeg_thread", 0, 0, 0); 1727 1728 do { 1729 do { 1730 rc = cam_sem_wait(&cmd_thread->job_sem); 1731 if (rc != 0 && errno != EINVAL) { 1732 CDBG_ERROR("%s: cam_sem_wait error (%s)", 1733 __func__, strerror(errno)); 1734 return NULL; 1735 } 1736 } while (rc != 0); 1737 1738 /* check ongoing q size */ 1739 num_ongoing_jobs = mm_jpeg_queue_get_size(&my_obj->ongoing_job_q); 1740 if (num_ongoing_jobs >= NUM_MAX_JPEG_CNCURRENT_JOBS) { 1741 CDBG("%s:%d] ongoing job already reach max %d", __func__, 1742 __LINE__, num_ongoing_jobs); 1743 continue; 1744 } 1745 1746 pthread_mutex_lock(&my_obj->job_lock); 1747 /* can go ahead with new work */ 1748 qdata = mm_jpeg_queue_deq(&cmd_thread->job_queue); 1749 node = (mm_jpeg_job_q_node_t*)qdata.p; 1750 if (node != NULL) { 1751 switch (node->type) { 1752 case MM_JPEG_CMD_TYPE_JOB: 1753 rc = mm_jpeg_process_encoding_job(my_obj, node); 1754 break; 1755 case MM_JPEG_CMD_TYPE_DECODE_JOB: 1756 rc = mm_jpegdec_process_decoding_job(my_obj, node); 1757 break; 1758 case MM_JPEG_CMD_TYPE_EXIT: 1759 default: 1760 /* free node */ 1761 free(node); 1762 /* set running flag to false */ 1763 running = 0; 1764 break; 1765 } 1766 } 1767 pthread_mutex_unlock(&my_obj->job_lock); 1768 1769 } while (running); 1770 return NULL; 1771 } 1772 1773 /** mm_jpeg_jobmgr_thread_launch: 1774 * 1775 * Arguments: 1776 * @my_obj: jpeg object 1777 * 1778 * Return: 1779 * 0 for success else failure 1780 * 1781 * Description: 1782 * launches the job manager thread 1783 * 1784 **/ 1785 int32_t mm_jpeg_jobmgr_thread_launch(mm_jpeg_obj *my_obj) 1786 { 1787 int32_t rc = 0; 1788 mm_jpeg_job_cmd_thread_t *job_mgr = &my_obj->job_mgr; 1789 1790 cam_sem_init(&job_mgr->job_sem, 0); 1791 mm_jpeg_queue_init(&job_mgr->job_queue); 1792 1793 /* launch the thread */ 1794 pthread_create(&job_mgr->pid, 1795 NULL, 1796 mm_jpeg_jobmgr_thread, 1797 (void *)my_obj); 1798 pthread_setname_np(job_mgr->pid, "CAM_jpeg_jobmgr"); 1799 return rc; 1800 } 1801 1802 /** mm_jpeg_jobmgr_thread_release: 1803 * 1804 * Arguments: 1805 * @my_obj: jpeg object 1806 * 1807 * Return: 1808 * 0 for success else failure 1809 * 1810 * Description: 1811 * Releases the job manager thread 1812 * 1813 **/ 1814 int32_t mm_jpeg_jobmgr_thread_release(mm_jpeg_obj * my_obj) 1815 { 1816 mm_jpeg_q_data_t qdata; 1817 int32_t rc = 0; 1818 mm_jpeg_job_cmd_thread_t * cmd_thread = &my_obj->job_mgr; 1819 mm_jpeg_job_q_node_t* node = 1820 (mm_jpeg_job_q_node_t *)malloc(sizeof(mm_jpeg_job_q_node_t)); 1821 if (NULL == node) { 1822 CDBG_ERROR("%s: No memory for mm_jpeg_job_q_node_t", __func__); 1823 return -1; 1824 } 1825 1826 memset(node, 0, sizeof(mm_jpeg_job_q_node_t)); 1827 node->type = MM_JPEG_CMD_TYPE_EXIT; 1828 1829 qdata.p = node; 1830 mm_jpeg_queue_enq(&cmd_thread->job_queue, qdata); 1831 cam_sem_post(&cmd_thread->job_sem); 1832 1833 /* wait until cmd thread exits */ 1834 if (pthread_join(cmd_thread->pid, NULL) != 0) { 1835 CDBG("%s: pthread dead already", __func__); 1836 } 1837 mm_jpeg_queue_deinit(&cmd_thread->job_queue); 1838 1839 cam_sem_destroy(&cmd_thread->job_sem); 1840 memset(cmd_thread, 0, sizeof(mm_jpeg_job_cmd_thread_t)); 1841 return rc; 1842 } 1843 1844 /** mm_jpeg_init: 1845 * 1846 * Arguments: 1847 * @my_obj: jpeg object 1848 * 1849 * Return: 1850 * 0 for success else failure 1851 * 1852 * Description: 1853 * Initializes the jpeg client 1854 * 1855 **/ 1856 int32_t mm_jpeg_init(mm_jpeg_obj *my_obj) 1857 { 1858 int32_t rc = 0; 1859 uint32_t work_buf_size; 1860 unsigned int i = 0; 1861 unsigned int initial_workbufs_cnt = 1; 1862 1863 /* init locks */ 1864 pthread_mutex_init(&my_obj->job_lock, NULL); 1865 1866 /* init ongoing job queue */ 1867 rc = mm_jpeg_queue_init(&my_obj->ongoing_job_q); 1868 if (0 != rc) { 1869 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 1870 pthread_mutex_destroy(&my_obj->job_lock); 1871 return -1; 1872 } 1873 1874 1875 /* init job semaphore and launch jobmgr thread */ 1876 CDBG("%s:%d] Launch jobmgr thread rc %d", __func__, __LINE__, rc); 1877 rc = mm_jpeg_jobmgr_thread_launch(my_obj); 1878 if (0 != rc) { 1879 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 1880 mm_jpeg_queue_deinit(&my_obj->ongoing_job_q); 1881 pthread_mutex_destroy(&my_obj->job_lock); 1882 return -1; 1883 } 1884 1885 /* set work buf size from max picture size */ 1886 if (my_obj->max_pic_w <= 0 || my_obj->max_pic_h <= 0) { 1887 CDBG_ERROR("%s:%d] Width and height are not valid " 1888 "dimensions, cannot calc work buf size",__func__, __LINE__); 1889 mm_jpeg_jobmgr_thread_release(my_obj); 1890 mm_jpeg_queue_deinit(&my_obj->ongoing_job_q); 1891 pthread_mutex_destroy(&my_obj->job_lock); 1892 return -1; 1893 } 1894 work_buf_size = CEILING64((uint32_t)my_obj->max_pic_w) * 1895 CEILING64((uint32_t)my_obj->max_pic_h) * 3U / 2U; 1896 for (i = 0; i < initial_workbufs_cnt; i++) { 1897 my_obj->ionBuffer[i].size = CEILING32(work_buf_size); 1898 CDBG_HIGH("Max picture size %d x %d, WorkBufSize = %zu", 1899 my_obj->max_pic_w, my_obj->max_pic_h, my_obj->ionBuffer[i].size); 1900 1901 my_obj->ionBuffer[i].addr = (uint8_t *)buffer_allocate(&my_obj->ionBuffer[i], 1); 1902 if (NULL == my_obj->ionBuffer[i].addr) { 1903 while (i--) { 1904 buffer_deallocate(&my_obj->ionBuffer[i]); 1905 } 1906 mm_jpeg_jobmgr_thread_release(my_obj); 1907 mm_jpeg_queue_deinit(&my_obj->ongoing_job_q); 1908 pthread_mutex_destroy(&my_obj->job_lock); 1909 CDBG_ERROR("%s:%d] Ion allocation failed",__func__, __LINE__); 1910 return -1; 1911 } 1912 } 1913 1914 my_obj->work_buf_cnt = i; 1915 1916 /* load OMX */ 1917 if (OMX_ErrorNone != OMX_Init()) { 1918 /* roll back in error case */ 1919 CDBG_ERROR("%s:%d] OMX_Init failed (%d)", __func__, __LINE__, rc); 1920 for (i = 0; i < initial_workbufs_cnt; i++) { 1921 buffer_deallocate(&my_obj->ionBuffer[i]); 1922 } 1923 mm_jpeg_jobmgr_thread_release(my_obj); 1924 mm_jpeg_queue_deinit(&my_obj->ongoing_job_q); 1925 pthread_mutex_destroy(&my_obj->job_lock); 1926 } 1927 1928 #ifdef LOAD_ADSP_RPC_LIB 1929 my_obj->adsprpc_lib_handle = dlopen("libadsprpc.so", RTLD_NOW); 1930 if (NULL == my_obj->adsprpc_lib_handle) { 1931 CDBG_ERROR("%s:%d] Cannot load the library", __func__, __LINE__); 1932 /* not returning error here bcoz even if this loading fails 1933 we can go ahead with SW JPEG enc */ 1934 } 1935 #endif 1936 1937 return rc; 1938 } 1939 1940 /** mm_jpeg_deinit: 1941 * 1942 * Arguments: 1943 * @my_obj: jpeg object 1944 * 1945 * Return: 1946 * 0 for success else failure 1947 * 1948 * Description: 1949 * Deinits the jpeg client 1950 * 1951 **/ 1952 int32_t mm_jpeg_deinit(mm_jpeg_obj *my_obj) 1953 { 1954 int32_t rc = 0; 1955 uint32_t i = 0; 1956 1957 /* release jobmgr thread */ 1958 rc = mm_jpeg_jobmgr_thread_release(my_obj); 1959 if (0 != rc) { 1960 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 1961 } 1962 1963 /* unload OMX engine */ 1964 OMX_Deinit(); 1965 1966 /* deinit ongoing job and cb queue */ 1967 rc = mm_jpeg_queue_deinit(&my_obj->ongoing_job_q); 1968 if (0 != rc) { 1969 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 1970 } 1971 1972 for (i = 0; i < my_obj->work_buf_cnt; i++) { 1973 /*Release the ION buffer*/ 1974 rc = buffer_deallocate(&my_obj->ionBuffer[i]); 1975 if (0 != rc) { 1976 CDBG_ERROR("%s:%d] Error releasing ION buffer", __func__, __LINE__); 1977 } 1978 } 1979 1980 /* destroy locks */ 1981 pthread_mutex_destroy(&my_obj->job_lock); 1982 1983 return rc; 1984 } 1985 1986 /** mm_jpeg_new_client: 1987 * 1988 * Arguments: 1989 * @my_obj: jpeg object 1990 * 1991 * Return: 1992 * 0 for success else failure 1993 * 1994 * Description: 1995 * Create new jpeg client 1996 * 1997 **/ 1998 uint32_t mm_jpeg_new_client(mm_jpeg_obj *my_obj) 1999 { 2000 uint32_t client_hdl = 0; 2001 uint8_t idx; 2002 int i = 0; 2003 2004 if (my_obj->num_clients >= MAX_JPEG_CLIENT_NUM) { 2005 CDBG_ERROR("%s: num of clients reached limit", __func__); 2006 return client_hdl; 2007 } 2008 2009 for (idx = 0; idx < MAX_JPEG_CLIENT_NUM; idx++) { 2010 if (0 == my_obj->clnt_mgr[idx].is_used) { 2011 break; 2012 } 2013 } 2014 2015 if (idx < MAX_JPEG_CLIENT_NUM) { 2016 /* client session avail */ 2017 /* generate client handler by index */ 2018 client_hdl = mm_jpeg_util_generate_handler(idx); 2019 2020 /* update client session */ 2021 my_obj->clnt_mgr[idx].is_used = 1; 2022 my_obj->clnt_mgr[idx].client_handle = client_hdl; 2023 2024 pthread_mutex_init(&my_obj->clnt_mgr[idx].lock, NULL); 2025 for (i = 0; i < MM_JPEG_MAX_SESSION; i++) { 2026 memset(&my_obj->clnt_mgr[idx].session[i], 0x0, sizeof(mm_jpeg_job_session_t)); 2027 } 2028 2029 /* increse client count */ 2030 my_obj->num_clients++; 2031 } 2032 2033 return client_hdl; 2034 } 2035 2036 /** mm_jpeg_start_job: 2037 * 2038 * Arguments: 2039 * @my_obj: jpeg object 2040 * @client_hdl: client handle 2041 * @job: pointer to encode job 2042 * @jobId: job id 2043 * 2044 * Return: 2045 * 0 for success else failure 2046 * 2047 * Description: 2048 * Start the encoding job 2049 * 2050 **/ 2051 int32_t mm_jpeg_start_job(mm_jpeg_obj *my_obj, 2052 mm_jpeg_job_t *job, 2053 uint32_t *job_id) 2054 { 2055 mm_jpeg_q_data_t qdata; 2056 int32_t rc = -1; 2057 uint8_t session_idx = 0; 2058 uint8_t client_idx = 0; 2059 mm_jpeg_job_q_node_t* node = NULL; 2060 mm_jpeg_job_session_t *p_session = NULL; 2061 mm_jpeg_encode_job_t *p_jobparams = &job->encode_job; 2062 2063 *job_id = 0; 2064 2065 /* check if valid session */ 2066 session_idx = GET_SESSION_IDX(p_jobparams->session_id); 2067 client_idx = GET_CLIENT_IDX(p_jobparams->session_id); 2068 CDBG_HIGH("%s:%d] session_idx %d client idx %d", __func__, __LINE__, 2069 session_idx, client_idx); 2070 2071 if ((session_idx >= MM_JPEG_MAX_SESSION) || 2072 (client_idx >= MAX_JPEG_CLIENT_NUM)) { 2073 CDBG_ERROR("%s:%d] invalid session id %x", __func__, __LINE__, 2074 job->encode_job.session_id); 2075 return rc; 2076 } 2077 2078 p_session = &my_obj->clnt_mgr[client_idx].session[session_idx]; 2079 if (OMX_FALSE == p_session->active) { 2080 CDBG_ERROR("%s:%d] session not active %x", __func__, __LINE__, 2081 job->encode_job.session_id); 2082 return rc; 2083 } 2084 2085 if ((p_jobparams->src_index >= (int32_t)p_session->params.num_src_bufs) || 2086 (p_jobparams->dst_index >= (int32_t)p_session->params.num_dst_bufs)) { 2087 CDBG_ERROR("%s:%d] invalid buffer indices", __func__, __LINE__); 2088 return rc; 2089 } 2090 2091 /* enqueue new job into todo job queue */ 2092 node = (mm_jpeg_job_q_node_t *)malloc(sizeof(mm_jpeg_job_q_node_t)); 2093 if (NULL == node) { 2094 CDBG_ERROR("%s: No memory for mm_jpeg_job_q_node_t", __func__); 2095 return -1; 2096 } 2097 2098 ATRACE_INT("Camera:JPEG", 2099 (int32_t)((uint32_t)session_idx<<16 | ++p_session->job_index)); 2100 2101 *job_id = job->encode_job.session_id | 2102 (((uint32_t)p_session->job_hist++ % JOB_HIST_MAX) << 16); 2103 2104 memset(node, 0, sizeof(mm_jpeg_job_q_node_t)); 2105 node->enc_info.encode_job = job->encode_job; 2106 if (p_session->thumb_from_main) { 2107 node->enc_info.encode_job.thumb_dim.src_dim = 2108 node->enc_info.encode_job.main_dim.src_dim; 2109 node->enc_info.encode_job.thumb_dim.crop = 2110 node->enc_info.encode_job.main_dim.crop; 2111 } 2112 node->enc_info.job_id = *job_id; 2113 node->enc_info.client_handle = p_session->client_hdl; 2114 node->type = MM_JPEG_CMD_TYPE_JOB; 2115 2116 2117 2118 qdata.p = node; 2119 rc = mm_jpeg_queue_enq(&my_obj->job_mgr.job_queue, qdata); 2120 if (0 == rc) { 2121 cam_sem_post(&my_obj->job_mgr.job_sem); 2122 } 2123 2124 CDBG_HIGH("%s:%d] X", __func__, __LINE__); 2125 2126 return rc; 2127 } 2128 2129 2130 2131 /** mm_jpeg_abort_job: 2132 * 2133 * Arguments: 2134 * @my_obj: jpeg object 2135 * @client_hdl: client handle 2136 * @jobId: job id 2137 * 2138 * Return: 2139 * 0 for success else failure 2140 * 2141 * Description: 2142 * Abort the encoding session 2143 * 2144 **/ 2145 int32_t mm_jpeg_abort_job(mm_jpeg_obj *my_obj, 2146 uint32_t jobId) 2147 { 2148 int32_t rc = -1; 2149 mm_jpeg_job_q_node_t *node = NULL; 2150 mm_jpeg_job_session_t *p_session = NULL; 2151 2152 CDBG("%s:%d] ", __func__, __LINE__); 2153 pthread_mutex_lock(&my_obj->job_lock); 2154 2155 /* abort job if in todo queue */ 2156 node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->job_mgr.job_queue, jobId); 2157 if (NULL != node) { 2158 free(node); 2159 goto abort_done; 2160 } 2161 2162 /* abort job if in ongoing queue */ 2163 node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->ongoing_job_q, jobId); 2164 if (NULL != node) { 2165 /* find job that is OMX ongoing, ask OMX to abort the job */ 2166 p_session = mm_jpeg_get_session(my_obj, node->enc_info.job_id); 2167 if (p_session) { 2168 mm_jpeg_session_abort(p_session); 2169 } else { 2170 CDBG_ERROR("%s:%d] Invalid job id 0x%x", __func__, __LINE__, 2171 node->enc_info.job_id); 2172 } 2173 free(node); 2174 goto abort_done; 2175 } 2176 2177 abort_done: 2178 pthread_mutex_unlock(&my_obj->job_lock); 2179 2180 return rc; 2181 } 2182 2183 2184 #ifdef MM_JPEG_READ_META_KEYFILE 2185 static int32_t mm_jpeg_read_meta_keyfile(mm_jpeg_job_session_t *p_session, 2186 const char *filename) 2187 { 2188 int rc = 0; 2189 FILE *fp = NULL; 2190 size_t file_size = 0; 2191 fp = fopen(filename, "r"); 2192 if (!fp) { 2193 CDBG_ERROR("%s:%d] Key not present", __func__, __LINE__); 2194 return -1; 2195 } 2196 fseek(fp, 0, SEEK_END); 2197 file_size = (size_t)ftell(fp); 2198 fseek(fp, 0, SEEK_SET); 2199 2200 p_session->meta_enc_key = (uint8_t *) malloc((file_size + 1) * sizeof(uint8_t)); 2201 2202 if (!p_session->meta_enc_key) { 2203 CDBG_ERROR("%s:%d] error", __func__, __LINE__); 2204 return -1; 2205 } 2206 2207 fread(p_session->meta_enc_key, 1, file_size, fp); 2208 fclose(fp); 2209 2210 p_session->meta_enc_keylen = file_size; 2211 2212 return rc; 2213 } 2214 #endif // MM_JPEG_READ_META_KEYFILE 2215 2216 /** mm_jpeg_create_session: 2217 * 2218 * Arguments: 2219 * @my_obj: jpeg object 2220 * @client_hdl: client handle 2221 * @p_params: pointer to encode params 2222 * @p_session_id: session id 2223 * 2224 * Return: 2225 * 0 for success else failure 2226 * 2227 * Description: 2228 * Start the encoding session 2229 * 2230 **/ 2231 int32_t mm_jpeg_create_session(mm_jpeg_obj *my_obj, 2232 uint32_t client_hdl, 2233 mm_jpeg_encode_params_t *p_params, 2234 uint32_t* p_session_id) 2235 { 2236 mm_jpeg_q_data_t qdata; 2237 int32_t rc = 0; 2238 OMX_ERRORTYPE ret = OMX_ErrorNone; 2239 uint8_t clnt_idx = 0; 2240 int session_idx = -1; 2241 mm_jpeg_job_session_t *p_session = NULL; 2242 mm_jpeg_job_session_t * p_prev_session = NULL; 2243 *p_session_id = 0; 2244 uint32_t i = 0; 2245 uint32_t num_omx_sessions; 2246 uint32_t work_buf_size; 2247 mm_jpeg_queue_t *p_session_handle_q, *p_out_buf_q; 2248 uint32_t work_bufs_need; 2249 char trace_tag[32]; 2250 2251 /* validate the parameters */ 2252 if ((p_params->num_src_bufs > MM_JPEG_MAX_BUF) 2253 || (p_params->num_dst_bufs > MM_JPEG_MAX_BUF)) { 2254 CDBG_ERROR("%s:%d] invalid num buffers", __func__, __LINE__); 2255 return -1; 2256 } 2257 2258 /* check if valid client */ 2259 clnt_idx = mm_jpeg_util_get_index_by_handler(client_hdl); 2260 if (clnt_idx >= MAX_JPEG_CLIENT_NUM) { 2261 CDBG_ERROR("%s: invalid client with handler (%d)", __func__, client_hdl); 2262 return -1; 2263 } 2264 2265 num_omx_sessions = 1; 2266 if (p_params->burst_mode) { 2267 num_omx_sessions = MM_JPEG_CONCURRENT_SESSIONS_COUNT; 2268 } 2269 work_bufs_need = my_obj->num_sessions + num_omx_sessions; 2270 if (work_bufs_need > MM_JPEG_CONCURRENT_SESSIONS_COUNT) { 2271 work_bufs_need = MM_JPEG_CONCURRENT_SESSIONS_COUNT; 2272 } 2273 CDBG_HIGH("%s:%d] >>>> Work bufs need %d", __func__, __LINE__, work_bufs_need); 2274 work_buf_size = CEILING64((uint32_t)my_obj->max_pic_w) * 2275 CEILING64((uint32_t)my_obj->max_pic_h) * 3 / 2; 2276 for (i = my_obj->work_buf_cnt; i < work_bufs_need; i++) { 2277 my_obj->ionBuffer[i].size = CEILING32(work_buf_size); 2278 CDBG_HIGH("Max picture size %d x %d, WorkBufSize = %zu", 2279 my_obj->max_pic_w, my_obj->max_pic_h, my_obj->ionBuffer[i].size); 2280 2281 my_obj->ionBuffer[i].addr = (uint8_t *)buffer_allocate(&my_obj->ionBuffer[i], 1); 2282 if (NULL == my_obj->ionBuffer[i].addr) { 2283 CDBG_ERROR("%s:%d] Ion allocation failed",__func__, __LINE__); 2284 goto error1; 2285 } 2286 my_obj->work_buf_cnt++; 2287 } 2288 2289 /* init omx handle queue */ 2290 p_session_handle_q = (mm_jpeg_queue_t *) malloc(sizeof(*p_session_handle_q)); 2291 if (NULL == p_session_handle_q) { 2292 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 2293 goto error1; 2294 } 2295 rc = mm_jpeg_queue_init(p_session_handle_q); 2296 if (0 != rc) { 2297 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 2298 free(p_session_handle_q); 2299 goto error1; 2300 } 2301 2302 /* init output buf queue */ 2303 p_out_buf_q = (mm_jpeg_queue_t *) malloc(sizeof(*p_out_buf_q)); 2304 if (NULL == p_out_buf_q) { 2305 CDBG_ERROR("%s:%d] Error: Cannot allocate memory\n", __func__, __LINE__); 2306 return -1; 2307 } 2308 2309 /* init omx handle queue */ 2310 rc = mm_jpeg_queue_init(p_out_buf_q); 2311 if (0 != rc) { 2312 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 2313 free(p_out_buf_q); 2314 goto error1; 2315 } 2316 2317 for (i = 0; i < num_omx_sessions; i++) { 2318 uint32_t buf_idx = 0U; 2319 session_idx = mm_jpeg_get_new_session_idx(my_obj, clnt_idx, &p_session); 2320 if (session_idx < 0 || NULL == p_session) { 2321 CDBG_ERROR("%s:%d] invalid session id (%d)", __func__, __LINE__, session_idx); 2322 goto error2; 2323 } 2324 2325 snprintf(trace_tag, sizeof(trace_tag), "Camera:JPEGsession%d", session_idx); 2326 ATRACE_INT(trace_tag, 1); 2327 2328 p_session->job_index = 0; 2329 2330 p_session->next_session = NULL; 2331 2332 if (p_prev_session) { 2333 p_prev_session->next_session = p_session; 2334 } 2335 p_prev_session = p_session; 2336 2337 buf_idx = my_obj->num_sessions + i; 2338 if (buf_idx < MM_JPEG_CONCURRENT_SESSIONS_COUNT) { 2339 p_session->work_buffer = my_obj->ionBuffer[buf_idx]; 2340 } else { 2341 p_session->work_buffer.addr = NULL; 2342 p_session->work_buffer.ion_fd = -1; 2343 p_session->work_buffer.p_pmem_fd = -1; 2344 } 2345 2346 p_session->jpeg_obj = (void*)my_obj; /* save a ptr to jpeg_obj */ 2347 2348 ret = mm_jpeg_session_create(p_session); 2349 if (OMX_ErrorNone != ret) { 2350 p_session->active = OMX_FALSE; 2351 CDBG_ERROR("%s:%d] jpeg session create failed", __func__, __LINE__); 2352 goto error2; 2353 } 2354 2355 uint32_t session_id = (JOB_ID_MAGICVAL << 24) | 2356 ((uint32_t)session_idx << 8) | clnt_idx; 2357 2358 if (!*p_session_id) { 2359 *p_session_id = session_id; 2360 } 2361 2362 /*copy the params*/ 2363 p_session->params = *p_params; 2364 if (p_session->thumb_from_main) { 2365 memcpy(p_session->params.src_thumb_buf, p_session->params.src_main_buf, 2366 sizeof(p_session->params.src_thumb_buf)); 2367 p_session->params.num_tmb_bufs = p_session->params.num_src_bufs; 2368 if (!p_session->params.encode_thumbnail) { 2369 p_session->params.num_tmb_bufs = 0; 2370 } 2371 p_session->params.thumb_dim.src_dim = p_session->params.main_dim.src_dim; 2372 p_session->params.thumb_dim.crop = p_session->params.main_dim.crop; 2373 } 2374 p_session->client_hdl = client_hdl; 2375 p_session->sessionId = session_id; 2376 p_session->session_handle_q = p_session_handle_q; 2377 p_session->out_buf_q = p_out_buf_q; 2378 2379 qdata.p = p_session; 2380 mm_jpeg_queue_enq(p_session_handle_q, qdata); 2381 2382 p_session->meta_enc_key = NULL; 2383 p_session->meta_enc_keylen = 0; 2384 2385 #ifdef MM_JPEG_READ_META_KEYFILE 2386 mm_jpeg_read_meta_keyfile(p_session, META_KEYFILE); 2387 #endif 2388 2389 if (OMX_FALSE == p_session->config) { 2390 rc = mm_jpeg_session_configure(p_session); 2391 if (rc) { 2392 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 2393 goto error2; 2394 } 2395 p_session->config = OMX_TRUE; 2396 } 2397 p_session->num_omx_sessions = num_omx_sessions; 2398 2399 CDBG_HIGH("%s:%d] session id %x", __func__, __LINE__, session_id); 2400 } 2401 2402 // Queue the output buf indexes 2403 for (i = 0; i < p_params->num_dst_bufs; i++) { 2404 qdata.u32 = i + 1; 2405 mm_jpeg_queue_enq(p_out_buf_q, qdata); 2406 } 2407 2408 return rc; 2409 2410 error1: 2411 rc = -1; 2412 error2: 2413 if (NULL != p_session) { 2414 ATRACE_INT(trace_tag, 0); 2415 } 2416 return rc; 2417 } 2418 2419 /** mm_jpegenc_destroy_job 2420 * 2421 * Arguments: 2422 * @p_session: Session obj 2423 * 2424 * Return: 2425 * 0 for success else failure 2426 * 2427 * Description: 2428 * Destroy the job based paramenters 2429 * 2430 **/ 2431 static int32_t mm_jpegenc_destroy_job(mm_jpeg_job_session_t *p_session) 2432 { 2433 mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job; 2434 int i = 0, rc = 0; 2435 2436 CDBG_HIGH("%s:%d] Exif entry count %d %d", __func__, __LINE__, 2437 (int)p_jobparams->exif_info.numOfEntries, 2438 (int)p_session->exif_count_local); 2439 for (i = 0; i < p_session->exif_count_local; i++) { 2440 rc = releaseExifEntry(&p_session->exif_info_local[i]); 2441 if (rc) { 2442 CDBG_ERROR("%s:%d] Exif release failed (%d)", __func__, __LINE__, rc); 2443 } 2444 } 2445 p_session->exif_count_local = 0; 2446 2447 return rc; 2448 } 2449 2450 /** mm_jpeg_session_encode: 2451 * 2452 * Arguments: 2453 * @p_session: encode session 2454 * 2455 * Return: 2456 * OMX_ERRORTYPE 2457 * 2458 * Description: 2459 * Start the encoding 2460 * 2461 **/ 2462 static void mm_jpegenc_job_done(mm_jpeg_job_session_t *p_session) 2463 { 2464 mm_jpeg_q_data_t qdata; 2465 mm_jpeg_obj *my_obj = (mm_jpeg_obj *)p_session->jpeg_obj; 2466 mm_jpeg_job_q_node_t *node = NULL; 2467 2468 /*Destroy job related params*/ 2469 mm_jpegenc_destroy_job(p_session); 2470 2471 /*remove the job*/ 2472 node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->ongoing_job_q, 2473 p_session->jobId); 2474 if (node) { 2475 free(node); 2476 } 2477 p_session->encoding = OMX_FALSE; 2478 2479 // Queue to available sessions 2480 qdata.p = p_session; 2481 mm_jpeg_queue_enq(p_session->session_handle_q, qdata); 2482 2483 if (p_session->auto_out_buf) { 2484 //Queue out buf index 2485 qdata.u32 = (uint32_t)(p_session->encode_job.dst_index + 1); 2486 mm_jpeg_queue_enq(p_session->out_buf_q, qdata); 2487 } 2488 2489 /* wake up jobMgr thread to work on new job if there is any */ 2490 cam_sem_post(&my_obj->job_mgr.job_sem); 2491 } 2492 2493 /** mm_jpeg_destroy_session: 2494 * 2495 * Arguments: 2496 * @my_obj: jpeg object 2497 * @session_id: session index 2498 * 2499 * Return: 2500 * 0 for success else failure 2501 * 2502 * Description: 2503 * Destroy the encoding session 2504 * 2505 **/ 2506 int32_t mm_jpeg_destroy_session(mm_jpeg_obj *my_obj, 2507 mm_jpeg_job_session_t *p_session) 2508 { 2509 mm_jpeg_q_data_t qdata; 2510 int32_t rc = 0; 2511 mm_jpeg_job_q_node_t *node = NULL; 2512 uint32_t session_id = 0; 2513 mm_jpeg_job_session_t *p_cur_sess; 2514 char trace_tag[32]; 2515 2516 if (NULL == p_session) { 2517 CDBG_ERROR("%s:%d] invalid session", __func__, __LINE__); 2518 return rc; 2519 } 2520 2521 session_id = p_session->sessionId; 2522 2523 pthread_mutex_lock(&my_obj->job_lock); 2524 2525 /* abort job if in todo queue */ 2526 CDBG_HIGH("%s:%d] abort todo jobs", __func__, __LINE__); 2527 node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id); 2528 while (NULL != node) { 2529 free(node); 2530 node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id); 2531 } 2532 2533 /* abort job if in ongoing queue */ 2534 CDBG_HIGH("%s:%d] abort ongoing jobs", __func__, __LINE__); 2535 node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id); 2536 while (NULL != node) { 2537 free(node); 2538 node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id); 2539 } 2540 2541 /* abort the current session */ 2542 mm_jpeg_session_abort(p_session); 2543 mm_jpeg_session_destroy(p_session); 2544 2545 p_cur_sess = p_session; 2546 2547 do { 2548 mm_jpeg_remove_session_idx(my_obj, p_cur_sess->sessionId); 2549 } while (NULL != (p_cur_sess = p_cur_sess->next_session)); 2550 2551 2552 pthread_mutex_unlock(&my_obj->job_lock); 2553 2554 while (1) { 2555 qdata = mm_jpeg_queue_deq(p_session->session_handle_q); 2556 if (NULL == qdata.p) 2557 break; 2558 } 2559 mm_jpeg_queue_deinit(p_session->session_handle_q); 2560 free(p_session->session_handle_q); 2561 p_session->session_handle_q = NULL; 2562 2563 while (1) { 2564 qdata = mm_jpeg_queue_deq(p_session->out_buf_q); 2565 if (0U == qdata.u32) 2566 break; 2567 } 2568 mm_jpeg_queue_deinit(p_session->out_buf_q); 2569 free(p_session->out_buf_q); 2570 p_session->out_buf_q = NULL; 2571 2572 2573 /* wake up jobMgr thread to work on new job if there is any */ 2574 cam_sem_post(&my_obj->job_mgr.job_sem); 2575 2576 snprintf(trace_tag, sizeof(trace_tag), "Camera:JPEGsession%d", GET_SESSION_IDX(session_id)); 2577 ATRACE_INT(trace_tag, 0); 2578 2579 CDBG_HIGH("%s:%d] destroy session successful. X", __func__, __LINE__); 2580 2581 return rc; 2582 } 2583 2584 2585 2586 2587 /** mm_jpeg_destroy_session: 2588 * 2589 * Arguments: 2590 * @my_obj: jpeg object 2591 * @session_id: session index 2592 * 2593 * Return: 2594 * 0 for success else failure 2595 * 2596 * Description: 2597 * Destroy the encoding session 2598 * 2599 **/ 2600 int32_t mm_jpeg_destroy_session_unlocked(mm_jpeg_obj *my_obj, 2601 mm_jpeg_job_session_t *p_session) 2602 { 2603 int32_t rc = -1; 2604 mm_jpeg_job_q_node_t *node = NULL; 2605 uint32_t session_id = 0; 2606 if (NULL == p_session) { 2607 CDBG_ERROR("%s:%d] invalid session", __func__, __LINE__); 2608 return rc; 2609 } 2610 2611 session_id = p_session->sessionId; 2612 2613 /* abort job if in todo queue */ 2614 CDBG("%s:%d] abort todo jobs", __func__, __LINE__); 2615 node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id); 2616 while (NULL != node) { 2617 free(node); 2618 node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id); 2619 } 2620 2621 /* abort job if in ongoing queue */ 2622 CDBG("%s:%d] abort ongoing jobs", __func__, __LINE__); 2623 node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id); 2624 while (NULL != node) { 2625 free(node); 2626 node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id); 2627 } 2628 2629 /* abort the current session */ 2630 mm_jpeg_session_abort(p_session); 2631 //mm_jpeg_remove_session_idx(my_obj, session_id); 2632 2633 return rc; 2634 } 2635 2636 /** mm_jpeg_destroy_session: 2637 * 2638 * Arguments: 2639 * @my_obj: jpeg object 2640 * @session_id: session index 2641 * 2642 * Return: 2643 * 0 for success else failure 2644 * 2645 * Description: 2646 * Destroy the encoding session 2647 * 2648 **/ 2649 int32_t mm_jpeg_destroy_session_by_id(mm_jpeg_obj *my_obj, uint32_t session_id) 2650 { 2651 mm_jpeg_job_session_t *p_session = mm_jpeg_get_session(my_obj, session_id); 2652 2653 return mm_jpeg_destroy_session(my_obj, p_session); 2654 } 2655 2656 2657 2658 /** mm_jpeg_close: 2659 * 2660 * Arguments: 2661 * @my_obj: jpeg object 2662 * @client_hdl: client handle 2663 * 2664 * Return: 2665 * 0 for success else failure 2666 * 2667 * Description: 2668 * Close the jpeg client 2669 * 2670 **/ 2671 int32_t mm_jpeg_close(mm_jpeg_obj *my_obj, uint32_t client_hdl) 2672 { 2673 int32_t rc = -1; 2674 uint8_t clnt_idx = 0; 2675 int i = 0; 2676 2677 /* check if valid client */ 2678 clnt_idx = mm_jpeg_util_get_index_by_handler(client_hdl); 2679 if (clnt_idx >= MAX_JPEG_CLIENT_NUM) { 2680 CDBG_ERROR("%s: invalid client with handler (%d)", __func__, client_hdl); 2681 return rc; 2682 } 2683 2684 CDBG("%s:%d] E", __func__, __LINE__); 2685 2686 /* abort all jobs from the client */ 2687 pthread_mutex_lock(&my_obj->job_lock); 2688 2689 CDBG("%s:%d] ", __func__, __LINE__); 2690 2691 for (i = 0; i < MM_JPEG_MAX_SESSION; i++) { 2692 if (OMX_TRUE == my_obj->clnt_mgr[clnt_idx].session[i].active) 2693 mm_jpeg_destroy_session_unlocked(my_obj, 2694 &my_obj->clnt_mgr[clnt_idx].session[i]); 2695 } 2696 2697 CDBG("%s:%d] ", __func__, __LINE__); 2698 2699 #ifdef LOAD_ADSP_RPC_LIB 2700 if (NULL != my_obj->adsprpc_lib_handle) { 2701 dlclose(my_obj->adsprpc_lib_handle); 2702 my_obj->adsprpc_lib_handle = NULL; 2703 } 2704 #endif 2705 2706 pthread_mutex_unlock(&my_obj->job_lock); 2707 CDBG("%s:%d] ", __func__, __LINE__); 2708 2709 /* invalidate client session */ 2710 pthread_mutex_destroy(&my_obj->clnt_mgr[clnt_idx].lock); 2711 memset(&my_obj->clnt_mgr[clnt_idx], 0, sizeof(mm_jpeg_client_t)); 2712 2713 rc = 0; 2714 CDBG("%s:%d] X", __func__, __LINE__); 2715 return rc; 2716 } 2717 2718 OMX_ERRORTYPE mm_jpeg_ebd(OMX_HANDLETYPE hComponent, 2719 OMX_PTR pAppData, 2720 OMX_BUFFERHEADERTYPE *pBuffer) 2721 { 2722 mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData; 2723 2724 CDBG_HIGH("%s:%d] count %d ", __func__, __LINE__, p_session->ebd_count); 2725 pthread_mutex_lock(&p_session->lock); 2726 p_session->ebd_count++; 2727 pthread_mutex_unlock(&p_session->lock); 2728 return 0; 2729 } 2730 2731 OMX_ERRORTYPE mm_jpeg_fbd(OMX_HANDLETYPE hComponent, 2732 OMX_PTR pAppData, 2733 OMX_BUFFERHEADERTYPE *pBuffer) 2734 { 2735 OMX_ERRORTYPE ret = OMX_ErrorNone; 2736 mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData; 2737 mm_jpeg_output_t output_buf; 2738 CDBG_HIGH("%s:%d] count %d ", __func__, __LINE__, p_session->fbd_count); 2739 CDBG_HIGH("[KPI Perf] : PROFILE_JPEG_FBD"); 2740 2741 pthread_mutex_lock(&p_session->lock); 2742 ATRACE_INT("Camera:JPEG", 2743 (int32_t)((uint32_t)GET_SESSION_IDX( 2744 p_session->sessionId)<<16 | --p_session->job_index)); 2745 if (MM_JPEG_ABORT_NONE != p_session->abort_state) { 2746 pthread_mutex_unlock(&p_session->lock); 2747 return ret; 2748 } 2749 2750 p_session->fbd_count++; 2751 if (NULL != p_session->params.jpeg_cb) { 2752 2753 p_session->job_status = JPEG_JOB_STATUS_DONE; 2754 output_buf.buf_filled_len = (uint32_t)pBuffer->nFilledLen; 2755 output_buf.buf_vaddr = pBuffer->pBuffer; 2756 output_buf.fd = 0; 2757 CDBG_HIGH("%s:%d] send jpeg callback %d buf 0x%p len %u JobID %u", 2758 __func__, __LINE__, 2759 p_session->job_status, pBuffer->pBuffer, 2760 (unsigned int)pBuffer->nFilledLen, p_session->jobId); 2761 p_session->params.jpeg_cb(p_session->job_status, 2762 p_session->client_hdl, 2763 p_session->jobId, 2764 &output_buf, 2765 p_session->params.userdata); 2766 2767 mm_jpegenc_job_done(p_session); 2768 2769 } 2770 pthread_mutex_unlock(&p_session->lock); 2771 CDBG("%s:%d] ", __func__, __LINE__); 2772 2773 return ret; 2774 } 2775 2776 2777 2778 OMX_ERRORTYPE mm_jpeg_event_handler(OMX_HANDLETYPE hComponent, 2779 OMX_PTR pAppData, 2780 OMX_EVENTTYPE eEvent, 2781 OMX_U32 nData1, 2782 OMX_U32 nData2, 2783 OMX_PTR pEventData) 2784 { 2785 mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData; 2786 2787 CDBG("%s:%d] %d %d %d state %d", __func__, __LINE__, eEvent, (int)nData1, 2788 (int)nData2, p_session->abort_state); 2789 2790 pthread_mutex_lock(&p_session->lock); 2791 2792 if (MM_JPEG_ABORT_INIT == p_session->abort_state) { 2793 p_session->abort_state = MM_JPEG_ABORT_DONE; 2794 pthread_cond_signal(&p_session->cond); 2795 pthread_mutex_unlock(&p_session->lock); 2796 return OMX_ErrorNone; 2797 } 2798 2799 if (eEvent == OMX_EventError) { 2800 p_session->error_flag = nData2; 2801 if (p_session->encoding == OMX_TRUE) { 2802 CDBG_ERROR("%s:%d] Error during encoding", __func__, __LINE__); 2803 2804 /* send jpeg callback */ 2805 if (NULL != p_session->params.jpeg_cb) { 2806 p_session->job_status = JPEG_JOB_STATUS_ERROR; 2807 CDBG_ERROR("%s:%d] send jpeg error callback %d", __func__, __LINE__, 2808 p_session->job_status); 2809 p_session->params.jpeg_cb(p_session->job_status, 2810 p_session->client_hdl, 2811 p_session->jobId, 2812 NULL, 2813 p_session->params.userdata); 2814 } 2815 2816 /* remove from ready queue */ 2817 mm_jpegenc_job_done(p_session); 2818 } 2819 pthread_cond_signal(&p_session->cond); 2820 } else if (eEvent == OMX_EventCmdComplete) { 2821 if (p_session->state_change_pending == OMX_TRUE) { 2822 p_session->state_change_pending = OMX_FALSE; 2823 pthread_cond_signal(&p_session->cond); 2824 } 2825 } 2826 2827 pthread_mutex_unlock(&p_session->lock); 2828 CDBG("%s:%d]", __func__, __LINE__); 2829 return OMX_ErrorNone; 2830 } 2831 2832 2833 2834 /* remove the first job from the queue with matching client handle */ 2835 mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_client_id( 2836 mm_jpeg_queue_t* queue, uint32_t client_hdl) 2837 { 2838 mm_jpeg_q_node_t* node = NULL; 2839 mm_jpeg_job_q_node_t* data = NULL; 2840 mm_jpeg_job_q_node_t* job_node = NULL; 2841 struct cam_list *head = NULL; 2842 struct cam_list *pos = NULL; 2843 2844 pthread_mutex_lock(&queue->lock); 2845 head = &queue->head.list; 2846 pos = head->next; 2847 while(pos != head) { 2848 node = member_of(pos, mm_jpeg_q_node_t, list); 2849 data = (mm_jpeg_job_q_node_t *)node->data.p; 2850 2851 if (data && (data->enc_info.client_handle == client_hdl)) { 2852 CDBG_HIGH("%s:%d] found matching client handle", __func__, __LINE__); 2853 job_node = data; 2854 cam_list_del_node(&node->list); 2855 queue->size--; 2856 free(node); 2857 CDBG_HIGH("%s: queue size = %d", __func__, queue->size); 2858 break; 2859 } 2860 pos = pos->next; 2861 } 2862 2863 pthread_mutex_unlock(&queue->lock); 2864 2865 return job_node; 2866 } 2867 2868 /* remove the first job from the queue with matching session id */ 2869 mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_session_id( 2870 mm_jpeg_queue_t* queue, uint32_t session_id) 2871 { 2872 mm_jpeg_q_node_t* node = NULL; 2873 mm_jpeg_job_q_node_t* data = NULL; 2874 mm_jpeg_job_q_node_t* job_node = NULL; 2875 struct cam_list *head = NULL; 2876 struct cam_list *pos = NULL; 2877 2878 pthread_mutex_lock(&queue->lock); 2879 head = &queue->head.list; 2880 pos = head->next; 2881 while(pos != head) { 2882 node = member_of(pos, mm_jpeg_q_node_t, list); 2883 data = (mm_jpeg_job_q_node_t *)node->data.p; 2884 2885 if (data && (data->enc_info.encode_job.session_id == session_id)) { 2886 CDBG_HIGH("%s:%d] found matching session id", __func__, __LINE__); 2887 job_node = data; 2888 cam_list_del_node(&node->list); 2889 queue->size--; 2890 free(node); 2891 CDBG_HIGH("%s: queue size = %d", __func__, queue->size); 2892 break; 2893 } 2894 pos = pos->next; 2895 } 2896 2897 pthread_mutex_unlock(&queue->lock); 2898 2899 return job_node; 2900 } 2901 2902 /* remove job from the queue with matching job id */ 2903 mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_job_id( 2904 mm_jpeg_queue_t* queue, uint32_t job_id) 2905 { 2906 mm_jpeg_q_node_t* node = NULL; 2907 mm_jpeg_job_q_node_t* data = NULL; 2908 mm_jpeg_job_q_node_t* job_node = NULL; 2909 struct cam_list *head = NULL; 2910 struct cam_list *pos = NULL; 2911 uint32_t lq_job_id; 2912 2913 pthread_mutex_lock(&queue->lock); 2914 head = &queue->head.list; 2915 pos = head->next; 2916 while(pos != head) { 2917 node = member_of(pos, mm_jpeg_q_node_t, list); 2918 data = (mm_jpeg_job_q_node_t *)node->data.p; 2919 2920 if(NULL == data) { 2921 CDBG_ERROR("%s:%d] Data is NULL", __func__, __LINE__); 2922 pthread_mutex_unlock(&queue->lock); 2923 return NULL; 2924 } 2925 2926 if (data->type == MM_JPEG_CMD_TYPE_DECODE_JOB) { 2927 lq_job_id = data->dec_info.job_id; 2928 } else { 2929 lq_job_id = data->enc_info.job_id; 2930 } 2931 2932 if (data && (lq_job_id == job_id)) { 2933 CDBG_HIGH("%s:%d] found matching job id", __func__, __LINE__); 2934 job_node = data; 2935 cam_list_del_node(&node->list); 2936 queue->size--; 2937 free(node); 2938 break; 2939 } 2940 pos = pos->next; 2941 } 2942 2943 pthread_mutex_unlock(&queue->lock); 2944 2945 return job_node; 2946 } 2947 2948 /* remove job from the queue with matching job id */ 2949 mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_unlk( 2950 mm_jpeg_queue_t* queue, uint32_t job_id) 2951 { 2952 mm_jpeg_q_node_t* node = NULL; 2953 mm_jpeg_job_q_node_t* data = NULL; 2954 mm_jpeg_job_q_node_t* job_node = NULL; 2955 struct cam_list *head = NULL; 2956 struct cam_list *pos = NULL; 2957 2958 head = &queue->head.list; 2959 pos = head->next; 2960 while(pos != head) { 2961 node = member_of(pos, mm_jpeg_q_node_t, list); 2962 data = (mm_jpeg_job_q_node_t *)node->data.p; 2963 2964 if (data && (data->enc_info.job_id == job_id)) { 2965 job_node = data; 2966 cam_list_del_node(&node->list); 2967 queue->size--; 2968 free(node); 2969 break; 2970 } 2971 pos = pos->next; 2972 } 2973 2974 return job_node; 2975 } 2976