mirror of
https://github.com/samsonjs/media.git
synced 2026-04-12 12:25:47 +00:00
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:
parent
2a3b4f6780
commit
41b86f660c
5 changed files with 77 additions and 11 deletions
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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}. */
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue