Skip to content

Conversation

@sayanurag
Copy link
Contributor

Reason for change: Moving the Teardown operation before the mpd update release cause some delay and results in more Http 404 errors.
Test Procedure: updated in ticket
Risks: Low

Reason for change: Moving the Teardown operation before the mpd update release cause some delay and results in more Http 404 errors.
Test Procedure: updated in ticket
Risks: Low

Signed-off-by: Anurag Krishnan <akrish513@cable.comcast.com>
Copilot AI review requested due to automatic review settings January 13, 2026 10:12
@sayanurag sayanurag requested a review from a team as a code owner January 13, 2026 10:12
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 addresses HTTP 404 errors occurring during channel changes by moving the MPD downloader release operation to happen immediately after stream abstraction deletion, rather than waiting for the complete Stop() sequence to finish.

Changes:

  • Added conditional MPD downloader release inside TeardownStream() when disableDownloads is true
  • The early release prevents unnecessary MPD update requests that would fail with HTTP 404 during channel transitions

// stop the mpd update immediately after Stream abstraction delete
if(mMPDDownloaderInstance != nullptr)
{
mMPDDownloaderInstance->Release();
Copy link
Contributor

Choose a reason for hiding this comment

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

Can this call be removed from other places since it is done here? I.e. from PrivateInstanceAAMP::detach() and PrivateInstanceAAMP::Stop()

Copilot AI review requested due to automatic review settings January 20, 2026 11:08
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 1 out of 1 changed files in this pull request and generated 3 comments.

Comment on lines +5231 to +5233
if(mMPDDownloaderInstance != nullptr)
{
mMPDDownloaderInstance->Release();
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

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

The new code block accesses mMPDDownloaderInstance without holding mLock. While this appears consistent with similar patterns elsewhere in the codebase (e.g., Stop() at line 8091 and detach() at line 7110), consider whether explicit locking is needed here for thread safety. The Release() method has internal locking via mMPDDnldMutex, but the pointer access itself is not synchronized. If mMPDDownloaderInstance can be deleted or modified from another thread during teardown, this could lead to a race condition.

Suggested change
if(mMPDDownloaderInstance != nullptr)
{
mMPDDownloaderInstance->Release();
AampMPDDownloader *mpdDownloader = NULL;
lock.lock();
mpdDownloader = mMPDDownloaderInstance;
lock.unlock();
if(mpdDownloader != NULL)
{
mpdDownloader->Release();

Copilot uses AI. Check for mistakes.
Comment on lines +5228 to +5235
if(disableDownloads)
{
// stop the mpd update immediately after Stream abstraction delete
if(mMPDDownloaderInstance != nullptr)
{
mMPDDownloaderInstance->Release();
}
}
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

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

This change introduces a potential double-call to mMPDDownloaderInstance->Release(). When TeardownStream(true, true) is called from Stop() (line 8088), this new code will call Release(), and then Stop() calls it again at line 8091-8094. While Release() is idempotent (protected by the mReleaseCalled flag), consider whether the duplicate call in Stop() should be removed to avoid confusion and make the cleanup flow clearer.

Suggested change
if(disableDownloads)
{
// stop the mpd update immediately after Stream abstraction delete
if(mMPDDownloaderInstance != nullptr)
{
mMPDDownloaderInstance->Release();
}
}
// Note: MPD downloader Release() is handled by the caller (e.g. Stop())
// to avoid duplicate Release() calls when TeardownStream(true, true) is
// invoked from Stop().

Copilot uses AI. Check for mistakes.
Comment on lines +5228 to +5235
if(disableDownloads)
{
// stop the mpd update immediately after Stream abstraction delete
if(mMPDDownloaderInstance != nullptr)
{
mMPDDownloaderInstance->Release();
}
}
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

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

The code uses a raw pointer (mMPDDownloaderInstance) with manual lifecycle management (new at line 5628, SAFE_DELETE at line 8199). Consider refactoring to use a smart pointer (e.g., std::unique_ptr) to follow modern C++ RAII principles and improve memory safety. This would make ownership semantics clearer and eliminate the possibility of memory leaks.

Copilot generated this review using guidance from repository custom instructions.
@sayanurag sayanurag force-pushed the feature/VPLAY-12164_http-404 branch from 6098e5f to 62d4beb Compare January 20, 2026 11:16
Copilot AI review requested due to automatic review settings January 21, 2026 20: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 1 out of 1 changed files in this pull request and generated 3 comments.


if(disableDownloads)
{
// stop the mpd update immediately after Stream abstraction delete
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

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

The comment "stop the mpd update immediately after Stream abstraction delete" is copied from line 8104 in the Stop() function but doesn't explain the rationale for this specific placement.

The comment should clarify:

  1. Why the MPD downloader needs to be released at this point in TeardownStream
  2. How this placement helps reduce HTTP 404 errors during channel changes (as mentioned in the PR description)
  3. The relationship with the existing Release() call in Stop() at line 8107

This will help future maintainers understand the design decision and prevent accidental removal or duplication.

Suggested change
// stop the mpd update immediately after Stream abstraction delete
/*
* DASH-specific teardown: explicitly stop MPD updates as soon as the
* stream abstraction has been stopped/deleted.
*
* Rationale:
* - When changing channels, the MPD downloader may still be running
* background manifest refreshes based on the old stream abstraction
* state (periods, adaptation sets, timelines, etc.).
* - If the service reuses the same MPD URL for the new channel or if
* the old MPD becomes invalid while those refreshes are still in
* flight, the downloader can issue requests that no longer match
* the server state, leading to transient HTTP 404s during channel
* changes (as described in the PR).
*
* By releasing the MPD downloader here, immediately after
* mpStreamAbstractionAAMP is torn down and only when downloads are
* being disabled, we ensure that no further MPD refreshes are issued
* based on stale stream state.
*
* Note:
* - There is also a later mMPDDownloaderInstance->Release() call in
* Stop() (line 8107) which serves as a final safety net / global
* cleanup.
* - This earlier Release() in TeardownStream is the intentional,
* protocol-aware shutdown point required to avoid the 404 bursts
* seen on rapid channel changes; the Stop()-level call must not be
* treated as a replacement for this one.
*/

Copilot uses AI. Check for mistakes.
Comment on lines +5242 to +5249
if(disableDownloads)
{
// stop the mpd update immediately after Stream abstraction delete
if(mMPDDownloaderInstance != nullptr)
{
mMPDDownloaderInstance->Release();
}
}
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

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

This new code path (calling mMPDDownloaderInstance->Release() inside TeardownStream when disableDownloads is true) lacks test coverage.

The existing TeardownStream tests in test/utests/tests/PrivAampTests/PrivAampTests.cpp (TeardownStreamTest, TeardownStreamTest_1, TeardownStreamTest_2) do not verify:

  1. That Release() is called when disableDownloads=true
  2. That Release() is NOT called when disableDownloads=false
  3. The interaction with mMPDDownloaderInstance being null vs non-null

Add test cases to verify this behavior, especially for the scenario described in the ticket (channel change causing HTTP 404 errors).

Copilot uses AI. Check for mistakes.
Comment on lines +5242 to +5249
if(disableDownloads)
{
// stop the mpd update immediately after Stream abstraction delete
if(mMPDDownloaderInstance != nullptr)
{
mMPDDownloaderInstance->Release();
}
}
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

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

This change introduces a potential duplicate Release() call when TeardownStream is invoked from the Stop() function. At line 8102, Stop() calls TeardownStream(true, true) with disableDownloads=true, which will trigger this new Release() call. Then at line 8107, Stop() calls mMPDDownloaderInstance->Release() again.

While Release() is idempotent (protected by the mReleaseCalled flag), this duplication suggests a design issue. Consider one of the following solutions:

  1. Remove the Release() call at line 8107 in Stop() since it's now handled in TeardownStream
  2. Remove this new code and keep the existing Release() call in Stop() at line 8107
  3. Add a clear comment explaining why Release() is called in both locations if both are truly needed

The PR description mentions "Moving the Teardown operation before the mpd update release cause some delay" which suggests option 1 (removing the call from Stop()) may be the intended solution.

Suggested change
if(disableDownloads)
{
// stop the mpd update immediately after Stream abstraction delete
if(mMPDDownloaderInstance != nullptr)
{
mMPDDownloaderInstance->Release();
}
}

Copilot uses AI. Check for mistakes.
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.

4 participants