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
6673483a
authored
Oct 20, 2016
by
ojw28
Committed by
GitHub
Oct 20, 2016
Browse files
Options
_('Browse Files')
Download
Plain Diff
Merge pull request #1971 from google/dev-v2
Update dev-v2-id3
parents
3e3248d7
924a0417
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
89 additions
and
116 deletions
RELEASENOTES.md
build.gradle
demo/src/main/AndroidManifest.xml
extensions/cronet/src/androidTest/java/com/google/android/exoplayer2/ext/cronet/CronetDataSourceTest.java
extensions/cronet/src/main/java/com/google/android/exoplayer2/ext/cronet/CronetDataSource.java
extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSource.java
library/src/androidTest/java/com/google/android/exoplayer2/upstream/cache/CacheDataSourceTest.java
library/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java
library/src/main/java/com/google/android/exoplayer2/extractor/ts/H265Reader.java
library/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java
library/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java
library/src/main/java/com/google/android/exoplayer2/source/dash/manifest/Representation.java
library/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java
library/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java
library/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSource.java
playbacktests/src/main/AndroidManifest.xml
RELEASENOTES.md
View file @
6673483a
# Release notes #
### r2.0.
3
###
### r2.0.
4
###
This release contains important bug fixes. Users of
r2.0.0, r2.0.1 and r2.0.2
This release contains important bug fixes. Users of
earlier r2.0.x versions
should proactively update to this version.
*
Fix crash on Jellybean devices when using playback controls
(
[
#1965
](
https://github.com/google/ExoPlayer/issues/1965
)
).
### r2.0.3 ###
*
Fixed NullPointerException in ExtractorMediaSource
(
[
#1914
](
https://github.com/google/ExoPlayer/issues/1914
)
.
(
[
#1914
](
https://github.com/google/ExoPlayer/issues/1914
)
)
.
*
Fixed NullPointerException in HlsMediaPeriod
(
[
#1907
](
https://github.com/google/ExoPlayer/issues/1907
)
.
(
[
#1907
](
https://github.com/google/ExoPlayer/issues/1907
)
)
.
*
Fixed memory leak in PlaybackControlView
(
[
#1908
](
https://github.com/google/ExoPlayer/issues/1908
)
.
(
[
#1908
](
https://github.com/google/ExoPlayer/issues/1908
)
)
.
*
Fixed strict mode violation when using
SimpleExoPlayer.setVideoPlayerTextureView().
*
Fixed L3 Widevine provisioning
(
[
#1925
](
https://github.com/google/ExoPlayer/issues/1925
)
.
(
[
#1925
](
https://github.com/google/ExoPlayer/issues/1925
)
)
.
*
Fixed hiding of controls with use_controller="false"
(
[
#1919
](
https://github.com/google/ExoPlayer/issues/1919
)
.
(
[
#1919
](
https://github.com/google/ExoPlayer/issues/1919
)
)
.
*
Improvements to Cronet network stack extension.
*
Misc bug fixes.
...
...
build.gradle
View file @
6673483a
...
...
@@ -35,7 +35,7 @@ allprojects {
releaseRepoName
=
'exoplayer'
releaseUserOrg
=
'google'
releaseGroupId
=
'com.google.android.exoplayer'
releaseVersion
=
'r2.0.
3
'
releaseVersion
=
'r2.0.
4
'
releaseWebsite
=
'https://github.com/google/ExoPlayer'
}
}
demo/src/main/AndroidManifest.xml
View file @
6673483a
...
...
@@ -16,8 +16,8 @@
<manifest
xmlns:android=
"http://schemas.android.com/apk/res/android"
package=
"com.google.android.exoplayer2.demo"
android:versionCode=
"200
3
"
android:versionName=
"2.0.
3
"
>
android:versionCode=
"200
4
"
android:versionName=
"2.0.
4
"
>
<uses-permission
android:name=
"android.permission.INTERNET"
/>
<uses-permission
android:name=
"android.permission.READ_EXTERNAL_STORAGE"
/>
...
...
extensions/cronet/src/androidTest/java/com/google/android/exoplayer2/ext/cronet/CronetDataSourceTest.java
View file @
6673483a
...
...
@@ -22,7 +22,6 @@ import static org.junit.Assert.assertFalse;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
junit
.
Assert
.
fail
;
import
static
org
.
mockito
.
Matchers
.
any
;
import
static
org
.
mockito
.
Matchers
.
anyInt
;
import
static
org
.
mockito
.
Matchers
.
anyString
;
import
static
org
.
mockito
.
Matchers
.
eq
;
import
static
org
.
mockito
.
Mockito
.
doAnswer
;
...
...
@@ -52,7 +51,6 @@ import java.net.UnknownHostException;
import
java.nio.ByteBuffer
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.Map
;
...
...
@@ -88,20 +86,7 @@ public final class CronetDataSourceTest {
private
Map
<
String
,
String
>
testResponseHeader
;
private
UrlResponseInfo
testUrlResponseInfo
;
/**
* MockableCronetEngine is an abstract class for helping creating new Requests.
*/
public
abstract
static
class
MockableCronetEngine
extends
CronetEngine
{
@Override
public
abstract
UrlRequest
createRequest
(
String
url
,
UrlRequest
.
Callback
callback
,
Executor
executor
,
int
priority
,
Collection
<
Object
>
connectionAnnotations
,
boolean
disableCache
,
boolean
disableConnectionMigration
,
boolean
allowDirectExecutor
);
}
@Mock
private
UrlRequest
.
Builder
mockUrlRequestBuilder
;
@Mock
private
UrlRequest
mockUrlRequest
;
@Mock
...
...
@@ -114,8 +99,7 @@ public final class CronetDataSourceTest {
private
Executor
mockExecutor
;
@Mock
private
UrlRequestException
mockUrlRequestException
;
@Mock
private
MockableCronetEngine
mockCronetEngine
;
@Mock
private
CronetEngine
mockCronetEngine
;
private
CronetDataSource
dataSourceUnderTest
;
...
...
@@ -135,15 +119,10 @@ public final class CronetDataSourceTest {
true
,
// resetTimeoutOnRedirects
mockClock
));
when
(
mockContentTypePredicate
.
evaluate
(
anyString
())).
thenReturn
(
true
);
when
(
mockCronetEngine
.
createRequest
(
anyString
(),
any
(
UrlRequest
.
Callback
.
class
),
any
(
Executor
.
class
),
anyInt
(),
eq
(
Collections
.
emptyList
()),
any
(
Boolean
.
class
),
any
(
Boolean
.
class
),
any
(
Boolean
.
class
))).
thenReturn
(
mockUrlRequest
);
when
(
mockCronetEngine
.
newUrlRequestBuilder
(
anyString
(),
any
(
UrlRequest
.
Callback
.
class
),
any
(
Executor
.
class
)))
.
thenReturn
(
mockUrlRequestBuilder
);
when
(
mockUrlRequestBuilder
.
build
()).
thenReturn
(
mockUrlRequest
);
mockStatusResponse
();
testDataSpec
=
new
DataSpec
(
Uri
.
parse
(
TEST_URL
),
0
,
C
.
LENGTH_UNSET
,
null
);
...
...
@@ -184,15 +163,7 @@ public final class CronetDataSourceTest {
dataSourceUnderTest
.
close
();
// Prepare a mock UrlRequest to be used in the second open() call.
final
UrlRequest
mockUrlRequest2
=
mock
(
UrlRequest
.
class
);
when
(
mockCronetEngine
.
createRequest
(
anyString
(),
any
(
UrlRequest
.
Callback
.
class
),
any
(
Executor
.
class
),
anyInt
(),
eq
(
Collections
.
emptyList
()),
any
(
Boolean
.
class
),
any
(
Boolean
.
class
),
any
(
Boolean
.
class
))).
thenReturn
(
mockUrlRequest2
);
when
(
mockUrlRequestBuilder
.
build
()).
thenReturn
(
mockUrlRequest2
);
doAnswer
(
new
Answer
<
Object
>()
{
@Override
public
Object
answer
(
InvocationOnMock
invocation
)
throws
Throwable
{
...
...
@@ -215,15 +186,8 @@ public final class CronetDataSourceTest {
mockResponseStartSuccess
();
dataSourceUnderTest
.
open
(
testDataSpec
);
verify
(
mockCronetEngine
).
createRequest
(
eq
(
TEST_URL
),
any
(
UrlRequest
.
Callback
.
class
),
any
(
Executor
.
class
),
anyInt
(),
eq
(
Collections
.
emptyList
()),
any
(
Boolean
.
class
),
any
(
Boolean
.
class
),
any
(
Boolean
.
class
));
verify
(
mockCronetEngine
)
.
newUrlRequestBuilder
(
eq
(
TEST_URL
),
any
(
UrlRequest
.
Callback
.
class
),
any
(
Executor
.
class
));
verify
(
mockUrlRequest
).
start
();
}
...
...
@@ -237,9 +201,9 @@ public final class CronetDataSourceTest {
dataSourceUnderTest
.
open
(
testDataSpec
);
// The header value to add is current position to current position + length - 1.
verify
(
mockUrlRequest
).
addHeader
(
"Range"
,
"bytes=1000-5999"
);
verify
(
mockUrlRequest
).
addHeader
(
"firstHeader"
,
"firstValue"
);
verify
(
mockUrlRequest
).
addHeader
(
"secondHeader"
,
"secondValue"
);
verify
(
mockUrlRequest
Builder
).
addHeader
(
"Range"
,
"bytes=1000-5999"
);
verify
(
mockUrlRequest
Builder
).
addHeader
(
"firstHeader"
,
"firstValue"
);
verify
(
mockUrlRequest
Builder
).
addHeader
(
"secondHeader"
,
"secondValue"
);
verify
(
mockUrlRequest
).
start
();
}
...
...
extensions/cronet/src/main/java/com/google/android/exoplayer2/ext/cronet/CronetDataSource.java
View file @
6673483a
...
...
@@ -412,8 +412,8 @@ public class CronetDataSource extends UrlRequest.Callback implements HttpDataSou
// Internal methods.
private
UrlRequest
buildRequest
(
DataSpec
dataSpec
)
throws
OpenException
{
UrlRequest
.
Builder
requestBuilder
=
new
UrlRequest
.
Builder
(
dataSpec
.
uri
.
toString
(),
this
,
executor
,
cronetEngine
);
UrlRequest
.
Builder
requestBuilder
=
cronetEngine
.
newUrlRequestBuilder
(
dataSpec
.
uri
.
toString
()
,
this
,
executor
);
// Set the headers.
synchronized
(
requestProperties
)
{
if
(
dataSpec
.
postBody
!=
null
&&
dataSpec
.
postBody
.
length
!=
0
...
...
extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSource.java
View file @
6673483a
...
...
@@ -65,7 +65,7 @@ public class OkHttpDataSource implements HttpDataSource {
private
long
bytesRead
;
/**
* @param callFactory A
n
{@link Call.Factory} for use by the source.
* @param callFactory A {@link Call.Factory} for use by the source.
* @param userAgent The User-Agent string that should be used.
* @param contentTypePredicate An optional {@link Predicate}. If a content type is rejected by the
* predicate then a InvalidContentTypeException} is thrown from {@link #open(DataSpec)}.
...
...
@@ -76,7 +76,7 @@ public class OkHttpDataSource implements HttpDataSource {
}
/**
* @param callFactory A
n
{@link Call.Factory} for use by the source.
* @param callFactory A {@link Call.Factory} for use by the source.
* @param userAgent The User-Agent string that should be used.
* @param contentTypePredicate An optional {@link Predicate}. If a content type is rejected by the
* predicate then a {@link InvalidContentTypeException} is thrown from
...
...
library/src/androidTest/java/com/google/android/exoplayer2/upstream/cache/CacheDataSourceTest.java
View file @
6673483a
...
...
@@ -177,8 +177,7 @@ public class CacheDataSourceTest extends InstrumentationTestCase {
builder
.
setSimulateUnknownLength
(
simulateUnknownLength
);
builder
.
appendReadData
(
TEST_DATA
);
FakeDataSource
upstream
=
builder
.
build
();
return
new
CacheDataSource
(
simpleCache
,
upstream
,
CacheDataSource
.
FLAG_BLOCK_ON_CACHE
|
CacheDataSource
.
FLAG_CACHE_UNBOUNDED_REQUESTS
,
return
new
CacheDataSource
(
simpleCache
,
upstream
,
CacheDataSource
.
FLAG_BLOCK_ON_CACHE
,
MAX_CACHE_FILE_SIZE
);
}
...
...
library/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java
View file @
6673483a
...
...
@@ -23,7 +23,7 @@ public interface ExoPlayerLibraryInfo {
/**
* The version of the library, expressed as a string.
*/
String
VERSION
=
"2.0.
3
"
;
String
VERSION
=
"2.0.
4
"
;
/**
* The version of the library, expressed as an integer.
...
...
@@ -32,7 +32,7 @@ public interface ExoPlayerLibraryInfo {
* corresponding integer version 1002003 (001-002-003), and "123.45.6" has the corresponding
* integer version 123045006 (123-045-006).
*/
int
VERSION_INT
=
200000
3
;
int
VERSION_INT
=
200000
4
;
/**
* Whether the library was compiled with {@link com.google.android.exoplayer2.util.Assertions}
...
...
library/src/main/java/com/google/android/exoplayer2/extractor/ts/H265Reader.java
View file @
6673483a
...
...
@@ -44,6 +44,7 @@ import java.util.Collections;
private
static
final
int
SUFFIX_SEI_NUT
=
40
;
private
TrackOutput
output
;
private
SampleReader
sampleReader
;
private
SeiReader
seiReader
;
// State that should not be reset on seek.
...
...
@@ -56,7 +57,6 @@ import java.util.Collections;
private
final
NalUnitTargetBuffer
pps
;
private
final
NalUnitTargetBuffer
prefixSei
;
private
final
NalUnitTargetBuffer
suffixSei
;
// TODO: Are both needed?
private
final
SampleReader
sampleReader
;
private
long
totalBytesWritten
;
// Per packet state that gets reset at the start of each packet.
...
...
@@ -72,7 +72,6 @@ import java.util.Collections;
pps
=
new
NalUnitTargetBuffer
(
PPS_NUT
,
128
);
prefixSei
=
new
NalUnitTargetBuffer
(
PREFIX_SEI_NUT
,
128
);
suffixSei
=
new
NalUnitTargetBuffer
(
SUFFIX_SEI_NUT
,
128
);
sampleReader
=
new
SampleReader
(
output
);
seiWrapper
=
new
ParsableByteArray
();
}
...
...
@@ -91,6 +90,7 @@ import java.util.Collections;
@Override
public
void
init
(
ExtractorOutput
extractorOutput
,
TrackIdGenerator
idGenerator
)
{
output
=
extractorOutput
.
track
(
idGenerator
.
getNextId
());
sampleReader
=
new
SampleReader
(
output
);
seiReader
=
new
SeiReader
(
extractorOutput
.
track
(
idGenerator
.
getNextId
()));
}
...
...
library/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java
View file @
6673483a
...
...
@@ -39,7 +39,6 @@ import com.google.android.exoplayer2.upstream.Loader;
import
com.google.android.exoplayer2.upstream.Loader.Loadable
;
import
com.google.android.exoplayer2.util.Assertions
;
import
com.google.android.exoplayer2.util.ConditionVariable
;
import
com.google.android.exoplayer2.util.Util
;
import
java.io.EOFException
;
import
java.io.IOException
;
...
...
@@ -593,8 +592,7 @@ import java.io.IOException;
ExtractorInput
input
=
null
;
try
{
long
position
=
positionHolder
.
position
;
length
=
dataSource
.
open
(
new
DataSpec
(
uri
,
position
,
C
.
LENGTH_UNSET
,
Util
.
sha1
(
uri
.
toString
())));
length
=
dataSource
.
open
(
new
DataSpec
(
uri
,
position
,
C
.
LENGTH_UNSET
,
null
));
if
(
length
!=
C
.
LENGTH_UNSET
)
{
length
+=
position
;
}
...
...
library/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java
View file @
6673483a
...
...
@@ -124,7 +124,7 @@ public final class DashMediaSource implements MediaSource {
this
.
minLoadableRetryCount
=
minLoadableRetryCount
;
this
.
livePresentationDelayMs
=
livePresentationDelayMs
;
eventDispatcher
=
new
EventDispatcher
(
eventHandler
,
eventListener
);
manifestParser
=
new
DashManifestParser
(
generateContentId
()
);
manifestParser
=
new
DashManifestParser
();
manifestCallback
=
new
ManifestCallback
();
manifestUriLock
=
new
Object
();
periodsById
=
new
SparseArray
<>();
...
...
@@ -468,10 +468,6 @@ public final class DashMediaSource implements MediaSource {
}
}
private
String
generateContentId
()
{
return
Util
.
sha1
(
manifestUri
.
toString
());
}
private
static
final
class
PeriodSeekInfo
{
public
static
PeriodSeekInfo
createPeriodSeekInfo
(
...
...
library/src/main/java/com/google/android/exoplayer2/source/dash/manifest/Representation.java
View file @
6673483a
...
...
@@ -57,7 +57,6 @@ public abstract class Representation {
*/
public
final
long
presentationTimeOffsetUs
;
private
final
String
cacheKey
;
private
final
RangedUri
initializationUri
;
/**
...
...
@@ -81,7 +80,8 @@ public abstract class Representation {
* @param revisionId Identifies the revision of the content.
* @param format The format of the representation.
* @param segmentBase A segment base element for the representation.
* @param customCacheKey A custom value to be returned from {@link #getCacheKey()}, or null.
* @param customCacheKey A custom value to be returned from {@link #getCacheKey()}, or null. This
* parameter is ignored if {@code segmentBase} consists of multiple segments.
* @return The constructed instance.
*/
public
static
Representation
newInstance
(
String
contentId
,
long
revisionId
,
Format
format
,
...
...
@@ -91,7 +91,7 @@ public abstract class Representation {
(
SingleSegmentBase
)
segmentBase
,
customCacheKey
,
C
.
LENGTH_UNSET
);
}
else
if
(
segmentBase
instanceof
MultiSegmentBase
)
{
return
new
MultiSegmentRepresentation
(
contentId
,
revisionId
,
format
,
(
MultiSegmentBase
)
segmentBase
,
customCacheKey
);
(
MultiSegmentBase
)
segmentBase
);
}
else
{
throw
new
IllegalArgumentException
(
"segmentBase must be of type SingleSegmentBase or "
+
"MultiSegmentBase"
);
...
...
@@ -99,12 +99,10 @@ public abstract class Representation {
}
private
Representation
(
String
contentId
,
long
revisionId
,
Format
format
,
SegmentBase
segmentBase
,
String
customCacheKey
)
{
SegmentBase
segmentBase
)
{
this
.
contentId
=
contentId
;
this
.
revisionId
=
revisionId
;
this
.
format
=
format
;
this
.
cacheKey
=
customCacheKey
!=
null
?
customCacheKey
:
contentId
+
"."
+
format
.
id
+
"."
+
revisionId
;
initializationUri
=
segmentBase
.
getInitialization
(
this
);
presentationTimeOffsetUs
=
segmentBase
.
getPresentationTimeOffsetUs
();
}
...
...
@@ -129,12 +127,10 @@ public abstract class Representation {
public
abstract
DashSegmentIndex
getIndex
();
/**
* Returns a cache key for the representation
, in the format
*
{@code contentId + "." + format.id + "." + revisionId}
.
* Returns a cache key for the representation
if a custom cache key or content id has been
*
provided and there is only single segment
.
*/
public
String
getCacheKey
()
{
return
cacheKey
;
}
public
abstract
String
getCacheKey
();
/**
* A DASH representation consisting of a single segment.
...
...
@@ -151,6 +147,7 @@ public abstract class Representation {
*/
public
final
long
contentLength
;
private
final
String
cacheKey
;
private
final
RangedUri
indexUri
;
private
final
SingleSegmentIndex
segmentIndex
;
...
...
@@ -187,9 +184,11 @@ public abstract class Representation {
*/
public
SingleSegmentRepresentation
(
String
contentId
,
long
revisionId
,
Format
format
,
SingleSegmentBase
segmentBase
,
String
customCacheKey
,
long
contentLength
)
{
super
(
contentId
,
revisionId
,
format
,
segmentBase
,
customCacheKey
);
super
(
contentId
,
revisionId
,
format
,
segmentBase
);
this
.
uri
=
Uri
.
parse
(
segmentBase
.
uri
);
this
.
indexUri
=
segmentBase
.
getIndex
();
this
.
cacheKey
=
customCacheKey
!=
null
?
customCacheKey
:
contentId
!=
null
?
contentId
+
"."
+
format
.
id
+
"."
+
revisionId
:
null
;
this
.
contentLength
=
contentLength
;
// If we have an index uri then the index is defined externally, and we shouldn't return one
// directly. If we don't, then we can't do better than an index defining a single segment.
...
...
@@ -207,6 +206,11 @@ public abstract class Representation {
return
segmentIndex
;
}
@Override
public
String
getCacheKey
()
{
return
cacheKey
;
}
}
/**
...
...
@@ -222,11 +226,10 @@ public abstract class Representation {
* @param revisionId Identifies the revision of the content.
* @param format The format of the representation.
* @param segmentBase The segment base underlying the representation.
* @param customCacheKey A custom value to be returned from {@link #getCacheKey()}, or null.
*/
public
MultiSegmentRepresentation
(
String
contentId
,
long
revisionId
,
Format
format
,
MultiSegmentBase
segmentBase
,
String
customCacheKey
)
{
super
(
contentId
,
revisionId
,
format
,
segmentBase
,
customCacheKey
);
MultiSegmentBase
segmentBase
)
{
super
(
contentId
,
revisionId
,
format
,
segmentBase
);
this
.
segmentBase
=
segmentBase
;
}
...
...
@@ -240,6 +243,11 @@ public abstract class Representation {
return
this
;
}
@Override
public
String
getCacheKey
()
{
return
null
;
}
// DashSegmentIndex implementation.
@Override
...
...
library/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java
View file @
6673483a
...
...
@@ -440,6 +440,10 @@ import java.util.Locale;
}
HlsMediaPlaylist
oldMediaPlaylist
=
variantPlaylists
[
oldVariantIndex
];
HlsMediaPlaylist
newMediaPlaylist
=
variantPlaylists
[
newVariantIndex
];
if
(
previousChunkIndex
<
oldMediaPlaylist
.
mediaSequence
)
{
// We have fallen behind the live window.
return
newMediaPlaylist
.
mediaSequence
-
1
;
}
double
offsetToLiveInstantSecs
=
0
;
for
(
int
i
=
previousChunkIndex
-
oldMediaPlaylist
.
mediaSequence
;
i
<
oldMediaPlaylist
.
segments
.
size
();
i
++)
{
...
...
library/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java
View file @
6673483a
...
...
@@ -15,6 +15,7 @@
*/
package
com
.
google
.
android
.
exoplayer2
.
ui
;
import
android.annotation.TargetApi
;
import
android.content.Context
;
import
android.content.res.TypedArray
;
import
android.os.SystemClock
;
...
...
@@ -75,6 +76,7 @@ public class PlaybackControlView extends FrameLayout {
private
ExoPlayer
player
;
private
VisibilityListener
visibilityListener
;
private
boolean
isAttachedToWindow
;
private
boolean
dragging
;
private
int
rewindMs
;
private
int
fastForwardMs
;
...
...
@@ -264,7 +266,7 @@ public class PlaybackControlView extends FrameLayout {
removeCallbacks
(
hideAction
);
if
(
showTimeoutMs
>
0
)
{
hideAtMs
=
SystemClock
.
uptimeMillis
()
+
showTimeoutMs
;
if
(
isAttachedToWindow
()
)
{
if
(
isAttachedToWindow
)
{
postDelayed
(
hideAction
,
showTimeoutMs
);
}
}
else
{
...
...
@@ -279,7 +281,7 @@ public class PlaybackControlView extends FrameLayout {
}
private
void
updatePlayPauseButton
()
{
if
(!
isVisible
()
||
!
isAttachedToWindow
()
)
{
if
(!
isVisible
()
||
!
isAttachedToWindow
)
{
return
;
}
boolean
playing
=
player
!=
null
&&
player
.
getPlayWhenReady
();
...
...
@@ -291,7 +293,7 @@ public class PlaybackControlView extends FrameLayout {
}
private
void
updateNavigation
()
{
if
(!
isVisible
()
||
!
isAttachedToWindow
()
)
{
if
(!
isVisible
()
||
!
isAttachedToWindow
)
{
return
;
}
Timeline
currentTimeline
=
player
!=
null
?
player
.
getCurrentTimeline
()
:
null
;
...
...
@@ -315,7 +317,7 @@ public class PlaybackControlView extends FrameLayout {
}
private
void
updateProgress
()
{
if
(!
isVisible
()
||
!
isAttachedToWindow
()
)
{
if
(!
isVisible
()
||
!
isAttachedToWindow
)
{
return
;
}
long
duration
=
player
==
null
?
0
:
player
.
getDuration
();
...
...
@@ -350,13 +352,18 @@ public class PlaybackControlView extends FrameLayout {
private
void
setButtonEnabled
(
boolean
enabled
,
View
view
)
{
view
.
setEnabled
(
enabled
);
if
(
Util
.
SDK_INT
>=
11
)
{
view
.
setAlpha
(
enabled
?
1
f
:
0.3f
);
setViewAlphaV11
(
view
,
enabled
?
1
f
:
0.3f
);
view
.
setVisibility
(
VISIBLE
);
}
else
{
view
.
setVisibility
(
enabled
?
VISIBLE
:
INVISIBLE
);
}
}
@TargetApi
(
11
)
private
void
setViewAlphaV11
(
View
view
,
float
alpha
)
{
view
.
setAlpha
(
alpha
);
}
private
String
stringForTime
(
long
timeMs
)
{
if
(
timeMs
==
C
.
TIME_UNSET
)
{
timeMs
=
0
;
...
...
@@ -426,6 +433,7 @@ public class PlaybackControlView extends FrameLayout {
@Override
public
void
onAttachedToWindow
()
{
super
.
onAttachedToWindow
();
isAttachedToWindow
=
true
;
if
(
hideAtMs
!=
C
.
TIME_UNSET
)
{
long
delayMs
=
hideAtMs
-
SystemClock
.
uptimeMillis
();
if
(
delayMs
<=
0
)
{
...
...
@@ -440,6 +448,7 @@ public class PlaybackControlView extends FrameLayout {
@Override
public
void
onDetachedFromWindow
()
{
super
.
onDetachedFromWindow
();
isAttachedToWindow
=
false
;
removeCallbacks
(
updateProgressAction
);
removeCallbacks
(
hideAction
);
}
...
...
library/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSource.java
View file @
6673483a
...
...
@@ -26,6 +26,7 @@ import com.google.android.exoplayer2.upstream.DataSpec;
import
com.google.android.exoplayer2.upstream.FileDataSource
;
import
com.google.android.exoplayer2.upstream.TeeDataSource
;
import
com.google.android.exoplayer2.upstream.cache.CacheDataSink.CacheDataSinkException
;
import
com.google.android.exoplayer2.util.Util
;
import
java.io.IOException
;
import
java.io.InterruptedIOException
;
import
java.lang.annotation.Retention
;
...
...
@@ -50,8 +51,7 @@ public final class CacheDataSource implements DataSource {
* Flags controlling the cache's behavior.
*/
@Retention
(
RetentionPolicy
.
SOURCE
)
@IntDef
(
flag
=
true
,
value
=
{
FLAG_BLOCK_ON_CACHE
,
FLAG_IGNORE_CACHE_ON_ERROR
,
FLAG_CACHE_UNBOUNDED_REQUESTS
})
@IntDef
(
flag
=
true
,
value
=
{
FLAG_BLOCK_ON_CACHE
,
FLAG_IGNORE_CACHE_ON_ERROR
})
public
@interface
Flags
{}
/**
* A flag indicating whether we will block reads if the cache key is locked. If this flag is
...
...
@@ -67,13 +67,6 @@ public final class CacheDataSource implements DataSource {
public
static
final
int
FLAG_IGNORE_CACHE_ON_ERROR
=
1
<<
1
;
/**
* A flag indicating whether the response is cached if the range of the request is unbounded.
* Disabled by default because, as a side effect, this may allow streams with every chunk from a
* separate URL cached which is broken currently.
*/
public
static
final
int
FLAG_CACHE_UNBOUNDED_REQUESTS
=
1
<<
2
;
/**
* Listener of {@link CacheDataSource} events.
*/
public
interface
EventListener
{
...
...
@@ -98,7 +91,6 @@ public final class CacheDataSource implements DataSource {
private
final
boolean
blockOnCache
;
private
final
boolean
ignoreCacheOnError
;
private
final
boolean
bypassUnboundedRequests
;
private
DataSource
currentDataSource
;
private
boolean
currentRequestUnbounded
;
...
...
@@ -127,8 +119,8 @@ public final class CacheDataSource implements DataSource {
*
* @param cache The cache.
* @param upstream A {@link DataSource} for reading data not in the cache.
* @param flags A combination of {@link #FLAG_BLOCK_ON_CACHE}
, {@link #FLAG_IGNORE_CACHE_ON_ERROR}
*
and {@link #FLAG_CACHE_UNBOUNDED_REQUESTS
} or 0.
* @param flags A combination of {@link #FLAG_BLOCK_ON_CACHE}
and {@link
*
#FLAG_IGNORE_CACHE_ON_ERROR
} or 0.
* @param maxCacheFileSize The maximum size of a cache file, in bytes. If the cached data size
* exceeds this value, then the data will be fragmented into multiple cache files. The
* finer-grained this is the finer-grained the eviction policy can be.
...
...
@@ -148,8 +140,8 @@ public final class CacheDataSource implements DataSource {
* @param upstream A {@link DataSource} for reading data not in the cache.
* @param cacheReadDataSource A {@link DataSource} for reading data from the cache.
* @param cacheWriteDataSink A {@link DataSink} for writing data to the cache.
* @param flags A combination of {@link #FLAG_BLOCK_ON_CACHE}
, {@link #FLAG_IGNORE_CACHE_ON_ERROR}
*
and {@link #FLAG_CACHE_UNBOUNDED_REQUESTS
} or 0.
* @param flags A combination of {@link #FLAG_BLOCK_ON_CACHE}
and {@link
*
#FLAG_IGNORE_CACHE_ON_ERROR
} or 0.
* @param eventListener An optional {@link EventListener} to receive events.
*/
public
CacheDataSource
(
Cache
cache
,
DataSource
upstream
,
DataSource
cacheReadDataSource
,
...
...
@@ -158,7 +150,6 @@ public final class CacheDataSource implements DataSource {
this
.
cacheReadDataSource
=
cacheReadDataSource
;
this
.
blockOnCache
=
(
flags
&
FLAG_BLOCK_ON_CACHE
)
!=
0
;
this
.
ignoreCacheOnError
=
(
flags
&
FLAG_IGNORE_CACHE_ON_ERROR
)
!=
0
;
this
.
bypassUnboundedRequests
=
(
flags
&
FLAG_CACHE_UNBOUNDED_REQUESTS
)
==
0
;
this
.
upstreamDataSource
=
upstream
;
if
(
cacheWriteDataSink
!=
null
)
{
this
.
cacheWriteDataSource
=
new
TeeDataSource
(
upstream
,
cacheWriteDataSink
);
...
...
@@ -173,10 +164,9 @@ public final class CacheDataSource implements DataSource {
try
{
uri
=
dataSpec
.
uri
;
flags
=
dataSpec
.
flags
;
key
=
dataSpec
.
key
;
key
=
dataSpec
.
key
!=
null
?
dataSpec
.
key
:
Util
.
sha1
(
uri
.
toString
())
;
readPosition
=
dataSpec
.
position
;
currentRequestIgnoresCache
=
(
ignoreCacheOnError
&&
seenCacheError
)
||
(
bypassUnboundedRequests
&&
dataSpec
.
length
==
C
.
LENGTH_UNSET
);
currentRequestIgnoresCache
=
ignoreCacheOnError
&&
seenCacheError
;
if
(
dataSpec
.
length
!=
C
.
LENGTH_UNSET
||
currentRequestIgnoresCache
)
{
bytesRemaining
=
dataSpec
.
length
;
}
else
{
...
...
playbacktests/src/main/AndroidManifest.xml
View file @
6673483a
...
...
@@ -17,8 +17,8 @@
<manifest
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:tools=
"http://schemas.android.com/tools"
package=
"com.google.android.exoplayer2.playbacktests"
android:versionCode=
"200
3
"
android:versionName=
"2.0.
3
"
>
android:versionCode=
"200
4
"
android:versionName=
"2.0.
4
"
>
<uses-permission
android:name=
"android.permission.INTERNET"
/>
<uses-permission
android:name=
"android.permission.WAKE_LOCK"
/>
...
...
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