Commit 50926658 by aquilescanta Committed by Ian Baker

Avoid throwing an exception for sample default values

Allows playback of content when the default value is
not valid, but not used for any samples.

Issue: #7207
PiperOrigin-RevId: 306631376
parent 91690f06
......@@ -65,6 +65,9 @@
* Remove deprecated members in `DefaultTrackSelector`.
* Add `Player.DeviceComponent` and implement it for `SimpleExoPlayer` so
that the device volume can be controlled by player.
* Avoid throwing an exception while parsing fragmented MP4 default sample
values where the most-significant bit is set
([#7207](https://github.com/google/ExoPlayer/issues/7207)).
* Text:
* Parse `<ruby>` and `<rt>` tags in WebVTT subtitles (rendering is coming
later).
......
......@@ -665,9 +665,9 @@ public class FragmentedMp4Extractor implements Extractor {
private static Pair<Integer, DefaultSampleValues> parseTrex(ParsableByteArray trex) {
trex.setPosition(Atom.FULL_HEADER_SIZE);
int trackId = trex.readInt();
int defaultSampleDescriptionIndex = trex.readUnsignedIntToInt() - 1;
int defaultSampleDuration = trex.readUnsignedIntToInt();
int defaultSampleSize = trex.readUnsignedIntToInt();
int defaultSampleDescriptionIndex = trex.readInt() - 1;
int defaultSampleDuration = trex.readInt();
int defaultSampleSize = trex.readInt();
int defaultSampleFlags = trex.readInt();
return Pair.create(trackId, new DefaultSampleValues(defaultSampleDescriptionIndex,
......@@ -753,8 +753,9 @@ public class FragmentedMp4Extractor implements Extractor {
}
}
private static void parseTruns(ContainerAtom traf, TrackBundle trackBundle, long decodeTime,
@Flags int flags) {
private static void parseTruns(
ContainerAtom traf, TrackBundle trackBundle, long decodeTime, @Flags int flags)
throws ParserException {
int trunCount = 0;
int totalSampleCount = 0;
List<LeafAtom> leafChildren = traf.leafChildren;
......@@ -874,13 +875,20 @@ public class FragmentedMp4Extractor implements Extractor {
DefaultSampleValues defaultSampleValues = trackBundle.defaultSampleValues;
int defaultSampleDescriptionIndex =
((atomFlags & 0x02 /* default_sample_description_index_present */) != 0)
? tfhd.readUnsignedIntToInt() - 1 : defaultSampleValues.sampleDescriptionIndex;
int defaultSampleDuration = ((atomFlags & 0x08 /* default_sample_duration_present */) != 0)
? tfhd.readUnsignedIntToInt() : defaultSampleValues.duration;
int defaultSampleSize = ((atomFlags & 0x10 /* default_sample_size_present */) != 0)
? tfhd.readUnsignedIntToInt() : defaultSampleValues.size;
int defaultSampleFlags = ((atomFlags & 0x20 /* default_sample_flags_present */) != 0)
? tfhd.readUnsignedIntToInt() : defaultSampleValues.flags;
? tfhd.readInt() - 1
: defaultSampleValues.sampleDescriptionIndex;
int defaultSampleDuration =
((atomFlags & 0x08 /* default_sample_duration_present */) != 0)
? tfhd.readInt()
: defaultSampleValues.duration;
int defaultSampleSize =
((atomFlags & 0x10 /* default_sample_size_present */) != 0)
? tfhd.readInt()
: defaultSampleValues.size;
int defaultSampleFlags =
((atomFlags & 0x20 /* default_sample_flags_present */) != 0)
? tfhd.readInt()
: defaultSampleValues.flags;
trackBundle.fragment.header = new DefaultSampleValues(defaultSampleDescriptionIndex,
defaultSampleDuration, defaultSampleSize, defaultSampleFlags);
return trackBundle;
......@@ -913,16 +921,22 @@ public class FragmentedMp4Extractor implements Extractor {
/**
* Parses a trun atom (defined in 14496-12).
*
* @param trackBundle The {@link TrackBundle} that contains the {@link TrackFragment} into
* which parsed data should be placed.
* @param trackBundle The {@link TrackBundle} that contains the {@link TrackFragment} into which
* parsed data should be placed.
* @param index Index of the track run in the fragment.
* @param decodeTime The decode time of the first sample in the fragment run.
* @param flags Flags to allow any required workaround to be executed.
* @param trun The trun atom to decode.
* @return The starting position of samples for the next run.
*/
private static int parseTrun(TrackBundle trackBundle, int index, long decodeTime,
@Flags int flags, ParsableByteArray trun, int trackRunStart) {
private static int parseTrun(
TrackBundle trackBundle,
int index,
long decodeTime,
@Flags int flags,
ParsableByteArray trun,
int trackRunStart)
throws ParserException {
trun.setPosition(Atom.HEADER_SIZE);
int fullAtom = trun.readInt();
int atomFlags = Atom.parseFullAtomFlags(fullAtom);
......@@ -940,7 +954,7 @@ public class FragmentedMp4Extractor implements Extractor {
boolean firstSampleFlagsPresent = (atomFlags & 0x04 /* first_sample_flags_present */) != 0;
int firstSampleFlags = defaultSampleValues.flags;
if (firstSampleFlagsPresent) {
firstSampleFlags = trun.readUnsignedIntToInt();
firstSampleFlags = trun.readInt();
}
boolean sampleDurationsPresent = (atomFlags & 0x100 /* sample_duration_present */) != 0;
......@@ -975,9 +989,10 @@ public class FragmentedMp4Extractor implements Extractor {
long cumulativeTime = index > 0 ? fragment.nextFragmentDecodeTime : decodeTime;
for (int i = trackRunStart; i < trackRunEnd; i++) {
// Use trun values if present, otherwise tfhd, otherwise trex.
int sampleDuration = sampleDurationsPresent ? trun.readUnsignedIntToInt()
: defaultSampleValues.duration;
int sampleSize = sampleSizesPresent ? trun.readUnsignedIntToInt() : defaultSampleValues.size;
int sampleDuration =
checkNonNegative(sampleDurationsPresent ? trun.readInt() : defaultSampleValues.duration);
int sampleSize =
checkNonNegative(sampleSizesPresent ? trun.readInt() : defaultSampleValues.size);
int sampleFlags = (i == 0 && firstSampleFlagsPresent) ? firstSampleFlags
: sampleFlagsPresent ? trun.readInt() : defaultSampleValues.flags;
if (sampleCompositionTimeOffsetsPresent) {
......@@ -1003,6 +1018,13 @@ public class FragmentedMp4Extractor implements Extractor {
return trackRunEnd;
}
private static int checkNonNegative(int value) throws ParserException {
if (value < 0) {
throw new ParserException("Unexpected negtive value: " + value);
}
return value;
}
private static void parseUuid(ParsableByteArray uuid, TrackFragment out,
byte[] extendedTypeScratch) throws ParserException {
uuid.setPosition(Atom.HEADER_SIZE);
......
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