Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for almost-seamless playback of multiple streams (optionally, in a loop) #127

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
2fee92f
Makefile make dist: Install to /usr/share/doc/omxplayer
pasky Jan 24, 2013
a7873ca
CLog::Log: Fix logging current time (with ms precision)
pasky Jan 24, 2013
47857fd
Quick'n'dirty (goto-based) support for playback of multiple files and…
pasky Jan 24, 2013
e6734c2
m_omx_reader: Convert OMXReader instance from statically to dynamical…
pasky Jan 24, 2013
8d42ab0
OMXThread::StopThread(): More specific debug message
pasky Jan 24, 2013
ce4b490
When playing multiple files, pre-open the file while playing the prev…
pasky Jan 24, 2013
a0e99a9
Fix 'q' in loop / multifile mode
pasky Jan 28, 2013
cd47dbb
Add loop option to repeat content seamlessly
bendenoz Jan 30, 2013
1ced7d3
Deinitialize / reinitialize COMX between files
pasky Feb 7, 2013
45018de
Add some more verbose error reporting
pasky Feb 7, 2013
10c6427
index on master: 45018de Add some more verbose error reporting
pasky Feb 12, 2013
0940fa9
WIP on master: 45018de Add some more verbose error reporting
pasky Feb 12, 2013
b6917df
Merge remote-tracking branch 'origin/master'
pasky Feb 22, 2013
7e1e8d0
Merge remote-tracking branch 'bendenoz/seamless_loop'
pasky Feb 26, 2013
9905dd3
Move seek code out of loop, unused audio.UnFlush() method
pasky Feb 26, 2013
4e43975
Merge attempt at seamless multi-file play support
pasky Feb 26, 2013
fb80d90
Loop only if not m_stop or some-such
pasky Feb 26, 2013
1b19826
Disable some excessive logging messages
pasky Feb 26, 2013
ad070e5
Disable m_av_clock->OMXSeek() call, it's broken (no audio and gets st…
pasky Feb 26, 2013
cd4ff65
Fix up transition to next video
pasky Feb 27, 2013
45af325
Fix m_omx_reader switchover race
pasky Mar 2, 2013
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ ffmpeg:
dist: omxplayer.bin
mkdir -p $(DIST)/usr/lib/omxplayer
mkdir -p $(DIST)/usr/bin
mkdir -p $(DIST)/usr/share/doc
mkdir -p $(DIST)/usr/share/doc/omxplayer
cp omxplayer omxplayer.bin $(DIST)/usr/bin
cp COPYING $(DIST)/usr/share/doc/
cp README.md $(DIST)/usr/share/doc/README
cp COPYING $(DIST)/usr/share/doc/omxplayer/
cp README.md $(DIST)/usr/share/doc/omxplayer/README
cp -a ffmpeg_compiled/usr/local/lib/*.so* $(DIST)/usr/lib/omxplayer/
tar -czf omxplayer-dist.tar.gz $(DIST)
20 changes: 15 additions & 5 deletions OMXAudio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,10 @@ bool COMXAudio::Initialize(IAudioCallback* pCallback, const CStdString& device,
deviceuse = "local";
}

if(!m_dllAvUtil.Load())
if(!m_dllAvUtil.Load()) {
printf("COMXAudio dll error\n");
return false;
}

m_Passthrough = false;

Expand Down Expand Up @@ -338,26 +340,34 @@ bool COMXAudio::Initialize(IAudioCallback* pCallback, const CStdString& device,
std::string componentName = "";

componentName = "OMX.broadcom.audio_render";
if(!m_omx_render.Initialize(componentName, OMX_IndexParamAudioInit))
if(!m_omx_render.Initialize(componentName, OMX_IndexParamAudioInit)) {
printf("COMXAudio audio_render init error\n");
return false;
}

OMX_CONFIG_BRCMAUDIODESTINATIONTYPE audioDest;
OMX_INIT_STRUCTURE(audioDest);
strncpy((char *)audioDest.sName, device.c_str(), strlen(device.c_str()));

omx_err = m_omx_render.SetConfig(OMX_IndexConfigBrcmAudioDestination, &audioDest);
if (omx_err != OMX_ErrorNone)
if (omx_err != OMX_ErrorNone) {
printf("COMXAudio audiodest error %d\n", omx_err);
return false;
}

componentName = "OMX.broadcom.audio_decode";
if(!m_omx_decoder.Initialize(componentName, OMX_IndexParamAudioInit))
if(!m_omx_decoder.Initialize(componentName, OMX_IndexParamAudioInit)) {
printf("COMXAudio audio_decode error\n");
return false;
}

if(!m_Passthrough)
{
componentName = "OMX.broadcom.audio_mixer";
if(!m_omx_mixer.Initialize(componentName, OMX_IndexParamAudioInit))
if(!m_omx_mixer.Initialize(componentName, OMX_IndexParamAudioInit)) {
printf("COMXAudio audio_mixer error\n");
return false;
}
}

if(m_Passthrough)
Expand Down
28 changes: 28 additions & 0 deletions OMXClock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ double OMXClock::SystemToPlaying(int64_t system)
m_pauseClock = 0;
m_iDisc = 0;
m_bReset = false;
//CLog::Log(LOGDEBUG, "**** reset: m_startClock %lld\n", m_startClock);
}

if (m_pauseClock)
Expand Down Expand Up @@ -221,6 +222,7 @@ void OMXClock::Discontinuity(double currentPts)
m_pauseClock = m_startClock;
m_iDisc = currentPts;
m_bReset = false;
//CLog::Log(LOGDEBUG, "**** discontinuity: cpts %f m_startClock %lld\n", currentPts, m_startClock);
UnLock();
}

Expand Down Expand Up @@ -680,6 +682,32 @@ bool OMXClock::OMXUpdateClock(double pts, bool lock /* = true */)
return true;
}

