From 4ee02a27de5c39c32f48e55f969f244252fee4b0 Mon Sep 17 00:00:00 2001 From: kimvde Date: Fri, 11 Dec 2020 11:14:11 +0000 Subject: [PATCH] Mp4Extractor: add smta metadata to audio track This is needed for slomo audio flattening. PiperOrigin-RevId: 346965990 --- .../exoplayer2/MetadataRetrieverTest.java | 21 +++++++++++++++---- .../extractor/mp4/MetadataUtil.java | 11 +++++----- .../extractor/mp4/Mp4Extractor.java | 4 ++-- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/library/core/src/test/java/com/google/android/exoplayer2/MetadataRetrieverTest.java b/library/core/src/test/java/com/google/android/exoplayer2/MetadataRetrieverTest.java index e9a3e351d2..c54ee67535 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/MetadataRetrieverTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/MetadataRetrieverTest.java @@ -17,6 +17,7 @@ package com.google.android.exoplayer2; import static com.google.android.exoplayer2.MetadataRetriever.retrieveMetadata; +import static com.google.android.exoplayer2.metadata.mp4.MdtaMetadataEntry.KEY_ANDROID_CAPTURE_FPS; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; @@ -24,8 +25,10 @@ import android.content.Context; import android.net.Uri; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.android.exoplayer2.metadata.mp4.MdtaMetadataEntry; import com.google.android.exoplayer2.metadata.mp4.MotionPhotoMetadata; import com.google.android.exoplayer2.metadata.mp4.SlowMotionData; +import com.google.android.exoplayer2.metadata.mp4.SmtaMetadataEntry; import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.testutil.AutoAdvancingFakeClock; import com.google.android.exoplayer2.util.MimeTypes; @@ -141,6 +144,8 @@ public class MetadataRetrieverTest { public void retrieveMetadata_sefSlowMotion_outputsExpectedMetadata() throws Exception { MediaItem mediaItem = MediaItem.fromUri(Uri.parse("asset://android_asset/media/mp4/sample_sef_slow_motion.mp4")); + SmtaMetadataEntry expectedSmtaEntry = + new SmtaMetadataEntry(/* captureFrameRate= */ 240, /* svcTemporalLayerCount= */ 4); List segments = new ArrayList<>(); segments.add( new SlowMotionData.Segment( @@ -149,6 +154,12 @@ public class MetadataRetrieverTest { new SlowMotionData.Segment( /* startTimeMs= */ 1255, /* endTimeMs= */ 1970, /* speedDivisor= */ 8)); SlowMotionData expectedSlowMotionData = new SlowMotionData(segments); + MdtaMetadataEntry expectedMdtaEntry = + new MdtaMetadataEntry( + KEY_ANDROID_CAPTURE_FPS, + /* value= */ new byte[] {67, 112, 0, 0}, + /* localeIndicator= */ 0, + /* typeIndicator= */ 23); ListenableFuture trackGroupsFuture = retrieveMetadata(context, mediaItem, clock); @@ -156,11 +167,13 @@ public class MetadataRetrieverTest { assertThat(trackGroups.length).isEqualTo(2); // Video and audio // Audio - assertThat(trackGroups.get(0).getFormat(0).metadata.length()).isEqualTo(1); - assertThat(trackGroups.get(0).getFormat(0).metadata.get(0)).isEqualTo(expectedSlowMotionData); + assertThat(trackGroups.get(0).getFormat(0).metadata.length()).isEqualTo(2); + assertThat(trackGroups.get(0).getFormat(0).metadata.get(0)).isEqualTo(expectedSmtaEntry); + assertThat(trackGroups.get(0).getFormat(0).metadata.get(1)).isEqualTo(expectedSlowMotionData); // Video - assertThat(trackGroups.get(1).getFormat(0).metadata.length()) - .isEqualTo(3); // 2 Mdta entries and 1 slow motion entry. + assertThat(trackGroups.get(1).getFormat(0).metadata.length()).isEqualTo(3); + assertThat(trackGroups.get(1).getFormat(0).metadata.get(0)).isEqualTo(expectedMdtaEntry); + assertThat(trackGroups.get(1).getFormat(0).metadata.get(1)).isEqualTo(expectedSmtaEntry); assertThat(trackGroups.get(1).getFormat(0).metadata.get(2)).isEqualTo(expectedSlowMotionData); } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/MetadataUtil.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/MetadataUtil.java index 4b00aa6452..53ed281152 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/MetadataUtil.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/MetadataUtil.java @@ -31,6 +31,7 @@ import com.google.android.exoplayer2.metadata.id3.TextInformationFrame; import com.google.android.exoplayer2.metadata.mp4.MdtaMetadataEntry; import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.ParsableByteArray; +import org.checkerframework.checker.nullness.compatqual.NullableType; /** Utilities for handling metadata in MP4. */ /* package */ final class MetadataUtil { @@ -290,9 +291,8 @@ import com.google.android.exoplayer2.util.ParsableByteArray; int trackType, @Nullable Metadata udtaMetaMetadata, @Nullable Metadata mdtaMetadata, - @Nullable Metadata smtaMetadata, Format.Builder formatBuilder, - Metadata.Entry... additionalEntries) { + @NullableType Metadata... additionalMetadata) { Metadata formatMetadata = new Metadata(); if (trackType == C.TRACK_TYPE_AUDIO) { @@ -314,12 +314,11 @@ import com.google.android.exoplayer2.util.ParsableByteArray; } } } - if (smtaMetadata != null) { - formatMetadata = formatMetadata.copyWithAppendedEntriesFrom(smtaMetadata); - } } - formatMetadata = formatMetadata.copyWithAppendedEntries(additionalEntries); + for (Metadata metadata : additionalMetadata) { + formatMetadata = formatMetadata.copyWithAppendedEntriesFrom(metadata); + } if (formatMetadata.length() > 0) { formatBuilder.setMetadata(formatMetadata); diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/Mp4Extractor.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/Mp4Extractor.java index 506ceacaa5..b59729b58d 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/Mp4Extractor.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/Mp4Extractor.java @@ -525,9 +525,9 @@ public final class Mp4Extractor implements Extractor, SeekMap { track.type, udtaMetaMetadata, mdtaMetadata, - smtaMetadata, formatBuilder, - /* additionalEntries...= */ slowMotionMetadataEntries.toArray(new Metadata.Entry[0])); + smtaMetadata, + slowMotionMetadataEntries.isEmpty() ? null : new Metadata(slowMotionMetadataEntries)); mp4Track.trackOutput.format(formatBuilder.build()); if (track.type == C.TRACK_TYPE_VIDEO && firstVideoTrackIndex == C.INDEX_UNSET) {