Skip to content

Commit

Permalink
Add type to DrmInitData.SchemeData
Browse files Browse the repository at this point in the history
At the moment, only CENC-defined scheme types are known values.
This will allow having more information about the encryption
scheme through the format, which in turn will allow more informed
decisions on format support.

Issue:#1661
Issue:#1989
Issue:#2089

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=159538907
  • Loading branch information
AquilesCanta authored and ojw28 committed Jun 22, 2017
1 parent 2c09f8e commit 317a994
Show file tree
Hide file tree
Showing 13 changed files with 158 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ public final class FormatTest extends TestCase {
}

public void testParcelable() {
DrmInitData.SchemeData DRM_DATA_1 = new DrmInitData.SchemeData(WIDEVINE_UUID, VIDEO_MP4,
DrmInitData.SchemeData DRM_DATA_1 = new DrmInitData.SchemeData(WIDEVINE_UUID, "cenc", VIDEO_MP4,
TestUtil.buildTestData(128, 1 /* data seed */));
DrmInitData.SchemeData DRM_DATA_2 = new DrmInitData.SchemeData(C.UUID_NIL, VIDEO_WEBM,
DrmInitData.SchemeData DRM_DATA_2 = new DrmInitData.SchemeData(C.UUID_NIL, null, VIDEO_WEBM,
TestUtil.buildTestData(128, 1 /* data seed */));
DrmInitData drmInitData = new DrmInitData(DRM_DATA_1, DRM_DATA_2);
byte[] projectionData = new byte[] {1, 2, 3};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,16 @@
*/
public class DrmInitDataTest extends TestCase {

private static final SchemeData DATA_1 =
new SchemeData(WIDEVINE_UUID, VIDEO_MP4, TestUtil.buildTestData(128, 1 /* data seed */));
private static final SchemeData DATA_2 =
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 */));
private static final SchemeData DATA_1 = new SchemeData(WIDEVINE_UUID, "cbc1", VIDEO_MP4,
TestUtil.buildTestData(128, 1 /* data seed */));
private static final SchemeData DATA_2 = new SchemeData(PLAYREADY_UUID, null, VIDEO_MP4,
TestUtil.buildTestData(128, 2 /* data seed */));
private static final SchemeData DATA_1B = new SchemeData(WIDEVINE_UUID, "cens", VIDEO_MP4,
TestUtil.buildTestData(128, 1 /* data seed */));
private static final SchemeData DATA_2B = new SchemeData(PLAYREADY_UUID, null, VIDEO_MP4,
TestUtil.buildTestData(128, 2 /* data seed */));
private static final SchemeData DATA_UNIVERSAL = new SchemeData(C.UUID_NIL, null, VIDEO_MP4,
TestUtil.buildTestData(128, 3 /* data seed */));

public void testParcelable() {
DrmInitData drmInitDataToParcel = new DrmInitData(DATA_1, DATA_2);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ private void setStubLicenseAndPlaybackDurationValues(long licenseDuration,
}

private static DrmInitData newDrmInitData() {
return new DrmInitData(new SchemeData(C.WIDEVINE_UUID, "mimeType",
return new DrmInitData(new SchemeData(C.WIDEVINE_UUID, "cenc", "mimeType",
new byte[] {1, 4, 7, 0, 3, 6}));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.drm.DrmInitData.SchemeData;
import com.google.android.exoplayer2.util.Assertions;
Expand Down Expand Up @@ -102,6 +103,33 @@ public SchemeData get(int index) {
return schemeDatas[index];
}

/**
* Returns a copy of the {@link DrmInitData} instance whose {@link SchemeData}s have been updated
* to have the specified scheme type.
*
* @param schemeType A protection scheme type. May be null.
* @return A copy of the {@link DrmInitData} instance whose {@link SchemeData}s have been updated
* to have the specified scheme type.
*/
public DrmInitData copyWithSchemeType(@Nullable String schemeType) {
boolean isCopyRequired = false;
for (SchemeData schemeData : schemeDatas) {
if (!Util.areEqual(schemeData.type, schemeType)) {
isCopyRequired = true;
break;
}
}
if (isCopyRequired) {
SchemeData[] schemeDatas = new SchemeData[this.schemeDatas.length];
for (int i = 0; i < schemeDatas.length; i++) {
schemeDatas[i] = this.schemeDatas[i].copyWithSchemeType(schemeType);
}
return new DrmInitData(schemeDatas);
} else {
return this;
}
}

@Override
public int hashCode() {
if (hashCode == 0) {
Expand Down Expand Up @@ -167,6 +195,10 @@ public static final class SchemeData implements Parcelable {
* applies to all schemes).
*/
private final UUID uuid;
/**
* The protection scheme type, or null if not applicable or unknown.
*/
@Nullable public final String type;
/**
* The mimeType of {@link #data}.
*/
Expand All @@ -183,29 +215,34 @@ public static final class SchemeData implements Parcelable {
/**
* @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 type The type of the protection scheme, or null if not applicable or unknown.
* @param mimeType The mimeType of the initialization data.
* @param data The initialization data.
*/
public SchemeData(UUID uuid, String mimeType, byte[] data) {
this(uuid, mimeType, data, false);
public SchemeData(UUID uuid, @Nullable String type, String mimeType, byte[] data) {
this(uuid, type, mimeType, data, false);
}

/**
* @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 type The type of the protection scheme, or null if not applicable or unknown.
* @param mimeType The mimeType of the initialization data.
* @param data The initialization data.
* @param requiresSecureDecryption Whether secure decryption is required.
*/
public SchemeData(UUID uuid, String mimeType, byte[] data, boolean requiresSecureDecryption) {
public SchemeData(UUID uuid, @Nullable String type, String mimeType, byte[] data,
boolean requiresSecureDecryption) {
this.uuid = Assertions.checkNotNull(uuid);
this.type = type;
this.mimeType = Assertions.checkNotNull(mimeType);
this.data = Assertions.checkNotNull(data);
this.requiresSecureDecryption = requiresSecureDecryption;
}

/* package */ SchemeData(Parcel in) {
uuid = new UUID(in.readLong(), in.readLong());
type = in.readString();
mimeType = in.readString();
data = in.createByteArray();
requiresSecureDecryption = in.readByte() != 0;
Expand All @@ -221,6 +258,19 @@ public boolean matches(UUID schemeUuid) {
return C.UUID_NIL.equals(uuid) || schemeUuid.equals(uuid);
}

/**
* Returns a copy of the {@link SchemeData} instance with the given scheme type.
*
* @param type A protection scheme type.
* @return A copy of the {@link SchemeData} instance with the given scheme type.
*/
public SchemeData copyWithSchemeType(String type) {
if (Util.areEqual(this.type, type)) {
return this;
}
return new SchemeData(uuid, type, mimeType, data, requiresSecureDecryption);
}

@Override
public boolean equals(Object obj) {
if (!(obj instanceof SchemeData)) {
Expand All @@ -231,13 +281,14 @@ public boolean equals(Object obj) {
}
SchemeData other = (SchemeData) obj;
return mimeType.equals(other.mimeType) && Util.areEqual(uuid, other.uuid)
&& Arrays.equals(data, other.data);
&& Util.areEqual(type, other.type) && Arrays.equals(data, other.data);
}

@Override
public int hashCode() {
if (hashCode == 0) {
int result = uuid.hashCode();
result = 31 * result + (type == null ? 0 : type.hashCode());
result = 31 * result + mimeType.hashCode();
result = 31 * result + Arrays.hashCode(data);
hashCode = result;
Expand All @@ -256,6 +307,7 @@ public int describeContents() {
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(uuid.getMostSignificantBits());
dest.writeLong(uuid.getLeastSignificantBits());
dest.writeString(type);
dest.writeString(mimeType);
dest.writeByteArray(data);
dest.writeByte((byte) (requiresSecureDecryption ? 1 : 0));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,7 @@ public int read(ExtractorInput input, PositionHolder seekPosition) throws IOExce
if (currentTrack.cryptoData == null) {
throw new ParserException("Encrypted Track found but ContentEncKeyID was not found");
}
currentTrack.drmInitData = new DrmInitData(new SchemeData(C.UUID_NIL,
currentTrack.drmInitData = new DrmInitData(new SchemeData(C.UUID_NIL, null,
MimeTypes.VIDEO_WEBM, currentTrack.cryptoData.encryptionKey));
}
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -615,19 +615,18 @@ private static StsdData parseStsd(ParsableByteArray stsd, int trackId, int rotat
|| childAtomType == Atom.TYPE_wvtt || childAtomType == Atom.TYPE_stpp
|| childAtomType == Atom.TYPE_c608) {
parseTextSampleEntry(stsd, childAtomType, childStartPosition, childAtomSize, trackId,
language, drmInitData, out);
language, out);
} else if (childAtomType == Atom.TYPE_camm) {
out.format = Format.createSampleFormat(Integer.toString(trackId),
MimeTypes.APPLICATION_CAMERA_MOTION, null, Format.NO_VALUE, drmInitData);
MimeTypes.APPLICATION_CAMERA_MOTION, null, Format.NO_VALUE, null);
}
stsd.setPosition(childStartPosition + childAtomSize);
}
return out;
}

private static void parseTextSampleEntry(ParsableByteArray parent, int atomType, int position,
int atomSize, int trackId, String language, DrmInitData drmInitData, StsdData out)
throws ParserException {
int atomSize, int trackId, String language, StsdData out) throws ParserException {
parent.setPosition(position + Atom.HEADER_SIZE + StsdData.STSD_HEADER_SIZE);

// Default values.
Expand Down Expand Up @@ -658,8 +657,7 @@ private static void parseTextSampleEntry(ParsableByteArray parent, int atomType,
}

out.format = Format.createTextSampleFormat(Integer.toString(trackId), mimeType, null,
Format.NO_VALUE, 0, language, Format.NO_VALUE, drmInitData, subsampleOffsetUs,
initializationData);
Format.NO_VALUE, 0, language, Format.NO_VALUE, null, subsampleOffsetUs, initializationData);
}

private static void parseVideoSampleEntry(ParsableByteArray parent, int atomType, int position,
Expand All @@ -677,7 +675,14 @@ private static void parseVideoSampleEntry(ParsableByteArray parent, int atomType
int childPosition = parent.getPosition();
if (atomType == Atom.TYPE_encv) {
atomType = parseSampleEntryEncryptionData(parent, position, size, out, entryIndex);
TrackEncryptionBox encryptionBox = out.trackEncryptionBoxes[entryIndex];
String schemeType = encryptionBox != null ? encryptionBox.schemeType : null;
if (schemeType != null) {
drmInitData = drmInitData.copyWithSchemeType(schemeType);
}
parent.setPosition(childPosition);
} else {
drmInitData = null;
}

List<byte[]> initializationData = null;
Expand Down Expand Up @@ -846,7 +851,14 @@ private static void parseAudioSampleEntry(ParsableByteArray parent, int atomType
int childPosition = parent.getPosition();
if (atomType == Atom.TYPE_enca) {
atomType = parseSampleEntryEncryptionData(parent, position, size, out, entryIndex);
TrackEncryptionBox encryptionBox = out.trackEncryptionBoxes[entryIndex];
String schemeType = encryptionBox != null ? encryptionBox.schemeType : null;
if (schemeType != null) {
drmInitData = drmInitData.copyWithSchemeType(schemeType);
}
parent.setPosition(childPosition);
} else {
drmInitData = null;
}

// If the atom type determines a MIME type, set it immediately.
Expand Down Expand Up @@ -1051,9 +1063,9 @@ private static int parseSampleEntryEncryptionData(ParsableByteArray parent, int
private static Pair<Integer, TrackEncryptionBox> parseSinfFromParent(ParsableByteArray parent,
int position, int size) {
int childPosition = position + Atom.HEADER_SIZE;

boolean isCencScheme = false;
TrackEncryptionBox trackEncryptionBox = null;
int schemeInformationBoxPosition = C.POSITION_UNSET;
int schemeInformationBoxSize = 0;
String schemeType = null;
Integer dataFormat = null;
while (childPosition - position < size) {
parent.setPosition(childPosition);
Expand All @@ -1063,24 +1075,30 @@ private static Pair<Integer, TrackEncryptionBox> parseSinfFromParent(ParsableByt
dataFormat = parent.readInt();
} else if (childAtomType == Atom.TYPE_schm) {
parent.skipBytes(4);
isCencScheme = parent.readInt() == TYPE_cenc;
// scheme_type field. Defined in ISO/IEC 23001-7:2016, section 4.1.
schemeType = parent.readString(4);
} else if (childAtomType == Atom.TYPE_schi) {
trackEncryptionBox = parseSchiFromParent(parent, childPosition, childAtomSize);
schemeInformationBoxPosition = childPosition;
schemeInformationBoxSize = childAtomSize;
}
childPosition += childAtomSize;
}

if (isCencScheme) {
if (schemeType != null) {
Assertions.checkArgument(dataFormat != null, "frma atom is mandatory");
Assertions.checkArgument(trackEncryptionBox != null, "schi->tenc atom is mandatory");
return Pair.create(dataFormat, trackEncryptionBox);
Assertions.checkArgument(schemeInformationBoxPosition != C.POSITION_UNSET,
"schi atom is mandatory");
TrackEncryptionBox encryptionBox = parseSchiFromParent(parent, schemeInformationBoxPosition,
schemeInformationBoxSize, schemeType);
Assertions.checkArgument(encryptionBox != null, "tenc atom is mandatory");
return Pair.create(dataFormat, encryptionBox);
} else {
return null;
}
}

private static TrackEncryptionBox parseSchiFromParent(ParsableByteArray parent, int position,
int size) {
int size, String schemeType) {
int childPosition = position + Atom.HEADER_SIZE;
while (childPosition - position < size) {
parent.setPosition(childPosition);
Expand All @@ -1092,7 +1110,8 @@ private static TrackEncryptionBox parseSchiFromParent(ParsableByteArray parent,
int defaultInitVectorSize = parent.readUnsignedByte();
byte[] defaultKeyId = new byte[16];
parent.readBytes(defaultKeyId, 0, defaultKeyId.length);
return new TrackEncryptionBox(defaultIsEncrypted, defaultInitVectorSize, defaultKeyId);
return new TrackEncryptionBox(defaultIsEncrypted, schemeType, defaultInitVectorSize,
defaultKeyId);
}
childPosition += childAtomSize;
}
Expand Down
Loading

0 comments on commit 317a994

Please sign in to comment.