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-01-29 03:11:09 (GMT)
commit679b668e3669a38bd08e93aa1f210ad11da0984e (patch)
treee5ed15581cb713e880f122e13892f0a857c2510d
parentfa9b6ca13d132adda29ebe0fd8b8894370384cae (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.
-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 186561f..86d001d 100644
--- a/mythtv/libs/libmythtv/avformatdecoder.cpp
+++ b/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;
}
diff --git a/mythtv/libs/libmythtv/avformatdecoder.h b/mythtv/libs/libmythtv/avformatdecoder.h
index 539099f..833f941 100644
--- a/mythtv/libs/libmythtv/avformatdecoder.h
+++ b/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
diff --git a/mythtv/libs/libmythtv/decoderbase.cpp b/mythtv/libs/libmythtv/decoderbase.cpp
index 5b14d93..4097746 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 79f7df8..2397cfd 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 df9d838..00838d9 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),
@@ -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;
diff --git a/mythtv/libs/libmythtv/mythplayer.h b/mythtv/libs/libmythtv/mythplayer.h
index 543811b..6237389 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; }
@@ -534,7 +534,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 bc7281f..10de281 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;
}
}