bool OMXClock::OMXSeek(int porti, double pts, bool lock /* = true */)
{
if(m_omx_clock.GetComponent() == NULL)
return false;

if(lock)
Lock();

OMX_ERRORTYPE omx_err = OMX_ErrorNone;
OMX_TIME_CONFIG_TIMESTAMPTYPE ts;
OMX_INIT_STRUCTURE(ts);

ts.nPortIndex = m_omx_clock.GetInputPort();
ts.nTimestamp = ToOMXTime((uint64_t)pts);

omx_err = OMX_SetConfig(m_omx_clock.GetComponent(), OMX_IndexConfigTimeClientStartTime, &ts);
if(omx_err != OMX_ErrorNone) {
CLog::Log(LOGERROR, "OMXClock::OMXUpdateClock error setting OMX_IndexConfigTimeClientStartTime: %x\n", omx_err);
}

if(lock)
UnLock();

return true;
}

bool OMXClock::OMXWaitStart(double pts, bool lock /* = true */)
{
if(m_omx_clock.GetComponent() == NULL)
Expand Down
1 change: 1 addition & 0 deletions OMXClock.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ class OMXClock
double OMXMediaTime(bool lock = true);
bool OMXPause(bool lock = true);
bool OMXResume(bool lock = true);
bool OMXSeek(int porti, double pts, bool lock = true);
bool OMXUpdateClock(double pts, bool lock = true);
bool OMXWaitStart(double pts, bool lock = true);
bool OMXSpeed(int speed, bool lock = true);
Expand Down
21 changes: 18 additions & 3 deletions OMXPlayerAudio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,17 @@ bool OMXPlayerAudio::Open(COMXStreamInfo &hints, OMXClock *av_clock, OMXReader *
if(ThreadHandle())
Close();

if (!m_dllAvUtil.Load() || !m_dllAvCodec.Load() || !m_dllAvFormat.Load() || !av_clock)
if (!m_dllAvUtil.Load() || !m_dllAvCodec.Load() || !m_dllAvFormat.Load() || !av_clock) {
printf("OMXPlayerAudio DLL error\n");
return false;
}

m_dllAvFormat.av_register_all();

SetReader(omx_reader);

m_hints = hints;
m_av_clock = av_clock;
m_omx_reader = omx_reader;
m_device = device;
m_passthrough = IAudioRenderer::ENCODED_NONE;
m_hw_decode = false;
Expand All @@ -121,7 +124,6 @@ bool OMXPlayerAudio::Open(COMXStreamInfo &hints, OMXClock *av_clock, OMXReader *
m_boost_on_downmix = boost_on_downmix;
m_iCurrentPts = DVD_NOPTS_VALUE;
m_bAbort = false;
m_bMpeg = m_omx_reader->IsMpegVideo();
m_use_thread = use_thread;
m_flush = false;
m_cached_size = 0;
Expand Down Expand Up @@ -164,6 +166,12 @@ bool OMXPlayerAudio::Open(COMXStreamInfo &hints, OMXClock *av_clock, OMXReader *
return true;
}

void OMXPlayerAudio::SetReader(OMXReader *omx_reader)
{
m_omx_reader = omx_reader;
m_bMpeg = m_omx_reader->IsMpegVideo();
}

bool OMXPlayerAudio::Close()
{
m_bAbort = true;
Expand Down Expand Up @@ -494,6 +502,11 @@ void OMXPlayerAudio::Flush()
UnLock();
}

void OMXPlayerAudio::UnFlush()
{
m_flush = false;
}

bool OMXPlayerAudio::AddPacket(OMXPacket *pkt)
{
bool ret = false;
Expand Down Expand Up @@ -523,6 +536,7 @@ bool OMXPlayerAudio::OpenAudioCodec()

if(!m_pAudioCodec->Open(m_hints))
{
printf("OMXPlayerAudio audio codec open error\n");
delete m_pAudioCodec; m_pAudioCodec = NULL;
return false;
}
Expand Down Expand Up @@ -634,6 +648,7 @@ bool OMXPlayerAudio::OpenDecoder()

if(!bAudioRenderOpen)
{
printf("OMXPlayerAudio audio decoder open error\n");
delete m_decoder;
m_decoder = NULL;
return false;
Expand Down
2 changes: 2 additions & 0 deletions OMXPlayerAudio.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,12 @@ class OMXPlayerAudio : public CThread
bool Open(COMXStreamInfo &hints, OMXClock *av_clock, OMXReader *omx_reader,
std::string device, bool passthrough, bool hw_decode,
bool boost_on_downmix, bool use_thread);
void SetReader(OMXReader *omx_reader);
bool Close();
bool Decode(OMXPacket *pkt);
void Process();
void Flush();
void UnFlush();
bool AddPacket(OMXPacket *pkt);
bool OpenAudioCodec();
void CloseAudioCodec();
Expand Down
41 changes: 33 additions & 8 deletions OMXPlayerVideo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,21 +131,18 @@ bool OMXPlayerVideo::Open(COMXStreamInfo &hints, OMXClock *av_clock, const CRect
m_Deinterlace = deinterlace;
m_display_aspect = display_aspect;
m_bMpeg = mpeg;
m_iCurrentPts = DVD_NOPTS_VALUE;
m_bAbort = false;
m_use_thread = use_thread;
m_flush = false;
m_cached_size = 0;
m_iVideoDelay = 0;
m_hdmi_clock_sync = hdmi_clock_sync;
m_pts = 0;
m_syncclock = true;
m_speed = DVD_PLAYSPEED_NORMAL;
m_iSubtitleDelay = 0;
m_pSubtitleCodec = NULL;
m_DestRect = DestRect;

m_FlipTimeStamp = m_av_clock->GetAbsoluteClock();
Reset();

if(!OpenDecoder())
{
Expand All @@ -161,6 +158,16 @@ bool OMXPlayerVideo::Open(COMXStreamInfo &hints, OMXClock *av_clock, const CRect
return true;
}

void OMXPlayerVideo::Reset()
{
m_iCurrentPts = DVD_NOPTS_VALUE;
m_bAbort = false;
m_syncclock = true;
m_FlipTimeStamp = m_av_clock->GetAbsoluteClock();
if(m_decoder)
m_decoder->Reset();
}

bool OMXPlayerVideo::Close()
{
m_bAbort = true;
Expand Down Expand Up @@ -246,13 +253,17 @@ void OMXPlayerVideo::Output(double pts)

m_av_clock->SetPTS(m_iCurrentPts);

// CLog::Log(LOGDEBUG, "PlayerVideo output pts %f(=%f) icc %f ipc %f ics %f ifs %f ifd %f\n", pts, m_iCurrentPts, iCurrentClock, iPlayingClock, iClockSleep, iFrameSleep, iFrameDuration);

// timestamp when we think next picture should be displayed based on current duration
m_FlipTimeStamp = iCurrentClock;
m_FlipTimeStamp += max(0.0, iSleepTime);
m_FlipTimeStamp += iFrameDuration;

while(m_av_clock->GetAbsoluteClock(false) < (iCurrentClock + iSleepTime + DVD_MSEC_TO_TIME(500)) )
double absclock;
while((absclock = m_av_clock->GetAbsoluteClock(false)) < (iCurrentClock + iSleepTime + DVD_MSEC_TO_TIME(500)) )
{
// CLog::Log(LOGDEBUG, "PlayerVideo wait (absclock %f < icc %f + ist %f + 500msec)\n", absclock, iCurrentClock, iSleepTime);
OMXClock::OMXSleep(10);
}

Expand All @@ -266,11 +277,14 @@ void OMXPlayerVideo::Output(double pts)

//g_renderManager.FlipPage(CThread::m_bStop, (iCurrentClock + iSleepTime) / DVD_TIME_BASE, -1, mDisplayField);

// CLog::Log(LOGDEBUG, "PlayerVideo abswait\n");
m_av_clock->WaitAbsoluteClock((iCurrentClock + iSleepTime));
// CLog::Log(LOGDEBUG, "PlayerVideo abswait over; m_pts %lld\n", (long long) m_pts);

// guess next frame pts. iDuration is always valid
if (m_speed != 0)
m_pts += m_frametime * m_speed / abs(m_speed);
// CLog::Log(LOGDEBUG, "PlayerVideo final m_pts %lld\n", (long long) m_pts);
}

bool OMXPlayerVideo::Decode(OMXPacket *pkt)
Expand All @@ -280,8 +294,10 @@ bool OMXPlayerVideo::Decode(OMXPacket *pkt)

bool ret = false;

if(!((unsigned long)m_decoder->GetFreeSpace() > pkt->size))
if(!((unsigned long)m_decoder->GetFreeSpace() > pkt->size)) {
// CLog::Log(LOGDEBUG, "decoder buffer full\n");
OMXClock::OMXSleep(10);
}

if (pkt->dts == DVD_NOPTS_VALUE && pkt->pts == DVD_NOPTS_VALUE)
pkt->pts = m_pts;
Expand Down Expand Up @@ -363,16 +379,20 @@ bool OMXPlayerVideo::Decode(OMXPacket *pkt)
}
else if((unsigned long)m_decoder->GetFreeSpace() > pkt->size)
{
if(m_bMpeg)
if(m_bMpeg) {
m_decoder->Decode(pkt->data, pkt->size, DVD_NOPTS_VALUE, DVD_NOPTS_VALUE);
else
} else {
// CLog::Log(LOGDEBUG, "--- decode pts %f\n", m_pts);
m_decoder->Decode(pkt->data, pkt->size, m_pts, m_pts);
}

m_av_clock->SetVideoClock(m_pts);

Output(m_pts);

ret = true;
} else {
// CLog::Log(LOGDEBUG, "--- decoder buffer full, dropping frame\n");
}

return ret;
Expand Down Expand Up @@ -482,6 +502,11 @@ void OMXPlayerVideo::Flush()
UnLock();
}

void OMXPlayerVideo::UnFlush()
{
m_flush = false;
}

bool OMXPlayerVideo::AddPacket(OMXPacket *pkt)
{
bool ret = false;
Expand Down
2 changes: 2 additions & 0 deletions OMXPlayerVideo.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,14 @@ class OMXPlayerVideo : public CThread
OMXPlayerVideo();
~OMXPlayerVideo();
bool Open(COMXStreamInfo &hints, OMXClock *av_clock, const CRect& DestRect, bool deinterlace, bool mpeg, bool hdmi_clock_sync, bool use_thread, float display_aspect);
void Reset();
bool Close();
void Output(double pts);
bool Decode(OMXPacket *pkt);
void Process();
void FlushSubtitles();
void Flush();
void UnFlush();
bool AddPacket(OMXPacket *pkt);
bool OpenDecoder();
bool CloseDecoder();
Expand Down
2 changes: 1 addition & 1 deletion OMXThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ bool OMXThread::StopThread()

m_thread = 0;

CLog::Log(LOGDEBUG, "%s::%s - Thread stopped\n", CLASSNAME, __func__);
CLog::Log(LOGDEBUG, "%s::%s - Thread with id %d stopped\n", CLASSNAME, __func__, (int)m_thread);
return true;
}

Expand Down
11 changes: 7 additions & 4 deletions OMXVideo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,7 @@ int COMXVideo::Decode(uint8_t *pData, int iSize, double dts, double pts)

if(m_setStartTime)
{
//if (val > 0) m_av_clock->OMXSeek(m_omx_decoder.GetOutputPort(), val);
omx_buffer->nFlags = OMX_BUFFERFLAG_STARTTIME;
m_setStartTime = false;
}
Expand All @@ -941,6 +942,8 @@ int COMXVideo::Decode(uint8_t *pData, int iSize, double dts, double pts)
if(demuxer_bytes == 0)
omx_buffer->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;

// CLog::Log(LOGDEBUG, "decoder ts %llu flags %lx\n", val, omx_buffer->nFlags);

int nRetry = 0;
while(true)
{
Expand Down Expand Up @@ -1045,10 +1048,10 @@ void COMXVideo::Reset(void)
m_omx_decoder.FlushInput();
m_omx_tunnel_decoder.Flush();

//m_setStartTime = true;
//m_setStartTimeText = true;
m_setStartTime = true;
m_setStartTimeText = true;

//m_first_frame = true;
// m_first_frame = true;
}

///////////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -1152,7 +1155,7 @@ void COMXVideo::WaitCompletion()
omx_buffer->nFilledLen = 0;
omx_buffer->nTimeStamp = ToOMXTime(0LL);

omx_buffer->nFlags = OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS | OMX_BUFFERFLAG_TIME_UNKNOWN;
omx_buffer->nFlags = OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_TIME_UNKNOWN;

omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer);
if (omx_err != OMX_ErrorNone)
Expand Down
Loading