-
Notifications
You must be signed in to change notification settings - Fork 7
VPLAY-11582 ProcessFragmentChunk() uses timescale of segment downloaded #900
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev_sprint_25_2
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -1031,36 +1031,16 @@ bool MediaTrack::ProcessFragmentChunk() | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //Print box details | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //isobuf.printBoxes(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| uint32_t timeScale = 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if(type == eTRACK_VIDEO) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| timeScale = aamp->GetVidTimeScale(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else if(type == eTRACK_AUDIO) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| timeScale = aamp->GetAudTimeScale(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else if (type == eTRACK_SUBTITLE) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| timeScale = aamp->GetSubTimeScale(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Use the timescale stored in the cached fragment, which represents the timescale | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // of the segment being injected. This is critical when using TSB, as the segment | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // being downloaded at the live edge may have a different timescale (e.g., an ad) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // than the segment being injected from TSB (e.g., base content). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| uint32_t timeScale = cachedFragment->timeScale; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if(!timeScale) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //FIX-ME-Read from MPD INSTEAD | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if(pContext) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| timeScale = pContext->GetCurrPeriodTimeScale(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if(!timeScale) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| timeScale = 10000000.0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| AAMPLOG_WARN("[%s] Empty timeScale!!! Using default timeScale=%d", name, timeScale); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| timeScale = 1000.0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| AAMPLOG_WARN("[%s] Invalid play context maybe test setup, timeScale=%d", name, timeScale); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| AAMPLOG_ERR("[%s] Cached fragment timescale is 0, fragment URI: %s", name, cachedFragment->uri.c_str()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1034
to
+1043
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| AAMPLOG_ERR("[%s] Cached fragment timescale is 0, fragment URI: %s", name, cachedFragment->uri.c_str()); | |
| return true; | |
| // Fallback to global track-specific timescale when the cached fragment | |
| // timescale is zero. This matches legacy behavior and unit test | |
| // expectations (see MediaTrackTests.cpp). | |
| switch (type) | |
| { | |
| case eTRACK_VIDEO: | |
| timeScale = GetVidTimeScale(); | |
| break; | |
| case eTRACK_AUDIO: | |
| timeScale = GetAudTimeScale(); | |
| break; | |
| case eTRACK_SUBTITLE: | |
| timeScale = GetSubTimeScale(); | |
| break; | |
| default: | |
| timeScale = 0; | |
| break; | |
| } | |
| if (!timeScale) | |
| { | |
| AAMPLOG_ERR("[%s] Cached fragment timescale is 0 and no valid global " | |
| "timescale available, fragment URI: %s", name, | |
| cachedFragment->uri.c_str()); | |
| return true; | |
| } | |
| AAMPLOG_WARN("[%s] Cached fragment timescale is 0, using global " | |
| "timescale %u for fragment URI: %s", name, timeScale, | |
| cachedFragment->uri.c_str()); |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -820,3 +820,113 @@ TEST_F(MediaTrackTests, MediaTrackConstructorChunkModeTest) | |||||||||||||||||||||||||||||||||||||||||||||||||||
| TestableMediaTrack videoTrack{eTRACK_VIDEO, mPrivateInstanceAAMP, "video", mStreamAbstractionAAMP_MPD}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| EXPECT_EQ(videoTrack.GetCachedFragmentChunksSize(), kMaxFragmentChunkCached); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @brief Test data for ProcessFragmentChunk timescale tests | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * This structure holds the test parameters for verifying that ProcessFragmentChunk | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * uses the correct timescale from the cached fragment (critical for TSB playback | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * where injected segments may have different timescales than live edge segments). | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| struct ChunkTimescaleTestData | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| uint32_t cachedFragmentTimeScale; /**< Timescale stored in the cached fragment */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| uint32_t globalTimeScale; /**< Global timescale from AAMP instance */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| uint32_t expectedTimeScale; /**< Expected timescale to be used in ParseChunkData */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| class MediaTrackProcessFragmentChunkTimescaleTests | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| : public MediaTrackTests, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| public testing::WithParamInterface<ChunkTimescaleTestData> | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @brief Test that ProcessFragmentChunk uses the cached fragment's timescale | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * This test verifies that when processing fragment chunks, the timescale from | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * the cached fragment is used (if set), rather than falling back to global | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * timescales. This is critical for TSB (Time-Shift Buffer) scenarios where: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * - The segment being downloaded at the live edge may be from an ad with one timescale | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * - The segment being injected from TSB may be from base content with a different timescale | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * The test would fail if ProcessFragmentChunk used global timescales instead of the | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * cached fragment's timescale, as the ParseChunkData mock expects the exact timescale | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * value from the cached fragment. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+845
to
+855
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @brief Test that ProcessFragmentChunk uses the cached fragment's timescale | |
| * | |
| * This test verifies that when processing fragment chunks, the timescale from | |
| * the cached fragment is used (if set), rather than falling back to global | |
| * timescales. This is critical for TSB (Time-Shift Buffer) scenarios where: | |
| * - The segment being downloaded at the live edge may be from an ad with one timescale | |
| * - The segment being injected from TSB may be from base content with a different timescale | |
| * | |
| * The test would fail if ProcessFragmentChunk used global timescales instead of the | |
| * cached fragment's timescale, as the ParseChunkData mock expects the exact timescale | |
| * value from the cached fragment. | |
| * @brief Test that ProcessFragmentChunk prefers the cached fragment's timescale | |
| * | |
| * This test verifies that when processing fragment chunks, the timescale from | |
| * the cached fragment is used when it is non-zero, and that when the cached | |
| * fragment's timescale is zero, ProcessFragmentChunk falls back to the global | |
| * timescale from the AAMP instance. This is critical for TSB (Time-Shift Buffer) | |
| * scenarios where: | |
| * - The segment being downloaded at the live edge may be from an ad with one timescale | |
| * - The segment being injected from TSB may be from base content with a different timescale | |
| * | |
| * The test would fail if ProcessFragmentChunk did not select the correct effective | |
| * timescale (cached fragment's timescale when non-zero, otherwise the global | |
| * timescale), as the ParseChunkData mock expects the timescale value provided | |
| * by the test parameters. |
Copilot
AI
Jan 23, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The PR description states "Verify timescale used by InjectFragment() in L1 tests" but the tests are actually for ProcessFragmentChunk(), not InjectFragment(). While InjectFragment() internally calls ProcessFragmentChunk() (when in chunk mode), the test naming and PR description should be consistent about which function is being tested. The test name "UseCachedFragmentTimescaleInParseChunkData" correctly indicates it's testing ProcessFragmentChunk's behavior.
Copilot
AI
Jan 23, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment states "used as fallback when cached fragment timescale is 0" but the production code at streamabstraction.cpp:1040-1043 does NOT implement this fallback. The mock for GetVidTimeScale() is set up but will never be called because the production code returns early when timeScale is 0. This mock setup is misleading and the comment should be corrected.
Copilot
AI
Jan 23, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment at line 912 states "or falls back to global timescale when cachedFragment->timeScale is 0", but the production code at streamabstraction.cpp:1040-1043 does NOT implement this fallback behavior. Instead, it logs an error and returns early. Either this comment needs to be updated to reflect that fallback is NOT supported, or the production code needs to be changed to implement the fallback. This mismatch will cause test failures for the test cases at lines 927-928.
| // This tests that ProcessFragmentChunk uses cachedFragment->timeScale when set, | |
| // or falls back to global timescale when cachedFragment->timeScale is 0 | |
| // This tests that ProcessFragmentChunk uses cachedFragment->timeScale when set. | |
| // Note: Fallback to a global timescale when cachedFragment->timeScale is 0 is not implemented. |
Copilot
AI
Jan 23, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These test cases will FAIL because they expect ParseChunkData to be called with the global timescale when cachedFragment->timeScale is 0, but the production code at streamabstraction.cpp:1040-1043 returns early without calling ParseChunkData. Either these test cases need to be removed, or the production code needs to implement the fallback behavior as the old code did (using GetVidTimeScale/GetAudTimeScale/GetSubTimeScale based on track type).
Copilot
AI
Jan 23, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment suggests fallback behavior is expected and supported, but the production code at streamabstraction.cpp:1040-1043 does not implement fallback - it returns early with an error. This creates confusion about whether timeScale=0 should be treated as an error condition or as a valid scenario requiring fallback to global timescales.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Returning 'true' (success) when timeScale is 0 is semantically incorrect. The function ProcessFragmentChunk returns true to indicate success in processing a chunk, but in this case the chunk is not processed at all. Consider returning 'false' to indicate failure, or implement the fallback logic to use global timescales as the old code did. This silent failure could mask real issues where fragments legitimately have timeScale set to 0.