MythTV master
mythplayerui.cpp
Go to the documentation of this file.
1#include <algorithm>
2
3// MythTV
8
11#include "livetvchain.h"
13#include "mheg/interactivetv.h"
14#include "mythplayerui.h"
15#include "mythsystemevent.h"
16#include "osd.h"
17#include "tv_play.h"
18
19#define LOC QString("PlayerUI: ")
20
22 PlayerContext *Context, PlayerFlags Flags)
23 : MythPlayerEditorUI(MainWindow, Tv, Context, Flags),
25 m_display(MainWindow->GetDisplay())
26{
27 // Finish setting up the overlays
28 m_osd.SetPlayer(this);
30
31 // User feedback during slow seeks
32 connect(this, &MythPlayerUI::SeekingSlow, [&](int Count)
33 {
34 UpdateOSDMessage(tr("Searching") + QString().fill('.', Count % 3), kOSDTimeout_Short);
36 });
37
38 // Seeking has finished; remove slow seek user feedback window
39 connect(this, &MythPlayerUI::SeekingComplete, [&]()
40 {
41 m_osdLock.lock();
43 m_osdLock.unlock();
44 });
45
46 // Seeking has finished; update position on OSD
47 connect(this, &MythPlayerUI::SeekingDone, [&]()
48 {
50 });
51
52 // Setup OSD debug
53 m_osdDebugTimer.setInterval(1s);
56
57 // Other connections
61
62 // Setup refresh interval.
65}
66
68{
69 LOG(VB_GENERAL, LOG_INFO, LOC + "Initialising player state");
71}
72
74{
75 if (OpenFile() < 0)
76 {
77 LOG(VB_GENERAL, LOG_ERR, LOC + "Unable to open video file.");
78 return false;
79 }
80
84 m_jumpChapter = 0;
87
88 if (!InitVideo())
89 {
90 LOG(VB_GENERAL, LOG_ERR, LOC + "Unable to initialize video.");
92 return false;
93 }
94
95 EventStart();
96 DecoderStart(true);
98 VideoStart();
99
100 m_playerThread->setPriority(QThread::TimeCriticalPriority);
101#ifdef Q_OS_ANDROID
102 setpriority(PRIO_PROCESS, m_playerThreadId, -20);
103#endif
106 return !IsErrored();
107}
108
110{
111 // TODO handle initial commskip and/or cutlist skip as well
112 if (m_bookmarkSeek > 30)
114}
115
117{
118 // Handle decoder callbacks
120
121 // Live TV program change
122 if (m_fileChanged)
123 FileChanged();
124
125 // Check if visualiser is wanted on first start and after video change
127 AutoVisualise(!m_videoDim.isEmpty());
128
129 // recreate the osd if a reinit was triggered by another thread
130 if (m_reinitOsd)
131 ReinitOSD();
132
133 // enable/disable forced subtitles if signalled by the decoder
138
139 // reset the scan (and hence deinterlacers) if triggered by the decoder
141
142 // refresh the position map for an in-progress recording while editing
144 {
145 if (m_editUpdateTimer.hasExpired(2000))
146 {
147 // N.B. the positionmap update and osd refresh are asynchronous
149 m_osdLock.lock();
151 m_osdLock.unlock();
152 m_editUpdateTimer.start();
153 }
154 }
155
156 // Refresh the programinfo in use status
157 m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
160 m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
161
162 // Disable timestretch if we are too close to the end of the buffer
163 if (m_ffrewSkip == 1 && (m_playSpeed > 1.0F) && IsNearEnd())
164 {
165 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Near end, Slowing down playback.");
166 Play(1.0F, true, true);
167 }
168
170 {
171 // Switch from the dummy recorder to the tuned program in livetv
172 m_playerCtx->m_tvchain->JumpToNext(true, 0s);
174 }
175 else if ((!m_allPaused || GetEof() != kEofStateNone) &&
178 {
179 // Switch to the next program in livetv
182 }
183
184 // Jump to the next program in livetv
186 {
188 }
189
190 // Change interactive stream if requested
191 if (!m_newStream.isEmpty())
192 {
194 m_newStream = QString();
195 }
196
197 // Disable fastforward if we are too close to the end of the buffer
198 if (m_ffrewSkip > 1 && (CalcMaxFFTime(100, false) < 100))
199 {
200 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Near end, stopping fastforward.");
201 Play(1.0F, true, true);
202 }
203
204 // Disable rewind if we are too close to the beginning of the buffer
205 if (m_ffrewSkip < 0 && CalcRWTime(-m_ffrewSkip) >= 0 &&
207 {
208 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Near start, stopping rewind.");
209 float stretch = (m_ffrewSkip > 0) ? 1.0F : m_audio.GetStretchFactor();
210 Play(stretch, true, true);
211 }
212
213 // Check for error
215 {
216 LOG(VB_GENERAL, LOG_ERR, LOC + "Unknown recorder error, exiting decoder");
217 if (!IsErrored())
218 SetErrored(tr("Irrecoverable recorder error"));
219 m_killDecoder = true;
220 return;
221 }
222
223 // Handle speed change
224 if (!qFuzzyCompare(m_playSpeed + 1.0F, m_nextPlaySpeed + 1.0F) &&
226 {
227 ChangeSpeed();
228 return;
229 }
230
231 // Check if we got a communication error, and if so pause playback
233 {
234 Pause();
236 }
237
238 // Handle end of file
239 EofState eof = GetEof();
240 if (HasReachedEof())
241 {
242#if CONFIG_MHEG
243 if (m_interactiveTV && m_interactiveTV->StreamStarted(false))
244 {
245 Pause();
246 return;
247 }
248#endif
250 {
251 LOG(VB_GENERAL, LOG_NOTICE, LOC + "LiveTV forcing JumpTo 1");
252 m_playerCtx->m_tvchain->JumpToNext(true, 0s);
253 return;
254 }
255
256 bool drained = false;
258 {
259 // We have audio only or mostly audio content. Exit when
260 // the audio is drained.
261 drained =
263 m_audio.IsPaused() ||
265 }
266 else
267 {
268 // We have normal or video only content. Exit when the
269 // video is drained.
271 }
272 if (eof != kEofStateDelayed || drained)
273 {
274 if (eof == kEofStateDelayed)
275 {
276 LOG(VB_PLAYBACK, LOG_INFO,
277 QString("waiting for no video frames %1")
279 }
280 LOG(VB_PLAYBACK, LOG_INFO,
281 QString("HasReachedEof() at framesPlayed=%1 totalFrames=%2")
283 Pause();
284 SetPlaying(false);
285 return;
286 }
287 }
288
289 // Handle rewind
290 if (m_rewindTime > 0 && (m_ffrewSkip == 1 || m_ffrewSkip == 0))
291 {
293 if (m_rewindTime > 0)
294 DoRewind(static_cast<uint64_t>(m_rewindTime), kInaccuracyDefault);
295 }
296
297 // Handle fast forward
298 if (m_ffTime > 0 && (m_ffrewSkip == 1 || m_ffrewSkip == 0))
299 {
301 if (m_ffTime > 0)
302 {
303 DoFastForward(static_cast<uint64_t>(m_ffTime), kInaccuracyDefault);
304 if (GetEof() != kEofStateNone)
305 return;
306 }
307 }
308
309 // Handle chapter jump
310 if (m_jumpChapter != 0)
312
313 // Handle commercial skipping
314 if (m_commBreakMap.GetSkipCommercials() != 0 && (m_ffrewSkip == 1))
315 {
316 if (!m_commBreakMap.HasMap())
317 {
318 //: The commercials/adverts have not been flagged
319 SetOSDStatus(tr("Not Flagged"), kOSDTimeout_Med);
320 QString message = "COMMFLAG_REQUEST ";
321 m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
322 message += QString("%1").arg(m_playerCtx->m_playingInfo->GetChanID()) +
324 m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
325 gCoreContext->SendMessage(message);
326 }
327 else
328 {
329 QString msg;
330 uint64_t jumpto = 0;
331 uint64_t frameCount = GetCurrentFrameCount();
332 // XXX CommBreakMap should use duration map not m_videoFrameRate
335 frameCount, msg);
336 if (!msg.isEmpty())
338 if (jump)
340 }
342 return;
343 }
344
345 // Handle automatic commercial skipping
346 uint64_t jumpto = 0;
347 if (m_deleteMap.IsEmpty() && (m_ffrewSkip == 1) &&
350 {
351 QString msg;
352 uint64_t frameCount = GetCurrentFrameCount();
353 // XXX CommBreakMap should use duration map not m_videoFrameRate
356 frameCount, msg);
357 if (!msg.isEmpty())
359 if (jump)
361 }
362
363 // Handle cutlist skipping
364 if (!m_allPaused && (m_ffrewSkip == 1) &&
366 {
367 if (jumpto == m_totalFrames)
368 {
371 }
372 else
373 {
375 }
376 }
377}
378
380{
381#if CONFIG_MHEG
382 // handle Interactive TV
383 if (GetInteractiveTV())
384 {
385 m_osdLock.lock();
386 m_itvLock.lock();
387 auto *window = qobject_cast<InteractiveScreen *>(m_captionsOverlay.GetWindow(OSD_WIN_INTERACT));
388 if ((m_interactiveTV->ImageHasChanged() || !m_itvVisible) && window)
389 {
390 m_interactiveTV->UpdateOSD(window, m_painter);
391 m_itvVisible = true;
392 }
393 m_itvLock.unlock();
394 m_osdLock.unlock();
395 }
396#endif // CONFIG_MHEG
397}
398
400{
402 // ensure we re-check double rate support following a speed change
403 UnlockScan();
404}
405
406void MythPlayerUI::ReinitVideo(bool ForceUpdate)
407{
408 MythPlayer::ReinitVideo(ForceUpdate);
409
410 // Signal to the main thread to reinit OSD
411 m_reinitOsd = true;
412
413 // Signal to main thread to reinit subtitles
415 emit EnableSubtitles(true);
416
417 // Signal to the main thread to check auto visualise
419}
420
422{
423 QRect visible;
424 QRect total;
425 float aspect = NAN;
426 float scaling = NAN;
427
428 m_osdLock.lock();
429 m_videoOutput->GetOSDBounds(total, visible, aspect, scaling, 1.0F);
430 m_osd.Init(visible, aspect);
431 m_captionsOverlay.Init(visible, aspect);
433
434#if CONFIG_MHEG
435 if (GetInteractiveTV())
436 {
437 QMutexLocker locker(&m_itvLock);
438 m_interactiveTV->Reinit(total, visible, aspect);
439 }
440#endif // CONFIG_MHEG
441
442 // If there is a forced text subtitle track (which is possible
443 // in e.g. a .mkv container), and forced subtitles are
444 // allowed, then start playback with that subtitle track
445 // selected. Otherwise, use the frontend settings to decide
446 // which captions/subtitles (if any) to enable at startup.
447 // TODO: modify the fix to #10735 to use this approach
448 // instead.
449 bool hasForcedTextTrack = false;
450 uint forcedTrackNumber = 0;
452 {
454 for (uint i = 0; !hasForcedTextTrack && i < numTextTracks; ++i)
455 {
457 {
458 hasForcedTextTrack = true;
459 forcedTrackNumber = i;
460 }
461 }
462 }
463 if (hasForcedTextTrack)
464 SetTrack(kTrackTypeRawText, forcedTrackNumber);
465 else
467
468 m_osdLock.unlock();
469
470 SetPlaying(true);
471 ClearAfterSeek(false);
474
477 AutoVisualise(!m_videoDim.isEmpty());
478}
479
481{
482 m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
483 {
485 {
486 // When initial playback gets underway, we override the ProgramInfo
487 // flags such that future calls to GetBookmark() will consider only
488 // an actual bookmark and not progstart or lastplaypos information.
492 }
493 }
494 m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
496}
497
499{
501
504 else if (DisplayNormalFrame())
505 {
508 else if (m_decoder && m_decoder->GetEof() != kEofStateNone)
510 else
511 m_framesPlayed = static_cast<uint64_t>(
513 }
514
515 return !IsErrored();
516}
517
519{
520 SetFrameInterval(GetScanType(), 1.0 / (m_videoFrameRate * static_cast<double>(m_playSpeed)));
522 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Display Refresh Rate: %1 Video Frame Rate: %2")
523 .arg(1000000.0 / m_refreshInterval.count(), 0, 'f', 3)
524 .arg(1000000.0 / m_frameInterval.count(), 0, 'f', 3));
525}
526
527void MythPlayerUI::RenderVideoFrame(MythVideoFrame *Frame, FrameScanType Scan, bool Prepare, std::chrono::microseconds Wait)
528{
529 if (!m_videoOutput)
530 return;
531
532 if (Prepare)
537 LOG(VB_PLAYBACK, LOG_DEBUG, QString("Clearing render one"));
538 m_renderOneFrame = false;
541 m_osd.Draw();
543
544 if (Wait > 0us)
546
548}
549
551{
552 m_fileChanged = false;
553 LOG(VB_PLAYBACK, LOG_INFO, LOC + "FileChanged");
554
555 Pause();
556 ChangeSpeed();
557 if (dynamic_cast<AvFormatDecoder *>(m_decoder))
558 m_playerCtx->m_buffer->Reset(false, true);
559 else
560 m_playerCtx->m_buffer->Reset(false, true, true);
562 Play();
563
565
566 m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
568 if (m_decoder)
570 m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
571
572 CheckTVChain();
574}
575
577{
579 {
581 {
583 m_needNewPauseFrame = false;
584
586 {
587 m_osdLock.lock();
588 LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("timecode video:%1 audio:%2")
589 .arg(m_latestVideoTimecode.count()).arg(m_latestAudioTimecode.count()));
590
591 // Use audio timecode when video timecode is not available for DVB audio recordings.
593 DeleteMap::UpdateOSD(timecode, &m_osd);
594 m_osdLock.unlock();
595 }
596 }
597 else
598 {
599 m_decodeOneFrame = true;
600 }
601 }
602}
603
604void MythPlayerUI::DoDisplayVideoFrame(MythVideoFrame* Frame, std::chrono::microseconds Due)
605{
606 if (Due < 0us)
607 {
608 m_videoOutput->SetFramesPlayed(static_cast<long long>(++m_framesPlayed));
610 LOG(VB_PLAYBACK, LOG_DEBUG, QString("Clearing render one"));
611 m_renderOneFrame = false;
612 }
613 else if (!FlagIsSet(kVideoIsNull) && Frame)
614 {
615
616 // Check scan type
617 bool showsecondfield = false;
618 FrameScanType ps = GetScanForDisplay(Frame, showsecondfield);
619
620 // if we get here, we're actually going to do video output
621 RenderVideoFrame(Frame, ps, true, Due);
622
623 // Only double rate CPU deinterlacers require an extra call to PrepareFrame
624 bool secondprepare = Frame->GetDoubleRateOption(DEINT_CPU) && !Frame->GetDoubleRateOption(DEINT_SHADER);
625 // and the first deinterlacing pass will have marked the frame as already deinterlaced
626 // which will break GetScanForDisplay below and subsequent deinterlacing
627 bool olddeinterlaced = Frame->m_alreadyDeinterlaced;
628 if (secondprepare)
629 Frame->m_alreadyDeinterlaced = false;
630 // Update scan settings now that deinterlacer has been set and we know
631 // whether we need a second field
632 ps = GetScanForDisplay(Frame, showsecondfield);
633
634 // Reset olddeinterlaced if necessary (pause frame etc)
635 if (!showsecondfield && secondprepare)
636 {
637 Frame->m_alreadyDeinterlaced = olddeinterlaced;
638 }
639 else if (showsecondfield)
640 {
641 // Second field
642 if (kScan_Interlaced == ps)
644 RenderVideoFrame(Frame, ps, secondprepare, Due + m_frameInterval / 2);
645 }
646 }
647 else
648 {
650 }
651}
652
654{
655 if (!m_videoOutput)
656 return;
657
659 {
660 SetErrored(tr("Serious error detected in Video Output"));
661 return;
662 }
663
664 // clear the buffering state
665 SetBuffering(false);
666
668 PreProcessNormalFrame(); // Allow interactiveTV to draw on pause frame
669
672 RenderVideoFrame(nullptr, scan, true, 0ms);
673}
674
675bool MythPlayerUI::DisplayNormalFrame(bool CheckPrebuffer)
676{
677 if (m_allPaused)
678 return false;
679
680 if (CheckPrebuffer && !PrebufferEnoughFrames())
681 return false;
682
683 // clear the buffering state
684 SetBuffering(false);
685
686 // retrieve the next frame
689
690 // Check aspect ratio
691 CheckAspectRatio(frame);
692
695
696 // Player specific processing (dvd, bd, mheg etc)
698
699 // handle scan type changes
701
702 // Detect letter boxing
703 // FIXME this is temporarily moved entirely into the main thread as there are
704 // too many threading issues and the decoder thread is not yet ready to handle
705 // QObject signals and slots.
706 // When refactoring is complete, move it into the decoder thread and
707 // signal switches via a new field in MythVideoFrame
710 {
712 ReinitOSD();
713 }
714
715 // When is the next frame due
716 std::chrono::microseconds due = m_avSync.AVSync(&m_audio, frame, m_frameInterval, m_playSpeed, !m_videoDim.isEmpty(),
718 // Display it
719 DoDisplayVideoFrame(frame, due);
722
723 return true;
724}
725
726void MythPlayerUI::SetVideoParams(int Width, int Height, double FrameRate, float Aspect,
727 bool ForceUpdate, int ReferenceFrames,
728 FrameScanType Scan, const QString &CodecName)
729{
730 MythPlayer::SetVideoParams(Width, Height, FrameRate, Aspect, ForceUpdate, ReferenceFrames,
731 Scan, CodecName);
732
733 // ensure deinterlacers are correctly reset after a change
734 UnlockScan();
735 FrameScanType newscan = DetectInterlace(Scan, static_cast<float>(m_videoFrameRate), m_videoDispDim.height());
737 ResetTracker();
738}
739
754void MythPlayerUI::SetWatched(bool ForceWatched)
755{
756 m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
758 {
759 m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
760 return;
761 }
762
763 uint64_t numFrames = GetCurrentFrameCount();
764
765 // For recordings we want to ignore the post-roll and account for
766 // in-progress recordings where totalFrames doesn't represent
767 // the full length of the recording. For videos we can only rely on
768 // totalFrames as duration metadata can be wrong
771 {
772
773 // If the recording is stopped early we need to use the recording end
774 // time, not the programme end time
776 qint64 starttime = pi->GetRecordingStartTime().toSecsSinceEpoch();
777 qint64 endactual = pi->GetRecordingEndTime().toSecsSinceEpoch();
778 qint64 endsched = pi->GetScheduledEndTime().toSecsSinceEpoch();
779 qint64 endtime = std::min(endactual, endsched);
780 numFrames = static_cast<uint64_t>((endtime - starttime) * m_videoFrameRate);
781 }
782
783 // 4 minutes min, 12 minutes max
784 auto offset = std::chrono::seconds(lround(0.14 * (numFrames / m_videoFrameRate)));
785 offset = std::clamp(offset, 240s, 720s);
786
787 if (ForceWatched || (m_framesPlayed > (numFrames - (offset.count() * m_videoFrameRate))))
788 {
790 LOG(VB_GENERAL, LOG_INFO, LOC + QString("Marking recording as watched using offset %1 minutes")
791 .arg(offset.count()/60));
792 }
793
794 m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
795}
796
798{
799 m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
802 m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
803}
804
806{
807 m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
810 m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
811}
812
814{
815 // At this point we may not have the correct frame rate.
816 // Since interlaced is always at 25 or 30 fps, if the interval
817 // is less than 30000 (33fps) it must be representing one
818 // field and not one frame, so multiply by 2.
819 std::chrono::microseconds realfi = m_frameInterval;
820 if (m_frameInterval < 30ms)
821 realfi = m_frameInterval * 2;
822 return (duration_cast<floatusecs>(realfi) / 2.0) > (duration_cast<floatusecs>(m_refreshInterval) * 0.995);
823}
824
826{
827 QString samplerate = MythMediaBuffer::BitrateToString(static_cast<uint64_t>(m_audio.GetSampleRate()), true);
828 Map.insert("samplerate", samplerate);
829 Map.insert("filename", m_playerCtx->m_buffer->GetSafeFilename());
830 Map.insert("decoderrate", m_playerCtx->m_buffer->GetDecoderRate());
831 Map.insert("storagerate", m_playerCtx->m_buffer->GetStorageRate());
832 Map.insert("bufferavail", m_playerCtx->m_buffer->GetAvailableBuffer());
833 Map.insert("buffersize", QString::number(m_playerCtx->m_buffer->GetBufferSize() >> 20));
835
836 if (m_videoOutput)
837 {
838 QString frames = QString("%1/%2").arg(m_videoOutput->ValidVideoFrames())
840 Map.insert("videoframes", frames);
841 }
842 if (m_decoder)
843 Map["videodecoder"] = m_decoder->GetCodecDecoderName();
844
845 Map["framerate"] = QString("%1%2%3")
846 .arg(static_cast<double>(m_outputJmeter.GetLastFPS()), 0, 'f', 2).arg(QChar(0xB1, 0))
847 .arg(static_cast<double>(m_outputJmeter.GetLastSD()), 0, 'f', 2);
848 Map["load"] = m_outputJmeter.GetLastCPUStats();
849
851
852 QString displayfps = QString("%1x%2@%3Hz")
853 .arg(m_display->GetResolution().width())
854 .arg(m_display->GetResolution().height())
855 .arg(m_display->GetRefreshRate(), 0, 'f', 2);
856 Map["displayfps"] = displayfps;
857}
858
860{
861 Map["audiocodec"] = avcodec_get_name(m_audio.GetCodec());
862 Map["audiochannels"] = QString::number(m_audio.GetOrigChannels());
863
864 int width = m_videoDispDim.width();
865 int height = m_videoDispDim.height();
866 Map["videocodec"] = GetEncodingType();
867 if (m_decoder)
868 Map["videocodecdesc"] = m_decoder->GetRawEncodingType();
869 Map["videowidth"] = QString::number(width);
870 Map["videoheight"] = QString::number(height);
871 Map["videoframerate"] = QString::number(m_videoFrameRate, 'f', 2);
872 Map["deinterlacer"] = GetDeinterlacerName();
873
874 if (width < 640)
875 return;
876
877 bool interlaced = is_interlaced(GetScanType());
878 if (height > 2100)
879 Map["videodescrip"] = interlaced ? "UHD_4K_I" : "UHD_4K_P";
880 else if (width == 1920 || height == 1080 || height == 1088)
881 Map["videodescrip"] = interlaced ? "HD_1080_I" : "HD_1080_P";
882 else if ((width == 1280 || height == 720) && !interlaced)
883 Map["videodescrip"] = "HD_720_P";
884 else if (height >= 720)
885 Map["videodescrip"] = "HD";
886 else
887 Map["videodescrip"] = "SD";
888}
889
891{
893 if (Visible)
894 {
895 // This should already have enabled the required monitors
896 m_osdDebugTimer.start();
897 }
898 else
899 {
900 // If we have cleared/escaped the debug OSD screen, then ChangeOSDDebug
901 // is not called, so we need to ensure we turn off the monitors
902 m_osdDebugTimer.stop();
905 }
906}
907
909{
910 m_osdLock.lock();
911 InfoMap infoMap;
912 GetPlaybackData(infoMap);
915 m_osdLock.unlock();
916}
917
919{
920 m_osdLock.lock();
921 bool enable = !m_osdDebug;
922 EnableBitrateMonitor(enable);
924 if (enable)
926 else
928 m_osdDebug = enable;
929 m_osdLock.unlock();
930}
931
933{
934 bool enable = VERBOSE_LEVEL_CHECK(VB_PLAYBACK, LOG_ANY) || Enable;
935 m_outputJmeter.SetNumCycles(enable ? static_cast<int>(m_videoFrameRate) : 0);
936}
937
939{
942}
943
944/* JumpToStream, JumpToProgram and SwitchToProgram all need to be moved into the
945 * parent object and hopefully simplified. The fairly involved logic does not
946 * sit well with the new design objectives for the player classes and are better
947 * suited to the high level logic in TV.
948 */
949void MythPlayerUI::JumpToStream(const QString &stream)
950{
951 LOG(VB_PLAYBACK, LOG_INFO, LOC + "JumpToStream - begin");
952
953 // Shouldn't happen
954 if (stream.isEmpty())
955 return;
956
957 Pause();
959
960 ProgramInfo pginfo(stream);
961 SetPlayingInfo(pginfo);
962
965 else
966 m_playerCtx->m_buffer->OpenFile(stream);
967
968 if (!m_playerCtx->m_buffer->IsOpen())
969 {
970 LOG(VB_GENERAL, LOG_ERR, LOC + "JumpToStream buffer OpenFile failed");
972 SetErrored(tr("Error opening remote stream buffer"));
973 return;
974 }
975
976 m_watchingRecording = false;
977 m_totalLength = 0s;
978 m_totalFrames = 0;
979 m_totalDuration = 0s;
980
981 // 120 retries ~= 60 seconds
982 if (OpenFile(120) < 0)
983 {
984 LOG(VB_GENERAL, LOG_ERR, LOC + "JumpToStream OpenFile failed.");
986 SetErrored(tr("Error opening remote stream"));
987 return;
988 }
989
990 if (m_totalLength == 0s)
991 {
992 long long len = m_playerCtx->m_buffer->GetRealFileSize();
993 m_totalLength = std::chrono::seconds(len / ((m_decoder->GetRawBitrate() * 1000) / 8));
994 m_totalFrames = static_cast<uint64_t>(m_totalLength.count() * SafeFPS());
995 }
996
997 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("JumpToStream length %1 bytes @ %2 Kbps = %3 Secs, %4 frames @ %5 fps")
999 .arg(m_totalLength.count()).arg(m_totalFrames).arg(m_decoder->GetFPS()) );
1000
1002
1003 // the bitrate is reset by m_playerCtx->m_buffer->OpenFile()...
1005 m_decoder->SetProgramInfo(pginfo);
1006
1007 Play();
1008 ChangeSpeed();
1009
1011#if CONFIG_MHEG
1012 if (m_interactiveTV) m_interactiveTV->StreamStarted();
1013#endif
1014
1015 LOG(VB_PLAYBACK, LOG_INFO, LOC + "JumpToStream - end");
1016}
1017
1019{
1020 if (!IsReallyNearEnd())
1021 return;
1022
1023 LOG(VB_PLAYBACK, LOG_INFO, LOC + "SwitchToProgram - start");
1024 bool discontinuity = false;
1025 bool newtype = false;
1026 int newid = -1;
1027 ProgramInfo *pginfo = m_playerCtx->m_tvchain->GetSwitchProgram(discontinuity, newtype, newid);
1028 if (!pginfo)
1029 return;
1030
1031 bool newIsDummy = m_playerCtx->m_tvchain->GetInputType(newid) == "DUMMY";
1032
1033 SetPlayingInfo(*pginfo);
1034 Pause();
1035 ChangeSpeed();
1036
1037 // Release all frames to ensure the current decoder resources are released
1038 DiscardVideoFrames(true, true);
1039
1040 if (newIsDummy)
1041 {
1042 OpenDummy();
1043 ResetPlaying();
1045 delete pginfo;
1046 return;
1047 }
1048
1050 {
1051 // Restore original ringbuffer
1052 auto *ic = dynamic_cast<MythInteractiveBuffer*>(m_playerCtx->m_buffer);
1053 if (ic)
1054 m_playerCtx->m_buffer = ic->TakeBuffer();
1055 delete ic;
1056 }
1057
1059
1060 if (!m_playerCtx->m_buffer->IsOpen())
1061 {
1062 LOG(VB_GENERAL, LOG_ERR, LOC + QString("SwitchToProgram's OpenFile failed (input type: %1)")
1063 .arg(m_playerCtx->m_tvchain->GetInputType(newid)));
1064 LOG(VB_GENERAL, LOG_ERR, m_playerCtx->m_tvchain->toString());
1066 SetErrored(tr("Error opening switch program buffer"));
1067 delete pginfo;
1068 return;
1069 }
1070
1071 if (GetEof() != kEofStateNone)
1072 {
1073 discontinuity = true;
1074 ResetCaptions();
1075 }
1076
1077 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("SwitchToProgram(void) "
1078 "discont: %1 newtype: %2 newid: %3 decoderEof: %4")
1079 .arg(discontinuity).arg(newtype).arg(newid).arg(GetEof()));
1080
1081 if (discontinuity || newtype)
1082 {
1083 m_playerCtx->m_tvchain->SetProgram(*pginfo);
1084 if (m_decoder)
1085 m_decoder->SetProgramInfo(*pginfo);
1086
1087 m_playerCtx->m_buffer->Reset(true);
1088 if (newtype)
1089 {
1090 if (OpenFile() < 0)
1091 SetErrored(tr("Error opening switch program file"));
1092 }
1093 else
1094 {
1095 ResetPlaying();
1096 }
1097 }
1098 else
1099 {
1101 if (m_decoder)
1102 {
1105 }
1106 }
1107 delete pginfo;
1108
1109 if (IsErrored())
1110 {
1111 LOG(VB_GENERAL, LOG_ERR, LOC + "SwitchToProgram failed.");
1113 return;
1114 }
1115
1117
1118 // the bitrate is reset by m_playerCtx->m_buffer->OpenFile()...
1119 if (m_decoder)
1122
1123 if (discontinuity || newtype)
1124 {
1125 CheckTVChain();
1127 }
1128
1129 Play();
1130 LOG(VB_PLAYBACK, LOG_INFO, LOC + "SwitchToProgram - end");
1131}
1132
1134{
1135 LOG(VB_PLAYBACK, LOG_INFO, LOC + "JumpToProgram - start");
1136 bool discontinuity = false;
1137 bool newtype = false;
1138 int newid = -1;
1139 std::chrono::seconds nextpos = m_playerCtx->m_tvchain->GetJumpPos();
1140 ProgramInfo *pginfo = m_playerCtx->m_tvchain->GetSwitchProgram(discontinuity, newtype, newid);
1141 if (!pginfo)
1142 return;
1143
1145
1146 bool newIsDummy = m_playerCtx->m_tvchain->GetInputType(newid) == "DUMMY";
1147 SetPlayingInfo(*pginfo);
1148
1149 Pause();
1150 ChangeSpeed();
1151 ResetCaptions();
1152
1153 // Release all frames to ensure the current decoder resources are released
1154 DiscardVideoFrames(true, true);
1155
1156 m_playerCtx->m_tvchain->SetProgram(*pginfo);
1157 m_playerCtx->m_buffer->Reset(true);
1158
1159 if (newIsDummy)
1160 {
1161 OpenDummy();
1162 ResetPlaying();
1164 delete pginfo;
1165 m_inJumpToProgramPause = false;
1166 return;
1167 }
1168
1169 SendMythSystemPlayEvent("PLAY_CHANGED", pginfo);
1170
1172 {
1173 // Restore original ringbuffer
1174 auto *ic = dynamic_cast<MythInteractiveBuffer*>(m_playerCtx->m_buffer);
1175 if (ic)
1176 m_playerCtx->m_buffer = ic->TakeBuffer();
1177 delete ic;
1178 }
1179
1181 if (!m_playerCtx->m_buffer->IsOpen())
1182 {
1183 LOG(VB_GENERAL, LOG_ERR, LOC + QString("JumpToProgram's OpenFile failed (input type: %1)")
1184 .arg(m_playerCtx->m_tvchain->GetInputType(newid)));
1185 LOG(VB_GENERAL, LOG_ERR, m_playerCtx->m_tvchain->toString());
1187 SetErrored(tr("Error opening jump program file buffer"));
1188 delete pginfo;
1189 m_inJumpToProgramPause = false;
1190 return;
1191 }
1192
1194
1195 bool wasDummy = m_isDummy;
1196 if (newtype || wasDummy)
1197 {
1198 if (OpenFile() < 0)
1199 SetErrored(tr("Error opening jump program file"));
1200 }
1201 else
1202 {
1203 ResetPlaying();
1204 }
1205
1206 if (IsErrored() || !m_decoder)
1207 {
1208 LOG(VB_GENERAL, LOG_ERR, LOC + "JumpToProgram failed.");
1209 if (!IsErrored())
1210 SetErrored(tr("Error reopening video decoder"));
1211 delete pginfo;
1212 m_inJumpToProgramPause = false;
1213 return;
1214 }
1215
1217
1218 // the bitrate is reset by m_playerCtx->m_buffer->OpenFile()...
1221
1222 m_decoder->SetProgramInfo(*pginfo);
1223 delete pginfo;
1224
1225 CheckTVChain();
1227 m_inJumpToProgramPause = false;
1228 Play();
1229 ChangeSpeed();
1230
1231 // check that we aren't too close to the end of program.
1232 // and if so set it to 10s from the end if completed recordings
1233 // or 3s if live
1234 std::chrono::seconds duration = m_playerCtx->m_tvchain->GetLengthAtCurPos();
1235 std::chrono::seconds maxpos = m_playerCtx->m_tvchain->HasNext() ? 10s : 3s;
1236
1237 if (nextpos > (duration - maxpos))
1238 {
1239 nextpos = duration - maxpos;
1240 if (nextpos < 0s)
1241 nextpos = 0s;
1242 }
1243 else if (nextpos < 0s)
1244 {
1245 // it's a relative position to the end
1246 nextpos += duration;
1247 }
1248
1249 // nextpos is the new position to use in seconds
1250 uint64_t nextframe = TranslatePositionMsToFrame(nextpos, true);
1251
1252 if (nextpos > 10s)
1253 DoJumpToFrame(nextframe, kInaccuracyNone);
1254
1256 LOG(VB_PLAYBACK, LOG_INFO, LOC + "JumpToProgram - end");
1257}
#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:41
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:847
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:395
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:321
virtual bool HasReachedEof(void) const
Definition: mythplayer.cpp:656
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:645
virtual void ResetPlaying(bool resetframes=true)
Definition: mythplayer.cpp:919
virtual int OpenFile(int Retries=4)
Definition: mythplayer.cpp:417
virtual void InitFrameInterval()
Definition: mythplayer.cpp:694
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:294
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:127
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:720
void SeekingComplete()
MythPlayerAVSync m_avSync
Definition: mythplayer.h:430
void SetBuffering(bool new_buffering)
Definition: mythplayer.cpp:700
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:153
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:231
bool GetAllowForcedSubtitles(void) const
Definition: mythplayer.h:203
void UnpauseDecoder(void)
Definition: mythplayer.cpp:992
bool Play(float speed=1.0, bool normal=true, bool unpauseaudio=true)
Definition: mythplayer.cpp:186
bool m_hasFullPositionMap
Definition: mythplayer.h:405
void CheckTVChain()
Definition: mythplayer.cpp:933
void SetPlaying(bool is_playing)
Definition: mythplayer.cpp:242
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:684
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:636
bool Init(QRect Rect, float FontAspect) override
Definition: osd.cpp:51
void Draw()
Definition: osd.cpp:458
void HideWindow(const QString &Window) override
Definition: osd.cpp:675
void SetText(const QString &Window, const InfoMap &Map, OSDTimeout Timeout)
Definition: osd.cpp:210
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:70
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
Definition: programinfo.h:375
void SetIgnoreProgStart(bool ignore)
If "ignore" is true QueryProgStart() will return 0, otherwise QueryProgStart() will return the progst...
Definition: programinfo.h:572
void SetIgnoreBookmark(bool ignore)
If "ignore" is true GetBookmark() will return 0, otherwise GetBookmark() will return the bookmark pos...
Definition: programinfo.h:565
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:400
void SetIgnoreLastPlayPos(bool ignore)
If "ignore" is true QueryLastPlayPos() will return 0, otherwise QueryLastPlayPos() will return the la...
Definition: programinfo.h:580
bool IsRecording(void) const
Definition: programinfo.h:493
TranscodingStatus QueryTranscodeStatus(void) const
Returns the "transcoded" field in "recorded" table.
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
Definition: programinfo.h:407
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:342
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:415
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:155
#define setpriority(x, y, z)
Definition: compat.h:120
#define PRIO_PROCESS
Definition: compat.h:119
unsigned int uint
Definition: compat.h:68
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)