| /* Copyright (c) 2013-2014, 2016, The Linux Foundation. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following |
| * disclaimer in the documentation and/or other materials provided |
| * with the distribution. |
| * * Neither the name of The Linux Foundation nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
| * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
| * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
| * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| */ |
| |
| // System dependencies |
| #include <pthread.h> |
| |
| // JPEG dependencies |
| #include "mm_jpeg_dbg.h" |
| #include "mm_jpeg_interface.h" |
| #include "mm_jpeg.h" |
| #include "mm_jpeg_inlines.h" |
| |
| OMX_ERRORTYPE mm_jpegdec_ebd(OMX_HANDLETYPE hComponent, |
| OMX_PTR pAppData, |
| OMX_BUFFERHEADERTYPE *pBuffer); |
| OMX_ERRORTYPE mm_jpegdec_fbd(OMX_HANDLETYPE hComponent, |
| OMX_PTR pAppData, |
| OMX_BUFFERHEADERTYPE* pBuffer); |
| OMX_ERRORTYPE mm_jpegdec_event_handler(OMX_HANDLETYPE hComponent, |
| OMX_PTR pAppData, |
| OMX_EVENTTYPE eEvent, |
| OMX_U32 nData1, |
| OMX_U32 nData2, |
| OMX_PTR pEventData); |
| |
| |
| /** mm_jpegdec_destroy_job |
| * |
| * Arguments: |
| * @p_session: Session obj |
| * |
| * Return: |
| * 0 for success else failure |
| * |
| * Description: |
| * Destroy the job based paramenters |
| * |
| **/ |
| static int32_t mm_jpegdec_destroy_job(mm_jpeg_job_session_t *p_session) |
| { |
| int32_t rc = 0; |
| |
| return rc; |
| } |
| |
| /** mm_jpeg_job_done: |
| * |
| * Arguments: |
| * @p_session: decode session |
| * |
| * Return: |
| * OMX_ERRORTYPE |
| * |
| * Description: |
| * Finalize the job |
| * |
| **/ |
| static void mm_jpegdec_job_done(mm_jpeg_job_session_t *p_session) |
| { |
| mm_jpeg_obj *my_obj = (mm_jpeg_obj *)p_session->jpeg_obj; |
| mm_jpeg_job_q_node_t *node = NULL; |
| |
| /*Destroy job related params*/ |
| mm_jpegdec_destroy_job(p_session); |
| |
| /*remove the job*/ |
| node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->ongoing_job_q, |
| p_session->jobId); |
| if (node) { |
| free(node); |
| } |
| p_session->encoding = OMX_FALSE; |
| |
| /* wake up jobMgr thread to work on new job if there is any */ |
| cam_sem_post(&my_obj->job_mgr.job_sem); |
| } |
| |
| |
| /** mm_jpegdec_session_send_buffers: |
| * |
| * Arguments: |
| * @data: job session |
| * |
| * Return: |
| * OMX error values |
| * |
| * Description: |
| * Send the buffers to OMX layer |
| * |
| **/ |
| OMX_ERRORTYPE mm_jpegdec_session_send_buffers(void *data) |
| { |
| uint32_t i = 0; |
| mm_jpeg_job_session_t* p_session = (mm_jpeg_job_session_t *)data; |
| OMX_ERRORTYPE ret = OMX_ErrorNone; |
| QOMX_BUFFER_INFO lbuffer_info; |
| mm_jpeg_decode_params_t *p_params = &p_session->dec_params; |
| |
| memset(&lbuffer_info, 0x0, sizeof(QOMX_BUFFER_INFO)); |
| for (i = 0; i < p_params->num_src_bufs; i++) { |
| LOGD("Source buffer %d", i); |
| lbuffer_info.fd = (OMX_U32)p_params->src_main_buf[i].fd; |
| ret = OMX_UseBuffer(p_session->omx_handle, &(p_session->p_in_omx_buf[i]), 0, |
| &lbuffer_info, p_params->src_main_buf[i].buf_size, |
| p_params->src_main_buf[i].buf_vaddr); |
| if (ret) { |
| LOGE("Error %d", ret); |
| return ret; |
| } |
| } |
| |
| LOGD("Exit"); |
| return ret; |
| } |
| |
| /** mm_jpeg_session_free_buffers: |
| * |
| * Arguments: |
| * @data: job session |
| * |
| * Return: |
| * OMX error values |
| * |
| * Description: |
| * Free the buffers from OMX layer |
| * |
| **/ |
| OMX_ERRORTYPE mm_jpegdec_session_free_buffers(void *data) |
| { |
| OMX_ERRORTYPE ret = OMX_ErrorNone; |
| uint32_t i = 0; |
| mm_jpeg_job_session_t* p_session = (mm_jpeg_job_session_t *)data; |
| mm_jpeg_decode_params_t *p_params = &p_session->dec_params; |
| |
| for (i = 0; i < p_params->num_src_bufs; i++) { |
| LOGD("Source buffer %d", i); |
| ret = OMX_FreeBuffer(p_session->omx_handle, 0, p_session->p_in_omx_buf[i]); |
| if (ret) { |
| LOGE("Error %d", ret); |
| return ret; |
| } |
| } |
| |
| for (i = 0; i < p_params->num_dst_bufs; i++) { |
| LOGD("Dest buffer %d", i); |
| ret = OMX_FreeBuffer(p_session->omx_handle, 1, p_session->p_out_omx_buf[i]); |
| if (ret) { |
| LOGE("Error"); |
| return ret; |
| } |
| } |
| LOGD("Exit"); |
| return ret; |
| } |
| |
| /** mm_jpegdec_session_create: |
| * |
| * Arguments: |
| * @p_session: job session |
| * |
| * Return: |
| * OMX error types |
| * |
| * Description: |
| * Create a jpeg encode session |
| * |
| **/ |
| OMX_ERRORTYPE mm_jpegdec_session_create(mm_jpeg_job_session_t* p_session) |
| { |
| OMX_ERRORTYPE rc = OMX_ErrorNone; |
| |
| pthread_mutex_init(&p_session->lock, NULL); |
| pthread_cond_init(&p_session->cond, NULL); |
| cirq_reset(&p_session->cb_q); |
| p_session->state_change_pending = OMX_FALSE; |
| p_session->abort_state = MM_JPEG_ABORT_NONE; |
| p_session->error_flag = OMX_ErrorNone; |
| p_session->ebd_count = 0; |
| p_session->fbd_count = 0; |
| p_session->encode_pid = -1; |
| p_session->config = OMX_FALSE; |
| |
| p_session->omx_callbacks.EmptyBufferDone = mm_jpegdec_ebd; |
| p_session->omx_callbacks.FillBufferDone = mm_jpegdec_fbd; |
| p_session->omx_callbacks.EventHandler = mm_jpegdec_event_handler; |
| p_session->exif_count_local = 0; |
| |
| rc = OMX_GetHandle(&p_session->omx_handle, |
| "OMX.qcom.image.jpeg.decoder", |
| (void *)p_session, |
| &p_session->omx_callbacks); |
| |
| if (OMX_ErrorNone != rc) { |
| LOGE("OMX_GetHandle failed (%d)", rc); |
| return rc; |
| } |
| return rc; |
| } |
| |
| /** mm_jpegdec_session_destroy: |
| * |
| * Arguments: |
| * @p_session: job session |
| * |
| * Return: |
| * none |
| * |
| * Description: |
| * Destroy a jpeg encode session |
| * |
| **/ |
| void mm_jpegdec_session_destroy(mm_jpeg_job_session_t* p_session) |
| { |
| OMX_ERRORTYPE rc = OMX_ErrorNone; |
| |
| LOGD("E"); |
| if (NULL == p_session->omx_handle) { |
| LOGE("invalid handle"); |
| return; |
| } |
| |
| rc = mm_jpeg_session_change_state(p_session, OMX_StateIdle, NULL); |
| if (rc) { |
| LOGE("Error"); |
| } |
| |
| rc = mm_jpeg_session_change_state(p_session, OMX_StateLoaded, |
| mm_jpegdec_session_free_buffers); |
| if (rc) { |
| LOGE("Error"); |
| } |
| |
| rc = OMX_FreeHandle(p_session->omx_handle); |
| if (0 != rc) { |
| LOGE("OMX_FreeHandle failed (%d)", rc); |
| } |
| p_session->omx_handle = NULL; |
| |
| |
| pthread_mutex_destroy(&p_session->lock); |
| pthread_cond_destroy(&p_session->cond); |
| LOGD("X"); |
| } |
| |
| /** mm_jpeg_session_config_port: |
| * |
| * Arguments: |
| * @p_session: job session |
| * |
| * Return: |
| * OMX error values |
| * |
| * Description: |
| * Configure OMX ports |
| * |
| **/ |
| OMX_ERRORTYPE mm_jpegdec_session_config_ports(mm_jpeg_job_session_t* p_session) |
| { |
| OMX_ERRORTYPE ret = OMX_ErrorNone; |
| mm_jpeg_decode_params_t *p_params = &p_session->dec_params; |
| mm_jpeg_decode_job_t *p_jobparams = &p_session->decode_job; |
| |
| mm_jpeg_buf_t *p_src_buf = |
| &p_params->src_main_buf[p_jobparams->src_index]; |
| |
| p_session->inputPort.nPortIndex = 0; |
| p_session->outputPort.nPortIndex = 1; |
| |
| |
| ret = OMX_GetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition, |
| &p_session->inputPort); |
| if (ret) { |
| LOGE("failed"); |
| return ret; |
| } |
| |
| ret = OMX_GetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition, |
| &p_session->outputPort); |
| if (ret) { |
| LOGE("failed"); |
| return ret; |
| } |
| |
| p_session->inputPort.format.image.nFrameWidth = |
| (OMX_U32)p_jobparams->main_dim.src_dim.width; |
| p_session->inputPort.format.image.nFrameHeight = |
| (OMX_U32)p_jobparams->main_dim.src_dim.height; |
| p_session->inputPort.format.image.nStride = |
| p_src_buf->offset.mp[0].stride; |
| p_session->inputPort.format.image.nSliceHeight = |
| (OMX_U32)p_src_buf->offset.mp[0].scanline; |
| p_session->inputPort.format.image.eColorFormat = |
| map_jpeg_format(p_params->color_format); |
| p_session->inputPort.nBufferSize = |
| p_params->src_main_buf[p_jobparams->src_index].buf_size; |
| p_session->inputPort.nBufferCountActual = (OMX_U32)p_params->num_src_bufs; |
| ret = OMX_SetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition, |
| &p_session->inputPort); |
| if (ret) { |
| LOGE("failed"); |
| return ret; |
| } |
| |
| return ret; |
| } |
| |
| |
| /** mm_jpegdec_session_config_main: |
| * |
| * Arguments: |
| * @p_session: job session |
| * |
| * Return: |
| * OMX error values |
| * |
| * Description: |
| * Configure main image |
| * |
| **/ |
| OMX_ERRORTYPE mm_jpegdec_session_config_main(mm_jpeg_job_session_t *p_session) |
| { |
| OMX_ERRORTYPE rc = OMX_ErrorNone; |
| |
| /* config port */ |
| LOGD("config port"); |
| rc = mm_jpegdec_session_config_ports(p_session); |
| if (OMX_ErrorNone != rc) { |
| LOGE("config port failed"); |
| return rc; |
| } |
| |
| |
| /* TODO: config crop */ |
| |
| return rc; |
| } |
| |
| /** mm_jpeg_session_configure: |
| * |
| * Arguments: |
| * @data: encode session |
| * |
| * Return: |
| * none |
| * |
| * Description: |
| * Configure the session |
| * |
| **/ |
| static OMX_ERRORTYPE mm_jpegdec_session_configure(mm_jpeg_job_session_t *p_session) |
| { |
| OMX_ERRORTYPE ret = OMX_ErrorNone; |
| |
| LOGD("E "); |
| |
| MM_JPEG_CHK_ABORT(p_session, ret, error); |
| |
| /* config main img */ |
| ret = mm_jpegdec_session_config_main(p_session); |
| if (OMX_ErrorNone != ret) { |
| LOGE("config main img failed"); |
| goto error; |
| } |
| |
| /* TODO: common config (if needed) */ |
| |
| ret = mm_jpeg_session_change_state(p_session, OMX_StateIdle, |
| mm_jpegdec_session_send_buffers); |
| if (ret) { |
| LOGE("change state to idle failed %d", ret); |
| goto error; |
| } |
| |
| ret = mm_jpeg_session_change_state(p_session, OMX_StateExecuting, |
| NULL); |
| if (ret) { |
| LOGE("change state to executing failed %d", ret); |
| goto error; |
| } |
| |
| error: |
| LOGD("X ret %d", ret); |
| return ret; |
| } |
| |
| static OMX_ERRORTYPE mm_jpeg_session_port_enable( |
| mm_jpeg_job_session_t *p_session, |
| OMX_U32 nPortIndex, |
| OMX_BOOL wait) |
| { |
| OMX_ERRORTYPE ret = OMX_ErrorNone; |
| OMX_EVENTTYPE lEvent; |
| |
| pthread_mutex_lock(&p_session->lock); |
| p_session->event_pending = OMX_TRUE; |
| pthread_mutex_unlock(&p_session->lock); |
| |
| ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandPortEnable, |
| nPortIndex, NULL); |
| |
| if (ret) { |
| LOGE("failed"); |
| return ret; |
| } |
| |
| if (wait == OMX_TRUE) { |
| // Wait for cmd complete |
| pthread_mutex_lock(&p_session->lock); |
| if (p_session->event_pending == OMX_TRUE) { |
| LOGD("before wait"); |
| pthread_cond_wait(&p_session->cond, &p_session->lock); |
| lEvent = p_session->omxEvent; |
| LOGD("after wait"); |
| } |
| lEvent = p_session->omxEvent; |
| pthread_mutex_unlock(&p_session->lock); |
| |
| if (lEvent != OMX_EventCmdComplete) { |
| LOGD("Unexpected event %d",lEvent); |
| return OMX_ErrorUndefined; |
| } |
| } |
| return OMX_ErrorNone; |
| } |
| |
| static OMX_ERRORTYPE mm_jpeg_session_port_disable( |
| mm_jpeg_job_session_t *p_session, |
| OMX_U32 nPortIndex, |
| OMX_BOOL wait) |
| { |
| OMX_ERRORTYPE ret = OMX_ErrorNone; |
| OMX_EVENTTYPE lEvent; |
| |
| pthread_mutex_lock(&p_session->lock); |
| p_session->event_pending = OMX_TRUE; |
| pthread_mutex_unlock(&p_session->lock); |
| |
| ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandPortDisable, |
| nPortIndex, NULL); |
| |
| if (ret) { |
| LOGE("failed"); |
| return ret; |
| } |
| if (wait == OMX_TRUE) { |
| // Wait for cmd complete |
| pthread_mutex_lock(&p_session->lock); |
| if (p_session->event_pending == OMX_TRUE) { |
| LOGD("before wait"); |
| pthread_cond_wait(&p_session->cond, &p_session->lock); |
| |
| LOGD("after wait"); |
| } |
| lEvent = p_session->omxEvent; |
| pthread_mutex_unlock(&p_session->lock); |
| |
| if (lEvent != OMX_EventCmdComplete) { |
| LOGD("Unexpected event %d",lEvent); |
| return OMX_ErrorUndefined; |
| } |
| } |
| return OMX_ErrorNone; |
| } |
| |
| |
| /** mm_jpegdec_session_decode: |
| * |
| * Arguments: |
| * @p_session: encode session |
| * |
| * Return: |
| * OMX_ERRORTYPE |
| * |
| * Description: |
| * Start the encoding |
| * |
| **/ |
| static OMX_ERRORTYPE mm_jpegdec_session_decode(mm_jpeg_job_session_t *p_session) |
| { |
| OMX_ERRORTYPE ret = OMX_ErrorNone; |
| mm_jpeg_decode_params_t *p_params = &p_session->dec_params; |
| mm_jpeg_decode_job_t *p_jobparams = &p_session->decode_job; |
| OMX_EVENTTYPE lEvent; |
| uint32_t i; |
| QOMX_BUFFER_INFO lbuffer_info; |
| |
| pthread_mutex_lock(&p_session->lock); |
| p_session->abort_state = MM_JPEG_ABORT_NONE; |
| p_session->encoding = OMX_FALSE; |
| pthread_mutex_unlock(&p_session->lock); |
| |
| if (OMX_FALSE == p_session->config) { |
| ret = mm_jpegdec_session_configure(p_session); |
| if (ret) { |
| LOGE("Error"); |
| goto error; |
| } |
| p_session->config = OMX_TRUE; |
| } |
| |
| pthread_mutex_lock(&p_session->lock); |
| p_session->encoding = OMX_TRUE; |
| pthread_mutex_unlock(&p_session->lock); |
| |
| MM_JPEG_CHK_ABORT(p_session, ret, error); |
| |
| p_session->event_pending = OMX_TRUE; |
| |
| ret = OMX_EmptyThisBuffer(p_session->omx_handle, |
| p_session->p_in_omx_buf[p_jobparams->src_index]); |
| if (ret) { |
| LOGE("Error"); |
| goto error; |
| } |
| |
| // Wait for port settings changed |
| pthread_mutex_lock(&p_session->lock); |
| if (p_session->event_pending == OMX_TRUE) { |
| LOGD("before wait"); |
| pthread_cond_wait(&p_session->cond, &p_session->lock); |
| } |
| lEvent = p_session->omxEvent; |
| LOGD("after wait"); |
| pthread_mutex_unlock(&p_session->lock); |
| |
| if (lEvent != OMX_EventPortSettingsChanged) { |
| LOGD("Unexpected event %d",lEvent); |
| goto error; |
| } |
| |
| // Disable output port (wait) |
| mm_jpeg_session_port_disable(p_session, |
| p_session->outputPort.nPortIndex, |
| OMX_TRUE); |
| |
| // Get port definition |
| ret = OMX_GetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition, |
| &p_session->outputPort); |
| if (ret) { |
| LOGE("failed"); |
| return ret; |
| } |
| |
| // Set port definition |
| p_session->outputPort.format.image.nFrameWidth = |
| (OMX_U32)p_jobparams->main_dim.dst_dim.width; |
| p_session->outputPort.format.image.nFrameHeight = |
| (OMX_U32)p_jobparams->main_dim.dst_dim.height; |
| p_session->outputPort.format.image.eColorFormat = |
| map_jpeg_format(p_params->color_format); |
| |
| p_session->outputPort.nBufferSize = |
| p_params->dest_buf[p_jobparams->dst_index].buf_size; |
| p_session->outputPort.nBufferCountActual = (OMX_U32)p_params->num_dst_bufs; |
| |
| p_session->outputPort.format.image.nSliceHeight = |
| (OMX_U32) |
| p_params->dest_buf[p_jobparams->dst_index].offset.mp[0].scanline; |
| p_session->outputPort.format.image.nStride = |
| p_params->dest_buf[p_jobparams->dst_index].offset.mp[0].stride; |
| |
| ret = OMX_SetParameter(p_session->omx_handle, OMX_IndexParamPortDefinition, |
| &p_session->outputPort); |
| if (ret) { |
| LOGE("failed"); |
| return ret; |
| } |
| |
| // Enable port (no wait) |
| mm_jpeg_session_port_enable(p_session, |
| p_session->outputPort.nPortIndex, |
| OMX_FALSE); |
| |
| memset(&lbuffer_info, 0x0, sizeof(QOMX_BUFFER_INFO)); |
| // Use buffers |
| for (i = 0; i < p_params->num_dst_bufs; i++) { |
| lbuffer_info.fd = (OMX_U32)p_params->dest_buf[i].fd; |
| LOGD("Dest buffer %d", (unsigned int)i); |
| ret = OMX_UseBuffer(p_session->omx_handle, &(p_session->p_out_omx_buf[i]), |
| 1, &lbuffer_info, p_params->dest_buf[i].buf_size, |
| p_params->dest_buf[i].buf_vaddr); |
| if (ret) { |
| LOGE("Error"); |
| return ret; |
| } |
| } |
| |
| // Wait for port enable completion |
| pthread_mutex_lock(&p_session->lock); |
| if (p_session->event_pending == OMX_TRUE) { |
| LOGD("before wait"); |
| pthread_cond_wait(&p_session->cond, &p_session->lock); |
| lEvent = p_session->omxEvent; |
| LOGD("after wait"); |
| } |
| lEvent = p_session->omxEvent; |
| pthread_mutex_unlock(&p_session->lock); |
| |
| if (lEvent != OMX_EventCmdComplete) { |
| LOGD("Unexpected event %d",lEvent); |
| goto error; |
| } |
| |
| ret = OMX_FillThisBuffer(p_session->omx_handle, |
| p_session->p_out_omx_buf[p_jobparams->dst_index]); |
| if (ret) { |
| LOGE("Error"); |
| goto error; |
| } |
| |
| MM_JPEG_CHK_ABORT(p_session, ret, error); |
| |
| error: |
| |
| LOGD("X "); |
| return ret; |
| } |
| |
| /** mm_jpegdec_process_decoding_job: |
| * |
| * Arguments: |
| * @my_obj: jpeg client |
| * @job_node: job node |
| * |
| * Return: |
| * 0 for success -1 otherwise |
| * |
| * Description: |
| * Start the encoding job |
| * |
| **/ |
| int32_t mm_jpegdec_process_decoding_job(mm_jpeg_obj *my_obj, mm_jpeg_job_q_node_t* job_node) |
| { |
| mm_jpeg_q_data_t qdata; |
| int32_t rc = 0; |
| OMX_ERRORTYPE ret = OMX_ErrorNone; |
| mm_jpeg_job_session_t *p_session = NULL; |
| |
| /* check if valid session */ |
| p_session = mm_jpeg_get_session(my_obj, job_node->dec_info.job_id); |
| if (NULL == p_session) { |
| LOGE("invalid job id %x", |
| job_node->dec_info.job_id); |
| return -1; |
| } |
| |
| /* sent encode cmd to OMX, queue job into ongoing queue */ |
| qdata.p = job_node; |
| rc = mm_jpeg_queue_enq(&my_obj->ongoing_job_q, qdata); |
| if (rc) { |
| LOGE("jpeg enqueue failed %d", ret); |
| goto error; |
| } |
| |
| p_session->decode_job = job_node->dec_info.decode_job; |
| p_session->jobId = job_node->dec_info.job_id; |
| ret = mm_jpegdec_session_decode(p_session); |
| if (ret) { |
| LOGE("encode session failed"); |
| goto error; |
| } |
| |
| LOGD("Success X "); |
| return rc; |
| |
| error: |
| |
| if ((OMX_ErrorNone != ret) && |
| (NULL != p_session->dec_params.jpeg_cb)) { |
| p_session->job_status = JPEG_JOB_STATUS_ERROR; |
| LOGD("send jpeg error callback %d", |
| p_session->job_status); |
| p_session->dec_params.jpeg_cb(p_session->job_status, |
| p_session->client_hdl, |
| p_session->jobId, |
| NULL, |
| p_session->dec_params.userdata); |
| } |
| |
| /*remove the job*/ |
| mm_jpegdec_job_done(p_session); |
| LOGD("Error X "); |
| |
| return rc; |
| } |
| |
| /** mm_jpeg_start_decode_job: |
| * |
| * Arguments: |
| * @my_obj: jpeg object |
| * @client_hdl: client handle |
| * @job: pointer to encode job |
| * @jobId: job id |
| * |
| * Return: |
| * 0 for success else failure |
| * |
| * Description: |
| * Start the encoding job |
| * |
| **/ |
| int32_t mm_jpegdec_start_decode_job(mm_jpeg_obj *my_obj, |
| mm_jpeg_job_t *job, |
| uint32_t *job_id) |
| { |
| mm_jpeg_q_data_t qdata; |
| int32_t rc = -1; |
| uint8_t session_idx = 0; |
| uint8_t client_idx = 0; |
| mm_jpeg_job_q_node_t* node = NULL; |
| mm_jpeg_job_session_t *p_session = NULL; |
| mm_jpeg_decode_job_t *p_jobparams = &job->decode_job; |
| |
| *job_id = 0; |
| |
| /* check if valid session */ |
| session_idx = GET_SESSION_IDX(p_jobparams->session_id); |
| client_idx = GET_CLIENT_IDX(p_jobparams->session_id); |
| LOGD("session_idx %d client idx %d", |
| session_idx, client_idx); |
| |
| if ((session_idx >= MM_JPEG_MAX_SESSION) || |
| (client_idx >= MAX_JPEG_CLIENT_NUM)) { |
| LOGE("invalid session id %x", |
| job->decode_job.session_id); |
| return rc; |
| } |
| |
| p_session = &my_obj->clnt_mgr[client_idx].session[session_idx]; |
| if (OMX_FALSE == p_session->active) { |
| LOGE("session not active %x", |
| job->decode_job.session_id); |
| return rc; |
| } |
| |
| if ((p_jobparams->src_index >= (int32_t)p_session->dec_params.num_src_bufs) || |
| (p_jobparams->dst_index >= (int32_t)p_session->dec_params.num_dst_bufs)) { |
| LOGE("invalid buffer indices"); |
| return rc; |
| } |
| |
| /* enqueue new job into todo job queue */ |
| node = (mm_jpeg_job_q_node_t *)malloc(sizeof(mm_jpeg_job_q_node_t)); |
| if (NULL == node) { |
| LOGE("No memory for mm_jpeg_job_q_node_t"); |
| return -1; |
| } |
| |
| *job_id = job->decode_job.session_id | |
| ((p_session->job_hist++ % JOB_HIST_MAX) << 16); |
| |
| memset(node, 0, sizeof(mm_jpeg_job_q_node_t)); |
| node->dec_info.decode_job = job->decode_job; |
| node->dec_info.job_id = *job_id; |
| node->dec_info.client_handle = p_session->client_hdl; |
| node->type = MM_JPEG_CMD_TYPE_DECODE_JOB; |
| |
| qdata.p = node; |
| rc = mm_jpeg_queue_enq(&my_obj->job_mgr.job_queue, qdata); |
| if (0 == rc) { |
| cam_sem_post(&my_obj->job_mgr.job_sem); |
| } |
| |
| return rc; |
| } |
| |
| /** mm_jpegdec_create_session: |
| * |
| * Arguments: |
| * @my_obj: jpeg object |
| * @client_hdl: client handle |
| * @p_params: pointer to encode params |
| * @p_session_id: session id |
| * |
| * Return: |
| * 0 for success else failure |
| * |
| * Description: |
| * Start the encoding session |
| * |
| **/ |
| int32_t mm_jpegdec_create_session(mm_jpeg_obj *my_obj, |
| uint32_t client_hdl, |
| mm_jpeg_decode_params_t *p_params, |
| uint32_t* p_session_id) |
| { |
| int32_t rc = 0; |
| OMX_ERRORTYPE ret = OMX_ErrorNone; |
| uint8_t clnt_idx = 0; |
| int session_idx = -1; |
| mm_jpeg_job_session_t *p_session = NULL; |
| *p_session_id = 0; |
| |
| /* validate the parameters */ |
| if ((p_params->num_src_bufs > MM_JPEG_MAX_BUF) |
| || (p_params->num_dst_bufs > MM_JPEG_MAX_BUF)) { |
| LOGE("invalid num buffers"); |
| return rc; |
| } |
| |
| /* check if valid client */ |
| clnt_idx = mm_jpeg_util_get_index_by_handler(client_hdl); |
| if (clnt_idx >= MAX_JPEG_CLIENT_NUM) { |
| LOGE("invalid client with handler (%d)", client_hdl); |
| return rc; |
| } |
| |
| session_idx = mm_jpeg_get_new_session_idx(my_obj, clnt_idx, &p_session); |
| if (session_idx < 0) { |
| LOGE("invalid session id (%d)", session_idx); |
| return rc; |
| } |
| |
| ret = mm_jpegdec_session_create(p_session); |
| if (OMX_ErrorNone != ret) { |
| p_session->active = OMX_FALSE; |
| LOGE("jpeg session create failed"); |
| return rc; |
| } |
| |
| *p_session_id = (JOB_ID_MAGICVAL << 24) | |
| ((unsigned)session_idx << 8) | clnt_idx; |
| |
| /*copy the params*/ |
| p_session->dec_params = *p_params; |
| p_session->client_hdl = client_hdl; |
| p_session->sessionId = *p_session_id; |
| p_session->jpeg_obj = (void*)my_obj; /* save a ptr to jpeg_obj */ |
| LOGD("session id %x", *p_session_id); |
| |
| return rc; |
| } |
| |
| /** mm_jpegdec_destroy_session: |
| * |
| * Arguments: |
| * @my_obj: jpeg object |
| * @session_id: session index |
| * |
| * Return: |
| * 0 for success else failure |
| * |
| * Description: |
| * Destroy the encoding session |
| * |
| **/ |
| int32_t mm_jpegdec_destroy_session(mm_jpeg_obj *my_obj, |
| mm_jpeg_job_session_t *p_session) |
| { |
| int32_t rc = 0; |
| mm_jpeg_job_q_node_t *node = NULL; |
| |
| if (NULL == p_session) { |
| LOGE("invalid session"); |
| return rc; |
| } |
| uint32_t session_id = p_session->sessionId; |
| pthread_mutex_lock(&my_obj->job_lock); |
| |
| /* abort job if in todo queue */ |
| LOGD("abort todo jobs"); |
| node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id); |
| while (NULL != node) { |
| free(node); |
| node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->job_mgr.job_queue, session_id); |
| } |
| |
| /* abort job if in ongoing queue */ |
| LOGD("abort ongoing jobs"); |
| node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id); |
| while (NULL != node) { |
| free(node); |
| node = mm_jpeg_queue_remove_job_by_session_id(&my_obj->ongoing_job_q, session_id); |
| } |
| |
| /* abort the current session */ |
| mm_jpeg_session_abort(p_session); |
| mm_jpegdec_session_destroy(p_session); |
| mm_jpeg_remove_session_idx(my_obj, session_id); |
| pthread_mutex_unlock(&my_obj->job_lock); |
| |
| /* wake up jobMgr thread to work on new job if there is any */ |
| cam_sem_post(&my_obj->job_mgr.job_sem); |
| LOGD("X"); |
| |
| return rc; |
| } |
| |
| /** mm_jpegdec_destroy_session_by_id: |
| * |
| * Arguments: |
| * @my_obj: jpeg object |
| * @session_id: session index |
| * |
| * Return: |
| * 0 for success else failure |
| * |
| * Description: |
| * Destroy the encoding session |
| * |
| **/ |
| int32_t mm_jpegdec_destroy_session_by_id(mm_jpeg_obj *my_obj, uint32_t session_id) |
| { |
| int32_t rc = 0; |
| mm_jpeg_job_session_t *p_session = mm_jpeg_get_session(my_obj, session_id); |
| |
| if (NULL == p_session) { |
| LOGE("session is not valid"); |
| return rc; |
| } |
| |
| return mm_jpegdec_destroy_session(my_obj, p_session); |
| } |
| |
| |
| |
| OMX_ERRORTYPE mm_jpegdec_ebd(OMX_HANDLETYPE hComponent, |
| OMX_PTR pAppData, |
| OMX_BUFFERHEADERTYPE *pBuffer) |
| { |
| mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData; |
| |
| LOGD("count %d ", p_session->ebd_count); |
| pthread_mutex_lock(&p_session->lock); |
| p_session->ebd_count++; |
| pthread_mutex_unlock(&p_session->lock); |
| return 0; |
| } |
| |
| OMX_ERRORTYPE mm_jpegdec_fbd(OMX_HANDLETYPE hComponent, |
| OMX_PTR pAppData, |
| OMX_BUFFERHEADERTYPE *pBuffer) |
| { |
| OMX_ERRORTYPE ret = OMX_ErrorNone; |
| mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData; |
| mm_jpeg_output_t output_buf; |
| |
| LOGD("count %d ", p_session->fbd_count); |
| |
| pthread_mutex_lock(&p_session->lock); |
| |
| if (MM_JPEG_ABORT_NONE != p_session->abort_state) { |
| pthread_mutex_unlock(&p_session->lock); |
| return ret; |
| } |
| |
| p_session->fbd_count++; |
| if (NULL != p_session->dec_params.jpeg_cb) { |
| p_session->job_status = JPEG_JOB_STATUS_DONE; |
| output_buf.buf_filled_len = (uint32_t)pBuffer->nFilledLen; |
| output_buf.buf_vaddr = pBuffer->pBuffer; |
| output_buf.fd = -1; |
| LOGD("send jpeg callback %d", |
| p_session->job_status); |
| p_session->dec_params.jpeg_cb(p_session->job_status, |
| p_session->client_hdl, |
| p_session->jobId, |
| &output_buf, |
| p_session->dec_params.userdata); |
| |
| /* remove from ready queue */ |
| mm_jpegdec_job_done(p_session); |
| } |
| pthread_mutex_unlock(&p_session->lock); |
| LOGD("Exit"); |
| |
| return ret; |
| } |
| |
| OMX_ERRORTYPE mm_jpegdec_event_handler(OMX_HANDLETYPE hComponent, |
| OMX_PTR pAppData, |
| OMX_EVENTTYPE eEvent, |
| OMX_U32 nData1, |
| OMX_U32 nData2, |
| OMX_PTR pEventData) |
| { |
| mm_jpeg_job_session_t *p_session = (mm_jpeg_job_session_t *) pAppData; |
| |
| LOGD("%d %d %d state %d", eEvent, (int)nData1, |
| (int)nData2, p_session->abort_state); |
| |
| LOGD("AppData=%p ", pAppData); |
| |
| pthread_mutex_lock(&p_session->lock); |
| p_session->omxEvent = eEvent; |
| if (MM_JPEG_ABORT_INIT == p_session->abort_state) { |
| p_session->abort_state = MM_JPEG_ABORT_DONE; |
| pthread_cond_signal(&p_session->cond); |
| pthread_mutex_unlock(&p_session->lock); |
| return OMX_ErrorNone; |
| } |
| |
| if (eEvent == OMX_EventError) { |
| if (p_session->encoding == OMX_TRUE) { |
| LOGD("Error during encoding"); |
| |
| /* send jpeg callback */ |
| if (NULL != p_session->dec_params.jpeg_cb) { |
| p_session->job_status = JPEG_JOB_STATUS_ERROR; |
| LOGD("send jpeg error callback %d", |
| p_session->job_status); |
| p_session->dec_params.jpeg_cb(p_session->job_status, |
| p_session->client_hdl, |
| p_session->jobId, |
| NULL, |
| p_session->dec_params.userdata); |
| } |
| |
| /* remove from ready queue */ |
| mm_jpegdec_job_done(p_session); |
| } |
| pthread_cond_signal(&p_session->cond); |
| } else if (eEvent == OMX_EventCmdComplete) { |
| p_session->state_change_pending = OMX_FALSE; |
| p_session->event_pending = OMX_FALSE; |
| pthread_cond_signal(&p_session->cond); |
| } else if (eEvent == OMX_EventPortSettingsChanged) { |
| p_session->event_pending = OMX_FALSE; |
| pthread_cond_signal(&p_session->cond); |
| } |
| |
| pthread_mutex_unlock(&p_session->lock); |
| LOGD("Exit"); |
| return OMX_ErrorNone; |
| } |
| |
| /** mm_jpegdec_abort_job: |
| * |
| * Arguments: |
| * @my_obj: jpeg object |
| * @client_hdl: client handle |
| * @jobId: job id |
| * |
| * Return: |
| * 0 for success else failure |
| * |
| * Description: |
| * Abort the encoding session |
| * |
| **/ |
| int32_t mm_jpegdec_abort_job(mm_jpeg_obj *my_obj, |
| uint32_t jobId) |
| { |
| int32_t rc = -1; |
| mm_jpeg_job_q_node_t *node = NULL; |
| mm_jpeg_job_session_t *p_session = NULL; |
| |
| LOGD("Enter"); |
| pthread_mutex_lock(&my_obj->job_lock); |
| |
| /* abort job if in todo queue */ |
| node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->job_mgr.job_queue, jobId); |
| if (NULL != node) { |
| free(node); |
| goto abort_done; |
| } |
| |
| /* abort job if in ongoing queue */ |
| node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->ongoing_job_q, jobId); |
| if (NULL != node) { |
| /* find job that is OMX ongoing, ask OMX to abort the job */ |
| p_session = mm_jpeg_get_session(my_obj, node->dec_info.job_id); |
| if (p_session) { |
| mm_jpeg_session_abort(p_session); |
| } else { |
| LOGE("Invalid job id 0x%x", |
| node->dec_info.job_id); |
| } |
| free(node); |
| goto abort_done; |
| } |
| |
| abort_done: |
| pthread_mutex_unlock(&my_obj->job_lock); |
| |
| return rc; |
| } |
| /** mm_jpegdec_init: |
| * |
| * Arguments: |
| * @my_obj: jpeg object |
| * |
| * Return: |
| * 0 for success else failure |
| * |
| * Description: |
| * Initializes the jpeg client |
| * |
| **/ |
| int32_t mm_jpegdec_init(mm_jpeg_obj *my_obj) |
| { |
| int32_t rc = 0; |
| |
| /* init locks */ |
| pthread_mutex_init(&my_obj->job_lock, NULL); |
| |
| /* init ongoing job queue */ |
| rc = mm_jpeg_queue_init(&my_obj->ongoing_job_q); |
| if (0 != rc) { |
| LOGE("Error"); |
| return -1; |
| } |
| |
| /* init job semaphore and launch jobmgr thread */ |
| LOGD("Launch jobmgr thread rc %d", rc); |
| rc = mm_jpeg_jobmgr_thread_launch(my_obj); |
| if (0 != rc) { |
| LOGE("Error"); |
| return -1; |
| } |
| |
| /* load OMX */ |
| if (OMX_ErrorNone != OMX_Init()) { |
| /* roll back in error case */ |
| LOGE("OMX_Init failed (%d)", rc); |
| mm_jpeg_jobmgr_thread_release(my_obj); |
| mm_jpeg_queue_deinit(&my_obj->ongoing_job_q); |
| pthread_mutex_destroy(&my_obj->job_lock); |
| } |
| |
| return rc; |
| } |
| |
| /** mm_jpegdec_deinit: |
| * |
| * Arguments: |
| * @my_obj: jpeg object |
| * |
| * Return: |
| * 0 for success else failure |
| * |
| * Description: |
| * Deinits the jpeg client |
| * |
| **/ |
| int32_t mm_jpegdec_deinit(mm_jpeg_obj *my_obj) |
| { |
| int32_t rc = 0; |
| |
| /* release jobmgr thread */ |
| rc = mm_jpeg_jobmgr_thread_release(my_obj); |
| if (0 != rc) { |
| LOGE("Error"); |
| } |
| |
| /* unload OMX engine */ |
| OMX_Deinit(); |
| |
| /* deinit ongoing job and cb queue */ |
| rc = mm_jpeg_queue_deinit(&my_obj->ongoing_job_q); |
| if (0 != rc) { |
| LOGE("Error"); |
| } |
| |
| /* destroy locks */ |
| pthread_mutex_destroy(&my_obj->job_lock); |
| |
| return rc; |
| } |