mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Refactor #6.3: Pull drm parsing up to SS SampleSource.
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=121001478
This commit is contained in:
parent
eb3460b3aa
commit
d82bb3f657
2 changed files with 53 additions and 45 deletions
|
|
@ -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;
|
||||||
// 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 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
||||||
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;
|
||||||
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;
|
||||||
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 {
|
||||||
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 {
|
||||||
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue