Skip to content

Commit 679b668

Browse files
author
Mark Kendall
committed
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.
1 parent fa9b6ca commit 679b668

File tree

8 files changed

+65
-44
lines changed

8 files changed

+65
-44
lines changed

mythtv/libs/libmythtv/avformatdecoder.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,18 @@ void AvFormatDecoder::SeekReset(long long newKey, uint skipFrames,
714714
}
715715
}
716716

717+
void AvFormatDecoder::SetEof(bool eof)
718+
{
719+
if (!eof && ic && ic->pb)
720+
{
721+
VERBOSE(VB_IMPORTANT, LOC +
722+
QString("Resetting byte context eof (livetv %1 was eof %2)")
723+
.arg(livetv).arg(ic->pb->eof_reached));
724+
ic->pb->eof_reached = 0;
725+
}
726+
DecoderBase::SetEof(eof);
727+
}
728+
717729
void AvFormatDecoder::Reset(bool reset_video_data, bool seek_reset)
718730
{
719731
VERBOSE(VB_PLAYBACK, LOC + QString("Reset(%1, %2)")
@@ -3925,8 +3937,7 @@ bool AvFormatDecoder::GetFrame(DecodeType decodetype)
39253937
if (retval == -EAGAIN)
39263938
continue;
39273939

3928-
ateof = true;
3929-
m_parent->SetEof();
3940+
SetEof(true);
39303941
delete pkt;
39313942
return false;
39323943
}

mythtv/libs/libmythtv/avformatdecoder.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,11 @@ class AvFormatDecoder : public DecoderBase
9898
AVSpecialDecode av_special_decode = kAVSpecialDecode_None);
9999
~AvFormatDecoder();
100100

101+
virtual void SetEof(bool eof);
102+
101103
void CloseCodecs();
102104
void CloseContext();
103-
void Reset(void);
105+
virtual void Reset(void);
104106
void Reset(bool reset_video_data = true, bool seek_reset = true);
105107

106108
/// Perform an av_probe_input_format on the passed data to see if we

mythtv/libs/libmythtv/decoderbase.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ void DecoderBase::Reset(void)
7777
dontSyncPositionMap = false;
7878

7979
waitingForChange = false;
80-
ateof = false;
80+
SetEof(false);
8181
}
8282

8383
void DecoderBase::SeekReset(long long, uint, bool, bool)

mythtv/libs/libmythtv/decoderbase.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ class DecoderBase
9494
char testbuf[kDecoderProbeBufferSize],
9595
int testbufsize = kDecoderProbeBufferSize) = 0;
9696

97+
virtual void SetEof(bool eof) { ateof = eof; }
98+
bool GetEof(void) { return ateof; }
99+
97100
void setExactSeeks(bool exact) { exactseeks = exact; }
98101
bool getExactSeeks(void) const { return exactseeks; }
99102
void setLiveTVMode(bool live) { livetv = live; }

mythtv/libs/libmythtv/mythcommflagplayer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ bool MythCommFlagPlayer::RebuildSeekTable(
108108
fflush( stdout );
109109
}
110110

