Commit 41b86f66 by sharjeel Committed by Oliver Woodman

sgpd support in ExoV2

This is basically clone of [] for Exo V2.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=124682237
parent 2a3b4f67
...@@ -99,6 +99,8 @@ import java.util.List; ...@@ -99,6 +99,8 @@ import java.util.List;
public static final int TYPE_frma = Util.getIntegerCodeForString("frma"); public static final int TYPE_frma = Util.getIntegerCodeForString("frma");
public static final int TYPE_saiz = Util.getIntegerCodeForString("saiz"); public static final int TYPE_saiz = Util.getIntegerCodeForString("saiz");
public static final int TYPE_saio = Util.getIntegerCodeForString("saio"); public static final int TYPE_saio = Util.getIntegerCodeForString("saio");
public static final int TYPE_sbgp = Util.getIntegerCodeForString("sbgp");
public static final int TYPE_sgpd = Util.getIntegerCodeForString("sgpd");
public static final int TYPE_uuid = Util.getIntegerCodeForString("uuid"); public static final int TYPE_uuid = Util.getIntegerCodeForString("uuid");
public static final int TYPE_senc = Util.getIntegerCodeForString("senc"); public static final int TYPE_senc = Util.getIntegerCodeForString("senc");
public static final int TYPE_pasp = Util.getIntegerCodeForString("pasp"); public static final int TYPE_pasp = Util.getIntegerCodeForString("pasp");
......
...@@ -1075,10 +1075,9 @@ import java.util.List; ...@@ -1075,10 +1075,9 @@ import java.util.List;
int childAtomSize = parent.readInt(); int childAtomSize = parent.readInt();
int childAtomType = parent.readInt(); int childAtomType = parent.readInt();
if (childAtomType == Atom.TYPE_tenc) { if (childAtomType == Atom.TYPE_tenc) {
parent.skipBytes(4); parent.skipBytes(6);
int firstInt = parent.readInt(); boolean defaultIsEncrypted = parent.readUnsignedByte() == 1;
boolean defaultIsEncrypted = (firstInt >> 8) == 1; int defaultInitVectorSize = parent.readUnsignedByte();
int defaultInitVectorSize = firstInt & 0xFF;
byte[] defaultKeyId = new byte[16]; byte[] defaultKeyId = new byte[16];
parent.readBytes(defaultKeyId, 0, defaultKeyId.length); parent.readBytes(defaultKeyId, 0, defaultKeyId.length);
return new TrackEncryptionBox(defaultIsEncrypted, defaultInitVectorSize, defaultKeyId); return new TrackEncryptionBox(defaultIsEncrypted, defaultInitVectorSize, defaultKeyId);
......
...@@ -51,6 +51,7 @@ import java.util.UUID; ...@@ -51,6 +51,7 @@ import java.util.UUID;
public final class FragmentedMp4Extractor implements Extractor { public final class FragmentedMp4Extractor implements Extractor {
private static final String TAG = "FragmentedMp4Extractor"; private static final String TAG = "FragmentedMp4Extractor";
private static final int SAMPLE_GROUP_TYPE_seig = Util.getIntegerCodeForString("seig");
/** /**
* Flag to work around an issue in some video streams where every frame is marked as a sync frame. * Flag to work around an issue in some video streams where every frame is marked as a sync frame.
...@@ -474,6 +475,12 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -474,6 +475,12 @@ public final class FragmentedMp4Extractor implements Extractor {
parseSenc(senc.data, fragment); parseSenc(senc.data, fragment);
} }
LeafAtom sbgp = traf.getLeafAtomOfType(Atom.TYPE_sbgp);
LeafAtom sgpd = traf.getLeafAtomOfType(Atom.TYPE_sgpd);
if (sbgp != null && sgpd != null) {
parseSgpd(sbgp.data, sgpd.data, fragment);
}
int childrenSize = traf.leafChildren.size(); int childrenSize = traf.leafChildren.size();
for (int i = 0; i < childrenSize; i++) { for (int i = 0; i < childrenSize; i++) {
LeafAtom atom = traf.leafChildren.get(i); LeafAtom atom = traf.leafChildren.get(i);
...@@ -721,6 +728,51 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -721,6 +728,51 @@ public final class FragmentedMp4Extractor implements Extractor {
out.fillEncryptionData(senc); out.fillEncryptionData(senc);
} }
private static void parseSgpd(ParsableByteArray sbgp, ParsableByteArray sgpd, TrackFragment out)
throws ParserException {
sbgp.setPosition(Atom.HEADER_SIZE);
int sbgpFullAtom = sbgp.readInt();
if (sbgp.readInt() != SAMPLE_GROUP_TYPE_seig) {
// Only seig grouping type is supported.
return;
}
if (Atom.parseFullAtomVersion(sbgpFullAtom) == 1) {
sbgp.skipBytes(4);
}
if (sbgp.readInt() != 1) {
throw new ParserException("Entry count in sbgp != 1 (unsupported).");
}
sgpd.setPosition(Atom.HEADER_SIZE);
int sgpdFullAtom = sgpd.readInt();
if (sgpd.readInt() != SAMPLE_GROUP_TYPE_seig) {
// Only seig grouping type is supported.
return;
}
int sgpdVersion = Atom.parseFullAtomVersion(sgpdFullAtom);
if (sgpdVersion == 1) {
if (sgpd.readUnsignedInt() == 0) {
throw new ParserException("Variable length decription in sgpd found (unsupported)");
}
} else if (sgpdVersion >= 2) {
sgpd.skipBytes(4);
}
if (sgpd.readUnsignedInt() != 1) {
throw new ParserException("Entry count in sgpd != 1 (unsupported).");
}
// CencSampleEncryptionInformationGroupEntry
sgpd.skipBytes(2);
boolean isProtected = sgpd.readUnsignedByte() == 1;
if (!isProtected) {
return;
}
int initVectorSize = sgpd.readUnsignedByte();
byte[] keyId = new byte[16];
sgpd.readBytes(keyId, 0, keyId.length);
out.definesEncryptionData = true;
out.trackEncryptionBox = new TrackEncryptionBox(isProtected, initVectorSize, keyId);
}
/** /**
* Parses a sidx atom (defined in 14496-12). * Parses a sidx atom (defined in 14496-12).
*/ */
...@@ -897,8 +949,12 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -897,8 +949,12 @@ public final class FragmentedMp4Extractor implements Extractor {
int sampleFlags = (fragment.definesEncryptionData ? C.BUFFER_FLAG_ENCRYPTED : 0) int sampleFlags = (fragment.definesEncryptionData ? C.BUFFER_FLAG_ENCRYPTED : 0)
| (fragment.sampleIsSyncFrameTable[sampleIndex] ? C.BUFFER_FLAG_KEY_FRAME : 0); | (fragment.sampleIsSyncFrameTable[sampleIndex] ? C.BUFFER_FLAG_KEY_FRAME : 0);
int sampleDescriptionIndex = fragment.header.sampleDescriptionIndex; int sampleDescriptionIndex = fragment.header.sampleDescriptionIndex;
byte[] encryptionKey = fragment.definesEncryptionData byte[] encryptionKey = null;
? track.sampleDescriptionEncryptionBoxes[sampleDescriptionIndex].keyId : null; if (fragment.definesEncryptionData) {
encryptionKey = fragment.trackEncryptionBox != null
? fragment.trackEncryptionBox.keyId
: track.sampleDescriptionEncryptionBoxes[sampleDescriptionIndex].keyId;
}
output.sampleMetadata(sampleTimeUs, sampleFlags, sampleSize, 0, encryptionKey); output.sampleMetadata(sampleTimeUs, sampleFlags, sampleSize, 0, encryptionKey);
currentTrackBundle.currentSampleIndex++; currentTrackBundle.currentSampleIndex++;
...@@ -945,8 +1001,9 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -945,8 +1001,9 @@ public final class FragmentedMp4Extractor implements Extractor {
TrackFragment trackFragment = trackBundle.fragment; TrackFragment trackFragment = trackBundle.fragment;
ParsableByteArray sampleEncryptionData = trackFragment.sampleEncryptionData; ParsableByteArray sampleEncryptionData = trackFragment.sampleEncryptionData;
int sampleDescriptionIndex = trackFragment.header.sampleDescriptionIndex; int sampleDescriptionIndex = trackFragment.header.sampleDescriptionIndex;
TrackEncryptionBox encryptionBox = trackBundle.track TrackEncryptionBox encryptionBox = trackFragment.trackEncryptionBox != null
.sampleDescriptionEncryptionBoxes[sampleDescriptionIndex]; ? trackFragment.trackEncryptionBox
: trackBundle.track.sampleDescriptionEncryptionBoxes[sampleDescriptionIndex];
int vectorSize = encryptionBox.initializationVectorSize; int vectorSize = encryptionBox.initializationVectorSize;
boolean subsampleEncryption = trackFragment boolean subsampleEncryption = trackFragment
.sampleHasSubsampleEncryptionTable[trackBundle.currentSampleIndex]; .sampleHasSubsampleEncryptionTable[trackBundle.currentSampleIndex];
...@@ -977,7 +1034,8 @@ public final class FragmentedMp4Extractor implements Extractor { ...@@ -977,7 +1034,8 @@ public final class FragmentedMp4Extractor implements Extractor {
|| atom == Atom.TYPE_tfhd || atom == Atom.TYPE_tkhd || atom == Atom.TYPE_trex || atom == Atom.TYPE_tfhd || atom == Atom.TYPE_tkhd || atom == Atom.TYPE_trex
|| atom == Atom.TYPE_trun || atom == Atom.TYPE_pssh || atom == Atom.TYPE_saiz || atom == Atom.TYPE_trun || atom == Atom.TYPE_pssh || atom == Atom.TYPE_saiz
|| atom == Atom.TYPE_saio || atom == Atom.TYPE_senc || atom == Atom.TYPE_uuid || atom == Atom.TYPE_saio || atom == Atom.TYPE_senc || atom == Atom.TYPE_uuid
|| atom == Atom.TYPE_elst || atom == Atom.TYPE_mehd; || atom == Atom.TYPE_sbgp || atom == Atom.TYPE_sgpd || atom == Atom.TYPE_elst
|| atom == Atom.TYPE_mehd;
} }
/** Returns whether the extractor should parse a container atom with type {@code atom}. */ /** Returns whether the extractor should parse a container atom with type {@code atom}. */
......
...@@ -16,7 +16,8 @@ ...@@ -16,7 +16,8 @@
package com.google.android.exoplayer.extractor.mp4; package com.google.android.exoplayer.extractor.mp4;
/** /**
* Encapsulates information parsed from a track encryption (tenc) box in an MP4 stream. * Encapsulates information parsed from a track encryption (tenc) box or sample group description
* (sgpd) box in an MP4 stream.
*/ */
public final class TrackEncryptionBox { public final class TrackEncryptionBox {
......
...@@ -67,6 +67,10 @@ import java.io.IOException; ...@@ -67,6 +67,10 @@ import java.io.IOException;
*/ */
public boolean[] sampleHasSubsampleEncryptionTable; public boolean[] sampleHasSubsampleEncryptionTable;
/** /**
* Fragment specific track encryption. May be null.
*/
public TrackEncryptionBox trackEncryptionBox;
/**
* If {@link #definesEncryptionData} is true, indicates the length of the sample encryption data. * If {@link #definesEncryptionData} is true, indicates the length of the sample encryption data.
* Undefined otherwise. * Undefined otherwise.
*/ */
...@@ -89,13 +93,15 @@ import java.io.IOException; ...@@ -89,13 +93,15 @@ import java.io.IOException;
* Resets the fragment. * Resets the fragment.
* <p> * <p>
* {@link #length} and {@link #nextFragmentDecodeTime} are set to 0, and both * {@link #length} and {@link #nextFragmentDecodeTime} are set to 0, and both
* {@link #definesEncryptionData} and {@link #sampleEncryptionDataNeedsFill} is set to false. * {@link #definesEncryptionData} and {@link #sampleEncryptionDataNeedsFill} is set to false,
* and {@link #trackEncryptionBox} is set to null.
*/ */
public void reset() { public void reset() {
length = 0; length = 0;
nextFragmentDecodeTime = 0; nextFragmentDecodeTime = 0;
definesEncryptionData = false; definesEncryptionData = false;
sampleEncryptionDataNeedsFill = false; sampleEncryptionDataNeedsFill = false;
trackEncryptionBox = null;
} }
/** /**
......
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