1 /* Copyright (c) 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 #include "mm_jpeg_inlines.h" 42 43 OMX_ERRORTYPE mm_jpegdec_ebd(OMX_HANDLETYPE hComponent, 44 OMX_PTR pAppData, 45 OMX_BUFFERHEADERTYPE *pBuffer); 46 OMX_ERRORTYPE mm_jpegdec_fbd(OMX_HANDLETYPE hComponent, 47 OMX_PTR pAppData, 48 OMX_BUFFERHEADERTYPE* pBuffer); 49 OMX_ERRORTYPE mm_jpegdec_event_handler(OMX_HANDLETYPE hComponent, 50 OMX_PTR pAppData, 51 OMX_EVENTTYPE eEvent, 52 OMX_U32 nData1, 53 OMX_U32 nData2, 54 OMX_PTR pEventData); 55 56 57 /** mm_jpegdec_destroy_job 58 * 59 * Arguments: 60 * @p_session: Session obj 61 * 62 * Return: 63 * 0 for success else failure 64 * 65 * Description: 66 * Destroy the job based paramenters 67 * 68 **/ 69 static int32_t mm_jpegdec_destroy_job(mm_jpeg_job_session_t *p_session) 70 { 71 mm_jpeg_decode_job_t *p_jobparams = &p_session->decode_job; 72 int32_t rc = 0; 73 74 return rc; 75 } 76 77 /** mm_jpeg_job_done: 78 * 79 * Arguments: 80 * @p_session: decode session 81 * 82 * Return: 83 * OMX_ERRORTYPE 84 * 85 * Description: 86 * Finalize the job 87 * 88 **/ 89 static void mm_jpegdec_job_done(mm_jpeg_job_session_t *p_session) 90 { 91 mm_jpeg_obj *my_obj = (mm_jpeg_obj *)p_session->jpeg_obj; 92 mm_jpeg_job_q_node_t *node = NULL; 93 94 /*Destroy job related params*/ 95 mm_jpegdec_destroy_job(p_session); 96 97 /*remove the job*/ 98 node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->ongoing_job_q, 99 p_session->jobId); 100 if (node) { 101 free(node); 102 } 103 p_session->encoding = OMX_FALSE; 104 105 /* wake up jobMgr thread to work on new job if there is any */ 106 cam_sem_post(&my_obj->job_mgr.job_sem); 107 } 108 109 110 /** mm_jpegdec_session_send_buffers: 111 * 112 * Arguments: 113 * @data: job session 114 * 115 * Return: 116 * OMX error values 117 * 118 * Description: 119 * Send the buffers to OMX layer 120 * 121 **/ 122 OMX_ERRORTYPE mm_jpegdec_session_send_buffers(void *data) 123 { 124 uint32_t i = 0; 125 mm_jpeg_job_session_t* p_session = (mm_jpeg_job_session_t *)data; 126 OMX_ERRORTYPE ret = OMX_ErrorNone; 127 QOMX_BUFFER_INFO lbuffer_info; 128 mm_jpeg_decode_params_t *p_params = &p_session->dec_params; 129 mm_jpeg_decode_job_t *p_jobparams = &p_session->decode_job; 130 131 memset(&lbuffer_info, 0x0, sizeof(QOMX_BUFFER_INFO)); 132 for (i = 0; i < p_params->num_src_bufs; i++) { 133 CDBG("%s:%d] Source buffer %d", __func__, __LINE__, i); 134 lbuffer_info.fd = p_params->src_main_buf[i].fd; 135 ret = OMX_UseBuffer(p_session->omx_handle, &(p_session->p_in_omx_buf[i]), 0, 136 &lbuffer_info, p_params->src_main_buf[i].buf_size, 137 p_params->src_main_buf[i].buf_vaddr); 138 if (ret) { 139 CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret); 140 return ret; 141 } 142 } 143 144 CDBG("%s:%d]", __func__, __LINE__); 145 return ret; 146 } 147 148 /** mm_jpeg_session_free_buffers: 149 * 150 * Arguments: 151 * @data: job session 152 * 153 * Return: 154 * OMX error values 155 * 156 * Description: 157 * Free the buffers from OMX layer 158 * 159 **/ 160 OMX_ERRORTYPE mm_jpegdec_session_free_buffers(void *data) 161 { 162 OMX_ERRORTYPE ret = OMX_ErrorNone; 163 uint32_t i = 0; 164 mm_jpeg_job_session_t* p_session = (mm_jpeg_job_session_t *)data; 165 mm_jpeg_decode_params_t *p_params = &p_session->dec_params; 166 mm_jpeg_decode_job_t *p_jobparams = &p_session->decode_job; 167 168 for (i = 0; i < p_params->num_src_bufs; i++) { 169 CDBG("%s:%d] Source buffer %d", __func__, __LINE__, i); 170 ret = OMX_FreeBuffer(p_session->omx_handle, 0, p_session->p_in_omx_buf[i]); 171 if (ret) { 172 CDBG_ERROR("%s:%d] Error %d", __func__, __LINE__, ret); 173 return ret; 174 } 175 } 176 177 for (i = 0; i < p_params->num_dst_bufs; i++) { 178 CDBG("%s:%d] Dest buffer %d", __func__, __LINE__, i); 179 ret = OMX_FreeBuffer(p_session->omx_handle, 1, p_session->p_out_omx_buf[i]); 180 if (ret) { 181 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 182 return ret; 183 } 184 } 185 CDBG("%s:%d]", __func__, __LINE__); 186 return ret; 187 } 188 189 /** mm_jpegdec_session_create: 190 * 191 * Arguments: 192 * @p_session: job session 193 * 194 * Return: 195 * OMX error types 196 * 197 * Description: 198 * Create a jpeg encode session 199 * 200 **/ 201 OMX_ERRORTYPE mm_jpegdec_session_create(mm_jpeg_job_session_t* p_session) 202 { 203 OMX_ERRORTYPE rc = OMX_ErrorNone; 204 mm_jpeg_cirq_t *p_cirq = NULL; 205 206 pthread_mutex_init(&p_session->lock, NULL); 207 pthread_cond_init(&p_session->cond, NULL); 208 cirq_reset(&p_session->cb_q); 209 p_session->state_change_pending = OMX_FALSE; 210 p_session->abort_state = MM_JPEG_ABORT_NONE; 211 p_session->error_flag = OMX_ErrorNone; 212 p_session->ebd_count = 0; 213 p_session->fbd_count = 0; 214 p_session->encode_pid = -1; 215 p_session->config = OMX_FALSE; 216 217 p_session->omx_callbacks.EmptyBufferDone = mm_jpegdec_ebd; 218 p_session->omx_callbacks.FillBufferDone = mm_jpegdec_fbd; 219 p_session->omx_callbacks.EventHandler = mm_jpegdec_event_handler; 220 p_session->exif_count_local = 0; 221 222 rc = OMX_GetHandle(&p_session->omx_handle, 223 "OMX.qcom.image.jpeg.decoder", 224 (void *)p_session, 225 &p_session->omx_callbacks); 226 227 if (OMX_ErrorNone != rc) { 228 CDBG_ERROR("%s:%d] OMX_GetHandle failed (%d)", __func__, __LINE__, rc); 229 return rc; 230 } 231 return rc; 232 } 233 234 /** mm_jpegdec_session_destroy: 235 * 236 * Arguments: 237 * @p_session: job session 238 * 239 * Return: 240 * none 241 * 242 * Description: 243 * Destroy a jpeg encode session 244 * 245 **/ 246 void mm_jpegdec_session_destroy(mm_jpeg_job_session_t* p_session) 247 { 248 OMX_ERRORTYPE rc = OMX_ErrorNone; 249 250 CDBG("%s:%d] E", __func__, __LINE__); 251 if (NULL == p_session->omx_handle) { 252 CDBG_ERROR("%s:%d] invalid handle", __func__, __LINE__); 253 return; 254 } 255 256 rc = mm_jpeg_session_change_state(p_session, OMX_StateIdle, NULL); 257 if (rc) { 258 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 259 } 260 261 rc = mm_jpeg_session_change_state(p_session, OMX_StateLoaded, 262 mm_jpegdec_session_free_buffers); 263 if (rc) { 264 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 265 } 266 267 rc = OMX_FreeHandle(p_session->omx_handle); 268 if (0 != rc) { 269 CDBG_ERROR("%s:%d] OMX_FreeHandle failed (%d)", __func__, __LINE__, rc); 270 } 271 p_session->omx_handle = NULL; 272 273 274 pthread_mutex_destroy(&p_session->lock); 275 pthread_cond_destroy(&p_session->cond); 276 CDBG("%s:%d] X", __func__, __LINE__); 277 } 278 279 /** mm_jpeg_session_config_port: 280 * 281 * Arguments: 282 * @p_session: job session 283 * 284 * Return: 285 * OMX error values 286 * 287 * Description: 288 * Configure OMX ports 289 * 290 **/ 291 OMX_ERRORTYPE mm_jpegdec_session_config_ports(mm_jpeg_job_session_t* p_session) 292 { 293 OMX_ERRORTYPE ret = OMX_ErrorNone; 294 mm_jpeg_decode_params_t *p_params = &p_session->dec_params; 295 mm_jpeg_decode_job_t *p_jobparams = &p_session->decode_job; 296 297 mm_jpeg_buf_t *p_src_buf = 298 &p_params->src_main_buf[p_jobparams->src_index]; 299 300 p_session->inputPort.nPortIndex = 0; 301 p_session->outputPort.nPortIndex = 1; 302 303 304 ret = OMX_GetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition, 305 &p_session->inputPort); 306 if (ret) { 307 CDBG_ERROR("%s:%d] failed", __func__, __LINE__); 308 return ret; 309 } 310 311 ret = OMX_GetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition, 312 &p_session->outputPort); 313 if (ret) { 314 CDBG_ERROR("%s:%d] failed", __func__, __LINE__); 315 return ret; 316 } 317 318 p_session->inputPort.format.image.nFrameWidth = 319 p_jobparams->main_dim.src_dim.width; 320 p_session->inputPort.format.image.nFrameHeight = 321 p_jobparams->main_dim.src_dim.height; 322 p_session->inputPort.format.image.nStride = 323 p_src_buf->offset.mp[0].stride; 324 p_session->inputPort.format.image.nSliceHeight = 325 p_src_buf->offset.mp[0].scanline; 326 p_session->inputPort.format.image.eColorFormat = 327 map_jpeg_format(p_params->color_format); 328 p_session->inputPort.nBufferSize = 329 p_params->src_main_buf[p_jobparams->src_index].buf_size; 330 p_session->inputPort.nBufferCountActual = p_params->num_src_bufs; 331 ret = OMX_SetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition, 332 &p_session->inputPort); 333 if (ret) { 334 CDBG_ERROR("%s:%d] failed", __func__, __LINE__); 335 return ret; 336 } 337 338 return ret; 339 } 340 341 342 /** mm_jpegdec_session_config_main: 343 * 344 * Arguments: 345 * @p_session: job session 346 * 347 * Return: 348 * OMX error values 349 * 350 * Description: 351 * Configure main image 352 * 353 **/ 354 OMX_ERRORTYPE mm_jpegdec_session_config_main(mm_jpeg_job_session_t *p_session) 355 { 356 OMX_ERRORTYPE rc = OMX_ErrorNone; 357 OMX_IMAGE_PARAM_QFACTORTYPE q_factor; 358 mm_jpeg_decode_params_t *p_params = &p_session->dec_params; 359 mm_jpeg_decode_job_t *p_jobparams = &p_session->decode_job; 360 361 /* config port */ 362 CDBG("%s:%d] config port", __func__, __LINE__); 363 rc = mm_jpegdec_session_config_ports(p_session); 364 if (OMX_ErrorNone != rc) { 365 CDBG_ERROR("%s: config port failed", __func__); 366 return rc; 367 } 368 369 370 /* TODO: config crop */ 371 372 return rc; 373 } 374 375 /** mm_jpeg_session_configure: 376 * 377 * Arguments: 378 * @data: encode session 379 * 380 * Return: 381 * none 382 * 383 * Description: 384 * Configure the session 385 * 386 **/ 387 static OMX_ERRORTYPE mm_jpegdec_session_configure(mm_jpeg_job_session_t *p_session) 388 { 389 OMX_ERRORTYPE ret = OMX_ErrorNone; 390 mm_jpeg_decode_params_t *p_params = &p_session->dec_params; 391 mm_jpeg_decode_job_t *p_jobparams = &p_session->decode_job; 392 mm_jpeg_obj *my_obj = (mm_jpeg_obj *)p_session->jpeg_obj; 393 394 CDBG("%s:%d] E ", __func__, __LINE__); 395 396 MM_JPEG_CHK_ABORT(p_session, ret, error); 397 398 /* config main img */ 399 ret = mm_jpegdec_session_config_main(p_session); 400 if (OMX_ErrorNone != ret) { 401 CDBG_ERROR("%s:%d] config main img failed", __func__, __LINE__); 402 goto error; 403 } 404 405 /* TODO: common config (if needed) */ 406 407 ret = mm_jpeg_session_change_state(p_session, OMX_StateIdle, 408 mm_jpegdec_session_send_buffers); 409 if (ret) { 410 CDBG_ERROR("%s:%d] change state to idle failed %d", 411 __func__, __LINE__, ret); 412 goto error; 413 } 414 415 ret = mm_jpeg_session_change_state(p_session, OMX_StateExecuting, 416 NULL); 417 if (ret) { 418 CDBG_ERROR("%s:%d] change state to executing failed %d", 419 __func__, __LINE__, ret); 420 goto error; 421 } 422 423 error: 424 CDBG("%s:%d] X ret %d", __func__, __LINE__, ret); 425 return ret; 426 } 427 428 static OMX_ERRORTYPE mm_jpeg_session_port_enable( 429 mm_jpeg_job_session_t *p_session, 430 OMX_U32 nPortIndex, 431 OMX_BOOL wait) 432 { 433 OMX_ERRORTYPE ret = OMX_ErrorNone; 434 OMX_EVENTTYPE lEvent; 435 436 pthread_mutex_lock(&p_session->lock); 437 p_session->event_pending = OMX_TRUE; 438 pthread_mutex_unlock(&p_session->lock); 439 440 ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandPortEnable, 441 nPortIndex, NULL); 442 443 if (ret) { 444 CDBG_ERROR("%s:%d] failed", __func__, __LINE__); 445 return ret; 446 } 447 448 if (wait == OMX_TRUE) { 449 // Wait for cmd complete 450 pthread_mutex_lock(&p_session->lock); 451 if (p_session->event_pending == OMX_TRUE) { 452 CDBG("%s:%d] before wait", __func__, __LINE__); 453 pthread_cond_wait(&p_session->cond, &p_session->lock); 454 lEvent = p_session->omxEvent; 455 CDBG("%s:%d] after wait", __func__, __LINE__); 456 } 457 lEvent = p_session->omxEvent; 458 pthread_mutex_unlock(&p_session->lock); 459 460 if (lEvent != OMX_EventCmdComplete) { 461 CDBG("%s:%d] Unexpected event %d", __func__, __LINE__,lEvent); 462 return OMX_ErrorUndefined; 463 } 464 } 465 return OMX_ErrorNone; 466 } 467 468 static OMX_ERRORTYPE mm_jpeg_session_port_disable( 469 mm_jpeg_job_session_t *p_session, 470 OMX_U32 nPortIndex, 471 OMX_BOOL wait) 472 { 473 OMX_ERRORTYPE ret = OMX_ErrorNone; 474 OMX_EVENTTYPE lEvent; 475 476 pthread_mutex_lock(&p_session->lock); 477 p_session->event_pending = OMX_TRUE; 478 pthread_mutex_unlock(&p_session->lock); 479 480 ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandPortDisable, 481 nPortIndex, NULL); 482 483 if (ret) { 484 CDBG_ERROR("%s:%d] failed", __func__, __LINE__); 485 return ret; 486 } 487 if (wait == OMX_TRUE) { 488 // Wait for cmd complete 489 pthread_mutex_lock(&p_session->lock); 490 if (p_session->event_pending == OMX_TRUE) { 491 CDBG("%s:%d] before wait", __func__, __LINE__); 492 pthread_cond_wait(&p_session->cond, &p_session->lock); 493 494 CDBG("%s:%d] after wait", __func__, __LINE__); 495 } 496 lEvent = p_session->omxEvent; 497 pthread_mutex_unlock(&p_session->lock); 498 499 if (lEvent != OMX_EventCmdComplete) { 500 CDBG("%s:%d] Unexpected event %d", __func__, __LINE__,lEvent); 501 return OMX_ErrorUndefined; 502 } 503 } 504 return OMX_ErrorNone; 505 } 506 507 508 /** mm_jpegdec_session_decode: 509 * 510 * Arguments: 511 * @p_session: encode session 512 * 513 * Return: 514 * OMX_ERRORTYPE 515 * 516 * Description: 517 * Start the encoding 518 * 519 **/ 520 static OMX_ERRORTYPE mm_jpegdec_session_decode(mm_jpeg_job_session_t *p_session) 521 { 522 OMX_ERRORTYPE ret = OMX_ErrorNone; 523 mm_jpeg_decode_params_t *p_params = &p_session->dec_params; 524 mm_jpeg_decode_job_t *p_jobparams = &p_session->decode_job; 525 int dest_idx = 0; 526 mm_jpeg_obj *my_obj = (mm_jpeg_obj *)p_session->jpeg_obj; 527 OMX_EVENTTYPE lEvent; 528 OMX_U32 i; 529 QOMX_BUFFER_INFO lbuffer_info; 530 531 pthread_mutex_lock(&p_session->lock); 532 p_session->abort_state = MM_JPEG_ABORT_NONE; 533 p_session->encoding = OMX_FALSE; 534 pthread_mutex_unlock(&p_session->lock); 535 536 if (OMX_FALSE == p_session->config) { 537 ret = mm_jpegdec_session_configure(p_session); 538 if (ret) { 539 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 540 goto error; 541 } 542 p_session->config = OMX_TRUE; 543 } 544 545 pthread_mutex_lock(&p_session->lock); 546 p_session->encoding = OMX_TRUE; 547 pthread_mutex_unlock(&p_session->lock); 548 549 MM_JPEG_CHK_ABORT(p_session, ret, error); 550 551 p_session->event_pending = OMX_TRUE; 552 553 ret = OMX_EmptyThisBuffer(p_session->omx_handle, 554 p_session->p_in_omx_buf[p_jobparams->src_index]); 555 if (ret) { 556 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 557 goto error; 558 } 559 560 // Wait for port settings changed 561 pthread_mutex_lock(&p_session->lock); 562 if (p_session->event_pending == OMX_TRUE) { 563 CDBG("%s:%d] before wait", __func__, __LINE__); 564 pthread_cond_wait(&p_session->cond, &p_session->lock); 565 } 566 lEvent = p_session->omxEvent; 567 CDBG("%s:%d] after wait", __func__, __LINE__); 568 pthread_mutex_unlock(&p_session->lock); 569 570 if (lEvent != OMX_EventPortSettingsChanged) { 571 CDBG("%s:%d] Unexpected event %d", __func__, __LINE__,lEvent); 572 goto error; 573 } 574 575 // Disable output port (wait) 576 mm_jpeg_session_port_disable(p_session, 577 p_session->outputPort.nPortIndex, 578 OMX_TRUE); 579 580 // Get port definition 581 ret = OMX_GetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition, 582 &p_session->outputPort); 583 if (ret) { 584 CDBG_ERROR("%s:%d] failed", __func__, __LINE__); 585 return ret; 586 } 587 588 // Set port definition 589 p_session->outputPort.format.image.nFrameWidth = 590 p_jobparams->main_dim.dst_dim.width; 591 p_session->outputPort.format.image.nFrameHeight = 592 p_jobparams->main_dim.dst_dim.height; 593 p_session->outputPort.format.image.eColorFormat = 594 map_jpeg_format(p_params->color_format); 595 596 p_session->outputPort.nBufferSize = 597 p_params->dest_buf[p_jobparams->dst_index].buf_size; 598 p_session->outputPort.nBufferCountActual = p_params->num_dst_bufs; 599 600 p_session->outputPort.format.image.nSliceHeight = 601 p_params->dest_buf[p_jobparams->dst_index].offset.mp[0].scanline; 602 p_session->outputPort.format.image.nStride = 603 p_params->dest_buf[p_jobparams->dst_index].offset.mp[0].stride; 604 605 ret = OMX_SetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition, 606 &p_session->outputPort); 607 if (ret) { 608 CDBG_ERROR("%s:%d] failed", __func__, __LINE__); 609 return ret; 610 } 611 612 // Enable port (no wait) 613 mm_jpeg_session_port_enable(p_session, 614 p_session->outputPort.nPortIndex, 615 OMX_FALSE); 616 617 memset(&lbuffer_info, 0x0, sizeof(QOMX_BUFFER_INFO)); 618 // Use buffers 619 for (i = 0; i < p_params->num_dst_bufs; i++) { 620 lbuffer_info.fd = p_params->dest_buf[i].fd; 621 CDBG("%s:%d] Dest buffer %d", __func__, __LINE__, i); 622 ret = OMX_UseBuffer(p_session->omx_handle, &(p_session->p_out_omx_buf[i]), 623 1, &lbuffer_info, p_params->dest_buf[i].buf_size, 624 p_params->dest_buf[i].buf_vaddr); 625 if (ret) { 626 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 627 return ret; 628 } 629 } 630 631 // Wait for port enable completion 632 pthread_mutex_lock(&p_session->lock); 633 if (p_session->event_pending == OMX_TRUE) { 634 CDBG("%s:%d] before wait", __func__, __LINE__); 635 pthread_cond_wait(&p_session->cond, &p_session->lock); 636 lEvent = p_session->omxEvent; 637 CDBG("%s:%d] after wait", __func__, __LINE__); 638 } 639 lEvent = p_session->omxEvent; 640 pthread_mutex_unlock(&p_session->lock); 641 642 if (lEvent != OMX_EventCmdComplete) { 643 CDBG("%s:%d] Unexpected event %d", __func__, __LINE__,lEvent); 644 goto error; 645 } 646 647 ret = OMX_FillThisBuffer(p_session->omx_handle, 648 p_session->p_out_omx_buf[p_jobparams->dst_index]); 649 if (ret) { 650 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 651 goto error; 652 } 653 654 MM_JPEG_CHK_ABORT(p_session, ret, error); 655 656 error: 657 658 CDBG("%s:%d] X ", __func__, __LINE__); 659 return ret; 660 } 661 662 /** mm_jpegdec_process_decoding_job: 663 * 664 * Arguments: 665 * @my_obj: jpeg client 666 * @job_node: job node 667 * 668 * Return: 669 * 0 for success -1 otherwise 670 * 671 * Description: 672 * Start the encoding job 673 * 674 **/ 675 int32_t mm_jpegdec_process_decoding_job(mm_jpeg_obj *my_obj, mm_jpeg_job_q_node_t* job_node) 676 { 677 int32_t rc = 0; 678 OMX_ERRORTYPE ret = OMX_ErrorNone; 679 mm_jpeg_job_session_t *p_session = NULL; 680 mm_jpeg_job_q_node_t *node = NULL; 681 682 /* check if valid session */ 683 p_session = mm_jpeg_get_session(my_obj, job_node->dec_info.job_id); 684 if (NULL == p_session) { 685 CDBG_ERROR("%s:%d] invalid job id %x", __func__, __LINE__, 686 job_node->dec_info.job_id); 687 return -1; 688 } 689 690 /* sent encode cmd to OMX, queue job into ongoing queue */ 691 rc = mm_jpeg_queue_enq(&my_obj->ongoing_job_q, job_node); 692 if (rc) { 693 CDBG_ERROR("%s:%d] jpeg enqueue failed %d", 694 __func__, __LINE__, ret); 695 goto error; 696 } 697 698 p_session->decode_job = job_node->dec_info.decode_job; 699 p_session->jobId = job_node->dec_info.job_id; 700 ret = mm_jpegdec_session_decode(p_session); 701 if (ret) { 702 CDBG_ERROR("%s:%d] encode session failed", __func__, __LINE__); 703 goto error; 704 } 705 706 CDBG("%s:%d] Success X ", __func__, __LINE__); 707 return rc; 708 709 error: 710 711 if ((OMX_ErrorNone != ret) && 712 (NULL != p_session->dec_params.jpeg_cb)) { 713 p_session->job_status = JPEG_JOB_STATUS_ERROR; 714 CDBG("%s:%d] send jpeg error callback %d", __func__, __LINE__, 715 p_session->job_status); 716 p_session->dec_params.jpeg_cb(p_session->job_status, 717 p_session->client_hdl, 718 p_session->jobId, 719 NULL, 720 p_session->dec_params.userdata); 721 } 722 723 /*remove the job*/ 724 mm_jpegdec_job_done(p_session); 725 CDBG("%s:%d] Error X ", __func__, __LINE__); 726 727 return rc; 728 } 729 730 /** mm_jpeg_start_decode_job: 731 * 732 * Arguments: 733 * @my_obj: jpeg object 734 * @client_hdl: client handle 735 * @job: pointer to encode job 736 * @jobId: job id 737 * 738 * Return: 739 * 0 for success else failure 740 * 741 * Description: 742 * Start the encoding job 743 * 744 **/ 745 int32_t mm_jpegdec_start_decode_job(mm_jpeg_obj *my_obj, 746 mm_jpeg_job_t *job, 747 uint32_t *job_id) 748 { 749 int32_t rc = -1; 750 uint8_t session_idx = 0; 751 uint8_t client_idx = 0; 752 mm_jpeg_job_q_node_t* node = NULL; 753 mm_jpeg_job_session_t *p_session = NULL; 754 mm_jpeg_decode_job_t *p_jobparams = &job->decode_job; 755 756 *job_id = 0; 757 758 /* check if valid session */ 759 session_idx = GET_SESSION_IDX(p_jobparams->session_id); 760 client_idx = GET_CLIENT_IDX(p_jobparams->session_id); 761 CDBG("%s:%d] session_idx %d client idx %d", __func__, __LINE__, 762 session_idx, client_idx); 763 764 if ((session_idx >= MM_JPEG_MAX_SESSION) || 765 (client_idx >= MAX_JPEG_CLIENT_NUM)) { 766 CDBG_ERROR("%s:%d] invalid session id %x", __func__, __LINE__, 767 job->decode_job.session_id); 768 return rc; 769 } 770 771 p_session = &my_obj->clnt_mgr[client_idx].session[session_idx]; 772 if (OMX_FALSE == p_session->active) { 773 CDBG_ERROR("%s:%d] session not active %x", __func__, __LINE__, 774 job->decode_job.session_id); 775 return rc; 776 } 777 778 if ((p_jobparams->src_index >= p_session->dec_params.num_src_bufs) || 779 (p_jobparams->dst_index >= p_session->dec_params.num_dst_bufs)) { 780 CDBG_ERROR("%s:%d] invalid buffer indices", __func__, __LINE__); 781 return rc; 782 } 783 784 /* enqueue new job into todo job queue */ 785 node = (mm_jpeg_job_q_node_t *)malloc(sizeof(mm_jpeg_job_q_node_t)); 786 if (NULL == node) { 787 CDBG_ERROR("%s: No memory for mm_jpeg_job_q_node_t", __func__); 788 return -1; 789 } 790 791 *job_id = job->decode_job.session_id | 792 ((p_session->job_hist++ % JOB_HIST_MAX) << 16); 793 794 memset(node, 0, sizeof(mm_jpeg_job_q_node_t)); 795 node->dec_info.decode_job = job->decode_job; 796 node->dec_info.job_id = *job_id; 797 node->dec_info.client_handle = p_session->client_hdl; 798 node->type = MM_JPEG_CMD_TYPE_DECODE_JOB; 799 800 rc = mm_jpeg_queue_enq(&my_obj->job_mgr.job_queue, node); 801 if (0 == rc) { 802 cam_sem_post(&my_obj->job_mgr.job_sem); 803 } 804 805 return rc; 806 } 807 808 /** mm_jpegdec_create_session: 809 * 810 * Arguments: 811 * @my_obj: jpeg object 812 * @client_hdl: client handle 813 * @p_params: pointer to encode params 814 * @p_session_id: session id 815 * 816 * Return: 817 * 0 for success else failure 818 * 819 * Description: 820 * Start the encoding session 821 * 822 **/ 823 int32_t mm_jpegdec_create_session(mm_jpeg_obj *my_obj, 824 uint32_t client_hdl, 825 mm_jpeg_decode_params_t *p_params, 826 uint32_t* p_session_id) 827 { 828 int32_t rc = 0; 829 OMX_ERRORTYPE ret = OMX_ErrorNone; 830 uint8_t clnt_idx = 0; 831 int session_idx = -1; 832 mm_jpeg_job_session_t *p_session = NULL; 833 *p_session_id = 0; 834 835 /* validate the parameters */ 836 if ((p_params->num_src_bufs > MM_JPEG_MAX_BUF) 837 || (p_params->num_dst_bufs > MM_JPEG_MAX_BUF)) { 838 CDBG_ERROR("%s:%d] invalid num buffers", __func__, __LINE__); 839 return rc; 840 } 841 842 /* check if valid client */ 843 clnt_idx = mm_jpeg_util_get_index_by_handler(client_hdl); 844 if (clnt_idx >= MAX_JPEG_CLIENT_NUM) { 845 CDBG_ERROR("%s: invalid client with handler (%d)", __func__, client_hdl); 846 return rc; 847 } 848 849 session_idx = mm_jpeg_get_new_session_idx(my_obj, clnt_idx, &p_session); 850 if (session_idx < 0) { 851 CDBG_ERROR("%s:%d] invalid session id (%d)", __func__, __LINE__, session_idx); 852 return rc; 853 } 854 855 ret = mm_jpegdec_session_create(p_session); 856 if (OMX_ErrorNone != ret) { 857 p_session->active = OMX_FALSE; 858 CDBG_ERROR("%s:%d] jpeg session create failed", __func__, __LINE__); 859 return rc; 860 } 861 862 *p_session_id = (JOB_ID_MAGICVAL << 24) | (session_idx << 8) | clnt_idx; 863 864 /*copy the params*/ 865 p_session->dec_params = *p_params; 866 p_session->client_hdl = client_hdl; 867 p_session->sessionId = *p_session_id; 868 p_session->jpeg_obj = (void*)my_obj; /* save a ptr to jpeg_obj */ 869 CDBG("%s:%d] session id %x", __func__, __LINE__, *p_session_id); 870 871 return rc; 872 } 873 874 /** mm_jpegdec_destroy_session: 875 * 876 * Arguments: 877 * @my_obj: jpeg object 878 * @session_id: session index 879 * 880 * Return: 881 * 0 for success else failure 882 * 883 * Description: 884 * Destroy the encoding session 885 * 886 **/ 887 int32_t mm_jpegdec_destroy_session(mm_jpeg_obj *my_obj, 888 mm_jpeg_job_session_t *p_session) 889 { 890 int32_t rc = 0; 891 uint8_t clnt_idx = 0; 892 mm_jpeg_job_q_node_t *node = NULL; 893 OMX_BOOL ret = OMX_FALSE; 894 895 if (NULL == p_session) { 896 CDBG_ERROR("%s:%d] invalid session", __func__, __LINE__); 897 return rc; 898 } 899 uint32_t session_id = p_session->sessionId; 900 pthread_mutex_lock(&my_obj->job_lock); 901 902 /* abort job if in todo queue */ 903 CDBG("%s:%d] abort todo jobs", __func__, __LINE__); 904 node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id); 905 while (NULL != node) { 906 free(node); 907 node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id); 908 } 909 910 /* abort job if in ongoing queue */ 911 CDBG("%s:%d] abort ongoing jobs", __func__, __LINE__); 912 node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id); 913 while (NULL != node) { 914 free(node); 915 node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id); 916 } 917 918 /* abort the current session */ 919 mm_jpeg_session_abort(p_session); 920 mm_jpegdec_session_destroy(p_session); 921 mm_jpeg_remove_session_idx(my_obj, session_id); 922 pthread_mutex_unlock(&my_obj->job_lock); 923 924 /* wake up jobMgr thread to work on new job if there is any */ 925 cam_sem_post(&my_obj->job_mgr.job_sem); 926 CDBG("%s:%d] X", __func__, __LINE__); 927 928 return rc; 929 } 930 931 /** mm_jpegdec_destroy_session_by_id: 932 * 933 * Arguments: 934 * @my_obj: jpeg object 935 * @session_id: session index 936 * 937 * Return: 938 * 0 for success else failure 939 * 940 * Description: 941 * Destroy the encoding session 942 * 943 **/ 944 int32_t mm_jpegdec_destroy_session_by_id(mm_jpeg_obj *my_obj, uint32_t session_id) 945 { 946 int32_t rc = 0; 947 mm_jpeg_job_session_t *p_session = mm_jpeg_get_session(my_obj, session_id); 948 949 if (NULL == p_session) { 950 CDBG_ERROR("%s:%d] session is not valid", __func__, __LINE__); 951 return rc; 952 } 953 954 return mm_jpegdec_destroy_session(my_obj, p_session); 955 } 956 957 958 959 OMX_ERRORTYPE mm_jpegdec_ebd(OMX_HANDLETYPE hComponent, 960 OMX_PTR pAppData, 961 OMX_BUFFERHEADERTYPE *pBuffer) 962 { 963 OMX_ERRORTYPE ret = OMX_ErrorNone; 964 mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData; 965 966 CDBG("%s:%d] count %d ", __func__, __LINE__, p_session->ebd_count); 967 pthread_mutex_lock(&p_session->lock); 968 p_session->ebd_count++; 969 pthread_mutex_unlock(&p_session->lock); 970 return 0; 971 } 972 973 OMX_ERRORTYPE mm_jpegdec_fbd(OMX_HANDLETYPE hComponent, 974 OMX_PTR pAppData, 975 OMX_BUFFERHEADERTYPE *pBuffer) 976 { 977 OMX_ERRORTYPE ret = OMX_ErrorNone; 978 mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData; 979 uint32_t i = 0; 980 int rc = 0; 981 mm_jpeg_output_t output_buf; 982 983 CDBG("%s:%d] count %d ", __func__, __LINE__, p_session->fbd_count); 984 985 pthread_mutex_lock(&p_session->lock); 986 987 if (MM_JPEG_ABORT_NONE != p_session->abort_state) { 988 pthread_mutex_unlock(&p_session->lock); 989 return ret; 990 } 991 992 p_session->fbd_count++; 993 if (NULL != p_session->dec_params.jpeg_cb) { 994 p_session->job_status = JPEG_JOB_STATUS_DONE; 995 output_buf.buf_filled_len = (uint32_t)pBuffer->nFilledLen; 996 output_buf.buf_vaddr = pBuffer->pBuffer; 997 output_buf.fd = 0; 998 CDBG("%s:%d] send jpeg callback %d", __func__, __LINE__, 999 p_session->job_status); 1000 p_session->dec_params.jpeg_cb(p_session->job_status, 1001 p_session->client_hdl, 1002 p_session->jobId, 1003 &output_buf, 1004 p_session->dec_params.userdata); 1005 1006 /* remove from ready queue */ 1007 mm_jpegdec_job_done(p_session); 1008 } 1009 pthread_mutex_unlock(&p_session->lock); 1010 CDBG("%s:%d] ", __func__, __LINE__); 1011 1012 return ret; 1013 } 1014 1015 OMX_ERRORTYPE mm_jpegdec_event_handler(OMX_HANDLETYPE hComponent, 1016 OMX_PTR pAppData, 1017 OMX_EVENTTYPE eEvent, 1018 OMX_U32 nData1, 1019 OMX_U32 nData2, 1020 OMX_PTR pEventData) 1021 { 1022 mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData; 1023 1024 CDBG("%s:%d] %d %d %d state %d", __func__, __LINE__, eEvent, (int)nData1, 1025 (int)nData2, p_session->abort_state); 1026 1027 CDBG("%s:%d] AppData=%p ", __func__, __LINE__, pAppData); 1028 1029 pthread_mutex_lock(&p_session->lock); 1030 p_session->omxEvent = eEvent; 1031 if (MM_JPEG_ABORT_INIT == p_session->abort_state) { 1032 p_session->abort_state = MM_JPEG_ABORT_DONE; 1033 pthread_cond_signal(&p_session->cond); 1034 pthread_mutex_unlock(&p_session->lock); 1035 return OMX_ErrorNone; 1036 } 1037 1038 if (eEvent == OMX_EventError) { 1039 if (p_session->encoding == OMX_TRUE) { 1040 CDBG("%s:%d] Error during encoding", __func__, __LINE__); 1041 1042 /* send jpeg callback */ 1043 if (NULL != p_session->dec_params.jpeg_cb) { 1044 p_session->job_status = JPEG_JOB_STATUS_ERROR; 1045 CDBG("%s:%d] send jpeg error callback %d", __func__, __LINE__, 1046 p_session->job_status); 1047 p_session->dec_params.jpeg_cb(p_session->job_status, 1048 p_session->client_hdl, 1049 p_session->jobId, 1050 NULL, 1051 p_session->dec_params.userdata); 1052 } 1053 1054 /* remove from ready queue */ 1055 mm_jpegdec_job_done(p_session); 1056 } 1057 pthread_cond_signal(&p_session->cond); 1058 } else if (eEvent == OMX_EventCmdComplete) { 1059 p_session->state_change_pending = OMX_FALSE; 1060 p_session->event_pending = OMX_FALSE; 1061 pthread_cond_signal(&p_session->cond); 1062 } else if (eEvent == OMX_EventPortSettingsChanged) { 1063 p_session->event_pending = OMX_FALSE; 1064 pthread_cond_signal(&p_session->cond); 1065 } 1066 1067 pthread_mutex_unlock(&p_session->lock); 1068 CDBG("%s:%d]", __func__, __LINE__); 1069 return OMX_ErrorNone; 1070 } 1071 1072 /** mm_jpegdec_abort_job: 1073 * 1074 * Arguments: 1075 * @my_obj: jpeg object 1076 * @client_hdl: client handle 1077 * @jobId: job id 1078 * 1079 * Return: 1080 * 0 for success else failure 1081 * 1082 * Description: 1083 * Abort the encoding session 1084 * 1085 **/ 1086 int32_t mm_jpegdec_abort_job(mm_jpeg_obj *my_obj, 1087 uint32_t jobId) 1088 { 1089 int32_t rc = -1; 1090 uint8_t clnt_idx = 0; 1091 mm_jpeg_job_q_node_t *node = NULL; 1092 OMX_BOOL ret = OMX_FALSE; 1093 mm_jpeg_job_session_t *p_session = NULL; 1094 1095 CDBG("%s:%d] ", __func__, __LINE__); 1096 pthread_mutex_lock(&my_obj->job_lock); 1097 1098 /* abort job if in todo queue */ 1099 node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->job_mgr.job_queue, jobId); 1100 if (NULL != node) { 1101 free(node); 1102 goto abort_done; 1103 } 1104 1105 /* abort job if in ongoing queue */ 1106 node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->ongoing_job_q, jobId); 1107 if (NULL != node) { 1108 /* find job that is OMX ongoing, ask OMX to abort the job */ 1109 p_session = mm_jpeg_get_session(my_obj, node->dec_info.job_id); 1110 if (p_session) { 1111 mm_jpeg_session_abort(p_session); 1112 } else { 1113 CDBG_ERROR("%s:%d] Invalid job id 0x%x", __func__, __LINE__, 1114 node->dec_info.job_id); 1115 } 1116 free(node); 1117 goto abort_done; 1118 } 1119 1120 abort_done: 1121 pthread_mutex_unlock(&my_obj->job_lock); 1122 1123 return rc; 1124 } 1125 /** mm_jpegdec_init: 1126 * 1127 * Arguments: 1128 * @my_obj: jpeg object 1129 * 1130 * Return: 1131 * 0 for success else failure 1132 * 1133 * Description: 1134 * Initializes the jpeg client 1135 * 1136 **/ 1137 int32_t mm_jpegdec_init(mm_jpeg_obj *my_obj) 1138 { 1139 int32_t rc = 0; 1140 1141 /* init locks */ 1142 pthread_mutex_init(&my_obj->job_lock, NULL); 1143 1144 /* init ongoing job queue */ 1145 rc = mm_jpeg_queue_init(&my_obj->ongoing_job_q); 1146 if (0 != rc) { 1147 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 1148 return -1; 1149 } 1150 1151 /* init job semaphore and launch jobmgr thread */ 1152 CDBG("%s:%d] Launch jobmgr thread rc %d", __func__, __LINE__, rc); 1153 rc = mm_jpeg_jobmgr_thread_launch(my_obj); 1154 if (0 != rc) { 1155 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 1156 return -1; 1157 } 1158 1159 /* load OMX */ 1160 if (OMX_ErrorNone != OMX_Init()) { 1161 /* roll back in error case */ 1162 CDBG_ERROR("%s:%d] OMX_Init failed (%d)", __func__, __LINE__, rc); 1163 mm_jpeg_jobmgr_thread_release(my_obj); 1164 mm_jpeg_queue_deinit(&my_obj->ongoing_job_q); 1165 pthread_mutex_destroy(&my_obj->job_lock); 1166 } 1167 1168 return rc; 1169 } 1170 1171 /** mm_jpegdec_deinit: 1172 * 1173 * Arguments: 1174 * @my_obj: jpeg object 1175 * 1176 * Return: 1177 * 0 for success else failure 1178 * 1179 * Description: 1180 * Deinits the jpeg client 1181 * 1182 **/ 1183 int32_t mm_jpegdec_deinit(mm_jpeg_obj *my_obj) 1184 { 1185 int32_t rc = 0; 1186 1187 /* release jobmgr thread */ 1188 rc = mm_jpeg_jobmgr_thread_release(my_obj); 1189 if (0 != rc) { 1190 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 1191 } 1192 1193 /* unload OMX engine */ 1194 OMX_Deinit(); 1195 1196 /* deinit ongoing job and cb queue */ 1197 rc = mm_jpeg_queue_deinit(&my_obj->ongoing_job_q); 1198 if (0 != rc) { 1199 CDBG_ERROR("%s:%d] Error", __func__, __LINE__); 1200 } 1201 1202 /* destroy locks */ 1203 pthread_mutex_destroy(&my_obj->job_lock); 1204 1205 return rc; 1206 } 1207