111-
while (!decoderEof)
111+
while (!GetEof())
112112
{
113113
if (inuse_timer.elapsed() > 2534)
114114
{

mythtv/libs/libmythtv/mythplayer.cpp

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@ MythPlayer::MythPlayer(bool muted)
130130
parentWidget(NULL), embedid(0),
131131
embx(-1), emby(-1), embw(-1), embh(-1),
132132
// State
133-
decoderEof(false),
134133
decoderPaused(false), pauseDecoder(false), unpauseDecoder(false),
135134
killdecoder(false), decoderSeek(-1), decodeOneFrame(false),
136135
needNewPauseFrame(false),
@@ -974,9 +973,6 @@ int MythPlayer::OpenFile(uint retries, bool allow_libmpeg2)
974973
CheckExtraAudioDecode();
975974
//noVideoTracks = !decoder->GetTrackCount(kTrackTypeVideo);
976975

977-
978-
decoderEof = false;
979-
980976
// Set 'no_video_decode' to true for audio only decodeing
981977
bool no_video_decode = false;
982978

@@ -2278,7 +2274,7 @@ void MythPlayer::SwitchToProgram(void)
22782274
{
22792275
OpenDummy();
22802276
ResetPlaying();
2281-
decoderEof = false;
2277+
SetEof(false);
22822278
delete pginfo;
22832279
return;
22842280
}
@@ -2292,21 +2288,21 @@ void MythPlayer::SwitchToProgram(void)
22922288
QString("(card type: %1).")
22932289
.arg(player_ctx->tvchain->GetCardType(newid)));
22942290
VERBOSE(VB_IMPORTANT, QString("\n") + player_ctx->tvchain->toString());
2295-
decoderEof = true;
2291+
SetEof(true);
22962292
SetErrored(QObject::tr("Error opening switch program buffer"));
22972293
delete pginfo;
22982294
return;
22992295
}
23002296

2301-
if (decoderEof)
2297+
if (GetEof())
23022298
{
23032299
discontinuity = true;
23042300
ResetCaptions();
23052301
}
23062302

23072303
VERBOSE(VB_PLAYBACK, LOC + QString("SwitchToProgram(void) "
23082304
"discont: %1 newtype: %2 newid: %3 decoderEof: %4")
2309-
.arg(discontinuity).arg(newtype).arg(newid).arg(decoderEof));
2305+
.arg(discontinuity).arg(newtype).arg(newid).arg(GetEof()));
23102306

23112307
if (discontinuity || newtype)
23122308
{
@@ -2336,10 +2332,12 @@ void MythPlayer::SwitchToProgram(void)
23362332
if (IsErrored())
23372333
{
23382334
VERBOSE(VB_IMPORTANT, LOC_ERR + "SwitchToProgram failed.");
2339-
decoderEof = true;
2335+
SetEof(true);
23402336
return;
23412337
}
23422338

2339+
SetEof(false);
2340+
23432341
// the bitrate is reset by player_ctx->buffer->OpenFile()...
23442342
if (decoder)
23452343
player_ctx->buffer->UpdateRawBitrate(decoder->GetRawBitrate());
@@ -2351,7 +2349,6 @@ void MythPlayer::SwitchToProgram(void)
23512349
forcePositionMapSync = true;
23522350
}
23532351

2354-
decoderEof = false;
23552352
Play();
23562353
VERBOSE(VB_PLAYBACK, LOC + "SwitchToProgram - end");
23572354
}
@@ -2366,10 +2363,9 @@ void MythPlayer::FileChangedCallback(void)
23662363
player_ctx->buffer->Reset(false, true);
23672364
else
23682365
player_ctx->buffer->Reset(false, true, true);
2366+
SetEof(false);
23692367
Play();
23702368

2371-
decoderEof = false;
2372-
23732369
player_ctx->SetPlayerChangingBuffers(false);
23742370

23752371
player_ctx->LockPlayingInfo(__FILE__, __LINE__);
@@ -2406,7 +2402,7 @@ void MythPlayer::JumpToProgram(void)
24062402
{
24072403
OpenDummy();
24082404
ResetPlaying();
2409-
decoderEof = false;
2405+
SetEof(false);
24102406
delete pginfo;
24112407
return;
24122408
}
@@ -2422,8 +2418,7 @@ void MythPlayer::JumpToProgram(void)
24222418
QString("(card type: %1).")
24232419
.arg(player_ctx->tvchain->GetCardType(newid)));
24242420
VERBOSE(VB_IMPORTANT, QString("\n") + player_ctx->tvchain->toString());
2425-
2426-
decoderEof = true;
2421+
SetEof(true);
24272422
SetErrored(QObject::tr("Error opening jump program file buffer"));
24282423
delete pginfo;
24292424
return;
@@ -2447,6 +2442,8 @@ void MythPlayer::JumpToProgram(void)
24472442
return;
24482443
}
24492444

