From 8db1331021c46a6357a70ebc6f68b59ccbcff3c0 Mon Sep 17 00:00:00 2001 From: Oliver Woodman Date: Tue, 11 Aug 2015 18:23:22 +0100 Subject: [PATCH] Propagate MediaFormat instead of TrackInfo. Issue #514. --- .../ext/opus/LibopusAudioTrackRenderer.java | 8 ++-- .../ext/vp9/LibvpxVideoTrackRenderer.java | 8 ++-- .../android/exoplayer/MediaFormatTest.java | 4 +- .../exoplayer/dash/DashChunkSourceTest.java | 16 +++---- .../android/exoplayer/DummyTrackRenderer.java | 2 +- .../android/exoplayer/ExoPlayerImpl.java | 15 +++--- .../exoplayer/ExoPlayerImplInternal.java | 18 ++++---- .../exoplayer/FrameworkSampleSource.java | 19 ++++---- .../MediaCodecAudioTrackRenderer.java | 5 +- .../MediaCodecVideoTrackRenderer.java | 5 +- .../google/android/exoplayer/MediaFormat.java | 38 ++++++--------- .../android/exoplayer/SampleSource.java | 13 +++--- .../exoplayer/SampleSourceTrackRenderer.java | 20 ++++---- .../android/exoplayer/SingleSampleSource.java | 35 +++++++++----- .../google/android/exoplayer/TrackInfo.java | 46 ------------------- .../android/exoplayer/TrackRenderer.java | 8 ++-- .../exoplayer/chunk/ChunkSampleSource.java | 9 ++-- .../android/exoplayer/chunk/ChunkSource.java | 20 ++++---- .../chunk/MultiTrackChunkSource.java | 9 ++-- .../chunk/SingleSampleChunkSource.java | 11 ++--- .../exoplayer/dash/DashChunkSource.java | 18 ++++---- .../extractor/ExtractorSampleSource.java | 11 ++--- .../android/exoplayer/hls/HlsChunkSource.java | 20 ++++---- .../exoplayer/hls/HlsSampleSource.java | 12 ++--- .../metadata/MetadataTrackRenderer.java | 6 +-- .../SmoothStreamingChunkSource.java | 19 ++++---- .../exoplayer/text/TextTrackRenderer.java | 12 ++--- .../text/eia608/Eia608TrackRenderer.java | 6 +-- 28 files changed, 178 insertions(+), 235 deletions(-) delete mode 100644 library/src/main/java/com/google/android/exoplayer/TrackInfo.java diff --git a/extensions/opus/src/main/java/com/google/android/exoplayer/ext/opus/LibopusAudioTrackRenderer.java b/extensions/opus/src/main/java/com/google/android/exoplayer/ext/opus/LibopusAudioTrackRenderer.java index 35d6278a17..3a71a67536 100644 --- a/extensions/opus/src/main/java/com/google/android/exoplayer/ext/opus/LibopusAudioTrackRenderer.java +++ b/extensions/opus/src/main/java/com/google/android/exoplayer/ext/opus/LibopusAudioTrackRenderer.java @@ -22,7 +22,6 @@ import com.google.android.exoplayer.MediaFormat; import com.google.android.exoplayer.MediaFormatHolder; import com.google.android.exoplayer.SampleSource; import com.google.android.exoplayer.SampleSourceTrackRenderer; -import com.google.android.exoplayer.TrackInfo; import com.google.android.exoplayer.TrackRenderer; import com.google.android.exoplayer.audio.AudioTrack; import com.google.android.exoplayer.ext.opus.OpusDecoderWrapper.InputBuffer; @@ -125,9 +124,10 @@ public final class LibopusAudioTrackRenderer extends SampleSourceTrackRenderer } @Override - protected boolean handlesTrack(TrackInfo trackInfo) { - return MimeTypes.AUDIO_OPUS.equalsIgnoreCase(trackInfo.mimeType) - || MimeTypes.AUDIO_WEBM.equalsIgnoreCase(trackInfo.mimeType); + protected boolean handlesTrack(MediaFormat mediaFormat) { + // TODO: Stop claiming to handle the WebM mime type (b/22996976). + return MimeTypes.AUDIO_OPUS.equalsIgnoreCase(mediaFormat.mimeType) + || MimeTypes.AUDIO_WEBM.equalsIgnoreCase(mediaFormat.mimeType); } @Override diff --git a/extensions/vp9/src/main/java/com/google/android/exoplayer/ext/vp9/LibvpxVideoTrackRenderer.java b/extensions/vp9/src/main/java/com/google/android/exoplayer/ext/vp9/LibvpxVideoTrackRenderer.java index 1ea758b6a1..fd64defd69 100644 --- a/extensions/vp9/src/main/java/com/google/android/exoplayer/ext/vp9/LibvpxVideoTrackRenderer.java +++ b/extensions/vp9/src/main/java/com/google/android/exoplayer/ext/vp9/LibvpxVideoTrackRenderer.java @@ -21,7 +21,6 @@ import com.google.android.exoplayer.MediaFormat; import com.google.android.exoplayer.MediaFormatHolder; import com.google.android.exoplayer.SampleSource; import com.google.android.exoplayer.SampleSourceTrackRenderer; -import com.google.android.exoplayer.TrackInfo; import com.google.android.exoplayer.TrackRenderer; import com.google.android.exoplayer.ext.vp9.VpxDecoderWrapper.InputBuffer; import com.google.android.exoplayer.ext.vp9.VpxDecoderWrapper.OutputBuffer; @@ -149,9 +148,10 @@ public final class LibvpxVideoTrackRenderer extends SampleSourceTrackRenderer { } @Override - protected boolean handlesTrack(TrackInfo trackInfo) { - return MimeTypes.VIDEO_VP9.equalsIgnoreCase(trackInfo.mimeType) - || MimeTypes.VIDEO_WEBM.equalsIgnoreCase(trackInfo.mimeType); + protected boolean handlesTrack(MediaFormat mediaFormat) { + // TODO: Stop claiming to handle the WebM mime type (b/22996976). + return MimeTypes.VIDEO_VP9.equalsIgnoreCase(mediaFormat.mimeType) + || MimeTypes.VIDEO_WEBM.equalsIgnoreCase(mediaFormat.mimeType); } @Override diff --git a/library/src/androidTest/java/com/google/android/exoplayer/MediaFormatTest.java b/library/src/androidTest/java/com/google/android/exoplayer/MediaFormatTest.java index 4c82d2fe6d..ffd2f7baa2 100644 --- a/library/src/androidTest/java/com/google/android/exoplayer/MediaFormatTest.java +++ b/library/src/androidTest/java/com/google/android/exoplayer/MediaFormatTest.java @@ -69,8 +69,8 @@ public final class MediaFormatTest extends TestCase { assertOptionalV16(out, android.media.MediaFormat.KEY_HEIGHT, in.height); assertOptionalV16(out, android.media.MediaFormat.KEY_CHANNEL_COUNT, in.channelCount); assertOptionalV16(out, android.media.MediaFormat.KEY_SAMPLE_RATE, in.sampleRate); - assertOptionalV16(out, android.media.MediaFormat.KEY_MAX_WIDTH, in.getMaxVideoWidth()); - assertOptionalV16(out, android.media.MediaFormat.KEY_MAX_HEIGHT, in.getMaxVideoHeight()); + assertOptionalV16(out, android.media.MediaFormat.KEY_MAX_WIDTH, in.maxWidth); + assertOptionalV16(out, android.media.MediaFormat.KEY_MAX_HEIGHT, in.maxHeight); for (int i = 0; i < in.initializationData.size(); i++) { byte[] originalData = in.initializationData.get(i); ByteBuffer frameworkBuffer = out.getByteBuffer("csd-" + i); diff --git a/library/src/androidTest/java/com/google/android/exoplayer/dash/DashChunkSourceTest.java b/library/src/androidTest/java/com/google/android/exoplayer/dash/DashChunkSourceTest.java index db387c179a..a1f329481e 100644 --- a/library/src/androidTest/java/com/google/android/exoplayer/dash/DashChunkSourceTest.java +++ b/library/src/androidTest/java/com/google/android/exoplayer/dash/DashChunkSourceTest.java @@ -91,11 +91,11 @@ public class DashChunkSourceTest extends InstrumentationTestCase { public void testMaxVideoDimensions() { DashChunkSource chunkSource = new DashChunkSource(generateVodMpd(), AdaptationSet.TYPE_VIDEO, null, null, null); - MediaFormat out = MediaFormat.createVideoFormat("video/h264", 1, 1, 1, 1, null); - chunkSource.getMaxVideoDimensions(out); + MediaFormat format = MediaFormat.createVideoFormat("video/h264", 1, 1, 1, 1, null); + format = chunkSource.getWithMaxVideoDimensions(format); - assertEquals(WIDE_WIDTH, out.getMaxVideoWidth()); - assertEquals(TALL_HEIGHT, out.getMaxVideoHeight()); + assertEquals(WIDE_WIDTH, format.maxWidth); + assertEquals(TALL_HEIGHT, format.maxHeight); } public void testGetSeekRangeOnVod() { @@ -121,11 +121,11 @@ public class DashChunkSourceTest extends InstrumentationTestCase { Representation.newInstance(0, 0, null, 0, WIDE_VIDEO, segmentBase2); DashChunkSource chunkSource = new DashChunkSource(null, null, representation1, representation2); - MediaFormat out = MediaFormat.createVideoFormat("video/h264", 1, 1, 1, 1, null); - chunkSource.getMaxVideoDimensions(out); + MediaFormat format = MediaFormat.createVideoFormat("video/h264", 1, 1, 1, 1, null); + format = chunkSource.getWithMaxVideoDimensions(format); - assertEquals(WIDE_WIDTH, out.getMaxVideoWidth()); - assertEquals(TALL_HEIGHT, out.getMaxVideoHeight()); + assertEquals(WIDE_WIDTH, format.maxWidth); + assertEquals(TALL_HEIGHT, format.maxHeight); } public void testLiveEdgeNoLatency() { diff --git a/library/src/main/java/com/google/android/exoplayer/DummyTrackRenderer.java b/library/src/main/java/com/google/android/exoplayer/DummyTrackRenderer.java index fd36939093..c1e91b2904 100644 --- a/library/src/main/java/com/google/android/exoplayer/DummyTrackRenderer.java +++ b/library/src/main/java/com/google/android/exoplayer/DummyTrackRenderer.java @@ -35,7 +35,7 @@ public final class DummyTrackRenderer extends TrackRenderer { } @Override - protected TrackInfo getTrackInfo(int track) { + protected MediaFormat getFormat(int track) { throw new IllegalStateException(); } diff --git a/library/src/main/java/com/google/android/exoplayer/ExoPlayerImpl.java b/library/src/main/java/com/google/android/exoplayer/ExoPlayerImpl.java index 2823cc7f31..7cac863dfa 100644 --- a/library/src/main/java/com/google/android/exoplayer/ExoPlayerImpl.java +++ b/library/src/main/java/com/google/android/exoplayer/ExoPlayerImpl.java @@ -34,7 +34,7 @@ import java.util.concurrent.CopyOnWriteArraySet; private final Handler eventHandler; private final ExoPlayerImplInternal internalPlayer; private final CopyOnWriteArraySet listeners; - private final TrackInfo[][] trackInfos; + private final MediaFormat[][] trackFormats; private final int[] selectedTrackIndices; private boolean playWhenReady; @@ -58,7 +58,7 @@ import java.util.concurrent.CopyOnWriteArraySet; this.playWhenReady = false; this.playbackState = STATE_IDLE; this.listeners = new CopyOnWriteArraySet<>(); - this.trackInfos = new TrackInfo[rendererCount][]; + this.trackFormats = new MediaFormat[rendererCount][]; this.selectedTrackIndices = new int[rendererCount]; eventHandler = new Handler() { @Override @@ -92,7 +92,7 @@ import java.util.concurrent.CopyOnWriteArraySet; @Override public void prepare(TrackRenderer... renderers) { - Arrays.fill(trackInfos, null); + Arrays.fill(trackFormats, null); internalPlayer.prepare(renderers); } @@ -116,12 +116,12 @@ import java.util.concurrent.CopyOnWriteArraySet; // TODO: Expose in ExoPlayer. public int getRendererTrackCount(int rendererIndex) { - return trackInfos[rendererIndex] != null ? trackInfos[rendererIndex].length : 0; + return trackFormats[rendererIndex] != null ? trackFormats[rendererIndex].length : 0; } // TODO: Expose in ExoPlayer. - public TrackInfo getRendererTrackInfo(int rendererIndex, int trackIndex) { - return trackInfos[rendererIndex][trackIndex]; + public MediaFormat getRendererTrackInfo(int rendererIndex, int trackIndex) { + return trackFormats[rendererIndex][trackIndex]; } // TODO: Expose in ExoPlayer. @@ -212,8 +212,7 @@ import java.util.concurrent.CopyOnWriteArraySet; /* package */ void handleEvent(Message msg) { switch (msg.what) { case ExoPlayerImplInternal.MSG_PREPARED: { - TrackInfo[][] trackInfos = (TrackInfo[][]) msg.obj; - System.arraycopy(trackInfos, 0, this.trackInfos, 0, trackInfos.length); + System.arraycopy(msg.obj, 0, trackFormats, 0, trackFormats.length); playbackState = msg.arg1; for (Listener listener : listeners) { listener.onPlayerStateChanged(playWhenReady, playbackState); diff --git a/library/src/main/java/com/google/android/exoplayer/ExoPlayerImplInternal.java b/library/src/main/java/com/google/android/exoplayer/ExoPlayerImplInternal.java index b87a16b165..45e06c1546 100644 --- a/library/src/main/java/com/google/android/exoplayer/ExoPlayerImplInternal.java +++ b/library/src/main/java/com/google/android/exoplayer/ExoPlayerImplInternal.java @@ -67,7 +67,7 @@ import java.util.List; private final Handler eventHandler; private final StandaloneMediaClock standaloneMediaClock; private final List enabledRenderers; - private final TrackInfo[][] trackInfos; + private final MediaFormat[][] trackFormats; private final int[] selectedTrackIndices; private final long minBufferUs; private final long minRebufferUs; @@ -101,7 +101,7 @@ import java.util.List; standaloneMediaClock = new StandaloneMediaClock(); enabledRenderers = new ArrayList<>(selectedTrackIndices.length); - trackInfos = new TrackInfo[selectedTrackIndices.length][]; + trackFormats = new MediaFormat[selectedTrackIndices.length][]; // Note: The documentation for Process.THREAD_PRIORITY_AUDIO that states "Applications can // not normally change to this priority" is incorrect. internalPlaybackThread = new PriorityHandlerThread(getClass().getSimpleName() + ":Handler", @@ -253,7 +253,7 @@ import java.util.List; private void prepareInternal(TrackRenderer[] renderers) throws ExoPlaybackException { resetInternal(); this.renderers = renderers; - Arrays.fill(trackInfos, null); + Arrays.fill(trackFormats, null); for (int i = 0; i < renderers.length; i++) { MediaClock mediaClock = renderers[i].getMediaClock(); if (mediaClock != null) { @@ -292,11 +292,11 @@ import java.util.List; for (int rendererIndex = 0; rendererIndex < renderers.length; rendererIndex++) { TrackRenderer renderer = renderers[rendererIndex]; int rendererTrackCount = renderer.getTrackCount(); - TrackInfo[] rendererTrackInfos = new TrackInfo[rendererTrackCount]; + MediaFormat[] rendererTrackFormats = new MediaFormat[rendererTrackCount]; for (int trackIndex = 0; trackIndex < rendererTrackCount; trackIndex++) { - rendererTrackInfos[trackIndex] = renderer.getTrackInfo(trackIndex); + rendererTrackFormats[trackIndex] = renderer.getFormat(trackIndex); } - trackInfos[rendererIndex] = rendererTrackInfos; + trackFormats[rendererIndex] = rendererTrackFormats; if (rendererTrackCount > 0) { if (durationUs == TrackRenderer.UNKNOWN_TIME_US) { // We've already encountered a track for which the duration is unknown, so the media @@ -312,7 +312,7 @@ import java.util.List; } } int trackIndex = selectedTrackIndices[rendererIndex]; - if (0 <= trackIndex && trackIndex < rendererTrackInfos.length) { + if (0 <= trackIndex && trackIndex < rendererTrackFormats.length) { renderer.enable(trackIndex, positionUs, false); enabledRenderers.add(renderer); allRenderersEnded = allRenderersEnded && renderer.isEnded(); @@ -332,7 +332,7 @@ import java.util.List; // Fire an event indicating that the player has been prepared, passing the initial state and // renderer track information. - eventHandler.obtainMessage(MSG_PREPARED, state, 0, trackInfos).sendToTarget(); + eventHandler.obtainMessage(MSG_PREPARED, state, 0, trackFormats).sendToTarget(); // Start the renderers if required, and schedule the first piece of work. if (playWhenReady && state == ExoPlayer.STATE_READY) { @@ -610,7 +610,7 @@ import java.util.List; boolean isEnabled = rendererState == TrackRenderer.STATE_ENABLED || rendererState == TrackRenderer.STATE_STARTED; - boolean shouldEnable = 0 <= trackIndex && trackIndex < trackInfos[rendererIndex].length; + boolean shouldEnable = 0 <= trackIndex && trackIndex < trackFormats[rendererIndex].length; if (isEnabled) { // The renderer is currently enabled. We need to disable it, so that we can either re-enable diff --git a/library/src/main/java/com/google/android/exoplayer/FrameworkSampleSource.java b/library/src/main/java/com/google/android/exoplayer/FrameworkSampleSource.java index 7116006bde..103747ae1d 100644 --- a/library/src/main/java/com/google/android/exoplayer/FrameworkSampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/FrameworkSampleSource.java @@ -73,7 +73,7 @@ public final class FrameworkSampleSource implements SampleSource, SampleSourceRe private IOException preparationError; private MediaExtractor extractor; - private TrackInfo[] trackInfos; + private MediaFormat[] trackFormats; private boolean prepared; private int remainingReleaseCount; private int[] trackStates; @@ -144,13 +144,9 @@ public final class FrameworkSampleSource implements SampleSource, SampleSourceRe trackStates = new int[extractor.getTrackCount()]; pendingDiscontinuities = new boolean[trackStates.length]; - trackInfos = new TrackInfo[trackStates.length]; + trackFormats = new MediaFormat[trackStates.length]; for (int i = 0; i < trackStates.length; i++) { - android.media.MediaFormat format = extractor.getTrackFormat(i); - long durationUs = format.containsKey(android.media.MediaFormat.KEY_DURATION) - ? format.getLong(android.media.MediaFormat.KEY_DURATION) : C.UNKNOWN_TIME_US; - String mime = format.getString(android.media.MediaFormat.KEY_MIME); - trackInfos[i] = new TrackInfo(mime, durationUs); + trackFormats[i] = createMediaFormat(extractor.getTrackFormat(i)); } prepared = true; } @@ -164,9 +160,9 @@ public final class FrameworkSampleSource implements SampleSource, SampleSourceRe } @Override - public TrackInfo getTrackInfo(int track) { + public MediaFormat getFormat(int track) { Assertions.checkState(prepared); - return trackInfos[track]; + return trackFormats[track]; } @Override @@ -200,7 +196,7 @@ public final class FrameworkSampleSource implements SampleSource, SampleSourceRe return NOTHING_READ; } if (trackStates[track] != TRACK_STATE_FORMAT_SENT) { - formatHolder.format = createMediaFormat(extractor.getTrackFormat(track)); + formatHolder.format = trackFormats[track]; formatHolder.drmInitData = Util.SDK_INT >= 18 ? getDrmInitDataV18() : null; trackStates[track] = TRACK_STATE_FORMAT_SENT; return FORMAT_READ; @@ -319,7 +315,8 @@ public final class FrameworkSampleSource implements SampleSource, SampleSourceRe long durationUs = format.containsKey(android.media.MediaFormat.KEY_DURATION) ? format.getLong(android.media.MediaFormat.KEY_DURATION) : C.UNKNOWN_TIME_US; return new MediaFormat(mimeType, maxInputSize, durationUs, width, height, MediaFormat.NO_VALUE, - channelCount, sampleRate, language, initializationData); + channelCount, sampleRate, language, initializationData, MediaFormat.NO_VALUE, + MediaFormat.NO_VALUE); } @TargetApi(16) diff --git a/library/src/main/java/com/google/android/exoplayer/MediaCodecAudioTrackRenderer.java b/library/src/main/java/com/google/android/exoplayer/MediaCodecAudioTrackRenderer.java index f6a67b2c38..d377746f25 100644 --- a/library/src/main/java/com/google/android/exoplayer/MediaCodecAudioTrackRenderer.java +++ b/library/src/main/java/com/google/android/exoplayer/MediaCodecAudioTrackRenderer.java @@ -193,8 +193,9 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer implem } @Override - protected boolean handlesTrack(TrackInfo trackInfo) { - return MimeTypes.isAudio(trackInfo.mimeType); + protected boolean handlesTrack(MediaFormat mediaFormat) { + // TODO: Check the mime type against the available decoders (b/22996976). + return MimeTypes.isAudio(mediaFormat.mimeType); } @Override diff --git a/library/src/main/java/com/google/android/exoplayer/MediaCodecVideoTrackRenderer.java b/library/src/main/java/com/google/android/exoplayer/MediaCodecVideoTrackRenderer.java index a9da5cf9d9..eba2e4985c 100644 --- a/library/src/main/java/com/google/android/exoplayer/MediaCodecVideoTrackRenderer.java +++ b/library/src/main/java/com/google/android/exoplayer/MediaCodecVideoTrackRenderer.java @@ -256,8 +256,9 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer { } @Override - protected boolean handlesTrack(TrackInfo trackInfo) { - return MimeTypes.isVideo(trackInfo.mimeType); + protected boolean handlesTrack(MediaFormat mediaFormat) { + // TODO: Check the mime type against the available decoders (b/22996976). + return MimeTypes.isVideo(mediaFormat.mimeType); } @Override diff --git a/library/src/main/java/com/google/android/exoplayer/MediaFormat.java b/library/src/main/java/com/google/android/exoplayer/MediaFormat.java index 5a5dff8fda..cea777eadf 100644 --- a/library/src/main/java/com/google/android/exoplayer/MediaFormat.java +++ b/library/src/main/java/com/google/android/exoplayer/MediaFormat.java @@ -35,6 +35,11 @@ public final class MediaFormat { public final String mimeType; public final int maxInputSize; + /** + * The duration in microseconds, or {@link C#UNKNOWN_TIME_US} if the duration is unknown, or + * {@link C#MATCH_LONGEST_US} if the duration should match the duration of the longest track whose + * duration is known. + */ public final long durationUs; public final int width; @@ -48,8 +53,8 @@ public final class MediaFormat { public final List initializationData; - private int maxWidth; - private int maxHeight; + public final int maxWidth; + public final int maxHeight; // Lazy-initialized hashcode. private int hashCode; @@ -71,7 +76,7 @@ public final class MediaFormat { public static MediaFormat createVideoFormat(String mimeType, int maxInputSize, long durationUs, int width, int height, float pixelWidthHeightRatio, List initializationData) { return new MediaFormat(mimeType, maxInputSize, durationUs, width, height, pixelWidthHeightRatio, - NO_VALUE, NO_VALUE, null, initializationData); + NO_VALUE, NO_VALUE, null, initializationData, NO_VALUE, NO_VALUE); } public static MediaFormat createAudioFormat(String mimeType, int maxInputSize, int channelCount, @@ -83,7 +88,7 @@ public final class MediaFormat { public static MediaFormat createAudioFormat(String mimeType, int maxInputSize, long durationUs, int channelCount, int sampleRate, List initializationData) { return new MediaFormat(mimeType, maxInputSize, durationUs, NO_VALUE, NO_VALUE, NO_VALUE, - channelCount, sampleRate, null, initializationData); + channelCount, sampleRate, null, initializationData, NO_VALUE, NO_VALUE); } public static MediaFormat createTextFormat(String mimeType, String language) { @@ -92,7 +97,7 @@ public final class MediaFormat { public static MediaFormat createTextFormat(String mimeType, String language, long durationUs) { return new MediaFormat(mimeType, NO_VALUE, durationUs, NO_VALUE, NO_VALUE, NO_VALUE, - NO_VALUE, NO_VALUE, language, null); + NO_VALUE, NO_VALUE, language, null, NO_VALUE, NO_VALUE); } public static MediaFormat createFormatForMimeType(String mimeType) { @@ -101,12 +106,12 @@ public final class MediaFormat { public static MediaFormat createFormatForMimeType(String mimeType, long durationUs) { return new MediaFormat(mimeType, NO_VALUE, durationUs, NO_VALUE, NO_VALUE, NO_VALUE, - NO_VALUE, NO_VALUE, null, null); + NO_VALUE, NO_VALUE, null, null, NO_VALUE, NO_VALUE); } /* package */ MediaFormat(String mimeType, int maxInputSize, long durationUs, int width, int height, float pixelWidthHeightRatio, int channelCount, int sampleRate, String language, - List initializationData) { + List initializationData, int maxWidth, int maxHeight) { this.mimeType = mimeType; this.maxInputSize = maxInputSize; this.durationUs = durationUs; @@ -118,26 +123,13 @@ public final class MediaFormat { this.language = language; this.initializationData = initializationData == null ? Collections.emptyList() : initializationData; - maxWidth = NO_VALUE; - maxHeight = NO_VALUE; - } - - @SuppressLint("InlinedApi") - public void setMaxVideoDimensions(int maxWidth, int maxHeight) { this.maxWidth = maxWidth; this.maxHeight = maxHeight; - if (frameworkMediaFormat != null) { - maybeSetIntegerV16(frameworkMediaFormat, android.media.MediaFormat.KEY_MAX_WIDTH, maxWidth); - maybeSetIntegerV16(frameworkMediaFormat, android.media.MediaFormat.KEY_MAX_HEIGHT, maxHeight); - } } - public int getMaxVideoWidth() { - return maxWidth; - } - - public int getMaxVideoHeight() { - return maxHeight; + public MediaFormat copyWithMaxVideoDimension(int maxWidth, int maxHeight) { + return new MediaFormat(mimeType, maxInputSize, durationUs, width, height, pixelWidthHeightRatio, + channelCount, sampleRate, language, initializationData, maxWidth, maxHeight); } /** diff --git a/library/src/main/java/com/google/android/exoplayer/SampleSource.java b/library/src/main/java/com/google/android/exoplayer/SampleSource.java index 539983d200..b33d18c5cb 100644 --- a/library/src/main/java/com/google/android/exoplayer/SampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/SampleSource.java @@ -20,9 +20,9 @@ import java.io.IOException; /** * A source of media samples. *

