Ticket #6974: 16-play-to-end

File 16-play-to-end, 8.9 KB (added by Mark Spieth, 9 years ago)
Line 
1play media to end when eof detected
2
3From: Mark Spieth <mspieth@digivation.com.au>
4
5
6---
7 mythtv/libs/libmythtv/mythplayer.cpp        |   52 +++++++++++++++++----------
8 mythtv/libs/libmythtv/mythplayer.h          |   14 ++++++-
9 mythtv/programs/mythtranscode/transcode.cpp |    1 +
10 3 files changed, 44 insertions(+), 23 deletions(-)
11
12diff --git a/mythtv/libs/libmythtv/mythplayer.cpp b/mythtv/libs/libmythtv/mythplayer.cpp
13index d13d741..e2cdc9b 100644
14--- a/mythtv/libs/libmythtv/mythplayer.cpp
15+++ b/mythtv/libs/libmythtv/mythplayer.cpp
16@@ -174,7 +174,7 @@ MythPlayer::MythPlayer(bool muted)
17       bufferPaused(false),  videoPaused(false),
18       allpaused(false),     playing(false),
19 
20-      eof(false),
21+      eof(kEofStateNone),
22       m_double_framerate(false),    m_double_process(false),
23       m_can_double(false),          m_deint_possible(true),
24       livetv(false),
25@@ -1005,7 +1005,7 @@ int MythPlayer::OpenFile(uint retries, bool allow_libmpeg2)
26     noVideoTracks = !decoder->GetTrackCount(kTrackTypeVideo);
27 
28 
29-    eof = false;
30+    eof = kEofStateNone;
31 
32     // Set 'no_video_decode' to true for audio only decodeing
33     bool no_video_decode = false;
34@@ -1972,6 +1972,7 @@ bool MythPlayer::PrebufferEnoughFrames(bool pause_audio, int min_buffers)
35 
36     bool was_buffering = buffering;
37     if (!(min_buffers ? (videoOutput->ValidVideoFrames() >= min_buffers) :
38+                        (eof != kEofStateNone) ||
39                         (videoOutput->hasHWAcceleration() ?
40                             videoOutput->EnoughPrebufferedFrames() :
41                             videoOutput->EnoughDecodedFrames())))
42@@ -2287,7 +2288,7 @@ void MythPlayer::SwitchToProgram(void)
43     {
44         OpenDummy();
45         ResetPlaying();
46-        eof = false;
47+        eof = kEofStateNone;
48         delete pginfo;
49         return;
50     }
51@@ -2301,13 +2302,13 @@ void MythPlayer::SwitchToProgram(void)
52                 QString("(card type: %1).")
53                 .arg(player_ctx->tvchain->GetCardType(newid)));
54         VERBOSE(VB_IMPORTANT, QString("\n") + player_ctx->tvchain->toString());
55-        eof = true;
56+        eof = kEofStateImmediate;
57         SetErrored(QObject::tr("Error opening switch program buffer"));
58         delete pginfo;
59         return;
60     }
61 
62-    if (eof)
63+    if (eof != kEofStateNone)
64     {
65         discontinuity = true;
66         ResetCaptions();
67@@ -2345,7 +2346,7 @@ void MythPlayer::SwitchToProgram(void)
68     if (IsErrored())
69     {
70         VERBOSE(VB_IMPORTANT, LOC_ERR + "SwitchToProgram failed.");
71-        eof = true;
72+        eof = kEofStateDelayed;
73         return;
74     }
75 
76@@ -2360,7 +2361,7 @@ void MythPlayer::SwitchToProgram(void)
77         forcePositionMapSync = true;
78     }
79 
80-    eof = false;
81+    eof = kEofStateNone;
82     Play();
83     VERBOSE(VB_PLAYBACK, LOC + "SwitchToProgram - end");
84 }
85@@ -2377,7 +2378,7 @@ void MythPlayer::FileChangedCallback(void)
86         player_ctx->buffer->Reset(false, true, true);
87     Play();
88 
89-    eof = false;
90+    eof = kEofStateNone;
91 
92     player_ctx->SetPlayerChangingBuffers(false);
93 
94@@ -2415,7 +2416,7 @@ void MythPlayer::JumpToProgram(void)
95     {
96         OpenDummy();
97         ResetPlaying();
98-        eof = false;
99+        eof = kEofStateNone;
100         delete pginfo;
101         return;
102     }
103@@ -2432,7 +2433,7 @@ void MythPlayer::JumpToProgram(void)
104                 .arg(player_ctx->tvchain->GetCardType(newid)));
105         VERBOSE(VB_IMPORTANT, QString("\n") + player_ctx->tvchain->toString());
106 
107-        eof = true;
108+        eof = kEofStateImmediate;
109         SetErrored(QObject::tr("Error opening jump program file buffer"));
110         delete pginfo;
111         return;
112@@ -2476,7 +2477,7 @@ void MythPlayer::JumpToProgram(void)
113     if (nextpos > 10)
114         DoFastForward(nextpos, true, false);
115 
116-    eof = false;
117+    eof = kEofStateNone;
118     player_ctx->SetPlayerChangingBuffers(false);
119     VERBOSE(VB_PLAYBACK, LOC + "JumpToProgram - end");
120 }
121@@ -2608,7 +2609,7 @@ void MythPlayer::EventLoop(void)
122         player_ctx->tvchain->JumpToNext(true, 1);
123         JumpToProgram();
124     }
125-    else if ((!allpaused || eof) && player_ctx->tvchain &&
126+    else if ((!allpaused || (eof != kEofStateNone)) && player_ctx->tvchain &&
127              (decoder && !decoder->GetWaitForChange()))
128     {
129         // Switch to the next program in livetv
130@@ -2659,7 +2660,7 @@ void MythPlayer::EventLoop(void)
131     }
132 
133     // Handle end of file
134-    if (eof)
135+    if (eof != kEofStateNone)
136     {
137         if (player_ctx->tvchain)
138         {
139@@ -2672,8 +2673,17 @@ void MythPlayer::EventLoop(void)
140         }
141         else if (!allpaused)
142         {
143-            SetPlaying(false);
144-            return;
145+            if (eof == kEofStateImmediate)
146+            {
147+                SetPlaying(false);
148+                return;
149+            }
150+            VERBOSE(VB_PLAYBACK, "waiting for no video frames " << videoOutput->ValidVideoFrames());
151+            if (videoOutput && videoOutput->ValidVideoFrames() < 3)
152+            {
153+                SetPlaying(false);
154+                return;
155+            }
156         }
157     }
158 
159@@ -2692,7 +2702,7 @@ void MythPlayer::EventLoop(void)
160         if (fftime > 0)
161         {
162             DoFastForward(fftime);
163-            if (eof)
164+            if (eof != kEofStateNone)
165                return;
166         }
167     }
168@@ -2754,7 +2764,7 @@ void MythPlayer::EventLoop(void)
169                   && !player_ctx->IsPIP() &&
170                   player_ctx->GetState() == kState_WatchingPreRecorded))
171             {
172-                eof = true;
173+                eof = kEofStateDelayed;
174             }
175         }
176         else
177@@ -2886,7 +2896,9 @@ void MythPlayer::DecoderLoop(bool pause)
178             decoderSeekLock.unlock();
179         }
180 
181-        bool obey_eof = eof && !(eof && player_ctx->tvchain && !allpaused);
182+        // eofstate
183+        // playtoend MRS
184+        bool obey_eof = (eof != kEofStateNone) && !((eof != kEofStateNone) && player_ctx->tvchain && !allpaused);
185         if (isDummy || ((decoderPaused || ffrew_skip == 0 || obey_eof) &&
186             !decodeOneFrame))
187         {
188@@ -4201,7 +4213,7 @@ bool MythPlayer::TranscodeGetNextFrame(
189     if (!decoder->GetFrame(kDecodeAV))
190         return false;
191 
192-    if (eof)
193+    if (eof != kEofStateNone)
194         return false;
195 
196     if (honorCutList && !deleteMap.IsEmpty())
197@@ -4226,7 +4238,7 @@ bool MythPlayer::TranscodeGetNextFrame(
198             did_ff = 1;
199         }
200     }
201-    if (eof)
202+    if (eof != kEofStateNone)
203       return false;
204     is_key = decoder->isLastFrameKey();
205     return true;
206diff --git a/mythtv/libs/libmythtv/mythplayer.h b/mythtv/libs/libmythtv/mythplayer.h
207index 4cb7b56..c808569 100644
208--- a/mythtv/libs/libmythtv/mythplayer.h
209+++ b/mythtv/libs/libmythtv/mythplayer.h
210@@ -110,6 +110,14 @@ class DecoderThread : public QThread
211     bool        m_start_paused;
212 };
213 
214+// Eof States
215+typedef enum
216+{
217+    kEofStateNone,
218+    kEofStateDelayed,
219+    kEofStateImmediate
220+} EofState;
221+
222 class MPUBLIC MythPlayer
223 {
224     // Do NOT add a decoder class to this list
225@@ -138,7 +146,7 @@ class MPUBLIC MythPlayer
226     void SetLength(int len)                   { totalLength = len; }
227     void SetFramesPlayed(uint64_t played)     { framesPlayed = played; }
228     void SetVideoFilters(const QString &override);
229-    void SetEof(void)                         { eof = true; }
230+    void SetEof(void)                         { eof = kEofStateDelayed; }
231     void SetPIPActive(bool is_active)         { pip_active = is_active; }
232     void SetPIPVisible(bool is_visible)       { pip_visible = is_visible; }
233 
234@@ -188,7 +196,7 @@ class MPUBLIC MythPlayer
235     // Bool Gets
236     bool    GetRawAudioState(void) const;
237     bool    GetLimitKeyRepeat(void) const     { return limitKeyRepeat; }
238-    bool    GetEof(void) const                { return eof; }
239+    bool    GetEof(void) const                { return eof != kEofStateNone; }
240     bool    IsErrored(void) const;
241     bool    IsPlaying(uint wait_ms = 0, bool wait_for = true) const;
242     bool    AtNormalSpeed(void) const         { return next_normal_speed; }
243@@ -560,7 +568,7 @@ class MPUBLIC MythPlayer
244     mutable QWaitCondition playingWaitCond;
245     mutable QMutex vidExitLock;
246     mutable QMutex playingLock;
247-    bool     eof;             ///< At end of file/ringbuffer
248+    EofState eof;             ///< At end of file/ringbuffer
249     bool     m_double_framerate;///< Output fps is double Video (input) rate
250     bool     m_double_process;///< Output filter must processed at double rate
251     bool     m_can_double;    ///< VideoOutput capable of doubling frame rate
252diff --git a/mythtv/programs/mythtranscode/transcode.cpp b/mythtv/programs/mythtranscode/transcode.cpp
253index 35f54e6..2bdd56f 100644
254--- a/mythtv/programs/mythtranscode/transcode.cpp
255+++ b/mythtv/programs/mythtranscode/transcode.cpp
256@@ -75,6 +75,7 @@ class AudioReencodeBuffer : public AudioOutput
257     }
258 
259     virtual void SetBlocking(bool block) { (void)block; }
260+    virtual void SetTimedBlocking(bool block) { (void)block; }
261     virtual void Reset(void)
262     {
263         audiobuffer_len = 0;