Skip to content

VPLAY-11126 [AAMP TSB] TsbReader waits for fragments in a tight loop#606

Draft
hthakkar-synamedia wants to merge 28 commits intodev_sprint_25_2from
feature/VPLAY-11126
Draft

VPLAY-11126 [AAMP TSB] TsbReader waits for fragments in a tight loop#606
hthakkar-synamedia wants to merge 28 commits intodev_sprint_25_2from
feature/VPLAY-11126

Conversation

@hthakkar-synamedia
Copy link
Contributor

@hthakkar-synamedia hthakkar-synamedia commented Oct 21, 2025

Reason for Change: When TsbReader tries to read the fragments that are not downloaded yet by the FetcherLoop, it enters into a quick tight loop. Fix here implements producer consumer design and wait for a conditional variable until new fragment is available.
Added L1 microtest
Test Procedure: - Refer Ticket
Risks:low

Reason for Change: When TsbReader tries to read the fragments that
are not downloaded yet by the FetcherLoop, it enters into a quick
tight loop. Fix here implements producer consumer design and wait
for a conditional variable until new fragment is available.
Test Procedure: - Refer Ticket
Risks:low
Reason for Change: When TsbReader tries to read the fragments that
are not downloaded yet by the FetcherLoop, it enters into a quick
tight loop. Fix here implements producer consumer design and wait
for a conditional variable until new fragment is available.

Test Procedure: - Refer Ticket

Risks:low
@hthakkar-synamedia
Copy link
Contributor Author

Addressed the comments

Copy link
Contributor Author

@hthakkar-synamedia hthakkar-synamedia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed the comments

Reason for Change: When TsbReader tries to read the fragments that
are not downloaded yet by the FetcherLoop, it enters into a quick
tight loop. Fix here implements producer consumer design and wait
for a conditional variable until new fragment is available.

Test Procedure: - Refer Ticket

Risks:low
Copy link
Contributor Author

@hthakkar-synamedia hthakkar-synamedia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed typo and modified the RaiseNewVideoTsbContentNotification function

Reason for Change: When TsbReader tries to read the fragments that
are not downloaded yet by the FetcherLoop, it enters into a quick
tight loop. Fix here implements producer consumer design and wait
for a conditional variable until new fragment is available.

Test Procedure: - Refer Ticket

Risks:low
Copilot AI review requested due to automatic review settings October 28, 2025 18:13
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR enhances the TSB (Time Shift Buffer) fragment fetching mechanism by adding a return value to AdvanceTsbFetch to indicate whether a segment was successfully cached, and implements a condition variable-based waiting mechanism to efficiently handle scenarios where no new fragments are available in the TSB.

Key Changes:

  • Modified AdvanceTsbFetch to return bool indicating if a fragment was cached
  • Added condition variable mNewVideoTsbContentCV to signal when new video content is written to TSB
  • Implemented WaitForNewVideoTsbFragment() to block until new content is available or downloads are disabled
  • Replaced polling with event-driven waiting in the TsbReader loop

Reviewed Changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
fragmentcollector_mpd.h Updated method signature and documentation for AdvanceTsbFetch to return bool
fragmentcollector_mpd.cpp Implemented return value logic, added segment tracking, and replaced sleep with condition variable waits
AampTSBSessionManager.h Added new methods and members for condition variable-based notification
AampTSBSessionManager.cpp Implemented wait/notify mechanism and initialized new member variable
priv_aamp.cpp Added notification to unblock waiting threads when downloads are disabled
test/utests/tests/FragmentCollectorMpdTests/FragmentCollectorMpdTestCases.cpp Updated tests to capture and verify the return value
test/utests/fakes/FakeTSBSessionManager.cpp Added stub implementations for new public methods

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Reason for Change: When TsbReader tries to read the fragments that
are not downloaded yet by the FetcherLoop, it enters into a quick
tight loop. Fix here implements producer consumer design and wait
for a conditional variable until new fragment is available.

Test Procedure: - Refer Ticket

Risks:low
Reason for Change: When TsbReader tries to read the fragments that
are not downloaded yet by the FetcherLoop, it enters into a quick
tight loop. Fix here implements producer consumer design and wait
for a conditional variable until new fragment is available.

Test Procedure: - Refer Ticket

Risks:low

