Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

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.
  • Loading branch information...
commit 679b668e3669a38bd08e93aa1f210ad11da0984e 1 parent fa9b6ca
Mark Kendall authored
View
15 mythtv/libs/libmythtv/avformatdecoder.cpp
@@ -714,6 +714,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)")
@@ -3925,8 +3937,7 @@ bool AvFormatDecoder::GetFrame(DecodeType decodetype)
if (retval == -EAGAIN)
continue;
- ateof = true;
- m_parent->SetEof();
+ SetEof(true);
delete pkt;
return false;
}
View
4 mythtv/libs/libmythtv/avformatdecoder.h
@@ -98,9 +98,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
View
2  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)
View
3  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; }
View
2  mythtv/libs/libmythtv/mythcommflagplayer.cpp
@@ -108,7 +108,7 @@ bool MythCommFlagPlayer::RebuildSeekTable(
fflush( stdout );
}
- while (!decoderEof)
+ while (!GetEof())
{
if (inuse_timer.elapsed() > 2534)
{
View
60 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),
@@ -974,9 +973,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;
@@ -2278,7 +2274,7 @@ void MythPlayer::SwitchToProgram(void)
{
OpenDummy();
ResetPlaying();
- decoderEof = false;
+ SetEof(false);
delete pginfo;
return;
}
@@ -2292,13 +2288,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();
@@ -2306,7 +2302,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)
{
@@ -2336,10 +2332,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());
@@ -2351,7 +2349,6 @@ void MythPlayer::SwitchToProgram(void)
forcePositionMapSync = true;
}
- decoderEof = false;
Play();
VERBOSE(VB_PLAYBACK, LOC + "SwitchToProgram - end");
}
@@ -2366,10 +2363,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__);
@@ -2406,7 +2402,7 @@ void MythPlayer::JumpToProgram(void)
{
OpenDummy();
ResetPlaying();
- decoderEof = false;
+ SetEof(false);
delete pginfo;
return;
}
@@ -2422,8 +2418,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;
@@ -2447,6 +2442,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);
@@ -2467,7 +2464,6 @@ void MythPlayer::JumpToProgram(void)
if (nextpos > 10)
DoFastForward(nextpos, true, false);
- decoderEof = false;
player_ctx->SetPlayerChangingBuffers(false);
VERBOSE(VB_PLAYBACK, LOC + "JumpToProgram - end");
}
@@ -2590,7 +2586,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
@@ -2641,7 +2637,7 @@ void MythPlayer::EventLoop(void)
}
// Handle end of file
- if (decoderEof)
+ if (GetEof())
{
if (player_ctx->tvchain)
{
@@ -2674,7 +2670,7 @@ void MythPlayer::EventLoop(void)
if (fftime > 0)
{
DoFastForward(fftime);
- if (decoderEof)
+ if (GetEof())
return;
}
}
@@ -2736,7 +2732,7 @@ void MythPlayer::EventLoop(void)
&& !player_ctx->IsPIP() &&
player_ctx->GetState() == kState_WatchingPreRecorded))
{
- decoderEof = true;
+ SetEof(true);
}
}
else
@@ -2839,6 +2835,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)
@@ -2878,8 +2890,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))
{
@@ -4232,7 +4244,7 @@ bool MythPlayer::TranscodeGetNextFrame(
if (!decoder->GetFrame(kDecodeAV))
return false;
- if (decoderEof)
+ if (GetEof())
return false;
if (honorCutList && !deleteMap.IsEmpty())
@@ -4257,7 +4269,7 @@ bool MythPlayer::TranscodeGetNextFrame(
did_ff = 1;
}
}
- if (decoderEof)
+ if (GetEof())
return false;
is_key = decoder->isLastFrameKey();
return true;
View
5 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; }
@@ -534,7 +534,6 @@ class MPUBLIC MythPlayer
QWaitCondition decoderThreadUnpause;
mutable QMutex decoderPauseLock;
mutable QMutex decoderSeekLock;
- bool decoderEof;
bool decoderPaused;
bool pauseDecoder;
bool unpauseDecoder;
View
18 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;
}
}
Please sign in to comment.
Something went wrong with that request. Please try again.