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
71fd335b
authored
Aug 04, 2020
by
olly
Committed by
kim-vde
Aug 07, 2020
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Simplify output format propagation
PiperOrigin-RevId: 324805335
parent
4d03d308
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
137 additions
and
228 deletions
library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java
library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsCollector.java
library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsListener.java
library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java
library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java
library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java
library/core/src/main/java/com/google/android/exoplayer2/video/VideoRendererEventListener.java
library/core/src/test/java/com/google/android/exoplayer2/analytics/AnalyticsCollectorTest.java
library/core/src/test/java/com/google/android/exoplayer2/audio/MediaCodecAudioRendererTest.java
library/core/src/test/java/com/google/android/exoplayer2/video/MediaCodecVideoRendererTest.java
testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeVideoRenderer.java
library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java
View file @
71fd335b
...
@@ -2188,11 +2188,9 @@ public class SimpleExoPlayer extends BasePlayer
...
@@ -2188,11 +2188,9 @@ public class SimpleExoPlayer extends BasePlayer
}
}
@Override
@Override
public
void
onVideoFrameProcessingOffset
(
public
void
onVideoFrameProcessingOffset
(
long
totalProcessingOffsetUs
,
int
frameCount
)
{
long
totalProcessingOffsetUs
,
int
frameCount
,
Format
format
)
{
for
(
VideoRendererEventListener
videoDebugListener
:
videoDebugListeners
)
{
for
(
VideoRendererEventListener
videoDebugListener
:
videoDebugListeners
)
{
videoDebugListener
.
onVideoFrameProcessingOffset
(
videoDebugListener
.
onVideoFrameProcessingOffset
(
totalProcessingOffsetUs
,
frameCount
);
totalProcessingOffsetUs
,
frameCount
,
format
);
}
}
}
}
...
...
library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsCollector.java
View file @
71fd335b
...
@@ -319,11 +319,10 @@ public class AnalyticsCollector
...
@@ -319,11 +319,10 @@ public class AnalyticsCollector
}
}
@Override
@Override
public
final
void
onVideoFrameProcessingOffset
(
public
final
void
onVideoFrameProcessingOffset
(
long
totalProcessingOffsetUs
,
int
frameCount
)
{
long
totalProcessingOffsetUs
,
int
frameCount
,
Format
format
)
{
EventTime
eventTime
=
generatePlayingMediaPeriodEventTime
();
EventTime
eventTime
=
generatePlayingMediaPeriodEventTime
();
for
(
AnalyticsListener
listener
:
listeners
)
{
for
(
AnalyticsListener
listener
:
listeners
)
{
listener
.
onVideoFrameProcessingOffset
(
eventTime
,
totalProcessingOffsetUs
,
frameCount
,
format
);
listener
.
onVideoFrameProcessingOffset
(
eventTime
,
totalProcessingOffsetUs
,
frameCount
);
}
}
}
}
...
...
library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsListener.java
View file @
71fd335b
...
@@ -591,10 +591,9 @@ public interface AnalyticsListener {
...
@@ -591,10 +591,9 @@ public interface AnalyticsListener {
* @param totalProcessingOffsetUs The sum of the video frame processing offsets for frames
* @param totalProcessingOffsetUs The sum of the video frame processing offsets for frames
* rendered since the last call to this method.
* rendered since the last call to this method.
* @param frameCount The number to samples included in {@code totalProcessingOffsetUs}.
* @param frameCount The number to samples included in {@code totalProcessingOffsetUs}.
* @param format The video {@link Format} being rendered.
*/
*/
default
void
onVideoFrameProcessingOffset
(
default
void
onVideoFrameProcessingOffset
(
EventTime
eventTime
,
long
totalProcessingOffsetUs
,
int
frameCount
,
Format
format
)
{}
EventTime
eventTime
,
long
totalProcessingOffsetUs
,
int
frameCount
)
{}
/**
/**
* Called when a frame is rendered for the first time since setting the surface, or since the
* Called when a frame is rendered for the first time since setting the surface, or since the
...
...
library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java
View file @
71fd335b
...
@@ -91,7 +91,6 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
...
@@ -91,7 +91,6 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
private
boolean
codecNeedsDiscardChannelsWorkaround
;
private
boolean
codecNeedsDiscardChannelsWorkaround
;
private
boolean
codecNeedsEosBufferTimestampWorkaround
;
private
boolean
codecNeedsEosBufferTimestampWorkaround
;
@Nullable
private
Format
codecPassthroughFormat
;
@Nullable
private
Format
codecPassthroughFormat
;
@Nullable
private
Format
inputFormat
;
private
long
currentPositionUs
;
private
long
currentPositionUs
;
private
boolean
allowFirstBufferPositionDiscontinuity
;
private
boolean
allowFirstBufferPositionDiscontinuity
;
private
boolean
allowPositionDiscontinuity
;
private
boolean
allowPositionDiscontinuity
;
...
@@ -379,29 +378,23 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
...
@@ -379,29 +378,23 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
@Override
@Override
protected
void
onInputFormatChanged
(
FormatHolder
formatHolder
)
throws
ExoPlaybackException
{
protected
void
onInputFormatChanged
(
FormatHolder
formatHolder
)
throws
ExoPlaybackException
{
super
.
onInputFormatChanged
(
formatHolder
);
super
.
onInputFormatChanged
(
formatHolder
);
inputFormat
=
formatHolder
.
format
;
eventDispatcher
.
inputFormatChanged
(
formatHolder
.
format
);
eventDispatcher
.
inputFormatChanged
(
inputFormat
);
}
}
@Override
@Override
protected
void
onOutputFormatChanged
(
Format
outputFormat
)
throws
ExoPlaybackException
{
protected
void
onOutputFormatChanged
(
Format
format
,
@Nullable
MediaFormat
mediaFormat
)
configureOutput
(
outputFormat
);
throws
ExoPlaybackException
{
}
@Override
protected
void
configureOutput
(
Format
outputFormat
)
throws
ExoPlaybackException
{
Format
audioSinkInputFormat
;
Format
audioSinkInputFormat
;
@Nullable
int
[]
channelMap
=
null
;
@Nullable
int
[]
channelMap
=
null
;
if
(
codecPassthroughFormat
!=
null
)
{
// Raw codec passthrough
if
(
codecPassthroughFormat
!=
null
)
{
// Raw codec passthrough
audioSinkInputFormat
=
codecPassthroughFormat
;
audioSinkInputFormat
=
codecPassthroughFormat
;
}
else
if
(
getCodec
()
==
null
)
{
// Codec bypass passthrough
}
else
if
(
getCodec
()
==
null
)
{
// Codec bypass passthrough
audioSinkInputFormat
=
outputF
ormat
;
audioSinkInputFormat
=
f
ormat
;
}
else
{
}
else
{
MediaFormat
mediaFormat
=
getCodec
().
getOutputFormat
();
@C
.
PcmEncoding
int
pcmEncoding
;
@C
.
PcmEncoding
int
pcmEncoding
;
if
(
MimeTypes
.
AUDIO_RAW
.
equals
(
outputF
ormat
.
sampleMimeType
))
{
if
(
MimeTypes
.
AUDIO_RAW
.
equals
(
f
ormat
.
sampleMimeType
))
{
// For PCM streams, the encoder passes through int samples despite set to float mode.
// For PCM streams, the encoder passes through int samples despite set to float mode.
pcmEncoding
=
outputF
ormat
.
pcmEncoding
;
pcmEncoding
=
f
ormat
.
pcmEncoding
;
}
else
if
(
Util
.
SDK_INT
>=
24
&&
mediaFormat
.
containsKey
(
MediaFormat
.
KEY_PCM_ENCODING
))
{
}
else
if
(
Util
.
SDK_INT
>=
24
&&
mediaFormat
.
containsKey
(
MediaFormat
.
KEY_PCM_ENCODING
))
{
pcmEncoding
=
mediaFormat
.
getInteger
(
MediaFormat
.
KEY_PCM_ENCODING
);
pcmEncoding
=
mediaFormat
.
getInteger
(
MediaFormat
.
KEY_PCM_ENCODING
);
}
else
if
(
mediaFormat
.
containsKey
(
VIVO_BITS_PER_SAMPLE_KEY
))
{
}
else
if
(
mediaFormat
.
containsKey
(
VIVO_BITS_PER_SAMPLE_KEY
))
{
...
@@ -409,22 +402,25 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
...
@@ -409,22 +402,25 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
}
else
{
}
else
{
// If the format is anything other than PCM then we assume that the audio decoder will
// If the format is anything other than PCM then we assume that the audio decoder will
// output 16-bit PCM.
// output 16-bit PCM.
pcmEncoding
=
C
.
ENCODING_PCM_16BIT
;
pcmEncoding
=
MimeTypes
.
AUDIO_RAW
.
equals
(
format
.
sampleMimeType
)
?
format
.
pcmEncoding
:
C
.
ENCODING_PCM_16BIT
;
}
}
audioSinkInputFormat
=
audioSinkInputFormat
=
new
Format
.
Builder
()
new
Format
.
Builder
()
.
setSampleMimeType
(
MimeTypes
.
AUDIO_RAW
)
.
setSampleMimeType
(
MimeTypes
.
AUDIO_RAW
)
.
setPcmEncoding
(
pcmEncoding
)
.
setPcmEncoding
(
pcmEncoding
)
.
setEncoderDelay
(
outputF
ormat
.
encoderDelay
)
.
setEncoderDelay
(
f
ormat
.
encoderDelay
)
.
setEncoderPadding
(
outputF
ormat
.
encoderPadding
)
.
setEncoderPadding
(
f
ormat
.
encoderPadding
)
.
setChannelCount
(
mediaFormat
.
getInteger
(
MediaFormat
.
KEY_CHANNEL_COUNT
))
.
setChannelCount
(
mediaFormat
.
getInteger
(
MediaFormat
.
KEY_CHANNEL_COUNT
))
.
setSampleRate
(
mediaFormat
.
getInteger
(
MediaFormat
.
KEY_SAMPLE_RATE
))
.
setSampleRate
(
mediaFormat
.
getInteger
(
MediaFormat
.
KEY_SAMPLE_RATE
))
.
build
();
.
build
();
if
(
codecNeedsDiscardChannelsWorkaround
if
(
codecNeedsDiscardChannelsWorkaround
&&
audioSinkInputFormat
.
channelCount
==
6
&&
audioSinkInputFormat
.
channelCount
==
6
&&
outputF
ormat
.
channelCount
<
6
)
{
&&
f
ormat
.
channelCount
<
6
)
{
channelMap
=
new
int
[
outputF
ormat
.
channelCount
];
channelMap
=
new
int
[
f
ormat
.
channelCount
];
for
(
int
i
=
0
;
i
<
outputF
ormat
.
channelCount
;
i
++)
{
for
(
int
i
=
0
;
i
<
f
ormat
.
channelCount
;
i
++)
{
channelMap
[
i
]
=
i
;
channelMap
[
i
]
=
i
;
}
}
}
}
...
@@ -432,7 +428,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
...
@@ -432,7 +428,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
try
{
try
{
audioSink
.
configure
(
audioSinkInputFormat
,
/* specifiedBufferSize= */
0
,
channelMap
);
audioSink
.
configure
(
audioSinkInputFormat
,
/* specifiedBufferSize= */
0
,
channelMap
);
}
catch
(
AudioSink
.
ConfigurationException
e
)
{
}
catch
(
AudioSink
.
ConfigurationException
e
)
{
throw
createRendererException
(
e
,
outputF
ormat
);
throw
createRendererException
(
e
,
f
ormat
);
}
}
}
}
...
@@ -621,8 +617,8 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
...
@@ -621,8 +617,8 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
try
{
try
{
audioSink
.
playToEndOfStream
();
audioSink
.
playToEndOfStream
();
}
catch
(
AudioSink
.
WriteException
e
)
{
}
catch
(
AudioSink
.
WriteException
e
)
{
Format
outputFormat
=
getCurren
tOutputFormat
();
@Nullable
Format
outputFormat
=
ge
tOutputFormat
();
throw
createRendererException
(
e
,
outputFormat
!=
null
?
outputFormat
:
inputFormat
);
throw
createRendererException
(
e
,
outputFormat
!=
null
?
outputFormat
:
getInputFormat
()
);
}
}
}
}
...
...
library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java
View file @
71fd335b
...
@@ -364,7 +364,9 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
...
@@ -364,7 +364,9 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
private
float
operatingRate
;
private
float
operatingRate
;
@Nullable
private
MediaCodec
codec
;
@Nullable
private
MediaCodec
codec
;
@Nullable
private
MediaCodecAdapter
codecAdapter
;
@Nullable
private
MediaCodecAdapter
codecAdapter
;
@Nullable
private
Format
codecFormat
;
@Nullable
private
Format
codecInputFormat
;
@Nullable
private
MediaFormat
codecOutputMediaFormat
;
private
boolean
codecOutputMediaFormatChanged
;
private
float
codecOperatingRate
;
private
float
codecOperatingRate
;
@Nullable
private
ArrayDeque
<
MediaCodecInfo
>
availableCodecInfos
;
@Nullable
private
ArrayDeque
<
MediaCodecInfo
>
availableCodecInfos
;
@Nullable
private
DecoderInitializationException
preferredDecoderInitializationException
;
@Nullable
private
DecoderInitializationException
preferredDecoderInitializationException
;
...
@@ -409,7 +411,6 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
...
@@ -409,7 +411,6 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
protected
DecoderCounters
decoderCounters
;
protected
DecoderCounters
decoderCounters
;
private
long
outputStreamOffsetUs
;
private
long
outputStreamOffsetUs
;
private
int
pendingOutputStreamOffsetCount
;
private
int
pendingOutputStreamOffsetCount
;
private
boolean
receivedOutputMediaFormatChange
;
/**
/**
* @param trackType The track type that the renderer handles. One of the {@code C.TRACK_TYPE_*}
* @param trackType The track type that the renderer handles. One of the {@code C.TRACK_TYPE_*}
...
@@ -613,35 +614,40 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
...
@@ -613,35 +614,40 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
*
*
* @param exception The exception.
* @param exception The exception.
*/
*/
protected
void
setPendingPlaybackException
(
ExoPlaybackException
exception
)
{
protected
final
void
setPendingPlaybackException
(
ExoPlaybackException
exception
)
{
pendingPlaybackException
=
exception
;
pendingPlaybackException
=
exception
;
}
}
/**
/**
* Polls the pending output format queue for a given buffer timestamp. If a format is present, it
* Updates the output formats for the specified output buffer timestamp, calling {@link
* is removed and returned. Otherwise returns {@code null}. Subclasses should only call this
* #onOutputFormatChanged} if a change has occurred.
* method if they are taking over responsibility for output format propagation (e.g., when using
*
* video tunneling).
* <p>Subclasses should only call this method if operating in a mode where buffers are not
* dequeued from the decoder, for example when using video tunneling).
*
*
* @throws ExoPlaybackException Thrown if an error occurs as a result of the output format change.
* @throws ExoPlaybackException Thrown if an error occurs as a result of the output format change.
*/
*/
protected
final
void
updateOutputFormatForTime
(
long
presentationTimeUs
)
protected
final
void
updateOutputFormatForTime
(
long
presentationTimeUs
)
throws
ExoPlaybackException
{
throws
ExoPlaybackException
{
boolean
outputFormatChanged
=
false
;
@Nullable
Format
format
=
formatQueue
.
pollFloor
(
presentationTimeUs
);
@Nullable
Format
format
=
formatQueue
.
pollFloor
(
presentationTimeUs
);
if
(
format
!=
null
)
{
if
(
format
!=
null
)
{
outputFormat
=
format
;
outputFormat
=
format
;
o
nOutputFormatChanged
(
outputFormat
)
;
o
utputFormatChanged
=
true
;
}
else
if
(
receivedOutputMediaFormatChange
&&
outputFormat
!=
null
)
{
}
// No Format change with the MediaFormat change, so we need to update based on the existing
if
(
outputFormatChanged
||
(
codecOutputMediaFormatChanged
&&
outputFormat
!=
null
))
{
// Format.
onOutputFormatChanged
(
outputFormat
,
codecOutputMediaFormat
);
co
nfigureOutput
(
outputFormat
)
;
co
decOutputMediaFormatChanged
=
false
;
}
}
}
receivedOutputMediaFormatChange
=
false
;
@Nullable
protected
Format
getInputFormat
()
{
return
inputFormat
;
}
}
@Nullable
@Nullable
protected
final
Format
get
Current
OutputFormat
()
{
protected
final
Format
getOutputFormat
()
{
return
outputFormat
;
return
outputFormat
;
}
}
...
@@ -651,6 +657,11 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
...
@@ -651,6 +657,11 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
}
}
@Nullable
@Nullable
protected
final
MediaFormat
getCodecOutputMediaFormat
()
{
return
codecOutputMediaFormat
;
}
@Nullable
protected
final
MediaCodecInfo
getCodecInfo
()
{
protected
final
MediaCodecInfo
getCodecInfo
()
{
return
codecInfo
;
return
codecInfo
;
}
}
...
@@ -905,11 +916,14 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
...
@@ -905,11 +916,14 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
protected
void
resetCodecStateForRelease
()
{
protected
void
resetCodecStateForRelease
()
{
resetCodecStateForFlush
();
resetCodecStateForFlush
();
pendingPlaybackException
=
null
;
c2Mp3TimestampTracker
=
null
;
availableCodecInfos
=
null
;
availableCodecInfos
=
null
;
codecInfo
=
null
;
codecInfo
=
null
;
codecFormat
=
null
;
codecInputFormat
=
null
;
codecOutputMediaFormat
=
null
;
codecOutputMediaFormatChanged
=
false
;
codecHasOutputMediaFormat
=
false
;
codecHasOutputMediaFormat
=
false
;
pendingPlaybackException
=
null
;
codecOperatingRate
=
CODEC_OPERATING_RATE_UNSET
;
codecOperatingRate
=
CODEC_OPERATING_RATE_UNSET
;
codecAdaptationWorkaroundMode
=
ADAPTATION_WORKAROUND_MODE_NEVER
;
codecAdaptationWorkaroundMode
=
ADAPTATION_WORKAROUND_MODE_NEVER
;
codecNeedsReconfigureWorkaround
=
false
;
codecNeedsReconfigureWorkaround
=
false
;
...
@@ -920,7 +934,6 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
...
@@ -920,7 +934,6 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
codecNeedsEosOutputExceptionWorkaround
=
false
;
codecNeedsEosOutputExceptionWorkaround
=
false
;
codecNeedsMonoChannelCountWorkaround
=
false
;
codecNeedsMonoChannelCountWorkaround
=
false
;
codecNeedsEosPropagation
=
false
;
codecNeedsEosPropagation
=
false
;
c2Mp3TimestampTracker
=
null
;
codecReconfigured
=
false
;
codecReconfigured
=
false
;
codecReconfigurationState
=
RECONFIGURATION_STATE_NONE
;
codecReconfigurationState
=
RECONFIGURATION_STATE_NONE
;
resetCodecBuffers
();
resetCodecBuffers
();
...
@@ -1110,16 +1123,17 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
...
@@ -1110,16 +1123,17 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
this
.
codecAdapter
=
codecAdapter
;
this
.
codecAdapter
=
codecAdapter
;
this
.
codecInfo
=
codecInfo
;
this
.
codecInfo
=
codecInfo
;
this
.
codecOperatingRate
=
codecOperatingRate
;
this
.
codecOperatingRate
=
codecOperatingRate
;
codecFormat
=
inputFormat
;
codec
Input
Format
=
inputFormat
;
codecAdaptationWorkaroundMode
=
codecAdaptationWorkaroundMode
(
codecName
);
codecAdaptationWorkaroundMode
=
codecAdaptationWorkaroundMode
(
codecName
);
codecNeedsReconfigureWorkaround
=
codecNeedsReconfigureWorkaround
(
codecName
);
codecNeedsReconfigureWorkaround
=
codecNeedsReconfigureWorkaround
(
codecName
);
codecNeedsDiscardToSpsWorkaround
=
codecNeedsDiscardToSpsWorkaround
(
codecName
,
codecFormat
);
codecNeedsDiscardToSpsWorkaround
=
codecNeedsDiscardToSpsWorkaround
(
codecName
,
codecInputFormat
);
codecNeedsFlushWorkaround
=
codecNeedsFlushWorkaround
(
codecName
);
codecNeedsFlushWorkaround
=
codecNeedsFlushWorkaround
(
codecName
);
codecNeedsSosFlushWorkaround
=
codecNeedsSosFlushWorkaround
(
codecName
);
codecNeedsSosFlushWorkaround
=
codecNeedsSosFlushWorkaround
(
codecName
);
codecNeedsEosFlushWorkaround
=
codecNeedsEosFlushWorkaround
(
codecName
);
codecNeedsEosFlushWorkaround
=
codecNeedsEosFlushWorkaround
(
codecName
);
codecNeedsEosOutputExceptionWorkaround
=
codecNeedsEosOutputExceptionWorkaround
(
codecName
);
codecNeedsEosOutputExceptionWorkaround
=
codecNeedsEosOutputExceptionWorkaround
(
codecName
);
codecNeedsMonoChannelCountWorkaround
=
codecNeedsMonoChannelCountWorkaround
=
codecNeedsMonoChannelCountWorkaround
(
codecName
,
codecFormat
);
codecNeedsMonoChannelCountWorkaround
(
codecName
,
codec
Input
Format
);
codecNeedsEosPropagation
=
codecNeedsEosPropagation
=
codecNeedsEosPropagationWorkaround
(
codecInfo
)
||
getCodecNeedsEosPropagation
();
codecNeedsEosPropagationWorkaround
(
codecInfo
)
||
getCodecNeedsEosPropagation
();
if
(
"c2.android.mp3.decoder"
.
equals
(
codecInfo
.
name
))
{
if
(
"c2.android.mp3.decoder"
.
equals
(
codecInfo
.
name
))
{
...
@@ -1234,8 +1248,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
...
@@ -1234,8 +1248,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
// For adaptive reconfiguration, decoders expect all reconfiguration data to be supplied at
// For adaptive reconfiguration, decoders expect all reconfiguration data to be supplied at
// the start of the buffer that also contains the first frame in the new format.
// the start of the buffer that also contains the first frame in the new format.
if
(
codecReconfigurationState
==
RECONFIGURATION_STATE_WRITE_PENDING
)
{
if
(
codecReconfigurationState
==
RECONFIGURATION_STATE_WRITE_PENDING
)
{
for
(
int
i
=
0
;
i
<
codecFormat
.
initializationData
.
size
();
i
++)
{
for
(
int
i
=
0
;
i
<
codec
Input
Format
.
initializationData
.
size
();
i
++)
{
byte
[]
data
=
codecFormat
.
initializationData
.
get
(
i
);
byte
[]
data
=
codec
Input
Format
.
initializationData
.
get
(
i
);
buffer
.
data
.
put
(
data
);
buffer
.
data
.
put
(
data
);
}
}
codecReconfigurationState
=
RECONFIGURATION_STATE_QUEUE_PENDING
;
codecReconfigurationState
=
RECONFIGURATION_STATE_QUEUE_PENDING
;
...
@@ -1270,7 +1284,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
...
@@ -1270,7 +1284,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
if
(
codecReconfigurationState
==
RECONFIGURATION_STATE_QUEUE_PENDING
)
{
if
(
codecReconfigurationState
==
RECONFIGURATION_STATE_QUEUE_PENDING
)
{
// We received a new format immediately before the end of the stream. We need to clear
// We received a new format immediately before the end of the stream. We need to clear
// the corresponding reconfiguration data from the current buffer, but re-write it into
// the corresponding reconfiguration data from the current buffer, but re-write it into
// a subsequent buffer if there are any (
e.g.
if the user seeks backwards).
// a subsequent buffer if there are any (
for example,
if the user seeks backwards).
buffer
.
clear
();
buffer
.
clear
();
codecReconfigurationState
=
RECONFIGURATION_STATE_WRITE_PENDING
;
codecReconfigurationState
=
RECONFIGURATION_STATE_WRITE_PENDING
;
}
}
...
@@ -1393,6 +1407,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
...
@@ -1393,6 +1407,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
* @param formatHolder A {@link FormatHolder} that holds the new {@link Format}.
* @param formatHolder A {@link FormatHolder} that holds the new {@link Format}.
* @throws ExoPlaybackException If an error occurs re-initializing the {@link MediaCodec}.
* @throws ExoPlaybackException If an error occurs re-initializing the {@link MediaCodec}.
*/
*/
@CallSuper
protected
void
onInputFormatChanged
(
FormatHolder
formatHolder
)
throws
ExoPlaybackException
{
protected
void
onInputFormatChanged
(
FormatHolder
formatHolder
)
throws
ExoPlaybackException
{
waitingForFirstSampleInFormat
=
true
;
waitingForFirstSampleInFormat
=
true
;
Format
newFormat
=
Assertions
.
checkNotNull
(
formatHolder
.
format
);
Format
newFormat
=
Assertions
.
checkNotNull
(
formatHolder
.
format
);
...
@@ -1426,12 +1441,12 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
...
@@ -1426,12 +1441,12 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
return
;
return
;
}
}
switch
(
canKeepCodec
(
codec
,
codecInfo
,
codecFormat
,
newFormat
))
{
switch
(
canKeepCodec
(
codec
,
codecInfo
,
codec
Input
Format
,
newFormat
))
{
case
KEEP_CODEC_RESULT_NO:
case
KEEP_CODEC_RESULT_NO:
drainAndReinitializeCodec
();
drainAndReinitializeCodec
();
break
;
break
;
case
KEEP_CODEC_RESULT_YES_WITH_FLUSH:
case
KEEP_CODEC_RESULT_YES_WITH_FLUSH:
codecFormat
=
newFormat
;
codec
Input
Format
=
newFormat
;
updateCodecOperatingRate
();
updateCodecOperatingRate
();
if
(
sourceDrmSession
!=
codecDrmSession
)
{
if
(
sourceDrmSession
!=
codecDrmSession
)
{
drainAndUpdateCodecDrmSession
();
drainAndUpdateCodecDrmSession
();
...
@@ -1448,9 +1463,9 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
...
@@ -1448,9 +1463,9 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
codecNeedsAdaptationWorkaroundBuffer
=
codecNeedsAdaptationWorkaroundBuffer
=
codecAdaptationWorkaroundMode
==
ADAPTATION_WORKAROUND_MODE_ALWAYS
codecAdaptationWorkaroundMode
==
ADAPTATION_WORKAROUND_MODE_ALWAYS
||
(
codecAdaptationWorkaroundMode
==
ADAPTATION_WORKAROUND_MODE_SAME_RESOLUTION
||
(
codecAdaptationWorkaroundMode
==
ADAPTATION_WORKAROUND_MODE_SAME_RESOLUTION
&&
newFormat
.
width
==
codecFormat
.
width
&&
newFormat
.
width
==
codec
Input
Format
.
width
&&
newFormat
.
height
==
codecFormat
.
height
);
&&
newFormat
.
height
==
codec
Input
Format
.
height
);
codecFormat
=
newFormat
;
codec
Input
Format
=
newFormat
;
updateCodecOperatingRate
();
updateCodecOperatingRate
();
if
(
sourceDrmSession
!=
codecDrmSession
)
{
if
(
sourceDrmSession
!=
codecDrmSession
)
{
drainAndUpdateCodecDrmSession
();
drainAndUpdateCodecDrmSession
();
...
@@ -1458,7 +1473,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
...
@@ -1458,7 +1473,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
}
}
break
;
break
;
case
KEEP_CODEC_RESULT_YES_WITHOUT_RECONFIGURATION:
case
KEEP_CODEC_RESULT_YES_WITHOUT_RECONFIGURATION:
codecFormat
=
newFormat
;
codec
Input
Format
=
newFormat
;
updateCodecOperatingRate
();
updateCodecOperatingRate
();
if
(
sourceDrmSession
!=
codecDrmSession
)
{
if
(
sourceDrmSession
!=
codecDrmSession
)
{
drainAndUpdateCodecDrmSession
();
drainAndUpdateCodecDrmSession
();
...
@@ -1470,40 +1485,18 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
...
@@ -1470,40 +1485,18 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
}
}
/**
/**
* Called when
the output {@link MediaFormat} of the {@link MediaCodec}
changes.
* Called when
one of the output formats
changes.
*
*
* <p>The default implementation is a no-op.
* <p>The default implementation is a no-op.
*
*
* @param codec The {@link MediaCodec} instance.
* @param format The input {@link Format} to which future output now corresponds. If the renderer
* @param outputMediaFormat The new output {@link MediaFormat}.
* is in bypass mode, this is also the output format.
* @throws ExoPlaybackException Thrown if an error occurs handling the new output media format.
* @param mediaFormat The codec output {@link MediaFormat}, or {@code null} if the renderer is in
*/
* bypass mode.
protected
void
onOutputMediaFormatChanged
(
MediaCodec
codec
,
MediaFormat
outputMediaFormat
)
throws
ExoPlaybackException
{
// Do nothing.
}
/**
* Called when the output {@link Format} changes.
*
* <p>The default implementation is a no-op.
*
* @param outputFormat The new output {@link Format}.
* @throws ExoPlaybackException Thrown if an error occurs handling the new output format.
*/
protected
void
onOutputFormatChanged
(
Format
outputFormat
)
throws
ExoPlaybackException
{
// Do nothing.
}
/**
* Configures the renderer output based on a {@link Format}.
*
* <p>The default implementation is a no-op.
*
* @param outputFormat The format to configure the output with.
* @throws ExoPlaybackException Thrown if an error occurs configuring the output.
* @throws ExoPlaybackException Thrown if an error occurs configuring the output.
*/
*/
protected
void
configureOutput
(
Format
outputFormat
)
throws
ExoPlaybackException
{
protected
void
onOutputFormatChanged
(
Format
format
,
@Nullable
MediaFormat
mediaFormat
)
throws
ExoPlaybackException
{
// Do nothing.
// Do nothing.
}
}
...
@@ -1633,7 +1626,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
...
@@ -1633,7 +1626,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
}
}
float
newCodecOperatingRate
=
float
newCodecOperatingRate
=
getCodecOperatingRateV23
(
operatingRate
,
codecFormat
,
getStreamFormats
());
getCodecOperatingRateV23
(
operatingRate
,
codec
Input
Format
,
getStreamFormats
());
if
(
codecOperatingRate
==
newCodecOperatingRate
)
{
if
(
codecOperatingRate
==
newCodecOperatingRate
)
{
// No change.
// No change.
}
else
if
(
newCodecOperatingRate
==
CODEC_OPERATING_RATE_UNSET
)
{
}
else
if
(
newCodecOperatingRate
==
CODEC_OPERATING_RATE_UNSET
)
{
...
@@ -1721,8 +1714,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
...
@@ -1721,8 +1714,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
if
(
outputIndex
<
0
)
{
if
(
outputIndex
<
0
)
{
if
(
outputIndex
==
MediaCodec
.
INFO_OUTPUT_FORMAT_CHANGED
/* (-2) */
)
{
if
(
outputIndex
==
MediaCodec
.
INFO_OUTPUT_FORMAT_CHANGED
/* (-2) */
)
{
processOutputMediaFormat
();
processOutputMediaFormatChanged
();
receivedOutputMediaFormatChange
=
true
;
return
true
;
return
true
;
}
else
if
(
outputIndex
==
MediaCodec
.
INFO_OUTPUT_BUFFERS_CHANGED
/* (-3) */
)
{
}
else
if
(
outputIndex
==
MediaCodec
.
INFO_OUTPUT_BUFFERS_CHANGED
/* (-3) */
)
{
processOutputBuffersChanged
();
processOutputBuffersChanged
();
...
@@ -1750,6 +1742,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
...
@@ -1750,6 +1742,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
this
.
outputIndex
=
outputIndex
;
this
.
outputIndex
=
outputIndex
;
outputBuffer
=
getOutputBuffer
(
outputIndex
);
outputBuffer
=
getOutputBuffer
(
outputIndex
);
// The dequeued buffer is a media buffer. Do some initial setup.
// The dequeued buffer is a media buffer. Do some initial setup.
// It will be processed by calling processOutputBuffer (possibly multiple times).
// It will be processed by calling processOutputBuffer (possibly multiple times).
if
(
outputBuffer
!=
null
)
{
if
(
outputBuffer
!=
null
)
{
...
@@ -1815,8 +1808,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
...
@@ -1815,8 +1808,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
return
false
;
return
false
;
}
}
/** Processes a
new
output {@link MediaFormat}. */
/** Processes a
change in the decoder
output {@link MediaFormat}. */
private
void
processOutputMediaFormat
()
throws
ExoPlaybackException
{
private
void
processOutputMediaFormat
Changed
()
{
codecHasOutputMediaFormat
=
true
;
codecHasOutputMediaFormat
=
true
;
MediaFormat
mediaFormat
=
codecAdapter
.
getOutputFormat
();
MediaFormat
mediaFormat
=
codecAdapter
.
getOutputFormat
();
if
(
codecAdaptationWorkaroundMode
!=
ADAPTATION_WORKAROUND_MODE_NEVER
if
(
codecAdaptationWorkaroundMode
!=
ADAPTATION_WORKAROUND_MODE_NEVER
...
@@ -1830,7 +1823,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
...
@@ -1830,7 +1823,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
if
(
codecNeedsMonoChannelCountWorkaround
)
{
if
(
codecNeedsMonoChannelCountWorkaround
)
{
mediaFormat
.
setInteger
(
MediaFormat
.
KEY_CHANNEL_COUNT
,
1
);
mediaFormat
.
setInteger
(
MediaFormat
.
KEY_CHANNEL_COUNT
,
1
);
}
}
onOutputMediaFormatChanged
(
codec
,
mediaFormat
);
codecOutputMediaFormat
=
mediaFormat
;
codecOutputMediaFormatChanged
=
true
;
}
}
/**
/**
...
@@ -1874,7 +1868,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
...
@@ -1874,7 +1868,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
* by the source.
* by the source.
* @param isLastBuffer Whether the buffer is the last sample of the current stream.
* @param isLastBuffer Whether the buffer is the last sample of the current stream.
* @param format The {@link Format} associated with the buffer.
* @param format The {@link Format} associated with the buffer.
* @return Whether the output buffer was fully processed (
e.g.
rendered or skipped).
* @return Whether the output buffer was fully processed (
for example,
rendered or skipped).
* @throws ExoPlaybackException If an error occurs processing the output buffer.
* @throws ExoPlaybackException If an error occurs processing the output buffer.
*/
*/
protected
abstract
boolean
processOutputBuffer
(
protected
abstract
boolean
processOutputBuffer
(
...
@@ -2121,7 +2115,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
...
@@ -2121,7 +2115,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
if
(!
batchBuffer
.
isEmpty
()
&&
waitingForFirstSampleInFormat
)
{
if
(!
batchBuffer
.
isEmpty
()
&&
waitingForFirstSampleInFormat
)
{
// This is the first buffer in a new format, the output format must be updated.
// This is the first buffer in a new format, the output format must be updated.
outputFormat
=
Assertions
.
checkNotNull
(
inputFormat
);
outputFormat
=
Assertions
.
checkNotNull
(
inputFormat
);
onOutputFormatChanged
(
outputFormat
);
onOutputFormatChanged
(
outputFormat
,
/* mediaFormat= */
null
);
waitingForFirstSampleInFormat
=
false
;
waitingForFirstSampleInFormat
=
false
;
}
}
...
...
library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java
View file @
71fd335b
...
@@ -153,9 +153,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
...
@@ -153,9 +153,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
private
long
totalVideoFrameProcessingOffsetUs
;
private
long
totalVideoFrameProcessingOffsetUs
;
private
int
videoFrameProcessingOffsetCount
;
private
int
videoFrameProcessingOffsetCount
;
@Nullable
private
MediaFormat
currentMediaFormat
;
private
int
mediaFormatWidth
;
private
int
mediaFormatHeight
;
private
int
currentWidth
;
private
int
currentWidth
;
private
int
currentHeight
;
private
int
currentHeight
;
private
int
currentUnappliedRotationDegrees
;
private
int
currentUnappliedRotationDegrees
;
...
@@ -262,8 +259,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
...
@@ -262,8 +259,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
currentHeight
=
Format
.
NO_VALUE
;
currentHeight
=
Format
.
NO_VALUE
;
currentPixelWidthHeightRatio
=
Format
.
NO_VALUE
;
currentPixelWidthHeightRatio
=
Format
.
NO_VALUE
;
scalingMode
=
VIDEO_SCALING_MODE_DEFAULT
;
scalingMode
=
VIDEO_SCALING_MODE_DEFAULT
;
mediaFormatWidth
=
Format
.
NO_VALUE
;
mediaFormatHeight
=
Format
.
NO_VALUE
;
clearReportedVideoSize
();
clearReportedVideoSize
();
}
}
...
@@ -449,7 +444,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
...
@@ -449,7 +444,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
@Override
@Override
protected
void
onDisabled
()
{
protected
void
onDisabled
()
{
currentMediaFormat
=
null
;
clearReportedVideoSize
();
clearReportedVideoSize
();
clearRenderedFirstFrame
();
clearRenderedFirstFrame
();
frameReleaseTimeHelper
.
disable
();
frameReleaseTimeHelper
.
disable
();
...
@@ -668,51 +662,37 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
...
@@ -668,51 +662,37 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
}
}
@Override
@Override
protected
void
onOutputMediaFormatChanged
(
MediaCodec
codec
,
MediaFormat
outputMediaFormat
)
{
protected
void
onOutputFormatChanged
(
Format
format
,
@Nullable
MediaFormat
mediaFormat
)
{
currentMediaFormat
=
outputMediaFormat
;
@Nullable
MediaCodec
codec
=
getCodec
();
boolean
hasCrop
=
if
(
codec
!=
null
)
{
outputMediaFormat
.
containsKey
(
KEY_CROP_RIGHT
)
// Must be applied each time the output format changes.
&&
outputMediaFormat
.
containsKey
(
KEY_CROP_LEFT
)
codec
.
setVideoScalingMode
(
scalingMode
);
&&
outputMediaFormat
.
containsKey
(
KEY_CROP_BOTTOM
)
}
&&
outputMediaFormat
.
containsKey
(
KEY_CROP_TOP
);
mediaFormatWidth
=
hasCrop
?
outputMediaFormat
.
getInteger
(
KEY_CROP_RIGHT
)
-
outputMediaFormat
.
getInteger
(
KEY_CROP_LEFT
)
+
1
:
outputMediaFormat
.
getInteger
(
MediaFormat
.
KEY_WIDTH
);
mediaFormatHeight
=
hasCrop
?
outputMediaFormat
.
getInteger
(
KEY_CROP_BOTTOM
)
-
outputMediaFormat
.
getInteger
(
KEY_CROP_TOP
)
+
1
:
outputMediaFormat
.
getInteger
(
MediaFormat
.
KEY_HEIGHT
);
// Must be applied each time the output MediaFormat changes.
codec
.
setVideoScalingMode
(
scalingMode
);
maybeNotifyVideoFrameProcessingOffset
();
}
@Override
protected
void
onOutputFormatChanged
(
Format
outputFormat
)
{
configureOutput
(
outputFormat
);
}
@Override
protected
void
configureOutput
(
Format
outputFormat
)
{
if
(
tunneling
)
{
if
(
tunneling
)
{
currentWidth
=
outputF
ormat
.
width
;
currentWidth
=
f
ormat
.
width
;
currentHeight
=
outputF
ormat
.
height
;
currentHeight
=
f
ormat
.
height
;
}
else
{
}
else
{
currentWidth
=
mediaFormatWidth
;
Assertions
.
checkNotNull
(
mediaFormat
);
currentHeight
=
mediaFormatHeight
;
boolean
hasCrop
=
}
mediaFormat
.
containsKey
(
KEY_CROP_RIGHT
)
currentPixelWidthHeightRatio
=
outputFormat
.
pixelWidthHeightRatio
;
&&
mediaFormat
.
containsKey
(
KEY_CROP_LEFT
)
&&
mediaFormat
.
containsKey
(
KEY_CROP_BOTTOM
)
&&
mediaFormat
.
containsKey
(
KEY_CROP_TOP
);
currentWidth
=
hasCrop
?
mediaFormat
.
getInteger
(
KEY_CROP_RIGHT
)
-
mediaFormat
.
getInteger
(
KEY_CROP_LEFT
)
+
1
:
mediaFormat
.
getInteger
(
MediaFormat
.
KEY_WIDTH
);
currentHeight
=
hasCrop
?
mediaFormat
.
getInteger
(
KEY_CROP_BOTTOM
)
-
mediaFormat
.
getInteger
(
KEY_CROP_TOP
)
+
1
:
mediaFormat
.
getInteger
(
MediaFormat
.
KEY_HEIGHT
);
}
currentPixelWidthHeightRatio
=
format
.
pixelWidthHeightRatio
;
if
(
Util
.
SDK_INT
>=
21
)
{
if
(
Util
.
SDK_INT
>=
21
)
{
// On API level 21 and above the decoder applies the rotation when rendering to the surface.
// On API level 21 and above the decoder applies the rotation when rendering to the surface.
// Hence currentUnappliedRotation should always be 0. For 90 and 270 degree rotations, we need
// Hence currentUnappliedRotation should always be 0. For 90 and 270 degree rotations, we need
// to flip the width, height and pixel aspect ratio to reflect the rotation that was applied.
// to flip the width, height and pixel aspect ratio to reflect the rotation that was applied.
if
(
outputFormat
.
rotationDegrees
==
90
||
outputF
ormat
.
rotationDegrees
==
270
)
{
if
(
format
.
rotationDegrees
==
90
||
f
ormat
.
rotationDegrees
==
270
)
{
int
rotatedHeight
=
currentWidth
;
int
rotatedHeight
=
currentWidth
;
currentWidth
=
currentHeight
;
currentWidth
=
currentHeight
;
currentHeight
=
rotatedHeight
;
currentHeight
=
rotatedHeight
;
...
@@ -720,9 +700,9 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
...
@@ -720,9 +700,9 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
}
}
}
else
{
}
else
{
// On API level 20 and below the decoder does not apply the rotation.
// On API level 20 and below the decoder does not apply the rotation.
currentUnappliedRotationDegrees
=
outputF
ormat
.
rotationDegrees
;
currentUnappliedRotationDegrees
=
f
ormat
.
rotationDegrees
;
}
}
currentFrameRate
=
outputF
ormat
.
frameRate
;
currentFrameRate
=
f
ormat
.
frameRate
;
updateSurfaceFrameRate
(
/* isNewSurface= */
false
);
updateSurfaceFrameRate
(
/* isNewSurface= */
false
);
}
}
...
@@ -811,7 +791,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
...
@@ -811,7 +791,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
||
(
isStarted
&&
shouldForceRenderOutputBuffer
(
earlyUs
,
elapsedSinceLastRenderUs
)));
||
(
isStarted
&&
shouldForceRenderOutputBuffer
(
earlyUs
,
elapsedSinceLastRenderUs
)));
if
(
forceRenderOutputBuffer
)
{
if
(
forceRenderOutputBuffer
)
{
long
releaseTimeNs
=
System
.
nanoTime
();
long
releaseTimeNs
=
System
.
nanoTime
();
notifyFrameMetadataListener
(
presentationTimeUs
,
releaseTimeNs
,
format
,
currentMediaFormat
);
notifyFrameMetadataListener
(
presentationTimeUs
,
releaseTimeNs
,
format
);
if
(
Util
.
SDK_INT
>=
21
)
{
if
(
Util
.
SDK_INT
>=
21
)
{
renderOutputBufferV21
(
codec
,
bufferIndex
,
presentationTimeUs
,
releaseTimeNs
);
renderOutputBufferV21
(
codec
,
bufferIndex
,
presentationTimeUs
,
releaseTimeNs
);
}
else
{
}
else
{
...
@@ -857,8 +837,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
...
@@ -857,8 +837,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
if
(
Util
.
SDK_INT
>=
21
)
{
if
(
Util
.
SDK_INT
>=
21
)
{
// Let the underlying framework time the release.
// Let the underlying framework time the release.
if
(
earlyUs
<
50000
)
{
if
(
earlyUs
<
50000
)
{
notifyFrameMetadataListener
(
notifyFrameMetadataListener
(
presentationTimeUs
,
adjustedReleaseTimeNs
,
format
);
presentationTimeUs
,
adjustedReleaseTimeNs
,
format
,
currentMediaFormat
);
renderOutputBufferV21
(
codec
,
bufferIndex
,
presentationTimeUs
,
adjustedReleaseTimeNs
);
renderOutputBufferV21
(
codec
,
bufferIndex
,
presentationTimeUs
,
adjustedReleaseTimeNs
);
updateVideoFrameProcessingOffsetCounters
(
earlyUs
);
updateVideoFrameProcessingOffsetCounters
(
earlyUs
);
return
true
;
return
true
;
...
@@ -877,8 +856,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
...
@@ -877,8 +856,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
return
false
;
return
false
;
}
}
}
}
notifyFrameMetadataListener
(
notifyFrameMetadataListener
(
presentationTimeUs
,
adjustedReleaseTimeNs
,
format
);
presentationTimeUs
,
adjustedReleaseTimeNs
,
format
,
currentMediaFormat
);
renderOutputBuffer
(
codec
,
bufferIndex
,
presentationTimeUs
);
renderOutputBuffer
(
codec
,
bufferIndex
,
presentationTimeUs
);
updateVideoFrameProcessingOffsetCounters
(
earlyUs
);
updateVideoFrameProcessingOffsetCounters
(
earlyUs
);
return
true
;
return
true
;
...
@@ -890,10 +868,10 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
...
@@ -890,10 +868,10 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
}
}
private
void
notifyFrameMetadataListener
(
private
void
notifyFrameMetadataListener
(
long
presentationTimeUs
,
long
releaseTimeNs
,
Format
format
,
MediaFormat
mediaFormat
)
{
long
presentationTimeUs
,
long
releaseTimeNs
,
Format
format
)
{
if
(
frameMetadataListener
!=
null
)
{
if
(
frameMetadataListener
!=
null
)
{
frameMetadataListener
.
onVideoFrameAboutToBeRendered
(
frameMetadataListener
.
onVideoFrameAboutToBeRendered
(
presentationTimeUs
,
releaseTimeNs
,
format
,
mediaFormat
);
presentationTimeUs
,
releaseTimeNs
,
format
,
getCodecOutputMediaFormat
()
);
}
}
}
}
...
@@ -1230,10 +1208,9 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
...
@@ -1230,10 +1208,9 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
}
}
private
void
maybeNotifyVideoFrameProcessingOffset
()
{
private
void
maybeNotifyVideoFrameProcessingOffset
()
{
@Nullable
Format
outputFormat
=
getCurrentOutputFormat
();
if
(
videoFrameProcessingOffsetCount
!=
0
)
{
if
(
outputFormat
!=
null
&&
videoFrameProcessingOffsetCount
!=
0
)
{
eventDispatcher
.
reportVideoFrameProcessingOffset
(
eventDispatcher
.
reportVideoFrameProcessingOffset
(
totalVideoFrameProcessingOffsetUs
,
videoFrameProcessingOffsetCount
,
outputFormat
);
totalVideoFrameProcessingOffsetUs
,
videoFrameProcessingOffsetCount
);
totalVideoFrameProcessingOffsetUs
=
0
;
totalVideoFrameProcessingOffsetUs
=
0
;
videoFrameProcessingOffsetCount
=
0
;
videoFrameProcessingOffsetCount
=
0
;
}
}
...
...
library/core/src/main/java/com/google/android/exoplayer2/video/VideoRendererEventListener.java
View file @
71fd335b
...
@@ -88,10 +88,8 @@ public interface VideoRendererEventListener {
...
@@ -88,10 +88,8 @@ public interface VideoRendererEventListener {
* @param totalProcessingOffsetUs The sum of all video frame processing offset samples for the
* @param totalProcessingOffsetUs The sum of all video frame processing offset samples for the
* video frames processed by the renderer in microseconds.
* video frames processed by the renderer in microseconds.
* @param frameCount The number of samples included in the {@code totalProcessingOffsetUs}.
* @param frameCount The number of samples included in the {@code totalProcessingOffsetUs}.
* @param format The {@link Format} that is currently output.
*/
*/
default
void
onVideoFrameProcessingOffset
(
default
void
onVideoFrameProcessingOffset
(
long
totalProcessingOffsetUs
,
int
frameCount
)
{}
long
totalProcessingOffsetUs
,
int
frameCount
,
Format
format
)
{}
/**
/**
* Called before a frame is rendered for the first time since setting the surface, and each time
* Called before a frame is rendered for the first time since setting the surface, and each time
...
@@ -182,13 +180,12 @@ public interface VideoRendererEventListener {
...
@@ -182,13 +180,12 @@ public interface VideoRendererEventListener {
}
}
/** Invokes {@link VideoRendererEventListener#onVideoFrameProcessingOffset}. */
/** Invokes {@link VideoRendererEventListener#onVideoFrameProcessingOffset}. */
public
void
reportVideoFrameProcessingOffset
(
public
void
reportVideoFrameProcessingOffset
(
long
totalProcessingOffsetUs
,
int
frameCount
)
{
long
totalProcessingOffsetUs
,
int
frameCount
,
Format
format
)
{
if
(
handler
!=
null
)
{
if
(
handler
!=
null
)
{
handler
.
post
(
handler
.
post
(
()
->
()
->
castNonNull
(
listener
)
castNonNull
(
listener
)
.
onVideoFrameProcessingOffset
(
totalProcessingOffsetUs
,
frameCount
,
format
));
.
onVideoFrameProcessingOffset
(
totalProcessingOffsetUs
,
frameCount
));
}
}
}
}
...
...
library/core/src/test/java/com/google/android/exoplayer2/analytics/AnalyticsCollectorTest.java
View file @
71fd335b
...
@@ -1955,7 +1955,7 @@ public final class AnalyticsCollectorTest {
...
@@ -1955,7 +1955,7 @@ public final class AnalyticsCollectorTest {
@Override
@Override
public
void
onVideoFrameProcessingOffset
(
public
void
onVideoFrameProcessingOffset
(
EventTime
eventTime
,
long
totalProcessingOffsetUs
,
int
frameCount
,
Format
format
)
{
EventTime
eventTime
,
long
totalProcessingOffsetUs
,
int
frameCount
)
{
reportedEvents
.
add
(
new
ReportedEvent
(
EVENT_VIDEO_FRAME_PROCESSING_OFFSET
,
eventTime
));
reportedEvents
.
add
(
new
ReportedEvent
(
EVENT_VIDEO_FRAME_PROCESSING_OFFSET
,
eventTime
));
}
}
...
...
library/core/src/test/java/com/google/android/exoplayer2/audio/MediaCodecAudioRendererTest.java
View file @
71fd335b
...
@@ -25,7 +25,9 @@ import static org.mockito.ArgumentMatchers.anyLong;
...
@@ -25,7 +25,9 @@ import static org.mockito.ArgumentMatchers.anyLong;
import
static
org
.
mockito
.
Mockito
.
verify
;
import
static
org
.
mockito
.
Mockito
.
verify
;
import
static
org
.
mockito
.
Mockito
.
when
;
import
static
org
.
mockito
.
Mockito
.
when
;
import
android.media.MediaFormat
;
import
android.os.SystemClock
;
import
android.os.SystemClock
;
import
androidx.annotation.Nullable
;
import
androidx.test.core.app.ApplicationProvider
;
import
androidx.test.core.app.ApplicationProvider
;
import
androidx.test.ext.junit.runners.AndroidJUnit4
;
import
androidx.test.ext.junit.runners.AndroidJUnit4
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.C
;
...
@@ -216,15 +218,16 @@ public class MediaCodecAudioRendererTest {
...
@@ -216,15 +218,16 @@ public class MediaCodecAudioRendererTest {
/* eventHandler= */
null
,
/* eventHandler= */
null
,
/* eventListener= */
null
)
{
/* eventListener= */
null
)
{
@Override
@Override
protected
void
onOutputFormatChanged
(
Format
outputFormat
)
throws
ExoPlaybackException
{
protected
void
onOutputFormatChanged
(
Format
format
,
@Nullable
MediaFormat
mediaFormat
)
super
.
onOutputFormatChanged
(
outputFormat
);
throws
ExoPlaybackException
{
if
(!
outputFormat
.
equals
(
AUDIO_AAC
))
{
super
.
onOutputFormatChanged
(
format
,
mediaFormat
);
if
(!
format
.
equals
(
AUDIO_AAC
))
{
setPendingPlaybackException
(
setPendingPlaybackException
(
ExoPlaybackException
.
createForRenderer
(
ExoPlaybackException
.
createForRenderer
(
new
AudioSink
.
ConfigurationException
(
"Test"
),
new
AudioSink
.
ConfigurationException
(
"Test"
),
"rendererName"
,
"rendererName"
,
/* rendererIndex= */
0
,
/* rendererIndex= */
0
,
outputF
ormat
,
f
ormat
,
FORMAT_HANDLED
));
FORMAT_HANDLED
));
}
}
}
}
...
@@ -254,8 +257,11 @@ public class MediaCodecAudioRendererTest {
...
@@ -254,8 +257,11 @@ public class MediaCodecAudioRendererTest {
exceptionThrowingRenderer
.
render
(
/* positionUs= */
0
,
SystemClock
.
elapsedRealtime
()
*
1000
);
exceptionThrowingRenderer
.
render
(
/* positionUs= */
0
,
SystemClock
.
elapsedRealtime
()
*
1000
);
exceptionThrowingRenderer
.
render
(
/* positionUs= */
250
,
SystemClock
.
elapsedRealtime
()
*
1000
);
exceptionThrowingRenderer
.
render
(
/* positionUs= */
250
,
SystemClock
.
elapsedRealtime
()
*
1000
);
MediaFormat
mediaFormat
=
new
MediaFormat
();
mediaFormat
.
setInteger
(
MediaFormat
.
KEY_CHANNEL_COUNT
,
2
);
mediaFormat
.
setInteger
(
MediaFormat
.
KEY_SAMPLE_RATE
,
32_000
);
// Simulating the exception being thrown when not traceable back to render.
// Simulating the exception being thrown when not traceable back to render.
exceptionThrowingRenderer
.
onOutputFormatChanged
(
changedFormat
);
exceptionThrowingRenderer
.
onOutputFormatChanged
(
changedFormat
,
mediaFormat
);
assertThrows
(
assertThrows
(
ExoPlaybackException
.
class
,
ExoPlaybackException
.
class
,
...
...
library/core/src/test/java/com/google/android/exoplayer2/video/MediaCodecVideoRendererTest.java
View file @
71fd335b
...
@@ -29,6 +29,7 @@ import static org.mockito.Mockito.verify;
...
@@ -29,6 +29,7 @@ import static org.mockito.Mockito.verify;
import
static
org
.
robolectric
.
Shadows
.
shadowOf
;
import
static
org
.
robolectric
.
Shadows
.
shadowOf
;
import
android.graphics.SurfaceTexture
;
import
android.graphics.SurfaceTexture
;
import
android.media.MediaFormat
;
import
android.os.Handler
;
import
android.os.Handler
;
import
android.os.Looper
;
import
android.os.Looper
;
import
android.os.SystemClock
;
import
android.os.SystemClock
;
...
@@ -37,7 +38,6 @@ import androidx.annotation.Nullable;
...
@@ -37,7 +38,6 @@ import androidx.annotation.Nullable;
import
androidx.test.core.app.ApplicationProvider
;
import
androidx.test.core.app.ApplicationProvider
;
import
androidx.test.ext.junit.runners.AndroidJUnit4
;
import
androidx.test.ext.junit.runners.AndroidJUnit4
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.ExoPlaybackException
;
import
com.google.android.exoplayer2.Format
;
import
com.google.android.exoplayer2.Format
;
import
com.google.android.exoplayer2.Renderer
;
import
com.google.android.exoplayer2.Renderer
;
import
com.google.android.exoplayer2.RendererCapabilities
;
import
com.google.android.exoplayer2.RendererCapabilities
;
...
@@ -113,9 +113,9 @@ public class MediaCodecVideoRendererTest {
...
@@ -113,9 +113,9 @@ public class MediaCodecVideoRendererTest {
}
}
@Override
@Override
protected
void
onOutputFormatChanged
(
Format
output
Format
)
{
protected
void
onOutputFormatChanged
(
Format
format
,
@Nullable
MediaFormat
media
Format
)
{
super
.
onOutputFormatChanged
(
output
Format
);
super
.
onOutputFormatChanged
(
format
,
media
Format
);
currentOutputFormat
=
outputF
ormat
;
currentOutputFormat
=
f
ormat
;
}
}
};
};
...
@@ -458,59 +458,4 @@ public class MediaCodecVideoRendererTest {
...
@@ -458,59 +458,4 @@ public class MediaCodecVideoRendererTest {
shadowLooper
.
idle
();
shadowLooper
.
idle
();
verify
(
eventListener
,
times
(
2
)).
onRenderedFirstFrame
(
any
());
verify
(
eventListener
,
times
(
2
)).
onRenderedFirstFrame
(
any
());
}
}
@Test
public
void
onVideoFrameProcessingOffset_isCalledAfterOutputFormatChanges
()
throws
ExoPlaybackException
{
Format
mp4Uhd
=
VIDEO_H264
.
buildUpon
().
setWidth
(
3840
).
setHeight
(
2160
).
build
();
FakeSampleStream
fakeSampleStream
=
new
FakeSampleStream
(
/* mediaSourceEventDispatcher= */
null
,
DrmSessionManager
.
DUMMY
,
new
DrmSessionEventListener
.
EventDispatcher
(),
/* initialFormat= */
mp4Uhd
,
ImmutableList
.
of
(
oneByteSample
(
/* timeUs= */
0
,
C
.
BUFFER_FLAG_KEY_FRAME
),
format
(
VIDEO_H264
),
oneByteSample
(
/* timeUs= */
50
,
C
.
BUFFER_FLAG_KEY_FRAME
),
oneByteSample
(
/* timeUs= */
100
),
format
(
mp4Uhd
),
oneByteSample
(
/* timeUs= */
150
,
C
.
BUFFER_FLAG_KEY_FRAME
),
oneByteSample
(
/* timeUs= */
200
),
oneByteSample
(
/* timeUs= */
250
),
format
(
VIDEO_H264
),
oneByteSample
(
/* timeUs= */
300
,
C
.
BUFFER_FLAG_KEY_FRAME
),
FakeSampleStreamItem
.
END_OF_STREAM_ITEM
));
mediaCodecVideoRenderer
.
enable
(
RendererConfiguration
.
DEFAULT
,
new
Format
[]
{
mp4Uhd
},
fakeSampleStream
,
/* positionUs= */
0
,
/* joining= */
false
,
/* mayRenderStartOfStream= */
true
,
/* offsetUs */
0
);
mediaCodecVideoRenderer
.
setCurrentStreamFinal
();
mediaCodecVideoRenderer
.
start
();
int
positionUs
=
10
;
do
{
mediaCodecVideoRenderer
.
render
(
positionUs
,
SystemClock
.
elapsedRealtime
()
*
1000
);
positionUs
+=
10
;
}
while
(!
mediaCodecVideoRenderer
.
isEnded
());
mediaCodecVideoRenderer
.
stop
();
shadowOf
(
testMainLooper
).
idle
();
InOrder
orderVerifier
=
inOrder
(
eventListener
);
orderVerifier
.
verify
(
eventListener
).
onVideoFrameProcessingOffset
(
anyLong
(),
eq
(
1
),
eq
(
mp4Uhd
));
orderVerifier
.
verify
(
eventListener
)
.
onVideoFrameProcessingOffset
(
anyLong
(),
eq
(
2
),
eq
(
VIDEO_H264
));
orderVerifier
.
verify
(
eventListener
).
onVideoFrameProcessingOffset
(
anyLong
(),
eq
(
3
),
eq
(
mp4Uhd
));
orderVerifier
.
verify
(
eventListener
)
.
onVideoFrameProcessingOffset
(
anyLong
(),
eq
(
1
),
eq
(
VIDEO_H264
));
orderVerifier
.
verifyNoMoreInteractions
();
}
}
}
testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeVideoRenderer.java
View file @
71fd335b
...
@@ -67,9 +67,7 @@ public class FakeVideoRenderer extends FakeRenderer {
...
@@ -67,9 +67,7 @@ public class FakeVideoRenderer extends FakeRenderer {
super
.
onStopped
();
super
.
onStopped
();
eventDispatcher
.
droppedFrames
(
/* droppedFrameCount= */
0
,
/* elapsedMs= */
0
);
eventDispatcher
.
droppedFrames
(
/* droppedFrameCount= */
0
,
/* elapsedMs= */
0
);
eventDispatcher
.
reportVideoFrameProcessingOffset
(
eventDispatcher
.
reportVideoFrameProcessingOffset
(
/* totalProcessingOffsetUs= */
400000
,
/* totalProcessingOffsetUs= */
400000
,
/* frameCount= */
10
);
/* frameCount= */
10
,
Assertions
.
checkNotNull
(
format
));
}
}
@Override
@Override
...
...
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