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
9f814850
authored
May 23, 2017
by
ojw28
Committed by
GitHub
May 23, 2017
Browse files
Options
_('Browse Files')
Download
Plain Diff
Merge pull request #2860 from google/dev-2.4.1-rc
r2.4.1
parents
d9794696
fe504594
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
51 changed files
with
787 additions
and
201 deletions
RELEASENOTES.md
build.gradle
demo/src/main/AndroidManifest.xml
demo/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java
extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.java
extensions/vp9/src/main/jni/generate_libvpx_android_configs.sh
library/core/src/androidTest/assets/ogg/bear_vorbis.ogg.0.dump
library/core/src/androidTest/assets/ogg/bear_vorbis.ogg.1.dump
library/core/src/androidTest/assets/ogg/bear_vorbis.ogg.2.dump
library/core/src/androidTest/assets/ogg/bear_vorbis.ogg.3.dump
library/core/src/androidTest/assets/ogg/bear_vorbis.ogg.unklen.dump
library/core/src/androidTest/java/com/google/android/exoplayer2/extractor/ts/TsExtractorTest.java
library/core/src/androidTest/java/com/google/android/exoplayer2/text/ttml/TtmlDecoderTest.java
library/core/src/main/java/com/google/android/exoplayer2/BaseRenderer.java
library/core/src/main/java/com/google/android/exoplayer2/ExoPlayer.java
library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerFactory.java
library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java
library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java
library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java
library/core/src/main/java/com/google/android/exoplayer2/audio/Sonic.java
library/core/src/main/java/com/google/android/exoplayer2/decoder/SimpleOutputBuffer.java
library/core/src/main/java/com/google/android/exoplayer2/extractor/DefaultExtractorsFactory.java
library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggPacket.java
library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/StreamReader.java
library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/VorbisReader.java
library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java
library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java
library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java
library/core/src/main/java/com/google/android/exoplayer2/metadata/MetadataRenderer.java
library/core/src/main/java/com/google/android/exoplayer2/text/TextRenderer.java
library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlDecoder.java
library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlNode.java
library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlRegion.java
library/core/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java
library/core/src/main/java/com/google/android/exoplayer2/upstream/Loader.java
library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSource.java
library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSourceFactory.java
library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheUtil.java
library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/SimpleCache.java
library/core/src/main/java/com/google/android/exoplayer2/video/DummySurface.java
library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java
library/hls/src/androidTest/java/com/google/android/exoplayer2/source/hls/playlist/HlsMasterPlaylistParserTest.java
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunk.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/playlist/HlsMasterPlaylist.java
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMediaPlaylist.java
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistTracker.java
library/ui/src/main/java/com/google/android/exoplayer2/ui/DefaultTimeBar.java
library/ui/src/main/res/values/attrs.xml
RELEASENOTES.md
View file @
9f814850
# Release notes #
# Release notes #
### r2.4.1 ###
*
Stability: Avoid OutOfMemoryError in extractors when parsing malformed media
(
[
#2780
](
https://github.com/google/ExoPlayer/issues/2780
)
).
*
Stability: Avoid native crash on Galaxy Nexus. Avoid unnecessarily large codec
input buffer allocations on all devices
(
[
#2607
](
https://github.com/google/ExoPlayer/issues/2607
)
).
*
Variable speed playback: Fix interpolation for rate/pitch adjustment
(
[
#2774
](
https://github.com/google/ExoPlayer/issues/2774
)
).
*
HLS: Include EXT-X-DATERANGE tags in HlsMediaPlaylist.
*
HLS: Don't expose CEA-608 track if CLOSED-CAPTIONS=NONE
(
[
#2743
](
https://github.com/google/ExoPlayer/issues/2743
)
).
*
HLS: Correctly propagate errors loading the media playlist
(
[
#2623
](
https://github.com/google/ExoPlayer/issues/2623
)
).
*
UI: DefaultTimeBar enhancements and bug fixes
(
[
#2740
](
https://github.com/google/ExoPlayer/issues/2740
)
).
*
Ogg: Fix failure to play some Ogg files
(
[
#2782
](
https://github.com/google/ExoPlayer/issues/2782
)
).
*
Captions: Don't select text tack with no language by default.
*
Captions: TTML positioning fixes
(
[
#2824
](
https://github.com/google/ExoPlayer/issues/2824
)
).
*
Misc bugfixes.
### r2.4.0 ###
### r2.4.0 ###
*
New modular library structure. You can read more about depending on individual
*
New modular library structure. You can read more about depending on individual
...
...
build.gradle
View file @
9f814850
...
@@ -16,7 +16,7 @@ buildscript {
...
@@ -16,7 +16,7 @@ buildscript {
jcenter
()
jcenter
()
}
}
dependencies
{
dependencies
{
classpath
'com.android.tools.build:gradle:2.3.
0
'
classpath
'com.android.tools.build:gradle:2.3.
1
'
classpath
'com.novoda:bintray-release:0.4.0'
classpath
'com.novoda:bintray-release:0.4.0'
}
}
// Workaround for the following test coverage issue. Remove when fixed:
// Workaround for the following test coverage issue. Remove when fixed:
...
@@ -48,7 +48,7 @@ allprojects {
...
@@ -48,7 +48,7 @@ allprojects {
releaseRepoName
=
getBintrayRepo
()
releaseRepoName
=
getBintrayRepo
()
releaseUserOrg
=
'google'
releaseUserOrg
=
'google'
releaseGroupId
=
'com.google.android.exoplayer'
releaseGroupId
=
'com.google.android.exoplayer'
releaseVersion
=
'r2.4.
0
'
releaseVersion
=
'r2.4.
1
'
releaseWebsite
=
'https://github.com/google/ExoPlayer'
releaseWebsite
=
'https://github.com/google/ExoPlayer'
}
}
if
(
it
.
hasProperty
(
'externalBuildDir'
))
{
if
(
it
.
hasProperty
(
'externalBuildDir'
))
{
...
...
demo/src/main/AndroidManifest.xml
View file @
9f814850
...
@@ -16,8 +16,8 @@
...
@@ -16,8 +16,8 @@
<manifest
xmlns:android=
"http://schemas.android.com/apk/res/android"
<manifest
xmlns:android=
"http://schemas.android.com/apk/res/android"
package=
"com.google.android.exoplayer2.demo"
package=
"com.google.android.exoplayer2.demo"
android:versionCode=
"240
0
"
android:versionCode=
"240
1
"
android:versionName=
"2.4.
0
"
>
android:versionName=
"2.4.
1
"
>
<uses-permission
android:name=
"android.permission.INTERNET"
/>
<uses-permission
android:name=
"android.permission.INTERNET"
/>
<uses-permission
android:name=
"android.permission.READ_EXTERNAL_STORAGE"
/>
<uses-permission
android:name=
"android.permission.READ_EXTERNAL_STORAGE"
/>
...
...
demo/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java
View file @
9f814850
...
@@ -234,7 +234,6 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay
...
@@ -234,7 +234,6 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay
Intent
intent
=
getIntent
();
Intent
intent
=
getIntent
();
boolean
needNewPlayer
=
player
==
null
;
boolean
needNewPlayer
=
player
==
null
;
if
(
needNewPlayer
)
{
if
(
needNewPlayer
)
{
boolean
preferExtensionDecoders
=
intent
.
getBooleanExtra
(
PREFER_EXTENSION_DECODERS
,
false
);
UUID
drmSchemeUuid
=
intent
.
hasExtra
(
DRM_SCHEME_UUID_EXTRA
)
UUID
drmSchemeUuid
=
intent
.
hasExtra
(
DRM_SCHEME_UUID_EXTRA
)
?
UUID
.
fromString
(
intent
.
getStringExtra
(
DRM_SCHEME_UUID_EXTRA
))
:
null
;
?
UUID
.
fromString
(
intent
.
getStringExtra
(
DRM_SCHEME_UUID_EXTRA
))
:
null
;
DrmSessionManager
<
FrameworkMediaCrypto
>
drmSessionManager
=
null
;
DrmSessionManager
<
FrameworkMediaCrypto
>
drmSessionManager
=
null
;
...
@@ -253,6 +252,7 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay
...
@@ -253,6 +252,7 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay
}
}
}
}
boolean
preferExtensionDecoders
=
intent
.
getBooleanExtra
(
PREFER_EXTENSION_DECODERS
,
false
);
@DefaultRenderersFactory
.
ExtensionRendererMode
int
extensionRendererMode
=
@DefaultRenderersFactory
.
ExtensionRendererMode
int
extensionRendererMode
=
((
DemoApplication
)
getApplication
()).
useExtensionRenderers
()
((
DemoApplication
)
getApplication
()).
useExtensionRenderers
()
?
(
preferExtensionDecoders
?
DefaultRenderersFactory
.
EXTENSION_RENDERER_MODE_PREFER
?
(
preferExtensionDecoders
?
DefaultRenderersFactory
.
EXTENSION_RENDERER_MODE_PREFER
...
@@ -261,10 +261,10 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay
...
@@ -261,10 +261,10 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay
DefaultRenderersFactory
renderersFactory
=
new
DefaultRenderersFactory
(
this
,
DefaultRenderersFactory
renderersFactory
=
new
DefaultRenderersFactory
(
this
,
drmSessionManager
,
extensionRendererMode
);
drmSessionManager
,
extensionRendererMode
);
TrackSelection
.
Factory
video
TrackSelectionFactory
=
TrackSelection
.
Factory
adaptive
TrackSelectionFactory
=
new
AdaptiveTrackSelection
.
Factory
(
BANDWIDTH_METER
);
new
AdaptiveTrackSelection
.
Factory
(
BANDWIDTH_METER
);
trackSelector
=
new
DefaultTrackSelector
(
video
TrackSelectionFactory
);
trackSelector
=
new
DefaultTrackSelector
(
adaptive
TrackSelectionFactory
);
trackSelectionHelper
=
new
TrackSelectionHelper
(
trackSelector
,
video
TrackSelectionFactory
);
trackSelectionHelper
=
new
TrackSelectionHelper
(
trackSelector
,
adaptive
TrackSelectionFactory
);
lastSeenTrackGroupArray
=
null
;
lastSeenTrackGroupArray
=
null
;
player
=
ExoPlayerFactory
.
newSimpleInstance
(
renderersFactory
,
trackSelector
);
player
=
ExoPlayerFactory
.
newSimpleInstance
(
renderersFactory
,
trackSelector
);
...
...
extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.java
View file @
9f814850
...
@@ -286,7 +286,7 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
...
@@ -286,7 +286,7 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
*
*
* @param outputBufferTimeUs The timestamp of the current output buffer.
* @param outputBufferTimeUs The timestamp of the current output buffer.
* @param nextOutputBufferTimeUs The timestamp of the next output buffer or
* @param nextOutputBufferTimeUs The timestamp of the next output buffer or
* {@link TIME_UNSET} if the next output buffer is unavailable.
* {@link
C#
TIME_UNSET} if the next output buffer is unavailable.
* @param positionUs The current playback position.
* @param positionUs The current playback position.
* @param joiningDeadlineMs The joining deadline.
* @param joiningDeadlineMs The joining deadline.
* @return Returns whether to drop the current output buffer.
* @return Returns whether to drop the current output buffer.
...
...
extensions/vp9/src/main/jni/generate_libvpx_android_configs.sh
View file @
9f814850
...
@@ -51,8 +51,7 @@ config[3]+=" --disable-sse3 --disable-ssse3 --disable-sse4_1 --disable-avx"
...
@@ -51,8 +51,7 @@ config[3]+=" --disable-sse3 --disable-ssse3 --disable-sse4_1 --disable-avx"
config[3]+
=
" --disable-avx2 --enable-pic"
config[3]+
=
" --disable-avx2 --enable-pic"
arch[4]
=
"arm64-v8a"
arch[4]
=
"arm64-v8a"
config[4]
=
"--force-target=armv8-android-gcc --sdk-path=
$ndk
--disable-neon"
config[4]
=
"--force-target=armv8-android-gcc --sdk-path=
$ndk
--enable-neon"
config[4]+
=
" --disable-neon-asm"
arch[5]
=
"x86_64"
arch[5]
=
"x86_64"
config[5]
=
"--force-target=x86_64-android-gcc --sdk-path=
$ndk
--disable-sse2"
config[5]
=
"--force-target=x86_64-android-gcc --sdk-path=
$ndk
--disable-sse2"
...
...
library/core/src/androidTest/assets/ogg/bear_vorbis.ogg.0.dump
View file @
9f814850
...
@@ -9,7 +9,7 @@ track 0:
...
@@ -9,7 +9,7 @@ track 0:
id = null
id = null
containerMimeType = null
containerMimeType = null
sampleMimeType = audio/vorbis
sampleMimeType = audio/vorbis
maxInputSize =
65025
maxInputSize =
-1
width = -1
width = -1
height = -1
height = -1
frameRate = -1.0
frameRate = -1.0
...
...
library/core/src/androidTest/assets/ogg/bear_vorbis.ogg.1.dump
View file @
9f814850
...
@@ -9,7 +9,7 @@ track 0:
...
@@ -9,7 +9,7 @@ track 0:
id = null
id = null
containerMimeType = null
containerMimeType = null
sampleMimeType = audio/vorbis
sampleMimeType = audio/vorbis
maxInputSize =
65025
maxInputSize =
-1
width = -1
width = -1
height = -1
height = -1
frameRate = -1.0
frameRate = -1.0
...
...
library/core/src/androidTest/assets/ogg/bear_vorbis.ogg.2.dump
View file @
9f814850
...
@@ -9,7 +9,7 @@ track 0:
...
@@ -9,7 +9,7 @@ track 0:
id = null
id = null
containerMimeType = null
containerMimeType = null
sampleMimeType = audio/vorbis
sampleMimeType = audio/vorbis
maxInputSize =
65025
maxInputSize =
-1
width = -1
width = -1
height = -1
height = -1
frameRate = -1.0
frameRate = -1.0
...
...
library/core/src/androidTest/assets/ogg/bear_vorbis.ogg.3.dump
View file @
9f814850
...
@@ -9,7 +9,7 @@ track 0:
...
@@ -9,7 +9,7 @@ track 0:
id = null
id = null
containerMimeType = null
containerMimeType = null
sampleMimeType = audio/vorbis
sampleMimeType = audio/vorbis
maxInputSize =
65025
maxInputSize =
-1
width = -1
width = -1
height = -1
height = -1
frameRate = -1.0
frameRate = -1.0
...
...
library/core/src/androidTest/assets/ogg/bear_vorbis.ogg.unklen.dump
View file @
9f814850
...
@@ -9,7 +9,7 @@ track 0:
...
@@ -9,7 +9,7 @@ track 0:
id = null
id = null
containerMimeType = null
containerMimeType = null
sampleMimeType = audio/vorbis
sampleMimeType = audio/vorbis
maxInputSize =
65025
maxInputSize =
-1
width = -1
width = -1
height = -1
height = -1
frameRate = -1.0
frameRate = -1.0
...
...
library/core/src/androidTest/java/com/google/android/exoplayer2/extractor/ts/TsExtractorTest.java
View file @
9f814850
...
@@ -75,7 +75,7 @@ public final class TsExtractorTest extends InstrumentationTestCase {
...
@@ -75,7 +75,7 @@ public final class TsExtractorTest extends InstrumentationTestCase {
public
void
testCustomPesReader
()
throws
Exception
{
public
void
testCustomPesReader
()
throws
Exception
{
CustomTsPayloadReaderFactory
factory
=
new
CustomTsPayloadReaderFactory
(
true
,
false
);
CustomTsPayloadReaderFactory
factory
=
new
CustomTsPayloadReaderFactory
(
true
,
false
);
TsExtractor
tsExtractor
=
new
TsExtractor
(
TsExtractor
.
MODE_
NORMAL
,
new
TimestampAdjuster
(
0
),
TsExtractor
tsExtractor
=
new
TsExtractor
(
TsExtractor
.
MODE_
MULTI_PMT
,
new
TimestampAdjuster
(
0
),
factory
);
factory
);
FakeExtractorInput
input
=
new
FakeExtractorInput
.
Builder
()
FakeExtractorInput
input
=
new
FakeExtractorInput
.
Builder
()
.
setData
(
TestUtil
.
getByteArray
(
getInstrumentation
(),
"ts/sample.ts"
))
.
setData
(
TestUtil
.
getByteArray
(
getInstrumentation
(),
"ts/sample.ts"
))
...
@@ -100,7 +100,7 @@ public final class TsExtractorTest extends InstrumentationTestCase {
...
@@ -100,7 +100,7 @@ public final class TsExtractorTest extends InstrumentationTestCase {
public
void
testCustomInitialSectionReader
()
throws
Exception
{
public
void
testCustomInitialSectionReader
()
throws
Exception
{
CustomTsPayloadReaderFactory
factory
=
new
CustomTsPayloadReaderFactory
(
false
,
true
);
CustomTsPayloadReaderFactory
factory
=
new
CustomTsPayloadReaderFactory
(
false
,
true
);
TsExtractor
tsExtractor
=
new
TsExtractor
(
TsExtractor
.
MODE_
NORMAL
,
new
TimestampAdjuster
(
0
),
TsExtractor
tsExtractor
=
new
TsExtractor
(
TsExtractor
.
MODE_
MULTI_PMT
,
new
TimestampAdjuster
(
0
),
factory
);
factory
);
FakeExtractorInput
input
=
new
FakeExtractorInput
.
Builder
()
FakeExtractorInput
input
=
new
FakeExtractorInput
.
Builder
()
.
setData
(
TestUtil
.
getByteArray
(
getInstrumentation
(),
"ts/sample_with_sdt.ts"
))
.
setData
(
TestUtil
.
getByteArray
(
getInstrumentation
(),
"ts/sample_with_sdt.ts"
))
...
...
library/core/src/androidTest/java/com/google/android/exoplayer2/text/ttml/TtmlDecoderTest.java
View file @
9f814850
...
@@ -157,39 +157,39 @@ public final class TtmlDecoderTest extends InstrumentationTestCase {
...
@@ -157,39 +157,39 @@ public final class TtmlDecoderTest extends InstrumentationTestCase {
assertEquals
(
2
,
output
.
size
());
assertEquals
(
2
,
output
.
size
());
Cue
ttmlCue
=
output
.
get
(
0
);
Cue
ttmlCue
=
output
.
get
(
0
);
assertEquals
(
"lorem"
,
ttmlCue
.
text
.
toString
());
assertEquals
(
"lorem"
,
ttmlCue
.
text
.
toString
());
assertEquals
(
10
.
f
/
100
.
f
,
ttmlCue
.
position
);
assertEquals
(
10
f
/
100
f
,
ttmlCue
.
position
);
assertEquals
(
10
.
f
/
100
.
f
,
ttmlCue
.
line
);
assertEquals
(
10
f
/
100
f
,
ttmlCue
.
line
);
assertEquals
(
20
.
f
/
100
.
f
,
ttmlCue
.
size
);
assertEquals
(
20
f
/
100
f
,
ttmlCue
.
size
);
ttmlCue
=
output
.
get
(
1
);
ttmlCue
=
output
.
get
(
1
);
assertEquals
(
"amet"
,
ttmlCue
.
text
.
toString
());
assertEquals
(
"amet"
,
ttmlCue
.
text
.
toString
());
assertEquals
(
60
.
f
/
100
.
f
,
ttmlCue
.
position
);
assertEquals
(
60
f
/
100
f
,
ttmlCue
.
position
);
assertEquals
(
10
.
f
/
100
.
f
,
ttmlCue
.
line
);
assertEquals
(
10
f
/
100
f
,
ttmlCue
.
line
);
assertEquals
(
20
.
f
/
100
.
f
,
ttmlCue
.
size
);
assertEquals
(
20
f
/
100
f
,
ttmlCue
.
size
);
output
=
subtitle
.
getCues
(
5000000
);
output
=
subtitle
.
getCues
(
5000000
);
assertEquals
(
1
,
output
.
size
());
assertEquals
(
1
,
output
.
size
());
ttmlCue
=
output
.
get
(
0
);
ttmlCue
=
output
.
get
(
0
);
assertEquals
(
"ipsum"
,
ttmlCue
.
text
.
toString
());
assertEquals
(
"ipsum"
,
ttmlCue
.
text
.
toString
());
assertEquals
(
40
.
f
/
100
.
f
,
ttmlCue
.
position
);
assertEquals
(
40
f
/
100
f
,
ttmlCue
.
position
);
assertEquals
(
40
.
f
/
100
.
f
,
ttmlCue
.
line
);
assertEquals
(
40
f
/
100
f
,
ttmlCue
.
line
);
assertEquals
(
20
.
f
/
100
.
f
,
ttmlCue
.
size
);
assertEquals
(
20
f
/
100
f
,
ttmlCue
.
size
);
output
=
subtitle
.
getCues
(
9000000
);
output
=
subtitle
.
getCues
(
9000000
);
assertEquals
(
1
,
output
.
size
());
assertEquals
(
1
,
output
.
size
());
ttmlCue
=
output
.
get
(
0
);
ttmlCue
=
output
.
get
(
0
);
assertEquals
(
"dolor"
,
ttmlCue
.
text
.
toString
());
assertEquals
(
"dolor"
,
ttmlCue
.
text
.
toString
());
assertEquals
(
10
.
f
/
100
.
f
,
ttmlCue
.
position
);
assertEquals
(
10
f
/
100
f
,
ttmlCue
.
position
);
assertEquals
(
80
.
f
/
100
.
f
,
ttmlCue
.
line
);
assertEquals
(
80
f
/
100
f
,
ttmlCue
.
line
);
assertEquals
(
Cue
.
DIMEN_UNSET
,
ttmlCue
.
size
);
assertEquals
(
1
f
,
ttmlCue
.
size
);
output
=
subtitle
.
getCues
(
21000000
);
output
=
subtitle
.
getCues
(
21000000
);
assertEquals
(
1
,
output
.
size
());
assertEquals
(
1
,
output
.
size
());
ttmlCue
=
output
.
get
(
0
);
ttmlCue
=
output
.
get
(
0
);
assertEquals
(
"She first said this"
,
ttmlCue
.
text
.
toString
());
assertEquals
(
"She first said this"
,
ttmlCue
.
text
.
toString
());
assertEquals
(
45
.
f
/
100
.
f
,
ttmlCue
.
position
);
assertEquals
(
45
f
/
100
f
,
ttmlCue
.
position
);
assertEquals
(
45
.
f
/
100
.
f
,
ttmlCue
.
line
);
assertEquals
(
45
f
/
100
f
,
ttmlCue
.
line
);
assertEquals
(
35
.
f
/
100
.
f
,
ttmlCue
.
size
);
assertEquals
(
35
f
/
100
f
,
ttmlCue
.
size
);
output
=
subtitle
.
getCues
(
25000000
);
output
=
subtitle
.
getCues
(
25000000
);
ttmlCue
=
output
.
get
(
0
);
ttmlCue
=
output
.
get
(
0
);
assertEquals
(
"She first said this\nThen this"
,
ttmlCue
.
text
.
toString
());
assertEquals
(
"She first said this\nThen this"
,
ttmlCue
.
text
.
toString
());
...
@@ -197,8 +197,8 @@ public final class TtmlDecoderTest extends InstrumentationTestCase {
...
@@ -197,8 +197,8 @@ public final class TtmlDecoderTest extends InstrumentationTestCase {
assertEquals
(
1
,
output
.
size
());
assertEquals
(
1
,
output
.
size
());
ttmlCue
=
output
.
get
(
0
);
ttmlCue
=
output
.
get
(
0
);
assertEquals
(
"She first said this\nThen this\nFinally this"
,
ttmlCue
.
text
.
toString
());
assertEquals
(
"She first said this\nThen this\nFinally this"
,
ttmlCue
.
text
.
toString
());
assertEquals
(
45
.
f
/
100
.
f
,
ttmlCue
.
position
);
assertEquals
(
45
f
/
100
f
,
ttmlCue
.
position
);
assertEquals
(
45
.
f
/
100
.
f
,
ttmlCue
.
line
);
assertEquals
(
45
f
/
100
f
,
ttmlCue
.
line
);
}
}
public
void
testEmptyStyleAttribute
()
throws
IOException
,
SubtitleDecoderException
{
public
void
testEmptyStyleAttribute
()
throws
IOException
,
SubtitleDecoderException
{
...
...
library/core/src/main/java/com/google/android/exoplayer2/BaseRenderer.java
View file @
9f814850
...
@@ -142,9 +142,9 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities {
...
@@ -142,9 +142,9 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities {
public
final
void
disable
()
{
public
final
void
disable
()
{
Assertions
.
checkState
(
state
==
STATE_ENABLED
);
Assertions
.
checkState
(
state
==
STATE_ENABLED
);
state
=
STATE_DISABLED
;
state
=
STATE_DISABLED
;
onDisabled
();
stream
=
null
;
stream
=
null
;
streamIsFinal
=
false
;
streamIsFinal
=
false
;
onDisabled
();
}
}
// RendererCapabilities implementation.
// RendererCapabilities implementation.
...
@@ -300,8 +300,6 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities {
...
@@ -300,8 +300,6 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities {
/**
/**
* Returns whether the upstream source is ready.
* Returns whether the upstream source is ready.
*
* @return Whether the source is ready.
*/
*/
protected
final
boolean
isSourceReady
()
{
protected
final
boolean
isSourceReady
()
{
return
readEndOfStream
?
streamIsFinal
:
stream
.
isReady
();
return
readEndOfStream
?
streamIsFinal
:
stream
.
isReady
();
...
...
library/core/src/main/java/com/google/android/exoplayer2/ExoPlayer.java
View file @
9f814850
...
@@ -15,6 +15,8 @@
...
@@ -15,6 +15,8 @@
*/
*/
package
com
.
google
.
android
.
exoplayer2
;
package
com
.
google
.
android
.
exoplayer2
;
import
android.os.Looper
;
import
android.support.annotation.IntDef
;
import
android.support.annotation.Nullable
;
import
android.support.annotation.Nullable
;
import
com.google.android.exoplayer2.audio.MediaCodecAudioRenderer
;
import
com.google.android.exoplayer2.audio.MediaCodecAudioRenderer
;
import
com.google.android.exoplayer2.metadata.MetadataRenderer
;
import
com.google.android.exoplayer2.metadata.MetadataRenderer
;
...
@@ -88,7 +90,9 @@ import com.google.android.exoplayer2.video.MediaCodecVideoRenderer;
...
@@ -88,7 +90,9 @@ import com.google.android.exoplayer2.video.MediaCodecVideoRenderer;
* thread. The application's main thread is ideal. Accessing an instance from multiple threads is
* thread. The application's main thread is ideal. Accessing an instance from multiple threads is
* discouraged, however if an application does wish to do this then it may do so provided that it
* discouraged, however if an application does wish to do this then it may do so provided that it
* ensures accesses are synchronized.</li>
* ensures accesses are synchronized.</li>
* <li>Registered listeners are called on the thread that created the ExoPlayer instance.</li>
* <li>Registered listeners are called on the thread that created the ExoPlayer instance, unless
* the thread that created the ExoPlayer instance does not have a {@link Looper}. In that case,
* registered listeners will be called on the application's main thread.</li>
* <li>An internal playback thread is responsible for playback. Injected player components such as
* <li>An internal playback thread is responsible for playback. Injected player components such as
* Renderers, MediaSources, TrackSelectors and LoadControls are called by the player on this
* Renderers, MediaSources, TrackSelectors and LoadControls are called by the player on this
* thread.</li>
* thread.</li>
...
@@ -113,8 +117,8 @@ public interface ExoPlayer {
...
@@ -113,8 +117,8 @@ public interface ExoPlayer {
* Called when the timeline and/or manifest has been refreshed.
* Called when the timeline and/or manifest has been refreshed.
* <p>
* <p>
* Note that if the timeline has changed then a position discontinuity may also have occurred.
* Note that if the timeline has changed then a position discontinuity may also have occurred.
* For example the current period index may have changed as a result of periods being added or
* For example
,
the current period index may have changed as a result of periods being added or
* removed from the timeline. Th
e
will <em>not</em> be reported via a separate call to
* removed from the timeline. Th
is
will <em>not</em> be reported via a separate call to
* {@link #onPositionDiscontinuity()}.
* {@link #onPositionDiscontinuity()}.
*
*
* @param timeline The latest timeline. Never null, but may be empty.
* @param timeline The latest timeline. Never null, but may be empty.
...
@@ -253,7 +257,8 @@ public interface ExoPlayer {
...
@@ -253,7 +257,8 @@ public interface ExoPlayer {
/**
/**
* Register a listener to receive events from the player. The listener's methods will be called on
* Register a listener to receive events from the player. The listener's methods will be called on
* the thread that was used to construct the player.
* the thread that was used to construct the player. However, if the thread used to construct the
* player does not have a {@link Looper}, then the listener will be called on the main thread.
*
*
* @param listener The listener to register.
* @param listener The listener to register.
*/
*/
...
...
library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerFactory.java
View file @
9f814850
...
@@ -16,7 +16,6 @@
...
@@ -16,7 +16,6 @@
package
com
.
google
.
android
.
exoplayer2
;
package
com
.
google
.
android
.
exoplayer2
;
import
android.content.Context
;
import
android.content.Context
;
import
android.os.Looper
;
import
com.google.android.exoplayer2.drm.DrmSessionManager
;
import
com.google.android.exoplayer2.drm.DrmSessionManager
;
import
com.google.android.exoplayer2.drm.FrameworkMediaCrypto
;
import
com.google.android.exoplayer2.drm.FrameworkMediaCrypto
;
import
com.google.android.exoplayer2.trackselection.TrackSelector
;
import
com.google.android.exoplayer2.trackselection.TrackSelector
;
...
@@ -29,8 +28,7 @@ public final class ExoPlayerFactory {
...
@@ -29,8 +28,7 @@ public final class ExoPlayerFactory {
private
ExoPlayerFactory
()
{}
private
ExoPlayerFactory
()
{}
/**
/**
* Creates a {@link SimpleExoPlayer} instance. Must be called from a thread that has an associated
* Creates a {@link SimpleExoPlayer} instance.
* {@link Looper}.
*
*
* @param context A {@link Context}.
* @param context A {@link Context}.
* @param trackSelector The {@link TrackSelector} that will be used by the instance.
* @param trackSelector The {@link TrackSelector} that will be used by the instance.
...
@@ -45,8 +43,7 @@ public final class ExoPlayerFactory {
...
@@ -45,8 +43,7 @@ public final class ExoPlayerFactory {
}
}
/**
/**
* Creates a {@link SimpleExoPlayer} instance. Must be called from a thread that has an associated
* Creates a {@link SimpleExoPlayer} instance. Available extension renderers are not used.
* {@link Looper}. Available extension renderers are not used.
*
*
* @param context A {@link Context}.
* @param context A {@link Context}.
* @param trackSelector The {@link TrackSelector} that will be used by the instance.
* @param trackSelector The {@link TrackSelector} that will be used by the instance.
...
@@ -63,8 +60,7 @@ public final class ExoPlayerFactory {
...
@@ -63,8 +60,7 @@ public final class ExoPlayerFactory {
}
}
/**
/**
* Creates a {@link SimpleExoPlayer} instance. Must be called from a thread that has an associated
* Creates a {@link SimpleExoPlayer} instance.
* {@link Looper}.
*
*
* @param context A {@link Context}.
* @param context A {@link Context}.
* @param trackSelector The {@link TrackSelector} that will be used by the instance.
* @param trackSelector The {@link TrackSelector} that will be used by the instance.
...
@@ -86,8 +82,7 @@ public final class ExoPlayerFactory {
...
@@ -86,8 +82,7 @@ public final class ExoPlayerFactory {
}
}
/**
/**
* Creates a {@link SimpleExoPlayer} instance. Must be called from a thread that has an associated
* Creates a {@link SimpleExoPlayer} instance.
* {@link Looper}.
*
*
* @param context A {@link Context}.
* @param context A {@link Context}.
* @param trackSelector The {@link TrackSelector} that will be used by the instance.
* @param trackSelector The {@link TrackSelector} that will be used by the instance.
...
@@ -112,8 +107,7 @@ public final class ExoPlayerFactory {
...
@@ -112,8 +107,7 @@ public final class ExoPlayerFactory {
}
}
/**
/**
* Creates a {@link SimpleExoPlayer} instance. Must be called from a thread that has an associated
* Creates a {@link SimpleExoPlayer} instance.
* {@link Looper}.
*
*
* @param context A {@link Context}.
* @param context A {@link Context}.
* @param trackSelector The {@link TrackSelector} that will be used by the instance.
* @param trackSelector The {@link TrackSelector} that will be used by the instance.
...
@@ -123,8 +117,7 @@ public final class ExoPlayerFactory {
...
@@ -123,8 +117,7 @@ public final class ExoPlayerFactory {
}
}
/**
/**
* Creates a {@link SimpleExoPlayer} instance. Must be called from a thread that has an associated
* Creates a {@link SimpleExoPlayer} instance.
* {@link Looper}.
*
*
* @param renderersFactory A factory for creating {@link Renderer}s to be used by the instance.
* @param renderersFactory A factory for creating {@link Renderer}s to be used by the instance.
* @param trackSelector The {@link TrackSelector} that will be used by the instance.
* @param trackSelector The {@link TrackSelector} that will be used by the instance.
...
@@ -135,8 +128,7 @@ public final class ExoPlayerFactory {
...
@@ -135,8 +128,7 @@ public final class ExoPlayerFactory {
}
}
/**
/**
* Creates a {@link SimpleExoPlayer} instance. Must be called from a thread that has an associated
* Creates a {@link SimpleExoPlayer} instance.
* {@link Looper}.
*
*
* @param renderersFactory A factory for creating {@link Renderer}s to be used by the instance.
* @param renderersFactory A factory for creating {@link Renderer}s to be used by the instance.
* @param trackSelector The {@link TrackSelector} that will be used by the instance.
* @param trackSelector The {@link TrackSelector} that will be used by the instance.
...
@@ -148,8 +140,7 @@ public final class ExoPlayerFactory {
...
@@ -148,8 +140,7 @@ public final class ExoPlayerFactory {
}
}
/**
/**
* Creates an {@link ExoPlayer} instance. Must be called from a thread that has an associated
* Creates an {@link ExoPlayer} instance.
* {@link Looper}.
*
*
* @param renderers The {@link Renderer}s that will be used by the instance.
* @param renderers The {@link Renderer}s that will be used by the instance.
* @param trackSelector The {@link TrackSelector} that will be used by the instance.
* @param trackSelector The {@link TrackSelector} that will be used by the instance.
...
@@ -159,8 +150,7 @@ public final class ExoPlayerFactory {
...
@@ -159,8 +150,7 @@ public final class ExoPlayerFactory {
}
}
/**
/**
* Creates an {@link ExoPlayer} instance. Must be called from a thread that has an associated
* Creates an {@link ExoPlayer} instance.
* {@link Looper}.
*
*
* @param renderers The {@link Renderer}s that will be used by the instance.
* @param renderers The {@link Renderer}s that will be used by the instance.
* @param trackSelector The {@link TrackSelector} that will be used by the instance.
* @param trackSelector The {@link TrackSelector} that will be used by the instance.
...
...
library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java
View file @
9f814850
...
@@ -92,7 +92,8 @@ import java.util.concurrent.CopyOnWriteArraySet;
...
@@ -92,7 +92,8 @@ import java.util.concurrent.CopyOnWriteArraySet;
trackGroups
=
TrackGroupArray
.
EMPTY
;
trackGroups
=
TrackGroupArray
.
EMPTY
;
trackSelections
=
emptyTrackSelections
;
trackSelections
=
emptyTrackSelections
;
playbackParameters
=
PlaybackParameters
.
DEFAULT
;
playbackParameters
=
PlaybackParameters
.
DEFAULT
;
eventHandler
=
new
Handler
()
{
Looper
eventLooper
=
Looper
.
myLooper
()
!=
null
?
Looper
.
myLooper
()
:
Looper
.
getMainLooper
();
eventHandler
=
new
Handler
(
eventLooper
)
{
@Override
@Override
public
void
handleMessage
(
Message
msg
)
{
public
void
handleMessage
(
Message
msg
)
{
ExoPlayerImpl
.
this
.
handleEvent
(
msg
);
ExoPlayerImpl
.
this
.
handleEvent
(
msg
);
...
...
library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java
View file @
9f814850
...
@@ -24,13 +24,13 @@ public interface ExoPlayerLibraryInfo {
...
@@ -24,13 +24,13 @@ public interface ExoPlayerLibraryInfo {
* The version of the library expressed as a string, for example "1.2.3".
* The version of the library expressed as a string, for example "1.2.3".
*/
*/
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION_INT) or vice versa.
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION_INT) or vice versa.
String
VERSION
=
"2.4.
0
"
;
String
VERSION
=
"2.4.
1
"
;
/**
/**
* The version of the library expressed as {@code "ExoPlayerLib/" + VERSION}.
* The version of the library expressed as {@code "ExoPlayerLib/" + VERSION}.
*/
*/
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION) or vice versa.
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION) or vice versa.
String
VERSION_SLASHY
=
"ExoPlayerLib/2.4.
0
"
;
String
VERSION_SLASHY
=
"ExoPlayerLib/2.4.
1
"
;
/**
/**
* The version of the library expressed as an integer, for example 1002003.
* The version of the library expressed as an integer, for example 1002003.
...
@@ -40,7 +40,7 @@ public interface ExoPlayerLibraryInfo {
...
@@ -40,7 +40,7 @@ public interface ExoPlayerLibraryInfo {
* integer version 123045006 (123-045-006).
* integer version 123045006 (123-045-006).
*/
*/
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION) or vice versa.
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION) or vice versa.
int
VERSION_INT
=
200400
0
;
int
VERSION_INT
=
200400
1
;
/**
/**
* Whether the library was compiled with {@link com.google.android.exoplayer2.util.Assertions}
* Whether the library was compiled with {@link com.google.android.exoplayer2.util.Assertions}
...
...
library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java
View file @
9f814850
...
@@ -20,6 +20,7 @@ import android.graphics.SurfaceTexture;
...
@@ -20,6 +20,7 @@ import android.graphics.SurfaceTexture;
import
android.media.MediaCodec
;
import
android.media.MediaCodec
;
import
android.media.PlaybackParams
;
import
android.media.PlaybackParams
;
import
android.os.Handler
;
import
android.os.Handler
;
import
android.os.Looper
;
import
android.support.annotation.Nullable
;
import
android.support.annotation.Nullable
;
import
android.util.Log
;
import
android.util.Log
;
import
android.view.Surface
;
import
android.view.Surface
;
...
@@ -111,8 +112,10 @@ public class SimpleExoPlayer implements ExoPlayer {
...
@@ -111,8 +112,10 @@ public class SimpleExoPlayer implements ExoPlayer {
protected
SimpleExoPlayer
(
RenderersFactory
renderersFactory
,
TrackSelector
trackSelector
,
protected
SimpleExoPlayer
(
RenderersFactory
renderersFactory
,
TrackSelector
trackSelector
,
LoadControl
loadControl
)
{
LoadControl
loadControl
)
{
componentListener
=
new
ComponentListener
();
componentListener
=
new
ComponentListener
();
renderers
=
renderersFactory
.
createRenderers
(
new
Handler
(),
componentListener
,
Looper
eventLooper
=
Looper
.
myLooper
()
!=
null
?
Looper
.
myLooper
()
:
Looper
.
getMainLooper
();
componentListener
,
componentListener
,
componentListener
);
Handler
eventHandler
=
new
Handler
(
eventLooper
);
renderers
=
renderersFactory
.
createRenderers
(
eventHandler
,
componentListener
,
componentListener
,
componentListener
,
componentListener
);
// Obtain counts of video and audio renderers.
// Obtain counts of video and audio renderers.
int
videoRendererCount
=
0
;
int
videoRendererCount
=
0
;
...
...
library/core/src/main/java/com/google/android/exoplayer2/audio/Sonic.java
View file @
9f814850
...
@@ -374,8 +374,8 @@ import java.util.Arrays;
...
@@ -374,8 +374,8 @@ import java.util.Arrays;
}
}
private
short
interpolate
(
short
[]
in
,
int
inPos
,
int
oldSampleRate
,
int
newSampleRate
)
{
private
short
interpolate
(
short
[]
in
,
int
inPos
,
int
oldSampleRate
,
int
newSampleRate
)
{
short
left
=
in
[
inPos
*
numChannels
];
short
left
=
in
[
inPos
];
short
right
=
in
[
inPos
*
numChannels
+
numChannels
];
short
right
=
in
[
inPos
+
numChannels
];
int
position
=
newRatePosition
*
oldSampleRate
;
int
position
=
newRatePosition
*
oldSampleRate
;
int
leftPosition
=
oldRatePosition
*
newSampleRate
;
int
leftPosition
=
oldRatePosition
*
newSampleRate
;
int
rightPosition
=
(
oldRatePosition
+
1
)
*
newSampleRate
;
int
rightPosition
=
(
oldRatePosition
+
1
)
*
newSampleRate
;
...
@@ -402,7 +402,7 @@ import java.util.Arrays;
...
@@ -402,7 +402,7 @@ import java.util.Arrays;
enlargeOutputBufferIfNeeded
(
1
);
enlargeOutputBufferIfNeeded
(
1
);
for
(
int
i
=
0
;
i
<
numChannels
;
i
++)
{
for
(
int
i
=
0
;
i
<
numChannels
;
i
++)
{
outputBuffer
[
numOutputSamples
*
numChannels
+
i
]
=
outputBuffer
[
numOutputSamples
*
numChannels
+
i
]
=
interpolate
(
pitchBuffer
,
position
+
i
,
oldSampleRate
,
newSampleRate
);
interpolate
(
pitchBuffer
,
position
*
numChannels
+
i
,
oldSampleRate
,
newSampleRate
);
}
}
newRatePosition
++;
newRatePosition
++;
numOutputSamples
++;
numOutputSamples
++;
...
...
library/core/src/main/java/com/google/android/exoplayer2/decoder/SimpleOutputBuffer.java
View file @
9f814850
...
@@ -16,6 +16,7 @@
...
@@ -16,6 +16,7 @@
package
com
.
google
.
android
.
exoplayer2
.
decoder
;
package
com
.
google
.
android
.
exoplayer2
.
decoder
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteOrder
;
/**
/**
* Buffer for {@link SimpleDecoder} output.
* Buffer for {@link SimpleDecoder} output.
...
@@ -40,7 +41,7 @@ public class SimpleOutputBuffer extends OutputBuffer {
...
@@ -40,7 +41,7 @@ public class SimpleOutputBuffer extends OutputBuffer {
public
ByteBuffer
init
(
long
timeUs
,
int
size
)
{
public
ByteBuffer
init
(
long
timeUs
,
int
size
)
{
this
.
timeUs
=
timeUs
;
this
.
timeUs
=
timeUs
;
if
(
data
==
null
||
data
.
capacity
()
<
size
)
{
if
(
data
==
null
||
data
.
capacity
()
<
size
)
{
data
=
ByteBuffer
.
allocateDirect
(
size
);
data
=
ByteBuffer
.
allocateDirect
(
size
)
.
order
(
ByteOrder
.
nativeOrder
())
;
}
}
data
.
position
(
0
);
data
.
position
(
0
);
data
.
limit
(
size
);
data
.
limit
(
size
);
...
...
library/core/src/main/java/com/google/android/exoplayer2/extractor/DefaultExtractorsFactory.java
View file @
9f814850
...
@@ -26,7 +26,9 @@ import com.google.android.exoplayer2.extractor.ts.AdtsExtractor;
...
@@ -26,7 +26,9 @@ import com.google.android.exoplayer2.extractor.ts.AdtsExtractor;
import
com.google.android.exoplayer2.extractor.ts.DefaultTsPayloadReaderFactory
;
import
com.google.android.exoplayer2.extractor.ts.DefaultTsPayloadReaderFactory
;
import
com.google.android.exoplayer2.extractor.ts.PsExtractor
;
import
com.google.android.exoplayer2.extractor.ts.PsExtractor
;
import
com.google.android.exoplayer2.extractor.ts.TsExtractor
;
import
com.google.android.exoplayer2.extractor.ts.TsExtractor
;
import
com.google.android.exoplayer2.extractor.ts.TsPayloadReader
;
import
com.google.android.exoplayer2.extractor.wav.WavExtractor
;
import
com.google.android.exoplayer2.extractor.wav.WavExtractor
;
import
com.google.android.exoplayer2.util.TimestampAdjuster
;
import
java.lang.reflect.Constructor
;
import
java.lang.reflect.Constructor
;
/**
/**
...
@@ -67,8 +69,13 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory {
...
@@ -67,8 +69,13 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory {
private
@MatroskaExtractor
.
Flags
int
matroskaFlags
;
private
@MatroskaExtractor
.
Flags
int
matroskaFlags
;
private
@FragmentedMp4Extractor
.
Flags
int
fragmentedMp4Flags
;
private
@FragmentedMp4Extractor
.
Flags
int
fragmentedMp4Flags
;
private
@Mp3Extractor
.
Flags
int
mp3Flags
;
private
@Mp3Extractor
.
Flags
int
mp3Flags
;
private
@TsExtractor
.
Mode
int
tsMode
;
private
@DefaultTsPayloadReaderFactory
.
Flags
int
tsFlags
;
private
@DefaultTsPayloadReaderFactory
.
Flags
int
tsFlags
;
public
DefaultExtractorsFactory
()
{
tsMode
=
TsExtractor
.
MODE_SINGLE_PMT
;
}
/**
/**
* Sets flags for {@link MatroskaExtractor} instances created by the factory.
* Sets flags for {@link MatroskaExtractor} instances created by the factory.
*
*
...
@@ -108,6 +115,18 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory {
...
@@ -108,6 +115,18 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory {
}
}
/**
/**
* Sets the mode for {@link TsExtractor} instances created by the factory.
*
* @see TsExtractor#TsExtractor(int, TimestampAdjuster, TsPayloadReader.Factory).
* @param mode The mode to use.
* @return The factory, for convenience.
*/
public
synchronized
DefaultExtractorsFactory
setTsExtractorMode
(
@TsExtractor
.
Mode
int
mode
)
{
tsMode
=
mode
;
return
this
;
}
/**
* Sets flags for {@link DefaultTsPayloadReaderFactory}s used by {@link TsExtractor} instances
* Sets flags for {@link DefaultTsPayloadReaderFactory}s used by {@link TsExtractor} instances
* created by the factory.
* created by the factory.
*
*
...
@@ -130,7 +149,7 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory {
...
@@ -130,7 +149,7 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory {
extractors
[
3
]
=
new
Mp3Extractor
(
mp3Flags
);
extractors
[
3
]
=
new
Mp3Extractor
(
mp3Flags
);
extractors
[
4
]
=
new
AdtsExtractor
();
extractors
[
4
]
=
new
AdtsExtractor
();
extractors
[
5
]
=
new
Ac3Extractor
();
extractors
[
5
]
=
new
Ac3Extractor
();
extractors
[
6
]
=
new
TsExtractor
(
tsFlags
);
extractors
[
6
]
=
new
TsExtractor
(
ts
Mode
,
ts
Flags
);
extractors
[
7
]
=
new
FlvExtractor
();
extractors
[
7
]
=
new
FlvExtractor
();
extractors
[
8
]
=
new
OggExtractor
();
extractors
[
8
]
=
new
OggExtractor
();
extractors
[
9
]
=
new
PsExtractor
();
extractors
[
9
]
=
new
PsExtractor
();
...
...
library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggPacket.java
View file @
9f814850
...
@@ -20,6 +20,7 @@ import com.google.android.exoplayer2.extractor.ExtractorInput;
...
@@ -20,6 +20,7 @@ import com.google.android.exoplayer2.extractor.ExtractorInput;
import
com.google.android.exoplayer2.util.Assertions
;
import
com.google.android.exoplayer2.util.Assertions
;
import
com.google.android.exoplayer2.util.ParsableByteArray
;
import
com.google.android.exoplayer2.util.ParsableByteArray
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.util.Arrays
;
/**
/**
* OGG packet class.
* OGG packet class.
...
@@ -27,8 +28,8 @@ import java.io.IOException;
...
@@ -27,8 +28,8 @@ import java.io.IOException;
/* package */
final
class
OggPacket
{
/* package */
final
class
OggPacket
{
private
final
OggPageHeader
pageHeader
=
new
OggPageHeader
();
private
final
OggPageHeader
pageHeader
=
new
OggPageHeader
();
private
final
ParsableByteArray
packetArray
=
private
final
ParsableByteArray
packetArray
=
new
ParsableByteArray
(
new
ParsableByteArray
(
new
byte
[
OggPageHeader
.
MAX_PAGE_PAYLOAD
],
0
);
new
byte
[
OggPageHeader
.
MAX_PAGE_PAYLOAD
],
0
);
private
int
currentSegmentIndex
=
C
.
INDEX_UNSET
;
private
int
currentSegmentIndex
=
C
.
INDEX_UNSET
;
private
int
segmentCount
;
private
int
segmentCount
;
...
@@ -85,6 +86,9 @@ import java.io.IOException;
...
@@ -85,6 +86,9 @@ import java.io.IOException;
int
size
=
calculatePacketSize
(
currentSegmentIndex
);
int
size
=
calculatePacketSize
(
currentSegmentIndex
);
int
segmentIndex
=
currentSegmentIndex
+
segmentCount
;
int
segmentIndex
=
currentSegmentIndex
+
segmentCount
;
if
(
size
>
0
)
{
if
(
size
>
0
)
{
if
(
packetArray
.
capacity
()
<
packetArray
.
limit
()
+
size
)
{
packetArray
.
data
=
Arrays
.
copyOf
(
packetArray
.
data
,
packetArray
.
limit
()
+
size
);
}
input
.
readFully
(
packetArray
.
data
,
packetArray
.
limit
(),
size
);
input
.
readFully
(
packetArray
.
data
,
packetArray
.
limit
(),
size
);
packetArray
.
setLimit
(
packetArray
.
limit
()
+
size
);
packetArray
.
setLimit
(
packetArray
.
limit
()
+
size
);
populated
=
pageHeader
.
laces
[
segmentIndex
-
1
]
!=
255
;
populated
=
pageHeader
.
laces
[
segmentIndex
-
1
]
!=
255
;
...
@@ -119,6 +123,17 @@ import java.io.IOException;
...
@@ -119,6 +123,17 @@ import java.io.IOException;
}
}
/**
/**
* Trims the packet data array.
*/
public
void
trimPayload
()
{
if
(
packetArray
.
data
.
length
==
OggPageHeader
.
MAX_PAGE_PAYLOAD
)
{
return
;
}
packetArray
.
data
=
Arrays
.
copyOf
(
packetArray
.
data
,
Math
.
max
(
OggPageHeader
.
MAX_PAGE_PAYLOAD
,
packetArray
.
limit
()));
}
/**
* Calculates the size of the packet starting from {@code startSegmentIndex}.
* Calculates the size of the packet starting from {@code startSegmentIndex}.
*
*
* @param startSegmentIndex the index of the first segment of the packet.
* @param startSegmentIndex the index of the first segment of the packet.
...
...
library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/StreamReader.java
View file @
9f814850
...
@@ -103,15 +103,12 @@ import java.io.IOException;
...
@@ -103,15 +103,12 @@ import java.io.IOException;
switch
(
state
)
{
switch
(
state
)
{
case
STATE_READ_HEADERS:
case
STATE_READ_HEADERS:
return
readHeaders
(
input
);
return
readHeaders
(
input
);
case
STATE_SKIP_HEADERS:
case
STATE_SKIP_HEADERS:
input
.
skipFully
((
int
)
payloadStartPosition
);
input
.
skipFully
((
int
)
payloadStartPosition
);
state
=
STATE_READ_PAYLOAD
;
state
=
STATE_READ_PAYLOAD
;
return
Extractor
.
RESULT_CONTINUE
;
return
Extractor
.
RESULT_CONTINUE
;
case
STATE_READ_PAYLOAD:
case
STATE_READ_PAYLOAD:
return
readPayload
(
input
,
seekPosition
);
return
readPayload
(
input
,
seekPosition
);
default
:
default
:
// Never happens.
// Never happens.
throw
new
IllegalStateException
();
throw
new
IllegalStateException
();
...
@@ -152,6 +149,8 @@ import java.io.IOException;
...
@@ -152,6 +149,8 @@ import java.io.IOException;
setupData
=
null
;
setupData
=
null
;
state
=
STATE_READ_PAYLOAD
;
state
=
STATE_READ_PAYLOAD
;
// First payload packet. Trim the payload array of the ogg packet after headers have been read.
oggPacket
.
trimPayload
();
return
Extractor
.
RESULT_CONTINUE
;
return
Extractor
.
RESULT_CONTINUE
;
}
}
...
...
library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/VorbisReader.java
View file @
9f814850
...
@@ -101,7 +101,7 @@ import java.util.ArrayList;
...
@@ -101,7 +101,7 @@ import java.util.ArrayList;
codecInitialisationData
.
add
(
vorbisSetup
.
setupHeaderData
);
codecInitialisationData
.
add
(
vorbisSetup
.
setupHeaderData
);
setupData
.
format
=
Format
.
createAudioSampleFormat
(
null
,
MimeTypes
.
AUDIO_VORBIS
,
null
,
setupData
.
format
=
Format
.
createAudioSampleFormat
(
null
,
MimeTypes
.
AUDIO_VORBIS
,
null
,
this
.
vorbisSetup
.
idHeader
.
bitrateNominal
,
OggPageHeader
.
MAX_PAGE_PAYLOAD
,
this
.
vorbisSetup
.
idHeader
.
bitrateNominal
,
Format
.
NO_VALUE
,
this
.
vorbisSetup
.
idHeader
.
channels
,
(
int
)
this
.
vorbisSetup
.
idHeader
.
sampleRate
,
this
.
vorbisSetup
.
idHeader
.
channels
,
(
int
)
this
.
vorbisSetup
.
idHeader
.
sampleRate
,
codecInitialisationData
,
null
,
0
,
null
);
codecInitialisationData
,
null
,
0
,
null
);
return
true
;
return
true
;
...
...
library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java
View file @
9f814850
...
@@ -65,13 +65,13 @@ public final class TsExtractor implements Extractor {
...
@@ -65,13 +65,13 @@ public final class TsExtractor implements Extractor {
* Modes for the extractor.
* Modes for the extractor.
*/
*/
@Retention
(
RetentionPolicy
.
SOURCE
)
@Retention
(
RetentionPolicy
.
SOURCE
)
@IntDef
({
MODE_
NORMAL
,
MODE_SINGLE_PMT
,
MODE_HLS
})
@IntDef
({
MODE_
MULTI_PMT
,
MODE_SINGLE_PMT
,
MODE_HLS
})
public
@interface
Mode
{}
public
@interface
Mode
{}
/**
/**
* Behave as defined in ISO/IEC 13818-1.
* Behave as defined in ISO/IEC 13818-1.
*/
*/
public
static
final
int
MODE_
NORMAL
=
0
;
public
static
final
int
MODE_
MULTI_PMT
=
0
;
/**
/**
* Assume only one PMT will be contained in the stream, even if more are declared by the PAT.
* Assume only one PMT will be contained in the stream, even if more are declared by the PAT.
*/
*/
...
@@ -132,12 +132,23 @@ public final class TsExtractor implements Extractor {
...
@@ -132,12 +132,23 @@ public final class TsExtractor implements Extractor {
* {@code FLAG_*} values that control the behavior of the payload readers.
* {@code FLAG_*} values that control the behavior of the payload readers.
*/
*/
public
TsExtractor
(
@Flags
int
defaultTsPayloadReaderFlags
)
{
public
TsExtractor
(
@Flags
int
defaultTsPayloadReaderFlags
)
{
this
(
MODE_NORMAL
,
new
TimestampAdjuster
(
0
),
this
(
MODE_SINGLE_PMT
,
defaultTsPayloadReaderFlags
);
}
/**
* @param mode Mode for the extractor. One of {@link #MODE_MULTI_PMT}, {@link #MODE_SINGLE_PMT}
* and {@link #MODE_HLS}.
* @param defaultTsPayloadReaderFlags A combination of {@link DefaultTsPayloadReaderFactory}
* {@code FLAG_*} values that control the behavior of the payload readers.
*/
public
TsExtractor
(
@Mode
int
mode
,
@Flags
int
defaultTsPayloadReaderFlags
)
{
this
(
mode
,
new
TimestampAdjuster
(
0
),
new
DefaultTsPayloadReaderFactory
(
defaultTsPayloadReaderFlags
));
new
DefaultTsPayloadReaderFactory
(
defaultTsPayloadReaderFlags
));
}
}
/**
/**
* @param mode Mode for the extractor. One of {@link #MODE_
NORMAL
}, {@link #MODE_SINGLE_PMT}
* @param mode Mode for the extractor. One of {@link #MODE_
MULTI_PMT
}, {@link #MODE_SINGLE_PMT}
* and {@link #MODE_HLS}.
* and {@link #MODE_HLS}.
* @param timestampAdjuster A timestamp adjuster for offsetting and scaling sample timestamps.
* @param timestampAdjuster A timestamp adjuster for offsetting and scaling sample timestamps.
* @param payloadReaderFactory Factory for injecting a custom set of payload readers.
* @param payloadReaderFactory Factory for injecting a custom set of payload readers.
...
...
library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java
View file @
9f814850
...
@@ -488,7 +488,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
...
@@ -488,7 +488,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
}
}
if
(
format
==
null
)
{
if
(
format
==
null
)
{
// We don't have a format yet, so try and read one.
// We don't have a format yet, so try and read one.
b
uffer
.
clear
();
flagsOnlyB
uffer
.
clear
();
int
result
=
readSource
(
formatHolder
,
flagsOnlyBuffer
,
true
);
int
result
=
readSource
(
formatHolder
,
flagsOnlyBuffer
,
true
);
if
(
result
==
C
.
RESULT_FORMAT_READ
)
{
if
(
result
==
C
.
RESULT_FORMAT_READ
)
{
onInputFormatChanged
(
formatHolder
.
format
);
onInputFormatChanged
(
formatHolder
.
format
);
...
...
library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java
View file @
9f814850
...
@@ -429,6 +429,7 @@ public final class MediaCodecUtil {
...
@@ -429,6 +429,7 @@ public final class MediaCodecUtil {
case
CodecProfileLevel
.
AVCLevel42
:
return
8704
*
16
*
16
;
case
CodecProfileLevel
.
AVCLevel42
:
return
8704
*
16
*
16
;
case
CodecProfileLevel
.
AVCLevel5
:
return
22080
*
16
*
16
;
case
CodecProfileLevel
.
AVCLevel5
:
return
22080
*
16
*
16
;
case
CodecProfileLevel
.
AVCLevel51
:
return
36864
*
16
*
16
;
case
CodecProfileLevel
.
AVCLevel51
:
return
36864
*
16
*
16
;
case
CodecProfileLevel
.
AVCLevel52
:
return
36864
*
16
*
16
;
default
:
return
-
1
;
default
:
return
-
1
;
}
}
}
}
...
...
library/core/src/main/java/com/google/android/exoplayer2/metadata/MetadataRenderer.java
View file @
9f814850
...
@@ -153,7 +153,6 @@ public final class MetadataRenderer extends BaseRenderer implements Callback {
...
@@ -153,7 +153,6 @@ public final class MetadataRenderer extends BaseRenderer implements Callback {
protected
void
onDisabled
()
{
protected
void
onDisabled
()
{
flushPendingMetadata
();
flushPendingMetadata
();
decoder
=
null
;
decoder
=
null
;
super
.
onDisabled
();
}
}
@Override
@Override
...
...
library/core/src/main/java/com/google/android/exoplayer2/text/TextRenderer.java
View file @
9f814850
...
@@ -254,7 +254,6 @@ public final class TextRenderer extends BaseRenderer implements Callback {
...
@@ -254,7 +254,6 @@ public final class TextRenderer extends BaseRenderer implements Callback {
streamFormat
=
null
;
streamFormat
=
null
;
clearOutput
();
clearOutput
();
releaseDecoder
();
releaseDecoder
();
super
.
onDisabled
();
}
}
@Override
@Override
...
...
library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlDecoder.java
View file @
9f814850
...
@@ -17,7 +17,6 @@ package com.google.android.exoplayer2.text.ttml;
...
@@ -17,7 +17,6 @@ package com.google.android.exoplayer2.text.ttml;
import
android.text.Layout
;
import
android.text.Layout
;
import
android.util.Log
;
import
android.util.Log
;
import
android.util.Pair
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.text.Cue
;
import
com.google.android.exoplayer2.text.Cue
;
import
com.google.android.exoplayer2.text.SimpleSubtitleDecoder
;
import
com.google.android.exoplayer2.text.SimpleSubtitleDecoder
;
...
@@ -100,7 +99,7 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
...
@@ -100,7 +99,7 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
XmlPullParser
xmlParser
=
xmlParserFactory
.
newPullParser
();
XmlPullParser
xmlParser
=
xmlParserFactory
.
newPullParser
();
Map
<
String
,
TtmlStyle
>
globalStyles
=
new
HashMap
<>();
Map
<
String
,
TtmlStyle
>
globalStyles
=
new
HashMap
<>();
Map
<
String
,
TtmlRegion
>
regionMap
=
new
HashMap
<>();
Map
<
String
,
TtmlRegion
>
regionMap
=
new
HashMap
<>();
regionMap
.
put
(
TtmlNode
.
ANONYMOUS_REGION_ID
,
new
TtmlRegion
());
regionMap
.
put
(
TtmlNode
.
ANONYMOUS_REGION_ID
,
new
TtmlRegion
(
null
));
ByteArrayInputStream
inputStream
=
new
ByteArrayInputStream
(
bytes
,
0
,
length
);
ByteArrayInputStream
inputStream
=
new
ByteArrayInputStream
(
bytes
,
0
,
length
);
xmlParser
.
setInput
(
inputStream
,
null
);
xmlParser
.
setInput
(
inputStream
,
null
);
TtmlSubtitle
ttmlSubtitle
=
null
;
TtmlSubtitle
ttmlSubtitle
=
null
;
...
@@ -211,9 +210,9 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
...
@@ -211,9 +210,9 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
globalStyles
.
put
(
style
.
getId
(),
style
);
globalStyles
.
put
(
style
.
getId
(),
style
);
}
}
}
else
if
(
XmlPullParserUtil
.
isStartTag
(
xmlParser
,
TtmlNode
.
TAG_REGION
))
{
}
else
if
(
XmlPullParserUtil
.
isStartTag
(
xmlParser
,
TtmlNode
.
TAG_REGION
))
{
Pair
<
String
,
TtmlRegion
>
ttmlRegionInfo
=
parseRegionAttributes
(
xmlParser
);
TtmlRegion
ttmlRegion
=
parseRegionAttributes
(
xmlParser
);
if
(
ttmlRegion
Info
!=
null
)
{
if
(
ttmlRegion
!=
null
)
{
globalRegions
.
put
(
ttmlRegion
Info
.
first
,
ttmlRegionInfo
.
second
);
globalRegions
.
put
(
ttmlRegion
.
id
,
ttmlRegion
);
}
}
}
}
}
while
(!
XmlPullParserUtil
.
isEndTag
(
xmlParser
,
TtmlNode
.
TAG_HEAD
));
}
while
(!
XmlPullParserUtil
.
isEndTag
(
xmlParser
,
TtmlNode
.
TAG_HEAD
));
...
@@ -221,41 +220,84 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
...
@@ -221,41 +220,84 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
}
}
/**
/**
* Parses a region declaration. Supports origin and extent definition but only when defined in
* Parses a region declaration.
* terms of percentage of the viewport. Regions that do not correctly declare origin are ignored.
* <p>
* If the region defines an origin and/or extent, it is required that they're defined as
* percentages of the viewport. Region declarations that define origin and/or extent in other
* formats are unsupported, and null is returned.
*/
*/
private
Pair
<
String
,
TtmlRegion
>
parseRegionAttributes
(
XmlPullParser
xmlParser
)
{
private
TtmlRegion
parseRegionAttributes
(
XmlPullParser
xmlParser
)
{
String
regionId
=
XmlPullParserUtil
.
getAttributeValue
(
xmlParser
,
TtmlNode
.
ATTR_ID
);
String
regionId
=
XmlPullParserUtil
.
getAttributeValue
(
xmlParser
,
TtmlNode
.
ATTR_ID
);
String
regionOrigin
=
XmlPullParserUtil
.
getAttributeValue
(
xmlParser
,
TtmlNode
.
ATTR_TTS_ORIGIN
);
if
(
regionId
==
null
)
{
String
regionExtent
=
XmlPullParserUtil
.
getAttributeValue
(
xmlParser
,
TtmlNode
.
ATTR_TTS_EXTENT
);
if
(
regionOrigin
==
null
||
regionId
==
null
)
{
return
null
;
return
null
;
}
}
float
position
=
Cue
.
DIMEN_UNSET
;
float
line
=
Cue
.
DIMEN_UNSET
;
float
position
;
Matcher
originMatcher
=
PERCENTAGE_COORDINATES
.
matcher
(
regionOrigin
);
float
line
;
if
(
originMatcher
.
matches
())
{
String
regionOrigin
=
XmlPullParserUtil
.
getAttributeValue
(
xmlParser
,
TtmlNode
.
ATTR_TTS_ORIGIN
);
try
{
if
(
regionOrigin
!=
null
)
{
position
=
Float
.
parseFloat
(
originMatcher
.
group
(
1
))
/
100
.
f
;
Matcher
originMatcher
=
PERCENTAGE_COORDINATES
.
matcher
(
regionOrigin
);
line
=
Float
.
parseFloat
(
originMatcher
.
group
(
2
))
/
100
.
f
;
if
(
originMatcher
.
matches
())
{
}
catch
(
NumberFormatException
e
)
{
try
{
Log
.
w
(
TAG
,
"Ignoring region with malformed origin: '"
+
regionOrigin
+
"'"
,
e
);
position
=
Float
.
parseFloat
(
originMatcher
.
group
(
1
))
/
100
f
;
position
=
Cue
.
DIMEN_UNSET
;
line
=
Float
.
parseFloat
(
originMatcher
.
group
(
2
))
/
100
f
;
}
catch
(
NumberFormatException
e
)
{
Log
.
w
(
TAG
,
"Ignoring region with malformed origin: "
+
regionOrigin
);
return
null
;
}
}
else
{
Log
.
w
(
TAG
,
"Ignoring region with unsupported origin: "
+
regionOrigin
);
return
null
;
}
}
}
else
{
// Origin is omitted. Default to top left.
position
=
0
;
line
=
0
;
}
}
float
width
=
Cue
.
DIMEN_UNSET
;
float
width
;
float
height
;
String
regionExtent
=
XmlPullParserUtil
.
getAttributeValue
(
xmlParser
,
TtmlNode
.
ATTR_TTS_EXTENT
);
if
(
regionExtent
!=
null
)
{
if
(
regionExtent
!=
null
)
{
Matcher
extentMatcher
=
PERCENTAGE_COORDINATES
.
matcher
(
regionExtent
);
Matcher
extentMatcher
=
PERCENTAGE_COORDINATES
.
matcher
(
regionExtent
);
if
(
extentMatcher
.
matches
())
{
if
(
extentMatcher
.
matches
())
{
try
{
try
{
width
=
Float
.
parseFloat
(
extentMatcher
.
group
(
1
))
/
100
.
f
;
width
=
Float
.
parseFloat
(
extentMatcher
.
group
(
1
))
/
100
f
;
height
=
Float
.
parseFloat
(
extentMatcher
.
group
(
2
))
/
100
f
;
}
catch
(
NumberFormatException
e
)
{
}
catch
(
NumberFormatException
e
)
{
Log
.
w
(
TAG
,
"Ignoring malformed region extent: '"
+
regionExtent
+
"'"
,
e
);
Log
.
w
(
TAG
,
"Ignoring region with malformed extent: "
+
regionOrigin
);
return
null
;
}
}
}
else
{
Log
.
w
(
TAG
,
"Ignoring region with unsupported extent: "
+
regionOrigin
);
return
null
;
}
}
else
{
// Extent is omitted. Default to extent of parent.
width
=
1
;
height
=
1
;
}
@Cue
.
AnchorType
int
lineAnchor
=
Cue
.
ANCHOR_TYPE_START
;
String
displayAlign
=
XmlPullParserUtil
.
getAttributeValue
(
xmlParser
,
TtmlNode
.
ATTR_TTS_DISPLAY_ALIGN
);
if
(
displayAlign
!=
null
)
{
switch
(
displayAlign
.
toLowerCase
())
{
case
"center"
:
lineAnchor
=
Cue
.
ANCHOR_TYPE_MIDDLE
;
line
+=
height
/
2
;
break
;
case
"after"
:
lineAnchor
=
Cue
.
ANCHOR_TYPE_END
;
line
+=
height
;
break
;
default
:
// Default "before" case. Do nothing.
break
;
}
}
}
}
return
position
!=
Cue
.
DIMEN_UNSET
?
new
Pair
<>(
regionId
,
new
TtmlRegion
(
position
,
line
,
Cue
.
LINE_TYPE_FRACTION
,
width
))
:
null
;
return
new
TtmlRegion
(
regionId
,
position
,
line
,
Cue
.
LINE_TYPE_FRACTION
,
lineAnchor
,
width
)
;
}
}
private
String
[]
parseStyleIds
(
String
parentStyleIds
)
{
private
String
[]
parseStyleIds
(
String
parentStyleIds
)
{
...
@@ -277,7 +319,7 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
...
@@ -277,7 +319,7 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
try
{
try
{
style
.
setBackgroundColor
(
ColorParser
.
parseTtmlColor
(
attributeValue
));
style
.
setBackgroundColor
(
ColorParser
.
parseTtmlColor
(
attributeValue
));
}
catch
(
IllegalArgumentException
e
)
{
}
catch
(
IllegalArgumentException
e
)
{
Log
.
w
(
TAG
,
"
failed parsing background value: '"
+
attributeValue
+
"'"
);
Log
.
w
(
TAG
,
"
Failed parsing background value: "
+
attributeValue
);
}
}
break
;
break
;
case
TtmlNode
.
ATTR_TTS_COLOR
:
case
TtmlNode
.
ATTR_TTS_COLOR
:
...
@@ -285,7 +327,7 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
...
@@ -285,7 +327,7 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
try
{
try
{
style
.
setFontColor
(
ColorParser
.
parseTtmlColor
(
attributeValue
));
style
.
setFontColor
(
ColorParser
.
parseTtmlColor
(
attributeValue
));
}
catch
(
IllegalArgumentException
e
)
{
}
catch
(
IllegalArgumentException
e
)
{
Log
.
w
(
TAG
,
"
failed parsing color value: '"
+
attributeValue
+
"'"
);
Log
.
w
(
TAG
,
"
Failed parsing color value: "
+
attributeValue
);
}
}
break
;
break
;
case
TtmlNode
.
ATTR_TTS_FONT_FAMILY
:
case
TtmlNode
.
ATTR_TTS_FONT_FAMILY
:
...
@@ -296,7 +338,7 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
...
@@ -296,7 +338,7 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
style
=
createIfNull
(
style
);
style
=
createIfNull
(
style
);
parseFontSize
(
attributeValue
,
style
);
parseFontSize
(
attributeValue
,
style
);
}
catch
(
SubtitleDecoderException
e
)
{
}
catch
(
SubtitleDecoderException
e
)
{
Log
.
w
(
TAG
,
"
failed parsing fontSize value: '"
+
attributeValue
+
"'"
);
Log
.
w
(
TAG
,
"
Failed parsing fontSize value: "
+
attributeValue
);
}
}
break
;
break
;
case
TtmlNode
.
ATTR_TTS_FONT_WEIGHT
:
case
TtmlNode
.
ATTR_TTS_FONT_WEIGHT
:
...
...
library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlNode.java
View file @
9f814850
...
@@ -50,14 +50,15 @@ import java.util.TreeSet;
...
@@ -50,14 +50,15 @@ import java.util.TreeSet;
public
static
final
String
ANONYMOUS_REGION_ID
=
""
;
public
static
final
String
ANONYMOUS_REGION_ID
=
""
;
public
static
final
String
ATTR_ID
=
"id"
;
public
static
final
String
ATTR_ID
=
"id"
;
public
static
final
String
ATTR_TTS_
BACKGROUND_COLOR
=
"backgroundColor
"
;
public
static
final
String
ATTR_TTS_
ORIGIN
=
"origin
"
;
public
static
final
String
ATTR_TTS_EXTENT
=
"extent"
;
public
static
final
String
ATTR_TTS_EXTENT
=
"extent"
;
public
static
final
String
ATTR_TTS_DISPLAY_ALIGN
=
"displayAlign"
;
public
static
final
String
ATTR_TTS_BACKGROUND_COLOR
=
"backgroundColor"
;
public
static
final
String
ATTR_TTS_FONT_STYLE
=
"fontStyle"
;
public
static
final
String
ATTR_TTS_FONT_STYLE
=
"fontStyle"
;
public
static
final
String
ATTR_TTS_FONT_SIZE
=
"fontSize"
;
public
static
final
String
ATTR_TTS_FONT_SIZE
=
"fontSize"
;
public
static
final
String
ATTR_TTS_FONT_FAMILY
=
"fontFamily"
;
public
static
final
String
ATTR_TTS_FONT_FAMILY
=
"fontFamily"
;
public
static
final
String
ATTR_TTS_FONT_WEIGHT
=
"fontWeight"
;
public
static
final
String
ATTR_TTS_FONT_WEIGHT
=
"fontWeight"
;
public
static
final
String
ATTR_TTS_COLOR
=
"color"
;
public
static
final
String
ATTR_TTS_COLOR
=
"color"
;
public
static
final
String
ATTR_TTS_ORIGIN
=
"origin"
;
public
static
final
String
ATTR_TTS_TEXT_DECORATION
=
"textDecoration"
;
public
static
final
String
ATTR_TTS_TEXT_DECORATION
=
"textDecoration"
;
public
static
final
String
ATTR_TTS_TEXT_ALIGN
=
"textAlign"
;
public
static
final
String
ATTR_TTS_TEXT_ALIGN
=
"textAlign"
;
...
@@ -179,7 +180,7 @@ import java.util.TreeSet;
...
@@ -179,7 +180,7 @@ import java.util.TreeSet;
for
(
Entry
<
String
,
SpannableStringBuilder
>
entry
:
regionOutputs
.
entrySet
())
{
for
(
Entry
<
String
,
SpannableStringBuilder
>
entry
:
regionOutputs
.
entrySet
())
{
TtmlRegion
region
=
regionMap
.
get
(
entry
.
getKey
());
TtmlRegion
region
=
regionMap
.
get
(
entry
.
getKey
());
cues
.
add
(
new
Cue
(
cleanUpText
(
entry
.
getValue
()),
null
,
region
.
line
,
region
.
lineType
,
cues
.
add
(
new
Cue
(
cleanUpText
(
entry
.
getValue
()),
null
,
region
.
line
,
region
.
lineType
,
Cue
.
TYPE_UNSET
,
region
.
position
,
Cue
.
TYPE_UNSET
,
region
.
width
));
region
.
lineAnchor
,
region
.
position
,
Cue
.
TYPE_UNSET
,
region
.
width
));
}
}
return
cues
;
return
cues
;
}
}
...
...
library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlRegion.java
View file @
9f814850
...
@@ -22,20 +22,24 @@ import com.google.android.exoplayer2.text.Cue;
...
@@ -22,20 +22,24 @@ import com.google.android.exoplayer2.text.Cue;
*/
*/
/* package */
final
class
TtmlRegion
{
/* package */
final
class
TtmlRegion
{
public
final
String
id
;
public
final
float
position
;
public
final
float
position
;
public
final
float
line
;
public
final
float
line
;
@Cue
.
LineType
@Cue
.
LineType
public
final
int
lineType
;
public
final
int
lineType
;
@Cue
.
AnchorType
public
final
int
lineAnchor
;
public
final
float
width
;
public
final
float
width
;
public
TtmlRegion
()
{
public
TtmlRegion
(
String
id
)
{
this
(
Cue
.
DIMEN_UNSET
,
Cue
.
DIMEN
_UNSET
,
Cue
.
TYPE_UNSET
,
Cue
.
DIMEN_UNSET
);
this
(
id
,
Cue
.
DIMEN_UNSET
,
Cue
.
DIMEN_UNSET
,
Cue
.
TYPE
_UNSET
,
Cue
.
TYPE_UNSET
,
Cue
.
DIMEN_UNSET
);
}
}
public
TtmlRegion
(
float
position
,
float
line
,
@Cue
.
LineType
int
lineType
,
float
width
)
{
public
TtmlRegion
(
String
id
,
float
position
,
float
line
,
@Cue
.
LineType
int
lineType
,
@Cue
.
AnchorType
int
lineAnchor
,
float
width
)
{
this
.
id
=
id
;
this
.
position
=
position
;
this
.
position
=
position
;
this
.
line
=
line
;
this
.
line
=
line
;
this
.
lineType
=
lineType
;
this
.
lineType
=
lineType
;
this
.
lineAnchor
=
lineAnchor
;
this
.
width
=
width
;
this
.
width
=
width
;
}
}
...
...
library/core/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java
View file @
9f814850
...
@@ -24,6 +24,7 @@ import com.google.android.exoplayer2.Format;
...
@@ -24,6 +24,7 @@ import com.google.android.exoplayer2.Format;
import
com.google.android.exoplayer2.RendererCapabilities
;
import
com.google.android.exoplayer2.RendererCapabilities
;
import
com.google.android.exoplayer2.source.TrackGroup
;
import
com.google.android.exoplayer2.source.TrackGroup
;
import
com.google.android.exoplayer2.source.TrackGroupArray
;
import
com.google.android.exoplayer2.source.TrackGroupArray
;
import
com.google.android.exoplayer2.upstream.BandwidthMeter
;
import
com.google.android.exoplayer2.util.Assertions
;
import
com.google.android.exoplayer2.util.Assertions
;
import
com.google.android.exoplayer2.util.Util
;
import
com.google.android.exoplayer2.util.Util
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
...
@@ -376,10 +377,21 @@ public class DefaultTrackSelector extends MappingTrackSelector {
...
@@ -376,10 +377,21 @@ public class DefaultTrackSelector extends MappingTrackSelector {
private
final
AtomicReference
<
Parameters
>
paramsReference
;
private
final
AtomicReference
<
Parameters
>
paramsReference
;
/**
/**
* Constructs an instance that does not support adaptive track
s
.
* Constructs an instance that does not support adaptive track
selection
.
*/
*/
public
DefaultTrackSelector
()
{
public
DefaultTrackSelector
()
{
this
(
null
);
this
((
TrackSelection
.
Factory
)
null
);
}
/**
* Constructs an instance that supports adaptive track selection. Adaptive track selections use
* the provided {@link BandwidthMeter} to determine which individual track should be used during
* playback.
*
* @param bandwidthMeter The {@link BandwidthMeter}.
*/
public
DefaultTrackSelector
(
BandwidthMeter
bandwidthMeter
)
{
this
(
new
AdaptiveTrackSelection
.
Factory
(
bandwidthMeter
));
}
}
/**
/**
...
@@ -867,7 +879,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
...
@@ -867,7 +879,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
}
}
protected
static
boolean
formatHasLanguage
(
Format
format
,
String
language
)
{
protected
static
boolean
formatHasLanguage
(
Format
format
,
String
language
)
{
return
TextUtils
.
equals
(
language
,
Util
.
normalizeLanguageCode
(
format
.
language
));
return
language
!=
null
&&
TextUtils
.
equals
(
language
,
Util
.
normalizeLanguageCode
(
format
.
language
));
}
}
// Viewport size util methods.
// Viewport size util methods.
...
...
library/core/src/main/java/com/google/android/exoplayer2/upstream/Loader.java
View file @
9f814850
...
@@ -33,11 +33,11 @@ import java.util.concurrent.ExecutorService;
...
@@ -33,11 +33,11 @@ import java.util.concurrent.ExecutorService;
public
final
class
Loader
implements
LoaderErrorThrower
{
public
final
class
Loader
implements
LoaderErrorThrower
{
/**
/**
* Thrown when an unexpected exception is encountered during loading.
* Thrown when an unexpected exception
or error
is encountered during loading.
*/
*/
public
static
final
class
UnexpectedLoaderException
extends
IOException
{
public
static
final
class
UnexpectedLoaderException
extends
IOException
{
public
UnexpectedLoaderException
(
Exception
cause
)
{
public
UnexpectedLoaderException
(
Throwable
cause
)
{
super
(
"Unexpected "
+
cause
.
getClass
().
getSimpleName
()
+
": "
+
cause
.
getMessage
(),
cause
);
super
(
"Unexpected "
+
cause
.
getClass
().
getSimpleName
()
+
": "
+
cause
.
getMessage
(),
cause
);
}
}
...
@@ -316,6 +316,14 @@ public final class Loader implements LoaderErrorThrower {
...
@@ -316,6 +316,14 @@ public final class Loader implements LoaderErrorThrower {
if
(!
released
)
{
if
(!
released
)
{
obtainMessage
(
MSG_IO_EXCEPTION
,
new
UnexpectedLoaderException
(
e
)).
sendToTarget
();
obtainMessage
(
MSG_IO_EXCEPTION
,
new
UnexpectedLoaderException
(
e
)).
sendToTarget
();
}
}
}
catch
(
OutOfMemoryError
e
)
{
// This can occur if a stream is malformed in a way that causes an extractor to think it
// needs to allocate a large amount of memory. We don't want the process to die in this
// case, but we do want the playback to fail.
Log
.
e
(
TAG
,
"OutOfMemory error loading stream"
,
e
);
if
(!
released
)
{
obtainMessage
(
MSG_IO_EXCEPTION
,
new
UnexpectedLoaderException
(
e
)).
sendToTarget
();
}
}
catch
(
Error
e
)
{
}
catch
(
Error
e
)
{
// We'd hope that the platform would kill the process if an Error is thrown here, but the
// We'd hope that the platform would kill the process if an Error is thrown here, but the
// executor may catch the error (b/20616433). Throw it here, but also pass and throw it from
// executor may catch the error (b/20616433). Throw it here, but also pass and throw it from
...
...
library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSource.java
View file @
9f814850
...
@@ -54,8 +54,8 @@ public final class CacheDataSource implements DataSource {
...
@@ -54,8 +54,8 @@ public final class CacheDataSource implements DataSource {
FLAG_IGNORE_CACHE_FOR_UNSET_LENGTH_REQUESTS
})
FLAG_IGNORE_CACHE_FOR_UNSET_LENGTH_REQUESTS
})
public
@interface
Flags
{}
public
@interface
Flags
{}
/**
/**
* A flag indicating whether we will block reads if the cache key is locked. If
this flag
is
* A flag indicating whether we will block reads if the cache key is locked. If
unset then data
is
*
set, then we will read from upstream if the cache key is lock
ed.
*
read from upstream if the cache key is locked, regardless of whether the data is cach
ed.
*/
*/
public
static
final
int
FLAG_BLOCK_ON_CACHE
=
1
<<
0
;
public
static
final
int
FLAG_BLOCK_ON_CACHE
=
1
<<
0
;
...
@@ -110,7 +110,23 @@ public final class CacheDataSource implements DataSource {
...
@@ -110,7 +110,23 @@ public final class CacheDataSource implements DataSource {
/**
/**
* Constructs an instance with default {@link DataSource} and {@link DataSink} instances for
* Constructs an instance with default {@link DataSource} and {@link DataSink} instances for
* reading and writing the cache and with {@link #DEFAULT_MAX_CACHE_FILE_SIZE}.
* reading and writing the cache.
*
* @param cache The cache.
* @param upstream A {@link DataSource} for reading data not in the cache.
*/
public
CacheDataSource
(
Cache
cache
,
DataSource
upstream
)
{
this
(
cache
,
upstream
,
0
,
DEFAULT_MAX_CACHE_FILE_SIZE
);
}
/**
* Constructs an instance with default {@link DataSource} and {@link DataSink} instances for
* reading and writing the cache.
*
* @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_IGNORE_CACHE_FOR_UNSET_LENGTH_REQUESTS}, or 0.
*/
*/
public
CacheDataSource
(
Cache
cache
,
DataSource
upstream
,
@Flags
int
flags
)
{
public
CacheDataSource
(
Cache
cache
,
DataSource
upstream
,
@Flags
int
flags
)
{
this
(
cache
,
upstream
,
flags
,
DEFAULT_MAX_CACHE_FILE_SIZE
);
this
(
cache
,
upstream
,
flags
,
DEFAULT_MAX_CACHE_FILE_SIZE
);
...
@@ -123,8 +139,8 @@ public final class CacheDataSource implements DataSource {
...
@@ -123,8 +139,8 @@ public final class CacheDataSource implements DataSource {
*
*
* @param cache The cache.
* @param cache The cache.
* @param upstream A {@link DataSource} for reading data not in the cache.
* @param upstream A {@link DataSource} for reading data not in the cache.
* @param flags A combination of {@link #FLAG_BLOCK_ON_CACHE}
and {@link
* @param flags A combination of {@link #FLAG_BLOCK_ON_CACHE}
, {@link #FLAG_IGNORE_CACHE_ON_ERROR}
*
#FLAG_IGNORE_CACHE_ON_ERROR}
or 0.
*
and {@link #FLAG_IGNORE_CACHE_FOR_UNSET_LENGTH_REQUESTS},
or 0.
* @param maxCacheFileSize The maximum size of a cache file, in bytes. If the cached data size
* @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
* 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.
* finer-grained this is the finer-grained the eviction policy can be.
...
@@ -145,8 +161,8 @@ public final class CacheDataSource implements DataSource {
...
@@ -145,8 +161,8 @@ public final class CacheDataSource implements DataSource {
* @param cacheReadDataSource A {@link DataSource} for reading data from the cache.
* @param cacheReadDataSource A {@link DataSource} for reading data from the cache.
* @param cacheWriteDataSink A {@link DataSink} for writing data to the cache. If null, cache is
* @param cacheWriteDataSink A {@link DataSink} for writing data to the cache. If null, cache is
* accessed read-only.
* accessed read-only.
* @param flags A combination of {@link #FLAG_BLOCK_ON_CACHE}
and {@link
* @param flags A combination of {@link #FLAG_BLOCK_ON_CACHE}
, {@link #FLAG_IGNORE_CACHE_ON_ERROR}
*
#FLAG_IGNORE_CACHE_ON_ERROR}
or 0.
*
and {@link #FLAG_IGNORE_CACHE_FOR_UNSET_LENGTH_REQUESTS},
or 0.
* @param eventListener An optional {@link EventListener} to receive events.
* @param eventListener An optional {@link EventListener} to receive events.
*/
*/
public
CacheDataSource
(
Cache
cache
,
DataSource
upstream
,
DataSource
cacheReadDataSource
,
public
CacheDataSource
(
Cache
cache
,
DataSource
upstream
,
DataSource
cacheReadDataSource
,
...
...
library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSourceFactory.java
View file @
9f814850
...
@@ -34,17 +34,25 @@ public final class CacheDataSourceFactory implements DataSource.Factory {
...
@@ -34,17 +34,25 @@ public final class CacheDataSourceFactory implements DataSource.Factory {
private
final
EventListener
eventListener
;
private
final
EventListener
eventListener
;
/**
/**
* @see CacheDataSource#CacheDataSource(Cache, DataSource)
*/
public
CacheDataSourceFactory
(
Cache
cache
,
DataSource
.
Factory
upstreamFactory
)
{
this
(
cache
,
upstreamFactory
,
0
);
}
/**
* @see CacheDataSource#CacheDataSource(Cache, DataSource, int)
* @see CacheDataSource#CacheDataSource(Cache, DataSource, int)
*/
*/
public
CacheDataSourceFactory
(
Cache
cache
,
DataSource
.
Factory
upstreamFactory
,
int
flags
)
{
public
CacheDataSourceFactory
(
Cache
cache
,
DataSource
.
Factory
upstreamFactory
,
@CacheDataSource
.
Flags
int
flags
)
{
this
(
cache
,
upstreamFactory
,
flags
,
CacheDataSource
.
DEFAULT_MAX_CACHE_FILE_SIZE
);
this
(
cache
,
upstreamFactory
,
flags
,
CacheDataSource
.
DEFAULT_MAX_CACHE_FILE_SIZE
);
}
}
/**
/**
* @see CacheDataSource#CacheDataSource(Cache, DataSource, int, long)
* @see CacheDataSource#CacheDataSource(Cache, DataSource, int, long)
*/
*/
public
CacheDataSourceFactory
(
Cache
cache
,
DataSource
.
Factory
upstreamFactory
,
int
flags
,
public
CacheDataSourceFactory
(
Cache
cache
,
DataSource
.
Factory
upstreamFactory
,
long
maxCacheFileSize
)
{
@CacheDataSource
.
Flags
int
flags
,
long
maxCacheFileSize
)
{
this
(
cache
,
upstreamFactory
,
new
FileDataSourceFactory
(),
this
(
cache
,
upstreamFactory
,
new
FileDataSourceFactory
(),
new
CacheDataSinkFactory
(
cache
,
maxCacheFileSize
),
flags
,
null
);
new
CacheDataSinkFactory
(
cache
,
maxCacheFileSize
),
flags
,
null
);
}
}
...
@@ -54,8 +62,8 @@ public final class CacheDataSourceFactory implements DataSource.Factory {
...
@@ -54,8 +62,8 @@ public final class CacheDataSourceFactory implements DataSource.Factory {
* EventListener)
* EventListener)
*/
*/
public
CacheDataSourceFactory
(
Cache
cache
,
Factory
upstreamFactory
,
public
CacheDataSourceFactory
(
Cache
cache
,
Factory
upstreamFactory
,
Factory
cacheReadDataSourceFactory
,
Factory
cacheReadDataSourceFactory
,
DataSink
.
Factory
cacheWriteDataSinkFactory
,
DataSink
.
Factory
cacheWriteDataSinkFactory
,
int
flags
,
EventListener
eventListener
)
{
@CacheDataSource
.
Flags
int
flags
,
EventListener
eventListener
)
{
this
.
cache
=
cache
;
this
.
cache
=
cache
;
this
.
upstreamFactory
=
upstreamFactory
;
this
.
upstreamFactory
=
upstreamFactory
;
this
.
cacheReadDataSourceFactory
=
cacheReadDataSourceFactory
;
this
.
cacheReadDataSourceFactory
=
cacheReadDataSourceFactory
;
...
...
library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheUtil.java
View file @
9f814850
...
@@ -64,7 +64,7 @@ public final class CacheUtil {
...
@@ -64,7 +64,7 @@ public final class CacheUtil {
}
}
/**
/**
* Returns already cached and missing bytes in the {@cache} for the data defined by {@code
* Returns already cached and missing bytes in the {@c
ode c
ache} for the data defined by {@code
* dataSpec}.
* dataSpec}.
*
*
* @param dataSpec Defines the data to be checked.
* @param dataSpec Defines the data to be checked.
...
...
library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/SimpleCache.java
View file @
9f814850
...
@@ -286,7 +286,9 @@ public final class SimpleCache implements Cache {
...
@@ -286,7 +286,9 @@ public final class SimpleCache implements Cache {
private
void
removeSpan
(
CacheSpan
span
,
boolean
removeEmptyCachedContent
)
throws
CacheException
{
private
void
removeSpan
(
CacheSpan
span
,
boolean
removeEmptyCachedContent
)
throws
CacheException
{
CachedContent
cachedContent
=
index
.
get
(
span
.
key
);
CachedContent
cachedContent
=
index
.
get
(
span
.
key
);
Assertions
.
checkState
(
cachedContent
.
removeSpan
(
span
));
if
(
cachedContent
==
null
||
!
cachedContent
.
removeSpan
(
span
))
{
return
;
}
totalSpace
-=
span
.
length
;
totalSpace
-=
span
.
length
;
if
(
removeEmptyCachedContent
&&
cachedContent
.
isEmpty
())
{
if
(
removeEmptyCachedContent
&&
cachedContent
.
isEmpty
())
{
index
.
removeEmpty
(
cachedContent
.
key
);
index
.
removeEmpty
(
cachedContent
.
key
);
...
...
library/core/src/main/java/com/google/android/exoplayer2/video/DummySurface.java
0 → 100644
View file @
9f814850
This diff is collapsed.
Click to expand it.
library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java
View file @
9f814850
...
@@ -376,7 +376,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
...
@@ -376,7 +376,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
}
}
@Override
@Override
protected
void
onOutputFormatChanged
(
MediaCodec
codec
,
android
.
media
.
MediaFormat
outputFormat
)
{
protected
void
onOutputFormatChanged
(
MediaCodec
codec
,
MediaFormat
outputFormat
)
{
boolean
hasCrop
=
outputFormat
.
containsKey
(
KEY_CROP_RIGHT
)
boolean
hasCrop
=
outputFormat
.
containsKey
(
KEY_CROP_RIGHT
)
&&
outputFormat
.
containsKey
(
KEY_CROP_LEFT
)
&&
outputFormat
.
containsKey
(
KEY_CROP_BOTTOM
)
&&
outputFormat
.
containsKey
(
KEY_CROP_LEFT
)
&&
outputFormat
.
containsKey
(
KEY_CROP_BOTTOM
)
&&
outputFormat
.
containsKey
(
KEY_CROP_TOP
);
&&
outputFormat
.
containsKey
(
KEY_CROP_TOP
);
...
@@ -408,11 +408,9 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
...
@@ -408,11 +408,9 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
@Override
@Override
protected
boolean
canReconfigureCodec
(
MediaCodec
codec
,
boolean
codecIsAdaptive
,
protected
boolean
canReconfigureCodec
(
MediaCodec
codec
,
boolean
codecIsAdaptive
,
Format
oldFormat
,
Format
newFormat
)
{
Format
oldFormat
,
Format
newFormat
)
{
return
areAdaptationCompatible
(
oldFormat
,
newFormat
)
return
areAdaptationCompatible
(
codecIsAdaptive
,
oldFormat
,
newFormat
)
&&
newFormat
.
width
<=
codecMaxValues
.
width
&&
newFormat
.
height
<=
codecMaxValues
.
height
&&
newFormat
.
width
<=
codecMaxValues
.
width
&&
newFormat
.
height
<=
codecMaxValues
.
height
&&
newFormat
.
maxInputSize
<=
codecMaxValues
.
inputSize
&&
newFormat
.
maxInputSize
<=
codecMaxValues
.
inputSize
;
&&
(
codecIsAdaptive
||
(
oldFormat
.
width
==
newFormat
.
width
&&
oldFormat
.
height
==
newFormat
.
height
));
}
}
@Override
@Override
...
@@ -664,7 +662,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
...
@@ -664,7 +662,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
}
}
boolean
haveUnknownDimensions
=
false
;
boolean
haveUnknownDimensions
=
false
;
for
(
Format
streamFormat
:
streamFormats
)
{
for
(
Format
streamFormat
:
streamFormats
)
{
if
(
areAdaptationCompatible
(
format
,
streamFormat
))
{
if
(
areAdaptationCompatible
(
codecInfo
.
adaptive
,
format
,
streamFormat
))
{
haveUnknownDimensions
|=
(
streamFormat
.
width
==
Format
.
NO_VALUE
haveUnknownDimensions
|=
(
streamFormat
.
width
==
Format
.
NO_VALUE
||
streamFormat
.
height
==
Format
.
NO_VALUE
);
||
streamFormat
.
height
==
Format
.
NO_VALUE
);
maxWidth
=
Math
.
max
(
maxWidth
,
streamFormat
.
width
);
maxWidth
=
Math
.
max
(
maxWidth
,
streamFormat
.
width
);
...
@@ -817,17 +815,19 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
...
@@ -817,17 +815,19 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
}
}
/**
/**
* Returns whether a
n adaptive codec with suitable {@link CodecMaxValues} will support adaptatio
n
* Returns whether a
codec with suitable {@link CodecMaxValues} will support adaptation betwee
n
*
between
two {@link Format}s.
* two {@link Format}s.
*
*
* @param codecIsAdaptive Whether the codec supports seamless resolution switches.
* @param first The first format.
* @param first The first format.
* @param second The second format.
* @param second The second format.
* @return Whether an adaptive codec with suitable {@link CodecMaxValues} will support adaptation
* @return Whether the codec will support adaptation between the two {@link Format}s.
* between two {@link Format}s.
*/
*/
private
static
boolean
areAdaptationCompatible
(
Format
first
,
Format
second
)
{
private
static
boolean
areAdaptationCompatible
(
boolean
codecIsAdaptive
,
Format
first
,
Format
second
)
{
return
first
.
sampleMimeType
.
equals
(
second
.
sampleMimeType
)
return
first
.
sampleMimeType
.
equals
(
second
.
sampleMimeType
)
&&
getRotationDegrees
(
first
)
==
getRotationDegrees
(
second
);
&&
getRotationDegrees
(
first
)
==
getRotationDegrees
(
second
)
&&
(
codecIsAdaptive
||
(
first
.
width
==
second
.
width
&&
first
.
height
==
second
.
height
));
}
}
private
static
float
getPixelWidthHeightRatio
(
Format
format
)
{
private
static
float
getPixelWidthHeightRatio
(
Format
format
)
{
...
...
library/hls/src/androidTest/java/com/google/android/exoplayer2/source/hls/playlist/HlsMasterPlaylistParserTest.java
View file @
9f814850
...
@@ -23,6 +23,7 @@ import com.google.android.exoplayer2.util.MimeTypes;
...
@@ -23,6 +23,7 @@ import com.google.android.exoplayer2.util.MimeTypes;
import
java.io.ByteArrayInputStream
;
import
java.io.ByteArrayInputStream
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.nio.charset.Charset
;
import
java.nio.charset.Charset
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.List
;
import
junit.framework.TestCase
;
import
junit.framework.TestCase
;
...
@@ -56,16 +57,22 @@ public class HlsMasterPlaylistParserTest extends TestCase {
...
@@ -56,16 +57,22 @@ public class HlsMasterPlaylistParserTest extends TestCase {
private
static
final
String
MASTER_PLAYLIST_WITH_CC
=
" #EXTM3U \n"
private
static
final
String
MASTER_PLAYLIST_WITH_CC
=
" #EXTM3U \n"
+
"#EXT-X-MEDIA:TYPE=CLOSED-CAPTIONS,LANGUAGE=\"es\",NAME=\"Eng\",INSTREAM-ID=\"SERVICE4\"\n"
+
"#EXT-X-MEDIA:TYPE=CLOSED-CAPTIONS,LANGUAGE=\"es\",NAME=\"Eng\",INSTREAM-ID=\"SERVICE4\"\n"
+
"\n"
+
"#EXT-X-STREAM-INF:BANDWIDTH=1280000,CODECS=\"mp4a.40.2,avc1.66.30\",RESOLUTION=304x128\n"
+
"#EXT-X-STREAM-INF:BANDWIDTH=1280000,CODECS=\"mp4a.40.2,avc1.66.30\",RESOLUTION=304x128\n"
+
"http://example.com/low.m3u8\n"
;
+
"http://example.com/low.m3u8\n"
;
private
static
final
String
MASTER_PLAYLIST_WITHOUT_CC
=
" #EXTM3U \n"
+
"#EXT-X-MEDIA:TYPE=CLOSED-CAPTIONS,LANGUAGE=\"es\",NAME=\"Eng\",INSTREAM-ID=\"SERVICE4\"\n"
+
"#EXT-X-STREAM-INF:BANDWIDTH=1280000,CODECS=\"mp4a.40.2,avc1.66.30\",RESOLUTION=304x128,"
+
"CLOSED-CAPTIONS=NONE\n"
+
"http://example.com/low.m3u8\n"
;
public
void
testParseMasterPlaylist
()
throws
IOException
{
public
void
testParseMasterPlaylist
()
throws
IOException
{
HlsMasterPlaylist
masterPlaylist
=
parseMasterPlaylist
(
PLAYLIST_URI
,
MASTER_PLAYLIST
);
HlsMasterPlaylist
masterPlaylist
=
parseMasterPlaylist
(
PLAYLIST_URI
,
MASTER_PLAYLIST
);
List
<
HlsMasterPlaylist
.
HlsUrl
>
variants
=
masterPlaylist
.
variants
;
List
<
HlsMasterPlaylist
.
HlsUrl
>
variants
=
masterPlaylist
.
variants
;
assertNotNull
(
variants
);
assertNotNull
(
variants
);
assertEquals
(
5
,
variants
.
size
());
assertEquals
(
5
,
variants
.
size
());
assertNull
(
masterPlaylist
.
muxedCaptionFormats
);
assertEquals
(
1280000
,
variants
.
get
(
0
).
format
.
bitrate
);
assertEquals
(
1280000
,
variants
.
get
(
0
).
format
.
bitrate
);
assertNotNull
(
variants
.
get
(
0
).
format
.
codecs
);
assertNotNull
(
variants
.
get
(
0
).
format
.
codecs
);
...
@@ -117,6 +124,11 @@ public class HlsMasterPlaylistParserTest extends TestCase {
...
@@ -117,6 +124,11 @@ public class HlsMasterPlaylistParserTest extends TestCase {
assertEquals
(
"es"
,
closedCaptionFormat
.
language
);
assertEquals
(
"es"
,
closedCaptionFormat
.
language
);
}
}
public
void
testPlaylistWithoutClosedCaptions
()
throws
IOException
{
HlsMasterPlaylist
playlist
=
parseMasterPlaylist
(
PLAYLIST_URI
,
MASTER_PLAYLIST_WITHOUT_CC
);
assertEquals
(
Collections
.
emptyList
(),
playlist
.
muxedCaptionFormats
);
}
private
static
HlsMasterPlaylist
parseMasterPlaylist
(
String
uri
,
String
playlistString
)
private
static
HlsMasterPlaylist
parseMasterPlaylist
(
String
uri
,
String
playlistString
)
throws
IOException
{
throws
IOException
{
Uri
playlistUri
=
Uri
.
parse
(
uri
);
Uri
playlistUri
=
Uri
.
parse
(
uri
);
...
...
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java
View file @
9f814850
...
@@ -92,6 +92,7 @@ import java.util.Locale;
...
@@ -92,6 +92,7 @@ import java.util.Locale;
private
boolean
isTimestampMaster
;
private
boolean
isTimestampMaster
;
private
byte
[]
scratchSpace
;
private
byte
[]
scratchSpace
;
private
IOException
fatalError
;
private
IOException
fatalError
;
private
HlsUrl
expectedPlaylistUrl
;
private
Uri
encryptionKeyUri
;
private
Uri
encryptionKeyUri
;
private
byte
[]
encryptionKey
;
private
byte
[]
encryptionKey
;
...
@@ -111,7 +112,8 @@ import java.util.Locale;
...
@@ -111,7 +112,8 @@ import java.util.Locale;
* @param timestampAdjusterProvider A provider of {@link TimestampAdjuster} instances. If
* @param timestampAdjusterProvider A provider of {@link TimestampAdjuster} instances. If
* multiple {@link HlsChunkSource}s are used for a single playback, they should all share the
* multiple {@link HlsChunkSource}s are used for a single playback, they should all share the
* same provider.
* same provider.
* @param muxedCaptionFormats List of muxed caption {@link Format}s.
* @param muxedCaptionFormats List of muxed caption {@link Format}s. Null if no closed caption
* information is available in the master playlist.
*/
*/
public
HlsChunkSource
(
HlsPlaylistTracker
playlistTracker
,
HlsUrl
[]
variants
,
public
HlsChunkSource
(
HlsPlaylistTracker
playlistTracker
,
HlsUrl
[]
variants
,
HlsDataSourceFactory
dataSourceFactory
,
TimestampAdjusterProvider
timestampAdjusterProvider
,
HlsDataSourceFactory
dataSourceFactory
,
TimestampAdjusterProvider
timestampAdjusterProvider
,
...
@@ -142,6 +144,9 @@ import java.util.Locale;
...
@@ -142,6 +144,9 @@ import java.util.Locale;
if
(
fatalError
!=
null
)
{
if
(
fatalError
!=
null
)
{
throw
fatalError
;
throw
fatalError
;
}
}
if
(
expectedPlaylistUrl
!=
null
)
{
playlistTracker
.
maybeThrowPlaylistRefreshError
(
expectedPlaylistUrl
);
}
}
}
/**
/**
...
@@ -194,6 +199,7 @@ import java.util.Locale;
...
@@ -194,6 +199,7 @@ import java.util.Locale;
public
void
getNextChunk
(
HlsMediaChunk
previous
,
long
playbackPositionUs
,
HlsChunkHolder
out
)
{
public
void
getNextChunk
(
HlsMediaChunk
previous
,
long
playbackPositionUs
,
HlsChunkHolder
out
)
{
int
oldVariantIndex
=
previous
==
null
?
C
.
INDEX_UNSET
int
oldVariantIndex
=
previous
==
null
?
C
.
INDEX_UNSET
:
trackGroup
.
indexOf
(
previous
.
trackFormat
);
:
trackGroup
.
indexOf
(
previous
.
trackFormat
);
expectedPlaylistUrl
=
null
;
// Use start time of the previous chunk rather than its end time because switching format will
// Use start time of the previous chunk rather than its end time because switching format will
// require downloading overlapping segments.
// require downloading overlapping segments.
long
bufferedDurationUs
=
previous
==
null
?
0
long
bufferedDurationUs
=
previous
==
null
?
0
...
@@ -207,6 +213,7 @@ import java.util.Locale;
...
@@ -207,6 +213,7 @@ import java.util.Locale;
HlsUrl
selectedUrl
=
variants
[
selectedVariantIndex
];
HlsUrl
selectedUrl
=
variants
[
selectedVariantIndex
];
if
(!
playlistTracker
.
isSnapshotValid
(
selectedUrl
))
{
if
(!
playlistTracker
.
isSnapshotValid
(
selectedUrl
))
{
out
.
playlist
=
selectedUrl
;
out
.
playlist
=
selectedUrl
;
expectedPlaylistUrl
=
selectedUrl
;
// Retry when playlist is refreshed.
// Retry when playlist is refreshed.
return
;
return
;
}
}
...
@@ -246,6 +253,7 @@ import java.util.Locale;
...
@@ -246,6 +253,7 @@ import java.util.Locale;
out
.
endOfStream
=
true
;
out
.
endOfStream
=
true
;
}
else
/* Live */
{
}
else
/* Live */
{
out
.
playlist
=
selectedUrl
;
out
.
playlist
=
selectedUrl
;
expectedPlaylistUrl
=
selectedUrl
;
}
}
return
;
return
;
}
}
...
...
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunk.java
View file @
9f814850
...
@@ -39,6 +39,7 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
...
@@ -39,6 +39,7 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
import
com.google.android.exoplayer2.util.TimestampAdjuster
;
import
com.google.android.exoplayer2.util.TimestampAdjuster
;
import
com.google.android.exoplayer2.util.Util
;
import
com.google.android.exoplayer2.util.Util
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.List
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
java.util.concurrent.atomic.AtomicInteger
;
...
@@ -104,7 +105,8 @@ import java.util.concurrent.atomic.AtomicInteger;
...
@@ -104,7 +105,8 @@ import java.util.concurrent.atomic.AtomicInteger;
* @param dataSpec Defines the data to be loaded.
* @param dataSpec Defines the data to be loaded.
* @param initDataSpec Defines the initialization data to be fed to new extractors. May be null.
* @param initDataSpec Defines the initialization data to be fed to new extractors. May be null.
* @param hlsUrl The url of the playlist from which this chunk was obtained.
* @param hlsUrl The url of the playlist from which this chunk was obtained.
* @param muxedCaptionFormats List of muxed caption {@link Format}s.
* @param muxedCaptionFormats List of muxed caption {@link Format}s. Null if no closed caption
* information is available in the master playlist.
* @param trackSelectionReason See {@link #trackSelectionReason}.
* @param trackSelectionReason See {@link #trackSelectionReason}.
* @param trackSelectionData See {@link #trackSelectionData}.
* @param trackSelectionData See {@link #trackSelectionData}.
* @param startTimeUs The start time of the chunk in microseconds.
* @param startTimeUs The start time of the chunk in microseconds.
...
@@ -356,9 +358,12 @@ import java.util.concurrent.atomic.AtomicInteger;
...
@@ -356,9 +358,12 @@ import java.util.concurrent.atomic.AtomicInteger;
// This flag ensures the change of pid between streams does not affect the sample queues.
// This flag ensures the change of pid between streams does not affect the sample queues.
@DefaultTsPayloadReaderFactory
.
Flags
@DefaultTsPayloadReaderFactory
.
Flags
int
esReaderFactoryFlags
=
DefaultTsPayloadReaderFactory
.
FLAG_IGNORE_SPLICE_INFO_STREAM
;
int
esReaderFactoryFlags
=
DefaultTsPayloadReaderFactory
.
FLAG_IGNORE_SPLICE_INFO_STREAM
;
if
(!
muxedCaptionFormats
.
isEmpty
())
{
List
<
Format
>
closedCaptionFormats
=
muxedCaptionFormats
;
if
(
closedCaptionFormats
!=
null
)
{
// The playlist declares closed caption renditions, we should ignore descriptors.
// The playlist declares closed caption renditions, we should ignore descriptors.
esReaderFactoryFlags
|=
DefaultTsPayloadReaderFactory
.
FLAG_OVERRIDE_CAPTION_DESCRIPTORS
;
esReaderFactoryFlags
|=
DefaultTsPayloadReaderFactory
.
FLAG_OVERRIDE_CAPTION_DESCRIPTORS
;
}
else
{
closedCaptionFormats
=
Collections
.
emptyList
();
}
}
String
codecs
=
trackFormat
.
codecs
;
String
codecs
=
trackFormat
.
codecs
;
if
(!
TextUtils
.
isEmpty
(
codecs
))
{
if
(!
TextUtils
.
isEmpty
(
codecs
))
{
...
@@ -373,7 +378,7 @@ import java.util.concurrent.atomic.AtomicInteger;
...
@@ -373,7 +378,7 @@ import java.util.concurrent.atomic.AtomicInteger;
}
}
}
}
extractor
=
new
TsExtractor
(
TsExtractor
.
MODE_HLS
,
timestampAdjuster
,
extractor
=
new
TsExtractor
(
TsExtractor
.
MODE_HLS
,
timestampAdjuster
,
new
DefaultTsPayloadReaderFactory
(
esReaderFactoryFlags
,
mux
edCaptionFormats
));
new
DefaultTsPayloadReaderFactory
(
esReaderFactoryFlags
,
clos
edCaptionFormats
));
}
}
if
(
usingNewExtractor
)
{
if
(
usingNewExtractor
)
{
extractor
.
init
(
extractorOutput
);
extractor
.
init
(
extractorOutput
);
...
...
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java
View file @
9f814850
...
@@ -84,7 +84,7 @@ public final class HlsMediaSource implements MediaSource,
...
@@ -84,7 +84,7 @@ public final class HlsMediaSource implements MediaSource,
@Override
@Override
public
void
maybeThrowSourceInfoRefreshError
()
throws
IOException
{
public
void
maybeThrowSourceInfoRefreshError
()
throws
IOException
{
playlistTracker
.
maybeThrowPlaylistRefreshError
();
playlistTracker
.
maybeThrowP
rimaryP
laylistRefreshError
();
}
}
@Override
@Override
...
...
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMasterPlaylist.java
View file @
9f814850
...
@@ -30,15 +30,31 @@ public final class HlsMasterPlaylist extends HlsPlaylist {
...
@@ -30,15 +30,31 @@ public final class HlsMasterPlaylist extends HlsPlaylist {
*/
*/
public
static
final
class
HlsUrl
{
public
static
final
class
HlsUrl
{
/**
* The http url from which the media playlist can be obtained.
*/
public
final
String
url
;
public
final
String
url
;
/**
* Format information associated with the HLS url.
*/
public
final
Format
format
;
public
final
Format
format
;
public
static
HlsUrl
createMediaPlaylistHlsUrl
(
String
baseUri
)
{
/**
* Creates an HLS url from a given http url.
*
* @param url The url.
* @return An HLS url.
*/
public
static
HlsUrl
createMediaPlaylistHlsUrl
(
String
url
)
{
Format
format
=
Format
.
createContainerFormat
(
"0"
,
MimeTypes
.
APPLICATION_M3U8
,
null
,
null
,
Format
format
=
Format
.
createContainerFormat
(
"0"
,
MimeTypes
.
APPLICATION_M3U8
,
null
,
null
,
Format
.
NO_VALUE
,
0
,
null
);
Format
.
NO_VALUE
,
0
,
null
);
return
new
HlsUrl
(
baseUri
,
format
);
return
new
HlsUrl
(
url
,
format
);
}
}
/**
* @param url See {@link #url}.
* @param format See {@link #format}.
*/
public
HlsUrl
(
String
url
,
Format
format
)
{
public
HlsUrl
(
String
url
,
Format
format
)
{
this
.
url
=
url
;
this
.
url
=
url
;
this
.
format
=
format
;
this
.
format
=
format
;
...
@@ -46,13 +62,39 @@ public final class HlsMasterPlaylist extends HlsPlaylist {
...
@@ -46,13 +62,39 @@ public final class HlsMasterPlaylist extends HlsPlaylist {
}
}
/**
* The list of variants declared by the playlist.
*/
public
final
List
<
HlsUrl
>
variants
;
public
final
List
<
HlsUrl
>
variants
;
/**
* The list of demuxed audios declared by the playlist.
*/
public
final
List
<
HlsUrl
>
audios
;
public
final
List
<
HlsUrl
>
audios
;
/**
* The list of subtitles declared by the playlist.
*/
public
final
List
<
HlsUrl
>
subtitles
;
public
final
List
<
HlsUrl
>
subtitles
;
/**
* The format of the audio muxed in the variants. May be null if the playlist does not declare any
* muxed audio.
*/
public
final
Format
muxedAudioFormat
;
public
final
Format
muxedAudioFormat
;
/**
* The format of the closed captions declared by the playlist. May be empty if the playlist
* explicitly declares no captions are available, or null if the playlist does not declare any
* captions information.
*/
public
final
List
<
Format
>
muxedCaptionFormats
;
public
final
List
<
Format
>
muxedCaptionFormats
;
/**
* @param baseUri The base uri. Used to resolve relative paths.
* @param variants See {@link #variants}.
* @param audios See {@link #audios}.
* @param subtitles See {@link #subtitles}.
* @param muxedAudioFormat See {@link #muxedAudioFormat}.
* @param muxedCaptionFormats See {@link #muxedCaptionFormats}.
*/
public
HlsMasterPlaylist
(
String
baseUri
,
List
<
HlsUrl
>
variants
,
List
<
HlsUrl
>
audios
,
public
HlsMasterPlaylist
(
String
baseUri
,
List
<
HlsUrl
>
variants
,
List
<
HlsUrl
>
audios
,
List
<
HlsUrl
>
subtitles
,
Format
muxedAudioFormat
,
List
<
Format
>
muxedCaptionFormats
)
{
List
<
HlsUrl
>
subtitles
,
Format
muxedAudioFormat
,
List
<
Format
>
muxedCaptionFormats
)
{
super
(
baseUri
);
super
(
baseUri
);
...
@@ -60,14 +102,20 @@ public final class HlsMasterPlaylist extends HlsPlaylist {
...
@@ -60,14 +102,20 @@ public final class HlsMasterPlaylist extends HlsPlaylist {
this
.
audios
=
Collections
.
unmodifiableList
(
audios
);
this
.
audios
=
Collections
.
unmodifiableList
(
audios
);
this
.
subtitles
=
Collections
.
unmodifiableList
(
subtitles
);
this
.
subtitles
=
Collections
.
unmodifiableList
(
subtitles
);
this
.
muxedAudioFormat
=
muxedAudioFormat
;
this
.
muxedAudioFormat
=
muxedAudioFormat
;
this
.
muxedCaptionFormats
=
Collections
.
unmodifiableList
(
muxedCaptionFormats
);
this
.
muxedCaptionFormats
=
muxedCaptionFormats
!=
null
?
Collections
.
unmodifiableList
(
muxedCaptionFormats
)
:
null
;
}
}
public
static
HlsMasterPlaylist
createSingleVariantMasterPlaylist
(
String
variantUri
)
{
/**
List
<
HlsUrl
>
variant
=
Collections
.
singletonList
(
HlsUrl
.
createMediaPlaylistHlsUrl
(
variantUri
));
* Creates a playlist with a single variant.
*
* @param variantUrl The url of the single variant.
* @return A master playlist with a single variant for the provided url.
*/
public
static
HlsMasterPlaylist
createSingleVariantMasterPlaylist
(
String
variantUrl
)
{
List
<
HlsUrl
>
variant
=
Collections
.
singletonList
(
HlsUrl
.
createMediaPlaylistHlsUrl
(
variantUrl
));
List
<
HlsUrl
>
emptyList
=
Collections
.
emptyList
();
List
<
HlsUrl
>
emptyList
=
Collections
.
emptyList
();
return
new
HlsMasterPlaylist
(
null
,
variant
,
emptyList
,
emptyList
,
null
,
return
new
HlsMasterPlaylist
(
null
,
variant
,
emptyList
,
emptyList
,
null
,
null
);
Collections
.<
Format
>
emptyList
());
}
}
}
}
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMediaPlaylist.java
View file @
9f814850
...
@@ -91,12 +91,14 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
...
@@ -91,12 +91,14 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
public
final
boolean
hasProgramDateTime
;
public
final
boolean
hasProgramDateTime
;
public
final
Segment
initializationSegment
;
public
final
Segment
initializationSegment
;
public
final
List
<
Segment
>
segments
;
public
final
List
<
Segment
>
segments
;
public
final
List
<
String
>
dateRanges
;
public
final
long
durationUs
;
public
final
long
durationUs
;
public
HlsMediaPlaylist
(
@PlaylistType
int
playlistType
,
String
baseUri
,
long
startOffsetUs
,
public
HlsMediaPlaylist
(
@PlaylistType
int
playlistType
,
String
baseUri
,
long
startOffsetUs
,
long
startTimeUs
,
boolean
hasDiscontinuitySequence
,
int
discontinuitySequence
,
long
startTimeUs
,
boolean
hasDiscontinuitySequence
,
int
discontinuitySequence
,
int
mediaSequence
,
int
version
,
long
targetDurationUs
,
boolean
hasEndTag
,
int
mediaSequence
,
int
version
,
long
targetDurationUs
,
boolean
hasEndTag
,
boolean
hasProgramDateTime
,
Segment
initializationSegment
,
List
<
Segment
>
segments
)
{
boolean
hasProgramDateTime
,
Segment
initializationSegment
,
List
<
Segment
>
segments
,
List
<
String
>
dateRanges
)
{
super
(
baseUri
);
super
(
baseUri
);
this
.
playlistType
=
playlistType
;
this
.
playlistType
=
playlistType
;
this
.
startTimeUs
=
startTimeUs
;
this
.
startTimeUs
=
startTimeUs
;
...
@@ -117,6 +119,7 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
...
@@ -117,6 +119,7 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
}
}
this
.
startOffsetUs
=
startOffsetUs
==
C
.
TIME_UNSET
?
C
.
TIME_UNSET
this
.
startOffsetUs
=
startOffsetUs
==
C
.
TIME_UNSET
?
C
.
TIME_UNSET
:
startOffsetUs
>=
0
?
startOffsetUs
:
durationUs
+
startOffsetUs
;
:
startOffsetUs
>=
0
?
startOffsetUs
:
durationUs
+
startOffsetUs
;
this
.
dateRanges
=
Collections
.
unmodifiableList
(
dateRanges
);
}
}
/**
/**
...
@@ -155,7 +158,7 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
...
@@ -155,7 +158,7 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
public
HlsMediaPlaylist
copyWith
(
long
startTimeUs
,
int
discontinuitySequence
)
{
public
HlsMediaPlaylist
copyWith
(
long
startTimeUs
,
int
discontinuitySequence
)
{
return
new
HlsMediaPlaylist
(
playlistType
,
baseUri
,
startOffsetUs
,
startTimeUs
,
true
,
return
new
HlsMediaPlaylist
(
playlistType
,
baseUri
,
startOffsetUs
,
startTimeUs
,
true
,
discontinuitySequence
,
mediaSequence
,
version
,
targetDurationUs
,
hasEndTag
,
discontinuitySequence
,
mediaSequence
,
version
,
targetDurationUs
,
hasEndTag
,
hasProgramDateTime
,
initializationSegment
,
segments
);
hasProgramDateTime
,
initializationSegment
,
segments
,
dateRanges
);
}
}
/**
/**
...
@@ -170,7 +173,7 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
...
@@ -170,7 +173,7 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
}
}
return
new
HlsMediaPlaylist
(
playlistType
,
baseUri
,
startOffsetUs
,
startTimeUs
,
return
new
HlsMediaPlaylist
(
playlistType
,
baseUri
,
startOffsetUs
,
startTimeUs
,
hasDiscontinuitySequence
,
discontinuitySequence
,
mediaSequence
,
version
,
targetDurationUs
,
hasDiscontinuitySequence
,
discontinuitySequence
,
mediaSequence
,
version
,
targetDurationUs
,
true
,
hasProgramDateTime
,
initializationSegment
,
segments
);
true
,
hasProgramDateTime
,
initializationSegment
,
segments
,
dateRanges
);
}
}
}
}
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java
View file @
9f814850
...
@@ -29,6 +29,7 @@ import java.io.IOException;
...
@@ -29,6 +29,7 @@ import java.io.IOException;
import
java.io.InputStream
;
import
java.io.InputStream
;
import
java.io.InputStreamReader
;
import
java.io.InputStreamReader
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.LinkedList
;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Queue
;
import
java.util.Queue
;
...
@@ -57,6 +58,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
...
@@ -57,6 +58,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
private
static
final
String
TAG_ENDLIST
=
"#EXT-X-ENDLIST"
;
private
static
final
String
TAG_ENDLIST
=
"#EXT-X-ENDLIST"
;
private
static
final
String
TAG_KEY
=
"#EXT-X-KEY"
;
private
static
final
String
TAG_KEY
=
"#EXT-X-KEY"
;
private
static
final
String
TAG_BYTERANGE
=
"#EXT-X-BYTERANGE"
;
private
static
final
String
TAG_BYTERANGE
=
"#EXT-X-BYTERANGE"
;
private
static
final
String
TAG_DATERANGE
=
"#EXT-X-DATERANGE"
;
private
static
final
String
TYPE_AUDIO
=
"AUDIO"
;
private
static
final
String
TYPE_AUDIO
=
"AUDIO"
;
private
static
final
String
TYPE_VIDEO
=
"VIDEO"
;
private
static
final
String
TYPE_VIDEO
=
"VIDEO"
;
...
@@ -69,6 +71,8 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
...
@@ -69,6 +71,8 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
private
static
final
String
BOOLEAN_TRUE
=
"YES"
;
private
static
final
String
BOOLEAN_TRUE
=
"YES"
;
private
static
final
String
BOOLEAN_FALSE
=
"NO"
;
private
static
final
String
BOOLEAN_FALSE
=
"NO"
;
private
static
final
String
ATTR_CLOSED_CAPTIONS_NONE
=
"CLOSED-CAPTIONS=NONE"
;
private
static
final
Pattern
REGEX_BANDWIDTH
=
Pattern
.
compile
(
"BANDWIDTH=(\\d+)\\b"
);
private
static
final
Pattern
REGEX_BANDWIDTH
=
Pattern
.
compile
(
"BANDWIDTH=(\\d+)\\b"
);
private
static
final
Pattern
REGEX_CODECS
=
Pattern
.
compile
(
"CODECS=\"(.+?)\""
);
private
static
final
Pattern
REGEX_CODECS
=
Pattern
.
compile
(
"CODECS=\"(.+?)\""
);
private
static
final
Pattern
REGEX_RESOLUTION
=
Pattern
.
compile
(
"RESOLUTION=(\\d+x\\d+)"
);
private
static
final
Pattern
REGEX_RESOLUTION
=
Pattern
.
compile
(
"RESOLUTION=(\\d+x\\d+)"
);
...
@@ -172,7 +176,8 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
...
@@ -172,7 +176,8 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
ArrayList
<
HlsMasterPlaylist
.
HlsUrl
>
audios
=
new
ArrayList
<>();
ArrayList
<
HlsMasterPlaylist
.
HlsUrl
>
audios
=
new
ArrayList
<>();
ArrayList
<
HlsMasterPlaylist
.
HlsUrl
>
subtitles
=
new
ArrayList
<>();
ArrayList
<
HlsMasterPlaylist
.
HlsUrl
>
subtitles
=
new
ArrayList
<>();
Format
muxedAudioFormat
=
null
;
Format
muxedAudioFormat
=
null
;
ArrayList
<
Format
>
muxedCaptionFormats
=
new
ArrayList
<>();
List
<
Format
>
muxedCaptionFormats
=
null
;
boolean
noClosedCaptions
=
false
;
String
line
;
String
line
;
while
(
iterator
.
hasNext
())
{
while
(
iterator
.
hasNext
())
{
...
@@ -209,6 +214,9 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
...
@@ -209,6 +214,9 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
mimeType
=
MimeTypes
.
APPLICATION_CEA708
;
mimeType
=
MimeTypes
.
APPLICATION_CEA708
;
accessibilityChannel
=
Integer
.
parseInt
(
instreamId
.
substring
(
7
));
accessibilityChannel
=
Integer
.
parseInt
(
instreamId
.
substring
(
7
));
}
}
if
(
muxedCaptionFormats
==
null
)
{
muxedCaptionFormats
=
new
ArrayList
<>();
}
muxedCaptionFormats
.
add
(
Format
.
createTextContainerFormat
(
id
,
null
,
mimeType
,
null
,
muxedCaptionFormats
.
add
(
Format
.
createTextContainerFormat
(
id
,
null
,
mimeType
,
null
,
Format
.
NO_VALUE
,
selectionFlags
,
language
,
accessibilityChannel
));
Format
.
NO_VALUE
,
selectionFlags
,
language
,
accessibilityChannel
));
break
;
break
;
...
@@ -220,6 +228,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
...
@@ -220,6 +228,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
int
bitrate
=
parseIntAttr
(
line
,
REGEX_BANDWIDTH
);
int
bitrate
=
parseIntAttr
(
line
,
REGEX_BANDWIDTH
);
String
codecs
=
parseOptionalStringAttr
(
line
,
REGEX_CODECS
);
String
codecs
=
parseOptionalStringAttr
(
line
,
REGEX_CODECS
);
String
resolutionString
=
parseOptionalStringAttr
(
line
,
REGEX_RESOLUTION
);
String
resolutionString
=
parseOptionalStringAttr
(
line
,
REGEX_RESOLUTION
);
noClosedCaptions
|=
line
.
contains
(
ATTR_CLOSED_CAPTIONS_NONE
);
int
width
;
int
width
;
int
height
;
int
height
;
if
(
resolutionString
!=
null
)
{
if
(
resolutionString
!=
null
)
{
...
@@ -242,6 +251,9 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
...
@@ -242,6 +251,9 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
variants
.
add
(
new
HlsMasterPlaylist
.
HlsUrl
(
line
,
format
));
variants
.
add
(
new
HlsMasterPlaylist
.
HlsUrl
(
line
,
format
));
}
}
}
}
if
(
noClosedCaptions
)
{
muxedCaptionFormats
=
Collections
.
emptyList
();
}
return
new
HlsMasterPlaylist
(
baseUri
,
variants
,
audios
,
subtitles
,
muxedAudioFormat
,
return
new
HlsMasterPlaylist
(
baseUri
,
variants
,
audios
,
subtitles
,
muxedAudioFormat
,
muxedCaptionFormats
);
muxedCaptionFormats
);
}
}
...
@@ -263,6 +275,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
...
@@ -263,6 +275,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
boolean
hasEndTag
=
false
;
boolean
hasEndTag
=
false
;
Segment
initializationSegment
=
null
;
Segment
initializationSegment
=
null
;
List
<
Segment
>
segments
=
new
ArrayList
<>();
List
<
Segment
>
segments
=
new
ArrayList
<>();
List
<
String
>
dateRanges
=
new
ArrayList
<>();
long
segmentDurationUs
=
0
;
long
segmentDurationUs
=
0
;
boolean
hasDiscontinuitySequence
=
false
;
boolean
hasDiscontinuitySequence
=
false
;
...
@@ -343,6 +356,8 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
...
@@ -343,6 +356,8 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
C
.
msToUs
(
Util
.
parseXsDateTime
(
line
.
substring
(
line
.
indexOf
(
':'
)
+
1
)));
C
.
msToUs
(
Util
.
parseXsDateTime
(
line
.
substring
(
line
.
indexOf
(
':'
)
+
1
)));
playlistStartTimeUs
=
programDatetimeUs
-
segmentStartTimeUs
;
playlistStartTimeUs
=
programDatetimeUs
-
segmentStartTimeUs
;
}
}
}
else
if
(
line
.
startsWith
(
TAG_DATERANGE
))
{
dateRanges
.
add
(
line
);
}
else
if
(!
line
.
startsWith
(
"#"
))
{
}
else
if
(!
line
.
startsWith
(
"#"
))
{
String
segmentEncryptionIV
;
String
segmentEncryptionIV
;
if
(!
isEncrypted
)
{
if
(!
isEncrypted
)
{
...
@@ -371,7 +386,8 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
...
@@ -371,7 +386,8 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
}
}
return
new
HlsMediaPlaylist
(
playlistType
,
baseUri
,
startOffsetUs
,
playlistStartTimeUs
,
return
new
HlsMediaPlaylist
(
playlistType
,
baseUri
,
startOffsetUs
,
playlistStartTimeUs
,
hasDiscontinuitySequence
,
playlistDiscontinuitySequence
,
mediaSequence
,
version
,
hasDiscontinuitySequence
,
playlistDiscontinuitySequence
,
mediaSequence
,
version
,
targetDurationUs
,
hasEndTag
,
playlistStartTimeUs
!=
0
,
initializationSegment
,
segments
);
targetDurationUs
,
hasEndTag
,
playlistStartTimeUs
!=
0
,
initializationSegment
,
segments
,
dateRanges
);
}
}
private
static
String
parseStringAttr
(
String
line
,
Pattern
pattern
)
throws
ParserException
{
private
static
String
parseStringAttr
(
String
line
,
Pattern
pattern
)
throws
ParserException
{
...
...
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistTracker.java
View file @
9f814850
...
@@ -200,19 +200,30 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
...
@@ -200,19 +200,30 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
}
}
/**
/**
* If the tracker is having trouble refreshing the
primary playlist or loading an irreplaceable
* If the tracker is having trouble refreshing the
master playlist or the primary playlist, this
*
playlist, this
method throws the underlying error. Otherwise, does nothing.
* method throws the underlying error. Otherwise, does nothing.
*
*
* @throws IOException The underlying error.
* @throws IOException The underlying error.
*/
*/
public
void
maybeThrowPlaylistRefreshError
()
throws
IOException
{
public
void
maybeThrowP
rimaryP
laylistRefreshError
()
throws
IOException
{
initialPlaylistLoader
.
maybeThrowError
();
initialPlaylistLoader
.
maybeThrowError
();
if
(
primaryHlsUrl
!=
null
)
{
if
(
primaryHlsUrl
!=
null
)
{
playlistBundles
.
get
(
primaryHlsUrl
).
mediaPlaylistLoader
.
maybeThrowError
(
);
maybeThrowPlaylistRefreshError
(
primaryHlsUrl
);
}
}
}
}
/**
/**
* If the playlist is having trouble loading the playlist referenced by the given {@link HlsUrl},
* this method throws the underlying error.
*
* @param url The {@link HlsUrl}.
* @throws IOException The underyling error.
*/
public
void
maybeThrowPlaylistRefreshError
(
HlsUrl
url
)
throws
IOException
{
playlistBundles
.
get
(
url
).
mediaPlaylistLoader
.
maybeThrowError
();
}
/**
* Triggers a playlist refresh and whitelists it.
* Triggers a playlist refresh and whitelists it.
*
*
* @param url The {@link HlsUrl} of the playlist to be refreshed.
* @param url The {@link HlsUrl} of the playlist to be refreshed.
...
...
library/ui/src/main/java/com/google/android/exoplayer2/ui/DefaultTimeBar.java
View file @
9f814850
...
@@ -61,22 +61,21 @@ public class DefaultTimeBar extends View implements TimeBar {
...
@@ -61,22 +61,21 @@ public class DefaultTimeBar extends View implements TimeBar {
private
static
final
int
DEFAULT_INCREMENT_COUNT
=
20
;
private
static
final
int
DEFAULT_INCREMENT_COUNT
=
20
;
private
static
final
int
DEFAULT_BAR_HEIGHT
=
4
;
private
static
final
int
DEFAULT_BAR_HEIGHT
=
4
;
private
static
final
int
DEFAULT_TOUCH_TARGET_HEIGHT
=
26
;
private
static
final
int
DEFAULT_TOUCH_TARGET_HEIGHT
=
26
;
private
static
final
int
DEFAULT_PLAYED_COLOR
=
0x33FFFFFF
;
private
static
final
int
DEFAULT_PLAYED_COLOR
=
0xFFFFFFFF
;
private
static
final
int
DEFAULT_BUFFERED_COLOR
=
0xCCFFFFFF
;
private
static
final
int
DEFAULT_AD_MARKER_COLOR
=
0xB2FFFF00
;
private
static
final
int
DEFAULT_AD_MARKER_COLOR
=
0xB2FFFF00
;
private
static
final
int
DEFAULT_AD_MARKER_WIDTH
=
4
;
private
static
final
int
DEFAULT_AD_MARKER_WIDTH
=
4
;
private
static
final
int
DEFAULT_SCRUBBER_ENABLED_SIZE
=
12
;
private
static
final
int
DEFAULT_SCRUBBER_ENABLED_SIZE
=
12
;
private
static
final
int
DEFAULT_SCRUBBER_DISABLED_SIZE
=
0
;
private
static
final
int
DEFAULT_SCRUBBER_DISABLED_SIZE
=
0
;
private
static
final
int
DEFAULT_SCRUBBER_DRAGGED_SIZE
=
16
;
private
static
final
int
DEFAULT_SCRUBBER_DRAGGED_SIZE
=
16
;
private
static
final
int
OPAQUE_COLOR
=
0xFF000000
;
private
final
Rect
seekBounds
;
private
final
Rect
seekBounds
;
private
final
Rect
progressBar
;
private
final
Rect
progressBar
;
private
final
Rect
bufferedBar
;
private
final
Rect
bufferedBar
;
private
final
Rect
scrubberBar
;
private
final
Rect
scrubberBar
;
private
final
Paint
progressPaint
;
private
final
Paint
playedPaint
;
private
final
Paint
bufferedPaint
;
private
final
Paint
scrubberPaint
;
private
final
Paint
scrubberPaint
;
private
final
Paint
bufferedPaint
;
private
final
Paint
unplayedPaint
;
private
final
Paint
adMarkerPaint
;
private
final
Paint
adMarkerPaint
;
private
final
int
barHeight
;
private
final
int
barHeight
;
private
final
int
touchTargetHeight
;
private
final
int
touchTargetHeight
;
...
@@ -115,9 +114,10 @@ public class DefaultTimeBar extends View implements TimeBar {
...
@@ -115,9 +114,10 @@ public class DefaultTimeBar extends View implements TimeBar {
progressBar
=
new
Rect
();
progressBar
=
new
Rect
();
bufferedBar
=
new
Rect
();
bufferedBar
=
new
Rect
();
scrubberBar
=
new
Rect
();
scrubberBar
=
new
Rect
();
progressPaint
=
new
Paint
();
playedPaint
=
new
Paint
();
bufferedPaint
=
new
Paint
();
scrubberPaint
=
new
Paint
();
scrubberPaint
=
new
Paint
();
bufferedPaint
=
new
Paint
();
unplayedPaint
=
new
Paint
();
adMarkerPaint
=
new
Paint
();
adMarkerPaint
=
new
Paint
();
// Calculate the dimensions and paints for drawn elements.
// Calculate the dimensions and paints for drawn elements.
...
@@ -147,13 +147,18 @@ public class DefaultTimeBar extends View implements TimeBar {
...
@@ -147,13 +147,18 @@ public class DefaultTimeBar extends View implements TimeBar {
scrubberDraggedSize
=
a
.
getDimensionPixelSize
(
scrubberDraggedSize
=
a
.
getDimensionPixelSize
(
R
.
styleable
.
DefaultTimeBar_scrubber_dragged_size
,
defaultScrubberDraggedSize
);
R
.
styleable
.
DefaultTimeBar_scrubber_dragged_size
,
defaultScrubberDraggedSize
);
int
playedColor
=
a
.
getInt
(
R
.
styleable
.
DefaultTimeBar_played_color
,
DEFAULT_PLAYED_COLOR
);
int
playedColor
=
a
.
getInt
(
R
.
styleable
.
DefaultTimeBar_played_color
,
DEFAULT_PLAYED_COLOR
);
int
scrubberColor
=
a
.
getInt
(
R
.
styleable
.
DefaultTimeBar_scrubber_color
,
getDefaultScrubberColor
(
playedColor
));
int
bufferedColor
=
a
.
getInt
(
R
.
styleable
.
DefaultTimeBar_buffered_color
,
int
bufferedColor
=
a
.
getInt
(
R
.
styleable
.
DefaultTimeBar_buffered_color
,
DEFAULT_BUFFERED_COLOR
);
getDefaultBufferedColor
(
playedColor
));
int
unplayedColor
=
a
.
getInt
(
R
.
styleable
.
DefaultTimeBar_unplayed_color
,
getDefaultUnplayedColor
(
playedColor
));
int
adMarkerColor
=
a
.
getInt
(
R
.
styleable
.
DefaultTimeBar_ad_marker_color
,
int
adMarkerColor
=
a
.
getInt
(
R
.
styleable
.
DefaultTimeBar_ad_marker_color
,
DEFAULT_AD_MARKER_COLOR
);
DEFAULT_AD_MARKER_COLOR
);
p
rogress
Paint
.
setColor
(
playedColor
);
p
layed
Paint
.
setColor
(
playedColor
);
scrubberPaint
.
setColor
(
OPAQUE_COLOR
|
played
Color
);
scrubberPaint
.
setColor
(
scrubber
Color
);
bufferedPaint
.
setColor
(
bufferedColor
);
bufferedPaint
.
setColor
(
bufferedColor
);
unplayedPaint
.
setColor
(
unplayedColor
);
adMarkerPaint
.
setColor
(
adMarkerColor
);
adMarkerPaint
.
setColor
(
adMarkerColor
);
}
finally
{
}
finally
{
a
.
recycle
();
a
.
recycle
();
...
@@ -165,9 +170,10 @@ public class DefaultTimeBar extends View implements TimeBar {
...
@@ -165,9 +170,10 @@ public class DefaultTimeBar extends View implements TimeBar {
scrubberEnabledSize
=
defaultScrubberEnabledSize
;
scrubberEnabledSize
=
defaultScrubberEnabledSize
;
scrubberDisabledSize
=
defaultScrubberDisabledSize
;
scrubberDisabledSize
=
defaultScrubberDisabledSize
;
scrubberDraggedSize
=
defaultScrubberDraggedSize
;
scrubberDraggedSize
=
defaultScrubberDraggedSize
;
scrubberPaint
.
setColor
(
OPAQUE_COLOR
|
DEFAULT_PLAYED_COLOR
);
playedPaint
.
setColor
(
DEFAULT_PLAYED_COLOR
);
progressPaint
.
setColor
(
DEFAULT_PLAYED_COLOR
);
scrubberPaint
.
setColor
(
getDefaultScrubberColor
(
DEFAULT_PLAYED_COLOR
));
bufferedPaint
.
setColor
(
DEFAULT_BUFFERED_COLOR
);
bufferedPaint
.
setColor
(
getDefaultBufferedColor
(
DEFAULT_PLAYED_COLOR
));
unplayedPaint
.
setColor
(
getDefaultUnplayedColor
(
DEFAULT_PLAYED_COLOR
));
adMarkerPaint
.
setColor
(
DEFAULT_AD_MARKER_COLOR
);
adMarkerPaint
.
setColor
(
DEFAULT_AD_MARKER_COLOR
);
}
}
formatBuilder
=
new
StringBuilder
();
formatBuilder
=
new
StringBuilder
();
...
@@ -337,16 +343,18 @@ public class DefaultTimeBar extends View implements TimeBar {
...
@@ -337,16 +343,18 @@ public class DefaultTimeBar extends View implements TimeBar {
@Override
@Override
protected
void
onMeasure
(
int
widthMeasureSpec
,
int
heightMeasureSpec
)
{
protected
void
onMeasure
(
int
widthMeasureSpec
,
int
heightMeasureSpec
)
{
int
measureWidth
=
MeasureSpec
.
getSize
(
widthMeasureSpec
);
int
heightMode
=
MeasureSpec
.
getMode
(
heightMeasureSpec
);
int
measureHeight
=
MeasureSpec
.
getSize
(
heightMeasureSpec
);
int
heightSize
=
MeasureSpec
.
getSize
(
heightMeasureSpec
);
setMeasuredDimension
(
measureWidth
,
measureHeight
);
int
height
=
heightMode
==
MeasureSpec
.
UNSPECIFIED
?
touchTargetHeight
:
heightMode
==
MeasureSpec
.
EXACTLY
?
heightSize
:
Math
.
min
(
touchTargetHeight
,
heightSize
);
setMeasuredDimension
(
MeasureSpec
.
getSize
(
widthMeasureSpec
),
height
);
}
}
@Override
@Override
protected
void
onLayout
(
boolean
changed
,
int
left
,
int
top
,
int
right
,
int
bottom
)
{
protected
void
onLayout
(
boolean
changed
,
int
left
,
int
top
,
int
right
,
int
bottom
)
{
int
width
=
right
-
left
;
int
width
=
right
-
left
;
int
height
=
bottom
-
top
;
int
height
=
bottom
-
top
;
int
barY
=
height
-
touchTargetHeight
;
int
barY
=
(
height
-
touchTargetHeight
)
/
2
;
int
seekLeft
=
getPaddingLeft
();
int
seekLeft
=
getPaddingLeft
();
int
seekRight
=
width
-
getPaddingRight
();
int
seekRight
=
width
-
getPaddingRight
();
int
progressY
=
barY
+
(
touchTargetHeight
-
barHeight
)
/
2
;
int
progressY
=
barY
+
(
touchTargetHeight
-
barHeight
)
/
2
;
...
@@ -457,12 +465,10 @@ public class DefaultTimeBar extends View implements TimeBar {
...
@@ -457,12 +465,10 @@ public class DefaultTimeBar extends View implements TimeBar {
scrubberBar
.
set
(
progressBar
);
scrubberBar
.
set
(
progressBar
);
long
newScrubberTime
=
scrubbing
?
scrubPosition
:
position
;
long
newScrubberTime
=
scrubbing
?
scrubPosition
:
position
;
if
(
duration
>
0
)
{
if
(
duration
>
0
)
{
int
bufferedPixelWidth
=
int
bufferedPixelWidth
=
(
int
)
((
progressBar
.
width
()
*
bufferedPosition
)
/
duration
);
(
int
)
((
progressBar
.
width
()
*
bufferedPosition
)
/
duration
);
bufferedBar
.
right
=
Math
.
min
(
progressBar
.
left
+
bufferedPixelWidth
,
progressBar
.
right
);
bufferedBar
.
right
=
progressBar
.
left
+
bufferedPixelWidth
;
int
scrubberPixelPosition
=
(
int
)
((
progressBar
.
width
()
*
newScrubberTime
)
/
duration
);
int
scrubberPixelPosition
=
scrubberBar
.
right
=
Math
.
min
(
progressBar
.
left
+
scrubberPixelPosition
,
progressBar
.
right
);
(
int
)
((
progressBar
.
width
()
*
newScrubberTime
)
/
duration
);
scrubberBar
.
right
=
progressBar
.
left
+
scrubberPixelPosition
;
}
else
{
}
else
{
bufferedBar
.
right
=
progressBar
.
left
;
bufferedBar
.
right
=
progressBar
.
left
;
scrubberBar
.
right
=
progressBar
.
left
;
scrubberBar
.
right
=
progressBar
.
left
;
...
@@ -502,21 +508,21 @@ public class DefaultTimeBar extends View implements TimeBar {
...
@@ -502,21 +508,21 @@ public class DefaultTimeBar extends View implements TimeBar {
int
barTop
=
progressBar
.
centerY
()
-
progressBarHeight
/
2
;
int
barTop
=
progressBar
.
centerY
()
-
progressBarHeight
/
2
;
int
barBottom
=
barTop
+
progressBarHeight
;
int
barBottom
=
barTop
+
progressBarHeight
;
if
(
duration
<=
0
)
{
if
(
duration
<=
0
)
{
canvas
.
drawRect
(
progressBar
.
left
,
barTop
,
progressBar
.
right
,
barBottom
,
progress
Paint
);
canvas
.
drawRect
(
progressBar
.
left
,
barTop
,
progressBar
.
right
,
barBottom
,
unplayed
Paint
);
return
;
return
;
}
}
int
bufferedLeft
=
bufferedBar
.
left
;
int
bufferedLeft
=
bufferedBar
.
left
;
int
bufferedRight
=
bufferedBar
.
right
;
int
bufferedRight
=
bufferedBar
.
right
;
int
progressLeft
=
Math
.
max
(
Math
.
max
(
progressBar
.
left
,
bufferedRight
),
scrubberBar
.
right
);
int
progressLeft
=
Math
.
max
(
Math
.
max
(
progressBar
.
left
,
bufferedRight
),
scrubberBar
.
right
);
if
(
progressLeft
<
progressBar
.
right
)
{
if
(
progressLeft
<
progressBar
.
right
)
{
canvas
.
drawRect
(
progressLeft
,
barTop
,
progressBar
.
right
,
barBottom
,
progress
Paint
);
canvas
.
drawRect
(
progressLeft
,
barTop
,
progressBar
.
right
,
barBottom
,
unplayed
Paint
);
}
}
bufferedLeft
=
Math
.
max
(
bufferedLeft
,
scrubberBar
.
right
);
bufferedLeft
=
Math
.
max
(
bufferedLeft
,
scrubberBar
.
right
);
if
(
bufferedRight
>
bufferedLeft
)
{
if
(
bufferedRight
>
bufferedLeft
)
{
canvas
.
drawRect
(
bufferedLeft
,
barTop
,
bufferedRight
,
barBottom
,
bufferedPaint
);
canvas
.
drawRect
(
bufferedLeft
,
barTop
,
bufferedRight
,
barBottom
,
bufferedPaint
);
}
}
if
(
scrubberBar
.
width
()
>
0
)
{
if
(
scrubberBar
.
width
()
>
0
)
{
canvas
.
drawRect
(
scrubberBar
.
left
,
barTop
,
scrubberBar
.
right
,
barBottom
,
scrubber
Paint
);
canvas
.
drawRect
(
scrubberBar
.
left
,
barTop
,
scrubberBar
.
right
,
barBottom
,
played
Paint
);
}
}
int
adMarkerOffset
=
adMarkerWidth
/
2
;
int
adMarkerOffset
=
adMarkerWidth
/
2
;
for
(
int
i
=
0
;
i
<
adBreakCount
;
i
++)
{
for
(
int
i
=
0
;
i
<
adBreakCount
;
i
++)
{
...
@@ -577,4 +583,16 @@ public class DefaultTimeBar extends View implements TimeBar {
...
@@ -577,4 +583,16 @@ public class DefaultTimeBar extends View implements TimeBar {
return
(
int
)
(
dps
*
displayMetrics
.
density
+
0.5f
);
return
(
int
)
(
dps
*
displayMetrics
.
density
+
0.5f
);
}
}
private
static
int
getDefaultScrubberColor
(
int
playedColor
)
{
return
0xFF000000
|
playedColor
;
}
private
static
int
getDefaultUnplayedColor
(
int
playedColor
)
{
return
0x33000000
|
(
playedColor
&
0x00FFFFFF
);
}
private
static
int
getDefaultBufferedColor
(
int
playedColor
)
{
return
0xCC000000
|
(
playedColor
&
0x00FFFFFF
);
}
}
}
library/ui/src/main/res/values/attrs.xml
View file @
9f814850
...
@@ -68,7 +68,9 @@
...
@@ -68,7 +68,9 @@
<attr
name=
"scrubber_disabled_size"
format=
"dimension"
/>
<attr
name=
"scrubber_disabled_size"
format=
"dimension"
/>
<attr
name=
"scrubber_dragged_size"
format=
"dimension"
/>
<attr
name=
"scrubber_dragged_size"
format=
"dimension"
/>
<attr
name=
"played_color"
format=
"color"
/>
<attr
name=
"played_color"
format=
"color"
/>
<attr
name=
"scrubber_color"
format=
"color"
/>
<attr
name=
"buffered_color"
format=
"color"
/>
<attr
name=
"buffered_color"
format=
"color"
/>
<attr
name=
"unplayed_color"
format=
"color"
/>
<attr
name=
"ad_marker_color"
format=
"color"
/>
<attr
name=
"ad_marker_color"
format=
"color"
/>
</declare-styleable>
</declare-styleable>
...
...
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