diff options
author | Thomas Reufer <thomas@reufer.ch> | 2014-02-10 21:53:25 +0100 |
---|---|---|
committer | Thomas Reufer <thomas@reufer.ch> | 2014-02-10 21:53:25 +0100 |
commit | 0094472cda6eefa9b5363ad844daf0fcfd00c326 (patch) | |
tree | b577f931820ef3899da856f9ccd0de04f4c8ffa8 /omx.c | |
parent | 88f137d194b1768344e954a1b1d35fb1fce03df9 (diff) | |
download | vdr-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.c | 386 |
1 files changed, 238 insertions, 148 deletions
@@ -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, ¶m) != 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, ¶m) != 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, ¶m) != 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, ×tamp) != 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, ×tamp) != 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, ®ion) != 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, ®ion) != 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; } |