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
1a34de59
authored
Feb 16, 2021
by
olly
Committed by
kim-vde
Feb 19, 2021
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Add plumbing for reporting internal decoder errors
PiperOrigin-RevId: 357732695
parent
e009322e
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
188 additions
and
26 deletions
RELEASENOTES.md
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/AudioRendererEventListener.java
library/core/src/main/java/com/google/android/exoplayer2/audio/DecoderAudioRenderer.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/source/MediaSourceEventListener.java
library/core/src/main/java/com/google/android/exoplayer2/video/DecoderVideoRenderer.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
RELEASENOTES.md
View file @
1a34de59
...
...
@@ -9,6 +9,8 @@
*
Audio:
*
Fix
`SimpleExoPlayer`
reporting audio session ID as 0 in some cases
(
[
#8585
](
https://github.com/google/ExoPlayer/issues/8585
)
).
*
Analytics:
*
Add
`onAudioCodecError`
and
`onVideoCodecError`
to
`AnalyticsListener`
.
*
Library restructuring:
*
`DebugTextViewHelper`
moved from
`ui`
package to
`util`
package.
*
Spherical UI components moved from
`video.spherical`
package to
...
...
library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java
View file @
1a34de59
...
...
@@ -2098,6 +2098,11 @@ public class SimpleExoPlayer extends BasePlayer
analyticsCollector
.
onVideoFrameProcessingOffset
(
totalProcessingOffsetUs
,
frameCount
);
}
@Override
public
void
onVideoCodecError
(
Exception
videoCodecError
)
{
analyticsCollector
.
onVideoCodecError
(
videoCodecError
);
}
// AudioRendererEventListener implementation
@Override
...
...
@@ -2156,6 +2161,11 @@ public class SimpleExoPlayer extends BasePlayer
analyticsCollector
.
onAudioSinkError
(
audioSinkError
);
}
@Override
public
void
onAudioCodecError
(
Exception
audioCodecError
)
{
analyticsCollector
.
onAudioCodecError
(
audioCodecError
);
}
// TextOutput implementation
@Override
...
...
library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsCollector.java
View file @
1a34de59
...
...
@@ -309,6 +309,15 @@ public class AnalyticsCollector
listener
->
listener
.
onAudioSinkError
(
eventTime
,
audioSinkError
));
}
@Override
public
final
void
onAudioCodecError
(
Exception
audioCodecError
)
{
EventTime
eventTime
=
generateReadingMediaPeriodEventTime
();
sendEvent
(
eventTime
,
AnalyticsListener
.
EVENT_AUDIO_CODEC_ERROR
,
listener
->
listener
.
onAudioCodecError
(
eventTime
,
audioCodecError
));
}
// Additional audio events.
/**
...
...
@@ -456,6 +465,15 @@ public class AnalyticsCollector
listener
.
onVideoFrameProcessingOffset
(
eventTime
,
totalProcessingOffsetUs
,
frameCount
));
}
@Override
public
final
void
onVideoCodecError
(
Exception
videoCodecError
)
{
EventTime
eventTime
=
generateReadingMediaPeriodEventTime
();
sendEvent
(
eventTime
,
AnalyticsListener
.
EVENT_VIDEO_CODEC_ERROR
,
listener
->
listener
.
onVideoCodecError
(
eventTime
,
videoCodecError
));
}
// Additional video events.
/**
...
...
library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsListener.java
View file @
1a34de59
...
...
@@ -17,6 +17,8 @@ package com.google.android.exoplayer2.analytics;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Assertions
.
checkNotNull
;
import
android.media.MediaCodec
;
import
android.media.MediaCodec.CodecException
;
import
android.os.Looper
;
import
android.util.SparseArray
;
import
android.view.Surface
;
...
...
@@ -35,6 +37,7 @@ import com.google.android.exoplayer2.Timeline;
import
com.google.android.exoplayer2.audio.AudioAttributes
;
import
com.google.android.exoplayer2.audio.AudioSink
;
import
com.google.android.exoplayer2.decoder.DecoderCounters
;
import
com.google.android.exoplayer2.decoder.DecoderException
;
import
com.google.android.exoplayer2.decoder.DecoderReuseEvaluation
;
import
com.google.android.exoplayer2.metadata.Metadata
;
import
com.google.android.exoplayer2.source.LoadEventInfo
;
...
...
@@ -198,6 +201,8 @@ public interface AnalyticsListener {
EVENT_DRM_KEYS_REMOVED
,
EVENT_DRM_SESSION_RELEASED
,
EVENT_PLAYER_RELEASED
,
EVENT_AUDIO_CODEC_ERROR
,
EVENT_VIDEO_CODEC_ERROR
,
})
@interface
EventFlags
{}
/** {@link Player#getCurrentTimeline()} changed. */
...
...
@@ -312,6 +317,10 @@ public interface AnalyticsListener {
int
EVENT_DRM_SESSION_RELEASED
=
1035
;
/** The player was released. */
int
EVENT_PLAYER_RELEASED
=
1036
;
/** The audio codec encountered an error. */
int
EVENT_AUDIO_CODEC_ERROR
=
1037
;
/** The video codec encountered an error. */
int
EVENT_VIDEO_CODEC_ERROR
=
1038
;
/** Time information of an event. */
final
class
EventTime
{
...
...
@@ -649,8 +658,14 @@ public interface AnalyticsListener {
EventTime
eventTime
,
LoadEventInfo
loadEventInfo
,
MediaLoadData
mediaLoadData
)
{}
/**
* Called when a media source loading error occurred. These errors are just for informational
* purposes and the player may recover.
* Called when a media source loading error occurred.
*
* <p>This method being called does not indicate that playback has failed, or that it will fail.
* The player may be able to recover from the error. Hence applications should <em>not</em>
* implement this method to display a user visible error or initiate an application level retry.
* {@link Player.EventListener#onPlayerError} is the appropriate place to implement such behavior.
* This method is called to provide the application with an opportunity to log the error if it
* wishes to do so.
*
* @param eventTime The event time.
* @param loadEventInfo The {@link LoadEventInfo} defining the load event.
...
...
@@ -829,8 +844,14 @@ public interface AnalyticsListener {
default
void
onSkipSilenceEnabledChanged
(
EventTime
eventTime
,
boolean
skipSilenceEnabled
)
{}
/**
* Called when {@link AudioSink} has encountered an error. These errors are just for informational
* purposes and the player may recover.
* Called when {@link AudioSink} has encountered an error.
*
* <p>This method being called does not indicate that playback has failed, or that it will fail.
* The player may be able to recover from the error. Hence applications should <em>not</em>
* implement this method to display a user visible error or initiate an application level retry.
* {@link Player.EventListener#onPlayerError} is the appropriate place to implement such behavior.
* This method is called to provide the application with an opportunity to log the error if it
* wishes to do so.
*
* @param eventTime The event time.
* @param audioSinkError Either a {@link AudioSink.InitializationException} or a {@link
...
...
@@ -839,6 +860,22 @@ public interface AnalyticsListener {
default
void
onAudioSinkError
(
EventTime
eventTime
,
Exception
audioSinkError
)
{}
/**
* Called when an audio decoder encounters an error.
*
* <p>This method being called does not indicate that playback has failed, or that it will fail.
* The player may be able to recover from the error. Hence applications should <em>not</em>
* implement this method to display a user visible error or initiate an application level retry.
* {@link Player.EventListener#onPlayerError} is the appropriate place to implement such behavior.
* This method is called to provide the application with an opportunity to log the error if it
* wishes to do so.
*
* @param eventTime The event time.
* @param audioCodecError The error. Typically a {@link CodecException} if the renderer uses
* {@link MediaCodec}, or a {@link DecoderException} if the renderer uses a software decoder.
*/
default
void
onAudioCodecError
(
EventTime
eventTime
,
Exception
audioCodecError
)
{}
/**
* Called when the volume changes.
*
* @param eventTime The event time.
...
...
@@ -932,6 +969,22 @@ public interface AnalyticsListener {
EventTime
eventTime
,
long
totalProcessingOffsetUs
,
int
frameCount
)
{}
/**
* Called when a video decoder encounters an error.
*
* <p>This method being called does not indicate that playback has failed, or that it will fail.
* The player may be able to recover from the error. Hence applications should <em>not</em>
* implement this method to display a user visible error or initiate an application level retry.
* {@link Player.EventListener#onPlayerError} is the appropriate place to implement such behavior.
* This method is called to provide the application with an opportunity to log the error if it
* wishes to do so.
*
* @param eventTime The event time.
* @param videoCodecError The error. Typically a {@link CodecException} if the renderer uses
* {@link MediaCodec}, or a {@link DecoderException} if the renderer uses a software decoder.
*/
default
void
onVideoCodecError
(
EventTime
eventTime
,
Exception
videoCodecError
)
{}
/**
* Called when a frame is rendered for the first time since setting the surface, or since the
* renderer was reset, or since the stream being rendered was changed.
*
...
...
@@ -987,8 +1040,14 @@ public interface AnalyticsListener {
default
void
onDrmKeysLoaded
(
EventTime
eventTime
)
{}
/**
* Called when a drm error occurs. These errors are just for informational purposes and the player
* may recover.
* Called when a drm error occurs.
*
* <p>This method being called does not indicate that playback has failed, or that it will fail.
* The player may be able to recover from the error. Hence applications should <em>not</em>
* implement this method to display a user visible error or initiate an application level retry.
* {@link Player.EventListener#onPlayerError} is the appropriate place to implement such behavior.
* This method is called to provide the application with an opportunity to log the error if it
* wishes to do so.
*
* @param eventTime The event time.
* @param error The error.
...
...
library/core/src/main/java/com/google/android/exoplayer2/audio/AudioRendererEventListener.java
View file @
1a34de59
...
...
@@ -18,15 +18,17 @@ package com.google.android.exoplayer2.audio;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Util
.
castNonNull
;
import
android.media.AudioTrack
;
import
android.media.MediaCodec
;
import
android.media.MediaCodec.CodecException
;
import
android.os.Handler
;
import
android.os.SystemClock
;
import
androidx.annotation.Nullable
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.ExoPlaybackException
;
import
com.google.android.exoplayer2.Format
;
import
com.google.android.exoplayer2.Player
;
import
com.google.android.exoplayer2.Renderer
;
import
com.google.android.exoplayer2.decoder.DecoderCounters
;
import
com.google.android.exoplayer2.decoder.DecoderException
;
import
com.google.android.exoplayer2.decoder.DecoderReuseEvaluation
;
import
com.google.android.exoplayer2.util.Assertions
;
...
...
@@ -114,24 +116,35 @@ public interface AudioRendererEventListener {
default
void
onSkipSilenceEnabledChanged
(
boolean
skipSilenceEnabled
)
{}
/**
* Called when an audio decoder encounters an error.
*
* <p>This method being called does not indicate that playback has failed, or that it will fail.
* The player may be able to recover from the error. Hence applications should <em>not</em>
* implement this method to display a user visible error or initiate an application level retry.
* {@link Player.EventListener#onPlayerError} is the appropriate place to implement such behavior.
* This method is called to provide the application with an opportunity to log the error if it
* wishes to do so.
*
* @param audioCodecError The error. Typically a {@link CodecException} if the renderer uses
* {@link MediaCodec}, or a {@link DecoderException} if the renderer uses a software decoder.
*/
default
void
onAudioCodecError
(
Exception
audioCodecError
)
{}
/**
* Called when {@link AudioSink} has encountered an error.
*
* <p>If the sink writes to a platform {@link AudioTrack}, this will called for all {@link
* AudioTrack} errors.
*
* <p>This method being called does not indicate that playback has failed, or that it will fail.
* The player may be able to recover from the error (for example by recreating the AudioTrack,
* possibly with different settings) and continue. Hence applications should <em>not</em>
* implement this method to display a user visible error or initiate an application level retry
* ({@link Player.EventListener#onPlayerError} is the appropriate place to implement such
* behavior). This method is called to provide the application with an opportunity to log the
* error if it wishes to do so.
* The player may be able to recover from the error. Hence applications should <em>not</em>
* implement this method to display a user visible error or initiate an application level retry.
* {@link Player.EventListener#onPlayerError} is the appropriate place to implement such behavior.
* This method is called to provide the application with an opportunity to log the error if it
* wishes to do so.
*
* <p>Fatal errors that cannot be recovered will be reported wrapped in a {@link
* ExoPlaybackException} by {@link Player.EventListener#onPlayerError(ExoPlaybackException)}.
*
* @param audioSinkError Either an {@link AudioSink.InitializationException} or a {@link
* AudioSink.WriteException} describing the error.
* @param audioSinkError The error that occurred. Typically an {@link
* AudioSink.InitializationException} or a {@link AudioSink.WriteException}.
*/
default
void
onAudioSinkError
(
Exception
audioSinkError
)
{}
...
...
@@ -230,5 +243,12 @@ public interface AudioRendererEventListener {
handler
.
post
(()
->
castNonNull
(
listener
).
onAudioSinkError
(
audioSinkError
));
}
}
/** Invokes {@link AudioRendererEventListener#onAudioCodecError(Exception)}. */
public
void
audioCodecError
(
Exception
audioCodecError
)
{
if
(
handler
!=
null
)
{
handler
.
post
(()
->
castNonNull
(
listener
).
onAudioCodecError
(
audioCodecError
));
}
}
}
}
library/core/src/main/java/com/google/android/exoplayer2/audio/DecoderAudioRenderer.java
View file @
1a34de59
...
...
@@ -300,6 +300,7 @@ public abstract class DecoderAudioRenderer<
while
(
feedInputBuffer
())
{}
TraceUtil
.
endSection
();
}
catch
(
DecoderException
e
)
{
eventDispatcher
.
audioCodecError
(
e
);
throw
createRendererException
(
e
,
inputFormat
);
}
catch
(
AudioSink
.
ConfigurationException
e
)
{
throw
createRendererException
(
e
,
e
.
format
);
...
...
@@ -618,7 +619,10 @@ public abstract class DecoderAudioRenderer<
eventDispatcher
.
decoderInitialized
(
decoder
.
getName
(),
codecInitializedTimestamp
,
codecInitializedTimestamp
-
codecInitializingTimestamp
);
decoderCounters
.
decoderInitCount
++;
}
catch
(
DecoderException
|
OutOfMemoryError
e
)
{
}
catch
(
DecoderException
e
)
{
eventDispatcher
.
audioCodecError
(
e
);
throw
createRendererException
(
e
,
inputFormat
);
}
catch
(
OutOfMemoryError
e
)
{
throw
createRendererException
(
e
,
inputFormat
);
}
}
...
...
library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java
View file @
1a34de59
...
...
@@ -415,6 +415,11 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
}
@Override
protected
void
onCodecError
(
Exception
codecError
)
{
eventDispatcher
.
audioCodecError
(
codecError
);
}
@Override
@Nullable
protected
DecoderReuseEvaluation
onInputFormatChanged
(
FormatHolder
formatHolder
)
throws
ExoPlaybackException
{
...
...
library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java
View file @
1a34de59
...
...
@@ -848,6 +848,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
decoderCounters
.
ensureUpdated
();
}
catch
(
IllegalStateException
e
)
{
if
(
isMediaCodecException
(
e
))
{
onCodecError
(
e
);
boolean
isRecoverable
=
enableRecoverableCodecExceptionRetries
&&
Util
.
SDK_INT
>=
21
...
...
@@ -1407,6 +1408,17 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
}
/**
* Called when a codec error has occurred.
*
* <p>The default implementation is a no-op.
*
* @param codecError The error.
*/
protected
void
onCodecError
(
Exception
codecError
)
{
// Do nothing.
}
/**
* Called when a new {@link Format} is read from the upstream {@link MediaPeriod}.
*
* @param formatHolder A {@link FormatHolder} that holds the new {@link Format}.
...
...
library/core/src/main/java/com/google/android/exoplayer2/source/MediaSourceEventListener.java
View file @
1a34de59
...
...
@@ -92,11 +92,11 @@ public interface MediaSourceEventListener {
* <em>not</em> be called in addition to this method.
*
* <p>This method being called does not indicate that playback has failed, or that it will fail.
* The player may be able to recover from the error
and continue. Hence applications should
*
<em>not</em> implement this method to display a user visible error or initiate an application
*
level retry ({@link Player.EventListener#onPlayerError} is the appropriate place to implement
*
such behavior). This method is called to provide the application with an opportunity to log the
*
error if it
wishes to do so.
* The player may be able to recover from the error
. Hence applications should <em>not</em>
*
implement this method to display a user visible error or initiate an application level retry.
*
{@link Player.EventListener#onPlayerError} is the appropriate place to implement such behavior.
*
This method is called to provide the application with an opportunity to log the error if it
* wishes to do so.
*
* @param windowIndex The window index in the timeline of the media source this load belongs to.
* @param mediaPeriodId The {@link MediaPeriodId} this load belongs to. Null if the load does not
...
...
library/core/src/main/java/com/google/android/exoplayer2/video/DecoderVideoRenderer.java
View file @
1a34de59
...
...
@@ -206,6 +206,7 @@ public abstract class DecoderVideoRenderer extends BaseRenderer {
while
(
feedInputBuffer
())
{}
TraceUtil
.
endSection
();
}
catch
(
DecoderException
e
)
{
eventDispatcher
.
videoCodecError
(
e
);
throw
createRendererException
(
e
,
inputFormat
);
}
decoderCounters
.
ensureUpdated
();
...
...
@@ -707,7 +708,10 @@ public abstract class DecoderVideoRenderer extends BaseRenderer {
decoderInitializedTimestamp
,
decoderInitializedTimestamp
-
decoderInitializingTimestamp
);
decoderCounters
.
decoderInitCount
++;
}
catch
(
DecoderException
|
OutOfMemoryError
e
)
{
}
catch
(
DecoderException
e
)
{
eventDispatcher
.
videoCodecError
(
e
);
throw
createRendererException
(
e
,
inputFormat
);
}
catch
(
OutOfMemoryError
e
)
{
throw
createRendererException
(
e
,
inputFormat
);
}
}
...
...
library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java
View file @
1a34de59
...
...
@@ -691,6 +691,11 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
}
@Override
protected
void
onCodecError
(
Exception
codecError
)
{
eventDispatcher
.
videoCodecError
(
codecError
);
}
@Override
@Nullable
protected
DecoderReuseEvaluation
onInputFormatChanged
(
FormatHolder
formatHolder
)
throws
ExoPlaybackException
{
...
...
library/core/src/main/java/com/google/android/exoplayer2/video/VideoRendererEventListener.java
View file @
1a34de59
...
...
@@ -17,14 +17,18 @@ package com.google.android.exoplayer2.video;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Util
.
castNonNull
;
import
android.media.MediaCodec
;
import
android.media.MediaCodec.CodecException
;
import
android.os.Handler
;
import
android.os.SystemClock
;
import
android.view.Surface
;
import
android.view.TextureView
;
import
androidx.annotation.Nullable
;
import
com.google.android.exoplayer2.Format
;
import
com.google.android.exoplayer2.Player
;
import
com.google.android.exoplayer2.Renderer
;
import
com.google.android.exoplayer2.decoder.DecoderCounters
;
import
com.google.android.exoplayer2.decoder.DecoderException
;
import
com.google.android.exoplayer2.decoder.DecoderReuseEvaluation
;
import
com.google.android.exoplayer2.util.Assertions
;
...
...
@@ -147,8 +151,21 @@ public interface VideoRendererEventListener {
default
void
onVideoDisabled
(
DecoderCounters
counters
)
{}
/**
* Dispatches events to a {@link VideoRendererEventListener}.
* Called when a video decoder encounters an error.
*
* <p>This method being called does not indicate that playback has failed, or that it will fail.
* The player may be able to recover from the error. Hence applications should <em>not</em>
* implement this method to display a user visible error or initiate an application level retry.
* {@link Player.EventListener#onPlayerError} is the appropriate place to implement such behavior.
* This method is called to provide the application with an opportunity to log the error if it
* wishes to do so.
*
* @param videoCodecError The error. Typically a {@link CodecException} if the renderer uses
* {@link MediaCodec}, or a {@link DecoderException} if the renderer uses a software decoder.
*/
default
void
onVideoCodecError
(
Exception
videoCodecError
)
{}
/** Dispatches events to a {@link VideoRendererEventListener}. */
final
class
EventDispatcher
{
@Nullable
private
final
Handler
handler
;
...
...
@@ -254,6 +271,12 @@ public interface VideoRendererEventListener {
}
}
/** Invokes {@link VideoRendererEventListener#onVideoCodecError(Exception)}. */
public
void
videoCodecError
(
Exception
videoCodecError
)
{
if
(
handler
!=
null
)
{
handler
.
post
(()
->
castNonNull
(
listener
).
onVideoCodecError
(
videoCodecError
));
}
}
}
}
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