- * A {@link SampleSource} may expose one or multiple tracks. The number of tracks and information - * about each can be queried using {@link SampleSourceReader#getTrackCount()} and - * {@link SampleSourceReader#getTrackInfo(int)} respectively. + * A {@link SampleSource} may expose one or multiple tracks. The number of tracks and each track's + * media format can be queried using {@link SampleSourceReader#getTrackCount()} and + * {@link SampleSourceReader#getFormat(int)} respectively. */ public interface SampleSource { @@ -87,13 +87,14 @@ public interface SampleSource { public int getTrackCount(); /** - * Returns information about the specified track. + * Returns the format of the specified track. *

* This method should not be called until after the source has been successfully prepared. * - * @return Information about the specified track. + * @param track The track index. + * @return The format of the specified track. */ - public TrackInfo getTrackInfo(int track); + public MediaFormat getFormat(int track); /** * Enable the specified track. This allows the track's format and samples to be read from diff --git a/library/src/main/java/com/google/android/exoplayer/SampleSourceTrackRenderer.java b/library/src/main/java/com/google/android/exoplayer/SampleSourceTrackRenderer.java index f2372df618..edf99ba2bb 100644 --- a/library/src/main/java/com/google/android/exoplayer/SampleSourceTrackRenderer.java +++ b/library/src/main/java/com/google/android/exoplayer/SampleSourceTrackRenderer.java @@ -30,7 +30,6 @@ public abstract class SampleSourceTrackRenderer extends TrackRenderer { private int enabledSourceTrackIndex; private int[] handledSourceTrackIndices; - private TrackInfo[] trackInfos; /** * @param source The upstream source from which the renderer obtains samples. @@ -48,27 +47,24 @@ public abstract class SampleSourceTrackRenderer extends TrackRenderer { int handledTrackCount = 0; int sourceTrackCount = source.getTrackCount(); int[] trackIndices = new int[sourceTrackCount]; - TrackInfo[] trackInfos = new TrackInfo[sourceTrackCount]; for (int trackIndex = 0; trackIndex < sourceTrackCount; trackIndex++) { - TrackInfo trackInfo = source.getTrackInfo(trackIndex); - if (handlesTrack(trackInfo)) { + MediaFormat format = source.getFormat(trackIndex); + if (handlesTrack(format)) { trackIndices[handledTrackCount] = trackIndex; - trackInfos[handledTrackCount] = trackInfo; handledTrackCount++; } } this.handledSourceTrackIndices = Arrays.copyOf(trackIndices, handledTrackCount); - this.trackInfos = Arrays.copyOf(trackInfos, handledTrackCount); return true; } /** * Returns whether this renderer is capable of handling the provided track. * - * @param trackInfo The track. + * @param mediaFormat The track. * @return True if the renderer can handle the track, false otherwise. */ - protected abstract boolean handlesTrack(TrackInfo trackInfo); + protected abstract boolean handlesTrack(MediaFormat mediaFormat); @Override protected void onEnabled(int track, long positionUs, boolean joining) @@ -89,7 +85,7 @@ public abstract class SampleSourceTrackRenderer extends TrackRenderer { @Override protected long getDurationUs() { - return source.getTrackInfo(enabledSourceTrackIndex).durationUs; + return source.getFormat(enabledSourceTrackIndex).durationUs; } @Override @@ -123,12 +119,12 @@ public abstract class SampleSourceTrackRenderer extends TrackRenderer { @Override protected final int getTrackCount() { - return trackInfos.length; + return handledSourceTrackIndices.length; } @Override - protected final TrackInfo getTrackInfo(int track) { - return trackInfos[track]; + protected final MediaFormat getFormat(int track) { + return source.getFormat(handledSourceTrackIndices[track]); } } diff --git a/library/src/main/java/com/google/android/exoplayer/SingleSampleSource.java b/library/src/main/java/com/google/android/exoplayer/SingleSampleSource.java index 36b44ced1c..c16d0474bb 100644 --- a/library/src/main/java/com/google/android/exoplayer/SingleSampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/SingleSampleSource.java @@ -20,6 +20,7 @@ import com.google.android.exoplayer.upstream.DataSource; import com.google.android.exoplayer.upstream.DataSpec; import com.google.android.exoplayer.upstream.Loader; import com.google.android.exoplayer.upstream.Loader.Loadable; +import com.google.android.exoplayer.util.Assertions; import android.net.Uri; import android.os.SystemClock; @@ -43,15 +44,18 @@ public final class SingleSampleSource implements SampleSource, SampleSourceReade */ private static final int INITIAL_SAMPLE_SIZE = 1; + private static final int STATE_SEND_FORMAT = 0; + private static final int STATE_SEND_SAMPLE = 1; + private static final int STATE_END_OF_STREAM = 2; + private final Uri uri; private final DataSource dataSource; private final MediaFormat format; - private final TrackInfo trackInfo; private final int minLoadableRetryCount; + private int state; private byte[] sampleData; private int sampleSize; - private boolean pendingSample; private boolean loadingFinished; private Loader loader; @@ -69,7 +73,6 @@ public final class SingleSampleSource implements SampleSource, SampleSourceReade this.dataSource = dataSource; this.format = format; this.minLoadableRetryCount = minLoadableRetryCount; - trackInfo = new TrackInfo(format.mimeType, format.durationUs); sampleData = new byte[INITIAL_SAMPLE_SIZE]; } @@ -92,13 +95,13 @@ public final class SingleSampleSource implements SampleSource, SampleSourceReade } @Override - public TrackInfo getTrackInfo(int track) { - return trackInfo; + public MediaFormat getFormat(int track) { + return format; } @Override public void enable(int track, long positionUs) { - pendingSample = true; + state = STATE_SEND_FORMAT; clearCurrentLoadableException(); maybeStartLoading(); } @@ -121,9 +124,16 @@ public final class SingleSampleSource implements SampleSource, SampleSourceReade SampleHolder sampleHolder, boolean onlyReadDiscontinuity) { if (onlyReadDiscontinuity) { return NOTHING_READ; - } else if (!pendingSample) { + } else if (state == STATE_END_OF_STREAM) { return END_OF_STREAM; - } else if (!loadingFinished) { + } else if (state == STATE_SEND_FORMAT) { + formatHolder.format = format; + state = STATE_SEND_SAMPLE; + return FORMAT_READ; + } + + Assertions.checkState(state == STATE_SEND_SAMPLE); + if (!loadingFinished) { return NOTHING_READ; } else { sampleHolder.timeUs = 0; @@ -133,13 +143,16 @@ public final class SingleSampleSource implements SampleSource, SampleSourceReade sampleHolder.replaceBuffer(sampleHolder.size); } sampleHolder.data.put(sampleData, 0, sampleSize); + state = STATE_END_OF_STREAM; return SAMPLE_READ; } } @Override public void seekToUs(long positionUs) { - pendingSample = true; + if (state == STATE_END_OF_STREAM) { + state = STATE_SEND_SAMPLE; + } } @Override @@ -149,7 +162,7 @@ public final class SingleSampleSource implements SampleSource, SampleSourceReade @Override public void disable(int track) { - pendingSample = false; + state = STATE_END_OF_STREAM; } @Override @@ -163,7 +176,7 @@ public final class SingleSampleSource implements SampleSource, SampleSourceReade // Private methods. private void maybeStartLoading() { - if (loadingFinished || !pendingSample || loader.isLoading()) { + if (loadingFinished || state != STATE_END_OF_STREAM || loader.isLoading()) { return; } if (currentLoadableException != null) { diff --git a/library/src/main/java/com/google/android/exoplayer/TrackInfo.java b/library/src/main/java/com/google/android/exoplayer/TrackInfo.java deleted file mode 100644 index f0ac31ac22..0000000000 --- a/library/src/main/java/com/google/android/exoplayer/TrackInfo.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.android.exoplayer; - -/** - * Holds high level information about a media track. - */ -public final class TrackInfo { - - /** - * The mime type. - */ - public final String mimeType; - - /** - * The duration in microseconds, or {@link C#UNKNOWN_TIME_US} if the duration is unknown, or - * {@link C#MATCH_LONGEST_US} if the duration should match the duration of the longest track whose - * duration is known. - */ - public final long durationUs; - - /** - * @param mimeType The mime type. - * @param durationUs The duration in microseconds, or {@link C#UNKNOWN_TIME_US} if the duration - * is unknown, or {@link C#MATCH_LONGEST_US} if the duration should match the duration of the - * longest track whose duration is known. - */ - public TrackInfo(String mimeType, long durationUs) { - this.mimeType = mimeType; - this.durationUs = durationUs; - } - -} diff --git a/library/src/main/java/com/google/android/exoplayer/TrackRenderer.java b/library/src/main/java/com/google/android/exoplayer/TrackRenderer.java index 00945d466d..3254c3c3a2 100644 --- a/library/src/main/java/com/google/android/exoplayer/TrackRenderer.java +++ b/library/src/main/java/com/google/android/exoplayer/TrackRenderer.java @@ -138,17 +138,17 @@ public abstract class TrackRenderer implements ExoPlayerComponent { } /** - * Returns information about the specified track. + * Returns the format of the specified track. *

