Commit 6a54ddd2 by olly Committed by kim-vde

FMP4: Correctly handle multiple sbgp and sgpd boxes

Find sbgp and sgpd boxes with grouping_type == seig in the case they don't
come first. Previoulsy we would only find them if they came first.

Issue: Issue: #7716
PiperOrigin-RevId: 325407819
parent b9612bc3
...@@ -215,6 +215,8 @@ ...@@ -215,6 +215,8 @@
([#7230](https://github.com/google/ExoPlayer/issues/7230)). ([#7230](https://github.com/google/ExoPlayer/issues/7230)).
* MP4: Fix playback of MP4 containing Opus. * MP4: Fix playback of MP4 containing Opus.
* Matroska: Remove support for "Invisible" block header flag. * Matroska: Remove support for "Invisible" block header flag.
* FMP4: Fix handling of `traf` boxes containing multiple `sbgp` or `sgpd`
boxes.
* FLV: Ignore SCRIPTDATA segments with invalid name types, rather than failing * FLV: Ignore SCRIPTDATA segments with invalid name types, rather than failing
playback ([#7675](https://github.com/google/ExoPlayer/issues/7675)). playback ([#7675](https://github.com/google/ExoPlayer/issues/7675)).
* Extractors: * Extractors:
......
...@@ -752,12 +752,7 @@ public class FragmentedMp4Extractor implements Extractor { ...@@ -752,12 +752,7 @@ public class FragmentedMp4Extractor implements Extractor {
parseSenc(senc.data, fragment); parseSenc(senc.data, fragment);
} }
@Nullable LeafAtom sbgp = traf.getLeafAtomOfType(Atom.TYPE_sbgp); parseSampleGroups(traf, encryptionBox != null ? encryptionBox.schemeType : null, fragment);
@Nullable LeafAtom sgpd = traf.getLeafAtomOfType(Atom.TYPE_sgpd);
if (sbgp != null && sgpd != null) {
parseSgpd(sbgp.data, sgpd.data, encryptionBox != null ? encryptionBox.schemeType : null,
fragment);
}
int leafChildrenSize = traf.leafChildren.size(); int leafChildrenSize = traf.leafChildren.size();
for (int i = 0; i < leafChildrenSize; i++) { for (int i = 0; i < leafChildrenSize; i++) {
...@@ -1099,32 +1094,43 @@ public class FragmentedMp4Extractor implements Extractor { ...@@ -1099,32 +1094,43 @@ public class FragmentedMp4Extractor implements Extractor {
out.fillEncryptionData(senc); out.fillEncryptionData(senc);
} }
private static void parseSgpd( private static void parseSampleGroups(
ParsableByteArray sbgp, ContainerAtom traf, @Nullable String schemeType, TrackFragment out) throws ParserException {
ParsableByteArray sgpd, // Find sbgp and sgpd boxes with grouping_type == seig.
@Nullable String schemeType, @Nullable ParsableByteArray sbgp = null;
TrackFragment out) @Nullable ParsableByteArray sgpd = null;
throws ParserException { for (int i = 0; i < traf.leafChildren.size(); i++) {
sbgp.setPosition(Atom.HEADER_SIZE); LeafAtom leafAtom = traf.leafChildren.get(i);
int sbgpFullAtom = sbgp.readInt(); ParsableByteArray leafAtomData = leafAtom.data;
if (sbgp.readInt() != SAMPLE_GROUP_TYPE_seig) { if (leafAtom.type == Atom.TYPE_sbgp) {
// Only seig grouping type is supported. leafAtomData.setPosition(Atom.FULL_HEADER_SIZE);
if (leafAtomData.readInt() == SAMPLE_GROUP_TYPE_seig) {
sbgp = leafAtomData;
}
} else if (leafAtom.type == Atom.TYPE_sgpd) {
leafAtomData.setPosition(Atom.FULL_HEADER_SIZE);
if (leafAtomData.readInt() == SAMPLE_GROUP_TYPE_seig) {
sgpd = leafAtomData;
}
}
}
if (sbgp == null || sgpd == null) {
return; return;
} }
if (Atom.parseFullAtomVersion(sbgpFullAtom) == 1) {
sbgp.skipBytes(4); // default_length. sbgp.setPosition(Atom.HEADER_SIZE);
int sbgpVersion = Atom.parseFullAtomVersion(sbgp.readInt());
sbgp.skipBytes(4); // grouping_type == seig.
if (sbgpVersion == 1) {
sbgp.skipBytes(4); // grouping_type_parameter.
} }
if (sbgp.readInt() != 1) { // entry_count. if (sbgp.readInt() != 1) { // entry_count.
throw new ParserException("Entry count in sbgp != 1 (unsupported)."); throw new ParserException("Entry count in sbgp != 1 (unsupported).");
} }
sgpd.setPosition(Atom.HEADER_SIZE); sgpd.setPosition(Atom.HEADER_SIZE);
int sgpdFullAtom = sgpd.readInt(); int sgpdVersion = Atom.parseFullAtomVersion(sgpd.readInt());
if (sgpd.readInt() != SAMPLE_GROUP_TYPE_seig) { sgpd.skipBytes(4); // grouping_type == seig.
// Only seig grouping type is supported.
return;
}
int sgpdVersion = Atom.parseFullAtomVersion(sgpdFullAtom);
if (sgpdVersion == 1) { if (sgpdVersion == 1) {
if (sgpd.readUnsignedInt() == 0) { if (sgpd.readUnsignedInt() == 0) {
throw new ParserException("Variable length description in sgpd found (unsupported)"); throw new ParserException("Variable length description in sgpd found (unsupported)");
...@@ -1135,6 +1141,7 @@ public class FragmentedMp4Extractor implements Extractor { ...@@ -1135,6 +1141,7 @@ public class FragmentedMp4Extractor implements Extractor {
if (sgpd.readUnsignedInt() != 1) { // entry_count. if (sgpd.readUnsignedInt() != 1) { // entry_count.
throw new ParserException("Entry count in sgpd != 1 (unsupported)."); throw new ParserException("Entry count in sgpd != 1 (unsupported).");
} }
// CencSampleEncryptionInformationGroupEntry // CencSampleEncryptionInformationGroupEntry
sgpd.skipBytes(1); // reserved = 0. sgpd.skipBytes(1); // reserved = 0.
int patternByte = sgpd.readUnsignedByte(); int patternByte = sgpd.readUnsignedByte();
......
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