@@ -419,6 +419,11 @@ int cSoftHdDevice::PlayAudio(const uchar *data, int size, uchar id)
419419 if (IsBufferingThresholdReached ())
420420 TriggerEvent (BufferingThresholdReachedEvent{});
421421
422+ // unpause audio, if the fast channel switch modes wants it to be started
423+ // the audio buffer reached the threshold and we are in live tv mode
424+ if (m_fastChannelSwitch == 2 && Transferring () && m_pAudio->IsPaused () && IsAudioBufferingThresholdReached ())
425+ m_pAudio->SetPaused (false );
426+
422427 AVPacket *avpkt;
423428 do {
424429 if (!(avpkt = m_audioReassemblyBuffer.PopAvPacket ()))
@@ -952,12 +957,16 @@ bool cSoftHdDevice::IsBufferingThresholdReached()
952957 int64_t syncedAudioBufferFillLevelMs = m_pAudio->GetInputPtsMs () - GetFirstAudioPtsMsToPlay ();
953958 int64_t syncedVideoBufferFillLevelMs = m_pVideoStream->GetInputPtsMs () - GetFirstVideoPtsMsToPlay ();
954959
960+ int audioBehindVideo = m_pRender->GetOutputPtsMs () - m_pAudio->GetOutputPtsMs () - GetVideoAudioDelayMs ();
961+ bool audioReachedVideo = audioBehindVideo <= 0 ;
962+
955963 bool reached = m_pRender->IsOutputBufferFull () && // video decoder output buffer (audio hardware output buffer is negligible)
956964 syncedVideoBufferFillLevelMs > GetBufferFillLevelThresholdMs () && // video decoder input buffer
957- syncedAudioBufferFillLevelMs > GetBufferFillLevelThresholdMs (); // audio decoder output buffer
965+ syncedAudioBufferFillLevelMs > GetBufferFillLevelThresholdMs () && // audio decoder output buffer
966+ (m_fastChannelSwitch == 2 ? audioReachedVideo : true ); // if fast channel switch played audio already, wait for audio to come up
958967
959968 if (reached) {
960- LOGDEBUG2 (L_AV_SYNC , " First received PTS: %s (audio), %s (video) buffer fill levels: %ldms (audio) %ldms (video)" ,
969+ LOGDEBUG2 (L_AV_SYNC , " buffering threshold reached - PTS: %s (audio), %s (video) - buffer fill levels: %ldms (audio) %ldms (video)" ,
961970 Timestamp2String (m_pAudio->GetOutputPtsMs (), 1 ),
962971 Timestamp2String (m_pRender->GetOutputPtsMs (), 1 ),
963972 syncedAudioBufferFillLevelMs,
@@ -967,6 +976,40 @@ bool cSoftHdDevice::IsBufferingThresholdReached()
967976 return reached;
968977}
969978
979+ /* *
980+ * Returns true, if audio buffer is filled enough to start audio playback
981+ *
982+ * @retval true if audio playback should start
983+ * @retval false if audio playback should not start
984+ *
985+ * @note Used for fast channel switch
986+ */
987+ bool cSoftHdDevice::IsAudioBufferingThresholdReached ()
988+ {
989+ if (m_pStateMachine->GetState () != BUFFERING )
990+ return false ;
991+
992+ bool audioHasInputPts = m_pAudio->HasInputPts ();
993+ bool videoHasInputPts = m_pVideoStream->HasInputPts ();
994+ bool videoHasOutputPts = m_pRender->GetOutputPtsMs () != AV_NOPTS_VALUE ;
995+
996+ // only start audio playback, if video is already there
997+ if (!audioHasInputPts || !videoHasInputPts || !videoHasOutputPts)
998+ return false ;
999+
1000+ int64_t audioBufferFillLevelMs = m_pAudio->GetInputPtsMs () - m_pAudio->GetOutputPtsMs ();
1001+ if (audioBufferFillLevelMs > GetBufferFillLevelThresholdMs ()) {
1002+ LOGDEBUG2 (L_AV_SYNC , " audio buffer reached threshold %dms - PTS: %s (audio), %s (video) - buffer fill levels: %ldms (audio)" ,
1003+ GetBufferFillLevelThresholdMs (),
1004+ Timestamp2String (m_pAudio->GetOutputPtsMs (), 1 ),
1005+ Timestamp2String (m_pRender->GetOutputPtsMs (), 1 ),
1006+ audioBufferFillLevelMs);
1007+ return true ;
1008+ }
1009+
1010+ return false ;
1011+ }
1012+
9701013/* ********************************************************************
9711014 * cSoftHdDevice public API - osd control
9721015 ********************************************************************/
@@ -1819,11 +1862,14 @@ bool cSoftHdDevice::SchedulePlaybackStart(void)
18191862
18201863 if (receivedAudio && receivedVideo) {
18211864 m_playbackMode = AUDIO_AND_VIDEO ;
1865+ // store the first PTSes beforehand, because dropping samples/frames will change the output of GetFirst*PtsMsToPlay()
18221866 int64_t firstAudioPtsMs = GetFirstAudioPtsMsToPlay ();
18231867 int64_t firstVideoPtsMs = GetFirstVideoPtsMsToPlay ();
18241868
1825- // store the first PTSes beforehand, because dropping samples/frames will change the output of GetFirst*PtsMsToPlay()
1826- m_pAudio->DropSamplesOlderThanPtsMs (firstAudioPtsMs);
1869+ // don't drop old audio, if we want to wait for it in fast channel switch mode including audio playback
1870+ if (m_fastChannelSwitch < 2 || !Transferring ())
1871+ m_pAudio->DropSamplesOlderThanPtsMs (firstAudioPtsMs);
1872+
18271873 m_pRender->SchedulePlaybackStartAtPtsMs (firstVideoPtsMs);
18281874 } else if (receivedAudio) {
18291875 LOGDEBUG (" device: audio only detected" );
0 commit comments