diff options
| author | Thomas Reufer <thomas@reufer.ch> | 2014-03-24 21:37:26 +0100 |
|---|---|---|
| committer | Thomas Reufer <thomas@reufer.ch> | 2014-03-24 21:37:26 +0100 |
| commit | 32d5868acc4c251d979eefb4f8e006b900ca0fd6 (patch) | |
| tree | a4e8668e7f278c60a09ec8d495eb592de1c2e07f | |
| parent | 3512c566f9f92f5b158f092fe071e4202b7eadca (diff) | |
| download | vdr-plugin-rpihddevice-32d5868acc4c251d979eefb4f8e006b900ca0fd6.tar.gz vdr-plugin-rpihddevice-32d5868acc4c251d979eefb4f8e006b900ca0fd6.tar.bz2 | |
fixed buffer stall after StillPicture()
| -rw-r--r-- | omx.c | 62 | ||||
| -rw-r--r-- | omx.h | 20 | ||||
| -rw-r--r-- | omxdevice.c | 23 | ||||
| -rw-r--r-- | omxdevice.h | 5 |
4 files changed, 83 insertions, 27 deletions
@@ -109,15 +109,28 @@ void cOmx::Action(void) m_eventReady->Wait(); while (!m_portEvents->empty()) { - HandlePortSettingsChanged(m_portEvents->front()); + switch (m_portEvents->front().event) + { + case ePortSettingsChanged: + HandlePortSettingsChanged(m_portEvents->front().data); + break; + + case eConfigChanged: + if (m_portEvents->front().data == OMX_IndexConfigBufferStall) + if (IsBufferStall() && !IsClockFreezed() && m_onBufferStall) + m_onBufferStall(m_onBufferStallData); + break; + + case eEndOfStream: + if (m_portEvents->front().data == 90 && m_onEndOfStream) + m_onEndOfStream(m_onEndOfStreamData); + break; + + default: + break; + } m_portEvents->pop(); } - if (m_stallEvent) - { - if (IsBufferStall() && !IsClockFreezed() && m_onBufferStall) - m_onBufferStall(m_onBufferStallData); - m_stallEvent = false; - } } } @@ -201,13 +214,25 @@ void cOmx::OnBufferEmpty(void *instance, COMPONENT_T *comp) void cOmx::OnPortSettingsChanged(void *instance, COMPONENT_T *comp, OMX_U32 data) { cOmx* omx = static_cast <cOmx*> (instance); - omx->m_portEvents->push(data); + PortEvent event = {ePortSettingsChanged, data}; + omx->m_portEvents->push(event); + omx->m_eventReady->Signal(); +} + +void cOmx::OnConfigChanged(void *instance, COMPONENT_T *comp, OMX_U32 data) +{ + cOmx* omx = static_cast <cOmx*> (instance); + PortEvent event = {eConfigChanged, data}; + omx->m_portEvents->push(event); 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); + PortEvent event = {eEndOfStream, data}; + omx->m_portEvents->push(event); + omx->m_eventReady->Signal(); } void cOmx::OnError(void *instance, COMPONENT_T *comp, OMX_U32 data) @@ -216,16 +241,6 @@ void cOmx::OnError(void *instance, COMPONENT_T *comp, OMX_U32 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_videoWidth(0), @@ -239,8 +254,7 @@ cOmx::cOmx() : m_clockReference(eClockRefNone), m_clockScale(0), m_eventReady(new cCondWait()), - m_portEvents(new std::queue<unsigned int>), - m_stallEvent(false), + m_portEvents(new std::queue<PortEvent>), m_onBufferStall(0), m_onBufferStallData(0) { @@ -366,6 +380,12 @@ void cOmx::SetBufferStallCallback(void (*onBufferStall)(void*), void* data) m_onBufferStallData = data; } +void cOmx::SetEndOfStreamCallback(void (*onEndOfStream)(void*), void* data) +{ + m_onEndOfStream = onEndOfStream; + m_onEndOfStreamData = data; +} + OMX_TICKS cOmx::ToOmxTicks(int64_t val) { OMX_TICKS ticks; @@ -27,6 +27,7 @@ public: int DeInit(void); void SetBufferStallCallback(void (*onBufferStall)(void*), void* data); + void SetEndOfStreamCallback(void (*onBufferStall)(void*), void* data); static OMX_TICKS ToOmxTicks(int64_t val); static int64_t FromOmxTicks(OMX_TICKS &ticks); @@ -120,6 +121,18 @@ private: eNumTunnels }; + enum eOmxEvent { + ePortSettingsChanged, + eConfigChanged, + eEndOfStream + }; + + struct PortEvent + { + eOmxEvent event; + int data; + }; + ILCLIENT_T *m_client; COMPONENT_T *m_comp[cOmx::eNumComponents + 1]; TUNNEL_T m_tun[cOmx::eNumTunnels + 1]; @@ -139,11 +152,14 @@ private: OMX_S32 m_clockScale; cCondWait *m_eventReady; - std::queue<unsigned int> *m_portEvents; - bool m_stallEvent; + std::queue<PortEvent> *m_portEvents; + void (*m_onBufferStall)(void*); void *m_onBufferStallData; + void (*m_onEndOfStream)(void*); + void *m_onEndOfStreamData; + void HandlePortSettingsChanged(unsigned int portId); void SetBufferStallThreshold(int delayMs); bool IsBufferStall(void); diff --git a/omxdevice.c b/omxdevice.c index 9b90762..700f0ee 100644 --- a/omxdevice.c +++ b/omxdevice.c @@ -77,6 +77,7 @@ int cOmxDevice::Init(void) return -1; } m_omx->SetBufferStallCallback(&OnBufferStall, this); + m_omx->SetEndOfStreamCallback(&OnEndOfStream, this); return 0; } @@ -179,18 +180,22 @@ void cOmxDevice::StillPicture(const uchar *Data, int Length) cDevice::StillPicture(Data, Length); else { + m_mutex->Lock(); + // manually restart clock and wait for video only m_omx->StopClock(); m_omx->SetClockScale(s_speeds[eForward][eNormal]); m_omx->StartClock(true, false); // to get a picture displayed, PlayVideo() needs to be called - // 4x for MPEG2 and 12x for H264... ? + // 4x for MPEG2 and 13x for H264... ? int repeat = - ParseVideoCodec(Data, Length) == cVideoCodec::eMPEG2 ? 4 : 12; + ParseVideoCodec(Data, Length) == cVideoCodec::eMPEG2 ? 4 : 13; while (repeat--) - PlayVideo(Data, Length, true); + PlayVideo(Data, Length, !repeat); + + m_mutex->Unlock(); } } @@ -303,7 +308,7 @@ int cOmxDevice::PlayVideo(const uchar *Data, int Length, bool singleFrame) PesLength(Data) - PesPayloadOffset(Data)); if (singleFrame && Length == PesLength(Data)) - buf->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; + buf->nFlags |= OMX_BUFFERFLAG_EOS; if (!m_omx->EmptyVideoBuffer(buf)) { @@ -546,6 +551,16 @@ void cOmxDevice::HandleBufferStall() m_mutex->Unlock(); } +void cOmxDevice::HandleEndOfStream() +{ + DBG("HandleEndOfStream()"); + + // flush pipes and restart clock after still image + FlushStreams(); + m_omx->SetClockScale(s_speeds[eForward][ePause]); + m_omx->StartClock(m_hasVideo, m_hasAudio); +} + void cOmxDevice::FlushStreams(bool flushVideoRender) { DBG("FlushStreams(%s)", flushVideoRender ? "flushVideoRender" : ""); diff --git a/omxdevice.h b/omxdevice.h index f7a8ca9..2b890a3 100644 --- a/omxdevice.h +++ b/omxdevice.h @@ -130,7 +130,12 @@ private: static void OnBufferStall(void *data) { (static_cast <cOmxDevice*> (data))->HandleBufferStall(); } + static void OnEndOfStream(void *data) + { (static_cast <cOmxDevice*> (data))->HandleEndOfStream(); } + void HandleBufferStall(); + void HandleEndOfStream(); + void FlushStreams(bool flushVideoRender = false); void ApplyTrickSpeed(int trickSpeed, bool forward); |
