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
246d4644
authored
Dec 06, 2018
by
ybai001
Committed by
GitHub
Dec 06, 2018
Browse files
Options
_('Browse Files')
Download
Plain Diff
Merge pull request #2 from google/dev-v2
Pull from google/ExoPlayer dev-v2
parents
7a924d64
556dd7e9
Hide whitespace changes
Inline
Side-by-side
Showing
35 changed files
with
404 additions
and
279 deletions
RELEASENOTES.md
extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsMediaSource.java
library/core/src/main/java/com/google/android/exoplayer2/audio/AudioRendererEventListener.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/ProgressiveDownloadHelper.java
library/core/src/main/java/com/google/android/exoplayer2/offline/SegmentDownloader.java
library/core/src/main/java/com/google/android/exoplayer2/source/ClippingMediaSource.java
library/core/src/main/java/com/google/android/exoplayer2/source/ConcatenatingMediaSource.java
library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java
library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaSource.java
library/core/src/main/java/com/google/android/exoplayer2/source/LoopingMediaSource.java
library/core/src/main/java/com/google/android/exoplayer2/source/MediaSource.java
library/core/src/main/java/com/google/android/exoplayer2/source/MergingMediaSource.java
library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaSource.java
library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdsMediaSource.java
library/core/src/main/java/com/google/android/exoplayer2/text/cea/Cea608Decoder.java
library/core/src/main/java/com/google/android/exoplayer2/upstream/DataSpec.java
library/core/src/main/java/com/google/android/exoplayer2/upstream/ParsingLoadable.java
library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSink.java
library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheUtil.java
library/core/src/main/java/com/google/android/exoplayer2/util/Util.java
library/core/src/main/java/com/google/android/exoplayer2/video/VideoRendererEventListener.java
library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CacheDataSourceTest.java
library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java
library/dash/src/main/java/com/google/android/exoplayer2/source/dash/offline/DashDownloadHelper.java
library/dash/src/main/java/com/google/android/exoplayer2/source/dash/offline/DashDownloader.java
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/offline/HlsDownloadHelper.java
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/offline/HlsDownloader.java
library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaSource.java
library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/offline/SsDownloadHelper.java
library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/offline/SsDownloader.java
testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaSource.java
testutils_robolectric/src/main/java/com/google/android/exoplayer2/testutil/CacheAsserts.java
RELEASENOTES.md
View file @
246d4644
...
@@ -9,6 +9,9 @@
...
@@ -9,6 +9,9 @@
(
[
#3314
](
https://github.com/google/ExoPlayer/issues/3314
)
).
(
[
#3314
](
https://github.com/google/ExoPlayer/issues/3314
)
).
*
Do not retry failed loads whose error is
`FileNotFoundException`
.
*
Do not retry failed loads whose error is
`FileNotFoundException`
.
*
Prevent Cea608Decoder from generating Subtitles with null Cues list
*
Prevent Cea608Decoder from generating Subtitles with null Cues list
*
Caching: Cache data with unknown length by default. The previous flag to opt in
to this behavior (
`DataSpec.FLAG_ALLOW_CACHING_UNKNOWN_LENGTH`
) has been
replaced with an opt out flag (
`DataSpec.FLAG_DONT_CACHE_IF_LENGTH_UNKNOWN`
).
### 2.9.2 ###
### 2.9.2 ###
...
...
extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsMediaSource.java
View file @
246d4644
...
@@ -77,6 +77,12 @@ public final class ImaAdsMediaSource extends BaseMediaSource implements SourceIn
...
@@ -77,6 +77,12 @@ public final class ImaAdsMediaSource extends BaseMediaSource implements SourceIn
}
}
@Override
@Override
@Nullable
public
Object
getTag
()
{
return
adsMediaSource
.
getTag
();
}
@Override
public
void
prepareSourceInternal
(
public
void
prepareSourceInternal
(
final
ExoPlayer
player
,
final
ExoPlayer
player
,
boolean
isTopLevelSource
,
boolean
isTopLevelSource
,
...
...
library/core/src/main/java/com/google/android/exoplayer2/audio/AudioRendererEventListener.java
View file @
246d4644
...
@@ -25,7 +25,8 @@ import com.google.android.exoplayer2.decoder.DecoderCounters;
...
@@ -25,7 +25,8 @@ import com.google.android.exoplayer2.decoder.DecoderCounters;
import
com.google.android.exoplayer2.util.Assertions
;
import
com.google.android.exoplayer2.util.Assertions
;
/**
/**
* Listener of audio {@link Renderer} events.
* Listener of audio {@link Renderer} events. All methods have no-op default implementations to
* allow selective overrides.
*/
*/
public
interface
AudioRendererEventListener
{
public
interface
AudioRendererEventListener
{
...
@@ -35,14 +36,14 @@ public interface AudioRendererEventListener {
...
@@ -35,14 +36,14 @@ public interface AudioRendererEventListener {
* @param counters {@link DecoderCounters} that will be updated by the renderer for as long as it
* @param counters {@link DecoderCounters} that will be updated by the renderer for as long as it
* remains enabled.
* remains enabled.
*/
*/
void
onAudioEnabled
(
DecoderCounters
counters
);
default
void
onAudioEnabled
(
DecoderCounters
counters
)
{}
/**
/**
* Called when the audio session is set.
* Called when the audio session is set.
*
*
* @param audioSessionId The audio session id.
* @param audioSessionId The audio session id.
*/
*/
void
onAudioSessionId
(
int
audioSessionId
);
default
void
onAudioSessionId
(
int
audioSessionId
)
{}
/**
/**
* Called when a decoder is created.
* Called when a decoder is created.
...
@@ -52,15 +53,15 @@ public interface AudioRendererEventListener {
...
@@ -52,15 +53,15 @@ public interface AudioRendererEventListener {
* finished.
* finished.
* @param initializationDurationMs The time taken to initialize the decoder in milliseconds.
* @param initializationDurationMs The time taken to initialize the decoder in milliseconds.
*/
*/
void
onAudioDecoderInitialized
(
String
decoderName
,
long
initializedTimestampMs
,
default
void
onAudioDecoderInitialized
(
long
initializationDurationMs
);
String
decoderName
,
long
initializedTimestampMs
,
long
initializationDurationMs
)
{}
/**
/**
* Called when the format of the media being consumed by the renderer changes.
* Called when the format of the media being consumed by the renderer changes.
*
*
* @param format The new format.
* @param format The new format.
*/
*/
void
onAudioInputFormatChanged
(
Format
format
);
default
void
onAudioInputFormatChanged
(
Format
format
)
{}
/**
/**
* Called when an {@link AudioSink} underrun occurs.
* Called when an {@link AudioSink} underrun occurs.
...
@@ -71,14 +72,15 @@ public interface AudioRendererEventListener {
...
@@ -71,14 +72,15 @@ public interface AudioRendererEventListener {
* as the buffered media can have a variable bitrate so the duration may be unknown.
* as the buffered media can have a variable bitrate so the duration may be unknown.
* @param elapsedSinceLastFeedMs The time since the {@link AudioSink} was last fed data.
* @param elapsedSinceLastFeedMs The time since the {@link AudioSink} was last fed data.
*/
*/
void
onAudioSinkUnderrun
(
int
bufferSize
,
long
bufferSizeMs
,
long
elapsedSinceLastFeedMs
);
default
void
onAudioSinkUnderrun
(
int
bufferSize
,
long
bufferSizeMs
,
long
elapsedSinceLastFeedMs
)
{}
/**
/**
* Called when the renderer is disabled.
* Called when the renderer is disabled.
*
*
* @param counters {@link DecoderCounters} that were updated by the renderer.
* @param counters {@link DecoderCounters} that were updated by the renderer.
*/
*/
void
onAudioDisabled
(
DecoderCounters
counters
);
default
void
onAudioDisabled
(
DecoderCounters
counters
)
{}
/**
/**
* Dispatches events to a {@link AudioRendererEventListener}.
* Dispatches events to a {@link AudioRendererEventListener}.
...
...
library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadHelper.java
View file @
246d4644
...
@@ -15,15 +15,21 @@
...
@@ -15,15 +15,21 @@
*/
*/
package
com
.
google
.
android
.
exoplayer2
.
offline
;
package
com
.
google
.
android
.
exoplayer2
.
offline
;
import
android.net.Uri
;
import
android.os.Handler
;
import
android.os.Handler
;
import
android.os.Looper
;
import
android.os.Looper
;
import
android.support.annotation.Nullable
;
import
android.support.annotation.Nullable
;
import
com.google.android.exoplayer2.source.TrackGroupArray
;
import
com.google.android.exoplayer2.source.TrackGroupArray
;
import
com.google.android.exoplayer2.util.Assertions
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.util.List
;
import
java.util.List
;
/** A helper for initializing and removing downloads. */
/**
public
abstract
class
DownloadHelper
{
* A helper for initializing and removing downloads.
*
* @param <T> The manifest type.
*/
public
abstract
class
DownloadHelper
<
T
>
{
/** A callback to be notified when the {@link DownloadHelper} is prepared. */
/** A callback to be notified when the {@link DownloadHelper} is prepared. */
public
interface
Callback
{
public
interface
Callback
{
...
@@ -44,6 +50,26 @@ public abstract class DownloadHelper {
...
@@ -44,6 +50,26 @@ public abstract class DownloadHelper {
void
onPrepareError
(
DownloadHelper
helper
,
IOException
e
);
void
onPrepareError
(
DownloadHelper
helper
,
IOException
e
);
}
}
private
final
String
downloadType
;
private
final
Uri
uri
;
@Nullable
private
final
String
cacheKey
;
@Nullable
private
T
manifest
;
@Nullable
private
TrackGroupArray
[]
trackGroupArrays
;
/**
* Create download helper.
*
* @param downloadType A download type. This value will be used as {@link DownloadAction#type}.
* @param uri A {@link Uri}.
* @param cacheKey An optional cache key.
*/
public
DownloadHelper
(
String
downloadType
,
Uri
uri
,
@Nullable
String
cacheKey
)
{
this
.
downloadType
=
downloadType
;
this
.
uri
=
uri
;
this
.
cacheKey
=
cacheKey
;
}
/**
/**
* Initializes the helper for starting a download.
* Initializes the helper for starting a download.
*
*
...
@@ -51,14 +77,15 @@ public abstract class DownloadHelper {
...
@@ -51,14 +77,15 @@ public abstract class DownloadHelper {
* will be invoked on the calling thread unless that thread does not have an associated {@link
* will be invoked on the calling thread unless that thread does not have an associated {@link
* Looper}, in which case it will be called on the application's main thread.
* Looper}, in which case it will be called on the application's main thread.
*/
*/
public
void
prepare
(
final
Callback
callback
)
{
public
final
void
prepare
(
final
Callback
callback
)
{
final
Handler
handler
=
final
Handler
handler
=
new
Handler
(
Looper
.
myLooper
()
!=
null
?
Looper
.
myLooper
()
:
Looper
.
getMainLooper
());
new
Handler
(
Looper
.
myLooper
()
!=
null
?
Looper
.
myLooper
()
:
Looper
.
getMainLooper
());
new
Thread
()
{
new
Thread
()
{
@Override
@Override
public
void
run
()
{
public
void
run
()
{
try
{
try
{
prepareInternal
();
manifest
=
loadManifest
(
uri
);
trackGroupArrays
=
getTrackGroupArrays
(
manifest
);
handler
.
post
(()
->
callback
.
onPrepared
(
DownloadHelper
.
this
));
handler
.
post
(()
->
callback
.
onPrepared
(
DownloadHelper
.
this
));
}
catch
(
final
IOException
e
)
{
}
catch
(
final
IOException
e
)
{
handler
.
post
(()
->
callback
.
onPrepareError
(
DownloadHelper
.
this
,
e
));
handler
.
post
(()
->
callback
.
onPrepareError
(
DownloadHelper
.
this
,
e
));
...
@@ -67,18 +94,20 @@ public abstract class DownloadHelper {
...
@@ -67,18 +94,20 @@ public abstract class DownloadHelper {
}.
start
();
}.
start
();
}
}
/**
/** Returns the manifest. Must not be called until after preparation completes. */
* Called on a background thread during preparation.
public
final
T
getManifest
()
{
*
Assertions
.
checkNotNull
(
manifest
);
* @throws IOException If preparation fails.
return
manifest
;
*/
}
protected
abstract
void
prepareInternal
()
throws
IOException
;
/**
/**
* Returns the number of periods for which media is available. Must not be called until after
* Returns the number of periods for which media is available. Must not be called until after
* preparation completes.
* preparation completes.
*/
*/
public
abstract
int
getPeriodCount
();
public
final
int
getPeriodCount
()
{
Assertions
.
checkNotNull
(
trackGroupArrays
);
return
trackGroupArrays
.
length
;
}
/**
/**
* Returns the track groups for the given period. Must not be called until after preparation
* Returns the track groups for the given period. Must not be called until after preparation
...
@@ -88,7 +117,10 @@ public abstract class DownloadHelper {
...
@@ -88,7 +117,10 @@ public abstract class DownloadHelper {
* @return The track groups for the period. May be {@link TrackGroupArray#EMPTY} for single stream
* @return The track groups for the period. May be {@link TrackGroupArray#EMPTY} for single stream
* content.
* content.
*/
*/
public
abstract
TrackGroupArray
getTrackGroups
(
int
periodIndex
);
public
final
TrackGroupArray
getTrackGroups
(
int
periodIndex
)
{
Assertions
.
checkNotNull
(
trackGroupArrays
);
return
trackGroupArrays
[
periodIndex
];
}
/**
/**
* Builds a {@link DownloadAction} for downloading the specified tracks. Must not be called until
* Builds a {@link DownloadAction} for downloading the specified tracks. Must not be called until
...
@@ -98,12 +130,41 @@ public abstract class DownloadHelper {
...
@@ -98,12 +130,41 @@ public abstract class DownloadHelper {
* @param trackKeys The selected tracks. If empty, all streams will be downloaded.
* @param trackKeys The selected tracks. If empty, all streams will be downloaded.
* @return The built {@link DownloadAction}.
* @return The built {@link DownloadAction}.
*/
*/
public
abstract
DownloadAction
getDownloadAction
(
@Nullable
byte
[]
data
,
List
<
TrackKey
>
trackKeys
);
public
final
DownloadAction
getDownloadAction
(
@Nullable
byte
[]
data
,
List
<
TrackKey
>
trackKeys
)
{
return
DownloadAction
.
createDownloadAction
(
downloadType
,
uri
,
toStreamKeys
(
trackKeys
),
cacheKey
,
data
);
}
/**
/**
* Builds a {@link DownloadAction} for removing the media. May be called in any state.
* Builds a {@link DownloadAction} for removing the media. May be called in any state.
*
*
* @return The built {@link DownloadAction}.
* @return The built {@link DownloadAction}.
*/
*/
public
abstract
DownloadAction
getRemoveAction
();
public
final
DownloadAction
getRemoveAction
()
{
return
DownloadAction
.
createRemoveAction
(
downloadType
,
uri
,
cacheKey
);
}
/**
* Loads the manifest. This method is called on a background thread.
*
* @param uri The manifest uri.
* @throws IOException If loading fails.
*/
protected
abstract
T
loadManifest
(
Uri
uri
)
throws
IOException
;
/**
* Returns the track group arrays for each period in the manifest.
*
* @param manifest The manifest.
* @return An array of {@link TrackGroupArray}s. One for each period in the manifest.
*/
protected
abstract
TrackGroupArray
[]
getTrackGroupArrays
(
T
manifest
);
/**
* Converts a list of {@link TrackKey track keys} to {@link StreamKey stream keys}.
*
* @param trackKeys A list of track keys.
* @return A corresponding list of stream keys.
*/
protected
abstract
List
<
StreamKey
>
toStreamKeys
(
List
<
TrackKey
>
trackKeys
);
}
}
library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadManager.java
View file @
246d4644
...
@@ -565,7 +565,7 @@ public final class DownloadManager {
...
@@ -565,7 +565,7 @@ public final class DownloadManager {
*/
*/
@TargetState
private
volatile
int
targetState
;
@TargetState
private
volatile
int
targetState
;
@MonotonicNonNull
private
volatile
Downloader
downloader
;
@MonotonicNonNull
private
Downloader
downloader
;
@MonotonicNonNull
private
Thread
thread
;
@MonotonicNonNull
private
Thread
thread
;
@MonotonicNonNull
private
Throwable
error
;
@MonotonicNonNull
private
Throwable
error
;
...
@@ -624,6 +624,7 @@ public final class DownloadManager {
...
@@ -624,6 +624,7 @@ public final class DownloadManager {
state
=
STATE_STARTED
;
state
=
STATE_STARTED
;
targetState
=
STATE_COMPLETED
;
targetState
=
STATE_COMPLETED
;
downloadManager
.
onTaskStateChange
(
this
);
downloadManager
.
onTaskStateChange
(
this
);
downloader
=
downloaderFactory
.
createDownloader
(
action
);
thread
=
new
Thread
(
this
);
thread
=
new
Thread
(
this
);
thread
.
start
();
thread
.
start
();
}
}
...
@@ -648,11 +649,7 @@ public final class DownloadManager {
...
@@ -648,11 +649,7 @@ public final class DownloadManager {
private
void
stopDownloadThread
(
@TargetState
int
targetState
)
{
private
void
stopDownloadThread
(
@TargetState
int
targetState
)
{
this
.
targetState
=
targetState
;
this
.
targetState
=
targetState
;
// TODO: The possibility of downloader being null here may prevent the download thread from
Assertions
.
checkNotNull
(
downloader
).
cancel
();
// stopping in a timely way. Fix this.
if
(
downloader
!=
null
)
{
downloader
.
cancel
();
}
Assertions
.
checkNotNull
(
thread
).
interrupt
();
Assertions
.
checkNotNull
(
thread
).
interrupt
();
}
}
...
@@ -675,7 +672,6 @@ public final class DownloadManager {
...
@@ -675,7 +672,6 @@ public final class DownloadManager {
logd
(
"Task is started"
,
this
);
logd
(
"Task is started"
,
this
);
Throwable
error
=
null
;
Throwable
error
=
null
;
try
{
try
{
downloader
=
downloaderFactory
.
createDownloader
(
action
);
if
(
action
.
isRemoveAction
)
{
if
(
action
.
isRemoveAction
)
{
downloader
.
remove
();
downloader
.
remove
();
}
else
{
}
else
{
...
...
library/core/src/main/java/com/google/android/exoplayer2/offline/ProgressiveDownloadHelper.java
View file @
246d4644
...
@@ -22,47 +22,28 @@ import java.util.Collections;
...
@@ -22,47 +22,28 @@ import java.util.Collections;
import
java.util.List
;
import
java.util.List
;
/** A {@link DownloadHelper} for progressive streams. */
/** A {@link DownloadHelper} for progressive streams. */
public
final
class
ProgressiveDownloadHelper
extends
DownloadHelper
{
public
final
class
ProgressiveDownloadHelper
extends
DownloadHelper
<
Void
>
{
private
final
Uri
uri
;
private
final
@Nullable
String
customCacheKey
;
public
ProgressiveDownloadHelper
(
Uri
uri
)
{
public
ProgressiveDownloadHelper
(
Uri
uri
)
{
this
(
uri
,
null
);
this
(
uri
,
null
);
}
}
public
ProgressiveDownloadHelper
(
Uri
uri
,
@Nullable
String
customCacheKey
)
{
public
ProgressiveDownloadHelper
(
Uri
uri
,
@Nullable
String
customCacheKey
)
{
this
.
uri
=
uri
;
super
(
DownloadAction
.
TYPE_PROGRESSIVE
,
uri
,
customCacheKey
);
this
.
customCacheKey
=
customCacheKey
;
}
@Override
protected
void
prepareInternal
()
{
// Do nothing.
}
@Override
public
int
getPeriodCount
()
{
return
1
;
}
}
@Override
@Override
p
ublic
TrackGroupArray
getTrackGroups
(
int
periodIndex
)
{
p
rotected
Void
loadManifest
(
Uri
uri
)
{
return
TrackGroupArray
.
EMPTY
;
return
null
;
}
}
@Override
@Override
public
DownloadAction
getDownloadAction
(
@Nullable
byte
[]
data
,
List
<
TrackKey
>
trackKeys
)
{
protected
TrackGroupArray
[]
getTrackGroupArrays
(
Void
manifest
)
{
return
DownloadAction
.
createDownloadAction
(
return
new
TrackGroupArray
[]
{
TrackGroupArray
.
EMPTY
};
DownloadAction
.
TYPE_PROGRESSIVE
,
uri
,
/* keys= */
Collections
.
emptyList
(),
customCacheKey
,
data
);
}
}
@Override
@Override
p
ublic
DownloadAction
getRemoveAction
(
)
{
p
rotected
List
<
StreamKey
>
toStreamKeys
(
List
<
TrackKey
>
trackKeys
)
{
return
DownloadAction
.
createRemoveAction
(
DownloadAction
.
TYPE_PROGRESSIVE
,
uri
,
customCacheKey
);
return
Collections
.
emptyList
(
);
}
}
}
}
library/core/src/main/java/com/google/android/exoplayer2/offline/SegmentDownloader.java
View file @
246d4644
...
@@ -62,7 +62,7 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M>> impleme
...
@@ -62,7 +62,7 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M>> impleme
private
static
final
int
BUFFER_SIZE_BYTES
=
128
*
1024
;
private
static
final
int
BUFFER_SIZE_BYTES
=
128
*
1024
;
private
final
Uri
manifestUri
;
private
final
DataSpec
manifestDataSpec
;
private
final
Cache
cache
;
private
final
Cache
cache
;
private
final
CacheDataSource
dataSource
;
private
final
CacheDataSource
dataSource
;
private
final
CacheDataSource
offlineDataSource
;
private
final
CacheDataSource
offlineDataSource
;
...
@@ -84,7 +84,7 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M>> impleme
...
@@ -84,7 +84,7 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M>> impleme
*/
*/
public
SegmentDownloader
(
public
SegmentDownloader
(
Uri
manifestUri
,
List
<
StreamKey
>
streamKeys
,
DownloaderConstructorHelper
constructorHelper
)
{
Uri
manifestUri
,
List
<
StreamKey
>
streamKeys
,
DownloaderConstructorHelper
constructorHelper
)
{
this
.
manifest
Uri
=
manifestUri
;
this
.
manifest
DataSpec
=
getCompressibleDataSpec
(
manifestUri
)
;
this
.
streamKeys
=
new
ArrayList
<>(
streamKeys
);
this
.
streamKeys
=
new
ArrayList
<>(
streamKeys
);
this
.
cache
=
constructorHelper
.
getCache
();
this
.
cache
=
constructorHelper
.
getCache
();
this
.
dataSource
=
constructorHelper
.
createCacheDataSource
();
this
.
dataSource
=
constructorHelper
.
createCacheDataSource
();
...
@@ -171,7 +171,7 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M>> impleme
...
@@ -171,7 +171,7 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M>> impleme
@Override
@Override
public
final
void
remove
()
throws
InterruptedException
{
public
final
void
remove
()
throws
InterruptedException
{
try
{
try
{
M
manifest
=
getManifest
(
offlineDataSource
,
manifest
Uri
);
M
manifest
=
getManifest
(
offlineDataSource
,
manifest
DataSpec
);
List
<
Segment
>
segments
=
getSegments
(
offlineDataSource
,
manifest
,
true
);
List
<
Segment
>
segments
=
getSegments
(
offlineDataSource
,
manifest
,
true
);
for
(
int
i
=
0
;
i
<
segments
.
size
();
i
++)
{
for
(
int
i
=
0
;
i
<
segments
.
size
();
i
++)
{
removeDataSpec
(
segments
.
get
(
i
).
dataSpec
);
removeDataSpec
(
segments
.
get
(
i
).
dataSpec
);
...
@@ -180,7 +180,7 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M>> impleme
...
@@ -180,7 +180,7 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M>> impleme
// Ignore exceptions when removing.
// Ignore exceptions when removing.
}
finally
{
}
finally
{
// Always attempt to remove the manifest.
// Always attempt to remove the manifest.
removeDataSpec
(
new
DataSpec
(
manifestUri
)
);
removeDataSpec
(
manifestDataSpec
);
}
}
}
}
...
@@ -190,11 +190,11 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M>> impleme
...
@@ -190,11 +190,11 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M>> impleme
* Loads and parses the manifest.
* Loads and parses the manifest.
*
*
* @param dataSource The {@link DataSource} through which to load.
* @param dataSource The {@link DataSource} through which to load.
* @param
uri The manifest uri
.
* @param
dataSpec The manifest {@link DataSpec}
.
* @return The manifest.
* @return The manifest.
* @throws IOException If an error occurs reading data.
* @throws IOException If an error occurs reading data.
*/
*/
protected
abstract
M
getManifest
(
DataSource
dataSource
,
Uri
uri
)
throws
IOException
;
protected
abstract
M
getManifest
(
DataSource
dataSource
,
DataSpec
dataSpec
)
throws
IOException
;
/**
/**
* Returns a list of all downloadable {@link Segment}s for a given manifest.
* Returns a list of all downloadable {@link Segment}s for a given manifest.
...
@@ -217,7 +217,7 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M>> impleme
...
@@ -217,7 +217,7 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M>> impleme
// Writes to downloadedSegments and downloadedBytes are safe. See the comment on download().
// Writes to downloadedSegments and downloadedBytes are safe. See the comment on download().
@SuppressWarnings
(
"NonAtomicVolatileUpdate"
)
@SuppressWarnings
(
"NonAtomicVolatileUpdate"
)
private
List
<
Segment
>
initDownload
()
throws
IOException
,
InterruptedException
{
private
List
<
Segment
>
initDownload
()
throws
IOException
,
InterruptedException
{
M
manifest
=
getManifest
(
dataSource
,
manifest
Uri
);
M
manifest
=
getManifest
(
dataSource
,
manifest
DataSpec
);
if
(!
streamKeys
.
isEmpty
())
{
if
(!
streamKeys
.
isEmpty
())
{
manifest
=
manifest
.
copy
(
streamKeys
);
manifest
=
manifest
.
copy
(
streamKeys
);
}
}
...
@@ -252,4 +252,12 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M>> impleme
...
@@ -252,4 +252,12 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M>> impleme
CacheUtil
.
remove
(
dataSpec
,
cache
,
cacheKeyFactory
);
CacheUtil
.
remove
(
dataSpec
,
cache
,
cacheKeyFactory
);
}
}
protected
static
DataSpec
getCompressibleDataSpec
(
Uri
uri
)
{
return
new
DataSpec
(
uri
,
/* absoluteStreamPosition= */
0
,
/* length= */
C
.
LENGTH_UNSET
,
/* key= */
null
,
/* flags= */
DataSpec
.
FLAG_ALLOW_GZIP
);
}
}
}
library/core/src/main/java/com/google/android/exoplayer2/source/ClippingMediaSource.java
View file @
246d4644
...
@@ -187,6 +187,12 @@ public final class ClippingMediaSource extends CompositeMediaSource<Void> {
...
@@ -187,6 +187,12 @@ public final class ClippingMediaSource extends CompositeMediaSource<Void> {
}
}
@Override
@Override
@Nullable
public
Object
getTag
()
{
return
mediaSource
.
getTag
();
}
@Override
public
void
prepareSourceInternal
(
public
void
prepareSourceInternal
(
ExoPlayer
player
,
ExoPlayer
player
,
boolean
isTopLevelSource
,
boolean
isTopLevelSource
,
...
...
library/core/src/main/java/com/google/android/exoplayer2/source/ConcatenatingMediaSource.java
View file @
246d4644
...
@@ -454,6 +454,12 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
...
@@ -454,6 +454,12 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
}
}
@Override
@Override
@Nullable
public
Object
getTag
()
{
return
null
;
}
@Override
public
final
synchronized
void
prepareSourceInternal
(
public
final
synchronized
void
prepareSourceInternal
(
ExoPlayer
player
,
ExoPlayer
player
,
boolean
isTopLevelSource
,
boolean
isTopLevelSource
,
...
@@ -1070,6 +1076,12 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
...
@@ -1070,6 +1076,12 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
}
}
@Override
@Override
@Nullable
public
Object
getTag
()
{
return
null
;
}
@Override
protected
void
releaseSourceInternal
()
{
protected
void
releaseSourceInternal
()
{
// Do nothing.
// Do nothing.
}
}
...
...
library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java
View file @
246d4644
...
@@ -850,6 +850,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
...
@@ -850,6 +850,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
private
DataSpec
dataSpec
;
private
DataSpec
dataSpec
;
private
long
length
;
private
long
length
;
@SuppressWarnings
(
"method.invocation.invalid"
)
public
ExtractingLoadable
(
public
ExtractingLoadable
(
Uri
uri
,
Uri
uri
,
DataSource
dataSource
,
DataSource
dataSource
,
...
@@ -864,7 +865,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
...
@@ -864,7 +865,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
this
.
positionHolder
=
new
PositionHolder
();
this
.
positionHolder
=
new
PositionHolder
();
this
.
pendingExtractorSeek
=
true
;
this
.
pendingExtractorSeek
=
true
;
this
.
length
=
C
.
LENGTH_UNSET
;
this
.
length
=
C
.
LENGTH_UNSET
;
dataSpec
=
new
DataSpec
(
uri
,
positionHolder
.
position
,
C
.
LENGTH_UNSET
,
customCacheKey
);
dataSpec
=
buildDataSpec
(
/* position= */
0
);
}
}
// Loadable implementation.
// Loadable implementation.
...
@@ -881,7 +882,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
...
@@ -881,7 +882,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
ExtractorInput
input
=
null
;
ExtractorInput
input
=
null
;
try
{
try
{
long
position
=
positionHolder
.
position
;
long
position
=
positionHolder
.
position
;
dataSpec
=
new
DataSpec
(
uri
,
position
,
C
.
LENGTH_UNSET
,
customCacheKey
);
dataSpec
=
buildDataSpec
(
position
);
length
=
dataSource
.
open
(
dataSpec
);
length
=
dataSource
.
open
(
dataSpec
);
if
(
length
!=
C
.
LENGTH_UNSET
)
{
if
(
length
!=
C
.
LENGTH_UNSET
)
{
length
+=
position
;
length
+=
position
;
...
@@ -915,6 +916,17 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
...
@@ -915,6 +916,17 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
// Internal methods.
// Internal methods.
private
DataSpec
buildDataSpec
(
long
position
)
{
// Disable caching if the content length cannot be resolved, since this is indicative of a
// progressive live stream.
return
new
DataSpec
(
uri
,
position
,
C
.
LENGTH_UNSET
,
customCacheKey
,
DataSpec
.
FLAG_DONT_CACHE_IF_LENGTH_UNKNOWN
);
}
private
void
setLoadPosition
(
long
position
,
long
timeUs
)
{
private
void
setLoadPosition
(
long
position
,
long
timeUs
)
{
positionHolder
.
position
=
position
;
positionHolder
.
position
=
position
;
seekTimeUs
=
timeUs
;
seekTimeUs
=
timeUs
;
...
...
library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaSource.java
View file @
246d4644
...
@@ -359,6 +359,12 @@ public final class ExtractorMediaSource extends BaseMediaSource
...
@@ -359,6 +359,12 @@ public final class ExtractorMediaSource extends BaseMediaSource
}
}
@Override
@Override
@Nullable
public
Object
getTag
()
{
return
tag
;
}
@Override
public
void
prepareSourceInternal
(
public
void
prepareSourceInternal
(
ExoPlayer
player
,
ExoPlayer
player
,
boolean
isTopLevelSource
,
boolean
isTopLevelSource
,
...
...
library/core/src/main/java/com/google/android/exoplayer2/source/LoopingMediaSource.java
View file @
246d4644
...
@@ -65,6 +65,12 @@ public final class LoopingMediaSource extends CompositeMediaSource<Void> {
...
@@ -65,6 +65,12 @@ public final class LoopingMediaSource extends CompositeMediaSource<Void> {
}
}
@Override
@Override
@Nullable
public
Object
getTag
()
{
return
childSource
.
getTag
();
}
@Override
public
void
prepareSourceInternal
(
public
void
prepareSourceInternal
(
ExoPlayer
player
,
ExoPlayer
player
,
boolean
isTopLevelSource
,
boolean
isTopLevelSource
,
...
...
library/core/src/main/java/com/google/android/exoplayer2/source/MediaSource.java
View file @
246d4644
...
@@ -219,6 +219,12 @@ public interface MediaSource {
...
@@ -219,6 +219,12 @@ public interface MediaSource {
*/
*/
void
removeEventListener
(
MediaSourceEventListener
eventListener
);
void
removeEventListener
(
MediaSourceEventListener
eventListener
);
/** Returns the tag set on the media source, or null if none was set. */
@Nullable
default
Object
getTag
()
{
return
null
;
}
/**
/**
* Starts source preparation if not yet started, and adds a listener for timeline and/or manifest
* Starts source preparation if not yet started, and adds a listener for timeline and/or manifest
* updates.
* updates.
...
...
library/core/src/main/java/com/google/android/exoplayer2/source/MergingMediaSource.java
View file @
246d4644
...
@@ -99,6 +99,12 @@ public final class MergingMediaSource extends CompositeMediaSource<Integer> {
...
@@ -99,6 +99,12 @@ public final class MergingMediaSource extends CompositeMediaSource<Integer> {
}
}
@Override
@Override
@Nullable
public
Object
getTag
()
{
return
mediaSources
.
length
>
0
?
mediaSources
[
0
].
getTag
()
:
null
;
}
@Override
public
void
prepareSourceInternal
(
public
void
prepareSourceInternal
(
ExoPlayer
player
,
ExoPlayer
player
,
boolean
isTopLevelSource
,
boolean
isTopLevelSource
,
...
...
library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaSource.java
View file @
246d4644
...
@@ -185,6 +185,7 @@ public final class SingleSampleMediaSource extends BaseMediaSource {
...
@@ -185,6 +185,7 @@ public final class SingleSampleMediaSource extends BaseMediaSource {
private
final
LoadErrorHandlingPolicy
loadErrorHandlingPolicy
;
private
final
LoadErrorHandlingPolicy
loadErrorHandlingPolicy
;
private
final
boolean
treatLoadErrorsAsEndOfStream
;
private
final
boolean
treatLoadErrorsAsEndOfStream
;
private
final
Timeline
timeline
;
private
final
Timeline
timeline
;
@Nullable
private
final
Object
tag
;
private
@Nullable
TransferListener
transferListener
;
private
@Nullable
TransferListener
transferListener
;
...
@@ -287,8 +288,8 @@ public final class SingleSampleMediaSource extends BaseMediaSource {
...
@@ -287,8 +288,8 @@ public final class SingleSampleMediaSource extends BaseMediaSource {
this
.
durationUs
=
durationUs
;
this
.
durationUs
=
durationUs
;
this
.
loadErrorHandlingPolicy
=
loadErrorHandlingPolicy
;
this
.
loadErrorHandlingPolicy
=
loadErrorHandlingPolicy
;
this
.
treatLoadErrorsAsEndOfStream
=
treatLoadErrorsAsEndOfStream
;
this
.
treatLoadErrorsAsEndOfStream
=
treatLoadErrorsAsEndOfStream
;
dataSpec
=
this
.
tag
=
tag
;
new
DataSpec
(
uri
,
DataSpec
.
FLAG_ALLOW_GZIP
|
DataSpec
.
FLAG_ALLOW_CACHING_UNKNOWN_LENGTH
);
dataSpec
=
new
DataSpec
(
uri
,
DataSpec
.
FLAG_ALLOW_GZIP
);
timeline
=
timeline
=
new
SinglePeriodTimeline
(
durationUs
,
/* isSeekable= */
true
,
/* isDynamic= */
false
,
tag
);
new
SinglePeriodTimeline
(
durationUs
,
/* isSeekable= */
true
,
/* isDynamic= */
false
,
tag
);
}
}
...
@@ -296,6 +297,12 @@ public final class SingleSampleMediaSource extends BaseMediaSource {
...
@@ -296,6 +297,12 @@ public final class SingleSampleMediaSource extends BaseMediaSource {
// MediaSource implementation.
// MediaSource implementation.
@Override
@Override
@Nullable
public
Object
getTag
()
{
return
tag
;
}
@Override
public
void
prepareSourceInternal
(
public
void
prepareSourceInternal
(
ExoPlayer
player
,
ExoPlayer
player
,
boolean
isTopLevelSource
,
boolean
isTopLevelSource
,
...
...
library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdsMediaSource.java
View file @
246d4644
...
@@ -320,6 +320,12 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
...
@@ -320,6 +320,12 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
}
}
@Override
@Override
@Nullable
public
Object
getTag
()
{
return
contentMediaSource
.
getTag
();
}
@Override
public
void
prepareSourceInternal
(
public
void
prepareSourceInternal
(
final
ExoPlayer
player
,
final
ExoPlayer
player
,
boolean
isTopLevelSource
,
boolean
isTopLevelSource
,
...
...
library/core/src/main/java/com/google/android/exoplayer2/text/cea/Cea608Decoder.java
View file @
246d4644
...
@@ -560,6 +560,14 @@ public final class Cea608Decoder extends CeaDecoder {
...
@@ -560,6 +560,14 @@ public final class Cea608Decoder extends CeaDecoder {
int
oldCaptionMode
=
this
.
captionMode
;
int
oldCaptionMode
=
this
.
captionMode
;
this
.
captionMode
=
captionMode
;
this
.
captionMode
=
captionMode
;
if
(
captionMode
==
CC_MODE_PAINT_ON
)
{
// Switching to paint-on mode should have no effect except to select the mode.
for
(
int
i
=
0
;
i
<
cueBuilders
.
size
();
i
++)
{
cueBuilders
.
get
(
i
).
setCaptionMode
(
captionMode
);
}
return
;
}
// Clear the working memory.
// Clear the working memory.
resetCueBuilders
();
resetCueBuilders
();
if
(
oldCaptionMode
==
CC_MODE_PAINT_ON
||
captionMode
==
CC_MODE_ROLL_UP
if
(
oldCaptionMode
==
CC_MODE_PAINT_ON
||
captionMode
==
CC_MODE_ROLL_UP
...
@@ -664,6 +672,10 @@ public final class Cea608Decoder extends CeaDecoder {
...
@@ -664,6 +672,10 @@ public final class Cea608Decoder extends CeaDecoder {
tabOffset
=
0
;
tabOffset
=
0
;
}
}
public
void
setCaptionMode
(
int
captionMode
)
{
this
.
captionMode
=
captionMode
;
}
public
void
setCaptionRowCount
(
int
captionRowCount
)
{
public
void
setCaptionRowCount
(
int
captionRowCount
)
{
this
.
captionRowCount
=
captionRowCount
;
this
.
captionRowCount
=
captionRowCount
;
}
}
...
...
library/core/src/main/java/com/google/android/exoplayer2/upstream/DataSpec.java
View file @
246d4644
...
@@ -32,32 +32,29 @@ public final class DataSpec {
...
@@ -32,32 +32,29 @@ public final class DataSpec {
/**
/**
* The flags that apply to any request for data. Possible flag values are {@link #FLAG_ALLOW_GZIP}
* The flags that apply to any request for data. Possible flag values are {@link #FLAG_ALLOW_GZIP}
* and {@link #FLAG_
ALLOW_CACHING_UNKNOWN_LENGTH
}.
* and {@link #FLAG_
DONT_CACHE_IF_LENGTH_UNKNOWN
}.
*/
*/
@Documented
@Documented
@Retention
(
RetentionPolicy
.
SOURCE
)
@Retention
(
RetentionPolicy
.
SOURCE
)
@IntDef
(
@IntDef
(
flag
=
true
,
flag
=
true
,
value
=
{
FLAG_ALLOW_GZIP
,
FLAG_
ALLOW_CACHING_UNKNOWN_LENGTH
})
value
=
{
FLAG_ALLOW_GZIP
,
FLAG_
DONT_CACHE_IF_LENGTH_UNKNOWN
})
public
@interface
Flags
{}
public
@interface
Flags
{}
/**
/**
*
Permit
s an underlying network stack to request that the server use gzip compression.
*
Allow
s an underlying network stack to request that the server use gzip compression.
*
<p>
*
*
Should not typically be set if the data being requested is already compressed (e.g. most audio
*
<p>Should not typically be set if the data being requested is already compressed (e.g. most
* and video requests). May be set when requesting other data.
* a
udio a
nd video requests). May be set when requesting other data.
*
<p>
*
*
When a {@link DataSource} is used to request data with this flag set, and if the
*
<p>When a {@link DataSource} is used to request data with this flag set, and if the {@link
*
{@link DataSource} does make a network request, then the value returned from
*
DataSource} does make a network request, then the value returned from {@link
*
{@link DataSource#open(DataSpec)} will typically be {@link C#LENGTH_UNSET}. The data read from
*
DataSource#open(DataSpec)} will typically be {@link C#LENGTH_UNSET}. The data read from {@link
*
{@link
DataSource#read(byte[], int, int)} will be the decompressed data.
* DataSource#read(byte[], int, int)} will be the decompressed data.
*/
*/
public
static
final
int
FLAG_ALLOW_GZIP
=
1
;
public
static
final
int
FLAG_ALLOW_GZIP
=
1
;
/**
/** Prevents caching if the length cannot be resolved when the {@link DataSource} is opened. */
* Permits content to be cached even if its length can not be resolved. Typically this's the case
public
static
final
int
FLAG_DONT_CACHE_IF_LENGTH_UNKNOWN
=
1
<<
1
;
// 2
* for progressive live streams and when {@link #FLAG_ALLOW_GZIP} is used.
*/
public
static
final
int
FLAG_ALLOW_CACHING_UNKNOWN_LENGTH
=
1
<<
1
;
// 2
/**
/**
* The set of HTTP methods that are supported by ExoPlayer {@link HttpDataSource}s. One of {@link
* The set of HTTP methods that are supported by ExoPlayer {@link HttpDataSource}s. One of {@link
...
...
library/core/src/main/java/com/google/android/exoplayer2/upstream/ParsingLoadable.java
View file @
246d4644
...
@@ -70,6 +70,24 @@ public final class ParsingLoadable<T> implements Loadable {
...
@@ -70,6 +70,24 @@ public final class ParsingLoadable<T> implements Loadable {
}
}
/**
/**
* Loads a single parsable object.
*
* @param dataSource The {@link DataSource} through which the object should be read.
* @param parser The {@link Parser} to parse the object from the response.
* @param dataSpec The {@link DataSpec} of the object to read.
* @param type The type of the data. One of the {@link C}{@code DATA_TYPE_*} constants.
* @return The parsed object
* @throws IOException Thrown if there is an error while loading or parsing.
*/
public
static
<
T
>
T
load
(
DataSource
dataSource
,
Parser
<?
extends
T
>
parser
,
DataSpec
dataSpec
,
int
type
)
throws
IOException
{
ParsingLoadable
<
T
>
loadable
=
new
ParsingLoadable
<>(
dataSource
,
dataSpec
,
type
,
parser
);
loadable
.
load
();
return
Assertions
.
checkNotNull
(
loadable
.
getResult
());
}
/**
* The {@link DataSpec} that defines the data to be loaded.
* The {@link DataSpec} that defines the data to be loaded.
*/
*/
public
final
DataSpec
dataSpec
;
public
final
DataSpec
dataSpec
;
...
@@ -91,11 +109,7 @@ public final class ParsingLoadable<T> implements Loadable {
...
@@ -91,11 +109,7 @@ public final class ParsingLoadable<T> implements Loadable {
* @param parser Parses the object from the response.
* @param parser Parses the object from the response.
*/
*/
public
ParsingLoadable
(
DataSource
dataSource
,
Uri
uri
,
int
type
,
Parser
<?
extends
T
>
parser
)
{
public
ParsingLoadable
(
DataSource
dataSource
,
Uri
uri
,
int
type
,
Parser
<?
extends
T
>
parser
)
{
this
(
this
(
dataSource
,
new
DataSpec
(
uri
,
DataSpec
.
FLAG_ALLOW_GZIP
),
type
,
parser
);
dataSource
,
new
DataSpec
(
uri
,
DataSpec
.
FLAG_ALLOW_GZIP
|
DataSpec
.
FLAG_ALLOW_CACHING_UNKNOWN_LENGTH
),
type
,
parser
);
}
}
/**
/**
...
...
library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSink.java
View file @
246d4644
...
@@ -121,7 +121,7 @@ public final class CacheDataSink implements DataSink {
...
@@ -121,7 +121,7 @@ public final class CacheDataSink implements DataSink {
@Override
@Override
public
void
open
(
DataSpec
dataSpec
)
throws
CacheDataSinkException
{
public
void
open
(
DataSpec
dataSpec
)
throws
CacheDataSinkException
{
if
(
dataSpec
.
length
==
C
.
LENGTH_UNSET
if
(
dataSpec
.
length
==
C
.
LENGTH_UNSET
&&
!
dataSpec
.
isFlagSet
(
DataSpec
.
FLAG_ALLOW_CACHING_UNKNOWN_LENGTH
))
{
&&
dataSpec
.
isFlagSet
(
DataSpec
.
FLAG_DONT_CACHE_IF_LENGTH_UNKNOWN
))
{
this
.
dataSpec
=
null
;
this
.
dataSpec
=
null
;
return
;
return
;
}
}
...
...
library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheUtil.java
View file @
246d4644
...
@@ -268,7 +268,7 @@ public final class CacheUtil {
...
@@ -268,7 +268,7 @@ public final class CacheUtil {
dataSpec
.
position
+
absoluteStreamPosition
-
dataSpec
.
absoluteStreamPosition
,
dataSpec
.
position
+
absoluteStreamPosition
-
dataSpec
.
absoluteStreamPosition
,
C
.
LENGTH_UNSET
,
C
.
LENGTH_UNSET
,
dataSpec
.
key
,
dataSpec
.
key
,
dataSpec
.
flags
|
DataSpec
.
FLAG_ALLOW_CACHING_UNKNOWN_LENGTH
);
dataSpec
.
flags
);
long
resolvedLength
=
dataSource
.
open
(
dataSpec
);
long
resolvedLength
=
dataSource
.
open
(
dataSpec
);
if
(
counters
.
contentLength
==
C
.
LENGTH_UNSET
&&
resolvedLength
!=
C
.
LENGTH_UNSET
)
{
if
(
counters
.
contentLength
==
C
.
LENGTH_UNSET
&&
resolvedLength
!=
C
.
LENGTH_UNSET
)
{
counters
.
contentLength
=
dataSpec
.
absoluteStreamPosition
+
resolvedLength
;
counters
.
contentLength
=
dataSpec
.
absoluteStreamPosition
+
resolvedLength
;
...
...
library/core/src/main/java/com/google/android/exoplayer2/util/Util.java
View file @
246d4644
...
@@ -48,8 +48,15 @@ import com.google.android.exoplayer2.C;
...
@@ -48,8 +48,15 @@ import com.google.android.exoplayer2.C;
import
com.google.android.exoplayer2.ExoPlayerLibraryInfo
;
import
com.google.android.exoplayer2.ExoPlayerLibraryInfo
;
import
com.google.android.exoplayer2.Format
;
import
com.google.android.exoplayer2.Format
;
import
com.google.android.exoplayer2.ParserException
;
import
com.google.android.exoplayer2.ParserException
;
import
com.google.android.exoplayer2.Renderer
;
import
com.google.android.exoplayer2.RendererCapabilities
;
import
com.google.android.exoplayer2.RenderersFactory
;
import
com.google.android.exoplayer2.SeekParameters
;
import
com.google.android.exoplayer2.SeekParameters
;
import
com.google.android.exoplayer2.audio.AudioRendererEventListener
;
import
com.google.android.exoplayer2.drm.DrmSessionManager
;
import
com.google.android.exoplayer2.drm.FrameworkMediaCrypto
;
import
com.google.android.exoplayer2.upstream.DataSource
;
import
com.google.android.exoplayer2.upstream.DataSource
;
import
com.google.android.exoplayer2.video.VideoRendererEventListener
;
import
java.io.ByteArrayOutputStream
;
import
java.io.ByteArrayOutputStream
;
import
java.io.Closeable
;
import
java.io.Closeable
;
import
java.io.File
;
import
java.io.File
;
...
@@ -1842,6 +1849,32 @@ public final class Util {
...
@@ -1842,6 +1849,32 @@ public final class Util {
return
displaySize
;
return
displaySize
;
}
}
/**
* Extract renderer capabilities for the renderers created by the provided renderers factory.
*
* @param renderersFactory A {@link RenderersFactory}.
* @param drmSessionManager An optional {@link DrmSessionManager} used by the renderers.
* @return The {@link RendererCapabilities} for each renderer created by the {@code
* renderersFactory}.
*/
public
static
RendererCapabilities
[]
getRendererCapabilities
(
RenderersFactory
renderersFactory
,
@Nullable
DrmSessionManager
<
FrameworkMediaCrypto
>
drmSessionManager
)
{
Renderer
[]
renderers
=
renderersFactory
.
createRenderers
(
new
Handler
(),
new
VideoRendererEventListener
()
{},
new
AudioRendererEventListener
()
{},
(
cues
)
->
{},
(
metadata
)
->
{},
drmSessionManager
);
RendererCapabilities
[]
capabilities
=
new
RendererCapabilities
[
renderers
.
length
];
for
(
int
i
=
0
;
i
<
renderers
.
length
;
i
++)
{
capabilities
[
i
]
=
renderers
[
i
].
getCapabilities
();
}
return
capabilities
;
}
@Nullable
@Nullable
private
static
String
getSystemProperty
(
String
name
)
{
private
static
String
getSystemProperty
(
String
name
)
{
try
{
try
{
...
...
library/core/src/main/java/com/google/android/exoplayer2/video/VideoRendererEventListener.java
View file @
246d4644
...
@@ -26,7 +26,8 @@ import com.google.android.exoplayer2.decoder.DecoderCounters;
...
@@ -26,7 +26,8 @@ import com.google.android.exoplayer2.decoder.DecoderCounters;
import
com.google.android.exoplayer2.util.Assertions
;
import
com.google.android.exoplayer2.util.Assertions
;
/**
/**
* Listener of video {@link Renderer} events.
* Listener of video {@link Renderer} events. All methods have no-op default implementations to
* allow selective overrides.
*/
*/
public
interface
VideoRendererEventListener
{
public
interface
VideoRendererEventListener
{
...
@@ -36,7 +37,7 @@ public interface VideoRendererEventListener {
...
@@ -36,7 +37,7 @@ public interface VideoRendererEventListener {
* @param counters {@link DecoderCounters} that will be updated by the renderer for as long as it
* @param counters {@link DecoderCounters} that will be updated by the renderer for as long as it
* remains enabled.
* remains enabled.
*/
*/
void
onVideoEnabled
(
DecoderCounters
counters
);
default
void
onVideoEnabled
(
DecoderCounters
counters
)
{}
/**
/**
* Called when a decoder is created.
* Called when a decoder is created.
...
@@ -46,15 +47,15 @@ public interface VideoRendererEventListener {
...
@@ -46,15 +47,15 @@ public interface VideoRendererEventListener {
* finished.
* finished.
* @param initializationDurationMs The time taken to initialize the decoder in milliseconds.
* @param initializationDurationMs The time taken to initialize the decoder in milliseconds.
*/
*/
void
onVideoDecoderInitialized
(
String
decoderName
,
long
initializedTimestampMs
,
default
void
onVideoDecoderInitialized
(
long
initializationDurationMs
);
String
decoderName
,
long
initializedTimestampMs
,
long
initializationDurationMs
)
{}
/**
/**
* Called when the format of the media being consumed by the renderer changes.
* Called when the format of the media being consumed by the renderer changes.
*
*
* @param format The new format.
* @param format The new format.
*/
*/
void
onVideoInputFormatChanged
(
Format
format
);
default
void
onVideoInputFormatChanged
(
Format
format
)
{}
/**
/**
* Called to report the number of frames dropped by the renderer. Dropped frames are reported
* Called to report the number of frames dropped by the renderer. Dropped frames are reported
...
@@ -62,12 +63,11 @@ public interface VideoRendererEventListener {
...
@@ -62,12 +63,11 @@ public interface VideoRendererEventListener {
* reaches a specified threshold whilst the renderer is started.
* reaches a specified threshold whilst the renderer is started.
*
*
* @param count The number of dropped frames.
* @param count The number of dropped frames.
* @param elapsedMs The duration in milliseconds over which the frames were dropped. This
* @param elapsedMs The duration in milliseconds over which the frames were dropped. This duration
* duration is timed from when the renderer was started or from when dropped frames were
* is timed from when the renderer was started or from when dropped frames were last reported
* last reported (whichever was more recent), and not from when the first of the reported
* (whichever was more recent), and not from when the first of the reported drops occurred.
* drops occurred.
*/
*/
void
onDroppedFrames
(
int
count
,
long
elapsedMs
);
default
void
onDroppedFrames
(
int
count
,
long
elapsedMs
)
{}
/**
/**
* Called before a frame is rendered for the first time since setting the surface, and each time
* Called before a frame is rendered for the first time since setting the surface, and each time
...
@@ -82,12 +82,12 @@ public interface VideoRendererEventListener {
...
@@ -82,12 +82,12 @@ public interface VideoRendererEventListener {
* this is not possible. Applications that use {@link TextureView} can apply the rotation by
* this is not possible. Applications that use {@link TextureView} can apply the rotation by
* calling {@link TextureView#setTransform}. Applications that do not expect to encounter
* calling {@link TextureView#setTransform}. Applications that do not expect to encounter
* rotated videos can safely ignore this parameter.
* rotated videos can safely ignore this parameter.
* @param pixelWidthHeightRatio The width to height ratio of each pixel. For the normal case
* @param pixelWidthHeightRatio The width to height ratio of each pixel. For the normal case
of
*
of
square pixels this will be equal to 1.0. Different values are indicative of anamorphic
* square pixels this will be equal to 1.0. Different values are indicative of anamorphic
* content.
* content.
*/
*/
void
onVideoSizeChanged
(
int
width
,
int
height
,
int
unappliedRotationDegrees
,
default
void
onVideoSizeChanged
(
float
pixelWidthHeightRatio
);
int
width
,
int
height
,
int
unappliedRotationDegrees
,
float
pixelWidthHeightRatio
)
{}
/**
/**
* Called when a frame is rendered for the first time since setting the surface, and when a frame
* Called when a frame is rendered for the first time since setting the surface, and when a frame
...
@@ -96,14 +96,14 @@ public interface VideoRendererEventListener {
...
@@ -96,14 +96,14 @@ public interface VideoRendererEventListener {
* @param surface The {@link Surface} to which a first frame has been rendered, or {@code null} if
* @param surface The {@link Surface} to which a first frame has been rendered, or {@code null} if
* the renderer renders to something that isn't a {@link Surface}.
* the renderer renders to something that isn't a {@link Surface}.
*/
*/
void
onRenderedFirstFrame
(
@Nullable
Surface
surface
);
default
void
onRenderedFirstFrame
(
@Nullable
Surface
surface
)
{}
/**
/**
* Called when the renderer is disabled.
* Called when the renderer is disabled.
*
*
* @param counters {@link DecoderCounters} that were updated by the renderer.
* @param counters {@link DecoderCounters} that were updated by the renderer.
*/
*/
void
onVideoDisabled
(
DecoderCounters
counters
);
default
void
onVideoDisabled
(
DecoderCounters
counters
)
{}
/**
/**
* Dispatches events to a {@link VideoRendererEventListener}.
* Dispatches events to a {@link VideoRendererEventListener}.
...
...
library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CacheDataSourceTest.java
View file @
246d4644
...
@@ -602,7 +602,6 @@ public final class CacheDataSourceTest {
...
@@ -602,7 +602,6 @@ public final class CacheDataSourceTest {
}
}
private
DataSpec
buildDataSpec
(
long
position
,
long
length
,
@Nullable
String
key
)
{
private
DataSpec
buildDataSpec
(
long
position
,
long
length
,
@Nullable
String
key
)
{
return
new
DataSpec
(
return
new
DataSpec
(
testDataUri
,
position
,
length
,
key
);
testDataUri
,
position
,
length
,
key
,
DataSpec
.
FLAG_ALLOW_CACHING_UNKNOWN_LENGTH
);
}
}
}
}
library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java
View file @
246d4644
...
@@ -608,6 +608,12 @@ public final class DashMediaSource extends BaseMediaSource {
...
@@ -608,6 +608,12 @@ public final class DashMediaSource extends BaseMediaSource {
// MediaSource implementation.
// MediaSource implementation.
@Override
@Override
@Nullable
public
Object
getTag
()
{
return
tag
;
}
@Override
public
void
prepareSourceInternal
(
public
void
prepareSourceInternal
(
ExoPlayer
player
,
ExoPlayer
player
,
boolean
isTopLevelSource
,
boolean
isTopLevelSource
,
...
...
library/dash/src/main/java/com/google/android/exoplayer2/source/dash/offline/DashDownloadHelper.java
View file @
246d4644
...
@@ -16,7 +16,6 @@
...
@@ -16,7 +16,6 @@
package
com
.
google
.
android
.
exoplayer2
.
source
.
dash
.
offline
;
package
com
.
google
.
android
.
exoplayer2
.
source
.
dash
.
offline
;
import
android.net.Uri
;
import
android.net.Uri
;
import
android.support.annotation.Nullable
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.Format
;
import
com.google.android.exoplayer2.Format
;
import
com.google.android.exoplayer2.offline.DownloadAction
;
import
com.google.android.exoplayer2.offline.DownloadAction
;
...
@@ -31,74 +30,49 @@ import com.google.android.exoplayer2.source.dash.manifest.DashManifestParser;
...
@@ -31,74 +30,49 @@ import com.google.android.exoplayer2.source.dash.manifest.DashManifestParser;
import
com.google.android.exoplayer2.source.dash.manifest.Representation
;
import
com.google.android.exoplayer2.source.dash.manifest.Representation
;
import
com.google.android.exoplayer2.upstream.DataSource
;
import
com.google.android.exoplayer2.upstream.DataSource
;
import
com.google.android.exoplayer2.upstream.ParsingLoadable
;
import
com.google.android.exoplayer2.upstream.ParsingLoadable
;
import
com.google.android.exoplayer2.util.Assertions
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.List
;
import
org.checkerframework.checker.nullness.qual.MonotonicNonNull
;
/** A {@link DownloadHelper} for DASH streams. */
/** A {@link DownloadHelper} for DASH streams. */
public
final
class
DashDownloadHelper
extends
DownloadHelper
{
public
final
class
DashDownloadHelper
extends
DownloadHelper
<
DashManifest
>
{
private
final
Uri
uri
;
private
final
DataSource
.
Factory
manifestDataSourceFactory
;
private
final
DataSource
.
Factory
manifestDataSourceFactory
;
private
@MonotonicNonNull
DashManifest
manifest
;
public
DashDownloadHelper
(
Uri
uri
,
DataSource
.
Factory
manifestDataSourceFactory
)
{
public
DashDownloadHelper
(
Uri
uri
,
DataSource
.
Factory
manifestDataSourceFactory
)
{
this
.
uri
=
uri
;
super
(
DownloadAction
.
TYPE_DASH
,
uri
,
/* cacheKey= */
null
)
;
this
.
manifestDataSourceFactory
=
manifestDataSourceFactory
;
this
.
manifestDataSourceFactory
=
manifestDataSourceFactory
;
}
}
@Override
@Override
protected
void
prepareInternal
(
)
throws
IOException
{
protected
DashManifest
loadManifest
(
Uri
uri
)
throws
IOException
{
DataSource
dataSource
=
manifestDataSourceFactory
.
createDataSource
();
DataSource
dataSource
=
manifestDataSourceFactory
.
createDataSource
();
manifest
=
return
ParsingLoadable
.
load
(
dataSource
,
new
DashManifestParser
(),
uri
,
C
.
DATA_TYPE_MANIFEST
);
ParsingLoadable
.
load
(
dataSource
,
new
DashManifestParser
(),
uri
,
C
.
DATA_TYPE_MANIFEST
);
}
/** Returns the DASH manifest. Must not be called until after preparation completes. */
public
DashManifest
getManifest
()
{
Assertions
.
checkNotNull
(
manifest
);
return
manifest
;
}
@Override
public
int
getPeriodCount
()
{
Assertions
.
checkNotNull
(
manifest
);
return
manifest
.
getPeriodCount
();
}
}
@Override
@Override
public
TrackGroupArray
getTrackGroups
(
int
periodIndex
)
{
public
TrackGroupArray
[]
getTrackGroupArrays
(
DashManifest
manifest
)
{
Assertions
.
checkNotNull
(
manifest
);
int
periodCount
=
manifest
.
getPeriodCount
();
List
<
AdaptationSet
>
adaptationSets
=
manifest
.
getPeriod
(
periodIndex
).
adaptationSets
;
TrackGroupArray
[]
trackGroupArrays
=
new
TrackGroupArray
[
periodCount
];
TrackGroup
[]
trackGroups
=
new
TrackGroup
[
adaptationSets
.
size
()];
for
(
int
periodIndex
=
0
;
periodIndex
<
periodCount
;
periodIndex
++)
{
for
(
int
i
=
0
;
i
<
trackGroups
.
length
;
i
++)
{
List
<
AdaptationSet
>
adaptationSets
=
manifest
.
getPeriod
(
periodIndex
).
adaptationSets
;
List
<
Representation
>
representations
=
adaptationSets
.
get
(
i
).
representations
;
TrackGroup
[]
trackGroups
=
new
TrackGroup
[
adaptationSets
.
size
()];
Format
[]
formats
=
new
Format
[
representations
.
size
()];
for
(
int
i
=
0
;
i
<
trackGroups
.
length
;
i
++)
{
int
representationsCount
=
representations
.
size
();
List
<
Representation
>
representations
=
adaptationSets
.
get
(
i
).
representations
;
for
(
int
j
=
0
;
j
<
representationsCount
;
j
++)
{
Format
[]
formats
=
new
Format
[
representations
.
size
()];
formats
[
j
]
=
representations
.
get
(
j
).
format
;
int
representationsCount
=
representations
.
size
();
for
(
int
j
=
0
;
j
<
representationsCount
;
j
++)
{
formats
[
j
]
=
representations
.
get
(
j
).
format
;
}
trackGroups
[
i
]
=
new
TrackGroup
(
formats
);
}
}
trackGroup
s
[
i
]
=
new
TrackGroup
(
format
s
);
trackGroup
Arrays
[
periodIndex
]
=
new
TrackGroupArray
(
trackGroup
s
);
}
}
return
new
TrackGroupArray
(
trackGroups
)
;
return
trackGroupArrays
;
}
}
@Override
@Override
public
DownloadAction
getDownloadAction
(
@Nullable
byte
[]
data
,
List
<
TrackKey
>
trackKeys
)
{
protected
List
<
StreamKey
>
toStreamKeys
(
List
<
TrackKey
>
trackKeys
)
{
return
DownloadAction
.
createDownloadAction
(
DownloadAction
.
TYPE_DASH
,
uri
,
toStreamKeys
(
trackKeys
),
/* customCacheKey= */
null
,
data
);
}
@Override
public
DownloadAction
getRemoveAction
()
{
return
DownloadAction
.
createRemoveAction
(
DownloadAction
.
TYPE_DASH
,
uri
,
/* customCacheKey= */
null
);
}
private
static
List
<
StreamKey
>
toStreamKeys
(
List
<
TrackKey
>
trackKeys
)
{
List
<
StreamKey
>
streamKeys
=
new
ArrayList
<>(
trackKeys
.
size
());
List
<
StreamKey
>
streamKeys
=
new
ArrayList
<>(
trackKeys
.
size
());
for
(
int
i
=
0
;
i
<
trackKeys
.
size
();
i
++)
{
for
(
int
i
=
0
;
i
<
trackKeys
.
size
();
i
++)
{
TrackKey
trackKey
=
trackKeys
.
get
(
i
);
TrackKey
trackKey
=
trackKeys
.
get
(
i
);
...
...
library/dash/src/main/java/com/google/android/exoplayer2/source/dash/offline/DashDownloader.java
View file @
246d4644
...
@@ -28,11 +28,13 @@ import com.google.android.exoplayer2.source.dash.DashUtil;
...
@@ -28,11 +28,13 @@ import com.google.android.exoplayer2.source.dash.DashUtil;
import
com.google.android.exoplayer2.source.dash.DashWrappingSegmentIndex
;
import
com.google.android.exoplayer2.source.dash.DashWrappingSegmentIndex
;
import
com.google.android.exoplayer2.source.dash.manifest.AdaptationSet
;
import
com.google.android.exoplayer2.source.dash.manifest.AdaptationSet
;
import
com.google.android.exoplayer2.source.dash.manifest.DashManifest
;
import
com.google.android.exoplayer2.source.dash.manifest.DashManifest
;
import
com.google.android.exoplayer2.source.dash.manifest.DashManifestParser
;
import
com.google.android.exoplayer2.source.dash.manifest.Period
;
import
com.google.android.exoplayer2.source.dash.manifest.Period
;
import
com.google.android.exoplayer2.source.dash.manifest.RangedUri
;
import
com.google.android.exoplayer2.source.dash.manifest.RangedUri
;
import
com.google.android.exoplayer2.source.dash.manifest.Representation
;
import
com.google.android.exoplayer2.source.dash.manifest.Representation
;
import
com.google.android.exoplayer2.upstream.DataSource
;
import
com.google.android.exoplayer2.upstream.DataSource
;
import
com.google.android.exoplayer2.upstream.DataSpec
;
import
com.google.android.exoplayer2.upstream.DataSpec
;
import
com.google.android.exoplayer2.upstream.ParsingLoadable
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.List
;
...
@@ -73,8 +75,9 @@ public final class DashDownloader extends SegmentDownloader<DashManifest> {
...
@@ -73,8 +75,9 @@ public final class DashDownloader extends SegmentDownloader<DashManifest> {
}
}
@Override
@Override
protected
DashManifest
getManifest
(
DataSource
dataSource
,
Uri
uri
)
throws
IOException
{
protected
DashManifest
getManifest
(
DataSource
dataSource
,
DataSpec
dataSpec
)
throws
IOException
{
return
DashUtil
.
loadManifest
(
dataSource
,
uri
);
return
ParsingLoadable
.
load
(
dataSource
,
new
DashManifestParser
(),
dataSpec
,
C
.
DATA_TYPE_MANIFEST
);
}
}
@Override
@Override
...
@@ -121,8 +124,7 @@ public final class DashDownloader extends SegmentDownloader<DashManifest> {
...
@@ -121,8 +124,7 @@ public final class DashDownloader extends SegmentDownloader<DashManifest> {
if
(!
allowIncompleteList
)
{
if
(!
allowIncompleteList
)
{
throw
e
;
throw
e
;
}
}
// Loading failed, but generating an incomplete segment list is allowed. Advance to the next
// Generating an incomplete segment list is allowed. Advance to the next representation.
// representation.
continue
;
continue
;
}
}
...
...
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java
View file @
246d4644
...
@@ -391,6 +391,12 @@ public final class HlsMediaSource extends BaseMediaSource
...
@@ -391,6 +391,12 @@ public final class HlsMediaSource extends BaseMediaSource
}
}
@Override
@Override
@Nullable
public
Object
getTag
()
{
return
tag
;
}
@Override
public
void
prepareSourceInternal
(
public
void
prepareSourceInternal
(
ExoPlayer
player
,
ExoPlayer
player
,
boolean
isTopLevelSource
,
boolean
isTopLevelSource
,
...
...
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/offline/HlsDownloadHelper.java
View file @
246d4644
...
@@ -16,7 +16,6 @@
...
@@ -16,7 +16,6 @@
package
com
.
google
.
android
.
exoplayer2
.
source
.
hls
.
offline
;
package
com
.
google
.
android
.
exoplayer2
.
source
.
hls
.
offline
;
import
android.net.Uri
;
import
android.net.Uri
;
import
android.support.annotation.Nullable
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.Format
;
import
com.google.android.exoplayer2.Format
;
import
com.google.android.exoplayer2.offline.DownloadAction
;
import
com.google.android.exoplayer2.offline.DownloadAction
;
...
@@ -36,46 +35,31 @@ import java.io.IOException;
...
@@ -36,46 +35,31 @@ import java.io.IOException;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
java.util.List
;
import
java.util.List
;
import
org.checkerframework.checker.nullness.qual.MonotonicNonNull
;
/** A {@link DownloadHelper} for HLS streams. */
/** A {@link DownloadHelper} for HLS streams. */
public
final
class
HlsDownloadHelper
extends
DownloadHelper
{
public
final
class
HlsDownloadHelper
extends
DownloadHelper
<
HlsPlaylist
>
{
private
final
Uri
uri
;
private
final
DataSource
.
Factory
manifestDataSourceFactory
;
private
final
DataSource
.
Factory
manifestDataSourceFactory
;
private
@MonotonicNonNull
HlsPlaylist
playlist
;
private
int
[]
renditionGroups
;
private
int
[]
renditionGroups
;
public
HlsDownloadHelper
(
Uri
uri
,
DataSource
.
Factory
manifestDataSourceFactory
)
{
public
HlsDownloadHelper
(
Uri
uri
,
DataSource
.
Factory
manifestDataSourceFactory
)
{
this
.
uri
=
uri
;
super
(
DownloadAction
.
TYPE_HLS
,
uri
,
/* cacheKey= */
null
)
;
this
.
manifestDataSourceFactory
=
manifestDataSourceFactory
;
this
.
manifestDataSourceFactory
=
manifestDataSourceFactory
;
}
}
@Override
@Override
protected
void
prepareInternal
(
)
throws
IOException
{
protected
HlsPlaylist
loadManifest
(
Uri
uri
)
throws
IOException
{
DataSource
dataSource
=
manifestDataSourceFactory
.
createDataSource
();
DataSource
dataSource
=
manifestDataSourceFactory
.
createDataSource
();
playlist
=
ParsingLoadable
.
load
(
dataSource
,
new
HlsPlaylistParser
(),
uri
,
C
.
DATA_TYPE_MANIFEST
);
return
ParsingLoadable
.
load
(
dataSource
,
new
HlsPlaylistParser
(),
uri
,
C
.
DATA_TYPE_MANIFEST
);
}
/** Returns the HLS playlist. Must not be called until after preparation completes. */
public
HlsPlaylist
getPlaylist
()
{
Assertions
.
checkNotNull
(
playlist
);
return
playlist
;
}
}
@Override
@Override
public
int
getPeriodCount
()
{
protected
TrackGroupArray
[]
getTrackGroupArrays
(
HlsPlaylist
playlist
)
{
Assertions
.
checkNotNull
(
playlist
);
return
1
;
}
@Override
public
TrackGroupArray
getTrackGroups
(
int
periodIndex
)
{
Assertions
.
checkNotNull
(
playlist
);
Assertions
.
checkNotNull
(
playlist
);
if
(
playlist
instanceof
HlsMediaPlaylist
)
{
if
(
playlist
instanceof
HlsMediaPlaylist
)
{
renditionGroups
=
new
int
[
0
];
renditionGroups
=
new
int
[
0
];
return
TrackGroupArray
.
EMPTY
;
return
new
TrackGroupArray
[]
{
TrackGroupArray
.
EMPTY
}
;
}
}
// TODO: Generate track groups as in playback. Reverse the mapping in getDownloadAction.
// TODO: Generate track groups as in playback. Reverse the mapping in getDownloadAction.
HlsMasterPlaylist
masterPlaylist
=
(
HlsMasterPlaylist
)
playlist
;
HlsMasterPlaylist
masterPlaylist
=
(
HlsMasterPlaylist
)
playlist
;
...
@@ -94,24 +78,18 @@ public final class HlsDownloadHelper extends DownloadHelper {
...
@@ -94,24 +78,18 @@ public final class HlsDownloadHelper extends DownloadHelper {
renditionGroups
[
trackGroupIndex
]
=
HlsMasterPlaylist
.
GROUP_INDEX_SUBTITLE
;
renditionGroups
[
trackGroupIndex
]
=
HlsMasterPlaylist
.
GROUP_INDEX_SUBTITLE
;
trackGroups
[
trackGroupIndex
++]
=
new
TrackGroup
(
toFormats
(
masterPlaylist
.
subtitles
));
trackGroups
[
trackGroupIndex
++]
=
new
TrackGroup
(
toFormats
(
masterPlaylist
.
subtitles
));
}
}
return
new
TrackGroupArray
(
Arrays
.
copyOf
(
trackGroups
,
trackGroupIndex
))
;
return
new
TrackGroupArray
[]
{
new
TrackGroupArray
(
Arrays
.
copyOf
(
trackGroups
,
trackGroupIndex
))}
;
}
}
@Override
@Override
public
DownloadAction
getDownloadAction
(
@Nullable
byte
[]
data
,
List
<
TrackKey
>
trackKeys
)
{
protected
List
<
StreamKey
>
toStreamKeys
(
List
<
TrackKey
>
trackKeys
)
{
Assertions
.
checkNotNull
(
renditionGroups
);
List
<
StreamKey
>
representationKeys
=
new
ArrayList
<>(
trackKeys
.
size
());
return
DownloadAction
.
createDownloadAction
(
for
(
int
i
=
0
;
i
<
trackKeys
.
size
();
i
++)
{
DownloadAction
.
TYPE_HLS
,
TrackKey
trackKey
=
trackKeys
.
get
(
i
);
uri
,
representationKeys
.
add
(
toStreamKeys
(
trackKeys
,
renditionGroups
),
new
StreamKey
(
renditionGroups
[
trackKey
.
groupIndex
],
trackKey
.
trackIndex
));
/* customCacheKey= */
null
,
}
data
);
return
representationKeys
;
}
@Override
public
DownloadAction
getRemoveAction
()
{
return
DownloadAction
.
createRemoveAction
(
DownloadAction
.
TYPE_HLS
,
uri
,
/* customCacheKey= */
null
);
}
}
private
static
Format
[]
toFormats
(
List
<
HlsMasterPlaylist
.
HlsUrl
>
hlsUrls
)
{
private
static
Format
[]
toFormats
(
List
<
HlsMasterPlaylist
.
HlsUrl
>
hlsUrls
)
{
...
@@ -121,13 +99,4 @@ public final class HlsDownloadHelper extends DownloadHelper {
...
@@ -121,13 +99,4 @@ public final class HlsDownloadHelper extends DownloadHelper {
}
}
return
formats
;
return
formats
;
}
}
private
static
List
<
StreamKey
>
toStreamKeys
(
List
<
TrackKey
>
trackKeys
,
int
[]
groups
)
{
List
<
StreamKey
>
representationKeys
=
new
ArrayList
<>(
trackKeys
.
size
());
for
(
int
i
=
0
;
i
<
trackKeys
.
size
();
i
++)
{
TrackKey
trackKey
=
trackKeys
.
get
(
i
);
representationKeys
.
add
(
new
StreamKey
(
groups
[
trackKey
.
groupIndex
],
trackKey
.
trackIndex
));
}
return
representationKeys
;
}
}
}
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/offline/HlsDownloader.java
View file @
246d4644
...
@@ -71,35 +71,37 @@ public final class HlsDownloader extends SegmentDownloader<HlsPlaylist> {
...
@@ -71,35 +71,37 @@ public final class HlsDownloader extends SegmentDownloader<HlsPlaylist> {
}
}
@Override
@Override
protected
HlsPlaylist
getManifest
(
DataSource
dataSource
,
Uri
uri
)
throws
IOException
{
protected
HlsPlaylist
getManifest
(
DataSource
dataSource
,
DataSpec
dataSpec
)
throws
IOException
{
return
loadManifest
(
dataSource
,
uri
);
return
loadManifest
(
dataSource
,
dataSpec
);
}
}
@Override
@Override
protected
List
<
Segment
>
getSegments
(
protected
List
<
Segment
>
getSegments
(
DataSource
dataSource
,
HlsPlaylist
playlist
,
boolean
allowIncompleteList
)
throws
IOException
{
DataSource
dataSource
,
HlsPlaylist
playlist
,
boolean
allowIncompleteList
)
throws
IOException
{
ArrayList
<
Uri
>
mediaPlaylistUris
=
new
ArrayList
<>();
String
baseUri
=
playlist
.
baseUri
;
ArrayList
<
DataSpec
>
mediaPlaylistDataSpecs
=
new
ArrayList
<>();
if
(
playlist
instanceof
HlsMasterPlaylist
)
{
if
(
playlist
instanceof
HlsMasterPlaylist
)
{
HlsMasterPlaylist
masterPlaylist
=
(
HlsMasterPlaylist
)
playlist
;
HlsMasterPlaylist
masterPlaylist
=
(
HlsMasterPlaylist
)
playlist
;
add
ResolvedUris
(
masterPlaylist
.
baseUri
,
masterPlaylist
.
variants
,
mediaPlaylistUri
s
);
add
MediaPlaylistDataSpecs
(
baseUri
,
masterPlaylist
.
variants
,
mediaPlaylistDataSpec
s
);
add
ResolvedUris
(
masterPlaylist
.
baseUri
,
masterPlaylist
.
audios
,
mediaPlaylistUri
s
);
add
MediaPlaylistDataSpecs
(
baseUri
,
masterPlaylist
.
audios
,
mediaPlaylistDataSpec
s
);
add
ResolvedUris
(
masterPlaylist
.
baseUri
,
masterPlaylist
.
subtitles
,
mediaPlaylistUri
s
);
add
MediaPlaylistDataSpecs
(
baseUri
,
masterPlaylist
.
subtitles
,
mediaPlaylistDataSpec
s
);
}
else
{
}
else
{
mediaPlaylist
Uris
.
add
(
Uri
.
parse
(
playlist
.
baseUri
));
mediaPlaylist
DataSpecs
.
add
(
SegmentDownloader
.
getCompressibleDataSpec
(
Uri
.
parse
(
baseUri
)
));
}
}
ArrayList
<
Segment
>
segments
=
new
ArrayList
<>();
ArrayList
<
Segment
>
segments
=
new
ArrayList
<>();
HashSet
<
Uri
>
seenEncryptionKeyUris
=
new
HashSet
<>();
HashSet
<
Uri
>
seenEncryptionKeyUris
=
new
HashSet
<>();
for
(
Uri
mediaPlaylistUri
:
mediaPlaylistUris
)
{
for
(
DataSpec
mediaPlaylistDataSpec
:
mediaPlaylistDataSpecs
)
{
segments
.
add
(
new
Segment
(
/* startTimeUs= */
0
,
mediaPlaylistDataSpec
));
HlsMediaPlaylist
mediaPlaylist
;
HlsMediaPlaylist
mediaPlaylist
;
try
{
try
{
mediaPlaylist
=
(
HlsMediaPlaylist
)
loadManifest
(
dataSource
,
mediaPlaylistUri
);
mediaPlaylist
=
(
HlsMediaPlaylist
)
loadManifest
(
dataSource
,
mediaPlaylistDataSpec
);
segments
.
add
(
new
Segment
(
mediaPlaylist
.
startTimeUs
,
new
DataSpec
(
mediaPlaylistUri
)));
}
catch
(
IOException
e
)
{
}
catch
(
IOException
e
)
{
if
(!
allowIncompleteList
)
{
if
(!
allowIncompleteList
)
{
throw
e
;
throw
e
;
}
}
segments
.
add
(
new
Segment
(
0
,
new
DataSpec
(
mediaPlaylistUri
)));
// Generating an incomplete segment list is allowed. Advance to the next media playlist.
continue
;
continue
;
}
}
HlsMediaPlaylist
.
Segment
lastInitSegment
=
null
;
HlsMediaPlaylist
.
Segment
lastInitSegment
=
null
;
...
@@ -109,39 +111,43 @@ public final class HlsDownloader extends SegmentDownloader<HlsPlaylist> {
...
@@ -109,39 +111,43 @@ public final class HlsDownloader extends SegmentDownloader<HlsPlaylist> {
HlsMediaPlaylist
.
Segment
initSegment
=
segment
.
initializationSegment
;
HlsMediaPlaylist
.
Segment
initSegment
=
segment
.
initializationSegment
;
if
(
initSegment
!=
null
&&
initSegment
!=
lastInitSegment
)
{
if
(
initSegment
!=
null
&&
initSegment
!=
lastInitSegment
)
{
lastInitSegment
=
initSegment
;
lastInitSegment
=
initSegment
;
addSegment
(
segments
,
mediaPlaylist
,
initSegment
,
seenEncryptionKeyUri
s
);
addSegment
(
mediaPlaylist
,
initSegment
,
seenEncryptionKeyUris
,
segment
s
);
}
}
addSegment
(
segments
,
mediaPlaylist
,
segment
,
seenEncryptionKeyUri
s
);
addSegment
(
mediaPlaylist
,
segment
,
seenEncryptionKeyUris
,
segment
s
);
}
}
}
}
return
segments
;
return
segments
;
}
}
private
static
HlsPlaylist
loadManifest
(
DataSource
dataSource
,
Uri
uri
)
throws
IOException
{
private
void
addMediaPlaylistDataSpecs
(
String
baseUri
,
List
<
HlsUrl
>
urls
,
List
<
DataSpec
>
out
)
{
return
ParsingLoadable
.
load
(
dataSource
,
new
HlsPlaylistParser
(),
uri
,
C
.
DATA_TYPE_MANIFEST
);
for
(
int
i
=
0
;
i
<
urls
.
size
();
i
++)
{
Uri
playlistUri
=
UriUtil
.
resolveToUri
(
baseUri
,
urls
.
get
(
i
).
url
);
out
.
add
(
SegmentDownloader
.
getCompressibleDataSpec
(
playlistUri
));
}
}
}
private
static
void
addSegment
(
private
static
HlsPlaylist
loadManifest
(
DataSource
dataSource
,
DataSpec
dataSpec
)
ArrayList
<
Segment
>
segments
,
throws
IOException
{
return
ParsingLoadable
.
load
(
dataSource
,
new
HlsPlaylistParser
(),
dataSpec
,
C
.
DATA_TYPE_MANIFEST
);
}
private
void
addSegment
(
HlsMediaPlaylist
mediaPlaylist
,
HlsMediaPlaylist
mediaPlaylist
,
HlsMediaPlaylist
.
Segment
hlsSegment
,
HlsMediaPlaylist
.
Segment
segment
,
HashSet
<
Uri
>
seenEncryptionKeyUris
)
{
HashSet
<
Uri
>
seenEncryptionKeyUris
,
long
startTimeUs
=
mediaPlaylist
.
startTimeUs
+
hlsSegment
.
relativeStartTimeUs
;
ArrayList
<
Segment
>
out
)
{
if
(
hlsSegment
.
fullSegmentEncryptionKeyUri
!=
null
)
{
String
baseUri
=
mediaPlaylist
.
baseUri
;
Uri
keyUri
=
UriUtil
.
resolveToUri
(
mediaPlaylist
.
baseUri
,
long
startTimeUs
=
mediaPlaylist
.
startTimeUs
+
segment
.
relativeStartTimeUs
;
hlsSegment
.
fullSegmentEncryptionKeyUri
);
if
(
segment
.
fullSegmentEncryptionKeyUri
!=
null
)
{
Uri
keyUri
=
UriUtil
.
resolveToUri
(
baseUri
,
segment
.
fullSegmentEncryptionKeyUri
);
if
(
seenEncryptionKeyUris
.
add
(
keyUri
))
{
if
(
seenEncryptionKeyUris
.
add
(
keyUri
))
{
segments
.
add
(
new
Segment
(
startTimeUs
,
new
DataSpec
(
keyUri
)));
out
.
add
(
new
Segment
(
startTimeUs
,
SegmentDownloader
.
getCompressible
DataSpec
(
keyUri
)));
}
}
}
}
Uri
resolvedUri
=
UriUtil
.
resolveToUri
(
mediaPlaylist
.
baseUri
,
hlsSegment
.
url
);
Uri
segmentUri
=
UriUtil
.
resolveToUri
(
baseUri
,
segment
.
url
);
segments
.
add
(
new
Segment
(
startTimeUs
,
DataSpec
dataSpec
=
new
DataSpec
(
resolvedUri
,
hlsSegment
.
byterangeOffset
,
hlsSegment
.
byterangeLength
,
null
)));
new
DataSpec
(
segmentUri
,
segment
.
byterangeOffset
,
segment
.
byterangeLength
,
/* key= */
null
);
}
out
.
add
(
new
Segment
(
startTimeUs
,
dataSpec
));
private
static
void
addResolvedUris
(
String
baseUri
,
List
<
HlsUrl
>
urls
,
List
<
Uri
>
out
)
{
for
(
int
i
=
0
;
i
<
urls
.
size
();
i
++)
{
out
.
add
(
UriUtil
.
resolveToUri
(
baseUri
,
urls
.
get
(
i
).
url
));
}
}
}
}
}
library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaSource.java
View file @
246d4644
...
@@ -504,6 +504,12 @@ public final class SsMediaSource extends BaseMediaSource
...
@@ -504,6 +504,12 @@ public final class SsMediaSource extends BaseMediaSource
// MediaSource implementation.
// MediaSource implementation.
@Override
@Override
@Nullable
public
Object
getTag
()
{
return
tag
;
}
@Override
public
void
prepareSourceInternal
(
public
void
prepareSourceInternal
(
ExoPlayer
player
,
ExoPlayer
player
,
boolean
isTopLevelSource
,
boolean
isTopLevelSource
,
...
...
library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/offline/SsDownloadHelper.java
View file @
246d4644
...
@@ -16,7 +16,6 @@
...
@@ -16,7 +16,6 @@
package
com
.
google
.
android
.
exoplayer2
.
source
.
smoothstreaming
.
offline
;
package
com
.
google
.
android
.
exoplayer2
.
source
.
smoothstreaming
.
offline
;
import
android.net.Uri
;
import
android.net.Uri
;
import
android.support.annotation.Nullable
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.offline.DownloadAction
;
import
com.google.android.exoplayer2.offline.DownloadAction
;
import
com.google.android.exoplayer2.offline.DownloadHelper
;
import
com.google.android.exoplayer2.offline.DownloadHelper
;
...
@@ -28,67 +27,38 @@ import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest;
...
@@ -28,67 +27,38 @@ import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest;
import
com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifestParser
;
import
com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifestParser
;
import
com.google.android.exoplayer2.upstream.DataSource
;
import
com.google.android.exoplayer2.upstream.DataSource
;
import
com.google.android.exoplayer2.upstream.ParsingLoadable
;
import
com.google.android.exoplayer2.upstream.ParsingLoadable
;
import
com.google.android.exoplayer2.util.Assertions
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.List
;
import
org.checkerframework.checker.nullness.qual.MonotonicNonNull
;
/** A {@link DownloadHelper} for SmoothStreaming streams. */
/** A {@link DownloadHelper} for SmoothStreaming streams. */
public
final
class
SsDownloadHelper
extends
DownloadHelper
{
public
final
class
SsDownloadHelper
extends
DownloadHelper
<
SsManifest
>
{
private
final
Uri
uri
;
private
final
DataSource
.
Factory
manifestDataSourceFactory
;
private
final
DataSource
.
Factory
manifestDataSourceFactory
;
private
@MonotonicNonNull
SsManifest
manifest
;
public
SsDownloadHelper
(
Uri
uri
,
DataSource
.
Factory
manifestDataSourceFactory
)
{
public
SsDownloadHelper
(
Uri
uri
,
DataSource
.
Factory
manifestDataSourceFactory
)
{
this
.
uri
=
uri
;
super
(
DownloadAction
.
TYPE_SS
,
uri
,
/* cacheKey= */
null
)
;
this
.
manifestDataSourceFactory
=
manifestDataSourceFactory
;
this
.
manifestDataSourceFactory
=
manifestDataSourceFactory
;
}
}
@Override
@Override
protected
void
prepareInternal
(
)
throws
IOException
{
protected
SsManifest
loadManifest
(
Uri
uri
)
throws
IOException
{
DataSource
dataSource
=
manifestDataSourceFactory
.
createDataSource
();
DataSource
dataSource
=
manifestDataSourceFactory
.
createDataSource
();
manifest
=
ParsingLoadable
.
load
(
dataSource
,
new
SsManifestParser
(),
uri
,
C
.
DATA_TYPE_MANIFEST
);
return
ParsingLoadable
.
load
(
dataSource
,
new
SsManifestParser
(),
uri
,
C
.
DATA_TYPE_MANIFEST
);
}
/** Returns the SmoothStreaming manifest. Must not be called until after preparation completes. */
public
SsManifest
getManifest
()
{
Assertions
.
checkNotNull
(
manifest
);
return
manifest
;
}
@Override
public
int
getPeriodCount
()
{
Assertions
.
checkNotNull
(
manifest
);
return
1
;
}
}
@Override
@Override
public
TrackGroupArray
getTrackGroups
(
int
periodIndex
)
{
protected
TrackGroupArray
[]
getTrackGroupArrays
(
SsManifest
manifest
)
{
Assertions
.
checkNotNull
(
manifest
);
SsManifest
.
StreamElement
[]
streamElements
=
manifest
.
streamElements
;
SsManifest
.
StreamElement
[]
streamElements
=
manifest
.
streamElements
;
TrackGroup
[]
trackGroups
=
new
TrackGroup
[
streamElements
.
length
];
TrackGroup
[]
trackGroups
=
new
TrackGroup
[
streamElements
.
length
];
for
(
int
i
=
0
;
i
<
streamElements
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
streamElements
.
length
;
i
++)
{
trackGroups
[
i
]
=
new
TrackGroup
(
streamElements
[
i
].
formats
);
trackGroups
[
i
]
=
new
TrackGroup
(
streamElements
[
i
].
formats
);
}
}
return
new
TrackGroupArray
(
trackGroups
)
;
return
new
TrackGroupArray
[]
{
new
TrackGroupArray
(
trackGroups
)}
;
}
}
@Override
@Override
public
DownloadAction
getDownloadAction
(
@Nullable
byte
[]
data
,
List
<
TrackKey
>
trackKeys
)
{
protected
List
<
StreamKey
>
toStreamKeys
(
List
<
TrackKey
>
trackKeys
)
{
return
DownloadAction
.
createDownloadAction
(
DownloadAction
.
TYPE_SS
,
uri
,
toStreamKeys
(
trackKeys
),
/* customCacheKey= */
null
,
data
);
}
@Override
public
DownloadAction
getRemoveAction
()
{
return
DownloadAction
.
createRemoveAction
(
DownloadAction
.
TYPE_SS
,
uri
,
/* customCacheKey= */
null
);
}
private
static
List
<
StreamKey
>
toStreamKeys
(
List
<
TrackKey
>
trackKeys
)
{
List
<
StreamKey
>
representationKeys
=
new
ArrayList
<>(
trackKeys
.
size
());
List
<
StreamKey
>
representationKeys
=
new
ArrayList
<>(
trackKeys
.
size
());
for
(
int
i
=
0
;
i
<
trackKeys
.
size
();
i
++)
{
for
(
int
i
=
0
;
i
<
trackKeys
.
size
();
i
++)
{
TrackKey
trackKey
=
trackKeys
.
get
(
i
);
TrackKey
trackKey
=
trackKeys
.
get
(
i
);
...
...
library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/offline/SsDownloader.java
View file @
246d4644
...
@@ -68,8 +68,8 @@ public final class SsDownloader extends SegmentDownloader<SsManifest> {
...
@@ -68,8 +68,8 @@ public final class SsDownloader extends SegmentDownloader<SsManifest> {
}
}
@Override
@Override
protected
SsManifest
getManifest
(
DataSource
dataSource
,
Uri
uri
)
throws
IOException
{
protected
SsManifest
getManifest
(
DataSource
dataSource
,
DataSpec
dataSpec
)
throws
IOException
{
return
ParsingLoadable
.
load
(
dataSource
,
new
SsManifestParser
(),
uri
,
C
.
DATA_TYPE_MANIFEST
);
return
ParsingLoadable
.
load
(
dataSource
,
new
SsManifestParser
(),
dataSpec
,
C
.
DATA_TYPE_MANIFEST
);
}
}
@Override
@Override
...
...
testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaSource.java
View file @
246d4644
...
@@ -89,6 +89,13 @@ public class FakeMediaSource extends BaseMediaSource {
...
@@ -89,6 +89,13 @@ public class FakeMediaSource extends BaseMediaSource {
}
}
@Override
@Override
@Nullable
public
Object
getTag
()
{
boolean
hasTimeline
=
timeline
!=
null
&&
!
timeline
.
isEmpty
();
return
hasTimeline
?
timeline
.
getWindow
(
0
,
new
Timeline
.
Window
()).
tag
:
null
;
}
@Override
public
synchronized
void
prepareSourceInternal
(
public
synchronized
void
prepareSourceInternal
(
ExoPlayer
player
,
ExoPlayer
player
,
boolean
isTopLevelSource
,
boolean
isTopLevelSource
,
...
...
testutils_robolectric/src/main/java/com/google/android/exoplayer2/testutil/CacheAsserts.java
View file @
246d4644
...
@@ -83,7 +83,7 @@ public final class CacheAsserts {
...
@@ -83,7 +83,7 @@ public final class CacheAsserts {
* @throws IOException If an error occurred reading from the Cache.
* @throws IOException If an error occurred reading from the Cache.
*/
*/
public
static
void
assertDataCached
(
Cache
cache
,
Uri
uri
,
byte
[]
expected
)
throws
IOException
{
public
static
void
assertDataCached
(
Cache
cache
,
Uri
uri
,
byte
[]
expected
)
throws
IOException
{
DataSpec
dataSpec
=
new
DataSpec
(
uri
,
DataSpec
.
FLAG_ALLOW_CACHING_UNKNOWN_LENGTH
);
DataSpec
dataSpec
=
new
DataSpec
(
uri
);
assertDataCached
(
cache
,
dataSpec
,
expected
);
assertDataCached
(
cache
,
dataSpec
,
expected
);
}
}
...
...
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