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