sgpd support in ExoV2

This is basically clone of [] for Exo V2.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=124682237
This commit is contained in:
sharjeel 2016-06-12 14:59:50 -07:00 committed by Oliver Woodman
parent 2a3b4f6780
commit 41b86f660c
5 changed files with 77 additions and 11 deletions

View file

@ -99,6 +99,8 @@ import java.util.List;
public static final int TYPE_frma = Util.getIntegerCodeForString("frma");
public static final int TYPE_saiz = Util.getIntegerCodeForString("saiz");
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_senc = Util.getIntegerCodeForString("senc");
public static final int TYPE_pasp = Util.getIntegerCodeForString("pasp");

View file

@ -1075,10 +1075,9 @@ import java.util.List;
int childAtomSize = parent.readInt();
int childAtomType = parent.readInt();
if (childAtomType == Atom.TYPE_tenc) {
parent.skipBytes(4);
int firstInt = parent.readInt();
boolean defaultIsEncrypted = (firstInt >> 8) == 1;
int defaultInitVectorSize = firstInt & 0xFF;
parent.skipBytes(6);
boolean defaultIsEncrypted = parent.readUnsignedByte() == 1;
int defaultInitVectorSize = parent.readUnsignedByte();
byte[] defaultKeyId = new byte[16];
parent.readBytes(defaultKeyId, 0, defaultKeyId.length);
return new TrackEncryptionBox(defaultIsEncrypted, defaultInitVectorSize, defaultKeyId);

View file

@ -51,6 +51,7 @@ import java.util.UUID;
public final class FragmentedMp4Extractor implements Extractor {
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.
@ -474,6 +475,12 @@ public final class FragmentedMp4Extractor implements Extractor {
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();
for (int i = 0; i < childrenSize; i++) {
LeafAtom atom = traf.leafChildren.get(i);
@ -721,6 +728,51 @@ public final class FragmentedMp4Extractor implements Extractor {
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).
*/
@ -897,8 +949,12 @@ public final class FragmentedMp4Extractor implements Extractor {
int sampleFlags = (fragment.definesEncryptionData ? C.BUFFER_FLAG_ENCRYPTED : 0)
| (fragment.sampleIsSyncFrameTable[sampleIndex] ? C.BUFFER_FLAG_KEY_FRAME : 0);
int sampleDescriptionIndex = fragment.header.sampleDescriptionIndex;
byte[] encryptionKey = fragment.definesEncryptionData
? track.sampleDescriptionEncryptionBoxes[sampleDescriptionIndex].keyId : null;
byte[] encryptionKey = null;
if (fragment.definesEncryptionData) {
encryptionKey = fragment.trackEncryptionBox != null
? fragment.trackEncryptionBox.keyId
: track.sampleDescriptionEncryptionBoxes[sampleDescriptionIndex].keyId;
}
output.sampleMetadata(sampleTimeUs, sampleFlags, sampleSize, 0, encryptionKey);
currentTrackBundle.currentSampleIndex++;
@ -945,8 +1001,9 @@ public final class FragmentedMp4Extractor implements Extractor {
TrackFragment trackFragment = trackBundle.fragment;
ParsableByteArray sampleEncryptionData = trackFragment.sampleEncryptionData;
int sampleDescriptionIndex = trackFragment.header.sampleDescriptionIndex;
TrackEncryptionBox encryptionBox = trackBundle.track
.sampleDescriptionEncryptionBoxes[sampleDescriptionIndex];
TrackEncryptionBox encryptionBox = trackFragment.trackEncryptionBox != null
? trackFragment.trackEncryptionBox
: trackBundle.track.sampleDescriptionEncryptionBoxes[sampleDescriptionIndex];
int vectorSize = encryptionBox.initializationVectorSize;
boolean subsampleEncryption = trackFragment
.sampleHasSubsampleEncryptionTable[trackBundle.currentSampleIndex];
@ -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_trun || atom == Atom.TYPE_pssh || atom == Atom.TYPE_saiz
|| 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}. */

View file

@ -16,7 +16,8 @@
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 {

View file

@ -66,6 +66,10 @@ import java.io.IOException;
* Undefined otherwise.
*/
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.
* Undefined otherwise.
@ -89,13 +93,15 @@ import java.io.IOException;
* Resets the fragment.
* <p>
* {@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() {
length = 0;
nextFragmentDecodeTime = 0;
definesEncryptionData = false;
sampleEncryptionDataNeedsFill = false;
trackEncryptionBox = null;
}
/**