From 0d679dad0d2fb8b5749f342b2cacaf961bbd6832 Mon Sep 17 00:00:00 2001 From: olly Date: Wed, 19 Oct 2016 07:59:35 -0700 Subject: [PATCH 01/17] Fix use of API level 19 method Issue: #1965 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=136595233 --- .../android/exoplayer2/ui/PlaybackControlView.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/library/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java b/library/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java index 3823f1760ec..096e67ec01c 100644 --- a/library/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java +++ b/library/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java @@ -75,6 +75,7 @@ public interface VisibilityListener { private ExoPlayer player; private VisibilityListener visibilityListener; + private boolean isAttachedToWindow; private boolean dragging; private int rewindMs; private int fastForwardMs; @@ -264,7 +265,7 @@ private void hideAfterTimeout() { removeCallbacks(hideAction); if (showTimeoutMs > 0) { hideAtMs = SystemClock.uptimeMillis() + showTimeoutMs; - if (isAttachedToWindow()) { + if (isAttachedToWindow) { postDelayed(hideAction, showTimeoutMs); } } else { @@ -279,7 +280,7 @@ private void updateAll() { } private void updatePlayPauseButton() { - if (!isVisible() || !isAttachedToWindow()) { + if (!isVisible() || !isAttachedToWindow) { return; } boolean playing = player != null && player.getPlayWhenReady(); @@ -291,7 +292,7 @@ private void updatePlayPauseButton() { } private void updateNavigation() { - if (!isVisible() || !isAttachedToWindow()) { + if (!isVisible() || !isAttachedToWindow) { return; } Timeline currentTimeline = player != null ? player.getCurrentTimeline() : null; @@ -315,7 +316,7 @@ private void updateNavigation() { } private void updateProgress() { - if (!isVisible() || !isAttachedToWindow()) { + if (!isVisible() || !isAttachedToWindow) { return; } long duration = player == null ? 0 : player.getDuration(); @@ -426,6 +427,7 @@ private void fastForward() { @Override public void onAttachedToWindow() { super.onAttachedToWindow(); + isAttachedToWindow = true; if (hideAtMs != C.TIME_UNSET) { long delayMs = hideAtMs - SystemClock.uptimeMillis(); if (delayMs <= 0) { @@ -440,6 +442,7 @@ public void onAttachedToWindow() { @Override public void onDetachedFromWindow() { super.onDetachedFromWindow(); + isAttachedToWindow = false; removeCallbacks(updateProgressAction); removeCallbacks(hideAction); } From 75b00753403487ed30baaa10d874659171a36fee Mon Sep 17 00:00:00 2001 From: olly Date: Wed, 19 Oct 2016 08:18:48 -0700 Subject: [PATCH 02/17] Add explicit TargetApi annotation to remove lint error ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=136597149 --- .../google/android/exoplayer2/ui/PlaybackControlView.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/library/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java b/library/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java index 096e67ec01c..89c778d0722 100644 --- a/library/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java +++ b/library/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.ui; +import android.annotation.TargetApi; import android.content.Context; import android.content.res.TypedArray; import android.os.SystemClock; @@ -351,13 +352,18 @@ private void updateProgress() { private void setButtonEnabled(boolean enabled, View view) { view.setEnabled(enabled); if (Util.SDK_INT >= 11) { - view.setAlpha(enabled ? 1f : 0.3f); + setViewAlphaV11(view, enabled ? 1f : 0.3f); view.setVisibility(VISIBLE); } else { view.setVisibility(enabled ? VISIBLE : INVISIBLE); } } + @TargetApi(11) + private void setViewAlphaV11(View view, float alpha) { + view.setAlpha(alpha); + } + private String stringForTime(long timeMs) { if (timeMs == C.TIME_UNSET) { timeMs = 0; From 8e0e0ca0dd56ecc5d32f9508014a001d7cb94c3c Mon Sep 17 00:00:00 2001 From: aquilescanta Date: Wed, 19 Oct 2016 09:58:41 -0700 Subject: [PATCH 03/17] Fix NPE when trying to play H265 in Ts files ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=136607848 --- .../google/android/exoplayer2/extractor/ts/H265Reader.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/H265Reader.java b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/H265Reader.java index 6283371a194..57d7e77bb7b 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/H265Reader.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/H265Reader.java @@ -44,6 +44,7 @@ private static final int SUFFIX_SEI_NUT = 40; private TrackOutput output; + private SampleReader sampleReader; private SeiReader seiReader; // State that should not be reset on seek. @@ -56,7 +57,6 @@ private final NalUnitTargetBuffer pps; private final NalUnitTargetBuffer prefixSei; private final NalUnitTargetBuffer suffixSei; // TODO: Are both needed? - private final SampleReader sampleReader; private long totalBytesWritten; // Per packet state that gets reset at the start of each packet. @@ -72,7 +72,6 @@ public H265Reader() { pps = new NalUnitTargetBuffer(PPS_NUT, 128); prefixSei = new NalUnitTargetBuffer(PREFIX_SEI_NUT, 128); suffixSei = new NalUnitTargetBuffer(SUFFIX_SEI_NUT, 128); - sampleReader = new SampleReader(output); seiWrapper = new ParsableByteArray(); } @@ -91,6 +90,7 @@ public void seek() { @Override public void init(ExtractorOutput extractorOutput, TrackIdGenerator idGenerator) { output = extractorOutput.track(idGenerator.getNextId()); + sampleReader = new SampleReader(output); seiReader = new SeiReader(extractorOutput.track(idGenerator.getNextId())); } From c7824c4660d2958ea331d23dbcca9cc74d39ad98 Mon Sep 17 00:00:00 2001 From: olly Date: Thu, 20 Oct 2016 03:35:32 -0700 Subject: [PATCH 04/17] Bump version to r2.0.4 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=136697697 --- RELEASENOTES.md | 19 ++++++++++++------- build.gradle | 2 +- demo/src/main/AndroidManifest.xml | 4 ++-- .../exoplayer2/ExoPlayerLibraryInfo.java | 4 ++-- playbacktests/src/main/AndroidManifest.xml | 4 ++-- 5 files changed, 19 insertions(+), 14 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 9e0439dd124..ce002238ef1 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,22 +1,27 @@ # Release notes # -### r2.0.3 ### +### r2.0.4 ### -This release contains important bug fixes. Users of r2.0.0, r2.0.1 and r2.0.2 +This release contains important bug fixes. Users of earlier r2.0.x versions should proactively update to this version. +* Fix crash on Jellybean devices when using playback controls + ([#1965](https://github.com/google/ExoPlayer/issues/1965)). + +### r2.0.3 ### + * Fixed NullPointerException in ExtractorMediaSource - ([#1914](https://github.com/google/ExoPlayer/issues/1914). + ([#1914](https://github.com/google/ExoPlayer/issues/1914)). * Fixed NullPointerException in HlsMediaPeriod - ([#1907](https://github.com/google/ExoPlayer/issues/1907). + ([#1907](https://github.com/google/ExoPlayer/issues/1907)). * Fixed memory leak in PlaybackControlView - ([#1908](https://github.com/google/ExoPlayer/issues/1908). + ([#1908](https://github.com/google/ExoPlayer/issues/1908)). * Fixed strict mode violation when using SimpleExoPlayer.setVideoPlayerTextureView(). * Fixed L3 Widevine provisioning - ([#1925](https://github.com/google/ExoPlayer/issues/1925). + ([#1925](https://github.com/google/ExoPlayer/issues/1925)). * Fixed hiding of controls with use_controller="false" - ([#1919](https://github.com/google/ExoPlayer/issues/1919). + ([#1919](https://github.com/google/ExoPlayer/issues/1919)). * Improvements to Cronet network stack extension. * Misc bug fixes. diff --git a/build.gradle b/build.gradle index c50dd31b278..8e9032be706 100644 --- a/build.gradle +++ b/build.gradle @@ -35,7 +35,7 @@ allprojects { releaseRepoName = 'exoplayer' releaseUserOrg = 'google' releaseGroupId = 'com.google.android.exoplayer' - releaseVersion = 'r2.0.3' + releaseVersion = 'r2.0.4' releaseWebsite = 'https://github.com/google/ExoPlayer' } } diff --git a/demo/src/main/AndroidManifest.xml b/demo/src/main/AndroidManifest.xml index 7fc0ac3d9cf..1f015827c9e 100644 --- a/demo/src/main/AndroidManifest.xml +++ b/demo/src/main/AndroidManifest.xml @@ -16,8 +16,8 @@ + android:versionCode="2004" + android:versionName="2.0.4"> diff --git a/library/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java b/library/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java index 23e6d4d5935..02c70bb0bea 100644 --- a/library/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java +++ b/library/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java @@ -23,7 +23,7 @@ public interface ExoPlayerLibraryInfo { /** * The version of the library, expressed as a string. */ - String VERSION = "2.0.3"; + String VERSION = "2.0.4"; /** * The version of the library, expressed as an integer. @@ -32,7 +32,7 @@ public interface ExoPlayerLibraryInfo { * corresponding integer version 1002003 (001-002-003), and "123.45.6" has the corresponding * integer version 123045006 (123-045-006). */ - int VERSION_INT = 2000003; + int VERSION_INT = 2000004; /** * Whether the library was compiled with {@link com.google.android.exoplayer2.util.Assertions} diff --git a/playbacktests/src/main/AndroidManifest.xml b/playbacktests/src/main/AndroidManifest.xml index 58ede793b20..6a10654af7b 100644 --- a/playbacktests/src/main/AndroidManifest.xml +++ b/playbacktests/src/main/AndroidManifest.xml @@ -17,8 +17,8 @@ + android:versionCode="2004" + android:versionName="2.0.4"> From a3ca5c48b388cdcce89b016d0c635b31ec1f88e7 Mon Sep 17 00:00:00 2001 From: ojw28 Date: Thu, 24 Nov 2016 19:28:24 +0000 Subject: [PATCH 05/17] Update ISSUE_TEMPLATE --- ISSUE_TEMPLATE | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ISSUE_TEMPLATE b/ISSUE_TEMPLATE index 3667c8cc969..6e55f3dcd66 100644 --- a/ISSUE_TEMPLATE +++ b/ISSUE_TEMPLATE @@ -1,5 +1,7 @@ +*** PLEASE DO NOT IGNORE THIS ISSUE TEMPLATE *** + Please search the existing issues before filing a new one, including issues that -are closed. When filing a new issue please include all of the following, unless +are closed. When filing a new issue please include ALL of the following, unless you're certain that they're not useful for the particular issue being reported. - A description of the issue. From 4f2cced4da4b6c42f2da51f38516a17a415e13c3 Mon Sep 17 00:00:00 2001 From: Greg Slomin Date: Tue, 29 Nov 2016 11:36:34 -0600 Subject: [PATCH 06/17] Added support for PCM u/a-law audio in FLV containers --- .../extractor/flv/AudioTagPayloadReader.java | 37 +++++++++++++------ .../android/exoplayer2/util/MimeTypes.java | 2 + 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/flv/AudioTagPayloadReader.java b/library/src/main/java/com/google/android/exoplayer2/extractor/flv/AudioTagPayloadReader.java index b48c4881d95..5eed202c0b2 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/flv/AudioTagPayloadReader.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/flv/AudioTagPayloadReader.java @@ -15,6 +15,8 @@ */ package com.google.android.exoplayer2.extractor.flv; +import android.media.AudioFormat; +import android.media.AudioTrack; import android.util.Pair; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; @@ -30,6 +32,8 @@ /* package */ final class AudioTagPayloadReader extends TagPayloadReader { // Audio format + private static final int AUDIO_FORMAT_ALAW = 7; + private static final int AUDIO_FORMAT_ULAW = 8; private static final int AUDIO_FORMAT_AAC = 10; // AAC PACKET TYPE @@ -44,6 +48,7 @@ // State variables private boolean hasParsedAudioDataHeader; private boolean hasOutputFormat; + private int audioFormat; public AudioTagPayloadReader(TrackOutput output) { super(output); @@ -58,15 +63,26 @@ public void seek() { protected boolean parseHeader(ParsableByteArray data) throws UnsupportedFormatException { if (!hasParsedAudioDataHeader) { int header = data.readUnsignedByte(); - int audioFormat = (header >> 4) & 0x0F; + audioFormat = (header >> 4) & 0x0F; int sampleRateIndex = (header >> 2) & 0x03; + int encodingSize = header & 0x01; if (sampleRateIndex < 0 || sampleRateIndex >= AUDIO_SAMPLING_RATE_TABLE.length) { throw new UnsupportedFormatException("Invalid sample rate index: " + sampleRateIndex); } - // TODO: Add support for MP3 and PCM. - if (audioFormat != AUDIO_FORMAT_AAC) { - throw new UnsupportedFormatException("Audio format not supported: " + audioFormat); + // TODO: Add support for MP3. + if (audioFormat == AUDIO_FORMAT_ALAW || audioFormat == AUDIO_FORMAT_ULAW) { + + String type = (audioFormat == AUDIO_FORMAT_ALAW) ? MimeTypes.AUDIO_ALAW : MimeTypes.AUDIO_ULAW; + int encoding = (encodingSize == 1) ? C.ENCODING_PCM_16BIT : C.ENCODING_PCM_8BIT; + Format format = Format.createAudioSampleFormat(null, type, null, Format.NO_VALUE, Format.NO_VALUE, + 1, 8000, encoding, null, null, 0, null); + output.format(format); + + hasOutputFormat = true; + } else if (audioFormat != AUDIO_FORMAT_AAC ) { + throw new UnsupportedFormatException("Audio format not supported: " + audioFormat); } + hasParsedAudioDataHeader = true; } else { // Skip header if it was parsed previously. @@ -78,8 +94,9 @@ protected boolean parseHeader(ParsableByteArray data) throws UnsupportedFormatEx @Override protected void parsePayload(ParsableByteArray data, long timeUs) { int packetType = data.readUnsignedByte(); - // Parse sequence header just in case it was not done before. + if (packetType == AAC_PACKET_TYPE_SEQUENCE_HEADER && !hasOutputFormat) { + // Parse sequence header just in case it was not done before. byte[] audioSpecifiConfig = new byte[data.bytesLeft()]; data.readBytes(audioSpecifiConfig, 0, audioSpecifiConfig.length); Pair audioParams = CodecSpecificDataUtil.parseAacAudioSpecificConfig( @@ -89,12 +106,10 @@ protected void parsePayload(ParsableByteArray data, long timeUs) { Collections.singletonList(audioSpecifiConfig), null, 0, null); output.format(format); hasOutputFormat = true; - } else if (packetType == AAC_PACKET_TYPE_AAC_RAW) { - // Sample audio AAC frames - int bytesToWrite = data.bytesLeft(); - output.sampleData(data, bytesToWrite); - output.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, bytesToWrite, 0, null); + } else if (audioFormat != AUDIO_FORMAT_AAC || packetType == AAC_PACKET_TYPE_AAC_RAW) { + int bytes = data.bytesLeft(); + output.sampleData(data, bytes); + output.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, bytes, 0, null); } } - } diff --git a/library/src/main/java/com/google/android/exoplayer2/util/MimeTypes.java b/library/src/main/java/com/google/android/exoplayer2/util/MimeTypes.java index 4776e4d0082..e08388f1739 100644 --- a/library/src/main/java/com/google/android/exoplayer2/util/MimeTypes.java +++ b/library/src/main/java/com/google/android/exoplayer2/util/MimeTypes.java @@ -47,6 +47,8 @@ public final class MimeTypes { public static final String AUDIO_MPEG_L1 = BASE_TYPE_AUDIO + "/mpeg-L1"; 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_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"; From 17cd73d8ed55bacccd1f567b9bd30c882311168e Mon Sep 17 00:00:00 2001 From: ojw28 Date: Thu, 1 Dec 2016 14:54:27 +0000 Subject: [PATCH 07/17] Revert "Added support for PCM u/a-law audio in FLV containers" --- .../extractor/flv/AudioTagPayloadReader.java | 37 ++++++------------- .../android/exoplayer2/util/MimeTypes.java | 2 - 2 files changed, 11 insertions(+), 28 deletions(-) diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/flv/AudioTagPayloadReader.java b/library/src/main/java/com/google/android/exoplayer2/extractor/flv/AudioTagPayloadReader.java index 5eed202c0b2..b48c4881d95 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/flv/AudioTagPayloadReader.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/flv/AudioTagPayloadReader.java @@ -15,8 +15,6 @@ */ package com.google.android.exoplayer2.extractor.flv; -import android.media.AudioFormat; -import android.media.AudioTrack; import android.util.Pair; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; @@ -32,8 +30,6 @@ /* package */ final class AudioTagPayloadReader extends TagPayloadReader { // Audio format - private static final int AUDIO_FORMAT_ALAW = 7; - private static final int AUDIO_FORMAT_ULAW = 8; private static final int AUDIO_FORMAT_AAC = 10; // AAC PACKET TYPE @@ -48,7 +44,6 @@ // State variables private boolean hasParsedAudioDataHeader; private boolean hasOutputFormat; - private int audioFormat; public AudioTagPayloadReader(TrackOutput output) { super(output); @@ -63,26 +58,15 @@ public void seek() { protected boolean parseHeader(ParsableByteArray data) throws UnsupportedFormatException { if (!hasParsedAudioDataHeader) { int header = data.readUnsignedByte(); - audioFormat = (header >> 4) & 0x0F; + int audioFormat = (header >> 4) & 0x0F; int sampleRateIndex = (header >> 2) & 0x03; - int encodingSize = header & 0x01; if (sampleRateIndex < 0 || sampleRateIndex >= AUDIO_SAMPLING_RATE_TABLE.length) { throw new UnsupportedFormatException("Invalid sample rate index: " + sampleRateIndex); } - // TODO: Add support for MP3. - if (audioFormat == AUDIO_FORMAT_ALAW || audioFormat == AUDIO_FORMAT_ULAW) { - - String type = (audioFormat == AUDIO_FORMAT_ALAW) ? MimeTypes.AUDIO_ALAW : MimeTypes.AUDIO_ULAW; - int encoding = (encodingSize == 1) ? C.ENCODING_PCM_16BIT : C.ENCODING_PCM_8BIT; - Format format = Format.createAudioSampleFormat(null, type, null, Format.NO_VALUE, Format.NO_VALUE, - 1, 8000, encoding, null, null, 0, null); - output.format(format); - - hasOutputFormat = true; - } else if (audioFormat != AUDIO_FORMAT_AAC ) { - throw new UnsupportedFormatException("Audio format not supported: " + audioFormat); + // TODO: Add support for MP3 and PCM. + if (audioFormat != AUDIO_FORMAT_AAC) { + throw new UnsupportedFormatException("Audio format not supported: " + audioFormat); } - hasParsedAudioDataHeader = true; } else { // Skip header if it was parsed previously. @@ -94,9 +78,8 @@ protected boolean parseHeader(ParsableByteArray data) throws UnsupportedFormatEx @Override protected void parsePayload(ParsableByteArray data, long timeUs) { int packetType = data.readUnsignedByte(); - + // Parse sequence header just in case it was not done before. if (packetType == AAC_PACKET_TYPE_SEQUENCE_HEADER && !hasOutputFormat) { - // Parse sequence header just in case it was not done before. byte[] audioSpecifiConfig = new byte[data.bytesLeft()]; data.readBytes(audioSpecifiConfig, 0, audioSpecifiConfig.length); Pair audioParams = CodecSpecificDataUtil.parseAacAudioSpecificConfig( @@ -106,10 +89,12 @@ protected void parsePayload(ParsableByteArray data, long timeUs) { Collections.singletonList(audioSpecifiConfig), null, 0, null); output.format(format); hasOutputFormat = true; - } else if (audioFormat != AUDIO_FORMAT_AAC || packetType == AAC_PACKET_TYPE_AAC_RAW) { - int bytes = data.bytesLeft(); - output.sampleData(data, bytes); - output.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, bytes, 0, null); + } else if (packetType == AAC_PACKET_TYPE_AAC_RAW) { + // Sample audio AAC frames + int bytesToWrite = data.bytesLeft(); + output.sampleData(data, bytesToWrite); + output.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, bytesToWrite, 0, null); } } + } diff --git a/library/src/main/java/com/google/android/exoplayer2/util/MimeTypes.java b/library/src/main/java/com/google/android/exoplayer2/util/MimeTypes.java index e08388f1739..4776e4d0082 100644 --- a/library/src/main/java/com/google/android/exoplayer2/util/MimeTypes.java +++ b/library/src/main/java/com/google/android/exoplayer2/util/MimeTypes.java @@ -47,8 +47,6 @@ public final class MimeTypes { public static final String AUDIO_MPEG_L1 = BASE_TYPE_AUDIO + "/mpeg-L1"; 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_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"; From e65110e1ed06da1ab0b6dbbf252f7e49e4879ce8 Mon Sep 17 00:00:00 2001 From: Oliver Woodman Date: Wed, 14 Dec 2016 17:00:46 +0000 Subject: [PATCH 08/17] Remove ClippingMediaSource from release --- .../source/ClippingMediaPeriod.java | 247 ------------------ .../source/ClippingMediaSource.java | 185 ------------- 2 files changed, 432 deletions(-) delete mode 100644 library/src/main/java/com/google/android/exoplayer2/source/ClippingMediaPeriod.java delete mode 100644 library/src/main/java/com/google/android/exoplayer2/source/ClippingMediaSource.java diff --git a/library/src/main/java/com/google/android/exoplayer2/source/ClippingMediaPeriod.java b/library/src/main/java/com/google/android/exoplayer2/source/ClippingMediaPeriod.java deleted file mode 100644 index c39bccda3dc..00000000000 --- a/library/src/main/java/com/google/android/exoplayer2/source/ClippingMediaPeriod.java +++ /dev/null @@ -1,247 +0,0 @@ -/* - * 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.source; - -import com.google.android.exoplayer2.C; -import com.google.android.exoplayer2.FormatHolder; -import com.google.android.exoplayer2.decoder.DecoderInputBuffer; -import com.google.android.exoplayer2.trackselection.TrackSelection; -import com.google.android.exoplayer2.util.Assertions; -import java.io.IOException; - -/** - * Wraps a {@link MediaPeriod} and clips its {@link SampleStream}s to provide a subsequence of their - * samples. - */ -/* package */ final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callback { - - public final MediaPeriod mediaPeriod; - private final ClippingMediaSource mediaSource; - - private MediaPeriod.Callback callback; - private long startUs; - private long endUs; - private ClippingSampleStream[] sampleStreams; - private boolean pendingInitialDiscontinuity; - - /** - * Creates a new clipping media period that provides a clipped view of the specified - * {@link MediaPeriod}'s sample streams. - * - * @param mediaPeriod The media period to clip. - * @param mediaSource The {@link ClippingMediaSource} to which this period belongs. - */ - public ClippingMediaPeriod(MediaPeriod mediaPeriod, ClippingMediaSource mediaSource) { - this.mediaPeriod = mediaPeriod; - this.mediaSource = mediaSource; - startUs = C.TIME_UNSET; - endUs = C.TIME_UNSET; - sampleStreams = new ClippingSampleStream[0]; - } - - @Override - public void prepare(MediaPeriod.Callback callback) { - this.callback = callback; - mediaPeriod.prepare(this); - } - - @Override - public void maybeThrowPrepareError() throws IOException { - mediaPeriod.maybeThrowPrepareError(); - } - - @Override - public TrackGroupArray getTrackGroups() { - return mediaPeriod.getTrackGroups(); - } - - @Override - public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, - SampleStream[] streams, boolean[] streamResetFlags, long positionUs) { - sampleStreams = new ClippingSampleStream[streams.length]; - SampleStream[] internalStreams = new SampleStream[streams.length]; - for (int i = 0; i < streams.length; i++) { - sampleStreams[i] = (ClippingSampleStream) streams[i]; - internalStreams[i] = sampleStreams[i] != null ? sampleStreams[i].stream : null; - } - long enablePositionUs = mediaPeriod.selectTracks(selections, mayRetainStreamFlags, - internalStreams, streamResetFlags, positionUs + startUs); - Assertions.checkState(enablePositionUs == positionUs + startUs - || (enablePositionUs >= startUs && enablePositionUs <= endUs)); - for (int i = 0; i < streams.length; i++) { - if (internalStreams[i] == null) { - sampleStreams[i] = null; - } else if (streams[i] == null || sampleStreams[i].stream != internalStreams[i]) { - sampleStreams[i] = new ClippingSampleStream(this, internalStreams[i], startUs, endUs, - pendingInitialDiscontinuity); - } - streams[i] = sampleStreams[i]; - } - return enablePositionUs - startUs; - } - - @Override - public long readDiscontinuity() { - if (pendingInitialDiscontinuity) { - for (ClippingSampleStream sampleStream : sampleStreams) { - if (sampleStream != null) { - sampleStream.clearPendingDiscontinuity(); - } - } - pendingInitialDiscontinuity = false; - // Always read an initial discontinuity, using mediaPeriod's discontinuity if set. - long discontinuityUs = readDiscontinuity(); - return discontinuityUs != C.TIME_UNSET ? discontinuityUs : 0; - } - long discontinuityUs = mediaPeriod.readDiscontinuity(); - if (discontinuityUs == C.TIME_UNSET) { - return C.TIME_UNSET; - } - Assertions.checkState(discontinuityUs >= startUs && discontinuityUs <= endUs); - return discontinuityUs - startUs; - } - - @Override - public long getBufferedPositionUs() { - long bufferedPositionUs = mediaPeriod.getBufferedPositionUs(); - if (bufferedPositionUs == C.TIME_END_OF_SOURCE || bufferedPositionUs >= endUs) { - return C.TIME_END_OF_SOURCE; - } - return Math.max(0, bufferedPositionUs - startUs); - } - - @Override - public long seekToUs(long positionUs) { - for (ClippingSampleStream sampleStream : sampleStreams) { - if (sampleStream != null) { - sampleStream.clearSentEos(); - } - } - long seekUs = mediaPeriod.seekToUs(positionUs + startUs); - Assertions.checkState(seekUs == positionUs + startUs || (seekUs >= startUs && seekUs <= endUs)); - return seekUs - startUs; - } - - @Override - public long getNextLoadPositionUs() { - long nextLoadPositionUs = mediaPeriod.getNextLoadPositionUs(); - if (nextLoadPositionUs == C.TIME_END_OF_SOURCE || nextLoadPositionUs >= endUs) { - return C.TIME_END_OF_SOURCE; - } - return nextLoadPositionUs - startUs; - } - - @Override - public boolean continueLoading(long positionUs) { - return mediaPeriod.continueLoading(positionUs + startUs); - } - - // MediaPeriod.Callback implementation. - - @Override - public void onPrepared(MediaPeriod mediaPeriod) { - startUs = mediaSource.getStartUs(); - endUs = mediaSource.getEndUs(); - Assertions.checkState(startUs != C.TIME_UNSET && endUs != C.TIME_UNSET); - // If the clipping start position is non-zero, the clipping sample streams will adjust - // timestamps on buffers they read from the unclipped sample streams. These adjusted buffer - // timestamps can be negative, because sample streams provide buffers starting at a key-frame, - // which may be before the clipping start point. When the renderer reads a buffer with a - // negative timestamp, its offset timestamp can jump backwards compared to the last timestamp - // read in the previous period. Renderer implementations may not allow this, so we signal a - // discontinuity which resets the renderers before they read the clipping sample stream. - pendingInitialDiscontinuity = startUs != 0; - callback.onPrepared(this); - } - - @Override - public void onContinueLoadingRequested(MediaPeriod source) { - callback.onContinueLoadingRequested(this); - } - - /** - * Wraps a {@link SampleStream} and clips its samples. - */ - private static final class ClippingSampleStream implements SampleStream { - - private final MediaPeriod mediaPeriod; - private final SampleStream stream; - private final long startUs; - private final long endUs; - - private boolean pendingDiscontinuity; - private boolean sentEos; - - public ClippingSampleStream(MediaPeriod mediaPeriod, SampleStream stream, long startUs, - long endUs, boolean pendingDiscontinuity) { - this.mediaPeriod = mediaPeriod; - this.stream = stream; - this.startUs = startUs; - this.endUs = endUs; - this.pendingDiscontinuity = pendingDiscontinuity; - } - - public void clearPendingDiscontinuity() { - pendingDiscontinuity = false; - } - - public void clearSentEos() { - sentEos = false; - } - - @Override - public boolean isReady() { - return stream.isReady(); - } - - @Override - public void maybeThrowError() throws IOException { - stream.maybeThrowError(); - } - - @Override - public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer) { - if (pendingDiscontinuity) { - return C.RESULT_NOTHING_READ; - } - if (sentEos) { - buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM); - return C.RESULT_BUFFER_READ; - } - int result = stream.readData(formatHolder, buffer); - // TODO: Clear gapless playback metadata if a format was read (if applicable). - if ((result == C.RESULT_BUFFER_READ && buffer.timeUs >= endUs) - || (result == C.RESULT_NOTHING_READ - && mediaPeriod.getBufferedPositionUs() == C.TIME_END_OF_SOURCE)) { - buffer.clear(); - buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM); - sentEos = true; - return C.RESULT_BUFFER_READ; - } - if (result == C.RESULT_BUFFER_READ) { - buffer.timeUs -= startUs; - } - return result; - } - - @Override - public void skipToKeyframeBefore(long timeUs) { - stream.skipToKeyframeBefore(startUs + timeUs); - } - - } - -} diff --git a/library/src/main/java/com/google/android/exoplayer2/source/ClippingMediaSource.java b/library/src/main/java/com/google/android/exoplayer2/source/ClippingMediaSource.java deleted file mode 100644 index e92dce82319..00000000000 --- a/library/src/main/java/com/google/android/exoplayer2/source/ClippingMediaSource.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * 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.source; - -import com.google.android.exoplayer2.C; -import com.google.android.exoplayer2.ExoPlayer; -import com.google.android.exoplayer2.Timeline; -import com.google.android.exoplayer2.upstream.Allocator; -import com.google.android.exoplayer2.util.Assertions; -import java.io.IOException; - -/** - * {@link MediaSource} that wraps a source and clips its timeline based on specified start/end - * positions. The wrapped source may only have a single period/window and it must not be dynamic - * (live). The specified start position must correspond to a synchronization sample in the period. - */ -public final class ClippingMediaSource implements MediaSource, MediaSource.Listener { - - private final MediaSource mediaSource; - private final long startUs; - private final long endUs; - - private MediaSource.Listener sourceListener; - private ClippingTimeline clippingTimeline; - - /** - * Creates a new clipping source that wraps the specified source. - * - * @param mediaSource The single-period, non-dynamic source to wrap. - * @param startPositionUs The start position within {@code mediaSource}'s timeline at which to - * start providing samples, in microseconds. - * @param endPositionUs The end position within {@code mediaSource}'s timeline at which to stop - * providing samples, in microseconds. Specify {@link C#TIME_END_OF_SOURCE} to provide samples - * from the specified start point up to the end of the source. - */ - public ClippingMediaSource(MediaSource mediaSource, long startPositionUs, long endPositionUs) { - Assertions.checkArgument(startPositionUs >= 0); - this.mediaSource = Assertions.checkNotNull(mediaSource); - startUs = startPositionUs; - endUs = endPositionUs; - } - - /** - * Returns the start position of the clipping source's timeline in microseconds. - */ - /* package */ long getStartUs() { - return clippingTimeline.startUs; - } - - /** - * Returns the end position of the clipping source's timeline in microseconds. - */ - /* package */ long getEndUs() { - return clippingTimeline.endUs; - } - - @Override - public void prepareSource(ExoPlayer player, boolean isTopLevelSource, Listener listener) { - this.sourceListener = listener; - mediaSource.prepareSource(player, false, this); - } - - @Override - public void maybeThrowSourceInfoRefreshError() throws IOException { - mediaSource.maybeThrowSourceInfoRefreshError(); - } - - @Override - public MediaPeriod createPeriod(int index, Allocator allocator, long positionUs) { - return new ClippingMediaPeriod( - mediaSource.createPeriod(index, allocator, startUs + positionUs), this); - } - - @Override - public void releasePeriod(MediaPeriod mediaPeriod) { - mediaSource.releasePeriod(((ClippingMediaPeriod) mediaPeriod).mediaPeriod); - } - - @Override - public void releaseSource() { - mediaSource.releaseSource(); - } - - // MediaSource.Listener implementation. - - @Override - public void onSourceInfoRefreshed(Timeline timeline, Object manifest) { - clippingTimeline = new ClippingTimeline(timeline, startUs, endUs); - sourceListener.onSourceInfoRefreshed(clippingTimeline, manifest); - } - - /** - * Provides a clipped view of a specified timeline. - */ - private static final class ClippingTimeline extends Timeline { - - private final Timeline timeline; - private final long startUs; - private final long endUs; - - /** - * Creates a new timeline that wraps the specified timeline. - * - * @param timeline The timeline to clip. - * @param startUs The number of microseconds to clip from the start of {@code timeline}. - * @param endUs The end position in microseconds for the clipped timeline relative to the start - * of {@code timeline}, or {@link C#TIME_END_OF_SOURCE} to clip no samples from the end. - */ - public ClippingTimeline(Timeline timeline, long startUs, long endUs) { - Assertions.checkArgument(timeline.getWindowCount() == 1); - Assertions.checkArgument(timeline.getPeriodCount() == 1); - Window window = timeline.getWindow(0, new Window(), false); - Assertions.checkArgument(!window.isDynamic); - long resolvedEndUs = endUs == C.TIME_END_OF_SOURCE ? window.durationUs : endUs; - if (window.durationUs != C.TIME_UNSET) { - Assertions.checkArgument(startUs == 0 || window.isSeekable); - Assertions.checkArgument(resolvedEndUs <= window.durationUs); - Assertions.checkArgument(startUs <= resolvedEndUs); - } - Period period = timeline.getPeriod(0, new Period()); - Assertions.checkArgument(period.getPositionInWindowUs() == 0); - this.timeline = timeline; - this.startUs = startUs; - this.endUs = resolvedEndUs; - } - - @Override - public int getWindowCount() { - return 1; - } - - @Override - public Window getWindow(int windowIndex, Window window, boolean setIds, - long defaultPositionProjectionUs) { - window = timeline.getWindow(0, window, setIds, defaultPositionProjectionUs); - window.durationUs = endUs != C.TIME_UNSET ? endUs - startUs : C.TIME_UNSET; - if (window.defaultPositionUs != C.TIME_UNSET) { - window.defaultPositionUs = Math.max(window.defaultPositionUs, startUs); - window.defaultPositionUs = endUs == C.TIME_UNSET ? window.defaultPositionUs - : Math.min(window.defaultPositionUs, endUs); - window.defaultPositionUs -= startUs; - } - long startMs = C.usToMs(startUs); - if (window.presentationStartTimeMs != C.TIME_UNSET) { - window.presentationStartTimeMs += startMs; - } - if (window.windowStartTimeMs != C.TIME_UNSET) { - window.windowStartTimeMs += startMs; - } - return window; - } - - @Override - public int getPeriodCount() { - return 1; - } - - @Override - public Period getPeriod(int periodIndex, Period period, boolean setIds) { - period = timeline.getPeriod(0, period, setIds); - period.durationUs = endUs != C.TIME_UNSET ? endUs - startUs : C.TIME_UNSET; - return period; - } - - @Override - public int getIndexOfPeriod(Object uid) { - return timeline.getIndexOfPeriod(uid); - } - - } - -} From 47ea5c909a55261f58e0de3ebda1d633666e1d2c Mon Sep 17 00:00:00 2001 From: Oliver Woodman Date: Wed, 14 Dec 2016 23:01:51 +0000 Subject: [PATCH 09/17] Delete CS classes --- .../playbacktests/Mp3PlaybackTest.java | 94 ---------------- .../playbacktests/Mp4PlaybackTest.java | 100 ------------------ 2 files changed, 194 deletions(-) delete mode 100644 playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/Mp3PlaybackTest.java delete mode 100644 playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/Mp4PlaybackTest.java diff --git a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/Mp3PlaybackTest.java b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/Mp3PlaybackTest.java deleted file mode 100644 index b640a058ee3..00000000000 --- a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/Mp3PlaybackTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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.playbacktests; - -import android.annotation.TargetApi; -import android.net.Uri; -import android.test.ActivityInstrumentationTestCase2; -import com.google.android.exoplayer2.ExoPlayer; -import com.google.android.exoplayer2.extractor.mp3.Mp3Extractor; -import com.google.android.exoplayer2.playbacktests.util.ActionSchedule; -import com.google.android.exoplayer2.playbacktests.util.ExoHostedTest; -import com.google.android.exoplayer2.playbacktests.util.HostActivity; -import com.google.android.exoplayer2.source.ExtractorMediaSource; -import com.google.android.exoplayer2.source.MediaSource; -import com.google.android.exoplayer2.upstream.DataSource; -import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; -import com.google.android.exoplayer2.upstream.TransferListener; -import com.google.android.exoplayer2.util.ClosedSource; -import com.google.android.exoplayer2.util.Util; - -/** - * Tests MP3 playback using {@link ExoPlayer}. - */ -@ClosedSource(reason = "Not yet ready") -public final class Mp3PlaybackTest extends ActivityInstrumentationTestCase2 { - - private static final String TAG = "Mp3PlaybackTest"; - private static final String URL = "http://storage.googleapis.com/exoplayer-test-media-0/play.mp3"; - - private static final long TEST_TIMEOUT_MS = 2 * 60 * 1000; - - public Mp3PlaybackTest() { - super(HostActivity.class); - } - - public void testPlayback() { - if (Util.SDK_INT < 16) { - // Pass. - return; - } - Mp3HostedTest test = new Mp3HostedTest(URL, true); - getActivity().runTest(test, TEST_TIMEOUT_MS); - } - - public void testPlaybackWithSeeking() { - if (Util.SDK_INT < 16) { - // Pass. - return; - } - Mp3HostedTest test = new Mp3HostedTest(URL, false); - ActionSchedule schedule = new ActionSchedule.Builder(TAG) - .delay(5000).seek(30000) - .delay(5000).seek(0) - .delay(5000).seek(30000) - .delay(5000).stop() - .build(); - test.setSchedule(schedule); - getActivity().runTest(test, TEST_TIMEOUT_MS); - } - - @TargetApi(16) - private static class Mp3HostedTest extends ExoHostedTest { - - private final Uri uri; - - public Mp3HostedTest(String uriString, boolean fullPlaybackNoSeeking) { - super("Mp3PlaybackTest", fullPlaybackNoSeeking); - uri = Uri.parse(uriString); - } - - @Override - public MediaSource buildSource(HostActivity host, String userAgent, - TransferListener mediaTransferListener) { - DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(host, userAgent, - mediaTransferListener); - return new ExtractorMediaSource(uri, dataSourceFactory, Mp3Extractor.FACTORY, null, null); - } - - } - -} diff --git a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/Mp4PlaybackTest.java b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/Mp4PlaybackTest.java deleted file mode 100644 index 3069063b657..00000000000 --- a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/Mp4PlaybackTest.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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.playbacktests; - -import android.annotation.TargetApi; -import android.net.Uri; -import android.test.ActivityInstrumentationTestCase2; -import com.google.android.exoplayer2.ExoPlayer; -import com.google.android.exoplayer2.decoder.DecoderCounters; -import com.google.android.exoplayer2.extractor.mp4.Mp4Extractor; -import com.google.android.exoplayer2.playbacktests.util.DecoderCountersUtil; -import com.google.android.exoplayer2.playbacktests.util.ExoHostedTest; -import com.google.android.exoplayer2.playbacktests.util.HostActivity; -import com.google.android.exoplayer2.source.ExtractorMediaSource; -import com.google.android.exoplayer2.source.MediaSource; -import com.google.android.exoplayer2.upstream.DataSource; -import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; -import com.google.android.exoplayer2.upstream.TransferListener; -import com.google.android.exoplayer2.util.ClosedSource; -import com.google.android.exoplayer2.util.Util; - -/** - * Tests MP4 playback using {@link ExoPlayer}. - */ -@ClosedSource(reason = "Not yet ready") -public final class Mp4PlaybackTest extends ActivityInstrumentationTestCase2 { - - private static final String SOURCE_URL = "http://redirector.c.youtube.com/videoplayback?id=604ed5" - + "ce52eda7ee&itag=22&source=youtube&sparams=ip,ipbits,expire,source,id&ip=0.0.0.0&ipbits=0&" - + "expire=19000000000&signature=513F28C7FDCBEC60A66C86C9A393556C99DC47FB.04C88036EEE12565A1ED" - + "864A875A58F15D8B5300&key=ik0"; - private static final String VIDEO_TAG = "Video"; - - private static final long TEST_TIMEOUT_MS = 15 * 60 * 1000; - private static final float MAX_DROPPED_VIDEO_FRAME_FRACTION = 0.01f; - private static final int EXPECTED_VIDEO_FRAME_COUNT = 14316; - - public Mp4PlaybackTest() { - super(HostActivity.class); - } - - public void testPlayback() { - if (Util.SDK_INT < 16) { - // Pass. - return; - } - Mp4HostedTest test = new Mp4HostedTest(SOURCE_URL, true); - getActivity().runTest(test, TEST_TIMEOUT_MS); - } - - @TargetApi(16) - private static class Mp4HostedTest extends ExoHostedTest { - - private final Uri uri; - - public Mp4HostedTest(String uriString, boolean fullPlaybackNoSeeking) { - super("Mp4PlaybackTest", fullPlaybackNoSeeking); - uri = Uri.parse(uriString); - } - - @Override - public MediaSource buildSource(HostActivity host, String userAgent, - TransferListener mediaTransferListener) { - DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(host, userAgent); - return new ExtractorMediaSource(uri, dataSourceFactory, Mp4Extractor.FACTORY, null, null); - } - - @Override - public void assertPassed(DecoderCounters audioCounters, DecoderCounters videoCounters) { - assertEquals(1, videoCounters.decoderInitCount); - assertEquals(1, videoCounters.decoderReleaseCount); - DecoderCountersUtil.assertSkippedOutputBufferCount(VIDEO_TAG, videoCounters, 0); - - // We allow one fewer output buffer due to the way that MediaCodecRenderer and the - // underlying decoders handle the end of stream. This should be tightened up in the future. - DecoderCountersUtil.assertTotalOutputBufferCount(VIDEO_TAG, videoCounters, - EXPECTED_VIDEO_FRAME_COUNT - 1, EXPECTED_VIDEO_FRAME_COUNT); - - int droppedFrameLimit = (int) Math.ceil(MAX_DROPPED_VIDEO_FRAME_FRACTION - * DecoderCountersUtil.getTotalOutputBuffers(videoCounters)); - DecoderCountersUtil.assertDroppedOutputBufferLimit(VIDEO_TAG, videoCounters, - droppedFrameLimit); - } - - } - -} From fc3ed0bf31c7c55c89aae74844134316759e349d Mon Sep 17 00:00:00 2001 From: olly Date: Wed, 14 Dec 2016 09:47:02 -0800 Subject: [PATCH 10/17] Add missing # chars to release notes! ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=142028608 --- RELEASENOTES.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index fa6c42ca88b..a3faadacce2 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -6,19 +6,19 @@ This release contains important bug fixes. Users of r2.0.x should proactively update to this version. * HLS: Support for seeking in live streams - ([87](https://github.com/google/ExoPlayer/issues/87)). + ([#87](https://github.com/google/ExoPlayer/issues/87)). * HLS: Improved support: * Support for EXT-X-PROGRAM-DATE-TIME - ([747](https://github.com/google/ExoPlayer/issues/747)). + ([#747](https://github.com/google/ExoPlayer/issues/747)). * Improved handling of sample timestamps and their alignment across variants and renditions. * Fix issue that could cause playbacks to get stuck in an endless initial buffering state. * Correctly propagate BehindLiveWindowException instead of IndexOutOfBoundsException exception - ([1695](https://github.com/google/ExoPlayer/issues/1695)). + ([#1695](https://github.com/google/ExoPlayer/issues/1695)). * MP3/MP4: Support for ID3 metadata, including embedded album art - ([979](https://github.com/google/ExoPlayer/issues/979)). + ([#979](https://github.com/google/ExoPlayer/issues/979)). * Improved customization of UI components. You can read about customization of ExoPlayer's UI components [here](https://medium.com/google-exoplayer/customizing-exoplayers-ui-components-728cf55ee07a#.9ewjg7avi). @@ -31,30 +31,30 @@ update to this version. * Support SCTE-35 splice information messages. * Support multiple table sections in a single PSI section. * Fix NullPointerException when an unsupported stream type is encountered - ([2149](https://github.com/google/ExoPlayer/issues/2149)). + ([#2149](https://github.com/google/ExoPlayer/issues/2149)). * Avoid failure when expected ID3 header not found - ([1966](https://github.com/google/ExoPlayer/issues/1966)). + ([#1966](https://github.com/google/ExoPlayer/issues/1966)). * Improvements to the upstream cache package. * Support caching of media segments for DASH, HLS and SmoothStreaming. Note that caching of manifest and playlist files is still not supported in the (normal) case where the corresponding responses are compressed. * Support caching for ExtractorMediaSource based playbacks. * Improved flexibility of SimpleExoPlayer - ([2102](https://github.com/google/ExoPlayer/issues/2102)). + ([#2102](https://github.com/google/ExoPlayer/issues/2102)). * Fix issue where only the audio of a video would play due to capability - detection issues ([2007](https://github.com/google/ExoPlayer/issues/2007)) - ([2034](https://github.com/google/ExoPlayer/issues/2034)) - ([2157](https://github.com/google/ExoPlayer/issues/2157)). + detection issues ([#2007](https://github.com/google/ExoPlayer/issues/2007)) + ([#2034](https://github.com/google/ExoPlayer/issues/2034)) + ([#2157](https://github.com/google/ExoPlayer/issues/2157)). * Fix issues that could cause ExtractorMediaSource based playbacks to get stuck - buffering ([1962](https://github.com/google/ExoPlayer/issues/1962)). + buffering ([#1962](https://github.com/google/ExoPlayer/issues/1962)). * Correctly set SimpleExoPlayerView surface aspect ratio when an active player - is attached ([2077](https://github.com/google/ExoPlayer/issues/1976)). + is attached ([#2077](https://github.com/google/ExoPlayer/issues/1976)). * OGG: Fix playback of short OGG files - ([1976](https://github.com/google/ExoPlayer/issues/1976)). + ([#1976](https://github.com/google/ExoPlayer/issues/1976)). * MP4: Support `.mp3` tracks - ([2066](https://github.com/google/ExoPlayer/issues/2066)). + ([#2066](https://github.com/google/ExoPlayer/issues/2066)). * SubRip: Don't fail playbacks if SubRip file contains negative timestamps - ([2145](https://github.com/google/ExoPlayer/issues/2145)). + ([#2145](https://github.com/google/ExoPlayer/issues/2145)). * Misc bugfixes. ### r2.0.4 ### @@ -185,11 +185,11 @@ V2 release. * Improvements to the upstream cache package. * MP4: Support `.mp3` tracks - ([2066](https://github.com/google/ExoPlayer/issues/2066)). + ([#2066](https://github.com/google/ExoPlayer/issues/2066)). * SubRip: Don't fail playbacks if SubRip file contains negative timestamps - ([2145](https://github.com/google/ExoPlayer/issues/2145)). + ([#2145](https://github.com/google/ExoPlayer/issues/2145)). * MPEG-TS: Avoid failure when expected ID3 header not found - ([1966](https://github.com/google/ExoPlayer/issues/1966)). + ([#1966](https://github.com/google/ExoPlayer/issues/1966)). * Misc bugfixes. ### r1.5.12 ### From a6360ab6c05235302ae9a54c8dab7678fa880d5e Mon Sep 17 00:00:00 2001 From: olly Date: Thu, 15 Dec 2016 03:31:18 -0800 Subject: [PATCH 11/17] Fix playback of media with >1MB preparation data Also clarify when getNextLoadPositionUs and continueLoading can be called. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=142124497 --- .../exoplayer2/ExoPlayerImplInternal.java | 7 ++--- .../source/ExtractorMediaPeriod.java | 2 +- .../exoplayer2/source/MediaPeriod.java | 28 +++++++++++++++++++ 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/library/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java b/library/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java index 66be6b74783..8866bb7c483 100644 --- a/library/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java +++ b/library/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java @@ -676,6 +676,7 @@ private void resetInternal(boolean releaseMediaSource) { standaloneMediaClock.stop(); rendererMediaClock = null; rendererMediaClockSource = null; + rendererPositionUs = RENDERER_TIMESTAMP_OFFSET_US; for (Renderer renderer : enabledRenderers) { try { ensureStopped(renderer); @@ -823,9 +824,6 @@ private boolean isTimelineReady(long playingPeriodDurationUs) { } private boolean haveSufficientBuffer(boolean rebuffering) { - if (loadingPeriodHolder == null) { - return false; - } long loadingPeriodBufferedPositionUs = !loadingPeriodHolder.prepared ? loadingPeriodHolder.startPositionUs : loadingPeriodHolder.mediaPeriod.getBufferedPositionUs(); @@ -1287,7 +1285,8 @@ private void handleContinueLoadingRequested(MediaPeriod period) { } private void maybeContinueLoading() { - long nextLoadPositionUs = loadingPeriodHolder.mediaPeriod.getNextLoadPositionUs(); + long nextLoadPositionUs = !loadingPeriodHolder.prepared ? 0 + : loadingPeriodHolder.mediaPeriod.getNextLoadPositionUs(); if (nextLoadPositionUs == C.TIME_END_OF_SOURCE) { setIsLoading(false); } else { diff --git a/library/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java b/library/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java index 0b7190d3828..8ab4d45c470 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java @@ -244,7 +244,7 @@ public boolean continueLoading(long playbackPositionUs) { @Override public long getNextLoadPositionUs() { - return getBufferedPositionUs(); + return enabledTrackCount == 0 ? C.TIME_END_OF_SOURCE : getBufferedPositionUs(); } @Override diff --git a/library/src/main/java/com/google/android/exoplayer2/source/MediaPeriod.java b/library/src/main/java/com/google/android/exoplayer2/source/MediaPeriod.java index a3c1c88df45..f4a9665b106 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/MediaPeriod.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/MediaPeriod.java @@ -133,4 +133,32 @@ long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, */ long seekToUs(long positionUs); + // SequenceableLoader interface. Overridden to provide more specific documentation. + + /** + * Returns the next load time, or {@link C#TIME_END_OF_SOURCE} if loading has finished. + *

