summaryrefslogtreecommitdiff
path: root/omx.c
diff options
context:
space:
mode:
authorThomas Reufer <thomas@reufer.ch>2014-02-10 21:53:25 +0100
committerThomas Reufer <thomas@reufer.ch>2014-02-10 21:53:25 +0100
commit0094472cda6eefa9b5363ad844daf0fcfd00c326 (patch)
treeb577f931820ef3899da856f9ccd0de04f4c8ffa8 /omx.c
parent88f137d194b1768344e954a1b1d35fb1fce03df9 (diff)
downloadvdr-plugin-rpihddevice-0.0.8.tar.gz
vdr-plugin-rpihddevice-0.0.8.tar.bz2
2014-02-10: Version 0.0.80.0.8
------------------------- - new: - image grabbing - implemented proper handling in case of buffer stall - reporting video size - support letter box and center cut out set by VDR - support video scaling - fixed: - increased number of audio buffer to fix replay issues with PES recordings - return correct number of audio bytes written from PlayAudio() - fixed start up in audio only mode - fixed still image with deinterlacer - fixed crash during deinitialization - fixed crash when copying 5.1 PCM audio - use cThread::mutex for locking - implement cOvgOsd::SetAreas() and cOvgOsd::SetActive() - audio codec clean up, drop AAC-LATM and rename ADTS to AAC - audio decoding thread clean up - known issues - StillImage() will cause buffer stall - artifacts with StillImage() and PES recordings - speed to fast when fast replaying audio only recordings
Diffstat (limited to 'omx.c')
-rw-r--r--omx.c386
1 files changed, 238 insertions, 148 deletions
diff --git a/omx.c b/omx.c
index e049281..7e79f87 100644
--- a/omx.c
+++ b/omx.c
@@ -17,12 +17,12 @@ extern "C" {
#include "bcm_host.h"
#define OMX_INIT_STRUCT(a) \
- memset(&(a), 0, sizeof(a)); \
- (a).nSize = sizeof(a); \
- (a).nVersion.s.nVersionMajor = OMX_VERSION_MAJOR; \
- (a).nVersion.s.nVersionMinor = OMX_VERSION_MINOR; \
- (a).nVersion.s.nRevision = OMX_VERSION_REVISION; \
- (a).nVersion.s.nStep = OMX_VERSION_STEP
+ memset(&(a), 0, sizeof(a)); \
+ (a).nSize = sizeof(a); \
+ (a).nVersion.s.nVersionMajor = OMX_VERSION_MAJOR; \
+ (a).nVersion.s.nVersionMinor = OMX_VERSION_MINOR; \
+ (a).nVersion.s.nRevision = OMX_VERSION_REVISION; \
+ (a).nVersion.s.nStep = OMX_VERSION_STEP
#define OMX_AUDIO_CHANNEL_MAPPING(s, c) \
switch (c) { \
@@ -104,26 +104,32 @@ void cOmx::Action(void)
{
while (Running())
{
- m_portEventReady->Wait();
+ m_eventReady->Wait();
while (!m_portEvents->empty())
{
HandlePortSettingsChanged(m_portEvents->front());
m_portEvents->pop();
}
+ if (m_stallEvent)
+ {
+ if (IsBufferStall() && m_onBufferStall)
+ m_onBufferStall(m_onBufferStallData);
+ m_stallEvent = false;
+ }
}
}
void cOmx::HandlePortSettingsChanged(unsigned int portId)
{
-// dsyslog("rpihddevice: HandlePortSettingsChanged(%d)", portId);
+ DBG("HandlePortSettingsChanged(%d)", portId);
switch (portId)
{
case 191:
if (ilclient_setup_tunnel(&m_tun[eVideoFxToVideoScheduler], 0, 0) != 0)
- esyslog("rpihddevice: failed to setup up tunnel from video fx to scheduler!");
+ ELOG("failed to setup up tunnel from video fx to scheduler!");
if (ilclient_change_component_state(m_comp[eVideoScheduler], OMX_StateExecuting) != 0)
- esyslog("rpihddevice: failed to enable video scheduler!");
+ ELOG("failed to enable video scheduler!");
break;
case 131:
@@ -132,46 +138,51 @@ void cOmx::HandlePortSettingsChanged(unsigned int portId)
portdef.nPortIndex = 131;
if (OMX_GetParameter(ILC_GET_HANDLE(m_comp[eVideoDecoder]), OMX_IndexParamPortDefinition,
&portdef) != OMX_ErrorNone)
- esyslog("rpihddevice: failed to get video decoder port format!");
+ ELOG("failed to get video decoder port format!");
OMX_CONFIG_INTERLACETYPE interlace;
OMX_INIT_STRUCT(interlace);
interlace.nPortIndex = 131;
if (OMX_GetConfig(ILC_GET_HANDLE(m_comp[eVideoDecoder]), OMX_IndexConfigCommonInterlace,
&interlace) != OMX_ErrorNone)
- esyslog("rpihddevice: failed to get video decoder interlace config!");
+ ELOG("failed to get video decoder interlace config!");
+
+ m_videoWidth = portdef.format.video.nFrameWidth;
+ m_videoHeight = portdef.format.video.nFrameHeight;
+ m_videoInterlaced = interlace.eMode != OMX_InterlaceProgressive;
bool deinterlace;
- deinterlace = (cRpiSetup::IsDisplayProgressive() &&
- (interlace.eMode != OMX_InterlaceProgressive));
+ deinterlace = (cRpiSetup::IsDisplayProgressive() && m_videoInterlaced);
- dsyslog("rpihddevice: decoding video %dx%d%s, %sabling deinterlacer",
- portdef.format.video.nFrameWidth,
- portdef.format.video.nFrameHeight,
- interlace.eMode == OMX_InterlaceProgressive ? "p" : "i",
+ ILOG("decoding video %dx%d%s, %sabling deinterlacer",
+ m_videoWidth, m_videoHeight, m_videoInterlaced ? "i" : "p",
deinterlace ? "en" : "dis");
OMX_CONFIG_IMAGEFILTERPARAMSTYPE filterparam;
OMX_INIT_STRUCT(filterparam);
filterparam.nPortIndex = 191;
- filterparam.nNumParams = 1;
- filterparam.nParams[0] = 3;
- filterparam.eImageFilter = deinterlace ? OMX_ImageFilterDeInterlaceAdvanced : OMX_ImageFilterNone;
+ filterparam.eImageFilter = OMX_ImageFilterNone;
+ if (deinterlace)
+ {
+ filterparam.nNumParams = 1;
+ filterparam.nParams[0] = 3;
+ filterparam.eImageFilter = OMX_ImageFilterDeInterlaceAdvanced;
+ }
if (OMX_SetConfig(ILC_GET_HANDLE(m_comp[eVideoFx]),
OMX_IndexConfigCommonImageFilterParameters, &filterparam) != OMX_ErrorNone)
- esyslog("rpihddevice: failed to set deinterlacing paramaters!");
+ ELOG("failed to set deinterlacing paramaters!");
if (ilclient_setup_tunnel(&m_tun[eVideoDecoderToVideoFx], 0, 0) != 0)
- esyslog("rpihddevice: failed to setup up tunnel from video decoder to fx!");
+ ELOG("failed to setup up tunnel from video decoder to fx!");
if (ilclient_change_component_state(m_comp[eVideoFx], OMX_StateExecuting) != 0)
- esyslog("rpihddevice: failed to enable video fx!");
+ ELOG("failed to enable video fx!");
break;
case 11:
- if (ilclient_setup_tunnel(&m_tun[eVideoSchedulerToVideoRender], 0, 1000) != 0)
- esyslog("rpihddevice: failed to setup up tunnel from scheduler to render!");
+ if (ilclient_setup_tunnel(&m_tun[eVideoSchedulerToVideoRender], 0, 0) != 0)
+ ELOG("failed to setup up tunnel from scheduler to render!");
if (ilclient_change_component_state(m_comp[eVideoRender], OMX_StateExecuting) != 0)
- esyslog("rpihddevice: failed to enable video render!");
+ ELOG("failed to enable video render!");
break;
}
}
@@ -189,38 +200,54 @@ void cOmx::OnPortSettingsChanged(void *instance, COMPONENT_T *comp, OMX_U32 data
{
cOmx* omx = static_cast <cOmx*> (instance);
omx->m_portEvents->push(data);
- omx->m_portEventReady->Signal();
+ omx->m_eventReady->Signal();
}
void cOmx::OnEndOfStream(void *instance, COMPONENT_T *comp, OMX_U32 data)
{
- cOmx* omx = static_cast <cOmx*> (instance);
+ //cOmx* omx = static_cast <cOmx*> (instance);
}
void cOmx::OnError(void *instance, COMPONENT_T *comp, OMX_U32 data)
{
if ((OMX_S32)data != OMX_ErrorSameState)
- esyslog("rpihddevice: OmxError(%s)", errStr((int)data));
+ ELOG("OmxError(%s)", errStr((int)data));
+}
+
+void cOmx::OnConfigChanged(void *instance, COMPONENT_T *comp, OMX_U32 data)
+{
+ cOmx* omx = static_cast <cOmx*> (instance);
+ if (data == OMX_IndexConfigBufferStall)
+ {
+ omx->m_stallEvent = true;
+ omx->m_eventReady->Signal();
+ }
}
cOmx::cOmx() :
cThread(),
- m_mutex(new cMutex()),
+ m_videoWidth(0),
+ m_videoHeight(0),
+ m_videoInterlaced(false),
m_setAudioStartTime(false),
m_setVideoStartTime(false),
m_setVideoDiscontinuity(false),
m_freeAudioBuffers(0),
m_freeVideoBuffers(0),
- m_clockReference(eClockRefAudio),
- m_portEventReady(new cCondWait()),
- m_portEvents(new std::queue<unsigned int>)
+ m_clockReference(eClockRefNone),
+ m_eventReady(new cCondWait()),
+ m_portEvents(new std::queue<unsigned int>),
+ m_stallEvent(false),
+ m_onBufferStall(0),
+ m_onBufferStallData(0)
{
+ memset(m_tun, 0, sizeof(m_tun));
+ memset(m_comp, 0, sizeof(m_comp));
}
cOmx::~cOmx()
{
- delete m_mutex;
- delete m_portEventReady;
+ delete m_eventReady;
delete m_portEvents;
}
@@ -228,47 +255,48 @@ int cOmx::Init(void)
{
m_client = ilclient_init();
if (m_client == NULL)
- esyslog("rpihddevice: ilclient_init() failed!");
+ ELOG("ilclient_init() failed!");
if (OMX_Init() != OMX_ErrorNone)
- esyslog("rpihddevice: OMX_Init() failed!");
+ ELOG("OMX_Init() failed!");
ilclient_set_error_callback(m_client, OnError, this);
ilclient_set_empty_buffer_done_callback(m_client, OnBufferEmpty, this);
ilclient_set_port_settings_callback(m_client, OnPortSettingsChanged, this);
ilclient_set_eos_callback(m_client, OnEndOfStream, this);
+ ilclient_set_configchanged_callback(m_client, OnConfigChanged, this);
// create video_decode
if (ilclient_create_component(m_client, &m_comp[eVideoDecoder],
"video_decode", (ILCLIENT_CREATE_FLAGS_T)
(ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_INPUT_BUFFERS)) != 0)
- esyslog("rpihddevice: failed creating video decoder!");
+ ELOG("failed creating video decoder!");
// create image_fx
if (ilclient_create_component(m_client, &m_comp[eVideoFx],
"image_fx", ILCLIENT_DISABLE_ALL_PORTS) != 0)
- esyslog("rpihddevice: failed creating video fx!");
+ ELOG("failed creating video fx!");
// create video_render
if (ilclient_create_component(m_client, &m_comp[eVideoRender],
"video_render", ILCLIENT_DISABLE_ALL_PORTS) != 0)
- esyslog("rpihddevice: failed creating video render!");
+ ELOG("failed creating video render!");
//create clock
if (ilclient_create_component(m_client, &m_comp[eClock],
"clock", ILCLIENT_DISABLE_ALL_PORTS) != 0)
- esyslog("rpihddevice: failed creating clock!");
+ ELOG("failed creating clock!");
// create audio_render
if (ilclient_create_component(m_client, &m_comp[eAudioRender],
"audio_render", (ILCLIENT_CREATE_FLAGS_T)
(ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_INPUT_BUFFERS)) != 0)
- esyslog("rpihddevice: failed creating audio render!");
+ ELOG("failed creating audio render!");
//create video_scheduler
if (ilclient_create_component(m_client, &m_comp[eVideoScheduler],
"video_scheduler", ILCLIENT_DISABLE_ALL_PORTS) != 0)
- esyslog("rpihddevice: failed creating video scheduler!");
+ ELOG("failed creating video scheduler!");
// setup tunnels
set_tunnel(&m_tun[eVideoDecoderToVideoFx],
@@ -288,62 +316,45 @@ int cOmx::Init(void)
// setup clock tunnels first
if (ilclient_setup_tunnel(&m_tun[eClockToVideoScheduler], 0, 0) != 0)
- esyslog("rpihddevice: failed to setup up tunnel from clock to video scheduler!");
+ ELOG("failed to setup up tunnel from clock to video scheduler!");
if (ilclient_setup_tunnel(&m_tun[eClockToAudioRender], 0, 0) != 0)
- esyslog("rpihddevice: failed to setup up tunnel from clock to audio render!");
+ ELOG("failed to setup up tunnel from clock to audio render!");
ilclient_change_component_state(m_comp[eClock], OMX_StateExecuting);
ilclient_change_component_state(m_comp[eVideoDecoder], OMX_StateIdle);
ilclient_change_component_state(m_comp[eVideoFx], OMX_StateIdle);
+ ilclient_change_component_state(m_comp[eAudioRender], OMX_StateIdle);
// set up the number and size of buffers for audio render
- m_freeAudioBuffers = 2; //64;
+ m_freeAudioBuffers = 8;
OMX_PARAM_PORTDEFINITIONTYPE param;
OMX_INIT_STRUCT(param);
param.nPortIndex = 100;
if (OMX_GetParameter(ILC_GET_HANDLE(m_comp[eAudioRender]),
OMX_IndexParamPortDefinition, &param) != OMX_ErrorNone)
- esyslog("rpihddevice: failed to get audio render port parameters!");
- param.nBufferSize = 160 * 1024;
+ ELOG("failed to get audio render port parameters!");
+ param.nBufferSize = KILOBYTE(160);
param.nBufferCountActual = m_freeAudioBuffers;
if (OMX_SetParameter(ILC_GET_HANDLE(m_comp[eAudioRender]),
OMX_IndexParamPortDefinition, &param) != OMX_ErrorNone)
- esyslog("rpihddevice: failed to set audio render port parameters!");
+ ELOG("failed to set audio render port parameters!");
OMX_INIT_STRUCT(param);
param.nPortIndex = 130;
if (OMX_GetParameter(ILC_GET_HANDLE(m_comp[eVideoDecoder]),
OMX_IndexParamPortDefinition, &param) != OMX_ErrorNone)
- esyslog("rpihddevice: failed to get video decoder port parameters!");
+ ELOG("failed to get video decoder port parameters!");
m_freeVideoBuffers = param.nBufferCountActual;
- dsyslog("rpihddevice: started with %d video and %d audio buffers",
+ DBG("started with %d video and %d audio buffers",
m_freeVideoBuffers, m_freeAudioBuffers);
-/* // configure video decoder stall callback
- OMX_CONFIG_BUFFERSTALLTYPE stallConf;
- OMX_INIT_STRUCT(stallConf);
- stallConf.nPortIndex = 131;
- stallConf.nDelay = 1500 * 1000;
- if (OMX_SetConfig(m_comp[eVideoDecoder], OMX_IndexConfigBufferStall,
- &stallConf) != OMX_ErrorNone)
- esyslog("rpihddevice: failed to set video decoder stall config!");
+ SetBufferStall(1500);
- OMX_CONFIG_REQUESTCALLBACKTYPE reqCallback;
- OMX_INIT_STRUCT(reqCallback);
- reqCallback.nPortIndex = 131;
- reqCallback.nIndex = OMX_IndexConfigBufferStall;
- reqCallback.bEnable = OMX_TRUE;
- if (OMX_SetConfig(m_comp[eVideoDecoder], OMX_IndexConfigRequestCallback,
- &reqCallback) != OMX_ErrorNone)
- esyslog("rpihddevice: failed to set video decoder stall callback!");
-*/
-// if (ilclient_enable_port_buffers(m_comp[eAudioRender], 100, NULL, NULL, NULL) != 0)
-// esyslog("rpihddevice: failed to enable port buffer on audio render!");
-
- SetClockState(cOmx::eClockStateRun);
+ FlushVideo();
+ FlushAudio();
Start();
@@ -360,11 +371,18 @@ int cOmx::DeInit(void)
ilclient_cleanup_components(m_comp);
OMX_Deinit();
+
ilclient_destroy(m_client);
return 0;
}
+void cOmx::SetBufferStallCallback(void (*onBufferStall)(void*), void* data)
+{
+ m_onBufferStall = onBufferStall;
+ m_onBufferStallData = data;
+}
+
OMX_TICKS cOmx::ToOmxTicks(int64_t val)
{
OMX_TICKS ticks;
@@ -399,20 +417,16 @@ uint64_t cOmx::TicksToPts(OMX_TICKS &ticks)
int64_t cOmx::GetSTC(void)
{
int64_t stc = -1;
-// return stc;
-
OMX_TIME_CONFIG_TIMESTAMPTYPE timestamp;
OMX_INIT_STRUCT(timestamp);
timestamp.nPortIndex = OMX_ALL;
if (OMX_GetConfig(ILC_GET_HANDLE(m_comp[eClock]),
OMX_IndexConfigTimeCurrentMediaTime, &timestamp) != OMX_ErrorNone)
- esyslog("rpihddevice: failed get current clock reference!");
+ ELOG("failed get current clock reference!");
else
stc = TicksToPts(timestamp.nTimestamp);
-// dsyslog("S %u", timestamp.nTimestamp.nLowPart);
-
return stc;
}
@@ -423,7 +437,7 @@ bool cOmx::IsClockRunning(void)
if (OMX_GetConfig(ILC_GET_HANDLE(m_comp[eClock]),
OMX_IndexConfigTimeClockState, &cstate) != OMX_ErrorNone)
- esyslog("rpihddevice: failed get clock state!");
+ ELOG("failed get clock state!");
if (cstate.eState == OMX_TIME_ClockStateRunning)
return true;
@@ -433,20 +447,20 @@ bool cOmx::IsClockRunning(void)
void cOmx::SetClockState(eClockState clockState)
{
-/* dsyslog("rpihddevice: SetClockState(%s)",
+ DBG("SetClockState(%s)",
clockState == eClockStateRun ? "eClockStateRun" :
clockState == eClockStateStop ? "eClockStateStop" :
clockState == eClockStateWaitForVideo ? "eClockStateWaitForVideo" :
clockState == eClockStateWaitForAudio ? "eClockStateWaitForAudio" :
clockState == eClockStateWaitForAudioVideo ? "eClockStateWaitForAudioVideo" :
"unknown");
-*/
+
OMX_TIME_CONFIG_CLOCKSTATETYPE cstate;
OMX_INIT_STRUCT(cstate);
if (OMX_GetConfig(ILC_GET_HANDLE(m_comp[eClock]),
OMX_IndexConfigTimeClockState, &cstate) != OMX_ErrorNone)
- esyslog("rpihddevice: failed to get clock state!");
+ ELOG("failed to get clock state!");
// if clock is already running, we need to stop it first
if ((cstate.eState == OMX_TIME_ClockStateRunning) &&
@@ -457,7 +471,7 @@ void cOmx::SetClockState(eClockState clockState)
cstate.eState = OMX_TIME_ClockStateStopped;
if (OMX_SetConfig(ILC_GET_HANDLE(m_comp[eClock]),
OMX_IndexConfigTimeClockState, &cstate) != OMX_ErrorNone)
- esyslog("rpihddevice: failed to stop clock!");
+ ELOG("failed to stop clock!");
}
cstate.nWaitMask = 0;
@@ -492,13 +506,13 @@ void cOmx::SetClockState(eClockState clockState)
break;
}
- if (cstate.eState == OMX_TIME_ClockStateWaitingForStartTime)
- // 200ms pre roll, value taken from omxplayer
- cstate.nOffset = ToOmxTicks(-1000LL * 200);
+// if (cstate.eState == OMX_TIME_ClockStateWaitingForStartTime)
+ // 50ms pre roll, was 200ms at omxplayer
+// cstate.nOffset = ToOmxTicks(-1000LL * 50);
if (OMX_SetConfig(ILC_GET_HANDLE(m_comp[eClock]),
OMX_IndexConfigTimeClockState, &cstate) != OMX_ErrorNone)
- esyslog("rpihddevice: failed to set clock state!");
+ ELOG("failed to set clock state!");
}
void cOmx::SetClockScale(float scale)
@@ -509,7 +523,7 @@ void cOmx::SetClockScale(float scale)
if (OMX_SetConfig(ILC_GET_HANDLE(m_comp[eClock]),
OMX_IndexConfigTimeScale, &scaleType) != OMX_ErrorNone)
- esyslog("rpihddevice: failed to set clock scale (%d)!", scaleType.xScale);
+ ELOG("failed to set clock scale (%d)!", scaleType.xScale);
}
void cOmx::SetStartTime(uint64_t pts)
@@ -521,7 +535,7 @@ void cOmx::SetStartTime(uint64_t pts)
if (OMX_SetConfig(ILC_GET_HANDLE(m_comp[eClock]),
OMX_IndexConfigTimeClientStartTime, &timeStamp) != OMX_ErrorNone)
- esyslog("rpihddevice: failed to set current start time!");
+ ELOG("failed to set current start time!");
}
void cOmx::SetCurrentReferenceTime(uint64_t pts)
@@ -535,7 +549,7 @@ void cOmx::SetCurrentReferenceTime(uint64_t pts)
m_clockReference == eClockRefAudio ?
OMX_IndexConfigTimeCurrentAudioReference :
OMX_IndexConfigTimeCurrentVideoReference, &timeStamp) != OMX_ErrorNone)
- esyslog("rpihddevice: failed to set current %s reference time!",
+ ELOG("failed to set current %s reference time!",
m_clockReference == eClockRefAudio ? "audio" : "video");
}
@@ -549,7 +563,7 @@ unsigned int cOmx::GetMediaTime(void)
if (OMX_GetConfig(ILC_GET_HANDLE(m_comp[eClock]),
OMX_IndexConfigTimeCurrentMediaTime, &timestamp) != OMX_ErrorNone)
- esyslog("rpihddevice: failed get current clock reference!");
+ ELOG("failed get current clock reference!");
else
ret = timestamp.nTimestamp.nLowPart;
@@ -558,19 +572,61 @@ unsigned int cOmx::GetMediaTime(void)
void cOmx::SetClockReference(eClockReference clockReference)
{
- m_clockReference = clockReference;
+ if (m_clockReference != clockReference)
+ {
+ OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE refClock;
+ OMX_INIT_STRUCT(refClock);
+ refClock.eClock =
+ (clockReference == eClockRefAudio) ? OMX_TIME_RefClockAudio :
+ (clockReference == eClockRefVideo) ? OMX_TIME_RefClockVideo :
+ OMX_TIME_RefClockNone;
- OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE refClock;
- OMX_INIT_STRUCT(refClock);
- refClock.eClock = (m_clockReference == eClockRefAudio) ?
- OMX_TIME_RefClockAudio : OMX_TIME_RefClockVideo;
+ if (OMX_SetConfig(ILC_GET_HANDLE(m_comp[eClock]),
+ OMX_IndexConfigTimeActiveRefClock, &refClock) != OMX_ErrorNone)
+ ELOG("failed set active clock reference!");
+ else
+ DBG("set active clock reference to %s",
+ clockReference == eClockRefAudio ? "audio" :
+ clockReference == eClockRefVideo ? "video" : "none");
+
+ m_clockReference = clockReference;
+ }
+}
- if (OMX_SetConfig(ILC_GET_HANDLE(m_comp[eClock]),
- OMX_IndexConfigTimeActiveRefClock, &refClock) != OMX_ErrorNone)
- esyslog("rpihddevice: failed set active clock reference!");
-/* else
- dsyslog("rpihddevice: set active clock reference to %s",
- m_clockReference == eClockRefAudio ? "audio" : "video"); */
+void cOmx::SetBufferStall(int delayMs)
+{
+ if (delayMs > 0)
+ {
+ OMX_CONFIG_BUFFERSTALLTYPE stallConf;
+ OMX_INIT_STRUCT(stallConf);
+ stallConf.nPortIndex = 131;
+ stallConf.nDelay = delayMs * 1000;
+ if (OMX_SetConfig(ILC_GET_HANDLE(m_comp[eVideoDecoder]),
+ OMX_IndexConfigBufferStall, &stallConf) != OMX_ErrorNone)
+ ELOG("failed to set video decoder stall config!");
+ }
+
+ // set buffer stall call back
+ OMX_CONFIG_REQUESTCALLBACKTYPE reqCallback;
+ OMX_INIT_STRUCT(reqCallback);
+ reqCallback.nPortIndex = 131;
+ reqCallback.nIndex = OMX_IndexConfigBufferStall;
+ reqCallback.bEnable = delayMs > 0 ? OMX_TRUE : OMX_FALSE;
+ if (OMX_SetConfig(ILC_GET_HANDLE(m_comp[eVideoDecoder]),
+ OMX_IndexConfigRequestCallback, &reqCallback) != OMX_ErrorNone)
+ ELOG("failed to set video decoder stall call back!");
+}
+
+bool cOmx::IsBufferStall(void)
+{
+ OMX_CONFIG_BUFFERSTALLTYPE stallConf;
+ OMX_INIT_STRUCT(stallConf);
+ stallConf.nPortIndex = 131;
+ if (OMX_GetConfig(ILC_GET_HANDLE(m_comp[eVideoDecoder]),
+ OMX_IndexConfigBufferStall, &stallConf) != OMX_ErrorNone)
+ ELOG("failed to get video decoder stall config!");
+
+ return stallConf.bStalled == OMX_TRUE;
}
void cOmx::SetVolume(int vol)
@@ -583,7 +639,7 @@ void cOmx::SetVolume(int vol)
if (OMX_SetConfig(ILC_GET_HANDLE(m_comp[eAudioRender]),
OMX_IndexConfigAudioVolume, &volume) != OMX_ErrorNone)
- esyslog("rpihddevice: failed to set volume!");
+ ELOG("failed to set volume!");
}
void cOmx::SetMute(bool mute)
@@ -595,7 +651,7 @@ void cOmx::SetMute(bool mute)
if (OMX_SetConfig(ILC_GET_HANDLE(m_comp[eAudioRender]),
OMX_IndexConfigAudioMute, &amute) != OMX_ErrorNone)
- esyslog("rpihddevice: failed to set mute state!");
+ ELOG("failed to set mute state!");
}
void cOmx::SendEos(void)
@@ -609,17 +665,15 @@ void cOmx::SendEos(void)
buf->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN | OMX_BUFFERFLAG_EOS;
if (OMX_EmptyThisBuffer(ILC_GET_HANDLE(m_comp[eVideoDecoder]), buf) != OMX_ErrorNone)
- esyslog("rpihddevice: failed to send empty packet to video decoder!");
+ ELOG("failed to send empty packet to video decoder!");
if (!m_eosEvent->Wait(10000))
- esyslog("rpihddevice: time out waiting for EOS event!");
+ ELOG("time out waiting for EOS event!");
#endif
}
void cOmx::StopVideo(void)
{
- dsyslog("rpihddevice: StopVideo()");
-
// put video decoder into idle
ilclient_change_component_state(m_comp[eVideoDecoder], OMX_StateIdle);
@@ -642,13 +696,17 @@ void cOmx::StopVideo(void)
// disable port buffers and allow video decoder to reconfig
ilclient_disable_port_buffers(m_comp[eVideoDecoder], 130, NULL, NULL, NULL);
+
+ m_videoWidth = 0;
+ m_videoHeight = 0;
+ m_videoInterlaced = false;
}
void cOmx::StopAudio(void)
{
// put audio render onto idle
ilclient_flush_tunnels(&m_tun[eClockToAudioRender], 1);
-// ilclient_disable_tunnel(&m_tun[eClockToAudioRender]);
+ ilclient_disable_tunnel(&m_tun[eClockToAudioRender]);
ilclient_change_component_state(m_comp[eAudioRender], OMX_StateIdle);
ilclient_disable_port_buffers(m_comp[eAudioRender], 100, NULL, NULL, NULL);
}
@@ -665,7 +723,7 @@ void cOmx::SetVideoDataUnitType(eDataUnitType dataUnitType)
if (OMX_SetParameter(ILC_GET_HANDLE(m_comp[eVideoDecoder]),
OMX_IndexParamBrcmDataUnit, &dataUnit) != OMX_ErrorNone)
- esyslog("rpihddevice: failed to set video decoder data unit type!");
+ ELOG("failed to set video decoder data unit type!");
}
@@ -676,7 +734,7 @@ void cOmx::SetVideoErrorConcealment(bool startWithValidFrame)
ectype.bStartWithValidFrame = startWithValidFrame ? OMX_TRUE : OMX_FALSE;
if (OMX_SetParameter(ILC_GET_HANDLE(m_comp[eVideoDecoder]),
OMX_IndexParamBrcmVideoDecodeErrorConcealment, &ectype) != OMX_ErrorNone)
- esyslog("rpihddevice: failed to set video decode error concealment failed\n");
+ ELOG("failed to set video decode error concealment failed\n");
}
void cOmx::FlushAudio(void)
@@ -684,7 +742,7 @@ void cOmx::FlushAudio(void)
ilclient_flush_tunnels(&m_tun[eClockToAudioRender], 1);
if (OMX_SendCommand(ILC_GET_HANDLE(m_comp[eAudioRender]), OMX_CommandFlush, 100, NULL) != OMX_ErrorNone)
- esyslog("rpihddevice: failed to flush audio render!");
+ ELOG("failed to flush audio render!");
}
void cOmx::FlushVideo(bool flushRender)
@@ -692,7 +750,7 @@ void cOmx::FlushVideo(bool flushRender)
ilclient_flush_tunnels(&m_tun[eClockToVideoScheduler], 1);
if (OMX_SendCommand(ILC_GET_HANDLE(m_comp[eVideoDecoder]), OMX_CommandFlush, 130, NULL) != OMX_ErrorNone)
- esyslog("rpihddevice: failed to flush video decoder!");
+ ELOG("failed to flush video decoder!");
ilclient_flush_tunnels(&m_tun[eVideoDecoderToVideoFx], 1);
ilclient_flush_tunnels(&m_tun[eVideoFxToVideoScheduler], 1);
@@ -706,7 +764,7 @@ void cOmx::FlushVideo(bool flushRender)
int cOmx::SetVideoCodec(cVideoCodec::eCodec codec, eDataUnitType dataUnit)
{
if (ilclient_change_component_state(m_comp[eVideoDecoder], OMX_StateIdle) != 0)
- esyslog("rpihddevice: failed to set video decoder to idle state!");
+ ELOG("failed to set video decoder to idle state!");
// configure video decoder
OMX_VIDEO_PARAM_PORTFORMATTYPE videoFormat;
@@ -719,7 +777,7 @@ int cOmx::SetVideoCodec(cVideoCodec::eCodec codec, eDataUnitType dataUnit)
if (OMX_SetParameter(ILC_GET_HANDLE(m_comp[eVideoDecoder]),
OMX_IndexParamVideoPortFormat, &videoFormat) != OMX_ErrorNone)
- esyslog("rpihddevice: failed to set video decoder parameters!");
+ ELOG("failed to set video decoder parameters!");
// start with valid frames only if codec is MPEG2
SetVideoErrorConcealment(codec == cVideoCodec::eMPEG2);
@@ -727,14 +785,14 @@ int cOmx::SetVideoCodec(cVideoCodec::eCodec codec, eDataUnitType dataUnit)
SetVideoDecoderExtraBuffers(3);
if (ilclient_enable_port_buffers(m_comp[eVideoDecoder], 130, NULL, NULL, NULL) != 0)
- esyslog("rpihddevice: failed to enable port buffer on video decoder!");
+ ELOG("failed to enable port buffer on video decoder!");
if (ilclient_change_component_state(m_comp[eVideoDecoder], OMX_StateExecuting) != 0)
- esyslog("rpihddevice: failed to set video decoder to executing state!");
+ ELOG("failed to set video decoder to executing state!");
// setup clock tunnels first
if (ilclient_setup_tunnel(&m_tun[eClockToVideoScheduler], 0, 0) != 0)
- esyslog("rpihddevice: failed to setup up tunnel from clock to video scheduler!");
+ ELOG("failed to setup up tunnel from clock to video scheduler!");
return 0;
}
@@ -747,27 +805,18 @@ void cOmx::SetVideoDecoderExtraBuffers(int extraBuffers)
u32.nU32 = extraBuffers;
if (OMX_SetParameter(ILC_GET_HANDLE(m_comp[eVideoDecoder]),
OMX_IndexParamBrcmExtraBuffers, &u32) != OMX_ErrorNone)
- esyslog("rpihddevice: failed to set video decoder extra buffers!");
+ ELOG("failed to set video decoder extra buffers!");
}
int cOmx::SetupAudioRender(cAudioCodec::eCodec outputFormat, int channels,
cAudioPort::ePort audioPort, int samplingRate)
{
- // put audio render onto idle
- ilclient_flush_tunnels(&m_tun[eClockToAudioRender], 1);
- ilclient_disable_tunnel(&m_tun[eClockToAudioRender]);
- ilclient_change_component_state(m_comp[eAudioRender], OMX_StateIdle);
- ilclient_disable_port_buffers(m_comp[eAudioRender], 100, NULL, NULL, NULL);
-
- if (OMX_SendCommand(ILC_GET_HANDLE(m_comp[eAudioRender]), OMX_CommandFlush, 100, NULL) != OMX_ErrorNone)
- esyslog("rpihddevice: failed to flush audio render!");
-
OMX_AUDIO_PARAM_PORTFORMATTYPE format;
OMX_INIT_STRUCT(format);
format.nPortIndex = 100;
if (OMX_GetParameter(ILC_GET_HANDLE(m_comp[eAudioRender]),
OMX_IndexParamAudioPortFormat, &format) != OMX_ErrorNone)
- esyslog("rpihddevice: failed to get audio port format parameters!");
+ ELOG("failed to get audio port format parameters!");
format.eEncoding =
outputFormat == cAudioCodec::ePCM ? OMX_AUDIO_CodingPCM :
@@ -775,12 +824,12 @@ int cOmx::SetupAudioRender(cAudioCodec::eCodec outputFormat, int channels,
outputFormat == cAudioCodec::eAC3 ? OMX_AUDIO_CodingDDP :
outputFormat == cAudioCodec::eEAC3 ? OMX_AUDIO_CodingDDP :
outputFormat == cAudioCodec::eAAC ? OMX_AUDIO_CodingAAC :
- outputFormat == cAudioCodec::eADTS ? OMX_AUDIO_CodingAAC :
+ outputFormat == cAudioCodec::eAAC ? OMX_AUDIO_CodingAAC :
OMX_AUDIO_CodingAutoDetect;
if (OMX_SetParameter(ILC_GET_HANDLE(m_comp[eAudioRender]),
OMX_IndexParamAudioPortFormat, &format) != OMX_ErrorNone)
- esyslog("rpihddevice: failed to set audio port format parameters!");
+ ELOG("failed to set audio port format parameters!");
switch (outputFormat)
{
@@ -795,7 +844,7 @@ int cOmx::SetupAudioRender(cAudioCodec::eCodec outputFormat, int channels,
if (OMX_SetParameter(ILC_GET_HANDLE(m_comp[eAudioRender]),
OMX_IndexParamAudioMp3, &mp3) != OMX_ErrorNone)
- esyslog("rpihddevice: failed to set audio render mp3 parameters!");
+ ELOG("failed to set audio render mp3 parameters!");
break;
case cAudioCodec::eAC3:
@@ -809,24 +858,20 @@ int cOmx::SetupAudioRender(cAudioCodec::eCodec outputFormat, int channels,
if (OMX_SetParameter(ILC_GET_HANDLE(m_comp[eAudioRender]),
OMX_IndexParamAudioDdp, &ddp) != OMX_ErrorNone)
- esyslog("rpihddevice: failed to set audio render ddp parameters!");
+ ELOG("failed to set audio render ddp parameters!");
break;
case cAudioCodec::eAAC:
- case cAudioCodec::eADTS:
OMX_AUDIO_PARAM_AACPROFILETYPE aac;
OMX_INIT_STRUCT(aac);
aac.nPortIndex = 100;
aac.nChannels = channels;
aac.nSampleRate = samplingRate;
- aac.eAACStreamFormat =
- outputFormat == cAudioCodec::eAAC ? OMX_AUDIO_AACStreamFormatMP4LATM :
- outputFormat == cAudioCodec::eADTS ? OMX_AUDIO_AACStreamFormatMP4ADTS :
- (OMX_AUDIO_AACSTREAMFORMATTYPE)0;
+ aac.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
if (OMX_SetParameter(ILC_GET_HANDLE(m_comp[eAudioRender]),
OMX_IndexParamAudioAac, &aac) != OMX_ErrorNone)
- esyslog("rpihddevice: failed to set audio render aac parameters!");
+ ELOG("failed to set audio render aac parameters!");
break;
case cAudioCodec::ePCM:
@@ -844,11 +889,11 @@ int cOmx::SetupAudioRender(cAudioCodec::eCodec outputFormat, int channels,
if (OMX_SetParameter(ILC_GET_HANDLE(m_comp[eAudioRender]),
OMX_IndexParamAudioPcm, &pcm) != OMX_ErrorNone)
- esyslog("rpihddevice: failed to set audio render pcm parameters!");
+ ELOG("failed to set audio render pcm parameters!");
break;
default:
- esyslog("rpihddevice: output codec not supported: %s!",
+ ELOG("output codec not supported: %s!",
cAudioCodec::Str(outputFormat));
break;
}
@@ -860,22 +905,65 @@ int cOmx::SetupAudioRender(cAudioCodec::eCodec outputFormat, int channels,
if (OMX_SetConfig(ILC_GET_HANDLE(m_comp[eAudioRender]),
OMX_IndexConfigBrcmAudioDestination, &audioDest) != OMX_ErrorNone)
- esyslog("rpihddevice: failed to set audio destination!");
+ ELOG("failed to set audio destination!");
if (ilclient_enable_port_buffers(m_comp[eAudioRender], 100, NULL, NULL, NULL) != 0)
- esyslog("rpihddevice: failed to enable port buffer on audio render!");
+ ELOG("failed to enable port buffer on audio render!");
ilclient_change_component_state(m_comp[eAudioRender], OMX_StateExecuting);
if (ilclient_setup_tunnel(&m_tun[eClockToAudioRender], 0, 0) != 0)
- esyslog("rpihddevice: failed to setup up tunnel from clock to video scheduler!");
+ ELOG("failed to setup up tunnel from clock to video scheduler!");
return 0;
}
+void cOmx::GetVideoSize(int &width, int &height, bool &interlaced)
+{
+ width = m_videoWidth;
+ height = m_videoHeight;
+ interlaced = m_videoInterlaced;
+}
+
+void cOmx::SetDisplayMode(bool letterbox, bool noaspect)
+{
+ OMX_CONFIG_DISPLAYREGIONTYPE region;
+ OMX_INIT_STRUCT(region);
+ region.nPortIndex = 90;
+ region.set = (OMX_DISPLAYSETTYPE)
+ (OMX_DISPLAY_SET_MODE | OMX_DISPLAY_SET_NOASPECT);
+
+ region.noaspect = noaspect ? OMX_TRUE : OMX_FALSE;
+ region.mode = letterbox ?
+ OMX_DISPLAY_MODE_LETTERBOX : OMX_DISPLAY_MODE_FILL;
+
+ if (OMX_SetConfig(ILC_GET_HANDLE(m_comp[eVideoRender]),
+ OMX_IndexConfigDisplayRegion, &region) != OMX_ErrorNone)
+ ELOG("failed to set display region!");
+}
+
+void cOmx::SetDisplayRegion(int x, int y, int width, int height)
+{
+ OMX_CONFIG_DISPLAYREGIONTYPE region;
+ OMX_INIT_STRUCT(region);
+ region.nPortIndex = 90;
+ region.set = (OMX_DISPLAYSETTYPE)
+ (OMX_DISPLAY_SET_FULLSCREEN | OMX_DISPLAY_SET_DEST_RECT);
+
+ region.fullscreen = (!x && !y && !width && !height) ? OMX_TRUE : OMX_FALSE;
+ region.dest_rect.x_offset = x;
+ region.dest_rect.y_offset = y;
+ region.dest_rect.width = width;
+ region.dest_rect.height = height;
+
+ if (OMX_SetConfig(ILC_GET_HANDLE(m_comp[eVideoRender]),
+ OMX_IndexConfigDisplayRegion, &region) != OMX_ErrorNone)
+ ELOG("failed to set display region!");
+}
+
OMX_BUFFERHEADERTYPE* cOmx::GetAudioBuffer(uint64_t pts)
{
- m_mutex->Lock();
+ Lock();
OMX_BUFFERHEADERTYPE* buf = NULL;
if (m_freeAudioBuffers > 0)
@@ -891,13 +979,14 @@ OMX_BUFFERHEADERTYPE* cOmx::GetAudioBuffer(uint64_t pts)
m_freeAudioBuffers--;
}
}
- m_mutex->Unlock();
+
+ Unlock();
return buf;
}
OMX_BUFFERHEADERTYPE* cOmx::GetVideoBuffer(uint64_t pts)
{
- m_mutex->Lock();
+ Lock();
OMX_BUFFERHEADERTYPE* buf = NULL;
if (m_freeVideoBuffers > 0)
@@ -915,7 +1004,8 @@ OMX_BUFFERHEADERTYPE* cOmx::GetVideoBuffer(uint64_t pts)
m_freeVideoBuffers--;
}
}
- m_mutex->Unlock();
+
+ Unlock();
return buf;
}