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
f94218a7
authored
Oct 06, 2016
by
ojw28
Committed by
GitHub
Oct 06, 2016
Browse files
Options
_('Browse Files')
Download
Plain Diff
Merge pull request #1905 from google/dev-v2
r2.0.2
parents
f8a8302f
6c12ec62
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
55 changed files
with
693 additions
and
246 deletions
README.md
RELEASENOTES.md
build.gradle
demo/src/main/AndroidManifest.xml
demo/src/main/assets/media.exolist.json
extensions/cronet/src/main/java/com/google/android/exoplayer2/ext/cronet/CronetDataSource.java
extensions/okhttp/README.md
extensions/okhttp/build.gradle
extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSource.java
library/build.gradle
library/src/androidTest/java/com/google/android/exoplayer2/extractor/ts/TsExtractorTest.java
library/src/main/java/com/google/android/exoplayer2/DefaultLoadControl.java
library/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java
library/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java
library/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java
library/src/main/java/com/google/android/exoplayer2/LoadControl.java
library/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java
library/src/main/java/com/google/android/exoplayer2/audio/Ac3Util.java
library/src/main/java/com/google/android/exoplayer2/extractor/ts/TimestampAdjuster.java → library/src/main/java/com/google/android/exoplayer2/extractor/TimestampAdjuster.java
library/src/main/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.java
library/src/main/java/com/google/android/exoplayer2/extractor/ts/Ac3Extractor.java
library/src/main/java/com/google/android/exoplayer2/extractor/ts/PsExtractor.java
library/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java
library/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java
library/src/main/java/com/google/android/exoplayer2/source/MergingMediaPeriod.java
library/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaPeriod.java
library/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.java
library/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java
library/src/main/java/com/google/android/exoplayer2/source/hls/HlsInitializationChunk.java
library/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunk.java
library/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java
library/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java
library/src/main/java/com/google/android/exoplayer2/source/hls/TimestampAdjusterProvider.java
library/src/main/java/com/google/android/exoplayer2/source/hls/WebvttExtractor.java
library/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMediaPlaylist.java
library/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java
library/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/DefaultSsChunkSource.java
library/src/main/java/com/google/android/exoplayer2/text/TextRenderer.java
library/src/main/java/com/google/android/exoplayer2/ui/AspectRatioFrameLayout.java
library/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java
library/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java
library/src/main/java/com/google/android/exoplayer2/upstream/AssetDataSource.java
library/src/main/java/com/google/android/exoplayer2/upstream/ByteArrayDataSource.java
library/src/main/java/com/google/android/exoplayer2/upstream/ContentDataSource.java
library/src/main/java/com/google/android/exoplayer2/upstream/DataSource.java
library/src/main/java/com/google/android/exoplayer2/upstream/DefaultAllocator.java
library/src/main/java/com/google/android/exoplayer2/upstream/DefaultHttpDataSource.java
library/src/main/java/com/google/android/exoplayer2/upstream/FileDataSource.java
library/src/main/java/com/google/android/exoplayer2/upstream/RawResourceDataSource.java
library/src/main/java/com/google/android/exoplayer2/upstream/UdpDataSource.java
library/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSource.java
library/src/main/res/layout/exo_simple_player_view.xml
library/src/main/res/values/attrs.xml
playbacktests/src/main/AndroidManifest.xml
playbacktests/src/main/java/com/google/android/exoplayer2/playbacktests/gts/DashTest.java
README.md
View file @
f94218a7
...
@@ -20,8 +20,6 @@ and extend, and can be updated through Play Store application updates.
...
@@ -20,8 +20,6 @@ and extend, and can be updated through Play Store application updates.
## Using ExoPlayer ##
## Using ExoPlayer ##
#### Via jCenter ####
The easiest way to get started using ExoPlayer is to add it as a gradle
The easiest way to get started using ExoPlayer is to add it as a gradle
dependency. You need to make sure you have the jcenter repository included in
dependency. You need to make sure you have the jcenter repository included in
the
`build.gradle`
file in the root of your project:
the
`build.gradle`
file in the root of your project:
...
@@ -44,31 +42,6 @@ project's [Releases][]. For more details, see the project on [Bintray][].
...
@@ -44,31 +42,6 @@ project's [Releases][]. For more details, see the project on [Bintray][].
[
Releases
]:
https://github.com/google/ExoPlayer/releases
[
Releases
]:
https://github.com/google/ExoPlayer/releases
[
Bintray
]:
https://bintray.com/google/exoplayer/exoplayer/view
[
Bintray
]:
https://bintray.com/google/exoplayer/exoplayer/view
#### As source ####
ExoPlayer can also be built from source using Gradle. You can include it as a
dependent project like so:
```
gradle
// settings.gradle
include
':app'
,
':..:ExoPlayer:library'
// app/build.gradle
dependencies
{
compile
project
(
':..:ExoPlayer:library'
)
}
```
#### As a jar ####
If you want to use ExoPlayer as a jar, run:
```
sh
./gradlew jarRelease
```
and copy
`library.jar`
to the libs folder of your new project.
## Developing ExoPlayer ##
## Developing ExoPlayer ##
#### Project branches ####
#### Project branches ####
...
...
RELEASENOTES.md
View file @
f94218a7
# Release notes #
# Release notes #
### r2.0.2 ###
*
Fixes for MergingMediaSource and sideloaded subtitles.
(
[
#1882
](
https://github.com/google/ExoPlayer/issues/1882
)
,
[
#1854
](
https://github.com/google/ExoPlayer/issues/1854
)
,
[
#1900
](
https://github.com/google/ExoPlayer/issues/1900
)
).
*
Reduced effect of application code leaking player references
(
[
#1855
](
https://github.com/google/ExoPlayer/issues/1855
)
).
*
Initial support for fragmented MP4 in HLS.
*
Misc bug fixes and minor features.
### r2.0.1 ###
### r2.0.1 ###
*
Fix playback of short duration content
*
Fix playback of short duration content
...
...
build.gradle
View file @
f94218a7
...
@@ -16,7 +16,6 @@
...
@@ -16,7 +16,6 @@
buildscript
{
buildscript
{
repositories
{
repositories
{
mavenCentral
()
jcenter
()
jcenter
()
}
}
dependencies
{
dependencies
{
...
@@ -27,11 +26,16 @@ buildscript {
...
@@ -27,11 +26,16 @@ buildscript {
allprojects
{
allprojects
{
repositories
{
repositories
{
mavenCentral
()
jcenter
()
}
}
project
.
ext
{
project
.
ext
{
compileSdkVersion
=
24
compileSdkVersion
=
24
targetSdkVersion
=
24
targetSdkVersion
=
24
buildToolsVersion
=
'23.0.3'
buildToolsVersion
=
'23.0.3'
releaseRepoName
=
'exoplayer'
releaseUserOrg
=
'google'
releaseGroupId
=
'com.google.android.exoplayer'
releaseVersion
=
'r2.0.2'
releaseWebsite
=
'https://github.com/google/ExoPlayer'
}
}
}
}
demo/src/main/AndroidManifest.xml
View file @
f94218a7
...
@@ -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=
"200
1
"
android:versionCode=
"200
2
"
android:versionName=
"2.0.
1
"
>
android:versionName=
"2.0.
2
"
>
<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/assets/media.exolist.json
View file @
f94218a7
...
@@ -303,10 +303,14 @@
...
@@ -303,10 +303,14 @@
"uri"
:
"https://devimages.apple.com.edgekey.net/streaming/examples/bipbop_16x9/bipbop_16x9_variant.m3u8"
"uri"
:
"https://devimages.apple.com.edgekey.net/streaming/examples/bipbop_16x9/bipbop_16x9_variant.m3u8"
},
},
{
{
"name"
:
"Apple master playlist advanced"
,
"name"
:
"Apple master playlist advanced
(TS)
"
,
"uri"
:
"https://tungsten.aaplimg.com/VOD/bipbop_adv_example_v2/master.m3u8"
"uri"
:
"https://tungsten.aaplimg.com/VOD/bipbop_adv_example_v2/master.m3u8"
},
},
{
{
"name"
:
"Apple master playlist advanced (fMP4)"
,
"uri"
:
"https://tungsten.aaplimg.com/VOD/bipbop_adv_fmp4_example/master.m3u8"
},
{
"name"
:
"Apple TS media playlist"
,
"name"
:
"Apple TS media playlist"
,
"uri"
:
"https://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/gear1/prog_index.m3u8"
"uri"
:
"https://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/gear1/prog_index.m3u8"
},
},
...
...
extensions/cronet/src/main/java/com/google/android/exoplayer2/ext/cronet/CronetDataSource.java
View file @
f94218a7
This diff is collapsed.
Click to expand it.
extensions/okhttp/README.md
View file @
f94218a7
...
@@ -2,8 +2,29 @@
...
@@ -2,8 +2,29 @@
## Description ##
## Description ##
The OkHttp Extension is an
[
HttpDataSource
][]
implementation using Square's
[
OkHttp
][]
.
The OkHttp Extension is an
[
HttpDataSource
][]
implementation using Square's
[
OkHttp
][]
.
## Using the extension ##
The easiest way to use the extension is to add it as a gradle dependency. You
need to make sure you have the jcenter repository included in the
`build.gradle`
file in the root of your project:
```
gradle
repositories
{
jcenter
()
}
```
Next, include the following in your module's
`build.gradle`
file:
```
gradle
compile
'com.google.android.exoplayer:extension-okhttp:rX.X.X'
```
where
`rX.X.X`
is the version, which must match the version of the ExoPlayer
library being used.
[
HttpDataSource
]:
https://google.github.io/ExoPlayer/doc/reference/com/google/android/exoplayer2/upstream/HttpDataSource.html
[
HttpDataSource
]:
https://google.github.io/ExoPlayer/doc/reference/com/google/android/exoplayer2/upstream/HttpDataSource.html
[
OkHttp
]:
https://square.github.io/okhttp/
[
OkHttp
]:
https://square.github.io/okhttp/
extensions/okhttp/build.gradle
View file @
f94218a7
...
@@ -12,6 +12,7 @@
...
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// See the License for the specific language governing permissions and
// limitations under the License.
// limitations under the License.
apply
plugin:
'com.android.library'
apply
plugin:
'com.android.library'
apply
plugin:
'bintray-release'
android
{
android
{
compileSdkVersion
project
.
ext
.
compileSdkVersion
compileSdkVersion
project
.
ext
.
compileSdkVersion
...
@@ -40,3 +41,13 @@ dependencies {
...
@@ -40,3 +41,13 @@ dependencies {
exclude
group:
'org.json'
exclude
group:
'org.json'
}
}
}
}
publish
{
artifactId
=
'extension-okhttp'
description
=
'An OkHttp extension for ExoPlayer.'
repoName
=
releaseRepoName
userOrg
=
releaseUserOrg
groupId
=
releaseGroupId
version
=
releaseVersion
website
=
releaseWebsite
}
extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSource.java
View file @
f94218a7
...
@@ -338,17 +338,21 @@ public class OkHttpDataSource implements HttpDataSource {
...
@@ -338,17 +338,21 @@ public class OkHttpDataSource implements HttpDataSource {
* @throws IOException If an error occurs reading from the source.
* @throws IOException If an error occurs reading from the source.
*/
*/
private
int
readInternal
(
byte
[]
buffer
,
int
offset
,
int
readLength
)
throws
IOException
{
private
int
readInternal
(
byte
[]
buffer
,
int
offset
,
int
readLength
)
throws
IOException
{
readLength
=
bytesToRead
==
C
.
LENGTH_UNSET
?
readLength
:
(
int
)
Math
.
min
(
readLength
,
bytesToRead
-
bytesRead
);
if
(
readLength
==
0
)
{
if
(
readLength
==
0
)
{
// We've read all of the requested data.
return
0
;
return
C
.
RESULT_END_OF_INPUT
;
}
if
(
bytesToRead
!=
C
.
LENGTH_UNSET
)
{
long
bytesRemaining
=
bytesToRead
-
bytesRead
;
if
(
bytesRemaining
==
0
)
{
return
C
.
RESULT_END_OF_INPUT
;
}
readLength
=
(
int
)
Math
.
min
(
readLength
,
bytesRemaining
);
}
}
int
read
=
responseByteStream
.
read
(
buffer
,
offset
,
readLength
);
int
read
=
responseByteStream
.
read
(
buffer
,
offset
,
readLength
);
if
(
read
==
-
1
)
{
if
(
read
==
-
1
)
{
if
(
bytesToRead
!=
C
.
LENGTH_UNSET
&&
bytesToRead
!=
bytesRead
)
{
if
(
bytesToRead
!=
C
.
LENGTH_UNSET
)
{
//
The server closed the connection having not sent
sufficient data.
//
End of stream reached having not read
sufficient data.
throw
new
EOFException
();
throw
new
EOFException
();
}
}
return
C
.
RESULT_END_OF_INPUT
;
return
C
.
RESULT_END_OF_INPUT
;
...
...
library/build.gradle
View file @
f94218a7
...
@@ -92,11 +92,11 @@ android.libraryVariants.all { variant ->
...
@@ -92,11 +92,11 @@ android.libraryVariants.all { variant ->
}
}
publish
{
publish
{
repoName
=
'exoplayer'
userOrg
=
'google'
groupId
=
'com.google.android.exoplayer'
artifactId
=
'exoplayer'
artifactId
=
'exoplayer'
version
=
'r2.0.1'
description
=
'The ExoPlayer library.'
description
=
'The ExoPlayer library.'
website
=
'https://github.com/google/ExoPlayer'
repoName
=
releaseRepoName
userOrg
=
releaseUserOrg
groupId
=
releaseGroupId
version
=
releaseVersion
website
=
releaseWebsite
}
}
library/src/androidTest/java/com/google/android/exoplayer2/extractor/ts/TsExtractorTest.java
View file @
f94218a7
...
@@ -20,6 +20,7 @@ import com.google.android.exoplayer2.Format;
...
@@ -20,6 +20,7 @@ import com.google.android.exoplayer2.Format;
import
com.google.android.exoplayer2.extractor.Extractor
;
import
com.google.android.exoplayer2.extractor.Extractor
;
import
com.google.android.exoplayer2.extractor.ExtractorOutput
;
import
com.google.android.exoplayer2.extractor.ExtractorOutput
;
import
com.google.android.exoplayer2.extractor.PositionHolder
;
import
com.google.android.exoplayer2.extractor.PositionHolder
;
import
com.google.android.exoplayer2.extractor.TimestampAdjuster
;
import
com.google.android.exoplayer2.extractor.TrackOutput
;
import
com.google.android.exoplayer2.extractor.TrackOutput
;
import
com.google.android.exoplayer2.testutil.FakeExtractorInput
;
import
com.google.android.exoplayer2.testutil.FakeExtractorInput
;
import
com.google.android.exoplayer2.testutil.FakeExtractorOutput
;
import
com.google.android.exoplayer2.testutil.FakeExtractorOutput
;
...
...
library/src/main/java/com/google/android/exoplayer2/DefaultLoadControl.java
View file @
f94218a7
...
@@ -68,7 +68,7 @@ public final class DefaultLoadControl implements LoadControl {
...
@@ -68,7 +68,7 @@ public final class DefaultLoadControl implements LoadControl {
* Constructs a new instance, using the {@code DEFAULT_*} constants defined in this class.
* Constructs a new instance, using the {@code DEFAULT_*} constants defined in this class.
*/
*/
public
DefaultLoadControl
()
{
public
DefaultLoadControl
()
{
this
(
new
DefaultAllocator
(
C
.
DEFAULT_BUFFER_SEGMENT_SIZE
));
this
(
new
DefaultAllocator
(
true
,
C
.
DEFAULT_BUFFER_SEGMENT_SIZE
));
}
}
/**
/**
...
@@ -105,6 +105,11 @@ public final class DefaultLoadControl implements LoadControl {
...
@@ -105,6 +105,11 @@ public final class DefaultLoadControl implements LoadControl {
}
}
@Override
@Override
public
void
onPrepared
()
{
reset
(
false
);
}
@Override
public
void
onTracksSelected
(
Renderer
[]
renderers
,
TrackGroupArray
trackGroups
,
public
void
onTracksSelected
(
Renderer
[]
renderers
,
TrackGroupArray
trackGroups
,
TrackSelections
<?>
trackSelections
)
{
TrackSelections
<?>
trackSelections
)
{
targetBufferSize
=
0
;
targetBufferSize
=
0
;
...
@@ -117,9 +122,13 @@ public final class DefaultLoadControl implements LoadControl {
...
@@ -117,9 +122,13 @@ public final class DefaultLoadControl implements LoadControl {
}
}
@Override
@Override
public
void
onTracksDisabled
()
{
public
void
onStopped
()
{
targetBufferSize
=
0
;
reset
(
true
);
isBuffering
=
false
;
}
@Override
public
void
onReleased
()
{
reset
(
true
);
}
}
@Override
@Override
...
@@ -147,4 +156,12 @@ public final class DefaultLoadControl implements LoadControl {
...
@@ -147,4 +156,12 @@ public final class DefaultLoadControl implements LoadControl {
:
(
bufferedDurationUs
<
minBufferUs
?
BELOW_LOW_WATERMARK
:
BETWEEN_WATERMARKS
);
:
(
bufferedDurationUs
<
minBufferUs
?
BELOW_LOW_WATERMARK
:
BETWEEN_WATERMARKS
);
}
}
private
void
reset
(
boolean
resetAllocator
)
{
targetBufferSize
=
0
;
isBuffering
=
false
;
if
(
resetAllocator
)
{
allocator
.
reset
();
}
}
}
}
library/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java
View file @
f94218a7
...
@@ -106,7 +106,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
...
@@ -106,7 +106,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
@Override
@Override
public
void
prepare
(
MediaSource
mediaSource
,
boolean
resetPosition
)
{
public
void
prepare
(
MediaSource
mediaSource
,
boolean
resetPosition
)
{
timeline
=
null
;
timeline
=
null
;
internalPlayer
.
setMediaSourc
e
(
mediaSource
,
resetPosition
);
internalPlayer
.
prepar
e
(
mediaSource
,
resetPosition
);
}
}
@Override
@Override
...
...
library/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java
View file @
f94218a7
...
@@ -75,7 +75,7 @@ import java.io.IOException;
...
@@ -75,7 +75,7 @@ import java.io.IOException;
public
static
final
int
MSG_ERROR
=
6
;
public
static
final
int
MSG_ERROR
=
6
;
// Internal messages
// Internal messages
private
static
final
int
MSG_
SET_MEDIA_SOURC
E
=
0
;
private
static
final
int
MSG_
PREPAR
E
=
0
;
private
static
final
int
MSG_SET_PLAY_WHEN_READY
=
1
;
private
static
final
int
MSG_SET_PLAY_WHEN_READY
=
1
;
private
static
final
int
MSG_DO_SOME_WORK
=
2
;
private
static
final
int
MSG_DO_SOME_WORK
=
2
;
private
static
final
int
MSG_SEEK_TO
=
3
;
private
static
final
int
MSG_SEEK_TO
=
3
;
...
@@ -164,8 +164,8 @@ import java.io.IOException;
...
@@ -164,8 +164,8 @@ import java.io.IOException;
handler
=
new
Handler
(
internalPlaybackThread
.
getLooper
(),
this
);
handler
=
new
Handler
(
internalPlaybackThread
.
getLooper
(),
this
);
}
}
public
void
setMediaSourc
e
(
MediaSource
mediaSource
,
boolean
resetPosition
)
{
public
void
prepar
e
(
MediaSource
mediaSource
,
boolean
resetPosition
)
{
handler
.
obtainMessage
(
MSG_
SET_MEDIA_SOURC
E
,
resetPosition
?
1
:
0
,
0
,
mediaSource
)
handler
.
obtainMessage
(
MSG_
PREPAR
E
,
resetPosition
?
1
:
0
,
0
,
mediaSource
)
.
sendToTarget
();
.
sendToTarget
();
}
}
...
@@ -253,8 +253,8 @@ import java.io.IOException;
...
@@ -253,8 +253,8 @@ import java.io.IOException;
public
boolean
handleMessage
(
Message
msg
)
{
public
boolean
handleMessage
(
Message
msg
)
{
try
{
try
{
switch
(
msg
.
what
)
{
switch
(
msg
.
what
)
{
case
MSG_
SET_MEDIA_SOURC
E:
{
case
MSG_
PREPAR
E:
{
setMediaSourc
eInternal
((
MediaSource
)
msg
.
obj
,
msg
.
arg1
!=
0
);
prepar
eInternal
((
MediaSource
)
msg
.
obj
,
msg
.
arg1
!=
0
);
return
true
;
return
true
;
}
}
case
MSG_SET_PLAY_WHEN_READY:
{
case
MSG_SET_PLAY_WHEN_READY:
{
...
@@ -335,9 +335,10 @@ import java.io.IOException;
...
@@ -335,9 +335,10 @@ import java.io.IOException;
}
}
}
}
private
void
setMediaSourc
eInternal
(
MediaSource
mediaSource
,
boolean
resetPosition
)
private
void
prepar
eInternal
(
MediaSource
mediaSource
,
boolean
resetPosition
)
throws
ExoPlaybackException
{
throws
ExoPlaybackException
{
resetInternal
();
resetInternal
();
loadControl
.
onPrepared
();
if
(
resetPosition
)
{
if
(
resetPosition
)
{
playbackInfo
=
new
PlaybackInfo
(
0
,
C
.
TIME_UNSET
);
playbackInfo
=
new
PlaybackInfo
(
0
,
C
.
TIME_UNSET
);
}
}
...
@@ -597,11 +598,13 @@ import java.io.IOException;
...
@@ -597,11 +598,13 @@ import java.io.IOException;
private
void
stopInternal
()
{
private
void
stopInternal
()
{
resetInternal
();
resetInternal
();
loadControl
.
onStopped
();
setState
(
ExoPlayer
.
STATE_IDLE
);
setState
(
ExoPlayer
.
STATE_IDLE
);
}
}
private
void
releaseInternal
()
{
private
void
releaseInternal
()
{
resetInternal
();
resetInternal
();
loadControl
.
onReleased
();
setState
(
ExoPlayer
.
STATE_IDLE
);
setState
(
ExoPlayer
.
STATE_IDLE
);
synchronized
(
this
)
{
synchronized
(
this
)
{
released
=
true
;
released
=
true
;
...
@@ -638,7 +641,6 @@ import java.io.IOException;
...
@@ -638,7 +641,6 @@ import java.io.IOException;
loadingPeriodHolder
=
null
;
loadingPeriodHolder
=
null
;
timeline
=
null
;
timeline
=
null
;
bufferAheadPeriodCount
=
0
;
bufferAheadPeriodCount
=
0
;
loadControl
.
onTracksDisabled
();
setIsLoading
(
false
);
setIsLoading
(
false
);
}
}
...
@@ -1262,11 +1264,14 @@ import java.io.IOException;
...
@@ -1262,11 +1264,14 @@ import java.io.IOException;
sampleStreams
,
streamResetFlags
,
positionUs
);
sampleStreams
,
streamResetFlags
,
positionUs
);
periodTrackSelections
=
trackSelections
;
periodTrackSelections
=
trackSelections
;
// Update whether we have enabled tracks and sanity check the expected streams are non-null.
hasEnabledTracks
=
false
;
hasEnabledTracks
=
false
;
for
(
int
i
=
0
;
i
<
sampleStreams
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
sampleStreams
.
length
;
i
++)
{
if
(
sampleStreams
[
i
]
!=
null
)
{
if
(
sampleStreams
[
i
]
!=
null
)
{
Assertions
.
checkState
(
trackSelections
.
get
(
i
)
!=
null
);
hasEnabledTracks
=
true
;
hasEnabledTracks
=
true
;
break
;
}
else
{
Assertions
.
checkState
(
trackSelections
.
get
(
i
)
==
null
);
}
}
}
}
...
...
library/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java
View file @
f94218a7
...
@@ -23,7 +23,7 @@ public interface ExoPlayerLibraryInfo {
...
@@ -23,7 +23,7 @@ public interface ExoPlayerLibraryInfo {
/**
/**
* The version of the library, expressed as a string.
* The version of the library, expressed as a string.
*/
*/
String
VERSION
=
"2.0.
1
"
;
String
VERSION
=
"2.0.
2
"
;
/**
/**
* The version of the library, expressed as an integer.
* The version of the library, expressed as an integer.
...
@@ -32,7 +32,7 @@ public interface ExoPlayerLibraryInfo {
...
@@ -32,7 +32,7 @@ public interface ExoPlayerLibraryInfo {
* corresponding integer version 1002003 (001-002-003), and "123.45.6" has the corresponding
* corresponding integer version 1002003 (001-002-003), and "123.45.6" has the corresponding
* integer version 123045006 (123-045-006).
* integer version 123045006 (123-045-006).
*/
*/
int
VERSION_INT
=
200000
1
;
int
VERSION_INT
=
200000
2
;
/**
/**
* 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/src/main/java/com/google/android/exoplayer2/LoadControl.java
View file @
f94218a7
...
@@ -26,6 +26,11 @@ import com.google.android.exoplayer2.upstream.Allocator;
...
@@ -26,6 +26,11 @@ import com.google.android.exoplayer2.upstream.Allocator;
public
interface
LoadControl
{
public
interface
LoadControl
{
/**
/**
* Called by the player when prepared with a new source.
*/
void
onPrepared
();
/**
* Called by the player when a track selection occurs.
* Called by the player when a track selection occurs.
*
*
* @param renderers The renderers.
* @param renderers The renderers.
...
@@ -36,9 +41,14 @@ public interface LoadControl {
...
@@ -36,9 +41,14 @@ public interface LoadControl {
TrackSelections
<?>
trackSelections
);
TrackSelections
<?>
trackSelections
);
/**
/**
* Called by the player when all tracks are disabled.
* Called by the player when stopped.
*/
void
onStopped
();
/**
* Called by the player when released.
*/
*/
void
on
TracksDisabl
ed
();
void
on
Releas
ed
();
/**
/**
* Returns the {@link Allocator} that should be used to obtain media buffer allocations.
* Returns the {@link Allocator} that should be used to obtain media buffer allocations.
...
...
library/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java
View file @
f94218a7
...
@@ -184,6 +184,14 @@ public final class SimpleExoPlayer implements ExoPlayer {
...
@@ -184,6 +184,14 @@ public final class SimpleExoPlayer implements ExoPlayer {
}
}
/**
/**
* Clears any {@link Surface}, {@link SurfaceHolder}, {@link SurfaceView} or {@link TextureView}
* currently set on the player.
*/
public
void
clearVideoSurface
()
{
setVideoSurface
(
null
);
}
/**
* Sets the {@link Surface} onto which video will be rendered. The caller is responsible for
* Sets the {@link Surface} onto which video will be rendered. The caller is responsible for
* tracking the lifecycle of the surface, and must clear the surface by calling
* tracking the lifecycle of the surface, and must clear the surface by calling
* {@code setVideoSurface(null)} if the surface is destroyed.
* {@code setVideoSurface(null)} if the surface is destroyed.
...
@@ -240,6 +248,9 @@ public final class SimpleExoPlayer implements ExoPlayer {
...
@@ -240,6 +248,9 @@ public final class SimpleExoPlayer implements ExoPlayer {
if
(
textureView
==
null
)
{
if
(
textureView
==
null
)
{
setVideoSurfaceInternal
(
null
);
setVideoSurfaceInternal
(
null
);
}
else
{
}
else
{
if
(
textureView
.
getSurfaceTextureListener
()
!=
null
)
{
Log
.
w
(
TAG
,
"Replacing existing SurfaceTextureListener."
);
}
SurfaceTexture
surfaceTexture
=
textureView
.
getSurfaceTexture
();
SurfaceTexture
surfaceTexture
=
textureView
.
getSurfaceTexture
();
setVideoSurfaceInternal
(
surfaceTexture
==
null
?
null
:
new
Surface
(
surfaceTexture
));
setVideoSurfaceInternal
(
surfaceTexture
==
null
?
null
:
new
Surface
(
surfaceTexture
));
textureView
.
setSurfaceTextureListener
(
componentListener
);
textureView
.
setSurfaceTextureListener
(
componentListener
);
...
@@ -456,6 +467,7 @@ public final class SimpleExoPlayer implements ExoPlayer {
...
@@ -456,6 +467,7 @@ public final class SimpleExoPlayer implements ExoPlayer {
@Override
@Override
public
void
release
()
{
public
void
release
()
{
player
.
release
();
player
.
release
();
removeSurfaceCallbacks
();
}
}
@Override
@Override
...
@@ -592,13 +604,17 @@ public final class SimpleExoPlayer implements ExoPlayer {
...
@@ -592,13 +604,17 @@ public final class SimpleExoPlayer implements ExoPlayer {
}
}
private
void
removeSurfaceCallbacks
()
{
private
void
removeSurfaceCallbacks
()
{
if
(
this
.
textureView
!=
null
)
{
if
(
textureView
!=
null
)
{
this
.
textureView
.
setSurfaceTextureListener
(
null
);
if
(
textureView
.
getSurfaceTextureListener
()
!=
componentListener
)
{
this
.
textureView
=
null
;
Log
.
w
(
TAG
,
"SurfaceTextureListener already unset or replaced."
);
}
else
{
textureView
.
setSurfaceTextureListener
(
null
);
}
textureView
=
null
;
}
}
if
(
this
.
surfaceHolder
!=
null
)
{
if
(
surfaceHolder
!=
null
)
{
this
.
surfaceHolder
.
removeCallback
(
componentListener
);
surfaceHolder
.
removeCallback
(
componentListener
);
this
.
surfaceHolder
=
null
;
surfaceHolder
=
null
;
}
}
}
}
...
...
library/src/main/java/com/google/android/exoplayer2/audio/Ac3Util.java
View file @
f94218a7
...
@@ -15,6 +15,7 @@
...
@@ -15,6 +15,7 @@
*/
*/
package
com
.
google
.
android
.
exoplayer2
.
audio
;
package
com
.
google
.
android
.
exoplayer2
.
audio
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.Format
;
import
com.google.android.exoplayer2.Format
;
import
com.google.android.exoplayer2.drm.DrmInitData
;
import
com.google.android.exoplayer2.drm.DrmInitData
;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
com.google.android.exoplayer2.util.MimeTypes
;
...
@@ -175,9 +176,12 @@ public final class Ac3Util {
...
@@ -175,9 +176,12 @@ public final class Ac3Util {
* Returns the size in bytes of the given AC-3 syncframe.
* Returns the size in bytes of the given AC-3 syncframe.
*
*
* @param data The syncframe to parse.
* @param data The syncframe to parse.
* @return The syncframe size in bytes.
* @return The syncframe size in bytes.
{@link C#LENGTH_UNSET} if the input is invalid.
*/
*/
public
static
int
parseAc3SyncframeSize
(
byte
[]
data
)
{
public
static
int
parseAc3SyncframeSize
(
byte
[]
data
)
{
if
(
data
.
length
<
5
)
{
return
C
.
LENGTH_UNSET
;
}
int
fscod
=
(
data
[
4
]
&
0xC0
)
>>
6
;
int
fscod
=
(
data
[
4
]
&
0xC0
)
>>
6
;
int
frmsizecod
=
data
[
4
]
&
0x3F
;
int
frmsizecod
=
data
[
4
]
&
0x3F
;
return
getAc3SyncframeSize
(
fscod
,
frmsizecod
);
return
getAc3SyncframeSize
(
fscod
,
frmsizecod
);
...
@@ -227,11 +231,17 @@ public final class Ac3Util {
...
@@ -227,11 +231,17 @@ public final class Ac3Util {
}
}
private
static
int
getAc3SyncframeSize
(
int
fscod
,
int
frmsizecod
)
{
private
static
int
getAc3SyncframeSize
(
int
fscod
,
int
frmsizecod
)
{
int
halfFrmsizecod
=
frmsizecod
/
2
;
if
(
fscod
<
0
||
fscod
>=
SAMPLE_RATE_BY_FSCOD
.
length
||
frmsizecod
<
0
||
halfFrmsizecod
>=
SYNCFRAME_SIZE_WORDS_BY_HALF_FRMSIZECOD_44_1
.
length
)
{
// Invalid values provided.
return
C
.
LENGTH_UNSET
;
}
int
sampleRate
=
SAMPLE_RATE_BY_FSCOD
[
fscod
];
int
sampleRate
=
SAMPLE_RATE_BY_FSCOD
[
fscod
];
if
(
sampleRate
==
44100
)
{
if
(
sampleRate
==
44100
)
{
return
2
*
(
SYNCFRAME_SIZE_WORDS_BY_HALF_FRMSIZECOD_44_1
[
frmsizecod
/
2
]
+
(
frmsizecod
%
2
));
return
2
*
(
SYNCFRAME_SIZE_WORDS_BY_HALF_FRMSIZECOD_44_1
[
halfFrmsizecod
]
+
(
frmsizecod
%
2
));
}
}
int
bitrate
=
BITRATE_BY_HALF_FRMSIZECOD
[
frmsizecod
/
2
];
int
bitrate
=
BITRATE_BY_HALF_FRMSIZECOD
[
halfFrmsizecod
];
if
(
sampleRate
==
32000
)
{
if
(
sampleRate
==
32000
)
{
return
6
*
bitrate
;
return
6
*
bitrate
;
}
else
{
// sampleRate == 48000
}
else
{
// sampleRate == 48000
...
...
library/src/main/java/com/google/android/exoplayer2/extractor/
ts/
TimestampAdjuster.java
→
library/src/main/java/com/google/android/exoplayer2/extractor/TimestampAdjuster.java
View file @
f94218a7
...
@@ -13,7 +13,7 @@
...
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* See the License for the specific language governing permissions and
* limitations under the License.
* limitations under the License.
*/
*/
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
ts
;
package
com
.
google
.
android
.
exoplayer2
.
extractor
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.C
;
...
...
library/src/main/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.java
View file @
f94218a7
...
@@ -30,6 +30,7 @@ import com.google.android.exoplayer2.extractor.ExtractorOutput;
...
@@ -30,6 +30,7 @@ import com.google.android.exoplayer2.extractor.ExtractorOutput;
import
com.google.android.exoplayer2.extractor.ExtractorsFactory
;
import
com.google.android.exoplayer2.extractor.ExtractorsFactory
;
import
com.google.android.exoplayer2.extractor.PositionHolder
;
import
com.google.android.exoplayer2.extractor.PositionHolder
;
import
com.google.android.exoplayer2.extractor.SeekMap
;
import
com.google.android.exoplayer2.extractor.SeekMap
;
import
com.google.android.exoplayer2.extractor.TimestampAdjuster
;
import
com.google.android.exoplayer2.extractor.TrackOutput
;
import
com.google.android.exoplayer2.extractor.TrackOutput
;
import
com.google.android.exoplayer2.extractor.mp4.Atom.ContainerAtom
;
import
com.google.android.exoplayer2.extractor.mp4.Atom.ContainerAtom
;
import
com.google.android.exoplayer2.extractor.mp4.Atom.LeafAtom
;
import
com.google.android.exoplayer2.extractor.mp4.Atom.LeafAtom
;
...
@@ -115,6 +116,9 @@ public final class FragmentedMp4Extractor implements Extractor {
...
@@ -115,6 +116,9 @@ public final class FragmentedMp4Extractor implements Extractor {
private
final
ParsableByteArray
nalLength
;
private
final
ParsableByteArray
nalLength
;
private
final
ParsableByteArray
encryptionSignalByte
;
private
final
ParsableByteArray
encryptionSignalByte
;
// Adjusts sample timestamps.
private
final
TimestampAdjuster
timestampAdjuster
;
// Parser state.
// Parser state.
private
final
ParsableByteArray
atomHeader
;
private
final
ParsableByteArray
atomHeader
;
private
final
byte
[]
extendedTypeScratch
;
private
final
byte
[]
extendedTypeScratch
;
...
@@ -140,24 +144,28 @@ public final class FragmentedMp4Extractor implements Extractor {
...
@@ -140,24 +144,28 @@ public final class FragmentedMp4Extractor implements Extractor {
private
boolean
haveOutputSeekMap
;
private
boolean
haveOutputSeekMap
;
public
FragmentedMp4Extractor
()
{
public
FragmentedMp4Extractor
()
{
this
(
0
);
this
(
0
,
null
);
}
}
/**
/**
* @param flags Flags that control the extractor's behavior.
* @param flags Flags that control the extractor's behavior.
* @param timestampAdjuster Adjusts sample timestamps. May be null if no adjustment is needed.
*/
*/
public
FragmentedMp4Extractor
(
@Flags
int
flags
)
{
public
FragmentedMp4Extractor
(
@Flags
int
flags
,
TimestampAdjuster
timestampAdjuster
)
{
this
(
flags
,
null
);
this
(
flags
,
null
,
timestampAdjuster
);
}
}
/**
/**
* @param flags Flags that control the extractor's behavior.
* @param flags Flags that control the extractor's behavior.
* @param sideloadedTrack Sideloaded track information, in the case that the extractor
* @param sideloadedTrack Sideloaded track information, in the case that the extractor
* will not receive a moov box in the input data.
* will not receive a moov box in the input data.
* @param timestampAdjuster Adjusts sample timestamps. May be null if no adjustment is needed.
*/
*/
public
FragmentedMp4Extractor
(
@Flags
int
flags
,
Track
sideloadedTrack
)
{
public
FragmentedMp4Extractor
(
@Flags
int
flags
,
Track
sideloadedTrack
,
TimestampAdjuster
timestampAdjuster
)
{
this
.
sideloadedTrack
=
sideloadedTrack
;
this
.
sideloadedTrack
=
sideloadedTrack
;
this
.
flags
=
flags
|
(
sideloadedTrack
!=
null
?
FLAG_SIDELOADED
:
0
);
this
.
flags
=
flags
|
(
sideloadedTrack
!=
null
?
FLAG_SIDELOADED
:
0
);
this
.
timestampAdjuster
=
timestampAdjuster
;
atomHeader
=
new
ParsableByteArray
(
Atom
.
LONG_HEADER_SIZE
);
atomHeader
=
new
ParsableByteArray
(
Atom
.
LONG_HEADER_SIZE
);
nalStartCode
=
new
ParsableByteArray
(
NalUnitUtil
.
NAL_START_CODE
);
nalStartCode
=
new
ParsableByteArray
(
NalUnitUtil
.
NAL_START_CODE
);
nalLength
=
new
ParsableByteArray
(
4
);
nalLength
=
new
ParsableByteArray
(
4
);
...
@@ -1012,6 +1020,9 @@ public final class FragmentedMp4Extractor implements Extractor {
...
@@ -1012,6 +1020,9 @@ public final class FragmentedMp4Extractor implements Extractor {
?
fragment
.
trackEncryptionBox
.
keyId
?
fragment
.
trackEncryptionBox
.
keyId
:
track
.
sampleDescriptionEncryptionBoxes
[
sampleDescriptionIndex
].
keyId
;
:
track
.
sampleDescriptionEncryptionBoxes
[
sampleDescriptionIndex
].
keyId
;
}
}
if
(
timestampAdjuster
!=
null
)
{
sampleTimeUs
=
timestampAdjuster
.
adjustSampleTimestamp
(
sampleTimeUs
);
}
output
.
sampleMetadata
(
sampleTimeUs
,
sampleFlags
,
sampleSize
,
0
,
encryptionKey
);
output
.
sampleMetadata
(
sampleTimeUs
,
sampleFlags
,
sampleSize
,
0
,
encryptionKey
);
currentTrackBundle
.
currentSampleIndex
++;
currentTrackBundle
.
currentSampleIndex
++;
...
...
library/src/main/java/com/google/android/exoplayer2/extractor/ts/Ac3Extractor.java
View file @
f94218a7
...
@@ -107,6 +107,9 @@ public final class Ac3Extractor implements Extractor {
...
@@ -107,6 +107,9 @@ public final class Ac3Extractor implements Extractor {
return
true
;
return
true
;
}
}
int
frameSize
=
Ac3Util
.
parseAc3SyncframeSize
(
scratch
.
data
);
int
frameSize
=
Ac3Util
.
parseAc3SyncframeSize
(
scratch
.
data
);
if
(
frameSize
==
C
.
LENGTH_UNSET
)
{
return
false
;
}
input
.
advancePeekPosition
(
frameSize
-
5
);
input
.
advancePeekPosition
(
frameSize
-
5
);
}
}
}
}
...
...
library/src/main/java/com/google/android/exoplayer2/extractor/ts/PsExtractor.java
View file @
f94218a7
...
@@ -23,6 +23,7 @@ import com.google.android.exoplayer2.extractor.ExtractorOutput;
...
@@ -23,6 +23,7 @@ import com.google.android.exoplayer2.extractor.ExtractorOutput;
import
com.google.android.exoplayer2.extractor.ExtractorsFactory
;
import
com.google.android.exoplayer2.extractor.ExtractorsFactory
;
import
com.google.android.exoplayer2.extractor.PositionHolder
;
import
com.google.android.exoplayer2.extractor.PositionHolder
;
import
com.google.android.exoplayer2.extractor.SeekMap
;
import
com.google.android.exoplayer2.extractor.SeekMap
;
import
com.google.android.exoplayer2.extractor.TimestampAdjuster
;
import
com.google.android.exoplayer2.util.ParsableBitArray
;
import
com.google.android.exoplayer2.util.ParsableBitArray
;
import
com.google.android.exoplayer2.util.ParsableByteArray
;
import
com.google.android.exoplayer2.util.ParsableByteArray
;
import
java.io.IOException
;
import
java.io.IOException
;
...
...
library/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java
View file @
f94218a7
...
@@ -25,6 +25,7 @@ import com.google.android.exoplayer2.extractor.ExtractorOutput;
...
@@ -25,6 +25,7 @@ import com.google.android.exoplayer2.extractor.ExtractorOutput;
import
com.google.android.exoplayer2.extractor.ExtractorsFactory
;
import
com.google.android.exoplayer2.extractor.ExtractorsFactory
;
import
com.google.android.exoplayer2.extractor.PositionHolder
;
import
com.google.android.exoplayer2.extractor.PositionHolder
;
import
com.google.android.exoplayer2.extractor.SeekMap
;
import
com.google.android.exoplayer2.extractor.SeekMap
;
import
com.google.android.exoplayer2.extractor.TimestampAdjuster
;
import
com.google.android.exoplayer2.util.Assertions
;
import
com.google.android.exoplayer2.util.Assertions
;
import
com.google.android.exoplayer2.util.ParsableBitArray
;
import
com.google.android.exoplayer2.util.ParsableBitArray
;
import
com.google.android.exoplayer2.util.ParsableByteArray
;
import
com.google.android.exoplayer2.util.ParsableByteArray
;
...
...
library/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java
View file @
f94218a7
...
@@ -456,7 +456,7 @@ import java.util.Arrays;
...
@@ -456,7 +456,7 @@ import java.util.Arrays;
lastSeekPositionUs
=
0
;
lastSeekPositionUs
=
0
;
notifyReset
=
prepared
;
notifyReset
=
prepared
;
for
(
int
i
=
0
;
i
<
sampleQueues
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
sampleQueues
.
length
;
i
++)
{
sampleQueues
[
i
].
reset
(
trackEnabledStates
[
i
]);
sampleQueues
[
i
].
reset
(
!
prepared
||
trackEnabledStates
[
i
]);
}
}
loadable
.
setLoadPosition
(
0
);
loadable
.
setLoadPosition
(
0
);
}
}
...
...
library/src/main/java/com/google/android/exoplayer2/source/MergingMediaPeriod.java
View file @
f94218a7
...
@@ -17,6 +17,7 @@ package com.google.android.exoplayer2.source;
...
@@ -17,6 +17,7 @@ package com.google.android.exoplayer2.source;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.trackselection.TrackSelection
;
import
com.google.android.exoplayer2.trackselection.TrackSelection
;
import
com.google.android.exoplayer2.util.Assertions
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.IdentityHashMap
;
import
java.util.IdentityHashMap
;
...
@@ -84,7 +85,8 @@ import java.util.IdentityHashMap;
...
@@ -84,7 +85,8 @@ import java.util.IdentityHashMap;
}
}
}
}
streamPeriodIndices
.
clear
();
streamPeriodIndices
.
clear
();
// Select tracks for each child, copying the resulting streams back into the streams array.
// Select tracks for each child, copying the resulting streams back into a new streams array.
SampleStream
[]
newStreams
=
new
SampleStream
[
selections
.
length
];
SampleStream
[]
childStreams
=
new
SampleStream
[
selections
.
length
];
SampleStream
[]
childStreams
=
new
SampleStream
[
selections
.
length
];
TrackSelection
[]
childSelections
=
new
TrackSelection
[
selections
.
length
];
TrackSelection
[]
childSelections
=
new
TrackSelection
[
selections
.
length
];
ArrayList
<
MediaPeriod
>
enabledPeriodsList
=
new
ArrayList
<>(
periods
.
length
);
ArrayList
<
MediaPeriod
>
enabledPeriodsList
=
new
ArrayList
<>(
periods
.
length
);
...
@@ -103,17 +105,22 @@ import java.util.IdentityHashMap;
...
@@ -103,17 +105,22 @@ import java.util.IdentityHashMap;
boolean
periodEnabled
=
false
;
boolean
periodEnabled
=
false
;
for
(
int
j
=
0
;
j
<
selections
.
length
;
j
++)
{
for
(
int
j
=
0
;
j
<
selections
.
length
;
j
++)
{
if
(
selectionChildIndices
[
j
]
==
i
)
{
if
(
selectionChildIndices
[
j
]
==
i
)
{
streams
[
j
]
=
childStreams
[
j
];
// Assert that the child provided a stream for the selection.
if
(
childStreams
[
j
]
!=
null
)
{
Assertions
.
checkState
(
childStreams
[
j
]
!=
null
);
periodEnabled
=
true
;
newStreams
[
j
]
=
childStreams
[
j
];
streamPeriodIndices
.
put
(
childStreams
[
j
],
i
);
periodEnabled
=
true
;
}
streamPeriodIndices
.
put
(
childStreams
[
j
],
i
);
}
else
if
(
streamChildIndices
[
j
]
==
i
)
{
// Assert that the child cleared any previous stream.
Assertions
.
checkState
(
childStreams
[
j
]
==
null
);
}
}
}
}
if
(
periodEnabled
)
{
if
(
periodEnabled
)
{
enabledPeriodsList
.
add
(
periods
[
i
]);
enabledPeriodsList
.
add
(
periods
[
i
]);
}
}
}
}
// Copy the new streams back into the streams array.
System
.
arraycopy
(
newStreams
,
0
,
streams
,
0
,
newStreams
.
length
);
// Update the local state.
// Update the local state.
enabledPeriods
=
new
MediaPeriod
[
enabledPeriodsList
.
size
()];
enabledPeriods
=
new
MediaPeriod
[
enabledPeriodsList
.
size
()];
enabledPeriodsList
.
toArray
(
enabledPeriods
);
enabledPeriodsList
.
toArray
(
enabledPeriods
);
...
@@ -133,21 +140,22 @@ import java.util.IdentityHashMap;
...
@@ -133,21 +140,22 @@ import java.util.IdentityHashMap;
@Override
@Override
public
long
readDiscontinuity
()
{
public
long
readDiscontinuity
()
{
long
positionUs
=
enabledPeriods
[
0
].
readDiscontinuity
();
long
positionUs
=
periods
[
0
].
readDiscontinuity
();
// Periods other than the first one are not allowed to report discontinuities.
for
(
int
i
=
1
;
i
<
periods
.
length
;
i
++)
{
if
(
periods
[
i
].
readDiscontinuity
()
!=
C
.
TIME_UNSET
)
{
throw
new
IllegalStateException
(
"Child reported discontinuity"
);
}
}
// It must be possible to seek enabled periods to the new position, if there is one.
if
(
positionUs
!=
C
.
TIME_UNSET
)
{
if
(
positionUs
!=
C
.
TIME_UNSET
)
{
// It must be possible to seek additional periods to the new position.
for
(
int
i
=
0
;
i
<
enabledPeriods
.
length
;
i
++)
{
for
(
int
i
=
1
;
i
<
enabledPeriods
.
length
;
i
++)
{
if
(
enabledPeriods
[
i
]
!=
periods
[
0
]
if
(
enabledPeriods
[
i
].
seekToUs
(
positionUs
)
!=
positionUs
)
{
&&
enabledPeriods
[
i
].
seekToUs
(
positionUs
)
!=
positionUs
)
{
throw
new
IllegalStateException
(
"Children seeked to different positions"
);
throw
new
IllegalStateException
(
"Children seeked to different positions"
);
}
}
}
}
}
}
// Additional periods are not allowed to report discontinuities.
for
(
int
i
=
1
;
i
<
enabledPeriods
.
length
;
i
++)
{
if
(
enabledPeriods
[
i
].
readDiscontinuity
()
!=
C
.
TIME_UNSET
)
{
throw
new
IllegalStateException
(
"Child reported discontinuity"
);
}
}
return
positionUs
;
return
positionUs
;
}
}
...
...
library/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaPeriod.java
View file @
f94218a7
...
@@ -41,7 +41,7 @@ import java.util.Arrays;
...
@@ -41,7 +41,7 @@ import java.util.Arrays;
/**
/**
* The initial size of the allocation used to hold the sample data.
* The initial size of the allocation used to hold the sample data.
*/
*/
private
static
final
int
INITIAL_SAMPLE_SIZE
=
1
;
private
static
final
int
INITIAL_SAMPLE_SIZE
=
1
024
;
private
final
Uri
uri
;
private
final
Uri
uri
;
private
final
DataSource
.
Factory
dataSourceFactory
;
private
final
DataSource
.
Factory
dataSourceFactory
;
...
@@ -71,7 +71,6 @@ import java.util.Arrays;
...
@@ -71,7 +71,6 @@ import java.util.Arrays;
tracks
=
new
TrackGroupArray
(
new
TrackGroup
(
format
));
tracks
=
new
TrackGroupArray
(
new
TrackGroup
(
format
));
sampleStreams
=
new
ArrayList
<>();
sampleStreams
=
new
ArrayList
<>();
loader
=
new
Loader
(
"Loader:SingleSampleMediaPeriod"
);
loader
=
new
Loader
(
"Loader:SingleSampleMediaPeriod"
);
sampleData
=
new
byte
[
INITIAL_SAMPLE_SIZE
];
}
}
public
void
release
()
{
public
void
release
()
{
...
@@ -269,7 +268,9 @@ import java.util.Arrays;
...
@@ -269,7 +268,9 @@ import java.util.Arrays;
int
result
=
0
;
int
result
=
0
;
while
(
result
!=
C
.
RESULT_END_OF_INPUT
)
{
while
(
result
!=
C
.
RESULT_END_OF_INPUT
)
{
sampleSize
+=
result
;
sampleSize
+=
result
;
if
(
sampleSize
==
sampleData
.
length
)
{
if
(
sampleData
==
null
)
{
sampleData
=
new
byte
[
INITIAL_SAMPLE_SIZE
];
}
else
if
(
sampleSize
==
sampleData
.
length
)
{
sampleData
=
Arrays
.
copyOf
(
sampleData
,
sampleData
.
length
*
2
);
sampleData
=
Arrays
.
copyOf
(
sampleData
,
sampleData
.
length
*
2
);
}
}
result
=
dataSource
.
read
(
sampleData
,
sampleSize
,
sampleData
.
length
-
sampleSize
);
result
=
dataSource
.
read
(
sampleData
,
sampleSize
,
sampleData
.
length
-
sampleSize
);
...
...
library/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.java
View file @
f94218a7
...
@@ -654,10 +654,10 @@ public class DashManifestParser extends DefaultHandler
...
@@ -654,10 +654,10 @@ public class DashManifestParser extends DefaultHandler
}
else
if
(
MimeTypes
.
isVideo
(
containerMimeType
))
{
}
else
if
(
MimeTypes
.
isVideo
(
containerMimeType
))
{
return
MimeTypes
.
getVideoMediaMimeType
(
codecs
);
return
MimeTypes
.
getVideoMediaMimeType
(
codecs
);
}
else
if
(
MimeTypes
.
APPLICATION_RAWCC
.
equals
(
containerMimeType
))
{
}
else
if
(
MimeTypes
.
APPLICATION_RAWCC
.
equals
(
containerMimeType
))
{
// We currently only support CEA-608 through RawCC
if
(
codecs
!=
null
)
{
if
(
codecs
!=
null
if
(
codecs
.
contains
(
"eia608"
)
||
codecs
.
contains
(
"cea608"
))
{
&&
(
codecs
.
contains
(
"eia608"
)
||
codecs
.
contains
(
"cea608"
)))
{
return
MimeTypes
.
APPLICATION_CEA608
;
return
MimeTypes
.
APPLICATION_CEA608
;
}
}
}
return
null
;
return
null
;
}
else
if
(
mimeTypeIsRawText
(
containerMimeType
))
{
}
else
if
(
mimeTypeIsRawText
(
containerMimeType
))
{
...
...
library/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java
View file @
f94218a7
...
@@ -21,11 +21,12 @@ import android.text.TextUtils;
...
@@ -21,11 +21,12 @@ import android.text.TextUtils;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.Format
;
import
com.google.android.exoplayer2.Format
;
import
com.google.android.exoplayer2.extractor.Extractor
;
import
com.google.android.exoplayer2.extractor.Extractor
;
import
com.google.android.exoplayer2.extractor.TimestampAdjuster
;
import
com.google.android.exoplayer2.extractor.mp3.Mp3Extractor
;
import
com.google.android.exoplayer2.extractor.mp3.Mp3Extractor
;
import
com.google.android.exoplayer2.extractor.mp4.FragmentedMp4Extractor
;
import
com.google.android.exoplayer2.extractor.ts.Ac3Extractor
;
import
com.google.android.exoplayer2.extractor.ts.Ac3Extractor
;
import
com.google.android.exoplayer2.extractor.ts.AdtsExtractor
;
import
com.google.android.exoplayer2.extractor.ts.AdtsExtractor
;
import
com.google.android.exoplayer2.extractor.ts.DefaultStreamReaderFactory
;
import
com.google.android.exoplayer2.extractor.ts.DefaultStreamReaderFactory
;
import
com.google.android.exoplayer2.extractor.ts.TimestampAdjuster
;
import
com.google.android.exoplayer2.extractor.ts.TsExtractor
;
import
com.google.android.exoplayer2.extractor.ts.TsExtractor
;
import
com.google.android.exoplayer2.source.BehindLiveWindowException
;
import
com.google.android.exoplayer2.source.BehindLiveWindowException
;
import
com.google.android.exoplayer2.source.TrackGroup
;
import
com.google.android.exoplayer2.source.TrackGroup
;
...
@@ -34,6 +35,7 @@ import com.google.android.exoplayer2.source.chunk.ChunkedTrackBlacklistUtil;
...
@@ -34,6 +35,7 @@ import com.google.android.exoplayer2.source.chunk.ChunkedTrackBlacklistUtil;
import
com.google.android.exoplayer2.source.chunk.DataChunk
;
import
com.google.android.exoplayer2.source.chunk.DataChunk
;
import
com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist
;
import
com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist
;
import
com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist
;
import
com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist
;
import
com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist.Segment
;
import
com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistParser
;
import
com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistParser
;
import
com.google.android.exoplayer2.trackselection.BaseTrackSelection
;
import
com.google.android.exoplayer2.trackselection.BaseTrackSelection
;
import
com.google.android.exoplayer2.trackselection.TrackSelection
;
import
com.google.android.exoplayer2.trackselection.TrackSelection
;
...
@@ -101,6 +103,7 @@ import java.util.Locale;
...
@@ -101,6 +103,7 @@ import java.util.Locale;
private
static
final
String
AC3_FILE_EXTENSION
=
".ac3"
;
private
static
final
String
AC3_FILE_EXTENSION
=
".ac3"
;
private
static
final
String
EC3_FILE_EXTENSION
=
".ec3"
;
private
static
final
String
EC3_FILE_EXTENSION
=
".ec3"
;
private
static
final
String
MP3_FILE_EXTENSION
=
".mp3"
;
private
static
final
String
MP3_FILE_EXTENSION
=
".mp3"
;
private
static
final
String
MP4_FILE_EXTENSION
=
".mp4"
;
private
static
final
String
VTT_FILE_EXTENSION
=
".vtt"
;
private
static
final
String
VTT_FILE_EXTENSION
=
".vtt"
;
private
static
final
String
WEBVTT_FILE_EXTENSION
=
".webvtt"
;
private
static
final
String
WEBVTT_FILE_EXTENSION
=
".webvtt"
;
...
@@ -118,6 +121,7 @@ import java.util.Locale;
...
@@ -118,6 +121,7 @@ import java.util.Locale;
private
long
durationUs
;
private
long
durationUs
;
private
IOException
fatalError
;
private
IOException
fatalError
;
private
HlsInitializationChunk
lastLoadedInitializationChunk
;
private
Uri
encryptionKeyUri
;
private
Uri
encryptionKeyUri
;
private
byte
[]
encryptionKey
;
private
byte
[]
encryptionKey
;
private
String
encryptionIvString
;
private
String
encryptionIvString
;
...
@@ -289,7 +293,6 @@ import java.util.Locale;
...
@@ -289,7 +293,6 @@ import java.util.Locale;
}
}
HlsMediaPlaylist
.
Segment
segment
=
mediaPlaylist
.
segments
.
get
(
chunkIndex
);
HlsMediaPlaylist
.
Segment
segment
=
mediaPlaylist
.
segments
.
get
(
chunkIndex
);
Uri
chunkUri
=
UriUtil
.
resolveToUri
(
mediaPlaylist
.
baseUri
,
segment
.
url
);
// Check if encryption is specified.
// Check if encryption is specified.
if
(
segment
.
isEncrypted
)
{
if
(
segment
.
isEncrypted
)
{
...
@@ -307,10 +310,6 @@ import java.util.Locale;
...
@@ -307,10 +310,6 @@ import java.util.Locale;
clearEncryptionData
();
clearEncryptionData
();
}
}
// Configure the data source and spec for the chunk.
DataSpec
dataSpec
=
new
DataSpec
(
chunkUri
,
segment
.
byterangeOffset
,
segment
.
byterangeLength
,
null
);
// Compute start and end times, and the sequence number of the next chunk.
// Compute start and end times, and the sequence number of the next chunk.
long
startTimeUs
;
long
startTimeUs
;
if
(
live
)
{
if
(
live
)
{
...
@@ -327,8 +326,15 @@ import java.util.Locale;
...
@@ -327,8 +326,15 @@ import java.util.Locale;
long
endTimeUs
=
startTimeUs
+
(
long
)
(
segment
.
durationSecs
*
C
.
MICROS_PER_SECOND
);
long
endTimeUs
=
startTimeUs
+
(
long
)
(
segment
.
durationSecs
*
C
.
MICROS_PER_SECOND
);
Format
format
=
variants
[
newVariantIndex
].
format
;
Format
format
=
variants
[
newVariantIndex
].
format
;
Uri
chunkUri
=
UriUtil
.
resolveToUri
(
mediaPlaylist
.
baseUri
,
segment
.
url
);
// Configure the extractor that will read the chunk.
// Configure the extractor that will read the chunk.
Extractor
extractor
;
Extractor
extractor
;
boolean
useInitializedExtractor
=
lastLoadedInitializationChunk
!=
null
&&
lastLoadedInitializationChunk
.
format
==
format
;
boolean
needNewExtractor
=
previous
==
null
||
previous
.
discontinuitySequenceNumber
!=
segment
.
discontinuitySequenceNumber
||
format
!=
previous
.
trackFormat
;
boolean
extractorNeedsInit
=
true
;
boolean
extractorNeedsInit
=
true
;
boolean
isTimestampMaster
=
false
;
boolean
isTimestampMaster
=
false
;
TimestampAdjuster
timestampAdjuster
=
null
;
TimestampAdjuster
timestampAdjuster
=
null
;
...
@@ -348,13 +354,21 @@ import java.util.Locale;
...
@@ -348,13 +354,21 @@ import java.util.Locale;
timestampAdjuster
=
timestampAdjusterProvider
.
getAdjuster
(
segment
.
discontinuitySequenceNumber
,
timestampAdjuster
=
timestampAdjusterProvider
.
getAdjuster
(
segment
.
discontinuitySequenceNumber
,
startTimeUs
);
startTimeUs
);
extractor
=
new
WebvttExtractor
(
format
.
language
,
timestampAdjuster
);
extractor
=
new
WebvttExtractor
(
format
.
language
,
timestampAdjuster
);
}
else
if
(
previous
==
null
}
else
if
(
lastPathSegment
.
endsWith
(
MP4_FILE_EXTENSION
))
{
||
previous
.
discontinuitySequenceNumber
!=
segment
.
discontinuitySequenceNumber
||
format
!=
previous
.
trackFormat
)
{
// MPEG-2 TS segments, but we need a new extractor.
isTimestampMaster
=
true
;
isTimestampMaster
=
true
;
timestampAdjuster
=
timestampAdjusterProvider
.
getAdjuster
(
segment
.
discontinuitySequenceNumber
,
if
(
needNewExtractor
)
{
startTimeUs
);
if
(
useInitializedExtractor
)
{
extractor
=
lastLoadedInitializationChunk
.
extractor
;
}
else
{
timestampAdjuster
=
timestampAdjusterProvider
.
getAdjuster
(
segment
.
discontinuitySequenceNumber
,
startTimeUs
);
extractor
=
new
FragmentedMp4Extractor
(
0
,
timestampAdjuster
);
}
}
else
{
extractor
=
previous
.
extractor
;
}
}
else
if
(
needNewExtractor
)
{
// MPEG-2 TS segments, but we need a new extractor.
// 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.
@DefaultStreamReaderFactory
.
WorkaroundFlags
@DefaultStreamReaderFactory
.
WorkaroundFlags
int
workaroundFlags
=
DefaultStreamReaderFactory
.
WORKAROUND_MAP_BY_TYPE
;
int
workaroundFlags
=
DefaultStreamReaderFactory
.
WORKAROUND_MAP_BY_TYPE
;
...
@@ -370,14 +384,31 @@ import java.util.Locale;
...
@@ -370,14 +384,31 @@ import java.util.Locale;
workaroundFlags
|=
DefaultStreamReaderFactory
.
WORKAROUND_IGNORE_H264_STREAM
;
workaroundFlags
|=
DefaultStreamReaderFactory
.
WORKAROUND_IGNORE_H264_STREAM
;
}
}
}
}
extractor
=
new
TsExtractor
(
timestampAdjuster
,
isTimestampMaster
=
true
;
new
DefaultStreamReaderFactory
(
workaroundFlags
));
if
(
useInitializedExtractor
)
{
extractor
=
lastLoadedInitializationChunk
.
extractor
;
}
else
{
timestampAdjuster
=
timestampAdjusterProvider
.
getAdjuster
(
segment
.
discontinuitySequenceNumber
,
startTimeUs
);
extractor
=
new
TsExtractor
(
timestampAdjuster
,
new
DefaultStreamReaderFactory
(
workaroundFlags
));
}
}
else
{
}
else
{
// MPEG-2 TS segments, and we need to continue using the same extractor.
// MPEG-2 TS segments, and we need to continue using the same extractor.
extractor
=
previous
.
extractor
;
extractor
=
previous
.
extractor
;
extractorNeedsInit
=
false
;
extractorNeedsInit
=
false
;
}
}
if
(
needNewExtractor
&&
mediaPlaylist
.
initializationSegment
!=
null
&&
!
useInitializedExtractor
)
{
out
.
chunk
=
buildInitializationChunk
(
mediaPlaylist
,
extractor
,
format
);
return
;
}
lastLoadedInitializationChunk
=
null
;
// Configure the data source and spec for the chunk.
DataSpec
dataSpec
=
new
DataSpec
(
chunkUri
,
segment
.
byterangeOffset
,
segment
.
byterangeLength
,
null
);
out
.
chunk
=
new
HlsMediaChunk
(
dataSource
,
dataSpec
,
format
,
out
.
chunk
=
new
HlsMediaChunk
(
dataSource
,
dataSpec
,
format
,
trackSelection
.
getSelectionReason
(),
trackSelection
.
getSelectionData
(),
trackSelection
.
getSelectionReason
(),
trackSelection
.
getSelectionData
(),
startTimeUs
,
endTimeUs
,
chunkMediaSequence
,
segment
.
discontinuitySequenceNumber
,
startTimeUs
,
endTimeUs
,
chunkMediaSequence
,
segment
.
discontinuitySequenceNumber
,
...
@@ -434,7 +465,9 @@ import java.util.Locale;
...
@@ -434,7 +465,9 @@ import java.util.Locale;
* @param chunk The chunk whose load has been completed.
* @param chunk The chunk whose load has been completed.
*/
*/
public
void
onChunkLoadCompleted
(
Chunk
chunk
)
{
public
void
onChunkLoadCompleted
(
Chunk
chunk
)
{
if
(
chunk
instanceof
MediaPlaylistChunk
)
{
if
(
chunk
instanceof
HlsInitializationChunk
)
{
lastLoadedInitializationChunk
=
(
HlsInitializationChunk
)
chunk
;
}
else
if
(
chunk
instanceof
MediaPlaylistChunk
)
{
MediaPlaylistChunk
mediaPlaylistChunk
=
(
MediaPlaylistChunk
)
chunk
;
MediaPlaylistChunk
mediaPlaylistChunk
=
(
MediaPlaylistChunk
)
chunk
;
scratchSpace
=
mediaPlaylistChunk
.
getDataHolder
();
scratchSpace
=
mediaPlaylistChunk
.
getDataHolder
();
setMediaPlaylist
(
mediaPlaylistChunk
.
variantIndex
,
mediaPlaylistChunk
.
getResult
());
setMediaPlaylist
(
mediaPlaylistChunk
.
variantIndex
,
mediaPlaylistChunk
.
getResult
());
...
@@ -462,6 +495,18 @@ import java.util.Locale;
...
@@ -462,6 +495,18 @@ import java.util.Locale;
// Private methods.
// Private methods.
private
HlsInitializationChunk
buildInitializationChunk
(
HlsMediaPlaylist
mediaPlaylist
,
Extractor
extractor
,
Format
format
)
{
Segment
initSegment
=
mediaPlaylist
.
initializationSegment
;
// The initialization segment is required before the actual media chunk.
Uri
initSegmentUri
=
UriUtil
.
resolveToUri
(
mediaPlaylist
.
baseUri
,
initSegment
.
url
);
DataSpec
initDataSpec
=
new
DataSpec
(
initSegmentUri
,
initSegment
.
byterangeOffset
,
initSegment
.
byterangeLength
,
null
);
return
new
HlsInitializationChunk
(
dataSource
,
initDataSpec
,
trackSelection
.
getSelectionReason
(),
trackSelection
.
getSelectionData
(),
extractor
,
format
);
}
private
long
msToRerequestLiveMediaPlaylist
(
int
variantIndex
)
{
private
long
msToRerequestLiveMediaPlaylist
(
int
variantIndex
)
{
HlsMediaPlaylist
mediaPlaylist
=
variantPlaylists
[
variantIndex
];
HlsMediaPlaylist
mediaPlaylist
=
variantPlaylists
[
variantIndex
];
long
timeSinceLastMediaPlaylistLoadMs
=
long
timeSinceLastMediaPlaylistLoadMs
=
...
...
library/src/main/java/com/google/android/exoplayer2/source/hls/HlsInitializationChunk.java
0 → 100644
View file @
f94218a7
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
google
.
android
.
exoplayer2
.
source
.
hls
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.Format
;
import
com.google.android.exoplayer2.extractor.DefaultExtractorInput
;
import
com.google.android.exoplayer2.extractor.Extractor
;
import
com.google.android.exoplayer2.extractor.ExtractorInput
;
import
com.google.android.exoplayer2.source.chunk.Chunk
;
import
com.google.android.exoplayer2.upstream.DataSource
;
import
com.google.android.exoplayer2.upstream.DataSpec
;
import
com.google.android.exoplayer2.util.Util
;
import
java.io.IOException
;
/**
* An HLS initialization chunk. Provides the extractor with information required for extracting the
* samples.
*/
/* package */
final
class
HlsInitializationChunk
extends
Chunk
{
public
final
Format
format
;
public
final
Extractor
extractor
;
private
int
bytesLoaded
;
private
volatile
boolean
loadCanceled
;
public
HlsInitializationChunk
(
DataSource
dataSource
,
DataSpec
dataSpec
,
int
trackSelectionReason
,
Object
trackSelectionData
,
Extractor
extractor
,
Format
format
)
{
super
(
dataSource
,
dataSpec
,
C
.
TRACK_TYPE_DEFAULT
,
null
,
trackSelectionReason
,
trackSelectionData
,
C
.
TIME_UNSET
,
C
.
TIME_UNSET
);
this
.
extractor
=
extractor
;
this
.
format
=
format
;
}
/**
* Sets the {@link HlsSampleStreamWrapper} that will receive the sample format information from
* the initialization chunk.
*
* @param output The output that will receive the format information.
*/
public
void
init
(
HlsSampleStreamWrapper
output
)
{
extractor
.
init
(
output
);
}
@Override
public
long
bytesLoaded
()
{
return
bytesLoaded
;
}
@Override
public
void
cancelLoad
()
{
loadCanceled
=
true
;
}
@Override
public
boolean
isLoadCanceled
()
{
return
loadCanceled
;
}
@Override
public
void
load
()
throws
IOException
,
InterruptedException
{
DataSpec
loadDataSpec
=
Util
.
getRemainderDataSpec
(
dataSpec
,
bytesLoaded
);
try
{
ExtractorInput
input
=
new
DefaultExtractorInput
(
dataSource
,
loadDataSpec
.
absoluteStreamPosition
,
dataSource
.
open
(
loadDataSpec
));
try
{
int
result
=
Extractor
.
RESULT_CONTINUE
;
while
(
result
==
Extractor
.
RESULT_CONTINUE
&&
!
loadCanceled
)
{
result
=
extractor
.
read
(
input
,
null
);
}
}
finally
{
bytesLoaded
=
(
int
)
(
input
.
getPosition
()
-
dataSpec
.
absoluteStreamPosition
);
}
}
finally
{
dataSource
.
close
();
}
}
}
library/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunk.java
View file @
f94218a7
...
@@ -19,7 +19,7 @@ import com.google.android.exoplayer2.Format;
...
@@ -19,7 +19,7 @@ import com.google.android.exoplayer2.Format;
import
com.google.android.exoplayer2.extractor.DefaultExtractorInput
;
import
com.google.android.exoplayer2.extractor.DefaultExtractorInput
;
import
com.google.android.exoplayer2.extractor.Extractor
;
import
com.google.android.exoplayer2.extractor.Extractor
;
import
com.google.android.exoplayer2.extractor.ExtractorInput
;
import
com.google.android.exoplayer2.extractor.ExtractorInput
;
import
com.google.android.exoplayer2.extractor.
ts.
TimestampAdjuster
;
import
com.google.android.exoplayer2.extractor.TimestampAdjuster
;
import
com.google.android.exoplayer2.source.chunk.MediaChunk
;
import
com.google.android.exoplayer2.source.chunk.MediaChunk
;
import
com.google.android.exoplayer2.upstream.DataSource
;
import
com.google.android.exoplayer2.upstream.DataSource
;
import
com.google.android.exoplayer2.upstream.DataSpec
;
import
com.google.android.exoplayer2.upstream.DataSpec
;
...
...
library/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java
View file @
f94218a7
...
@@ -39,6 +39,7 @@ import com.google.android.exoplayer2.upstream.Allocator;
...
@@ -39,6 +39,7 @@ import com.google.android.exoplayer2.upstream.Allocator;
import
com.google.android.exoplayer2.upstream.DataSource
;
import
com.google.android.exoplayer2.upstream.DataSource
;
import
com.google.android.exoplayer2.upstream.Loader
;
import
com.google.android.exoplayer2.upstream.Loader
;
import
com.google.android.exoplayer2.upstream.ParsingLoadable
;
import
com.google.android.exoplayer2.upstream.ParsingLoadable
;
import
com.google.android.exoplayer2.util.Assertions
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.IdentityHashMap
;
import
java.util.IdentityHashMap
;
...
@@ -154,7 +155,8 @@ import java.util.List;
...
@@ -154,7 +155,8 @@ import java.util.List;
}
}
boolean
selectedNewTracks
=
false
;
boolean
selectedNewTracks
=
false
;
streamWrapperIndices
.
clear
();
streamWrapperIndices
.
clear
();
// Select tracks for each child, copying the resulting streams back into the streams array.
// Select tracks for each child, copying the resulting streams back into a new streams array.
SampleStream
[]
newStreams
=
new
SampleStream
[
selections
.
length
];
SampleStream
[]
childStreams
=
new
SampleStream
[
selections
.
length
];
SampleStream
[]
childStreams
=
new
SampleStream
[
selections
.
length
];
TrackSelection
[]
childSelections
=
new
TrackSelection
[
selections
.
length
];
TrackSelection
[]
childSelections
=
new
TrackSelection
[
selections
.
length
];
ArrayList
<
HlsSampleStreamWrapper
>
enabledSampleStreamWrapperList
=
new
ArrayList
<>(
ArrayList
<
HlsSampleStreamWrapper
>
enabledSampleStreamWrapperList
=
new
ArrayList
<>(
...
@@ -168,19 +170,23 @@ import java.util.List;
...
@@ -168,19 +170,23 @@ import java.util.List;
mayRetainStreamFlags
,
childStreams
,
streamResetFlags
,
!
seenFirstTrackSelection
);
mayRetainStreamFlags
,
childStreams
,
streamResetFlags
,
!
seenFirstTrackSelection
);
boolean
wrapperEnabled
=
false
;
boolean
wrapperEnabled
=
false
;
for
(
int
j
=
0
;
j
<
selections
.
length
;
j
++)
{
for
(
int
j
=
0
;
j
<
selections
.
length
;
j
++)
{
if
(
selectionChildIndices
[
j
]
==
i
if
(
selectionChildIndices
[
j
]
==
i
)
{
||
(
selectionChildIndices
[
j
]
==
C
.
INDEX_UNSET
&&
streamChildIndices
[
j
]
==
i
))
{
// Assert that the child provided a stream for the selection.
streams
[
j
]
=
childStreams
[
j
];
Assertions
.
checkState
(
childStreams
[
j
]
!=
null
);
if
(
childStreams
[
j
]
!=
null
)
{
newStreams
[
j
]
=
childStreams
[
j
];
wrapperEnabled
=
true
;
wrapperEnabled
=
true
;
streamWrapperIndices
.
put
(
childStreams
[
j
],
i
);
streamWrapperIndices
.
put
(
childStreams
[
j
],
i
);
}
}
else
if
(
streamChildIndices
[
j
]
==
i
)
{
// Assert that the child cleared any previous stream.
Assertions
.
checkState
(
childStreams
[
j
]
==
null
);
}
}
}
}
if
(
wrapperEnabled
)
{
if
(
wrapperEnabled
)
{
enabledSampleStreamWrapperList
.
add
(
sampleStreamWrappers
[
i
]);
enabledSampleStreamWrapperList
.
add
(
sampleStreamWrappers
[
i
]);
}
}
}
}
// Copy the new streams back into the streams array.
System
.
arraycopy
(
newStreams
,
0
,
streams
,
0
,
newStreams
.
length
);
// Update the local state.
// Update the local state.
enabledSampleStreamWrappers
=
new
HlsSampleStreamWrapper
[
enabledSampleStreamWrapperList
.
size
()];
enabledSampleStreamWrappers
=
new
HlsSampleStreamWrapper
[
enabledSampleStreamWrapperList
.
size
()];
enabledSampleStreamWrapperList
.
toArray
(
enabledSampleStreamWrappers
);
enabledSampleStreamWrapperList
.
toArray
(
enabledSampleStreamWrappers
);
...
...
library/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java
View file @
f94218a7
...
@@ -358,6 +358,8 @@ import java.util.LinkedList;
...
@@ -358,6 +358,8 @@ import java.util.LinkedList;
HlsMediaChunk
mediaChunk
=
(
HlsMediaChunk
)
loadable
;
HlsMediaChunk
mediaChunk
=
(
HlsMediaChunk
)
loadable
;
mediaChunk
.
init
(
this
);
mediaChunk
.
init
(
this
);
mediaChunks
.
add
(
mediaChunk
);
mediaChunks
.
add
(
mediaChunk
);
}
else
if
(
loadable
instanceof
HlsInitializationChunk
)
{
((
HlsInitializationChunk
)
loadable
).
init
(
this
);
}
}
long
elapsedRealtimeMs
=
loader
.
startLoading
(
loadable
,
this
,
minLoadableRetryCount
);
long
elapsedRealtimeMs
=
loader
.
startLoading
(
loadable
,
this
,
minLoadableRetryCount
);
eventDispatcher
.
loadStarted
(
loadable
.
dataSpec
,
loadable
.
type
,
trackType
,
loadable
.
trackFormat
,
eventDispatcher
.
loadStarted
(
loadable
.
dataSpec
,
loadable
.
type
,
trackType
,
loadable
.
trackFormat
,
...
...
library/src/main/java/com/google/android/exoplayer2/source/hls/TimestampAdjusterProvider.java
View file @
f94218a7
...
@@ -16,7 +16,7 @@
...
@@ -16,7 +16,7 @@
package
com
.
google
.
android
.
exoplayer2
.
source
.
hls
;
package
com
.
google
.
android
.
exoplayer2
.
source
.
hls
;
import
android.util.SparseArray
;
import
android.util.SparseArray
;
import
com.google.android.exoplayer2.extractor.
ts.
TimestampAdjuster
;
import
com.google.android.exoplayer2.extractor.TimestampAdjuster
;
/**
/**
* Provides {@link TimestampAdjuster} instances for use during HLS playbacks.
* Provides {@link TimestampAdjuster} instances for use during HLS playbacks.
...
...
library/src/main/java/com/google/android/exoplayer2/source/hls/WebvttExtractor.java
View file @
f94218a7
...
@@ -24,8 +24,8 @@ import com.google.android.exoplayer2.extractor.ExtractorInput;
...
@@ -24,8 +24,8 @@ import com.google.android.exoplayer2.extractor.ExtractorInput;
import
com.google.android.exoplayer2.extractor.ExtractorOutput
;
import
com.google.android.exoplayer2.extractor.ExtractorOutput
;
import
com.google.android.exoplayer2.extractor.PositionHolder
;
import
com.google.android.exoplayer2.extractor.PositionHolder
;
import
com.google.android.exoplayer2.extractor.SeekMap
;
import
com.google.android.exoplayer2.extractor.SeekMap
;
import
com.google.android.exoplayer2.extractor.TimestampAdjuster
;
import
com.google.android.exoplayer2.extractor.TrackOutput
;
import
com.google.android.exoplayer2.extractor.TrackOutput
;
import
com.google.android.exoplayer2.extractor.ts.TimestampAdjuster
;
import
com.google.android.exoplayer2.text.SubtitleDecoderException
;
import
com.google.android.exoplayer2.text.SubtitleDecoderException
;
import
com.google.android.exoplayer2.text.webvtt.WebvttParserUtil
;
import
com.google.android.exoplayer2.text.webvtt.WebvttParserUtil
;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
com.google.android.exoplayer2.util.MimeTypes
;
...
...
library/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMediaPlaylist.java
View file @
f94218a7
...
@@ -38,6 +38,10 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
...
@@ -38,6 +38,10 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
public
final
long
byterangeOffset
;
public
final
long
byterangeOffset
;
public
final
long
byterangeLength
;
public
final
long
byterangeLength
;
public
Segment
(
String
uri
,
long
byterangeOffset
,
long
byterangeLength
)
{
this
(
uri
,
0
,
-
1
,
C
.
TIME_UNSET
,
false
,
null
,
null
,
byterangeOffset
,
byterangeLength
);
}
public
Segment
(
String
uri
,
double
durationSecs
,
int
discontinuitySequenceNumber
,
public
Segment
(
String
uri
,
double
durationSecs
,
int
discontinuitySequenceNumber
,
long
startTimeUs
,
boolean
isEncrypted
,
String
encryptionKeyUri
,
String
encryptionIV
,
long
startTimeUs
,
boolean
isEncrypted
,
String
encryptionKeyUri
,
String
encryptionIV
,
long
byterangeOffset
,
long
byterangeLength
)
{
long
byterangeOffset
,
long
byterangeLength
)
{
...
@@ -64,17 +68,19 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
...
@@ -64,17 +68,19 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
public
final
int
mediaSequence
;
public
final
int
mediaSequence
;
public
final
int
targetDurationSecs
;
public
final
int
targetDurationSecs
;
public
final
int
version
;
public
final
int
version
;
public
final
Segment
initializationSegment
;
public
final
List
<
Segment
>
segments
;
public
final
List
<
Segment
>
segments
;
public
final
boolean
live
;
public
final
boolean
live
;
public
final
long
durationUs
;
public
final
long
durationUs
;
public
HlsMediaPlaylist
(
String
baseUri
,
int
mediaSequence
,
int
targetDurationSecs
,
int
version
,
public
HlsMediaPlaylist
(
String
baseUri
,
int
mediaSequence
,
int
targetDurationSecs
,
int
version
,
boolean
live
,
List
<
Segment
>
segments
)
{
boolean
live
,
Segment
initializationSegment
,
List
<
Segment
>
segments
)
{
super
(
baseUri
,
HlsPlaylist
.
TYPE_MEDIA
);
super
(
baseUri
,
HlsPlaylist
.
TYPE_MEDIA
);
this
.
mediaSequence
=
mediaSequence
;
this
.
mediaSequence
=
mediaSequence
;
this
.
targetDurationSecs
=
targetDurationSecs
;
this
.
targetDurationSecs
=
targetDurationSecs
;
this
.
version
=
version
;
this
.
version
=
version
;
this
.
live
=
live
;
this
.
live
=
live
;
this
.
initializationSegment
=
initializationSegment
;
this
.
segments
=
segments
;
this
.
segments
=
segments
;
if
(!
segments
.
isEmpty
())
{
if
(!
segments
.
isEmpty
())
{
...
...
library/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java
View file @
f94218a7
...
@@ -44,6 +44,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
...
@@ -44,6 +44,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
private
static
final
String
TAG_MEDIA
=
"#EXT-X-MEDIA"
;
private
static
final
String
TAG_MEDIA
=
"#EXT-X-MEDIA"
;
private
static
final
String
TAG_DISCONTINUITY
=
"#EXT-X-DISCONTINUITY"
;
private
static
final
String
TAG_DISCONTINUITY
=
"#EXT-X-DISCONTINUITY"
;
private
static
final
String
TAG_DISCONTINUITY_SEQUENCE
=
"#EXT-X-DISCONTINUITY-SEQUENCE"
;
private
static
final
String
TAG_DISCONTINUITY_SEQUENCE
=
"#EXT-X-DISCONTINUITY-SEQUENCE"
;
private
static
final
String
TAG_INIT_SEGMENT
=
"#EXT-X-MAP"
;
private
static
final
String
TAG_MEDIA_DURATION
=
"#EXTINF"
;
private
static
final
String
TAG_MEDIA_DURATION
=
"#EXTINF"
;
private
static
final
String
TAG_MEDIA_SEQUENCE
=
"#EXT-X-MEDIA-SEQUENCE"
;
private
static
final
String
TAG_MEDIA_SEQUENCE
=
"#EXT-X-MEDIA-SEQUENCE"
;
private
static
final
String
TAG_TARGET_DURATION
=
"#EXT-X-TARGETDURATION"
;
private
static
final
String
TAG_TARGET_DURATION
=
"#EXT-X-TARGETDURATION"
;
...
@@ -79,6 +80,8 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
...
@@ -79,6 +80,8 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
+
":([\\d\\.]+)\\b"
);
+
":([\\d\\.]+)\\b"
);
private
static
final
Pattern
REGEX_BYTERANGE
=
Pattern
.
compile
(
TAG_BYTERANGE
private
static
final
Pattern
REGEX_BYTERANGE
=
Pattern
.
compile
(
TAG_BYTERANGE
+
":(\\d+(?:@\\d+)?)\\b"
);
+
":(\\d+(?:@\\d+)?)\\b"
);
private
static
final
Pattern
REGEX_ATTR_BYTERANGE
=
Pattern
.
compile
(
"BYTERANGE=\"(\\d+(?:@\\d+)?)\\b\""
);
private
static
final
Pattern
REGEX_METHOD
=
Pattern
.
compile
(
"METHOD=("
+
METHOD_NONE
+
"|"
private
static
final
Pattern
REGEX_METHOD
=
Pattern
.
compile
(
"METHOD=("
+
METHOD_NONE
+
"|"
+
METHOD_AES128
+
")"
);
+
METHOD_AES128
+
")"
);
private
static
final
Pattern
REGEX_URI
=
Pattern
.
compile
(
"URI=\"(.+?)\""
);
private
static
final
Pattern
REGEX_URI
=
Pattern
.
compile
(
"URI=\"(.+?)\""
);
...
@@ -212,13 +215,14 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
...
@@ -212,13 +215,14 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
int
targetDurationSecs
=
0
;
int
targetDurationSecs
=
0
;
int
version
=
1
;
// Default version == 1.
int
version
=
1
;
// Default version == 1.
boolean
live
=
true
;
boolean
live
=
true
;
Segment
initializationSegment
=
null
;
List
<
Segment
>
segments
=
new
ArrayList
<>();
List
<
Segment
>
segments
=
new
ArrayList
<>();
double
segmentDurationSecs
=
0.0
;
double
segmentDurationSecs
=
0.0
;
int
discontinuitySequenceNumber
=
0
;
int
discontinuitySequenceNumber
=
0
;
long
segmentStartTimeUs
=
0
;
long
segmentStartTimeUs
=
0
;
long
segmentByte
r
angeOffset
=
0
;
long
segmentByte
R
angeOffset
=
0
;
long
segmentByte
r
angeLength
=
C
.
LENGTH_UNSET
;
long
segmentByte
R
angeLength
=
C
.
LENGTH_UNSET
;
int
segmentMediaSequence
=
0
;
int
segmentMediaSequence
=
0
;
boolean
isEncrypted
=
false
;
boolean
isEncrypted
=
false
;
...
@@ -228,7 +232,20 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
...
@@ -228,7 +232,20 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
String
line
;
String
line
;
while
(
iterator
.
hasNext
())
{
while
(
iterator
.
hasNext
())
{
line
=
iterator
.
next
();
line
=
iterator
.
next
();
if
(
line
.
startsWith
(
TAG_TARGET_DURATION
))
{
if
(
line
.
startsWith
(
TAG_INIT_SEGMENT
))
{
String
uri
=
parseStringAttr
(
line
,
REGEX_URI
);
String
byteRange
=
parseOptionalStringAttr
(
line
,
REGEX_ATTR_BYTERANGE
);
if
(
byteRange
!=
null
)
{
String
[]
splitByteRange
=
byteRange
.
split
(
"@"
);
segmentByteRangeLength
=
Long
.
parseLong
(
splitByteRange
[
0
]);
if
(
splitByteRange
.
length
>
1
)
{
segmentByteRangeOffset
=
Long
.
parseLong
(
splitByteRange
[
1
]);
}
}
initializationSegment
=
new
Segment
(
uri
,
segmentByteRangeOffset
,
segmentByteRangeLength
);
segmentByteRangeOffset
=
0
;
segmentByteRangeLength
=
C
.
LENGTH_UNSET
;
}
else
if
(
line
.
startsWith
(
TAG_TARGET_DURATION
))
{
targetDurationSecs
=
parseIntAttr
(
line
,
REGEX_TARGET_DURATION
);
targetDurationSecs
=
parseIntAttr
(
line
,
REGEX_TARGET_DURATION
);
}
else
if
(
line
.
startsWith
(
TAG_MEDIA_SEQUENCE
))
{
}
else
if
(
line
.
startsWith
(
TAG_MEDIA_SEQUENCE
))
{
mediaSequence
=
parseIntAttr
(
line
,
REGEX_MEDIA_SEQUENCE
);
mediaSequence
=
parseIntAttr
(
line
,
REGEX_MEDIA_SEQUENCE
);
...
@@ -250,9 +267,9 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
...
@@ -250,9 +267,9 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
}
else
if
(
line
.
startsWith
(
TAG_BYTERANGE
))
{
}
else
if
(
line
.
startsWith
(
TAG_BYTERANGE
))
{
String
byteRange
=
parseStringAttr
(
line
,
REGEX_BYTERANGE
);
String
byteRange
=
parseStringAttr
(
line
,
REGEX_BYTERANGE
);
String
[]
splitByteRange
=
byteRange
.
split
(
"@"
);
String
[]
splitByteRange
=
byteRange
.
split
(
"@"
);
segmentByte
r
angeLength
=
Long
.
parseLong
(
splitByteRange
[
0
]);
segmentByte
R
angeLength
=
Long
.
parseLong
(
splitByteRange
[
0
]);
if
(
splitByteRange
.
length
>
1
)
{
if
(
splitByteRange
.
length
>
1
)
{
segmentByte
r
angeOffset
=
Long
.
parseLong
(
splitByteRange
[
1
]);
segmentByte
R
angeOffset
=
Long
.
parseLong
(
splitByteRange
[
1
]);
}
}
}
else
if
(
line
.
startsWith
(
TAG_DISCONTINUITY_SEQUENCE
))
{
}
else
if
(
line
.
startsWith
(
TAG_DISCONTINUITY_SEQUENCE
))
{
discontinuitySequenceNumber
=
Integer
.
parseInt
(
line
.
substring
(
line
.
indexOf
(
':'
)
+
1
));
discontinuitySequenceNumber
=
Integer
.
parseInt
(
line
.
substring
(
line
.
indexOf
(
':'
)
+
1
));
...
@@ -268,24 +285,24 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
...
@@ -268,24 +285,24 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
segmentEncryptionIV
=
Integer
.
toHexString
(
segmentMediaSequence
);
segmentEncryptionIV
=
Integer
.
toHexString
(
segmentMediaSequence
);
}
}
segmentMediaSequence
++;
segmentMediaSequence
++;
if
(
segmentByte
r
angeLength
==
C
.
LENGTH_UNSET
)
{
if
(
segmentByte
R
angeLength
==
C
.
LENGTH_UNSET
)
{
segmentByte
r
angeOffset
=
0
;
segmentByte
R
angeOffset
=
0
;
}
}
segments
.
add
(
new
Segment
(
line
,
segmentDurationSecs
,
discontinuitySequenceNumber
,
segments
.
add
(
new
Segment
(
line
,
segmentDurationSecs
,
discontinuitySequenceNumber
,
segmentStartTimeUs
,
isEncrypted
,
encryptionKeyUri
,
segmentEncryptionIV
,
segmentStartTimeUs
,
isEncrypted
,
encryptionKeyUri
,
segmentEncryptionIV
,
segmentByte
rangeOffset
,
segmentByter
angeLength
));
segmentByte
RangeOffset
,
segmentByteR
angeLength
));
segmentStartTimeUs
+=
(
long
)
(
segmentDurationSecs
*
C
.
MICROS_PER_SECOND
);
segmentStartTimeUs
+=
(
long
)
(
segmentDurationSecs
*
C
.
MICROS_PER_SECOND
);
segmentDurationSecs
=
0.0
;
segmentDurationSecs
=
0.0
;
if
(
segmentByte
r
angeLength
!=
C
.
LENGTH_UNSET
)
{
if
(
segmentByte
R
angeLength
!=
C
.
LENGTH_UNSET
)
{
segmentByte
rangeOffset
+=
segmentByter
angeLength
;
segmentByte
RangeOffset
+=
segmentByteR
angeLength
;
}
}
segmentByte
r
angeLength
=
C
.
LENGTH_UNSET
;
segmentByte
R
angeLength
=
C
.
LENGTH_UNSET
;
}
else
if
(
line
.
equals
(
TAG_ENDLIST
))
{
}
else
if
(
line
.
equals
(
TAG_ENDLIST
))
{
live
=
false
;
live
=
false
;
}
}
}
}
return
new
HlsMediaPlaylist
(
baseUri
,
mediaSequence
,
targetDurationSecs
,
version
,
live
,
return
new
HlsMediaPlaylist
(
baseUri
,
mediaSequence
,
targetDurationSecs
,
version
,
live
,
Collections
.
unmodifiableList
(
segments
));
initializationSegment
,
Collections
.
unmodifiableList
(
segments
));
}
}
private
static
String
parseStringAttr
(
String
line
,
Pattern
pattern
)
throws
ParserException
{
private
static
String
parseStringAttr
(
String
line
,
Pattern
pattern
)
throws
ParserException
{
...
...
library/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/DefaultSsChunkSource.java
View file @
f94218a7
...
@@ -101,7 +101,7 @@ public class DefaultSsChunkSource implements SsChunkSource {
...
@@ -101,7 +101,7 @@ public class DefaultSsChunkSource implements SsChunkSource {
trackEncryptionBoxes
,
nalUnitLengthFieldLength
,
null
,
null
);
trackEncryptionBoxes
,
nalUnitLengthFieldLength
,
null
,
null
);
FragmentedMp4Extractor
extractor
=
new
FragmentedMp4Extractor
(
FragmentedMp4Extractor
extractor
=
new
FragmentedMp4Extractor
(
FragmentedMp4Extractor
.
FLAG_WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME
FragmentedMp4Extractor
.
FLAG_WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME
|
FragmentedMp4Extractor
.
FLAG_WORKAROUND_IGNORE_TFDT_BOX
,
track
);
|
FragmentedMp4Extractor
.
FLAG_WORKAROUND_IGNORE_TFDT_BOX
,
track
,
null
);
extractorWrappers
[
i
]
=
new
ChunkExtractorWrapper
(
extractor
,
format
,
false
,
false
);
extractorWrappers
[
i
]
=
new
ChunkExtractorWrapper
(
extractor
,
format
,
false
,
false
);
}
}
}
}
...
...
library/src/main/java/com/google/android/exoplayer2/text/TextRenderer.java
View file @
f94218a7
...
@@ -160,21 +160,27 @@ public final class TextRenderer extends BaseRenderer implements Callback {
...
@@ -160,21 +160,27 @@ public final class TextRenderer extends BaseRenderer implements Callback {
}
}
}
}
if
(
nextSubtitle
!=
null
&&
nextSubtitle
.
timeUs
<=
positionUs
)
{
if
(
nextSubtitle
!=
null
)
{
// Advance to the next subtitle. Sync the next event index and trigger an update.
if
(
nextSubtitle
.
isEndOfStream
())
{
if
(
subtitle
!=
null
)
{
if
(!
textRendererNeedsUpdate
&&
getNextEventTime
()
==
Long
.
MAX_VALUE
)
{
subtitle
.
release
();
if
(
subtitle
!=
null
)
{
}
subtitle
.
release
();
subtitle
=
nextSubtitle
;
subtitle
=
null
;
nextSubtitle
=
null
;
}
if
(
subtitle
.
isEndOfStream
())
{
nextSubtitle
.
release
();
outputStreamEnded
=
true
;
nextSubtitle
=
null
;
subtitle
.
release
();
outputStreamEnded
=
true
;
subtitle
=
null
;
}
return
;
}
else
if
(
nextSubtitle
.
timeUs
<=
positionUs
)
{
// Advance to the next subtitle. Sync the next event index and trigger an update.
if
(
subtitle
!=
null
)
{
subtitle
.
release
();
}
subtitle
=
nextSubtitle
;
nextSubtitle
=
null
;
nextSubtitleEventIndex
=
subtitle
.
getNextEventTimeIndex
(
positionUs
);
textRendererNeedsUpdate
=
true
;
}
}
nextSubtitleEventIndex
=
subtitle
.
getNextEventTimeIndex
(
positionUs
);
textRendererNeedsUpdate
=
true
;
}
}
if
(
textRendererNeedsUpdate
)
{
if
(
textRendererNeedsUpdate
)
{
...
...
library/src/main/java/com/google/android/exoplayer2/ui/AspectRatioFrameLayout.java
View file @
f94218a7
...
@@ -16,15 +16,31 @@
...
@@ -16,15 +16,31 @@
package
com
.
google
.
android
.
exoplayer2
.
ui
;
package
com
.
google
.
android
.
exoplayer2
.
ui
;
import
android.content.Context
;
import
android.content.Context
;
import
android.content.res.TypedArray
;
import
android.util.AttributeSet
;
import
android.util.AttributeSet
;
import
android.widget.FrameLayout
;
import
android.widget.FrameLayout
;
import
com.google.android.exoplayer2.R
;
/**
/**
* A {@link FrameLayout} that resizes itself to match a specified aspect ratio.
* A {@link FrameLayout} that resizes itself to match a specified aspect ratio.
*/
*/
public
final
class
AspectRatioFrameLayout
extends
FrameLayout
{
public
final
class
AspectRatioFrameLayout
extends
FrameLayout
{
/**
/**
* Either the width or height is decreased to obtain the desired aspect ratio.
*/
public
static
final
int
RESIZE_MODE_FIT
=
0
;
/**
* The width is fixed and the height is increased or decreased to obtain the desired aspect ratio.
*/
public
static
final
int
RESIZE_MODE_FIXED_WIDTH
=
1
;
/**
* The height is fixed and the width is increased or decreased to obtain the desired aspect ratio.
*/
public
static
final
int
RESIZE_MODE_FIXED_HEIGHT
=
2
;
/**
* The {@link FrameLayout} will not resize itself if the fractional difference between its natural
* The {@link FrameLayout} will not resize itself if the fractional difference between its natural
* aspect ratio and the requested aspect ratio falls below this threshold.
* aspect ratio and the requested aspect ratio falls below this threshold.
* <p>
* <p>
...
@@ -36,13 +52,24 @@ public final class AspectRatioFrameLayout extends FrameLayout {
...
@@ -36,13 +52,24 @@ public final class AspectRatioFrameLayout extends FrameLayout {
private
static
final
float
MAX_ASPECT_RATIO_DEFORMATION_FRACTION
=
0.01f
;
private
static
final
float
MAX_ASPECT_RATIO_DEFORMATION_FRACTION
=
0.01f
;
private
float
videoAspectRatio
;
private
float
videoAspectRatio
;
private
int
resizeMode
;
public
AspectRatioFrameLayout
(
Context
context
)
{
public
AspectRatioFrameLayout
(
Context
context
)
{
super
(
context
);
this
(
context
,
null
);
}
}
public
AspectRatioFrameLayout
(
Context
context
,
AttributeSet
attrs
)
{
public
AspectRatioFrameLayout
(
Context
context
,
AttributeSet
attrs
)
{
super
(
context
,
attrs
);
super
(
context
,
attrs
);
resizeMode
=
RESIZE_MODE_FIT
;
if
(
attrs
!=
null
)
{
TypedArray
a
=
context
.
getTheme
().
obtainStyledAttributes
(
attrs
,
R
.
styleable
.
AspectRatioFrameLayout
,
0
,
0
);
try
{
resizeMode
=
a
.
getInt
(
R
.
styleable
.
AspectRatioFrameLayout_resize_mode
,
RESIZE_MODE_FIT
);
}
finally
{
a
.
recycle
();
}
}
}
}
/**
/**
...
@@ -57,6 +84,19 @@ public final class AspectRatioFrameLayout extends FrameLayout {
...
@@ -57,6 +84,19 @@ public final class AspectRatioFrameLayout extends FrameLayout {
}
}
}
}
/**
* Sets the resize mode which can be of value {@link #RESIZE_MODE_FIT},
* {@link #RESIZE_MODE_FIXED_HEIGHT} or {@link #RESIZE_MODE_FIXED_WIDTH}.
*
* @param resizeMode The resize mode.
*/
public
void
setResizeMode
(
int
resizeMode
)
{
if
(
this
.
resizeMode
!=
resizeMode
)
{
this
.
resizeMode
=
resizeMode
;
requestLayout
();
}
}
@Override
@Override
protected
void
onMeasure
(
int
widthMeasureSpec
,
int
heightMeasureSpec
)
{
protected
void
onMeasure
(
int
widthMeasureSpec
,
int
heightMeasureSpec
)
{
super
.
onMeasure
(
widthMeasureSpec
,
heightMeasureSpec
);
super
.
onMeasure
(
widthMeasureSpec
,
heightMeasureSpec
);
...
@@ -74,10 +114,20 @@ public final class AspectRatioFrameLayout extends FrameLayout {
...
@@ -74,10 +114,20 @@ public final class AspectRatioFrameLayout extends FrameLayout {
return
;
return
;
}
}
if
(
aspectDeformation
>
0
)
{
switch
(
resizeMode
)
{
height
=
(
int
)
(
width
/
videoAspectRatio
);
case
RESIZE_MODE_FIXED_WIDTH:
}
else
{
height
=
(
int
)
(
width
/
videoAspectRatio
);
width
=
(
int
)
(
height
*
videoAspectRatio
);
break
;
case
RESIZE_MODE_FIXED_HEIGHT:
width
=
(
int
)
(
height
*
videoAspectRatio
);
break
;
default
:
if
(
aspectDeformation
>
0
)
{
height
=
(
int
)
(
width
/
videoAspectRatio
);
}
else
{
width
=
(
int
)
(
height
*
videoAspectRatio
);
}
break
;
}
}
super
.
onMeasure
(
MeasureSpec
.
makeMeasureSpec
(
width
,
MeasureSpec
.
EXACTLY
),
super
.
onMeasure
(
MeasureSpec
.
makeMeasureSpec
(
width
,
MeasureSpec
.
EXACTLY
),
MeasureSpec
.
makeMeasureSpec
(
height
,
MeasureSpec
.
EXACTLY
));
MeasureSpec
.
makeMeasureSpec
(
height
,
MeasureSpec
.
EXACTLY
));
...
...
library/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java
View file @
f94218a7
...
@@ -128,11 +128,21 @@ public class PlaybackControlView extends FrameLayout {
...
@@ -128,11 +128,21 @@ public class PlaybackControlView extends FrameLayout {
}
}
/**
/**
* Returns the player currently being controlled by this view, or null if no player is set.
*/
public
ExoPlayer
getPlayer
()
{
return
player
;
}
/**
* Sets the {@link ExoPlayer} to control.
* Sets the {@link ExoPlayer} to control.
*
*
* @param player the {@code ExoPlayer} to control.
* @param player the {@code ExoPlayer} to control.
*/
*/
public
void
setPlayer
(
ExoPlayer
player
)
{
public
void
setPlayer
(
ExoPlayer
player
)
{
if
(
this
.
player
==
player
)
{
return
;
}
if
(
this
.
player
!=
null
)
{
if
(
this
.
player
!=
null
)
{
this
.
player
.
removeListener
(
componentListener
);
this
.
player
.
removeListener
(
componentListener
);
}
}
...
...
library/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java
View file @
f94218a7
...
@@ -63,6 +63,7 @@ public final class SimpleExoPlayerView extends FrameLayout {
...
@@ -63,6 +63,7 @@ public final class SimpleExoPlayerView extends FrameLayout {
super
(
context
,
attrs
,
defStyleAttr
);
super
(
context
,
attrs
,
defStyleAttr
);
boolean
useTextureView
=
false
;
boolean
useTextureView
=
false
;
int
resizeMode
=
AspectRatioFrameLayout
.
RESIZE_MODE_FIT
;
if
(
attrs
!=
null
)
{
if
(
attrs
!=
null
)
{
TypedArray
a
=
context
.
getTheme
().
obtainStyledAttributes
(
attrs
,
TypedArray
a
=
context
.
getTheme
().
obtainStyledAttributes
(
attrs
,
R
.
styleable
.
SimpleExoPlayerView
,
0
,
0
);
R
.
styleable
.
SimpleExoPlayerView
,
0
,
0
);
...
@@ -70,6 +71,8 @@ public final class SimpleExoPlayerView extends FrameLayout {
...
@@ -70,6 +71,8 @@ public final class SimpleExoPlayerView extends FrameLayout {
useController
=
a
.
getBoolean
(
R
.
styleable
.
SimpleExoPlayerView_use_controller
,
useController
);
useController
=
a
.
getBoolean
(
R
.
styleable
.
SimpleExoPlayerView_use_controller
,
useController
);
useTextureView
=
a
.
getBoolean
(
R
.
styleable
.
SimpleExoPlayerView_use_texture_view
,
useTextureView
=
a
.
getBoolean
(
R
.
styleable
.
SimpleExoPlayerView_use_texture_view
,
useTextureView
);
useTextureView
);
resizeMode
=
a
.
getInt
(
R
.
styleable
.
SimpleExoPlayerView_resize_mode
,
AspectRatioFrameLayout
.
RESIZE_MODE_FIT
);
}
finally
{
}
finally
{
a
.
recycle
();
a
.
recycle
();
}
}
...
@@ -78,6 +81,7 @@ public final class SimpleExoPlayerView extends FrameLayout {
...
@@ -78,6 +81,7 @@ public final class SimpleExoPlayerView extends FrameLayout {
LayoutInflater
.
from
(
context
).
inflate
(
R
.
layout
.
exo_simple_player_view
,
this
);
LayoutInflater
.
from
(
context
).
inflate
(
R
.
layout
.
exo_simple_player_view
,
this
);
componentListener
=
new
ComponentListener
();
componentListener
=
new
ComponentListener
();
layout
=
(
AspectRatioFrameLayout
)
findViewById
(
R
.
id
.
video_frame
);
layout
=
(
AspectRatioFrameLayout
)
findViewById
(
R
.
id
.
video_frame
);
layout
.
setResizeMode
(
resizeMode
);
controller
=
(
PlaybackControlView
)
findViewById
(
R
.
id
.
control
);
controller
=
(
PlaybackControlView
)
findViewById
(
R
.
id
.
control
);
shutterView
=
findViewById
(
R
.
id
.
shutter
);
shutterView
=
findViewById
(
R
.
id
.
shutter
);
subtitleLayout
=
(
SubtitleView
)
findViewById
(
R
.
id
.
subtitles
);
subtitleLayout
=
(
SubtitleView
)
findViewById
(
R
.
id
.
subtitles
);
...
@@ -94,6 +98,13 @@ public final class SimpleExoPlayerView extends FrameLayout {
...
@@ -94,6 +98,13 @@ public final class SimpleExoPlayerView extends FrameLayout {
}
}
/**
/**
* Returns the player currently set on this view, or null if no player is set.
*/
public
SimpleExoPlayer
getPlayer
()
{
return
player
;
}
/**
* Set the {@link SimpleExoPlayer} to use. The {@link SimpleExoPlayer#setTextOutput} and
* Set the {@link SimpleExoPlayer} to use. The {@link SimpleExoPlayer#setTextOutput} and
* {@link SimpleExoPlayer#setVideoListener} method of the player will be called and previous
* {@link SimpleExoPlayer#setVideoListener} method of the player will be called and previous
* assignments are overridden.
* assignments are overridden.
...
@@ -101,6 +112,9 @@ public final class SimpleExoPlayerView extends FrameLayout {
...
@@ -101,6 +112,9 @@ public final class SimpleExoPlayerView extends FrameLayout {
* @param player The {@link SimpleExoPlayer} to use.
* @param player The {@link SimpleExoPlayer} to use.
*/
*/
public
void
setPlayer
(
SimpleExoPlayer
player
)
{
public
void
setPlayer
(
SimpleExoPlayer
player
)
{
if
(
this
.
player
==
player
)
{
return
;
}
if
(
this
.
player
!=
null
)
{
if
(
this
.
player
!=
null
)
{
this
.
player
.
setTextOutput
(
null
);
this
.
player
.
setTextOutput
(
null
);
this
.
player
.
setVideoListener
(
null
);
this
.
player
.
setVideoListener
(
null
);
...
@@ -120,7 +134,9 @@ public final class SimpleExoPlayerView extends FrameLayout {
...
@@ -120,7 +134,9 @@ public final class SimpleExoPlayerView extends FrameLayout {
}
else
{
}
else
{
shutterView
.
setVisibility
(
VISIBLE
);
shutterView
.
setVisibility
(
VISIBLE
);
}
}
setUseController
(
useController
);
if
(
useController
)
{
controller
.
setPlayer
(
player
);
}
}
}
/**
/**
...
@@ -131,6 +147,9 @@ public final class SimpleExoPlayerView extends FrameLayout {
...
@@ -131,6 +147,9 @@ public final class SimpleExoPlayerView extends FrameLayout {
* @param useController If {@code false} the playback control is never used.
* @param useController If {@code false} the playback control is never used.
*/
*/
public
void
setUseController
(
boolean
useController
)
{
public
void
setUseController
(
boolean
useController
)
{
if
(
this
.
useController
==
useController
)
{
return
;
}
this
.
useController
=
useController
;
this
.
useController
=
useController
;
if
(
useController
)
{
if
(
useController
)
{
controller
.
setPlayer
(
player
);
controller
.
setPlayer
(
player
);
...
@@ -141,6 +160,17 @@ public final class SimpleExoPlayerView extends FrameLayout {
...
@@ -141,6 +160,17 @@ public final class SimpleExoPlayerView extends FrameLayout {
}
}
/**
/**
* Sets the resize mode which can be of value {@link AspectRatioFrameLayout#RESIZE_MODE_FIT},
* {@link AspectRatioFrameLayout#RESIZE_MODE_FIXED_HEIGHT} or
* {@link AspectRatioFrameLayout#RESIZE_MODE_FIXED_WIDTH}.
*
* @param resizeMode The resize mode.
*/
public
void
setResizeMode
(
int
resizeMode
)
{
layout
.
setResizeMode
(
resizeMode
);
}
/**
* Set the {@link PlaybackControlView.VisibilityListener}.
* Set the {@link PlaybackControlView.VisibilityListener}.
*
*
* @param listener The listener to be notified about visibility changes.
* @param listener The listener to be notified about visibility changes.
...
...
library/src/main/java/com/google/android/exoplayer2/upstream/AssetDataSource.java
View file @
f94218a7
...
@@ -104,29 +104,35 @@ public final class AssetDataSource implements DataSource {
...
@@ -104,29 +104,35 @@ public final class AssetDataSource implements DataSource {
@Override
@Override
public
int
read
(
byte
[]
buffer
,
int
offset
,
int
readLength
)
throws
AssetDataSourceException
{
public
int
read
(
byte
[]
buffer
,
int
offset
,
int
readLength
)
throws
AssetDataSourceException
{
if
(
bytesRemaining
==
0
)
{
if
(
readLength
==
0
)
{
return
0
;
}
else
if
(
bytesRemaining
==
0
)
{
return
C
.
RESULT_END_OF_INPUT
;
return
C
.
RESULT_END_OF_INPUT
;
}
else
{
}
int
bytesRead
;
try
{
int
bytesToRead
=
bytesRemaining
==
C
.
LENGTH_UNSET
?
readLength
:
(
int
)
Math
.
min
(
bytesRemaining
,
readLength
);
bytesRead
=
inputStream
.
read
(
buffer
,
offset
,
bytesToRead
);
}
catch
(
IOException
e
)
{
throw
new
AssetDataSourceException
(
e
);
}
if
(
bytesRead
>
0
)
{
int
bytesRead
;
if
(
bytesRemaining
!=
C
.
LENGTH_UNSET
)
{
try
{
bytesRemaining
-=
bytesRead
;
int
bytesToRead
=
bytesRemaining
==
C
.
LENGTH_UNSET
?
readLength
}
:
(
int
)
Math
.
min
(
bytesRemaining
,
readLength
);
if
(
listener
!=
null
)
{
bytesRead
=
inputStream
.
read
(
buffer
,
offset
,
bytesToRead
);
listener
.
onBytesTransferred
(
this
,
bytesRead
);
}
catch
(
IOException
e
)
{
}
throw
new
AssetDataSourceException
(
e
);
}
}
return
bytesRead
;
if
(
bytesRead
==
-
1
)
{
if
(
bytesRemaining
!=
C
.
LENGTH_UNSET
)
{
// End of stream reached having not read sufficient data.
throw
new
AssetDataSourceException
(
new
EOFException
());
}
return
C
.
RESULT_END_OF_INPUT
;
}
if
(
bytesRemaining
!=
C
.
LENGTH_UNSET
)
{
bytesRemaining
-=
bytesRead
;
}
if
(
listener
!=
null
)
{
listener
.
onBytesTransferred
(
this
,
bytesRead
);
}
}
return
bytesRead
;
}
}
@Override
@Override
...
...
library/src/main/java/com/google/android/exoplayer2/upstream/ByteArrayDataSource.java
View file @
f94218a7
...
@@ -54,15 +54,18 @@ public final class ByteArrayDataSource implements DataSource {
...
@@ -54,15 +54,18 @@ public final class ByteArrayDataSource implements DataSource {
}
}
@Override
@Override
public
int
read
(
byte
[]
buffer
,
int
offset
,
int
length
)
throws
IOException
{
public
int
read
(
byte
[]
buffer
,
int
offset
,
int
readLength
)
throws
IOException
{
if
(
bytesRemaining
==
0
)
{
if
(
readLength
==
0
)
{
return
0
;
}
else
if
(
bytesRemaining
==
0
)
{
return
C
.
RESULT_END_OF_INPUT
;
return
C
.
RESULT_END_OF_INPUT
;
}
}
length
=
Math
.
min
(
length
,
bytesRemaining
);
System
.
arraycopy
(
data
,
readPosition
,
buffer
,
offset
,
length
);
readLength
=
Math
.
min
(
readLength
,
bytesRemaining
);
readPosition
+=
length
;
System
.
arraycopy
(
data
,
readPosition
,
buffer
,
offset
,
readLength
);
bytesRemaining
-=
length
;
readPosition
+=
readLength
;
return
length
;
bytesRemaining
-=
readLength
;
return
readLength
;
}
}
@Override
@Override
...
...
library/src/main/java/com/google/android/exoplayer2/upstream/ContentDataSource.java
View file @
f94218a7
...
@@ -103,29 +103,35 @@ public final class ContentDataSource implements DataSource {
...
@@ -103,29 +103,35 @@ public final class ContentDataSource implements DataSource {
@Override
@Override
public
int
read
(
byte
[]
buffer
,
int
offset
,
int
readLength
)
throws
ContentDataSourceException
{
public
int
read
(
byte
[]
buffer
,
int
offset
,
int
readLength
)
throws
ContentDataSourceException
{
if
(
bytesRemaining
==
0
)
{
if
(
readLength
==
0
)
{
return
0
;
}
else
if
(
bytesRemaining
==
0
)
{
return
C
.
RESULT_END_OF_INPUT
;
return
C
.
RESULT_END_OF_INPUT
;
}
else
{
}
int
bytesRead
;
try
{
int
bytesToRead
=
bytesRemaining
==
C
.
LENGTH_UNSET
?
readLength
:
(
int
)
Math
.
min
(
bytesRemaining
,
readLength
);
bytesRead
=
inputStream
.
read
(
buffer
,
offset
,
bytesToRead
);
}
catch
(
IOException
e
)
{
throw
new
ContentDataSourceException
(
e
);
}
if
(
bytesRead
>
0
)
{
int
bytesRead
;
if
(
bytesRemaining
!=
C
.
LENGTH_UNSET
)
{
try
{
bytesRemaining
-=
bytesRead
;
int
bytesToRead
=
bytesRemaining
==
C
.
LENGTH_UNSET
?
readLength
}
:
(
int
)
Math
.
min
(
bytesRemaining
,
readLength
);
if
(
listener
!=
null
)
{
bytesRead
=
inputStream
.
read
(
buffer
,
offset
,
bytesToRead
);
listener
.
onBytesTransferred
(
this
,
bytesRead
);
}
catch
(
IOException
e
)
{
}
throw
new
ContentDataSourceException
(
e
);
}
}
return
bytesRead
;
if
(
bytesRead
==
-
1
)
{
if
(
bytesRemaining
!=
C
.
LENGTH_UNSET
)
{
// End of stream reached having not read sufficient data.
throw
new
ContentDataSourceException
(
new
EOFException
());
}
return
C
.
RESULT_END_OF_INPUT
;
}
if
(
bytesRemaining
!=
C
.
LENGTH_UNSET
)
{
bytesRemaining
-=
bytesRead
;
}
if
(
listener
!=
null
)
{
listener
.
onBytesTransferred
(
this
,
bytesRead
);
}
}
return
bytesRead
;
}
}
@Override
@Override
...
...
library/src/main/java/com/google/android/exoplayer2/upstream/DataSource.java
View file @
f94218a7
...
@@ -55,14 +55,18 @@ public interface DataSource {
...
@@ -55,14 +55,18 @@ public interface DataSource {
/**
/**
* Reads up to {@code length} bytes of data and stores them into {@code buffer}, starting at
* Reads up to {@code length} bytes of data and stores them into {@code buffer}, starting at
* index {@code offset}. Blocks until at least one byte of data can be read, the end of the opened
* index {@code offset}.
* range is detected, or an exception is thrown.
* <p>
* If {@code length} is zero then 0 is returned. Otherwise, if no data is available because the
* end of the opened range has been reached, then {@link C#RESULT_END_OF_INPUT} is returned.
* Otherwise, the call will block until at least one byte of data has been read and the number of
* bytes read is returned.
*
*
* @param buffer The buffer into which the read data should be stored.
* @param buffer The buffer into which the read data should be stored.
* @param offset The start offset into {@code buffer} at which data should be written.
* @param offset The start offset into {@code buffer} at which data should be written.
* @param readLength The maximum number of bytes to read.
* @param readLength The maximum number of bytes to read.
* @return The number of bytes read, or {@link C#RESULT_END_OF_INPUT} if
the end of the opened
* @return The number of bytes read, or {@link C#RESULT_END_OF_INPUT} if
no data is avaliable
*
range is
reached.
*
because the end of the opened range has been
reached.
* @throws IOException If an error occurs reading from the source.
* @throws IOException If an error occurs reading from the source.
*/
*/
int
read
(
byte
[]
buffer
,
int
offset
,
int
readLength
)
throws
IOException
;
int
read
(
byte
[]
buffer
,
int
offset
,
int
readLength
)
throws
IOException
;
...
...
library/src/main/java/com/google/android/exoplayer2/upstream/DefaultAllocator.java
View file @
f94218a7
...
@@ -26,6 +26,7 @@ public final class DefaultAllocator implements Allocator {
...
@@ -26,6 +26,7 @@ public final class DefaultAllocator implements Allocator {
private
static
final
int
AVAILABLE_EXTRA_CAPACITY
=
100
;
private
static
final
int
AVAILABLE_EXTRA_CAPACITY
=
100
;
private
final
boolean
trimOnReset
;
private
final
int
individualAllocationSize
;
private
final
int
individualAllocationSize
;
private
final
byte
[]
initialAllocationBlock
;
private
final
byte
[]
initialAllocationBlock
;
private
final
Allocation
[]
singleAllocationReleaseHolder
;
private
final
Allocation
[]
singleAllocationReleaseHolder
;
...
@@ -38,10 +39,12 @@ public final class DefaultAllocator implements Allocator {
...
@@ -38,10 +39,12 @@ public final class DefaultAllocator implements Allocator {
/**
/**
* Constructs an instance without creating any {@link Allocation}s up front.
* Constructs an instance without creating any {@link Allocation}s up front.
*
*
* @param trimOnReset Whether memory is freed when the allocator is reset. Should be true unless
* the allocator will be re-used by multiple player instances.
* @param individualAllocationSize The length of each individual {@link Allocation}.
* @param individualAllocationSize The length of each individual {@link Allocation}.
*/
*/
public
DefaultAllocator
(
int
individualAllocationSize
)
{
public
DefaultAllocator
(
boolean
trimOnReset
,
int
individualAllocationSize
)
{
this
(
individualAllocationSize
,
0
);
this
(
trimOnReset
,
individualAllocationSize
,
0
);
}
}
/**
/**
...
@@ -49,12 +52,16 @@ public final class DefaultAllocator implements Allocator {
...
@@ -49,12 +52,16 @@ public final class DefaultAllocator implements Allocator {
* <p>
* <p>
* Note: {@link Allocation}s created up front will never be discarded by {@link #trim()}.
* Note: {@link Allocation}s created up front will never be discarded by {@link #trim()}.
*
*
* @param trimOnReset Whether memory is freed when the allocator is reset. Should be true unless
* the allocator will be re-used by multiple player instances.
* @param individualAllocationSize The length of each individual {@link Allocation}.
* @param individualAllocationSize The length of each individual {@link Allocation}.
* @param initialAllocationCount The number of allocations to create up front.
* @param initialAllocationCount The number of allocations to create up front.
*/
*/
public
DefaultAllocator
(
int
individualAllocationSize
,
int
initialAllocationCount
)
{
public
DefaultAllocator
(
boolean
trimOnReset
,
int
individualAllocationSize
,
int
initialAllocationCount
)
{
Assertions
.
checkArgument
(
individualAllocationSize
>
0
);
Assertions
.
checkArgument
(
individualAllocationSize
>
0
);
Assertions
.
checkArgument
(
initialAllocationCount
>=
0
);
Assertions
.
checkArgument
(
initialAllocationCount
>=
0
);
this
.
trimOnReset
=
trimOnReset
;
this
.
individualAllocationSize
=
individualAllocationSize
;
this
.
individualAllocationSize
=
individualAllocationSize
;
this
.
availableCount
=
initialAllocationCount
;
this
.
availableCount
=
initialAllocationCount
;
this
.
availableAllocations
=
new
Allocation
[
initialAllocationCount
+
AVAILABLE_EXTRA_CAPACITY
];
this
.
availableAllocations
=
new
Allocation
[
initialAllocationCount
+
AVAILABLE_EXTRA_CAPACITY
];
...
@@ -70,6 +77,12 @@ public final class DefaultAllocator implements Allocator {
...
@@ -70,6 +77,12 @@ public final class DefaultAllocator implements Allocator {
singleAllocationReleaseHolder
=
new
Allocation
[
1
];
singleAllocationReleaseHolder
=
new
Allocation
[
1
];
}
}
public
synchronized
void
reset
()
{
if
(
trimOnReset
)
{
setTargetBufferSize
(
0
);
}
}
public
synchronized
void
setTargetBufferSize
(
int
targetBufferSize
)
{
public
synchronized
void
setTargetBufferSize
(
int
targetBufferSize
)
{
boolean
targetBufferSizeReduced
=
targetBufferSize
<
this
.
targetBufferSize
;
boolean
targetBufferSizeReduced
=
targetBufferSize
<
this
.
targetBufferSize
;
this
.
targetBufferSize
=
targetBufferSize
;
this
.
targetBufferSize
=
targetBufferSize
;
...
...
library/src/main/java/com/google/android/exoplayer2/upstream/DefaultHttpDataSource.java
View file @
f94218a7
...
@@ -550,11 +550,18 @@ public class DefaultHttpDataSource implements HttpDataSource {
...
@@ -550,11 +550,18 @@ public class DefaultHttpDataSource implements HttpDataSource {
if
(
readLength
==
0
)
{
if
(
readLength
==
0
)
{
return
0
;
return
0
;
}
}
if
(
bytesToRead
!=
C
.
LENGTH_UNSET
)
{
long
bytesRemaining
=
bytesToRead
-
bytesRead
;
if
(
bytesRemaining
==
0
)
{
return
C
.
RESULT_END_OF_INPUT
;
}
readLength
=
(
int
)
Math
.
min
(
readLength
,
bytesRemaining
);
}
int
read
=
inputStream
.
read
(
buffer
,
offset
,
readLength
);
int
read
=
inputStream
.
read
(
buffer
,
offset
,
readLength
);
if
(
read
==
-
1
)
{
if
(
read
==
-
1
)
{
if
(
bytesToRead
!=
C
.
LENGTH_UNSET
&&
bytesToRead
!=
bytesRead
)
{
if
(
bytesToRead
!=
C
.
LENGTH_UNSET
)
{
//
The server closed the connection having not sent
sufficient data.
//
End of stream reached having not read
sufficient data.
throw
new
EOFException
();
throw
new
EOFException
();
}
}
return
C
.
RESULT_END_OF_INPUT
;
return
C
.
RESULT_END_OF_INPUT
;
...
...
library/src/main/java/com/google/android/exoplayer2/upstream/FileDataSource.java
View file @
f94218a7
...
@@ -80,7 +80,9 @@ public final class FileDataSource implements DataSource {
...
@@ -80,7 +80,9 @@ public final class FileDataSource implements DataSource {
@Override
@Override
public
int
read
(
byte
[]
buffer
,
int
offset
,
int
readLength
)
throws
FileDataSourceException
{
public
int
read
(
byte
[]
buffer
,
int
offset
,
int
readLength
)
throws
FileDataSourceException
{
if
(
bytesRemaining
==
0
)
{
if
(
readLength
==
0
)
{
return
0
;
}
else
if
(
bytesRemaining
==
0
)
{
return
C
.
RESULT_END_OF_INPUT
;
return
C
.
RESULT_END_OF_INPUT
;
}
else
{
}
else
{
int
bytesRead
;
int
bytesRead
;
...
...
library/src/main/java/com/google/android/exoplayer2/upstream/RawResourceDataSource.java
View file @
f94218a7
...
@@ -132,29 +132,35 @@ public final class RawResourceDataSource implements DataSource {
...
@@ -132,29 +132,35 @@ public final class RawResourceDataSource implements DataSource {
@Override
@Override
public
int
read
(
byte
[]
buffer
,
int
offset
,
int
readLength
)
throws
RawResourceDataSourceException
{
public
int
read
(
byte
[]
buffer
,
int
offset
,
int
readLength
)
throws
RawResourceDataSourceException
{
if
(
bytesRemaining
==
0
)
{
if
(
readLength
==
0
)
{
return
0
;
}
else
if
(
bytesRemaining
==
0
)
{
return
C
.
RESULT_END_OF_INPUT
;
return
C
.
RESULT_END_OF_INPUT
;
}
else
{
}
int
bytesRead
;
try
{
int
bytesToRead
=
bytesRemaining
==
C
.
LENGTH_UNSET
?
readLength
:
(
int
)
Math
.
min
(
bytesRemaining
,
readLength
);
bytesRead
=
inputStream
.
read
(
buffer
,
offset
,
bytesToRead
);
}
catch
(
IOException
e
)
{
throw
new
RawResourceDataSourceException
(
e
);
}
if
(
bytesRead
>
0
)
{
int
bytesRead
;
if
(
bytesRemaining
!=
C
.
LENGTH_UNSET
)
{
try
{
bytesRemaining
-=
bytesRead
;
int
bytesToRead
=
bytesRemaining
==
C
.
LENGTH_UNSET
?
readLength
}
:
(
int
)
Math
.
min
(
bytesRemaining
,
readLength
);
if
(
listener
!=
null
)
{
bytesRead
=
inputStream
.
read
(
buffer
,
offset
,
bytesToRead
);
listener
.
onBytesTransferred
(
this
,
bytesRead
);
}
catch
(
IOException
e
)
{
}
throw
new
RawResourceDataSourceException
(
e
);
}
}
return
bytesRead
;
if
(
bytesRead
==
-
1
)
{
if
(
bytesRemaining
!=
C
.
LENGTH_UNSET
)
{
// End of stream reached having not read sufficient data.
throw
new
RawResourceDataSourceException
(
new
EOFException
());
}
return
C
.
RESULT_END_OF_INPUT
;
}
if
(
bytesRemaining
!=
C
.
LENGTH_UNSET
)
{
bytesRemaining
-=
bytesRead
;
}
if
(
listener
!=
null
)
{
listener
.
onBytesTransferred
(
this
,
bytesRead
);
}
}
return
bytesRead
;
}
}
@Override
@Override
...
...
library/src/main/java/com/google/android/exoplayer2/upstream/UdpDataSource.java
View file @
f94218a7
...
@@ -129,6 +129,10 @@ public final class UdpDataSource implements DataSource {
...
@@ -129,6 +129,10 @@ public final class UdpDataSource implements DataSource {
@Override
@Override
public
int
read
(
byte
[]
buffer
,
int
offset
,
int
readLength
)
throws
UdpDataSourceException
{
public
int
read
(
byte
[]
buffer
,
int
offset
,
int
readLength
)
throws
UdpDataSourceException
{
if
(
readLength
==
0
)
{
return
0
;
}
if
(
packetRemaining
==
0
)
{
if
(
packetRemaining
==
0
)
{
// We've read all of the data from the current packet. Get another.
// We've read all of the data from the current packet. Get another.
try
{
try
{
...
@@ -136,7 +140,6 @@ public final class UdpDataSource implements DataSource {
...
@@ -136,7 +140,6 @@ public final class UdpDataSource implements DataSource {
}
catch
(
IOException
e
)
{
}
catch
(
IOException
e
)
{
throw
new
UdpDataSourceException
(
e
);
throw
new
UdpDataSourceException
(
e
);
}
}
packetRemaining
=
packet
.
getLength
();
packetRemaining
=
packet
.
getLength
();
if
(
listener
!=
null
)
{
if
(
listener
!=
null
)
{
listener
.
onBytesTransferred
(
this
,
packetRemaining
);
listener
.
onBytesTransferred
(
this
,
packetRemaining
);
...
...
library/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSource.java
View file @
f94218a7
...
@@ -194,12 +194,15 @@ public final class CacheDataSource implements DataSource {
...
@@ -194,12 +194,15 @@ public final class CacheDataSource implements DataSource {
}
}
@Override
@Override
public
int
read
(
byte
[]
buffer
,
int
offset
,
int
max
)
throws
IOException
{
public
int
read
(
byte
[]
buffer
,
int
offset
,
int
readLength
)
throws
IOException
{
if
(
readLength
==
0
)
{
return
0
;
}
if
(
bytesRemaining
==
0
)
{
if
(
bytesRemaining
==
0
)
{
return
C
.
RESULT_END_OF_INPUT
;
return
C
.
RESULT_END_OF_INPUT
;
}
}
try
{
try
{
int
bytesRead
=
currentDataSource
.
read
(
buffer
,
offset
,
max
);
int
bytesRead
=
currentDataSource
.
read
(
buffer
,
offset
,
readLength
);
if
(
bytesRead
>=
0
)
{
if
(
bytesRead
>=
0
)
{
if
(
currentDataSource
==
cacheReadDataSource
)
{
if
(
currentDataSource
==
cacheReadDataSource
)
{
totalCachedBytesRead
+=
bytesRead
;
totalCachedBytesRead
+=
bytesRead
;
...
@@ -218,7 +221,7 @@ public final class CacheDataSource implements DataSource {
...
@@ -218,7 +221,7 @@ public final class CacheDataSource implements DataSource {
closeCurrentSource
();
closeCurrentSource
();
if
(
bytesRemaining
>
0
||
bytesRemaining
==
C
.
LENGTH_UNSET
)
{
if
(
bytesRemaining
>
0
||
bytesRemaining
==
C
.
LENGTH_UNSET
)
{
if
(
openNextSource
(
false
))
{
if
(
openNextSource
(
false
))
{
return
read
(
buffer
,
offset
,
max
);
return
read
(
buffer
,
offset
,
readLength
);
}
}
}
}
}
}
...
...
library/src/main/res/layout/exo_simple_player_view.xml
View file @
f94218a7
...
@@ -22,17 +22,17 @@
...
@@ -22,17 +22,17 @@
android:layout_height=
"match_parent"
android:layout_height=
"match_parent"
android:layout_gravity=
"center"
>
android:layout_gravity=
"center"
>
<View
android:id=
"@+id/shutter"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:background=
"@android:color/black"
/>
<com.google.android.exoplayer2.ui.SubtitleView
android:id=
"@+id/subtitles"
<com.google.android.exoplayer2.ui.SubtitleView
android:id=
"@+id/subtitles"
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
/>
android:layout_height=
"match_parent"
/>
</com.google.android.exoplayer2.ui.AspectRatioFrameLayout>
</com.google.android.exoplayer2.ui.AspectRatioFrameLayout>
<View
android:id=
"@+id/shutter"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:background=
"@android:color/black"
/>
<com.google.android.exoplayer2.ui.PlaybackControlView
android:id=
"@+id/control"
<com.google.android.exoplayer2.ui.PlaybackControlView
android:id=
"@+id/control"
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
/>
android:layout_height=
"match_parent"
/>
...
...
library/src/main/res/values/attrs.xml
View file @
f94218a7
...
@@ -14,8 +14,21 @@
...
@@ -14,8 +14,21 @@
limitations under the License.
limitations under the License.
-->
-->
<resources>
<resources>
<attr
name=
"resize_mode"
format=
"enum"
>
<enum
name=
"fit"
value=
"0"
/>
<enum
name=
"fixed_width"
value=
"1"
/>
<enum
name=
"fixed_height"
value=
"2"
/>
</attr>
<declare-styleable
name=
"SimpleExoPlayerView"
>
<declare-styleable
name=
"SimpleExoPlayerView"
>
<attr
name=
"use_controller"
format=
"boolean"
/>
<attr
name=
"use_controller"
format=
"boolean"
/>
<attr
name=
"use_texture_view"
format=
"boolean"
/>
<attr
name=
"use_texture_view"
format=
"boolean"
/>
<attr
name=
"resize_mode"
/>
</declare-styleable>
</declare-styleable>
<declare-styleable
name=
"AspectRatioFrameLayout"
>
<attr
name=
"resize_mode"
/>
</declare-styleable>
</resources>
</resources>
playbacktests/src/main/AndroidManifest.xml
View file @
f94218a7
...
@@ -17,8 +17,8 @@
...
@@ -17,8 +17,8 @@
<manifest
xmlns:android=
"http://schemas.android.com/apk/res/android"
<manifest
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:tools=
"http://schemas.android.com/tools"
xmlns:tools=
"http://schemas.android.com/tools"
package=
"com.google.android.exoplayer2.playbacktests"
package=
"com.google.android.exoplayer2.playbacktests"
android:versionCode=
"200
1
"
android:versionCode=
"200
2
"
android:versionName=
"2.0.
1
"
>
android:versionName=
"2.0.
2
"
>
<uses-permission
android:name=
"android.permission.INTERNET"
/>
<uses-permission
android:name=
"android.permission.INTERNET"
/>
<uses-permission
android:name=
"android.permission.WAKE_LOCK"
/>
<uses-permission
android:name=
"android.permission.WAKE_LOCK"
/>
...
...
playbacktests/src/main/java/com/google/android/exoplayer2/playbacktests/gts/DashTest.java
View file @
f94218a7
...
@@ -19,6 +19,8 @@ import android.annotation.TargetApi;
...
@@ -19,6 +19,8 @@ import android.annotation.TargetApi;
import
android.media.MediaDrm
;
import
android.media.MediaDrm
;
import
android.media.UnsupportedSchemeException
;
import
android.media.UnsupportedSchemeException
;
import
android.net.Uri
;
import
android.net.Uri
;
import
android.os.Handler
;
import
android.os.Looper
;
import
android.test.ActivityInstrumentationTestCase2
;
import
android.test.ActivityInstrumentationTestCase2
;
import
android.util.Log
;
import
android.util.Log
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.C
;
...
@@ -801,7 +803,7 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
...
@@ -801,7 +803,7 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
private
DashTestTrackSelector
(
String
audioFormatId
,
String
[]
videoFormatIds
,
private
DashTestTrackSelector
(
String
audioFormatId
,
String
[]
videoFormatIds
,
boolean
canIncludeAdditionalVideoFormats
)
{
boolean
canIncludeAdditionalVideoFormats
)
{
super
(
n
ull
);
super
(
n
ew
Handler
(
Looper
.
getMainLooper
())
);
this
.
audioFormatId
=
audioFormatId
;
this
.
audioFormatId
=
audioFormatId
;
this
.
videoFormatIds
=
videoFormatIds
;
this
.
videoFormatIds
=
videoFormatIds
;
this
.
canIncludeAdditionalVideoFormats
=
canIncludeAdditionalVideoFormats
;
this
.
canIncludeAdditionalVideoFormats
=
canIncludeAdditionalVideoFormats
;
...
...
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