vdr-plugin-softhddevice-drm-gles 1.6.8-daba64b
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#include <vdr/thread.h>
31
32#include "audio.h"
33#include "codec_audio.h"
34#include "config.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 "statemachine.h"
44#include "videorender.h"
45#include "videostream.h"
46
55 : m_pConfig(config)
56{
57 m_pStateMachine = std::make_unique<cStateMachine>(this);
58}
59
66{
67 if (!m_initialized)
68 return;
69
70 m_initialized = false; // not necessary, just for documentation
71
72 delete m_pEventHandler;
73 delete m_pHardwareDevice;
74 delete m_pSpuDecoder;
75}
76
77/*********************************************************************
78 * VDR cPlugin interface (wrapped by cPluginSoftHdDevice)
79 ********************************************************************/
80
85{
86 LOGDEBUG("device: %s:", __FUNCTION__);
87
88 // the following are deleted in the destructor
92
93 m_channelSwitchStartTime = std::chrono::steady_clock::now();
95
98
99 m_initialized = true;
100
101 return true;
102}
103
108{
109 LOGDEBUG("device: %s", __FUNCTION__);
111
112 return true;
113}
114
119{
120 LOGDEBUG("device: %s", __FUNCTION__);
123}
124
125/*********************************************************************
126 * VDR cDevice interface
127 ********************************************************************/
128
135{
136 LOGDEBUG("device: %s: %d", __FUNCTION__, on);
137
138 if (on)
139 m_pOsdProvider = new cSoftOsdProvider(this); // no need to delete it, VDR does it
140
141 cDevice::MakePrimaryDevice(on);
142}
143
148{
149 bool hasDecoder = !IsDetached();
150
151// LOGDEBUG("device: %s: %d", __FUNCTION__, hasDecoder);
152
153 return hasDecoder;
154}
155
163{
164 LOGDEBUG("device: %s:", __FUNCTION__);
165 if (!IsPrimaryDevice())
166 return NULL;
167
168 return m_pSpuDecoder;
169}
170
180uchar *cSoftHdDevice::GrabImage(int &size, bool jpeg, int quality, int width, int height)
181{
182 if (!width || !height) {
183 LOGWARNING("device: %s: width or height is 0 - skip!", __FUNCTION__);
184 return nullptr;
185 }
186
187 if (IsDetached())
188 return nullptr;
189
190 if (m_pGrab->IsActive()) {
191 LOGWARNING("device: %s: wait for the last grab to be finished - skip!", __FUNCTION__);
192 return nullptr;
193 }
194
195 LOGDEBUG2(L_GRAB, "device: %s: %d, %d, %d, %dx%d", __FUNCTION__, size, jpeg, quality, width, height);
196
197 if (!m_pGrab->Start(jpeg, quality, width, height, m_screenWidth, m_screenHeight))
198 return nullptr;
199
200 if (!m_pGrab->ProcessGrab())
201 return nullptr;
202
203 size = m_pGrab->Size();
205
206 m_pGrab->Finish();
207
208 return result;
209}
210
218{
219 LOGDEBUG("device: %s: %d", __FUNCTION__, videoDisplayFormat);
220
221 cDevice::SetVideoDisplayFormat(videoDisplayFormat);
222}
223
235{
236 LOGDEBUG("device: %s: %d", __FUNCTION__, videoFormat16_9);
237
238 // FIXME: 4:3 / 16:9 video format not supported.
239 SetVideoDisplayFormat(eVideoDisplayFormat(Setup.VideoDisplayFormat));
240}
241
254void cSoftHdDevice::GetVideoSize(int &width, int &height, double &aspectRatio)
255{
256// LOGDEBUG("device: %s: %d x %d @ %f", __FUNCTION__, *width, *height, *aspectRatio);
257
258 if (IsDetached()) { // return default values according to vdr docs
259 width = 0;
260 height = 0;
261 aspectRatio = 1.0;
262 return;
263 }
264
265 m_pVideoStream->GetVideoSize(&width, &height, &aspectRatio);
266}
267
277void cSoftHdDevice::GetOsdSize(int &width, int &height, double &aspectRatio)
278{
279 if (IsDetached()) { // hardcode to 1920x1080 in detached state
280 width = 1920;
281 height = 1080;
282 aspectRatio = (double)width / (double)height;
283 return;
284 }
285
286 std::lock_guard<std::mutex> lock(m_sizeMutex);
287 width = m_osdWidth;
288 height = m_osdHeight;
289 aspectRatio = (double)width / (double)height;
290}
291
298{
299 if (IsDetached())
300 return;
301
302 LOGDEBUG("device: %s: %d", __FUNCTION__, volume);
304 m_pAudio->SetVolume((volume * 1000) / 255);
305}
306
311{
312 bool canReplay = !IsDetached();
313
314 LOGDEBUG("device: %s: %d", __FUNCTION__, canReplay);
315
316 return canReplay;
317}
318
325{
326 LOGDEBUG("device: %s: %d", __FUNCTION__, play_mode);
327
328 // A new play mode arrived, attach first if we did detach because of an external player
332 }
333
334 switch (play_mode) {
335 case pmNone:
337 break;
338 case pmAudioVideo:
339 case pmAudioOnly:
340 case pmAudioOnlyBlack:
341 case pmVideoOnly:
343 break;
345 // External players like mpv (vdr-plugin-mpv) want to acquire DRM/ALSA
346 // so we release it here and set a flag. As soon as the next SetPlayMode arrives
347 // we then can attach again before changing to the new playmode.
351 break;
352 default:
353 LOGERROR("device: %s: playmode not supported %d", play_mode);
354 return false;
355 break;
356 }
357
358 return true;
359}
360
374int cSoftHdDevice::PlayAudio(const uchar *data, int size, uchar id)
375{
376// LOGDEBUG("device: %s: %p %p %d %d", __FUNCTION__, this, data, size, id);
377 if (IsDetached())
378 return size;
379
380 m_receivedAudio = true;
381
382 if (m_pAudio->IsBufferFull())
383 return 0;
384
385 cPesAudio pesPacket((const uint8_t*)data, size);
386
387 if (!pesPacket.IsValid()) {
389
390 return size;
391 }
392
394 auto now = std::chrono::steady_clock::now();
395 auto timeUntilFirstPacketReceived = std::chrono::duration_cast<std::chrono::milliseconds>(now - m_channelSwitchStartTime).count();
396 LOGDEBUG("device: first valid audio packet arrives %dms after channel switch was triggered", timeUntilFirstPacketReceived);
397
400 }
402
403 if (Transferring()) { // compensation is only necessary with live streams
408 }
409
410 if (m_audioChannelID != id) {
414 LOGDEBUG("device: %s: new channel id 0x%02X", __FUNCTION__, m_audioChannelID);
415 }
416
417 m_audioReassemblyBuffer.Push(pesPacket.GetPayload(), pesPacket.GetPayloadSize(), pesPacket.GetPts());
418
421
422 // unpause audio, if the fast channel switch mode wants it to be started,
423 // the audio buffer reached the threshold and we are in live tv mode
425 m_pAudio->SetPaused(false);
426
428 do {
430 break;
431
433 // The playback has just started
436 }
437
441 } while (avpkt != nullptr);
442
443 return size;
444}
445
460int cSoftHdDevice::PlayVideo(const uchar *data, int size)
461{
462// LOGDEBUG("device: %s: %p %d", __FUNCTION__, data, size);
463 if (IsDetached())
464 return size;
465
466 m_receivedVideo = true;
467
469}
470
476{
477 if (IsDetached())
478 return AV_NOPTS_VALUE;
479
480 switch (m_playbackMode) {
481 case NONE:
482 return AV_NOPTS_VALUE;
483 case AUDIO_AND_VIDEO:
484 case VIDEO_ONLY:
485 return m_pRender->GetVideoClock();
486 case AUDIO_ONLY:
488 }
489
490 abort();
491}
492
501{
503 return rect;
504
505 double scaleFactor = std::min((double)m_screenWidth / m_osdWidth, (double)m_screenHeight / m_osdHeight);
506 int width = std::lround(scaleFactor * rect.Width());
507 int height = std::lround(scaleFactor * rect.Height());
508 int x = std::lround(scaleFactor * rect.X());
509 int y = std::lround(scaleFactor * rect.Y());
510
511 x = std::max(0, x);
512 y = std::max(0, y);
513 if (x + width > m_screenWidth)
514 width = m_screenWidth - x;
515 if (y + height > m_screenHeight)
516 height = m_screenHeight - y;
517
518 if (width <= 0 || height <= 0)
519 return cRect::Null;
520
521 LOGDEBUG2(L_DRM, "device: %s: scale rect %dx%d-%d|%d -> %dx%d-%d|%d", __FUNCTION__,
522 rect.Width(), rect.Height(), rect.X(), rect.Y(), width, height, x, y);
523
524 return cRect(x, y, width, height);
525}
526
536{
537 if (IsDetached())
538 return;
539
540 LOGDEBUG2(L_OSD, "device: %s: %dx%d%+d%+d",
541 __FUNCTION__, rect.Width(), rect.Height(), rect.X(), rect.Y());
542
543 if (m_pRender)
545}
546
559void cSoftHdDevice::TrickSpeed(int speed, bool forward)
560{
561 LOGDEBUG("device: %s: %d %s", __FUNCTION__, speed, forward ? "forward" : "backward");
562
563 // This normalizes the VDR frame displaying count into a factor, representing how fast/slow the playback shall be.
564 // 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).
565 // This is necessary because VDR sends only I-frames during trickspeed, but the distance between I-frames depends on the encoding parameters.
566 // 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.
567
568 double normalizedSpeed = 1;
569 static constexpr double MAX_SPEED = 3;
570
571 // these are arbitrary values, which feel just right
572 static constexpr double FAST_TRICKSPEED_FACTOR = 5; // the higher the factor, the faster the fast forward/reverse
573 static constexpr double SLOW_FORWARD_FACTOR = 2; // the higher the factor, the slower the slow-mo
574
575 // Fastest speed in reverse slow-mo is the original speed. Slower speeds are too slow, because of the already low frame rate.
576 static constexpr double SLOW_REVERSE_FACTOR = 1;
577
578 // speed of the trickspeed (VDR's magic frame displaying count)
579 switch (speed) {
580 case 6:
581 case 8:
582 case 63:
583 normalizedSpeed = 1; // slowest (both, in fast trickspeed and slow-mo)
584 break;
585 case 3:
586 case 4:
587 case 48:
588 normalizedSpeed = 2;
589 break;
590 case 1:
591 case 2:
592 case 24:
593 normalizedSpeed = 3; // fastest (both, in fast trickspeed and slow-mo)
594 break;
595 }
596
597 // figure out if VDR demands slow-mo or fast trickspeed
598 double tmp;
599 switch (speed) {
600 case 8:
601 case 4:
602 case 2:
603 case 63:
604 case 48:
605 case 24:
606 // slow-mo
607 tmp = (MAX_SPEED + 1) - normalizedSpeed;
608
609 if (forward)
611 else
613
614 normalizedSpeed = 1 / tmp;
615 break;
616 default:
617 // fast trickspeed
619 break;
620 }
621
622 TriggerEvent(TrickSpeedEvent{normalizedSpeed, speed != 0, forward});
623}
624
633{
634 LOGDEBUG("device: %s:", __FUNCTION__);
635 cDevice::Clear();
636
637 if (IsDetached())
638 return;
639
640 m_pRender->Halt();
642
645
649
652
653 m_pRender->Reset();
654
655 m_pAudio->SetPaused(true);
657 FlushAudio();
658
659 m_pStateMachine->ChangeState(BUFFERING);
660
661 m_pRender->Resume();
663}
664
671{
672 cDevice::Play();
673
675}
676
681{
682 LOGDEBUG("device: %s:", __FUNCTION__);
683 cDevice::Freeze();
684
686}
687
694void cSoftHdDevice::StillPicture(const uchar *data, int size)
695{
696 LOGDEBUG("device: %s: %s %p %d", __FUNCTION__, data[0] == 0x47 ? "ts" : "pes", data, size);
697
698 if (data[0] == 0x47) { // ts sync byte
699 cDevice::StillPicture(data, size);
700 return;
701 }
702
703 TriggerEvent(StillPictureEvent{data, size});
704}
705
719{
720// LOGDEBUG("device: %s: timeout %d", __FUNCTION__, timeout_ms);
721 if (IsDetached())
722 return true;
723
725 return true;
726
727 usleep(timeoutMs * 1000);
728
729 return false;
730}
731
748{
749 if (IsDetached())
750 return true;
751
752// LOGDEBUG("device: %s: timeout %d ms", __FUNCTION__, timeoutMs);
753
754 const auto buffersEmpty = [&]() {
755 return m_playbackMode == AUDIO_ONLY
758 };
759
761 while (!buffersEmpty() && !timeout.TimedOut())
762 cCondWait::SleepMs(std::min(5, timeoutMs));
763
764 return buffersEmpty();
765}
766
767#if APIVERSNUM >= 30014
773bool cSoftHdDevice::Drain(void)
774{
775 if (IsDetached())
776 return true;
777
778 // enter drain mode once
779 if (!m_draining) {
780 LOGDEBUG("device: %s: start draining", __FUNCTION__);
781 m_draining = true;
785 }
786
787 const auto buffersEmpty = [&]() {
788 return m_playbackMode == AUDIO_ONLY
791 };
792
793 if (!buffersEmpty())
794 return false;
795
796 LOGDEBUG("device: %s: drained, buffers are empty", __FUNCTION__);
797 m_draining = false;
798
799 return true;
800}
801#endif
802
803/*********************************************************************
804 * VDR cStatus interface
805 ********************************************************************/
806
813void cSoftHdDevice::ChannelSwitch(const cDevice *device, int channelNum, bool liveView)
814{
815 if (device != cDevice::PrimaryDevice())
816 return;
817
818 if (!liveView)
819 return;
820
821 if (channelNum == 0)
822 m_channelSwitchStartTime = std::chrono::steady_clock::now();
823}
824
825/*********************************************************************
826 * cSoftHdDevice public API - playback, display, decoder control
827 ********************************************************************/
828
837
846
855
870
878
885{
887
891 if (!mode->width || !m_pRender->CanHandleMode(mode))
893 } else if (idx >= CONFIG_DISPLAY_MODE_MANUAL)
895
896 // Check, if the requested mode differs from the current one at all
897 if (!m_pConfig->CompareCurrentMode(mode)) {
898 LOGDEBUG("Add display mode change event to %s mode %dx%d@%.2f%s",
899 idx == CONFIG_DISPLAY_MODE_DEFAULT ? "default" :
900 (idx == CONFIG_DISPLAY_MODE_FOLLOW_VIDEO ? "follow video" :
901 (idx == CONFIG_DISPLAY_MODE_FOLLOW_VIDEO_INTERLACED ? "follow video interlaced" :
902 "fixed")),
903 mode->width, mode->height, mode->refreshRateHz, mode->interlaced ? "i" : "");
905 }
906}
907
935{
936 if (m_pStateMachine->GetState() != BUFFERING)
937 return false;
938
942
943 // 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.
944 // Check for buffer fill level only if at least one PES packet was reassembled and pushed to the respective decoder.
947
949 LOGDEBUG("device: %s: Detected audio only", __FUNCTION__);
950 return true;
952 LOGDEBUG("device: %s: Detected video only", __FUNCTION__);
953 return true;
955 return false; // Either no video or no audio received, yet. Or, video didn't make it to the output buffer, yet.
956
959
961
962 // if channel switch mode is CHANNEL_SWITCH_FAST_AUDIO, wait for audio to come up with video before firing a BufferingThresholdReached
964
965 bool reached = m_pRender->IsOutputBufferFull() && // video decoder output buffer (audio hardware output buffer is negligible)
966 syncedVideoBufferFillLevelMs > GetBufferFillLevelThresholdMs() && // video decoder input buffer
967 syncedAudioBufferFillLevelMs > GetBufferFillLevelThresholdMs() && // audio decoder output buffer
969
970 if (reached) {
971 LOGDEBUG2(L_AV_SYNC, "buffering threshold reached - PTS: %s (audio), %s (video) - buffer fill levels: %ldms (audio) %ldms (video)",
976 }
977
978 return reached;
979}
980
990{
991 if (m_pStateMachine->GetState() != BUFFERING)
992 return false;
993
997
998 // only start audio playback, if video is already there
1000 return false;
1001
1004 LOGDEBUG2(L_AV_SYNC, "audio buffer reached threshold %dms - PTS: %s (audio), %s (video) - buffer fill levels: %ldms (audio)",
1009 return true;
1010 }
1011
1012 return false;
1013}
1014
1015/*********************************************************************
1016 * cSoftHdDevice public API - osd control
1017 ********************************************************************/
1018
1019#ifdef USE_GLES
1027
1035
1045
1055#endif
1056
1061{
1062 if (IsDetached())
1063 return;
1064
1066}
1067
1080void cSoftHdDevice::OsdDrawARGB(int xi, int yi, int height, int width, int pitch,
1081 const uint8_t * argb, int x, int y)
1082{
1083 if (IsDetached())
1084 return;
1085
1086 m_pRender->OsdDrawARGB(xi, yi, height, width, pitch, argb, x, y);
1087}
1088
1095void cSoftHdDevice::SetOsdSize(int width, int height)
1096{
1097 std::lock_guard<std::mutex> lock(m_sizeMutex);
1098 m_osdWidth = width;
1099 m_osdHeight = height;
1100}
1101
1108void cSoftHdDevice::SetScreenSize(int width, int height)
1109{
1110 std::lock_guard<std::mutex> lock(m_sizeMutex);
1111 m_screenWidth = width;
1112 m_screenHeight = height;
1113}
1114
1115/*********************************************************************
1116 * cSoftHdDevice public API - audio control
1117 ********************************************************************/
1118
1128
1133{
1134 LOGDEBUG("%s:", __FUNCTION__);
1135 m_audioChannelID = -1;
1136}
1137
1138/*********************************************************************
1139 * cSoftHdDevice public API - logging, statistics
1140 ********************************************************************/
1141
1150{
1151 *duped = 0;
1152 *dropped = 0;
1153 *counter = 0;
1154 if (m_pRender) {
1156 }
1157}
1158
1159/*********************************************************************
1160 * cSoftHdDevice public API - mediaplayer
1161 ********************************************************************/
1162
1174
1186
1196{
1197 if (m_pAudio->LazyInit())
1198 LOGFATAL("%s: audio init failed, abort!", __FUNCTION__);
1199
1200 if (m_pAudio->IsBufferFull())
1201 return 0;
1202
1204 return 1;
1205}
1206
1216{
1217 if (m_pAudio->LazyInit())
1218 LOGFATAL("%s: audio init failed, abort!", __FUNCTION__);
1219
1221 return 0;
1222
1224
1225 return 1;
1226}
1227
1228/*********************************************************************
1229 * cSoftHdDevice public API - detach/ attach
1230 ********************************************************************/
1231
1239{
1240 if (cDevice::Replaying()) {
1241 LOGDEBUG("device: %s: Device is replaying, stop replay first", __FUNCTION__);
1242 StopReplay();
1243 }
1244
1245 if (IsPrimaryDevice(false)) {
1246 m_needsMakePrimary = true;
1247 MakePrimaryDevice(false);
1248 }
1249
1252}
1253
1261{
1262 m_forceDetached = false;
1263
1264 if (m_needsMakePrimary) {
1265 MakePrimaryDevice(true);
1266 m_needsMakePrimary = false;
1267 }
1268
1270}
1271
1276{
1277 std::lock_guard<std::mutex> lock(m_mutex);
1278 return m_pStateMachine->GetState() == State::DETACHED;
1279}
1280
1281/*********************************************************************
1282 * cSoftHdDevice public API - pip
1283 ********************************************************************/
1284
1295int cSoftHdDevice::PlayPipVideo(const uchar *data, int size)
1296{
1297// LOGDEBUG("device: %s: %p %d", __FUNCTION__, data, size);
1298
1299 // This is a bit hacky:
1300 // Because we do no sync with the pip stream, we simply drop data
1301 // if the input buffer is full -> this prevents us from having a buffer overflow
1302 // caused by the pip stream.
1304 return size;
1305
1306 return PlayVideoInternal(m_pPipStream, &m_pipReassemblyBuffer, data, size, false, false);
1307}
1308
1332
1337{
1338 std::lock_guard<std::mutex> lock(m_mutex);
1339 return m_pPipHandler->IsEnabled();
1340}
1341
1349
1350/*
1351 * Wrapper functions for cVideoRender and cPipHandler
1352 */
1354{
1355 std::lock_guard<std::mutex> lock(m_mutex);
1356 m_pRender->Halt();
1358 m_pRender->Resume();
1359};
1360
1362{
1363 std::lock_guard<std::mutex> lock(m_mutex);
1364 m_pRender->Halt();
1365 m_pRender->SetPipActive(active);
1366 m_pRender->Resume();
1367};
1368
1369/*********************************************************************
1370 * cSoftHdDevice private functions
1371 ********************************************************************/
1372
1381static void PrintStreamData(const uchar *payload)
1382{
1383 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",
1384 payload[0],
1385 payload[1],
1386 payload[2],
1387 payload[3],
1388 payload[4],
1389 payload[5],
1390 payload[6],
1391 payload[7],
1392 payload[8],
1393 payload[9],
1394 payload[10],
1395 payload[11],
1396 payload[12],
1397 payload[13],
1398 payload[14],
1399 payload[15],
1400 payload[16],
1401 payload[17],
1402 payload[18],
1403 payload[19],
1404 payload[20],
1405 payload[21],
1406 payload[22],
1407 payload[23],
1408 payload[24]
1409 );
1410}
1411
1423{
1424 // LOGDEBUG("device: %s: %p %d %s", __FUNCTION__, data, size, mainStream ? "video" : "pip");
1425
1426 if (stream->IsInputBufferFull())
1427 return 0;
1428
1429 cPesVideo pesPacket((const uint8_t*)data, size);
1430
1431 if (!pesPacket.IsValid()) {
1432 buffer->Reset();
1433
1434 return size;
1435 }
1436
1437 if (mainStream) {
1439 auto now = std::chrono::steady_clock::now();
1440 auto timeUntilFirstPacketReceived = std::chrono::duration_cast<std::chrono::milliseconds>(now - m_channelSwitchStartTime).count();
1441 LOGDEBUG("device: first valid video packet arrives %dms after channel switch was triggered", timeUntilFirstPacketReceived);
1442
1445
1446 }
1447 m_receivedValidVideo = true;
1448 }
1449
1450 if (trackJitter) {
1454 }
1455
1456 if (stream->GetCodecId() == AV_CODEC_ID_NONE) {
1457 // The playback has just started
1458 if (!pesPacket.HasPts() || !buffer->ParseCodecHeader(pesPacket.GetPayload(), pesPacket.GetPayloadSize())) {
1459 // received the middle of fragmented data, wait for the next PES packets with the start of a new frame
1460 return size;
1461 }
1462
1463 PrintStreamData(data);
1464 buffer->Push(pesPacket.GetPayload(), pesPacket.GetPayloadSize(), pesPacket.GetPts());
1465
1466 stream->Open(buffer->GetCodec());
1467 } else {
1468 int payloadOffset = 0;
1469 if (pesPacket.HasPts() && !buffer->IsEmpty()) {
1470 // received the first fragment of a new frame, finish the current reassembly buffer into an AVPacket
1471 stream->PushAvPacket(buffer->PopAvPacket());
1472
1473 // populate the cleared buffer with the next frame
1474 if (buffer->HasLeadingZero(pesPacket.GetPayload(), pesPacket.GetPayloadSize()))
1475 payloadOffset = 1; // H.264/HEVC streams may have a leading zero byte before the start code
1476 }
1477
1478 buffer->Push(pesPacket.GetPayload() + payloadOffset, pesPacket.GetPayloadSize() - payloadOffset, pesPacket.GetPts());
1479 }
1480
1481 return size;
1482}
1483
1494
1502void cSoftHdDevice::HandleStillPicture(const uchar *data, int size)
1503{
1506
1507 // skip BufferUnderrunEvent{VIDEO} in renderer
1509
1510 const uchar *currentPacketStart = data;
1511 while (currentPacketStart < data + size) {
1513
1514 if (pesPacket.IsValid())
1516 else {
1517 LOGWARNING("device: %s: invalid PES packet", __FUNCTION__);
1518 break;
1519 }
1520
1521 currentPacketStart += pesPacket.GetPacketLength();
1522 }
1523
1525 m_pVideoStream->ResetInputPts(); // stillpicture shouldn't trigger having video data
1527}
1528
1535{
1536 LOGDEBUG("Set display mode: %dx%d@%.2f%s",
1537 mode.width,
1538 mode.height,
1539 mode.refreshRateHz,
1540 mode.interlaced ? "i" : "");
1541
1544}
1545
1567
1580
1588
1589/*********************************************************************
1590 * cSoftHdDevice state transitioning functions
1591 ********************************************************************/
1592
1600{
1601 m_pStateMachine->OnEventReceived(event);
1602}
1603
1613{
1614 switch (state) {
1615 case PLAY:
1618 m_pAudio->SetPaused(true);
1620 break;
1621 case BUFFERING:
1624 break;
1625 case TRICK_SPEED:
1626 // The filter thread needs to be restarted for interlaced streams to be rendered with deinterlacer again. It is started lazily.
1628 m_pRender->SetTrickSpeed(0, false, false);
1635 break;
1636 case STOP:
1637 m_receivedAudio = false;
1638 m_receivedVideo = false;
1639 m_receivedValidAudio = false;
1640 m_receivedValidVideo = false;
1641 break;
1642 case DETACHED:
1643 m_pAudio = new cSoftHdAudio(this);
1644 m_pRender = new cVideoRender(this);
1648 int err = m_pRender->Init(); // starts display thread
1649 if (err < 0) { // drm init failed -> force detached mode
1650 delete m_pAudioDecoder;
1651 delete m_pVideoStream;
1652 delete m_pGrab;
1653 delete m_pRender;
1654 delete m_pAudio;
1655 LOGERROR("device: display init failed -> start in detached mode");
1656 m_forceDetached = true;
1657 break;
1658 }
1659 m_pVideoStream->StartDecoder(); // starts decoding thread
1661 m_pPipStream->StartDecoder(); // starts decoding thread
1662 m_pPipHandler = new cPipHandler(this);
1663 // Audio is init lazily (includes starting thread)
1664
1665 break;
1666 }
1667}
1668
1678{
1679 switch (state) {
1680 case BUFFERING:
1685 }
1686 break;
1687 case PLAY:
1689 m_pAudio->SetPaused(false);
1690
1691 if (m_playbackMode != AUDIO_ONLY) {
1693 m_pRender->SetStillpicture(false);
1695 }
1696 break;
1697 case TRICK_SPEED:
1698 // The filter thread needs to be restarted for interlaced streams
1699 // to be rendered without deinterlacer in trick speed mode.
1700 // It is started lazily.
1705 break;
1706 case STOP:
1707 if (m_forceDetached) {
1708 m_pStateMachine->SetState(DETACHED);
1709 break;
1710 }
1711
1712 FlushAudio();
1713
1716 m_pRender->Reset();
1718
1727
1728 break;
1729 case DETACHED:
1730 delete m_pPipHandler;
1731 m_pPipHandler = nullptr;
1732
1733 // resume the previously stopped threads
1735 m_pRender->Resume();
1736
1737 // now do the detach
1738 m_pPipStream->Exit();
1739 delete m_pPipStream;
1740
1741#ifdef USE_GLES
1742 // The opengl thread was probably locked before cmdCopyBufferToOutputFb().
1743 // 1) set running to false
1744 // 2) continue the thread (which will skip the waiting cmd->Execute())
1745 // 3) do the real thread cancel and cleanup
1746 // We need to keep this order to prevent a deadlock!
1750#endif
1751 m_pRender->Exit(); // render must be stopped before videostream!
1753 m_pAudio->Exit(); // audio must be stopped after renderer!
1754
1755 delete m_pAudioDecoder; // includes a Close()
1756 delete m_pVideoStream;
1757 delete m_pGrab;
1758 delete m_pRender;
1759 delete m_pAudio;
1760
1761 break;
1762 }
1763}
1764
1769{
1770 m_pRender->Halt();
1772}
1773
1782
1783#ifdef USE_GLES
1791
1800#endif
1801
1806{
1807 return m_forceDetached;
1808}
1809
1819{
1820 if (m_pAudio->LazyInit())
1821 return -1;
1822
1823 if (setVolume)
1824 m_pAudio->SetVolume((m_volume * 1000) / 255);
1825
1826 return 0;
1827}
1828
1837
1845void cSoftHdDevice::SetTrickSpeed(double speed, bool active, bool forward)
1846{
1847 m_pRender->SetTrickSpeed(speed, active, forward);
1848}
1849
1860{
1863
1866 // store the first PTSes beforehand, because dropping samples/frames will change the output of GetFirst*PtsMsToPlay()
1869
1870 // don't drop old audio, if we want to wait for it in fast channel switch mode including audio playback
1873
1875 } else if (receivedAudio) {
1876 LOGDEBUG("device: audio only detected");
1879 } else if (receivedVideo) {
1880 LOGDEBUG("device: video only detected");
1883 } else {
1884 // Sometimes a DeviceClear() can jump in between signalling the ThresholdReachedEvent
1885 // and progressing it, e.g. the video thread signals the ThresholdReached, VDR sends a DeviceClear()
1886 // and OnEventReceived wants to process the ThresholdReachedEvent with empty buffers.
1887 LOGDEBUG("device: buffering threshold reached and no a/v available, keep BUFFERING state");
1888 return false;
1889 }
1890
1891 return true;
1892}
1893
1903
1910{
1911 // resume from pause
1913
1914 switch (m_playbackMode) {
1915 case AUDIO_ONLY:
1917 m_pAudio->SetPaused(false);
1918 break;
1919 case AUDIO_AND_VIDEO:
1922 if (audioBehindVideoByMs > 0) {
1924 m_pAudio->SetPaused(false);
1925 } else
1927
1928 // fallthrough
1929 case VIDEO_ONLY:
1930 m_pRender->SetStillpicture(false);
1932 break;
1933 case NONE:
1934 LOGFATAL("STATE MACHINE: play event in PLAY state with NONE playback mode. This is a bug.");
1935 break;
1936 }
1937}
1938
1955
1960{
1962}
Audio Interface Header File.
Audio Decoder.
Definition codec_audio.h:59
void FlushBuffers(void)
Flush the audio decoder buffers.
void Decode(const AVPacket *)
Forward an audio packet either to the decoder or passthrough.
AVCodecID GetCodecId() const
Definition codec_audio.h:68
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.
Event handler thread.
void AddEvent(Event)
Add an event to the queue.
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:79
Video PES Packet Parser.
Definition pes.h:64
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 Disable(void)
Stop picture-in-picture.
void ChannelSwap(bool)
Swap the pip channel with main live channel.
bool IsEnabled(void)
Definition pipreceiver.h:68
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:486
Video Stream Reassembly Buffer.
Definition pes.h:145
AVPacket * PopAvPacket(void) override
Definition pes.h:148
bool HasLeadingZero(const uint8_t *, int)
Check if video data has a leading zero byte before the start code.
Definition pes.cpp:469
bool ParseCodecHeader(const uint8_t *, int)
Parse video codec header to detect codec type.
Definition pes.cpp:432
AVCodecID GetCodec(void)
Definition pes.h:128
void Reset(void)
Reset the reassembly buffer.
Definition pes.cpp:659
virtual void Push(const uint8_t *data, int size, int64_t pts)
Definition pes.h:123
bool IsEmpty(void)
Definition pes.h:125
Audio Interface.
Definition audio.h:51
void ResetHwDelayBaseline(void)
Reset the hw delay baseline.
Definition audio.cpp:1175
int64_t GetInputPtsMs(void)
Definition audio.h:72
void SetHwDelayBaseline(void)
Set the hw delay baseline.
Definition audio.cpp:1157
int64_t GetHardwareOutputPtsTimebaseUnits(void)
Get the hardware output PTS in timebase units.
Definition audio.cpp:848
void SetVolume(int)
Set mixer volume (0-1000)
Definition audio.cpp:862
void DropSamplesOlderThanPtsMs(int64_t)
Drop samples older than the given PTS.
Definition audio.cpp:420
int64_t GetOutputPtsMs(void)
Get the output PTS of the ringbuffer.
Definition audio.cpp:775
void ClockDriftCompensation(void)
Calculate clock drift compensation.
Definition audio.cpp:1205
void Exit(void)
Cleanup audio output module (alsa)
Definition audio.cpp:974
void SetPaused(bool)
Set audio playback pause state.
Definition audio.cpp:884
bool IsPaused(void)
Definition audio.h:59
bool IsBufferEmpty(void)
Definition audio.h:63
void SetPassthroughMask(int mask)
Definition audio.h:84
int LazyInit(void)
Initialize audio output module (alsa)
Definition audio.cpp:952
bool HasInputPts(void)
Definition audio.h:71
bool IsBufferFull(void)
Definition audio.h:62
void FlushBuffers(void)
Flush audio buffers.
Definition audio.cpp:723
Plugin Configuration.
Definition config.h:65
bool ConfigParseH264Dimensions
parse h264 stream for width and height for decoder init
Definition config.h:119
sDrmMode RequestedDrmMode
is set to the requested mode which should be changed to
Definition config.h:154
int ConfigVideoAudioDelayMs
config audio delay
Definition config.h:85
std::atomic< int > StatMaxLongTermAudioJitterMs
logged max overall audio jitter since stream start
Definition config.h:146
int ConfigVideoChannelSwitchMode
channel switch mode (enum ChannelSwitchMode)
Definition config.h:77
int ConfigMaxSizeGPUImageCache
config max gpu image cache size
Definition config.h:123
std::atomic< int > StatMaxShortTermAudioJitterMs
logged max audio jitter of the last 1000 packets
Definition config.h:145
int ConfigDecoderFallbackToSwNumPkts
maximum number of packets sent before fallback to sw decoder
Definition config.h:117
std::vector< sDrmMode > CollectedDrmModes
collected available drm modes on the current connector
Definition config.h:149
bool ConfigDisableDeint
disable deinterlacer
Definition config.h:115
int ConfigDisableOglOsd
config disable ogl osd
Definition config.h:137
int ConfigAdditionalBufferLengthMs
config size ms of a/v buffer
Definition config.h:114
bool CompareCurrentMode(sDrmMode *)
Return true, if the given mode is equal to the current display mode.
Definition config.cpp:166
std::atomic< int > StatMaxShortTermVideoJitterMs
logged max video jitter of the last 1000 packets
Definition config.h:147
bool ConfigDecoderNeedsIFrame
start h264 decoder only when an I-Frame arrives
Definition config.h:118
sDrmMode AutoDetectedDrmMode
auto detected mode on the first startup (maybe equal to UserSetMode)
Definition config.h:150
int ConfigPipUseAlt
Definition config.h:103
std::atomic< int > StatMaxLongTermVideoJitterMs
logged max overall video jitter since stream start
Definition config.h:148
sDrmMode CurrentVideoDrmMode
currently used video drm mode
Definition config.h:153
void OsdDrawARGB(int, int, int, int, int, const uint8_t *, int, int)
Draw an OSD pixmap.
cReassemblyBufferVideo m_videoReassemblyBuffer
video pes reassembly buffer
void ResumeFromPause(void)
Resume playback from pause state.
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
bool IsAudioBufferingThresholdReached(void)
Returns true, if audio buffer is filled enough to start audio playback.
int m_volume
track the volume in the device (for attach)
void SetScreenSize(int, int)
Set the screen size.
virtual void StillPicture(const uchar *, int)
Display the given I-frame as a still picture.
void PipSetSize(void)
bool HaltOpenGlThread(void)
Pause the OpenGL worker thread.
void HandleDisplayModeChange(const sDrmMode &)
Set the display mode.
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)
cDvbSpuDecoder * m_pSpuDecoder
pointer to spu decoder
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.
bool IsDetachForced(void)
Returns true, the a detached plugin start was forced.
int PlayAudioPkts(AVPacket *)
Play an audio packet.
virtual void GetOsdSize(int &, int &, double &)
Returns the width, height and aspect ratio the OSD should have.
bool m_initialized
true, if the plugin had a successful Initialize()
void SetEnableHdr(bool)
Enable HDR display mode.
void SetRenderPipActive(bool)
void GetStats(int *, int *, int *)
Get statistics from the renderer.
void SetTrickSpeed(double, bool, bool)
Set the trickspeed in the renderer.
void HaltVideoThreads(void)
Pause the rendering and decoder thread.
void ResetChannelId(void)
Reset the channel ID (restarts audio)
void ResumeVideoThreads(void)
Resume the rendering and decoder thread.
cHardwareDevice * m_pHardwareDevice
pointer to hardware device description
virtual bool CanReplay(void) const
Return true if this device can currently start a replay session.
bool SchedulePlaybackStart(void)
Schedules the playback start.
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.
cEventHandler * m_pEventHandler
event handler thread
cPipHandler * m_pPipHandler
pointer to pip handler
void Detach(void)
Detach the device.
void ResumeOpenGlThread(void)
Resume the OpenGL worker thread.
virtual int PlayVideo(const uchar *, int)
Play a video packet of the main videostream.
void ResetPipStream(void)
Resets pip stream and render pipeline.
int GetVideoAudioDelayMs(void)
std::chrono::steady_clock::time_point m_dataReceivedTime
timestamp, when the first audio or video data after a channel switch arrives in Play*()
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)
void EnterState(State)
Actions to be performed when entering a state.
bool IsBufferingThresholdReached(void)
Check if the buffering threshold has been reached.
int InitAudio(bool)
Init the audio lazily.
cVideoRender * m_pRender
pointer to cVideoRender object
std::unique_ptr< cStateMachine > m_pStateMachine
void SetOsdSize(int, int)
Set the OSD size.
cSoftHdGrab * m_pGrab
pointer to grabber object
void LeaveState(State)
Actions to be performed when leaving a state.
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
true, if device should be made a primary device after attach
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.
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)
Return true, if the output buffers are empty, false otherwise.
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 PlayVideoPkts(AVPacket *)
Play a video packet.
std::atomic< bool > m_receivedValidAudio
flag if valid audio packets have been received
cJitterTracker m_audioJitterTracker
audio jitter tracker
std::atomic< bool > m_receivedValidVideo
flag if valid video packets have been received
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.
std::atomic< bool > m_draining
true, if the device is in draining mode (waiting for empty buffers)
int PlayVideoInternal(cVideoStream *, cReassemblyBufferVideo *, const uchar *, int, bool, bool)
Play a video packet.
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
void TriggerEvent(const Event &)
With this wrapper function, the device can directly act as an event reveiver.
virtual ~cSoftHdDevice(void)
Destroy the device.
void ResetVideoFilter(void)
Reset the video deinterlace filter.
int m_audioChannelID
current audio channel ID
std::atomic< ChannelSwitchMode > m_channelSwitchMode
current channel switch mode
void PipDisable(void)
virtual void SetVideoFormat(bool)
Set the video format.
void PausePlayback(bool)
Pause the playback.
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.
void ResumePlayback(void)
Resume playback again.
virtual cSpuDecoder * GetSpuDecoder(void)
Get the device SPU decoder.
cJitterTracker m_videoJitterTracker
video jitter tracker
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()
void SetDisplayMode(int)
Trigger a display mode change event if the mode changed.
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.
void ScheduleResyncAtPtsMs(int64_t)
Schedule aa a/v resync in the render thread at the given pts.
bool m_externalPlayerActive
true, if we detached for an external player
Grabbing Processor.
Definition grab.h:79
bool IsActive(void)
Definition grab.h:83
bool Start(bool, int, int, int, int, int)
Start a grab in the video renderer.
Definition grab.cpp:661
uint8_t * Image(void)
Definition grab.h:85
bool ProcessGrab(void)
Start the conversion.
Definition grab.cpp:780
int Size(void)
Definition grab.h:86
void Finish(void)
Clean up.
Definition grab.cpp:695
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 ReInitDisplayMode(void)
Re-Initialize the drm device with current display mode settings.
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 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.
int Init(void)
Initialize the renderer.
bool CanHandleMode(sDrmMode *)
Wrapper to check, if drm can handle the display mode.
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.
bool BuffersEmpty(void)
Return true, if the input AVPacket, videofilter and drm output buffer queues are empty.
void SetDecoderFallbackToSwNumPkts(int numPackets)
Definition videostream.h:90
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 Drain(void)
Drains the video stream by finalizing any pending data.
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)
Definition videostream.h:76
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:74
bool HasInputPts(void)
Definition videostream.h:75
Audio Decoder Header File.
Plugin Configuration Header File.
__attribute__((weak)) union gbm_bo_handle gbm_bo_get_handle_for_plane(struct gbm_bo *bo
Grabbing Interface Header File.
std::variant< PlayEvent, PauseEvent, StopEvent, TrickSpeedEvent, StillPictureEvent, DetachEvent, AttachEvent, BufferUnderrunEvent, BufferingThresholdReachedEvent, ScheduleResyncAtPtsMsEvent, ResyncEvent, DisplayChangeEvent > Event
State
ChannelSwitchMode
Channel switch modes.
Definition config.h:54
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
@ CHANNEL_SWITCH_AVSYNC
Definition config.h:55
@ CHANNEL_SWITCH_FAST_AUDIO
Definition config.h:57
@ CONFIG_DISPLAY_MODE_DEFAULT
Definition config.h:43
@ CONFIG_DISPLAY_MODE_FOLLOW_VIDEO_INTERLACED
Definition config.h:45
@ CONFIG_DISPLAY_MODE_FOLLOW_VIDEO
Definition config.h:44
@ CONFIG_DISPLAY_MODE_MANUAL
Definition config.h:46
#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
#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
@ L_DRM
drm logs
Definition logger.h:60
@ 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.
Device State Machine and Event Handler Header File.
Holds possible display configurations.
Definition config.h:30
int width
display width
Definition config.h:31
bool interlaced
is this an interlaced mode?
Definition config.h:34
int height
display height
Definition config.h:32
double refreshRateHz
display refresh rate
Definition config.h:33
Video Renderer (Display) Header File.
Video Input Stream Header File.