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