From 454b106921524fd8746aeb106ade6c4a8f7178a8 Mon Sep 17 00:00:00 2001 From: olly Date: Mon, 6 Aug 2018 03:06:27 -0700 Subject: [PATCH] Fix freezing playing multi-period DASH with EventStreams EventSampleStream.readData required eventStreamUpdatable to be false for END_OF_STREAM to be returned, but it was only being set to false when the manifest became static. This change also sets it to false if the period is not the last one in a dynamic manifest. It also renames it the parameter to appendable, since that's what it really represents. Events may still be removed from the start of the EventStream as the period starts moving out of the live window. Issue: #4492 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=207517265 --- RELEASENOTES.md | 7 ++- .../source/dash/DashMediaPeriod.java | 5 ++- .../source/dash/EventSampleStream.java | 45 ++++++++++--------- 3 files changed, 34 insertions(+), 23 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 9dd0ed3dfe..c529babcec 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -99,8 +99,11 @@ ([#4491](https://github.com/google/ExoPlayer/issues/4491)). * CEA-608: Improve handling of embedded styles ([#4321](https://github.com/google/ExoPlayer/issues/4321)). -* DASH: Exclude text streams from duration calculations - ([#4029](https://github.com/google/ExoPlayer/issues/4029)). +* DASH: + * Exclude text streams from duration calculations + ([#4029](https://github.com/google/ExoPlayer/issues/4029)). + * Fix freezing when playing multi-period manifests with `EventStream`s + ([#4492](https://github.com/google/ExoPlayer/issues/4492)). * DRM: Allow DrmInitData to carry a license server URL ([#3393](https://github.com/google/ExoPlayer/issues/3393)). * MPEG-TS: Fix bug preventing SCTE-35 cues from being output diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java index a22fd5ab2a..eeb27261a7 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java @@ -149,7 +149,10 @@ import java.util.List; for (EventSampleStream eventSampleStream : eventSampleStreams) { for (EventStream eventStream : eventStreams) { if (eventStream.id().equals(eventSampleStream.eventStreamId())) { - eventSampleStream.updateEventStream(eventStream, manifest.dynamic); + int lastPeriodIndex = manifest.getPeriodCount() - 1; + eventSampleStream.updateEventStream( + eventStream, + /* eventStreamAppendable= */ manifest.dynamic && periodIndex == lastPeriodIndex); break; } } diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/EventSampleStream.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/EventSampleStream.java index 7fef59f6a1..9f812b8e84 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/EventSampleStream.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/EventSampleStream.java @@ -36,37 +36,53 @@ import java.io.IOException; private final EventMessageEncoder eventMessageEncoder; private long[] eventTimesUs; - private boolean eventStreamUpdatable; + private boolean eventStreamAppendable; private EventStream eventStream; private boolean isFormatSentDownstream; private int currentIndex; private long pendingSeekPositionUs; - EventSampleStream(EventStream eventStream, Format upstreamFormat, boolean eventStreamUpdatable) { + public EventSampleStream( + EventStream eventStream, Format upstreamFormat, boolean eventStreamAppendable) { this.upstreamFormat = upstreamFormat; this.eventStream = eventStream; eventMessageEncoder = new EventMessageEncoder(); pendingSeekPositionUs = C.TIME_UNSET; eventTimesUs = eventStream.presentationTimesUs; - updateEventStream(eventStream, eventStreamUpdatable); + updateEventStream(eventStream, eventStreamAppendable); } - void updateEventStream(EventStream eventStream, boolean eventStreamUpdatable) { + public String eventStreamId() { + return eventStream.id(); + } + + public void updateEventStream(EventStream eventStream, boolean eventStreamAppendable) { long lastReadPositionUs = currentIndex == 0 ? C.TIME_UNSET : eventTimesUs[currentIndex - 1]; - this.eventStreamUpdatable = eventStreamUpdatable; + this.eventStreamAppendable = eventStreamAppendable; this.eventStream = eventStream; this.eventTimesUs = eventStream.presentationTimesUs; if (pendingSeekPositionUs != C.TIME_UNSET) { seekToUs(pendingSeekPositionUs); } else if (lastReadPositionUs != C.TIME_UNSET) { - currentIndex = Util.binarySearchCeil(eventTimesUs, lastReadPositionUs, false, false); + currentIndex = + Util.binarySearchCeil( + eventTimesUs, lastReadPositionUs, /* inclusive= */ false, /* stayInBounds= */ false); } } - String eventStreamId() { - return eventStream.id(); + /** + * Seeks to the specified position in microseconds. + * + * @param positionUs The seek position in microseconds. + */ + public void seekToUs(long positionUs) { + currentIndex = + Util.binarySearchCeil( + eventTimesUs, positionUs, /* inclusive= */ true, /* stayInBounds= */ false); + boolean isPendingSeek = eventStreamAppendable && currentIndex == eventTimesUs.length; + pendingSeekPositionUs = isPendingSeek ? positionUs : C.TIME_UNSET; } @Override @@ -88,7 +104,7 @@ import java.io.IOException; return C.RESULT_FORMAT_READ; } if (currentIndex == eventTimesUs.length) { - if (!eventStreamUpdatable) { + if (!eventStreamAppendable) { buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM); return C.RESULT_BUFFER_READ; } else { @@ -118,15 +134,4 @@ import java.io.IOException; return skipped; } - /** - * Seeks to the specified position in microseconds. - * - * @param positionUs The seek position in microseconds. - */ - public void seekToUs(long positionUs) { - currentIndex = Util.binarySearchCeil(eventTimesUs, positionUs, true, false); - boolean isPendingSeek = eventStreamUpdatable && currentIndex == eventTimesUs.length; - pendingSeekPositionUs = isPendingSeek ? positionUs : C.TIME_UNSET; - } - }