* This method may be called when the renderer is in the following states: * {@link #STATE_PREPARED}, {@link #STATE_ENABLED}, {@link #STATE_STARTED} * * @param track The track index. - * @return Information about the specified track. + * @return The format of the specified track. */ // TODO: This method should be abstract. This implementation is provided as an interim step only. - protected TrackInfo getTrackInfo(int track) { - return new TrackInfo("application/octet-stream", getDurationUs()); + protected MediaFormat getFormat(int track) { + return MediaFormat.createFormatForMimeType("application/octet-stream", getDurationUs()); } /** diff --git a/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java b/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java index 4afd5ca565..6835b6aeb9 100644 --- a/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java @@ -22,7 +22,6 @@ import com.google.android.exoplayer.MediaFormatHolder; import com.google.android.exoplayer.SampleHolder; import com.google.android.exoplayer.SampleSource; import com.google.android.exoplayer.SampleSource.SampleSourceReader; -import com.google.android.exoplayer.TrackInfo; import com.google.android.exoplayer.TrackRenderer; import com.google.android.exoplayer.extractor.DefaultTrackOutput; import com.google.android.exoplayer.upstream.Loader; @@ -132,7 +131,7 @@ public class ChunkSampleSource implements SampleSource, SampleSourceReader, Load if (state == STATE_PREPARED) { return true; } - loader = new Loader("Loader:" + chunkSource.getTrackInfo().mimeType); + loader = new Loader("Loader:" + chunkSource.getFormat().mimeType); state = STATE_PREPARED; return true; } @@ -144,10 +143,10 @@ public class ChunkSampleSource implements SampleSource, SampleSourceReader, Load } @Override - public TrackInfo getTrackInfo(int track) { + public MediaFormat getFormat(int track) { Assertions.checkState(state == STATE_PREPARED || state == STATE_ENABLED); Assertions.checkState(track == 0); - return chunkSource.getTrackInfo(); + return chunkSource.getFormat(); } @Override @@ -232,7 +231,7 @@ public class ChunkSampleSource implements SampleSource, SampleSourceReader, Load if (haveSamples || currentChunk.isMediaFormatFinal) { MediaFormat mediaFormat = currentChunk.getMediaFormat(); if (!mediaFormat.equals(downstreamMediaFormat, true)) { - chunkSource.getMaxVideoDimensions(mediaFormat); + mediaFormat = chunkSource.getWithMaxVideoDimensions(mediaFormat); formatHolder.format = mediaFormat; formatHolder.drmInitData = currentChunk.getDrmInitData(); downstreamMediaFormat = mediaFormat; diff --git a/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSource.java b/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSource.java index 1723f201d1..80509f30aa 100644 --- a/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSource.java +++ b/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSource.java @@ -16,7 +16,6 @@ package com.google.android.exoplayer.chunk; import com.google.android.exoplayer.MediaFormat; -import com.google.android.exoplayer.TrackInfo; import java.io.IOException; import java.util.List; @@ -32,23 +31,24 @@ import java.util.List; public interface ChunkSource { /** - * Gets information about the track for which this instance provides {@link Chunk}s. + * Gets the format. *

* May be called when the source is disabled or enabled. * - * @return Information about the track. + * @return The format. */ - TrackInfo getTrackInfo(); + MediaFormat getFormat(); /** - * Adaptive video {@link ChunkSource} implementations must set the maximum video dimensions on - * the supplied {@link MediaFormat}. Other implementations do nothing. - *

- * Only called when the source is enabled. + * Adaptive video {@link ChunkSource} implementations must return a copy of the provided + * {@link MediaFormat} with the maximum video dimensions set. Other implementations can return + * the provided {@link MediaFormat} directly. * - * @param out The {@link MediaFormat} on which the maximum video dimensions should be set. + * @param format The format to be copied or returned. + * @return A copy of the provided {@link MediaFormat} with the maximum video dimensions set, or + * the provided format. */ - void getMaxVideoDimensions(MediaFormat out); + MediaFormat getWithMaxVideoDimensions(MediaFormat format); /** * Called when the source is enabled. diff --git a/library/src/main/java/com/google/android/exoplayer/chunk/MultiTrackChunkSource.java b/library/src/main/java/com/google/android/exoplayer/chunk/MultiTrackChunkSource.java index c612dca454..194529735b 100644 --- a/library/src/main/java/com/google/android/exoplayer/chunk/MultiTrackChunkSource.java +++ b/library/src/main/java/com/google/android/exoplayer/chunk/MultiTrackChunkSource.java @@ -18,7 +18,6 @@ package com.google.android.exoplayer.chunk; import com.google.android.exoplayer.ExoPlaybackException; import com.google.android.exoplayer.ExoPlayer.ExoPlayerComponent; import com.google.android.exoplayer.MediaFormat; -import com.google.android.exoplayer.TrackInfo; import com.google.android.exoplayer.util.Assertions; import java.io.IOException; @@ -61,8 +60,8 @@ public final class MultiTrackChunkSource implements ChunkSource, ExoPlayerCompon } @Override - public TrackInfo getTrackInfo() { - return selectedSource.getTrackInfo(); + public MediaFormat getFormat() { + return selectedSource.getFormat(); } @Override @@ -94,8 +93,8 @@ public final class MultiTrackChunkSource implements ChunkSource, ExoPlayerCompon } @Override - public void getMaxVideoDimensions(MediaFormat out) { - selectedSource.getMaxVideoDimensions(out); + public MediaFormat getWithMaxVideoDimensions(MediaFormat format) { + return selectedSource.getWithMaxVideoDimensions(format); } @Override diff --git a/library/src/main/java/com/google/android/exoplayer/chunk/SingleSampleChunkSource.java b/library/src/main/java/com/google/android/exoplayer/chunk/SingleSampleChunkSource.java index 1068e1699a..5584741460 100644 --- a/library/src/main/java/com/google/android/exoplayer/chunk/SingleSampleChunkSource.java +++ b/library/src/main/java/com/google/android/exoplayer/chunk/SingleSampleChunkSource.java @@ -17,7 +17,6 @@ package com.google.android.exoplayer.chunk; import com.google.android.exoplayer.C; import com.google.android.exoplayer.MediaFormat; -import com.google.android.exoplayer.TrackInfo; import com.google.android.exoplayer.upstream.DataSource; import com.google.android.exoplayer.upstream.DataSpec; @@ -36,7 +35,6 @@ public final class SingleSampleChunkSource implements ChunkSource { private final Format format; private final long durationUs; private final MediaFormat mediaFormat; - private final TrackInfo trackInfo; /** * @param dataSource A {@link DataSource} suitable for loading the sample data. @@ -54,17 +52,16 @@ public final class SingleSampleChunkSource implements ChunkSource { this.format = format; this.durationUs = durationUs; this.mediaFormat = mediaFormat; - trackInfo = new TrackInfo(format.mimeType, durationUs); } @Override - public TrackInfo getTrackInfo() { - return trackInfo; + public MediaFormat getFormat() { + return mediaFormat; } @Override - public void getMaxVideoDimensions(MediaFormat out) { - // Do nothing. + public MediaFormat getWithMaxVideoDimensions(MediaFormat format) { + return format; } @Override diff --git a/library/src/main/java/com/google/android/exoplayer/dash/DashChunkSource.java b/library/src/main/java/com/google/android/exoplayer/dash/DashChunkSource.java index eb1b096947..f3e20ac602 100644 --- a/library/src/main/java/com/google/android/exoplayer/dash/DashChunkSource.java +++ b/library/src/main/java/com/google/android/exoplayer/dash/DashChunkSource.java @@ -18,7 +18,6 @@ package com.google.android.exoplayer.dash; import com.google.android.exoplayer.BehindLiveWindowException; import com.google.android.exoplayer.MediaFormat; import com.google.android.exoplayer.TimeRange; -import com.google.android.exoplayer.TrackInfo; import com.google.android.exoplayer.TrackRenderer; import com.google.android.exoplayer.chunk.Chunk; import com.google.android.exoplayer.chunk.ChunkExtractorWrapper; @@ -98,7 +97,7 @@ public class DashChunkSource implements ChunkSource { private final Handler eventHandler; private final EventListener eventListener; - private final TrackInfo trackInfo; + private final MediaFormat mediaFormat; private final DataSource dataSource; private final FormatEvaluator formatEvaluator; private final Evaluation evaluation; @@ -263,7 +262,9 @@ public class DashChunkSource implements ChunkSource { adaptationSetIndex, representationIndices); long periodDurationUs = (representations[0].periodDurationMs == TrackRenderer.UNKNOWN_TIME_US) ? TrackRenderer.UNKNOWN_TIME_US : representations[0].periodDurationMs * 1000; - this.trackInfo = new TrackInfo(representations[0].format.mimeType, periodDurationUs); + // TODO: Remove this and pass proper formats instead (b/22996976). + this.mediaFormat = MediaFormat.createFormatForMimeType(representations[0].format.mimeType, + periodDurationUs); this.formats = new Format[representations.length]; this.representationHolders = new HashMap<>(); @@ -284,15 +285,14 @@ public class DashChunkSource implements ChunkSource { } @Override - public final void getMaxVideoDimensions(MediaFormat out) { - if (trackInfo.mimeType.startsWith("video")) { - out.setMaxVideoDimensions(maxWidth, maxHeight); - } + public final MediaFormat getWithMaxVideoDimensions(MediaFormat format) { + return MimeTypes.isVideo(mediaFormat.mimeType) + ? format.copyWithMaxVideoDimension(maxWidth, maxHeight) : format; } @Override - public final TrackInfo getTrackInfo() { - return trackInfo; + public final MediaFormat getFormat() { + return mediaFormat; } // VisibleForTesting diff --git a/library/src/main/java/com/google/android/exoplayer/extractor/ExtractorSampleSource.java b/library/src/main/java/com/google/android/exoplayer/extractor/ExtractorSampleSource.java index f50d9475b1..a2c60422e7 100644 --- a/library/src/main/java/com/google/android/exoplayer/extractor/ExtractorSampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/extractor/ExtractorSampleSource.java @@ -22,7 +22,6 @@ import com.google.android.exoplayer.ParserException; import com.google.android.exoplayer.SampleHolder; import com.google.android.exoplayer.SampleSource; import com.google.android.exoplayer.SampleSource.SampleSourceReader; -import com.google.android.exoplayer.TrackInfo; import com.google.android.exoplayer.TrackRenderer; import com.google.android.exoplayer.drm.DrmInitData; import com.google.android.exoplayer.upstream.Allocator; @@ -163,7 +162,7 @@ public final class ExtractorSampleSource implements SampleSource, SampleSourceRe private boolean prepared; private int enabledTrackCount; - private TrackInfo[] trackInfos; + private MediaFormat[] mediaFormats; private long maxTrackDurationUs; private boolean[] pendingMediaFormat; private boolean[] pendingDiscontinuities; @@ -292,11 +291,11 @@ public final class ExtractorSampleSource implements SampleSource, SampleSourceRe trackEnabledStates = new boolean[trackCount]; pendingDiscontinuities = new boolean[trackCount]; pendingMediaFormat = new boolean[trackCount]; - trackInfos = new TrackInfo[trackCount]; + mediaFormats = new MediaFormat[trackCount]; maxTrackDurationUs = C.UNKNOWN_TIME_US; for (int i = 0; i < trackCount; i++) { MediaFormat format = sampleQueues.valueAt(i).getFormat(); - trackInfos[i] = new TrackInfo(format.mimeType, format.durationUs); + mediaFormats[i] = format; if (format.durationUs != C.UNKNOWN_TIME_US && format.durationUs > maxTrackDurationUs) { maxTrackDurationUs = format.durationUs; } @@ -314,9 +313,9 @@ public final class ExtractorSampleSource implements SampleSource, SampleSourceRe } @Override - public TrackInfo getTrackInfo(int track) { + public MediaFormat getFormat(int track) { Assertions.checkState(prepared); - return trackInfos[track]; + return mediaFormats[track]; } @Override diff --git a/library/src/main/java/com/google/android/exoplayer/hls/HlsChunkSource.java b/library/src/main/java/com/google/android/exoplayer/hls/HlsChunkSource.java index f9578f8a09..2ddc201554 100644 --- a/library/src/main/java/com/google/android/exoplayer/hls/HlsChunkSource.java +++ b/library/src/main/java/com/google/android/exoplayer/hls/HlsChunkSource.java @@ -224,19 +224,17 @@ public class HlsChunkSource { } /** - * Adaptive implementations must set the maximum video dimensions on the supplied - * {@link MediaFormat}. Other implementations do nothing. - *

- * Only called when the source is enabled. + * Adaptive implementations must return a copy of the provided {@link MediaFormat} with the + * maximum video dimensions set. Other implementations can return the provided {@link MediaFormat} + * directly. * - * @param out The {@link MediaFormat} on which the maximum video dimensions should be set. + * @param format The format to be copied or returned. + * @return A copy of the provided {@link MediaFormat} with the maximum video dimensions set, or + * the provided format. */ - public void getMaxVideoDimensions(MediaFormat out) { - if (maxWidth == -1 || maxHeight == -1) { - // Not adaptive. - return; - } - out.setMaxVideoDimensions(maxWidth, maxHeight); + public MediaFormat getMaxVideoDimensions(MediaFormat format) { + return (maxWidth == -1 || maxHeight == -1) ? format + : format.copyWithMaxVideoDimension(maxWidth, maxHeight); } /** diff --git a/library/src/main/java/com/google/android/exoplayer/hls/HlsSampleSource.java b/library/src/main/java/com/google/android/exoplayer/hls/HlsSampleSource.java index bf7f3981d5..92b66b5381 100644 --- a/library/src/main/java/com/google/android/exoplayer/hls/HlsSampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/hls/HlsSampleSource.java @@ -22,7 +22,6 @@ import com.google.android.exoplayer.MediaFormatHolder; import com.google.android.exoplayer.SampleHolder; import com.google.android.exoplayer.SampleSource; import com.google.android.exoplayer.SampleSource.SampleSourceReader; -import com.google.android.exoplayer.TrackInfo; import com.google.android.exoplayer.TrackRenderer; import com.google.android.exoplayer.chunk.BaseChunkSampleSourceEventListener; import com.google.android.exoplayer.chunk.Chunk; @@ -71,7 +70,7 @@ public final class HlsSampleSource implements SampleSource, SampleSourceReader, private int enabledTrackCount; private boolean[] trackEnabledStates; private boolean[] pendingDiscontinuities; - private TrackInfo[] trackInfos; + private MediaFormat[] mediaFormats; private MediaFormat[] downstreamMediaFormats; private Format downstreamFormat; @@ -135,10 +134,9 @@ public final class HlsSampleSource implements SampleSource, SampleSourceReader, trackEnabledStates = new boolean[trackCount]; pendingDiscontinuities = new boolean[trackCount]; downstreamMediaFormats = new MediaFormat[trackCount]; - trackInfos = new TrackInfo[trackCount]; + mediaFormats = new MediaFormat[trackCount]; for (int i = 0; i < trackCount; i++) { - MediaFormat format = extractor.getMediaFormat(i); - trackInfos[i] = new TrackInfo(format.mimeType, chunkSource.getDurationUs()); + mediaFormats[i] = extractor.getMediaFormat(i); } prepared = true; return true; @@ -170,9 +168,9 @@ public final class HlsSampleSource implements SampleSource, SampleSourceReader, } @Override - public TrackInfo getTrackInfo(int track) { + public MediaFormat getFormat(int track) { Assertions.checkState(prepared); - return trackInfos[track]; + return mediaFormats[track]; } @Override diff --git a/library/src/main/java/com/google/android/exoplayer/metadata/MetadataTrackRenderer.java b/library/src/main/java/com/google/android/exoplayer/metadata/MetadataTrackRenderer.java index 18d87c31f0..19c28c262a 100644 --- a/library/src/main/java/com/google/android/exoplayer/metadata/MetadataTrackRenderer.java +++ b/library/src/main/java/com/google/android/exoplayer/metadata/MetadataTrackRenderer.java @@ -16,11 +16,11 @@ package com.google.android.exoplayer.metadata; import com.google.android.exoplayer.ExoPlaybackException; +import com.google.android.exoplayer.MediaFormat; import com.google.android.exoplayer.MediaFormatHolder; import com.google.android.exoplayer.SampleHolder; import com.google.android.exoplayer.SampleSource; import com.google.android.exoplayer.SampleSourceTrackRenderer; -import com.google.android.exoplayer.TrackInfo; import com.google.android.exoplayer.TrackRenderer; import com.google.android.exoplayer.util.Assertions; @@ -88,8 +88,8 @@ public final class MetadataTrackRenderer extends SampleSourceTrackRenderer im } @Override - protected boolean handlesTrack(TrackInfo trackInfo) { - return metadataParser.canParse(trackInfo.mimeType); + protected boolean handlesTrack(MediaFormat mediaFormat) { + return metadataParser.canParse(mediaFormat.mimeType); } @Override diff --git a/library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingChunkSource.java b/library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingChunkSource.java index 3ba85d663e..fc9c62d117 100644 --- a/library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingChunkSource.java +++ b/library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingChunkSource.java @@ -17,7 +17,6 @@ package com.google.android.exoplayer.smoothstreaming; import com.google.android.exoplayer.BehindLiveWindowException; import com.google.android.exoplayer.MediaFormat; -import com.google.android.exoplayer.TrackInfo; import com.google.android.exoplayer.chunk.Chunk; import com.google.android.exoplayer.chunk.ChunkExtractorWrapper; import com.google.android.exoplayer.chunk.ChunkOperationHolder; @@ -59,7 +58,7 @@ public class SmoothStreamingChunkSource implements ChunkSource { private static final int MINIMUM_MANIFEST_REFRESH_PERIOD_MS = 5000; private static final int INITIALIZATION_VECTOR_SIZE = 8; - private final TrackInfo trackInfo; + private final MediaFormat mediaFormat; private final DataSource dataSource; private final FormatEvaluator formatEvaluator; private final Evaluation evaluation; @@ -135,7 +134,9 @@ public class SmoothStreamingChunkSource implements ChunkSource { this.liveEdgeLatencyUs = liveEdgeLatencyMs * 1000; StreamElement streamElement = getElement(initialManifest); - trackInfo = new TrackInfo(streamElement.tracks[0].format.mimeType, initialManifest.durationUs); + // TODO: Remove this and pass proper formats instead (b/22996976). + mediaFormat = MediaFormat.createFormatForMimeType(streamElement.tracks[0].format.mimeType, + initialManifest.durationUs); evaluation = new Evaluation(); TrackEncryptionBox[] trackEncryptionBoxes = null; @@ -180,15 +181,14 @@ public class SmoothStreamingChunkSource implements ChunkSource { } @Override - public final void getMaxVideoDimensions(MediaFormat out) { - if (trackInfo.mimeType.startsWith("video")) { - out.setMaxVideoDimensions(maxWidth, maxHeight); - } + public final MediaFormat getWithMaxVideoDimensions(MediaFormat format) { + return MimeTypes.isVideo(mediaFormat.mimeType) + ? format.copyWithMaxVideoDimension(maxWidth, maxHeight) : format; } @Override - public final TrackInfo getTrackInfo() { - return trackInfo; + public final MediaFormat getFormat() { + return mediaFormat; } @Override @@ -384,7 +384,6 @@ public class SmoothStreamingChunkSource implements ChunkSource { if (streamElement.type == StreamElement.TYPE_VIDEO) { MediaFormat format = MediaFormat.createVideoFormat(mimeType, MediaFormat.NO_VALUE, trackFormat.width, trackFormat.height, Arrays.asList(trackElement.csd)); - format.setMaxVideoDimensions(streamElement.maxWidth, streamElement.maxHeight); return format; } else if (streamElement.type == StreamElement.TYPE_AUDIO) { List csd; diff --git a/library/src/main/java/com/google/android/exoplayer/text/TextTrackRenderer.java b/library/src/main/java/com/google/android/exoplayer/text/TextTrackRenderer.java index 640d2eaf5d..d7f8bd9e69 100644 --- a/library/src/main/java/com/google/android/exoplayer/text/TextTrackRenderer.java +++ b/library/src/main/java/com/google/android/exoplayer/text/TextTrackRenderer.java @@ -16,11 +16,11 @@ package com.google.android.exoplayer.text; import com.google.android.exoplayer.ExoPlaybackException; +import com.google.android.exoplayer.MediaFormat; import com.google.android.exoplayer.MediaFormatHolder; import com.google.android.exoplayer.SampleHolder; import com.google.android.exoplayer.SampleSource; import com.google.android.exoplayer.SampleSourceTrackRenderer; -import com.google.android.exoplayer.TrackInfo; import com.google.android.exoplayer.TrackRenderer; import com.google.android.exoplayer.util.Assertions; @@ -150,15 +150,15 @@ public final class TextTrackRenderer extends SampleSourceTrackRenderer implement } @Override - protected boolean handlesTrack(TrackInfo trackInfo) { - return getParserIndex(trackInfo) != -1; + protected boolean handlesTrack(MediaFormat mediaFormat) { + return getParserIndex(mediaFormat) != -1; } @Override protected void onEnabled(int track, long positionUs, boolean joining) throws ExoPlaybackException { super.onEnabled(track, positionUs, joining); - parserIndex = getParserIndex(getTrackInfo(track)); + parserIndex = getParserIndex(getFormat(track)); parserThread = new HandlerThread("textParser"); parserThread.start(); parserHelper = new SubtitleParserHelper(parserThread.getLooper(), subtitleParsers[parserIndex]); @@ -296,9 +296,9 @@ public final class TextTrackRenderer extends SampleSourceTrackRenderer implement textRenderer.onCues(cues); } - private int getParserIndex(TrackInfo trackInfo) { + private int getParserIndex(MediaFormat mediaFormat) { for (int i = 0; i < subtitleParsers.length; i++) { - if (subtitleParsers[i].canParse(trackInfo.mimeType)) { + if (subtitleParsers[i].canParse(mediaFormat.mimeType)) { return i; } } diff --git a/library/src/main/java/com/google/android/exoplayer/text/eia608/Eia608TrackRenderer.java b/library/src/main/java/com/google/android/exoplayer/text/eia608/Eia608TrackRenderer.java index f906396490..316b660cd4 100644 --- a/library/src/main/java/com/google/android/exoplayer/text/eia608/Eia608TrackRenderer.java +++ b/library/src/main/java/com/google/android/exoplayer/text/eia608/Eia608TrackRenderer.java @@ -17,11 +17,11 @@ package com.google.android.exoplayer.text.eia608; import com.google.android.exoplayer.C; import com.google.android.exoplayer.ExoPlaybackException; +import com.google.android.exoplayer.MediaFormat; import com.google.android.exoplayer.MediaFormatHolder; import com.google.android.exoplayer.SampleHolder; import com.google.android.exoplayer.SampleSource; import com.google.android.exoplayer.SampleSourceTrackRenderer; -import com.google.android.exoplayer.TrackInfo; import com.google.android.exoplayer.TrackRenderer; import com.google.android.exoplayer.text.Cue; import com.google.android.exoplayer.text.TextRenderer; @@ -89,8 +89,8 @@ public final class Eia608TrackRenderer extends SampleSourceTrackRenderer impleme } @Override - protected boolean handlesTrack(TrackInfo trackInfo) { - return eia608Parser.canParse(trackInfo.mimeType); + protected boolean handlesTrack(MediaFormat mediaFormat) { + return eia608Parser.canParse(mediaFormat.mimeType); } @Override