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