blob: 646eddc36622e2d5bf791f296b6568190ed5dd66 [file] [log] [blame]
/*--------------------------------------------------------------------------
Copyright (c) 2009, Code Aurora Forum. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Code Aurora nor
the names of its contributors may be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------*/
/*============================================================================
O p e n M A X w r a p p e r s
O p e n M A X C o r e
*//** @file omx_vdec.c
This module contains the implementation of the OpenMAX core & component.
*//*========================================================================*/
//////////////////////////////////////////////////////////////////////////////
// Include Files
//////////////////////////////////////////////////////////////////////////////
//#define LOG_NDEBUG 0
#define DEBUG_ON 0
#include "qtv_msg.h"
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#ifdef USE_EGL_IMAGE_GPU
#include <EGL/egl.h>
#include <EGL/eglQCOM.h>
#endif
#ifdef _ANDROID_
#include "cutils/properties.h"
#endif //_ANDROID_
#include "adsp.h"
#include "omx_vdec.h"
#include "MP4_Utils.h"
#define H264_START_CODE 0x00000001
#define H264_START_CODE_MASK 0x00FFFFFF
#define VC1_SP_MP_START_CODE 0xC5000000
#define VC1_SP_MP_START_CODE_RCV_V1 0x85000000
#define VC1_SP_MP_START_CODE_MASK 0xFF000000
#define VC1_AP_START_CODE 0x00000100
#define VC1_AP_START_CODE_MASK 0xFFFFFF00
#define VC1_STRUCT_C_LEN 5
#define VC1_AP_SLICE_START_CODE 0x0000010B
#define VC1_AP_SLICE_START_CODE_MASK 0xFFFFFFFF
#define MAKEFOURCC(ch0,ch1,ch2,ch3) ((uint32)(uint8)(ch0) | \
((uint32)(uint8)(ch1) << 8) | \
((uint32)(uint8)(ch2) << 16) | \
((uint32)(uint8)(ch3) << 24 ))
#define EGL_BUFFER_HANDLE_QCOM 0x4F00
#define EGL_BUFFER_OFFSET_QCOM 0x4F01
genericQueue::genericQueue()
{
head = NULL;
tail = NULL;
numElements = 0;
}
int genericQueue::Enqueue(void *data)
{
if (NULL == data)
return 1;
node *new_node = new node;
new_node->data = data;
new_node->next = NULL;
if (0 == numElements) {
head = new_node;
} else {
tail->next = new_node;
}
tail = new_node;
++numElements;
return 0;
}
void *genericQueue::Dequeue()
{
if (!head)
return NULL;
void *retVal = head->data;
node *head_next = head->next;
delete head;
head = head_next;
--numElements;
if (0 == numElements) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"FA: Setting Tail to NULL\n");
tail = NULL;
}
return retVal;
}
int genericQueue::GetSize()
{
int ret = numElements;
return ret;
}
void *genericQueue::checkHead()
{
void *ret = NULL;
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED, "FA: check Head\n");
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"FA: check Head: after mutex\n");
if (head)
ret = head->data;
else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Queue Head is NULL\n");
ret = NULL;
}
return ret;
}
void *genericQueue::checkTail()
{
void *ret = NULL;
if (tail)
ret = tail->data;
else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Tail is NULL\n");
ret = NULL;
}
return ret;
}
genericQueue::~genericQueue()
{
node *tmp = head;
node *tmp_next;
while (tmp) {
tmp_next = tmp->next;
delete tmp;
tmp = tmp_next;
}
head = NULL;
tail = NULL;
}
// omx_cmd_queue destructor
omx_vdec::omx_cmd_queue::~omx_cmd_queue()
{
// Nothing to do
}
// omx cmd queue constructor
omx_vdec::omx_cmd_queue::omx_cmd_queue():m_read(0), m_write(0), m_size(0)
{
memset(m_q, 0, sizeof(omx_event) * OMX_CORE_CONTROL_CMDQ_SIZE);
}
// omx cmd queue insert
bool omx_vdec::omx_cmd_queue::insert_entry(unsigned p1, unsigned p2,
unsigned id)
{
bool ret = true;
if (m_size < OMX_CORE_CONTROL_CMDQ_SIZE) {
m_q[m_write].id = id;
m_q[m_write].param1 = p1;
m_q[m_write].param2 = p2;
m_q[m_write].canceled = false;
m_write++;
m_size++;
if (m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) {
m_write = 0;
}
} else {
ret = false;
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"ERROR!!! Command Queue Full\n");
}
return ret;
}
// omx cmd queue delete
bool omx_vdec::omx_cmd_queue::delete_entry(unsigned *p1, unsigned *p2,
unsigned *id, bool * canceled)
{
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;
if (canceled) {
*canceled = m_q[m_read].canceled;
}
// 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;
}
//#define OMX_VDEC_NONUI_VERSION
#ifdef _ANDROID_
VideoHeap::VideoHeap(int fd, size_t size, void *base)
{
// dup file descriptor, map once, use pmem
init(dup(fd), base, size, 0, "/dev/pmem_adsp");
}
#endif // _ANDROID_
/* ======================================================================
FUNCTION
omx_vdec::omx_vdec
DESCRIPTION
Constructor
PARAMETERS
None
RETURN VALUE
None.
========================================================================== */
omx_vdec::omx_vdec():m_state(OMX_StateInvalid),
m_app_data(NULL),
m_loc_use_buf_hdr(NULL), m_vdec(NULL), m_inp_mem_ptr(NULL),
//m_inp_bm_ptr(NULL),
m_out_mem_ptr(NULL),
//m_out_bm_ptr(NULL),
m_first_pending_buf_idx(-1),
m_outstanding_frames(-OMX_CORE_NUM_OUTPUT_BUFFERS),
m_eos_timestamp(0), m_out_buf_count(OMX_CORE_NUM_OUTPUT_BUFFERS),
//m_out_bm_count(0),
m_inp_buf_count(0),
m_inp_buf_size(OMX_CORE_INPUT_BUFFER_SIZE),
m_inp_bPopulated(OMX_FALSE),
m_out_bPopulated(OMX_FALSE),
m_height(0),
m_width(0),
m_dec_width(0),
m_dec_height(0),
m_crop_x(0),
m_crop_y(0),
m_crop_dx(0),
m_crop_dy(0),
m_bInterlaced(false),
m_port_height(0),
m_port_width(0),
m_nalu_bytes(0),
m_msg_cnt(0),
m_cmd_cnt(0),
m_etb_cnt(0),
m_ebd_cnt(0),
m_ftb_cnt(0),
m_fbd_cnt(0),
m_inp_bEnabled(OMX_TRUE),
m_out_bEnabled(OMX_TRUE),
m_event_port_settings_sent(false),
m_is_use_buffer(false),
m_is_input_use_buffer(false),
m_bEoSNotifyPending(false),
m_platform_list(NULL),
m_platform_entry(NULL),
m_pmem_info(NULL),
m_h264_utils(NULL),
m_pcurrent_frame(NULL),
m_default_arbitrary_bytes(true),
m_default_arbitrary_bytes_vc1(true),
m_default_accumulate_subframe(true),
m_bAccumulate_subframe(false),
m_bArbitraryBytes(true),
m_arbitrary_bytes_input_mem_ptr(NULL),
m_current_arbitrary_bytes_input(NULL),
m_bPartialFrame(false),
m_bStartCode(false), m_header_state(HEADER_STATE_RECEIVED_NONE), m_use_pmem(0),
flush_before_vdec_op_q(NULL),
m_b_divX_parser(false),
m_mp4_utils(NULL),
m_timestamp_interval(0),
m_prev_timestamp(0),
m_b_display_order(false),
m_pPrevFrame(NULL),
m_codec_format(0),
m_codec_profile(0),
m_bInvalidState(false),
m_display_id(NULL),
m_is_use_egl_buffer(false)
{
/* Assumption is that , to begin with , we have all the frames with client */
memset(m_out_flags, 0x00, (OMX_CORE_NUM_OUTPUT_BUFFERS + 7) / 8);
memset(m_flags, 0x00, 4);
memset(&m_cmp, 0, sizeof(m_cmp));
memset(&m_cb, 0, sizeof(m_cb));
memset(&m_vdec_cfg, 0, sizeof(m_vdec_cfg));
m_vdec_cfg.vdec_fd = -1;
m_vdec_cfg.inputBuffer = NULL;
m_vdec_cfg.outputBuffer = NULL;
memset(&m_frame_info, 0, sizeof(m_frame_info));
memset(m_out_bm_count, 0x0, (OMX_CORE_NUM_OUTPUT_BUFFERS + 7) / 8);
memset(m_inp_bm_count, 0x0, (MAX_NUM_INPUT_BUFFERS + 7) / 8);
memset(&m_arbitrary_bytes_info, 0,
sizeof(union omx_arbitrary_bytes_info));
for (int i = 0; i < OMX_CORE_NUM_INPUT_BUFFERS; i++) {
input[i] = NULL;
}
for (int i = 0; i < OMX_CORE_NUM_INPUT_BUFFERS; i++) {
m_arbitrary_bytes_input[i] = NULL;
memset(&m_extra_buf_info[i], 0,
sizeof(struct
omx_extra_arbitrarybytes_buff_info));
m_input_buff_info[i].pArbitrary_bytes_freed = NULL;
m_input_buff_info[i].bfree_input = true;
}
m_vendor_config.pData = NULL;
m_bWaitForResource = false;
m_color_format = (OMX_COLOR_FORMATTYPE)OMX_QCOM_COLOR_FormatYVU420SemiPlanar;
return;
}
/* ======================================================================
FUNCTION
omx_vdec::~omx_vdec
DESCRIPTION
Destructor
PARAMETERS
None
RETURN VALUE
None.
========================================================================== */
omx_vdec::~omx_vdec()
{
m_pmem_info = NULL;
m_nalu_bytes = 0;
m_port_width = m_port_height = 0;
if (flush_before_vdec_op_q) {
delete flush_before_vdec_op_q;
flush_before_vdec_op_q = NULL;
}
return;
}
/* ======================================================================
FUNCTION
omx_vdec::OMXCntrlFrameDoneCbStub
DESCRIPTION
Frame done callback from the video decoder
PARAMETERS
1. ctxt(I) -- Context information to the self.
2. frame(I) -- video frame decoded
RETURN VALUE
None.
========================================================================== */
void omx_vdec::frame_done_cb_stub(struct vdec_context *ctxt,
struct vdec_frame *frame)
{
omx_vdec *pThis = (omx_vdec *) ctxt->extra;
pThis->post_event((unsigned)ctxt, (unsigned)frame,
OMX_COMPONENT_GENERATE_FRAME_DONE);
return;
}
/* ======================================================================
FUNCTION
omx_vdec::frame_done_display_order_cb
DESCRIPTION
Frame done callback from the video decoder with a display order
PARAMETERS
1. ctxt(I) -- Context information to the self.
2. frame(I) -- video frame decoded
RETURN VALUE
None.
========================================================================== */
void omx_vdec::frame_done_display_order_cb(struct vdec_context *ctxt, struct vdec_frame *frame)
{
bool bCurrentBFrame = false;
omx_vdec *pThis = (omx_vdec *) ctxt->extra;
if (pThis->m_pPrevFrame)
{
if (frame->frameDetails.ePicType[0] == VDEC_PICTURE_TYPE_B)
{
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,"frame_done_display_order_cb - b frame");
bCurrentBFrame = true;
}
if (bCurrentBFrame)
{
if (pThis->m_pPrevFrame->timestamp < frame->timestamp)
{
/* Swap timestamp */
pThis->m_pPrevFrame->timestamp ^= frame->timestamp;
frame->timestamp ^= pThis->m_pPrevFrame->timestamp;
pThis->m_pPrevFrame->timestamp ^= frame->timestamp;
}
pThis->frame_done_cb(ctxt, frame);
}
else if (frame->flags & FRAME_FLAG_EOS)
{
pThis->frame_done_cb(ctxt, pThis->m_pPrevFrame);
pThis->frame_done_cb(ctxt, frame);
pThis->m_pPrevFrame = NULL;
}
else
{
if (pThis->m_pPrevFrame->timestamp > frame->timestamp)
{
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,"Warning - previous ts > current ts. And both are non B-frames");
}
pThis->frame_done_cb(ctxt, pThis->m_pPrevFrame);
pThis->m_pPrevFrame = frame;
}
}
else
{
if (frame->flags & FRAME_FLAG_EOS)
{
pThis->frame_done_cb(ctxt, frame);
}
else if (frame->flags & FRAME_FLAG_FLUSHED) {
pThis->frame_done_cb(ctxt, frame);
}
else
{
pThis->m_pPrevFrame = frame;
}
}
}
/* ======================================================================
FUNCTION
omx_vdec::OMXCntrlFrameDoneCb
DESCRIPTION
Frame done callback from the video decoder
PARAMETERS
1. ctxt(I) -- Context information to the self.
2. frame(I) -- video frame decoded
RETURN VALUE
None.
========================================================================== */
void omx_vdec::frame_done_cb(struct vdec_context *ctxt,
struct vdec_frame *frame)
{
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"omx_vdec::frame_done_cb \n");
omx_vdec *pThis = (omx_vdec *) ctxt->extra;
OMX_BUFFERHEADERTYPE *pBufHdr;
pBufHdr = (OMX_BUFFERHEADERTYPE *) pThis->m_out_mem_ptr;
if (pThis->m_out_mem_ptr) {
unsigned int i;
for (i = 0; i < pThis->m_out_buf_count; i++, pBufHdr++) {
if (pBufHdr->pOutputPortPrivate == frame) {
if (BITMASK_ABSENT((pThis->m_out_flags), i)) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"\n Warning: Double framedone - Frame is still with IL client \n");
return;
}
break;
}
}
// Copy from PMEM area to user defined area
if (pThis->omx_vdec_get_use_buf_flg()) {
pThis->omx_vdec_cpy_user_buf(pBufHdr);
}
if (i < pThis->m_out_buf_count) {
BITMASK_CLEAR((pThis->m_out_flags), i);
pThis->m_fbd_cnt++;
QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"FBD: Count %d %x %lld\n",
pThis->m_fbd_cnt, pThis->m_out_flags[0],
frame->timestamp);
if (pThis->m_cb.FillBufferDone) {
OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo =
NULL;
if (pBufHdr->pPlatformPrivate) {
pPMEMInfo =
(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO
*)
((OMX_QCOM_PLATFORM_PRIVATE_LIST *)
pBufHdr->pPlatformPrivate)->
entryList->entry;
QTV_MSG_PRIO2(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"\n PMEM fd %u, Offset %x \n",
(unsigned)pPMEMInfo->
pmem_fd,
(unsigned)pPMEMInfo->
offset);
}
if (frame->flags & FRAME_FLAG_FLUSHED) {
pBufHdr->nFilledLen = 0;
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"\n **** Flushed Frame-%d **** \n",
i);
} else {
if(!pThis->omx_vdec_get_use_egl_buf_flg()) {
pThis->fill_extradata(pBufHdr, frame);
}
else {
pBufHdr->nFilledLen = pThis->get_output_buffer_size();
// Invalidate the cache for the size of the decoded frame
#ifdef USE_PMEM_ADSP_CACHED
vdec_cachemaint(frame->buffer.pmem_id, pBufHdr->pBuffer, pBufHdr->nFilledLen, PMEM_CACHE_INVALIDATE);
#endif
}
}
// If the decoder provides frame done for last frame then set the eos flag.
if ((frame->flags & FRAME_FLAG_EOS)) { /* || // @Temporary blocked
((frame->timestamp > 0) && (frame->timestamp == pThis->m_eos_timestamp))) */
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"\n **** Frame-%d EOS with last timestamp **** \n",
i);
pBufHdr->nFlags |= OMX_BUFFERFLAG_EOS;
}
pBufHdr->nTimeStamp = frame->timestamp;
PrintFrameHdr(pBufHdr);
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"FBD %d with TS %d \n",
pThis->m_fbd_cnt,
(unsigned)pBufHdr->nTimeStamp);
++pThis->m_outstanding_frames;
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"FBD Outstanding frame cnt %d\n",
pThis->m_outstanding_frames);
#ifdef OMX_VDEC_NONUI_VERSION
if ((pThis->m_fbd_cnt < 1)
|| (frame->flags & FRAME_FLAG_FLUSHED)) {
pThis->m_cb.FillBufferDone(&pThis->
m_cmp,
pThis->
m_app_data,
pBufHdr);
} else {
pThis->post_event((unsigned)&pThis->
m_cmp,
(unsigned)pBufHdr,
OMX_COMPONENT_GENERATE_FTB);
}
#else
pThis->m_cb.FillBufferDone(&pThis->m_cmp,
pThis->m_app_data,
pBufHdr);
#endif
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"Error: FrameDoneCb Ignored due to NULL callbacks \n");
}
} else {
if(frame->flags & FRAME_FATAL_ERROR) {
pThis->m_bInvalidState = true;
pThis->m_cb.EventHandler(&pThis->m_cmp, pThis->m_app_data,
OMX_EventError,
OMX_ErrorHardware, 0,
NULL);
return;
}
// fake frame provided by the decoder to indicate end of stream
else if (frame->flags & FRAME_FLAG_EOS) {
OMX_BUFFERHEADERTYPE *pBufHdr =
(OMX_BUFFERHEADERTYPE *) pThis->
m_out_mem_ptr;
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"\n **** Fake Frame EOS **** \n");
for (i = 0; i < pThis->m_out_buf_count;
i++, pBufHdr++) {
if (BITMASK_PRESENT
((pThis->m_out_flags), i)) {
BITMASK_CLEAR((pThis->
m_out_flags), i);
break;
}
}
if (i < pThis->m_out_buf_count) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"EOS Indication used buffer numbered %d\n",
i);
pBufHdr->nFlags |= OMX_BUFFERFLAG_EOS;
pBufHdr->nFilledLen = 0;
pBufHdr->nTimeStamp = frame->timestamp;
if (pBufHdr->nTimeStamp == 0) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"eos timestamp used is %lld\n",
pThis->
m_eos_timestamp);
pBufHdr->nTimeStamp =
pThis->m_eos_timestamp;
}
pThis->m_cb.FillBufferDone(&pThis->
m_cmp,
pThis->
m_app_data,
pBufHdr);
pThis->m_bEoSNotifyPending = false;
++pThis->m_outstanding_frames;
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"FBD Outstanding frame cnt %d\n",
pThis->
m_outstanding_frames);
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"Failed to send EOS to the IL Client\n");
pThis->m_bEoSNotifyPending = true;
}
}
}
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Error: InvalidCb Ignored due to NULL Out storage \n");
}
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
"frame_done_cb buffer->nTimeStamp %d nFlags %d\n",
pBufHdr->nTimeStamp, pBufHdr->nFlags);
return;
}
/* ======================================================================
FUNCTION
omx_vdec::OMXCntrlBufferDoneCbStub
DESCRIPTION
Buffer done callback from the decoder. This stub posts the command to the
decoder pipe which will be executed by the decoder later to the client.
PARAMETERS
1. ctxt(I) -- Context information to the self.
2. cookie(I) -- Context information related to the specific input buffer
RETURN VALUE
true/false
========================================================================== */
void omx_vdec::buffer_done_cb_stub(struct vdec_context *ctxt, void *cookie)
{
omx_vdec *pThis = (omx_vdec *) ctxt->extra;
pThis->post_event((unsigned)ctxt, (unsigned)cookie,
OMX_COMPONENT_GENERATE_BUFFER_DONE);
return;
}
/* ======================================================================
FUNCTION
omx_vdec::OMXCntrlBufferDoneCb
DESCRIPTION
Buffer done callback from the decoder.
PARAMETERS
1. ctxt(I) -- Context information to the self.
2. cookie(I) -- Context information related to the specific input buffer
RETURN VALUE
true/false
========================================================================== */
void omx_vdec::buffer_done_cb(struct vdec_context *ctxt, void *cookie)
{
omx_vdec *pThis = (omx_vdec *) ctxt->extra;
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"buffer Done callback received\n");
if (pThis->m_cb.EmptyBufferDone) {
OMX_BUFFERHEADERTYPE *bufHdr = (OMX_BUFFERHEADERTYPE *) cookie;
PrintFrameHdr(bufHdr);
unsigned int nPortIndex =
bufHdr - (OMX_BUFFERHEADERTYPE *) pThis->m_inp_mem_ptr;
if (nPortIndex < MAX_NUM_INPUT_BUFFERS) {
if (!pThis->is_pending(nPortIndex)) {
if (pThis->m_bArbitraryBytes) {
pThis->
buffer_done_cb_arbitrarybytes(ctxt,
cookie);
} else {
pThis->m_cb.EmptyBufferDone(&pThis->
m_cmp,
pThis->
m_app_data,
bufHdr);
}
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"buffer Done callback received for pending buffer; Ignoring!!\n");
}
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
"Warning!! Buffer Done Callback Came with Incorrect buffer\n");
}
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"BufferDoeCb Ignored due to NULL callbacks \n");
}
return;
}
/* ======================================================================
FUNCTION
omx_vdec::buffer_done_cb_arbitrarybytes
DESCRIPTION
Buffer done callback for arbitrary bytes.
PARAMETERS
1. ctxt(I) -- Context information to the self.
2. cookie(I) -- Context information related to the specific input buffer
RETURN VALUE
true/false
========================================================================== */
void omx_vdec::buffer_done_cb_arbitrarybytes(struct vdec_context *ctxt,
void *cookie)
{
omx_vdec *pThis = (omx_vdec *) ctxt->extra;
OMX_BUFFERHEADERTYPE *bufHdr = (OMX_BUFFERHEADERTYPE *) cookie;
OMX_S8 extra_buf_index =
pThis->find_extra_buffer_index(bufHdr->pBuffer);
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
"buffer_done_cb_arbitrarybytes %d\n", extra_buf_index);
if (extra_buf_index != -1) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"buffer Done callback - end of arbitrary bytes buffer!!\n");
pThis->free_extra_buffer(extra_buf_index);
unsigned int nPortIndex =
pThis->m_extra_buf_info[extra_buf_index].
arbitrarybytesInput -
(OMX_BUFFERHEADERTYPE *) pThis->
m_arbitrary_bytes_input_mem_ptr;
if (nPortIndex < MAX_NUM_INPUT_BUFFERS) {
pThis->m_cb.EmptyBufferDone(&pThis->m_cmp,
pThis->m_app_data,
pThis->
m_extra_buf_info
[extra_buf_index].
arbitrarybytesInput);
pThis->m_extra_buf_info[extra_buf_index].
arbitrarybytesInput = NULL;
pThis->push_pending_buffers_proxy();
} else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
"Incorrect previous arbitrary bytes buffer %p\n",
pThis->m_extra_buf_info[extra_buf_index].
arbitrarybytesInput);
}
}
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"buffer Done callback - m_bPartialFrame %d m_current_frame %p\n",
pThis->m_bPartialFrame, pThis->m_current_frame);
pThis->free_input_buffer(bufHdr);
}
/* ======================================================================
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(struct vdec_context *ctxt, unsigned char id)
{
unsigned p1; // Parameter - 1
unsigned p2; // Parameter - 2
unsigned ident = 0;
unsigned qsize = 0; // qsize
omx_vdec *pThis = (omx_vdec *) ctxt->extra;
bool canceled = false;
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"OMXCntrlProessMsgCb[%x,%d] Enter: \n", (unsigned)ctxt,
(unsigned)id);
if (!pThis) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"ERROR : ProcessMsgCb: Context is incorrect; bailing out\n");
return;
}
// Protect the shared queue data structure
do {
canceled = false;
pThis->mutex_lock();
qsize = pThis->m_ftb_q.m_size;
if (qsize) {
pThis->m_ftb_q.delete_entry(&p1, &p2, &ident,
&canceled);
if (canceled) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_HIGH,
"canceled ftb %x", p2);
pThis->mutex_unlock();
continue;
}
} else {
qsize = pThis->m_cmd_q.m_size;
if (qsize) {
pThis->m_cmd_q.delete_entry(&p1, &p2, &ident);
} else if (pThis->m_bArbitraryBytes) {
if (pThis->m_current_arbitrary_bytes_input !=
NULL) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"process_event_cb - continue using m_current_arbitrary_bytes_input %p\n",
pThis->
m_current_arbitrary_bytes_input);
ident =
OMX_COMPONENT_GENERATE_ETB_ARBITRARYBYTES;
} else if (qsize =
pThis->m_etb_arbitrarybytes_q.
m_size) {
QTV_MSG_PRIO3(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"ETBQ[%d] FTBQ[%d] CMDQ[%d]\n",
pThis->
m_etb_arbitrarybytes_q.
m_size,
pThis->m_ftb_q.m_size,
pThis->m_cmd_q.m_size);
pThis->m_etb_arbitrarybytes_q.
delete_entry(&p1, &p2, &ident);
pThis->m_current_arbitrary_bytes_input =
(OMX_BUFFERHEADERTYPE *) p2;
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"set m_current_arbitrary_bytes_input %p %d\n",
pThis->
m_current_arbitrary_bytes_input);
}
}
}
if (qsize) {
pThis->m_msg_cnt++;
}
pThis->mutex_unlock();
if ((qsize > 0)
|| (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARYBYTES)) {
id = ident;
QTV_MSG_PRIO7(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Process ->%d[%d]ebd %d fbd %d oc %d %x,%x\n",
pThis->m_state, ident, pThis->m_etb_cnt,
pThis->m_fbd_cnt,
pThis->m_outstanding_frames,
pThis->m_flags[0] ,
pThis->m_out_flags[0]);
if (id == OMX_COMPONENT_GENERATE_EVENT) {
if (pThis->m_cb.EventHandler) {
if (p1 == OMX_CommandStateSet) {
pThis->m_state =
(OMX_STATETYPE) p2;
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"Process -> state set to %d \n",
pThis->m_state);
pThis->m_cb.
EventHandler(&pThis->m_cmp,
pThis->
m_app_data,
OMX_EventCmdComplete,
p1, p2, NULL);
}
/* posting error events for illegal state transition */
else if (p1 == OMX_EventError) {
if (p2 == OMX_ErrorInvalidState) {
pThis->m_state =
OMX_StateInvalid;
pThis->m_cb.
EventHandler
(&pThis->m_cmp,
pThis->m_app_data,
OMX_EventError,
OMX_ErrorInvalidState,
0, NULL);
pThis->
execute_omx_flush
(OMX_ALL);
} else {
pThis->m_cb.
EventHandler
(&pThis->m_cmp,
pThis->m_app_data,
OMX_EventError, p2,
0, NULL);
}
} else if (p1 == OMX_CommandPortDisable) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"Process -> Port %d set to PORT_STATE_DISABLED state \n",
p2);
pThis->m_cb.
EventHandler(&pThis->m_cmp,
pThis->
m_app_data,
OMX_EventCmdComplete,
p1, p2, NULL);
} else if (p1 == OMX_CommandPortEnable) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"Process -> Port %d set to PORT_STATE_ENABLED state \n",
p2);
pThis->m_cb.
EventHandler(&pThis->m_cmp,
pThis->
m_app_data,
OMX_EventCmdComplete,
p1, p2, NULL);
} else {
pThis->m_cb.
EventHandler(&pThis->m_cmp,
pThis->
m_app_data,
OMX_EventCmdComplete,
p1, p2, NULL);
}
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"Error: ProcessMsgCb ignored due to NULL callbacks\n");
}
} else if (id == OMX_COMPONENT_GENERATE_EVENT_FLUSH) {
pThis->m_cb.EventHandler(&pThis->m_cmp,
pThis->m_app_data,
OMX_EventCmdComplete,
p1, p2, NULL);
} else if (id == OMX_COMPONENT_GENERATE_BUFFER_DONE) {
buffer_done_cb((struct vdec_context *)p1,
(void *)p2);
} else if (id == OMX_COMPONENT_GENERATE_FRAME_DONE) {
if (pThis->m_b_display_order)
{
frame_done_display_order_cb((struct vdec_context *)p1,(struct vdec_frame *)p2);
}
else
{
frame_done_cb((struct vdec_context *)p1,
(struct vdec_frame *)p2);
}
} else if (id == OMX_COMPONENT_GENERATE_ETB) {
pThis->
empty_this_buffer_proxy_frame_based((OMX_HANDLETYPE) p1, (OMX_BUFFERHEADERTYPE *) p2);
} else if (id ==
OMX_COMPONENT_GENERATE_ETB_ARBITRARYBYTES) {
pThis->
empty_this_buffer_proxy_arbitrary_bytes((OMX_HANDLETYPE) p1, pThis->m_current_arbitrary_bytes_input);
} else if (id == OMX_COMPONENT_GENERATE_FTB) {
pThis->
fill_this_buffer_proxy((OMX_HANDLETYPE) p1,
(OMX_BUFFERHEADERTYPE
*) p2);
} else if (id == OMX_COMPONENT_GENERATE_COMMAND) {
pThis->send_command_proxy(&pThis->m_cmp,
(OMX_COMMANDTYPE) p1,
(OMX_U32) p2,
(OMX_PTR) NULL);
} else if (id == OMX_COMPONENT_PUSH_PENDING_BUFS) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"process_event_cb :: push_pending_buffer_proxy\n");
pThis->push_pending_buffers_proxy();
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"Error: ProcessMsgCb Ignored due to Invalid Identifier\n");
}
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"OMXCntrlProessMsgCb[%x,%d] Exit: \n",
(unsigned)ctxt, (unsigned)id);
}
if (pThis->m_bArbitraryBytes) {
unsigned cmd_ftb_qsize = 0;
pThis->mutex_lock();
cmd_ftb_qsize =
pThis->m_cmd_q.m_size + pThis->m_ftb_q.m_size;
qsize =
cmd_ftb_qsize +
pThis->m_etb_arbitrarybytes_q.m_size;
QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"process_event_cb %d %d %d\n",
pThis->m_cmd_q.m_size,
pThis->m_ftb_q.m_size,
pThis->m_etb_arbitrarybytes_q.m_size);
pThis->mutex_unlock();
if (cmd_ftb_qsize == 0 && pThis->m_bWaitForResource) {
// if cmd_ftb_qsize >0, always come back to process those, otherwise if we are out of buffer
// wait until free_input_buffer is called when q6 sends a buffer done, don't loop forever.
qsize = 0;
} else if (qsize == 0
&& pThis->m_current_arbitrary_bytes_input) {
qsize = 1;
}
} else {
pThis->mutex_lock();
qsize = pThis->m_cmd_q.m_size + pThis->m_ftb_q.m_size;
pThis->mutex_unlock();
}
} while (qsize > 0);
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"process_event_cb Exit\n");
return;
}
/* ======================================================================
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)
{
#ifdef _ANDROID_
char property_value[PROPERTY_VALUE_MAX] = {0};
#endif
OMX_ERRORTYPE eRet = OMX_ErrorNone;
int r, fd;
fd = open("/dev/vdec", O_RDWR);
if(fd < 0)
{
QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"Omx_vdec::Comp Init Returning failure\n");
// Another decoder instance is running. return from here.
return OMX_ErrorInsufficientResources;
}
//close(fd);
m_vdec_cfg.vdec_fd = fd;
#ifdef _ANDROID_
if(0 != property_get("persist.omxvideo.arb-bytes", property_value, NULL))
{
if(!strcmp(property_value, "false"))
{
m_default_arbitrary_bytes = false;
}
}
else
{
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR, "OMX_VDEC:: Comp Init failed in \
getting value for the Android property [persist.omxvideo.arb-bytes]");
}
if(0 != property_get("persist.omxvideo.arb-bytes-vc1", property_value, NULL))
{
if(!strcmp(property_value, "false"))
{
m_default_arbitrary_bytes_vc1 = false;
}
}
else
{
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR, "OMX_VDEC:: Comp Init failed in \
getting value for the Android property [persist.omxvideo.arb-bytes-vc1]");
}
if(0 != property_get("persist.omxvideo.accsubframe", property_value, NULL))
{
if(!strcmp(property_value, "false"))
{
m_default_accumulate_subframe = false;
}
}
else
{
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR, "OMX_VDEC:: Comp Init failed in \
getting value for the Android property [persist.omxvideo.accsubframe]");
}
#endif
m_vdec_cfg.buffer_done = buffer_done_cb_stub;
m_vdec_cfg.frame_done = frame_done_cb_stub;
m_vdec_cfg.process_message = process_event_cb;
m_vdec_cfg.height = OMX_CORE_QCIF_HEIGHT;
m_vdec_cfg.width = OMX_CORE_QCIF_WIDTH;
m_vdec_cfg.extra = this;
// Copy the role information which provides the decoder kind
strncpy(m_vdec_cfg.kind, role, 128);
if (!strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.mpeg4",
OMX_MAX_STRINGNAME_SIZE)) {
strncpy((char *)m_cRole, "video_decoder.mpeg4",
OMX_MAX_STRINGNAME_SIZE);
m_vdec_cfg.fourcc = MAKEFOURCC('m', 'p', '4', 'v');
} else
if (!strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.h263",
OMX_MAX_STRINGNAME_SIZE)) {
strncpy((char *)m_cRole, "video_decoder.h263",
OMX_MAX_STRINGNAME_SIZE);
m_vdec_cfg.fourcc = MAKEFOURCC('h', '2', '6', '3');
} else
if (!strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc",
OMX_MAX_STRINGNAME_SIZE)) {
strncpy((char *)m_cRole, "video_decoder.avc",
OMX_MAX_STRINGNAME_SIZE);
m_vdec_cfg.fourcc = MAKEFOURCC('h', '2', '6', '4');
} else
if (!strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.vc1",
OMX_MAX_STRINGNAME_SIZE)) {
strncpy((char *)m_cRole, "video_decoder.vc1",
OMX_MAX_STRINGNAME_SIZE);
m_vdec_cfg.fourcc = MAKEFOURCC('w', 'm', 'v', '3');
} else
if(!strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.divx",
OMX_MAX_STRINGNAME_SIZE)) {
strncpy((char *)m_cRole, "video_decoder.divx",
OMX_MAX_STRINGNAME_SIZE);
m_vdec_cfg.fourcc = MAKEFOURCC('D', 'I', 'V', 'X');
}else
if (!strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.vp",
OMX_MAX_STRINGNAME_SIZE)) {
strncpy((char *)m_cRole, "video_decoder.vp",
OMX_MAX_STRINGNAME_SIZE);
m_vdec_cfg.fourcc = MAKEFOURCC('V', 'P', '6', '0');
} else
if (!strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.spark",
OMX_MAX_STRINGNAME_SIZE)) {
strncpy((char *)m_cRole, "video_decoder.spark",
OMX_MAX_STRINGNAME_SIZE);
m_vdec_cfg.fourcc = MAKEFOURCC('F', 'L', 'V', '1');
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"\n Unknown Component\n");
eRet = OMX_ErrorInvalidComponentName;
}
if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.divx", 27) == 0) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Mp4 output buffer Count updated\n");
m_out_buf_count = OMX_CORE_NUM_OUTPUT_BUFFERS_MP4;
m_outstanding_frames = -OMX_CORE_NUM_OUTPUT_BUFFERS_MP4;
m_bArbitraryBytes = false;
m_b_divX_parser = true;
memset(&m_divX_buffer_info, 0, sizeof(m_divX_buffer_info));
m_divX_buffer_info.parsing_required = true;
m_mp4_utils = new MP4_Utils();
m_b_display_order = true;
m_codec_format = QOMX_VIDEO_DIVXFormat4;
} else if ( (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.h263", 27) == 0 )
|| (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.spark", 28) == 0)
|| (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.mpeg4", 28) == 0)
) {
m_out_buf_count = OMX_CORE_NUM_OUTPUT_BUFFERS_MP4;
m_outstanding_frames = -OMX_CORE_NUM_OUTPUT_BUFFERS_MP4;
m_mp4_utils = new MP4_Utils();
} else if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc", 26) ==
0) {
m_h264_utils = new H264_Utils();
m_bAccumulate_subframe = true; // by default
m_bAccumulate_subframe = (m_bAccumulate_subframe && m_default_accumulate_subframe);
m_out_buf_count = OMX_CORE_NUM_OUTPUT_BUFFERS_H264;
m_outstanding_frames = -OMX_CORE_NUM_OUTPUT_BUFFERS_H264;
} else if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.vc1", 26) ==
0) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"VC1 component init\n");
m_out_buf_count = OMX_CORE_NUM_OUTPUT_BUFFERS_VC1;
m_outstanding_frames = -OMX_CORE_NUM_OUTPUT_BUFFERS_VC1;
m_bAccumulate_subframe = true;
m_bArbitraryBytes = false;
m_bAccumulate_subframe = (m_bAccumulate_subframe && m_default_accumulate_subframe);
} else if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.vp", 25) ==
0) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"VP6 component init\n");
m_out_buf_count = OMX_CORE_NUM_OUTPUT_BUFFERS_VC1;
m_outstanding_frames = -OMX_CORE_NUM_OUTPUT_BUFFERS_VC1;
m_bAccumulate_subframe = false;
m_bArbitraryBytes = false;
}
if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.vc1", 26) == 0)
{
m_bArbitraryBytes = (m_bArbitraryBytes && m_default_arbitrary_bytes_vc1);
}
else
{
m_bArbitraryBytes = (m_bArbitraryBytes && m_default_arbitrary_bytes);
}
m_crop_dy = m_height = m_vdec_cfg.height;
m_crop_dx = m_width = m_vdec_cfg.width;
m_port_height = m_height;
m_port_width = m_width;
m_state = OMX_StateLoaded;
m_first_pending_buf_idx = -1;
flush_before_vdec_op_q = new genericQueue();
if(flush_before_vdec_op_q == NULL) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,"flush_before_vdec_op_q creation failed\n");
eRet = OMX_ErrorInsufficientResources;
}
eRet = create_msg_thread();
return eRet;
}
/* ======================================================================
FUNCTION
omx_vdec::GetComponentVersion
DESCRIPTION
Returns the component version.
PARAMETERS
TBD.
RETURN VALUE
OMX_ErrorNone.
========================================================================== */
OMX_ERRORTYPE omx_vdec::get_component_version(OMX_IN OMX_HANDLETYPE hComp,
OMX_OUT OMX_STRING componentName,
OMX_OUT OMX_VERSIONTYPE *
componentVersion,
OMX_OUT OMX_VERSIONTYPE *
specVersion,
OMX_OUT OMX_UUIDTYPE *
componentUUID)
{
if (m_state == OMX_StateInvalid) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Get Comp Version in Invalid State\n");
return OMX_ErrorInvalidState;
}
/* TBD -- Return the proper 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)
{
if (m_state == OMX_StateInvalid) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Send Command in Invalid State\n");
return OMX_ErrorInvalidState;
}
post_event((unsigned)cmd, (unsigned)param1,
OMX_COMPONENT_GENERATE_COMMAND);
semaphore_wait();
return OMX_ErrorNone;
}
/* ======================================================================
FUNCTION
omx_vdec::SendCommand
DESCRIPTION
Returns zero if all the buffers released..
PARAMETERS
None.
RETURN VALUE
true/false
========================================================================== */
OMX_ERRORTYPE omx_vdec::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,
OMX_IN OMX_COMMANDTYPE cmd,
OMX_IN OMX_U32 param1,
OMX_IN OMX_PTR cmdData)
{
OMX_ERRORTYPE eRet = OMX_ErrorNone;
// Handle only IDLE and executing
OMX_STATETYPE eState = (OMX_STATETYPE) param1;
int bFlag = 1;
if (cmd == OMX_CommandStateSet) {
/***************************/
/* Current State is Loaded */
/***************************/
if (m_state == OMX_StateLoaded) {
if (eState == OMX_StateIdle) {
if (allocate_done() ||
(m_inp_bEnabled == OMX_FALSE
&& m_out_bEnabled == OMX_FALSE)) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"OMXCORE-SM: Loaded-->Idle\n");
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"OMXCORE-SM: Loaded-->Idle-Pending\n");
BITMASK_SET(m_flags,
OMX_COMPONENT_IDLE_PENDING);
// Skip the event notification
bFlag = 0;
}
}
/* Requesting transition from Loaded to Loaded */
else if (eState == OMX_StateLoaded) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"OMXCORE-SM: Loaded-->Loaded\n");
post_event(OMX_EventError, OMX_ErrorSameState,
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorSameState;
}
/* Requesting transition from Loaded to WaitForResources */
else if (eState == OMX_StateWaitForResources) {
/* Since error is None , we will post an event at the end of this function definition */
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"OMXCORE-SM: Loaded-->WaitForResources\n");
}
/* Requesting transition from Loaded to Executing */
else if (eState == OMX_StateExecuting) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"OMXCORE-SM: Loaded-->Executing\n");
post_event(OMX_EventError,
OMX_ErrorIncorrectStateTransition,
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorIncorrectStateTransition;
}
/* Requesting transition from Loaded to Pause */
else if (eState == OMX_StatePause) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"OMXCORE-SM: Loaded-->Pause\n");
post_event(OMX_EventError,
OMX_ErrorIncorrectStateTransition,
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorIncorrectStateTransition;
}
/* Requesting transition from Loaded to Invalid */
else if (eState == OMX_StateInvalid) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"OMXCORE-SM: Loaded-->Invalid\n");
post_event(OMX_EventError,
OMX_ErrorInvalidState,
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorInvalidState;
} else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"OMXCORE-SM: Loaded-->Invalid(%d Not Handled)\n",
eState);
eRet = OMX_ErrorBadParameter;
}
}
/***************************/
/* Current State is IDLE */
/***************************/
else if (m_state == OMX_StateIdle) {
if (eState == OMX_StateLoaded) {
if (release_done()) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"OMXCORE-SM: Idle-->Loaded\n");
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"OMXCORE-SM: Idle-->Loaded-Pending\n");
BITMASK_SET(m_flags,
OMX_COMPONENT_LOADING_PENDING);
// Skip the event notification
bFlag = 0;
}
} else if (eState == OMX_StateExecuting) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"OMXCORE-SM: Idle-->Executing\n");
if (m_bArbitraryBytes) {
initialize_arbitrary_bytes_environment
();
}
if (m_h264_utils) {
m_h264_utils->
initialize_frame_checking_environment
();
}
}
/* Requesting transition from Idle to Idle */
else if (eState == OMX_StateIdle) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"OMXCORE-SM: Idle-->Idle\n");
post_event(OMX_EventError, OMX_ErrorSameState,
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorSameState;
}
/* Requesting transition from Idle to WaitForResources */
else if (eState == OMX_StateWaitForResources) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"OMXCORE-SM: Idle-->WaitForResources\n");
post_event(OMX_EventError,
OMX_ErrorIncorrectStateTransition,
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorIncorrectStateTransition;
}
/* Requesting transition from Idle to Pause */
else if (eState == OMX_StatePause) {
/* Since error is None , we will post an event at the end of this function definition */
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"OMXCORE-SM: Idle-->Pause\n");
}
/* Requesting transition from Idle to Invalid */
else if (eState == OMX_StateInvalid) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"OMXCORE-SM: Idle-->Invalid\n");
post_event(OMX_EventError,
OMX_ErrorInvalidState,
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorInvalidState;
} else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"OMXCORE-SM: Idle --> %d Not Handled\n",
eState);
eRet = OMX_ErrorBadParameter;
}
}
/******************************/
/* Current State is Executing */
/******************************/
else if (m_state == OMX_StateExecuting) {
if (eState == OMX_StateIdle) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"\n OMXCORE-SM: Executing --> Idle \n");
execute_omx_flush(OMX_ALL);
} else if (eState == OMX_StatePause) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"\n OMXCORE-SM: Executing --> Paused \n");
}
/* Requesting transition from Executing to Loaded */
else if (eState == OMX_StateLoaded) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"\n OMXCORE-SM: Executing --> Loaded \n");
post_event(OMX_EventError,
OMX_ErrorIncorrectStateTransition,
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorIncorrectStateTransition;
}
/* Requesting transition from Executing to WaitForResources */
else if (eState == OMX_StateWaitForResources) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"\n OMXCORE-SM: Executing --> WaitForResources \n");
post_event(OMX_EventError,
OMX_ErrorIncorrectStateTransition,
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorIncorrectStateTransition;
}
/* Requesting transition from Executing to Executing */
else if (eState == OMX_StateExecuting) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"\n OMXCORE-SM: Executing --> Executing \n");
post_event(OMX_EventError, OMX_ErrorSameState,
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorSameState;
}
/* Requesting transition from Executing to Invalid */
else if (eState == OMX_StateInvalid) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"\n OMXCORE-SM: Executing --> Invalid \n");
post_event(OMX_EventError,
OMX_ErrorInvalidState,
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorInvalidState;
} else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"OMXCORE-SM: Executing --> %d Not Handled\n",
eState);
eRet = OMX_ErrorBadParameter;
}
}
/***************************/
/* Current State is Pause */
/***************************/
else if (m_state == OMX_StatePause) {
if (eState == OMX_StateExecuting) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"\n Pause --> Executing \n");
} else if (eState == OMX_StateIdle) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"\n Pause --> Idle \n");
execute_omx_flush(OMX_ALL);
}
/* Requesting transition from Pause to loaded */
else if (eState == OMX_StateLoaded) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"\n Pause --> loaded \n");
post_event(OMX_EventError,
OMX_ErrorIncorrectStateTransition,
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorIncorrectStateTransition;
}
/* Requesting transition from Pause to WaitForResources */
else if (eState == OMX_StateWaitForResources) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"\n Pause --> WaitForResources \n");
post_event(OMX_EventError,
OMX_ErrorIncorrectStateTransition,
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorIncorrectStateTransition;
}
/* Requesting transition from Pause to Pause */
else if (eState == OMX_StatePause) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"\n Pause --> Pause \n");
post_event(OMX_EventError, OMX_ErrorSameState,
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorSameState;
}
/* Requesting transition from Pause to Invalid */
else if (eState == OMX_StateInvalid) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"\n Pause --> Invalid \n");
post_event(OMX_EventError,
OMX_ErrorInvalidState,
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorInvalidState;
} else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"OMXCORE-SM: Paused --> %d Not Handled\n",
eState);
eRet = OMX_ErrorBadParameter;
}
}
/***************************/
/* Current State is WaitForResources */
/***************************/
else if (m_state == OMX_StateWaitForResources) {
/* Requesting transition from WaitForResources to Loaded */
if (eState == OMX_StateLoaded) {
/* Since error is None , we will post an event at the end of this function definition */
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"OMXCORE-SM: WaitForResources-->Loaded\n");
}
/* Requesting transition from WaitForResources to WaitForResources */
else if (eState == OMX_StateWaitForResources) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"OMXCORE-SM: WaitForResources-->WaitForResources\n");
post_event(OMX_EventError, OMX_ErrorSameState,
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorSameState;
}
/* Requesting transition from WaitForResources to Executing */
else if (eState == OMX_StateExecuting) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"OMXCORE-SM: WaitForResources-->Executing\n");
post_event(OMX_EventError,
OMX_ErrorIncorrectStateTransition,
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorIncorrectStateTransition;
}
/* Requesting transition from WaitForResources to Pause */
else if (eState == OMX_StatePause) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"OMXCORE-SM: WaitForResources-->Pause\n");
post_event(OMX_EventError,
OMX_ErrorIncorrectStateTransition,
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorIncorrectStateTransition;
}
/* Requesting transition from WaitForResources to Invalid */
else if (eState == OMX_StateInvalid) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"OMXCORE-SM: WaitForResources-->Invalid\n");
post_event(OMX_EventError,
OMX_ErrorInvalidState,
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorInvalidState;
}
/* Requesting transition from WaitForResources to Loaded - is NOT tested by Khronos TS */
} else {
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"OMXCORE-SM: %d --> %d(Not Handled)\n",
m_state, eState);
eRet = OMX_ErrorBadParameter;
}
}
/********************************/
/* Current State is Invalid */
/*******************************/
else if (m_state == OMX_StateInvalid) {
/* State Transition from Inavlid to any state */
if (eState ==
(OMX_StateLoaded || OMX_StateWaitForResources
|| OMX_StateIdle || OMX_StateExecuting || OMX_StatePause
|| OMX_StateInvalid)) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"OMXCORE-SM: Invalid -->Loaded\n");
post_event(OMX_EventError, OMX_ErrorInvalidState,
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorInvalidState;
}
} else if (cmd == OMX_CommandFlush) {
execute_omx_flush(param1);
if (0 == param1 || OMX_ALL == param1) {
//generate input flush event only.
post_event(OMX_CommandFlush, OMX_CORE_INPUT_PORT_INDEX,
OMX_COMPONENT_GENERATE_EVENT_FLUSH);
}
if (1 == param1 || OMX_ALL == param1) {
//generate output flush event only.
post_event(OMX_CommandFlush, OMX_CORE_OUTPUT_PORT_INDEX,
OMX_COMPONENT_GENERATE_EVENT_FLUSH);
}
bFlag = 0;
} else if (cmd == OMX_CommandPortEnable) {
if (param1 != OMX_CORE_OUTPUT_PORT_INDEX) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"OMXCORE-SM:Enable should be on Ouput Port\n");
}
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"OMXCORE-SM:Recieved command ENABLE (%d)\n", cmd);
// call vdec_open
if (!m_vdec && (m_first_pending_buf_idx >= 0)) {
if (m_vendor_config.pData) {
m_vdec_cfg.sequenceHeader =
m_vendor_config.pData;
m_vdec_cfg.sequenceHeaderLen =
m_vendor_config.nDataSize;
m_vdec_cfg.height = m_port_height;
m_vdec_cfg.width = m_port_width;
m_vdec_cfg.size_of_nal_length_field =
m_nalu_bytes;
m_vdec_cfg.color_format = m_color_format;
m_vdec = vdec_open(&m_vdec_cfg);
eRet =
(m_vdec ==
NULL) ? OMX_ErrorHardware : OMX_ErrorNone;
} else {
eRet =
omx_vdec_create_native_decoder(input
[m_first_pending_buf_idx]);
}
if (OMX_ErrorNone != eRet) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"Native decoder creation failed\n");
semaphore_post();
return eRet;
}
OMX_BUFFERHEADERTYPE *tmp_buf_hdr =
(OMX_BUFFERHEADERTYPE *) flush_before_vdec_op_q->
Dequeue();
while (tmp_buf_hdr) {
vdec_release_frame(m_vdec,
(vdec_frame *) tmp_buf_hdr->
pOutputPortPrivate);
tmp_buf_hdr =
(OMX_BUFFERHEADERTYPE *)
flush_before_vdec_op_q->Dequeue();
}
#ifdef _ANDROID_
OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo =
m_pmem_info;
// create IMemoryHeap object
m_heap_ptr =
new
VideoHeap(((vdec_frame *) (&m_vdec_cfg.
outputBuffer[0]))->
buffer.pmem_id, m_vdec->arena[0].size,
((vdec_frame *) (&m_vdec_cfg.
outputBuffer[0]))->
buffer.base);
for (unsigned i = 0; i < m_out_buf_count; i++) {
pPMEMInfo->pmem_fd = (OMX_U32) m_heap_ptr.get();
pPMEMInfo++;
}
QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"VideoHeap : fd %d data %d size %d\n",
((vdec_frame *) (&m_vdec_cfg.
outputBuffer[0]))->
buffer.pmem_id,
((vdec_frame *) (&m_vdec_cfg.
outputBuffer[0]))->
buffer.base, m_vdec->arena[0].size);
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"m_heap_ptr =%d",
(unsigned)m_heap_ptr.get());
#endif //_ANDROID_
}
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 {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"OMXCORE-SM: Disabled-->Enabled Pending\n");
BITMASK_SET(m_flags,
OMX_COMPONENT_INPUT_ENABLE_PENDING);
}
// Skip the event notification
bFlag = 0;
}
if (param1 == OMX_CORE_OUTPUT_PORT_INDEX || param1 == OMX_ALL) {
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 {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"OMXCORE-SM: Disabled-->Enabled Pending\n");
BITMASK_SET(m_flags,
OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
}
// Skip the event notification
bFlag = 0;
}
} else if (cmd == OMX_CommandPortDisable) {
if (param1 != OMX_CORE_OUTPUT_PORT_INDEX) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"OMXCORE-SM:Disable should be on Ouput Port\n");
}
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"OMXCORE-SM:Recieved command DISABLE (%d)\n",
cmd);
if (param1 == OMX_CORE_INPUT_PORT_INDEX || param1 == OMX_ALL) {
m_inp_bEnabled = OMX_FALSE;
if ((m_state == OMX_StateLoaded
|| m_state == OMX_StateIdle)
&& release_input_done()) {
post_event(OMX_CommandPortDisable,
OMX_CORE_INPUT_PORT_INDEX,
OMX_COMPONENT_GENERATE_EVENT);
} else {
BITMASK_SET(m_flags,
OMX_COMPONENT_INPUT_DISABLE_PENDING);
if (m_state == OMX_StatePause
|| m_state == OMX_StateExecuting) {
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;
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) {
execute_omx_flush
(OMX_CORE_OUTPUT_PORT_INDEX);
}
}
// Skip the event notification
bFlag = 0;
}
} else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Error: Invalid Command received other than StateSet (%d)\n",
cmd);
eRet = OMX_ErrorNotImplemented;
}
if (eRet == OMX_ErrorNone && bFlag) {
post_event(cmd, eState, OMX_COMPONENT_GENERATE_EVENT);
}
semaphore_post();
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;
if (flushType == 0 || flushType == OMX_ALL) {
//flush input only
execute_input_flush();
}
if (flushType == 1 || flushType == OMX_ALL) {
//flush output only
execute_output_flush();
}
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(void)
{
unsigned i;
bool canceled;
bool bRet = false;
OMX_BUFFERHEADERTYPE *pOutBufHdr =
(OMX_BUFFERHEADERTYPE *) m_out_mem_ptr;
unsigned int p1 = 0;
unsigned int p2 = 0;
unsigned id = 0;
int nFlushFrameCnt = 0;
if (pOutBufHdr) {
unsigned nPortIndex;
//We will ignore this Queue once m_vdec is created. This will cause no harm
//now since when output buffers are created in m_vdec, m_vdec assumes that
//all buffers are with itself.
OMX_BUFFERHEADERTYPE *tmp_buf_hdr =
(OMX_BUFFERHEADERTYPE *) flush_before_vdec_op_q->Dequeue();
while (tmp_buf_hdr) {
nPortIndex =
tmp_buf_hdr -
((OMX_BUFFERHEADERTYPE *) m_out_mem_ptr);
BITMASK_CLEAR(m_out_flags, nPortIndex);
m_cb.FillBufferDone(&m_cmp, m_app_data, tmp_buf_hdr);
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
"Flushing output buffer = %d",
m_out_buf_count);
tmp_buf_hdr =
(OMX_BUFFERHEADERTYPE *) flush_before_vdec_op_q->
Dequeue();
}
}
if (m_vdec) {
/* . Execute the decoder flush */
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"\n *** Calling vdec_flush *** \n");
if (VDEC_SUCCESS ==
vdec_flush_port(m_vdec, &nFlushFrameCnt,
VDEC_FLUSH_ALL_PORT)) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"\n *** Flush Succeeded : Flush Frame Cnt %d *** \n",
nFlushFrameCnt);
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"\n *** Flush Failed *** \n");
}
}
while (m_ftb_q.m_size > 0) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
"Flushing FTB Q\n");
m_ftb_q.delete_entry(&p1, &p2, &id, &canceled);
if (!canceled)
m_cb.FillBufferDone(&m_cmp, m_app_data,
(OMX_BUFFERHEADERTYPE *) p2);
}
if (m_b_display_order)
{
if(m_pPrevFrame) {
frame_done_cb((struct vdec_context *)&m_vdec_cfg, m_pPrevFrame);
m_pPrevFrame = NULL;
}
m_divX_buffer_info.parsing_required = true;
}
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(void)
{
bool bRet = false;
OMX_BUFFERHEADERTYPE *pInpBufHdr =
(OMX_BUFFERHEADERTYPE *) m_inp_mem_ptr;
if (!pInpBufHdr) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Omx Flush issued at wrong context\n");
} else {
int nFlushFrameCnt = 0;
int i, index;
unsigned int p1, p2, ident;
/* 1. Take care of the pending buffers in the input side */
/* During flush clear the pending buffer index. Otherwise FTB followed by flush
** could push duplicate frames to the decoder
*/
if (m_bArbitraryBytes) {
if (m_current_arbitrary_bytes_input) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
" Flush:: current arbitrary bytes not null %x ",
m_current_arbitrary_bytes_input);
m_current_arbitrary_bytes_input->nFilledLen =
m_current_arbitrary_bytes_input->nOffset;
m_current_arbitrary_bytes_input->nOffset = 0;
index = get_free_extra_buffer_index();
if (index != -1) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
" Flush:flushing current bufferindex %d ",
index);
m_extra_buf_info[index].
arbitrarybytesInput =
m_current_arbitrary_bytes_input;
m_current_arbitrary_bytes_input = NULL;
}
else {
m_cb.EmptyBufferDone(&m_cmp, m_app_data,
m_current_arbitrary_bytes_input);
}
}
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
" Flush:: qsize %d ",
m_etb_arbitrarybytes_q.m_size);
while (m_etb_arbitrarybytes_q.
delete_entry(&p1, &p2, &ident)) {
index = get_free_extra_buffer_index();
if (index == -1) {
m_cb.EmptyBufferDone(&m_cmp, m_app_data,
(OMX_BUFFERHEADERTYPE
*) p2);
continue;
}
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Generating the buffer done in flush, qsize %d\n",
m_etb_arbitrarybytes_q.m_size);
pInpBufHdr = (OMX_BUFFERHEADERTYPE *) p2;
m_extra_buf_info[index].arbitrarybytesInput =
pInpBufHdr;
//post_event((unsigned)&m_vdec_cfg,(unsigned)pInpBufHdr,OMX_COMPONENT_GENERATE_BUFFER_DONE);
}
for (i = 0; i < m_inp_buf_count; i++) {
if (m_extra_buf_info[i].bExtra_pBuffer_in_use) {
input[i]->pBuffer =
m_extra_buf_info[i].extra_pBuffer;
input[i]->nOffset = 0;
input[i]->nFilledLen = 0;
input[i]->nFlags = 0;
if (m_extra_buf_info[i].arbitrarybytesInput) {
m_extra_buf_info[i].arbitrarybytesInput->nFilledLen =
m_extra_buf_info[i].arbitrarybytesInput->nOffset;
m_extra_buf_info[i].arbitrarybytesInput->nOffset = 0;
}
remove_top_entry();
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"Generating the buffer done in flush, index %d\n",
i);
buffer_done_cb_stub(&m_vdec_cfg,
input[i]);
}
}
if (m_bArbitraryBytes) {
initialize_arbitrary_bytes_environment();
}
if (m_h264_utils) {
m_h264_utils->
initialize_frame_checking_environment();
}
} else {
do {
if (m_bAccumulate_subframe) {
if (m_pcurrent_frame) {
unsigned nBufferIndex =
m_pcurrent_frame -
((OMX_BUFFERHEADERTYPE *)
m_inp_mem_ptr);
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"Found a valid current Frame in Flush, index %d\n",
nBufferIndex);
add_entry(nBufferIndex);
}
m_pcurrent_frame = NULL;
m_bPartialFrame = false;
if (m_h264_utils) {
m_h264_utils->
initialize_frame_checking_environment
();
}
}
i = remove_top_entry();
if (i >= 0) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"Generating the buffer done in flush, i %d\n",
i);
pInpBufHdr = input[i];
post_event((unsigned)&m_vdec_cfg,
(unsigned)pInpBufHdr,
OMX_COMPONENT_GENERATE_BUFFER_DONE);
}
} while (i >= 0);
}
}
return bRet;
}
/* ======================================================================
FUNCTION
omx_vdec::SendCommandEvent
DESCRIPTION
Send the event to decoder pipe. This is needed to generate the callbacks
in decoder thread context.
PARAMETERS
None.
RETURN VALUE
true/false
========================================================================== */
bool omx_vdec::post_event(unsigned int p1, unsigned int p2, unsigned int id)
{
bool bRet = false;
mutex_lock();
m_cmd_cnt++;
if (id == OMX_COMPONENT_GENERATE_FTB) {
m_ftb_q.insert_entry(p1, p2, id);
} else if ((id == OMX_COMPONENT_GENERATE_ETB_ARBITRARYBYTES)) {
m_etb_arbitrarybytes_q.insert_entry(p1, p2, id);
} else {
m_cmd_q.insert_entry(p1, p2, id);
}
bRet = true;
post_message(id);
mutex_unlock();
// for all messages that needs a callback before
// vdec is actually opened, skips the proxy
QTV_MSG_PRIO8(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Post -->%d[%x,%d]ebd %d fbd %d oc %d %x,%x \n", m_state,
(unsigned)m_vdec, id, m_etb_cnt, m_fbd_cnt,
m_outstanding_frames, m_flags[0] , m_out_flags[0]);
return bRet;
}
/* ======================================================================
FUNCTION
omx_vdec::GetParameter
DESCRIPTION
OMX Get Parameter method implementation
PARAMETERS
<TBD>.
RETURN VALUE
Error None if successful.
========================================================================== */
OMX_ERRORTYPE omx_vdec::get_parameter(OMX_IN OMX_HANDLETYPE hComp,
OMX_IN OMX_INDEXTYPE paramIndex,
OMX_INOUT OMX_PTR paramData)
{
OMX_ERRORTYPE eRet = OMX_ErrorNone;
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED, "get_parameter: \n");
if (m_state == OMX_StateInvalid) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Get Param in Invalid State\n");
return OMX_ErrorInvalidState;
}
if (paramData == NULL) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Get Param in Invalid paramData \n");
return OMX_ErrorBadParameter;
}
switch (paramIndex) {
case OMX_IndexParamPortDefinition:
{
OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_parameter: OMX_IndexParamPortDefinition\n");
portDefn->nVersion.nVersion = OMX_SPEC_VERSION;
portDefn->nSize = sizeof(portDefn);
portDefn->bEnabled = OMX_TRUE;
portDefn->bPopulated = OMX_TRUE;
portDefn->eDomain = OMX_PortDomainVideo;
portDefn->format.video.nFrameHeight = m_crop_dy;
portDefn->format.video.nFrameWidth = m_crop_dx;
portDefn->format.video.nStride = m_port_width;
portDefn->format.video.nSliceHeight = m_port_height;
portDefn->format.video.xFramerate = 25;
if (0 == portDefn->nPortIndex) {
VDecoder_buf_info bufferReq;
if (!m_inp_buf_count) {
if (VDEC_SUCCESS !=
vdec_get_input_buf_requirements
(&bufferReq)) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"get_parameter: ERROR - Failed in get input buffer requirement\n");
m_inp_buf_count =
OMX_CORE_NUM_INPUT_BUFFERS;
m_inp_buf_size =
OMX_CORE_INPUT_BUFFER_SIZE;
} else {
m_inp_buf_count =
bufferReq.numbuf;
m_inp_buf_size =
bufferReq.buffer_size;
}
}
portDefn->nBufferCountActual = m_inp_buf_count;
portDefn->nBufferCountMin =
OMX_CORE_NUM_INPUT_BUFFERS;
portDefn->nBufferSize = m_inp_buf_size;
portDefn->eDir = OMX_DirInput;
portDefn->format.video.eColorFormat =
OMX_COLOR_FormatUnused;
portDefn->format.video.eCompressionFormat =
OMX_VIDEO_CodingAVC;
portDefn->bEnabled = m_inp_bEnabled;
portDefn->bPopulated = m_inp_bPopulated;
} else if (1 == portDefn->nPortIndex) {
int extraDataSize,chroma_height, chroma_width;
portDefn->eDir = OMX_DirOutput;
if (m_vdec) {
portDefn->nBufferCountActual =
m_vdec_cfg.numOutputBuffers;
portDefn->nBufferCountMin =
m_vdec_cfg.numOutputBuffers;
} else {
portDefn->nBufferCountActual =
m_out_buf_count;
portDefn->nBufferCountMin =
m_out_buf_count;
}
extraDataSize = get_extradata_size();
if (m_color_format == QOMX_COLOR_FormatYVU420PackedSemiPlanar32m4ka) {
portDefn->nBufferSize = (m_port_width * m_port_height + 4095) & ~4095;
chroma_height = ((m_port_height >> 1) + 31) & ~31;
chroma_width = 2 * ((m_port_width >> 1) + 31) & ~31;
portDefn->nBufferSize += (chroma_height * chroma_width) + extraDataSize;
} else {
portDefn->nBufferSize = m_port_height * m_port_width * 3/2 + extraDataSize;
}
portDefn->format.video.eColorFormat =
m_color_format;
portDefn->format.video.eCompressionFormat =
OMX_VIDEO_CodingUnused;
portDefn->bEnabled = m_out_bEnabled;
portDefn->bPopulated = m_out_bPopulated;
} else {
portDefn->eDir = OMX_DirMax;
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
" get_parameter: Bad Port idx %d",
(int)portDefn->nPortIndex);
eRet = OMX_ErrorBadPortIndex;
}
break;
}
case OMX_IndexParamVideoInit:
{
OMX_PORT_PARAM_TYPE *portParamType =
(OMX_PORT_PARAM_TYPE *) paramData;
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_parameter: OMX_IndexParamVideoInit\n");
portParamType->nVersion.nVersion = OMX_SPEC_VERSION;
portParamType->nSize = sizeof(portParamType);
portParamType->nPorts = 2;
portParamType->nStartPortNumber = 0;
break;
}
case OMX_IndexParamVideoPortFormat:
{
OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
(OMX_VIDEO_PARAM_PORTFORMATTYPE *) paramData;
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_parameter: OMX_IndexParamVideoPortFormat\n");
portFmt->nVersion.nVersion = OMX_SPEC_VERSION;
portFmt->nSize = sizeof(portFmt);
if (0 == portFmt->nPortIndex) {
if (0 == portFmt->nIndex) {
if (!strncmp
(m_vdec_cfg.kind,
"OMX.qcom.video.decoder.avc",
OMX_MAX_STRINGNAME_SIZE)) {
portFmt->eColorFormat =
OMX_COLOR_FormatUnused;
portFmt->eCompressionFormat =
OMX_VIDEO_CodingAVC;
} else
if (!strncmp
(m_vdec_cfg.kind,
"OMX.qcom.video.decoder.h263",
OMX_MAX_STRINGNAME_SIZE)) {
portFmt->eColorFormat =
OMX_COLOR_FormatUnused;
portFmt->eCompressionFormat =
OMX_VIDEO_CodingH263;
} else
if (!strncmp
(m_vdec_cfg.kind,
"OMX.qcom.video.decoder.mpeg4",
OMX_MAX_STRINGNAME_SIZE)) {
portFmt->eColorFormat =
OMX_COLOR_FormatUnused;
portFmt->eCompressionFormat =
OMX_VIDEO_CodingMPEG4;
} else
if (!strncmp
(m_vdec_cfg.kind,
"OMX.qcom.video.decoder.vc1",
OMX_MAX_STRINGNAME_SIZE)) {
portFmt->eColorFormat =
OMX_COLOR_FormatUnused;
portFmt->eCompressionFormat =
OMX_VIDEO_CodingWMV;
}else
if (!strncmp
(m_vdec_cfg.kind,
"OMX.qcom.video.decoder.divx",
OMX_MAX_STRINGNAME_SIZE)) {
portFmt->eColorFormat =
OMX_COLOR_FormatUnused;
portFmt->eCompressionFormat =
(OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingDivx;
} else
if (!strncmp
(m_vdec_cfg.kind,
"OMX.qcom.video.decoder.vp",
OMX_MAX_STRINGNAME_SIZE)) {
portFmt->eColorFormat =
OMX_COLOR_FormatUnused;
portFmt->eCompressionFormat =
(OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingVp;
} else
if (!strncmp
(m_vdec_cfg.kind,
"OMX.qcom.video.decoder.spark",
OMX_MAX_STRINGNAME_SIZE)) {
portFmt->eColorFormat =
OMX_COLOR_FormatUnused;
portFmt->eCompressionFormat =
(OMX_VIDEO_CODINGTYPE)QOMX_VIDEO_CodingSpark;
}
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"get_parameter: OMX_IndexParamVideoPortFormat:"
" NoMore compression formats\n");
eRet = OMX_ErrorNoMore;
}
} else if (1 == portFmt->nPortIndex) {
if (1 == portFmt->nIndex) {
portFmt->eColorFormat =
(OMX_COLOR_FORMATTYPE)
QOMX_COLOR_FormatYVU420PackedSemiPlanar32m4ka;
portFmt->eCompressionFormat =
OMX_VIDEO_CodingUnused;
} else if (0 == portFmt->nIndex) {
portFmt->eColorFormat =
(OMX_COLOR_FORMATTYPE)
OMX_QCOM_COLOR_FormatYVU420SemiPlanar;
portFmt->eCompressionFormat =
OMX_VIDEO_CodingUnused;
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"get_parameter: OMX_IndexParamVideoPortFormat:"
" NoMore Color formats\n");
eRet = OMX_ErrorNoMore;
}
} else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"get_parameter: Bad port index %d\n",
(int)portFmt->nPortIndex);
eRet = OMX_ErrorBadPortIndex;
}
break;
}
/*Component should support this port definition */
case OMX_IndexParamAudioInit:
{
OMX_PORT_PARAM_TYPE *audioPortParamType =
(OMX_PORT_PARAM_TYPE *) paramData;
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_parameter: OMX_IndexParamAudioInit\n");
audioPortParamType->nVersion.nVersion =
OMX_SPEC_VERSION;
audioPortParamType->nSize = sizeof(audioPortParamType);
audioPortParamType->nPorts = 0;
audioPortParamType->nStartPortNumber = 0;
break;
}
/*Component should support this port definition */
case OMX_IndexParamImageInit:
{
OMX_PORT_PARAM_TYPE *imagePortParamType =
(OMX_PORT_PARAM_TYPE *) paramData;
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_parameter: OMX_IndexParamImageInit\n");
imagePortParamType->nVersion.nVersion =
OMX_SPEC_VERSION;
imagePortParamType->nSize = sizeof(imagePortParamType);
imagePortParamType->nPorts = 0;
imagePortParamType->nStartPortNumber = 0;
break;
}
/*Component should support this port definition */
case OMX_IndexParamOtherInit:
{
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"get_parameter: OMX_IndexParamOtherInit %08x\n",
paramIndex);
eRet = OMX_ErrorUnsupportedIndex;
break;
}
case OMX_IndexParamStandardComponentRole:
{
OMX_PARAM_COMPONENTROLETYPE *comp_role;
comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
comp_role->nVersion.nVersion = OMX_SPEC_VERSION;
comp_role->nSize = sizeof(*comp_role);
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Getparameter: OMX_IndexParamStandardComponentRole %d\n",
paramIndex);
if (NULL != comp_role->cRole) {
strncpy((char *)comp_role->cRole,
(const char *)m_cRole,
OMX_MAX_STRINGNAME_SIZE);
} else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"Getparameter: OMX_IndexParamStandardComponentRole %d is passed with NULL parameter for role\n",
paramIndex);
eRet = OMX_ErrorBadParameter;
}
break;
}
/* Added for parameter test */
case OMX_IndexParamPriorityMgmt:
{
OMX_PRIORITYMGMTTYPE *priorityMgmType =
(OMX_PRIORITYMGMTTYPE *) paramData;
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_parameter: OMX_IndexParamPriorityMgmt\n");
priorityMgmType->nVersion.nVersion = OMX_SPEC_VERSION;
priorityMgmType->nSize = sizeof(priorityMgmType);
break;
}
/* Added for parameter test */
case OMX_IndexParamCompBufferSupplier:
{
OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType =
(OMX_PARAM_BUFFERSUPPLIERTYPE *) paramData;
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_parameter: OMX_IndexParamCompBufferSupplier\n");
bufferSupplierType->nSize = sizeof(bufferSupplierType);
bufferSupplierType->nVersion.nVersion =
OMX_SPEC_VERSION;
if (0 == bufferSupplierType->nPortIndex)
bufferSupplierType->nPortIndex =
OMX_BufferSupplyUnspecified;
else if (1 == bufferSupplierType->nPortIndex)
bufferSupplierType->nPortIndex =
OMX_BufferSupplyUnspecified;
else
eRet = OMX_ErrorBadPortIndex;
break;
}
case OMX_IndexParamVideoAvc:
{
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_parameter: OMX_IndexParamVideoAvc %08x\n",
paramIndex);
break;
}
case OMX_QcomIndexParamInterlaced:
{
OMX_QCOM_PARAM_VIDEO_INTERLACETYPE *portInterlace =
(OMX_QCOM_PARAM_VIDEO_INTERLACETYPE *) paramData;
if (portInterlace->nPortIndex == 1)
portInterlace->bInterlace =
(OMX_BOOL) m_bInterlaced;
else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"get_parameter: Bad port index %d should be queried on only o/p port\n",
(int)portInterlace->nPortIndex);
eRet = OMX_ErrorBadPortIndex;
}
break;
}
case OMX_IndexParamVideoProfileLevelQuerySupported:
{
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported %08x\n",
paramIndex);
OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType =
(OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData;
if(profileLevelType->nPortIndex == 0) {
if (!strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE))
{
if (profileLevelType->nProfileIndex == 0)
{
profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline;
profileLevelType->eLevel = OMX_VIDEO_AVCLevel31;
}
else
{
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n",
profileLevelType->nProfileIndex);
eRet = OMX_ErrorNoMore;
}
}
else if((!strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.h263",OMX_MAX_STRINGNAME_SIZE)))
{
if (profileLevelType->nProfileIndex == 0)
{
profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline;
profileLevelType->eLevel = OMX_VIDEO_H263Level60;
}
else
{
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n",
profileLevelType->nProfileIndex);
eRet = OMX_ErrorNoMore;
}
}
else if (!strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.mpeg4",OMX_MAX_STRINGNAME_SIZE))
{
if (profileLevelType->nProfileIndex == 0)
{
profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5;
}
else
{
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n",
profileLevelType->nProfileIndex);
eRet = OMX_ErrorNoMore;
}
}
else if (!strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.divx",OMX_MAX_STRINGNAME_SIZE))
{
if (profileLevelType->nProfileIndex == 0)
{
profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5;
}
else
{
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n",
profileLevelType->nProfileIndex);
eRet = OMX_ErrorNoMore;
}
}
else if (!strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.vp",OMX_MAX_STRINGNAME_SIZE))
{
if (profileLevelType->nProfileIndex == 0)
{
profileLevelType->eProfile = QOMX_VIDEO_VPProfileAdvanced;
profileLevelType->eLevel = QOMX_VIDEO_VPFormat6;
}
else
{
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n",
profileLevelType->nProfileIndex);
eRet = OMX_ErrorNoMore;
}
}
else if((!strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.spark",OMX_MAX_STRINGNAME_SIZE)))
{
if (profileLevelType->nProfileIndex == 0)
{
profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline;
profileLevelType->eLevel = OMX_VIDEO_H263Level60;
}
else
{
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %d\n",
profileLevelType->nProfileIndex);
eRet = OMX_ErrorNoMore;
}
}
}
else
{
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queries on Input port only %d\n",
profileLevelType->nPortIndex);
eRet = OMX_ErrorBadPortIndex;
}
break;
}
default:
{
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"get_parameter: unknown param %08x\n",
paramIndex);
eRet = OMX_ErrorUnsupportedIndex;
}
}
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"\n get_parameter returning Height %d , Width %d \n",
m_height, m_width);
return eRet;
}
/* ======================================================================
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 i;
if (m_state == OMX_StateInvalid) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Set Param in Invalid State\n");
return OMX_ErrorInvalidState;
}
if (paramData == NULL) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Set Param in Invalid paramData \n");
return OMX_ErrorBadParameter;
}
switch (paramIndex) {
case OMX_IndexParamPortDefinition:
{
OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"set_parameter: OMX_IndexParamPortDefinition H= %d, W = %d\n",
(int)portDefn->format.video.nFrameHeight,
(int)portDefn->format.video.nFrameWidth);
if (((m_state == OMX_StateLoaded) &&
!BITMASK_PRESENT(m_flags,
OMX_COMPONENT_IDLE_PENDING))
/* Or while the I/P or the O/P port or disabled */
||
((OMX_DirInput == portDefn->eDir
&& m_inp_bEnabled == FALSE)
|| (OMX_DirOutput == portDefn->eDir
&& m_out_bEnabled == FALSE))) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Set Parameter called in valid state");
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"Set Parameter called in Invalid State\n");
return OMX_ErrorIncorrectStateOperation;
}
if (OMX_DirOutput == portDefn->eDir) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"set_parameter: OMX_IndexParamPortDefinition on output port\n");
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"set_parameter op port: stride %d\n",
(int)portDefn->format.video.
nStride);
/*
If actual buffer count is greater than the Min buffer
count,change the actual count.
m_inp_buf_count is initialized to OMX_CORE_NUM_INPUT_BUFFERS
in the constructor
*/
if (portDefn->nBufferCountActual >
m_out_buf_count) {
m_out_buf_count =
portDefn->nBufferCountActual;
} else if (portDefn->nBufferCountActual <
m_out_buf_count) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
" Set_parameter: Actual buffer count = %d less than Min Buff count",
portDefn->
nBufferCountActual);
eRet = OMX_ErrorBadParameter;
}
/* Save the DisplayID to be used in useEGLImage api to query the
pmem fd and offset from GPU client.
*/
m_display_id = portDefn->format.video.pNativeWindow;
} else if (OMX_DirInput == portDefn->eDir) {
if (m_height !=
portDefn->format.video.nFrameHeight
|| m_width !=
portDefn->format.video.nFrameWidth) {
m_crop_x = m_crop_y = 0;
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"set_parameter ip port: stride %d\n",
(int)portDefn->format.
video.nStride);
// Re-start case since image dimensions have changed
QTV_MSG_PRIO4(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"\nSetParameter: Dimension mismatch. Old H: %d New H: %d Old W: %d New W: %d\n",
m_height,
(int)portDefn->format.
video.nFrameHeight,
m_width,
(int)portDefn->format.
video.nFrameWidth);
m_crop_dy = m_port_height =
m_vdec_cfg.height = m_height =
portDefn->format.video.nFrameHeight;
m_crop_dx = m_port_width =
m_vdec_cfg.width = m_width =
portDefn->format.video.nFrameWidth;
QTV_MSG_PRIO2(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"\n VDEC Open with new H %d and W %d\n",
m_height, m_width);
if ((m_height % 16) != 0) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"\n Height %d is not a multiple of 16",
m_height);
m_vdec_cfg.height =
(m_height / 16 + 1) * 16;
QTV_MSG_PRIO2(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"\n Height %d adjusted to %d \n",
m_height,
m_vdec_cfg.
height);
}
if (m_width % 16 != 0) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"\n Width %d is not a multiple of 16",
m_width);
m_vdec_cfg.width =
(m_width / 16 + 1) * 16;
QTV_MSG_PRIO2(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"\n Width %d adjusted to %d \n",
m_width,
m_vdec_cfg.width);
}
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"\n set_parameter: Image Dimensions same \n");
}
/*
If actual buffer count is greater than the Min buffer
count,change the actual count.
m_inp_buf_count is initialized to OMX_CORE_NUM_INPUT_BUFFERS
in the constructor
*/
if (portDefn->nBufferCountActual >
OMX_CORE_NUM_INPUT_BUFFERS) {
m_inp_buf_count =
portDefn->nBufferCountActual;
} else if (portDefn->nBufferCountActual <
OMX_CORE_NUM_INPUT_BUFFERS) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
" Set_parameter: Actual buffer count = %d less than Min Buff count",
portDefn->
nBufferCountActual);
eRet = OMX_ErrorBadParameter;
}
} else if (portDefn->eDir == OMX_DirMax) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
" Set_parameter: Bad Port idx %d",
(int)portDefn->nPortIndex);
eRet = OMX_ErrorBadPortIndex;
}
}
break;
case OMX_IndexParamVideoPortFormat:
{
OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
(OMX_VIDEO_PARAM_PORTFORMATTYPE *) paramData;
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
"set_parameter: OMX_IndexParamVideoPortFormat %d\n",
portFmt->eColorFormat);
if (1 == portFmt->nPortIndex) {
m_color_format = portFmt->eColorFormat;
}
}
break;
case OMX_QcomIndexPortDefn:
{
OMX_QCOM_PARAM_PORTDEFINITIONTYPE *portFmt =
(OMX_QCOM_PARAM_PORTDEFINITIONTYPE *) paramData;
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"set_parameter: OMX_IndexQcomParamPortDefinitionType %d\n",
portFmt->nFramePackingFormat);
if (portFmt->nPortIndex == 0) // Input port
{
if (portFmt->nFramePackingFormat ==
OMX_QCOM_FramePacking_Arbitrary) {
m_bArbitraryBytes = true;
if (strncmp
(m_vdec_cfg.kind,
"OMX.qcom.video.decoder.avc",
26) == 0
||
(strncmp
(m_vdec_cfg.kind,
"OMX.qcom.video.decoder.vc1",
26) == 0)) {
m_bAccumulate_subframe = true;
} else if (strncmp
(m_vdec_cfg.kind,
"OMX.qcom.video.decoder.vp",
25) == 0) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"Setparameter: OMX_QcomIndexPortDefn - Arbitrary not supported for VP6");
m_bArbitraryBytes = false;
m_bAccumulate_subframe = false;
eRet = OMX_ErrorUnsupportedSetting;
}
} else if (portFmt->nFramePackingFormat ==
OMX_QCOM_FramePacking_OnlyOneCompleteFrame)
{
m_bArbitraryBytes = false;
m_bAccumulate_subframe = false;
} else if (portFmt->nFramePackingFormat ==
OMX_QCOM_FramePacking_OnlyOneCompleteSubFrame)
{
m_bArbitraryBytes = false;
if (strncmp
(m_vdec_cfg.kind,
"OMX.qcom.video.decoder.avc",
26) == 0
||
(strncmp
(m_vdec_cfg.kind,
"OMX.qcom.video.decoder.vc1",
26) == 0)) {
m_bAccumulate_subframe = true;
} else if (strncmp
(m_vdec_cfg.kind,
"OMX.qcom.video.decoder.vp",
25) == 0) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"Setparameter: OMX_QcomIndexPortDefn - Subframe not supported for VP6");
m_bArbitraryBytes = false;
m_bAccumulate_subframe = false;
eRet = OMX_ErrorUnsupportedSetting;
}
}
}
}
break;
case OMX_IndexParamStandardComponentRole:
{
OMX_PARAM_COMPONENTROLETYPE *comp_role;
comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"set_parameter: OMX_IndexParamStandardComponentRole %s\n",
comp_role->cRole);
if (!strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc",
OMX_MAX_STRINGNAME_SIZE)) {
if (!strncmp
((char *)comp_role->cRole,
"video_decoder.avc",
OMX_MAX_STRINGNAME_SIZE)) {
strncpy((char *)m_cRole,
"video_decoder.avc",
OMX_MAX_STRINGNAME_SIZE);
} else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"Setparameter: unknown Index %s\n",
comp_role->cRole);
eRet = OMX_ErrorUnsupportedSetting;
}
} else
if (!strncmp
(m_vdec_cfg.kind,
"OMX.qcom.video.decoder.mpeg4",
OMX_MAX_STRINGNAME_SIZE)) {
if (!strncmp
((const char *)comp_role->cRole,
"video_decoder.mpeg4",
OMX_MAX_STRINGNAME_SIZE)) {
strncpy((char *)m_cRole,
"video_decoder.mpeg4",
OMX_MAX_STRINGNAME_SIZE);
} else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"Setparameter: unknown Index %s\n",
comp_role->cRole);
eRet = OMX_ErrorUnsupportedSetting;
}
} else
if (!strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.h263",
OMX_MAX_STRINGNAME_SIZE)) {
if (!strncmp
((const char *)comp_role->cRole,
"video_decoder.h263",
OMX_MAX_STRINGNAME_SIZE)) {
strncpy((char *)m_cRole,
"video_decoder.h263",
OMX_MAX_STRINGNAME_SIZE);
} else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"Setparameter: unknown Index %s\n",
comp_role->cRole);
eRet = OMX_ErrorUnsupportedSetting;
}
} else
if (!strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.divx",
OMX_MAX_STRINGNAME_SIZE)) {
if (!strncmp
((const char *)comp_role->cRole,
"video_decoder.divx",
OMX_MAX_STRINGNAME_SIZE)) {
strncpy((char *)m_cRole,
"video_decoder.divx",
OMX_MAX_STRINGNAME_SIZE);
} else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"Setparameter: unknown Index %s\n",
comp_role->cRole);
eRet = OMX_ErrorUnsupportedSetting;
}
} else
if (!strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.vc1",
OMX_MAX_STRINGNAME_SIZE)) {
if (!strncmp
((const char *)comp_role->cRole,
"video_decoder.vc1",
OMX_MAX_STRINGNAME_SIZE)) {
strncpy((char *)m_cRole,
"video_decoder.vc1",
OMX_MAX_STRINGNAME_SIZE);
} else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"Setparameter: unknown Index %s\n",
comp_role->cRole);
eRet = OMX_ErrorUnsupportedSetting;
}
} else
if (!strncmp
(m_vdec_cfg.kind,
"OMX.qcom.video.decoder.vp",
OMX_MAX_STRINGNAME_SIZE)) {
if (!strncmp
((const char *)comp_role->cRole,
"video_decoder.vp",
OMX_MAX_STRINGNAME_SIZE)) {
strncpy((char *)m_cRole,
"video_decoder.vp",
OMX_MAX_STRINGNAME_SIZE);
} else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"Setparameter: unknown Index %s\n",
comp_role->cRole);
eRet = OMX_ErrorUnsupportedSetting;
}
} else
if (!strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.spark",
OMX_MAX_STRINGNAME_SIZE)) {
if (!strncmp
((const char *)comp_role->cRole,
"video_decoder.spark",
OMX_MAX_STRINGNAME_SIZE)) {
strncpy((char *)m_cRole,
"video_decoder.spark",
OMX_MAX_STRINGNAME_SIZE);
} else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"Setparameter: unknown Index %s\n",
comp_role->cRole);
eRet = OMX_ErrorUnsupportedSetting;
}
} else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"Setparameter: unknown param %s\n",
m_vdec_cfg.kind);
eRet = OMX_ErrorInvalidComponentName;
}
break;
}
case OMX_IndexParamPriorityMgmt:
{
if (m_state != OMX_StateLoaded) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"Set Parameter called in Invalid State\n");
return OMX_ErrorIncorrectStateOperation;
}
OMX_PRIORITYMGMTTYPE *priorityMgmtype =
(OMX_PRIORITYMGMTTYPE *) paramData;
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"set_parameter: OMX_IndexParamPriorityMgmt %d\n",
priorityMgmtype->nGroupID);
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"set_parameter: priorityMgmtype %d\n",
priorityMgmtype->nGroupPriority);
m_priority_mgm.nGroupID = priorityMgmtype->nGroupID;
m_priority_mgm.nGroupPriority =
priorityMgmtype->nGroupPriority;
break;
}
case OMX_IndexParamCompBufferSupplier:
{
OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType =
(OMX_PARAM_BUFFERSUPPLIERTYPE *) paramData;
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"set_parameter: OMX_IndexParamCompBufferSupplier %d\n",
bufferSupplierType->eBufferSupplier);
if (bufferSupplierType->nPortIndex == 0
|| bufferSupplierType->nPortIndex == 1)
m_buffer_supplier.eBufferSupplier =
bufferSupplierType->eBufferSupplier;
else
eRet = OMX_ErrorBadPortIndex;
break;
}
case OMX_IndexParamVideoAvc:
{
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"set_parameter: OMX_IndexParamVideoAvc %d\n",
paramIndex);
break;
}
case OMX_QcomIndexParamVideoDivx:
{
QOMX_VIDEO_PARAM_DIVXTYPE *divxType =
(QOMX_VIDEO_PARAM_DIVXTYPE *) paramData;
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"set_parameter: OMX_QcomIndexParamVideoDivx %d\n",
paramIndex);
if(divxType->nPortIndex == 0) {
m_codec_format = divxType->eFormat;
m_codec_profile = divxType->eProfile;
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"set_parameter: OMX_QcomIndexParamVideoDivx Format %d, Profile %d\n",
m_codec_format,m_codec_profile);
if(divxType->eFormat == QOMX_VIDEO_DIVXFormat311)
m_b_divX_parser = false;
}
else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"set_parameter: OMX_QcomIndexParamVideoDivx BAD PORT INDEX%d \n",
divxType->nPortIndex);
eRet = OMX_ErrorBadPortIndex;
}
break;
}
case OMX_QcomIndexParamVideoVp:
{
QOMX_VIDEO_PARAM_VPTYPE *vpType =
(QOMX_VIDEO_PARAM_VPTYPE *) paramData;
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"set_parameter: OMX_QcomIndexParamVideoVp %d\n",
paramIndex);
if(vpType->nPortIndex == 0) {
m_codec_format = vpType->eFormat;
m_codec_profile = vpType->eProfile;
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"set_parameter: OMX_QcomIndexParamVideoVp Format %d, Profile %d\n",
m_codec_format,m_codec_profile);
}
else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"set_parameter: OMX_QcomIndexParamVideoVp BAD PORT INDEX%d \n",
vpType->nPortIndex);
eRet = OMX_ErrorBadPortIndex;
}
break;
}
case OMX_QcomIndexParamVideoSpark:
{
QOMX_VIDEO_PARAM_SPARKTYPE *sparkType =
(QOMX_VIDEO_PARAM_SPARKTYPE *) paramData;
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"set_parameter: OMX_QcomIndexParamVideoSpark %d\n",
paramIndex);
if(sparkType->nPortIndex == 0) {
m_codec_format = sparkType->eFormat;
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"set_parameter: OMX_QcomIndexParamVideoSpark Format %d\n",
m_codec_format);
}
else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"set_parameter: OMX_QcomIndexParamVideoSpark BAD PORT INDEX%d \n",
sparkType->nPortIndex);
eRet = OMX_ErrorBadPortIndex;
}
break;
}
default:
{
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Setparameter: unknown param %d\n",
paramIndex);
eRet = OMX_ErrorUnsupportedIndex;
}
}
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)
{
OMX_ERRORTYPE eRet = OMX_ErrorNone;
if (m_state == OMX_StateInvalid) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Get Config in Invalid State\n");
return OMX_ErrorInvalidState;
}
switch (configIndex) {
case OMX_QcomIndexConfigInterlaced:
{
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 {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"get_config: OMX_QcomIndexConfigInterlaced:"
" NoMore Interlaced formats\n");
eRet = OMX_ErrorNoMore;
}
} else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"get_config: Bad port index %d queried on only o/p port\n",
(int)configFmt->nPortIndex);
eRet = OMX_ErrorBadPortIndex;
}
break;
}
default:
{
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"get_config: unknown param %d\n",
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)
{
OMX_ERRORTYPE ret = OMX_ErrorNone;
OMX_VIDEO_CONFIG_NALSIZE *pNal;
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"set_config, store the NAL length size\n");
if (m_state == OMX_StateInvalid) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Set Config in Invalid State\n");
return OMX_ErrorInvalidState;
}
if (m_state == OMX_StateExecuting) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"set_config:Ignore in Exe state\n");
return ret;
}
if (configIndex == OMX_IndexVendorVideoExtraData) {
OMX_VENDOR_EXTRADATATYPE *config =
(OMX_VENDOR_EXTRADATATYPE *) configData;
if (!strcmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc")) {
OMX_U32 extra_size;
// Parsing done here for the AVC atom is definitely not generic
// Currently this piece of code is working, but certainly
// not tested with all .mp4 files.
// Incase of failure, we might need to revisit this
// for a generic piece of code.
// Retrieve size of NAL length field
// byte #4 contains the size of NAL lenght field
m_nalu_bytes = (config->pData[4] & 0x03) + 1;
extra_size = 0;
if (m_nalu_bytes > 2) {
/* Presently we assume that only one SPS and one PPS in AvC1 Atom */
extra_size = (m_nalu_bytes - 2) * 2;
}
// SPS starts from byte #6
OMX_U8 *pSrcBuf = (OMX_U8 *) (&config->pData[6]);
OMX_U8 *pDestBuf;
m_vendor_config.nPortIndex = config->nPortIndex;
// minus 6 --> SPS starts from byte #6
// minus 1 --> picture param set byte to be ignored from avcatom
m_vendor_config.nDataSize =
config->nDataSize - 6 - 1 + extra_size;
m_vendor_config.pData =
(OMX_U8 *) malloc(m_vendor_config.nDataSize);
OMX_U32 len;
OMX_U8 index = 0;
// case where SPS+PPS is sent as part of set_config
pDestBuf = m_vendor_config.pData;
QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Rxd SPS+PPS nPortIndex[%d] len[%d] data[0x%x]\n",
m_vendor_config.nPortIndex,
m_vendor_config.nDataSize,
m_vendor_config.pData);
while (index < 2) {
uint8 *psize;
len = *pSrcBuf;
len = len << 8;
len |= *(pSrcBuf + 1);
psize = (uint8 *) & len;
memcpy(pDestBuf + m_nalu_bytes, pSrcBuf + 2,
len);
for (int i = 0; i < m_nalu_bytes; i++) {
pDestBuf[i] =
psize[m_nalu_bytes - 1 - i];
}
//memcpy(pDestBuf,pSrcBuf,(len+2));
pDestBuf += len + m_nalu_bytes;
pSrcBuf += len + 2;
index++;
pSrcBuf++; // skip picture param set
len = 0;
}
m_header_state = HEADER_STATE_RECEIVED_COMPLETE;
} else
if (!strcmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.mpeg4")) {
m_vendor_config.nPortIndex = config->nPortIndex;
m_vendor_config.nDataSize = config->nDataSize;
m_vendor_config.pData =
(OMX_U8 *) malloc((config->nDataSize));
memcpy(m_vendor_config.pData, config->pData,
config->nDataSize);
} else
if (!strcmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.vc1"))
{
if ((((*((OMX_U32 *) config->pData)) &
VC1_SP_MP_START_CODE_MASK) ==
VC1_SP_MP_START_CODE)
||
(((*((OMX_U32 *) config->pData)) &
VC1_SP_MP_START_CODE_MASK) ==
VC1_SP_MP_START_CODE_RCV_V1)
) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
"set_config - VC1 simple/main profile\n");
m_vendor_config.nPortIndex = config->nPortIndex;
m_vendor_config.nDataSize = config->nDataSize;
m_vendor_config.pData =
(OMX_U8 *) malloc(config->nDataSize);
memcpy(m_vendor_config.pData, config->pData,
config->nDataSize);
} else if (*((OMX_U32 *) config->pData) == 0x0F010000) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
"set_config - VC1 Advance profile\n");
m_vendor_config.nPortIndex = config->nPortIndex;
m_vendor_config.nDataSize = config->nDataSize;
m_vendor_config.pData =
(OMX_U8 *) malloc((config->nDataSize));
memcpy(m_vendor_config.pData, config->pData,
config->nDataSize);
} else if ((config->nDataSize == VC1_STRUCT_C_LEN)) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_LOW,
"set_config - VC1 Simple/Main profile struct C only\n");
m_vendor_config.nPortIndex = config->nPortIndex;
m_vendor_config.nDataSize = config->nDataSize;
m_vendor_config.pData = (OMX_U8*)malloc(config->nDataSize);
memcpy(m_vendor_config.pData,config->pData,config->nDataSize);
}
else {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"set_config - Error: Unknown VC1 profile\n");
}
}
} else if (configIndex == OMX_IndexConfigVideoNalSize) {
pNal =
reinterpret_cast < OMX_VIDEO_CONFIG_NALSIZE * >(configData);
m_nalu_bytes = pNal->nNaluBytes;
if (m_nalu_bytes == 0) {
m_bStartCode = true;
} else if (m_nalu_bytes < 0 || m_nalu_bytes > 4) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"set_config, invalid NAL length size [%d]\n",
m_nalu_bytes);
m_nalu_bytes = 4;
m_bStartCode = false;
ret = OMX_ErrorBadParameter;
} else {
m_bStartCode = false;
}
}
return ret;
}
/* ======================================================================
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)
{
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"get_extension_index: Error, Not implemented\n");
if (m_state == OMX_StateInvalid) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Get Extension Index in Invalid State\n");
return OMX_ErrorInvalidState;
}
return OMX_ErrorNotImplemented;
}
/* ======================================================================
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)
{
*state = m_state;
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_state: Returning the state %d\n", *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)
{
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Error: component_tunnel_request Not Implemented\n");
return OMX_ErrorNotImplemented;
}
/* ======================================================================
FUNCTION
omx_vdec::UseInputBuffer
DESCRIPTION
Helper function for Use buffer in the input pin
PARAMETERS
None.
RETURN VALUE
true/false
========================================================================== */
OMX_ERRORTYPE omx_vdec::use_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_IN OMX_U8 * buffer)
{
OMX_ERRORTYPE eRet = OMX_ErrorNone;
OMX_BUFFERHEADERTYPE *bufHdr; // buffer header
unsigned i,temp; // Temporary counter
temp = OMX_CORE_NUM_INPUT_BUFFERS;
if (bytes <= OMX_CORE_INPUT_BUFFER_SIZE) {
if (!m_inp_mem_ptr) {
int nBufHdrSize =
m_inp_buf_count * sizeof(OMX_BUFFERHEADERTYPE);
temp = BITMASK_SIZE(m_inp_buf_count);
m_inp_mem_ptr =
(char *)calloc((nBufHdrSize + temp), 1);
m_use_pmem = 0;
if (m_inp_mem_ptr) {
// We have valid Input memory block here
QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Ist User Input Buffer(%d,%d,%d)\n",
m_inp_buf_count, nBufHdrSize,
m_inp_bm_count);
if (m_bArbitraryBytes) {
if (!m_arbitrary_bytes_input_mem_ptr) {
m_arbitrary_bytes_input_mem_ptr
=
(char *)
calloc((nBufHdrSize), 1);
}
*bufferHdr =
(OMX_BUFFERHEADERTYPE *)
m_arbitrary_bytes_input_mem_ptr;
bufHdr =
(OMX_BUFFERHEADERTYPE *)
m_arbitrary_bytes_input_mem_ptr;
//m_inp_bm_ptr = ((char*)bufHdr) + nBufHdrSize ;
m_arbitrary_bytes_input[0] =
*bufferHdr;;
} else {
*bufferHdr =
(OMX_BUFFERHEADERTYPE *)
m_inp_mem_ptr;
bufHdr =
(OMX_BUFFERHEADERTYPE *)
m_inp_mem_ptr;
//m_inp_bm_ptr = ((char*)bufHdr) + nBufHdrSize ;
input[0] = *bufferHdr;
}
BITMASK_SET(m_inp_bm_count, 0);
// Settting the entire storage nicely
for (i = 0; i < m_inp_buf_count; i++, bufHdr++) {
memset(bufHdr, 0,
sizeof(OMX_BUFFERHEADERTYPE));
bufHdr->nSize =
sizeof(OMX_BUFFERHEADERTYPE);
bufHdr->nVersion.nVersion =
OMX_SPEC_VERSION;
bufHdr->nAllocLen =
OMX_CORE_INPUT_BUFFER_SIZE;
bufHdr->pAppPrivate = appData;
bufHdr->nInputPortIndex =
OMX_CORE_INPUT_PORT_INDEX;
//QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"Input BufferHdr[%p] index[%d]\n",\
bufHdr, i);
}
if (m_bArbitraryBytes) {
input[0] = bufHdr =
(OMX_BUFFERHEADERTYPE *)
m_inp_mem_ptr;
for (i = 0; i < m_inp_buf_count;
i++, bufHdr++) {
memset(bufHdr, 0,
sizeof
(OMX_BUFFERHEADERTYPE));
bufHdr->pBuffer = NULL;
bufHdr->nSize =
sizeof
(OMX_BUFFERHEADERTYPE);
bufHdr->nVersion.nVersion =
OMX_SPEC_VERSION;
bufHdr->nAllocLen =
m_inp_buf_size;
bufHdr->pAppPrivate = appData;
bufHdr->nInputPortIndex =
OMX_CORE_INPUT_PORT_INDEX;
QTV_MSG_PRIO2(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"arbitrarybytesInput Buffer %p arbitrarybytesInput[%p]\n",
bufHdr->pBuffer,
bufHdr);
if (m_extra_buf_info[i].
extra_pBuffer == NULL) {
m_extra_buf_info[i].
extra_pBuffer =
(OMX_U8 *)
malloc
(m_inp_buf_size);
if (m_extra_buf_info[i].
extra_pBuffer ==
NULL) {
QTV_MSG_PRIO
(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"ERROR - Failed to get extra_pBuffer\n");
eRet =
OMX_ErrorInsufficientResources;
break;
}
}
memset(m_extra_buf_info[i].
extra_pBuffer, 0,
m_inp_buf_size);
m_extra_buf_info[i].
bExtra_pBuffer_in_use =
false;
m_extra_buf_info[i].
arbitrarybytesInput = NULL;
}
}
omx_vdec_set_input_use_buf_flg();
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Input buffer memory allocation failed\n");
eRet = OMX_ErrorInsufficientResources;
}
} else {
for (i = 0; i < m_inp_buf_count; i++) {
if (BITMASK_ABSENT(m_inp_bm_count, i)) {
// bit space available
break;
}
}
if (i < m_inp_buf_count) {
if (m_bArbitraryBytes) {
*bufferHdr =
((OMX_BUFFERHEADERTYPE *)
m_arbitrary_bytes_input_mem_ptr) +
i;
m_arbitrary_bytes_input[i] = *bufferHdr;
input[i] =
((OMX_BUFFERHEADERTYPE *)
m_inp_mem_ptr) + i;
} else {
*bufferHdr =
((OMX_BUFFERHEADERTYPE *)
m_inp_mem_ptr) + i;
input[i] = *bufferHdr;
}
(*bufferHdr)->pAppPrivate = appData;
BITMASK_SET(m_inp_bm_count, i);
} else {
eRet = OMX_ErrorInsufficientResources;
}
}
(*bufferHdr)->pBuffer = (OMX_U8 *) buffer;
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"BUffer Header[%p] buffer=%p\n", *bufferHdr,
(*bufferHdr)->pBuffer);
} else {
eRet = OMX_ErrorInsufficientResources;
}
return eRet;
}
/* ======================================================================
FUNCTION
omx_vdec::UseOutputBuffer
DESCRIPTION
Helper function for Use buffer in the input pin
PARAMETERS
None.
RETURN VALUE
true/false
========================================================================== */
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; // buffer header
unsigned i; // Temporary counter
if (!m_out_mem_ptr) {
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;
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Ist Use Output Buffer(%d)\n", m_out_buf_count);
nBufHdrSize = m_out_buf_count * sizeof(OMX_BUFFERHEADERTYPE);
nPMEMInfoSize = m_out_buf_count *
sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
nPlatformListSize = m_out_buf_count *
sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
nPlatformEntrySize = m_out_buf_count *
sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
//m_out_bm_count = BITMASK_SIZE(m_out_buf_count);
QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"UOB::TotalBufHdr %d BufHdrSize %d PMEM %d PL %d\n",
nBufHdrSize, sizeof(OMX_BUFFERHEADERTYPE),
nPMEMInfoSize, nPlatformListSize);
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"UOB::PE %d bmSize %d \n", nPlatformEntrySize,
m_out_bm_count);
/*
* Memory for output side involves the following:
* 1. Array of Buffer Headers
* 2. Platform specific information List
* 3. Platform specific Entry List
* 4. PMem Information entries
* 5. Bitmask array to hold the buffer allocation details
* In order to minimize the memory management entire allocation
* is done in one step.
*/
/*m_out_mem_ptr = (char *)calloc(nBufHdrSize +
nPlatformListSize +
nPlatformEntrySize +
nPMEMInfoSize +m_out_bm_count, 1); */
// Alloc mem for out buffer headers
m_out_mem_ptr = (char *)calloc(nBufHdrSize, 1);
// Alloc mem for platform specific info
char *pPtr = NULL;
pPtr = (char *)calloc(nPlatformListSize + nPlatformEntrySize +
nPMEMInfoSize, 1);
// Alloc mem for maintaining a copy of use buf headers
char *omxHdr = (char *)calloc(nBufHdrSize, 1);
m_loc_use_buf_hdr = (OMX_BUFFERHEADERTYPE *) omxHdr;
if (m_out_mem_ptr && m_loc_use_buf_hdr && pPtr) {
bufHdr = (OMX_BUFFERHEADERTYPE *) 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;
//m_out_bm_ptr = (((char *) pPMEMInfo) + nPMEMInfoSize);
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"UOB::Memory Allocation Succeeded for OUT port%p\n",
m_out_mem_ptr);
// Settting the entire storage nicely
QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"UOB::bHdr %p OutMem %p PE %p pmem[%p]\n",
bufHdr, m_out_mem_ptr, pPlatformEntry,
pPMEMInfo);
for (i = 0; i < m_out_buf_count; i++) {
memset(bufHdr, 0, sizeof(OMX_BUFFERHEADERTYPE));
bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
// Set the values when we determine the right HxW param
bufHdr->nAllocLen = bytes; // get_output_buffer_size();
bufHdr->nFilledLen = 0;
bufHdr->pAppPrivate = appData;
bufHdr->nOutputPortIndex =
OMX_CORE_OUTPUT_PORT_INDEX;
// Platform specific PMEM Information
// Initialize the Platform Entry
pPlatformEntry->type =
OMX_QCOM_PLATFORM_PRIVATE_PMEM;
pPlatformEntry->entry = pPMEMInfo;
// Initialize the Platform List
pPlatformList->nEntries = 1;
pPlatformList->entryList = pPlatformEntry;
// Assign the buffer space to the bufHdr
bufHdr->pBuffer = buffer;
// Keep this NULL till vdec_open is done
bufHdr->pOutputPortPrivate = NULL;
pPMEMInfo->offset = 0;
bufHdr->pPlatformPrivate = pPlatformList;
// Move the buffer and buffer header pointers
bufHdr++;
pPMEMInfo++;
pPlatformEntry++;
pPlatformList++;
}
*bufferHdr = (OMX_BUFFERHEADERTYPE *) m_out_mem_ptr;
BITMASK_SET(m_out_bm_count, 0x0);
} else {
QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Output buf mem alloc failed[0x%x][0x%x][0x%x]\n",
m_out_mem_ptr, m_loc_use_buf_hdr, pPtr);
eRet = OMX_ErrorInsufficientResources;
return eRet;
}
} else {
for (i = 0; i < m_out_buf_count; i++) {
if (BITMASK_ABSENT(m_out_bm_count, i)) {
break;
}
}
if (i < m_out_buf_count) {
// found an empty buffer at i
*bufferHdr =
((OMX_BUFFERHEADERTYPE *) m_out_mem_ptr) + i;
(*bufferHdr)->pAppPrivate = appData;
(*bufferHdr)->pBuffer = buffer;
BITMASK_SET(m_out_bm_count, i);
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"All Output Buf Allocated:\n");
eRet = OMX_ErrorInsufficientResources;
return eRet;
}
}
if (allocate_done()) {
omx_vdec_display_in_buf_hdrs();
omx_vdec_display_out_buf_hdrs();
//omx_vdec_dup_use_buf_hdrs();
//omx_vdec_display_out_use_buf_hdrs();
// If use buffer and pmem alloc buffers
// then dont make any local copies of use buf headers
omx_vdec_set_use_buf_flg();
}
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 eRet = OMX_ErrorNone;
if (m_state == OMX_StateInvalid) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Use Buffer in Invalid State\n");
return OMX_ErrorInvalidState;
}
if (port == OMX_CORE_INPUT_PORT_INDEX) {
eRet =
use_input_buffer(hComp, bufferHdr, port, appData, bytes,
buffer);
} else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
eRet =
use_output_buffer(hComp, bufferHdr, port, appData, bytes,
buffer);
} else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Error: Invalid Port Index received %d\n",
(int)port);
eRet = OMX_ErrorBadPortIndex;
}
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);
}
} else if (port == OMX_CORE_OUTPUT_PORT_INDEX
&& m_out_bPopulated) {
if (BITMASK_PRESENT
(m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
if (m_event_port_settings_sent) {
if (VDEC_SUCCESS != vdec_commit_memory(m_vdec)) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"ERROR!!! vdec_commit_memory failed\n");
m_bInvalidState = true;
m_cb.EventHandler(&m_cmp, m_app_data,
OMX_EventError,
OMX_ErrorInsufficientResources, 0,
NULL);
eRet = OMX_ErrorInsufficientResources;
}
}
// Populate the Buffer Headers
omx_vdec_get_out_buf_hdrs();
// Populate Use Buffer Headers
if (omx_vdec_get_use_buf_flg()) {
omx_vdec_dup_use_buf_hdrs();
omx_vdec_get_out_use_buf_hdrs();
omx_vdec_add_entries();
omx_vdec_display_out_buf_hdrs();
}
BITMASK_CLEAR((m_flags),
OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
post_event(OMX_CommandPortEnable,
OMX_CORE_OUTPUT_PORT_INDEX,
OMX_COMPONENT_GENERATE_EVENT);
m_event_port_settings_sent = false;
}
}
}
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;
OMX_BUFFERHEADERTYPE *bufHdr; // buffer header
unsigned i; // Temporary counter
// m_inp_buf_count = OMX_CORE_NUM_INPUT_BUFFERS;
if (bytes <= OMX_CORE_INPUT_BUFFER_SIZE) {
if (!m_inp_mem_ptr) {
Vdec_BufferInfo vdec_buf;
int nBufHdrSize =
m_inp_buf_count * sizeof(OMX_BUFFERHEADERTYPE);
//m_inp_bm_count = BITMASK_SIZE(m_inp_buf_count);
m_inp_mem_ptr = (char *)calloc((nBufHdrSize), 1);
if (m_inp_mem_ptr) {
// We have valid Input memory block here
QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Allocating First Input Buffer(%d,%d,%d)\n",
m_inp_buf_count, nBufHdrSize,
m_inp_bm_count);
if (m_bArbitraryBytes) {
input[0] = bufHdr =
(OMX_BUFFERHEADERTYPE *)
m_inp_mem_ptr;
} else {
input[0] = *bufferHdr = bufHdr =
(OMX_BUFFERHEADERTYPE *)
m_inp_mem_ptr;
// m_inp_bm_ptr = ((char *)buf) + nBufSize;
}
BITMASK_SET(m_inp_bm_count, 0);
// Settting the entire storage nicely
for (i = 0; i < m_inp_buf_count; i++, bufHdr++) {
memset(bufHdr, 0,
sizeof(OMX_BUFFERHEADERTYPE));
if (m_bArbitraryBytes) {
bufHdr->pBuffer = NULL;
bufHdr->nAllocLen =
m_inp_buf_size;
} else {
if (VDEC_EFAILED ==
vdec_allocate_input_buffer
(m_inp_buf_size, &vdec_buf,
m_use_pmem)) {
QTV_MSG_PRIO
(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"ERROR - Failed to allocate memory from vdec\n");
bufHdr->pBuffer = NULL;
} else {
if (m_use_pmem) {
if (i == 0) {
m_vdec_cfg.
inputBuffer
=
(struct
Vdec_BufferInfo
*)
malloc
(sizeof
(struct
Vdec_BufferInfo)
*
m_inp_buf_count);
if (m_vdec_cfg.inputBuffer == NULL) {
QTV_MSG_PRIO
(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"ERROR - Failed to get input structures\n");
eRet = OMX_ErrorInsufficientResources;
break;
}
m_vdec_cfg.
numInputBuffers
= 0;
}
m_vdec_cfg.
inputBuffer
[i].base =
vdec_buf.
base;
m_vdec_cfg.
inputBuffer
[i].
pmem_id =
vdec_buf.
pmem_id;
m_vdec_cfg.
inputBuffer
[i].
bufferSize =
vdec_buf.
bufferSize;
m_vdec_cfg.
inputBuffer
[i].
pmem_offset
=
vdec_buf.
pmem_offset;
m_vdec_cfg.
inputBuffer
[i].state =
VDEC_BUFFER_WITH_APP;
m_vdec_cfg.
numInputBuffers++;
}
bufHdr->pBuffer =
(OMX_U8 *) vdec_buf.
base;
bufHdr->nAllocLen =
vdec_buf.bufferSize;
}
}
bufHdr->nSize =
sizeof(OMX_BUFFERHEADERTYPE);
bufHdr->nVersion.nVersion =
OMX_SPEC_VERSION;
bufHdr->pAppPrivate = appData;
bufHdr->nInputPortIndex =
OMX_CORE_INPUT_PORT_INDEX;
QTV_MSG_PRIO2(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"Input Buffer %p bufHdr[%p]\n",
bufHdr->pBuffer, bufHdr);
if (!m_bArbitraryBytes
&& bufHdr->pBuffer == NULL) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"ERROR - Failed to get input buffer\n");
eRet =
OMX_ErrorInsufficientResources;
break;
}
}
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"Input buffer memory allocation failed\n");
eRet = OMX_ErrorInsufficientResources;
}
if (m_bArbitraryBytes) {
if (!m_arbitrary_bytes_input_mem_ptr) {
m_arbitrary_bytes_input_mem_ptr =
(char *)calloc((nBufHdrSize), 1);
}
if (m_arbitrary_bytes_input_mem_ptr) {
m_arbitrary_bytes_input[0] =
*bufferHdr = bufHdr =
(OMX_BUFFERHEADERTYPE *)
m_arbitrary_bytes_input_mem_ptr;
for (i = 0; i < m_inp_buf_count;
i++, bufHdr++) {
memset(bufHdr, 0,
sizeof
(OMX_BUFFERHEADERTYPE));
if (VDEC_EFAILED ==
vdec_allocate_input_buffer
(m_inp_buf_size, &vdec_buf,
m_use_pmem)) {
QTV_MSG_PRIO
(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"ERROR - Failed to allocate memory from vdec\n");
bufHdr->pBuffer = NULL;
} else {
if (m_use_pmem) {
if (i == 0) {
m_vdec_cfg.
inputBuffer
=
(struct
Vdec_BufferInfo
*)
malloc
(sizeof
(struct
Vdec_BufferInfo)
*
(m_inp_buf_count
+
OMX_CORE_NUM_INPUT_BUFFERS));
if (m_vdec_cfg.inputBuffer == NULL) {
QTV_MSG_PRIO
(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"ERROR - Failed to get input structures\n");
eRet = OMX_ErrorInsufficientResources;
break;
}
m_vdec_cfg.
numInputBuffers
= 0;
}
m_vdec_cfg.
inputBuffer
[i].base =
vdec_buf.
base;
m_vdec_cfg.
inputBuffer
[i].
pmem_id =
vdec_buf.
pmem_id;
m_vdec_cfg.
inputBuffer
[i].
bufferSize =
vdec_buf.
bufferSize;
m_vdec_cfg.
inputBuffer
[i].
pmem_offset
=
vdec_buf.
pmem_offset;
m_vdec_cfg.
inputBuffer
[i].state =
VDEC_BUFFER_WITH_APP;
m_vdec_cfg.
numInputBuffers++;
}
bufHdr->pBuffer =
(OMX_U8 *) vdec_buf.
base;
bufHdr->nAllocLen =
vdec_buf.bufferSize;
}
bufHdr->nSize =
sizeof
(OMX_BUFFERHEADERTYPE);
bufHdr->nVersion.nVersion =
OMX_SPEC_VERSION;
bufHdr->pAppPrivate = appData;
bufHdr->nInputPortIndex =
OMX_CORE_INPUT_PORT_INDEX;
QTV_MSG_PRIO2(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"arbitrarybytesInput Buffer %p arbitrarybytesInput[%p]\n",
bufHdr->pBuffer,
bufHdr);
if (bufHdr->pBuffer == NULL) {
QTV_MSG_PRIO
(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"ERROR - Failed to get arbitrarybytesInput buffer\n");
eRet =
OMX_ErrorInsufficientResources;
break;
}
}
}
for (int i = 0; i < OMX_CORE_NUM_INPUT_BUFFERS;
i++) {
if (m_extra_buf_info[i].extra_pBuffer ==
NULL) {
//m_extra_buf_info[i].extra_pBuffer = (OMX_U8*) malloc(m_inp_buf_size);
if (VDEC_EFAILED ==
vdec_allocate_input_buffer
(m_inp_buf_size, &vdec_buf,
m_use_pmem)) {
QTV_MSG_PRIO
(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"ERROR - Failed to allocate memory from vdec\n");
bufHdr->pBuffer = NULL;
} else {
if (m_use_pmem) {
m_vdec_cfg.
inputBuffer
[m_inp_buf_count
+ i].base =
vdec_buf.
base;
m_vdec_cfg.
inputBuffer
[m_inp_buf_count
+
i].
pmem_id =
vdec_buf.
pmem_id;
m_vdec_cfg.
inputBuffer
[m_inp_buf_count
+
i].
bufferSize =
vdec_buf.
bufferSize;
m_vdec_cfg.
inputBuffer
[m_inp_buf_count
+
i].
pmem_offset
=
vdec_buf.
pmem_offset;
m_vdec_cfg.
inputBuffer
[m_inp_buf_count
+
i].state =
VDEC_BUFFER_WITH_APP;
m_vdec_cfg.
numInputBuffers++;
}
m_extra_buf_info[i].
extra_pBuffer =
(OMX_U8 *) vdec_buf.
base;
}
if (m_extra_buf_info[i].
extra_pBuffer == NULL) {
QTV_MSG_PRIO
(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"ERROR - Failed to get extra_pBuffer\n");
eRet =
OMX_ErrorInsufficientResources;
break;
}
}
memset(m_extra_buf_info[i].
extra_pBuffer, 0,
vdec_buf.bufferSize);
m_extra_buf_info[i].
bExtra_pBuffer_in_use = false;
m_extra_buf_info[i].
arbitrarybytesInput = NULL;
}
}
} else {
for (i = 0; i < m_inp_buf_count; i++) {
if (BITMASK_ABSENT(m_inp_bm_count, i)) {
// bit space available
break;
}
}
if (i < m_inp_buf_count) {
// found an empty buffer at i
if (m_bArbitraryBytes) {
m_arbitrary_bytes_input[i] =
*bufferHdr =
((OMX_BUFFERHEADERTYPE *)
m_arbitrary_bytes_input_mem_ptr) +
i;
} else {
*bufferHdr =
((OMX_BUFFERHEADERTYPE *)
m_inp_mem_ptr) + i;
}
input[i] =
((OMX_BUFFERHEADERTYPE *) m_inp_mem_ptr) +
i;
(*bufferHdr)->pAppPrivate = appData;
BITMASK_SET(m_inp_bm_count, i);
} else {
eRet = OMX_ErrorInsufficientResources;
}
}
} else {
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) {
OMX_ERRORTYPE eRet = OMX_ErrorNone;
OMX_BUFFERHEADERTYPE *bufHdr; // buffer header
unsigned i; // Temporary counter
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Allocating Output Buffer(%d)\n", m_out_mem_ptr);
if (!m_out_mem_ptr) {
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;
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Allocating First Output Buffer(%d)\n",
m_out_buf_count);
nBufHdrSize = m_out_buf_count * sizeof(OMX_BUFFERHEADERTYPE);
nPMEMInfoSize = m_out_buf_count *
sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
nPlatformListSize = m_out_buf_count *
sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
nPlatformEntrySize = m_out_buf_count *
sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
//m_out_bm_count = BITMASK_SIZE(m_out_buf_count);
QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"TotalBufHdr %d BufHdrSize %d PMEM %d PL %d\n",
nBufHdrSize, sizeof(OMX_BUFFERHEADERTYPE),
nPMEMInfoSize, nPlatformListSize);
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"PE %d bmSize %d \n", nPlatformEntrySize,
m_out_bm_count);
/*
* Memory for output side involves the following:
* 1. Array of Buffer Headers
* 2. Platform specific information List
* 3. Platform specific Entry List
* 4. PMem Information entries
* 5. Bitmask array to hold the buffer allocation details
* In order to minimize the memory management entire allocation
* is done in one step.
*/
//m_out_mem_ptr = (char *)calloc(nBufHdrSize + nPlatformListSize + nPlatformEntrySize +
// nPMEMInfoSize +m_out_bm_count, 1);
// Alloc mem for output buf headers
m_out_mem_ptr = (char *)calloc(nBufHdrSize, 1);
// Alloc mem for platform specific info
char *pPtr = NULL;
pPtr = (char *)calloc(nPlatformListSize + nPlatformEntrySize +
nPMEMInfoSize, 1);
if (m_out_mem_ptr && pPtr) {
bufHdr = (OMX_BUFFERHEADERTYPE *) 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;
//m_out_bm_ptr = (((char *) pPMEMInfo) + nPMEMInfoSize);
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Memory Allocation Succeeded for OUT port%p\n",
m_out_mem_ptr);
// Settting the entire storage nicely
QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"bHdr %p OutMem %p PE %p\n", bufHdr,
m_out_mem_ptr, pPlatformEntry);
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
" Pmem Info = %p \n", pPMEMInfo);
for (i = 0; i < m_out_buf_count; i++) {
memset(bufHdr, 0, sizeof(OMX_BUFFERHEADERTYPE));
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 = appData;
bufHdr->nOutputPortIndex =
OMX_CORE_OUTPUT_PORT_INDEX;
// Platform specific PMEM Information
// Initialize the Platform Entry
//QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,"Initializing the Platform Entry for %d\n",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 = (OMX_U8 *) 0xDEADBEEF;
bufHdr->pOutputPortPrivate = NULL;
pPMEMInfo->offset = 0;
bufHdr->pPlatformPrivate = pPlatformList;
// Move the buffer and buffer header pointers
bufHdr++;
pPMEMInfo++;
pPlatformEntry++;
pPlatformList++;
}
*bufferHdr = (OMX_BUFFERHEADERTYPE *) m_out_mem_ptr;
//m_out_bm_ptr[0]=0x1;
BITMASK_SET(m_out_bm_count, 0);
} else {
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Output buf mem alloc failed[0x%x][0x%x]\n",
m_out_mem_ptr, pPtr);
eRet = OMX_ErrorInsufficientResources;
}
} else {
for (i = 0; i < m_out_buf_count; i++) {
if (BITMASK_ABSENT(m_out_bm_count, i)) {
break;
}
}
if (i < m_out_buf_count) {
// found an empty buffer at i
*bufferHdr =
((OMX_BUFFERHEADERTYPE *) m_out_mem_ptr) + i;
(*bufferHdr)->pAppPrivate = appData;
BITMASK_SET(m_out_bm_count, i);
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"All the Output Buffers have been Allocated ; Returning Insufficient \n");
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) {
OMX_ERRORTYPE eRet = OMX_ErrorNone; // OMX return type
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"\n Allocate buffer on port %d \n", (int)port);
if (m_state == OMX_StateInvalid) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Allocate Buf in Invalid State\n");
return OMX_ErrorInvalidState;
}
// What if the client calls again.
if (port == OMX_CORE_INPUT_PORT_INDEX) {
eRet =
allocate_input_buffer(hComp, bufferHdr, port, appData,
bytes);
} else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
eRet =
allocate_output_buffer(hComp, bufferHdr, port, appData,
bytes);
} else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Error: Invalid Port Index received %d\n",
(int)port);
eRet = OMX_ErrorBadPortIndex;
}
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"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) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Input allocate done");
if (BITMASK_PRESENT
(m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"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) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"output allocate done");
if (m_event_port_settings_sent) {
if (VDEC_SUCCESS != vdec_commit_memory(m_vdec)) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"ERROR!!! vdec_commit_memory failed\n");
m_bInvalidState = true;
m_cb.EventHandler(&m_cmp, m_app_data,
OMX_EventError,
OMX_ErrorInsufficientResources, 0,
NULL);
eRet = OMX_ErrorInsufficientResources;
}
}
if (BITMASK_PRESENT
(m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
// Populate the Buffer Headers
if (m_vdec)
omx_vdec_get_out_buf_hdrs();
// Populate Use Buffer Headers
if (omx_vdec_get_use_buf_flg()) {
omx_vdec_dup_use_buf_hdrs();
omx_vdec_get_out_use_buf_hdrs();
omx_vdec_add_entries();
omx_vdec_display_out_buf_hdrs();
}
#ifdef _ANDROID_
OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo =
m_pmem_info;
// create IMemoryHeap object
m_heap_ptr =
new
VideoHeap(((vdec_frame *) (&m_vdec_cfg.
outputBuffer
[0]))->buffer.
pmem_id, m_vdec->arena[0].size,
((vdec_frame *) (&m_vdec_cfg.
outputBuffer
[0]))->buffer.
base);
for (unsigned i = 0; i < m_out_buf_count; i++) {
pPMEMInfo->pmem_fd =
(OMX_U32) m_heap_ptr.get();
pPMEMInfo++;
}
QTV_MSG_PRIO3(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"VideoHeap : fd %d data %d size %d\n",
((vdec_frame *) (&m_vdec_cfg.
outputBuffer
[0]))->buffer.
pmem_id,
((vdec_frame *) (&m_vdec_cfg.
outputBuffer
[0]))->buffer.
base, m_vdec->arena[0].size);
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"m_heap_ptr =%d",
(unsigned)m_heap_ptr.get());
#endif //_ANDROID_
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"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);
m_event_port_settings_sent = false;
}
}
}
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Allocate Buffer exit with ret Code %d\n", eRet);
return eRet;
}
// Free Buffer - API call
/* ======================================================================
FUNCTION
omx_vdec::FreeBuffer
DESCRIPTION
PARAMETERS
None.
RETURN VALUE
true/false
========================================================================== */
void omx_vdec::cancel_ftb_entry(OMX_BUFFERHEADERTYPE * buffer) {
int i = 0;
mutex_lock();
for (i = 0; i < m_ftb_q.m_size; i++) {
if (m_ftb_q.m_q[i].param2 == (unsigned)buffer) {
m_ftb_q.m_q[i].canceled = true;
break;
}
}
mutex_unlock();
}
// 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;
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED, "free_buffer \n");
if (m_state == OMX_StateIdle
&& (BITMASK_PRESENT(m_flags, OMX_COMPONENT_LOADING_PENDING))) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
" free buffer while Component in Loading pending\n");
} else
if ((m_inp_bEnabled == OMX_FALSE
&& port == OMX_CORE_INPUT_PORT_INDEX)
|| (m_out_bEnabled == OMX_FALSE
&& port == OMX_CORE_OUTPUT_PORT_INDEX)) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Free Buffer while port %d disabled\n", port);
} else if (m_state == OMX_StateExecuting || m_state == OMX_StatePause) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Invalid state to free buffer,ports need to be disabled\n");
post_event(OMX_EventError, OMX_ErrorPortUnpopulated,
OMX_COMPONENT_GENERATE_EVENT);
return eRet;
} else if (m_state != OMX_StateInvalid) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Invalid state to free buffer,port lost Buffers\n");
post_event(OMX_EventError, OMX_ErrorPortUnpopulated,
OMX_COMPONENT_GENERATE_EVENT);
}
if (port == OMX_CORE_INPUT_PORT_INDEX) {
// check if the buffer is valid
if (m_bArbitraryBytes) {
nPortIndex =
buffer -
(OMX_BUFFERHEADERTYPE *)
m_arbitrary_bytes_input_mem_ptr;
if (m_extra_buf_info[nPortIndex].extra_pBuffer != NULL) {
if (omx_vdec_get_input_use_buf_flg()) {
free(m_extra_buf_info[nPortIndex].extra_pBuffer);
}
else {
Vdec_BufferInfo buf_info;
buf_info.base =
m_extra_buf_info[nPortIndex].extra_pBuffer;
if (m_use_pmem) {
buf_info.bufferSize =
m_vdec_cfg.
inputBuffer[m_inp_buf_count +
nPortIndex].bufferSize;
buf_info.pmem_id =
m_vdec_cfg.
inputBuffer[m_inp_buf_count +
nPortIndex].pmem_id;
buf_info.pmem_offset =
m_vdec_cfg.
inputBuffer[m_inp_buf_count +
nPortIndex].pmem_offset;
}
//free(m_extra_buf_info[nPortIndex].extra_pBuffer);
vdec_free_input_buffer(&buf_info, m_use_pmem);
}
m_extra_buf_info[nPortIndex].extra_pBuffer =
NULL;
}
} else {
nPortIndex =
buffer - (OMX_BUFFERHEADERTYPE *) m_inp_mem_ptr;
}
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"free_buffer on i/p port - Port idx %d \n",
nPortIndex);
if (nPortIndex < m_inp_buf_count) {
if(omx_vdec_get_input_use_buf_flg()) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"free_buffer on i/p port - use buffer so do not free pBuffer %x \n",
buffer->pBuffer);
}
else{
Vdec_BufferInfo buf_info;
buf_info.base = buffer->pBuffer;
if (m_use_pmem) {
buf_info.bufferSize =
m_vdec_cfg.inputBuffer[m_inp_buf_count +
nPortIndex].
bufferSize;
buf_info.pmem_id =
m_vdec_cfg.inputBuffer[m_inp_buf_count +
nPortIndex].pmem_id;
buf_info.pmem_offset =
m_vdec_cfg.inputBuffer[m_inp_buf_count +
nPortIndex].
pmem_offset;
}
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"free_buffer on i/p port - pBuffer %x \n",
buffer->pBuffer);
vdec_free_input_buffer(&buf_info, m_use_pmem);
buffer->pBuffer = NULL;
}
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"free_buffer on i/p port - before Clear bitmask %x \n",
m_inp_bm_count);
// Clear the bit associated with it.
BITMASK_CLEAR(m_inp_bm_count, nPortIndex);
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"free_buffer on i/p port - after Clear bitmask %x \n",
m_inp_bm_count);
m_inp_bPopulated = OMX_FALSE;
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Error: free_buffer , \
Port Index calculation came out Invalid\n");
eRet = OMX_ErrorBadPortIndex;
}
if (BITMASK_PRESENT
((m_flags), OMX_COMPONENT_INPUT_DISABLE_PENDING)
&& release_input_done()) {
if (m_use_pmem) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Release input done freeing input buffer \n");
if (m_vdec_cfg.inputBuffer) {
free(m_vdec_cfg.inputBuffer);
m_vdec_cfg.inputBuffer = NULL;
}
}
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"MOVING TO DISABLED STATE \n");
BITMASK_CLEAR((m_flags),
OMX_COMPONENT_INPUT_DISABLE_PENDING);
post_event(OMX_CommandPortDisable,
OMX_CORE_INPUT_PORT_INDEX,
OMX_COMPONENT_GENERATE_EVENT);
}
if (omx_vdec_get_input_use_buf_flg() && release_input_done()) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Resetting use_buf flag\n");
omx_vdec_reset_input_use_buf_flg();
}
} else if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
// check if the buffer is valid
nPortIndex = buffer - (OMX_BUFFERHEADERTYPE *) m_out_mem_ptr;
if (nPortIndex < m_out_buf_count) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"free_buffer on o/p port - Port idx %d \n",
nPortIndex);
// Clear the bit associated with it.
BITMASK_CLEAR(m_out_bm_count, nPortIndex);
cancel_ftb_entry(buffer);
m_out_bPopulated = OMX_FALSE;
if (omx_vdec_get_use_buf_flg()) {
OMX_BUFFERHEADERTYPE *temp;
// Remove both the mappings.
temp = m_use_buf_hdrs.find(buffer);
if (buffer && temp) {
m_use_buf_hdrs.erase(buffer);
m_use_buf_hdrs.erase(temp);
}
}
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Error: free_buffer , \
Port Index calculation came out Invalid\n");
eRet = OMX_ErrorBadPortIndex;
}
if (BITMASK_PRESENT
((m_flags), OMX_COMPONENT_OUTPUT_DISABLE_PENDING)
&& release_output_done()) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"FreeBuffer : If any Disable event pending,post it\n");
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"MOVING TO DISABLED STATE \n");
BITMASK_CLEAR((m_flags),
OMX_COMPONENT_OUTPUT_DISABLE_PENDING);
if (m_vdec) {
m_out_buf_count = m_vdec_cfg.numOutputBuffers;
omx_vdec_free_output_port_memory();
}
if(omx_vdec_get_use_egl_buf_flg()) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Resetting use_egl_buf flag\n");
omx_vdec_reset_use_elg_buf_flg();
}
post_event(OMX_CommandPortDisable,
OMX_CORE_OUTPUT_PORT_INDEX,
OMX_COMPONENT_GENERATE_EVENT);
return eRet;
}
if (omx_vdec_get_use_buf_flg() && release_done()) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Resetting use_buf flag\n");
omx_vdec_reset_use_buf_flg();
}
} 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)
{
QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
"empty_this_buffer buffer %p, len %d, offset %d timestamp %ld\n",
buffer->pBuffer, buffer->nFilledLen, buffer->nOffset,
buffer->nTimeStamp);
OMX_ERRORTYPE eRet = OMX_ErrorNone;
if (m_state == OMX_StateInvalid) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"ETB in Invalid State\n");
return OMX_ErrorInvalidState;
}
if (!buffer) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Buffer Header NULL\n");
return OMX_ErrorBadParameter;
}
if (m_bArbitraryBytes) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
"empty_this_buffer - post event OMX_COMPONENT_GENERATE_ETB_ARBITRARYBYTES\n");
post_event((unsigned)hComp, (unsigned)buffer,
OMX_COMPONENT_GENERATE_ETB_ARBITRARYBYTES);
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
"empty_this_buffer - post event OMX_COMPONENT_GENERATE_ETB\n");
post_event((unsigned)hComp, (unsigned)buffer,
OMX_COMPONENT_GENERATE_ETB);
// eRet = empty_this_buffer_frame_based(hComp, buffer);
}
return eRet;
}
/* ======================================================================
FUNCTION
omx_vdec::empty_this_buffer_frame_based
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_frame_based(OMX_IN OMX_HANDLETYPE hComp,
OMX_IN OMX_BUFFERHEADERTYPE * buffer) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
"empty_this_buffer_frame_based - enter\n");
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
"empty_this_buffer_frame_based buffer->nTimeStamp %d nFlags %d\n",
buffer->nTimeStamp, buffer->nFlags);
unsigned height = 0,val_height = 0;
unsigned width = 0, val_width = 0;
bool bInterlace = false;
unsigned cropx = 0, cropy = 0, cropdx = 0, cropdy = 0;
/*if(m_state == OMX_StateInvalid)
{
QTV_MSG_PRIO(QTVDIAG_GENERAL,QTVDIAG_PRIO_MED,_ERROR("ETB in Invalid State\n");
return OMX_ErrorInvalidState;
} */
if(m_bInvalidState == true)
{
buffer_done_cb_stub(&m_vdec_cfg, buffer);
return OMX_ErrorNone;
}
OMX_ERRORTYPE ret = OMX_ErrorNone;
OMX_ERRORTYPE ret1 = OMX_ErrorNone;
OMX_U32 ret2;
bool has_frame = true;
unsigned nBufferIndex =
buffer - ((OMX_BUFFERHEADERTYPE *) m_inp_mem_ptr);
if (m_event_port_settings_sent == true) {
if (m_bAccumulate_subframe == false) {
add_entry(nBufferIndex);
return OMX_ErrorNone;
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
"empty_this_buffer - m_event_port_settings_sent == true\n");
return add_entry_subframe_stitching(buffer);
}
}
if (!m_vdec) {
if (nBufferIndex > m_inp_buf_count) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"omx_vdec::etb--> Buffer Index Invalid\n");
return OMX_ErrorBadPortIndex;
}
if ((strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc", 26)
== 0)
&& m_header_state != HEADER_STATE_RECEIVED_COMPLETE) {
bool is_partial;
has_frame = false;
ret2 =
m_h264_utils->check_header(buffer, m_nalu_bytes,
is_partial,
(OMX_U32)
m_header_state);
if (ret2 == -1) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"omx_vdec::etb--> Wrong Data before recieving the header\n");
buffer_done_cb_stub(&m_vdec_cfg, buffer);
return OMX_ErrorFormatNotDetected;
} else {
if (is_partial) {
if (m_header_state ==
HEADER_STATE_RECEIVED_NONE) {
m_vendor_config.pData =
(OMX_U8 *) malloc(buffer->
nFilledLen);
memcpy(m_vendor_config.pData,
buffer->pBuffer,
buffer->nFilledLen);
m_vendor_config.nDataSize =
buffer->nFilledLen;
m_header_state =
HEADER_STATE_RECEIVED_PARTIAL;
} else {
if (m_vendor_config.pData) {
OMX_U8 *tempData;
tempData =
m_vendor_config.
pData;
m_vendor_config.pData =
(OMX_U8 *)
malloc(buffer->
nFilledLen +
m_vendor_config.
nDataSize);
memcpy(m_vendor_config.
pData, tempData,
m_vendor_config.
nDataSize);
memcpy(m_vendor_config.
pData +
m_vendor_config.
nDataSize,
buffer->pBuffer,
buffer->
nFilledLen);
m_vendor_config.
nDataSize +=
buffer->nFilledLen;
free(tempData);
m_header_state =
HEADER_STATE_RECEIVED_COMPLETE;
} else {
QTV_MSG_PRIO
(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"omx_vdec::etb--> header_state partial but pData NULL\n");
return
OMX_ErrorFormatNotDetected;
}
}
} else {
if (m_vendor_config.pData) {
free(m_vendor_config.pData);
}
m_vendor_config.pData =
(OMX_U8 *) malloc(buffer->
nFilledLen);
memcpy(m_vendor_config.pData,
buffer->pBuffer,
buffer->nFilledLen);
m_vendor_config.nDataSize =
buffer->nFilledLen;
m_header_state =
HEADER_STATE_RECEIVED_COMPLETE;
}
if (m_header_state !=
HEADER_STATE_RECEIVED_COMPLETE) {
buffer_done_cb_stub(&m_vdec_cfg,
buffer);
return OMX_ErrorNone;
}
}
} else
if ((strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.mpeg4",
28) == 0))
{
has_frame = MP4_Utils::HasFrame(buffer);
} else
if ((strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.vc1",
26) == 0))
{
if(!m_bArbitraryBytes)
has_frame = false;
} else
if ((strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.divx",
27) == 0))
{
if (m_codec_format != QOMX_VIDEO_DIVXFormat311)
has_frame = MP4_Utils::HasFrame(buffer);
}
ret =
omx_vdec_check_port_settings(buffer, height, width,
bInterlace, cropx, cropy,
cropdx, cropdy);
if (ret != OMX_ErrorNone) {
buffer_done_cb_stub(&m_vdec_cfg, buffer);
m_bInvalidState = true;
m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventError,
OMX_ErrorFormatNotDetected , 0, NULL);
return ret;
}
m_bInterlaced = bInterlace;
QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"ETB::after parsing-->Ht[%d] Wd[%d] m_ht[%d] m_wdth[%d]\n",
height, width, m_height, m_width);
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"ETB::after parsing-->cropdy[%d] Cropdx[%d] \n",
cropdy, cropdx);
m_crop_x = cropx;
m_crop_y = cropy;
m_crop_dx = cropdx;
m_crop_dy = cropdy;
QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"ETB::after parsing-->Height[%d] Width[%d] m_ht[%d] m_wdth[%d]\n",
height, width, m_height, m_width);
if (m_color_format == QOMX_COLOR_FormatYVU420PackedSemiPlanar32m4ka)
{
val_height = (m_crop_dy + 15) & ~15;
val_width = (m_crop_dx + 15) & ~15;
}
else
{
val_height = height;
val_width = width;
}
if ((ret1 =
omx_vdec_validate_port_param(val_height,
val_width)) == OMX_ErrorNone) {
m_port_height = height;
m_port_width = width;
// Create native decoder to figure out the output buffer count and size.
ret = omx_vdec_create_native_decoder(buffer);
if (OMX_ErrorNone != ret) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"Native decoder creation failed\n");
m_bInvalidState = true;
m_cb.EventHandler(&m_cmp, m_app_data,
OMX_EventError,
OMX_ErrorInsufficientResources, 0,
NULL);
return ret;
}
if ((m_crop_dy == height == m_height)
&& (m_crop_dx == width == m_width)
&& (m_out_buf_count == m_vdec_cfg.numOutputBuffers)
&& (!m_bInterlaced)) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
"Port setting Changed is not needed\n");
if (VDEC_SUCCESS != vdec_commit_memory(m_vdec)) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"ERROR!!! vdec_commit_memory failed\n");
m_bInvalidState = true;
m_cb.EventHandler(&m_cmp, m_app_data,
OMX_EventError,
OMX_ErrorInsufficientResources, 0,
NULL);
return OMX_ErrorInsufficientResources;
}
// Populate Output Buffer Headers
omx_vdec_get_out_buf_hdrs();
// Populate Use Buffer Headers
if (omx_vdec_get_use_buf_flg()) {
omx_vdec_dup_use_buf_hdrs();
omx_vdec_get_out_use_buf_hdrs();
omx_vdec_display_out_buf_hdrs();
omx_vdec_add_entries();
omx_vdec_display_out_use_buf_hdrs();
}
OMX_BUFFERHEADERTYPE *tmp_buf_hdr =
(OMX_BUFFERHEADERTYPE *)
flush_before_vdec_op_q->Dequeue();
while (tmp_buf_hdr) {
vdec_release_frame(m_vdec,
(vdec_frame *)
tmp_buf_hdr->
pOutputPortPrivate);
tmp_buf_hdr =
(OMX_BUFFERHEADERTYPE *)
flush_before_vdec_op_q->Dequeue();
}
#ifdef _ANDROID_
OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo =
m_pmem_info;
// create IMemoryHeap object
m_heap_ptr =
new
VideoHeap(((vdec_frame *) (&m_vdec_cfg.
outputBuffer
[0]))->buffer.
pmem_id, m_vdec->arena[0].size,
((vdec_frame *) (&m_vdec_cfg.
outputBuffer
[0]))->buffer.
base);
for (unsigned i = 0;
i < m_vdec_cfg.numOutputBuffers; i++) {
pPMEMInfo->pmem_fd =
(OMX_U32) m_heap_ptr.get();
pPMEMInfo++;
}
QTV_MSG_PRIO3(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"VideoHeap : fd %d data %d size %d\n",
((vdec_frame *) (&m_vdec_cfg.
outputBuffer
[0]))->buffer.
pmem_id,
((vdec_frame *) (&m_vdec_cfg.
outputBuffer
[0]))->buffer.
base, m_vdec->arena[0].size);
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"m_heap_ptr =%d",
(unsigned)m_heap_ptr.get());
#endif //_ANDROID_
} else {
// Store the Ht and Width param so that the client can do a GetParam
m_event_port_settings_sent = true;
// Notify Apps about the Event [ PortSettingsChangedEvent ]
if (m_cb.EventHandler) {
m_cb.EventHandler(&m_cmp, m_app_data,
OMX_EventPortSettingsChanged,
OMX_CORE_OUTPUT_PORT_INDEX,
0, NULL);
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"Sending OMX EVENT PORT_SETTINGS_CHANGED EVENT \n");
}
if (has_frame) {
if (m_bAccumulate_subframe == false
|| (buffer->
nFlags & OMX_BUFFERFLAG_EOS)) {
add_entry(nBufferIndex);
return OMX_ErrorNone;
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_HIGH,
"After sending Port Setting Change Event\n");
return
add_entry_subframe_stitching
(buffer);
}
}
}
if (!has_frame) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
"There is no frame to send - do buffer done and return\n");
buffer_done_cb_stub(&m_vdec_cfg, buffer);
return OMX_ErrorNone;
}
} else {
m_bInvalidState = true;
m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventError,
ret1, 0, NULL);
return ret1;
}
}
return empty_this_buffer_proxy(hComp, buffer);
}
/* ======================================================================
FUNCTION
omx_vdec::empty_this_buffer_proxy_arbitrary_bytes
DESCRIPTION
This routine is used to push the arbritary bit stream to
the video decoder.
PARAMETERS
None.
RETURN VALUE
OMX Error None if everything went successful.
========================================================================== */
OMX_ERRORTYPE omx_vdec::
empty_this_buffer_proxy_arbitrary_bytes(OMX_HANDLETYPE hComp,
OMX_BUFFERHEADERTYPE * buffer) {
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"omx_vdec::empty_this_buffer_proxy_arbitrary_bytes - m_current_arbitrary_bytes_input %p %p\n",
m_current_arbitrary_bytes_input, m_vdec);
if (m_state == OMX_StateInvalid) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"empty_this_buffer_proxy_arbitrary_bytes in Invalid State\n");
m_current_arbitrary_bytes_input = NULL;
return OMX_ErrorInvalidState;
}
if (m_bInvalidState) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"empty_this_buffer_proxy_arbitrary_bytes in Invalid State Flag true\n");
buffer_done_cb_stub(&m_vdec_cfg, buffer);
return OMX_ErrorNone;
}
if (!m_bPartialFrame) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Start to get complete new frame %x\n",
m_current_frame);
m_current_frame = get_free_input_buffer();
if (m_current_frame == NULL) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
"omx_vdec::empty_this_buffer_proxy_arbitrary_bytes, waiting for resource");
m_bWaitForResource = true;
return OMX_ErrorNone;
}
m_current_frame->pBuffer = buffer->pBuffer + buffer->nOffset;
m_current_frame->nOffset = 0;
m_current_frame->nFilledLen = 0;
}
if (!m_vdec) {
if (m_vendor_config.pData) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Sending SPS+PPS as part of vdec_open\n");
} else {
if (strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.mpeg4",
28) == 0) {
m_arbitrary_bytes_info.start_code.m_start_code =
VOP_START_CODE;
m_arbitrary_bytes_info.start_code.
m_start_code_mask = VOP_START_CODE_MASK;
m_bStartCode = true;
} else
if (strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.divx",
27) == 0) {
m_arbitrary_bytes_info.start_code.m_start_code =
VOP_START_CODE;
m_arbitrary_bytes_info.start_code.
m_start_code_mask = VOP_START_CODE_MASK;
m_bStartCode = true;
}else
if (strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.spark",
28) == 0) {
if (m_codec_format == QOMX_VIDEO_SparkFormat1) {
m_arbitrary_bytes_info.start_code.m_start_code =
SPARK1_START_CODE;
}
else {
m_arbitrary_bytes_info.start_code.m_start_code =
SHORT_HEADER_START_CODE;
}
m_arbitrary_bytes_info.start_code.
m_start_code_mask = SHORT_HEADER_MASK;
m_bStartCode = true;
}else
if (strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.h263",
27) == 0) {
m_arbitrary_bytes_info.start_code.m_start_code =
SHORT_HEADER_START_CODE;
m_arbitrary_bytes_info.start_code.
m_start_code_mask = SHORT_HEADER_MASK;
m_bStartCode = true;
} else
if (strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc",
26) == 0) {
if (m_nalu_bytes == 0) {
m_arbitrary_bytes_info.start_code.
m_start_code = H264_START_CODE;
m_arbitrary_bytes_info.start_code.
m_start_code_mask =
H264_START_CODE_MASK;
m_bStartCode = true;
} else {
m_bStartCode = false;
}
} else
if (strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.vc1",
26) == 0) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"VC1 clip \n");
if ((((*((OMX_U32 *) m_current_frame->pBuffer))
& VC1_SP_MP_START_CODE_MASK) ==
VC1_SP_MP_START_CODE)
||
(((*((OMX_U32 *) m_current_frame->pBuffer))
& VC1_SP_MP_START_CODE_MASK) ==
VC1_SP_MP_START_CODE_RCV_V1)
) {
OMX_U32 *pBuf32;
OMX_U8 *pBuf8;
pBuf32 =
(OMX_U32 *) m_current_frame->
pBuffer;
/* size of struct C or sequence header appears right after the number of frames information in the sequence header */
m_vdec_cfg.sequenceHeaderLen =
*(++pBuf32);
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"empty_this_buffer_proxy_arbitrary_bytes: sequence header len: %d \n",
m_vdec_cfg.
sequenceHeaderLen);
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"VC1 clip - Simple Main Profile\n");
if (m_vendor_config.pData) {
free(m_vendor_config.pData);
}
m_vendor_config.nPortIndex = 0;
if (((*
((OMX_U32 *) m_current_frame->
pBuffer)) &
VC1_SP_MP_START_CODE_MASK) ==
VC1_SP_MP_START_CODE) {
m_vendor_config.nDataSize =
OMX_VC1_SEQ_LAYER_SIZE_WITHOUT_STRUCTC
+
m_vdec_cfg.
sequenceHeaderLen;
m_arbitrary_bytes_info.
frame_size.
m_timestamp_field_present =
1;
} else
if (((*
((OMX_U32 *) m_current_frame->
pBuffer)) &
VC1_SP_MP_START_CODE_MASK) ==
VC1_SP_MP_START_CODE_RCV_V1) {
m_vendor_config.nDataSize =
OMX_VC1_SEQ_LAYER_SIZE_V1_WITHOUT_STRUCTC
+
m_vdec_cfg.
sequenceHeaderLen;
/* set the time stamp field to be 0 so that the timestamp field is not parsed for RCV V1 format */
m_arbitrary_bytes_info.
frame_size.
m_timestamp_field_present =
0;
}
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"empty_this_buffer_proxy_arbitrary_bytes: m_vendor_config.nDataSize: %d \n",
m_vendor_config.
nDataSize);
m_vendor_config.pData =
(OMX_U8 *) malloc(m_vendor_config.
nDataSize);
memcpy(m_vendor_config.pData,
m_current_arbitrary_bytes_input->
pBuffer +
m_current_arbitrary_bytes_input->
nOffset,
m_vendor_config.nDataSize);
m_current_arbitrary_bytes_input->
nFilledLen -=
m_vendor_config.nDataSize;
memmove
(m_current_arbitrary_bytes_input->
pBuffer,
m_current_arbitrary_bytes_input->
pBuffer +
m_vendor_config.nDataSize,
m_current_arbitrary_bytes_input->
nFilledLen);
m_bStartCode = false;
m_bAccumulate_subframe = false;
} else
if (*((OMX_U32 *) m_current_frame->pBuffer)
== 0x0F010000) {
m_arbitrary_bytes_info.start_code.
m_start_code = VC1_AP_START_CODE;
m_arbitrary_bytes_info.start_code.
m_start_code_mask =
VC1_AP_START_CODE_MASK;
m_bStartCode = true;
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_HIGH,
"empty_this_buffer_proxy_arbitrary_bytes - Warning: Possibility of Simple Main VC1 profile without sequence layer\n");
}
}
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Start code 0x%.8x mask 0x%.8x\n",
m_arbitrary_bytes_info.start_code.
m_start_code,
m_arbitrary_bytes_info.start_code.
m_start_code_mask);
}
}
if (get_one_complete_frame(m_current_frame)) {
empty_this_buffer_proxy_frame_based(hComp, m_current_frame);
} else {
int pend_idx = get_first_pending_index();
if (pend_idx >= 0) {
push_pending_buffers_proxy();
}
}
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) {
int push_cnt = 0;
OMX_ERRORTYPE ret = OMX_ErrorNone;
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"EMPTY THIS BUFFER...%p\n", buffer);
++m_etb_cnt;
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"ETB: Count %u TS %lld\n", m_etb_cnt, buffer->nTimeStamp);
if (m_bAccumulate_subframe) {
ret = empty_this_buffer_proxy_subframe_stitching(buffer);
} else {
unsigned nPortIndex =
buffer - ((OMX_BUFFERHEADERTYPE *) m_inp_mem_ptr);
if (nPortIndex < m_inp_buf_count) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Original Empty this buffer\n");
int pend_idx = get_first_pending_index();
if (pend_idx >= 0 && (pend_idx != (int)nPortIndex)) {
// Buffer-2 will hold the existing buffer in hand
// We are trying to append the data to buffer2
OMX_BUFFERHEADERTYPE *buffer2 = input[pend_idx];
signed long long T1 = buffer->nTimeStamp;
signed long long T2 = buffer2->nTimeStamp;
{
add_entry(nPortIndex);
QTV_MSG_PRIO2(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"Setting the pending flag for buffer-%d (%x) \n",
nPortIndex + 1,
m_flags[0] );
push_cnt = push_pending_buffers_proxy();
}
} else {
push_cnt += push_one_input_buffer(buffer);
}
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"empty_this_buffer_proxy pushed %d frames to the decoder\n",
push_cnt);
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"FATAL ERROR: Why client is pushing the invalid buffer\n");
ret = OMX_ErrorFormatNotDetected;
}
}
return ret;
}
/* ======================================================================
FUNCTION
omx_vdec::empty_this_buffer_subframe_stitching
DESCRIPTION
This routine is used to push the encoded video frames to
the video decoder considering the subframe stitching
PARAMETERS
None.
RETURN VALUE
OMX Error None if everything went successful.
========================================================================== */
OMX_ERRORTYPE omx_vdec::
empty_this_buffer_proxy_subframe_stitching(OMX_BUFFERHEADERTYPE * buffer) {
#if DEBUG_ON
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"empty_this_buffer_proxy_subframe_stitching, length %d offset %d\n",
buffer->nFilledLen, buffer->nOffset);
for (OMX_U32 i = 0; i < 32; i++) {
printf("0x%.2x ", buffer->pBuffer[buffer->nOffset + i]);
if (i % 16 == 15) {
printf("\n");
}
}
printf("\n");
if (m_pcurrent_frame) {
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"empty_this_buffer_proxy_subframe_stitching, current length %d offset %d\n",
m_pcurrent_frame->nFilledLen,
m_pcurrent_frame->nOffset);
for (OMX_U32 i = 0; i < 32; i++) {
printf("0x%.2x ", m_pcurrent_frame->pBuffer[i]);
if (i % 16 == 15) {
printf("\n");
}
}
printf("\n");
}
#endif
int pend_idx = -1;
int push_cnt = 0;
unsigned nPortIndex = buffer - ((OMX_BUFFERHEADERTYPE *) m_inp_mem_ptr);
OMX_ERRORTYPE ret = OMX_ErrorNone;
bool isUpdatetimestamp = false;
bool is_frame_no_error = true;
if (nPortIndex < m_inp_buf_count) {
OMX_BOOL isNewFrame = OMX_TRUE;
if (buffer->nFilledLen > 0) {
if (strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc",
26) == 0) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"empty_this_buffer_proxy_subframe_stitching- H264\n");
is_frame_no_error =
m_h264_utils->isNewFrame(buffer->pBuffer +
buffer->nOffset,
buffer->nFilledLen,
m_vdec_cfg.
size_of_nal_length_field,
isNewFrame,
isUpdatetimestamp);
if(isUpdatetimestamp && (m_pcurrent_frame != NULL)) {
m_pcurrent_frame->nTimeStamp = buffer->nTimeStamp;
}
} else
if (strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.vc1",
26) == 0) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"empty_this_buffer_proxy_subframe_stitching- VC1\n");
is_frame_no_error =
find_new_frame_ap_vc1(buffer->pBuffer +
buffer->nOffset,
buffer->nFilledLen,
isNewFrame);
}
if (false == is_frame_no_error) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"empty_this_buffer_proxy_subframe_stitching- Bit stream Error send Eventerro\n");
m_bInvalidState = true;
m_cb.EventHandler(&m_cmp, m_app_data,
OMX_EventError,
OMX_ErrorStreamCorrupt, 0,
NULL);
return OMX_ErrorStreamCorrupt;
}
}
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"After Subframe stitching process %d\n",
isNewFrame);
if (OMX_TRUE == isNewFrame) {
pend_idx = get_first_pending_index();
nPortIndex =
m_pcurrent_frame -
((OMX_BUFFERHEADERTYPE *) m_inp_mem_ptr);
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Subframe stitching - NEW Frame %d %d\n",
pend_idx, nPortIndex);
if (pend_idx >= 0 && (pend_idx != (int)nPortIndex)) {
add_entry(nPortIndex);
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Setting the pending flag for buffer-%d (%x) \n",
nPortIndex + 1, m_flags[0] );
push_cnt = push_pending_buffers_proxy();
} else if (m_pcurrent_frame) {
push_cnt +=
push_one_input_buffer(m_pcurrent_frame);
}
if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Subframe stitching - EOS\n");
pend_idx = get_first_pending_index();
nPortIndex =
buffer -
((OMX_BUFFERHEADERTYPE *) m_inp_mem_ptr);
if (pend_idx >= 0
&& (pend_idx != (int)nPortIndex)) {
add_entry(nPortIndex);
QTV_MSG_PRIO2(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"Setting the pending flag for buffer-%d (%x) \n",
nPortIndex + 1,
m_flags[0] );
push_cnt = push_pending_buffers_proxy();
} else {
push_cnt +=
push_one_input_buffer(buffer);
}
} else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"empty_this_buffer_proxy_subframe_stitching pushed %d frames to the decoder\n",
push_cnt);
m_pcurrent_frame = buffer;
if (m_bArbitraryBytes) {
m_pcurrent_frame->pBuffer +=
m_pcurrent_frame->nOffset;
m_pcurrent_frame->nOffset = 0;
}
}
} else {
if (m_bArbitraryBytes) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
"empty_this_buffer_proxy_subframe_stitching arbitrary bytes - SUBFRAME_TYPE_PREVIOUS_FRAME\n");
if (m_pcurrent_frame == NULL) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_HIGH,
"DUDE - It's not a new frame but m_pcurrent_frame is NULL - It's a good case for first Subframe\n");
m_pcurrent_frame = buffer;
} else
if (find_extra_buffer_index
(m_pcurrent_frame->pBuffer) != -1) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_HIGH,
"Copy the new buffer to the current frame allocLen %d\n",
m_pcurrent_frame->
nAllocLen);
memcpy(m_pcurrent_frame->pBuffer +
m_pcurrent_frame->nFilledLen,
buffer->pBuffer +
buffer->nOffset,
buffer->nFilledLen);
m_pcurrent_frame->nFilledLen +=
buffer->nFilledLen;
} else
if (find_extra_buffer_index(buffer->pBuffer)
!= -1) {
QTV_MSG_PRIO4(QTVDIAG_GENERAL,
QTVDIAG_PRIO_HIGH,
"Buffer %p must be an extra buffer size of current len %d extra len %d extra offset %d\n",
buffer->pBuffer,
m_pcurrent_frame->
nFilledLen,
buffer->nFilledLen,
buffer->nOffset);
memmove(buffer->pBuffer +
m_pcurrent_frame->nFilledLen,
buffer->pBuffer +
buffer->nOffset,
buffer->nFilledLen);
memcpy(buffer->pBuffer,
m_pcurrent_frame->pBuffer,
m_pcurrent_frame->nFilledLen);
/* We need to swap pBuffer pointer so buffer done cb will free the unused pbuffer */
OMX_U8 *temp =
m_pcurrent_frame->pBuffer;
m_pcurrent_frame->pBuffer =
buffer->pBuffer;
buffer->pBuffer = temp;
m_pcurrent_frame->nFilledLen +=
buffer->nFilledLen;
} else
if ((m_pcurrent_frame->pBuffer +
m_pcurrent_frame->nFilledLen ==
buffer->pBuffer + buffer->nOffset)
&& (m_pcurrent_frame->nFilledLen +
buffer->nFilledLen <=
m_pcurrent_frame->nAllocLen)) {
QTV_MSG_PRIO2(QTVDIAG_GENERAL,
QTVDIAG_PRIO_HIGH,
"No need memcpy, current length %d added by %d\n",
m_pcurrent_frame->
nFilledLen,
buffer->nFilledLen);
m_pcurrent_frame->nFilledLen +=
buffer->nFilledLen;
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_HIGH,
"Buffer is not enough. Need to get extra buffer \n");
OMX_S8 index =
get_free_extra_buffer_index();
if (index != -1) {
memcpy(m_extra_buf_info[index].
extra_pBuffer,
m_pcurrent_frame->
pBuffer,
m_pcurrent_frame->
nFilledLen);
memcpy(m_extra_buf_info[index].
extra_pBuffer +
m_pcurrent_frame->
nFilledLen,
buffer->pBuffer +
buffer->nOffset,
buffer->nFilledLen);
m_pcurrent_frame->pBuffer =
m_extra_buf_info[index].
extra_pBuffer;
m_pcurrent_frame->nFilledLen +=
buffer->nFilledLen;
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"Couldn't find extra buffer\n");
return OMX_ErrorHardware;
}
}
} else // non arbitrary bytes - previous frame
{
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Subframe stitching - Previous Frame\n");
if (m_pcurrent_frame == NULL) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_HIGH,
"It's not a new frame but m_pcurrent_frame is NULL - it's a good case for the first Subframe\n");
m_pcurrent_frame = buffer;
} else if (m_pcurrent_frame->nFilledLen +
buffer->nFilledLen <=
m_pcurrent_frame->nAllocLen) {
// Stitching the current buffer into previous one
memcpy(&m_pcurrent_frame->
pBuffer[m_pcurrent_frame->
nFilledLen],
buffer->pBuffer,
buffer->nFilledLen);
m_pcurrent_frame->nFilledLen +=
buffer->nFilledLen;
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_HIGH,
"Not enough memory - Stitching failed \n");
ret = OMX_ErrorFormatNotDetected;
}
}
m_pcurrent_frame->nFlags |= buffer->nFlags;
if (m_pcurrent_frame->nFlags & OMX_BUFFERFLAG_EOS) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Subframe stitching partial frame - EOS\n");
pend_idx = get_first_pending_index();
nPortIndex =
m_pcurrent_frame -
((OMX_BUFFERHEADERTYPE *) m_inp_mem_ptr);
if (pend_idx >= 0
&& (pend_idx != (int)nPortIndex)) {
add_entry(nPortIndex);
QTV_MSG_PRIO2(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"Setting the pending flag for buffer-%d (%x) \n",
nPortIndex + 1,
m_flags[0] );
push_cnt = push_pending_buffers_proxy();
} else {
push_cnt +=
push_one_input_buffer
(m_pcurrent_frame);
}
}
buffer_done_cb_stub(&m_vdec_cfg, buffer);
}
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"FATAL ERROR: Why client is pushing the invalid buffer\n");
ret = OMX_ErrorFormatNotDetected;
}
return ret;
}
/* ======================================================================
FUNCTION
omx_vdec::add_entry_subframe_stitching
DESCRIPTION
add_entry scenarion when SUBFRAME stitching required
PARAMETERS
None.
RETURN VALUE
OMX Error None if everything went successful.
========================================================================== */
OMX_ERRORTYPE omx_vdec::
add_entry_subframe_stitching(OMX_IN OMX_BUFFERHEADERTYPE * buffer) {
#if DEBUG_ON
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"add_entry_subframe_stitching, length %d\n",
buffer->nFilledLen);
for (OMX_U32 i = 0; i < 32; i++) {
printf("0x%.2x ", buffer->pBuffer[buffer->nOffset + i]);
if (i % 16 == 15) {
printf("\n");
}
}
printf("\n");
if (m_pcurrent_frame) {
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"add_entry_subframe_stitching, current length %d offset %d\n",
m_pcurrent_frame->nFilledLen,
m_pcurrent_frame->nOffset);
for (OMX_U32 i = 0; i < 32; i++) {
printf("0x%.2x ", m_pcurrent_frame->pBuffer[i]);
if (i % 16 == 15) {
printf("\n");
}
}
printf("\n");
}
#endif
OMX_ERRORTYPE ret = OMX_ErrorNone;
unsigned nBufferIndex =
m_pcurrent_frame - ((OMX_BUFFERHEADERTYPE *) m_inp_mem_ptr);
OMX_BOOL isNewFrame = OMX_FALSE;
bool isUpdatetimestamp = false;
bool is_frame_no_error = true;
if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc", 26) == 0) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"add_entry_subframe_stitching- H264\n");
is_frame_no_error =
m_h264_utils->isNewFrame(buffer->pBuffer + buffer->nOffset,
buffer->nFilledLen,
m_vdec_cfg.
size_of_nal_length_field,
isNewFrame,
isUpdatetimestamp);
if(isUpdatetimestamp && (m_pcurrent_frame != NULL)) {
m_pcurrent_frame->nTimeStamp = buffer->nTimeStamp;
}
} else if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.vc1", 26) ==
0) {
is_frame_no_error =
find_new_frame_ap_vc1(buffer->pBuffer + buffer->nOffset,
buffer->nFilledLen, isNewFrame);
}
if (false == is_frame_no_error) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Subframe stitching - Bit stream Error send Eventerro\n");
m_bInvalidState = true;
m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventError,
OMX_ErrorStreamCorrupt, 0, NULL);
return OMX_ErrorStreamCorrupt;
}
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
"add_entry_subframe_stitching\n");
if (OMX_TRUE == isNewFrame) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"add_entry_subframe_stitching - NEW Frame\n");
if (m_pcurrent_frame != NULL || buffer->nFlags & OMX_BUFFERFLAG_EOS) {
if(m_pcurrent_frame == NULL)
{
m_pcurrent_frame = buffer;
nBufferIndex = m_pcurrent_frame - ((OMX_BUFFERHEADERTYPE *) m_inp_mem_ptr);
}
m_pcurrent_frame->nFlags |= buffer->nFlags;
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"add_entry_subframe_stitching - add entry previous buffer\n");
add_entry(nBufferIndex);
}
m_pcurrent_frame = buffer;
if (m_bArbitraryBytes) {
m_pcurrent_frame->pBuffer += m_pcurrent_frame->nOffset;
m_pcurrent_frame->nOffset = 0;
}
} else if (m_bArbitraryBytes) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"add_entry_subframe_stitching arbitrary bytes - SUBFRAME_TYPE_PREVIOUS_FRAME\n");
if (m_pcurrent_frame == NULL) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
"It's not a new frame but m_pcurrent_frame is NULL - It's a good case for first Subframe\n");
m_pcurrent_frame = buffer;
} else if (find_extra_buffer_index(m_pcurrent_frame->pBuffer) != -1) { /*/
(m_pcurrent_frame->nFilledLen + buffer->nFilledLen <= m_pcurrent_frame->nAllocLen)) */
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
"Copy the new buffer to the current frame allocLen %d\n",
m_pcurrent_frame->nAllocLen);
memcpy(m_pcurrent_frame->pBuffer +
m_pcurrent_frame->nFilledLen,
buffer->pBuffer + buffer->nOffset,
buffer->nFilledLen);
m_pcurrent_frame->nFilledLen += buffer->nFilledLen;
m_pcurrent_frame->nTimeStamp = buffer->nTimeStamp;
if(buffer->nFlags & OMX_BUFFERFLAG_EOS ) {
m_pcurrent_frame->nFlags |= buffer->nFlags;
add_entry(nBufferIndex);
}
} else if (find_extra_buffer_index(buffer->pBuffer) != -1) {
QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
"Buffer %p must be an extra buffer size of current len %d extra len %d extra offset %d\n",
buffer->pBuffer,
m_pcurrent_frame->nFilledLen,
buffer->nFilledLen, buffer->nOffset);
memmove(buffer->pBuffer + m_pcurrent_frame->nFilledLen,
buffer->pBuffer + buffer->nOffset,
buffer->nFilledLen);
memcpy(buffer->pBuffer, m_pcurrent_frame->pBuffer,
m_pcurrent_frame->nFilledLen);
/* We need to swap pBuffer pointer so buffer done cb will free the unused pbuffer */
OMX_U8 *temp = m_pcurrent_frame->pBuffer;
m_pcurrent_frame->pBuffer = buffer->pBuffer;
buffer->pBuffer = temp;
m_pcurrent_frame->nFilledLen += buffer->nFilledLen;
} else
if ((m_pcurrent_frame->pBuffer +
m_pcurrent_frame->nFilledLen ==
buffer->pBuffer + buffer->nOffset)
&& (m_pcurrent_frame->nFilledLen + buffer->nFilledLen <=
m_pcurrent_frame->nAllocLen)) {
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
"No need memcpy, current length %d added by %d\n",
m_pcurrent_frame->nFilledLen,
buffer->nFilledLen);
m_pcurrent_frame->nFilledLen += buffer->nFilledLen;
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
"Buffer is not enough. Need to get extra buffer \n");
OMX_S8 index = get_free_extra_buffer_index();
if (index != -1) {
memcpy(m_extra_buf_info[index].extra_pBuffer,
m_pcurrent_frame->pBuffer,
m_pcurrent_frame->nFilledLen);
memcpy(m_extra_buf_info[index].extra_pBuffer +
m_pcurrent_frame->nFilledLen,
buffer->pBuffer + buffer->nOffset,
buffer->nFilledLen);
m_pcurrent_frame->pBuffer =
m_extra_buf_info[index].extra_pBuffer;
m_pcurrent_frame->nFilledLen +=
buffer->nFilledLen;
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"Couldn't find extra buffer\n");
return OMX_ErrorHardware;
}
}
buffer_done_cb_stub(&m_vdec_cfg, buffer);
} else // non arbitrary bytes previous frame
{
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"add_entry_subframe_stitching - SUBFRAME_TYPE_PREVIOUS_FRAME\n");
if (m_pcurrent_frame == NULL) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
"It's not a new frame but m_pcurrent_frame is NULL - It's a good case for first Subframe\n");
m_pcurrent_frame = buffer;
} else if (m_pcurrent_frame->nFilledLen + buffer->nFilledLen <=
m_pcurrent_frame->nAllocLen) {
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
"Concat the current Subframe into previous one, size of prev %d current %d\n",
m_pcurrent_frame->nFilledLen,
buffer->nFilledLen);
// Stitching the current buffer into previous one
memcpy(&m_pcurrent_frame->
pBuffer[m_pcurrent_frame->nFilledLen],
buffer->pBuffer, buffer->nFilledLen);
m_pcurrent_frame->nFilledLen += buffer->nFilledLen;
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"ERROR - Not enough memory - Stitching failed \n");
ret = OMX_ErrorFormatNotDetected;
}
buffer_done_cb_stub(&m_vdec_cfg, buffer);
}
return ret;
}
/* ======================================================================
FUNCTION
omx_vdec::PushPendingBuffers
DESCRIPTION
Internal method used to push the pending buffers.
PARAMETERS
None.
RETURN VALUE
true/false
========================================================================== */
unsigned omx_vdec::push_pending_buffers(void) {
post_event(0, 0, OMX_COMPONENT_PUSH_PENDING_BUFS);
return 0;
}
/* ======================================================================
FUNCTION
omx_vdec::PushPendingBufers
DESCRIPTION
This routine is used to push the pending buffers if decoder
has space.
PARAMETERS
None.
RETURN VALUE
Returns the push count. either 0, 1 or 2.
========================================================================== */
unsigned omx_vdec::push_pending_buffers_proxy(void) {
unsigned push_cnt = 0;
unsigned int ret = 0;
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"omx_vdec::push_pending_buffer_proxy\n");
while (is_pending()) {
// If both buffers are pending try to push the first one
int pend_idx = get_first_pending_index();
ret = push_one_input_buffer(input[pend_idx]);
if (ret == 0) {
// If we are not able to push then skip the next step
return push_cnt;
}
push_cnt += ret;
}
if (get_first_pending_index() >= (int)m_inp_buf_count) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"FATAL Error: pending index invalid\n");
}
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"push_pending_buffers pushed %d frames to the decoder\n",
push_cnt);
return push_cnt;
}
/* ======================================================================
FUNCTION
omx_vdec::PushOneInputBuffer
DESCRIPTION
This routine is used to push the encoded video frames to
the video decoder.
PARAMETERS
None.
RETURN VALUE
True if it is able to the push the buffer to the decoders.
========================================================================== */
unsigned omx_vdec::push_one_input_buffer(OMX_IN OMX_BUFFERHEADERTYPE * buffer) {
unsigned push_cnt = 0;
QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"push_one_input_buffer pBuffer %p, nOffset %d, nFilledLen %d\n",
buffer->pBuffer, buffer->nOffset, buffer->nFilledLen);
unsigned nPortIndex = buffer - ((OMX_BUFFERHEADERTYPE *) m_inp_mem_ptr);
if (nPortIndex < m_inp_buf_count) {
if (m_b_divX_parser)
{
if (m_prev_timestamp < buffer->nTimeStamp)
{
if ((m_timestamp_interval > (buffer->nTimeStamp - m_prev_timestamp)) ||
(m_timestamp_interval == 0))
{
m_timestamp_interval = buffer->nTimeStamp - m_prev_timestamp;
}
m_prev_timestamp = buffer->nTimeStamp;
}
if (m_divX_buffer_info.parsing_required)
{
m_divX_buffer_info.nFrames = m_mp4_utils->parse_frames_in_chunk(
buffer->pBuffer + buffer->nOffset,
buffer->nFilledLen,
m_timestamp_interval,
m_divX_buffer_info.frame_info);
m_divX_buffer_info.parsing_required = false;
}
if ((buffer->nFlags & OMX_BUFFERFLAG_EOS) && (m_divX_buffer_info.nFrames == 0))
{
// Zero length EOS
m_divX_buffer_info.nFrames = 1 ;
}
while (m_divX_buffer_info.last_decoded_index < m_divX_buffer_info.nFrames)
{
memset(&m_frame_info,0,sizeof(m_frame_info));
m_frame_info.data = buffer->pBuffer + buffer->nOffset +
m_divX_buffer_info.frame_info[m_divX_buffer_info.last_decoded_index].offset;
m_frame_info.len = m_divX_buffer_info.frame_info[m_divX_buffer_info.last_decoded_index].size;
m_frame_info.timestamp = buffer->nTimeStamp +
m_divX_buffer_info.frame_info[m_divX_buffer_info.last_decoded_index].timestamp_increment;
bool all_done = (m_divX_buffer_info.last_decoded_index == m_divX_buffer_info.nFrames - 1)?true:false;
remove_top_entry();
if ((buffer->nFlags & OMX_BUFFERFLAG_EOS) && all_done)
{
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,"empty_this_buffer: EOS received with TS %d\n",(int)buffer->nTimeStamp);
m_eos_timestamp = buffer->nTimeStamp;
m_frame_info.flags = FRAME_FLAG_EOS;
}
void *cookie = ((all_done)?buffer:NULL);
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,"Post input buffer %d ts %d", m_ebd_cnt, m_frame_info.timestamp);
int nRet = vdec_post_input_buffer(m_vdec, &(m_frame_info), cookie, m_use_pmem);
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,"vdec_post_input_buffer returned %d\n",nRet);
if(VDEC_EOUTOFBUFFERS == nRet)
{
push_back_entry(nPortIndex);
break;
}
else if (all_done)
{
++m_ebd_cnt;
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"\n ETB Count %u \n", m_ebd_cnt);
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"\n First pending buffer index is set to %d (%x)\n",
m_first_pending_buf_idx, m_flags[0] );
push_cnt++;
memset(&m_divX_buffer_info, 0, sizeof(m_divX_buffer_info));
m_divX_buffer_info.parsing_required = true;
break;
}
else
{
m_divX_buffer_info.last_decoded_index++;
}
}
}
else {
memset(&m_frame_info, 0, sizeof(m_frame_info));
if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"empty_this_buffer: EOS received with TS %d\n",
(int)buffer->nTimeStamp);
m_eos_timestamp = buffer->nTimeStamp;
m_frame_info.flags = FRAME_FLAG_EOS;
}
PrintFrameHdr(buffer);
m_frame_info.data = buffer->pBuffer + buffer->nOffset;
m_frame_info.len = buffer->nFilledLen;
m_frame_info.timestamp = buffer->nTimeStamp;
m_frame_info.flags = buffer->nFlags;
remove_top_entry();
int nRet =
vdec_post_input_buffer(m_vdec, &(m_frame_info), buffer,
m_use_pmem);
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"vdec_post_input_buffer returned %d\n", nRet);
if (VDEC_EOUTOFBUFFERS == nRet) {
push_back_entry(nPortIndex);
} else {
++m_ebd_cnt;
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"\n ETB Count %u \n", m_ebd_cnt);
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"\n First pending buffer index is set to %d (%x)\n",
m_first_pending_buf_idx, m_flags[0] );
push_cnt++;
}
}
}
return push_cnt;
}
/* ======================================================================
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_StateInvalid) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"FTB in Invalid State\n");
return OMX_ErrorInvalidState;
}
if (m_out_bEnabled == OMX_FALSE) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"FTB when port disabled \n");
return OMX_ErrorIncorrectStateOperation;
}
post_event((unsigned)hComp, (unsigned)buffer,
OMX_COMPONENT_GENERATE_FTB);
return OMX_ErrorNone;
}
/* ======================================================================
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_proxy(OMX_IN OMX_HANDLETYPE hComp,
OMX_IN OMX_BUFFERHEADERTYPE *
bufferAdd) {
OMX_BUFFERHEADERTYPE *buffer = bufferAdd;
// pOutMem points to the start of the array
unsigned nPortIndex = buffer - ((OMX_BUFFERHEADERTYPE *) m_out_mem_ptr);
if ((m_event_port_settings_sent == true) || !m_vdec
|| (m_out_bEnabled != OMX_TRUE)) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"OMX_VDEC::FTB --> Decoder Not initialised\n");
flush_before_vdec_op_q->Enqueue((void *)buffer);
BITMASK_SET((m_out_flags), nPortIndex);
return OMX_ErrorNone;
}
m_ftb_cnt++;
PrintFrameHdr(buffer);
unsigned push_cnt = 0;
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"FTB Outstanding frame cnt %d\n", m_outstanding_frames);
if(m_bInvalidState == true)
{
m_cb.FillBufferDone(&m_cmp, m_app_data, buffer);
return OMX_ErrorNone;
}
if (omx_vdec_get_use_buf_flg()) {
// Get the PMEM buf
OMX_BUFFERHEADERTYPE *tempHdr;
tempHdr = m_use_buf_hdrs.find(buffer);
if (tempHdr) {
QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"FTB::Found bufHdr[0x%x]0x%x-->0x%x\n",
buffer, buffer->pBuffer, tempHdr,
tempHdr->pBuffer);
// Map the pBuf add to pMEM address.
buffer = tempHdr;
} else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"FTB::No match found bufHdr[0x%x] \n",
buffer);
}
}
if (nPortIndex < m_out_buf_count) {
if (m_state == OMX_StateExecuting) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"FTB:: push_pending_buffer_proxy\n");
push_cnt = push_pending_buffers_proxy();
}
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"FTB Pushed %d input frames at the same time\n",
push_cnt);
if (BITMASK_PRESENT((m_out_flags), nPortIndex)) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"FTB[%d] Ignored \n", nPortIndex);
return OMX_ErrorNone;
}
if (true == m_bEoSNotifyPending) {
unsigned int i = 0;
OMX_BUFFERHEADERTYPE *pBufHdr =
&(((OMX_BUFFERHEADERTYPE *)
m_out_mem_ptr)[nPortIndex]);
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"FTB: EOS notify pending - Generate EOS using buffer[%d]\n",
nPortIndex);
pBufHdr->nFlags = OMX_BUFFERFLAG_EOS;
pBufHdr->nFilledLen = 0;
pBufHdr->nTimeStamp = m_eos_timestamp;
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"FBD Outstanding frame cnt %d\n",
m_outstanding_frames);
m_bEoSNotifyPending = false;
if (omx_vdec_get_use_buf_flg()) {
// get the pMEM corresponding to the pBUF
// copy the pMEM contents to pBUF
}
m_cb.FillBufferDone(&m_cmp, m_app_data, pBufHdr);
} else {
vdec_frame *frame =
(vdec_frame *) buffer->pOutputPortPrivate;
if (frame->flags) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"FTB Reset frame flags\n");
frame->flags = 0;
}
if (buffer->nFlags) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"FTB Reset buffer hdr flags\n");
buffer->nFlags = 0;
}
BITMASK_SET((m_out_flags), nPortIndex);
// Release frame should be called only while executing
// We stash the h64 frame inside the OutputPortPrivate field
--m_outstanding_frames;
vdec_release_frame(m_vdec,
(vdec_frame *) buffer->
pOutputPortPrivate);
}
} else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"FATAL ERROR:Invalid Port Index[%d]\n",
nPortIndex);
}
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) {
m_cb = *callbacks;
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) {
OMX_BUFFERHEADERTYPE *bufferHdr = NULL;
int i;
if (OMX_StateLoaded != m_state) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"WARNING:Rxd DeInit,OMX not in LOADED state %d\n",
m_state);
for(i =0; i <m_inp_buf_count; i++ ) {
if(m_bArbitraryBytes && m_arbitrary_bytes_input_mem_ptr) {
bufferHdr =
((OMX_BUFFERHEADERTYPE *)m_arbitrary_bytes_input_mem_ptr) + i;
}
else if (m_inp_mem_ptr) {
bufferHdr =
((OMX_BUFFERHEADERTYPE *)m_inp_mem_ptr) + i;
}
if(bufferHdr && bufferHdr->pBuffer && !omx_vdec_get_input_use_buf_flg()) {
Vdec_BufferInfo buf_info;
buf_info.base = bufferHdr->pBuffer;
if (m_use_pmem) {
buf_info.bufferSize =
m_vdec_cfg.inputBuffer[i].bufferSize;
buf_info.pmem_id =
m_vdec_cfg.inputBuffer[i].pmem_id;
buf_info.pmem_offset =
m_vdec_cfg.inputBuffer[i].pmem_offset;
}
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"free_buffer on i/p port - pBuffer %x \n",
bufferHdr->pBuffer);
vdec_free_input_buffer(&buf_info, m_use_pmem);
}
}
}
if (m_bArbitraryBytes) {
for (i = 0; i < OMX_CORE_NUM_INPUT_BUFFERS; i++) {
if (m_extra_buf_info[i].extra_pBuffer) {
if(omx_vdec_get_input_use_buf_flg()) {
free(m_extra_buf_info[i].extra_pBuffer);
}
else {
Vdec_BufferInfo buf_info;
buf_info.base =
m_extra_buf_info[i].extra_pBuffer;
if (m_use_pmem) {
buf_info.bufferSize =
m_vdec_cfg.
inputBuffer[m_inp_buf_count +
i].bufferSize;
buf_info.pmem_id =
m_vdec_cfg.
inputBuffer[m_inp_buf_count +
i].pmem_id;
buf_info.pmem_offset =
m_vdec_cfg.
inputBuffer[m_inp_buf_count +
i].pmem_offset;
}
//free(m_extra_buf_info[nPortIndex].extra_pBuffer);
vdec_free_input_buffer(&buf_info, m_use_pmem);
}
m_extra_buf_info[i].extra_pBuffer = NULL;
}
}
}
if (m_vdec) {
vdec_close(m_vdec);
m_vdec_cfg.vdec_fd = -1;
m_vdec = NULL;
}
if (m_vdec_cfg.vdec_fd >= 0) {
close(m_vdec_cfg.vdec_fd);
m_vdec_cfg.vdec_fd = -1;
}
if (m_inp_mem_ptr) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Freeing the Input Memory\n");
free(m_inp_mem_ptr);
m_inp_mem_ptr = NULL;
}
if (m_arbitrary_bytes_input_mem_ptr) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Freeing the Input Memory\n");
free(m_arbitrary_bytes_input_mem_ptr);
m_arbitrary_bytes_input_mem_ptr = NULL;
}
if (m_loc_use_buf_hdr) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Freeing the UseBuffer Header Memory\n");
}
if (m_use_buf_hdrs.size()) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"WARNING::Cleanup Not correct\n");
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"WARNING::Num of ele still in the container=%d\n",
m_use_buf_hdrs.size());
m_use_buf_hdrs.show();
m_use_buf_hdrs.eraseall();
}
if (m_h264_utils) {
delete m_h264_utils;
m_h264_utils = NULL;
}
if(m_mp4_utils)
{
delete m_mp4_utils;
m_mp4_utils = NULL;
}
QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
"Unread mesg FTB-Q[%d] CMD-Q[%d] ETB-Q[%d]\n",
m_ftb_q.m_size, m_cmd_q.m_size,
m_etb_arbitrarybytes_q.m_size);
// Reset counters in mesg queues
m_ftb_q.m_size = 0;
m_cmd_q.m_size = 0;
m_etb_arbitrarybytes_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_arbitrarybytes_q.m_read = m_etb_arbitrarybytes_q.m_write = 0;
if (m_vendor_config.pData) {
free(m_vendor_config.pData);
m_vendor_config.pData = NULL;
}
#ifdef _ANDROID_
// Clear the strong reference
m_heap_ptr.clear();
#endif // _ANDROID_
omx_vdec_free_output_port_memory();
return OMX_ErrorNone;
}
/* ======================================================================
FUNCTION
omx_vdec::use_egl_output_buffer
DESCRIPTION
OMX Use EGL Image method implementation <TBD>.
PARAMETERS
<TBD>.
RETURN VALUE
Not Implemented error.
========================================================================== */
OMX_ERRORTYPE omx_vdec::use_egl_output_buffer(OMX_IN OMX_HANDLETYPE hComp,
OMX_INOUT OMX_BUFFERHEADERTYPE **
bufferHdr, OMX_IN OMX_U32 port,
OMX_IN OMX_PTR appData,
OMX_IN void *eglImage)
{
OMX_ERRORTYPE eRet = OMX_ErrorNone;
OMX_BUFFERHEADERTYPE *bufHdr; // buffer header
unsigned i; // Temporary counter
#ifdef USE_EGL_IMAGE_GPU
PFNEGLQUERYIMAGEQUALCOMMPROC egl_queryfunc;
EGLint fd = -1, offset = 0;
#else
int fd = -1, offset = 0;
#endif
vdec_frame *output_buf;
#ifdef USE_EGL_IMAGE_GPU
if(m_display_id == NULL) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Display ID is not set by IL client and EGL image can't be used with out this \n");
return OMX_ErrorInsufficientResources;
}
egl_queryfunc = (PFNEGLQUERYIMAGEQUALCOMMPROC)
eglGetProcAddress("eglQueryImageKHR");
egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_HANDLE_QCOM,
&fd);
egl_queryfunc(m_display_id, eglImage, EGL_BUFFER_OFFSET_QCOM,
&offset);
#else //with OMX test app
struct temp_egl {
int pmem_fd;
int offset;
};
struct temp_egl *temp_egl_id;
temp_egl_id = (struct temp_egl *)eglImage;
fd = temp_egl_id->pmem_fd;
offset = temp_egl_id->offset;
#endif
if (fd < 0) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Improper pmem fd by EGL clinet %d \n",fd);
return OMX_ErrorInsufficientResources;
}
if (!m_out_mem_ptr) {
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;
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Ist Use Output Buffer(%d)\n", m_out_buf_count);
nBufHdrSize = m_out_buf_count * sizeof(OMX_BUFFERHEADERTYPE);
nPMEMInfoSize = m_out_buf_count *
sizeof(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO);
nPlatformListSize = m_out_buf_count *
sizeof(OMX_QCOM_PLATFORM_PRIVATE_LIST);
nPlatformEntrySize = m_out_buf_count *
sizeof(OMX_QCOM_PLATFORM_PRIVATE_ENTRY);
//m_out_bm_count = BITMASK_SIZE(m_out_buf_count);
QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"UOB::TotalBufHdr %d BufHdrSize %d PMEM %d PL %d\n",
nBufHdrSize, sizeof(OMX_BUFFERHEADERTYPE),
nPMEMInfoSize, nPlatformListSize);
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"UOB::PE %d bmSize %d \n", nPlatformEntrySize,
m_out_bm_count);
/*
* Memory for output side involves the following:
* 1. Array of Buffer Headers
* 2. Platform specific information List
* 3. Platform specific Entry List
* 4. PMem Information entries
* 5. Bitmask array to hold the buffer allocation details
* In order to minimize the memory management entire allocation
* is done in one step.
*/
/*m_out_mem_ptr = (char *)calloc(nBufHdrSize +
nPlatformListSize +
nPlatformEntrySize +
nPMEMInfoSize +m_out_bm_count, 1); */
// Alloc mem for out buffer headers
m_out_mem_ptr = (char *)calloc(nBufHdrSize, 1);
// Alloc mem for platform specific info
char *pPtr = NULL;
pPtr = (char *)calloc(nPlatformListSize + nPlatformEntrySize +
nPMEMInfoSize, 1);
m_vdec_cfg.outputBuffer =
(struct vdec_frame *)malloc(sizeof(struct vdec_frame) *
m_out_buf_count);
if (m_out_mem_ptr && pPtr && m_vdec_cfg.outputBuffer) {
bufHdr = (OMX_BUFFERHEADERTYPE *) 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;
//m_out_bm_ptr = (((char *) pPMEMInfo) + nPMEMInfoSize);
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"UOB::Memory Allocation Succeeded for OUT port%p\n",
m_out_mem_ptr);
// Settting the entire storage nicely
QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"UOB::bHdr %p OutMem %p PE %p pmem[%p]\n",
bufHdr, m_out_mem_ptr, pPlatformEntry,
pPMEMInfo);
for (i = 0; i < m_out_buf_count; i++) {
memset(bufHdr, 0, sizeof(OMX_BUFFERHEADERTYPE));
bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
// Set the values when we determine the right HxW param
bufHdr->nAllocLen = get_output_buffer_size();
bufHdr->nFilledLen = 0;
bufHdr->pAppPrivate = appData;
bufHdr->nOutputPortIndex =
OMX_CORE_OUTPUT_PORT_INDEX;
// Platform specific PMEM Information
// Initialize the Platform Entry
pPlatformEntry->type =
OMX_QCOM_PLATFORM_PRIVATE_PMEM;
pPlatformEntry->entry = pPMEMInfo;
// Initialize the Platform List
pPlatformList->nEntries = 1;
pPlatformList->entryList = pPlatformEntry;
// Assign the buffer space to the bufHdr
bufHdr->pBuffer = (OMX_U8*)eglImage;
// Keep this NULL till vdec_open is done
bufHdr->pOutputPortPrivate = NULL;
pPMEMInfo->offset = 0;
bufHdr->pPlatformPrivate = pPlatformList;
// Move the buffer and buffer header pointers
bufHdr++;
pPMEMInfo++;
pPlatformEntry++;
pPlatformList++;
}
*bufferHdr = (OMX_BUFFERHEADERTYPE *) m_out_mem_ptr;
output_buf = (vdec_frame *) &m_vdec_cfg.outputBuffer[0];
output_buf[0].buffer.pmem_id = fd;
output_buf[0].buffer.pmem_offset = offset;
output_buf[0].buffer.bufferSize = get_output_buffer_size();
output_buf[0].buffer.base = (OMX_U8*)eglImage;
output_buf[0].buffer.state = VDEC_BUFFER_WITH_APP_FLUSHED;
BITMASK_SET(m_out_bm_count, 0x0);
} else {
QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Output buf mem alloc failed[0x%x][0x%x][0x%x]\n",
m_out_mem_ptr, m_loc_use_buf_hdr, pPtr);
eRet = OMX_ErrorInsufficientResources;
return eRet;
}
} else {
for (i = 0; i < m_out_buf_count; i++) {
if (BITMASK_ABSENT(m_out_bm_count, i)) {
break;
}
}
if (i < m_out_buf_count) {
// found an empty buffer at i
*bufferHdr =
((OMX_BUFFERHEADERTYPE *) m_out_mem_ptr) + i;
(*bufferHdr)->pAppPrivate = appData;
(*bufferHdr)->pBuffer = (OMX_U8*)eglImage;
output_buf = (vdec_frame *) &m_vdec_cfg.outputBuffer[0] ;
output_buf[i].buffer.pmem_id = fd;
output_buf[i].buffer.pmem_offset = offset;
output_buf[i].buffer.bufferSize = get_output_buffer_size();
output_buf[i].buffer.base = (OMX_U8*)eglImage;
output_buf[i].buffer.state = VDEC_BUFFER_WITH_APP_FLUSHED;
BITMASK_SET(m_out_bm_count, i);
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"All Output Buf Allocated:\n");
eRet = OMX_ErrorInsufficientResources;
return eRet;
}
}
if (allocate_done()) {
omx_vdec_display_in_buf_hdrs();
omx_vdec_display_out_buf_hdrs();
//omx_vdec_dup_use_buf_hdrs();
//omx_vdec_display_out_use_buf_hdrs();
// If use buffer and pmem alloc buffers
// then dont make any local copies of use buf headers
omx_vdec_set_use_egl_buf_flg();
}
return eRet;
}
/* ======================================================================
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) {
OMX_ERRORTYPE eRet = OMX_ErrorNone;
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
"use_EGL_image: Begin \n");
if (m_state == OMX_StateInvalid) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Use Buffer in Invalid State\n");
return OMX_ErrorInvalidState;
}
if (port == OMX_CORE_OUTPUT_PORT_INDEX) {
eRet =
use_egl_output_buffer(hComp, bufferHdr, port, appData, eglImage);
} else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Error: Invalid Port Index received %d\n",
(int)port);
eRet = OMX_ErrorBadPortIndex;
}
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_OUTPUT_PORT_INDEX
&& m_out_bPopulated) {
if (BITMASK_PRESENT
(m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
if (m_event_port_settings_sent) {
if (VDEC_SUCCESS != vdec_commit_memory(m_vdec)) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"ERROR!!! vdec_commit_memory failed\n");
m_bInvalidState = true;
m_cb.EventHandler(&m_cmp, m_app_data,
OMX_EventError,
OMX_ErrorInsufficientResources, 0,
NULL);
eRet = OMX_ErrorInsufficientResources;
}
}
// Populate the Buffer Headers
omx_vdec_get_out_buf_hdrs();
BITMASK_CLEAR((m_flags),
OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
post_event(OMX_CommandPortEnable,
OMX_CORE_OUTPUT_PORT_INDEX,
OMX_COMPONENT_GENERATE_EVENT);
m_event_port_settings_sent = false;
}
}
}
return eRet;
}
/* ======================================================================
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) {
OMX_ERRORTYPE eRet = OMX_ErrorNone;
if (!strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.mpeg4",
OMX_MAX_STRINGNAME_SIZE)) {
if ((0 == index) && role) {
strncpy((char *)role, "video_decoder.mpeg4",
OMX_MAX_STRINGNAME_SIZE);
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"component_role_enum: role %s\n", role);
} else {
eRet = OMX_ErrorNoMore;
}
} else
if (!strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.h263",
OMX_MAX_STRINGNAME_SIZE)) {
if ((0 == index) && role) {
strncpy((char *)role, "video_decoder.h263",
OMX_MAX_STRINGNAME_SIZE);
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"component_role_enum: role %s\n", role);
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"\n No more roles \n");
eRet = OMX_ErrorNoMore;
}
} else
if (!strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.divx",
OMX_MAX_STRINGNAME_SIZE)) {
if ((0 == index) && role) {
strncpy((char *)role, "video_decoder.divx",
OMX_MAX_STRINGNAME_SIZE);
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"component_role_enum: role %s\n", role);
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"\n No more roles \n");
eRet = OMX_ErrorNoMore;
}
} else
if (!strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc",
OMX_MAX_STRINGNAME_SIZE)) {
if ((0 == index) && role) {
strncpy((char *)role, "video_decoder.avc",
OMX_MAX_STRINGNAME_SIZE);
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"component_role_enum: role %s\n", role);
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"\n No more roles \n");
eRet = OMX_ErrorNoMore;
}
} else
if (!strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.vc1",
OMX_MAX_STRINGNAME_SIZE)) {
if ((0 == index) && role) {
strncpy((char *)role, "video_decoder.vc1",
OMX_MAX_STRINGNAME_SIZE);
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"component_role_enum: role %s\n", role);
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"\n No more roles \n");
eRet = OMX_ErrorNoMore;
}
} else
if (!strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.vp",
OMX_MAX_STRINGNAME_SIZE)) {
if ((0 == index) && role) {
strncpy((char *)role, "video_decoder.vp",
OMX_MAX_STRINGNAME_SIZE);
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"component_role_enum: role %s\n", role);
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"\n No more roles \n");
eRet = OMX_ErrorNoMore;
}
} else
if (!strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.spark",
OMX_MAX_STRINGNAME_SIZE)) {
if ((0 == index) && role) {
strncpy((char *)role, "video_decoder.spark",
OMX_MAX_STRINGNAME_SIZE);
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"component_role_enum: role %s\n", role);
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"\n No more roles \n");
eRet = OMX_ErrorNoMore;
}
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"\n Querying Role on Unknown Component\n");
eRet = OMX_ErrorInvalidComponentName;
}
return eRet;
}
/* ======================================================================
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 < m_inp_buf_count; i++) {
if (BITMASK_ABSENT(m_inp_bm_count, i)) {
break;
}
}
}
if (i == m_inp_buf_count) {
bRet = true;
}
if (i == m_inp_buf_count && 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 < m_out_buf_count; j++) {
if (BITMASK_ABSENT(m_out_bm_count, j)) {
break;
}
}
}
if (j == m_out_buf_count) {
bRet = true;
}
if (j == m_out_buf_count && m_out_bEnabled) {
m_out_bPopulated = OMX_TRUE;
}
return bRet;
}
/* ======================================================================
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::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::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;
if (m_inp_mem_ptr) {
for (; j < m_inp_buf_count; j++) {
if (BITMASK_PRESENT(m_inp_bm_count, j)) {
break;
}
}
if (j == m_inp_buf_count) {
bRet = true;
}
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Error: Invalid Inp/OutMem pointers \n");
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;
if (m_out_mem_ptr) {
for (; j < m_out_buf_count; j++) {
if (BITMASK_PRESENT(m_out_bm_count, j)) {
break;
}
}
if (j == m_out_buf_count) {
bRet = true;
}
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Error: Invalid Inp/OutMem pointers \n");
bRet = true;
}
return bRet;
}
/* ======================================================================
FUNCTION
omx_vdec::omx_vdec_get_out_buf_hdrs
DESCRIPTION
Get the PMEM area from video decoder
PARAMETERS
None.
RETURN VALUE
None
========================================================================== */
void omx_vdec::omx_vdec_get_out_buf_hdrs() {
OMX_BUFFERHEADERTYPE *bufHdr;
OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pPMEMInfo = m_pmem_info;
bufHdr = (OMX_BUFFERHEADERTYPE *) m_out_mem_ptr;
vdec_frame *base_frame = (vdec_frame *) & m_vdec_cfg.outputBuffer[0];
m_out_buf_count = m_vdec_cfg.numOutputBuffers;
if (base_frame) {
for (unsigned int i = 0; i < m_out_buf_count; i++) {
bufHdr->nAllocLen = m_vdec_cfg.nOutBufAllocLen; //get_output_buffer_size();
//bufHdr->nFilledLen= get_output_buffer_size();
bufHdr->nFilledLen = 0;
bufHdr->pBuffer =
(OMX_U8 *) (base_frame[i].buffer.base);
bufHdr->pOutputPortPrivate = (void *)&base_frame[i];
pPMEMInfo->offset = base_frame[i].buffer.pmem_offset;
pPMEMInfo->pmem_fd = base_frame[i].buffer.pmem_id;
QTV_MSG_PRIO5(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED, "Output Buffer param: Index [%d]: \
fd 0x%x output 0x%x base 0x%x off 0x%x\n", i,
(unsigned)pPMEMInfo->pmem_fd, &base_frame[i], (unsigned)base_frame[i].buffer.base, (unsigned)pPMEMInfo->offset);
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Output [%d]: buf %x \n", i,
(unsigned)bufHdr->pBuffer);
bufHdr++;
pPMEMInfo++;
}
}
return;
}
/* ======================================================================
FUNCTION
omx_vdec::omx_vdec_get_out_use_buf_hdrs
DESCRIPTION
Maintain a local copy of the output use buffers
PARAMETERS
None.
RETURN VALUE
None
========================================================================== */
void omx_vdec::omx_vdec_get_out_use_buf_hdrs() {
OMX_BUFFERHEADERTYPE *bufHdr;
int nBufHdrSize = 0;
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED, "GET OUTPUT USE BUF\n");
bufHdr = (OMX_BUFFERHEADERTYPE *) m_loc_use_buf_hdr;
vdec_frame *base_frame = (vdec_frame *) & m_vdec_cfg.outputBuffer[0];
nBufHdrSize = m_out_buf_count * sizeof(OMX_BUFFERHEADERTYPE);
if (base_frame) {
for (unsigned int i = 0; i < m_out_buf_count; i++) {
bufHdr->nAllocLen = get_output_buffer_size();
//bufHdr->nFilledLen= get_output_buffer_size();
bufHdr->nFilledLen = 0;
bufHdr->pBuffer =
(OMX_U8 *) (base_frame[i].buffer.base);
bufHdr->pOutputPortPrivate = (void *)&base_frame[i];
// just the offset instead of physical address
QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"OutputBuffer[%d]: buf[0x%x]: pmem[0x%x] \n",
i, (unsigned)bufHdr->pBuffer,
(OMX_U8 *) (base_frame[i].buffer.base));
bufHdr++;
}
}
}
/* ======================================================================
FUNCTION
omx_vdec::omx_vdec_check_port_settings
DESCRIPTION
Parser to check the HxW param
PARAMETERS
None.
RETURN VALUE
None
========================================================================== */
OMX_ERRORTYPE omx_vdec::omx_vdec_check_port_settings(OMX_BUFFERHEADERTYPE *
buffer, unsigned &height,
unsigned &width,
bool & bInterlace,
unsigned &cropx,
unsigned &cropy,
unsigned &cropdx,
unsigned &cropdy) {
OMX_ERRORTYPE ret = OMX_ErrorNone;
OMX_U8 *buf;
OMX_U32 buf_len;
OMX_U32 mult_fact = 16;
if (m_vendor_config.pData) {
buf = m_vendor_config.pData;
buf_len = m_vendor_config.nDataSize;
} else {
buf = buffer->pBuffer;
buf_len = buffer->nFilledLen;
}
if (!strcmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc")) {
if (false ==
m_h264_utils->parseHeader(buf, buf_len, m_nalu_bytes,
height, width, bInterlace, cropx,
cropy, cropdx, cropdy)) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Parsing Error unsupported profile or level\n");
return OMX_ErrorStreamCorrupt;
}
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Parsing Done height[%d] width[%d]\n", height,
width);
} else if ((!strcmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.mpeg4"))
|| (!strcmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.h263"))
|| (!strcmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.divx") &&
m_codec_format != QOMX_VIDEO_DIVXFormat311) ) {
mp4StreamType dataStream;
dataStream.data = (unsigned char *)buf;
dataStream.numBytes = (unsigned long int)buf_len;
if (false == m_mp4_utils->parseHeader(&dataStream)) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"VOL header parsing failure, aborting playback\n");
return OMX_ErrorStreamCorrupt;
}
cropx = cropy = 0;
cropdy = height = m_mp4_utils->SrcHeight();
cropdx = width = m_mp4_utils->SrcWidth();
bInterlace = false;
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"MPEG4/H263 ht[%d] wdth[%d]\n", height, width);
} else if (!strcmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.spark")) {
mp4StreamType dataStream;
dataStream.data = (unsigned char *)buf;
dataStream.numBytes = (unsigned long int)buf_len;
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Parsing Spark bit stream\n");
if (false == m_mp4_utils->parseSparkHeader(&dataStream)) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Parsing Error unsupported profile or level\n");
return OMX_ErrorStreamCorrupt;
}
cropx = cropy = 0;
cropdy = height = m_mp4_utils->SrcHeight();
cropdx = width = m_mp4_utils->SrcWidth();
bInterlace = false;
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"SPARK ht[%d] wdth[%d]\n", height, width);
} else if (!strcmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.divx") &&
m_codec_format == QOMX_VIDEO_DIVXFormat311) {
bInterlace = false;
cropx = cropy = 0;
cropdy = height = m_crop_dy;
cropdx = width = m_crop_dx;
} else if (!strcmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.vp")) {
// TODO FOR VP6
OMX_U8 *pBuf;
if (buf_len <= 8)
return OMX_ErrorStreamCorrupt;
pBuf = buf;
/* Skip the first 4 bytes to start reading the Height and Width*/
pBuf += 4;
cropx = cropy = 0;
cropdy = height = ( ((OMX_U32) (*pBuf++)) * 16);
cropdx = width = ( ((OMX_U32) (*pBuf)) * 16);
bInterlace = false;
} else if (!strcmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.vc1")) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW, "omx_vdec_check_port_settings - start code in seq header %x\n", ((*((OMX_U32 *) buf)))); // & VC1_SP_MP_START_CODE_MASK));
if ((((*((OMX_U32 *) buf)) & VC1_SP_MP_START_CODE_MASK) ==
VC1_SP_MP_START_CODE)
|| (((*((OMX_U32 *) buf)) & VC1_SP_MP_START_CODE_MASK) ==
VC1_SP_MP_START_CODE_RCV_V1)
) {
OMX_U32 *pBuf32, num_frames = 0;
OMX_U8 *pBuf8;
pBuf32 = (OMX_U32 *) buf;
/* get the number of frames from the sequence header */
num_frames = *pBuf32 & 0x00FFFFFF;
/* size of struct C appears right after the number of frames information in the sequence header */
m_vdec_cfg.sequenceHeaderLen = *(++pBuf32);
/* advance the pointer by the size of struct C in order to get the height and width */
pBuf8 = (OMX_U8 *) (++pBuf32);
pBuf8 += m_vdec_cfg.sequenceHeaderLen;
/* read the height and width information which are each 4 bytes */
pBuf32 = (OMX_U32 *) pBuf8;
height = *pBuf32;
width = *(++pBuf32);
bInterlace = false;
m_bAccumulate_subframe = false;
QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"omx_vdec_check_port_settings - VC1 Simple/Main profile, %d x %d %x x %x\n",
width, height, width, height);
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"omx_vdec_check_port_settings - VC1 sequence header length %d\n",
m_vdec_cfg.sequenceHeaderLen);
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"omx_vdec_check_port_settings - num_frames %d\n",
num_frames);
} else if (*((OMX_U32 *) buf) == 0x0F010000) {
OMX_U16 temp_dimension =
((OMX_U16) (buf[6]) << 4) | ((OMX_U16) (buf[7]) >>
4);
width = 2 * (temp_dimension + 1);
temp_dimension =
((OMX_U16) (buf[7] & 0x0F) << 8) |
(OMX_U16) (buf[8]);
height = 2 * (temp_dimension + 1);
bInterlace = ((buf[9] & 0x40) ? true : false);
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
"omx_vdec_check_port_settings - VC1 Advance profile Width:%d x Height:%d\n",
width, height);
} else if(m_vendor_config.nDataSize == VC1_STRUCT_C_LEN) {
QTV_MSG_PRIO2(QTVDIAG_GENERAL,QTVDIAG_PRIO_LOW,
"QC_DEBUG :: omx_vdec_check_port_settings - VC1 height and width, %d x %d\n",
width, height);
height = m_height;
width = m_width;
}
else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"omx_vdec_check_port_settings - ERROR: Unknown VC1 profile. Couldn't find height and width\n");
return OMX_ErrorStreamCorrupt;
}
cropdy = height;
cropdx = width;
cropx = cropy = 0;
}
if( m_color_format == QOMX_COLOR_FormatYVU420PackedSemiPlanar32m4ka)
mult_fact = 32;
if ((height % mult_fact) != 0) {
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"\n Height %d is not a multiple of %d",
height, mult_fact);
height = (height / mult_fact + 1) * mult_fact;
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"\n Height adjusted to %d \n", height);
}
if ((width % mult_fact) != 0) {
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"\n Width %d is not a multiple of %d",
width, mult_fact);
width = (width / mult_fact + 1) * mult_fact;
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"\n Width adjusted to %d \n", width);
}
return OMX_ErrorNone;
}
/* ======================================================================
FUNCTION
omx_vdec::omx_vdec_validate_port_param
DESCRIPTION
Get the PMEM area from video decoder
PARAMETERS
None.
RETURN VALUE
None
========================================================================== */
OMX_ERRORTYPE omx_vdec::omx_vdec_validate_port_param(int height, int width) {
OMX_ERRORTYPE ret = OMX_ErrorNone;
long hxw = height * width;
if (hxw > (OMX_CORE_720P_HEIGHT * OMX_CORE_720P_WIDTH)) {
ret = OMX_ErrorNotImplemented;
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Invalid Ht[%d] wdth[%d]\n", height, width);
}
return ret;
}
/* ======================================================================
FUNCTION
omx_vdec::omx_vdec_add_entries
DESCRIPTION
Add the buf header entries to the container
PARAMETERS
None.
RETURN VALUE
None
========================================================================== */
void omx_vdec::omx_vdec_add_entries() {
OMX_BUFFERHEADERTYPE *pOmxHdr = (OMX_BUFFERHEADERTYPE *) m_out_mem_ptr;
OMX_BUFFERHEADERTYPE *pOmxOutHdr = m_loc_use_buf_hdr;
for (unsigned int i = 0; i < 8; i++, pOmxHdr++, pOmxOutHdr++) {
m_use_buf_hdrs.insert(pOmxOutHdr, pOmxHdr);
m_use_buf_hdrs.insert(pOmxHdr, pOmxOutHdr);
}
}
/* ======================================================================
FUNCTION
omx_vdec::omx_vdec_dup_use_buf_hdrs
DESCRIPTION
Populate the copy buffer [ use buffer ]
PARAMETERS
None.
RETURN VALUE
None
========================================================================== */
OMX_ERRORTYPE omx_vdec::omx_vdec_dup_use_buf_hdrs() {
OMX_ERRORTYPE eRet = OMX_ErrorNone;
OMX_BUFFERHEADERTYPE *bufHdr; // buffer header
OMX_BUFFERHEADERTYPE *pHdr = (OMX_BUFFERHEADERTYPE *) m_out_mem_ptr;
int nBufHdrSize = 0;
nBufHdrSize = m_out_buf_count * sizeof(OMX_BUFFERHEADERTYPE);
memcpy(m_loc_use_buf_hdr, pHdr, nBufHdrSize);
omx_vdec_display_out_use_buf_hdrs();
return OMX_ErrorNone;
}
void omx_vdec::omx_vdec_cpy_user_buf(OMX_BUFFERHEADERTYPE * pBufHdr) {
OMX_BUFFERHEADERTYPE *bufHdr;
bufHdr = m_use_buf_hdrs.find(pBufHdr);
if (bufHdr) {
QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"CPY::Found bufHdr[0x%x]0x%x-->[0x%x]0x%x\n",
pBufHdr->pBuffer, pBufHdr, bufHdr,
bufHdr->pBuffer);
// Map the local buff address to the user space address.
// Basically pMEM -->pBuf translation
// DO A MEMCPY from pMEM are to the user defined add
QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"CPY::[bufferHdr]pBuffer maps[0x%x]0x%x-->[0x%x]0x%x\n",
pBufHdr->pBuffer, pBufHdr, bufHdr,
bufHdr->pBuffer);
// first buffer points to user defined add, sec one to PMEM area
memcpy(pBufHdr->pBuffer, bufHdr->pBuffer,
get_output_buffer_size());
} else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"CPY::No match found bufHdr[0x%x] \n", pBufHdr);
omx_vdec_display_out_use_buf_hdrs();
}
}
void omx_vdec::omx_vdec_display_in_buf_hdrs() {
OMX_BUFFERHEADERTYPE *omxhdr = ((OMX_BUFFERHEADERTYPE *) m_inp_mem_ptr);
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"^^^^^INPUT BUF HDRS^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
for (unsigned int i = 0; i < 2; i++) {
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"hdr[0x%x] buffer[0x%x]\n", omxhdr + i,
(omxhdr + i)->pBuffer);
}
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"^^^^^^^INPUT BUF HDRS^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
}
void omx_vdec::omx_vdec_display_out_buf_hdrs() {
OMX_BUFFERHEADERTYPE *omxhdr = ((OMX_BUFFERHEADERTYPE *) m_out_mem_ptr);
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"^^^^^^^^OUTPUT BUF HDRS^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
for (unsigned int i = 0; i < 8; i++) {
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"hdr[0x%x] buffer[0x%x]\n", omxhdr + i,
(omxhdr + i)->pBuffer);
}
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"^^^^^^^^^OUTPUT BUF HDRS^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
}
void omx_vdec::omx_vdec_display_out_use_buf_hdrs() {
OMX_BUFFERHEADERTYPE *omxhdr = m_loc_use_buf_hdr;
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"^^^^^^^^^USE OUTPUT BUF HDRS^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
for (unsigned int i = 0; i < 8; i++) {
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"hdr[0x%x] buffer[0x%x]\n", omxhdr + i,
(omxhdr + i)->pBuffer);
}
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"^^^^^^^^^^^USE OUTPUT BUF HDRS^^^^^^^^^^^^^^^^^^^^^^^^^\n");
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"^^^^^^^^^^USE BUF HDRS MAPPING^^^^^^^^^^^^^^^^^^^^^^^^^\n");
m_use_buf_hdrs.show();
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
}
/* ======================================================================
FUNCTION
omx_vdec::omx_vdec_create_native_decoder
DESCRIPTION
Native decoder creation
PARAMETERS
None.
RETURN VALUE
OMX_ErrorNone if successful
========================================================================== */
OMX_ERRORTYPE omx_vdec::
omx_vdec_create_native_decoder(OMX_IN OMX_BUFFERHEADERTYPE * buffer) {
OMX_ERRORTYPE eRet = OMX_ErrorNone;
OMX_U32 codec_type;
// if NALU is zero assume START CODE
m_vdec_cfg.height = m_port_height;
m_vdec_cfg.width = m_port_width;
m_vdec_cfg.size_of_nal_length_field = m_nalu_bytes;
m_vdec_cfg.vc1Rowbase = 0;
m_vdec_cfg.postProc = 0;
m_vdec_cfg.color_format = m_color_format;
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED, "m_vdec_cfg.kind %s\n",
m_vdec_cfg.kind);
if (!m_vendor_config.pData) {
if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.mpeg4", 28)
== 0 ) {
m_vdec_cfg.sequenceHeader =
(byte *) malloc(buffer->nFilledLen);
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Mpeg4 clip \n");
m_vdec_cfg.sequenceHeaderLen = buffer->nFilledLen;
memcpy(m_vdec_cfg.sequenceHeader, buffer->pBuffer,
m_vdec_cfg.sequenceHeaderLen);
} else if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.divx", 27)
== 0 ) {
if(m_codec_format == QOMX_VIDEO_DIVXFormat311) {
m_vdec_cfg.sequenceHeader = NULL;
m_vdec_cfg.sequenceHeaderLen = 0;
m_vdec_cfg.fourcc = MAKEFOURCC('D', 'I', 'V', '3');
}else {
m_vdec_cfg.sequenceHeader =
(byte *) malloc(buffer->nFilledLen);
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Divx clip \n");
m_vdec_cfg.sequenceHeaderLen = buffer->nFilledLen;
memcpy(m_vdec_cfg.sequenceHeader, buffer->pBuffer,
m_vdec_cfg.sequenceHeaderLen);
m_vdec_cfg.fourcc = MAKEFOURCC('D', 'I', 'V', 'X');
}
}else
if (strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc",
26) == 0) {
m_vdec_cfg.sequenceHeader =
(byte *) malloc(buffer->nFilledLen);
m_vdec_cfg.sequenceHeaderLen =
m_h264_utils->parse_first_h264_input_buffer(buffer,
m_vdec_cfg.
size_of_nal_length_field);
memcpy(m_vdec_cfg.sequenceHeader, buffer->pBuffer,
m_vdec_cfg.sequenceHeaderLen);
buffer->nFilledLen -= m_vdec_cfg.sequenceHeaderLen;
memmove(buffer->pBuffer,
&buffer->pBuffer[m_vdec_cfg.sequenceHeaderLen],
buffer->nFilledLen);
} else
if (strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.spark",
28) == 0) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"SPARK clip \n");
m_vdec_cfg.sequenceHeaderLen = 0;
m_vdec_cfg.sequenceHeader = NULL;
} else
if (strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.h263",
27) == 0) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"H263 clip \n");
m_vdec_cfg.sequenceHeaderLen = 0;
m_vdec_cfg.sequenceHeader = NULL;
} else
if (strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.vp",
25) == 0) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"VP6 clip \n");
m_vdec_cfg.sequenceHeaderLen = 0;
m_vdec_cfg.sequenceHeader = NULL;
} else
if (strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.vc1",
26) == 0) {
m_vdec_cfg.sequenceHeader =
(byte *) malloc(buffer->nFilledLen);
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"VC1 clip \n");
if ((((*((OMX_U32 *) buffer->pBuffer)) &
VC1_SP_MP_START_CODE_MASK) ==
VC1_SP_MP_START_CODE)
||
(((*((OMX_U32 *) buffer->pBuffer)) &
VC1_SP_MP_START_CODE_MASK) ==
VC1_SP_MP_START_CODE_RCV_V1)
)
{
OMX_U32 pos_sequence_header =
0, sequence_layer_len = 0;
OMX_U32 *pBuf32, num_frames;
OMX_U8 *pBuf8;
pBuf32 = (OMX_U32 *) buffer->pBuffer;
/* get the number of frames from the sequence header */
num_frames = *pBuf32 & 0x00FFFFFF;
/* size of struct C appears right after the number of frames information in the sequence header */
m_vdec_cfg.sequenceHeaderLen = *(++pBuf32);
/* advance the pointer by the size of struct C in order to get the height and width */
pBuf8 = (OMX_U8 *) (++pBuf32);
pBuf8 += m_vdec_cfg.sequenceHeaderLen;
/* read the height and width information which are each 4 bytes */
pBuf32 = (OMX_U32 *) pBuf8;
m_vdec_cfg.height = *pBuf32;
m_vdec_cfg.width = *(++pBuf32);
/* get the position of struct C or sequence header */
pos_sequence_header = OMX_VC1_POS_STRUCT_C;
if (((*((OMX_U32 *) buffer->pBuffer)) &
VC1_SP_MP_START_CODE_MASK) ==
VC1_SP_MP_START_CODE) {
sequence_layer_len =
OMX_VC1_SEQ_LAYER_SIZE_WITHOUT_STRUCTC
+ m_vdec_cfg.sequenceHeaderLen;
} else
if (((*((OMX_U32 *) buffer->pBuffer)) &
VC1_SP_MP_START_CODE_MASK) ==
VC1_SP_MP_START_CODE_RCV_V1) {
sequence_layer_len =
OMX_VC1_SEQ_LAYER_SIZE_V1_WITHOUT_STRUCTC
+ m_vdec_cfg.sequenceHeaderLen;
}
/* copy the sequence header information to be sent to vdec core */
memcpy(m_vdec_cfg.sequenceHeader,
&buffer->pBuffer[pos_sequence_header],
m_vdec_cfg.sequenceHeaderLen);
for (int i = 0;
i < m_vdec_cfg.sequenceHeaderLen; i++) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"seq header: %x",
m_vdec_cfg.
sequenceHeader[i]);
}
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"\n");
/* update the nFilledLen based on the number of bytes of the sequence layer */
buffer->nFilledLen -= sequence_layer_len;
memmove(buffer->pBuffer,
&buffer->pBuffer[sequence_layer_len],
buffer->nFilledLen);
}
else if (*((OMX_U32 *) buffer->pBuffer) == 0x0F010000) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
"VC1 Advance profile\n");
// Skip the start code. With the start code (first byte is 0x00),
// then Q6 will think it is a simple profile
m_vdec_cfg.sequenceHeaderLen =
buffer->nFilledLen - 4;
memcpy(m_vdec_cfg.sequenceHeader,
buffer->pBuffer + 4,
m_vdec_cfg.sequenceHeaderLen);
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"Error: Unknown VC1 profile\n");
}
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"ERROR: Not supported codec. But let's try it anyway\n");
m_vdec_cfg.sequenceHeaderLen = buffer->nFilledLen;
memcpy(m_vdec_cfg.sequenceHeader, buffer->pBuffer,
m_vdec_cfg.sequenceHeaderLen);
}
} else {
m_vdec_cfg.sequenceHeader =
(byte *) malloc(m_vendor_config.nDataSize);
if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.mpeg4", 28)
== 0) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Mpeg4 clip \n");
memcpy(m_vdec_cfg.sequenceHeader, m_vendor_config.pData,
m_vendor_config.nDataSize);
m_vdec_cfg.sequenceHeaderLen =
m_vendor_config.nDataSize;
#if 1 // temporary until q6 can decode without VOL header
memmove(buffer->pBuffer + buffer->nOffset +
m_vendor_config.nDataSize,
buffer->pBuffer + buffer->nOffset,
buffer->nFilledLen);
memcpy(buffer->pBuffer + buffer->nOffset,
m_vendor_config.pData,
m_vendor_config.nDataSize);
buffer->nFilledLen += m_vendor_config.nDataSize;
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"size %d\n", buffer->nFilledLen);
#endif
} else
if ((strncmp
(m_vdec_cfg.kind, "OMX.qcom.video.decoder.vc1",
26) == 0)
&&
((((*((OMX_U32 *) m_vendor_config.pData)) &
VC1_SP_MP_START_CODE_MASK) == VC1_SP_MP_START_CODE)
||
(((*((OMX_U32 *) m_vendor_config.pData)) &
VC1_SP_MP_START_CODE_MASK) ==
VC1_SP_MP_START_CODE_RCV_V1)
)) {
OMX_U32 pos_sequence_header = 0, sequence_layer_len = 0;
OMX_U32 *pBuf32, num_frames = 0;
OMX_U8 *pBuf8;
pBuf32 = (OMX_U32 *) m_vendor_config.pData;
/* get the number of frames from the sequence header */
num_frames = *pBuf32 & 0x00FFFFFF;
/* size of struct C appears right after the number of frames information in the sequence header */
m_vdec_cfg.sequenceHeaderLen = *(++pBuf32);
/* advance the pointer by the size of struct C in order to get the height and width */
pBuf8 = (OMX_U8 *) (++pBuf32);
pBuf8 += m_vdec_cfg.sequenceHeaderLen;
/* read the height and width information which are each 4 bytes */
pBuf32 = (OMX_U32 *) pBuf8;
m_vdec_cfg.height = *pBuf32;
m_vdec_cfg.width = *(++pBuf32);
/* the struct C / sequence header starts at position 8 in the sequence header */
pos_sequence_header = OMX_VC1_POS_STRUCT_C;
if (((*((OMX_U32 *) m_current_frame->pBuffer)) &
VC1_SP_MP_START_CODE_MASK) ==
VC1_SP_MP_START_CODE) {
m_vendor_config.nDataSize =
OMX_VC1_SEQ_LAYER_SIZE_WITHOUT_STRUCTC +
m_vdec_cfg.sequenceHeaderLen;
} else
if (((*((OMX_U32 *) m_current_frame->pBuffer)) &
VC1_SP_MP_START_CODE_MASK) ==
VC1_SP_MP_START_CODE_RCV_V1) {
m_vendor_config.nDataSize =
OMX_VC1_SEQ_LAYER_SIZE_V1_WITHOUT_STRUCTC +
m_vdec_cfg.sequenceHeaderLen;
}
/* copy the sequence header information to be sent to vdec core */
memcpy(m_vdec_cfg.sequenceHeader,
&m_vendor_config.pData[pos_sequence_header],
m_vdec_cfg.sequenceHeaderLen);
} else {
memcpy(m_vdec_cfg.sequenceHeader, m_vendor_config.pData,
m_vendor_config.nDataSize);
m_vdec_cfg.sequenceHeaderLen =
m_vendor_config.nDataSize;
}
}
#if 1
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"OMX - header, length %d\n",
m_vdec_cfg.sequenceHeaderLen);
for (OMX_U32 i = 0; i < m_vdec_cfg.sequenceHeaderLen; i++) {
printf("0x%.2x ", m_vdec_cfg.sequenceHeader[i]);
if (i % 16 == 15) {
printf("\n");
}
}
printf("\n");
#endif
m_vdec = vdec_open(&m_vdec_cfg);
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED, "vdec_open[%p]\n",
m_vdec);
if (!m_vdec) {
m_bInvalidState = true;
m_cb.EventHandler(&m_cmp, m_app_data, OMX_EventError,
OMX_ErrorInsufficientResources, 0, NULL);
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"ERROR!!! vdec_open failed\n");
if (m_vdec_cfg.sequenceHeader) {
free(m_vdec_cfg.sequenceHeader);
}
return OMX_ErrorHardware;
}
if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc", 26) == 0) {
if (m_h264_utils != NULL) {
m_h264_utils->allocate_rbsp_buffer(OMX_CORE_INPUT_BUFFER_SIZE);
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"ERROR!!! m_h264_utils exist\n");
}
}
if (m_vdec_cfg.sequenceHeader) {
free(m_vdec_cfg.sequenceHeader);
}
return eRet;
}
/* ======================================================================
FUNCTION
omx_vdec::omx_vdec_free_output_port_memory
DESCRIPTION
Free output port memory
PARAMETERS
None.
RETURN VALUE
None
========================================================================== */
void omx_vdec::omx_vdec_free_output_port_memory(void) {
if (m_out_mem_ptr) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Freeing the Output Memory\n");
free(m_out_mem_ptr);
m_out_mem_ptr = NULL;
}
if (m_platform_list) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Freeing the platform list\n");
free(m_platform_list);
m_platform_list = NULL;
}
if (m_platform_entry) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Freeing the platform entry\n");
m_platform_entry = NULL;
}
if (m_pmem_info) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Freeing the pmem info\n");
m_pmem_info = NULL;
}
if(omx_vdec_get_use_egl_buf_flg() && m_vdec_cfg.outputBuffer) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Freeing the output buf info egl \n");
if (m_vdec_cfg.outputBuffer) {
free(m_vdec_cfg.outputBuffer);
m_vdec_cfg.outputBuffer = NULL;
}
}
}
/* ======================================================================
FUNCTION
omx_vdec::get_free_input_buffer
DESCRIPTION
get a free input buffer
PARAMETERS
None
RETURN VALUE
pointer to input buffer header
NULL if couldn't find
========================================================================== */
OMX_BUFFERHEADERTYPE *omx_vdec::get_free_input_buffer() {
int i;
for (i = 0; i < m_inp_buf_count; i++) {
if (m_input_buff_info[i].bfree_input) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
"get_free_input_buffer_index - Find free input buffer %d\n",
i);
m_input_buff_info[i].bfree_input = false;
return input[i];
}
}
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
"get_free_input_buffer_index - Couldn't find free extra buffer\n");
return NULL;
}
/* ======================================================================
FUNCTION
omx_vdec::find_input_buffer_index
DESCRIPTION
find input buffer index
PARAMETERS
OMX_U8* buffer
RETURN VALUE
index of extra buffer
-1 if couldn't find
========================================================================== */
OMX_S8 omx_vdec::find_input_buffer_index(OMX_BUFFERHEADERTYPE * pBuffer) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
"find_input_buffer_index %p\n", pBuffer);
OMX_S8 i;
for (i = 0; i < m_inp_buf_count; i++) {
if (pBuffer == input[i]) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
"find_input_buffer_index %d\n", i);
return i;
}
}
return -1;
}
/* ======================================================================
FUNCTION
omx_vdec::free_input_buffer
DESCRIPTION
free input buffer that is passed
PARAMETERS
OMX_BUFFERHEADERTYPE *pBuffer
RETURN VALUE
true if successfull
false if buffer is not part extra buffer
========================================================================== */
bool omx_vdec::free_input_buffer(OMX_BUFFERHEADERTYPE * pBuffer) {
int i;
for (i = 0; i < m_inp_buf_count; i++) {
if (pBuffer == input[i]) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
"free_input_buffer input %p\n", input);
if (m_input_buff_info[i].pArbitrary_bytes_freed) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"free_input_buffer - EmptyBufferDone!!\n");
m_cb.EmptyBufferDone(&m_cmp, m_app_data,
m_input_buff_info[i].
pArbitrary_bytes_freed);
m_input_buff_info[i].pArbitrary_bytes_freed =
NULL;
}
m_input_buff_info[i].bfree_input = true;
m_bWaitForResource = false;
return true;
}
}
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"free_input_buffer - Error: Couldn't find input %p\n",
input);
return false;
}
/* ======================================================================
FUNCTION
omx_vdec::get_free_extra_buffer_index
DESCRIPTION
get an extra buffer that's been already allocated
PARAMETERS
None
RETURN VALUE
index of extra buffer
-1 if couldn't find
========================================================================== */
OMX_S8 omx_vdec::get_free_extra_buffer_index() {
int i;
for (i = 0; i < m_inp_buf_count; i++) {
if (!m_extra_buf_info[i].bExtra_pBuffer_in_use) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
"get_free_extra_buffer - Find free extra buffer %d\n",
i);
m_extra_buf_info[i].bExtra_pBuffer_in_use = true;
return i;
}
}
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"ERROR: get_free_extra_buffer - Couldn't find free extra buffer\n");
return -1;
}
/* ======================================================================
FUNCTION
omx_vdec::find_extra_buffer_index
DESCRIPTION
determine if buffer is belong to an extra buffer
PARAMETERS
OMX_U8* buffer
RETURN VALUE
index of extra buffer
-1 if couldn't find
========================================================================== */
OMX_S8 omx_vdec::find_extra_buffer_index(OMX_U8 * buffer) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
"find_extra_buffer_index %p\n", buffer);
OMX_S8 i;
for (i = 0; i < m_inp_buf_count; i++) {
if (m_extra_buf_info[i].bExtra_pBuffer_in_use
&& (buffer == m_extra_buf_info[i].extra_pBuffer)) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
"find_extra_buffer_index - Find used extra buffer %d\n",
i);
return i;
}
}
return -1;
}
/* ======================================================================
FUNCTION
omx_vdec::free_extra_buffer
DESCRIPTION
free extra buffer that is passed
PARAMETERS
OMX_S8 index
RETURN VALUE
true if successfull
false if buffer is not part extra buffer
========================================================================== */
bool omx_vdec::free_extra_buffer(OMX_S8 index) {
if (index < 0 || index > OMX_CORE_NUM_INPUT_BUFFERS) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"free_extra_buffer - Error: Invalid index \n");
return false;
}
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_LOW,
"free_extra_buffer index %d\n", index);
m_extra_buf_info[index].bExtra_pBuffer_in_use = false;
return true;
}
/* ======================================================================
FUNCTION
initialize_arbitrary_bytes_environment
DESCRIPTION
Initialize some member variables used for arbitrary bytes input packing format
This function is used before parsing arbitrary input buffer or
after doing flush to parse the next I frame (seek, fast forward, fast rewind, etc).
PARAMETERS
none
RETURN VALUE
true if success
false otherwise
========================================================================== */
void omx_vdec::initialize_arbitrary_bytes_environment() {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"initialize_arbitrary_bytes_environment \n");
if (m_bStartCode) {
m_arbitrary_bytes_info.start_code.m_last_4byte = 0xFFFFFFFF;
m_arbitrary_bytes_info.start_code.m_last_start_code = 0;
} else {
m_arbitrary_bytes_info.frame_size.m_size_byte_left = 0;
m_arbitrary_bytes_info.frame_size.m_size_remaining = 0;
m_arbitrary_bytes_info.frame_size.m_timestamp_byte_left = 0;
}
m_is_copy_truncated = false;
m_current_frame = NULL;
m_current_arbitrary_bytes_input = NULL;
m_pcurrent_frame = NULL;
m_bPartialFrame = false;
}
/* ======================================================================
FUNCTION
omx_vdec::get_one_complete_frame
DESCRIPTION
Try to get one complete frame
PARAMETERS
OMX_OUT OMX_BUFFERHEADERTYPE* dest
RETURN VALUE
true if get one complete frame
false if get partial frame or failed
========================================================================== */
bool omx_vdec::get_one_complete_frame(OMX_OUT OMX_BUFFERHEADERTYPE * dest) {
if (m_current_arbitrary_bytes_input == NULL) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Error - m_current_arbitrary_bytes_input is NULL \n");
return false;
}
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Start of get_one_complete_frame - flags %d\n",
m_current_arbitrary_bytes_input->nFlags);
get_one_frame(dest, m_current_arbitrary_bytes_input, &m_bPartialFrame);
while (m_bPartialFrame) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_one_complete_frame got partial frame dest->pBuffer %p\n",
dest->pBuffer);
unsigned p1; // Parameter - 1
unsigned p2; // Parameter - 2
unsigned ident = 0;
mutex_lock();
if (m_etb_arbitrarybytes_q.m_size) {
m_etb_arbitrarybytes_q.delete_entry(&p1, &p2, &ident);
}
mutex_unlock();
if (ident == OMX_COMPONENT_GENERATE_ETB_ARBITRARYBYTES) {
m_current_arbitrary_bytes_input =
(OMX_BUFFERHEADERTYPE *) p2;
QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_one_complete_frame - partial frame continue to get one frame %p %p offset %d flags %d\n",
m_current_arbitrary_bytes_input,
m_current_arbitrary_bytes_input->pBuffer,
m_current_arbitrary_bytes_input->nOffset,
m_current_arbitrary_bytes_input->nFlags);
get_one_frame(dest, m_current_arbitrary_bytes_input,
&m_bPartialFrame);
} else {
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_one_complete_frame - No buffer available. Try again later\n",
p2, ident);
m_current_arbitrary_bytes_input = NULL;
break;
}
}
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"After get_one_complete_frame - m_current_frame %p %p\n",
dest, dest->pBuffer);
QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"After get_one_complete_frame - nFilledLen %d nOffset %d nFlags %d partial %d\n",
dest->nFilledLen, dest->nOffset, dest->nFlags,
m_bPartialFrame);
if (!m_bPartialFrame) {
dest->nOffset = 0;
#if DEBUG_ON
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_one_complete_frame buffer, length %d %x\n",
dest->nFilledLen, dest->nFilledLen);
for (OMX_U32 i = 0; i < 32; i++) {
printf("0x%.2x ", dest->pBuffer[i]);
if (i % 16 == 15) {
printf("\n");
}
}
if (dest->nFilledLen > 64) {
printf(".....\n");
for (OMX_U32 i = dest->nFilledLen - 32;
i < dest->nFilledLen; i++) {
printf("0x%.2x ", dest->pBuffer[i]);
if (i % 16 == 15) {
printf("\n");
}
}
}
printf("\n");
#endif
return true;
} else {
//m_current_frame = dest;
return false;
}
}
/* ======================================================================
FUNCTION
omx_vdec::get_one_frame
DESCRIPTION
- strore one frame from source to dest
- set the dest->offset to indicate the beginning of the new frame
- set the source->offset for the next frame
- update the remaining source->nFilledLen
PARAMETERS
OMX_OUT OMX_BUFFERHEADERTYPE* dest,
OMX_IN OMX_BUFFERHEADERTYPE* source,
OMX_INOUT bool *isPartialFrame
RETURN VALUE
OMX_ERRORTYPE
========================================================================== */
OMX_ERRORTYPE omx_vdec::get_one_frame(OMX_OUT OMX_BUFFERHEADERTYPE * dest,
OMX_IN OMX_BUFFERHEADERTYPE * source,
OMX_INOUT bool * isPartialFrame) {
QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_one_frame dest %p source %p isPartialFrame %d\n",
dest, source, *isPartialFrame);
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Before get_one_frame\n");
QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"dest pBuf %p len %d offset %d flags %d\n", dest->pBuffer,
dest->nFilledLen, dest->nOffset, dest->nFlags);
QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"source pBuf %p len %d offset %d flags %d\n",
source->pBuffer, source->nFilledLen, source->nOffset,
source->nFlags);
#if DEBUG_ON
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_one_frame source, length %d\n", source->nFilledLen);
for (OMX_U32 i = 0; (i < 32) && (i < source->nFilledLen); i++) {
printf("0x%.2x ", source->pBuffer[source->nOffset + i]);
if (i % 16 == 15) {
printf("\n");
}
}
printf("\n");
#endif
if (m_bStartCode) {
get_one_frame_using_start_code(dest, source, isPartialFrame);
} else {
if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc", 26)
== 0) {
get_one_frame_h264_size_nal(dest, source,
isPartialFrame);
} else {
get_one_frame_sp_mp_vc1(dest, source, isPartialFrame);
}
}
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"After get_one_frame\n");
QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"dest pBuf %p len %d offset %d flags %d\n", dest->pBuffer,
dest->nFilledLen, dest->nOffset, dest->nFlags);
QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"source pBuf %p len %d offset %d flags %d\n",
source->pBuffer, source->nFilledLen, source->nOffset,
source->nFlags);
return OMX_ErrorNone;
}
/* ======================================================================
FUNCTION
omx_vdec::get_one_frame_using_start_code
DESCRIPTION
PARAMETERS
OMX_OUT OMX_BUFFERHEADERTYPE* dest,
OMX_IN OMX_BUFFERHEADERTYPE* source,
OMX_IN OMX_U32 start_code,
OMX_INOUT OMX_U32 *current_position,
OMX_INOUT bool *isPartialFrame
RETURN VALUE
OMX_ERRORTYPE
========================================================================== */
OMX_ERRORTYPE omx_vdec::
get_one_frame_using_start_code(OMX_OUT OMX_BUFFERHEADERTYPE * dest,
OMX_IN OMX_BUFFERHEADERTYPE * source,
OMX_INOUT bool * isPartialFrame) {
OMX_U32 code = m_arbitrary_bytes_info.start_code.m_last_4byte;
OMX_U32 readSize = 0;
OMX_U32 copy_size = 0;
OMX_U32 pos = 0;
OMX_U32 in_len = source->nFilledLen;
OMX_U8 *inputBitStream = source->pBuffer + source->nOffset;
OMX_U8 scl = 4; // by default start code length is 4
bool bH264 = false;
if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc", 26) == 0)
{
scl = 3; // h264 uses 3 bytes start code
bH264 = true;
}
// To concatenate with previous frame if there is
if (*isPartialFrame == false) {
dest->nOffset = dest->nFilledLen;
}
while (pos < in_len) {
code <<= 8;
code |= (0x000000FF & *inputBitStream);
if ((code & m_arbitrary_bytes_info.start_code.
m_start_code_mask) ==
m_arbitrary_bytes_info.start_code.m_start_code) {
scl = 4;
if (bH264 && (code>>24))
scl = 3;
if (readSize > scl -1 ) {
// in this case, this start code is the beyond
// the buffer boundary, fully inside inputBitStream buffer
readSize = readSize - scl + 1;
copy_size = readSize;
if ((m_arbitrary_bytes_info.start_code.
m_last_start_code & m_arbitrary_bytes_info.
start_code.m_start_code_mask)
== m_arbitrary_bytes_info.start_code.
m_start_code) {
// we have a start code left over from the previous frame
scl = 4;
if (bH264 &&
(m_arbitrary_bytes_info.start_code.m_last_start_code >> 24))
scl = 3; // only 2 zeros are in the start code
QTV_MSG_PRIO3(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"source->nOffset = %d start_code %x %x\n",
source->nOffset, code,
m_arbitrary_bytes_info.
start_code.
m_last_start_code);
if (find_extra_buffer_index
(dest->pBuffer) == -1) {
OMX_S8 index =
get_free_extra_buffer_index
();
if (index != -1) {
OMX_U8 *temp_buffer =
dest->pBuffer;
OMX_U32 temp_size =
dest->nFilledLen;
dest->pBuffer =
m_extra_buf_info
[index].
extra_pBuffer;
if(dest->nAllocLen < dest->nFilledLen) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"Not enough memory %d \n",
__LINE__);
temp_size = dest->nAllocLen;
m_is_copy_truncated = true;
}
memcpy(dest->pBuffer,
temp_buffer,
temp_size);
} else {
QTV_MSG_PRIO
(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"Couldn't find extra buffer\n");
return
OMX_ErrorHardware;
}
QTV_MSG_PRIO2(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"Copy the start_code %d %x\n",
dest->nFilledLen,
m_arbitrary_bytes_info.
start_code.
m_last_start_code);
for (OMX_S8 i = 0; i < scl; i++) {
*(dest->pBuffer +
dest->nFilledLen) =
(OMX_U8) ((m_arbitrary_bytes_info.
start_code.
m_last_start_code & 0xFF
<< (8 * (scl - 1 - i))) >> (8 *
(scl - 1 - i)));
dest->nFilledLen++;
}
}
if(!m_is_copy_truncated) {
copy_size = readSize;
if((dest->nAllocLen - dest->nFilledLen)
< readSize) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"ERROR -- memcpy failed at line %d \n",
__LINE__);
copy_size = dest->nAllocLen - dest->nFilledLen;
m_is_copy_truncated = true;
}
memcpy(dest->pBuffer + dest->nFilledLen,
source->pBuffer +
source->nOffset, copy_size);
}
} else
if (find_extra_buffer_index(dest->pBuffer)
!= -1) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_MED,
"Concatenate to extra buffer\n");
if(!m_is_copy_truncated) {
copy_size = readSize;
if((dest->nAllocLen - dest->nFilledLen)
< readSize) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"ERROR -- memcpy failed at line %d \n",
__LINE__);
copy_size = dest->nAllocLen - dest->nFilledLen;
m_is_copy_truncated = true;
}
memcpy(dest->pBuffer + dest->nFilledLen,
source->pBuffer +
source->nOffset, copy_size);
}
}
dest->nFilledLen += copy_size;
dest->nFlags = source->nFlags;
dest->nTimeStamp = source->nTimeStamp;
*isPartialFrame = false;
m_is_copy_truncated = false;
m_arbitrary_bytes_info.start_code.
m_last_start_code = 0x00;
break;
} else if (*isPartialFrame) {
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Start code boundary = %x %d\n",
code, readSize);
m_arbitrary_bytes_info.start_code.
m_last_start_code = code;
dest->nFilledLen -= (scl - 1 - readSize);
dest->nFlags = source->nFlags;
*isPartialFrame = false;
m_is_copy_truncated = false;
readSize++;
break;
} else {
m_arbitrary_bytes_info.start_code.
m_last_start_code = 0x00;
}
}
inputBitStream++;
pos++;
readSize++;
}
m_arbitrary_bytes_info.start_code.m_last_4byte = code;
if (pos == source->nFilledLen) {
OMX_S8 index;
if (*isPartialFrame == false) {
index = get_free_extra_buffer_index();
if (index != -1) {
QTV_MSG_PRIO4(QTVDIAG_GENERAL,
QTVDIAG_PRIO_HIGH,
"With free extra buffer used %p %p %d %d\n",
m_extra_buf_info[index].
extra_pBuffer, dest->pBuffer,
dest->nOffset, dest->nFilledLen);
OMX_U8 *temp_buffer = dest->pBuffer;
OMX_U32 temp_size = dest->nOffset;
dest->pBuffer =
m_extra_buf_info[index].extra_pBuffer;
if(dest->nAllocLen < dest->nOffset) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"Not enough memory %d \n",
__LINE__);
temp_size = dest->nAllocLen;
m_is_copy_truncated = true;
}
memcpy(dest->pBuffer, temp_buffer,
temp_size);
} else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"Error - couldn't get free extra buffer %p",
dest->pBuffer);
return OMX_ErrorHardware;
}
if (m_extra_buf_info[index].arbitrarybytesInput) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"ERROR - Previous arbitrary bytes input hasn't been freed");
}
m_extra_buf_info[index].arbitrarybytesInput = source;
}
if ((m_arbitrary_bytes_info.start_code.
m_last_start_code & m_arbitrary_bytes_info.start_code.
m_start_code_mask)
== m_arbitrary_bytes_info.start_code.m_start_code) {
scl = 4;
if (bH264 &&
(m_arbitrary_bytes_info.start_code.m_last_start_code>>24))
scl = 3;
for (OMX_S8 i = 0; i < scl; i++) {
*(dest->pBuffer + dest->nFilledLen) =
(OMX_U8) ((m_arbitrary_bytes_info.
start_code.
m_last_start_code & 0xFF << (8 *
(scl - 1 - i)))
>> (8 * (scl - 1 - i)));
dest->nFilledLen++;
}
m_arbitrary_bytes_info.start_code.m_last_start_code =
0x00;
}
if(!m_is_copy_truncated) {
copy_size = readSize;
if((dest->nAllocLen - dest->nFilledLen)
< readSize) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"ERROR -- memcpy failed at line %d \n",
__LINE__);
copy_size = dest->nAllocLen - dest->nFilledLen;
m_is_copy_truncated = true;
}
memcpy(dest->pBuffer + dest->nFilledLen,
source->pBuffer + source->nOffset, copy_size);
}
dest->nFilledLen += copy_size;
dest->nFlags = source->nFlags;
dest->nTimeStamp = source->nTimeStamp;
if (*isPartialFrame == true) {
unsigned int nPortIndex =
source -
(OMX_BUFFERHEADERTYPE *)
m_arbitrary_bytes_input_mem_ptr;
if (nPortIndex < MAX_NUM_INPUT_BUFFERS) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_HIGH,
"get_one_frame - EmptyBufferDone %p\n",
source);
m_cb.EmptyBufferDone(&m_cmp, m_app_data,
source);
} else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"ERROR!! Incorrect arbitrary bytes buffer %p\n",
source);
}
} else {
*isPartialFrame = true;
source->nFilledLen -= readSize;
source->nOffset += readSize;
}
m_current_arbitrary_bytes_input = NULL;
if (dest->nFlags & OMX_BUFFERFLAG_EOS) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"EOS observed\n");
*isPartialFrame = false;
}
#if DEBUG_ON
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_one_frame partial buffer, length %d\n",
dest->nFilledLen);
for (OMX_U32 i = 0; i < 32; i++) {
printf("0x%.2x ", dest->pBuffer[dest->nOffset + i]);
if (i % 16 == 15) {
printf("\n");
}
}
printf("\n");
#endif
} else {
source->nFilledLen -= readSize;
source->nOffset += readSize;
}
return OMX_ErrorNone;
}
/* ======================================================================
FUNCTION
get_one_frame_h264_size_nal
DESCRIPTION
get one nal from size nal length clip
PARAMETERS
OMX_IN OMX_BUFFERHEADERTYPE* buffer.
RETURN VALUE
true if success
false otherwise
========================================================================== */
OMX_ERRORTYPE omx_vdec::
get_one_frame_h264_size_nal(OMX_OUT OMX_BUFFERHEADERTYPE * dest,
OMX_IN OMX_BUFFERHEADERTYPE * source,
OMX_INOUT bool * isPartialFrame) {
int i = 0;
int j = 0;
OMX_U8 temp_size[4];
OMX_U32 sizeofNAL = 0;
if ((source->nFilledLen == 0) && (source->nFlags & OMX_BUFFERFLAG_EOS)) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"EOS observed\n");
dest->nFlags = source->nFlags;
m_current_arbitrary_bytes_input = NULL;
if (*isPartialFrame == true) {
unsigned int nPortIndex =
source -
(OMX_BUFFERHEADERTYPE *)
m_arbitrary_bytes_input_mem_ptr;
if (nPortIndex < MAX_NUM_INPUT_BUFFERS) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_HIGH,
"get_one_frame_h264_size_nal - EmptyBufferDone %p\n",
source);
m_cb.EmptyBufferDone(&m_cmp, m_app_data,
source);
} else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"ERROR!! Incorrect arbitrary bytes buffer %p\n",
source);
}
}
*isPartialFrame = false;
return OMX_ErrorNone;
}
if (*isPartialFrame == false) {
dest->nOffset = dest->nFilledLen;
if (source->nFilledLen < m_nalu_bytes) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_one_frame_h264_size_nal - get_free_extra_buffer_index\n");
OMX_S8 index = get_free_extra_buffer_index();
if (index != -1) {
OMX_U8 *temp_buffer = dest->pBuffer;
dest->pBuffer =
m_extra_buf_info[index].extra_pBuffer;
memcpy(dest->pBuffer, temp_buffer,
dest->nFilledLen);
memcpy(dest->pBuffer + dest->nFilledLen,
source->pBuffer + source->nOffset,
source->nFilledLen);
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"Error - Couldn't find extra buffer\n");
return OMX_ErrorHardware;
}
if (m_extra_buf_info[index].arbitrarybytesInput) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"ERROR - Previous arbitrary bytes input hasn't been freed");
}
m_extra_buf_info[index].arbitrarybytesInput = source;
}
sizeofNAL = m_nalu_bytes;
m_arbitrary_bytes_info.frame_size.m_size_remaining = 0;
while (source->nFilledLen && sizeofNAL) {
sizeofNAL--;
m_arbitrary_bytes_info.frame_size.m_size_remaining |=
source->pBuffer[source->
nOffset] << (sizeofNAL << 3);
source->nOffset++;
dest->nFilledLen++;
source->nFilledLen--;
}
m_arbitrary_bytes_info.frame_size.m_size_byte_left = sizeofNAL;
QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_one_frame_h264_size_nal - m_size_remaining %d %x m_size_byte_left %d\n",
m_arbitrary_bytes_info.frame_size.
m_size_remaining,
m_arbitrary_bytes_info.frame_size.
m_size_remaining,
m_arbitrary_bytes_info.frame_size.
m_size_byte_left);
if (m_arbitrary_bytes_info.frame_size.m_size_byte_left > 0) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_one_frame_h264_size_nal - partialFrame at size nal length %d\n",
m_arbitrary_bytes_info.frame_size.
m_size_byte_left);
*isPartialFrame = true;
m_current_arbitrary_bytes_input = NULL;
return OMX_ErrorNone;
}
dest->nTimeStamp = source->nTimeStamp;
} else if (m_arbitrary_bytes_info.frame_size.m_size_byte_left > 0) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_one_frame_h264_size_nal - find the frame size %d\n",
m_arbitrary_bytes_info.frame_size.
m_size_byte_left);
sizeofNAL = m_arbitrary_bytes_info.frame_size.m_size_byte_left;
while (source->nFilledLen && sizeofNAL) {
sizeofNAL--;
m_arbitrary_bytes_info.frame_size.m_size_remaining |=
source->pBuffer[source->
nOffset] << (sizeofNAL << 3);
dest->pBuffer[dest->nFilledLen] =
source->pBuffer[source->nOffset];
source->nOffset++;
dest->nFilledLen++;
source->nFilledLen--;
}
m_arbitrary_bytes_info.frame_size.m_size_byte_left = sizeofNAL;
if (m_arbitrary_bytes_info.frame_size.m_size_byte_left > 0) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Error - Never go here, unless input buffer is extremely small\n");
}
dest->nTimeStamp = source->nTimeStamp;
}
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_one_frame_h264_size_nal - get the frame remaining size %d, dest size %d\n",
m_arbitrary_bytes_info.frame_size.m_size_remaining,
dest->nFilledLen);
OMX_S8 extra_buffer_index = find_extra_buffer_index(dest->pBuffer);
if (m_arbitrary_bytes_info.frame_size.m_size_remaining >=
source->nFilledLen) {
bool complete_nal = false;
if (m_arbitrary_bytes_info.frame_size.m_size_remaining ==
source->nFilledLen) {
complete_nal = true;
}
if (extra_buffer_index == -1 && (!m_is_copy_truncated)) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_one_frame_h264_size_nal - get_free_extra_buffer_index\n");
OMX_S8 index = get_free_extra_buffer_index();
if (index != -1) {
OMX_U8 *temp_buffer = dest->pBuffer;
unsigned int tmp_size = dest->nFilledLen;
dest->pBuffer =
m_extra_buf_info[index].extra_pBuffer;
if (dest->nAllocLen < dest->nFilledLen) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_HIGH,
"Not enough memory - \n");
tmp_size = dest->nAllocLen;
m_is_copy_truncated = true;
}
memcpy(dest->pBuffer, temp_buffer, tmp_size);
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_FATAL,
"Error - Couldn't find extra buffer\n");
return OMX_ErrorHardware;
}
if (m_extra_buf_info[index].arbitrarybytesInput) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"ERROR - Previous arbitrary bytes input hasn't been freed");
}
m_extra_buf_info[index].arbitrarybytesInput = source;
}
if (!m_is_copy_truncated) {
unsigned int copy_size = source->nFilledLen;
if ((dest->nAllocLen - dest->nFilledLen) <
source->nFilledLen) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"ERROR - we should never reach here memcpy failed at line %d",
__LINE__);
copy_size = dest->nAllocLen - dest->nFilledLen;
m_is_copy_truncated = true;
}
memcpy(dest->pBuffer + dest->nFilledLen,
source->pBuffer + source->nOffset, copy_size);
dest->nFilledLen += copy_size;
}
m_arbitrary_bytes_info.frame_size.m_size_remaining -=
source->nFilledLen;
source->nOffset += source->nFilledLen;
source->nFilledLen = 0;
if (*isPartialFrame == true) {
unsigned int nPortIndex =
source -
(OMX_BUFFERHEADERTYPE *)
m_arbitrary_bytes_input_mem_ptr;
if (nPortIndex < MAX_NUM_INPUT_BUFFERS) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_HIGH,
"get_one_frame_h264_size_nal - EmptyBufferDone %p\n",
source);
m_cb.EmptyBufferDone(&m_cmp, m_app_data,
source);
} else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"ERROR!! Incorrect arbitrary bytes buffer %p\n",
source);
}
}
if (complete_nal) {
*isPartialFrame = false;
m_is_copy_truncated = false;
m_arbitrary_bytes_info.frame_size.m_size_remaining = 0;
} else {
*isPartialFrame = true;
}
m_current_arbitrary_bytes_input = NULL;
} else {
unsigned int copy_size =
m_arbitrary_bytes_info.frame_size.m_size_remaining;
if (extra_buffer_index != -1 && (false == m_is_copy_truncated)) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Concatenate to extra buffer\n");
if ((dest->nAllocLen - dest->nFilledLen) <
m_arbitrary_bytes_info.frame_size.
m_size_remaining) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_HIGH,
"Not enough memory - %d \n",
__LINE__);
copy_size =
(dest->nAllocLen - dest->nFilledLen);
m_is_copy_truncated = true;
dest->nFilledLen += copy_size;
}
memcpy(dest->pBuffer + dest->nFilledLen,
source->pBuffer + source->nOffset, copy_size);
}
if (false == m_is_copy_truncated)
dest->nFilledLen += copy_size;
source->nOffset +=
m_arbitrary_bytes_info.frame_size.m_size_remaining;
source->nFilledLen -=
m_arbitrary_bytes_info.frame_size.m_size_remaining;
m_arbitrary_bytes_info.frame_size.m_size_remaining = 0;
m_is_copy_truncated = false;
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_one_frame_h264_size_nal - dest size %d\n",
dest->nFilledLen);
dest->nFlags = source->nFlags;
if (source->nFilledLen == 0) {
m_current_arbitrary_bytes_input = NULL;
if (*isPartialFrame == false) {
OMX_S8 input_index =
find_input_buffer_index(dest);
if ((input_index == -1)
|| m_input_buff_info[input_index].
pArbitrary_bytes_freed) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"ERROR - Couldn't find input index %d or Previous arbitrary bytes input hasn't been freed",
input_index);
}
m_input_buff_info[input_index].
pArbitrary_bytes_freed = source;
}
}
*isPartialFrame = false;
#if DEBUG_ON
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_one_frame_h264_size_nal partial buffer, length %d\n",
dest->nFilledLen);
for (OMX_U32 i = 0; i < 32; i++) {
printf("0x%.2x ", dest->pBuffer[dest->nOffset + i]);
if (i % 16 == 15) {
printf("\n");
}
}
printf("\n");
#endif
}
return OMX_ErrorNone;
}
/* ======================================================================
FUNCTION
get_one_frame_sp_mp_vc1
DESCRIPTION
get one nal from size nal length clip
PARAMETERS
OMX_IN OMX_BUFFERHEADERTYPE* buffer.
RETURN VALUE
true if success
false otherwise
========================================================================== */
OMX_ERRORTYPE omx_vdec::get_one_frame_sp_mp_vc1(OMX_OUT OMX_BUFFERHEADERTYPE *
dest,
OMX_IN OMX_BUFFERHEADERTYPE *
source,
OMX_INOUT bool *
isPartialFrame) {
int i = 0;
int j = 0;
OMX_U8 temp_size[4];
OMX_U8 temp_timestamp[4];
OMX_U32 timestamp = 0;
OMX_U32 frameSizeBytes = 0;
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_HIGH,
"get_one_frame_sp_mp_vc1 - timestamp field present: %d\n",
m_arbitrary_bytes_info.frame_size.
m_timestamp_field_present);
if ((source->nFilledLen == 0) && (source->nFlags & OMX_BUFFERFLAG_EOS)) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"EOS observed\n");
dest->nFlags = source->nFlags;
m_current_arbitrary_bytes_input = NULL;
if (*isPartialFrame == true) {
unsigned int nPortIndex =
source -
(OMX_BUFFERHEADERTYPE *)
m_arbitrary_bytes_input_mem_ptr;
if (nPortIndex < MAX_NUM_INPUT_BUFFERS) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_HIGH,
"get_one_frame_sp_mp_vc1 - EmptyBufferDone %p\n",
source);
m_cb.EmptyBufferDone(&m_cmp, m_app_data,
source);
} else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"ERROR!! Incorrect arbitrary bytes buffer %p\n",
source);
}
}
*isPartialFrame = false;
return OMX_ErrorNone;
}
// Frame size
if (*isPartialFrame == false) {
dest->nOffset = dest->nFilledLen;
/* for RCV V1 format, there is no timestamp field, so this should not be parsed */
if (m_arbitrary_bytes_info.frame_size.
m_timestamp_field_present == 1) {
m_arbitrary_bytes_info.frame_size.
m_timestamp_byte_left = 5;
}
if (source->nFilledLen < 8) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_one_frame_sp_mp_vc1 - get_free_extra_buffer_index\n");
OMX_S8 index = get_free_extra_buffer_index();
if (index != -1) {
dest->pBuffer =
m_extra_buf_info[index].extra_pBuffer;
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"Error - Couldn't find extra buffer\n");
return OMX_ErrorHardware;
}
if (m_extra_buf_info[index].arbitrarybytesInput) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"ERROR - Previous arbitrary bytes input hasn't been freed");
}
m_extra_buf_info[index].arbitrarybytesInput = source;
}
frameSizeBytes = 3;
m_arbitrary_bytes_info.frame_size.m_size_remaining = 0;
while (source->nFilledLen && frameSizeBytes) {
frameSizeBytes--;
m_arbitrary_bytes_info.frame_size.m_size_remaining |=
source->pBuffer[source->
nOffset] << ((2 -
frameSizeBytes) << 3);
source->nOffset++;
source->nFilledLen--;
}
m_arbitrary_bytes_info.frame_size.m_size_byte_left =
frameSizeBytes;
if (m_arbitrary_bytes_info.frame_size.m_size_byte_left > 0) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_one_frame_sp_mp_vc1 - partialFrame at size nal length %d\n",
m_arbitrary_bytes_info.frame_size.
m_size_byte_left);
*isPartialFrame = true;
m_current_arbitrary_bytes_input = NULL;
return OMX_ErrorNone;
} else {
/* in the case of RCV V1 format, there is no timestamp field left, but increment byte for key field */
if (m_arbitrary_bytes_info.frame_size.
m_timestamp_field_present == 0
&& source->nFilledLen > 0) {
source->nFilledLen--;
source->nOffset++;
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"RCV V1- source filled len: %d, source offset: %d \n",
source->nFilledLen,
source->nOffset);
}
}
} else if (m_arbitrary_bytes_info.frame_size.m_size_byte_left > 0) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_one_frame_sp_mp_vc1 - find the frame size %d\n",
m_arbitrary_bytes_info.frame_size.
m_size_byte_left);
frameSizeBytes =
m_arbitrary_bytes_info.frame_size.m_size_byte_left;
while (source->nFilledLen && frameSizeBytes) {
frameSizeBytes--;
m_arbitrary_bytes_info.frame_size.m_size_remaining |=
source->pBuffer[source->
nOffset] << ((2 -
frameSizeBytes) << 3);
source->nOffset++;
source->nFilledLen--;
}
m_arbitrary_bytes_info.frame_size.m_size_byte_left =
frameSizeBytes;
if (m_arbitrary_bytes_info.frame_size.m_size_byte_left > 0) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_ERROR,
"Error - Never go here, unless input buffer is extremely small\n");
} else {
/* in the case of RCV V1, no timestamp field, but increment the byte for key field */
if (m_arbitrary_bytes_info.frame_size.
m_timestamp_field_present == 0
&& source->nFilledLen > 0) {
source->nFilledLen--;
source->nOffset++;
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"RCV V1- source filled len: %d, source offset: %d \n",
source->nFilledLen,
source->nOffset);
}
}
}
OMX_S8 extra_buffer_index = find_extra_buffer_index(dest->pBuffer);
// Time stamp
QTV_MSG_PRIO2(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_one_frame_sp_mp_vc1 - partialFrame at time stamp byte left %d, nFilledLen %d\n",
m_arbitrary_bytes_info.frame_size.m_timestamp_byte_left,
source->nFilledLen);
if (m_arbitrary_bytes_info.frame_size.m_timestamp_field_present == 1) {
if ((m_arbitrary_bytes_info.frame_size.m_timestamp_byte_left >
0) && (source->nFilledLen < 5)) {
if (source->nFilledLen != 0) {
if (m_arbitrary_bytes_info.frame_size.
m_timestamp_byte_left == 5) {
source->nFilledLen--; // for KEY and RES
source->nOffset++;
m_arbitrary_bytes_info.frame_size.
m_timestamp_byte_left--;
}
frameSizeBytes =
m_arbitrary_bytes_info.frame_size.
m_timestamp_byte_left;
timestamp = 0;
while (source->nFilledLen && frameSizeBytes) {
frameSizeBytes--;
timestamp |=
source->pBuffer[source->
nOffset] << ((3 -
frameSizeBytes)
<< 3);
source->nOffset++;
source->nFilledLen--;
}
dest->nTimeStamp = (OMX_TICKS) timestamp;
m_arbitrary_bytes_info.frame_size.
m_timestamp_byte_left = frameSizeBytes;
}
QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_one_frame_sp_mp_vc1 - partialFrame at time stamp %d %d %x %x\n",
m_arbitrary_bytes_info.frame_size.
m_timestamp_byte_left, dest->nTimeStamp,
dest->nTimeStamp, timestamp);
*isPartialFrame = true;
m_current_arbitrary_bytes_input = NULL;
return OMX_ErrorNone;
} else if (m_arbitrary_bytes_info.frame_size.
m_timestamp_byte_left > 0) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_one_frame_sp_mp_vc1 - find the time stamp %d\n",
m_arbitrary_bytes_info.frame_size.
m_timestamp_byte_left);
if (m_arbitrary_bytes_info.frame_size.
m_timestamp_byte_left == 5) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"m_arbitrary_bytes_info.frame_size.m_timestamp_byte_left == 5\n");
source->nFilledLen--; // for KEY and RES
source->nOffset++;
m_arbitrary_bytes_info.frame_size.
m_timestamp_byte_left--;
dest->nTimeStamp = 0;
}
frameSizeBytes =
m_arbitrary_bytes_info.frame_size.
m_timestamp_byte_left;
timestamp = dest->nTimeStamp;
while (source->nFilledLen && frameSizeBytes) {
frameSizeBytes--;
timestamp |=
source->pBuffer[source->
nOffset] << ((3 -
frameSizeBytes)
<< 3);
source->nOffset++;
source->nFilledLen--;
}
dest->nTimeStamp = (OMX_TICKS) timestamp;
QTV_MSG_PRIO3(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"timeStamp %x dest timestamp %x, temp_timestamp %x\n",
timestamp, dest->nTimeStamp,
temp_timestamp);
m_arbitrary_bytes_info.frame_size.
m_timestamp_byte_left = frameSizeBytes;
if (extra_buffer_index == -1) {
dest->pBuffer += 8;
}
if (m_arbitrary_bytes_info.frame_size.
m_timestamp_byte_left > 0) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"Error - Never go here, unless input buffer is extremely small\n");
}
}
}
QTV_MSG_PRIO4(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_one_frame_sp_mp_vc1 - get the frame remaining size %d, dest size %d, dest ts %x %d\n",
m_arbitrary_bytes_info.frame_size.m_size_remaining,
dest->nFilledLen, dest->nTimeStamp, dest->nTimeStamp);
if (m_arbitrary_bytes_info.frame_size.m_size_remaining >=
source->nFilledLen) {
bool complete_frame = false;
if (m_arbitrary_bytes_info.frame_size.m_size_remaining ==
source->nFilledLen) {
complete_frame = true;
}
if (extra_buffer_index == -1 && (!m_is_copy_truncated)) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_one_frame_sp_mp_vc1 - get_free_extra_buffer_index\n");
OMX_S8 index = get_free_extra_buffer_index();
if (index != -1) {
OMX_U8 *temp_buffer = dest->pBuffer;
unsigned int tmp_size = dest->nFilledLen;
dest->pBuffer =
m_extra_buf_info[index].extra_pBuffer;
if (dest->nAllocLen < dest->nFilledLen) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_HIGH,
"Not enough memory - \n");
tmp_size = dest->nAllocLen;
m_is_copy_truncated = true;
}
memcpy(dest->pBuffer, temp_buffer, tmp_size);
} else {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_FATAL,
"Error - Couldn't find extra buffer\n");
return OMX_ErrorHardware;
}
if (m_extra_buf_info[index].arbitrarybytesInput) {
QTV_MSG_PRIO(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"ERROR - Previous arbitrary bytes input hasn't been freed");
}
m_extra_buf_info[index].arbitrarybytesInput = source;
}
if (!m_is_copy_truncated) {
unsigned int copy_size = source->nFilledLen;
if ((dest->nAllocLen - dest->nFilledLen) <
source->nFilledLen) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"ERROR - we should never reach here memcpy failed at line %d",
__LINE__);
copy_size = dest->nAllocLen - dest->nFilledLen;
m_is_copy_truncated = true;
}
memcpy(dest->pBuffer + dest->nFilledLen,
source->pBuffer + source->nOffset, copy_size);
dest->nFilledLen += copy_size;
}
m_arbitrary_bytes_info.frame_size.m_size_remaining -=
source->nFilledLen;
source->nOffset += source->nFilledLen;
source->nFilledLen = 0;
if (*isPartialFrame == true) {
unsigned int nPortIndex =
source -
(OMX_BUFFERHEADERTYPE *)
m_arbitrary_bytes_input_mem_ptr;
if (nPortIndex < MAX_NUM_INPUT_BUFFERS) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_HIGH,
"get_one_frame_sp_mp_vc1 - EmptyBufferDone %p\n",
source);
m_cb.EmptyBufferDone(&m_cmp, m_app_data,
source);
} else {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"ERROR!! Incorrect arbitrary bytes buffer %p\n",
source);
}
}
if (complete_frame) {
*isPartialFrame = false;
} else {
*isPartialFrame = true;
}
m_current_arbitrary_bytes_input = NULL;
} else {
unsigned int copy_size =
m_arbitrary_bytes_info.frame_size.m_size_remaining;
if (extra_buffer_index != -1 && (false == m_is_copy_truncated)) {
QTV_MSG_PRIO(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"Concatenate to extra buffer\n");
if ((dest->nAllocLen - dest->nFilledLen) <
m_arbitrary_bytes_info.frame_size.
m_size_remaining) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_HIGH,
"Not enough memory - %d \n",
__LINE__);
copy_size =
(dest->nAllocLen - dest->nFilledLen);
m_is_copy_truncated = true;
dest->nFilledLen += copy_size;
}
memcpy(dest->pBuffer + dest->nFilledLen,
source->pBuffer + source->nOffset, copy_size);
}
if (false == m_is_copy_truncated)
dest->nFilledLen += copy_size;
source->nOffset +=
m_arbitrary_bytes_info.frame_size.m_size_remaining;
source->nFilledLen -=
m_arbitrary_bytes_info.frame_size.m_size_remaining;
m_arbitrary_bytes_info.frame_size.m_size_remaining = 0;
m_is_copy_truncated = false;
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_one_frame_sp_mp_vc1 - dest size %d\n",
dest->nFilledLen);
dest->nFlags = source->nFlags;
if (source->nFilledLen == 0) {
m_current_arbitrary_bytes_input = NULL;
if (*isPartialFrame == false) {
OMX_S8 input_index =
find_input_buffer_index(dest);
if ((input_index == -1)
|| m_input_buff_info[input_index].
pArbitrary_bytes_freed) {
QTV_MSG_PRIO1(QTVDIAG_GENERAL,
QTVDIAG_PRIO_ERROR,
"ERROR - Couldn't find input index %d or Previous arbitrary bytes input hasn't been freed",
input_index);
}
m_input_buff_info[input_index].
pArbitrary_bytes_freed = source;
}
}
*isPartialFrame = false;
#if DEBUG_ON
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"get_one_frame_sp_mp_vc1 partial buffer, length %d\n",
dest->nFilledLen);
for (OMX_U32 i = 0; i < 32; i++) {
printf("0x%.2x ", dest->pBuffer[dest->nOffset + i]);
if (i % 16 == 15) {
printf("\n");
}
}
printf("\n");
#endif
}
return OMX_ErrorNone;
}
void omx_vdec::fill_extradata(OMX_INOUT OMX_BUFFERHEADERTYPE * pBufHdr,
OMX_IN vdec_frame * frame) {
int n = 0;
Vdec_FrameDetailsType *frameDetails = &frame->frameDetails;
uint32 addr = 0;
uint32 end = (uint32) (pBufHdr->pBuffer + pBufHdr->nAllocLen);
OMX_OTHER_EXTRADATATYPE *pExtraData = 0;
OMX_QCOM_EXTRADATA_FRAMEINFO *pExtraFrameInfo = 0;
OMX_QCOM_EXTRADATA_FRAMEDIMENSION *pExtraFrameDimension = 0;
OMX_QCOM_EXTRADATA_CODEC_DATA *pExtraCodecData = 0;
uint32 size = 0;
pBufHdr->nFlags |= OMX_BUFFERFLAG_EXTRADATA;
m_dec_width = frameDetails->nDecPicWidth;
m_dec_height = frameDetails->nDecPicHeight;
pBufHdr->nFilledLen = m_dec_width * m_dec_height * 3 / 2;
addr = (uint32) (pBufHdr->pBuffer + pBufHdr->nFilledLen);
// align to a 4 byte boundary
addr = (addr + 3) & (~3);
// read to the end of existing extra data sections
pExtraData = (OMX_OTHER_EXTRADATATYPE *) addr;
if (m_vdec_cfg.postProc) {
while (addr < end && pExtraData->eType != OMX_ExtraDataNone) {
addr += pExtraData->nSize;
pExtraData = (OMX_OTHER_EXTRADATATYPE *) addr;
}
}
// append the common frame info extra data
size =
(OMX_EXTRADATA_HEADER_SIZE + sizeof(OMX_QCOM_EXTRADATA_FRAMEINFO) +
3) & (~3);
pExtraData->nSize = size;
pExtraData->nVersion.nVersion = OMX_SPEC_VERSION;
pExtraData->nPortIndex = 1;
pExtraData->eType = (OMX_EXTRADATATYPE) OMX_ExtraDataFrameInfo; /* Extra Data type */
pExtraData->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEINFO); /* Size of the supporting data to follow */
pExtraFrameInfo = (OMX_QCOM_EXTRADATA_FRAMEINFO *) pExtraData->data;
pBufHdr->nFlags &= (~OMX_BUFFERFLAG_SYNCFRAME);
if (frameDetails->ePicType[0] == VDEC_PICTURE_TYPE_I) {
pBufHdr->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
}
if (frameDetails->ePicFormat == VDEC_PROGRESSIVE_FRAME)
pExtraFrameInfo->interlaceType =
OMX_QCOM_InterlaceFrameProgressive;
else if (frameDetails->ePicFormat = VDEC_INTERLACED_FRAME) {
if (frameDetails->bTopFieldFirst)
pExtraFrameInfo->interlaceType =
OMX_QCOM_InterlaceInterleaveFrameTopFieldFirst;
else
pExtraFrameInfo->interlaceType =
OMX_QCOM_InterlaceInterleaveFrameBottomFieldFirst;
}
pExtraFrameInfo->panScan.numWindows = frameDetails->panScan.numWindows;
for (n = 0; n < frameDetails->panScan.numWindows; n++) {
pExtraFrameInfo->panScan.window[n].x =
frameDetails->panScan.winHorOffset[n];
pExtraFrameInfo->panScan.window[n].y =
frameDetails->panScan.winVerOffset[n];
pExtraFrameInfo->panScan.window[n].dx =
frameDetails->panScan.winWidth[n];
pExtraFrameInfo->panScan.window[n].dy =
frameDetails->panScan.winHeight[n];
}
pExtraFrameInfo->nConcealedMacroblocks =
frameDetails->nPercentConcealedMacroblocks;
// append the derived timestamp or YUV range mapping
addr += size;
pExtraData = (OMX_OTHER_EXTRADATATYPE *) addr;
size =
(OMX_EXTRADATA_HEADER_SIZE + sizeof(OMX_QCOM_EXTRADATA_CODEC_DATA) +
3) & (~3);
pExtraData->nSize = size;
pExtraData->nVersion.nVersion = OMX_SPEC_VERSION;
pExtraData->nPortIndex = 1;
pExtraCodecData = (OMX_QCOM_EXTRADATA_CODEC_DATA *) pExtraData->data;
if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc", 26) == 0) {
pExtraData->eType = (OMX_EXTRADATATYPE) OMX_ExtraDataH264; /* Extra Data type */
pExtraData->nDataSize = sizeof(OMX_QCOM_H264EXTRADATA); /* Size of the supporting data to follow */
pExtraCodecData->h264ExtraData.seiTimeStamp =
frameDetails->calculatedTimeStamp;
} else if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.vc1", 26) ==
0) {
pExtraData->eType = (OMX_EXTRADATATYPE) OMX_ExtraDataVC1; /* Extra Data type */
pExtraData->nDataSize = sizeof(OMX_QCOM_VC1EXTRADATA); /* Size of the supporting data to follow */
pExtraCodecData->vc1ExtraData.nVC1RangeY =
frameDetails->nVC1RangeY;
pExtraCodecData->vc1ExtraData.nVC1RangeUV =
frameDetails->nVC1RangeUV;
pExtraCodecData->vc1ExtraData.eVC1PicResolution =
(OMX_QCOM_VC1RESOLUTIONTYPE) frameDetails->ePicResolution;
}
// append the Height and Width adjusted to multiple of 16 and Actual Height and Width
addr += size;
pExtraData = (OMX_OTHER_EXTRADATATYPE *)addr;
size = (OMX_EXTRADATA_HEADER_SIZE + sizeof(OMX_QCOM_EXTRADATA_FRAMEDIMENSION) + 3 ) & (~3);
pExtraData->nSize = size;
pExtraData->nVersion.nVersion = OMX_SPEC_VERSION;
pExtraData->nPortIndex = 1;
if (strncmp(m_vdec_cfg.kind, "OMX.qcom.video.decoder.avc", 26) == 0)
{
pExtraData->eType = (OMX_EXTRADATATYPE) OMX_ExtraDataFrameDimension;
pExtraData->nDataSize = sizeof(OMX_QCOM_EXTRADATA_FRAMEDIMENSION); /* Size of the supporting data to follow */
pExtraFrameDimension = (OMX_QCOM_EXTRADATA_FRAMEDIMENSION *)pExtraData->data;
pExtraFrameDimension->nDecWidth = frameDetails->nDecPicWidth;
pExtraFrameDimension->nDecHeight = frameDetails->nDecPicHeight;
pExtraFrameDimension->nActualWidth = frameDetails->cwin.x2 - frameDetails->cwin.x1;
pExtraFrameDimension->nActualHeight= frameDetails->cwin.y2 - frameDetails->cwin.y1;
}
// append extradata terminator
addr += size;
pExtraData = (OMX_OTHER_EXTRADATATYPE *) addr;
pExtraData->nSize = OMX_EXTRADATA_HEADER_SIZE;
pExtraData->nVersion.nVersion = OMX_SPEC_VERSION;
pExtraData->nPortIndex = 1;
pExtraData->eType = OMX_ExtraDataNone;
pExtraData->nDataSize = 0;
pBufHdr->nOffset = 0;
if (frameDetails->cwin.x1 || frameDetails->cwin.y1)
{
pBufHdr->nOffset = frameDetails->cwin.y1 * frameDetails->nDecPicWidth + frameDetails->cwin.x1;
}
}
/* ======================================================================
FUNCTION
find_new_frame_ap_vc1
DESCRIPTION
finds whether the BDU belongs to previous frame
PARAMETERS
OMX_IN OMX_U8* buffer.
OMX_IN OMX_U32 buffer_length
OMX_OUT OMX_BOOL isNewFrame
RETURN VALUE
true if success
false otherwise
========================================================================== */
bool omx_vdec::find_new_frame_ap_vc1(OMX_IN OMX_U8 * buffer,
OMX_IN OMX_U32 buffer_length,
OMX_OUT OMX_BOOL & isNewFrame) {
uint32 code = 0xFFFFFFFF;
isNewFrame = OMX_TRUE;
for (uint32 i = 0; i < buffer_length; i++) {
code <<= 8;
code |= *buffer++;
if ((code & VC1_AP_SLICE_START_CODE_MASK) ==
VC1_AP_SLICE_START_CODE) {
isNewFrame = OMX_FALSE;
break;
}
}
QTV_MSG_PRIO1(QTVDIAG_GENERAL, QTVDIAG_PRIO_MED,
"find_new_frame_ap_vc1 %d\n", isNewFrame);
return true;
}