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