Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
SDK
/
exoplayer
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
35e030f5
authored
May 20, 2019
by
Oliver Woodman
Committed by
GitHub
May 20, 2019
Browse files
Options
_('Browse Files')
Download
Plain Diff
Merge pull request #5895 from google/dev-v2-r2.10.1
r2.10.1
parents
44293e8f
9ec330e7
Show whitespace changes
Inline
Side-by-side
Showing
33 changed files
with
355 additions
and
115 deletions
RELEASENOTES.md
constants.gradle
demos/main/src/main/java/com/google/android/exoplayer2/demo/DownloadTracker.java
demos/main/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java
extensions/cronet/src/main/java/com/google/android/exoplayer2/ext/cronet/CronetDataSource.java
extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoader.java
extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSource.java
gradle.properties
javadoc_library.gradle
library/core/proguard-rules.txt
library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java
library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java
library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java
library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsListener.java
library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java
library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java
library/core/src/main/java/com/google/android/exoplayer2/metadata/icy/IcyDecoder.java
library/core/src/main/java/com/google/android/exoplayer2/offline/DefaultDownloadIndex.java
library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadHelper.java
library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadManager.java
library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadService.java
library/core/src/main/java/com/google/android/exoplayer2/offline/WritableDownloadIndex.java
library/core/src/main/java/com/google/android/exoplayer2/scheduler/PlatformScheduler.java
library/core/src/main/java/com/google/android/exoplayer2/text/dvb/DvbParser.java
library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultHttpDataSource.java
library/core/src/test/java/com/google/android/exoplayer2/metadata/icy/IcyDecoderTest.java
library/core/src/test/java/com/google/android/exoplayer2/offline/DownloadManagerTest.java
library/dash/README.md
library/hls/README.md
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java
library/smoothstreaming/README.md
library/ui/README.md
testutils_robolectric/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaChunk.java
RELEASENOTES.md
View file @
35e030f5
# Release notes #
# Release notes #
### 2.10.1 ###
*
Offline: Add option to remove all downloads.
*
HLS: Fix
`NullPointerException`
when using HLS chunkless preparation
(
[
#5868
](
https://github.com/google/ExoPlayer/issues/5868
)
).
*
Fix handling of empty values and line terminators in SHOUTcast ICY metadata
(
[
#5876
](
https://github.com/google/ExoPlayer/issues/5876
)
).
*
Fix DVB subtitles for SDK 28
(
[
#5862
](
https://github.com/google/ExoPlayer/issues/5862
)
).
*
Add a workaround for a decoder failure on ZTE Axon7 mini devices when playing
48kHz audio (
[
#5821
](
https://github.com/google/ExoPlayer/issues/5821
)
).
### 2.10.0 ###
### 2.10.0 ###
*
Core library:
*
Core library:
...
...
constants.gradle
View file @
35e030f5
...
@@ -13,8 +13,8 @@
...
@@ -13,8 +13,8 @@
// limitations under the License.
// limitations under the License.
project
.
ext
{
project
.
ext
{
// ExoPlayer version and version code.
// ExoPlayer version and version code.
releaseVersion
=
'2.10.
0
'
releaseVersion
=
'2.10.
1
'
releaseVersionCode
=
201000
0
releaseVersionCode
=
201000
1
minSdkVersion
=
16
minSdkVersion
=
16
targetSdkVersion
=
28
targetSdkVersion
=
28
compileSdkVersion
=
28
compileSdkVersion
=
28
...
...
demos/main/src/main/java/com/google/android/exoplayer2/demo/DownloadTracker.java
View file @
35e030f5
...
@@ -30,15 +30,12 @@ import com.google.android.exoplayer2.offline.DownloadIndex;
...
@@ -30,15 +30,12 @@ import com.google.android.exoplayer2.offline.DownloadIndex;
import
com.google.android.exoplayer2.offline.DownloadManager
;
import
com.google.android.exoplayer2.offline.DownloadManager
;
import
com.google.android.exoplayer2.offline.DownloadRequest
;
import
com.google.android.exoplayer2.offline.DownloadRequest
;
import
com.google.android.exoplayer2.offline.DownloadService
;
import
com.google.android.exoplayer2.offline.DownloadService
;
import
com.google.android.exoplayer2.offline.StreamKey
;
import
com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo
;
import
com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo
;
import
com.google.android.exoplayer2.upstream.DataSource
;
import
com.google.android.exoplayer2.upstream.DataSource
;
import
com.google.android.exoplayer2.util.Log
;
import
com.google.android.exoplayer2.util.Log
;
import
com.google.android.exoplayer2.util.Util
;
import
com.google.android.exoplayer2.util.Util
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.concurrent.CopyOnWriteArraySet
;
import
java.util.concurrent.CopyOnWriteArraySet
;
/** Tracks media that has been downloaded. */
/** Tracks media that has been downloaded. */
...
@@ -86,11 +83,9 @@ public class DownloadTracker {
...
@@ -86,11 +83,9 @@ public class DownloadTracker {
}
}
@SuppressWarnings
(
"unchecked"
)
@SuppressWarnings
(
"unchecked"
)
public
List
<
StreamKey
>
getOfflineStreamKeys
(
Uri
uri
)
{
public
DownloadRequest
getDownloadRequest
(
Uri
uri
)
{
Download
download
=
downloads
.
get
(
uri
);
Download
download
=
downloads
.
get
(
uri
);
return
download
!=
null
&&
download
.
state
!=
Download
.
STATE_FAILED
return
download
!=
null
&&
download
.
state
!=
Download
.
STATE_FAILED
?
download
.
request
:
null
;
?
download
.
request
.
streamKeys
:
Collections
.
emptyList
();
}
}
public
void
toggleDownload
(
public
void
toggleDownload
(
...
...
demos/main/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java
View file @
35e030f5
...
@@ -45,7 +45,8 @@ import com.google.android.exoplayer2.drm.HttpMediaDrmCallback;
...
@@ -45,7 +45,8 @@ import com.google.android.exoplayer2.drm.HttpMediaDrmCallback;
import
com.google.android.exoplayer2.drm.UnsupportedDrmException
;
import
com.google.android.exoplayer2.drm.UnsupportedDrmException
;
import
com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.DecoderInitializationException
;
import
com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.DecoderInitializationException
;
import
com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException
;
import
com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException
;
import
com.google.android.exoplayer2.offline.StreamKey
;
import
com.google.android.exoplayer2.offline.DownloadHelper
;
import
com.google.android.exoplayer2.offline.DownloadRequest
;
import
com.google.android.exoplayer2.source.BehindLiveWindowException
;
import
com.google.android.exoplayer2.source.BehindLiveWindowException
;
import
com.google.android.exoplayer2.source.ConcatenatingMediaSource
;
import
com.google.android.exoplayer2.source.ConcatenatingMediaSource
;
import
com.google.android.exoplayer2.source.MediaSource
;
import
com.google.android.exoplayer2.source.MediaSource
;
...
@@ -75,7 +76,6 @@ import java.lang.reflect.Constructor;
...
@@ -75,7 +76,6 @@ import java.lang.reflect.Constructor;
import
java.net.CookieHandler
;
import
java.net.CookieHandler
;
import
java.net.CookieManager
;
import
java.net.CookieManager
;
import
java.net.CookiePolicy
;
import
java.net.CookiePolicy
;
import
java.util.List
;
import
java.util.UUID
;
import
java.util.UUID
;
/** An activity that plays media using {@link SimpleExoPlayer}. */
/** An activity that plays media using {@link SimpleExoPlayer}. */
...
@@ -457,32 +457,25 @@ public class PlayerActivity extends AppCompatActivity
...
@@ -457,32 +457,25 @@ public class PlayerActivity extends AppCompatActivity
}
}
private
MediaSource
buildMediaSource
(
Uri
uri
,
@Nullable
String
overrideExtension
)
{
private
MediaSource
buildMediaSource
(
Uri
uri
,
@Nullable
String
overrideExtension
)
{
DownloadRequest
downloadRequest
=
((
DemoApplication
)
getApplication
()).
getDownloadTracker
().
getDownloadRequest
(
uri
);
if
(
downloadRequest
!=
null
)
{
return
DownloadHelper
.
createMediaSource
(
downloadRequest
,
dataSourceFactory
);
}
@ContentType
int
type
=
Util
.
inferContentType
(
uri
,
overrideExtension
);
@ContentType
int
type
=
Util
.
inferContentType
(
uri
,
overrideExtension
);
List
<
StreamKey
>
offlineStreamKeys
=
getOfflineStreamKeys
(
uri
);
switch
(
type
)
{
switch
(
type
)
{
case
C
.
TYPE_DASH
:
case
C
.
TYPE_DASH
:
return
new
DashMediaSource
.
Factory
(
dataSourceFactory
)
return
new
DashMediaSource
.
Factory
(
dataSourceFactory
).
createMediaSource
(
uri
);
.
setStreamKeys
(
offlineStreamKeys
)
.
createMediaSource
(
uri
);
case
C
.
TYPE_SS
:
case
C
.
TYPE_SS
:
return
new
SsMediaSource
.
Factory
(
dataSourceFactory
)
return
new
SsMediaSource
.
Factory
(
dataSourceFactory
).
createMediaSource
(
uri
);
.
setStreamKeys
(
offlineStreamKeys
)
.
createMediaSource
(
uri
);
case
C
.
TYPE_HLS
:
case
C
.
TYPE_HLS
:
return
new
HlsMediaSource
.
Factory
(
dataSourceFactory
)
return
new
HlsMediaSource
.
Factory
(
dataSourceFactory
).
createMediaSource
(
uri
);
.
setStreamKeys
(
offlineStreamKeys
)
.
createMediaSource
(
uri
);
case
C
.
TYPE_OTHER
:
case
C
.
TYPE_OTHER
:
return
new
ProgressiveMediaSource
.
Factory
(
dataSourceFactory
).
createMediaSource
(
uri
);
return
new
ProgressiveMediaSource
.
Factory
(
dataSourceFactory
).
createMediaSource
(
uri
);
default
:
{
default
:
throw
new
IllegalStateException
(
"Unsupported type: "
+
type
);
throw
new
IllegalStateException
(
"Unsupported type: "
+
type
);
}
}
}
}
}
private
List
<
StreamKey
>
getOfflineStreamKeys
(
Uri
uri
)
{
return
((
DemoApplication
)
getApplication
()).
getDownloadTracker
().
getOfflineStreamKeys
(
uri
);
}
private
DefaultDrmSessionManager
<
FrameworkMediaCrypto
>
buildDrmSessionManagerV18
(
private
DefaultDrmSessionManager
<
FrameworkMediaCrypto
>
buildDrmSessionManagerV18
(
UUID
uuid
,
String
licenseUrl
,
String
[]
keyRequestPropertiesArray
,
boolean
multiSession
)
UUID
uuid
,
String
licenseUrl
,
String
[]
keyRequestPropertiesArray
,
boolean
multiSession
)
...
...
extensions/cronet/src/main/java/com/google/android/exoplayer2/ext/cronet/CronetDataSource.java
View file @
35e030f5
...
@@ -113,7 +113,7 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource {
...
@@ -113,7 +113,7 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource {
private
final
CronetEngine
cronetEngine
;
private
final
CronetEngine
cronetEngine
;
private
final
Executor
executor
;
private
final
Executor
executor
;
private
final
Predicate
<
String
>
contentTypePredicate
;
@Nullable
private
final
Predicate
<
String
>
contentTypePredicate
;
private
final
int
connectTimeoutMs
;
private
final
int
connectTimeoutMs
;
private
final
int
readTimeoutMs
;
private
final
int
readTimeoutMs
;
private
final
boolean
resetTimeoutOnRedirects
;
private
final
boolean
resetTimeoutOnRedirects
;
...
@@ -153,12 +153,26 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource {
...
@@ -153,12 +153,26 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource {
* hop from Cronet's internal network thread to the response handling thread. However, to
* hop from Cronet's internal network thread to the response handling thread. However, to
* avoid slowing down overall network performance, care must be taken to make sure response
* avoid slowing down overall network performance, care must be taken to make sure response
* handling is a fast operation when using a direct executor.
* handling is a fast operation when using a direct executor.
*/
public
CronetDataSource
(
CronetEngine
cronetEngine
,
Executor
executor
)
{
this
(
cronetEngine
,
executor
,
/* contentTypePredicate= */
null
);
}
/**
* @param cronetEngine A CronetEngine.
* @param executor The {@link java.util.concurrent.Executor} that will handle responses. This may
* be a direct executor (i.e. executes tasks on the calling thread) in order to avoid a thread
* hop from Cronet's internal network thread to the response handling thread. However, to
* avoid slowing down overall network performance, care must be taken to make sure response
* handling is a fast operation when using a direct executor.
* @param contentTypePredicate An optional {@link Predicate}. If a content type is rejected by the
* @param contentTypePredicate An optional {@link Predicate}. If a content type is rejected by the
* predicate then an {@link InvalidContentTypeException} is thrown from {@link
* predicate then an {@link InvalidContentTypeException} is thrown from {@link
* #open(DataSpec)}.
* #open(DataSpec)}.
*/
*/
public
CronetDataSource
(
public
CronetDataSource
(
CronetEngine
cronetEngine
,
Executor
executor
,
Predicate
<
String
>
contentTypePredicate
)
{
CronetEngine
cronetEngine
,
Executor
executor
,
@Nullable
Predicate
<
String
>
contentTypePredicate
)
{
this
(
this
(
cronetEngine
,
cronetEngine
,
executor
,
executor
,
...
@@ -188,7 +202,7 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource {
...
@@ -188,7 +202,7 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource {
public
CronetDataSource
(
public
CronetDataSource
(
CronetEngine
cronetEngine
,
CronetEngine
cronetEngine
,
Executor
executor
,
Executor
executor
,
Predicate
<
String
>
contentTypePredicate
,
@Nullable
Predicate
<
String
>
contentTypePredicate
,
int
connectTimeoutMs
,
int
connectTimeoutMs
,
int
readTimeoutMs
,
int
readTimeoutMs
,
boolean
resetTimeoutOnRedirects
,
boolean
resetTimeoutOnRedirects
,
...
@@ -225,7 +239,7 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource {
...
@@ -225,7 +239,7 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource {
public
CronetDataSource
(
public
CronetDataSource
(
CronetEngine
cronetEngine
,
CronetEngine
cronetEngine
,
Executor
executor
,
Executor
executor
,
Predicate
<
String
>
contentTypePredicate
,
@Nullable
Predicate
<
String
>
contentTypePredicate
,
int
connectTimeoutMs
,
int
connectTimeoutMs
,
int
readTimeoutMs
,
int
readTimeoutMs
,
boolean
resetTimeoutOnRedirects
,
boolean
resetTimeoutOnRedirects
,
...
@@ -246,7 +260,7 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource {
...
@@ -246,7 +260,7 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource {
/* package */
CronetDataSource
(
/* package */
CronetDataSource
(
CronetEngine
cronetEngine
,
CronetEngine
cronetEngine
,
Executor
executor
,
Executor
executor
,
Predicate
<
String
>
contentTypePredicate
,
@Nullable
Predicate
<
String
>
contentTypePredicate
,
int
connectTimeoutMs
,
int
connectTimeoutMs
,
int
readTimeoutMs
,
int
readTimeoutMs
,
boolean
resetTimeoutOnRedirects
,
boolean
resetTimeoutOnRedirects
,
...
...
extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoader.java
View file @
35e030f5
...
@@ -948,8 +948,8 @@ public final class ImaAdsLoader
...
@@ -948,8 +948,8 @@ public final class ImaAdsLoader
@Override
@Override
public
void
onTimelineChanged
(
public
void
onTimelineChanged
(
Timeline
timeline
,
@Nullable
Object
manifest
,
@Player
.
TimelineChangeReason
int
reason
)
{
Timeline
timeline
,
@Nullable
Object
manifest
,
@Player
.
TimelineChangeReason
int
reason
)
{
if
(
reason
==
Player
.
TIMELINE_CHANGE_REASON_RESET
)
{
if
(
timeline
.
isEmpty
()
)
{
// The player is being reset
and this source will be released
.
// The player is being reset
or contains no media
.
return
;
return
;
}
}
Assertions
.
checkArgument
(
timeline
.
getPeriodCount
()
==
1
);
Assertions
.
checkArgument
(
timeline
.
getPeriodCount
()
==
1
);
...
...
extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSource.java
View file @
35e030f5
...
@@ -77,6 +77,15 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource {
...
@@ -77,6 +77,15 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource {
* @param callFactory A {@link Call.Factory} (typically an {@link okhttp3.OkHttpClient}) for use
* @param callFactory A {@link Call.Factory} (typically an {@link okhttp3.OkHttpClient}) for use
* by the source.
* by the source.
* @param userAgent An optional User-Agent string.
* @param userAgent An optional User-Agent string.
*/
public
OkHttpDataSource
(
Call
.
Factory
callFactory
,
@Nullable
String
userAgent
)
{
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.
* @param contentTypePredicate An optional {@link Predicate}. If a content type is rejected by the
* @param contentTypePredicate An optional {@link Predicate}. If a content type is rejected by the
* predicate then a {@link InvalidContentTypeException} is thrown from {@link
* predicate then a {@link InvalidContentTypeException} is thrown from {@link
* #open(DataSpec)}.
* #open(DataSpec)}.
...
...
gradle.properties
View file @
35e030f5
...
@@ -3,3 +3,4 @@ android.useAndroidX=true
...
@@ -3,3 +3,4 @@ android.useAndroidX=true
android.enableJetifier
=
true
android.enableJetifier
=
true
android.enableUnitTestBinaryResources
=
true
android.enableUnitTestBinaryResources
=
true
buildDir
=
buildout
buildDir
=
buildout
org.gradle.jvmargs
=
-Xmx2g -XX:MaxMetaspaceSize=512m
javadoc_library.gradle
View file @
35e030f5
...
@@ -18,10 +18,13 @@ android.libraryVariants.all { variant ->
...
@@ -18,10 +18,13 @@ android.libraryVariants.all { variant ->
if
(!
name
.
equals
(
"release"
))
{
if
(!
name
.
equals
(
"release"
))
{
return
;
// Skip non-release builds.
return
;
// Skip non-release builds.
}
}
def
allSourceDirs
=
variant
.
sourceSets
.
inject
([])
{
acc
,
val
->
acc
<<
val
.
javaDirectories
}
task
(
"generateJavadoc"
,
type:
Javadoc
)
{
task
(
"generateJavadoc"
,
type:
Javadoc
)
{
description
=
"Generates Javadoc for the ${javadocTitle}."
description
=
"Generates Javadoc for the ${javadocTitle}."
title
=
"ExoPlayer ${javadocTitle}"
title
=
"ExoPlayer ${javadocTitle}"
source
=
variant
.
javaCompileProvider
.
get
().
source
source
=
allSourceDirs
options
{
options
{
links
"http://docs.oracle.com/javase/7/docs/api/"
links
"http://docs.oracle.com/javase/7/docs/api/"
linksOffline
"https://developer.android.com/reference"
,
linksOffline
"https://developer.android.com/reference"
,
...
...
library/core/proguard-rules.txt
View file @
35e030f5
...
@@ -46,18 +46,21 @@
...
@@ -46,18 +46,21 @@
# Constructors accessed via reflection in DownloadHelper
# Constructors accessed via reflection in DownloadHelper
-dontnote com.google.android.exoplayer2.source.dash.DashMediaSource$Factory
-dontnote com.google.android.exoplayer2.source.dash.DashMediaSource$Factory
-keepclassmembers class com.google.android.exoplayer2.source.dash.DashMediaSource$Factory {
-keepclass
eswith
members class com.google.android.exoplayer2.source.dash.DashMediaSource$Factory {
<init>(com.google.android.exoplayer2.upstream.DataSource$Factory);
<init>(com.google.android.exoplayer2.upstream.DataSource$Factory);
** setStreamKeys(java.util.List);
com.google.android.exoplayer2.source.dash.DashMediaSource createMediaSource(android.net.Uri);
com.google.android.exoplayer2.source.dash.DashMediaSource createMediaSource(android.net.Uri);
}
}
-dontnote com.google.android.exoplayer2.source.hls.HlsMediaSource$Factory
-dontnote com.google.android.exoplayer2.source.hls.HlsMediaSource$Factory
-keepclassmembers class com.google.android.exoplayer2.source.hls.HlsMediaSource$Factory {
-keepclass
eswith
members class com.google.android.exoplayer2.source.hls.HlsMediaSource$Factory {
<init>(com.google.android.exoplayer2.upstream.DataSource$Factory);
<init>(com.google.android.exoplayer2.upstream.DataSource$Factory);
** setStreamKeys(java.util.List);
com.google.android.exoplayer2.source.hls.HlsMediaSource createMediaSource(android.net.Uri);
com.google.android.exoplayer2.source.hls.HlsMediaSource createMediaSource(android.net.Uri);
}
}
-dontnote com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource$Factory
-dontnote com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource$Factory
-keepclassmembers class com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource$Factory {
-keepclass
eswith
members class com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource$Factory {
<init>(com.google.android.exoplayer2.upstream.DataSource$Factory);
<init>(com.google.android.exoplayer2.upstream.DataSource$Factory);
** setStreamKeys(java.util.List);
com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource createMediaSource(android.net.Uri);
com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource createMediaSource(android.net.Uri);
}
}
...
...
library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java
View file @
35e030f5
...
@@ -1053,12 +1053,15 @@ import java.util.concurrent.atomic.AtomicBoolean;
...
@@ -1053,12 +1053,15 @@ import java.util.concurrent.atomic.AtomicBoolean;
&&
nextInfo
.
resolvedPeriodIndex
==
currentPeriodIndex
&&
nextInfo
.
resolvedPeriodIndex
==
currentPeriodIndex
&&
nextInfo
.
resolvedPeriodTimeUs
>
oldPeriodPositionUs
&&
nextInfo
.
resolvedPeriodTimeUs
>
oldPeriodPositionUs
&&
nextInfo
.
resolvedPeriodTimeUs
<=
newPeriodPositionUs
)
{
&&
nextInfo
.
resolvedPeriodTimeUs
<=
newPeriodPositionUs
)
{
try
{
sendMessageToTarget
(
nextInfo
.
message
);
sendMessageToTarget
(
nextInfo
.
message
);
}
finally
{
if
(
nextInfo
.
message
.
getDeleteAfterDelivery
()
||
nextInfo
.
message
.
isCanceled
())
{
if
(
nextInfo
.
message
.
getDeleteAfterDelivery
()
||
nextInfo
.
message
.
isCanceled
())
{
pendingMessages
.
remove
(
nextPendingMessageIndex
);
pendingMessages
.
remove
(
nextPendingMessageIndex
);
}
else
{
}
else
{
nextPendingMessageIndex
++;
nextPendingMessageIndex
++;
}
}
}
nextInfo
=
nextInfo
=
nextPendingMessageIndex
<
pendingMessages
.
size
()
nextPendingMessageIndex
<
pendingMessages
.
size
()
?
pendingMessages
.
get
(
nextPendingMessageIndex
)
?
pendingMessages
.
get
(
nextPendingMessageIndex
)
...
...
library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java
View file @
35e030f5
...
@@ -29,11 +29,11 @@ public final class ExoPlayerLibraryInfo {
...
@@ -29,11 +29,11 @@ public final class ExoPlayerLibraryInfo {
/** The version of the library expressed as a string, for example "1.2.3". */
/** 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.
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION_INT) or vice versa.
public
static
final
String
VERSION
=
"2.10.
0
"
;
public
static
final
String
VERSION
=
"2.10.
1
"
;
/** The version of the library expressed as {@code "ExoPlayerLib/" + VERSION}. */
/** The version of the library expressed as {@code "ExoPlayerLib/" + VERSION}. */
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION) or vice versa.
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION) or vice versa.
public
static
final
String
VERSION_SLASHY
=
"ExoPlayerLib/2.10.
0
"
;
public
static
final
String
VERSION_SLASHY
=
"ExoPlayerLib/2.10.
1
"
;
/**
/**
* The version of the library expressed as an integer, for example 1002003.
* The version of the library expressed as an integer, for example 1002003.
...
@@ -43,7 +43,7 @@ public final class ExoPlayerLibraryInfo {
...
@@ -43,7 +43,7 @@ public final class ExoPlayerLibraryInfo {
* integer version 123045006 (123-045-006).
* integer version 123045006 (123-045-006).
*/
*/
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION) or vice versa.
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION) or vice versa.
public
static
final
int
VERSION_INT
=
201000
0
;
public
static
final
int
VERSION_INT
=
201000
1
;
/**
/**
* Whether the library was compiled with {@link com.google.android.exoplayer2.util.Assertions}
* Whether the library was compiled with {@link com.google.android.exoplayer2.util.Assertions}
...
...
library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java
View file @
35e030f5
...
@@ -1231,7 +1231,7 @@ public class SimpleExoPlayer extends BasePlayer
...
@@ -1231,7 +1231,7 @@ public class SimpleExoPlayer extends BasePlayer
Log
.
w
(
Log
.
w
(
TAG
,
TAG
,
"Player is accessed on the wrong thread. See "
"Player is accessed on the wrong thread. See "
+
"https://exoplayer.dev/
faqs
.html#"
+
"https://exoplayer.dev/
troubleshooting
.html#"
+
"what-do-player-is-accessed-on-the-wrong-thread-warnings-mean"
,
+
"what-do-player-is-accessed-on-the-wrong-thread-warnings-mean"
,
hasNotifiedFullWrongThreadWarning
?
null
:
new
IllegalStateException
());
hasNotifiedFullWrongThreadWarning
?
null
:
new
IllegalStateException
());
hasNotifiedFullWrongThreadWarning
=
true
;
hasNotifiedFullWrongThreadWarning
=
true
;
...
...
library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsListener.java
View file @
35e030f5
...
@@ -59,7 +59,7 @@ public interface AnalyticsListener {
...
@@ -59,7 +59,7 @@ public interface AnalyticsListener {
public
final
Timeline
timeline
;
public
final
Timeline
timeline
;
/**
/**
* Window index in the {@
code
timeline} this event belongs to, or the prospective window index
* Window index in the {@
link #
timeline} this event belongs to, or the prospective window index
* if the timeline is not yet known and empty.
* if the timeline is not yet known and empty.
*/
*/
public
final
int
windowIndex
;
public
final
int
windowIndex
;
...
@@ -76,7 +76,7 @@ public interface AnalyticsListener {
...
@@ -76,7 +76,7 @@ public interface AnalyticsListener {
public
final
long
eventPlaybackPositionMs
;
public
final
long
eventPlaybackPositionMs
;
/**
/**
* Position in the current timeline window ({@
code timeline.getCurrentWindowIndex()}
or the
* Position in the current timeline window ({@
link Player#getCurrentWindowIndex()})
or the
* currently playing ad at the time of the event, in milliseconds.
* currently playing ad at the time of the event, in milliseconds.
*/
*/
public
final
long
currentPlaybackPositionMs
;
public
final
long
currentPlaybackPositionMs
;
...
@@ -91,15 +91,15 @@ public interface AnalyticsListener {
...
@@ -91,15 +91,15 @@ public interface AnalyticsListener {
* @param realtimeMs Elapsed real-time as returned by {@code SystemClock.elapsedRealtime()} at
* @param realtimeMs Elapsed real-time as returned by {@code SystemClock.elapsedRealtime()} at
* the time of the event, in milliseconds.
* the time of the event, in milliseconds.
* @param timeline Timeline at the time of the event.
* @param timeline Timeline at the time of the event.
* @param windowIndex Window index in the {@
code
timeline} this event belongs to, or the
* @param windowIndex Window index in the {@
link #
timeline} this event belongs to, or the
* prospective window index if the timeline is not yet known and empty.
* prospective window index if the timeline is not yet known and empty.
* @param mediaPeriodId Media period identifier for the media period this event belongs to, or
* @param mediaPeriodId Media period identifier for the media period this event belongs to, or
* {@code null} if the event is not associated with a specific media period.
* {@code null} if the event is not associated with a specific media period.
* @param eventPlaybackPositionMs Position in the window or ad this event belongs to at the time
* @param eventPlaybackPositionMs Position in the window or ad this event belongs to at the time
* of the event, in milliseconds.
* of the event, in milliseconds.
* @param currentPlaybackPositionMs Position in the current timeline window ({@
code
* @param currentPlaybackPositionMs Position in the current timeline window ({@
link
*
timeline.getCurrentWindowIndex()} or the currently playing ad at the time of the event,
*
Player#getCurrentWindowIndex()}) or the currently playing ad at the time of the event, in
*
in
milliseconds.
* milliseconds.
* @param totalBufferedDurationMs Total buffered duration from {@link
* @param totalBufferedDurationMs Total buffered duration from {@link
* #currentPlaybackPositionMs} at the time of the event, in milliseconds. This includes
* #currentPlaybackPositionMs} at the time of the event, in milliseconds. This includes
* pre-buffered data for subsequent ads and windows.
* pre-buffered data for subsequent ads and windows.
...
...
library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java
View file @
35e030f5
...
@@ -786,7 +786,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
...
@@ -786,7 +786,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
// Set codec configuration values.
// Set codec configuration values.
if
(
Util
.
SDK_INT
>=
23
)
{
if
(
Util
.
SDK_INT
>=
23
)
{
mediaFormat
.
setInteger
(
MediaFormat
.
KEY_PRIORITY
,
0
/* realtime priority */
);
mediaFormat
.
setInteger
(
MediaFormat
.
KEY_PRIORITY
,
0
/* realtime priority */
);
if
(
codecOperatingRate
!=
CODEC_OPERATING_RATE_UNSET
)
{
if
(
codecOperatingRate
!=
CODEC_OPERATING_RATE_UNSET
&&
!
deviceDoesntSupportOperatingRate
()
)
{
mediaFormat
.
setFloat
(
MediaFormat
.
KEY_OPERATING_RATE
,
codecOperatingRate
);
mediaFormat
.
setFloat
(
MediaFormat
.
KEY_OPERATING_RATE
,
codecOperatingRate
);
}
}
}
}
...
@@ -810,6 +810,17 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
...
@@ -810,6 +810,17 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
}
}
/**
/**
* Returns whether the device's decoders are known to not support setting the codec operating
* rate.
*
* <p>See <a href="https://github.com/google/ExoPlayer/issues/5821">GitHub issue #5821</a>.
*/
private
static
boolean
deviceDoesntSupportOperatingRate
()
{
return
Util
.
SDK_INT
==
23
&&
(
"ZTE B2017G"
.
equals
(
Util
.
MODEL
)
||
"AXON 7 mini"
.
equals
(
Util
.
MODEL
));
}
/**
* Returns whether the decoder is known to output six audio channels when provided with input with
* Returns whether the decoder is known to output six audio channels when provided with input with
* fewer than six channels.
* fewer than six channels.
* <p>
* <p>
...
...
library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java
View file @
35e030f5
...
@@ -60,7 +60,7 @@ import java.util.List;
...
@@ -60,7 +60,7 @@ import java.util.List;
* The threshold number of samples to trim from the start/end of an audio track when applying an
* The threshold number of samples to trim from the start/end of an audio track when applying an
* edit below which gapless info can be used (rather than removing samples from the sample table).
* edit below which gapless info can be used (rather than removing samples from the sample table).
*/
*/
private
static
final
int
MAX_GAPLESS_TRIM_SIZE_SAMPLES
=
3
;
private
static
final
int
MAX_GAPLESS_TRIM_SIZE_SAMPLES
=
4
;
/** The magic signature for an Opus Identification header, as defined in RFC-7845. */
/** The magic signature for an Opus Identification header, as defined in RFC-7845. */
private
static
final
byte
[]
opusMagic
=
Util
.
getUtf8Bytes
(
"OpusHead"
);
private
static
final
byte
[]
opusMagic
=
Util
.
getUtf8Bytes
(
"OpusHead"
);
...
...
library/core/src/main/java/com/google/android/exoplayer2/metadata/icy/IcyDecoder.java
View file @
35e030f5
...
@@ -31,7 +31,7 @@ public final class IcyDecoder implements MetadataDecoder {
...
@@ -31,7 +31,7 @@ public final class IcyDecoder implements MetadataDecoder {
private
static
final
String
TAG
=
"IcyDecoder"
;
private
static
final
String
TAG
=
"IcyDecoder"
;
private
static
final
Pattern
METADATA_ELEMENT
=
Pattern
.
compile
(
"(.+?)='(.
+?)';"
);
private
static
final
Pattern
METADATA_ELEMENT
=
Pattern
.
compile
(
"(.+?)='(.
*?)';"
,
Pattern
.
DOTALL
);
private
static
final
String
STREAM_KEY_NAME
=
"streamtitle"
;
private
static
final
String
STREAM_KEY_NAME
=
"streamtitle"
;
private
static
final
String
STREAM_KEY_URL
=
"streamurl"
;
private
static
final
String
STREAM_KEY_URL
=
"streamurl"
;
...
...
library/core/src/main/java/com/google/android/exoplayer2/offline/DefaultDownloadIndex.java
View file @
35e030f5
...
@@ -234,6 +234,19 @@ public final class DefaultDownloadIndex implements WritableDownloadIndex {
...
@@ -234,6 +234,19 @@ public final class DefaultDownloadIndex implements WritableDownloadIndex {
}
}
@Override
@Override
public
void
setStatesToRemoving
()
throws
DatabaseIOException
{
ensureInitialized
();
try
{
ContentValues
values
=
new
ContentValues
();
values
.
put
(
COLUMN_STATE
,
Download
.
STATE_REMOVING
);
SQLiteDatabase
writableDatabase
=
databaseProvider
.
getWritableDatabase
();
writableDatabase
.
update
(
tableName
,
values
,
/* whereClause= */
null
,
/* whereArgs= */
null
);
}
catch
(
SQLException
e
)
{
throw
new
DatabaseIOException
(
e
);
}
}
@Override
public
void
setStopReason
(
int
stopReason
)
throws
DatabaseIOException
{
public
void
setStopReason
(
int
stopReason
)
throws
DatabaseIOException
{
ensureInitialized
();
ensureInitialized
();
try
{
try
{
...
...
library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadHelper.java
View file @
35e030f5
...
@@ -20,7 +20,6 @@ import android.os.Handler;
...
@@ -20,7 +20,6 @@ import android.os.Handler;
import
android.os.HandlerThread
;
import
android.os.HandlerThread
;
import
android.os.Message
;
import
android.os.Message
;
import
androidx.annotation.Nullable
;
import
androidx.annotation.Nullable
;
import
android.util.Pair
;
import
android.util.SparseIntArray
;
import
android.util.SparseIntArray
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.ExoPlaybackException
;
import
com.google.android.exoplayer2.ExoPlaybackException
;
...
@@ -32,6 +31,7 @@ import com.google.android.exoplayer2.drm.FrameworkMediaCrypto;
...
@@ -32,6 +31,7 @@ import com.google.android.exoplayer2.drm.FrameworkMediaCrypto;
import
com.google.android.exoplayer2.source.MediaPeriod
;
import
com.google.android.exoplayer2.source.MediaPeriod
;
import
com.google.android.exoplayer2.source.MediaSource
;
import
com.google.android.exoplayer2.source.MediaSource
;
import
com.google.android.exoplayer2.source.MediaSource.MediaPeriodId
;
import
com.google.android.exoplayer2.source.MediaSource.MediaPeriodId
;
import
com.google.android.exoplayer2.source.ProgressiveMediaSource
;
import
com.google.android.exoplayer2.source.TrackGroup
;
import
com.google.android.exoplayer2.source.TrackGroup
;
import
com.google.android.exoplayer2.source.TrackGroupArray
;
import
com.google.android.exoplayer2.source.TrackGroupArray
;
import
com.google.android.exoplayer2.trackselection.BaseTrackSelection
;
import
com.google.android.exoplayer2.trackselection.BaseTrackSelection
;
...
@@ -44,6 +44,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
...
@@ -44,6 +44,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
import
com.google.android.exoplayer2.upstream.Allocator
;
import
com.google.android.exoplayer2.upstream.Allocator
;
import
com.google.android.exoplayer2.upstream.BandwidthMeter
;
import
com.google.android.exoplayer2.upstream.BandwidthMeter
;
import
com.google.android.exoplayer2.upstream.DataSource
;
import
com.google.android.exoplayer2.upstream.DataSource
;
import
com.google.android.exoplayer2.upstream.DataSource.Factory
;
import
com.google.android.exoplayer2.upstream.DefaultAllocator
;
import
com.google.android.exoplayer2.upstream.DefaultAllocator
;
import
com.google.android.exoplayer2.upstream.TransferListener
;
import
com.google.android.exoplayer2.upstream.TransferListener
;
import
com.google.android.exoplayer2.util.Assertions
;
import
com.google.android.exoplayer2.util.Assertions
;
...
@@ -106,30 +107,13 @@ public final class DownloadHelper {
...
@@ -106,30 +107,13 @@ public final class DownloadHelper {
void
onPrepareError
(
DownloadHelper
helper
,
IOException
e
);
void
onPrepareError
(
DownloadHelper
helper
,
IOException
e
);
}
}
@Nullable
private
static
final
Constructor
<?>
DASH_FACTORY_CONSTRUCTOR
;
private
static
final
MediaSourceFactory
DASH_FACTORY
=
@Nullable
private
static
final
Constructor
<?>
HLS_FACTORY_CONSTRUCTOR
;
getMediaSourceFactory
(
"com.google.android.exoplayer2.source.dash.DashMediaSource$Factory"
);
@Nullable
private
static
final
Constructor
<?>
SS_FACTORY_CONSTRUCTOR
;
private
static
final
MediaSourceFactory
SS_FACTORY
=
@Nullable
private
static
final
Method
DASH_FACTORY_CREATE_METHOD
;
getMediaSourceFactory
(
@Nullable
private
static
final
Method
HLS_FACTORY_CREATE_METHOD
;
@Nullable
private
static
final
Method
SS_FACTORY_CREATE_METHOD
;
static
{
Pair
<
@NullableType
Constructor
<?>,
@NullableType
Method
>
dashFactoryMethods
=
getMediaSourceFactoryMethods
(
"com.google.android.exoplayer2.source.dash.DashMediaSource$Factory"
);
DASH_FACTORY_CONSTRUCTOR
=
dashFactoryMethods
.
first
;
DASH_FACTORY_CREATE_METHOD
=
dashFactoryMethods
.
second
;
Pair
<
@NullableType
Constructor
<?>,
@NullableType
Method
>
hlsFactoryMethods
=
getMediaSourceFactoryMethods
(
"com.google.android.exoplayer2.source.hls.HlsMediaSource$Factory"
);
HLS_FACTORY_CONSTRUCTOR
=
hlsFactoryMethods
.
first
;
HLS_FACTORY_CREATE_METHOD
=
hlsFactoryMethods
.
second
;
Pair
<
@NullableType
Constructor
<?>,
@NullableType
Method
>
ssFactoryMethods
=
getMediaSourceFactoryMethods
(
"com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource$Factory"
);
"com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource$Factory"
);
SS_FACTORY_CONSTRUCTOR
=
ssFactoryMethods
.
first
;
private
static
final
MediaSourceFactory
HLS_FACTORY
=
SS_FACTORY_CREATE_METHOD
=
ssFactoryMethods
.
second
;
getMediaSourceFactory
(
"com.google.android.exoplayer2.source.hls.HlsMediaSource$Factory"
);
}
/**
/**
* Creates a {@link DownloadHelper} for progressive streams.
* Creates a {@link DownloadHelper} for progressive streams.
...
@@ -202,8 +186,7 @@ public final class DownloadHelper {
...
@@ -202,8 +186,7 @@ public final class DownloadHelper {
DownloadRequest
.
TYPE_DASH
,
DownloadRequest
.
TYPE_DASH
,
uri
,
uri
,
/* cacheKey= */
null
,
/* cacheKey= */
null
,
createMediaSource
(
DASH_FACTORY
.
createMediaSource
(
uri
,
dataSourceFactory
,
/* streamKeys= */
null
),
uri
,
dataSourceFactory
,
DASH_FACTORY_CONSTRUCTOR
,
DASH_FACTORY_CREATE_METHOD
),
trackSelectorParameters
,
trackSelectorParameters
,
Util
.
getRendererCapabilities
(
renderersFactory
,
drmSessionManager
));
Util
.
getRendererCapabilities
(
renderersFactory
,
drmSessionManager
));
}
}
...
@@ -252,8 +235,7 @@ public final class DownloadHelper {
...
@@ -252,8 +235,7 @@ public final class DownloadHelper {
DownloadRequest
.
TYPE_HLS
,
DownloadRequest
.
TYPE_HLS
,
uri
,
uri
,
/* cacheKey= */
null
,
/* cacheKey= */
null
,
createMediaSource
(
HLS_FACTORY
.
createMediaSource
(
uri
,
dataSourceFactory
,
/* streamKeys= */
null
),
uri
,
dataSourceFactory
,
HLS_FACTORY_CONSTRUCTOR
,
HLS_FACTORY_CREATE_METHOD
),
trackSelectorParameters
,
trackSelectorParameters
,
Util
.
getRendererCapabilities
(
renderersFactory
,
drmSessionManager
));
Util
.
getRendererCapabilities
(
renderersFactory
,
drmSessionManager
));
}
}
...
@@ -302,11 +284,42 @@ public final class DownloadHelper {
...
@@ -302,11 +284,42 @@ public final class DownloadHelper {
DownloadRequest
.
TYPE_SS
,
DownloadRequest
.
TYPE_SS
,
uri
,
uri
,
/* cacheKey= */
null
,
/* cacheKey= */
null
,
createMediaSource
(
uri
,
dataSourceFactory
,
SS_FACTORY_CONSTRUCTOR
,
SS_FACTORY_CREATE_METHOD
),
SS_FACTORY
.
createMediaSource
(
uri
,
dataSourceFactory
,
/* streamKeys= */
null
),
trackSelectorParameters
,
trackSelectorParameters
,
Util
.
getRendererCapabilities
(
renderersFactory
,
drmSessionManager
));
Util
.
getRendererCapabilities
(
renderersFactory
,
drmSessionManager
));
}
}
/**
* Utility method to create a MediaSource which only contains the tracks defined in {@code
* downloadRequest}.
*
* @param downloadRequest A {@link DownloadRequest}.
* @param dataSourceFactory A factory for {@link DataSource}s to read the media.
* @return A MediaSource which only contains the tracks defined in {@code downloadRequest}.
*/
public
static
MediaSource
createMediaSource
(
DownloadRequest
downloadRequest
,
DataSource
.
Factory
dataSourceFactory
)
{
MediaSourceFactory
factory
;
switch
(
downloadRequest
.
type
)
{
case
DownloadRequest
.
TYPE_DASH
:
factory
=
DASH_FACTORY
;
break
;
case
DownloadRequest
.
TYPE_SS
:
factory
=
SS_FACTORY
;
break
;
case
DownloadRequest
.
TYPE_HLS
:
factory
=
HLS_FACTORY
;
break
;
case
DownloadRequest
.
TYPE_PROGRESSIVE
:
return
new
ProgressiveMediaSource
.
Factory
(
dataSourceFactory
)
.
createMediaSource
(
downloadRequest
.
uri
);
default
:
throw
new
IllegalStateException
(
"Unsupported type: "
+
downloadRequest
.
type
);
}
return
factory
.
createMediaSource
(
downloadRequest
.
uri
,
dataSourceFactory
,
downloadRequest
.
streamKeys
);
}
private
final
String
downloadType
;
private
final
String
downloadType
;
private
final
Uri
uri
;
private
final
Uri
uri
;
@Nullable
private
final
String
cacheKey
;
@Nullable
private
final
String
cacheKey
;
...
@@ -739,37 +752,56 @@ public final class DownloadHelper {
...
@@ -739,37 +752,56 @@ public final class DownloadHelper {
}
}
}
}
private
static
Pair
<
@NullableType
Constructor
<?>,
@NullableType
Method
>
private
static
MediaSourceFactory
getMediaSourceFactory
(
String
className
)
{
getMediaSourceFactoryMethods
(
String
className
)
{
Constructor
<?>
constructor
=
null
;
Constructor
<?>
constructor
=
null
;
Method
setStreamKeysMethod
=
null
;
Method
createMethod
=
null
;
Method
createMethod
=
null
;
try
{
try
{
// LINT.IfChange
// LINT.IfChange
Class
<?>
factoryClazz
=
Class
.
forName
(
className
);
Class
<?>
factoryClazz
=
Class
.
forName
(
className
);
constructor
=
factoryClazz
.
getConstructor
(
DataSource
.
Factory
.
class
);
constructor
=
factoryClazz
.
getConstructor
(
Factory
.
class
);
setStreamKeysMethod
=
factoryClazz
.
getMethod
(
"setStreamKeys"
,
List
.
class
);
createMethod
=
factoryClazz
.
getMethod
(
"createMediaSource"
,
Uri
.
class
);
createMethod
=
factoryClazz
.
getMethod
(
"createMediaSource"
,
Uri
.
class
);
// LINT.ThenChange(../../../../../../../../proguard-rules.txt)
// LINT.ThenChange(../../../../../../../../proguard-rules.txt)
}
catch
(
Exception
e
)
{
}
catch
(
ClassNotFound
Exception
e
)
{
// Expected if the app was built without the respective module.
// Expected if the app was built without the respective module.
}
catch
(
NoSuchMethodException
|
SecurityException
e
)
{
// Something is wrong with the library or the proguard configuration.
throw
new
IllegalStateException
(
e
);
}
}
return
Pair
.
create
(
constructor
,
createMethod
);
return
new
MediaSourceFactory
(
constructor
,
setStreamKeysMethod
,
createMethod
);
}
}
private
static
MediaSource
createMediaSource
(
private
static
final
class
MediaSourceFactory
{
Uri
uri
,
@Nullable
private
final
Constructor
<?>
constructor
;
DataSource
.
Factory
dataSourceFactory
,
@Nullable
private
final
Method
setStreamKeysMethod
;
@Nullable
Constructor
<?>
factoryConstructor
,
@Nullable
private
final
Method
createMethod
;
@Nullable
Method
createMediaSourceMethod
)
{
if
(
factoryConstructor
==
null
||
createMediaSourceMethod
==
null
)
{
public
MediaSourceFactory
(
@Nullable
Constructor
<?>
constructor
,
@Nullable
Method
setStreamKeysMethod
,
@Nullable
Method
createMethod
)
{
this
.
constructor
=
constructor
;
this
.
setStreamKeysMethod
=
setStreamKeysMethod
;
this
.
createMethod
=
createMethod
;
}
private
MediaSource
createMediaSource
(
Uri
uri
,
Factory
dataSourceFactory
,
@Nullable
List
<
StreamKey
>
streamKeys
)
{
if
(
constructor
==
null
||
setStreamKeysMethod
==
null
||
createMethod
==
null
)
{
throw
new
IllegalStateException
(
"Module missing to create media source."
);
throw
new
IllegalStateException
(
"Module missing to create media source."
);
}
}
try
{
try
{
Object
factory
=
factoryConstructor
.
newInstance
(
dataSourceFactory
);
Object
factory
=
constructor
.
newInstance
(
dataSourceFactory
);
return
(
MediaSource
)
Assertions
.
checkNotNull
(
createMediaSourceMethod
.
invoke
(
factory
,
uri
));
if
(
streamKeys
!=
null
)
{
setStreamKeysMethod
.
invoke
(
factory
,
streamKeys
);
}
return
(
MediaSource
)
Assertions
.
checkNotNull
(
createMethod
.
invoke
(
factory
,
uri
));
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
throw
new
IllegalStateException
(
"Failed to instantiate media source."
,
e
);
throw
new
IllegalStateException
(
"Failed to instantiate media source."
,
e
);
}
}
}
}
}
private
static
final
class
MediaPreparer
private
static
final
class
MediaPreparer
implements
MediaSource
.
SourceInfoRefreshListener
,
MediaPeriod
.
Callback
,
Handler
.
Callback
{
implements
MediaSource
.
SourceInfoRefreshListener
,
MediaPeriod
.
Callback
,
Handler
.
Callback
{
...
...
library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadManager.java
View file @
35e030f5
...
@@ -133,10 +133,11 @@ public final class DownloadManager {
...
@@ -133,10 +133,11 @@ public final class DownloadManager {
private
static
final
int
MSG_SET_MIN_RETRY_COUNT
=
5
;
private
static
final
int
MSG_SET_MIN_RETRY_COUNT
=
5
;
private
static
final
int
MSG_ADD_DOWNLOAD
=
6
;
private
static
final
int
MSG_ADD_DOWNLOAD
=
6
;
private
static
final
int
MSG_REMOVE_DOWNLOAD
=
7
;
private
static
final
int
MSG_REMOVE_DOWNLOAD
=
7
;
private
static
final
int
MSG_TASK_STOPPED
=
8
;
private
static
final
int
MSG_REMOVE_ALL_DOWNLOADS
=
8
;
private
static
final
int
MSG_CONTENT_LENGTH_CHANGED
=
9
;
private
static
final
int
MSG_TASK_STOPPED
=
9
;
private
static
final
int
MSG_UPDATE_PROGRESS
=
10
;
private
static
final
int
MSG_CONTENT_LENGTH_CHANGED
=
10
;
private
static
final
int
MSG_RELEASE
=
11
;
private
static
final
int
MSG_UPDATE_PROGRESS
=
11
;
private
static
final
int
MSG_RELEASE
=
12
;
private
static
final
String
TAG
=
"DownloadManager"
;
private
static
final
String
TAG
=
"DownloadManager"
;
...
@@ -446,6 +447,12 @@ public final class DownloadManager {
...
@@ -446,6 +447,12 @@ public final class DownloadManager {
internalHandler
.
obtainMessage
(
MSG_REMOVE_DOWNLOAD
,
id
).
sendToTarget
();
internalHandler
.
obtainMessage
(
MSG_REMOVE_DOWNLOAD
,
id
).
sendToTarget
();
}
}
/** Cancels all pending downloads and removes all downloaded data. */
public
void
removeAllDownloads
()
{
pendingMessages
++;
internalHandler
.
obtainMessage
(
MSG_REMOVE_ALL_DOWNLOADS
).
sendToTarget
();
}
/**
/**
* Stops the downloads and releases resources. Waits until the downloads are persisted to the
* Stops the downloads and releases resources. Waits until the downloads are persisted to the
* download index. The manager must not be accessed after this method has been called.
* download index. The manager must not be accessed after this method has been called.
...
@@ -652,6 +659,9 @@ public final class DownloadManager {
...
@@ -652,6 +659,9 @@ public final class DownloadManager {
id
=
(
String
)
message
.
obj
;
id
=
(
String
)
message
.
obj
;
removeDownload
(
id
);
removeDownload
(
id
);
break
;
break
;
case
MSG_REMOVE_ALL_DOWNLOADS:
removeAllDownloads
();
break
;
case
MSG_TASK_STOPPED:
case
MSG_TASK_STOPPED:
Task
task
=
(
Task
)
message
.
obj
;
Task
task
=
(
Task
)
message
.
obj
;
onTaskStopped
(
task
);
onTaskStopped
(
task
);
...
@@ -797,6 +807,36 @@ public final class DownloadManager {
...
@@ -797,6 +807,36 @@ public final class DownloadManager {
syncTasks
();
syncTasks
();
}
}
private
void
removeAllDownloads
()
{
List
<
Download
>
terminalDownloads
=
new
ArrayList
<>();
try
(
DownloadCursor
cursor
=
downloadIndex
.
getDownloads
(
STATE_COMPLETED
,
STATE_FAILED
))
{
while
(
cursor
.
moveToNext
())
{
terminalDownloads
.
add
(
cursor
.
getDownload
());
}
}
catch
(
IOException
e
)
{
Log
.
e
(
TAG
,
"Failed to load downloads."
);
}
for
(
int
i
=
0
;
i
<
downloads
.
size
();
i
++)
{
downloads
.
set
(
i
,
copyDownloadWithState
(
downloads
.
get
(
i
),
STATE_REMOVING
));
}
for
(
int
i
=
0
;
i
<
terminalDownloads
.
size
();
i
++)
{
downloads
.
add
(
copyDownloadWithState
(
terminalDownloads
.
get
(
i
),
STATE_REMOVING
));
}
Collections
.
sort
(
downloads
,
InternalHandler:
:
compareStartTimes
);
try
{
downloadIndex
.
setStatesToRemoving
();
}
catch
(
IOException
e
)
{
Log
.
e
(
TAG
,
"Failed to update index."
,
e
);
}
ArrayList
<
Download
>
updateList
=
new
ArrayList
<>(
downloads
);
for
(
int
i
=
0
;
i
<
downloads
.
size
();
i
++)
{
DownloadUpdate
update
=
new
DownloadUpdate
(
downloads
.
get
(
i
),
/* isRemove= */
false
,
updateList
);
mainHandler
.
obtainMessage
(
MSG_DOWNLOAD_UPDATE
,
update
).
sendToTarget
();
}
syncTasks
();
}
private
void
release
()
{
private
void
release
()
{
for
(
Task
task
:
activeTasks
.
values
())
{
for
(
Task
task
:
activeTasks
.
values
())
{
task
.
cancel
(
/* released= */
true
);
task
.
cancel
(
/* released= */
true
);
...
@@ -1057,16 +1097,7 @@ public final class DownloadManager {
...
@@ -1057,16 +1097,7 @@ public final class DownloadManager {
// to set STATE_STOPPED either, because it doesn't have a stopReason argument.
// to set STATE_STOPPED either, because it doesn't have a stopReason argument.
Assertions
.
checkState
(
Assertions
.
checkState
(
state
!=
STATE_COMPLETED
&&
state
!=
STATE_FAILED
&&
state
!=
STATE_STOPPED
);
state
!=
STATE_COMPLETED
&&
state
!=
STATE_FAILED
&&
state
!=
STATE_STOPPED
);
return
putDownload
(
return
putDownload
(
copyDownloadWithState
(
download
,
state
));
new
Download
(
download
.
request
,
state
,
download
.
startTimeMs
,
/* updateTimeMs= */
System
.
currentTimeMillis
(),
download
.
contentLength
,
/* stopReason= */
0
,
FAILURE_REASON_NONE
,
download
.
progress
));
}
}
private
Download
putDownload
(
Download
download
)
{
private
Download
putDownload
(
Download
download
)
{
...
@@ -1120,6 +1151,18 @@ public final class DownloadManager {
...
@@ -1120,6 +1151,18 @@ public final class DownloadManager {
return
C
.
INDEX_UNSET
;
return
C
.
INDEX_UNSET
;
}
}
private
static
Download
copyDownloadWithState
(
Download
download
,
@Download
.
State
int
state
)
{
return
new
Download
(
download
.
request
,
state
,
download
.
startTimeMs
,
/* updateTimeMs= */
System
.
currentTimeMillis
(),
download
.
contentLength
,
/* stopReason= */
0
,
FAILURE_REASON_NONE
,
download
.
progress
);
}
private
static
int
compareStartTimes
(
Download
first
,
Download
second
)
{
private
static
int
compareStartTimes
(
Download
first
,
Download
second
)
{
return
Util
.
compareLong
(
first
.
startTimeMs
,
second
.
startTimeMs
);
return
Util
.
compareLong
(
first
.
startTimeMs
,
second
.
startTimeMs
);
}
}
...
...
library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadService.java
View file @
35e030f5
...
@@ -78,6 +78,16 @@ public abstract class DownloadService extends Service {
...
@@ -78,6 +78,16 @@ public abstract class DownloadService extends Service {
"com.google.android.exoplayer.downloadService.action.REMOVE_DOWNLOAD"
;
"com.google.android.exoplayer.downloadService.action.REMOVE_DOWNLOAD"
;
/**
/**
* Removes all downloads. Extras:
*
* <ul>
* <li>{@link #KEY_FOREGROUND} - See {@link #KEY_FOREGROUND}.
* </ul>
*/
public
static
final
String
ACTION_REMOVE_ALL_DOWNLOADS
=
"com.google.android.exoplayer.downloadService.action.REMOVE_ALL_DOWNLOADS"
;
/**
* Resumes all downloads except those that have a non-zero {@link Download#stopReason}. Extras:
* Resumes all downloads except those that have a non-zero {@link Download#stopReason}. Extras:
*
*
* <ul>
* <ul>
...
@@ -297,6 +307,19 @@ public abstract class DownloadService extends Service {
...
@@ -297,6 +307,19 @@ public abstract class DownloadService extends Service {
}
}
/**
/**
* Builds an {@link Intent} for removing all downloads.
*
* @param context A {@link Context}.
* @param clazz The concrete download service being targeted by the intent.
* @param foreground Whether this intent will be used to start the service in the foreground.
* @return The created intent.
*/
public
static
Intent
buildRemoveAllDownloadsIntent
(
Context
context
,
Class
<?
extends
DownloadService
>
clazz
,
boolean
foreground
)
{
return
getIntent
(
context
,
clazz
,
ACTION_REMOVE_ALL_DOWNLOADS
,
foreground
);
}
/**
* Builds an {@link Intent} for resuming all downloads.
* Builds an {@link Intent} for resuming all downloads.
*
*
* @param context A {@link Context}.
* @param context A {@link Context}.
...
@@ -415,6 +438,19 @@ public abstract class DownloadService extends Service {
...
@@ -415,6 +438,19 @@ public abstract class DownloadService extends Service {
}
}
/**
/**
* Starts the service if not started already and removes all downloads.
*
* @param context A {@link Context}.
* @param clazz The concrete download service to be started.
* @param foreground Whether the service is started in the foreground.
*/
public
static
void
sendRemoveAllDownloads
(
Context
context
,
Class
<?
extends
DownloadService
>
clazz
,
boolean
foreground
)
{
Intent
intent
=
buildRemoveAllDownloadsIntent
(
context
,
clazz
,
foreground
);
startService
(
context
,
intent
,
foreground
);
}
/**
* Starts the service if not started already and resumes all downloads.
* Starts the service if not started already and resumes all downloads.
*
*
* @param context A {@link Context}.
* @param context A {@link Context}.
...
@@ -560,6 +596,9 @@ public abstract class DownloadService extends Service {
...
@@ -560,6 +596,9 @@ public abstract class DownloadService extends Service {
downloadManager
.
removeDownload
(
contentId
);
downloadManager
.
removeDownload
(
contentId
);
}
}
break
;
break
;
case
ACTION_REMOVE_ALL_DOWNLOADS:
downloadManager
.
removeAllDownloads
();
break
;
case
ACTION_RESUME_DOWNLOADS:
case
ACTION_RESUME_DOWNLOADS:
downloadManager
.
resumeDownloads
();
downloadManager
.
resumeDownloads
();
break
;
break
;
...
...
library/core/src/main/java/com/google/android/exoplayer2/offline/WritableDownloadIndex.java
View file @
35e030f5
...
@@ -45,6 +45,13 @@ public interface WritableDownloadIndex extends DownloadIndex {
...
@@ -45,6 +45,13 @@ public interface WritableDownloadIndex extends DownloadIndex {
void
setDownloadingStatesToQueued
()
throws
IOException
;
void
setDownloadingStatesToQueued
()
throws
IOException
;
/**
/**
* Sets all states to {@link Download#STATE_REMOVING}.
*
* @throws IOException If an error occurs updating the state.
*/
void
setStatesToRemoving
()
throws
IOException
;
/**
* Sets the stop reason of the downloads in a terminal state ({@link Download#STATE_COMPLETED},
* Sets the stop reason of the downloads in a terminal state ({@link Download#STATE_COMPLETED},
* {@link Download#STATE_FAILED}).
* {@link Download#STATE_FAILED}).
*
*
...
...
library/core/src/main/java/com/google/android/exoplayer2/scheduler/PlatformScheduler.java
View file @
35e030f5
...
@@ -36,7 +36,7 @@ import com.google.android.exoplayer2.util.Util;
...
@@ -36,7 +36,7 @@ import com.google.android.exoplayer2.util.Util;
* <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
* <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
* <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
* <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
*
*
* <service android:name="com.google.android.exoplayer2.
util.
scheduler.PlatformScheduler$PlatformSchedulerService"
* <service android:name="com.google.android.exoplayer2.scheduler.PlatformScheduler$PlatformSchedulerService"
* android:permission="android.permission.BIND_JOB_SERVICE"
* android:permission="android.permission.BIND_JOB_SERVICE"
* android:exported="true"/>
* android:exported="true"/>
* }</pre>
* }</pre>
...
...
library/core/src/main/java/com/google/android/exoplayer2/text/dvb/DvbParser.java
View file @
35e030f5
...
@@ -21,7 +21,6 @@ import android.graphics.Color;
...
@@ -21,7 +21,6 @@ import android.graphics.Color;
import
android.graphics.Paint
;
import
android.graphics.Paint
;
import
android.graphics.PorterDuff
;
import
android.graphics.PorterDuff
;
import
android.graphics.PorterDuffXfermode
;
import
android.graphics.PorterDuffXfermode
;
import
android.graphics.Region
;
import
android.util.SparseArray
;
import
android.util.SparseArray
;
import
com.google.android.exoplayer2.text.Cue
;
import
com.google.android.exoplayer2.text.Cue
;
import
com.google.android.exoplayer2.util.Log
;
import
com.google.android.exoplayer2.util.Log
;
...
@@ -150,6 +149,8 @@ import java.util.List;
...
@@ -150,6 +149,8 @@ import java.util.List;
List
<
Cue
>
cues
=
new
ArrayList
<>();
List
<
Cue
>
cues
=
new
ArrayList
<>();
SparseArray
<
PageRegion
>
pageRegions
=
subtitleService
.
pageComposition
.
regions
;
SparseArray
<
PageRegion
>
pageRegions
=
subtitleService
.
pageComposition
.
regions
;
for
(
int
i
=
0
;
i
<
pageRegions
.
size
();
i
++)
{
for
(
int
i
=
0
;
i
<
pageRegions
.
size
();
i
++)
{
// Save clean clipping state.
canvas
.
save
();
PageRegion
pageRegion
=
pageRegions
.
valueAt
(
i
);
PageRegion
pageRegion
=
pageRegions
.
valueAt
(
i
);
int
regionId
=
pageRegions
.
keyAt
(
i
);
int
regionId
=
pageRegions
.
keyAt
(
i
);
RegionComposition
regionComposition
=
subtitleService
.
regions
.
get
(
regionId
);
RegionComposition
regionComposition
=
subtitleService
.
regions
.
get
(
regionId
);
...
@@ -163,9 +164,7 @@ import java.util.List;
...
@@ -163,9 +164,7 @@ import java.util.List;
displayDefinition
.
horizontalPositionMaximum
);
displayDefinition
.
horizontalPositionMaximum
);
int
clipBottom
=
Math
.
min
(
baseVerticalAddress
+
regionComposition
.
height
,
int
clipBottom
=
Math
.
min
(
baseVerticalAddress
+
regionComposition
.
height
,
displayDefinition
.
verticalPositionMaximum
);
displayDefinition
.
verticalPositionMaximum
);
canvas
.
clipRect
(
baseHorizontalAddress
,
baseVerticalAddress
,
clipRight
,
clipBottom
,
canvas
.
clipRect
(
baseHorizontalAddress
,
baseVerticalAddress
,
clipRight
,
clipBottom
);
Region
.
Op
.
REPLACE
);
ClutDefinition
clutDefinition
=
subtitleService
.
cluts
.
get
(
regionComposition
.
clutId
);
ClutDefinition
clutDefinition
=
subtitleService
.
cluts
.
get
(
regionComposition
.
clutId
);
if
(
clutDefinition
==
null
)
{
if
(
clutDefinition
==
null
)
{
clutDefinition
=
subtitleService
.
ancillaryCluts
.
get
(
regionComposition
.
clutId
);
clutDefinition
=
subtitleService
.
ancillaryCluts
.
get
(
regionComposition
.
clutId
);
...
@@ -214,9 +213,11 @@ import java.util.List;
...
@@ -214,9 +213,11 @@ import java.util.List;
(
float
)
regionComposition
.
height
/
displayDefinition
.
height
));
(
float
)
regionComposition
.
height
/
displayDefinition
.
height
));
canvas
.
drawColor
(
Color
.
TRANSPARENT
,
PorterDuff
.
Mode
.
CLEAR
);
canvas
.
drawColor
(
Color
.
TRANSPARENT
,
PorterDuff
.
Mode
.
CLEAR
);
// Restore clean clipping state.
canvas
.
restore
();
}
}
return
cues
;
return
Collections
.
unmodifiableList
(
cues
)
;
}
}
// Static parsing.
// Static parsing.
...
...
library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultHttpDataSource.java
View file @
35e030f5
...
@@ -89,6 +89,11 @@ public class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou
...
@@ -89,6 +89,11 @@ public class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou
private
long
bytesSkipped
;
private
long
bytesSkipped
;
private
long
bytesRead
;
private
long
bytesRead
;
/** @param userAgent The User-Agent string that should be used. */
public
DefaultHttpDataSource
(
String
userAgent
)
{
this
(
userAgent
,
/* contentTypePredicate= */
null
);
}
/**
/**
* @param userAgent The User-Agent string that should be used.
* @param userAgent The User-Agent string that should be used.
* @param contentTypePredicate An optional {@link Predicate}. If a content type is rejected by the
* @param contentTypePredicate An optional {@link Predicate}. If a content type is rejected by the
...
...
library/core/src/test/java/com/google/android/exoplayer2/metadata/icy/IcyDecoderTest.java
View file @
35e030f5
...
@@ -49,6 +49,17 @@ public final class IcyDecoderTest {
...
@@ -49,6 +49,17 @@ public final class IcyDecoderTest {
}
}
@Test
@Test
public
void
decode_emptyTitle
()
{
IcyDecoder
decoder
=
new
IcyDecoder
();
Metadata
metadata
=
decoder
.
decode
(
"StreamTitle='';StreamURL='test_url';"
);
assertThat
(
metadata
.
length
()).
isEqualTo
(
1
);
IcyInfo
streamInfo
=
(
IcyInfo
)
metadata
.
get
(
0
);
assertThat
(
streamInfo
.
title
).
isEmpty
();
assertThat
(
streamInfo
.
url
).
isEqualTo
(
"test_url"
);
}
@Test
public
void
decode_semiColonInTitle
()
{
public
void
decode_semiColonInTitle
()
{
IcyDecoder
decoder
=
new
IcyDecoder
();
IcyDecoder
decoder
=
new
IcyDecoder
();
Metadata
metadata
=
decoder
.
decode
(
"StreamTitle='test; title';StreamURL='test_url';"
);
Metadata
metadata
=
decoder
.
decode
(
"StreamTitle='test; title';StreamURL='test_url';"
);
...
@@ -71,6 +82,17 @@ public final class IcyDecoderTest {
...
@@ -71,6 +82,17 @@ public final class IcyDecoderTest {
}
}
@Test
@Test
public
void
decode_lineTerminatorInTitle
()
{
IcyDecoder
decoder
=
new
IcyDecoder
();
Metadata
metadata
=
decoder
.
decode
(
"StreamTitle='test\r\ntitle';StreamURL='test_url';"
);
assertThat
(
metadata
.
length
()).
isEqualTo
(
1
);
IcyInfo
streamInfo
=
(
IcyInfo
)
metadata
.
get
(
0
);
assertThat
(
streamInfo
.
title
).
isEqualTo
(
"test\r\ntitle"
);
assertThat
(
streamInfo
.
url
).
isEqualTo
(
"test_url"
);
}
@Test
public
void
decode_notIcy
()
{
public
void
decode_notIcy
()
{
IcyDecoder
decoder
=
new
IcyDecoder
();
IcyDecoder
decoder
=
new
IcyDecoder
();
Metadata
metadata
=
decoder
.
decode
(
"NotIcyData"
);
Metadata
metadata
=
decoder
.
decode
(
"NotIcyData"
);
...
...
library/core/src/test/java/com/google/android/exoplayer2/offline/DownloadManagerTest.java
View file @
35e030f5
...
@@ -244,6 +244,27 @@ public class DownloadManagerTest {
...
@@ -244,6 +244,27 @@ public class DownloadManagerTest {
}
}
@Test
@Test
public
void
removeAllDownloads_removesAllDownloads
()
throws
Throwable
{
// Finish one download and keep one running.
DownloadRunner
runner1
=
new
DownloadRunner
(
uri1
);
DownloadRunner
runner2
=
new
DownloadRunner
(
uri2
);
runner1
.
postDownloadRequest
();
runner1
.
getDownloader
(
0
).
unblock
();
downloadManagerListener
.
blockUntilTasksCompleteAndThrowAnyDownloadError
();
runner2
.
postDownloadRequest
();
runner1
.
postRemoveAllRequest
();
runner1
.
getDownloader
(
1
).
unblock
();
runner2
.
getDownloader
(
1
).
unblock
();
downloadManagerListener
.
blockUntilTasksCompleteAndThrowAnyDownloadError
();
runner1
.
getTask
().
assertRemoved
();
runner2
.
getTask
().
assertRemoved
();
assertThat
(
downloadManager
.
getCurrentDownloads
()).
isEmpty
();
assertThat
(
downloadIndex
.
getDownloads
().
getCount
()).
isEqualTo
(
0
);
}
@Test
public
void
differentDownloadRequestsMerged
()
throws
Throwable
{
public
void
differentDownloadRequestsMerged
()
throws
Throwable
{
DownloadRunner
runner
=
new
DownloadRunner
(
uri1
);
DownloadRunner
runner
=
new
DownloadRunner
(
uri1
);
FakeDownloader
downloader1
=
runner
.
getDownloader
(
0
);
FakeDownloader
downloader1
=
runner
.
getDownloader
(
0
);
...
@@ -605,6 +626,11 @@ public class DownloadManagerTest {
...
@@ -605,6 +626,11 @@ public class DownloadManagerTest {
return
this
;
return
this
;
}
}
private
DownloadRunner
postRemoveAllRequest
()
{
runOnMainThread
(()
->
downloadManager
.
removeAllDownloads
());
return
this
;
}
private
DownloadRunner
postDownloadRequest
(
StreamKey
...
keys
)
{
private
DownloadRunner
postDownloadRequest
(
StreamKey
...
keys
)
{
DownloadRequest
downloadRequest
=
DownloadRequest
downloadRequest
=
new
DownloadRequest
(
new
DownloadRequest
(
...
...
library/dash/README.md
View file @
35e030f5
...
@@ -6,7 +6,9 @@ play DASH content, instantiate a `DashMediaSource` and pass it to
...
@@ -6,7 +6,9 @@ play DASH content, instantiate a `DashMediaSource` and pass it to
## Links ##
## Links ##
*
[
Developer Guide
][]
.
*
[
Javadoc
][]
: Classes matching
`com.google.android.exoplayer2.source.dash.*`
*
[
Javadoc
][]
: Classes matching
`com.google.android.exoplayer2.source.dash.*`
belong to this module.
belong to this module.
[
Developer Guide
]:
https://exoplayer.dev/dash.html
[
Javadoc
]:
https://exoplayer.dev/doc/reference/index.html
[
Javadoc
]:
https://exoplayer.dev/doc/reference/index.html
library/hls/README.md
View file @
35e030f5
...
@@ -5,7 +5,9 @@ instantiate a `HlsMediaSource` and pass it to `ExoPlayer.prepare`.
...
@@ -5,7 +5,9 @@ instantiate a `HlsMediaSource` and pass it to `ExoPlayer.prepare`.
## Links ##
## Links ##
*
[
Developer Guide
][]
.
*
[
Javadoc
][]
: Classes matching
`com.google.android.exoplayer2.source.hls.*`
*
[
Javadoc
][]
: Classes matching
`com.google.android.exoplayer2.source.hls.*`
belong to this module.
belong to this module.
[
Developer Guide
]:
https://exoplayer.dev/hls.html
[
Javadoc
]:
https://exoplayer.dev/doc/reference/index.html
[
Javadoc
]:
https://exoplayer.dev/doc/reference/index.html
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java
View file @
35e030f5
...
@@ -802,7 +802,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
...
@@ -802,7 +802,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
if
(
isPrimaryTrackInVariant
)
{
if
(
isPrimaryTrackInVariant
)
{
channelCount
=
variantFormat
.
channelCount
;
channelCount
=
variantFormat
.
channelCount
;
selectionFlags
=
variantFormat
.
selectionFlags
;
selectionFlags
=
variantFormat
.
selectionFlags
;
roleFlags
=
mediaTag
Format
.
roleFlags
;
roleFlags
=
variant
Format
.
roleFlags
;
language
=
variantFormat
.
language
;
language
=
variantFormat
.
language
;
label
=
variantFormat
.
label
;
label
=
variantFormat
.
label
;
}
}
...
...
library/smoothstreaming/README.md
View file @
35e030f5
...
@@ -5,8 +5,10 @@ instantiate a `SsMediaSource` and pass it to `ExoPlayer.prepare`.
...
@@ -5,8 +5,10 @@ instantiate a `SsMediaSource` and pass it to `ExoPlayer.prepare`.
## Links ##
## Links ##
*
[
Developer Guide
][]
.
*
[
Javadoc
][]
: Classes matching
*
[
Javadoc
][]
: Classes matching
`com.google.android.exoplayer2.source.smoothstreaming.*`
belong to this
`com.google.android.exoplayer2.source.smoothstreaming.*`
belong to this
module.
module.
[
Developer Guide
]:
https://exoplayer.dev/smoothstreaming.html
[
Javadoc
]:
https://exoplayer.dev/doc/reference/index.html
[
Javadoc
]:
https://exoplayer.dev/doc/reference/index.html
library/ui/README.md
View file @
35e030f5
...
@@ -4,7 +4,9 @@ Provides UI components and resources for use with ExoPlayer.
...
@@ -4,7 +4,9 @@ Provides UI components and resources for use with ExoPlayer.
## Links ##
## Links ##
*
[
Developer Guide
][]
.
*
[
Javadoc
][]
: Classes matching
`com.google.android.exoplayer2.ui.*`
*
[
Javadoc
][]
: Classes matching
`com.google.android.exoplayer2.ui.*`
belong to this module.
belong to this module.
[
Developer Guide
]:
https://exoplayer.dev/ui-components.html
[
Javadoc
]:
https://exoplayer.dev/doc/reference/index.html
[
Javadoc
]:
https://exoplayer.dev/doc/reference/index.html
testutils_robolectric/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaChunk.java
View file @
35e030f5
...
@@ -27,7 +27,7 @@ import java.io.IOException;
...
@@ -27,7 +27,7 @@ import java.io.IOException;
/** Fake {@link MediaChunk}. */
/** Fake {@link MediaChunk}. */
public
final
class
FakeMediaChunk
extends
MediaChunk
{
public
final
class
FakeMediaChunk
extends
MediaChunk
{
private
static
final
DataSource
DATA_SOURCE
=
new
DefaultHttpDataSource
(
"TEST_AGENT"
,
null
);
private
static
final
DataSource
DATA_SOURCE
=
new
DefaultHttpDataSource
(
"TEST_AGENT"
);
public
FakeMediaChunk
(
Format
trackFormat
,
long
startTimeUs
,
long
endTimeUs
)
{
public
FakeMediaChunk
(
Format
trackFormat
,
long
startTimeUs
,
long
endTimeUs
)
{
this
(
new
DataSpec
(
Uri
.
EMPTY
),
trackFormat
,
startTimeUs
,
endTimeUs
);
this
(
new
DataSpec
(
Uri
.
EMPTY
),
trackFormat
,
startTimeUs
,
endTimeUs
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment