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