summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Reufer <thomas@reufer.ch>2014-03-24 21:37:26 +0100
committerThomas Reufer <thomas@reufer.ch>2014-03-24 21:37:26 +0100
commit32d5868acc4c251d979eefb4f8e006b900ca0fd6 (patch)
treea4e8668e7f278c60a09ec8d495eb592de1c2e07f
parent3512c566f9f92f5b158f092fe071e4202b7eadca (diff)
downloadvdr-plugin-rpihddevice-32d5868acc4c251d979eefb4f8e006b900ca0fd6.tar.gz
vdr-plugin-rpihddevice-32d5868acc4c251d979eefb4f8e006b900ca0fd6.tar.bz2
fixed buffer stall after StillPicture()
-rw-r--r--omx.c62
-rw-r--r--omx.h20
-rw-r--r--omxdevice.c23
-rw-r--r--omxdevice.h5
4 files changed, 83 insertions, 27 deletions
diff --git a/omx.c b/omx.c
index 978bf39..4fd95dc 100644
--- a/omx.c
+++ b/omx.c
@@ -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;
diff --git a/omx.h b/omx.h
index d7b64dc..415fcb4 100644
--- a/omx.h
+++ b/omx.h
@@ -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);