summaryrefslogtreecommitdiff
path: root/msmcobalt/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'msmcobalt/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp')
-rw-r--r--msmcobalt/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp12700
1 files changed, 12700 insertions, 0 deletions
diff --git a/msmcobalt/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp b/msmcobalt/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp
new file mode 100644
index 0000000..90b930a
--- /dev/null
+++ b/msmcobalt/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp
@@ -0,0 +1,12700 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2010 - 2016, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of The Linux Foundation nor
+ the names of its contributors may be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED 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
+
+ This module contains the implementation of the OpenMAX core & component.
+
+*//*========================================================================*/
+
+//////////////////////////////////////////////////////////////////////////////
+// Include Files
+//////////////////////////////////////////////////////////////////////////////
+
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+
+#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 <stdlib.h>
+#include <media/hardware/HardwareAPI.h>
+#include <media/msm_media_info.h>
+#include <sys/eventfd.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
+
+#include <qdMetaData.h>
+#include <gralloc_priv.h>
+
+#ifdef ANDROID_JELLYBEAN_MR2
+#include "QComOMXMetadata.h"
+#endif
+
+#ifdef USE_EGL_IMAGE_GPU
+#include <EGL/egl.h>
+#include <EGL/eglQCOM.h>
+#define EGL_BUFFER_HANDLE 0x4F00
+#define EGL_BUFFER_OFFSET 0x4F01
+#endif
+
+#define BUFFER_LOG_LOC "/data/misc/media"
+
+#ifdef OUTPUT_EXTRADATA_LOG
+FILE *outputExtradataFile;
+char output_extradata_filename [] = "/data/misc/media/extradata";
+#endif
+
+#define DEFAULT_FPS 30
+#define MAX_SUPPORTED_FPS 240
+#define DEFAULT_WIDTH_ALIGNMENT 128
+#define DEFAULT_HEIGHT_ALIGNMENT 32
+
+#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
+#define POLL_TIMEOUT 0x7fffffff
+
+#define MEM_DEVICE "/dev/ion"
+
+#ifdef _ANDROID_
+extern "C" {
+#include<utils/Log.h>
+}
+#endif//_ANDROID_
+
+#define SZ_4K 0x1000
+#define SZ_1M 0x100000
+
+#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); }
+#define EXTRADATA_IDX(__num_planes) ((__num_planes) ? (__num_planes) - 1 : 0)
+#define ALIGN(x, to_align) ((((unsigned) x) + (to_align - 1)) & ~(to_align - 1))
+
+#define DEFAULT_EXTRADATA (OMX_INTERLACE_EXTRADATA | OMX_FRAMEPACK_EXTRADATA | OMX_OUTPUTCROP_EXTRADATA | OMX_DISPLAY_INFO_EXTRADATA)
+#define DEFAULT_CONCEAL_COLOR "32784" //0x8010, black by default
+
+#ifndef ION_FLAG_CP_BITSTREAM
+#define ION_FLAG_CP_BITSTREAM 0
+#endif
+
+#ifndef ION_FLAG_CP_PIXEL
+#define ION_FLAG_CP_PIXEL 0
+#endif
+
+#ifdef MASTER_SIDE_CP
+#define MEM_HEAP_ID ION_SECURE_HEAP_ID
+#define SECURE_ALIGN SZ_4K
+#define SECURE_FLAGS_INPUT_BUFFER (ION_SECURE | ION_FLAG_CP_BITSTREAM)
+#define SECURE_FLAGS_OUTPUT_BUFFER (ION_SECURE | ION_FLAG_CP_PIXEL)
+#else //SLAVE_SIDE_CP
+#define MEM_HEAP_ID ION_CP_MM_HEAP_ID
+#define SECURE_ALIGN SZ_1M
+#define SECURE_FLAGS_INPUT_BUFFER ION_SECURE
+#define SECURE_FLAGS_OUTPUT_BUFFER ION_SECURE
+#endif
+
+static OMX_U32 maxSmoothStreamingWidth = 1920;
+static OMX_U32 maxSmoothStreamingHeight = 1088;
+
+void* async_message_thread (void *input)
+{
+ OMX_BUFFERHEADERTYPE *buffer;
+ struct v4l2_plane plane[VIDEO_MAX_PLANES];
+ struct pollfd pfds[2];
+ struct v4l2_buffer v4l2_buf;
+ memset((void *)&v4l2_buf,0,sizeof(v4l2_buf));
+ struct v4l2_event dqevent;
+ omx_vdec *omx = reinterpret_cast<omx_vdec*>(input);
+ pfds[0].events = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLRDBAND | POLLPRI;
+ pfds[1].events = POLLIN | POLLERR;
+ pfds[0].fd = omx->drv_ctx.video_driver_fd;
+ pfds[1].fd = omx->m_poll_efd;
+ int error_code = 0,rc=0,bytes_read = 0,bytes_written = 0;
+ DEBUG_PRINT_HIGH("omx_vdec: Async thread start");
+ prctl(PR_SET_NAME, (unsigned long)"VideoDecCallBackThread", 0, 0, 0);
+ while (!omx->async_thread_force_stop) {
+ rc = poll(pfds, 2, POLL_TIMEOUT);
+ if (!rc) {
+ DEBUG_PRINT_ERROR("Poll timedout");
+ break;
+ } else if (rc < 0 && errno != EINTR && errno != EAGAIN) {
+ DEBUG_PRINT_ERROR("Error while polling: %d, errno = %d", rc, errno);
+ break;
+ }
+ if ((pfds[1].revents & POLLIN) || (pfds[1].revents & POLLERR)) {
+ DEBUG_PRINT_HIGH("async_message_thread interrupted to be exited");
+ break;
+ }
+ if ((pfds[0].revents & POLLIN) || (pfds[0].revents & POLLRDNORM)) {
+ struct vdec_msginfo vdec_msg;
+ memset(&vdec_msg, 0, sizeof(vdec_msg));
+ v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ v4l2_buf.memory = V4L2_MEMORY_USERPTR;
+ v4l2_buf.length = omx->drv_ctx.num_planes;
+ v4l2_buf.m.planes = plane;
+ while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) {
+ vdec_msg.msgcode=VDEC_MSG_RESP_OUTPUT_BUFFER_DONE;
+ vdec_msg.status_code=VDEC_S_SUCCESS;
+ vdec_msg.msgdata.output_frame.client_data=(void*)&v4l2_buf;
+ vdec_msg.msgdata.output_frame.len=plane[0].bytesused;
+ vdec_msg.msgdata.output_frame.bufferaddr=(void*)plane[0].m.userptr;
+ vdec_msg.msgdata.output_frame.time_stamp= ((uint64_t)v4l2_buf.timestamp.tv_sec * (uint64_t)1000000) +
+ (uint64_t)v4l2_buf.timestamp.tv_usec;
+
+ if (omx->async_message_process(input,&vdec_msg) < 0) {
+ DEBUG_PRINT_HIGH("async_message_thread Exited");
+ break;
+ }
+ }
+ }
+ if ((pfds[0].revents & POLLOUT) || (pfds[0].revents & POLLWRNORM)) {
+ struct vdec_msginfo vdec_msg;
+ v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ v4l2_buf.memory = V4L2_MEMORY_USERPTR;
+ v4l2_buf.length = 1;
+ v4l2_buf.m.planes = plane;
+ while (!ioctl(pfds[0].fd, VIDIOC_DQBUF, &v4l2_buf)) {
+ vdec_msg.msgcode=VDEC_MSG_RESP_INPUT_BUFFER_DONE;
+ vdec_msg.status_code=VDEC_S_SUCCESS;
+ vdec_msg.msgdata.input_frame_clientdata=(void*)&v4l2_buf;
+ if (omx->async_message_process(input,&vdec_msg) < 0) {
+ DEBUG_PRINT_HIGH("async_message_thread Exited");
+ break;
+ }
+ }
+ }
+ if (pfds[0].revents & POLLPRI) {
+ rc = ioctl(pfds[0].fd, VIDIOC_DQEVENT, &dqevent);
+ if (dqevent.type == V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT ) {
+ struct vdec_msginfo vdec_msg;
+ unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
+
+ vdec_msg.msgcode=VDEC_MSG_EVT_CONFIG_CHANGED;
+ vdec_msg.status_code=VDEC_S_SUCCESS;
+ vdec_msg.msgdata.output_frame.picsize.frame_height = ptr[0];
+ vdec_msg.msgdata.output_frame.picsize.frame_width = ptr[1];
+ DEBUG_PRINT_HIGH("VIDC Port Reconfig received insufficient");
+ if(ptr[2] & V4L2_EVENT_BITDEPTH_FLAG) {
+ omx->dpb_bit_depth = ptr[3];
+ DEBUG_PRINT_HIGH("VIDC Port Reconfig Bitdepth change - %d", ptr[3]);
+ }
+ if(ptr[2] & V4L2_EVENT_PICSTRUCT_FLAG) {
+ omx->m_progressive = ptr[4];
+ DEBUG_PRINT_HIGH("VIDC Port Reconfig PicStruct change - %d", ptr[4]);
+ }
+ if (omx->async_message_process(input,&vdec_msg) < 0) {
+ DEBUG_PRINT_HIGH("async_message_thread Exited");
+ break;
+ }
+ } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_FLUSH_DONE) {
+ struct vdec_msginfo vdec_msg;
+ vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_INPUT_DONE;
+ vdec_msg.status_code=VDEC_S_SUCCESS;
+ DEBUG_PRINT_HIGH("VIDC Input Flush Done Recieved");
+ if (omx->async_message_process(input,&vdec_msg) < 0) {
+ DEBUG_PRINT_HIGH("async_message_thread Exited");
+ break;
+ }
+ vdec_msg.msgcode=VDEC_MSG_RESP_FLUSH_OUTPUT_DONE;
+ vdec_msg.status_code=VDEC_S_SUCCESS;
+ DEBUG_PRINT_HIGH("VIDC Output Flush Done Recieved");
+ if (omx->async_message_process(input,&vdec_msg) < 0) {
+ DEBUG_PRINT_HIGH("async_message_thread Exited");
+ break;
+ }
+ } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_OVERLOAD) {
+ struct vdec_msginfo vdec_msg;
+ vdec_msg.msgcode=VDEC_MSG_EVT_HW_OVERLOAD;
+ vdec_msg.status_code=VDEC_S_SUCCESS;
+ DEBUG_PRINT_ERROR("HW Overload received");
+ if (omx->async_message_process(input,&vdec_msg) < 0) {
+ DEBUG_PRINT_HIGH("async_message_thread Exited");
+ break;
+ }
+ } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED) {
+ struct vdec_msginfo vdec_msg;
+ vdec_msg.msgcode=VDEC_MSG_EVT_HW_UNSUPPORTED;
+ vdec_msg.status_code=VDEC_S_SUCCESS;
+ DEBUG_PRINT_ERROR("HW Unsupported received");
+ if (omx->async_message_process(input,&vdec_msg) < 0) {
+ DEBUG_PRINT_HIGH("async_message_thread Exited");
+ break;
+ }
+ } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_SYS_ERROR) {
+ struct vdec_msginfo vdec_msg;
+ vdec_msg.msgcode = VDEC_MSG_EVT_HW_ERROR;
+ vdec_msg.status_code = VDEC_S_SUCCESS;
+ DEBUG_PRINT_HIGH("SYS Error Recieved");
+ if (omx->async_message_process(input,&vdec_msg) < 0) {
+ DEBUG_PRINT_HIGH("async_message_thread Exited");
+ break;
+ }
+ } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE) {
+ unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
+
+ DEBUG_PRINT_LOW("REFERENCE RELEASE EVENT RECVD fd = %d offset = %d", ptr[0], ptr[1]);
+ } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER) {
+ unsigned int *ptr = (unsigned int *)(void *)dqevent.u.data;
+ struct vdec_msginfo vdec_msg;
+
+ DEBUG_PRINT_LOW("Release unqueued buffer event recvd fd = %d offset = %d", ptr[0], ptr[1]);
+
+ v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ v4l2_buf.memory = V4L2_MEMORY_USERPTR;
+ v4l2_buf.length = omx->drv_ctx.num_planes;
+ v4l2_buf.m.planes = plane;
+ v4l2_buf.index = ptr[5];
+ v4l2_buf.flags = 0;
+
+ vdec_msg.msgcode = VDEC_MSG_RESP_OUTPUT_BUFFER_DONE;
+ vdec_msg.status_code = VDEC_S_SUCCESS;
+ vdec_msg.msgdata.output_frame.client_data = (void*)&v4l2_buf;
+ vdec_msg.msgdata.output_frame.len = 0;
+ vdec_msg.msgdata.output_frame.bufferaddr = (void*)(intptr_t)ptr[2];
+ vdec_msg.msgdata.output_frame.time_stamp = ((uint64_t)ptr[3] * (uint64_t)1000000) +
+ (uint64_t)ptr[4];
+ if (omx->async_message_process(input,&vdec_msg) < 0) {
+ DEBUG_PRINT_HIGH("async_message_thread Exitedn");
+ break;
+ }
+ } else {
+ DEBUG_PRINT_HIGH("VIDC Some Event recieved");
+ continue;
+ }
+ }
+ }
+ DEBUG_PRINT_HIGH("omx_vdec: Async thread stop");
+ return NULL;
+}
+
+void* message_thread_dec(void *input)
+{
+ omx_vdec* omx = reinterpret_cast<omx_vdec*>(input);
+ unsigned char id;
+ int n;
+
+ fd_set readFds;
+ int res = 0;
+ struct timeval tv;
+
+ DEBUG_PRINT_HIGH("omx_vdec: message thread start");
+ prctl(PR_SET_NAME, (unsigned long)"VideoDecMsgThread", 0, 0, 0);
+ while (!omx->message_thread_stop) {
+
+ tv.tv_sec = 2;
+ tv.tv_usec = 0;
+
+ FD_ZERO(&readFds);
+ FD_SET(omx->m_pipe_in, &readFds);
+
+ res = select(omx->m_pipe_in + 1, &readFds, NULL, NULL, &tv);
+ if (res < 0) {
+ DEBUG_PRINT_ERROR("select() ERROR: %s", strerror(errno));
+ continue;
+ } else if (res == 0 /*timeout*/ || omx->message_thread_stop) {
+ continue;
+ }
+
+ 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_LOW("ERROR: read from pipe failed, ret %d errno %d", n, errno);
+ break;
+ }
+ }
+ DEBUG_PRINT_HIGH("omx_vdec: message thread stop");
+ 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", id,omx->m_pipe_out);
+ ret_value = write(omx->m_pipe_out, &id, 1);
+ if (ret_value <= 0) {
+ DEBUG_PRINT_ERROR("post_message to pipe failed : %s", strerror(errno));
+ } else {
+ DEBUG_PRINT_LOW("post_message to pipe done %d",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 long p1, unsigned long p2, unsigned long 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", __func__);
+ }
+ return ret;
+}
+
+// omx cmd queue pop
+bool omx_vdec::omx_cmd_queue::pop_entry(unsigned long *p1, unsigned long *p2, unsigned long *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,
+ ion_user_handle_t handle, int ionMapfd)
+{
+ (void) devicefd;
+ (void) size;
+ (void) base;
+ (void) handle;
+ (void) ionMapfd;
+ // 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_error_propogated(false),
+ m_state(OMX_StateInvalid),
+ m_app_data(NULL),
+ m_inp_mem_ptr(NULL),
+ m_out_mem_ptr(NULL),
+ input_flush_progress (false),
+ output_flush_progress (false),
+ input_use_buffer (false),
+ output_use_buffer (false),
+ ouput_egl_buffers(false),
+ m_use_output_pmem(OMX_FALSE),
+ m_out_mem_region_smi(OMX_FALSE),
+ m_out_pvt_entry_pmem(OMX_FALSE),
+ 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),
+#ifdef _ANDROID_
+ m_heap_ptr(NULL),
+#endif
+ m_inp_bEnabled(OMX_TRUE),
+ m_out_bEnabled(OMX_TRUE),
+ m_in_alloc_cnt(0),
+ m_platform_list(NULL),
+ m_platform_entry(NULL),
+ m_pmem_info(NULL),
+ h264_parser(NULL),
+ arbitrary_bytes (true),
+ psource_frame (NULL),
+ pdest_frame (NULL),
+ m_inp_heap_ptr (NULL),
+ m_phdr_pmem_ptr(NULL),
+ m_heap_inp_bm_count (0),
+ codec_type_parse ((codec_type)0),
+ first_frame_meta (true),
+ frame_count (0),
+ nal_count (0),
+ nal_length(0),
+ look_ahead_nal (false),
+ first_frame(0),
+ first_buffer(NULL),
+ first_frame_size (0),
+ m_device_file_ptr(NULL),
+ m_vc1_profile((vc1_profile_type)0),
+ h264_last_au_ts(LLONG_MAX),
+ h264_last_au_flags(0),
+ m_disp_hor_size(0),
+ m_disp_vert_size(0),
+ prev_ts(LLONG_MAX),
+ prev_ts_actual(LLONG_MAX),
+ rst_prev_ts(true),
+ frm_int(0),
+ in_reconfig(false),
+ m_display_id(NULL),
+ client_extradata(0),
+ m_reject_avc_1080p_mp (0),
+#ifdef _ANDROID_
+ m_enable_android_native_buffers(OMX_FALSE),
+ m_use_android_native_buffers(OMX_FALSE),
+#endif
+ m_desc_buffer_ptr(NULL),
+ secure_mode(false),
+ allocate_native_handle(false),
+ m_other_extradata(NULL),
+ m_profile(0),
+ client_set_fps(false),
+ stereo_output_mode(HAL_NO_3D),
+ m_last_rendered_TS(-1),
+ m_queued_codec_config_count(0),
+ current_perf_level(V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL),
+ secure_scaling_to_non_secure_opb(false),
+ m_force_compressed_for_dpb(false),
+ m_is_display_session(false)
+{
+ m_pipe_in = -1;
+ m_pipe_out = -1;
+ m_poll_efd = -1;
+ drv_ctx.video_driver_fd = -1;
+ drv_ctx.extradata_info.ion.fd_ion_data.fd = -1;
+ /* Assumption is that , to begin with , we have all the frames with decoder */
+ DEBUG_PRINT_HIGH("In %u bit OMX vdec Constructor", (unsigned int)sizeof(long) * 8);
+ memset(&m_debug,0,sizeof(m_debug));
+#ifdef _ANDROID_
+ char property_value[PROPERTY_VALUE_MAX] = {0};
+ property_get("vidc.debug.level", property_value, "1");
+ debug_level = atoi(property_value);
+ property_value[0] = '\0';
+
+ DEBUG_PRINT_HIGH("In OMX vdec Constructor");
+
+ 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;
+ }
+ prev_n_filled_len = 0;
+ property_value[0] = '\0';
+ 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] = '\0';
+ 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);
+
+ property_value[0] = '\0';
+ property_get("vidc.dec.profile.check", property_value, "0");
+ m_reject_avc_1080p_mp = atoi(property_value);
+ DEBUG_PRINT_HIGH("vidc.dec.profile.check value is %d",m_reject_avc_1080p_mp);
+
+ property_value[0] = '\0';
+ property_get("vidc.dec.log.in", property_value, "0");
+ m_debug.in_buffer_log = atoi(property_value);
+
+ property_value[0] = '\0';
+ property_get("vidc.dec.log.out", property_value, "0");
+ m_debug.out_buffer_log = atoi(property_value);
+ snprintf(m_debug.log_loc, PROPERTY_VALUE_MAX, "%s", BUFFER_LOG_LOC);
+
+ property_value[0] = '\0';
+ property_get("vidc.dec.meta.log.out", property_value, "0");
+ m_debug.out_meta_buffer_log = atoi(property_value);
+ snprintf(m_debug.log_loc, PROPERTY_VALUE_MAX, "%s", BUFFER_LOG_LOC);
+
+ property_value[0] = '\0';
+ property_get("vidc.log.loc", property_value, "");
+ if (*property_value)
+ strlcpy(m_debug.log_loc, property_value, PROPERTY_VALUE_MAX);
+
+ property_value[0] = '\0';
+ property_get("vidc.dec.120fps.enabled", property_value, "0");
+
+ //if this feature is not enabled then reset this value -ve
+ if(atoi(property_value)) {
+ DEBUG_PRINT_LOW("feature 120 FPS decode enabled");
+ m_last_rendered_TS = 0;
+ }
+
+ property_value[0] = '\0';
+ property_get("vidc.dec.debug.dyn.disabled", property_value, "0");
+ m_disable_dynamic_buf_mode = atoi(property_value);
+ DEBUG_PRINT_HIGH("vidc.dec.debug.dyn.disabled value is %d",m_disable_dynamic_buf_mode);
+
+#ifdef _UBWC_
+ property_value[0] = '\0';
+ property_get("debug.gralloc.gfx_ubwc_disable", property_value, "0");
+ m_disable_ubwc_mode = atoi(property_value);
+ DEBUG_PRINT_HIGH("UBWC mode is %s", m_disable_ubwc_mode ? "disabled" : "enabled");
+#else
+ m_disable_ubwc_mode = true;
+#endif
+#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(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
+ memset(&m_custom_buffersize, 0, sizeof(m_custom_buffersize));
+ memset(&m_client_color_space, 0, sizeof(DescribeColorAspectsParams));
+ memset(&m_internal_color_space, 0, sizeof(DescribeColorAspectsParams));
+ m_demux_entries = 0;
+ msg_thread_id = 0;
+ async_thread_id = 0;
+ msg_thread_created = false;
+ async_thread_created = false;
+ async_thread_force_stop = false;
+ message_thread_stop = false;
+#ifdef _ANDROID_ICS_
+ memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
+#endif
+ memset(&drv_ctx.extradata_info, 0, sizeof(drv_ctx.extradata_info));
+
+ /* invalidate m_frame_pack_arrangement */
+ memset(&m_frame_pack_arrangement, 0, sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
+ m_frame_pack_arrangement.cancel_flag = 1;
+
+ drv_ctx.timestamp_adjust = false;
+ m_vendor_config.pData = NULL;
+ pthread_mutex_init(&m_lock, NULL);
+ pthread_mutex_init(&c_lock, NULL);
+ pthread_mutex_init(&buf_lock, NULL);
+ sem_init(&m_cmd_lock,0,0);
+ sem_init(&m_safe_flush, 0, 0);
+ streaming[CAPTURE_PORT] =
+ streaming[OUTPUT_PORT] = false;
+#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);
+ dynamic_buf_mode = false;
+ out_dynamic_list = NULL;
+ is_down_scalar_enabled = false;
+ m_downscalar_width = 0;
+ m_downscalar_height = 0;
+ m_force_down_scalar = 0;
+ m_reconfig_height = 0;
+ m_reconfig_width = 0;
+ m_smoothstreaming_mode = false;
+ m_smoothstreaming_width = 0;
+ m_smoothstreaming_height = 0;
+ is_q6_platform = false;
+ m_perf_control.send_hint_to_mpctl(true);
+ m_input_pass_buffer_fd = false;
+ memset(&m_extradata_info, 0, sizeof(m_extradata_info));
+ m_client_color_space.nPortIndex = (OMX_U32)OMX_CORE_INPUT_PORT_INDEX;
+ m_client_color_space.sAspects.mRange = ColorAspects::RangeUnspecified;
+ m_client_color_space.sAspects.mPrimaries = ColorAspects::PrimariesUnspecified;
+ m_client_color_space.sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
+ m_client_color_space.sAspects.mTransfer = ColorAspects::TransferUnspecified;
+
+ m_internal_color_space.nPortIndex = (OMX_U32)OMX_CORE_OUTPUT_PORT_INDEX;
+ m_internal_color_space.sAspects.mRange = ColorAspects::RangeUnspecified;
+ m_internal_color_space.sAspects.mPrimaries = ColorAspects::PrimariesUnspecified;
+ m_internal_color_space.sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
+ m_internal_color_space.sAspects.mTransfer = ColorAspects::TransferUnspecified;
+ m_internal_color_space.nSize = sizeof(DescribeColorAspectsParams);
+}
+
+static const int event_type[] = {
+ V4L2_EVENT_MSM_VIDC_FLUSH_DONE,
+ V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_SUFFICIENT,
+ V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT,
+ V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_BITDEPTH_CHANGED_INSUFFICIENT,
+ V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE,
+ V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER,
+ V4L2_EVENT_MSM_VIDC_SYS_ERROR,
+ V4L2_EVENT_MSM_VIDC_HW_OVERLOAD,
+ V4L2_EVENT_MSM_VIDC_HW_UNSUPPORTED
+};
+
+static OMX_ERRORTYPE subscribe_to_events(int fd)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ struct v4l2_event_subscription sub;
+ int array_sz = sizeof(event_type)/sizeof(int);
+ int i,rc;
+ if (fd < 0) {
+ DEBUG_PRINT_ERROR("Invalid input: %d", fd);
+ return OMX_ErrorBadParameter;
+ }
+
+ for (i = 0; i < array_sz; ++i) {
+ memset(&sub, 0, sizeof(sub));
+ sub.type = event_type[i];
+ rc = ioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
+ if (rc) {
+ DEBUG_PRINT_ERROR("Failed to subscribe event: 0x%x", sub.type);
+ break;
+ }
+ }
+ if (i < array_sz) {
+ for (--i; i >=0 ; i--) {
+ memset(&sub, 0, sizeof(sub));
+ sub.type = event_type[i];
+ rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
+ if (rc)
+ DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
+ }
+ eRet = OMX_ErrorNotImplemented;
+ }
+ return eRet;
+}
+
+
+static OMX_ERRORTYPE unsubscribe_to_events(int fd)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ struct v4l2_event_subscription sub;
+ int array_sz = sizeof(event_type)/sizeof(int);
+ int i,rc;
+ if (fd < 0) {
+ DEBUG_PRINT_ERROR("Invalid input: %d", fd);
+ return OMX_ErrorBadParameter;
+ }
+
+ for (i = 0; i < array_sz; ++i) {
+ memset(&sub, 0, sizeof(sub));
+ sub.type = event_type[i];
+ rc = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
+ if (rc) {
+ DEBUG_PRINT_ERROR("Failed to unsubscribe event: 0x%x", sub.type);
+ break;
+ }
+ }
+ return eRet;
+}
+
+/* ======================================================================
+ 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 (msg_thread_created) {
+ DEBUG_PRINT_HIGH("Signalling close to OMX Msg Thread");
+ message_thread_stop = true;
+ post_message(this, OMX_COMPONENT_CLOSE_MSG);
+ DEBUG_PRINT_HIGH("Waiting on OMX Msg Thread exit");
+ pthread_join(msg_thread_id,NULL);
+ }
+ close(m_pipe_in);
+ close(m_pipe_out);
+ m_pipe_in = -1;
+ m_pipe_out = -1;
+ DEBUG_PRINT_HIGH("Waiting on OMX Async Thread exit");
+ if(eventfd_write(m_poll_efd, 1)) {
+ DEBUG_PRINT_ERROR("eventfd_write failed for fd: %d, errno = %d, force stop async_thread", m_poll_efd, errno);
+ async_thread_force_stop = true;
+ }
+
+ if (async_thread_created)
+ pthread_join(async_thread_id,NULL);
+ unsubscribe_to_events(drv_ctx.video_driver_fd);
+ close(m_poll_efd);
+ close(drv_ctx.video_driver_fd);
+ pthread_mutex_destroy(&m_lock);
+ pthread_mutex_destroy(&c_lock);
+ pthread_mutex_destroy(&buf_lock);
+ sem_destroy(&m_cmd_lock);
+ if (perf_flag) {
+ DEBUG_PRINT_HIGH("--> TOTAL PROCESSING TIME");
+ dec_time.end();
+ }
+ DEBUG_PRINT_INFO("Exit OMX vdec Destructor: fd=%d",drv_ctx.video_driver_fd);
+ m_perf_control.send_hint_to_mpctl(false);
+}
+
+int release_buffers(omx_vdec* obj, enum vdec_buffer buffer_type)
+{
+ struct v4l2_requestbuffers bufreq;
+ int rc = 0;
+ if (buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
+ bufreq.memory = V4L2_MEMORY_USERPTR;
+ bufreq.count = 0;
+ bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ rc = ioctl(obj->drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
+ } else if(buffer_type == VDEC_BUFFER_TYPE_INPUT) {
+ bufreq.memory = V4L2_MEMORY_USERPTR;
+ bufreq.count = 0;
+ bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ rc = ioctl(obj->drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
+ }
+ return rc;
+}
+
+OMX_ERRORTYPE omx_vdec::set_dpb(bool is_split_mode, int dpb_color_format)
+{
+ int rc = 0;
+ struct v4l2_ext_control ctrl[2];
+ struct v4l2_ext_controls controls;
+
+ DEBUG_PRINT_HIGH("DPB mode: %s DPB color format: %s OPB color format: %s",
+ is_split_mode ? "split" : "combined",
+ dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC ? "nv12_ubwc":
+ dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC ? "nv12_10bit_ubwc":
+ dpb_color_format == V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE ? "same as opb":
+ "unknown",
+ capture_capability == V4L2_PIX_FMT_NV12 ? "nv12":
+ capture_capability == V4L2_PIX_FMT_NV12_UBWC ? "nv12_ubwc":
+ "unknown");
+
+ ctrl[0].id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE;
+ if (is_split_mode) {
+ ctrl[0].value = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_SECONDARY;
+ } else {
+ ctrl[0].value = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_PRIMARY;
+ }
+
+ ctrl[1].id = V4L2_CID_MPEG_VIDC_VIDEO_DPB_COLOR_FORMAT;
+ ctrl[1].value = dpb_color_format;
+
+ controls.count = 2;
+ controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
+ controls.controls = ctrl;
+
+ rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_EXT_CTRLS, &controls);
+ if (rc) {
+ DEBUG_PRINT_ERROR("Failed to set ext ctrls for opb_dpb: %d\n", rc);
+ return OMX_ErrorUnsupportedSetting;
+ }
+ return OMX_ErrorNone;
+}
+
+
+OMX_ERRORTYPE omx_vdec::decide_dpb_buffer_mode(bool force_split_mode)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ struct v4l2_format fmt;
+ int rc = 0;
+
+ if (!BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_IDLE_PENDING) &&
+ !BITMASK_PRESENT(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
+ DEBUG_PRINT_LOW("Invalid state to decide on dpb-opb split");
+ return eRet;
+ }
+
+ bool cpu_access = capture_capability != V4L2_PIX_FMT_NV12_UBWC;
+
+ if (cpu_access) {
+ if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_8) {
+ if ((m_force_compressed_for_dpb || (m_progressive && (eCompressionFormat != OMX_VIDEO_CodingVP9))) &&
+ !force_split_mode && !m_disable_split_mode && !drv_ctx.idr_only_decoding) {
+ /* Disabled split mode for VP9. In split mode the DPB buffers are part of the internal
+ * scratch buffers and the driver does not does the reference buffer management for
+ * scratch buffers. In case of VP9 with spatial scalability, when a sequence changed
+ * event is received with the new resolution, and when a flush is sent by the driver, it
+ * releases all the references of internal scratch buffers. However as per the VP9
+ * spatial scalability, even after the flush, the buffers which have not yet received
+ * release reference event should not be unmapped and freed. Currently in driver,
+ * reference buffer management of the internal scratch buffer is not implemented
+ * and hence the DPB buffers get unmapped. For other codecs it does not matter
+ * as with the new SPS/PPS, the DPB is flushed.
+ */
+ //split DPB-OPB
+ //DPB -> UBWC , OPB -> Linear
+ eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC);
+ } else if (force_split_mode) {
+ //DPB -> Linear, OPB -> Linear
+ eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE);
+ } else {
+ //DPB-OPB combined linear
+ eRet = set_dpb(false, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE);
+ }
+ } else if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10) {
+ //split DPB-OPB
+ //DPB -> UBWC, OPB -> Linear
+ eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC);
+ }
+ } else { //no cpu access
+ if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_8) {
+ if (force_split_mode) {
+ //split DPB-OPB
+ //DPB -> UBWC, OPB -> UBWC
+ eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_UBWC);
+ } else {
+ //DPB-OPB combined UBWC
+ eRet = set_dpb(false, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_NONE);
+ }
+ } else if (dpb_bit_depth == MSM_VIDC_BIT_DEPTH_10) {
+ //split DPB-OPB
+ //DPB -> UBWC, OPB -> UBWC
+ eRet = set_dpb(true, V4L2_MPEG_VIDC_VIDEO_DPB_COLOR_FMT_TP10_UBWC);
+ }
+ }
+ if (eRet) {
+ DEBUG_PRINT_HIGH("Failed to set DPB buffer mode: %d", eRet);
+ }
+
+ //Restore the capture format again here, because
+ //in switching between different DPB-OPB modes, the pixelformat
+ //on capture port may be changed. Don't change resolutions.
+ memset(&fmt, 0x0, sizeof(struct v4l2_format));
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
+ fmt.fmt.pix_mp.pixelformat = capture_capability;
+ rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
+ if (rc) {
+ DEBUG_PRINT_ERROR("%s: Failed set format on capture mplane", __func__);
+ return OMX_ErrorUnsupportedSetting;
+ }
+
+ return eRet;
+}
+
+int omx_vdec::enable_downscalar()
+{
+ int rc = 0;
+ struct v4l2_control control;
+ struct v4l2_format fmt;
+
+ if (is_down_scalar_enabled) {
+ DEBUG_PRINT_LOW("%s: already enabled", __func__);
+ return 0;
+ }
+
+ DEBUG_PRINT_LOW("omx_vdec::enable_downscalar");
+ rc = decide_dpb_buffer_mode(true);
+ if (rc) {
+ DEBUG_PRINT_ERROR("%s: decide_dpb_buffer_mode Failed ", __func__);
+ return rc;
+ }
+ is_down_scalar_enabled = true;
+
+ memset(&control, 0x0, sizeof(struct v4l2_control));
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_KEEP_ASPECT_RATIO;
+ control.value = 1;
+ rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
+ if (rc) {
+ DEBUG_PRINT_ERROR("%s: Failed to set VIDEO_KEEP_ASPECT_RATIO", __func__);
+ return rc;
+ }
+
+ return 0;
+}
+
+int omx_vdec::disable_downscalar()
+{
+ int rc = 0;
+ struct v4l2_control control;
+
+ if (!is_down_scalar_enabled) {
+ DEBUG_PRINT_LOW("omx_vdec::disable_downscalar: already disabled");
+ return 0;
+ }
+
+ rc = decide_dpb_buffer_mode(false);
+ if (rc < 0) {
+ DEBUG_PRINT_ERROR("%s:decide_dpb_buffer_mode failed\n", __func__);
+ return rc;
+ }
+ is_down_scalar_enabled = false;
+
+ return rc;
+}
+
+int omx_vdec::decide_downscalar()
+{
+ int rc = 0;
+ struct v4l2_format fmt;
+ enum color_fmts color_format;
+ OMX_U32 width, height;
+
+ if (!m_downscalar_width || !m_downscalar_height) {
+ DEBUG_PRINT_LOW("%s: downscalar not supported", __func__);
+ return 0;
+ }
+
+ if (m_force_down_scalar) {
+ DEBUG_PRINT_LOW("%s: m_force_down_scalar %d ", __func__, m_force_down_scalar);
+ return 0;
+ }
+
+ memset(&fmt, 0x0, sizeof(struct v4l2_format));
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ fmt.fmt.pix_mp.pixelformat = capture_capability;
+ rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
+ if (rc < 0) {
+ DEBUG_PRINT_ERROR("%s: Failed to get format on capture mplane", __func__);
+ return rc;
+ }
+
+ height = fmt.fmt.pix_mp.height;
+ width = fmt.fmt.pix_mp.width;
+
+ DEBUG_PRINT_HIGH("%s: driver wxh = %dx%d, downscalar wxh = %dx%d m_is_display_session = %d", __func__,
+ fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height, m_downscalar_width, m_downscalar_height, m_is_display_session);
+
+ if ((fmt.fmt.pix_mp.width * fmt.fmt.pix_mp.height >= m_downscalar_width * m_downscalar_height) &&
+ m_is_display_session) {
+ rc = enable_downscalar();
+ if (rc < 0) {
+ DEBUG_PRINT_ERROR("%s: enable_downscalar failed\n", __func__);
+ return rc;
+ }
+
+ width = m_downscalar_width > fmt.fmt.pix_mp.width ?
+ fmt.fmt.pix_mp.width : m_downscalar_width;
+ height = m_downscalar_height > fmt.fmt.pix_mp.height ?
+ fmt.fmt.pix_mp.height : m_downscalar_height;
+ switch (capture_capability) {
+ case V4L2_PIX_FMT_NV12:
+ color_format = COLOR_FMT_NV12;
+ break;
+ case V4L2_PIX_FMT_NV12_UBWC:
+ color_format = COLOR_FMT_NV12_UBWC;
+ break;
+ case V4L2_PIX_FMT_NV12_TP10_UBWC:
+ color_format = COLOR_FMT_NV12_BPP10_UBWC;
+ break;
+ default:
+ DEBUG_PRINT_ERROR("Color format not recognized\n");
+ rc = OMX_ErrorUndefined;
+ return rc;
+ }
+ } else {
+
+ rc = disable_downscalar();
+ if (rc < 0) {
+ DEBUG_PRINT_ERROR("%s: disable_downscalar failed\n", __func__);
+ return rc;
+ }
+ }
+
+ memset(&fmt, 0x0, sizeof(struct v4l2_format));
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ fmt.fmt.pix_mp.height = height;
+ fmt.fmt.pix_mp.width = width;
+ fmt.fmt.pix_mp.pixelformat = capture_capability;
+ rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
+ if (rc) {
+ DEBUG_PRINT_ERROR("%s: Failed set format on capture mplane", __func__);
+ return rc;
+ }
+
+ rc = get_buffer_req(&drv_ctx.op_buf);
+ if (rc) {
+ DEBUG_PRINT_ERROR("%s: Failed to get output buffer requirements", __func__);
+ return rc;
+ }
+
+ return rc;
+}
+
+/* ======================================================================
+ 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 long p1; // Parameter - 1
+ unsigned long p2; // Parameter - 2
+ unsigned long ident;
+ unsigned qsize=0; // qsize
+ omx_vdec *pThis = (omx_vdec *) ctxt;
+
+ if (!pThis) {
+ DEBUG_PRINT_ERROR("ERROR: %s()::Context is incorrect, bailing out",
+ __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("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("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 == (unsigned long)OMX_ErrorHardware) {
+ pThis->omx_report_error();
+ } else {
+ pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
+ OMX_EventError, p2, (OMX_U32)NULL, NULL );
+ }
+ break;
+
+ case OMX_CommandPortDisable:
+ DEBUG_PRINT_HIGH("OMX_CommandPortDisable complete for port [%lu]", 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) {
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
+ if (release_buffers(pThis, VDEC_BUFFER_TYPE_OUTPUT))
+ DEBUG_PRINT_HIGH("Failed to release output buffers");
+ OMX_ERRORTYPE eRet1 = pThis->get_buffer_req(&pThis->drv_ctx.op_buf);
+ pThis->in_reconfig = false;
+ 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("OMX_CommandPortEnable complete for port [%lu]", 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", __func__);
+ }
+ break;
+ case OMX_COMPONENT_GENERATE_ETB_ARBITRARY:
+ if (pThis->empty_this_buffer_proxy_arbitrary((OMX_HANDLETYPE)p1,\
+ (OMX_BUFFERHEADERTYPE *)(intptr_t)p2) != OMX_ErrorNone) {
+ DEBUG_PRINT_ERROR("empty_this_buffer_proxy_arbitrary failure");
+ pThis->omx_report_error ();
+ }
+ break;
+ case OMX_COMPONENT_GENERATE_ETB: {
+ OMX_ERRORTYPE iret;
+ iret = pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1, (OMX_BUFFERHEADERTYPE *)p2);
+ if (iret == OMX_ErrorInsufficientResources) {
+ DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure due to HW overload");
+ pThis->omx_report_hw_overload ();
+ } else if (iret != OMX_ErrorNone) {
+ DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure");
+ pThis->omx_report_error ();
+ }
+ }
+ break;
+
+ case OMX_COMPONENT_GENERATE_FTB:
+ if ( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)(intptr_t)p1,\
+ (OMX_BUFFERHEADERTYPE *)(intptr_t)p2) != OMX_ErrorNone) {
+ DEBUG_PRINT_ERROR("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("OMX_COMPONENT_GENERATE_EBD failure");
+ pThis->omx_report_error ();
+ } else {
+ if (p2 == VDEC_S_INPUT_BITSTREAM_ERR && p1) {
+ pThis->time_stamp_dts.remove_time_stamp(
+ ((OMX_BUFFERHEADERTYPE *)(intptr_t)p1)->nTimeStamp,
+ (pThis->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
+ ?true:false);
+ }
+
+ if ( pThis->empty_buffer_done(&pThis->m_cmp,
+ (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone) {
+ DEBUG_PRINT_ERROR("empty_buffer_done failure");
+ pThis->omx_report_error ();
+ }
+ }
+ break;
+ case OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED: {
+ int64_t *timestamp = (int64_t *)(intptr_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("OMX_COMPONENT_GENERATE_FBD failure");
+ pThis->omx_report_error ();
+ } else if ( pThis->fill_buffer_done(&pThis->m_cmp,
+ (OMX_BUFFERHEADERTYPE *)(intptr_t)p1) != OMX_ErrorNone ) {
+ DEBUG_PRINT_ERROR("fill_buffer_done failure");
+ pThis->omx_report_error ();
+ }
+ break;
+
+ case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH:
+ DEBUG_PRINT_HIGH("Driver flush i/p Port complete");
+ if (!pThis->input_flush_progress) {
+ DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver");
+ } else {
+ pThis->execute_input_flush();
+ if (pThis->m_cb.EventHandler) {
+ if (p2 != VDEC_S_SUCCESS) {
+ DEBUG_PRINT_ERROR("OMX_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("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->stream_off(OMX_CORE_INPUT_PORT_INDEX)) {
+ DEBUG_PRINT_ERROR("Failed to call streamoff on OUTPUT Port");
+ pThis->omx_report_error ();
+ } else {
+ pThis->streaming[OUTPUT_PORT] = false;
+ }
+ if (!pThis->output_flush_progress) {
+ DEBUG_PRINT_LOW("Input flush done hence issue stop");
+ pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\
+ OMX_COMPONENT_GENERATE_STOP_DONE);
+ }
+ }
+ }
+ } else {
+ DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
+ }
+ }
+ break;
+
+ case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH:
+ DEBUG_PRINT_HIGH("Driver flush o/p Port complete");
+ if (!pThis->output_flush_progress) {
+ DEBUG_PRINT_HIGH("WARNING: Unexpected flush from driver");
+ } else {
+ pThis->execute_output_flush();
+ if (pThis->m_cb.EventHandler) {
+ if (p2 != VDEC_S_SUCCESS) {
+ DEBUG_PRINT_ERROR("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("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("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);
+ BITMASK_CLEAR (&pThis->m_flags,
+ OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
+
+ }
+ }
+
+ if (BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING)) {
+ if (pThis->stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) {
+ DEBUG_PRINT_ERROR("Failed to call streamoff on CAPTURE Port");
+ pThis->omx_report_error ();
+ break;
+ }
+ pThis->streaming[CAPTURE_PORT] = false;
+ if (!pThis->input_flush_progress) {
+ DEBUG_PRINT_LOW("Output flush done hence issue stop");
+ pThis->post_event ((unsigned int)NULL, VDEC_S_SUCCESS,\
+ OMX_COMPONENT_GENERATE_STOP_DONE);
+ }
+ }
+ }
+ } else {
+ DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
+ }
+ }
+ break;
+
+ case OMX_COMPONENT_GENERATE_START_DONE:
+ DEBUG_PRINT_HIGH("Rxd OMX_COMPONENT_GENERATE_START_DONE");
+
+ if (pThis->m_cb.EventHandler) {
+ if (p2 != VDEC_S_SUCCESS) {
+ DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_START_DONE Failure");
+ pThis->omx_report_error ();
+ } else {
+ DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_START_DONE Success");
+ if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
+ DEBUG_PRINT_LOW("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("VDEC_IOCTL_CMD_PAUSE failed");
+ pThis->omx_report_error ();
+ }
+ }
+ }
+ } else {
+ DEBUG_PRINT_LOW("Event Handler callback is NULL");
+ }
+ break;
+
+ case OMX_COMPONENT_GENERATE_PAUSE_DONE:
+ DEBUG_PRINT_HIGH("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("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("Rxd OMX_COMPONENT_GENERATE_RESUME_DONE");
+ if (pThis->m_cb.EventHandler) {
+ if (p2 != VDEC_S_SUCCESS) {
+ DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_RESUME_DONE failed");
+ pThis->omx_report_error ();
+ } else {
+ if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
+ DEBUG_PRINT_LOW("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("Rxd OMX_COMPONENT_GENERATE_STOP_DONE");
+ if (pThis->m_cb.EventHandler) {
+ if (p2 != VDEC_S_SUCCESS) {
+ DEBUG_PRINT_ERROR("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("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("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:
+ if (p2 == OMX_IndexParamPortDefinition) {
+ DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexParamPortDefinition");
+ pThis->in_reconfig = true;
+ } else if (p2 == OMX_IndexConfigCommonOutputCrop) {
+ DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_IndexConfigCommonOutputCrop");
+
+ /* Check if resolution is changed in smooth streaming mode */
+ if (pThis->m_smoothstreaming_mode &&
+ (pThis->framesize.nWidth !=
+ pThis->drv_ctx.video_resolution.frame_width) ||
+ (pThis->framesize.nHeight !=
+ pThis->drv_ctx.video_resolution.frame_height)) {
+
+ DEBUG_PRINT_HIGH("Resolution changed from: wxh = %dx%d to: wxh = %dx%d",
+ pThis->framesize.nWidth,
+ pThis->framesize.nHeight,
+ pThis->drv_ctx.video_resolution.frame_width,
+ pThis->drv_ctx.video_resolution.frame_height);
+
+ /* Update new resolution */
+ pThis->framesize.nWidth =
+ pThis->drv_ctx.video_resolution.frame_width;
+ pThis->framesize.nHeight =
+ pThis->drv_ctx.video_resolution.frame_height;
+
+ /* Update C2D with new resolution */
+ if (!pThis->client_buffers.update_buffer_req()) {
+ DEBUG_PRINT_ERROR("Setting C2D buffer requirements failed");
+ }
+ }
+
+ /* Update new crop information */
+ pThis->rectangle.nLeft = pThis->drv_ctx.frame_size.left;
+ pThis->rectangle.nTop = pThis->drv_ctx.frame_size.top;
+ pThis->rectangle.nWidth = pThis->drv_ctx.frame_size.right;
+ pThis->rectangle.nHeight = pThis->drv_ctx.frame_size.bottom;
+
+ /* Validate the new crop information */
+ if (pThis->rectangle.nLeft + pThis->rectangle.nWidth >
+ pThis->drv_ctx.video_resolution.frame_width) {
+
+ DEBUG_PRINT_HIGH("Crop L[%u] + R[%u] > W[%u]",
+ pThis->rectangle.nLeft, pThis->rectangle.nWidth,
+ pThis->drv_ctx.video_resolution.frame_width);
+ pThis->rectangle.nLeft = 0;
+
+ if (pThis->rectangle.nWidth >
+ pThis->drv_ctx.video_resolution.frame_width) {
+
+ DEBUG_PRINT_HIGH("Crop R[%u] > W[%u]",
+ pThis->rectangle.nWidth,
+ pThis->drv_ctx.video_resolution.frame_width);
+ pThis->rectangle.nWidth =
+ pThis->drv_ctx.video_resolution.frame_width;
+ }
+ }
+ if (pThis->rectangle.nTop + pThis->rectangle.nHeight >
+ pThis->drv_ctx.video_resolution.frame_height) {
+
+ DEBUG_PRINT_HIGH("Crop T[%u] + B[%u] > H[%u]",
+ pThis->rectangle.nTop, pThis->rectangle.nHeight,
+ pThis->drv_ctx.video_resolution.frame_height);
+ pThis->rectangle.nTop = 0;
+
+ if (pThis->rectangle.nHeight >
+ pThis->drv_ctx.video_resolution.frame_height) {
+
+ DEBUG_PRINT_HIGH("Crop B[%u] > H[%u]",
+ pThis->rectangle.nHeight,
+ pThis->drv_ctx.video_resolution.frame_height);
+ pThis->rectangle.nHeight =
+ pThis->drv_ctx.video_resolution.frame_height;
+ }
+ }
+ DEBUG_PRINT_HIGH("Updated Crop Info: L: %u, T: %u, R: %u, B: %u",
+ pThis->rectangle.nLeft, pThis->rectangle.nTop,
+ pThis->rectangle.nWidth, pThis->rectangle.nHeight);
+ } else if (p2 == OMX_QTIIndexConfigDescribeColorAspects) {
+ DEBUG_PRINT_HIGH("Rxd PORT_RECONFIG: OMX_QTIIndexConfigDescribeColorAspects");
+ } else {
+ DEBUG_PRINT_ERROR("Rxd Invalid PORT_RECONFIG event (%lu)", p2);
+ break;
+ }
+ if (pThis->m_debug.outfile) {
+ fclose(pThis->m_debug.outfile);
+ pThis->m_debug.outfile = NULL;
+ }
+ if (pThis->m_debug.out_ymeta_file) {
+ fclose(pThis->m_debug.out_ymeta_file);
+ pThis->m_debug.out_ymeta_file = NULL;
+ }
+ if (pThis->m_debug.out_uvmeta_file) {
+ fclose(pThis->m_debug.out_uvmeta_file);
+ pThis->m_debug.out_uvmeta_file = NULL;
+ }
+
+ if (pThis->secure_mode && pThis->m_cb.EventHandler && pThis->in_reconfig) {
+ pThis->prefetchNewBuffers();
+ }
+
+ if (pThis->m_cb.EventHandler) {
+ uint32_t frame_data[4];
+ frame_data[0] = (p2 == OMX_IndexParamPortDefinition) ?
+ pThis->m_reconfig_height : pThis->rectangle.nHeight;
+ frame_data[1] = (p2 == OMX_IndexParamPortDefinition) ?
+ pThis->m_reconfig_width : pThis->rectangle.nWidth;
+
+ frame_data[2] = (p2 == OMX_IndexParamPortDefinition) ?
+ frame_data[0] : pThis->drv_ctx.video_resolution.frame_height;
+
+ frame_data[3] = (p2 == OMX_IndexParamPortDefinition) ?
+ frame_data[1] : pThis->drv_ctx.video_resolution.frame_width;
+
+ pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
+ OMX_EventPortSettingsChanged, p1, p2, (void*) frame_data );
+ } else {
+ DEBUG_PRINT_ERROR("ERROR: %s()::EventHandler is NULL", __func__);
+ }
+ break;
+
+ case OMX_COMPONENT_GENERATE_EOS_DONE:
+ DEBUG_PRINT_HIGH("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("OMX_COMPONENT_GENERATE_HARDWARE_ERROR");
+ pThis->omx_report_error();
+ break;
+
+ case OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING:
+ DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING");
+ pThis->omx_report_unsupported_setting();
+ break;
+
+ case OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD:
+ DEBUG_PRINT_ERROR("OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD");
+ pThis->omx_report_hw_overload();
+ 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);
+
+}
+
+int omx_vdec::update_resolution(int width, int height, int stride, int scan_lines)
+{
+ int format_changed = 0;
+ if ((height != (int)drv_ctx.video_resolution.frame_height) ||
+ (width != (int)drv_ctx.video_resolution.frame_width)) {
+ DEBUG_PRINT_HIGH("NOTE_CIF: W/H %d (%d), %d (%d)",
+ width, drv_ctx.video_resolution.frame_width,
+ height,drv_ctx.video_resolution.frame_height);
+ format_changed = 1;
+ }
+ drv_ctx.video_resolution.frame_height = height;
+ drv_ctx.video_resolution.frame_width = width;
+ drv_ctx.video_resolution.scan_lines = scan_lines;
+ drv_ctx.video_resolution.stride = stride;
+ if(!is_down_scalar_enabled) {
+ rectangle.nLeft = 0;
+ rectangle.nTop = 0;
+ rectangle.nWidth = drv_ctx.video_resolution.frame_width;
+ rectangle.nHeight = drv_ctx.video_resolution.frame_height;
+ }
+ return format_changed;
+}
+
+OMX_ERRORTYPE omx_vdec::is_video_session_supported()
+{
+ if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",
+ OMX_MAX_STRINGNAME_SIZE) &&
+ (m_profile == HIGH_PROFILE || m_profile == MAIN_PROFILE)) {
+ m_decoder_capability.max_width = 1280;
+ m_decoder_capability.max_height = 720;
+ DEBUG_PRINT_HIGH("Set max_width=1280 & max_height=720 for H264 HP/MP");
+ }
+
+ if ((drv_ctx.video_resolution.frame_width *
+ drv_ctx.video_resolution.frame_height >
+ m_decoder_capability.max_width *
+ m_decoder_capability.max_height) ||
+ (drv_ctx.video_resolution.frame_width*
+ drv_ctx.video_resolution.frame_height <
+ m_decoder_capability.min_width *
+ m_decoder_capability.min_height)) {
+ DEBUG_PRINT_ERROR(
+ "Unsupported WxH = (%u)x(%u) supported range is min(%u)x(%u) - max(%u)x(%u)",
+ drv_ctx.video_resolution.frame_width,
+ drv_ctx.video_resolution.frame_height,
+ m_decoder_capability.min_width,
+ m_decoder_capability.min_height,
+ m_decoder_capability.max_width,
+ m_decoder_capability.max_height);
+ return OMX_ErrorUnsupportedSetting;
+ }
+ DEBUG_PRINT_HIGH("video session supported");
+ return OMX_ErrorNone;
+}
+
+int omx_vdec::log_input_buffers(const char *buffer_addr, int buffer_len)
+{
+ if (m_debug.in_buffer_log && !m_debug.infile) {
+ if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE)) {
+ snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.m4v",
+ m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
+ } else if(!strncmp(drv_ctx.kind,"OMX.qcom.video.decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
+ snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.mpg", m_debug.log_loc,
+ drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
+ } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263", OMX_MAX_STRINGNAME_SIZE)) {
+ snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.263",
+ m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
+ } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", OMX_MAX_STRINGNAME_SIZE) ||
+ !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
+ snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.264",
+ m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
+ } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
+ snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.265",
+ m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
+ } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1", OMX_MAX_STRINGNAME_SIZE)) {
+ snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.vc1",
+ m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
+ } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv", OMX_MAX_STRINGNAME_SIZE)) {
+ snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.vc1",
+ m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
+ } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE)) {
+ snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.ivf",
+ m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
+ } else if(!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
+ snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.ivf",
+ m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
+ } else {
+ snprintf(m_debug.infile_name, OMX_MAX_STRINGNAME_SIZE, "%s/input_dec_%d_%d_%p.divx",
+ m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
+ }
+ m_debug.infile = fopen (m_debug.infile_name, "ab");
+ if (!m_debug.infile) {
+ DEBUG_PRINT_HIGH("Failed to open input file: %s for logging", m_debug.infile_name);
+ m_debug.infile_name[0] = '\0';
+ return -1;
+ }
+ if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
+ !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
+ struct ivf_file_header {
+ OMX_U8 signature[4]; //='DKIF';
+ OMX_U8 version ; //= 0;
+ OMX_U8 headersize ; //= 32;
+ OMX_U32 FourCC;
+ OMX_U8 width;
+ OMX_U8 height;
+ OMX_U32 rate;
+ OMX_U32 scale;
+ OMX_U32 length;
+ OMX_U8 unused[4];
+ } file_header;
+
+ memset((void *)&file_header,0,sizeof(file_header));
+ file_header.signature[0] = 'D';
+ file_header.signature[1] = 'K';
+ file_header.signature[2] = 'I';
+ file_header.signature[3] = 'F';
+ file_header.version = 0;
+ file_header.headersize = 32;
+ switch (drv_ctx.decoder_format) {
+ case VDEC_CODECTYPE_VP8:
+ file_header.FourCC = 0x30385056;
+ break;
+ case VDEC_CODECTYPE_VP9:
+ file_header.FourCC = 0x30395056;
+ break;
+ default:
+ DEBUG_PRINT_ERROR("unsupported format for VP8/VP9");
+ break;
+ }
+ fwrite((const char *)&file_header,
+ sizeof(file_header),1,m_debug.infile);
+ }
+ }
+ if (m_debug.infile && buffer_addr && buffer_len) {
+ if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
+ !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
+ struct vpx_ivf_frame_header {
+ OMX_U32 framesize;
+ OMX_U32 timestamp_lo;
+ OMX_U32 timestamp_hi;
+ } vpx_frame_header;
+ vpx_frame_header.framesize = buffer_len;
+ /* Currently FW doesn't use timestamp values */
+ vpx_frame_header.timestamp_lo = 0;
+ vpx_frame_header.timestamp_hi = 0;
+ fwrite((const char *)&vpx_frame_header,
+ sizeof(vpx_frame_header),1,m_debug.infile);
+ }
+ fwrite(buffer_addr, buffer_len, 1, m_debug.infile);
+ }
+ return 0;
+}
+
+int omx_vdec::log_output_buffers(OMX_BUFFERHEADERTYPE *buffer) {
+ int buf_index = 0;
+ char *temp = NULL;
+
+ if (m_debug.out_buffer_log && !m_debug.outfile && buffer->nFilledLen) {
+ snprintf(m_debug.outfile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.yuv",
+ m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
+ m_debug.outfile = fopen (m_debug.outfile_name, "ab");
+ if (!m_debug.outfile) {
+ DEBUG_PRINT_HIGH("Failed to open output file: %s for logging", m_debug.log_loc);
+ m_debug.outfile_name[0] = '\0';
+ return -1;
+ }
+ }
+
+ if (m_debug.out_meta_buffer_log && !m_debug.out_ymeta_file && !m_debug.out_uvmeta_file
+ && buffer->nFilledLen) {
+ snprintf(m_debug.out_ymetafile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.ymeta",
+ m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
+ snprintf(m_debug.out_uvmetafile_name, OMX_MAX_STRINGNAME_SIZE, "%s/output_%d_%d_%p.uvmeta",
+ m_debug.log_loc, drv_ctx.video_resolution.frame_width, drv_ctx.video_resolution.frame_height, this);
+ m_debug.out_ymeta_file = fopen (m_debug.out_ymetafile_name, "ab");
+ m_debug.out_uvmeta_file = fopen (m_debug.out_uvmetafile_name, "ab");
+ if (!m_debug.out_ymeta_file || !m_debug.out_uvmeta_file) {
+ DEBUG_PRINT_HIGH("Failed to open output y/uv meta file: %s for logging", m_debug.log_loc);
+ m_debug.out_ymetafile_name[0] = '\0';
+ m_debug.out_uvmetafile_name[0] = '\0';
+ return -1;
+ }
+ }
+
+ if ((!m_debug.outfile && !m_debug.out_ymeta_file) || !buffer || !buffer->nFilledLen)
+ return 0;
+
+ buf_index = buffer - m_out_mem_ptr;
+ temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr;
+
+ if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
+ DEBUG_PRINT_HIGH("Logging UBWC yuv width/height(%u/%u)",
+ drv_ctx.video_resolution.frame_width,
+ drv_ctx.video_resolution.frame_height);
+
+ if (m_debug.outfile)
+ fwrite(temp, buffer->nFilledLen, 1, m_debug.outfile);
+
+ if (m_debug.out_ymeta_file && m_debug.out_uvmeta_file) {
+ unsigned int width = 0, height = 0;
+ unsigned int y_plane, y_meta_plane;
+ int y_stride = 0, y_sclines = 0;
+ int y_meta_stride = 0, y_meta_scanlines = 0, uv_meta_stride = 0, uv_meta_scanlines = 0;
+ int color_fmt = COLOR_FMT_NV12_UBWC;
+ int i;
+ int bytes_written = 0;
+
+ width = drv_ctx.video_resolution.frame_width;
+ height = drv_ctx.video_resolution.frame_height;
+ y_meta_stride = VENUS_Y_META_STRIDE(color_fmt, width);
+ y_meta_scanlines = VENUS_Y_META_SCANLINES(color_fmt, height);
+ y_stride = VENUS_Y_STRIDE(color_fmt, width);
+ y_sclines = VENUS_Y_SCANLINES(color_fmt, height);
+ uv_meta_stride = VENUS_UV_META_STRIDE(color_fmt, width);
+ uv_meta_scanlines = VENUS_UV_META_SCANLINES(color_fmt, height);
+
+ y_meta_plane = MSM_MEDIA_ALIGN(y_meta_stride * y_meta_scanlines, 4096);
+ y_plane = MSM_MEDIA_ALIGN(y_stride * y_sclines, 4096);
+
+ temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr;
+ for (i = 0; i < y_meta_scanlines; i++) {
+ bytes_written = fwrite(temp, y_meta_stride, 1, m_debug.out_ymeta_file);
+ temp += y_meta_stride;
+ }
+
+ temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr + y_meta_plane + y_plane;
+ for(i = 0; i < uv_meta_scanlines; i++) {
+ bytes_written += fwrite(temp, uv_meta_stride, 1, m_debug.out_uvmeta_file);
+ temp += uv_meta_stride;
+ }
+ }
+ } else if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12 && m_debug.outfile) {
+ int stride = drv_ctx.video_resolution.stride;
+ int scanlines = drv_ctx.video_resolution.scan_lines;
+ if (m_smoothstreaming_mode) {
+ stride = drv_ctx.video_resolution.frame_width;
+ scanlines = drv_ctx.video_resolution.frame_height;
+ stride = (stride + DEFAULT_WIDTH_ALIGNMENT - 1) & (~(DEFAULT_WIDTH_ALIGNMENT - 1));
+ scanlines = (scanlines + DEFAULT_HEIGHT_ALIGNMENT - 1) & (~(DEFAULT_HEIGHT_ALIGNMENT - 1));
+ }
+ unsigned i;
+ DEBUG_PRINT_HIGH("Logging width/height(%u/%u) stride/scanlines(%u/%u)",
+ drv_ctx.video_resolution.frame_width,
+ drv_ctx.video_resolution.frame_height, stride, scanlines);
+ int bytes_written = 0;
+ for (i = 0; i < drv_ctx.video_resolution.frame_height; i++) {
+ bytes_written = fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile);
+ temp += stride;
+ }
+ temp = (char *)drv_ctx.ptr_outputbuffer[buf_index].bufferaddr + stride * scanlines;
+ int stride_c = stride;
+ for(i = 0; i < drv_ctx.video_resolution.frame_height/2; i++) {
+ bytes_written += fwrite(temp, drv_ctx.video_resolution.frame_width, 1, m_debug.outfile);
+ temp += stride_c;
+ }
+ }
+ return 0;
+}
+
+/* ======================================================================
+ 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 v4l2_fmtdesc fdesc;
+ struct v4l2_format fmt;
+ struct v4l2_requestbuffers bufreq;
+ struct v4l2_control control;
+ struct v4l2_frmsizeenum frmsize;
+ unsigned int alignment = 0,buffer_size = 0;
+ int fds[2];
+ int r,ret=0;
+ bool codec_ambiguous = false;
+ OMX_STRING device_name = (OMX_STRING)"/dev/video32";
+ char property_value[PROPERTY_VALUE_MAX] = {0};
+ FILE *soc_file = NULL;
+ char buffer[10];
+
+#ifdef _ANDROID_
+ char platform_name[PROPERTY_VALUE_MAX];
+ property_get("ro.board.platform", platform_name, "0");
+ if (!strncmp(platform_name, "msm8610", 7)) {
+ device_name = (OMX_STRING)"/dev/video/q6_dec";
+ is_q6_platform = true;
+ maxSmoothStreamingWidth = 1280;
+ maxSmoothStreamingHeight = 720;
+ }
+#endif
+
+ is_thulium_v1 = false;
+ soc_file = fopen("/sys/devices/soc0/soc_id", "r");
+ if (soc_file) {
+ fread(buffer, 1, 4, soc_file);
+ fclose(soc_file);
+ if (atoi(buffer) == 246) {
+ soc_file = fopen("/sys/devices/soc0/revision", "r");
+ if (soc_file) {
+ fread(buffer, 1, 4, soc_file);
+ fclose(soc_file);
+ if (atoi(buffer) == 1) {
+ is_thulium_v1 = true;
+ DEBUG_PRINT_HIGH("is_thulium_v1 = TRUE");
+ }
+ }
+ }
+ }
+
+#ifdef _ANDROID_
+ /*
+ * turn off frame parsing for Android by default.
+ * Clients may configure OMX_QCOM_FramePacking_Arbitrary to enable this mode
+ */
+ arbitrary_bytes = false;
+ property_get("vidc.dec.debug.arbitrarybytes.mode", property_value, "0");
+ if (atoi(property_value)) {
+ DEBUG_PRINT_HIGH("arbitrary_bytes mode enabled via property command");
+ arbitrary_bytes = true;
+ }
+#endif
+
+ if (!strncmp(role, "OMX.qcom.video.decoder.avc.secure",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ secure_mode = true;
+ arbitrary_bytes = false;
+ role = (OMX_STRING)"OMX.qcom.video.decoder.avc";
+ } else if (!strncmp(role, "OMX.qcom.video.decoder.mpeg2.secure",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ secure_mode = true;
+ arbitrary_bytes = false;
+ role = (OMX_STRING)"OMX.qcom.video.decoder.mpeg2";
+ } else if (!strncmp(role, "OMX.qcom.video.decoder.hevc.secure",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ secure_mode = true;
+ arbitrary_bytes = false;
+ role = (OMX_STRING)"OMX.qcom.video.decoder.hevc";
+ } else if (!strncmp(role, "OMX.qcom.video.decoder.vc1.secure",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ secure_mode = true;
+ arbitrary_bytes = false;
+ role = (OMX_STRING)"OMX.qcom.video.decoder.vc1";
+ } else if (!strncmp(role, "OMX.qcom.video.decoder.wmv.secure",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ secure_mode = true;
+ arbitrary_bytes = false;
+ role = (OMX_STRING)"OMX.qcom.video.decoder.wmv";
+ } else if (!strncmp(role, "OMX.qcom.video.decoder.mpeg4.secure",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ secure_mode = true;
+ arbitrary_bytes = false;
+ role = (OMX_STRING)"OMX.qcom.video.decoder.mpeg4";
+ } else if (!strncmp(role, "OMX.qcom.video.decoder.vp9.secure",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ secure_mode = true;
+ arbitrary_bytes = false;
+ role = (OMX_STRING)"OMX.qcom.video.decoder.vp9";
+ }
+ else if (!strncmp(role, "OMX.qcom.video.decoder.vp8.secure",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ secure_mode = true;
+ arbitrary_bytes = false;
+ role = (OMX_STRING)"OMX.qcom.video.decoder.vp8";
+ }
+
+ drv_ctx.video_driver_fd = open(device_name, O_RDWR);
+
+ DEBUG_PRINT_INFO("component_init: %s : fd=%d", role, drv_ctx.video_driver_fd);
+
+ if (drv_ctx.video_driver_fd < 0) {
+ DEBUG_PRINT_ERROR("Omx_vdec::Comp Init Returning failure, errno %d", errno);
+ return OMX_ErrorInsufficientResources;
+ }
+ drv_ctx.frame_rate.fps_numerator = DEFAULT_FPS;
+ drv_ctx.frame_rate.fps_denominator = 1;
+ operating_frame_rate = DEFAULT_FPS;
+ high_fps = false;
+ m_poll_efd = eventfd(0, 0);
+ if (m_poll_efd < 0) {
+ DEBUG_PRINT_ERROR("Failed to create event fd(%s)", strerror(errno));
+ return OMX_ErrorInsufficientResources;
+ }
+ ret = subscribe_to_events(drv_ctx.video_driver_fd);
+ if (!ret) {
+ async_thread_created = true;
+ ret = pthread_create(&async_thread_id,0,async_message_thread,this);
+ }
+ if (ret) {
+ DEBUG_PRINT_ERROR("Failed to create async_message_thread");
+ async_thread_created = false;
+ return OMX_ErrorInsufficientResources;
+ }
+
+#ifdef OUTPUT_EXTRADATA_LOG
+ outputExtradataFile = fopen (output_extradata_filename, "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;
+ output_capability=V4L2_PIX_FMT_MPEG4;
+ /*Initialize Start Code for MPEG4*/
+ codec_type_parse = CODEC_TYPE_MPEG4;
+ m_frame_parser.init_start_codes(codec_type_parse);
+ } 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;
+ output_capability = V4L2_PIX_FMT_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);
+ } 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("H263 Decoder selected");
+ drv_ctx.decoder_format = VDEC_CODECTYPE_H263;
+ eCompressionFormat = OMX_VIDEO_CodingH263;
+ output_capability = V4L2_PIX_FMT_H263;
+ codec_type_parse = CODEC_TYPE_H263;
+ m_frame_parser.init_start_codes(codec_type_parse);
+ } 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 ("DIVX 311 Decoder selected");
+ drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_3;
+ output_capability = V4L2_PIX_FMT_DIVX_311;
+ eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
+ codec_type_parse = CODEC_TYPE_DIVX;
+ m_frame_parser.init_start_codes(codec_type_parse);
+
+ } 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 ("DIVX 4 Decoder selected");
+ drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_4;
+ output_capability = V4L2_PIX_FMT_DIVX;
+ eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
+ codec_type_parse = CODEC_TYPE_DIVX;
+ codec_ambiguous = true;
+ m_frame_parser.init_start_codes(codec_type_parse);
+
+ } 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 ("DIVX 5/6 Decoder selected");
+ drv_ctx.decoder_format = VDEC_CODECTYPE_DIVX_6;
+ output_capability = V4L2_PIX_FMT_DIVX;
+ eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
+ codec_type_parse = CODEC_TYPE_DIVX;
+ codec_ambiguous = true;
+ m_frame_parser.init_start_codes(codec_type_parse);
+
+ } 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;
+ output_capability=V4L2_PIX_FMT_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);
+ if (is_thulium_v1) {
+ arbitrary_bytes = true;
+ DEBUG_PRINT_HIGH("Enable arbitrary_bytes for h264");
+ }
+ } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc",\
+ OMX_MAX_STRINGNAME_SIZE)) {
+ strlcpy((char *)m_cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
+ drv_ctx.decoder_format = VDEC_CODECTYPE_MVC;
+ output_capability = V4L2_PIX_FMT_H264_MVC;
+ eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingMVC;
+ codec_type_parse = CODEC_TYPE_H264;
+ m_frame_parser.init_start_codes(codec_type_parse);
+ m_frame_parser.init_nal_length(nal_length);
+ } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc",\
+ OMX_MAX_STRINGNAME_SIZE)) {
+ strlcpy((char *)m_cRole, "video_decoder.hevc",OMX_MAX_STRINGNAME_SIZE);
+ drv_ctx.decoder_format = VDEC_CODECTYPE_HEVC;
+ output_capability = V4L2_PIX_FMT_HEVC;
+ eCompressionFormat = (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingHevc;
+ codec_type_parse = CODEC_TYPE_HEVC;
+ m_frame_parser.init_start_codes(codec_type_parse);
+ m_frame_parser.init_nal_length(nal_length);
+ } 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;
+ output_capability = V4L2_PIX_FMT_VC1_ANNEX_G;
+ m_frame_parser.init_start_codes(codec_type_parse);
+ } 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;
+ output_capability = V4L2_PIX_FMT_VC1_ANNEX_L;
+ m_frame_parser.init_start_codes(codec_type_parse);
+ } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", \
+ OMX_MAX_STRINGNAME_SIZE)) {
+ strlcpy((char *)m_cRole, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
+ drv_ctx.decoder_format = VDEC_CODECTYPE_VP8;
+ output_capability = V4L2_PIX_FMT_VP8;
+ eCompressionFormat = OMX_VIDEO_CodingVP8;
+ codec_type_parse = CODEC_TYPE_VP8;
+ arbitrary_bytes = false;
+ } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", \
+ OMX_MAX_STRINGNAME_SIZE)) {
+ strlcpy((char *)m_cRole, "video_decoder.vp9",OMX_MAX_STRINGNAME_SIZE);
+ drv_ctx.decoder_format = VDEC_CODECTYPE_VP9;
+ output_capability = V4L2_PIX_FMT_VP9;
+ eCompressionFormat = OMX_VIDEO_CodingVP9;
+ codec_type_parse = CODEC_TYPE_VP9;
+ arbitrary_bytes = false;
+ } else {
+ DEBUG_PRINT_ERROR("ERROR:Unknown Component");
+ eRet = OMX_ErrorInvalidComponentName;
+ }
+
+ if (eRet == OMX_ErrorNone) {
+ OMX_COLOR_FORMATTYPE dest_color_format;
+ if (m_disable_ubwc_mode) {
+ drv_ctx.output_format = VDEC_YUV_FORMAT_NV12;
+ } else {
+ drv_ctx.output_format = VDEC_YUV_FORMAT_NV12_UBWC;
+ }
+ if (eCompressionFormat == (OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingMVC)
+ dest_color_format = (OMX_COLOR_FORMATTYPE)
+ QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
+ else
+ dest_color_format = (OMX_COLOR_FORMATTYPE)
+ QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
+ if (!client_buffers.set_color_format(dest_color_format)) {
+ DEBUG_PRINT_ERROR("Setting color format failed");
+ eRet = OMX_ErrorInsufficientResources;
+ }
+
+ dpb_bit_depth = MSM_VIDC_BIT_DEPTH_8;
+ m_progressive = MSM_VIDC_PIC_STRUCT_PROGRESSIVE;
+
+ if (m_disable_ubwc_mode) {
+ capture_capability = V4L2_PIX_FMT_NV12;
+ } else {
+ capture_capability = V4L2_PIX_FMT_NV12_UBWC;
+ }
+
+ struct v4l2_capability cap;
+ ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_QUERYCAP, &cap);
+ if (ret) {
+ DEBUG_PRINT_ERROR("Failed to query capabilities");
+ /*TODO: How to handle this case */
+ } else {
+ DEBUG_PRINT_LOW("Capabilities: driver_name = %s, card = %s, bus_info = %s,"
+ " version = %d, capabilities = %x", cap.driver, cap.card,
+ cap.bus_info, cap.version, cap.capabilities);
+ }
+ ret=0;
+ fdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ fdesc.index=0;
+ while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
+ DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
+ fdesc.pixelformat, fdesc.flags);
+ fdesc.index++;
+ }
+ fdesc.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ fdesc.index=0;
+ while (ioctl(drv_ctx.video_driver_fd, VIDIOC_ENUM_FMT, &fdesc) == 0) {
+
+ DEBUG_PRINT_HIGH("fmt: description: %s, fmt: %x, flags = %x", fdesc.description,
+ fdesc.pixelformat, fdesc.flags);
+ fdesc.index++;
+ }
+ update_resolution(320, 240, 320, 240);
+ fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
+ fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
+ fmt.fmt.pix_mp.pixelformat = output_capability;
+ ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
+ if (ret) {
+ /*TODO: How to handle this case */
+ DEBUG_PRINT_ERROR("Failed to set format on output port");
+ return OMX_ErrorInsufficientResources;
+ }
+ DEBUG_PRINT_HIGH("Set Format was successful");
+ if (codec_ambiguous) {
+ if (output_capability == V4L2_PIX_FMT_DIVX) {
+ struct v4l2_control divx_ctrl;
+
+ if (drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_4) {
+ divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_4;
+ } else if (drv_ctx.decoder_format == VDEC_CODECTYPE_DIVX_5) {
+ divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_5;
+ } else {
+ divx_ctrl.value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_6;
+ }
+
+ divx_ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_DIVX_FORMAT;
+ ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &divx_ctrl);
+ if (ret) {
+ DEBUG_PRINT_ERROR("Failed to set divx version");
+ }
+ } else {
+ DEBUG_PRINT_ERROR("Codec should not be ambiguous");
+ }
+ }
+
+ property_get("persist.vidc.dec.conceal_color", property_value, DEFAULT_CONCEAL_COLOR);
+ m_conceal_color= atoi(property_value);
+ DEBUG_PRINT_HIGH("trying to set 0x%u as conceal color\n", (unsigned int)m_conceal_color);
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR;
+ control.value = m_conceal_color;
+ ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
+ if (ret) {
+ DEBUG_PRINT_ERROR("Failed to set conceal color %d\n", ret);
+ }
+
+ //Get the hardware capabilities
+ memset((void *)&frmsize,0,sizeof(frmsize));
+ frmsize.index = 0;
+ frmsize.pixel_format = output_capability;
+ ret = ioctl(drv_ctx.video_driver_fd,
+ VIDIOC_ENUM_FRAMESIZES, &frmsize);
+ if (ret || frmsize.type != V4L2_FRMSIZE_TYPE_STEPWISE) {
+ DEBUG_PRINT_ERROR("Failed to get framesizes");
+ return OMX_ErrorHardware;
+ }
+
+ if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
+ m_decoder_capability.min_width = frmsize.stepwise.min_width;
+ m_decoder_capability.max_width = frmsize.stepwise.max_width;
+ m_decoder_capability.min_height = frmsize.stepwise.min_height;
+ m_decoder_capability.max_height = frmsize.stepwise.max_height;
+ }
+
+ memset(&fmt, 0x0, sizeof(struct v4l2_format));
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
+ fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
+ fmt.fmt.pix_mp.pixelformat = capture_capability;
+ ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
+ if (ret) {
+ /*TODO: How to handle this case */
+ DEBUG_PRINT_ERROR("Failed to set format on capture port");
+ }
+ memset(&framesize, 0, sizeof(OMX_FRAMESIZETYPE));
+ framesize.nWidth = drv_ctx.video_resolution.frame_width;
+ framesize.nHeight = drv_ctx.video_resolution.frame_height;
+
+ memset(&rectangle, 0, sizeof(OMX_CONFIG_RECTTYPE));
+ rectangle.nWidth = drv_ctx.video_resolution.frame_width;
+ rectangle.nHeight = drv_ctx.video_resolution.frame_height;
+
+ DEBUG_PRINT_HIGH("Set Format was successful");
+ if (secure_mode) {
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE;
+ control.value = 1;
+ DEBUG_PRINT_LOW("Omx_vdec:: calling to open secure device %d", ret);
+ ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
+ if (ret) {
+ DEBUG_PRINT_ERROR("Omx_vdec:: Unable to open secure device %d", ret);
+ return OMX_ErrorInsufficientResources;
+ }
+ }
+ if (output_capability == V4L2_PIX_FMT_H264_MVC) {
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_MVC_BUFFER_LAYOUT;
+ control.value = V4L2_MPEG_VIDC_VIDEO_MVC_TOP_BOTTOM;
+ ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
+ if (ret) {
+ DEBUG_PRINT_ERROR("Failed to set MVC buffer layout");
+ return OMX_ErrorInsufficientResources;
+ }
+ }
+
+ if (is_thulium_v1) {
+ eRet = enable_smoothstreaming();
+ if (eRet != OMX_ErrorNone) {
+ DEBUG_PRINT_ERROR("Failed to enable smooth streaming on driver");
+ return eRet;
+ }
+ }
+
+ /*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;
+
+ if (secure_mode) {
+ drv_ctx.op_buf.alignment = SECURE_ALIGN;
+ drv_ctx.ip_buf.alignment = SECURE_ALIGN;
+ } else {
+ drv_ctx.op_buf.alignment = SZ_4K;
+ drv_ctx.ip_buf.alignment = SZ_4K;
+ }
+
+ drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
+ drv_ctx.extradata = 0;
+ drv_ctx.picture_order = VDEC_ORDER_DISPLAY;
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
+ control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY;
+ ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
+ drv_ctx.idr_only_decoding = 0;
+
+#ifdef _ANDROID_
+ property_get("vidc.dec.downscalar_width",property_value,"0");
+ if (atoi(property_value)) {
+ m_downscalar_width = atoi(property_value);
+ }
+ property_get("vidc.dec.downscalar_height",property_value,"0");
+ if (atoi(property_value)) {
+ m_downscalar_height = atoi(property_value);
+ }
+
+ if (m_downscalar_width < m_decoder_capability.min_width ||
+ m_downscalar_height < m_decoder_capability.min_height) {
+ m_downscalar_width = 0;
+ m_downscalar_height = 0;
+ }
+
+ DEBUG_PRINT_LOW("Downscaler configured WxH %dx%d\n",
+ m_downscalar_width, m_downscalar_height);
+
+ property_get("vidc.disable.split.mode",property_value,"0");
+ m_disable_split_mode = atoi(property_value);
+ DEBUG_PRINT_HIGH("split mode is %s", m_disable_split_mode ? "disabled" : "enabled");
+#endif
+ m_state = OMX_StateLoaded;
+#ifdef DEFAULT_EXTRADATA
+ enable_extradata(DEFAULT_EXTRADATA, true, true);
+#endif
+ eRet = get_buffer_req(&drv_ctx.ip_buf);
+ DEBUG_PRINT_HIGH("Input Buffer Size =%u",(unsigned int)drv_ctx.ip_buf.buffer_size);
+ get_buffer_req(&drv_ctx.op_buf);
+ if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264 ||
+ drv_ctx.decoder_format == VDEC_CODECTYPE_HEVC ||
+ drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) {
+ 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("h264_scratch.pBuffer Allocation failed ");
+ return OMX_ErrorInsufficientResources;
+ }
+ }
+ if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264 ||
+ drv_ctx.decoder_format == VDEC_CODECTYPE_MVC) {
+ if (m_frame_parser.mutils == NULL) {
+ m_frame_parser.mutils = new H264_Utils();
+ if (m_frame_parser.mutils == NULL) {
+ DEBUG_PRINT_ERROR("parser utils Allocation failed ");
+ eRet = OMX_ErrorInsufficientResources;
+ } else {
+ 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");
+ eRet = OMX_ErrorInsufficientResources;
+ } else {
+ m_pipe_in = fds[0];
+ m_pipe_out = fds[1];
+ msg_thread_created = true;
+ r = pthread_create(&msg_thread_id,0,message_thread_dec,this);
+
+ if (r < 0) {
+ DEBUG_PRINT_ERROR("component_init(): message_thread_dec creation failed");
+ msg_thread_created = false;
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ }
+ }
+
+ if (eRet != OMX_ErrorNone) {
+ DEBUG_PRINT_ERROR("Component Init Failed");
+ } else {
+ DEBUG_PRINT_INFO("omx_vdec::component_init() success : fd=%d",
+ drv_ctx.video_driver_fd);
+ }
+ //memset(&h264_mv_buff,0,sizeof(struct h264_mv_buffer));
+ 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
+ )
+{
+ (void) hComp;
+ (void) componentName;
+ (void) componentVersion;
+ (void) componentUUID;
+ if (m_state == OMX_StateInvalid) {
+ DEBUG_PRINT_ERROR("Get Comp Version in Invalid State");
+ 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
+ )
+{
+ (void) hComp;
+ (void) cmdData;
+ DEBUG_PRINT_LOW("send_command: Recieved a Command from Client");
+ if (m_state == OMX_StateInvalid) {
+ DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State");
+ 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("send_command(): ERROR OMX_CommandFlush "
+ "to invalid port: %u", (unsigned int)param1);
+ return OMX_ErrorBadPortIndex;
+ }
+
+ post_event((unsigned)cmd,(unsigned)param1,OMX_COMPONENT_GENERATE_COMMAND);
+ sem_wait(&m_cmd_lock);
+ DEBUG_PRINT_LOW("send_command: Command Processed");
+ 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
+ )
+{
+ (void) hComp;
+ (void) cmdData;
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ OMX_STATETYPE eState = (OMX_STATETYPE) param1;
+ int bFlag = 1,sem_posted = 0,ret=0;
+
+ DEBUG_PRINT_LOW("send_command_proxy(): cmd = %d", cmd);
+ DEBUG_PRINT_HIGH("send_command_proxy(): Current State %d, Expected State %d",
+ m_state, eState);
+
+ if (cmd == OMX_CommandStateSet) {
+ DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandStateSet issued");
+ DEBUG_PRINT_HIGH("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");
+ } else {
+ DEBUG_PRINT_LOW("send_command_proxy(): Loaded-->Idle-Pending");
+ 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");
+ 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");
+ }
+ /* Requesting transition from Loaded to Executing */
+ else if (eState == OMX_StateExecuting) {
+ DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Loaded-->Executing");
+ 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");
+ 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");
+ 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)",\
+ 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");
+ } else {
+ DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Loaded-Pending");
+ 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");
+ //BITMASK_SET(&m_flags, OMX_COMPONENT_EXECUTE_PENDING);
+ bFlag = 1;
+ DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
+ m_state=OMX_StateExecuting;
+ DEBUG_PRINT_HIGH("Stream On CAPTURE Was successful");
+ }
+ /* Requesting transition from Idle to Idle */
+ else if (eState == OMX_StateIdle) {
+ DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Idle");
+ 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");
+ 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("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");
+ bFlag = 0;
+ }
+ }
+ /* Requesting transition from Idle to Invalid */
+ else if (eState == OMX_StateInvalid) {
+ DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle-->Invalid");
+ post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorInvalidState;
+ } else {
+ DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Idle --> %d Not Handled",eState);
+ eRet = OMX_ErrorBadParameter;
+ }
+ }
+
+ /******************************/
+ /* Current State is Executing */
+ /******************************/
+ else if (m_state == OMX_StateExecuting) {
+ DEBUG_PRINT_LOW("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("send_command_proxy(): Executing --> Idle");
+ 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("PAUSE Command Issued");
+ m_state = OMX_StatePause;
+ bFlag = 1;
+ }
+ /* Requesting transition from Executing to Loaded */
+ else if (eState == OMX_StateLoaded) {
+ DEBUG_PRINT_ERROR("send_command_proxy(): Executing --> Loaded");
+ 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("send_command_proxy(): Executing --> WaitForResources");
+ 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("send_command_proxy(): Executing --> Executing");
+ 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("send_command_proxy(): Executing --> Invalid");
+ post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorInvalidState;
+ } else {
+ DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Executing --> %d Not Handled",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("Pause --> Executing");
+ m_state = OMX_StateExecuting;
+ bFlag = 1;
+ }
+ /* 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("Pause --> Idle");
+ 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("Pause --> loaded");
+ 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("Pause --> WaitForResources");
+ 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("Pause --> Pause");
+ 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("Pause --> Invalid");
+ post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorInvalidState;
+ } else {
+ DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): Paused --> %d Not Handled",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");
+ }
+ /* Requesting transition from WaitForResources to WaitForResources */
+ else if (eState == OMX_StateWaitForResources) {
+ DEBUG_PRINT_ERROR("ERROR::send_command_proxy(): WaitForResources-->WaitForResources");
+ 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");
+ 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");
+ 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");
+ 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)",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");
+ post_event(OMX_EventError,OMX_ErrorInvalidState,\
+ OMX_COMPONENT_GENERATE_EVENT);
+ eRet = OMX_ErrorInvalidState;
+ }
+ } else if (cmd == OMX_CommandFlush) {
+ DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandFlush issued"
+ "with param1: %u", (unsigned int)param1);
+#ifdef _MSM8974_
+ send_codec_config();
+#endif
+ if (cmd == OMX_CommandFlush && (param1 == OMX_CORE_INPUT_PORT_INDEX ||
+ param1 == OMX_ALL)) {
+ if (android_atomic_add(0, &m_queued_codec_config_count) > 0) {
+ struct timespec ts;
+
+ clock_gettime(CLOCK_REALTIME, &ts);
+ ts.tv_sec += 2;
+ DEBUG_PRINT_LOW("waiting for %d EBDs of CODEC CONFIG buffers ",
+ m_queued_codec_config_count);
+ BITMASK_SET(&m_flags, OMX_COMPONENT_FLUSH_DEFERRED);
+ if (sem_timedwait(&m_safe_flush, &ts)) {
+ DEBUG_PRINT_ERROR("Failed to wait for EBDs of CODEC CONFIG buffers");
+ }
+ BITMASK_CLEAR (&m_flags,OMX_COMPONENT_FLUSH_DEFERRED);
+ }
+ }
+
+ 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("Set the Semaphore");
+ sem_post (&m_cmd_lock);
+ execute_omx_flush(param1);
+ }
+ bFlag = 0;
+ } else if ( cmd == OMX_CommandPortEnable) {
+ DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortEnable issued"
+ "with param1: %u", (unsigned int)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");
+ 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("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");
+ BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
+ // Skip the event notification
+ bFlag = 0;
+ /* enable/disable downscaling if required */
+ ret = decide_downscalar();
+ if (ret) {
+ DEBUG_PRINT_LOW("decide_downscalar failed\n");
+ }
+ }
+ }
+ } else if (cmd == OMX_CommandPortDisable) {
+ DEBUG_PRINT_HIGH("send_command_proxy(): OMX_CommandPortDisable issued"
+ "with param1: %u", (unsigned int)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()) {
+ 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("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)",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)
+{
+ bool bRet = false;
+ struct v4l2_plane plane;
+ struct v4l2_buffer v4l2_buf;
+ struct v4l2_decoder_cmd dec;
+ DEBUG_PRINT_LOW("in %s, flushing %u", __func__, (unsigned int)flushType);
+ memset((void *)&v4l2_buf,0,sizeof(v4l2_buf));
+ dec.cmd = V4L2_DEC_QCOM_CMD_FLUSH;
+
+ DEBUG_PRINT_HIGH("in %s: reconfig? %d", __func__, in_reconfig);
+
+ if (in_reconfig && flushType == OMX_CORE_OUTPUT_PORT_INDEX) {
+ output_flush_progress = true;
+ dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE;
+ } else {
+ /* XXX: The driver/hardware does not support flushing of individual ports
+ * in all states. So we pretty much need to flush both ports internally,
+ * but client should only get the FLUSH_(INPUT|OUTPUT)_DONE for the one it
+ * requested. Since OMX_COMPONENT_(OUTPUT|INPUT)_FLUSH_PENDING isn't set,
+ * we automatically omit sending the FLUSH done for the "opposite" port. */
+ input_flush_progress = true;
+ output_flush_progress = true;
+ dec.flags = V4L2_DEC_QCOM_CMD_FLUSH_OUTPUT | V4L2_DEC_QCOM_CMD_FLUSH_CAPTURE;
+ request_perf_level(VIDC_TURBO);
+ }
+
+ if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) {
+ DEBUG_PRINT_ERROR("Flush Port (%u) Failed ", (unsigned int)flushType);
+ 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 long p1 = 0; // Parameter - 1
+ unsigned long p2 = 0; // Parameter - 2
+ unsigned long ident = 0;
+ bool bRet = true;
+
+ /*Generate FBD for all Buffers in the FTBq*/
+ pthread_mutex_lock(&m_lock);
+ DEBUG_PRINT_LOW("Initiate Output Flush");
+
+ //reset last render TS
+ if(m_last_rendered_TS > 0) {
+ m_last_rendered_TS = 0;
+ }
+
+ while (m_ftb_q.m_size) {
+ DEBUG_PRINT_LOW("Buffer queue size %lu pending buf cnt %d",
+ m_ftb_q.m_size,pending_output_buffers);
+ m_ftb_q.pop_entry(&p1,&p2,&ident);
+ DEBUG_PRINT_LOW("ID(%lx) P1(%lx) P2(%lx)", ident, p1, p2);
+ if (ident == m_fill_output_msg ) {
+ m_cb.FillBufferDone(&m_cmp, m_app_data, (OMX_BUFFERHEADERTYPE *)(intptr_t)p2);
+ } else if (ident == OMX_COMPONENT_GENERATE_FBD) {
+ fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)(intptr_t)p1);
+ }
+ }
+ pthread_mutex_unlock(&m_lock);
+ output_flush_progress = false;
+
+ if (arbitrary_bytes) {
+ prev_ts = LLONG_MAX;
+ rst_prev_ts = true;
+ }
+ DEBUG_PRINT_HIGH("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 long p1 = 0; // Parameter - 1
+ unsigned long p2 = 0; // Parameter - 2
+ unsigned long ident = 0;
+ bool bRet = true;
+
+ /*Generate EBD for all Buffers in the ETBq*/
+ DEBUG_PRINT_LOW("Initiate Input Flush");
+
+ pthread_mutex_lock(&m_lock);
+ DEBUG_PRINT_LOW("Check if the Queue is empty");
+ while (m_etb_q.m_size) {
+ m_etb_q.pop_entry(&p1,&p2,&ident);
+
+ if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARY) {
+ DEBUG_PRINT_LOW("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("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("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("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("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 long) pdest_frame, (unsigned int)NULL,
+ (unsigned int)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("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 long p1,
+ unsigned long p2,
+ unsigned long id)
+{
+ bool bRet = false;
+
+ /* Just drop messages typically generated by hardware (w/o client request),
+ * if we've reported an error to client. */
+ if (m_error_propogated) {
+ switch (id) {
+ case OMX_COMPONENT_GENERATE_PORT_RECONFIG:
+ case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
+ DEBUG_PRINT_ERROR("Dropping message %lx "
+ "since client expected to be in error state", id);
+ return false;
+ default:
+ /* whatever */
+ break;
+ }
+ }
+
+ pthread_mutex_lock(&m_lock);
+
+ if (id == m_fill_output_msg ||
+ id == OMX_COMPONENT_GENERATE_FBD ||
+ id == OMX_COMPONENT_GENERATE_PORT_RECONFIG ||
+ id == OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH) {
+ 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 ||
+ id == OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH) {
+ m_etb_q.insert_entry(p1,p2,id);
+ } else {
+ m_cmd_q.insert_entry(p1,p2,id);
+ }
+
+ bRet = true;
+ DEBUG_PRINT_LOW("Value of this pointer in post_event %p",this);
+ post_message(this, id);
+
+ pthread_mutex_unlock(&m_lock);
+
+ return bRet;
+}
+
+OMX_ERRORTYPE omx_vdec::get_supported_profile_level(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)) {
+ profileLevelType->eLevel = OMX_VIDEO_AVCLevel52;
+ if (profileLevelType->nProfileIndex == 0) {
+ profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline;
+ } else if (profileLevelType->nProfileIndex == 1) {
+ profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain;
+ } else if (profileLevelType->nProfileIndex == 2) {
+ profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh;
+ } else if (profileLevelType->nProfileIndex == 3) {
+ profileLevelType->eProfile = QOMX_VIDEO_AVCProfileConstrainedBaseline;
+ } else if (profileLevelType->nProfileIndex == 4) {
+ profileLevelType->eProfile = QOMX_VIDEO_AVCProfileConstrainedHigh;
+ } else {
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
+ (unsigned int)profileLevelType->nProfileIndex);
+ eRet = OMX_ErrorNoMore;
+ }
+ } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
+ if (profileLevelType->nProfileIndex == 0) {
+ profileLevelType->eProfile = QOMX_VIDEO_MVCProfileStereoHigh;
+ profileLevelType->eLevel = QOMX_VIDEO_MVCLevel51;
+ } else {
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
+ (unsigned int)profileLevelType->nProfileIndex);
+ eRet = OMX_ErrorNoMore;
+ }
+ } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
+ if (profileLevelType->nProfileIndex == 0) {
+ profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain;
+ profileLevelType->eLevel = OMX_VIDEO_HEVCMainTierLevel51;
+ } else if (profileLevelType->nProfileIndex == 1) {
+ profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain10;
+ profileLevelType->eLevel = OMX_VIDEO_HEVCMainTierLevel51;
+ } else {
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
+ (unsigned int)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_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
+ (unsigned int)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_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
+ (unsigned int)profileLevelType->nProfileIndex);
+ eRet = OMX_ErrorNoMore;
+ }
+ } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE) ||
+ !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",OMX_MAX_STRINGNAME_SIZE)) {
+ 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_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u",
+ (unsigned int)profileLevelType->nProfileIndex);
+ eRet = OMX_ErrorNoMore;
+ }
+ } else {
+ DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported ret NoMore for codec: %s", drv_ctx.kind);
+ eRet = OMX_ErrorNoMore;
+ }
+ } else {
+ DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queries on Input port only %u",
+ (unsigned int)profileLevelType->nPortIndex);
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ return eRet;
+}
+
+/* ======================================================================
+ 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)
+{
+ (void) hComp;
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+
+ DEBUG_PRINT_LOW("get_parameter:");
+ if (m_state == OMX_StateInvalid) {
+ DEBUG_PRINT_ERROR("Get Param in Invalid State");
+ return OMX_ErrorInvalidState;
+ }
+ if (paramData == NULL) {
+ DEBUG_PRINT_LOW("Get Param in Invalid paramData");
+ return OMX_ErrorBadParameter;
+ }
+ switch ((unsigned long)paramIndex) {
+ case OMX_IndexParamPortDefinition: {
+ VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE);
+ OMX_PARAM_PORTDEFINITIONTYPE *portDefn =
+ (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition");
+ decide_dpb_buffer_mode(is_down_scalar_enabled);
+ eRet = update_portdef(portDefn);
+ if (eRet == OMX_ErrorNone)
+ m_port_def = *portDefn;
+ break;
+ }
+ case OMX_IndexParamVideoInit: {
+ VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
+ OMX_PORT_PARAM_TYPE *portParamType =
+ (OMX_PORT_PARAM_TYPE *) paramData;
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit");
+
+ portParamType->nVersion.nVersion = OMX_SPEC_VERSION;
+ portParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
+ portParamType->nPorts = 2;
+ portParamType->nStartPortNumber = 0;
+ break;
+ }
+ case OMX_IndexParamVideoPortFormat: {
+ VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE);
+ OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
+ (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat");
+
+ portFmt->nVersion.nVersion = OMX_SPEC_VERSION;
+ portFmt->nSize = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE);
+
+ 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");
+ eRet = OMX_ErrorNoMore;
+ }
+ } else if (1 == portFmt->nPortIndex) {
+ portFmt->eCompressionFormat = OMX_VIDEO_CodingUnused;
+
+ // Distinguish non-surface mode from normal playback use-case based on
+ // usage hinted via "OMX.google.android.index.useAndroidNativeBuffer2"
+ // For non-android, use the default list
+ // Also use default format-list if FLEXIBLE YUV is supported,
+ // as the client negotiates the standard color-format if it needs to
+ bool useNonSurfaceMode = false;
+#if defined(_ANDROID_) && !defined(FLEXYUV_SUPPORTED)
+ useNonSurfaceMode = (m_enable_android_native_buffers == OMX_FALSE);
+#endif
+ if (is_thulium_v1) {
+ portFmt->eColorFormat = getPreferredColorFormatDefaultMode(portFmt->nIndex);
+ } else {
+ portFmt->eColorFormat = useNonSurfaceMode ?
+ getPreferredColorFormatNonSurfaceMode(portFmt->nIndex) :
+ getPreferredColorFormatDefaultMode(portFmt->nIndex);
+ }
+
+ if (portFmt->eColorFormat == OMX_COLOR_FormatMax ) {
+ eRet = OMX_ErrorNoMore;
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat:"\
+ " NoMore Color formats");
+ }
+ DEBUG_PRINT_HIGH("returning color-format: 0x%x", portFmt->eColorFormat);
+ } else {
+ DEBUG_PRINT_ERROR("get_parameter: Bad port index %d",
+ (int)portFmt->nPortIndex);
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ break;
+ }
+ /*Component should support this port definition*/
+ case OMX_IndexParamAudioInit: {
+ VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
+ OMX_PORT_PARAM_TYPE *audioPortParamType =
+ (OMX_PORT_PARAM_TYPE *) paramData;
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit");
+ audioPortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
+ audioPortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
+ audioPortParamType->nPorts = 0;
+ audioPortParamType->nStartPortNumber = 0;
+ break;
+ }
+ /*Component should support this port definition*/
+ case OMX_IndexParamImageInit: {
+ VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
+ OMX_PORT_PARAM_TYPE *imagePortParamType =
+ (OMX_PORT_PARAM_TYPE *) paramData;
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit");
+ imagePortParamType->nVersion.nVersion = OMX_SPEC_VERSION;
+ imagePortParamType->nSize = sizeof(OMX_PORT_PARAM_TYPE);
+ imagePortParamType->nPorts = 0;
+ imagePortParamType->nStartPortNumber = 0;
+ break;
+
+ }
+ /*Component should support this port definition*/
+ case OMX_IndexParamOtherInit: {
+ DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamOtherInit %08x",
+ paramIndex);
+ eRet =OMX_ErrorUnsupportedIndex;
+ break;
+ }
+ case OMX_IndexParamStandardComponentRole: {
+ VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE);
+ 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",
+ paramIndex);
+ strlcpy((char*)comp_role->cRole,(const char*)m_cRole,
+ OMX_MAX_STRINGNAME_SIZE);
+ break;
+ }
+ /* Added for parameter test */
+ case OMX_IndexParamPriorityMgmt: {
+ VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE);
+ OMX_PRIORITYMGMTTYPE *priorityMgmType =
+ (OMX_PRIORITYMGMTTYPE *) paramData;
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt");
+ priorityMgmType->nVersion.nVersion = OMX_SPEC_VERSION;
+ priorityMgmType->nSize = sizeof(OMX_PRIORITYMGMTTYPE);
+
+ break;
+ }
+ /* Added for parameter test */
+ case OMX_IndexParamCompBufferSupplier: {
+ VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE);
+ OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType =
+ (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier");
+
+ bufferSupplierType->nSize = sizeof(OMX_PARAM_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",
+ paramIndex);
+ break;
+ }
+ case (OMX_INDEXTYPE)QOMX_IndexParamVideoMvc: {
+ DEBUG_PRINT_LOW("get_parameter: QOMX_IndexParamVideoMvc %08x",
+ paramIndex);
+ break;
+ }
+ case OMX_IndexParamVideoH263: {
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoH263 %08x",
+ paramIndex);
+ break;
+ }
+ case OMX_IndexParamVideoMpeg4: {
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg4 %08x",
+ paramIndex);
+ break;
+ }
+ case OMX_IndexParamVideoMpeg2: {
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg2 %08x",
+ paramIndex);
+ break;
+ }
+ case OMX_IndexParamVideoProfileLevelQuerySupported: {
+ VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
+ DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported %08x", paramIndex);
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType =
+ (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData;
+ eRet = get_supported_profile_level(profileLevelType);
+ break;
+ }
+#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
+ case OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage: {
+ VALIDATE_OMX_PARAM_DATA(paramData, GetAndroidNativeBufferUsageParams);
+ DEBUG_PRINT_LOW("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage");
+ GetAndroidNativeBufferUsageParams* nativeBuffersUsage = (GetAndroidNativeBufferUsageParams *) paramData;
+ if (nativeBuffersUsage->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
+
+ if (secure_mode && !secure_scaling_to_non_secure_opb) {
+ nativeBuffersUsage->nUsage = (GRALLOC_USAGE_PRIVATE_MM_HEAP | GRALLOC_USAGE_PROTECTED |
+ GRALLOC_USAGE_PRIVATE_UNCACHED);
+ } else {
+ nativeBuffersUsage->nUsage = GRALLOC_USAGE_PRIVATE_UNCACHED;
+ }
+ } else {
+ DEBUG_PRINT_HIGH("get_parameter: OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage failed!");
+ eRet = OMX_ErrorBadParameter;
+ }
+ }
+ break;
+#endif
+
+#ifdef FLEXYUV_SUPPORTED
+ case OMX_QcomIndexFlexibleYUVDescription: {
+ DEBUG_PRINT_LOW("get_parameter: describeColorFormat");
+ VALIDATE_OMX_PARAM_DATA(paramData, DescribeColorFormatParams);
+ eRet = describeColorFormat(paramData);
+ break;
+ }
+#endif
+ case OMX_IndexParamVideoProfileLevelCurrent: {
+ VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
+ struct v4l2_control profile_control, level_control;
+
+ switch (drv_ctx.decoder_format) {
+ case VDEC_CODECTYPE_H264:
+ profile_control.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
+ level_control.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
+ break;
+ default:
+ DEBUG_PRINT_ERROR("get_param of OMX_IndexParamVideoProfileLevelCurrent only available for H264");
+ eRet = OMX_ErrorNotImplemented;
+ break;
+ }
+
+ if (!eRet && !ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &profile_control)) {
+ switch ((enum v4l2_mpeg_video_h264_profile)profile_control.value) {
+ case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
+ case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
+ pParam->eProfile = OMX_VIDEO_AVCProfileBaseline;
+ break;
+ case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
+ pParam->eProfile = OMX_VIDEO_AVCProfileMain;
+ break;
+ case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED:
+ pParam->eProfile = OMX_VIDEO_AVCProfileExtended;
+ break;
+ case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
+ pParam->eProfile = OMX_VIDEO_AVCProfileHigh;
+ break;
+ case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10:
+ pParam->eProfile = OMX_VIDEO_AVCProfileHigh10;
+ break;
+ case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422:
+ pParam->eProfile = OMX_VIDEO_AVCProfileHigh422;
+ break;
+ case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE:
+ case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10_INTRA:
+ case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422_INTRA:
+ case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_INTRA:
+ case V4L2_MPEG_VIDEO_H264_PROFILE_CAVLC_444_INTRA:
+ case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_BASELINE:
+ case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH:
+ case V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH_INTRA:
+ case V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH:
+ case V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH:
+ case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH:
+ eRet = OMX_ErrorUnsupportedIndex;
+ break;
+ }
+ } else {
+ eRet = OMX_ErrorUnsupportedIndex;
+ }
+
+
+ if (!eRet && !ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &level_control)) {
+ switch ((enum v4l2_mpeg_video_h264_level)level_control.value) {
+ case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
+ pParam->eLevel = OMX_VIDEO_AVCLevel1;
+ break;
+ case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
+ pParam->eLevel = OMX_VIDEO_AVCLevel1b;
+ break;
+ case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
+ pParam->eLevel = OMX_VIDEO_AVCLevel11;
+ break;
+ case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
+ pParam->eLevel = OMX_VIDEO_AVCLevel12;
+ break;
+ case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
+ pParam->eLevel = OMX_VIDEO_AVCLevel13;
+ break;
+ case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
+ pParam->eLevel = OMX_VIDEO_AVCLevel2;
+ break;
+ case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
+ pParam->eLevel = OMX_VIDEO_AVCLevel21;
+ break;
+ case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
+ pParam->eLevel = OMX_VIDEO_AVCLevel22;
+ break;
+ case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
+ pParam->eLevel = OMX_VIDEO_AVCLevel3;
+ break;
+ case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
+ pParam->eLevel = OMX_VIDEO_AVCLevel31;
+ break;
+ case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
+ pParam->eLevel = OMX_VIDEO_AVCLevel32;
+ break;
+ case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
+ pParam->eLevel = OMX_VIDEO_AVCLevel4;
+ break;
+ case V4L2_MPEG_VIDEO_H264_LEVEL_4_1:
+ pParam->eLevel = OMX_VIDEO_AVCLevel41;
+ break;
+ case V4L2_MPEG_VIDEO_H264_LEVEL_4_2:
+ pParam->eLevel = OMX_VIDEO_AVCLevel42;
+ break;
+ case V4L2_MPEG_VIDEO_H264_LEVEL_5_0:
+ pParam->eLevel = OMX_VIDEO_AVCLevel5;
+ break;
+ case V4L2_MPEG_VIDEO_H264_LEVEL_5_1:
+ pParam->eLevel = OMX_VIDEO_AVCLevel51;
+ break;
+ case V4L2_MPEG_VIDEO_H264_LEVEL_5_2:
+ pParam->eLevel = OMX_VIDEO_AVCLevel52;
+ break;
+ }
+ } else {
+ eRet = OMX_ErrorUnsupportedIndex;
+ }
+
+ break;
+
+ }
+ case OMX_QTIIndexParamVideoClientExtradata:
+ {
+ VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_CLIENT_EXTRADATATYPE);
+ DEBUG_PRINT_LOW("get_parameter: OMX_QTIIndexParamVideoClientExtradata");
+ QOMX_VIDEO_CLIENT_EXTRADATATYPE *pParam =
+ (QOMX_VIDEO_CLIENT_EXTRADATATYPE *)paramData;
+ pParam->nExtradataSize = VENUS_EXTRADATA_SIZE(4096, 2160);
+ pParam->nExtradataAllocSize = pParam->nExtradataSize * MAX_NUM_INPUT_OUTPUT_BUFFERS;
+ eRet = OMX_ErrorNone;
+ break;
+ }
+ default: {
+ DEBUG_PRINT_ERROR("get_parameter: unknown param %08x", paramIndex);
+ eRet =OMX_ErrorUnsupportedIndex;
+ }
+
+ }
+
+ DEBUG_PRINT_LOW("get_parameter returning WxH(%d x %d) SxSH(%d x %d)",
+ drv_ctx.video_resolution.frame_width,
+ drv_ctx.video_resolution.frame_height,
+ drv_ctx.video_resolution.stride,
+ drv_ctx.video_resolution.scan_lines);
+
+ return eRet;
+}
+
+#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
+OMX_ERRORTYPE omx_vdec::use_android_native_buffer(OMX_IN OMX_HANDLETYPE hComp, OMX_PTR data)
+{
+ DEBUG_PRINT_LOW("Inside use_android_native_buffer");
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)data;
+
+ if ((params == NULL) ||
+ (params->nativeBuffer == NULL) ||
+ (params->nativeBuffer->handle == NULL) ||
+ !m_enable_android_native_buffers)
+ return OMX_ErrorBadParameter;
+ m_use_android_native_buffers = OMX_TRUE;
+ sp<android_native_buffer_t> nBuf = params->nativeBuffer;
+ private_handle_t *handle = (private_handle_t *)nBuf->handle;
+ if (OMX_CORE_OUTPUT_PORT_INDEX == params->nPortIndex) { //android native buffers can be used only on Output port
+ OMX_U8 *buffer = NULL;
+ if (!secure_mode) {
+ buffer = (OMX_U8*)mmap(0, handle->size,
+ PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
+ if (buffer == MAP_FAILED) {
+ DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
+ return OMX_ErrorInsufficientResources;
+ }
+ }
+ eRet = use_buffer(hComp,params->bufferHeader,params->nPortIndex,data,handle->size,buffer);
+ } else {
+ eRet = OMX_ErrorBadParameter;
+ }
+ return eRet;
+}
+#endif
+
+OMX_ERRORTYPE omx_vdec::enable_smoothstreaming() {
+ struct v4l2_control control;
+ struct v4l2_format fmt;
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_CONTINUE_DATA_TRANSFER;
+ control.value = 1;
+ int rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
+ if (rc < 0) {
+ DEBUG_PRINT_ERROR("Failed to enable Smooth Streaming on driver.");
+ return OMX_ErrorHardware;
+ }
+ m_smoothstreaming_mode = true;
+ return OMX_ErrorNone;
+}
+
+/* ======================================================================
+ FUNCTION
+ omx_vdec::Setparameter
+
+ DESCRIPTION
+ OMX Set Parameter method implementation.
+
+ PARAMETERS
+ <TBD>.
+
+ RETURN VALUE
+ OMX Error None if successful.
+
+ ========================================================================== */
+OMX_ERRORTYPE omx_vdec::set_parameter(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_INDEXTYPE paramIndex,
+ OMX_IN OMX_PTR paramData)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ int ret=0;
+ struct v4l2_format fmt;
+#ifdef _ANDROID_
+ char property_value[PROPERTY_VALUE_MAX] = {0};
+#endif
+ if (m_state == OMX_StateInvalid) {
+ DEBUG_PRINT_ERROR("Set Param in Invalid State");
+ return OMX_ErrorInvalidState;
+ }
+ if (paramData == NULL) {
+ DEBUG_PRINT_ERROR("Get Param in Invalid paramData");
+ return OMX_ErrorBadParameter;
+ }
+ if ((m_state != OMX_StateLoaded) &&
+ BITMASK_ABSENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING) &&
+ (m_out_bEnabled == OMX_TRUE) &&
+ BITMASK_ABSENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING) &&
+ (m_inp_bEnabled == OMX_TRUE)) {
+ DEBUG_PRINT_ERROR("Set Param in Invalid State");
+ return OMX_ErrorIncorrectStateOperation;
+ }
+ switch ((unsigned long)paramIndex) {
+ case OMX_IndexParamPortDefinition: {
+ VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE);
+ OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
+ portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
+ //TODO: Check if any allocate buffer/use buffer/useNativeBuffer has
+ //been called.
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition H= %d, W = %d",
+ (int)portDefn->format.video.nFrameHeight,
+ (int)portDefn->format.video.nFrameWidth);
+
+ if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
+ DEBUG_PRINT_ERROR("ERROR: Buffers requested exceeds max limit %d",
+ portDefn->nBufferCountActual);
+ eRet = OMX_ErrorBadParameter;
+ break;
+ }
+ if (OMX_DirOutput == portDefn->eDir) {
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition OP port");
+ bool port_format_changed = false;
+ m_display_id = portDefn->format.video.pNativeWindow;
+ unsigned int buffer_size;
+ /* update output port resolution with client supplied dimensions
+ in case scaling is enabled, else it follows input resolution set
+ */
+ decide_dpb_buffer_mode(is_down_scalar_enabled);
+ if (is_down_scalar_enabled) {
+ DEBUG_PRINT_LOW("SetParam OP: WxH(%u x %u)",
+ (unsigned int)portDefn->format.video.nFrameWidth,
+ (unsigned int)portDefn->format.video.nFrameHeight);
+ if (portDefn->format.video.nFrameHeight != 0x0 &&
+ portDefn->format.video.nFrameWidth != 0x0) {
+ memset(&fmt, 0x0, sizeof(struct v4l2_format));
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ fmt.fmt.pix_mp.pixelformat = capture_capability;
+ ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
+ if (ret) {
+ DEBUG_PRINT_ERROR("Get Resolution failed");
+ eRet = OMX_ErrorHardware;
+ break;
+ }
+ if ((portDefn->format.video.nFrameHeight != (unsigned int)fmt.fmt.pix_mp.height) ||
+ (portDefn->format.video.nFrameWidth != (unsigned int)fmt.fmt.pix_mp.width)) {
+ port_format_changed = true;
+ }
+
+ /* set crop info */
+ rectangle.nLeft = 0;
+ rectangle.nTop = 0;
+ rectangle.nWidth = portDefn->format.video.nFrameWidth;
+ rectangle.nHeight = portDefn->format.video.nFrameHeight;
+
+ eRet = is_video_session_supported();
+ if (eRet)
+ break;
+ memset(&fmt, 0x0, sizeof(struct v4l2_format));
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ fmt.fmt.pix_mp.height = (unsigned int)portDefn->format.video.nFrameHeight;
+ fmt.fmt.pix_mp.width = (unsigned int)portDefn->format.video.nFrameWidth;
+ fmt.fmt.pix_mp.pixelformat = capture_capability;
+ DEBUG_PRINT_LOW("fmt.fmt.pix_mp.height = %d , fmt.fmt.pix_mp.width = %d",
+ fmt.fmt.pix_mp.height, fmt.fmt.pix_mp.width);
+ ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
+ if (ret) {
+ DEBUG_PRINT_ERROR("Set Resolution failed");
+ eRet = OMX_ErrorUnsupportedSetting;
+ } else
+ eRet = get_buffer_req(&drv_ctx.op_buf);
+ }
+
+ if (eRet) {
+ break;
+ }
+
+ if (secure_mode) {
+ struct v4l2_control control;
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE_SCALING_THRESHOLD;
+ if (ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control) < 0) {
+ DEBUG_PRINT_ERROR("Failed getting secure scaling threshold : %d, id was : %x", errno, control.id);
+ eRet = OMX_ErrorHardware;
+ } else {
+ /* This is a workaround for a bug in fw which uses stride
+ * and slice instead of width and height to check against
+ * the threshold.
+ */
+ OMX_U32 stride, slice;
+ if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
+ stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, portDefn->format.video.nFrameWidth);
+ slice = VENUS_Y_SCANLINES(COLOR_FMT_NV12, portDefn->format.video.nFrameHeight);
+ } else if (drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
+ stride = VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, portDefn->format.video.nFrameWidth);
+ slice = VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, portDefn->format.video.nFrameHeight);
+ } else {
+ stride = portDefn->format.video.nFrameWidth;
+ slice = portDefn->format.video.nFrameHeight;
+ }
+
+ DEBUG_PRINT_LOW("Stride is %d, slice is %d, sxs is %d\n", stride, slice, stride * slice);
+ DEBUG_PRINT_LOW("Threshold value is %d\n", control.value);
+
+ if (stride * slice <= (OMX_U32)control.value) {
+ secure_scaling_to_non_secure_opb = true;
+ DEBUG_PRINT_HIGH("Enabling secure scalar out of CPZ");
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_NON_SECURE_OUTPUT2;
+ control.value = 1;
+ if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) {
+ DEBUG_PRINT_ERROR("Enabling non-secure output2 failed");
+ eRet = OMX_ErrorUnsupportedSetting;
+ }
+ }
+ }
+ }
+ }
+
+ if (eRet) {
+ break;
+ }
+
+ if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
+ DEBUG_PRINT_ERROR("Requested o/p buf count (%u) exceeds limit (%u)",
+ portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS);
+ eRet = OMX_ErrorBadParameter;
+ } else if (!client_buffers.get_buffer_req(buffer_size)) {
+ DEBUG_PRINT_ERROR("Error in getting buffer requirements");
+ eRet = OMX_ErrorBadParameter;
+ } else if (!port_format_changed) {
+
+ // Buffer count can change only when port is unallocated
+ if (m_out_mem_ptr &&
+ (portDefn->nBufferCountActual != drv_ctx.op_buf.actualcount ||
+ portDefn->nBufferSize != drv_ctx.op_buf.buffer_size)) {
+
+ DEBUG_PRINT_ERROR("Cannot change o/p buffer count since all buffers are not freed yet !");
+ eRet = OMX_ErrorInvalidState;
+ break;
+ }
+
+ // route updating of buffer requirements via c2d proxy.
+ // Based on whether c2d is enabled, requirements will be handed
+ // to the vidc driver appropriately
+ eRet = client_buffers.set_buffer_req(portDefn->nBufferSize,
+ portDefn->nBufferCountActual);
+ if (eRet == OMX_ErrorNone) {
+ m_port_def = *portDefn;
+ } else {
+ DEBUG_PRINT_ERROR("ERROR: OP Requirements(#%d: %u) Requested(#%u: %u)",
+ drv_ctx.op_buf.mincount, (unsigned int)buffer_size,
+ (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize);
+ eRet = OMX_ErrorBadParameter;
+ }
+ }
+ } else if (OMX_DirInput == portDefn->eDir) {
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPortDefinition IP port");
+ bool port_format_changed = false;
+ if ((portDefn->format.video.xFramerate >> 16) > 0 &&
+ (portDefn->format.video.xFramerate >> 16) <= MAX_SUPPORTED_FPS) {
+ // Frame rate only should be set if this is a "known value" or to
+ // activate ts prediction logic (arbitrary mode only) sending input
+ // timestamps with max value (LLONG_MAX).
+ DEBUG_PRINT_HIGH("set_parameter: frame rate set by omx client : %u",
+ (unsigned int)portDefn->format.video.xFramerate >> 16);
+ Q16ToFraction(portDefn->format.video.xFramerate, drv_ctx.frame_rate.fps_numerator,
+ drv_ctx.frame_rate.fps_denominator);
+ if (!drv_ctx.frame_rate.fps_numerator) {
+ DEBUG_PRINT_ERROR("Numerator is zero setting to 30");
+ drv_ctx.frame_rate.fps_numerator = 30;
+ }
+ if (drv_ctx.frame_rate.fps_denominator)
+ drv_ctx.frame_rate.fps_numerator = (int)
+ drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
+ drv_ctx.frame_rate.fps_denominator = 1;
+ frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 /
+ drv_ctx.frame_rate.fps_numerator;
+ DEBUG_PRINT_LOW("set_parameter: frm_int(%u) fps(%.2f)",
+ (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator /
+ (float)drv_ctx.frame_rate.fps_denominator);
+
+ struct v4l2_outputparm oparm;
+ /*XXX: we're providing timing info as seconds per frame rather than frames
+ * per second.*/
+ oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
+ oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
+
+ struct v4l2_streamparm sparm;
+ sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ sparm.parm.output = oparm;
+ if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
+ DEBUG_PRINT_ERROR("Unable to convey fps info to driver, performance might be affected");
+ eRet = OMX_ErrorHardware;
+ break;
+ }
+ m_perf_control.request_cores(frm_int);
+ }
+
+ if (drv_ctx.video_resolution.frame_height !=
+ portDefn->format.video.nFrameHeight ||
+ drv_ctx.video_resolution.frame_width !=
+ portDefn->format.video.nFrameWidth) {
+ DEBUG_PRINT_LOW("SetParam IP: WxH(%u x %u)",
+ (unsigned int)portDefn->format.video.nFrameWidth,
+ (unsigned int)portDefn->format.video.nFrameHeight);
+ port_format_changed = true;
+ OMX_U32 frameWidth = portDefn->format.video.nFrameWidth;
+ OMX_U32 frameHeight = portDefn->format.video.nFrameHeight;
+ if (frameHeight != 0x0 && frameWidth != 0x0) {
+ if (m_smoothstreaming_mode &&
+ ((frameWidth * frameHeight) <
+ (m_smoothstreaming_width * m_smoothstreaming_height))) {
+ frameWidth = m_smoothstreaming_width;
+ frameHeight = m_smoothstreaming_height;
+ DEBUG_PRINT_LOW("NOTE: Setting resolution %u x %u "
+ "for adaptive-playback/smooth-streaming",
+ (unsigned int)frameWidth, (unsigned int)frameHeight);
+ }
+ update_resolution(frameWidth, frameHeight,
+ frameWidth, frameHeight);
+ eRet = is_video_session_supported();
+ if (eRet)
+ break;
+ if (is_down_scalar_enabled) {
+ memset(&fmt, 0x0, sizeof(struct v4l2_format));
+ fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
+ fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
+ fmt.fmt.pix_mp.pixelformat = output_capability;
+ DEBUG_PRINT_LOW("DS Enabled : height = %d , width = %d",
+ fmt.fmt.pix_mp.height,fmt.fmt.pix_mp.width);
+ ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
+ } else {
+ memset(&fmt, 0x0, sizeof(struct v4l2_format));
+ fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
+ fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
+ fmt.fmt.pix_mp.pixelformat = output_capability;
+ DEBUG_PRINT_LOW("DS Disabled : height = %d , width = %d",
+ fmt.fmt.pix_mp.height,fmt.fmt.pix_mp.width);
+ ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ fmt.fmt.pix_mp.pixelformat = capture_capability;
+ ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
+ }
+ if (ret) {
+ DEBUG_PRINT_ERROR("Set Resolution failed");
+ eRet = OMX_ErrorUnsupportedSetting;
+ } else {
+ if (!is_down_scalar_enabled)
+ eRet = get_buffer_req(&drv_ctx.op_buf);
+ }
+ }
+ }
+ if (m_custom_buffersize.input_buffersize
+ && (portDefn->nBufferSize > m_custom_buffersize.input_buffersize)) {
+ DEBUG_PRINT_ERROR("ERROR: Custom buffer size set by client: %d, trying to set: %d",
+ m_custom_buffersize.input_buffersize, portDefn->nBufferSize);
+ eRet = OMX_ErrorBadParameter;
+ break;
+ }
+ if (portDefn->nBufferCountActual > MAX_NUM_INPUT_OUTPUT_BUFFERS) {
+ DEBUG_PRINT_ERROR("Requested i/p buf count (%u) exceeds limit (%u)",
+ portDefn->nBufferCountActual, MAX_NUM_INPUT_OUTPUT_BUFFERS);
+ eRet = OMX_ErrorBadParameter;
+ break;
+ }
+ // Buffer count can change only when port is unallocated
+ if (m_inp_mem_ptr &&
+ (portDefn->nBufferCountActual != drv_ctx.ip_buf.actualcount ||
+ portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size)) {
+ DEBUG_PRINT_ERROR("Cannot change i/p buffer count since all buffers are not freed yet !");
+ eRet = OMX_ErrorInvalidState;
+ break;
+ }
+
+ if (portDefn->nBufferCountActual >= drv_ctx.ip_buf.mincount
+ || portDefn->nBufferSize != drv_ctx.ip_buf.buffer_size) {
+ port_format_changed = true;
+ vdec_allocatorproperty *buffer_prop = &drv_ctx.ip_buf;
+ drv_ctx.ip_buf.actualcount = portDefn->nBufferCountActual;
+ drv_ctx.ip_buf.buffer_size = (portDefn->nBufferSize + buffer_prop->alignment - 1) &
+ (~(buffer_prop->alignment - 1));
+ eRet = set_buffer_req(buffer_prop);
+ }
+ if (false == port_format_changed) {
+ DEBUG_PRINT_ERROR("ERROR: IP Requirements(#%d: %u) Requested(#%u: %u)",
+ drv_ctx.ip_buf.mincount, (unsigned int)drv_ctx.ip_buf.buffer_size,
+ (unsigned int)portDefn->nBufferCountActual, (unsigned int)portDefn->nBufferSize);
+ eRet = OMX_ErrorBadParameter;
+ }
+ } else if (portDefn->eDir == OMX_DirMax) {
+ DEBUG_PRINT_ERROR(" Set_parameter: Bad Port idx %d",
+ (int)portDefn->nPortIndex);
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ }
+ break;
+ case OMX_IndexParamVideoPortFormat: {
+ VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE);
+ OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
+ (OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
+ int ret=0;
+ struct v4l2_format fmt;
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoPortFormat 0x%x, port: %u",
+ portFmt->eColorFormat, (unsigned int)portFmt->nPortIndex);
+
+ memset(&fmt, 0x0, sizeof(struct v4l2_format));
+ if (1 == portFmt->nPortIndex) {
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
+ if (ret < 0) {
+ DEBUG_PRINT_ERROR("%s: Failed to get format on capture mplane", __func__);
+ return OMX_ErrorBadParameter;
+ }
+ enum vdec_output_fromat op_format;
+ if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
+ QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m ||
+ portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
+ QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView ||
+ portFmt->eColorFormat == OMX_COLOR_FormatYUV420Planar ||
+ portFmt->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
+ op_format = (enum vdec_output_fromat)VDEC_YUV_FORMAT_NV12;
+ } else if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
+ QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) {
+ op_format = (enum vdec_output_fromat)VDEC_YUV_FORMAT_NV12_UBWC;
+ } else
+ eRet = OMX_ErrorBadParameter;
+
+ if (portFmt->eColorFormat == (OMX_COLOR_FORMATTYPE)
+ QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) {
+ fmt.fmt.pix_mp.pixelformat = capture_capability = V4L2_PIX_FMT_NV12_UBWC;
+ } else {
+ fmt.fmt.pix_mp.pixelformat = capture_capability = V4L2_PIX_FMT_NV12;
+ }
+
+ if (eRet == OMX_ErrorNone) {
+ drv_ctx.output_format = op_format;
+ ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
+ if (ret) {
+ DEBUG_PRINT_ERROR("Set output format failed");
+ eRet = OMX_ErrorUnsupportedSetting;
+ /*TODO: How to handle this case */
+ } else {
+ eRet = get_buffer_req(&drv_ctx.op_buf);
+ }
+ }
+ if (eRet == OMX_ErrorNone) {
+ if (!client_buffers.set_color_format(portFmt->eColorFormat)) {
+ DEBUG_PRINT_ERROR("Set color format failed");
+ eRet = OMX_ErrorBadParameter;
+ }
+ }
+ }
+ }
+ break;
+
+ case OMX_QcomIndexPortDefn: {
+ VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_PARAM_PORTDEFINITIONTYPE);
+ OMX_QCOM_PARAM_PORTDEFINITIONTYPE *portFmt =
+ (OMX_QCOM_PARAM_PORTDEFINITIONTYPE *) paramData;
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexQcomParamPortDefinitionType %u",
+ (unsigned int)portFmt->nFramePackingFormat);
+
+ /* Input port */
+ if (portFmt->nPortIndex == 0) {
+ // arbitrary_bytes mode cannot be changed arbitrarily since this controls how:
+ // - headers are allocated and
+ // - headers-indices are derived
+ // Avoid changing arbitrary_bytes when the port is already allocated
+ if (m_inp_mem_ptr) {
+ DEBUG_PRINT_ERROR("Cannot change arbitrary-bytes-mode since input port is not free!");
+ return OMX_ErrorUnsupportedSetting;
+ }
+ if (portFmt->nFramePackingFormat == OMX_QCOM_FramePacking_Arbitrary) {
+ if (secure_mode || m_input_pass_buffer_fd) {
+ arbitrary_bytes = false;
+ DEBUG_PRINT_ERROR("setparameter: cannot set to arbitary bytes mode");
+ eRet = OMX_ErrorUnsupportedSetting;
+ } else {
+ arbitrary_bytes = true;
+ }
+ } else if (portFmt->nFramePackingFormat ==
+ OMX_QCOM_FramePacking_OnlyOneCompleteFrame) {
+ arbitrary_bytes = false;
+#ifdef _ANDROID_
+ property_get("vidc.dec.debug.arbitrarybytes.mode", property_value, "0");
+ if (atoi(property_value)) {
+ DEBUG_PRINT_HIGH("arbitrary_bytes enabled via property command");
+ arbitrary_bytes = true;
+ }
+#endif
+ } else {
+ DEBUG_PRINT_ERROR("Setparameter: unknown FramePacking format %u",
+ (unsigned int)portFmt->nFramePackingFormat);
+ eRet = OMX_ErrorUnsupportedSetting;
+ }
+ } else if (portFmt->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
+ DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port");
+ if ( (portFmt->nMemRegion > OMX_QCOM_MemRegionInvalid &&
+ portFmt->nMemRegion < OMX_QCOM_MemRegionMax) &&
+ portFmt->nCacheAttr == OMX_QCOM_CacheAttrNone) {
+ m_out_mem_region_smi = OMX_TRUE;
+ if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) {
+ DEBUG_PRINT_HIGH("set_parameter: OMX_IndexQcomParamPortDefinitionType OP Port: out pmem set");
+ m_use_output_pmem = OMX_TRUE;
+ }
+ }
+ }
+ }
+ if (is_thulium_v1 && !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",
+ OMX_MAX_STRINGNAME_SIZE)) {
+ arbitrary_bytes = true;
+ DEBUG_PRINT_HIGH("Force arbitrary_bytes to true for h264");
+ }
+ break;
+
+ case OMX_IndexParamStandardComponentRole: {
+ VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE);
+ OMX_PARAM_COMPONENTROLETYPE *comp_role;
+ comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamStandardComponentRole %s",
+ comp_role->cRole);
+
+ if ((m_state == OMX_StateLoaded)&&
+ !BITMASK_PRESENT(&m_flags, OMX_COMPONENT_IDLE_PENDING)) {
+ DEBUG_PRINT_LOW("Set Parameter called in valid state");
+ } else {
+ DEBUG_PRINT_ERROR("Set Parameter called in Invalid State");
+ return OMX_ErrorIncorrectStateOperation;
+ }
+
+ if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc", OMX_MAX_STRINGNAME_SIZE)) {
+ if (!strncmp((char*)comp_role->cRole, "video_decoder.avc", OMX_MAX_STRINGNAME_SIZE)) {
+ strlcpy((char*)m_cRole, "video_decoder.avc", OMX_MAX_STRINGNAME_SIZE);
+ } else {
+ DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
+ eRet =OMX_ErrorUnsupportedSetting;
+ }
+ } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
+ if (!strncmp((char*)comp_role->cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
+ strlcpy((char*)m_cRole, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
+ } else {
+ DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
+ eRet = OMX_ErrorUnsupportedSetting;
+ }
+ } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE)) {
+ if (!strncmp((const char*)comp_role->cRole, "video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE)) {
+ strlcpy((char*)m_cRole, "video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE);
+ } else {
+ DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
+ eRet = OMX_ErrorUnsupportedSetting;
+ }
+ } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263", OMX_MAX_STRINGNAME_SIZE)) {
+ if (!strncmp((const char*)comp_role->cRole, "video_decoder.h263", OMX_MAX_STRINGNAME_SIZE)) {
+ strlcpy((char*)m_cRole, "video_decoder.h263", OMX_MAX_STRINGNAME_SIZE);
+ } else {
+ DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
+ eRet =OMX_ErrorUnsupportedSetting;
+ }
+ } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
+ if (!strncmp((const char*)comp_role->cRole, "video_decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE)) {
+ strlcpy((char*)m_cRole, "video_decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE);
+ } else {
+ DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
+ eRet = OMX_ErrorUnsupportedSetting;
+ }
+ } else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx", OMX_MAX_STRINGNAME_SIZE)) ||
+ (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311", OMX_MAX_STRINGNAME_SIZE)) ||
+ (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx4", OMX_MAX_STRINGNAME_SIZE))
+ ) {
+ if (!strncmp((const char*)comp_role->cRole, "video_decoder.divx", OMX_MAX_STRINGNAME_SIZE)) {
+ strlcpy((char*)m_cRole, "video_decoder.divx", OMX_MAX_STRINGNAME_SIZE);
+ } else {
+ DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
+ eRet =OMX_ErrorUnsupportedSetting;
+ }
+ } else if ( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1", OMX_MAX_STRINGNAME_SIZE)) ||
+ (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv", OMX_MAX_STRINGNAME_SIZE))
+ ) {
+ if (!strncmp((const char*)comp_role->cRole, "video_decoder.vc1", OMX_MAX_STRINGNAME_SIZE)) {
+ strlcpy((char*)m_cRole, "video_decoder.vc1", OMX_MAX_STRINGNAME_SIZE);
+ } else {
+ DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
+ eRet =OMX_ErrorUnsupportedSetting;
+ }
+ } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8", OMX_MAX_STRINGNAME_SIZE)) {
+ if (!strncmp((const char*)comp_role->cRole, "video_decoder.vp8", OMX_MAX_STRINGNAME_SIZE) ||
+ !strncmp((const char*)comp_role->cRole, "video_decoder.vpx", OMX_MAX_STRINGNAME_SIZE)) {
+ strlcpy((char*)m_cRole, "video_decoder.vp8", OMX_MAX_STRINGNAME_SIZE);
+ } else {
+ DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
+ eRet = OMX_ErrorUnsupportedSetting;
+ }
+ } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9", OMX_MAX_STRINGNAME_SIZE)) {
+ if (!strncmp((const char*)comp_role->cRole, "video_decoder.vp9", OMX_MAX_STRINGNAME_SIZE) ||
+ !strncmp((const char*)comp_role->cRole, "video_decoder.vpx", OMX_MAX_STRINGNAME_SIZE)) {
+ strlcpy((char*)m_cRole, "video_decoder.vp9", OMX_MAX_STRINGNAME_SIZE);
+ } else {
+ DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
+ eRet = OMX_ErrorUnsupportedSetting;
+ }
+ } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
+ if (!strncmp((const char*)comp_role->cRole, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
+ strlcpy((char*)m_cRole, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE);
+ } else {
+ DEBUG_PRINT_ERROR("Setparameter: unknown Index %s", comp_role->cRole);
+ eRet = OMX_ErrorUnsupportedSetting;
+ }
+ } else {
+ DEBUG_PRINT_ERROR("Setparameter: unknown param %s", drv_ctx.kind);
+ eRet = OMX_ErrorInvalidComponentName;
+ }
+ break;
+ }
+
+ case OMX_IndexParamPriorityMgmt: {
+ VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE);
+ if (m_state != OMX_StateLoaded) {
+ DEBUG_PRINT_ERROR("Set Parameter called in Invalid State");
+ return OMX_ErrorIncorrectStateOperation;
+ }
+ OMX_PRIORITYMGMTTYPE *priorityMgmtype = (OMX_PRIORITYMGMTTYPE*) paramData;
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamPriorityMgmt %u",
+ (unsigned int)priorityMgmtype->nGroupID);
+
+ DEBUG_PRINT_LOW("set_parameter: priorityMgmtype %u",
+ (unsigned int)priorityMgmtype->nGroupPriority);
+
+ m_priority_mgm.nGroupID = priorityMgmtype->nGroupID;
+ m_priority_mgm.nGroupPriority = priorityMgmtype->nGroupPriority;
+
+ break;
+ }
+
+ case OMX_IndexParamCompBufferSupplier: {
+ VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE);
+ OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamCompBufferSupplier %d",
+ bufferSupplierType->eBufferSupplier);
+ if (bufferSupplierType->nPortIndex == 0 || bufferSupplierType->nPortIndex ==1)
+ m_buffer_supplier.eBufferSupplier = bufferSupplierType->eBufferSupplier;
+
+ else
+
+ eRet = OMX_ErrorBadPortIndex;
+
+ break;
+
+ }
+ case OMX_IndexParamVideoAvc: {
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoAvc %d",
+ paramIndex);
+ break;
+ }
+ case (OMX_INDEXTYPE)QOMX_IndexParamVideoMvc: {
+ DEBUG_PRINT_LOW("set_parameter: QOMX_IndexParamVideoMvc %d",
+ paramIndex);
+ break;
+ }
+ case OMX_IndexParamVideoH263: {
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoH263 %d",
+ paramIndex);
+ break;
+ }
+ case OMX_IndexParamVideoMpeg4: {
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg4 %d",
+ paramIndex);
+ break;
+ }
+ case OMX_IndexParamVideoMpeg2: {
+ DEBUG_PRINT_LOW("set_parameter: OMX_IndexParamVideoMpeg2 %d",
+ paramIndex);
+ break;
+ }
+ case OMX_QTIIndexParamLowLatencyMode: {
+ struct v4l2_control control;
+ int rc = 0;
+ QOMX_EXTNINDEX_VIDEO_VENC_LOW_LATENCY_MODE* pParam =
+ (QOMX_EXTNINDEX_VIDEO_VENC_LOW_LATENCY_MODE*)paramData;
+ if (pParam->bLowLatencyMode) {
+ DEBUG_PRINT_HIGH("Enabling DECODE order");
+ time_stamp_dts.set_timestamp_reorder_mode(false);
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
+ control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
+ rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
+ if (rc) {
+ DEBUG_PRINT_ERROR("Set picture order failed");
+ eRet = OMX_ErrorUnsupportedSetting;
+ }
+ }
+ break;
+ }
+ case OMX_QcomIndexParamVideoDecoderPictureOrder: {
+ VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_DECODER_PICTURE_ORDER);
+ QOMX_VIDEO_DECODER_PICTURE_ORDER *pictureOrder =
+ (QOMX_VIDEO_DECODER_PICTURE_ORDER *)paramData;
+ struct v4l2_control control;
+ int pic_order,rc=0;
+ DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoDecoderPictureOrder %d",
+ pictureOrder->eOutputPictureOrder);
+ if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DISPLAY_ORDER) {
+ pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY;
+ } else if (pictureOrder->eOutputPictureOrder == QOMX_VIDEO_DECODE_ORDER) {
+ pic_order = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
+ time_stamp_dts.set_timestamp_reorder_mode(false);
+ } else
+ eRet = OMX_ErrorBadParameter;
+ if (eRet == OMX_ErrorNone) {
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
+ control.value = pic_order;
+ rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
+ if (rc) {
+ DEBUG_PRINT_ERROR("Set picture order failed");
+ eRet = OMX_ErrorUnsupportedSetting;
+ }
+ }
+ break;
+ }
+ case OMX_QcomIndexParamConcealMBMapExtraData:
+ VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
+ eRet = enable_extradata(VDEC_EXTRADATA_MB_ERROR_MAP, false,
+ ((QOMX_ENABLETYPE *)paramData)->bEnable);
+ break;
+ case OMX_QcomIndexParamFrameInfoExtraData:
+ VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
+ eRet = enable_extradata(OMX_FRAMEINFO_EXTRADATA, false,
+ ((QOMX_ENABLETYPE *)paramData)->bEnable);
+ break;
+ case OMX_ExtraDataFrameDimension:
+ VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
+ eRet = enable_extradata(OMX_FRAMEDIMENSION_EXTRADATA, false,
+ ((QOMX_ENABLETYPE *)paramData)->bEnable);
+ break;
+ case OMX_QcomIndexParamInterlaceExtraData:
+ VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
+ eRet = enable_extradata(OMX_INTERLACE_EXTRADATA, false,
+ ((QOMX_ENABLETYPE *)paramData)->bEnable);
+ break;
+ case OMX_QcomIndexParamH264TimeInfo:
+ VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
+ eRet = enable_extradata(OMX_TIMEINFO_EXTRADATA, false,
+ ((QOMX_ENABLETYPE *)paramData)->bEnable);
+ break;
+ case OMX_QcomIndexParamVideoFramePackingExtradata:
+ VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
+ eRet = enable_extradata(OMX_FRAMEPACK_EXTRADATA, false,
+ ((QOMX_ENABLETYPE *)paramData)->bEnable);
+ break;
+ case OMX_QcomIndexParamVideoQPExtraData:
+ VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
+ eRet = enable_extradata(OMX_QP_EXTRADATA, false,
+ ((QOMX_ENABLETYPE *)paramData)->bEnable);
+ break;
+ case OMX_QcomIndexParamVideoInputBitsInfoExtraData:
+ VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
+ eRet = enable_extradata(OMX_BITSINFO_EXTRADATA, false,
+ ((QOMX_ENABLETYPE *)paramData)->bEnable);
+ break;
+ case OMX_QcomIndexEnableExtnUserData:
+ VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
+ eRet = enable_extradata(OMX_EXTNUSER_EXTRADATA, false,
+ ((QOMX_ENABLETYPE *)paramData)->bEnable);
+ break;
+ case OMX_QTIIndexParamVQZipSEIExtraData:
+ VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
+ eRet = enable_extradata(OMX_VQZIPSEI_EXTRADATA, false,
+ ((QOMX_ENABLETYPE *)paramData)->bEnable);
+ break;
+ case OMX_QcomIndexParamVideoDivx: {
+ QOMX_VIDEO_PARAM_DIVXTYPE* divXType = (QOMX_VIDEO_PARAM_DIVXTYPE *) paramData;
+ }
+ break;
+ case OMX_QcomIndexPlatformPvt: {
+ VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_PLATFORMPRIVATE_EXTN);
+ DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port");
+ OMX_QCOM_PLATFORMPRIVATE_EXTN* entryType = (OMX_QCOM_PLATFORMPRIVATE_EXTN *) paramData;
+ if (entryType->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) {
+ DEBUG_PRINT_HIGH("set_parameter: Platform Private entry type (%d) not supported.", entryType->type);
+ eRet = OMX_ErrorUnsupportedSetting;
+ } else {
+ m_out_pvt_entry_pmem = OMX_TRUE;
+ if ((m_out_mem_region_smi && m_out_pvt_entry_pmem)) {
+ DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexPlatformPvt OP Port: out pmem set");
+ m_use_output_pmem = OMX_TRUE;
+ }
+ }
+
+ }
+ break;
+ case OMX_QcomIndexParamVideoSyncFrameDecodingMode: {
+ DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamVideoSyncFrameDecodingMode");
+ DEBUG_PRINT_HIGH("set idr only decoding for thumbnail mode");
+ struct v4l2_control control;
+ int rc;
+ drv_ctx.idr_only_decoding = 1;
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER;
+ control.value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE;
+ rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
+ if (rc) {
+ DEBUG_PRINT_ERROR("Set picture order failed");
+ eRet = OMX_ErrorUnsupportedSetting;
+ } else {
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE;
+ control.value = V4L2_MPEG_VIDC_VIDEO_SYNC_FRAME_DECODE_ENABLE;
+ rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control);
+ if (rc) {
+ DEBUG_PRINT_ERROR("Sync frame setting failed");
+ eRet = OMX_ErrorUnsupportedSetting;
+ }
+ /*Setting sync frame decoding on driver might change buffer
+ * requirements so update them here*/
+ if (get_buffer_req(&drv_ctx.ip_buf)) {
+ DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer i/p requirements");
+ eRet = OMX_ErrorUnsupportedSetting;
+ }
+ if (get_buffer_req(&drv_ctx.op_buf)) {
+ DEBUG_PRINT_ERROR("Sync frame setting failed: falied to get buffer o/p requirements");
+ eRet = OMX_ErrorUnsupportedSetting;
+ }
+ }
+ }
+ break;
+
+ case OMX_QcomIndexParamIndexExtraDataType: {
+ VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXEXTRADATATYPE);
+ QOMX_INDEXEXTRADATATYPE *extradataIndexType = (QOMX_INDEXEXTRADATATYPE *) paramData;
+ if ((extradataIndexType->nIndex == OMX_IndexParamPortDefinition) &&
+ (extradataIndexType->bEnabled == OMX_TRUE) &&
+ (extradataIndexType->nPortIndex == 1)) {
+ DEBUG_PRINT_HIGH("set_parameter: OMX_QcomIndexParamIndexExtraDataType SmoothStreaming");
+ eRet = enable_extradata(OMX_PORTDEF_EXTRADATA, false, extradataIndexType->bEnabled);
+
+ }
+ }
+ break;
+ case OMX_QcomIndexParamEnableSmoothStreaming: {
+#ifndef SMOOTH_STREAMING_DISABLED
+ eRet = enable_smoothstreaming();
+#else
+ eRet = OMX_ErrorUnsupportedSetting;
+#endif
+ }
+ break;
+#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
+ /* Need to allow following two set_parameters even in Idle
+ * state. This is ANDROID architecture which is not in sync
+ * with openmax standard. */
+ case OMX_GoogleAndroidIndexEnableAndroidNativeBuffers: {
+ VALIDATE_OMX_PARAM_DATA(paramData, EnableAndroidNativeBuffersParams);
+ EnableAndroidNativeBuffersParams* enableNativeBuffers = (EnableAndroidNativeBuffersParams *) paramData;
+ if (enableNativeBuffers->nPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) {
+ DEBUG_PRINT_ERROR("Enable/Disable android-native-buffers allowed only on output port!");
+ eRet = OMX_ErrorUnsupportedSetting;
+ break;
+ } else if (m_out_mem_ptr) {
+ DEBUG_PRINT_ERROR("Enable/Disable android-native-buffers is not allowed since Output port is not free !");
+ eRet = OMX_ErrorInvalidState;
+ break;
+ }
+ if (enableNativeBuffers) {
+ m_enable_android_native_buffers = enableNativeBuffers->enable;
+ }
+#if !defined(FLEXYUV_SUPPORTED)
+ if (m_enable_android_native_buffers) {
+ // Use the most-preferred-native-color-format as surface-mode is hinted here
+ if(!client_buffers.set_color_format(getPreferredColorFormatDefaultMode(0))) {
+ DEBUG_PRINT_ERROR("Failed to set native color format!");
+ eRet = OMX_ErrorUnsupportedSetting;
+ }
+ }
+#endif
+ }
+ break;
+ case OMX_GoogleAndroidIndexUseAndroidNativeBuffer: {
+ VALIDATE_OMX_PARAM_DATA(paramData, UseAndroidNativeBufferParams);
+ eRet = use_android_native_buffer(hComp, paramData);
+ }
+ break;
+#if ALLOCATE_OUTPUT_NATIVEHANDLE
+ case OMX_GoogleAndroidIndexAllocateNativeHandle: {
+
+ AllocateNativeHandleParams* allocateNativeHandleParams = (AllocateNativeHandleParams *) paramData;
+ VALIDATE_OMX_PARAM_DATA(paramData, AllocateNativeHandleParams);
+
+ if (allocateNativeHandleParams->nPortIndex != OMX_CORE_INPUT_PORT_INDEX) {
+ DEBUG_PRINT_ERROR("Enable/Disable allocate-native-handle allowed only on input port!");
+ eRet = OMX_ErrorUnsupportedSetting;
+ break;
+ } else if (m_inp_mem_ptr) {
+ DEBUG_PRINT_ERROR("Enable/Disable allocate-native-handle is not allowed since Input port is not free !");
+ eRet = OMX_ErrorInvalidState;
+ break;
+ }
+
+ if (allocateNativeHandleParams != NULL) {
+ allocate_native_handle = allocateNativeHandleParams->enable;
+ }
+ }
+ break;
+#endif //ALLOCATE_OUTPUT_NATIVEHANDLE
+#endif
+ case OMX_QcomIndexParamEnableTimeStampReorder: {
+ VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXTIMESTAMPREORDER);
+ QOMX_INDEXTIMESTAMPREORDER *reorder = (QOMX_INDEXTIMESTAMPREORDER *)paramData;
+ if (drv_ctx.picture_order == (vdec_output_order)QOMX_VIDEO_DISPLAY_ORDER) {
+ if (reorder->bEnable == OMX_TRUE) {
+ frm_int =0;
+ time_stamp_dts.set_timestamp_reorder_mode(true);
+ } else
+ time_stamp_dts.set_timestamp_reorder_mode(false);
+ } else {
+ time_stamp_dts.set_timestamp_reorder_mode(false);
+ if (reorder->bEnable == OMX_TRUE) {
+ eRet = OMX_ErrorUnsupportedSetting;
+ }
+ }
+ }
+ break;
+ case OMX_IndexParamVideoProfileLevelCurrent: {
+ VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam =
+ (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
+ if (pParam) {
+ m_profile_lvl.eProfile = pParam->eProfile;
+ m_profile_lvl.eLevel = pParam->eLevel;
+ }
+ break;
+
+ }
+ case OMX_QcomIndexParamVideoMetaBufferMode:
+ {
+ VALIDATE_OMX_PARAM_DATA(paramData, StoreMetaDataInBuffersParams);
+ StoreMetaDataInBuffersParams *metabuffer =
+ (StoreMetaDataInBuffersParams *)paramData;
+ if (!metabuffer) {
+ DEBUG_PRINT_ERROR("Invalid param: %p", metabuffer);
+ eRet = OMX_ErrorBadParameter;
+ break;
+ }
+ if (m_disable_dynamic_buf_mode) {
+ DEBUG_PRINT_HIGH("Dynamic buffer mode is disabled");
+ eRet = OMX_ErrorUnsupportedSetting;
+ break;
+ }
+ if (metabuffer->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
+
+ if (m_out_mem_ptr) {
+ DEBUG_PRINT_ERROR("Enable/Disable dynamic-buffer-mode is not allowed since Output port is not free !");
+ eRet = OMX_ErrorInvalidState;
+ break;
+ }
+ //set property dynamic buffer mode to driver.
+ struct v4l2_control control;
+ struct v4l2_format fmt;
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE_OUTPUT;
+ if (metabuffer->bStoreMetaData == true) {
+ control.value = V4L2_MPEG_VIDC_VIDEO_DYNAMIC;
+ } else {
+ control.value = V4L2_MPEG_VIDC_VIDEO_STATIC;
+ }
+ int rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL,&control);
+ if (!rc) {
+ DEBUG_PRINT_HIGH("%s buffer mode",
+ (metabuffer->bStoreMetaData == true)? "Enabled dynamic" : "Disabled dynamic");
+ dynamic_buf_mode = metabuffer->bStoreMetaData;
+ } else {
+ DEBUG_PRINT_ERROR("Failed to %s buffer mode",
+ (metabuffer->bStoreMetaData == true)? "enable dynamic" : "disable dynamic");
+ eRet = OMX_ErrorUnsupportedSetting;
+ }
+ } else {
+ DEBUG_PRINT_ERROR(
+ "OMX_QcomIndexParamVideoMetaBufferMode not supported for port: %u",
+ (unsigned int)metabuffer->nPortIndex);
+ eRet = OMX_ErrorUnsupportedSetting;
+ }
+ break;
+ }
+ case OMX_QcomIndexParamVideoDownScalar:
+ {
+ VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXDOWNSCALAR);
+ QOMX_INDEXDOWNSCALAR* pParam = (QOMX_INDEXDOWNSCALAR*)paramData;
+ struct v4l2_control control;
+ int rc;
+ DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoDownScalar %d\n", pParam->bEnable);
+
+ if (pParam && pParam->bEnable) {
+ rc = enable_downscalar();
+ if (rc < 0) {
+ DEBUG_PRINT_ERROR("%s: enable_downscalar failed\n", __func__);
+ return OMX_ErrorUnsupportedSetting;
+ }
+ m_force_down_scalar = pParam->bEnable;
+ } else {
+ rc = disable_downscalar();
+ if (rc < 0) {
+ DEBUG_PRINT_ERROR("%s: disable_downscalar failed\n", __func__);
+ return OMX_ErrorUnsupportedSetting;
+ }
+ m_force_down_scalar = pParam->bEnable;
+ }
+ break;
+ }
+#ifdef ADAPTIVE_PLAYBACK_SUPPORTED
+ case OMX_QcomIndexParamVideoAdaptivePlaybackMode:
+ {
+ VALIDATE_OMX_PARAM_DATA(paramData, PrepareForAdaptivePlaybackParams);
+ DEBUG_PRINT_LOW("set_parameter: OMX_GoogleAndroidIndexPrepareForAdaptivePlayback");
+ PrepareForAdaptivePlaybackParams* pParams =
+ (PrepareForAdaptivePlaybackParams *) paramData;
+ if (pParams->nPortIndex == OMX_CORE_OUTPUT_PORT_INDEX) {
+ if (!pParams->bEnable) {
+ return OMX_ErrorNone;
+ }
+ if (pParams->nMaxFrameWidth > maxSmoothStreamingWidth
+ || pParams->nMaxFrameHeight > maxSmoothStreamingHeight) {
+ DEBUG_PRINT_ERROR(
+ "Adaptive playback request exceeds max supported resolution : [%u x %u] vs [%u x %u]",
+ (unsigned int)pParams->nMaxFrameWidth, (unsigned int)pParams->nMaxFrameHeight,
+ (unsigned int)maxSmoothStreamingWidth, (unsigned int)maxSmoothStreamingHeight);
+ eRet = OMX_ErrorBadParameter;
+ } else {
+ eRet = enable_adaptive_playback(pParams->nMaxFrameWidth, pParams->nMaxFrameHeight);
+ }
+ } else {
+ DEBUG_PRINT_ERROR(
+ "Prepare for adaptive playback supported only on output port");
+ eRet = OMX_ErrorBadParameter;
+ }
+ break;
+ }
+
+ case OMX_QTIIndexParamVideoPreferAdaptivePlayback:
+ {
+ VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
+ DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVideoPreferAdaptivePlayback");
+ m_disable_dynamic_buf_mode = ((QOMX_ENABLETYPE *)paramData)->bEnable;
+ if (m_disable_dynamic_buf_mode) {
+ DEBUG_PRINT_HIGH("Prefer Adaptive Playback is set");
+ }
+ break;
+ }
+#endif
+ case OMX_QcomIndexParamVideoCustomBufferSize:
+ {
+ VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_CUSTOM_BUFFERSIZE);
+ DEBUG_PRINT_LOW("set_parameter: OMX_QcomIndexParamVideoCustomBufferSize");
+ QOMX_VIDEO_CUSTOM_BUFFERSIZE* pParam = (QOMX_VIDEO_CUSTOM_BUFFERSIZE*)paramData;
+ if (pParam->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) {
+ struct v4l2_control control;
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_BUFFER_SIZE_LIMIT;
+ control.value = pParam->nBufferSize;
+ if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
+ DEBUG_PRINT_ERROR("Failed to set input buffer size");
+ eRet = OMX_ErrorUnsupportedSetting;
+ } else {
+ eRet = get_buffer_req(&drv_ctx.ip_buf);
+ if (eRet == OMX_ErrorNone) {
+ m_custom_buffersize.input_buffersize = drv_ctx.ip_buf.buffer_size;
+ DEBUG_PRINT_HIGH("Successfully set custom input buffer size = %d",
+ m_custom_buffersize.input_buffersize);
+ } else {
+ DEBUG_PRINT_ERROR("Failed to get buffer requirement");
+ }
+ }
+ } else {
+ DEBUG_PRINT_ERROR("ERROR: Custom buffer size in not supported on output port");
+ eRet = OMX_ErrorBadParameter;
+ }
+ break;
+ }
+ case OMX_QTIIndexParamVQZIPSEIType:
+ {
+ VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE);
+ DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVQZIPSEIType");
+ OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE *pParam =
+ (OMX_QTI_VIDEO_PARAM_VQZIP_SEI_TYPE *)paramData;
+ DEBUG_PRINT_LOW("Enable VQZIP SEI: %d", pParam->bEnable);
+ eRet = enable_extradata(OMX_VQZIPSEI_EXTRADATA, false,
+ ((QOMX_ENABLETYPE *)paramData)->bEnable);
+ if (eRet != OMX_ErrorNone) {
+ DEBUG_PRINT_ERROR("ERROR: Failed to set SEI Extradata");
+ eRet = OMX_ErrorBadParameter;
+ client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
+ } else {
+ eRet = enable_extradata(OMX_QP_EXTRADATA, false,
+ ((QOMX_ENABLETYPE *)paramData)->bEnable);
+ if (eRet != OMX_ErrorNone) {
+ DEBUG_PRINT_ERROR("ERROR: Failed to set QP Extradata");
+ eRet = OMX_ErrorBadParameter;
+ client_extradata = client_extradata & ~OMX_VQZIPSEI_EXTRADATA;
+ client_extradata = client_extradata & ~OMX_QP_EXTRADATA;
+ }
+ }
+ break;
+ }
+
+ case OMX_QTIIndexParamPassInputBufferFd:
+ {
+ VALIDATE_OMX_PARAM_DATA(paramData, QOMX_ENABLETYPE);
+ if (arbitrary_bytes) {
+ DEBUG_PRINT_ERROR("OMX_QTIIndexParamPassInputBufferFd not supported in arbitrary buffer mode");
+ eRet = OMX_ErrorUnsupportedSetting;
+ break;
+ }
+
+ m_input_pass_buffer_fd = ((QOMX_ENABLETYPE *)paramData)->bEnable;
+ if (m_input_pass_buffer_fd)
+ DEBUG_PRINT_LOW("Enable passing input buffer FD");
+ break;
+ }
+ case OMX_QTIIndexParamForceCompressedForDPB:
+ {
+ VALIDATE_OMX_PARAM_DATA(paramData, OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE);
+ DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamForceCompressedForDPB");
+ OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE *pParam =
+ (OMX_QTI_VIDEO_PARAM_FORCE_COMPRESSED_FOR_DPB_TYPE *)paramData;
+ if (m_disable_ubwc_mode) {
+ DEBUG_PRINT_ERROR("OMX_QTIIndexParamForceCompressedForDPB not supported when ubwc disabled");
+ eRet = OMX_ErrorUnsupportedSetting;
+ break;
+ }
+ if (!paramData) {
+ DEBUG_PRINT_ERROR("set_parameter: OMX_QTIIndexParamForceCompressedForDPB paramData NULL");
+ eRet = OMX_ErrorBadParameter;
+ break;
+ }
+
+ m_force_compressed_for_dpb = pParam->bEnable;
+ break;
+ }
+ case OMX_QTIIndexParamForceUnCompressedForOPB:
+ {
+ DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamForceUnCompressedForOPB");
+ OMX_QTI_VIDEO_PARAM_FORCE_UNCOMPRESSED_FOR_OPB_TYPE *pParam =
+ (OMX_QTI_VIDEO_PARAM_FORCE_UNCOMPRESSED_FOR_OPB_TYPE *)paramData;
+ if (!paramData) {
+ DEBUG_PRINT_ERROR("set_parameter: OMX_QTIIndexParamForceUnCompressedForOPB paramData is NULL");
+ eRet = OMX_ErrorBadParameter;
+ break;
+ }
+ m_disable_ubwc_mode = pParam->bEnable;
+ DEBUG_PRINT_LOW("set_parameter: UBWC %s for OPB", pParam->bEnable ? "disabled" : "enabled");
+ break;
+ }
+ case OMX_QTIIndexParamVideoClientExtradata:
+ {
+ VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_CLIENT_EXTRADATATYPE);
+ DEBUG_PRINT_LOW("set_parameter: OMX_QTIIndexParamVideoClientExtradata");
+ QOMX_VIDEO_CLIENT_EXTRADATATYPE *pParam =
+ (QOMX_VIDEO_CLIENT_EXTRADATATYPE *)paramData;
+ OMX_U32 extradata_size = VENUS_EXTRADATA_SIZE(4096, 2160);
+ if (pParam->nExtradataSize < extradata_size ||
+ pParam->nExtradataAllocSize < (extradata_size * MAX_NUM_INPUT_OUTPUT_BUFFERS) ||
+ pParam->nExtradataAllocSize < (pParam->nExtradataSize * MAX_NUM_INPUT_OUTPUT_BUFFERS)) {
+ DEBUG_PRINT_ERROR("set_parameter: Incorrect buffer size for client extradata");
+ eRet = OMX_ErrorBadParameter;
+ break;
+ }
+ if (!m_client_extradata_info.set_extradata_info(dup(pParam->nFd),
+ pParam->nExtradataAllocSize, pParam->nExtradataSize)) {
+ DEBUG_PRINT_ERROR("set_parameter: Setting client extradata failed.");
+ eRet = OMX_ErrorBadParameter;
+ break;
+ }
+ break;
+ }
+
+ default: {
+ DEBUG_PRINT_ERROR("Setparameter: unknown param %d", paramIndex);
+ eRet = OMX_ErrorUnsupportedIndex;
+ }
+ }
+ if (eRet != OMX_ErrorNone)
+ DEBUG_PRINT_ERROR("set_parameter: Error: 0x%x, setting param 0x%x", eRet, paramIndex);
+ return eRet;
+}
+
+/* ======================================================================
+ FUNCTION
+ omx_vdec::GetConfig
+
+ DESCRIPTION
+ OMX Get Config Method implementation.
+
+ PARAMETERS
+ <TBD>.
+
+ RETURN VALUE
+ OMX Error None if successful.
+
+ ========================================================================== */
+OMX_ERRORTYPE omx_vdec::get_config(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_INDEXTYPE configIndex,
+ OMX_INOUT OMX_PTR configData)
+{
+ (void) hComp;
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+
+ if (m_state == OMX_StateInvalid) {
+ DEBUG_PRINT_ERROR("Get Config in Invalid State");
+ return OMX_ErrorInvalidState;
+ }
+
+ switch ((unsigned long)configIndex) {
+ case OMX_QcomIndexConfigInterlaced: {
+ VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_CONFIG_INTERLACETYPE);
+ OMX_QCOM_CONFIG_INTERLACETYPE *configFmt =
+ (OMX_QCOM_CONFIG_INTERLACETYPE *) configData;
+ if (configFmt->nPortIndex == 1) {
+ if (configFmt->nIndex == 0) {
+ configFmt->eInterlaceType = OMX_QCOM_InterlaceFrameProgressive;
+ } else if (configFmt->nIndex == 1) {
+ configFmt->eInterlaceType =
+ OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
+ } else if (configFmt->nIndex == 2) {
+ configFmt->eInterlaceType =
+ OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
+ } else {
+ DEBUG_PRINT_ERROR("get_config: OMX_QcomIndexConfigInterlaced:"
+ " NoMore Interlaced formats");
+ eRet = OMX_ErrorNoMore;
+ }
+
+ } else {
+ DEBUG_PRINT_ERROR("get_config: Bad port index %d queried on only o/p port",
+ (int)configFmt->nPortIndex);
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ break;
+ }
+ case OMX_QcomIndexQueryNumberOfVideoDecInstance: {
+ VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_QUERY_DECODER_INSTANCES);
+ QOMX_VIDEO_QUERY_DECODER_INSTANCES *decoderinstances =
+ (QOMX_VIDEO_QUERY_DECODER_INSTANCES*)configData;
+ decoderinstances->nNumOfInstances = 16;
+ /*TODO: How to handle this case */
+ break;
+ }
+ case OMX_QcomIndexConfigVideoFramePackingArrangement: {
+ if (drv_ctx.decoder_format == VDEC_CODECTYPE_H264) {
+ VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_FRAME_PACK_ARRANGEMENT);
+ OMX_QCOM_FRAME_PACK_ARRANGEMENT *configFmt =
+ (OMX_QCOM_FRAME_PACK_ARRANGEMENT *) configData;
+ memcpy(configFmt, &m_frame_pack_arrangement,
+ sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
+ } else {
+ DEBUG_PRINT_ERROR("get_config: Framepack data not supported for non H264 codecs");
+ }
+ break;
+ }
+ case OMX_IndexConfigCommonOutputCrop: {
+ VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_RECTTYPE);
+ OMX_CONFIG_RECTTYPE *rect = (OMX_CONFIG_RECTTYPE *) configData;
+ memcpy(rect, &rectangle, sizeof(OMX_CONFIG_RECTTYPE));
+ DEBUG_PRINT_HIGH("get_config: crop info: L: %u, T: %u, R: %u, B: %u",
+ rectangle.nLeft, rectangle.nTop,
+ rectangle.nWidth, rectangle.nHeight);
+ break;
+ }
+ case OMX_QcomIndexConfigPerfLevel: {
+ VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL);
+ struct v4l2_control control;
+ OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *perf =
+ (OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *)configData;
+
+ control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL;
+ if (ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control) < 0) {
+ DEBUG_PRINT_ERROR("Failed getting performance level: %d", errno);
+ eRet = OMX_ErrorHardware;
+ }
+
+ if (eRet == OMX_ErrorNone) {
+ switch (control.value) {
+ case V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO:
+ perf->ePerfLevel = OMX_QCOM_PerfLevelTurbo;
+ break;
+ default:
+ DEBUG_PRINT_HIGH("Unknown perf level %d, reporting Nominal instead", control.value);
+ /* Fall through */
+ case V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL:
+ perf->ePerfLevel = OMX_QCOM_PerfLevelNominal;
+ break;
+ }
+ }
+
+ break;
+ }
+ case OMX_QcomIndexConfigH264EntropyCodingCabac: {
+ VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_H264ENTROPYCODINGTYPE);
+ QOMX_VIDEO_H264ENTROPYCODINGTYPE *coding = (QOMX_VIDEO_H264ENTROPYCODINGTYPE *)configData;
+ struct v4l2_control control;
+
+ if (drv_ctx.decoder_format != VDEC_CODECTYPE_H264) {
+ DEBUG_PRINT_ERROR("get_config of OMX_QcomIndexConfigH264EntropyCodingCabac only available for H264");
+ eRet = OMX_ErrorNotImplemented;
+ break;
+ }
+
+ control.id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE;
+ if (!ioctl(drv_ctx.video_driver_fd, VIDIOC_G_CTRL, &control)) {
+ coding->bCabac = (OMX_BOOL)
+ (control.value == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC);
+ /* We can't query driver at the moment for the cabac mode, so
+ * just use 0xff...f as a place holder for future improvement */
+ coding->nCabacInitIdc = ~0;
+ } else {
+ eRet = OMX_ErrorUnsupportedIndex;
+ }
+
+ break;
+ }
+ case OMX_QTIIndexConfigDescribeColorAspects:
+ {
+ VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams);
+ DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData;
+
+ print_debug_color_aspects(&(m_client_color_space.sAspects), "GetConfig Client");
+ print_debug_color_aspects(&(m_internal_color_space.sAspects), "GetConfig Internal");
+
+ if (params->bRequestingDataSpace) {
+ DEBUG_PRINT_ERROR("Does not handle dataspace request");
+ return OMX_ErrorUnsupportedSetting;
+ }
+ if (m_internal_color_space.bDataSpaceChanged == OMX_TRUE) {
+ DEBUG_PRINT_LOW("Updating Client's color aspects with internal");
+ memcpy(&(m_client_color_space.sAspects),
+ &(m_internal_color_space.sAspects), sizeof(ColorAspects));
+ m_internal_color_space.bDataSpaceChanged = OMX_FALSE;
+ }
+ memcpy(&(params->sAspects), &(m_client_color_space.sAspects), sizeof(ColorAspects));
+
+ break;
+ }
+ default: {
+ DEBUG_PRINT_ERROR("get_config: unknown param %d",configIndex);
+ eRet = OMX_ErrorBadParameter;
+ }
+
+ }
+
+ return eRet;
+}
+
+/* ======================================================================
+ FUNCTION
+ omx_vdec::SetConfig
+
+ DESCRIPTION
+ OMX Set Config method implementation
+
+ PARAMETERS
+ <TBD>.
+
+ RETURN VALUE
+ OMX Error None if successful.
+ ========================================================================== */
+OMX_ERRORTYPE omx_vdec::set_config(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_INDEXTYPE configIndex,
+ OMX_IN OMX_PTR configData)
+{
+ (void) hComp;
+ if (m_state == OMX_StateInvalid) {
+ DEBUG_PRINT_ERROR("Get Config in Invalid State");
+ return OMX_ErrorInvalidState;
+ }
+
+ OMX_ERRORTYPE ret = OMX_ErrorNone;
+ OMX_VIDEO_CONFIG_NALSIZE *pNal;
+
+ DEBUG_PRINT_LOW("Set Config Called");
+
+ if (configIndex == OMX_IndexConfigVideoNalSize) {
+ struct v4l2_control temp;
+ temp.id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT;
+
+ VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_NALSIZE);
+ pNal = reinterpret_cast < OMX_VIDEO_CONFIG_NALSIZE * >(configData);
+ switch (pNal->nNaluBytes) {
+ case 0:
+ temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_STARTCODES;
+ break;
+ case 2:
+ temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_TWO_BYTE_LENGTH;
+ break;
+ case 4:
+ temp.value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_FOUR_BYTE_LENGTH;
+ break;
+ default:
+ return OMX_ErrorUnsupportedSetting;
+ }
+
+ if (!arbitrary_bytes) {
+ /* In arbitrary bytes mode, the assembler strips out nal size and replaces
+ * with start code, so only need to notify driver in frame by frame mode */
+ if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &temp)) {
+ DEBUG_PRINT_ERROR("Failed to set V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT");
+ return OMX_ErrorHardware;
+ }
+ }
+
+ nal_length = pNal->nNaluBytes;
+ m_frame_parser.init_nal_length(nal_length);
+
+ DEBUG_PRINT_LOW("OMX_IndexConfigVideoNalSize called with Size %d", nal_length);
+ return ret;
+ } else if ((int)configIndex == (int)OMX_IndexVendorVideoFrameRate) {
+ OMX_VENDOR_VIDEOFRAMERATE *config = (OMX_VENDOR_VIDEOFRAMERATE *) configData;
+ DEBUG_PRINT_HIGH("Index OMX_IndexVendorVideoFrameRate %u", (unsigned int)config->nFps);
+
+ if (config->nPortIndex == OMX_CORE_INPUT_PORT_INDEX) {
+ if (config->bEnabled) {
+ if ((config->nFps >> 16) > 0) {
+ DEBUG_PRINT_HIGH("set_config: frame rate set by omx client : %u",
+ (unsigned int)config->nFps >> 16);
+ Q16ToFraction(config->nFps, drv_ctx.frame_rate.fps_numerator,
+ drv_ctx.frame_rate.fps_denominator);
+
+ if (!drv_ctx.frame_rate.fps_numerator) {
+ DEBUG_PRINT_ERROR("Numerator is zero setting to 30");
+ drv_ctx.frame_rate.fps_numerator = 30;
+ }
+
+ if (drv_ctx.frame_rate.fps_denominator) {
+ drv_ctx.frame_rate.fps_numerator = (int)
+ drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator;
+ }
+
+ drv_ctx.frame_rate.fps_denominator = 1;
+ frm_int = drv_ctx.frame_rate.fps_denominator * 1e6 /
+ drv_ctx.frame_rate.fps_numerator;
+
+ struct v4l2_outputparm oparm;
+ /*XXX: we're providing timing info as seconds per frame rather than frames
+ * per second.*/
+ oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
+ oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
+
+ struct v4l2_streamparm sparm;
+ sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ sparm.parm.output = oparm;
+ if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
+ DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \
+ performance might be affected");
+ ret = OMX_ErrorHardware;
+ }
+ client_set_fps = true;
+ } else {
+ DEBUG_PRINT_ERROR("Frame rate not supported.");
+ ret = OMX_ErrorUnsupportedSetting;
+ }
+ } else {
+ DEBUG_PRINT_HIGH("set_config: Disabled client's frame rate");
+ client_set_fps = false;
+ }
+ } else {
+ DEBUG_PRINT_ERROR(" Set_config: Bad Port idx %d",
+ (int)config->nPortIndex);
+ ret = OMX_ErrorBadPortIndex;
+ }
+
+ return ret;
+ } else if ((int)configIndex == (int)OMX_QcomIndexConfigPerfLevel) {
+ OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *perf =
+ (OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *)configData;
+ struct v4l2_control control;
+
+ DEBUG_PRINT_LOW("Set perf level: %d", perf->ePerfLevel);
+
+ control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL;
+
+ switch (perf->ePerfLevel) {
+ case OMX_QCOM_PerfLevelNominal:
+ control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL;
+ break;
+ case OMX_QCOM_PerfLevelTurbo:
+ control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO;
+ break;
+ default:
+ ret = OMX_ErrorUnsupportedSetting;
+ break;
+ }
+
+ if (ret == OMX_ErrorNone) {
+ ret = (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) ?
+ OMX_ErrorUnsupportedSetting : OMX_ErrorNone;
+ }
+
+ return ret;
+ } else if ((int)configIndex == (int)OMX_QcomIndexConfigPictureTypeDecode) {
+ OMX_QCOM_VIDEO_CONFIG_PICTURE_TYPE_DECODE *config =
+ (OMX_QCOM_VIDEO_CONFIG_PICTURE_TYPE_DECODE *)configData;
+ struct v4l2_control control;
+ DEBUG_PRINT_LOW("Set picture type decode: %d", config->eDecodeType);
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_PICTYPE_DEC_MODE;
+
+ switch (config->eDecodeType) {
+ case OMX_QCOM_PictypeDecode_I:
+ control.value = V4L2_MPEG_VIDC_VIDEO_PICTYPE_DECODE_ON;
+ break;
+ case OMX_QCOM_PictypeDecode_IPB:
+ default:
+ control.value = V4L2_MPEG_VIDC_VIDEO_PICTYPE_DECODE_OFF;
+ break;
+ }
+
+ ret = (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control) < 0) ?
+ OMX_ErrorUnsupportedSetting : OMX_ErrorNone;
+ if (ret)
+ DEBUG_PRINT_ERROR("Failed to set picture type decode");
+
+ return ret;
+ } else if ((int)configIndex == (int)OMX_IndexConfigPriority) {
+ OMX_PARAM_U32TYPE *priority = (OMX_PARAM_U32TYPE *)configData;
+ DEBUG_PRINT_LOW("Set_config: priority %d",priority->nU32);
+
+ struct v4l2_control control;
+
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_PRIORITY;
+ if (priority->nU32 == 0)
+ control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_ENABLE;
+ else
+ control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_DISABLE;
+
+ if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
+ DEBUG_PRINT_ERROR("Failed to set Priority");
+ ret = OMX_ErrorUnsupportedSetting;
+ }
+ return ret;
+ } else if ((int)configIndex == (int)OMX_IndexConfigOperatingRate) {
+ OMX_PARAM_U32TYPE *rate = (OMX_PARAM_U32TYPE *)configData;
+ DEBUG_PRINT_LOW("Set_config: operating-rate %u fps", rate->nU32 >> 16);
+
+ struct v4l2_control control;
+
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE;
+ control.value = rate->nU32;
+
+ operating_frame_rate = rate->nU32 >> 16;
+
+ if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
+ ret = errno == -EBUSY ? OMX_ErrorInsufficientResources :
+ OMX_ErrorUnsupportedSetting;
+ DEBUG_PRINT_ERROR("Failed to set operating rate %u fps (%s)",
+ rate->nU32 >> 16, errno == -EBUSY ? "HW Overload" : strerror(errno));
+ }
+ return ret;
+
+ } else if ((int)configIndex == (int)OMX_QTIIndexConfigDescribeColorAspects) {
+ VALIDATE_OMX_PARAM_DATA(configData, DescribeColorAspectsParams);
+ DescribeColorAspectsParams *params = (DescribeColorAspectsParams *)configData;
+ if (!DEFAULT_EXTRADATA & OMX_DISPLAY_INFO_EXTRADATA) {
+ enable_extradata(OMX_DISPLAY_INFO_EXTRADATA, true, true);
+ }
+
+ print_debug_color_aspects(&(params->sAspects), "Set Config");
+ memcpy(&m_client_color_space, params, sizeof(DescribeColorAspectsParams));
+ return ret;
+ }
+
+ return OMX_ErrorNotImplemented;
+}
+
+#define extn_equals(param, extn) (!strcmp(param, extn))
+
+/* ======================================================================
+ FUNCTION
+ omx_vdec::GetExtensionIndex
+
+ DESCRIPTION
+ OMX GetExtensionIndex method implementaion. <TBD>
+
+ PARAMETERS
+ <TBD>.
+
+ RETURN VALUE
+ OMX Error None if everything successful.
+
+ ========================================================================== */
+OMX_ERRORTYPE omx_vdec::get_extension_index(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_STRING paramName,
+ OMX_OUT OMX_INDEXTYPE* indexType)
+{
+ (void) hComp;
+ if (m_state == OMX_StateInvalid) {
+ DEBUG_PRINT_ERROR("Get Extension Index in Invalid State");
+ return OMX_ErrorInvalidState;
+ } else if (extn_equals(paramName, "OMX.QCOM.index.param.video.SyncFrameDecodingMode")) {
+ *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoSyncFrameDecodingMode;
+ } else if (extn_equals(paramName, "OMX.QCOM.index.param.IndexExtraData")) {
+ *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamIndexExtraDataType;
+ } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_FRAMEPACKING_EXTRADATA)) {
+ *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoFramePackingExtradata;
+ } else if (extn_equals(paramName, OMX_QCOM_INDEX_CONFIG_VIDEO_FRAMEPACKING_INFO)) {
+ *indexType = (OMX_INDEXTYPE)OMX_QcomIndexConfigVideoFramePackingArrangement;
+ } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_QP_EXTRADATA)) {
+ *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoQPExtraData;
+ } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_INPUTBITSINFO_EXTRADATA)) {
+ *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoInputBitsInfoExtraData;
+ } else if (extn_equals(paramName, OMX_QCOM_INDEX_PARAM_VIDEO_EXTNUSER_EXTRADATA)) {
+ *indexType = (OMX_INDEXTYPE)OMX_QcomIndexEnableExtnUserData;
+ }
+#if defined (_ANDROID_HONEYCOMB_) || defined (_ANDROID_ICS_)
+ else if (extn_equals(paramName, "OMX.google.android.index.enableAndroidNativeBuffers")) {
+ *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexEnableAndroidNativeBuffers;
+ } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer2")) {
+ *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer2;
+ } else if (extn_equals(paramName, "OMX.google.android.index.useAndroidNativeBuffer")) {
+ DEBUG_PRINT_ERROR("Extension: %s is supported", paramName);
+ *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexUseAndroidNativeBuffer;
+ } else if (extn_equals(paramName, "OMX.google.android.index.getAndroidNativeBufferUsage")) {
+ *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexGetAndroidNativeBufferUsage;
+ }
+#if ALLOCATE_OUTPUT_NATIVEHANDLE
+ else if (extn_equals(paramName, "OMX.google.android.index.allocateNativeHandle")) {
+ *indexType = (OMX_INDEXTYPE)OMX_GoogleAndroidIndexAllocateNativeHandle;
+ }
+#endif //ALLOCATE_OUTPUT_NATIVEHANDLE
+#endif
+ else if (extn_equals(paramName, "OMX.google.android.index.storeMetaDataInBuffers")) {
+ *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoMetaBufferMode;
+ }
+#ifdef ADAPTIVE_PLAYBACK_SUPPORTED
+ else if (extn_equals(paramName, "OMX.google.android.index.prepareForAdaptivePlayback")) {
+ *indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoAdaptivePlaybackMode;
+ } else if (extn_equals(paramName, OMX_QTI_INDEX_PARAM_VIDEO_PREFER_ADAPTIVE_PLAYBACK)) {
+ *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamVideoPreferAdaptivePlayback;
+ }
+#endif
+#ifdef FLEXYUV_SUPPORTED
+ else if (extn_equals(paramName,"OMX.google.android.index.describeColorFormat")) {
+ *indexType = (OMX_INDEXTYPE)OMX_QcomIndexFlexibleYUVDescription;
+ }
+#endif
+ else if (extn_equals(paramName, "OMX.QCOM.index.param.video.PassInputBufferFd")) {
+ *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamPassInputBufferFd;
+ } else if (extn_equals(paramName, "OMX.QTI.index.param.video.ForceCompressedForDPB")) {
+ *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceCompressedForDPB;
+ } else if (extn_equals(paramName, "OMX.QTI.index.param.video.ForceUnCompressedForOPB")) {
+ *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamForceUnCompressedForOPB;
+ } else if (extn_equals(paramName, "OMX.QTI.index.param.video.LowLatency")) {
+ *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamLowLatencyMode;
+ } else if (extn_equals(paramName, OMX_QTI_INDEX_PARAM_VIDEO_CLIENT_EXTRADATA)) {
+ *indexType = (OMX_INDEXTYPE)OMX_QTIIndexParamVideoClientExtradata;
+ } else if (extn_equals(paramName, "OMX.google.android.index.describeColorAspects")) {
+ *indexType = (OMX_INDEXTYPE)OMX_QTIIndexConfigDescribeColorAspects;
+ } else {
+ DEBUG_PRINT_ERROR("Extension: %s not implemented", paramName);
+ return OMX_ErrorNotImplemented;
+ }
+ return OMX_ErrorNone;
+}
+
+/* ======================================================================
+ FUNCTION
+ omx_vdec::GetState
+
+ DESCRIPTION
+ Returns the state information back to the caller.<TBD>
+
+ PARAMETERS
+ <TBD>.
+
+ RETURN VALUE
+ Error None if everything is successful.
+ ========================================================================== */
+OMX_ERRORTYPE omx_vdec::get_state(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_OUT OMX_STATETYPE* state)
+{
+ (void) hComp;
+ *state = m_state;
+ DEBUG_PRINT_LOW("get_state: Returning the state %d",*state);
+ return OMX_ErrorNone;
+}
+
+/* ======================================================================
+ FUNCTION
+ omx_vdec::ComponentTunnelRequest
+
+ DESCRIPTION
+ OMX Component Tunnel Request method implementation. <TBD>
+
+ PARAMETERS
+ None.
+
+ RETURN VALUE
+ OMX Error None if everything successful.
+
+ ========================================================================== */
+OMX_ERRORTYPE omx_vdec::component_tunnel_request(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_U32 port,
+ OMX_IN OMX_HANDLETYPE peerComponent,
+ OMX_IN OMX_U32 peerPort,
+ OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup)
+{
+ (void) hComp;
+ (void) port;
+ (void) peerComponent;
+ (void) peerPort;
+ (void) tunnelSetup;
+ DEBUG_PRINT_ERROR("Error: component_tunnel_request Not Implemented");
+ return OMX_ErrorNotImplemented;
+}
+
+/* ======================================================================
+ FUNCTION
+ omx_vdec::UseOutputBuffer
+
+ DESCRIPTION
+ Helper function for Use buffer in the input pin
+
+ PARAMETERS
+ None.
+
+ RETURN VALUE
+ true/false
+
+ ========================================================================== */
+OMX_ERRORTYPE omx_vdec::allocate_extradata()
+{
+#ifdef USE_ION
+ 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);
+ }
+ drv_ctx.extradata_info.size = (drv_ctx.extradata_info.size + 4095) & (~4095);
+ drv_ctx.extradata_info.ion.ion_device_fd = alloc_map_ion_memory(
+ drv_ctx.extradata_info.size, 4096,
+ &drv_ctx.extradata_info.ion.ion_alloc_data,
+ &drv_ctx.extradata_info.ion.fd_ion_data, 0);
+ if (drv_ctx.extradata_info.ion.ion_device_fd < 0) {
+ DEBUG_PRINT_ERROR("Failed to alloc extradata memory");
+ return OMX_ErrorInsufficientResources;
+ }
+ drv_ctx.extradata_info.uaddr = (char *)mmap(NULL,
+ drv_ctx.extradata_info.size,
+ PROT_READ|PROT_WRITE, MAP_SHARED,
+ drv_ctx.extradata_info.ion.fd_ion_data.fd , 0);
+ if (drv_ctx.extradata_info.uaddr == MAP_FAILED) {
+ DEBUG_PRINT_ERROR("Failed to map extradata memory");
+ close(drv_ctx.extradata_info.ion.fd_ion_data.fd);
+ free_ion_memory(&drv_ctx.extradata_info.ion);
+ return OMX_ErrorInsufficientResources;
+ }
+ }
+#endif
+ if (!m_other_extradata) {
+ m_other_extradata = (OMX_OTHER_EXTRADATATYPE *)malloc(drv_ctx.extradata_info.buffer_size);
+ if (!m_other_extradata) {
+ DEBUG_PRINT_ERROR("Failed to alloc memory\n");
+ return OMX_ErrorInsufficientResources;
+ }
+ }
+ return OMX_ErrorNone;
+}
+
+void omx_vdec::free_extradata()
+{
+#ifdef USE_ION
+ 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);
+ free_ion_memory(&drv_ctx.extradata_info.ion);
+ }
+ memset(&drv_ctx.extradata_info, 0, sizeof(drv_ctx.extradata_info));
+#endif
+ if (m_other_extradata) {
+ free(m_other_extradata);
+ m_other_extradata = NULL;
+ }
+}
+
+OMX_ERRORTYPE omx_vdec::use_output_buffer(
+ OMX_IN OMX_HANDLETYPE hComp,
+ OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
+ OMX_IN OMX_U32 port,
+ OMX_IN OMX_PTR appData,
+ OMX_IN OMX_U32 bytes,
+ OMX_IN OMX_U8* buffer)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header
+ unsigned i= 0; // Temporary counter
+ struct vdec_setbuffer_cmd setbuffers;
+ OMX_PTR privateAppData = NULL;
+ private_handle_t *handle = NULL;
+ OMX_U8 *buff = buffer;
+ struct v4l2_buffer buf;
+ struct v4l2_plane plane[VIDEO_MAX_PLANES];
+ int extra_idx = 0;
+ (void) hComp;
+ (void) port;
+
+ if (!m_out_mem_ptr) {
+ DEBUG_PRINT_HIGH("Use_op_buf:Allocating output headers");
+ eRet = allocate_output_headers();
+ if (eRet == OMX_ErrorNone)
+ eRet = allocate_extradata();
+ }
+
+ if (eRet == OMX_ErrorNone) {
+ for (i=0; i< drv_ctx.op_buf.actualcount; i++) {
+ if (BITMASK_ABSENT(&m_out_bm_count,i)) {
+ break;
+ }
+ }
+ }
+
+ if (i >= drv_ctx.op_buf.actualcount) {
+ DEBUG_PRINT_ERROR("Already using %d o/p buffers", drv_ctx.op_buf.actualcount);
+ eRet = OMX_ErrorInsufficientResources;
+ }
+
+ if (eRet != OMX_ErrorNone)
+ return eRet;
+
+ if (dynamic_buf_mode) {
+ *bufferHdr = (m_out_mem_ptr + i );
+ (*bufferHdr)->pBuffer = NULL;
+ if (i == (drv_ctx.op_buf.actualcount - 1) && !streaming[CAPTURE_PORT]) {
+ enum v4l2_buf_type buf_type;
+ int rr = 0;
+ buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ if (rr = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON, &buf_type)) {
+ DEBUG_PRINT_ERROR("STREAMON FAILED : %d", rr);
+ return OMX_ErrorInsufficientResources;
+ } else {
+ streaming[CAPTURE_PORT] = true;
+ DEBUG_PRINT_LOW("STREAMON Successful");
+ }
+
+ DEBUG_PRINT_HIGH("Enabling Turbo mode");
+ request_perf_level(VIDC_TURBO);
+ }
+ BITMASK_SET(&m_out_bm_count,i);
+ (*bufferHdr)->pAppPrivate = appData;
+ (*bufferHdr)->pBuffer = buffer;
+ (*bufferHdr)->nAllocLen = sizeof(struct VideoDecoderOutputMetaData);
+ return eRet;
+ }
+
+ if (eRet == OMX_ErrorNone) {
+#if defined(_ANDROID_HONEYCOMB_) || defined(_ANDROID_ICS_)
+ if (m_enable_android_native_buffers) {
+ if (m_use_android_native_buffers) {
+ UseAndroidNativeBufferParams *params = (UseAndroidNativeBufferParams *)appData;
+ sp<android_native_buffer_t> nBuf = params->nativeBuffer;
+ handle = (private_handle_t *)nBuf->handle;
+ privateAppData = params->pAppPrivate;
+ } else {
+ handle = (private_handle_t *)buff;
+ privateAppData = appData;
+ }
+ if (!handle) {
+ DEBUG_PRINT_ERROR("handle is invalid");
+ return OMX_ErrorBadParameter;
+ }
+
+ if ((OMX_U32)handle->size < drv_ctx.op_buf.buffer_size) {
+ if (secure_mode && secure_scaling_to_non_secure_opb) {
+ DEBUG_PRINT_HIGH("Buffer size expected %u, got %u, but it's ok since we will never map it",
+ (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size);
+ } else {
+ DEBUG_PRINT_ERROR("Insufficient sized buffer given for playback,"
+ " expected %u, got %u",
+ (unsigned int)drv_ctx.op_buf.buffer_size, (unsigned int)handle->size);
+ return OMX_ErrorBadParameter;
+ }
+ }
+
+ drv_ctx.op_buf.buffer_size = handle->size;
+
+ if (!m_use_android_native_buffers) {
+ if (!secure_mode) {
+ buff = (OMX_U8*)mmap(0, handle->size,
+ PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
+ if (buff == MAP_FAILED) {
+ DEBUG_PRINT_ERROR("Failed to mmap pmem with fd = %d, size = %d", handle->fd, handle->size);
+ return OMX_ErrorInsufficientResources;
+ }
+ }
+ }
+#if defined(_ANDROID_ICS_)
+ native_buffer[i].nativehandle = handle;
+ native_buffer[i].privatehandle = handle;
+#endif
+ if (!handle) {
+ DEBUG_PRINT_ERROR("Native Buffer handle is NULL");
+ return OMX_ErrorBadParameter;
+ }
+ drv_ctx.ptr_outputbuffer[i].pmem_fd = handle->fd;
+ drv_ctx.ptr_outputbuffer[i].offset = 0;
+ drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
+ drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
+ drv_ctx.ptr_outputbuffer[i].mmaped_size = handle->size;
+ } else
+#endif
+
+ if (!ouput_egl_buffers && !m_use_output_pmem) {
+#ifdef USE_ION
+ drv_ctx.op_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
+ drv_ctx.op_buf.buffer_size,drv_ctx.op_buf.alignment,
+ &drv_ctx.op_buf_ion_info[i].ion_alloc_data,
+ &drv_ctx.op_buf_ion_info[i].fd_ion_data,
+ secure_mode ? SECURE_FLAGS_OUTPUT_BUFFER : 0);
+ if (drv_ctx.op_buf_ion_info[i].ion_device_fd < 0) {
+ DEBUG_PRINT_ERROR("ION device fd is bad %d", drv_ctx.op_buf_ion_info[i].ion_device_fd);
+ return OMX_ErrorInsufficientResources;
+ }
+ drv_ctx.ptr_outputbuffer[i].pmem_fd = \
+ drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
+#else
+ drv_ctx.ptr_outputbuffer[i].pmem_fd = \
+ open (MEM_DEVICE,O_RDWR);
+
+ if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) {
+ DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd);
+ return OMX_ErrorInsufficientResources;
+ }
+
+ /* FIXME: why is this code even here? We already open MEM_DEVICE a few lines above */
+ if (drv_ctx.ptr_outputbuffer[i].pmem_fd == 0) {
+ drv_ctx.ptr_outputbuffer[i].pmem_fd = \
+ open (MEM_DEVICE,O_RDWR);
+ if (drv_ctx.ptr_outputbuffer[i].pmem_fd < 0) {
+ DEBUG_PRINT_ERROR("ION/pmem buffer fd is bad %d", drv_ctx.ptr_outputbuffer[i].pmem_fd);
+ return OMX_ErrorInsufficientResources;
+ }
+ }
+
+ if (!align_pmem_buffers(drv_ctx.ptr_outputbuffer[i].pmem_fd,
+ drv_ctx.op_buf.buffer_size,
+ drv_ctx.op_buf.alignment)) {
+ DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
+ close(drv_ctx.ptr_outputbuffer[i].pmem_fd);
+ return OMX_ErrorInsufficientResources;
+ }
+#endif
+ if (!secure_mode) {
+ drv_ctx.ptr_outputbuffer[i].bufferaddr =
+ (unsigned char *)mmap(NULL, drv_ctx.op_buf.buffer_size,
+ PROT_READ|PROT_WRITE, MAP_SHARED,
+ drv_ctx.ptr_outputbuffer[i].pmem_fd,0);
+ if (drv_ctx.ptr_outputbuffer[i].bufferaddr == MAP_FAILED) {
+ close(drv_ctx.ptr_outputbuffer[i].pmem_fd);
+#ifdef USE_ION
+ free_ion_memory(&drv_ctx.op_buf_ion_info[i]);
+#endif
+ DEBUG_PRINT_ERROR("Unable to mmap output buffer");
+ return OMX_ErrorInsufficientResources;
+ }
+ }
+ drv_ctx.ptr_outputbuffer[i].offset = 0;
+ privateAppData = appData;
+ } else {
+
+ DEBUG_PRINT_LOW("Use_op_buf: out_pmem=%d",m_use_output_pmem);
+ if (!appData || !bytes ) {
+ if (!secure_mode && !buffer) {
+ DEBUG_PRINT_ERROR("Bad parameters for use buffer in EGL image case");
+ return OMX_ErrorBadParameter;
+ }
+ }
+
+ OMX_QCOM_PLATFORM_PRIVATE_LIST *pmem_list;
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pmem_info;
+ pmem_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST*) appData;
+ if (!pmem_list || !pmem_list->entryList || !pmem_list->entryList->entry ||
+ !pmem_list->nEntries ||
+ pmem_list->entryList->type != OMX_QCOM_PLATFORM_PRIVATE_PMEM) {
+ DEBUG_PRINT_ERROR("Pmem info not valid in use buffer");
+ return OMX_ErrorBadParameter;
+ }
+ pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
+ pmem_list->entryList->entry;
+ DEBUG_PRINT_LOW("vdec: use buf: pmem_fd=0x%lx",
+ pmem_info->pmem_fd);
+ drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_info->pmem_fd;
+ drv_ctx.ptr_outputbuffer[i].offset = pmem_info->offset;
+ drv_ctx.ptr_outputbuffer[i].bufferaddr = buff;
+ drv_ctx.ptr_outputbuffer[i].mmaped_size =
+ drv_ctx.ptr_outputbuffer[i].buffer_len = drv_ctx.op_buf.buffer_size;
+ privateAppData = appData;
+ }
+ m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset;
+ m_pmem_info[i].pmem_fd = drv_ctx.ptr_outputbuffer[i].pmem_fd;
+ m_pmem_info[i].size = drv_ctx.ptr_outputbuffer[i].buffer_len;
+ m_pmem_info[i].mapped_size = drv_ctx.ptr_outputbuffer[i].mmaped_size;
+ m_pmem_info[i].buffer = drv_ctx.ptr_outputbuffer[i].bufferaddr;
+
+ *bufferHdr = (m_out_mem_ptr + i );
+ if (secure_mode)
+ drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr;
+ //setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
+ memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[i],
+ sizeof (vdec_bufferpayload));
+
+ DEBUG_PRINT_HIGH("Set the Output Buffer Idx: %d Addr: %p, pmem_fd=0x%x", i,
+ drv_ctx.ptr_outputbuffer[i].bufferaddr,
+ drv_ctx.ptr_outputbuffer[i].pmem_fd );
+
+ buf.index = i;
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ buf.memory = V4L2_MEMORY_USERPTR;
+ plane[0].length = drv_ctx.op_buf.buffer_size;
+ plane[0].m.userptr = (unsigned long)drv_ctx.ptr_outputbuffer[i].bufferaddr -
+ (unsigned long)drv_ctx.ptr_outputbuffer[i].offset;
+ plane[0].reserved[0] = drv_ctx.ptr_outputbuffer[i].pmem_fd;
+ plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[i].offset;
+ plane[0].data_offset = 0;
+ extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
+ if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
+ plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
+ plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + i * drv_ctx.extradata_info.buffer_size);
+#ifdef USE_ION
+ plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
+#endif
+ plane[extra_idx].reserved[1] = i * drv_ctx.extradata_info.buffer_size;
+ plane[extra_idx].data_offset = 0;
+ } else if (extra_idx >= VIDEO_MAX_PLANES) {
+ DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx);
+ return OMX_ErrorBadParameter;
+ }
+ buf.m.planes = plane;
+ buf.length = drv_ctx.num_planes;
+
+ if (ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf)) {
+ DEBUG_PRINT_ERROR("Failed to prepare bufs");
+ /*TODO: How to handle this case */
+ return OMX_ErrorInsufficientResources;
+ }
+
+ if (i == (drv_ctx.op_buf.actualcount -1) && !streaming[CAPTURE_PORT]) {
+ enum v4l2_buf_type buf_type;
+ buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ if (ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type)) {
+ return OMX_ErrorInsufficientResources;
+ } else {
+ streaming[CAPTURE_PORT] = true;
+ DEBUG_PRINT_LOW("STREAMON Successful");
+ }
+
+ DEBUG_PRINT_HIGH("Enabling Turbo mode");
+ request_perf_level(VIDC_TURBO);
+ }
+
+ (*bufferHdr)->nAllocLen = drv_ctx.op_buf.buffer_size;
+ if (m_enable_android_native_buffers) {
+ DEBUG_PRINT_LOW("setting pBuffer to private_handle_t %p", handle);
+ (*bufferHdr)->pBuffer = (OMX_U8 *)handle;
+ } else {
+ (*bufferHdr)->pBuffer = buff;
+ }
+ (*bufferHdr)->pAppPrivate = privateAppData;
+ BITMASK_SET(&m_out_bm_count,i);
+ }
+ return eRet;
+}
+
+/* ======================================================================
+ FUNCTION
+ omx_vdec::use_input_heap_buffers
+
+ DESCRIPTION
+ OMX Use Buffer Heap allocation method implementation.
+
+ PARAMETERS
+ <TBD>.
+
+ RETURN VALUE
+ OMX Error None , if everything successful.
+
+ ========================================================================== */
+OMX_ERRORTYPE omx_vdec::use_input_heap_buffers(
+ OMX_IN OMX_HANDLETYPE hComp,
+ OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
+ OMX_IN OMX_U32 port,
+ OMX_IN OMX_PTR appData,
+ OMX_IN OMX_U32 bytes,
+ OMX_IN OMX_U8* buffer)
+{
+ DEBUG_PRINT_LOW("Inside %s, %p", __FUNCTION__, buffer);
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+
+ if (secure_mode) {
+ DEBUG_PRINT_ERROR("use_input_heap_buffers is not allowed in secure mode");
+ return OMX_ErrorUndefined;
+ }
+
+ if (!m_inp_heap_ptr)
+ m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*)
+ calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
+ drv_ctx.ip_buf.actualcount);
+ if (!m_phdr_pmem_ptr)
+ m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**)
+ calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
+ drv_ctx.ip_buf.actualcount);
+ if (!m_inp_heap_ptr || !m_phdr_pmem_ptr) {
+ DEBUG_PRINT_ERROR("Insufficent memory");
+ eRet = OMX_ErrorInsufficientResources;
+ } else if (m_in_alloc_cnt < drv_ctx.ip_buf.actualcount) {
+ input_use_buffer = true;
+ memset(&m_inp_heap_ptr[m_in_alloc_cnt], 0, sizeof(OMX_BUFFERHEADERTYPE));
+ m_inp_heap_ptr[m_in_alloc_cnt].pBuffer = buffer;
+ m_inp_heap_ptr[m_in_alloc_cnt].nAllocLen = bytes;
+ m_inp_heap_ptr[m_in_alloc_cnt].pAppPrivate = appData;
+ m_inp_heap_ptr[m_in_alloc_cnt].nInputPortIndex = (OMX_U32) OMX_DirInput;
+ m_inp_heap_ptr[m_in_alloc_cnt].nOutputPortIndex = (OMX_U32) OMX_DirMax;
+ *bufferHdr = &m_inp_heap_ptr[m_in_alloc_cnt];
+ eRet = allocate_input_buffer(hComp, &m_phdr_pmem_ptr[m_in_alloc_cnt], port, appData, bytes);
+ DEBUG_PRINT_HIGH("Heap buffer(%p) Pmem buffer(%p)", *bufferHdr, m_phdr_pmem_ptr[m_in_alloc_cnt]);
+ if (!m_input_free_q.insert_entry((unsigned long)m_phdr_pmem_ptr[m_in_alloc_cnt],
+ (unsigned)NULL, (unsigned)NULL)) {
+ DEBUG_PRINT_ERROR("ERROR:Free_q is full");
+ return OMX_ErrorInsufficientResources;
+ }
+ m_in_alloc_cnt++;
+ } else {
+ DEBUG_PRINT_ERROR("All i/p buffers have been set!");
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ return eRet;
+}
+
+/* ======================================================================
+ FUNCTION
+ omx_vdec::UseBuffer
+
+ DESCRIPTION
+ OMX Use Buffer method implementation.
+
+ PARAMETERS
+ <TBD>.
+
+ RETURN VALUE
+ OMX Error None , if everything successful.
+
+ ========================================================================== */
+OMX_ERRORTYPE omx_vdec::use_buffer(
+ OMX_IN OMX_HANDLETYPE hComp,
+ OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
+ OMX_IN OMX_U32 port,
+ OMX_IN OMX_PTR appData,
+ OMX_IN OMX_U32 bytes,
+ OMX_IN OMX_U8* buffer)
+{
+ OMX_ERRORTYPE error = OMX_ErrorNone;
+ struct vdec_setbuffer_cmd setbuffers;
+
+ if (bufferHdr == NULL || bytes == 0 || (!secure_mode && buffer == NULL)) {
+ DEBUG_PRINT_ERROR("bad param 0x%p %u 0x%p",bufferHdr, (unsigned int)bytes, buffer);
+ return OMX_ErrorBadParameter;
+ }
+ if (m_state == OMX_StateInvalid) {
+ DEBUG_PRINT_ERROR("Use Buffer in Invalid State");
+ return OMX_ErrorInvalidState;
+ }
+ if (port == OMX_CORE_INPUT_PORT_INDEX) {
+ // If this is not the first allocation (i.e m_inp_mem_ptr is allocated),
+ // ensure that use-buffer was called for previous allocation.
+ // Mix-and-match of useBuffer and allocateBuffer is not allowed
+ if (m_inp_mem_ptr && !input_use_buffer) {
+ DEBUG_PRINT_ERROR("'Use' Input buffer called after 'Allocate' Input buffer !");
+ return OMX_ErrorUndefined;
+ }
+ error = use_input_heap_buffers(hComp, bufferHdr, port, appData, bytes, buffer);
+ } else if (port == OMX_CORE_OUTPUT_PORT_INDEX)
+ error = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer); //not tested
+ else {
+ DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port);
+ error = OMX_ErrorBadPortIndex;
+ }
+ DEBUG_PRINT_LOW("Use Buffer: port %u, buffer %p, eRet %d", (unsigned int)port, *bufferHdr, error);
+ if (error == OMX_ErrorNone) {
+ if (allocate_done() && BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
+ // Send the callback now
+ BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
+ post_event(OMX_CommandStateSet,OMX_StateIdle,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+ if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated &&
+ BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
+ BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
+ post_event(OMX_CommandPortEnable,
+ OMX_CORE_INPUT_PORT_INDEX,
+ OMX_COMPONENT_GENERATE_EVENT);
+ } else if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated &&
+ BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
+ BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
+ post_event(OMX_CommandPortEnable,
+ OMX_CORE_OUTPUT_PORT_INDEX,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+ }
+ return error;
+}
+
+OMX_ERRORTYPE omx_vdec::free_input_buffer(unsigned int bufferindex,
+ OMX_BUFFERHEADERTYPE *pmem_bufferHdr)
+{
+ if (m_inp_heap_ptr && !input_use_buffer && arbitrary_bytes) {
+ if (m_inp_heap_ptr[bufferindex].pBuffer)
+ free(m_inp_heap_ptr[bufferindex].pBuffer);
+ m_inp_heap_ptr[bufferindex].pBuffer = NULL;
+ }
+ if (pmem_bufferHdr)
+ free_input_buffer(pmem_bufferHdr);
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE omx_vdec::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
+{
+ unsigned int index = 0;
+ if (bufferHdr == NULL || m_inp_mem_ptr == NULL) {
+ return OMX_ErrorBadParameter;
+ }
+
+ index = bufferHdr - m_inp_mem_ptr;
+ DEBUG_PRINT_LOW("Free Input Buffer index = %d",index);
+
+ auto_lock l(buf_lock);
+ bufferHdr->pInputPortPrivate = NULL;
+
+ if (index < drv_ctx.ip_buf.actualcount && drv_ctx.ptr_inputbuffer) {
+ DEBUG_PRINT_LOW("Free Input Buffer index = %d",index);
+ if (drv_ctx.ptr_inputbuffer[index].pmem_fd >= 0) {
+ struct vdec_setbuffer_cmd setbuffers;
+ setbuffers.buffer_type = VDEC_BUFFER_TYPE_INPUT;
+ memcpy (&setbuffers.buffer,&drv_ctx.ptr_inputbuffer[index],
+ sizeof (vdec_bufferpayload));
+ if (!secure_mode) {
+ DEBUG_PRINT_LOW("unmap the input buffer fd=%d",
+ drv_ctx.ptr_inputbuffer[index].pmem_fd);
+ DEBUG_PRINT_LOW("unmap the input buffer size=%u address = %p",
+ (unsigned int)drv_ctx.ptr_inputbuffer[index].mmaped_size,
+ drv_ctx.ptr_inputbuffer[index].bufferaddr);
+ munmap (drv_ctx.ptr_inputbuffer[index].bufferaddr,
+ drv_ctx.ptr_inputbuffer[index].mmaped_size);
+ }
+
+ if (allocate_native_handle){
+ native_handle_t *nh = (native_handle_t *)bufferHdr->pBuffer;
+ native_handle_close(nh);
+ native_handle_delete(nh);
+ } else {
+ // Close fd for non-secure and secure non-native-handle case
+ close(drv_ctx.ptr_inputbuffer[index].pmem_fd);
+ }
+ drv_ctx.ptr_inputbuffer[index].pmem_fd = -1;
+
+ if (m_desc_buffer_ptr && m_desc_buffer_ptr[index].buf_addr) {
+ free(m_desc_buffer_ptr[index].buf_addr);
+ m_desc_buffer_ptr[index].buf_addr = NULL;
+ m_desc_buffer_ptr[index].desc_data_size = 0;
+ }
+#ifdef USE_ION
+ free_ion_memory(&drv_ctx.ip_buf_ion_info[index]);
+#endif
+ }
+ }
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE omx_vdec::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
+{
+ unsigned int index = 0;
+
+ if (bufferHdr == NULL || m_out_mem_ptr == NULL) {
+ return OMX_ErrorBadParameter;
+ }
+
+ index = bufferHdr - m_out_mem_ptr;
+ DEBUG_PRINT_LOW("Free ouput Buffer index = %d",index);
+
+ if (index < drv_ctx.op_buf.actualcount
+ && drv_ctx.ptr_outputbuffer) {
+ DEBUG_PRINT_LOW("Free ouput Buffer index = %d addr = %p", index,
+ drv_ctx.ptr_outputbuffer[index].bufferaddr);
+
+ struct vdec_setbuffer_cmd setbuffers;
+ setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT;
+ memcpy (&setbuffers.buffer,&drv_ctx.ptr_outputbuffer[index],
+ sizeof (vdec_bufferpayload));
+
+ if (!dynamic_buf_mode) {
+ if (streaming[CAPTURE_PORT] &&
+ !(in_reconfig || BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING))) {
+ if (stream_off(OMX_CORE_OUTPUT_PORT_INDEX)) {
+ DEBUG_PRINT_ERROR("STREAMOFF Failed");
+ } else {
+ DEBUG_PRINT_LOW("STREAMOFF Successful");
+ }
+ }
+#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 (!secure_mode) {
+ DEBUG_PRINT_LOW("unmap the output buffer fd = %d",
+ drv_ctx.ptr_outputbuffer[0].pmem_fd);
+ DEBUG_PRINT_LOW("unmap the ouput buffer size=%u address = %p",
+ (unsigned int)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]);
+#endif
+ }
+#ifdef _ANDROID_
+ }
+#endif
+ } //!dynamic_buf_mode
+ if (release_output_done()) {
+ free_extradata();
+ }
+ }
+
+ return OMX_ErrorNone;
+
+}
+
+OMX_ERRORTYPE omx_vdec::allocate_input_heap_buffer(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE **bufferHdr,
+ OMX_U32 port,
+ OMX_PTR appData,
+ OMX_U32 bytes)
+{
+ OMX_BUFFERHEADERTYPE *input = NULL;
+ unsigned char *buf_addr = NULL;
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ unsigned i = 0;
+
+ /* Sanity Check*/
+ if (bufferHdr == NULL) {
+ return OMX_ErrorBadParameter;
+ }
+
+ if (m_inp_heap_ptr == NULL) {
+ m_inp_heap_ptr = (OMX_BUFFERHEADERTYPE*) \
+ calloc( (sizeof(OMX_BUFFERHEADERTYPE)),
+ drv_ctx.ip_buf.actualcount);
+ m_phdr_pmem_ptr = (OMX_BUFFERHEADERTYPE**) \
+ calloc( (sizeof(OMX_BUFFERHEADERTYPE*)),
+ drv_ctx.ip_buf.actualcount);
+
+ if (m_inp_heap_ptr == NULL || m_phdr_pmem_ptr == NULL) {
+ DEBUG_PRINT_ERROR("m_inp_heap_ptr or m_phdr_pmem_ptr Allocation failed ");
+ return OMX_ErrorInsufficientResources;
+ }
+ }
+
+ /*Find a Free index*/
+ for (i=0; i< drv_ctx.ip_buf.actualcount; i++) {
+ if (BITMASK_ABSENT(&m_heap_inp_bm_count,i)) {
+ DEBUG_PRINT_LOW("Free Input Buffer Index %d",i);
+ break;
+ }
+ }
+
+ if (i < drv_ctx.ip_buf.actualcount) {
+ buf_addr = (unsigned char *)malloc (drv_ctx.ip_buf.buffer_size);
+
+ if (buf_addr == NULL) {
+ return OMX_ErrorInsufficientResources;
+ }
+
+ *bufferHdr = (m_inp_heap_ptr + i);
+ input = *bufferHdr;
+ BITMASK_SET(&m_heap_inp_bm_count,i);
+
+ input->pBuffer = (OMX_U8 *)buf_addr;
+ input->nSize = sizeof(OMX_BUFFERHEADERTYPE);
+ input->nVersion.nVersion = OMX_SPEC_VERSION;
+ input->nAllocLen = drv_ctx.ip_buf.buffer_size;
+ input->pAppPrivate = appData;
+ input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX;
+ DEBUG_PRINT_LOW("Address of Heap Buffer %p",*bufferHdr );
+ eRet = allocate_input_buffer(hComp,&m_phdr_pmem_ptr [i],port,appData,bytes);
+ DEBUG_PRINT_LOW("Address of Pmem Buffer %p",m_phdr_pmem_ptr[i]);
+ /*Add the Buffers to freeq*/
+ if (!m_input_free_q.insert_entry((unsigned long)m_phdr_pmem_ptr[i],
+ (unsigned)NULL, (unsigned)NULL)) {
+ DEBUG_PRINT_ERROR("ERROR:Free_q is full");
+ return OMX_ErrorInsufficientResources;
+ }
+ } else {
+ return OMX_ErrorBadParameter;
+ }
+
+ return eRet;
+
+}
+
+
+/* ======================================================================
+ FUNCTION
+ omx_vdec::AllocateInputBuffer
+
+ DESCRIPTION
+ Helper function for allocate buffer in the input pin
+
+ PARAMETERS
+ None.
+
+ RETURN VALUE
+ true/false
+
+ ========================================================================== */
+OMX_ERRORTYPE omx_vdec::allocate_input_buffer(
+ OMX_IN OMX_HANDLETYPE hComp,
+ OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
+ OMX_IN OMX_U32 port,
+ OMX_IN OMX_PTR appData,
+ OMX_IN OMX_U32 bytes)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ struct vdec_setbuffer_cmd setbuffers;
+ OMX_BUFFERHEADERTYPE *input = NULL;
+ unsigned i = 0;
+ unsigned char *buf_addr = NULL;
+ int pmem_fd = -1;
+
+ (void) hComp;
+ (void) port;
+
+
+ if (bytes != drv_ctx.ip_buf.buffer_size) {
+ DEBUG_PRINT_LOW("Requested Size is wrong %u epected is %u",
+ (unsigned int)bytes, (unsigned int)drv_ctx.ip_buf.buffer_size);
+ return OMX_ErrorBadParameter;
+ }
+
+ if (!m_inp_mem_ptr) {
+ DEBUG_PRINT_HIGH("Allocate i/p buffer Header: Cnt(%d) Sz(%u)",
+ drv_ctx.ip_buf.actualcount,
+ (unsigned int)drv_ctx.ip_buf.buffer_size);
+
+ m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \
+ calloc( (sizeof(OMX_BUFFERHEADERTYPE)), drv_ctx.ip_buf.actualcount);
+
+ if (m_inp_mem_ptr == NULL) {
+ return OMX_ErrorInsufficientResources;
+ }
+
+ drv_ctx.ptr_inputbuffer = (struct vdec_bufferpayload *) \
+ calloc ((sizeof (struct vdec_bufferpayload)),drv_ctx.ip_buf.actualcount);
+
+ if (drv_ctx.ptr_inputbuffer == NULL) {
+ return OMX_ErrorInsufficientResources;
+ }
+#ifdef USE_ION
+ drv_ctx.ip_buf_ion_info = (struct vdec_ion *) \
+ calloc ((sizeof (struct vdec_ion)),drv_ctx.ip_buf.actualcount);
+
+ if (drv_ctx.ip_buf_ion_info == NULL) {
+ return OMX_ErrorInsufficientResources;
+ }
+#endif
+
+ for (i=0; i < drv_ctx.ip_buf.actualcount; i++) {
+ drv_ctx.ptr_inputbuffer [i].pmem_fd = -1;
+#ifdef USE_ION
+ drv_ctx.ip_buf_ion_info[i].ion_device_fd = -1;
+#endif
+ }
+ }
+
+ for (i=0; i< drv_ctx.ip_buf.actualcount; i++) {
+ if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
+ DEBUG_PRINT_LOW("Free Input Buffer Index %d",i);
+ break;
+ }
+ }
+
+ if (i < drv_ctx.ip_buf.actualcount) {
+ struct v4l2_buffer buf;
+ struct v4l2_plane plane;
+ int rc;
+ DEBUG_PRINT_LOW("Allocate input Buffer");
+#ifdef USE_ION
+ drv_ctx.ip_buf_ion_info[i].ion_device_fd = alloc_map_ion_memory(
+ drv_ctx.ip_buf.buffer_size,drv_ctx.op_buf.alignment,
+ &drv_ctx.ip_buf_ion_info[i].ion_alloc_data,
+ &drv_ctx.ip_buf_ion_info[i].fd_ion_data, secure_mode ?
+ SECURE_FLAGS_INPUT_BUFFER : ION_FLAG_CACHED);
+ if (drv_ctx.ip_buf_ion_info[i].ion_device_fd < 0) {
+ return OMX_ErrorInsufficientResources;
+ }
+ pmem_fd = drv_ctx.ip_buf_ion_info[i].fd_ion_data.fd;
+#else
+ pmem_fd = open (MEM_DEVICE,O_RDWR);
+
+ if (pmem_fd < 0) {
+ DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer");
+ return OMX_ErrorInsufficientResources;
+ }
+
+ if (pmem_fd == 0) {
+ pmem_fd = open (MEM_DEVICE,O_RDWR);
+
+ if (pmem_fd < 0) {
+ DEBUG_PRINT_ERROR("open failed for pmem/adsp for input buffer");
+ return OMX_ErrorInsufficientResources;
+ }
+ }
+
+ if (!align_pmem_buffers(pmem_fd, drv_ctx.ip_buf.buffer_size,
+ drv_ctx.ip_buf.alignment)) {
+ DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
+ close(pmem_fd);
+ return OMX_ErrorInsufficientResources;
+ }
+#endif
+ if (!secure_mode) {
+ buf_addr = (unsigned char *)mmap(NULL,
+ drv_ctx.ip_buf.buffer_size,
+ PROT_READ|PROT_WRITE, MAP_SHARED, pmem_fd, 0);
+
+ if (buf_addr == MAP_FAILED) {
+ close(pmem_fd);
+#ifdef USE_ION
+ free_ion_memory(&drv_ctx.ip_buf_ion_info[i]);
+#endif
+ DEBUG_PRINT_ERROR("Map Failed to allocate input buffer");
+ return OMX_ErrorInsufficientResources;
+ }
+ }
+ *bufferHdr = (m_inp_mem_ptr + i);
+ if (secure_mode)
+ drv_ctx.ptr_inputbuffer [i].bufferaddr = *bufferHdr;
+ else
+ drv_ctx.ptr_inputbuffer [i].bufferaddr = buf_addr;
+ drv_ctx.ptr_inputbuffer [i].pmem_fd = pmem_fd;
+ drv_ctx.ptr_inputbuffer [i].buffer_len = drv_ctx.ip_buf.buffer_size;
+ drv_ctx.ptr_inputbuffer [i].mmaped_size = drv_ctx.ip_buf.buffer_size;
+ drv_ctx.ptr_inputbuffer [i].offset = 0;
+
+
+ buf.index = i;
+ buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ buf.memory = V4L2_MEMORY_USERPTR;
+ plane.bytesused = 0;
+ plane.length = drv_ctx.ptr_inputbuffer [i].mmaped_size;
+ plane.m.userptr = (unsigned long)drv_ctx.ptr_inputbuffer[i].bufferaddr;
+ plane.reserved[0] =drv_ctx.ptr_inputbuffer [i].pmem_fd;
+ plane.reserved[1] = 0;
+ plane.data_offset = drv_ctx.ptr_inputbuffer[i].offset;
+ buf.m.planes = &plane;
+ buf.length = 1;
+
+ DEBUG_PRINT_LOW("Set the input Buffer Idx: %d Addr: %p", i,
+ drv_ctx.ptr_inputbuffer[i].bufferaddr);
+
+ rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf);
+
+ if (rc) {
+ DEBUG_PRINT_ERROR("Failed to prepare bufs");
+ /*TODO: How to handle this case */
+ return OMX_ErrorInsufficientResources;
+ }
+
+ input = *bufferHdr;
+ BITMASK_SET(&m_inp_bm_count,i);
+ DEBUG_PRINT_LOW("Buffer address %p of pmem",*bufferHdr);
+ if (allocate_native_handle) {
+ native_handle_t *nh = native_handle_create(1 /*numFds*/, 0 /*numInts*/);
+ if (!nh) {
+ DEBUG_PRINT_ERROR("Native handle create failed");
+ return OMX_ErrorInsufficientResources;
+ }
+ nh->data[0] = drv_ctx.ptr_inputbuffer[i].pmem_fd;
+ input->pBuffer = (OMX_U8 *)nh;
+ } else if (secure_mode || m_input_pass_buffer_fd) {
+ /*Legacy method, pass ion fd stashed directly in pBuffer*/
+ input->pBuffer = (OMX_U8 *)(intptr_t)drv_ctx.ptr_inputbuffer[i].pmem_fd;
+ } else {
+ input->pBuffer = (OMX_U8 *)buf_addr;
+ }
+ input->nSize = sizeof(OMX_BUFFERHEADERTYPE);
+ input->nVersion.nVersion = OMX_SPEC_VERSION;
+ input->nAllocLen = drv_ctx.ip_buf.buffer_size;
+ input->pAppPrivate = appData;
+ input->nInputPortIndex = OMX_CORE_INPUT_PORT_INDEX;
+ input->pInputPortPrivate = (void *)&drv_ctx.ptr_inputbuffer [i];
+
+ if (drv_ctx.disable_dmx) {
+ eRet = allocate_desc_buffer(i);
+ }
+ } else {
+ DEBUG_PRINT_ERROR("ERROR:Input Buffer Index not found");
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ return eRet;
+}
+
+
+/* ======================================================================
+ FUNCTION
+ omx_vdec::AllocateOutputBuffer
+
+ DESCRIPTION
+ Helper fn for AllocateBuffer in the output pin
+
+ PARAMETERS
+ <TBD>.
+
+ RETURN VALUE
+ OMX Error None if everything went well.
+
+ ========================================================================== */
+OMX_ERRORTYPE omx_vdec::allocate_output_buffer(
+ OMX_IN OMX_HANDLETYPE hComp,
+ OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
+ OMX_IN OMX_U32 port,
+ OMX_IN OMX_PTR appData,
+ OMX_IN OMX_U32 bytes)
+{
+ (void)hComp;
+ (void)port;
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header
+ unsigned i= 0; // Temporary counter
+ struct vdec_setbuffer_cmd setbuffers;
+ int extra_idx = 0;
+#ifdef USE_ION
+ int ion_device_fd =-1;
+ struct ion_allocation_data ion_alloc_data;
+ struct ion_fd_data fd_ion_data;
+#endif
+ if (!m_out_mem_ptr) {
+ DEBUG_PRINT_HIGH("Allocate o/p buffer Header: Cnt(%d) Sz(%u)",
+ drv_ctx.op_buf.actualcount,
+ (unsigned int)drv_ctx.op_buf.buffer_size);
+ int nBufHdrSize = 0;
+ int nPlatformEntrySize = 0;
+ int nPlatformListSize = 0;
+ int nPMEMInfoSize = 0;
+ int pmem_fd = -1;
+ unsigned char *pmem_baseaddress = NULL;
+
+ OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList;
+ OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry;
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
+
+ DEBUG_PRINT_LOW("Allocating First Output Buffer(%d)",
+ drv_ctx.op_buf.actualcount);
+ nBufHdrSize = drv_ctx.op_buf.actualcount *
+ sizeof(OMX_BUFFERHEADERTYPE);
+
+ nPMEMInfoSize = drv_ctx.op_buf.actualcount *
+ sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
+ nPlatformListSize = drv_ctx.op_buf.actualcount *
+ sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
+ nPlatformEntrySize = drv_ctx.op_buf.actualcount *
+ sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
+
+ DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %u PMEM %d PL %d",nBufHdrSize,
+ (unsigned int)sizeof(OMX_BUFFERHEADERTYPE),
+ nPMEMInfoSize,
+ nPlatformListSize);
+ DEBUG_PRINT_LOW("PE %d OutputBuffer Count %d",nPlatformEntrySize,
+ drv_ctx.op_buf.actualcount);
+#ifdef USE_ION
+ // Allocate output buffers as cached to improve performance of software-reading
+ // of the YUVs. Output buffers are cache-invalidated in driver.
+ // If color-conversion is involved, Only the C2D output buffers are cached, no
+ // need to cache the decoder's output buffers
+ int cache_flag = client_buffers.is_color_conversion_enabled() ? 0 : ION_FLAG_CACHED;
+ ion_device_fd = alloc_map_ion_memory(
+ drv_ctx.op_buf.buffer_size * drv_ctx.op_buf.actualcount,
+ secure_scaling_to_non_secure_opb ? SZ_4K : drv_ctx.op_buf.alignment,
+ &ion_alloc_data, &fd_ion_data,
+ (secure_mode && !secure_scaling_to_non_secure_opb) ?
+ SECURE_FLAGS_OUTPUT_BUFFER : cache_flag);
+ if (ion_device_fd < 0) {
+ return OMX_ErrorInsufficientResources;
+ }
+ pmem_fd = fd_ion_data.fd;
+#else
+ pmem_fd = open (MEM_DEVICE,O_RDWR);
+
+ if (pmem_fd < 0) {
+ DEBUG_PRINT_ERROR("ERROR:pmem fd for output buffer %d",
+ drv_ctx.op_buf.buffer_size);
+ return OMX_ErrorInsufficientResources;
+ }
+
+ if (!align_pmem_buffers(pmem_fd, drv_ctx.op_buf.buffer_size *
+ drv_ctx.op_buf.actualcount,
+ drv_ctx.op_buf.alignment)) {
+ DEBUG_PRINT_ERROR("align_pmem_buffers() failed");
+ close(pmem_fd);
+ return OMX_ErrorInsufficientResources;
+ }
+#endif
+ if (!secure_mode) {
+ pmem_baseaddress = (unsigned char *)mmap(NULL,
+ (drv_ctx.op_buf.buffer_size *
+ drv_ctx.op_buf.actualcount),
+ PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd,0);
+ if (pmem_baseaddress == MAP_FAILED) {
+ DEBUG_PRINT_ERROR("MMAP failed for Size %u",
+ (unsigned int)drv_ctx.op_buf.buffer_size);
+ close(pmem_fd);
+#ifdef USE_ION
+ free_ion_memory(&drv_ctx.op_buf_ion_info[i]);
+#endif
+ return OMX_ErrorInsufficientResources;
+ }
+ }
+ m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1);
+ // Alloc mem for platform specific info
+ char *pPtr=NULL;
+ pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
+ nPMEMInfoSize,1);
+ drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *)\
+ calloc (sizeof(struct vdec_bufferpayload),
+ drv_ctx.op_buf.actualcount);
+ drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo *)\
+ calloc (sizeof (struct vdec_output_frameinfo),
+ drv_ctx.op_buf.actualcount);
+ if (!drv_ctx.ptr_outputbuffer || !drv_ctx.ptr_respbuffer) {
+ DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.ptr_outputbuffer or drv_ctx.ptr_respbuffer ");
+ return OMX_ErrorInsufficientResources;
+ }
+
+#ifdef USE_ION
+ drv_ctx.op_buf_ion_info = (struct vdec_ion *)\
+ calloc (sizeof(struct vdec_ion),
+ drv_ctx.op_buf.actualcount);
+ if (!drv_ctx.op_buf_ion_info) {
+ DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_ion_info");
+ return OMX_ErrorInsufficientResources;
+ }
+#endif
+
+ if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer
+ && drv_ctx.ptr_respbuffer) {
+ drv_ctx.ptr_outputbuffer[0].mmaped_size =
+ (drv_ctx.op_buf.buffer_size *
+ drv_ctx.op_buf.actualcount);
+ bufHdr = m_out_mem_ptr;
+ m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
+ m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
+ (((char *) m_platform_list) + nPlatformListSize);
+ m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
+ (((char *) m_platform_entry) + nPlatformEntrySize);
+ pPlatformList = m_platform_list;
+ pPlatformEntry = m_platform_entry;
+ pPMEMInfo = m_pmem_info;
+
+ DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr);
+
+ // Settting the entire storage nicely
+ DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr, m_out_mem_ptr,pPlatformEntry);
+ DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo);
+ for (i=0; i < drv_ctx.op_buf.actualcount ; i++) {
+ bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
+ bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
+ // Set the values when we determine the right HxW param
+ bufHdr->nAllocLen = bytes;
+ bufHdr->nFilledLen = 0;
+ bufHdr->pAppPrivate = appData;
+ bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
+ // Platform specific PMEM Information
+ // Initialize the Platform Entry
+ //DEBUG_PRINT_LOW("Initializing the Platform Entry for %d",i);
+ pPlatformEntry->type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
+ pPlatformEntry->entry = pPMEMInfo;
+ // Initialize the Platform List
+ pPlatformList->nEntries = 1;
+ pPlatformList->entryList = pPlatformEntry;
+ // Keep pBuffer NULL till vdec is opened
+ bufHdr->pBuffer = NULL;
+ bufHdr->nOffset = 0;
+
+ pPMEMInfo->offset = drv_ctx.op_buf.buffer_size*i;
+ pPMEMInfo->pmem_fd = -1;
+ bufHdr->pPlatformPrivate = pPlatformList;
+
+ drv_ctx.ptr_outputbuffer[i].pmem_fd = pmem_fd;
+ m_pmem_info[i].pmem_fd = pmem_fd;
+#ifdef USE_ION
+ drv_ctx.op_buf_ion_info[i].ion_device_fd = ion_device_fd;
+ drv_ctx.op_buf_ion_info[i].ion_alloc_data = ion_alloc_data;
+ drv_ctx.op_buf_ion_info[i].fd_ion_data = fd_ion_data;
+#endif
+
+ /*Create a mapping between buffers*/
+ bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i];
+ drv_ctx.ptr_respbuffer[i].client_data = (void *)\
+ &drv_ctx.ptr_outputbuffer[i];
+ drv_ctx.ptr_outputbuffer[i].offset = drv_ctx.op_buf.buffer_size*i;
+ drv_ctx.ptr_outputbuffer[i].bufferaddr =
+ pmem_baseaddress + (drv_ctx.op_buf.buffer_size*i);
+ m_pmem_info[i].size = drv_ctx.ptr_outputbuffer[i].buffer_len;
+ m_pmem_info[i].mapped_size = drv_ctx.ptr_outputbuffer[i].mmaped_size;
+ m_pmem_info[i].buffer = drv_ctx.ptr_outputbuffer[i].bufferaddr;
+
+ DEBUG_PRINT_LOW("pmem_fd = %d offset = %u address = %p",
+ pmem_fd, (unsigned int)drv_ctx.ptr_outputbuffer[i].offset,
+ drv_ctx.ptr_outputbuffer[i].bufferaddr);
+ // Move the buffer and buffer header pointers
+ bufHdr++;
+ pPMEMInfo++;
+ pPlatformEntry++;
+ pPlatformList++;
+ }
+ } else {
+ DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\
+ m_out_mem_ptr, pPtr);
+ if (m_out_mem_ptr) {
+ free(m_out_mem_ptr);
+ m_out_mem_ptr = NULL;
+ }
+ if (pPtr) {
+ free(pPtr);
+ pPtr = NULL;
+ }
+ if (drv_ctx.ptr_outputbuffer) {
+ free(drv_ctx.ptr_outputbuffer);
+ drv_ctx.ptr_outputbuffer = NULL;
+ }
+ if (drv_ctx.ptr_respbuffer) {
+ free(drv_ctx.ptr_respbuffer);
+ drv_ctx.ptr_respbuffer = NULL;
+ }
+#ifdef USE_ION
+ if (drv_ctx.op_buf_ion_info) {
+ DEBUG_PRINT_LOW("Free o/p ion context");
+ free(drv_ctx.op_buf_ion_info);
+ drv_ctx.op_buf_ion_info = NULL;
+ }
+#endif
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ if (eRet == OMX_ErrorNone)
+ eRet = allocate_extradata();
+ }
+
+ for (i=0; i< drv_ctx.op_buf.actualcount; i++) {
+ if (BITMASK_ABSENT(&m_out_bm_count,i)) {
+ DEBUG_PRINT_LOW("Found a Free Output Buffer %d",i);
+ break;
+ }
+ }
+
+ if (eRet == OMX_ErrorNone) {
+ if (i < drv_ctx.op_buf.actualcount) {
+ struct v4l2_buffer buf;
+ struct v4l2_plane plane[VIDEO_MAX_PLANES];
+ int rc;
+ m_pmem_info[i].offset = drv_ctx.ptr_outputbuffer[i].offset;
+
+ drv_ctx.ptr_outputbuffer[i].buffer_len =
+ drv_ctx.op_buf.buffer_size;
+
+ *bufferHdr = (m_out_mem_ptr + i );
+ if (secure_mode) {
+#ifdef USE_ION
+ drv_ctx.ptr_outputbuffer[i].bufferaddr =
+ (OMX_U8 *)(intptr_t)drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
+#else
+ drv_ctx.ptr_outputbuffer[i].bufferaddr = *bufferHdr;
+#endif
+ }
+ drv_ctx.ptr_outputbuffer[i].mmaped_size = drv_ctx.op_buf.buffer_size;
+
+ buf.index = i;
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ buf.memory = V4L2_MEMORY_USERPTR;
+ plane[0].length = drv_ctx.op_buf.buffer_size;
+ plane[0].m.userptr = (unsigned long)drv_ctx.ptr_outputbuffer[i].bufferaddr -
+ (unsigned long)drv_ctx.ptr_outputbuffer[i].offset;
+#ifdef USE_ION
+ plane[0].reserved[0] = drv_ctx.op_buf_ion_info[i].fd_ion_data.fd;
+#endif
+ plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[i].offset;
+ plane[0].data_offset = 0;
+ extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
+ if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
+ plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
+ plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + i * drv_ctx.extradata_info.buffer_size);
+#ifdef USE_ION
+ plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
+#endif
+ plane[extra_idx].reserved[1] = i * drv_ctx.extradata_info.buffer_size;
+ plane[extra_idx].data_offset = 0;
+ } else if (extra_idx >= VIDEO_MAX_PLANES) {
+ DEBUG_PRINT_ERROR("Extradata index higher than allowed: %d", extra_idx);
+ return OMX_ErrorBadParameter;
+ }
+ buf.m.planes = plane;
+ buf.length = drv_ctx.num_planes;
+ DEBUG_PRINT_LOW("Set the Output Buffer Idx: %d Addr: %p", i, drv_ctx.ptr_outputbuffer[i].bufferaddr);
+ rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_PREPARE_BUF, &buf);
+ if (rc) {
+ /*TODO: How to handle this case */
+ return OMX_ErrorInsufficientResources;
+ }
+
+ if (i == (drv_ctx.op_buf.actualcount -1 ) && !streaming[CAPTURE_PORT]) {
+ enum v4l2_buf_type buf_type;
+ buf_type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ rc=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
+ if (rc) {
+ return OMX_ErrorInsufficientResources;
+ } else {
+ streaming[CAPTURE_PORT] = true;
+ DEBUG_PRINT_LOW("STREAMON Successful");
+ }
+
+ DEBUG_PRINT_HIGH("Enabling Turbo mode");
+ request_perf_level(VIDC_TURBO);
+ }
+
+ (*bufferHdr)->pBuffer = (OMX_U8*)drv_ctx.ptr_outputbuffer[i].bufferaddr;
+ (*bufferHdr)->pAppPrivate = appData;
+ BITMASK_SET(&m_out_bm_count,i);
+ } else {
+ DEBUG_PRINT_ERROR("All the Output Buffers have been Allocated ; Returning Insufficient");
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ }
+
+ return eRet;
+}
+
+
+// AllocateBuffer -- API Call
+/* ======================================================================
+ FUNCTION
+ omx_vdec::AllocateBuffer
+
+ DESCRIPTION
+ Returns zero if all the buffers released..
+
+ PARAMETERS
+ None.
+
+ RETURN VALUE
+ true/false
+
+ ========================================================================== */
+OMX_ERRORTYPE omx_vdec::allocate_buffer(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
+ OMX_IN OMX_U32 port,
+ OMX_IN OMX_PTR appData,
+ OMX_IN OMX_U32 bytes)
+{
+ unsigned i = 0;
+ OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type
+
+ DEBUG_PRINT_LOW("Allocate buffer on port %d", (int)port);
+ if (m_state == OMX_StateInvalid) {
+ DEBUG_PRINT_ERROR("Allocate Buf in Invalid State");
+ return OMX_ErrorInvalidState;
+ }
+
+ if (port == OMX_CORE_INPUT_PORT_INDEX) {
+ // If this is not the first allocation (i.e m_inp_mem_ptr is allocated),
+ // ensure that use-buffer was never called.
+ // Mix-and-match of useBuffer and allocateBuffer is not allowed
+ if (m_inp_mem_ptr && input_use_buffer) {
+ DEBUG_PRINT_ERROR("'Allocate' Input buffer called after 'Use' Input buffer !");
+ return OMX_ErrorUndefined;
+ }
+ if (arbitrary_bytes) {
+ eRet = allocate_input_heap_buffer (hComp,bufferHdr,port,appData,bytes);
+ } else {
+ eRet = allocate_input_buffer(hComp,bufferHdr,port,appData,bytes);
+ }
+ } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
+ eRet = client_buffers.allocate_buffers_color_convert(hComp,bufferHdr,port,
+ appData,bytes);
+ } else {
+ DEBUG_PRINT_ERROR("Error: Invalid Port Index received %d",(int)port);
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ DEBUG_PRINT_LOW("Checking for Output Allocate buffer Done");
+ if (eRet == OMX_ErrorNone) {
+ if (allocate_done()) {
+ if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING)) {
+ // Send the callback now
+ BITMASK_CLEAR((&m_flags),OMX_COMPONENT_IDLE_PENDING);
+ post_event(OMX_CommandStateSet,OMX_StateIdle,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+ }
+ if (port == OMX_CORE_INPUT_PORT_INDEX && m_inp_bPopulated) {
+ if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
+ BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
+ post_event(OMX_CommandPortEnable,
+ OMX_CORE_INPUT_PORT_INDEX,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+ }
+ if (port == OMX_CORE_OUTPUT_PORT_INDEX && m_out_bPopulated) {
+ if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
+ BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
+ post_event(OMX_CommandPortEnable,
+ OMX_CORE_OUTPUT_PORT_INDEX,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+ }
+ }
+ DEBUG_PRINT_LOW("Allocate Buffer exit with ret Code %d",eRet);
+ return eRet;
+}
+
+// Free Buffer - API call
+/* ======================================================================
+ FUNCTION
+ omx_vdec::FreeBuffer
+
+ DESCRIPTION
+
+ PARAMETERS
+ None.
+
+ RETURN VALUE
+ true/false
+
+ ========================================================================== */
+OMX_ERRORTYPE omx_vdec::free_buffer(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_U32 port,
+ OMX_IN OMX_BUFFERHEADERTYPE* buffer)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ unsigned int nPortIndex;
+ (void) hComp;
+ DEBUG_PRINT_LOW("In for decoder free_buffer");
+
+ if (m_state == OMX_StateIdle &&
+ (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
+ DEBUG_PRINT_LOW(" free buffer while Component in Loading pending");
+ } else if ((m_inp_bEnabled == OMX_FALSE && port == OMX_CORE_INPUT_PORT_INDEX)||
+ (m_out_bEnabled == OMX_FALSE && port == OMX_CORE_OUTPUT_PORT_INDEX)) {
+ DEBUG_PRINT_LOW("Free Buffer while port %u disabled", (unsigned int)port);
+ } else if ((port == OMX_CORE_INPUT_PORT_INDEX &&
+ BITMASK_PRESENT(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING)) ||
+ (port == OMX_CORE_OUTPUT_PORT_INDEX &&
+ BITMASK_PRESENT(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING))) {
+ DEBUG_PRINT_LOW("Free Buffer while port %u enable pending", (unsigned int)port);
+ } else if (m_state == OMX_StateExecuting || m_state == OMX_StatePause) {
+ DEBUG_PRINT_ERROR("Invalid state to free buffer,ports need to be disabled");
+ post_event(OMX_EventError,
+ OMX_ErrorPortUnpopulated,
+ OMX_COMPONENT_GENERATE_EVENT);
+
+ return OMX_ErrorIncorrectStateOperation;
+ } else if (m_state != OMX_StateInvalid) {
+ DEBUG_PRINT_ERROR("Invalid state to free buffer,port lost Buffers");
+ post_event(OMX_EventError,
+ OMX_ErrorPortUnpopulated,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+
+ if (port == OMX_CORE_INPUT_PORT_INDEX) {
+ /*Check if arbitrary bytes*/
+ if (!arbitrary_bytes && !input_use_buffer)
+ nPortIndex = buffer - m_inp_mem_ptr;
+ else
+ nPortIndex = buffer - m_inp_heap_ptr;
+
+ DEBUG_PRINT_LOW("free_buffer on i/p port - Port idx %d", nPortIndex);
+ if (nPortIndex < drv_ctx.ip_buf.actualcount &&
+ BITMASK_PRESENT(&m_inp_bm_count, nPortIndex)) {
+ // Clear the bit associated with it.
+ BITMASK_CLEAR(&m_inp_bm_count,nPortIndex);
+ BITMASK_CLEAR(&m_heap_inp_bm_count,nPortIndex);
+ if (input_use_buffer == true) {
+
+ DEBUG_PRINT_LOW("Free pmem Buffer index %d",nPortIndex);
+ if (m_phdr_pmem_ptr)
+ free_input_buffer(m_phdr_pmem_ptr[nPortIndex]);
+ } else {
+ if (arbitrary_bytes) {
+ if (m_phdr_pmem_ptr)
+ free_input_buffer(nPortIndex,m_phdr_pmem_ptr[nPortIndex]);
+ else
+ free_input_buffer(nPortIndex,NULL);
+ } else
+ free_input_buffer(buffer);
+ }
+ m_inp_bPopulated = OMX_FALSE;
+ if(release_input_done())
+ release_buffers(this, VDEC_BUFFER_TYPE_INPUT);
+ /*Free the Buffer Header*/
+ if (release_input_done()) {
+ DEBUG_PRINT_HIGH("ALL input buffers are freed/released");
+ free_input_buffer_header();
+ }
+ } else {
+ DEBUG_PRINT_ERROR("Error: free_buffer ,Port Index Invalid");
+ eRet = OMX_ErrorBadPortIndex;
+ }
+
+ if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING)
+ && release_input_done()) {
+ DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
+ BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_DISABLE_PENDING);
+ post_event(OMX_CommandPortDisable,
+ OMX_CORE_INPUT_PORT_INDEX,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+ } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
+ // check if the buffer is valid
+ nPortIndex = buffer - client_buffers.get_il_buf_hdr();
+ if (nPortIndex < drv_ctx.op_buf.actualcount &&
+ BITMASK_PRESENT(&m_out_bm_count, nPortIndex)) {
+ DEBUG_PRINT_LOW("free_buffer on o/p port - Port idx %d", nPortIndex);
+ // Clear the bit associated with it.
+ BITMASK_CLEAR(&m_out_bm_count,nPortIndex);
+ m_out_bPopulated = OMX_FALSE;
+ client_buffers.free_output_buffer (buffer);
+
+ if(release_output_done()) {
+ release_buffers(this, VDEC_BUFFER_TYPE_OUTPUT);
+ }
+ if (release_output_done()) {
+ free_output_buffer_header();
+ }
+ } else {
+ DEBUG_PRINT_ERROR("Error: free_buffer , Port Index Invalid");
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ if (BITMASK_PRESENT((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING)
+ && release_output_done()) {
+ DEBUG_PRINT_LOW("FreeBuffer : If any Disable event pending,post it");
+
+ DEBUG_PRINT_LOW("MOVING TO DISABLED STATE");
+ BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
+#ifdef _ANDROID_ICS_
+ if (m_enable_android_native_buffers) {
+ DEBUG_PRINT_LOW("FreeBuffer - outport disabled: reset native buffers");
+ memset(&native_buffer, 0 ,(sizeof(struct nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
+ }
+#endif
+
+ post_event(OMX_CommandPortDisable,
+ OMX_CORE_OUTPUT_PORT_INDEX,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+ } else {
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ if ((eRet == OMX_ErrorNone) &&
+ (BITMASK_PRESENT(&m_flags ,OMX_COMPONENT_LOADING_PENDING))) {
+ if (release_done()) {
+ // Send the callback now
+ BITMASK_CLEAR((&m_flags),OMX_COMPONENT_LOADING_PENDING);
+ post_event(OMX_CommandStateSet, OMX_StateLoaded,
+ OMX_COMPONENT_GENERATE_EVENT);
+ }
+ }
+ return eRet;
+}
+
+
+/* ======================================================================
+ FUNCTION
+ omx_vdec::EmptyThisBuffer
+
+ DESCRIPTION
+ This routine is used to push the encoded video frames to
+ the video decoder.
+
+ PARAMETERS
+ None.
+
+ RETURN VALUE
+ OMX Error None if everything went successful.
+
+ ========================================================================== */
+OMX_ERRORTYPE omx_vdec::empty_this_buffer(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_BUFFERHEADERTYPE* buffer)
+{
+ OMX_ERRORTYPE ret1 = OMX_ErrorNone;
+ unsigned int nBufferIndex = drv_ctx.ip_buf.actualcount;
+
+ if (m_state != OMX_StateExecuting &&
+ m_state != OMX_StatePause &&
+ m_state != OMX_StateIdle) {
+ DEBUG_PRINT_ERROR("Empty this buffer in Invalid State");
+ return OMX_ErrorInvalidState;
+ }
+
+ if (buffer == NULL) {
+ DEBUG_PRINT_ERROR("ERROR:ETB Buffer is NULL");
+ return OMX_ErrorBadParameter;
+ }
+
+ if (!m_inp_bEnabled) {
+ DEBUG_PRINT_ERROR("ERROR:ETB incorrect state operation, input port is disabled.");
+ return OMX_ErrorIncorrectStateOperation;
+ }
+
+ if (buffer->nInputPortIndex != OMX_CORE_INPUT_PORT_INDEX) {
+ DEBUG_PRINT_ERROR("ERROR:ETB invalid port in header %u", (unsigned int)buffer->nInputPortIndex);
+ return OMX_ErrorBadPortIndex;
+ }
+
+ if (perf_flag) {
+ if (!latency) {
+ dec_time.stop();
+ latency = dec_time.processing_time_us();
+ dec_time.start();
+ }
+ }
+
+ if (arbitrary_bytes) {
+ nBufferIndex = buffer - m_inp_heap_ptr;
+ } else {
+ if (input_use_buffer == true) {
+ nBufferIndex = buffer - m_inp_heap_ptr;
+ if (nBufferIndex >= drv_ctx.ip_buf.actualcount ) {
+ DEBUG_PRINT_ERROR("ERROR: ETB nBufferIndex is invalid in use-buffer mode");
+ return OMX_ErrorBadParameter;
+ }
+ m_inp_mem_ptr[nBufferIndex].nFilledLen = m_inp_heap_ptr[nBufferIndex].nFilledLen;
+ m_inp_mem_ptr[nBufferIndex].nTimeStamp = m_inp_heap_ptr[nBufferIndex].nTimeStamp;
+ m_inp_mem_ptr[nBufferIndex].nFlags = m_inp_heap_ptr[nBufferIndex].nFlags;
+ buffer = &m_inp_mem_ptr[nBufferIndex];
+ DEBUG_PRINT_LOW("Non-Arbitrary mode - buffer address is: malloc %p, pmem%p in Index %d, buffer %p of size %u",
+ &m_inp_heap_ptr[nBufferIndex], &m_inp_mem_ptr[nBufferIndex],nBufferIndex, buffer, (unsigned int)buffer->nFilledLen);
+ } else {
+ nBufferIndex = buffer - m_inp_mem_ptr;
+ }
+ }
+
+ if (nBufferIndex >= drv_ctx.ip_buf.actualcount ) {
+ DEBUG_PRINT_ERROR("ERROR:ETB nBufferIndex is invalid");
+ return OMX_ErrorBadParameter;
+ }
+
+ if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
+ codec_config_flag = true;
+ DEBUG_PRINT_LOW("%s: codec_config buffer", __FUNCTION__);
+ }
+
+ /* The client should not set this when codec is in arbitrary bytes mode */
+ if (m_input_pass_buffer_fd) {
+ buffer->pBuffer = (OMX_U8*)drv_ctx.ptr_inputbuffer[nBufferIndex].bufferaddr;
+ }
+
+ DEBUG_PRINT_LOW("[ETB] BHdr(%p) pBuf(%p) nTS(%lld) nFL(%u)",
+ buffer, buffer->pBuffer, buffer->nTimeStamp, (unsigned int)buffer->nFilledLen);
+ if (arbitrary_bytes) {
+ post_event ((unsigned long)hComp,(unsigned long)buffer,
+ OMX_COMPONENT_GENERATE_ETB_ARBITRARY);
+ } else {
+ post_event ((unsigned long)hComp,(unsigned long)buffer,OMX_COMPONENT_GENERATE_ETB);
+ }
+ time_stamp_dts.insert_timestamp(buffer);
+ return OMX_ErrorNone;
+}
+
+/* ======================================================================
+ FUNCTION
+ omx_vdec::empty_this_buffer_proxy
+
+ DESCRIPTION
+ This routine is used to push the encoded video frames to
+ the video decoder.
+
+ PARAMETERS
+ None.
+
+ RETURN VALUE
+ OMX Error None if everything went successful.
+
+ ========================================================================== */
+OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_BUFFERHEADERTYPE* buffer)
+{
+ (void) hComp;
+ int push_cnt = 0,i=0;
+ unsigned nPortIndex = 0;
+ OMX_ERRORTYPE ret = OMX_ErrorNone;
+ struct vdec_input_frameinfo frameinfo;
+ struct vdec_bufferpayload *temp_buffer;
+ struct vdec_seqheader seq_header;
+ bool port_setting_changed = true;
+
+ /*Should we generate a Aync error event*/
+ if (buffer == NULL || buffer->pInputPortPrivate == NULL) {
+ DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy is invalid");
+ return OMX_ErrorBadParameter;
+ }
+
+ nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
+
+ if (nPortIndex >= drv_ctx.ip_buf.actualcount) {
+ DEBUG_PRINT_ERROR("ERROR:empty_this_buffer_proxy invalid nPortIndex[%u]",
+ nPortIndex);
+ return OMX_ErrorBadParameter;
+ }
+
+ pending_input_buffers++;
+
+ /* return zero length and not an EOS buffer */
+ if (!arbitrary_bytes && (buffer->nFilledLen == 0) &&
+ ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0)) {
+ DEBUG_PRINT_HIGH("return zero legth buffer");
+ post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
+ OMX_COMPONENT_GENERATE_EBD);
+ return OMX_ErrorNone;
+ }
+
+ if (input_flush_progress == true) {
+ DEBUG_PRINT_LOW("Flush in progress return buffer ");
+ post_event ((unsigned long)buffer,VDEC_S_SUCCESS,
+ OMX_COMPONENT_GENERATE_EBD);
+ return OMX_ErrorNone;
+ }
+
+ auto_lock l(buf_lock);
+ temp_buffer = (struct vdec_bufferpayload *)buffer->pInputPortPrivate;
+
+ if (!temp_buffer || (temp_buffer - drv_ctx.ptr_inputbuffer) > (int)drv_ctx.ip_buf.actualcount) {
+ return OMX_ErrorBadParameter;
+ }
+ /* If its first frame, H264 codec and reject is true, then parse the nal
+ and get the profile. Based on this, reject the clip playback */
+ if (first_frame == 0 && codec_type_parse == CODEC_TYPE_H264 &&
+ m_reject_avc_1080p_mp) {
+ first_frame = 1;
+ DEBUG_PRINT_ERROR("Parse nal to get the profile");
+ h264_parser->parse_nal((OMX_U8*)buffer->pBuffer, buffer->nFilledLen,
+ NALU_TYPE_SPS);
+ m_profile = h264_parser->get_profile();
+ ret = is_video_session_supported();
+ if (ret) {
+ post_event ((unsigned long)buffer,VDEC_S_SUCCESS,OMX_COMPONENT_GENERATE_EBD);
+ post_event(OMX_EventError, OMX_ErrorInvalidState,OMX_COMPONENT_GENERATE_EVENT);
+ /* Move the state to Invalid to avoid queueing of pending ETB to the driver */
+ m_state = OMX_StateInvalid;
+ return OMX_ErrorNone;
+ }
+ }
+
+ DEBUG_PRINT_LOW("ETBProxy: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
+ /*for use buffer we need to memcpy the data*/
+ temp_buffer->buffer_len = buffer->nFilledLen;
+
+ if (input_use_buffer && temp_buffer->bufferaddr && !secure_mode) {
+ if (buffer->nFilledLen <= temp_buffer->buffer_len) {
+ if (arbitrary_bytes) {
+ memcpy (temp_buffer->bufferaddr, (buffer->pBuffer + buffer->nOffset),buffer->nFilledLen);
+ } else {
+ memcpy (temp_buffer->bufferaddr, (m_inp_heap_ptr[nPortIndex].pBuffer + m_inp_heap_ptr[nPortIndex].nOffset),
+ buffer->nFilledLen);
+ }
+ } else {
+ return OMX_ErrorBadParameter;
+ }
+
+ }
+
+ frameinfo.bufferaddr = temp_buffer->bufferaddr;
+ frameinfo.client_data = (void *) buffer;
+ frameinfo.datalen = temp_buffer->buffer_len;
+ frameinfo.flags = 0;
+ frameinfo.offset = buffer->nOffset;
+ frameinfo.pmem_fd = temp_buffer->pmem_fd;
+ frameinfo.pmem_offset = temp_buffer->offset;
+ frameinfo.timestamp = buffer->nTimeStamp;
+ if (drv_ctx.disable_dmx && m_desc_buffer_ptr && m_desc_buffer_ptr[nPortIndex].buf_addr) {
+ DEBUG_PRINT_LOW("ETB: dmx enabled");
+ if (m_demux_entries == 0) {
+ extract_demux_addr_offsets(buffer);
+ }
+
+ DEBUG_PRINT_LOW("ETB: handle_demux_data - entries=%u",(unsigned int)m_demux_entries);
+ handle_demux_data(buffer);
+ frameinfo.desc_addr = (OMX_U8 *)m_desc_buffer_ptr[nPortIndex].buf_addr;
+ frameinfo.desc_size = m_desc_buffer_ptr[nPortIndex].desc_data_size;
+ } else {
+ frameinfo.desc_addr = NULL;
+ frameinfo.desc_size = 0;
+ }
+ if (!arbitrary_bytes) {
+ frameinfo.flags |= buffer->nFlags;
+ }
+
+#ifdef _ANDROID_
+ if (m_debug_timestamp) {
+ if (arbitrary_bytes) {
+ DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp);
+ m_timestamp_list.insert_ts(buffer->nTimeStamp);
+ } else if (!arbitrary_bytes && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
+ DEBUG_PRINT_LOW("Inserting TIMESTAMP (%lld) into queue", buffer->nTimeStamp);
+ m_timestamp_list.insert_ts(buffer->nTimeStamp);
+ }
+ }
+#endif
+
+ log_input_buffers((const char *)temp_buffer->bufferaddr, temp_buffer->buffer_len);
+
+if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) {
+ frameinfo.flags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
+ buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
+ }
+
+ if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
+ DEBUG_PRINT_HIGH("Rxd i/p EOS, Notify Driver that EOS has been reached");
+ frameinfo.flags |= VDEC_BUFFERFLAG_EOS;
+ h264_scratch.nFilledLen = 0;
+ nal_count = 0;
+ look_ahead_nal = false;
+ frame_count = 0;
+ if (m_frame_parser.mutils)
+ m_frame_parser.mutils->initialize_frame_checking_environment();
+ m_frame_parser.flush();
+ h264_last_au_ts = LLONG_MAX;
+ h264_last_au_flags = 0;
+ memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
+ m_demux_entries = 0;
+ }
+ struct v4l2_buffer buf;
+ struct v4l2_plane plane;
+ memset( (void *)&buf, 0, sizeof(buf));
+ memset( (void *)&plane, 0, sizeof(plane));
+ int rc;
+ unsigned long print_count;
+ if (temp_buffer->buffer_len == 0 || (buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
+ buf.flags = V4L2_QCOM_BUF_FLAG_EOS;
+ DEBUG_PRINT_HIGH("INPUT EOS reached") ;
+ }
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ buf.index = nPortIndex;
+ buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ buf.memory = V4L2_MEMORY_USERPTR;
+ plane.bytesused = temp_buffer->buffer_len;
+ plane.length = drv_ctx.ip_buf.buffer_size;
+ plane.m.userptr = (unsigned long)temp_buffer->bufferaddr -
+ (unsigned long)temp_buffer->offset;
+ plane.reserved[0] = temp_buffer->pmem_fd;
+ plane.reserved[1] = temp_buffer->offset;
+ plane.data_offset = 0;
+ buf.m.planes = &plane;
+ buf.length = 1;
+ if (frameinfo.timestamp >= LLONG_MAX) {
+ buf.flags |= V4L2_QCOM_BUF_TIMESTAMP_INVALID;
+ }
+ //assumption is that timestamp is in milliseconds
+ buf.timestamp.tv_sec = frameinfo.timestamp / 1000000;
+ buf.timestamp.tv_usec = (frameinfo.timestamp % 1000000);
+ buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) ? V4L2_QCOM_BUF_FLAG_CODECCONFIG: 0;
+ buf.flags |= (buffer->nFlags & OMX_BUFFERFLAG_DECODEONLY) ? V4L2_QCOM_BUF_FLAG_DECODEONLY: 0;
+
+ if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
+ DEBUG_PRINT_LOW("Increment codec_config buffer counter");
+ android_atomic_inc(&m_queued_codec_config_count);
+ }
+
+ rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
+ if (rc) {
+ DEBUG_PRINT_ERROR("Failed to qbuf Input buffer to driver, send ETB back to client");
+ m_cb.EmptyBufferDone(hComp, m_app_data, buffer);
+ 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;
+
+ buf_type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ DEBUG_PRINT_LOW("send_command_proxy(): Idle-->Executing");
+ ret=ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMON,&buf_type);
+ if (!ret) {
+ DEBUG_PRINT_HIGH("Streamon on OUTPUT Plane was successful");
+ streaming[OUTPUT_PORT] = true;
+ } else if (errno == EBUSY) {
+ DEBUG_PRINT_ERROR("Failed to call stream on OUTPUT due to HW_OVERLOAD");
+ post_event ((unsigned long)buffer, VDEC_S_SUCCESS,
+ OMX_COMPONENT_GENERATE_EBD);
+ return OMX_ErrorInsufficientResources;
+ } else {
+ DEBUG_PRINT_ERROR("Failed to call streamon on OUTPUT");
+ DEBUG_PRINT_LOW("If Stream on failed no buffer should be queued");
+ post_event ((unsigned long)buffer, VDEC_S_SUCCESS,
+ OMX_COMPONENT_GENERATE_EBD);
+ return OMX_ErrorBadParameter;
+ }
+ }
+ DEBUG_PRINT_LOW("[ETBP] pBuf(%p) nTS(%lld) Sz(%u)",
+ frameinfo.bufferaddr, (long long)frameinfo.timestamp,
+ (unsigned int)frameinfo.datalen);
+
+ return ret;
+}
+
+/* ======================================================================
+ FUNCTION
+ omx_vdec::FillThisBuffer
+
+ DESCRIPTION
+ IL client uses this method to release the frame buffer
+ after displaying them.
+
+ PARAMETERS
+ None.
+
+ RETURN VALUE
+ true/false
+
+ ========================================================================== */
+OMX_ERRORTYPE omx_vdec::fill_this_buffer(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_BUFFERHEADERTYPE* buffer)
+{
+ if (m_state != OMX_StateExecuting &&
+ m_state != OMX_StatePause &&
+ m_state != OMX_StateIdle) {
+ DEBUG_PRINT_ERROR("FTB in Invalid State");
+ return OMX_ErrorInvalidState;
+ }
+
+ if (!m_out_bEnabled) {
+ DEBUG_PRINT_ERROR("ERROR:FTB incorrect state operation, output port is disabled.");
+ return OMX_ErrorIncorrectStateOperation;
+ }
+
+ unsigned nPortIndex = 0;
+ if (dynamic_buf_mode) {
+ private_handle_t *handle = NULL;
+ struct VideoDecoderOutputMetaData *meta;
+ unsigned int nPortIndex = 0;
+
+ if (!buffer || !buffer->pBuffer) {
+ DEBUG_PRINT_ERROR("%s: invalid params: %p", __FUNCTION__, buffer);
+ return OMX_ErrorBadParameter;
+ }
+
+ //get the buffer type and fd info
+ meta = (struct VideoDecoderOutputMetaData *)buffer->pBuffer;
+ handle = (private_handle_t *)meta->pHandle;
+ DEBUG_PRINT_LOW("FTB: metabuf: %p buftype: %d bufhndl: %p ", meta, meta->eType, meta->pHandle);
+
+ if (!handle) {
+ DEBUG_PRINT_ERROR("FTB: Error: IL client passed an invalid buf handle - %p", handle);
+ return OMX_ErrorBadParameter;
+ }
+ //Fill outputbuffer with buffer details, this will be sent to f/w during VIDIOC_QBUF
+ nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr());
+ if (nPortIndex < drv_ctx.op_buf.actualcount &&
+ nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) {
+ drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd = handle->fd;
+ drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = (OMX_U8*) buffer;
+
+ //Store private handle from GraphicBuffer
+ native_buffer[nPortIndex].privatehandle = handle;
+ native_buffer[nPortIndex].nativehandle = handle;
+ } else {
+ DEBUG_PRINT_ERROR("[FTB]Invalid native_buffer index: %d", nPortIndex);
+ return OMX_ErrorBadParameter;
+ }
+
+ //buffer->nAllocLen will be sizeof(struct VideoDecoderOutputMetaData). Overwrite
+ //this with a more sane size so that we don't compensate in rest of code
+ //We'll restore this size later on, so that it's transparent to client
+ buffer->nFilledLen = 0;
+ buffer->nAllocLen = handle->size;
+
+ if (handle->flags & private_handle_t::PRIV_FLAGS_DISP_CONSUMER) {
+ m_is_display_session = true;
+ } else {
+ m_is_display_session = false;
+ }
+ DEBUG_PRINT_LOW("%s: m_is_display_session = %d", __func__, m_is_display_session);
+
+ drv_ctx.op_buf.buffer_size = handle->size;
+ }
+
+ nPortIndex = buffer - client_buffers.get_il_buf_hdr();
+ if (buffer == NULL ||
+ (nPortIndex >= drv_ctx.op_buf.actualcount)) {
+ DEBUG_PRINT_ERROR("FTB: ERROR: invalid buffer index, nPortIndex %u bufCount %u",
+ nPortIndex, drv_ctx.op_buf.actualcount);
+ return OMX_ErrorBadParameter;
+ }
+
+ if (buffer->nOutputPortIndex != OMX_CORE_OUTPUT_PORT_INDEX) {
+ DEBUG_PRINT_ERROR("ERROR:FTB invalid port in header %u", (unsigned int)buffer->nOutputPortIndex);
+ return OMX_ErrorBadPortIndex;
+ }
+
+ DEBUG_PRINT_LOW("[FTB] bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
+ post_event((unsigned long) hComp, (unsigned long)buffer, m_fill_output_msg);
+ return OMX_ErrorNone;
+}
+/* ======================================================================
+ FUNCTION
+ omx_vdec::fill_this_buffer_proxy
+
+ DESCRIPTION
+ IL client uses this method to release the frame buffer
+ after displaying them.
+
+ PARAMETERS
+ None.
+
+ RETURN VALUE
+ true/false
+
+ ========================================================================== */
+OMX_ERRORTYPE omx_vdec::fill_this_buffer_proxy(
+ OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_BUFFERHEADERTYPE* bufferAdd)
+{
+ OMX_ERRORTYPE nRet = OMX_ErrorNone;
+ OMX_BUFFERHEADERTYPE *buffer = bufferAdd;
+ unsigned nPortIndex = 0;
+ struct vdec_fillbuffer_cmd fillbuffer;
+ struct vdec_bufferpayload *ptr_outputbuffer = NULL;
+ struct vdec_output_frameinfo *ptr_respbuffer = NULL;
+
+ nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr());
+
+ if (bufferAdd == NULL || nPortIndex >= drv_ctx.op_buf.actualcount) {
+ DEBUG_PRINT_ERROR("FTBProxy: ERROR: invalid buffer index, nPortIndex %u bufCount %u",
+ nPortIndex, drv_ctx.op_buf.actualcount);
+ return OMX_ErrorBadParameter;
+ }
+
+ DEBUG_PRINT_LOW("FTBProxy: bufhdr = %p, bufhdr->pBuffer = %p",
+ bufferAdd, bufferAdd->pBuffer);
+ /*Return back the output buffer to client*/
+ if (m_out_bEnabled != OMX_TRUE || output_flush_progress == true || in_reconfig) {
+ DEBUG_PRINT_LOW("Output Buffers return flush/disable condition");
+ buffer->nFilledLen = 0;
+ m_cb.FillBufferDone (hComp,m_app_data,buffer);
+ return OMX_ErrorNone;
+ }
+
+ if (dynamic_buf_mode) {
+ drv_ctx.ptr_outputbuffer[nPortIndex].offset = 0;
+ drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len = buffer->nAllocLen;
+ buf_ref_add(nPortIndex);
+ drv_ctx.ptr_outputbuffer[nPortIndex].mmaped_size = buffer->nAllocLen;
+ }
+
+ pending_output_buffers++;
+ buffer = client_buffers.get_dr_buf_hdr(bufferAdd);
+ if (!buffer) {
+ DEBUG_PRINT_ERROR("err: client_buffer ptr invalid");
+ return OMX_ErrorBadParameter;
+ }
+ ptr_respbuffer = (struct vdec_output_frameinfo*)buffer->pOutputPortPrivate;
+ if (ptr_respbuffer) {
+ ptr_outputbuffer = (struct vdec_bufferpayload*)ptr_respbuffer->client_data;
+ }
+
+ if (ptr_respbuffer == NULL || ptr_outputbuffer == NULL) {
+ DEBUG_PRINT_ERROR("resp buffer or outputbuffer is NULL");
+ buffer->nFilledLen = 0;
+ m_cb.FillBufferDone (hComp,m_app_data,buffer);
+ pending_output_buffers--;
+ return OMX_ErrorBadParameter;
+ }
+
+ int rc = 0;
+ struct v4l2_buffer buf;
+ struct v4l2_plane plane[VIDEO_MAX_PLANES];
+ memset( (void *)&buf, 0, sizeof(buf));
+ memset( (void *)plane, 0, (sizeof(struct v4l2_plane)*VIDEO_MAX_PLANES));
+ unsigned int extra_idx = 0;
+
+ buf.index = nPortIndex;
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ buf.memory = V4L2_MEMORY_USERPTR;
+ plane[0].bytesused = buffer->nFilledLen;
+ plane[0].length = buffer->nAllocLen;
+ plane[0].m.userptr =
+ (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr -
+ (unsigned long)drv_ctx.ptr_outputbuffer[nPortIndex].offset;
+ plane[0].reserved[0] = drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd;
+ plane[0].reserved[1] = drv_ctx.ptr_outputbuffer[nPortIndex].offset;
+ plane[0].data_offset = 0;
+ extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
+ if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
+ plane[extra_idx].bytesused = 0;
+ plane[extra_idx].length = drv_ctx.extradata_info.buffer_size;
+ plane[extra_idx].m.userptr = (long unsigned int) (drv_ctx.extradata_info.uaddr + nPortIndex * drv_ctx.extradata_info.buffer_size);
+#ifdef USE_ION
+ plane[extra_idx].reserved[0] = drv_ctx.extradata_info.ion.fd_ion_data.fd;
+#endif
+ plane[extra_idx].reserved[1] = nPortIndex * drv_ctx.extradata_info.buffer_size;
+ plane[extra_idx].data_offset = 0;
+ } else if (extra_idx >= VIDEO_MAX_PLANES) {
+ DEBUG_PRINT_ERROR("Extradata index higher than expected: %u", extra_idx);
+ return OMX_ErrorBadParameter;
+ }
+ buf.m.planes = plane;
+ buf.length = drv_ctx.num_planes;
+ DEBUG_PRINT_LOW("SENDING FTB TO F/W - fd[0] = %d fd[1] = %d offset[1] = %d in_flush = %d",
+ plane[0].reserved[0],plane[extra_idx].reserved[0], plane[extra_idx].reserved[1], output_flush_progress);
+
+ rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_QBUF, &buf);
+ if (rc) {
+ /*TODO: How to handle this case */
+ buffer->nFilledLen = 0;
+ DEBUG_PRINT_ERROR("Failed to qbuf to driver, send FTB back to client");
+ m_cb.FillBufferDone(hComp, m_app_data, buffer);
+ }
+return OMX_ErrorNone;
+}
+
+/* ======================================================================
+ FUNCTION
+ omx_vdec::SetCallbacks
+
+ DESCRIPTION
+ Set the callbacks.
+
+ PARAMETERS
+ None.
+
+ RETURN VALUE
+ OMX Error None if everything successful.
+
+ ========================================================================== */
+OMX_ERRORTYPE omx_vdec::set_callbacks(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_IN OMX_CALLBACKTYPE* callbacks,
+ OMX_IN OMX_PTR appData)
+{
+ (void) hComp;
+ m_cb = *callbacks;
+ DEBUG_PRINT_LOW("Callbacks Set %p %p %p",m_cb.EmptyBufferDone,\
+ m_cb.EventHandler,m_cb.FillBufferDone);
+ m_app_data = appData;
+ return OMX_ErrorNotImplemented;
+}
+
+/* ======================================================================
+ FUNCTION
+ omx_vdec::ComponentDeInit
+
+ DESCRIPTION
+ Destroys the component and release memory allocated to the heap.
+
+ PARAMETERS
+ <TBD>.
+
+ RETURN VALUE
+ OMX Error None if everything successful.
+
+ ========================================================================== */
+OMX_ERRORTYPE omx_vdec::component_deinit(OMX_IN OMX_HANDLETYPE hComp)
+{
+ (void) hComp;
+
+ unsigned i = 0;
+ if (OMX_StateLoaded != m_state) {
+ DEBUG_PRINT_ERROR("WARNING:Rxd DeInit,OMX not in LOADED state %d",\
+ m_state);
+ DEBUG_PRINT_ERROR("Playback Ended - FAILED");
+ } else {
+ DEBUG_PRINT_HIGH("Playback Ended - PASSED");
+ }
+
+ /*Check if the output buffers have to be cleaned up*/
+ if (m_out_mem_ptr) {
+ DEBUG_PRINT_LOW("Freeing the Output Memory");
+ for (i = 0; i < drv_ctx.op_buf.actualcount; i++ ) {
+ if (BITMASK_PRESENT(&m_out_bm_count, i)) {
+ BITMASK_CLEAR(&m_out_bm_count, i);
+ client_buffers.free_output_buffer (&m_out_mem_ptr[i]);
+ }
+
+ if (release_output_done()) {
+ break;
+ }
+ }
+#ifdef _ANDROID_ICS_
+ memset(&native_buffer, 0, (sizeof(nativebuffer) * MAX_NUM_INPUT_OUTPUT_BUFFERS));
+#endif
+ }
+
+ /*Check if the input buffers have to be cleaned up*/
+ if (m_inp_mem_ptr || m_inp_heap_ptr) {
+ DEBUG_PRINT_LOW("Freeing the Input Memory");
+ for (i = 0; i<drv_ctx.ip_buf.actualcount; i++ ) {
+
+ if (BITMASK_PRESENT(&m_inp_bm_count, i)) {
+ BITMASK_CLEAR(&m_inp_bm_count, i);
+ if (m_inp_mem_ptr)
+ free_input_buffer (i,&m_inp_mem_ptr[i]);
+ else
+ free_input_buffer (i,NULL);
+ }
+
+ if (release_input_done()) {
+ break;
+ }
+ }
+ }
+ free_input_buffer_header();
+ free_output_buffer_header();
+ if (h264_scratch.pBuffer) {
+ free(h264_scratch.pBuffer);
+ h264_scratch.pBuffer = NULL;
+ }
+
+ if (h264_parser) {
+ delete h264_parser;
+ h264_parser = NULL;
+ }
+
+ if (m_frame_parser.mutils) {
+ DEBUG_PRINT_LOW("Free utils parser");
+ delete (m_frame_parser.mutils);
+ m_frame_parser.mutils = NULL;
+ }
+
+ if (m_platform_list) {
+ free(m_platform_list);
+ m_platform_list = NULL;
+ }
+ if (m_vendor_config.pData) {
+ free(m_vendor_config.pData);
+ m_vendor_config.pData = NULL;
+ }
+
+ // Reset counters in mesg queues
+ m_ftb_q.m_size=0;
+ m_cmd_q.m_size=0;
+ m_etb_q.m_size=0;
+ m_ftb_q.m_read = m_ftb_q.m_write =0;
+ m_cmd_q.m_read = m_cmd_q.m_write =0;
+ m_etb_q.m_read = m_etb_q.m_write =0;
+#ifdef _ANDROID_
+ if (m_debug_timestamp) {
+ m_timestamp_list.reset_ts_list();
+ }
+#endif
+
+ DEBUG_PRINT_LOW("Calling VDEC_IOCTL_STOP_NEXT_MSG");
+ //(void)ioctl(drv_ctx.video_driver_fd, VDEC_IOCTL_STOP_NEXT_MSG,
+ // NULL);
+ DEBUG_PRINT_HIGH("Close the driver instance");
+
+ if (m_debug.infile) {
+ fclose(m_debug.infile);
+ m_debug.infile = NULL;
+ }
+ if (m_debug.outfile) {
+ fclose(m_debug.outfile);
+ m_debug.outfile = NULL;
+ }
+ if (m_debug.out_ymeta_file) {
+ fclose(m_debug.out_ymeta_file);
+ m_debug.out_ymeta_file = NULL;
+ }
+ if (m_debug.out_uvmeta_file) {
+ fclose(m_debug.out_uvmeta_file);
+ m_debug.out_uvmeta_file = NULL;
+ }
+#ifdef OUTPUT_EXTRADATA_LOG
+ if (outputExtradataFile)
+ fclose (outputExtradataFile);
+#endif
+ DEBUG_PRINT_INFO("omx_vdec::component_deinit() complete");
+ return OMX_ErrorNone;
+}
+
+/* ======================================================================
+ FUNCTION
+ omx_vdec::UseEGLImage
+
+ DESCRIPTION
+ OMX Use EGL Image method implementation <TBD>.
+
+ PARAMETERS
+ <TBD>.
+
+ RETURN VALUE
+ Not Implemented error.
+
+ ========================================================================== */
+OMX_ERRORTYPE omx_vdec::use_EGL_image(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_INOUT OMX_BUFFERHEADERTYPE** bufferHdr,
+ OMX_IN OMX_U32 port,
+ OMX_IN OMX_PTR appData,
+ OMX_IN void* eglImage)
+{
+ (void) appData;
+ OMX_QCOM_PLATFORM_PRIVATE_LIST pmem_list;
+ OMX_QCOM_PLATFORM_PRIVATE_ENTRY pmem_entry;
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO pmem_info;
+
+#ifdef USE_EGL_IMAGE_GPU
+ PFNEGLQUERYIMAGEQUALCOMMPROC egl_queryfunc;
+ EGLint fd = -1, offset = 0,pmemPtr = 0;
+#else
+ int fd = -1, offset = 0;
+#endif
+ DEBUG_PRINT_HIGH("use EGL image support for decoder");
+ if (!bufferHdr || !eglImage|| port != OMX_CORE_OUTPUT_PORT_INDEX) {
+ DEBUG_PRINT_ERROR("Invalid EGL image");
+ }
+#ifdef USE_EGL_IMAGE_GPU
+ if (m_display_id == NULL) {
+ DEBUG_PRINT_ERROR("Display ID is not set by IL client");
+ return OMX_ErrorInsufficientResources;
+ }
+ egl_queryfunc = (PFNEGLQUERYIMAGEQUALCOMMPROC)
+ eglGetProcAddress("eglQueryImageKHR");
+ egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_HANDLE, &fd);
+ egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_OFFSET, &offset);
+ egl_queryfunc(m_display_id, eglImage, EGL_BITMAP_POINTER_KHR, &pmemPtr);
+#else //with OMX test app
+ struct temp_egl {
+ int pmem_fd;
+ int offset;
+ };
+ struct temp_egl *temp_egl_id = NULL;
+ void * pmemPtr = (void *) eglImage;
+ temp_egl_id = (struct temp_egl *)eglImage;
+ if (temp_egl_id != NULL) {
+ fd = temp_egl_id->pmem_fd;
+ offset = temp_egl_id->offset;
+ }
+#endif
+ if (fd < 0) {
+ DEBUG_PRINT_ERROR("Improper pmem fd by EGL client %d",fd);
+ return OMX_ErrorInsufficientResources;
+ }
+ pmem_info.pmem_fd = (OMX_U32) fd;
+ pmem_info.offset = (OMX_U32) offset;
+ pmem_entry.entry = (void *) &pmem_info;
+ pmem_entry.type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
+ pmem_list.entryList = &pmem_entry;
+ pmem_list.nEntries = 1;
+ ouput_egl_buffers = true;
+ if (OMX_ErrorNone != use_buffer(hComp,bufferHdr, port,
+ (void *)&pmem_list, drv_ctx.op_buf.buffer_size,
+ (OMX_U8 *)pmemPtr)) {
+ DEBUG_PRINT_ERROR("use buffer call failed for egl image");
+ return OMX_ErrorInsufficientResources;
+ }
+ return OMX_ErrorNone;
+}
+
+/* ======================================================================
+ FUNCTION
+ omx_vdec::ComponentRoleEnum
+
+ DESCRIPTION
+ OMX Component Role Enum method implementation.
+
+ PARAMETERS
+ <TBD>.
+
+ RETURN VALUE
+ OMX Error None if everything is successful.
+ ========================================================================== */
+OMX_ERRORTYPE omx_vdec::component_role_enum(OMX_IN OMX_HANDLETYPE hComp,
+ OMX_OUT OMX_U8* role,
+ OMX_IN OMX_U32 index)
+{
+ (void) hComp;
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+
+ if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE)) {
+ if ((0 == index) && role) {
+ strlcpy((char *)role, "video_decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE);
+ DEBUG_PRINT_LOW("component_role_enum: role %s",role);
+ } else {
+ eRet = OMX_ErrorNoMore;
+ }
+ }
+ if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) {
+ if ((0 == index) && role) {
+ strlcpy((char *)role, "video_decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE);
+ DEBUG_PRINT_LOW("component_role_enum: role %s",role);
+ } else {
+ eRet = OMX_ErrorNoMore;
+ }
+ } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE)) {
+ if ((0 == index) && role) {
+ strlcpy((char *)role, "video_decoder.h263",OMX_MAX_STRINGNAME_SIZE);
+ DEBUG_PRINT_LOW("component_role_enum: role %s",role);
+ } else {
+ DEBUG_PRINT_LOW("No more roles");
+ eRet = OMX_ErrorNoMore;
+ }
+ }
+
+ else if ((!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE)) ||
+ (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.divx311",OMX_MAX_STRINGNAME_SIZE))) {
+ if ((0 == index) && role) {
+ strlcpy((char *)role, "video_decoder.divx",OMX_MAX_STRINGNAME_SIZE);
+ DEBUG_PRINT_LOW("component_role_enum: role %s",role);
+ } else {
+ DEBUG_PRINT_LOW("No more roles");
+ eRet = OMX_ErrorNoMore;
+ }
+ } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) {
+ if ((0 == index) && role) {
+ strlcpy((char *)role, "video_decoder.avc",OMX_MAX_STRINGNAME_SIZE);
+ DEBUG_PRINT_LOW("component_role_enum: role %s",role);
+ } else {
+ DEBUG_PRINT_LOW("No more roles");
+ eRet = OMX_ErrorNoMore;
+ }
+ } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) {
+ if ((0 == index) && role) {
+ strlcpy((char *)role, "video_decoder.mvc", OMX_MAX_STRINGNAME_SIZE);
+ DEBUG_PRINT_LOW("component_role_enum: role %s",role);
+ } else {
+ DEBUG_PRINT_LOW("No more roles");
+ eRet = OMX_ErrorNoMore;
+ }
+ } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) {
+ if ((0 == index) && role) {
+ strlcpy((char *)role, "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE);
+ DEBUG_PRINT_LOW("component_role_enum: role %s", role);
+ } else {
+ DEBUG_PRINT_LOW("No more roles");
+ eRet = OMX_ErrorNoMore;
+ }
+ } else if ( (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vc1",OMX_MAX_STRINGNAME_SIZE)) ||
+ (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.wmv",OMX_MAX_STRINGNAME_SIZE))
+ ) {
+ if ((0 == index) && role) {
+ strlcpy((char *)role, "video_decoder.vc1",OMX_MAX_STRINGNAME_SIZE);
+ DEBUG_PRINT_LOW("component_role_enum: role %s",role);
+ } else {
+ DEBUG_PRINT_LOW("No more roles");
+ eRet = OMX_ErrorNoMore;
+ }
+ } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE)) {
+ if ((0 == index) && role) {
+ strlcpy((char *)role, "video_decoder.vp8",OMX_MAX_STRINGNAME_SIZE);
+ DEBUG_PRINT_LOW("component_role_enum: role %s",role);
+ } else {
+ DEBUG_PRINT_LOW("No more roles");
+ eRet = OMX_ErrorNoMore;
+ }
+ } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",OMX_MAX_STRINGNAME_SIZE)) {
+ if ((0 == index) && role) {
+ strlcpy((char *)role, "video_decoder.vp9",OMX_MAX_STRINGNAME_SIZE);
+ DEBUG_PRINT_LOW("component_role_enum: role %s",role);
+ } else {
+ DEBUG_PRINT_LOW("No more roles");
+ eRet = OMX_ErrorNoMore;
+ }
+ } else {
+ DEBUG_PRINT_ERROR("ERROR:Querying Role on Unknown Component");
+ eRet = OMX_ErrorInvalidComponentName;
+ }
+ return eRet;
+}
+
+
+
+
+/* ======================================================================
+ FUNCTION
+ omx_vdec::AllocateDone
+
+ DESCRIPTION
+ Checks if entire buffer pool is allocated by IL Client or not.
+ Need this to move to IDLE state.
+
+ PARAMETERS
+ None.
+
+ RETURN VALUE
+ true/false.
+
+ ========================================================================== */
+bool omx_vdec::allocate_done(void)
+{
+ bool bRet = false;
+ bool bRet_In = false;
+ bool bRet_Out = false;
+
+ bRet_In = allocate_input_done();
+ bRet_Out = allocate_output_done();
+
+ if (bRet_In && bRet_Out) {
+ bRet = true;
+ }
+
+ return bRet;
+}
+/* ======================================================================
+ FUNCTION
+ omx_vdec::AllocateInputDone
+
+ DESCRIPTION
+ Checks if I/P buffer pool is allocated by IL Client or not.
+
+ PARAMETERS
+ None.
+
+ RETURN VALUE
+ true/false.
+
+ ========================================================================== */
+bool omx_vdec::allocate_input_done(void)
+{
+ bool bRet = false;
+ unsigned i=0;
+
+ if (m_inp_mem_ptr == NULL) {
+ return bRet;
+ }
+ if (m_inp_mem_ptr ) {
+ for (; i<drv_ctx.ip_buf.actualcount; i++) {
+ if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
+ break;
+ }
+ }
+ }
+ if (i == drv_ctx.ip_buf.actualcount) {
+ bRet = true;
+ DEBUG_PRINT_HIGH("Allocate done for all i/p buffers");
+ }
+ if (i==drv_ctx.ip_buf.actualcount && m_inp_bEnabled) {
+ m_inp_bPopulated = OMX_TRUE;
+ }
+ return bRet;
+}
+/* ======================================================================
+ FUNCTION
+ omx_vdec::AllocateOutputDone
+
+ DESCRIPTION
+ Checks if entire O/P buffer pool is allocated by IL Client or not.
+
+ PARAMETERS
+ None.
+
+ RETURN VALUE
+ true/false.
+
+ ========================================================================== */
+bool omx_vdec::allocate_output_done(void)
+{
+ bool bRet = false;
+ unsigned j=0;
+
+ if (m_out_mem_ptr == NULL) {
+ return bRet;
+ }
+
+ if (m_out_mem_ptr) {
+ for (; j < drv_ctx.op_buf.actualcount; j++) {
+ if (BITMASK_ABSENT(&m_out_bm_count,j)) {
+ break;
+ }
+ }
+ }
+
+ if (j == drv_ctx.op_buf.actualcount) {
+ bRet = true;
+ DEBUG_PRINT_HIGH("Allocate done for all o/p buffers");
+ if (m_out_bEnabled)
+ m_out_bPopulated = OMX_TRUE;
+ }
+
+ return bRet;
+}
+
+/* ======================================================================
+ FUNCTION
+ omx_vdec::ReleaseDone
+
+ DESCRIPTION
+ Checks if IL client has released all the buffers.
+
+ PARAMETERS
+ None.
+
+ RETURN VALUE
+ true/false
+
+ ========================================================================== */
+bool omx_vdec::release_done(void)
+{
+ bool bRet = false;
+
+ if (release_input_done()) {
+ if (release_output_done()) {
+ bRet = true;
+ }
+ }
+ return bRet;
+}
+
+
+/* ======================================================================
+ FUNCTION
+ omx_vdec::ReleaseOutputDone
+
+ DESCRIPTION
+ Checks if IL client has released all the buffers.
+
+ PARAMETERS
+ None.
+
+ RETURN VALUE
+ true/false
+
+ ========================================================================== */
+bool omx_vdec::release_output_done(void)
+{
+ bool bRet = false;
+ unsigned i=0,j=0;
+
+ DEBUG_PRINT_LOW("Value of m_out_mem_ptr %p", m_out_mem_ptr);
+ if (m_out_mem_ptr) {
+ for (; j < drv_ctx.op_buf.actualcount ; j++) {
+ if (BITMASK_PRESENT(&m_out_bm_count,j)) {
+ break;
+ }
+ }
+ if (j == drv_ctx.op_buf.actualcount) {
+ m_out_bm_count = 0;
+ bRet = true;
+ }
+ } else {
+ m_out_bm_count = 0;
+ bRet = true;
+ }
+ return bRet;
+}
+/* ======================================================================
+ FUNCTION
+ omx_vdec::ReleaseInputDone
+
+ DESCRIPTION
+ Checks if IL client has released all the buffers.
+
+ PARAMETERS
+ None.
+
+ RETURN VALUE
+ true/false
+
+ ========================================================================== */
+bool omx_vdec::release_input_done(void)
+{
+ bool bRet = false;
+ unsigned i=0,j=0;
+
+ DEBUG_PRINT_LOW("Value of m_inp_mem_ptr %p",m_inp_mem_ptr);
+ if (m_inp_mem_ptr) {
+ for (; j<drv_ctx.ip_buf.actualcount; j++) {
+ if ( BITMASK_PRESENT(&m_inp_bm_count,j)) {
+ break;
+ }
+ }
+ if (j==drv_ctx.ip_buf.actualcount) {
+ bRet = true;
+ }
+ } else {
+ bRet = true;
+ }
+ return bRet;
+}
+
+OMX_ERRORTYPE omx_vdec::fill_buffer_done(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE * buffer)
+{
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = NULL;
+ if (!buffer || (buffer - m_out_mem_ptr) >= (int)drv_ctx.op_buf.actualcount) {
+ DEBUG_PRINT_ERROR("[FBD] ERROR in ptr(%p)", buffer);
+ return OMX_ErrorBadParameter;
+ } else if (output_flush_progress) {
+ DEBUG_PRINT_LOW("FBD: Buffer (%p) flushed", buffer);
+ buffer->nFilledLen = 0;
+ buffer->nTimeStamp = 0;
+ buffer->nFlags &= ~OMX_BUFFERFLAG_EXTRADATA;
+ buffer->nFlags &= ~QOMX_VIDEO_BUFFERFLAG_EOSEQ;
+ buffer->nFlags &= ~OMX_BUFFERFLAG_DATACORRUPT;
+ }
+
+ if (m_debug_extradata) {
+ if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_EOSEQ) {
+ DEBUG_PRINT_HIGH("***************************************************");
+ DEBUG_PRINT_HIGH("FillBufferDone: End Of Sequence Received");
+ DEBUG_PRINT_HIGH("***************************************************");
+ }
+
+ if (buffer->nFlags & OMX_BUFFERFLAG_DATACORRUPT) {
+ DEBUG_PRINT_HIGH("***************************************************");
+ DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received");
+ DEBUG_PRINT_HIGH("***************************************************");
+ }
+ }
+
+
+ DEBUG_PRINT_LOW("fill_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p, flags: 0x%x, timestamp: %lld",
+ buffer, buffer->pBuffer, buffer->nFlags, buffer->nTimeStamp);
+ pending_output_buffers --;
+
+ if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
+ DEBUG_PRINT_HIGH("Output EOS has been reached");
+ if (!output_flush_progress)
+ post_event((unsigned)NULL, (unsigned)NULL,
+ OMX_COMPONENT_GENERATE_EOS_DONE);
+
+ 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 long) pdest_frame,(unsigned)NULL,
+ (unsigned)NULL);
+ pdest_frame = NULL;
+ }
+ }
+
+ if (!output_flush_progress && (buffer->nFilledLen > 0)) {
+ // set the default colorspace advised by client, since the bitstream may be
+ // devoid of colorspace-info.
+ if (m_enable_android_native_buffers) {
+ ColorSpace_t color_space = ITU_R_601;
+
+ // Disabled ?
+ // WA for VP8. Vp8 encoder does not embed color-info (yet!).
+ // Encoding RGBA results in 601-LR for all resolutions.
+ // This conflicts with the client't defaults which are based on resolution.
+ // Eg: 720p will be encoded as 601-LR. Client will say 709.
+ // Re-enable this code once vp8 encoder generates color-info and hence the
+ // decoder will be able to override with the correct source color.
+#if 0
+ switch (m_client_color_space.sAspects.mPrimaries) {
+ case ColorAspects::PrimariesBT601_6_625:
+ case ColorAspects::PrimariesBT601_6_525:
+ {
+ color_space = m_client_color_space.sAspects.mRange == ColorAspects::RangeFull ?
+ ITU_R_601_FR : ITU_R_601;
+ break;
+ }
+ case ColorAspects::PrimariesBT709_5:
+ {
+ color_space = ITU_R_709;
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+#endif
+ DEBUG_PRINT_LOW("setMetaData for Color Space (client) = 0x%x (601=%u FR=%u 709=%u)",
+ color_space, ITU_R_601, ITU_R_601_FR, ITU_R_709);
+ set_colorspace_in_handle(color_space, buffer - m_out_mem_ptr);
+ }
+ DEBUG_PRINT_LOW("Processing extradata");
+ handle_extradata(buffer);
+ }
+
+#ifdef OUTPUT_EXTRADATA_LOG
+ if (outputExtradataFile) {
+ int buf_index = buffer - m_out_mem_ptr;
+ OMX_U8 *pBuffer = (OMX_U8 *)(drv_ctx.ptr_outputbuffer[buf_index].bufferaddr);
+
+ OMX_OTHER_EXTRADATATYPE *p_extra = NULL;
+ p_extra = (OMX_OTHER_EXTRADATATYPE *)
+ ((unsigned long)(pBuffer + buffer->nOffset + buffer->nFilledLen + 3)&(~3));
+
+ while (p_extra && (OMX_U8*)p_extra < (pBuffer + buffer->nAllocLen) ) {
+ DEBUG_PRINT_LOW("WRITING extradata, size=%d,type=%x",
+ p_extra->nSize, p_extra->eType);
+ fwrite (p_extra,1,p_extra->nSize,outputExtradataFile);
+
+ if (p_extra->eType == OMX_ExtraDataNone) {
+ break;
+ }
+ p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + p_extra->nSize);
+ }
+ }
+#endif
+
+ /* For use buffer we need to copy the data */
+ if (!output_flush_progress) {
+ /* This is the error check for non-recoverable errros */
+ bool is_duplicate_ts_valid = true;
+ bool is_interlaced = (drv_ctx.interlace != VDEC_InterlaceFrameProgressive);
+
+ if (output_capability == V4L2_PIX_FMT_MPEG4 ||
+ output_capability == V4L2_PIX_FMT_MPEG2 ||
+ output_capability == V4L2_PIX_FMT_DIVX ||
+ output_capability == V4L2_PIX_FMT_DIVX_311)
+ is_duplicate_ts_valid = false;
+
+ if ((output_capability == V4L2_PIX_FMT_H264 ||
+ output_capability == V4L2_PIX_FMT_H264_MVC) &&
+ is_interlaced) {
+ if (buffer->nFlags & QOMX_VIDEO_BUFFERFLAG_MBAFF) {
+ is_interlaced = false;
+ }
+ }
+
+ if (buffer->nFilledLen > 0) {
+ time_stamp_dts.get_next_timestamp(buffer,
+ is_interlaced && is_duplicate_ts_valid);
+ if (m_debug_timestamp) {
+ {
+ OMX_TICKS expected_ts = 0;
+ m_timestamp_list.pop_min_ts(expected_ts);
+ if (is_interlaced && is_duplicate_ts_valid) {
+ m_timestamp_list.pop_min_ts(expected_ts);
+ }
+ DEBUG_PRINT_LOW("Current timestamp (%lld),Popped TIMESTAMP (%lld) from list",
+ buffer->nTimeStamp, expected_ts);
+
+ if (buffer->nTimeStamp != expected_ts) {
+ DEBUG_PRINT_ERROR("ERROR in omx_vdec::async_message_process timestamp Check");
+ }
+ }
+ }
+ }
+ }
+
+ if (m_cb.FillBufferDone) {
+ if (buffer->nFilledLen > 0) {
+ if (arbitrary_bytes)
+ adjust_timestamp(buffer->nTimeStamp);
+ else
+ set_frame_rate(buffer->nTimeStamp);
+
+ if (perf_flag) {
+ if (!proc_frms) {
+ dec_time.stop();
+ latency = dec_time.processing_time_us() - latency;
+ DEBUG_PRINT_HIGH(">>> FBD Metrics: Latency(%.2f)mS", latency / 1e3);
+ dec_time.start();
+ fps_metrics.start();
+ }
+ proc_frms++;
+ if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
+ OMX_U64 proc_time = 0;
+ fps_metrics.stop();
+ proc_time = fps_metrics.processing_time_us();
+ DEBUG_PRINT_HIGH(">>> FBD Metrics: proc_frms(%u) proc_time(%.2f)S fps(%.2f)",
+ (unsigned int)proc_frms, (float)proc_time / 1e6,
+ (float)(1e6 * proc_frms) / proc_time);
+ proc_frms = 0;
+ }
+ }
+ }
+ if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
+ prev_ts = LLONG_MAX;
+ rst_prev_ts = true;
+ }
+
+ pPMEMInfo = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
+ ((OMX_QCOM_PLATFORM_PRIVATE_LIST *)
+ buffer->pPlatformPrivate)->entryList->entry;
+ DEBUG_PRINT_LOW("Before FBD callback Accessed Pmeminfo %lu",pPMEMInfo->pmem_fd);
+ OMX_BUFFERHEADERTYPE *il_buffer;
+ il_buffer = client_buffers.get_il_buf_hdr(buffer);
+ OMX_U32 current_framerate = (int)(drv_ctx.frame_rate.fps_numerator / drv_ctx.frame_rate.fps_denominator);
+
+ if (il_buffer && m_last_rendered_TS >= 0) {
+ OMX_TICKS ts_delta = (OMX_TICKS)llabs(il_buffer->nTimeStamp - m_last_rendered_TS);
+
+ // Current frame can be send for rendering if
+ // (a) current FPS is <= 60
+ // (b) is the next frame after the frame with TS 0
+ // (c) is the first frame after seek
+ // (d) the delta TS b\w two consecutive frames is > 16 ms
+ // (e) its TS is equal to previous frame TS
+ // (f) if marked EOS
+
+ if(current_framerate <= 60 || m_last_rendered_TS == 0 ||
+ il_buffer->nTimeStamp == 0 || ts_delta >= 16000 ||
+ ts_delta == 0 || (il_buffer->nFlags & OMX_BUFFERFLAG_EOS)) {
+ m_last_rendered_TS = il_buffer->nTimeStamp;
+ } else {
+ //mark for droping
+ buffer->nFilledLen = 0;
+ }
+
+ DEBUG_PRINT_LOW(" -- %s Frame -- info:: fps(%d) lastRenderTime(%lld) bufferTs(%lld) ts_delta(%lld)",
+ buffer->nFilledLen? "Rendering":"Dropping",current_framerate,m_last_rendered_TS,
+ il_buffer->nTimeStamp,ts_delta);
+
+ //above code makes sure that delta b\w two consecutive frames is not
+ //greater than 16ms, slow-mo feature, so cap fps to max 60
+ if (current_framerate > 60 ) {
+ current_framerate = 60;
+ }
+ }
+
+ // add current framerate to gralloc meta data
+ if (m_enable_android_native_buffers && m_out_mem_ptr) {
+ OMX_U32 buf_index = buffer - m_out_mem_ptr;
+ setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
+ UPDATE_REFRESH_RATE, (void*)&current_framerate);
+ }
+
+ if (buffer->nFilledLen && m_enable_android_native_buffers && m_out_mem_ptr) {
+ OMX_U32 buf_index = buffer - m_out_mem_ptr;
+ DEBUG_PRINT_LOW("stereo_output_mode = %d",stereo_output_mode);
+ setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
+ S3D_FORMAT, (void*)&stereo_output_mode);
+ }
+
+ if (il_buffer) {
+ log_output_buffers(il_buffer);
+ if (dynamic_buf_mode) {
+ unsigned int nPortIndex = 0;
+ nPortIndex = buffer-((OMX_BUFFERHEADERTYPE *)client_buffers.get_il_buf_hdr());
+
+ // Since we're passing around handles, adjust nFilledLen and nAllocLen
+ // to size of the handle. Do it _after_ log_output_buffers which
+ // requires the respective sizes to be accurate.
+
+ buffer->nAllocLen = sizeof(struct VideoDecoderOutputMetaData);
+ buffer->nFilledLen = buffer->nFilledLen ?
+ sizeof(struct VideoDecoderOutputMetaData) : 0;
+
+ //Clear graphic buffer handles in dynamic mode
+ if (nPortIndex < drv_ctx.op_buf.actualcount &&
+ nPortIndex < MAX_NUM_INPUT_OUTPUT_BUFFERS) {
+ native_buffer[nPortIndex].privatehandle = NULL;
+ native_buffer[nPortIndex].nativehandle = NULL;
+ } else {
+ DEBUG_PRINT_ERROR("[FBD]Invalid native_buffer index: %d", nPortIndex);
+ return OMX_ErrorBadParameter;
+ }
+ }
+ m_cb.FillBufferDone (hComp,m_app_data,il_buffer);
+ } else {
+ DEBUG_PRINT_ERROR("Invalid buffer address from get_il_buf_hdr");
+ return OMX_ErrorBadParameter;
+ }
+ DEBUG_PRINT_LOW("After Fill Buffer Done callback %lu",pPMEMInfo->pmem_fd);
+ } else {
+ return OMX_ErrorBadParameter;
+ }
+
+#ifdef ADAPTIVE_PLAYBACK_SUPPORTED
+ if (m_smoothstreaming_mode && m_out_mem_ptr) {
+ OMX_U32 buf_index = buffer - m_out_mem_ptr;
+ BufferDim_t dim;
+ private_handle_t *private_handle = NULL;
+ dim.sliceWidth = framesize.nWidth;
+ dim.sliceHeight = framesize.nHeight;
+ if (buf_index < drv_ctx.op_buf.actualcount &&
+ buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS &&
+ native_buffer[buf_index].privatehandle)
+ private_handle = native_buffer[buf_index].privatehandle;
+ if (private_handle) {
+ DEBUG_PRINT_LOW("set metadata: update buf-geometry with stride %d slice %d",
+ dim.sliceWidth, dim.sliceHeight);
+ setMetaData(private_handle, UPDATE_BUFFER_GEOMETRY, (void*)&dim);
+ }
+ }
+#endif
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE omx_vdec::empty_buffer_done(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE* buffer)
+{
+
+ int nBufferIndex = buffer - m_inp_mem_ptr;
+
+ if (buffer == NULL || (nBufferIndex >= (int)drv_ctx.ip_buf.actualcount)) {
+ DEBUG_PRINT_ERROR("empty_buffer_done: ERROR bufhdr = %p", buffer);
+ return OMX_ErrorBadParameter;
+ }
+
+ DEBUG_PRINT_LOW("empty_buffer_done: bufhdr = %p, bufhdr->pBuffer = %p, bufhdr->nFlags = 0x%x",
+ buffer, buffer->pBuffer, buffer->nFlags);
+ pending_input_buffers--;
+
+ if (arbitrary_bytes) {
+ if (pdest_frame == NULL && input_flush_progress == false) {
+ DEBUG_PRINT_LOW("Push input from buffer done address of Buffer %p",buffer);
+ pdest_frame = buffer;
+ buffer->nFilledLen = 0;
+ buffer->nTimeStamp = LLONG_MAX;
+ push_input_buffer (hComp);
+ } else {
+ DEBUG_PRINT_LOW("Push buffer into freeq address of Buffer %p",buffer);
+ buffer->nFilledLen = 0;
+ if (!m_input_free_q.insert_entry((unsigned long)buffer,
+ (unsigned)NULL, (unsigned)NULL)) {
+ DEBUG_PRINT_ERROR("ERROR:i/p free Queue is FULL Error");
+ }
+ }
+ } else if (m_cb.EmptyBufferDone) {
+ buffer->nFilledLen = 0;
+ if (input_use_buffer == true) {
+ buffer = &m_inp_heap_ptr[buffer-m_inp_mem_ptr];
+ }
+
+ /* Restore the FD that we over-wrote in ETB */
+ if (m_input_pass_buffer_fd) {
+ buffer->pBuffer = (OMX_U8*)(uintptr_t)drv_ctx.ptr_inputbuffer[nBufferIndex].pmem_fd;
+ }
+
+ m_cb.EmptyBufferDone(hComp ,m_app_data, buffer);
+ }
+ return OMX_ErrorNone;
+}
+
+int omx_vdec::async_message_process (void *context, void* message)
+{
+ omx_vdec* omx = NULL;
+ struct vdec_msginfo *vdec_msg = NULL;
+ OMX_BUFFERHEADERTYPE* omxhdr = NULL;
+ struct v4l2_buffer *v4l2_buf_ptr = NULL;
+ struct v4l2_plane *plane = NULL;
+ struct vdec_output_frameinfo *output_respbuf = NULL;
+ int rc=1;
+ if (context == NULL || message == NULL) {
+ DEBUG_PRINT_ERROR("FATAL ERROR in omx_vdec::async_message_process NULL Check");
+ return -1;
+ }
+ vdec_msg = (struct vdec_msginfo *)message;
+
+ omx = reinterpret_cast<omx_vdec*>(context);
+
+ switch (vdec_msg->msgcode) {
+
+ case VDEC_MSG_EVT_HW_ERROR:
+ omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
+ OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
+ break;
+
+ case VDEC_MSG_EVT_HW_OVERLOAD:
+ omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
+ OMX_COMPONENT_GENERATE_HARDWARE_OVERLOAD);
+ break;
+
+ case VDEC_MSG_EVT_HW_UNSUPPORTED:
+ omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
+ OMX_COMPONENT_GENERATE_UNSUPPORTED_SETTING);
+ break;
+
+ case VDEC_MSG_RESP_START_DONE:
+ omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
+ OMX_COMPONENT_GENERATE_START_DONE);
+ break;
+
+ case VDEC_MSG_RESP_STOP_DONE:
+ omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
+ OMX_COMPONENT_GENERATE_STOP_DONE);
+ break;
+
+ case VDEC_MSG_RESP_RESUME_DONE:
+ omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
+ OMX_COMPONENT_GENERATE_RESUME_DONE);
+ break;
+
+ case VDEC_MSG_RESP_PAUSE_DONE:
+ omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
+ OMX_COMPONENT_GENERATE_PAUSE_DONE);
+ break;
+
+ case VDEC_MSG_RESP_FLUSH_INPUT_DONE:
+ omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
+ OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH);
+ break;
+ case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE:
+ omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
+ OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH);
+ break;
+ case VDEC_MSG_RESP_INPUT_FLUSHED:
+ case VDEC_MSG_RESP_INPUT_BUFFER_DONE:
+
+ /* omxhdr = (OMX_BUFFERHEADERTYPE* )
+ vdec_msg->msgdata.input_frame_clientdata; */
+
+ v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.input_frame_clientdata;
+ if (omx->m_inp_mem_ptr == NULL || v4l2_buf_ptr == NULL ||
+ v4l2_buf_ptr->index >= omx->drv_ctx.ip_buf.actualcount) {
+ omxhdr = NULL;
+ vdec_msg->status_code = VDEC_S_EFATAL;
+ break;
+
+ }
+ omxhdr = omx->m_inp_mem_ptr + v4l2_buf_ptr->index;
+
+ if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_INPUT_UNSUPPORTED) {
+ DEBUG_PRINT_HIGH("Unsupported input");
+ omx->post_event ((unsigned)NULL, vdec_msg->status_code,\
+ OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
+ }
+ if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DATA_CORRUPT) {
+ omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
+ vdec_msg->status_code = VDEC_S_INPUT_BITSTREAM_ERR;
+ }
+ if (omxhdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
+
+ DEBUG_PRINT_LOW("Decrement codec_config buffer counter");
+ android_atomic_dec(&omx->m_queued_codec_config_count);
+ if ((android_atomic_add(0, &omx->m_queued_codec_config_count) == 0) &&
+ BITMASK_PRESENT(&omx->m_flags, OMX_COMPONENT_FLUSH_DEFERRED)) {
+ DEBUG_PRINT_LOW("sem post for CODEC CONFIG buffer");
+ sem_post(&omx->m_safe_flush);
+ }
+ }
+ if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME ||
+ v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_IDRFRAME) {
+ omxhdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
+ }
+ omx->post_event ((unsigned long)omxhdr,vdec_msg->status_code,
+ OMX_COMPONENT_GENERATE_EBD);
+ break;
+ case VDEC_MSG_EVT_INFO_FIELD_DROPPED:
+ int64_t *timestamp;
+ timestamp = (int64_t *) malloc(sizeof(int64_t));
+ if (timestamp) {
+ *timestamp = vdec_msg->msgdata.output_frame.time_stamp;
+ omx->post_event ((unsigned long)timestamp, vdec_msg->status_code,
+ OMX_COMPONENT_GENERATE_INFO_FIELD_DROPPED);
+ DEBUG_PRINT_HIGH("Field dropped time stamp is %lld",
+ (long long)vdec_msg->msgdata.output_frame.time_stamp);
+ }
+ break;
+ case VDEC_MSG_RESP_OUTPUT_FLUSHED:
+ case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE:
+
+ v4l2_buf_ptr = (v4l2_buffer*)vdec_msg->msgdata.output_frame.client_data;
+ if (v4l2_buf_ptr == NULL || omx->m_out_mem_ptr == NULL ||
+ v4l2_buf_ptr->index >= omx->drv_ctx.op_buf.actualcount) {
+ omxhdr = NULL;
+ vdec_msg->status_code = VDEC_S_EFATAL;
+ break;
+ }
+ plane = v4l2_buf_ptr->m.planes;
+ omxhdr = omx->m_out_mem_ptr + v4l2_buf_ptr->index;
+
+ if (omxhdr && omxhdr->pOutputPortPrivate &&
+ ((omxhdr - omx->m_out_mem_ptr) < (int)omx->drv_ctx.op_buf.actualcount) &&
+ (((struct vdec_output_frameinfo *)omxhdr->pOutputPortPrivate
+ - omx->drv_ctx.ptr_respbuffer) < (int)omx->drv_ctx.op_buf.actualcount)) {
+
+ if (vdec_msg->msgdata.output_frame.len <= omxhdr->nAllocLen) {
+ omxhdr->nFilledLen = vdec_msg->msgdata.output_frame.len;
+ omxhdr->nOffset = vdec_msg->msgdata.output_frame.offset;
+ omxhdr->nTimeStamp = vdec_msg->msgdata.output_frame.time_stamp;
+ omxhdr->nFlags = 0;
+
+ if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS) {
+ omxhdr->nFlags |= OMX_BUFFERFLAG_EOS;
+ //rc = -1;
+ }
+ if (omxhdr->nFilledLen) {
+ omxhdr->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
+ }
+ if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME || v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_IDRFRAME) {
+ omxhdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
+ } else {
+ omxhdr->nFlags &= ~OMX_BUFFERFLAG_SYNCFRAME;
+ }
+ if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOSEQ) {
+ omxhdr->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
+ }
+ if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) {
+ omxhdr->nFlags |= OMX_BUFFERFLAG_DECODEONLY;
+ }
+ if (v4l2_buf_ptr->flags & V4L2_MSM_BUF_FLAG_MBAFF) {
+ omxhdr->nFlags |= QOMX_VIDEO_BUFFERFLAG_MBAFF;
+ }
+ if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_READONLY) {
+ omxhdr->nFlags |= OMX_BUFFERFLAG_READONLY;
+ DEBUG_PRINT_LOW("F_B_D: READONLY BUFFER - REFERENCE WITH F/W fd = %d",
+ omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].pmem_fd);
+ }
+
+ if (omxhdr && (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DROP_FRAME) &&
+ !omx->output_flush_progress &&
+ !(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_DECODEONLY) &&
+ !(v4l2_buf_ptr->flags & V4L2_QCOM_BUF_FLAG_EOS)) {
+ unsigned int index = v4l2_buf_ptr->index;
+ unsigned int extra_idx = EXTRADATA_IDX(omx->drv_ctx.num_planes);
+ omx->time_stamp_dts.remove_time_stamp(
+ omxhdr->nTimeStamp,
+ (omx->drv_ctx.interlace != VDEC_InterlaceFrameProgressive)
+ ?true:false);
+ plane[0].bytesused = 0;
+ plane[0].m.userptr =
+ (unsigned long)omx->drv_ctx.ptr_outputbuffer[index].bufferaddr -
+ (unsigned long)omx->drv_ctx.ptr_outputbuffer[index].offset;
+ plane[0].reserved[0] = omx->drv_ctx.ptr_outputbuffer[index].pmem_fd;
+ plane[0].reserved[1] = omx->drv_ctx.ptr_outputbuffer[index].offset;
+ plane[0].data_offset = 0;
+ v4l2_buf_ptr->flags = 0x0;
+ if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
+ plane[extra_idx].bytesused = 0;
+ plane[extra_idx].length = omx->drv_ctx.extradata_info.buffer_size;
+ plane[extra_idx].m.userptr = (long unsigned int) (omx->drv_ctx.extradata_info.uaddr + index * omx->drv_ctx.extradata_info.buffer_size);
+#ifdef USE_ION
+ plane[extra_idx].reserved[0] = omx->drv_ctx.extradata_info.ion.fd_ion_data.fd;
+#endif
+ plane[extra_idx].reserved[1] = v4l2_buf_ptr->index * omx->drv_ctx.extradata_info.buffer_size;
+ plane[extra_idx].data_offset = 0;
+ } else if (extra_idx >= VIDEO_MAX_PLANES) {
+ DEBUG_PRINT_ERROR("Extradata index higher than expected: %u", extra_idx);
+ return -1;
+ }
+
+ DEBUG_PRINT_LOW("SENDING FTB TO F/W from async_message_process - fd[0] = %d fd[1] = %d offset[1] = %d in_flush = %d",
+ plane[0].reserved[0],plane[extra_idx].reserved[0], plane[extra_idx].reserved[1], omx->output_flush_progress);
+ if(ioctl(omx->drv_ctx.video_driver_fd, VIDIOC_QBUF, v4l2_buf_ptr)) {
+ DEBUG_PRINT_ERROR("Failed to queue buffer back to driver: %d, %d, %d", v4l2_buf_ptr->length, v4l2_buf_ptr->m.planes[0].reserved[0], v4l2_buf_ptr->m.planes[1].reserved[0]);
+ return -1;
+ }
+ break;
+ }
+ if (v4l2_buf_ptr->flags & V4L2_QCOM_BUF_DATA_CORRUPT) {
+ omxhdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
+ }
+
+ output_respbuf = (struct vdec_output_frameinfo *)\
+ omxhdr->pOutputPortPrivate;
+ if (!output_respbuf) {
+ DEBUG_PRINT_ERROR("async_message_process: invalid output buf received");
+ return -1;
+ }
+ output_respbuf->len = vdec_msg->msgdata.output_frame.len;
+ output_respbuf->offset = vdec_msg->msgdata.output_frame.offset;
+
+ if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_KEYFRAME) {
+ output_respbuf->pic_type = PICTURE_TYPE_I;
+ }
+ if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_PFRAME) {
+ output_respbuf->pic_type = PICTURE_TYPE_P;
+ }
+ if (v4l2_buf_ptr->flags & V4L2_BUF_FLAG_BFRAME) {
+ output_respbuf->pic_type = PICTURE_TYPE_B;
+ }
+
+ if (vdec_msg->msgdata.output_frame.len) {
+ DEBUG_PRINT_LOW("Processing extradata");
+ omx->handle_extradata(omxhdr);
+
+ if (omx->m_extradata_info.output_crop_updated) {
+ DEBUG_PRINT_LOW("Read FBD crop from output extra data");
+ vdec_msg->msgdata.output_frame.framesize.left = omx->m_extradata_info.output_crop_rect.nLeft;
+ vdec_msg->msgdata.output_frame.framesize.top = omx->m_extradata_info.output_crop_rect.nTop;
+ vdec_msg->msgdata.output_frame.framesize.right = omx->m_extradata_info.output_crop_rect.nWidth;
+ vdec_msg->msgdata.output_frame.framesize.bottom = omx->m_extradata_info.output_crop_rect.nHeight;
+ vdec_msg->msgdata.output_frame.picsize.frame_width = omx->m_extradata_info.output_width;
+ vdec_msg->msgdata.output_frame.picsize.frame_height = omx->m_extradata_info.output_height;
+ } else {
+ DEBUG_PRINT_LOW("Read FBD crop from v4l2 reserved fields");
+ vdec_msg->msgdata.output_frame.framesize.left = plane[0].reserved[2];
+ vdec_msg->msgdata.output_frame.framesize.top = plane[0].reserved[3];
+ vdec_msg->msgdata.output_frame.framesize.right = plane[0].reserved[2] + plane[0].reserved[4];
+ vdec_msg->msgdata.output_frame.framesize.bottom = plane[0].reserved[3] + plane[0].reserved[5];
+ vdec_msg->msgdata.output_frame.picsize.frame_width = plane[0].reserved[6];
+ vdec_msg->msgdata.output_frame.picsize.frame_height = plane[0].reserved[7];
+ }
+ }
+
+ vdec_msg->msgdata.output_frame.bufferaddr =
+ omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].bufferaddr;
+
+ if (vdec_msg->msgdata.output_frame.len)
+ memcpy(&omx->drv_ctx.frame_size,
+ &vdec_msg->msgdata.output_frame.framesize,
+ sizeof(struct vdec_framesize));
+
+ DEBUG_PRINT_LOW("[RespBufDone] Fd(%d) Buf(%p) Ts(%lld) PicType(%u) Flags (0x%x)"
+ " FillLen(%u) Crop: L(%u) T(%u) R(%u) B(%u)",
+ omx->drv_ctx.ptr_outputbuffer[v4l2_buf_ptr->index].pmem_fd,
+ omxhdr, (long long)vdec_msg->msgdata.output_frame.time_stamp,
+ vdec_msg->msgdata.output_frame.pic_type, v4l2_buf_ptr->flags,
+ (unsigned int)vdec_msg->msgdata.output_frame.len,
+ vdec_msg->msgdata.output_frame.framesize.left,
+ vdec_msg->msgdata.output_frame.framesize.top,
+ vdec_msg->msgdata.output_frame.framesize.right,
+ vdec_msg->msgdata.output_frame.framesize.bottom);
+
+ /* Post event if resolution OR crop changed */
+ /* filled length will be changed if resolution changed */
+ /* Crop parameters can be changed even without resolution change */
+ if (omxhdr->nFilledLen
+ && ((omx->prev_n_filled_len != omxhdr->nFilledLen)
+ || (omx->drv_ctx.frame_size.left != vdec_msg->msgdata.output_frame.framesize.left)
+ || (omx->drv_ctx.frame_size.top != vdec_msg->msgdata.output_frame.framesize.top)
+ || (omx->drv_ctx.frame_size.right != vdec_msg->msgdata.output_frame.framesize.right)
+ || (omx->drv_ctx.frame_size.bottom != vdec_msg->msgdata.output_frame.framesize.bottom)
+ || (omx->drv_ctx.video_resolution.frame_width != vdec_msg->msgdata.output_frame.picsize.frame_width)
+ || (omx->drv_ctx.video_resolution.frame_height != vdec_msg->msgdata.output_frame.picsize.frame_height) )) {
+
+ DEBUG_PRINT_HIGH("Parameters Changed From: Len: %u, WxH: %dx%d, L: %u, T: %u, R: %u, B: %u --> Len: %u, WxH: %dx%d, L: %u, T: %u, R: %u, B: %u",
+ omx->prev_n_filled_len,
+ omx->drv_ctx.video_resolution.frame_width,
+ omx->drv_ctx.video_resolution.frame_height,
+ omx->drv_ctx.frame_size.left, omx->drv_ctx.frame_size.top,
+ omx->drv_ctx.frame_size.right, omx->drv_ctx.frame_size.bottom,
+ omxhdr->nFilledLen, vdec_msg->msgdata.output_frame.picsize.frame_width,
+ vdec_msg->msgdata.output_frame.picsize.frame_height,
+ vdec_msg->msgdata.output_frame.framesize.left,
+ vdec_msg->msgdata.output_frame.framesize.top,
+ vdec_msg->msgdata.output_frame.framesize.right,
+ vdec_msg->msgdata.output_frame.framesize.bottom);
+
+ omx->drv_ctx.video_resolution.frame_width =
+ vdec_msg->msgdata.output_frame.picsize.frame_width;
+ omx->drv_ctx.video_resolution.frame_height =
+ vdec_msg->msgdata.output_frame.picsize.frame_height;
+ if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
+ omx->drv_ctx.video_resolution.stride =
+ VENUS_Y_STRIDE(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_width);
+ omx->drv_ctx.video_resolution.scan_lines =
+ VENUS_Y_SCANLINES(COLOR_FMT_NV12, omx->drv_ctx.video_resolution.frame_height);
+ } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
+ omx->drv_ctx.video_resolution.stride =
+ VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, omx->drv_ctx.video_resolution.frame_width);
+ omx->drv_ctx.video_resolution.scan_lines =
+ VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, omx->drv_ctx.video_resolution.frame_height);
+ }
+
+ omx->post_event(OMX_CORE_OUTPUT_PORT_INDEX,
+ OMX_IndexConfigCommonOutputCrop,
+ OMX_COMPONENT_GENERATE_PORT_RECONFIG);
+ }
+
+ if (omxhdr->nFilledLen)
+ omx->prev_n_filled_len = omxhdr->nFilledLen;
+
+ if (omxhdr && omxhdr->nFilledLen && !omx->high_fps) {
+ omx->request_perf_level(VIDC_NOMINAL);
+ }
+ if (omx->output_use_buffer && omxhdr->pBuffer &&
+ vdec_msg->msgdata.output_frame.bufferaddr)
+ memcpy ( omxhdr->pBuffer, (void *)
+ ((unsigned long)vdec_msg->msgdata.output_frame.bufferaddr +
+ (unsigned long)vdec_msg->msgdata.output_frame.offset),
+ vdec_msg->msgdata.output_frame.len);
+ } else {
+ DEBUG_PRINT_ERROR("Invalid filled length = %u, buffer size = %u, prev_length = %u",
+ (unsigned int)vdec_msg->msgdata.output_frame.len,
+ omxhdr->nAllocLen, omx->prev_n_filled_len);
+ omxhdr->nFilledLen = 0;
+ }
+
+ omx->post_event ((unsigned long)omxhdr, vdec_msg->status_code,
+ OMX_COMPONENT_GENERATE_FBD);
+
+ } else if (vdec_msg->msgdata.output_frame.flags & OMX_BUFFERFLAG_EOS) {
+ omx->post_event ((unsigned long)NULL, vdec_msg->status_code,
+ OMX_COMPONENT_GENERATE_EOS_DONE);
+ } else {
+ omx->post_event ((unsigned int)NULL, vdec_msg->status_code,
+ OMX_COMPONENT_GENERATE_HARDWARE_ERROR);
+ }
+ break;
+ case VDEC_MSG_EVT_CONFIG_CHANGED:
+ DEBUG_PRINT_HIGH("Port settings changed");
+ omx->m_reconfig_width = vdec_msg->msgdata.output_frame.picsize.frame_width;
+ omx->m_reconfig_height = vdec_msg->msgdata.output_frame.picsize.frame_height;
+ omx->post_event (OMX_CORE_OUTPUT_PORT_INDEX, OMX_IndexParamPortDefinition,
+ OMX_COMPONENT_GENERATE_PORT_RECONFIG);
+ if (!omx->high_fps) {
+ omx->request_perf_level(VIDC_NOMINAL);
+ }
+ break;
+ default:
+ break;
+ }
+ return rc;
+}
+
+OMX_ERRORTYPE omx_vdec::empty_this_buffer_proxy_arbitrary (
+ OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE *buffer
+ )
+{
+ unsigned address,p2,id;
+ DEBUG_PRINT_LOW("Empty this arbitrary");
+
+ if (buffer == NULL) {
+ return OMX_ErrorBadParameter;
+ }
+ DEBUG_PRINT_LOW("ETBProxyArb: bufhdr = %p, bufhdr->pBuffer = %p", buffer, buffer->pBuffer);
+ DEBUG_PRINT_LOW("ETBProxyArb: nFilledLen %u, flags %u, timestamp %lld",
+ (unsigned int)buffer->nFilledLen, (unsigned int)buffer->nFlags, buffer->nTimeStamp);
+
+ /* return zero length and not an EOS buffer */
+ /* return buffer if input flush in progress */
+ if ((input_flush_progress == true) || ((buffer->nFilledLen == 0) &&
+ ((buffer->nFlags & OMX_BUFFERFLAG_EOS) == 0))) {
+ DEBUG_PRINT_HIGH("return zero legth buffer or flush in progress");
+ m_cb.EmptyBufferDone (hComp,m_app_data,buffer);
+ return OMX_ErrorNone;
+ }
+
+ if (psource_frame == NULL) {
+ DEBUG_PRINT_LOW("Set Buffer as source Buffer %p time stamp %lld",buffer,buffer->nTimeStamp);
+ psource_frame = buffer;
+ DEBUG_PRINT_LOW("Try to Push One Input Buffer ");
+ push_input_buffer (hComp);
+ } else {
+ DEBUG_PRINT_LOW("Push the source buffer into pendingq %p",buffer);
+ if (!m_input_pending_q.insert_entry((unsigned long)buffer, (unsigned)NULL,
+ (unsigned)NULL)) {
+ return OMX_ErrorBadParameter;
+ }
+ }
+
+ if (codec_config_flag && !(buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) {
+ codec_config_flag = false;
+ }
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE omx_vdec::push_input_buffer (OMX_HANDLETYPE hComp)
+{
+ unsigned long address,p2,id;
+ OMX_ERRORTYPE ret = OMX_ErrorNone;
+
+ if (pdest_frame == NULL || psource_frame == NULL) {
+ /*Check if we have a destination buffer*/
+ if (pdest_frame == NULL) {
+ DEBUG_PRINT_LOW("Get a Destination buffer from the queue");
+ if (m_input_free_q.m_size) {
+ m_input_free_q.pop_entry(&address,&p2,&id);
+ pdest_frame = (OMX_BUFFERHEADERTYPE *)address;
+ pdest_frame->nFilledLen = 0;
+ pdest_frame->nTimeStamp = LLONG_MAX;
+ DEBUG_PRINT_LOW("Address of Pmem Buffer %p",pdest_frame);
+ }
+ }
+
+ /*Check if we have a destination buffer*/
+ if (psource_frame == NULL) {
+ DEBUG_PRINT_LOW("Get a source buffer from the queue");
+ if (m_input_pending_q.m_size) {
+ m_input_pending_q.pop_entry(&address,&p2,&id);
+ psource_frame = (OMX_BUFFERHEADERTYPE *)address;
+ DEBUG_PRINT_LOW("Next source Buffer %p time stamp %lld",psource_frame,
+ psource_frame->nTimeStamp);
+ DEBUG_PRINT_LOW("Next source Buffer flag %u length %u",
+ (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
+
+ }
+ }
+
+ }
+
+ while ((pdest_frame != NULL) && (psource_frame != NULL)) {
+ switch (codec_type_parse) {
+ case CODEC_TYPE_MPEG4:
+ case CODEC_TYPE_H263:
+ case CODEC_TYPE_MPEG2:
+ ret = push_input_sc_codec(hComp);
+ break;
+ case CODEC_TYPE_H264:
+ ret = push_input_h264(hComp);
+ break;
+ case CODEC_TYPE_HEVC:
+ ret = push_input_hevc(hComp);
+ break;
+ case CODEC_TYPE_VC1:
+ ret = push_input_vc1(hComp);
+ break;
+ default:
+ break;
+ }
+ if (ret != OMX_ErrorNone) {
+ DEBUG_PRINT_ERROR("Pushing input Buffer Failed");
+ omx_report_error ();
+ break;
+ }
+ }
+
+ return ret;
+}
+
+OMX_ERRORTYPE omx_vdec::push_input_sc_codec(OMX_HANDLETYPE hComp)
+{
+ OMX_U32 partial_frame = 1;
+ OMX_BOOL generate_ebd = OMX_TRUE;
+ unsigned long address = 0, p2 = 0, id = 0;
+
+ DEBUG_PRINT_LOW("Start Parsing the bit stream address %p TimeStamp %lld",
+ psource_frame,psource_frame->nTimeStamp);
+ if (m_frame_parser.parse_sc_frame(psource_frame,
+ pdest_frame,&partial_frame) == -1) {
+ DEBUG_PRINT_ERROR("Error In Parsing Return Error");
+ return OMX_ErrorBadParameter;
+ }
+
+ if (partial_frame == 0) {
+ DEBUG_PRINT_LOW("Frame size %u source %p frame count %d",
+ (unsigned int)pdest_frame->nFilledLen,psource_frame,frame_count);
+
+
+ DEBUG_PRINT_LOW("TimeStamp updated %lld", pdest_frame->nTimeStamp);
+ /*First Parsed buffer will have only header Hence skip*/
+ if (frame_count == 0) {
+ DEBUG_PRINT_LOW("H263/MPEG4 Codec First Frame ");
+
+ if (codec_type_parse == CODEC_TYPE_MPEG4 ||
+ codec_type_parse == CODEC_TYPE_DIVX) {
+ mp4StreamType psBits;
+ psBits.data = pdest_frame->pBuffer + pdest_frame->nOffset;
+ psBits.numBytes = pdest_frame->nFilledLen;
+ mp4_headerparser.parseHeader(&psBits);
+ }
+
+ frame_count++;
+ } else {
+ pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
+ if (pdest_frame->nFilledLen) {
+ /*Push the frame to the Decoder*/
+ if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
+ return OMX_ErrorBadParameter;
+ }
+ frame_count++;
+ pdest_frame = NULL;
+
+ if (m_input_free_q.m_size) {
+ m_input_free_q.pop_entry(&address,&p2,&id);
+ pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
+ pdest_frame->nFilledLen = 0;
+ }
+ } else if (!(psource_frame->nFlags & OMX_BUFFERFLAG_EOS)) {
+ DEBUG_PRINT_ERROR("Zero len buffer return back to POOL");
+ m_input_free_q.insert_entry((unsigned long) pdest_frame, (unsigned)NULL,
+ (unsigned)NULL);
+ pdest_frame = NULL;
+ }
+ }
+ } else {
+ DEBUG_PRINT_LOW("Not a Complete Frame %u", (unsigned int)pdest_frame->nFilledLen);
+ /*Check if Destination Buffer is full*/
+ if (pdest_frame->nAllocLen ==
+ pdest_frame->nFilledLen + pdest_frame->nOffset) {
+ DEBUG_PRINT_ERROR("ERROR:Frame Not found though Destination Filled");
+ return OMX_ErrorStreamCorrupt;
+ }
+ }
+
+ if (psource_frame->nFilledLen == 0) {
+ if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
+ if (pdest_frame) {
+ pdest_frame->nFlags |= psource_frame->nFlags;
+ pdest_frame->nTimeStamp = psource_frame->nTimeStamp;
+ DEBUG_PRINT_LOW("Frame Found start Decoding Size =%u TimeStamp = %lld",
+ (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
+ DEBUG_PRINT_LOW("Found a frame size = %u number = %d",
+ (unsigned int)pdest_frame->nFilledLen,frame_count++);
+ /*Push the frame to the Decoder*/
+ if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
+ return OMX_ErrorBadParameter;
+ }
+ frame_count++;
+ pdest_frame = NULL;
+ } else {
+ DEBUG_PRINT_LOW("Last frame in else dest addr") ;
+ generate_ebd = OMX_FALSE;
+ }
+ }
+ if (generate_ebd) {
+ DEBUG_PRINT_LOW("Buffer Consumed return back to client %p",psource_frame);
+ m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
+ psource_frame = NULL;
+
+ if (m_input_pending_q.m_size) {
+ DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame);
+ m_input_pending_q.pop_entry(&address,&p2,&id);
+ psource_frame = (OMX_BUFFERHEADERTYPE *) address;
+ DEBUG_PRINT_LOW("Next source Buffer %p time stamp %lld",psource_frame,
+ psource_frame->nTimeStamp);
+ DEBUG_PRINT_LOW("Next source Buffer flag %u length %u",
+ (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
+ }
+ }
+ }
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE omx_vdec::push_input_h264 (OMX_HANDLETYPE hComp)
+{
+ OMX_U32 partial_frame = 1;
+ unsigned long address = 0, p2 = 0, id = 0;
+ OMX_BOOL isNewFrame = OMX_FALSE;
+ OMX_BOOL generate_ebd = OMX_TRUE;
+
+ if (h264_scratch.pBuffer == NULL) {
+ DEBUG_PRINT_ERROR("ERROR:H.264 Scratch Buffer not allocated");
+ return OMX_ErrorBadParameter;
+ }
+ DEBUG_PRINT_LOW("Pending h264_scratch.nFilledLen %u "
+ "look_ahead_nal %d", (unsigned int)h264_scratch.nFilledLen, look_ahead_nal);
+ DEBUG_PRINT_LOW("Pending pdest_frame->nFilledLen %u",(unsigned int)pdest_frame->nFilledLen);
+ if (h264_scratch.nFilledLen && look_ahead_nal) {
+ look_ahead_nal = false;
+ if ((pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
+ h264_scratch.nFilledLen) {
+ memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
+ h264_scratch.pBuffer,h264_scratch.nFilledLen);
+ pdest_frame->nFilledLen += h264_scratch.nFilledLen;
+ DEBUG_PRINT_LOW("Copy the previous NAL (h264 scratch) into Dest frame");
+ h264_scratch.nFilledLen = 0;
+ } else {
+ DEBUG_PRINT_ERROR("Error:1: Destination buffer overflow for H264");
+ return OMX_ErrorBadParameter;
+ }
+ }
+
+ /* If an empty input is queued with EOS, do not coalesce with the destination-frame yet, as this may result
+ in EOS flag getting associated with the destination
+ */
+ if (!psource_frame->nFilledLen && (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) &&
+ pdest_frame->nFilledLen) {
+ DEBUG_PRINT_HIGH("delay ETB for 'empty buffer with EOS'");
+ generate_ebd = OMX_FALSE;
+ }
+
+ if (nal_length == 0) {
+ DEBUG_PRINT_LOW("Zero NAL, hence parse using start code");
+ if (m_frame_parser.parse_sc_frame(psource_frame,
+ &h264_scratch,&partial_frame) == -1) {
+ DEBUG_PRINT_ERROR("Error In Parsing Return Error");
+ return OMX_ErrorBadParameter;
+ }
+ } else {
+ DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d ",nal_length);
+ if (m_frame_parser.parse_h264_nallength(psource_frame,
+ &h264_scratch,&partial_frame) == -1) {
+ DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error");
+ return OMX_ErrorBadParameter;
+ }
+ }
+
+ if (partial_frame == 0) {
+ if (nal_count == 0 && h264_scratch.nFilledLen == 0) {
+ DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip");
+ nal_count++;
+ h264_scratch.nTimeStamp = psource_frame->nTimeStamp;
+ h264_scratch.nFlags = psource_frame->nFlags;
+ } else {
+ DEBUG_PRINT_LOW("Parsed New NAL Length = %u",(unsigned int)h264_scratch.nFilledLen);
+ if (h264_scratch.nFilledLen) {
+ h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer, h264_scratch.nFilledLen,
+ NALU_TYPE_SPS);
+#ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
+ if (client_extradata & OMX_TIMEINFO_EXTRADATA)
+ h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer,
+ h264_scratch.nFilledLen, NALU_TYPE_SEI);
+ else if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
+ // If timeinfo is present frame info from SEI is already processed
+ h264_parser->parse_nal((OMX_U8*)h264_scratch.pBuffer,
+ h264_scratch.nFilledLen, NALU_TYPE_SEI);
+#endif
+ m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame);
+ nal_count++;
+ if (VALID_TS(h264_last_au_ts) && !VALID_TS(pdest_frame->nTimeStamp)) {
+ pdest_frame->nTimeStamp = h264_last_au_ts;
+ pdest_frame->nFlags = h264_last_au_flags;
+#ifdef PANSCAN_HDLR
+ if (client_extradata & OMX_FRAMEINFO_EXTRADATA)
+ h264_parser->update_panscan_data(h264_last_au_ts);
+#endif
+ }
+ if (m_frame_parser.mutils->nalu_type == NALU_TYPE_NON_IDR ||
+ m_frame_parser.mutils->nalu_type == NALU_TYPE_IDR) {
+ h264_last_au_ts = h264_scratch.nTimeStamp;
+ h264_last_au_flags = h264_scratch.nFlags;
+#ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
+ if (client_extradata & OMX_TIMEINFO_EXTRADATA) {
+ OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(h264_last_au_ts);
+ if (!VALID_TS(h264_last_au_ts))
+ h264_last_au_ts = ts_in_sei;
+ }
+#endif
+ } else
+ h264_last_au_ts = LLONG_MAX;
+ }
+
+ if (!isNewFrame) {
+ if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
+ h264_scratch.nFilledLen) {
+ DEBUG_PRINT_LOW("Not a NewFrame Copy into Dest len %u",
+ (unsigned int)h264_scratch.nFilledLen);
+ memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
+ h264_scratch.pBuffer,h264_scratch.nFilledLen);
+ pdest_frame->nFilledLen += h264_scratch.nFilledLen;
+ if (m_frame_parser.mutils->nalu_type == NALU_TYPE_EOSEQ)
+ pdest_frame->nFlags |= QOMX_VIDEO_BUFFERFLAG_EOSEQ;
+ h264_scratch.nFilledLen = 0;
+ } else {
+ DEBUG_PRINT_LOW("Error:2: Destination buffer overflow for H264");
+ return OMX_ErrorBadParameter;
+ }
+ } else if(h264_scratch.nFilledLen) {
+ look_ahead_nal = true;
+ DEBUG_PRINT_LOW("Frame Found start Decoding Size =%u TimeStamp = %llu",
+ (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
+ DEBUG_PRINT_LOW("Found a frame size = %u number = %d",
+ (unsigned int)pdest_frame->nFilledLen,frame_count++);
+
+ if (pdest_frame->nFilledLen == 0) {
+ DEBUG_PRINT_LOW("Copy the Current Frame since and push it");
+ look_ahead_nal = false;
+ if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
+ h264_scratch.nFilledLen) {
+ memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
+ h264_scratch.pBuffer,h264_scratch.nFilledLen);
+ pdest_frame->nFilledLen += h264_scratch.nFilledLen;
+ h264_scratch.nFilledLen = 0;
+ } else {
+ DEBUG_PRINT_ERROR("Error:3: Destination buffer overflow for H264");
+ return OMX_ErrorBadParameter;
+ }
+ } else {
+ if (psource_frame->nFilledLen || h264_scratch.nFilledLen) {
+ DEBUG_PRINT_LOW("Reset the EOS Flag");
+ pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
+ }
+ /*Push the frame to the Decoder*/
+ if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
+ return OMX_ErrorBadParameter;
+ }
+ //frame_count++;
+ pdest_frame = NULL;
+ if (m_input_free_q.m_size) {
+ m_input_free_q.pop_entry(&address,&p2,&id);
+ pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
+ DEBUG_PRINT_LOW("Pop the next pdest_buffer %p",pdest_frame);
+ pdest_frame->nFilledLen = 0;
+ pdest_frame->nFlags = 0;
+ pdest_frame->nTimeStamp = LLONG_MAX;
+ }
+ }
+ }
+ }
+ } else {
+ DEBUG_PRINT_LOW("Not a Complete Frame, pdest_frame->nFilledLen %u", (unsigned int)pdest_frame->nFilledLen);
+ /*Check if Destination Buffer is full*/
+ if (h264_scratch.nAllocLen ==
+ h264_scratch.nFilledLen + h264_scratch.nOffset) {
+ DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled");
+ return OMX_ErrorStreamCorrupt;
+ }
+ }
+
+ if (!psource_frame->nFilledLen) {
+ DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client",psource_frame);
+
+ if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
+ if (pdest_frame) {
+ DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer");
+ if ( (pdest_frame->nAllocLen - pdest_frame->nFilledLen) >=
+ h264_scratch.nFilledLen) {
+ if(pdest_frame->nFilledLen == 0) {
+ /* No residual frame from before, send whatever
+ * we have left */
+ memcpy((pdest_frame->pBuffer + pdest_frame->nFilledLen),
+ h264_scratch.pBuffer, h264_scratch.nFilledLen);
+ pdest_frame->nFilledLen += h264_scratch.nFilledLen;
+ h264_scratch.nFilledLen = 0;
+ pdest_frame->nTimeStamp = h264_scratch.nTimeStamp;
+ } else {
+ m_frame_parser.mutils->isNewFrame(&h264_scratch, 0, isNewFrame);
+ if(!isNewFrame) {
+ /* Have a residual frame, but we know that the
+ * AU in this frame is belonging to whatever
+ * frame we had left over. So append it */
+ memcpy ((pdest_frame->pBuffer + pdest_frame->nFilledLen),
+ h264_scratch.pBuffer,h264_scratch.nFilledLen);
+ pdest_frame->nFilledLen += h264_scratch.nFilledLen;
+ h264_scratch.nFilledLen = 0;
+ if (h264_last_au_ts != LLONG_MAX)
+ pdest_frame->nTimeStamp = h264_last_au_ts;
+ } else {
+ /* Completely new frame, let's just push what
+ * we have now. The resulting EBD would trigger
+ * another push */
+ generate_ebd = OMX_FALSE;
+ pdest_frame->nTimeStamp = h264_last_au_ts;
+ h264_last_au_ts = h264_scratch.nTimeStamp;
+ }
+ }
+ } else {
+ DEBUG_PRINT_ERROR("ERROR:4: Destination buffer overflow for H264");
+ return OMX_ErrorBadParameter;
+ }
+
+ /* Iff we coalesced two buffers, inherit the flags of both bufs */
+ if(generate_ebd == OMX_TRUE) {
+ pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags;
+ }
+
+ DEBUG_PRINT_LOW("pdest_frame->nFilledLen =%u TimeStamp = %llu",
+ (unsigned int)pdest_frame->nFilledLen,pdest_frame->nTimeStamp);
+ DEBUG_PRINT_LOW("Push AU frame number %d to driver", frame_count++);
+#ifndef PROCESS_EXTRADATA_IN_OUTPUT_PORT
+ if (client_extradata & OMX_TIMEINFO_EXTRADATA) {
+ OMX_S64 ts_in_sei = h264_parser->process_ts_with_sei_vui(pdest_frame->nTimeStamp);
+ if (!VALID_TS(pdest_frame->nTimeStamp))
+ pdest_frame->nTimeStamp = ts_in_sei;
+ }
+#endif
+ /*Push the frame to the Decoder*/
+ if (empty_this_buffer_proxy(hComp,pdest_frame) != OMX_ErrorNone) {
+ return OMX_ErrorBadParameter;
+ }
+ frame_count++;
+ pdest_frame = NULL;
+ } else {
+ DEBUG_PRINT_LOW("Last frame in else dest addr %p size %u",
+ pdest_frame, (unsigned int)h264_scratch.nFilledLen);
+ generate_ebd = OMX_FALSE;
+ }
+ }
+ }
+ if (generate_ebd && !psource_frame->nFilledLen) {
+ m_cb.EmptyBufferDone (hComp,m_app_data,psource_frame);
+ psource_frame = NULL;
+ if (m_input_pending_q.m_size) {
+ DEBUG_PRINT_LOW("Pull Next source Buffer %p",psource_frame);
+ m_input_pending_q.pop_entry(&address,&p2,&id);
+ psource_frame = (OMX_BUFFERHEADERTYPE *) address;
+ DEBUG_PRINT_LOW("Next source Buffer flag %u src length %u",
+ (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen);
+ }
+ }
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE copy_buffer(OMX_BUFFERHEADERTYPE* pDst, OMX_BUFFERHEADERTYPE* pSrc)
+{
+ OMX_ERRORTYPE rc = OMX_ErrorNone;
+ if ((pDst->nAllocLen - pDst->nFilledLen) >= pSrc->nFilledLen) {
+ memcpy((pDst->pBuffer + pDst->nFilledLen), pSrc->pBuffer, pSrc->nFilledLen);
+ if (pDst->nTimeStamp == LLONG_MAX) {
+ pDst->nTimeStamp = pSrc->nTimeStamp;
+ DEBUG_PRINT_LOW("Assign Dst nTimeStamp = %lld", pDst->nTimeStamp);
+ }
+ pDst->nFilledLen += pSrc->nFilledLen;
+ pSrc->nFilledLen = 0;
+ } else {
+ DEBUG_PRINT_ERROR("Error: Destination buffer overflow");
+ rc = OMX_ErrorBadParameter;
+ }
+ return rc;
+}
+
+OMX_ERRORTYPE omx_vdec::push_input_hevc(OMX_HANDLETYPE hComp)
+{
+ OMX_U32 partial_frame = 1;
+ unsigned long address,p2,id;
+ OMX_BOOL isNewFrame = OMX_FALSE;
+ OMX_BOOL generate_ebd = OMX_TRUE;
+ OMX_ERRORTYPE rc = OMX_ErrorNone;
+ if (h264_scratch.pBuffer == NULL) {
+ DEBUG_PRINT_ERROR("ERROR:Hevc Scratch Buffer not allocated");
+ return OMX_ErrorBadParameter;
+ }
+
+ DEBUG_PRINT_LOW("h264_scratch.nFilledLen %u has look_ahead_nal %d \
+ pdest_frame nFilledLen %u nTimeStamp %lld",
+ (unsigned int)h264_scratch.nFilledLen, look_ahead_nal, (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
+
+ if (h264_scratch.nFilledLen && look_ahead_nal) {
+ look_ahead_nal = false;
+ rc = copy_buffer(pdest_frame, &h264_scratch);
+ if (rc != OMX_ErrorNone) {
+ return rc;
+ }
+ }
+
+ if (nal_length == 0) {
+ if (m_frame_parser.parse_sc_frame(psource_frame,
+ &h264_scratch,&partial_frame) == -1) {
+ DEBUG_PRINT_ERROR("Error In Parsing Return Error");
+ return OMX_ErrorBadParameter;
+ }
+ } else {
+ DEBUG_PRINT_LOW("Non-zero NAL length clip, hence parse with NAL size %d",nal_length);
+ if (m_frame_parser.parse_h264_nallength(psource_frame,
+ &h264_scratch,&partial_frame) == -1) {
+ DEBUG_PRINT_ERROR("Error In Parsing NAL size, Return Error");
+ return OMX_ErrorBadParameter;
+ }
+ }
+
+ if (partial_frame == 0) {
+ if (nal_count == 0 && h264_scratch.nFilledLen == 0) {
+ DEBUG_PRINT_LOW("First NAL with Zero Length, hence Skip");
+ nal_count++;
+ h264_scratch.nTimeStamp = psource_frame->nTimeStamp;
+ h264_scratch.nFlags = psource_frame->nFlags;
+ } else {
+ DEBUG_PRINT_LOW("Parsed New NAL Length = %u", (unsigned int)h264_scratch.nFilledLen);
+ if (h264_scratch.nFilledLen) {
+ m_hevc_utils.isNewFrame(&h264_scratch, 0, isNewFrame);
+ nal_count++;
+ }
+
+ if (!isNewFrame) {
+ DEBUG_PRINT_LOW("Not a new frame, copy h264_scratch nFilledLen %u \
+ nTimestamp %lld, pdest_frame nFilledLen %u nTimestamp %lld",
+ (unsigned int)h264_scratch.nFilledLen, h264_scratch.nTimeStamp,
+ (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
+ rc = copy_buffer(pdest_frame, &h264_scratch);
+ if (rc != OMX_ErrorNone) {
+ return rc;
+ }
+ } else {
+ look_ahead_nal = true;
+ if (pdest_frame->nFilledLen == 0) {
+ look_ahead_nal = false;
+ DEBUG_PRINT_LOW("dest nation buffer empty, copy scratch buffer");
+ rc = copy_buffer(pdest_frame, &h264_scratch);
+ if (rc != OMX_ErrorNone) {
+ return OMX_ErrorBadParameter;
+ }
+ } else {
+ if (psource_frame->nFilledLen || h264_scratch.nFilledLen) {
+ pdest_frame->nFlags &= ~OMX_BUFFERFLAG_EOS;
+ }
+ DEBUG_PRINT_LOW("FrameDetected # %d pdest_frame nFilledLen %u \
+ nTimeStamp %lld, look_ahead_nal in h264_scratch \
+ nFilledLen %u nTimeStamp %lld",
+ frame_count++, (unsigned int)pdest_frame->nFilledLen,
+ pdest_frame->nTimeStamp, (unsigned int)h264_scratch.nFilledLen,
+ h264_scratch.nTimeStamp);
+ if (empty_this_buffer_proxy(hComp, pdest_frame) != OMX_ErrorNone) {
+ return OMX_ErrorBadParameter;
+ }
+ pdest_frame = NULL;
+ if (m_input_free_q.m_size) {
+ m_input_free_q.pop_entry(&address, &p2, &id);
+ pdest_frame = (OMX_BUFFERHEADERTYPE *) address;
+ DEBUG_PRINT_LOW("pop the next pdest_buffer %p", pdest_frame);
+ pdest_frame->nFilledLen = 0;
+ pdest_frame->nFlags = 0;
+ pdest_frame->nTimeStamp = LLONG_MAX;
+ }
+ }
+ }
+ }
+ } else {
+ DEBUG_PRINT_LOW("psource_frame is partial nFilledLen %u nTimeStamp %lld, \
+ pdest_frame nFilledLen %u nTimeStamp %lld, h264_scratch \
+ nFilledLen %u nTimeStamp %lld",
+ (unsigned int)psource_frame->nFilledLen, psource_frame->nTimeStamp,
+ (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp,
+ (unsigned int)h264_scratch.nFilledLen, h264_scratch.nTimeStamp);
+
+ if (h264_scratch.nAllocLen ==
+ h264_scratch.nFilledLen + h264_scratch.nOffset) {
+ DEBUG_PRINT_ERROR("ERROR: Frame Not found though Destination Filled");
+ return OMX_ErrorStreamCorrupt;
+ }
+ }
+
+ if (!psource_frame->nFilledLen) {
+ DEBUG_PRINT_LOW("Buffer Consumed return source %p back to client", psource_frame);
+ if (psource_frame->nFlags & OMX_BUFFERFLAG_EOS) {
+ if (pdest_frame) {
+ DEBUG_PRINT_LOW("EOS Reached Pass Last Buffer");
+ rc = copy_buffer(pdest_frame, &h264_scratch);
+ if ( rc != OMX_ErrorNone ) {
+ return rc;
+ }
+ pdest_frame->nTimeStamp = h264_scratch.nTimeStamp;
+ pdest_frame->nFlags = h264_scratch.nFlags | psource_frame->nFlags;
+ DEBUG_PRINT_LOW("Push EOS frame number:%d nFilledLen =%u TimeStamp = %lld",
+ frame_count, (unsigned int)pdest_frame->nFilledLen, pdest_frame->nTimeStamp);
+ if (empty_this_buffer_proxy(hComp, pdest_frame) != OMX_ErrorNone) {
+ return OMX_ErrorBadParameter;
+ }
+ frame_count++;
+ pdest_frame = NULL;
+ } else {
+ DEBUG_PRINT_LOW("Last frame in else dest addr %p size %u",
+ pdest_frame, (unsigned int)h264_scratch.nFilledLen);
+ generate_ebd = OMX_FALSE;
+ }
+ }
+ }
+
+ if (generate_ebd && !psource_frame->nFilledLen) {
+ m_cb.EmptyBufferDone (hComp, m_app_data, psource_frame);
+ psource_frame = NULL;
+ if (m_input_pending_q.m_size) {
+ m_input_pending_q.pop_entry(&address, &p2, &id);
+ psource_frame = (OMX_BUFFERHEADERTYPE *)address;
+ DEBUG_PRINT_LOW("Next source Buffer flag %u nFilledLen %u, nTimeStamp %lld",
+ (unsigned int)psource_frame->nFlags, (unsigned int)psource_frame->nFilledLen, psource_frame->nTimeStamp);
+ }
+ }
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE omx_vdec::push_input_vc1(OMX_HANDLETYPE hComp)
+{
+ OMX_U8 *buf, *pdest;
+ OMX_U32 partial_frame = 1;
+ OMX_U32 buf_len, dest_len;
+
+ if (first_frame == 0) {
+ first_frame = 1;
+ DEBUG_PRINT_LOW("First i/p buffer for VC1 arbitrary bytes");
+ if (!m_vendor_config.pData) {
+ DEBUG_PRINT_LOW("Check profile type in 1st source buffer");
+ buf = psource_frame->pBuffer;
+ buf_len = psource_frame->nFilledLen;
+
+ if ((*((OMX_U32 *) buf) & VC1_SP_MP_START_CODE_MASK) ==
+ VC1_SP_MP_START_CODE) {
+ m_vc1_profile = VC1_SP_MP_RCV;
+ } else if (*((OMX_U32 *) buf) & VC1_AP_SEQ_START_CODE) {
+ m_vc1_profile = VC1_AP;
+ } else {
+ DEBUG_PRINT_ERROR("Invalid sequence layer in first buffer");
+ return OMX_ErrorStreamCorrupt;
+ }
+ } else {
+ pdest = pdest_frame->pBuffer + pdest_frame->nFilledLen +
+ pdest_frame->nOffset;
+ dest_len = pdest_frame->nAllocLen - (pdest_frame->nFilledLen +
+ pdest_frame->nOffset);
+
+ if (dest_len < m_vendor_config.nDataSize) {
+ DEBUG_PRINT_ERROR("Destination buffer full");
+ return OMX_ErrorBadParameter;
+ } else {
+ memcpy(pdest, m_vendor_config.pData, m_vendor_config.nDataSize);
+ pdest_frame->nFilledLen += m_vendor_config.nDataSize;
+ }
+ }
+ }
+
+ switch (m_vc1_profile) {
+ case VC1_AP:
+ DEBUG_PRINT_LOW("VC1 AP, hence parse using frame start code");
+ if (push_input_sc_codec(hComp) != OMX_ErrorNone) {
+ DEBUG_PRINT_ERROR("Error In Parsing VC1 AP start code");
+ return OMX_ErrorBadParameter;
+ }
+ break;
+
+ case VC1_SP_MP_RCV:
+ default:
+ DEBUG_PRINT_ERROR("Unsupported VC1 profile in ArbitraryBytes Mode");
+ return OMX_ErrorBadParameter;
+ }
+ return OMX_ErrorNone;
+}
+
+#ifndef USE_ION
+bool omx_vdec::align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size,
+ OMX_U32 alignment)
+{
+ struct pmem_allocation allocation;
+ allocation.size = buffer_size;
+ allocation.align = clip2(alignment);
+ if (allocation.align < 4096) {
+ allocation.align = 4096;
+ }
+ if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0) {
+ DEBUG_PRINT_ERROR("Aligment(%u) failed with pmem driver Sz(%lu)",
+ allocation.align, allocation.size);
+ return false;
+ }
+ return true;
+}
+#endif
+#ifdef USE_ION
+int omx_vdec::alloc_map_ion_memory(OMX_U32 buffer_size,
+ OMX_U32 alignment, struct ion_allocation_data *alloc_data,
+ struct ion_fd_data *fd_data, int flag)
+{
+ int fd = -EINVAL;
+ int rc = -EINVAL;
+ int ion_dev_flag;
+ struct vdec_ion ion_buf_info;
+ if (!alloc_data || buffer_size <= 0 || !fd_data) {
+ DEBUG_PRINT_ERROR("Invalid arguments to alloc_map_ion_memory");
+ return -EINVAL;
+ }
+ ion_dev_flag = O_RDONLY;
+ fd = open (MEM_DEVICE, ion_dev_flag);
+ if (fd < 0) {
+ DEBUG_PRINT_ERROR("opening ion device failed with fd = %d", fd);
+ return fd;
+ }
+
+ alloc_data->flags = flag;
+ alloc_data->len = buffer_size;
+ alloc_data->align = clip2(alignment);
+ if (alloc_data->align < 4096) {
+ alloc_data->align = 4096;
+ }
+
+ alloc_data->heap_id_mask = ION_HEAP(ION_IOMMU_HEAP_ID);
+ if (secure_mode && (alloc_data->flags & ION_SECURE)) {
+ alloc_data->heap_id_mask = ION_HEAP(MEM_HEAP_ID);
+ }
+
+ /* Use secure display cma heap for obvious reasons. */
+ if (alloc_data->flags & ION_FLAG_CP_BITSTREAM) {
+ alloc_data->heap_id_mask |= ION_HEAP(ION_SECURE_DISPLAY_HEAP_ID);
+ }
+
+ rc = ioctl(fd,ION_IOC_ALLOC,alloc_data);
+ if (rc || !alloc_data->handle) {
+ DEBUG_PRINT_ERROR("ION ALLOC memory failed");
+ alloc_data->handle = 0;
+ close(fd);
+ fd = -ENOMEM;
+ return fd;
+ }
+ fd_data->handle = alloc_data->handle;
+ rc = ioctl(fd,ION_IOC_MAP,fd_data);
+ if (rc) {
+ DEBUG_PRINT_ERROR("ION MAP failed ");
+ ion_buf_info.ion_alloc_data = *alloc_data;
+ ion_buf_info.ion_device_fd = fd;
+ ion_buf_info.fd_ion_data = *fd_data;
+ free_ion_memory(&ion_buf_info);
+ fd_data->fd =-1;
+ fd = -ENOMEM;
+ }
+
+ return fd;
+}
+
+void omx_vdec::free_ion_memory(struct vdec_ion *buf_ion_info)
+{
+
+ if (!buf_ion_info) {
+ DEBUG_PRINT_ERROR("ION: free called with invalid fd/allocdata");
+ return;
+ }
+ if (ioctl(buf_ion_info->ion_device_fd,ION_IOC_FREE,
+ &buf_ion_info->ion_alloc_data.handle)) {
+ DEBUG_PRINT_ERROR("ION: free failed" );
+ }
+ close(buf_ion_info->ion_device_fd);
+ buf_ion_info->ion_device_fd = -1;
+ buf_ion_info->ion_alloc_data.handle = 0;
+ buf_ion_info->fd_ion_data.fd = -1;
+}
+#endif
+void omx_vdec::free_output_buffer_header()
+{
+ DEBUG_PRINT_HIGH("ALL output buffers are freed/released");
+ output_use_buffer = false;
+ ouput_egl_buffers = false;
+
+ if (m_out_mem_ptr) {
+ free (m_out_mem_ptr);
+ m_out_mem_ptr = NULL;
+ }
+
+ if (m_platform_list) {
+ free(m_platform_list);
+ m_platform_list = NULL;
+ }
+
+ if (drv_ctx.ptr_respbuffer) {
+ free (drv_ctx.ptr_respbuffer);
+ drv_ctx.ptr_respbuffer = NULL;
+ }
+ if (drv_ctx.ptr_outputbuffer) {
+ free (drv_ctx.ptr_outputbuffer);
+ drv_ctx.ptr_outputbuffer = NULL;
+ }
+#ifdef USE_ION
+ if (drv_ctx.op_buf_ion_info) {
+ DEBUG_PRINT_LOW("Free o/p ion context");
+ free(drv_ctx.op_buf_ion_info);
+ drv_ctx.op_buf_ion_info = NULL;
+ }
+#endif
+ buf_ref_remove();
+}
+
+void omx_vdec::free_input_buffer_header()
+{
+ input_use_buffer = false;
+ if (arbitrary_bytes) {
+ if (m_inp_heap_ptr) {
+ DEBUG_PRINT_LOW("Free input Heap Pointer");
+ free (m_inp_heap_ptr);
+ m_inp_heap_ptr = NULL;
+ }
+
+ if (m_phdr_pmem_ptr) {
+ DEBUG_PRINT_LOW("Free input pmem header Pointer");
+ free (m_phdr_pmem_ptr);
+ m_phdr_pmem_ptr = NULL;
+ }
+ }
+ if (m_inp_mem_ptr) {
+ DEBUG_PRINT_LOW("Free input pmem Pointer area");
+ free (m_inp_mem_ptr);
+ m_inp_mem_ptr = NULL;
+ }
+ /* We just freed all the buffer headers, every thing in m_input_free_q,
+ * m_input_pending_q, pdest_frame, and psource_frame is now invalid */
+ while (m_input_free_q.m_size) {
+ unsigned long address, p2, id;
+ m_input_free_q.pop_entry(&address, &p2, &id);
+ }
+ while (m_input_pending_q.m_size) {
+ unsigned long address, p2, id;
+ m_input_pending_q.pop_entry(&address, &p2, &id);
+ }
+ pdest_frame = NULL;
+ psource_frame = NULL;
+ if (drv_ctx.ptr_inputbuffer) {
+ DEBUG_PRINT_LOW("Free Driver Context pointer");
+ free (drv_ctx.ptr_inputbuffer);
+ drv_ctx.ptr_inputbuffer = NULL;
+ }
+#ifdef USE_ION
+ if (drv_ctx.ip_buf_ion_info) {
+ DEBUG_PRINT_LOW("Free ion context");
+ free(drv_ctx.ip_buf_ion_info);
+ drv_ctx.ip_buf_ion_info = NULL;
+ }
+#endif
+}
+
+int omx_vdec::stream_off(OMX_U32 port)
+{
+ enum v4l2_buf_type btype;
+ int rc = 0;
+ enum v4l2_ports v4l2_port = OUTPUT_PORT;
+
+ if (port == OMX_CORE_INPUT_PORT_INDEX) {
+ btype = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ v4l2_port = OUTPUT_PORT;
+ } else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
+ btype = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ v4l2_port = CAPTURE_PORT;
+ } else if (port == OMX_ALL) {
+ int rc_input = stream_off(OMX_CORE_INPUT_PORT_INDEX);
+ int rc_output = stream_off(OMX_CORE_OUTPUT_PORT_INDEX);
+
+ if (!rc_input)
+ return rc_input;
+ else
+ return rc_output;
+ }
+
+ if (!streaming[v4l2_port]) {
+ // already streamed off, warn and move on
+ DEBUG_PRINT_HIGH("Warning: Attempting to stream off on %d port,"
+ " which is already streamed off", v4l2_port);
+ return 0;
+ }
+
+ DEBUG_PRINT_HIGH("Streaming off %d port", v4l2_port);
+
+ rc = ioctl(drv_ctx.video_driver_fd, VIDIOC_STREAMOFF, &btype);
+ if (rc) {
+ /*TODO: How to handle this case */
+ DEBUG_PRINT_ERROR("Failed to call streamoff on %d Port", v4l2_port);
+ } else {
+ streaming[v4l2_port] = false;
+ }
+
+ return rc;
+}
+
+OMX_ERRORTYPE omx_vdec::get_buffer_req(vdec_allocatorproperty *buffer_prop)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ struct v4l2_requestbuffers bufreq;
+ unsigned int buf_size = 0, extra_data_size = 0, default_extra_data_size = 0;
+ unsigned int final_extra_data_size = 0;
+ struct v4l2_format fmt;
+ int ret = 0;
+ DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)",
+ buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
+ bufreq.memory = V4L2_MEMORY_USERPTR;
+ bufreq.count = 1;
+ if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
+ bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ fmt.fmt.pix_mp.pixelformat = output_capability;
+ } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
+ bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ fmt.fmt.pix_mp.pixelformat = capture_capability;
+ } else {
+ eRet = OMX_ErrorBadParameter;
+ }
+ if (eRet==OMX_ErrorNone) {
+ ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
+ }
+ if (ret) {
+ DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
+ /*TODO: How to handle this case */
+ eRet = OMX_ErrorInsufficientResources;
+ return eRet;
+ } else {
+ bool is_res_1080p_or_below = (drv_ctx.video_resolution.frame_width <= 1920 &&
+ drv_ctx.video_resolution.frame_height <= 1088) ||
+ (drv_ctx.video_resolution.frame_height <= 1088 &&
+ drv_ctx.video_resolution.frame_width <= 1920);
+
+ int fps = drv_ctx.frame_rate.fps_numerator / (float)drv_ctx.frame_rate.fps_denominator;
+ bool fps_above_180 = (fps >= 180 || operating_frame_rate >= 180) ? true : false;
+ bool increase_output = (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) && (bufreq.count >= 16);
+
+ if (increase_output && fps_above_180 &&
+ output_capability == V4L2_PIX_FMT_H264 &&
+ is_res_1080p_or_below) {
+ high_fps = true;
+ DEBUG_PRINT_LOW("High fps - fps = %d operating_rate = %d", fps, operating_frame_rate);
+ DEBUG_PRINT_LOW("getbufreq[output]: Increase buffer count (%d) to (%d) to support high fps",
+ bufreq.count, bufreq.count + 10);
+ bufreq.count += 10;
+ ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
+ if (ret) {
+ DEBUG_PRINT_ERROR("(Failed to set updated buffer count to driver");
+ eRet = OMX_ErrorInsufficientResources;
+ return eRet;
+ }
+ DEBUG_PRINT_LOW("new buf count = %d set to driver", bufreq.count);
+ request_perf_level(VIDC_TURBO);
+ }
+
+ buffer_prop->actualcount = bufreq.count;
+ buffer_prop->mincount = bufreq.count;
+ DEBUG_PRINT_HIGH("Count = %d",bufreq.count);
+ }
+ DEBUG_PRINT_LOW("GetBufReq IN: ActCnt(%d) Size(%u)",
+ buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
+
+ ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
+
+ if (fmt.type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+ drv_ctx.num_planes = fmt.fmt.pix_mp.num_planes;
+ DEBUG_PRINT_HIGH("Buffer Size = %d",fmt.fmt.pix_mp.plane_fmt[0].sizeimage);
+
+ if (ret) {
+ /*TODO: How to handle this case */
+ DEBUG_PRINT_ERROR("Requesting buffer requirements failed");
+ eRet = OMX_ErrorInsufficientResources;
+ } else {
+ int extra_idx = 0;
+
+ eRet = is_video_session_supported();
+ if (eRet)
+ return eRet;
+
+ buffer_prop->buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
+ buf_size = buffer_prop->buffer_size;
+ extra_idx = EXTRADATA_IDX(drv_ctx.num_planes);
+ if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
+ extra_data_size = fmt.fmt.pix_mp.plane_fmt[extra_idx].sizeimage;
+ } else if (extra_idx >= VIDEO_MAX_PLANES) {
+ DEBUG_PRINT_ERROR("Extradata index is more than allowed: %d", extra_idx);
+ return OMX_ErrorBadParameter;
+ }
+
+ default_extra_data_size = VENUS_EXTRADATA_SIZE(
+ drv_ctx.video_resolution.frame_height,
+ drv_ctx.video_resolution.frame_width);
+ final_extra_data_size = extra_data_size > default_extra_data_size ?
+ extra_data_size : default_extra_data_size;
+
+ final_extra_data_size = (final_extra_data_size + buffer_prop->alignment - 1) &
+ (~(buffer_prop->alignment - 1));
+
+ drv_ctx.extradata_info.size = buffer_prop->actualcount * final_extra_data_size;
+ drv_ctx.extradata_info.count = buffer_prop->actualcount;
+ drv_ctx.extradata_info.buffer_size = final_extra_data_size;
+ buf_size = (buf_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
+ DEBUG_PRINT_LOW("GetBufReq UPDATE: ActCnt(%d) Size(%u) BufSize(%d)",
+ buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size, buf_size);
+ if (extra_data_size)
+ DEBUG_PRINT_LOW("GetBufReq UPDATE: extradata: TotalSize(%d) BufferSize(%lu)",
+ drv_ctx.extradata_info.size, drv_ctx.extradata_info.buffer_size);
+
+ if (in_reconfig) // BufReq will be set to driver when port is disabled
+ buffer_prop->buffer_size = buf_size;
+ else if (buf_size != buffer_prop->buffer_size) {
+ buffer_prop->buffer_size = buf_size;
+ eRet = set_buffer_req(buffer_prop);
+ }
+ }
+ DEBUG_PRINT_LOW("GetBufReq OUT: ActCnt(%d) Size(%u)",
+ buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
+ return eRet;
+}
+
+OMX_ERRORTYPE omx_vdec::set_buffer_req(vdec_allocatorproperty *buffer_prop)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ unsigned buf_size = 0;
+ struct v4l2_format fmt, c_fmt;
+ struct v4l2_requestbuffers bufreq;
+ int ret = 0;
+ DEBUG_PRINT_LOW("SetBufReq IN: ActCnt(%d) Size(%u)",
+ buffer_prop->actualcount, (unsigned int)buffer_prop->buffer_size);
+ buf_size = (buffer_prop->buffer_size + buffer_prop->alignment - 1)&(~(buffer_prop->alignment - 1));
+ if (buf_size != buffer_prop->buffer_size) {
+ DEBUG_PRINT_ERROR("Buffer size alignment error: Requested(%u) Required(%d)",
+ (unsigned int)buffer_prop->buffer_size, buf_size);
+ eRet = OMX_ErrorBadParameter;
+ } else {
+ memset(&fmt, 0x0, sizeof(struct v4l2_format));
+ memset(&c_fmt, 0x0, sizeof(struct v4l2_format));
+ fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
+ fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
+ fmt.fmt.pix_mp.plane_fmt[0].sizeimage = buf_size;
+
+ if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
+ fmt.type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ fmt.fmt.pix_mp.pixelformat = output_capability;
+ ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
+ } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
+ c_fmt.type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ c_fmt.fmt.pix_mp.pixelformat = capture_capability;
+ ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &c_fmt);
+ c_fmt.fmt.pix_mp.plane_fmt[0].sizeimage = buf_size;
+ ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &c_fmt);
+ } else {
+ eRet = OMX_ErrorBadParameter;
+ }
+
+ if (ret) {
+ /*TODO: How to handle this case */
+ DEBUG_PRINT_ERROR("Setting buffer requirements (format) failed %d", ret);
+ eRet = OMX_ErrorInsufficientResources;
+ }
+
+ bufreq.memory = V4L2_MEMORY_USERPTR;
+ bufreq.count = buffer_prop->actualcount;
+ if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_INPUT) {
+ bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ } else if (buffer_prop->buffer_type == VDEC_BUFFER_TYPE_OUTPUT) {
+ bufreq.type=V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ } else {
+ eRet = OMX_ErrorBadParameter;
+ }
+
+ if (eRet==OMX_ErrorNone) {
+ ret = ioctl(drv_ctx.video_driver_fd,VIDIOC_REQBUFS, &bufreq);
+ }
+
+ if (ret) {
+ DEBUG_PRINT_ERROR("Setting buffer requirements (reqbufs) failed %d", ret);
+ /*TODO: How to handle this case */
+ eRet = OMX_ErrorInsufficientResources;
+ } else if (bufreq.count < buffer_prop->actualcount) {
+ DEBUG_PRINT_ERROR("Driver refused to change the number of buffers"
+ " on v4l2 port %d to %d (prefers %d)", bufreq.type,
+ buffer_prop->actualcount, bufreq.count);
+ eRet = OMX_ErrorInsufficientResources;
+ } else {
+ if (!client_buffers.update_buffer_req()) {
+ DEBUG_PRINT_ERROR("Setting c2D buffer requirements failed");
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ }
+ }
+ return eRet;
+}
+
+OMX_ERRORTYPE omx_vdec::update_picture_resolution()
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ return eRet;
+}
+
+OMX_ERRORTYPE omx_vdec::update_portdef(OMX_PARAM_PORTDEFINITIONTYPE *portDefn)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ struct v4l2_format fmt;
+ if (!portDefn) {
+ return OMX_ErrorBadParameter;
+ }
+ DEBUG_PRINT_LOW("omx_vdec::update_portdef");
+ portDefn->nVersion.nVersion = OMX_SPEC_VERSION;
+ portDefn->nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
+ portDefn->eDomain = OMX_PortDomainVideo;
+ if (drv_ctx.frame_rate.fps_denominator > 0)
+ portDefn->format.video.xFramerate = (drv_ctx.frame_rate.fps_numerator /
+ drv_ctx.frame_rate.fps_denominator) << 16; //Q16 format
+ else {
+ DEBUG_PRINT_ERROR("Error: Divide by zero");
+ return OMX_ErrorBadParameter;
+ }
+ memset(&fmt, 0x0, sizeof(struct v4l2_format));
+ if (0 == portDefn->nPortIndex) {
+ portDefn->eDir = OMX_DirInput;
+ portDefn->nBufferCountActual = drv_ctx.ip_buf.actualcount;
+ portDefn->nBufferCountMin = drv_ctx.ip_buf.mincount;
+ portDefn->nBufferSize = drv_ctx.ip_buf.buffer_size;
+ portDefn->format.video.eColorFormat = OMX_COLOR_FormatUnused;
+ portDefn->format.video.eCompressionFormat = eCompressionFormat;
+ portDefn->bEnabled = m_inp_bEnabled;
+ portDefn->bPopulated = m_inp_bPopulated;
+
+ fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ fmt.fmt.pix_mp.pixelformat = output_capability;
+ ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
+ } else if (1 == portDefn->nPortIndex) {
+ unsigned int buf_size = 0;
+ int ret = 0;
+ if (!is_down_scalar_enabled) {
+ fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
+ fmt.fmt.pix_mp.pixelformat = capture_capability;
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
+ }
+
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ fmt.fmt.pix_mp.pixelformat = capture_capability;
+ ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
+ if (ret) {
+ DEBUG_PRINT_ERROR("Get Resolution failed");
+ return OMX_ErrorHardware;
+ }
+ drv_ctx.op_buf.buffer_size = fmt.fmt.pix_mp.plane_fmt[0].sizeimage;
+ if (!client_buffers.update_buffer_req()) {
+ DEBUG_PRINT_ERROR("client_buffers.update_buffer_req Failed");
+ return OMX_ErrorHardware;
+ }
+
+ if (!client_buffers.get_buffer_req(buf_size)) {
+ DEBUG_PRINT_ERROR("update buffer requirements");
+ return OMX_ErrorHardware;
+ }
+ portDefn->nBufferSize = buf_size;
+ portDefn->eDir = OMX_DirOutput;
+ portDefn->nBufferCountActual = drv_ctx.op_buf.actualcount;
+ portDefn->nBufferCountMin = drv_ctx.op_buf.mincount;
+ portDefn->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
+ portDefn->bEnabled = m_out_bEnabled;
+ portDefn->bPopulated = m_out_bPopulated;
+ if (!client_buffers.get_color_format(portDefn->format.video.eColorFormat)) {
+ DEBUG_PRINT_ERROR("Error in getting color format");
+ return OMX_ErrorHardware;
+ }
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ fmt.fmt.pix_mp.pixelformat = capture_capability;
+ } else {
+ portDefn->eDir = OMX_DirMax;
+ DEBUG_PRINT_LOW(" get_parameter: Bad Port idx %d",
+ (int)portDefn->nPortIndex);
+ eRet = OMX_ErrorBadPortIndex;
+ }
+ update_resolution(fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
+ fmt.fmt.pix_mp.plane_fmt[0].bytesperline, fmt.fmt.pix_mp.plane_fmt[0].reserved[0]);
+
+ portDefn->format.video.nFrameHeight = drv_ctx.video_resolution.frame_height;
+ portDefn->format.video.nFrameWidth = drv_ctx.video_resolution.frame_width;
+ portDefn->format.video.nStride = drv_ctx.video_resolution.stride;
+ portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.scan_lines;
+
+ if ((portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420Planar) ||
+ (portDefn->format.video.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar)) {
+ portDefn->format.video.nStride = ALIGN(drv_ctx.video_resolution.frame_width, 16);
+ portDefn->format.video.nSliceHeight = drv_ctx.video_resolution.frame_height;
+ }
+ DEBUG_PRINT_HIGH("update_portdef(%u): Width = %u Height = %u Stride = %d "
+ "SliceHeight = %u eColorFormat = %d nBufSize %u nBufCnt %u",
+ (unsigned int)portDefn->nPortIndex,
+ (unsigned int)portDefn->format.video.nFrameWidth,
+ (unsigned int)portDefn->format.video.nFrameHeight,
+ (int)portDefn->format.video.nStride,
+ (unsigned int)portDefn->format.video.nSliceHeight,
+ (unsigned int)portDefn->format.video.eColorFormat,
+ (unsigned int)portDefn->nBufferSize,
+ (unsigned int)portDefn->nBufferCountActual);
+
+ return eRet;
+}
+
+OMX_ERRORTYPE omx_vdec::allocate_output_headers()
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ OMX_BUFFERHEADERTYPE *bufHdr = NULL;
+ unsigned i= 0;
+
+ if (!m_out_mem_ptr) {
+ DEBUG_PRINT_HIGH("Use o/p buffer case - Header List allocation");
+ int nBufHdrSize = 0;
+ int nPlatformEntrySize = 0;
+ int nPlatformListSize = 0;
+ int nPMEMInfoSize = 0;
+ OMX_QCOM_PLATFORM_PRIVATE_LIST *pPlatformList;
+ OMX_QCOM_PLATFORM_PRIVATE_ENTRY *pPlatformEntry;
+ OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo;
+
+ DEBUG_PRINT_LOW("Setting First Output Buffer(%d)",
+ drv_ctx.op_buf.actualcount);
+ nBufHdrSize = drv_ctx.op_buf.actualcount *
+ sizeof(OMX_BUFFERHEADERTYPE);
+
+ nPMEMInfoSize = drv_ctx.op_buf.actualcount *
+ sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
+ nPlatformListSize = drv_ctx.op_buf.actualcount *
+ sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
+ nPlatformEntrySize = drv_ctx.op_buf.actualcount *
+ sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
+
+ DEBUG_PRINT_LOW("TotalBufHdr %d BufHdrSize %u PMEM %d PL %d",nBufHdrSize,
+ (unsigned int)sizeof(OMX_BUFFERHEADERTYPE),
+ nPMEMInfoSize,
+ nPlatformListSize);
+ DEBUG_PRINT_LOW("PE %d bmSize % " PRId64 , nPlatformEntrySize,
+ m_out_bm_count);
+ m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1);
+ // Alloc mem for platform specific info
+ char *pPtr=NULL;
+ pPtr = (char*) calloc(nPlatformListSize + nPlatformEntrySize +
+ nPMEMInfoSize,1);
+ drv_ctx.ptr_outputbuffer = (struct vdec_bufferpayload *) \
+ calloc (sizeof(struct vdec_bufferpayload),
+ drv_ctx.op_buf.actualcount);
+ drv_ctx.ptr_respbuffer = (struct vdec_output_frameinfo *)\
+ calloc (sizeof (struct vdec_output_frameinfo),
+ drv_ctx.op_buf.actualcount);
+ if (!drv_ctx.ptr_outputbuffer || !drv_ctx.ptr_respbuffer) {
+ DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.ptr_outputbuffer or drv_ctx.ptr_respbuffer");
+ return OMX_ErrorInsufficientResources;
+ }
+
+#ifdef USE_ION
+ drv_ctx.op_buf_ion_info = (struct vdec_ion * ) \
+ calloc (sizeof(struct vdec_ion),drv_ctx.op_buf.actualcount);
+ if (!drv_ctx.op_buf_ion_info) {
+ DEBUG_PRINT_ERROR("Failed to alloc drv_ctx.op_buf_ion_info");
+ return OMX_ErrorInsufficientResources;
+ }
+#endif
+ if (dynamic_buf_mode) {
+ out_dynamic_list = (struct dynamic_buf_list *) \
+ calloc (sizeof(struct dynamic_buf_list), drv_ctx.op_buf.actualcount);
+ if (out_dynamic_list) {
+ for (unsigned int i = 0; i < drv_ctx.op_buf.actualcount; i++)
+ out_dynamic_list[i].dup_fd = -1;
+ }
+ }
+
+ if (m_out_mem_ptr && pPtr && drv_ctx.ptr_outputbuffer
+ && drv_ctx.ptr_respbuffer) {
+ bufHdr = m_out_mem_ptr;
+ m_platform_list = (OMX_QCOM_PLATFORM_PRIVATE_LIST *)(pPtr);
+ m_platform_entry= (OMX_QCOM_PLATFORM_PRIVATE_ENTRY *)
+ (((char *) m_platform_list) + nPlatformListSize);
+ m_pmem_info = (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *)
+ (((char *) m_platform_entry) + nPlatformEntrySize);
+ pPlatformList = m_platform_list;
+ pPlatformEntry = m_platform_entry;
+ pPMEMInfo = m_pmem_info;
+
+ DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr);
+
+ // Settting the entire storage nicely
+ DEBUG_PRINT_LOW("bHdr %p OutMem %p PE %p",bufHdr,
+ m_out_mem_ptr,pPlatformEntry);
+ DEBUG_PRINT_LOW(" Pmem Info = %p",pPMEMInfo);
+ for (i=0; i < drv_ctx.op_buf.actualcount ; i++) {
+ bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
+ bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
+ // Set the values when we determine the right HxW param
+ bufHdr->nAllocLen = 0;
+ bufHdr->nFilledLen = 0;
+ bufHdr->pAppPrivate = NULL;
+ bufHdr->nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
+ pPlatformEntry->type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
+ pPlatformEntry->entry = pPMEMInfo;
+ // Initialize the Platform List
+ pPlatformList->nEntries = 1;
+ pPlatformList->entryList = pPlatformEntry;
+ // Keep pBuffer NULL till vdec is opened
+ bufHdr->pBuffer = NULL;
+ pPMEMInfo->offset = 0;
+ pPMEMInfo->pmem_fd = -1;
+ bufHdr->pPlatformPrivate = pPlatformList;
+ drv_ctx.ptr_outputbuffer[i].pmem_fd = -1;
+#ifdef USE_ION
+ drv_ctx.op_buf_ion_info[i].ion_device_fd =-1;
+#endif
+ /*Create a mapping between buffers*/
+ bufHdr->pOutputPortPrivate = &drv_ctx.ptr_respbuffer[i];
+ drv_ctx.ptr_respbuffer[i].client_data = (void *) \
+ &drv_ctx.ptr_outputbuffer[i];
+ // Move the buffer and buffer header pointers
+ bufHdr++;
+ pPMEMInfo++;
+ pPlatformEntry++;
+ pPlatformList++;
+ }
+ } else {
+ DEBUG_PRINT_ERROR("Output buf mem alloc failed[0x%p][0x%p]",\
+ m_out_mem_ptr, pPtr);
+ if (m_out_mem_ptr) {
+ free(m_out_mem_ptr);
+ m_out_mem_ptr = NULL;
+ }
+ if (pPtr) {
+ free(pPtr);
+ pPtr = NULL;
+ }
+ if (drv_ctx.ptr_outputbuffer) {
+ free(drv_ctx.ptr_outputbuffer);
+ drv_ctx.ptr_outputbuffer = NULL;
+ }
+ if (drv_ctx.ptr_respbuffer) {
+ free(drv_ctx.ptr_respbuffer);
+ drv_ctx.ptr_respbuffer = NULL;
+ }
+#ifdef USE_ION
+ if (drv_ctx.op_buf_ion_info) {
+ DEBUG_PRINT_LOW("Free o/p ion context");
+ free(drv_ctx.op_buf_ion_info);
+ drv_ctx.op_buf_ion_info = NULL;
+ }
+#endif
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ } else {
+ eRet = OMX_ErrorInsufficientResources;
+ }
+ return eRet;
+}
+
+void omx_vdec::complete_pending_buffer_done_cbs()
+{
+ unsigned long p1, p2, ident;
+ omx_cmd_queue tmp_q, pending_bd_q;
+ pthread_mutex_lock(&m_lock);
+ // pop all pending GENERATE FDB from ftb queue
+ while (m_ftb_q.m_size) {
+ m_ftb_q.pop_entry(&p1,&p2,&ident);
+ if (ident == OMX_COMPONENT_GENERATE_FBD) {
+ pending_bd_q.insert_entry(p1,p2,ident);
+ } else {
+ tmp_q.insert_entry(p1,p2,ident);
+ }
+ }
+ //return all non GENERATE FDB to ftb queue
+ while (tmp_q.m_size) {
+ tmp_q.pop_entry(&p1,&p2,&ident);
+ m_ftb_q.insert_entry(p1,p2,ident);
+ }
+ // pop all pending GENERATE EDB from etb queue
+ while (m_etb_q.m_size) {
+ m_etb_q.pop_entry(&p1,&p2,&ident);
+ if (ident == OMX_COMPONENT_GENERATE_EBD) {
+ pending_bd_q.insert_entry(p1,p2,ident);
+ } else {
+ tmp_q.insert_entry(p1,p2,ident);
+ }
+ }
+ //return all non GENERATE FDB to etb queue
+ while (tmp_q.m_size) {
+ tmp_q.pop_entry(&p1,&p2,&ident);
+ m_etb_q.insert_entry(p1,p2,ident);
+ }
+ pthread_mutex_unlock(&m_lock);
+ // process all pending buffer dones
+ while (pending_bd_q.m_size) {
+ pending_bd_q.pop_entry(&p1,&p2,&ident);
+ switch (ident) {
+ case OMX_COMPONENT_GENERATE_EBD:
+ if (empty_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) {
+ DEBUG_PRINT_ERROR("ERROR: empty_buffer_done() failed!");
+ omx_report_error ();
+ }
+ break;
+
+ case OMX_COMPONENT_GENERATE_FBD:
+ if (fill_buffer_done(&m_cmp, (OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) {
+ DEBUG_PRINT_ERROR("ERROR: fill_buffer_done() failed!");
+ omx_report_error ();
+ }
+ break;
+ }
+ }
+}
+
+void omx_vdec::set_frame_rate(OMX_S64 act_timestamp)
+{
+ OMX_U32 new_frame_interval = 0;
+ if (VALID_TS(act_timestamp) && VALID_TS(prev_ts) && act_timestamp != prev_ts
+ && llabs(act_timestamp - prev_ts) > 2000) {
+ new_frame_interval = client_set_fps ? frm_int : (act_timestamp - prev_ts) > 0 ?
+ llabs(act_timestamp - prev_ts) : llabs(act_timestamp - prev_ts_actual);
+ if (new_frame_interval != frm_int || frm_int == 0) {
+ frm_int = new_frame_interval;
+ if (frm_int) {
+ drv_ctx.frame_rate.fps_numerator = 1e6;
+ drv_ctx.frame_rate.fps_denominator = frm_int;
+ DEBUG_PRINT_LOW("set_frame_rate: frm_int(%u) fps(%f)",
+ (unsigned int)frm_int, drv_ctx.frame_rate.fps_numerator /
+ (float)drv_ctx.frame_rate.fps_denominator);
+ m_perf_control.request_cores(frm_int);
+ /* We need to report the difference between this FBD and the previous FBD
+ * back to the driver for clock scaling purposes. */
+ struct v4l2_outputparm oparm;
+ /*XXX: we're providing timing info as seconds per frame rather than frames
+ * per second.*/
+ oparm.timeperframe.numerator = drv_ctx.frame_rate.fps_denominator;
+ oparm.timeperframe.denominator = drv_ctx.frame_rate.fps_numerator;
+
+ struct v4l2_streamparm sparm;
+ sparm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ sparm.parm.output = oparm;
+ if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_PARM, &sparm)) {
+ DEBUG_PRINT_ERROR("Unable to convey fps info to driver, \
+ performance might be affected");
+ }
+
+ }
+ }
+ }
+ prev_ts = act_timestamp;
+}
+
+void omx_vdec::adjust_timestamp(OMX_S64 &act_timestamp)
+{
+ if (rst_prev_ts && VALID_TS(act_timestamp)) {
+ prev_ts = act_timestamp;
+ prev_ts_actual = act_timestamp;
+ rst_prev_ts = false;
+ } else if (VALID_TS(prev_ts)) {
+ bool codec_cond = (drv_ctx.timestamp_adjust)?
+ (!VALID_TS(act_timestamp) || act_timestamp < prev_ts_actual || llabs(act_timestamp - prev_ts_actual) <= 2000) :
+ (!VALID_TS(act_timestamp) || act_timestamp <= prev_ts_actual);
+ prev_ts_actual = act_timestamp; //unadjusted previous timestamp
+ if (frm_int > 0 && codec_cond) {
+ DEBUG_PRINT_LOW("adjust_timestamp: original ts[%lld]", act_timestamp);
+ act_timestamp = prev_ts + frm_int;
+ DEBUG_PRINT_LOW("adjust_timestamp: predicted ts[%lld]", act_timestamp);
+ prev_ts = act_timestamp;
+ } else {
+ if (drv_ctx.picture_order == VDEC_ORDER_DISPLAY && act_timestamp < prev_ts) {
+ // ensure that timestamps can never step backwards when in display order
+ act_timestamp = prev_ts;
+ }
+ set_frame_rate(act_timestamp);
+ }
+ } else if (frm_int > 0) // In this case the frame rate was set along
+ { // with the port definition, start ts with 0
+ act_timestamp = prev_ts = 0; // and correct if a valid ts is received.
+ rst_prev_ts = true;
+ }
+}
+
+OMX_BUFFERHEADERTYPE* omx_vdec::get_omx_output_buffer_header(int index)
+{
+ return m_out_mem_ptr + index;
+}
+
+void omx_vdec::convert_color_space_info(OMX_U32 primaries, OMX_U32 range,
+ OMX_U32 transfer, OMX_U32 matrix, ColorSpace_t *color_space, ColorAspects *aspects)
+{
+ switch (primaries) {
+ case MSM_VIDC_BT709_5:
+ *color_space = ITU_R_709;
+ aspects->mPrimaries = ColorAspects::PrimariesBT709_5;
+ break;
+ case MSM_VIDC_BT470_6_M:
+ aspects->mPrimaries = ColorAspects::PrimariesBT470_6M;
+ break;
+ case MSM_VIDC_BT601_6_625:
+ aspects->mPrimaries = ColorAspects::PrimariesBT601_6_625;
+ break;
+ case MSM_VIDC_BT601_6_525:
+ *color_space = range ? ITU_R_601_FR : ITU_R_601;
+ aspects->mPrimaries = ColorAspects::PrimariesBT601_6_525;
+ break;
+ case MSM_VIDC_GENERIC_FILM:
+ aspects->mPrimaries = ColorAspects::PrimariesGenericFilm;
+ break;
+ case MSM_VIDC_BT2020:
+ aspects->mPrimaries = ColorAspects::PrimariesBT2020;
+ break;
+ case MSM_VIDC_UNSPECIFIED:
+ //Client does not expect ColorAspects::PrimariesUnspecified, but rather the supplied default
+ default:
+ //aspects->mPrimaries = ColorAspects::PrimariesOther;
+ aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries;
+ break;
+ }
+
+ aspects->mRange = range ? ColorAspects::RangeFull : ColorAspects::RangeLimited;
+
+ switch (transfer) {
+ case MSM_VIDC_TRANSFER_BT709_5:
+ case MSM_VIDC_TRANSFER_601_6_525: // case MSM_VIDC_TRANSFER_601_6_625:
+ aspects->mTransfer = ColorAspects::TransferSMPTE170M;
+ break;
+ case MSM_VIDC_TRANSFER_BT_470_6_M:
+ aspects->mTransfer = ColorAspects::TransferGamma22;
+ break;
+ case MSM_VIDC_TRANSFER_BT_470_6_BG:
+ aspects->mTransfer = ColorAspects::TransferGamma28;
+ break;
+ case MSM_VIDC_TRANSFER_SMPTE_240M:
+ aspects->mTransfer = ColorAspects::TransferSMPTE240M;
+ break;
+ case MSM_VIDC_TRANSFER_LINEAR:
+ aspects->mTransfer = ColorAspects::TransferLinear;
+ break;
+ case MSM_VIDC_TRANSFER_IEC_61966:
+ aspects->mTransfer = ColorAspects::TransferXvYCC;
+ break;
+ case MSM_VIDC_TRANSFER_BT_1361:
+ aspects->mTransfer = ColorAspects::TransferBT1361;
+ break;
+ case MSM_VIDC_TRANSFER_SRGB:
+ aspects->mTransfer = ColorAspects::TransferSRGB;
+ break;
+ default:
+ //aspects->mTransfer = ColorAspects::TransferOther;
+ aspects->mTransfer = m_client_color_space.sAspects.mTransfer;
+ break;
+ }
+
+ switch (matrix) {
+ case MSM_VIDC_MATRIX_BT_709_5:
+ aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
+ break;
+ case MSM_VIDC_MATRIX_FCC_47:
+ aspects->mMatrixCoeffs = ColorAspects::MatrixBT470_6M;
+ break;
+ case MSM_VIDC_MATRIX_601_6_625:
+ case MSM_VIDC_MATRIX_601_6_525:
+ aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6;
+ break;
+ case MSM_VIDC_MATRIX_SMPTE_240M:
+ aspects->mMatrixCoeffs = ColorAspects::MatrixSMPTE240M;
+ break;
+ case MSM_VIDC_MATRIX_BT_2020:
+ aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020;
+ break;
+ case MSM_VIDC_MATRIX_BT_2020_CONST:
+ aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020Constant;
+ break;
+ default:
+ //aspects->mMatrixCoeffs = ColorAspects::MatrixOther;
+ aspects->mMatrixCoeffs = m_client_color_space.sAspects.mMatrixCoeffs;
+ break;
+ }
+}
+
+void omx_vdec::print_debug_color_aspects(ColorAspects *aspects, const char *prefix) {
+ DEBUG_PRINT_HIGH("%s : Color aspects : Primaries = %d Range = %d Transfer = %d MatrixCoeffs = %d",
+ prefix, aspects->mPrimaries, aspects->mRange, aspects->mTransfer, aspects->mMatrixCoeffs);
+}
+
+void omx_vdec::handle_color_space_info(void *data, unsigned int buf_index)
+{
+ ColorSpace_t color_space = ITU_R_601;
+ ColorAspects tempAspects;
+ memset(&tempAspects, 0x0, sizeof(ColorAspects));
+ ColorAspects *aspects = &tempAspects;
+
+ switch(output_capability) {
+ case V4L2_PIX_FMT_MPEG2:
+ {
+ struct msm_vidc_mpeg2_seqdisp_payload *seqdisp_payload;
+ seqdisp_payload = (struct msm_vidc_mpeg2_seqdisp_payload *)data;
+
+ /* Refer MPEG2 Spec @ Rec. ISO/IEC 13818-2, ITU-T Draft Rec. H.262 to
+ * understand this code */
+
+ if (seqdisp_payload && seqdisp_payload->color_descp) {
+
+ convert_color_space_info(seqdisp_payload->color_primaries, 1,
+ seqdisp_payload->transfer_char, seqdisp_payload->matrix_coeffs,
+ &color_space,aspects);
+ m_disp_hor_size = seqdisp_payload->disp_width;
+ m_disp_vert_size = seqdisp_payload->disp_height;
+ }
+ }
+ break;
+ case V4L2_PIX_FMT_H264:
+ case V4L2_PIX_FMT_HEVC:
+ {
+ struct msm_vidc_vui_display_info_payload *display_info_payload;
+ display_info_payload = (struct msm_vidc_vui_display_info_payload*)data;
+
+ /* Refer H264 Spec @ Rec. ITU-T H.264 (02/2014) to understand this code */
+
+ if (display_info_payload->video_signal_present_flag &&
+ display_info_payload->color_description_present_flag) {
+ convert_color_space_info(display_info_payload->color_primaries,
+ display_info_payload->video_full_range_flag,
+ display_info_payload->transfer_characteristics,
+ display_info_payload->matrix_coefficients,
+ &color_space,aspects);
+ }
+ }
+ break;
+ case V4L2_PIX_FMT_VC1_ANNEX_G:
+ case V4L2_PIX_FMT_VC1_ANNEX_L:
+ {
+ struct msm_vidc_vc1_seqdisp_payload *vc1_seq_disp_payload;
+ vc1_seq_disp_payload = (struct msm_vidc_vc1_seqdisp_payload*)data;
+
+ /* Refer VC-1 Spec @ SMPTE Draft Standard for Television Date: 2005-08-23
+ * SMPTE 421M to understand this code */
+
+ if (m_enable_android_native_buffers &&
+ vc1_seq_disp_payload->color_primaries) {
+
+ convert_color_space_info(vc1_seq_disp_payload->color_primaries,
+ 1,
+ vc1_seq_disp_payload->transfer_char,
+ vc1_seq_disp_payload->matrix_coeffs,
+ &color_space,aspects);
+ }
+ }
+ break;
+ case V4L2_PIX_FMT_VP8:
+ {
+ struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload;
+ vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data;
+
+ /* Refer VP8 Data Format in latest VP8 spec and Decoding Guide November 2011
+ * to understand this code */
+
+ if (vpx_color_space_payload->color_space == 0) {
+ color_space = ITU_R_601;
+ } else {
+ DEBUG_PRINT_ERROR("Unsupported Color space for VP8");
+ break;
+ }
+ }
+ break;
+ case V4L2_PIX_FMT_VP9:
+ {
+ struct msm_vidc_vpx_colorspace_payload *vpx_color_space_payload;
+ vpx_color_space_payload = (struct msm_vidc_vpx_colorspace_payload*)data;
+
+ /* Refer VP9 Spec @ VP9 Bitstream & Decoding Process Specification - v0.6 31st March 2016
+ * to understand this code */
+
+ switch(vpx_color_space_payload->color_space) {
+ case MSM_VIDC_CS_BT_601:
+ aspects->mMatrixCoeffs = ColorAspects::MatrixBT601_6;
+ aspects->mTransfer = ColorAspects::TransferSMPTE170M;
+ aspects->mPrimaries = ColorAspects::PrimariesBT601_6_625;
+ aspects->mRange = m_client_color_space.sAspects.mRange;
+ break;
+ case MSM_VIDC_CS_BT_709:
+ color_space = ITU_R_709;
+ aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
+ aspects->mTransfer = ColorAspects::TransferSMPTE170M;
+ aspects->mPrimaries = ColorAspects::PrimariesBT709_5;
+ aspects->mRange = m_client_color_space.sAspects.mRange;
+ break;
+ case MSM_VIDC_CS_SMPTE_170:
+ aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
+ aspects->mTransfer = ColorAspects::TransferSMPTE170M;
+ aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries;
+ aspects->mRange = m_client_color_space.sAspects.mRange;
+ break;
+ case MSM_VIDC_CS_SMPTE_240:
+ aspects->mMatrixCoeffs = m_client_color_space.sAspects.mMatrixCoeffs;
+ aspects->mTransfer = ColorAspects::TransferSMPTE240M;
+ aspects->mPrimaries = m_client_color_space.sAspects.mPrimaries;
+ aspects->mRange = m_client_color_space.sAspects.mRange;
+ break;
+ case MSM_VIDC_CS_BT_2020:
+ aspects->mMatrixCoeffs = ColorAspects::MatrixBT2020;
+ aspects->mTransfer = ColorAspects:: TransferSMPTE170M;
+ aspects->mPrimaries = ColorAspects::PrimariesBT2020;
+ aspects->mRange = m_client_color_space.sAspects.mRange;
+ break;
+ case MSM_VIDC_CS_RESERVED:
+ aspects->mMatrixCoeffs = ColorAspects::MatrixOther;
+ aspects->mTransfer = ColorAspects::TransferOther;
+ aspects->mPrimaries = ColorAspects::PrimariesOther;
+ aspects->mRange = m_client_color_space.sAspects.mRange;
+ break;
+ case MSM_VIDC_CS_RGB:
+ aspects->mMatrixCoeffs = ColorAspects::MatrixBT709_5;
+ aspects->mTransfer = ColorAspects::TransferSMPTE170M;
+ aspects->mPrimaries = ColorAspects::PrimariesOther;
+ aspects->mRange = m_client_color_space.sAspects.mRange;
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ if (m_enable_android_native_buffers) {
+ DEBUG_PRINT_HIGH("setMetaData for Color Space = 0x%x (601=%u FR=%u 709=%u)", color_space, ITU_R_601, ITU_R_601_FR, ITU_R_709);
+ set_colorspace_in_handle(color_space, buf_index);
+ }
+ print_debug_color_aspects(aspects, "Bitstream");
+
+ if (m_internal_color_space.sAspects.mPrimaries != aspects->mPrimaries ||
+ m_internal_color_space.sAspects.mTransfer != aspects->mTransfer ||
+ m_internal_color_space.sAspects.mMatrixCoeffs != aspects->mMatrixCoeffs ||
+ m_internal_color_space.sAspects.mRange != aspects->mRange) {
+ memcpy(&(m_internal_color_space.sAspects), aspects, sizeof(ColorAspects));
+ m_internal_color_space.bDataSpaceChanged = OMX_TRUE;
+
+ DEBUG_PRINT_HIGH("Initiating PORT Reconfig");
+ print_debug_color_aspects(&(m_internal_color_space.sAspects), "Internal");
+ print_debug_color_aspects(&(m_client_color_space.sAspects), "Client");
+
+ post_event(OMX_CORE_OUTPUT_PORT_INDEX,
+ OMX_QTIIndexConfigDescribeColorAspects,
+ OMX_COMPONENT_GENERATE_PORT_RECONFIG);
+ }
+}
+
+void omx_vdec::set_colorspace_in_handle(ColorSpace_t color_space, unsigned int buf_index) {
+ private_handle_t *private_handle = NULL;
+ if (buf_index < drv_ctx.op_buf.actualcount &&
+ buf_index < MAX_NUM_INPUT_OUTPUT_BUFFERS &&
+ native_buffer[buf_index].privatehandle) {
+ private_handle = native_buffer[buf_index].privatehandle;
+ }
+ if (private_handle) {
+ setMetaData(private_handle, UPDATE_COLOR_SPACE, (void*)&color_space);
+ }
+}
+
+void omx_vdec::handle_extradata(OMX_BUFFERHEADERTYPE *p_buf_hdr)
+{
+ OMX_OTHER_EXTRADATATYPE *p_extra = NULL, *p_sei = NULL, *p_vui = NULL, *p_client_extra = NULL;
+ OMX_U8 *pBuffer = NULL;
+ OMX_U32 num_conceal_MB = 0;
+ OMX_TICKS time_stamp = 0;
+ OMX_U32 frame_rate = 0;
+ unsigned long consumed_len = 0;
+ OMX_U32 num_MB_in_frame;
+ OMX_U32 recovery_sei_flags = 1;
+ int enable = OMX_InterlaceFrameProgressive;
+
+ if (output_flush_progress)
+ return;
+
+ 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;
+
+ if (drv_ctx.ptr_outputbuffer[buf_index].bufferaddr == NULL) {
+ DEBUG_PRINT_ERROR("handle_extradata: Error: Mapped output buffer address is NULL");
+ return;
+ }
+
+ if (!drv_ctx.extradata_info.uaddr) {
+ DEBUG_PRINT_HIGH("NULL drv_ctx.extradata_info.uaddr");
+ return;
+ }
+ if (!secure_mode && (drv_ctx.extradata_info.buffer_size > (p_buf_hdr->nAllocLen - p_buf_hdr->nFilledLen)) ) {
+ DEBUG_PRINT_ERROR("Error: Insufficient size allocated for extra-data");
+ p_extra = NULL;
+ return;
+ }
+ if (!secure_mode) {
+ pBuffer = (OMX_U8*)mmap(0, drv_ctx.ptr_outputbuffer[buf_index].buffer_len,
+ PROT_READ|PROT_WRITE, MAP_SHARED, drv_ctx.ptr_outputbuffer[buf_index].pmem_fd, 0);
+ if (pBuffer == MAP_FAILED) {
+ DEBUG_PRINT_ERROR("handle_extradata output buffer mmap failed - errno: %d", errno);
+ return;
+ }
+ p_extra = (OMX_OTHER_EXTRADATATYPE *)
+ ((unsigned long)(pBuffer + p_buf_hdr->nOffset + p_buf_hdr->nFilledLen + 3)&(~3));
+ } else
+ p_extra = m_other_extradata;
+
+ AutoUnmap autounmap(pBuffer, drv_ctx.ptr_outputbuffer[buf_index].buffer_len);
+ if (m_client_extradata_info.getBase() &&
+ m_client_extradata_info.getSize() >= drv_ctx.extradata_info.buffer_size) {
+ p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (m_client_extradata_info.getBase() +
+ buf_index * m_client_extradata_info.getSize());
+ }
+
+ char *p_extradata = drv_ctx.extradata_info.uaddr + buf_index * drv_ctx.extradata_info.buffer_size;
+
+ if (!secure_mode && ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen))) {
+ p_extra = NULL;
+ DEBUG_PRINT_ERROR("Error: out of bound memory access by p_extra");
+ return;
+ }
+ m_extradata_info.output_crop_updated = OMX_FALSE;
+ OMX_OTHER_EXTRADATATYPE *data = (struct OMX_OTHER_EXTRADATATYPE *)p_extradata;
+ if (data && p_extra) {
+ while ((consumed_len < drv_ctx.extradata_info.buffer_size)
+ && (data->eType != (OMX_EXTRADATATYPE)MSM_VIDC_EXTRADATA_NONE)) {
+ if ((consumed_len + data->nSize) > (unsigned)drv_ctx.extradata_info.buffer_size) {
+ DEBUG_PRINT_LOW("Invalid extra data size");
+ break;
+ }
+
+ if (!secure_mode && ((OMX_U8*)p_extra > (pBuffer + p_buf_hdr->nAllocLen))) {
+ p_extra = NULL;
+ DEBUG_PRINT_ERROR("Error: out of bound memory access by p_extra");
+ return;
+ }
+
+ DEBUG_PRINT_LOW("handle_extradata: eType = 0x%x", data->eType);
+ switch ((unsigned long)data->eType) {
+ case MSM_VIDC_EXTRADATA_INTERLACE_VIDEO:
+ struct msm_vidc_interlace_payload *payload;
+ OMX_U32 interlace_color_format;
+ payload = (struct msm_vidc_interlace_payload *)(void *)data->data;
+ if (payload) {
+ enable = OMX_InterlaceFrameProgressive;
+ switch (payload->format) {
+ case MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE:
+ drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
+ break;
+ case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST:
+ drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
+ enable = OMX_InterlaceInterleaveFrameTopFieldFirst;
+ break;
+ case MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST:
+ drv_ctx.interlace = VDEC_InterlaceInterleaveFrameBottomFieldFirst;
+ enable = OMX_InterlaceInterleaveFrameBottomFieldFirst;
+ break;
+ default:
+ DEBUG_PRINT_LOW("default case - set to progressive");
+ drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
+ }
+ switch (payload->color_format) {
+ case MSM_VIDC_HAL_INTERLACE_COLOR_FORMAT_NV12:
+ interlace_color_format = (int)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
+ break;
+ case MSM_VIDC_HAL_INTERLACE_COLOR_FORMAT_NV12_UBWC:
+ interlace_color_format = (int)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed;
+ break;
+ default:
+ interlace_color_format = (int)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
+ DEBUG_PRINT_ERROR("Error - Unknown color format hint for interlaced frame");
+ }
+ }
+
+ if (m_enable_android_native_buffers) {
+ DEBUG_PRINT_LOW("setMetaData INTERLACED format:%d color_format: %x enable:%d mbaff:%d",
+ payload->format, interlace_color_format ,enable,
+ (p_buf_hdr->nFlags & QOMX_VIDEO_BUFFERFLAG_MBAFF)?true:false);
+
+ setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
+ PP_PARAM_INTERLACED, (void*)&enable);
+
+ if (interlace_color_format == QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m) {
+ setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
+ LINEAR_FORMAT, (void*)&interlace_color_format);
+ } else if (interlace_color_format == QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) {
+ setMetaData((private_handle_t *)native_buffer[buf_index].privatehandle,
+ LINEAR_FORMAT, NULL);
+ }
+ }
+ if (client_extradata & OMX_INTERLACE_EXTRADATA) {
+ append_interlace_extradata(p_extra, payload->format);
+ p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
+ if (p_client_extra) {
+ append_interlace_extradata(p_client_extra, payload->format);
+ p_client_extra = (OMX_OTHER_EXTRADATATYPE *)
+ (((OMX_U8 *)p_client_extra) + ALIGN(p_client_extra->nSize, 4));
+ }
+ }
+ break;
+ case MSM_VIDC_EXTRADATA_FRAME_RATE:
+ struct msm_vidc_framerate_payload *frame_rate_payload;
+ frame_rate_payload = (struct msm_vidc_framerate_payload *)(void *)data->data;
+ frame_rate = frame_rate_payload->frame_rate;
+ break;
+ case MSM_VIDC_EXTRADATA_TIMESTAMP:
+ struct msm_vidc_ts_payload *time_stamp_payload;
+ time_stamp_payload = (struct msm_vidc_ts_payload *)(void *)data->data;
+ time_stamp = time_stamp_payload->timestamp_lo;
+ time_stamp |= ((unsigned long long)time_stamp_payload->timestamp_hi << 32);
+ p_buf_hdr->nTimeStamp = time_stamp;
+ break;
+ case MSM_VIDC_EXTRADATA_NUM_CONCEALED_MB:
+ struct msm_vidc_concealmb_payload *conceal_mb_payload;
+ conceal_mb_payload = (struct msm_vidc_concealmb_payload *)(void *)data->data;
+ num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) *
+ (drv_ctx.video_resolution.frame_height + 15)) >> 8;
+ num_conceal_MB = ((num_MB_in_frame > 0)?(conceal_mb_payload->num_mbs * 100 / num_MB_in_frame) : 0);
+ break;
+ case MSM_VIDC_EXTRADATA_INDEX:
+ int *etype;
+ etype = (int *)(void *)data->data;
+ if (etype && *etype == MSM_VIDC_EXTRADATA_ASPECT_RATIO) {
+ struct msm_vidc_aspect_ratio_payload *aspect_ratio_payload;
+ aspect_ratio_payload = (struct msm_vidc_aspect_ratio_payload *)(++etype);
+ if (aspect_ratio_payload) {
+ ((struct vdec_output_frameinfo *)
+ p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_width = aspect_ratio_payload->aspect_width;
+ ((struct vdec_output_frameinfo *)
+ p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info.par_height = aspect_ratio_payload->aspect_height;
+ }
+ } else if (etype && *etype == MSM_VIDC_EXTRADATA_OUTPUT_CROP) {
+ struct msm_vidc_output_crop_payload *output_crop_payload;
+ output_crop_payload = (struct msm_vidc_output_crop_payload *)(++etype);
+ if (output_crop_payload) {
+ m_extradata_info.output_crop_rect.nLeft = output_crop_payload->left;
+ m_extradata_info.output_crop_rect.nTop = output_crop_payload->top;
+ m_extradata_info.output_crop_rect.nWidth = output_crop_payload->left + output_crop_payload->display_width;
+ m_extradata_info.output_crop_rect.nHeight = output_crop_payload->top + output_crop_payload->display_height;
+ m_extradata_info.output_width = output_crop_payload->width;
+ m_extradata_info.output_height = output_crop_payload->height;
+ m_extradata_info.output_crop_updated = OMX_TRUE;
+ }
+ }
+ break;
+ case MSM_VIDC_EXTRADATA_RECOVERY_POINT_SEI:
+ struct msm_vidc_recoverysei_payload *recovery_sei_payload;
+ recovery_sei_payload = (struct msm_vidc_recoverysei_payload *)(void *)data->data;
+ recovery_sei_flags = recovery_sei_payload->flags;
+ if (recovery_sei_flags != MSM_VIDC_FRAME_RECONSTRUCTION_CORRECT) {
+ p_buf_hdr->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
+ DEBUG_PRINT_HIGH("***************************************************");
+ DEBUG_PRINT_HIGH("FillBufferDone: OMX_BUFFERFLAG_DATACORRUPT Received");
+ DEBUG_PRINT_HIGH("***************************************************");
+ }
+ break;
+ case MSM_VIDC_EXTRADATA_PANSCAN_WINDOW:
+ panscan_payload = (struct msm_vidc_panscan_window_payload *)(void *)data->data;
+ if (panscan_payload->num_panscan_windows > MAX_PAN_SCAN_WINDOWS) {
+ DEBUG_PRINT_ERROR("Panscan windows are more than supported\n");
+ DEBUG_PRINT_ERROR("Max supported = %d FW returned = %d\n",
+ MAX_PAN_SCAN_WINDOWS, panscan_payload->num_panscan_windows);
+ return;
+ }
+ break;
+ case MSM_VIDC_EXTRADATA_MPEG2_SEQDISP:
+ case MSM_VIDC_EXTRADATA_VUI_DISPLAY_INFO:
+ case MSM_VIDC_EXTRADATA_VC1_SEQDISP:
+ case MSM_VIDC_EXTRADATA_VPX_COLORSPACE_INFO:
+ handle_color_space_info((void *)data->data, buf_index);
+ break;
+ case MSM_VIDC_EXTRADATA_S3D_FRAME_PACKING:
+ struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload;
+ s3d_frame_packing_payload = (struct msm_vidc_s3d_frame_packing_payload *)(void *)data->data;
+ switch (s3d_frame_packing_payload->fpa_type) {
+ case MSM_VIDC_FRAMEPACK_SIDE_BY_SIDE:
+ if (s3d_frame_packing_payload->content_interprtation_type == 1)
+ stereo_output_mode = HAL_3D_SIDE_BY_SIDE_L_R;
+ else if (s3d_frame_packing_payload->content_interprtation_type == 2)
+ stereo_output_mode = HAL_3D_SIDE_BY_SIDE_R_L;
+ else {
+ DEBUG_PRINT_ERROR("Unsupported side-by-side framepacking type");
+ stereo_output_mode = HAL_NO_3D;
+ }
+ break;
+ case MSM_VIDC_FRAMEPACK_TOP_BOTTOM:
+ stereo_output_mode = HAL_3D_TOP_BOTTOM;
+ break;
+ default:
+ DEBUG_PRINT_ERROR("Unsupported framepacking type");
+ stereo_output_mode = HAL_NO_3D;
+ }
+ DEBUG_PRINT_LOW("setMetaData FRAMEPACKING : fpa_type = %u, content_interprtation_type = %u, stereo_output_mode= %d",
+ s3d_frame_packing_payload->fpa_type, s3d_frame_packing_payload->content_interprtation_type, stereo_output_mode);
+ if (client_extradata & OMX_FRAMEPACK_EXTRADATA) {
+ append_framepack_extradata(p_extra, s3d_frame_packing_payload);
+ p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
+ if (p_client_extra) {
+ append_framepack_extradata(p_client_extra, s3d_frame_packing_payload);
+ p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
+ }
+ }
+ break;
+ case MSM_VIDC_EXTRADATA_FRAME_QP:
+ struct msm_vidc_frame_qp_payload *qp_payload;
+ qp_payload = (struct msm_vidc_frame_qp_payload*)(void *)data->data;
+ if (client_extradata & OMX_QP_EXTRADATA) {
+ append_qp_extradata(p_extra, qp_payload);
+ p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
+ if (p_client_extra) {
+ append_qp_extradata(p_client_extra, qp_payload);
+ p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
+ }
+ }
+ break;
+ case MSM_VIDC_EXTRADATA_FRAME_BITS_INFO:
+ struct msm_vidc_frame_bits_info_payload *bits_info_payload;
+ bits_info_payload = (struct msm_vidc_frame_bits_info_payload*)(void *)data->data;
+ if (client_extradata & OMX_BITSINFO_EXTRADATA) {
+ append_bitsinfo_extradata(p_extra, bits_info_payload);
+ p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
+ if (p_client_extra) {
+ append_bitsinfo_extradata(p_client_extra, bits_info_payload);
+ p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
+ }
+ }
+ break;
+ case MSM_VIDC_EXTRADATA_STREAM_USERDATA:
+ if (client_extradata & OMX_EXTNUSER_EXTRADATA) {
+ append_user_extradata(p_extra, data);
+ p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
+ if (p_client_extra) {
+ append_user_extradata(p_client_extra, data);
+ p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
+ }
+ }
+ break;
+ case MSM_VIDC_EXTRADATA_VQZIP_SEI:
+ struct msm_vidc_vqzip_sei_payload *vqzip_payload;
+ vqzip_payload = (struct msm_vidc_vqzip_sei_payload*)(void *)data->data;
+ if (client_extradata & OMX_VQZIPSEI_EXTRADATA) {
+ p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
+ append_vqzip_extradata(p_extra, vqzip_payload);
+ p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
+ if (p_client_extra) {
+ append_vqzip_extradata(p_client_extra, vqzip_payload);
+ p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
+ }
+ }
+ break;
+ default:
+ DEBUG_PRINT_LOW("Unrecognized extradata");
+ goto unrecognized_extradata;
+ }
+ consumed_len += data->nSize;
+ data = (OMX_OTHER_EXTRADATATYPE *)((char *)data + data->nSize);
+ }
+ if (client_extradata & OMX_FRAMEINFO_EXTRADATA) {
+ p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
+ append_frame_info_extradata(p_extra,
+ num_conceal_MB, ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type, frame_rate,
+ time_stamp, panscan_payload,&((struct vdec_output_frameinfo *)
+ p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info);
+ p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
+ if (p_client_extra) {
+ append_frame_info_extradata(p_client_extra,
+ num_conceal_MB, ((struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate)->pic_type, frame_rate,
+ time_stamp, panscan_payload,&((struct vdec_output_frameinfo *)
+ p_buf_hdr->pOutputPortPrivate)->aspect_ratio_info);
+ p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
+ }
+ }
+ if (client_extradata & OMX_FRAMEDIMENSION_EXTRADATA) {
+ append_frame_dimension_extradata(p_extra);
+ p_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_extra) + ALIGN(p_extra->nSize, 4));
+ if (p_client_extra) {
+ append_frame_dimension_extradata(p_client_extra);
+ p_client_extra = (OMX_OTHER_EXTRADATATYPE *) (((OMX_U8 *) p_client_extra) + ALIGN(p_client_extra->nSize, 4));
+ }
+ }
+ }
+unrecognized_extradata:
+ if (client_extradata && p_extra) {
+ p_buf_hdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
+ append_terminator_extradata(p_extra);
+ if (p_client_extra) {
+ append_terminator_extradata(p_client_extra);
+ }
+ }
+ if (secure_mode && p_extradata && m_other_extradata) {
+ struct vdec_output_frameinfo *ptr_extradatabuff = NULL;
+ memcpy(p_extradata, m_other_extradata, drv_ctx.extradata_info.buffer_size);
+ ptr_extradatabuff = (struct vdec_output_frameinfo *)p_buf_hdr->pOutputPortPrivate;
+ ptr_extradatabuff->metadata_info.metabufaddr = (void *)p_extradata;
+ ptr_extradatabuff->metadata_info.size = drv_ctx.extradata_info.buffer_size;
+ ptr_extradatabuff->metadata_info.fd = drv_ctx.extradata_info.ion.fd_ion_data.fd;
+ ptr_extradatabuff->metadata_info.offset = buf_index * drv_ctx.extradata_info.buffer_size;
+ ptr_extradatabuff->metadata_info.buffer_size = drv_ctx.extradata_info.size;
+ }
+ return;
+}
+
+OMX_ERRORTYPE omx_vdec::enable_extradata(OMX_U32 requested_extradata,
+ bool is_internal, bool enable)
+{
+ OMX_ERRORTYPE ret = OMX_ErrorNone;
+ struct v4l2_control control;
+ if (m_state != OMX_StateLoaded) {
+ DEBUG_PRINT_ERROR("ERROR: enable extradata allowed in Loaded state only");
+ return OMX_ErrorIncorrectStateOperation;
+ }
+ DEBUG_PRINT_HIGH("NOTE: enable_extradata: actual[%u] requested[%u] enable[%d], is_internal: %d",
+ (unsigned int)client_extradata, (unsigned int)requested_extradata, enable, is_internal);
+
+ if (!is_internal) {
+ if (enable)
+ client_extradata |= requested_extradata;
+ else
+ client_extradata = client_extradata & ~requested_extradata;
+ }
+
+ if (enable) {
+ if (requested_extradata & OMX_INTERLACE_EXTRADATA) {
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
+ control.value = V4L2_MPEG_VIDC_EXTRADATA_INTERLACE_VIDEO;
+ if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
+ DEBUG_PRINT_HIGH("Failed to set interlaced extradata."
+ " Quality of interlaced clips might be impacted.");
+ }
+ }
+ if (requested_extradata & OMX_FRAMEINFO_EXTRADATA) {
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
+ control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_RATE;
+ if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
+ DEBUG_PRINT_HIGH("Failed to set framerate extradata");
+ }
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
+ control.value = V4L2_MPEG_VIDC_EXTRADATA_NUM_CONCEALED_MB;
+ if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
+ DEBUG_PRINT_HIGH("Failed to set concealed MB extradata");
+ }
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
+ control.value = V4L2_MPEG_VIDC_EXTRADATA_RECOVERY_POINT_SEI;
+ if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
+ DEBUG_PRINT_HIGH("Failed to set recovery point SEI extradata");
+ }
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
+ control.value = V4L2_MPEG_VIDC_EXTRADATA_PANSCAN_WINDOW;
+ if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
+ DEBUG_PRINT_HIGH("Failed to set panscan extradata");
+ }
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
+ control.value = V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO;
+ if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
+ DEBUG_PRINT_HIGH("Failed to set panscan extradata");
+ }
+ if (output_capability == V4L2_PIX_FMT_MPEG2) {
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
+ control.value = V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP;
+ if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
+ DEBUG_PRINT_HIGH("Failed to set panscan extradata");
+ }
+ }
+ }
+ if (requested_extradata & OMX_TIMEINFO_EXTRADATA) {
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
+ control.value = V4L2_MPEG_VIDC_EXTRADATA_TIMESTAMP;
+ if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
+ DEBUG_PRINT_HIGH("Failed to set timeinfo extradata");
+ }
+ }
+ if (!secure_mode && (requested_extradata & OMX_FRAMEPACK_EXTRADATA)) {
+ if (output_capability == V4L2_PIX_FMT_H264) {
+ DEBUG_PRINT_HIGH("enable OMX_FRAMEPACK_EXTRADATA");
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
+ control.value = V4L2_MPEG_VIDC_EXTRADATA_S3D_FRAME_PACKING;
+ if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
+ DEBUG_PRINT_HIGH("Failed to set S3D_FRAME_PACKING extradata");
+ }
+ } else {
+ DEBUG_PRINT_HIGH("OMX_FRAMEPACK_EXTRADATA supported for H264 only");
+ }
+ }
+ if (requested_extradata & OMX_QP_EXTRADATA) {
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
+ control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP;
+ if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
+ DEBUG_PRINT_HIGH("Failed to set QP extradata");
+ }
+ }
+ if (requested_extradata & OMX_BITSINFO_EXTRADATA) {
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
+ control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_BITS_INFO;
+ if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
+ DEBUG_PRINT_HIGH("Failed to set frame bits info extradata");
+ }
+ }
+ if (!secure_mode && (requested_extradata & OMX_EXTNUSER_EXTRADATA)) {
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
+ control.value = V4L2_MPEG_VIDC_EXTRADATA_STREAM_USERDATA;
+ if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
+ DEBUG_PRINT_HIGH("Failed to set stream userdata extradata");
+ }
+ }
+ if (requested_extradata & OMX_VQZIPSEI_EXTRADATA) {
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
+ control.value = V4L2_MPEG_VIDC_EXTRADATA_VQZIP_SEI;
+ if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
+ DEBUG_PRINT_HIGH("Failed to set VQZip SEI extradata");
+ }
+ client_extradata |= OMX_VQZIPSEI_EXTRADATA;
+
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
+ control.value = V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP;
+ if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
+ DEBUG_PRINT_HIGH("Failed to set QP extradata");
+ }
+ client_extradata |= OMX_QP_EXTRADATA;
+ }
+ if (requested_extradata & OMX_OUTPUTCROP_EXTRADATA) {
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
+ control.value = V4L2_MPEG_VIDC_EXTRADATA_OUTPUT_CROP;
+ DEBUG_PRINT_LOW("Enable output crop extra data");
+ if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
+ DEBUG_PRINT_HIGH("Failed to set output crop extradata");
+ }
+ }
+ if (requested_extradata & OMX_DISPLAY_INFO_EXTRADATA) {
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA;
+ switch(output_capability) {
+ case V4L2_PIX_FMT_H264:
+ case V4L2_PIX_FMT_HEVC:
+ control.value = V4L2_MPEG_VIDC_EXTRADATA_VUI_DISPLAY;
+ break;
+ case CODEC_TYPE_MPEG2:
+ control.value = V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP;
+ break;
+ case V4L2_PIX_FMT_VP8:
+ case V4L2_PIX_FMT_VP9:
+ control.value = V4L2_MPEG_VIDC_EXTRADATA_VPX_COLORSPACE;
+ break;
+ case V4L2_PIX_FMT_VC1_ANNEX_G:
+ case V4L2_PIX_FMT_VC1_ANNEX_L:
+ control.value = V4L2_MPEG_VIDC_EXTRADATA_VC1_SEQDISP;
+ break;
+ default:
+ DEBUG_PRINT_HIGH("Don't support Disp info for this codec : %s", drv_ctx.kind);
+ return ret;
+ }
+
+ if (ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
+ DEBUG_PRINT_HIGH("Failed to set Display info extradata");
+ }
+ }
+ }
+ ret = get_buffer_req(&drv_ctx.op_buf);
+ return ret;
+}
+
+OMX_U32 omx_vdec::count_MB_in_extradata(OMX_OTHER_EXTRADATATYPE *extra)
+{
+ OMX_U32 num_MB = 0, byte_count = 0, num_MB_in_frame = 0;
+ OMX_U8 *data_ptr = extra->data, data = 0;
+ while (byte_count < extra->nDataSize) {
+ data = *data_ptr;
+ while (data) {
+ num_MB += (data&0x01);
+ data >>= 1;
+ }
+ data_ptr++;
+ byte_count++;
+ }
+ num_MB_in_frame = ((drv_ctx.video_resolution.frame_width + 15) *
+ (drv_ctx.video_resolution.frame_height + 15)) >> 8;
+ return ((num_MB_in_frame > 0)?(num_MB * 100 / num_MB_in_frame) : 0);
+}
+
+void omx_vdec::print_debug_extradata(OMX_OTHER_EXTRADATATYPE *extra)
+{
+ if (!m_debug_extradata || !extra)
+ return;
+
+
+ DEBUG_PRINT_HIGH(
+ "============== Extra Data ==============\n"
+ " Size: %u\n"
+ " Version: %u\n"
+ " PortIndex: %u\n"
+ " Type: %x\n"
+ " DataSize: %u",
+ (unsigned int)extra->nSize, (unsigned int)extra->nVersion.nVersion,
+ (unsigned int)extra->nPortIndex, extra->eType, (unsigned int)extra->nDataSize);
+
+ if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat) {
+ OMX_STREAMINTERLACEFORMAT *intfmt = (OMX_STREAMINTERLACEFORMAT *)(void *)extra->data;
+ DEBUG_PRINT_HIGH(
+ "------ Interlace Format ------\n"
+ " Size: %u\n"
+ " Version: %u\n"
+ " PortIndex: %u\n"
+ " Is Interlace Format: %d\n"
+ " Interlace Formats: %u\n"
+ "=========== End of Interlace ===========",
+ (unsigned int)intfmt->nSize, (unsigned int)intfmt->nVersion.nVersion, (unsigned int)intfmt->nPortIndex,
+ intfmt->bInterlaceFormat, (unsigned int)intfmt->nInterlaceFormats);
+ } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo) {
+ OMX_QCOM_EXTRADATA_FRAMEINFO *fminfo = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(void *)extra->data;
+
+ DEBUG_PRINT_HIGH(
+ "-------- Frame Format --------\n"
+ " Picture Type: %d\n"
+ " Interlace Type: %d\n"
+ " Pan Scan Total Frame Num: %u\n"
+ " Concealed Macro Blocks: %u\n"
+ " frame rate: %u\n"
+ " Time Stamp: %llu\n"
+ " Aspect Ratio X: %u\n"
+ " Aspect Ratio Y: %u",
+ fminfo->ePicType,
+ fminfo->interlaceType,
+ (unsigned int)fminfo->panScan.numWindows,
+ (unsigned int)fminfo->nConcealedMacroblocks,
+ (unsigned int)fminfo->nFrameRate,
+ fminfo->nTimeStamp,
+ (unsigned int)fminfo->aspectRatio.aspectRatioX,
+ (unsigned int)fminfo->aspectRatio.aspectRatioY);
+
+ for (OMX_U32 i = 0; i < fminfo->panScan.numWindows; i++) {
+ DEBUG_PRINT_HIGH(
+ "------------------------------"
+ " Pan Scan Frame Num: %u\n"
+ " Rectangle x: %d\n"
+ " Rectangle y: %d\n"
+ " Rectangle dx: %d\n"
+ " Rectangle dy: %d",
+ (unsigned int)i, (unsigned int)fminfo->panScan.window[i].x, (unsigned int)fminfo->panScan.window[i].y,
+ (unsigned int)fminfo->panScan.window[i].dx, (unsigned int)fminfo->panScan.window[i].dy);
+ }
+
+ DEBUG_PRINT_HIGH("========= End of Frame Format ==========");
+ } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement) {
+ OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)(void *)extra->data;
+ DEBUG_PRINT_HIGH(
+ "------------------ Framepack Format ----------\n"
+ " id: %u \n"
+ " cancel_flag: %u \n"
+ " type: %u \n"
+ " quincunx_sampling_flagFormat: %u \n"
+ " content_interpretation_type: %u \n"
+ " spatial_flipping_flag: %u \n"
+ " frame0_flipped_flag: %u \n"
+ " field_views_flag: %u \n"
+ " current_frame_is_frame0_flag: %u \n"
+ " frame0_self_contained_flag: %u \n"
+ " frame1_self_contained_flag: %u \n"
+ " frame0_grid_position_x: %u \n"
+ " frame0_grid_position_y: %u \n"
+ " frame1_grid_position_x: %u \n"
+ " frame1_grid_position_y: %u \n"
+ " reserved_byte: %u \n"
+ " repetition_period: %u \n"
+ " extension_flag: %u \n"
+ "================== End of Framepack ===========",
+ (unsigned int)framepack->id,
+ (unsigned int)framepack->cancel_flag,
+ (unsigned int)framepack->type,
+ (unsigned int)framepack->quincunx_sampling_flag,
+ (unsigned int)framepack->content_interpretation_type,
+ (unsigned int)framepack->spatial_flipping_flag,
+ (unsigned int)framepack->frame0_flipped_flag,
+ (unsigned int)framepack->field_views_flag,
+ (unsigned int)framepack->current_frame_is_frame0_flag,
+ (unsigned int)framepack->frame0_self_contained_flag,
+ (unsigned int)framepack->frame1_self_contained_flag,
+ (unsigned int)framepack->frame0_grid_position_x,
+ (unsigned int)framepack->frame0_grid_position_y,
+ (unsigned int)framepack->frame1_grid_position_x,
+ (unsigned int)framepack->frame1_grid_position_y,
+ (unsigned int)framepack->reserved_byte,
+ (unsigned int)framepack->repetition_period,
+ (unsigned int)framepack->extension_flag);
+ } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataQP) {
+ OMX_QCOM_EXTRADATA_QP * qp = (OMX_QCOM_EXTRADATA_QP *)(void *)extra->data;
+ DEBUG_PRINT_HIGH(
+ "---- QP (Frame quantization parameter) ----\n"
+ " Frame QP: %u \n"
+ "================ End of QP ================\n",
+ (unsigned int)qp->nQP);
+ } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo) {
+ OMX_QCOM_EXTRADATA_BITS_INFO * bits = (OMX_QCOM_EXTRADATA_BITS_INFO *)(void *)extra->data;
+ DEBUG_PRINT_HIGH(
+ "--------- Input bits information --------\n"
+ " Header bits: %u \n"
+ " Frame bits: %u \n"
+ "===== End of Input bits information =====\n",
+ (unsigned int)bits->header_bits, (unsigned int)bits->frame_bits);
+ } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataMP2UserData) {
+ OMX_QCOM_EXTRADATA_USERDATA *userdata = (OMX_QCOM_EXTRADATA_USERDATA *)(void *)extra->data;
+ OMX_U8 *data_ptr = (OMX_U8 *)userdata->data;
+ OMX_U32 userdata_size = extra->nDataSize - sizeof(userdata->type);
+ OMX_U32 i = 0;
+ DEBUG_PRINT_HIGH(
+ "-------------- Userdata -------------\n"
+ " Stream userdata type: %u\n"
+ " userdata size: %u\n"
+ " STREAM_USERDATA:",
+ (unsigned int)userdata->type, (unsigned int)userdata_size);
+ for (i = 0; i < userdata_size; i+=4) {
+ DEBUG_PRINT_HIGH(" %x %x %x %x",
+ data_ptr[i], data_ptr[i+1],
+ data_ptr[i+2], data_ptr[i+3]);
+ }
+ DEBUG_PRINT_HIGH(
+ "=========== End of Userdata ===========");
+ } else if (extra->eType == (OMX_EXTRADATATYPE)OMX_ExtraDataVQZipSEI) {
+ OMX_QCOM_EXTRADATA_VQZIPSEI *vq = (OMX_QCOM_EXTRADATA_VQZIPSEI *)(void *)extra->data;
+ DEBUG_PRINT_HIGH(
+ "-------------- VQZip -------------\n"
+ " Size: %u\n",
+ (unsigned int)vq->nSize);
+ DEBUG_PRINT_HIGH( "=========== End of VQZip ===========");
+ } else if (extra->eType == OMX_ExtraDataNone) {
+ DEBUG_PRINT_HIGH("========== End of Terminator ===========");
+ } else {
+ DEBUG_PRINT_HIGH("======= End of Driver Extradata ========");
+ }
+}
+
+void omx_vdec::append_interlace_extradata(OMX_OTHER_EXTRADATATYPE *extra,
+ OMX_U32 interlaced_format_type)
+{
+ OMX_STREAMINTERLACEFORMAT *interlace_format;
+
+ if (!(client_extradata & OMX_INTERLACE_EXTRADATA)) {
+ return;
+ }
+ if (!extra) {
+ DEBUG_PRINT_ERROR("Error: append_interlace_extradata - invalid input");
+ return;
+ }
+ extra->nSize = OMX_INTERLACE_EXTRADATA_SIZE;
+ extra->nVersion.nVersion = OMX_SPEC_VERSION;
+ extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
+ extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInterlaceFormat;
+ extra->nDataSize = sizeof(OMX_STREAMINTERLACEFORMAT);
+ interlace_format = (OMX_STREAMINTERLACEFORMAT *)(void *)extra->data;
+ interlace_format->nSize = sizeof(OMX_STREAMINTERLACEFORMAT);
+ interlace_format->nVersion.nVersion = OMX_SPEC_VERSION;
+ interlace_format->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
+
+ if (interlaced_format_type == MSM_VIDC_INTERLACE_FRAME_PROGRESSIVE) {
+ interlace_format->bInterlaceFormat = OMX_FALSE;
+ interlace_format->nInterlaceFormats = OMX_InterlaceFrameProgressive;
+ drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
+ } else if (interlaced_format_type == MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_TOPFIELDFIRST) {
+ interlace_format->bInterlaceFormat = OMX_TRUE;
+ interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameTopFieldFirst;
+ drv_ctx.interlace = VDEC_InterlaceInterleaveFrameTopFieldFirst;
+ } else if (interlaced_format_type == MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST) {
+ interlace_format->bInterlaceFormat = OMX_TRUE;
+ interlace_format->nInterlaceFormats = OMX_InterlaceInterleaveFrameBottomFieldFirst;
+ drv_ctx.interlace = VDEC_InterlaceInterleaveFrameBottomFieldFirst;
+ } else {
+ //default case - set to progressive
+ interlace_format->bInterlaceFormat = OMX_FALSE;
+ interlace_format->nInterlaceFormats = OMX_InterlaceFrameProgressive;
+ drv_ctx.interlace = VDEC_InterlaceFrameProgressive;
+ }
+ print_debug_extradata(extra);
+}
+
+void omx_vdec::append_frame_dimension_extradata(OMX_OTHER_EXTRADATATYPE *extra)
+{
+ OMX_QCOM_EXTRADATA_FRAMEDIMENSION *frame_dimension;
+ if (!(client_extradata & OMX_FRAMEDIMENSION_EXTRADATA)) {
+ return;
+ }
+ extra->nSize = OMX_FRAMEDIMENSION_EXTRADATA_SIZE;
+ extra->nVersion.nVersion = OMX_SPEC_VERSION;
+ extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
+ extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameDimension;
+ extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEDIMENSION);
+ frame_dimension = (OMX_QCOM_EXTRADATA_FRAMEDIMENSION *)(void *)extra->data;
+ frame_dimension->nDecWidth = rectangle.nLeft;
+ frame_dimension->nDecHeight = rectangle.nTop;
+ frame_dimension->nActualWidth = rectangle.nWidth;
+ frame_dimension->nActualHeight = rectangle.nHeight;
+}
+
+void omx_vdec::fill_aspect_ratio_info(
+ struct vdec_aspectratioinfo *aspect_ratio_info,
+ OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info)
+{
+ m_extradata = frame_info;
+ m_extradata->aspectRatio.aspectRatioX = aspect_ratio_info->par_width;
+ m_extradata->aspectRatio.aspectRatioY = aspect_ratio_info->par_height;
+ DEBUG_PRINT_LOW("aspectRatioX %u aspectRatioY %u", (unsigned int)m_extradata->aspectRatio.aspectRatioX,
+ (unsigned int)m_extradata->aspectRatio.aspectRatioY);
+}
+
+void omx_vdec::append_frame_info_extradata(OMX_OTHER_EXTRADATATYPE *extra,
+ OMX_U32 num_conceal_mb, OMX_U32 picture_type, OMX_U32 frame_rate,
+ OMX_TICKS time_stamp, struct msm_vidc_panscan_window_payload *panscan_payload,
+ struct vdec_aspectratioinfo *aspect_ratio_info)
+{
+ OMX_QCOM_EXTRADATA_FRAMEINFO *frame_info = NULL;
+ struct msm_vidc_panscan_window *panscan_window;
+ if (!(client_extradata & OMX_FRAMEINFO_EXTRADATA)) {
+ return;
+ }
+ extra->nSize = OMX_FRAMEINFO_EXTRADATA_SIZE;
+ extra->nVersion.nVersion = OMX_SPEC_VERSION;
+ extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
+ extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFrameInfo;
+ extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEINFO);
+ frame_info = (OMX_QCOM_EXTRADATA_FRAMEINFO *)(void *)extra->data;
+ switch (picture_type) {
+ case PICTURE_TYPE_I:
+ frame_info->ePicType = OMX_VIDEO_PictureTypeI;
+ break;
+ case PICTURE_TYPE_P:
+ frame_info->ePicType = OMX_VIDEO_PictureTypeP;
+ break;
+ case PICTURE_TYPE_B:
+ frame_info->ePicType = OMX_VIDEO_PictureTypeB;
+ break;
+ default:
+ frame_info->ePicType = (OMX_VIDEO_PICTURETYPE)0;
+ }
+ if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameTopFieldFirst)
+ frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
+ else if (drv_ctx.interlace == VDEC_InterlaceInterleaveFrameBottomFieldFirst)
+ frame_info->interlaceType = OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
+ else
+ frame_info->interlaceType = OMX_QCOM_InterlaceFrameProgressive;
+ memset(&frame_info->aspectRatio, 0, sizeof(frame_info->aspectRatio));
+ frame_info->nConcealedMacroblocks = num_conceal_mb;
+ frame_info->nFrameRate = frame_rate;
+ frame_info->nTimeStamp = time_stamp;
+ frame_info->panScan.numWindows = 0;
+ if (output_capability == V4L2_PIX_FMT_MPEG2) {
+ if (m_disp_hor_size && m_disp_vert_size) {
+ frame_info->displayAspectRatio.displayHorizontalSize = m_disp_hor_size;
+ frame_info->displayAspectRatio.displayVerticalSize = m_disp_vert_size;
+ } else {
+ frame_info->displayAspectRatio.displayHorizontalSize = 0;
+ frame_info->displayAspectRatio.displayVerticalSize = 0;
+ }
+ }
+
+ if (panscan_payload) {
+ frame_info->panScan.numWindows = panscan_payload->num_panscan_windows;
+ panscan_window = &panscan_payload->wnd[0];
+ for (OMX_U32 i = 0; i < frame_info->panScan.numWindows; i++) {
+ frame_info->panScan.window[i].x = panscan_window->panscan_window_width;
+ frame_info->panScan.window[i].y = panscan_window->panscan_window_height;
+ frame_info->panScan.window[i].dx = panscan_window->panscan_width_offset;
+ frame_info->panScan.window[i].dy = panscan_window->panscan_height_offset;
+ panscan_window++;
+ }
+ }
+ fill_aspect_ratio_info(aspect_ratio_info, frame_info);
+ print_debug_extradata(extra);
+}
+
+void omx_vdec::append_portdef_extradata(OMX_OTHER_EXTRADATATYPE *extra)
+{
+ OMX_PARAM_PORTDEFINITIONTYPE *portDefn = NULL;
+ extra->nSize = OMX_PORTDEF_EXTRADATA_SIZE;
+ extra->nVersion.nVersion = OMX_SPEC_VERSION;
+ extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
+ extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataPortDef;
+ extra->nDataSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
+ portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *)(void *)extra->data;
+ *portDefn = m_port_def;
+ DEBUG_PRINT_LOW("append_portdef_extradata height = %u width = %u "
+ "stride = %u sliceheight = %u",(unsigned int)portDefn->format.video.nFrameHeight,
+ (unsigned int)portDefn->format.video.nFrameWidth,
+ (unsigned int)portDefn->format.video.nStride,
+ (unsigned int)portDefn->format.video.nSliceHeight);
+}
+
+void omx_vdec::append_framepack_extradata(OMX_OTHER_EXTRADATATYPE *extra,
+ struct msm_vidc_s3d_frame_packing_payload *s3d_frame_packing_payload)
+{
+ OMX_QCOM_FRAME_PACK_ARRANGEMENT *framepack;
+ if (FRAME_PACK_SIZE*sizeof(OMX_U32) != sizeof(struct msm_vidc_s3d_frame_packing_payload)) {
+ DEBUG_PRINT_ERROR("frame packing size mismatch");
+ return;
+ }
+ extra->nSize = OMX_FRAMEPACK_EXTRADATA_SIZE;
+ extra->nVersion.nVersion = OMX_SPEC_VERSION;
+ extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
+ extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataFramePackingArrangement;
+ extra->nDataSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT);
+ framepack = (OMX_QCOM_FRAME_PACK_ARRANGEMENT *)(void *)extra->data;
+ framepack->nSize = sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT);
+ framepack->nVersion.nVersion = OMX_SPEC_VERSION;
+ framepack->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
+ memcpy(&framepack->id, s3d_frame_packing_payload,
+ sizeof(struct msm_vidc_s3d_frame_packing_payload));
+ memcpy(&m_frame_pack_arrangement, framepack,
+ sizeof(OMX_QCOM_FRAME_PACK_ARRANGEMENT));
+ print_debug_extradata(extra);
+}
+
+void omx_vdec::append_qp_extradata(OMX_OTHER_EXTRADATATYPE *extra,
+ struct msm_vidc_frame_qp_payload *qp_payload)
+{
+ OMX_QCOM_EXTRADATA_QP * qp = NULL;
+ if (!qp_payload) {
+ DEBUG_PRINT_ERROR("QP payload is NULL");
+ return;
+ }
+ extra->nSize = OMX_QP_EXTRADATA_SIZE;
+ extra->nVersion.nVersion = OMX_SPEC_VERSION;
+ extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
+ extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataQP;
+ extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_QP);
+ qp = (OMX_QCOM_EXTRADATA_QP *)(void *)extra->data;
+ qp->nQP = qp_payload->frame_qp;
+ print_debug_extradata(extra);
+}
+
+void omx_vdec::append_bitsinfo_extradata(OMX_OTHER_EXTRADATATYPE *extra,
+ struct msm_vidc_frame_bits_info_payload *bits_payload)
+{
+ OMX_QCOM_EXTRADATA_BITS_INFO * bits = NULL;
+ if (!bits_payload) {
+ DEBUG_PRINT_ERROR("bits info payload is NULL");
+ return;
+ }
+ extra->nSize = OMX_BITSINFO_EXTRADATA_SIZE;
+ extra->nVersion.nVersion = OMX_SPEC_VERSION;
+ extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
+ extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataInputBitsInfo;
+ extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_BITS_INFO);
+ bits = (OMX_QCOM_EXTRADATA_BITS_INFO*)(void *)extra->data;
+ bits->frame_bits = bits_payload->frame_bits;
+ bits->header_bits = bits_payload->header_bits;
+ print_debug_extradata(extra);
+}
+
+void omx_vdec::append_user_extradata(OMX_OTHER_EXTRADATATYPE *extra,
+ OMX_OTHER_EXTRADATATYPE *p_user)
+{
+ int userdata_size = 0;
+ struct msm_vidc_stream_userdata_payload *userdata_payload = NULL;
+ userdata_payload =
+ (struct msm_vidc_stream_userdata_payload *)(void *)p_user->data;
+ userdata_size = p_user->nDataSize;
+ extra->nSize = OMX_USERDATA_EXTRADATA_SIZE + userdata_size;
+ extra->nVersion.nVersion = OMX_SPEC_VERSION;
+ extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
+ extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataMP2UserData;
+ extra->nDataSize = userdata_size;
+ if (extra->nDataSize && (p_user->nDataSize >= extra->nDataSize))
+ memcpy(extra->data, p_user->data, extra->nDataSize);
+ print_debug_extradata(extra);
+}
+
+void omx_vdec::append_terminator_extradata(OMX_OTHER_EXTRADATATYPE *extra)
+{
+ if (!client_extradata) {
+ return;
+ }
+ extra->nSize = sizeof(OMX_OTHER_EXTRADATATYPE);
+ extra->nVersion.nVersion = OMX_SPEC_VERSION;
+ extra->eType = OMX_ExtraDataNone;
+ extra->nDataSize = 0;
+ extra->data[0] = 0;
+
+ print_debug_extradata(extra);
+}
+
+void omx_vdec::append_vqzip_extradata(OMX_OTHER_EXTRADATATYPE *extra,
+ struct msm_vidc_vqzip_sei_payload *vqzip_payload)
+{
+ OMX_QCOM_EXTRADATA_VQZIPSEI *vq = NULL;
+
+ extra->nSize = OMX_VQZIPSEI_EXTRADATA_SIZE + vqzip_payload->size;
+ extra->nVersion.nVersion = OMX_SPEC_VERSION;
+ extra->nPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
+ extra->eType = (OMX_EXTRADATATYPE)OMX_ExtraDataVQZipSEI;
+ extra->nDataSize = sizeof(OMX_QCOM_EXTRADATA_VQZIPSEI) + vqzip_payload->size;
+
+ vq = (OMX_QCOM_EXTRADATA_VQZIPSEI *)(void *)extra->data;
+ vq->nSize = vqzip_payload->size;
+ memcpy(vq->data, vqzip_payload->data, vqzip_payload->size);
+
+ print_debug_extradata(extra);
+}
+
+OMX_ERRORTYPE omx_vdec::allocate_desc_buffer(OMX_U32 index)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ if (index >= drv_ctx.ip_buf.actualcount) {
+ DEBUG_PRINT_ERROR("ERROR:Desc Buffer Index not found");
+ return OMX_ErrorInsufficientResources;
+ }
+ if (m_desc_buffer_ptr == NULL) {
+ m_desc_buffer_ptr = (desc_buffer_hdr*) \
+ calloc( (sizeof(desc_buffer_hdr)),
+ drv_ctx.ip_buf.actualcount);
+ if (m_desc_buffer_ptr == NULL) {
+ DEBUG_PRINT_ERROR("m_desc_buffer_ptr Allocation failed ");
+ return OMX_ErrorInsufficientResources;
+ }
+ }
+
+ m_desc_buffer_ptr[index].buf_addr = (unsigned char *)malloc (DESC_BUFFER_SIZE * sizeof(OMX_U8));
+ if (m_desc_buffer_ptr[index].buf_addr == NULL) {
+ DEBUG_PRINT_ERROR("desc buffer Allocation failed ");
+ return OMX_ErrorInsufficientResources;
+ }
+
+ return eRet;
+}
+
+void omx_vdec::insert_demux_addr_offset(OMX_U32 address_offset)
+{
+ DEBUG_PRINT_LOW("Inserting address offset (%u) at idx (%u)", (unsigned int)address_offset,(unsigned int)m_demux_entries);
+ if (m_demux_entries < 8192) {
+ m_demux_offsets[m_demux_entries++] = address_offset;
+ }
+ return;
+}
+
+void omx_vdec::extract_demux_addr_offsets(OMX_BUFFERHEADERTYPE *buf_hdr)
+{
+ OMX_U32 bytes_to_parse = buf_hdr->nFilledLen;
+ OMX_U8 *buf = buf_hdr->pBuffer + buf_hdr->nOffset;
+ OMX_U32 index = 0;
+
+ m_demux_entries = 0;
+
+ while (index < bytes_to_parse) {
+ if ( ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
+ (buf[index+2] == 0x00) && (buf[index+3] == 0x01)) ||
+ ((buf[index] == 0x00) && (buf[index+1] == 0x00) &&
+ (buf[index+2] == 0x01)) ) {
+ //Found start code, insert address offset
+ insert_demux_addr_offset(index);
+ if (buf[index+2] == 0x01) // 3 byte start code
+ index += 3;
+ else //4 byte start code
+ index += 4;
+ } else
+ index++;
+ }
+ DEBUG_PRINT_LOW("Extracted (%u) demux entry offsets", (unsigned int)m_demux_entries);
+ return;
+}
+
+OMX_ERRORTYPE omx_vdec::handle_demux_data(OMX_BUFFERHEADERTYPE *p_buf_hdr)
+{
+ //fix this, handle 3 byte start code, vc1 terminator entry
+ OMX_U8 *p_demux_data = NULL;
+ OMX_U32 desc_data = 0;
+ OMX_U32 start_addr = 0;
+ OMX_U32 nal_size = 0;
+ OMX_U32 suffix_byte = 0;
+ OMX_U32 demux_index = 0;
+ OMX_U32 buffer_index = 0;
+
+ if (m_desc_buffer_ptr == NULL) {
+ DEBUG_PRINT_ERROR("m_desc_buffer_ptr is NULL. Cannot append demux entries.");
+ return OMX_ErrorBadParameter;
+ }
+
+ buffer_index = p_buf_hdr - ((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr);
+ if (buffer_index > drv_ctx.ip_buf.actualcount) {
+ DEBUG_PRINT_ERROR("handle_demux_data:Buffer index is incorrect (%u)", (unsigned int)buffer_index);
+ return OMX_ErrorBadParameter;
+ }
+
+ p_demux_data = (OMX_U8 *) m_desc_buffer_ptr[buffer_index].buf_addr;
+
+ if ( ((OMX_U8*)p_demux_data == NULL) ||
+ ((m_demux_entries * 16) + 1) > DESC_BUFFER_SIZE) {
+ DEBUG_PRINT_ERROR("Insufficient buffer. Cannot append demux entries.");
+ return OMX_ErrorBadParameter;
+ } else {
+ for (; demux_index < m_demux_entries; demux_index++) {
+ desc_data = 0;
+ start_addr = m_demux_offsets[demux_index];
+ if (p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 2] == 0x01) {
+ suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 3];
+ } else {
+ suffix_byte = p_buf_hdr->pBuffer[m_demux_offsets[demux_index] + 4];
+ }
+ if (demux_index < (m_demux_entries - 1)) {
+ nal_size = m_demux_offsets[demux_index + 1] - m_demux_offsets[demux_index] - 2;
+ } else {
+ nal_size = p_buf_hdr->nFilledLen - m_demux_offsets[demux_index] - 2;
+ }
+ DEBUG_PRINT_LOW("Start_addr(0x%x), suffix_byte(0x%x),nal_size(%u),demux_index(%u)",
+ (unsigned int)start_addr,
+ (unsigned int)suffix_byte,
+ (unsigned int)nal_size,
+ (unsigned int)demux_index);
+ desc_data = (start_addr >> 3) << 1;
+ desc_data |= (start_addr & 7) << 21;
+ desc_data |= suffix_byte << 24;
+
+ memcpy(p_demux_data, &desc_data, sizeof(OMX_U32));
+ memcpy(p_demux_data + 4, &nal_size, sizeof(OMX_U32));
+ memset(p_demux_data + 8, 0, sizeof(OMX_U32));
+ memset(p_demux_data + 12, 0, sizeof(OMX_U32));
+
+ p_demux_data += 16;
+ }
+ if (codec_type_parse == CODEC_TYPE_VC1) {
+ DEBUG_PRINT_LOW("VC1 terminator entry");
+ desc_data = 0;
+ desc_data = 0x82 << 24;
+ memcpy(p_demux_data, &desc_data, sizeof(OMX_U32));
+ memset(p_demux_data + 4, 0, sizeof(OMX_U32));
+ memset(p_demux_data + 8, 0, sizeof(OMX_U32));
+ memset(p_demux_data + 12, 0, sizeof(OMX_U32));
+ p_demux_data += 16;
+ m_demux_entries++;
+ }
+ //Add zero word to indicate end of descriptors
+ memset(p_demux_data, 0, sizeof(OMX_U32));
+
+ m_desc_buffer_ptr[buffer_index].desc_data_size = (m_demux_entries * 16) + sizeof(OMX_U32);
+ DEBUG_PRINT_LOW("desc table data size=%u", (unsigned int)m_desc_buffer_ptr[buffer_index].desc_data_size);
+ }
+ memset(m_demux_offsets, 0, ( sizeof(OMX_U32) * 8192) );
+ m_demux_entries = 0;
+ DEBUG_PRINT_LOW("Demux table complete!");
+ return OMX_ErrorNone;
+}
+
+void omx_vdec::request_perf_level(enum vidc_perf_level perf_level)
+{
+ struct v4l2_control control;
+ char property_value[PROPERTY_VALUE_MAX] = {0};
+
+ property_get("vidc.debug.turbo", property_value, "0");
+ memset(&control, 0, sizeof(v4l2_control));
+ control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL;
+ switch (perf_level) {
+ case VIDC_NOMINAL:
+ if (atoi(property_value))
+ control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO;
+ else
+ control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL;
+ break;
+ case VIDC_TURBO:
+ control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO;
+ break;
+ default:
+ DEBUG_PRINT_ERROR("Requested PERF level not supported");
+ break;
+ }
+ if ((current_perf_level == (OMX_U32)control.value) && !in_reconfig)
+ return;
+
+ DEBUG_PRINT_HIGH("changing performance level to %d", control.value);
+ if (!ioctl(drv_ctx.video_driver_fd, VIDIOC_S_CTRL, &control)) {
+ current_perf_level = control.value;
+ } else {
+ DEBUG_PRINT_ERROR("Failed to set PERF level");
+ }
+}
+
+omx_vdec::allocate_color_convert_buf::allocate_color_convert_buf()
+{
+ enabled = false;
+ omx = NULL;
+ init_members();
+ ColorFormat = OMX_COLOR_FormatMax;
+ dest_format = YCbCr420P;
+ m_c2d_width = 0;
+ m_c2d_height = 0;
+}
+
+void omx_vdec::allocate_color_convert_buf::set_vdec_client(void *client)
+{
+ omx = reinterpret_cast<omx_vdec*>(client);
+}
+
+void omx_vdec::allocate_color_convert_buf::init_members()
+{
+ allocated_count = 0;
+ buffer_size_req = 0;
+ buffer_alignment_req = 0;
+ m_c2d_width = m_c2d_height = 0;
+ memset(m_platform_list_client,0,sizeof(m_platform_list_client));
+ memset(m_platform_entry_client,0,sizeof(m_platform_entry_client));
+ memset(m_pmem_info_client,0,sizeof(m_pmem_info_client));
+ memset(m_out_mem_ptr_client,0,sizeof(m_out_mem_ptr_client));
+#ifdef USE_ION
+ memset(op_buf_ion_info,0,sizeof(m_platform_entry_client));
+#endif
+ for (int i = 0; i < MAX_COUNT; i++)
+ pmem_fd[i] = -1;
+}
+
+omx_vdec::allocate_color_convert_buf::~allocate_color_convert_buf()
+{
+ c2d.destroy();
+}
+
+bool omx_vdec::allocate_color_convert_buf::update_buffer_req()
+{
+ bool status = true;
+ unsigned int src_size = 0, destination_size = 0;
+ unsigned int height, width;
+ struct v4l2_format fmt;
+ OMX_COLOR_FORMATTYPE drv_color_format;
+
+ if (!omx) {
+ DEBUG_PRINT_ERROR("Invalid client in color convert");
+ return false;
+ }
+ if (!enabled) {
+ DEBUG_PRINT_HIGH("No color conversion required");
+ return status;
+ }
+ pthread_mutex_lock(&omx->c_lock);
+
+ memset(&fmt, 0x0, sizeof(struct v4l2_format));
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ fmt.fmt.pix_mp.pixelformat = omx->capture_capability;
+ ioctl(omx->drv_ctx.video_driver_fd, VIDIOC_G_FMT, &fmt);
+ width = fmt.fmt.pix_mp.width;
+ height = fmt.fmt.pix_mp.height;
+
+ bool resolution_upgrade = (height > m_c2d_height ||
+ width > m_c2d_width);
+ if (resolution_upgrade) {
+ // resolution upgraded ? ensure we are yet to allocate;
+ // failing which, c2d buffers will never be reallocated and bad things will happen
+ if (allocated_count > 0) {
+ DEBUG_PRINT_ERROR("Cannot change C2D buffer requirements with %d active allocations",
+ allocated_count);
+ status = false;
+ goto fail_update_buf_req;
+ }
+ }
+
+ if (omx->drv_ctx.output_format != VDEC_YUV_FORMAT_NV12 &&
+ ColorFormat != OMX_COLOR_FormatYUV420Planar) {
+ DEBUG_PRINT_ERROR("update_buffer_req: Unsupported color conversion");
+ status = false;
+ goto fail_update_buf_req;
+ }
+ c2d.close();
+ status = c2d.open(height,
+ width,
+ NV12_128m,dest_format);
+ if (status) {
+ status = c2d.get_buffer_size(C2D_INPUT,src_size);
+ if (status)
+ status = c2d.get_buffer_size(C2D_OUTPUT,destination_size);
+ }
+ if (status) {
+ if (!src_size || src_size > omx->drv_ctx.op_buf.buffer_size ||
+ !destination_size) {
+ DEBUG_PRINT_ERROR("ERROR: Size mismatch in C2D src_size %d"
+ "driver size %u destination size %d",
+ src_size, (unsigned int)omx->drv_ctx.op_buf.buffer_size,
+ destination_size);
+ status = false;
+ c2d.close();
+ buffer_size_req = 0;
+ // TODO: make this fatal. Driver is not supposed to quote size
+ // smaller than what C2D needs !!
+ } else {
+ buffer_size_req = destination_size;
+ m_c2d_height = height;
+ m_c2d_width = width;
+ }
+ }
+fail_update_buf_req:
+ pthread_mutex_unlock(&omx->c_lock);
+ return status;
+}
+
+bool omx_vdec::allocate_color_convert_buf::set_color_format(
+ OMX_COLOR_FORMATTYPE dest_color_format)
+{
+ bool status = true;
+ OMX_COLOR_FORMATTYPE drv_color_format;
+ if (!omx) {
+ DEBUG_PRINT_ERROR("Invalid client in color convert");
+ return false;
+ }
+ pthread_mutex_lock(&omx->c_lock);
+ if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12)
+ if (omx->drv_ctx.decoder_format == VDEC_CODECTYPE_MVC)
+ drv_color_format = (OMX_COLOR_FORMATTYPE)
+ QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
+ else
+ drv_color_format = (OMX_COLOR_FORMATTYPE)
+ QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
+ else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC) {
+ drv_color_format = (OMX_COLOR_FORMATTYPE)
+ QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed;
+ } else {
+ DEBUG_PRINT_ERROR("Incorrect color format");
+ status = false;
+ }
+ if (status &&
+ drv_color_format != dest_color_format &&
+ drv_color_format != (OMX_COLOR_FORMATTYPE)
+ QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView &&
+ drv_color_format != (OMX_COLOR_FORMATTYPE)
+ QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed &&
+ dest_color_format != (OMX_COLOR_FORMATTYPE)
+ QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed) {
+ DEBUG_PRINT_LOW("Enabling C2D");
+ if ((dest_color_format != OMX_COLOR_FormatYUV420Planar) &&
+ (dest_color_format != OMX_COLOR_FormatYUV420SemiPlanar)) {
+ DEBUG_PRINT_ERROR("Unsupported color format for c2d");
+ status = false;
+ } else {
+ ColorFormat = dest_color_format;
+ dest_format = (dest_color_format == OMX_COLOR_FormatYUV420Planar) ?
+ YCbCr420P : YCbCr420SP;
+ if (enabled)
+ c2d.destroy();
+ enabled = false;
+ if (!c2d.init()) {
+ DEBUG_PRINT_ERROR("open failed for c2d");
+ status = false;
+ } else
+ enabled = true;
+ }
+ } else {
+ if (enabled)
+ c2d.destroy();
+ enabled = false;
+ }
+ pthread_mutex_unlock(&omx->c_lock);
+ return status;
+}
+
+OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr()
+{
+ if (!omx) {
+ DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
+ return NULL;
+ }
+ if (!enabled)
+ return omx->m_out_mem_ptr;
+ return m_out_mem_ptr_client;
+}
+
+ OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_il_buf_hdr
+(OMX_BUFFERHEADERTYPE *bufadd)
+{
+ if (!omx) {
+ DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
+ return NULL;
+ }
+ if (!enabled)
+ return bufadd;
+
+ unsigned index = 0;
+ index = bufadd - omx->m_out_mem_ptr;
+ if (index < omx->drv_ctx.op_buf.actualcount) {
+ m_out_mem_ptr_client[index].nFlags = (bufadd->nFlags & OMX_BUFFERFLAG_EOS);
+ m_out_mem_ptr_client[index].nTimeStamp = bufadd->nTimeStamp;
+ bool status;
+ if (!omx->in_reconfig && !omx->output_flush_progress && bufadd->nFilledLen) {
+ pthread_mutex_lock(&omx->c_lock);
+ cache_clean_buffer(index);
+ status = c2d.convert(omx->drv_ctx.ptr_outputbuffer[index].pmem_fd,
+ omx->m_out_mem_ptr->pBuffer, bufadd->pBuffer, pmem_fd[index],
+ pmem_baseaddress[index], pmem_baseaddress[index]);
+ if (!status) {
+ DEBUG_PRINT_ERROR("Failed color conversion %d", status);
+ m_out_mem_ptr_client[index].nFilledLen = 0;
+ pthread_mutex_unlock(&omx->c_lock);
+ return &m_out_mem_ptr_client[index];
+ } else {
+ unsigned int filledLen = 0;
+ c2d.get_output_filled_length(filledLen);
+ m_out_mem_ptr_client[index].nFilledLen = filledLen;
+ cache_clean_invalidate_buffer(index);
+ }
+ pthread_mutex_unlock(&omx->c_lock);
+ } else
+ m_out_mem_ptr_client[index].nFilledLen = 0;
+ return &m_out_mem_ptr_client[index];
+ }
+ DEBUG_PRINT_ERROR("Index messed up in the get_il_buf_hdr");
+ return NULL;
+}
+
+ OMX_BUFFERHEADERTYPE* omx_vdec::allocate_color_convert_buf::get_dr_buf_hdr
+(OMX_BUFFERHEADERTYPE *bufadd)
+{
+ if (!omx) {
+ DEBUG_PRINT_ERROR("Invalid param get_buf_hdr");
+ return NULL;
+ }
+ if (!enabled)
+ return bufadd;
+ unsigned index = 0;
+ index = bufadd - m_out_mem_ptr_client;
+ if (index < omx->drv_ctx.op_buf.actualcount) {
+ return &omx->m_out_mem_ptr[index];
+ }
+ DEBUG_PRINT_ERROR("Index messed up in the get_dr_buf_hdr");
+ return NULL;
+}
+ bool omx_vdec::allocate_color_convert_buf::get_buffer_req
+(unsigned int &buffer_size)
+{
+ bool status = true;
+ pthread_mutex_lock(&omx->c_lock);
+ if (!enabled)
+ buffer_size = omx->drv_ctx.op_buf.buffer_size;
+ else {
+ if (!c2d.get_buffer_size(C2D_OUTPUT,buffer_size)) {
+ DEBUG_PRINT_ERROR("Get buffer size failed");
+ status = false;
+ goto fail_get_buffer_size;
+ }
+ }
+fail_get_buffer_size:
+ pthread_mutex_unlock(&omx->c_lock);
+ return status;
+}
+
+OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::set_buffer_req(
+ OMX_U32 buffer_size, OMX_U32 actual_count) {
+ OMX_U32 expectedSize = enabled ? buffer_size_req : omx->drv_ctx.op_buf.buffer_size;
+
+ if (buffer_size < expectedSize) {
+ DEBUG_PRINT_ERROR("OP Requirements: Client size(%u) insufficient v/s requested(%u)",
+ buffer_size, expectedSize);
+ return OMX_ErrorBadParameter;
+ }
+ if (actual_count < omx->drv_ctx.op_buf.actualcount) {
+ DEBUG_PRINT_ERROR("OP Requirements: Client count(%u) insufficient v/s requested(%u)",
+ actual_count, omx->drv_ctx.op_buf.actualcount);
+ return OMX_ErrorBadParameter;
+ }
+
+ bool reqs_updated = false;
+ if (enabled) {
+ // disallow changing buffer size/count while we have active allocated buffers
+ if (allocated_count > 0) {
+ DEBUG_PRINT_ERROR("Cannot change C2D buffer size from %u to %u with %d active allocations",
+ buffer_size_req, buffer_size, allocated_count);
+ return OMX_ErrorInvalidState;
+ }
+
+ buffer_size_req = buffer_size;
+ } else {
+ if (buffer_size > omx->drv_ctx.op_buf.buffer_size) {
+ omx->drv_ctx.op_buf.buffer_size = buffer_size;
+ reqs_updated = true;
+ }
+ }
+
+ if (actual_count > omx->drv_ctx.op_buf.actualcount) {
+ omx->drv_ctx.op_buf.actualcount = actual_count;
+ reqs_updated = true;
+ }
+
+ if (reqs_updated) {
+ omx->drv_ctx.extradata_info.count = omx->drv_ctx.op_buf.actualcount;
+ omx->drv_ctx.extradata_info.size = omx->drv_ctx.extradata_info.count *
+ omx->drv_ctx.extradata_info.buffer_size;
+ return omx->set_buffer_req(&(omx->drv_ctx.op_buf));
+ }
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::free_output_buffer(
+ OMX_BUFFERHEADERTYPE *bufhdr)
+{
+ unsigned int index = 0;
+
+ if (!enabled)
+ return omx->free_output_buffer(bufhdr);
+ if (enabled && omx->is_component_secure())
+ return OMX_ErrorNone;
+ if (!allocated_count || !bufhdr) {
+ DEBUG_PRINT_ERROR("Color convert no buffer to be freed %p",bufhdr);
+ return OMX_ErrorBadParameter;
+ }
+ index = bufhdr - m_out_mem_ptr_client;
+ if (index >= omx->drv_ctx.op_buf.actualcount) {
+ DEBUG_PRINT_ERROR("Incorrect index color convert free_output_buffer");
+ return OMX_ErrorBadParameter;
+ }
+ if (pmem_fd[index] >= 0) {
+ munmap(pmem_baseaddress[index], buffer_size_req);
+ close(pmem_fd[index]);
+ }
+ pmem_fd[index] = -1;
+#ifdef USE_ION
+ omx->free_ion_memory(&op_buf_ion_info[index]);
+#endif
+ m_heap_ptr[index].video_heap_ptr = NULL;
+ if (allocated_count > 0)
+ allocated_count--;
+ else
+ allocated_count = 0;
+ if (!allocated_count) {
+ pthread_mutex_lock(&omx->c_lock);
+ c2d.close();
+ init_members();
+ pthread_mutex_unlock(&omx->c_lock);
+ }
+ return omx->free_output_buffer(&omx->m_out_mem_ptr[index]);
+}
+
+OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::allocate_buffers_color_convert(OMX_HANDLETYPE hComp,
+ OMX_BUFFERHEADERTYPE **bufferHdr,OMX_U32 port,OMX_PTR appData,OMX_U32 bytes)
+{
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ if (!enabled) {
+ eRet = omx->allocate_output_buffer(hComp,bufferHdr,port,appData,bytes);
+ return eRet;
+ }
+ if (enabled && omx->is_component_secure()) {
+ DEBUG_PRINT_ERROR("Notin color convert mode secure_mode %d",
+ omx->is_component_secure());
+ return OMX_ErrorUnsupportedSetting;
+ }
+ if (!bufferHdr || bytes > buffer_size_req) {
+ DEBUG_PRINT_ERROR("Invalid params allocate_buffers_color_convert %p", bufferHdr);
+ DEBUG_PRINT_ERROR("color_convert buffer_size_req %u bytes %u",
+ (unsigned int)buffer_size_req, (unsigned int)bytes);
+ return OMX_ErrorBadParameter;
+ }
+ if (allocated_count >= omx->drv_ctx.op_buf.actualcount) {
+ DEBUG_PRINT_ERROR("Actual count err in allocate_buffers_color_convert");
+ return OMX_ErrorInsufficientResources;
+ }
+ OMX_BUFFERHEADERTYPE *temp_bufferHdr = NULL;
+ eRet = omx->allocate_output_buffer(hComp,&temp_bufferHdr,
+ port,appData,omx->drv_ctx.op_buf.buffer_size);
+ if (eRet != OMX_ErrorNone || !temp_bufferHdr) {
+ DEBUG_PRINT_ERROR("Buffer allocation failed color_convert");
+ return eRet;
+ }
+ if ((temp_bufferHdr - omx->m_out_mem_ptr) >=
+ (int)omx->drv_ctx.op_buf.actualcount) {
+ DEBUG_PRINT_ERROR("Invalid header index %ld",
+ (long int)(temp_bufferHdr - omx->m_out_mem_ptr));
+ return OMX_ErrorUndefined;
+ }
+ unsigned int i = allocated_count;
+#ifdef USE_ION
+ // Allocate color-conversion buffers as cached to improve software-reading
+ // performance of YUV (thumbnails). NOTE: These buffers will need an explicit
+ // cache invalidation.
+ op_buf_ion_info[i].ion_device_fd = omx->alloc_map_ion_memory(
+ buffer_size_req,buffer_alignment_req,
+ &op_buf_ion_info[i].ion_alloc_data,&op_buf_ion_info[i].fd_ion_data,
+ ION_FLAG_CACHED);
+ pmem_fd[i] = op_buf_ion_info[i].fd_ion_data.fd;
+ if (op_buf_ion_info[i].ion_device_fd < 0) {
+ DEBUG_PRINT_ERROR("alloc_map_ion failed in color_convert");
+ return OMX_ErrorInsufficientResources;
+ }
+ pmem_baseaddress[i] = (unsigned char *)mmap(NULL,buffer_size_req,
+ PROT_READ|PROT_WRITE,MAP_SHARED,pmem_fd[i],0);
+
+ if (pmem_baseaddress[i] == MAP_FAILED) {
+ DEBUG_PRINT_ERROR("MMAP failed for Size %d",buffer_size_req);
+ close(pmem_fd[i]);
+ omx->free_ion_memory(&op_buf_ion_info[i]);
+ return OMX_ErrorInsufficientResources;
+ }
+ m_heap_ptr[i].video_heap_ptr = new VideoHeap (
+ op_buf_ion_info[i].ion_device_fd,buffer_size_req,
+ pmem_baseaddress[i],op_buf_ion_info[i].ion_alloc_data.handle,pmem_fd[i]);
+#endif
+ m_pmem_info_client[i].pmem_fd = (unsigned long)m_heap_ptr[i].video_heap_ptr.get();
+ m_pmem_info_client[i].offset = 0;
+ m_platform_entry_client[i].entry = (void *)&m_pmem_info_client[i];
+ m_platform_entry_client[i].type = OMX_QCOM_PLATFORM_PRIVATE_PMEM;
+ m_platform_list_client[i].nEntries = 1;
+ m_platform_list_client[i].entryList = &m_platform_entry_client[i];
+ m_out_mem_ptr_client[i].pOutputPortPrivate = NULL;
+ m_out_mem_ptr_client[i].nAllocLen = buffer_size_req;
+ m_out_mem_ptr_client[i].nFilledLen = 0;
+ m_out_mem_ptr_client[i].nFlags = 0;
+ m_out_mem_ptr_client[i].nOutputPortIndex = OMX_CORE_OUTPUT_PORT_INDEX;
+ m_out_mem_ptr_client[i].nSize = sizeof(OMX_BUFFERHEADERTYPE);
+ m_out_mem_ptr_client[i].nVersion.nVersion = OMX_SPEC_VERSION;
+ m_out_mem_ptr_client[i].pPlatformPrivate = &m_platform_list_client[i];
+ m_out_mem_ptr_client[i].pBuffer = pmem_baseaddress[i];
+ m_out_mem_ptr_client[i].pAppPrivate = appData;
+ *bufferHdr = &m_out_mem_ptr_client[i];
+ DEBUG_PRINT_HIGH("IL client buffer header %p", *bufferHdr);
+ allocated_count++;
+ return eRet;
+}
+
+bool omx_vdec::is_component_secure()
+{
+ return secure_mode;
+}
+
+bool omx_vdec::allocate_color_convert_buf::get_color_format(OMX_COLOR_FORMATTYPE &dest_color_format)
+{
+ bool status = true;
+ if (!enabled) {
+ if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12) {
+ if (omx->drv_ctx.decoder_format == VDEC_CODECTYPE_MVC)
+ dest_color_format = (OMX_COLOR_FORMATTYPE)
+ QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mMultiView;
+ else
+ dest_color_format = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m;
+ } else if (omx->drv_ctx.output_format == VDEC_YUV_FORMAT_NV12_UBWC){
+ dest_color_format = (OMX_COLOR_FORMATTYPE)QOMX_COLOR_FORMATYUV420PackedSemiPlanar32mCompressed;
+ } else
+ status = false;
+ } else {
+ if (ColorFormat == OMX_COLOR_FormatYUV420Planar ||
+ ColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
+ dest_color_format = ColorFormat;
+ } else
+ status = false;
+ }
+ return status;
+}
+
+OMX_ERRORTYPE omx_vdec::allocate_color_convert_buf::cache_ops(
+ unsigned int index, unsigned int cmd)
+{
+ if (!enabled) {
+ return OMX_ErrorNone;
+ }
+
+ if (!omx || index >= omx->drv_ctx.op_buf.actualcount) {
+ DEBUG_PRINT_ERROR("%s: Invalid param", __func__);
+ return OMX_ErrorBadParameter;
+ }
+
+ struct ion_flush_data flush_data;
+ struct ion_custom_data custom_data;
+
+ memset(&flush_data, 0x0, sizeof(flush_data));
+ memset(&custom_data, 0x0, sizeof(custom_data));
+
+ flush_data.vaddr = pmem_baseaddress[index];
+ flush_data.fd = op_buf_ion_info[index].fd_ion_data.fd;
+ flush_data.handle = op_buf_ion_info[index].fd_ion_data.handle;
+ flush_data.length = buffer_size_req;
+ custom_data.cmd = cmd;
+ custom_data.arg = (unsigned long)&flush_data;
+
+ DEBUG_PRINT_LOW("Cache %s: fd=%d handle=%d va=%p size=%d",
+ (cmd == ION_IOC_CLEAN_CACHES) ? "Clean" : "Invalidate",
+ flush_data.fd, flush_data.handle, flush_data.vaddr,
+ flush_data.length);
+ int ret = ioctl(op_buf_ion_info[index].ion_device_fd, ION_IOC_CUSTOM, &custom_data);
+ if (ret < 0) {
+ DEBUG_PRINT_ERROR("Cache %s failed: %s\n",
+ (cmd == ION_IOC_CLEAN_CACHES) ? "Clean" : "Invalidate",
+ strerror(errno));
+ return OMX_ErrorUndefined;
+ }
+ return OMX_ErrorNone;
+}
+
+void omx_vdec::buf_ref_add(int nPortIndex)
+{
+ unsigned long i = 0;
+ bool buf_present = false;
+ long fd = drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd;
+ OMX_U32 offset = drv_ctx.ptr_outputbuffer[nPortIndex].offset;
+
+ if (!dynamic_buf_mode || !out_dynamic_list) {
+ return;
+ }
+
+ pthread_mutex_lock(&m_lock);
+ for (i = 0; i < drv_ctx.op_buf.actualcount; i++) {
+ //check the buffer fd, offset, uv addr with list contents
+ //If present increment reference.
+ if ((out_dynamic_list[i].fd == fd) &&
+ (out_dynamic_list[i].offset == offset)) {
+ DEBUG_PRINT_LOW("buf_ref_add: [ALREADY PRESENT] fd = %u ref_count = %u",
+ (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count);
+ if (!secure_mode) {
+ drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = out_dynamic_list[i].buffaddr;
+ }
+ buf_present = true;
+ break;
+ }
+ }
+ if (!buf_present) {
+ for (i = 0; i < drv_ctx.op_buf.actualcount; i++) {
+ //search for a entry to insert details of the new buffer
+ if (out_dynamic_list[i].dup_fd < 0) {
+ out_dynamic_list[i].fd = fd;
+ out_dynamic_list[i].offset = offset;
+ out_dynamic_list[i].dup_fd = dup(fd);
+ out_dynamic_list[i].ref_count++;
+ DEBUG_PRINT_LOW("buf_ref_add: [ADDED] fd = %u ref_count = %u",
+ (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count);
+
+ if (!secure_mode) {
+ drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr =
+ (OMX_U8*)mmap(0, drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len,
+ PROT_READ|PROT_WRITE, MAP_SHARED,
+ drv_ctx.ptr_outputbuffer[nPortIndex].pmem_fd, 0);
+ //mmap returns (void *)-1 on failure and sets error code in errno.
+ if (drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr == MAP_FAILED) {
+ DEBUG_PRINT_ERROR("buf_ref_add: mmap failed - errno: %d", errno);
+ drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr = NULL;
+ break;
+ }
+ out_dynamic_list[i].buffaddr = drv_ctx.ptr_outputbuffer[nPortIndex].bufferaddr;
+ out_dynamic_list[i].mapped_size = drv_ctx.ptr_outputbuffer[nPortIndex].buffer_len;
+ DEBUG_PRINT_LOW("mmap: %p %ld", out_dynamic_list[i].buffaddr, out_dynamic_list[i].mapped_size);
+ }
+ break;
+ }
+ }
+ }
+ pthread_mutex_unlock(&m_lock);
+}
+
+void omx_vdec::buf_ref_remove()
+{
+ unsigned long i = 0;
+
+ if (!dynamic_buf_mode || !out_dynamic_list) {
+ return;
+ }
+
+ pthread_mutex_lock(&m_lock);
+ for (i = 0; i < drv_ctx.op_buf.actualcount; i++) {
+ if (!secure_mode && out_dynamic_list[i].buffaddr && out_dynamic_list[i].mapped_size) {
+ DEBUG_PRINT_LOW("munmap: %p %ld", out_dynamic_list[i].buffaddr, out_dynamic_list[i].mapped_size);
+ munmap(out_dynamic_list[i].buffaddr,
+ out_dynamic_list[i].mapped_size);
+ }
+
+ DEBUG_PRINT_LOW("buf_ref_remove: [REMOVED] fd = %u ref_count = %u",
+ (unsigned int)out_dynamic_list[i].fd, (unsigned int)out_dynamic_list[i].ref_count);
+ close(out_dynamic_list[i].dup_fd);
+ out_dynamic_list[i].dup_fd = -1;
+ }
+ pthread_mutex_unlock(&m_lock);
+
+ if (out_dynamic_list) {
+ free(out_dynamic_list);
+ out_dynamic_list = NULL;
+ }
+}
+
+#ifdef _MSM8974_
+void omx_vdec::send_codec_config() {
+ if (codec_config_flag) {
+ unsigned long p1 = 0; // Parameter - 1
+ unsigned long p2 = 0; // Parameter - 2
+ unsigned long 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);
+ }
+}
+#endif
+
+omx_vdec::perf_control::perf_control()
+{
+ m_perf_lib = NULL;
+ m_perf_handle = 0;
+ m_perf_lock_acquire = NULL;
+ m_perf_lock_release = NULL;
+}
+
+omx_vdec::perf_control::~perf_control()
+{
+ if (m_perf_handle != 0 && m_perf_lock_release) {
+ DEBUG_PRINT_LOW("NOTE2: release perf lock");
+ m_perf_lock_release(m_perf_handle);
+ }
+ if (m_perf_lib) {
+ dlclose(m_perf_lib);
+ }
+}
+
+struct omx_vdec::perf_control::mpctl_stats omx_vdec::perf_control::mpctl_obj = {0, 0, 0};
+
+omx_vdec::perf_lock omx_vdec::perf_control::m_perf_lock;
+
+void omx_vdec::perf_control::send_hint_to_mpctl(bool state)
+{
+ if (load_lib() == false) {
+ return;
+ }
+ m_perf_lock.lock();
+ /* 0x4401 maps to video decode playback hint
+ * in perflock, enum number is 44 and state
+ * being sent on perflock acquire is 01 (true)
+ */
+ int arg = 0x4401;
+
+ if (state == true) {
+ mpctl_obj.vid_inst_count++;
+ } else if (state == false) {
+ mpctl_obj.vid_inst_count--;
+ }
+
+ if (m_perf_lock_acquire && mpctl_obj.vid_inst_count == 1 && mpctl_obj.vid_acquired == false) {
+ mpctl_obj.vid_disp_handle = m_perf_lock_acquire(0, 0, &arg, sizeof(arg) / sizeof(int));
+ mpctl_obj.vid_acquired = true;
+ DEBUG_PRINT_INFO("Video slvp perflock acquired");
+ } else if (m_perf_lock_release && (mpctl_obj.vid_inst_count == 0 || mpctl_obj.vid_inst_count > 1) && mpctl_obj.vid_acquired == true) {
+ m_perf_lock_release(mpctl_obj.vid_disp_handle);
+ mpctl_obj.vid_acquired = false;
+ DEBUG_PRINT_INFO("Video slvp perflock released");
+ }
+ m_perf_lock.unlock();
+}
+
+void omx_vdec::perf_control::request_cores(int frame_duration_us)
+{
+ if (frame_duration_us > MIN_FRAME_DURATION_FOR_PERF_REQUEST_US) {
+ return;
+ }
+ bool retVal = load_lib();
+ if (retVal && m_perf_lock_acquire && m_perf_handle == 0) {
+ int arg = 0x700 /*base value*/ + 2 /*cores*/;
+ m_perf_handle = m_perf_lock_acquire(m_perf_handle, 0, &arg, sizeof(arg)/sizeof(int));
+ if (m_perf_handle) {
+ DEBUG_PRINT_HIGH("perf lock acquired");
+ }
+ }
+}
+
+bool omx_vdec::perf_control::load_lib()
+{
+ char perf_lib_path[PROPERTY_VALUE_MAX] = {0};
+ if (m_perf_lib)
+ return true;
+
+ if((property_get("ro.vendor.extension_library", perf_lib_path, NULL) <= 0)) {
+ DEBUG_PRINT_ERROR("vendor library not set in ro.vendor.extension_library");
+ goto handle_err;
+ }
+
+ if ((m_perf_lib = dlopen(perf_lib_path, RTLD_NOW)) == NULL) {
+ DEBUG_PRINT_ERROR("Failed to open %s : %s",perf_lib_path, dlerror());
+ goto handle_err;
+ } else {
+ m_perf_lock_acquire = (perf_lock_acquire_t)dlsym(m_perf_lib, "perf_lock_acq");
+ if (m_perf_lock_acquire == NULL) {
+ DEBUG_PRINT_ERROR("Failed to load symbol: perf_lock_acq");
+ goto handle_err;
+ }
+ m_perf_lock_release = (perf_lock_release_t)dlsym(m_perf_lib, "perf_lock_rel");
+ if (m_perf_lock_release == NULL) {
+ DEBUG_PRINT_ERROR("Failed to load symbol: perf_lock_rel");
+ goto handle_err;
+ }
+ }
+ return true;
+
+handle_err:
+ if (m_perf_lib) {
+ dlclose(m_perf_lib);
+ }
+ m_perf_lib = NULL;
+ return false;
+}
+
+OMX_ERRORTYPE omx_vdec::enable_adaptive_playback(unsigned long nMaxFrameWidth,
+ unsigned long nMaxFrameHeight)
+{
+
+ OMX_ERRORTYPE eRet = OMX_ErrorNone;
+ int ret = 0;
+ unsigned long min_res_buf_count = 0;
+
+ eRet = enable_smoothstreaming();
+ if (eRet != OMX_ErrorNone) {
+ DEBUG_PRINT_ERROR("Failed to enable Adaptive Playback on driver");
+ return eRet;
+ }
+
+ DEBUG_PRINT_HIGH("Enabling Adaptive playback for %lu x %lu",
+ nMaxFrameWidth,
+ nMaxFrameHeight);
+ m_smoothstreaming_mode = true;
+ m_smoothstreaming_width = nMaxFrameWidth;
+ m_smoothstreaming_height = nMaxFrameHeight;
+
+ //Get upper limit buffer count for min supported resolution
+ struct v4l2_format fmt;
+ fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ fmt.fmt.pix_mp.height = m_decoder_capability.min_height;
+ fmt.fmt.pix_mp.width = m_decoder_capability.min_width;
+ fmt.fmt.pix_mp.pixelformat = output_capability;
+
+ ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
+ if (ret) {
+ DEBUG_PRINT_ERROR("Set Resolution failed for HxW = %ux%u",
+ m_decoder_capability.min_height,
+ m_decoder_capability.min_width);
+ return OMX_ErrorUnsupportedSetting;
+ }
+
+ eRet = get_buffer_req(&drv_ctx.op_buf);
+ if (eRet != OMX_ErrorNone) {
+ DEBUG_PRINT_ERROR("failed to get_buffer_req");
+ return eRet;
+ }
+
+ min_res_buf_count = drv_ctx.op_buf.mincount;
+ DEBUG_PRINT_LOW("enable adaptive - upper limit buffer count = %lu for HxW %ux%u",
+ min_res_buf_count, m_decoder_capability.min_height, m_decoder_capability.min_width);
+
+ update_resolution(m_smoothstreaming_width, m_smoothstreaming_height,
+ m_smoothstreaming_width, m_smoothstreaming_height);
+ eRet = is_video_session_supported();
+ if (eRet != OMX_ErrorNone) {
+ DEBUG_PRINT_ERROR("video session is not supported");
+ return eRet;
+ }
+
+ //Get upper limit buffer size for max smooth streaming resolution set
+ fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ fmt.fmt.pix_mp.height = drv_ctx.video_resolution.frame_height;
+ fmt.fmt.pix_mp.width = drv_ctx.video_resolution.frame_width;
+ fmt.fmt.pix_mp.pixelformat = output_capability;
+ ret = ioctl(drv_ctx.video_driver_fd, VIDIOC_S_FMT, &fmt);
+ if (ret) {
+ DEBUG_PRINT_ERROR("Set Resolution failed for adaptive playback");
+ return OMX_ErrorUnsupportedSetting;
+ }
+
+ eRet = get_buffer_req(&drv_ctx.op_buf);
+ if (eRet != OMX_ErrorNone) {
+ DEBUG_PRINT_ERROR("failed to get_buffer_req!!");
+ return eRet;
+ }
+ DEBUG_PRINT_LOW("enable adaptive - upper limit buffer size = %u",
+ (unsigned int)drv_ctx.op_buf.buffer_size);
+
+ drv_ctx.op_buf.mincount = min_res_buf_count;
+ drv_ctx.op_buf.actualcount = min_res_buf_count;
+ drv_ctx.op_buf.buffer_size = drv_ctx.op_buf.buffer_size;
+ eRet = set_buffer_req(&drv_ctx.op_buf);
+ if (eRet != OMX_ErrorNone) {
+ DEBUG_PRINT_ERROR("failed to set_buffer_req");
+ return eRet;
+ }
+
+ eRet = get_buffer_req(&drv_ctx.op_buf);
+ if (eRet != OMX_ErrorNone) {
+ DEBUG_PRINT_ERROR("failed to get_buffer_req!!!");
+ return eRet;
+ }
+ DEBUG_PRINT_HIGH("adaptive playback enabled, buf count = %u bufsize = %u",
+ drv_ctx.op_buf.mincount, (unsigned int)drv_ctx.op_buf.buffer_size);
+ return eRet;
+}
+
+//static
+OMX_ERRORTYPE omx_vdec::describeColorFormat(OMX_PTR pParam) {
+
+#ifndef FLEXYUV_SUPPORTED
+ return OMX_ErrorUndefined;
+#else
+
+ if (pParam == NULL) {
+ DEBUG_PRINT_ERROR("describeColorFormat: invalid params");
+ return OMX_ErrorBadParameter;
+ }
+
+ DescribeColorFormatParams *params = (DescribeColorFormatParams*)pParam;
+
+ MediaImage *img = &(params->sMediaImage);
+ switch(params->eColorFormat) {
+ case QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m:
+ {
+ img->mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
+ img->mNumPlanes = 3;
+ // mWidth and mHeight represent the W x H of the largest plane
+ // In our case, this happens to be the Stride x Scanlines of Y plane
+ img->mWidth = params->nFrameWidth;
+ img->mHeight = params->nFrameHeight;
+ size_t planeWidth = VENUS_Y_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
+ size_t planeHeight = VENUS_Y_SCANLINES(COLOR_FMT_NV12, params->nFrameHeight);
+ img->mBitDepth = 8;
+ //Plane 0 (Y)
+ img->mPlane[MediaImage::Y].mOffset = 0;
+ img->mPlane[MediaImage::Y].mColInc = 1;
+ img->mPlane[MediaImage::Y].mRowInc = planeWidth; //same as stride
+ img->mPlane[MediaImage::Y].mHorizSubsampling = 1;
+ img->mPlane[MediaImage::Y].mVertSubsampling = 1;
+ //Plane 1 (U)
+ img->mPlane[MediaImage::U].mOffset = planeWidth * planeHeight;
+ img->mPlane[MediaImage::U].mColInc = 2; //interleaved UV
+ img->mPlane[MediaImage::U].mRowInc =
+ VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
+ img->mPlane[MediaImage::U].mHorizSubsampling = 2;
+ img->mPlane[MediaImage::U].mVertSubsampling = 2;
+ //Plane 2 (V)
+ img->mPlane[MediaImage::V].mOffset = planeWidth * planeHeight + 1;
+ img->mPlane[MediaImage::V].mColInc = 2; //interleaved UV
+ img->mPlane[MediaImage::V].mRowInc =
+ VENUS_UV_STRIDE(COLOR_FMT_NV12, params->nFrameWidth);
+ img->mPlane[MediaImage::V].mHorizSubsampling = 2;
+ img->mPlane[MediaImage::V].mVertSubsampling = 2;
+ break;
+ }
+
+ case OMX_COLOR_FormatYUV420Planar:
+ case OMX_COLOR_FormatYUV420SemiPlanar:
+ // We need not describe the standard OMX linear formats as these are
+ // understood by client. Fail this deliberately to let client fill-in
+ return OMX_ErrorUnsupportedSetting;
+
+ default:
+ // Rest all formats which are non-linear cannot be described
+ DEBUG_PRINT_LOW("color-format %x is not flexible", params->eColorFormat);
+ img->mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
+ return OMX_ErrorNone;
+ };
+
+ DEBUG_PRINT_LOW("NOTE: Describe color format : %x", params->eColorFormat);
+ DEBUG_PRINT_LOW(" FrameWidth x FrameHeight : %d x %d", params->nFrameWidth, params->nFrameHeight);
+ DEBUG_PRINT_LOW(" YWidth x YHeight : %d x %d", img->mWidth, img->mHeight);
+ for (size_t i = 0; i < img->mNumPlanes; ++i) {
+ DEBUG_PRINT_LOW(" Plane[%zu] : offset=%d / xStep=%d / yStep = %d",
+ i, img->mPlane[i].mOffset, img->mPlane[i].mColInc, img->mPlane[i].mRowInc);
+ }
+ return OMX_ErrorNone;
+#endif //FLEXYUV_SUPPORTED
+}
+
+void omx_vdec::prefetchNewBuffers() {
+
+ struct v4l2_decoder_cmd dec;
+ uint32_t prefetch_count;
+ uint32_t prefetch_size;
+ uint32_t want_size;
+ uint32_t have_size;
+ int color_fmt, rc;
+ uint32_t new_calculated_size;
+ uint32_t new_buffer_size;
+ uint32_t new_buffer_count;
+ uint32_t old_buffer_size;
+ uint32_t old_buffer_count;
+
+ memset((void *)&dec, 0 , sizeof(dec));
+ DEBUG_PRINT_LOW("Old size : %zu, count : %d, width : %u, height : %u\n",
+ drv_ctx.op_buf.buffer_size, drv_ctx.op_buf.actualcount,
+ drv_ctx.video_resolution.frame_width,
+ drv_ctx.video_resolution.frame_height);
+ dec.cmd = V4L2_DEC_QCOM_CMD_RECONFIG_HINT;
+ if (ioctl(drv_ctx.video_driver_fd, VIDIOC_DECODER_CMD, &dec)) {
+ DEBUG_PRINT_ERROR("Buffer info cmd failed : %d\n", errno);
+ } else {
+ DEBUG_PRINT_LOW("From driver, new size is %d, count is %d\n",
+ dec.raw.data[0], dec.raw.data[1]);
+ }
+
+ switch ((int)drv_ctx.output_format) {
+ case VDEC_YUV_FORMAT_NV12:
+ color_fmt = COLOR_FMT_NV12;
+ break;
+ case VDEC_YUV_FORMAT_NV12_UBWC:
+ color_fmt = COLOR_FMT_NV12_UBWC;
+ break;
+ default:
+ color_fmt = -1;
+ DEBUG_PRINT_HIGH("Color format : %x not supported for secure memory prefetching\n", drv_ctx.output_format);
+ return;
+ }
+
+ new_calculated_size = VENUS_BUFFER_SIZE(color_fmt, m_reconfig_width, m_reconfig_height);
+ DEBUG_PRINT_LOW("New calculated size for width : %d, height : %d, is %d\n",
+ m_reconfig_width, m_reconfig_height, new_calculated_size);
+ new_buffer_size = (dec.raw.data[0] > new_calculated_size) ? dec.raw.data[0] : new_calculated_size;
+ new_buffer_count = dec.raw.data[1];
+ old_buffer_size = drv_ctx.op_buf.buffer_size;
+ old_buffer_count = drv_ctx.op_buf.actualcount;
+
+ new_buffer_count = old_buffer_count > new_buffer_count ? old_buffer_count : new_buffer_count;
+
+ prefetch_count = new_buffer_count;
+ prefetch_size = new_buffer_size - old_buffer_size;
+ want_size = new_buffer_size * new_buffer_count;
+ have_size = old_buffer_size * old_buffer_count;
+
+ if (want_size > have_size) {
+ DEBUG_PRINT_LOW("Want: %d, have : %d\n", want_size, have_size);
+ DEBUG_PRINT_LOW("prefetch_count: %d, prefetch_size : %d\n", prefetch_count, prefetch_size);
+
+ int ion_fd = open(MEM_DEVICE, O_RDONLY);
+ if (ion_fd < 0) {
+ DEBUG_PRINT_ERROR("Ion fd open failed : %d\n", ion_fd);
+ return;
+ }
+
+ struct ion_custom_data *custom_data = (struct ion_custom_data*) malloc(sizeof(*custom_data));
+ struct ion_prefetch_data *prefetch_data = (struct ion_prefetch_data*) malloc(sizeof(*prefetch_data));
+ struct ion_prefetch_regions *regions = (struct ion_prefetch_regions*) malloc(sizeof(*regions));
+ size_t *sizes = (size_t*) malloc(sizeof(size_t) * prefetch_count);
+
+ if (custom_data == NULL || prefetch_data == NULL || regions == NULL || sizes == NULL) {
+ DEBUG_PRINT_ERROR("prefetch data allocation failed");
+ goto prefetch_exit;
+ }
+
+ for (uint32_t i = 0; i < prefetch_count; i++) {
+ sizes[i] = prefetch_size;
+ }
+
+ regions[0].nr_sizes = prefetch_count;
+ regions[0].sizes = sizes;
+ regions[0].vmid = ION_FLAG_CP_PIXEL;
+
+ prefetch_data->nr_regions = 1;
+ prefetch_data->regions = regions;
+ prefetch_data->heap_id = ION_HEAP(ION_SECURE_HEAP_ID);
+
+ custom_data->cmd = ION_IOC_PREFETCH;
+ custom_data->arg = (unsigned long )prefetch_data;
+
+ rc = ioctl(ion_fd, ION_IOC_CUSTOM, custom_data);
+ if (rc) {
+ DEBUG_PRINT_ERROR("Custom prefetch ioctl failed rc : %d, errno : %d\n", rc, errno);
+ }
+
+prefetch_exit:
+ close(ion_fd);
+ free(sizes);
+ free(regions);
+ free(prefetch_data);
+ free(custom_data);
+ }
+}
+