- Core library:
- Verify correct thread usage in
SimpleExoPlayer
by default. Opt-out is still possible until the next major release usingsetThrowsWhenUsingWrongThread(false)
(#4463). - Add
Player.getCurrentStaticMetadata
andEventListener.onStaticMetadataChanged
to expose static metadata belonging to the currently playing stream (#7266). - Add
PlayerMessage.setLooper
and deprecatePlayerMessage.setHandler
. - Add option to
MergingMediaSource
to clip the durations of all sources to have the same length (#8422). - Remove
Player.setVideoDecoderOutputBufferRenderer
from Player API. UsesetVideoSurfaceView
andclearVideoSurfaceView
instead. - Default
SingleSampleMediaSource.treatLoadErrorsAsEndOfStream
totrue
so that errors loading external subtitle files do not cause playback to fail (#8430). A warning will be logged bySingleSampleMediaPeriod
whenever a load error is treated as though the end of the stream has been reached. - Time out on release to prevent ANRs if an underlying platform call is stuck (#4352).
- Time out when detaching a surface to prevent ANRs if the underlying platform call is stuck (#5887).
- Fix bug where
AnalyticsListener
callbacks could arrive in the wrong order (#8048).
- Verify correct thread usage in
- Media transformation:
- Add a new
transformer
module for converting media streams. The initially available transformations are changing the container format, removing tracks, and slow motion flattening.
- Add a new
- Low latency live streaming:
- Support low-latency DASH (also known as ULL-CMAF) and Apple's low-latency HLS extension.
- Add
LiveConfiguration
toMediaItem
to define live offset and playback speed adjustment parameters. The same parameters can be set onDefaultMediaSourceFactory
to apply for allMediaItems
. - Add
LivePlaybackSpeedControl
to control playback speed adjustments during live playbacks. Such adjustments allow the player to stay close to the live offset.DefaultLivePlaybackSpeedControl
is provided as a default implementation. - Add
targetLiveOffsetUs
parameter toLoadControl.shouldStartPlayback
.
- Extractors:
- Populate codecs string for H.264/AVC in MP4, Matroska and FLV streams to allow decoder capability checks based on codec profile and level (#8393).
- Populate codecs string for H.265/HEVC in MP4, Matroska and MPEG-TS streams to allow decoder capability checks based on codec profile and level (#8393).
- Add support for playing JPEG motion photos (#5405).
- Handle sample size mismatches between raw audio
stsd
information andstsz
fixed sample size in MP4 extractors. - Fix Vorbis private codec data parsing in the Matroska extractor (#8496).
- Track selection:
- Move
Player.getTrackSelector
to theExoPlayer
interface. - Move the mutable parts of
TrackSelection
into anExoTrackSelection
subclass. - Allow parallel adaptation of video and audio (#5111).
- Simplify enabling tunneling with
DefaultTrackSelector
.ParametersBuilder.setTunnelingAudioSessionId
has been replaced withParametersBuilder.setTunnelingEnabled
. The player's audio session ID will be used, and so a tunneling specific ID is no longer needed. - Add additional configuration parameters to
DefaultTrackSelector
.DefaultTrackSelector.ParametersBuilder
now includes:setPreferredVideoMimeType
,setPreferredVideoMimeTypes
,setPreferredAudioMimeType
andsetPreferredAudioMimeTypes
for specifying preferred video and audio MIME type(s) (#8320).setPreferredAudioLanguages
andsetPreferredTextLanguages
for specifying multiple preferred audio and text languages.setPreferredAudioRoleFlags
for specifying preferred audio role flags.
- Forward
Timeline
andMediaPeriodId
toTrackSelection.Factory
.
- Move
- DASH:
- HLS:
- Support playlist delta updates, blocking playlist reloads and rendition reports.
- Support low-latency HLS playback (
EXT-X-PART
and preload hints) (#5011).
- UI:
- Improve
StyledPlayerControlView
button animations. - Miscellaneous fixes for
StyledPlayerControlView
in minimal mode.
- Improve
- DRM:
- Fix playback failure when switching from PlayReady protected content to Widevine or Clearkey protected content in a playlist.
- Add
ExoMediaDrm.KeyRequest.getRequestType
(#7847). - Drop key and provision responses if
DefaultDrmSession
is released while waiting for the response. This prevents harmless log messages of the form:IllegalStateException: sending message to a Handler on a dead thread
(#8328). - Allow apps to fully customize DRM behaviour for each
MediaItem
by passing aDrmSessionManagerProvider
toMediaSourceFactory
(#8466).
- Analytics:
- Add an
onEvents
callback toPlayer.EventListener
andAnalyticsListener
. When one or more player states change simultaneously,onEvents
is called once after all of the callbacks associated with the individual state changes. - Pass a
DecoderReuseEvaluation
toAnalyticsListener
'sonVideoInputFormatChanged
andonAudioInputFormatChanged
methods. TheDecoderReuseEvaluation
indicates whether it was possible to re-use an existing decoder instance for the new format, and if not then the reasons why.
- Add an
- Video:
- Fall back to AVC/HEVC decoders for Dolby Vision streams with level 10 to 13 (#8530).
- Fix VP9 format capability checks on API level 23 and earlier. The platform does not correctly report the VP9 level supported by the decoder in this case, so we estimate it based on the decoder's maximum supported bitrate.
- Audio:
- Fix handling of audio session IDs (#8190).
SimpleExoPlayer
now generates an audio session ID on construction, which can be immediately queried by callingSimpleExoPlayer.getAudioSessionId
. The audio session ID will only change if application code callsSimpleExoPlayer.setAudioSessionId
. - Replace
onAudioSessionId
withonAudioSessionIdChanged
inAudioListener
andAnalyticsListener
. Note thatonAudioSessionIdChanged
is called in fewer cases thanonAudioSessionId
was called, due to the improved handling of audio session IDs as described above. - Retry playback after some types of
AudioTrack
error. - Create E-AC3 JOC passthrough
AudioTrack
instances using the maximum supported channel count (instead of assuming 6 channels) from API 29.
- Fix handling of audio session IDs (#8190).
- Text:
- Data sources:
- For
HttpDataSource
implementations, default to using the user agent of the underlying network stack. - Deprecate
HttpDataSource.Factory.getDefaultRequestProperties
.HttpDataSource.Factory.setDefaultRequestProperties
instead. - Add
DefaultHttpDataSource.Factory
and deprecateDefaultHttpDataSourceFactory
.
- For
- Metadata retriever:
- Parse Google Photos HEIC and JPEG motion photo metadata.
- IMA extension:
- Add support for playback of ads in playlists (#3750).
- Add
ImaAdsLoader.Builder.setEnableContinuousPlayback
for setting whether to request ads for continuous playback. - Upgrade IMA SDK dependency to 3.22.0. This fixes leaking of the ad view group (#7344, #8339).
- Fix a bug that could cause the next content position played after a seek to snap back to the cue point of the preceding ad, rather than the requested content position.
- Fix a regression that caused an ad group to be skipped after an initial seek to a non-zero position. Unsupported VPAID ads will still be skipped, but only after the preload timeout rather than instantly (#8428, #7832).
- Fix a regression that caused a short ad followed by another ad to be skipped due to playback being stuck buffering waiting for the second ad to load (#8492).
- FFmpeg extension:
- Link the FFmpeg library statically, saving 350KB in binary size on average.
- OkHttp extension:
- Add
OkHttpDataSource.Factory
and deprecateOkHttpDataSourceFactory
.
- Add
- Cronet extension:
- Add
CronetDataSource.Factory
and deprecateCronetDataSourceFactory
. - Support setting the user agent on
CronetDataSource.Factory
andCronetEngineWrapper
.
- Add
- MediaSession extension:
- Support
setPlaybackSpeed(float)
and disable it by default. UseMediaSessionConnector.setEnabledPlaybackActions(long)
to enable (#8229).
- Support
- Remove deprecated symbols:
AdaptiveMediaSourceEventListener
. UseMediaSourceEventListener
instead.DashMediaSource.Factory.setMinLoadableRetryCount(int)
. UseDashMediaSource.Factory.setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)
instead.DefaultAnalyticsListener
. UseAnalyticsListener
instead.DefaultLoadControl
constructors. UseDefaultLoadControl.Builder
instead.DrmInitData.get(UUID)
. UseDrmInitData.get(int)
andDrmInitData.SchemeData.matches(UUID)
instead.ExtractorsMediaSource.Factory.setMinLoadableRetryCount(int)
. UseExtractorsMediaSource.Factory.setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)
instead.FixedTrackSelection.Factory
. If you need to disable adaptive selection inDefaultTrackSelector
, enable theDefaultTrackSelector.Parameters.forceHighestSupportedBitrate
flag.HlsMediaSource.Factory.setMinLoadableRetryCount(int)
. UseHlsMediaSource.Factory.setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)
instead.MappedTrackInfo.getTrackFormatSupport(int, int, int)
. UseMappedTrackInfo.getTrackSupport(int, int, int)
instead.MappedTrackInfo.getTrackTypeRendererSupport(int)
. UseMappedTrackInfo.getTypeSupport(int)
instead.MappedTrackInfo.getUnassociatedTrackGroups()
. UseMappedTrackInfo.getUnmappedTrackGroups()
instead.MappedTrackInfo.length
. UseMappedTrackInfo.getRendererCount()
instead.Player.DefaultEventListener.onTimelineChanged(Timeline, Object)
. UsePlayer.EventListener.onTimelineChanged(Timeline, int)
instead.Player.setAudioAttributes(AudioAttributes)
. UsePlayer.AudioComponent.setAudioAttributes(AudioAttributes, boolean)
instead.PlayerView.setDefaultArtwork(Bitmap)
. UsePlayerView.setDefaultArtwork(Drawable)
instead.PlayerView.setShowBuffering(boolean)
. UsePlayerView.setShowBuffering(int)
instead.SimpleExoPlayer.clearMetadataOutput(MetadataOutput)
. UseSimpleExoPlayer.removeMetadataOutput(MetadataOutput)
instead.SimpleExoPlayer.clearTextOutput(TextOutput)
. UseSimpleExoPlayer.removeTextOutput(TextOutput)
instead.SimpleExoPlayer.clearVideoListener()
. UseSimpleExoPlayer.removeVideoListener(VideoListener)
instead.SimpleExoPlayer.getAudioStreamType()
. UseSimpleExoPlayer.getAudioAttributes()
instead.SimpleExoPlayer.setAudioDebugListener(AudioRendererEventListener)
. UseSimpleExoPlayer.addAnalyticsListener(AnalyticsListener)
instead.SimpleExoPlayer.setAudioStreamType(int)
. UseSimpleExoPlayer.setAudioAttributes(AudioAttributes)
instead.SimpleExoPlayer.setMetadataOutput(MetadataOutput)
. UseSimpleExoPlayer.addMetadataOutput(MetadataOutput)
instead. If your application is callingSimpleExoPlayer.setMetadataOutput(null)
, make sure to replace this call with a call toSimpleExoPlayer.removeMetadataOutput(MetadataOutput)
.SimpleExoPlayer.setPlaybackParams(PlaybackParams)
. UseSimpleExoPlayer.setPlaybackParameters(PlaybackParameters)
instead.SimpleExoPlayer.setTextOutput(TextOutput)
. UseSimpleExoPlayer.addTextOutput(TextOutput)
instead. If your application is callingSimpleExoPlayer.setTextOutput(null)
, make sure to replace this call with a call toSimpleExoPlayer.removeTextOutput(TextOutput)
.SimpleExoPlayer.setVideoDebugListener(VideoRendererEventListener)
. UseSimpleExoPlayer.addAnalyticsListener(AnalyticsListener)
instead.SimpleExoPlayer.setVideoListener(VideoListener)
. UseSimpleExoPlayer.addVideoListener(VideoListener)
instead. If your application is callingSimpleExoPlayer.setVideoListener(null)
, make sure to replace this call with a call toSimpleExoPlayer.removeVideoListener(VideoListener)
.SimpleExoPlayer.VideoListener
. Usecom.google.android.exoplayer2.video.VideoListener
instead.SingleSampleMediaSource.EventListener
and constructors. UseMediaSourceEventListener
andSingleSampleMediaSource.Factory
instead.SimpleExoPlayer.addVideoDebugListener
,SimpleExoPlayer.removeVideoDebugListener
,SimpleExoPlayer.addAudioDebugListener
andSimpleExoPlayer.removeAudioDebugListener
. UseSimpleExoPlayer.addAnalyticsListener
andSimpleExoPlayer.removeAnalyticsListener
instead.SingleSampleMediaSource.Factory.setMinLoadableRetryCount(int)
. UseSingleSampleMediaSource.Factory.setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)
instead.SsMediaSource.Factory.setMinLoadableRetryCount(int)
. UseSsMediaSource.Factory.setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)
instead.