diff --git a/priv_aamp.cpp b/priv_aamp.cpp index 031c73f39..e539c4fe9 100644 --- a/priv_aamp.cpp +++ b/priv_aamp.cpp @@ -2695,15 +2695,6 @@ void PrivateInstanceAAMP::MonitorProgress(bool sync, bool beginningOfStream) end -= offset; } - // If tsb is not available for linear send -1 for start and end - // so that xre detect this as tsbless playback - // Override above logic if mEnableSeekableRange is set, used by third-party apps - if (!ISCONFIGSET_PRIV(eAAMPConfig_EnableSeekRange) && (mContentType == ContentType_LINEAR && !mFogTSBEnabled && !IsLocalAAMPTsb())) - { - start = -1; - end = -1; - } - if(IsLiveStream()) { if(eMEDIAFORMAT_DASH == mMediaFormat) @@ -2737,6 +2728,15 @@ void PrivateInstanceAAMP::MonitorProgress(bool sync, bool beginningOfStream) } } + // If TSB is not available for linear playback, send -1 for start and end + // so that XRE detects this as TSB-less playback. + // Override the above logic when mEnableSeekableRange is set for third-party apps. + if (!ISCONFIGSET_PRIV(eAAMPConfig_EnableSeekRange) && (mContentType == ContentType_LINEAR && !mFogTSBEnabled && !IsLocalAAMPTsb())) + { + start = -1; + end = -1; + } + const BitsPerSecond availableBandwidth = mhAbrManager.GetCurrentlyAvailableBandwidth(); const BitsPerSecond networkBandwidth = mhAbrManager.GetNetworkBandwidth(); @@ -2803,24 +2803,28 @@ void PrivateInstanceAAMP::MonitorProgress(bool sync, bool beginningOfStream) SETCONFIGVALUE_PRIV(AAMP_STREAM_SETTING, eAAMPConfig_ProgressLogging, false); } } + if (ISCONFIGSET_PRIV(eAAMPConfig_ProgressLogging)) { static int tick; int divisor = GETCONFIGVALUE_PRIV(eAAMPConfig_ProgressLoggingDivisor); if( divisor==0 || (tick++ % divisor) == 0 ) { + auto formatPos = [](double valMs) -> long { + return (valMs == -1.0) ? -1 : (long)(valMs / 1000); + }; AAMPLOG_MIL("aamp pos: [%ld..%ld..%ld..%lld..%.2f..%.2f..%.2f..%s..%" BITSPERSECOND_FORMAT "..%" BITSPERSECOND_FORMAT "..%.2f]", - (long)(start / 1000), - (long)(reportFormattedCurrPos / 1000), - (long)(end / 1000), - (long long) videoPTS, - (double)(videoBufferedDuration / 1000.0), - (double)(audioBufferedDuration /1000.0), - (double)(latency / 1000.0), - seiTimecode.c_str(), - bps, - networkBandwidth, - currentRate); + formatPos(start), + (long)(reportFormattedCurrPos / 1000), + formatPos(end), + (long long) videoPTS, + (double)(videoBufferedDuration / 1000.0), + (double)(audioBufferedDuration /1000.0), + (double)(latency / 1000.0), + seiTimecode.c_str(), + bps, + networkBandwidth, + currentRate); } } diff --git a/test/utests/tests/PrivAampTests/PrivAampTests.cpp b/test/utests/tests/PrivAampTests/PrivAampTests.cpp index c0b03af46..c59fe5e65 100644 --- a/test/utests/tests/PrivAampTests/PrivAampTests.cpp +++ b/test/utests/tests/PrivAampTests/PrivAampTests.cpp @@ -1629,6 +1629,45 @@ TEST_F(PrivAampTests, MonitorProgressRewindToBoS_ProgressBeforeSpeedChange) p_aamp->MonitorProgress(true, false); } +/** + * @brief Regression test for Positive Live latency value. + * + * Verifies that live latency is never negative during TSB-less linear HLS + * playback. Before the fix, start/end were overwritten to -1 (XRE sentinel) + * before HLS latency was calculated (latency = end - position), producing a + * large negative latency value. The fix moves the sentinel assignment to after + * the latency calculation. + */ +TEST_F(PrivAampTests, MonitorProgress_TsbLessLinearHLS_LatencyNonNegative) +{ + constexpr double CULLED_SECONDS = 0.0; + constexpr double DURATION_SECONDS = 1000.0; + constexpr double SEEK_POS_SECONDS = 100.0; + + // Setup: TSB-less linear HLS live playback + p_aamp->SetState(eSTATE_PLAYING, true); + p_aamp->mDownloadsEnabled = true; + p_aamp->rate = AAMP_NORMAL_PLAY_RATE; + p_aamp->mSinkPaused = false; + p_aamp->mMediaFormat = eMEDIAFORMAT_HLS; + p_aamp->SetIsLiveStream(true); + p_aamp->SetContentType("LINEAR_TV"); + p_aamp->mFogTSBEnabled = false; + p_aamp->SetLocalAAMPTsb(false); + p_aamp->durationSeconds = DURATION_SECONDS; + p_aamp->culledSeconds = CULLED_SECONDS; + p_aamp->seek_pos_seconds = SEEK_POS_SECONDS; + p_aamp->trickStartUTCMS = -1; + + EXPECT_CALL(*g_mockAampConfig, IsConfigSet(_)).WillRepeatedly(Return(false)); + EXPECT_CALL(*g_mockAampStreamSinkManager, GetStreamSink(_)).WillRepeatedly(Return(g_mockAampGstPlayer)); + + p_aamp->MonitorProgress(true, false); + + // Live latency must be non-negative after the fix. + EXPECT_GE(p_aamp->GetCurrentLatencyMs(), 0L); +} + TEST_F(PrivAampTests,UpdateDurationTest) { p_aamp->UpdateDuration(232.436);