From 3f9e3107ec6baef0c56a69624d6722cb98e23a30 Mon Sep 17 00:00:00 2001 From: kimvde Date: Thu, 7 Nov 2019 15:19:37 +0000 Subject: [PATCH 01/10] Fix extractor sniffing in FLAC extension Assuming that a flac stream starts with bytes ['f', 'L', 'a', 'C', 0, 0, 0, 0x22] is not always correct as it could also start with ['f', 'L', 'a', 'C', 0x80, 0, 0, 0x22] (see https://xiph.org/flac/format.html#metadata_block_streaminfo). PiperOrigin-RevId: 279080562 --- .../exoplayer2/ext/flac/FlacExtractor.java | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacExtractor.java b/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacExtractor.java index 59fb7b48353..fb5d41c0dea 100644 --- a/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacExtractor.java +++ b/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacExtractor.java @@ -72,11 +72,8 @@ public final class FlacExtractor implements Extractor { */ public static final int FLAG_DISABLE_ID3_METADATA = 1; - /** - * FLAC signature: first 4 is the signature word, second 4 is the sizeof STREAMINFO. 0x22 is the - * mandatory STREAMINFO. - */ - private static final byte[] FLAC_SIGNATURE = {'f', 'L', 'a', 'C', 0, 0, 0, 0x22}; + /** FLAC stream marker */ + private static final byte[] FLAC_STREAM_MARKER = {'f', 'L', 'a', 'C'}; private final ParsableByteArray outputBuffer; private final Id3Peeker id3Peeker; @@ -126,7 +123,7 @@ public boolean sniff(ExtractorInput input) throws IOException, InterruptedExcept if (input.getPosition() == 0) { id3Metadata = peekId3Data(input); } - return peekFlacSignature(input); + return peekFlacStreamMarker(input); } @Override @@ -255,15 +252,15 @@ private int handlePendingSeek( } /** - * Peeks from the beginning of the input to see if {@link #FLAC_SIGNATURE} is present. + * Peeks from the beginning of the input to see if {@link #FLAC_STREAM_MARKER} is present. * - * @return Whether the input begins with {@link #FLAC_SIGNATURE}. + * @return Whether the input begins with {@link #FLAC_STREAM_MARKER}. */ - private static boolean peekFlacSignature(ExtractorInput input) + private static boolean peekFlacStreamMarker(ExtractorInput input) throws IOException, InterruptedException { - byte[] header = new byte[FLAC_SIGNATURE.length]; - input.peekFully(header, /* offset= */ 0, FLAC_SIGNATURE.length); - return Arrays.equals(header, FLAC_SIGNATURE); + byte[] header = new byte[FLAC_STREAM_MARKER.length]; + input.peekFully(header, /* offset= */ 0, FLAC_STREAM_MARKER.length); + return Arrays.equals(header, FLAC_STREAM_MARKER); } /** From ed6eb3aa58fa9c237630977986f7b81db8e4b2b3 Mon Sep 17 00:00:00 2001 From: kimvde Date: Thu, 7 Nov 2019 16:05:30 +0000 Subject: [PATCH 02/10] Fix FLAC bit rate computation PiperOrigin-RevId: 279088193 --- extensions/flac/src/androidTest/assets/bear.flac.0.dump | 2 +- extensions/flac/src/androidTest/assets/bear.flac.1.dump | 2 +- extensions/flac/src/androidTest/assets/bear.flac.2.dump | 2 +- extensions/flac/src/androidTest/assets/bear.flac.3.dump | 2 +- .../flac/src/androidTest/assets/bear_with_id3.flac.0.dump | 2 +- .../flac/src/androidTest/assets/bear_with_id3.flac.1.dump | 2 +- .../flac/src/androidTest/assets/bear_with_id3.flac.2.dump | 2 +- .../flac/src/androidTest/assets/bear_with_id3.flac.3.dump | 2 +- .../com/google/android/exoplayer2/util/FlacStreamMetadata.java | 2 +- library/core/src/test/assets/ogg/bear_flac.ogg.0.dump | 2 +- library/core/src/test/assets/ogg/bear_flac.ogg.1.dump | 2 +- library/core/src/test/assets/ogg/bear_flac.ogg.2.dump | 2 +- library/core/src/test/assets/ogg/bear_flac.ogg.3.dump | 2 +- library/core/src/test/assets/ogg/bear_flac.ogg.unklen.dump | 2 +- .../core/src/test/assets/ogg/bear_flac_noseektable.ogg.0.dump | 2 +- .../core/src/test/assets/ogg/bear_flac_noseektable.ogg.1.dump | 2 +- .../core/src/test/assets/ogg/bear_flac_noseektable.ogg.2.dump | 2 +- .../core/src/test/assets/ogg/bear_flac_noseektable.ogg.3.dump | 2 +- .../src/test/assets/ogg/bear_flac_noseektable.ogg.unklen.dump | 2 +- 19 files changed, 19 insertions(+), 19 deletions(-) diff --git a/extensions/flac/src/androidTest/assets/bear.flac.0.dump b/extensions/flac/src/androidTest/assets/bear.flac.0.dump index 71359322b01..87060e8d61f 100644 --- a/extensions/flac/src/androidTest/assets/bear.flac.0.dump +++ b/extensions/flac/src/androidTest/assets/bear.flac.0.dump @@ -5,7 +5,7 @@ seekMap: numberOfTracks = 1 track 0: format: - bitrate = 768000 + bitrate = 1536000 id = null containerMimeType = null sampleMimeType = audio/raw diff --git a/extensions/flac/src/androidTest/assets/bear.flac.1.dump b/extensions/flac/src/androidTest/assets/bear.flac.1.dump index 820b9eed10f..b12f4dbf9df 100644 --- a/extensions/flac/src/androidTest/assets/bear.flac.1.dump +++ b/extensions/flac/src/androidTest/assets/bear.flac.1.dump @@ -5,7 +5,7 @@ seekMap: numberOfTracks = 1 track 0: format: - bitrate = 768000 + bitrate = 1536000 id = null containerMimeType = null sampleMimeType = audio/raw diff --git a/extensions/flac/src/androidTest/assets/bear.flac.2.dump b/extensions/flac/src/androidTest/assets/bear.flac.2.dump index c2d58347eb7..613023e86c2 100644 --- a/extensions/flac/src/androidTest/assets/bear.flac.2.dump +++ b/extensions/flac/src/androidTest/assets/bear.flac.2.dump @@ -5,7 +5,7 @@ seekMap: numberOfTracks = 1 track 0: format: - bitrate = 768000 + bitrate = 1536000 id = null containerMimeType = null sampleMimeType = audio/raw diff --git a/extensions/flac/src/androidTest/assets/bear.flac.3.dump b/extensions/flac/src/androidTest/assets/bear.flac.3.dump index 8c1115f1ecc..79f369751c4 100644 --- a/extensions/flac/src/androidTest/assets/bear.flac.3.dump +++ b/extensions/flac/src/androidTest/assets/bear.flac.3.dump @@ -5,7 +5,7 @@ seekMap: numberOfTracks = 1 track 0: format: - bitrate = 768000 + bitrate = 1536000 id = null containerMimeType = null sampleMimeType = audio/raw diff --git a/extensions/flac/src/androidTest/assets/bear_with_id3.flac.0.dump b/extensions/flac/src/androidTest/assets/bear_with_id3.flac.0.dump index d8903fcade8..3a3ba57572f 100644 --- a/extensions/flac/src/androidTest/assets/bear_with_id3.flac.0.dump +++ b/extensions/flac/src/androidTest/assets/bear_with_id3.flac.0.dump @@ -5,7 +5,7 @@ seekMap: numberOfTracks = 1 track 0: format: - bitrate = 768000 + bitrate = 1536000 id = null containerMimeType = null sampleMimeType = audio/raw diff --git a/extensions/flac/src/androidTest/assets/bear_with_id3.flac.1.dump b/extensions/flac/src/androidTest/assets/bear_with_id3.flac.1.dump index 100fdd1eaf0..a07fcaa0a20 100644 --- a/extensions/flac/src/androidTest/assets/bear_with_id3.flac.1.dump +++ b/extensions/flac/src/androidTest/assets/bear_with_id3.flac.1.dump @@ -5,7 +5,7 @@ seekMap: numberOfTracks = 1 track 0: format: - bitrate = 768000 + bitrate = 1536000 id = null containerMimeType = null sampleMimeType = audio/raw diff --git a/extensions/flac/src/androidTest/assets/bear_with_id3.flac.2.dump b/extensions/flac/src/androidTest/assets/bear_with_id3.flac.2.dump index 6c3cd731b3d..c4d13dd2e6c 100644 --- a/extensions/flac/src/androidTest/assets/bear_with_id3.flac.2.dump +++ b/extensions/flac/src/androidTest/assets/bear_with_id3.flac.2.dump @@ -5,7 +5,7 @@ seekMap: numberOfTracks = 1 track 0: format: - bitrate = 768000 + bitrate = 1536000 id = null containerMimeType = null sampleMimeType = audio/raw diff --git a/extensions/flac/src/androidTest/assets/bear_with_id3.flac.3.dump b/extensions/flac/src/androidTest/assets/bear_with_id3.flac.3.dump index decf9c6af33..2f389909e7a 100644 --- a/extensions/flac/src/androidTest/assets/bear_with_id3.flac.3.dump +++ b/extensions/flac/src/androidTest/assets/bear_with_id3.flac.3.dump @@ -5,7 +5,7 @@ seekMap: numberOfTracks = 1 track 0: format: - bitrate = 768000 + bitrate = 1536000 id = null containerMimeType = null sampleMimeType = audio/raw diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/FlacStreamMetadata.java b/library/core/src/main/java/com/google/android/exoplayer2/util/FlacStreamMetadata.java index 2c814294af0..9c5862b4833 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/FlacStreamMetadata.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/FlacStreamMetadata.java @@ -109,7 +109,7 @@ public int maxDecodedFrameSize() { /** Returns the bit-rate of the FLAC stream. */ public int bitRate() { - return bitsPerSample * sampleRate; + return bitsPerSample * sampleRate * channels; } /** Returns the duration of the FLAC stream in microseconds. */ diff --git a/library/core/src/test/assets/ogg/bear_flac.ogg.0.dump b/library/core/src/test/assets/ogg/bear_flac.ogg.0.dump index 5b8d893f1ab..ccd09181a81 100644 --- a/library/core/src/test/assets/ogg/bear_flac.ogg.0.dump +++ b/library/core/src/test/assets/ogg/bear_flac.ogg.0.dump @@ -5,7 +5,7 @@ seekMap: numberOfTracks = 1 track 0: format: - bitrate = 768000 + bitrate = 1536000 id = null containerMimeType = null sampleMimeType = audio/flac diff --git a/library/core/src/test/assets/ogg/bear_flac.ogg.1.dump b/library/core/src/test/assets/ogg/bear_flac.ogg.1.dump index fff76c5b053..0f36b2b32e7 100644 --- a/library/core/src/test/assets/ogg/bear_flac.ogg.1.dump +++ b/library/core/src/test/assets/ogg/bear_flac.ogg.1.dump @@ -5,7 +5,7 @@ seekMap: numberOfTracks = 1 track 0: format: - bitrate = 768000 + bitrate = 1536000 id = null containerMimeType = null sampleMimeType = audio/flac diff --git a/library/core/src/test/assets/ogg/bear_flac.ogg.2.dump b/library/core/src/test/assets/ogg/bear_flac.ogg.2.dump index b4d35341615..b3ff58e707c 100644 --- a/library/core/src/test/assets/ogg/bear_flac.ogg.2.dump +++ b/library/core/src/test/assets/ogg/bear_flac.ogg.2.dump @@ -5,7 +5,7 @@ seekMap: numberOfTracks = 1 track 0: format: - bitrate = 768000 + bitrate = 1536000 id = null containerMimeType = null sampleMimeType = audio/flac diff --git a/library/core/src/test/assets/ogg/bear_flac.ogg.3.dump b/library/core/src/test/assets/ogg/bear_flac.ogg.3.dump index 27c29cba585..ea2eff8b040 100644 --- a/library/core/src/test/assets/ogg/bear_flac.ogg.3.dump +++ b/library/core/src/test/assets/ogg/bear_flac.ogg.3.dump @@ -5,7 +5,7 @@ seekMap: numberOfTracks = 1 track 0: format: - bitrate = 768000 + bitrate = 1536000 id = null containerMimeType = null sampleMimeType = audio/flac diff --git a/library/core/src/test/assets/ogg/bear_flac.ogg.unklen.dump b/library/core/src/test/assets/ogg/bear_flac.ogg.unklen.dump index 5b8d893f1ab..ccd09181a81 100644 --- a/library/core/src/test/assets/ogg/bear_flac.ogg.unklen.dump +++ b/library/core/src/test/assets/ogg/bear_flac.ogg.unklen.dump @@ -5,7 +5,7 @@ seekMap: numberOfTracks = 1 track 0: format: - bitrate = 768000 + bitrate = 1536000 id = null containerMimeType = null sampleMimeType = audio/flac diff --git a/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.0.dump b/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.0.dump index 2ecdc9784cd..0972d17f2f9 100644 --- a/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.0.dump +++ b/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.0.dump @@ -5,7 +5,7 @@ seekMap: numberOfTracks = 1 track 0: format: - bitrate = 768000 + bitrate = 1536000 id = null containerMimeType = null sampleMimeType = audio/flac diff --git a/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.1.dump b/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.1.dump index 0ed2a86b9ed..e33b81c90fd 100644 --- a/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.1.dump +++ b/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.1.dump @@ -5,7 +5,7 @@ seekMap: numberOfTracks = 1 track 0: format: - bitrate = 768000 + bitrate = 1536000 id = null containerMimeType = null sampleMimeType = audio/flac diff --git a/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.2.dump b/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.2.dump index 229e90584e6..b8b7d853930 100644 --- a/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.2.dump +++ b/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.2.dump @@ -5,7 +5,7 @@ seekMap: numberOfTracks = 1 track 0: format: - bitrate = 768000 + bitrate = 1536000 id = null containerMimeType = null sampleMimeType = audio/flac diff --git a/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.3.dump b/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.3.dump index 89c6d178ff4..c8660175487 100644 --- a/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.3.dump +++ b/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.3.dump @@ -5,7 +5,7 @@ seekMap: numberOfTracks = 1 track 0: format: - bitrate = 768000 + bitrate = 1536000 id = null containerMimeType = null sampleMimeType = audio/flac diff --git a/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.unklen.dump b/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.unklen.dump index 7a4ba81f23e..735d97eed18 100644 --- a/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.unklen.dump +++ b/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.unklen.dump @@ -5,7 +5,7 @@ seekMap: numberOfTracks = 1 track 0: format: - bitrate = 768000 + bitrate = 1536000 id = null containerMimeType = null sampleMimeType = audio/flac From 2b1c2171e7e6ed29af0185622e0c59233868a2d4 Mon Sep 17 00:00:00 2001 From: andrewlewis Date: Mon, 11 Nov 2019 05:33:45 +0000 Subject: [PATCH 03/10] Handle new signaling for E-AC3 JOC in DASH Issue: #6636 PiperOrigin-RevId: 279666771 --- RELEASENOTES.md | 5 +++++ .../exoplayer2/source/dash/manifest/DashManifestParser.java | 6 ++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 5d14b6f6a10..573ed48c796 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,5 +1,10 @@ # Release notes # +### 2.10.8 (2019-11-18) ### + +* Handle new signaling for E-AC3 JOC audio in DASH + ([#6636](https://github.com/google/ExoPlayer/issues/6636)). + ### 2.10.7 (2019-11-12) ### * HLS: Fix detection of Dolby Atmos to match the HLS authoring specification. diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.java index 95e8c7f942a..d83be8d465c 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.java @@ -1417,8 +1417,10 @@ protected static String parseEac3SupplementalProperties(List supplem for (int i = 0; i < supplementalProperties.size(); i++) { Descriptor descriptor = supplementalProperties.get(i); String schemeIdUri = descriptor.schemeIdUri; - if ("tag:dolby.com,2014:dash:DolbyDigitalPlusExtensionType:2014".equals(schemeIdUri) - && "ec+3".equals(descriptor.value)) { + if (("tag:dolby.com,2018:dash:EC3_ExtensionComplexityIndex:2018".equals(schemeIdUri) + && "JOC".equals(descriptor.value)) + || ("tag:dolby.com,2014:dash:DolbyDigitalPlusExtensionType:2014".equals(schemeIdUri) + && "ec+3".equals(descriptor.value))) { return MimeTypes.AUDIO_E_AC3_JOC; } } From a8b65ca8d6aaa188884edb4f4e5fa6b6cbf587af Mon Sep 17 00:00:00 2001 From: kimvde Date: Mon, 11 Nov 2019 14:22:30 +0000 Subject: [PATCH 04/10] Compute format maxInputSize in FlacReader Use the maximum frame size as the maximum sample size if provided. PiperOrigin-RevId: 279722820 --- .../google/android/exoplayer2/extractor/ogg/FlacReader.java | 4 +++- library/core/src/test/assets/ogg/bear_flac.ogg.0.dump | 2 +- library/core/src/test/assets/ogg/bear_flac.ogg.1.dump | 2 +- library/core/src/test/assets/ogg/bear_flac.ogg.2.dump | 2 +- library/core/src/test/assets/ogg/bear_flac.ogg.3.dump | 2 +- library/core/src/test/assets/ogg/bear_flac.ogg.unklen.dump | 2 +- .../core/src/test/assets/ogg/bear_flac_noseektable.ogg.0.dump | 2 +- .../core/src/test/assets/ogg/bear_flac_noseektable.ogg.1.dump | 2 +- .../core/src/test/assets/ogg/bear_flac_noseektable.ogg.2.dump | 2 +- .../core/src/test/assets/ogg/bear_flac_noseektable.ogg.3.dump | 2 +- .../src/test/assets/ogg/bear_flac_noseektable.ogg.unklen.dump | 2 +- 11 files changed, 13 insertions(+), 11 deletions(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/FlacReader.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/FlacReader.java index e1218b55724..f7735d84de9 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/FlacReader.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/FlacReader.java @@ -73,6 +73,8 @@ protected boolean readHeaders(ParsableByteArray packet, long position, SetupData byte[] data = packet.data; if (streamMetadata == null) { streamMetadata = new FlacStreamMetadata(data, 17); + int maxInputSize = + streamMetadata.maxFrameSize == 0 ? Format.NO_VALUE : streamMetadata.maxFrameSize; byte[] metadata = Arrays.copyOfRange(data, 9, packet.limit()); metadata[4] = (byte) 0x80; // Set the last metadata block flag, ignore the other blocks List initializationData = Collections.singletonList(metadata); @@ -82,7 +84,7 @@ protected boolean readHeaders(ParsableByteArray packet, long position, SetupData MimeTypes.AUDIO_FLAC, /* codecs= */ null, streamMetadata.bitRate(), - /* maxInputSize= */ Format.NO_VALUE, + maxInputSize, streamMetadata.channels, streamMetadata.sampleRate, initializationData, diff --git a/library/core/src/test/assets/ogg/bear_flac.ogg.0.dump b/library/core/src/test/assets/ogg/bear_flac.ogg.0.dump index ccd09181a81..365040c46c7 100644 --- a/library/core/src/test/assets/ogg/bear_flac.ogg.0.dump +++ b/library/core/src/test/assets/ogg/bear_flac.ogg.0.dump @@ -9,7 +9,7 @@ track 0: id = null containerMimeType = null sampleMimeType = audio/flac - maxInputSize = -1 + maxInputSize = 5776 width = -1 height = -1 frameRate = -1.0 diff --git a/library/core/src/test/assets/ogg/bear_flac.ogg.1.dump b/library/core/src/test/assets/ogg/bear_flac.ogg.1.dump index 0f36b2b32e7..ff020b32fd4 100644 --- a/library/core/src/test/assets/ogg/bear_flac.ogg.1.dump +++ b/library/core/src/test/assets/ogg/bear_flac.ogg.1.dump @@ -9,7 +9,7 @@ track 0: id = null containerMimeType = null sampleMimeType = audio/flac - maxInputSize = -1 + maxInputSize = 5776 width = -1 height = -1 frameRate = -1.0 diff --git a/library/core/src/test/assets/ogg/bear_flac.ogg.2.dump b/library/core/src/test/assets/ogg/bear_flac.ogg.2.dump index b3ff58e707c..88deeaebd31 100644 --- a/library/core/src/test/assets/ogg/bear_flac.ogg.2.dump +++ b/library/core/src/test/assets/ogg/bear_flac.ogg.2.dump @@ -9,7 +9,7 @@ track 0: id = null containerMimeType = null sampleMimeType = audio/flac - maxInputSize = -1 + maxInputSize = 5776 width = -1 height = -1 frameRate = -1.0 diff --git a/library/core/src/test/assets/ogg/bear_flac.ogg.3.dump b/library/core/src/test/assets/ogg/bear_flac.ogg.3.dump index ea2eff8b040..2eb7be2454b 100644 --- a/library/core/src/test/assets/ogg/bear_flac.ogg.3.dump +++ b/library/core/src/test/assets/ogg/bear_flac.ogg.3.dump @@ -9,7 +9,7 @@ track 0: id = null containerMimeType = null sampleMimeType = audio/flac - maxInputSize = -1 + maxInputSize = 5776 width = -1 height = -1 frameRate = -1.0 diff --git a/library/core/src/test/assets/ogg/bear_flac.ogg.unklen.dump b/library/core/src/test/assets/ogg/bear_flac.ogg.unklen.dump index ccd09181a81..365040c46c7 100644 --- a/library/core/src/test/assets/ogg/bear_flac.ogg.unklen.dump +++ b/library/core/src/test/assets/ogg/bear_flac.ogg.unklen.dump @@ -9,7 +9,7 @@ track 0: id = null containerMimeType = null sampleMimeType = audio/flac - maxInputSize = -1 + maxInputSize = 5776 width = -1 height = -1 frameRate = -1.0 diff --git a/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.0.dump b/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.0.dump index 0972d17f2f9..c07b2f3844c 100644 --- a/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.0.dump +++ b/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.0.dump @@ -9,7 +9,7 @@ track 0: id = null containerMimeType = null sampleMimeType = audio/flac - maxInputSize = -1 + maxInputSize = 5776 width = -1 height = -1 frameRate = -1.0 diff --git a/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.1.dump b/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.1.dump index e33b81c90fd..a7fce3c9015 100644 --- a/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.1.dump +++ b/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.1.dump @@ -9,7 +9,7 @@ track 0: id = null containerMimeType = null sampleMimeType = audio/flac - maxInputSize = -1 + maxInputSize = 5776 width = -1 height = -1 frameRate = -1.0 diff --git a/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.2.dump b/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.2.dump index b8b7d853930..d05d36bd1ef 100644 --- a/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.2.dump +++ b/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.2.dump @@ -9,7 +9,7 @@ track 0: id = null containerMimeType = null sampleMimeType = audio/flac - maxInputSize = -1 + maxInputSize = 5776 width = -1 height = -1 frameRate = -1.0 diff --git a/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.3.dump b/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.3.dump index c8660175487..376cb684996 100644 --- a/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.3.dump +++ b/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.3.dump @@ -9,7 +9,7 @@ track 0: id = null containerMimeType = null sampleMimeType = audio/flac - maxInputSize = -1 + maxInputSize = 5776 width = -1 height = -1 frameRate = -1.0 diff --git a/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.unklen.dump b/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.unklen.dump index 735d97eed18..44a93a60371 100644 --- a/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.unklen.dump +++ b/library/core/src/test/assets/ogg/bear_flac_noseektable.ogg.unklen.dump @@ -9,7 +9,7 @@ track 0: id = null containerMimeType = null sampleMimeType = audio/flac - maxInputSize = -1 + maxInputSize = 5776 width = -1 height = -1 frameRate = -1.0 From 4b012a9b6e16c440c592d43b22330a9c17356283 Mon Sep 17 00:00:00 2001 From: andrewlewis Date: Tue, 12 Nov 2019 00:18:44 +0000 Subject: [PATCH 05/10] Don't check channels for E-AC3 JOC passthrough PiperOrigin-RevId: 279841132 --- .../android/exoplayer2/audio/MediaCodecAudioRenderer.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java index 36db657956c..b8756de5786 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java @@ -543,7 +543,8 @@ protected void onOutputFormatChanged(MediaCodec codec, MediaFormat outputFormat) @C.Encoding protected int getPassthroughEncoding(int channelCount, String mimeType) { if (MimeTypes.AUDIO_E_AC3_JOC.equals(mimeType)) { - if (audioSink.supportsOutput(channelCount, C.ENCODING_E_AC3_JOC)) { + // E-AC3 JOC is object-based so the output channel count is arbitrary. + if (audioSink.supportsOutput(/* channelCount= */ Format.NO_VALUE, C.ENCODING_E_AC3_JOC)) { return MimeTypes.getEncoding(MimeTypes.AUDIO_E_AC3_JOC); } // E-AC3 receivers can decode JOC streams, but in 2-D rather than 3-D, so try to fall back. From c0e633fbe118878c778bfa1fe7c2efccac1b0e22 Mon Sep 17 00:00:00 2001 From: bachinger Date: Tue, 12 Nov 2019 15:32:57 +0000 Subject: [PATCH 06/10] use getPeriodByUid when searching for subsequent period of seek timeline Issue: #6641 PiperOrigin-RevId: 279963739 --- .../google/android/exoplayer2/ExoPlayerImplInternal.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java index b6ac22059f8..3a34fc14b5b 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java @@ -1433,6 +1433,7 @@ private void handleSourceInfoRefreshEndedPlayback() { * @throws IllegalSeekPositionException If the window index of the seek position is outside the * bounds of the timeline. */ + @Nullable private Pair resolveSeekPosition( SeekPosition seekPosition, boolean trySubsequentPeriods) { Timeline timeline = playbackInfo.timeline; @@ -1467,11 +1468,12 @@ private Pair resolveSeekPosition( } if (trySubsequentPeriods) { // Try and find a subsequent period from the seek timeline in the internal timeline. + @Nullable Object periodUid = resolveSubsequentPeriod(periodPosition.first, seekTimeline, timeline); if (periodUid != null) { - // We found one. Map the SeekPosition onto the corresponding default position. + // We found one. Use the default position of the corresponding window. return getPeriodPosition( - timeline, timeline.getPeriod(periodIndex, period).windowIndex, C.TIME_UNSET); + timeline, timeline.getPeriodByUid(periodUid, period).windowIndex, C.TIME_UNSET); } } // We didn't find one. Give up. From 1345010e27975ea420fa097abdfae1aef0f199d9 Mon Sep 17 00:00:00 2001 From: Oliver Woodman Date: Fri, 15 Nov 2019 05:16:29 +0000 Subject: [PATCH 07/10] Merge pull request #6650 from stanionascu:dev-v2-dv PiperOrigin-RevId: 280573887 --- .../com/google/android/exoplayer2/video/DolbyVisionConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/video/DolbyVisionConfig.java b/library/core/src/main/java/com/google/android/exoplayer2/video/DolbyVisionConfig.java index 3aeff9d553a..3a13540e12f 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/video/DolbyVisionConfig.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/video/DolbyVisionConfig.java @@ -36,7 +36,7 @@ public static DolbyVisionConfig parse(ParsableByteArray data) { int dvProfile = (profileData >> 1); int dvLevel = ((profileData & 0x1) << 5) | ((data.readUnsignedByte() >> 3) & 0x1F); String codecsPrefix; - if (dvProfile == 4 || dvProfile == 5) { + if (dvProfile == 4 || dvProfile == 5 || dvProfile == 7) { codecsPrefix = "dvhe"; } else if (dvProfile == 8) { codecsPrefix = "hev1"; From 2e0719b5553519a6d6b1445f5e89c1f6ea23759d Mon Sep 17 00:00:00 2001 From: olly Date: Fri, 15 Nov 2019 04:29:30 +0000 Subject: [PATCH 08/10] Parse channel count and sample rate from ALAC initialization data Also remove the "do we really need to do this" comment for AAC. Parsing from codec specific data is likely to be more robust, so I think we should continue to do it for formats where we've seen this problem. Issue: #6648 PiperOrigin-RevId: 280575466 --- .../exoplayer2/extractor/mp4/AtomParsers.java | 10 +++- .../util/CodecSpecificDataUtil.java | 34 +++++++++---- .../util/CodecSpecificDataUtilTest.java | 48 +++++++++++++++++++ 3 files changed, 81 insertions(+), 11 deletions(-) create mode 100644 library/core/src/test/java/com/google/android/exoplayer2/util/CodecSpecificDataUtilTest.java diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java index 58bd59a4482..694ad22e299 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java @@ -1114,8 +1114,8 @@ private static void parseAudioSampleEntry(ParsableByteArray parent, int atomType mimeType = mimeTypeAndInitializationData.first; initializationData = mimeTypeAndInitializationData.second; if (MimeTypes.AUDIO_AAC.equals(mimeType)) { - // TODO: Do we really need to do this? See [Internal: b/10903778] - // Update sampleRate and channelCount from the AudioSpecificConfig initialization data. + // Update sampleRate and channelCount from the AudioSpecificConfig initialization data, + // which is more reliable. See [Internal: b/10903778]. Pair audioSpecificConfig = CodecSpecificDataUtil.parseAacAudioSpecificConfig(initializationData); sampleRate = audioSpecificConfig.first; @@ -1160,6 +1160,12 @@ private static void parseAudioSampleEntry(ParsableByteArray parent, int atomType initializationData = new byte[childAtomBodySize]; parent.setPosition(childPosition + Atom.FULL_HEADER_SIZE); parent.readBytes(initializationData, /* offset= */ 0, childAtomBodySize); + // Update sampleRate and channelCount from the AudioSpecificConfig initialization data, + // which is more reliable. See https://github.com/google/ExoPlayer/pull/6629. + Pair audioSpecificConfig = + CodecSpecificDataUtil.parseAlacAudioSpecificConfig(initializationData); + sampleRate = audioSpecificConfig.first; + channelCount = audioSpecificConfig.second; } childPosition += childAtomSize; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/CodecSpecificDataUtil.java b/library/core/src/main/java/com/google/android/exoplayer2/util/CodecSpecificDataUtil.java index 16a891dbc6a..8d62a65fcf6 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/CodecSpecificDataUtil.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/CodecSpecificDataUtil.java @@ -83,7 +83,7 @@ public final class CodecSpecificDataUtil { private CodecSpecificDataUtil() {} /** - * Parses an AudioSpecificConfig, as defined in ISO 14496-3 1.6.2.1 + * Parses an AAC AudioSpecificConfig, as defined in ISO 14496-3 1.6.2.1 * * @param audioSpecificConfig A byte array containing the AudioSpecificConfig to parse. * @return A pair consisting of the sample rate in Hz and the channel count. @@ -95,7 +95,7 @@ public static Pair parseAacAudioSpecificConfig(byte[] audioSpe } /** - * Parses an AudioSpecificConfig, as defined in ISO 14496-3 1.6.2.1 + * Parses an AAC AudioSpecificConfig, as defined in ISO 14496-3 1.6.2.1 * * @param bitArray A {@link ParsableBitArray} containing the AudioSpecificConfig to parse. The * position is advanced to the end of the AudioSpecificConfig. @@ -104,8 +104,8 @@ public static Pair parseAacAudioSpecificConfig(byte[] audioSpe * @return A pair consisting of the sample rate in Hz and the channel count. * @throws ParserException If the AudioSpecificConfig cannot be parsed as it's not supported. */ - public static Pair parseAacAudioSpecificConfig(ParsableBitArray bitArray, - boolean forceReadToEnd) throws ParserException { + public static Pair parseAacAudioSpecificConfig( + ParsableBitArray bitArray, boolean forceReadToEnd) throws ParserException { int audioObjectType = getAacAudioObjectType(bitArray); int sampleRate = getAacSamplingFrequency(bitArray); int channelConfiguration = bitArray.readBits(4); @@ -166,10 +166,10 @@ public static Pair parseAacAudioSpecificConfig(ParsableBitArra * Builds a simple HE-AAC LC AudioSpecificConfig, as defined in ISO 14496-3 1.6.2.1 * * @param sampleRate The sample rate in Hz. - * @param numChannels The number of channels. + * @param channelCount The channel count. * @return The AudioSpecificConfig. */ - public static byte[] buildAacLcAudioSpecificConfig(int sampleRate, int numChannels) { + public static byte[] buildAacLcAudioSpecificConfig(int sampleRate, int channelCount) { int sampleRateIndex = C.INDEX_UNSET; for (int i = 0; i < AUDIO_SPECIFIC_CONFIG_SAMPLING_RATE_TABLE.length; ++i) { if (sampleRate == AUDIO_SPECIFIC_CONFIG_SAMPLING_RATE_TABLE[i]) { @@ -178,13 +178,13 @@ public static byte[] buildAacLcAudioSpecificConfig(int sampleRate, int numChanne } int channelConfig = C.INDEX_UNSET; for (int i = 0; i < AUDIO_SPECIFIC_CONFIG_CHANNEL_COUNT_TABLE.length; ++i) { - if (numChannels == AUDIO_SPECIFIC_CONFIG_CHANNEL_COUNT_TABLE[i]) { + if (channelCount == AUDIO_SPECIFIC_CONFIG_CHANNEL_COUNT_TABLE[i]) { channelConfig = i; } } if (sampleRate == C.INDEX_UNSET || channelConfig == C.INDEX_UNSET) { - throw new IllegalArgumentException("Invalid sample rate or number of channels: " - + sampleRate + ", " + numChannels); + throw new IllegalArgumentException( + "Invalid sample rate or number of channels: " + sampleRate + ", " + channelCount); } return buildAacAudioSpecificConfig(AUDIO_OBJECT_TYPE_AAC_LC, sampleRateIndex, channelConfig); } @@ -205,6 +205,22 @@ public static byte[] buildAacAudioSpecificConfig(int audioObjectType, int sample return specificConfig; } + /** + * Parses an ALAC AudioSpecificConfig (i.e. an ALACSpecificConfig). + * + * @param audioSpecificConfig A byte array containing the AudioSpecificConfig to parse. + * @return A pair consisting of the sample rate in Hz and the channel count. + */ + public static Pair parseAlacAudioSpecificConfig(byte[] audioSpecificConfig) { + ParsableByteArray byteArray = new ParsableByteArray(audioSpecificConfig); + byteArray.setPosition(9); + int channelCount = byteArray.readUnsignedByte(); + byteArray.setPosition(20); + int sampleRate = byteArray.readUnsignedIntToInt(); + return Pair.create(sampleRate, channelCount); + } + /** * Builds an RFC 6381 AVC codec string using the provided parameters. * diff --git a/library/core/src/test/java/com/google/android/exoplayer2/util/CodecSpecificDataUtilTest.java b/library/core/src/test/java/com/google/android/exoplayer2/util/CodecSpecificDataUtilTest.java new file mode 100644 index 00000000000..a880e822505 --- /dev/null +++ b/library/core/src/test/java/com/google/android/exoplayer2/util/CodecSpecificDataUtilTest.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2019 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 com.google.android.exoplayer2.util; + +import static com.google.common.truth.Truth.assertThat; + +import android.util.Pair; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** Unit test for {@link CodecSpecificDataUtil}. */ +@RunWith(AndroidJUnit4.class) +public class CodecSpecificDataUtilTest { + + @Test + public void parseAlacAudioSpecificConfig() { + byte[] alacSpecificConfig = + new byte[] { + 0, 0, 16, 0, // frameLength + 0, // compatibleVersion + 16, // bitDepth + 40, 10, 14, // tuning parameters + 2, // numChannels = 2 + 0, 0, // maxRun + 0, 0, 64, 4, // maxFrameBytes + 0, 46, -32, 0, // avgBitRate + 0, 1, 119, 0, // sampleRate = 96000 + }; + Pair sampleRateAndChannelCount = + CodecSpecificDataUtil.parseAlacAudioSpecificConfig(alacSpecificConfig); + assertThat(sampleRateAndChannelCount.first).isEqualTo(96000); + assertThat(sampleRateAndChannelCount.second).isEqualTo(2); + } +} From ae271c1689e450946e5a55bdbac5460d13c7e455 Mon Sep 17 00:00:00 2001 From: Oliver Woodman Date: Sun, 17 Nov 2019 04:53:48 +0000 Subject: [PATCH 09/10] Bump version to 2.10.8 --- RELEASENOTES.md | 19 +++++++++++++++---- constants.gradle | 4 ++-- .../exoplayer2/ExoPlayerLibraryInfo.java | 6 +++--- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 573ed48c796..07c97bdea89 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -2,10 +2,21 @@ ### 2.10.8 (2019-11-18) ### -* Handle new signaling for E-AC3 JOC audio in DASH - ([#6636](https://github.com/google/ExoPlayer/issues/6636)). - -### 2.10.7 (2019-11-12) ### +* E-AC3 JOC + * Handle new signaling in DASH manifests + ([#6636](https://github.com/google/ExoPlayer/issues/6636)). + * Remove incorrect channel count check when determining output support. +* FLAC + * Fix sniffing for some FLAC streams. + * Fix FLAC `Format.bitrate` values. +* Parse ALAC channel count and sample rate information from a more robust source + when contained in MP4 + ([#6648](https://github.com/google/ExoPlayer/issues/6648)). +* Fix seeking into multi-period content in the edge case that the period + containing the seek position has just been removed + ([#6641](https://github.com/google/ExoPlayer/issues/6641)). + +### 2.10.7 (2019-11-06) ### * HLS: Fix detection of Dolby Atmos to match the HLS authoring specification. * MediaSession extension: Update shuffle and repeat modes when playback state diff --git a/constants.gradle b/constants.gradle index 59b6b7ff42f..edb099b7e8b 100644 --- a/constants.gradle +++ b/constants.gradle @@ -13,8 +13,8 @@ // limitations under the License. project.ext { // ExoPlayer version and version code. - releaseVersion = '2.10.7' - releaseVersionCode = 2010007 + releaseVersion = '2.10.8' + releaseVersionCode = 2010008 minSdkVersion = 16 targetSdkVersion = 28 compileSdkVersion = 28 diff --git a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java index 79d395a8584..f678889abc4 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java @@ -29,11 +29,11 @@ public final class ExoPlayerLibraryInfo { /** The version of the library expressed as a string, for example "1.2.3". */ // Intentionally hardcoded. Do not derive from other constants (e.g. VERSION_INT) or vice versa. - public static final String VERSION = "2.10.7"; + public static final String VERSION = "2.10.8"; /** The version of the library expressed as {@code "ExoPlayerLib/" + VERSION}. */ // Intentionally hardcoded. Do not derive from other constants (e.g. VERSION) or vice versa. - public static final String VERSION_SLASHY = "ExoPlayerLib/2.10.7"; + public static final String VERSION_SLASHY = "ExoPlayerLib/2.10.8"; /** * The version of the library expressed as an integer, for example 1002003. @@ -43,7 +43,7 @@ public final class ExoPlayerLibraryInfo { * integer version 123045006 (123-045-006). */ // Intentionally hardcoded. Do not derive from other constants (e.g. VERSION) or vice versa. - public static final int VERSION_INT = 2010007; + public static final int VERSION_INT = 2010008; /** * Whether the library was compiled with {@link com.google.android.exoplayer2.util.Assertions} From 30f79a4c4724cd2970f1df79a333b0d53e5f5bbf Mon Sep 17 00:00:00 2001 From: Oliver Woodman Date: Mon, 18 Nov 2019 17:17:23 +0000 Subject: [PATCH 10/10] Tweak release notes --- RELEASENOTES.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 07c97bdea89..6df173c7d40 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,11 +1,12 @@ # Release notes # -### 2.10.8 (2019-11-18) ### +### 2.10.8 (2019-11-19) ### * E-AC3 JOC * Handle new signaling in DASH manifests ([#6636](https://github.com/google/ExoPlayer/issues/6636)). - * Remove incorrect channel count check when determining output support. + * Fix E-AC3 JOC passthrough playback failing to initialize due to incorrect + channel count check. * FLAC * Fix sniffing for some FLAC streams. * Fix FLAC `Format.bitrate` values.