From facfa5267787fd51e3ab04b89ad13c763e8cbc41 Mon Sep 17 00:00:00 2001 From: olly Date: Wed, 14 Jun 2017 07:56:37 -0700 Subject: [PATCH 01/24] Log frame counts when we see a spurious audio timestamp ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=158977741 --- .../java/com/google/android/exoplayer2/audio/AudioTrack.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioTrack.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioTrack.java index 44a96373f3..92838e34b0 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioTrack.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioTrack.java @@ -1292,7 +1292,7 @@ public final class AudioTrack { // The timestamp time base is probably wrong. String message = "Spurious audio timestamp (system clock mismatch): " + audioTimestampFramePosition + ", " + audioTimestampUs + ", " + systemClockUs + ", " - + playbackPositionUs; + + playbackPositionUs + ", " + getSubmittedFrames() + ", " + getWrittenFrames(); if (failOnSpuriousAudioTimestamp) { throw new InvalidAudioTrackTimestampException(message); } @@ -1303,7 +1303,7 @@ public final class AudioTrack { // The timestamp frame position is probably wrong. String message = "Spurious audio timestamp (frame position mismatch): " + audioTimestampFramePosition + ", " + audioTimestampUs + ", " + systemClockUs + ", " - + playbackPositionUs; + + playbackPositionUs + ", " + getSubmittedFrames() + ", " + getWrittenFrames(); if (failOnSpuriousAudioTimestamp) { throw new InvalidAudioTrackTimestampException(message); } From e8ee868a9f65a1e9013dee2729b46df9aa54a83b Mon Sep 17 00:00:00 2001 From: andrewlewis Date: Thu, 15 Jun 2017 02:36:46 -0700 Subject: [PATCH 02/24] Add support for mono input to the GVR extension Issue: #2710 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=159082518 --- extensions/gvr/build.gradle | 2 +- .../google/android/exoplayer2/ext/gvr/GvrAudioProcessor.java | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/extensions/gvr/build.gradle b/extensions/gvr/build.gradle index f622a73758..e15c8b1ad8 100644 --- a/extensions/gvr/build.gradle +++ b/extensions/gvr/build.gradle @@ -25,7 +25,7 @@ android { dependencies { compile project(':library-core') - compile 'com.google.vr:sdk-audio:1.30.0' + compile 'com.google.vr:sdk-audio:1.60.1' } ext { diff --git a/extensions/gvr/src/main/java/com/google/android/exoplayer2/ext/gvr/GvrAudioProcessor.java b/extensions/gvr/src/main/java/com/google/android/exoplayer2/ext/gvr/GvrAudioProcessor.java index 980424904d..a56bc7f0a9 100644 --- a/extensions/gvr/src/main/java/com/google/android/exoplayer2/ext/gvr/GvrAudioProcessor.java +++ b/extensions/gvr/src/main/java/com/google/android/exoplayer2/ext/gvr/GvrAudioProcessor.java @@ -82,6 +82,9 @@ public final class GvrAudioProcessor implements AudioProcessor { maybeReleaseGvrAudioSurround(); int surroundFormat; switch (channelCount) { + case 1: + surroundFormat = GvrAudioSurround.SurroundFormat.SURROUND_MONO; + break; case 2: surroundFormat = GvrAudioSurround.SurroundFormat.SURROUND_STEREO; break; From e618080c7385e9ddf7217f668fd5635c86e34dec Mon Sep 17 00:00:00 2001 From: olly Date: Fri, 7 Apr 2017 07:08:04 +0100 Subject: [PATCH 03/24] Adjust incorrect looking max-channel counts Issue: #2940 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=159099602 --- .../extractor/flv/AudioTagPayloadReader.java | 2 +- .../exoplayer2/mediacodec/MediaCodecInfo.java | 38 ++++++++++++++++++- .../android/exoplayer2/util/MimeTypes.java | 5 ++- 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/flv/AudioTagPayloadReader.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/flv/AudioTagPayloadReader.java index 8e3bd08375..2f21898007 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/flv/AudioTagPayloadReader.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/flv/AudioTagPayloadReader.java @@ -67,7 +67,7 @@ import java.util.Collections; hasOutputFormat = true; } else if (audioFormat == AUDIO_FORMAT_ALAW || audioFormat == AUDIO_FORMAT_ULAW) { String type = audioFormat == AUDIO_FORMAT_ALAW ? MimeTypes.AUDIO_ALAW - : MimeTypes.AUDIO_ULAW; + : MimeTypes.AUDIO_MLAW; int pcmEncoding = (header & 0x01) == 1 ? C.ENCODING_PCM_16BIT : C.ENCODING_PCM_8BIT; Format format = Format.createAudioSampleFormat(null, type, null, Format.NO_VALUE, Format.NO_VALUE, 1, 8000, pcmEncoding, null, null, 0, null); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java index 3c788a60a4..a7c237edb2 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java @@ -264,7 +264,9 @@ public final class MediaCodecInfo { logNoSupport("channelCount.aCaps"); return false; } - if (audioCapabilities.getMaxInputChannelCount() < channelCount) { + int maxInputChannelCount = adjustMaxInputChannelCount(name, mimeType, + audioCapabilities.getMaxInputChannelCount()); + if (maxInputChannelCount < channelCount) { logNoSupport("channelCount.support, " + channelCount); return false; } @@ -281,6 +283,40 @@ public final class MediaCodecInfo { + Util.DEVICE_DEBUG_INFO + "]"); } + private static int adjustMaxInputChannelCount(String name, String mimeType, int maxChannelCount) { + if (maxChannelCount > 1 || (Util.SDK_INT >= 26 && maxChannelCount > 0)) { + // The maximum channel count looks like it's been set correctly. + return maxChannelCount; + } + if (MimeTypes.AUDIO_MPEG.equals(mimeType) + || MimeTypes.AUDIO_AMR_NB.equals(mimeType) + || MimeTypes.AUDIO_AMR_WB.equals(mimeType) + || MimeTypes.AUDIO_AAC.equals(mimeType) + || MimeTypes.AUDIO_VORBIS.equals(mimeType) + || MimeTypes.AUDIO_OPUS.equals(mimeType) + || MimeTypes.AUDIO_RAW.equals(mimeType) + || MimeTypes.AUDIO_FLAC.equals(mimeType) + || MimeTypes.AUDIO_ALAW.equals(mimeType) + || MimeTypes.AUDIO_MLAW.equals(mimeType) + || MimeTypes.AUDIO_MSGSM.equals(mimeType)) { + // Platform code should have set a default. + return maxChannelCount; + } + // The maximum channel count looks incorrect. Adjust it to an assumed default. + int assumedMaxChannelCount; + if (MimeTypes.AUDIO_AC3.equals(mimeType)) { + assumedMaxChannelCount = 6; + } else if (MimeTypes.AUDIO_E_AC3.equals(mimeType)) { + assumedMaxChannelCount = 16; + } else { + // Default to the platform limit, which is 30. + assumedMaxChannelCount = 30; + } + Log.w(TAG, "AssumedMaxChannelAdjustment: " + name + ", [" + maxChannelCount + " to " + + assumedMaxChannelCount + "]"); + return assumedMaxChannelCount; + } + private static boolean isAdaptive(CodecCapabilities capabilities) { return Util.SDK_INT >= 19 && isAdaptiveV19(capabilities); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/MimeTypes.java b/library/core/src/main/java/com/google/android/exoplayer2/util/MimeTypes.java index e227ea1068..db1122dbe7 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/MimeTypes.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/MimeTypes.java @@ -48,7 +48,7 @@ public final class MimeTypes { public static final String AUDIO_MPEG_L2 = BASE_TYPE_AUDIO + "/mpeg-L2"; public static final String AUDIO_RAW = BASE_TYPE_AUDIO + "/raw"; public static final String AUDIO_ALAW = BASE_TYPE_AUDIO + "/g711-alaw"; - public static final String AUDIO_ULAW = BASE_TYPE_AUDIO + "/g711-mlaw"; + public static final String AUDIO_MLAW = BASE_TYPE_AUDIO + "/g711-mlaw"; public static final String AUDIO_AC3 = BASE_TYPE_AUDIO + "/ac3"; public static final String AUDIO_E_AC3 = BASE_TYPE_AUDIO + "/eac3"; public static final String AUDIO_TRUEHD = BASE_TYPE_AUDIO + "/true-hd"; @@ -59,8 +59,9 @@ public final class MimeTypes { public static final String AUDIO_OPUS = BASE_TYPE_AUDIO + "/opus"; public static final String AUDIO_AMR_NB = BASE_TYPE_AUDIO + "/3gpp"; public static final String AUDIO_AMR_WB = BASE_TYPE_AUDIO + "/amr-wb"; - public static final String AUDIO_FLAC = BASE_TYPE_AUDIO + "/x-flac"; + public static final String AUDIO_FLAC = BASE_TYPE_AUDIO + "/flac"; public static final String AUDIO_ALAC = BASE_TYPE_AUDIO + "/alac"; + public static final String AUDIO_MSGSM = BASE_TYPE_AUDIO + "/gsm"; public static final String AUDIO_UNKNOWN = BASE_TYPE_AUDIO + "/x-unknown"; public static final String TEXT_VTT = BASE_TYPE_TEXT + "/vtt"; From 92206b9fc2434027cd524be1901c13b8131d5eeb Mon Sep 17 00:00:00 2001 From: olly Date: Sun, 7 May 2017 05:37:26 +0100 Subject: [PATCH 04/24] TTML: Ignore regions that don't declare origin and extent Issue: #2953 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=159218386 --- .../exoplayer2/text/ttml/TtmlDecoderTest.java | 10 ++++++--- .../exoplayer2/text/ttml/TtmlDecoder.java | 22 +++++++++++++------ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/text/ttml/TtmlDecoderTest.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/text/ttml/TtmlDecoderTest.java index 496e3f87de..492cf036b4 100644 --- a/library/core/src/androidTest/java/com/google/android/exoplayer2/text/ttml/TtmlDecoderTest.java +++ b/library/core/src/androidTest/java/com/google/android/exoplayer2/text/ttml/TtmlDecoderTest.java @@ -179,9 +179,13 @@ public final class TtmlDecoderTest extends InstrumentationTestCase { assertEquals(1, output.size()); ttmlCue = output.get(0); assertEquals("dolor", ttmlCue.text.toString()); - assertEquals(10f / 100f, ttmlCue.position); - assertEquals(80f / 100f, ttmlCue.line); - assertEquals(1f, ttmlCue.size); + assertEquals(Cue.DIMEN_UNSET, ttmlCue.position); + assertEquals(Cue.DIMEN_UNSET, ttmlCue.line); + assertEquals(Cue.DIMEN_UNSET, ttmlCue.size); + // TODO: Should be as below, once https://github.com/google/ExoPlayer/issues/2953 is fixed. + // assertEquals(10f / 100f, ttmlCue.position); + // assertEquals(80f / 100f, ttmlCue.line); + // assertEquals(1f, ttmlCue.size); output = subtitle.getCues(21000000); assertEquals(1, output.size()); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlDecoder.java b/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlDecoder.java index 0012ce2c22..e438aa1837 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlDecoder.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlDecoder.java @@ -222,9 +222,9 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder { /** * Parses a region declaration. *

- * If the region defines an origin and/or extent, it is required that they're defined as - * percentages of the viewport. Region declarations that define origin and/or extent in other - * formats are unsupported, and null is returned. + * If the region defines an origin and extent, it is required that they're defined as percentages + * of the viewport. Region declarations that define origin and extent in other formats are + * unsupported, and null is returned. */ private TtmlRegion parseRegionAttributes(XmlPullParser xmlParser) { String regionId = XmlPullParserUtil.getAttributeValue(xmlParser, TtmlNode.ATTR_ID); @@ -250,9 +250,13 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder { return null; } } else { + Log.w(TAG, "Ignoring region without an origin"); + return null; + // TODO: Should default to top left as below in this case, but need to fix + // https://github.com/google/ExoPlayer/issues/2953 first. // Origin is omitted. Default to top left. - position = 0; - line = 0; + // position = 0; + // line = 0; } float width; @@ -273,9 +277,13 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder { return null; } } else { + Log.w(TAG, "Ignoring region without an extent"); + return null; + // TODO: Should default to extent of parent as below in this case, but need to fix + // https://github.com/google/ExoPlayer/issues/2953 first. // Extent is omitted. Default to extent of parent. - width = 1; - height = 1; + // width = 1; + // height = 1; } @Cue.AnchorType int lineAnchor = Cue.ANCHOR_TYPE_START; From 76faa5b6d2d271474bcae6ee106177aa53de3ed3 Mon Sep 17 00:00:00 2001 From: olly Date: Mon, 19 Jun 2017 06:48:18 -0700 Subject: [PATCH 05/24] Move clearing of joining deadline back to onStopped ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=159421000 --- .../google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.java | 2 +- .../android/exoplayer2/video/MediaCodecVideoRenderer.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.java b/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.java index 4b629c8d2a..29423547b6 100644 --- a/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.java +++ b/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.java @@ -480,11 +480,11 @@ public final class LibvpxVideoRenderer extends BaseRenderer { protected void onStarted() { droppedFrames = 0; droppedFrameAccumulationStartTimeMs = SystemClock.elapsedRealtime(); - joiningDeadlineMs = C.TIME_UNSET; } @Override protected void onStopped() { + joiningDeadlineMs = C.TIME_UNSET; maybeNotifyDroppedFrames(); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java index 0304c33b3c..990a29dc4e 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java @@ -260,11 +260,11 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { super.onStarted(); droppedFrames = 0; droppedFrameAccumulationStartTimeMs = SystemClock.elapsedRealtime(); - joiningDeadlineMs = C.TIME_UNSET; } @Override protected void onStopped() { + joiningDeadlineMs = C.TIME_UNSET; maybeNotifyDroppedFrames(); super.onStopped(); } From 4b8cddbefd7f212b65b78c612ae7b12053bdb882 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20Wr=C3=B3tniak?= Date: Sat, 17 Jun 2017 16:18:43 +0200 Subject: [PATCH 06/24] Introduced failing unit test for ContentDataSource --- .../core/src/androidTest/AndroidManifest.xml | 3 + .../upstream/AndroidDataSourceTest.java | 31 +++++++++ .../exoplayer2/upstream/TestDataProvider.java | 64 +++++++++++++++++++ 3 files changed, 98 insertions(+) create mode 100644 library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/AndroidDataSourceTest.java create mode 100644 library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/TestDataProvider.java diff --git a/library/core/src/androidTest/AndroidManifest.xml b/library/core/src/androidTest/AndroidManifest.xml index 9eab386b51..8968ae59d6 100644 --- a/library/core/src/androidTest/AndroidManifest.xml +++ b/library/core/src/androidTest/AndroidManifest.xml @@ -24,6 +24,9 @@ android:allowBackup="false" tools:ignore="MissingApplicationIcon,HardcodedDebugMode"> + Date: Sat, 17 Jun 2017 16:26:29 +0200 Subject: [PATCH 07/24] InputStream creation for ContentDataSource changed --- .../google/android/exoplayer2/upstream/ContentDataSource.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/ContentDataSource.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/ContentDataSource.java index f806f47410..5d0d9a80e9 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/ContentDataSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/ContentDataSource.java @@ -71,7 +71,7 @@ public final class ContentDataSource implements DataSource { try { uri = dataSpec.uri; assetFileDescriptor = resolver.openAssetFileDescriptor(uri, "r"); - inputStream = new FileInputStream(assetFileDescriptor.getFileDescriptor()); + inputStream = assetFileDescriptor.createInputStream(); long skipped = inputStream.skip(dataSpec.position); if (skipped < dataSpec.position) { // We expect the skip to be satisfied in full. If it isn't then we're probably trying to From 66c461e65b57e289189846580ba42672539210e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20Wr=C3=B3tniak?= Date: Mon, 19 Jun 2017 12:46:09 +0200 Subject: [PATCH 08/24] Comments from https://github.com/google/ExoPlayer/pull/2963#discussion_r122669328 applied --- .../upstream/AndroidDataSourceConstants.java | 8 +++++ .../upstream/AndroidDataSourceTest.java | 31 ------------------- .../upstream/AssetDataSourceTest.java | 21 +++++++++++++ .../upstream/ContentDataSourceTest.java | 21 +++++++++++++ .../upstream/ContentDataSource.java | 18 ++++++----- 5 files changed, 61 insertions(+), 38 deletions(-) create mode 100644 library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/AndroidDataSourceConstants.java delete mode 100644 library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/AndroidDataSourceTest.java create mode 100644 library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/AssetDataSourceTest.java create mode 100644 library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/ContentDataSourceTest.java diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/AndroidDataSourceConstants.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/AndroidDataSourceConstants.java new file mode 100644 index 0000000000..ad19b7a824 --- /dev/null +++ b/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/AndroidDataSourceConstants.java @@ -0,0 +1,8 @@ +package com.google.android.exoplayer2.upstream; + +final class AndroidDataSourceConstants { + static final long SAMPLE_MP4_BYTES = 101597; + static final String SAMPLE_MP4_PATH = "/mp4/sample.mp4"; + + private AndroidDataSourceConstants() {} +} diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/AndroidDataSourceTest.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/AndroidDataSourceTest.java deleted file mode 100644 index 42dadaf379..0000000000 --- a/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/AndroidDataSourceTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.google.android.exoplayer2.upstream; - -import android.content.Context; -import android.net.Uri; -import android.test.InstrumentationTestCase; - -public class AndroidDataSourceTest extends InstrumentationTestCase { - - private static final long SAMPLE_MP4_BYTES = 101597; - private static final String SAMPLE_MP4_PATH = "/mp4/sample.mp4"; - - public void testAssetDataSource() throws Exception { - final Context context = getInstrumentation().getContext(); - AssetDataSource dataSource = new AssetDataSource(context); - Uri assetUri = Uri.parse("file:///android_asset" + SAMPLE_MP4_PATH); - DataSpec dataSpec = new DataSpec(assetUri); - long sourceLengthBytes = dataSource.open(dataSpec); - - assertEquals(SAMPLE_MP4_BYTES, sourceLengthBytes); - } - - public void testContentDataSource() throws Exception { - Context context = getInstrumentation().getContext(); - ContentDataSource dataSource = new ContentDataSource(context); - Uri contentUri = Uri.parse("content://exoplayer" + SAMPLE_MP4_PATH); - DataSpec dataSpec = new DataSpec(contentUri); - long sourceLengthBytes = dataSource.open(dataSpec); - - assertEquals(SAMPLE_MP4_BYTES, sourceLengthBytes); - } -} diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/AssetDataSourceTest.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/AssetDataSourceTest.java new file mode 100644 index 0000000000..178842bd4d --- /dev/null +++ b/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/AssetDataSourceTest.java @@ -0,0 +1,21 @@ +package com.google.android.exoplayer2.upstream; + +import android.content.Context; +import android.net.Uri; +import android.test.InstrumentationTestCase; + +import static com.google.android.exoplayer2.upstream.AndroidDataSourceConstants.SAMPLE_MP4_BYTES; +import static com.google.android.exoplayer2.upstream.AndroidDataSourceConstants.SAMPLE_MP4_PATH; + +public class AssetDataSourceTest extends InstrumentationTestCase { + + public void testAssetDataSource() throws Exception { + final Context context = getInstrumentation().getContext(); + AssetDataSource dataSource = new AssetDataSource(context); + Uri assetUri = Uri.parse("file:///android_asset" + SAMPLE_MP4_PATH); + DataSpec dataSpec = new DataSpec(assetUri); + long sourceLengthBytes = dataSource.open(dataSpec); + + assertEquals(SAMPLE_MP4_BYTES, sourceLengthBytes); + } +} diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/ContentDataSourceTest.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/ContentDataSourceTest.java new file mode 100644 index 0000000000..b2edeea0cc --- /dev/null +++ b/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/ContentDataSourceTest.java @@ -0,0 +1,21 @@ +package com.google.android.exoplayer2.upstream; + +import android.content.Context; +import android.net.Uri; +import android.test.InstrumentationTestCase; + +import static com.google.android.exoplayer2.upstream.AndroidDataSourceConstants.SAMPLE_MP4_BYTES; +import static com.google.android.exoplayer2.upstream.AndroidDataSourceConstants.SAMPLE_MP4_PATH; + +public class ContentDataSourceTest extends InstrumentationTestCase { + + public void testContentDataSource() throws Exception { + Context context = getInstrumentation().getContext(); + ContentDataSource dataSource = new ContentDataSource(context); + Uri contentUri = Uri.parse("content://exoplayer" + SAMPLE_MP4_PATH); + DataSpec dataSpec = new DataSpec(contentUri); + long sourceLengthBytes = dataSource.open(dataSpec); + + assertEquals(SAMPLE_MP4_BYTES, sourceLengthBytes); + } +} diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/ContentDataSource.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/ContentDataSource.java index 5d0d9a80e9..9421b7ba03 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/ContentDataSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/ContentDataSource.java @@ -71,7 +71,7 @@ public final class ContentDataSource implements DataSource { try { uri = dataSpec.uri; assetFileDescriptor = resolver.openAssetFileDescriptor(uri, "r"); - inputStream = assetFileDescriptor.createInputStream(); + inputStream = new FileInputStream(assetFileDescriptor.getFileDescriptor()); long skipped = inputStream.skip(dataSpec.position); if (skipped < dataSpec.position) { // We expect the skip to be satisfied in full. If it isn't then we're probably trying to @@ -81,12 +81,16 @@ public final class ContentDataSource implements DataSource { if (dataSpec.length != C.LENGTH_UNSET) { bytesRemaining = dataSpec.length; } else { - bytesRemaining = inputStream.available(); - if (bytesRemaining == 0) { - // FileInputStream.available() returns 0 if the remaining length cannot be determined, or - // if it's greater than Integer.MAX_VALUE. We don't know the true length in either case, - // so treat as unbounded. - bytesRemaining = C.LENGTH_UNSET; + bytesRemaining = assetFileDescriptor.getLength(); + if (bytesRemaining == AssetFileDescriptor.UNKNOWN_LENGTH) { + // The asset must extend to the end of the file. + bytesRemaining = inputStream.available(); + if (bytesRemaining == 0) { + // FileInputStream.available() returns 0 if the remaining length cannot be determined, or + // if it's greater than Integer.MAX_VALUE. We don't know the true length in either case, + // so treat as unbounded. + bytesRemaining = C.LENGTH_UNSET; + } } } } catch (IOException e) { From 795e3be44029878b5772014f92a5fb435b335299 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20Wr=C3=B3tniak?= Date: Mon, 19 Jun 2017 16:09:54 +0200 Subject: [PATCH 09/24] null AssetFileDescriptors support added in `ContentDataSource` --- .../upstream/AndroidDataSourceConstants.java | 8 +++++++ .../upstream/ContentDataSourceTest.java | 23 +++++++++++++++++-- .../exoplayer2/upstream/TestDataProvider.java | 4 ++++ .../upstream/ContentDataSource.java | 4 ++++ 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/AndroidDataSourceConstants.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/AndroidDataSourceConstants.java index ad19b7a824..d11202ccf2 100644 --- a/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/AndroidDataSourceConstants.java +++ b/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/AndroidDataSourceConstants.java @@ -1,8 +1,16 @@ package com.google.android.exoplayer2.upstream; +import android.content.ContentResolver; +import android.net.Uri; + final class AndroidDataSourceConstants { static final long SAMPLE_MP4_BYTES = 101597; static final String SAMPLE_MP4_PATH = "/mp4/sample.mp4"; + static final String TEST_DATA_PROVIDER_AUTHORITY = "exoplayer"; + static final Uri NULL_DESCRIPTOR_URI = new Uri.Builder() + .scheme(ContentResolver.SCHEME_CONTENT) + .authority(TEST_DATA_PROVIDER_AUTHORITY) + .build(); private AndroidDataSourceConstants() {} } diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/ContentDataSourceTest.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/ContentDataSourceTest.java index b2edeea0cc..1cd14b45e1 100644 --- a/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/ContentDataSourceTest.java +++ b/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/ContentDataSourceTest.java @@ -1,21 +1,40 @@ package com.google.android.exoplayer2.upstream; +import android.content.ContentResolver; import android.content.Context; import android.net.Uri; import android.test.InstrumentationTestCase; +import static com.google.android.exoplayer2.upstream.AndroidDataSourceConstants.NULL_DESCRIPTOR_URI; import static com.google.android.exoplayer2.upstream.AndroidDataSourceConstants.SAMPLE_MP4_BYTES; import static com.google.android.exoplayer2.upstream.AndroidDataSourceConstants.SAMPLE_MP4_PATH; +import static com.google.android.exoplayer2.upstream.AndroidDataSourceConstants.TEST_DATA_PROVIDER_AUTHORITY; public class ContentDataSourceTest extends InstrumentationTestCase { - public void testContentDataSource() throws Exception { + public void testValidContentDataSource() throws Exception { Context context = getInstrumentation().getContext(); ContentDataSource dataSource = new ContentDataSource(context); - Uri contentUri = Uri.parse("content://exoplayer" + SAMPLE_MP4_PATH); + Uri contentUri = new Uri.Builder() + .scheme(ContentResolver.SCHEME_CONTENT) + .authority(TEST_DATA_PROVIDER_AUTHORITY) + .path(SAMPLE_MP4_PATH).build(); DataSpec dataSpec = new DataSpec(contentUri); long sourceLengthBytes = dataSource.open(dataSpec); assertEquals(SAMPLE_MP4_BYTES, sourceLengthBytes); } + + public void testNullContentDataSource() throws Exception { + Context context = getInstrumentation().getContext(); + ContentDataSource dataSource = new ContentDataSource(context); + DataSpec dataSpec = new DataSpec(NULL_DESCRIPTOR_URI); + + try { + dataSource.open(dataSpec); + fail("Expected exception not thrown."); + } catch (ContentDataSource.ContentDataSourceException e) { + // Expected. + } + } } diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/TestDataProvider.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/TestDataProvider.java index 851e7b4b0c..f6e09a7067 100644 --- a/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/TestDataProvider.java +++ b/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/TestDataProvider.java @@ -29,6 +29,10 @@ public class TestDataProvider extends ContentProvider { @Nullable @Override public AssetFileDescriptor openAssetFile(@NonNull final Uri uri, @NonNull final String mode) throws FileNotFoundException { + if (uri.equals(AndroidDataSourceConstants.NULL_DESCRIPTOR_URI)) { + return null; + } + try { Context context = getContext(); assertNotNull(context); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/ContentDataSource.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/ContentDataSource.java index 9421b7ba03..3a9be552d2 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/ContentDataSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/ContentDataSource.java @@ -22,6 +22,7 @@ import android.net.Uri; import com.google.android.exoplayer2.C; import java.io.EOFException; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; @@ -71,6 +72,9 @@ public final class ContentDataSource implements DataSource { try { uri = dataSpec.uri; assetFileDescriptor = resolver.openAssetFileDescriptor(uri, "r"); + if (assetFileDescriptor == null) { + throw new FileNotFoundException("Could not open file descriptor for: " + uri); + } inputStream = new FileInputStream(assetFileDescriptor.getFileDescriptor()); long skipped = inputStream.skip(dataSpec.position); if (skipped < dataSpec.position) { From 5eb64dbe1208a61c157d87f1e33fc33180ad85c3 Mon Sep 17 00:00:00 2001 From: Oliver Woodman Date: Fri, 23 Jun 2017 17:20:51 +0100 Subject: [PATCH 10/24] Fix ContentDataSource and enhance tests to validate read data --- .../core/src/androidTest/AndroidManifest.xml | 4 +- .../assets/binary/1024_incrementing_bytes.mp3 | Bin 0 -> 1024 bytes .../upstream/AndroidDataSourceConstants.java | 16 -- .../upstream/AssetDataSourceTest.java | 59 ++++++-- .../upstream/ContentDataSourceTest.java | 139 ++++++++++++++---- .../exoplayer2/upstream/TestDataProvider.java | 68 --------- .../upstream/ContentDataSource.java | 5 +- .../android/exoplayer2/testutil/TestUtil.java | 17 +++ 8 files changed, 185 insertions(+), 123 deletions(-) create mode 100644 library/core/src/androidTest/assets/binary/1024_incrementing_bytes.mp3 delete mode 100644 library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/AndroidDataSourceConstants.java delete mode 100644 library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/TestDataProvider.java diff --git a/library/core/src/androidTest/AndroidManifest.xml b/library/core/src/androidTest/AndroidManifest.xml index 8968ae59d6..a50de35b62 100644 --- a/library/core/src/androidTest/AndroidManifest.xml +++ b/library/core/src/androidTest/AndroidManifest.xml @@ -25,8 +25,8 @@ tools:ignore="MissingApplicationIcon,HardcodedDebugMode"> + android:authorities="com.google.android.exoplayer2.core.test" + android:name="com.google.android.exoplayer2.upstream.ContentDataSourceTest$TestContentProvider"/> MC+6cQE@6%&_`l#-T_m6KOcR8m$^Ra4i{)Y8_`)zddH zG%_|ZH8Z!cw6eCbwX=6{baHlab#wRd^z!!c_45x13RUz zF>}`JIdkXDU$Ah|;w4L$Enl&6)#^2C*R9{Mant54TeofBv2)k%J$v` Date: Fri, 23 Jun 2017 17:37:28 +0100 Subject: [PATCH 11/24] Mini cleanup --- .../exoplayer2/upstream/ContentDataSourceTest.java | 10 ++++++---- .../android/exoplayer2/upstream/ContentDataSource.java | 6 +++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/ContentDataSourceTest.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/ContentDataSourceTest.java index 10a408c578..d8743a0a2c 100644 --- a/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/ContentDataSourceTest.java +++ b/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/ContentDataSourceTest.java @@ -33,6 +33,7 @@ import java.io.IOException; */ public final class ContentDataSourceTest extends InstrumentationTestCase { + private static final String AUTHORITY = "com.google.android.exoplayer2.core.test"; private static final String DATA_PATH = "binary/1024_incrementing_bytes.mp3"; private static final long DATA_LENGTH = 1024; @@ -40,7 +41,7 @@ public final class ContentDataSourceTest extends InstrumentationTestCase { ContentDataSource dataSource = new ContentDataSource(getInstrumentation().getContext()); Uri contentUri = new Uri.Builder() .scheme(ContentResolver.SCHEME_CONTENT) - .authority(TestContentProvider.AUTHORITY) + .authority(AUTHORITY) .path(DATA_PATH).build(); DataSpec dataSpec = new DataSpec(contentUri); try { @@ -57,7 +58,7 @@ public final class ContentDataSourceTest extends InstrumentationTestCase { ContentDataSource dataSource = new ContentDataSource(getInstrumentation().getContext()); Uri contentUri = new Uri.Builder() .scheme(ContentResolver.SCHEME_CONTENT) - .authority(TestContentProvider.AUTHORITY) + .authority(AUTHORITY) .build(); DataSpec dataSpec = new DataSpec(contentUri); try { @@ -70,10 +71,11 @@ public final class ContentDataSourceTest extends InstrumentationTestCase { } } + /** + * A {@link ContentProvider} for the test. + */ public static final class TestContentProvider extends ContentProvider { - private static final String AUTHORITY = "com.google.android.exoplayer2.core.test"; - @Override public boolean onCreate() { return true; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/ContentDataSource.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/ContentDataSource.java index 507162519a..d118b91378 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/ContentDataSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/ContentDataSource.java @@ -91,9 +91,9 @@ public final class ContentDataSource implements DataSource { // The asset must extend to the end of the file. bytesRemaining = inputStream.available(); if (bytesRemaining == 0) { - // FileInputStream.available() returns 0 if the remaining length cannot be determined, or - // if it's greater than Integer.MAX_VALUE. We don't know the true length in either case, - // so treat as unbounded. + // FileInputStream.available() returns 0 if the remaining length cannot be determined, + // or if it's greater than Integer.MAX_VALUE. We don't know the true length in either + // case, so treat as unbounded. bytesRemaining = C.LENGTH_UNSET; } } From fd9b162d0fe635e9dbbbcffd0ff1a63ee45cfc08 Mon Sep 17 00:00:00 2001 From: olly Date: Fri, 23 Jun 2017 09:44:27 -0700 Subject: [PATCH 12/24] Fix setSelectionOverride(index, tracks, null) Issue: #2988 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=159958591 --- .../MappingTrackSelectorTest.java | 196 ++++++++++++++++++ .../android/exoplayer2/source/TrackGroup.java | 2 +- .../trackselection/MappingTrackSelector.java | 8 +- 3 files changed, 201 insertions(+), 5 deletions(-) create mode 100644 library/core/src/androidTest/java/com/google/android/exoplayer2/trackselection/MappingTrackSelectorTest.java diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/trackselection/MappingTrackSelectorTest.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/trackselection/MappingTrackSelectorTest.java new file mode 100644 index 0000000000..c31c651384 --- /dev/null +++ b/library/core/src/androidTest/java/com/google/android/exoplayer2/trackselection/MappingTrackSelectorTest.java @@ -0,0 +1,196 @@ +/* + * 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 com.google.android.exoplayer2.trackselection; + +import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.ExoPlaybackException; +import com.google.android.exoplayer2.Format; +import com.google.android.exoplayer2.RendererCapabilities; +import com.google.android.exoplayer2.source.TrackGroup; +import com.google.android.exoplayer2.source.TrackGroupArray; +import com.google.android.exoplayer2.util.MimeTypes; +import junit.framework.TestCase; + +/** + * Unit tests for {@link MappingTrackSelector}. + */ +public final class MappingTrackSelectorTest extends TestCase { + + private static final RendererCapabilities VIDEO_CAPABILITIES = + new FakeRendererCapabilities(C.TRACK_TYPE_VIDEO); + private static final RendererCapabilities AUDIO_CAPABILITIES = + new FakeRendererCapabilities(C.TRACK_TYPE_AUDIO); + private static final RendererCapabilities[] RENDERER_CAPABILITIES = new RendererCapabilities[] { + VIDEO_CAPABILITIES, AUDIO_CAPABILITIES + }; + + private static final TrackGroup VIDEO_TRACK_GROUP = new TrackGroup( + Format.createVideoSampleFormat("video", MimeTypes.VIDEO_H264, null, Format.NO_VALUE, + Format.NO_VALUE, 1024, 768, Format.NO_VALUE, null, null)); + private static final TrackGroup AUDIO_TRACK_GROUP = new TrackGroup( + Format.createAudioSampleFormat("audio", MimeTypes.AUDIO_AAC, null, Format.NO_VALUE, + Format.NO_VALUE, 2, 44100, null, null, 0, null)); + private static final TrackGroupArray TRACK_GROUPS = new TrackGroupArray( + VIDEO_TRACK_GROUP, AUDIO_TRACK_GROUP); + + private static final TrackSelection[] TRACK_SELECTIONS = new TrackSelection[] { + new FixedTrackSelection(VIDEO_TRACK_GROUP, 0), + new FixedTrackSelection(AUDIO_TRACK_GROUP, 0) + }; + + /** + * Tests that the video and audio track groups are mapped onto the correct renderers. + */ + public void testMapping() throws ExoPlaybackException { + FakeMappingTrackSelector trackSelector = new FakeMappingTrackSelector(); + trackSelector.selectTracks(RENDERER_CAPABILITIES, TRACK_GROUPS); + trackSelector.assertMappedTrackGroups(0, VIDEO_TRACK_GROUP); + trackSelector.assertMappedTrackGroups(1, AUDIO_TRACK_GROUP); + } + + /** + * Tests that the video and audio track groups are mapped onto the correct renderers when the + * renderer ordering is reversed. + */ + public void testMappingReverseOrder() throws ExoPlaybackException { + FakeMappingTrackSelector trackSelector = new FakeMappingTrackSelector(); + RendererCapabilities[] reverseOrderRendererCapabilities = new RendererCapabilities[] { + AUDIO_CAPABILITIES, VIDEO_CAPABILITIES}; + trackSelector.selectTracks(reverseOrderRendererCapabilities, TRACK_GROUPS); + trackSelector.assertMappedTrackGroups(0, AUDIO_TRACK_GROUP); + trackSelector.assertMappedTrackGroups(1, VIDEO_TRACK_GROUP); + } + + /** + * Tests video and audio track groups are mapped onto the correct renderers when there are + * multiple track groups of the same type. + */ + public void testMappingMulti() throws ExoPlaybackException { + FakeMappingTrackSelector trackSelector = new FakeMappingTrackSelector(); + TrackGroupArray multiTrackGroups = new TrackGroupArray(VIDEO_TRACK_GROUP, AUDIO_TRACK_GROUP, + VIDEO_TRACK_GROUP); + trackSelector.selectTracks(RENDERER_CAPABILITIES, multiTrackGroups); + trackSelector.assertMappedTrackGroups(0, VIDEO_TRACK_GROUP, VIDEO_TRACK_GROUP); + trackSelector.assertMappedTrackGroups(1, AUDIO_TRACK_GROUP); + } + + /** + * Tests the result of {@link MappingTrackSelector#selectTracks(RendererCapabilities[], + * TrackGroupArray[], int[][][])} is propagated correctly to the result of + * {@link MappingTrackSelector#selectTracks(RendererCapabilities[], TrackGroupArray)}. + */ + public void testSelectTracks() throws ExoPlaybackException { + FakeMappingTrackSelector trackSelector = new FakeMappingTrackSelector(TRACK_SELECTIONS); + TrackSelectorResult result = trackSelector.selectTracks(RENDERER_CAPABILITIES, TRACK_GROUPS); + assertEquals(TRACK_SELECTIONS[0], result.selections.get(0)); + assertEquals(TRACK_SELECTIONS[1], result.selections.get(1)); + } + + /** + * Tests that a null override clears a track selection. + */ + public void testSelectTracksWithNullOverride() throws ExoPlaybackException { + FakeMappingTrackSelector trackSelector = new FakeMappingTrackSelector(TRACK_SELECTIONS); + trackSelector.setSelectionOverride(0, new TrackGroupArray(VIDEO_TRACK_GROUP), null); + TrackSelectorResult result = trackSelector.selectTracks(RENDERER_CAPABILITIES, TRACK_GROUPS); + assertNull(result.selections.get(0)); + assertEquals(TRACK_SELECTIONS[1], result.selections.get(1)); + } + + /** + * Tests that a null override can be cleared. + */ + public void testSelectTracksWithClearedNullOverride() throws ExoPlaybackException { + FakeMappingTrackSelector trackSelector = new FakeMappingTrackSelector(TRACK_SELECTIONS); + trackSelector.setSelectionOverride(0, new TrackGroupArray(VIDEO_TRACK_GROUP), null); + trackSelector.clearSelectionOverride(0, new TrackGroupArray(VIDEO_TRACK_GROUP)); + TrackSelectorResult result = trackSelector.selectTracks(RENDERER_CAPABILITIES, TRACK_GROUPS); + assertEquals(TRACK_SELECTIONS[0], result.selections.get(0)); + assertEquals(TRACK_SELECTIONS[1], result.selections.get(1)); + } + + /** + * Tests that an override is not applied for a different set of available track groups. + */ + public void testSelectTracksWithNullOverrideForDifferentTracks() throws ExoPlaybackException { + FakeMappingTrackSelector trackSelector = new FakeMappingTrackSelector(TRACK_SELECTIONS); + trackSelector.setSelectionOverride(0, new TrackGroupArray(VIDEO_TRACK_GROUP), null); + TrackSelectorResult result = trackSelector.selectTracks(RENDERER_CAPABILITIES, + new TrackGroupArray(VIDEO_TRACK_GROUP, AUDIO_TRACK_GROUP, VIDEO_TRACK_GROUP)); + assertEquals(TRACK_SELECTIONS[0], result.selections.get(0)); + assertEquals(TRACK_SELECTIONS[1], result.selections.get(1)); + } + + /** + * A {@link MappingTrackSelector} that returns a fixed result from + * {@link #selectTracks(RendererCapabilities[], TrackGroupArray[], int[][][])}. + */ + private static final class FakeMappingTrackSelector extends MappingTrackSelector { + + private final TrackSelection[] result; + private TrackGroupArray[] lastRendererTrackGroupArrays; + + public FakeMappingTrackSelector(TrackSelection... result) { + this.result = result.length == 0 ? null : result; + } + + @Override + protected TrackSelection[] selectTracks(RendererCapabilities[] rendererCapabilities, + TrackGroupArray[] rendererTrackGroupArrays, int[][][] rendererFormatSupports) + throws ExoPlaybackException { + lastRendererTrackGroupArrays = rendererTrackGroupArrays; + return result == null ? new TrackSelection[rendererCapabilities.length] : result; + } + + public void assertMappedTrackGroups(int rendererIndex, TrackGroup... expected) { + assertEquals(expected.length, lastRendererTrackGroupArrays[rendererIndex].length); + for (int i = 0; i < expected.length; i++) { + assertEquals(expected[i], lastRendererTrackGroupArrays[rendererIndex].get(i)); + } + } + + } + + /** + * A {@link RendererCapabilities} that advertises adaptive support for all tracks of a given type. + */ + private static final class FakeRendererCapabilities implements RendererCapabilities { + + private final int trackType; + + public FakeRendererCapabilities(int trackType) { + this.trackType = trackType; + } + + @Override + public int getTrackType() { + return trackType; + } + + @Override + public int supportsFormat(Format format) throws ExoPlaybackException { + return MimeTypes.getTrackType(format.sampleMimeType) == trackType + ? (FORMAT_HANDLED | ADAPTIVE_SEAMLESS) : FORMAT_UNSUPPORTED_TYPE; + } + + @Override + public int supportsMixedMimeTypeAdaptation() throws ExoPlaybackException { + return ADAPTIVE_SEAMLESS; + } + + } + +} diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/TrackGroup.java b/library/core/src/main/java/com/google/android/exoplayer2/source/TrackGroup.java index 393ac1988a..06410d5426 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/TrackGroup.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/TrackGroup.java @@ -42,7 +42,7 @@ public final class TrackGroup { private int hashCode; /** - * @param formats The track formats. Must not be null or contain null elements. + * @param formats The track formats. Must not be null, contain null elements or be of length 0. */ public TrackGroup(Format... formats) { Assertions.checkState(formats.length > 0); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/MappingTrackSelector.java b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/MappingTrackSelector.java index 690723cf15..3499efdb16 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/MappingTrackSelector.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/MappingTrackSelector.java @@ -304,10 +304,10 @@ public abstract class MappingTrackSelector extends TrackSelector { trackSelections[i] = null; } else { TrackGroupArray rendererTrackGroup = rendererTrackGroupArrays[i]; - Map overrides = selectionOverrides.get(i); - SelectionOverride override = overrides == null ? null : overrides.get(rendererTrackGroup); - if (override != null) { - trackSelections[i] = override.createTrackSelection(rendererTrackGroup); + if (hasSelectionOverride(i, rendererTrackGroup)) { + SelectionOverride override = selectionOverrides.get(i).get(rendererTrackGroup); + trackSelections[i] = override == null ? null + : override.createTrackSelection(rendererTrackGroup); } } } From d4e598f4172352e1ab6eb916aed9de1c03686957 Mon Sep 17 00:00:00 2001 From: Alex Birkett Date: Fri, 23 Jun 2017 18:56:40 +0200 Subject: [PATCH 13/24] Make OkHttpDataSource userAgent parameter optional --- .../ext/okhttp/OkHttpDataSource.java | 21 ++++++++++++------- .../ext/okhttp/OkHttpDataSourceFactory.java | 11 ++++++---- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSource.java b/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSource.java index 47850c0637..fac35bd427 100644 --- a/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSource.java +++ b/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSource.java @@ -16,6 +16,8 @@ package com.google.android.exoplayer2.ext.okhttp; import android.net.Uri; +import android.support.annotation.Nullable; + import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.upstream.DataSourceException; import com.google.android.exoplayer2.upstream.DataSpec; @@ -67,11 +69,11 @@ public class OkHttpDataSource implements HttpDataSource { /** * @param callFactory A {@link Call.Factory} (typically an {@link okhttp3.OkHttpClient}) for use * by the source. - * @param userAgent The User-Agent string that should be used. + * @param userAgent An optional User-Agent string that should be used. * @param contentTypePredicate An optional {@link Predicate}. If a content type is rejected by the * predicate then a InvalidContentTypeException} is thrown from {@link #open(DataSpec)}. */ - public OkHttpDataSource(Call.Factory callFactory, String userAgent, + public OkHttpDataSource(Call.Factory callFactory, @Nullable String userAgent, Predicate contentTypePredicate) { this(callFactory, userAgent, contentTypePredicate, null); } @@ -79,13 +81,13 @@ public class OkHttpDataSource implements HttpDataSource { /** * @param callFactory A {@link Call.Factory} (typically an {@link okhttp3.OkHttpClient}) for use * by the source. - * @param userAgent The User-Agent string that should be used. + * @param userAgent An optional User-Agent string that should be used. * @param contentTypePredicate An optional {@link Predicate}. If a content type is rejected by the * predicate then a {@link InvalidContentTypeException} is thrown from * {@link #open(DataSpec)}. * @param listener An optional listener. */ - public OkHttpDataSource(Call.Factory callFactory, String userAgent, + public OkHttpDataSource(Call.Factory callFactory, @Nullable String userAgent, Predicate contentTypePredicate, TransferListener listener) { this(callFactory, userAgent, contentTypePredicate, listener, null, null); } @@ -93,7 +95,7 @@ public class OkHttpDataSource implements HttpDataSource { /** * @param callFactory A {@link Call.Factory} (typically an {@link okhttp3.OkHttpClient}) for use * by the source. - * @param userAgent The User-Agent string that should be used. + * @param userAgent An optional User-Agent string that should be used. * @param contentTypePredicate An optional {@link Predicate}. If a content type is rejected by the * predicate then a {@link InvalidContentTypeException} is thrown from * {@link #open(DataSpec)}. @@ -102,11 +104,11 @@ public class OkHttpDataSource implements HttpDataSource { * @param defaultRequestProperties The optional default {@link RequestProperties} to be sent to * the server as HTTP headers on every request. */ - public OkHttpDataSource(Call.Factory callFactory, String userAgent, + public OkHttpDataSource(Call.Factory callFactory, @Nullable String userAgent, Predicate contentTypePredicate, TransferListener listener, CacheControl cacheControl, RequestProperties defaultRequestProperties) { this.callFactory = Assertions.checkNotNull(callFactory); - this.userAgent = Assertions.checkNotEmpty(userAgent); + this.userAgent = userAgent; this.contentTypePredicate = contentTypePredicate; this.listener = listener; this.cacheControl = cacheControl; @@ -280,7 +282,10 @@ public class OkHttpDataSource implements HttpDataSource { } builder.addHeader("Range", rangeRequest); } - builder.addHeader("User-Agent", userAgent); + if (userAgent != null) { + builder.addHeader("User-Agent", userAgent); + } + if (!allowGzip) { builder.addHeader("Accept-Encoding", "identity"); } diff --git a/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSourceFactory.java b/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSourceFactory.java index 5228065db1..6ee09df7de 100644 --- a/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSourceFactory.java +++ b/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSourceFactory.java @@ -15,6 +15,8 @@ */ package com.google.android.exoplayer2.ext.okhttp; +import android.support.annotation.Nullable; + import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.HttpDataSource; import com.google.android.exoplayer2.upstream.HttpDataSource.BaseFactory; @@ -36,10 +38,10 @@ public final class OkHttpDataSourceFactory extends BaseFactory { /** * @param callFactory A {@link Call.Factory} (typically an {@link okhttp3.OkHttpClient}) for use * by the sources created by the factory. - * @param userAgent The User-Agent string that should be used. + * @param userAgent An optional User-Agent string that should be used. * @param listener An optional listener. */ - public OkHttpDataSourceFactory(Call.Factory callFactory, String userAgent, + public OkHttpDataSourceFactory(Call.Factory callFactory, @Nullable String userAgent, TransferListener listener) { this(callFactory, userAgent, listener, null); } @@ -47,11 +49,12 @@ public final class OkHttpDataSourceFactory extends BaseFactory { /** * @param callFactory A {@link Call.Factory} (typically an {@link okhttp3.OkHttpClient}) for use * by the sources created by the factory. - * @param userAgent The User-Agent string that should be used. + * @param userAgent An optional User-Agent string that should be used. * @param listener An optional listener. * @param cacheControl An optional {@link CacheControl} for setting the Cache-Control header. */ - public OkHttpDataSourceFactory(Call.Factory callFactory, String userAgent, + public OkHttpDataSourceFactory(Call.Factory callFactory, + @Nullable String userAgent, TransferListener listener, CacheControl cacheControl) { this.callFactory = callFactory; this.userAgent = userAgent; From 045a153cb7afdffc69b46adb9de1aad8b14b909f Mon Sep 17 00:00:00 2001 From: Oliver Woodman Date: Sun, 25 Jun 2017 15:16:11 +0100 Subject: [PATCH 14/24] Clean up okhttp datasource. --- .../ext/okhttp/OkHttpDataSource.java | 39 ++++++++++--------- .../ext/okhttp/OkHttpDataSourceFactory.java | 24 ++++++------ 2 files changed, 33 insertions(+), 30 deletions(-) diff --git a/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSource.java b/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSource.java index fac35bd427..167fc68e86 100644 --- a/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSource.java +++ b/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSource.java @@ -16,8 +16,8 @@ package com.google.android.exoplayer2.ext.okhttp; import android.net.Uri; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; - import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.upstream.DataSourceException; import com.google.android.exoplayer2.upstream.DataSpec; @@ -47,13 +47,14 @@ public class OkHttpDataSource implements HttpDataSource { private static final AtomicReference skipBufferReference = new AtomicReference<>(); - private final Call.Factory callFactory; - private final String userAgent; - private final Predicate contentTypePredicate; - private final TransferListener listener; - private final CacheControl cacheControl; - private final RequestProperties defaultRequestProperties; - private final RequestProperties requestProperties; + @NonNull private final Call.Factory callFactory; + @NonNull private final RequestProperties requestProperties; + + @Nullable private final String userAgent; + @Nullable private final Predicate contentTypePredicate; + @Nullable private final TransferListener listener; + @Nullable private final CacheControl cacheControl; + @Nullable private final RequestProperties defaultRequestProperties; private DataSpec dataSpec; private Response response; @@ -69,33 +70,34 @@ public class OkHttpDataSource implements HttpDataSource { /** * @param callFactory A {@link Call.Factory} (typically an {@link okhttp3.OkHttpClient}) for use * by the source. - * @param userAgent An optional User-Agent string that should be used. + * @param userAgent An optional User-Agent string. * @param contentTypePredicate An optional {@link Predicate}. If a content type is rejected by the * predicate then a InvalidContentTypeException} is thrown from {@link #open(DataSpec)}. */ - public OkHttpDataSource(Call.Factory callFactory, @Nullable String userAgent, - Predicate contentTypePredicate) { + public OkHttpDataSource(@NonNull Call.Factory callFactory, @Nullable String userAgent, + @Nullable Predicate contentTypePredicate) { this(callFactory, userAgent, contentTypePredicate, null); } /** * @param callFactory A {@link Call.Factory} (typically an {@link okhttp3.OkHttpClient}) for use * by the source. - * @param userAgent An optional User-Agent string that should be used. + * @param userAgent An optional User-Agent string. * @param contentTypePredicate An optional {@link Predicate}. If a content type is rejected by the * predicate then a {@link InvalidContentTypeException} is thrown from * {@link #open(DataSpec)}. * @param listener An optional listener. */ - public OkHttpDataSource(Call.Factory callFactory, @Nullable String userAgent, - Predicate contentTypePredicate, TransferListener listener) { + public OkHttpDataSource(@NonNull Call.Factory callFactory, @Nullable String userAgent, + @Nullable Predicate contentTypePredicate, + @Nullable TransferListener listener) { this(callFactory, userAgent, contentTypePredicate, listener, null, null); } /** * @param callFactory A {@link Call.Factory} (typically an {@link okhttp3.OkHttpClient}) for use * by the source. - * @param userAgent An optional User-Agent string that should be used. + * @param userAgent An optional User-Agent string. * @param contentTypePredicate An optional {@link Predicate}. If a content type is rejected by the * predicate then a {@link InvalidContentTypeException} is thrown from * {@link #open(DataSpec)}. @@ -104,9 +106,10 @@ public class OkHttpDataSource implements HttpDataSource { * @param defaultRequestProperties The optional default {@link RequestProperties} to be sent to * the server as HTTP headers on every request. */ - public OkHttpDataSource(Call.Factory callFactory, @Nullable String userAgent, - Predicate contentTypePredicate, TransferListener listener, - CacheControl cacheControl, RequestProperties defaultRequestProperties) { + public OkHttpDataSource(@NonNull Call.Factory callFactory, @Nullable String userAgent, + @Nullable Predicate contentTypePredicate, + @Nullable TransferListener listener, + @Nullable CacheControl cacheControl, @Nullable RequestProperties defaultRequestProperties) { this.callFactory = Assertions.checkNotNull(callFactory); this.userAgent = userAgent; this.contentTypePredicate = contentTypePredicate; diff --git a/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSourceFactory.java b/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSourceFactory.java index 6ee09df7de..32fc5a58cb 100644 --- a/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSourceFactory.java +++ b/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSourceFactory.java @@ -15,8 +15,8 @@ */ package com.google.android.exoplayer2.ext.okhttp; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; - import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.HttpDataSource; import com.google.android.exoplayer2.upstream.HttpDataSource.BaseFactory; @@ -30,32 +30,32 @@ import okhttp3.Call; */ public final class OkHttpDataSourceFactory extends BaseFactory { - private final Call.Factory callFactory; - private final String userAgent; - private final TransferListener listener; - private final CacheControl cacheControl; + @NonNull private final Call.Factory callFactory; + @Nullable private final String userAgent; + @Nullable private final TransferListener listener; + @Nullable private final CacheControl cacheControl; /** * @param callFactory A {@link Call.Factory} (typically an {@link okhttp3.OkHttpClient}) for use * by the sources created by the factory. - * @param userAgent An optional User-Agent string that should be used. + * @param userAgent An optional User-Agent string. * @param listener An optional listener. */ - public OkHttpDataSourceFactory(Call.Factory callFactory, @Nullable String userAgent, - TransferListener listener) { + public OkHttpDataSourceFactory(@NonNull Call.Factory callFactory, @Nullable String userAgent, + @Nullable TransferListener listener) { this(callFactory, userAgent, listener, null); } /** * @param callFactory A {@link Call.Factory} (typically an {@link okhttp3.OkHttpClient}) for use * by the sources created by the factory. - * @param userAgent An optional User-Agent string that should be used. + * @param userAgent An optional User-Agent string. * @param listener An optional listener. * @param cacheControl An optional {@link CacheControl} for setting the Cache-Control header. */ - public OkHttpDataSourceFactory(Call.Factory callFactory, - @Nullable String userAgent, - TransferListener listener, CacheControl cacheControl) { + public OkHttpDataSourceFactory(@NonNull Call.Factory callFactory, @Nullable String userAgent, + @Nullable TransferListener listener, + @Nullable CacheControl cacheControl) { this.callFactory = callFactory; this.userAgent = userAgent; this.listener = listener; From a5eba0162b08f786d5a57b28746737a9ed83504e Mon Sep 17 00:00:00 2001 From: hoangtc Date: Mon, 26 Jun 2017 02:46:42 -0700 Subject: [PATCH 15/24] Update DrmSessionException. Make DrmSessionException takes in Throwable cause instead of Exception cause, which is more limiting and doesn't add any benefit. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=160121486 --- .../java/com/google/android/exoplayer2/drm/DrmSession.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/DrmSession.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/DrmSession.java index 538db9e1d9..cd694396b7 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/DrmSession.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/DrmSession.java @@ -28,11 +28,11 @@ import java.util.Map; @TargetApi(16) public interface DrmSession { - /** Wraps the exception which is the cause of the error state. */ + /** Wraps the throwable which is the cause of the error state. */ class DrmSessionException extends Exception { - public DrmSessionException(Exception e) { - super(e); + public DrmSessionException(Throwable cause) { + super(cause); } } From 2f7de7d3e8a7b29f29d429d1deaffee7a33a5883 Mon Sep 17 00:00:00 2001 From: olly Date: Mon, 26 Jun 2017 04:02:03 -0700 Subject: [PATCH 16/24] Merge ContentDataSource fixes + tests from GitHub https://github.com/google/ExoPlayer/pull/2963/files https://github.com/google/ExoPlayer/commit/8bb643976fe20d1ec684291aa7bf5337e474bec4 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=160128047 --- .../upstream/AssetDataSourceTest.java | 35 +++++-------------- .../upstream/ContentDataSourceTest.java | 13 ++----- .../android/exoplayer2/testutil/TestUtil.java | 22 ++++++++++++ 3 files changed, 33 insertions(+), 37 deletions(-) diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/AssetDataSourceTest.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/AssetDataSourceTest.java index d8e61eb94c..102c89ec2b 100644 --- a/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/AssetDataSourceTest.java +++ b/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/AssetDataSourceTest.java @@ -15,10 +15,8 @@ */ package com.google.android.exoplayer2.upstream; -import android.content.Context; import android.net.Uri; import android.test.InstrumentationTestCase; -import android.test.MoreAsserts; import com.google.android.exoplayer2.testutil.TestUtil; /** @@ -27,36 +25,19 @@ import com.google.android.exoplayer2.testutil.TestUtil; public final class AssetDataSourceTest extends InstrumentationTestCase { private static final String DATA_PATH = "binary/1024_incrementing_bytes.mp3"; - private static final long DATA_LENGTH = 1024; public void testReadFileUri() throws Exception { - Context context = getInstrumentation().getContext(); - AssetDataSource dataSource = new AssetDataSource(context); - Uri assetUri = Uri.parse("file:///android_asset/" + DATA_PATH); - DataSpec dataSpec = new DataSpec(assetUri); - try { - long length = dataSource.open(dataSpec); - assertEquals(DATA_LENGTH, length); - byte[] readData = TestUtil.readToEnd(dataSource); - MoreAsserts.assertEquals(TestUtil.getByteArray(getInstrumentation(), DATA_PATH), readData); - } finally { - dataSource.close(); - } + AssetDataSource dataSource = new AssetDataSource(getInstrumentation().getContext()); + DataSpec dataSpec = new DataSpec(Uri.parse("file:///android_asset/" + DATA_PATH)); + TestUtil.assertDataSourceContent(dataSource, dataSpec, + TestUtil.getByteArray(getInstrumentation(), DATA_PATH)); } public void testReadAssetUri() throws Exception { - Context context = getInstrumentation().getContext(); - AssetDataSource dataSource = new AssetDataSource(context); - Uri assetUri = Uri.parse("asset:///" + DATA_PATH); - DataSpec dataSpec = new DataSpec(assetUri); - try { - long length = dataSource.open(dataSpec); - assertEquals(DATA_LENGTH, length); - byte[] readData = TestUtil.readToEnd(dataSource); - MoreAsserts.assertEquals(TestUtil.getByteArray(getInstrumentation(), DATA_PATH), readData); - } finally { - dataSource.close(); - } + AssetDataSource dataSource = new AssetDataSource(getInstrumentation().getContext()); + DataSpec dataSpec = new DataSpec(Uri.parse("asset:///" + DATA_PATH)); + TestUtil.assertDataSourceContent(dataSource, dataSpec, + TestUtil.getByteArray(getInstrumentation(), DATA_PATH)); } } diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/ContentDataSourceTest.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/ContentDataSourceTest.java index d8743a0a2c..834e7e1374 100644 --- a/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/ContentDataSourceTest.java +++ b/library/core/src/androidTest/java/com/google/android/exoplayer2/upstream/ContentDataSourceTest.java @@ -23,7 +23,6 @@ import android.database.Cursor; import android.net.Uri; import android.support.annotation.NonNull; import android.test.InstrumentationTestCase; -import android.test.MoreAsserts; import com.google.android.exoplayer2.testutil.TestUtil; import java.io.FileNotFoundException; import java.io.IOException; @@ -35,7 +34,6 @@ public final class ContentDataSourceTest extends InstrumentationTestCase { private static final String AUTHORITY = "com.google.android.exoplayer2.core.test"; private static final String DATA_PATH = "binary/1024_incrementing_bytes.mp3"; - private static final long DATA_LENGTH = 1024; public void testReadValidUri() throws Exception { ContentDataSource dataSource = new ContentDataSource(getInstrumentation().getContext()); @@ -44,14 +42,8 @@ public final class ContentDataSourceTest extends InstrumentationTestCase { .authority(AUTHORITY) .path(DATA_PATH).build(); DataSpec dataSpec = new DataSpec(contentUri); - try { - long length = dataSource.open(dataSpec); - assertEquals(DATA_LENGTH, length); - byte[] readData = TestUtil.readToEnd(dataSource); - MoreAsserts.assertEquals(TestUtil.getByteArray(getInstrumentation(), DATA_PATH), readData); - } finally { - dataSource.close(); - } + TestUtil.assertDataSourceContent(dataSource, dataSpec, + TestUtil.getByteArray(getInstrumentation(), DATA_PATH)); } public void testReadInvalidUri() throws Exception { @@ -66,6 +58,7 @@ public final class ContentDataSourceTest extends InstrumentationTestCase { fail(); } catch (ContentDataSource.ContentDataSourceException e) { // Expected. + assertTrue(e.getCause() instanceof FileNotFoundException); } finally { dataSource.close(); } diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/TestUtil.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/TestUtil.java index f75239318a..363f60b10d 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/TestUtil.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/TestUtil.java @@ -17,12 +17,14 @@ package com.google.android.exoplayer2.testutil; import android.app.Instrumentation; import android.test.InstrumentationTestCase; +import android.test.MoreAsserts; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.extractor.Extractor; import com.google.android.exoplayer2.extractor.PositionHolder; import com.google.android.exoplayer2.extractor.SeekMap; import com.google.android.exoplayer2.testutil.FakeExtractorInput.SimulatedIOException; import com.google.android.exoplayer2.upstream.DataSource; +import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Util; import java.io.IOException; @@ -390,4 +392,24 @@ public class TestUtil { } } + /** + * Asserts that data read from a {@link DataSource} matches {@code expected}. + * + * @param dataSource The {@link DataSource} through which to read. + * @param dataSpec The {@link DataSpec} to use when opening the {@link DataSource}. + * @param expectedData The expected data. + * @throws IOException If an error occurs reading fom the {@link DataSource}. + */ + public static void assertDataSourceContent(DataSource dataSource, DataSpec dataSpec, + byte[] expectedData) throws IOException { + try { + long length = dataSource.open(dataSpec); + Assert.assertEquals(length, expectedData.length); + byte[] readData = TestUtil.readToEnd(dataSource); + MoreAsserts.assertEquals(expectedData, readData); + } finally { + dataSource.close(); + } + } + } From 6c24d9380560adfc7c2577cdadf49d770541c383 Mon Sep 17 00:00:00 2001 From: eguven Date: Mon, 26 Jun 2017 06:51:52 -0700 Subject: [PATCH 17/24] Fix FLAC extension native part compilation In the latest NDK version (r15) compilation fails because 'memset' isn't defined. Included cstring header. Issue: #2977 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=160139022 --- extensions/flac/src/main/jni/flac_parser.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/extensions/flac/src/main/jni/flac_parser.cc b/extensions/flac/src/main/jni/flac_parser.cc index e4925cb462..6c6e57f5f7 100644 --- a/extensions/flac/src/main/jni/flac_parser.cc +++ b/extensions/flac/src/main/jni/flac_parser.cc @@ -22,6 +22,7 @@ #include #include +#include #define LOG_TAG "FLACParser" #define ALOGE(...) \ From efd17f86c5507a68e2568b2d4a30f9280eb53bab Mon Sep 17 00:00:00 2001 From: aquilescanta Date: Tue, 27 Jun 2017 09:38:31 -0700 Subject: [PATCH 18/24] Add URLs EXT-X-STREAM-INF uris only once This prevents ExoPlayer from thinking there are many more video tracks than there actually are. And will prevent downloading multiple times the same rendition once offline support for HLS is added. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=160285777 --- .../source/hls/playlist/HlsPlaylistParser.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java index a867659838..c64b98b5f3 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java @@ -30,6 +30,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Queue; @@ -174,6 +175,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser variantUrls = new HashSet<>(); ArrayList variants = new ArrayList<>(); ArrayList audios = new ArrayList<>(); ArrayList subtitles = new ArrayList<>(); @@ -251,11 +253,13 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser Date: Thu, 29 Jun 2017 00:37:28 -0700 Subject: [PATCH 19/24] Show larger scrubber handle when focused Also remove updateScrubberState as it doesn't do anything useful. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=160496133 --- .../android/exoplayer2/ui/DefaultTimeBar.java | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/DefaultTimeBar.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/DefaultTimeBar.java index 4ede786175..2b699c8957 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/DefaultTimeBar.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/DefaultTimeBar.java @@ -89,7 +89,6 @@ public class DefaultTimeBar extends View implements TimeBar { private final Formatter formatter; private final Runnable stopScrubbingRunnable; - private int scrubberSize; private OnScrubListener listener; private int keyCountIncrement; private long keyTimeIncrement; @@ -184,7 +183,6 @@ public class DefaultTimeBar extends View implements TimeBar { stopScrubbing(false); } }; - scrubberSize = scrubberEnabledSize; scrubberPadding = (Math.max(scrubberDisabledSize, Math.max(scrubberEnabledSize, scrubberDraggedSize)) + 1) / 2; @@ -234,8 +232,6 @@ public class DefaultTimeBar extends View implements TimeBar { this.duration = duration; if (scrubbing && duration == C.TIME_UNSET) { stopScrubbing(true); - } else { - updateScrubberState(); } update(); } @@ -251,7 +247,6 @@ public class DefaultTimeBar extends View implements TimeBar { @Override public void setEnabled(boolean enabled) { super.setEnabled(enabled); - updateScrubberState(); if (scrubbing && !enabled) { stopScrubbing(true); } @@ -436,7 +431,6 @@ public class DefaultTimeBar extends View implements TimeBar { private void startScrubbing() { scrubbing = true; - updateScrubberState(); ViewParent parent = getParent(); if (parent != null) { parent.requestDisallowInterceptTouchEvent(true); @@ -452,18 +446,12 @@ public class DefaultTimeBar extends View implements TimeBar { if (parent != null) { parent.requestDisallowInterceptTouchEvent(false); } - updateScrubberState(); invalidate(); if (listener != null) { listener.onScrubStop(this, getScrubberPosition(), canceled); } } - private void updateScrubberState() { - scrubberSize = scrubbing ? scrubberDraggedSize - : (isEnabled() && duration >= 0 ? scrubberEnabledSize : scrubberDisabledSize); - } - private void update() { bufferedBar.set(progressBar); scrubberBar.set(progressBar); @@ -543,6 +531,8 @@ public class DefaultTimeBar extends View implements TimeBar { if (duration <= 0) { return; } + int scrubberSize = (scrubbing || isFocused()) ? scrubberDraggedSize + : (isEnabled() ? scrubberEnabledSize : scrubberDisabledSize); int playheadRadius = scrubberSize / 2; int playheadCenter = Util.constrainValue(scrubberBar.right, scrubberBar.left, progressBar.right); From df84f2930cdb1f75d273668a96953c0aae102943 Mon Sep 17 00:00:00 2001 From: tonihei Date: Thu, 29 Jun 2017 04:16:16 -0700 Subject: [PATCH 20/24] Clarify JavaDoc of MediaPeriod. Two of MediaPeriod's methods are only called after the media period has been prepared. Added this to JavaDoc of these method to simplify implementations. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=160510373 --- .../com/google/android/exoplayer2/source/MediaPeriod.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/MediaPeriod.java b/library/core/src/main/java/com/google/android/exoplayer2/source/MediaPeriod.java index 3b06542855..aaf4c89ff7 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/MediaPeriod.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/MediaPeriod.java @@ -106,6 +106,8 @@ public interface MediaPeriod extends SequenceableLoader { /** * Discards buffered media up to the specified position. + *

+ * This method should only be called after the period has been prepared. * * @param positionUs The position in microseconds. */ @@ -116,6 +118,8 @@ public interface MediaPeriod extends SequenceableLoader { *

* After this method has returned a value other than {@link C#TIME_UNSET}, all * {@link SampleStream}s provided by the period are guaranteed to start from a key frame. + *

+ * This method should only be called after the period has been prepared. * * @return If a discontinuity was read then the playback position in microseconds after the * discontinuity. Else {@link C#TIME_UNSET}. From 79f7db7fcd1285e1248045fd486a109dade941e4 Mon Sep 17 00:00:00 2001 From: olly Date: Thu, 29 Jun 2017 06:49:30 -0700 Subject: [PATCH 21/24] Prefer Google over MediaTek for PCM decoding pre-O. Issue: #2873 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=160520136 --- .../exoplayer2/mediacodec/MediaCodecUtil.java | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java index 5369dffeb6..392162f607 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java @@ -56,8 +56,10 @@ public final class MediaCodecUtil { } private static final String TAG = "MediaCodecUtil"; + private static final String GOOGLE_RAW_DECODER_NAME = "OMX.google.raw.decoder"; + private static final String MTK_RAW_DECODER_NAME = "OMX.MTK.AUDIO.DECODER.RAW"; private static final MediaCodecInfo PASSTHROUGH_DECODER_INFO = - MediaCodecInfo.newPassthroughInstance("OMX.google.raw.decoder"); + MediaCodecInfo.newPassthroughInstance(GOOGLE_RAW_DECODER_NAME); private static final Pattern PROFILE_PATTERN = Pattern.compile("^\\D?(\\d+)$"); private static final HashMap> decoderInfosCache = new HashMap<>(); @@ -155,6 +157,7 @@ public final class MediaCodecUtil { + ". Assuming: " + decoderInfos.get(0).name); } } + applyWorkarounds(decoderInfos); decoderInfos = Collections.unmodifiableList(decoderInfos); decoderInfosCache.put(key, decoderInfos); return decoderInfos; @@ -339,6 +342,27 @@ public final class MediaCodecUtil { return true; } + /** + * Modifies a list of {@link MediaCodecInfo}s to apply workarounds where we know better than the + * platform. + * + * @param decoderInfos The list to modify. + */ + private static void applyWorkarounds(List decoderInfos) { + if (Util.SDK_INT < 26 && decoderInfos.size() > 1 + && MTK_RAW_DECODER_NAME.equals(decoderInfos.get(0).name)) { + // Prefer the Google raw decoder over the MediaTek one [Internal: b/62337687]. + for (int i = 1; i < decoderInfos.size(); i++) { + MediaCodecInfo decoderInfo = decoderInfos.get(i); + if (GOOGLE_RAW_DECODER_NAME.equals(decoderInfo.name)) { + decoderInfos.remove(i); + decoderInfos.add(0, decoderInfo); + break; + } + } + } + } + /** * Returns whether the decoder is known to fail when adapting, despite advertising itself as an * adaptive decoder. From a579b8d82dd74dca8a4e6b666c0df693aa14aa80 Mon Sep 17 00:00:00 2001 From: olly Date: Fri, 30 Jun 2017 02:52:20 -0700 Subject: [PATCH 22/24] Fix DvbParser bug Issue: #2957 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=160628086 --- .../com/google/android/exoplayer2/text/dvb/DvbParser.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/dvb/DvbParser.java b/library/core/src/main/java/com/google/android/exoplayer2/text/dvb/DvbParser.java index 96c8a89801..c0caf1e57a 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/dvb/DvbParser.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/dvb/DvbParser.java @@ -667,13 +667,15 @@ import java.util.List; int runLength = 0; int clutIndex = 0; int peek = data.readBits(2); - if (!data.readBit()) { + if (peek != 0x00) { runLength = 1; clutIndex = peek; } else if (data.readBit()) { runLength = 3 + data.readBits(3); clutIndex = data.readBits(2); - } else if (!data.readBit()) { + } else if (data.readBit()) { + runLength = 1; + } else { switch (data.readBits(2)) { case 0x00: endOfPixelCodeString = true; From 43daf0f2bb96bb514d22561dd4821f6ce7562aa9 Mon Sep 17 00:00:00 2001 From: andrewlewis Date: Thu, 15 Jun 2017 08:06:31 -0700 Subject: [PATCH 23/24] Update MIME type in FLAC test data ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=159104188 --- library/core/src/androidTest/assets/ogg/bear_flac.ogg.0.dump | 2 +- library/core/src/androidTest/assets/ogg/bear_flac.ogg.1.dump | 2 +- library/core/src/androidTest/assets/ogg/bear_flac.ogg.2.dump | 2 +- library/core/src/androidTest/assets/ogg/bear_flac.ogg.3.dump | 2 +- .../core/src/androidTest/assets/ogg/bear_flac.ogg.unklen.dump | 2 +- .../src/androidTest/assets/ogg/bear_flac_noseektable.ogg.0.dump | 2 +- .../src/androidTest/assets/ogg/bear_flac_noseektable.ogg.1.dump | 2 +- .../src/androidTest/assets/ogg/bear_flac_noseektable.ogg.2.dump | 2 +- .../src/androidTest/assets/ogg/bear_flac_noseektable.ogg.3.dump | 2 +- .../assets/ogg/bear_flac_noseektable.ogg.unklen.dump | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/library/core/src/androidTest/assets/ogg/bear_flac.ogg.0.dump b/library/core/src/androidTest/assets/ogg/bear_flac.ogg.0.dump index 16816917b7..5ba8cc29ae 100644 --- a/library/core/src/androidTest/assets/ogg/bear_flac.ogg.0.dump +++ b/library/core/src/androidTest/assets/ogg/bear_flac.ogg.0.dump @@ -8,7 +8,7 @@ track 0: bitrate = -1 id = null containerMimeType = null - sampleMimeType = audio/x-flac + sampleMimeType = audio/flac maxInputSize = 768000 width = -1 height = -1 diff --git a/library/core/src/androidTest/assets/ogg/bear_flac.ogg.1.dump b/library/core/src/androidTest/assets/ogg/bear_flac.ogg.1.dump index fec523f971..f698fd28cf 100644 --- a/library/core/src/androidTest/assets/ogg/bear_flac.ogg.1.dump +++ b/library/core/src/androidTest/assets/ogg/bear_flac.ogg.1.dump @@ -8,7 +8,7 @@ track 0: bitrate = -1 id = null containerMimeType = null - sampleMimeType = audio/x-flac + sampleMimeType = audio/flac maxInputSize = 768000 width = -1 height = -1 diff --git a/library/core/src/androidTest/assets/ogg/bear_flac.ogg.2.dump b/library/core/src/androidTest/assets/ogg/bear_flac.ogg.2.dump index a4a60989ed..8d803d0bac 100644 --- a/library/core/src/androidTest/assets/ogg/bear_flac.ogg.2.dump +++ b/library/core/src/androidTest/assets/ogg/bear_flac.ogg.2.dump @@ -8,7 +8,7 @@ track 0: bitrate = -1 id = null containerMimeType = null - sampleMimeType = audio/x-flac + sampleMimeType = audio/flac maxInputSize = 768000 width = -1 height = -1 diff --git a/library/core/src/androidTest/assets/ogg/bear_flac.ogg.3.dump b/library/core/src/androidTest/assets/ogg/bear_flac.ogg.3.dump index a77575bb0c..09f6267270 100644 --- a/library/core/src/androidTest/assets/ogg/bear_flac.ogg.3.dump +++ b/library/core/src/androidTest/assets/ogg/bear_flac.ogg.3.dump @@ -8,7 +8,7 @@ track 0: bitrate = -1 id = null containerMimeType = null - sampleMimeType = audio/x-flac + sampleMimeType = audio/flac maxInputSize = 768000 width = -1 height = -1 diff --git a/library/core/src/androidTest/assets/ogg/bear_flac.ogg.unklen.dump b/library/core/src/androidTest/assets/ogg/bear_flac.ogg.unklen.dump index 16816917b7..5ba8cc29ae 100644 --- a/library/core/src/androidTest/assets/ogg/bear_flac.ogg.unklen.dump +++ b/library/core/src/androidTest/assets/ogg/bear_flac.ogg.unklen.dump @@ -8,7 +8,7 @@ track 0: bitrate = -1 id = null containerMimeType = null - sampleMimeType = audio/x-flac + sampleMimeType = audio/flac maxInputSize = 768000 width = -1 height = -1 diff --git a/library/core/src/androidTest/assets/ogg/bear_flac_noseektable.ogg.0.dump b/library/core/src/androidTest/assets/ogg/bear_flac_noseektable.ogg.0.dump index 7be7d02493..73e537f8c8 100644 --- a/library/core/src/androidTest/assets/ogg/bear_flac_noseektable.ogg.0.dump +++ b/library/core/src/androidTest/assets/ogg/bear_flac_noseektable.ogg.0.dump @@ -8,7 +8,7 @@ track 0: bitrate = -1 id = null containerMimeType = null - sampleMimeType = audio/x-flac + sampleMimeType = audio/flac maxInputSize = 768000 width = -1 height = -1 diff --git a/library/core/src/androidTest/assets/ogg/bear_flac_noseektable.ogg.1.dump b/library/core/src/androidTest/assets/ogg/bear_flac_noseektable.ogg.1.dump index 34f19c6bce..3b7dc3fd1e 100644 --- a/library/core/src/androidTest/assets/ogg/bear_flac_noseektable.ogg.1.dump +++ b/library/core/src/androidTest/assets/ogg/bear_flac_noseektable.ogg.1.dump @@ -8,7 +8,7 @@ track 0: bitrate = -1 id = null containerMimeType = null - sampleMimeType = audio/x-flac + sampleMimeType = audio/flac maxInputSize = 768000 width = -1 height = -1 diff --git a/library/core/src/androidTest/assets/ogg/bear_flac_noseektable.ogg.2.dump b/library/core/src/androidTest/assets/ogg/bear_flac_noseektable.ogg.2.dump index 68484d2cf4..b6a6741fcc 100644 --- a/library/core/src/androidTest/assets/ogg/bear_flac_noseektable.ogg.2.dump +++ b/library/core/src/androidTest/assets/ogg/bear_flac_noseektable.ogg.2.dump @@ -8,7 +8,7 @@ track 0: bitrate = -1 id = null containerMimeType = null - sampleMimeType = audio/x-flac + sampleMimeType = audio/flac maxInputSize = 768000 width = -1 height = -1 diff --git a/library/core/src/androidTest/assets/ogg/bear_flac_noseektable.ogg.3.dump b/library/core/src/androidTest/assets/ogg/bear_flac_noseektable.ogg.3.dump index 8b2e7858b0..738002f7ef 100644 --- a/library/core/src/androidTest/assets/ogg/bear_flac_noseektable.ogg.3.dump +++ b/library/core/src/androidTest/assets/ogg/bear_flac_noseektable.ogg.3.dump @@ -8,7 +8,7 @@ track 0: bitrate = -1 id = null containerMimeType = null - sampleMimeType = audio/x-flac + sampleMimeType = audio/flac maxInputSize = 768000 width = -1 height = -1 diff --git a/library/core/src/androidTest/assets/ogg/bear_flac_noseektable.ogg.unklen.dump b/library/core/src/androidTest/assets/ogg/bear_flac_noseektable.ogg.unklen.dump index 8d398efdb8..a237fd0dfc 100644 --- a/library/core/src/androidTest/assets/ogg/bear_flac_noseektable.ogg.unklen.dump +++ b/library/core/src/androidTest/assets/ogg/bear_flac_noseektable.ogg.unklen.dump @@ -8,7 +8,7 @@ track 0: bitrate = -1 id = null containerMimeType = null - sampleMimeType = audio/x-flac + sampleMimeType = audio/flac maxInputSize = 768000 width = -1 height = -1 From 1b64d62e61dd68635df0df3a1a83d303db4d0b12 Mon Sep 17 00:00:00 2001 From: olly Date: Fri, 30 Jun 2017 10:48:03 -0700 Subject: [PATCH 24/24] Update release notes + bump version number ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=160663100 --- RELEASENOTES.md | 22 +++++++++++++++++-- build.gradle | 2 +- demo/src/main/AndroidManifest.xml | 4 ++-- .../exoplayer2/ExoPlayerLibraryInfo.java | 6 ++--- 4 files changed, 26 insertions(+), 8 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 4f147e2bbd..f9f6b02c19 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,11 +1,29 @@ # Release notes # +### r2.4.3 ### + +* Audio: Workaround custom audio decoders misreporting their maximum supported + channel counts ([#2940](https://github.com/google/ExoPlayer/issues/2940)). +* Audio: Workaround for broken MediaTek raw decoder on some devices + ([#2873](https://github.com/google/ExoPlayer/issues/2873)). +* Captions: Fix TTML captions appearing at the top of the screen + ([#2953](https://github.com/google/ExoPlayer/issues/2953)). +* Captions: Fix handling of some DVB subtitles + ([#2957](https://github.com/google/ExoPlayer/issues/2957)). +* Track selection: Fix setSelectionOverride(index, tracks, null) + ([#2988](https://github.com/google/ExoPlayer/issues/2988)). +* GVR extension: Add support for mono input + ([#2710](https://github.com/google/ExoPlayer/issues/2710)). +* FLAC extension: Fix failing build + ([#2977](https://github.com/google/ExoPlayer/pull/2977)). +* Misc bugfixes. + ### r2.4.2 ### * Stability: Work around Nexus 10 reboot when playing certain content - ([2806](https://github.com/google/ExoPlayer/issues/2806)). + ([#2806](https://github.com/google/ExoPlayer/issues/2806)). * MP3: Correctly treat MP3s with INFO headers as constant bitrate - ([2895](https://github.com/google/ExoPlayer/issues/2895)). + ([#2895](https://github.com/google/ExoPlayer/issues/2895)). * HLS: Use average rather than peak bandwidth when available ([#2863](https://github.com/google/ExoPlayer/issues/2863)). * SmoothStreaming: Fix timeline for live streams diff --git a/build.gradle b/build.gradle index 4f18e7c801..01d8b6616c 100644 --- a/build.gradle +++ b/build.gradle @@ -48,7 +48,7 @@ allprojects { releaseRepoName = getBintrayRepo() releaseUserOrg = 'google' releaseGroupId = 'com.google.android.exoplayer' - releaseVersion = 'r2.4.2' + releaseVersion = 'r2.4.3' releaseWebsite = 'https://github.com/google/ExoPlayer' } if (it.hasProperty('externalBuildDir')) { diff --git a/demo/src/main/AndroidManifest.xml b/demo/src/main/AndroidManifest.xml index 34256d41c1..addce60cad 100644 --- a/demo/src/main/AndroidManifest.xml +++ b/demo/src/main/AndroidManifest.xml @@ -16,8 +16,8 @@ + android:versionCode="2403" + android:versionName="2.4.3"> 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 c6fc139208..650ce727cd 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 @@ -24,13 +24,13 @@ public interface 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. - String VERSION = "2.4.2"; + String VERSION = "2.4.3"; /** * The version of the library expressed as {@code "ExoPlayerLib/" + VERSION}. */ // Intentionally hardcoded. Do not derive from other constants (e.g. VERSION) or vice versa. - String VERSION_SLASHY = "ExoPlayerLib/2.4.2"; + String VERSION_SLASHY = "ExoPlayerLib/2.4.3"; /** * The version of the library expressed as an integer, for example 1002003. @@ -40,7 +40,7 @@ public interface ExoPlayerLibraryInfo { * integer version 123045006 (123-045-006). */ // Intentionally hardcoded. Do not derive from other constants (e.g. VERSION) or vice versa. - int VERSION_INT = 2004002; + int VERSION_INT = 2004003; /** * Whether the library was compiled with {@link com.google.android.exoplayer2.util.Assertions}