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