MythTV  master
mythbdplayer.cpp
Go to the documentation of this file.
1 #include "bdringbuffer.h"
2 #include "avformatdecoderbd.h"
3 #include "mythbdplayer.h"
4 
5 #include <unistd.h> // for usleep()
6 
7 #define LOC QString("BDPlayer: ")
8 
10 {
11  EofState eof = GetEof();
12  // DeleteMap and EditMode from the parent MythPlayer should not be
13  // relevant here.
14  return eof != kEofStateNone && !m_allPaused;
15 }
16 
18 {
19  DisplayMenu();
20 }
21 
22 bool MythBDPlayer::GoToMenu(QString str)
23 {
25  {
26  int64_t pts = 0;
28  if (frame)
29  pts = (int64_t)(frame->timecode * 90);
30  return m_playerCtx->m_buffer->BD()->GoToMenu(str, pts);
31  }
32  return false;
33 }
34 
36 {
37  if (!m_playerCtx->m_buffer->IsBD())
38  return;
39 
40  m_osdLock.lock();
41  BDOverlay *overlay = nullptr;
42  while (m_osd && (nullptr != (overlay = m_playerCtx->m_buffer->BD()->GetOverlay())))
43  m_osd->DisplayBDOverlay(overlay);
44  m_osdLock.unlock();
45 }
46 
48 {
49  if (m_playerCtx->m_buffer->IsBD() &&
51  {
53  }
54  DisplayMenu();
56 }
57 
59 {
60  if (!m_initialBDState.isEmpty())
62 
64 }
65 
67 {
68  if (!m_playerCtx->m_buffer->IsBD())
69  {
70  SetErrored("RingBuffer is not a Blu-Ray disc.");
71  return !IsErrored();
72  }
73 
74  int nbframes = m_videoOutput ? m_videoOutput->ValidVideoFrames() : 0;
75 
76  // completely drain the video buffers for certain situations
77  bool drain = m_playerCtx->m_buffer->BD()->BDWaitingForPlayer() &&
78  (nbframes > 0);
79 
80  if (drain)
81  {
82  if (nbframes < 2 && m_videoOutput)
84 
85  // if we go below the pre-buffering limit, the player will pause
86  // so do this 'manually'
87  DisplayNormalFrame(false);
88  return !IsErrored();
89  }
90 
91  // clear the mythtv imposed wait state
93  {
94  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Clearing Mythtv BD wait state");
96  return !IsErrored();
97  }
98 
100  {
101  if (nbframes > 1 && !m_stillFrameShowing)
102  {
104  DisplayNormalFrame(false);
105  return !IsErrored();
106  }
107 
108  if (!m_stillFrameShowing)
109  m_needNewPauseFrame = true;
110 
111  // we are in a still frame so pause video output
112  if (!m_videoPaused)
113  {
114  PauseVideo();
115  return !IsErrored();
116  }
117 
118  // flag if we have no frame
119  if (nbframes == 0)
120  {
121  LOG(VB_PLAYBACK, LOG_WARNING, LOC +
122  "Warning: In BD Still but no video frames in queue");
123  usleep(10000);
124  return !IsErrored();
125  }
126 
127  if (!m_stillFrameShowing)
128  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Entering still frame.");
129  m_stillFrameShowing = true;
130  }
131  else
132  {
134  {
135  UnpauseVideo();
136  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Exiting still frame.");
137  }
138  m_stillFrameShowing = false;
139  }
140 
141  return MythPlayer::VideoLoop();
142 }
143 
144 bool MythBDPlayer::JumpToFrame(uint64_t frame)
145 {
146  if (frame == ~0x0ULL)
147  return false;
148 
149  return MythPlayer::JumpToFrame(frame);
150 }
151 
153 {
154  m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
156  {
157  QString name;
158  QString serialid;
159  if (m_playerCtx->m_playingInfo->GetTitle().isEmpty() &&
160  m_playerCtx->m_buffer->BD()->GetNameAndSerialNum(name, serialid))
161  {
163  }
164  }
165  m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
166 
168 }
169 
171 {
172  if (m_playerCtx->m_buffer->BD() && m_playerCtx->m_buffer->BD()->IsOpen())
173  return m_playerCtx->m_buffer->BD()->GetNumChapters();
174  return -1;
175 }
176 
178 {
179  if (m_playerCtx->m_buffer->BD() && m_playerCtx->m_buffer->BD()->IsOpen())
180  return m_playerCtx->m_buffer->BD()->GetCurrentChapter() + 1;
181  return -1;
182 }
183 
184 int64_t MythBDPlayer::GetChapter(int chapter)
185 {
186  uint total = GetNumChapters();
187  if (!total)
188  return -1;
189 
190  return (int64_t)m_playerCtx->m_buffer->BD()->GetChapterStartFrame(chapter-1);
191 }
192 
193 void MythBDPlayer::GetChapterTimes(QList<long long> &times)
194 {
195  uint total = GetNumChapters();
196  if (!total)
197  return;
198 
199  for (uint i = 0; i < total; i++)
200  times.push_back(m_playerCtx->m_buffer->BD()->GetChapterStartTime(i));
201 }
202 
204 {
206  return 0;
207 
208  if (m_playerCtx->m_buffer->BD() && m_playerCtx->m_buffer->BD()->IsOpen())
209  return m_playerCtx->m_buffer->BD()->GetNumTitles();
210  return 0;
211 }
212 
214 {
215  if (m_playerCtx->m_buffer->BD() && m_playerCtx->m_buffer->BD()->IsOpen())
216  return m_playerCtx->m_buffer->BD()->GetNumAngles();
217  return 0;
218 }
219 
221 {
222  if (m_playerCtx->m_buffer->BD() && m_playerCtx->m_buffer->BD()->IsOpen())
223  return m_playerCtx->m_buffer->BD()->GetCurrentTitle();
224  return -1;
225 }
226 
228 {
229  if (m_playerCtx->m_buffer->BD() && m_playerCtx->m_buffer->BD()->IsOpen())
230  return m_playerCtx->m_buffer->BD()->GetCurrentAngle();
231  return -1;
232 }
233 
234 int MythBDPlayer::GetTitleDuration(int title) const
235 {
236  if (m_playerCtx->m_buffer->BD() && m_playerCtx->m_buffer->BD()->IsOpen() &&
237  title >= 0 && title < GetNumTitles())
238  {
239  return m_playerCtx->m_buffer->BD()->GetTitleDuration(title);
240  }
241  return 0;
242 }
243 
244 QString MythBDPlayer::GetTitleName(int title) const
245 {
246  if (title >= 0 && title < GetNumTitles())
247  {
248  int secs = GetTitleDuration(title);
249  // BD doesn't provide title names, so show title number and duration
250  int hours = secs / 60 / 60;
251  int minutes = (secs / 60) - (hours * 60);
252  secs = secs % 60;
253  QString name = QString("%1 (%2:%3:%4)").arg(title+1)
254  .arg(hours, 2, 10, QChar(48)).arg(minutes, 2, 10, QChar(48))
255  .arg(secs, 2, 10, QChar(48));
256  return name;
257  }
258  return QString();
259 }
260 
261 QString MythBDPlayer::GetAngleName(int angle) const
262 {
263  if (angle >= 1 && angle <= GetNumAngles())
264  {
265  QString name = tr("Angle %1").arg(angle);
266  return name;
267  }
268  return QString();
269 }
270 
272 {
274  return false;
275 
276  uint total = GetNumTitles();
277  if (!total || title == GetCurrentTitle() || title >= (int)total)
278  return false;
279 
280  Pause();
281 
282  bool ok = false;
283  if (m_playerCtx->m_buffer->BD()->SwitchTitle(title))
284  {
285  ResetCaptions();
286  if (OpenFile() != 0)
287  {
288  SetErrored(tr("Failed to switch title."));
289  }
290  else
291  {
292  ok = true;
293  m_forcePositionMapSync = true;
294  }
295  }
296 
297  Play();
298  return ok;
299 }
300 
302 {
304  return false;
305 
306  uint total = GetNumTitles();
307  int next = GetCurrentTitle() + 1;
308  if (!total || next >= (int)total)
309  return false;
310 
311  return SwitchTitle(next);
312 }
313 
315 {
317  return false;
318 
319  uint total = GetNumTitles();
320  int prev = GetCurrentTitle() - 1;
321  if (!total || prev < 0)
322  return false;
323 
324  return SwitchTitle(prev);
325 }
326 
328 {
329  uint total = GetNumAngles();
330  if (!total || angle == GetCurrentAngle())
331  return false;
332 
333  if (angle >= (int)total)
334  angle = 0;
335 
336  return m_playerCtx->m_buffer->BD()->SwitchAngle(angle);
337 }
338 
340 {
341  uint total = GetNumAngles();
342  int next = GetCurrentAngle() + 1;
343  if (!total)
344  return false;
345 
346  if (next >= (int)total)
347  next = 0;
348 
349  return SwitchAngle(next);
350 }
351 
353 {
354  uint total = GetNumAngles();
355  int prev = GetCurrentAngle() - 1;
356  if (!total || total == 1)
357  return false;
358 
359  if (prev < 0)
360  prev = total;
361 
362  return SwitchAngle(prev);
363 }
364 
366 {
367  QStringList fields;
368  QString name;
369  QString serialid;
370  QString bdstate;
371 
372  if (!m_playerCtx->m_buffer->IsInMenu() &&
374  {
375  if (!m_playerCtx->m_buffer->BD()->GetNameAndSerialNum(name, serialid))
376  {
377  LOG(VB_GENERAL, LOG_ERR, LOC +
378  "BD has no name and serial number. Cannot set bookmark.");
379  return;
380  }
381 
382  if (!clear && !m_playerCtx->m_buffer->BD()->GetBDStateSnapshot(bdstate))
383  {
384  LOG(VB_GENERAL, LOG_ERR, LOC +
385  "Unable to retrieve BD state. Cannot set bookmark.");
386  return;
387  }
388 
389  LOG(VB_GENERAL, LOG_INFO, LOC + QString("BDState:%1").arg(bdstate));
390 
391  m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
393  {
394  fields += serialid;
395  fields += name;
396 
397  if (!clear)
398  {
399  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Set bookmark");
400  fields += bdstate;
401  }
402  else
403  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Clear bookmark");
404 
406 
407  }
408  m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
409  }
410 }
411 
413 {
415  return 0;
416 
417  QString name;
418  QString serialid;
419  uint64_t frames = 0;
420 
421  m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
422 
424  {
425  if (!m_playerCtx->m_buffer->BD()->GetNameAndSerialNum(name, serialid))
426  {
427  m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
428  return 0;
429  }
430 
431  QStringList bdbookmark = m_playerCtx->m_playingInfo->QueryBDBookmark(serialid);
432 
433  if (!bdbookmark.empty())
434  {
435  m_initialBDState = bdbookmark[0];
436  frames = ~0x0ULL;
437  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Get Bookmark: bookmark found");
438  }
439  }
440 
441  m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
442  return frames;;
443 }
444 
445 void MythBDPlayer::CreateDecoder(char *testbuf, int testreadsize)
446 {
448  testreadsize))
449  {
451  m_playerFlags));
452  }
453 }
void DisplayBDOverlay(BDOverlay *Overlay)
Definition: osd.cpp:1238
bool SwitchTitle(int title) override
bool NextTitle(void) override
int64_t m_dispTimecode
Definition: mythplayer.h:828
void SetErrored(const QString &reason)
#define LOC
Definition: mythbdplayer.cpp:7
long long timecode
Definition: mythframe.h:149
void SetScanType(FrameScanType)
Definition: mythplayer.cpp:583
int GetNumChapters(void) override
int GetNumTitles(void) const override
void ResetCaptions(void)
bool GetNameAndSerialNum(QString &_name, QString &_serialnum)
bool SwitchTitle(uint32_t index)
RingBuffer * m_buffer
virtual bool JumpToFrame(uint64_t frame)
int GetCurrentTitle(void) const override
void UnlockPlayingInfo(const char *file, int line) const
BDOverlay * GetOverlay(void)
void PreProcessNormalFrame(void) override
QString GetTitle(void) const
Definition: programinfo.h:353
QString GetFilename(void) const
Returns name of file used by this RingBuffer.
void PauseVideo(void)
Definition: mythplayer.cpp:313
virtual void VideoStart(void)
uint32_t GetNumChapters(void)
uint64_t GetChapterStartFrame(uint32_t chapter)
virtual int ValidVideoFrames(void) const
Returns number of frames that are fully decoded.
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
bool GetBDStateSnapshot(QString &state)
Get a snapshot of the current BD state.
void SkipBDWaitingForPlayer(void)
Definition: bdringbuffer.h:87
virtual bool VideoLoop(void)
bool IsDatabaseIgnored(void) const
/brief Returns true if database is being ignored.
uint64_t GetCurrentAngle(void) const
Definition: bdringbuffer.h:101
bool JumpToFrame(uint64_t frame) override
bool PrevAngle(void) override
uint64_t GetChapterStartTime(uint32_t chapter)
PlayerContext * m_playerCtx
Definition: mythplayer.h:638
virtual void UpdatePauseFrame(int64_t &DisplayTimecode)=0
int GetCurrentChapter(void) override
int GetCurrentTitle(void)
void SetBookmark(bool clear) override
bool IsHDMVNavigation(void) const
Definition: bdringbuffer.h:116
bool GoToMenu(const QString &str, int64_t pts)
jump to a Blu-ray root or popup menu
EofState
Definition: decoderbase.h:67
ProgramInfo * m_playingInfo
Currently playing info.
virtual int OpenFile(uint retries=4)
Definition: mythplayer.cpp:728
QString GetAngleName(int angle) const override
virtual bool IsInMenu(void) const
QStringList QueryBDBookmark(const QString &serialid) const
Queries "bdbookmark" table for bookmarking BD serial number.
virtual void EventStart(void)
static void clear(SettingsMap &cache, SettingsMap &overrides, const QString &myKey)
Definition: mythdb.cpp:836
QString m_initialBDState
Definition: mythbdplayer.h:73
uint32_t GetNumTitles(void) const
Definition: bdringbuffer.h:99
void LockPlayingInfo(const char *file, int line) const
EofState GetEof(void) const
bool SwitchAngle(uint angle)
static void SaveBDBookmark(const QStringList &fields)
bool m_forcePositionMapSync
Definition: mythplayer.h:800
int64_t GetChapter(int chapter) override
unsigned int uint
Definition: compat.h:140
bool BDWaitingForPlayer(void)
Definition: bdringbuffer.h:86
bool GoToMenu(QString str) override
virtual bool IsBookmarkAllowed(void)
bool IsBD(void) const
bool IsErrored(void) const
uint64_t GetBookmark(void) override
bool m_allPaused
Definition: mythplayer.h:671
virtual void DisplayNormalFrame(bool check_prebuffer=true)
void EventStart(void) override
void CreateDecoder(char *testbuf, int testreadsize) override
bool Play(float speed=1.0, bool normal=true, bool unpauseaudio=true)
Definition: mythplayer.cpp:283
void UnpauseVideo(void)
Definition: mythplayer.cpp:321
static bool CanHandle(char testbuf[kDecoderProbeBufferSize], const QString &filename, int testbufsize=kDecoderProbeBufferSize)
Perform an av_probe_input_format on the passed data to see if we can decode it with this class.
bool PrevTitle(void) override
void SetTitle(const QString &t, const QString &st=nullptr)
void VideoStart(void) override
PictureAttribute next(PictureAttributeSupported supported, PictureAttribute attribute)
bool VideoLoop(void) override
uint64_t GetNumAngles(void)
Definition: bdringbuffer.h:112
bool RestoreBDStateSnapshot(const QString &state)
Restore a BD snapshot.
bool m_needNewPauseFrame
Definition: mythplayer.h:665
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
void SetDecoder(DecoderBase *dec)
Sets the stream decoder, deleting any existing recorder.
bool m_videoPaused
Definition: mythplayer.h:670
int GetNumAngles(void) const override
void DisplayPauseFrame(void) override
void DisplayMenu(void)
QString GetTitleName(int title) const override
int GetTitleDuration(int title) const override
const char * frames[3]
Definition: element.c:46
MythVideoOutput * m_videoOutput
Definition: mythplayer.h:637
int GetCurrentAngle(void) const override
int GetTitleDuration(int title)
bool SwitchAngle(int angle) override
virtual VideoFrame * GetLastShownFrame(void)
Returns frame from the head of the ready to be displayed queue, if StartDisplayingFrame has been call...
OSD * m_osd
Definition: mythplayer.h:784
bool m_stillFrameShowing
Definition: mythbdplayer.h:72
const BDRingBuffer * BD(void) const
bool Pause(void)
Definition: mythplayer.cpp:251
bool IsOpen(void) const override
Returns true if open for either reading or writing.
Definition: bdringbuffer.h:115
PlayerFlags m_playerFlags
Definition: mythplayer.h:634
bool NextAngle(void) override
bool HasReachedEof(void) const override
Definition: mythbdplayer.cpp:9
virtual void DisplayPauseFrame(void)
bool IsInStillFrame(void) const override
void GetChapterTimes(QList< long long > &times) override
QMutex m_osdLock
Definition: mythplayer.h:786
uint32_t GetCurrentChapter(void)