+ * This method should only be called after the period has been prepared. It may be called when no + * tracks are selected. + */ + @Override + long getNextLoadPositionUs(); + + /** + * Attempts to continue loading. + *

+ * This method may be called both during and after the period has been prepared. + *

+ * A period may call {@link Callback#onContinueLoadingRequested(SequenceableLoader)} on the + * {@link Callback} passed to {@link #prepare(Callback)} to request that this method be called + * when the period is permitted to continue loading data. A period may do this both during and + * after preparation. + * + * @param positionUs The current playback position. + * @return True if progress was made, meaning that {@link #getNextLoadPositionUs()} will return + * a different value than prior to the call. False otherwise. + */ + @Override + boolean continueLoading(long positionUs); + } From ada19a25403ac11f4899624febfca8a2d17e17b2 Mon Sep 17 00:00:00 2001 From: olly Date: Fri, 16 Dec 2016 06:03:28 -0800 Subject: [PATCH 12/17] Correctly offset subsample timestamps. This has always been broken in V2, but the issue is now also visible for the very first period in the timeline because we offset if by 60s. Previously the issue would only have been visible from the start of the second period. Issue: #2208 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=142252702 --- .../java/com/google/android/exoplayer2/BaseRenderer.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/src/main/java/com/google/android/exoplayer2/BaseRenderer.java b/library/src/main/java/com/google/android/exoplayer2/BaseRenderer.java index 447e39bf52f..514bbca8f4e 100644 --- a/library/src/main/java/com/google/android/exoplayer2/BaseRenderer.java +++ b/library/src/main/java/com/google/android/exoplayer2/BaseRenderer.java @@ -267,6 +267,12 @@ protected final int readSource(FormatHolder formatHolder, DecoderInputBuffer buf return streamIsFinal ? C.RESULT_BUFFER_READ : C.RESULT_NOTHING_READ; } buffer.timeUs += streamOffsetUs; + } else if (result == C.RESULT_FORMAT_READ) { + Format format = formatHolder.format; + if (format.subsampleOffsetUs != Format.OFFSET_SAMPLE_RELATIVE) { + format = format.copyWithSubsampleOffsetUs(format.subsampleOffsetUs + streamOffsetUs); + formatHolder.format = format; + } } return result; } From f3d1065b5f26824535cea51dafa90daff13b90b4 Mon Sep 17 00:00:00 2001 From: olly Date: Mon, 19 Dec 2016 06:56:04 -0800 Subject: [PATCH 13/17] Fix large timestamps for HLS playbacks - If there's no program-date-time then this change is a no-op. - If there is a program-date-time this change considers the period as having started at the epoch rather than at the start of the content. The window is then set to start at the start of the content. This is a little weird, but is required so that the period sample timestamps match the start of the period. Note that this also brings the handling of on-demand in line with how the live case is handled, meaning there wont be weird changes if a live stream changes into an on-demand one. Issue: #2224 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=142442719 --- .../android/exoplayer2/source/hls/HlsMediaSource.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java b/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java index 2f46fc694c6..869efa6cdcf 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java @@ -104,15 +104,14 @@ public void onPrimaryPlaylistRefreshed(HlsMediaPlaylist playlist) { SinglePeriodTimeline timeline; if (playlistTracker.isLive()) { // TODO: fix windowPositionInPeriodUs when playlist is empty. - long windowPositionInPeriodUs = playlist.startTimeUs; List segments = playlist.segments; long windowDefaultStartPositionUs = segments.isEmpty() ? 0 : segments.get(Math.max(0, segments.size() - 3)).relativeStartTimeUs; timeline = new SinglePeriodTimeline(C.TIME_UNSET, playlist.durationUs, - windowPositionInPeriodUs, windowDefaultStartPositionUs, true, !playlist.hasEndTag); + playlist.startTimeUs, windowDefaultStartPositionUs, true, !playlist.hasEndTag); } else /* not live */ { - timeline = new SinglePeriodTimeline(playlist.durationUs, playlist.durationUs, 0, 0, true, - false); + timeline = new SinglePeriodTimeline(playlist.startTimeUs + playlist.durationUs, + playlist.durationUs, playlist.startTimeUs, 0, true, false); } sourceListener.onSourceInfoRefreshed(timeline, playlist); } From cb3f3499265e5dbf50ac4544b5a3a8fe7fd0ad8c Mon Sep 17 00:00:00 2001 From: olly Date: Tue, 20 Dec 2016 03:28:19 -0800 Subject: [PATCH 14/17] Bump version + update release notes ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=142539314 --- RELEASENOTES.md | 16 +++++++++++++--- build.gradle | 2 +- demo/src/main/AndroidManifest.xml | 4 ++-- .../android/exoplayer2/ExoPlayerLibraryInfo.java | 4 ++-- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index a3faadacce2..a468e72a7ab 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,9 +1,19 @@ # Release notes # -### r2.1.0 ### +### r2.1.1 ### + +Bugfix release only. Users of r2.1.0 and r2.0.x should proactively update to +this version. -This release contains important bug fixes. Users of r2.0.x should proactively -update to this version. +* Fix some subtitle types (e.g. WebVTT) being displayed out of sync + ([#2208](https://github.com/google/ExoPlayer/issues/2208)). +* Fix incorrect position reporting for on-demand HLS media that includes + EXT-X-PROGRAM-DATE-TIME tags + ([#2224](https://github.com/google/ExoPlayer/issues/2224)). +* Fix issue where playbacks could get stuck in the initial buffering state if + over 1MB of data needs to be read to initialize the playback. + +### r2.1.0 ### * HLS: Support for seeking in live streams ([#87](https://github.com/google/ExoPlayer/issues/87)). diff --git a/build.gradle b/build.gradle index 0ea3ad66f30..358b8f14048 100644 --- a/build.gradle +++ b/build.gradle @@ -35,7 +35,7 @@ allprojects { releaseRepoName = 'exoplayer' releaseUserOrg = 'google' releaseGroupId = 'com.google.android.exoplayer' - releaseVersion = 'r2.1.0' + releaseVersion = 'r2.1.1' releaseWebsite = 'https://github.com/google/ExoPlayer' } } diff --git a/demo/src/main/AndroidManifest.xml b/demo/src/main/AndroidManifest.xml index d1b44abafe8..4c6d8322112 100644 --- a/demo/src/main/AndroidManifest.xml +++ b/demo/src/main/AndroidManifest.xml @@ -16,8 +16,8 @@ + android:versionCode="2101" + android:versionName="2.1.1"> diff --git a/library/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java b/library/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java index 45f63d713da..ea522ac4c84 100644 --- a/library/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java +++ b/library/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java @@ -23,7 +23,7 @@ public interface ExoPlayerLibraryInfo { /** * The version of the library, expressed as a string. */ - String VERSION = "2.1.0"; + String VERSION = "2.1.1"; /** * The version of the library, expressed as an integer. @@ -32,7 +32,7 @@ public interface ExoPlayerLibraryInfo { * corresponding integer version 1002003 (001-002-003), and "123.45.6" has the corresponding * integer version 123045006 (123-045-006). */ - int VERSION_INT = 2001000; + int VERSION_INT = 2001001; /** * Whether the library was compiled with {@link com.google.android.exoplayer2.util.Assertions} From 807e2db02617a324968a5c672e050261e7bbca0a Mon Sep 17 00:00:00 2001 From: ojw28 Date: Wed, 21 Dec 2016 00:51:06 +0000 Subject: [PATCH 15/17] Delete HlsTest --- .../exoplayer2/playbacktests/hls/HlsTest.java | 171 ------------------ 1 file changed, 171 deletions(-) delete mode 100644 playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/hls/HlsTest.java diff --git a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/hls/HlsTest.java b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/hls/HlsTest.java deleted file mode 100644 index 99f8944c48e..00000000000 --- a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/hls/HlsTest.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * 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.playbacktests.hls; - -import android.annotation.TargetApi; -import android.net.Uri; -import android.test.ActivityInstrumentationTestCase2; -import com.google.android.exoplayer2.C; -import com.google.android.exoplayer2.ExoPlayer; -import com.google.android.exoplayer2.playbacktests.util.ExoHostedTest; -import com.google.android.exoplayer2.playbacktests.util.HostActivity; -import com.google.android.exoplayer2.source.MediaSource; -import com.google.android.exoplayer2.source.hls.HlsMediaSource; -import com.google.android.exoplayer2.upstream.DataSource; -import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; -import com.google.android.exoplayer2.upstream.TransferListener; -import com.google.android.exoplayer2.util.Assertions; -import com.google.android.exoplayer2.util.ClosedSource; -import com.google.android.exoplayer2.util.Util; -import java.io.IOException; - -/** - * Tests HLS playbacks using {@link ExoPlayer}. - */ -@ClosedSource(reason = "Streams are internal") -public final class HlsTest extends ActivityInstrumentationTestCase2 { - - private static final String TAG = "HlsTest"; - private static final String BASE_URL = "https://storage.googleapis.com/" - + "exoplayer-test-media-internal-63834241aced7884c2544af1a3452e01/hls/bipbop/"; - private static final long TIMEOUT_MS = 3 * 60 * 1000; - - public HlsTest() { - super(HostActivity.class); - } - - /** - * Tests playback for two variants with all segments available. - */ - public void testAllSegmentsAvailable() throws IOException { - testPlaybackForPath("bipbop-all-200.m3u8"); - } - - /** - * Tests playback for a single variant with all segments available. - */ - public void testSingleGearAllSegmentsAvailable() throws IOException { - testPlaybackForPath("gear1/prog_index.m3u8"); - } - - /** - * Tests playback for two variants where the first has an unavailable playlist. Playback should - * succeed using the second variant. - */ - public void testGear1PlaylistMissing() throws IOException { - testPlaybackForPath("bipbop-gear1-playlist-404.m3u8"); - } - - /** - * Tests playback for two variants where the second has an unavailable playlist. Playback should - * succeed using the first variant. - */ - public void testGear2PlaylistMissing() throws IOException { - testPlaybackForPath("bipbop-gear2-playlist-404.m3u8"); - } - - /** - * Tests playback for two variants where the first has a missing first segment. Playback should - * succeed using the first segment from the second variant. - */ - public void testGear1Seg1Missing() throws IOException { - testPlaybackForPath("bipbop-gear1-seg1-404.m3u8"); - } - - /** - * Tests playback for two variants where the second has a missing first segment. Playback should - * succeed using the first segment from the first variant. - */ - public void testGear2Seg1Missing() throws IOException { - testPlaybackForPath("bipbop-gear2-seg1-404.m3u8"); - } - - /** - * Tests playback for two variants where the first has a missing second segment. Playback should - * succeed using the second segment from the second variant. - */ - public void testGear1Seg2Missing() throws IOException { - testPlaybackForPath("bipbop-gear1-seg2-404.m3u8"); - } - - /** - * Tests playback for two variants where the second has a missing second segment. Playback should - * succeed using the second segment from the first variant. - */ - public void testGear2Seg2Missing() throws IOException { - testPlaybackForPath("bipbop-gear2-seg2-404.m3u8"); - } - - /** - * Tests playback for two variants where the first has a missing sixth segment. Playback should - * succeed using the sixth segment from the second variant. - */ - public void testGear1Seg6Missing() throws IOException { - testPlaybackForPath("bipbop-gear1-seg6-404.m3u8"); - } - - /** - * Tests playback for two variants where the second has a missing sixth segment. Playback should - * succeed using the sixth segment from the first variant. - */ - public void testGear2Seg6Missing() throws IOException { - testPlaybackForPath("bipbop-gear2-seg6-404.m3u8"); - } - - /** - * Tests playback of a single variant with a missing sixth segment. Playback should fail, however - * should not do so until playback reaches the missing segment at 60 seconds. - */ - public void testSingleGearSeg6Missing() throws IOException { - testPlaybackForPath("gear1/prog_index-seg6-404.m3u8", 60000); - } - - private void testPlaybackForPath(String path) throws IOException { - testPlaybackForPath(path, C.TIME_UNSET); - } - - private void testPlaybackForPath(String path, long expectedFailureTimeMs) throws IOException { - if (Util.SDK_INT < 16) { - // Pass. - return; - } - HlsHostedTest test = new HlsHostedTest(Uri.parse(BASE_URL + path), expectedFailureTimeMs); - getActivity().runTest(test, TIMEOUT_MS); - } - - @TargetApi(16) - private static class HlsHostedTest extends ExoHostedTest { - - private final Uri playlistUri; - - public HlsHostedTest(Uri playlistUri, long expectedFailureTimeMs) { - super(TAG, expectedFailureTimeMs == C.TIME_UNSET - ? ExoHostedTest.EXPECTED_PLAYING_TIME_MEDIA_DURATION_MS : expectedFailureTimeMs, - expectedFailureTimeMs == C.TIME_UNSET); - this.playlistUri = Assertions.checkNotNull(playlistUri); - } - - @Override - public MediaSource buildSource(HostActivity host, String userAgent, - TransferListener mediaTransferListener) { - DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(host, userAgent, - mediaTransferListener); - return new HlsMediaSource(playlistUri, dataSourceFactory, null, null); - } - - } - -} From d816d26d83804339007806fca2ffd84316b2b975 Mon Sep 17 00:00:00 2001 From: Ippei Nawate Date: Wed, 4 Jan 2017 17:24:53 +0900 Subject: [PATCH 16/17] Fix RELEASENOTES.md --- RELEASENOTES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index a468e72a7ab..fdb5e3d8a2b 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -58,7 +58,7 @@ this version. * Fix issues that could cause ExtractorMediaSource based playbacks to get stuck buffering ([#1962](https://github.com/google/ExoPlayer/issues/1962)). * Correctly set SimpleExoPlayerView surface aspect ratio when an active player - is attached ([#2077](https://github.com/google/ExoPlayer/issues/1976)). + is attached ([#2077](https://github.com/google/ExoPlayer/issues/2077)). * OGG: Fix playback of short OGG files ([#1976](https://github.com/google/ExoPlayer/issues/1976)). * MP4: Support `.mp3` tracks From 75eb047e626ff5405c55cf1da382735124935c35 Mon Sep 17 00:00:00 2001 From: Hassan Abid Date: Thu, 5 Jan 2017 21:31:08 +0900 Subject: [PATCH 17/17] remove ClippingMediaSourceTest from library --- .../source/ClippingMediaSourceTest.java | 143 ------------------ 1 file changed, 143 deletions(-) delete mode 100644 library/src/androidTest/java/com/google/android/exoplayer2/source/ClippingMediaSourceTest.java diff --git a/library/src/androidTest/java/com/google/android/exoplayer2/source/ClippingMediaSourceTest.java b/library/src/androidTest/java/com/google/android/exoplayer2/source/ClippingMediaSourceTest.java deleted file mode 100644 index 0933fb858b0..00000000000 --- a/library/src/androidTest/java/com/google/android/exoplayer2/source/ClippingMediaSourceTest.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * 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.source; - -import static org.mockito.Mockito.doAnswer; - -import android.test.InstrumentationTestCase; -import com.google.android.exoplayer2.C; -import com.google.android.exoplayer2.ExoPlayer; -import com.google.android.exoplayer2.Timeline; -import com.google.android.exoplayer2.Timeline.Period; -import com.google.android.exoplayer2.Timeline.Window; -import com.google.android.exoplayer2.source.MediaSource.Listener; -import com.google.android.exoplayer2.testutil.TestUtil; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -/** - * Unit tests for {@link ClippingMediaSource}. - */ -public final class ClippingMediaSourceTest extends InstrumentationTestCase { - - private static final long TEST_PERIOD_DURATION_US = 1000000; - private static final long TEST_CLIP_AMOUNT_US = 300000; - - @Mock - private MediaSource mockMediaSource; - private Timeline clippedTimeline; - private Window window; - private Period period; - - @Override - protected void setUp() throws Exception { - TestUtil.setUpMockito(this); - window = new Timeline.Window(); - period = new Timeline.Period(); - } - - public void testNoClipping() { - Timeline timeline = new SinglePeriodTimeline(C.msToUs(TEST_PERIOD_DURATION_US), true); - - Timeline clippedTimeline = getClippedTimeline(timeline, 0, TEST_PERIOD_DURATION_US); - - assertEquals(1, clippedTimeline.getWindowCount()); - assertEquals(1, clippedTimeline.getPeriodCount()); - assertEquals(TEST_PERIOD_DURATION_US, clippedTimeline.getWindow(0, window).getDurationUs()); - assertEquals(TEST_PERIOD_DURATION_US, clippedTimeline.getPeriod(0, period).getDurationUs()); - } - - public void testClippingUnseekableWindowThrows() { - Timeline timeline = new SinglePeriodTimeline(C.msToUs(TEST_PERIOD_DURATION_US), false); - - // If the unseekable window isn't clipped, clipping succeeds. - getClippedTimeline(timeline, 0, TEST_PERIOD_DURATION_US); - try { - // If the unseekable window is clipped, clipping fails. - getClippedTimeline(timeline, 1, TEST_PERIOD_DURATION_US); - fail("Expected clipping to fail."); - } catch (IllegalArgumentException e) { - // Expected. - } - } - - public void testClippingStart() { - Timeline timeline = new SinglePeriodTimeline(C.msToUs(TEST_PERIOD_DURATION_US), true); - - Timeline clippedTimeline = getClippedTimeline(timeline, TEST_CLIP_AMOUNT_US, - TEST_PERIOD_DURATION_US); - assertEquals(TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US, - clippedTimeline.getWindow(0, window).getDurationUs()); - assertEquals(TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US, - clippedTimeline.getPeriod(0, period).getDurationUs()); - } - - public void testClippingEnd() { - Timeline timeline = new SinglePeriodTimeline(C.msToUs(TEST_PERIOD_DURATION_US), true); - - Timeline clippedTimeline = getClippedTimeline(timeline, 0, - TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US); - assertEquals(TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US, - clippedTimeline.getWindow(0, window).getDurationUs()); - assertEquals(TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US, - clippedTimeline.getPeriod(0, period).getDurationUs()); - } - - public void testClippingStartAndEnd() { - Timeline timeline = new SinglePeriodTimeline(C.msToUs(TEST_PERIOD_DURATION_US), true); - - Timeline clippedTimeline = getClippedTimeline(timeline, TEST_CLIP_AMOUNT_US, - TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US * 2); - assertEquals(TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US * 3, - clippedTimeline.getWindow(0, window).getDurationUs()); - assertEquals(TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US * 3, - clippedTimeline.getPeriod(0, period).getDurationUs()); - } - - /** - * Wraps the specified timeline in a {@link ClippingMediaSource} and returns the clipped timeline. - */ - private Timeline getClippedTimeline(Timeline timeline, long startMs, long endMs) { - mockMediaSourceSourceWithTimeline(timeline); - new ClippingMediaSource(mockMediaSource, startMs, endMs).prepareSource(null, true, - new Listener() { - @Override - public void onSourceInfoRefreshed(Timeline timeline, Object manifest) { - clippedTimeline = timeline; - } - }); - return clippedTimeline; - } - - /** - * Returns a mock {@link MediaSource} with the specified {@link Timeline} in its source info. - */ - private MediaSource mockMediaSourceSourceWithTimeline(final Timeline timeline) { - doAnswer(new Answer() { - @Override - public Void answer(InvocationOnMock invocation) throws Throwable { - MediaSource.Listener listener = (MediaSource.Listener) invocation.getArguments()[2]; - listener.onSourceInfoRefreshed(timeline, null); - return null; - } - }).when(mockMediaSource).prepareSource(Mockito.any(ExoPlayer.class), Mockito.anyBoolean(), - Mockito.any(MediaSource.Listener.class)); - return mockMediaSource; - } - -}