MythTV master
mythbdplayer.cpp
Go to the documentation of this file.
1// MythTV
2#include "tv_play.h"
6
10
11// Std
12#include <unistd.h>
13
14#define LOC QString("BDPlayer: ")
15
17 : MythPlayerUI(MainWindow, Tv, Context, Flags)
18{
19 connect(Tv, &TV::GoToMenu, this, &MythBDPlayer::GoToMenu);
20}
21
23{
24 EofState eof = GetEof();
25 // DeleteMap and EditMode from the parent MythPlayer should not be
26 // relevant here.
27 return eof != kEofStateNone && !m_allPaused;
28}
29
31{
33}
34
35void MythBDPlayer::GoToMenu(const QString& Menu)
36{
38 return;
39
40 mpeg::chrono::pts pts = 0_pts;
41 const auto * frame = m_videoOutput->GetLastShownFrame();
42 if (frame)
43 pts = duration_cast<mpeg::chrono::pts>(frame->m_timecode);
45}
46
48{
49 if (!m_playerCtx->m_buffer->IsBD())
50 return;
51
52 MythBDOverlay *overlay = nullptr;
53 while (nullptr != (overlay = m_playerCtx->m_buffer->BD()->GetOverlay()))
55}
56
58{
63}
64
66{
67 if (!m_initialBDState.isEmpty())
69
71}
72
74{
75 if (!m_playerCtx->m_buffer->IsBD())
76 {
77 SetErrored("RingBuffer is not a Blu-Ray disc.");
78 return !IsErrored();
79 }
80
81 int nbframes = m_videoOutput ? m_videoOutput->ValidVideoFrames() : 0;
82
83 // completely drain the video buffers for certain situations
84 if (m_playerCtx->m_buffer->BD()->BDWaitingForPlayer() && (nbframes > 0))
85 {
86 if (nbframes < 2 && m_videoOutput)
88
89 // if we go below the pre-buffering limit, the player will pause
90 // so do this 'manually'
91 DisplayNormalFrame(false);
92 return !IsErrored();
93 }
94
95 // clear the mythtv imposed wait state
97 {
98 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Clearing Mythtv BD wait state");
100 return !IsErrored();
101 }
102
104 {
105 if (nbframes > 1 && !m_stillFrameShowing)
106 {
108 DisplayNormalFrame(false);
109 return !IsErrored();
110 }
111
113 m_needNewPauseFrame = true;
114
115 // we are in a still frame so pause video output
116 if (!m_videoPaused)
117 {
118 PauseVideo();
119 return !IsErrored();
120 }
121
122 // flag if we have no frame
123 if (nbframes == 0)
124 {
125 LOG(VB_PLAYBACK, LOG_WARNING, LOC + "Warning: In BD Still but no video frames in queue");
126 std::this_thread::sleep_for(10ms);
127 return !IsErrored();
128 }
129
131 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Entering still frame.");
132 m_stillFrameShowing = true;
133 }
134 else
135 {
137 {
138 UnpauseVideo();
139 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Exiting still frame.");
140 }
141 m_stillFrameShowing = false;
142 }
143
145}
146
148{
149 if (Frame == ~0x0ULL)
150 return false;
152}
153
155{
156 m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
158 {
159 QString name;
160 QString serialid;
161 if (m_playerCtx->m_playingInfo->GetTitle().isEmpty() &&
162 m_playerCtx->m_buffer->BD()->GetNameAndSerialNum(name, serialid))
163 {
165 }
166 }
167 m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
168
170}
171
173{
175 return static_cast<int>(m_playerCtx->m_buffer->BD()->GetNumChapters());
176 return -1;
177}
178
180{
182 return static_cast<int>(m_playerCtx->m_buffer->BD()->GetCurrentChapter() + 1);
183 return -1;
184}
185
186int64_t MythBDPlayer::GetChapter(int Chapter)
187{
188 if (GetNumChapters() < 1)
189 return -1;
190 auto chapter = static_cast<uint32_t>(Chapter - 1);
191 return static_cast<int64_t>(m_playerCtx->m_buffer->BD()->GetChapterStartFrame(chapter));
192}
193
194void MythBDPlayer::GetChapterTimes(QList<std::chrono::seconds> &ChapterTimes)
195{
196 uint total = static_cast<uint>(GetNumChapters());
197 for (uint i = 0; i < total; i++)
198 ChapterTimes.push_back(m_playerCtx->m_buffer->BD()->GetChapterStartTime(i));
199}
200
202{
204 return 0;
205
207 return static_cast<int>(m_playerCtx->m_buffer->BD()->GetNumTitles());
208 return 0;
209}
210
212{
214 return static_cast<int>(m_playerCtx->m_buffer->BD()->GetNumAngles());
215 return 0;
216}
217
219{
222 return -1;
223}
224
226{
228 return static_cast<int>(m_playerCtx->m_buffer->BD()->GetCurrentAngle());
229 return -1;
230}
231
232std::chrono::seconds MythBDPlayer::GetTitleDuration(int Title) const
233{
234 if (m_playerCtx->m_buffer->BD() && m_playerCtx->m_buffer->BD()->IsOpen() &&
235 Title >= 0 && Title < GetNumTitles())
236 {
237 return m_playerCtx->m_buffer->BD()->GetTitleDuration(Title);
238 }
239 return 0s;
240}
241
242QString MythBDPlayer::GetTitleName(int Title) const
243{
244 if (Title >= 0 && Title < GetNumTitles())
245 {
246 // BD doesn't provide title names, so show title number and duration
247 QString timestr = MythDate::formatTime(GetTitleDuration(Title), "HH:mm:ss");
248 QString name = QString("%1 (%2)").arg(Title+1).arg(timestr);
249 return name;
250 }
251 return {};
252}
253
254QString MythBDPlayer::GetAngleName(int Angle) const
255{
256 if (Angle >= 1 && Angle <= GetNumAngles())
257 return tr("Angle %1").arg(Angle);
258 return {};
259}
260
262{
264 return false;
265
266 int total = GetNumTitles();
267 if ((total < 1) || Title == GetCurrentTitle() || (Title >= total))
268 return false;
269
270 Pause();
271
272 bool ok = false;
273 if (m_playerCtx->m_buffer->BD()->SwitchTitle(static_cast<uint32_t>(Title)))
274 {
276 if (OpenFile() != 0)
277 {
278 SetErrored(tr("Failed to switch title."));
279 }
280 else
281 {
282 ok = true;
284 }
285 }
286
287 Play();
288 return ok;
289}
290
292{
294 return false;
295
296 int total = GetNumTitles();
297 int next = GetCurrentTitle() + 1;
298 if ((total < 1) || (next >= total))
299 return false;
300
301 return SwitchTitle(next);
302}
303
305{
307 return false;
308
309 uint total = static_cast<uint>(GetNumTitles());
310 int prev = GetCurrentTitle() - 1;
311 if (!total || prev < 0)
312 return false;
313
314 return SwitchTitle(prev);
315}
316
318{
319 int total = GetNumAngles();
320 if (!total || Angle == GetCurrentAngle())
321 return false;
322
323 if (Angle >= total)
324 Angle = 0;
325
326 return m_playerCtx->m_buffer->BD()->SwitchAngle(static_cast<uint>(Angle));
327}
328
330{
331 int total = GetNumAngles();
332 int next = GetCurrentAngle() + 1;
333 if (total < 1)
334 return false;
335 if (next >= total)
336 next = 0;
337 return SwitchAngle(next);
338}
339
341{
342 int total = GetNumAngles();
343 int prev = GetCurrentAngle() - 1;
344 if ((total < 1) || total == 1)
345 return false;
346 if (prev < 0)
347 prev = total;
348 return SwitchAngle(prev);
349}
350
352{
354 {
355 QString name;
356 QString serialid;
357 if (!m_playerCtx->m_buffer->BD()->GetNameAndSerialNum(name, serialid))
358 {
359 LOG(VB_GENERAL, LOG_ERR, LOC + "BD has no name and serial number. Cannot set bookmark.");
360 return;
361 }
362
363 QString bdstate;
364 if (!Clear && !m_playerCtx->m_buffer->BD()->GetBDStateSnapshot(bdstate))
365 {
366 LOG(VB_GENERAL, LOG_ERR, LOC + "Unable to retrieve BD state. Cannot set bookmark.");
367 return;
368 }
369
370 LOG(VB_GENERAL, LOG_INFO, LOC + QString("BDState:%1").arg(bdstate));
371
372 m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
374 {
375 QStringList fields;
376 fields += serialid;
377 fields += name;
378
379 if (!Clear)
380 {
381 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Set bookmark");
382 fields += bdstate;
383 }
384 else
385 {
386 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Clear bookmark");
387 }
388
390 }
391 m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
392 }
393}
394
396{
397 uint64_t frames = 0;
399 return frames;
400
401 m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
402
404 {
405 QString name;
406 QString serialid;
407 if (!m_playerCtx->m_buffer->BD()->GetNameAndSerialNum(name, serialid))
408 {
409 m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
410 return frames;
411 }
412
413 QStringList bdbookmark = m_playerCtx->m_playingInfo->QueryBDBookmark(serialid);
414
415 if (!bdbookmark.empty())
416 {
417 m_initialBDState = bdbookmark[0];
418 frames = ~0x0ULL;
419 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Get Bookmark: bookmark found");
420 }
421 }
422
423 m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
424 return frames;
425}
426
428{
431}
#define Clear(a)
static bool CanHandle(TestBufferVec &testbuf, const QString &filename)
Perform an av_probe_input_format on the passed data to see if we can decode it with this class.
bool GetNameAndSerialNum(QString &Name, QString &SerialNum) override
bool RestoreBDStateSnapshot(const QString &State)
Restore a BD snapshot.
void SkipBDWaitingForPlayer(void)
bool IsOpen(void) const override
int GetCurrentTitle(void)
MythBDOverlay * GetOverlay(void)
uint32_t GetNumTitles(void) const
uint32_t GetCurrentChapter(void)
uint64_t GetCurrentAngle(void) const
std::chrono::seconds GetTitleDuration(int Title)
bool SwitchAngle(uint Angle)
uint64_t GetNumAngles(void) const
bool GetBDStateSnapshot(QString &State)
Get a snapshot of the current BD state.
bool SwitchTitle(uint32_t Index)
bool IsHDMVNavigation(void) const
uint32_t GetNumChapters(void)
bool BDWaitingForPlayer(void) const
bool GoToMenu(const QString &Menu, mpeg::chrono::pts Pts)
jump to a Blu-ray root or popup menu
uint64_t GetChapterStartFrame(uint32_t Chapter)
std::chrono::seconds GetChapterStartTime(uint32_t Chapter)
bool IsInStillFrame(void) const override
int GetCurrentTitle(void) const override
void DisplayPauseFrame(void) override
void CreateDecoder(TestBufferVec &TestBuffer) override
int GetNumTitles(void) const override
void GetChapterTimes(QList< std::chrono::seconds > &ChapterTimes) override
void DisplayMenu(void)
void SetBookmark(bool Clear) override
bool HasReachedEof(void) const override
bool NextTitle(void) override
bool JumpToFrame(uint64_t Frame) override
bool PrevTitle(void) override
uint64_t GetBookmark(void) override
void GoToMenu(const QString &Menu)
QString m_initialBDState
Definition: mythbdplayer.h:54
QString GetTitleName(int Title) const override
bool SwitchTitle(int Title) override
int64_t GetChapter(int Chapter) override
void EventStart(void) override
QString GetAngleName(int Angle) const override
std::chrono::seconds GetTitleDuration(int Title) const override
int GetNumChapters(void) override
bool VideoLoop(void) override
bool NextAngle(void) override
void PreProcessNormalFrame(void) override
void VideoStart(void) override
int GetCurrentChapter(void) override
bool PrevAngle(void) override
MythBDPlayer(MythMainWindow *MainWindow, TV *Tv, PlayerContext *Context, PlayerFlags Flags=kNoFlags)
int GetNumAngles(void) const override
int GetCurrentAngle(void) const override
bool m_stillFrameShowing
Definition: mythbdplayer.h:53
bool SwitchAngle(int Angle) override
void DisplayBDOverlay(MythBDOverlay *Overlay)
bool IsDatabaseIgnored(void) const
/brief Returns true if database is being ignored.
virtual bool IsInMenu(void) const
virtual bool IsBookmarkAllowed(void)
const MythBDBuffer * BD(void) const
bool IsBD(void) const
QString GetFilename(void) const
std::chrono::milliseconds & DisplayTimecode()
MythCaptionsOverlay m_captionsOverlay
virtual void VideoStart()
virtual bool VideoLoop()
virtual void DisplayPauseFrame()
virtual void EventStart()
virtual bool DisplayNormalFrame(bool CheckPrebuffer=true)
bool m_needNewPauseFrame
Definition: mythplayer.h:391
std::chrono::microseconds m_frameInterval
always adjusted for play_speed
Definition: mythplayer.h:486
void UnpauseVideo(void)
Definition: mythplayer.cpp:224
bool m_allPaused
Definition: mythplayer.h:394
void SetDecoder(DecoderBase *dec)
Sets the stream decoder, deleting any existing recorder.
virtual bool JumpToFrame(uint64_t frame)
Definition: mythplayer.cpp:892
virtual int OpenFile(int Retries=4)
Definition: mythplayer.cpp:417
bool m_forcePositionMapSync
Definition: mythplayer.h:476
void SetErrored(const QString &reason)
bool m_videoPaused
Definition: mythplayer.h:393
PlayerFlags m_playerFlags
Definition: mythplayer.h:372
bool IsErrored(void) const
MythPlayerAVSync m_avSync
Definition: mythplayer.h:430
bool Pause(void)
Definition: mythplayer.cpp:153
void PauseVideo(void)
Definition: mythplayer.cpp:216
bool Play(float speed=1.0, bool normal=true, bool unpauseaudio=true)
Definition: mythplayer.cpp:186
PlayerContext * m_playerCtx
Definition: mythplayer.h:366
MythVideoOutput * m_videoOutput
Definition: mythplayer.h:364
EofState GetEof(void) const
virtual void UpdatePauseFrame(std::chrono::milliseconds &, FrameScanType=kScan_Progressive)
Definition: mythvideoout.h:87
virtual int ValidVideoFrames() const
Returns number of frames that are fully decoded.
virtual MythVideoFrame * GetLastShownFrame()
Returns frame from the head of the ready to be displayed queue, if StartDisplayingFrame has been call...
void SetScanType(FrameScanType Scan, MythVideoOutput *VideoOutput, std::chrono::microseconds FrameInterval)
void LockPlayingInfo(const char *file, int line) const
MythMediaBuffer * m_buffer
void UnlockPlayingInfo(const char *file, int line) const
ProgramInfo * m_playingInfo
Currently playing info.
void SetTitle(const QString &t, const QString &st=nullptr)
QStringList QueryBDBookmark(const QString &serialid) const
Queries "bdbookmark" table for bookmarking BD serial number.
QString GetTitle(void) const
Definition: programinfo.h:362
static void SaveBDBookmark(const QStringList &fields)
void GoToMenu(const QString &Menu)
Control TV playback.
Definition: tv_play.h:156
EofState
Definition: decoderbase.h:68
@ kEofStateNone
Definition: decoderbase.h:69
std::vector< char > TestBufferVec
Definition: decoderbase.h:23
unsigned int uint
Definition: freesurround.h:24
#define LOC
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
PlayerFlags
Definition: mythplayer.h:65
QString formatTime(std::chrono::milliseconds msecs, QString fmt)
Format a milliseconds time value.
Definition: mythdate.cpp:242
std::chrono::duration< CHRONO_TYPE, std::ratio< 1, 90000 > > pts
Definition: mythchrono.h:55
@ kScan_Progressive