vdr-plugin-softhddevice-drm-gles 1.6.4-d0291bb
softhddevice.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: AGPL-3.0-or-later
2
18#include <chrono>
19#include <mutex>
20#include <variant>
21#include <libintl.h>
22
23extern "C" {
24#include <libavcodec/avcodec.h>
25}
26
27#include <vdr/dvbspu.h>
28#include <vdr/skins.h>
29#include <vdr/status.h>
30
31#include "audio.h"
32#include "codec_audio.h"
33#include "config.h"
34#include "event.h"
35#include "grab.h"
36#include "hardwaredevice.h"
37#include "jittertracker.h"
38#include "logger.h"
39#include "pes.h"
40#include "pipreceiver.h"
41#include "softhddevice.h"
42#include "softhdosdprovider.h"
43#include "videorender.h"
44#include "videostream.h"
45
54 : m_pSpuDecoder(new cDvbSpuDecoder()),
55 m_pConfig(config),
56 m_pipUseAlt(m_pConfig->ConfigPipUseAlt)
57{
58// LOGDEBUG("device: %s:", __FUNCTION__);
59
60 m_channelSwitchStartTime = std::chrono::steady_clock::now();
62}
63
70{
71 LOGDEBUG("device: %s:", __FUNCTION__);
72 delete m_pHardwareDevice;
73 delete m_pSpuDecoder;
74}
75
80{
81 LOGDEBUG("device: %s:", __FUNCTION__);
82 m_pHardwareDevice = new cHardwareDevice(); // deleted in destructor
83
84 return true;
85}
86
91{
92 LOGDEBUG("device: %s", __FUNCTION__);
94
95 return true;
96}
97
102{
103 LOGDEBUG("device: %s", __FUNCTION__);
105}
106
117
124{
125 LOGDEBUG("device: %s: %d", __FUNCTION__, on);
126
127 if (on)
128 m_pOsdProvider = new cSoftOsdProvider(this); // no need to delete it, VDR does it
129
130 cDevice::MakePrimaryDevice(on);
131}
132
139void cSoftHdDevice::ChannelSwitch(const cDevice *device, int channelNum, bool liveView)
140{
141 if (device != cDevice::PrimaryDevice())
142 return;
143
144 if (!liveView)
145 return;
146
147 if (channelNum == 0)
148 m_channelSwitchStartTime = std::chrono::steady_clock::now();
149}
150
158{
159 LOGDEBUG("device: %s:", __FUNCTION__);
160 if (!IsPrimaryDevice())
161 return NULL;
162
163 return m_pSpuDecoder;
164}
165
170{
171 bool hasDecoder = !IsDetached();
172
173// LOGDEBUG("device: %s: %d", __FUNCTION__, hasDecoder);
174
175 return hasDecoder;
176}
177
182{
183 bool canReplay = !IsDetached();
184
185 LOGDEBUG("device: %s: %d", __FUNCTION__, canReplay);
186
187 return canReplay;
188}
189
201{
202 uint64_t startStateChange = cTimeMs::Now();
203 LOGDEBUG("device: STATE MACHINE received %s", EventToString(event));
204 bool needsResume = false;
205
206#ifdef USE_GLES
207 // Lock the GL thread before the state machine lock, because cmdCopyBufferToOutputFb() calls
208 // cSoftHdDevice::OsdDrawARGB(), which itself locks the state machine mutex and we can end
209 // up in a deadlock then.
210 // We can safely unlock the thread again after the state change, because cSoftHdDevice::OsdDrawARGB()
211 // always tests if we are in detached mode and this new state is probably set then.
212 bool needsOglResume = false;
215#endif
216
217 { // locked state machine context
218 std::lock_guard<std::mutex> lock(m_mutex);
219
220 if (m_state != DETACHED) {
221 m_pRender->Halt();
223 needsResume = true;
224 }
225
226 auto invalid = [this, &event]() {
227 LOGWARNING("device: Invalid event '%s' in state '%s' received", EventToString(event), StateToString(m_state));
228 };
229
230 switch (m_state) {
231 case State::DETACHED:
232 std::visit(overload{
233 [&invalid](const PlayEvent&) { invalid(); },
234 [&invalid](const PauseEvent&) { invalid(); },
235 [&invalid](const StopEvent&) { invalid(); },
236 [&invalid](const TrickSpeedEvent&) { invalid(); },
237 [&invalid](const StillPictureEvent&) { invalid(); },
238 [](const DetachEvent&) { /* ignore */ },
239 [this](const AttachEvent&) {
240 if (!m_forceDetached)
241 SetState(STOP);
242 },
243 [&invalid](const BufferUnderrunEvent&) { invalid(); },
245 [&invalid](const PipEvent&) { invalid(); },
247 [&invalid](const ResyncEvent&) { invalid(); },
248 }, event);
249 needsResume = false;
250 break;
251 case State::STOP:
252 std::visit(overload{
253 [this](const PlayEvent&) {
255 m_pAudio->SetVolume((m_volume * 1000) / 255);
259 },
260 [&invalid](const PauseEvent&) { invalid(); },
261 [&invalid](const StopEvent&) { invalid(); },
262 [&invalid](const TrickSpeedEvent&) { invalid(); },
263 [this](const StillPictureEvent& s) {
264 HandleStillPicture(s.data, s.size);
265 },
266 [this, &needsResume](const DetachEvent&) {
269 needsResume = false;
270 },
271 [&invalid](const AttachEvent&) { invalid(); },
272 [&invalid](const BufferUnderrunEvent&) { invalid(); },
274 [this](const PipEvent& p) {
276 },
278 [&invalid](const ResyncEvent&) { invalid(); },
279 }, event);
280 break;
281 case State::BUFFERING:
282 std::visit(overload{
283 [this](const PlayEvent&) {
284 // ignore
285 },
286 [this](const PauseEvent&) {
287 // ignore
288 },
289 [this](const StopEvent&) {
290 SetState(STOP);
291 },
292 [this](const TrickSpeedEvent& t) {
293 // abort buffering and proceed with trick speed immediately, because trick speed shall be as fast and as demanded as possible
294 SetState(PLAY);
295 m_pRender->SetTrickSpeed(t.speed, t.active, t.forward);
297 },
298 [this](const StillPictureEvent& s) {
299 HandleStillPicture(s.data, s.size);
300 },
301 [this, &needsResume](const DetachEvent&) {
303 needsResume = false;
304 },
305 [&invalid](const AttachEvent&) { invalid(); },
306 [&invalid](const BufferUnderrunEvent&) { invalid(); },
307 [this](const BufferingThresholdReachedEvent&) {
310
315 // store the first PTSes beforehand, because dropping samples/frames will change the output of GetFirst*PtsMsToPlay()
318 } else if (receivedAudio) {
319 LOGDEBUG("device: audio only detected");
322 } else if (receivedVideo) {
323 LOGDEBUG("device: video only detected");
326 } else
327 LOGFATAL("device: buffering threshold reached and no a/v available. This is a bug.");
328
329 SetState(PLAY);
330 },
331 [this](const PipEvent& p) {
333 },
334 [this](const ScheduleResyncAtPtsMsEvent& s) {
335 SetState(PLAY);
337 },
338 [&invalid](const ResyncEvent&) { invalid(); },
339 }, event);
340 break;
341 case State::PLAY:
342 std::visit(overload{
343 [this](const PlayEvent&) {
344 // resume from pause
346 switch (m_playbackMode) {
347 case AUDIO_ONLY:
349 m_pAudio->SetPaused(false);
350 break;
351 case AUDIO_AND_VIDEO:
354 if (audioBehindVideoByMs > 0) {
356 m_pAudio->SetPaused(false);
357 } else
359
360 // fallthrough
361 case VIDEO_ONLY:
364 break;
365 case NONE:
366 LOGFATAL("device: play event in PLAY state with NONE playback mode. This is a bug.");
367 break;
368 }
369 },
370 [this](const PauseEvent&) {
373 else
375
376 m_pAudio->SetPaused(true);
378 },
379 [this](const StopEvent&) {
380 SetState(STOP);
381 },
382 [this](const TrickSpeedEvent& t) {
383 m_pRender->SetTrickSpeed(t.speed, t.active, t.forward);
385 },
386 [this](const StillPictureEvent& s) {
387 HandleStillPicture(s.data, s.size);
388 },
389 [this, &needsResume](const DetachEvent&) {
392 needsResume = false;
393 },
394 [&invalid](const AttachEvent&) { invalid(); },
395 [this](const BufferUnderrunEvent&) {
397 },
399 // ignore
400 },
401 [this](const PipEvent& p) {
403 },
404 [this](const ScheduleResyncAtPtsMsEvent& s) {
406 },
407 [this](const ResyncEvent&) {
409 },
410 }, event);
411 break;
413 std::visit(overload{
414 [this](const PlayEvent&) {
415 SetState(PLAY);
416 },
417 [this](const PauseEvent&) {
419 m_pAudio->SetPaused(true);
421 },
422 [this](const StopEvent&) {
423 SetState(STOP);
424 },
425 [this](const TrickSpeedEvent& t) {
426 // resume from pause, or change trick speed direction/speed
427 m_pRender->SetTrickSpeed(t.speed, t.active, t.forward);
429 },
430 [this](const StillPictureEvent& s) {
431 HandleStillPicture(s.data, s.size);
432 },
433 [this, &needsResume](const DetachEvent&) {
436 needsResume = false;
437 },
438 [&invalid](const AttachEvent&) { invalid(); },
439 [this](const BufferUnderrunEvent&) {
440 // ignore during trick speed. Fast forward/reverse as fast and as demanded as possible
441 },
443 [this](const PipEvent& p) {
445 },
447 [&invalid](const ResyncEvent&) { invalid(); },
448 }, event);
449 break;
450 }
451
452 if (needsResume) {
454 m_pRender->Resume();
455 }
456
457 } // end of locked state machine context
458#ifdef USE_GLES
461#endif
462
463 uint64_t stopStateChange = cTimeMs::Now();
464 LOGDEBUG("device: STATE MACHINE state change done in %d ms", (int)(stopStateChange - startStateChange));
465}
466
476 switch (state) {
477 case BUFFERING:
479 // nothing
480 break;
481 case PLAY:
483 m_pAudio->SetPaused(false);
484
485 if (m_playbackMode != AUDIO_ONLY) {
489 }
490 break;
491 case TRICK_SPEED:
492 // The filter thread needs to be restarted for interlaced streams to be rendered without deinterlacer in trick speed mode. It is started lazily.
497 break;
498 case STOP:
499 FlushAudio();
500
503 m_pRender->Reset();
505
514
515 break;
516 case DETACHED:
517 delete m_pPipHandler;
518 m_pPipHandler = nullptr;
519
520 // resume the previously stopped threads
522 m_pRender->Resume();
523
524 // now do the detach
526 delete m_pPipStream;
527
528#ifdef USE_GLES
529 // The opengl thread was probably locked before cmdCopyBufferToOutputFb().
530 // 1) set running to false
531 // 2) continue the thread (which will skip the waiting cmd->Execute())
532 // 3) do the real thread cancel and cleanup
533 // We need to keep this order to prevent a deadlock!
537#endif
538 m_pRender->Exit(); // render must be stopped before videostream!
540 m_pAudio->Exit(); // audio must be stopped after renderer!
541
542 delete m_pAudioDecoder; // includes a Close()
543 delete m_pVideoStream;
544 delete m_pGrab;
545 delete m_pRender;
546 delete m_pAudio;
547
548 break;
549 }
550}
551
561 switch (state) {
562 case PLAY:
565 m_pAudio->SetPaused(true);
567 break;
568 case BUFFERING:
571 break;
572 case TRICK_SPEED:
573 // The filter thread needs to be restarted for interlaced streams to be rendered with deinterlacer again. It is started lazily.
575 m_pRender->SetTrickSpeed(0, false, false);
582 break;
583 case STOP:
584 m_receivedAudio = false;
585 m_receivedVideo = false;
586 break;
587 case DETACHED:
588 m_pAudio = new cSoftHdAudio(this);
589 m_pRender = new cVideoRender(this);
593 m_pRender->Init(); // starts display thread
594 m_pVideoStream->StartDecoder(); // starts decoding thread
596 m_pPipStream->StartDecoder(); // starts decoding thread
597 m_pPipHandler = new cPipHandler(this);
598 // Audio is init lazily (includes starting thread)
599
600 break;
601 }
602}
603
610{
611 if (m_state != newState) {
612 LOGDEBUG("device: Preparing to leave state %s", StateToString(m_state));
614 LOGDEBUG("device: Changing state %s -> %s", StateToString(m_state), StateToString(newState));
617 LOGDEBUG("device: State changed to %s", StateToString(m_state));
618 }
619}
620
627{
628 LOGDEBUG("device: %s: %d", __FUNCTION__, play_mode);
629
630 switch (play_mode) {
631 case pmNone:
633 break;
634 case pmAudioVideo:
635 case pmAudioOnly:
636 case pmAudioOnlyBlack:
637 case pmVideoOnly:
639 break;
640 default:
641 LOGERROR("device: %s: playmode not supported %d", play_mode);
642 return 0;
643 break;
644 }
645
646 return 1;
647}
648
654{
655 if (IsDetached())
656 return AV_NOPTS_VALUE;
657
658 switch (m_playbackMode) {
659 case NONE:
660 return AV_NOPTS_VALUE;
661 case AUDIO_AND_VIDEO:
662 case VIDEO_ONLY:
663 return m_pRender->GetVideoClock();
664 case AUDIO_ONLY:
666 }
667
668 abort();
669}
670
683void cSoftHdDevice::TrickSpeed(int speed, bool forward)
684{
685 LOGDEBUG("device: %s: %d %s", __FUNCTION__, speed, forward ? "forward" : "backward");
686
687 // This normalizes the VDR frame displaying count into a factor, representing how fast/slow the playback shall be.
688 // For example, a factor of 2.0 means twice as fast as normal, a factor of 0.5 means half as fast as normal (slow-mo).
689 // This is necessary because VDR sends only I-frames during trickspeed, but the distance between I-frames depends on the encoding parameters.
690 // Therefore, we send a normalized factor for the further components, which then calculate the necessary frame displaying count by considering the distance between I-frames.
691
692 double normalizedSpeed = 1;
693 static constexpr double MAX_SPEED = 3;
694
695 // these are arbitrary values, which feel just right
696 static constexpr double FAST_TRICKSPEED_FACTOR = 5; // the higher the factor, the faster the fast forward/reverse
697 static constexpr double SLOW_FORWARD_FACTOR = 2; // the higher the factor, the slower the slow-mo
698
699 // Fastest speed in reverse slow-mo is the original speed. Slower speeds are too slow, because of the already low frame rate.
700 static constexpr double SLOW_REVERSE_FACTOR = 1;
701
702 // speed of the trickspeed (VDR's magic frame displaying count)
703 switch (speed) {
704 case 6:
705 case 8:
706 case 63:
707 normalizedSpeed = 1; // slowest (both, in fast trickspeed and slow-mo)
708 break;
709 case 3:
710 case 4:
711 case 48:
712 normalizedSpeed = 2;
713 break;
714 case 1:
715 case 2:
716 case 24:
717 normalizedSpeed = 3; // fastest (both, in fast trickspeed and slow-mo)
718 break;
719 }
720
721 // figure out if VDR demands slow-mo or fast trickspeed
722 double tmp;
723 switch (speed) {
724 case 8:
725 case 4:
726 case 2:
727 case 63:
728 case 48:
729 case 24:
730 // slow-mo
731 tmp = (MAX_SPEED + 1) - normalizedSpeed;
732
733 if (forward)
735 else
737
738 normalizedSpeed = 1 / tmp;
739 break;
740 default:
741 // fast trickspeed
743 break;
744 }
745
746 OnEventReceived(TrickSpeedEvent{normalizedSpeed, speed != 0, forward});
747}
748
757{
758 LOGDEBUG("device: %s:", __FUNCTION__);
759 cDevice::Clear();
760
761 if (IsDetached())
762 return;
763
764 m_pRender->Halt();
766
769
773
776
777 m_pRender->Reset();
778
779 m_pAudio->SetPaused(true);
780 FlushAudio();
781
783
784 m_pRender->Resume();
786}
787
794{
795 cDevice::Play();
796
798}
799
804{
805 LOGDEBUG("device: %s:", __FUNCTION__);
806 cDevice::Freeze();
807
809}
810
817void cSoftHdDevice::StillPicture(const uchar *data, int size)
818{
819 LOGDEBUG("device: %s: %s %p %d", __FUNCTION__, data[0] == 0x47 ? "ts" : "pes", data, size);
820
821 if (data[0] == 0x47) { // ts sync byte
822 cDevice::StillPicture(data, size);
823 return;
824 }
825
827}
828
836void cSoftHdDevice::HandleStillPicture(const uchar *data, int size)
837{
840
841 // skip BufferUnderrunEvent{VIDEO} in renderer
843
844 const uchar *currentPacketStart = data;
845 while (currentPacketStart < data + size) {
847
848 if (pesPacket.IsValid())
850 else {
851 LOGWARNING("device: %s: invalid PES packet", __FUNCTION__);
852 break;
853 }
854
855 currentPacketStart += pesPacket.GetPacketLength();
856 }
857
859 m_pVideoStream->ResetInputPts(); // stillpicture shouldn't trigger having video data
861}
862
876{
877// LOGDEBUG("device: %s: timeout %d", __FUNCTION__, timeout_ms);
878 if (IsDetached())
879 return true;
880
882 return true;
883
884 usleep(timeoutMs * 1000);
885
886 return false;
887}
888
895{
896 if (IsDetached())
897 return true;
898
899 LOGDEBUG("device: %s: timeout %d ms", __FUNCTION__, timeoutMs);
901 if (timeoutMs) { // let display thread work
902 usleep(timeoutMs * 1000);
903 }
905 }
906
907 return true;
908}
909
917{
918 LOGDEBUG("device: %s: %d", __FUNCTION__, videoDisplayFormat);
919
920 cDevice::SetVideoDisplayFormat(videoDisplayFormat);
921}
922
934{
935 LOGDEBUG("device: %s: %d", __FUNCTION__, videoFormat16_9);
936
937 // FIXME: 4:3 / 16:9 video format not supported.
938 SetVideoDisplayFormat(eVideoDisplayFormat(Setup.VideoDisplayFormat));
939}
940
953void cSoftHdDevice::GetVideoSize(int &width, int &height, double &aspectRatio)
954{
955// LOGDEBUG("device: %s: %d x %d @ %f", __FUNCTION__, *width, *height, *aspectRatio);
956
957 if (IsDetached()) { // return default values according to vdr docs
958 width = 0;
959 height = 0;
960 aspectRatio = 1.0;
961 return;
962 }
963
964 m_pVideoStream->GetVideoSize(&width, &height, &aspectRatio);
965}
966
976void cSoftHdDevice::GetOsdSize(int &width, int &height, double &aspectRatio)
977{
978 if (IsDetached()) { // hardcode to 1920x1080 in detached state
979 width = 1920;
980 height = 1080;
981 aspectRatio = (double)width / (double)height;
982 return;
983 }
984
985 std::lock_guard<std::mutex> lock(m_sizeMutex);
986 width = m_screenWidth;
987 height = m_screenHeight;
988 aspectRatio = (double)width / (double)height;
989}
990
998void cSoftHdDevice::SetScreenSize(int width, int height, double refreshRateHz)
999{
1000 std::lock_guard<std::mutex> lock(m_sizeMutex);
1001 m_screenWidth = width;
1002 m_screenHeight = height;
1004}
1005
1014static void PrintStreamData(const uchar *payload)
1015{
1016 LOGDEBUG2(L_CODEC, "Stream: %02X%02X%02X | %02X | %02X%02X | %02X%02X%02X | %02X%02X%02X%02X %02X%02X%02X%02X %02X%02X%02X%02X %02X%02X%02X%02X",
1017 payload[0],
1018 payload[1],
1019 payload[2],
1020 payload[3],
1021 payload[4],
1022 payload[5],
1023 payload[6],
1024 payload[7],
1025 payload[8],
1026 payload[9],
1027 payload[10],
1028 payload[11],
1029 payload[12],
1030 payload[13],
1031 payload[14],
1032 payload[15],
1033 payload[16],
1034 payload[17],
1035 payload[18],
1036 payload[19],
1037 payload[20],
1038 payload[21],
1039 payload[22],
1040 payload[23],
1041 payload[24]
1042 );
1043}
1044
1058int cSoftHdDevice::PlayAudio(const uchar *data, int size, uchar id)
1059{
1060// LOGDEBUG("device: %s: %p %p %d %d", __FUNCTION__, this, data, size, id);
1061 if (IsDetached())
1062 return size;
1063
1064 if (!m_receivedAudio && Transferring()) {
1065 auto now = std::chrono::steady_clock::now();
1066 auto timeUntilFirstPacketReceived = std::chrono::duration_cast<std::chrono::milliseconds>(now - m_channelSwitchStartTime).count();
1067 LOGDEBUG("device: first audio packet arrives %dms after channel switch was triggered", timeUntilFirstPacketReceived);
1068
1069 if (!m_receivedVideo)
1071 }
1072
1073 m_receivedAudio = true;
1074
1075 if (m_pAudio->IsBufferFull())
1076 return 0;
1077
1078 cPesAudio pesPacket((const uint8_t*)data, size);
1079
1080 if (!pesPacket.IsValid()) {
1082
1083 return size;
1084 }
1085
1086 if (Transferring()) { // compensation is only necessary with live streams
1091 }
1092
1093 if (m_audioChannelID != id) {
1097 LOGDEBUG("device: %s: new channel id 0x%02X", __FUNCTION__, m_audioChannelID);
1098 }
1099
1100 m_audioReassemblyBuffer.Push(pesPacket.GetPayload(), pesPacket.GetPayloadSize(), pesPacket.GetPts());
1101
1104
1105 AVPacket *avpkt;
1106 do {
1108 break;
1109
1111 // The playback has just started
1114 }
1115
1117 AVPacket *copy = avpkt;
1119 } while (avpkt != nullptr);
1120
1121 return size;
1122}
1123
1125{
1126 //LOGDEBUG("device: %s:", __FUNCTION__);
1127}
1128
1130{
1131 //LOGDEBUG("device: %s: %s", __FUNCTION__, on ? "true" : "false");
1132}
1133
1135 int audio_channel)
1136{
1137 //LOGDEBUG("device: %s: %d", __FUNCTION__, audio_channel);
1138}
1139
1141{
1142 //LOGDEBUG("device: %s:", __FUNCTION__);
1143 return 0;
1144}
1145
1152{
1153 if (IsDetached())
1154 return;
1155
1156 LOGDEBUG("device: %s: %d", __FUNCTION__, volume);
1157 m_volume = volume;
1158 m_pAudio->SetVolume((volume * 1000) / 255);
1159}
1160
1175int cSoftHdDevice::PlayVideo(const uchar *data, int size)
1176{
1177// LOGDEBUG("device: %s: %p %d", __FUNCTION__, data, size);
1178 if (IsDetached())
1179 return size;
1180
1181 if (!m_receivedVideo && Transferring()) {
1182 auto now = std::chrono::steady_clock::now();
1183 auto timeUntilFirstPacketReceived = std::chrono::duration_cast<std::chrono::milliseconds>(now - m_channelSwitchStartTime).count();
1184 LOGDEBUG("device: first video packet arrives %dms after channel switch was triggered", timeUntilFirstPacketReceived);
1185
1186 if (!m_receivedAudio)
1188 }
1189
1190 m_receivedVideo = true;
1191
1193}
1194
1205int cSoftHdDevice::PlayPipVideo(const uchar *data, int size)
1206{
1207// LOGDEBUG("device: %s: %p %d", __FUNCTION__, data, size);
1208
1209 // This is a bit hacky:
1210 // Because we do no sync with the pip stream, we simply drop data
1211 // if the input buffer is full -> this prevents us from having a buffer overflow
1212 // caused by the pip stream.
1214 return size;
1215
1216 return PlayVideoInternal(m_pPipStream, &m_pipReassemblyBuffer, data, size, false);
1217}
1218
1229{
1230 // LOGDEBUG("device: %s: %p %d", __FUNCTION__, data, size);
1231
1232 if (stream->IsInputBufferFull())
1233 return 0;
1234
1235 cPesVideo pesPacket((const uint8_t*)data, size);
1236
1237 if (!pesPacket.IsValid()) {
1238 buffer->Reset();
1239
1240 return size;
1241 }
1242
1243 if (trackJitter) {
1247 }
1248
1249 if (stream->GetCodecId() == AV_CODEC_ID_NONE) {
1250 // The playback has just started
1251 if (!pesPacket.HasPts() || !buffer->ParseCodecHeader(pesPacket.GetPayload(), pesPacket.GetPayloadSize())) {
1252 // received the middle of fragmented data, wait for the next PES packets with the start of a new frame
1253 return size;
1254 }
1255
1256 PrintStreamData(data);
1257 buffer->Push(pesPacket.GetPayload(), pesPacket.GetPayloadSize(), pesPacket.GetPts());
1258
1259 stream->Open(buffer->GetCodec());
1260 } else {
1261 int payloadOffset = 0;
1262 if (pesPacket.HasPts() && !buffer->IsEmpty()) {
1263 // received the first fragment of a new frame, finish the current reassembly buffer into an AVPacket
1264 stream->PushAvPacket(buffer->PopAvPacket());
1265
1266 // populate the cleared buffer with the next frame
1267 if (buffer->HasLeadingZero(pesPacket.GetPayload(), pesPacket.GetPayloadSize()))
1268 payloadOffset = 1; // H.264/HEVC streams may have a leading zero byte before the start code
1269 }
1270
1271 buffer->Push(pesPacket.GetPayload() + payloadOffset, pesPacket.GetPayloadSize() - payloadOffset, pesPacket.GetPts());
1272 }
1273
1274 return size;
1275}
1276
1284
1312{
1313 if (m_state != BUFFERING)
1314 return false;
1315
1319
1320 // Assume audio only or video only if no PES fragment from the other stream has been received, while the buffering threshold of the other stream is reached.
1321 // Check for buffer fill level only if at least one PES packet was reassembled and pushed to the respective decoder.
1324
1326 LOGDEBUG("device: %s: Detected audio only", __FUNCTION__);
1327 return true;
1329 LOGDEBUG("device: %s: Detected video only", __FUNCTION__);
1330 return true;
1332 return false; // Either no video or no audio received, yet. Or, video didn't make it to the output buffer, yet.
1333
1336
1337 bool reached = m_pRender->IsOutputBufferFull() && // video decoder output buffer (audio hardware output buffer is negligible)
1338 syncedVideoBufferFillLevelMs > GetBufferFillLevelThresholdMs() && // video decoder input buffer
1339 syncedAudioBufferFillLevelMs > GetBufferFillLevelThresholdMs(); // audio decoder output buffer
1340
1341 if (reached) {
1342 LOGDEBUG2(L_AV_SYNC, "First received PTS: %s (audio), %s (video) buffer fill levels: %ldms (audio) %ldms (video)",
1347 }
1348
1349 return reached;
1350}
1351
1373
1386
1396uchar *cSoftHdDevice::GrabImage(int &size, bool jpeg, int quality, int width, int height)
1397{
1398 if (IsDetached())
1399 return NULL;
1400
1401 if (m_pGrab->Active()) {
1402 LOGWARNING("device: %s: wait for the last grab to be finished - skip!", __FUNCTION__);
1403 return NULL;
1404 }
1405
1406 LOGDEBUG2(L_GRAB, "device: %s: %d, %d, %d, %dx%d", __FUNCTION__, size, jpeg, quality, width, height);
1407
1408 int screenWidth = 0;
1409 int screenHeight = 0;
1410 double aspectRatio = 0.0f;
1412
1413 if (!m_pGrab->Start(jpeg, quality, width, height, screenWidth, screenHeight))
1414 return NULL;
1415
1416 size = m_pGrab->Size();
1417
1418 return m_pGrab->Image();
1419}
1420
1432
1442{
1443 if (IsDetached())
1444 return;
1445
1446 LOGDEBUG2(L_OSD, "device: %s: %dx%d%+d%+d",
1447 __FUNCTION__, rect.Width(), rect.Height(), rect.X(), rect.Y());
1448
1449 if (m_pRender)
1451}
1452
1457{
1458 return " -a device\taudio device (e.g. alsa: hw:0,0)\n"
1459 " -p device\taudio device for pass-through (e.g. hw:0,1)\n"
1460 " -c channel\taudio mixer channel name (e.g. PCM)\n"
1461 " -o device\tdrm device (e.g. /dev/dri/card0)\n"
1462 " -d resolution\tdisplay resolution (e.g. 1920x1080@50)\n"
1463 " -D start in detached state\n"
1464 " -w workaround\tenable/disable workarounds\n"
1465#ifdef USE_GLES
1466 "\tdisable-ogl-osd disable openGL osd\n"
1467#endif
1468 "\tdisable-pip disable picture-in-picture\n"
1469 "\n";
1470}
1471
1479{
1480 //
1481 // Parse arguments.
1482 //
1483
1484 for (;;) {
1485#ifdef USE_GLES
1486 switch (getopt(argc, argv, "-a:c:p:o:d:Dw:")) {
1487#else
1488 switch (getopt(argc, argv, "-a:c:p:o:d:D")) {
1489#endif
1490 case 'a': // audio device for pcm
1492 continue;
1493 case 'c': // channel of audio mixer
1495 continue;
1496 case 'p': // pass-through audio device
1498 continue;
1499 case 'o': // set display drm device
1501 continue;
1502 case 'd': // set display output
1504 continue;
1505 case 'D': // start plugin in detached state
1506 m_forceDetached = true;
1507 continue;
1508 case 'w': // workarounds
1509 if (!strcasecmp("disable-pip", optarg)) {
1510 m_disablePip = true;
1511#ifdef USE_GLES
1512 } else if (!strcasecmp("disable-ogl-osd", optarg)) {
1514#endif
1515 } else {
1516 fprintf(stderr, gettext("Workaround '%s' unsupported\n"),
1517 optarg);
1518 return 0;
1519 }
1520 continue;
1521 case EOF:
1522 break;
1523 case '-':
1524 fprintf(stderr, gettext("We need no long options\n"));
1525 return 0;
1526 case ':':
1527 fprintf(stderr, gettext("Missing argument for option '%c'\n"), optopt);
1528 return 0;
1529 default:
1530 fprintf(stderr, gettext("Unknown option '%c'\n"), optopt);
1531 return 0;
1532 }
1533 break;
1534 }
1535
1536 while (optind < argc) {
1537 fprintf(stderr, gettext("Unhandled argument '%s'\n"), argv[optind++]);
1538 }
1539
1540 return 1;
1541}
1542
1547{
1548 if (IsDetached())
1549 return;
1550
1552}
1553
1566void cSoftHdDevice::OsdDrawARGB(int xi, int yi, int height, int width, int pitch,
1567 const uint8_t * argb, int x, int y)
1568{
1569 if (IsDetached())
1570 return;
1571
1572 m_pRender->OsdDrawARGB(xi, yi, height, width, pitch, argb, x, y);
1573}
1574
1575#ifdef USE_GLES
1583
1591
1601
1611
1612#endif
1613
1622
1631
1640
1655
1665
1670{
1671 LOGDEBUG("%s:", __FUNCTION__);
1672 m_audioChannelID = -1;
1673}
1674
1683{
1684 *duped = 0;
1685 *dropped = 0;
1686 *counter = 0;
1687 if (m_pRender) {
1689 }
1690}
1691
1692/*****************************************************************************
1693 * media player functions
1694 ****************************************************************************/
1695
1707
1719
1729{
1730 m_pAudio->LazyInit();
1731
1732 if (m_pAudio->IsBufferFull())
1733 return 0;
1734
1736 return 1;
1737}
1738
1748{
1749 m_pAudio->LazyInit();
1750
1752 return 0;
1753
1755
1756 return 1;
1757}
1758
1759/*****************************************************************************
1760 * Detach and attach functionality
1761 ****************************************************************************/
1762
1770{
1771 if (cDevice::Replaying()) {
1772 LOGDEBUG("device: %s: Device is replaying, stop replay first", __FUNCTION__);
1773 StopReplay();
1774 }
1775
1776 if (IsPrimaryDevice(false)) {
1777 m_needsMakePrimary = true;
1778 MakePrimaryDevice(false);
1779 }
1780
1782}
1783
1791{
1792 m_forceDetached = false;
1793
1794 if (m_needsMakePrimary) {
1795 MakePrimaryDevice(true);
1796 m_needsMakePrimary = false;
1797 }
1798
1800}
1801
1806{
1807 std::lock_guard<std::mutex> lock(m_mutex);
1808 return m_state == State::DETACHED;
1809}
1810
1811/*****************************************************************************
1812 * PiP functionality
1813 ****************************************************************************/
1814
1832
1837{
1838 std::lock_guard<std::mutex> lock(m_mutex);
1839 return m_pPipHandler->IsEnabled();
1840}
1841
1854
Audio and Alsa Interface Header File.
Audio Decoder.
void FlushBuffers(void)
Flush the audio decoder buffers.
void Decode(const AVPacket *)
Decode an audio packet.
AVCodecID GetCodecId() const
void SetPassthroughMask(int)
Set audio pass-through mask.
void Open(AVCodecID, AVCodecParameters *=nullptr, AVRational={ .num=1,.den=90000 })
Open and initiate the audio decoder.
void Close(void)
Close the audio decoder.
Hardware device.
int GetQuirks(void)
Get Hardware Quirks.
int GetShortTermMaxJitterMs(void)
int GetLongTermMaxJitterMs(void)
void PacketReceived(void)
Called each time a packet is received.
void Reset(void)
Resets the jitter tracker.
Main Video Stream.
Audio PES Packet Parser.
Definition pes.h:78
Video PES Packet Parser.
Definition pes.h:63
PiP Stream Handler.
Definition pipreceiver.h:55
void ChannelChange(int)
Change the pip channel.
void SwapPosition(void)
Swap pip between normal and alternative position.
void Toggle(void)
Toggle picture-in-picture.
void HandleEvent(enum PipState)
Handle a pip event.
void Disable(void)
Stop picture-in-picture.
void ChannelSwap(bool)
Swap the pip channel with main live channel.
bool IsEnabled(void)
Definition pipreceiver.h:60
void Enable(void)
Start picture-in-picture.
void SetSize(void)
Set size and position for the pip window.
PiP Video Stream.
AVPacket * PopAvPacket(void) override
Pop an audio AVPacket from the reassembly buffer.
Definition pes.cpp:458
Video Stream Reassembly Buffer.
Definition pes.h:144
AVPacket * PopAvPacket(void) override
Definition pes.h:147
bool HasLeadingZero(const uint8_t *, int)
Check if video data has a leading zero byte before the start code.
Definition pes.cpp:441
bool ParseCodecHeader(const uint8_t *, int)
Parse video codec header to detect codec type.
Definition pes.cpp:407
AVCodecID GetCodec(void)
Definition pes.h:127
void Reset(void)
Reset the reassembly buffer.
Definition pes.cpp:627
virtual void Push(const uint8_t *data, int size, int64_t pts)
Definition pes.h:122
bool IsEmpty(void)
Definition pes.h:124
Audio Interface.
Definition audio.h:50
void LazyInit(void)
Initialize audio output module (alsa)
Definition audio.cpp:1195
void ResetHwDelayBaseline(void)
Reset the hw delay baseline.
Definition audio.cpp:1532
int64_t GetInputPtsMs(void)
Definition audio.h:70
void SetPassthroughMask(int)
Set audio passthrough mask.
Definition audio.cpp:1176
void SetHwDelayBaseline(void)
Set the hw delay baseline.
Definition audio.cpp:1512
int64_t GetHardwareOutputPtsTimebaseUnits(void)
Get the hardware output PTS in timebase units.
Definition audio.cpp:1084
void SetVolume(int)
Set mixer volume (0-1000)
Definition audio.cpp:1098
void DropSamplesOlderThanPtsMs(int64_t)
Drop samples older than the given PTS.
Definition audio.cpp:698
int64_t GetOutputPtsMs(void)
Get the output PTS of the ringbuffer.
Definition audio.cpp:1022
void ClockDriftCompensation(void)
Calculate clock drift compensation.
Definition audio.cpp:1966
void Exit(void)
Cleanup audio output module (alsa)
Definition audio.cpp:1210
void SetPaused(bool)
Set audio playback pause state.
Definition audio.cpp:1121
bool HasInputPts(void)
Definition audio.h:69
bool IsBufferFull(void)
Definition audio.h:61
void FlushBuffers(void)
Flush audio buffers.
Definition audio.cpp:981
Plugin Configuration.
Definition config.h:29
bool ConfigParseH264Dimensions
parse h264 stream for width and height for decoder init
Definition config.h:81
const char * ConfigDrmDevice
user requested drm device (e.g. "/dev/dri/card0")
Definition config.h:94
int ConfigVideoAudioDelayMs
config audio delay
Definition config.h:47
const char * ConfigDisplayResolution
display resolution (syntax: "1920x1080@50")
Definition config.h:95
std::atomic< int > StatMaxLongTermAudioJitterMs
logged max overall audio jitter since stream start
Definition config.h:106
int ConfigMaxSizeGPUImageCache
config max gpu image cache size
Definition config.h:85
std::atomic< int > StatMaxShortTermAudioJitterMs
logged max audio jitter of the last 1000 packets
Definition config.h:105
int ConfigDecoderFallbackToSwNumPkts
maximum number of packets sent before fallback to sw decoder
Definition config.h:79
const char * ConfigAudioPCMDevice
audio PCM device
Definition config.h:91
bool ConfigDisableDeint
disable deinterlacer
Definition config.h:77
int ConfigDisableOglOsd
config disable ogl osd
Definition config.h:97
int ConfigAdditionalBufferLengthMs
config size ms of a/v buffer
Definition config.h:76
const char * ConfigAudioMixerChannel
audio mixer channel name
Definition config.h:93
std::atomic< int > StatMaxShortTermVideoJitterMs
logged max video jitter of the last 1000 packets
Definition config.h:107
bool ConfigDecoderNeedsIFrame
start h264 decoder only when an I-Frame arrives
Definition config.h:80
std::atomic< int > StatMaxLongTermVideoJitterMs
logged max overall video jitter since stream start
Definition config.h:108
const char * ConfigAudioPassthroughDevice
audio passthrough device
Definition config.h:92
void SetState(State)
Sets the device into the given state.
void OsdDrawARGB(int, int, int, int, int, const uint8_t *, int, int)
Draw an OSD pixmap.
cReassemblyBufferVideo m_videoReassemblyBuffer
video pes reassembly buffer
void Stop(void)
Called by VDR when the plugin is stopped.
bool m_pipUseAlt
use alternative pip position
cReassemblyBufferVideo m_pipReassemblyBuffer
pip pes reassembly buffer
void PipChannelSwap(bool)
cVideoStream * m_pPipStream
pointer to pip video stream
void FlushAudio(void)
Clear all audio data from the decoder and ringbuffer.
void PipSwapPosition(void)
static constexpr int MIN_BUFFER_FILL_LEVEL_THRESHOLD_MS
min buffering threshold in ms
int m_volume
track the volume in the device (for attach)
virtual void StillPicture(const uchar *, int)
Display the given I-frame as a still picture.
void PipSetSize(void)
cSoftOsdProvider * m_pOsdProvider
pointer to cSoftOsdProvider object
cVideoStream * m_pVideoStream
pointer to main video stream
cReassemblyBufferAudio m_audioReassemblyBuffer
audio pes reassembly buffer
int MaxSizeGPUImageCache(void)
Get the maximum GPU image cache size.
std::atomic< bool > m_receivedAudio
flag if audio packets have been received
void SetRenderPipSize(void)
Wrapper functions for cVideoRender and cPipHandler.
cDvbSpuDecoder * m_pSpuDecoder
pointer to spu decoder
void OnEnteringState(State)
Actions to be performed when entering a state.
int Start(void)
Called by VDR when the plugin is started.
void SetEnableOglOsd(void)
Enables OpenGL/ES Osd.
virtual void GetVideoSize(int &, int &, double &)
Get the video size.
int PlayAudioPkts(AVPacket *)
Play an audio packet.
virtual void GetOsdSize(int &, int &, double &)
Returns the width, height and aspect ratio the OSD.
void SetEnableHdr(bool)
Enable HDR display mode.
void SetRenderPipActive(bool)
void GetStats(int *, int *, int *)
Get statistics from the renderer.
void ResetChannelId(void)
Reset the channel ID (restarts audio)
cHardwareDevice * m_pHardwareDevice
pointer to hardware device description
virtual bool CanReplay(void) const
Return true if this device can currently start a replay session.
virtual void SetDigitalAudioDevice(bool)
std::mutex m_mutex
mutex to lock the state machine
virtual bool HasDecoder(void) const
Tells whether this device has an MPEG decoder.
virtual void Clear(void)
Clears all video and audio data from the device.
void OnEventReceived(const Event &)
Event handler for playback state transitions.
cPipHandler * m_pPipHandler
pointer to pip handler
void Detach(void)
Detach the device.
virtual int PlayVideo(const uchar *, int)
Play a video packet of the main videostream.
void ResetPipStream(void)
Resets pip stream and render pipeline.
double m_screenRefreshRateHz
std::chrono::steady_clock::time_point m_dataReceivedTime
timestamp, when the first audio or video data after a channel switch arrives in Play*()
std::atomic< State > m_state
current plugin state, normal plugin start sets detached state
void OnLeavingState(State)
Actions to be performed when leaving a state.
virtual bool SetPlayMode(ePlayMode)
Sets the device into the given play mode.
cAudioDecoder * m_pAudioDecoder
pointer to cAudioDecoder object
void SetAudioCodec(enum AVCodecID, AVCodecParameters *, AVRational)
Open an audio codec.
virtual void Play(void)
Sets the device into play mode (after a previous trick mode, or pause)
bool IsBufferingThresholdReached(void)
Check if the buffering threshold has been reached.
cVideoRender * m_pRender
pointer to cVideoRender object
virtual void SetAudioChannelDevice(int)
cSoftHdGrab * m_pGrab
pointer to grabber object
const char * CommandLineHelp(void)
Return command line help string.
int OglOsdIsDisabled(void)
Is the OpenGL/ES osd disabled?
cSoftHdDevice(cSoftHdConfig *)
Create the device.
int PlayPipVideo(const uchar *, int)
Play a video packet of the pip videostream.
bool m_needsMakePrimary
virtual void ChannelSwitch(const cDevice *, int, bool)
Monitor a channel switch triggered by VDR (cStatus::ChannelSwitch())
cSoftHdAudio * m_pAudio
pointer to cSoftHdAudio object
cSoftHdConfig * m_pConfig
pointer to cSoftHdConfig object
virtual cRect CanScaleVideo(const cRect &, int taCenter)
Ask the output, if it can scale video.
bool m_disablePip
true, if pip was disabled by the user
virtual void SetVolumeDevice(int)
Sets the audio volume on this device (Volume = 0...255).
virtual int64_t GetSTC(void)
Gets the current System Time Counter, which can be used to synchronize audio, video and subtitles.
virtual bool Flush(int=0)
Flush the device output buffers.
bool IsDetached(void) const
Returns true, if the device is detached.
virtual void TrickSpeed(int, bool)
Sets the device into a mode where replay is done slower.
std::chrono::steady_clock::time_point m_channelSwitchStartTime
timestamp, when VDR triggered a channel switch
void SetDecoderFallbackToSw(bool)
Force the decoder to fallback to software if the hardware decoder fails after the configured amount o...
virtual int PlayAudio(const uchar *, int, uchar)
Play an audio packet.
void PipToggle(void)
bool PipIsEnabled(void)
Returns true, if pip is currently enabled.
std::mutex m_sizeMutex
mutex to lock screen size (which is accessed by different threads)
bool Initialize(void)
Initialize the device.
std::atomic< bool > m_receivedVideo
flag if video packets have been received
void SetDecoderNeedsIFrame(void)
Forces the h264 decoder to wait for an I-Frame to start.
int PlayVideoInternal(cVideoStream *, cReassemblyBufferVideo *, const uchar *, int, bool)
Play a video packet.
virtual int GetAudioChannelDevice(void)
int PlayVideoPkts(AVPacket *)
Play a video packet.
void SetScreenSize(int, int, double)
Set the screen size.
cJitterTracker m_audioJitterTracker
audio jitter tracker
int GetBufferFillLevelThresholdMs()
Returns the buffer fill level threshold in milliseconds.
void HandleStillPicture(const uchar *data, int size)
The still picture data received from VDR can contain multiple PES packets.
virtual void SetVideoDisplayFormat(eVideoDisplayFormat)
Sets the video display format.
virtual void Freeze(void)
Puts the device into "freeze frame" mode.
void SetParseH264Dimensions(void)
Parse the h264 stream width and height before starting the decoder.
void SetDisableOglOsd(void)
Disables OpenGL/ES Osd (called from setup menu or conf)
bool m_forceDetached
start the plugin in detached state
virtual ~cSoftHdDevice(void)
Destroy the device.
int m_audioChannelID
current audio channel ID
void PipDisable(void)
virtual void SetVideoFormat(bool)
Set the video format.
virtual void MakePrimaryDevice(bool)
Informs a device that it will be the primary device.
void SetVideoCodec(enum AVCodecID, AVCodecParameters *, AVRational)
Open a video codec.
void PipEnable(void)
void SetPassthroughMask(int)
Set the passthrough mask (called from setup menu or conf)
void SetDisableDeint(void)
Disables deinterlacer (called from setup menu or conf)
virtual uchar * GrabImage(int &, bool, int, int, int)
Grabs the currently visible screen image.
virtual cSpuDecoder * GetSpuDecoder(void)
Get the device SPU decoder.
cJitterTracker m_videoJitterTracker
video jitter tracker
virtual void SetAudioTrackDevice(eTrackType)
std::atomic< PlaybackMode > m_playbackMode
current playback mode
void OsdClose(void)
Close the OSD.
int64_t GetFirstAudioPtsMsToPlay()
Calculate the first audio PTS that should be played during synchronized playback.
virtual void ScaleVideo(const cRect &=cRect::Null)
Scale the currently shown video.
int64_t GetFirstVideoPtsMsToPlay()
int ProcessArgs(int, char *[])
Process the command line arguments.
void PipChannelChange(int)
virtual bool Poll(cPoller &, int=0)
Return true if the device itself or any of the file handles in poller is ready for further action.
void Attach(void)
Attach the device again.
Grabbing Processor.
Definition grab.h:85
bool Start(bool, int, int, int, int, int)
Start a grab in the video renderer.
Definition grab.cpp:340
uint8_t * Image(void)
Definition grab.h:91
bool Active(void)
Definition grab.h:89
int Size(void)
Definition grab.h:92
Plugin OSD provider.
void RequestStopOpenGlThread(void)
Initiate a stop of the OpenGL thread without waiting.
void StopOpenGlThread(void)
Stop the OpenGL thread and cancel it if necessary.
void UnlockOpenGlThread(void)
Unlock the OpenGL thread.
bool LockOpenGlThread(void)
Lock the OpenGL thread.
Video Renderer.
void PushPipFrame(AVFrame *)
Push a PiP frame into the render ringbuffer.
bool IsOutputBufferFull(void)
Check, if the main render output buffer is full.
void SetEnableHdr(bool enable)
void Reset()
Reset the renderer.
void ResetBufferReuseStrategy()
void Halt(void)
void OsdClear(void)
Clear the OSD (draw an empty/ transparent OSD)
void ScheduleVideoPlaybackPauseAt(int64_t ptsMs)
void ScheduleResyncAtPtsMs(int64_t ptsMs)
void ClearDecoderToDisplayQueue(void)
Clear (empty) the decoder to display queue.
void Init(void)
Initialize the renderer.
void ResetDecodingStrategy()
void Exit(void)
Exit and cleanup the renderer.
void EnableOglOsd(void)
void ResetPipBufferReuseStrategy()
void GetStats(int *, int *, int *)
Get some rendering statistics.
void DisplayBlackFrame(void)
Display a black video frame.
void PushMainFrame(AVFrame *)
Push a main frame into the render ringbuffer.
void SetVideoOutputPosition(const cRect &)
Set size and position of the video on the screen.
int64_t GetOutputPtsMs(void)
Get the output PTS in milliseconds.
void SetPipActive(bool on)
void ClearPipDecoderToDisplayQueue(void)
Clear (empty) the decoder to display queue.
cQueue< cDrmBuffer > * GetPipOutputBuffer(void)
void Resume(void)
void SetStillpicture(bool active)
void SchedulePlaybackStartAtPtsMs(int64_t ptsMs)
int64_t GetVideoClock(void)
void OsdDrawARGB(int, int, int, int, int, const uint8_t *, int, int)
Draw an OSD ARGB image.
void SetScheduleAudioResume(bool resume)
void SetDisplayOneFrameThenPause(bool pause)
void SetPipSize(bool)
Set the size and position of the pip window.
void DisableOglOsd(void)
void SetPlaybackPaused(bool pause)
void ResetFrameCounter(void)
Send start condition to video thread.
void SetTrickSpeed(double, bool, bool)
Set the trickspeed parameters.
void ResetPipDecodingStrategy()
cQueue< cDrmBuffer > * GetMainOutputBuffer(void)
Video Input Stream.
Definition videostream.h:47
void GetVideoSize(int *, int *, double *)
Get video size and aspect ratio.
void SetDecoderFallbackToSwNumPkts(int numPackets)
Definition videostream.h:90
void Flush(void)
Flushes the video stream by finalizing any pending data.
void StartDecoder()
Start the decoder.
void ClearVdrCoreToDecoderQueue(void)
Clears all video stream data, which is buffered to be decoded.
void ResetInputPts(void)
Definition videostream.h:77
void Resume(void)
Definition videostream.h:65
int GetVideoPacketMax(void)
Definition videostream.h:79
void SetStartDecodingWithIFrame(bool enable)
Definition videostream.h:88
size_t GetAvPacketsFilled(void)
Definition videostream.h:70
void DisableDeint(bool disable)
Definition videostream.h:87
void CloseDecoder(void)
Close the decoder.
void Exit(void)
Exit video stream.
void CancelFilterThread(void)
Stop filter thread.
void FlushDecoder(void)
Flush the decoder.
void Open(AVCodecID, AVCodecParameters *=nullptr, AVRational={ .num=1,.den=90000 })
Open a video codec.
bool PushAvPacket(AVPacket *avpkt)
Pushes a pre-assembled AVPacket directly to the processing queue.
bool IsInputBufferFull(void)
Definition videostream.h:71
void ResetFilterThreadNeededCheck()
Definition videostream.h:83
int64_t GetInputPtsMs(void)
void SetParseH264Dimensions(bool enable)
Definition videostream.h:89
void Halt(void)
Definition videostream.h:64
virtual void SetDeinterlacerDeactivated(bool deactivate)
Definition videostream.h:85
void ResetTrickSpeedFramesSentCounter(void)
Definition videostream.h:73
bool HasInputPts(void)
Definition videostream.h:74
Audio Decoder Header File.
Plugin Configuration Header File.
__attribute__((weak)) union gbm_bo_handle gbm_bo_get_handle_for_plane(struct gbm_bo *bo
State Machine and Event Header File.
Grabbing Interface Header File.
const char * EventToString(const Event &e)
State
const char * StateToString(State s)
static void PrintStreamData(const uchar *payload)
Print the start code, stream id, length, first three bytes (start code) of the payload,...
@ AUDIO_AND_VIDEO
@ VIDEO_ONLY
@ AUDIO_ONLY
@ NONE
@ PLAY
@ STOP
@ BUFFERING
@ TRICK_SPEED
@ DETACHED
#define LOGDEBUG2
log to LOG_DEBUG and add a prefix
Definition logger.h:47
#define LOGDEBUG
log to LOG_DEBUG
Definition logger.h:45
#define LOGERROR
log to LOG_ERR
Definition logger.h:39
#define AV_NOPTS_VALUE
Definition misc.h:74
#define LOGWARNING
log to LOG_WARN
Definition logger.h:41
std::variant< PlayEvent, PauseEvent, StopEvent, TrickSpeedEvent, StillPictureEvent, DetachEvent, AttachEvent, BufferUnderrunEvent, BufferingThresholdReachedEvent, PipEvent, ScheduleResyncAtPtsMsEvent, ResyncEvent > Event
Definition event.h:82
#define LOGFATAL
log to LOG_ERR and abort
Definition logger.h:37
static const char * Timestamp2String(int64_t ts, uint8_t divisor)
Nice time-stamp string.
Definition misc.h:127
@ PIPSTOP
Definition event.h:34
@ L_AV_SYNC
audio/video sync logs
Definition logger.h:57
@ L_OSD
osd logs
Definition logger.h:59
@ L_CODEC
codec logs
Definition logger.h:61
@ L_GRAB
grabbing logs
Definition logger.h:69
Describes a hardware device.
Jitter Tracking of Incoming Packets Header File.
Logger Header File.
PES Packet Parser Header File.
PiP (Picture-in-Picture) Interface Header File.
Output Device Header File.
OSD Provider Header File.
Video Renderer (Display) Header File.
Video Input Stream Header File.