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