From cfed8791b0fb5698cf8d0b268e7746d1153cfb3a Mon Sep 17 00:00:00 2001 From: tonihei Date: Mon, 15 Jan 2018 07:55:53 -0800 Subject: [PATCH] Send downStreamFormatChanged notification for embedded streams. This allows listeners to get notified of any change to the embedded tracks. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=181969023 --- .../source/chunk/ChunkSampleStream.java | 55 ++++++-- .../source/dash/DashMediaPeriod.java | 127 +++++++++++++----- .../source/smoothstreaming/SsMediaPeriod.java | 12 +- .../testutil/FakeAdaptiveMediaPeriod.java | 11 +- 4 files changed, 154 insertions(+), 51 deletions(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java index b0a2686ef6..e740e6607e 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java @@ -46,6 +46,7 @@ public class ChunkSampleStream implements SampleStream, S public final int primaryTrackType; private final int[] embeddedTrackTypes; + private final Format[] embeddedTrackFormats; private final boolean[] embeddedTracksSelected; private final T chunkSource; private final SequenceableLoader.Callback> callback; @@ -65,9 +66,10 @@ public class ChunkSampleStream implements SampleStream, S /* package */ boolean loadingFinished; /** - * @param primaryTrackType The type of the primary track. One of the {@link C} - * {@code TRACK_TYPE_*} constants. + * @param primaryTrackType The type of the primary track. One of the {@link C} {@code + * TRACK_TYPE_*} constants. * @param embeddedTrackTypes The types of any embedded tracks, or null. + * @param embeddedTrackFormats The formats of the embedded tracks, or null. * @param chunkSource A {@link ChunkSource} from which chunks to load are obtained. * @param callback An {@link Callback} for the stream. * @param allocator An {@link Allocator} from which allocations can be obtained. @@ -76,11 +78,19 @@ public class ChunkSampleStream implements SampleStream, S * before propagating an error. * @param eventDispatcher A dispatcher to notify of events. */ - public ChunkSampleStream(int primaryTrackType, int[] embeddedTrackTypes, T chunkSource, - Callback> callback, Allocator allocator, long positionUs, - int minLoadableRetryCount, EventDispatcher eventDispatcher) { + public ChunkSampleStream( + int primaryTrackType, + int[] embeddedTrackTypes, + Format[] embeddedTrackFormats, + T chunkSource, + Callback> callback, + Allocator allocator, + long positionUs, + int minLoadableRetryCount, + EventDispatcher eventDispatcher) { this.primaryTrackType = primaryTrackType; this.embeddedTrackTypes = embeddedTrackTypes; + this.embeddedTrackFormats = embeddedTrackFormats; this.chunkSource = chunkSource; this.callback = callback; this.eventDispatcher = eventDispatcher; @@ -555,6 +565,8 @@ public class ChunkSampleStream implements SampleStream, S private final SampleQueue sampleQueue; private final int index; + private boolean formatNotificationSent; + public EmbeddedSampleStream(ChunkSampleStream parent, SampleQueue sampleQueue, int index) { this.parent = parent; this.sampleQueue = sampleQueue; @@ -568,12 +580,19 @@ public class ChunkSampleStream implements SampleStream, S @Override public int skipData(long positionUs) { + int skipCount; if (loadingFinished && positionUs > sampleQueue.getLargestQueuedTimestampUs()) { - return sampleQueue.advanceToEnd(); + skipCount = sampleQueue.advanceToEnd(); } else { - int skipCount = sampleQueue.advanceTo(positionUs, true, true); - return skipCount == SampleQueue.ADVANCE_FAILED ? 0 : skipCount; + skipCount = sampleQueue.advanceTo(positionUs, true, true); + if (skipCount == SampleQueue.ADVANCE_FAILED) { + skipCount = 0; + } } + if (skipCount > 0) { + maybeNotifyTrackFormatChanged(); + } + return skipCount; } @Override @@ -587,8 +606,13 @@ public class ChunkSampleStream implements SampleStream, S if (isPendingReset()) { return C.RESULT_NOTHING_READ; } - return sampleQueue.read(formatHolder, buffer, formatRequired, loadingFinished, - lastSeekPositionUs); + int result = + sampleQueue.read( + formatHolder, buffer, formatRequired, loadingFinished, lastSeekPositionUs); + if (result == C.RESULT_BUFFER_READ) { + maybeNotifyTrackFormatChanged(); + } + return result; } public void release() { @@ -596,6 +620,17 @@ public class ChunkSampleStream implements SampleStream, S embeddedTracksSelected[index] = false; } + private void maybeNotifyTrackFormatChanged() { + if (!formatNotificationSent) { + eventDispatcher.downstreamFormatChanged( + embeddedTrackTypes[index], + embeddedTrackFormats[index], + C.SELECTION_REASON_UNKNOWN, + /* trackSelectionData= */ null, + lastSeekPositionUs); + formatNotificationSent = true; + } + } } } 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 8a69f98653..569328c101 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 @@ -436,26 +436,33 @@ import java.util.Map; } AdaptationSet firstAdaptationSet = adaptationSets.get(adaptationSetIndices[0]); - int primaryTrackGroupIndex = trackGroupCount; - boolean hasEventMessageTrack = primaryGroupHasEventMessageTrackFlags[i]; - boolean hasCea608Track = primaryGroupHasCea608TrackFlags[i]; + int primaryTrackGroupIndex = trackGroupCount++; + int eventMessageTrackGroupIndex = + primaryGroupHasEventMessageTrackFlags[i] ? trackGroupCount++ : C.INDEX_UNSET; + int cea608TrackGroupIndex = + primaryGroupHasCea608TrackFlags[i] ? trackGroupCount++ : C.INDEX_UNSET; - trackGroups[trackGroupCount] = new TrackGroup(formats); - trackGroupInfos[trackGroupCount++] = TrackGroupInfo.primaryTrack(firstAdaptationSet.type, - adaptationSetIndices, primaryTrackGroupIndex, hasEventMessageTrack, hasCea608Track); - if (hasEventMessageTrack) { + trackGroups[primaryTrackGroupIndex] = new TrackGroup(formats); + trackGroupInfos[primaryTrackGroupIndex] = + TrackGroupInfo.primaryTrack( + firstAdaptationSet.type, + adaptationSetIndices, + primaryTrackGroupIndex, + eventMessageTrackGroupIndex, + cea608TrackGroupIndex); + if (eventMessageTrackGroupIndex != C.INDEX_UNSET) { Format format = Format.createSampleFormat(firstAdaptationSet.id + ":emsg", MimeTypes.APPLICATION_EMSG, null, Format.NO_VALUE, null); - trackGroups[trackGroupCount] = new TrackGroup(format); - trackGroupInfos[trackGroupCount++] = TrackGroupInfo.embeddedEmsgTrack(adaptationSetIndices, - primaryTrackGroupIndex); + trackGroups[eventMessageTrackGroupIndex] = new TrackGroup(format); + trackGroupInfos[eventMessageTrackGroupIndex] = + TrackGroupInfo.embeddedEmsgTrack(adaptationSetIndices, primaryTrackGroupIndex); } - if (hasCea608Track) { + if (cea608TrackGroupIndex != C.INDEX_UNSET) { Format format = Format.createTextSampleFormat(firstAdaptationSet.id + ":cea608", MimeTypes.APPLICATION_CEA608, 0, null); - trackGroups[trackGroupCount] = new TrackGroup(format); - trackGroupInfos[trackGroupCount++] = TrackGroupInfo.embeddedCea608Track( - adaptationSetIndices, primaryTrackGroupIndex); + trackGroups[cea608TrackGroupIndex] = new TrackGroup(format); + trackGroupInfos[cea608TrackGroupIndex] = + TrackGroupInfo.embeddedCea608Track(adaptationSetIndices, primaryTrackGroupIndex); } } return trackGroupCount; @@ -476,24 +483,39 @@ import java.util.Map; TrackSelection selection, long positionUs) { int embeddedTrackCount = 0; int[] embeddedTrackTypes = new int[2]; - boolean enableEventMessageTrack = trackGroupInfo.hasEmbeddedEventMessageTrack; + Format[] embeddedTrackFormats = new Format[2]; + boolean enableEventMessageTrack = + trackGroupInfo.embeddedEventMessageTrackGroupIndex != C.INDEX_UNSET; if (enableEventMessageTrack) { + embeddedTrackFormats[embeddedTrackCount] = + trackGroups.get(trackGroupInfo.embeddedEventMessageTrackGroupIndex).getFormat(0); embeddedTrackTypes[embeddedTrackCount++] = C.TRACK_TYPE_METADATA; } - boolean enableCea608Track = trackGroupInfo.hasEmbeddedCea608Track; + boolean enableCea608Track = trackGroupInfo.embeddedCea608TrackGroupIndex != C.INDEX_UNSET; if (enableCea608Track) { + embeddedTrackFormats[embeddedTrackCount] = + trackGroups.get(trackGroupInfo.embeddedCea608TrackGroupIndex).getFormat(0); embeddedTrackTypes[embeddedTrackCount++] = C.TRACK_TYPE_TEXT; } if (embeddedTrackCount < embeddedTrackTypes.length) { + embeddedTrackFormats = Arrays.copyOf(embeddedTrackFormats, embeddedTrackCount); embeddedTrackTypes = Arrays.copyOf(embeddedTrackTypes, embeddedTrackCount); } DashChunkSource chunkSource = chunkSourceFactory.createDashChunkSource( manifestLoaderErrorThrower, manifest, periodIndex, trackGroupInfo.adaptationSetIndices, selection, trackGroupInfo.trackType, elapsedRealtimeOffset, enableEventMessageTrack, enableCea608Track); - ChunkSampleStream stream = new ChunkSampleStream<>(trackGroupInfo.trackType, - embeddedTrackTypes, chunkSource, this, allocator, positionUs, minLoadableRetryCount, - eventDispatcher); + ChunkSampleStream stream = + new ChunkSampleStream<>( + trackGroupInfo.trackType, + embeddedTrackTypes, + embeddedTrackFormats, + chunkSource, + this, + allocator, + positionUs, + minLoadableRetryCount, + eventDispatcher); return stream; } @@ -578,43 +600,74 @@ import java.util.Map; public final int eventStreamGroupIndex; public final int primaryTrackGroupIndex; - public final boolean hasEmbeddedEventMessageTrack; - public final boolean hasEmbeddedCea608Track; + public final int embeddedEventMessageTrackGroupIndex; + public final int embeddedCea608TrackGroupIndex; - public static TrackGroupInfo primaryTrack(int trackType, int[] adaptationSetIndices, - int primaryTrackGroupIndex, boolean hasEmbeddedEventMessageTrack, - boolean hasEmbeddedCea608Track) { - return new TrackGroupInfo(trackType, CATEGORY_PRIMARY, adaptationSetIndices, - primaryTrackGroupIndex, hasEmbeddedEventMessageTrack, hasEmbeddedCea608Track, -1); + public static TrackGroupInfo primaryTrack( + int trackType, + int[] adaptationSetIndices, + int primaryTrackGroupIndex, + int embeddedEventMessageTrackGroupIndex, + int embeddedCea608TrackGroupIndex) { + return new TrackGroupInfo( + trackType, + CATEGORY_PRIMARY, + adaptationSetIndices, + primaryTrackGroupIndex, + embeddedEventMessageTrackGroupIndex, + embeddedCea608TrackGroupIndex, + -1); } public static TrackGroupInfo embeddedEmsgTrack(int[] adaptationSetIndices, int primaryTrackGroupIndex) { - return new TrackGroupInfo(C.TRACK_TYPE_METADATA, CATEGORY_EMBEDDED, - adaptationSetIndices, primaryTrackGroupIndex, false, false, -1); + return new TrackGroupInfo( + C.TRACK_TYPE_METADATA, + CATEGORY_EMBEDDED, + adaptationSetIndices, + primaryTrackGroupIndex, + C.INDEX_UNSET, + C.INDEX_UNSET, + -1); } public static TrackGroupInfo embeddedCea608Track(int[] adaptationSetIndices, int primaryTrackGroupIndex) { - return new TrackGroupInfo(C.TRACK_TYPE_TEXT, CATEGORY_EMBEDDED, - adaptationSetIndices, primaryTrackGroupIndex, false, false, -1); + return new TrackGroupInfo( + C.TRACK_TYPE_TEXT, + CATEGORY_EMBEDDED, + adaptationSetIndices, + primaryTrackGroupIndex, + C.INDEX_UNSET, + C.INDEX_UNSET, + -1); } public static TrackGroupInfo mpdEventTrack(int eventStreamIndex) { - return new TrackGroupInfo(C.TRACK_TYPE_METADATA, CATEGORY_MANIFEST_EVENTS, - null, -1, false, false, eventStreamIndex); + return new TrackGroupInfo( + C.TRACK_TYPE_METADATA, + CATEGORY_MANIFEST_EVENTS, + null, + -1, + C.INDEX_UNSET, + C.INDEX_UNSET, + eventStreamIndex); } - private TrackGroupInfo(int trackType, @TrackGroupCategory int trackGroupCategory, - int[] adaptationSetIndices, int primaryTrackGroupIndex, - boolean hasEmbeddedEventMessageTrack, boolean hasEmbeddedCea608Track, + private TrackGroupInfo( + int trackType, + @TrackGroupCategory int trackGroupCategory, + int[] adaptationSetIndices, + int primaryTrackGroupIndex, + int embeddedEventMessageTrackGroupIndex, + int embeddedCea608TrackGroupIndex, int eventStreamGroupIndex) { this.trackType = trackType; this.adaptationSetIndices = adaptationSetIndices; this.trackGroupCategory = trackGroupCategory; this.primaryTrackGroupIndex = primaryTrackGroupIndex; - this.hasEmbeddedEventMessageTrack = hasEmbeddedEventMessageTrack; - this.hasEmbeddedCea608Track = hasEmbeddedCea608Track; + this.embeddedEventMessageTrackGroupIndex = embeddedEventMessageTrackGroupIndex; + this.embeddedCea608TrackGroupIndex = embeddedCea608TrackGroupIndex; this.eventStreamGroupIndex = eventStreamGroupIndex; } } diff --git a/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriod.java b/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriod.java index 99804ca809..a600741362 100644 --- a/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriod.java +++ b/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriod.java @@ -207,8 +207,16 @@ import java.util.ArrayList; int streamElementIndex = trackGroups.indexOf(selection.getTrackGroup()); SsChunkSource chunkSource = chunkSourceFactory.createChunkSource(manifestLoaderErrorThrower, manifest, streamElementIndex, selection, trackEncryptionBoxes); - return new ChunkSampleStream<>(manifest.streamElements[streamElementIndex].type, null, - chunkSource, this, allocator, positionUs, minLoadableRetryCount, eventDispatcher); + return new ChunkSampleStream<>( + manifest.streamElements[streamElementIndex].type, + null, + null, + chunkSource, + this, + allocator, + positionUs, + minLoadableRetryCount, + eventDispatcher); } private static TrackGroupArray buildTrackGroups(SsManifest manifest) { diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeAdaptiveMediaPeriod.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeAdaptiveMediaPeriod.java index 7b9fe3db07..d32dda65f4 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeAdaptiveMediaPeriod.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeAdaptiveMediaPeriod.java @@ -132,8 +132,15 @@ public class FakeAdaptiveMediaPeriod extends FakeMediaPeriod protected SampleStream createSampleStream(TrackSelection trackSelection) { FakeChunkSource chunkSource = chunkSourceFactory.createChunkSource(trackSelection, durationUs); return new ChunkSampleStream<>( - MimeTypes.getTrackType(trackSelection.getSelectedFormat().sampleMimeType), null, - chunkSource, this, allocator, 0, 3, eventDispatcher); + MimeTypes.getTrackType(trackSelection.getSelectedFormat().sampleMimeType), + null, + null, + chunkSource, + this, + allocator, + 0, + 3, + eventDispatcher); } @Override