MythTV  0.27pre
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Groups Pages
mythdvdplayer.cpp
Go to the documentation of this file.
1 #include "dvdringbuffer.h"
2 #include "DetectLetterbox.h"
3 #include "audiooutput.h"
4 #include "myth_imgconvert.h"
5 #include "avformatdecoderdvd.h"
6 #include "mythdvdplayer.h"
7 
8 #define LOC QString("DVDPlayer: ")
9 
11  : MythPlayer(flags), m_buttonVersion(0),
12  dvd_stillframe_showing(false),
13  m_initial_title(-1), m_initial_audio_track(-1),
14  m_initial_subtitle_track(-1),
15  m_stillFrameLength(0)
16 {
17 }
18 
19 void MythDVDPlayer::AutoDeint(VideoFrame *frame, bool allow_lock)
20 {
21  (void)frame;
22  (void)allow_lock;
24 }
25 
27  int64_t timecode, bool wrap)
28 {
29  MythPlayer::ReleaseNextVideoFrame(buffer, timecode,
31 }
32 
34 {
35  EofState eof = GetEof();
36  if (eof != kEofStateNone && !allpaused)
37  return true;
38  // DeleteMap and EditMode from the parent MythPlayer should not be
39  // relevant here.
40  return false;
41 }
42 
44 {
45  if ((kDisplayAVSubtitle & mode) && player_ctx->buffer->IsDVD())
47  MythPlayer::DisableCaptions(mode, osd_msg);
48 }
49 
51 {
52  if ((kDisplayAVSubtitle & mode) && player_ctx->buffer->IsDVD())
55  MythPlayer::EnableCaptions(mode, osd_msg);
56 }
57 
59 {
60  if (player_ctx->buffer->IsDVD() &&
62  {
64  }
67 }
68 
70 {
73 }
74 
76 {
78 }
79 
81 {
83  if (decoder_change_lock.tryLock(1))
84  {
85  if (decoder)
87  decoder_change_lock.unlock();
88  }
89  return res;
90 }
91 
93 {
95  return (player_ctx->buffer->IsDVD() &&
96  (player_ctx->buffer->DVD()->GetCurrentTime() < 2));
97 }
98 
100 {
102 }
103 
105 {
106  if (!player_ctx->buffer->IsDVD())
107  {
108  SetErrored("RingBuffer is not a DVD.");
109  return !IsErrored();
110  }
111 
112  int nbframes = 0;
113  if (videoOutput)
114  nbframes = videoOutput->ValidVideoFrames();
115 
116 #if 0
117  LOG(VB_PLAYBACK, LOG_DEBUG,
118  LOC + QString("Validframes %1, FreeFrames %2, VideoPaused %3")
119  .arg(nbframes).arg(videoOutput->FreeVideoFrames()).arg(videoPaused));
120 #endif
121 
122  // completely drain the video buffers for certain situations
123  bool release_all = player_ctx->buffer->DVD()->DVDWaitingForPlayer() &&
124  (nbframes > 0);
125  bool release_one = (nbframes > 1) && videoPaused && !allpaused &&
127  player_ctx->buffer->DVD()->IsWaiting() ||
129  if (release_all || release_one)
130  {
131  if (nbframes < 5 && videoOutput)
133 
134  // if we go below the pre-buffering limit, the player will pause
135  // so do this 'manually'
136  DisplayNormalFrame(false);
137  // unpause the still frame if more frames become available
138  if (dvd_stillframe_showing && nbframes > 1)
139  {
140  dvd_stillframe_showing = false;
141  UnpauseVideo();
142  }
143  return !IsErrored();
144  }
145 
146  // clear the mythtv imposed wait state
148  {
149  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Clearing MythTV DVD wait state");
150  bool inStillFrame = player_ctx->buffer->DVD()->IsInStillFrame();
152  ClearAfterSeek(true);
153  if (!inStillFrame && videoPaused && !allpaused)
154  UnpauseVideo();
155  return !IsErrored();
156  }
157 
158  // wait for the video buffers to drain
159  if (nbframes < 2)
160  {
161  // clear the DVD wait state
162  if (player_ctx->buffer->DVD()->IsWaiting())
163  {
164  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Clearing DVD wait state");
165  bool inStillFrame = player_ctx->buffer->DVD()->IsInStillFrame();
166  player_ctx->buffer->DVD()->WaitSkip();
167  if (!inStillFrame && videoPaused && !allpaused)
168  UnpauseVideo();
169  return !IsErrored();
170  }
171 
172  // we need a custom presentation method for still frame menus with audio
173  if (player_ctx->buffer->DVD()->IsInMenu() &&
175  {
176  // ensure we refresh the pause frame
178  needNewPauseFrame = true;
180  dvd_stillframe_showing = true;
182  return !IsErrored();
183  }
184 
185  // the still frame is treated as a pause frame
186  if (player_ctx->buffer->DVD()->IsInStillFrame())
187  {
188  // ensure we refresh the pause frame
190  needNewPauseFrame = true;
191 
192  // we are in a still frame so pause video output
193  if (!videoPaused)
194  {
195  PauseVideo();
196  return !IsErrored();
197  }
198 
199  // see if the pause frame has timed out
200  StillFrameCheck();
201 
202  // flag if we have no frame
203  if (nbframes == 0)
204  {
205  LOG(VB_PLAYBACK, LOG_WARNING, LOC +
206  "In DVD Menu: No video frames in queue");
207  usleep(10000);
208  return !IsErrored();
209  }
210 
211  dvd_stillframe_showing = true;
212  }
213  else
214  {
215  dvd_stillframe_showing = false;
216  }
217  }
218 
219  // unpause the still frame if more frames become available
220  if (dvd_stillframe_showing && nbframes > 1)
221  {
222  UnpauseVideo();
223  dvd_stillframe_showing = false;
224  return !IsErrored();
225  }
226 
227  return MythPlayer::VideoLoop();
228 }
229 
231 {
232  // clear the buffering state
233  SetBuffering(false);
234 
237 
238  osdLock.lock();
239  videofiltersLock.lock();
242  videofiltersLock.unlock();
243  osdLock.unlock();
244 
245  AVSync(NULL, true);
246 }
247 
248 bool MythDVDPlayer::FastForward(float seconds)
249 {
250  if (decoder)
252  return MythPlayer::FastForward(seconds);
253 }
254 
255 bool MythDVDPlayer::Rewind(float seconds)
256 {
257  if (decoder)
259  return MythPlayer::Rewind(seconds);
260 }
261 
262 bool MythDVDPlayer::JumpToFrame(uint64_t frame)
263 {
264  if (decoder)
266  return MythPlayer::JumpToFrame(frame);
267 }
268 
270 {
271  if (player_ctx->buffer->DVD())
272  player_ctx->buffer->DVD()->SetParent(this);
273 
274  player_ctx->LockPlayingInfo(__FILE__, __LINE__);
275  if (player_ctx->playingInfo)
276  {
277  QString name;
278  QString serialid;
279  if (player_ctx->playingInfo->GetTitle().isEmpty() &&
280  player_ctx->buffer->DVD() &&
281  player_ctx->buffer->DVD()->GetNameAndSerialNum(name, serialid))
282  {
284  }
285  }
286  player_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
287 
289 }
290 
292 {
294  if (m_initial_title > -1)
296 
297  if (m_initial_audio_track > -1)
300  if (m_initial_subtitle_track > -1)
303 
304  if (bookmarkseek > 30)
305  {
306 
307  // we need to trigger a dvd cell change to ensure the new title length
308  // is set and the position map updated accordingly
309  decodeOneFrame = true;
310  int count = 0;
311  while (count++ < 100 && decodeOneFrame)
312  usleep(50000);
313  }
316 }
317 
318 void MythDVDPlayer::ResetPlaying(bool resetframes)
319 {
321 }
322 
324 {
325  if (player_ctx->buffer->DVD())
326  player_ctx->buffer->DVD()->SetParent(NULL);
327 }
328 
329 bool MythDVDPlayer::PrepareAudioSample(int64_t &timecode)
330 {
332  WrapTimecode(timecode, TC_AUDIO);
333 
334  if (player_ctx->buffer->IsDVD() &&
336  return true;
337  return false;
338 }
339 
341 {
343  SetDVDBookmark(0);
344  else
346 }
347 
349 {
351  return 0;
352 
353  QStringList dvdbookmark = QStringList();
354  QString name;
355  QString serialid;
356  long long frames = 0;
357  player_ctx->LockPlayingInfo(__FILE__, __LINE__);
358  if (player_ctx->playingInfo)
359  {
360  if (!player_ctx->buffer->DVD()->GetNameAndSerialNum(name, serialid))
361  {
362  player_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
363  return 0;
364  }
365  dvdbookmark = player_ctx->playingInfo->QueryDVDBookmark(serialid);
366  if (!dvdbookmark.empty())
367  {
368  QStringList::Iterator it = dvdbookmark.begin();
369  m_initial_title = (*it).toInt();
370  frames = (long long)((*++it).toLongLong() & 0xffffffffLL);
371  m_initial_audio_track = (*++it).toInt();
372  m_initial_subtitle_track = (*++it).toInt();
373  LOG(VB_PLAYBACK, LOG_INFO, LOC +
374  QString("Get Bookmark: title %1 audiotrack %2 subtrack %3 "
375  "frame %4")
377  .arg(m_initial_subtitle_track).arg(frames));
378  }
379  }
380  player_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
381  return frames;;
382 }
383 
385 {
387  if (decoder)
390  player_ctx->buffer->DVD()->SetDVDSpeed(-1);
391  else if (player_ctx->buffer->IsDVD())
393 }
394 
395 void MythDVDPlayer::AVSync(VideoFrame *frame, bool limit_delay)
396 {
397  MythPlayer::AVSync(frame, true);
398 }
399 
400 long long MythDVDPlayer::CalcMaxFFTime(long long ff, bool setjump) const
401 {
402  if ((totalFrames > 0) && player_ctx->buffer->IsDVD() &&
403  player_ctx->buffer->DVD()->TitleTimeLeft() < 5)
404  return 0;
405  return MythPlayer::CalcMaxFFTime(ff, setjump);
406 }
407 
409 {
410  if (!player_ctx->buffer->IsDVD())
411  return 0;
412 
413  return (m_stillFrameLength > 0) ?
414  (m_stillFrameTimer.elapsed() / 1000) :
416 
417 }
418 
420 {
422 }
423 
424 void MythDVDPlayer::SeekForScreenGrab(uint64_t &number, uint64_t frameNum,
425  bool absolute)
426 {
427  if (!player_ctx->buffer->IsDVD())
428  return;
429  if (GoToMenu("menu"))
430  {
431  if (player_ctx->buffer->DVD()->IsInMenu() &&
433  {
434  GoToDVDProgram(1);
435  }
436  }
437  else if (player_ctx->buffer->DVD()->GetTotalTimeOfTitle() < 60)
438  {
439  GoToDVDProgram(1);
440  number = frameNum;
441  if (number >= totalFrames)
442  number = totalFrames / 2;
443  }
444 }
445 
447 {
448  if (kTrackTypeAudio == type)
449  player_ctx->buffer->DVD()->SetTrack(type, trackNo);
450  return MythPlayer::SetTrack(type, trackNo);
451 }
452 
454 {
455  if (!player_ctx->buffer->IsDVD())
456  return 0;
457  return player_ctx->buffer->DVD()->NumPartsInTitle();
458 }
459 
461 {
462  if (!player_ctx->buffer->IsDVD())
463  return 0;
464  return player_ctx->buffer->DVD()->GetPart();
465 }
466 
467 void MythDVDPlayer::GetChapterTimes(QList<long long> &times)
468 {
469  if (!player_ctx->buffer->IsDVD())
470  return;
471  player_ctx->buffer->DVD()->GetChapterTimes(times);
472 }
473 
475 {
476  if (!player_ctx->buffer->IsDVD())
477  return false;
478 
479  int total = GetNumChapters();
480  int current = GetCurrentChapter();
481 
482  if (chapter < 0 || chapter > total)
483  {
484  if (chapter < 0)
485  {
486  chapter = current -1;
487  if (chapter < 0) chapter = 0;
488  }
489  else if (chapter > total)
490  {
491  chapter = current + 1;
492  if (chapter > total) chapter = total;
493  }
494  }
495 
496  bool success = player_ctx->buffer->DVD()->playTrack(chapter);
497  if (success)
498  {
499  if (decoder)
500  {
502  if (player_ctx->buffer->DVD()->GetCellStart() == 0)
503  decoder->SeekReset(framesPlayed, 0, true, true);
504  }
506  }
507 
508  jumpchapter = 0;
509  return success;
510 }
511 
513 {
514  if (!osd || !player_ctx->buffer->IsDVD())
515  return;
516 
517  uint buttonversion = 0;
518  AVSubtitle *dvdSubtitle = player_ctx->buffer->DVD()->GetMenuSubtitle(buttonversion);
519  bool numbuttons = player_ctx->buffer->DVD()->NumMenuButtons();
520 
521  // nothing to do
522  if (buttonversion == ((uint)m_buttonVersion))
523  {
525  return;
526  }
527 
528  // clear any buttons
529  if (!numbuttons || !dvdSubtitle || (buttonversion == 0))
530  {
531  SetCaptionsEnabled(false, false);
532  osdLock.lock();
533  if (osd)
534  osd->ClearSubtitles();
535  osdLock.unlock();
536  m_buttonVersion = 0;
538  return;
539  }
540 
541  m_buttonVersion = buttonversion;
542  QRect buttonPos = player_ctx->buffer->DVD()->GetButtonCoords();
543  osdLock.lock();
544  if (osd)
545  osd->DisplayDVDButton(dvdSubtitle, buttonPos);
546  osdLock.unlock();
549 }
550 
551 bool MythDVDPlayer::GoToMenu(QString str)
552 {
553  if (!player_ctx->buffer->IsDVD())
554  return false;
556  bool ret = player_ctx->buffer->DVD()->GoToMenu(str);
557 
558  if (!ret)
559  {
560  SetOSDMessage(QObject::tr("DVD Menu Not Available"), kOSDTimeout_Med);
561  LOG(VB_GENERAL, LOG_ERR, "No DVD Menu available.");
562  return false;
563  }
564 
565  return true;
566 }
567 
568 void MythDVDPlayer::GoToDVDProgram(bool direction)
569 {
570  if (!player_ctx->buffer->IsDVD())
571  return;
572  if (direction == 0)
574  else
576 }
577 
578 void MythDVDPlayer::SetDVDBookmark(uint64_t frame)
579 {
580  if (!player_ctx->buffer->IsDVD())
581  return;
582 
583  uint64_t framenum = frame;
584  QStringList fields;
585  QString name;
586  QString serialid;
587  int title = 0;
588  int part;
589  int audiotrack = -1;
590  int subtitletrack = -1;
591  if (!player_ctx->buffer->DVD()->GetNameAndSerialNum(name, serialid))
592  {
593  LOG(VB_GENERAL, LOG_ERR, LOC +
594  "DVD has no name and serial number. Cannot set bookmark.");
595  return;
596  }
597 
599  player_ctx->buffer->DVD()->
600  GetTotalTimeOfTitle() > 120 && frame > 0)
601  {
602  audiotrack = GetTrack(kTrackTypeAudio);
604  {
605  subtitletrack = player_ctx->buffer->DVD()->GetTrack(
607  }
608  player_ctx->buffer->DVD()->GetPartAndTitle(part, title);
609  }
610  else
611  framenum = 0;
612 
613  player_ctx->LockPlayingInfo(__FILE__, __LINE__);
614  if (player_ctx->playingInfo)
615  {
616  fields += serialid;
617  fields += name;
618  fields += QString("%1").arg(title);
619  fields += QString("%1").arg(audiotrack);
620  fields += QString("%1").arg(subtitletrack);
621  fields += QString("%1").arg(framenum);
623  LOG(VB_PLAYBACK, LOG_INFO, LOC +
624  QString("Set Bookmark: title %1 audiotrack %2 subtrack %3 frame %4")
625  .arg(title).arg(audiotrack).arg(subtitletrack).arg(framenum));
626  }
627  player_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
628 }
629 
631 {
632  if (player_ctx->buffer->DVD() && player_ctx->buffer->DVD()->IsOpen())
633  return player_ctx->buffer->DVD()->GetNumAngles();
634  return 0;
635 }
636 
638 {
639  if (player_ctx->buffer->DVD() && player_ctx->buffer->DVD()->IsOpen())
640  return player_ctx->buffer->DVD()->GetCurrentAngle();
641  return -1;
642 }
643 
644 QString MythDVDPlayer::GetAngleName(int angle) const
645 {
646  if (angle >= 1 && angle <= GetNumAngles())
647  {
648  QString name = QObject::tr("Angle %1").arg(angle);
649  return name;
650  }
651  return QString();
652 }
653 
655 {
656  uint total = GetNumAngles();
657  if (!total || angle == GetCurrentAngle())
658  return false;
659 
660  if (angle < 1 || angle > (int)total)
661  angle = 1;
662 
663  return player_ctx->buffer->DVD()->SwitchAngle(angle);
664 }
665 
667 {
668  m_stillFrameTimerLock.lock();
670  m_stillFrameTimerLock.unlock();
671 }
672 
674 {
675  if (length != m_stillFrameLength)
676  {
677  m_stillFrameTimerLock.lock();
678  m_stillFrameLength = length;
680  m_stillFrameTimerLock.unlock();
681  }
682 }
683 
685 {
686  if (player_ctx->buffer->IsDVD() &&
688  (m_stillFrameLength > 0) && (m_stillFrameLength < 0xff))
689  {
690  m_stillFrameTimerLock.lock();
691  int elapsedTime = m_stillFrameTimer.elapsed() / 1000;
692  m_stillFrameTimerLock.unlock();
693  if (elapsedTime >= m_stillFrameLength)
694  {
695  LOG(VB_PLAYBACK, LOG_INFO, LOC +
696  QString("Stillframe timeout after %1 seconds")
697  .arg(m_stillFrameLength));
699  m_stillFrameLength = 0;
700  }
701  }
702 }
703 
704 void MythDVDPlayer::CreateDecoder(char *testbuf, int testreadsize)
705 {
707  testreadsize))
708  {
710  playerFlags));
711  }
712 }