| /*-------------------------------------------------------------------------- |
| Copyright (c) 2010-2012, Code Aurora Forum. 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 Code Aurora 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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. |
| --------------------------------------------------------------------------*/ |
| |
| /*============================================================================ |
| O p e n M A X w r a p p e r s |
| O p e n M A X C o r e |
| |
| *//** @file omx_vdec.cpp |
| This module contains the implementation of the OpenMAX core & component. |
| |
| *//*========================================================================*/ |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // Include Files |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| #include <string.h> |
| #include <pthread.h> |
| #include <sys/prctl.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <errno.h> |
| #include "omx_vdec.h" |
| #include <fcntl.h> |
| #include <limits.h> |
| #include <qdMetaData.h> |
| |
| #ifndef _ANDROID_ |
| #include <sys/ioctl.h> |
| #include <sys/mman.h> |
| #endif //_ANDROID_ |
| |
| #ifdef _ANDROID_ |
| #include <cutils/properties.h> |
| #undef USE_EGL_IMAGE_GPU |
| #endif |
| |
| #if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_) |
| #include <gralloc_priv.h> |
| #endif |
| |
| #ifdef _ANDROID_ |
| #include "DivXDrmDecrypt.h" |
| #endif //_ANDROID_ |
| |
| #ifdef USE_EGL_IMAGE_GPU |
| #include <EGL/egl.h> |
| #include <EGL/eglQCOM.h> |
| #define EGL_BUFFER_HANDLE_QCOM 0x4F00 |
| #define EGL_BUFFER_OFFSET_QCOM 0x4F01 |
| #endif |
| |
| #ifdef INPUT_BUFFER_LOG |
| #define INPUT_BUFFER_FILE_NAME "/data/input-bitstream.\0\0\0\0" |
| #define INPUT_BUFFER_FILE_NAME_LEN 30 |
| FILE *inputBufferFile1; |
| char inputfilename [INPUT_BUFFER_FILE_NAME_LEN] = "\0"; |
| #endif |
| #ifdef OUTPUT_BUFFER_LOG |
| FILE *outputBufferFile1; |
| char outputfilename [] = "/data/output.yuv"; |
| #endif |
| #ifdef OUTPUT_EXTRADATA_LOG |
| FILE *outputExtradataFile; |
| char ouputextradatafilename [] = "/data/extradata"; |
| #endif |
| |
| #define DEFAULT_FPS 30 |
| #define MAX_NUM_SPS 32 |
| #define MAX_NUM_PPS 256 |
| #define MAX_INPUT_ERROR (MAX_NUM_SPS + MAX_NUM_PPS) |
| #define MAX_SUPPORTED_FPS 120 |
| |
| #define VC1_SP_MP_START_CODE 0xC5000000 |
| #define VC1_SP_MP_START_CODE_MASK 0xFF000000 |
| #define VC1_AP_SEQ_START_CODE 0x0F010000 |
| #define VC1_STRUCT_C_PROFILE_MASK 0xF0 |
| #define VC1_STRUCT_B_LEVEL_MASK 0xE0000000 |
| #define VC1_SIMPLE_PROFILE 0 |
| #define VC1_MAIN_PROFILE 1 |
| #define VC1_ADVANCE_PROFILE 3 |
| #define VC1_SIMPLE_PROFILE_LOW_LEVEL 0 |
| #define VC1_SIMPLE_PROFILE_MED_LEVEL 2 |
| #define VC1_STRUCT_C_LEN 4 |
| #define VC1_STRUCT_C_POS 8 |
| #define VC1_STRUCT_A_POS 12 |
| #define VC1_STRUCT_B_POS 24 |
| #define VC1_SEQ_LAYER_SIZE 36 |
| |
| #ifdef USE_ION |
| #define MEM_DEVICE "/dev/ion" |
| #define MEM_HEAP_ID ION_CP_MM_HEAP_ID |
| #elif MAX_RES_720P |
| #define MEM_DEVICE "/dev/pmem_adsp" |
| #elif MAX_RES_1080P_EBI |
| #define MEM_DEVICE "/dev/pmem_adsp" |
| #elif MAX_RES_1080P |
| #define MEM_DEVICE "/dev/pmem_smipool" |
| #endif |
| |
| /* |
| #ifdef _ANDROID_ |
| extern "C"{ |
| #include<utils/Log.h> |
| } |
| #endif//_ANDROID_ |
| */ |
| |
| #undef DEBUG_PRINT_LOW |
| #undef DEBUG_PRINT_HIGH |
| #undef DEBUG_PRINT_ERROR |
| |
| #define DEBUG_PRINT_LOW ALOGV |
| #define DEBUG_PRINT_HIGH ALOGV |
| #define DEBUG_PRINT_ERROR ALOGE |
| |
| #ifndef _ANDROID_ |
| #include <glib.h> |
| #define strlcpy g_strlcpy |
| #endif |
| |
| #define Log2(number, power) { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) && power < 16) { temp >>=0x1; power++; } } |
| #define Q16ToFraction(q,num,den) { OMX_U32 power; Log2(q,power); num = q >> power; den = 0x1 << (16 - power); } |
| |
| bool omx_vdec::m_secure_display = false; |
| |
| #ifdef MAX_RES_1080P |
| static const OMX_U32 kMaxSmoothStreamingWidth = 1920; |
| static const OMX_U32 kMaxSmoothStreamingHeight = 1088; |
| #else |
| static const OMX_U32 kMaxSmoothStreamingWidth = 1280; |
| static const OMX_U32 kMaxSmoothStreamingHeight = 720; |
| #endif |
| |
| void* async_message_thread (void *input) |
| { |
| struct vdec_ioctl_msg ioctl_msg; |
| struct vdec_msginfo vdec_msg; |
| omx_vdec *omx = reinterpret_cast<omx_vdec*>(input); |
| int error_code = 0; |
| DEBUG_PRINT_HIGH("omx_vdec: Async thread start\n"); |
| prctl(PR_SET_NAME, (unsigned long)"VideoDecCallBackThread", 0, 0, 0); |
| while (1) |
| { |
| ioctl_msg.in = NULL; |
| ioctl_msg.out = (void*)&vdec_msg; |
| /*Wait for a message from the video decoder driver*/ |
| error_code = ioctl ( omx->drv_ctx.video_driver_fd,VDEC_IOCTL_GET_NEXT_MSG, |
| (void*)&ioctl_msg); |
| if (error_code == -512) // ERESTARTSYS |
| { |
| DEBUG_PRINT_ERROR("\n ERESTARTSYS received in ioctl read next msg!"); |
| } |
| else if (error_code < 0) |
| { |
| DEBUG_PRINT_ERROR("\n Error in ioctl read next msg"); |
| break; |
| } /*Call Instance specific process function*/ |
| else if (omx->async_message_process(input,&vdec_msg) < 0) |
| { |
| DEBUG_PRINT_ERROR("\nERROR:Wrong ioctl message"); |
| } |
| } |
| DEBUG_PRINT_HIGH("omx_vdec: Async thread stop\n"); |
| return NULL; |
| } |
| |
| void* message_thread(void *input) |
| { |
| omx_vdec* omx = reinterpret_cast<omx_vdec*>(input); |
| unsigned char id; |
| int n; |
| |
| DEBUG_PRINT_HIGH("omx_vdec: message thread start\n"); |
| prctl(PR_SET_NAME, (unsigned long)"VideoDecMsgThread", 0, 0, 0); |
| while (1) |
| { |
| |
| n = read(omx->m_pipe_in, &id, 1); |
| |
| if(0 == n) |
| { |
| break; |
| } |
| |
| if (1 == n) |
| { |
| omx->process_event_cb(omx, id); |
| } |
| if ((n < 0) && (errno != EINTR)) |
| { |
| DEBUG_PRINT_ERROR("\nERROR: read from pipe failed, ret %d errno %d", n, errno); |
| break; |
| } |
| } |
| DEBUG_PRINT_HIGH("omx_vdec: message thread stop\n"); |
| return 0; |
| } |
| |
| void post_message(omx_vdec *omx, unsigned char id) |
| { |
| int ret_value; |
| DEBUG_PRINT_LOW("omx_vdec: post_message %d pipe out%d\n", id,omx->m_pipe_out); |
| ret_value = write(omx->m_pipe_out, &id, 1); |
| DEBUG_PRINT_LOW("post_message to pipe done %d\n",ret_value); |
| } |
| |
| // omx_cmd_queue destructor |
| omx_vdec::omx_cmd_queue::~omx_cmd_queue() |
| { |
| // Nothing to do |
| } |
| |
| // omx cmd queue constructor |
| omx_vdec::omx_cmd_queue::omx_cmd_queue(): m_read(0),m_write(0),m_size(0) |
| { |
| memset(m_q,0,sizeof(omx_event)*OMX_CORE_CONTROL_CMDQ_SIZE); |
| } |
| |
| // omx cmd queue insert |
| bool omx_vdec::omx_cmd_queue::insert_entry(unsigned p1, unsigned p2, unsigned id) |
| { |
| bool ret = true; |
| if(m_size < OMX_CORE_CONTROL_CMDQ_SIZE) |
| { |
| m_q[m_write].id = id; |
| m_q[m_write].param1 = p1; |
| m_q[m_write].param2 = p2; |
| m_write++; |
| m_size ++; |
| if(m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) |
| { |
| m_write = 0; |
| } |
| } |
| else |
| { |
| ret = false; |
| DEBUG_PRINT_ERROR("ERROR: %s()::Command Queue Full\n", __func__); |
| } |
| return ret; |
| } |
| |
| // omx cmd queue pop |
| bool omx_vdec::omx_cmd_queue::pop_entry(unsigned *p1, unsigned *p2, unsigned *id) |
| { |
| bool ret = true; |
| if (m_size > 0) |
| { |
| *id = m_q[m_read].id; |
| *p1 = m_q[m_read].param1; |
| *p2 = m_q[m_read].param2; |
| // Move the read pointer ahead |
| ++m_read; |
| --m_size; |
| if(m_read >= OMX_CORE_CONTROL_CMDQ_SIZE) |
| { |
| m_read = 0; |
| } |
| } |
| else |
| { |
| ret = false; |
| } |
| return ret; |
| } |
| |
| // Retrieve the first mesg type in the queue |
| unsigned omx_vdec::omx_cmd_queue::get_q_msg_type() |
| { |
| return m_q[m_read].id; |
| } |
| |
| #ifdef _ANDROID_ |
| omx_vdec::ts_arr_list::ts_arr_list() |
| { |
| //initialize timestamps array |
| memset(m_ts_arr_list, 0, ( sizeof(ts_entry) * MAX_NUM_INPUT_OUTPUT_BUFFERS) ); |
| } |
| omx_vdec::ts_arr_list::~ts_arr_list() |
| { |
| //free m_ts_arr_list? |
| } |
| |
| bool omx_vdec::ts_arr_list::insert_ts(OMX_TICKS ts) |
| { |
| bool ret = true; |
| bool duplicate_ts = false; |
| int idx = 0; |
| |
| //insert at the first available empty location |
| for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) |
| { |
| if (!m_ts_arr_list[idx].valid) |
| { |
| //found invalid or empty entry, save timestamp |
| m_ts_arr_list[idx].valid = true; |
| m_ts_arr_list[idx].timestamp = ts; |
| DEBUG_PRINT_LOW("Insert_ts(): Inserting TIMESTAMP (%lld) at idx (%d)", |
| ts, idx); |
| break; |
| } |
| } |
| |
| if (idx == MAX_NUM_INPUT_OUTPUT_BUFFERS) |
| { |
| DEBUG_PRINT_LOW("Timestamp array list is FULL. Unsuccessful insert"); |
| ret = false; |
| } |
| return ret; |
| } |
| |
| bool omx_vdec::ts_arr_list::pop_min_ts(OMX_TICKS &ts) |
| { |
| bool ret = true; |
| int min_idx = -1; |
| OMX_TICKS min_ts = 0; |
| int idx = 0; |
| |
| for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) |
| { |
| |
| if (m_ts_arr_list[idx].valid) |
| { |
| //found valid entry, save index |
| if (min_idx < 0) |
| { |
| //first valid entry |
| min_ts = m_ts_arr_list[idx].timestamp; |
| min_idx = idx; |
| } |
| else if (m_ts_arr_list[idx].timestamp < min_ts) |
| { |
| min_ts = m_ts_arr_list[idx].timestamp; |
| min_idx = idx; |
| } |
| } |
| |
| } |
| |
| if (min_idx < 0) |
| { |
| //no valid entries found |
| DEBUG_PRINT_LOW("Timestamp array list is empty. Unsuccessful pop"); |
| ts = 0; |
| ret = false; |
| } |
| else |
| { |
| ts = m_ts_arr_list[min_idx].timestamp; |
| m_ts_arr_list[min_idx].valid = false; |
| DEBUG_PRINT_LOW("Pop_min_ts:Timestamp (%lld), index(%d)", |
| ts, min_idx); |
| } |
| |
| return ret; |
| |
| } |
| |
| |
| bool omx_vdec::ts_arr_list::reset_ts_list() |
| { |
| bool ret = true; |
| int idx = 0; |
| |
| DEBUG_PRINT_LOW("reset_ts_list(): Resetting timestamp array list"); |
| for ( ; idx < MAX_NUM_INPUT_OUTPUT_BUFFERS; idx++) |
| { |
| m_ts_arr_list[idx].valid = false; |
| } |
| return ret; |
| } |
| #endif |
| |
| // factory function executed by the core to create instances |
| void *get_omx_component_factory_fn(void) |
| { |
| return (new omx_vdec); |
| } |
| |
| #ifdef _ANDROID_ |
| #ifdef USE_ION |
| VideoHeap::VideoHeap(int devicefd, size_t size, void* base, |
| struct ion_handle *handle, int ionMapfd) |
| { |
| m_ion_device_fd = devicefd; |
| m_ion_handle = handle; |
| MemoryHeapBase::init(ionMapfd, base, size, 0, MEM_DEVICE); |
| //ionInit(devicefd, base, size, 0 , MEM_DEVICE,handle,ionMapfd); |
| } |
| #else |
| VideoHeap::VideoHeap(int fd, size_t size, void* base) |
| { |
| // dup file descriptor, map once, use pmem |
| init(dup(fd), base, size, 0 , MEM_DEVICE); |
| } |
| #endif |
| #endif // _ANDROID_ |
| /* ====================================================================== |
| FUNCTION |
| omx_vdec::omx_vdec |
| |
| DESCRIPTION |
| Constructor |
| |
| PARAMETERS |
| None |
| |
| RETURN VALUE |
| None. |
| ========================================================================== */ |
| omx_vdec::omx_vdec(): m_state(OMX_StateInvalid), |
| m_app_data(NULL), |
| m_inp_mem_ptr(NULL), |
| m_out_mem_ptr(NULL), |
| m_phdr_pmem_ptr(NULL), |
| pending_input_buffers(0), |
| pending_output_buffers(0), |
| m_out_bm_count(0), |
| m_inp_bm_count(0), |
| m_inp_bPopulated(OMX_FALSE), |
| m_out_bPopulated(OMX_FALSE), |
| m_flags(0), |
| m_inp_bEnabled(OMX_TRUE), |
| m_out_bEnabled(OMX_TRUE), |
| m_platform_list(NULL), |
| m_platform_entry(NULL), |
| m_pmem_info(NULL), |
| output_flush_progress (false), |
| input_flush_progress (false), |
| input_use_buffer (false), |
| output_use_buffer (false), |
| arbitrary_bytes (true), |
| psource_frame (NULL), |
| pdest_frame (NULL), |
| m_inp_heap_ptr (NULL), |
| m_heap_inp_bm_count (0), |
| codec_type_parse ((codec_type)0), |
| first_frame_meta (true), |
| frame_count (0), |
| nal_length(0), |
| nal_count (0), |
| look_ahead_nal (false), |
| first_frame(0), |
| first_buffer(NULL), |
| first_frame_size (0), |
| m_error_propogated(false), |
| m_device_file_ptr(NULL), |
| m_vc1_profile((vc1_profile_type)0), |
| prev_ts(LLONG_MAX), |
| rst_prev_ts(true), |
| frm_int(0), |
| m_in_alloc_cnt(0), |
| m_display_id(NULL), |
| ouput_egl_buffers(false), |
| h264_parser(NULL), |
| client_extradata(0), |
| h264_last_au_ts(LLONG_MAX), |
| h264_last_au_flags(0), |
| m_inp_err_count(0), |
| #ifdef _ANDROID_ |
| m_heap_ptr(NULL), |
| m_heap_count(0), |
| m_enable_android_native_buffers(OMX_FALSE), |
| m_use_android_native_buffers(OMX_FALSE), |
| #endif |
| in_reconfig(false), |
| m_use_output_pmem(OMX_FALSE), |
| m_out_mem_region_smi(OMX_FALSE), |
| m_out_pvt_entry_pmem(OMX_FALSE), |
| secure_mode(false) |
| #ifdef _ANDROID_ |
| ,iDivXDrmDecrypt(NULL) |
| #endif |
| ,m_desc_buffer_ptr(NULL) |
| ,m_extradata(NULL) |
| ,m_use_smoothstreaming(false) |
| ,m_smoothstreaming_height(0) |
| ,m_smoothstreaming_width(0) |
| { |
| /* Assumption is that , to begin with , we have all the frames with decoder */ |
| DEBUG_PRINT_HIGH("In OMX vdec Constructor"); |
| #ifdef _ANDROID_ |
| char property_value[PROPERTY_VALUE_MAX] = {0}; |
| property_get("vidc.dec.debug.perf", property_value, "0"); |
| perf_flag = atoi(property_value); |
| if (perf_flag) |
| { |
| DEBUG_PRINT_HIGH("vidc.dec.debug.perf is %d", perf_flag); |
| dec_time.start(); |
| proc_frms = latency = 0; |
| } |
| property_value[0] = NULL; |
| property_get("vidc.dec.debug.ts", property_value, "0"); |
| m_debug_timestamp = atoi(property_value); |
| DEBUG_PRINT_HIGH("vidc.dec.debug.ts value is %d",m_debug_timestamp); |
| if (m_debug_timestamp) |
| { |
| time_stamp_dts.set_timestamp_reorder_mode(true); |
| time_stamp_dts.enable_debug_print(true); |
| } |
| |
| property_value[0] = NULL; |
| property_get("vidc.dec.debug.concealedmb", property_value, "0"); |
| m_debug_concealedmb = atoi(property_value); |
| DEBUG_PRINT_HIGH("vidc.dec.debug.concealedmb value is %d",m_debug_concealedmb); |
| |
| #endif |
| memset(&m_cmp,0,sizeof(m_cmp)); |
| memset(&m_cb,0,sizeof(m_cb)); |
| memset (&drv_ctx,0,sizeof(drv_ctx)); |
| memset (&h264_scratch,0,sizeof (OMX_BUFFERHEADERTYPE)); |
| memset (m_hwdevice_name,0,sizeof(m_hwdevice_name)); |
| memset(&op_buf_rcnfg, 0 ,sizeof(vdec_allocatorproperty)); |
| memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) ); |
| m_demux_entries = 0; |
| drv_ctx.timestamp_adjust = false; |
| drv_ctx.video_driver_fd = -1; |
| m_vendor_config.pData = NULL; |
| pthread_mutex_init(&m_lock, NULL); |
| pthread_mutex_init(&c_lock, NULL); |
| sem_init(&m_cmd_lock,0,0); |
| #ifdef _ANDROID_ |
| char extradata_value[PROPERTY_VALUE_MAX] = {0}; |
| property_get("vidc.dec.debug.extradata", extradata_value, "0"); |
| m_debug_extradata = atoi(extradata_value); |
| DEBUG_PRINT_HIGH("vidc.dec.debug.extradata value is %d",m_debug_extradata); |
| #endif |
| m_fill_output_msg = OMX_COMPONENT_GENERATE_FTB; |
| client_buffers.set_vdec_client(this); |
| memset(native_buffer, 0, sizeof(native_buffer)); |
| } |
| |
| |
| /* ====================================================================== |
| FUNCTION |
| omx_vdec::~omx_vdec |
| |
| DESCRIPTION |
| Destructor |
| |
| PARAMETERS |
| None |
| |
| RETURN VALUE |
| None. |
| ========================================================================== */ |
| omx_vdec::~omx_vdec() |
| { |
| m_pmem_info = NULL; |
| DEBUG_PRINT_HIGH("In OMX vdec Destructor"); |
| if(m_pipe_in) close(m_pipe_in); |
| if(m_pipe_out) close(m_pipe_out); |
| m_pipe_in = -1; |
| m_pipe_out = -1; |
| DEBUG_PRINT_HIGH("Waiting on OMX Msg Thread exit"); |
| pthread_join(msg_thread_id,NULL); |
| DEBUG_PRINT_HIGH("Waiting on OMX Async Thread exit"); |
| pthread_join(async_thread_id,NULL); |
| pthread_mutex_destroy(&m_lock); |
| pthread_mutex_destroy(&c_lock); |
| sem_destroy(&m_cmd_lock); |
| #ifdef _ANDROID_ |
| if (perf_flag) |
| { |
| DEBUG_PRINT_HIGH("--> TOTAL PROCESSING TIME"); |
| dec_time.end(); |
| } |
| #endif /* _ANDROID_ */ |
| DEBUG_PRINT_HIGH("Exit OMX vdec Destructor"); |
| } |
| |
| /* ====================================================================== |
| FUNCTION |
| omx_vdec::OMXCntrlProcessMsgCb |
| |
| DESCRIPTION |
| IL Client callbacks are generated through this routine. The decoder |
| provides the thread context for this routine. |
| |
| PARAMETERS |
| ctxt -- Context information related to the self. |
| id -- Event identifier. This could be any of the following: |
| 1. Command completion event |
| 2. Buffer done callback event |
| 3. Frame done callback event |
| |
| RETURN VALUE |
| None. |
| |
| ========================================================================== */ |
| void omx_vdec::process_event_cb(void *ctxt, unsigned char id) |
| { |
| unsigned p1; // Parameter - 1 |
| unsigned p2; // Parameter - 2 |
| unsigned ident; |
| unsigned qsize=0; // qsize |
| omx_vdec *pThis = (omx_vdec *) ctxt; |
| |
| if(!pThis) |
| { |
| DEBUG_PRINT_ERROR("ERROR: %s()::Context is incorrect, bailing out\n", |
| __func__); |
| return; |
| } |
| |
| // Protect the shared queue data structure |
| do |
| { |
| /*Read the message id's from the queue*/ |
| pthread_mutex_lock(&pThis->m_lock); |
| qsize = pThis->m_cmd_q.m_size; |
| if(qsize) |
| { |
| pThis->m_cmd_q.pop_entry(&p1,&p2,&ident); |
| } |
| |
| if (qsize == 0 && pThis->m_state != OMX_StatePause) |
| { |
| qsize = pThis->m_ftb_q.m_size; |
| if (qsize) |
| { |
| pThis->m_ftb_q.pop_entry(&p1,&p2,&ident); |
| } |
| } |
| |
| if (qsize == 0 && pThis->m_state != OMX_StatePause) |
| { |
| qsize = pThis->m_etb_q.m_size; |
| if (qsize) |
| { |
| pThis->m_etb_q.pop_entry(&p1,&p2,&ident); |
| } |
| } |
| pthread_mutex_unlock(&pThis->m_lock); |
| |
| /*process message if we have one*/ |
| if(qsize > 0) |
| { |
| id = ident; |
| switch (id) |
| { |
| case OMX_COMPONENT_GENERATE_EVENT: |
| if (pThis->m_cb.EventHandler) |
| { |
| switch (p1) |
| { |
| case OMX_CommandStateSet: |
| pThis->m_state = (OMX_STATETYPE) p2; |
| DEBUG_PRINT_HIGH("\n OMX_CommandStateSet complete, m_state = %d", |
| pThis->m_state); |
| pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, |
| OMX_EventCmdComplete, p1, p2, NULL); |
| break; |
| |
| case OMX_EventError: |
| if(p2 == OMX_StateInvalid) |
| { |
| DEBUG_PRINT_ERROR("\n OMX_EventError: p2 is OMX_StateInvalid"); |
| pThis->m_state = (OMX_STATETYPE) p2; |
| pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, |
| OMX_EventError, OMX_ErrorInvalidState, p2, NULL); |
| } |
| else if (p2 == OMX_ErrorHardware) |
| { |
| pThis->omx_report_error(); |
| } |
| else |
| { |
| pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, |
| OMX_EventError, p2, NULL, NULL ); |
| } |
| break; |
| |
| case OMX_CommandPortDisable: |
| DEBUG_PRINT_HIGH("\n OMX_CommandPortDisable complete for port [%d]", p2); |
| if (BITMASK_PRESENT(&pThis->m_flags, |
| OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) |
| { |
| BITMASK_SET(&pThis->m_flags, OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED); |
| break; |
| } |
| if (p2 == OMX_CORE_OUTPUT_PORT_INDEX && pThis->in_reconfig) |
| { |
| pThis->in_reconfig = false; |
| pThis->drv_ctx.op_buf = pThis->op_buf_rcnfg; |
| OMX_ERRORTYPE eRet = pThis->set_buffer_req(&pThis->drv_ctx.op_buf); |
| if(eRet != OMX_ErrorNone) |
| { |
| DEBUG_PRINT_ERROR("set_buffer_req failed eRet = %d",eRet); |
| pThis->omx_report_error(); |
| break; |
| } |
| } |
| pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, |
| OMX_EventCmdComplete, p1, p2, NULL ); |
| break; |
| case OMX_CommandPortEnable: |
| DEBUG_PRINT_HIGH("\n OMX_CommandPortEnable complete for port [%d]", p2); |
| pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,\ |
| OMX_EventCmdComplete, p1, p2, NULL ); |
| break; |
| |
| default: |
| pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, |
| OMX_EventCmdComplete, p1, p2, NULL ); |
| break; |
| |
| } |
| } |
| else |
| { |
| DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL\n", __func__); |
| } |
| break; |
| case OMX_COMPONENT_GENERATE_ETB_ARBITRARY: |
| if (pThis->empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\ |
| (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) |
| { |
| DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy_arbitrary failure"); |
| pThis->omx_report_error (); |
| } |
| break; |
| case OMX_COMPONENT_GENERATE_ETB: |
| if (pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1,\ |
| (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) |
| { |
| DEBUG_PRINT_ERROR("\n empty_this_buffer_proxy failure"); |
| pThis->omx_report_error (); |
| } |
| break; |
| |
| case OMX_COMPONENT_GENERATE_FTB: |
| if ( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)p1,\ |
| (OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) |
| { |
| DEBUG_PRINT_ERROR("\n fill_this_buffer_proxy failure"); |
| pThis->omx_report_error (); |
| } |
| break; |
| |
| case OMX_COMPONENT_GENERATE_COMMAND: |
| pThis->send_command_proxy(&pThis->m_cmp,(OMX_COMMANDTYPE)p1,\ |
| (OMX_U32)p2,(OMX_PTR)NULL); |
| break; |
| |
| case OMX_COMPONENT_GENERATE_EBD: |
| |
| if (p2 != VDEC_S_SUCCESS && p2 != VDEC_S_INPUT_BITSTREAM_ERR) |
| { |
| DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_EBD failure"); |
| pThis->omx_report_error (); |
| } |
| else |
| { |
| if (p2 == VDEC_S_INPUT_BITSTREAM_ERR && p1) |
| { |
| pThis->m_inp_err_count++; |
| pThis->time_stamp_dts.remove_time_stamp( |
| ((OMX_BUFFERHEADERTYPE *)p1)->nTimeStamp, |
| (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive) |
| ?true:false); |
| } |
| else |
| { |
| pThis->m_inp_err_count = 0; |
| } |
| if ( pThis->empty_buffer_done(&pThis->m_cmp, |
| (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) |
| { |
| DEBUG_PRINT_ERROR("\n empty_buffer_done failure"); |
| pThis->omx_report_error (); |
| } |
| if(!pThis->arbitrary_bytes && pThis->m_inp_err_count > MAX_INPUT_ERROR) |
| { |
| DEBUG_PRINT_ERROR("\n Input bitstream error for consecutive %d frames.", MAX_INPUT_ERROR); |
| pThis->omx_report_error (); |
| } |
| } |
| break; |
| case OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED: |
| { |
| int64_t *timestamp = (int64_t *)p1; |
| if (p1) |
| { |
| pThis->time_stamp_dts.remove_time_stamp(*timestamp, |
| (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive) |
| ?true:false); |
| free(timestamp); |
| } |
| } |
| break; |
| case OMX_COMPONENT_GENERATE_FBD: |
| if (p2 != VDEC_S_SUCCESS) |
| { |
| DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_FBD failure"); |
| pThis->omx_report_error (); |
| } |
| else if ( pThis->fill_buffer_done(&pThis->m_cmp, |
| (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) |
| { |
| DEBUG_PRINT_ERROR("\n fill_buffer_done failure"); |
| pThis->omx_report_error (); |
| } |
| break; |
| |
| case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH: |
| DEBUG_PRINT_HIGH("\n Driver flush i/p Port complete"); |
| if (!pThis->input_flush_progress) |
| { |
| DEBUG_PRINT_ERROR("\n WARNING: Unexpected flush from driver"); |
| } |
| else |
| { |
| pThis->execute_input_flush(); |
| if (pThis->m_cb.EventHandler) |
| { |
| if (p2 != VDEC_S_SUCCESS) |
| { |
| DEBUG_PRINT_ERROR("\nOMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH failure"); |
| pThis->omx_report_error (); |
| } |
| else |
| { |
| /*Check if we need generate event for Flush done*/ |
| if(BITMASK_PRESENT(&pThis->m_flags, |
| OMX_COMPONENT_INPUT_FLUSH_PENDING)) |
| { |
| BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_INPUT_FLUSH_PENDING); |
| DEBUG_PRINT_LOW("\n Input Flush completed - Notify Client"); |
| pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, |
| OMX_EventCmdComplete,OMX_CommandFlush, |
| OMX_CORE_INPUT_PORT_INDEX,NULL ); |
| } |
| if (BITMASK_PRESENT(&pThis->m_flags, |
| OMX_COMPONENT_IDLE_PENDING)) |
| { |
| if (!pThis->output_flush_progress) |
| { |
| DEBUG_PRINT_LOW("\n Output flush done hence issue stop"); |
| if (ioctl (pThis->drv_ctx.video_driver_fd, |
| VDEC_IOCTL_CMD_STOP,NULL ) < 0) |
| { |
| DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_STOP failed"); |
| pThis->omx_report_error (); |
| } |
| } |
| } |
| } |
| } |
| else |
| { |
| DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); |
| } |
| } |
| break; |
| |
| case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH: |
| DEBUG_PRINT_HIGH("\n Driver flush o/p Port complete"); |
| if (!pThis->output_flush_progress) |
| { |
| DEBUG_PRINT_ERROR("\n WARNING: Unexpected flush from driver"); |
| } |
| else |
| { |
| pThis->execute_output_flush(); |
| if (pThis->m_cb.EventHandler) |
| { |
| if (p2 != VDEC_S_SUCCESS) |
| { |
| DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH failed"); |
| pThis->omx_report_error (); |
| } |
| else |
| { |
| /*Check if we need generate event for Flush done*/ |
| if(BITMASK_PRESENT(&pThis->m_flags, |
| OMX_COMPONENT_OUTPUT_FLUSH_PENDING)) |
| { |
| DEBUG_PRINT_LOW("\n Notify Output Flush done"); |
| BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING); |
| pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, |
| OMX_EventCmdComplete,OMX_CommandFlush, |
| OMX_CORE_OUTPUT_PORT_INDEX,NULL ); |
| } |
| if(BITMASK_PRESENT(&pThis->m_flags, |
| OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING)) |
| { |
| DEBUG_PRINT_LOW("\n Internal flush complete"); |
| BITMASK_CLEAR (&pThis->m_flags, |
| OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING); |
| if (BITMASK_PRESENT(&pThis->m_flags, |
| OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED)) |
| { |
| pThis->post_event(OMX_CommandPortDisable, |
| OMX_CORE_OUTPUT_PORT_INDEX, |
| OMX_COMPONENT_GENERATE_EVENT); |
| BITMASK_CLEAR (&pThis->m_flags, |
| OMX_COMPONENT_DISABLE_OUTPUT_DEFERRED); |
| |
| } |
| } |
| |
| if (BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING)) |
| { |
| if (!pThis->input_flush_progress) |
| { |
| DEBUG_PRINT_LOW("\n Input flush done hence issue stop"); |
| if (ioctl (pThis->drv_ctx.video_driver_fd, |
| VDEC_IOCTL_CMD_STOP,NULL ) < 0) |
| { |
| DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_STOP failed"); |
| pThis->omx_report_error (); |
| } |
| } |
| } |
| } |
| } |
| else |
| { |
| DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); |
| } |
| } |
| break; |
| |
| case OMX_COMPONENT_GENERATE_START_DONE: |
| DEBUG_PRINT_HIGH("\n Rxd OMX_COMPONENT_GENERATE_START_DONE"); |
| |
| if (pThis->m_cb.EventHandler) |
| { |
| if (p2 != VDEC_S_SUCCESS) |
| { |
| DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_START_DONE Failure"); |
| pThis->omx_report_error (); |
| } |
| else |
| { |
| DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_START_DONE Success"); |
| if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) |
| { |
| DEBUG_PRINT_LOW("\n Move to executing"); |
| // Send the callback now |
| BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING); |
| pThis->m_state = OMX_StateExecuting; |
| pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, |
| OMX_EventCmdComplete,OMX_CommandStateSet, |
| OMX_StateExecuting, NULL); |
| } |
| else if (BITMASK_PRESENT(&pThis->m_flags, |
| OMX_COMPONENT_PAUSE_PENDING)) |
| { |
| if (ioctl (pThis->drv_ctx.video_driver_fd, |
| VDEC_IOCTL_CMD_PAUSE,NULL ) < 0) |
| { |
| DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_PAUSE failed"); |
| pThis->omx_report_error (); |
| } |
| } |
| } |
| } |
| else |
| { |
| DEBUG_PRINT_LOW("\n Event Handler callback is NULL"); |
| } |
| break; |
| |
| case OMX_COMPONENT_GENERATE_PAUSE_DONE: |
| DEBUG_PRINT_HIGH("\n Rxd OMX_COMPONENT_GENERATE_PAUSE_DONE"); |
| if (pThis->m_cb.EventHandler) |
| { |
| if (p2 != VDEC_S_SUCCESS) |
| { |
| DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_PAUSE_DONE ret failed"); |
| pThis->omx_report_error (); |
| } |
| else |
| { |
| pThis->complete_pending_buffer_done_cbs(); |
| if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_PAUSE_PENDING)) |
| { |
| DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_PAUSE_DONE nofity"); |
| //Send the callback now |
| BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_PAUSE_PENDING); |
| pThis->m_state = OMX_StatePause; |
| pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, |
| OMX_EventCmdComplete,OMX_CommandStateSet, |
| OMX_StatePause, NULL); |
| } |
| } |
| } |
| else |
| { |
| DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); |
| } |
| |
| break; |
| |
| case OMX_COMPONENT_GENERATE_RESUME_DONE: |
| DEBUG_PRINT_HIGH("\n Rxd OMX_COMPONENT_GENERATE_RESUME_DONE"); |
| if (pThis->m_cb.EventHandler) |
| { |
| if (p2 != VDEC_S_SUCCESS) |
| { |
| DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_RESUME_DONE failed"); |
| pThis->omx_report_error (); |
| } |
| else |
| { |
| if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) |
| { |
| DEBUG_PRINT_LOW("\n Moving the decoder to execute state"); |
| // Send the callback now |
| BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING); |
| pThis->m_state = OMX_StateExecuting; |
| pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, |
| OMX_EventCmdComplete,OMX_CommandStateSet, |
| OMX_StateExecuting,NULL); |
| } |
| } |
| } |
| else |
| { |
| DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); |
| } |
| |
| break; |
| |
| case OMX_COMPONENT_GENERATE_STOP_DONE: |
| DEBUG_PRINT_HIGH("\n Rxd OMX_COMPONENT_GENERATE_STOP_DONE"); |
| if (pThis->m_cb.EventHandler) |
| { |
| if (p2 != VDEC_S_SUCCESS) |
| { |
| DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_STOP_DONE ret failed"); |
| pThis->omx_report_error (); |
| } |
| else |
| { |
| pThis->complete_pending_buffer_done_cbs(); |
| if(BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_IDLE_PENDING)) |
| { |
| DEBUG_PRINT_LOW("\n OMX_COMPONENT_GENERATE_STOP_DONE Success"); |
| // Send the callback now |
| BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_IDLE_PENDING); |
| pThis->m_state = OMX_StateIdle; |
| DEBUG_PRINT_LOW("\n Move to Idle State"); |
| pThis->m_cb.EventHandler(&pThis->m_cmp,pThis->m_app_data, |
| OMX_EventCmdComplete,OMX_CommandStateSet, |
| OMX_StateIdle,NULL); |
| } |
| } |
| } |
| else |
| { |
| DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); |
| } |
| |
| break; |
| |
| case OMX_COMPONENT_GENERATE_PORT_RECONFIG: |
| DEBUG_PRINT_HIGH("\n Rxd OMX_COMPONENT_GENERATE_PORT_RECONFIG"); |
| if (p2 == OMX_IndexParamPortDefinition && (pThis->start_port_reconfig() != OMX_ErrorNone)) |
| pThis->omx_report_error(); |
| else |
| { |
| if (pThis->m_cb.EventHandler) { |
| pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, |
| OMX_EventPortSettingsChanged, p1, p2, NULL ); |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); |
| } |
| if (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive) |
| { |
| OMX_INTERLACETYPE format = (OMX_INTERLACETYPE)-1; |
| OMX_EVENTTYPE event = (OMX_EVENTTYPE)OMX_EventIndexsettingChanged; |
| if (pThis->drv_ctx.interlace == VDEC_InterlaceInterleaveFrameTopFieldFirst) |
| format = OMX_InterlaceInterleaveFrameTopFieldFirst; |
| else if (pThis->drv_ctx.interlace == VDEC_InterlaceInterleaveFrameBottomFieldFirst) |
| format = OMX_InterlaceInterleaveFrameBottomFieldFirst; |
| else //unsupported interlace format; raise a error |
| event = OMX_EventError; |
| if (pThis->m_cb.EventHandler) { |
| pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, |
| event, format, 0, NULL ); |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); |
| } |
| } |
| } |
| break; |
| |
| case OMX_COMPONENT_GENERATE_EOS_DONE: |
| DEBUG_PRINT_HIGH("\n Rxd OMX_COMPONENT_GENERATE_EOS_DONE"); |
| if (pThis->m_cb.EventHandler) { |
| pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data, OMX_EventBufferFlag, |
| OMX_CORE_OUTPUT_PORT_INDEX, OMX_BUFFERFLAG_EOS, NULL ); |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__); |
| } |
| pThis->prev_ts = LLONG_MAX; |
| pThis->rst_prev_ts = true; |
| break; |
| |
| case OMX_COMPONENT_GENERATE_HARDWARE_ERROR: |
| DEBUG_PRINT_ERROR("\n OMX_COMPONENT_GENERATE_HARDWARE_ERROR"); |
| pThis->omx_report_error (); |
| break; |
| |
| default: |
| break; |
| } |
| } |
| pthread_mutex_lock(&pThis->m_lock); |
| qsize = pThis->m_cmd_q.m_size; |
| if (pThis->m_state != OMX_StatePause) |
| qsize += (pThis->m_ftb_q.m_size + pThis->m_etb_q.m_size); |
| pthread_mutex_unlock(&pThis->m_lock); |
| } |
| while(qsize>0); |
| |
| } |
| |
| void omx_vdec::update_resolution(int width, int height) |
| { |
| drv_ctx.video_resolution.frame_height = height; |
| drv_ctx.video_resolution.frame_width = width; |
| drv_ctx.video_resolution.scan_lines = height; |
| drv_ctx.video_resolution.stride = width; |
| rectangle.nLeft = 0; |
| rectangle.nTop = 0; |
| rectangle.nWidth = drv_ctx.video_resolution.frame_width; |
| rectangle.nHeight = drv_ctx.video_resolution.frame_height; |
| } |
| |
| /* ====================================================================== |
| FUNCTION |
| omx_vdec::ComponentInit |
| |
| DESCRIPTION |
| Initialize the component. |
| |
| PARAMETERS |
| ctxt -- Context information related to the self. |
| id -- Event identifier. This could be any of the following: |
| 1. Command completion event |
| 2. Buffer done callback event |
| 3. Frame done callback event |
| |
| RETURN VALUE |
| None. |
| |
| ========================================================================== */ |
| OMX_ERRORTYPE omx_vdec::component_init(OMX_STRING role) |
| { |
| |
| OMX_ERRORTYPE eRet = OMX_ErrorNone; |
| struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; |
| unsigned int alignment = 0,buffer_size = 0; |
| int fds[2]; |
| int r; |
| OMX_STRING device_name = "/dev/msm_vidc_dec"; |
| |
| if(!strncmp(role, "OMX.qcom.video.decoder.avc.smoothstreaming",OMX_MAX_STRINGNAME_SIZE)){ |
| ALOGI("smooth streaming role"); |
| m_use_smoothstreaming = true; |
| role = "OMX.qcom.video.decoder.avc"; |
| } |
| if(!strncmp(role, "OMX.qcom.video.decoder.avc.smoothstreaming.secure",OMX_MAX_STRINGNAME_SIZE)){ |
| ALOGI("secure smooth streaming role"); |
| m_use_smoothstreaming = true; |
| role = "OMX.qcom.video.decoder.avc.secure"; |
| } |
| |
| if(!strncmp(role, "OMX.qcom.video.decoder.avc.secure",OMX_MAX_STRINGNAME_SIZE)){ |
| secure_mode = true; |
| arbitrary_bytes = false; |
| role = "OMX.qcom.video.decoder.avc"; |
| device_name = "/dev/msm_vidc_dec_sec"; |
| } |
| |
| if (secure_mode) { |
| if (secureDisplay(qService::IQService::START) < 0) { |
| DEBUG_PRINT_HIGH("Sending message to start securing display failed"); |
| } |
| } |
| |
| DEBUG_PRINT_HIGH("\n omx_vdec::component_init(): Start of New Playback : role = %s : DEVICE = %s", |
| role, device_name); |
| |
| drv_ctx.video_driver_fd = open(device_name, O_RDWR | O_NONBLOCK); |
| |
| DEBUG_PRINT_HIGH("\n omx_vdec::component_init(): Open returned fd %d, errno %d", |
| drv_ctx.video_driver_fd, errno); |
| |
| if(drv_ctx.video_driver_fd == 0){ |
| drv_ctx.video_driver_fd = open(device_name, O_RDWR | O_NONBLOCK); |
| } |
| |
| if(drv_ctx.video_driver_fd < 0) |
| { |
| DEBUG_PRINT_ERROR("Omx_vdec::Comp Init Returning failure, errno %d\n", errno); |
| eRet = OMX_ErrorInsufficientResources; |
| goto cleanup; |
| } |
| drv_ctx.frame_rate.fps_numerator = DEFAULT_FPS; |
| drv_ctx.frame_rate.fps_denominator = 1; |
| |
| |
| #ifdef INPUT_BUFFER_LOG |
| strcpy(inputfilename, INPUT_BUFFER_FILE_NAME); |
| #endif |
| #ifdef OUTPUT_BUFFER_LOG |
| outputBufferFile1 = fopen (outputfilename, "ab"); |
| #endif |
| #ifdef OUTPUT_EXTRADATA_LOG |
| outputExtradataFile = fopen (ouputextradatafilename, "ab"); |
| #endif |
| |
| // Copy the role information which provides the decoder kind |
| strlcpy(drv_ctx.kind,role,128); |
| if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg4",\ |
| OMX_MAX_STRINGNAME_SIZE)) |
| { |
| strlcpy((char *)m_cRole, "video_decoder.mpeg4",\ |
| OMX_MAX_STRINGNAME_SIZE); |
| drv_ctx.timestamp_adjust = true; |
| drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG4; |
| eCompressionFormat = OMX_VIDEO_CodingMPEG4; |
| /*Initialize Start Code for MPEG4*/ |
| codec_type_parse = CODEC_TYPE_MPEG4; |
| m_frame_parser.init_start_codes (codec_type_parse); |
| #ifdef INPUT_BUFFER_LOG |
| strcat(inputfilename, "m4v"); |
| #endif |
| } |
| else if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2",\ |
| OMX_MAX_STRINGNAME_SIZE)) |
| { |
| strlcpy((char *)m_cRole, "video_decoder.mpeg2",\ |
| OMX_MAX_STRINGNAME_SIZE); |
| drv_ctx.decoder_format = VDEC_CODECTYPE_MPEG2; |
| eCompressionFormat = OMX_VIDEO_CodingMPEG2; |
| /*Initialize Start Code for MPEG2*/ |
| codec_type_parse = CODEC_TYPE_MPEG2; |
| m_frame_parser.init_start_codes (codec_type_parse); |
| #ifdef INPUT_BUFFER_LOG |
| strcat(inputfilename, "mpg"); |
| #endif |
| } |
| else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",\ |
| OMX_MAX_STRINGNAME_SIZE)) |
| { |
| strlcpy((char *)m_cRole, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE); |
| DEBUG_PRINT_LOW("\n H263 Decoder selected"); |
| drv_ctx.decoder_format = VDEC_CODECTYPE_H263; |
| eCompressionFormat = OMX_VIDEO_CodingH263; |
| codec_type_parse = CODEC_TYPE_H263; |
| m_frame_parser.init_start_codes (codec_type_parse); |
| #ifdef INPUT_BUFFER_LOG |
| strcat(inputfilename, "263"); |
| #endif |
| } |
| #ifdef MAX_RES_1080P |
| else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",\ |
| OMX_MAX_STRINGNAME_SIZE)) |
| { |
| strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE); |
| DEBUG_PRINT_LOW ("\n DIVX 311 Decoder selected"); |
| drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_3; |
| eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx; |
| codec_type_parse = CODEC_TYPE_DIVX; |
| m_frame_parser.init_start_codes (codec_type_parse); |
| #ifdef _ANDROID_ |
| OMX_ERRORTYPE err = createDivxDrmContext(); |
| if( err != OMX_ErrorNone ) { |
| DEBUG_PRINT_ERROR("createDivxDrmContext Failed"); |
| eRet = err; |
| goto cleanup; |
| } |
| #endif //_ANDROID_ |
| } |
| else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4",\ |
| OMX_MAX_STRINGNAME_SIZE)) |
| { |
| strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE); |
| DEBUG_PRINT_ERROR ("\n DIVX 4 Decoder selected"); |
| drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_4; |
| eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx; |
| codec_type_parse = CODEC_TYPE_DIVX; |
| m_frame_parser.init_start_codes (codec_type_parse); |
| #ifdef _ANDROID_ |
| OMX_ERRORTYPE err = createDivxDrmContext(); |
| if( err != OMX_ErrorNone ) { |
| DEBUG_PRINT_ERROR("createDivxDrmContext Failed"); |
| eRet = err; |
| goto cleanup; |
| } |
| #endif //_ANDROID_ |
| } |
| else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",\ |
| OMX_MAX_STRINGNAME_SIZE)) |
| { |
| strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE); |
| DEBUG_PRINT_ERROR ("\n DIVX 5/6 Decoder selected"); |
| drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_6; |
| eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx; |
| codec_type_parse = CODEC_TYPE_DIVX; |
| m_frame_parser.init_start_codes (codec_type_parse); |
| #ifdef _ANDROID_ |
| OMX_ERRORTYPE err = createDivxDrmContext(); |
| if( err != OMX_ErrorNone ) { |
| DEBUG_PRINT_ERROR("createDivxDrmContext Failed"); |
| eRet = err; |
| goto cleanup; |
| } |
| #endif //_ANDROID_ |
| } |
| #else |
| else if((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4",\ |
| OMX_MAX_STRINGNAME_SIZE)) || (!strncmp(drv_ctx.kind, \ |
| "OMX.qcom.video.decoder.divx", OMX_MAX_STRINGNAME_SIZE))) |
| { |
| strlcpy((char *)m_cRole, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE); |
| DEBUG_PRINT_ERROR ("\n DIVX Decoder selected"); |
| drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_5; |
| eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx; |
| codec_type_parse = CODEC_TYPE_DIVX; |
| m_frame_parser.init_start_codes (codec_type_parse); |
| |
| #ifdef _ANDROID_ |
| OMX_ERRORTYPE err = createDivxDrmContext(); |
| if( err != OMX_ErrorNone ) { |
| DEBUG_PRINT_ERROR("createDivxDrmContext Failed"); |
| eRet = err; |
| goto cleanup; |
| } |
| #endif //_ANDROID_ |
| } |
| #endif |
| else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",\ |
| OMX_MAX_STRINGNAME_SIZE)) |
| { |
| strlcpy((char *)m_cRole, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE); |
| drv_ctx.decoder_format = VDEC_CODECTYPE_H264; |
| eCompressionFormat = OMX_VIDEO_CodingAVC; |
| codec_type_parse = CODEC_TYPE_H264; |
| m_frame_parser.init_start_codes (codec_type_parse); |
| m_frame_parser.init_nal_length(nal_length); |
| #ifdef INPUT_BUFFER_LOG |
| strcat(inputfilename, "264"); |
| #endif |
| } |
| else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",\ |
| OMX_MAX_STRINGNAME_SIZE)) |
| { |
| strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE); |
| drv_ctx.decoder_format = VDEC_CODECTYPE_VC1; |
| eCompressionFormat = OMX_VIDEO_CodingWMV; |
| codec_type_parse = CODEC_TYPE_VC1; |
| m_frame_parser.init_start_codes (codec_type_parse); |
| #ifdef INPUT_BUFFER_LOG |
| strcat(inputfilename, "vc1"); |
| #endif |
| } |
| else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",\ |
| OMX_MAX_STRINGNAME_SIZE)) |
| { |
| strlcpy((char *)m_cRole, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE); |
| drv_ctx.decoder_format = VDEC_CODECTYPE_VC1_RCV; |
| eCompressionFormat = OMX_VIDEO_CodingWMV; |
| codec_type_parse = CODEC_TYPE_VC1; |
| m_frame_parser.init_start_codes (codec_type_parse); |
| #ifdef INPUT_BUFFER_LOG |
| strcat(inputfilename, "vc1"); |
| #endif |
| } |
| else |
| { |
| DEBUG_PRINT_ERROR("\nERROR:Unknown Component\n"); |
| eRet = OMX_ErrorInvalidComponentName; |
| } |
| #ifdef INPUT_BUFFER_LOG |
| inputBufferFile1 = fopen (inputfilename, "ab"); |
| #endif |
| if (eRet == OMX_ErrorNone) |
| { |
| #ifdef MAX_RES_720P |
| drv_ctx.output_format = VDEC_YUV_FORMAT_NV12; |
| |
| #endif |
| #ifdef MAX_RES_1080P |
| drv_ctx.output_format = VDEC_YUV_FORMAT_TILE_4x2; |
| OMX_COLOR_FORMATTYPE dest_color_format = (OMX_COLOR_FORMATTYPE) |
| QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka; |
| if (!client_buffers.set_color_format(dest_color_format)) { |
| DEBUG_PRINT_ERROR("\n Setting color format failed"); |
| eRet = OMX_ErrorInsufficientResources; |
| } |
| #endif |
| /*Initialize Decoder with codec type and resolution*/ |
| ioctl_msg.in = &drv_ctx.decoder_format; |
| ioctl_msg.out = NULL; |
| |
| if ( (eRet == OMX_ErrorNone) && |
| ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_SET_CODEC, |
| (void*)&ioctl_msg) < 0) |
| |
| { |
| DEBUG_PRINT_ERROR("\n Set codec type failed"); |
| eRet = OMX_ErrorInsufficientResources; |
| } |
| |
| /*Set the output format*/ |
| ioctl_msg.in = &drv_ctx.output_format; |
| ioctl_msg.out = NULL; |
| |
| if ( (eRet == OMX_ErrorNone) && |
| ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_SET_OUTPUT_FORMAT, |
| (void*)&ioctl_msg) < 0) |
| { |
| DEBUG_PRINT_ERROR("\n Set output format failed"); |
| eRet = OMX_ErrorInsufficientResources; |
| } |
| |
| if (m_use_smoothstreaming) { |
| int rc = ioctl(drv_ctx.video_driver_fd, |
| VDEC_IOCTL_SET_CONT_ON_RECONFIG); |
| if(rc < 0) { |
| DEBUG_PRINT_ERROR("Failed to enable Smooth Streaming on driver."); |
| } else { |
| m_smoothstreaming_width = kMaxSmoothStreamingWidth; |
| m_smoothstreaming_height = kMaxSmoothStreamingHeight; |
| } |
| } |
| |
| if (m_use_smoothstreaming) |
| update_resolution(kMaxSmoothStreamingWidth, kMaxSmoothStreamingHeight); |
| else |
| update_resolution(176, 144); |
| |
| ioctl_msg.in = &drv_ctx.video_resolution; |
| ioctl_msg.out = NULL; |
| |
| if ( (eRet == OMX_ErrorNone) && |
| ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_SET_PICRES, |
| (void*)&ioctl_msg) < 0) |
| { |
| DEBUG_PRINT_ERROR("\n Set Resolution failed"); |
| eRet = OMX_ErrorInsufficientResources; |
| } |
| |
| /*Get the Buffer requirements for input and output ports*/ |
| drv_ctx.ip_buf.buffer_type = VDEC_BUFFER_TYPE_INPUT; |
| drv_ctx.op_buf.buffer_type = VDEC_BUFFER_TYPE_OUTPUT; |
| drv_ctx.interlace = VDEC_InterlaceFrameProgressive; |
| drv_ctx.extradata = 0; |
| drv_ctx.picture_order = VDEC_ORDER_DISPLAY; |
| drv_ctx.idr_only_decoding = 0; |
| |
| if (eRet == OMX_ErrorNone) |
| eRet = get_buffer_req(&drv_ctx.ip_buf); |
| if (eRet == OMX_ErrorNone) |
| eRet = get_buffer_req(&drv_ctx.op_buf); |
| m_state = OMX_StateLoaded; |
| #ifdef DEFAULT_EXTRADATA |
| if (eRet == OMX_ErrorNone && !secure_mode) |
| eRet = enable_extradata(DEFAULT_EXTRADATA); |
| #endif |
| if ( (codec_type_parse == CODEC_TYPE_VC1) || |
| (codec_type_parse == CODEC_TYPE_H264)) //add CP check here |
| { |
| //Check if dmx can be disabled |
| struct vdec_ioctl_msg ioctl_msg = {NULL, NULL}; |
| OMX_ERRORTYPE eRet = OMX_ErrorNone; |
| ioctl_msg.out = &drv_ctx.disable_dmx; |
| if (ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_GET_DISABLE_DMX_SUPPORT, &ioctl_msg)) |
| { |
| DEBUG_PRINT_ERROR("Error VDEC_IOCTL_GET_DISABLE_DMX_SUPPORT"); |
| eRet = OMX_ErrorHardware; |
| } |
| else |
| { |
| if (drv_ctx.disable_dmx && !secure_mode) |
| { |
| DEBUG_PRINT_HIGH("DMX disable is supported"); |
| |
| int rc = ioctl(drv_ctx.video_driver_fd, |
| VDEC_IOCTL_SET_DISABLE_DMX); |
| if(rc < 0) { |
| DEBUG_PRINT_ERROR("Failed to disable dmx on driver."); |
| drv_ctx.disable_dmx = false; |
| eRet = OMX_ErrorHardware; |
| } |
| } |
| else { |
| drv_ctx.disable_dmx = false; |
| } |
| } |
| } |
| if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) |
| { |
| if (m_frame_parser.mutils == NULL) |
| { |
| m_frame_parser.mutils = new H264_Utils(); |
| |
| if (m_frame_parser.mutils == NULL) |
| { |
| DEBUG_PRINT_ERROR("\n parser utils Allocation failed "); |
| eRet = OMX_ErrorInsufficientResources; |
| } |
| else |
| { |
| h264_scratch.nAllocLen = drv_ctx.ip_buf.buffer_size; |
| h264_scratch.pBuffer = (OMX_U8 *)malloc (drv_ctx.ip_buf.buffer_size); |
| h264_scratch.nFilledLen = 0; |
| h264_scratch.nOffset = 0; |
| |
| if (h264_scratch.pBuffer == NULL) |
| { |
| DEBUG_PRINT_ERROR("\n h264_scratch.pBuffer Allocation failed "); |
| return OMX_ErrorInsufficientResources; |
| } |
| m_frame_parser.mutils->initialize_frame_checking_environment(); |
| m_frame_parser.mutils->allocate_rbsp_buffer (drv_ctx.ip_buf.buffer_size); |
| } |
| } |
| |
| h264_parser = new h264_stream_parser(); |
| if (!h264_parser) |
| { |
| DEBUG_PRINT_ERROR("ERROR: H264 parser allocation failed!"); |
| eRet = OMX_ErrorInsufficientResources; |
| } |
| } |
| |
| if(pipe(fds)) |
| { |
| DEBUG_PRINT_ERROR("pipe creation failed\n"); |
| eRet = OMX_ErrorInsufficientResources; |
| } |
| else |
| { |
| int temp1[2]; |
| if(fds[0] == 0 || fds[1] == 0) |
| { |
| if (pipe (temp1)) |
| { |
| DEBUG_PRINT_ERROR("pipe creation failed\n"); |
| return OMX_ErrorInsufficientResources; |
| } |
| //close (fds[0]); |
| //close (fds[1]); |
| fds[0] = temp1 [0]; |
| fds[1] = temp1 [1]; |
| } |
| m_pipe_in = fds[0]; |
| m_pipe_out = fds[1]; |
| r = pthread_create(&msg_thread_id,0,message_thread,this); |
| |
| if(r < 0) |
| { |
| DEBUG_PRINT_ERROR("\n component_init(): message_thread creation failed"); |
| eRet = OMX_ErrorInsufficientResources; |
| } |
| else |
| { |
| r = pthread_create(&async_thread_id,0,async_message_thread,this); |
| if(r < 0) |
| { |
| DEBUG_PRINT_ERROR("\n component_init(): async_message_thread creation failed"); |
| eRet = OMX_ErrorInsufficientResources; |
| } |
| } |
| } |
| } |
| |
| if (eRet != OMX_ErrorNone) |
| { |
| DEBUG_PRINT_ERROR("\n Component Init Failed"); |
| DEBUG_PRINT_HIGH("\n Calling VDEC_IOCTL_STOP_NEXT_MSG"); |
| (void)ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_STOP_NEXT_MSG, |
| NULL); |
| DEBUG_PRINT_HIGH("\n Calling close() on Video Driver"); |
| close (drv_ctx.video_driver_fd); |
| drv_ctx.video_driver_fd = -1; |
| } |
| else |
| { |
| DEBUG_PRINT_HIGH("\n omx_vdec::component_init() success"); |
| } |
| |
| memset(&h264_mv_buff,0,sizeof(struct h264_mv_buffer)); |
| |
| cleanup: |
| |
| if (secure_mode && (eRet == OMX_ErrorNone)) { |
| if (secureDisplay(qService::IQService::END) < 0) { |
| DEBUG_PRINT_HIGH("sending message to stop securing display failed"); |
| } |
| } |
| |
| return eRet; |
| } |
| |
| /* ====================================================================== |
| FUNCTION |
| omx_vdec::GetComponentVersion |
| |
| DESCRIPTION |
| Returns the component version. |
| |
| PARAMETERS |
| TBD. |
| |
| RETURN VALUE |
| OMX_ErrorNone. |
| |
| ========================================================================== */ |
| OMX_ERRORTYPE omx_vdec::get_component_version |
| ( |
| OMX_IN OMX_HANDLETYPE hComp, |
| OMX_OUT OMX_STRING componentName, |
| OMX_OUT OMX_VERSIONTYPE* componentVersion, |
| OMX_OUT OMX_VERSIONTYPE* specVersion, |
| OMX_OUT OMX_UUIDTYPE* componentUUID |
| ) |
| { |
| if(m_state == OMX_StateInvalid) |
| { |
| DEBUG_PRINT_ERROR("Get Comp Version in Invalid State\n"); |
| return OMX_ErrorInvalidState; |
| } |
| /* TBD -- Return the proper version */ |
| if (specVersion) |
| { |
| specVersion->nVersion = OMX_SPEC_VERSION; |
| } |
| return OMX_ErrorNone; |
| } |
| /* ====================================================================== |
| FUNCTION |
| omx_vdec::SendCommand |
| |
| DESCRIPTION |
| Returns zero if all the buffers released.. |
| |
| PARAMETERS |
| None. |
| |
| RETURN VALUE |
| true/false |
| |
| ========================================================================== */ |
| OMX_ERRORTYPE omx_vdec::send_command(OMX_IN OMX_HANDLETYPE hComp, |
| OMX_IN OMX_COMMANDTYPE cmd, |
| OMX_IN OMX_U32 param1, |
| OMX_IN OMX_PTR cmdData |
| ) |
| { |
| DEBUG_PRINT_LOW("\n send_command: Recieved a Command from Client"); |
| if(m_state == OMX_StateInvalid) |
| { |
| DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State\n"); |
| return OMX_ErrorInvalidState; |
| } |
| if (cmd == OMX_CommandFlush && param1 != OMX_CORE_INPUT_PORT_INDEX |
| && param1 != OMX_CORE_OUTPUT_PORT_INDEX && param1 != OMX_ALL) |
| { |
| DEBUG_PRINT_ERROR("\n send_command(): ERROR OMX_CommandFlush " |
| "to invalid port: %d", param1); |
| return OMX_ErrorBadPortIndex; |
| } |
| post_event((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND); |
| sem_wait(&m_cmd_lock); |
| DEBUG_PRINT_LOW("\n send_command: Command Processed\n"); |
| return OMX_ErrorNone; |
| } |
| |
| /* ====================================================================== |
| FUNCTION |
| omx_vdec::SendCommand |
| |
| DESCRIPTION |
| Returns zero if all the buffers released.. |
| |
| PARAMETERS |
| None. |
| |
| RETURN VALUE |
| true/false |
| |
| ========================================================================== */ |
| OMX_ERRORTYPE omx_vdec::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp, |
| OMX_IN OMX_COMMANDTYPE cmd, |
| OMX_IN OMX_U32 param1, |
| OMX_IN OMX_PTR cmdData |
| ) |
| { |
| OMX_ERRORTYPE eRet = OMX_ErrorNone; |
| OMX_STATETYPE eState = (OMX_STATETYPE) param1; |
| int bFlag = 1,sem_posted = 0; |
| |
| DEBUG_PRINT_LOW("\n send_command_proxy(): cmd = %d", cmd); |
| DEBUG_PRINT_HIGH("\n send_command_proxy(): Current State %d, Expected State %d", |
| m_state, eState); |
| |
| if(cmd == OMX_CommandStateSet) |
| { |
| DEBUG_PRINT_HIGH("\n send_command_proxy(): OMX_CommandStateSet issued"); |
| DEBUG_PRINT_HIGH("\n Current State %d, Expected State %d", m_state, eState); |
| /***************************/ |
| /* Current State is Loaded */ |
| /***************************/ |
| if(m_state == OMX_StateLoaded) |
| { |
| if(eState == OMX_StateIdle) |
| { |
| //if all buffers are allocated or all ports disabled |
| if(allocate_done() || |
| (m_inp_bEnabled == OMX_FALSE && m_out_bEnabled == OMX_FALSE)) |
| { |
| DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle\n"); |
| } |
| else |
| { |
| DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle-Pending\n"); |
| BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING); |
| // Skip the event notification |
| bFlag = 0; |
| } |
| } |
| /* Requesting transition from Loaded to Loaded */ |
| else if(eState == OMX_StateLoaded) |
| { |
| DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Loaded\n"); |
| post_event(OMX_EventError,OMX_ErrorSameState,\ |
| OMX_COMPONENT_GENERATE_EVENT); |
| eRet = OMX_ErrorSameState; |
| } |
| /* Requesting transition from Loaded to WaitForResources */ |
| else if(eState == OMX_StateWaitForResources) |
| { |
| /* Since error is None , we will post an event |
| at the end of this function definition */ |
| DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->WaitForResources\n"); |
| } |
| /* Requesting transition from Loaded to Executing */ |
| else if(eState == OMX_StateExecuting) |
| { |
| DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Executing\n"); |
| post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ |
| OMX_COMPONENT_GENERATE_EVENT); |
| eRet = OMX_ErrorIncorrectStateTransition; |
| } |
| /* Requesting transition from Loaded to Pause */ |
| else if(eState == OMX_StatePause) |
| { |
| DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Pause\n"); |
| post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ |
| OMX_COMPONENT_GENERATE_EVENT); |
| eRet = OMX_ErrorIncorrectStateTransition; |
| } |
| /* Requesting transition from Loaded to Invalid */ |
| else if(eState == OMX_StateInvalid) |
| { |
| DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid\n"); |
| post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); |
| eRet = OMX_ErrorInvalidState; |
| } |
| else |
| { |
| DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Invalid(%d Not Handled)\n",\ |
| eState); |
| eRet = OMX_ErrorBadParameter; |
| } |
| } |
| |
| /***************************/ |
| /* Current State is IDLE */ |
| /***************************/ |
| else if(m_state == OMX_StateIdle) |
| { |
| if(eState == OMX_StateLoaded) |
| { |
| if(release_done()) |
| { |
| /* |
| Since error is None , we will post an event at the end |
| of this function definition |
| */ |
| DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded\n"); |
| } |
| else |
| { |
| DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded-Pending\n"); |
| BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING); |
| // Skip the event notification |
| bFlag = 0; |
| } |
| } |
| /* Requesting transition from Idle to Executing */ |
| else if(eState == OMX_StateExecuting) |
| { |
| DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing\n"); |
| BITMASK_SET(&m_flags, OMX_COMPONENT_EXECUTE_PENDING); |
| bFlag = 0; |
| if (ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_START, |
| NULL) < 0) |
| { |
| DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_START FAILED"); |
| omx_report_error (); |
| eRet = OMX_ErrorHardware; |
| } |
| } |
| /* Requesting transition from Idle to Idle */ |
| else if(eState == OMX_StateIdle) |
| { |
| DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Idle\n"); |
| post_event(OMX_EventError,OMX_ErrorSameState,\ |
| OMX_COMPONENT_GENERATE_EVENT); |
| eRet = OMX_ErrorSameState; |
| } |
| /* Requesting transition from Idle to WaitForResources */ |
| else if(eState == OMX_StateWaitForResources) |
| { |
| DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->WaitForResources\n"); |
| post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ |
| OMX_COMPONENT_GENERATE_EVENT); |
| eRet = OMX_ErrorIncorrectStateTransition; |
| } |
| /* Requesting transition from Idle to Pause */ |
| else if(eState == OMX_StatePause) |
| { |
| /*To pause the Video core we need to start the driver*/ |
| if (ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_START, |
| NULL) < 0) |
| { |
| DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_START FAILED"); |
| omx_report_error (); |
| eRet = OMX_ErrorHardware; |
| } |
| else |
| { |
| BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING); |
| DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Pause\n"); |
| bFlag = 0; |
| } |
| } |
| /* Requesting transition from Idle to Invalid */ |
| else if(eState == OMX_StateInvalid) |
| { |
| DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Invalid\n"); |
| post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); |
| eRet = OMX_ErrorInvalidState; |
| } |
| else |
| { |
| DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle --> %d Not Handled\n",eState); |
| eRet = OMX_ErrorBadParameter; |
| } |
| } |
| |
| /******************************/ |
| /* Current State is Executing */ |
| /******************************/ |
| else if(m_state == OMX_StateExecuting) |
| { |
| DEBUG_PRINT_LOW("\n Command Recieved in OMX_StateExecuting"); |
| /* Requesting transition from Executing to Idle */ |
| if(eState == OMX_StateIdle) |
| { |
| /* Since error is None , we will post an event |
| at the end of this function definition |
| */ |
| DEBUG_PRINT_LOW("\n send_command_proxy(): Executing --> Idle \n"); |
| BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING); |
| if(!sem_posted) |
| { |
| sem_posted = 1; |
| sem_post (&m_cmd_lock); |
| execute_omx_flush(OMX_ALL); |
| } |
| bFlag = 0; |
| } |
| /* Requesting transition from Executing to Paused */ |
| else if(eState == OMX_StatePause) |
| { |
| DEBUG_PRINT_LOW("\n PAUSE Command Issued"); |
| if (ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_PAUSE, |
| NULL) < 0) |
| { |
| DEBUG_PRINT_ERROR("\n Error In Pause State"); |
| post_event(OMX_EventError,OMX_ErrorHardware,\ |
| OMX_COMPONENT_GENERATE_EVENT); |
| eRet = OMX_ErrorHardware; |
| } |
| else |
| { |
| BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING); |
| DEBUG_PRINT_LOW("send_command_proxy(): Executing-->Pause\n"); |
| bFlag = 0; |
| } |
| } |
| /* Requesting transition from Executing to Loaded */ |
| else if(eState == OMX_StateLoaded) |
| { |
| DEBUG_PRINT_ERROR("\n send_command_proxy(): Executing --> Loaded \n"); |
| post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ |
| OMX_COMPONENT_GENERATE_EVENT); |
| eRet = OMX_ErrorIncorrectStateTransition; |
| } |
| /* Requesting transition from Executing to WaitForResources */ |
| else if(eState == OMX_StateWaitForResources) |
| { |
| DEBUG_PRINT_ERROR("\n send_command_proxy(): Executing --> WaitForResources \n"); |
| post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ |
| OMX_COMPONENT_GENERATE_EVENT); |
| eRet = OMX_ErrorIncorrectStateTransition; |
| } |
| /* Requesting transition from Executing to Executing */ |
| else if(eState == OMX_StateExecuting) |
| { |
| DEBUG_PRINT_ERROR("\n send_command_proxy(): Executing --> Executing \n"); |
| post_event(OMX_EventError,OMX_ErrorSameState,\ |
| OMX_COMPONENT_GENERATE_EVENT); |
| eRet = OMX_ErrorSameState; |
| } |
| /* Requesting transition from Executing to Invalid */ |
| else if(eState == OMX_StateInvalid) |
| { |
| DEBUG_PRINT_ERROR("\n send_command_proxy(): Executing --> Invalid \n"); |
| post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); |
| eRet = OMX_ErrorInvalidState; |
| } |
| else |
| { |
| DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Executing --> %d Not Handled\n",eState); |
| eRet = OMX_ErrorBadParameter; |
| } |
| } |
| /***************************/ |
| /* Current State is Pause */ |
| /***************************/ |
| else if(m_state == OMX_StatePause) |
| { |
| /* Requesting transition from Pause to Executing */ |
| if(eState == OMX_StateExecuting) |
| { |
| DEBUG_PRINT_LOW("\n Pause --> Executing \n"); |
| if (ioctl (drv_ctx.video_driver_fd,VDEC_IOCTL_CMD_RESUME, |
| NULL) < 0) |
| { |
| DEBUG_PRINT_ERROR("\n VDEC_IOCTL_CMD_RESUME failed"); |
| post_event(OMX_EventError,OMX_ErrorHardware,\ |
| OMX_COMPONENT_GENERATE_EVENT); |
| eRet = OMX_ErrorHardware; |
| } |
| else |
| { |
| BITMASK_SET(&m_flags,OMX_COMPONENT_EXECUTE_PENDING); |
| DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing\n"); |
| post_event (NULL,VDEC_S_SUCCESS,\ |
| OMX_COMPONENT_GENERATE_RESUME_DONE); |
| bFlag = 0; |
| } |
| } |
| /* Requesting transition from Pause to Idle */ |
| else if(eState == OMX_StateIdle) |
| { |
| /* Since error is None , we will post an event |
| at the end of this function definition */ |
| DEBUG_PRINT_LOW("\n Pause --> Idle \n"); |
| BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING); |
| if(!sem_posted) |
| { |
| sem_posted = 1; |
| sem_post (&m_cmd_lock); |
| execute_omx_flush(OMX_ALL); |
| } |
| bFlag = 0; |
| } |
| /* Requesting transition from Pause to loaded */ |
| else if(eState == OMX_StateLoaded) |
| { |
| DEBUG_PRINT_ERROR("\n Pause --> loaded \n"); |
| post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ |
| OMX_COMPONENT_GENERATE_EVENT); |
| eRet = OMX_ErrorIncorrectStateTransition; |
| } |
| /* Requesting transition from Pause to WaitForResources */ |
| else if(eState == OMX_StateWaitForResources) |
| { |
| DEBUG_PRINT_ERROR("\n Pause --> WaitForResources \n"); |
| post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ |
| OMX_COMPONENT_GENERATE_EVENT); |
| eRet = OMX_ErrorIncorrectStateTransition; |
| } |
| /* Requesting transition from Pause to Pause */ |
| else if(eState == OMX_StatePause) |
| { |
| DEBUG_PRINT_ERROR("\n Pause --> Pause \n"); |
| post_event(OMX_EventError,OMX_ErrorSameState,\ |
| OMX_COMPONENT_GENERATE_EVENT); |
| eRet = OMX_ErrorSameState; |
| } |
| /* Requesting transition from Pause to Invalid */ |
| else if(eState == OMX_StateInvalid) |
| { |
| DEBUG_PRINT_ERROR("\n Pause --> Invalid \n"); |
| post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); |
| eRet = OMX_ErrorInvalidState; |
| } |
| else |
| { |
| DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Paused --> %d Not Handled\n",eState); |
| eRet = OMX_ErrorBadParameter; |
| } |
| } |
| /***************************/ |
| /* Current State is WaitForResources */ |
| /***************************/ |
| else if(m_state == OMX_StateWaitForResources) |
| { |
| /* Requesting transition from WaitForResources to Loaded */ |
| if(eState == OMX_StateLoaded) |
| { |
| /* Since error is None , we will post an event |
| at the end of this function definition */ |
| DEBUG_PRINT_LOW("send_command_proxy(): WaitForResources-->Loaded\n"); |
| } |
| /* Requesting transition from WaitForResources to WaitForResources */ |
| else if (eState == OMX_StateWaitForResources) |
| { |
| DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->WaitForResources\n"); |
| post_event(OMX_EventError,OMX_ErrorSameState, |
| OMX_COMPONENT_GENERATE_EVENT); |
| eRet = OMX_ErrorSameState; |
| } |
| /* Requesting transition from WaitForResources to Executing */ |
| else if(eState == OMX_StateExecuting) |
| { |
| DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Executing\n"); |
| post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ |
| OMX_COMPONENT_GENERATE_EVENT); |
| eRet = OMX_ErrorIncorrectStateTransition; |
| } |
| /* Requesting transition from WaitForResources to Pause */ |
| else if(eState == OMX_StatePause) |
| { |
| DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Pause\n"); |
| post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\ |
| OMX_COMPONENT_GENERATE_EVENT); |
| eRet = OMX_ErrorIncorrectStateTransition; |
| } |
| /* Requesting transition from WaitForResources to Invalid */ |
| else if(eState == OMX_StateInvalid) |
| { |
| DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->Invalid\n"); |
| post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT); |
| eRet = OMX_ErrorInvalidState; |
| } |
| /* Requesting transition from WaitForResources to Loaded - |
| is NOT tested by Khronos TS */ |
| |
| } |
| else |
| { |
| DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): %d --> %d(Not Handled)\n",m_state,eState); |
| eRet = OMX_ErrorBadParameter; |
| } |
| } |
| /********************************/ |
| /* Current State is Invalid */ |
| /*******************************/ |
| else if(m_state == OMX_StateInvalid) |
| { |
| /* State Transition from Inavlid to any state */ |
| if(eState == (OMX_StateLoaded || OMX_StateWaitForResources |
| || OMX_StateIdle || OMX_StateExecuting |
| || OMX_StatePause || OMX_StateInvalid)) |
| { |
| DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Invalid -->Loaded\n"); |
| post_event(OMX_EventError,OMX_ErrorInvalidState,\ |
| OMX_COMPONENT_GENERATE_EVENT); |
| eRet = OMX_ErrorInvalidState; |
| } |
| } |
| else if (cmd == OMX_CommandFlush) |
| { |
| DEBUG_PRINT_HIGH("\n send_command_proxy(): OMX_CommandFlush issued" |
| "with param1: %d", param1); |
| if(OMX_CORE_INPUT_PORT_INDEX == param1 || OMX_ALL == param1) |
| { |
| BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING); |
| } |
| if(OMX_CORE_OUTPUT_PORT_INDEX == param1 || OMX_ALL == param1) |
| { |
| BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_PENDING); |
| } |
| if (!sem_posted){ |
| sem_posted = 1; |
| DEBUG_PRINT_LOW("\n Set the Semaphore"); |
| sem_post (&m_cmd_lock); |
| execute_omx_flush(param1); |
| } |
| bFlag = 0; |
| } |
| else if ( cmd == OMX_CommandPortEnable) |
| { |
| DEBUG_PRINT_HIGH("\n send_command_proxy(): OMX_CommandPortEnable issued" |
| "with param1: %d", param1); |
| if(param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) |
| { |
| m_inp_bEnabled = OMX_TRUE; |
| |
| if( (m_state == OMX_StateLoaded && |
| !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) |
| || allocate_input_done()) |
| { |
| post_event(OMX_CommandPortEnable,OMX_CORE_INPUT_PORT_INDEX, |
| OMX_COMPONENT_GENERATE_EVENT); |
| } |
| else |
| { |
| DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending\n"); |
| BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING); |
| // Skip the event notification |
| bFlag = 0; |
| } |
| } |
| if(param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) |
| { |
| DEBUG_PRINT_LOW("\n Enable output Port command recieved"); |
| m_out_bEnabled = OMX_TRUE; |
| |
| if( (m_state == OMX_StateLoaded && |
| !BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) |
| || (allocate_output_done())) |
| { |
| post_event(OMX_CommandPortEnable,OMX_CORE_OUTPUT_PORT_INDEX, |
| OMX_COMPONENT_GENERATE_EVENT); |
| |
| } |
| else |
| { |
| DEBUG_PRINT_LOW("send_command_proxy(): Disabled-->Enabled Pending\n"); |
| BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING); |
| // Skip the event notification |
| bFlag = 0; |
| } |
| } |
| } |
| else if (cmd == OMX_CommandPortDisable) |
| { |
| DEBUG_PRINT_HIGH("\n send_command_proxy(): OMX_CommandPortDisable issued" |
| "with param1: %d", param1); |
| if(param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) |
| { |
| m_inp_bEnabled = OMX_FALSE; |
| if((m_state == OMX_StateLoaded || m_state == OMX_StateIdle) |
| && release_input_done()) |
| { |
| post_event(OMX_CommandPortDisable,OMX_CORE_INPUT_PORT_INDEX, |
| OMX_COMPONENT_GENERATE_EVENT); |
| } |
| else |
| { |
| BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_DISABLE_PENDING); |
| if(m_state == OMX_StatePause ||m_state == OMX_StateExecuting) |
| { |
| if(!sem_posted) |
| { |
| sem_posted = 1; |
| sem_post (&m_cmd_lock); |
| } |
| execute_omx_flush(OMX_CORE_INPUT_PORT_INDEX); |
| } |
| |
| // Skip the event notification |
| bFlag = 0; |
| } |
| } |
| if(param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) |
| { |
| m_out_bEnabled = OMX_FALSE; |
| DEBUG_PRINT_LOW("\n Disable output Port command recieved"); |
| if((m_state == OMX_StateLoaded || m_state == OMX_StateIdle) |
| && release_output_done()) |
| { |
| post_event(OMX_CommandPortDisable,OMX_CORE_OUTPUT_PORT_INDEX,\ |
| OMX_COMPONENT_GENERATE_EVENT); |
| } |
| else |
| { |
| BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_DISABLE_PENDING); |
| if(m_state == OMX_StatePause ||m_state == OMX_StateExecuting) |
| { |
| if (!sem_posted) |
| { |
| sem_posted = 1; |
| sem_post (&m_cmd_lock); |
| } |
| BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_IN_DISABLE_PENDING); |
| execute_omx_flush(OMX_CORE_OUTPUT_PORT_INDEX); |
| } |
| // Skip the event notification |
| bFlag = 0; |
| |
| } |
| } |
| } |
| else |
| { |
| DEBUG_PRINT_ERROR("Error: Invalid Command other than StateSet (%d)\n",cmd); |
| eRet = OMX_ErrorNotImplemented; |
| } |
| if(eRet == OMX_ErrorNone && bFlag) |
| { |
| post_event(cmd,eState,OMX_COMPONENT_GENERATE_EVENT); |
| } |
| if(!sem_posted) |
| { |
| sem_post(&m_cmd_lock); |
| } |
| |
| return eRet; |
| } |
| |
| /* ====================================================================== |
| FUNCTION |
| omx_vdec::ExecuteOmxFlush |
| |
| DESCRIPTION |
| Executes the OMX flush. |
| |
| PARAMETERS |
| flushtype - input flush(1)/output flush(0)/ both. |
| |
| RETURN VALUE |
| true/false |
| |
| ========================================================================== */ |
| bool omx_vdec::execute_omx_flush(OMX_U32 flushType) |
| { |
| struct vdec_ioctl_msg ioctl_msg = {NULL, NULL}; |
| enum vdec_bufferflush flush_dir; |
| bool bRet = false; |
| switch (flushType) |
| { |
| case OMX_CORE_INPUT_PORT_INDEX: |
| input_flush_progress = true; |
| flush_dir = VDEC_FLUSH_TYPE_INPUT; |
| break; |
| case OMX_CORE_OUTPUT_PORT_INDEX: |
| output_flush_progress = true; |
| flush_dir = VDEC_FLUSH_TYPE_OUTPUT; |
| break; |
| default: |
| input_flush_progress = true; |
| output_flush_progress = true; |
| flush_dir = VDEC_FLUSH_TYPE_ALL; |
| } |
| ioctl_msg.in = &flush_dir; |
| ioctl_msg.out = NULL; |
| if (ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_CMD_FLUSH, &ioctl_msg) < 0) |
| { |
| DEBUG_PRINT_ERROR("\n Flush Port (%d) Failed ", (int)flush_dir); |
| bRet = false; |
| } |
| return bRet; |
| } |
| /*========================================================================= |
| FUNCTION : execute_output_flush |
| |
| DESCRIPTION |
| Executes the OMX flush at OUTPUT PORT. |
| |
| PARAMETERS |
| None. |
| |
| RETURN VALUE |
| true/false |
| ==========================================================================*/ |
| bool omx_vdec::execute_output_flush() |
| { |
| unsigned p1 = 0; // Parameter - 1 |
| unsigned p2 = 0; // Parameter - 2 |
| unsigned ident = 0; |
| bool bRet = true; |
| |
| /*Generate FBD for all Buffers in the FTBq*/ |
| pthread_mutex_lock(&m_lock); |
| DEBUG_PRINT_LOW("\n Initiate Output Flush"); |
| while (m_ftb_q.m_size) |
| { |
| DEBUG_PRINT_LOW("\n Buffer queue size %d pending buf cnt %d", |
| m_ftb_q.m_size,pending_output_buffers); |
| m_ftb_q.pop_entry(&p1,&p2,&ident); |
| DEBUG_PRINT_LOW("\n ID(%x) P1(%x) P2(%x)", ident, p1, p2); |
| if(ident == m_fill_output_msg) |
| { |
| pending_output_buffers++; |
| m_cb.FillBufferDone(&m_cmp, m_app_data, (OMX_BUFFERHEADERTYPE *)p2); |
| } |
| else if (ident == OMX_COMPONENT_GENERATE_FBD) |
| { |
| fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1); |
| } |
| } |
| pthread_mutex_unlock(&m_lock); |
| output_flush_progress = false; |
| |
| if (arbitrary_bytes) |
| { |
| prev_ts = LLONG_MAX; |
| rst_prev_ts = true; |
| } |
| DEBUG_PRINT_HIGH("\n OMX flush o/p Port complete PenBuf(%d)", pending_output_buffers); |
| return bRet; |
| } |
| /*========================================================================= |
| FUNCTION : execute_input_flush |
| |
| DESCRIPTION |
| Executes the OMX flush at INPUT PORT. |
| |
| PARAMETERS |
| None. |
| |
| RETURN VALUE |
| true/false |
| ==========================================================================*/ |
| bool omx_vdec::execute_input_flush() |
| { |
| unsigned i =0; |
| unsigned p1 = 0; // Parameter - 1 |
| unsigned p2 = 0; // Parameter - 2 |
| unsigned ident = 0; |
| bool bRet = true; |
| |
| /*Generate EBD for all Buffers in the ETBq*/ |
| DEBUG_PRINT_LOW("\n Initiate Input Flush \n"); |
| |
| pthread_mutex_lock(&m_lock); |
| DEBUG_PRINT_LOW("\n Check if the Queue is empty \n"); |
| while (m_etb_q.m_size) |
| { |
| m_etb_q.pop_entry(&p1,&p2,&ident); |
| |
| if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) |
| { |
| 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) |
| { |
| 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); |
| } |
| } |
| time_stamp_dts.flush_timestamp(); |
| /*Check if Heap Buffers are to be flushed*/ |
| if (arbitrary_bytes && !(codec_config_flag)) |
| { |
| DEBUG_PRINT_LOW("\n Reset all the variables before flusing"); |
| h264_scratch.nFilledLen = 0; |
| nal_count = 0; |
| look_ahead_nal = false; |
| frame_count = 0; |
| h264_last_au_ts = LLONG_MAX; |
| h264_last_au_flags = 0; |
| memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) ); |
| m_demux_entries = 0; |
| DEBUG_PRINT_LOW("\n Initialize parser"); |
| if (m_frame_parser.mutils) |
| { |
| m_frame_parser.mutils->initialize_frame_checking_environment(); |
| } |
| |
| while (m_input_pending_q.m_size) |
| { |
| m_input_pending_q.pop_entry(&p1,&p2,&ident); |
| m_cb.EmptyBufferDone(&m_cmp ,m_app_data, (OMX_BUFFERHEADERTYPE *)p1); |
| } |
| |
| if (psource_frame) |
| { |
| m_cb.EmptyBufferDone(&m_cmp ,m_app_data,psource_frame); |
| psource_frame = NULL; |
| } |
| |
| if (pdest_frame) |
| { |
| pdest_frame->nFilledLen = 0; |
| m_input_free_q.insert_entry((unsigned) pdest_frame,NULL,NULL); |
| pdest_frame = NULL; |
| } |
| m_frame_parser.flush(); |
| } |
| else if (codec_config_flag) |
| { |
| DEBUG_PRINT_HIGH("frame_parser flushing skipped due to codec config buffer " |
| "is not sent to the driver yet"); |
| } |
| pthread_mutex_unlock(&m_lock); |
| input_flush_progress = false; |
| if (!arbitrary_bytes) |
| { |
| prev_ts = LLONG_MAX; |
| rst_prev_ts = true; |
| } |
| #ifdef _ANDROID_ |
| if (m_debug_timestamp) |
| { |
| m_timestamp_list.reset_ts_list(); |
| } |
| #endif |
| DEBUG_PRINT_HIGH("\n OMX flush i/p Port complete PenBuf(%d)", pending_input_buffers); |
| return bRet; |
| } |
| |
| |
| /* ====================================================================== |
| FUNCTION |
| omx_vdec::SendCommandEvent |
| |
| DESCRIPTION |
| Send the event to decoder pipe. This is needed to generate the callbacks |
| in decoder thread context. |
| |
| PARAMETERS |
| None. |
| |
| RETURN VALUE |
| true/false |
| |
| ========================================================================== */ |
| bool omx_vdec::post_event(unsigned int p1, |
| unsigned int p2, |
| unsigned int id) |
| { |
| bool bRet = false; |
| |
| |
| pthread_mutex_lock(&m_lock); |
| |
| if (id == m_fill_output_msg || |
| id == OMX_COMPONENT_GENERATE_FBD) |
| { |
| m_ftb_q.insert_entry(p1,p2,id); |
| } |
| else if (id == OMX_COMPONENT_GENERATE_ETB || |
| id == OMX_COMPONENT_GENERATE_EBD || |
| id == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) |
| { |
| m_etb_q.insert_entry(p1,p2,id); |
| } |
| else |
| { |
| m_cmd_q.insert_entry(p1,p2,id); |
| } |
| |
| bRet = true; |
| DEBUG_PRINT_LOW("\n Value of this pointer in post_event 0x%x", p2); |
| post_message(this, id); |
| |
| pthread_mutex_unlock(&m_lock); |
| |
| return bRet; |
| } |
| #ifdef MAX_RES_720P |
| OMX_ERRORTYPE omx_vdec::get_supported_profile_level_for_720p(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType) |
| { |
| OMX_ERRORTYPE eRet = OMX_ErrorNone; |
| if(!profileLevelType) |
| return OMX_ErrorBadParameter; |
| |
| if(profileLevelType->nPortIndex == 0) { |
| if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) |
| { |
| if (profileLevelType->nProfileIndex == 0) |
| { |
| profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline; |
| profileLevelType->eLevel = OMX_VIDEO_AVCLevel31; |
| |
| } |
| else if (profileLevelType->nProfileIndex == 1) |
| { |
| profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain; |
| profileLevelType->eLevel = OMX_VIDEO_AVCLevel31; |
| } |
| else if(profileLevelType->nProfileIndex == 2) |
| { |
| profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh; |
| profileLevelType->eLevel = OMX_VIDEO_AVCLevel31; |
| } |
| else |
| { |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", |
| profileLevelType->nProfileIndex); |
| eRet = OMX_ErrorNoMore; |
| } |
| } else if((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE))) |
| { |
| if (profileLevelType->nProfileIndex == 0) |
| { |
| profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline; |
| profileLevelType->eLevel = OMX_VIDEO_H263Level70; |
| } |
| else |
| { |
| DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", profileLevelType->nProfileIndex); |
| eRet = OMX_ErrorNoMore; |
| } |
| } |
| else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) |
| { |
| if (profileLevelType->nProfileIndex == 0) |
| { |
| profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileSimple; |
| profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5; |
| } |
| else if(profileLevelType->nProfileIndex == 1) |
| { |
| profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple; |
| profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5; |
| } |
| else |
| { |
| DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", profileLevelType->nProfileIndex); |
| eRet = OMX_ErrorNoMore; |
| } |
| } |
| } |
| else |
| { |
| DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queries on Input port only %d\n", profileLevelType->nPortIndex); |
| eRet = OMX_ErrorBadPortIndex; |
| } |
| return eRet; |
| } |
| #endif |
| #ifdef MAX_RES_1080P |
| OMX_ERRORTYPE omx_vdec::get_supported_profile_level_for_1080p(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType) |
| { |
| OMX_ERRORTYPE eRet = OMX_ErrorNone; |
| if(!profileLevelType) |
| return OMX_ErrorBadParameter; |
| |
| if(profileLevelType->nPortIndex == 0) { |
| if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) |
| { |
| if (profileLevelType->nProfileIndex == 0) |
| { |
| profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline; |
| profileLevelType->eLevel = OMX_VIDEO_AVCLevel4; |
| |
| } |
| else if (profileLevelType->nProfileIndex == 1) |
| { |
| profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain; |
| profileLevelType->eLevel = OMX_VIDEO_AVCLevel4; |
| } |
| else if(profileLevelType->nProfileIndex == 2) |
| { |
| profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh; |
| profileLevelType->eLevel = OMX_VIDEO_AVCLevel4; |
| } |
| else |
| { |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", |
| profileLevelType->nProfileIndex); |
| eRet = OMX_ErrorNoMore; |
| } |
| } |
| else if((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE))) |
| { |
| if (profileLevelType->nProfileIndex == 0) |
| { |
| profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline; |
| profileLevelType->eLevel = OMX_VIDEO_H263Level70; |
| } |
| else |
| { |
| DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", profileLevelType->nProfileIndex); |
| eRet = OMX_ErrorNoMore; |
| } |
| } |
| else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) |
| { |
| if (profileLevelType->nProfileIndex == 0) |
| { |
| profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileSimple; |
| profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5; |
| } |
| else if(profileLevelType->nProfileIndex == 1) |
| { |
| profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple; |
| profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5; |
| } |
| else |
| { |
| DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", profileLevelType->nProfileIndex); |
| eRet = OMX_ErrorNoMore; |
| } |
| } |
| else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) |
| { |
| if (profileLevelType->nProfileIndex == 0) |
| { |
| profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileSimple; |
| profileLevelType->eLevel = OMX_VIDEO_MPEG2LevelHL; |
| } |
| else if(profileLevelType->nProfileIndex == 1) |
| { |
| profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileMain; |
| profileLevelType->eLevel = OMX_VIDEO_MPEG2LevelHL; |
| } |
| else |
| { |
| DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n", profileLevelType->nProfileIndex); |
| eRet = OMX_ErrorNoMore; |
| } |
| } |
| } |
| else |
| { |
| DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queries on Input port only %d\n", profileLevelType->nPortIndex); |
| eRet = OMX_ErrorBadPortIndex; |
| } |
| return eRet; |
| } |
| #endif |
| |
| /* ====================================================================== |
| FUNCTION |
| omx_vdec::GetParameter |
| |
| DESCRIPTION |
| OMX Get Parameter method implementation |
| |
| PARAMETERS |
| <TBD>. |
| |
| RETURN VALUE |
| Error None if successful. |
| |
| ========================================================================== */ |
| OMX_ERRORTYPE omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE hComp, |
| OMX_IN OMX_INDEXTYPE paramIndex, |
| OMX_INOUT OMX_PTR paramData) |
| { |
| OMX_ERRORTYPE eRet = OMX_ErrorNone; |
| |
| DEBUG_PRINT_LOW("get_parameter: \n"); |
| if(m_state == OMX_StateInvalid) |
| { |
| DEBUG_PRINT_ERROR("Get Param in Invalid State\n"); |
| return OMX_ErrorInvalidState; |
| } |
| if(paramData == NULL) |
| { |
| DEBUG_PRINT_LOW("Get Param in Invalid paramData \n"); |
| return OMX_ErrorBadParameter; |
| } |
| switch(paramIndex) |
| { |
| case OMX_IndexParamPortDefinition: |
| { |
| OMX_PARAM_PORTDEFINITIONTYPE *portDefn = |
| (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition\n"); |
| eRet = update_portdef(portDefn); |
| if (eRet == OMX_ErrorNone) |
| m_port_def = *portDefn; |
| break; |
| } |
| case OMX_IndexParamVideoInit: |
| { |
| OMX_PORT_PARAM_TYPE *portParamType = |
| (OMX_PORT_PARAM_TYPE *) paramData; |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit\n"); |
| |
| portParamType->nVersion.nVersion = OMX_SPEC_VERSION; |
| portParamType->nSize = sizeof(portParamType); |
| portParamType->nPorts = 2; |
| portParamType->nStartPortNumber = 0; |
| break; |
| } |
| case OMX_IndexParamVideoPortFormat: |
| { |
| OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt = |
| (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData; |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat\n"); |
| |
| portFmt->nVersion.nVersion = OMX_SPEC_VERSION; |
| portFmt->nSize = sizeof(portFmt); |
| |
| if (0 == portFmt->nPortIndex) |
| { |
| if (0 == portFmt->nIndex) |
| { |
| portFmt->eColorFormat = OMX_COLOR_FormatUnused; |
| portFmt->eCompressionFormat = eCompressionFormat; |
| } |
| else |
| { |
| DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoPortFormat:"\ |
| " NoMore compression formats\n"); |
| eRet = OMX_ErrorNoMore; |
| } |
| } |
| else if (1 == portFmt->nPortIndex) |
| { |
| portFmt->eCompressionFormat = OMX_VIDEO_CodingUnused; |
| #ifdef MAX_RES_720P |
| if (0 == portFmt->nIndex) |
| portFmt->eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; |
| else if(1 == portFmt->nIndex) |
| portFmt->eColorFormat = (OMX_COLOR_FORMATTYPE) |
| QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka; |
| #endif |
| #ifdef MAX_RES_1080P |
| if(0 == portFmt->nIndex) |
| portFmt->eColorFormat = (OMX_COLOR_FORMATTYPE) |
| QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka; |
| #endif |
| else if (1 == portFmt->nIndex) { |
| portFmt->eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; |
| } else if (2 == portFmt->nIndex) { |
| portFmt->eColorFormat = OMX_COLOR_FormatYUV420Planar; |
| } |
| else |
| { |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat:"\ |
| " NoMore Color formats\n"); |
| eRet = OMX_ErrorNoMore; |
| } |
| ALOGI("get_parameter: color-format=%x @ index=%d", portFmt->eColorFormat, portFmt->nIndex); |
| } |
| else |
| { |
| DEBUG_PRINT_ERROR("get_parameter: Bad port index %d\n", |
| (int)portFmt->nPortIndex); |
| eRet = OMX_ErrorBadPortIndex; |
| } |
| break; |
| } |
| /*Component should support this port definition*/ |
| case OMX_IndexParamAudioInit: |
| { |
| OMX_PORT_PARAM_TYPE *audioPortParamType = |
| (OMX_PORT_PARAM_TYPE *) paramData; |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit\n"); |
| audioPortParamType->nVersion.nVersion = OMX_SPEC_VERSION; |
| audioPortParamType->nSize = sizeof(audioPortParamType); |
| audioPortParamType->nPorts = 0; |
| audioPortParamType->nStartPortNumber = 0; |
| break; |
| } |
| /*Component should support this port definition*/ |
| case OMX_IndexParamImageInit: |
| { |
| OMX_PORT_PARAM_TYPE *imagePortParamType = |
| (OMX_PORT_PARAM_TYPE *) paramData; |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit\n"); |
| imagePortParamType->nVersion.nVersion = OMX_SPEC_VERSION; |
| imagePortParamType->nSize = sizeof(imagePortParamType); |
| imagePortParamType->nPorts = 0; |
| imagePortParamType->nStartPortNumber = 0; |
| break; |
| |
| } |
| /*Component should support this port definition*/ |
| case OMX_IndexParamOtherInit: |
| { |
| DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamOtherInit %08x\n", |
| paramIndex); |
| eRet =OMX_ErrorUnsupportedIndex; |
| break; |
| } |
| case OMX_IndexParamStandardComponentRole: |
| { |
| OMX_PARAM_COMPONENTROLETYPE *comp_role; |
| comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData; |
| comp_role->nVersion.nVersion = OMX_SPEC_VERSION; |
| comp_role->nSize = sizeof(*comp_role); |
| |
| DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d\n", |
| paramIndex); |
| strlcpy((char*)comp_role->cRole,(const char*)m_cRole, |
| OMX_MAX_STRINGNAME_SIZE); |
| break; |
| } |
| /* Added for parameter test */ |
| case OMX_IndexParamPriorityMgmt: |
| { |
| |
| OMX_PRIORITYMGMTTYPE *priorityMgmType = |
| (OMX_PRIORITYMGMTTYPE *) paramData; |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt\n"); |
| priorityMgmType->nVersion.nVersion = OMX_SPEC_VERSION; |
| priorityMgmType->nSize = sizeof(priorityMgmType); |
| |
| break; |
| } |
| /* Added for parameter test */ |
| case OMX_IndexParamCompBufferSupplier: |
| { |
| OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = |
| (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData; |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier\n"); |
| |
| bufferSupplierType->nSize = sizeof(bufferSupplierType); |
| bufferSupplierType->nVersion.nVersion = OMX_SPEC_VERSION; |
| if(0 == bufferSupplierType->nPortIndex) |
| bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified; |
| else if (1 == bufferSupplierType->nPortIndex) |
| bufferSupplierType->nPortIndex = OMX_BufferSupplyUnspecified; |
| else |
| eRet = OMX_ErrorBadPortIndex; |
| |
| |
| break; |
| } |
| case OMX_IndexParamVideoAvc: |
| { |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc %08x\n", |
| paramIndex); |
| break; |
| } |
| case OMX_IndexParamVideoH263: |
| { |
| DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoH263 %08x\n", |
|