From 2f0a1779e2183b990885b099d1beed38438d9bac Mon Sep 17 00:00:00 2001 From: Oliver Woodman Date: Mon, 8 Dec 2014 20:13:52 +0000 Subject: [PATCH] Stop piping PSSH information through the extractor. It's cleaner to not inject data into the extractor only so that it can be read out as though it were parsed from the stream. This is also an incremental step towards fixing Github issue #119. --- .../exoplayer/chunk/Mp4MediaChunk.java | 23 ++++++++++++++++--- .../exoplayer/dash/DashChunkSource.java | 2 +- .../parser/mp4/FragmentedMp4Extractor.java | 14 ----------- .../SmoothStreamingChunkSource.java | 17 ++++++++------ 4 files changed, 31 insertions(+), 25 deletions(-) diff --git a/library/src/main/java/com/google/android/exoplayer/chunk/Mp4MediaChunk.java b/library/src/main/java/com/google/android/exoplayer/chunk/Mp4MediaChunk.java index a4d05cacd7..e39c53ebff 100644 --- a/library/src/main/java/com/google/android/exoplayer/chunk/Mp4MediaChunk.java +++ b/library/src/main/java/com/google/android/exoplayer/chunk/Mp4MediaChunk.java @@ -40,6 +40,17 @@ public final class Mp4MediaChunk extends MediaChunk { private MediaFormat mediaFormat; private Map psshInfo; + /** + * @deprecated Use the other constructor, passing null as {@code psshInfo}. + */ + @Deprecated + public Mp4MediaChunk(DataSource dataSource, DataSpec dataSpec, Format format, + int trigger, long startTimeUs, long endTimeUs, int nextChunkIndex, + Extractor extractor, boolean maybeSelfContained, long sampleOffsetUs) { + this(dataSource, dataSpec, format, trigger, startTimeUs, endTimeUs, nextChunkIndex, + extractor, null, maybeSelfContained, sampleOffsetUs); + } + /** * @param dataSource A {@link DataSource} for loading the data. * @param dataSpec Defines the data to be loaded. @@ -49,6 +60,8 @@ public final class Mp4MediaChunk extends MediaChunk { * @param endTimeUs The end time of the media contained by the chunk, in microseconds. * @param nextChunkIndex The index of the next chunk, or -1 if this is the last chunk. * @param extractor The extractor that will be used to extract the samples. + * @param psshInfo Pssh data. May be null if pssh data is present within the stream, meaning it + * can be obtained directly from {@code extractor}, or if no pssh data is required. * @param maybeSelfContained Set to true if this chunk might be self contained, meaning it might * contain a moov atom defining the media format of the chunk. This parameter can always be * safely set to true. Setting to false where the chunk is known to not be self contained may @@ -56,12 +69,13 @@ public final class Mp4MediaChunk extends MediaChunk { * @param sampleOffsetUs An offset to subtract from the sample timestamps parsed by the extractor. */ public Mp4MediaChunk(DataSource dataSource, DataSpec dataSpec, Format format, - int trigger, long startTimeUs, long endTimeUs, int nextChunkIndex, - Extractor extractor, boolean maybeSelfContained, long sampleOffsetUs) { + int trigger, long startTimeUs, long endTimeUs, int nextChunkIndex, Extractor extractor, + Map psshInfo, boolean maybeSelfContained, long sampleOffsetUs) { super(dataSource, dataSpec, format, trigger, startTimeUs, endTimeUs, nextChunkIndex); this.extractor = extractor; this.maybeSelfContained = maybeSelfContained; this.sampleOffsetUs = sampleOffsetUs; + this.psshInfo = psshInfo; } @Override @@ -97,7 +111,10 @@ public final class Mp4MediaChunk extends MediaChunk { } if (prepared) { mediaFormat = extractor.getFormat(); - psshInfo = extractor.getPsshInfo(); + Map extractorPsshInfo = extractor.getPsshInfo(); + if (extractorPsshInfo != null) { + psshInfo = extractorPsshInfo; + } } } return prepared; 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 9bcb1aa3b8..d0c123bdc9 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 @@ -438,7 +438,7 @@ public class DashChunkSource implements ChunkSource { startTimeUs, endTimeUs, nextAbsoluteSegmentNum, null, representationHolder.vttHeader); } else { return new Mp4MediaChunk(dataSource, dataSpec, representation.format, trigger, startTimeUs, - endTimeUs, nextAbsoluteSegmentNum, representationHolder.extractor, false, + endTimeUs, nextAbsoluteSegmentNum, representationHolder.extractor, null, false, presentationTimeOffsetUs); } } diff --git a/library/src/main/java/com/google/android/exoplayer/parser/mp4/FragmentedMp4Extractor.java b/library/src/main/java/com/google/android/exoplayer/parser/mp4/FragmentedMp4Extractor.java index 9950aecd2a..34f0404083 100644 --- a/library/src/main/java/com/google/android/exoplayer/parser/mp4/FragmentedMp4Extractor.java +++ b/library/src/main/java/com/google/android/exoplayer/parser/mp4/FragmentedMp4Extractor.java @@ -189,20 +189,6 @@ public final class FragmentedMp4Extractor implements Extractor { this.track = track; } - /** - * Sideloads pssh information into the extractor, so that it can be read through - * {@link #getPsshInfo()}. - * - * @param uuid The UUID of the scheme for which information is being sideloaded. - * @param data The corresponding data. - */ - public void putPsshInfo(UUID uuid, byte[] data) { - // TODO: This is for SmoothStreaming. Consider using something other than - // FragmentedMp4Extractor.getPsshInfo to obtain the pssh data for that use case, so that we can - // remove this method. - psshData.put(uuid, data); - } - @Override public Map getPsshInfo() { return psshData.isEmpty() ? null : psshData; 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 2b676e6b52..936fdf824d 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 @@ -48,6 +48,8 @@ import java.io.IOException; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.UUID; /** * An {@link ChunkSource} for SmoothStreaming. @@ -69,6 +71,7 @@ public class SmoothStreamingChunkSource implements ChunkSource { private final int maxHeight; private final SparseArray extractors; + private final Map psshInfo; private final SmoothStreamingFormat[] formats; private SmoothStreamingManifest currentManifest; @@ -140,6 +143,9 @@ public class SmoothStreamingChunkSource implements ChunkSource { byte[] keyId = getKeyId(protectionElement.data); trackEncryptionBoxes = new TrackEncryptionBox[1]; trackEncryptionBoxes[0] = new TrackEncryptionBox(true, INITIALIZATION_VECTOR_SIZE, keyId); + psshInfo = Collections.singletonMap(protectionElement.uuid, protectionElement.data); + } else { + psshInfo = null; } int trackCount = trackIndices != null ? trackIndices.length : streamElement.tracks.length; @@ -163,9 +169,6 @@ public class SmoothStreamingChunkSource implements ChunkSource { FragmentedMp4Extractor.WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME); extractor.setTrack(new Track(trackIndex, trackType, streamElement.timescale, mediaFormat, trackEncryptionBoxes)); - if (protectionElement != null) { - extractor.putPsshInfo(protectionElement.uuid, protectionElement.data); - } extractors.put(trackIndex, extractor); } this.maxHeight = maxHeight; @@ -296,8 +299,8 @@ public class SmoothStreamingChunkSource implements ChunkSource { Uri uri = streamElement.buildRequestUri(selectedFormat.trackIndex, chunkIndex); Chunk mediaChunk = newMediaChunk(selectedFormat, uri, null, - extractors.get(Integer.parseInt(selectedFormat.id)), dataSource, currentAbsoluteChunkIndex, - isLastChunk, chunkStartTimeUs, nextChunkStartTimeUs, 0); + extractors.get(Integer.parseInt(selectedFormat.id)), psshInfo, dataSource, + currentAbsoluteChunkIndex, isLastChunk, chunkStartTimeUs, nextChunkStartTimeUs, 0); out.chunk = mediaChunk; } @@ -361,7 +364,7 @@ public class SmoothStreamingChunkSource implements ChunkSource { } private static MediaChunk newMediaChunk(Format formatInfo, Uri uri, String cacheKey, - Extractor extractor, DataSource dataSource, int chunkIndex, + Extractor extractor, Map psshInfo, DataSource dataSource, int chunkIndex, boolean isLast, long chunkStartTimeUs, long nextChunkStartTimeUs, int trigger) { int nextChunkIndex = isLast ? -1 : chunkIndex + 1; long nextStartTimeUs = isLast ? -1 : nextChunkStartTimeUs; @@ -370,7 +373,7 @@ public class SmoothStreamingChunkSource implements ChunkSource { // In SmoothStreaming each chunk contains sample timestamps relative to the start of the chunk. // To convert them the absolute timestamps, we need to set sampleOffsetUs to -chunkStartTimeUs. return new Mp4MediaChunk(dataSource, dataSpec, formatInfo, trigger, chunkStartTimeUs, - nextStartTimeUs, nextChunkIndex, extractor, false, -chunkStartTimeUs); + nextStartTimeUs, nextChunkIndex, extractor, psshInfo, false, -chunkStartTimeUs); } private static byte[] getKeyId(byte[] initData) {