mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +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_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;
|
||||||
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;
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
|| 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 @@
|
||||||
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 {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,10 @@ import java.io.IOException;
|
||||||
* Undefined otherwise.
|
* Undefined otherwise.
|
||||||
*/
|
*/
|
||||||
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;
|
||||||
* 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue