@@ -911,10 +911,8 @@ bool SESSION::CSession::GetNextSample(ISampleReader*& sampleReader)
911911 return false ;
912912}
913913
914- bool SESSION::CSession::SeekTime (double seekTime)
914+ bool SESSION::CSession::SeekTime (double seekTime, bool & isError )
915915{
916- bool ret{false };
917-
918916 if (m_streams.empty ())
919917 return false ;
920918
@@ -949,26 +947,14 @@ bool SESSION::CSession::SeekTime(double seekTime)
949947
950948 seekTime -= chapterTime;
951949
952- // don't try to seek past the end of the stream, leave a sensible amount so we can buffer properly
953950 if (m_adaptiveTree->IsLive ())
954951 {
955- double maxSeek{0 };
956- uint64_t curTime;
957- uint64_t maxTime{0 };
958- for (auto & stream : m_streams)
959- {
960- if (stream->IsEnabled () && (curTime = stream->m_adStream .getMaxTimeMs ()) && curTime > maxTime)
961- {
962- maxTime = curTime;
963- }
964- }
965-
966- maxSeek = (static_cast <double >(maxTime) / 1000 ) - m_adaptiveTree->m_liveDelay ;
967- if (maxSeek < 0 )
968- maxSeek = 0 ;
952+ double delayPtsSecs =
953+ (static_cast <double >(GetMediaDurationMs ()) / 1000 ) - m_adaptiveTree->m_liveDelay ;
969954
970- if (seekTime > maxSeek)
971- seekTime = maxSeek;
955+ // Check to avoid seek into live delay duration portion, to allow an appropriate live buffering
956+ if (seekTime > delayPtsSecs)
957+ seekTime = delayPtsSecs;
972958 }
973959
974960 // Helper lambda to check if reader is started,
@@ -1023,12 +1009,18 @@ bool SESSION::CSession::SeekTime(double seekTime)
10231009 const double seekSecs = static_cast <double >(seekTimeCorrected) / STREAM_TIME_BASE;
10241010
10251011 if (!SeekAdStream (*m_timingStream, seekSecs))
1012+ {
1013+ isError = true ;
10261014 return false ;
1015+ }
10271016
1017+ // Note: The following "running" check will download/read the package right now
1018+ // allowing you to read the PTS diff from stream reader
10281019 if (!CheckReaderRunning (*m_timingStream))
10291020 return false ;
10301021
10311022 ptsDiff = timingReader->GetPTSDiff ();
1023+
10321024 if (ptsDiff < 0 && seekTimeCorrected + ptsDiff > seekTimeCorrected)
10331025 seekTimeCorrected = 0 ;
10341026 else
@@ -1063,17 +1055,29 @@ bool SESSION::CSession::SeekTime(double seekTime)
10631055 const double seekSecs{static_cast <double >(seekTimeCorrected - ptsDiff) / STREAM_TIME_BASE};
10641056
10651057 if (!SeekAdStream (*stream, seekSecs))
1066- continue ;
1058+ {
1059+ if (stream->m_info .GetStreamType () == INPUTSTREAM_TYPE_SUBTITLE)
1060+ continue ; // Subtitles failure should not block the seek operations
1061+
1062+ isError = true ;
1063+ return false ;
1064+ }
10671065 }
10681066
10691067 if (!CheckReaderRunning (*stream))
1070- continue ;
1068+ return false ;
10711069
10721070 streamReader->SetPTSDiff (ptsDiff);
10731071
10741072 if (!streamReader->TimeSeek (seekTimeCorrected))
10751073 {
10761074 streamReader->Reset (true );
1075+
1076+ if (stream->m_info .GetStreamType () == INPUTSTREAM_TYPE_SUBTITLE)
1077+ continue ; // Subtitles failure should not block the seek operations
1078+
1079+ isError = true ;
1080+ return false ;
10771081 }
10781082 else
10791083 {
@@ -1085,16 +1089,20 @@ bool SESSION::CSession::SeekTime(double seekTime)
10851089 LOG::Log (LOGINFO, " Seek time %0.1lf for stream: %i continues at %0.1lf (PTS: %llu)" , seekTime,
10861090 streamReader->GetStreamId (), destTime, streamReader->PTS ());
10871091
1092+ // We replace the seek time PTS initially requested with the PTS of the video sample found
1093+ // in order to search the audio/subtitle sample packet more accurately.
1094+ // f.e. in the case of MP4 the video packet has very few sample sync points
1095+ // while the audio stream usually has many sample sync points, this cause a misalignment
1096+ // because for the video you will never find an exact sample for the requested PTS.
1097+ // Then get the nearest PTS found for the video, then align the audio/subtitles with it.
10881098 if (stream->m_info .GetStreamType () == INPUTSTREAM_TYPE_VIDEO)
10891099 {
10901100 seekTime = destTime;
10911101 seekTimeCorrected = streamReader->PTS ();
10921102 }
1093- ret = true ;
10941103 }
10951104 }
1096-
1097- return ret;
1105+ return true ;
10981106}
10991107
11001108void SESSION::CSession::OnDemuxRead ()
@@ -1105,7 +1113,10 @@ void SESSION::CSession::OnDemuxRead()
11051113
11061114 if (GetChapterSeekTime () > 0 )
11071115 {
1108- SeekTime (GetChapterSeekTime ());
1116+ bool isError{false };
1117+ if (!SeekTime (GetChapterSeekTime (), isError))
1118+ DeleteStreams ();
1119+
11091120 ResetChapterSeekTime ();
11101121 }
11111122 }
@@ -1349,3 +1360,11 @@ PLAYLIST::CAdaptationSet* SESSION::CSession::DetermineDefaultAdpSet(PLAYLIST::CP
13491360
13501361 return defaultAdp;
13511362}
1363+
1364+ uint64_t SESSION::CSession::GetMediaDurationMs ()
1365+ {
1366+ if (!m_timingStream || !m_timingStream->IsEnabled ())
1367+ return 0 ;
1368+
1369+ return m_timingStream->m_adStream .getMaxTimeMs ();
1370+ }
0 commit comments