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