blob: 59860edc5ab9940af1ecf9fea469099c5697e55a [file] [log] [blame]
/*--------------------------------------------------------------------------
Copyright (c) 2010-2016, Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of The Linux Foundation nor
the names of its contributors may be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------*/
/*============================================================================
O p e n M A X w r a p p e r s
O p e n M A X C o r e
*//** @file omx_video_base.cpp
This module contains the implementation of the OpenMAX core & component.
*//*========================================================================*/
//////////////////////////////////////////////////////////////////////////////
// Include Files
//////////////////////////////////////////////////////////////////////////////
#define __STDC_FORMAT_MACROS //enables the format specifiers in inttypes.h
#include <inttypes.h>
#include <string.h>
#include "omx_video_base.h"
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/prctl.h>
#ifdef _ANDROID_ICS_
#include <media/hardware/HardwareAPI.h>
#include <gralloc_priv.h>
#endif
#ifndef _ANDROID_
#include <glib.h>
#define strlcpy g_strlcpy
#endif
#define H264_SUPPORTED_WIDTH (480)
#define H264_SUPPORTED_HEIGHT (368)
#define MPEG4_SUPPORTED_WIDTH (480)
#define MPEG4_SUPPORTED_HEIGHT (368)
#define VC1_SP_MP_START_CODE 0xC5000000
#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_PROFILE_MASK 0xF0
#define VC1_STRUCT_B_LEVEL_MASK 0xE0000000
#define VC1_SIMPLE_PROFILE 0
#define VC1_MAIN_PROFILE 1
#define VC1_ADVANCE_PROFILE 3
#define VC1_SIMPLE_PROFILE_LOW_LEVEL 0
#define VC1_SIMPLE_PROFILE_MED_LEVEL 2
#define VC1_STRUCT_C_LEN 4
#define VC1_STRUCT_C_POS 8
#define VC1_STRUCT_A_POS 12
#define VC1_STRUCT_B_POS 24
#define VC1_SEQ_LAYER_SIZE 36
#define SZ_4K 0x1000
#define SZ_1M 0x100000
typedef struct OMXComponentCapabilityFlagsType {
////////////////// OMX COMPONENT CAPABILITY RELATED MEMBERS
OMX_U32 nSize;
OMX_VERSIONTYPE nVersion;
OMX_BOOL iIsOMXComponentMultiThreaded;
OMX_BOOL iOMXComponentSupportsExternalOutputBufferAlloc;
OMX_BOOL iOMXComponentSupportsExternalInputBufferAlloc;
OMX_BOOL iOMXComponentSupportsMovableInputBuffers;
OMX_BOOL iOMXComponentSupportsPartialFrames;
OMX_BOOL iOMXComponentUsesNALStartCodes;
OMX_BOOL iOMXComponentCanHandleIncompleteFrames;
OMX_BOOL iOMXComponentUsesFullAVCFrames;
} OMXComponentCapabilityFlagsType;
#define OMX_COMPONENT_CAPABILITY_TYPE_INDEX 0xFF7A347
void* message_thread(void *input)
{
omx_video* omx = reinterpret_cast<omx_video*>(input);
unsigned char id;
int n;
DEBUG_PRINT_LOW("omx_venc: message thread start");
prctl(PR_SET_NAME, (unsigned long)"VideoEncMsgThread", 0, 0, 0);
while (1) {
n = read(omx->m_pipe_in, &id, 1);
if (0 == n) {
break;
}
if (1 == n) {
omx->process_event_cb(omx, id);
}
#ifdef QLE_BUILD
if (n < 0) break;
#else
if ((n < 0) && (errno != EINTR)) break;
#endif
}
DEBUG_PRINT_LOW("omx_venc: message thread stop");
return 0;
}
void post_message(omx_video *omx, unsigned char id)
{
DEBUG_PRINT_LOW("omx_venc: post_message %d", id);
write(omx->m_pipe_out, &id, 1);
}
// omx_cmd_queue destructor
omx_video::omx_cmd_queue::~omx_cmd_queue()
{
// Nothing to do
}
// omx cmd queue constructor
omx_video::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_video::omx_cmd_queue::insert_entry(unsigned long p1, unsigned long p2, unsigned long id)
{
bool ret = true;
if (m_size < OMX_CORE_CONTROL_CMDQ_SIZE) {
m_q[m_write].id = id;
m_q[m_write].param1 = p1;
m_q[m_write].param2 = p2;
m_write++;
m_size ++;
if (m_write >= OMX_CORE_CONTROL_CMDQ_SIZE) {
m_write = 0;
}
} else {
ret = false;
DEBUG_PRINT_ERROR("ERROR!!! Command Queue Full");
}
return ret;
}
// omx cmd queue pop
bool omx_video::omx_cmd_queue::pop_entry(unsigned long *p1, unsigned long *p2, unsigned long *id)
{
bool ret = true;
if (m_size > 0) {
*id = m_q[m_read].id;
*p1 = m_q[m_read].param1;
*p2 = m_q[m_read].param2;
// Move the read pointer ahead
++m_read;
--m_size;
if (m_read >= OMX_CORE_CONTROL_CMDQ_SIZE) {
m_read = 0;
}
} else {
ret = false;
}
return ret;
}
// Retrieve the first mesg type in the queue
unsigned omx_video::omx_cmd_queue::get_q_msg_type()
{
return m_q[m_read].id;
}
#ifdef _ANDROID_
VideoHeap::VideoHeap(int fd, size_t size, void* base)
{
// dup file descriptor, map once, use pmem
init(dup(fd), base, size, 0 , MEM_DEVICE);
}
#endif // _ANDROID_
/* ======================================================================
FUNCTION
omx_venc::omx_venc
DESCRIPTION
Constructor
PARAMETERS
None
RETURN VALUE
None.
========================================================================== */
omx_video::omx_video():
c2d_opened(false),
psource_frame(NULL),
pdest_frame(NULL),
secure_session(false),
mEmptyEosBuffer(NULL),
m_pipe_in(-1),
m_pipe_out(-1),
m_pInput_pmem(NULL),
m_pOutput_pmem(NULL),
#ifdef USE_ION
m_pInput_ion(NULL),
m_pOutput_ion(NULL),
#endif
m_error_propogated(false),
m_state(OMX_StateInvalid),
m_app_data(NULL),
m_use_input_pmem(OMX_FALSE),
m_use_output_pmem(OMX_FALSE),
m_input_msg_id(OMX_COMPONENT_GENERATE_ETB),
m_inp_mem_ptr(NULL),
m_out_mem_ptr(NULL),
input_flush_progress (false),
output_flush_progress (false),
input_use_buffer (false),
output_use_buffer (false),
pending_input_buffers(0),
pending_output_buffers(0),
m_out_bm_count(0),
m_inp_bm_count(0),
m_flags(0),
m_etb_count(0),
m_fbd_count(0),
m_event_port_settings_sent(false),
hw_overload(false)
{
DEBUG_PRINT_HIGH("omx_video(): Inside Constructor()");
memset(&m_cmp,0,sizeof(m_cmp));
memset(&m_pCallbacks,0,sizeof(m_pCallbacks));
async_thread_created = false;
msg_thread_created = false;
mUsesColorConversion = false;
pthread_mutex_init(&m_lock, NULL);
sem_init(&m_cmd_lock,0,0);
DEBUG_PRINT_LOW("meta_buffer_hdr = %p", meta_buffer_hdr);
}
/* ======================================================================
FUNCTION
omx_venc::~omx_venc
DESCRIPTION
Destructor
PARAMETERS
None
RETURN VALUE
None.
========================================================================== */
omx_video::~omx_video()
{
DEBUG_PRINT_HIGH("~omx_video(): Inside Destructor()");
if (m_pipe_in >= 0) close(m_pipe_in);
if (m_pipe_out >= 0) close(m_pipe_out);
DEBUG_PRINT_HIGH("omx_video: Waiting on Msg Thread exit");
if (msg_thread_created)
pthread_join(msg_thread_id,NULL);
DEBUG_PRINT_HIGH("omx_video: Waiting on Async Thread exit");
/*For V4L2 based drivers, pthread_join is done in device_close
* so no need to do it here*/
#ifndef _MSM8974_
if (async_thread_created)
pthread_join(async_thread_id,NULL);
#endif
pthread_mutex_destroy(&m_lock);
sem_destroy(&m_cmd_lock);
DEBUG_PRINT_HIGH("m_etb_count = %" PRIu64 ", m_fbd_count = %" PRIu64, m_etb_count,
m_fbd_count);
DEBUG_PRINT_HIGH("omx_video: Destructor exit");
DEBUG_PRINT_HIGH("Exiting OMX Video Encoder ...");
}
/* ======================================================================
FUNCTION
omx_venc::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_video::process_event_cb(void *ctxt, unsigned char id)
{
unsigned long p1; // Parameter - 1
unsigned long p2; // Parameter - 2
unsigned long ident;
unsigned qsize=0; // qsize
omx_video *pThis = (omx_video *) ctxt;
if (!pThis) {
DEBUG_PRINT_ERROR("ERROR:ProcessMsgCb:Context is incorrect; bailing out");
return;
}
// Protect the shared queue data structure
do {
/*Read the message id's from the queue*/
pthread_mutex_lock(&pThis->m_lock);
qsize = pThis->m_cmd_q.m_size;
if (qsize) {
pThis->m_cmd_q.pop_entry(&p1,&p2,&ident);
}
if (qsize == 0) {
qsize = pThis->m_ftb_q.m_size;
if (qsize) {
pThis->m_ftb_q.pop_entry(&p1,&p2,&ident);
}
}
if (qsize == 0) {
qsize = pThis->m_etb_q.m_size;
if (qsize) {
pThis->m_etb_q.pop_entry(&p1,&p2,&ident);
}
}
pthread_mutex_unlock(&pThis->m_lock);
/*process message if we have one*/
if (qsize > 0) {
id = ident;
switch (id) {
case OMX_COMPONENT_GENERATE_EVENT:
if (pThis->m_pCallbacks.EventHandler) {
switch (p1) {
case OMX_CommandStateSet:
pThis->m_state = (OMX_STATETYPE) p2;
DEBUG_PRINT_LOW("Process -> state set to %d", pThis->m_state);
pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
OMX_EventCmdComplete, p1, p2, NULL);
break;
case OMX_EventError:
DEBUG_PRINT_ERROR("ERROR: OMX_EventError: p2 = %lu", p2);
if (p2 == (unsigned)OMX_ErrorHardware) {
pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
OMX_EventError,OMX_ErrorHardware,0,NULL);
} else {
pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
OMX_EventError, p2, 0, 0);
}
break;
case OMX_CommandPortDisable:
DEBUG_PRINT_LOW("Process -> Port %lu set to PORT_STATE_DISABLED" \
"state", p2);
pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
OMX_EventCmdComplete, p1, p2, NULL );
break;
case OMX_CommandPortEnable:
DEBUG_PRINT_LOW("Process ->Port %lu set PORT_STATE_ENABLED state" \
, p2);
pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,\
OMX_EventCmdComplete, p1, p2, NULL );
break;
default:
DEBUG_PRINT_LOW("process_event_cb forwarding EventCmdComplete %lu", p1);
pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
OMX_EventCmdComplete, p1, p2, NULL );
break;
}
} else {
DEBUG_PRINT_ERROR("ERROR: ProcessMsgCb NULL callbacks");
}
break;
case OMX_COMPONENT_GENERATE_ETB_OPQ:
DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_ETB_OPQ");
if (pThis->empty_this_buffer_opaque((OMX_HANDLETYPE)p1,\
(OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
DEBUG_PRINT_ERROR("ERROR: ETBProxy() failed!");
pThis->omx_report_error ();
}
break;
case OMX_COMPONENT_GENERATE_ETB: {
OMX_ERRORTYPE iret;
DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_ETB");
iret = pThis->empty_this_buffer_proxy((OMX_HANDLETYPE)p1, (OMX_BUFFERHEADERTYPE *)p2);
if (iret == OMX_ErrorInsufficientResources) {
DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure due to HW overload");
pThis->omx_report_hw_overload ();
} else if (iret != OMX_ErrorNone) {
DEBUG_PRINT_ERROR("empty_this_buffer_proxy failure");
pThis->omx_report_error ();
}
}
break;
case OMX_COMPONENT_GENERATE_FTB:
if ( pThis->fill_this_buffer_proxy((OMX_HANDLETYPE)p1,\
(OMX_BUFFERHEADERTYPE *)p2) != OMX_ErrorNone) {
DEBUG_PRINT_ERROR("ERROR: FTBProxy() failed!");
pThis->omx_report_error ();
}
break;
case OMX_COMPONENT_GENERATE_COMMAND:
pThis->send_command_proxy(&pThis->m_cmp,(OMX_COMMANDTYPE)p1,\
(OMX_U32)p2,(OMX_PTR)NULL);
break;
case OMX_COMPONENT_GENERATE_EBD:
if ( pThis->empty_buffer_done(&pThis->m_cmp,
(OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone) {
DEBUG_PRINT_ERROR("ERROR: empty_buffer_done() failed!");
pThis->omx_report_error ();
}
break;
case OMX_COMPONENT_GENERATE_FBD:
if ( pThis->fill_buffer_done(&pThis->m_cmp,
(OMX_BUFFERHEADERTYPE *)p1) != OMX_ErrorNone ) {
DEBUG_PRINT_ERROR("ERROR: fill_buffer_done() failed!");
pThis->omx_report_error ();
}
break;
case OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH:
pThis->input_flush_progress = false;
DEBUG_PRINT_HIGH("m_etb_count at i/p flush = %" PRIu64, m_etb_count);
m_etb_count = 0;
if (pThis->m_pCallbacks.EventHandler) {
/*Check if we need generate event for Flush done*/
if (BITMASK_PRESENT(&pThis->m_flags,
OMX_COMPONENT_INPUT_FLUSH_PENDING)) {
BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_INPUT_FLUSH_PENDING);
pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
OMX_EventCmdComplete,OMX_CommandFlush,
PORT_INDEX_IN,NULL );
} else if (BITMASK_PRESENT(&pThis->m_flags,
OMX_COMPONENT_IDLE_PENDING)) {
if (!pThis->output_flush_progress) {
DEBUG_PRINT_LOW("dev_stop called after input flush complete");
if (dev_stop() != 0) {
DEBUG_PRINT_ERROR("ERROR: dev_stop() failed in i/p flush!");
pThis->omx_report_error ();
}
}
}
}
break;
case OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH:
pThis->output_flush_progress = false;
DEBUG_PRINT_HIGH("m_fbd_count at o/p flush = %" PRIu64, m_fbd_count);
m_fbd_count = 0;
if (pThis->m_pCallbacks.EventHandler) {
/*Check if we need generate event for Flush done*/
if (BITMASK_PRESENT(&pThis->m_flags,
OMX_COMPONENT_OUTPUT_FLUSH_PENDING)) {
BITMASK_CLEAR (&pThis->m_flags,OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
OMX_EventCmdComplete,OMX_CommandFlush,
PORT_INDEX_OUT,NULL );
} else if (BITMASK_PRESENT(&pThis->m_flags ,OMX_COMPONENT_IDLE_PENDING)) {
DEBUG_PRINT_LOW("dev_stop called after Output flush complete");
if (!pThis->input_flush_progress) {
if (dev_stop() != 0) {
DEBUG_PRINT_ERROR("ERROR: dev_stop() failed in o/p flush!");
pThis->omx_report_error ();
}
}
}
}
break;
case OMX_COMPONENT_GENERATE_START_DONE:
DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_START_DONE msg");
if (pThis->m_pCallbacks.EventHandler) {
DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_START_DONE Success");
if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_START_DONE Move to \
executing");
// Send the callback now
BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
pThis->m_state = OMX_StateExecuting;
pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
OMX_EventCmdComplete,OMX_CommandStateSet,
OMX_StateExecuting, NULL);
} else if (BITMASK_PRESENT(&pThis->m_flags,
OMX_COMPONENT_PAUSE_PENDING)) {
if (dev_pause()) {
DEBUG_PRINT_ERROR("ERROR: dev_pause() failed in Start Done!");
pThis->omx_report_error ();
}
} else if (BITMASK_PRESENT(&pThis->m_flags,
OMX_COMPONENT_LOADED_START_PENDING)) {
if (dev_loaded_start_done()) {
DEBUG_PRINT_LOW("successful loaded Start Done!");
} else {
DEBUG_PRINT_ERROR("ERROR: failed in loaded Start Done!");
pThis->omx_report_error ();
}
BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_LOADED_START_PENDING);
} else {
DEBUG_PRINT_LOW("ERROR: unknown flags=%" PRIx64, pThis->m_flags);
}
} else {
DEBUG_PRINT_LOW("Event Handler callback is NULL");
}
break;
case OMX_COMPONENT_GENERATE_PAUSE_DONE:
DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_PAUSE_DONE msg");
if (pThis->m_pCallbacks.EventHandler) {
if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_PAUSE_PENDING)) {
//Send the callback now
pThis->complete_pending_buffer_done_cbs();
DEBUG_PRINT_LOW("omx_video::process_event_cb() Sending PAUSE complete after all pending EBD/FBD");
BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_PAUSE_PENDING);
pThis->m_state = OMX_StatePause;
pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
OMX_EventCmdComplete,OMX_CommandStateSet,
OMX_StatePause, NULL);
}
}
break;
case OMX_COMPONENT_GENERATE_RESUME_DONE:
DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_RESUME_DONE msg");
if (pThis->m_pCallbacks.EventHandler) {
if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_EXECUTE_PENDING)) {
// Send the callback now
BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_EXECUTE_PENDING);
pThis->m_state = OMX_StateExecuting;
pThis->m_pCallbacks.EventHandler(&pThis->m_cmp, pThis->m_app_data,
OMX_EventCmdComplete,OMX_CommandStateSet,
OMX_StateExecuting,NULL);
}
}
break;
case OMX_COMPONENT_GENERATE_STOP_DONE:
DEBUG_PRINT_LOW("OMX_COMPONENT_GENERATE_STOP_DONE msg");
if (pThis->m_pCallbacks.EventHandler) {
pThis->complete_pending_buffer_done_cbs();
if (BITMASK_PRESENT(&pThis->m_flags,OMX_COMPONENT_IDLE_PENDING)) {
// Send the callback now
BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_IDLE_PENDING);
pThis->m_state = OMX_StateIdle;
pThis->m_pCallbacks.EventHandler(&pThis->m_cmp,pThis->m_app_data,
OMX_EventCmdComplete,OMX_CommandStateSet,
OMX_StateIdle,NULL);
} else if (BITMASK_PRESENT(&pThis->m_flags,
OMX_COMPONENT_LOADED_STOP_PENDING)) {
if (dev_loaded_stop_done()) {
DEBUG_PRINT_LOW("successful loaded Stop Done!");
} else {
DEBUG_PRINT_ERROR("ERROR: failed in loaded Stop Done!");
pThis->omx_report_error ();
}
BITMASK_CLEAR((&pThis->m_flags),OMX_COMPONENT_LOADED_STOP_PENDING);
} else {
DEBUG_PRINT_LOW("ERROR: unknown flags=%" PRIx64, pThis->m_flags);
}
}
break;
case OMX_COMPONENT_GENERATE_HARDWARE_ERROR:
DEBUG_PRINT_ERROR("ERROR: OMX_COMPONENT_GENERATE_HARDWARE_ERROR!");
pThis->omx_report_error ();
break;
#ifndef _MSM8974_
case OMX_COMPONENT_GENERATE_LTRUSE_FAILED:
DEBUG_PRINT_ERROR("ERROR: OMX_COMPONENT_GENERATE_LTRUSE_FAILED!");
if (pThis->m_pCallbacks.EventHandler) {
DEBUG_PRINT_ERROR("Sending QOMX_ErrorLTRUseFailed, p2 = 0x%x", p2);
pThis->m_pCallbacks.EventHandler(
&pThis->m_cmp, pThis->m_app_data,
OMX_EventError, QOMX_ErrorLTRUseFailed, NULL, NULL);
}
break;
#endif
default:
DEBUG_PRINT_LOW("process_event_cb unknown msg id 0x%02x", id);
break;
}
}
pthread_mutex_lock(&pThis->m_lock);
qsize = pThis->m_cmd_q.m_size + pThis->m_ftb_q.m_size +\
pThis->m_etb_q.m_size;
pthread_mutex_unlock(&pThis->m_lock);
} while (qsize>0);
DEBUG_PRINT_LOW("exited the while loop");
}
/* ======================================================================
FUNCTION
omx_venc::GetComponentVersion
DESCRIPTION
Returns the component version.
PARAMETERS
TBD.
RETURN VALUE
OMX_ErrorNone.
========================================================================== */
OMX_ERRORTYPE omx_video::get_component_version
(
OMX_IN OMX_HANDLETYPE hComp,
OMX_OUT OMX_STRING componentName,
OMX_OUT OMX_VERSIONTYPE* componentVersion,
OMX_OUT OMX_VERSIONTYPE* specVersion,
OMX_OUT OMX_UUIDTYPE* componentUUID
)
{
(void)hComp;
(void)componentName;
(void)componentVersion;
(void)componentUUID;
if (m_state == OMX_StateInvalid) {
DEBUG_PRINT_ERROR("ERROR: Get Comp Version in Invalid State");
return OMX_ErrorInvalidState;
}
/* TBD -- Return the proper version */
if (specVersion) {
specVersion->nVersion = OMX_SPEC_VERSION;
}
return OMX_ErrorNone;
}
/* ======================================================================
FUNCTION
omx_venc::SendCommand
DESCRIPTION
Returns zero if all the buffers released..
PARAMETERS
None.
RETURN VALUE
true/false
========================================================================== */
OMX_ERRORTYPE omx_video::send_command(OMX_IN OMX_HANDLETYPE hComp,
OMX_IN OMX_COMMANDTYPE cmd,
OMX_IN OMX_U32 param1,
OMX_IN OMX_PTR cmdData
)
{
(void)hComp;
if (m_state == OMX_StateInvalid) {
DEBUG_PRINT_ERROR("ERROR: Send Command in Invalid State");
return OMX_ErrorInvalidState;
}
if (cmd == OMX_CommandFlush || cmd == OMX_CommandPortDisable || cmd == OMX_CommandPortEnable) {
if ((param1 != (OMX_U32)PORT_INDEX_IN) && (param1 != (OMX_U32)PORT_INDEX_OUT) && (param1 != (OMX_U32)PORT_INDEX_BOTH)) {
DEBUG_PRINT_ERROR("ERROR: omx_video::send_command-->bad port index");
return OMX_ErrorBadPortIndex;
}
}
if (cmd == OMX_CommandMarkBuffer) {
if (param1 != PORT_INDEX_IN) {
DEBUG_PRINT_ERROR("ERROR: omx_video::send_command-->bad port index");
return OMX_ErrorBadPortIndex;
}
if (!cmdData) {
DEBUG_PRINT_ERROR("ERROR: omx_video::send_command-->param is null");
return OMX_ErrorBadParameter;
}
}
post_event((unsigned long)cmd,(unsigned long)param1,OMX_COMPONENT_GENERATE_COMMAND);
sem_wait(&m_cmd_lock);
return OMX_ErrorNone;
}
/* ======================================================================
FUNCTION
omx_venc::SendCommand
DESCRIPTION
Returns zero if all the buffers released..
PARAMETERS
None.
RETURN VALUE
true/false
========================================================================== */
OMX_ERRORTYPE omx_video::send_command_proxy(OMX_IN OMX_HANDLETYPE hComp,
OMX_IN OMX_COMMANDTYPE cmd,
OMX_IN OMX_U32 param1,
OMX_IN OMX_PTR cmdData
)
{
(void)hComp;
(void)cmdData;
OMX_ERRORTYPE eRet = OMX_ErrorNone;
OMX_STATETYPE eState = (OMX_STATETYPE) param1;
int bFlag = 1;
if (cmd == OMX_CommandStateSet) {
/***************************/
/* Current State is Loaded */
/***************************/
if (m_state == OMX_StateLoaded) {
if (eState == OMX_StateIdle) {
//if all buffers are allocated or all ports disabled
if (allocate_done() ||
( m_sInPortDef.bEnabled == OMX_FALSE && m_sOutPortDef.bEnabled == OMX_FALSE)) {
DEBUG_PRINT_LOW("OMXCORE-SM: Loaded-->Idle");
} else {
DEBUG_PRINT_LOW("OMXCORE-SM: Loaded-->Idle-Pending");
BITMASK_SET(&m_flags, OMX_COMPONENT_IDLE_PENDING);
// Skip the event notification
bFlag = 0;
}
}
/* Requesting transition from Loaded to Loaded */
else if (eState == OMX_StateLoaded) {
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Loaded");
post_event(OMX_EventError,OMX_ErrorSameState,\
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorSameState;
}
/* Requesting transition from Loaded to WaitForResources */
else if (eState == OMX_StateWaitForResources) {
/* Since error is None , we will post an event
at the end of this function definition */
DEBUG_PRINT_LOW("OMXCORE-SM: Loaded-->WaitForResources");
}
/* Requesting transition from Loaded to Executing */
else if (eState == OMX_StateExecuting) {
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Executing");
post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorIncorrectStateTransition;
}
/* Requesting transition from Loaded to Pause */
else if (eState == OMX_StatePause) {
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Pause");
post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorIncorrectStateTransition;
}
/* Requesting transition from Loaded to Invalid */
else if (eState == OMX_StateInvalid) {
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->Invalid");
post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorInvalidState;
} else {
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Loaded-->%d Not Handled",\
eState);
eRet = OMX_ErrorBadParameter;
}
}
/***************************/
/* Current State is IDLE */
/***************************/
else if (m_state == OMX_StateIdle) {
if (eState == OMX_StateLoaded) {
if (release_done()) {
/*
Since error is None , we will post an event at the end
of this function definition
*/
DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Loaded");
if (dev_stop() != 0) {
DEBUG_PRINT_ERROR("ERROR: dev_stop() failed at Idle --> Loaded");
eRet = OMX_ErrorHardware;
}
} else {
DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Loaded-Pending");
BITMASK_SET(&m_flags, OMX_COMPONENT_LOADING_PENDING);
// Skip the event notification
bFlag = 0;
}
}
/* Requesting transition from Idle to Executing */
else if (eState == OMX_StateExecuting) {
if ( dev_start() ) {
DEBUG_PRINT_ERROR("ERROR: dev_start() failed in SCP on Idle --> Exe");
omx_report_error ();
eRet = OMX_ErrorHardware;
} else {
BITMASK_SET(&m_flags,OMX_COMPONENT_EXECUTE_PENDING);
DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Executing");
bFlag = 0;
}
dev_start_done();
}
/* Requesting transition from Idle to Idle */
else if (eState == OMX_StateIdle) {
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle-->Idle");
post_event(OMX_EventError,OMX_ErrorSameState,\
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorSameState;
}
/* Requesting transition from Idle to WaitForResources */
else if (eState == OMX_StateWaitForResources) {
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle-->WaitForResources");
post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorIncorrectStateTransition;
}
/* Requesting transition from Idle to Pause */
else if (eState == OMX_StatePause) {
/*To pause the Video core we need to start the driver*/
if ( dev_start() ) {
DEBUG_PRINT_ERROR("ERROR: dev_start() failed in SCP on Idle --> Pause");
omx_report_error ();
eRet = OMX_ErrorHardware;
} else {
BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING);
DEBUG_PRINT_LOW("OMXCORE-SM: Idle-->Pause");
bFlag = 0;
}
}
/* Requesting transition from Idle to Invalid */
else if (eState == OMX_StateInvalid) {
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle-->Invalid");
post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorInvalidState;
} else {
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Idle --> %d Not Handled",eState);
eRet = OMX_ErrorBadParameter;
}
}
/******************************/
/* Current State is Executing */
/******************************/
else if (m_state == OMX_StateExecuting) {
/* Requesting transition from Executing to Idle */
if (eState == OMX_StateIdle) {
/* Since error is None , we will post an event
at the end of this function definition
*/
DEBUG_PRINT_LOW("OMXCORE-SM: Executing --> Idle");
//here this should be Pause-Idle pending and should be cleared when flush is complete and change the state to Idle
BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
execute_omx_flush(OMX_ALL);
bFlag = 0;
}
/* Requesting transition from Executing to Paused */
else if (eState == OMX_StatePause) {
if (dev_pause()) {
DEBUG_PRINT_ERROR("ERROR: dev_pause() failed in SCP on Exe --> Pause");
post_event(OMX_EventError,OMX_ErrorHardware,\
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorHardware;
} else {
BITMASK_SET(&m_flags,OMX_COMPONENT_PAUSE_PENDING);
DEBUG_PRINT_LOW("OMXCORE-SM: Executing-->Pause");
bFlag = 0;
}
}
/* Requesting transition from Executing to Loaded */
else if (eState == OMX_StateLoaded) {
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Executing --> Loaded");
post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorIncorrectStateTransition;
}
/* Requesting transition from Executing to WaitForResources */
else if (eState == OMX_StateWaitForResources) {
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Executing --> WaitForResources");
post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorIncorrectStateTransition;
}
/* Requesting transition from Executing to Executing */
else if (eState == OMX_StateExecuting) {
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Executing --> Executing");
post_event(OMX_EventError,OMX_ErrorSameState,\
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorSameState;
}
/* Requesting transition from Executing to Invalid */
else if (eState == OMX_StateInvalid) {
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Executing --> Invalid");
post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorInvalidState;
} else {
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Executing --> %d Not Handled",eState);
eRet = OMX_ErrorBadParameter;
}
}
/***************************/
/* Current State is Pause */
/***************************/
else if (m_state == OMX_StatePause) {
/* Requesting transition from Pause to Executing */
if (eState == OMX_StateExecuting) {
DEBUG_PRINT_LOW("Pause --> Executing");
if ( dev_resume() ) {
post_event(OMX_EventError,OMX_ErrorHardware,\
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorHardware;
} else {
BITMASK_SET(&m_flags,OMX_COMPONENT_EXECUTE_PENDING);
DEBUG_PRINT_LOW("OMXCORE-SM: Pause-->Executing");
post_event (0, 0, OMX_COMPONENT_GENERATE_RESUME_DONE);
bFlag = 0;
}
}
/* Requesting transition from Pause to Idle */
else if (eState == OMX_StateIdle) {
/* Since error is None , we will post an event
at the end of this function definition */
DEBUG_PRINT_LOW("Pause --> Idle");
BITMASK_SET(&m_flags,OMX_COMPONENT_IDLE_PENDING);
execute_omx_flush(OMX_ALL);
bFlag = 0;
}
/* Requesting transition from Pause to loaded */
else if (eState == OMX_StateLoaded) {
DEBUG_PRINT_ERROR("ERROR: Pause --> loaded");
post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorIncorrectStateTransition;
}
/* Requesting transition from Pause to WaitForResources */
else if (eState == OMX_StateWaitForResources) {
DEBUG_PRINT_ERROR("ERROR: Pause --> WaitForResources");
post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorIncorrectStateTransition;
}
/* Requesting transition from Pause to Pause */
else if (eState == OMX_StatePause) {
DEBUG_PRINT_ERROR("ERROR: Pause --> Pause");
post_event(OMX_EventError,OMX_ErrorSameState,\
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorSameState;
}
/* Requesting transition from Pause to Invalid */
else if (eState == OMX_StateInvalid) {
DEBUG_PRINT_ERROR("ERROR: Pause --> Invalid");
post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorInvalidState;
} else {
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Paused --> %d Not Handled",eState);
eRet = OMX_ErrorBadParameter;
}
}
/***************************/
/* Current State is WaitForResources */
/***************************/
else if (m_state == OMX_StateWaitForResources) {
/* Requesting transition from WaitForResources to Loaded */
if (eState == OMX_StateLoaded) {
/* Since error is None , we will post an event
at the end of this function definition */
DEBUG_PRINT_LOW("OMXCORE-SM: WaitForResources-->Loaded");
}
/* Requesting transition from WaitForResources to WaitForResources */
else if (eState == OMX_StateWaitForResources) {
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: WaitForResources-->WaitForResources");
post_event(OMX_EventError,OMX_ErrorSameState,
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorSameState;
}
/* Requesting transition from WaitForResources to Executing */
else if (eState == OMX_StateExecuting) {
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: WaitForResources-->Executing");
post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorIncorrectStateTransition;
}
/* Requesting transition from WaitForResources to Pause */
else if (eState == OMX_StatePause) {
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: WaitForResources-->Pause");
post_event(OMX_EventError,OMX_ErrorIncorrectStateTransition,\
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorIncorrectStateTransition;
}
/* Requesting transition from WaitForResources to Invalid */
else if (eState == OMX_StateInvalid) {
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: WaitForResources-->Invalid");
post_event(OMX_EventError,eState,OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorInvalidState;
}
/* Requesting transition from WaitForResources to Loaded -
is NOT tested by Khronos TS */
} else {
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: %d --> %d(Not Handled)",m_state,eState);
eRet = OMX_ErrorBadParameter;
}
}
/********************************/
/* Current State is Invalid */
/*******************************/
else if (m_state == OMX_StateInvalid) {
/* State Transition from Inavlid to any state */
if (eState == (OMX_StateLoaded || OMX_StateWaitForResources
|| OMX_StateIdle || OMX_StateExecuting
|| OMX_StatePause || OMX_StateInvalid)) {
DEBUG_PRINT_ERROR("ERROR: OMXCORE-SM: Invalid -->Loaded");
post_event(OMX_EventError,OMX_ErrorInvalidState,\
OMX_COMPONENT_GENERATE_EVENT);
eRet = OMX_ErrorInvalidState;
}
} else if (cmd == OMX_CommandFlush) {
if (0 == param1 || OMX_ALL == param1) {
BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_FLUSH_PENDING);
}
if (1 == param1 || OMX_ALL == param1) {
//generate output flush event only.
BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_FLUSH_PENDING);
}
execute_omx_flush(param1);
bFlag = 0;
} else if ( cmd == OMX_CommandPortEnable) {
if (param1 == PORT_INDEX_IN || param1 == OMX_ALL) {
m_sInPortDef.bEnabled = OMX_TRUE;
if ( (m_state == OMX_StateLoaded &&
!BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
|| allocate_input_done()) {
post_event(OMX_CommandPortEnable,PORT_INDEX_IN,
OMX_COMPONENT_GENERATE_EVENT);
} else {
DEBUG_PRINT_LOW("OMXCORE-SM: Disabled-->Enabled Pending");
BITMASK_SET(&m_flags, OMX_COMPONENT_INPUT_ENABLE_PENDING);
// Skip the event notification
bFlag = 0;
}
}
if (param1 == PORT_INDEX_OUT || param1 == OMX_ALL) {
m_sOutPortDef.bEnabled = OMX_TRUE;
if ( (m_state == OMX_StateLoaded &&
!BITMASK_PRESENT(&m_flags,OMX_COMPONENT_IDLE_PENDING))
|| (allocate_output_done())) {
post_event(OMX_CommandPortEnable,PORT_INDEX_OUT,
OMX_COMPONENT_GENERATE_EVENT);
} else {
DEBUG_PRINT_LOW("OMXCORE-SM: Disabled-->Enabled Pending");
BITMASK_SET(&m_flags, OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
// Skip the event notification
bFlag = 0;
}
}
} else if (cmd == OMX_CommandPortDisable) {
if (param1 == PORT_INDEX_IN || param1 == OMX_ALL) {
m_sInPortDef.bEnabled = OMX_FALSE;
if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
&& release_input_done()) {
post_event(OMX_CommandPortDisable,PORT_INDEX_IN,
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(PORT_INDEX_IN);
}
// Skip the event notification
bFlag = 0;
}
}
if (param1 == PORT_INDEX_OUT || param1 == OMX_ALL) {
m_sOutPortDef.bEnabled = OMX_FALSE;
if ((m_state == OMX_StateLoaded || m_state == OMX_StateIdle)
&& release_output_done()) {
post_event(OMX_CommandPortDisable,PORT_INDEX_OUT,\
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(PORT_INDEX_OUT);
}
// Skip the event notification
bFlag = 0;
}
}
} else {
DEBUG_PRINT_ERROR("ERROR: Invalid Command received other than StateSet (%d)",cmd);
eRet = OMX_ErrorNotImplemented;
}
if (eRet == OMX_ErrorNone && bFlag) {
post_event(cmd,eState,OMX_COMPONENT_GENERATE_EVENT);
}
sem_post(&m_cmd_lock);
return eRet;
}
/* ======================================================================
FUNCTION
omx_venc::ExecuteOmxFlush
DESCRIPTION
Executes the OMX flush.
PARAMETERS
flushtype - input flush(1)/output flush(0)/ both.
RETURN VALUE
true/false
========================================================================== */
bool omx_video::execute_omx_flush(OMX_U32 flushType)
{
bool bRet = false;
DEBUG_PRINT_LOW("execute_omx_flush - %u", (unsigned int)flushType);
#ifdef _MSM8974_
/* XXX: The driver/hardware does not support flushing of individual ports
* in all states. So we pretty much need to flush both ports internally,
* but client should only get the FLUSH_(INPUT|OUTPUT)_DONE for the one it
* requested. Since OMX_COMPONENT_(OUTPUT|INPUT)_FLUSH_PENDING isn't set,
* we automatically omit sending the FLUSH done for the "opposite" port. */
input_flush_progress = true;
output_flush_progress = true;
bRet = execute_flush_all();
#else
if (flushType == 0 || flushType == OMX_ALL) {
input_flush_progress = true;
//flush input only
bRet = execute_input_flush();
}
if (flushType == 1 || flushType == OMX_ALL) {
//flush output only
output_flush_progress = true;
bRet = execute_output_flush();
}
#endif
return bRet;
}
/*=========================================================================
FUNCTION : execute_output_flush
DESCRIPTION
Executes the OMX flush at OUTPUT PORT.
PARAMETERS
None.
RETURN VALUE
true/false
==========================================================================*/
bool omx_video::execute_output_flush(void)
{
unsigned long p1 = 0; // Parameter - 1
unsigned long p2 = 0; // Parameter - 2
unsigned long ident = 0;
bool bRet = true;
/*Generate FBD for all Buffers in the FTBq*/
DEBUG_PRINT_LOW("execute_output_flush");
pthread_mutex_lock(&m_lock);
while (m_ftb_q.m_size) {
m_ftb_q.pop_entry(&p1,&p2,&ident);
if (ident == OMX_COMPONENT_GENERATE_FTB ) {
pending_output_buffers++;
fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
} else if (ident == OMX_COMPONENT_GENERATE_FBD) {
fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
}
}
pthread_mutex_unlock(&m_lock);
/*Check if there are buffers with the Driver*/
if (dev_flush(PORT_INDEX_OUT)) {
DEBUG_PRINT_ERROR("ERROR: o/p dev_flush() Failed");
return false;
}
return bRet;
}
/*=========================================================================
FUNCTION : execute_input_flush
DESCRIPTION
Executes the OMX flush at INPUT PORT.
PARAMETERS
None.
RETURN VALUE
true/false
==========================================================================*/
bool omx_video::execute_input_flush(void)
{
unsigned long p1 = 0; // Parameter - 1
unsigned long p2 = 0; // Parameter - 2
unsigned long ident = 0;
bool bRet = true;
/*Generate EBD for all Buffers in the ETBq*/
DEBUG_PRINT_LOW("execute_input_flush");
pthread_mutex_lock(&m_lock);
while (m_etb_q.m_size) {
m_etb_q.pop_entry(&p1,&p2,&ident);
if (ident == OMX_COMPONENT_GENERATE_ETB) {
pending_input_buffers++;
empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
} else if (ident == OMX_COMPONENT_GENERATE_EBD) {
empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
} else if (ident == OMX_COMPONENT_GENERATE_ETB_OPQ) {
m_pCallbacks.EmptyBufferDone(&m_cmp,m_app_data,(OMX_BUFFERHEADERTYPE *)p2);
}
}
if (mUseProxyColorFormat) {
if (psource_frame) {
m_pCallbacks.EmptyBufferDone(&m_cmp,m_app_data,psource_frame);
psource_frame = NULL;
}
while (m_opq_meta_q.m_size) {
unsigned long p1,p2,id;
m_opq_meta_q.pop_entry(&p1,&p2,&id);
m_pCallbacks.EmptyBufferDone(&m_cmp,m_app_data,
(OMX_BUFFERHEADERTYPE *)p1);
}
if (pdest_frame) {
m_opq_pmem_q.insert_entry((unsigned long)pdest_frame,0,0);
pdest_frame = NULL;
}
}
pthread_mutex_unlock(&m_lock);
/*Check if there are buffers with the Driver*/
if (dev_flush(PORT_INDEX_IN)) {
DEBUG_PRINT_ERROR("ERROR: i/p dev_flush() Failed");
return false;
}
return bRet;
}
/*=========================================================================
FUNCTION : execute_flush
DESCRIPTION
Executes the OMX flush at INPUT & OUTPUT PORT.
PARAMETERS
None.
RETURN VALUE
true/false
==========================================================================*/
#ifdef _MSM8974_
bool omx_video::execute_flush_all(void)
{
unsigned long p1 = 0; // Parameter - 1
unsigned long p2 = 0; // Parameter - 2
unsigned long ident = 0;
bool bRet = true;
DEBUG_PRINT_LOW("execute_flush_all");
/*Generate EBD for all Buffers in the ETBq*/
pthread_mutex_lock(&m_lock);
while (m_etb_q.m_size) {
m_etb_q.pop_entry(&p1,&p2,&ident);
if (ident == OMX_COMPONENT_GENERATE_ETB) {
pending_input_buffers++;
empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
} else if (ident == OMX_COMPONENT_GENERATE_EBD) {
empty_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
} else if(ident == OMX_COMPONENT_GENERATE_ETB_OPQ) {
m_pCallbacks.EmptyBufferDone(&m_cmp,m_app_data,(OMX_BUFFERHEADERTYPE *)p2);
}
}
if(mUseProxyColorFormat) {
if(psource_frame) {
m_pCallbacks.EmptyBufferDone(&m_cmp,m_app_data,psource_frame);
psource_frame = NULL;
}
while(m_opq_meta_q.m_size) {
unsigned long p1,p2,id;
m_opq_meta_q.pop_entry(&p1,&p2,&id);
m_pCallbacks.EmptyBufferDone(&m_cmp,m_app_data,
(OMX_BUFFERHEADERTYPE *)p1);
}
if(pdest_frame){
m_opq_pmem_q.insert_entry((unsigned long)pdest_frame,0,0);
pdest_frame = NULL;
}
}
/*Generate FBD for all Buffers in the FTBq*/
DEBUG_PRINT_LOW("execute_output_flush");
while (m_ftb_q.m_size) {
m_ftb_q.pop_entry(&p1,&p2,&ident);
if (ident == OMX_COMPONENT_GENERATE_FTB ) {
pending_output_buffers++;
fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p2);
} else if (ident == OMX_COMPONENT_GENERATE_FBD) {
fill_buffer_done(&m_cmp,(OMX_BUFFERHEADERTYPE *)p1);
}
}
pthread_mutex_unlock(&m_lock);
/*Check if there are buffers with the Driver*/
if (dev_flush(PORT_INDEX_BOTH)) {
DEBUG_PRINT_ERROR("ERROR: dev_flush() Failed");
return false;
}
return bRet;
}
#endif
/* ======================================================================
FUNCTION
omx_venc::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_video::post_event(unsigned long p1,
unsigned long p2,
unsigned long id)
{
bool bRet = false;
pthread_mutex_lock(&m_lock);
if ((id == OMX_COMPONENT_GENERATE_FTB) ||
(id == OMX_COMPONENT_GENERATE_FBD) ||
(id == OMX_COMPONENT_GENERATE_EVENT_OUTPUT_FLUSH)) {
m_ftb_q.insert_entry(p1,p2,id);
} else if ((id == OMX_COMPONENT_GENERATE_ETB) ||
(id == OMX_COMPONENT_GENERATE_EBD) ||
(id == OMX_COMPONENT_GENERATE_EVENT_INPUT_FLUSH)) {
m_etb_q.insert_entry(p1,p2,id);
} else {
m_cmd_q.insert_entry(p1,p2,id);
}
bRet = true;
DEBUG_PRINT_LOW("Value of this pointer in post_event %p",this);
post_message(this, id);
pthread_mutex_unlock(&m_lock);
return bRet;
}
/* ======================================================================
FUNCTION
omx_venc::GetParameter
DESCRIPTION
OMX Get Parameter method implementation
PARAMETERS
<TBD>.
RETURN VALUE
Error None if successful.
========================================================================== */
OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp,
OMX_IN OMX_INDEXTYPE paramIndex,
OMX_INOUT OMX_PTR paramData)
{
(void)hComp;
OMX_ERRORTYPE eRet = OMX_ErrorNone;
unsigned int height=0,width = 0;
DEBUG_PRINT_LOW("get_parameter:");
if (m_state == OMX_StateInvalid) {
DEBUG_PRINT_ERROR("ERROR: Get Param in Invalid State");
return OMX_ErrorInvalidState;
}
if (paramData == NULL) {
DEBUG_PRINT_ERROR("ERROR: Get Param in Invalid paramData");
return OMX_ErrorBadParameter;
}
switch ((int)paramIndex) {
case OMX_IndexParamPortDefinition:
{
VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_PORTDEFINITIONTYPE);
OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPortDefinition");
if (portDefn->nPortIndex == (OMX_U32) PORT_INDEX_IN) {
dev_get_buf_req (&m_sInPortDef.nBufferCountMin,
&m_sInPortDef.nBufferCountActual,
&m_sInPortDef.nBufferSize,
m_sInPortDef.nPortIndex);
DEBUG_PRINT_LOW("m_sInPortDef: size = %u, min cnt = %u, actual cnt = %u",
(unsigned int)m_sInPortDef.nBufferSize, (unsigned int)m_sInPortDef.nBufferCountMin,
(unsigned int)m_sInPortDef.nBufferCountActual);
memcpy(portDefn, &m_sInPortDef, sizeof(m_sInPortDef));
#ifdef _ANDROID_ICS_
if (meta_mode_enable) {
portDefn->nBufferSize = sizeof(encoder_media_buffer_type);
}
if (mUseProxyColorFormat) {
portDefn->format.video.eColorFormat =
(OMX_COLOR_FORMATTYPE)QOMX_COLOR_FormatAndroidOpaque;
}
#endif
} else if (portDefn->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
if (m_state != OMX_StateExecuting) {
dev_get_buf_req (&m_sOutPortDef.nBufferCountMin,
&m_sOutPortDef.nBufferCountActual,
&m_sOutPortDef.nBufferSize,
m_sOutPortDef.nPortIndex);
}
DEBUG_PRINT_LOW("m_sOutPortDef: size = %u, min cnt = %u, actual cnt = %u",
(unsigned int)m_sOutPortDef.nBufferSize, (unsigned int)m_sOutPortDef.nBufferCountMin,
(unsigned int)m_sOutPortDef.nBufferCountActual);
memcpy(portDefn, &m_sOutPortDef, sizeof(m_sOutPortDef));
} else {
DEBUG_PRINT_ERROR("ERROR: GetParameter called on Bad Port Index");
eRet = OMX_ErrorBadPortIndex;
}
break;
}
case OMX_IndexParamVideoInit:
{
VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
OMX_PORT_PARAM_TYPE *portParamType =
(OMX_PORT_PARAM_TYPE *) paramData;
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoInit");
memcpy(portParamType, &m_sPortParam, sizeof(m_sPortParam));
break;
}
case OMX_IndexParamVideoPortFormat:
{
VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PORTFORMATTYPE);
OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt =
(OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoPortFormat");
if (portFmt->nPortIndex == (OMX_U32) PORT_INDEX_IN) {
unsigned index = portFmt->nIndex;
//we support two formats
//index 0 - Venus flavour of YUV420SP
//index 1 - opaque which internally maps to YUV420SP.
//index 2 - vannilla YUV420SP
//this can be extended in the future
int supportedFormats[] = {
[0] = QOMX_COLOR_FORMATYUV420PackedSemiPlanar32m,
[1] = QOMX_COLOR_FormatAndroidOpaque,
[2] = OMX_COLOR_FormatYUV420SemiPlanar,
};
if (index > (sizeof(supportedFormats)/sizeof(*supportedFormats) - 1))
eRet = OMX_ErrorNoMore;
else {
memcpy(portFmt, &m_sInPortFormat, sizeof(m_sInPortFormat));
portFmt->nIndex = index; //restore index set from client
portFmt->eColorFormat = (OMX_COLOR_FORMATTYPE)supportedFormats[index];
}
} else if (portFmt->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
memcpy(portFmt, &m_sOutPortFormat, sizeof(m_sOutPortFormat));
} else {
DEBUG_PRINT_ERROR("ERROR: GetParameter called on Bad Port Index");
eRet = OMX_ErrorBadPortIndex;
}
break;
}
case OMX_IndexParamVideoBitrate:
{
VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_BITRATETYPE);
OMX_VIDEO_PARAM_BITRATETYPE* pParam = (OMX_VIDEO_PARAM_BITRATETYPE*)paramData;
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoBitrate");
if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
memcpy(pParam, &m_sParamBitrate, sizeof(m_sParamBitrate));
} else {
DEBUG_PRINT_ERROR("ERROR: GetParameter called on Bad Port Index");
eRet = OMX_ErrorBadPortIndex;
}
break;
}
case OMX_IndexParamVideoMpeg4:
{
VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_MPEG4TYPE);
OMX_VIDEO_PARAM_MPEG4TYPE* pParam = (OMX_VIDEO_PARAM_MPEG4TYPE*)paramData;
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoMpeg4");
memcpy(pParam, &m_sParamMPEG4, sizeof(m_sParamMPEG4));
break;
}
case OMX_IndexParamVideoH263:
{
VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_H263TYPE);
OMX_VIDEO_PARAM_H263TYPE* pParam = (OMX_VIDEO_PARAM_H263TYPE*)paramData;
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoH263");
memcpy(pParam, &m_sParamH263, sizeof(m_sParamH263));
break;
}
case OMX_IndexParamVideoAvc:
{
VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_AVCTYPE);
OMX_VIDEO_PARAM_AVCTYPE* pParam = (OMX_VIDEO_PARAM_AVCTYPE*)paramData;
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoAvc");
memcpy(pParam, &m_sParamAVC, sizeof(m_sParamAVC));
break;
}
case (OMX_INDEXTYPE)OMX_IndexParamVideoVp8:
{
VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_VP8TYPE);
OMX_VIDEO_PARAM_VP8TYPE* pParam = (OMX_VIDEO_PARAM_VP8TYPE*)paramData;
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoVp8");
memcpy(pParam, &m_sParamVP8, sizeof(m_sParamVP8));
break;
}
case (OMX_INDEXTYPE)OMX_IndexParamVideoHevc:
{
VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_HEVCTYPE);
OMX_VIDEO_PARAM_HEVCTYPE* pParam = (OMX_VIDEO_PARAM_HEVCTYPE*)paramData;
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoHevc");
memcpy(pParam, &m_sParamHEVC, sizeof(m_sParamHEVC));
break;
}
case OMX_IndexParamVideoProfileLevelQuerySupported:
{
VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported");
eRet = get_supported_profile_level(pParam);
if (eRet && eRet != OMX_ErrorNoMore)
DEBUG_PRINT_ERROR("Invalid entry returned from get_supported_profile_level %u, %u",
(unsigned int)pParam->eProfile, (unsigned int)pParam->eLevel);
break;
}
case OMX_IndexParamVideoProfileLevelCurrent:
{
VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE);
OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData;
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelCurrent");
memcpy(pParam, &m_sParamProfileLevel, sizeof(m_sParamProfileLevel));
break;
}
/*Component should support this port definition*/
case OMX_IndexParamAudioInit:
{
VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
OMX_PORT_PARAM_TYPE *audioPortParamType = (OMX_PORT_PARAM_TYPE *) paramData;
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamAudioInit");
memcpy(audioPortParamType, &m_sPortParam_audio, sizeof(m_sPortParam_audio));
break;
}
/*Component should support this port definition*/
case OMX_IndexParamImageInit:
{
VALIDATE_OMX_PARAM_DATA(paramData, OMX_PORT_PARAM_TYPE);
OMX_PORT_PARAM_TYPE *imagePortParamType = (OMX_PORT_PARAM_TYPE *) paramData;
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamImageInit");
memcpy(imagePortParamType, &m_sPortParam_img, sizeof(m_sPortParam_img));
break;
}
/*Component should support this port definition*/
case OMX_IndexParamOtherInit:
{
DEBUG_PRINT_ERROR("ERROR: get_parameter: OMX_IndexParamOtherInit %08x", paramIndex);
eRet =OMX_ErrorUnsupportedIndex;
break;
}
case OMX_IndexParamStandardComponentRole:
{
VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_COMPONENTROLETYPE);
OMX_PARAM_COMPONENTROLETYPE *comp_role;
comp_role = (OMX_PARAM_COMPONENTROLETYPE *) paramData;
comp_role->nVersion.nVersion = OMX_SPEC_VERSION;
comp_role->nSize = sizeof(*comp_role);
DEBUG_PRINT_LOW("Getparameter: OMX_IndexParamStandardComponentRole %d",paramIndex);
strlcpy((char*)comp_role->cRole,(const char*)m_cRole,OMX_MAX_STRINGNAME_SIZE);
break;
}
/* Added for parameter test */
case OMX_IndexParamPriorityMgmt:
{
VALIDATE_OMX_PARAM_DATA(paramData, OMX_PRIORITYMGMTTYPE);
OMX_PRIORITYMGMTTYPE *priorityMgmType = (OMX_PRIORITYMGMTTYPE *) paramData;
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamPriorityMgmt");
memcpy(priorityMgmType, &m_sPriorityMgmt, sizeof(m_sPriorityMgmt));
break;
}
/* Added for parameter test */
case OMX_IndexParamCompBufferSupplier:
{
VALIDATE_OMX_PARAM_DATA(paramData, OMX_PARAM_BUFFERSUPPLIERTYPE);
OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE*) paramData;
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamCompBufferSupplier");
if (bufferSupplierType->nPortIndex ==(OMX_U32) PORT_INDEX_IN) {
memcpy(bufferSupplierType, &m_sInBufSupplier, sizeof(m_sInBufSupplier));
} else if (bufferSupplierType->nPortIndex ==(OMX_U32) PORT_INDEX_OUT) {
memcpy(bufferSupplierType, &m_sOutBufSupplier, sizeof(m_sOutBufSupplier));
} else {
DEBUG_PRINT_ERROR("ERROR: GetParameter called on Bad Port Index");
eRet = OMX_ErrorBadPortIndex;
}
break;
}
case OMX_IndexParamVideoQuantization:
{
VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_QUANTIZATIONTYPE);
OMX_VIDEO_PARAM_QUANTIZATIONTYPE *session_qp = (OMX_VIDEO_PARAM_QUANTIZATIONTYPE*) paramData;
DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoQuantization");
memcpy(session_qp, &m_sSessionQuantization, sizeof(m_sSessionQuantization));
break;
}
case OMX_QcomIndexParamVideoQPRange:
{
VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_VIDEO_PARAM_QPRANGETYPE);
OMX_QCOM_VIDEO_PARAM_QPRANGETYPE *qp_range = (OMX_QCOM_VIDEO_PARAM_QPRANGETYPE*) paramData;
DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamVideoQPRange");
memcpy(qp_range, &m_sSessionQPRange, sizeof(m_sSessionQPRange));
break;
}
case OMX_IndexParamVideoErrorCorrection:
{
VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE);
OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE* errorresilience = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE*)paramData;
DEBUG_PRINT_LOW("OMX_IndexParamVideoErrorCorrection");
errorresilience->bEnableHEC = m_sErrorCorrection.bEnableHEC;
errorresilience->bEnableResync = m_sErrorCorrection.bEnableResync;
errorresilience->nResynchMarkerSpacing = m_sErrorCorrection.nResynchMarkerSpacing;
break;
}
case OMX_IndexParamVideoIntraRefresh:
{
VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_INTRAREFRESHTYPE);
OMX_VIDEO_PARAM_INTRAREFRESHTYPE* intrarefresh = (OMX_VIDEO_PARAM_INTRAREFRESHTYPE*)paramData;
DEBUG_PRINT_LOW("OMX_IndexParamVideoIntraRefresh");
DEBUG_PRINT_ERROR("OMX_IndexParamVideoIntraRefresh GET");
intrarefresh->eRefreshMode = m_sIntraRefresh.eRefreshMode;
intrarefresh->nCirMBs = m_sIntraRefresh.nCirMBs;
break;
}
case OMX_QcomIndexPortDefn:
//TODO
break;
case OMX_COMPONENT_CAPABILITY_TYPE_INDEX:
{
VALIDATE_OMX_PARAM_DATA(paramData, OMXComponentCapabilityFlagsType);
OMXComponentCapabilityFlagsType *pParam = reinterpret_cast<OMXComponentCapabilityFlagsType*>(paramData);
DEBUG_PRINT_LOW("get_parameter: OMX_COMPONENT_CAPABILITY_TYPE_INDEX");
pParam->iIsOMXComponentMultiThreaded = OMX_TRUE;
pParam->iOMXComponentSupportsExternalOutputBufferAlloc = OMX_FALSE;
pParam->iOMXComponentSupportsExternalInputBufferAlloc = OMX_TRUE;
pParam->iOMXComponentSupportsMovableInputBuffers = OMX_TRUE;
pParam->iOMXComponentUsesNALStartCodes = OMX_TRUE;
pParam->iOMXComponentSupportsPartialFrames = OMX_FALSE;
pParam->iOMXComponentCanHandleIncompleteFrames = OMX_FALSE;
pParam->iOMXComponentUsesFullAVCFrames = OMX_FALSE;
m_use_input_pmem = OMX_TRUE;
DEBUG_PRINT_LOW("Supporting capability index in encoder node");
break;
}
#if !defined(MAX_RES_720P) || defined(_MSM8974_)
case OMX_QcomIndexParamIndexExtraDataType:
{
VALIDATE_OMX_PARAM_DATA(paramData, QOMX_INDEXEXTRADATATYPE);
DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamIndexExtraDataType");
QOMX_INDEXEXTRADATATYPE *pParam = (QOMX_INDEXEXTRADATATYPE *)paramData;
if (pParam->nIndex == (OMX_INDEXTYPE)OMX_ExtraDataVideoEncoderSliceInfo) {
if (pParam->nPortIndex == PORT_INDEX_OUT) {
pParam->bEnabled =
(OMX_BOOL)(m_sExtraData & VEN_EXTRADATA_SLICEINFO);
DEBUG_PRINT_HIGH("Slice Info extradata %d", pParam->bEnabled);
} else {
DEBUG_PRINT_ERROR("get_parameter: slice information is "
"valid for output port only");
eRet =OMX_ErrorUnsupportedIndex;
}
} else if (pParam->nIndex == (OMX_INDEXTYPE)OMX_ExtraDataVideoEncoderMBInfo) {
if (pParam->nPortIndex == PORT_INDEX_OUT) {
pParam->bEnabled =
(OMX_BOOL)(m_sExtraData & VEN_EXTRADATA_MBINFO);
DEBUG_PRINT_HIGH("MB Info extradata %d", pParam->bEnabled);
} else {
DEBUG_PRINT_ERROR("get_parameter: MB information is "
"valid for output port only");
eRet = OMX_ErrorUnsupportedIndex;
}
}
#ifndef _MSM8974_
else if (pParam->nIndex == (OMX_INDEXTYPE)OMX_ExtraDataVideoLTRInfo) {
if (pParam->nPortIndex == PORT_INDEX_OUT) {
pParam->bEnabled =
(OMX_BOOL)(m_sExtraData & VEN_EXTRADATA_LTRINFO);
DEBUG_PRINT_HIGH("LTR Info extradata %d", pParam->bEnabled);
} else {
DEBUG_PRINT_ERROR("get_parameter: LTR information is "
"valid for output port only");
eRet = OMX_ErrorUnsupportedIndex;
}
}
#endif
else {
DEBUG_PRINT_ERROR("get_parameter: unsupported extradata index (0x%x)",
pParam->nIndex);
eRet = OMX_ErrorUnsupportedIndex;
}
break;
}
case QOMX_IndexParamVideoLTRCountRangeSupported:
{
VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTNINDEX_RANGETYPE);
DEBUG_PRINT_HIGH("get_parameter: QOMX_IndexParamVideoLTRCountRangeSupported");
QOMX_EXTNINDEX_RANGETYPE *pParam = (QOMX_EXTNINDEX_RANGETYPE *)paramData;
if (pParam->nPortIndex == PORT_INDEX_OUT) {
OMX_U32 min = 0, max = 0, step_size = 0;
if (dev_get_capability_ltrcount(&min, &max, &step_size)) {
pParam->nMin = min;
pParam->nMax = max;
pParam->nStepSize = step_size;
} else {
DEBUG_PRINT_ERROR("get_parameter: get_capability_ltrcount failed");
eRet = OMX_ErrorUndefined;
}
} else {
DEBUG_PRINT_ERROR("LTR count range is valid for output port only");
eRet = OMX_ErrorUnsupportedIndex;
}
}
break;
case OMX_QcomIndexParamVideoLTRCount:
{
VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_VIDEO_PARAM_LTRCOUNT_TYPE);
DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamVideoLTRCount");
OMX_QCOM_VIDEO_PARAM_LTRCOUNT_TYPE *pParam =
reinterpret_cast<OMX_QCOM_VIDEO_PARAM_LTRCOUNT_TYPE*>(paramData);
memcpy(pParam, &m_sParamLTRCount, sizeof(m_sParamLTRCount));
break;
}
#endif
case QOMX_IndexParamVideoSyntaxHdr:
{
VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTNINDEX_PARAMTYPE);
DEBUG_PRINT_HIGH("QOMX_IndexParamVideoSyntaxHdr");
QOMX_EXTNINDEX_PARAMTYPE* pParam =
reinterpret_cast<QOMX_EXTNINDEX_PARAMTYPE*>(paramData);
if (pParam->pData == NULL) {
DEBUG_PRINT_ERROR("Error: Data buffer is NULL");
eRet = OMX_ErrorBadParameter;
break;
}
if (get_syntaxhdr_enable == false) {
DEBUG_PRINT_ERROR("ERROR: get_parameter: Get syntax header disabled");
eRet = OMX_ErrorUnsupportedIndex;
break;
}
BITMASK_SET(&m_flags, OMX_COMPONENT_LOADED_START_PENDING);
if (dev_loaded_start()) {
DEBUG_PRINT_LOW("device start successful");
} else {
DEBUG_PRINT_ERROR("device start failed");
BITMASK_CLEAR(&m_flags, OMX_COMPONENT_LOADED_START_PENDING);
return OMX_ErrorHardware;
}
if (dev_get_seq_hdr(pParam->pData,
(unsigned)(pParam->nSize - sizeof(QOMX_EXTNINDEX_PARAMTYPE)),
(unsigned *)(void *)&pParam->nDataSize)) {
DEBUG_PRINT_HIGH("get syntax header successful (hdrlen = %u)",
(unsigned int)pParam->nDataSize);
for (unsigned i = 0; i < pParam->nDataSize; i++) {
DEBUG_PRINT_LOW("Header[%d] = %x", i, *((char *)pParam->pData + i));
}
} else {
DEBUG_PRINT_ERROR("Error returned from GetSyntaxHeader()");
eRet = OMX_ErrorHardware;
}
BITMASK_SET(&m_flags, OMX_COMPONENT_LOADED_STOP_PENDING);
if (dev_loaded_stop()) {
DEBUG_PRINT_LOW("device stop successful");
} else {
DEBUG_PRINT_ERROR("device stop failed");
BITMASK_CLEAR(&m_flags, OMX_COMPONENT_LOADED_STOP_PENDING);
eRet = OMX_ErrorHardware;
}
break;
}
case OMX_QcomIndexHierarchicalStructure:
{
VALIDATE_OMX_PARAM_DATA(paramData, QOMX_VIDEO_HIERARCHICALLAYERS);
QOMX_VIDEO_HIERARCHICALLAYERS* hierp = (QOMX_VIDEO_HIERARCHICALLAYERS*) paramData;
DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexHierarchicalStructure");
memcpy(hierp, &m_sHierLayers, sizeof(m_sHierLayers));
break;
}
case OMX_QcomIndexParamPerfLevel:
{
VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_VIDEO_PARAM_PERF_LEVEL);
OMX_U32 perflevel;
OMX_QCOM_VIDEO_PARAM_PERF_LEVEL *pParam =
reinterpret_cast<OMX_QCOM_VIDEO_PARAM_PERF_LEVEL*>(paramData);
DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamPerfLevel");
if (!dev_get_performance_level(&perflevel)) {
DEBUG_PRINT_ERROR("Invalid entry returned from get_performance_level %d",
pParam->ePerfLevel);
} else {
pParam->ePerfLevel = (QOMX_VIDEO_PERF_LEVEL)perflevel;
}
break;
}
case OMX_QcomIndexParamH264VUITimingInfo:
{
VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_VIDEO_PARAM_VUI_TIMING_INFO);
OMX_U32 enabled;
OMX_QCOM_VIDEO_PARAM_VUI_TIMING_INFO *pParam =
reinterpret_cast<OMX_QCOM_VIDEO_PARAM_VUI_TIMING_INFO*>(paramData);
DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamH264VUITimingInfo");
if (!dev_get_vui_timing_info(&enabled)) {
DEBUG_PRINT_ERROR("Invalid entry returned from get_vui_Timing_info %d",
pParam->bEnable);
} else {
pParam->bEnable = (OMX_BOOL)enabled;
}
break;
}
case OMX_QcomIndexParamPeakBitrate:
{
VALIDATE_OMX_PARAM_DATA(paramData, OMX_QCOM_VIDEO_PARAM_PEAK_BITRATE);
OMX_U32 peakbitrate;
OMX_QCOM_VIDEO_PARAM_PEAK_BITRATE *pParam =
reinterpret_cast<OMX_QCOM_VIDEO_PARAM_PEAK_BITRATE*>(paramData);
DEBUG_PRINT_LOW("get_parameter: OMX_QcomIndexParamPeakBitrate");
if (!dev_get_peak_bitrate(&peakbitrate)) {
DEBUG_PRINT_ERROR("Invalid entry returned from get_peak_bitrate %u",
(unsigned int)pParam->nPeakBitrate);
} else {
pParam->nPeakBitrate = peakbitrate;
}
break;
}
case QOMX_IndexParamVideoInitialQp:
{
VALIDATE_OMX_PARAM_DATA(paramData, QOMX_EXTNINDEX_VIDEO_INITIALQP);
QOMX_EXTNINDEX_VIDEO_INITIALQP* initqp =
reinterpret_cast<QOMX_EXTNINDEX_VIDEO_INITIALQP *>(paramData);
memcpy(initqp, &m_sParamInitqp, sizeof(m_sParamInitqp));
break;
}
case OMX_IndexParamVideoSliceFMO:
default:
{
DEBUG_PRINT_LOW("ERROR: get_parameter: unknown param %08x", paramIndex);
eRet =OMX_ErrorUnsupportedIndex;
break;
}
}
return eRet;
}
/* ======================================================================
FUNCTION
omx_video::GetConfig
DESCRIPTION
OMX Get Config Method implementation.
PARAMETERS
<TBD>.
RETURN VALUE
OMX Error None if successful.
========================================================================== */
OMX_ERRORTYPE omx_video::get_config(OMX_IN OMX_HANDLETYPE hComp,
OMX_IN OMX_INDEXTYPE configIndex,
OMX_INOUT OMX_PTR configData)
{
(void)hComp;
////////////////////////////////////////////////////////////////
// Supported Config Index Type
// =============================================================
// OMX_IndexConfigVideoBitrate OMX_VIDEO_CONFIG_BITRATETYPE
// OMX_IndexConfigVideoFramerate OMX_CONFIG_FRAMERATETYPE
// OMX_IndexConfigCommonRotate OMX_CONFIG_ROTATIONTYPE
////////////////////////////////////////////////////////////////
if (configData == NULL) {
DEBUG_PRINT_ERROR("ERROR: param is null");
return OMX_ErrorBadParameter;
}
if (m_state == OMX_StateInvalid) {
DEBUG_PRINT_ERROR("ERROR: can't be in invalid state");
return OMX_ErrorIncorrectStateOperation;
}
//@todo need to validate params
switch ((int)configIndex) {
case OMX_IndexConfigVideoBitrate:
{
VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_BITRATETYPE);
OMX_VIDEO_CONFIG_BITRATETYPE* pParam = reinterpret_cast<OMX_VIDEO_CONFIG_BITRATETYPE*>(configData);
memcpy(pParam, &m_sConfigBitrate, sizeof(m_sConfigBitrate));
break;
}
case OMX_IndexConfigVideoFramerate:
{
VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_FRAMERATETYPE);
OMX_CONFIG_FRAMERATETYPE* pParam = reinterpret_cast<OMX_CONFIG_FRAMERATETYPE*>(configData);
memcpy(pParam, &m_sConfigFramerate, sizeof(m_sConfigFramerate));
break;
}
case OMX_IndexConfigCommonRotate:
{
VALIDATE_OMX_PARAM_DATA(configData, OMX_CONFIG_ROTATIONTYPE);
OMX_CONFIG_ROTATIONTYPE* pParam = reinterpret_cast<OMX_CONFIG_ROTATIONTYPE*>(configData);
memcpy(pParam, &m_sConfigFrameRotation, sizeof(m_sConfigFrameRotation));
break;
}
case QOMX_IndexConfigVideoIntraperiod:
{
DEBUG_PRINT_LOW("get_config:QOMX_IndexConfigVideoIntraperiod");
VALIDATE_OMX_PARAM_DATA(configData, QOMX_VIDEO_INTRAPERIODTYPE);
QOMX_VIDEO_INTRAPERIODTYPE* pParam = reinterpret_cast<QOMX_VIDEO_INTRAPERIODTYPE*>(configData);
memcpy(pParam, &m_sIntraperiod, sizeof(m_sIntraperiod));
break;
}
case OMX_IndexConfigVideoAVCIntraPeriod:
{
VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_AVCINTRAPERIOD);
OMX_VIDEO_CONFIG_AVCINTRAPERIOD *pParam =
reinterpret_cast<OMX_VIDEO_CONFIG_AVCINTRAPERIOD*>(configData);
DEBUG_PRINT_LOW("get_config: OMX_IndexConfigVideoAVCIntraPeriod");
memcpy(pParam, &m_sConfigAVCIDRPeriod, sizeof(m_sConfigAVCIDRPeriod));
break;
}
case OMX_IndexConfigCommonDeinterlace:
{
VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_CONFIG_DEINTERLACE);
OMX_VIDEO_CONFIG_DEINTERLACE *pParam =
reinterpret_cast<OMX_VIDEO_CONFIG_DEINTERLACE*>(configData);
DEBUG_PRINT_LOW("get_config: OMX_IndexConfigCommonDeinterlace");
memcpy(pParam, &m_sConfigDeinterlace, sizeof(m_sConfigDeinterlace));
break;
}
case OMX_IndexConfigVideoVp8ReferenceFrame:
{
VALIDATE_OMX_PARAM_DATA(configData, OMX_VIDEO_VP8REFERENCEFRAMETYPE);
OMX_VIDEO_VP8REFERENCEFRAMETYPE* pParam =
reinterpret_cast<OMX_VIDEO_VP8REFERENCEFRAMETYPE*>(configData);
DEBUG_PRINT_LOW("get_config: OMX_IndexConfigVideoVp8ReferenceFrame");
memcpy(pParam, &m_sConfigVp8ReferenceFrame, sizeof(m_sConfigVp8ReferenceFrame));
break;
}
case OMX_QcomIndexConfigPerfLevel:
{
VALIDATE_OMX_PARAM_DATA(configData, OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL);
OMX_U32 perflevel;
OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *pParam =
reinterpret_cast<OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL*>(configData);
DEBUG_PRINT_LOW("get_config: OMX_QcomIndexConfigPerfLevel");
if (!dev_get_performance_level(&perflevel)) {
DEBUG_PRINT_ERROR("Invalid entry returned from get_performance_level %d",
pParam->ePerfLevel);
} else {
pParam->ePerfLevel = (QOMX_VIDEO_PERF_LEVEL)perflevel;
}
break;
}
default:
DEBUG_PRINT_ERROR("ERROR: unsupported index %d", (int) configIndex);
return OMX_ErrorUnsupportedIndex;
}
return OMX_ErrorNone;
}
/* ======================================================================
FUNCTION
omx_video::GetExtensionIndex
DESCRIPTION
OMX GetExtensionIndex method implementaion. <TBD>
PARAMETERS
<TBD>.
RETURN VALUE
OMX Error None if everything successful.
========================================================================== */
OMX_ERRORTYPE omx_video::get_extension_index(OMX_IN OMX_HANDLETYPE hComp,
OMX_IN OMX_STRING paramName,
OMX_OUT OMX_INDEXTYPE* indexType)
{
(void)hComp;
if (m_state == OMX_StateInvalid) {
DEBUG_PRINT_ERROR("ERROR: Get Extension Index in Invalid State");
return OMX_ErrorInvalidState;
}
#ifdef MAX_RES_1080P
if (!strncmp(paramName, "OMX.QCOM.index.param.SliceDeliveryMode",
sizeof("OMX.QCOM.index.param.SliceDeliveryMode") - 1)) {
*indexType = (OMX_INDEXTYPE)OMX_QcomIndexEnableSliceDeliveryMode;
return OMX_ErrorNone;
}
#endif
#ifdef _ANDROID_ICS_
if (!strncmp(paramName, "OMX.google.android.index.storeMetaDataInBuffers",
sizeof("OMX.google.android.index.storeMetaDataInBuffers") - 1)) {
*indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamVideoMetaBufferMode;
return OMX_ErrorNone;
}
#endif
if (!strncmp(paramName, "OMX.google.android.index.prependSPSPPSToIDRFrames",
sizeof("OMX.google.android.index.prependSPSPPSToIDRFrames") - 1)) {
*indexType = (OMX_INDEXTYPE)OMX_QcomIndexParamSequenceHeaderWithIDR;
return OMX_ErrorNone;
}
return OMX_ErrorNotImplemented;
}
/* ======================================================================
FUNCTION
omx_video::GetState
DESCRIPTION
Returns the state information back to the caller.<TBD>
PARAMETERS
<TBD>.
RETURN VALUE
Error None if everything is successful.
========================================================================== */
OMX_ERRORTYPE omx_video::get_state(OMX_IN OMX_HANDLETYPE hComp,
OMX_OUT OMX_STATETYPE* state)
{
(void)hComp;
*state = m_state;
DEBUG_PRINT_LOW("get_state: Returning the state %d",*state);
return OMX_ErrorNone;
}
/* ======================================================================
FUNCTION
omx_video::ComponentTunnelRequest
DESCRIPTION
OMX Component Tunnel Request method implementation. <TBD>
PARAMETERS
None.
RETURN VALUE
OMX Error None if everything successful.
========================================================================== */
OMX_ERRORTYPE omx_video::component_tunnel_request(OMX_IN OMX_HANDLETYPE hComp,
OMX_IN OMX_U32 port,
OMX_IN OMX_HANDLETYPE peerComponent,
OMX_IN OMX_U32 peerPort,
OMX_INOUT OMX_TUNNELSETUPTYPE* tunnelSetup)
{
(void) hComp, (void) port, (void) peerComponent, (void) peerPort, (void) tunnelSetup;
DEBUG_PRINT_ERROR("ERROR: component_tunnel_request Not Implemented");
return OMX_ErrorNotImplemented;
}
/* ======================================================================
FUNCTION
omx_video::UseInputBuffer
DESCRIPTION
Helper function for Use buffer in the input pin
PARAMETERS
None.
RETURN VALUE
true/false
========================================================================== */
OMX_ERRORTYPE omx_video::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)
{
(void) hComp;
OMX_ERRORTYPE eRet = OMX_ErrorNone;
unsigned i = 0;
unsigned char *buf_addr = NULL;
DEBUG_PRINT_HIGH("use_input_buffer: port = %u appData = %p bytes = %u buffer = %p",(unsigned int)port,appData,(unsigned int)bytes,buffer);
if (bytes != m_sInPortDef.nBufferSize) {
DEBUG_PRINT_ERROR("ERROR: use_input_buffer: Size Mismatch!! "
"bytes[%u] != Port.nBufferSize[%u]", (unsigned int)bytes, (unsigned int)m_sInPortDef.nBufferSize);
return OMX_ErrorBadParameter;
}
if (!m_inp_mem_ptr) {
input_use_buffer = true;
m_inp_mem_ptr = (OMX_BUFFERHEADERTYPE*) \
calloc( (sizeof(OMX_BUFFERHEADERTYPE)), m_sInPortDef.nBufferCountActual);
if (m_inp_mem_ptr == NULL) {
DEBUG_PRINT_ERROR("ERROR: calloc() Failed for m_inp_mem_ptr");
return OMX_ErrorInsufficientResources;
}
DEBUG_PRINT_LOW("Successfully allocated m_inp_mem_ptr = %p", m_inp_mem_ptr);
m_pInput_pmem = (struct pmem *) calloc(sizeof (struct pmem), m_sInPortDef.nBufferCountActual);
if (m_pInput_pmem == NULL) {
DEBUG_PRINT_ERROR("ERROR: calloc() Failed for m_pInput_pmem");
return OMX_ErrorInsufficientResources;
}
#ifdef USE_ION
m_pInput_ion = (struct venc_ion *) calloc(sizeof (struct venc_ion), m_sInPortDef.nBufferCountActual);
if (m_pInput_ion == NULL) {
DEBUG_PRINT_ERROR("ERROR: calloc() Failed for m_pInput_ion");
return OMX_ErrorInsufficientResources;
}
#endif
for (i=0; i< m_sInPortDef.nBufferCountActual; i++) {
m_pInput_pmem[i].fd = -1;
#ifdef USE_ION
m_pInput_ion[i].ion_device_fd =-1;
m_pInput_ion[i].fd_ion_data.fd =-1;
m_pInput_ion[i].ion_alloc_data.handle = 0;
#endif
}
}
for (i=0; i< m_sInPortDef.nBufferCountActual; i++) {
if (BITMASK_ABSENT(&m_inp_bm_count,i)) {
break;
}
}
if (i < m_sInPortDef.nBufferCountActual) {
*bufferHdr = (m_inp_mem_ptr + i);
BITMASK_SET(&m_inp_bm_count,i);
(*bufferHdr)->pBuffer = (OMX_U8 *)buffer;
(*bufferHdr)->nSize = sizeof(OMX_BUFFERHEADERTYPE);
(*bufferHdr)->nVersion.nVersion = OMX_SPEC_VERSION;
(*bufferHdr)->nAllocLen = m_sInPortDef.nBufferSize;
(*bufferHdr)->pAppPrivate = appData;
(*bufferHdr)->nInputPortIndex = PORT_INDEX_IN;
if (!m_use_input_pmem) {
#ifdef USE_ION
#ifdef _MSM8974_
m_pInput_ion[i].ion_device_fd = alloc_map_ion_memory(m_sInPortDef.nBufferSize,
&m_pInput_ion[i].ion_alloc_data,
&m_pInput_ion[i].fd_ion_data,0);
#else
m_pInput_ion[i].ion_device_fd = alloc_map_ion_memory(m_sInPortDef.nBufferSize,
&m_pInput_ion[i].ion_alloc_data,
&m_pInput_ion[i].fd_ion_data,ION_FLAG_CACHED);
#endif
if (m_pInput_ion[i].ion_device_fd < 0) {
DEBUG_PRINT_ERROR("ERROR:ION device open() Failed");
return OMX_ErrorInsufficientResources;
}
m_pInput_pmem[i].fd = m_pInput_ion[i].fd_ion_data.fd;
#else
m_pInput_pmem[i].fd = open (MEM_DEVICE,O_RDWR);
if (m_pInput_pmem[i].fd == 0) {
m_pInput_pmem[i].fd = open (MEM_DEVICE,O_RDWR);
}
if (m_pInput_pmem[i] .fd < 0) {
DEBUG_PRINT_ERROR("ERROR: /dev/pmem_adsp open() Failed");
return OMX_ErrorInsufficientResources;
}
#endif
m_pInput_pmem[i].size = m_sInPortDef.nBufferSize;
m_pInput_pmem[i].offset = 0;
m_pInput_pmem[i].buffer = NULL;
if(!secure_session) {
m_pInput_pmem[i].buffer = (unsigned char *)mmap(
NULL,m_pInput_pmem[i].size,PROT_READ|PROT_WRITE,
MAP_SHARED,m_pInput_pmem[i].fd,0);
if (m_pInput_pmem[i].buffer == MAP_FAILED) {
DEBUG_PRINT_ERROR("ERROR: mmap() Failed");
m_pInput_pmem[i].buffer = NULL;
close(m_pInput_pmem[i].fd);
#ifdef USE_ION
free_ion_memory(&m_pInput_ion[i]);
#endif
return OMX_ErrorInsufficientResources;
}
}
} else {
OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pParam = reinterpret_cast<OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *>((*bufferHdr)->pAppPrivate);
DEBUG_PRINT_LOW("Inside qcom_ext with luma:(fd:%lu,offset:0x%x)", pParam->pmem_fd, (unsigned)pParam->offset);
if (pParam) {
m_pInput_pmem[i].fd = pParam->pmem_fd;
m_pInput_pmem[i].offset = pParam->offset;
m_pInput_pmem[i].size = m_sInPortDef.nBufferSize;
m_pInput_pmem[i].buffer = (unsigned char *)buffer;
DEBUG_PRINT_LOW("DBG:: pParam->pmem_fd = %u, pParam->offset = %u",
(unsigned int)pParam->pmem_fd, (unsigned int)pParam->offset);
} else {
DEBUG_PRINT_ERROR("ERROR: Invalid AppData given for PMEM i/p UseBuffer case");
return OMX_ErrorBadParameter;
}
}
DEBUG_PRINT_LOW("use_inp:: bufhdr = %p, pBuffer = %p, m_pInput_pmem[i].buffer = %p",
(*bufferHdr), (*bufferHdr)->pBuffer, m_pInput_pmem[i].buffer);
if ( dev_use_buf(&m_pInput_pmem[i],PORT_INDEX_IN,i) != true) {
DEBUG_PRINT_ERROR("ERROR: dev_use_buf() Failed for i/p buf");
return OMX_ErrorInsufficientResources;
}
} else {
DEBUG_PRINT_ERROR("ERROR: All buffers are already used, invalid use_buf call for "
"index = %u", i);
eRet = OMX_ErrorInsufficientResources;
}
return eRet;
}
/* ======================================================================
FUNCTION
omx_video::UseOutputBuffer
DESCRIPTION
Helper function for Use buffer in the input pin
PARAMETERS
None.
RETURN VALUE
true/false
========================================================================== */
OMX_ERRORTYPE omx_video::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)
{
(void)hComp, (void)port;
OMX_ERRORTYPE eRet = OMX_ErrorNone;
OMX_BUFFERHEADERTYPE *bufHdr= NULL; // buffer header
unsigned i= 0; // Temporary counter
unsigned char *buf_addr = NULL;
#ifdef _MSM8974_
int align_size;
#endif
DEBUG_PRINT_HIGH("Inside use_output_buffer()");
if (bytes != m_sOutPortDef.nBufferSize) {
DEBUG_PRINT_ERROR("ERROR: use_output_buffer: Size Mismatch!! "
"bytes[%u] != Port.nBufferSize[%u]", (unsigned int)bytes, (unsigned int)m_sOutPortDef.nBufferSize);
return OMX_ErrorBadParameter;
}
if (!m_out_mem_ptr) {
output_use_buffer = true;
int nBufHdrSize = 0;
DEBUG_PRINT_LOW("Allocating First Output Buffer(%u)",(unsigned int)m_sOutPortDef.nBufferCountActual);
nBufHdrSize = m_sOutPortDef.nBufferCountActual * sizeof(OMX_BUFFERHEADERTYPE);
/*
* Memory for output side involves the following:
* 1. Array of Buffer Headers
* 2. Bitmask array to hold the buffer allocation details
* In order to minimize the memory management entire allocation
* is done in one step.
*/
//OMX Buffer header
m_out_mem_ptr = (OMX_BUFFERHEADERTYPE *)calloc(nBufHdrSize,1);
if (m_out_mem_ptr == NULL) {
DEBUG_PRINT_ERROR("ERROR: calloc() Failed for m_out_mem_ptr");
return OMX_ErrorInsufficientResources;
}
m_pOutput_pmem = (struct pmem *) calloc(sizeof (struct pmem), m_sOutPortDef.nBufferCountActual);
if (m_pOutput_pmem == NULL) {
DEBUG_PRINT_ERROR("ERROR: calloc() Failed for m_pOutput_pmem");
return OMX_ErrorInsufficientResources;
}
#ifdef USE_ION
m_pOutput_ion = (struct venc_ion *) calloc(sizeof (struct venc_ion), m_sOutPortDef.nBufferCountActual);
if (m_pOutput_ion == NULL) {
DEBUG_PRINT_ERROR("ERROR: calloc() Failed for m_pOutput_ion");
return OMX_ErrorInsufficientResources;
}
#endif
if (m_out_mem_ptr) {
bufHdr = m_out_mem_ptr;
DEBUG_PRINT_LOW("Memory Allocation Succeeded for OUT port%p",m_out_mem_ptr);
// Settting the entire storage nicely
for (i=0; i < m_sOutPortDef.nBufferCountActual ; i++) {
bufHdr->nSize = sizeof(OMX_BUFFERHEADERTYPE);
bufHdr->nVersion.nVersion = OMX_SPEC_VERSION;
bufHdr->nAllocLen = bytes;
bufHdr->nFilledLen = 0;
bufHdr->pAppPrivate = appData;
bufHdr->nOutputPortIndex = PORT_INDEX_OUT;
bufHdr->pBuffer = NULL;
bufHdr++;
m_pOutput_pmem[i].fd = -1;
#ifdef USE_ION
m_pOutput_ion[i].ion_device_fd =-1;
m_pOutput_ion[i].fd_ion_data.fd=-1;
m_pOutput_ion[i].ion_alloc_data.handle = 0;
#endif
}
} else {
DEBUG_PRINT_ERROR("ERROR: Output buf mem alloc failed[0x%p]",m_out_mem_ptr);
eRet = OMX_ErrorInsufficientResources;
}
}
for (i=0; i< m_sOutPortDef.nBufferCountActual; i++) {
if (BITMASK_ABSENT(&m_out_bm_count,i)) {
break;
}
}
if (eRet == OMX_ErrorNone) {
if (i < m_sOutPortDef.nBufferCountActual) {
*bufferHdr = (m_out_mem_ptr + i );
(*bufferHdr)->pBuffer = (OMX_U8 *)buffer;
(*bufferHdr)->pAppPrivate = appData;
if (!m_use_output_pmem) {
#ifdef USE_ION
#ifdef _MSM8974_
align_size = (m_sOutPortDef.nBufferSize + (SZ_4K - 1)) & ~(SZ_4K - 1);
m_pOutput_ion[i].ion_device_fd = alloc_map_ion_memory(align_size,
&m_pOutput_ion[i].ion_alloc_data,
&m_pOutput_ion[i].fd_ion_data,0);
#else
m_pOutput_ion[i].ion_device_fd = alloc_map_ion_memory(
m_sOutPortDef.nBufferSize,
&m_pOutput_ion[i].ion_alloc_data,
&m_pOutput_ion[i].fd_ion_data,ION_FLAG_CACHED);
#endif
if (m_pOutput_ion[i].ion_device_fd < 0) {
DEBUG_PRINT_ERROR("ERROR:ION device open() Failed");
return OMX_ErrorInsufficientResources;
}
m_pOutput_pmem[i].fd = m_pOutput_ion[i].fd_ion_data.fd;
#else
m_pOutput_pmem[i].fd = open (MEM_DEVICE,O_RDWR);
if (m_pOutput_pmem[i].fd == 0) {
m_pOutput_pmem[i].fd = open (MEM_DEVICE,O_RDWR);
}
if (m_pOutput_pmem[i].fd < 0) {
DEBUG_PRINT_ERROR("ERROR: /dev/pmem_adsp open() Failed");
return OMX_ErrorInsufficientResources;
}
#endif
m_pOutput_pmem[i].size = m_sOutPortDef.nBufferSize;
m_pOutput_pmem[i].offset = 0;
m_pOutput_pmem[i].buffer = NULL;
if(!secure_session) {
#ifdef _MSM8974_
m_pOutput_pmem[i].buffer = (unsigned char *)mmap(NULL,
align_size,PROT_READ|PROT_WRITE,
MAP_SHARED,m_pOutput_pmem[i].fd,0);
#else
m_pOutput_pmem[i].buffer = (unsigned char *)mmap(NULL,
m_pOutput_pmem[i].size,PROT_READ|PROT_WRITE,
MAP_SHARED,m_pOutput_pmem[i].fd,0);
#endif
if (m_pOutput_pmem[i].buffer == MAP_FAILED) {
DEBUG_PRINT_ERROR("ERROR: mmap() Failed");
m_pOutput_pmem[i].buffer = NULL;
close(m_pOutput_pmem[i].fd);
#ifdef USE_ION
free_ion_memory(&m_pOutput_ion[i]);
#endif
return OMX_ErrorInsufficientResources;
}
}
} else {
OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO *pParam = reinterpret_cast<OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO*>((*bufferHdr)->pAppPrivate);
DEBUG_PRINT_LOW("Inside qcom_ext pParam: %p", pParam);
if (pParam) {
DEBUG_PRINT_LOW("Inside qcom_ext with luma:(fd:%lu,offset:0x%x)", pParam->pmem_fd, (int)pParam->offset);
m_pOutput_pmem[i].fd = pParam->pmem_fd;
m_pOutput_pmem[i].offset = pParam->offset;
m_pOutput_pmem[i].size = m_sOutPortDef.nBufferSize;
m_pOutput_pmem[i].buffer = (unsigned char *)buffer;
} else {
DEBUG_PRINT_ERROR("ERROR: Invalid AppData given for PMEM o/p UseBuffer case");
return OMX_ErrorBadParameter;
}
buf_addr = (unsigned char *)buffer;
}
DEBUG_PRINT_LOW("use_out:: bufhdr = %p, pBuffer = %p, m_pOutput_pmem[i].buffer = %p",
(*bufferHdr), (*bufferHdr)->pBuffer, m_pOutput_pmem[i].buffer);
if (dev_use_buf(&m_pOutput_pmem[i],PORT_INDEX_OUT,i) != true) {
DEBUG_PRINT_ERROR("ERROR: dev_use_buf Failed for o/p buf");
return OMX_ErrorInsufficientResources;
}
BITMASK_SET(&m_out_bm_count,i);
} else {
DEBUG_PRINT_ERROR("ERROR: All o/p Buffers have been Used, invalid use_buf call for "
"index = %u", i);
eRet = OMX_ErrorInsufficientResources;
}
}
return eRet;
}
/* ======================================================================
FUNCTION
omx_video::UseBuffer
DESCRIPTION
OMX Use Buffer method implementation.
PARAMETERS
<TBD>.
RETURN VALUE
OMX Error None , if everything successful.
========================================================================== */
OMX_ERRORTYPE omx_video::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) {
DEBUG_PRINT_ERROR("ERROR: Use Buffer in Invalid State");
return OMX_ErrorInvalidState;
}
if (port == PORT_INDEX_IN) {
eRet = use_input_buffer(hComp,bufferHdr,port,appData,bytes,buffer);
} else if (port == PORT_INDEX_OUT) {
eRet = use_output_buffer(hComp,bufferHdr,port,appData,bytes,buffer);
} else {
DEBUG_PRINT_ERROR("ERROR: Invalid Port Index received %d",(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 == PORT_INDEX_IN && m_sInPortDef.bPopulated) {
if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_INPUT_ENABLE_PENDING)) {
BITMASK_CLEAR((&m_flags),OMX_COMPONENT_INPUT_ENABLE_PENDING);
post_event(OMX_CommandPortEnable,
PORT_INDEX_IN,
OMX_COMPONENT_GENERATE_EVENT);
}
} else if (port == PORT_INDEX_OUT && m_sOutPortDef.bPopulated) {
if (BITMASK_PRESENT(&m_flags,OMX_COMPONENT_OUTPUT_ENABLE_PENDING)) {
BITMASK_CLEAR((&m_flags),OMX_COMPONENT_OUTPUT_ENABLE_PENDING);
post_event(OMX_CommandPortEnable,
PORT_INDEX_OUT,
OMX_COMPONENT_GENERATE_EVENT);
m_event_port_settings_sent = false;
}
}
}
return eRet;
}
OMX_ERRORTYPE omx_video::free_input_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
{
unsigned int index = 0;
OMX_U8 *temp_buff ;
if (bufferHdr == NULL || m_inp_mem_ptr == NULL) {
DEBUG_PRINT_ERROR("ERROR: free_input: Invalid bufferHdr[%p] or m_inp_mem_ptr[%p]",
bufferHdr, m_inp_mem_ptr);
return OMX_ErrorBadParameter;
}
index = bufferHdr - ((!meta_mode_enable)?m_inp_mem_ptr:meta_buffer_hdr);
#ifdef _ANDROID_ICS_
if (meta_mode_enable) {
if (index < m_sInPortDef.nBufferCountActual) {
memset(&meta_buffer_hdr[index], 0, sizeof(meta_buffer_hdr[index]));
memset(&meta_buffers[index], 0, sizeof(meta_buffers[index]));
}
if (!mUseProxyColorFormat)
return OMX_ErrorNone;
else {
c2d_conv.close();
opaque_buffer_hdr[index] = NULL;
}
}
#endif
if (index < m_sInPortDef.nBufferCountActual && !mUseProxyColorFormat &&
dev_free_buf(&m_pInput_pmem[index],PORT_INDEX_IN) != true) {
DEBUG_PRINT_LOW("ERROR: dev_free_buf() Failed for i/p buf");
}
if (index < m_sInPortDef.nBufferCountActual && m_pInput_pmem) {
auto_lock l(m_lock);
if (m_pInput_pmem[index].fd > 0 && input_use_buffer == false) {
DEBUG_PRINT_LOW("FreeBuffer:: i/p AllocateBuffer case");
if(!secure_session) {
munmap (m_pInput_pmem[index].buffer,m_pInput_pmem[index].size);
} else {
free(m_pInput_pmem[index].buffer);
}
m_pInput_pmem[index].buffer = NULL;
close (m_pInput_pmem[index].fd);
#ifdef USE_ION
free_ion_memory(&m_pInput_ion[index]);
#endif
m_pInput_pmem[index].fd = -1;
} else if (m_pInput_pmem[index].fd > 0 && (input_use_buffer == true &&
m_use_input_pmem == OMX_FALSE)) {
DEBUG_PRINT_LOW("FreeBuffer:: i/p Heap UseBuffer case");
if (dev_free_buf(&m_pInput_pmem[index],PORT_INDEX_IN) != true) {
DEBUG_PRINT_ERROR("ERROR: dev_free_buf() Failed for i/p buf");
}
if(!secure_session) {
munmap (m_pInput_pmem[index].buffer,m_pInput_pmem[index].size);
m_pInput_pmem[index].buffer = NULL;
}
close (m_pInput_pmem[index].fd);
#ifdef USE_ION
free_ion_memory(&m_pInput_ion[index]);
#endif
m_pInput_pmem[index].fd = -1;
} else {
DEBUG_PRINT_ERROR("FreeBuffer:: fd is invalid or i/p PMEM UseBuffer case");
}
}
return OMX_ErrorNone;
}
OMX_ERRORTYPE omx_video::free_output_buffer(OMX_BUFFERHEADERTYPE *bufferHdr)
{
unsigned int index = 0;
OMX_U8 *temp_buff ;
if (bufferHdr == NULL || m_out_mem_ptr == NULL) {
DEBUG_PRINT_ERROR("ERROR: free_output: Invalid bufferHdr[%p] or m_out_mem_ptr[%p]",
bufferHdr, m_out_mem_ptr);
return OMX_ErrorBadParameter;
}
index = bufferHdr - m_out_mem_ptr;
if (index < m_sOutPortDef.nBufferCountActual &&
dev_free_buf(&m_pOutput_pmem[index],PORT_INDEX_OUT) != true) {
DEBUG_PRINT_ERROR("ERROR: dev_free_buf Failed for o/p buf");
}
if (index < m_sOutPortDef.nBufferCountActual && m_pOutput_pmem) {
if (m_pOutput_pmem[index].fd > 0 && output_use_buffer == false ) {
DEBUG_PRINT_LOW("FreeBuffer:: o/p AllocateBuffer case");
if(!secure_session) {
munmap (m_pOutput_pmem[index].buffer,
m_pOutput_pmem[index].size);
} else {
char *data = (char*) m_pOutput_pmem[index].buffer;
native_handle_t *handle = NULL;
memcpy(&handle, data + sizeof(OMX_U32), sizeof(native_handle_t*));
native_handle_delete(handle);
free(m_pOutput_pmem[index].buffer);
}
close (m_pOutput_pmem[index].fd);
#ifdef USE_ION
free_ion_memory(&m_pOutput_ion[index]);
#endif
m_pOutput_pmem[index].fd = -1;
} else if ( m_pOutput_pmem[index].fd > 0 && (output_use_buffer == true
&& m_use_output_pmem == OMX_FALSE)) {
DEBUG_PRINT_LOW("FreeBuffer:: o/p Heap UseBuffer case");
if (dev_free_buf(&m_pOutput_pmem[index],PORT_INDEX_OUT) != true) {
DEBUG_PRINT_ERROR("ERROR: dev_free_buf Failed for o/p buf");
}
if(!secure_session) {
munmap (m_pOutput_pmem[index].buffer,
m_pOutput_pmem[index].size);
}
close (m_pOutput_pmem[index].fd);
#ifdef USE_ION
free_ion_memory(&m_pOutput_ion[index]);
#endif
m_pOutput_pmem[index].fd = -1;
} else {
DEBUG_PRINT_LOW("FreeBuffer:: fd is invalid or o/p PMEM UseBuffer case");
}
}
return OMX_ErrorNone;
}
#ifdef _ANDROID_ICS_
OMX_ERRORTYPE omx_video::allocate_input_meta_buffer(
OMX_HANDLETYPE hComp,