Merge branch 'dev_sprint_25_2' of github.com:rdkcentral/aamp into feature/VPLAY-11126
Copilot AI review requested due to automatic review settings October 29, 2025 09:55
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Reason for Change: When TsbReader tries to read the fragments that are
not downloaded yet by the FetcherLoop, it enters into a quick tight loop.
Fix here implements producer consumer design and wait for a conditional
variable until new fragment is available.

Test Procedure: - Refer Ticket

Risks:low
hthakkar-synamedia and others added 2 commits February 10, 2026 16:38
Reason for Change: When TsbReader tries to read the fragments that are
not downloaded yet by the FetcherLoop, it enters into a quick tight loop.
Fix here implements producer consumer design and wait for a conditional
variable until new fragment is available.

Test Procedure: - Refer Ticket

Risks:low
@hthakkar-synamedia hthakkar-synamedia marked this pull request as ready for review February 20, 2026 17:18
@hthakkar-synamedia hthakkar-synamedia requested a review from a team as a code owner February 20, 2026 17:18
Copilot AI review requested due to automatic review settings February 20, 2026 17:18
Avoid race where the TsbReader thread reads predicate between flag being set and the notify firing.

Before joining tsbReaderThreadID, NotifyVideoTsbWaiters() is now called, avoiding potential deadlock:

Avoid tight loop and log spam when rate <= AAMP_NORMAL_PLAY_RATE and no segment is found.

Signed-off-by: Philip Stroffolino <philip_stroffolino@cable.comcast.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

