Skip to content

Commit 0e63274

Browse files
committed
device: enable fast channel switch
1 parent d533b8e commit 0e63274

8 files changed

Lines changed: 36 additions & 10 deletions

File tree

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,10 @@ Setup: /etc/vdr/setup.conf
203203
2 = display mode follows video resolution respecting interlaced modes (width, height, refresh rate, interlaced flag)
204204
Same as above, but now the display also chooses an interlaced mode for interlaced input (except for 576i) if available
205205

206+
softhddevice-drm-gles.VideoFastChannelSwitch = 0
207+
0 = enable fast channel switch: the first available frame is displayed as a still-picture as soon as possible until a/v is in sync
208+
1 = fast channel switch is disabled
209+
206210
softhddevice-drm-gles.MaxSizeGPUImageCache = 128
207211
how many GPU memory should be used for image caching
208212

config.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ bool cSoftHdConfig::SetupParse(const char *name, const char *value)
4040
// Video
4141
} else if (!strcasecmp(name, "VideoEnableHDR")) { ConfigVideoEnableHDR = atoi(value);
4242
} else if (!strcasecmp(name, "VideoDisplayMode")) { ConfigVideoDisplayMode = std::min(atoi(value), static_cast<int>(CONFIG_DISPLAY_MODE_FOLLOW_VIDEO_INTERLACED));
43+
} else if (!strcasecmp(name, "VideoFastChannelSwitch")){ ConfigVideoFastChannelSwitch = atoi(value);
4344

4445
// Audio
4546
} else if (!strcasecmp(name, "AudioSoftvol")) { ConfigAudioSoftvol = atoi(value);

config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class cSoftHdConfig {
5858
// Video
5959
int ConfigVideoEnableHDR = 0; ///< enable HDR
6060
int ConfigVideoDisplayMode = CONFIG_DISPLAY_MODE_DEFAULT; ///< display mode (enum ConfigDisplayMode)
61+
bool ConfigVideoFastChannelSwitch = false; ///< first video frame is presented as still-picture as soon as possible
6162

6263
// Audio
6364
bool ConfigAudioSoftvol = false; ///< config use software volume

softhddevice.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ bool cSoftHdDevice::Initialize(void)
9494
m_dataReceivedTime = m_channelSwitchStartTime;
9595

9696
m_pipUseAlt = m_pConfig->ConfigPipUseAlt;
97+
m_fastChannelSwitch = m_pConfig->ConfigVideoFastChannelSwitch;
9798

9899
m_initialized = true;
99100

@@ -1633,7 +1634,11 @@ void cSoftHdDevice::EnterState(State state)
16331634
switch (state) {
16341635
case BUFFERING:
16351636
m_pAudio->ResetHwDelayBaseline();
1636-
// nothing
1637+
if (m_fastChannelSwitch) {
1638+
LOGDEBUG2(L_AV_SYNC, "%s: fast channel switch: display one frame and then pause", __FUNCTION__);
1639+
m_pRender->SetPlaybackPaused(false);
1640+
m_pRender->SetDisplayOneFrameThenPause(true);
1641+
}
16371642
break;
16381643
case PLAY:
16391644
if (m_playbackMode != VIDEO_ONLY)

softhddevice.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ class cSoftHdDevice : public cDevice, public cStatus {
147147
void SetParseH264Dimensions(void);
148148
void SetDecoderFallbackToSw(bool);
149149
void SetEnableHdr(bool);
150+
void SetEnableFastChannelSwitch(bool enable) { m_fastChannelSwitch = enable; };
150151
void SetDisplayMode(int);
151152
bool IsBufferingThresholdReached(void);
152153
bool IsVideoOnlyPlayback(void) { return m_playbackMode == VIDEO_ONLY; };
@@ -256,6 +257,7 @@ class cSoftHdDevice : public cDevice, public cStatus {
256257
cJitterTracker m_videoJitterTracker{"video"}; ///< video jitter tracker
257258
std::chrono::steady_clock::time_point m_channelSwitchStartTime; ///< timestamp, when VDR triggered a channel switch
258259
std::chrono::steady_clock::time_point m_dataReceivedTime; ///< timestamp, when the first audio or video data after a channel switch arrives in Play*()
260+
bool m_fastChannelSwitch = false; ///< enable fast channel switch: display a video frame as still frame asap after stream start
259261

260262
std::atomic<PlaybackMode> m_playbackMode = NONE; ///< current playback mode
261263
int m_audioChannelID = -1; ///< current audio channel ID

softhdsetupmenu.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ void cMenuSetupSoft::Create(void)
7777
if (m_cVideoMenu) {
7878
Add(new cMenuEditBoolItem(tr(" Enable HDR"), &m_cVideoEnableHDR, trVDR("no"), trVDR("yes")));
7979
Add(new cMenuEditStraItem(tr(" Display mode"), &m_cVideoDisplayMode, m_displayModePtrs.size(), m_displayModePtrs.data()));
80+
Add(new cMenuEditBoolItem(tr(" Enable fast channel switch"), &m_cVideoFastChannelSwitch, trVDR("no"), trVDR("yes")));
8081
}
8182

8283
//
@@ -304,6 +305,7 @@ cMenuSetupSoft::cMenuSetupSoft(cSoftHdDevice *device)
304305
m_cVideoMenu = 0;
305306
m_cVideoEnableHDR = m_pConfig->ConfigVideoEnableHDR;
306307
m_cVideoDisplayMode = m_pConfig->ConfigVideoDisplayMode;
308+
m_cVideoFastChannelSwitch = m_pConfig->ConfigVideoFastChannelSwitch;
307309

308310
//
309311
// Audio
@@ -455,6 +457,8 @@ void cMenuSetupSoft::Store(void)
455457
// only save default and auto adjusted modes
456458
if (m_pConfig->ConfigVideoDisplayMode < CONFIG_DISPLAY_MODE_MANUAL)
457459
SetupStore("VideoDisplayMode", m_cVideoDisplayMode);
460+
SetupStore("VideoFastChannelSwitch", m_pConfig->ConfigVideoFastChannelSwitch = m_cVideoFastChannelSwitch);
461+
m_pDevice->SetEnableFastChannelSwitch(m_pConfig->ConfigVideoFastChannelSwitch);
458462

459463
//
460464
// Audio

softhdsetupmenu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class cMenuSetupSoft : public cMenuSetupPage {
4141
int m_cVideoMenu;
4242
int m_cVideoEnableHDR;
4343
int m_cVideoDisplayMode;
44+
int m_cVideoFastChannelSwitch;
4445

4546
// Audio
4647
int m_cAudioMenu;

videorender.cpp

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,7 @@ bool cVideoRender::DisplayFrame(void)
720720
m_eventQueue.push_back(BufferingThresholdReachedEvent{});
721721

722722
bool skipBufferUnderrunCheck = m_videoPlaybackPaused ||
723+
m_displayOneFrameThenPause ||
723724
m_videoPlaybackPauseScheduledAt != AV_NOPTS_VALUE ||
724725
m_pDevice->IsVideoOnlyPlayback() ||
725726
IsTrickSpeed() ||
@@ -772,19 +773,26 @@ bool cVideoRender::DisplayFrame(void)
772773
m_pAudio->DropSamplesOlderThanPtsMs(drmBuffer->frame->pts * 1000 * av_q2d(m_timebase));
773774
}
774775

775-
if (m_displayOneFrameThenPause) {
776-
m_videoPlaybackPaused = true;
777-
m_displayOneFrameThenPause = false;
778-
}
779-
780776
pageFlipDone = PageFlip(drmBuffer, pipBuffer);
781-
if (m_startCounter == 1 && m_pDevice->Transferring()) {
777+
778+
// log channel switch duration
779+
if (m_pDevice->Transferring() && ((m_startCounter == 0 && m_displayOneFrameThenPause) || m_startCounter == 1)) {
782780
auto now = std::chrono::steady_clock::now();
783781
auto channelSwitchDurationMs = std::chrono::duration_cast<std::chrono::milliseconds>(now - m_pDevice->GetChannelSwitchStartTime()).count();
784782
auto durationSinceFirstPacketMs = std::chrono::duration_cast<std::chrono::milliseconds>(now - m_pDevice->GetChannelSwitchFirstPacketTime()).count();
785-
if (m_pConfig->ConfigShowChannelSwitchDurationMessage)
786-
Skins.Message(mtInfo, cString::sprintf(tr("channel switch done in %ldms (%ldms)"), channelSwitchDurationMs, durationSinceFirstPacketMs));
787-
LOGDEBUG("channel switch done in %dms, %dms after first packet was received", channelSwitchDurationMs, durationSinceFirstPacketMs);
783+
784+
if (m_startCounter == 0) {
785+
LOGDEBUG("first frame displayed %dms after channel switch, %dms after first packet was received", channelSwitchDurationMs, durationSinceFirstPacketMs);
786+
} else {
787+
if (m_pConfig->ConfigShowChannelSwitchDurationMessage)
788+
Skins.Message(mtInfo, cString::sprintf(tr("channel switch done in %ldms (%ldms)"), channelSwitchDurationMs, durationSinceFirstPacketMs));
789+
LOGDEBUG("in sync after channel switch in %dms, %dms after first packet was received", channelSwitchDurationMs, durationSinceFirstPacketMs);
790+
}
791+
}
792+
793+
if (m_displayOneFrameThenPause) {
794+
m_videoPlaybackPaused = true;
795+
m_displayOneFrameThenPause = false;
788796
}
789797

790798
if (m_pCurrentlyDisplayed)

0 commit comments

Comments
 (0)