From 99faaf7cd04116922fc35ab5c72c023d6b23e8a8 Mon Sep 17 00:00:00 2001 From: Praveen Chavan Date: Wed, 16 Oct 2013 12:43:57 -0700 Subject: mm-video: venc: allocate input buffers as uncached YUV data written by CPU producers (MediaCodec apps) are not Bug: 10192531 Change-Id: I1975b9b63ad4af474340ac366af32c8c3863b4bb --- mm-video-legacy/vidc/venc/src/omx_video_base.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm-video-legacy/vidc/venc/src/omx_video_base.cpp b/mm-video-legacy/vidc/venc/src/omx_video_base.cpp index 9c225bdc..84099b28 100644 --- a/mm-video-legacy/vidc/venc/src/omx_video_base.cpp +++ b/mm-video-legacy/vidc/venc/src/omx_video_base.cpp @@ -2751,7 +2751,7 @@ OMX_ERRORTYPE omx_video::allocate_input_buffer( #ifdef USE_ION m_pInput_ion[i].ion_device_fd = alloc_map_ion_memory(m_sInPortDef.nBufferSize, &m_pInput_ion[i].ion_alloc_data, - &m_pInput_ion[i].fd_ion_data,ION_FLAG_CACHED); + &m_pInput_ion[i].fd_ion_data,0); if(m_pInput_ion[i].ion_device_fd < 0) { DEBUG_PRINT_ERROR("\nERROR:ION device open() Failed"); return OMX_ErrorInsufficientResources; -- cgit v1.2.3 From a7cc922ab8aacc121d0abca2ba687d5551ad7523 Mon Sep 17 00:00:00 2001 From: Praveen Chavan Date: Wed, 30 Oct 2013 19:41:11 -0700 Subject: mm-video: vidc: Fix codec config behavior in flush Send pending codec config data to the driver when flushing. Reset intermediate buffers handles when input port is disabled and port buffers are freed. Bug: 11099331 Signed-off: Leena Winterrowd Change-Id: Ifd674b71ce04a4be16b564c53122ce5c5e4d92f1 --- mm-video-v4l2/vidc/vdec/inc/omx_vdec.h | 3 ++ mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp | 66 ++++++++++++++++++++---- 2 files changed, 60 insertions(+), 9 deletions(-) diff --git a/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h b/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h index 765af594..02bf093b 100755 --- a/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h +++ b/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h @@ -959,6 +959,9 @@ class omx_vdec: public qc_omx_component allocate_color_convert_buf client_buffers; #endif struct video_decoder_capability m_decoder_capability; +#ifdef _MSM8974_ + void send_codec_config(); +#endif }; #ifdef _MSM8974_ diff --git a/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp b/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp index e702c627..1cc359ce 100755 --- a/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp +++ b/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp @@ -2156,6 +2156,7 @@ OMX_ERRORTYPE omx_vdec::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp, } else if (cmd == OMX_CommandFlush) { DEBUG_PRINT_HIGH("\n send_command_proxy(): OMX_CommandFlush issued" "with param1: %lu", param1); + send_codec_config(); if (OMX_CORE_INPUT_PORT_INDEX == param1 || OMX_ALL == param1) { BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING); } @@ -2208,6 +2209,7 @@ OMX_ERRORTYPE omx_vdec::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp, DEBUG_PRINT_HIGH("\n send_command_proxy(): OMX_CommandPortDisable issued" "with param1: %lu", param1); if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) { + codec_config_flag = false; m_inp_bEnabled = OMX_FALSE; if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle) && release_input_done()) { @@ -5178,13 +5180,6 @@ OMX_ERRORTYPE omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_ERRORTYPE ret1 = OMX_ErrorNone; unsigned int nBufferIndex = drv_ctx.ip_buf.actualcount; - if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { - codec_config_flag = true; - DEBUG_PRINT_LOW("%s: codec_config buffer", __FUNCTION__); - } else { - codec_config_flag = false; - } - if (m_state == OMX_StateInvalid) { DEBUG_PRINT_ERROR("Empty this buffer in Invalid State\n"); return OMX_ErrorInvalidState; @@ -5243,6 +5238,11 @@ OMX_ERRORTYPE omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp, return OMX_ErrorBadParameter; } + if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { + codec_config_flag = true; + DEBUG_PRINT_LOW("%s: codec_config buffer", __FUNCTION__); + } + DEBUG_PRINT_LOW("[ETB] BHdr(%p) pBuf(%p) nTS(%lld) nFL(%lu)", buffer, buffer->pBuffer, buffer->nTimeStamp, buffer->nFilledLen); if (arbitrary_bytes) { @@ -5500,6 +5500,9 @@ OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE h DEBUG_PRINT_ERROR("Failed to qbuf Input buffer to driver\n"); return OMX_ErrorHardware; } + if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) { + codec_config_flag = false; + } if (!streaming[OUTPUT_PORT]) { enum v4l2_buf_type buf_type; int ret,r; @@ -7369,12 +7372,14 @@ void omx_vdec::free_input_buffer_header() free (m_inp_mem_ptr); m_inp_mem_ptr = NULL; } - /* We just freed all the buffer headers, every thing in m_input_free_q - * is now invalid */ + /* We just freed all the buffer headers, every thing in m_input_free_q, + * pdest_frame, and psource_frame is now invalid */ while (m_input_free_q.m_size) { unsigned address, p2, id; m_input_free_q.pop_entry(&address, &p2, &id); } + pdest_frame = NULL; + psource_frame = NULL; if (drv_ctx.ptr_inputbuffer) { DEBUG_PRINT_LOW("\n Free Driver Context pointer"); free (drv_ctx.ptr_inputbuffer); @@ -8929,3 +8934,46 @@ void omx_vdec::buf_ref_remove(OMX_U32 fd, OMX_U32 offset) } pthread_mutex_unlock(&m_lock); } + +void omx_vdec::send_codec_config() { + if (codec_config_flag) { + unsigned p1 = 0; // Parameter - 1 + unsigned p2 = 0; // Parameter - 2 + unsigned ident = 0; + pthread_mutex_lock(&m_lock); + DEBUG_PRINT_LOW("\n Check Queue for codec_config buffer \n"); + while (m_etb_q.m_size) { + m_etb_q.pop_entry(&p1,&p2,&ident); + if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) { + if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { + if (empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\ + (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) { + DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy_arbitrary failure"); + omx_report_error(); + } + } else { + DEBUG_PRINT_LOW("\n Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2); + m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2); + } + } else if (ident == OMX_COMPONENT_GENERATE_ETB) { + if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { + if (empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\ + (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) { + DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy failure"); + omx_report_error (); + } + } else { + pending_input_buffers++; + DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d", + (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers); + empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2); + } + } else if (ident == OMX_COMPONENT_GENERATE_EBD) { + DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_EBD %p", + (OMX_BUFFERHEADERTYPE *)p1); + empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1); + } + } + pthread_mutex_unlock(&m_lock); + } +} -- cgit v1.2.3 From a943a925f77029181f0bd74f6794ea4175819582 Mon Sep 17 00:00:00 2001 From: Praveen Chavan Date: Fri, 1 Nov 2013 02:24:24 -0700 Subject: mm-video: vidc: stability fixes in decoder Synchronize access to extradata buffer which is allocated and accessed in separate threads. Do not unmap output handles in dynamic buffer mode when buffers are freed (since they are unmapped already in FBD) Bug: 11099331 Bug: 11366221 Signed-off: Leena Winterrowd Change-Id: I26d02c183d8496a52d4ded51c53f44eaf5e6e0b0 --- mm-video-v4l2/vidc/vdec/inc/omx_vdec.h | 16 +++++- mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp | 71 ++++++++++++++++-------- 2 files changed, 63 insertions(+), 24 deletions(-) diff --git a/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h b/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h index 02bf093b..00d5e6e2 100755 --- a/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h +++ b/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h @@ -721,12 +721,26 @@ class omx_vdec: public qc_omx_component nativebuffer native_buffer[MAX_NUM_INPUT_OUTPUT_BUFFERS]; #endif - + class auto_lock { + public: + auto_lock(pthread_mutex_t *lock) + : mLock(lock) { + if (mLock) + pthread_mutex_lock(mLock); + } + ~auto_lock() { + if (mLock) + pthread_mutex_unlock(mLock); + } + private: + pthread_mutex_t *mLock; + }; //************************************************************* //*******************MEMBER VARIABLES ************************* //************************************************************* pthread_mutex_t m_lock; pthread_mutex_t c_lock; + pthread_mutex_t e_lock; //sem to handle the minimum procesing of commands sem_t m_cmd_lock; bool m_error_propogated; diff --git a/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp b/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp index 1cc359ce..9887143f 100755 --- a/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp +++ b/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp @@ -611,6 +611,7 @@ omx_vdec::omx_vdec(): m_error_propogated(false), m_vendor_config.pData = NULL; pthread_mutex_init(&m_lock, NULL); pthread_mutex_init(&c_lock, NULL); + pthread_mutex_init(&e_lock, NULL); sem_init(&m_cmd_lock,0,0); streaming[CAPTURE_PORT] = streaming[OUTPUT_PORT] = false; @@ -729,6 +730,7 @@ omx_vdec::~omx_vdec() close(drv_ctx.video_driver_fd); pthread_mutex_destroy(&m_lock); pthread_mutex_destroy(&c_lock); + pthread_mutex_destroy(&e_lock); sem_destroy(&m_cmd_lock); if (perf_flag) { DEBUG_PRINT_HIGH("--> TOTAL PROCESSING TIME"); @@ -3819,11 +3821,13 @@ OMX_ERRORTYPE omx_vdec::component_tunnel_request(OMX_IN OMX_HANDLETYPE OMX_ERRORTYPE omx_vdec::allocate_extradata() { #ifdef USE_ION + auto_lock extradata_lock(&e_lock); if (drv_ctx.extradata_info.buffer_size) { if (drv_ctx.extradata_info.ion.ion_alloc_data.handle) { munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size); close(drv_ctx.extradata_info.ion.fd_ion_data.fd); free_ion_memory(&drv_ctx.extradata_info.ion); + memset(&drv_ctx.extradata_info, 0, sizeof(drv_ctx.extradata_info)); } drv_ctx.extradata_info.size = (drv_ctx.extradata_info.size + 4095) & (~4095); drv_ctx.extradata_info.ion.ion_device_fd = alloc_map_ion_memory( @@ -3852,6 +3856,7 @@ OMX_ERRORTYPE omx_vdec::allocate_extradata() void omx_vdec::free_extradata() { #ifdef USE_ION + auto_lock extradata_lock(&e_lock); if (drv_ctx.extradata_info.uaddr) { munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size); close(drv_ctx.extradata_info.ion.fd_ion_data.fd); @@ -4324,36 +4329,39 @@ OMX_ERRORTYPE omx_vdec::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr) setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT; memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[index], sizeof (vdec_bufferpayload)); + + if (!dynamic_buf_mode) { #ifdef _ANDROID_ - if (m_enable_android_native_buffers) { - if (!secure_mode) { - if (drv_ctx.ptr_outputbuffer[index].pmem_fd > 0) { - munmap(drv_ctx.ptr_outputbuffer[index].bufferaddr, - drv_ctx.ptr_outputbuffer[index].mmaped_size); - } - } - drv_ctx.ptr_outputbuffer[index].pmem_fd = -1; - } else { -#endif - if (drv_ctx.ptr_outputbuffer[0].pmem_fd > 0 && !ouput_egl_buffers && !m_use_output_pmem) { + if (m_enable_android_native_buffers) { if (!secure_mode) { - DEBUG_PRINT_LOW("\n unmap the output buffer fd = %d", - drv_ctx.ptr_outputbuffer[0].pmem_fd); - DEBUG_PRINT_LOW("\n unmap the ouput buffer size=%d address = %p", - drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount, - drv_ctx.ptr_outputbuffer[0].bufferaddr); - munmap (drv_ctx.ptr_outputbuffer[0].bufferaddr, - drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount); + if (drv_ctx.ptr_outputbuffer[index].pmem_fd > 0) { + munmap(drv_ctx.ptr_outputbuffer[index].bufferaddr, + drv_ctx.ptr_outputbuffer[index].mmaped_size); + } } - close (drv_ctx.ptr_outputbuffer[0].pmem_fd); - drv_ctx.ptr_outputbuffer[0].pmem_fd = -1; + drv_ctx.ptr_outputbuffer[index].pmem_fd = -1; + } else { +#endif + if (drv_ctx.ptr_outputbuffer[0].pmem_fd > 0 && !ouput_egl_buffers && !m_use_output_pmem) { + if (!secure_mode) { + DEBUG_PRINT_LOW("\n unmap the output buffer fd = %d", + drv_ctx.ptr_outputbuffer[0].pmem_fd); + DEBUG_PRINT_LOW("\n unmap the ouput buffer size=%d address = %p", + drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount, + drv_ctx.ptr_outputbuffer[0].bufferaddr); + munmap (drv_ctx.ptr_outputbuffer[0].bufferaddr, + drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount); + } + close (drv_ctx.ptr_outputbuffer[0].pmem_fd); + drv_ctx.ptr_outputbuffer[0].pmem_fd = -1; #ifdef USE_ION - free_ion_memory(&drv_ctx.op_buf_ion_info[0]); + free_ion_memory(&drv_ctx.op_buf_ion_info[0]); #endif - } + } #ifdef _ANDROID_ - } + } #endif + } //!dynamic_buf_mode if (release_output_done()) { free_extradata(); } @@ -7378,6 +7386,12 @@ void omx_vdec::free_input_buffer_header() unsigned address, p2, id; m_input_free_q.pop_entry(&address, &p2, &id); } + /* We just freed all the buffer headers, every thing in m_input_pending_q, + * is now invalid too*/ + while (m_input_pending_q.m_size) { + unsigned address, p2, id; + m_input_pending_q.pop_entry(&address, &p2, &id); + } pdest_frame = NULL; psource_frame = NULL; if (drv_ctx.ptr_inputbuffer) { @@ -7950,9 +7964,17 @@ void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr) int enable = 0; OMX_U32 mbaff = 0; int buf_index = p_buf_hdr - m_out_mem_ptr; + if (buf_index >= drv_ctx.extradata_info.count) { + DEBUG_PRINT_ERROR("handle_extradata: invalid index(%d) max(%d)", + buf_index, drv_ctx.extradata_info.count); + return; + } struct msm_vidc_panscan_window_payload *panscan_payload = NULL; OMX_U8 *pBuffer = (OMX_U8 *)(drv_ctx.ptr_outputbuffer[buf_index].bufferaddr) + p_buf_hdr->nOffset; + + auto_lock extradata_lock(&e_lock); + if (!drv_ctx.extradata_info.uaddr) { return; } @@ -8051,6 +8073,9 @@ void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr) } consumed_len += data->nSize; data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize); + if (data->nSize) { + break; + } } if (!secure_mode && (client_extradata & OMX_FRAMEINFO_EXTRADATA)) { p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA; -- cgit v1.2.3 From e048a842a91d7ce310b2ed2be23ab50d3b39c5c4 Mon Sep 17 00:00:00 2001 From: Praveen Chavan Date: Wed, 30 Oct 2013 19:41:11 -0700 Subject: mm-video: vidc: Fix codec config behavior in flush Send pending codec config data to the driver when flushing. Reset intermediate buffers handles when input port is disabled and port buffers are freed. Bug: 11099331 Signed-off: Leena Winterrowd Change-Id: Ifd674b71ce04a4be16b564c53122ce5c5e4d92f1 --- mm-video-v4l2/vidc/vdec/inc/omx_vdec.h | 3 ++ mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp | 66 ++++++++++++++++++++---- 2 files changed, 60 insertions(+), 9 deletions(-) diff --git a/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h b/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h index 765af594..02bf093b 100755 --- a/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h +++ b/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h @@ -959,6 +959,9 @@ class omx_vdec: public qc_omx_component allocate_color_convert_buf client_buffers; #endif struct video_decoder_capability m_decoder_capability; +#ifdef _MSM8974_ + void send_codec_config(); +#endif }; #ifdef _MSM8974_ diff --git a/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp b/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp index e702c627..1cc359ce 100755 --- a/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp +++ b/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp @@ -2156,6 +2156,7 @@ OMX_ERRORTYPE omx_vdec::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp, } else if (cmd == OMX_CommandFlush) { DEBUG_PRINT_HIGH("\n send_command_proxy(): OMX_CommandFlush issued" "with param1: %lu", param1); + send_codec_config(); if (OMX_CORE_INPUT_PORT_INDEX == param1 || OMX_ALL == param1) { BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING); } @@ -2208,6 +2209,7 @@ OMX_ERRORTYPE omx_vdec::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp, DEBUG_PRINT_HIGH("\n send_command_proxy(): OMX_CommandPortDisable issued" "with param1: %lu", param1); if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) { + codec_config_flag = false; m_inp_bEnabled = OMX_FALSE; if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle) && release_input_done()) { @@ -5178,13 +5180,6 @@ OMX_ERRORTYPE omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_ERRORTYPE ret1 = OMX_ErrorNone; unsigned int nBufferIndex = drv_ctx.ip_buf.actualcount; - if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { - codec_config_flag = true; - DEBUG_PRINT_LOW("%s: codec_config buffer", __FUNCTION__); - } else { - codec_config_flag = false; - } - if (m_state == OMX_StateInvalid) { DEBUG_PRINT_ERROR("Empty this buffer in Invalid State\n"); return OMX_ErrorInvalidState; @@ -5243,6 +5238,11 @@ OMX_ERRORTYPE omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp, return OMX_ErrorBadParameter; } + if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { + codec_config_flag = true; + DEBUG_PRINT_LOW("%s: codec_config buffer", __FUNCTION__); + } + DEBUG_PRINT_LOW("[ETB] BHdr(%p) pBuf(%p) nTS(%lld) nFL(%lu)", buffer, buffer->pBuffer, buffer->nTimeStamp, buffer->nFilledLen); if (arbitrary_bytes) { @@ -5500,6 +5500,9 @@ OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE h DEBUG_PRINT_ERROR("Failed to qbuf Input buffer to driver\n"); return OMX_ErrorHardware; } + if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) { + codec_config_flag = false; + } if (!streaming[OUTPUT_PORT]) { enum v4l2_buf_type buf_type; int ret,r; @@ -7369,12 +7372,14 @@ void omx_vdec::free_input_buffer_header() free (m_inp_mem_ptr); m_inp_mem_ptr = NULL; } - /* We just freed all the buffer headers, every thing in m_input_free_q - * is now invalid */ + /* We just freed all the buffer headers, every thing in m_input_free_q, + * pdest_frame, and psource_frame is now invalid */ while (m_input_free_q.m_size) { unsigned address, p2, id; m_input_free_q.pop_entry(&address, &p2, &id); } + pdest_frame = NULL; + psource_frame = NULL; if (drv_ctx.ptr_inputbuffer) { DEBUG_PRINT_LOW("\n Free Driver Context pointer"); free (drv_ctx.ptr_inputbuffer); @@ -8929,3 +8934,46 @@ void omx_vdec::buf_ref_remove(OMX_U32 fd, OMX_U32 offset) } pthread_mutex_unlock(&m_lock); } + +void omx_vdec::send_codec_config() { + if (codec_config_flag) { + unsigned p1 = 0; // Parameter - 1 + unsigned p2 = 0; // Parameter - 2 + unsigned ident = 0; + pthread_mutex_lock(&m_lock); + DEBUG_PRINT_LOW("\n Check Queue for codec_config buffer \n"); + while (m_etb_q.m_size) { + m_etb_q.pop_entry(&p1,&p2,&ident); + if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) { + if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { + if (empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\ + (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) { + DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy_arbitrary failure"); + omx_report_error(); + } + } else { + DEBUG_PRINT_LOW("\n Flush Input Heap Buffer %p",(OMX_BUFFERHEADERTYPE *)p2); + m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p2); + } + } else if (ident == OMX_COMPONENT_GENERATE_ETB) { + if (((OMX_BUFFERHEADERTYPE *)p2)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { + if (empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\ + (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) { + DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy failure"); + omx_report_error (); + } + } else { + pending_input_buffers++; + DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_ETB %p, pending_input_buffers %d", + (OMX_BUFFERHEADERTYPE *)p2, pending_input_buffers); + empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2); + } + } else if (ident == OMX_COMPONENT_GENERATE_EBD) { + DEBUG_PRINT_LOW("\n Flush Input OMX_COMPONENT_GENERATE_EBD %p", + (OMX_BUFFERHEADERTYPE *)p1); + empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1); + } + } + pthread_mutex_unlock(&m_lock); + } +} -- cgit v1.2.3 From 36114d4155f1fc6aa95badcd8fe97c3eaedc9271 Mon Sep 17 00:00:00 2001 From: Praveen Chavan Date: Fri, 1 Nov 2013 02:24:24 -0700 Subject: mm-video: vidc: stability fixes in decoder Synchronize access to extradata buffer which is allocated and accessed in separate threads. Do not unmap output handles in dynamic buffer mode when buffers are freed (since they are unmapped already in FBD) Bug: 11099331 Bug: 11366221 Signed-off: Leena Winterrowd Change-Id: I26d02c183d8496a52d4ded51c53f44eaf5e6e0b0 --- mm-video-v4l2/vidc/vdec/inc/omx_vdec.h | 16 +++++- mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp | 71 ++++++++++++++++-------- 2 files changed, 63 insertions(+), 24 deletions(-) diff --git a/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h b/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h index 02bf093b..00d5e6e2 100755 --- a/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h +++ b/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h @@ -721,12 +721,26 @@ class omx_vdec: public qc_omx_component nativebuffer native_buffer[MAX_NUM_INPUT_OUTPUT_BUFFERS]; #endif - + class auto_lock { + public: + auto_lock(pthread_mutex_t *lock) + : mLock(lock) { + if (mLock) + pthread_mutex_lock(mLock); + } + ~auto_lock() { + if (mLock) + pthread_mutex_unlock(mLock); + } + private: + pthread_mutex_t *mLock; + }; //************************************************************* //*******************MEMBER VARIABLES ************************* //************************************************************* pthread_mutex_t m_lock; pthread_mutex_t c_lock; + pthread_mutex_t e_lock; //sem to handle the minimum procesing of commands sem_t m_cmd_lock; bool m_error_propogated; diff --git a/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp b/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp index 1cc359ce..9887143f 100755 --- a/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp +++ b/mm-video-v4l2/vidc/vdec/src/omx_vdec_msm8974.cpp @@ -611,6 +611,7 @@ omx_vdec::omx_vdec(): m_error_propogated(false), m_vendor_config.pData = NULL; pthread_mutex_init(&m_lock, NULL); pthread_mutex_init(&c_lock, NULL); + pthread_mutex_init(&e_lock, NULL); sem_init(&m_cmd_lock,0,0); streaming[CAPTURE_PORT] = streaming[OUTPUT_PORT] = false; @@ -729,6 +730,7 @@ omx_vdec::~omx_vdec() close(drv_ctx.video_driver_fd); pthread_mutex_destroy(&m_lock); pthread_mutex_destroy(&c_lock); + pthread_mutex_destroy(&e_lock); sem_destroy(&m_cmd_lock); if (perf_flag) { DEBUG_PRINT_HIGH("--> TOTAL PROCESSING TIME"); @@ -3819,11 +3821,13 @@ OMX_ERRORTYPE omx_vdec::component_tunnel_request(OMX_IN OMX_HANDLETYPE OMX_ERRORTYPE omx_vdec::allocate_extradata() { #ifdef USE_ION + auto_lock extradata_lock(&e_lock); if (drv_ctx.extradata_info.buffer_size) { if (drv_ctx.extradata_info.ion.ion_alloc_data.handle) { munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size); close(drv_ctx.extradata_info.ion.fd_ion_data.fd); free_ion_memory(&drv_ctx.extradata_info.ion); + memset(&drv_ctx.extradata_info, 0, sizeof(drv_ctx.extradata_info)); } drv_ctx.extradata_info.size = (drv_ctx.extradata_info.size + 4095) & (~4095); drv_ctx.extradata_info.ion.ion_device_fd = alloc_map_ion_memory( @@ -3852,6 +3856,7 @@ OMX_ERRORTYPE omx_vdec::allocate_extradata() void omx_vdec::free_extradata() { #ifdef USE_ION + auto_lock extradata_lock(&e_lock); if (drv_ctx.extradata_info.uaddr) { munmap((void *)drv_ctx.extradata_info.uaddr, drv_ctx.extradata_info.size); close(drv_ctx.extradata_info.ion.fd_ion_data.fd); @@ -4324,36 +4329,39 @@ OMX_ERRORTYPE omx_vdec::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr) setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT; memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[index], sizeof (vdec_bufferpayload)); + + if (!dynamic_buf_mode) { #ifdef _ANDROID_ - if (m_enable_android_native_buffers) { - if (!secure_mode) { - if (drv_ctx.ptr_outputbuffer[index].pmem_fd > 0) { - munmap(drv_ctx.ptr_outputbuffer[index].bufferaddr, - drv_ctx.ptr_outputbuffer[index].mmaped_size); - } - } - drv_ctx.ptr_outputbuffer[index].pmem_fd = -1; - } else { -#endif - if (drv_ctx.ptr_outputbuffer[0].pmem_fd > 0 && !ouput_egl_buffers && !m_use_output_pmem) { + if (m_enable_android_native_buffers) { if (!secure_mode) { - DEBUG_PRINT_LOW("\n unmap the output buffer fd = %d", - drv_ctx.ptr_outputbuffer[0].pmem_fd); - DEBUG_PRINT_LOW("\n unmap the ouput buffer size=%d address = %p", - drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount, - drv_ctx.ptr_outputbuffer[0].bufferaddr); - munmap (drv_ctx.ptr_outputbuffer[0].bufferaddr, - drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount); + if (drv_ctx.ptr_outputbuffer[index].pmem_fd > 0) { + munmap(drv_ctx.ptr_outputbuffer[index].bufferaddr, + drv_ctx.ptr_outputbuffer[index].mmaped_size); + } } - close (drv_ctx.ptr_outputbuffer[0].pmem_fd); - drv_ctx.ptr_outputbuffer[0].pmem_fd = -1; + drv_ctx.ptr_outputbuffer[index].pmem_fd = -1; + } else { +#endif + if (drv_ctx.ptr_outputbuffer[0].pmem_fd > 0 && !ouput_egl_buffers && !m_use_output_pmem) { + if (!secure_mode) { + DEBUG_PRINT_LOW("\n unmap the output buffer fd = %d", + drv_ctx.ptr_outputbuffer[0].pmem_fd); + DEBUG_PRINT_LOW("\n unmap the ouput buffer size=%d address = %p", + drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount, + drv_ctx.ptr_outputbuffer[0].bufferaddr); + munmap (drv_ctx.ptr_outputbuffer[0].bufferaddr, + drv_ctx.ptr_outputbuffer[0].mmaped_size * drv_ctx.op_buf.actualcount); + } + close (drv_ctx.ptr_outputbuffer[0].pmem_fd); + drv_ctx.ptr_outputbuffer[0].pmem_fd = -1; #ifdef USE_ION - free_ion_memory(&drv_ctx.op_buf_ion_info[0]); + free_ion_memory(&drv_ctx.op_buf_ion_info[0]); #endif - } + } #ifdef _ANDROID_ - } + } #endif + } //!dynamic_buf_mode if (release_output_done()) { free_extradata(); } @@ -7378,6 +7386,12 @@ void omx_vdec::free_input_buffer_header() unsigned address, p2, id; m_input_free_q.pop_entry(&address, &p2, &id); } + /* We just freed all the buffer headers, every thing in m_input_pending_q, + * is now invalid too*/ + while (m_input_pending_q.m_size) { + unsigned address, p2, id; + m_input_pending_q.pop_entry(&address, &p2, &id); + } pdest_frame = NULL; psource_frame = NULL; if (drv_ctx.ptr_inputbuffer) { @@ -7950,9 +7964,17 @@ void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr) int enable = 0; OMX_U32 mbaff = 0; int buf_index = p_buf_hdr - m_out_mem_ptr; + if (buf_index >= drv_ctx.extradata_info.count) { + DEBUG_PRINT_ERROR("handle_extradata: invalid index(%d) max(%d)", + buf_index, drv_ctx.extradata_info.count); + return; + } struct msm_vidc_panscan_window_payload *panscan_payload = NULL; OMX_U8 *pBuffer = (OMX_U8 *)(drv_ctx.ptr_outputbuffer[buf_index].bufferaddr) + p_buf_hdr->nOffset; + + auto_lock extradata_lock(&e_lock); + if (!drv_ctx.extradata_info.uaddr) { return; } @@ -8051,6 +8073,9 @@ void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr) } consumed_len += data->nSize; data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize); + if (data->nSize) { + break; + } } if (!secure_mode && (client_extradata & OMX_FRAMEINFO_EXTRADATA)) { p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA; -- cgit v1.2.3 From 9051a9833db84a4dad38adebc94fdb0861ae3b94 Mon Sep 17 00:00:00 2001 From: Arun Menon Date: Wed, 14 Aug 2013 16:00:03 +0530 Subject: mm-video: vidc: release registered buffers from driver In some scenarios, component may restart from loaded to idle state in the same context and it is resulting in the preapare buf failure as previous buffers are not unregistered. Unregister the buffers from driver while stopping the component. b/11051201 Signed-off: Manikanta Kanamarlapudi Change-Id: I048cf715d2e83b05df99eaf10776cff0bbb2acd2 --- .../vidc/venc/src/video_encoder_device_v4l2.cpp | 27 ++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp b/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp index ecb7c6b1..98443b76 100755 --- a/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp +++ b/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp @@ -1438,7 +1438,8 @@ bool venc_dev::venc_set_config(void *configData, OMX_INDEXTYPE index) unsigned venc_dev::venc_stop( void) { struct venc_msg venc_msg; - int rc = 0; + struct v4l2_requestbuffers bufreq; + int rc = 0, ret = 0; if (!stopped) { enum v4l2_buf_type cap_type; @@ -1452,6 +1453,17 @@ unsigned venc_dev::venc_stop( void) cap_type, rc); } else streaming[OUTPUT_PORT] = false; + + DEBUG_PRINT_LOW("Releasing registered buffers from driver on o/p port"); + bufreq.memory = V4L2_MEMORY_USERPTR; + bufreq.count = 0; + bufreq.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + ret = ioctl(m_nDriver_fd, VIDIOC_REQBUFS, &bufreq); + + if (ret) { + DEBUG_PRINT_ERROR("\nERROR: VIDIOC_REQBUFS OUTPUT MPLANE Failed \n "); + return false; + } } if (!rc && streaming[CAPTURE_PORT]) { @@ -1463,9 +1475,20 @@ unsigned venc_dev::venc_stop( void) cap_type, rc); } else streaming[CAPTURE_PORT] = false; + + DEBUG_PRINT_LOW("Releasing registered buffers from driver on capture port"); + bufreq.memory = V4L2_MEMORY_USERPTR; + bufreq.count = 0; + bufreq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + ret = ioctl(m_nDriver_fd, VIDIOC_REQBUFS, &bufreq); + + if (ret) { + DEBUG_PRINT_ERROR("\nERROR: VIDIOC_REQBUFS CAPTURE MPLANE Failed \n "); + return false; + } } - if (!rc) { + if (!rc && !ret) { venc_stop_done(); stopped = 1; } -- cgit v1.2.3 From 2e277fbebd51de1d4f029f7950ed2a98731177dc Mon Sep 17 00:00:00 2001 From: Arun Menon Date: Thu, 29 Aug 2013 18:16:51 +0800 Subject: mm-video: venc: switch between executing and loaded. when the v4l2 modules stopped, it will free all output and input buffers. So when it is re-started again, re-do the VIDIOC_REQBUFS command again. b/11051201 Signed-off: Kim Zhang Change-Id: I7c6de237fdd7476ca4ebc7d1f1016e86f3af9d95 --- .../vidc/venc/inc/video_encoder_device_v4l2.h | 3 ++ .../vidc/venc/src/video_encoder_device_v4l2.cpp | 35 +++++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h b/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h index 7b4b250f..557ba2c3 100755 --- a/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h +++ b/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h @@ -251,6 +251,7 @@ class venc_dev }; int stopped; + int resume_in_stopped; bool m_max_allowed_bitrate_check; pthread_t m_tid; bool async_thread_created; @@ -300,6 +301,8 @@ class venc_dev bool venc_set_slice_delivery_mode(OMX_U32 enable); bool venc_set_extradata(OMX_U32 extra_data); bool venc_set_idr_period(OMX_U32 nPFrames, OMX_U32 nIDRPeriod); + bool venc_reconfig_reqbufs(); + #ifdef MAX_RES_1080P OMX_U32 pmem_free(); OMX_U32 pmem_allocate(OMX_U32 size, OMX_U32 alignment, OMX_U32 count); diff --git a/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp b/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp index 98443b76..7dcfcb44 100755 --- a/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp +++ b/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp @@ -677,6 +677,7 @@ bool venc_dev::venc_open(OMX_U32 codec) m_sOutput_buff_property.mincount = m_sOutput_buff_property.actualcount = bufreq.count; + resume_in_stopped = 0; metadatamode = 0; control.id = V4L2_CID_MPEG_VIDEO_HEADER_MODE; @@ -1491,6 +1492,9 @@ unsigned venc_dev::venc_stop( void) if (!rc && !ret) { venc_stop_done(); stopped = 1; + /*set flag to re-configure when started again*/ + resume_in_stopped = 1; + } } @@ -1558,6 +1562,12 @@ unsigned venc_dev::venc_start(void) venc_config_print(); + if(resume_in_stopped){ + /*set buffercount when restarted*/ + venc_reconfig_reqbufs(); + resume_in_stopped = 0; + } + /* Check if slice_delivery mode is enabled & max slices is sufficient for encoding complete frame */ if (slice_mode.enable && multislice.mslice_size && (m_sVenc_cfg.input_width * m_sVenc_cfg.input_height)/(256 * multislice.mslice_size) >= MAX_SUPPORTED_SLICES_PER_FRAME) { @@ -1611,6 +1621,29 @@ void venc_dev::venc_config_print() } +bool venc_dev::venc_reconfig_reqbufs() +{ + struct v4l2_requestbuffers bufreq; + + bufreq.memory = V4L2_MEMORY_USERPTR; + bufreq.count = m_sInput_buff_property.actualcount; + bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + if(ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq)) { + DEBUG_PRINT_ERROR("\n VIDIOC_REQBUFS OUTPUT_MPLANE Failed when resume\n"); + return false; + } + + bufreq.memory = V4L2_MEMORY_USERPTR; + bufreq.count = m_sOutput_buff_property.actualcount; + bufreq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + if(ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq)) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting o/p buffer count failed when resume\n"); + return false; + } + return true; +} + unsigned venc_dev::venc_flush( unsigned port) { struct v4l2_encoder_cmd enc; @@ -2544,7 +2577,7 @@ bool venc_dev::venc_set_entropy_config(OMX_BOOL enable, OMX_U32 i_cabac_level) } DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d\n", control.id, control.value); - entropy.longentropysel=control.value; + entropy.cabacmodel=control.value; } else if (!enable) { control.value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC; control.id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE; -- cgit v1.2.3 From cf8408186605323a6797e5f431192ab434e79fff Mon Sep 17 00:00:00 2001 From: Arun Menon Date: Wed, 30 Oct 2013 17:07:23 -0700 Subject: mm-video: vidc: venc: add set ctrl to request sequence header The omx component can explicitly request for sequence header using the set ctrl id - V4L2_CID_MPEG_VIDC_VIDEO_REQUEST_SEQ_HEADER. The omx component should not rely on the driver to send sequence header on it's own. b/11051201 Change-Id: Ie5c2adc11c15b84a7f659d75357a09b7758ea199 --- mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) mode change 100755 => 100644 mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp diff --git a/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp b/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp old mode 100755 new mode 100644 index 7dcfcb44..ef7de6f5 --- a/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp +++ b/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp @@ -1549,7 +1549,9 @@ unsigned venc_dev::venc_start(void) { enum v4l2_buf_type buf_type; int ret,r; - DEBUG_PRINT_HIGH("\n %s(): Check Profile/Level set in driver before start", + struct v4l2_control control = {0}; + + DEBUG_PRINT_HIGH("%s(): Check Profile/Level set in driver before start", __func__); if (!venc_set_profile_level(0, 0)) { @@ -1585,6 +1587,15 @@ unsigned venc_dev::venc_start(void) return 1; streaming[CAPTURE_PORT] = true; + + control.id = V4L2_CID_MPEG_VIDC_VIDEO_REQUEST_SEQ_HEADER; + control.value = 1; + ret = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); + if (ret) { + DEBUG_PRINT_ERROR("failed to request seq header"); + return 1; + } + stopped = 0; return 0; } -- cgit v1.2.3