pstroffolino and others added 2 commits March 1, 2026 14:24
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 2, 2026 00:48
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Comment on lines +10009 to +10026
if (segmentFound)
{
aamp->interruptibleMsSleep(50); //To Avoid tight loop adding a small delay
}
// AAMP could reach the end of the TSB only when doing FF (rate > AAMP_NORMAL_PLAY_RATE)
else if (aamp->rate > AAMP_NORMAL_PLAY_RATE)
{
// All the segments in TSB have been sent to gstreamer; avoid indefinite
// blocking in WaitForVideoTsbContentOrAbort by using a bounded, interruptible
// sleep before retrying the fetch loop.
aamp->interruptibleMsSleep(50);
}
else
{
// Unexpected: no segment found at normal/slow rate outside of EOS. Sleep to
// avoid a tight loop and throttle log output until the condition resolves.
AAMPLOG_TRACE("No segment found for rate <= AAMP_NORMAL_PLAY_RATE, retrying");
aamp->interruptibleMsSleep(50);
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR description says TsbReader will block on a condition variable until new fragments are available, but this loop still only polls with interruptibleMsSleep(50) and never calls AampTSBSessionManager::WaitForVideoTsbContentOrAbort(). As a result, the newly added Wait/Notify mechanism is unused in production and the tight-loop/polling behavior remains (the comment even references WaitForVideoTsbContentOrAbort without actually using it). Consider calling WaitForVideoTsbContentOrAbort() when no segments were cached and the cache is not full, and ensure the wait can be interrupted on abort/stop paths.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

@pstroffolino pstroffolino Mar 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this valid issue? If so, how important to address?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think this is a valid issue

Copilot AI review requested due to automatic review settings March 2, 2026 01:52
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Comment on lines +10500 to +10506
// Unblock TsbReader if it is waiting for new video TSB content (e.g. during FF
// on local AAMP TSB where DisableDownloads is not called and therefore
// NotifyVideoTsbWaiters is not triggered via the downloads-disabled path).
if (AampTSBSessionManager *tsbMgr = aamp->GetTSBSessionManager())
{
tsbMgr->NotifyVideoTsbWaiters();
}
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This stop-path comment says it is unblocking TsbReader waiting on WaitForVideoTsbContentOrAbort(), but StreamAbstractionAAMP_MPD::TsbReader() never calls WaitForVideoTsbContentOrAbort() (it only uses WaitForManifestUpdate() / WaitForCachedFragmentChunkInjected() / sleeps). Either wire TsbReader() up to the new condition variable as intended, or adjust/remove this comment + notification so it matches actual behavior.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

valid issue?

Signed-off-by: Philip Stroffolino <philip_stroffolino@cable.comcast.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Copilot AI review requested due to automatic review settings March 2, 2026 14:57
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Comment on lines +595 to +597
// Brief sleep to allow thread to enter waiting state
// Note: This is a timing assumption, but std::thread provides no "is waiting" status check
std::this_thread::sleep_for(std::chrono::milliseconds(10));
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test relies on a fixed sleep to “let the consumer thread enter waiting state”. Fixed timing sleeps can be flaky across different CI loads and platforms. Prefer a deterministic handshake (e.g., a promise/condition_variable that the consumer signals after it is ready to wait) so the test does not depend on scheduling.

Copilot uses AI. Check for mistakes.
Comment on lines +591 to +601
std::thread consumerThread([this]() {
mAampTSBSessionManager->WaitForVideoTsbContentOrAbort();
});

// Brief sleep to allow thread to enter waiting state
// Note: This is a timing assumption, but std::thread provides no "is waiting" status check
std::this_thread::sleep_for(std::chrono::milliseconds(10));

mAampTSBSessionManager->NotifyVideoTsbWaiter();

consumerThread.join();
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If WaitForVideoTsbContentOrAbort() fails to unblock, this join will hang the entire test binary indefinitely. Consider adding a bounded wait (e.g., run the wait in a future and ASSERT that it completes within a timeout) so failures are reported rather than deadlocking CI.

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings March 4, 2026 15:40
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.

Comment on lines 143 to +147
EXPECT_CALL(*g_mockTSBReader, IsEos()).WillOnce(Return(false));
EXPECT_CALL(*g_mockTSBSessionManager, PushNextTsbFragment(mediaStreamContext, _)).WillOnce(Return(true));

// Call the protected method through testable wrapper
mMpdStream->TestAdvanceTsbFetch(trackIdx, trickPlay, delta, waitForFreeFrag, bCacheFullState);
bool result = mMpdStream->TestAdvanceTsbFetch(trackIdx, trickPlay, delta, waitForFreeFrag, bCacheFullState);
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The expectations are set on g_mockTSBReader, but GetTsbReader is configured to return a real AampTsbReader (tsbReader). As a result, the EXPECT_CALLs on g_mockTSBReader will never be satisfied and this test will fail. Return g_mockTSBReader (as a shared_ptr) from GetTsbReader or set expectations against the actual object being used.

Copilot uses AI. Check for mistakes.
Comment on lines 146 to +147
// Call the protected method through testable wrapper
mMpdStream->TestAdvanceTsbFetch(trackIdx, trickPlay, delta, waitForFreeFrag, bCacheFullState);
bool result = mMpdStream->TestAdvanceTsbFetch(trackIdx, trickPlay, delta, waitForFreeFrag, bCacheFullState);
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test allocates MediaStreamContext with new and never deletes it. Please switch to RAII (e.g., std::unique_ptr) or ensure it is deleted at the end of the test to avoid leaking across the unit test process.

Copilot uses AI. Check for mistakes.
Comment on lines 179 to +183
// Verify that PushNextTsbFragment is NOT called when track is disabled
EXPECT_CALL(*g_mockTSBSessionManager, PushNextTsbFragment(mediaStreamContext, _)).Times(0);

// Call the protected method through testable wrapper
mMpdStream->TestAdvanceTsbFetch(trackIdx, trickPlay, delta, waitForFreeFrag, bCacheFullState);
bool result = mMpdStream->TestAdvanceTsbFetch(trackIdx, trickPlay, delta, waitForFreeFrag, bCacheFullState);
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as above: g_mockTSBReader has EXPECT_CALL(TrackEnabled) but GetTsbReader returns a real AampTsbReader instance (tsbReader). The TrackEnabled expectation will be unmet and the test will fail. Configure GetTsbReader to return g_mockTSBReader (or otherwise ensure expectations are set on the object actually used).

Copilot uses AI. Check for mistakes.
Comment on lines +607 to +614
mAampTSBSessionManager->NotifyVideoTsbWaiter();

// Spawn a thread that waits for the notification
std::thread consumerThread([this]() {
mAampTSBSessionManager->WaitForVideoTsbContentOrAbort();
});

consumerThread.join();
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as the previous test: this thread join is unbounded. Please add a bounded wait/timeout-based assertion (e.g., future.wait_for) so a regression cannot deadlock the full test suite.

Copilot uses AI. Check for mistakes.
@hthakkar-synamedia hthakkar-synamedia marked this pull request as draft March 4, 2026 16:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants