Commit d82bb3f6 by olly Committed by Oliver Woodman

Refactor #6.3: Pull drm parsing up to SS SampleSource.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=121001478
parent eb3460b3
...@@ -29,19 +29,15 @@ import com.google.android.exoplayer.chunk.FormatEvaluator; ...@@ -29,19 +29,15 @@ import com.google.android.exoplayer.chunk.FormatEvaluator;
import com.google.android.exoplayer.chunk.FormatEvaluator.Evaluation; import com.google.android.exoplayer.chunk.FormatEvaluator.Evaluation;
import com.google.android.exoplayer.chunk.MediaChunk; import com.google.android.exoplayer.chunk.MediaChunk;
import com.google.android.exoplayer.drm.DrmInitData; import com.google.android.exoplayer.drm.DrmInitData;
import com.google.android.exoplayer.drm.DrmInitData.SchemeInitData;
import com.google.android.exoplayer.extractor.mp4.FragmentedMp4Extractor; import com.google.android.exoplayer.extractor.mp4.FragmentedMp4Extractor;
import com.google.android.exoplayer.extractor.mp4.Track; import com.google.android.exoplayer.extractor.mp4.Track;
import com.google.android.exoplayer.extractor.mp4.TrackEncryptionBox; import com.google.android.exoplayer.extractor.mp4.TrackEncryptionBox;
import com.google.android.exoplayer.smoothstreaming.SmoothStreamingManifest.ProtectionElement;
import com.google.android.exoplayer.smoothstreaming.SmoothStreamingManifest.StreamElement; import com.google.android.exoplayer.smoothstreaming.SmoothStreamingManifest.StreamElement;
import com.google.android.exoplayer.upstream.DataSource; import com.google.android.exoplayer.upstream.DataSource;
import com.google.android.exoplayer.upstream.DataSpec; import com.google.android.exoplayer.upstream.DataSpec;
import com.google.android.exoplayer.util.MimeTypes;
import android.net.Uri; import android.net.Uri;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Base64;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
...@@ -53,16 +49,14 @@ import java.util.List; ...@@ -53,16 +49,14 @@ import java.util.List;
// TODO[REFACTOR]: Handle multiple stream elements of the same type (at a higher level). // TODO[REFACTOR]: Handle multiple stream elements of the same type (at a higher level).
public class SmoothStreamingChunkSource implements ChunkSource { public class SmoothStreamingChunkSource implements ChunkSource {
private static final int INITIALIZATION_VECTOR_SIZE = 8;
private final int streamElementType; private final int streamElementType;
private final DataSource dataSource; private final DataSource dataSource;
private final Evaluation evaluation; private final Evaluation evaluation;
private final FormatEvaluator adaptiveFormatEvaluator; private final FormatEvaluator adaptiveFormatEvaluator;
private TrackEncryptionBox[] trackEncryptionBoxes;
private DrmInitData.Mapped drmInitData;
private SmoothStreamingManifest currentManifest; private SmoothStreamingManifest currentManifest;
private TrackEncryptionBox[] trackEncryptionBoxes;
private DrmInitData drmInitData;
private int currentManifestChunkOffset; private int currentManifestChunkOffset;
private boolean needManifestRefresh; private boolean needManifestRefresh;
...@@ -104,20 +98,11 @@ public class SmoothStreamingChunkSource implements ChunkSource { ...@@ -104,20 +98,11 @@ public class SmoothStreamingChunkSource implements ChunkSource {
} }
} }
public void init(SmoothStreamingManifest initialManifest) { public void init(SmoothStreamingManifest initialManifest,
currentManifest = initialManifest; TrackEncryptionBox[] trackEncryptionBoxes, DrmInitData drmInitData) {
ProtectionElement protectionElement = currentManifest.protectionElement; this.currentManifest = initialManifest;
if (protectionElement != null) { this.trackEncryptionBoxes = trackEncryptionBoxes;
byte[] keyId = getProtectionElementKeyId(protectionElement.data); this.drmInitData = drmInitData;
trackEncryptionBoxes = new TrackEncryptionBox[1];
trackEncryptionBoxes[0] = new TrackEncryptionBox(true, INITIALIZATION_VECTOR_SIZE, keyId);
drmInitData = new DrmInitData.Mapped();
drmInitData.put(protectionElement.uuid,
new SchemeInitData(MimeTypes.VIDEO_MP4, protectionElement.data));
} else {
trackEncryptionBoxes = null;
drmInitData = null;
}
initForManifest(currentManifest); initForManifest(currentManifest);
} }
...@@ -327,26 +312,4 @@ public class SmoothStreamingChunkSource implements ChunkSource { ...@@ -327,26 +312,4 @@ public class SmoothStreamingChunkSource implements ChunkSource {
chunkEndTimeUs, chunkIndex, sampleOffsetUs, extractorWrapper, sampleFormat, drmInitData); chunkEndTimeUs, chunkIndex, sampleOffsetUs, extractorWrapper, sampleFormat, drmInitData);
} }
private static byte[] getProtectionElementKeyId(byte[] initData) {
StringBuilder initDataStringBuilder = new StringBuilder();
for (int i = 0; i < initData.length; i += 2) {
initDataStringBuilder.append((char) initData[i]);
}
String initDataString = initDataStringBuilder.toString();
String keyIdString = initDataString.substring(
initDataString.indexOf("<KID>") + 5, initDataString.indexOf("</KID>"));
byte[] keyId = Base64.decode(keyIdString, Base64.DEFAULT);
swap(keyId, 0, 3);
swap(keyId, 1, 2);
swap(keyId, 4, 5);
swap(keyId, 6, 7);
return keyId;
}
private static void swap(byte[] data, int firstPosition, int secondPosition) {
byte temp = data[firstPosition];
data[firstPosition] = data[secondPosition];
data[secondPosition] = temp;
}
} }
...@@ -26,17 +26,23 @@ import com.google.android.exoplayer.TrackStream; ...@@ -26,17 +26,23 @@ import com.google.android.exoplayer.TrackStream;
import com.google.android.exoplayer.chunk.ChunkSampleSource; import com.google.android.exoplayer.chunk.ChunkSampleSource;
import com.google.android.exoplayer.chunk.ChunkSampleSourceEventListener; import com.google.android.exoplayer.chunk.ChunkSampleSourceEventListener;
import com.google.android.exoplayer.chunk.FormatEvaluator.AdaptiveEvaluator; import com.google.android.exoplayer.chunk.FormatEvaluator.AdaptiveEvaluator;
import com.google.android.exoplayer.drm.DrmInitData;
import com.google.android.exoplayer.drm.DrmInitData.SchemeInitData;
import com.google.android.exoplayer.extractor.mp4.TrackEncryptionBox;
import com.google.android.exoplayer.smoothstreaming.SmoothStreamingManifest.ProtectionElement;
import com.google.android.exoplayer.upstream.BandwidthMeter; import com.google.android.exoplayer.upstream.BandwidthMeter;
import com.google.android.exoplayer.upstream.DataSource; import com.google.android.exoplayer.upstream.DataSource;
import com.google.android.exoplayer.upstream.DataSourceFactory; import com.google.android.exoplayer.upstream.DataSourceFactory;
import com.google.android.exoplayer.upstream.DefaultAllocator; import com.google.android.exoplayer.upstream.DefaultAllocator;
import com.google.android.exoplayer.util.Assertions; import com.google.android.exoplayer.util.Assertions;
import com.google.android.exoplayer.util.ManifestFetcher; import com.google.android.exoplayer.util.ManifestFetcher;
import com.google.android.exoplayer.util.MimeTypes;
import com.google.android.exoplayer.util.Util; import com.google.android.exoplayer.util.Util;
import android.net.Uri; import android.net.Uri;
import android.os.Handler; import android.os.Handler;
import android.os.SystemClock; import android.os.SystemClock;
import android.util.Base64;
import android.util.Pair; import android.util.Pair;
import java.io.IOException; import java.io.IOException;
...@@ -50,6 +56,7 @@ import java.util.List; ...@@ -50,6 +56,7 @@ import java.util.List;
public final class SmoothStreamingSampleSource implements SampleSource { public final class SmoothStreamingSampleSource implements SampleSource {
private static final int MINIMUM_MANIFEST_REFRESH_PERIOD_MS = 5000; private static final int MINIMUM_MANIFEST_REFRESH_PERIOD_MS = 5000;
private static final int INITIALIZATION_VECTOR_SIZE = 8;
private final ManifestFetcher<SmoothStreamingManifest> manifestFetcher; private final ManifestFetcher<SmoothStreamingManifest> manifestFetcher;
private final SmoothStreamingChunkSource[] chunkSources; private final SmoothStreamingChunkSource[] chunkSources;
...@@ -118,8 +125,24 @@ public final class SmoothStreamingSampleSource implements SampleSource { ...@@ -118,8 +125,24 @@ public final class SmoothStreamingSampleSource implements SampleSource {
return false; return false;
} else { } else {
durationUs = currentManifest.durationUs; durationUs = currentManifest.durationUs;
TrackEncryptionBox[] trackEncryptionBoxes;
DrmInitData.Mapped drmInitData;
ProtectionElement protectionElement = currentManifest.protectionElement;
if (protectionElement != null) {
byte[] keyId = getProtectionElementKeyId(protectionElement.data);
trackEncryptionBoxes = new TrackEncryptionBox[1];
trackEncryptionBoxes[0] = new TrackEncryptionBox(true, INITIALIZATION_VECTOR_SIZE, keyId);
drmInitData = new DrmInitData.Mapped();
drmInitData.put(protectionElement.uuid,
new SchemeInitData(MimeTypes.VIDEO_MP4, protectionElement.data));
} else {
trackEncryptionBoxes = null;
drmInitData = null;
}
for (SmoothStreamingChunkSource chunkSource : chunkSources) { for (SmoothStreamingChunkSource chunkSource : chunkSources) {
chunkSource.init(currentManifest); chunkSource.init(currentManifest, trackEncryptionBoxes, drmInitData);
} }
} }
} }
...@@ -301,4 +324,26 @@ public final class SmoothStreamingSampleSource implements SampleSource { ...@@ -301,4 +324,26 @@ public final class SmoothStreamingSampleSource implements SampleSource {
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException();
} }
private static byte[] getProtectionElementKeyId(byte[] initData) {
StringBuilder initDataStringBuilder = new StringBuilder();
for (int i = 0; i < initData.length; i += 2) {
initDataStringBuilder.append((char) initData[i]);
}
String initDataString = initDataStringBuilder.toString();
String keyIdString = initDataString.substring(
initDataString.indexOf("<KID>") + 5, initDataString.indexOf("</KID>"));
byte[] keyId = Base64.decode(keyIdString, Base64.DEFAULT);
swap(keyId, 0, 3);
swap(keyId, 1, 2);
swap(keyId, 4, 5);
swap(keyId, 6, 7);
return keyId;
}
private static void swap(byte[] data, int firstPosition, int secondPosition) {
byte temp = data[firstPosition];
data[firstPosition] = data[secondPosition];
data[secondPosition] = temp;
}
} }
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