diff --git a/libraries/extractor/src/test/java/androidx/media3/extractor/mp4/Mp4ExtractorTest.java b/libraries/extractor/src/test/java/androidx/media3/extractor/mp4/Mp4ExtractorTest.java new file mode 100644 index 0000000000..f4f0f1132b --- /dev/null +++ b/libraries/extractor/src/test/java/androidx/media3/extractor/mp4/Mp4ExtractorTest.java @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package androidx.media3.extractor.mp4; + +import androidx.media3.test.utils.ExtractorAsserts; +import com.google.common.collect.ImmutableList; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.ParameterizedRobolectricTestRunner; +import org.robolectric.ParameterizedRobolectricTestRunner.Parameter; +import org.robolectric.ParameterizedRobolectricTestRunner.Parameters; + +/** Tests for {@link Mp4Extractor}. */ +@RunWith(ParameterizedRobolectricTestRunner.class) +public final class Mp4ExtractorTest { + + @Parameters(name = "{0}") + public static ImmutableList params() { + return ExtractorAsserts.configs(); + } + + @Parameter public ExtractorAsserts.SimulationConfig simulationConfig; + + @Test + public void mp4Sample() throws Exception { + ExtractorAsserts.assertBehavior(Mp4Extractor::new, "media/mp4/sample.mp4", simulationConfig); + } + + @Test + public void mp4SampleWithSlowMotionMetadata() throws Exception { + ExtractorAsserts.assertBehavior( + Mp4Extractor::new, "media/mp4/sample_android_slow_motion.mp4", simulationConfig); + } + + /** + * Test case for https://github.com/google/ExoPlayer/issues/6774. The sample file contains an mdat + * atom whose size indicates that it extends 8 bytes beyond the end of the file. + */ + @Test + public void mp4SampleWithMdatTooLong() throws Exception { + ExtractorAsserts.assertBehavior( + Mp4Extractor::new, "media/mp4/sample_mdat_too_long.mp4", simulationConfig); + } + + @Test + public void mp4SampleWithAc3Track() throws Exception { + ExtractorAsserts.assertBehavior( + Mp4Extractor::new, "media/mp4/sample_ac3.mp4", simulationConfig); + } + + @Test + public void mp4SampleWithAc4Track() throws Exception { + ExtractorAsserts.assertBehavior( + Mp4Extractor::new, "media/mp4/sample_ac4.mp4", simulationConfig); + } + + @Test + public void mp4SampleWithAc4Level4Track() throws Exception { + ExtractorAsserts.assertBehavior( + Mp4Extractor::new, "media/mp4/sample_ac4_level4.mp4", simulationConfig); + } + + @Test + public void mp4SampleWithEac3Track() throws Exception { + ExtractorAsserts.assertBehavior( + Mp4Extractor::new, "media/mp4/sample_eac3.mp4", simulationConfig); + } + + @Test + public void mp4SampleWithEac3jocTrack() throws Exception { + ExtractorAsserts.assertBehavior( + Mp4Extractor::new, "media/mp4/sample_eac3joc.mp4", simulationConfig); + } + + @Test + public void mp4SampleWithOpusTrack() throws Exception { + ExtractorAsserts.assertBehavior( + Mp4Extractor::new, "media/mp4/sample_opus.mp4", simulationConfig); + } + + @Test + public void mp4SampleWithMha1Track() throws Exception { + ExtractorAsserts.assertBehavior( + Mp4Extractor::new, "media/mp4/sample_mpegh_mha1.mp4", simulationConfig); + } + + @Test + public void mp4SampleWithMhm1Track() throws Exception { + ExtractorAsserts.assertBehavior( + Mp4Extractor::new, "media/mp4/sample_mpegh_mhm1.mp4", simulationConfig); + } + + @Test + public void mp4SampleWithColorInfo() throws Exception { + ExtractorAsserts.assertBehavior( + Mp4Extractor::new, "media/mp4/sample_with_color_info.mp4", simulationConfig); + } + + /** + * Test case for https://github.com/google/ExoPlayer/issues/9332. The file contains a colr box + * with size=18 and type=nclx. This is not valid according to the spec (size must be 19), but + * files like this exist in the wild. + */ + @Test + public void mp4Sample18ByteNclxColr() throws Exception { + ExtractorAsserts.assertBehavior( + Mp4Extractor::new, "media/mp4/sample_18byte_nclx_colr.mp4", simulationConfig); + } + + @Test + public void mp4SampleWithDolbyTrueHDTrack() throws Exception { + ExtractorAsserts.assertBehavior( + Mp4Extractor::new, "media/mp4/sample_dthd.mp4", simulationConfig); + } + + @Test + public void mp4SampleWithColrMdcvAndClli() throws Exception { + ExtractorAsserts.assertBehavior( + Mp4Extractor::new, "media/mp4/sample_with_colr_mdcv_and_clli.mp4", simulationConfig); + } + + /** Test case for supporting original QuickTime specification [Internal: b/297137302]. */ + @Test + public void mp4SampleWithOriginalQuicktimeSpecification() throws Exception { + ExtractorAsserts.assertBehavior( + Mp4Extractor::new, + "media/mp4/sample_with_original_quicktime_specification.mov", + simulationConfig); + } + + @Test + public void mp4SampleWithAv1c() throws Exception { + ExtractorAsserts.assertBehavior( + Mp4Extractor::new, "media/mp4/sample_with_av1c.mp4", simulationConfig); + } +} diff --git a/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4.mp4.0.dump b/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4.mp4.0.dump new file mode 100644 index 0000000000..90cd9d402c --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4.mp4.0.dump @@ -0,0 +1,100 @@ +seekMap: + isSeekable = true + duration = 853333 + getPosition(0) = [[timeUs=0, position=665]] + getPosition(1) = [[timeUs=1, position=665]] + getPosition(426666) = [[timeUs=426666, position=81945]] + getPosition(853333) = [[timeUs=853333, position=81945]] +numberOfTracks = 1 +track 0: + total output bytes = 162700 + sample count = 20 + format 0: + id = 1 + sampleMimeType = audio/ac4 + maxInputSize = 8158 + channelCount = 21 + sampleRate = 48000 + language = und + metadata = entries=[Mp4Timestamp: creation time=3785281997, modification time=3785281997, timescale=600] + sample 0: + time = 0 + flags = 1 + data = length 8135, hash B524F88E + sample 1: + time = 42666 + flags = 0 + data = length 8135, hash FB80C2FB + sample 2: + time = 85333 + flags = 0 + data = length 8135, hash 907C0C31 + sample 3: + time = 128000 + flags = 0 + data = length 8135, hash FDFBD32B + sample 4: + time = 170666 + flags = 0 + data = length 8135, hash 6CAF0549 + sample 5: + time = 213333 + flags = 0 + data = length 8135, hash F5CA1C9A + sample 6: + time = 256000 + flags = 0 + data = length 8135, hash B1B5160D + sample 7: + time = 298666 + flags = 0 + data = length 8135, hash 9E923B3F + sample 8: + time = 341333 + flags = 0 + data = length 8135, hash B1C0BB1F + sample 9: + time = 384000 + flags = 0 + data = length 8135, hash 56F65A03 + sample 10: + time = 426666 + flags = 1 + data = length 8135, hash D07FA9A1 + sample 11: + time = 469333 + flags = 0 + data = length 8135, hash EF26FDDE + sample 12: + time = 512000 + flags = 0 + data = length 8135, hash 8946EEEB + sample 13: + time = 554666 + flags = 0 + data = length 8135, hash AC2E4C99 + sample 14: + time = 597333 + flags = 0 + data = length 8135, hash B63A1D8 + sample 15: + time = 640000 + flags = 0 + data = length 8135, hash 23119F0F + sample 16: + time = 682666 + flags = 0 + data = length 8135, hash 507972CA + sample 17: + time = 725333 + flags = 0 + data = length 8135, hash E574BC00 + sample 18: + time = 768000 + flags = 0 + data = length 8135, hash 52F482FA + sample 19: + time = 810666 + flags = 536870912 + data = length 8135, hash C1A7B518 +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4.mp4.1.dump b/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4.mp4.1.dump new file mode 100644 index 0000000000..90cd9d402c --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4.mp4.1.dump @@ -0,0 +1,100 @@ +seekMap: + isSeekable = true + duration = 853333 + getPosition(0) = [[timeUs=0, position=665]] + getPosition(1) = [[timeUs=1, position=665]] + getPosition(426666) = [[timeUs=426666, position=81945]] + getPosition(853333) = [[timeUs=853333, position=81945]] +numberOfTracks = 1 +track 0: + total output bytes = 162700 + sample count = 20 + format 0: + id = 1 + sampleMimeType = audio/ac4 + maxInputSize = 8158 + channelCount = 21 + sampleRate = 48000 + language = und + metadata = entries=[Mp4Timestamp: creation time=3785281997, modification time=3785281997, timescale=600] + sample 0: + time = 0 + flags = 1 + data = length 8135, hash B524F88E + sample 1: + time = 42666 + flags = 0 + data = length 8135, hash FB80C2FB + sample 2: + time = 85333 + flags = 0 + data = length 8135, hash 907C0C31 + sample 3: + time = 128000 + flags = 0 + data = length 8135, hash FDFBD32B + sample 4: + time = 170666 + flags = 0 + data = length 8135, hash 6CAF0549 + sample 5: + time = 213333 + flags = 0 + data = length 8135, hash F5CA1C9A + sample 6: + time = 256000 + flags = 0 + data = length 8135, hash B1B5160D + sample 7: + time = 298666 + flags = 0 + data = length 8135, hash 9E923B3F + sample 8: + time = 341333 + flags = 0 + data = length 8135, hash B1C0BB1F + sample 9: + time = 384000 + flags = 0 + data = length 8135, hash 56F65A03 + sample 10: + time = 426666 + flags = 1 + data = length 8135, hash D07FA9A1 + sample 11: + time = 469333 + flags = 0 + data = length 8135, hash EF26FDDE + sample 12: + time = 512000 + flags = 0 + data = length 8135, hash 8946EEEB + sample 13: + time = 554666 + flags = 0 + data = length 8135, hash AC2E4C99 + sample 14: + time = 597333 + flags = 0 + data = length 8135, hash B63A1D8 + sample 15: + time = 640000 + flags = 0 + data = length 8135, hash 23119F0F + sample 16: + time = 682666 + flags = 0 + data = length 8135, hash 507972CA + sample 17: + time = 725333 + flags = 0 + data = length 8135, hash E574BC00 + sample 18: + time = 768000 + flags = 0 + data = length 8135, hash 52F482FA + sample 19: + time = 810666 + flags = 536870912 + data = length 8135, hash C1A7B518 +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4.mp4.2.dump b/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4.mp4.2.dump new file mode 100644 index 0000000000..5f9737eed8 --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4.mp4.2.dump @@ -0,0 +1,60 @@ +seekMap: + isSeekable = true + duration = 853333 + getPosition(0) = [[timeUs=0, position=665]] + getPosition(1) = [[timeUs=1, position=665]] + getPosition(426666) = [[timeUs=426666, position=81945]] + getPosition(853333) = [[timeUs=853333, position=81945]] +numberOfTracks = 1 +track 0: + total output bytes = 81350 + sample count = 10 + format 0: + id = 1 + sampleMimeType = audio/ac4 + maxInputSize = 8158 + channelCount = 21 + sampleRate = 48000 + language = und + metadata = entries=[Mp4Timestamp: creation time=3785281997, modification time=3785281997, timescale=600] + sample 0: + time = 426666 + flags = 1 + data = length 8135, hash D07FA9A1 + sample 1: + time = 469333 + flags = 0 + data = length 8135, hash EF26FDDE + sample 2: + time = 512000 + flags = 0 + data = length 8135, hash 8946EEEB + sample 3: + time = 554666 + flags = 0 + data = length 8135, hash AC2E4C99 + sample 4: + time = 597333 + flags = 0 + data = length 8135, hash B63A1D8 + sample 5: + time = 640000 + flags = 0 + data = length 8135, hash 23119F0F + sample 6: + time = 682666 + flags = 0 + data = length 8135, hash 507972CA + sample 7: + time = 725333 + flags = 0 + data = length 8135, hash E574BC00 + sample 8: + time = 768000 + flags = 0 + data = length 8135, hash 52F482FA + sample 9: + time = 810666 + flags = 536870912 + data = length 8135, hash C1A7B518 +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4.mp4.3.dump b/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4.mp4.3.dump new file mode 100644 index 0000000000..5f9737eed8 --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4.mp4.3.dump @@ -0,0 +1,60 @@ +seekMap: + isSeekable = true + duration = 853333 + getPosition(0) = [[timeUs=0, position=665]] + getPosition(1) = [[timeUs=1, position=665]] + getPosition(426666) = [[timeUs=426666, position=81945]] + getPosition(853333) = [[timeUs=853333, position=81945]] +numberOfTracks = 1 +track 0: + total output bytes = 81350 + sample count = 10 + format 0: + id = 1 + sampleMimeType = audio/ac4 + maxInputSize = 8158 + channelCount = 21 + sampleRate = 48000 + language = und + metadata = entries=[Mp4Timestamp: creation time=3785281997, modification time=3785281997, timescale=600] + sample 0: + time = 426666 + flags = 1 + data = length 8135, hash D07FA9A1 + sample 1: + time = 469333 + flags = 0 + data = length 8135, hash EF26FDDE + sample 2: + time = 512000 + flags = 0 + data = length 8135, hash 8946EEEB + sample 3: + time = 554666 + flags = 0 + data = length 8135, hash AC2E4C99 + sample 4: + time = 597333 + flags = 0 + data = length 8135, hash B63A1D8 + sample 5: + time = 640000 + flags = 0 + data = length 8135, hash 23119F0F + sample 6: + time = 682666 + flags = 0 + data = length 8135, hash 507972CA + sample 7: + time = 725333 + flags = 0 + data = length 8135, hash E574BC00 + sample 8: + time = 768000 + flags = 0 + data = length 8135, hash 52F482FA + sample 9: + time = 810666 + flags = 536870912 + data = length 8135, hash C1A7B518 +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4.mp4.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4.mp4.unknown_length.dump new file mode 100644 index 0000000000..90cd9d402c --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4.mp4.unknown_length.dump @@ -0,0 +1,100 @@ +seekMap: + isSeekable = true + duration = 853333 + getPosition(0) = [[timeUs=0, position=665]] + getPosition(1) = [[timeUs=1, position=665]] + getPosition(426666) = [[timeUs=426666, position=81945]] + getPosition(853333) = [[timeUs=853333, position=81945]] +numberOfTracks = 1 +track 0: + total output bytes = 162700 + sample count = 20 + format 0: + id = 1 + sampleMimeType = audio/ac4 + maxInputSize = 8158 + channelCount = 21 + sampleRate = 48000 + language = und + metadata = entries=[Mp4Timestamp: creation time=3785281997, modification time=3785281997, timescale=600] + sample 0: + time = 0 + flags = 1 + data = length 8135, hash B524F88E + sample 1: + time = 42666 + flags = 0 + data = length 8135, hash FB80C2FB + sample 2: + time = 85333 + flags = 0 + data = length 8135, hash 907C0C31 + sample 3: + time = 128000 + flags = 0 + data = length 8135, hash FDFBD32B + sample 4: + time = 170666 + flags = 0 + data = length 8135, hash 6CAF0549 + sample 5: + time = 213333 + flags = 0 + data = length 8135, hash F5CA1C9A + sample 6: + time = 256000 + flags = 0 + data = length 8135, hash B1B5160D + sample 7: + time = 298666 + flags = 0 + data = length 8135, hash 9E923B3F + sample 8: + time = 341333 + flags = 0 + data = length 8135, hash B1C0BB1F + sample 9: + time = 384000 + flags = 0 + data = length 8135, hash 56F65A03 + sample 10: + time = 426666 + flags = 1 + data = length 8135, hash D07FA9A1 + sample 11: + time = 469333 + flags = 0 + data = length 8135, hash EF26FDDE + sample 12: + time = 512000 + flags = 0 + data = length 8135, hash 8946EEEB + sample 13: + time = 554666 + flags = 0 + data = length 8135, hash AC2E4C99 + sample 14: + time = 597333 + flags = 0 + data = length 8135, hash B63A1D8 + sample 15: + time = 640000 + flags = 0 + data = length 8135, hash 23119F0F + sample 16: + time = 682666 + flags = 0 + data = length 8135, hash 507972CA + sample 17: + time = 725333 + flags = 0 + data = length 8135, hash E574BC00 + sample 18: + time = 768000 + flags = 0 + data = length 8135, hash 52F482FA + sample 19: + time = 810666 + flags = 536870912 + data = length 8135, hash C1A7B518 +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/media/mp4/sample_ac4_level4.mp4 b/libraries/test_data/src/test/assets/media/mp4/sample_ac4_level4.mp4 new file mode 100644 index 0000000000..7e110d301e Binary files /dev/null and b/libraries/test_data/src/test/assets/media/mp4/sample_ac4_level4.mp4 differ