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