mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Discard already written sample data for clipped DASH periods
DASH periods can have a duration that is less than the end of the last chunk in the period. In these cases, the sample data needs to be clipped to the declared period duration. This already happens IF the period duration is known at the point where we start loading the media chunk. However, if the duration becomes known later or is reduced (e.g. in a live stream), the existing media chunks are not clipped. This causes unclean transitions across periods where the player tries to transition to the next period, but renderers struggle to output all the remaining surplus samples that should have been clipped. This can be fixed by asking ChunkSampleStream to discard surplus samples that were loaded beyond a clipped duration when evaluating the sample queue between chunk loads. Issue: androidx/media#1698 PiperOrigin-RevId: 713288221
This commit is contained in:
parent
bb3b85a359
commit
b321c8d3bd
@ -62,6 +62,9 @@
|
||||
* Parse `scte214:supplementalCodecs` attribute from DASH manifest to
|
||||
detect Dolby Vision formats
|
||||
([#1785](https://github.com/androidx/media/pull/1785)).
|
||||
* Improve handling of period transitions in live streams where the period
|
||||
contains media samples beyond the declared period duration
|
||||
([#1698](https://github.com/androidx/media/issues/1698)).
|
||||
* Smooth Streaming Extension:
|
||||
* RTSP Extension:
|
||||
* Decoder Extensions (FFmpeg, VP9, AV1, etc.):
|
||||
|
@ -722,6 +722,39 @@ public class ChunkSampleStream<T extends ChunkSource>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Discards upstream samples that exceed the given clipped duration of the stream.
|
||||
*
|
||||
* @param clippedDurationUs The clipped duration of the stream in microseconds, or {@link
|
||||
* C#TIME_UNSET} if not known.
|
||||
*/
|
||||
public void discardUpstreamSamplesForClippedDuration(long clippedDurationUs) {
|
||||
Assertions.checkState(!loader.isLoading());
|
||||
if (isPendingReset() || clippedDurationUs == C.TIME_UNSET || mediaChunks.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
BaseMediaChunk lastMediaChunk = getLastMediaChunk();
|
||||
long lastMediaChunkEndTimeUs =
|
||||
lastMediaChunk.clippedEndTimeUs != C.TIME_UNSET
|
||||
? lastMediaChunk.clippedEndTimeUs
|
||||
: lastMediaChunk.endTimeUs;
|
||||
if (lastMediaChunkEndTimeUs <= clippedDurationUs) {
|
||||
// Last chunk doesn't need to be clipped further.
|
||||
return;
|
||||
}
|
||||
long largestQueuedTimestampUs = primarySampleQueue.getLargestQueuedTimestampUs();
|
||||
if (largestQueuedTimestampUs <= clippedDurationUs) {
|
||||
// No data beyond new duration that needs to be clipped.
|
||||
return;
|
||||
}
|
||||
primarySampleQueue.discardUpstreamFrom(clippedDurationUs);
|
||||
for (SampleQueue embeddedSampleQueue : embeddedSampleQueues) {
|
||||
embeddedSampleQueue.discardUpstreamFrom(clippedDurationUs);
|
||||
}
|
||||
mediaSourceEventDispatcher.upstreamDiscarded(
|
||||
primaryTrackType, clippedDurationUs, largestQueuedTimestampUs);
|
||||
}
|
||||
|
||||
private void discardUpstream(int preferredQueueSize) {
|
||||
Assertions.checkState(!loader.isLoading());
|
||||
|
||||
|
@ -324,6 +324,12 @@ import java.util.regex.Pattern;
|
||||
|
||||
@Override
|
||||
public void reevaluateBuffer(long positionUs) {
|
||||
for (ChunkSampleStream<DashChunkSource> sampleStream : sampleStreams) {
|
||||
if (!sampleStream.isLoading()) {
|
||||
long periodDurationUs = manifest.getPeriodDurationUs(periodIndex);
|
||||
sampleStream.discardUpstreamSamplesForClippedDuration(periodDurationUs);
|
||||
}
|
||||
}
|
||||
compositeSequenceableLoader.reevaluateBuffer(positionUs);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user