Commit 2f0a1779 by Oliver Woodman

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.
parent cf80c4d9
...@@ -41,6 +41,17 @@ public final class Mp4MediaChunk extends MediaChunk { ...@@ -41,6 +41,17 @@ public final class Mp4MediaChunk extends MediaChunk {
private Map<UUID, byte[]> psshInfo; private Map<UUID, byte[]> 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 dataSource A {@link DataSource} for loading the data.
* @param dataSpec Defines the data to be loaded. * @param dataSpec Defines the data to be loaded.
* @param format The format of the stream to which this chunk belongs. * @param format The format of the stream to which this chunk belongs.
...@@ -49,6 +60,8 @@ public final class Mp4MediaChunk extends MediaChunk { ...@@ -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 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 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 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 * @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 * 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 * 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 { ...@@ -56,12 +69,13 @@ public final class Mp4MediaChunk extends MediaChunk {
* @param sampleOffsetUs An offset to subtract from the sample timestamps parsed by the extractor. * @param sampleOffsetUs An offset to subtract from the sample timestamps parsed by the extractor.
*/ */
public Mp4MediaChunk(DataSource dataSource, DataSpec dataSpec, Format format, public Mp4MediaChunk(DataSource dataSource, DataSpec dataSpec, Format format,
int trigger, long startTimeUs, long endTimeUs, int nextChunkIndex, int trigger, long startTimeUs, long endTimeUs, int nextChunkIndex, Extractor extractor,
Extractor extractor, boolean maybeSelfContained, long sampleOffsetUs) { Map<UUID, byte[]> psshInfo, boolean maybeSelfContained, long sampleOffsetUs) {
super(dataSource, dataSpec, format, trigger, startTimeUs, endTimeUs, nextChunkIndex); super(dataSource, dataSpec, format, trigger, startTimeUs, endTimeUs, nextChunkIndex);
this.extractor = extractor; this.extractor = extractor;
this.maybeSelfContained = maybeSelfContained; this.maybeSelfContained = maybeSelfContained;
this.sampleOffsetUs = sampleOffsetUs; this.sampleOffsetUs = sampleOffsetUs;
this.psshInfo = psshInfo;
} }
@Override @Override
...@@ -97,7 +111,10 @@ public final class Mp4MediaChunk extends MediaChunk { ...@@ -97,7 +111,10 @@ public final class Mp4MediaChunk extends MediaChunk {
} }
if (prepared) { if (prepared) {
mediaFormat = extractor.getFormat(); mediaFormat = extractor.getFormat();
psshInfo = extractor.getPsshInfo(); Map<UUID, byte[]> extractorPsshInfo = extractor.getPsshInfo();
if (extractorPsshInfo != null) {
psshInfo = extractorPsshInfo;
}
} }
} }
return prepared; return prepared;
......
...@@ -438,7 +438,7 @@ public class DashChunkSource implements ChunkSource { ...@@ -438,7 +438,7 @@ public class DashChunkSource implements ChunkSource {
startTimeUs, endTimeUs, nextAbsoluteSegmentNum, null, representationHolder.vttHeader); startTimeUs, endTimeUs, nextAbsoluteSegmentNum, null, representationHolder.vttHeader);
} else { } else {
return new Mp4MediaChunk(dataSource, dataSpec, representation.format, trigger, startTimeUs, return new Mp4MediaChunk(dataSource, dataSpec, representation.format, trigger, startTimeUs,
endTimeUs, nextAbsoluteSegmentNum, representationHolder.extractor, false, endTimeUs, nextAbsoluteSegmentNum, representationHolder.extractor, null, false,
presentationTimeOffsetUs); presentationTimeOffsetUs);
} }
} }
......
...@@ -189,20 +189,6 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -189,20 +189,6 @@ public final class FragmentedMp4Extractor implements Extractor {
this.track = track; 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 @Override
public Map<UUID, byte[]> getPsshInfo() { public Map<UUID, byte[]> getPsshInfo() {
return psshData.isEmpty() ? null : psshData; return psshData.isEmpty() ? null : psshData;
......
...@@ -48,6 +48,8 @@ import java.io.IOException; ...@@ -48,6 +48,8 @@ import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.UUID;
/** /**
* An {@link ChunkSource} for SmoothStreaming. * An {@link ChunkSource} for SmoothStreaming.
...@@ -69,6 +71,7 @@ public class SmoothStreamingChunkSource implements ChunkSource { ...@@ -69,6 +71,7 @@ public class SmoothStreamingChunkSource implements ChunkSource {
private final int maxHeight; private final int maxHeight;
private final SparseArray<FragmentedMp4Extractor> extractors; private final SparseArray<FragmentedMp4Extractor> extractors;
private final Map<UUID, byte[]> psshInfo;
private final SmoothStreamingFormat[] formats; private final SmoothStreamingFormat[] formats;
private SmoothStreamingManifest currentManifest; private SmoothStreamingManifest currentManifest;
...@@ -140,6 +143,9 @@ public class SmoothStreamingChunkSource implements ChunkSource { ...@@ -140,6 +143,9 @@ public class SmoothStreamingChunkSource implements ChunkSource {
byte[] keyId = getKeyId(protectionElement.data); byte[] keyId = getKeyId(protectionElement.data);
trackEncryptionBoxes = new TrackEncryptionBox[1]; trackEncryptionBoxes = new TrackEncryptionBox[1];
trackEncryptionBoxes[0] = new TrackEncryptionBox(true, INITIALIZATION_VECTOR_SIZE, keyId); 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; int trackCount = trackIndices != null ? trackIndices.length : streamElement.tracks.length;
...@@ -163,9 +169,6 @@ public class SmoothStreamingChunkSource implements ChunkSource { ...@@ -163,9 +169,6 @@ public class SmoothStreamingChunkSource implements ChunkSource {
FragmentedMp4Extractor.WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME); FragmentedMp4Extractor.WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME);
extractor.setTrack(new Track(trackIndex, trackType, streamElement.timescale, mediaFormat, extractor.setTrack(new Track(trackIndex, trackType, streamElement.timescale, mediaFormat,
trackEncryptionBoxes)); trackEncryptionBoxes));
if (protectionElement != null) {
extractor.putPsshInfo(protectionElement.uuid, protectionElement.data);
}
extractors.put(trackIndex, extractor); extractors.put(trackIndex, extractor);
} }
this.maxHeight = maxHeight; this.maxHeight = maxHeight;
...@@ -296,8 +299,8 @@ public class SmoothStreamingChunkSource implements ChunkSource { ...@@ -296,8 +299,8 @@ public class SmoothStreamingChunkSource implements ChunkSource {
Uri uri = streamElement.buildRequestUri(selectedFormat.trackIndex, chunkIndex); Uri uri = streamElement.buildRequestUri(selectedFormat.trackIndex, chunkIndex);
Chunk mediaChunk = newMediaChunk(selectedFormat, uri, null, Chunk mediaChunk = newMediaChunk(selectedFormat, uri, null,
extractors.get(Integer.parseInt(selectedFormat.id)), dataSource, currentAbsoluteChunkIndex, extractors.get(Integer.parseInt(selectedFormat.id)), psshInfo, dataSource,
isLastChunk, chunkStartTimeUs, nextChunkStartTimeUs, 0); currentAbsoluteChunkIndex, isLastChunk, chunkStartTimeUs, nextChunkStartTimeUs, 0);
out.chunk = mediaChunk; out.chunk = mediaChunk;
} }
...@@ -361,7 +364,7 @@ public class SmoothStreamingChunkSource implements ChunkSource { ...@@ -361,7 +364,7 @@ public class SmoothStreamingChunkSource implements ChunkSource {
} }
private static MediaChunk newMediaChunk(Format formatInfo, Uri uri, String cacheKey, private static MediaChunk newMediaChunk(Format formatInfo, Uri uri, String cacheKey,
Extractor extractor, DataSource dataSource, int chunkIndex, Extractor extractor, Map<UUID, byte[]> psshInfo, DataSource dataSource, int chunkIndex,
boolean isLast, long chunkStartTimeUs, long nextChunkStartTimeUs, int trigger) { boolean isLast, long chunkStartTimeUs, long nextChunkStartTimeUs, int trigger) {
int nextChunkIndex = isLast ? -1 : chunkIndex + 1; int nextChunkIndex = isLast ? -1 : chunkIndex + 1;
long nextStartTimeUs = isLast ? -1 : nextChunkStartTimeUs; long nextStartTimeUs = isLast ? -1 : nextChunkStartTimeUs;
...@@ -370,7 +373,7 @@ public class SmoothStreamingChunkSource implements ChunkSource { ...@@ -370,7 +373,7 @@ public class SmoothStreamingChunkSource implements ChunkSource {
// In SmoothStreaming each chunk contains sample timestamps relative to the start of the chunk. // 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. // To convert them the absolute timestamps, we need to set sampleOffsetUs to -chunkStartTimeUs.
return new Mp4MediaChunk(dataSource, dataSpec, formatInfo, trigger, 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) { private static byte[] getKeyId(byte[] initData) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment