From aa73e137d62705a1934b01dfcd483b412fa9704c Mon Sep 17 00:00:00 2001 From: olly Date: Tue, 7 Jun 2016 02:27:51 -0700 Subject: [PATCH] Propagate manifest format info through to renderers. DASH and SS manifests define potentially useful information that isn't present in the actual media streams. Primarily the representation id, but bitrate, fps and language may also be defined only at the manifest leve. This change merges the information into the sample format that's propagated to the renderers. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=124225175 --- .../com/google/android/exoplayer/Format.java | 16 ++++++++++++++ .../chunk/ChunkExtractorWrapper.java | 21 +++++++++++-------- .../exoplayer/dash/DashChunkSource.java | 12 ++++------- .../SmoothStreamingChunkSource.java | 2 +- .../exoplayer/util/DebugTextViewHelper.java | 9 ++++---- 5 files changed, 38 insertions(+), 22 deletions(-) diff --git a/library/src/main/java/com/google/android/exoplayer/Format.java b/library/src/main/java/com/google/android/exoplayer/Format.java index 07a0cbf68d..7d4e5183ff 100644 --- a/library/src/main/java/com/google/android/exoplayer/Format.java +++ b/library/src/main/java/com/google/android/exoplayer/Format.java @@ -376,6 +376,22 @@ public final class Format implements Parcelable { initializationData, drmInitData, requiresSecureDecryption); } + public Format copyWithManifestFormatInfo(Format manifestFormat, + boolean preferManifestDrmInitData) { + String id = manifestFormat.id; + int bitrate = this.bitrate == NO_VALUE ? manifestFormat.bitrate : this.bitrate; + float frameRate = this.frameRate == NO_VALUE ? manifestFormat.frameRate : this.frameRate; + String language = this.language == null ? manifestFormat.language : this.language; + DrmInitData drmInitData = (preferManifestDrmInitData && manifestFormat.drmInitData != null) + || this.drmInitData == null ? manifestFormat.drmInitData : this.drmInitData; + boolean requiresSecureDecryption = this.requiresSecureDecryption + || manifestFormat.requiresSecureDecryption; + return new Format(id, containerMimeType, sampleMimeType, bitrate, maxInputSize, width, + height, frameRate, rotationDegrees, pixelWidthHeightRatio, channelCount, sampleRate, + pcmEncoding, encoderDelay, encoderPadding, selectionFlags, language, subsampleOffsetUs, + initializationData, drmInitData, requiresSecureDecryption); + } + public Format copyWithGaplessInfo(int encoderDelay, int encoderPadding) { return new Format(id, containerMimeType, sampleMimeType, bitrate, maxInputSize, width, height, frameRate, rotationDegrees, pixelWidthHeightRatio, channelCount, sampleRate, diff --git a/library/src/main/java/com/google/android/exoplayer/chunk/ChunkExtractorWrapper.java b/library/src/main/java/com/google/android/exoplayer/chunk/ChunkExtractorWrapper.java index ad82d41e3a..76b15c55ba 100644 --- a/library/src/main/java/com/google/android/exoplayer/chunk/ChunkExtractorWrapper.java +++ b/library/src/main/java/com/google/android/exoplayer/chunk/ChunkExtractorWrapper.java @@ -48,7 +48,8 @@ public final class ChunkExtractorWrapper implements ExtractorOutput, TrackOutput } private final Extractor extractor; - private final DrmInitData drmInitData; + private final Format manifestFormat; + private final boolean preferManifestDrmInitData; private boolean extractorInitialized; private SingleTrackMetadataOutput metadataOutput; @@ -59,12 +60,16 @@ public final class ChunkExtractorWrapper implements ExtractorOutput, TrackOutput /** * @param extractor The extractor to wrap. - * @param drmInitData {@link DrmInitData} that should be added to any format extracted from the - * stream. If set, overrides any {@link DrmInitData} extracted from the stream. + * @param manifestFormat A manifest defined {@link Format} whose data should be merged into any + * sample {@link Format} output from the {@link Extractor}. + * @param preferManifestDrmInitData Whether {@link DrmInitData} defined in {@code manifestFormat} + * should be preferred when the sample and manifest {@link Format}s are merged. */ - public ChunkExtractorWrapper(Extractor extractor, DrmInitData drmInitData) { + public ChunkExtractorWrapper(Extractor extractor, Format manifestFormat, + boolean preferManifestDrmInitData) { this.extractor = extractor; - this.drmInitData = drmInitData; + this.manifestFormat = manifestFormat; + this.preferManifestDrmInitData = preferManifestDrmInitData; } /** @@ -122,10 +127,8 @@ public final class ChunkExtractorWrapper implements ExtractorOutput, TrackOutput @Override public void format(Format format) { - if (drmInitData != null) { - format = format.copyWithDrmInitData(drmInitData); - } - trackOutput.format(format); + trackOutput.format(format.copyWithManifestFormatInfo(manifestFormat, + preferManifestDrmInitData)); } @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 6a10bb970e..457e8dcabb 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 @@ -35,7 +35,6 @@ import com.google.android.exoplayer.dash.mpd.MediaPresentationDescription; import com.google.android.exoplayer.dash.mpd.Period; import com.google.android.exoplayer.dash.mpd.RangedUri; import com.google.android.exoplayer.dash.mpd.Representation; -import com.google.android.exoplayer.drm.DrmInitData; import com.google.android.exoplayer.extractor.ChunkIndex; import com.google.android.exoplayer.extractor.SeekMap; import com.google.android.exoplayer.extractor.mkv.MatroskaExtractor; @@ -366,19 +365,16 @@ public class DashChunkSource implements ChunkSource { this.periodDurationUs = periodDurationUs; this.representation = representation; String containerMimeType = representation.format.containerMimeType; + // Prefer drmInitData obtained from the manifest over drmInitData obtained from the stream, + // as per DASH IF Interoperability Recommendations V3.0, 7.5.3. extractorWrapper = mimeTypeIsRawText(containerMimeType) ? null : new ChunkExtractorWrapper( mimeTypeIsWebm(containerMimeType) ? new MatroskaExtractor() - : new FragmentedMp4Extractor(), representation.format.drmInitData); + : new FragmentedMp4Extractor(), + representation.format, true /* preferManifestDrmInitData */); segmentIndex = representation.getIndex(); } public void setSampleFormat(Format sampleFormat) { - DrmInitData manifestDrmInitData = representation.format.drmInitData; - if (manifestDrmInitData != null) { - // Prefer drmInitData obtained from the manifest over drmInitData obtained from the stream, - // as per DASH IF Interoperability Recommendations V3.0, 7.5.3. - sampleFormat = sampleFormat.copyWithDrmInitData(manifestDrmInitData); - } this.sampleFormat = sampleFormat; } 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 f5d7097aae..cef6f96fe4 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 @@ -96,7 +96,7 @@ public class SmoothStreamingChunkSource implements ChunkSource { FragmentedMp4Extractor extractor = new FragmentedMp4Extractor( FragmentedMp4Extractor.FLAG_WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME | FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_TFDT_BOX, track); - extractorWrappers[j] = new ChunkExtractorWrapper(extractor, formats[j].drmInitData); + extractorWrappers[j] = new ChunkExtractorWrapper(extractor, formats[j], false); } enabledFormats = new Format[tracks.length]; diff --git a/library/src/main/java/com/google/android/exoplayer/util/DebugTextViewHelper.java b/library/src/main/java/com/google/android/exoplayer/util/DebugTextViewHelper.java index 09a41b1104..97ee4e08ad 100644 --- a/library/src/main/java/com/google/android/exoplayer/util/DebugTextViewHelper.java +++ b/library/src/main/java/com/google/android/exoplayer/util/DebugTextViewHelper.java @@ -122,8 +122,8 @@ public final class DebugTextViewHelper implements Runnable, ExoPlayer.EventListe if (format == null) { return ""; } - return "\n" + format.sampleMimeType + "(r:" + format.width + "x" + format.height - + getCodecCounterBufferCountString(player.getVideoCodecCounters()) + ")"; + return "\n" + format.sampleMimeType + "(id:" + format.id + " r:" + format.width + "x" + + format.height + getCodecCounterBufferCountString(player.getVideoCodecCounters()) + ")"; } private String getAudioString() { @@ -131,8 +131,9 @@ public final class DebugTextViewHelper implements Runnable, ExoPlayer.EventListe if (format == null) { return ""; } - return "\n" + format.sampleMimeType + "(hz:" + format.sampleRate + " ch:" + format.channelCount - + getCodecCounterBufferCountString(player.getAudioCodecCounters()) + ")"; + return "\n" + format.sampleMimeType + "(id:" + format.id + " hz:" + format.sampleRate + " ch:" + + format.channelCount + getCodecCounterBufferCountString(player.getAudioCodecCounters()) + + ")"; } private static String getCodecCounterBufferCountString(CodecCounters counters) {