From 1381c92d7686c72eb7b830c21f2746b16c912ff1 Mon Sep 17 00:00:00 2001 From: ybai001 Date: Wed, 25 Sep 2024 09:17:50 +0800 Subject: [PATCH 1/4] Add AC-4 channel configuration support in DASH --- .../dash/manifest/DashManifestParser.java | 63 ++++++++++- ...agmentedMp4ExtractorParameterizedTest.java | 9 ++ .../sample_ac4_level4_fragmented.mp4.0.dump | 98 ++++++++++++++++++ .../sample_ac4_level4_fragmented.mp4.1.dump | 98 ++++++++++++++++++ .../sample_ac4_level4_fragmented.mp4.2.dump | 58 +++++++++++ .../sample_ac4_level4_fragmented.mp4.3.dump | 58 +++++++++++ ..._level4_fragmented.mp4.unknown_length.dump | 98 ++++++++++++++++++ .../mp4/sample_ac4_level4_fragmented.mp4 | Bin 0 -> 163552 bytes 8 files changed, 479 insertions(+), 3 deletions(-) create mode 100644 libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.0.dump create mode 100644 libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.1.dump create mode 100644 libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.2.dump create mode 100644 libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.3.dump create mode 100644 libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.unknown_length.dump create mode 100644 libraries/test_data/src/test/assets/media/mp4/sample_ac4_level4_fragmented.mp4 diff --git a/libraries/exoplayer_dash/src/main/java/androidx/media3/exoplayer/dash/manifest/DashManifestParser.java b/libraries/exoplayer_dash/src/main/java/androidx/media3/exoplayer/dash/manifest/DashManifestParser.java index 8caff5bd922..ef798c910c4 100644 --- a/libraries/exoplayer_dash/src/main/java/androidx/media3/exoplayer/dash/manifest/DashManifestParser.java +++ b/libraries/exoplayer_dash/src/main/java/androidx/media3/exoplayer/dash/manifest/DashManifestParser.java @@ -77,6 +77,17 @@ public class DashManifestParser extends DefaultHandler private static final Pattern CEA_708_ACCESSIBILITY_PATTERN = Pattern.compile("([1-9]|[1-5][0-9]|6[0-3])=.*"); + /** + * Maps the value attribute of an AudioChannelConfiguration with schemeIdUri + * "tag:dolby.com,2015:dash:audio_channel_configuration:2015", as defined by ETSI TS 103 190-2 + * v1.2.1 clause G.3. Table A.27 in ETSI TS 103 190-2 v1.2.1 defines the speaker counts of each + * speaker group index, numbers will be counted only when respective indexes present. + */ + private static final int[] DOLBY_AC4_CHANNEL_CONFIGURATION_MAPPING = + new int[] { + 2, 1, 2, 2, 2, 2, 1, 2, 2, 1, 1, 1, 1, 2, 1, 1, 2, 2, 2 + }; + /** * Maps the value attribute of an AudioChannelConfiguration with schemeIdUri * "urn:mpeg:mpegB:cicp:ChannelConfiguration", as defined by ISO 23001-8 clause 8.1, to a channel @@ -441,7 +452,7 @@ protected AdaptationSet parseAdaptationSet( } else if (XmlPullParserUtil.isStartTag(xpp, "Role")) { roleDescriptors.add(parseDescriptor(xpp, "Role")); } else if (XmlPullParserUtil.isStartTag(xpp, "AudioChannelConfiguration")) { - audioChannels = parseAudioChannelConfiguration(xpp); + audioChannels = parseAudioChannelConfiguration(xpp, codecs); } else if (XmlPullParserUtil.isStartTag(xpp, "Accessibility")) { accessibilityDescriptors.add(parseDescriptor(xpp, "Accessibility")); } else if (XmlPullParserUtil.isStartTag(xpp, "EssentialProperty")) { @@ -720,7 +731,7 @@ protected RepresentationInfo parseRepresentation( } baseUrls.addAll(parseBaseUrl(xpp, parentBaseUrls, dvbProfileDeclared)); } else if (XmlPullParserUtil.isStartTag(xpp, "AudioChannelConfiguration")) { - audioChannels = parseAudioChannelConfiguration(xpp); + audioChannels = parseAudioChannelConfiguration(xpp, codecs); } else if (XmlPullParserUtil.isStartTag(xpp, "SegmentBase")) { segmentBase = parseSegmentBase(xpp, (SingleSegmentBase) segmentBase); } else if (XmlPullParserUtil.isStartTag(xpp, "SegmentList")) { @@ -1487,7 +1498,7 @@ protected long parseAvailabilityTimeOffsetUs( // AudioChannelConfiguration parsing. - protected int parseAudioChannelConfiguration(XmlPullParser xpp) + protected int parseAudioChannelConfiguration(XmlPullParser xpp, String codecs) throws XmlPullParserException, IOException { String schemeIdUri = parseString(xpp, "schemeIdUri", null); int audioChannels; @@ -1509,6 +1520,9 @@ protected int parseAudioChannelConfiguration(XmlPullParser xpp) case "urn:dolby:dash:audio_channel_configuration:2011": audioChannels = parseDolbyChannelConfiguration(xpp); break; + case "tag:dolby.com,2015:dash:audio_channel_configuration:2015": + audioChannels = parseDolbyAC4ChannelConfiguration(xpp, codecs); + break; default: audioChannels = Format.NO_VALUE; break; @@ -2043,6 +2057,49 @@ protected static int parseDolbyChannelConfiguration(XmlPullParser xpp) { } } + /** + * Parses the number of channels from the value attribute of an AudioChannelConfiguration with + * schemeIdUri "tag:dolby.com,2015:dash:audio_channel_configuration:2015" as defined by table A.27 + * in ETSI TS 103 190-2 v1.2.1. + * + * @param xpp The parser from which to read. + * @return The parsed number of channels, or {@link Format#NO_VALUE} if the channel count could + * not be parsed. + */ + protected static int parseDolbyAC4ChannelConfiguration(XmlPullParser xpp, String codecs) { + @Nullable String value = xpp.getAttributeValue(null, "value"); + // The value attribute must be set to a six-digit uppercase hexadecimal + if (value == null || value.length() != 6) { + return Format.NO_VALUE; + } + final int DOLBY_AC4_OBJECT_BASED_AUDIO_STREAM = 0x800000; + final int ac4ChannelMask = Integer.parseInt(value, /* radix= */ 16); + if ((ac4ChannelMask & DOLBY_AC4_OBJECT_BASED_AUDIO_STREAM) == + DOLBY_AC4_OBJECT_BASED_AUDIO_STREAM) { + // object-based audio content + String[] codecList = Util.splitCodecs(codecs); + // The AC-4 codec string format is "ac-4.xx.yy.zz", where zz is presentation level + final String AC4_PRESENTATION_LEVEL3 = "03"; + final String AC4_PRESENTATION_LEVEL4 = "04"; + String[] parts = Ascii.toLowerCase(codecList[0].trim()).split("\\."); + if (parts.length == 4 && parts[0].equals("ac-4")) { + if (parts[3].equals(AC4_PRESENTATION_LEVEL3)) { + return 18; // AC-4 Level 3 object-based content is mapped to 17.1 channels + } else if (parts[3].equals(AC4_PRESENTATION_LEVEL4)) { + return 21; // AC-4 Level 4 object-based content is mapped to 20.1 channels + } + } + return Format.NO_VALUE; + } + // channel-based audio content + // bits 0...18 indicate the presence of individual channel groups + int channelCount = 0; + for (int i = 0; i < DOLBY_AC4_CHANNEL_CONFIGURATION_MAPPING.length; i++) { + channelCount += ((ac4ChannelMask >> i) & 0x1) * DOLBY_AC4_CHANNEL_CONFIGURATION_MAPPING[i]; + } + return channelCount == 0 ? Format.NO_VALUE : channelCount; + } + protected static long parseLastSegmentNumberSupplementalProperty( List supplementalProperties) { for (int i = 0; i < supplementalProperties.size(); i++) { diff --git a/libraries/extractor/src/test/java/androidx/media3/extractor/mp4/FragmentedMp4ExtractorParameterizedTest.java b/libraries/extractor/src/test/java/androidx/media3/extractor/mp4/FragmentedMp4ExtractorParameterizedTest.java index 9d324eff241..c6790d7e639 100644 --- a/libraries/extractor/src/test/java/androidx/media3/extractor/mp4/FragmentedMp4ExtractorParameterizedTest.java +++ b/libraries/extractor/src/test/java/androidx/media3/extractor/mp4/FragmentedMp4ExtractorParameterizedTest.java @@ -110,6 +110,15 @@ public void sampleWithAc4Track() throws Exception { /* closedCaptionFormats= */ ImmutableList.of(), "media/mp4/sample_ac4_fragmented.mp4"); } + @Test + public void sampleWithAc4Level4Track() throws Exception { + ExtractorAsserts.assertBehavior( + getExtractorFactory( + /* closedCaptionFormats= */ ImmutableList.of(), subtitlesParsedDuringExtraction), + "media/mp4/sample_ac4_level4_fragmented.mp4", + simulationConfig); + } + @Test public void sampleWithProtectedAc4Track() throws Exception { assertExtractorBehavior( diff --git a/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.0.dump b/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.0.dump new file mode 100644 index 00000000000..a535bb7059e --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.0.dump @@ -0,0 +1,98 @@ +seekMap: + isSeekable = true + duration = 853333 + getPosition(0) = [[timeUs=0, position=669]] + getPosition(1) = [[timeUs=0, position=669]] + getPosition(426666) = [[timeUs=0, position=669]] + getPosition(853333) = [[timeUs=0, position=669]] +numberOfTracks = 1 +track 0: + total output bytes = 162700 + sample count = 20 + format 0: + id = 1 + sampleMimeType = audio/ac4 + channelCount = 21 + sampleRate = 48000 + language = und + 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 = 0 + data = length 8135, hash C1A7B518 +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.1.dump b/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.1.dump new file mode 100644 index 00000000000..a535bb7059e --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.1.dump @@ -0,0 +1,98 @@ +seekMap: + isSeekable = true + duration = 853333 + getPosition(0) = [[timeUs=0, position=669]] + getPosition(1) = [[timeUs=0, position=669]] + getPosition(426666) = [[timeUs=0, position=669]] + getPosition(853333) = [[timeUs=0, position=669]] +numberOfTracks = 1 +track 0: + total output bytes = 162700 + sample count = 20 + format 0: + id = 1 + sampleMimeType = audio/ac4 + channelCount = 21 + sampleRate = 48000 + language = und + 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 = 0 + data = length 8135, hash C1A7B518 +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.2.dump b/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.2.dump new file mode 100644 index 00000000000..12d737fcc09 --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.2.dump @@ -0,0 +1,58 @@ +seekMap: + isSeekable = true + duration = 853333 + getPosition(0) = [[timeUs=0, position=669]] + getPosition(1) = [[timeUs=0, position=669]] + getPosition(426666) = [[timeUs=0, position=669]] + getPosition(853333) = [[timeUs=0, position=669]] +numberOfTracks = 1 +track 0: + total output bytes = 81350 + sample count = 10 + format 0: + id = 1 + sampleMimeType = audio/ac4 + channelCount = 21 + sampleRate = 48000 + language = und + 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 = 0 + data = length 8135, hash C1A7B518 +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.3.dump b/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.3.dump new file mode 100644 index 00000000000..12d737fcc09 --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.3.dump @@ -0,0 +1,58 @@ +seekMap: + isSeekable = true + duration = 853333 + getPosition(0) = [[timeUs=0, position=669]] + getPosition(1) = [[timeUs=0, position=669]] + getPosition(426666) = [[timeUs=0, position=669]] + getPosition(853333) = [[timeUs=0, position=669]] +numberOfTracks = 1 +track 0: + total output bytes = 81350 + sample count = 10 + format 0: + id = 1 + sampleMimeType = audio/ac4 + channelCount = 21 + sampleRate = 48000 + language = und + 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 = 0 + data = length 8135, hash C1A7B518 +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.unknown_length.dump new file mode 100644 index 00000000000..a535bb7059e --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.unknown_length.dump @@ -0,0 +1,98 @@ +seekMap: + isSeekable = true + duration = 853333 + getPosition(0) = [[timeUs=0, position=669]] + getPosition(1) = [[timeUs=0, position=669]] + getPosition(426666) = [[timeUs=0, position=669]] + getPosition(853333) = [[timeUs=0, position=669]] +numberOfTracks = 1 +track 0: + total output bytes = 162700 + sample count = 20 + format 0: + id = 1 + sampleMimeType = audio/ac4 + channelCount = 21 + sampleRate = 48000 + language = und + 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 = 0 + data = length 8135, hash C1A7B518 +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/media/mp4/sample_ac4_level4_fragmented.mp4 b/libraries/test_data/src/test/assets/media/mp4/sample_ac4_level4_fragmented.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..e0e505a43aaf62c1c66bb7632395c697bb0741c1 GIT binary patch literal 163552 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 literal 0 HcmV?d00001 From 7b3effb871b67abfd8c7f10df4a43946e3a791fc Mon Sep 17 00:00:00 2001 From: ybai001 Date: Mon, 18 Nov 2024 10:29:40 +0800 Subject: [PATCH 2/4] Update test code based on the latest code structure --- .../exoplayer/e2etest/Mp4PlaybackTest.java | 1 + ...agmentedMp4ExtractorParameterizedTest.java | 7 +- ...ding_within_gop_sample_dependencies.0.dump | 98 +++++++++++++++++++ ...ding_within_gop_sample_dependencies.1.dump | 98 +++++++++++++++++++ ...ding_within_gop_sample_dependencies.2.dump | 58 +++++++++++ ...ding_within_gop_sample_dependencies.3.dump | 58 +++++++++++ ...op_sample_dependencies.unknown_length.dump | 98 +++++++++++++++++++ 7 files changed, 413 insertions(+), 5 deletions(-) create mode 100644 libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.reading_within_gop_sample_dependencies.0.dump create mode 100644 libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.reading_within_gop_sample_dependencies.1.dump create mode 100644 libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.reading_within_gop_sample_dependencies.2.dump create mode 100644 libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.reading_within_gop_sample_dependencies.3.dump create mode 100644 libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.reading_within_gop_sample_dependencies.unknown_length.dump diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/Mp4PlaybackTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/Mp4PlaybackTest.java index 95f84904e1d..fed265301c7 100644 --- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/Mp4PlaybackTest.java +++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/Mp4PlaybackTest.java @@ -50,6 +50,7 @@ public static ImmutableList mediaSamples() { "sample_ac3_fragmented.mp4", "sample_ac3.mp4", "sample_ac4_fragmented.mp4", + "sample_ac4_level4_fragmented.mp4", "sample_ac4.mp4", "sample_android_slow_motion.mp4", "sample_eac3_fragmented.mp4", diff --git a/libraries/extractor/src/test/java/androidx/media3/extractor/mp4/FragmentedMp4ExtractorParameterizedTest.java b/libraries/extractor/src/test/java/androidx/media3/extractor/mp4/FragmentedMp4ExtractorParameterizedTest.java index c6790d7e639..ad823b2ed63 100644 --- a/libraries/extractor/src/test/java/androidx/media3/extractor/mp4/FragmentedMp4ExtractorParameterizedTest.java +++ b/libraries/extractor/src/test/java/androidx/media3/extractor/mp4/FragmentedMp4ExtractorParameterizedTest.java @@ -112,11 +112,8 @@ public void sampleWithAc4Track() throws Exception { @Test public void sampleWithAc4Level4Track() throws Exception { - ExtractorAsserts.assertBehavior( - getExtractorFactory( - /* closedCaptionFormats= */ ImmutableList.of(), subtitlesParsedDuringExtraction), - "media/mp4/sample_ac4_level4_fragmented.mp4", - simulationConfig); + assertExtractorBehavior( + /* closedCaptionFormats= */ ImmutableList.of(), "media/mp4/sample_ac4_level4_fragmented.mp4"); } @Test diff --git a/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.reading_within_gop_sample_dependencies.0.dump b/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.reading_within_gop_sample_dependencies.0.dump new file mode 100644 index 00000000000..a535bb7059e --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.reading_within_gop_sample_dependencies.0.dump @@ -0,0 +1,98 @@ +seekMap: + isSeekable = true + duration = 853333 + getPosition(0) = [[timeUs=0, position=669]] + getPosition(1) = [[timeUs=0, position=669]] + getPosition(426666) = [[timeUs=0, position=669]] + getPosition(853333) = [[timeUs=0, position=669]] +numberOfTracks = 1 +track 0: + total output bytes = 162700 + sample count = 20 + format 0: + id = 1 + sampleMimeType = audio/ac4 + channelCount = 21 + sampleRate = 48000 + language = und + 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 = 0 + data = length 8135, hash C1A7B518 +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.reading_within_gop_sample_dependencies.1.dump b/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.reading_within_gop_sample_dependencies.1.dump new file mode 100644 index 00000000000..a535bb7059e --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.reading_within_gop_sample_dependencies.1.dump @@ -0,0 +1,98 @@ +seekMap: + isSeekable = true + duration = 853333 + getPosition(0) = [[timeUs=0, position=669]] + getPosition(1) = [[timeUs=0, position=669]] + getPosition(426666) = [[timeUs=0, position=669]] + getPosition(853333) = [[timeUs=0, position=669]] +numberOfTracks = 1 +track 0: + total output bytes = 162700 + sample count = 20 + format 0: + id = 1 + sampleMimeType = audio/ac4 + channelCount = 21 + sampleRate = 48000 + language = und + 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 = 0 + data = length 8135, hash C1A7B518 +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.reading_within_gop_sample_dependencies.2.dump b/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.reading_within_gop_sample_dependencies.2.dump new file mode 100644 index 00000000000..12d737fcc09 --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.reading_within_gop_sample_dependencies.2.dump @@ -0,0 +1,58 @@ +seekMap: + isSeekable = true + duration = 853333 + getPosition(0) = [[timeUs=0, position=669]] + getPosition(1) = [[timeUs=0, position=669]] + getPosition(426666) = [[timeUs=0, position=669]] + getPosition(853333) = [[timeUs=0, position=669]] +numberOfTracks = 1 +track 0: + total output bytes = 81350 + sample count = 10 + format 0: + id = 1 + sampleMimeType = audio/ac4 + channelCount = 21 + sampleRate = 48000 + language = und + 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 = 0 + data = length 8135, hash C1A7B518 +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.reading_within_gop_sample_dependencies.3.dump b/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.reading_within_gop_sample_dependencies.3.dump new file mode 100644 index 00000000000..12d737fcc09 --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.reading_within_gop_sample_dependencies.3.dump @@ -0,0 +1,58 @@ +seekMap: + isSeekable = true + duration = 853333 + getPosition(0) = [[timeUs=0, position=669]] + getPosition(1) = [[timeUs=0, position=669]] + getPosition(426666) = [[timeUs=0, position=669]] + getPosition(853333) = [[timeUs=0, position=669]] +numberOfTracks = 1 +track 0: + total output bytes = 81350 + sample count = 10 + format 0: + id = 1 + sampleMimeType = audio/ac4 + channelCount = 21 + sampleRate = 48000 + language = und + 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 = 0 + data = length 8135, hash C1A7B518 +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.reading_within_gop_sample_dependencies.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.reading_within_gop_sample_dependencies.unknown_length.dump new file mode 100644 index 00000000000..a535bb7059e --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp4/sample_ac4_level4_fragmented.mp4.reading_within_gop_sample_dependencies.unknown_length.dump @@ -0,0 +1,98 @@ +seekMap: + isSeekable = true + duration = 853333 + getPosition(0) = [[timeUs=0, position=669]] + getPosition(1) = [[timeUs=0, position=669]] + getPosition(426666) = [[timeUs=0, position=669]] + getPosition(853333) = [[timeUs=0, position=669]] +numberOfTracks = 1 +track 0: + total output bytes = 162700 + sample count = 20 + format 0: + id = 1 + sampleMimeType = audio/ac4 + channelCount = 21 + sampleRate = 48000 + language = und + 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 = 0 + data = length 8135, hash C1A7B518 +tracksEnded = true From 7c0b1d8f1245da81cdc8f2e05947743e5825de82 Mon Sep 17 00:00:00 2001 From: ybai001 Date: Wed, 20 Nov 2024 13:45:11 +0800 Subject: [PATCH 3/4] Remove sample_ac4_level4_fragmented.mp4 from Mp4PlaybackTest.java --- .../java/androidx/media3/exoplayer/e2etest/Mp4PlaybackTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/Mp4PlaybackTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/Mp4PlaybackTest.java index fed265301c7..95f84904e1d 100644 --- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/Mp4PlaybackTest.java +++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/Mp4PlaybackTest.java @@ -50,7 +50,6 @@ public static ImmutableList mediaSamples() { "sample_ac3_fragmented.mp4", "sample_ac3.mp4", "sample_ac4_fragmented.mp4", - "sample_ac4_level4_fragmented.mp4", "sample_ac4.mp4", "sample_android_slow_motion.mp4", "sample_eac3_fragmented.mp4", From 11cb83623da27d55f0c7c8ba82ecb07953839e3d Mon Sep 17 00:00:00 2001 From: ybai001 Date: Wed, 20 Nov 2024 14:40:06 +0800 Subject: [PATCH 4/4] Update DashManifestParser.java --- .../media3/exoplayer/dash/manifest/DashManifestParser.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/exoplayer_dash/src/main/java/androidx/media3/exoplayer/dash/manifest/DashManifestParser.java b/libraries/exoplayer_dash/src/main/java/androidx/media3/exoplayer/dash/manifest/DashManifestParser.java index f78c89317e5..2ef41109630 100644 --- a/libraries/exoplayer_dash/src/main/java/androidx/media3/exoplayer/dash/manifest/DashManifestParser.java +++ b/libraries/exoplayer_dash/src/main/java/androidx/media3/exoplayer/dash/manifest/DashManifestParser.java @@ -90,8 +90,6 @@ public class DashManifestParser extends DefaultHandler /** * Maps the value attribute of an AudioChannelConfiguration with schemeIdUri - * "urn:mpeg:mpegB:cicp:ChannelConfiguration", as defined by ISO 23001-8 clause 8.1, to a channel - * count. * "urn:mpeg:mpegB:cicp:ChannelConfiguration", as defined by ISO 23091-3:2018 clause 6.2, to a * channel count. */