From 4e8895d5cb03600d2389ef382abe02ffd3b6fbf6 Mon Sep 17 00:00:00 2001 From: olly Date: Tue, 15 Jun 2021 17:27:44 +0100 Subject: [PATCH] Fix issue where a trun atom could be associated with the wrong track Note that this removes a workaround for malformed content, in which the track_ID is set incorrectly. It's unclear there was sufficient reason to implement that workaround, and so it's preferable to remove it, rather than implementing the concept of unrecognized tracks, which would be needed to keep it and to also fix this issue. Issue: #9056 #minor-release PiperOrigin-RevId: 379506261 --- RELEASENOTES.md | 8 +++++ .../extractor/mp4/FragmentedMp4Extractor.java | 31 ++++++++----------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index c22e1e648d0..e99fd84e749 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -50,6 +50,14 @@ passthrough capability from API 29 onwards, instead of using the HDMI audio plug intent ([#6500](https://github.com/google/ExoPlayer/pull/6500)). +* Extractors: + * Fix issue where a `trun` atom could be associated with the wrong track + in an FMP4 stream + ([#9056](https://github.com/google/ExoPlayer/pull/9056)). The fix + removes a previous workaround to handle content in which the `track_ID` + is set incorrectly + ([#4083](https://github.com/google/ExoPlayer/issues/4083)). Such content + is malformed and should be re-encoded. * Ad playback: * Support changing ad break positions in the player logic ([#5067](https://github.com/google/ExoPlayer/issues/5067). diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.java index e3e5f270905..0ec5bd48edf 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.java @@ -556,7 +556,7 @@ private DefaultSampleValues getDefaultSampleValues( } private void onMoofContainerAtomRead(ContainerAtom moof) throws ParserException { - parseMoof(moof, trackBundles, flags, scratchBytes); + parseMoof(moof, trackBundles, sideloadedTrack != null, flags, scratchBytes); @Nullable DrmInitData drmInitData = getDrmInitDataFromAtoms(moof.leafChildren); if (drmInitData != null) { @@ -703,7 +703,8 @@ private static long parseMehd(ParsableByteArray mehd) { private static void parseMoof( ContainerAtom moof, - SparseArray trackBundleArray, + SparseArray trackBundles, + boolean haveSideloadedTrack, @Flags int flags, byte[] extendedTypeScratch) throws ParserException { @@ -712,7 +713,7 @@ private static void parseMoof( Atom.ContainerAtom child = moof.containerChildren.get(i); // TODO: Support multiple traf boxes per track in a single moof. if (child.type == Atom.TYPE_traf) { - parseTraf(child, trackBundleArray, flags, extendedTypeScratch); + parseTraf(child, trackBundles, haveSideloadedTrack, flags, extendedTypeScratch); } } } @@ -720,12 +721,13 @@ private static void parseMoof( /** Parses a traf atom (defined in 14496-12). */ private static void parseTraf( ContainerAtom traf, - SparseArray trackBundleArray, + SparseArray trackBundles, + boolean haveSideloadedTrack, @Flags int flags, byte[] extendedTypeScratch) throws ParserException { LeafAtom tfhd = checkNotNull(traf.getLeafAtomOfType(Atom.TYPE_tfhd)); - @Nullable TrackBundle trackBundle = parseTfhd(tfhd.data, trackBundleArray); + @Nullable TrackBundle trackBundle = parseTfhd(tfhd.data, trackBundles, haveSideloadedTrack); if (trackBundle == null) { return; } @@ -883,17 +885,21 @@ private static void parseSaio(ParsableByteArray saio, TrackFragment out) throws * * @param tfhd The tfhd atom to decode. * @param trackBundles The track bundles, one of which corresponds to the tfhd atom being parsed. + * @param haveSideloadedTrack Whether {@code trackBundles} contains a single bundle corresponding + * to a side-loaded track. * @return The {@link TrackBundle} to which the {@link TrackFragment} belongs, or null if the tfhd * does not refer to any {@link TrackBundle}. */ @Nullable private static TrackBundle parseTfhd( - ParsableByteArray tfhd, SparseArray trackBundles) { + ParsableByteArray tfhd, SparseArray trackBundles, boolean haveSideloadedTrack) { tfhd.setPosition(Atom.HEADER_SIZE); int fullAtom = tfhd.readInt(); int atomFlags = Atom.parseFullAtomFlags(fullAtom); int trackId = tfhd.readInt(); - @Nullable TrackBundle trackBundle = getTrackBundle(trackBundles, trackId); + @Nullable + TrackBundle trackBundle = + haveSideloadedTrack ? trackBundles.valueAt(0) : trackBundles.get(trackId); if (trackBundle == null) { return null; } @@ -929,17 +935,6 @@ private static TrackBundle parseTfhd( return trackBundle; } - private static @Nullable TrackBundle getTrackBundle( - SparseArray trackBundles, int trackId) { - if (trackBundles.size() == 1) { - // Ignore track id if there is only one track. This is either because we have a side-loaded - // track or to cope with non-matching track indices (see - // https://github.com/google/ExoPlayer/issues/4083). - return trackBundles.valueAt(/* index= */ 0); - } - return trackBundles.get(trackId); - } - /** * Parses a tfdt atom (defined in 14496-12). *