MythTV master
mythplayerui.cpp
Go to the documentation of this file.
1#include <algorithm>
2
3// MythTV
5#include "libmythbase/mythconfig.h"
9
12#include "livetvchain.h"
14#include "mheg/interactivetv.h"
15#include "mythplayerui.h"
16#include "mythsystemevent.h"
17#include "osd.h"
18#include "tv_play.h"
19
20#define LOC QString("PlayerUI: ")
21
23 PlayerContext *Context, PlayerFlags Flags)
24 : MythPlayerEditorUI(MainWindow, Tv, Context, Flags),
26 m_display(MainWindow->GetDisplay())
27{
28 // Finish setting up the overlays
29 m_osd.SetPlayer(this);
31
32 // User feedback during slow seeks
33 connect(this, &MythPlayerUI::SeekingSlow, this, [&](int Count)
34 {
35 UpdateOSDMessage(tr("Searching") + QString().fill('.', Count % 3), kOSDTimeout_Short);
37 });
38
39 // Seeking has finished; remove slow seek user feedback window
40 connect(this, &MythPlayerUI::SeekingComplete, this, [&]()
41 {
42 m_osdLock.lock();
44 m_osdLock.unlock();
45 });
46
47 // Seeking has finished; update position on OSD
48 connect(this, &MythPlayerUI::SeekingDone, this, [&]()
49 {
51 });
52
53 // Setup OSD debug
54 m_osdDebugTimer.setInterval(1s);
57
58 // Other connections
62
63 // Setup refresh interval.
66}
67
69{
70 LOG(VB_GENERAL, LOG_INFO, LOC + "Initialising player state");
72}
73
75{
76 if (OpenFile() < 0)
77 {
78 LOG(VB_GENERAL, LOG_ERR, LOC + "Unable to open video file.");
79 return false;
80 }
81
85 m_jumpChapter = 0;
88
89 if (!InitVideo())
90 {
91 LOG(VB_GENERAL, LOG_ERR, LOC + "Unable to initialize video.");
93 return false;
94 }
95
96 EventStart();
97 DecoderStart(true);
99 VideoStart();
100
101 m_playerThread->setPriority(QThread::TimeCriticalPriority);
102#ifdef Q_OS_ANDROID
103 setpriority(PRIO_PROCESS, m_playerThreadId, -20);
104#endif
107 return !IsErrored();
108}
109
111{
112 // TODO handle initial commskip and/or cutlist skip as well
113 if (m_bookmarkSeek > 30)
115}
116
118{
119 // Handle decoder callbacks
121
122 // Live TV program change
123 if (m_fileChanged)
124 FileChanged();
125
126 // Check if visualiser is wanted on first start and after video change
128 AutoVisualise(!m_videoDim.isEmpty());
129
130 // recreate the osd if a reinit was triggered by another thread
131 if (m_reinitOsd)
132 ReinitOSD();
133
134 // enable/disable forced subtitles if signalled by the decoder
139
140 // reset the scan (and hence deinterlacers) if triggered by the decoder
142
143 // refresh the position map for an in-progress recording while editing
145 {
146 if (m_editUpdateTimer.hasExpired(2000))
147 {
148 // N.B. the positionmap update and osd refresh are asynchronous
150 m_osdLock.lock();
152 m_osdLock.unlock();
153 m_editUpdateTimer.start();
154 }
155 }
156
157 // Refresh the programinfo in use status
158 m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
161 m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
162
163 // Disable timestretch if we are too close to the end of the buffer
164 if (m_ffrewSkip == 1 && (m_playSpeed > 1.0F) && IsNearEnd())
165 {
166 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Near end, Slowing down playback.");
167 Play(1.0F, true, true);
168 }
169
171 {
172 // Switch from the dummy recorder to the tuned program in livetv
173 m_playerCtx->m_tvchain->JumpToNext(true, 0s);
175 }
176 else if ((!m_allPaused || GetEof() != kEofStateNone) &&
179 {
180 // Switch to the next program in livetv
183 }
184
185 // Jump to the next program in livetv
187 {
189 }
190
191 // Change interactive stream if requested
192 if (!m_newStream.isEmpty())
193 {
195 m_newStream = QString();
196 }
197
198 // Disable fastforward if we are too close to the end of the buffer
199 if (m_ffrewSkip > 1 && (CalcMaxFFTime(100, false) < 100))
200 {
201 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Near end, stopping fastforward.");
202 Play(1.0F, true, true);
203 }
204
205 // Disable rewind if we are too close to the beginning of the buffer
206 if (m_ffrewSkip < 0 && CalcRWTime(-m_ffrewSkip) >= 0 &&
208 {
209 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Near start, stopping rewind.");
210 float stretch = (m_ffrewSkip > 0) ? 1.0F : m_audio.GetStretchFactor();
211 Play(stretch, true, true);
212 }
213
214 // Check for error
216 {
217 LOG(VB_GENERAL, LOG_ERR, LOC + "Unknown recorder error, exiting decoder");
218 if (!IsErrored())
219 SetErrored(tr("Irrecoverable recorder error"));
220 m_killDecoder = true;
221 return;
222 }
223
224 // Handle speed change
225 if (!qFuzzyCompare(m_playSpeed + 1.0F, m_nextPlaySpeed + 1.0F) &&
227 {
228 ChangeSpeed();
229 return;
230 }
231
232 // Check if we got a communication error, and if so pause playback
234 {
235 Pause();
237 }
238
239 // Handle end of file
240 EofState eof = GetEof();
241 if (HasReachedEof())
242 {
243#if CONFIG_MHEG
244 if (m_interactiveTV && m_interactiveTV->StreamStarted(false))
245 {
246 Pause();
247 return;
248 }
249#endif
251 {
252 LOG(VB_GENERAL, LOG_NOTICE, LOC + "LiveTV forcing JumpTo 1");
253 m_playerCtx->m_tvchain->JumpToNext(true, 0s);
254 return;
255 }
256
257 bool drained = false;
259 {
260 // We have audio only or mostly audio content. Exit when
261 // the audio is drained.
262 drained =
264 m_audio.IsPaused() ||
266 }
267 else
268 {
269 // We have normal or video only content. Exit when the
270 // video is drained.
272 }
273 if (eof != kEofStateDelayed || drained)
274 {
275 if (eof == kEofStateDelayed)
276 {
277 LOG(VB_PLAYBACK, LOG_INFO,
278 QString("waiting for no video frames %1")
280 }
281 LOG(VB_PLAYBACK, LOG_INFO,
282 QString("HasReachedEof() at framesPlayed=%1 totalFrames=%2")
284 Pause();
285 SetPlaying(false);
286 return;
287 }
288 }
289
290 // Handle rewind
291 if (m_rewindTime > 0 && (m_ffrewSkip == 1 || m_ffrewSkip == 0))
292 {
294 if (m_rewindTime > 0)
295 DoRewind(static_cast<uint64_t>(m_rewindTime), kInaccuracyDefault);
296 }
297
298 // Handle fast forward
299 if (m_ffTime > 0 && (m_ffrewSkip == 1 || m_ffrewSkip == 0))
300 {
302 if (m_ffTime > 0)
303 {
304 DoFastForward(static_cast<uint64_t>(m_ffTime), kInaccuracyDefault);
305 if (GetEof() != kEofStateNone)
306 return;
307 }
308 }
309
310 // Handle chapter jump
311 if (m_jumpChapter != 0)
313
314 // Handle commercial skipping
315 if (m_commBreakMap.GetSkipCommercials() != 0 && (m_ffrewSkip == 1))
316 {
317 if (!m_commBreakMap.HasMap())
318 {
319 //: The commercials/adverts have not been flagged
320 SetOSDStatus(tr("Not Flagged"), kOSDTimeout_Med);
321 QString message = "COMMFLAG_REQUEST ";
322 m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
323 message += QString("%1").arg(m_playerCtx->m_playingInfo->GetChanID()) +
325 m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
326 gCoreContext->SendMessage(message);
327 }
328 else
329 {
330 QString msg;
331 uint64_t jumpto = 0;
332 uint64_t frameCount = GetCurrentFrameCount();
333 // XXX CommBreakMap should use duration map not m_videoFrameRate
336 frameCount, msg);
337 if (!msg.isEmpty())
339 if (jump)
341 }
343 return;
344 }
345
346 // Handle automatic commercial skipping
347 uint64_t jumpto = 0;
348 if (m_deleteMap.IsEmpty() && (m_ffrewSkip == 1) &&
351 {
352 QString msg;
353 uint64_t frameCount = GetCurrentFrameCount();
354 // XXX CommBreakMap should use duration map not m_videoFrameRate
357 frameCount, msg);
358 if (!msg.isEmpty())
360 if (jump)
362 }
363
364 // Handle cutlist skipping
365 if (!m_allPaused && (m_ffrewSkip == 1) &&
367 {
368 if (jumpto == m_totalFrames)
369 {
372 }
373 else
374 {
376 }
377 }
378}
379
381{
382#if CONFIG_MHEG
383 // handle Interactive TV
384 if (GetInteractiveTV())
385 {
386 m_osdLock.lock();
387 m_itvLock.lock();
388 auto *window = qobject_cast<InteractiveScreen *>(m_captionsOverlay.GetWindow(OSD_WIN_INTERACT));
389 if ((m_interactiveTV->ImageHasChanged() || !m_itvVisible) && window)
390 {
391 m_interactiveTV->UpdateOSD(window, m_painter);
392 m_itvVisible = true;
393 }
394 m_itvLock.unlock();
395 m_osdLock.unlock();
396 }
397#endif // CONFIG_MHEG
398}
399
401{
403 // ensure we re-check double rate support following a speed change
404 UnlockScan();
405}
406
407void MythPlayerUI::ReinitVideo(bool ForceUpdate)
408{
409 MythPlayer::ReinitVideo(ForceUpdate);
410
411 // Signal to the main thread to reinit OSD
412 m_reinitOsd = true;
413
414 // Signal to main thread to reinit subtitles
416 emit EnableSubtitles(true);
417
418 // Signal to the main thread to check auto visualise
420}
421
423{
424 QRect visible;
425 QRect total;
426 float aspect = NAN;
427 float scaling = NAN;
428
429 m_osdLock.lock();
430 m_videoOutput->GetOSDBounds(total, visible, aspect, scaling, 1.0F);
431 m_osd.Init(visible, aspect);
432 m_captionsOverlay.Init(visible, aspect);
434
435#if CONFIG_MHEG
436 if (GetInteractiveTV())
437 {
438 QMutexLocker locker(&m_itvLock);
439 m_interactiveTV->Reinit(total, visible, aspect);
440 }
441#endif // CONFIG_MHEG
442
443 // If there is a forced text subtitle track (which is possible
444 // in e.g. a .mkv container), and forced subtitles are
445 // allowed, then start playback with that subtitle track
446 // selected. Otherwise, use the frontend settings to decide
447 // which captions/subtitles (if any) to enable at startup.
448 // TODO: modify the fix to #10735 to use this approach
449 // instead.
450 bool hasForcedTextTrack = false;
451 uint forcedTrackNumber = 0;
453 {
455 for (uint i = 0; !hasForcedTextTrack && i < numTextTracks; ++i)
456 {
458 {
459 hasForcedTextTrack = true;
460 forcedTrackNumber = i;
461 }
462 }
463 }
464 if (hasForcedTextTrack)
465 SetTrack(kTrackTypeRawText, forcedTrackNumber);
466 else
468
469 m_osdLock.unlock();
470
471 SetPlaying(true);
472 ClearAfterSeek(false);
475
478 AutoVisualise(!m_videoDim.isEmpty());
479}
480
482{
483 m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
484 {
486 {
487 // When initial playback gets underway, we override the ProgramInfo
488 // flags such that future calls to GetBookmark() will consider only
489 // an actual bookmark and not progstart or lastplaypos information.
493 }
494 }
495 m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
497}
498
500{
502
504 {
506 }
507 else if (DisplayNormalFrame())
508 {
511 else if (m_decoder && m_decoder->GetEof() != kEofStateNone)
513 else
514 m_framesPlayed = static_cast<uint64_t>(
516 }
517
518 return !IsErrored();
519}
520
522{
523 SetFrameInterval(GetScanType(), 1.0 / (m_videoFrameRate * static_cast<double>(m_playSpeed)));
525 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Display Refresh Rate: %1 Video Frame Rate: %2")
526 .arg(1000000.0 / m_refreshInterval.count(), 0, 'f', 3)
527 .arg(1000000.0 / m_frameInterval.count(), 0, 'f', 3));
528}
529
530void MythPlayerUI::RenderVideoFrame(MythVideoFrame *Frame, FrameScanType Scan, bool Prepare, std::chrono::microseconds Wait)
531{
532 if (!m_videoOutput)
533 return;
534
535 if (Prepare)
540 LOG(VB_PLAYBACK, LOG_DEBUG, QString("Clearing render one"));
541 m_renderOneFrame = false;
544 m_osd.Draw();
546
547 if (Wait > 0us)
549
551}
552
554{
555 m_fileChanged = false;
556 LOG(VB_PLAYBACK, LOG_INFO, LOC + "FileChanged");
557
558 Pause();
559 ChangeSpeed();
560 if (dynamic_cast<AvFormatDecoder *>(m_decoder))
561 m_playerCtx->m_buffer->Reset(false, true);
562 else
563 m_playerCtx->m_buffer->Reset(false, true, true);
565 Play();
566
568
569 m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
571 if (m_decoder)
573 m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
574
575 CheckTVChain();
577}
578
580{
582 {
584 {
586 m_needNewPauseFrame = false;
587
589 {
590 m_osdLock.lock();
591 LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("timecode video:%1 audio:%2")
592 .arg(m_latestVideoTimecode.count()).arg(m_latestAudioTimecode.count()));
593
594 // Use audio timecode when video timecode is not available for DVB audio recordings.
596 DeleteMap::UpdateOSD(timecode, &m_osd);
597 m_osdLock.unlock();
598 }
599 }
600 else
601 {
602 m_decodeOneFrame = true;
603 }
604 }
605}
606
607void MythPlayerUI::DoDisplayVideoFrame(MythVideoFrame* Frame, std::chrono::microseconds Due)
608{
609 if (Due < 0us)
610 {
611 m_videoOutput->SetFramesPlayed(static_cast<long long>(++m_framesPlayed));
613 LOG(VB_PLAYBACK, LOG_DEBUG, QString("Clearing render one"));
614 m_renderOneFrame = false;
615 }
616 else if (!FlagIsSet(kVideoIsNull) && Frame)
617 {
618
619 // Check scan type
620 bool showsecondfield = false;
621 FrameScanType ps = GetScanForDisplay(Frame, showsecondfield);
622
623 // if we get here, we're actually going to do video output
624 RenderVideoFrame(Frame, ps, true, Due);
625
626 // Only double rate CPU deinterlacers require an extra call to PrepareFrame
627 bool secondprepare = Frame->GetDoubleRateOption(DEINT_CPU) && !Frame->GetDoubleRateOption(DEINT_SHADER);
628 // and the first deinterlacing pass will have marked the frame as already deinterlaced
629 // which will break GetScanForDisplay below and subsequent deinterlacing
630 bool olddeinterlaced = Frame->m_alreadyDeinterlaced;
631 if (secondprepare)
632 Frame->m_alreadyDeinterlaced = false;
633 // Update scan settings now that deinterlacer has been set and we know
634 // whether we need a second field
635 ps = GetScanForDisplay(Frame, showsecondfield);
636
637 // Reset olddeinterlaced if necessary (pause frame etc)
638 if (!showsecondfield && secondprepare)
639 {
640 Frame->m_alreadyDeinterlaced = olddeinterlaced;
641 }
642 else if (showsecondfield)
643 {
644 // Second field
645 if (kScan_Interlaced == ps)
647 RenderVideoFrame(Frame, ps, secondprepare, Due + m_frameInterval / 2);
648 }
649 }
650 else
651 {
653 }
654}
655
657{
658 if (!m_videoOutput)
659 return;
660
662 {
663 SetErrored(tr("Serious error detected in Video Output"));
664 return;
665 }
666
667 // clear the buffering state
668 SetBuffering(false);
669
671 PreProcessNormalFrame(); // Allow interactiveTV to draw on pause frame
672
675 RenderVideoFrame(nullptr, scan, true, 0ms);
676}
677
678bool MythPlayerUI::DisplayNormalFrame(bool CheckPrebuffer)
679{
680 if (m_allPaused)
681 return false;
682
683 if (CheckPrebuffer && !PrebufferEnoughFrames())
684 return false;
685
686 // clear the buffering state
687 SetBuffering(false);
688
689 // retrieve the next frame
692
693 // Check aspect ratio
694 CheckAspectRatio(frame);
695
698
699 // Player specific processing (dvd, bd, mheg etc)
701
702 // handle scan type changes
704
705 // Detect letter boxing
706 // FIXME this is temporarily moved entirely into the main thread as there are
707 // too many threading issues and the decoder thread is not yet ready to handle
708 // QObject signals and slots.
709 // When refactoring is complete, move it into the decoder thread and
710 // signal switches via a new field in MythVideoFrame
713 {
715 ReinitOSD();
716 }
717
718 // When is the next frame due
719 std::chrono::microseconds due = m_avSync.AVSync(&m_audio, frame, m_frameInterval, m_playSpeed, !m_videoDim.isEmpty(),
721 // Display it
722 DoDisplayVideoFrame(frame, due);
725
726 return true;
727}
728
729void MythPlayerUI::SetVideoParams(int Width, int Height, double FrameRate, float Aspect,
730 bool ForceUpdate, int ReferenceFrames,
731 FrameScanType Scan, const QString &CodecName)
732{
733 MythPlayer::SetVideoParams(Width, Height, FrameRate, Aspect, ForceUpdate, ReferenceFrames,
734 Scan, CodecName);
735
736 // ensure deinterlacers are correctly reset after a change
737 UnlockScan();
738 FrameScanType newscan = DetectInterlace(Scan, static_cast<float>(m_videoFrameRate), m_videoDispDim.height());
740 ResetTracker();
741}
742
757void MythPlayerUI::SetWatched(bool ForceWatched)
758{
759 m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
761 {
762 m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
763 return;
764 }
765
766 uint64_t numFrames = GetCurrentFrameCount();
767
768 // For recordings we want to ignore the post-roll and account for
769 // in-progress recordings where totalFrames doesn't represent
770 // the full length of the recording. For videos we can only rely on
771 // totalFrames as duration metadata can be wrong
774 {
775
776 // If the recording is stopped early we need to use the recording end
777 // time, not the programme end time
779 qint64 starttime = pi->GetRecordingStartTime().toSecsSinceEpoch();
780 qint64 endactual = pi->GetRecordingEndTime().toSecsSinceEpoch();
781 qint64 endsched = pi->GetScheduledEndTime().toSecsSinceEpoch();
782 qint64 endtime = std::min(endactual, endsched);
783 numFrames = static_cast<uint64_t>((endtime - starttime) * m_videoFrameRate);
784 }
785
786 // 4 minutes min, 12 minutes max
787 auto offset = std::chrono::seconds(lround(0.14 * (numFrames / m_videoFrameRate)));
788 offset = std::clamp(offset, 240s, 720s);
789
790 if (ForceWatched || (m_framesPlayed > (numFrames - (offset.count() * m_videoFrameRate))))
791 {
793 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Marking recording as watched using offset %1 minutes")
794 .arg(offset.count()/60));
795 }
796
797 m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
798}
799
801{
802 m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
805 m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
806}
807
809{
810 m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
813 m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
814}
815
817{
818 // At this point we may not have the correct frame rate.
819 // Since interlaced is always at 25 or 30 fps, if the interval
820 // is less than 30000 (33fps) it must be representing one
821 // field and not one frame, so multiply by 2.
822 std::chrono::microseconds realfi = m_frameInterval;
823 if (m_frameInterval < 30ms)
824 realfi = m_frameInterval * 2;
825 return (duration_cast<floatusecs>(realfi) / 2.0) > (duration_cast<floatusecs>(m_refreshInterval) * 0.995);
826}
827
829{
830 QString samplerate = MythMediaBuffer::BitrateToString(static_cast<uint64_t>(m_audio.GetSampleRate()), true);
831 Map.insert("samplerate", samplerate);
832 Map.insert("filename", m_playerCtx->m_buffer->GetSafeFilename());
833 Map.insert("decoderrate", m_playerCtx->m_buffer->GetDecoderRate());
834 Map.insert("storagerate", m_playerCtx->m_buffer->GetStorageRate());
835 Map.insert("bufferavail", m_playerCtx->m_buffer->GetAvailableBuffer());
836 Map.insert("buffersize", QString::number(m_playerCtx->m_buffer->GetBufferSize() >> 20));
838
839 if (m_videoOutput)
840 {
841 QString frames = QString("%1/%2").arg(m_videoOutput->ValidVideoFrames())
843 Map.insert("videoframes", frames);
844 }
845 if (m_decoder)
846 Map["videodecoder"] = m_decoder->GetCodecDecoderName();
847
848 Map["framerate"] = QString::fromUtf8("%1±%2")
849 .arg(static_cast<double>(m_outputJmeter.GetLastFPS()), 0, 'f', 2)
850 .arg(static_cast<double>(m_outputJmeter.GetLastSD()), 0, 'f', 2);
851 Map["load"] = m_outputJmeter.GetLastCPUStats();
852
854
855 QString displayfps = QString("%1x%2@%3Hz")
856 .arg(m_display->GetResolution().width())
857 .arg(m_display->GetResolution().height())
858 .arg(m_display->GetRefreshRate(), 0, 'f', 2);
859 Map["displayfps"] = displayfps;
860}
861
863{
864 Map["audiocodec"] = avcodec_get_name(m_audio.GetCodec());
865 Map["audiochannels"] = QString::number(m_audio.GetOrigChannels());
866
867 int width = m_videoDispDim.width();
868 int height = m_videoDispDim.height();
869 Map["videocodec"] = GetEncodingType();
870 if (m_decoder)
871 Map["videocodecdesc"] = m_decoder->GetRawEncodingType();
872 Map["videowidth"] = QString::number(width);
873 Map["videoheight"] = QString::number(height);
874 Map["videoframerate"] = QString::number(m_videoFrameRate, 'f', 2);
875 Map["deinterlacer"] = GetDeinterlacerName();
876
877 if (width < 640)
878 return;
879
880 bool interlaced = is_interlaced(GetScanType());
881 if (height > 2100)
882 Map["videodescrip"] = interlaced ? "UHD_4K_I" : "UHD_4K_P";
883 else if (width == 1920 || height == 1080 || height == 1088)
884 Map["videodescrip"] = interlaced ? "HD_1080_I" : "HD_1080_P";
885 else if ((width == 1280 || height == 720) && !interlaced)
886 Map["videodescrip"] = "HD_720_P";
887 else if (height >= 720)
888 Map["videodescrip"] = "HD";
889 else
890 Map["videodescrip"] = "SD";
891}
892
894{
896 if (Visible)
897 {
898 // This should already have enabled the required monitors
899 m_osdDebugTimer.start();
900 }
901 else
902 {
903 // If we have cleared/escaped the debug OSD screen, then ChangeOSDDebug
904 // is not called, so we need to ensure we turn off the monitors
905 m_osdDebugTimer.stop();
908 }
909}
910
912{
913 m_osdLock.lock();
914 InfoMap infoMap;
915 GetPlaybackData(infoMap);
918 m_osdLock.unlock();
919}
920
922{
923 m_osdLock.lock();
924 bool enable = !m_osdDebug;
925 EnableBitrateMonitor(enable);
927 if (enable)
929 else
931 m_osdDebug = enable;
932 m_osdLock.unlock();
933}
934
936{
937 bool enable = VERBOSE_LEVEL_CHECK(VB_PLAYBACK, LOG_ANY) || Enable;
938 m_outputJmeter.SetNumCycles(enable ? static_cast<int>(m_videoFrameRate) : 0);
939}
940
942{
945}
946
947/* JumpToStream, JumpToProgram and SwitchToProgram all need to be moved into the
948 * parent object and hopefully simplified. The fairly involved logic does not
949 * sit well with the new design objectives for the player classes and are better
950 * suited to the high level logic in TV.
951 */
952void MythPlayerUI::JumpToStream(const QString &stream)
953{
954 LOG(VB_PLAYBACK, LOG_INFO, LOC + "JumpToStream - begin");
955
956 // Shouldn't happen
957 if (stream.isEmpty())
958 return;
959
960 Pause();
962
963 ProgramInfo pginfo(stream);
964 SetPlayingInfo(pginfo);
965
968 else
969 m_playerCtx->m_buffer->OpenFile(stream);
970
971 if (!m_playerCtx->m_buffer->IsOpen())
972 {
973 LOG(VB_GENERAL, LOG_ERR, LOC + "JumpToStream buffer OpenFile failed");
975 SetErrored(tr("Error opening remote stream buffer"));
976 return;
977 }
978
979 m_watchingRecording = false;
980 m_totalLength = 0s;
981 m_totalFrames = 0;
982 m_totalDuration = 0s;
983
984 // 120 retries ~= 60 seconds
985 if (OpenFile(120) < 0)
986 {
987 LOG(VB_GENERAL, LOG_ERR, LOC + "JumpToStream OpenFile failed.");
989 SetErrored(tr("Error opening remote stream"));
990 return;
991 }
992
993 if (m_totalLength == 0s)
994 {
995 long long len = m_playerCtx->m_buffer->GetRealFileSize();
996 m_totalLength = std::chrono::seconds(len / ((m_decoder->GetRawBitrate() * 1000) / 8));
997 m_totalFrames = static_cast<uint64_t>(m_totalLength.count() * SafeFPS());
998 }
999
1000 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("JumpToStream length %1 bytes @ %2 Kbps = %3 Secs, %4 frames @ %5 fps")
1002 .arg(m_totalLength.count()).arg(m_totalFrames).arg(m_decoder->GetFPS()) );
1003
1005
1006 // the bitrate is reset by m_playerCtx->m_buffer->OpenFile()...
1008 m_decoder->SetProgramInfo(pginfo);
1009
1010 Play();
1011 ChangeSpeed();
1012
1014#if CONFIG_MHEG
1015 if (m_interactiveTV) m_interactiveTV->StreamStarted();
1016#endif
1017
1018 LOG(VB_PLAYBACK, LOG_INFO, LOC + "JumpToStream - end");
1019}
1020
1022{
1023 if (!IsReallyNearEnd())
1024 return;
1025
1026 LOG(VB_PLAYBACK, LOG_INFO, LOC + "SwitchToProgram - start");
1027 bool discontinuity = false;
1028 bool newtype = false;
1029 int newid = -1;
1030 ProgramInfo *pginfo = m_playerCtx->m_tvchain->GetSwitchProgram(discontinuity, newtype, newid);
1031 if (!pginfo)
1032 return;
1033
1034 bool newIsDummy = m_playerCtx->m_tvchain->GetInputType(newid) == "DUMMY";
1035
1036 SetPlayingInfo(*pginfo);
1037 Pause();
1038 ChangeSpeed();
1039
1040 // Release all frames to ensure the current decoder resources are released
1041 DiscardVideoFrames(true, true);
1042
1043 if (newIsDummy)
1044 {
1045 OpenDummy();
1046 ResetPlaying();
1048 delete pginfo;
1049 return;
1050 }
1051
1053 {
1054 // Restore original ringbuffer
1055 auto *ic = dynamic_cast<MythInteractiveBuffer*>(m_playerCtx->m_buffer);
1056 if (ic)
1057 m_playerCtx->m_buffer = ic->TakeBuffer();
1058 delete ic;
1059 }
1060
1062
1063 if (!m_playerCtx->m_buffer->IsOpen())
1064 {
1065 LOG(VB_GENERAL, LOG_ERR, LOC + QString("SwitchToProgram's OpenFile failed (input type: %1)")
1066 .arg(m_playerCtx->m_tvchain->GetInputType(newid)));
1067 LOG(VB_GENERAL, LOG_ERR, m_playerCtx->m_tvchain->toString());
1069 SetErrored(tr("Error opening switch program buffer"));
1070 delete pginfo;
1071 return;
1072 }
1073
1074 if (GetEof() != kEofStateNone)
1075 {
1076 discontinuity = true;
1077 ResetCaptions();
1078 }
1079
1080 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("SwitchToProgram(void) "
1081 "discont: %1 newtype: %2 newid: %3 decoderEof: %4")
1082 .arg(discontinuity).arg(newtype).arg(newid).arg(GetEof()));
1083
1084 if (discontinuity || newtype)
1085 {
1086 m_playerCtx->m_tvchain->SetProgram(*pginfo);
1087 if (m_decoder)
1088 m_decoder->SetProgramInfo(*pginfo);
1089
1090 m_playerCtx->m_buffer->Reset(true);
1091 if (newtype)
1092 {
1093 if (OpenFile() < 0)
1094 SetErrored(tr("Error opening switch program file"));
1095 }
1096 else
1097 {
1098 ResetPlaying();
1099 }
1100 }
1101 else
1102 {
1104 if (m_decoder)
1105 {
1108 }
1109 }
1110 delete pginfo;
1111
1112 if (IsErrored())
1113 {
1114 LOG(VB_GENERAL, LOG_ERR, LOC + "SwitchToProgram failed.");
1116 return;
1117 }
1118
1120
1121 // the bitrate is reset by m_playerCtx->m_buffer->OpenFile()...
1122 if (m_decoder)
1125
1126 if (discontinuity || newtype)
1127 {
1128 CheckTVChain();
1130 }
1131
1132 Play();
1133 LOG(VB_PLAYBACK, LOG_INFO, LOC + "SwitchToProgram - end");
1134}
1135
1137{
1138 LOG(VB_PLAYBACK, LOG_INFO, LOC + "JumpToProgram - start");
1139 bool discontinuity = false;
1140 bool newtype = false;
1141 int newid = -1;
1142 std::chrono::seconds nextpos = m_playerCtx->m_tvchain->GetJumpPos();
1143 ProgramInfo *pginfo = m_playerCtx->m_tvchain->GetSwitchProgram(discontinuity, newtype, newid);
1144 if (!pginfo)
1145 return;
1146
1148
1149 bool newIsDummy = m_playerCtx->m_tvchain->GetInputType(newid) == "DUMMY";
1150 SetPlayingInfo(*pginfo);
1151
1152 Pause();
1153 ChangeSpeed();
1154 ResetCaptions();
1155
1156 // Release all frames to ensure the current decoder resources are released
1157 DiscardVideoFrames(true, true);
1158
1159 m_playerCtx->m_tvchain->SetProgram(*pginfo);
1160 m_playerCtx->m_buffer->Reset(true);
1161
1162 if (newIsDummy)
1163 {
1164 OpenDummy();
1165 ResetPlaying();
1167 delete pginfo;
1168 m_inJumpToProgramPause = false;
1169 return;
1170 }
1171
1172 SendMythSystemPlayEvent("PLAY_CHANGED", pginfo);
1173
1175 {
1176 // Restore original ringbuffer
1177 auto *ic = dynamic_cast<MythInteractiveBuffer*>(m_playerCtx->m_buffer);
1178 if (ic)
1179 m_playerCtx->m_buffer = ic->TakeBuffer();
1180 delete ic;
1181 }
1182
1184 if (!m_playerCtx->m_buffer->IsOpen())
1185 {
1186 LOG(VB_GENERAL, LOG_ERR, LOC + QString("JumpToProgram's OpenFile failed (input type: %1)")
1187 .arg(m_playerCtx->m_tvchain->GetInputType(newid)));
1188 LOG(VB_GENERAL, LOG_ERR, m_playerCtx->m_tvchain->toString());
1190 SetErrored(tr("Error opening jump program file buffer"));
1191 delete pginfo;
1192 m_inJumpToProgramPause = false;
1193 return;
1194 }
1195
1197
1198 bool wasDummy = m_isDummy;
1199 if (newtype || wasDummy)
1200 {
1201 if (OpenFile() < 0)
1202 SetErrored(tr("Error opening jump program file"));
1203 }
1204 else
1205 {
1206 ResetPlaying();
1207 }
1208
1209 if (IsErrored() || !m_decoder)
1210 {
1211 LOG(VB_GENERAL, LOG_ERR, LOC + "JumpToProgram failed.");
1212 if (!IsErrored())
1213 SetErrored(tr("Error reopening video decoder"));
1214 delete pginfo;
1215 m_inJumpToProgramPause = false;
1216 return;
1217 }
1218
1220
1221 // the bitrate is reset by m_playerCtx->m_buffer->OpenFile()...
1224
1225 m_decoder->SetProgramInfo(*pginfo);
1226 delete pginfo;
1227
1228 CheckTVChain();
1230 m_inJumpToProgramPause = false;
1231 Play();
1232 ChangeSpeed();
1233
1234 // check that we aren't too close to the end of program.
1235 // and if so set it to 10s from the end if completed recordings
1236 // or 3s if live
1237 std::chrono::seconds duration = m_playerCtx->m_tvchain->GetLengthAtCurPos();
1238 std::chrono::seconds maxpos = m_playerCtx->m_tvchain->HasNext() ? 10s : 3s;
1239
1240 if (nextpos > (duration - maxpos))
1241 {
1242 nextpos = duration - maxpos;
1243 if (nextpos < 0s)
1244 nextpos = 0s;
1245 }
1246 else if (nextpos < 0s)
1247 {
1248 // it's a relative position to the end
1249 nextpos += duration;
1250 }
1251
1252 // nextpos is the new position to use in seconds
1253 uint64_t nextframe = TranslatePositionMsToFrame(nextpos, true);
1254
1255 if (nextpos > 10s)
1256 DoJumpToFrame(nextframe, kInaccuracyNone);
1257
1259 LOG(VB_PLAYBACK, LOG_INFO, LOC + "JumpToProgram - end");
1260}
#define Clear(a)
virtual std::chrono::milliseconds GetAudioBufferedTime(void)
report amount of audio buffered in milliseconds.
Definition: audiooutput.h:151
AudioOutput * GetAudioOutput(void) const
Return internal AudioOutput object.
Definition: audioplayer.h:100
bool IsPaused(void)
float GetStretchFactor(void) const
Definition: audioplayer.h:62
int GetSampleRate(void) const
Definition: audioplayer.h:58
void DeleteOutput(void)
int GetOrigChannels(void) const
Definition: audioplayer.h:57
AVCodecID GetCodec(void) const
Definition: audioplayer.h:56
A decoder for media files.
CommSkipMode GetAutoCommercialSkip(void) const
bool DoSkipCommercials(uint64_t &jumpToFrame, uint64_t framesPlayed, double video_frame_rate, uint64_t totalFrames, QString &comm_msg)
void LoadMap(PlayerContext *player_ctx, uint64_t framesPlayed)
bool HasMap(void) const
Definition: commbreakmap.h:25
bool AutoCommercialSkip(uint64_t &jumpToFrame, uint64_t framesPlayed, double video_frame_rate, uint64_t totalFrames, QString &comm_msg)
int GetSkipCommercials(void) const
Definition: commbreakmap.h:30
void SkipCommercials(int direction)
virtual QString GetRawEncodingType(void)
Definition: decoderbase.h:199
virtual uint GetTrackCount(uint Type)
void SetProgramInfo(const ProgramInfo &pginfo)
Definition: decoderbase.cpp:40
virtual QString GetCodecDecoderName(void) const =0
virtual void UpdateFramesPlayed(void)
void SetReadAdjust(long long adjust)
uint GetRawBitrate(void) const
Returns the estimated bitrate if the video were played at normal speed.
Definition: decoderbase.h:191
void SetWaitForChange(void)
bool GetWaitForChange(void) const
int GetfpsMultiplier(void) const
Definition: decoderbase.h:252
StreamInfo GetTrackInfo(uint Type, uint TrackNo)
EofState GetEof(void)
Definition: decoderbase.h:135
virtual double GetFPS(void) const
Definition: decoderbase.h:189
void UpdateOSD(uint64_t frame, double frame_rate, OSD *osd)
Show and update the edit mode On Screen Display.
Definition: deletemap.cpp:189
bool TrackerWantsToJump(uint64_t frame, uint64_t &to) const
Returns true if the given frame has passed the last cut point start and provides the frame number of ...
Definition: deletemap.cpp:860
bool IsEditing(void) const
Definition: deletemap.h:41
bool IsEmpty(void) const
Definition: deletemap.cpp:271
bool Detect(MythVideoFrame *Frame, float VideoAspect, AdjustFillMode &Current)
Detects if this frame is or is not letterboxed.
bool RecordCycleTime()
void SetNumCycles(int cycles)
QString GetLastCPUStats(void) const
Definition: jitterometer.h:55
float GetLastFPS(void) const
Definition: jitterometer.h:53
float GetLastSD(void) const
Definition: jitterometer.h:54
bool HasNext(void) const
std::chrono::seconds GetJumpPos(void)
Returns the jump position in seconds and clears it.
bool NeedsToSwitch(void) const
Returns true iff a switch is required but no jump is required m_jumppos sets to INT_MAX means not set...
Definition: livetvchain.h:66
void JumpToNext(bool up, std::chrono::seconds pos)
jump to the next (up == true) or previous (up == false) liveTV program If pos > 0: indicate the absol...
void SetProgram(const ProgramInfo &pginfo)
QString toString() const
ProgramInfo * GetSwitchProgram(bool &discont, bool &newtype, int &newid)
Returns the recording we should switch to.
std::chrono::seconds GetLengthAtCurPos(void)
bool NeedsToJump(void) const
Returns true iff a switch and jump are required.
Definition: livetvchain.h:69
QString GetInputType(int pos=-1) const
void EnableSubtitles(int Type, bool ForcedOnly=false)
MythScreenType * GetWindow(const QString &Window) override
void SendMessage(const QString &message)
double GetRefreshRate() const
std::chrono::microseconds GetRefreshInterval(std::chrono::microseconds Fallback) const
QSize GetResolution()
long long GetRealFileSize(void) const
QString GetStorageRate(void)
void Reset(bool Full=false, bool ToAdjust=false, bool ResetInternal=false)
Resets the read-ahead thread and our position in the file.
MythBufferType GetType() const
void ResetCommsError(void)
bool GetCommsError(void) const
void UpdateRawBitrate(uint RawBitrate)
Set the raw bit rate, to allow RingBuffer adjust effective bitrate.
void IgnoreLiveEOF(bool Ignore)
Tells RingBuffer whether to ignore the end-of-file.
QString GetSafeFilename(void)
void EnableBitrateMonitor(bool Enable)
virtual bool OpenFile(const QString &Filename, std::chrono::milliseconds Retry=kDefaultOpenTimeout)=0
uint GetBufferSize(void) const
QString GetAvailableBuffer(void)
QString GetDecoderRate(void)
virtual bool IsOpen(void) const =0
static QString BitrateToString(uint64_t Rate, bool Hz=false)
long long SetAdjustFilesize(void)
void Unpause(void)
Unpauses the read-ahead thread.
static constexpr std::chrono::milliseconds kLiveTVOpenTimeout
virtual bool Init(QRect Rect, float FontAspect)
void SetPlayer(MythPlayerUI *Player)
void GetAVSyncData(InfoMap &Map) const
std::chrono::microseconds AVSync(AudioPlayer *Audio, MythVideoFrame *Frame, std::chrono::microseconds FrameInterval, float PlaySpeed, bool HaveVideo, bool Force)
void SetRefreshInterval(std::chrono::microseconds interval)
void WaitForFrame(std::chrono::microseconds FrameDue)
std::chrono::milliseconds & DisplayTimecode()
virtual void SetTrack(uint Type, uint TrackNo)
InteractiveTV * GetInteractiveTV() override
void SetCaptionsEnabled(bool Enable, bool UpdateOSD=true)
MythCaptionsOverlay m_captionsOverlay
MythCaptionsState m_captionsState
void EnableSubtitles(bool Enable)
InteractiveTV * m_interactiveTV
void InitialiseState() override
QElapsedTimer m_editUpdateTimer
void UpdateOSDPosition()
Update the OSD status/position window.
void UpdateOSDMessage(const QString &Message)
void SetOSDStatus(const QString &Title, OSDTimeout Timeout)
QRecursiveMutex m_osdLock
MythPainter * m_painter
virtual void PreProcessNormalFrame()
MythDisplay * m_display
Definition: mythplayerui.h:72
void SwitchToProgram()
virtual void SetLastPlayPosition(uint64_t frame=0)
virtual void VideoStart()
MythPlayerUI(MythMainWindow *MainWindow, TV *Tv, PlayerContext *Context, PlayerFlags Flags)
QTimer m_osdDebugTimer
Definition: mythplayerui.h:70
bool StartPlaying()
void FileChanged()
void RenderVideoFrame(MythVideoFrame *Frame, FrameScanType Scan, bool Prepare, std::chrono::microseconds Wait)
void GetPlaybackData(InfoMap &Map)
virtual void InitialSeek()
virtual bool VideoLoop()
virtual void SetBookmark(bool Clear=false)
void InitFrameInterval() override
void ChangeOSDDebug()
virtual void DisplayPauseFrame()
virtual void EventStart()
bool CanSupportDoubleRate()
std::chrono::microseconds m_refreshInterval
Definition: mythplayerui.h:60
void RefreshPauseFrame()
void SetWatched(bool ForceWatched=false)
Determines if the recording should be considered watched.
void InitialiseState() override
void ChangeSpeed() override
void EnableBitrateMonitor(bool Enable=false)
void DoDisplayVideoFrame(MythVideoFrame *Frame, std::chrono::microseconds Due)
void GetCodecDescription(InfoMap &Map)
void JumpToStream(const QString &stream)
Jitterometer m_outputJmeter
Definition: mythplayerui.h:59
virtual void EventLoop()
virtual bool DisplayNormalFrame(bool CheckPrebuffer=true)
void ReinitVideo(bool ForceUpdate) override
void OSDDebugVisibilityChanged(bool Visible)
void JumpToProgram()
void UpdateOSDDebug()
void EnableFrameRateMonitor(bool Enable=false)
void SetVideoParams(int Width, int Height, double FrameRate, float Aspect, bool ForceUpdate, int ReferenceFrames, FrameScanType Scan=kScan_Ignore, const QString &CodecName=QString()) override
DetectLetterbox m_detectLetterBox
void CheckAspectRatio(MythVideoFrame *Frame)
bool InitVideo() override
void AutoVisualise(bool HaveVideo)
Enable visualisation if possible, there is no video and user has requested.
bool m_needNewPauseFrame
Definition: mythplayer.h:390
void SetEof(EofState eof)
void OpenDummy(void)
Definition: mythplayer.cpp:392
bool m_normalSpeed
Definition: mythplayer.h:493
bool FlagIsSet(PlayerFlags arg)
Definition: mythplayer.h:317
std::chrono::microseconds m_frameInterval
always adjusted for play_speed
Definition: mythplayer.h:486
long long m_rewindTime
Definition: mythplayer.h:427
bool m_inJumpToProgramPause
Definition: mythplayer.h:384
virtual void SetVideoParams(int w, int h, double fps, float aspect, bool ForceUpdate, int ReferenceFrames, FrameScanType=kScan_Ignore, const QString &codecName=QString())
Definition: mythplayer.cpp:318
virtual bool HasReachedEof(void) const
Definition: mythplayer.cpp:653
uint64_t TranslatePositionMsToFrame(std::chrono::milliseconds position, bool use_cutlist) const
Definition: mythplayer.h:256
bool m_decodeOneFrame
Definition: mythplayer.h:388
bool m_captionsEnabledbyDefault
This allows us to enable captions/subtitles later if the streams are not immediately available when t...
Definition: mythplayer.h:462
bool m_allPaused
Definition: mythplayer.h:393
bool m_disableForcedSubtitles
Definition: mythplayer.h:464
virtual void DecoderStart(bool start_paused)
bool UpdateFFRewSkip(float ffrewScale=1.0F)
DecoderBase * m_decoder
Definition: mythplayer.h:361
DeleteMap m_deleteMap
Definition: mythplayer.h:478
static const double kInaccuracyNone
Definition: mythplayer.h:238
void DoJumpToFrame(uint64_t frame, double inaccuracy)
AudioPlayer m_audio
Definition: mythplayer.h:472
uint64_t GetCurrentFrameCount(void) const
uint64_t m_framesPlayed
Definition: mythplayer.h:423
CommBreakMap m_commBreakMap
Definition: mythplayer.h:475
int m_fpsMultiplier
used to detect changes
Definition: mythplayer.h:487
void SeekingSlow(int Count)
long long CalcRWTime(long long rw) const
CalcRWTime(rw): rewind rw frames back.
void DiscardVideoFrames(bool KeyFrame, bool Flushed)
Places frames in the available frames queue.
Definition: mythplayer.cpp:642
virtual void ResetPlaying(bool resetframes=true)
Definition: mythplayer.cpp:916
virtual int OpenFile(int Retries=4)
Definition: mythplayer.cpp:414
virtual void InitFrameInterval()
Definition: mythplayer.cpp:691
bool m_isDummy
Definition: mythplayer.h:500
uint64_t m_bookmarkSeek
Definition: mythplayer.h:412
int m_jumpChapter
Definition: mythplayer.h:409
virtual long long CalcMaxFFTime(long long ff, bool setjump=true) const
CalcMaxFFTime(ffframes): forward ffframes forward.
bool m_forcePositionMapSync
Definition: mythplayer.h:476
bool m_renderOneFrame
Definition: mythplayer.h:389
int m_ffrewSkip
Definition: mythplayer.h:488
virtual void ReinitVideo(bool ForceUpdate)
Definition: mythplayer.cpp:291
std::chrono::seconds m_totalDuration
Definition: mythplayer.h:426
float m_nextPlaySpeed
Definition: mythplayer.h:483
void SetErrored(const QString &reason)
uint64_t m_totalFrames
Definition: mythplayer.h:424
bool m_videoPaused
Definition: mythplayer.h:392
bool IsNearEnd(void)
Returns true iff near end of recording.
bool IsWatchingInprogress(void) const
Definition: mythplayer.cpp:124
float m_playSpeed
Definition: mythplayer.h:484
bool m_enableForcedSubtitles
Definition: mythplayer.h:463
bool IsErrored(void) const
QSize m_videoDispDim
Video (input) width & height.
Definition: mythplayer.h:438
int m_endExitPrompt
Definition: mythplayer.h:413
bool volatile m_killDecoder
Definition: mythplayer.h:387
QSize m_videoDim
Video (input) buffer width & height.
Definition: mythplayer.h:439
virtual bool PrebufferEnoughFrames(int min_buffers=0)
Definition: mythplayer.cpp:717
void SeekingComplete()
MythPlayerAVSync m_avSync
Definition: mythplayer.h:430
void SetBuffering(bool new_buffering)
Definition: mythplayer.cpp:697
bool m_watchingRecording
Definition: mythplayer.h:403
bool IsReallyNearEnd(void) const
Returns true iff really near end of recording.
float m_videoAspect
Video (input) Apect Ratio.
Definition: mythplayer.h:441
bool Pause(void)
Definition: mythplayer.cpp:150
QThread * m_playerThread
Definition: mythplayer.h:367
virtual bool DoJumpChapter(int chapter)
int m_bufferingCounter
Definition: mythplayer.h:503
double m_videoFrameRate
Video (input) Frame Rate (often inaccurate)
Definition: mythplayer.h:435
void ClearAfterSeek(bool clearvideobuffers=true)
This is to support seeking...
virtual void ChangeSpeed(void)
long long m_ffTime
If m_ffTime>0, number of frames to seek forward.
Definition: mythplayer.h:418
std::chrono::milliseconds m_latestVideoTimecode
Definition: mythplayer.h:428
void SetPlayingInfo(const ProgramInfo &pginfo)
Definition: mythplayer.cpp:228
bool GetAllowForcedSubtitles(void) const
Definition: mythplayer.h:203
void UnpauseDecoder(void)
Definition: mythplayer.cpp:989
bool Play(float speed=1.0, bool normal=true, bool unpauseaudio=true)
Definition: mythplayer.cpp:183
bool m_hasFullPositionMap
Definition: mythplayer.h:405
void CheckTVChain()
Definition: mythplayer.cpp:930
void SetPlaying(bool is_playing)
Definition: mythplayer.cpp:239
PlayerContext * m_playerCtx
Definition: mythplayer.h:365
std::chrono::seconds m_totalLength
Definition: mythplayer.h:425
MythVideoOutput * m_videoOutput
Definition: mythplayer.h:363
void SeekingDone()
bool DoRewind(uint64_t frames, double inaccuracy)
void SetFrameInterval(FrameScanType scan, double frame_period)
Definition: mythplayer.cpp:681
QString GetEncodingType(void) const
EofState GetEof(void) const
std::chrono::milliseconds m_latestAudioTimecode
Definition: mythplayer.h:429
bool m_fileChanged
Definition: mythplayer.h:491
static const double kInaccuracyDefault
Definition: mythplayer.h:239
bool DoFastForward(uint64_t frames, double inaccuracy)
uint m_keyframeDist
Video (input) Number of frames between key frames (often inaccurate)
Definition: mythplayer.h:445
AdjustFillMode GetAdjustFill(void) const
void ToggleAdjustFill(AdjustFillMode AdjustFillMode=kAdjustFill_Toggle)
Sets up letterboxing for various standard video frame and monitor dimensions, then calls MoveResize()...
QRect GetDisplayVisibleRect(void) const
virtual void UpdatePauseFrame(std::chrono::milliseconds &, FrameScanType=kScan_Progressive)
Definition: mythvideoout.h:87
virtual void StartDisplayingFrame()
Tell GetLastShownFrame() to return the next frame from the head of the queue of frames to display.
virtual void GetOSDBounds(QRect &Total, QRect &Visible, float &VisibleAspect, float &FontScaling, float ThemeAspect) const
virtual int ValidVideoFrames() const
Returns number of frames that are fully decoded.
bool IsErrored() const
virtual void EndFrame()=0
virtual void PrepareFrame(MythVideoFrame *Frame, FrameScanType Scan=kScan_Ignore)=0
virtual long long GetFramesPlayed()
virtual void RenderEnd()=0
virtual MythVideoFrame * GetLastShownFrame()
Returns frame from the head of the ready to be displayed queue, if StartDisplayingFrame has been call...
int FreeVideoFrames()
Returns number of frames available for decoding onto.
virtual void SetFramesPlayed(long long FramesPlayed)
virtual void DoneDisplayingFrame(MythVideoFrame *Frame)
Releases frame returned from GetLastShownFrame() onto the queue of frames ready for decoding onto.
virtual void RenderFrame(MythVideoFrame *Frame, FrameScanType)=0
FrameScanType GetScanForDisplay(MythVideoFrame *Frame, bool &SecondField)
FrameScanType DetectInterlace(FrameScanType NewScan, float Rate, int VideoHeight)
void SetScanType(FrameScanType Scan, MythVideoOutput *VideoOutput, std::chrono::microseconds FrameInterval)
void CheckScanUpdate(MythVideoOutput *VideoOutput, std::chrono::microseconds FrameInterval)
FrameScanType GetScanType() const
void InitialiseScan(MythVideoOutput *VideoOutput)
virtual void AutoDeint(MythVideoFrame *Frame, MythVideoOutput *VideoOutput, std::chrono::microseconds FrameInterval, bool AllowLock=true)
Check whether deinterlacing should be enabled.
void ResetWindow(const QString &Window)
Definition: osd.cpp:651
bool Init(QRect Rect, float FontAspect) override
Definition: osd.cpp:52
void Draw()
Definition: osd.cpp:454
void HideWindow(const QString &Window) override
Definition: osd.cpp:690
void SetText(const QString &Window, const InfoMap &Map, OSDTimeout Timeout)
Definition: osd.cpp:208
void LockPlayingInfo(const char *file, int line) const
TVState GetState(void) const
void SetPlayerChangingBuffers(bool val)
Definition: playercontext.h:89
bool IsRecorderErrored(void) const
MythMediaBuffer * m_buffer
LiveTVChain * m_tvchain
void UnlockPlayingInfo(const char *file, int line) const
ProgramInfo * m_playingInfo
Currently playing info.
Holds information on recordings and videos.
Definition: programinfo.h:74
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
Definition: programinfo.h:380
void SetIgnoreProgStart(bool ignore)
If "ignore" is true QueryProgStart() will return 0, otherwise QueryProgStart() will return the progst...
Definition: programinfo.h:577
void SetIgnoreBookmark(bool ignore)
If "ignore" is true GetBookmark() will return 0, otherwise GetBookmark() will return the bookmark pos...
Definition: programinfo.h:570
void SaveWatched(bool watchedFlag)
Set "watched" field in recorded/videometadata to "watchedFlag".
void UpdateInUseMark(bool force=false)
QDateTime GetScheduledEndTime(void) const
The scheduled end time of the program.
Definition: programinfo.h:405
void SetIgnoreLastPlayPos(bool ignore)
If "ignore" is true QueryLastPlayPos() will return 0, otherwise QueryLastPlayPos() will return the la...
Definition: programinfo.h:585
bool IsRecording(void) const
Definition: programinfo.h:498
TranscodingStatus QueryTranscodeStatus(void) const
Returns the "transcoded" field in "recorded" table.
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
Definition: programinfo.h:412
void SaveLastPlayPos(uint64_t frame)
TODO Move to RecordingInfo.
QString MakeUniqueKey(void) const
Creates a unique string that can be used to identify an existing recording.
Definition: programinfo.h:346
QString GetPlaybackURL(bool checkMaster=false, bool forceCheckLocal=false)
Returns filename or URL to be used to play back this recording.
QDateTime GetRecordingEndTime(void) const
Approximate time the recording should have ended, did end, or is intended to end.
Definition: programinfo.h:420
void SaveBookmark(uint64_t frame)
Clears any existing bookmark in DB and if frame is greater than 0 sets a new bookmark.
bool m_forced
Subtitle and RawText.
Definition: decoderbase.h:108
void ChangeOSDDebug()
void UpdateLastPlayPosition(uint64_t frame)
void UpdateBookmark(bool Clear=false)
void InitialisePlayerState()
Control TV playback.
Definition: tv_play.h:156
#define setpriority(x, y, z)
Definition: compat.h:74
#define PRIO_PROCESS
Definition: compat.h:73
unsigned int uint
Definition: compat.h:60
EofState
Definition: decoderbase.h:68
@ kEofStateDelayed
Definition: decoderbase.h:70
@ kEofStateNone
Definition: decoderbase.h:69
@ kEofStateImmediate
Definition: decoderbase.h:71
@ kTrackTypeRawText
Definition: decoderbase.h:36
static constexpr const char * OSD_WIN_INTERACT
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
@ DEINT_SHADER
Definition: mythframe.h:73
@ DEINT_CPU
Definition: mythframe.h:72
static bool VERBOSE_LEVEL_CHECK(uint64_t mask, LogLevel_t level)
Definition: mythlogging.h:29
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
@ kMythBufferMHEG
PlayerFlags
Definition: mythplayer.h:64
@ kMusicChoice
Definition: mythplayer.h:75
@ kVideoIsNull
Definition: mythplayer.h:72
#define LOC
void SendMythSystemPlayEvent(const QString &msg, const ProgramInfo *pginfo)
QHash< QString, QString > InfoMap
Definition: mythtypes.h:15
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:15
def scan(profile, smoonURL, gate)
Definition: scan.py:54
@ kOSDTimeout_Short
Definition: osd.h:59
@ kOSDTimeout_None
Definition: osd.h:58
@ kOSDTimeout_Med
Definition: osd.h:60
static constexpr const char * OSD_WIN_MESSAGE
Definition: osd.h:29
static constexpr const char * OSD_WIN_DEBUG
Definition: osd.h:33
@ TRANSCODING_COMPLETE
Definition: programtypes.h:158
static eu8 clamp(eu8 value, eu8 low, eu8 high)
Definition: pxsup2dast.c:204
@ kCommSkipOff
Definition: tv.h:135
@ kState_WatchingPreRecorded
Watching Pre-recorded is a TV only state for when we are watching a pre-existing recording.
Definition: tv.h:70
@ kDisplayNone
Definition: videoouttypes.h:12
AdjustFillMode
Definition: videoouttypes.h:72
FrameScanType
Definition: videoouttypes.h:95
@ kScan_Intr2ndField
Definition: videoouttypes.h:99
@ kScan_Ignore
Definition: videoouttypes.h:96
@ kScan_Interlaced
Definition: videoouttypes.h:98
@ kScan_Detect
Definition: videoouttypes.h:97
@ kScan_Progressive
bool is_interlaced(FrameScanType Scan)