summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Kendall <mkendall@mythtv.org>2011-01-29 03:11:09 (GMT)
committer Mark Kendall <mkendall@mythtv.org>2011-02-15 01:33:02 (GMT)
commitad1543aefe287de8706c2e8365208b973427f5dd (patch)
treeca6123fd7a0af1ecbf2764fcf34968ab91a27f5c
parentb2c0afc005ea54cef3a562690fa4dcc349a06599 (diff)
Refactor 'eof' handling in the decoder and player classes.
This moves all eof 'ownership' into the decoder which is then queried by the player as needed. AvFormatDecoder is extended to reset the picture buffer eof flag to zero if we are clearing the eof state. This fixes livetv program transitions where the decoder has already decided it has hit the end of the file before we switch to the next program and as a result stops returning frames. My only concern here is the extra locking now required inside the GetEof method in MythPlayer. The current plan of action is however to ensure the decoder locking is 'industrial strength' (Hint: it currently isn't) before looking at how to minimise the locking required in the main playback loop. (cherry picked from commit 679b668e3669a38bd08e93aa1f210ad11da0984e)
-rw-r--r--mythtv/libs/libmythtv/avformatdecoder.cpp15
-rw-r--r--mythtv/libs/libmythtv/avformatdecoder.h4
-rw-r--r--mythtv/libs/libmythtv/decoderbase.cpp2
-rw-r--r--mythtv/libs/libmythtv/decoderbase.h3
-rw-r--r--mythtv/libs/libmythtv/mythcommflagplayer.cpp2
-rw-r--r--mythtv/libs/libmythtv/mythplayer.cpp60
-rw-r--r--mythtv/libs/libmythtv/mythplayer.h5
-rw-r--r--mythtv/libs/libmythtv/nuppeldecoder.cpp18
8 files changed, 65 insertions, 44 deletions
diff --git a/mythtv/libs/libmythtv/avformatdecoder.cpp b/mythtv/libs/libmythtv/avformatdecoder.cpp
index b2b299c..05df6a5 100644
--- a/mythtv/libs/libmythtv/avformatdecoder.cpp
+++ b/mythtv/libs/libmythtv/avformatdecoder.cpp
@@ -743,6 +743,18 @@ void AvFormatDecoder::SeekReset(long long newKey, uint skipFrames,
}
}
+void AvFormatDecoder::SetEof(bool eof)
+{
+ if (!eof && ic && ic->pb)
+ {
+ VERBOSE(VB_IMPORTANT, LOC +
+ QString("Resetting byte context eof (livetv %1 was eof %2)")
+ .arg(livetv).arg(ic->pb->eof_reached));
+ ic->pb->eof_reached = 0;
+ }
+ DecoderBase::SetEof(eof);
+}
+
void AvFormatDecoder::Reset(bool reset_video_data, bool seek_reset)
{
VERBOSE(VB_PLAYBACK, LOC + QString("Reset(%1, %2)")
@@ -4259,8 +4271,7 @@ bool AvFormatDecoder::GetFrame(DecodeType decodetype)
if (retval == -EAGAIN)
continue;
- ateof = true;
- m_parent->SetEof();
+ SetEof(true);
delete pkt;
return false;
}
diff --git a/mythtv/libs/libmythtv/avformatdecoder.h b/mythtv/libs/libmythtv/avformatdecoder.h
index aef6e68..0f10bb2 100644
--- a/mythtv/libs/libmythtv/avformatdecoder.h
+++ b/mythtv/libs/libmythtv/avformatdecoder.h
@@ -95,9 +95,11 @@ class AvFormatDecoder : public DecoderBase
AVSpecialDecode av_special_decode = kAVSpecialDecode_None);
~AvFormatDecoder();
+ virtual void SetEof(bool eof);
+
void CloseCodecs();
void CloseContext();
- void Reset(void);
+ virtual void Reset(void);
void Reset(bool reset_video_data = true, bool seek_reset = true);
/// Perform an av_probe_input_format on the passed data to see if we
diff --git a/mythtv/libs/libmythtv/decoderbase.cpp b/mythtv/libs/libmythtv/decoderbase.cpp
index df11e14..8849258 100644
--- a/mythtv/libs/libmythtv/decoderbase.cpp
+++ b/mythtv/libs/libmythtv/decoderbase.cpp
@@ -77,7 +77,7 @@ void DecoderBase::Reset(void)
dontSyncPositionMap = false;
waitingForChange = false;
- ateof = false;
+ SetEof(false);
}
void DecoderBase::SeekReset(long long, uint, bool, bool)
diff --git a/mythtv/libs/libmythtv/decoderbase.h b/mythtv/libs/libmythtv/decoderbase.h
index aca1d60..e4311e3 100644
--- a/mythtv/libs/libmythtv/decoderbase.h
+++ b/mythtv/libs/libmythtv/decoderbase.h
@@ -94,6 +94,9 @@ class DecoderBase
char testbuf[kDecoderProbeBufferSize],
int testbufsize = kDecoderProbeBufferSize) = 0;
+ virtual void SetEof(bool eof) { ateof = eof; }
+ bool GetEof(void) { return ateof; }
+
void setExactSeeks(bool exact) { exactseeks = exact; }
bool getExactSeeks(void) const { return exactseeks; }
void setLiveTVMode(bool live) { livetv = live; }
diff --git a/mythtv/libs/libmythtv/mythcommflagplayer.cpp b/mythtv/libs/libmythtv/mythcommflagplayer.cpp
index ac1187f..6b15270 100644
--- a/mythtv/libs/libmythtv/mythcommflagplayer.cpp
+++ b/mythtv/libs/libmythtv/mythcommflagplayer.cpp
@@ -108,7 +108,7 @@ bool MythCommFlagPlayer::RebuildSeekTable(
fflush( stdout );
}
- while (!decoderEof)
+ while (!GetEof())
{
if (inuse_timer.elapsed() > 2534)
{
diff --git a/mythtv/libs/libmythtv/mythplayer.cpp b/mythtv/libs/libmythtv/mythplayer.cpp
index 52bd5b3..d7e4e24 100644
--- a/mythtv/libs/libmythtv/mythplayer.cpp
+++ b/mythtv/libs/libmythtv/mythplayer.cpp
@@ -130,7 +130,6 @@ MythPlayer::MythPlayer(bool muted)
parentWidget(NULL), embedid(0),
embx(-1), emby(-1), embw(-1), embh(-1),
// State
- decoderEof(false),
decoderPaused(false), pauseDecoder(false), unpauseDecoder(false),
killdecoder(false), decoderSeek(-1), decodeOneFrame(false),
needNewPauseFrame(false),
@@ -968,9 +967,6 @@ int MythPlayer::OpenFile(uint retries, bool allow_libmpeg2)
CheckExtraAudioDecode();
noVideoTracks = !decoder->GetTrackCount(kTrackTypeVideo);
-
- decoderEof = false;
-
// Set 'no_video_decode' to true for audio only decodeing
bool no_video_decode = false;
@@ -2193,7 +2189,7 @@ void MythPlayer::SwitchToProgram(void)
{
OpenDummy();
ResetPlaying();
- decoderEof = false;
+ SetEof(false);
delete pginfo;
return;
}
@@ -2207,13 +2203,13 @@ void MythPlayer::SwitchToProgram(void)
QString("(card type: %1).")
.arg(player_ctx->tvchain->GetCardType(newid)));
VERBOSE(VB_IMPORTANT, QString("\n") + player_ctx->tvchain->toString());
- decoderEof = true;
+ SetEof(true);
SetErrored(QObject::tr("Error opening switch program buffer"));
delete pginfo;
return;
}
- if (decoderEof)
+ if (GetEof())
{
discontinuity = true;
ResetCaptions();
@@ -2221,7 +2217,7 @@ void MythPlayer::SwitchToProgram(void)
VERBOSE(VB_PLAYBACK, LOC + QString("SwitchToProgram(void) "
"discont: %1 newtype: %2 newid: %3 decoderEof: %4")
- .arg(discontinuity).arg(newtype).arg(newid).arg(decoderEof));
+ .arg(discontinuity).arg(newtype).arg(newid).arg(GetEof()));
if (discontinuity || newtype)
{
@@ -2251,10 +2247,12 @@ void MythPlayer::SwitchToProgram(void)
if (IsErrored())
{
VERBOSE(VB_IMPORTANT, LOC_ERR + "SwitchToProgram failed.");
- decoderEof = true;
+ SetEof(true);
return;
}
+ SetEof(false);
+
// the bitrate is reset by player_ctx->buffer->OpenFile()...
if (decoder)
player_ctx->buffer->UpdateRawBitrate(decoder->GetRawBitrate());
@@ -2266,7 +2264,6 @@ void MythPlayer::SwitchToProgram(void)
forcePositionMapSync = true;
}
- decoderEof = false;
Play();
VERBOSE(VB_PLAYBACK, LOC + "SwitchToProgram - end");
}
@@ -2281,10 +2278,9 @@ void MythPlayer::FileChangedCallback(void)
player_ctx->buffer->Reset(false, true);
else
player_ctx->buffer->Reset(false, true, true);
+ SetEof(false);
Play();
- decoderEof = false;
-
player_ctx->SetPlayerChangingBuffers(false);
player_ctx->LockPlayingInfo(__FILE__, __LINE__);
@@ -2322,7 +2318,7 @@ void MythPlayer::JumpToProgram(void)
{
OpenDummy();
ResetPlaying();
- decoderEof = false;
+ SetEof(false);
delete pginfo;
return;
}
@@ -2338,8 +2334,7 @@ void MythPlayer::JumpToProgram(void)
QString("(card type: %1).")
.arg(player_ctx->tvchain->GetCardType(newid)));
VERBOSE(VB_IMPORTANT, QString("\n") + player_ctx->tvchain->toString());
-
- decoderEof = true;
+ SetEof(true);
SetErrored(QObject::tr("Error opening jump program file buffer"));
delete pginfo;
return;
@@ -2363,6 +2358,8 @@ void MythPlayer::JumpToProgram(void)
return;
}
+ SetEof(false);
+
// the bitrate is reset by player_ctx->buffer->OpenFile()...
player_ctx->buffer->UpdateRawBitrate(decoder->GetRawBitrate());
player_ctx->buffer->IgnoreLiveEOF(false);
@@ -2383,7 +2380,6 @@ void MythPlayer::JumpToProgram(void)
if (nextpos > 10)
DoFastForward(nextpos, true, false);
- decoderEof = false;
player_ctx->SetPlayerChangingBuffers(false);
VERBOSE(VB_PLAYBACK, LOC + "JumpToProgram - end");
}
@@ -2506,7 +2502,7 @@ void MythPlayer::EventLoop(void)
player_ctx->tvchain->JumpToNext(true, 1);
JumpToProgram();
}
- else if ((!allpaused || decoderEof) && player_ctx->tvchain &&
+ else if ((!allpaused || GetEof()) && player_ctx->tvchain &&
(decoder && !decoder->GetWaitForChange()))
{
// Switch to the next program in livetv
@@ -2557,7 +2553,7 @@ void MythPlayer::EventLoop(void)
}
// Handle end of file
- if (decoderEof)
+ if (GetEof())
{
if (player_ctx->tvchain)
{
@@ -2590,7 +2586,7 @@ void MythPlayer::EventLoop(void)
if (fftime > 0)
{
DoFastForward(fftime);
- if (decoderEof)
+ if (GetEof())
return;
}
}
@@ -2652,7 +2648,7 @@ void MythPlayer::EventLoop(void)
&& !player_ctx->IsPIP() &&
player_ctx->GetState() == kState_WatchingPreRecorded))
{
- decoderEof = true;
+ SetEof(true);
}
}
else
@@ -2755,6 +2751,22 @@ void MythPlayer::DecoderPauseCheck(void)
UnpauseDecoder();
}
+bool MythPlayer::GetEof(void)
+{
+ decoder_change_lock.lock();
+ bool eof = decoder ? decoder->GetEof() : true;
+ decoder_change_lock.unlock();
+ return eof;
+}
+
+void MythPlayer::SetEof(bool eof)
+{
+ decoder_change_lock.lock();
+ if (decoder)
+ decoder->SetEof(eof);
+ decoder_change_lock.unlock();
+}
+
void MythPlayer::DecoderLoop(bool pause)
{
if (pause)
@@ -2796,8 +2808,8 @@ void MythPlayer::DecoderLoop(bool pause)
decoder_change_lock.unlock();
}
- bool obey_eof = decoderEof &&
- !(decoderEof && player_ctx->tvchain && !allpaused);
+ bool obey_eof = GetEof() &&
+ !(GetEof() && player_ctx->tvchain && !allpaused);
if (isDummy || ((decoderPaused || ffrew_skip == 0 || obey_eof) &&
!decodeOneFrame))
{
@@ -4135,7 +4147,7 @@ bool MythPlayer::TranscodeGetNextFrame(
if (!decoder->GetFrame(kDecodeAV))
return false;
- if (decoderEof)
+ if (GetEof())
return false;
if (honorCutList && !deleteMap.IsEmpty())
@@ -4160,7 +4172,7 @@ bool MythPlayer::TranscodeGetNextFrame(
did_ff = 1;
}
}
- if (decoderEof)
+ if (GetEof())
return false;
is_key = decoder->isLastFrameKey();
return true;
diff --git a/mythtv/libs/libmythtv/mythplayer.h b/mythtv/libs/libmythtv/mythplayer.h
index 17a1684..87f8753 100644
--- a/mythtv/libs/libmythtv/mythplayer.h
+++ b/mythtv/libs/libmythtv/mythplayer.h
@@ -124,7 +124,7 @@ class MPUBLIC MythPlayer
void SetLength(int len) { totalLength = len; }
void SetFramesPlayed(uint64_t played) { framesPlayed = played; }
void SetVideoFilters(const QString &override);
- void SetEof(void) { decoderEof = true; }
+ void SetEof(bool eof);
void SetPIPActive(bool is_active) { pip_active = is_active; }
void SetPIPVisible(bool is_visible) { pip_visible = is_visible; }
@@ -175,7 +175,7 @@ class MPUBLIC MythPlayer
// Bool Gets
bool GetRawAudioState(void) const;
bool GetLimitKeyRepeat(void) const { return limitKeyRepeat; }
- bool GetEof(void) const { return decoderEof; }
+ bool GetEof(void);
bool IsErrored(void) const;
bool IsPlaying(uint wait_ms = 0, bool wait_for = true) const;
bool AtNormalSpeed(void) const { return next_normal_speed; }
@@ -531,7 +531,6 @@ class MPUBLIC MythPlayer
QWaitCondition decoderThreadUnpause;
mutable QMutex decoderPauseLock;
mutable QMutex decoderSeekLock;
- bool decoderEof;
bool decoderPaused;
bool pauseDecoder;
bool unpauseDecoder;
diff --git a/mythtv/libs/libmythtv/nuppeldecoder.cpp b/mythtv/libs/libmythtv/nuppeldecoder.cpp
index a0915c9..d75661e 100644
--- a/mythtv/libs/libmythtv/nuppeldecoder.cpp
+++ b/mythtv/libs/libmythtv/nuppeldecoder.cpp
@@ -1056,8 +1056,7 @@ bool NuppelDecoder::GetFrame(DecodeType decodetype)
if (!ReadFrameheader(&frameheader))
{
- ateof = true;
- GetPlayer()->SetEof();
+ SetEof(true);
return false;
}
@@ -1065,8 +1064,7 @@ bool NuppelDecoder::GetFrame(DecodeType decodetype)
if (!ringBuffer->LiveMode() &&
((frameheader.frametype == 'Q') || (frameheader.frametype == 'K')))
{
- ateof = true;
- GetPlayer()->SetEof();
+ SetEof(true);
return false;
}
@@ -1083,8 +1081,7 @@ bool NuppelDecoder::GetFrame(DecodeType decodetype)
if (!ReadFrameheader(&frameheader))
{
- ateof = true;
- GetPlayer()->SetEof();
+ SetEof(true);
return false;
}
seeklen = 1;
@@ -1098,8 +1095,7 @@ bool NuppelDecoder::GetFrame(DecodeType decodetype)
if (ringBuffer->Read(dummy, sizetoskip) != sizetoskip)
{
delete [] dummy;
- ateof = true;
- GetPlayer()->SetEof();
+ SetEof(true);
return false;
}
@@ -1157,15 +1153,13 @@ bool NuppelDecoder::GetFrame(DecodeType decodetype)
VERBOSE(VB_IMPORTANT, QString("Broken packet: %1 %2")
.arg(frameheader.frametype)
.arg(frameheader.packetlength));
- ateof = true;
- GetPlayer()->SetEof();
+ SetEof(true);
return false;
}
if (ringBuffer->Read(strm, frameheader.packetlength) !=
frameheader.packetlength)
{
- ateof = true;
- GetPlayer()->SetEof();
+ SetEof(true);
return false;
}
}