mm_jpeg.c revision ce69270a348f6002c378cc821bedd54ae486c7a7
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 107OMX_ERRORTYPE mm_jpeg_ebd(OMX_HANDLETYPE hComponent, 108 OMX_PTR pAppData, 109 OMX_BUFFERHEADERTYPE* pBuffer); 110OMX_ERRORTYPE mm_jpeg_fbd(OMX_HANDLETYPE hComponent, 111 OMX_PTR pAppData, 112 OMX_BUFFERHEADERTYPE* pBuffer); 113OMX_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 **/ 132static 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 **/ 226mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_client_id( 227 mm_jpeg_queue_t* queue, uint32_t client_hdl); 228mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_job_id( 229 mm_jpeg_queue_t* queue, uint32_t job_id); 230mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_session_id( 231 mm_jpeg_queue_t* queue, uint32_t session_id); 232mm_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 **/ 239typedef OMX_ERRORTYPE (*mm_jpeg_transition_func_t)(void *); 240 241 242/** mm_jpeg_queue_func_t: 243 * 244 * Intermediate function for queue operation 245 **/ 246typedef 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 **/ 260OMX_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 **/ 321OMX_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 **/ 373OMX_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 **/ 442OMX_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 **/ 485void 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 **/ 533OMX_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 **/ 593OMX_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 **/ 636int 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 **/ 673OMX_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 if (p_session->params.encode_thumbnail) { 728 mm_jpeg_buf_t *p_tmb_buf = 729 &p_params->src_thumb_buf[p_jobparams->thumb_index]; 730 p_session->inputTmbPort.format.image.nFrameWidth = 731 p_jobparams->thumb_dim.src_dim.width; 732 p_session->inputTmbPort.format.image.nFrameHeight = 733 p_jobparams->thumb_dim.src_dim.height; 734 p_session->inputTmbPort.format.image.nStride = 735 p_tmb_buf->offset.mp[0].stride; 736 p_session->inputTmbPort.format.image.nSliceHeight = 737 p_tmb_buf->offset.mp[0].scanline; 738 p_session->inputTmbPort.format.image.eColorFormat = 739 map_jpeg_format(p_params->color_format); 740 p_session->inputTmbPort.nBufferSize = 741 p_params->src_thumb_buf[p_jobparams->thumb_index].buf_size; 742 p_session->inputTmbPort.nBufferCountActual = p_params->num_tmb_bufs; 743 ret = OMX_SetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition, 744 &p_session->inputTmbPort); 745 746 if (ret) { 747 CDBG_ERROR("%s:%d] failed", __func__, __LINE__); 748 return ret; 749 } 750 751 // Enable thumbnail port 752 ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandPortEnable, 753 p_session->inputTmbPort.nPortIndex, NULL); 754 755 if (ret) { 756 CDBG_ERROR("%s:%d] failed", __func__, __LINE__); 757 return ret; 758 } 759 } else { 760 // Disable thumbnail port 761 ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandPortDisable, 762 p_session->inputTmbPort.nPortIndex, NULL); 763 764 if (ret) { 765 CDBG_ERROR("%s:%d] failed", __func__, __LINE__); 766 return ret; 767 } 768 } 769 770 p_session->outputPort.nBufferSize = 771 p_params->dest_buf[p_jobparams->dst_index].buf_size; 772 p_session->outputPort.nBufferCountActual = p_params->num_dst_bufs; 773 ret = OMX_SetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition, 774 &p_session->outputPort); 775 if (ret) { 776 CDBG_ERROR("%s:%d] failed", __func__, __LINE__); 777 return ret; 778 } 779 780 return ret; 781} 782 783/** mm_jpeg_omx_config_thumbnail: 784 * 785 * Arguments: 786 * @p_session: job session 787 * 788 * Return: 789 * OMX error values 790 * 791 * Description: 792 * Configure OMX ports 793 * 794 **/ 795OMX_ERRORTYPE mm_jpeg_session_config_thumbnail(mm_jpeg_job_session_t* p_session) 796{ 797 OMX_ERRORTYPE ret = OMX_ErrorNone; 798 QOMX_THUMBNAIL_INFO thumbnail_info; 799 OMX_INDEXTYPE thumb_indextype; 800 OMX_BOOL encode_thumbnail = OMX_FALSE; 801 mm_jpeg_encode_params_t *p_params = &p_session->params; 802 mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job; 803 mm_jpeg_dim_t *p_thumb_dim = &p_jobparams->thumb_dim; 804 mm_jpeg_dim_t *p_main_dim = &p_jobparams->main_dim; 805 QOMX_YUV_FRAME_INFO *p_frame_info = &thumbnail_info.tmbOffset; 806 mm_jpeg_buf_t *p_tmb_buf = &p_params->src_thumb_buf[p_jobparams->thumb_index]; 807 808 CDBG_HIGH("%s:%d] encode_thumbnail %d", __func__, __LINE__, 809 p_params->encode_thumbnail); 810 if (OMX_FALSE == p_params->encode_thumbnail) { 811 return ret; 812 } 813 814 if ((p_thumb_dim->dst_dim.width == 0) || (p_thumb_dim->dst_dim.height == 0)) { 815 CDBG_ERROR("%s:%d] Error invalid output dim for thumbnail", 816 __func__, __LINE__); 817 return OMX_ErrorBadParameter; 818 } 819 820 if ((p_thumb_dim->src_dim.width == 0) || (p_thumb_dim->src_dim.height == 0)) { 821 CDBG_ERROR("%s:%d] Error invalid input dim for thumbnail", 822 __func__, __LINE__); 823 return OMX_ErrorBadParameter; 824 } 825 826 if ((p_thumb_dim->crop.width == 0) || (p_thumb_dim->crop.height == 0)) { 827 p_thumb_dim->crop.width = p_thumb_dim->src_dim.width; 828 p_thumb_dim->crop.height = p_thumb_dim->src_dim.height; 829 } 830 831 /* check crop boundary */ 832 if ((p_thumb_dim->crop.width + p_thumb_dim->crop.left > p_thumb_dim->src_dim.width) || 833 (p_thumb_dim->crop.height + p_thumb_dim->crop.top > p_thumb_dim->src_dim.height)) { 834 CDBG_ERROR("%s:%d] invalid crop boundary (%d, %d) offset (%d, %d) out of (%d, %d)", 835 __func__, __LINE__, 836 p_thumb_dim->crop.width, 837 p_thumb_dim->crop.height, 838 p_thumb_dim->crop.left, 839 p_thumb_dim->crop.top, 840 p_thumb_dim->src_dim.width, 841 p_thumb_dim->src_dim.height); 842 return OMX_ErrorBadParameter; 843 } 844 845 memset(&thumbnail_info, 0x0, sizeof(QOMX_THUMBNAIL_INFO)); 846 ret = OMX_GetExtensionIndex(p_session->omx_handle, 847 QOMX_IMAGE_EXT_THUMBNAIL_NAME, 848 &thumb_indextype); 849 if (ret) { 850 CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret); 851 return ret; 852 } 853 854 /* fill thumbnail info */ 855 thumbnail_info.scaling_enabled = 1; 856 thumbnail_info.input_width = p_thumb_dim->src_dim.width; 857 thumbnail_info.input_height = p_thumb_dim->src_dim.height; 858 thumbnail_info.crop_info.nWidth = p_thumb_dim->crop.width; 859 thumbnail_info.crop_info.nHeight = p_thumb_dim->crop.height; 860 thumbnail_info.crop_info.nLeft = p_thumb_dim->crop.left; 861 thumbnail_info.crop_info.nTop = p_thumb_dim->crop.top; 862 863 if ((p_main_dim->src_dim.width < p_thumb_dim->src_dim.width) || 864 (p_main_dim->src_dim.height < p_thumb_dim->src_dim.height)) { 865 CDBG_ERROR("%s:%d] Improper thumbnail dim %dx%d resetting to %dx%d", 866 __func__, __LINE__, 867 p_thumb_dim->src_dim.width, 868 p_thumb_dim->src_dim.height, 869 p_main_dim->src_dim.width, 870 p_main_dim->src_dim.height); 871 thumbnail_info.input_width = p_main_dim->src_dim.width; 872 thumbnail_info.input_height = p_main_dim->src_dim.height; 873 if ((thumbnail_info.crop_info.nWidth > thumbnail_info.input_width) 874 || (thumbnail_info.crop_info.nHeight > thumbnail_info.input_height)) { 875 thumbnail_info.crop_info.nLeft = 0; 876 thumbnail_info.crop_info.nTop = 0; 877 thumbnail_info.crop_info.nWidth = thumbnail_info.input_width; 878 thumbnail_info.crop_info.nHeight = thumbnail_info.input_height; 879 } 880 } 881 882 if ((p_thumb_dim->dst_dim.width > p_thumb_dim->src_dim.width) 883 || (p_thumb_dim->dst_dim.height > p_thumb_dim->src_dim.height)) { 884 CDBG_ERROR("%s:%d] Incorrect thumbnail dim %dx%d resetting to %dx%d", 885 __func__, __LINE__, 886 p_thumb_dim->dst_dim.width, 887 p_thumb_dim->dst_dim.height, 888 p_thumb_dim->src_dim.width, 889 p_thumb_dim->src_dim.height); 890 thumbnail_info.output_width = p_thumb_dim->src_dim.width; 891 thumbnail_info.output_height = p_thumb_dim->src_dim.height; 892 } else { 893 thumbnail_info.output_width = p_thumb_dim->dst_dim.width; 894 thumbnail_info.output_height = p_thumb_dim->dst_dim.height; 895 } 896 897 memset(p_frame_info, 0x0, sizeof(*p_frame_info)); 898 899 p_frame_info->cbcrStartOffset[0] = p_tmb_buf->offset.mp[0].len; 900 p_frame_info->cbcrStartOffset[1] = p_tmb_buf->offset.mp[1].len; 901 p_frame_info->yOffset = p_tmb_buf->offset.mp[0].offset; 902 p_frame_info->cbcrOffset[0] = p_tmb_buf->offset.mp[1].offset; 903 p_frame_info->cbcrOffset[1] = p_tmb_buf->offset.mp[2].offset; 904 905 ret = OMX_SetParameter(p_session->omx_handle, thumb_indextype, 906 &thumbnail_info); 907 if (ret) { 908 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 909 return ret; 910 } 911 912 return ret; 913} 914 915/** mm_jpeg_session_config_main_crop: 916 * 917 * Arguments: 918 * @p_session: job session 919 * 920 * Return: 921 * OMX error values 922 * 923 * Description: 924 * Configure main image crop 925 * 926 **/ 927OMX_ERRORTYPE mm_jpeg_session_config_main_crop(mm_jpeg_job_session_t *p_session) 928{ 929 OMX_CONFIG_RECTTYPE rect_type_in, rect_type_out; 930 OMX_ERRORTYPE ret = OMX_ErrorNone; 931 mm_jpeg_encode_params_t *p_params = &p_session->params; 932 mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job; 933 mm_jpeg_dim_t *dim = &p_jobparams->main_dim; 934 935 if ((dim->crop.width == 0) || (dim->crop.height == 0)) { 936 dim->crop.width = dim->src_dim.width; 937 dim->crop.height = dim->src_dim.height; 938 } 939 /* error check first */ 940 if ((dim->crop.width + dim->crop.left > dim->src_dim.width) || 941 (dim->crop.height + dim->crop.top > dim->src_dim.height)) { 942 CDBG_ERROR("%s:%d] invalid crop boundary (%d, %d) out of (%d, %d)", 943 __func__, __LINE__, 944 dim->crop.width + dim->crop.left, 945 dim->crop.height + dim->crop.top, 946 dim->src_dim.width, 947 dim->src_dim.height); 948 return OMX_ErrorBadParameter; 949 } 950 951 memset(&rect_type_in, 0, sizeof(rect_type_in)); 952 memset(&rect_type_out, 0, sizeof(rect_type_out)); 953 rect_type_in.nPortIndex = 0; 954 rect_type_out.nPortIndex = 0; 955 956 if ((dim->src_dim.width != dim->crop.width) || 957 (dim->src_dim.height != dim->crop.height) || 958 (dim->src_dim.width != dim->dst_dim.width) || 959 (dim->src_dim.height != dim->dst_dim.height)) { 960 /* Scaler information */ 961 rect_type_in.nWidth = CEILING2(dim->crop.width); 962 rect_type_in.nHeight = CEILING2(dim->crop.height); 963 rect_type_in.nLeft = dim->crop.left; 964 rect_type_in.nTop = dim->crop.top; 965 966 if (dim->dst_dim.width && dim->dst_dim.height) { 967 rect_type_out.nWidth = dim->dst_dim.width; 968 rect_type_out.nHeight = dim->dst_dim.height; 969 } 970 } 971 972 ret = OMX_SetConfig(p_session->omx_handle, OMX_IndexConfigCommonInputCrop, 973 &rect_type_in); 974 if (OMX_ErrorNone != ret) { 975 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 976 return ret; 977 } 978 979 CDBG("%s:%d] OMX_IndexConfigCommonInputCrop w = %d, h = %d, l = %d, t = %d," 980 " port_idx = %d", __func__, __LINE__, 981 (int)rect_type_in.nWidth, (int)rect_type_in.nHeight, 982 (int)rect_type_in.nLeft, (int)rect_type_in.nTop, 983 (int)rect_type_in.nPortIndex); 984 985 ret = OMX_SetConfig(p_session->omx_handle, OMX_IndexConfigCommonOutputCrop, 986 &rect_type_out); 987 if (OMX_ErrorNone != ret) { 988 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 989 return ret; 990 } 991 CDBG("%s:%d] OMX_IndexConfigCommonOutputCrop w = %d, h = %d," 992 " port_idx = %d", __func__, __LINE__, 993 (int)rect_type_out.nWidth, (int)rect_type_out.nHeight, 994 (int)rect_type_out.nPortIndex); 995 996 return ret; 997} 998 999/** mm_jpeg_session_config_main: 1000 * 1001 * Arguments: 1002 * @p_session: job session 1003 * 1004 * Return: 1005 * OMX error values 1006 * 1007 * Description: 1008 * Configure main image 1009 * 1010 **/ 1011OMX_ERRORTYPE mm_jpeg_session_config_main(mm_jpeg_job_session_t *p_session) 1012{ 1013 OMX_ERRORTYPE rc = OMX_ErrorNone; 1014 OMX_IMAGE_PARAM_QFACTORTYPE q_factor; 1015 mm_jpeg_encode_params_t *p_params = &p_session->params; 1016 mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job; 1017 1018 /* config port */ 1019 CDBG("%s:%d] config port", __func__, __LINE__); 1020 rc = mm_jpeg_session_config_ports(p_session); 1021 if (OMX_ErrorNone != rc) { 1022 CDBG_ERROR("%s: config port failed", __func__); 1023 return rc; 1024 } 1025 1026 /* config buffer offset */ 1027 CDBG("%s:%d] config main buf offset", __func__, __LINE__); 1028 rc = mm_jpeg_session_config_main_buffer_offset(p_session); 1029 if (OMX_ErrorNone != rc) { 1030 CDBG_ERROR("%s: config buffer offset failed", __func__); 1031 return rc; 1032 } 1033 1034 /* config crop */ 1035 CDBG("%s:%d] config main crop", __func__, __LINE__); 1036 rc = mm_jpeg_session_config_main_crop(p_session); 1037 if (OMX_ErrorNone != rc) { 1038 CDBG_ERROR("%s: config crop failed", __func__); 1039 return rc; 1040 } 1041 1042 /* set quality */ 1043 memset(&q_factor, 0, sizeof(q_factor)); 1044 q_factor.nPortIndex = 0; 1045 q_factor.nQFactor = p_params->quality; 1046 rc = OMX_SetParameter(p_session->omx_handle, OMX_IndexParamQFactor, &q_factor); 1047 CDBG("%s:%d] config QFactor: %d", __func__, __LINE__, (int)q_factor.nQFactor); 1048 if (OMX_ErrorNone != rc) { 1049 CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, rc); 1050 return rc; 1051 } 1052 1053 return rc; 1054} 1055 1056/** mm_jpeg_session_config_common: 1057 * 1058 * Arguments: 1059 * @p_session: job session 1060 * 1061 * Return: 1062 * OMX error values 1063 * 1064 * Description: 1065 * Configure common parameters 1066 * 1067 **/ 1068OMX_ERRORTYPE mm_jpeg_session_config_common(mm_jpeg_job_session_t *p_session) 1069{ 1070 OMX_ERRORTYPE rc = OMX_ErrorNone; 1071 int i; 1072 OMX_INDEXTYPE exif_idx; 1073 OMX_CONFIG_ROTATIONTYPE rotate; 1074 mm_jpeg_encode_params_t *p_params = &p_session->params; 1075 mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job; 1076 QOMX_EXIF_INFO exif_info; 1077 1078 /* set rotation */ 1079 memset(&rotate, 0, sizeof(rotate)); 1080 rotate.nPortIndex = 1; 1081 rotate.nRotation = p_jobparams->rotation; 1082 rc = OMX_SetConfig(p_session->omx_handle, OMX_IndexConfigCommonRotate, 1083 &rotate); 1084 if (OMX_ErrorNone != rc) { 1085 CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, rc); 1086 return rc; 1087 } 1088 CDBG("%s:%d] Set rotation to %d at port_idx = %d", __func__, __LINE__, 1089 (int)p_jobparams->rotation, (int)rotate.nPortIndex); 1090 1091 /* Set Exif data*/ 1092 memset(&p_session->exif_info_all[0], 0, sizeof(p_session->exif_info_all)); 1093 1094 exif_info.numOfEntries = p_params->exif_info.numOfEntries; 1095 exif_info.exif_data = &p_session->exif_info_all[0]; 1096 /*If Exif data has been passed copy it*/ 1097 if (p_params->exif_info.numOfEntries > 0) { 1098 CDBG("%s:%d] Num of exif entries passed from HAL: %d", __func__, __LINE__, 1099 p_params->exif_info.numOfEntries); 1100 memcpy(exif_info.exif_data, p_params->exif_info.exif_data, 1101 sizeof(QEXIF_INFO_DATA) * p_params->exif_info.numOfEntries); 1102 } 1103 1104 if (exif_info.numOfEntries > 0) { 1105 /* set exif tags */ 1106 CDBG("%s:%d] Set exif tags count %d", __func__, __LINE__, 1107 (int)exif_info.numOfEntries); 1108 rc = OMX_GetExtensionIndex(p_session->omx_handle, QOMX_IMAGE_EXT_EXIF_NAME, 1109 &exif_idx); 1110 if (OMX_ErrorNone != rc) { 1111 CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, rc); 1112 return rc; 1113 } 1114 1115 rc = OMX_SetParameter(p_session->omx_handle, exif_idx, 1116 &exif_info); 1117 if (OMX_ErrorNone != rc) { 1118 CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, rc); 1119 return rc; 1120 } 1121 } 1122 1123 return rc; 1124} 1125 1126/** mm_jpeg_session_abort: 1127 * 1128 * Arguments: 1129 * @p_session: jpeg session 1130 * 1131 * Return: 1132 * OMX_BOOL 1133 * 1134 * Description: 1135 * Abort ongoing job 1136 * 1137 **/ 1138OMX_BOOL mm_jpeg_session_abort(mm_jpeg_job_session_t *p_session) 1139{ 1140 OMX_ERRORTYPE ret = OMX_ErrorNone; 1141 1142 CDBG("%s:%d] E", __func__, __LINE__); 1143 pthread_mutex_lock(&p_session->lock); 1144 if (OMX_TRUE == p_session->abort_flag) { 1145 pthread_mutex_unlock(&p_session->lock); 1146 CDBG("%s:%d] **** ALREADY ABORTED", __func__, __LINE__); 1147 return 0; 1148 } 1149 p_session->abort_flag = OMX_TRUE; 1150 if (OMX_TRUE == p_session->encoding) { 1151 p_session->state_change_pending = OMX_TRUE; 1152 1153 CDBG("%s:%d] **** ABORTING", __func__, __LINE__); 1154 1155 ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandStateSet, 1156 OMX_StateIdle, NULL); 1157 1158 if (ret != OMX_ErrorNone) { 1159 CDBG("%s:%d] OMX_SendCommand returned error %d", __func__, __LINE__, ret); 1160 pthread_mutex_unlock(&p_session->lock); 1161 return 1; 1162 } 1163 1164 CDBG("%s:%d] before wait", __func__, __LINE__); 1165 pthread_cond_wait(&p_session->cond, &p_session->lock); 1166 CDBG("%s:%d] after wait", __func__, __LINE__); 1167 } 1168 pthread_mutex_unlock(&p_session->lock); 1169 CDBG("%s:%d] X", __func__, __LINE__); 1170 return 0; 1171} 1172 1173/** mm_jpeg_get_job_idx: 1174 * 1175 * Arguments: 1176 * @my_obj: jpeg object 1177 * @client_idx: client index 1178 * 1179 * Return: 1180 * job index 1181 * 1182 * Description: 1183 * Get job index by client id 1184 * 1185 **/ 1186inline int mm_jpeg_get_new_session_idx(mm_jpeg_obj *my_obj, int client_idx, 1187 mm_jpeg_job_session_t **pp_session) 1188{ 1189 int i = 0; 1190 int index = -1; 1191 for (i = 0; i < MM_JPEG_MAX_SESSION; i++) { 1192 pthread_mutex_lock(&my_obj->clnt_mgr[client_idx].lock); 1193 if (!my_obj->clnt_mgr[client_idx].session[i].active) { 1194 *pp_session = &my_obj->clnt_mgr[client_idx].session[i]; 1195 my_obj->clnt_mgr[client_idx].session[i].active = OMX_TRUE; 1196 index = i; 1197 pthread_mutex_unlock(&my_obj->clnt_mgr[client_idx].lock); 1198 break; 1199 } 1200 pthread_mutex_unlock(&my_obj->clnt_mgr[client_idx].lock); 1201 } 1202 return index; 1203} 1204 1205/** mm_jpeg_get_job_idx: 1206 * 1207 * Arguments: 1208 * @my_obj: jpeg object 1209 * @client_idx: client index 1210 * 1211 * Return: 1212 * job index 1213 * 1214 * Description: 1215 * Get job index by client id 1216 * 1217 **/ 1218inline void mm_jpeg_remove_session_idx(mm_jpeg_obj *my_obj, uint32_t job_id) 1219{ 1220 int client_idx = GET_CLIENT_IDX(job_id); 1221 int session_idx= GET_SESSION_IDX(job_id); 1222 CDBG("%s:%d] client_idx %d session_idx %d", __func__, __LINE__, 1223 client_idx, session_idx); 1224 pthread_mutex_lock(&my_obj->clnt_mgr[client_idx].lock); 1225 my_obj->clnt_mgr[client_idx].session[session_idx].active = OMX_FALSE; 1226 pthread_mutex_unlock(&my_obj->clnt_mgr[client_idx].lock); 1227} 1228 1229/** mm_jpeg_get_session_idx: 1230 * 1231 * Arguments: 1232 * @my_obj: jpeg object 1233 * @client_idx: client index 1234 * 1235 * Return: 1236 * job index 1237 * 1238 * Description: 1239 * Get job index by client id 1240 * 1241 **/ 1242inline mm_jpeg_job_session_t *mm_jpeg_get_session(mm_jpeg_obj *my_obj, uint32_t job_id) 1243{ 1244 mm_jpeg_job_session_t *p_session = NULL; 1245 int client_idx = GET_CLIENT_IDX(job_id); 1246 int session_idx= GET_SESSION_IDX(job_id); 1247 1248 CDBG("%s:%d] client_idx %d session_idx %d", __func__, __LINE__, 1249 client_idx, session_idx); 1250 if ((session_idx >= MM_JPEG_MAX_SESSION) || 1251 (client_idx >= MAX_JPEG_CLIENT_NUM)) { 1252 CDBG_ERROR("%s:%d] invalid job id %x", __func__, __LINE__, 1253 job_id); 1254 return NULL; 1255 } 1256 pthread_mutex_lock(&my_obj->clnt_mgr[client_idx].lock); 1257 p_session = &my_obj->clnt_mgr[client_idx].session[session_idx]; 1258 pthread_mutex_unlock(&my_obj->clnt_mgr[client_idx].lock); 1259 return p_session; 1260} 1261 1262/** mm_jpeg_session_configure: 1263 * 1264 * Arguments: 1265 * @data: encode session 1266 * 1267 * Return: 1268 * none 1269 * 1270 * Description: 1271 * Configure the session 1272 * 1273 **/ 1274static OMX_ERRORTYPE mm_jpeg_session_configure(mm_jpeg_job_session_t *p_session) 1275{ 1276 OMX_ERRORTYPE ret = OMX_ErrorNone; 1277 mm_jpeg_encode_params_t *p_params = &p_session->params; 1278 mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job; 1279 mm_jpeg_obj *my_obj = (mm_jpeg_obj *)p_session->jpeg_obj; 1280 1281 CDBG("%s:%d] E ", __func__, __LINE__); 1282 1283 MM_JPEG_CHK_ABORT(p_session, ret, error); 1284 1285 /* config main img */ 1286 ret = mm_jpeg_session_config_main(p_session); 1287 if (OMX_ErrorNone != ret) { 1288 CDBG_ERROR("%s:%d] config main img failed", __func__, __LINE__); 1289 goto error; 1290 } 1291 1292 /* config thumbnail */ 1293 ret = mm_jpeg_session_config_thumbnail(p_session); 1294 if (OMX_ErrorNone != ret) { 1295 CDBG_ERROR("%s:%d] config thumbnail img failed", __func__, __LINE__); 1296 goto error; 1297 } 1298 1299 /* config encoding mode */ 1300 CDBG("%s:%d] config encoding mode", __func__, __LINE__); 1301 ret = mm_jpeg_encoding_mode(p_session); 1302 if (OMX_ErrorNone != ret) { 1303 CDBG_ERROR("%s: config encoding mode failed", __func__); 1304 return ret; 1305 } 1306 1307 /* common config */ 1308 ret = mm_jpeg_session_config_common(p_session); 1309 if (OMX_ErrorNone != ret) { 1310 CDBG_ERROR("%s:%d] config common failed", __func__, __LINE__); 1311 goto error; 1312 } 1313 1314 ret = mm_jpeg_session_change_state(p_session, OMX_StateIdle, 1315 mm_jpeg_session_send_buffers); 1316 if (ret) { 1317 CDBG_ERROR("%s:%d] change state to idle failed %d", 1318 __func__, __LINE__, ret); 1319 goto error; 1320 } 1321 1322 ret = mm_jpeg_session_change_state(p_session, OMX_StateExecuting, 1323 NULL); 1324 if (ret) { 1325 CDBG_ERROR("%s:%d] change state to executing failed %d", 1326 __func__, __LINE__, ret); 1327 goto error; 1328 } 1329 1330error: 1331 CDBG("%s:%d] X ret %d", __func__, __LINE__, ret); 1332 return ret; 1333} 1334 1335/** mm_jpeg_session_encode: 1336 * 1337 * Arguments: 1338 * @p_session: encode session 1339 * 1340 * Return: 1341 * OMX_ERRORTYPE 1342 * 1343 * Description: 1344 * Start the encoding 1345 * 1346 **/ 1347static inline void mm_jpeg_job_done(mm_jpeg_job_session_t *p_session) 1348{ 1349 mm_jpeg_obj *my_obj = (mm_jpeg_obj *)p_session->jpeg_obj; 1350 mm_jpeg_job_q_node_t *node = NULL; 1351 1352 /*remove the job*/ 1353 node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->ongoing_job_q, 1354 p_session->jobId); 1355 if (node) { 1356 free(node); 1357 } 1358 p_session->encoding = OMX_FALSE; 1359 1360 /* wake up jobMgr thread to work on new job if there is any */ 1361 cam_sem_post(&my_obj->job_mgr.job_sem); 1362} 1363 1364/** mm_jpeg_session_encode: 1365 * 1366 * Arguments: 1367 * @p_session: encode session 1368 * 1369 * Return: 1370 * OMX_ERRORTYPE 1371 * 1372 * Description: 1373 * Start the encoding 1374 * 1375 **/ 1376static OMX_ERRORTYPE mm_jpeg_session_encode(mm_jpeg_job_session_t *p_session) 1377{ 1378 OMX_ERRORTYPE ret = OMX_ErrorNone; 1379 mm_jpeg_encode_params_t *p_params = &p_session->params; 1380 mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job; 1381 int dest_idx = 0; 1382 mm_jpeg_obj *my_obj = (mm_jpeg_obj *)p_session->jpeg_obj; 1383 1384 pthread_mutex_lock(&p_session->lock); 1385 p_session->abort_flag = OMX_FALSE; 1386 p_session->encoding = OMX_FALSE; 1387 pthread_mutex_unlock(&p_session->lock); 1388 1389 if (OMX_FALSE == p_session->config) { 1390 ret = mm_jpeg_session_configure(p_session); 1391 if (ret) { 1392 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 1393 goto error; 1394 } 1395 p_session->config = OMX_TRUE; 1396 } 1397 1398 pthread_mutex_lock(&p_session->lock); 1399 p_session->encoding = OMX_TRUE; 1400 pthread_mutex_unlock(&p_session->lock); 1401 1402 MM_JPEG_CHK_ABORT(p_session, ret, error); 1403 1404#ifdef MM_JPEG_DUMP_INPUT 1405 DUMP_TO_FILE("/data/mm_jpeg_int.yuv", 1406 p_session->p_in_omx_buf[p_jobparams->src_index]->pBuffer, 1407 (int)p_session->p_in_omx_buf[p_jobparams->src_index]->nAllocLen); 1408#endif 1409 1410 ret = OMX_EmptyThisBuffer(p_session->omx_handle, 1411 p_session->p_in_omx_buf[p_jobparams->src_index]); 1412 if (ret) { 1413 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 1414 goto error; 1415 } 1416 1417 if (p_session->params.encode_thumbnail) { 1418 ret = OMX_EmptyThisBuffer(p_session->omx_handle, 1419 p_session->p_in_omx_thumb_buf[p_jobparams->thumb_index]); 1420 if (ret) { 1421 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 1422 goto error; 1423 } 1424 } 1425 1426 ret = OMX_FillThisBuffer(p_session->omx_handle, 1427 p_session->p_out_omx_buf[p_jobparams->dst_index]); 1428 if (ret) { 1429 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 1430 goto error; 1431 } 1432 1433 MM_JPEG_CHK_ABORT(p_session, ret, error); 1434 1435error: 1436 1437 CDBG("%s:%d] X ", __func__, __LINE__); 1438 return ret; 1439} 1440 1441/** mm_jpeg_process_encoding_job: 1442 * 1443 * Arguments: 1444 * @my_obj: jpeg client 1445 * @job_node: job node 1446 * 1447 * Return: 1448 * 0 for success -1 otherwise 1449 * 1450 * Description: 1451 * Start the encoding job 1452 * 1453 **/ 1454int32_t mm_jpeg_process_encoding_job(mm_jpeg_obj *my_obj, mm_jpeg_job_q_node_t* job_node) 1455{ 1456 int32_t rc = 0; 1457 OMX_ERRORTYPE ret = OMX_ErrorNone; 1458 mm_jpeg_job_session_t *p_session = NULL; 1459 mm_jpeg_job_q_node_t *node = NULL; 1460 1461 /* check if valid session */ 1462 p_session = mm_jpeg_get_session(my_obj, job_node->enc_info.job_id); 1463 if (NULL == p_session) { 1464 CDBG_ERROR("%s:%d] invalid job id %x", __func__, __LINE__, 1465 job_node->enc_info.job_id); 1466 return -1; 1467 } 1468 1469 /* sent encode cmd to OMX, queue job into ongoing queue */ 1470 rc = mm_jpeg_queue_enq(&my_obj->ongoing_job_q, job_node); 1471 if (rc) { 1472 CDBG_ERROR("%s:%d] jpeg enqueue failed %d", 1473 __func__, __LINE__, ret); 1474 goto error; 1475 } 1476 1477 p_session->encode_job = job_node->enc_info.encode_job; 1478 p_session->jobId = job_node->enc_info.job_id; 1479 ret = mm_jpeg_session_encode(p_session); 1480 if (ret) { 1481 CDBG_ERROR("%s:%d] encode session failed", __func__, __LINE__); 1482 goto error; 1483 } 1484 1485 CDBG("%s:%d] Success X ", __func__, __LINE__); 1486 return rc; 1487 1488error: 1489 1490 if ((OMX_ErrorNone != ret) && 1491 (NULL != p_session->params.jpeg_cb)) { 1492 p_session->job_status = JPEG_JOB_STATUS_ERROR; 1493 CDBG("%s:%d] send jpeg error callback %d", __func__, __LINE__, 1494 p_session->job_status); 1495 p_session->params.jpeg_cb(p_session->job_status, 1496 p_session->client_hdl, 1497 p_session->jobId, 1498 NULL, 1499 p_session->params.userdata); 1500 } 1501 1502 /*remove the job*/ 1503 mm_jpeg_job_done(p_session); 1504 CDBG("%s:%d] Error X ", __func__, __LINE__); 1505 1506 return rc; 1507} 1508 1509/** mm_jpeg_jobmgr_thread: 1510 * 1511 * Arguments: 1512 * @my_obj: jpeg object 1513 * 1514 * Return: 1515 * 0 for success else failure 1516 * 1517 * Description: 1518 * job manager thread main function 1519 * 1520 **/ 1521static void *mm_jpeg_jobmgr_thread(void *data) 1522{ 1523 int rc = 0; 1524 int running = 1; 1525 uint32_t num_ongoing_jobs = 0; 1526 mm_jpeg_obj *my_obj = (mm_jpeg_obj*)data; 1527 mm_jpeg_job_cmd_thread_t *cmd_thread = &my_obj->job_mgr; 1528 mm_jpeg_job_q_node_t* node = NULL; 1529 1530 do { 1531 do { 1532 rc = cam_sem_wait(&cmd_thread->job_sem); 1533 if (rc != 0 && errno != EINVAL) { 1534 CDBG_ERROR("%s: cam_sem_wait error (%s)", 1535 __func__, strerror(errno)); 1536 return NULL; 1537 } 1538 } while (rc != 0); 1539 1540 /* check ongoing q size */ 1541 num_ongoing_jobs = mm_jpeg_queue_get_size(&my_obj->ongoing_job_q); 1542 if (num_ongoing_jobs >= NUM_MAX_JPEG_CNCURRENT_JOBS) { 1543 CDBG("%s:%d] ongoing job already reach max %d", __func__, 1544 __LINE__, num_ongoing_jobs); 1545 continue; 1546 } 1547 1548 pthread_mutex_lock(&my_obj->job_lock); 1549 /* can go ahead with new work */ 1550 node = (mm_jpeg_job_q_node_t*)mm_jpeg_queue_deq(&cmd_thread->job_queue); 1551 if (node != NULL) { 1552 switch (node->type) { 1553 case MM_JPEG_CMD_TYPE_JOB: 1554 rc = mm_jpeg_process_encoding_job(my_obj, node); 1555 break; 1556 case MM_JPEG_CMD_TYPE_EXIT: 1557 default: 1558 /* free node */ 1559 free(node); 1560 /* set running flag to false */ 1561 running = 0; 1562 break; 1563 } 1564 } 1565 pthread_mutex_unlock(&my_obj->job_lock); 1566 1567 } while (running); 1568 return NULL; 1569} 1570 1571/** mm_jpeg_jobmgr_thread_launch: 1572 * 1573 * Arguments: 1574 * @my_obj: jpeg object 1575 * 1576 * Return: 1577 * 0 for success else failure 1578 * 1579 * Description: 1580 * launches the job manager thread 1581 * 1582 **/ 1583int32_t mm_jpeg_jobmgr_thread_launch(mm_jpeg_obj *my_obj) 1584{ 1585 int32_t rc = 0; 1586 mm_jpeg_job_cmd_thread_t *job_mgr = &my_obj->job_mgr; 1587 1588 cam_sem_init(&job_mgr->job_sem, 0); 1589 mm_jpeg_queue_init(&job_mgr->job_queue); 1590 1591 /* launch the thread */ 1592 pthread_create(&job_mgr->pid, 1593 NULL, 1594 mm_jpeg_jobmgr_thread, 1595 (void *)my_obj); 1596 return rc; 1597} 1598 1599/** mm_jpeg_jobmgr_thread_release: 1600 * 1601 * Arguments: 1602 * @my_obj: jpeg object 1603 * 1604 * Return: 1605 * 0 for success else failure 1606 * 1607 * Description: 1608 * Releases the job manager thread 1609 * 1610 **/ 1611int32_t mm_jpeg_jobmgr_thread_release(mm_jpeg_obj * my_obj) 1612{ 1613 int32_t rc = 0; 1614 mm_jpeg_job_cmd_thread_t * cmd_thread = &my_obj->job_mgr; 1615 mm_jpeg_job_q_node_t* node = 1616 (mm_jpeg_job_q_node_t *)malloc(sizeof(mm_jpeg_job_q_node_t)); 1617 if (NULL == node) { 1618 CDBG_ERROR("%s: No memory for mm_jpeg_job_q_node_t", __func__); 1619 return -1; 1620 } 1621 1622 memset(node, 0, sizeof(mm_jpeg_job_q_node_t)); 1623 node->type = MM_JPEG_CMD_TYPE_EXIT; 1624 1625 mm_jpeg_queue_enq(&cmd_thread->job_queue, node); 1626 cam_sem_post(&cmd_thread->job_sem); 1627 1628 /* wait until cmd thread exits */ 1629 if (pthread_join(cmd_thread->pid, NULL) != 0) { 1630 CDBG("%s: pthread dead already", __func__); 1631 } 1632 mm_jpeg_queue_deinit(&cmd_thread->job_queue); 1633 1634 cam_sem_destroy(&cmd_thread->job_sem); 1635 memset(cmd_thread, 0, sizeof(mm_jpeg_job_cmd_thread_t)); 1636 return rc; 1637} 1638 1639/** mm_jpeg_init: 1640 * 1641 * Arguments: 1642 * @my_obj: jpeg object 1643 * 1644 * Return: 1645 * 0 for success else failure 1646 * 1647 * Description: 1648 * Initializes the jpeg client 1649 * 1650 **/ 1651int32_t mm_jpeg_init(mm_jpeg_obj *my_obj) 1652{ 1653 int32_t rc = 0; 1654 1655 /* init locks */ 1656 pthread_mutex_init(&my_obj->job_lock, NULL); 1657 1658 /* init ongoing job queue */ 1659 rc = mm_jpeg_queue_init(&my_obj->ongoing_job_q); 1660 if (0 != rc) { 1661 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 1662 return -1; 1663 } 1664 1665 /* init job semaphore and launch jobmgr thread */ 1666 CDBG("%s:%d] Launch jobmgr thread rc %d", __func__, __LINE__, rc); 1667 rc = mm_jpeg_jobmgr_thread_launch(my_obj); 1668 if (0 != rc) { 1669 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 1670 return -1; 1671 } 1672 1673 /* load OMX */ 1674 if (OMX_ErrorNone != OMX_Init()) { 1675 /* roll back in error case */ 1676 CDBG_ERROR("%s:%d] OMX_Init failed (%d)", __func__, __LINE__, rc); 1677 mm_jpeg_jobmgr_thread_release(my_obj); 1678 mm_jpeg_queue_deinit(&my_obj->ongoing_job_q); 1679 pthread_mutex_destroy(&my_obj->job_lock); 1680 } 1681 1682 return rc; 1683} 1684 1685/** mm_jpeg_deinit: 1686 * 1687 * Arguments: 1688 * @my_obj: jpeg object 1689 * 1690 * Return: 1691 * 0 for success else failure 1692 * 1693 * Description: 1694 * Deinits the jpeg client 1695 * 1696 **/ 1697int32_t mm_jpeg_deinit(mm_jpeg_obj *my_obj) 1698{ 1699 int32_t rc = 0; 1700 1701 /* release jobmgr thread */ 1702 rc = mm_jpeg_jobmgr_thread_release(my_obj); 1703 if (0 != rc) { 1704 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 1705 } 1706 1707 /* unload OMX engine */ 1708 OMX_Deinit(); 1709 1710 /* deinit ongoing job and cb queue */ 1711 rc = mm_jpeg_queue_deinit(&my_obj->ongoing_job_q); 1712 if (0 != rc) { 1713 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 1714 } 1715 1716 /* destroy locks */ 1717 pthread_mutex_destroy(&my_obj->job_lock); 1718 1719 return rc; 1720} 1721 1722/** mm_jpeg_new_client: 1723 * 1724 * Arguments: 1725 * @my_obj: jpeg object 1726 * 1727 * Return: 1728 * 0 for success else failure 1729 * 1730 * Description: 1731 * Create new jpeg client 1732 * 1733 **/ 1734uint32_t mm_jpeg_new_client(mm_jpeg_obj *my_obj) 1735{ 1736 uint32_t client_hdl = 0; 1737 uint8_t idx; 1738 int i = 0; 1739 1740 if (my_obj->num_clients >= MAX_JPEG_CLIENT_NUM) { 1741 CDBG_ERROR("%s: num of clients reached limit", __func__); 1742 return client_hdl; 1743 } 1744 1745 for (idx = 0; idx < MAX_JPEG_CLIENT_NUM; idx++) { 1746 if (0 == my_obj->clnt_mgr[idx].is_used) { 1747 break; 1748 } 1749 } 1750 1751 if (idx < MAX_JPEG_CLIENT_NUM) { 1752 /* client session avail */ 1753 /* generate client handler by index */ 1754 client_hdl = mm_jpeg_util_generate_handler(idx); 1755 1756 /* update client session */ 1757 my_obj->clnt_mgr[idx].is_used = 1; 1758 my_obj->clnt_mgr[idx].client_handle = client_hdl; 1759 1760 pthread_mutex_init(&my_obj->clnt_mgr[idx].lock, NULL); 1761 for (i = 0; i < MM_JPEG_MAX_SESSION; i++) { 1762 memset(&my_obj->clnt_mgr[idx].session[i], 0x0, sizeof(mm_jpeg_job_session_t)); 1763 } 1764 1765 /* increse client count */ 1766 my_obj->num_clients++; 1767 } 1768 1769 return client_hdl; 1770} 1771 1772/** mm_jpeg_start_job: 1773 * 1774 * Arguments: 1775 * @my_obj: jpeg object 1776 * @client_hdl: client handle 1777 * @job: pointer to encode job 1778 * @jobId: job id 1779 * 1780 * Return: 1781 * 0 for success else failure 1782 * 1783 * Description: 1784 * Start the encoding job 1785 * 1786 **/ 1787int32_t mm_jpeg_start_job(mm_jpeg_obj *my_obj, 1788 mm_jpeg_job_t *job, 1789 uint32_t *job_id) 1790{ 1791 int32_t rc = -1; 1792 uint8_t session_idx = 0; 1793 uint8_t client_idx = 0; 1794 mm_jpeg_job_q_node_t* node = NULL; 1795 mm_jpeg_job_session_t *p_session = NULL; 1796 mm_jpeg_encode_job_t *p_jobparams = &job->encode_job; 1797 1798 *job_id = 0; 1799 1800 /* check if valid session */ 1801 session_idx = GET_SESSION_IDX(p_jobparams->session_id); 1802 client_idx = GET_CLIENT_IDX(p_jobparams->session_id); 1803 CDBG("%s:%d] session_idx %d client idx %d", __func__, __LINE__, 1804 session_idx, client_idx); 1805 1806 if ((session_idx >= MM_JPEG_MAX_SESSION) || 1807 (client_idx >= MAX_JPEG_CLIENT_NUM)) { 1808 CDBG_ERROR("%s:%d] invalid session id %x", __func__, __LINE__, 1809 job->encode_job.session_id); 1810 return rc; 1811 } 1812 1813 p_session = &my_obj->clnt_mgr[client_idx].session[session_idx]; 1814 if (OMX_FALSE == p_session->active) { 1815 CDBG_ERROR("%s:%d] session not active %x", __func__, __LINE__, 1816 job->encode_job.session_id); 1817 return rc; 1818 } 1819 1820 if ((p_jobparams->src_index >= p_session->params.num_src_bufs) || 1821 (p_jobparams->dst_index >= p_session->params.num_dst_bufs)) { 1822 CDBG_ERROR("%s:%d] invalid buffer indices", __func__, __LINE__); 1823 return rc; 1824 } 1825 1826 /* enqueue new job into todo job queue */ 1827 node = (mm_jpeg_job_q_node_t *)malloc(sizeof(mm_jpeg_job_q_node_t)); 1828 if (NULL == node) { 1829 CDBG_ERROR("%s: No memory for mm_jpeg_job_q_node_t", __func__); 1830 return -1; 1831 } 1832 1833 *job_id = job->encode_job.session_id | 1834 ((p_session->job_hist++ % JOB_HIST_MAX) << 16); 1835 1836 memset(node, 0, sizeof(mm_jpeg_job_q_node_t)); 1837 node->enc_info.encode_job = job->encode_job; 1838 node->enc_info.job_id = *job_id; 1839 node->enc_info.client_handle = p_session->client_hdl; 1840 node->type = MM_JPEG_CMD_TYPE_JOB; 1841 1842 rc = mm_jpeg_queue_enq(&my_obj->job_mgr.job_queue, node); 1843 if (0 == rc) { 1844 cam_sem_post(&my_obj->job_mgr.job_sem); 1845 } 1846 1847 return rc; 1848} 1849 1850/** mm_jpeg_abort_job: 1851 * 1852 * Arguments: 1853 * @my_obj: jpeg object 1854 * @client_hdl: client handle 1855 * @jobId: job id 1856 * 1857 * Return: 1858 * 0 for success else failure 1859 * 1860 * Description: 1861 * Abort the encoding session 1862 * 1863 **/ 1864int32_t mm_jpeg_abort_job(mm_jpeg_obj *my_obj, 1865 uint32_t jobId) 1866{ 1867 int32_t rc = -1; 1868 uint8_t clnt_idx = 0; 1869 mm_jpeg_job_q_node_t *node = NULL; 1870 OMX_BOOL ret = OMX_FALSE; 1871 mm_jpeg_job_session_t *p_session = NULL; 1872 1873 CDBG("%s:%d] ", __func__, __LINE__); 1874 pthread_mutex_lock(&my_obj->job_lock); 1875 1876 /* abort job if in todo queue */ 1877 node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->job_mgr.job_queue, jobId); 1878 if (NULL != node) { 1879 free(node); 1880 goto abort_done; 1881 } 1882 1883 /* abort job if in ongoing queue */ 1884 node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->ongoing_job_q, jobId); 1885 if (NULL != node) { 1886 /* find job that is OMX ongoing, ask OMX to abort the job */ 1887 p_session = mm_jpeg_get_session(my_obj, node->enc_info.job_id); 1888 if (p_session) { 1889 mm_jpeg_session_abort(p_session); 1890 } else { 1891 CDBG_ERROR("%s:%d] Invalid job id 0x%x", __func__, __LINE__, 1892 node->enc_info.job_id); 1893 } 1894 free(node); 1895 goto abort_done; 1896 } 1897 1898abort_done: 1899 pthread_mutex_unlock(&my_obj->job_lock); 1900 1901 return rc; 1902} 1903 1904/** mm_jpeg_create_session: 1905 * 1906 * Arguments: 1907 * @my_obj: jpeg object 1908 * @client_hdl: client handle 1909 * @p_params: pointer to encode params 1910 * @p_session_id: session id 1911 * 1912 * Return: 1913 * 0 for success else failure 1914 * 1915 * Description: 1916 * Start the encoding session 1917 * 1918 **/ 1919int32_t mm_jpeg_create_session(mm_jpeg_obj *my_obj, 1920 uint32_t client_hdl, 1921 mm_jpeg_encode_params_t *p_params, 1922 uint32_t* p_session_id) 1923{ 1924 int32_t rc = 0; 1925 OMX_ERRORTYPE ret = OMX_ErrorNone; 1926 uint8_t clnt_idx = 0; 1927 int session_idx = -1; 1928 mm_jpeg_job_session_t *p_session = NULL; 1929 *p_session_id = 0; 1930 1931 /* validate the parameters */ 1932 if ((p_params->num_src_bufs > MM_JPEG_MAX_BUF) 1933 || (p_params->num_dst_bufs > MM_JPEG_MAX_BUF)) { 1934 CDBG_ERROR("%s:%d] invalid num buffers", __func__, __LINE__); 1935 return -1; 1936 } 1937 1938 /* check if valid client */ 1939 clnt_idx = mm_jpeg_util_get_index_by_handler(client_hdl); 1940 if (clnt_idx >= MAX_JPEG_CLIENT_NUM) { 1941 CDBG_ERROR("%s: invalid client with handler (%d)", __func__, client_hdl); 1942 return -1; 1943 } 1944 1945 session_idx = mm_jpeg_get_new_session_idx(my_obj, clnt_idx, &p_session); 1946 if (session_idx < 0) { 1947 CDBG_ERROR("%s:%d] invalid session id (%d)", __func__, __LINE__, session_idx); 1948 return -1; 1949 } 1950 1951 ret = mm_jpeg_session_create(p_session); 1952 if (OMX_ErrorNone != ret) { 1953 p_session->active = OMX_FALSE; 1954 CDBG_ERROR("%s:%d] jpeg session create failed", __func__, __LINE__); 1955 return ret; 1956 } 1957 1958 *p_session_id = (JOB_ID_MAGICVAL << 24) | (session_idx << 8) | clnt_idx; 1959 1960 /*copy the params*/ 1961 p_session->params = *p_params; 1962 p_session->client_hdl = client_hdl; 1963 p_session->sessionId = *p_session_id; 1964 p_session->jpeg_obj = (void*)my_obj; /* save a ptr to jpeg_obj */ 1965 CDBG("%s:%d] session id %x", __func__, __LINE__, *p_session_id); 1966 1967 return ret; 1968} 1969 1970/** mm_jpeg_destroy_session: 1971 * 1972 * Arguments: 1973 * @my_obj: jpeg object 1974 * @session_id: session index 1975 * 1976 * Return: 1977 * 0 for success else failure 1978 * 1979 * Description: 1980 * Destroy the encoding session 1981 * 1982 **/ 1983int32_t mm_jpeg_destroy_session(mm_jpeg_obj *my_obj, 1984 mm_jpeg_job_session_t *p_session) 1985{ 1986 int32_t rc = 0; 1987 uint8_t clnt_idx = 0; 1988 mm_jpeg_job_q_node_t *node = NULL; 1989 OMX_BOOL ret = OMX_FALSE; 1990 uint32_t session_id = p_session->sessionId; 1991 1992 if (NULL == p_session) { 1993 CDBG_ERROR("%s:%d] invalid session", __func__, __LINE__); 1994 return rc; 1995 } 1996 1997 pthread_mutex_lock(&my_obj->job_lock); 1998 1999 /* abort job if in todo queue */ 2000 CDBG("%s:%d] abort todo jobs", __func__, __LINE__); 2001 node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id); 2002 while (NULL != node) { 2003 free(node); 2004 node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id); 2005 } 2006 2007 /* abort job if in ongoing queue */ 2008 CDBG("%s:%d] abort ongoing jobs", __func__, __LINE__); 2009 node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id); 2010 while (NULL != node) { 2011 free(node); 2012 node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id); 2013 } 2014 2015 /* abort the current session */ 2016 mm_jpeg_session_abort(p_session); 2017 mm_jpeg_session_destroy(p_session); 2018 mm_jpeg_remove_session_idx(my_obj, session_id); 2019 pthread_mutex_unlock(&my_obj->job_lock); 2020 2021 /* wake up jobMgr thread to work on new job if there is any */ 2022 cam_sem_post(&my_obj->job_mgr.job_sem); 2023 CDBG("%s:%d] X", __func__, __LINE__); 2024 2025 return rc; 2026} 2027 2028/** mm_jpeg_destroy_session: 2029 * 2030 * Arguments: 2031 * @my_obj: jpeg object 2032 * @session_id: session index 2033 * 2034 * Return: 2035 * 0 for success else failure 2036 * 2037 * Description: 2038 * Destroy the encoding session 2039 * 2040 **/ 2041int32_t mm_jpeg_destroy_session_unlocked(mm_jpeg_obj *my_obj, 2042 mm_jpeg_job_session_t *p_session) 2043{ 2044 int32_t rc = -1; 2045 uint8_t clnt_idx = 0; 2046 mm_jpeg_job_q_node_t *node = NULL; 2047 OMX_BOOL ret = OMX_FALSE; 2048 uint32_t session_id = p_session->sessionId; 2049 2050 if (NULL == p_session) { 2051 CDBG_ERROR("%s:%d] invalid session", __func__, __LINE__); 2052 return rc; 2053 } 2054 2055 /* abort job if in todo queue */ 2056 CDBG("%s:%d] abort todo jobs", __func__, __LINE__); 2057 node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id); 2058 while (NULL != node) { 2059 free(node); 2060 node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id); 2061 } 2062 2063 /* abort job if in ongoing queue */ 2064 CDBG("%s:%d] abort ongoing jobs", __func__, __LINE__); 2065 node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id); 2066 while (NULL != node) { 2067 free(node); 2068 node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id); 2069 } 2070 2071 /* abort the current session */ 2072 mm_jpeg_session_abort(p_session); 2073 mm_jpeg_remove_session_idx(my_obj, session_id); 2074 2075 return rc; 2076} 2077 2078/** mm_jpeg_destroy_session: 2079 * 2080 * Arguments: 2081 * @my_obj: jpeg object 2082 * @session_id: session index 2083 * 2084 * Return: 2085 * 0 for success else failure 2086 * 2087 * Description: 2088 * Destroy the encoding session 2089 * 2090 **/ 2091int32_t mm_jpeg_destroy_session_by_id(mm_jpeg_obj *my_obj, uint32_t session_id) 2092{ 2093 mm_jpeg_job_session_t *p_session = mm_jpeg_get_session(my_obj, session_id); 2094 2095 return mm_jpeg_destroy_session(my_obj, p_session); 2096} 2097 2098/** mm_jpeg_close: 2099 * 2100 * Arguments: 2101 * @my_obj: jpeg object 2102 * @client_hdl: client handle 2103 * 2104 * Return: 2105 * 0 for success else failure 2106 * 2107 * Description: 2108 * Close the jpeg client 2109 * 2110 **/ 2111int32_t mm_jpeg_close(mm_jpeg_obj *my_obj, uint32_t client_hdl) 2112{ 2113 int32_t rc = -1; 2114 uint8_t clnt_idx = 0; 2115 mm_jpeg_job_q_node_t *node = NULL; 2116 OMX_BOOL ret = OMX_FALSE; 2117 int i = 0; 2118 2119 /* check if valid client */ 2120 clnt_idx = mm_jpeg_util_get_index_by_handler(client_hdl); 2121 if (clnt_idx >= MAX_JPEG_CLIENT_NUM) { 2122 CDBG_ERROR("%s: invalid client with handler (%d)", __func__, client_hdl); 2123 return rc; 2124 } 2125 2126 CDBG("%s:%d] E", __func__, __LINE__); 2127 2128 /* abort all jobs from the client */ 2129 pthread_mutex_lock(&my_obj->job_lock); 2130 2131 CDBG("%s:%d] ", __func__, __LINE__); 2132 2133 for (i = 0; i < MM_JPEG_MAX_SESSION; i++) { 2134 if (OMX_TRUE == my_obj->clnt_mgr[clnt_idx].session[i].active) 2135 mm_jpeg_destroy_session_unlocked(my_obj, 2136 &my_obj->clnt_mgr[clnt_idx].session[i]); 2137 } 2138 2139 CDBG("%s:%d] ", __func__, __LINE__); 2140 2141 pthread_mutex_unlock(&my_obj->job_lock); 2142 CDBG("%s:%d] ", __func__, __LINE__); 2143 2144 /* invalidate client session */ 2145 pthread_mutex_destroy(&my_obj->clnt_mgr[clnt_idx].lock); 2146 memset(&my_obj->clnt_mgr[clnt_idx], 0, sizeof(mm_jpeg_client_t)); 2147 2148 rc = 0; 2149 CDBG("%s:%d] X", __func__, __LINE__); 2150 return rc; 2151} 2152 2153OMX_ERRORTYPE mm_jpeg_ebd(OMX_HANDLETYPE hComponent, 2154 OMX_PTR pAppData, 2155 OMX_BUFFERHEADERTYPE *pBuffer) 2156{ 2157 OMX_ERRORTYPE ret = OMX_ErrorNone; 2158 mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData; 2159 2160 CDBG("%s:%d] count %d ", __func__, __LINE__, p_session->ebd_count); 2161 pthread_mutex_lock(&p_session->lock); 2162 p_session->ebd_count++; 2163 pthread_mutex_unlock(&p_session->lock); 2164 return 0; 2165} 2166 2167OMX_ERRORTYPE mm_jpeg_fbd(OMX_HANDLETYPE hComponent, 2168 OMX_PTR pAppData, 2169 OMX_BUFFERHEADERTYPE *pBuffer) 2170{ 2171 OMX_ERRORTYPE ret = OMX_ErrorNone; 2172 mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData; 2173 uint32_t i = 0; 2174 int rc = 0; 2175 mm_jpeg_output_t output_buf; 2176 2177 CDBG("%s:%d] count %d ", __func__, __LINE__, p_session->fbd_count); 2178 2179 if (OMX_TRUE == p_session->abort_flag) { 2180 pthread_cond_signal(&p_session->cond); 2181 return ret; 2182 } 2183 2184 pthread_mutex_lock(&p_session->lock); 2185 p_session->fbd_count++; 2186 if (NULL != p_session->params.jpeg_cb) { 2187 p_session->job_status = JPEG_JOB_STATUS_DONE; 2188 output_buf.buf_filled_len = (uint32_t)pBuffer->nFilledLen; 2189 output_buf.buf_vaddr = pBuffer->pBuffer; 2190 output_buf.fd = 0; 2191 CDBG("%s:%d] send jpeg callback %d", __func__, __LINE__, 2192 p_session->job_status); 2193 p_session->params.jpeg_cb(p_session->job_status, 2194 p_session->client_hdl, 2195 p_session->jobId, 2196 &output_buf, 2197 p_session->params.userdata); 2198 2199 /* remove from ready queue */ 2200 mm_jpeg_job_done(p_session); 2201 } 2202 pthread_mutex_unlock(&p_session->lock); 2203 CDBG("%s:%d] ", __func__, __LINE__); 2204 2205 return ret; 2206} 2207 2208OMX_ERRORTYPE mm_jpeg_event_handler(OMX_HANDLETYPE hComponent, 2209 OMX_PTR pAppData, 2210 OMX_EVENTTYPE eEvent, 2211 OMX_U32 nData1, 2212 OMX_U32 nData2, 2213 OMX_PTR pEventData) 2214{ 2215 mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData; 2216 2217 CDBG("%s:%d] %d %d %d", __func__, __LINE__, eEvent, (int)nData1, 2218 (int)nData2); 2219 2220 pthread_mutex_lock(&p_session->lock); 2221 2222 if (OMX_TRUE == p_session->abort_flag) { 2223 pthread_cond_signal(&p_session->cond); 2224 pthread_mutex_unlock(&p_session->lock); 2225 return OMX_ErrorNone; 2226 } 2227 2228 if (eEvent == OMX_EventError) { 2229 p_session->error_flag = OMX_ErrorHardware; 2230 if (p_session->encoding == OMX_TRUE) { 2231 CDBG("%s:%d] Error during encoding", __func__, __LINE__); 2232 2233 /* send jpeg callback */ 2234 if (NULL != p_session->params.jpeg_cb) { 2235 p_session->job_status = JPEG_JOB_STATUS_ERROR; 2236 CDBG("%s:%d] send jpeg error callback %d", __func__, __LINE__, 2237 p_session->job_status); 2238 p_session->params.jpeg_cb(p_session->job_status, 2239 p_session->client_hdl, 2240 p_session->jobId, 2241 NULL, 2242 p_session->params.userdata); 2243 } 2244 2245 /* remove from ready queue */ 2246 mm_jpeg_job_done(p_session); 2247 } 2248 pthread_cond_signal(&p_session->cond); 2249 } else if (eEvent == OMX_EventCmdComplete) { 2250 if (p_session->state_change_pending == OMX_TRUE) { 2251 p_session->state_change_pending = OMX_FALSE; 2252 pthread_cond_signal(&p_session->cond); 2253 } 2254 } 2255 2256 pthread_mutex_unlock(&p_session->lock); 2257 CDBG("%s:%d]", __func__, __LINE__); 2258 return OMX_ErrorNone; 2259} 2260 2261/* remove the first job from the queue with matching client handle */ 2262mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_client_id( 2263 mm_jpeg_queue_t* queue, uint32_t client_hdl) 2264{ 2265 mm_jpeg_q_node_t* node = NULL; 2266 mm_jpeg_job_q_node_t* data = NULL; 2267 mm_jpeg_job_q_node_t* job_node = NULL; 2268 struct cam_list *head = NULL; 2269 struct cam_list *pos = NULL; 2270 2271 pthread_mutex_lock(&queue->lock); 2272 head = &queue->head.list; 2273 pos = head->next; 2274 while(pos != head) { 2275 node = member_of(pos, mm_jpeg_q_node_t, list); 2276 data = (mm_jpeg_job_q_node_t *)node->data; 2277 2278 if (data && (data->enc_info.client_handle == client_hdl)) { 2279 CDBG_ERROR("%s:%d] found matching client handle", __func__, __LINE__); 2280 job_node = data; 2281 cam_list_del_node(&node->list); 2282 queue->size--; 2283 free(node); 2284 CDBG_ERROR("%s: queue size = %d", __func__, queue->size); 2285 break; 2286 } 2287 pos = pos->next; 2288 } 2289 2290 pthread_mutex_unlock(&queue->lock); 2291 2292 return job_node; 2293} 2294 2295/* remove the first job from the queue with matching session id */ 2296mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_session_id( 2297 mm_jpeg_queue_t* queue, uint32_t session_id) 2298{ 2299 mm_jpeg_q_node_t* node = NULL; 2300 mm_jpeg_job_q_node_t* data = NULL; 2301 mm_jpeg_job_q_node_t* job_node = NULL; 2302 struct cam_list *head = NULL; 2303 struct cam_list *pos = NULL; 2304 2305 pthread_mutex_lock(&queue->lock); 2306 head = &queue->head.list; 2307 pos = head->next; 2308 while(pos != head) { 2309 node = member_of(pos, mm_jpeg_q_node_t, list); 2310 data = (mm_jpeg_job_q_node_t *)node->data; 2311 2312 if (data && (data->enc_info.encode_job.session_id == session_id)) { 2313 CDBG_ERROR("%s:%d] found matching session id", __func__, __LINE__); 2314 job_node = data; 2315 cam_list_del_node(&node->list); 2316 queue->size--; 2317 free(node); 2318 CDBG_ERROR("%s: queue size = %d", __func__, queue->size); 2319 break; 2320 } 2321 pos = pos->next; 2322 } 2323 2324 pthread_mutex_unlock(&queue->lock); 2325 2326 return job_node; 2327} 2328 2329/* remove job from the queue with matching job id */ 2330mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_job_id( 2331 mm_jpeg_queue_t* queue, uint32_t job_id) 2332{ 2333 mm_jpeg_q_node_t* node = NULL; 2334 mm_jpeg_job_q_node_t* data = NULL; 2335 mm_jpeg_job_q_node_t* job_node = NULL; 2336 struct cam_list *head = NULL; 2337 struct cam_list *pos = NULL; 2338 2339 pthread_mutex_lock(&queue->lock); 2340 head = &queue->head.list; 2341 pos = head->next; 2342 while(pos != head) { 2343 node = member_of(pos, mm_jpeg_q_node_t, list); 2344 data = (mm_jpeg_job_q_node_t *)node->data; 2345 2346 if (data && (data->enc_info.job_id == job_id)) { 2347 CDBG_ERROR("%s:%d] found matching job id", __func__, __LINE__); 2348 job_node = data; 2349 cam_list_del_node(&node->list); 2350 queue->size--; 2351 free(node); 2352 break; 2353 } 2354 pos = pos->next; 2355 } 2356 2357 pthread_mutex_unlock(&queue->lock); 2358 2359 return job_node; 2360} 2361 2362/* remove job from the queue with matching job id */ 2363mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_unlk( 2364 mm_jpeg_queue_t* queue, uint32_t job_id) 2365{ 2366 mm_jpeg_q_node_t* node = NULL; 2367 mm_jpeg_job_q_node_t* data = NULL; 2368 mm_jpeg_job_q_node_t* job_node = NULL; 2369 struct cam_list *head = NULL; 2370 struct cam_list *pos = NULL; 2371 2372 head = &queue->head.list; 2373 pos = head->next; 2374 while(pos != head) { 2375 node = member_of(pos, mm_jpeg_q_node_t, list); 2376 data = (mm_jpeg_job_q_node_t *)node->data; 2377 2378 if (data && (data->enc_info.job_id == job_id)) { 2379 job_node = data; 2380 cam_list_del_node(&node->list); 2381 queue->size--; 2382 free(node); 2383 break; 2384 } 2385 pos = pos->next; 2386 } 2387 2388 return job_node; 2389} 2390