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