2445+
SetEof(false);
2446+
24502447
// the bitrate is reset by player_ctx->buffer->OpenFile()...
24512448
player_ctx->buffer->UpdateRawBitrate(decoder->GetRawBitrate());
24522449
player_ctx->buffer->IgnoreLiveEOF(false);
@@ -2467,7 +2464,6 @@ void MythPlayer::JumpToProgram(void)
24672464
if (nextpos > 10)
24682465
DoFastForward(nextpos, true, false);
24692466

2470-
decoderEof = false;
24712467
player_ctx->SetPlayerChangingBuffers(false);
24722468
VERBOSE(VB_PLAYBACK, LOC + "JumpToProgram - end");
24732469
}
@@ -2590,7 +2586,7 @@ void MythPlayer::EventLoop(void)
25902586
player_ctx->tvchain->JumpToNext(true, 1);
25912587
JumpToProgram();
25922588
}
2593-
else if ((!allpaused || decoderEof) && player_ctx->tvchain &&
2589+
else if ((!allpaused || GetEof()) && player_ctx->tvchain &&
25942590
(decoder && !decoder->GetWaitForChange()))
25952591
{
25962592
// Switch to the next program in livetv
@@ -2641,7 +2637,7 @@ void MythPlayer::EventLoop(void)
26412637
}
26422638

26432639
// Handle end of file
2644-
if (decoderEof)
2640+
if (GetEof())
26452641
{
26462642
if (player_ctx->tvchain)
26472643
{
@@ -2674,7 +2670,7 @@ void MythPlayer::EventLoop(void)
26742670
if (fftime > 0)
26752671
{
26762672
DoFastForward(fftime);
2677-
if (decoderEof)
2673+
if (GetEof())
26782674
return;
26792675
}
26802676
}
@@ -2736,7 +2732,7 @@ void MythPlayer::EventLoop(void)
27362732
&& !player_ctx->IsPIP() &&
27372733
player_ctx->GetState() == kState_WatchingPreRecorded))
27382734
{
2739-
decoderEof = true;
2735+
SetEof(true);
27402736
}
27412737
}
27422738
else
@@ -2839,6 +2835,22 @@ void MythPlayer::DecoderPauseCheck(void)
28392835
UnpauseDecoder();
28402836
}
28412837

2838+
bool MythPlayer::GetEof(void)
2839+
{
2840+
decoder_change_lock.lock();
2841+
bool eof = decoder ? decoder->GetEof() : true;
2842+
decoder_change_lock.unlock();
2843+
return eof;
2844+
}
2845+
2846+
void MythPlayer::SetEof(bool eof)
2847+
{
2848+
decoder_change_lock.lock();
2849+
if (decoder)
2850+
decoder->SetEof(eof);
2851+
decoder_change_lock.unlock();
2852+
}
2853+
28422854
void MythPlayer::DecoderLoop(bool pause)
28432855
{
28442856
if (pause)
@@ -2878,8 +2890,8 @@ void MythPlayer::DecoderLoop(bool pause)
28782890
decoder_change_lock.unlock();
28792891
}
28802892

