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
505 else if (DisplayNormalFrame())
506 {
509 else if (m_decoder && m_decoder->GetEof() != kEofStateNone)
511 else
512 m_framesPlayed = static_cast<uint64_t>(
514 }
515
516 return !IsErrored();
517}
518
520{
521 SetFrameInterval(GetScanType(), 1.0 / (m_videoFrameRate * static_cast<double>(m_playSpeed)));
523 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Display Refresh Rate: %1 Video Frame Rate: %2")
524 .arg(1000000.0 / m_refreshInterval.count(), 0, 'f', 3)
525 .arg(1000000.0 / m_frameInterval.count(), 0, 'f', 3));
526}
527
528void MythPlayerUI::RenderVideoFrame(MythVideoFrame *Frame, FrameScanType Scan, bool Prepare, std::chrono::microseconds Wait)
529{
530 if (!m_videoOutput)
531 return;
532
533 if (Prepare)
538 LOG(VB_PLAYBACK, LOG_DEBUG, QString("Clearing render one"));
539 m_renderOneFrame = false;
542 m_osd.Draw();
544
545 if (Wait > 0us)
547
549}
550
552{
553 m_fileChanged = false;
554 LOG(VB_PLAYBACK, LOG_INFO, LOC + "FileChanged");
555
556 Pause();
557 ChangeSpeed();
558 if (dynamic_cast<AvFormatDecoder *>(m_decoder))
559 m_playerCtx->m_buffer->Reset(false, true);
560 else
561 m_playerCtx->m_buffer->Reset(false, true, true);
563 Play();
564
566
567 m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
569 if (m_decoder)
571 m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
572
573 CheckTVChain();
575}
576
578{
580 {
582 {
584 m_needNewPauseFrame = false;
585
587 {
588 m_osdLock.lock();
589 LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("timecode video:%1 audio:%2")
590 .arg(m_latestVideoTimecode.count()).arg(m_latestAudioTimecode.count()));
591
592 // Use audio timecode when video timecode is not available for DVB audio recordings.
594 DeleteMap::UpdateOSD(timecode, &m_osd);
595 m_osdLock.unlock();
596 }
597 }
598 else
599 {
600 m_decodeOneFrame = true;
601 }
602 }
603}
604
605void MythPlayerUI::DoDisplayVideoFrame(MythVideoFrame* Frame, std::chrono::microseconds Due)
606{
607 if (Due < 0us)
608 {
609 m_videoOutput->SetFramesPlayed(static_cast<long long>(++m_framesPlayed));
611 LOG(VB_PLAYBACK, LOG_DEBUG, QString("Clearing render one"));
612 m_renderOneFrame = false;
613 }
614 else if (!FlagIsSet(kVideoIsNull) && Frame)
615 {
616
617 // Check scan type
618 bool showsecondfield = false;
619 FrameScanType ps = GetScanForDisplay(Frame, showsecondfield);
620
621 // if we get here, we're actually going to do video output
622 RenderVideoFrame(Frame, ps, true, Due);
623
624 // Only double rate CPU deinterlacers require an extra call to PrepareFrame
625 bool secondprepare = Frame->GetDoubleRateOption(DEINT_CPU) && !Frame->GetDoubleRateOption(DEINT_SHADER);
626 // and the first deinterlacing pass will have marked the frame as already deinterlaced
627 // which will break GetScanForDisplay below and subsequent deinterlacing
628 bool olddeinterlaced = Frame->m_alreadyDeinterlaced;
629 if (secondprepare)
630 Frame->m_alreadyDeinterlaced = false;
631 // Update scan settings now that deinterlacer has been set and we know
632 // whether we need a second field
633 ps = GetScanForDisplay(Frame, showsecondfield);
634
635 // Reset olddeinterlaced if necessary (pause frame etc)
636 if (!showsecondfield && secondprepare)
637 {
638 Frame->m_alreadyDeinterlaced = olddeinterlaced;
639 }
640 else if (showsecondfield)
641 {
642 // Second field
643 if (kScan_Interlaced == ps)
645 RenderVideoFrame(Frame, ps, secondprepare, Due + m_frameInterval / 2);
646 }
647 }
648 else
649 {
651 }
652}
653
655{
656 if (!m_videoOutput)
657 return;
658
660 {
661 SetErrored(tr("Serious error detected in Video Output"));
662 return;
663 }
664
665 // clear the buffering state
666 SetBuffering(false);
667
669 PreProcessNormalFrame(); // Allow interactiveTV to draw on pause frame
670
673 RenderVideoFrame(nullptr, scan, true, 0ms);
674}
675
676bool MythPlayerUI::DisplayNormalFrame(bool CheckPrebuffer)
677{
678 if (m_allPaused)
679 return false;
680
681 if (CheckPrebuffer && !PrebufferEnoughFrames())
682 return false;
683
684 // clear the buffering state
685 SetBuffering(false);
686
687 // retrieve the next frame
690
691 // Check aspect ratio
692 CheckAspectRatio(frame);
693
696
697 // Player specific processing (dvd, bd, mheg etc)
699
700 // handle scan type changes
702
703 // Detect letter boxing
704 // FIXME this is temporarily moved entirely into the main thread as there are
705 // too many threading issues and the decoder thread is not yet ready to handle
706 // QObject signals and slots.
707 // When refactoring is complete, move it into the decoder thread and
708 // signal switches via a new field in MythVideoFrame
711 {
713 ReinitOSD();
714 }
715
716 // When is the next frame due
717 std::chrono::microseconds due = m_avSync.AVSync(&m_audio, frame, m_frameInterval, m_playSpeed, !m_videoDim.isEmpty(),
719 // Display it
720 DoDisplayVideoFrame(frame, due);
723
724 return true;
725}
726
727void MythPlayerUI::SetVideoParams(int Width, int Height, double FrameRate, float Aspect,
728 bool ForceUpdate, int ReferenceFrames,
729 FrameScanType Scan, const QString &CodecName)
730{
731 MythPlayer::SetVideoParams(Width, Height, FrameRate, Aspect, ForceUpdate, ReferenceFrames,
732 Scan, CodecName);
733
734 // ensure deinterlacers are correctly reset after a change
735 UnlockScan();
736 FrameScanType newscan = DetectInterlace(Scan, static_cast<float>(m_videoFrameRate), m_videoDispDim.height());
738 ResetTracker();
739}
740
755void MythPlayerUI::SetWatched(bool ForceWatched)
756{
757 m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
759 {
760 m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
761 return;
762 }
763
764 uint64_t numFrames = GetCurrentFrameCount();
765
766 // For recordings we want to ignore the post-roll and account for
767 // in-progress recordings where totalFrames doesn't represent
768 // the full length of the recording. For videos we can only rely on
769 // totalFrames as duration metadata can be wrong
772 {
773
774 // If the recording is stopped early we need to use the recording end
775 // time, not the programme end time
777 qint64 starttime = pi->GetRecordingStartTime().toSecsSinceEpoch();
778 qint64 endactual = pi->GetRecordingEndTime().toSecsSinceEpoch();
779 qint64 endsched = pi->GetScheduledEndTime().toSecsSinceEpoch();
780 qint64 endtime = std::min(endactual, endsched);
781 numFrames = static_cast<uint64_t>((endtime - starttime) * m_videoFrameRate);
782 }
783
784 // 4 minutes min, 12 minutes max
785 auto offset = std::chrono::seconds(lround(0.14 * (numFrames / m_videoFrameRate)));
786 offset = std::clamp(offset, 240s, 720s);
787
788 if (ForceWatched || (m_framesPlayed > (numFrames - (offset.count() * m_videoFrameRate))))
789 {
791 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Marking recording as watched using offset %1 minutes")
792 .arg(offset.count()/60));
793 }
794
795 m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
796}
797
799{
800 m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
803 m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
804}
805
807{
808 m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
811 m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
812}
813
815{
816 // At this point we may not have the correct frame rate.
817 // Since interlaced is always at 25 or 30 fps, if the interval
818 // is less than 30000 (33fps) it must be representing one
819 // field and not one frame, so multiply by 2.
820 std::chrono::microseconds realfi = m_frameInterval;
821 if (m_frameInterval < 30ms)
822 realfi = m_frameInterval * 2;
823 return (duration_cast<floatusecs>(realfi) / 2.0) > (duration_cast<floatusecs>(m_refreshInterval) * 0.995);
824}
825
827{
828 QString samplerate = MythMediaBuffer::BitrateToString(static_cast<uint64_t>(m_audio.GetSampleRate()), true);
829 Map.insert("samplerate", samplerate);
830 Map.insert("filename", m_playerCtx->m_buffer->GetSafeFilename());
831 Map.insert("decoderrate", m_playerCtx->m_buffer->GetDecoderRate());
832 Map.insert("storagerate", m_playerCtx->m_buffer->GetStorageRate());
833 Map.insert("bufferavail", m_playerCtx->m_buffer->GetAvailableBuffer());
834 Map.insert("buffersize", QString::number(m_playerCtx->m_buffer->GetBufferSize() >> 20));
836
837 if (m_videoOutput)
838 {
839 QString frames = QString("%1/%2").arg(m_videoOutput->ValidVideoFrames())
841 Map.insert("videoframes", frames);
842 }
843 if (m_decoder)
844 Map["videodecoder"] = m_decoder->GetCodecDecoderName();
845
846 Map["framerate"] = QString("%1%2%3")
847 .arg(static_cast<double>(m_outputJmeter.GetLastFPS()), 0, 'f', 2).arg(QChar(0xB1, 0))
848 .arg(static_cast<double>(m_outputJmeter.GetLastSD()), 0, 'f', 2);
849 Map["load"] = m_outputJmeter.GetLastCPUStats();
850
852
853 QString displayfps = QString("%1x%2@%3Hz")
854 .arg(m_display->GetResolution().width())
855 .arg(m_display->GetResolution().height())
856 .arg(m_display->GetRefreshRate(), 0, 'f', 2);
857 Map["displayfps"] = displayfps;
858}
859
861{
862 Map["audiocodec"] = avcodec_get_name(m_audio.GetCodec());
863 Map["audiochannels"] = QString::number(m_audio.GetOrigChannels());
864
865 int width = m_videoDispDim.width();
866 int height = m_videoDispDim.height();
867 Map["videocodec"] = GetEncodingType();
868 if (m_decoder)
869 Map["videocodecdesc"] = m_decoder->GetRawEncodingType();
870 Map["videowidth"] = QString::number(width);
871 Map["videoheight"] = QString::number(height);
872 Map["videoframerate"] = QString::number(m_videoFrameRate, 'f', 2);
873 Map["deinterlacer"] = GetDeinterlacerName();
874
875 if (width < 640)
876 return;
877
878 bool interlaced = is_interlaced(GetScanType());
879 if (height > 2100)
880 Map["videodescrip"] = interlaced ? "UHD_4K_I" : "UHD_4K_P";
881 else if (width == 1920 || height == 1080 || height == 1088)
882 Map["videodescrip"] = interlaced ? "HD_1080_I" : "HD_1080_P";
883 else if ((width == 1280 || height == 720) && !interlaced)
884 Map["videodescrip"] = "HD_720_P";
885 else if (height >= 720)
886 Map["videodescrip"] = "HD";
887 else
888 Map["videodescrip"] = "SD";
889}
890
892{
894 if (Visible)
895 {
896 // This should already have enabled the required monitors
897 m_osdDebugTimer.start();
898 }
899 else
900 {
901 // If we have cleared/escaped the debug OSD screen, then ChangeOSDDebug
902 // is not called, so we need to ensure we turn off the monitors
903 m_osdDebugTimer.stop();
906 }
907}
908
910{
911 m_osdLock.lock();
912 InfoMap infoMap;
913 GetPlaybackData(infoMap);
916 m_osdLock.unlock();
917}
918
920{
921 m_osdLock.lock();
922 bool enable = !m_osdDebug;
923 EnableBitrateMonitor(enable);
925 if (enable)
927 else
929 m_osdDebug = enable;
930 m_osdLock.unlock();
931}
932
934{
935 bool enable = VERBOSE_LEVEL_CHECK(VB_PLAYBACK, LOG_ANY) || Enable;
936 m_outputJmeter.SetNumCycles(enable ? static_cast<int>(m_videoFrameRate) : 0);
937}
938
940{
943}
944
945/* JumpToStream, JumpToProgram and SwitchToProgram all need to be moved into the
946 * parent object and hopefully simplified. The fairly involved logic does not
947 * sit well with the new design objectives for the player classes and are better
948 * suited to the high level logic in TV.
949 */
950void MythPlayerUI::JumpToStream(const QString &stream)
951{
952 LOG(VB_PLAYBACK, LOG_INFO, LOC + "JumpToStream - begin");
953
954 // Shouldn't happen
955 if (stream.isEmpty())
956 return;
957
958 Pause();
960
961 ProgramInfo pginfo(stream);
962 SetPlayingInfo(pginfo);
963
966 else
967 m_playerCtx->m_buffer->OpenFile(stream);
968
969 if (!m_playerCtx->m_buffer->IsOpen())
970 {
971 LOG(VB_GENERAL, LOG_ERR, LOC + "JumpToStream buffer OpenFile failed");
973 SetErrored(tr("Error opening remote stream buffer"));
974 return;
975 }
976
977 m_watchingRecording = false;
978 m_totalLength = 0s;
979 m_totalFrames = 0;
980 m_totalDuration = 0s;
981
982 // 120 retries ~= 60 seconds
983 if (OpenFile(120) < 0)
984 {
985 LOG(VB_GENERAL, LOG_ERR, LOC + "JumpToStream OpenFile failed.");
987 SetErrored(tr("Error opening remote stream"));
988 return;
989 }
990
991 if (m_totalLength == 0s)
992 {
993 long long len = m_playerCtx->m_buffer->GetRealFileSize();
994 m_totalLength = std::chrono::seconds(len / ((m_decoder->GetRawBitrate() * 1000) / 8));
995 m_totalFrames = static_cast<uint64_t>(m_totalLength.count() * SafeFPS());
996 }
997
998 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("JumpToStream length %1 bytes @ %2 Kbps = %3 Secs, %4 frames @ %5 fps")
1000 .arg(m_totalLength.count()).arg(m_totalFrames).arg(m_decoder->GetFPS()) );
1001
1003
1004 // the bitrate is reset by m_playerCtx->m_buffer->OpenFile()...
1006 m_decoder->SetProgramInfo(pginfo);
1007
1008 Play();
1009 ChangeSpeed();
1010
1012#if CONFIG_MHEG
1013 if (m_interactiveTV) m_interactiveTV->StreamStarted();
1014#endif
1015
1016 LOG(VB_PLAYBACK, LOG_INFO, LOC + "JumpToStream - end");
1017}
1018
1020{
1021 if (!IsReallyNearEnd())
1022 return;
1023
1024 LOG(VB_PLAYBACK, LOG_INFO, LOC + "SwitchToProgram - start");
1025 bool discontinuity = false;
1026 bool newtype = false;
1027 int newid = -1;
1028 ProgramInfo *pginfo = m_playerCtx->m_tvchain->GetSwitchProgram(discontinuity, newtype, newid);
1029 if (!pginfo)
1030 return;
1031
1032 bool newIsDummy = m_playerCtx->m_tvchain->GetInputType(newid) == "DUMMY";
1033
1034 SetPlayingInfo(*pginfo);
1035 Pause();
1036 ChangeSpeed();
1037
1038 // Release all frames to ensure the current decoder resources are released
1039 DiscardVideoFrames(true, true);
1040
1041 if (newIsDummy)
1042 {
1043 OpenDummy();
1044 ResetPlaying();
1046 delete pginfo;
1047 return;
1048 }
1049
1051 {
1052 // Restore original ringbuffer
1053 auto *ic = dynamic_cast<MythInteractiveBuffer*>(m_playerCtx->m_buffer);
1054 if (ic)
1055 m_playerCtx->m_buffer = ic->TakeBuffer();
1056 delete ic;
1057 }
1058
1060
1061 if (!m_playerCtx->m_buffer->IsOpen())
1062 {
1063 LOG(VB_GENERAL, LOG_ERR, LOC + QString("SwitchToProgram's OpenFile failed (input type: %1)")
1064 .arg(m_playerCtx->m_tvchain->GetInputType(newid)));
1065 LOG(VB_GENERAL, LOG_ERR, m_playerCtx->m_tvchain->toString());
1067 SetErrored(tr("Error opening switch program buffer"));
1068 delete pginfo;
1069 return;
1070 }
1071
1072 if (GetEof() != kEofStateNone)
1073 {
1074 discontinuity = true;
1075 ResetCaptions();
1076 }
1077
1078 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("SwitchToProgram(void) "
1079 "discont: %1 newtype: %2 newid: %3 decoderEof: %4")
1080 .arg(discontinuity).arg(newtype).arg(newid).arg(GetEof()));
1081
1082 if (discontinuity || newtype)
1083 {
1084 m_playerCtx->m_tvchain->SetProgram(*pginfo);
1085 if (m_decoder)
1086 m_decoder->SetProgramInfo(*pginfo);
1087
1088 m_playerCtx->m_buffer->Reset(true);
1089 if (newtype)
1090 {
1091 if (OpenFile() < 0)
1092 SetErrored(tr("Error opening switch program file"));
1093 }
1094 else
1095 {
1096 ResetPlaying();
1097 }
1098 }
1099 else
1100 {
1102 if (m_decoder)
1103 {
1106 }
1107 }
1108 delete pginfo;
1109
1110 if (IsErrored())
1111 {
1112 LOG(VB_GENERAL, LOG_ERR, LOC + "SwitchToProgram failed.");
1114 return;
1115 }
1116
1118
1119 // the bitrate is reset by m_playerCtx->m_buffer->OpenFile()...
1120 if (m_decoder)
1123
1124 if (discontinuity || newtype)
1125 {
1126 CheckTVChain();
1128 }
1129
1130 Play();
1131 LOG(VB_PLAYBACK, LOG_INFO, LOC + "SwitchToProgram - end");
1132}
1133
1135{
1136 LOG(VB_PLAYBACK, LOG_INFO, LOC + "JumpToProgram - start");
1137 bool discontinuity = false;
1138 bool newtype = false;
1139 int newid = -1;
1140 std::chrono::seconds nextpos = m_playerCtx->m_tvchain->GetJumpPos();
1141 ProgramInfo *pginfo = m_playerCtx->m_tvchain->GetSwitchProgram(discontinuity, newtype, newid);
1142 if (!pginfo)
1143 return;
1144
1146
1147 bool newIsDummy = m_playerCtx->m_tvchain->GetInputType(newid) == "DUMMY";
1148 SetPlayingInfo(*pginfo);
1149
1150 Pause();
1151 ChangeSpeed();
1152 ResetCaptions();
1153
1154 // Release all frames to ensure the current decoder resources are released
1155 DiscardVideoFrames(true, true);
1156
1157 m_playerCtx->m_tvchain->SetProgram(*pginfo);
1158 m_playerCtx->m_buffer->Reset(true);
1159
1160 if (newIsDummy)
1161 {
1162 OpenDummy();
1163 ResetPlaying();
1165 delete pginfo;
1166 m_inJumpToProgramPause = false;
1167 return;
1168 }
1169
1170 SendMythSystemPlayEvent("PLAY_CHANGED", pginfo);
1171
1173 {
1174 // Restore original ringbuffer
1175 auto *ic = dynamic_cast<MythInteractiveBuffer*>(m_playerCtx->m_buffer);
1176 if (ic)
1177 m_playerCtx->m_buffer = ic->TakeBuffer();
1178 delete ic;
1179 }
1180
1182 if (!m_playerCtx->m_buffer->IsOpen())
1183 {
1184 LOG(VB_GENERAL, LOG_ERR, LOC + QString("JumpToProgram's OpenFile failed (input type: %1)")
1185 .arg(m_playerCtx->m_tvchain->GetInputType(newid)));
1186 LOG(VB_GENERAL, LOG_ERR, m_playerCtx->m_tvchain->toString());
1188 SetErrored(tr("Error opening jump program file buffer"));
1189 delete pginfo;
1190 m_inJumpToProgramPause = false;
1191 return;
1192 }
1193
1195
1196 bool wasDummy = m_isDummy;
1197 if (newtype || wasDummy)
1198 {
1199 if (OpenFile() < 0)
1200 SetErrored(tr("Error opening jump program file"));
1201 }
1202 else
1203 {
1204 ResetPlaying();
1205 }
1206
1207 if (IsErrored() || !m_decoder)
1208 {
1209 LOG(VB_GENERAL, LOG_ERR, LOC + "JumpToProgram failed.");
1210 if (!IsErrored())
1211 SetErrored(tr("Error reopening video decoder"));
1212 delete pginfo;
1213 m_inJumpToProgramPause = false;
1214 return;
1215 }
1216
1218
1219 // the bitrate is reset by m_playerCtx->m_buffer->OpenFile()...
1222
1223 m_decoder->SetProgramInfo(*pginfo);
1224 delete pginfo;
1225
1226 CheckTVChain();
1228 m_inJumpToProgramPause = false;
1229 Play();
1230 ChangeSpeed();
1231
1232 // check that we aren't too close to the end of program.
1233 // and if so set it to 10s from the end if completed recordings
1234 // or 3s if live
1235 std::chrono::seconds duration = m_playerCtx->m_tvchain->GetLengthAtCurPos();
1236 std::chrono::seconds maxpos = m_playerCtx->m_tvchain->HasNext() ? 10s : 3s;
1237
1238 if (nextpos > (duration - maxpos))
1239 {
1240 nextpos = duration - maxpos;
1241 if (nextpos < 0s)
1242 nextpos = 0s;
1243 }
1244 else if (nextpos < 0s)
1245 {
1246 // it's a relative position to the end
1247 nextpos += duration;
1248 }
1249
1250 // nextpos is the new position to use in seconds
1251 uint64_t nextframe = TranslatePositionMsToFrame(nextpos, true);
1252
1253 if (nextpos > 10s)
1254 DoJumpToFrame(nextframe, kInaccuracyNone);
1255
1257 LOG(VB_PLAYBACK, LOG_INFO, LOC + "JumpToProgram - end");
1258}
#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)
Definition: audioplayer.cpp:95
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:177
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:846
bool IsEditing(void) const
Definition: deletemap.h:41
bool IsEmpty(void) const
Definition: deletemap.cpp:259
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:650
bool Init(QRect Rect, float FontAspect) override
Definition: osd.cpp:51
void Draw()
Definition: osd.cpp:453
void HideWindow(const QString &Window) override
Definition: osd.cpp:689
void SetText(const QString &Window, const InfoMap &Map, OSDTimeout Timeout)
Definition: osd.cpp:207
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:206
@ 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)