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
e2ff401e
authored
Oct 17, 2016
by
ojw28
Committed by
GitHub
Oct 17, 2016
Browse files
Options
_('Browse Files')
Download
Plain Diff
Merge pull request #1958 from google/dev-v2
Merge dev-v2 into dev-v2-id3
parents
66652f65
cecb1f5f
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
37 changed files
with
458 additions
and
287 deletions
RELEASENOTES.md
build.gradle
demo/src/main/AndroidManifest.xml
extensions/cronet/src/androidTest/java/com/google/android/exoplayer2/ext/cronet/CronetDataSourceTest.java
extensions/cronet/src/main/java/com/google/android/exoplayer2/ext/cronet/CronetDataSource.java
library/src/androidTest/java/com/google/android/exoplayer2/extractor/ts/AdtsReaderTest.java
library/src/androidTest/java/com/google/android/exoplayer2/extractor/ts/TsExtractorTest.java
library/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java
library/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java
library/src/main/java/com/google/android/exoplayer2/drm/HttpMediaDrmCallback.java
library/src/main/java/com/google/android/exoplayer2/extractor/Extractor.java
library/src/main/java/com/google/android/exoplayer2/extractor/ExtractorOutput.java
library/src/main/java/com/google/android/exoplayer2/extractor/ts/Ac3Extractor.java
library/src/main/java/com/google/android/exoplayer2/extractor/ts/Ac3Reader.java
library/src/main/java/com/google/android/exoplayer2/extractor/ts/AdtsExtractor.java
library/src/main/java/com/google/android/exoplayer2/extractor/ts/AdtsReader.java
library/src/main/java/com/google/android/exoplayer2/extractor/ts/DefaultStreamReaderFactory.java
library/src/main/java/com/google/android/exoplayer2/extractor/ts/DtsReader.java
library/src/main/java/com/google/android/exoplayer2/extractor/ts/ElementaryStreamReader.java
library/src/main/java/com/google/android/exoplayer2/extractor/ts/H262Reader.java
library/src/main/java/com/google/android/exoplayer2/extractor/ts/H264Reader.java
library/src/main/java/com/google/android/exoplayer2/extractor/ts/H265Reader.java
library/src/main/java/com/google/android/exoplayer2/extractor/ts/Id3Reader.java
library/src/main/java/com/google/android/exoplayer2/extractor/ts/MpegAudioReader.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/chunk/ChunkExtractorWrapper.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/HlsMediaPeriod.java
library/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java
library/src/main/java/com/google/android/exoplayer2/upstream/DefaultHttpDataSource.java
library/src/main/java/com/google/android/exoplayer2/util/MimeTypes.java
playbacktests/src/main/AndroidManifest.xml
testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeExtractorOutput.java
testutils/src/main/java/com/google/android/exoplayer2/testutil/TestUtil.java
RELEASENOTES.md
View file @
e2ff401e
# Release notes #
# Release notes #
### r2.0.3 ###
This release contains important bug fixes. Users of r2.0.0, r2.0.1 and r2.0.2
should proactively update to this version.
*
Fixed NullPointerException in ExtractorMediaSource
(
[
#1914
](
https://github.com/google/ExoPlayer/issues/1914
)
.
*
Fixed NullPointerException in HlsMediaPeriod
(
[
#1907
](
https://github.com/google/ExoPlayer/issues/1907
)
.
*
Fixed memory leak in PlaybackControlView
(
[
#1908
](
https://github.com/google/ExoPlayer/issues/1908
)
.
*
Fixed strict mode violation when using
SimpleExoPlayer.setVideoPlayerTextureView().
*
Fixed L3 Widevine provisioning
(
[
#1925
](
https://github.com/google/ExoPlayer/issues/1925
)
.
*
Fixed hiding of controls with use_controller="false"
(
[
#1919
](
https://github.com/google/ExoPlayer/issues/1919
)
.
*
Improvements to Cronet network stack extension.
*
Misc bug fixes.
### r2.0.2 ###
### r2.0.2 ###
*
Fixes for MergingMediaSource and sideloaded subtitles.
*
Fixes for MergingMediaSource and sideloaded subtitles.
...
@@ -88,6 +108,13 @@ some of the motivations behind ExoPlayer 2.x
...
@@ -88,6 +108,13 @@ some of the motivations behind ExoPlayer 2.x
*
Suppressed "Sending message to a Handler on a dead thread" warnings
*
Suppressed "Sending message to a Handler on a dead thread" warnings
(
[
#426
](
https://github.com/google/ExoPlayer/issues/426
)
).
(
[
#426
](
https://github.com/google/ExoPlayer/issues/426
)
).
### r1.5.12 ###
*
Improvements to Cronet network stack extension.
*
Fix bug in demo app introduced in r1.5.11 that caused L3 Widevine
provisioning requests to fail.
*
Misc bugfixes.
### r1.5.11 ###
### r1.5.11 ###
*
Cronet network stack extension.
*
Cronet network stack extension.
...
...
build.gradle
View file @
e2ff401e
...
@@ -35,7 +35,7 @@ allprojects {
...
@@ -35,7 +35,7 @@ allprojects {
releaseRepoName
=
'exoplayer'
releaseRepoName
=
'exoplayer'
releaseUserOrg
=
'google'
releaseUserOrg
=
'google'
releaseGroupId
=
'com.google.android.exoplayer'
releaseGroupId
=
'com.google.android.exoplayer'
releaseVersion
=
'r2.0.
2
'
releaseVersion
=
'r2.0.
3
'
releaseWebsite
=
'https://github.com/google/ExoPlayer'
releaseWebsite
=
'https://github.com/google/ExoPlayer'
}
}
}
}
demo/src/main/AndroidManifest.xml
View file @
e2ff401e
...
@@ -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
2
"
android:versionCode=
"200
3
"
android:versionName=
"2.0.
2
"
>
android:versionName=
"2.0.
3
"
>
<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"
/>
...
...
extensions/cronet/src/androidTest/java/com/google/android/exoplayer2/ext/cronet/CronetDataSourceTest.java
View file @
e2ff401e
This diff is collapsed.
Click to expand it.
extensions/cronet/src/main/java/com/google/android/exoplayer2/ext/cronet/CronetDataSource.java
View file @
e2ff401e
...
@@ -103,6 +103,7 @@ public class CronetDataSource extends UrlRequest.Callback implements HttpDataSou
...
@@ -103,6 +103,7 @@ public class CronetDataSource extends UrlRequest.Callback implements HttpDataSou
// Accessed by the calling thread only.
// Accessed by the calling thread only.
private
boolean
opened
;
private
boolean
opened
;
private
long
bytesToSkip
;
private
long
bytesRemaining
;
private
long
bytesRemaining
;
// Written from the calling thread only. currentUrlRequest.start() calls ensure writes are visible
// Written from the calling thread only. currentUrlRequest.start() calls ensure writes are visible
...
@@ -242,9 +243,10 @@ public class CronetDataSource extends UrlRequest.Callback implements HttpDataSou
...
@@ -242,9 +243,10 @@ public class CronetDataSource extends UrlRequest.Callback implements HttpDataSou
}
}
}
}
// TODO: Handle the case where we requested a range starting from a non-zero position and
// If we requested a range starting from a non-zero position and received a 200 rather than a
// received a 200 rather than a 206. This occurs if the server does not support partial
// 206, then the server does not support partial requests. We'll need to manually skip to the
// requests, and requires that the source skips to the requested position.
// requested position.
bytesToSkip
=
responseCode
==
200
&&
dataSpec
.
position
!=
0
?
dataSpec
.
position
:
0
;
// Calculate the content length.
// Calculate the content length.
if
(!
getIsCompressed
(
responseInfo
))
{
if
(!
getIsCompressed
(
responseInfo
))
{
...
@@ -281,7 +283,7 @@ public class CronetDataSource extends UrlRequest.Callback implements HttpDataSou
...
@@ -281,7 +283,7 @@ public class CronetDataSource extends UrlRequest.Callback implements HttpDataSou
readBuffer
=
ByteBuffer
.
allocateDirect
(
READ_BUFFER_SIZE_BYTES
);
readBuffer
=
ByteBuffer
.
allocateDirect
(
READ_BUFFER_SIZE_BYTES
);
readBuffer
.
limit
(
0
);
readBuffer
.
limit
(
0
);
}
}
if
(!
readBuffer
.
hasRemaining
())
{
while
(!
readBuffer
.
hasRemaining
())
{
// Fill readBuffer with more data from Cronet.
// Fill readBuffer with more data from Cronet.
operation
.
close
();
operation
.
close
();
readBuffer
.
clear
();
readBuffer
.
clear
();
...
@@ -301,6 +303,12 @@ public class CronetDataSource extends UrlRequest.Callback implements HttpDataSou
...
@@ -301,6 +303,12 @@ public class CronetDataSource extends UrlRequest.Callback implements HttpDataSou
}
else
{
}
else
{
// The operation didn't time out, fail or finish, and therefore data must have been read.
// The operation didn't time out, fail or finish, and therefore data must have been read.
readBuffer
.
flip
();
readBuffer
.
flip
();
Assertions
.
checkState
(
readBuffer
.
hasRemaining
());
if
(
bytesToSkip
>
0
)
{
int
bytesSkipped
=
(
int
)
Math
.
min
(
readBuffer
.
remaining
(),
bytesToSkip
);
readBuffer
.
position
(
readBuffer
.
position
()
+
bytesSkipped
);
bytesToSkip
-=
bytesSkipped
;
}
}
}
}
}
...
@@ -408,8 +416,10 @@ public class CronetDataSource extends UrlRequest.Callback implements HttpDataSou
...
@@ -408,8 +416,10 @@ public class CronetDataSource extends UrlRequest.Callback implements HttpDataSou
executor
,
cronetEngine
);
executor
,
cronetEngine
);
// Set the headers.
// Set the headers.
synchronized
(
requestProperties
)
{
synchronized
(
requestProperties
)
{
if
(
dataSpec
.
postBody
!=
null
&&
!
requestProperties
.
containsKey
(
CONTENT_TYPE
))
{
if
(
dataSpec
.
postBody
!=
null
&&
dataSpec
.
postBody
.
length
!=
0
throw
new
OpenException
(
"POST request must set Content-Type"
,
dataSpec
,
Status
.
IDLE
);
&&
!
requestProperties
.
containsKey
(
CONTENT_TYPE
))
{
throw
new
OpenException
(
"POST request with non-empty body must set Content-Type"
,
dataSpec
,
Status
.
IDLE
);
}
}
for
(
Entry
<
String
,
String
>
headerEntry
:
requestProperties
.
entrySet
())
{
for
(
Entry
<
String
,
String
>
headerEntry
:
requestProperties
.
entrySet
())
{
requestBuilder
.
addHeader
(
headerEntry
.
getKey
(),
headerEntry
.
getValue
());
requestBuilder
.
addHeader
(
headerEntry
.
getKey
(),
headerEntry
.
getValue
());
...
@@ -426,10 +436,13 @@ public class CronetDataSource extends UrlRequest.Callback implements HttpDataSou
...
@@ -426,10 +436,13 @@ public class CronetDataSource extends UrlRequest.Callback implements HttpDataSou
}
}
requestBuilder
.
addHeader
(
"Range"
,
rangeValue
.
toString
());
requestBuilder
.
addHeader
(
"Range"
,
rangeValue
.
toString
());
}
}
// Set the body.
// Set the
method and (if non-empty) the
body.
if
(
dataSpec
.
postBody
!=
null
)
{
if
(
dataSpec
.
postBody
!=
null
)
{
requestBuilder
.
setUploadDataProvider
(
new
ByteArrayUploadDataProvider
(
dataSpec
.
postBody
),
requestBuilder
.
setHttpMethod
(
"POST"
);
executor
);
if
(
dataSpec
.
postBody
.
length
!=
0
)
{
requestBuilder
.
setUploadDataProvider
(
new
ByteArrayUploadDataProvider
(
dataSpec
.
postBody
),
executor
);
}
}
}
return
requestBuilder
.
build
();
return
requestBuilder
.
build
();
}
}
...
...
library/src/androidTest/java/com/google/android/exoplayer2/extractor/ts/AdtsReaderTest.java
View file @
e2ff401e
...
@@ -16,6 +16,8 @@
...
@@ -16,6 +16,8 @@
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
ts
;
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
ts
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.extractor.ts.ElementaryStreamReader.TrackIdGenerator
;
import
com.google.android.exoplayer2.testutil.FakeExtractorOutput
;
import
com.google.android.exoplayer2.testutil.FakeTrackOutput
;
import
com.google.android.exoplayer2.testutil.FakeTrackOutput
;
import
com.google.android.exoplayer2.testutil.TestUtil
;
import
com.google.android.exoplayer2.testutil.TestUtil
;
import
com.google.android.exoplayer2.util.ParsableByteArray
;
import
com.google.android.exoplayer2.util.ParsableByteArray
;
...
@@ -66,9 +68,12 @@ public class AdtsReaderTest extends TestCase {
...
@@ -66,9 +68,12 @@ public class AdtsReaderTest extends TestCase {
@Override
@Override
protected
void
setUp
()
throws
Exception
{
protected
void
setUp
()
throws
Exception
{
adtsOutput
=
new
FakeTrackOutput
();
FakeExtractorOutput
fakeExtractorOutput
=
new
FakeExtractorOutput
();
id3Output
=
new
FakeTrackOutput
();
adtsOutput
=
fakeExtractorOutput
.
track
(
0
);
adtsReader
=
new
AdtsReader
(
adtsOutput
,
id3Output
);
id3Output
=
fakeExtractorOutput
.
track
(
1
);
adtsReader
=
new
AdtsReader
(
true
);
TrackIdGenerator
idGenerator
=
new
TrackIdGenerator
(
0
,
1
);
adtsReader
.
init
(
fakeExtractorOutput
,
idGenerator
);
data
=
new
ParsableByteArray
(
TEST_DATA
);
data
=
new
ParsableByteArray
(
TEST_DATA
);
firstFeed
=
true
;
firstFeed
=
true
;
}
}
...
...
library/src/androidTest/java/com/google/android/exoplayer2/extractor/ts/TsExtractorTest.java
View file @
e2ff401e
...
@@ -22,6 +22,7 @@ import com.google.android.exoplayer2.extractor.ExtractorOutput;
...
@@ -22,6 +22,7 @@ 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.TimestampAdjuster
;
import
com.google.android.exoplayer2.extractor.TrackOutput
;
import
com.google.android.exoplayer2.extractor.TrackOutput
;
import
com.google.android.exoplayer2.extractor.ts.ElementaryStreamReader.EsInfo
;
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
;
import
com.google.android.exoplayer2.testutil.FakeTrackOutput
;
import
com.google.android.exoplayer2.testutil.FakeTrackOutput
;
...
@@ -72,7 +73,7 @@ public final class TsExtractorTest extends InstrumentationTestCase {
...
@@ -72,7 +73,7 @@ public final class TsExtractorTest extends InstrumentationTestCase {
public
void
testCustomPesReader
()
throws
Exception
{
public
void
testCustomPesReader
()
throws
Exception
{
CustomEsReaderFactory
factory
=
new
CustomEsReaderFactory
();
CustomEsReaderFactory
factory
=
new
CustomEsReaderFactory
();
TsExtractor
tsExtractor
=
new
TsExtractor
(
new
TimestampAdjuster
(
0
),
factory
);
TsExtractor
tsExtractor
=
new
TsExtractor
(
new
TimestampAdjuster
(
0
),
factory
,
false
);
FakeExtractorInput
input
=
new
FakeExtractorInput
.
Builder
()
FakeExtractorInput
input
=
new
FakeExtractorInput
.
Builder
()
.
setData
(
TestUtil
.
getByteArray
(
getInstrumentation
(),
"ts/sample.ts"
))
.
setData
(
TestUtil
.
getByteArray
(
getInstrumentation
(),
"ts/sample.ts"
))
.
setSimulateIOErrors
(
false
)
.
setSimulateIOErrors
(
false
)
...
@@ -107,12 +108,12 @@ public final class TsExtractorTest extends InstrumentationTestCase {
...
@@ -107,12 +108,12 @@ public final class TsExtractorTest extends InstrumentationTestCase {
private
static
final
class
CustomEsReader
extends
ElementaryStreamReader
{
private
static
final
class
CustomEsReader
extends
ElementaryStreamReader
{
private
final
String
language
;
private
TrackOutput
output
;
public
int
packetsRead
=
0
;
public
int
packetsRead
=
0
;
public
CustomEsReader
(
TrackOutput
output
,
String
language
)
{
public
CustomEsReader
(
String
language
)
{
super
(
output
);
this
.
language
=
language
;
output
.
format
(
Format
.
createTextSampleFormat
(
"Overriding format"
,
"mime"
,
null
,
0
,
0
,
language
,
null
,
0
));
}
}
@Override
@Override
...
@@ -120,6 +121,13 @@ public final class TsExtractorTest extends InstrumentationTestCase {
...
@@ -120,6 +121,13 @@ public final class TsExtractorTest extends InstrumentationTestCase {
}
}
@Override
@Override
public
void
init
(
ExtractorOutput
extractorOutput
,
TrackIdGenerator
idGenerator
)
{
output
=
extractorOutput
.
track
(
idGenerator
.
getNextId
());
output
.
format
(
Format
.
createTextSampleFormat
(
"Overriding format"
,
"mime"
,
null
,
0
,
0
,
language
,
null
,
0
));
}
@Override
public
void
packetStarted
(
long
pesTimeUs
,
boolean
dataAlignmentIndicator
)
{
public
void
packetStarted
(
long
pesTimeUs
,
boolean
dataAlignmentIndicator
)
{
}
}
...
@@ -148,16 +156,12 @@ public final class TsExtractorTest extends InstrumentationTestCase {
...
@@ -148,16 +156,12 @@ public final class TsExtractorTest extends InstrumentationTestCase {
}
}
@Override
@Override
public
ElementaryStreamReader
onPmtEntry
(
int
pid
,
int
streamType
,
public
ElementaryStreamReader
createStreamReader
(
int
streamType
,
EsInfo
esInfo
)
{
ElementaryStreamReader
.
EsInfo
esInfo
,
ExtractorOutput
output
)
{
if
(
streamType
==
3
)
{
if
(
streamType
==
3
)
{
// We need to manually avoid a duplicate custom reader creation.
reader
=
new
CustomEsReader
(
esInfo
.
language
);
if
(
reader
==
null
)
{
reader
=
new
CustomEsReader
(
output
.
track
(
pid
),
esInfo
.
language
);
}
return
reader
;
return
reader
;
}
else
{
}
else
{
return
defaultFactory
.
onPmtEntry
(
pid
,
streamType
,
esInfo
,
output
);
return
defaultFactory
.
createStreamReader
(
streamType
,
esInfo
);
}
}
}
}
...
...
library/src/main/java/com/google/android/exoplayer2/ExoPlayerLibraryInfo.java
View file @
e2ff401e
...
@@ -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.
2
"
;
String
VERSION
=
"2.0.
3
"
;
/**
/**
* 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
2
;
int
VERSION_INT
=
200000
3
;
/**
/**
* 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/SimpleExoPlayer.java
View file @
e2ff401e
...
@@ -108,6 +108,7 @@ public final class SimpleExoPlayer implements ExoPlayer {
...
@@ -108,6 +108,7 @@ public final class SimpleExoPlayer implements ExoPlayer {
private
Format
audioFormat
;
private
Format
audioFormat
;
private
Surface
surface
;
private
Surface
surface
;
private
boolean
ownsSurface
;
private
SurfaceHolder
surfaceHolder
;
private
SurfaceHolder
surfaceHolder
;
private
TextureView
textureView
;
private
TextureView
textureView
;
private
TextRenderer
.
Output
textOutput
;
private
TextRenderer
.
Output
textOutput
;
...
@@ -206,7 +207,7 @@ public final class SimpleExoPlayer implements ExoPlayer {
...
@@ -206,7 +207,7 @@ public final class SimpleExoPlayer implements ExoPlayer {
*/
*/
public
void
setVideoSurface
(
Surface
surface
)
{
public
void
setVideoSurface
(
Surface
surface
)
{
removeSurfaceCallbacks
();
removeSurfaceCallbacks
();
setVideoSurfaceInternal
(
surface
);
setVideoSurfaceInternal
(
surface
,
false
);
}
}
/**
/**
...
@@ -219,9 +220,9 @@ public final class SimpleExoPlayer implements ExoPlayer {
...
@@ -219,9 +220,9 @@ public final class SimpleExoPlayer implements ExoPlayer {
removeSurfaceCallbacks
();
removeSurfaceCallbacks
();
this
.
surfaceHolder
=
surfaceHolder
;
this
.
surfaceHolder
=
surfaceHolder
;
if
(
surfaceHolder
==
null
)
{
if
(
surfaceHolder
==
null
)
{
setVideoSurfaceInternal
(
null
);
setVideoSurfaceInternal
(
null
,
false
);
}
else
{
}
else
{
setVideoSurfaceInternal
(
surfaceHolder
.
getSurface
());
setVideoSurfaceInternal
(
surfaceHolder
.
getSurface
()
,
false
);
surfaceHolder
.
addCallback
(
componentListener
);
surfaceHolder
.
addCallback
(
componentListener
);
}
}
}
}
...
@@ -246,13 +247,13 @@ public final class SimpleExoPlayer implements ExoPlayer {
...
@@ -246,13 +247,13 @@ public final class SimpleExoPlayer implements ExoPlayer {
removeSurfaceCallbacks
();
removeSurfaceCallbacks
();
this
.
textureView
=
textureView
;
this
.
textureView
=
textureView
;
if
(
textureView
==
null
)
{
if
(
textureView
==
null
)
{
setVideoSurfaceInternal
(
null
);
setVideoSurfaceInternal
(
null
,
true
);
}
else
{
}
else
{
if
(
textureView
.
getSurfaceTextureListener
()
!=
null
)
{
if
(
textureView
.
getSurfaceTextureListener
()
!=
null
)
{
Log
.
w
(
TAG
,
"Replacing existing SurfaceTextureListener."
);
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
)
,
true
);
textureView
.
setSurfaceTextureListener
(
componentListener
);
textureView
.
setSurfaceTextureListener
(
componentListener
);
}
}
}
}
...
@@ -477,6 +478,12 @@ public final class SimpleExoPlayer implements ExoPlayer {
...
@@ -477,6 +478,12 @@ public final class SimpleExoPlayer implements ExoPlayer {
public
void
release
()
{
public
void
release
()
{
player
.
release
();
player
.
release
();
removeSurfaceCallbacks
();
removeSurfaceCallbacks
();
if
(
surface
!=
null
)
{
if
(
ownsSurface
)
{
surface
.
release
();
}
surface
=
null
;
}
}
}
@Override
@Override
...
@@ -627,8 +634,9 @@ public final class SimpleExoPlayer implements ExoPlayer {
...
@@ -627,8 +634,9 @@ public final class SimpleExoPlayer implements ExoPlayer {
}
}
}
}
private
void
setVideoSurfaceInternal
(
Surface
surface
)
{
private
void
setVideoSurfaceInternal
(
Surface
surface
,
boolean
ownsSurface
)
{
this
.
surface
=
surface
;
// Note: We don't turn this method into a no-op if the surface is being replaced with itself
// so as to ensure onRenderedFirstFrame callbacks are still called in this case.
ExoPlayerMessage
[]
messages
=
new
ExoPlayerMessage
[
videoRendererCount
];
ExoPlayerMessage
[]
messages
=
new
ExoPlayerMessage
[
videoRendererCount
];
int
count
=
0
;
int
count
=
0
;
for
(
Renderer
renderer
:
renderers
)
{
for
(
Renderer
renderer
:
renderers
)
{
...
@@ -636,12 +644,18 @@ public final class SimpleExoPlayer implements ExoPlayer {
...
@@ -636,12 +644,18 @@ public final class SimpleExoPlayer implements ExoPlayer {
messages
[
count
++]
=
new
ExoPlayerMessage
(
renderer
,
C
.
MSG_SET_SURFACE
,
surface
);
messages
[
count
++]
=
new
ExoPlayerMessage
(
renderer
,
C
.
MSG_SET_SURFACE
,
surface
);
}
}
}
}
if
(
surface
==
null
)
{
if
(
this
.
surface
!=
null
&&
this
.
surface
!=
surface
)
{
// Block to ensure that the surface is not accessed after the method returns.
// If we created this surface, we are responsible for releasing it.
if
(
this
.
ownsSurface
)
{
this
.
surface
.
release
();
}
// We're replacing a surface. Block to ensure that it's not accessed after the method returns.
player
.
blockingSendMessages
(
messages
);
player
.
blockingSendMessages
(
messages
);
}
else
{
}
else
{
player
.
sendMessages
(
messages
);
player
.
sendMessages
(
messages
);
}
}
this
.
surface
=
surface
;
this
.
ownsSurface
=
ownsSurface
;
}
}
private
final
class
ComponentListener
implements
VideoRendererEventListener
,
private
final
class
ComponentListener
implements
VideoRendererEventListener
,
...
@@ -790,7 +804,7 @@ public final class SimpleExoPlayer implements ExoPlayer {
...
@@ -790,7 +804,7 @@ public final class SimpleExoPlayer implements ExoPlayer {
@Override
@Override
public
void
surfaceCreated
(
SurfaceHolder
holder
)
{
public
void
surfaceCreated
(
SurfaceHolder
holder
)
{
setVideoSurfaceInternal
(
holder
.
getSurface
());
setVideoSurfaceInternal
(
holder
.
getSurface
()
,
false
);
}
}
@Override
@Override
...
@@ -800,14 +814,14 @@ public final class SimpleExoPlayer implements ExoPlayer {
...
@@ -800,14 +814,14 @@ public final class SimpleExoPlayer implements ExoPlayer {
@Override
@Override
public
void
surfaceDestroyed
(
SurfaceHolder
holder
)
{
public
void
surfaceDestroyed
(
SurfaceHolder
holder
)
{
setVideoSurfaceInternal
(
null
);
setVideoSurfaceInternal
(
null
,
false
);
}
}
// TextureView.SurfaceTextureListener implementation
// TextureView.SurfaceTextureListener implementation
@Override
@Override
public
void
onSurfaceTextureAvailable
(
SurfaceTexture
surfaceTexture
,
int
width
,
int
height
)
{
public
void
onSurfaceTextureAvailable
(
SurfaceTexture
surfaceTexture
,
int
width
,
int
height
)
{
setVideoSurfaceInternal
(
new
Surface
(
surfaceTexture
));
setVideoSurfaceInternal
(
new
Surface
(
surfaceTexture
)
,
true
);
}
}
@Override
@Override
...
@@ -817,7 +831,7 @@ public final class SimpleExoPlayer implements ExoPlayer {
...
@@ -817,7 +831,7 @@ public final class SimpleExoPlayer implements ExoPlayer {
@Override
@Override
public
boolean
onSurfaceTextureDestroyed
(
SurfaceTexture
surfaceTexture
)
{
public
boolean
onSurfaceTextureDestroyed
(
SurfaceTexture
surfaceTexture
)
{
setVideoSurface
(
null
);
setVideoSurface
Internal
(
null
,
true
);
return
true
;
return
true
;
}
}
...
...
library/src/main/java/com/google/android/exoplayer2/drm/HttpMediaDrmCallback.java
View file @
e2ff401e
...
@@ -71,7 +71,7 @@ public final class HttpMediaDrmCallback implements MediaDrmCallback {
...
@@ -71,7 +71,7 @@ public final class HttpMediaDrmCallback implements MediaDrmCallback {
@Override
@Override
public
byte
[]
executeProvisionRequest
(
UUID
uuid
,
ProvisionRequest
request
)
throws
IOException
{
public
byte
[]
executeProvisionRequest
(
UUID
uuid
,
ProvisionRequest
request
)
throws
IOException
{
String
url
=
request
.
getDefaultUrl
()
+
"&signedRequest="
+
new
String
(
request
.
getData
());
String
url
=
request
.
getDefaultUrl
()
+
"&signedRequest="
+
new
String
(
request
.
getData
());
return
executePost
(
url
,
n
ull
,
null
);
return
executePost
(
url
,
n
ew
byte
[
0
]
,
null
);
}
}
@Override
@Override
...
@@ -81,6 +81,7 @@ public final class HttpMediaDrmCallback implements MediaDrmCallback {
...
@@ -81,6 +81,7 @@ public final class HttpMediaDrmCallback implements MediaDrmCallback {
url
=
defaultUrl
;
url
=
defaultUrl
;
}
}
Map
<
String
,
String
>
requestProperties
=
new
HashMap
<>();
Map
<
String
,
String
>
requestProperties
=
new
HashMap
<>();
requestProperties
.
put
(
"Content-Type"
,
"application/octet-stream"
);
if
(
C
.
PLAYREADY_UUID
.
equals
(
uuid
))
{
if
(
C
.
PLAYREADY_UUID
.
equals
(
uuid
))
{
requestProperties
.
putAll
(
PLAYREADY_KEY_REQUEST_PROPERTIES
);
requestProperties
.
putAll
(
PLAYREADY_KEY_REQUEST_PROPERTIES
);
}
}
...
@@ -93,8 +94,6 @@ public final class HttpMediaDrmCallback implements MediaDrmCallback {
...
@@ -93,8 +94,6 @@ public final class HttpMediaDrmCallback implements MediaDrmCallback {
private
byte
[]
executePost
(
String
url
,
byte
[]
data
,
Map
<
String
,
String
>
requestProperties
)
private
byte
[]
executePost
(
String
url
,
byte
[]
data
,
Map
<
String
,
String
>
requestProperties
)
throws
IOException
{
throws
IOException
{
HttpDataSource
dataSource
=
dataSourceFactory
.
createDataSource
();
HttpDataSource
dataSource
=
dataSourceFactory
.
createDataSource
();
// Note: This will be overridden by a Content-Type in requestProperties, if one is set.
dataSource
.
setRequestProperty
(
"Content-Type"
,
"application/octet-stream"
);
if
(
requestProperties
!=
null
)
{
if
(
requestProperties
!=
null
)
{
for
(
Map
.
Entry
<
String
,
String
>
requestProperty
:
requestProperties
.
entrySet
())
{
for
(
Map
.
Entry
<
String
,
String
>
requestProperty
:
requestProperties
.
entrySet
())
{
dataSource
.
setRequestProperty
(
requestProperty
.
getKey
(),
requestProperty
.
getValue
());
dataSource
.
setRequestProperty
(
requestProperty
.
getKey
(),
requestProperty
.
getValue
());
...
...
library/src/main/java/com/google/android/exoplayer2/extractor/Extractor.java
View file @
e2ff401e
...
@@ -56,7 +56,7 @@ public interface Extractor {
...
@@ -56,7 +56,7 @@ public interface Extractor {
boolean
sniff
(
ExtractorInput
input
)
throws
IOException
,
InterruptedException
;
boolean
sniff
(
ExtractorInput
input
)
throws
IOException
,
InterruptedException
;
/**
/**
* Initializes the extractor with an {@link ExtractorOutput}.
* Initializes the extractor with an {@link ExtractorOutput}.
Called at most once.
*
*
* @param output An {@link ExtractorOutput} to receive extracted data.
* @param output An {@link ExtractorOutput} to receive extracted data.
*/
*/
...
...
library/src/main/java/com/google/android/exoplayer2/extractor/ExtractorOutput.java
View file @
e2ff401e
...
@@ -21,18 +21,19 @@ package com.google.android.exoplayer2.extractor;
...
@@ -21,18 +21,19 @@ package com.google.android.exoplayer2.extractor;
public
interface
ExtractorOutput
{
public
interface
ExtractorOutput
{
/**
/**
* Called
when the {@link Extractor} identifies the existence of a track in the stream
.
* Called
by the {@link Extractor} to get the {@link TrackOutput} for a specific track
.
* <p>
* <p>
* Returns a {@link TrackOutput} that will receive track level data belonging to the track.
* The same {@link TrackOutput} is returned if multiple calls are made with the same
* {@code trackId}.
*
*
* @param trackId A
unique
track identifier.
* @param trackId A track identifier.
* @return The {@link TrackOutput}
that should receive track level data belonging to the track
.
* @return The {@link TrackOutput}
for the given track identifier
.
*/
*/
TrackOutput
track
(
int
trackId
);
TrackOutput
track
(
int
trackId
);
/**
/**
* Called when all tracks have been identified, meaning
that {@link #track(int)} will not
be
* Called when all tracks have been identified, meaning
no new {@code trackId} values will
be
*
called again
.
*
passed to {@link #track(int)}
.
*/
*/
void
endTracks
();
void
endTracks
();
...
...
library/src/main/java/com/google/android/exoplayer2/extractor/ts/Ac3Extractor.java
View file @
e2ff401e
...
@@ -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.ts.ElementaryStreamReader.TrackIdGenerator
;
import
com.google.android.exoplayer2.util.ParsableByteArray
;
import
com.google.android.exoplayer2.util.ParsableByteArray
;
import
com.google.android.exoplayer2.util.Util
;
import
com.google.android.exoplayer2.util.Util
;
...
@@ -117,7 +118,8 @@ public final class Ac3Extractor implements Extractor {
...
@@ -117,7 +118,8 @@ public final class Ac3Extractor implements Extractor {
@Override
@Override
public
void
init
(
ExtractorOutput
output
)
{
public
void
init
(
ExtractorOutput
output
)
{
reader
=
new
Ac3Reader
(
output
.
track
(
0
));
// TODO: Add support for embedded ID3.
reader
=
new
Ac3Reader
();
// TODO: Add support for embedded ID3.
reader
.
init
(
output
,
new
TrackIdGenerator
(
0
,
1
));
output
.
endTracks
();
output
.
endTracks
();
output
.
seekMap
(
new
SeekMap
.
Unseekable
(
C
.
TIME_UNSET
));
output
.
seekMap
(
new
SeekMap
.
Unseekable
(
C
.
TIME_UNSET
));
}
}
...
...
library/src/main/java/com/google/android/exoplayer2/extractor/ts/Ac3Reader.java
View file @
e2ff401e
...
@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.extractor.ts;
...
@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.extractor.ts;
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.audio.Ac3Util
;
import
com.google.android.exoplayer2.audio.Ac3Util
;
import
com.google.android.exoplayer2.extractor.ExtractorOutput
;
import
com.google.android.exoplayer2.extractor.TrackOutput
;
import
com.google.android.exoplayer2.extractor.TrackOutput
;
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
;
...
@@ -37,6 +38,8 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
...
@@ -37,6 +38,8 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
private
final
ParsableByteArray
headerScratchBytes
;
private
final
ParsableByteArray
headerScratchBytes
;
private
final
String
language
;
private
final
String
language
;
private
TrackOutput
output
;
private
int
state
;
private
int
state
;
private
int
bytesRead
;
private
int
bytesRead
;
...
@@ -54,21 +57,17 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
...
@@ -54,21 +57,17 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
/**
/**
* Constructs a new reader for (E-)AC-3 elementary streams.
* Constructs a new reader for (E-)AC-3 elementary streams.
*
* @param output Track output for extracted samples.
*/
*/
public
Ac3Reader
(
TrackOutput
output
)
{
public
Ac3Reader
()
{
this
(
output
,
null
);
this
(
null
);
}
}
/**
/**
* Constructs a new reader for (E-)AC-3 elementary streams.
* Constructs a new reader for (E-)AC-3 elementary streams.
*
*
* @param output Track output for extracted samples.
* @param language Track language.
* @param language Track language.
*/
*/
public
Ac3Reader
(
TrackOutput
output
,
String
language
)
{
public
Ac3Reader
(
String
language
)
{
super
(
output
);
headerScratchBits
=
new
ParsableBitArray
(
new
byte
[
HEADER_SIZE
]);
headerScratchBits
=
new
ParsableBitArray
(
new
byte
[
HEADER_SIZE
]);
headerScratchBytes
=
new
ParsableByteArray
(
headerScratchBits
.
data
);
headerScratchBytes
=
new
ParsableByteArray
(
headerScratchBits
.
data
);
state
=
STATE_FINDING_SYNC
;
state
=
STATE_FINDING_SYNC
;
...
@@ -83,6 +82,11 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
...
@@ -83,6 +82,11 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
}
}
@Override
@Override
public
void
init
(
ExtractorOutput
extractorOutput
,
TrackIdGenerator
generator
)
{
output
=
extractorOutput
.
track
(
generator
.
getNextId
());
}
@Override
public
void
packetStarted
(
long
pesTimeUs
,
boolean
dataAlignmentIndicator
)
{
public
void
packetStarted
(
long
pesTimeUs
,
boolean
dataAlignmentIndicator
)
{
timeUs
=
pesTimeUs
;
timeUs
=
pesTimeUs
;
}
}
...
...
library/src/main/java/com/google/android/exoplayer2/extractor/ts/AdtsExtractor.java
View file @
e2ff401e
...
@@ -22,6 +22,7 @@ import com.google.android.exoplayer2.extractor.ExtractorOutput;
...
@@ -22,6 +22,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.ts.ElementaryStreamReader.TrackIdGenerator
;
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
com.google.android.exoplayer2.util.Util
;
import
com.google.android.exoplayer2.util.Util
;
...
@@ -126,7 +127,8 @@ public final class AdtsExtractor implements Extractor {
...
@@ -126,7 +127,8 @@ public final class AdtsExtractor implements Extractor {
@Override
@Override
public
void
init
(
ExtractorOutput
output
)
{
public
void
init
(
ExtractorOutput
output
)
{
reader
=
new
AdtsReader
(
output
.
track
(
0
),
output
.
track
(
1
));
reader
=
new
AdtsReader
(
true
);
reader
.
init
(
output
,
new
TrackIdGenerator
(
0
,
1
));
output
.
endTracks
();
output
.
endTracks
();
output
.
seekMap
(
new
SeekMap
.
Unseekable
(
C
.
TIME_UNSET
));
output
.
seekMap
(
new
SeekMap
.
Unseekable
(
C
.
TIME_UNSET
));
}
}
...
...
library/src/main/java/com/google/android/exoplayer2/extractor/ts/AdtsReader.java
View file @
e2ff401e
...
@@ -19,6 +19,8 @@ import android.util.Log;
...
@@ -19,6 +19,8 @@ import android.util.Log;
import
android.util.Pair
;
import
android.util.Pair
;
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.DummyTrackOutput
;
import
com.google.android.exoplayer2.extractor.ExtractorOutput
;
import
com.google.android.exoplayer2.extractor.TrackOutput
;
import
com.google.android.exoplayer2.extractor.TrackOutput
;
import
com.google.android.exoplayer2.util.CodecSpecificDataUtil
;
import
com.google.android.exoplayer2.util.CodecSpecificDataUtil
;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
com.google.android.exoplayer2.util.MimeTypes
;
...
@@ -53,11 +55,14 @@ import java.util.Collections;
...
@@ -53,11 +55,14 @@ import java.util.Collections;
private
static
final
int
ID3_SIZE_OFFSET
=
6
;
private
static
final
int
ID3_SIZE_OFFSET
=
6
;
private
static
final
byte
[]
ID3_IDENTIFIER
=
{
'I'
,
'D'
,
'3'
};
private
static
final
byte
[]
ID3_IDENTIFIER
=
{
'I'
,
'D'
,
'3'
};
private
final
boolean
exposeId3
;
private
final
ParsableBitArray
adtsScratch
;
private
final
ParsableBitArray
adtsScratch
;
private
final
ParsableByteArray
id3HeaderBuffer
;
private
final
ParsableByteArray
id3HeaderBuffer
;
private
final
TrackOutput
id3Output
;
private
final
String
language
;
private
final
String
language
;
private
TrackOutput
output
;
private
TrackOutput
id3Output
;
private
int
state
;
private
int
state
;
private
int
bytesRead
;
private
int
bytesRead
;
...
@@ -77,26 +82,21 @@ import java.util.Collections;
...
@@ -77,26 +82,21 @@ import java.util.Collections;
private
long
currentSampleDuration
;
private
long
currentSampleDuration
;
/**
/**
* @param output A {@link TrackOutput} to which AAC samples should be written.
* @param exposeId3 True if the reader should expose ID3 information.
* @param id3Output A {@link TrackOutput} to which ID3 samples should be written.
*/
*/
public
AdtsReader
(
TrackOutput
output
,
TrackOutput
id3Output
)
{
public
AdtsReader
(
boolean
exposeId3
)
{
this
(
output
,
id3Output
,
null
);
this
(
exposeId3
,
null
);
}
}
/**
/**
* @param output A {@link TrackOutput} to which AAC samples should be written.
* @param exposeId3 True if the reader should expose ID3 information.
* @param id3Output A {@link TrackOutput} to which ID3 samples should be written.
* @param language Track language.
* @param language Track language.
*/
*/
public
AdtsReader
(
TrackOutput
output
,
TrackOutput
id3Output
,
String
language
)
{
public
AdtsReader
(
boolean
exposeId3
,
String
language
)
{
super
(
output
);
this
.
id3Output
=
id3Output
;
id3Output
.
format
(
Format
.
createSampleFormat
(
null
,
MimeTypes
.
APPLICATION_ID3
,
null
,
Format
.
NO_VALUE
,
null
));
adtsScratch
=
new
ParsableBitArray
(
new
byte
[
HEADER_SIZE
+
CRC_SIZE
]);
adtsScratch
=
new
ParsableBitArray
(
new
byte
[
HEADER_SIZE
+
CRC_SIZE
]);
id3HeaderBuffer
=
new
ParsableByteArray
(
Arrays
.
copyOf
(
ID3_IDENTIFIER
,
ID3_HEADER_SIZE
));
id3HeaderBuffer
=
new
ParsableByteArray
(
Arrays
.
copyOf
(
ID3_IDENTIFIER
,
ID3_HEADER_SIZE
));
setFindingSampleState
();
setFindingSampleState
();
this
.
exposeId3
=
exposeId3
;
this
.
language
=
language
;
this
.
language
=
language
;
}
}
...
@@ -106,6 +106,18 @@ import java.util.Collections;
...
@@ -106,6 +106,18 @@ import java.util.Collections;
}
}
@Override
@Override
public
void
init
(
ExtractorOutput
extractorOutput
,
TrackIdGenerator
idGenerator
)
{
output
=
extractorOutput
.
track
(
idGenerator
.
getNextId
());
if
(
exposeId3
)
{
id3Output
=
extractorOutput
.
track
(
idGenerator
.
getNextId
());
id3Output
.
format
(
Format
.
createSampleFormat
(
null
,
MimeTypes
.
APPLICATION_ID3
,
null
,
Format
.
NO_VALUE
,
null
));
}
else
{
id3Output
=
new
DummyTrackOutput
();
}
}
@Override
public
void
packetStarted
(
long
pesTimeUs
,
boolean
dataAlignmentIndicator
)
{
public
void
packetStarted
(
long
pesTimeUs
,
boolean
dataAlignmentIndicator
)
{
timeUs
=
pesTimeUs
;
timeUs
=
pesTimeUs
;
}
}
...
...
library/src/main/java/com/google/android/exoplayer2/extractor/ts/DefaultStreamReaderFactory.java
View file @
e2ff401e
...
@@ -16,9 +16,7 @@
...
@@ -16,9 +16,7 @@
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
ts
;
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
ts
;
import
android.support.annotation.IntDef
;
import
android.support.annotation.IntDef
;
import
android.util.SparseBooleanArray
;
import
com.google.android.exoplayer2.extractor.ts.ElementaryStreamReader.EsInfo
;
import
com.google.android.exoplayer2.extractor.DummyTrackOutput
;
import
com.google.android.exoplayer2.extractor.ExtractorOutput
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.RetentionPolicy
;
...
@@ -28,80 +26,54 @@ import java.lang.annotation.RetentionPolicy;
...
@@ -28,80 +26,54 @@ import java.lang.annotation.RetentionPolicy;
public
final
class
DefaultStreamReaderFactory
implements
ElementaryStreamReader
.
Factory
{
public
final
class
DefaultStreamReaderFactory
implements
ElementaryStreamReader
.
Factory
{
/**
/**
* Flags controlling
what workarounds are enabled for elementary stream readers
.
* Flags controlling
elementary stream readers behaviour
.
*/
*/
@Retention
(
RetentionPolicy
.
SOURCE
)
@Retention
(
RetentionPolicy
.
SOURCE
)
@IntDef
(
flag
=
true
,
value
=
{
WORKAROUND_ALLOW_NON_IDR_KEYFRAMES
,
WORKAROUND
_IGNORE_AAC_STREAM
,
@IntDef
(
flag
=
true
,
value
=
{
FLAG_ALLOW_NON_IDR_KEYFRAMES
,
FLAG
_IGNORE_AAC_STREAM
,
WORKAROUND_IGNORE_H264_STREAM
,
WORKAROUND_DETECT_ACCESS_UNITS
,
WORKAROUND_MAP_BY_TYPE
})
FLAG_IGNORE_H264_STREAM
,
FLAG_DETECT_ACCESS_UNITS
})
public
@interface
Workaround
Flags
{
public
@interface
Flags
{
}
}
public
static
final
int
WORKAROUND_ALLOW_NON_IDR_KEYFRAMES
=
1
;
public
static
final
int
FLAG_ALLOW_NON_IDR_KEYFRAMES
=
1
;
public
static
final
int
WORKAROUND_IGNORE_AAC_STREAM
=
2
;
public
static
final
int
FLAG_IGNORE_AAC_STREAM
=
2
;
public
static
final
int
WORKAROUND_IGNORE_H264_STREAM
=
4
;
public
static
final
int
FLAG_IGNORE_H264_STREAM
=
4
;
public
static
final
int
WORKAROUND_DETECT_ACCESS_UNITS
=
8
;
public
static
final
int
FLAG_DETECT_ACCESS_UNITS
=
8
;
public
static
final
int
WORKAROUND_MAP_BY_TYPE
=
16
;
private
static
final
int
BASE_EMBEDDED_TRACK_ID
=
0x2000
;
// 0xFF + 1.
@Flags
private
final
int
flags
;
private
final
SparseBooleanArray
trackIds
;
@WorkaroundFlags
private
final
int
workaroundFlags
;
private
Id3Reader
id3Reader
;
private
int
nextEmbeddedTrackId
=
BASE_EMBEDDED_TRACK_ID
;
public
DefaultStreamReaderFactory
()
{
public
DefaultStreamReaderFactory
()
{
this
(
0
);
this
(
0
);
}
}
public
DefaultStreamReaderFactory
(
int
workaroundFlags
)
{
public
DefaultStreamReaderFactory
(
@Flags
int
flags
)
{
trackIds
=
new
SparseBooleanArray
();
this
.
flags
=
flags
;
this
.
workaroundFlags
=
workaroundFlags
;
}
}
@Override
@Override
public
ElementaryStreamReader
onPmtEntry
(
int
pid
,
int
streamType
,
public
ElementaryStreamReader
createStreamReader
(
int
streamType
,
EsInfo
esInfo
)
{
ElementaryStreamReader
.
EsInfo
esInfo
,
ExtractorOutput
output
)
{
if
((
workaroundFlags
&
WORKAROUND_MAP_BY_TYPE
)
!=
0
&&
id3Reader
==
null
)
{
// Setup an ID3 track regardless of whether there's a corresponding entry, in case one
// appears intermittently during playback. See b/20261500.
id3Reader
=
new
Id3Reader
(
output
.
track
(
TsExtractor
.
TS_STREAM_TYPE_ID3
));
}
int
trackId
=
(
workaroundFlags
&
WORKAROUND_MAP_BY_TYPE
)
!=
0
?
streamType
:
pid
;
if
(
trackIds
.
get
(
trackId
))
{
return
null
;
}
trackIds
.
put
(
trackId
,
true
);
switch
(
streamType
)
{
switch
(
streamType
)
{
case
TsExtractor
.
TS_STREAM_TYPE_MPA
:
case
TsExtractor
.
TS_STREAM_TYPE_MPA
:
case
TsExtractor
.
TS_STREAM_TYPE_MPA_LSF
:
case
TsExtractor
.
TS_STREAM_TYPE_MPA_LSF
:
return
new
MpegAudioReader
(
output
.
track
(
trackId
),
esInfo
.
language
);
return
new
MpegAudioReader
(
esInfo
.
language
);
case
TsExtractor
.
TS_STREAM_TYPE_AAC
:
case
TsExtractor
.
TS_STREAM_TYPE_AAC
:
return
(
workaroundFlags
&
WORKAROUND
_IGNORE_AAC_STREAM
)
!=
0
?
null
return
(
flags
&
FLAG
_IGNORE_AAC_STREAM
)
!=
0
?
null
:
new
AdtsReader
(
output
.
track
(
trackId
),
new
DummyTrackOutput
()
,
esInfo
.
language
);
:
new
AdtsReader
(
false
,
esInfo
.
language
);
case
TsExtractor
.
TS_STREAM_TYPE_AC3
:
case
TsExtractor
.
TS_STREAM_TYPE_AC3
:
case
TsExtractor
.
TS_STREAM_TYPE_E_AC3
:
case
TsExtractor
.
TS_STREAM_TYPE_E_AC3
:
return
new
Ac3Reader
(
output
.
track
(
trackId
),
esInfo
.
language
);
return
new
Ac3Reader
(
esInfo
.
language
);
case
TsExtractor
.
TS_STREAM_TYPE_DTS
:
case
TsExtractor
.
TS_STREAM_TYPE_DTS
:
case
TsExtractor
.
TS_STREAM_TYPE_HDMV_DTS
:
case
TsExtractor
.
TS_STREAM_TYPE_HDMV_DTS
:
return
new
DtsReader
(
output
.
track
(
trackId
),
esInfo
.
language
);
return
new
DtsReader
(
esInfo
.
language
);
case
TsExtractor
.
TS_STREAM_TYPE_H262
:
case
TsExtractor
.
TS_STREAM_TYPE_H262
:
return
new
H262Reader
(
output
.
track
(
trackId
)
);
return
new
H262Reader
();
case
TsExtractor
.
TS_STREAM_TYPE_H264
:
case
TsExtractor
.
TS_STREAM_TYPE_H264
:
return
(
workaroundFlags
&
WORKAROUND_IGNORE_H264_STREAM
)
!=
0
return
(
flags
&
FLAG_IGNORE_H264_STREAM
)
!=
0
?
null
?
null
:
new
H264Reader
(
output
.
track
(
trackId
),
:
new
H264Reader
((
flags
&
FLAG_ALLOW_NON_IDR_KEYFRAMES
)
!=
0
,
new
SeiReader
(
output
.
track
(
nextEmbeddedTrackId
++)),
(
flags
&
FLAG_DETECT_ACCESS_UNITS
)
!=
0
);
(
workaroundFlags
&
WORKAROUND_ALLOW_NON_IDR_KEYFRAMES
)
!=
0
,
(
workaroundFlags
&
WORKAROUND_DETECT_ACCESS_UNITS
)
!=
0
);
case
TsExtractor
.
TS_STREAM_TYPE_H265
:
case
TsExtractor
.
TS_STREAM_TYPE_H265
:
return
new
H265Reader
(
output
.
track
(
trackId
),
return
new
H265Reader
();
new
SeiReader
(
output
.
track
(
nextEmbeddedTrackId
++)));
case
TsExtractor
.
TS_STREAM_TYPE_ID3
:
case
TsExtractor
.
TS_STREAM_TYPE_ID3
:
if
((
workaroundFlags
&
WORKAROUND_MAP_BY_TYPE
)
!=
0
)
{
return
new
Id3Reader
();
return
id3Reader
;
}
else
{
return
new
Id3Reader
(
output
.
track
(
nextEmbeddedTrackId
++));
}
default
:
default
:
return
null
;
return
null
;
}
}
...
...
library/src/main/java/com/google/android/exoplayer2/extractor/ts/DtsReader.java
View file @
e2ff401e
...
@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.extractor.ts;
...
@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.extractor.ts;
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.audio.DtsUtil
;
import
com.google.android.exoplayer2.audio.DtsUtil
;
import
com.google.android.exoplayer2.extractor.ExtractorOutput
;
import
com.google.android.exoplayer2.extractor.TrackOutput
;
import
com.google.android.exoplayer2.extractor.TrackOutput
;
import
com.google.android.exoplayer2.util.ParsableByteArray
;
import
com.google.android.exoplayer2.util.ParsableByteArray
;
...
@@ -37,6 +38,8 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
...
@@ -37,6 +38,8 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
private
final
ParsableByteArray
headerScratchBytes
;
private
final
ParsableByteArray
headerScratchBytes
;
private
final
String
language
;
private
final
String
language
;
private
TrackOutput
output
;
private
int
state
;
private
int
state
;
private
int
bytesRead
;
private
int
bytesRead
;
...
@@ -54,20 +57,9 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
...
@@ -54,20 +57,9 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
/**
/**
* Constructs a new reader for DTS elementary streams.
* Constructs a new reader for DTS elementary streams.
*
*
* @param output Track output for extracted samples.
*/
public
DtsReader
(
TrackOutput
output
)
{
this
(
output
,
null
);
}
/**
* Constructs a new reader for DTS elementary streams.
*
* @param output Track output for extracted samples.
* @param language Track language.
* @param language Track language.
*/
*/
public
DtsReader
(
TrackOutput
output
,
String
language
)
{
public
DtsReader
(
String
language
)
{
super
(
output
);
headerScratchBytes
=
new
ParsableByteArray
(
new
byte
[
HEADER_SIZE
]);
headerScratchBytes
=
new
ParsableByteArray
(
new
byte
[
HEADER_SIZE
]);
headerScratchBytes
.
data
[
0
]
=
(
byte
)
((
SYNC_VALUE
>>
24
)
&
0xFF
);
headerScratchBytes
.
data
[
0
]
=
(
byte
)
((
SYNC_VALUE
>>
24
)
&
0xFF
);
headerScratchBytes
.
data
[
1
]
=
(
byte
)
((
SYNC_VALUE
>>
16
)
&
0xFF
);
headerScratchBytes
.
data
[
1
]
=
(
byte
)
((
SYNC_VALUE
>>
16
)
&
0xFF
);
...
@@ -85,6 +77,11 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
...
@@ -85,6 +77,11 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
}
}
@Override
@Override
public
void
init
(
ExtractorOutput
extractorOutput
,
TrackIdGenerator
idGenerator
)
{
output
=
extractorOutput
.
track
(
idGenerator
.
getNextId
());
}
@Override
public
void
packetStarted
(
long
pesTimeUs
,
boolean
dataAlignmentIndicator
)
{
public
void
packetStarted
(
long
pesTimeUs
,
boolean
dataAlignmentIndicator
)
{
timeUs
=
pesTimeUs
;
timeUs
=
pesTimeUs
;
}
}
...
...
library/src/main/java/com/google/android/exoplayer2/extractor/ts/ElementaryStreamReader.java
View file @
e2ff401e
...
@@ -33,17 +33,12 @@ public abstract class ElementaryStreamReader {
...
@@ -33,17 +33,12 @@ public abstract class ElementaryStreamReader {
* Returns an {@link ElementaryStreamReader} for a given PMT entry. May return null if the
* Returns an {@link ElementaryStreamReader} for a given PMT entry. May return null if the
* stream type is not supported or if the stream already has a reader assigned to it.
* stream type is not supported or if the stream already has a reader assigned to it.
*
*
* @param pid The pid for the PMT entry.
* @param streamType Stream type value as defined in the PMT entry or associated descriptors.
* @param streamType One of the {@link TsExtractor}{@code .TS_STREAM_TYPE_*} constants defining
* @param esInfo Information associated to the elementary stream provided in the PMT.
* the type of the stream.
* @param esInfo The descriptor information linked to the elementary stream.
* @param output The {@link ExtractorOutput} that provides the {@link TrackOutput}s for the
* created readers.
* @return An {@link ElementaryStreamReader} for the elementary streams carried by the provided
* @return An {@link ElementaryStreamReader} for the elementary streams carried by the provided
* pid. {@code null} if the stream is not supported or if it should be ignored.
* pid. {@code null} if the stream is not supported or if it should be ignored.
*/
*/
ElementaryStreamReader
onPmtEntry
(
int
pid
,
int
streamType
,
EsInfo
esInfo
,
ElementaryStreamReader
createStreamReader
(
int
streamType
,
EsInfo
esInfo
);
ExtractorOutput
output
);
}
}
...
@@ -70,13 +65,24 @@ public abstract class ElementaryStreamReader {
...
@@ -70,13 +65,24 @@ public abstract class ElementaryStreamReader {
}
}
protected
final
TrackOutput
output
;
/**
/**
*
@param output A {@link TrackOutput} to which samples should be written
.
*
Generates track ids for initializing {@link ElementaryStreamReader}s' {@link TrackOutput}s
.
*/
*/
protected
ElementaryStreamReader
(
TrackOutput
output
)
{
public
static
final
class
TrackIdGenerator
{
this
.
output
=
output
;
private
final
int
firstId
;
private
final
int
idIncrement
;
private
int
generatedIdCount
;
public
TrackIdGenerator
(
int
firstId
,
int
idIncrement
)
{
this
.
firstId
=
firstId
;
this
.
idIncrement
=
idIncrement
;
}
public
int
getNextId
()
{
return
firstId
+
idIncrement
*
generatedIdCount
++;
}
}
}
/**
/**
...
@@ -85,6 +91,15 @@ public abstract class ElementaryStreamReader {
...
@@ -85,6 +91,15 @@ public abstract class ElementaryStreamReader {
public
abstract
void
seek
();
public
abstract
void
seek
();
/**
/**
* Initializes the reader by providing outputs and ids for the tracks.
*
* @param extractorOutput The {@link ExtractorOutput} that receives the extracted data.
* @param idGenerator A {@link TrackIdGenerator} that generates unique track ids for the
* {@link TrackOutput}s.
*/
public
abstract
void
init
(
ExtractorOutput
extractorOutput
,
TrackIdGenerator
idGenerator
);
/**
* Called when a packet starts.
* Called when a packet starts.
*
*
* @param pesTimeUs The timestamp associated with the packet.
* @param pesTimeUs The timestamp associated with the packet.
...
...
library/src/main/java/com/google/android/exoplayer2/extractor/ts/H262Reader.java
View file @
e2ff401e
...
@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.extractor.ts;
...
@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.extractor.ts;
import
android.util.Pair
;
import
android.util.Pair
;
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.ExtractorOutput
;
import
com.google.android.exoplayer2.extractor.TrackOutput
;
import
com.google.android.exoplayer2.extractor.TrackOutput
;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
com.google.android.exoplayer2.util.NalUnitUtil
;
import
com.google.android.exoplayer2.util.NalUnitUtil
;
...
@@ -35,6 +36,8 @@ import java.util.Collections;
...
@@ -35,6 +36,8 @@ import java.util.Collections;
private
static
final
int
START_EXTENSION
=
0xB5
;
private
static
final
int
START_EXTENSION
=
0xB5
;
private
static
final
int
START_GROUP
=
0xB8
;
private
static
final
int
START_GROUP
=
0xB8
;
private
TrackOutput
output
;
// Maps (frame_rate_code - 1) indices to values, as defined in ITU-T H.262 Table 6-4.
// Maps (frame_rate_code - 1) indices to values, as defined in ITU-T H.262 Table 6-4.
private
static
final
double
[]
FRAME_RATE_VALUES
=
new
double
[]
{
private
static
final
double
[]
FRAME_RATE_VALUES
=
new
double
[]
{
24000
d
/
1001
,
24
,
25
,
30000
d
/
1001
,
30
,
50
,
60000
d
/
1001
,
60
};
24000
d
/
1001
,
24
,
25
,
30000
d
/
1001
,
30
,
50
,
60000
d
/
1001
,
60
};
...
@@ -58,8 +61,7 @@ import java.util.Collections;
...
@@ -58,8 +61,7 @@ import java.util.Collections;
private
long
framePosition
;
private
long
framePosition
;
private
long
frameTimeUs
;
private
long
frameTimeUs
;
public
H262Reader
(
TrackOutput
output
)
{
public
H262Reader
()
{
super
(
output
);
prefixFlags
=
new
boolean
[
4
];
prefixFlags
=
new
boolean
[
4
];
csdBuffer
=
new
CsdBuffer
(
128
);
csdBuffer
=
new
CsdBuffer
(
128
);
}
}
...
@@ -74,6 +76,11 @@ import java.util.Collections;
...
@@ -74,6 +76,11 @@ import java.util.Collections;
}
}
@Override
@Override
public
void
init
(
ExtractorOutput
extractorOutput
,
TrackIdGenerator
idGenerator
)
{
output
=
extractorOutput
.
track
(
idGenerator
.
getNextId
());
}
@Override
public
void
packetStarted
(
long
pesTimeUs
,
boolean
dataAlignmentIndicator
)
{
public
void
packetStarted
(
long
pesTimeUs
,
boolean
dataAlignmentIndicator
)
{
pesPtsUsAvailable
=
pesTimeUs
!=
C
.
TIME_UNSET
;
pesPtsUsAvailable
=
pesTimeUs
!=
C
.
TIME_UNSET
;
if
(
pesPtsUsAvailable
)
{
if
(
pesPtsUsAvailable
)
{
...
...
library/src/main/java/com/google/android/exoplayer2/extractor/ts/H264Reader.java
View file @
e2ff401e
...
@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.extractor.ts;
...
@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.extractor.ts;
import
android.util.SparseArray
;
import
android.util.SparseArray
;
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.ExtractorOutput
;
import
com.google.android.exoplayer2.extractor.TrackOutput
;
import
com.google.android.exoplayer2.extractor.TrackOutput
;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
com.google.android.exoplayer2.util.NalUnitUtil
;
import
com.google.android.exoplayer2.util.NalUnitUtil
;
...
@@ -37,17 +38,20 @@ import java.util.List;
...
@@ -37,17 +38,20 @@ import java.util.List;
private
static
final
int
NAL_UNIT_TYPE_SPS
=
7
;
// Sequence parameter set
private
static
final
int
NAL_UNIT_TYPE_SPS
=
7
;
// Sequence parameter set
private
static
final
int
NAL_UNIT_TYPE_PPS
=
8
;
// Picture parameter set
private
static
final
int
NAL_UNIT_TYPE_PPS
=
8
;
// Picture parameter set
// State that should not be reset on seek.
private
final
boolean
allowNonIdrKeyframes
;
private
boolean
hasOutputFormat
;
private
final
boolean
detectAccessUnits
;
// State that should be reset on seek.
private
final
SeiReader
seiReader
;
private
final
boolean
[]
prefixFlags
;
private
final
SampleReader
sampleReader
;
private
final
NalUnitTargetBuffer
sps
;
private
final
NalUnitTargetBuffer
sps
;
private
final
NalUnitTargetBuffer
pps
;
private
final
NalUnitTargetBuffer
pps
;
private
final
NalUnitTargetBuffer
sei
;
private
final
NalUnitTargetBuffer
sei
;
private
long
totalBytesWritten
;
private
long
totalBytesWritten
;
private
final
boolean
[]
prefixFlags
;
private
TrackOutput
output
;
private
SeiReader
seiReader
;
private
SampleReader
sampleReader
;
// State that should not be reset on seek.
private
boolean
hasOutputFormat
;
// Per packet state that gets reset at the start of each packet.
// Per packet state that gets reset at the start of each packet.
private
long
pesTimeUs
;
private
long
pesTimeUs
;
...
@@ -56,19 +60,15 @@ import java.util.List;
...
@@ -56,19 +60,15 @@ import java.util.List;
private
final
ParsableByteArray
seiWrapper
;
private
final
ParsableByteArray
seiWrapper
;
/**
/**
* @param output A {@link TrackOutput} to which H.264 samples should be written.
* @param seiReader A reader for CEA-608 samples in SEI NAL units.
* @param allowNonIdrKeyframes Whether to treat samples consisting of non-IDR I slices as
* @param allowNonIdrKeyframes Whether to treat samples consisting of non-IDR I slices as
* synchronization samples (key-frames).
* synchronization samples (key-frames).
* @param detectAccessUnits Whether to split the input stream into access units (samples) based on
* @param detectAccessUnits Whether to split the input stream into access units (samples) based on
* slice headers. Pass {@code false} if the stream contains access unit delimiters (AUDs).
* slice headers. Pass {@code false} if the stream contains access unit delimiters (AUDs).
*/
*/
public
H264Reader
(
TrackOutput
output
,
SeiReader
seiReader
,
boolean
allowNonIdrKeyframes
,
public
H264Reader
(
boolean
allowNonIdrKeyframes
,
boolean
detectAccessUnits
)
{
boolean
detectAccessUnits
)
{
super
(
output
);
this
.
seiReader
=
seiReader
;
prefixFlags
=
new
boolean
[
3
];
prefixFlags
=
new
boolean
[
3
];
sampleReader
=
new
SampleReader
(
output
,
allowNonIdrKeyframes
,
detectAccessUnits
);
this
.
allowNonIdrKeyframes
=
allowNonIdrKeyframes
;
this
.
detectAccessUnits
=
detectAccessUnits
;
sps
=
new
NalUnitTargetBuffer
(
NAL_UNIT_TYPE_SPS
,
128
);
sps
=
new
NalUnitTargetBuffer
(
NAL_UNIT_TYPE_SPS
,
128
);
pps
=
new
NalUnitTargetBuffer
(
NAL_UNIT_TYPE_PPS
,
128
);
pps
=
new
NalUnitTargetBuffer
(
NAL_UNIT_TYPE_PPS
,
128
);
sei
=
new
NalUnitTargetBuffer
(
NAL_UNIT_TYPE_SEI
,
128
);
sei
=
new
NalUnitTargetBuffer
(
NAL_UNIT_TYPE_SEI
,
128
);
...
@@ -86,6 +86,13 @@ import java.util.List;
...
@@ -86,6 +86,13 @@ import java.util.List;
}
}
@Override
@Override
public
void
init
(
ExtractorOutput
extractorOutput
,
TrackIdGenerator
idGenerator
)
{
output
=
extractorOutput
.
track
(
idGenerator
.
getNextId
());
sampleReader
=
new
SampleReader
(
output
,
allowNonIdrKeyframes
,
detectAccessUnits
);
seiReader
=
new
SeiReader
(
extractorOutput
.
track
(
idGenerator
.
getNextId
()));
}
@Override
public
void
packetStarted
(
long
pesTimeUs
,
boolean
dataAlignmentIndicator
)
{
public
void
packetStarted
(
long
pesTimeUs
,
boolean
dataAlignmentIndicator
)
{
this
.
pesTimeUs
=
pesTimeUs
;
this
.
pesTimeUs
=
pesTimeUs
;
}
}
...
...
library/src/main/java/com/google/android/exoplayer2/extractor/ts/H265Reader.java
View file @
e2ff401e
...
@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.extractor.ts;
...
@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.extractor.ts;
import
android.util.Log
;
import
android.util.Log
;
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.ExtractorOutput
;
import
com.google.android.exoplayer2.extractor.TrackOutput
;
import
com.google.android.exoplayer2.extractor.TrackOutput
;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
com.google.android.exoplayer2.util.NalUnitUtil
;
import
com.google.android.exoplayer2.util.NalUnitUtil
;
...
@@ -42,11 +43,13 @@ import java.util.Collections;
...
@@ -42,11 +43,13 @@ import java.util.Collections;
private
static
final
int
PREFIX_SEI_NUT
=
39
;
private
static
final
int
PREFIX_SEI_NUT
=
39
;
private
static
final
int
SUFFIX_SEI_NUT
=
40
;
private
static
final
int
SUFFIX_SEI_NUT
=
40
;
private
TrackOutput
output
;
private
SeiReader
seiReader
;
// State that should not be reset on seek.
// State that should not be reset on seek.
private
boolean
hasOutputFormat
;
private
boolean
hasOutputFormat
;
// State that should be reset on seek.
// State that should be reset on seek.
private
final
SeiReader
seiReader
;
private
final
boolean
[]
prefixFlags
;
private
final
boolean
[]
prefixFlags
;
private
final
NalUnitTargetBuffer
vps
;
private
final
NalUnitTargetBuffer
vps
;
private
final
NalUnitTargetBuffer
sps
;
private
final
NalUnitTargetBuffer
sps
;
...
@@ -62,13 +65,7 @@ import java.util.Collections;
...
@@ -62,13 +65,7 @@ import java.util.Collections;
// Scratch variables to avoid allocations.
// Scratch variables to avoid allocations.
private
final
ParsableByteArray
seiWrapper
;
private
final
ParsableByteArray
seiWrapper
;
/**
public
H265Reader
()
{
* @param output A {@link TrackOutput} to which H.265 samples should be written.
* @param seiReader A reader for CEA-608 samples in SEI NAL units.
*/
public
H265Reader
(
TrackOutput
output
,
SeiReader
seiReader
)
{
super
(
output
);
this
.
seiReader
=
seiReader
;
prefixFlags
=
new
boolean
[
3
];
prefixFlags
=
new
boolean
[
3
];
vps
=
new
NalUnitTargetBuffer
(
VPS_NUT
,
128
);
vps
=
new
NalUnitTargetBuffer
(
VPS_NUT
,
128
);
sps
=
new
NalUnitTargetBuffer
(
SPS_NUT
,
128
);
sps
=
new
NalUnitTargetBuffer
(
SPS_NUT
,
128
);
...
@@ -92,6 +89,12 @@ import java.util.Collections;
...
@@ -92,6 +89,12 @@ import java.util.Collections;
}
}
@Override
@Override
public
void
init
(
ExtractorOutput
extractorOutput
,
TrackIdGenerator
idGenerator
)
{
output
=
extractorOutput
.
track
(
idGenerator
.
getNextId
());
seiReader
=
new
SeiReader
(
extractorOutput
.
track
(
idGenerator
.
getNextId
()));
}
@Override
public
void
packetStarted
(
long
pesTimeUs
,
boolean
dataAlignmentIndicator
)
{
public
void
packetStarted
(
long
pesTimeUs
,
boolean
dataAlignmentIndicator
)
{
this
.
pesTimeUs
=
pesTimeUs
;
this
.
pesTimeUs
=
pesTimeUs
;
}
}
...
...
library/src/main/java/com/google/android/exoplayer2/extractor/ts/Id3Reader.java
View file @
e2ff401e
...
@@ -17,6 +17,7 @@ package com.google.android.exoplayer2.extractor.ts;
...
@@ -17,6 +17,7 @@ package com.google.android.exoplayer2.extractor.ts;
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.ExtractorOutput
;
import
com.google.android.exoplayer2.extractor.TrackOutput
;
import
com.google.android.exoplayer2.extractor.TrackOutput
;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
com.google.android.exoplayer2.util.ParsableByteArray
;
import
com.google.android.exoplayer2.util.ParsableByteArray
;
...
@@ -30,6 +31,8 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
...
@@ -30,6 +31,8 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
private
final
ParsableByteArray
id3Header
;
private
final
ParsableByteArray
id3Header
;
private
TrackOutput
output
;
// State that should be reset on seek.
// State that should be reset on seek.
private
boolean
writingSample
;
private
boolean
writingSample
;
...
@@ -38,10 +41,7 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
...
@@ -38,10 +41,7 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
private
int
sampleSize
;
private
int
sampleSize
;
private
int
sampleBytesRead
;
private
int
sampleBytesRead
;
public
Id3Reader
(
TrackOutput
output
)
{
public
Id3Reader
()
{
super
(
output
);
output
.
format
(
Format
.
createSampleFormat
(
null
,
MimeTypes
.
APPLICATION_ID3
,
null
,
Format
.
NO_VALUE
,
null
));
id3Header
=
new
ParsableByteArray
(
ID3_HEADER_SIZE
);
id3Header
=
new
ParsableByteArray
(
ID3_HEADER_SIZE
);
}
}
...
@@ -51,6 +51,13 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
...
@@ -51,6 +51,13 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
}
}
@Override
@Override
public
void
init
(
ExtractorOutput
extractorOutput
,
TrackIdGenerator
idGenerator
)
{
output
=
extractorOutput
.
track
(
idGenerator
.
getNextId
());
output
.
format
(
Format
.
createSampleFormat
(
null
,
MimeTypes
.
APPLICATION_ID3
,
null
,
Format
.
NO_VALUE
,
null
));
}
@Override
public
void
packetStarted
(
long
pesTimeUs
,
boolean
dataAlignmentIndicator
)
{
public
void
packetStarted
(
long
pesTimeUs
,
boolean
dataAlignmentIndicator
)
{
if
(!
dataAlignmentIndicator
)
{
if
(!
dataAlignmentIndicator
)
{
return
;
return
;
...
...
library/src/main/java/com/google/android/exoplayer2/extractor/ts/MpegAudioReader.java
View file @
e2ff401e
...
@@ -17,6 +17,7 @@ package com.google.android.exoplayer2.extractor.ts;
...
@@ -17,6 +17,7 @@ package com.google.android.exoplayer2.extractor.ts;
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.ExtractorOutput
;
import
com.google.android.exoplayer2.extractor.MpegAudioHeader
;
import
com.google.android.exoplayer2.extractor.MpegAudioHeader
;
import
com.google.android.exoplayer2.extractor.TrackOutput
;
import
com.google.android.exoplayer2.extractor.TrackOutput
;
import
com.google.android.exoplayer2.util.ParsableByteArray
;
import
com.google.android.exoplayer2.util.ParsableByteArray
;
...
@@ -36,6 +37,8 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
...
@@ -36,6 +37,8 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
private
final
MpegAudioHeader
header
;
private
final
MpegAudioHeader
header
;
private
final
String
language
;
private
final
String
language
;
private
TrackOutput
output
;
private
int
state
;
private
int
state
;
private
int
frameBytesRead
;
private
int
frameBytesRead
;
private
boolean
hasOutputFormat
;
private
boolean
hasOutputFormat
;
...
@@ -50,12 +53,11 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
...
@@ -50,12 +53,11 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
// The timestamp to attach to the next sample in the current packet.
// The timestamp to attach to the next sample in the current packet.
private
long
timeUs
;
private
long
timeUs
;
public
MpegAudioReader
(
TrackOutput
output
)
{
public
MpegAudioReader
()
{
this
(
output
,
null
);
this
(
null
);
}
}
public
MpegAudioReader
(
TrackOutput
output
,
String
language
)
{
public
MpegAudioReader
(
String
language
)
{
super
(
output
);
state
=
STATE_FINDING_HEADER
;
state
=
STATE_FINDING_HEADER
;
// The first byte of an MPEG Audio frame header is always 0xFF.
// The first byte of an MPEG Audio frame header is always 0xFF.
headerScratch
=
new
ParsableByteArray
(
4
);
headerScratch
=
new
ParsableByteArray
(
4
);
...
@@ -72,6 +74,11 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
...
@@ -72,6 +74,11 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
}
}
@Override
@Override
public
void
init
(
ExtractorOutput
extractorOutput
,
TrackIdGenerator
idGenerator
)
{
output
=
extractorOutput
.
track
(
idGenerator
.
getNextId
());
}
@Override
public
void
packetStarted
(
long
pesTimeUs
,
boolean
dataAlignmentIndicator
)
{
public
void
packetStarted
(
long
pesTimeUs
,
boolean
dataAlignmentIndicator
)
{
timeUs
=
pesTimeUs
;
timeUs
=
pesTimeUs
;
}
}
...
...
library/src/main/java/com/google/android/exoplayer2/extractor/ts/PsExtractor.java
View file @
e2ff401e
...
@@ -24,6 +24,7 @@ import com.google.android.exoplayer2.extractor.ExtractorsFactory;
...
@@ -24,6 +24,7 @@ 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.TimestampAdjuster
;
import
com.google.android.exoplayer2.extractor.ts.ElementaryStreamReader.TrackIdGenerator
;
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
;
...
@@ -49,6 +50,7 @@ public final class PsExtractor implements Extractor {
...
@@ -49,6 +50,7 @@ public final class PsExtractor implements Extractor {
private
static
final
int
SYSTEM_HEADER_START_CODE
=
0x000001BB
;
private
static
final
int
SYSTEM_HEADER_START_CODE
=
0x000001BB
;
private
static
final
int
PACKET_START_CODE_PREFIX
=
0x000001
;
private
static
final
int
PACKET_START_CODE_PREFIX
=
0x000001
;
private
static
final
int
MPEG_PROGRAM_END_CODE
=
0x000001B9
;
private
static
final
int
MPEG_PROGRAM_END_CODE
=
0x000001B9
;
private
static
final
int
MAX_STREAM_ID_PLUS_ONE
=
0x100
;
private
static
final
long
MAX_SEARCH_LENGTH
=
1024
*
1024
;
private
static
final
long
MAX_SEARCH_LENGTH
=
1024
*
1024
;
public
static
final
int
PRIVATE_STREAM_1
=
0xBD
;
public
static
final
int
PRIVATE_STREAM_1
=
0xBD
;
...
@@ -189,16 +191,18 @@ public final class PsExtractor implements Extractor {
...
@@ -189,16 +191,18 @@ public final class PsExtractor implements Extractor {
// Private stream, used for AC3 audio.
// Private stream, used for AC3 audio.
// NOTE: This may need further parsing to determine if its DTS, but that's likely only
// NOTE: This may need further parsing to determine if its DTS, but that's likely only
// valid for DVDs.
// valid for DVDs.
elementaryStreamReader
=
new
Ac3Reader
(
output
.
track
(
streamId
)
);
elementaryStreamReader
=
new
Ac3Reader
();
foundAudioTrack
=
true
;
foundAudioTrack
=
true
;
}
else
if
(!
foundAudioTrack
&&
(
streamId
&
AUDIO_STREAM_MASK
)
==
AUDIO_STREAM
)
{
}
else
if
(!
foundAudioTrack
&&
(
streamId
&
AUDIO_STREAM_MASK
)
==
AUDIO_STREAM
)
{
elementaryStreamReader
=
new
MpegAudioReader
(
output
.
track
(
streamId
)
);
elementaryStreamReader
=
new
MpegAudioReader
();
foundAudioTrack
=
true
;
foundAudioTrack
=
true
;
}
else
if
(!
foundVideoTrack
&&
(
streamId
&
VIDEO_STREAM_MASK
)
==
VIDEO_STREAM
)
{
}
else
if
(!
foundVideoTrack
&&
(
streamId
&
VIDEO_STREAM_MASK
)
==
VIDEO_STREAM
)
{
elementaryStreamReader
=
new
H262Reader
(
output
.
track
(
streamId
)
);
elementaryStreamReader
=
new
H262Reader
();
foundVideoTrack
=
true
;
foundVideoTrack
=
true
;
}
}
if
(
elementaryStreamReader
!=
null
)
{
if
(
elementaryStreamReader
!=
null
)
{
TrackIdGenerator
idGenerator
=
new
TrackIdGenerator
(
streamId
,
MAX_STREAM_ID_PLUS_ONE
);
elementaryStreamReader
.
init
(
output
,
idGenerator
);
payloadReader
=
new
PesReader
(
elementaryStreamReader
,
timestampAdjuster
);
payloadReader
=
new
PesReader
(
elementaryStreamReader
,
timestampAdjuster
);
psPayloadReaders
.
put
(
streamId
,
payloadReader
);
psPayloadReaders
.
put
(
streamId
,
payloadReader
);
}
}
...
...
library/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java
View file @
e2ff401e
...
@@ -17,6 +17,7 @@ package com.google.android.exoplayer2.extractor.ts;
...
@@ -17,6 +17,7 @@ package com.google.android.exoplayer2.extractor.ts;
import
android.util.Log
;
import
android.util.Log
;
import
android.util.SparseArray
;
import
android.util.SparseArray
;
import
android.util.SparseBooleanArray
;
import
android.util.SparseIntArray
;
import
android.util.SparseIntArray
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.extractor.Extractor
;
import
com.google.android.exoplayer2.extractor.Extractor
;
...
@@ -26,6 +27,9 @@ import com.google.android.exoplayer2.extractor.ExtractorsFactory;
...
@@ -26,6 +27,9 @@ 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.TimestampAdjuster
;
import
com.google.android.exoplayer2.extractor.TrackOutput
;
import
com.google.android.exoplayer2.extractor.ts.ElementaryStreamReader.EsInfo
;
import
com.google.android.exoplayer2.extractor.ts.ElementaryStreamReader.TrackIdGenerator
;
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
;
...
@@ -50,12 +54,6 @@ public final class TsExtractor implements Extractor {
...
@@ -50,12 +54,6 @@ public final class TsExtractor implements Extractor {
};
};
private
static
final
String
TAG
=
"TsExtractor"
;
private
static
final
int
TS_PACKET_SIZE
=
188
;
private
static
final
int
TS_SYNC_BYTE
=
0x47
;
// First byte of each TS packet.
private
static
final
int
TS_PAT_PID
=
0
;
public
static
final
int
TS_STREAM_TYPE_MPA
=
0x03
;
public
static
final
int
TS_STREAM_TYPE_MPA
=
0x03
;
public
static
final
int
TS_STREAM_TYPE_MPA_LSF
=
0x04
;
public
static
final
int
TS_STREAM_TYPE_MPA_LSF
=
0x04
;
public
static
final
int
TS_STREAM_TYPE_AAC
=
0x0F
;
public
static
final
int
TS_STREAM_TYPE_AAC
=
0x0F
;
...
@@ -68,6 +66,12 @@ public final class TsExtractor implements Extractor {
...
@@ -68,6 +66,12 @@ public final class TsExtractor implements Extractor {
public
static
final
int
TS_STREAM_TYPE_H265
=
0x24
;
public
static
final
int
TS_STREAM_TYPE_H265
=
0x24
;
public
static
final
int
TS_STREAM_TYPE_ID3
=
0x15
;
public
static
final
int
TS_STREAM_TYPE_ID3
=
0x15
;
private
static
final
String
TAG
=
"TsExtractor"
;
private
static
final
int
TS_PACKET_SIZE
=
188
;
private
static
final
int
TS_SYNC_BYTE
=
0x47
;
// First byte of each TS packet.
private
static
final
int
TS_PAT_PID
=
0
;
private
static
final
int
MAX_PID_PLUS_ONE
=
0x2000
;
private
static
final
long
AC3_FORMAT_IDENTIFIER
=
Util
.
getIntegerCodeForString
(
"AC-3"
);
private
static
final
long
AC3_FORMAT_IDENTIFIER
=
Util
.
getIntegerCodeForString
(
"AC-3"
);
private
static
final
long
E_AC3_FORMAT_IDENTIFIER
=
Util
.
getIntegerCodeForString
(
"EAC3"
);
private
static
final
long
E_AC3_FORMAT_IDENTIFIER
=
Util
.
getIntegerCodeForString
(
"EAC3"
);
...
@@ -76,15 +80,19 @@ public final class TsExtractor implements Extractor {
...
@@ -76,15 +80,19 @@ public final class TsExtractor implements Extractor {
private
static
final
int
BUFFER_PACKET_COUNT
=
5
;
// Should be at least 2
private
static
final
int
BUFFER_PACKET_COUNT
=
5
;
// Should be at least 2
private
static
final
int
BUFFER_SIZE
=
TS_PACKET_SIZE
*
BUFFER_PACKET_COUNT
;
private
static
final
int
BUFFER_SIZE
=
TS_PACKET_SIZE
*
BUFFER_PACKET_COUNT
;
private
final
boolean
mapByType
;
private
final
TimestampAdjuster
timestampAdjuster
;
private
final
TimestampAdjuster
timestampAdjuster
;
private
final
ParsableByteArray
tsPacketBuffer
;
private
final
ParsableByteArray
tsPacketBuffer
;
private
final
ParsableBitArray
tsScratch
;
private
final
ParsableBitArray
tsScratch
;
private
final
SparseIntArray
continuityCounters
;
private
final
SparseIntArray
continuityCounters
;
private
final
ElementaryStreamReader
.
Factory
streamReaderFactory
;
private
final
ElementaryStreamReader
.
Factory
streamReaderFactory
;
/* package */
final
SparseArray
<
TsPayloadReader
>
tsPayloadReaders
;
// Indexed by pid
private
final
SparseArray
<
TsPayloadReader
>
tsPayloadReaders
;
// Indexed by pid
private
final
SparseBooleanArray
trackIds
;
// Accessed only by the loading thread.
// Accessed only by the loading thread.
private
ExtractorOutput
output
;
private
ExtractorOutput
output
;
private
boolean
tracksEnded
;
private
ElementaryStreamReader
id3Reader
;
public
TsExtractor
()
{
public
TsExtractor
()
{
this
(
new
TimestampAdjuster
(
0
));
this
(
new
TimestampAdjuster
(
0
));
...
@@ -94,22 +102,26 @@ public final class TsExtractor implements Extractor {
...
@@ -94,22 +102,26 @@ public final class TsExtractor implements Extractor {
* @param timestampAdjuster A timestamp adjuster for offsetting and scaling sample timestamps.
* @param timestampAdjuster A timestamp adjuster for offsetting and scaling sample timestamps.
*/
*/
public
TsExtractor
(
TimestampAdjuster
timestampAdjuster
)
{
public
TsExtractor
(
TimestampAdjuster
timestampAdjuster
)
{
this
(
timestampAdjuster
,
new
DefaultStreamReaderFactory
());
this
(
timestampAdjuster
,
new
DefaultStreamReaderFactory
()
,
false
);
}
}
/**
/**
* @param timestampAdjuster A timestamp adjuster for offsetting and scaling sample timestamps.
* @param timestampAdjuster A timestamp adjuster for offsetting and scaling sample timestamps.
* @param customReaderFactory Factory for injecting a custom set of elementary stream readers.
* @param customReaderFactory Factory for injecting a custom set of elementary stream readers.
* @param mapByType True if {@link TrackOutput}s should be mapped by their type, false to map them
* by their PID.
*/
*/
public
TsExtractor
(
TimestampAdjuster
timestampAdjuster
,
public
TsExtractor
(
TimestampAdjuster
timestampAdjuster
,
ElementaryStreamReader
.
Factory
customReaderFactory
)
{
ElementaryStreamReader
.
Factory
customReaderFactory
,
boolean
mapByType
)
{
this
.
timestampAdjuster
=
timestampAdjuster
;
this
.
timestampAdjuster
=
timestampAdjuster
;
this
.
streamReaderFactory
=
Assertions
.
checkNotNull
(
customReaderFactory
);
this
.
streamReaderFactory
=
Assertions
.
checkNotNull
(
customReaderFactory
);
this
.
mapByType
=
mapByType
;
tsPacketBuffer
=
new
ParsableByteArray
(
BUFFER_SIZE
);
tsPacketBuffer
=
new
ParsableByteArray
(
BUFFER_SIZE
);
tsScratch
=
new
ParsableBitArray
(
new
byte
[
3
]);
tsScratch
=
new
ParsableBitArray
(
new
byte
[
3
]);
trackIds
=
new
SparseBooleanArray
();
tsPayloadReaders
=
new
SparseArray
<>();
tsPayloadReaders
=
new
SparseArray
<>();
tsPayloadReaders
.
put
(
TS_PAT_PID
,
new
PatReader
());
continuityCounters
=
new
SparseIntArray
();
continuityCounters
=
new
SparseIntArray
();
resetPayloadReaders
();
}
}
// Extractor implementation.
// Extractor implementation.
...
@@ -141,11 +153,10 @@ public final class TsExtractor implements Extractor {
...
@@ -141,11 +153,10 @@ public final class TsExtractor implements Extractor {
@Override
@Override
public
void
seek
(
long
position
)
{
public
void
seek
(
long
position
)
{
timestampAdjuster
.
reset
();
timestampAdjuster
.
reset
();
for
(
int
i
=
0
;
i
<
tsPayloadReaders
.
size
();
i
++)
{
tsPayloadReaders
.
valueAt
(
i
).
seek
();
}
tsPacketBuffer
.
reset
();
tsPacketBuffer
.
reset
();
continuityCounters
.
clear
();
continuityCounters
.
clear
();
// Elementary stream readers' state should be cleared to get consistent behaviours when seeking.
resetPayloadReaders
();
}
}
@Override
@Override
...
@@ -240,6 +251,13 @@ public final class TsExtractor implements Extractor {
...
@@ -240,6 +251,13 @@ public final class TsExtractor implements Extractor {
// Internals.
// Internals.
private
void
resetPayloadReaders
()
{
trackIds
.
clear
();
tsPayloadReaders
.
clear
();
tsPayloadReaders
.
put
(
TS_PAT_PID
,
new
PatReader
());
id3Reader
=
null
;
}
/**
/**
* Parses TS packet payload data.
* Parses TS packet payload data.
*/
*/
...
@@ -333,7 +351,7 @@ public final class TsExtractor implements Extractor {
...
@@ -333,7 +351,7 @@ public final class TsExtractor implements Extractor {
patScratch
.
skipBits
(
13
);
// network_PID (13)
patScratch
.
skipBits
(
13
);
// network_PID (13)
}
else
{
}
else
{
int
pid
=
patScratch
.
readBits
(
13
);
int
pid
=
patScratch
.
readBits
(
13
);
tsPayloadReaders
.
put
(
pid
,
new
PmtReader
());
tsPayloadReaders
.
put
(
pid
,
new
PmtReader
(
pid
));
}
}
}
}
}
}
...
@@ -353,14 +371,16 @@ public final class TsExtractor implements Extractor {
...
@@ -353,14 +371,16 @@ public final class TsExtractor implements Extractor {
private
final
ParsableBitArray
pmtScratch
;
private
final
ParsableBitArray
pmtScratch
;
private
final
ParsableByteArray
sectionData
;
private
final
ParsableByteArray
sectionData
;
private
final
int
pid
;
private
int
sectionLength
;
private
int
sectionLength
;
private
int
sectionBytesRead
;
private
int
sectionBytesRead
;
private
int
crc
;
private
int
crc
;
public
PmtReader
()
{
public
PmtReader
(
int
pid
)
{
pmtScratch
=
new
ParsableBitArray
(
new
byte
[
5
]);
pmtScratch
=
new
ParsableBitArray
(
new
byte
[
5
]);
sectionData
=
new
ParsableByteArray
();
sectionData
=
new
ParsableByteArray
();
this
.
pid
=
pid
;
}
}
@Override
@Override
...
@@ -413,6 +433,14 @@ public final class TsExtractor implements Extractor {
...
@@ -413,6 +433,14 @@ public final class TsExtractor implements Extractor {
// Skip the descriptors.
// Skip the descriptors.
sectionData
.
skipBytes
(
programInfoLength
);
sectionData
.
skipBytes
(
programInfoLength
);
if
(
mapByType
&&
id3Reader
==
null
)
{
// Setup an ID3 track regardless of whether there's a corresponding entry, in case one
// appears intermittently during playback. See [Internal: b/20261500].
EsInfo
dummyEsInfo
=
new
EsInfo
(
TS_STREAM_TYPE_ID3
,
null
,
new
byte
[
0
]);
id3Reader
=
streamReaderFactory
.
createStreamReader
(
TS_STREAM_TYPE_ID3
,
dummyEsInfo
);
id3Reader
.
init
(
output
,
new
TrackIdGenerator
(
TS_STREAM_TYPE_ID3
,
MAX_PID_PLUS_ONE
));
}
int
remainingEntriesLength
=
sectionLength
-
9
/* Length of fields before descriptors */
int
remainingEntriesLength
=
sectionLength
-
9
/* Length of fields before descriptors */
-
programInfoLength
-
4
/* CRC length */
;
-
programInfoLength
-
4
/* CRC length */
;
while
(
remainingEntriesLength
>
0
)
{
while
(
remainingEntriesLength
>
0
)
{
...
@@ -422,21 +450,40 @@ public final class TsExtractor implements Extractor {
...
@@ -422,21 +450,40 @@ public final class TsExtractor implements Extractor {
int
elementaryPid
=
pmtScratch
.
readBits
(
13
);
int
elementaryPid
=
pmtScratch
.
readBits
(
13
);
pmtScratch
.
skipBits
(
4
);
// reserved
pmtScratch
.
skipBits
(
4
);
// reserved
int
esInfoLength
=
pmtScratch
.
readBits
(
12
);
// ES_info_length.
int
esInfoLength
=
pmtScratch
.
readBits
(
12
);
// ES_info_length.
E
lementaryStreamReader
.
E
sInfo
esInfo
=
readEsInfo
(
sectionData
,
esInfoLength
);
EsInfo
esInfo
=
readEsInfo
(
sectionData
,
esInfoLength
);
if
(
streamType
==
0x06
)
{
if
(
streamType
==
0x06
)
{
streamType
=
esInfo
.
streamType
;
streamType
=
esInfo
.
streamType
;
}
}
remainingEntriesLength
-=
esInfoLength
+
5
;
remainingEntriesLength
-=
esInfoLength
+
5
;
ElementaryStreamReader
pesPayloadReader
=
streamReaderFactory
.
onPmtEntry
(
elementaryPid
,
streamType
,
esInfo
,
output
);
int
trackId
=
mapByType
?
streamType
:
elementaryPid
;
if
(
trackIds
.
get
(
trackId
))
{
continue
;
}
trackIds
.
put
(
trackId
,
true
);
ElementaryStreamReader
pesPayloadReader
;
if
(
mapByType
&&
streamType
==
TS_STREAM_TYPE_ID3
)
{
pesPayloadReader
=
id3Reader
;
}
else
{
pesPayloadReader
=
streamReaderFactory
.
createStreamReader
(
streamType
,
esInfo
);
pesPayloadReader
.
init
(
output
,
new
TrackIdGenerator
(
trackId
,
MAX_PID_PLUS_ONE
));
}
if
(
pesPayloadReader
!=
null
)
{
if
(
pesPayloadReader
!=
null
)
{
tsPayloadReaders
.
put
(
elementaryPid
,
tsPayloadReaders
.
put
(
elementaryPid
,
new
PesReader
(
pesPayloadReader
,
timestampAdjuster
));
new
PesReader
(
pesPayloadReader
,
timestampAdjuster
));
}
}
}
}
if
(
mapByType
)
{
output
.
endTracks
();
if
(!
tracksEnded
)
{
output
.
endTracks
();
}
}
else
{
tsPayloadReaders
.
remove
(
TS_PAT_PID
);
tsPayloadReaders
.
remove
(
pid
);
output
.
endTracks
();
}
tracksEnded
=
true
;
}
}
/**
/**
...
@@ -447,7 +494,7 @@ public final class TsExtractor implements Extractor {
...
@@ -447,7 +494,7 @@ public final class TsExtractor implements Extractor {
* @param length The length of descriptors to read from the current position in {@code data}.
* @param length The length of descriptors to read from the current position in {@code data}.
* @return The stream info read from the available descriptors.
* @return The stream info read from the available descriptors.
*/
*/
private
E
lementaryStreamReader
.
E
sInfo
readEsInfo
(
ParsableByteArray
data
,
int
length
)
{
private
EsInfo
readEsInfo
(
ParsableByteArray
data
,
int
length
)
{
int
descriptorsStartPosition
=
data
.
getPosition
();
int
descriptorsStartPosition
=
data
.
getPosition
();
int
descriptorsEndPosition
=
descriptorsStartPosition
+
length
;
int
descriptorsEndPosition
=
descriptorsStartPosition
+
length
;
int
streamType
=
-
1
;
int
streamType
=
-
1
;
...
@@ -479,7 +526,7 @@ public final class TsExtractor implements Extractor {
...
@@ -479,7 +526,7 @@ public final class TsExtractor implements Extractor {
data
.
skipBytes
(
positionOfNextDescriptor
-
data
.
getPosition
());
data
.
skipBytes
(
positionOfNextDescriptor
-
data
.
getPosition
());
}
}
data
.
setPosition
(
descriptorsEndPosition
);
data
.
setPosition
(
descriptorsEndPosition
);
return
new
E
lementaryStreamReader
.
E
sInfo
(
streamType
,
language
,
return
new
EsInfo
(
streamType
,
language
,
Arrays
.
copyOfRange
(
sectionData
.
data
,
descriptorsStartPosition
,
descriptorsEndPosition
));
Arrays
.
copyOfRange
(
sectionData
.
data
,
descriptorsStartPosition
,
descriptorsEndPosition
));
}
}
...
...
library/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java
View file @
e2ff401e
...
@@ -17,6 +17,7 @@ package com.google.android.exoplayer2.source;
...
@@ -17,6 +17,7 @@ package com.google.android.exoplayer2.source;
import
android.net.Uri
;
import
android.net.Uri
;
import
android.os.Handler
;
import
android.os.Handler
;
import
android.util.SparseArray
;
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.FormatHolder
;
import
com.google.android.exoplayer2.FormatHolder
;
...
@@ -41,7 +42,6 @@ import com.google.android.exoplayer2.util.ConditionVariable;
...
@@ -41,7 +42,6 @@ import com.google.android.exoplayer2.util.ConditionVariable;
import
com.google.android.exoplayer2.util.Util
;
import
com.google.android.exoplayer2.util.Util
;
import
java.io.EOFException
;
import
java.io.EOFException
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.util.Arrays
;
/**
/**
* A {@link MediaPeriod} that extracts data using an {@link Extractor}.
* A {@link MediaPeriod} that extracts data using an {@link Extractor}.
...
@@ -68,6 +68,7 @@ import java.util.Arrays;
...
@@ -68,6 +68,7 @@ import java.util.Arrays;
private
final
Runnable
maybeFinishPrepareRunnable
;
private
final
Runnable
maybeFinishPrepareRunnable
;
private
final
Runnable
onContinueLoadingRequestedRunnable
;
private
final
Runnable
onContinueLoadingRequestedRunnable
;
private
final
Handler
handler
;
private
final
Handler
handler
;
private
final
SparseArray
<
DefaultTrackOutput
>
sampleQueues
;
private
Callback
callback
;
private
Callback
callback
;
private
SeekMap
seekMap
;
private
SeekMap
seekMap
;
...
@@ -77,7 +78,6 @@ import java.util.Arrays;
...
@@ -77,7 +78,6 @@ import java.util.Arrays;
private
boolean
seenFirstTrackSelection
;
private
boolean
seenFirstTrackSelection
;
private
boolean
notifyReset
;
private
boolean
notifyReset
;
private
int
enabledTrackCount
;
private
int
enabledTrackCount
;
private
DefaultTrackOutput
[]
sampleQueues
;
private
TrackGroupArray
tracks
;
private
TrackGroupArray
tracks
;
private
long
durationUs
;
private
long
durationUs
;
private
boolean
[]
trackEnabledStates
;
private
boolean
[]
trackEnabledStates
;
...
@@ -131,7 +131,7 @@ import java.util.Arrays;
...
@@ -131,7 +131,7 @@ import java.util.Arrays;
handler
=
new
Handler
();
handler
=
new
Handler
();
pendingResetPositionUs
=
C
.
TIME_UNSET
;
pendingResetPositionUs
=
C
.
TIME_UNSET
;
sampleQueues
=
new
DefaultTrackOutput
[
0
]
;
sampleQueues
=
new
SparseArray
<>()
;
length
=
C
.
LENGTH_UNSET
;
length
=
C
.
LENGTH_UNSET
;
}
}
...
@@ -141,8 +141,9 @@ import java.util.Arrays;
...
@@ -141,8 +141,9 @@ import java.util.Arrays;
@Override
@Override
public
void
run
()
{
public
void
run
()
{
extractorHolder
.
release
();
extractorHolder
.
release
();
for
(
DefaultTrackOutput
sampleQueue
:
sampleQueues
)
{
int
trackCount
=
sampleQueues
.
size
();
sampleQueue
.
disable
();
for
(
int
i
=
0
;
i
<
trackCount
;
i
++)
{
sampleQueues
.
valueAt
(
i
).
disable
();
}
}
}
}
});
});
...
@@ -178,7 +179,7 @@ import java.util.Arrays;
...
@@ -178,7 +179,7 @@ import java.util.Arrays;
Assertions
.
checkState
(
trackEnabledStates
[
track
]);
Assertions
.
checkState
(
trackEnabledStates
[
track
]);
enabledTrackCount
--;
enabledTrackCount
--;
trackEnabledStates
[
track
]
=
false
;
trackEnabledStates
[
track
]
=
false
;
sampleQueues
[
track
]
.
disable
();
sampleQueues
.
valueAt
(
track
)
.
disable
();
streams
[
i
]
=
null
;
streams
[
i
]
=
null
;
}
}
}
}
...
@@ -201,9 +202,10 @@ import java.util.Arrays;
...
@@ -201,9 +202,10 @@ import java.util.Arrays;
if
(!
seenFirstTrackSelection
)
{
if
(!
seenFirstTrackSelection
)
{
// At the time of the first track selection all queues will be enabled, so we need to disable
// At the time of the first track selection all queues will be enabled, so we need to disable
// any that are no longer required.
// any that are no longer required.
for
(
int
i
=
0
;
i
<
sampleQueues
.
length
;
i
++)
{
int
trackCount
=
sampleQueues
.
size
();
for
(
int
i
=
0
;
i
<
trackCount
;
i
++)
{
if
(!
trackEnabledStates
[
i
])
{
if
(!
trackEnabledStates
[
i
])
{
sampleQueues
[
i
]
.
disable
();
sampleQueues
.
valueAt
(
i
)
.
disable
();
}
}
}
}
}
}
...
@@ -270,11 +272,12 @@ import java.util.Arrays;
...
@@ -270,11 +272,12 @@ import java.util.Arrays;
// Treat all seeks into non-seekable media as being to t=0.
// Treat all seeks into non-seekable media as being to t=0.
positionUs
=
seekMap
.
isSeekable
()
?
positionUs
:
0
;
positionUs
=
seekMap
.
isSeekable
()
?
positionUs
:
0
;
lastSeekPositionUs
=
positionUs
;
lastSeekPositionUs
=
positionUs
;
int
trackCount
=
sampleQueues
.
size
();
// If we're not pending a reset, see if we can seek within the sample queues.
// If we're not pending a reset, see if we can seek within the sample queues.
boolean
seekInsideBuffer
=
!
isPendingReset
();
boolean
seekInsideBuffer
=
!
isPendingReset
();
for
(
int
i
=
0
;
seekInsideBuffer
&&
i
<
sampleQueues
.
length
;
i
++)
{
for
(
int
i
=
0
;
seekInsideBuffer
&&
i
<
trackCount
;
i
++)
{
if
(
trackEnabledStates
[
i
])
{
if
(
trackEnabledStates
[
i
])
{
seekInsideBuffer
=
sampleQueues
[
i
]
.
skipToKeyframeBefore
(
positionUs
);
seekInsideBuffer
=
sampleQueues
.
valueAt
(
i
)
.
skipToKeyframeBefore
(
positionUs
);
}
}
}
}
// If we failed to seek within the sample queues, we need to restart.
// If we failed to seek within the sample queues, we need to restart.
...
@@ -284,8 +287,8 @@ import java.util.Arrays;
...
@@ -284,8 +287,8 @@ import java.util.Arrays;
if
(
loader
.
isLoading
())
{
if
(
loader
.
isLoading
())
{
loader
.
cancelLoading
();
loader
.
cancelLoading
();
}
else
{
}
else
{
for
(
int
i
=
0
;
i
<
sampleQueues
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
trackCount
;
i
++)
{
sampleQueues
[
i
]
.
reset
(
trackEnabledStates
[
i
]);
sampleQueues
.
valueAt
(
i
)
.
reset
(
trackEnabledStates
[
i
]);
}
}
}
}
}
}
...
@@ -296,7 +299,7 @@ import java.util.Arrays;
...
@@ -296,7 +299,7 @@ import java.util.Arrays;
// SampleStream methods.
// SampleStream methods.
/* package */
boolean
isReady
(
int
track
)
{
/* package */
boolean
isReady
(
int
track
)
{
return
loadingFinished
||
(!
isPendingReset
()
&&
!
sampleQueues
[
track
]
.
isEmpty
());
return
loadingFinished
||
(!
isPendingReset
()
&&
!
sampleQueues
.
valueAt
(
track
)
.
isEmpty
());
}
}
/* package */
void
maybeThrowError
()
throws
IOException
{
/* package */
void
maybeThrowError
()
throws
IOException
{
...
@@ -308,7 +311,8 @@ import java.util.Arrays;
...
@@ -308,7 +311,8 @@ import java.util.Arrays;
return
C
.
RESULT_NOTHING_READ
;
return
C
.
RESULT_NOTHING_READ
;
}
}
return
sampleQueues
[
track
].
readData
(
formatHolder
,
buffer
,
loadingFinished
,
lastSeekPositionUs
);
return
sampleQueues
.
valueAt
(
track
).
readData
(
formatHolder
,
buffer
,
loadingFinished
,
lastSeekPositionUs
);
}
}
// Loader.Callback implementation.
// Loader.Callback implementation.
...
@@ -332,8 +336,9 @@ import java.util.Arrays;
...
@@ -332,8 +336,9 @@ import java.util.Arrays;
long
loadDurationMs
,
boolean
released
)
{
long
loadDurationMs
,
boolean
released
)
{
copyLengthFromLoader
(
loadable
);
copyLengthFromLoader
(
loadable
);
if
(!
released
&&
enabledTrackCount
>
0
)
{
if
(!
released
&&
enabledTrackCount
>
0
)
{
for
(
int
i
=
0
;
i
<
sampleQueues
.
length
;
i
++)
{
int
trackCount
=
sampleQueues
.
size
();
sampleQueues
[
i
].
reset
(
trackEnabledStates
[
i
]);
for
(
int
i
=
0
;
i
<
trackCount
;
i
++)
{
sampleQueues
.
valueAt
(
i
).
reset
(
trackEnabledStates
[
i
]);
}
}
callback
.
onContinueLoadingRequested
(
this
);
callback
.
onContinueLoadingRequested
(
this
);
}
}
...
@@ -358,11 +363,13 @@ import java.util.Arrays;
...
@@ -358,11 +363,13 @@ import java.util.Arrays;
@Override
@Override
public
TrackOutput
track
(
int
id
)
{
public
TrackOutput
track
(
int
id
)
{
sampleQueues
=
Arrays
.
copyOf
(
sampleQueues
,
sampleQueues
.
length
+
1
);
DefaultTrackOutput
trackOutput
=
sampleQueues
.
get
(
id
);
DefaultTrackOutput
sampleQueue
=
new
DefaultTrackOutput
(
allocator
);
if
(
trackOutput
==
null
)
{
sampleQueue
.
setUpstreamFormatChangeListener
(
this
);
trackOutput
=
new
DefaultTrackOutput
(
allocator
);
sampleQueues
[
sampleQueues
.
length
-
1
]
=
sampleQueue
;
trackOutput
.
setUpstreamFormatChangeListener
(
this
);
return
sampleQueue
;
sampleQueues
.
put
(
id
,
trackOutput
);
}
return
trackOutput
;
}
}
@Override
@Override
...
@@ -390,18 +397,18 @@ import java.util.Arrays;
...
@@ -390,18 +397,18 @@ import java.util.Arrays;
if
(
released
||
prepared
||
seekMap
==
null
||
!
tracksBuilt
)
{
if
(
released
||
prepared
||
seekMap
==
null
||
!
tracksBuilt
)
{
return
;
return
;
}
}
for
(
DefaultTrackOutput
sampleQueue
:
sampleQueues
)
{
int
trackCount
=
sampleQueues
.
size
();
if
(
sampleQueue
.
getUpstreamFormat
()
==
null
)
{
for
(
int
i
=
0
;
i
<
trackCount
;
i
++)
{
if
(
sampleQueues
.
valueAt
(
i
).
getUpstreamFormat
()
==
null
)
{
return
;
return
;
}
}
}
}
loadCondition
.
close
();
loadCondition
.
close
();
int
trackCount
=
sampleQueues
.
length
;
TrackGroup
[]
trackArray
=
new
TrackGroup
[
trackCount
];
TrackGroup
[]
trackArray
=
new
TrackGroup
[
trackCount
];
trackEnabledStates
=
new
boolean
[
trackCount
];
trackEnabledStates
=
new
boolean
[
trackCount
];
durationUs
=
seekMap
.
getDurationUs
();
durationUs
=
seekMap
.
getDurationUs
();
for
(
int
i
=
0
;
i
<
trackCount
;
i
++)
{
for
(
int
i
=
0
;
i
<
trackCount
;
i
++)
{
trackArray
[
i
]
=
new
TrackGroup
(
sampleQueues
[
i
]
.
getUpstreamFormat
());
trackArray
[
i
]
=
new
TrackGroup
(
sampleQueues
.
valueAt
(
i
)
.
getUpstreamFormat
());
}
}
tracks
=
new
TrackGroupArray
(
trackArray
);
tracks
=
new
TrackGroupArray
(
trackArray
);
prepared
=
true
;
prepared
=
true
;
...
@@ -455,8 +462,9 @@ import java.util.Arrays;
...
@@ -455,8 +462,9 @@ import java.util.Arrays;
// a new load.
// a new load.
lastSeekPositionUs
=
0
;
lastSeekPositionUs
=
0
;
notifyReset
=
prepared
;
notifyReset
=
prepared
;
for
(
int
i
=
0
;
i
<
sampleQueues
.
length
;
i
++)
{
int
trackCount
=
sampleQueues
.
size
();
sampleQueues
[
i
].
reset
(!
prepared
||
trackEnabledStates
[
i
]);
for
(
int
i
=
0
;
i
<
trackCount
;
i
++)
{
sampleQueues
.
valueAt
(
i
).
reset
(!
prepared
||
trackEnabledStates
[
i
]);
}
}
loadable
.
setLoadPosition
(
0
);
loadable
.
setLoadPosition
(
0
);
}
}
...
@@ -464,17 +472,19 @@ import java.util.Arrays;
...
@@ -464,17 +472,19 @@ import java.util.Arrays;
private
int
getExtractedSamplesCount
()
{
private
int
getExtractedSamplesCount
()
{
int
extractedSamplesCount
=
0
;
int
extractedSamplesCount
=
0
;
for
(
DefaultTrackOutput
sampleQueue
:
sampleQueues
)
{
int
trackCount
=
sampleQueues
.
size
();
extractedSamplesCount
+=
sampleQueue
.
getWriteIndex
();
for
(
int
i
=
0
;
i
<
trackCount
;
i
++)
{
extractedSamplesCount
+=
sampleQueues
.
valueAt
(
i
).
getWriteIndex
();
}
}
return
extractedSamplesCount
;
return
extractedSamplesCount
;
}
}
private
long
getLargestQueuedTimestampUs
()
{
private
long
getLargestQueuedTimestampUs
()
{
long
largestQueuedTimestampUs
=
Long
.
MIN_VALUE
;
long
largestQueuedTimestampUs
=
Long
.
MIN_VALUE
;
for
(
DefaultTrackOutput
sampleQueue
:
sampleQueues
)
{
int
trackCount
=
sampleQueues
.
size
();
for
(
int
i
=
0
;
i
<
trackCount
;
i
++)
{
largestQueuedTimestampUs
=
Math
.
max
(
largestQueuedTimestampUs
,
largestQueuedTimestampUs
=
Math
.
max
(
largestQueuedTimestampUs
,
sampleQueue
.
getLargestQueuedTimestampUs
());
sampleQueue
s
.
valueAt
(
i
)
.
getLargestQueuedTimestampUs
());
}
}
return
largestQueuedTimestampUs
;
return
largestQueuedTimestampUs
;
}
}
...
@@ -523,7 +533,7 @@ import java.util.Arrays;
...
@@ -523,7 +533,7 @@ import java.util.Arrays;
@Override
@Override
public
void
skipToKeyframeBefore
(
long
timeUs
)
{
public
void
skipToKeyframeBefore
(
long
timeUs
)
{
sampleQueues
[
track
]
.
skipToKeyframeBefore
(
timeUs
);
sampleQueues
.
valueAt
(
track
)
.
skipToKeyframeBefore
(
timeUs
);
}
}
}
}
...
...
library/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkExtractorWrapper.java
View file @
e2ff401e
...
@@ -59,6 +59,7 @@ public final class ChunkExtractorWrapper implements ExtractorOutput, TrackOutput
...
@@ -59,6 +59,7 @@ public final class ChunkExtractorWrapper implements ExtractorOutput, TrackOutput
// Accessed only on the loader thread.
// Accessed only on the loader thread.
private
boolean
seenTrack
;
private
boolean
seenTrack
;
private
int
seenTrackId
;
/**
/**
* @param extractor The extractor to wrap.
* @param extractor The extractor to wrap.
...
@@ -116,8 +117,9 @@ public final class ChunkExtractorWrapper implements ExtractorOutput, TrackOutput
...
@@ -116,8 +117,9 @@ public final class ChunkExtractorWrapper implements ExtractorOutput, TrackOutput
@Override
@Override
public
TrackOutput
track
(
int
id
)
{
public
TrackOutput
track
(
int
id
)
{
Assertions
.
checkState
(!
seenTrack
);
Assertions
.
checkState
(!
seenTrack
||
seenTrackId
==
id
);
seenTrack
=
true
;
seenTrack
=
true
;
seenTrackId
=
id
;
return
this
;
return
this
;
}
}
...
...
library/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.java
View file @
e2ff401e
...
@@ -655,7 +655,9 @@ public class DashManifestParser extends DefaultHandler
...
@@ -655,7 +655,9 @@ public class DashManifestParser extends DefaultHandler
return
MimeTypes
.
getVideoMediaMimeType
(
codecs
);
return
MimeTypes
.
getVideoMediaMimeType
(
codecs
);
}
else
if
(
MimeTypes
.
APPLICATION_RAWCC
.
equals
(
containerMimeType
))
{
}
else
if
(
MimeTypes
.
APPLICATION_RAWCC
.
equals
(
containerMimeType
))
{
if
(
codecs
!=
null
)
{
if
(
codecs
!=
null
)
{
if
(
codecs
.
contains
(
"eia608"
)
||
codecs
.
contains
(
"cea608"
))
{
if
(
codecs
.
contains
(
"cea708"
))
{
return
MimeTypes
.
APPLICATION_CEA708
;
}
else
if
(
codecs
.
contains
(
"eia608"
)
||
codecs
.
contains
(
"cea608"
))
{
return
MimeTypes
.
APPLICATION_CEA608
;
return
MimeTypes
.
APPLICATION_CEA608
;
}
}
}
}
...
...
library/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java
View file @
e2ff401e
...
@@ -257,8 +257,16 @@ import java.util.Locale;
...
@@ -257,8 +257,16 @@ import java.util.Locale;
chunkMediaSequence
=
getLiveNextChunkSequenceNumber
(
previous
.
chunkIndex
,
oldVariantIndex
,
chunkMediaSequence
=
getLiveNextChunkSequenceNumber
(
previous
.
chunkIndex
,
oldVariantIndex
,
newVariantIndex
);
newVariantIndex
);
if
(
chunkMediaSequence
<
mediaPlaylist
.
mediaSequence
)
{
if
(
chunkMediaSequence
<
mediaPlaylist
.
mediaSequence
)
{
fatalError
=
new
BehindLiveWindowException
();
// We try getting the next chunk without adapting in case that's the reason for falling
return
;
// behind the live window.
newVariantIndex
=
oldVariantIndex
;
mediaPlaylist
=
variantPlaylists
[
newVariantIndex
];
chunkMediaSequence
=
getLiveNextChunkSequenceNumber
(
previous
.
chunkIndex
,
oldVariantIndex
,
newVariantIndex
);
if
(
chunkMediaSequence
<
mediaPlaylist
.
mediaSequence
)
{
fatalError
=
new
BehindLiveWindowException
();
return
;
}
}
}
}
}
}
else
{
}
else
{
...
@@ -369,29 +377,29 @@ import java.util.Locale;
...
@@ -369,29 +377,29 @@ import java.util.Locale;
}
}
}
else
if
(
needNewExtractor
)
{
}
else
if
(
needNewExtractor
)
{
// MPEG-2 TS segments, but we need a new extractor.
// 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.
@DefaultStreamReaderFactory
.
WorkaroundFlags
int
workaroundFlags
=
DefaultStreamReaderFactory
.
WORKAROUND_MAP_BY_TYPE
;
String
codecs
=
variants
[
newVariantIndex
].
format
.
codecs
;
if
(!
TextUtils
.
isEmpty
(
codecs
))
{
// Sometimes AAC and H264 streams are declared in TS chunks even though they don't really
// exist. If we know from the codec attribute that they don't exist, then we can explicitly
// ignore them even if they're declared.
if
(!
MimeTypes
.
AUDIO_AAC
.
equals
(
MimeTypes
.
getAudioMediaMimeType
(
codecs
)))
{
workaroundFlags
|=
DefaultStreamReaderFactory
.
WORKAROUND_IGNORE_AAC_STREAM
;
}
if
(!
MimeTypes
.
VIDEO_H264
.
equals
(
MimeTypes
.
getVideoMediaMimeType
(
codecs
)))
{
workaroundFlags
|=
DefaultStreamReaderFactory
.
WORKAROUND_IGNORE_H264_STREAM
;
}
}
isTimestampMaster
=
true
;
isTimestampMaster
=
true
;
if
(
useInitializedExtractor
)
{
if
(
useInitializedExtractor
)
{
extractor
=
lastLoadedInitializationChunk
.
extractor
;
extractor
=
lastLoadedInitializationChunk
.
extractor
;
}
else
{
}
else
{
timestampAdjuster
=
timestampAdjusterProvider
.
getAdjuster
(
timestampAdjuster
=
timestampAdjusterProvider
.
getAdjuster
(
segment
.
discontinuitySequenceNumber
,
startTimeUs
);
segment
.
discontinuitySequenceNumber
,
startTimeUs
);
// This flag ensures the change of pid between streams does not affect the sample queues.
@DefaultStreamReaderFactory
.
Flags
int
esReaderFactoryFlags
=
0
;
String
codecs
=
variants
[
newVariantIndex
].
format
.
codecs
;
if
(!
TextUtils
.
isEmpty
(
codecs
))
{
// Sometimes AAC and H264 streams are declared in TS chunks even though they don't really
// exist. If we know from the codec attribute that they don't exist, then we can
// explicitly ignore them even if they're declared.
if
(!
MimeTypes
.
AUDIO_AAC
.
equals
(
MimeTypes
.
getAudioMediaMimeType
(
codecs
)))
{
esReaderFactoryFlags
|=
DefaultStreamReaderFactory
.
FLAG_IGNORE_AAC_STREAM
;
}
if
(!
MimeTypes
.
VIDEO_H264
.
equals
(
MimeTypes
.
getVideoMediaMimeType
(
codecs
)))
{
esReaderFactoryFlags
|=
DefaultStreamReaderFactory
.
FLAG_IGNORE_H264_STREAM
;
}
}
extractor
=
new
TsExtractor
(
timestampAdjuster
,
extractor
=
new
TsExtractor
(
timestampAdjuster
,
new
DefaultStreamReaderFactory
(
workaroundFlags
)
);
new
DefaultStreamReaderFactory
(
esReaderFactoryFlags
),
true
);
}
}
}
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.
...
...
library/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java
View file @
e2ff401e
...
@@ -328,7 +328,7 @@ import java.util.List;
...
@@ -328,7 +328,7 @@ import java.util.List;
sampleStreamWrappers
=
new
HlsSampleStreamWrapper
[]
{
sampleStreamWrappers
=
new
HlsSampleStreamWrapper
[]
{
buildSampleStreamWrapper
(
C
.
TRACK_TYPE_DEFAULT
,
baseUri
,
variants
,
null
,
null
)};
buildSampleStreamWrapper
(
C
.
TRACK_TYPE_DEFAULT
,
baseUri
,
variants
,
null
,
null
)};
pendingPrepareCount
=
1
;
pendingPrepareCount
=
1
;
sampleStreamWrappers
[
0
].
prepare
();
sampleStreamWrappers
[
0
].
continuePreparing
();
return
;
return
;
}
}
...
@@ -369,16 +369,16 @@ import java.util.List;
...
@@ -369,16 +369,16 @@ import java.util.List;
selectedVariants
.
toArray
(
variants
);
selectedVariants
.
toArray
(
variants
);
HlsSampleStreamWrapper
sampleStreamWrapper
=
buildSampleStreamWrapper
(
C
.
TRACK_TYPE_DEFAULT
,
HlsSampleStreamWrapper
sampleStreamWrapper
=
buildSampleStreamWrapper
(
C
.
TRACK_TYPE_DEFAULT
,
baseUri
,
variants
,
masterPlaylist
.
muxedAudioFormat
,
masterPlaylist
.
muxedCaptionFormat
);
baseUri
,
variants
,
masterPlaylist
.
muxedAudioFormat
,
masterPlaylist
.
muxedCaptionFormat
);
sampleStreamWrapper
.
prepare
();
sampleStreamWrappers
[
currentWrapperIndex
++]
=
sampleStreamWrapper
;
sampleStreamWrappers
[
currentWrapperIndex
++]
=
sampleStreamWrapper
;
sampleStreamWrapper
.
continuePreparing
();
}
}
// Build audio stream wrappers.
// Build audio stream wrappers.
for
(
int
i
=
0
;
i
<
audioVariants
.
size
();
i
++)
{
for
(
int
i
=
0
;
i
<
audioVariants
.
size
();
i
++)
{
HlsSampleStreamWrapper
sampleStreamWrapper
=
buildSampleStreamWrapper
(
C
.
TRACK_TYPE_AUDIO
,
HlsSampleStreamWrapper
sampleStreamWrapper
=
buildSampleStreamWrapper
(
C
.
TRACK_TYPE_AUDIO
,
baseUri
,
new
HlsMasterPlaylist
.
HlsUrl
[]
{
audioVariants
.
get
(
i
)},
null
,
null
);
baseUri
,
new
HlsMasterPlaylist
.
HlsUrl
[]
{
audioVariants
.
get
(
i
)},
null
,
null
);
sampleStreamWrapper
.
prepare
();
sampleStreamWrappers
[
currentWrapperIndex
++]
=
sampleStreamWrapper
;
sampleStreamWrappers
[
currentWrapperIndex
++]
=
sampleStreamWrapper
;
sampleStreamWrapper
.
continuePreparing
();
}
}
// Build subtitle stream wrappers.
// Build subtitle stream wrappers.
...
...
library/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java
View file @
e2ff401e
...
@@ -144,8 +144,10 @@ import java.util.LinkedList;
...
@@ -144,8 +144,10 @@ import java.util.LinkedList;
pendingResetPositionUs
=
positionUs
;
pendingResetPositionUs
=
positionUs
;
}
}
public
void
prepare
()
{
public
void
continuePreparing
()
{
continueLoading
(
lastSeekPositionUs
);
if
(!
prepared
)
{
continueLoading
(
lastSeekPositionUs
);
}
}
}
/**
/**
...
@@ -154,7 +156,8 @@ import java.util.LinkedList;
...
@@ -154,7 +156,8 @@ import java.util.LinkedList;
*/
*/
public
void
prepareSingleTrack
(
Format
format
)
{
public
void
prepareSingleTrack
(
Format
format
)
{
track
(
0
).
format
(
format
);
track
(
0
).
format
(
format
);
endTracks
();
sampleQueuesBuilt
=
true
;
maybeFinishPrepare
();
}
}
public
void
maybeThrowPrepareError
()
throws
IOException
{
public
void
maybeThrowPrepareError
()
throws
IOException
{
...
...
library/src/main/java/com/google/android/exoplayer2/upstream/DefaultHttpDataSource.java
View file @
e2ff401e
...
@@ -413,11 +413,16 @@ public class DefaultHttpDataSource implements HttpDataSource {
...
@@ -413,11 +413,16 @@ public class DefaultHttpDataSource implements HttpDataSource {
connection
.
setInstanceFollowRedirects
(
followRedirects
);
connection
.
setInstanceFollowRedirects
(
followRedirects
);
connection
.
setDoOutput
(
postBody
!=
null
);
connection
.
setDoOutput
(
postBody
!=
null
);
if
(
postBody
!=
null
)
{
if
(
postBody
!=
null
)
{
connection
.
setFixedLengthStreamingMode
(
postBody
.
length
);
connection
.
setRequestMethod
(
"POST"
);
connection
.
connect
();
if
(
postBody
.
length
==
0
)
{
OutputStream
os
=
connection
.
getOutputStream
();
connection
.
connect
();
os
.
write
(
postBody
);
}
else
{
os
.
close
();
connection
.
setFixedLengthStreamingMode
(
postBody
.
length
);
connection
.
connect
();
OutputStream
os
=
connection
.
getOutputStream
();
os
.
write
(
postBody
);
os
.
close
();
}
}
else
{
}
else
{
connection
.
connect
();
connection
.
connect
();
}
}
...
...
library/src/main/java/com/google/android/exoplayer2/util/MimeTypes.java
View file @
e2ff401e
...
@@ -65,6 +65,7 @@ public final class MimeTypes {
...
@@ -65,6 +65,7 @@ public final class MimeTypes {
public
static
final
String
APPLICATION_WEBM
=
BASE_TYPE_APPLICATION
+
"/webm"
;
public
static
final
String
APPLICATION_WEBM
=
BASE_TYPE_APPLICATION
+
"/webm"
;
public
static
final
String
APPLICATION_ID3
=
BASE_TYPE_APPLICATION
+
"/id3"
;
public
static
final
String
APPLICATION_ID3
=
BASE_TYPE_APPLICATION
+
"/id3"
;
public
static
final
String
APPLICATION_CEA608
=
BASE_TYPE_APPLICATION
+
"/cea-608"
;
public
static
final
String
APPLICATION_CEA608
=
BASE_TYPE_APPLICATION
+
"/cea-608"
;
public
static
final
String
APPLICATION_CEA708
=
BASE_TYPE_APPLICATION
+
"/cea-708"
;
public
static
final
String
APPLICATION_SUBRIP
=
BASE_TYPE_APPLICATION
+
"/x-subrip"
;
public
static
final
String
APPLICATION_SUBRIP
=
BASE_TYPE_APPLICATION
+
"/x-subrip"
;
public
static
final
String
APPLICATION_TTML
=
BASE_TYPE_APPLICATION
+
"/ttml+xml"
;
public
static
final
String
APPLICATION_TTML
=
BASE_TYPE_APPLICATION
+
"/ttml+xml"
;
public
static
final
String
APPLICATION_M3U8
=
BASE_TYPE_APPLICATION
+
"/x-mpegURL"
;
public
static
final
String
APPLICATION_M3U8
=
BASE_TYPE_APPLICATION
+
"/x-mpegURL"
;
...
...
playbacktests/src/main/AndroidManifest.xml
View file @
e2ff401e
...
@@ -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
2
"
android:versionCode=
"200
3
"
android:versionName=
"2.0.
2
"
>
android:versionName=
"2.0.
3
"
>
<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"
/>
...
...
testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeExtractorOutput.java
View file @
e2ff401e
...
@@ -23,7 +23,6 @@ import java.io.File;
...
@@ -23,7 +23,6 @@ import java.io.File;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.io.PrintWriter
;
import
java.io.PrintWriter
;
import
junit.framework.Assert
;
import
junit.framework.Assert
;
import
junit.framework.TestCase
;
/**
/**
* A fake {@link ExtractorOutput}.
* A fake {@link ExtractorOutput}.
...
@@ -37,8 +36,6 @@ public final class FakeExtractorOutput implements ExtractorOutput, Dumper.Dumpab
...
@@ -37,8 +36,6 @@ public final class FakeExtractorOutput implements ExtractorOutput, Dumper.Dumpab
*/
*/
private
static
final
boolean
WRITE_DUMP
=
false
;
private
static
final
boolean
WRITE_DUMP
=
false
;
private
final
boolean
allowDuplicateTrackIds
;
public
final
SparseArray
<
FakeTrackOutput
>
trackOutputs
;
public
final
SparseArray
<
FakeTrackOutput
>
trackOutputs
;
public
int
numberOfTracks
;
public
int
numberOfTracks
;
...
@@ -46,11 +43,6 @@ public final class FakeExtractorOutput implements ExtractorOutput, Dumper.Dumpab
...
@@ -46,11 +43,6 @@ public final class FakeExtractorOutput implements ExtractorOutput, Dumper.Dumpab
public
SeekMap
seekMap
;
public
SeekMap
seekMap
;
public
FakeExtractorOutput
()
{
public
FakeExtractorOutput
()
{
this
(
false
);
}
public
FakeExtractorOutput
(
boolean
allowDuplicateTrackIds
)
{
this
.
allowDuplicateTrackIds
=
allowDuplicateTrackIds
;
trackOutputs
=
new
SparseArray
<>();
trackOutputs
=
new
SparseArray
<>();
}
}
...
@@ -58,11 +50,10 @@ public final class FakeExtractorOutput implements ExtractorOutput, Dumper.Dumpab
...
@@ -58,11 +50,10 @@ public final class FakeExtractorOutput implements ExtractorOutput, Dumper.Dumpab
public
FakeTrackOutput
track
(
int
trackId
)
{
public
FakeTrackOutput
track
(
int
trackId
)
{
FakeTrackOutput
output
=
trackOutputs
.
get
(
trackId
);
FakeTrackOutput
output
=
trackOutputs
.
get
(
trackId
);
if
(
output
==
null
)
{
if
(
output
==
null
)
{
Assert
.
assertFalse
(
tracksEnded
);
numberOfTracks
++;
numberOfTracks
++;
output
=
new
FakeTrackOutput
();
output
=
new
FakeTrackOutput
();
trackOutputs
.
put
(
trackId
,
output
);
trackOutputs
.
put
(
trackId
,
output
);
}
else
{
TestCase
.
assertTrue
(
"Duplicate track id: "
+
trackId
,
allowDuplicateTrackIds
);
}
}
return
output
;
return
output
;
}
}
...
...
testutils/src/main/java/com/google/android/exoplayer2/testutil/TestUtil.java
View file @
e2ff401e
...
@@ -267,8 +267,8 @@ public class TestUtil {
...
@@ -267,8 +267,8 @@ public class TestUtil {
*/
*/
public
static
FakeExtractorOutput
assertOutput
(
Extractor
extractor
,
String
sampleFile
,
public
static
FakeExtractorOutput
assertOutput
(
Extractor
extractor
,
String
sampleFile
,
byte
[]
fileData
,
Instrumentation
instrumentation
,
boolean
simulateIOErrors
,
byte
[]
fileData
,
Instrumentation
instrumentation
,
boolean
simulateIOErrors
,
boolean
simulateUnknownLength
,
boolean
simulateUnknownLength
,
boolean
simulatePartialReads
)
throws
IOException
,
boolean
simulatePartialReads
)
throws
IOException
,
InterruptedException
{
InterruptedException
{
FakeExtractorInput
input
=
new
FakeExtractorInput
.
Builder
().
setData
(
fileData
)
FakeExtractorInput
input
=
new
FakeExtractorInput
.
Builder
().
setData
(
fileData
)
.
setSimulateIOErrors
(
simulateIOErrors
)
.
setSimulateIOErrors
(
simulateIOErrors
)
.
setSimulateUnknownLength
(
simulateUnknownLength
)
.
setSimulateUnknownLength
(
simulateUnknownLength
)
...
...
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