2881-
bool obey_eof = decoderEof &&
2882-
!(decoderEof && player_ctx->tvchain && !allpaused);
2893+
bool obey_eof = GetEof() &&
2894+
!(GetEof() && player_ctx->tvchain && !allpaused);
28832895
if (isDummy || ((decoderPaused || ffrew_skip == 0 || obey_eof) &&
28842896
!decodeOneFrame))
28852897
{
@@ -4232,7 +4244,7 @@ bool MythPlayer::TranscodeGetNextFrame(
42324244
if (!decoder->GetFrame(kDecodeAV))
42334245
return false;
42344246

4235-
if (decoderEof)
4247+
if (GetEof())
42364248
return false;
42374249

42384250
if (honorCutList && !deleteMap.IsEmpty())
@@ -4257,7 +4269,7 @@ bool MythPlayer::TranscodeGetNextFrame(
42574269
did_ff = 1;
42584270
}
42594271
}
4260-
if (decoderEof)
4272+
if (GetEof())
42614273
return false;
42624274
is_key = decoder->isLastFrameKey();
42634275
return true;

mythtv/libs/libmythtv/mythplayer.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ class MPUBLIC MythPlayer
124124
void SetLength(int len) { totalLength = len; }
125125
void SetFramesPlayed(uint64_t played) { framesPlayed = played; }
126126
void SetVideoFilters(const QString &override);
127-
void SetEof(void) { decoderEof = true; }
127+
void SetEof(bool eof);
128128
void SetPIPActive(bool is_active) { pip_active = is_active; }
129129
void SetPIPVisible(bool is_visible) { pip_visible = is_visible; }
130130

@@ -175,7 +175,7 @@ class MPUBLIC MythPlayer
175175
// Bool Gets
176176
bool GetRawAudioState(void) const;
177177
bool GetLimitKeyRepeat(void) const { return limitKeyRepeat; }
178-
bool GetEof(void) const { return decoderEof; }
178+
bool GetEof(void);
179179
bool IsErrored(void) const;
180180
bool IsPlaying(uint wait_ms = 0, bool wait_for = true) const;
181181
bool AtNormalSpeed(void) const { return next_normal_speed; }
@@ -534,7 +534,6 @@ class MPUBLIC MythPlayer
534534
QWaitCondition decoderThreadUnpause;
535535
mutable QMutex decoderPauseLock;
536536
mutable QMutex decoderSeekLock;
537-
bool decoderEof;
538537
bool decoderPaused;
539538
bool pauseDecoder;
540539
bool unpauseDecoder;

mythtv/libs/libmythtv/nuppeldecoder.cpp

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,17 +1056,15 @@ bool NuppelDecoder::GetFrame(DecodeType decodetype)
10561056

10571057
if (!ReadFrameheader(&frameheader))
10581058
{
1059-
ateof = true;
1060-
GetPlayer()->SetEof();
1059+
SetEof(true);
10611060
return false;
10621061
}
10631062

10641063

10651064
if (!ringBuffer->LiveMode() &&
10661065
((frameheader.frametype == 'Q') || (frameheader.frametype == 'K')))
10671066
{
1068-
ateof = true;
1069-
GetPlayer()->SetEof();
1067+
SetEof(true);
10701068
return false;
10711069
}
10721070

@@ -1083,8 +1081,7 @@ bool NuppelDecoder::GetFrame(DecodeType decodetype)
10831081

10841082
if (!ReadFrameheader(&frameheader))
10851083
{
1086-
ateof = true;
1087-
GetPlayer()->SetEof();
1084+
SetEof(true);
10881085
return false;
10891086
}
10901087
seeklen = 1;
@@ -1098,8 +1095,7 @@ bool NuppelDecoder::GetFrame(DecodeType decodetype)
10981095
if (ringBuffer->Read(dummy, sizetoskip) != sizetoskip)
10991096
{
11001097
delete [] dummy;
1101-
ateof = true;
1102-
GetPlayer()->SetEof();
1098+
SetEof(true);
11031099
return false;
11041100
}
11051101

@@ -1157,15 +1153,13 @@ bool NuppelDecoder::GetFrame(DecodeType decodetype)
11571153
VERBOSE(VB_IMPORTANT, QString("Broken packet: %1 %2")
11581154
.arg(frameheader.frametype)
11591155
.arg(frameheader.packetlength));
1160-
ateof = true;
1161-
GetPlayer()->SetEof();
1156+
SetEof(true);
11621157
return false;
11631158
}
11641159
if (ringBuffer->Read(strm, frameheader.packetlength) !=
11651160
frameheader.packetlength)
11661161
{
1167-
ateof = true;
1168-
GetPlayer()->SetEof();
1162+
SetEof(true);
11691163
return false;
11701164
}
11711165
}

0 commit comments

Comments
 (0)