Simplify DrmInitData.
- This moves to a single DrmInitData implementation that supports both specific and universal UUID matching. You can also do a combination of the two, which was not previously possible. - The object model is simplified as a result. This is a precursor to a change where DrmInitData will be included directly in the Format to enable key rotation. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=121472592
This commit is contained in:
parent
686816a610
commit
6e5ae4eddc
@ -19,8 +19,8 @@ import static com.google.android.exoplayer.drm.StreamingDrmSessionManager.PLAYRE
|
|||||||
import static com.google.android.exoplayer.drm.StreamingDrmSessionManager.WIDEVINE_UUID;
|
import static com.google.android.exoplayer.drm.StreamingDrmSessionManager.WIDEVINE_UUID;
|
||||||
import static com.google.android.exoplayer.util.MimeTypes.VIDEO_MP4;
|
import static com.google.android.exoplayer.util.MimeTypes.VIDEO_MP4;
|
||||||
|
|
||||||
import com.google.android.exoplayer.drm.DrmInitData.SchemeInitData;
|
import com.google.android.exoplayer.C;
|
||||||
import com.google.android.exoplayer.drm.DrmInitData.UuidSchemeInitDataTuple;
|
import com.google.android.exoplayer.drm.DrmInitData.SchemeData;
|
||||||
import com.google.android.exoplayer.testutil.TestUtil;
|
import com.google.android.exoplayer.testutil.TestUtil;
|
||||||
|
|
||||||
import android.test.MoreAsserts;
|
import android.test.MoreAsserts;
|
||||||
@ -32,53 +32,110 @@ import junit.framework.TestCase;
|
|||||||
*/
|
*/
|
||||||
public class DrmInitDataTest extends TestCase {
|
public class DrmInitDataTest extends TestCase {
|
||||||
|
|
||||||
private static final SchemeInitData DATA_1 =
|
private static final SchemeData DATA_1 =
|
||||||
new SchemeInitData(VIDEO_MP4, TestUtil.buildTestData(128, 1 /* data seed */));
|
new SchemeData(WIDEVINE_UUID, VIDEO_MP4, TestUtil.buildTestData(128, 1 /* data seed */));
|
||||||
private static final SchemeInitData DATA_2 =
|
private static final SchemeData DATA_2 =
|
||||||
new SchemeInitData(VIDEO_MP4, TestUtil.buildTestData(128, 2 /* data seed */));
|
new SchemeData(PLAYREADY_UUID, VIDEO_MP4, TestUtil.buildTestData(128, 2 /* data seed */));
|
||||||
|
private static final SchemeData DATA_1B =
|
||||||
|
new SchemeData(WIDEVINE_UUID, VIDEO_MP4, TestUtil.buildTestData(128, 1 /* data seed */));
|
||||||
|
private static final SchemeData DATA_2B =
|
||||||
|
new SchemeData(PLAYREADY_UUID, VIDEO_MP4, TestUtil.buildTestData(128, 2 /* data seed */));
|
||||||
|
private static final SchemeData DATA_UNIVERSAL =
|
||||||
|
new SchemeData(C.UUID_NIL, VIDEO_MP4, TestUtil.buildTestData(128, 3 /* data seed */));
|
||||||
|
|
||||||
public void testMappedEquals() {
|
public void testEquals() {
|
||||||
DrmInitData.Mapped drmInitData = new DrmInitData.Mapped(
|
DrmInitData drmInitData = new DrmInitData(DATA_1, DATA_2);
|
||||||
new UuidSchemeInitDataTuple(WIDEVINE_UUID, DATA_1),
|
|
||||||
new UuidSchemeInitDataTuple(PLAYREADY_UUID, DATA_2));
|
|
||||||
|
|
||||||
// Basic non-referential equality test.
|
// Basic non-referential equality test.
|
||||||
DrmInitData.Mapped testInitData = new DrmInitData.Mapped(
|
DrmInitData testInitData = new DrmInitData(DATA_1, DATA_2);
|
||||||
new UuidSchemeInitDataTuple(WIDEVINE_UUID, DATA_1),
|
|
||||||
new UuidSchemeInitDataTuple(PLAYREADY_UUID, DATA_2));
|
|
||||||
assertEquals(drmInitData, testInitData);
|
assertEquals(drmInitData, testInitData);
|
||||||
assertEquals(drmInitData.hashCode(), testInitData.hashCode());
|
assertEquals(drmInitData.hashCode(), testInitData.hashCode());
|
||||||
|
|
||||||
// Passing the tuples in reverse order shouldn't affect equality.
|
// Basic non-referential equality test with non-referential scheme data.
|
||||||
testInitData = new DrmInitData.Mapped(
|
testInitData = new DrmInitData(DATA_1B, DATA_2B);
|
||||||
new UuidSchemeInitDataTuple(PLAYREADY_UUID, DATA_2),
|
assertEquals(drmInitData, testInitData);
|
||||||
new UuidSchemeInitDataTuple(WIDEVINE_UUID, DATA_1));
|
assertEquals(drmInitData.hashCode(), testInitData.hashCode());
|
||||||
|
|
||||||
|
// Passing the scheme data in reverse order shouldn't affect equality.
|
||||||
|
testInitData = new DrmInitData(DATA_2, DATA_1);
|
||||||
|
assertEquals(drmInitData, testInitData);
|
||||||
|
assertEquals(drmInitData.hashCode(), testInitData.hashCode());
|
||||||
|
|
||||||
|
// Ditto.
|
||||||
|
testInitData = new DrmInitData(DATA_2B, DATA_1B);
|
||||||
assertEquals(drmInitData, testInitData);
|
assertEquals(drmInitData, testInitData);
|
||||||
assertEquals(drmInitData.hashCode(), testInitData.hashCode());
|
assertEquals(drmInitData.hashCode(), testInitData.hashCode());
|
||||||
|
|
||||||
// Different number of tuples should affect equality.
|
// Different number of tuples should affect equality.
|
||||||
testInitData = new DrmInitData.Mapped(
|
testInitData = new DrmInitData(DATA_1);
|
||||||
new UuidSchemeInitDataTuple(WIDEVINE_UUID, DATA_1));
|
|
||||||
MoreAsserts.assertNotEqual(drmInitData, testInitData);
|
MoreAsserts.assertNotEqual(drmInitData, testInitData);
|
||||||
|
|
||||||
// Different data in one of the tuples should affect equality.
|
// Different data in one of the tuples should affect equality.
|
||||||
testInitData = new DrmInitData.Mapped(
|
testInitData = new DrmInitData(DATA_1, DATA_1);
|
||||||
new UuidSchemeInitDataTuple(WIDEVINE_UUID, DATA_1),
|
|
||||||
new UuidSchemeInitDataTuple(PLAYREADY_UUID, DATA_1));
|
|
||||||
MoreAsserts.assertNotEqual(drmInitData, testInitData);
|
MoreAsserts.assertNotEqual(drmInitData, testInitData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testUniversalEquals() {
|
public void testGet() {
|
||||||
DrmInitData.Universal drmInitData = new DrmInitData.Universal(DATA_1);
|
// Basic matching.
|
||||||
|
DrmInitData testInitData = new DrmInitData(DATA_1, DATA_2);
|
||||||
|
assertEquals(DATA_1, testInitData.get(WIDEVINE_UUID));
|
||||||
|
assertEquals(DATA_2, testInitData.get(PLAYREADY_UUID));
|
||||||
|
assertNull(testInitData.get(C.UUID_NIL));
|
||||||
|
|
||||||
// Basic non-referential equality test.
|
// Basic matching including universal data.
|
||||||
DrmInitData.Universal testInitData = new DrmInitData.Universal(DATA_1);
|
testInitData = new DrmInitData(DATA_1, DATA_2, DATA_UNIVERSAL);
|
||||||
assertEquals(drmInitData, testInitData);
|
assertEquals(DATA_1, testInitData.get(WIDEVINE_UUID));
|
||||||
assertEquals(drmInitData.hashCode(), testInitData.hashCode());
|
assertEquals(DATA_2, testInitData.get(PLAYREADY_UUID));
|
||||||
|
assertEquals(DATA_UNIVERSAL, testInitData.get(C.UUID_NIL));
|
||||||
|
|
||||||
// Different data should affect equality.
|
// Passing the scheme data in reverse order shouldn't affect equality.
|
||||||
testInitData = new DrmInitData.Universal(DATA_2);
|
testInitData = new DrmInitData(DATA_UNIVERSAL, DATA_2, DATA_1);
|
||||||
MoreAsserts.assertNotEqual(drmInitData, testInitData);
|
assertEquals(DATA_1, testInitData.get(WIDEVINE_UUID));
|
||||||
|
assertEquals(DATA_2, testInitData.get(PLAYREADY_UUID));
|
||||||
|
assertEquals(DATA_UNIVERSAL, testInitData.get(C.UUID_NIL));
|
||||||
|
|
||||||
|
// Universal data should be returned in the absence of a specific match.
|
||||||
|
testInitData = new DrmInitData(DATA_1, DATA_UNIVERSAL);
|
||||||
|
assertEquals(DATA_1, testInitData.get(WIDEVINE_UUID));
|
||||||
|
assertEquals(DATA_UNIVERSAL, testInitData.get(PLAYREADY_UUID));
|
||||||
|
assertEquals(DATA_UNIVERSAL, testInitData.get(C.UUID_NIL));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDuplicateSchemeDataRejected() {
|
||||||
|
try {
|
||||||
|
new DrmInitData(DATA_1, DATA_1);
|
||||||
|
fail();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// Expected.
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
new DrmInitData(DATA_1, DATA_1B);
|
||||||
|
fail();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// Expected.
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
new DrmInitData(DATA_1, DATA_2, DATA_1B);
|
||||||
|
fail();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// Expected.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSchemeDataMatches() {
|
||||||
|
assertTrue(DATA_1.matches(WIDEVINE_UUID));
|
||||||
|
assertFalse(DATA_1.matches(PLAYREADY_UUID));
|
||||||
|
assertFalse(DATA_2.matches(C.UUID_NIL));
|
||||||
|
|
||||||
|
assertFalse(DATA_2.matches(WIDEVINE_UUID));
|
||||||
|
assertTrue(DATA_2.matches(PLAYREADY_UUID));
|
||||||
|
assertFalse(DATA_2.matches(C.UUID_NIL));
|
||||||
|
|
||||||
|
assertTrue(DATA_UNIVERSAL.matches(WIDEVINE_UUID));
|
||||||
|
assertTrue(DATA_UNIVERSAL.matches(PLAYREADY_UUID));
|
||||||
|
assertTrue(DATA_UNIVERSAL.matches(C.UUID_NIL));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ import com.google.android.exoplayer.C;
|
|||||||
import com.google.android.exoplayer.Format;
|
import com.google.android.exoplayer.Format;
|
||||||
import com.google.android.exoplayer.ParserException;
|
import com.google.android.exoplayer.ParserException;
|
||||||
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.drm.DrmInitData.SchemeData;
|
||||||
import com.google.android.exoplayer.extractor.ChunkIndex;
|
import com.google.android.exoplayer.extractor.ChunkIndex;
|
||||||
import com.google.android.exoplayer.extractor.mkv.StreamBuilder.ContentEncodingSettings;
|
import com.google.android.exoplayer.extractor.mkv.StreamBuilder.ContentEncodingSettings;
|
||||||
import com.google.android.exoplayer.testutil.FakeExtractorOutput;
|
import com.google.android.exoplayer.testutil.FakeExtractorOutput;
|
||||||
@ -237,10 +237,10 @@ public final class MatroskaExtractorTest extends InstrumentationTestCase {
|
|||||||
assertSeekMap(DEFAULT_TIMECODE_SCALE, 1);
|
assertSeekMap(DEFAULT_TIMECODE_SCALE, 1);
|
||||||
DrmInitData drmInitData = extractorOutput.drmInitData;
|
DrmInitData drmInitData = extractorOutput.drmInitData;
|
||||||
assertNotNull(drmInitData);
|
assertNotNull(drmInitData);
|
||||||
SchemeInitData widevineInitData = drmInitData.get(WIDEVINE_UUID);
|
SchemeData widevineInitData = drmInitData.get(WIDEVINE_UUID);
|
||||||
assertEquals(MimeTypes.VIDEO_WEBM, widevineInitData.mimeType);
|
assertEquals(MimeTypes.VIDEO_WEBM, widevineInitData.mimeType);
|
||||||
android.test.MoreAsserts.assertEquals(TEST_ENCRYPTION_KEY_ID, widevineInitData.data);
|
android.test.MoreAsserts.assertEquals(TEST_ENCRYPTION_KEY_ID, widevineInitData.data);
|
||||||
SchemeInitData zeroInitData = drmInitData.get(ZERO_UUID);
|
SchemeData zeroInitData = drmInitData.get(ZERO_UUID);
|
||||||
assertEquals(MimeTypes.VIDEO_WEBM, zeroInitData.mimeType);
|
assertEquals(MimeTypes.VIDEO_WEBM, zeroInitData.mimeType);
|
||||||
android.test.MoreAsserts.assertEquals(TEST_ENCRYPTION_KEY_ID, zeroInitData.data);
|
android.test.MoreAsserts.assertEquals(TEST_ENCRYPTION_KEY_ID, zeroInitData.data);
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,8 @@ import com.google.android.exoplayer.util.Util;
|
|||||||
import android.media.AudioFormat;
|
import android.media.AudioFormat;
|
||||||
import android.media.MediaCodec;
|
import android.media.MediaCodec;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines constants that are generally useful throughout the library.
|
* Defines constants that are generally useful throughout the library.
|
||||||
*/
|
*/
|
||||||
@ -175,6 +177,12 @@ public final class C {
|
|||||||
public static final int DEFAULT_MUXED_BUFFER_SIZE = DEFAULT_VIDEO_BUFFER_SIZE
|
public static final int DEFAULT_MUXED_BUFFER_SIZE = DEFAULT_VIDEO_BUFFER_SIZE
|
||||||
+ DEFAULT_AUDIO_BUFFER_SIZE + DEFAULT_TEXT_BUFFER_SIZE;
|
+ DEFAULT_AUDIO_BUFFER_SIZE + DEFAULT_TEXT_BUFFER_SIZE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Nil UUID as defined by
|
||||||
|
* <a href="https://tools.ietf.org/html/rfc4122#section-4.1.7">RFC4122</a>.
|
||||||
|
*/
|
||||||
|
public static final UUID UUID_NIL = new UUID(0L, 0L);
|
||||||
|
|
||||||
private C() {}
|
private C() {}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,7 @@
|
|||||||
package com.google.android.exoplayer;
|
package com.google.android.exoplayer;
|
||||||
|
|
||||||
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.drm.DrmInitData.SchemeData;
|
||||||
import com.google.android.exoplayer.drm.DrmInitData.UuidSchemeInitDataTuple;
|
|
||||||
import com.google.android.exoplayer.extractor.ExtractorSampleSource;
|
import com.google.android.exoplayer.extractor.ExtractorSampleSource;
|
||||||
import com.google.android.exoplayer.extractor.mp4.PsshAtomUtil;
|
import com.google.android.exoplayer.extractor.mp4.PsshAtomUtil;
|
||||||
import com.google.android.exoplayer.util.Assertions;
|
import com.google.android.exoplayer.util.Assertions;
|
||||||
@ -287,15 +286,13 @@ public final class FrameworkSampleSource implements SampleSource {
|
|||||||
if (psshInfo == null || psshInfo.isEmpty()) {
|
if (psshInfo == null || psshInfo.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
UuidSchemeInitDataTuple[] uuidSchemeInitDataTuples =
|
SchemeData[] schemeDatas = new SchemeData[psshInfo.size()];
|
||||||
new UuidSchemeInitDataTuple[psshInfo.size()];
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (UUID uuid : psshInfo.keySet()) {
|
for (UUID uuid : psshInfo.keySet()) {
|
||||||
byte[] psshAtom = PsshAtomUtil.buildPsshAtom(uuid, psshInfo.get(uuid));
|
byte[] psshAtom = PsshAtomUtil.buildPsshAtom(uuid, psshInfo.get(uuid));
|
||||||
SchemeInitData schemeData = new SchemeInitData(MimeTypes.VIDEO_MP4, psshAtom);
|
schemeDatas[count++] = new SchemeData(uuid, MimeTypes.VIDEO_MP4, psshAtom);
|
||||||
uuidSchemeInitDataTuples[count++] = new UuidSchemeInitDataTuple(uuid, schemeData);
|
|
||||||
}
|
}
|
||||||
return new DrmInitData.Mapped(uuidSchemeInitDataTuples);
|
return new DrmInitData(schemeDatas);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void seekToUsInternal(long positionUs, boolean force) {
|
private void seekToUsInternal(long positionUs, boolean force) {
|
||||||
|
@ -37,7 +37,7 @@ import com.google.android.exoplayer.dash.mpd.Period;
|
|||||||
import com.google.android.exoplayer.dash.mpd.RangedUri;
|
import com.google.android.exoplayer.dash.mpd.RangedUri;
|
||||||
import com.google.android.exoplayer.dash.mpd.Representation;
|
import com.google.android.exoplayer.dash.mpd.Representation;
|
||||||
import com.google.android.exoplayer.drm.DrmInitData;
|
import com.google.android.exoplayer.drm.DrmInitData;
|
||||||
import com.google.android.exoplayer.drm.DrmInitData.UuidSchemeInitDataTuple;
|
import com.google.android.exoplayer.drm.DrmInitData.SchemeData;
|
||||||
import com.google.android.exoplayer.extractor.ChunkIndex;
|
import com.google.android.exoplayer.extractor.ChunkIndex;
|
||||||
import com.google.android.exoplayer.extractor.SeekMap;
|
import com.google.android.exoplayer.extractor.SeekMap;
|
||||||
import com.google.android.exoplayer.extractor.mkv.MatroskaExtractor;
|
import com.google.android.exoplayer.extractor.mkv.MatroskaExtractor;
|
||||||
@ -344,19 +344,17 @@ public class DashChunkSource implements ChunkSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static DrmInitData getDrmInitData(AdaptationSet adaptationSet) {
|
private static DrmInitData getDrmInitData(AdaptationSet adaptationSet) {
|
||||||
ArrayList<UuidSchemeInitDataTuple> uuidSchemeInitDataTuples = null;
|
ArrayList<SchemeData> schemeDatas = null;
|
||||||
for (int i = 0; i < adaptationSet.contentProtections.size(); i++) {
|
for (int i = 0; i < adaptationSet.contentProtections.size(); i++) {
|
||||||
ContentProtection contentProtection = adaptationSet.contentProtections.get(i);
|
ContentProtection contentProtection = adaptationSet.contentProtections.get(i);
|
||||||
if (contentProtection.uuid != null && contentProtection.data != null) {
|
if (contentProtection.schemeData != null) {
|
||||||
if (uuidSchemeInitDataTuples == null) {
|
if (schemeDatas == null) {
|
||||||
uuidSchemeInitDataTuples = new ArrayList<UuidSchemeInitDataTuple>();
|
schemeDatas = new ArrayList<SchemeData>();
|
||||||
}
|
}
|
||||||
uuidSchemeInitDataTuples.add(
|
schemeDatas.add(contentProtection.schemeData);
|
||||||
new UuidSchemeInitDataTuple(contentProtection.uuid, contentProtection.data));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return uuidSchemeInitDataTuples == null ? null
|
return schemeDatas == null ? null : new DrmInitData(schemeDatas);
|
||||||
: new DrmInitData.Mapped(uuidSchemeInitDataTuples);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long getPeriodDurationUs(MediaPresentationDescription manifest, int index) {
|
private static long getPeriodDurationUs(MediaPresentationDescription manifest, int index) {
|
||||||
|
@ -15,12 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer.dash.mpd;
|
package com.google.android.exoplayer.dash.mpd;
|
||||||
|
|
||||||
import com.google.android.exoplayer.drm.DrmInitData.SchemeInitData;
|
import com.google.android.exoplayer.drm.DrmInitData.SchemeData;
|
||||||
import com.google.android.exoplayer.util.Assertions;
|
import com.google.android.exoplayer.util.Assertions;
|
||||||
import com.google.android.exoplayer.util.Util;
|
import com.google.android.exoplayer.util.Util;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a ContentProtection tag in an AdaptationSet.
|
* Represents a ContentProtection tag in an AdaptationSet.
|
||||||
*/
|
*/
|
||||||
@ -31,25 +29,18 @@ public class ContentProtection {
|
|||||||
*/
|
*/
|
||||||
public final String schemeUriId;
|
public final String schemeUriId;
|
||||||
|
|
||||||
/**
|
|
||||||
* The UUID of the protection scheme. May be null.
|
|
||||||
*/
|
|
||||||
public final UUID uuid;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Protection scheme specific initialization data. May be null.
|
* Protection scheme specific initialization data. May be null.
|
||||||
*/
|
*/
|
||||||
public final SchemeInitData data;
|
public final SchemeData schemeData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param schemeUriId Identifies the content protection scheme.
|
* @param schemeUriId Identifies the content protection scheme.
|
||||||
* @param uuid The UUID of the protection scheme, if known. May be null.
|
* @param schemeData Protection scheme specific initialization data. May be null.
|
||||||
* @param data Protection scheme specific initialization data. May be null.
|
|
||||||
*/
|
*/
|
||||||
public ContentProtection(String schemeUriId, UUID uuid, SchemeInitData data) {
|
public ContentProtection(String schemeUriId, SchemeData schemeData) {
|
||||||
this.schemeUriId = Assertions.checkNotNull(schemeUriId);
|
this.schemeUriId = Assertions.checkNotNull(schemeUriId);
|
||||||
this.uuid = uuid;
|
this.schemeData = schemeData;
|
||||||
this.data = data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -62,17 +53,12 @@ public class ContentProtection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ContentProtection other = (ContentProtection) obj;
|
ContentProtection other = (ContentProtection) obj;
|
||||||
return schemeUriId.equals(other.schemeUriId)
|
return schemeUriId.equals(other.schemeUriId) && Util.areEqual(schemeData, other.schemeData);
|
||||||
&& Util.areEqual(uuid, other.uuid)
|
|
||||||
&& Util.areEqual(data, other.data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
int hashCode = schemeUriId.hashCode();
|
return (31 * schemeUriId.hashCode()) + (schemeData != null ? schemeData.hashCode() : 0);
|
||||||
hashCode = (31 * hashCode) + (uuid != null ? uuid.hashCode() : 0);
|
|
||||||
hashCode = (31 * hashCode) + (data != null ? data.hashCode() : 0);
|
|
||||||
return hashCode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ import com.google.android.exoplayer.dash.mpd.SegmentBase.SegmentList;
|
|||||||
import com.google.android.exoplayer.dash.mpd.SegmentBase.SegmentTemplate;
|
import com.google.android.exoplayer.dash.mpd.SegmentBase.SegmentTemplate;
|
||||||
import com.google.android.exoplayer.dash.mpd.SegmentBase.SegmentTimelineElement;
|
import com.google.android.exoplayer.dash.mpd.SegmentBase.SegmentTimelineElement;
|
||||||
import com.google.android.exoplayer.dash.mpd.SegmentBase.SingleSegmentBase;
|
import com.google.android.exoplayer.dash.mpd.SegmentBase.SingleSegmentBase;
|
||||||
import com.google.android.exoplayer.drm.DrmInitData.SchemeInitData;
|
import com.google.android.exoplayer.drm.DrmInitData.SchemeData;
|
||||||
import com.google.android.exoplayer.extractor.mp4.PsshAtomUtil;
|
import com.google.android.exoplayer.extractor.mp4.PsshAtomUtil;
|
||||||
import com.google.android.exoplayer.upstream.UriLoadable;
|
import com.google.android.exoplayer.upstream.UriLoadable;
|
||||||
import com.google.android.exoplayer.util.Assertions;
|
import com.google.android.exoplayer.util.Assertions;
|
||||||
@ -314,29 +314,29 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
|
|||||||
protected ContentProtection parseContentProtection(XmlPullParser xpp)
|
protected ContentProtection parseContentProtection(XmlPullParser xpp)
|
||||||
throws XmlPullParserException, IOException {
|
throws XmlPullParserException, IOException {
|
||||||
String schemeIdUri = xpp.getAttributeValue(null, "schemeIdUri");
|
String schemeIdUri = xpp.getAttributeValue(null, "schemeIdUri");
|
||||||
UUID uuid = null;
|
SchemeData schemeData = null;
|
||||||
SchemeInitData data = null;
|
|
||||||
boolean seenPsshElement = false;
|
boolean seenPsshElement = false;
|
||||||
do {
|
do {
|
||||||
xpp.next();
|
xpp.next();
|
||||||
// The cenc:pssh element is defined in 23001-7:2015.
|
// The cenc:pssh element is defined in 23001-7:2015.
|
||||||
if (ParserUtil.isStartTag(xpp, "cenc:pssh") && xpp.next() == XmlPullParser.TEXT) {
|
if (ParserUtil.isStartTag(xpp, "cenc:pssh") && xpp.next() == XmlPullParser.TEXT) {
|
||||||
seenPsshElement = true;
|
seenPsshElement = true;
|
||||||
data = new SchemeInitData(MimeTypes.VIDEO_MP4,
|
byte[] data = Base64.decode(xpp.getText(), Base64.DEFAULT);
|
||||||
Base64.decode(xpp.getText(), Base64.DEFAULT));
|
UUID uuid = PsshAtomUtil.parseUuid(data);
|
||||||
uuid = PsshAtomUtil.parseUuid(data.data);
|
if (uuid != null) {
|
||||||
|
schemeData = new SchemeData(uuid, MimeTypes.VIDEO_MP4, data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} while (!ParserUtil.isEndTag(xpp, "ContentProtection"));
|
} while (!ParserUtil.isEndTag(xpp, "ContentProtection"));
|
||||||
if (seenPsshElement && uuid == null) {
|
if (seenPsshElement && schemeData == null) {
|
||||||
Log.w(TAG, "Skipped unsupported ContentProtection element");
|
Log.w(TAG, "Skipped unsupported ContentProtection element");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return buildContentProtection(schemeIdUri, uuid, data);
|
return buildContentProtection(schemeIdUri, schemeData);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ContentProtection buildContentProtection(String schemeIdUri, UUID uuid,
|
protected ContentProtection buildContentProtection(String schemeIdUri, SchemeData schemeData) {
|
||||||
SchemeInitData data) {
|
return new ContentProtection(schemeIdUri, schemeData);
|
||||||
return new ContentProtection(schemeIdUri, uuid, data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,119 +15,103 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer.drm;
|
package com.google.android.exoplayer.drm;
|
||||||
|
|
||||||
|
import com.google.android.exoplayer.C;
|
||||||
|
import com.google.android.exoplayer.drm.DrmInitData.SchemeData;
|
||||||
import com.google.android.exoplayer.util.Assertions;
|
import com.google.android.exoplayer.util.Assertions;
|
||||||
import com.google.android.exoplayer.util.Util;
|
import com.google.android.exoplayer.util.Util;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encapsulates DRM initialization data for possibly multiple DRM schemes.
|
* Encapsulates DRM initialization data for possibly multiple DRM schemes.
|
||||||
*/
|
*/
|
||||||
public interface DrmInitData {
|
public final class DrmInitData implements Comparator<SchemeData> {
|
||||||
|
|
||||||
/**
|
private final SchemeData[] schemeDatas;
|
||||||
* Retrieves initialization data for a given DRM scheme, specified by its UUID.
|
|
||||||
*
|
|
||||||
* @param schemeUuid The DRM scheme's UUID.
|
|
||||||
* @return The initialization data for the scheme, or null if the scheme is not supported.
|
|
||||||
*/
|
|
||||||
SchemeInitData get(UUID schemeUuid);
|
|
||||||
|
|
||||||
/**
|
// Lazily initialized hashcode.
|
||||||
* A {@link DrmInitData} implementation that maps UUID onto scheme specific data.
|
private int hashCode;
|
||||||
*/
|
|
||||||
final class Mapped implements DrmInitData {
|
|
||||||
|
|
||||||
private final UuidSchemeInitDataTuple[] schemeDatas;
|
public DrmInitData(List<SchemeData> schemeDatas) {
|
||||||
|
this(false, schemeDatas.toArray(new SchemeData[schemeDatas.size()]));
|
||||||
|
}
|
||||||
|
|
||||||
// Lazily initialized hashcode.
|
public DrmInitData(SchemeData... schemeDatas) {
|
||||||
private int hashCode;
|
this(true, schemeDatas);
|
||||||
|
}
|
||||||
|
|
||||||
public Mapped(UuidSchemeInitDataTuple... schemeDatas) {
|
private DrmInitData(boolean cloneSchemeDatas, SchemeData... schemeDatas) {
|
||||||
this.schemeDatas = schemeDatas.clone();
|
if (cloneSchemeDatas) {
|
||||||
Arrays.sort(this.schemeDatas); // Required for correct equals and hashcode implementations.
|
schemeDatas = schemeDatas.clone();
|
||||||
}
|
}
|
||||||
|
// Sorting ensures that universal scheme data(i.e. data that applies to all schemes) is matched
|
||||||
public Mapped(List<UuidSchemeInitDataTuple> schemeDatas) {
|
// last. It's also required by the equals and hashcode implementations.
|
||||||
this.schemeDatas = schemeDatas.toArray(new UuidSchemeInitDataTuple[schemeDatas.size()]);
|
Arrays.sort(schemeDatas, this);
|
||||||
Arrays.sort(this.schemeDatas); // Required for correct equals and hashcode implementations.
|
// Check for no duplicates.
|
||||||
}
|
for (int i = 1; i < schemeDatas.length; i++) {
|
||||||
|
if (schemeDatas[i - 1].uuid.equals(schemeDatas[i].uuid)) {
|
||||||
@Override
|
throw new IllegalArgumentException("Duplicate data for uuid: " + schemeDatas[i].uuid);
|
||||||
public SchemeInitData get(UUID schemeUuid) {
|
|
||||||
for (UuidSchemeInitDataTuple schemeData : schemeDatas) {
|
|
||||||
if (schemeUuid.equals(schemeData.uuid)) {
|
|
||||||
return schemeData.data;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
this.schemeDatas = schemeDatas;
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
if (hashCode == 0) {
|
|
||||||
hashCode = Arrays.hashCode(schemeDatas);
|
|
||||||
}
|
|
||||||
return hashCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (obj == null || getClass() != obj.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return Arrays.equals(schemeDatas, ((Mapped) obj).schemeDatas);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link DrmInitData} implementation that returns the same data for all schemes.
|
* Retrieves data for a given DRM scheme, specified by its UUID.
|
||||||
|
*
|
||||||
|
* @param uuid The DRM scheme's UUID.
|
||||||
|
* @return The initialization data for the scheme, or null if the scheme is not supported.
|
||||||
*/
|
*/
|
||||||
final class Universal implements DrmInitData {
|
public SchemeData get(UUID uuid) {
|
||||||
|
for (SchemeData schemeData : schemeDatas) {
|
||||||
private final SchemeInitData data;
|
if (schemeData.matches(uuid)) {
|
||||||
|
return schemeData;
|
||||||
public Universal(SchemeInitData data) {
|
|
||||||
this.data = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SchemeInitData get(UUID schemeUuid) {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return data == null ? 0 : data.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj) {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
if (obj == null || getClass() != obj.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return Util.areEqual(data, ((Universal) obj).data);
|
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
if (hashCode == 0) {
|
||||||
|
hashCode = Arrays.hashCode(schemeDatas);
|
||||||
|
}
|
||||||
|
return hashCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (obj == null || getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Arrays.equals(schemeDatas, ((DrmInitData) obj).schemeDatas);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compare(SchemeData first, SchemeData second) {
|
||||||
|
return C.UUID_NIL.equals(first.uuid) ? (C.UUID_NIL.equals(second.uuid) ? 0 : 1)
|
||||||
|
: first.uuid.compareTo(second.uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scheme initialization data.
|
* Scheme initialization data.
|
||||||
*/
|
*/
|
||||||
final class SchemeInitData {
|
public static final class SchemeData {
|
||||||
|
|
||||||
// Lazily initialized hashcode.
|
// Lazily initialized hashcode.
|
||||||
private int hashCode;
|
private int hashCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link UUID} of the DRM scheme, or {@link C#UUID_NIL} if the data is universal (i.e.
|
||||||
|
* applies to all schemes).
|
||||||
|
*/
|
||||||
|
private final UUID uuid;
|
||||||
/**
|
/**
|
||||||
* The mimeType of {@link #data}.
|
* The mimeType of {@link #data}.
|
||||||
*/
|
*/
|
||||||
@ -138,73 +122,51 @@ public interface DrmInitData {
|
|||||||
public final byte[] data;
|
public final byte[] data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param uuid The {@link UUID} of the DRM scheme, or {@link C#UUID_NIL} if the data is
|
||||||
|
* universal (i.e. applies to all schemes).
|
||||||
* @param mimeType The mimeType of the initialization data.
|
* @param mimeType The mimeType of the initialization data.
|
||||||
* @param data The initialization data.
|
* @param data The initialization data.
|
||||||
*/
|
*/
|
||||||
public SchemeInitData(String mimeType, byte[] data) {
|
public SchemeData(UUID uuid, String mimeType, byte[] data) {
|
||||||
|
this.uuid = Assertions.checkNotNull(uuid);
|
||||||
this.mimeType = Assertions.checkNotNull(mimeType);
|
this.mimeType = Assertions.checkNotNull(mimeType);
|
||||||
this.data = Assertions.checkNotNull(data);
|
this.data = Assertions.checkNotNull(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this initialization data applies to the specified scheme.
|
||||||
|
*
|
||||||
|
* @param schemeUuid The scheme {@link UUID}.
|
||||||
|
* @return True if this initialization data applies to the specified scheme. False otherwise.
|
||||||
|
*/
|
||||||
|
public boolean matches(UUID schemeUuid) {
|
||||||
|
return C.UUID_NIL.equals(uuid) || schemeUuid.equals(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (!(obj instanceof SchemeInitData)) {
|
if (!(obj instanceof SchemeData)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (obj == this) {
|
if (obj == this) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
SchemeInitData other = (SchemeInitData) obj;
|
SchemeData other = (SchemeData) obj;
|
||||||
return mimeType.equals(other.mimeType) && Arrays.equals(data, other.data);
|
return mimeType.equals(other.mimeType) && Util.areEqual(uuid, other.uuid)
|
||||||
|
&& Arrays.equals(data, other.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
if (hashCode == 0) {
|
if (hashCode == 0) {
|
||||||
hashCode = mimeType.hashCode() + 31 * Arrays.hashCode(data);
|
int result = ((uuid == null) ? 0 : uuid.hashCode());
|
||||||
|
result = 31 * result + mimeType.hashCode();
|
||||||
|
result = 31 * result + Arrays.hashCode(data);
|
||||||
|
hashCode = result;
|
||||||
}
|
}
|
||||||
return hashCode;
|
return hashCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* A tuple consisting of a {@link UUID} and a {@link SchemeInitData}.
|
|
||||||
* <p>
|
|
||||||
* Implements {@link Comparable} based on {@link UUID} ordering.
|
|
||||||
*/
|
|
||||||
final class UuidSchemeInitDataTuple implements Comparable<UuidSchemeInitDataTuple> {
|
|
||||||
|
|
||||||
public final UUID uuid;
|
|
||||||
public final SchemeInitData data;
|
|
||||||
|
|
||||||
public UuidSchemeInitDataTuple(UUID uuid, SchemeInitData data) {
|
|
||||||
this.uuid = Assertions.checkNotNull(uuid);
|
|
||||||
this.data = Assertions.checkNotNull(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(UuidSchemeInitDataTuple another) {
|
|
||||||
return uuid.compareTo(another.uuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return uuid.hashCode() + 31 * data.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (obj == null || getClass() != obj.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
UuidSchemeInitDataTuple other = (UuidSchemeInitDataTuple) obj;
|
|
||||||
return Util.areEqual(uuid, other.uuid) && Util.areEqual(data, other.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer.drm;
|
package com.google.android.exoplayer.drm;
|
||||||
|
|
||||||
import com.google.android.exoplayer.drm.DrmInitData.SchemeInitData;
|
import com.google.android.exoplayer.drm.DrmInitData.SchemeData;
|
||||||
import com.google.android.exoplayer.extractor.mp4.PsshAtomUtil;
|
import com.google.android.exoplayer.extractor.mp4.PsshAtomUtil;
|
||||||
import com.google.android.exoplayer.util.Util;
|
import com.google.android.exoplayer.util.Util;
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ public class StreamingDrmSessionManager implements DrmSessionManager {
|
|||||||
private int state;
|
private int state;
|
||||||
private MediaCrypto mediaCrypto;
|
private MediaCrypto mediaCrypto;
|
||||||
private Exception lastException;
|
private Exception lastException;
|
||||||
private SchemeInitData schemeInitData;
|
private SchemeData schemeData;
|
||||||
private byte[] sessionId;
|
private byte[] sessionId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -273,19 +273,19 @@ public class StreamingDrmSessionManager implements DrmSessionManager {
|
|||||||
requestHandlerThread.start();
|
requestHandlerThread.start();
|
||||||
postRequestHandler = new PostRequestHandler(requestHandlerThread.getLooper());
|
postRequestHandler = new PostRequestHandler(requestHandlerThread.getLooper());
|
||||||
}
|
}
|
||||||
if (schemeInitData == null) {
|
if (schemeData == null) {
|
||||||
schemeInitData = drmInitData.get(uuid);
|
schemeData = drmInitData.get(uuid);
|
||||||
if (schemeInitData == null) {
|
if (schemeData == null) {
|
||||||
onError(new IllegalStateException("Media does not support uuid: " + uuid));
|
onError(new IllegalStateException("Media does not support uuid: " + uuid));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (Util.SDK_INT < 21) {
|
if (Util.SDK_INT < 21) {
|
||||||
// Prior to L the Widevine CDM required data to be extracted from the PSSH atom.
|
// Prior to L the Widevine CDM required data to be extracted from the PSSH atom.
|
||||||
byte[] psshData = PsshAtomUtil.parseSchemeSpecificData(schemeInitData.data, WIDEVINE_UUID);
|
byte[] psshData = PsshAtomUtil.parseSchemeSpecificData(schemeData.data, WIDEVINE_UUID);
|
||||||
if (psshData == null) {
|
if (psshData == null) {
|
||||||
// Extraction failed. schemeData isn't a Widevine PSSH atom, so leave it unchanged.
|
// Extraction failed. schemeData isn't a Widevine PSSH atom, so leave it unchanged.
|
||||||
} else {
|
} else {
|
||||||
schemeInitData = new SchemeInitData(schemeInitData.mimeType, psshData);
|
schemeData = new SchemeData(WIDEVINE_UUID, schemeData.mimeType, psshData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -306,7 +306,7 @@ public class StreamingDrmSessionManager implements DrmSessionManager {
|
|||||||
postRequestHandler = null;
|
postRequestHandler = null;
|
||||||
requestHandlerThread.quit();
|
requestHandlerThread.quit();
|
||||||
requestHandlerThread = null;
|
requestHandlerThread = null;
|
||||||
schemeInitData = null;
|
schemeData = null;
|
||||||
mediaCrypto = null;
|
mediaCrypto = null;
|
||||||
lastException = null;
|
lastException = null;
|
||||||
if (sessionId != null) {
|
if (sessionId != null) {
|
||||||
@ -368,7 +368,7 @@ public class StreamingDrmSessionManager implements DrmSessionManager {
|
|||||||
private void postKeyRequest() {
|
private void postKeyRequest() {
|
||||||
KeyRequest keyRequest;
|
KeyRequest keyRequest;
|
||||||
try {
|
try {
|
||||||
keyRequest = mediaDrm.getKeyRequest(sessionId, schemeInitData.data, schemeInitData.mimeType,
|
keyRequest = mediaDrm.getKeyRequest(sessionId, schemeData.data, schemeData.mimeType,
|
||||||
MediaDrm.KEY_TYPE_STREAMING, optionalKeyRequestParameters);
|
MediaDrm.KEY_TYPE_STREAMING, optionalKeyRequestParameters);
|
||||||
postRequestHandler.obtainMessage(MSG_KEYS, keyRequest).sendToTarget();
|
postRequestHandler.obtainMessage(MSG_KEYS, keyRequest).sendToTarget();
|
||||||
} catch (NotProvisionedException e) {
|
} catch (NotProvisionedException e) {
|
||||||
|
@ -19,7 +19,7 @@ import com.google.android.exoplayer.C;
|
|||||||
import com.google.android.exoplayer.Format;
|
import com.google.android.exoplayer.Format;
|
||||||
import com.google.android.exoplayer.ParserException;
|
import com.google.android.exoplayer.ParserException;
|
||||||
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.drm.DrmInitData.SchemeData;
|
||||||
import com.google.android.exoplayer.extractor.ChunkIndex;
|
import com.google.android.exoplayer.extractor.ChunkIndex;
|
||||||
import com.google.android.exoplayer.extractor.Extractor;
|
import com.google.android.exoplayer.extractor.Extractor;
|
||||||
import com.google.android.exoplayer.extractor.ExtractorInput;
|
import com.google.android.exoplayer.extractor.ExtractorInput;
|
||||||
@ -484,8 +484,8 @@ public final class MatroskaExtractor implements Extractor {
|
|||||||
throw new ParserException("Encrypted Track found but ContentEncKeyID was not found");
|
throw new ParserException("Encrypted Track found but ContentEncKeyID was not found");
|
||||||
}
|
}
|
||||||
if (!sentDrmInitData) {
|
if (!sentDrmInitData) {
|
||||||
extractorOutput.drmInitData(new DrmInitData.Universal(
|
extractorOutput.drmInitData(new DrmInitData(
|
||||||
new SchemeInitData(MimeTypes.VIDEO_WEBM, currentTrack.encryptionKeyId)));
|
new SchemeData(C.UUID_NIL, MimeTypes.VIDEO_WEBM, currentTrack.encryptionKeyId)));
|
||||||
sentDrmInitData = true;
|
sentDrmInitData = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,7 @@ package com.google.android.exoplayer.extractor.mp4;
|
|||||||
import com.google.android.exoplayer.C;
|
import com.google.android.exoplayer.C;
|
||||||
import com.google.android.exoplayer.ParserException;
|
import com.google.android.exoplayer.ParserException;
|
||||||
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.drm.DrmInitData.SchemeData;
|
||||||
import com.google.android.exoplayer.drm.DrmInitData.UuidSchemeInitDataTuple;
|
|
||||||
import com.google.android.exoplayer.extractor.ChunkIndex;
|
import com.google.android.exoplayer.extractor.ChunkIndex;
|
||||||
import com.google.android.exoplayer.extractor.Extractor;
|
import com.google.android.exoplayer.extractor.Extractor;
|
||||||
import com.google.android.exoplayer.extractor.ExtractorInput;
|
import com.google.android.exoplayer.extractor.ExtractorInput;
|
||||||
@ -320,25 +319,24 @@ public final class FragmentedMp4Extractor implements Extractor {
|
|||||||
List<Atom.LeafAtom> moovLeafChildren = moov.leafChildren;
|
List<Atom.LeafAtom> moovLeafChildren = moov.leafChildren;
|
||||||
int moovLeafChildrenSize = moovLeafChildren.size();
|
int moovLeafChildrenSize = moovLeafChildren.size();
|
||||||
|
|
||||||
ArrayList<UuidSchemeInitDataTuple> uuidSchemeInitDataTuples = null;
|
ArrayList<SchemeData> schemeDatas = null;
|
||||||
for (int i = 0; i < moovLeafChildrenSize; i++) {
|
for (int i = 0; i < moovLeafChildrenSize; i++) {
|
||||||
LeafAtom child = moovLeafChildren.get(i);
|
LeafAtom child = moovLeafChildren.get(i);
|
||||||
if (child.type == Atom.TYPE_pssh) {
|
if (child.type == Atom.TYPE_pssh) {
|
||||||
if (uuidSchemeInitDataTuples == null) {
|
if (schemeDatas == null) {
|
||||||
uuidSchemeInitDataTuples = new ArrayList<UuidSchemeInitDataTuple>();
|
schemeDatas = new ArrayList<SchemeData>();
|
||||||
}
|
}
|
||||||
byte[] psshData = child.data.data;
|
byte[] psshData = child.data.data;
|
||||||
UUID uuid = PsshAtomUtil.parseUuid(psshData);
|
UUID uuid = PsshAtomUtil.parseUuid(psshData);
|
||||||
if (uuid == null) {
|
if (uuid == null) {
|
||||||
Log.w(TAG, "Skipped pssh atom (failed to extract uuid)");
|
Log.w(TAG, "Skipped pssh atom (failed to extract uuid)");
|
||||||
} else {
|
} else {
|
||||||
uuidSchemeInitDataTuples.add(new UuidSchemeInitDataTuple(uuid,
|
schemeDatas.add(new SchemeData(uuid, MimeTypes.VIDEO_MP4, psshData));
|
||||||
new SchemeInitData(MimeTypes.VIDEO_MP4, psshData)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (uuidSchemeInitDataTuples != null) {
|
if (schemeDatas != null) {
|
||||||
extractorOutput.drmInitData(new DrmInitData.Mapped(uuidSchemeInitDataTuples));
|
extractorOutput.drmInitData(new DrmInitData(schemeDatas));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read declaration of track fragments in the Moov box.
|
// Read declaration of track fragments in the Moov box.
|
||||||
|
@ -29,8 +29,7 @@ import com.google.android.exoplayer.chunk.ChunkTrackStreamEventListener;
|
|||||||
import com.google.android.exoplayer.chunk.FormatEvaluator;
|
import com.google.android.exoplayer.chunk.FormatEvaluator;
|
||||||
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;
|
||||||
import com.google.android.exoplayer.drm.DrmInitData.SchemeInitData;
|
import com.google.android.exoplayer.drm.DrmInitData.SchemeData;
|
||||||
import com.google.android.exoplayer.drm.DrmInitData.UuidSchemeInitDataTuple;
|
|
||||||
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.ProtectionElement;
|
||||||
import com.google.android.exoplayer.smoothstreaming.SmoothStreamingManifest.StreamElement;
|
import com.google.android.exoplayer.smoothstreaming.SmoothStreamingManifest.StreamElement;
|
||||||
@ -70,7 +69,7 @@ public final class SmoothStreamingSampleSource implements SampleSource {
|
|||||||
private long durationUs;
|
private long durationUs;
|
||||||
private SmoothStreamingManifest currentManifest;
|
private SmoothStreamingManifest currentManifest;
|
||||||
private TrackEncryptionBox[] trackEncryptionBoxes;
|
private TrackEncryptionBox[] trackEncryptionBoxes;
|
||||||
private DrmInitData.Mapped drmInitData;
|
private DrmInitData drmInitData;
|
||||||
private TrackGroupArray trackGroups;
|
private TrackGroupArray trackGroups;
|
||||||
private int[] trackGroupElementIndices;
|
private int[] trackGroupElementIndices;
|
||||||
private boolean pendingReset;
|
private boolean pendingReset;
|
||||||
@ -120,8 +119,8 @@ public final class SmoothStreamingSampleSource implements SampleSource {
|
|||||||
byte[] keyId = getProtectionElementKeyId(protectionElement.data);
|
byte[] keyId = getProtectionElementKeyId(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);
|
||||||
drmInitData = new DrmInitData.Mapped(new UuidSchemeInitDataTuple(protectionElement.uuid,
|
drmInitData = new DrmInitData(
|
||||||
new SchemeInitData(MimeTypes.VIDEO_MP4, protectionElement.data)));
|
new SchemeData(protectionElement.uuid, MimeTypes.VIDEO_MP4, protectionElement.data));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user