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