Merge pull request #528 from zgzong:patch-2

PiperOrigin-RevId: 554869426
(cherry picked from commit ef54364478)
This commit is contained in:
Tianyi Feng 2023-08-10 12:09:43 +00:00
parent 57c73d51da
commit 294fa261b7
4 changed files with 152 additions and 1 deletions

View file

@ -410,7 +410,9 @@ public class DefaultDashChunkSource implements DashChunkSource {
}
long periodDurationUs = representationHolder.periodDurationUs;
boolean periodEnded = periodDurationUs != C.TIME_UNSET;
boolean isLastPeriodInDynamicManifest =
manifest.dynamic && periodIndex == manifest.getPeriodCount() - 1;
boolean periodEnded = !isLastPeriodInDynamicManifest || periodDurationUs != C.TIME_UNSET;
if (representationHolder.getSegmentCount() == 0) {
// The index doesn't define any segments.
@ -420,6 +422,16 @@ public class DefaultDashChunkSource implements DashChunkSource {
long firstAvailableSegmentNum = representationHolder.getFirstAvailableSegmentNum(nowUnixTimeUs);
long lastAvailableSegmentNum = representationHolder.getLastAvailableSegmentNum(nowUnixTimeUs);
if (isLastPeriodInDynamicManifest) {
long lastAvailableSegmentEndTimeUs =
representationHolder.getSegmentEndTimeUs(lastAvailableSegmentNum);
long lastSegmentDurationUs =
lastAvailableSegmentEndTimeUs
- representationHolder.getSegmentStartTimeUs(lastAvailableSegmentNum);
// Account for some inaccuracy in the overall period duration value by assuming that the
// period is finished once no further full sample fits into the overall duration.
periodEnded &= (lastAvailableSegmentEndTimeUs + lastSegmentDurationUs >= periodDurationUs);
}
long segmentNum =
getSegmentNum(
representationHolder,

View file

@ -38,6 +38,7 @@ import androidx.media3.exoplayer.source.MediaLoadData;
import androidx.media3.exoplayer.source.chunk.BundledChunkExtractor;
import androidx.media3.exoplayer.source.chunk.Chunk;
import androidx.media3.exoplayer.source.chunk.ChunkHolder;
import androidx.media3.exoplayer.source.chunk.MediaChunk;
import androidx.media3.exoplayer.trackselection.AdaptiveTrackSelection;
import androidx.media3.exoplayer.trackselection.FixedTrackSelection;
import androidx.media3.exoplayer.upstream.CmcdConfiguration;
@ -414,6 +415,104 @@ public class DefaultDashChunkSourceTest {
"key4=5.0");
}
@Test
public void
getNextChunk_afterLastAvailableButBeforeEndOfLiveManifestWithKnownDuration_doesNotReturnEndOfStream()
throws Exception {
DashManifest manifest =
new DashManifestParser()
.parse(
Uri.parse("https://example.com/test.mpd"),
TestUtil.getInputStream(
ApplicationProvider.getApplicationContext(),
"media/mpd/sample_mpd_live_known_duration_not_ended"));
DefaultDashChunkSource chunkSource =
new DefaultDashChunkSource(
BundledChunkExtractor.FACTORY,
new LoaderErrorThrower.Placeholder(),
manifest,
new BaseUrlExclusionList(),
/* periodIndex= */ 0,
/* adaptationSetIndices= */ new int[] {0},
new FixedTrackSelection(new TrackGroup(new Format.Builder().build()), /* track= */ 0),
C.TRACK_TYPE_VIDEO,
new FakeDataSource(),
/* elapsedRealtimeOffsetMs= */ 0,
/* maxSegmentsPerLoad= */ 1,
/* enableEventMessageTrack= */ false,
/* closedCaptionFormats= */ ImmutableList.of(),
/* playerTrackEmsgHandler= */ null,
PlayerId.UNSET,
/* cmcdConfiguration= */ null);
ChunkHolder output = new ChunkHolder();
// Populate with last available media chunk
chunkSource.getNextChunk(
/* playbackPositionUs= */ 0,
/* loadPositionUs= */ 0,
/* queue= */ ImmutableList.of(),
output);
Chunk previousChunk = output.chunk;
output.clear();
// Request another chunk
chunkSource.getNextChunk(
/* playbackPositionUs= */ 0,
/* loadPositionUs= */ 4_000_000,
/* queue= */ ImmutableList.of((MediaChunk) previousChunk),
output);
assertThat(output.endOfStream).isFalse();
assertThat(output.chunk).isNull();
}
@Test
public void getNextChunk_atEndOfLiveManifestWithKnownDuration_returnsEndOfStream()
throws Exception {
DashManifest manifest =
new DashManifestParser()
.parse(
Uri.parse("https://example.com/test.mpd"),
TestUtil.getInputStream(
ApplicationProvider.getApplicationContext(),
"media/mpd/sample_mpd_live_known_duration_ended"));
DefaultDashChunkSource chunkSource =
new DefaultDashChunkSource(
BundledChunkExtractor.FACTORY,
new LoaderErrorThrower.Placeholder(),
manifest,
new BaseUrlExclusionList(),
/* periodIndex= */ 0,
/* adaptationSetIndices= */ new int[] {0},
new FixedTrackSelection(new TrackGroup(new Format.Builder().build()), /* track= */ 0),
C.TRACK_TYPE_VIDEO,
new FakeDataSource(),
/* elapsedRealtimeOffsetMs= */ 0,
/* maxSegmentsPerLoad= */ 1,
/* enableEventMessageTrack= */ false,
/* closedCaptionFormats= */ ImmutableList.of(),
/* playerTrackEmsgHandler= */ null,
PlayerId.UNSET,
/* cmcdConfiguration= */ null);
ChunkHolder output = new ChunkHolder();
// Populate with last media chunk
chunkSource.getNextChunk(
/* playbackPositionUs= */ 0,
/* loadPositionUs= */ 4_000_000,
/* queue= */ ImmutableList.of(),
output);
Chunk previousChunk = output.chunk;
output.clear();
// Request next chunk
chunkSource.getNextChunk(
/* playbackPositionUs= */ 0,
/* loadPositionUs= */ 8_000_000,
/* queue= */ ImmutableList.of((MediaChunk) previousChunk),
output);
assertThat(output.endOfStream).isTrue();
}
private DashChunkSource createDashChunkSource(
int numberOfTracks, @Nullable CmcdConfiguration cmcdConfiguration) throws IOException {
Assertions.checkArgument(numberOfTracks < 6);

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<MPD
type="dynamic"
timeShiftBufferDepth="PT16S"
minimumUpdatePeriod="PT4M"
availabilityStartTime="2024-01-01T00:01:00Z">
<UTCTiming
schemeIdUri="urn:mpeg:dash:utc:direct:2014"
value="2024-01-01T00:01:00Z" />
<Period id="1" start="PT0S" duration="PT10S">
<AdaptationSet id="0" contentType="video">
<SegmentTemplate presentationTimeOffset="0" timescale="1000" startNumber="1" media="video_$Time$.m4s">
<SegmentTimeline>
<S t="0" d="4000" r="1"/>
</SegmentTimeline>
</SegmentTemplate>
<Representation id="0"/>
</AdaptationSet>
</Period>
</MPD>

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<MPD
type="dynamic"
timeShiftBufferDepth="PT16S"
minimumUpdatePeriod="PT4M"
availabilityStartTime="2024-01-01T00:01:00Z">
<UTCTiming
schemeIdUri="urn:mpeg:dash:utc:direct:2014"
value="2024-01-01T00:01:00Z" />
<Period id="1" start="PT0S" duration="PT10S">
<AdaptationSet id="0" contentType="video">
<SegmentTemplate presentationTimeOffset="0" timescale="1000" startNumber="1" media="video_$Time$.m4s">
<SegmentTimeline>
<S t="0" d="4000"/>
</SegmentTimeline>
</SegmentTemplate>
<Representation id="0"/>
</AdaptationSet>
</Period>
</MPD>