diff options
| author | Thomas Reufer <thomas@reufer.ch> | 2016-04-19 16:13:58 +0200 |
|---|---|---|
| committer | Thomas Reufer <thomas@reufer.ch> | 2016-04-20 12:13:35 +0200 |
| commit | a56615560a7f7f3f28239fcf9a06ec7c214e2a25 (patch) | |
| tree | 36c495eb6fda85c19950c5dd2a5af54c7b6bbc05 | |
| parent | 76205090f2682ac1ff7553f69e4d88b38d9d1481 (diff) | |
| download | vdr-plugin-rpihddevice-a56615560a7f7f3f28239fcf9a06ec7c214e2a25.tar.gz vdr-plugin-rpihddevice-a56615560a7f7f3f28239fcf9a06ec7c214e2a25.tar.bz2 | |
move all video related OMX stuff to cRpiOmxVideoDecoder
| -rw-r--r-- | omx.c | 483 | ||||
| -rw-r--r-- | omx.h | 38 | ||||
| -rw-r--r-- | omxdevice.c | 7 | ||||
| -rw-r--r-- | video.c | 288 | ||||
| -rw-r--r-- | video.h | 20 |
5 files changed, 455 insertions, 381 deletions
@@ -33,10 +33,6 @@ extern "C" { #define OMX_PRE_ROLL 0 -// default: 20x 81920 bytes, now 128x 64k (8M) -#define OMX_VIDEO_BUFFERS 128 -#define OMX_VIDEO_BUFFERSIZE KILOBYTE(64); - // default: 16x 4096 bytes, now 128x 16k (2M) #define OMX_AUDIO_BUFFERS 128 #define OMX_AUDIO_BUFFERSIZE KILOBYTE(16); @@ -194,8 +190,7 @@ void cOmx::Action(void) switch (event->event) { case cOmxEvents::ePortSettingsChanged: - if (m_handlePortEvents) - HandlePortSettingsChanged(event->data); + HandlePortSettingsChanged(event->data); for (cOmxEventHandler *handler = m_eventHandlers->First(); handler; handler = m_eventHandlers->Next(handler)) @@ -250,22 +245,14 @@ void cOmx::Action(void) } } -bool cOmx::PollVideo(void) -{ - return (m_usedVideoBuffers[0] * 100 / OMX_VIDEO_BUFFERS) < 90; -} - void cOmx::GetBufferUsage(int &audio, int &video) { audio = 0; - video = 0; for (int i = 0; i < BUFFERSTAT_FILTER_SIZE; i++) { audio += m_usedAudioBuffers[i]; - video += m_usedVideoBuffers[i]; } audio = audio * 100 / BUFFERSTAT_FILTER_SIZE / OMX_AUDIO_BUFFERS; - video = video * 100 / BUFFERSTAT_FILTER_SIZE / OMX_VIDEO_BUFFERS; } void cOmx::HandlePortBufferEmptied(eOmxComponent component) @@ -297,16 +284,16 @@ void cOmx::HandlePortSettingsChanged(unsigned int portId) switch (portId) { case 191: - if (ilclient_setup_tunnel(&m_tun[eVideoFxToVideoScheduler], 0, 0) != 0) + if (!SetupTunnel(eVideoFxToVideoScheduler)) ELOG("failed to setup up tunnel from video fx to scheduler!"); - if (ilclient_change_component_state(m_comp[eVideoScheduler], OMX_StateExecuting) != 0) + if (!ChangeComponentState(eVideoScheduler, OMX_StateExecuting)) ELOG("failed to enable video scheduler!"); break; case 11: - if (ilclient_setup_tunnel(&m_tun[eVideoSchedulerToVideoRender], 0, 0) != 0) + if (!SetupTunnel(eVideoSchedulerToVideoRender)) ELOG("failed to setup up tunnel from scheduler to render!"); - if (ilclient_change_component_state(m_comp[eVideoRender], OMX_StateExecuting) != 0) + if (!ChangeComponentState(eVideoRender, OMX_StateExecuting)) ELOG("failed to enable video render!"); break; } @@ -355,14 +342,10 @@ cOmx::cOmx() : cThread(), m_client(NULL), m_setAudioStartTime(false), - m_setVideoStartTime(false), - m_setVideoDiscontinuity(false), m_spareAudioBuffers(0), - m_spareVideoBuffers(0), m_clockReference(eClockRefNone), m_clockScale(0), m_portEvents(new cOmxEvents()), - m_handlePortEvents(false), m_eventHandlers(new cList<cOmxEventHandler>) { memset(m_tun, 0, sizeof(m_tun)); @@ -390,72 +373,41 @@ int cOmx::Init(int display, int layer) 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) - ELOG("failed creating video decoder!"); - - // create image_fx - if (ilclient_create_component(m_client, &m_comp[eVideoFx], - "image_fx", ILCLIENT_DISABLE_ALL_PORTS) != 0) - ELOG("failed creating video fx!"); - // create video_render - if (ilclient_create_component(m_client, &m_comp[eVideoRender], - "video_render", ILCLIENT_DISABLE_ALL_PORTS) != 0) + if (!CreateComponent(eVideoRender)) ELOG("failed creating video render!"); //create clock - if (ilclient_create_component(m_client, &m_comp[eClock], - "clock", ILCLIENT_DISABLE_ALL_PORTS) != 0) + if (!CreateComponent(eClock)) 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) + if (!CreateComponent(eAudioRender, true)) ELOG("failed creating audio render!"); //create video_scheduler - if (ilclient_create_component(m_client, &m_comp[eVideoScheduler], - "video_scheduler", ILCLIENT_DISABLE_ALL_PORTS) != 0) + if (!CreateComponent(eVideoScheduler)) ELOG("failed creating video scheduler!"); - // setup tunnels - set_tunnel(&m_tun[eVideoDecoderToVideoFx], - m_comp[eVideoDecoder], 131, m_comp[eVideoFx], 190); - - set_tunnel(&m_tun[eVideoFxToVideoScheduler], - m_comp[eVideoFx], 191, m_comp[eVideoScheduler], 10); - - set_tunnel(&m_tun[eVideoSchedulerToVideoRender], - m_comp[eVideoScheduler], 11, m_comp[eVideoRender], 90); - - set_tunnel(&m_tun[eClockToVideoScheduler], - m_comp[eClock], 80, m_comp[eVideoScheduler], 12); - - set_tunnel(&m_tun[eClockToAudioRender], - m_comp[eClock], 81, m_comp[eAudioRender], 101); + // set tunnels + SetTunnel(eVideoSchedulerToVideoRender, eVideoScheduler, 11, eVideoRender, 90); + SetTunnel(eClockToVideoScheduler, eClock, 80, eVideoScheduler, 12); + SetTunnel(eClockToAudioRender, eClock, 81, eAudioRender, 101); // setup clock tunnels first - if (ilclient_setup_tunnel(&m_tun[eClockToVideoScheduler], 0, 0) != 0) + if (!SetupTunnel(eClockToVideoScheduler)) ELOG("failed to setup up tunnel from clock to video scheduler!"); - if (ilclient_setup_tunnel(&m_tun[eClockToAudioRender], 0, 0) != 0) + if (!SetupTunnel(eClockToAudioRender)) 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); + ChangeComponentState(eClock, OMX_StateExecuting); + ChangeComponentState(eAudioRender, OMX_StateIdle); SetDisplay(display, layer); SetClockLatencyTarget(); - SetBufferStallThreshold(20000); SetClockReference(cOmx::eClockRefVideo); - FlushVideo(); FlushAudio(); Start(); @@ -468,27 +420,93 @@ int cOmx::DeInit(void) Cancel(-1); m_portEvents->Add(0); - for (int i = 0; i < eNumTunnels; i++) - ilclient_disable_tunnel(&m_tun[i]); + DisableTunnel(eClockToAudioRender); - ilclient_teardown_tunnels(m_tun); - ilclient_state_transition(m_comp, OMX_StateIdle); - ilclient_state_transition(m_comp, OMX_StateLoaded); - ilclient_cleanup_components(m_comp); + ChangeComponentState(eClock, OMX_StateIdle); + ChangeComponentState(eAudioRender, OMX_StateIdle); - OMX_Deinit(); + CleanupComponent(eClock); + CleanupComponent(eAudioRender); + CleanupComponent(eVideoScheduler); + CleanupComponent(eVideoRender); + OMX_Deinit(); ilclient_destroy(m_client); - return 0; } -bool cOmx::ChangeState(eOmxComponent comp, OMX_STATETYPE state) +bool cOmx::CreateComponent(eOmxComponent comp, bool enableInputBuffers) +{ + return (comp >= 0 && comp < eNumComponents && + !ilclient_create_component(m_client, &m_comp[comp], + comp == eClock ? "clock" : + comp == eVideoDecoder ? "video_decode" : + comp == eVideoFx ? "image_fx" : + comp == eVideoScheduler ? "video_scheduler" : + comp == eVideoRender ? "video_render" : + comp == eAudioRender ? "audio_render" : "", + (ILCLIENT_CREATE_FLAGS_T)(ILCLIENT_DISABLE_ALL_PORTS | + (enableInputBuffers ? ILCLIENT_ENABLE_INPUT_BUFFERS : 0)))); +} + +void cOmx::CleanupComponent(eOmxComponent comp) +{ + if (comp >= 0 && comp < eNumComponents) + { + COMPONENT_T *c[2] = { m_comp[comp], 0 }; + ilclient_cleanup_components(c); + } +} + +bool cOmx::ChangeComponentState(eOmxComponent comp, OMX_STATETYPE state) { return comp >= 0 && comp < eNumComponents && !ilclient_change_component_state(m_comp[comp], state); } +bool cOmx::FlushComponent(eOmxComponent comp, int port) +{ + if (comp >= 0 && comp < eNumComponents) + { + if (OMX_SendCommand(ILC_GET_HANDLE(m_comp[comp]), OMX_CommandFlush, + port, NULL) == OMX_ErrorNone) + { + ilclient_wait_for_event(m_comp[comp], OMX_EventCmdComplete, + OMX_CommandFlush, 0, port, 0, ILCLIENT_PORT_FLUSH, + VCOS_EVENT_FLAGS_SUSPEND); + + return true; + } + } + return false; +} + +bool cOmx::EnablePortBuffers(eOmxComponent comp, int port) +{ + return comp >= 0 && comp < eNumComponents && + !ilclient_enable_port_buffers(m_comp[comp], port, NULL, NULL, NULL); +} + +void cOmx::DisablePortBuffers(eOmxComponent comp, int port, + OMX_BUFFERHEADERTYPE *buffers) +{ + if (comp >= 0 && comp < eNumComponents) + ilclient_disable_port_buffers(m_comp[comp], port, buffers, NULL, NULL); +} + +OMX_BUFFERHEADERTYPE* cOmx::GetBuffer(eOmxComponent comp, int port) +{ + return (comp >= 0 && comp < eNumComponents) ? + ilclient_get_input_buffer(m_comp[comp], port, 0) : 0; +} + +bool cOmx::EmptyBuffer(eOmxComponent comp, OMX_BUFFERHEADERTYPE *buf) +{ + return buf && comp >= 0 && comp < eNumComponents && + (OMX_EmptyThisBuffer(ILC_GET_HANDLE(m_comp[comp]), buf) + == OMX_ErrorNone); +} + bool cOmx::GetParameter(eOmxComponent comp, OMX_INDEXTYPE index, OMX_PTR param) { return param && comp >= 0 && comp < eNumComponents && @@ -496,6 +514,13 @@ bool cOmx::GetParameter(eOmxComponent comp, OMX_INDEXTYPE index, OMX_PTR param) == OMX_ErrorNone); } +bool cOmx::SetParameter(eOmxComponent comp, OMX_INDEXTYPE index, OMX_PTR param) +{ + return param && comp >= 0 && comp < eNumComponents && + (OMX_SetParameter(ILC_GET_HANDLE(m_comp[comp]), index, param) + == OMX_ErrorNone); +} + bool cOmx::GetConfig(eOmxComponent comp, OMX_INDEXTYPE index, OMX_PTR config) { return config && comp >= 0 && comp < eNumComponents && @@ -503,12 +528,49 @@ bool cOmx::GetConfig(eOmxComponent comp, OMX_INDEXTYPE index, OMX_PTR config) == OMX_ErrorNone); } +bool cOmx::SetConfig(eOmxComponent comp, OMX_INDEXTYPE index, OMX_PTR config) +{ + return config && comp >= 0 && comp < eNumComponents && + (OMX_SetConfig(ILC_GET_HANDLE(m_comp[comp]), index, config) + == OMX_ErrorNone); +} + +void cOmx::SetTunnel(eOmxTunnel tunnel, eOmxComponent srcComp, int srcPort, + eOmxComponent dstComp, int dstPort) +{ + if (tunnel >= 0 && tunnel < eNumTunnels && srcComp >= 0 && srcComp + < eNumComponents && dstComp >= 0 && dstComp < eNumComponents) + set_tunnel(&m_tun[tunnel], + m_comp[srcComp], srcPort, m_comp[dstComp], dstPort); +} + bool cOmx::SetupTunnel(eOmxTunnel tunnel, int timeout) { return tunnel >= 0 && tunnel < eNumTunnels && !ilclient_setup_tunnel(&m_tun[tunnel], 0, timeout); } +void cOmx::DisableTunnel(eOmxTunnel tunnel) +{ + if (tunnel >= 0 && tunnel < eNumTunnels) + ilclient_disable_tunnel(&m_tun[tunnel]); +} + +void cOmx::TeardownTunnel(eOmxTunnel tunnel) +{ + if (tunnel >= 0 && tunnel < eNumTunnels) + { + TUNNEL_T t[2] = { m_tun[tunnel], 0 }; + ilclient_teardown_tunnels(t); + } +} + +void cOmx::FlushTunnel(eOmxTunnel tunnel) +{ + if (tunnel >= 0 && tunnel < eNumTunnels) + ilclient_flush_tunnels(&m_tun[tunnel], 1); +} + void cOmx::AddEventHandler(cOmxEventHandler *handler) { Lock(); @@ -600,7 +662,6 @@ void cOmx::StartClock(bool waitForVideo, bool waitForAudio) if (waitForVideo) { cstate.eState = OMX_TIME_ClockStateWaitingForStartTime; - m_setVideoStartTime = true; cstate.nWaitMask |= OMX_CLOCKPORT0; } if (waitForAudio) @@ -744,30 +805,6 @@ void cOmx::SetClockLatencyTarget(void) ELOG("failed set video render latency target!"); } -void cOmx::SetBufferStallThreshold(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; @@ -805,40 +842,6 @@ void cOmx::SetMute(bool mute) ELOG("failed to set mute state!"); } -void cOmx::StopVideo(void) -{ - Lock(); - - // disable port buffers and allow video decoder to reconfig - ilclient_disable_port_buffers(m_comp[eVideoDecoder], 130, - m_spareVideoBuffers, NULL, NULL); - - m_spareVideoBuffers = 0; - m_handlePortEvents = false; - - // put video decoder into idle - ilclient_change_component_state(m_comp[eVideoDecoder], OMX_StateIdle); - - // put video fx into idle - ilclient_flush_tunnels(&m_tun[eVideoDecoderToVideoFx], 1); - ilclient_disable_tunnel(&m_tun[eVideoDecoderToVideoFx]); - ilclient_change_component_state(m_comp[eVideoFx], OMX_StateIdle); - - // put video scheduler into idle - ilclient_flush_tunnels(&m_tun[eVideoFxToVideoScheduler], 1); - ilclient_disable_tunnel(&m_tun[eVideoFxToVideoScheduler]); - ilclient_flush_tunnels(&m_tun[eClockToVideoScheduler], 1); - ilclient_disable_tunnel(&m_tun[eClockToVideoScheduler]); - ilclient_change_component_state(m_comp[eVideoScheduler], OMX_StateIdle); - - // put video render into idle - ilclient_flush_tunnels(&m_tun[eVideoSchedulerToVideoRender], 1); - ilclient_disable_tunnel(&m_tun[eVideoSchedulerToVideoRender]); - ilclient_change_component_state(m_comp[eVideoRender], OMX_StateIdle); - - Unlock(); -} - void cOmx::StopAudio(void) { Lock(); @@ -854,16 +857,6 @@ void cOmx::StopAudio(void) Unlock(); } -void cOmx::SetVideoErrorConcealment(bool startWithValidFrame) -{ - OMX_PARAM_BRCMVIDEODECODEERRORCONCEALMENTTYPE ectype; - OMX_INIT_STRUCT(ectype); - ectype.bStartWithValidFrame = startWithValidFrame ? OMX_TRUE : OMX_FALSE; - if (OMX_SetParameter(ILC_GET_HANDLE(m_comp[eVideoDecoder]), - OMX_IndexParamBrcmVideoDecodeErrorConcealment, &ectype) != OMX_ErrorNone) - ELOG("failed to set video decode error concealment failed\n"); -} - void cOmx::FlushAudio(void) { Lock(); @@ -879,137 +872,6 @@ void cOmx::FlushAudio(void) Unlock(); } -void cOmx::FlushVideo(bool flushRender) -{ - Lock(); - if (OMX_SendCommand(ILC_GET_HANDLE(m_comp[eVideoDecoder]), OMX_CommandFlush, 130, NULL) != OMX_ErrorNone) - ELOG("failed to flush video decoder!"); - - ilclient_wait_for_event(m_comp[eVideoDecoder], OMX_EventCmdComplete, - OMX_CommandFlush, 0, 130, 0, ILCLIENT_PORT_FLUSH, - VCOS_EVENT_FLAGS_SUSPEND); - - ilclient_flush_tunnels(&m_tun[eVideoDecoderToVideoFx], 1); - ilclient_flush_tunnels(&m_tun[eVideoFxToVideoScheduler], 1); - - if (flushRender) - ilclient_flush_tunnels(&m_tun[eVideoSchedulerToVideoRender], 1); - - ilclient_flush_tunnels(&m_tun[eClockToVideoScheduler], 1); - - m_setVideoDiscontinuity = true; - Unlock(); -} - -int cOmx::SetVideoCodec(cVideoCodec::eCodec codec) -{ - Lock(); - - if (ilclient_change_component_state(m_comp[eVideoDecoder], OMX_StateIdle) != 0) - ELOG("failed to set video decoder to idle state!"); - - // configure video decoder - OMX_VIDEO_PARAM_PORTFORMATTYPE videoFormat; - OMX_INIT_STRUCT(videoFormat); - videoFormat.nPortIndex = 130; - videoFormat.eCompressionFormat = - codec == cVideoCodec::eMPEG2 ? OMX_VIDEO_CodingMPEG2 : - codec == cVideoCodec::eH264 ? OMX_VIDEO_CodingAVC : - OMX_VIDEO_CodingAutoDetect; - - if (OMX_SetParameter(ILC_GET_HANDLE(m_comp[eVideoDecoder]), - OMX_IndexParamVideoPortFormat, &videoFormat) != OMX_ErrorNone) - ELOG("failed to set video decoder parameters!"); - - OMX_PARAM_PORTDEFINITIONTYPE param; - OMX_INIT_STRUCT(param); - param.nPortIndex = 130; - if (OMX_GetParameter(ILC_GET_HANDLE(m_comp[eVideoDecoder]), - OMX_IndexParamPortDefinition, ¶m) != OMX_ErrorNone) - ELOG("failed to get video decoder port parameters!"); - - param.nBufferSize = OMX_VIDEO_BUFFERSIZE; - param.nBufferCountActual = OMX_VIDEO_BUFFERS; - for (int i = 0; i < BUFFERSTAT_FILTER_SIZE; i++) - m_usedVideoBuffers[i] = 0; - - if (OMX_SetParameter(ILC_GET_HANDLE(m_comp[eVideoDecoder]), - OMX_IndexParamPortDefinition, ¶m) != OMX_ErrorNone) - ELOG("failed to set video decoder port parameters!"); - - // start with valid frames only if codec is MPEG2 - // update: with FW from 2015/01/18 this is not necessary anymore - SetVideoErrorConcealment(true /*codec == cVideoCodec::eMPEG2*/); - - // update: with FW from 2014/02/04 this is not necessary anymore - //SetVideoDecoderExtraBuffers(3); - - if (ilclient_enable_port_buffers(m_comp[eVideoDecoder], 130, NULL, NULL, NULL) != 0) - ELOG("failed to enable port buffer on video decoder!"); - - if (ilclient_change_component_state(m_comp[eVideoDecoder], OMX_StateExecuting) != 0) - ELOG("failed to set video decoder to executing state!"); - - // setup clock tunnels first - if (ilclient_setup_tunnel(&m_tun[eClockToVideoScheduler], 0, 0) != 0) - ELOG("failed to setup up tunnel from clock to video scheduler!"); - - m_handlePortEvents = true; - - Unlock(); - return 0; -} - -int cOmx::SetupDeinterlacer(cDeinterlacerMode::eMode mode) -{ - OMX_CONFIG_IMAGEFILTERPARAMSTYPE filterparam; - OMX_INIT_STRUCT(filterparam); - filterparam.nPortIndex = 191; - filterparam.eImageFilter = OMX_ImageFilterNone; - - OMX_PARAM_U32TYPE extraBuffers; - OMX_INIT_STRUCT(extraBuffers); - extraBuffers.nPortIndex = 130; - - if (cDeinterlacerMode::Active(mode)) - { - mode = cDeinterlacerMode::eFast; - - filterparam.nNumParams = 4; - filterparam.nParams[0] = 3; - filterparam.nParams[1] = 0; // default frame interval - filterparam.nParams[2] = 0; // half framerate - filterparam.nParams[3] = 1; // use qpus - - filterparam.eImageFilter = mode == cDeinterlacerMode::eFast ? - OMX_ImageFilterDeInterlaceFast : - OMX_ImageFilterDeInterlaceAdvanced; - - if (mode == cDeinterlacerMode::eFast) - extraBuffers.nU32 = -2; - } - if (OMX_SetConfig(ILC_GET_HANDLE(m_comp[eVideoFx]), - OMX_IndexConfigCommonImageFilterParameters, &filterparam) != OMX_ErrorNone) - ELOG("failed to set deinterlacing paramaters!"); - - if (OMX_SetParameter(ILC_GET_HANDLE(m_comp[eVideoFx]), - OMX_IndexParamBrcmExtraBuffers, &extraBuffers) != OMX_ErrorNone) - ELOG("failed to set video fx extra buffers!"); - - return 0; -} - -void cOmx::SetVideoDecoderExtraBuffers(int extraBuffers) -{ - OMX_PARAM_U32TYPE u32; - OMX_INIT_STRUCT(u32); - u32.nPortIndex = 130; - u32.nU32 = extraBuffers; - if (OMX_SetParameter(ILC_GET_HANDLE(m_comp[eVideoDecoder]), - OMX_IndexParamBrcmExtraBuffers, &u32) != OMX_ErrorNone) - ELOG("failed to set video decoder extra buffers!"); -} - int cOmx::SetupAudioRender(cAudioCodec::eCodec outputFormat, int channels, cRpiAudioPort::ePort audioPort, int samplingRate, int frameSize) { @@ -1258,48 +1120,6 @@ OMX_BUFFERHEADERTYPE* cOmx::GetAudioBuffer(int64_t pts) return buf; } -OMX_BUFFERHEADERTYPE* cOmx::GetVideoBuffer(int64_t pts) -{ - Lock(); - OMX_BUFFERHEADERTYPE* buf = 0; - if (m_spareVideoBuffers) - { - buf = m_spareVideoBuffers; - m_spareVideoBuffers = - static_cast <OMX_BUFFERHEADERTYPE*>(buf->pAppPrivate); - buf->pAppPrivate = 0; - } - else - { - buf = ilclient_get_input_buffer(m_comp[eVideoDecoder], 130, 0); - if (buf) - m_usedVideoBuffers[0]++; - } - - if (buf) - { - buf->nFilledLen = 0; - buf->nOffset = 0; - buf->nFlags = 0; - - if (pts == OMX_INVALID_PTS) - buf->nFlags |= OMX_BUFFERFLAG_TIME_UNKNOWN; - else if (m_setVideoStartTime) - { - buf->nFlags |= OMX_BUFFERFLAG_STARTTIME; - m_setVideoStartTime = false; - } - if (m_setVideoDiscontinuity) - { - buf->nFlags |= OMX_BUFFERFLAG_DISCONTINUITY; - m_setVideoDiscontinuity = false; - } - cOmx::PtsToTicks(pts, buf->nTimeStamp); - } - Unlock(); - return buf; -} - #ifdef DEBUG_BUFFERS void cOmx::DumpBuffer(OMX_BUFFERHEADERTYPE *buf, const char *prefix) { @@ -1346,9 +1166,6 @@ bool cOmx::EmptyAudioBuffer(OMX_BUFFERHEADERTYPE *buf) if (buf->nFlags & OMX_BUFFERFLAG_STARTTIME) m_setAudioStartTime = true; - if (buf->nFlags & OMX_BUFFERFLAG_DISCONTINUITY) - m_setVideoDiscontinuity = true; - buf->nFilledLen = 0; buf->pAppPrivate = m_spareAudioBuffers; m_spareAudioBuffers = buf; @@ -1357,31 +1174,3 @@ bool cOmx::EmptyAudioBuffer(OMX_BUFFERHEADERTYPE *buf) Unlock(); return ret; } - -bool cOmx::EmptyVideoBuffer(OMX_BUFFERHEADERTYPE *buf) -{ - if (!buf) - return false; - - Lock(); - bool ret = true; -#ifdef DEBUG_BUFFERS - DumpBuffer(buf, "V"); -#endif - - if (OMX_EmptyThisBuffer(ILC_GET_HANDLE(m_comp[eVideoDecoder]), buf) - != OMX_ErrorNone) - { - ELOG("failed to empty OMX video buffer"); - - if (buf->nFlags & OMX_BUFFERFLAG_STARTTIME) - m_setVideoStartTime = true; - - buf->nFilledLen = 0; - buf->pAppPrivate = m_spareVideoBuffers; - m_spareVideoBuffers = buf; - ret = false; - } - Unlock(); - return ret; -} @@ -67,9 +67,23 @@ public: eInvalidComponent }; - bool ChangeState(eOmxComponent comp, OMX_STATETYPE state); + bool CreateComponent(eOmxComponent comp, bool enableInputBuffers = false); + void CleanupComponent(eOmxComponent comp); + bool ChangeComponentState(eOmxComponent comp, OMX_STATETYPE state); + bool FlushComponent(eOmxComponent comp, int port); + + bool EnablePortBuffers(eOmxComponent comp, int port); + void DisablePortBuffers(eOmxComponent comp, int port, + OMX_BUFFERHEADERTYPE *buffers = 0); + + OMX_BUFFERHEADERTYPE* GetBuffer(eOmxComponent comp, int port); + bool EmptyBuffer(eOmxComponent comp, OMX_BUFFERHEADERTYPE *buf); + bool GetParameter(eOmxComponent comp, OMX_INDEXTYPE index, OMX_PTR param); + bool SetParameter(eOmxComponent comp, OMX_INDEXTYPE index, OMX_PTR param); + bool GetConfig(eOmxComponent comp, OMX_INDEXTYPE index, OMX_PTR config); + bool SetConfig(eOmxComponent comp, OMX_INDEXTYPE index, OMX_PTR config); enum eOmxTunnel { eVideoDecoderToVideoFx = 0, @@ -80,7 +94,13 @@ public: eNumTunnels }; + void SetTunnel(eOmxTunnel tunnel, eOmxComponent srcComp, int srcPort, + eOmxComponent dstComp, int dstPort); + bool SetupTunnel(eOmxTunnel tunnel, int timeout = 0); + void DisableTunnel(eOmxTunnel tunnel); + void TeardownTunnel(eOmxTunnel tunnel); + void FlushTunnel(eOmxTunnel tunnel); static OMX_TICKS ToOmxTicks(int64_t val); static int64_t FromOmxTicks(OMX_TICKS &ticks); @@ -116,17 +136,10 @@ public: void SetClockLatencyTarget(void); void SetVolume(int vol); void SetMute(bool mute); - void StopVideo(void); void StopAudio(void); - void SetVideoErrorConcealment(bool startWithValidFrame); - void SetVideoDecoderExtraBuffers(int extraBuffers); - void FlushAudio(void); - void FlushVideo(bool flushRender = false); - int SetVideoCodec(cVideoCodec::eCodec codec); - int SetupDeinterlacer(cDeinterlacerMode::eMode mode); int SetupAudioRender(cAudioCodec::eCodec outputFormat, int channels, cRpiAudioPort::ePort audioPort, int samplingRate = 0, int frameSize = 0); @@ -137,12 +150,8 @@ public: void SetDisplay(int display, int layer); OMX_BUFFERHEADERTYPE* GetAudioBuffer(int64_t pts = OMX_INVALID_PTS); - OMX_BUFFERHEADERTYPE* GetVideoBuffer(int64_t pts = OMX_INVALID_PTS); - - bool PollVideo(void); bool EmptyAudioBuffer(OMX_BUFFERHEADERTYPE *buf); - bool EmptyVideoBuffer(OMX_BUFFERHEADERTYPE *buf); void GetBufferUsage(int &audio, int &video); @@ -161,8 +170,6 @@ private: TUNNEL_T m_tun[cOmx::eNumTunnels + 1]; bool m_setAudioStartTime; - bool m_setVideoStartTime; - bool m_setVideoDiscontinuity; #define BUFFERSTAT_FILTER_SIZE 64 @@ -170,19 +177,16 @@ private: int m_usedVideoBuffers[BUFFERSTAT_FILTER_SIZE]; OMX_BUFFERHEADERTYPE* m_spareAudioBuffers; - OMX_BUFFERHEADERTYPE* m_spareVideoBuffers; eClockReference m_clockReference; OMX_S32 m_clockScale; cOmxEvents *m_portEvents; - bool m_handlePortEvents; cList<cOmxEventHandler> *m_eventHandlers; void HandlePortBufferEmptied(eOmxComponent component); void HandlePortSettingsChanged(unsigned int portId); - void SetBufferStallThreshold(int delayMs); bool IsBufferStall(void); static void OnBufferEmpty(void *instance, COMPONENT_T *comp); diff --git a/omxdevice.c b/omxdevice.c index 3b85b52..d021b54 100644 --- a/omxdevice.c +++ b/omxdevice.c @@ -328,7 +328,7 @@ int cOmxDevice::PlayAudio(const uchar *Data, int Length, uchar Id) int cOmxDevice::PlayVideo(const uchar *Data, int Length, bool EndOfFrame) { // prevent writing incomplete frames - if (m_hasVideo && !m_omx->PollVideo()) + if (m_hasVideo && m_video && !m_video->Poll()) return 0; m_mutex->Lock(); @@ -615,7 +615,12 @@ void cOmxDevice::HandleEndOfStream(void) m_mutex->Lock(); m_omx->StopClock(); + + if (m_hasVideo && m_video) + m_video->Clear(); + m_omx->ResetClock(); + m_omx->SetClockScale(s_playbackSpeeds[m_direction][m_playbackSpeed]); m_omx->StartClock(m_hasVideo, m_hasAudio); @@ -70,22 +70,143 @@ void cRpiVideoDecoder::NotifyEndOfStream(void) /* ------------------------------------------------------------------------- */ +// default: 20x 81920 bytes, now 128x 64k (8M) +#define OMX_VIDEO_BUFFERS 128 +#define OMX_VIDEO_BUFFERSIZE KILOBYTE(64); + +#define OMX_VIDEO_BUFFERSTALL_TIMEOUT_MS 20000 + cRpiOmxVideoDecoder::cRpiOmxVideoDecoder(cVideoCodec::eCodec codec, cOmx *omx, void (*onStreamStart)(void*, const cVideoFrameFormat *format), void (*onEndOfStream)(void*), void* callbackData) : cRpiVideoDecoder(codec, onStreamStart, onEndOfStream, callbackData), cOmxEventHandler(), - m_omx(omx) + m_omx(omx), + m_setDiscontinuity(true), + m_setStartTime(true), + m_spareBuffers(0) { ILOG("new OMX %s video codec", cVideoCodec::Str(codec)); + + // create video_decode + if (!m_omx->CreateComponent(cOmx::eVideoDecoder, true)) + ELOG("failed creating video decoder!"); + + // create image_fx + if (!m_omx->CreateComponent(cOmx::eVideoFx)) + ELOG("failed creating video fx!"); + + m_omx->SetTunnel(cOmx::eVideoDecoderToVideoFx, + cOmx::eVideoDecoder, 131, cOmx::eVideoFx, 190); + + m_omx->SetTunnel(cOmx::eVideoFxToVideoScheduler, + cOmx::eVideoFx, 191, cOmx::eVideoScheduler, 10); + + if (!m_omx->ChangeComponentState(cOmx::eVideoDecoder, OMX_StateIdle)) + ELOG("failed to set video decoder to idle state!"); + + if (!m_omx->ChangeComponentState(cOmx::eVideoFx, OMX_StateIdle)) + ELOG("failed to set video fx to idle state!"); + + OMX_CONFIG_BUFFERSTALLTYPE stallConf; + OMX_INIT_STRUCT(stallConf); + stallConf.nPortIndex = 131; + stallConf.nDelay = OMX_VIDEO_BUFFERSTALL_TIMEOUT_MS * 1000; + if (!m_omx->SetConfig(cOmx::eVideoDecoder, + OMX_IndexConfigBufferStall, &stallConf)) + 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 = OMX_TRUE; + if (!m_omx->SetConfig(cOmx::eVideoDecoder, + OMX_IndexConfigRequestCallback, &reqCallback)) + ELOG("failed to set video decoder stall call back!"); + + // configure video decoder + OMX_VIDEO_PARAM_PORTFORMATTYPE videoFormat; + OMX_INIT_STRUCT(videoFormat); + videoFormat.nPortIndex = 130; + videoFormat.eCompressionFormat = + codec == cVideoCodec::eMPEG2 ? OMX_VIDEO_CodingMPEG2 : + codec == cVideoCodec::eH264 ? OMX_VIDEO_CodingAVC : + OMX_VIDEO_CodingAutoDetect; + + if (!m_omx->SetParameter(cOmx::eVideoDecoder, + OMX_IndexParamVideoPortFormat, &videoFormat)) + ELOG("failed to set video decoder parameters!"); + + OMX_PARAM_PORTDEFINITIONTYPE param; + OMX_INIT_STRUCT(param); + param.nPortIndex = 130; + if (!m_omx->GetParameter(cOmx::eVideoDecoder, + OMX_IndexParamPortDefinition, ¶m)) + ELOG("failed to get video decoder port parameters!"); + + param.nBufferSize = OMX_VIDEO_BUFFERSIZE; + param.nBufferCountActual = OMX_VIDEO_BUFFERS; + for (int i = 0; i < BUFFERSTAT_FILTER_SIZE; i++) + m_usedBuffers[i] = 0; + + if (!m_omx->SetParameter(cOmx::eVideoDecoder, + OMX_IndexParamPortDefinition, ¶m)) + ELOG("failed to set video decoder port parameters!"); + + OMX_PARAM_BRCMVIDEODECODEERRORCONCEALMENTTYPE ectype; + OMX_INIT_STRUCT(ectype); + ectype.bStartWithValidFrame = OMX_TRUE; + if (!m_omx->SetParameter(cOmx::eVideoDecoder, + OMX_IndexParamBrcmVideoDecodeErrorConcealment, &ectype)) + ELOG("failed to set video decode error concealment failed!"); + + if (!m_omx->EnablePortBuffers(cOmx::eVideoDecoder, 130)) + ELOG("failed to enable port buffer on video decoder!"); + + if (!m_omx->ChangeComponentState(cOmx::eVideoDecoder, OMX_StateExecuting)) + ELOG("failed to set video decoder to executing state!"); + + // setup clock tunnels first + if (!m_omx->SetupTunnel(cOmx::eClockToVideoScheduler)) + ELOG("failed to setup up tunnel from clock to video scheduler!"); + m_omx->AddEventHandler(this); - m_omx->SetVideoCodec(codec); } cRpiOmxVideoDecoder::~cRpiOmxVideoDecoder() { Clear(true); - m_omx->StopVideo(); + + // disable port buffers + m_omx->DisablePortBuffers(cOmx::eVideoDecoder, 130, m_spareBuffers); + m_spareBuffers = 0; + + // put video decoder into idle + m_omx->ChangeComponentState(cOmx::eVideoDecoder, OMX_StateIdle); + + // put video fx into idle + m_omx->FlushTunnel(cOmx::eVideoDecoderToVideoFx); + m_omx->DisableTunnel(cOmx::eVideoDecoderToVideoFx); + m_omx->ChangeComponentState(cOmx::eVideoFx, OMX_StateIdle); + + // put video scheduler into idle + m_omx->FlushTunnel(cOmx::eVideoFxToVideoScheduler); + m_omx->DisableTunnel(cOmx::eVideoFxToVideoScheduler); + m_omx->FlushTunnel(cOmx::eClockToVideoScheduler); + m_omx->DisableTunnel(cOmx::eClockToVideoScheduler); + m_omx->ChangeComponentState(cOmx::eVideoScheduler, OMX_StateIdle); + + // put video render into idle + m_omx->FlushTunnel(cOmx::eVideoSchedulerToVideoRender); + m_omx->DisableTunnel(cOmx::eVideoSchedulerToVideoRender); + m_omx->ChangeComponentState(cOmx::eVideoRender, OMX_StateIdle); + + // clean up image_fx & decoder + m_omx->CleanupComponent(cOmx::eVideoFx); + m_omx->CleanupComponent(cOmx::eVideoDecoder); + m_omx->RemoveEventHandler(this); } @@ -94,8 +215,22 @@ bool cRpiOmxVideoDecoder::WriteData(const unsigned char *data, { while (length > 0) { - if (OMX_BUFFERHEADERTYPE *buf = m_omx->GetVideoBuffer(pts)) + if (OMX_BUFFERHEADERTYPE *buf = GetBuffer()) { + if (pts == OMX_INVALID_PTS) + buf->nFlags |= OMX_BUFFERFLAG_TIME_UNKNOWN; + else if (m_setStartTime) + { + buf->nFlags |= OMX_BUFFERFLAG_STARTTIME; + m_setStartTime = false; + } + if (m_setDiscontinuity) + { + buf->nFlags |= OMX_BUFFERFLAG_DISCONTINUITY; + m_setDiscontinuity = false; + } + cOmx::PtsToTicks(pts, buf->nTimeStamp); + buf->nFilledLen = buf->nAllocLen < length ? buf->nAllocLen : length; memcpy(buf->pBuffer, data, buf->nFilledLen); @@ -105,7 +240,7 @@ bool cRpiOmxVideoDecoder::WriteData(const unsigned char *data, if (eof && !length) buf->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; - if (!m_omx->EmptyVideoBuffer(buf)) + if (!EmptyBuffer(buf)) { ELOG("failed to pass buffer to video decoder!"); return false; @@ -121,28 +256,55 @@ bool cRpiOmxVideoDecoder::WriteData(const unsigned char *data, bool cRpiOmxVideoDecoder::Poll(void) { - return m_omx->PollVideo(); + return (m_usedBuffers[0] * 100 / OMX_VIDEO_BUFFERS) < 90; } void cRpiOmxVideoDecoder::Flush(void) { DBG("SubmitEOS()"); - OMX_BUFFERHEADERTYPE *buf = m_omx->GetVideoBuffer(0); + OMX_BUFFERHEADERTYPE *buf = GetBuffer(); if (buf) { - buf->nFlags = OMX_BUFFERFLAG_EOS | OMX_BUFFERFLAG_ENDOFFRAME; + cOmx::PtsToTicks(0, buf->nTimeStamp); + buf->nFlags = OMX_BUFFERFLAG_EOS | OMX_BUFFERFLAG_ENDOFFRAME | + OMX_BUFFERFLAG_TIME_UNKNOWN; buf->nFilledLen = m_codec == cVideoCodec::eMPEG2 ? sizeof(s_mpeg2EndOfSequence) : sizeof(s_h264EndOfSequence); memcpy(buf->pBuffer, m_codec == cVideoCodec::eMPEG2 ? s_mpeg2EndOfSequence : s_h264EndOfSequence, buf->nFilledLen); } - if (!m_omx->EmptyVideoBuffer(buf)) + if (!EmptyBuffer(buf)) ELOG("failed to submit EOS packet!"); } -void cRpiOmxVideoDecoder::Clear(bool flushVideoRender) +int cRpiOmxVideoDecoder::GetBufferUsage(void) { - m_omx->FlushVideo(flushVideoRender); + int usage = 0; + for (int i = 0; i < BUFFERSTAT_FILTER_SIZE; i++) + usage += m_usedBuffers[i]; + + return usage * 100 / BUFFERSTAT_FILTER_SIZE / OMX_VIDEO_BUFFERS; +} + +void cRpiOmxVideoDecoder::Clear(bool flushRender) +{ + if (!m_omx->FlushComponent(cOmx::eVideoDecoder, 130)) + ELOG("failed to flush video decoder!"); + + m_omx->FlushTunnel(cOmx::eVideoDecoderToVideoFx); + + if (!m_omx->FlushComponent(cOmx::eVideoFx, 190)) + ELOG("failed to flush video fx!"); + + m_omx->FlushTunnel(cOmx::eVideoFxToVideoScheduler); + + if (flushRender) + m_omx->FlushTunnel(cOmx::eVideoSchedulerToVideoRender); + + m_omx->FlushTunnel(cOmx::eClockToVideoScheduler); + + m_setDiscontinuity = true; + m_setStartTime = true; } void cRpiOmxVideoDecoder::PortSettingsChanged(int port) @@ -194,7 +356,7 @@ void cRpiOmxVideoDecoder::PortSettingsChanged(int port) NotifyStreamStart(); // if necessary, setup deinterlacer - m_omx->SetupDeinterlacer( + SetupDeinterlacer( cRpiDisplay::IsProgressive() && m_format.Interlaced() ? ( m_format.width * m_format.height > 576 * 720 ? cDeinterlacerMode::eFast : @@ -204,7 +366,7 @@ void cRpiOmxVideoDecoder::PortSettingsChanged(int port) if (!m_omx->SetupTunnel(cOmx::eVideoDecoderToVideoFx, 0)) ELOG("failed to setup up tunnel from video decoder to fx!"); - if (!m_omx->ChangeState(cOmx::eVideoFx, OMX_StateExecuting)) + if (!m_omx->ChangeComponentState(cOmx::eVideoFx, OMX_StateExecuting)) ELOG("failed to enable video fx!"); break; @@ -219,7 +381,11 @@ void cRpiOmxVideoDecoder::EndOfStreamReceived(int port) void cRpiOmxVideoDecoder::BufferEmptied(cOmx::eOmxComponent comp) { - + if (comp == cOmx::eVideoDecoder) + { + cMutexLock MutexLock(&m_mutex); + m_usedBuffers[0]--; + } } void cRpiOmxVideoDecoder::BufferStalled(void) @@ -228,4 +394,98 @@ void cRpiOmxVideoDecoder::BufferStalled(void) Clear(); } +void cRpiOmxVideoDecoder::Tick(void) +{ + for (int i = BUFFERSTAT_FILTER_SIZE - 1; i > 0; i--) + m_usedBuffers[i] = m_usedBuffers[i - 1]; +} + +OMX_BUFFERHEADERTYPE* cRpiOmxVideoDecoder::GetBuffer(void) +{ + OMX_BUFFERHEADERTYPE* buf = 0; + cMutexLock MutexLock(&m_mutex); + + if (m_spareBuffers) + { + buf = m_spareBuffers; + m_spareBuffers = static_cast <OMX_BUFFERHEADERTYPE*>(buf->pAppPrivate); + buf->pAppPrivate = 0; + } + else + { + buf = m_omx->GetBuffer(cOmx::eVideoDecoder, 130); + if (buf) + m_usedBuffers[0]++; + } + + if (buf) + { + buf->nFilledLen = 0; + buf->nOffset = 0; + buf->nFlags = 0; + } + return buf; +} + +bool cRpiOmxVideoDecoder::EmptyBuffer(OMX_BUFFERHEADERTYPE *buf) +{ + bool ret = true; + +#ifdef DEBUG_BUFFERS + cOmx::DumpBuffer(buf, "V"); +#endif + + if (!m_omx->EmptyBuffer(cOmx::eVideoDecoder, buf)) + { + ELOG("failed to empty OMX video buffer"); + cMutexLock MutexLock(&m_mutex); + + if (buf->nFlags & OMX_BUFFERFLAG_STARTTIME) + m_setStartTime = true; + + buf->nFilledLen = 0; + buf->pAppPrivate = m_spareBuffers; + m_spareBuffers = buf; + ret = false; + } + return ret; +} + +void cRpiOmxVideoDecoder::SetupDeinterlacer(cDeinterlacerMode::eMode mode) +{ + DBG("SetupDeinterlacer(%s)", cDeinterlacerMode::Str(mode)); + + OMX_CONFIG_IMAGEFILTERPARAMSTYPE filterparam; + OMX_INIT_STRUCT(filterparam); + filterparam.nPortIndex = 191; + filterparam.eImageFilter = OMX_ImageFilterNone; + + OMX_PARAM_U32TYPE extraBuffers; + OMX_INIT_STRUCT(extraBuffers); + extraBuffers.nPortIndex = 130; + + if (cDeinterlacerMode::Active(mode)) + { + filterparam.nNumParams = 4; + filterparam.nParams[0] = 3; + filterparam.nParams[1] = 0; // default frame interval + filterparam.nParams[2] = 0; // half framerate + filterparam.nParams[3] = 1; // use qpus + + filterparam.eImageFilter = mode == cDeinterlacerMode::eFast ? + OMX_ImageFilterDeInterlaceFast : + OMX_ImageFilterDeInterlaceAdvanced; + + if (mode == cDeinterlacerMode::eFast) + extraBuffers.nU32 = -2; + } + if (!m_omx->SetConfig(cOmx::eVideoFx, + OMX_IndexConfigCommonImageFilterParameters, &filterparam)) + ELOG("failed to set deinterlacing paramaters!"); + + if (!m_omx->SetParameter(cOmx::eVideoFx, + OMX_IndexParamBrcmExtraBuffers, &extraBuffers)) + ELOG("failed to set video fx extra buffers!"); +} + /* ------------------------------------------------------------------------- */ @@ -46,6 +46,8 @@ public: const cVideoFrameFormat *GetFrameFormat(void) { return &m_format; } + virtual int GetBufferUsage(void) { return 0; }; + protected: static const unsigned char s_mpeg2EndOfSequence[4]; @@ -79,17 +81,31 @@ public: unsigned int length, int64_t pts, bool eof); virtual bool Poll(void); - virtual void Clear(bool flushVideoRender = false); + virtual void Clear(bool flushRender = false); virtual void Flush(void); + virtual int GetBufferUsage(void); + protected: virtual void PortSettingsChanged(int port); virtual void EndOfStreamReceived(int port); virtual void BufferEmptied(cOmx::eOmxComponent comp); virtual void BufferStalled(void); + virtual void Tick(void); + + OMX_BUFFERHEADERTYPE* GetBuffer(void); + bool EmptyBuffer(OMX_BUFFERHEADERTYPE *buf); + + void SetupDeinterlacer(cDeinterlacerMode::eMode mode); + + cMutex m_mutex; + cOmx *m_omx; + int m_usedBuffers[BUFFERSTAT_FILTER_SIZE]; + bool m_setDiscontinuity; + bool m_setStartTime; - cOmx *m_omx; + OMX_BUFFERHEADERTYPE *m_spareBuffers; private: |
