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
f9030987
authored
Apr 25, 2017
by
Oliver Woodman
Browse files
Options
_('Browse Files')
Download
Plain Diff
Merge branch 'dev-v2' of persistent-
https://github.com/google/ExoPlayer
into dev-v2
parents
51de6e53
fb88087a
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
824 additions
and
127 deletions
extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.java
library/core/src/androidTest/java/com/google/android/exoplayer2/FormatTest.java
library/core/src/main/java/com/google/android/exoplayer2/C.java
library/core/src/main/java/com/google/android/exoplayer2/Format.java
library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java
library/core/src/main/java/com/google/android/exoplayer2/extractor/DefaultExtractorsFactory.java
library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java
library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java
library/core/src/main/java/com/google/android/exoplayer2/video/ColorInfo.java
library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java
library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java
library/hls/src/androidTest/java/com/google/android/exoplayer2/source/hls/playlist/HlsMediaPlaylistParserTest.java
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMasterPlaylist.java
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMediaPlaylist.java
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylist.java
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistTracker.java
library/ui/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java
library/ui/src/main/res/values/attrs.xml
extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.java
View file @
f9030987
...
...
@@ -262,11 +262,11 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
return
false
;
}
// Drop the frame if we're joining and are more than 30ms late, or if we have the next frame
// and that's also late. Else we'll render what we have.
if
((
joiningDeadlineMs
!=
C
.
TIME_UNSET
&&
outputBuffer
.
timeUs
<
positionUs
-
30000
)
||
(
nextOutputBuffer
!=
null
&&
!
nextOutputBuffer
.
isEndOfStream
()
&&
nextOutputBuffer
.
timeUs
<
positionU
s
))
{
final
long
nextOutputBufferTimeUs
=
nextOutputBuffer
!=
null
&&
!
nextOutputBuffer
.
isEndOfStream
()
?
nextOutputBuffer
.
timeUs
:
C
.
TIME_UNSET
;
if
(
shouldDropOutputBuffer
(
outputBuffer
.
timeUs
,
nextOutputBufferTimeUs
,
positionUs
,
joiningDeadlineM
s
))
{
dropBuffer
();
return
true
;
}
...
...
@@ -280,6 +280,25 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
return
false
;
}
/**
* Returns whether the current frame should be dropped.
*
* @param outputBufferTimeUs The timestamp of the current output buffer.
* @param nextOutputBufferTimeUs The timestamp of the next output buffer or
* {@link TIME_UNSET} if the next output buffer is unavailable.
* @param positionUs The current playback position.
* @param joiningDeadlineMs The joining deadline.
* @return Returns whether to drop the current output buffer.
*/
protected
boolean
shouldDropOutputBuffer
(
long
outputBufferTimeUs
,
long
nextOutputBufferTimeUs
,
long
positionUs
,
long
joiningDeadlineMs
)
{
// Drop the frame if we're joining and are more than 30ms late, or if we have the next frame
// and that's also late. Else we'll render what we have.
return
(
joiningDeadlineMs
!=
C
.
TIME_UNSET
&&
outputBufferTimeUs
<
positionUs
-
30000
)
||
(
nextOutputBufferTimeUs
!=
C
.
TIME_UNSET
&&
nextOutputBufferTimeUs
<
positionUs
);
}
private
void
renderBuffer
()
{
int
bufferMode
=
outputBuffer
.
mode
;
boolean
renderRgb
=
bufferMode
==
VpxDecoder
.
OUTPUT_MODE_RGB
&&
surface
!=
null
;
...
...
@@ -445,13 +464,16 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
protected
void
onPositionReset
(
long
positionUs
,
boolean
joining
)
{
inputStreamEnded
=
false
;
outputStreamEnded
=
false
;
renderedFirstFrame
=
false
;
clearRenderedFirstFrame
()
;
consecutiveDroppedFrameCount
=
0
;
if
(
decoder
!=
null
)
{
flushDecoder
();
}
joiningDeadlineMs
=
joining
&&
allowedJoiningTimeMs
>
0
?
(
SystemClock
.
elapsedRealtime
()
+
allowedJoiningTimeMs
)
:
C
.
TIME_UNSET
;
if
(
joining
)
{
setJoiningDeadlineMs
();
}
else
{
joiningDeadlineMs
=
C
.
TIME_UNSET
;
}
}
@Override
...
...
@@ -473,6 +495,7 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
format
=
null
;
waitingForKeys
=
false
;
clearReportedVideoSize
();
clearRenderedFirstFrame
();
try
{
releaseDecoder
();
}
finally
{
...
...
@@ -549,28 +572,44 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
private
void
setOutput
(
Surface
surface
,
VpxOutputBufferRenderer
outputBufferRenderer
)
{
// At most one output may be non-null. Both may be null if the output is being cleared.
Assertions
.
checkState
(
surface
==
null
||
outputBufferRenderer
==
null
);
// We only need to update the decoder if the output has changed.
if
(
this
.
surface
!=
surface
||
this
.
outputBufferRenderer
!=
outputBufferRenderer
)
{
// The output has changed.
this
.
surface
=
surface
;
this
.
outputBufferRenderer
=
outputBufferRenderer
;
outputMode
=
outputBufferRenderer
!=
null
?
VpxDecoder
.
OUTPUT_MODE_YUV
:
surface
!=
null
?
VpxDecoder
.
OUTPUT_MODE_RGB
:
VpxDecoder
.
OUTPUT_MODE_NONE
;
// If outputMode is OUTPUT_MODE_NONE we leave the mode of the underlying decoder unchanged in
// anticipation that a subsequent output will likely be of the same type as the one that was
// set previously.
if
(
decoder
!=
null
&&
outputMode
!=
VpxDecoder
.
OUTPUT_MODE_NONE
)
{
decoder
.
setOutputMode
(
outputMode
);
if
(
outputMode
!=
VpxDecoder
.
OUTPUT_MODE_NONE
)
{
if
(
decoder
!=
null
)
{
decoder
.
setOutputMode
(
outputMode
);
}
// If we know the video size, report it again immediately.
maybeRenotifyVideoSizeChanged
();
// We haven't rendered to the new output yet.
clearRenderedFirstFrame
();
if
(
getState
()
==
STATE_STARTED
)
{
setJoiningDeadlineMs
();
}
}
else
{
// The output has been removed. We leave the outputMode of the underlying decoder unchanged
// in anticipation that a subsequent output will likely be of the same type.
clearReportedVideoSize
();
clearRenderedFirstFrame
();
}
}
else
if
(
outputMode
!=
VpxDecoder
.
OUTPUT_MODE_NONE
)
{
// The output is unchanged and non-null. If we know the video size and/or have already
// rendered to the output, report these again immediately.
maybeRenotifyVideoSizeChanged
();
maybeRenotifyRenderedFirstFrame
();
}
// Clear state so that we always call the event listener with the video size and when a frame
// is rendered, even if the output hasn't changed.
renderedFirstFrame
=
false
;
clearReportedVideoSize
();
}
private
void
clearReportedVideoSize
()
{
reportedWidth
=
Format
.
NO_VALUE
;
reportedHeight
=
Format
.
NO_VALUE
;
private
void
setJoiningDeadlineMs
()
{
joiningDeadlineMs
=
allowedJoiningTimeMs
>
0
?
(
SystemClock
.
elapsedRealtime
()
+
allowedJoiningTimeMs
)
:
C
.
TIME_UNSET
;
}
private
void
clearRenderedFirstFrame
()
{
renderedFirstFrame
=
false
;
}
private
void
maybeNotifyRenderedFirstFrame
()
{
...
...
@@ -580,6 +619,17 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
}
}
private
void
maybeRenotifyRenderedFirstFrame
()
{
if
(
renderedFirstFrame
)
{
eventDispatcher
.
renderedFirstFrame
(
surface
);
}
}
private
void
clearReportedVideoSize
()
{
reportedWidth
=
Format
.
NO_VALUE
;
reportedHeight
=
Format
.
NO_VALUE
;
}
private
void
maybeNotifyVideoSizeChanged
(
int
width
,
int
height
)
{
if
(
reportedWidth
!=
width
||
reportedHeight
!=
height
)
{
reportedWidth
=
width
;
...
...
@@ -588,6 +638,12 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
}
}
private
void
maybeRenotifyVideoSizeChanged
()
{
if
(
reportedWidth
!=
Format
.
NO_VALUE
||
reportedHeight
!=
Format
.
NO_VALUE
)
{
eventDispatcher
.
videoSizeChanged
(
reportedWidth
,
reportedHeight
,
0
,
1
);
}
}
private
void
maybeNotifyDroppedFrames
()
{
if
(
droppedFrames
>
0
)
{
long
now
=
SystemClock
.
elapsedRealtime
();
...
...
library/core/src/androidTest/java/com/google/android/exoplayer2/FormatTest.java
View file @
f9030987
...
...
@@ -29,6 +29,7 @@ import com.google.android.exoplayer2.metadata.id3.TextInformationFrame;
import
com.google.android.exoplayer2.testutil.TestUtil
;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
com.google.android.exoplayer2.util.Util
;
import
com.google.android.exoplayer2.video.ColorInfo
;
import
java.nio.ByteBuffer
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
...
...
@@ -61,11 +62,13 @@ public final class FormatTest extends TestCase {
Metadata
metadata
=
new
Metadata
(
new
TextInformationFrame
(
"id1"
,
"description1"
,
"value1"
),
new
TextInformationFrame
(
"id2"
,
"description2"
,
"value2"
));
ColorInfo
colorInfo
=
new
ColorInfo
(
C
.
COLOR_SPACE_BT709
,
C
.
COLOR_RANGE_LIMITED
,
C
.
COLOR_TRANSFER_SDR
,
new
byte
[]
{
1
,
2
,
3
,
4
,
5
,
6
,
7
});
Format
formatToParcel
=
new
Format
(
"id"
,
MimeTypes
.
VIDEO_MP4
,
MimeTypes
.
VIDEO_H264
,
null
,
1024
,
2048
,
1920
,
1080
,
24
,
90
,
2
,
projectionData
,
C
.
STEREO_MODE_TOP_BOTTOM
,
6
,
44100
,
C
.
ENCODING_PCM_24BIT
,
1001
,
1002
,
0
,
"und"
,
Format
.
NO_VALUE
,
Format
.
OFFSET_SAMPLE_RELATIV
E
,
INIT_DATA
,
drmInitData
,
metadata
);
1024
,
2048
,
1920
,
1080
,
24
,
90
,
2
,
projectionData
,
C
.
STEREO_MODE_TOP_BOTTOM
,
colorInfo
,
6
,
44100
,
C
.
ENCODING_PCM_24BIT
,
1001
,
1002
,
0
,
"und"
,
Format
.
NO_VALU
E
,
Format
.
OFFSET_SAMPLE_RELATIVE
,
INIT_DATA
,
drmInitData
,
metadata
);
Parcel
parcel
=
Parcel
.
obtain
();
formatToParcel
.
writeToParcel
(
parcel
,
0
);
...
...
library/core/src/main/java/com/google/android/exoplayer2/C.java
View file @
f9030987
...
...
@@ -20,6 +20,7 @@ import android.content.Context;
import
android.media.AudioFormat
;
import
android.media.AudioManager
;
import
android.media.MediaCodec
;
import
android.media.MediaFormat
;
import
android.support.annotation.IntDef
;
import
android.view.Surface
;
import
com.google.android.exoplayer2.util.Util
;
...
...
@@ -555,6 +556,67 @@ public final class C {
public
static
final
int
STEREO_MODE_STEREO_MESH
=
3
;
/**
* Video colorspaces.
*/
@Retention
(
RetentionPolicy
.
SOURCE
)
@IntDef
({
Format
.
NO_VALUE
,
COLOR_SPACE_BT709
,
COLOR_SPACE_BT601
,
COLOR_SPACE_BT2020
})
public
@interface
ColorSpace
{}
/**
* @see MediaFormat#COLOR_STANDARD_BT709
*/
@SuppressWarnings
(
"InlinedApi"
)
public
static
final
int
COLOR_SPACE_BT709
=
MediaFormat
.
COLOR_STANDARD_BT709
;
/**
* @see MediaFormat#COLOR_STANDARD_BT601_PAL
*/
@SuppressWarnings
(
"InlinedApi"
)
public
static
final
int
COLOR_SPACE_BT601
=
MediaFormat
.
COLOR_STANDARD_BT601_PAL
;
/**
* @see MediaFormat#COLOR_STANDARD_BT2020
*/
@SuppressWarnings
(
"InlinedApi"
)
public
static
final
int
COLOR_SPACE_BT2020
=
MediaFormat
.
COLOR_STANDARD_BT2020
;
/**
* Video color transfer characteristics.
*/
@Retention
(
RetentionPolicy
.
SOURCE
)
@IntDef
({
Format
.
NO_VALUE
,
COLOR_TRANSFER_SDR
,
COLOR_TRANSFER_ST2084
,
COLOR_TRANSFER_HLG
})
public
@interface
ColorTransfer
{}
/**
* @see MediaFormat#COLOR_TRANSFER_SDR_VIDEO
*/
@SuppressWarnings
(
"InlinedApi"
)
public
static
final
int
COLOR_TRANSFER_SDR
=
MediaFormat
.
COLOR_TRANSFER_SDR_VIDEO
;
/**
* @see MediaFormat#COLOR_TRANSFER_ST2084
*/
@SuppressWarnings
(
"InlinedApi"
)
public
static
final
int
COLOR_TRANSFER_ST2084
=
MediaFormat
.
COLOR_TRANSFER_ST2084
;
/**
* @see MediaFormat#COLOR_TRANSFER_HLG
*/
@SuppressWarnings
(
"InlinedApi"
)
public
static
final
int
COLOR_TRANSFER_HLG
=
MediaFormat
.
COLOR_TRANSFER_HLG
;
/**
* Video color range.
*/
@Retention
(
RetentionPolicy
.
SOURCE
)
@IntDef
({
Format
.
NO_VALUE
,
COLOR_RANGE_LIMITED
,
COLOR_RANGE_FULL
})
public
@interface
ColorRange
{}
/**
* @see MediaFormat#COLOR_RANGE_LIMITED
*/
@SuppressWarnings
(
"InlinedApi"
)
public
static
final
int
COLOR_RANGE_LIMITED
=
MediaFormat
.
COLOR_RANGE_LIMITED
;
/**
* @see MediaFormat#COLOR_RANGE_FULL
*/
@SuppressWarnings
(
"InlinedApi"
)
public
static
final
int
COLOR_RANGE_FULL
=
MediaFormat
.
COLOR_RANGE_FULL
;
/**
* Priority for media playback.
*
* <p>Larger values indicate higher priorities.
...
...
library/core/src/main/java/com/google/android/exoplayer2/Format.java
View file @
f9030987
...
...
@@ -24,6 +24,7 @@ import com.google.android.exoplayer2.drm.DrmInitData;
import
com.google.android.exoplayer2.metadata.Metadata
;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
com.google.android.exoplayer2.util.Util
;
import
com.google.android.exoplayer2.video.ColorInfo
;
import
java.nio.ByteBuffer
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
...
...
@@ -128,6 +129,10 @@ public final class Format implements Parcelable {
* The projection data for 360/VR video, or null if not applicable.
*/
public
final
byte
[]
projectionData
;
/**
* The color metadata associated with the video, helps with accurate color reproduction.
*/
public
final
ColorInfo
colorInfo
;
// Audio specific.
...
...
@@ -192,7 +197,7 @@ public final class Format implements Parcelable {
String
sampleMimeType
,
String
codecs
,
int
bitrate
,
int
width
,
int
height
,
float
frameRate
,
List
<
byte
[]>
initializationData
,
@C
.
SelectionFlags
int
selectionFlags
)
{
return
new
Format
(
id
,
containerMimeType
,
sampleMimeType
,
codecs
,
bitrate
,
NO_VALUE
,
width
,
height
,
frameRate
,
NO_VALUE
,
NO_VALUE
,
null
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
height
,
frameRate
,
NO_VALUE
,
NO_VALUE
,
null
,
NO_VALUE
,
null
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
selectionFlags
,
null
,
NO_VALUE
,
OFFSET_SAMPLE_RELATIVE
,
initializationData
,
null
,
null
);
}
...
...
@@ -210,17 +215,18 @@ public final class Format implements Parcelable {
DrmInitData
drmInitData
)
{
return
createVideoSampleFormat
(
id
,
sampleMimeType
,
codecs
,
bitrate
,
maxInputSize
,
width
,
height
,
frameRate
,
initializationData
,
rotationDegrees
,
pixelWidthHeightRatio
,
null
,
NO_VALUE
,
drmInitData
);
NO_VALUE
,
null
,
drmInitData
);
}
public
static
Format
createVideoSampleFormat
(
String
id
,
String
sampleMimeType
,
String
codecs
,
int
bitrate
,
int
maxInputSize
,
int
width
,
int
height
,
float
frameRate
,
List
<
byte
[]>
initializationData
,
int
rotationDegrees
,
float
pixelWidthHeightRatio
,
byte
[]
projectionData
,
@C
.
StereoMode
int
stereoMode
,
DrmInitData
drmInitData
)
{
byte
[]
projectionData
,
@C
.
StereoMode
int
stereoMode
,
ColorInfo
colorInfo
,
DrmInitData
drmInitData
)
{
return
new
Format
(
id
,
null
,
sampleMimeType
,
codecs
,
bitrate
,
maxInputSize
,
width
,
height
,
frameRate
,
rotationDegrees
,
pixelWidthHeightRatio
,
projectionData
,
stereoMode
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
0
,
null
,
NO_VALUE
,
OFFSET_SAMPLE_RELATIV
E
,
initializationData
,
drmInitData
,
null
);
frameRate
,
rotationDegrees
,
pixelWidthHeightRatio
,
projectionData
,
stereoMode
,
colorInfo
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
0
,
null
,
NO_VALU
E
,
OFFSET_SAMPLE_RELATIVE
,
initializationData
,
drmInitData
,
null
);
}
// Audio.
...
...
@@ -229,8 +235,8 @@ public final class Format implements Parcelable {
String
sampleMimeType
,
String
codecs
,
int
bitrate
,
int
channelCount
,
int
sampleRate
,
List
<
byte
[]>
initializationData
,
@C
.
SelectionFlags
int
selectionFlags
,
String
language
)
{
return
new
Format
(
id
,
containerMimeType
,
sampleMimeType
,
codecs
,
bitrate
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
null
,
NO_VALUE
,
channelCount
,
sampleRate
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
selectionFlags
,
language
,
NO_VALUE
,
OFFSET_SAMPLE_RELATIVE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
null
,
NO_VALUE
,
null
,
channelCount
,
sampleRate
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
selectionFlags
,
language
,
NO_VALUE
,
OFFSET_SAMPLE_RELATIVE
,
initializationData
,
null
,
null
);
}
...
...
@@ -257,7 +263,7 @@ public final class Format implements Parcelable {
List
<
byte
[]>
initializationData
,
DrmInitData
drmInitData
,
@C
.
SelectionFlags
int
selectionFlags
,
String
language
,
Metadata
metadata
)
{
return
new
Format
(
id
,
null
,
sampleMimeType
,
codecs
,
bitrate
,
maxInputSize
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
null
,
NO_VALUE
,
channelCount
,
sampleRate
,
pcmEncoding
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
null
,
NO_VALUE
,
null
,
channelCount
,
sampleRate
,
pcmEncoding
,
encoderDelay
,
encoderPadding
,
selectionFlags
,
language
,
NO_VALUE
,
OFFSET_SAMPLE_RELATIVE
,
initializationData
,
drmInitData
,
metadata
);
}
...
...
@@ -275,8 +281,8 @@ public final class Format implements Parcelable {
String
sampleMimeType
,
String
codecs
,
int
bitrate
,
@C
.
SelectionFlags
int
selectionFlags
,
String
language
,
int
accessibilityChannel
)
{
return
new
Format
(
id
,
containerMimeType
,
sampleMimeType
,
codecs
,
bitrate
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
null
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
selectionFlags
,
language
,
accessibilityChannel
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
null
,
NO_VALUE
,
null
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
selectionFlags
,
language
,
accessibilityChannel
,
OFFSET_SAMPLE_RELATIVE
,
null
,
null
,
null
);
}
...
...
@@ -305,7 +311,7 @@ public final class Format implements Parcelable {
int
accessibilityChannel
,
DrmInitData
drmInitData
,
long
subsampleOffsetUs
,
List
<
byte
[]>
initializationData
)
{
return
new
Format
(
id
,
null
,
sampleMimeType
,
codecs
,
bitrate
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
null
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
null
,
NO_VALUE
,
null
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
selectionFlags
,
language
,
accessibilityChannel
,
subsampleOffsetUs
,
initializationData
,
drmInitData
,
null
);
}
...
...
@@ -315,7 +321,7 @@ public final class Format implements Parcelable {
public
static
Format
createImageSampleFormat
(
String
id
,
String
sampleMimeType
,
String
codecs
,
int
bitrate
,
List
<
byte
[]>
initializationData
,
String
language
,
DrmInitData
drmInitData
)
{
return
new
Format
(
id
,
null
,
sampleMimeType
,
codecs
,
bitrate
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
null
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
null
,
NO_VALUE
,
null
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
0
,
language
,
NO_VALUE
,
OFFSET_SAMPLE_RELATIVE
,
initializationData
,
drmInitData
,
null
);
}
...
...
@@ -326,7 +332,7 @@ public final class Format implements Parcelable {
String
sampleMimeType
,
String
codecs
,
int
bitrate
,
@C
.
SelectionFlags
int
selectionFlags
,
String
language
)
{
return
new
Format
(
id
,
containerMimeType
,
sampleMimeType
,
codecs
,
bitrate
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
null
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
null
,
NO_VALUE
,
null
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
selectionFlags
,
language
,
NO_VALUE
,
OFFSET_SAMPLE_RELATIVE
,
null
,
null
,
null
);
}
...
...
@@ -334,22 +340,22 @@ public final class Format implements Parcelable {
public
static
Format
createSampleFormat
(
String
id
,
String
sampleMimeType
,
long
subsampleOffsetUs
)
{
return
new
Format
(
id
,
null
,
sampleMimeType
,
null
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
null
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
null
,
NO_VALUE
,
null
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
0
,
null
,
NO_VALUE
,
subsampleOffsetUs
,
null
,
null
,
null
);
}
public
static
Format
createSampleFormat
(
String
id
,
String
sampleMimeType
,
String
codecs
,
int
bitrate
,
DrmInitData
drmInitData
)
{
return
new
Format
(
id
,
null
,
sampleMimeType
,
codecs
,
bitrate
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
null
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
null
,
NO_VALUE
,
null
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
NO_VALUE
,
0
,
null
,
NO_VALUE
,
OFFSET_SAMPLE_RELATIVE
,
null
,
drmInitData
,
null
);
}
/* package */
Format
(
String
id
,
String
containerMimeType
,
String
sampleMimeType
,
String
codecs
,
int
bitrate
,
int
maxInputSize
,
int
width
,
int
height
,
float
frameRate
,
int
rotationDegrees
,
float
pixelWidthHeightRatio
,
byte
[]
projectionData
,
@C
.
StereoMode
int
stereoMode
,
int
channelCount
,
int
sampleRate
,
@C
.
PcmEncoding
int
pcmEncoding
,
int
encoderDelay
,
int
encoderPadding
,
@C
.
SelectionFlags
int
selectionFlags
,
String
language
,
ColorInfo
colorInfo
,
int
channelCount
,
int
sampleRate
,
@C
.
PcmEncoding
int
pcmEncoding
,
int
encoder
Delay
,
int
encoder
Padding
,
@C
.
SelectionFlags
int
selectionFlags
,
String
language
,
int
accessibilityChannel
,
long
subsampleOffsetUs
,
List
<
byte
[]>
initializationData
,
DrmInitData
drmInitData
,
Metadata
metadata
)
{
this
.
id
=
id
;
...
...
@@ -365,6 +371,7 @@ public final class Format implements Parcelable {
this
.
pixelWidthHeightRatio
=
pixelWidthHeightRatio
;
this
.
projectionData
=
projectionData
;
this
.
stereoMode
=
stereoMode
;
this
.
colorInfo
=
colorInfo
;
this
.
channelCount
=
channelCount
;
this
.
sampleRate
=
sampleRate
;
this
.
pcmEncoding
=
pcmEncoding
;
...
...
@@ -396,6 +403,7 @@ public final class Format implements Parcelable {
boolean
hasProjectionData
=
in
.
readInt
()
!=
0
;
projectionData
=
hasProjectionData
?
in
.
createByteArray
()
:
null
;
stereoMode
=
in
.
readInt
();
colorInfo
=
in
.
readParcelable
(
ColorInfo
.
class
.
getClassLoader
());
channelCount
=
in
.
readInt
();
sampleRate
=
in
.
readInt
();
pcmEncoding
=
in
.
readInt
();
...
...
@@ -417,26 +425,26 @@ public final class Format implements Parcelable {
public
Format
copyWithMaxInputSize
(
int
maxInputSize
)
{
return
new
Format
(
id
,
containerMimeType
,
sampleMimeType
,
codecs
,
bitrate
,
maxInputSize
,
width
,
height
,
frameRate
,
rotationDegrees
,
pixelWidthHeightRatio
,
projectionData
,
stereoMode
,
c
hannelCount
,
sampleRate
,
pcmEncoding
,
encoderDelay
,
encoderPadding
,
selectionFlags
,
language
,
accessibilityChannel
,
subsampleOffsetUs
,
initializationData
,
drmInitData
,
metadata
);
stereoMode
,
c
olorInfo
,
channelCount
,
sampleRate
,
pcmEncoding
,
encoderDelay
,
encoderPadding
,
selectionFlags
,
language
,
accessibilityChannel
,
subsampleOffsetUs
,
initializationData
,
drmInitData
,
metadata
);
}
public
Format
copyWithSubsampleOffsetUs
(
long
subsampleOffsetUs
)
{
return
new
Format
(
id
,
containerMimeType
,
sampleMimeType
,
codecs
,
bitrate
,
maxInputSize
,
width
,
height
,
frameRate
,
rotationDegrees
,
pixelWidthHeightRatio
,
projectionData
,
stereoMode
,
c
hannelCount
,
sampleRate
,
pcmEncoding
,
encoderDelay
,
encoderPadding
,
selectionFlags
,
language
,
accessibilityChannel
,
subsampleOffsetUs
,
initializationData
,
drmInitData
,
metadata
);
stereoMode
,
c
olorInfo
,
channelCount
,
sampleRate
,
pcmEncoding
,
encoderDelay
,
encoderPadding
,
selectionFlags
,
language
,
accessibilityChannel
,
subsampleOffsetUs
,
initializationData
,
drmInitData
,
metadata
);
}
public
Format
copyWithContainerInfo
(
String
id
,
String
codecs
,
int
bitrate
,
int
width
,
int
height
,
@C
.
SelectionFlags
int
selectionFlags
,
String
language
)
{
return
new
Format
(
id
,
containerMimeType
,
sampleMimeType
,
codecs
,
bitrate
,
maxInputSize
,
width
,
height
,
frameRate
,
rotationDegrees
,
pixelWidthHeightRatio
,
projectionData
,
stereoMode
,
c
hannelCount
,
sampleRate
,
pcmEncoding
,
encoderDelay
,
encoderPadding
,
selectionFlags
,
language
,
accessibilityChannel
,
subsampleOffsetUs
,
initializationData
,
drmInitData
,
metadata
);
stereoMode
,
c
olorInfo
,
channelCount
,
sampleRate
,
pcmEncoding
,
encoderDelay
,
encoderPadding
,
selectionFlags
,
language
,
accessibilityChannel
,
subsampleOffsetUs
,
initializationData
,
drmInitData
,
metadata
);
}
@SuppressWarnings
(
"ReferenceEquality"
)
...
...
@@ -455,33 +463,33 @@ public final class Format implements Parcelable {
:
this
.
drmInitData
;
return
new
Format
(
id
,
containerMimeType
,
sampleMimeType
,
codecs
,
bitrate
,
maxInputSize
,
width
,
height
,
frameRate
,
rotationDegrees
,
pixelWidthHeightRatio
,
projectionData
,
stereoMode
,
c
hannelCount
,
sampleRate
,
pcmEncoding
,
encoderDelay
,
encoderPadding
,
selectionFlags
,
language
,
accessibilityChannel
,
subsampleOffsetUs
,
initializationData
,
drmInit
Data
,
metadata
);
c
olorInfo
,
channelCount
,
sampleRate
,
pcmEncoding
,
encoderDelay
,
encoderPadding
,
selectionFlags
,
language
,
accessibilityChannel
,
subsampleOffsetUs
,
initialization
Data
,
drmInitData
,
metadata
);
}
public
Format
copyWithGaplessInfo
(
int
encoderDelay
,
int
encoderPadding
)
{
return
new
Format
(
id
,
containerMimeType
,
sampleMimeType
,
codecs
,
bitrate
,
maxInputSize
,
width
,
height
,
frameRate
,
rotationDegrees
,
pixelWidthHeightRatio
,
projectionData
,
stereoMode
,
c
hannelCount
,
sampleRate
,
pcmEncoding
,
encoderDelay
,
encoderPadding
,
selectionFlags
,
language
,
accessibilityChannel
,
subsampleOffsetUs
,
initializationData
,
drmInitData
,
metadata
);
stereoMode
,
c
olorInfo
,
channelCount
,
sampleRate
,
pcmEncoding
,
encoderDelay
,
encoderPadding
,
selectionFlags
,
language
,
accessibilityChannel
,
subsampleOffsetUs
,
initializationData
,
drmInitData
,
metadata
);
}
public
Format
copyWithDrmInitData
(
DrmInitData
drmInitData
)
{
return
new
Format
(
id
,
containerMimeType
,
sampleMimeType
,
codecs
,
bitrate
,
maxInputSize
,
width
,
height
,
frameRate
,
rotationDegrees
,
pixelWidthHeightRatio
,
projectionData
,
stereoMode
,
c
hannelCount
,
sampleRate
,
pcmEncoding
,
encoderDelay
,
encoderPadding
,
selectionFlags
,
language
,
accessibilityChannel
,
subsampleOffsetUs
,
initializationData
,
drmInitData
,
metadata
);
stereoMode
,
c
olorInfo
,
channelCount
,
sampleRate
,
pcmEncoding
,
encoderDelay
,
encoderPadding
,
selectionFlags
,
language
,
accessibilityChannel
,
subsampleOffsetUs
,
initializationData
,
drmInitData
,
metadata
);
}
public
Format
copyWithMetadata
(
Metadata
metadata
)
{
return
new
Format
(
id
,
containerMimeType
,
sampleMimeType
,
codecs
,
bitrate
,
maxInputSize
,
width
,
height
,
frameRate
,
rotationDegrees
,
pixelWidthHeightRatio
,
projectionData
,
stereoMode
,
c
hannelCount
,
sampleRate
,
pcmEncoding
,
encoderDelay
,
encoderPadding
,
selectionFlags
,
language
,
accessibilityChannel
,
subsampleOffsetUs
,
initializationData
,
drmInitData
,
metadata
);
stereoMode
,
c
olorInfo
,
channelCount
,
sampleRate
,
pcmEncoding
,
encoderDelay
,
encoderPadding
,
selectionFlags
,
language
,
accessibilityChannel
,
subsampleOffsetUs
,
initializationData
,
drmInitData
,
metadata
);
}
/**
...
...
@@ -513,6 +521,7 @@ public final class Format implements Parcelable {
for
(
int
i
=
0
;
i
<
initializationData
.
size
();
i
++)
{
format
.
setByteBuffer
(
"csd-"
+
i
,
ByteBuffer
.
wrap
(
initializationData
.
get
(
i
)));
}
maybeSetColorInfoV24
(
format
,
colorInfo
);
return
format
;
}
...
...
@@ -569,6 +578,7 @@ public final class Format implements Parcelable {
||
!
Util
.
areEqual
(
codecs
,
other
.
codecs
)
||
!
Util
.
areEqual
(
drmInitData
,
other
.
drmInitData
)
||
!
Util
.
areEqual
(
metadata
,
other
.
metadata
)
||
!
Util
.
areEqual
(
colorInfo
,
other
.
colorInfo
)
||
!
Arrays
.
equals
(
projectionData
,
other
.
projectionData
)
||
initializationData
.
size
()
!=
other
.
initializationData
.
size
())
{
return
false
;
...
...
@@ -581,6 +591,17 @@ public final class Format implements Parcelable {
return
true
;
}
@TargetApi
(
24
)
private
static
void
maybeSetColorInfoV24
(
MediaFormat
format
,
ColorInfo
colorInfo
)
{
if
(
colorInfo
==
null
)
{
return
;
}
maybeSetIntegerV16
(
format
,
MediaFormat
.
KEY_COLOR_TRANSFER
,
colorInfo
.
colorTransfer
);
maybeSetIntegerV16
(
format
,
MediaFormat
.
KEY_COLOR_STANDARD
,
colorInfo
.
colorSpace
);
maybeSetIntegerV16
(
format
,
MediaFormat
.
KEY_COLOR_RANGE
,
colorInfo
.
colorRange
);
maybeSetByteBufferV16
(
format
,
MediaFormat
.
KEY_HDR_STATIC_INFO
,
colorInfo
.
hdrStaticInfo
);
}
@TargetApi
(
16
)
private
static
void
maybeSetStringV16
(
MediaFormat
format
,
String
key
,
String
value
)
{
if
(
value
!=
null
)
{
...
...
@@ -602,6 +623,13 @@ public final class Format implements Parcelable {
}
}
@TargetApi
(
16
)
private
static
void
maybeSetByteBufferV16
(
MediaFormat
format
,
String
key
,
byte
[]
value
)
{
if
(
value
!=
null
)
{
format
.
setByteBuffer
(
key
,
ByteBuffer
.
wrap
(
value
));
}
}
// Utility methods
/**
...
...
@@ -659,6 +687,7 @@ public final class Format implements Parcelable {
dest
.
writeByteArray
(
projectionData
);
}
dest
.
writeInt
(
stereoMode
);
dest
.
writeParcelable
(
colorInfo
,
flags
);
dest
.
writeInt
(
channelCount
);
dest
.
writeInt
(
sampleRate
);
dest
.
writeInt
(
pcmEncoding
);
...
...
library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java
View file @
f9030987
...
...
@@ -240,6 +240,18 @@ public class SimpleExoPlayer implements ExoPlayer {
}
/**
* Clears the {@link Surface} onto which video is being rendered if it matches the one passed.
* Else does nothing.
*
* @param surface The surface to clear.
*/
public
void
clearVideoSurface
(
Surface
surface
)
{
if
(
surface
!=
null
&&
surface
==
this
.
surface
)
{
setVideoSurface
(
null
);
}
}
/**
* Sets the {@link SurfaceHolder} that holds the {@link Surface} onto which video will be
* rendered. The player will track the lifecycle of the surface automatically.
*
...
...
@@ -257,13 +269,35 @@ public class SimpleExoPlayer implements ExoPlayer {
}
/**
* Clears the {@link SurfaceHolder} that holds the {@link Surface} onto which video is being
* rendered if it matches the one passed. Else does nothing.
*
* @param surfaceHolder The surface holder to clear.
*/
public
void
clearVideoSurfaceHolder
(
SurfaceHolder
surfaceHolder
)
{
if
(
surfaceHolder
!=
null
&&
surfaceHolder
==
this
.
surfaceHolder
)
{
setVideoSurfaceHolder
(
null
);
}
}
/**
* Sets the {@link SurfaceView} onto which video will be rendered. The player will track the
* lifecycle of the surface automatically.
*
* @param surfaceView The surface view.
*/
public
void
setVideoSurfaceView
(
SurfaceView
surfaceView
)
{
setVideoSurfaceHolder
(
surfaceView
.
getHolder
());
setVideoSurfaceHolder
(
surfaceView
==
null
?
null
:
surfaceView
.
getHolder
());
}
/**
* Clears the {@link SurfaceView} onto which video is being rendered if it matches the one passed.
* Else does nothing.
*
* @param surfaceView The texture view to clear.
*/
public
void
clearVideoSurfaceView
(
SurfaceView
surfaceView
)
{
clearVideoSurfaceHolder
(
surfaceView
==
null
?
null
:
surfaceView
.
getHolder
());
}
/**
...
...
@@ -288,6 +322,18 @@ public class SimpleExoPlayer implements ExoPlayer {
}
/**
* Clears the {@link TextureView} onto which video is being rendered if it matches the one passed.
* Else does nothing.
*
* @param textureView The texture view to clear.
*/
public
void
clearVideoTextureView
(
TextureView
textureView
)
{
if
(
textureView
!=
null
&&
textureView
==
this
.
textureView
)
{
setVideoTextureView
(
null
);
}
}
/**
* Sets the stream type for audio playback (see {@link C.StreamType} and
* {@link android.media.AudioTrack#AudioTrack(int, int, int, int, int, int)}). If the stream type
* is not set, audio renderers use {@link C#STREAM_TYPE_DEFAULT}.
...
...
@@ -405,30 +451,34 @@ public class SimpleExoPlayer implements ExoPlayer {
}
/**
*
Sets a listener to receive debug events from the video renderer
.
*
Clears the listener receiving video events if it matches the one passed. Else does nothing
.
*
* @param listener The listener.
* @param listener The listener
to clear
.
*/
public
void
setVideoDebugListener
(
VideoRendererEventListener
listener
)
{
videoDebugListener
=
listener
;
public
void
clearVideoListener
(
VideoListener
listener
)
{
if
(
videoListener
==
listener
)
{
videoListener
=
null
;
}
}
/**
* Sets a
listener to receive debug events from the audio renderer
.
* Sets a
n output to receive text events
.
*
* @param
listener The listener
.
* @param
output The output
.
*/
public
void
set
AudioDebugListener
(
AudioRendererEventListener
listener
)
{
audioDebugListener
=
listener
;
public
void
set
TextOutput
(
TextRenderer
.
Output
output
)
{
textOutput
=
output
;
}
/**
*
Sets an output to receive text events
.
*
Clears the output receiving text events if it matches the one passed. Else does nothing
.
*
* @param output The output.
* @param output The output
to clear
.
*/
public
void
setTextOutput
(
TextRenderer
.
Output
output
)
{
textOutput
=
output
;
public
void
clearTextOutput
(
TextRenderer
.
Output
output
)
{
if
(
textOutput
==
output
)
{
textOutput
=
null
;
}
}
/**
...
...
@@ -440,6 +490,35 @@ public class SimpleExoPlayer implements ExoPlayer {
metadataOutput
=
output
;
}
/**
* Clears the output receiving metadata events if it matches the one passed. Else does nothing.
*
* @param output The output to clear.
*/
public
void
clearMetadataOutput
(
MetadataRenderer
.
Output
output
)
{
if
(
metadataOutput
==
output
)
{
metadataOutput
=
null
;
}
}
/**
* Sets a listener to receive debug events from the video renderer.
*
* @param listener The listener.
*/
public
void
setVideoDebugListener
(
VideoRendererEventListener
listener
)
{
videoDebugListener
=
listener
;
}
/**
* Sets a listener to receive debug events from the audio renderer.
*
* @param listener The listener.
*/
public
void
setAudioDebugListener
(
AudioRendererEventListener
listener
)
{
audioDebugListener
=
listener
;
}
// ExoPlayer implementation
@Override
...
...
library/core/src/main/java/com/google/android/exoplayer2/extractor/DefaultExtractorsFactory.java
View file @
f9030987
...
...
@@ -64,11 +64,25 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory {
FLAC_EXTRACTOR_CONSTRUCTOR
=
flacExtractorConstructor
;
}
private
@MatroskaExtractor
.
Flags
int
matroskaFlags
;
private
@FragmentedMp4Extractor
.
Flags
int
fragmentedMp4Flags
;
private
@Mp3Extractor
.
Flags
int
mp3Flags
;
private
@DefaultTsPayloadReaderFactory
.
Flags
int
tsFlags
;
/**
* Sets flags for {@link MatroskaExtractor} instances created by the factory.
*
* @see MatroskaExtractor#MatroskaExtractor(int)
* @param flags The flags to use.
* @return The factory, for convenience.
*/
public
synchronized
DefaultExtractorsFactory
setMatroskaExtractorFlags
(
@MatroskaExtractor
.
Flags
int
flags
)
{
this
.
matroskaFlags
=
flags
;
return
this
;
}
/**
* Sets flags for {@link FragmentedMp4Extractor} instances created by the factory.
*
* @see FragmentedMp4Extractor#FragmentedMp4Extractor(int)
...
...
@@ -110,7 +124,7 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory {
@Override
public
synchronized
Extractor
[]
createExtractors
()
{
Extractor
[]
extractors
=
new
Extractor
[
FLAC_EXTRACTOR_CONSTRUCTOR
==
null
?
11
:
12
];
extractors
[
0
]
=
new
MatroskaExtractor
();
extractors
[
0
]
=
new
MatroskaExtractor
(
matroskaFlags
);
extractors
[
1
]
=
new
FragmentedMp4Extractor
(
fragmentedMp4Flags
);
extractors
[
2
]
=
new
Mp4Extractor
();
extractors
[
3
]
=
new
Mp3Extractor
(
mp3Flags
);
...
...
library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java
View file @
f9030987
...
...
@@ -15,6 +15,7 @@
*/
package
com
.
google
.
android
.
exoplayer2
.
extractor
.
mkv
;
import
android.support.annotation.IntDef
;
import
android.util.SparseArray
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.Format
;
...
...
@@ -36,8 +37,11 @@ import com.google.android.exoplayer2.util.NalUnitUtil;
import
com.google.android.exoplayer2.util.ParsableByteArray
;
import
com.google.android.exoplayer2.util.Util
;
import
com.google.android.exoplayer2.video.AvcConfig
;
import
com.google.android.exoplayer2.video.ColorInfo
;
import
com.google.android.exoplayer2.video.HevcConfig
;
import
java.io.IOException
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteOrder
;
import
java.util.ArrayList
;
...
...
@@ -64,6 +68,22 @@ public final class MatroskaExtractor implements Extractor {
};
/**
* Flags controlling the behavior of the extractor.
*/
@Retention
(
RetentionPolicy
.
SOURCE
)
@IntDef
(
flag
=
true
,
value
=
{
FLAG_DISABLE_SEEK_FOR_CUES
})
public
@interface
Flags
{}
/**
* Flag to disable seeking for cues.
* <p>
* Normally (i.e. when this flag is not set) the extractor will seek to the cues element if its
* position is specified in the seek head and if it's after the first cluster. Setting this flag
* disables seeking to the cues element. If the cues element is after the first cluster then the
* media is treated as being unseekable.
*/
public
static
final
int
FLAG_DISABLE_SEEK_FOR_CUES
=
1
;
private
static
final
int
UNSET_ENTRY_ID
=
-
1
;
private
static
final
int
BLOCK_STATE_START
=
0
;
...
...
@@ -168,6 +188,23 @@ public final class MatroskaExtractor implements Extractor {
private
static
final
int
ID_PROJECTION
=
0x7670
;
private
static
final
int
ID_PROJECTION_PRIVATE
=
0x7672
;
private
static
final
int
ID_STEREO_MODE
=
0x53B8
;
private
static
final
int
ID_COLOUR
=
0x55B0
;
private
static
final
int
ID_COLOUR_RANGE
=
0x55B9
;
private
static
final
int
ID_COLOUR_TRANSFER
=
0x55BA
;
private
static
final
int
ID_COLOUR_PRIMARIES
=
0x55BB
;
private
static
final
int
ID_MAX_CLL
=
0x55BC
;
private
static
final
int
ID_MAX_FALL
=
0x55BD
;
private
static
final
int
ID_MASTERING_METADATA
=
0x55D0
;
private
static
final
int
ID_PRIMARY_R_CHROMATICITY_X
=
0x55D1
;
private
static
final
int
ID_PRIMARY_R_CHROMATICITY_Y
=
0x55D2
;
private
static
final
int
ID_PRIMARY_G_CHROMATICITY_X
=
0x55D3
;
private
static
final
int
ID_PRIMARY_G_CHROMATICITY_Y
=
0x55D4
;
private
static
final
int
ID_PRIMARY_B_CHROMATICITY_X
=
0x55D5
;
private
static
final
int
ID_PRIMARY_B_CHROMATICITY_Y
=
0x55D6
;
private
static
final
int
ID_WHITE_POINT_CHROMATICITY_X
=
0x55D7
;
private
static
final
int
ID_WHITE_POINT_CHROMATICITY_Y
=
0x55D8
;
private
static
final
int
ID_LUMNINANCE_MAX
=
0x55D9
;
private
static
final
int
ID_LUMNINANCE_MIN
=
0x55DA
;
private
static
final
int
LACING_NONE
=
0
;
private
static
final
int
LACING_XIPH
=
1
;
...
...
@@ -222,6 +259,7 @@ public final class MatroskaExtractor implements Extractor {
private
final
EbmlReader
reader
;
private
final
VarintReader
varintReader
;
private
final
SparseArray
<
Track
>
tracks
;
private
final
boolean
seekForCuesEnabled
;
// Temporary arrays.
private
final
ParsableByteArray
nalStartCode
;
...
...
@@ -289,12 +327,17 @@ public final class MatroskaExtractor implements Extractor {
private
ExtractorOutput
extractorOutput
;
public
MatroskaExtractor
()
{
this
(
new
DefaultEbmlReader
());
this
(
0
);
}
public
MatroskaExtractor
(
@Flags
int
flags
)
{
this
(
new
DefaultEbmlReader
(),
flags
);
}
/* package */
MatroskaExtractor
(
EbmlReader
reader
)
{
/* package */
MatroskaExtractor
(
EbmlReader
reader
,
@Flags
int
flags
)
{
this
.
reader
=
reader
;
this
.
reader
.
init
(
new
InnerEbmlReaderOutput
());
seekForCuesEnabled
=
(
flags
&
FLAG_DISABLE_SEEK_FOR_CUES
)
==
0
;
varintReader
=
new
VarintReader
();
tracks
=
new
SparseArray
<>();
scratch
=
new
ParsableByteArray
(
4
);
...
...
@@ -368,6 +411,8 @@ public final class MatroskaExtractor implements Extractor {
case
ID_CUE_TRACK_POSITIONS:
case
ID_BLOCK_GROUP:
case
ID_PROJECTION:
case
ID_COLOUR:
case
ID_MASTERING_METADATA:
return
EbmlReader
.
TYPE_MASTER
;
case
ID_EBML_READ_VERSION:
case
ID_DOC_TYPE_READ_VERSION:
...
...
@@ -398,6 +443,11 @@ public final class MatroskaExtractor implements Extractor {
case
ID_CUE_CLUSTER_POSITION:
case
ID_REFERENCE_BLOCK:
case
ID_STEREO_MODE:
case
ID_COLOUR_RANGE:
case
ID_COLOUR_TRANSFER:
case
ID_COLOUR_PRIMARIES:
case
ID_MAX_CLL:
case
ID_MAX_FALL:
return
EbmlReader
.
TYPE_UNSIGNED_INT
;
case
ID_DOC_TYPE:
case
ID_CODEC_ID:
...
...
@@ -413,6 +463,16 @@ public final class MatroskaExtractor implements Extractor {
return
EbmlReader
.
TYPE_BINARY
;
case
ID_DURATION:
case
ID_SAMPLING_FREQUENCY:
case
ID_PRIMARY_R_CHROMATICITY_X:
case
ID_PRIMARY_R_CHROMATICITY_Y:
case
ID_PRIMARY_G_CHROMATICITY_X:
case
ID_PRIMARY_G_CHROMATICITY_Y:
case
ID_PRIMARY_B_CHROMATICITY_X:
case
ID_PRIMARY_B_CHROMATICITY_Y:
case
ID_WHITE_POINT_CHROMATICITY_X:
case
ID_WHITE_POINT_CHROMATICITY_Y:
case
ID_LUMNINANCE_MAX:
case
ID_LUMNINANCE_MIN:
return
EbmlReader
.
TYPE_FLOAT
;
default
:
return
EbmlReader
.
TYPE_UNKNOWN
;
...
...
@@ -448,7 +508,7 @@ public final class MatroskaExtractor implements Extractor {
case
ID_CLUSTER:
if
(!
sentSeekMap
)
{
// We need to build cues before parsing the cluster.
if
(
cuesContentPosition
!=
C
.
POSITION_UNSET
)
{
if
(
seekForCuesEnabled
&&
cuesContentPosition
!=
C
.
POSITION_UNSET
)
{
// We know where the Cues element is located. Seek to request it.
seekForCues
=
true
;
}
else
{
...
...
@@ -471,6 +531,9 @@ public final class MatroskaExtractor implements Extractor {
case
ID_TRACK_ENTRY:
currentTrack
=
new
Track
();
break
;
case
ID_MASTERING_METADATA:
currentTrack
.
hasColorInfo
=
true
;
break
;
default
:
break
;
}
...
...
@@ -681,6 +744,60 @@ public final class MatroskaExtractor implements Extractor {
break
;
}
break
;
case
ID_COLOUR_PRIMARIES:
currentTrack
.
hasColorInfo
=
true
;
switch
((
int
)
value
)
{
case
1
:
currentTrack
.
colorSpace
=
C
.
COLOR_SPACE_BT709
;
break
;
case
4
:
// BT.470M.
case
5
:
// BT.470BG.
case
6
:
// SMPTE 170M.
case
7
:
// SMPTE 240M.
currentTrack
.
colorSpace
=
C
.
COLOR_SPACE_BT601
;
break
;
case
9
:
currentTrack
.
colorSpace
=
C
.
COLOR_SPACE_BT2020
;
break
;
default
:
break
;
}
break
;
case
ID_COLOUR_TRANSFER:
switch
((
int
)
value
)
{
case
1
:
// BT.709.
case
6
:
// SMPTE 170M.
case
7
:
// SMPTE 240M.
currentTrack
.
colorTransfer
=
C
.
COLOR_TRANSFER_SDR
;
break
;
case
16
:
currentTrack
.
colorTransfer
=
C
.
COLOR_TRANSFER_ST2084
;
break
;
case
18
:
currentTrack
.
colorTransfer
=
C
.
COLOR_TRANSFER_HLG
;
break
;
default
:
break
;
}
break
;
case
ID_COLOUR_RANGE:
switch
((
int
)
value
)
{
case
1
:
// Broadcast range.
currentTrack
.
colorRange
=
C
.
COLOR_RANGE_LIMITED
;
break
;
case
2
:
currentTrack
.
colorRange
=
C
.
COLOR_RANGE_FULL
;
break
;
default
:
break
;
}
break
;
case
ID_MAX_CLL:
currentTrack
.
maxContentLuminance
=
(
int
)
value
;
break
;
case
ID_MAX_FALL:
currentTrack
.
maxFrameAverageLuminance
=
(
int
)
value
;
break
;
default
:
break
;
}
...
...
@@ -694,6 +811,36 @@ public final class MatroskaExtractor implements Extractor {
case
ID_SAMPLING_FREQUENCY:
currentTrack
.
sampleRate
=
(
int
)
value
;
break
;
case
ID_PRIMARY_R_CHROMATICITY_X:
currentTrack
.
primaryRChromaticityX
=
(
float
)
value
;
break
;
case
ID_PRIMARY_R_CHROMATICITY_Y:
currentTrack
.
primaryRChromaticityY
=
(
float
)
value
;
break
;
case
ID_PRIMARY_G_CHROMATICITY_X:
currentTrack
.
primaryGChromaticityX
=
(
float
)
value
;
break
;
case
ID_PRIMARY_G_CHROMATICITY_Y:
currentTrack
.
primaryGChromaticityY
=
(
float
)
value
;
break
;
case
ID_PRIMARY_B_CHROMATICITY_X:
currentTrack
.
primaryBChromaticityX
=
(
float
)
value
;
break
;
case
ID_PRIMARY_B_CHROMATICITY_Y:
currentTrack
.
primaryBChromaticityY
=
(
float
)
value
;
break
;
case
ID_WHITE_POINT_CHROMATICITY_X:
currentTrack
.
whitePointChromaticityX
=
(
float
)
value
;
break
;
case
ID_WHITE_POINT_CHROMATICITY_Y:
currentTrack
.
whitePointChromaticityY
=
(
float
)
value
;
break
;
case
ID_LUMNINANCE_MAX:
currentTrack
.
maxMasteringLuminance
=
(
float
)
value
;
break
;
case
ID_LUMNINANCE_MIN:
currentTrack
.
minMasteringLuminance
=
(
float
)
value
;
break
;
default
:
break
;
}
...
...
@@ -1305,6 +1452,16 @@ public final class MatroskaExtractor implements Extractor {
private
static
final
class
Track
{
private
static
final
int
DISPLAY_UNIT_PIXELS
=
0
;
private
static
final
int
MAX_CHROMATICITY
=
50000
;
// Defined in CTA-861.3.
/**
* Default max content light level (CLL) that should be encoded into hdrStaticInfo.
*/
private
static
final
int
DEFAULT_MAX_CLL
=
1000
;
// nits.
/**
* Default frame-average light level (FALL) that should be encoded into hdrStaticInfo.
*/
private
static
final
int
DEFAULT_MAX_FALL
=
200
;
// nits.
// Common elements.
public
String
codecId
;
...
...
@@ -1326,6 +1483,25 @@ public final class MatroskaExtractor implements Extractor {
public
byte
[]
projectionData
=
null
;
@C
.
StereoMode
public
int
stereoMode
=
Format
.
NO_VALUE
;
public
boolean
hasColorInfo
=
false
;
@C
.
ColorSpace
public
int
colorSpace
=
Format
.
NO_VALUE
;
@C
.
ColorTransfer
public
int
colorTransfer
=
Format
.
NO_VALUE
;
@C
.
ColorRange
public
int
colorRange
=
Format
.
NO_VALUE
;
public
int
maxContentLuminance
=
DEFAULT_MAX_CLL
;
public
int
maxFrameAverageLuminance
=
DEFAULT_MAX_FALL
;
public
float
primaryRChromaticityX
=
Format
.
NO_VALUE
;
public
float
primaryRChromaticityY
=
Format
.
NO_VALUE
;
public
float
primaryGChromaticityX
=
Format
.
NO_VALUE
;
public
float
primaryGChromaticityY
=
Format
.
NO_VALUE
;
public
float
primaryBChromaticityX
=
Format
.
NO_VALUE
;
public
float
primaryBChromaticityY
=
Format
.
NO_VALUE
;
public
float
whitePointChromaticityX
=
Format
.
NO_VALUE
;
public
float
whitePointChromaticityY
=
Format
.
NO_VALUE
;
public
float
maxMasteringLuminance
=
Format
.
NO_VALUE
;
public
float
minMasteringLuminance
=
Format
.
NO_VALUE
;
// Audio elements. Initially set to their default values.
public
int
channelCount
=
1
;
...
...
@@ -1495,9 +1671,15 @@ public final class MatroskaExtractor implements Extractor {
if
(
displayWidth
!=
Format
.
NO_VALUE
&&
displayHeight
!=
Format
.
NO_VALUE
)
{
pixelWidthHeightRatio
=
((
float
)
(
height
*
displayWidth
))
/
(
width
*
displayHeight
);
}
ColorInfo
colorInfo
=
null
;
if
(
hasColorInfo
)
{
byte
[]
hdrStaticInfo
=
getHdrStaticInfo
();
colorInfo
=
new
ColorInfo
(
colorSpace
,
colorRange
,
colorTransfer
,
hdrStaticInfo
);
}
format
=
Format
.
createVideoSampleFormat
(
Integer
.
toString
(
trackId
),
mimeType
,
null
,
Format
.
NO_VALUE
,
maxInputSize
,
width
,
height
,
Format
.
NO_VALUE
,
initializationData
,
Format
.
NO_VALUE
,
pixelWidthHeightRatio
,
projectionData
,
stereoMode
,
drmInitData
);
Format
.
NO_VALUE
,
pixelWidthHeightRatio
,
projectionData
,
stereoMode
,
colorInfo
,
drmInitData
);
}
else
if
(
MimeTypes
.
APPLICATION_SUBRIP
.
equals
(
mimeType
))
{
type
=
C
.
TRACK_TYPE_TEXT
;
format
=
Format
.
createTextSampleFormat
(
Integer
.
toString
(
trackId
),
mimeType
,
null
,
...
...
@@ -1517,6 +1699,38 @@ public final class MatroskaExtractor implements Extractor {
}
/**
* Returns the HDR Static Info as defined in CTA-861.3.
*/
private
byte
[]
getHdrStaticInfo
()
{
// Are all fields present.
if
(
primaryRChromaticityX
==
Format
.
NO_VALUE
||
primaryRChromaticityY
==
Format
.
NO_VALUE
||
primaryGChromaticityX
==
Format
.
NO_VALUE
||
primaryGChromaticityY
==
Format
.
NO_VALUE
||
primaryBChromaticityX
==
Format
.
NO_VALUE
||
primaryBChromaticityY
==
Format
.
NO_VALUE
||
whitePointChromaticityX
==
Format
.
NO_VALUE
||
whitePointChromaticityY
==
Format
.
NO_VALUE
||
maxMasteringLuminance
==
Format
.
NO_VALUE
||
minMasteringLuminance
==
Format
.
NO_VALUE
)
{
return
null
;
}
byte
[]
hdrStaticInfoData
=
new
byte
[
25
];
ByteBuffer
hdrStaticInfo
=
ByteBuffer
.
wrap
(
hdrStaticInfoData
);
hdrStaticInfo
.
put
((
byte
)
0
);
// Type.
hdrStaticInfo
.
putShort
((
short
)
((
primaryRChromaticityX
*
MAX_CHROMATICITY
)
+
0.5f
));
hdrStaticInfo
.
putShort
((
short
)
((
primaryRChromaticityY
*
MAX_CHROMATICITY
)
+
0.5f
));
hdrStaticInfo
.
putShort
((
short
)
((
primaryGChromaticityX
*
MAX_CHROMATICITY
)
+
0.5f
));
hdrStaticInfo
.
putShort
((
short
)
((
primaryGChromaticityY
*
MAX_CHROMATICITY
)
+
0.5f
));
hdrStaticInfo
.
putShort
((
short
)
((
primaryBChromaticityX
*
MAX_CHROMATICITY
)
+
0.5f
));
hdrStaticInfo
.
putShort
((
short
)
((
primaryBChromaticityY
*
MAX_CHROMATICITY
)
+
0.5f
));
hdrStaticInfo
.
putShort
((
short
)
((
whitePointChromaticityX
*
MAX_CHROMATICITY
)
+
0.5f
));
hdrStaticInfo
.
putShort
((
short
)
((
whitePointChromaticityY
*
MAX_CHROMATICITY
)
+
0.5f
));
hdrStaticInfo
.
putShort
((
short
)
(
maxMasteringLuminance
+
0.5f
));
hdrStaticInfo
.
putShort
((
short
)
(
minMasteringLuminance
+
0.5f
));
hdrStaticInfo
.
putShort
((
short
)
maxContentLuminance
);
hdrStaticInfo
.
putShort
((
short
)
maxFrameAverageLuminance
);
return
hdrStaticInfoData
;
}
/**
* Builds initialization data for a {@link Format} from FourCC codec private data.
* <p>
* VC1 is the only supported compression type.
...
...
library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java
View file @
f9030987
...
...
@@ -762,7 +762,7 @@ import java.util.List;
out
.
format
=
Format
.
createVideoSampleFormat
(
Integer
.
toString
(
trackId
),
mimeType
,
null
,
Format
.
NO_VALUE
,
Format
.
NO_VALUE
,
width
,
height
,
Format
.
NO_VALUE
,
initializationData
,
rotationDegrees
,
pixelWidthHeightRatio
,
projectionData
,
stereoMode
,
drmInitData
);
rotationDegrees
,
pixelWidthHeightRatio
,
projectionData
,
stereoMode
,
null
,
drmInitData
);
}
/**
...
...
library/core/src/main/java/com/google/android/exoplayer2/video/ColorInfo.java
0 → 100644
View file @
f9030987
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
google
.
android
.
exoplayer2
.
video
;
import
android.os.Parcel
;
import
android.os.Parcelable
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.Format
;
import
java.util.Arrays
;
/**
* Stores color info.
*/
public
final
class
ColorInfo
implements
Parcelable
{
/**
* The color space of the video. Valid values are {@link C#COLOR_SPACE_BT601}, {@link
* C#COLOR_SPACE_BT709}, {@link C#COLOR_SPACE_BT2020} or {@link Format#NO_VALUE} if unknown.
*/
@C
.
ColorSpace
public
final
int
colorSpace
;
/**
* The color range of the video. Valid values are {@link C#COLOR_RANGE_LIMITED}, {@link
* C#COLOR_RANGE_FULL} or {@link Format#NO_VALUE} if unknown.
*/
@C
.
ColorRange
public
final
int
colorRange
;
/**
* The color transfer characteristicks of the video. Valid values are {@link
* C#COLOR_TRANSFER_HLG}, {@link C#COLOR_TRANSFER_ST2084}, {@link C#COLOR_TRANSFER_SDR} or {@link
* Format#NO_VALUE} if unknown.
*/
@C
.
ColorTransfer
public
final
int
colorTransfer
;
/**
* HdrStaticInfo as defined in CTA-861.3.
*/
public
final
byte
[]
hdrStaticInfo
;
// Lazily initialized hashcode.
private
int
hashCode
;
/**
* Constructs the ColorInfo.
*
* @param colorSpace The color space of the video.
* @param colorRange The color range of the video.
* @param colorTransfer The color transfer characteristics of the video.
* @param hdrStaticInfo HdrStaticInfo as defined in CTA-861.3.
*/
public
ColorInfo
(
@C
.
ColorSpace
int
colorSpace
,
@C
.
ColorRange
int
colorRange
,
@C
.
ColorTransfer
int
colorTransfer
,
byte
[]
hdrStaticInfo
)
{
this
.
colorSpace
=
colorSpace
;
this
.
colorRange
=
colorRange
;
this
.
colorTransfer
=
colorTransfer
;
this
.
hdrStaticInfo
=
hdrStaticInfo
;
}
@SuppressWarnings
(
"ResourceType"
)
/* package */
ColorInfo
(
Parcel
in
)
{
colorSpace
=
in
.
readInt
();
colorRange
=
in
.
readInt
();
colorTransfer
=
in
.
readInt
();
boolean
hasHdrStaticInfo
=
in
.
readInt
()
!=
0
;
hdrStaticInfo
=
hasHdrStaticInfo
?
in
.
createByteArray
()
:
null
;
}
// Parcelable implementation.
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
{
return
true
;
}
if
(
obj
==
null
||
getClass
()
!=
obj
.
getClass
())
{
return
false
;
}
ColorInfo
other
=
(
ColorInfo
)
obj
;
if
(
colorSpace
!=
other
.
colorSpace
||
colorRange
!=
other
.
colorRange
||
colorTransfer
!=
other
.
colorTransfer
||
!
Arrays
.
equals
(
hdrStaticInfo
,
other
.
hdrStaticInfo
))
{
return
false
;
}
return
true
;
}
@Override
public
String
toString
()
{
return
"ColorInfo("
+
colorSpace
+
", "
+
colorRange
+
", "
+
colorTransfer
+
", "
+
(
hdrStaticInfo
!=
null
)
+
")"
;
}
@Override
public
int
hashCode
()
{
if
(
hashCode
==
0
)
{
int
result
=
17
;
result
=
31
*
result
+
colorSpace
;
result
=
31
*
result
+
colorRange
;
result
=
31
*
result
+
colorTransfer
;
result
=
31
*
result
+
Arrays
.
hashCode
(
hdrStaticInfo
);
hashCode
=
result
;
}
return
hashCode
;
}
@Override
public
int
describeContents
()
{
return
0
;
}
@Override
public
void
writeToParcel
(
Parcel
dest
,
int
flags
)
{
dest
.
writeInt
(
colorSpace
);
dest
.
writeInt
(
colorRange
);
dest
.
writeInt
(
colorTransfer
);
dest
.
writeInt
(
hdrStaticInfo
!=
null
?
1
:
0
);
if
(
hdrStaticInfo
!=
null
)
{
dest
.
writeByteArray
(
hdrStaticInfo
);
}
}
public
static
final
Parcelable
.
Creator
<
ColorInfo
>
CREATOR
=
new
Parcelable
.
Creator
<
ColorInfo
>()
{
@Override
public
ColorInfo
createFromParcel
(
Parcel
in
)
{
return
new
ColorInfo
(
in
);
}
@Override
public
ColorInfo
[]
newArray
(
int
size
)
{
return
new
ColorInfo
[
0
];
}
};
}
library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java
View file @
f9030987
...
...
@@ -166,7 +166,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
currentPixelWidthHeightRatio
=
Format
.
NO_VALUE
;
pendingPixelWidthHeightRatio
=
Format
.
NO_VALUE
;
scalingMode
=
C
.
VIDEO_SCALING_MODE_DEFAULT
;
clear
Last
ReportedVideoSize
();
clearReportedVideoSize
();
}
@Override
...
...
@@ -229,8 +229,11 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
super
.
onPositionReset
(
positionUs
,
joining
);
clearRenderedFirstFrame
();
consecutiveDroppedFrameCount
=
0
;
joiningDeadlineMs
=
joining
&&
allowedJoiningTimeMs
>
0
?
(
SystemClock
.
elapsedRealtime
()
+
allowedJoiningTimeMs
)
:
C
.
TIME_UNSET
;
if
(
joining
)
{
setJoiningDeadlineMs
();
}
else
{
joiningDeadlineMs
=
C
.
TIME_UNSET
;
}
}
@Override
...
...
@@ -272,7 +275,8 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
currentHeight
=
Format
.
NO_VALUE
;
currentPixelWidthHeightRatio
=
Format
.
NO_VALUE
;
pendingPixelWidthHeightRatio
=
Format
.
NO_VALUE
;
clearLastReportedVideoSize
();
clearReportedVideoSize
();
clearRenderedFirstFrame
();
frameReleaseTimeHelper
.
disable
();
tunnelingOnFrameRenderedListener
=
null
;
try
{
...
...
@@ -312,11 +316,25 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
maybeInitCodec
();
}
}
if
(
surface
!=
null
)
{
// If we know the video size, report it again immediately.
maybeRenotifyVideoSizeChanged
();
// We haven't rendered to the new surface yet.
clearRenderedFirstFrame
();
if
(
state
==
STATE_STARTED
)
{
setJoiningDeadlineMs
();
}
}
else
{
// The surface has been removed.
clearReportedVideoSize
();
clearRenderedFirstFrame
();
}
}
else
if
(
surface
!=
null
)
{
// The surface is unchanged and non-null. If we know the video size and/or have already
// rendered to the surface, report these again immediately.
maybeRenotifyVideoSizeChanged
();
maybeRenotifyRenderedFirstFrame
();
}
// Clear state so that we always call the event listener with the video size and when a frame
// is rendered, even if the surface hasn't changed.
clearRenderedFirstFrame
();
clearLastReportedVideoSize
();
}
@Override
...
...
@@ -521,6 +539,11 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
maybeNotifyRenderedFirstFrame
();
}
private
void
setJoiningDeadlineMs
()
{
joiningDeadlineMs
=
allowedJoiningTimeMs
>
0
?
(
SystemClock
.
elapsedRealtime
()
+
allowedJoiningTimeMs
)
:
C
.
TIME_UNSET
;
}
private
void
clearRenderedFirstFrame
()
{
renderedFirstFrame
=
false
;
// The first frame notification is triggered by renderOutputBuffer or renderOutputBufferV21 for
...
...
@@ -543,7 +566,13 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
}
}
private
void
clearLastReportedVideoSize
()
{
private
void
maybeRenotifyRenderedFirstFrame
()
{
if
(
renderedFirstFrame
)
{
eventDispatcher
.
renderedFirstFrame
(
surface
);
}
}
private
void
clearReportedVideoSize
()
{
reportedWidth
=
Format
.
NO_VALUE
;
reportedHeight
=
Format
.
NO_VALUE
;
reportedPixelWidthHeightRatio
=
Format
.
NO_VALUE
;
...
...
@@ -563,6 +592,13 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
}
}
private
void
maybeRenotifyVideoSizeChanged
()
{
if
(
reportedWidth
!=
Format
.
NO_VALUE
||
reportedHeight
!=
Format
.
NO_VALUE
)
{
eventDispatcher
.
videoSizeChanged
(
currentWidth
,
currentHeight
,
currentUnappliedRotationDegrees
,
currentPixelWidthHeightRatio
);
}
}
private
void
maybeNotifyDroppedFrames
()
{
if
(
droppedFrames
>
0
)
{
long
now
=
SystemClock
.
elapsedRealtime
();
...
...
library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java
View file @
f9030987
...
...
@@ -393,7 +393,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
if
(
MimeTypes
.
APPLICATION_RAWCC
.
equals
(
containerMimeType
))
{
extractor
=
new
RawCcExtractor
(
representation
.
format
);
}
else
if
(
mimeTypeIsWebm
(
containerMimeType
))
{
extractor
=
new
MatroskaExtractor
();
extractor
=
new
MatroskaExtractor
(
MatroskaExtractor
.
FLAG_DISABLE_SEEK_FOR_CUES
);
}
else
{
int
flags
=
0
;
if
(
enableEventMessageTrack
)
{
...
...
library/hls/src/androidTest/java/com/google/android/exoplayer2/source/hls/playlist/HlsMediaPlaylistParserTest.java
View file @
f9030987
...
...
@@ -70,7 +70,6 @@ public class HlsMediaPlaylistParserTest extends TestCase {
try
{
HlsPlaylist
playlist
=
new
HlsPlaylistParser
().
parse
(
playlistUri
,
inputStream
);
assertNotNull
(
playlist
);
assertEquals
(
HlsPlaylist
.
TYPE_MEDIA
,
playlist
.
type
);
HlsMediaPlaylist
mediaPlaylist
=
(
HlsMediaPlaylist
)
playlist
;
assertEquals
(
HlsMediaPlaylist
.
PLAYLIST_TYPE_VOD
,
mediaPlaylist
.
playlistType
);
...
...
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMasterPlaylist.java
View file @
f9030987
...
...
@@ -55,7 +55,7 @@ public final class HlsMasterPlaylist extends HlsPlaylist {
public
HlsMasterPlaylist
(
String
baseUri
,
List
<
HlsUrl
>
variants
,
List
<
HlsUrl
>
audios
,
List
<
HlsUrl
>
subtitles
,
Format
muxedAudioFormat
,
List
<
Format
>
muxedCaptionFormats
)
{
super
(
baseUri
,
HlsPlaylist
.
TYPE_MASTER
);
super
(
baseUri
);
this
.
variants
=
Collections
.
unmodifiableList
(
variants
);
this
.
audios
=
Collections
.
unmodifiableList
(
audios
);
this
.
subtitles
=
Collections
.
unmodifiableList
(
subtitles
);
...
...
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMediaPlaylist.java
View file @
f9030987
...
...
@@ -97,7 +97,7 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
long
startTimeUs
,
boolean
hasDiscontinuitySequence
,
int
discontinuitySequence
,
int
mediaSequence
,
int
version
,
long
targetDurationUs
,
boolean
hasEndTag
,
boolean
hasProgramDateTime
,
Segment
initializationSegment
,
List
<
Segment
>
segments
)
{
super
(
baseUri
,
HlsPlaylist
.
TYPE_MEDIA
);
super
(
baseUri
);
this
.
playlistType
=
playlistType
;
this
.
startTimeUs
=
startTimeUs
;
this
.
hasDiscontinuitySequence
=
hasDiscontinuitySequence
;
...
...
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylist.java
View file @
f9030987
...
...
@@ -15,30 +15,15 @@
*/
package
com
.
google
.
android
.
exoplayer2
.
source
.
hls
.
playlist
;
import
android.support.annotation.IntDef
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
/**
* Represents an HLS playlist.
*/
public
abstract
class
HlsPlaylist
{
/**
* The type of playlist.
*/
@Retention
(
RetentionPolicy
.
SOURCE
)
@IntDef
({
TYPE_MASTER
,
TYPE_MEDIA
})
public
@interface
Type
{}
public
static
final
int
TYPE_MASTER
=
0
;
public
static
final
int
TYPE_MEDIA
=
1
;
public
final
String
baseUri
;
@Type
public
final
int
type
;
protected
HlsPlaylist
(
String
baseUri
,
@Type
int
type
)
{
protected
HlsPlaylist
(
String
baseUri
)
{
this
.
baseUri
=
baseUri
;
this
.
type
=
type
;
}
}
library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistTracker.java
View file @
f9030987
...
...
@@ -477,9 +477,15 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
@Override
public
void
onLoadCompleted
(
ParsingLoadable
<
HlsPlaylist
>
loadable
,
long
elapsedRealtimeMs
,
long
loadDurationMs
)
{
processLoadedPlaylist
((
HlsMediaPlaylist
)
loadable
.
getResult
());
eventDispatcher
.
loadCompleted
(
loadable
.
dataSpec
,
C
.
DATA_TYPE_MANIFEST
,
elapsedRealtimeMs
,
loadDurationMs
,
loadable
.
bytesLoaded
());
HlsPlaylist
result
=
loadable
.
getResult
();
if
(
result
instanceof
HlsMediaPlaylist
)
{
processLoadedPlaylist
((
HlsMediaPlaylist
)
result
);
eventDispatcher
.
loadCompleted
(
loadable
.
dataSpec
,
C
.
DATA_TYPE_MANIFEST
,
elapsedRealtimeMs
,
loadDurationMs
,
loadable
.
bytesLoaded
());
}
else
{
onLoadError
(
loadable
,
elapsedRealtimeMs
,
loadDurationMs
,
new
ParserException
(
"Loaded playlist has unexpected type."
));
}
}
@Override
...
...
library/ui/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java
View file @
f9030987
...
...
@@ -21,6 +21,8 @@ import android.content.res.Resources;
import
android.content.res.TypedArray
;
import
android.graphics.Bitmap
;
import
android.graphics.BitmapFactory
;
import
android.support.annotation.NonNull
;
import
android.support.annotation.Nullable
;
import
android.util.AttributeSet
;
import
android.view.KeyEvent
;
import
android.view.LayoutInflater
;
...
...
@@ -74,12 +76,18 @@ import java.util.List;
* <li>Default: {@code null}</li>
* </ul>
* </li>
* <li><b>{@code use_controller}</b> - Whether
playback controls are displayed
.
* <li><b>{@code use_controller}</b> - Whether
the playback controls can be shown
.
* <ul>
* <li>Corresponding method: {@link #setUseController(boolean)}</li>
* <li>Default: {@code true}</li>
* </ul>
* </li>
* <li><b>{@code hide_on_touch}</b> - Whether the playback controls are hidden by touch events.
* <ul>
* <li>Corresponding method: {@link #setControllerHideOnTouch(boolean)}</li>
* <li>Default: {@code true}</li>
* </ul>
* </li>
* <li><b>{@code resize_mode}</b> - Controls how video and album art is resized within the view.
* Valid values are {@code fit}, {@code fixed_width}, {@code fixed_height} and {@code fill}.
* <ul>
...
...
@@ -190,6 +198,7 @@ public final class SimpleExoPlayerView extends FrameLayout {
private
boolean
useArtwork
;
private
Bitmap
defaultArtwork
;
private
int
controllerShowTimeoutMs
;
private
boolean
controllerHideOnTouch
;
public
SimpleExoPlayerView
(
Context
context
)
{
this
(
context
,
null
);
...
...
@@ -228,6 +237,7 @@ public final class SimpleExoPlayerView extends FrameLayout {
int
surfaceType
=
SURFACE_TYPE_SURFACE_VIEW
;
int
resizeMode
=
AspectRatioFrameLayout
.
RESIZE_MODE_FIT
;
int
controllerShowTimeoutMs
=
PlaybackControlView
.
DEFAULT_SHOW_TIMEOUT_MS
;
boolean
controllerHideOnTouch
=
true
;
if
(
attrs
!=
null
)
{
TypedArray
a
=
context
.
getTheme
().
obtainStyledAttributes
(
attrs
,
R
.
styleable
.
SimpleExoPlayerView
,
0
,
0
);
...
...
@@ -242,6 +252,8 @@ public final class SimpleExoPlayerView extends FrameLayout {
resizeMode
=
a
.
getInt
(
R
.
styleable
.
SimpleExoPlayerView_resize_mode
,
resizeMode
);
controllerShowTimeoutMs
=
a
.
getInt
(
R
.
styleable
.
SimpleExoPlayerView_show_timeout
,
controllerShowTimeoutMs
);
controllerHideOnTouch
=
a
.
getBoolean
(
R
.
styleable
.
SimpleExoPlayerView_hide_on_touch
,
controllerHideOnTouch
);
}
finally
{
a
.
recycle
();
}
...
...
@@ -304,11 +316,36 @@ public final class SimpleExoPlayerView extends FrameLayout {
this
.
controller
=
null
;
}
this
.
controllerShowTimeoutMs
=
controller
!=
null
?
controllerShowTimeoutMs
:
0
;
this
.
controllerHideOnTouch
=
controllerHideOnTouch
;
this
.
useController
=
useController
&&
controller
!=
null
;
hideController
();
}
/**
* Switches the view targeted by a given {@link SimpleExoPlayer}.
*
* @param player The player whose target view is being switched.
* @param oldPlayerView The old view to detach from the player.
* @param newPlayerView The new view to attach to the player.
*/
public
static
void
switchTargetView
(
@NonNull
SimpleExoPlayer
player
,
@Nullable
SimpleExoPlayerView
oldPlayerView
,
@Nullable
SimpleExoPlayerView
newPlayerView
)
{
if
(
oldPlayerView
==
newPlayerView
)
{
return
;
}
// We attach the new view before detaching the old one because this ordering allows the player
// to swap directly from one surface to another, without transitioning through a state where no
// surface is attached. This is significantly more efficient and achieves a more seamless
// transition when using platform provided video decoders.
if
(
newPlayerView
!=
null
)
{
newPlayerView
.
setPlayer
(
player
);
}
if
(
oldPlayerView
!=
null
)
{
oldPlayerView
.
setPlayer
(
null
);
}
}
/**
* Returns the player currently set on this view, or null if no player is set.
*/
public
SimpleExoPlayer
getPlayer
()
{
...
...
@@ -319,6 +356,12 @@ public final class SimpleExoPlayerView extends FrameLayout {
* Set the {@link SimpleExoPlayer} to use. The {@link SimpleExoPlayer#setTextOutput} and
* {@link SimpleExoPlayer#setVideoListener} method of the player will be called and previous
* assignments are overridden.
* <p>
* To transition a {@link SimpleExoPlayer} from targeting one view to another, it's recommended to
* use {@link #switchTargetView(SimpleExoPlayer, SimpleExoPlayerView, SimpleExoPlayerView)} rather
* than this method. If you do wish to use this method directly, be sure to attach the player to
* the new view <em>before</em> calling {@code setPlayer(null)} to detach it from the old one.
* This ordering is significantly more efficient and may allow for more seamless transitions.
*
* @param player The {@link SimpleExoPlayer} to use.
*/
...
...
@@ -327,10 +370,14 @@ public final class SimpleExoPlayerView extends FrameLayout {
return
;
}
if
(
this
.
player
!=
null
)
{
this
.
player
.
setTextOutput
(
null
);
this
.
player
.
setVideoListener
(
null
);
this
.
player
.
removeListener
(
componentListener
);
this
.
player
.
setVideoSurface
(
null
);
this
.
player
.
clearTextOutput
(
componentListener
);
this
.
player
.
clearVideoListener
(
componentListener
);
if
(
surfaceView
instanceof
TextureView
)
{
this
.
player
.
clearVideoTextureView
((
TextureView
)
surfaceView
);
}
else
if
(
surfaceView
instanceof
SurfaceView
)
{
this
.
player
.
clearVideoSurfaceView
((
SurfaceView
)
surfaceView
);
}
}
this
.
player
=
player
;
if
(
useController
)
{
...
...
@@ -346,8 +393,8 @@ public final class SimpleExoPlayerView extends FrameLayout {
player
.
setVideoSurfaceView
((
SurfaceView
)
surfaceView
);
}
player
.
setVideoListener
(
componentListener
);
player
.
addListener
(
componentListener
);
player
.
setTextOutput
(
componentListener
);
player
.
addListener
(
componentListener
);
maybeShowController
(
false
);
updateForCurrentTrackSelections
();
}
else
{
...
...
@@ -407,17 +454,17 @@ public final class SimpleExoPlayerView extends FrameLayout {
}
/**
* Returns whether the playback controls
are enabled
.
* Returns whether the playback controls
can be shown
.
*/
public
boolean
getUseController
()
{
return
useController
;
}
/**
* Sets whether
playback controls are enabled. If set to {@code false} the playback controls are
* never visible and are disconnected from the player.
* Sets whether
the playback controls can be shown. If set to {@code false} the playback controls
*
are
never visible and are disconnected from the player.
*
* @param useController Whether
playback controls should be enabled
.
* @param useController Whether
the playback controls can be shown
.
*/
public
void
setUseController
(
boolean
useController
)
{
Assertions
.
checkState
(!
useController
||
controller
!=
null
);
...
...
@@ -487,6 +534,23 @@ public final class SimpleExoPlayerView extends FrameLayout {
}
/**
* Returns whether the playback controls are hidden by touch events.
*/
public
boolean
getControllerHideOnTouch
()
{
return
controllerHideOnTouch
;
}
/**
* Sets whether the playback controls are hidden by touch events.
*
* @param controllerHideOnTouch Whether the playback controls are hidden by touch events.
*/
public
void
setControllerHideOnTouch
(
boolean
controllerHideOnTouch
)
{
Assertions
.
checkState
(
controller
!=
null
);
this
.
controllerHideOnTouch
=
controllerHideOnTouch
;
}
/**
* Set the {@link PlaybackControlView.VisibilityListener}.
*
* @param listener The listener to be notified about visibility changes.
...
...
@@ -573,10 +637,10 @@ public final class SimpleExoPlayerView extends FrameLayout {
if
(!
useController
||
player
==
null
||
ev
.
getActionMasked
()
!=
MotionEvent
.
ACTION_DOWN
)
{
return
false
;
}
if
(
controller
.
isVisible
())
{
controller
.
hide
();
}
else
{
if
(!
controller
.
isVisible
())
{
maybeShowController
(
true
);
}
else
if
(
controllerHideOnTouch
)
{
controller
.
hide
();
}
return
true
;
}
...
...
library/ui/src/main/res/values/attrs.xml
View file @
f9030987
...
...
@@ -39,11 +39,12 @@
<attr
name=
"use_artwork"
format=
"boolean"
/>
<attr
name=
"default_artwork"
format=
"reference"
/>
<attr
name=
"use_controller"
format=
"boolean"
/>
<attr
name=
"hide_on_touch"
format=
"boolean"
/>
<attr
name=
"resize_mode"
/>
<attr
name=
"surface_type"
/>
<attr
name=
"show_timeout"
/>
<attr
name=
"rewind_increment"
/>
<attr
name=
"fastforward_increment"
/>
<attr
name=
"resize_mode"
/>
<attr
name=
"player_layout_id"
/>
<attr
name=
"controller_layout_id"
/>
</declare-styleable>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment