From 8367339ff3da874940488601ebd1bcf4a1e1cdeb Mon Sep 17 00:00:00 2001 From: rkandh015 Date: Thu, 9 Jul 2026 14:02:22 +0530 Subject: [PATCH 1/8] handling race conditions --- AampStreamSinkManager.cpp | 2 +- StreamSink.h | 7 ++++++- aampgstplayer.cpp | 6 +++--- aampgstplayer.h | 3 ++- middleware/InterfacePlayerRDK.cpp | 2 +- middleware/InterfacePlayerRDK.h | 2 +- priv_aamp.cpp | 2 +- 7 files changed, 15 insertions(+), 9 deletions(-) diff --git a/AampStreamSinkManager.cpp b/AampStreamSinkManager.cpp index ca9354bb54..0f5023f118 100644 --- a/AampStreamSinkManager.cpp +++ b/AampStreamSinkManager.cpp @@ -497,7 +497,7 @@ void AampStreamSinkManager::SetActive(PrivateInstanceAAMP *aamp, double position mGstPlayer->ChangeAamp(aamp, mInactiveGstPlayersMap[aamp]->GetID3MetadataHandler()); aamp->mIsFlushOperationInProgress = true; - mGstPlayer->Flush(position, aamp->rate, true); + mGstPlayer->Flush(position, aamp->rate, true,false); aamp->mIsFlushOperationInProgress = false; mGstPlayer->SetSubtitleMute(aamp->subtitles_muted); if(!aamp->IsTuneCompleted() && aamp->IsPlayEnabled() && (mPipelineMode == ePIPELINEMODE_SINGLE)) diff --git a/StreamSink.h b/StreamSink.h index 80ae915e42..2951699021 100644 --- a/StreamSink.h +++ b/StreamSink.h @@ -133,9 +133,14 @@ class StreamSink * @param[in] position - playback position * @param[in] rate - Speed * @param[in] shouldTearDown - if pipeline is not in a valid state, tear down pipeline + * @param[in] keepPausedSeek - true only when this Flush is part of an explicit seek-with-keepPaused + * request. Must NOT be inferred from the pipeline's incidental paused + * state (which can be true for unrelated reasons such as buffering or + * fragment caching), since that conflation can permanently block later + * PLAYING transitions when no explicit resume ever arrives. * @return void */ - virtual void Flush(double position = 0, int rate = AAMP_NORMAL_PLAY_RATE, bool shouldTearDown = true){} + virtual void Flush(double position = 0, int rate = AAMP_NORMAL_PLAY_RATE, bool shouldTearDown = true, bool keepPausedSeek = false){} /** * @brief Flush the audio playbin diff --git a/aampgstplayer.cpp b/aampgstplayer.cpp index 9957537a79..32a3f24a5e 100644 --- a/aampgstplayer.cpp +++ b/aampgstplayer.cpp @@ -1124,7 +1124,7 @@ void AAMPGstPlayer::SetAudioVolume(int volume) /** * @brief Flush cached GstBuffers and set seek position & rate */ -void AAMPGstPlayer::Flush(double position, int rate, bool shouldTearDown) +void AAMPGstPlayer::Flush(double position, int rate, bool shouldTearDown, bool keepPausedSeek) { if(ISCONFIGSET(eAAMPConfig_SuppressDecode)) { @@ -1136,7 +1136,7 @@ void AAMPGstPlayer::Flush(double position, int rate, bool shouldTearDown) { isAppSeek = true; } - bool ret = playerInstance->Flush(position, rate, shouldTearDown, isAppSeek); + bool ret = playerInstance->Flush(position, rate, shouldTearDown, isAppSeek, keepPausedSeek); if(ret) { for (int i = 0; i < AAMP_TRACK_COUNT; i++) @@ -1269,7 +1269,7 @@ void AAMPGstPlayer::SeekStreamSink(double position, double rate) // shouldTearDown is set to false, because in case of a new tune pipeline // might not be in a playing/paused state which causes Flush() to destroy // pipeline. This has to be avoided. - Flush(position, rate, false); + Flush(position, rate, false, false); } diff --git a/aampgstplayer.h b/aampgstplayer.h index 426297cc1f..86d390b59e 100644 --- a/aampgstplayer.h +++ b/aampgstplayer.h @@ -167,8 +167,9 @@ class AAMPGstPlayer : public StreamSink * @param[in] position playback seek position * @param[in] rate playback rate * @param[in] shouldTearDown flag indicates if pipeline should be destroyed if in invalid state + * @param[in] keepPausedSeek true only for an explicit seek-with-keepPaused request */ - void Flush(double position, int rate, bool shouldTearDown) override; + void Flush(double position, int rate, bool shouldTearDown, bool keepPausedSeek) override; /** * @fn Pause * @param[in] pause flag to pause/play the pipeline diff --git a/middleware/InterfacePlayerRDK.cpp b/middleware/InterfacePlayerRDK.cpp index fb29e69038..bd90c9eab1 100644 --- a/middleware/InterfacePlayerRDK.cpp +++ b/middleware/InterfacePlayerRDK.cpp @@ -1565,7 +1565,7 @@ bool InterfacePlayerRDK::IsUsingRialtoSink() /** * @brief Flush cached GstBuffers and set seek position & rate */ -bool InterfacePlayerRDK::Flush(double position, int rate, bool shouldTearDown, bool isAppSeek) +bool InterfacePlayerRDK::Flush(double position, int rate, bool shouldTearDown, bool isAppSeek, bool keepPausedSeek) { GstState aud_current; GstState aud_pending; diff --git a/middleware/InterfacePlayerRDK.h b/middleware/InterfacePlayerRDK.h index ba5a090828..515ccb7877 100644 --- a/middleware/InterfacePlayerRDK.h +++ b/middleware/InterfacePlayerRDK.h @@ -717,7 +717,7 @@ class InterfacePlayerRDK * @param[in] GstState The desired GStreamer pipeline state. * @param[in] gstMediaFormat The media format for the pipeline. */ - bool Flush(double position, int rate, bool shouldTearDown, bool isAppSeek); + bool Flush(double position, int rate, bool shouldTearDown, bool isAppSeek, bool keepPausedSeek); /** * @fn TimerAdd * @param[in] funcPtr function to execute on timer expiry diff --git a/priv_aamp.cpp b/priv_aamp.cpp index 057a52b5fb..4612a6eaa9 100644 --- a/priv_aamp.cpp +++ b/priv_aamp.cpp @@ -6503,7 +6503,7 @@ void PrivateInstanceAAMP::TuneHelper(TuneType tuneType, bool seekWhilePaused) // shouldTearDown is set to false, because in case of a new tune pipeline // might not be in a playing/paused state which causes Flush() to destroy // pipeline. This has to be avoided. - sink->Flush(flushPosition, rate, false); + sink->Flush(flushPosition, rate, false, seekWhilePaused); } } From c8543b0705117908c25876cf1cde10ca51d0225b Mon Sep 17 00:00:00 2001 From: rekhap2kandhavelan Date: Sun, 12 Jul 2026 21:14:57 +0530 Subject: [PATCH 2/8] Update main_aamp.cpp --- main_aamp.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/main_aamp.cpp b/main_aamp.cpp index 1e0223ad00..4bccb1584c 100755 --- a/main_aamp.cpp +++ b/main_aamp.cpp @@ -917,6 +917,15 @@ void PlayerInstanceAAMP::SetRateInternal(float rate,int overshootcorrection) { retValue = sink->Pause(false, false); } + //If pipeline failed to reach PLAYING state, do not + // mark mSinkPaused=false and trigger a re-tune to recover + if (!retValue) + { + AAMPLOG_ERR("SetRateInternal: Pipeline resume FAILED Triggering re-tune for recovery."); + aamp->ScheduleRetune(eGSTREAMER_PIPELINE_PAUSED_TIMEOUT, + eMEDIATYPE_VIDEO); + return; + } // required since buffers are already cached in paused state aamp->NotifyFirstBufferProcessed(sink ? sink->GetVideoRectangle() : std::string()); } From 08eadec30290787e527eeaf93fc2642f33115476 Mon Sep 17 00:00:00 2001 From: rekhap2kandhavelan Date: Sun, 12 Jul 2026 21:18:32 +0530 Subject: [PATCH 3/8] Update main_aamp.cpp --- main_aamp.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/main_aamp.cpp b/main_aamp.cpp index 4bccb1584c..e4116e6c9e 100755 --- a/main_aamp.cpp +++ b/main_aamp.cpp @@ -932,6 +932,11 @@ void PlayerInstanceAAMP::SetRateInternal(float rate,int overshootcorrection) } aamp->mSinkPaused = false; aamp->ResumeDownloads(); + if (retValue) + { + aamp->mSinkPaused = false; + aamp->ResumeDownloads(); + } } } else if (rate == 0) From 0e978197e504d995d97cc4828181c369ca95ce58 Mon Sep 17 00:00:00 2001 From: rekhap2kandhavelan Date: Sun, 12 Jul 2026 21:18:32 +0530 Subject: [PATCH 4/8] Update main_aamp.cpp --- main_aamp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main_aamp.cpp b/main_aamp.cpp index e4116e6c9e..2c3704a0b7 100755 --- a/main_aamp.cpp +++ b/main_aamp.cpp @@ -922,7 +922,7 @@ void PlayerInstanceAAMP::SetRateInternal(float rate,int overshootcorrection) if (!retValue) { AAMPLOG_ERR("SetRateInternal: Pipeline resume FAILED Triggering re-tune for recovery."); - aamp->ScheduleRetune(eGSTREAMER_PIPELINE_PAUSED_TIMEOUT, + aamp->ScheduleRetune(eGST_ERROR_GST_PIPELINE_INTERNAL, eMEDIATYPE_VIDEO); return; } From d0f7351581f9b58f0c695f6a9a8e0aa1c5e79210 Mon Sep 17 00:00:00 2001 From: rekhap2kandhavelan Date: Sun, 12 Jul 2026 22:17:09 +0530 Subject: [PATCH 5/8] Update aampgstplayer.cpp --- aampgstplayer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aampgstplayer.cpp b/aampgstplayer.cpp index 32a3f24a5e..1e7134830c 100644 --- a/aampgstplayer.cpp +++ b/aampgstplayer.cpp @@ -1136,7 +1136,7 @@ void AAMPGstPlayer::Flush(double position, int rate, bool shouldTearDown, bool k { isAppSeek = true; } - bool ret = playerInstance->Flush(position, rate, shouldTearDown, isAppSeek, keepPausedSeek); + bool ret = playerInstance->Flush(position, rate, shouldTearDown, isAppSeek /*, keepPausedSeek */); if(ret) { for (int i = 0; i < AAMP_TRACK_COUNT; i++) From 4dbdb4c2397c01b78a69a110d1f9aef599858c5b Mon Sep 17 00:00:00 2001 From: rekhap2kandhavelan Date: Mon, 13 Jul 2026 13:10:16 +0530 Subject: [PATCH 6/8] Update main_aamp.cpp fix applied for linear freeze issue --- main_aamp.cpp | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/main_aamp.cpp b/main_aamp.cpp index 2c3704a0b7..5c45487b80 100755 --- a/main_aamp.cpp +++ b/main_aamp.cpp @@ -917,26 +917,35 @@ void PlayerInstanceAAMP::SetRateInternal(float rate,int overshootcorrection) { retValue = sink->Pause(false, false); } - //If pipeline failed to reach PLAYING state, do not - // mark mSinkPaused=false and trigger a re-tune to recover - if (!retValue) - { - AAMPLOG_ERR("SetRateInternal: Pipeline resume FAILED Triggering re-tune for recovery."); - aamp->ScheduleRetune(eGST_ERROR_GST_PIPELINE_INTERNAL, - eMEDIATYPE_VIDEO); - return; - } - // required since buffers are already cached in paused state - aamp->NotifyFirstBufferProcessed(sink ? sink->GetVideoRectangle() : std::string()); + if (sink && !retValue) + { + // Pipeline resume did not complete (async PAUSED->PLAYING wedged by a + // rapid trickplay->seek->resume race - seen on both VOD and FOG-TSB linear). + // Recover by re-seeking to the current position: the same mechanism the + // local-TSB resume path uses. Works uniformly for VOD, FOG-TSB & local TSB. + AAMPLOG_WARN("SetRateInternal: pipeline resume failed (GstState timeout); recovering via re-seek"); + aamp->SetState(eSTATE_SEEKING); + aamp->seek_pos_seconds = aamp->GetPositionSeconds(); + aamp->rate = AAMP_NORMAL_PLAY_RATE; + aamp->mSinkPaused = false; + { + std::lock_guard lock(aamp->GetStreamLock()); + aamp->TuneHelper(eTUNETYPE_SEEK, false); + } + // Skip common notification (like local-TSB path): state -> PLAYING + // via NotifyFirstBufferProcessed once fragments arrive. + retValue = false; + aamp->NotifySpeedChanged(aamp->rate, false); + } + else + { + // required since buffers are already cached in paused state + aamp->NotifyFirstBufferProcessed(sink ? sink->GetVideoRectangle() : std::string()); + } } } aamp->mSinkPaused = false; aamp->ResumeDownloads(); - if (retValue) - { - aamp->mSinkPaused = false; - aamp->ResumeDownloads(); - } } } else if (rate == 0) From 13b113013849c3c70774b59883b5920cd2220c44 Mon Sep 17 00:00:00 2001 From: rekhap2kandhavelan Date: Mon, 13 Jul 2026 16:55:46 +0530 Subject: [PATCH 7/8] Update aampgstplayer.cpp --- aampgstplayer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aampgstplayer.cpp b/aampgstplayer.cpp index 1e7134830c..32a3f24a5e 100644 --- a/aampgstplayer.cpp +++ b/aampgstplayer.cpp @@ -1136,7 +1136,7 @@ void AAMPGstPlayer::Flush(double position, int rate, bool shouldTearDown, bool k { isAppSeek = true; } - bool ret = playerInstance->Flush(position, rate, shouldTearDown, isAppSeek /*, keepPausedSeek */); + bool ret = playerInstance->Flush(position, rate, shouldTearDown, isAppSeek, keepPausedSeek); if(ret) { for (int i = 0; i < AAMP_TRACK_COUNT; i++) From 7f3cb8d968a82d86f5c1e6ae2ddff5201bf7ce2e Mon Sep 17 00:00:00 2001 From: rekhap2kandhavelan Date: Mon, 20 Jul 2026 06:37:53 +0530 Subject: [PATCH 8/8] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- main_aamp.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/main_aamp.cpp b/main_aamp.cpp index 5c45487b80..fc6e19b654 100755 --- a/main_aamp.cpp +++ b/main_aamp.cpp @@ -928,10 +928,11 @@ void PlayerInstanceAAMP::SetRateInternal(float rate,int overshootcorrection) aamp->seek_pos_seconds = aamp->GetPositionSeconds(); aamp->rate = AAMP_NORMAL_PLAY_RATE; aamp->mSinkPaused = false; - { - std::lock_guard lock(aamp->GetStreamLock()); - aamp->TuneHelper(eTUNETYPE_SEEK, false); - } + { + std::lock_guard lock(aamp->GetStreamLock()); + aamp->TuneHelper(eTUNETYPE_SEEK, false); + } + // Skip common notification (like local-TSB path): state -> PLAYING // via NotifyFirstBufferProcessed once fragments arrive. retValue = false;