1.4.0
This release includes the following changes since the 1.3.1 release:
- Common Library:
- Forward presumed no-op seek calls to the protected
BasePlayer.seekTo()
andSimpleBasePlayer.handleSeek()
methods instead of ignoring them. If you are implementing these methods in a custom player, you may need to handle these additional calls withmediaItemIndex == C.INDEX_UNSET
. - Remove compile dependency on enhanced Java 8 desugaring (#1312).
- Ensure the duration passed to
MediaItem.Builder.setImageDurationMs()
is ignored for a non-imageMediaItem
(as documented). - Add
Format.customData
to store app-provided custom information aboutFormat
instances.
- Forward presumed no-op seek calls to the protected
- ExoPlayer:
- Add
BasePreloadManager
which coordinates the preloading for multiple sources based on the priorities defined by theirrankingData
. Customization is possible by extending this class. AddDefaultPreloadManager
which usesPreloadMediaSource
to preload media samples of the sources into memory, and uses an integerrankingData
that indicates the index of an item on the UI. - Add
PlayerId
to most methods ofLoadControl
to enableLoadControl
implementations to support multiple players. - Remove
Buffer.isDecodeOnly()
andC.BUFFER_FLAG_DECODE_ONLY
. There is no need to set this flag as renderers and decoders will decide to skip buffers based on timestamp. CustomRenderer
implementations should check if the buffer time is at leastBaseRenderer.getLastResetPositionUs()
to decide whether a sample should be shown. CustomSimpleDecoder
implementations can checkisAtLeastOutputStartTimeUs()
if needed or mark other buffers withDecoderOutputBuffer.shouldBeSkipped
to skip them. - Allow a null value to be returned by
TargetPreloadStatusControl.getTargetPreloadStatus(T)
to indicate not to preload aMediaSource
with the givenrankingData
. - Add
remove(MediaSource)
toBasePreloadManager
. - Add
reset()
toBasePreloadManager
to release all the holding sources while keep the preload manager instance. - Add
ExoPlayer.setPriority()
(andBuilder.setPriority()
) to define the priority value used inPriorityTaskManager
and for MediaCodec importance from API 35. - Fix issue with updating the last rebuffer time which resulted in incorrect
bs
(buffer starvation) key in CMCD (#1124). - Add
PreloadMediaSource.PreloadControl.onLoadedToTheEndOfSource(PreloadMediaSource)
to indicate that the source has loaded to the end. This allows theDefaultPreloadManager
and the customPreloadMediaSource.PreloadControl
implementations to preload the next source or take other actions. - Fix bug where silence skipping at the end of items can trigger a playback exception.
- Add
clear
toPreloadMediaSource
to discard the preloading period. - Add new error code
PlaybackException.ERROR_CODE_DECODING_RESOURCES_RECLAIMED
that is used when codec resources are reclaimed for higher priority tasks. - Let
AdsMediaSource
load preroll ads before initial content media preparation completes (#1358). - Fix bug where playback moved to
STATE_ENDED
when re-preparing a multi-period DASH live stream after the original period was already removed from the manifest. - Rename
onTimelineRefreshed()
toonSourcePrepared()
andonPrepared()
toonTracksSelected()
inPreloadMediaSource.PreloadControl
. Also rename the IntDefs inDefaultPreloadManager.Stage
accordingly. - Add experimental support for dynamic scheduling to better align work with CPU wake-cycles and delay waking up to when renderers can progress. You can enable this using
experimentalSetDynamicSchedulingEnabled()
when setting up your ExoPlayer instance. - Add
Renderer.getDurationToProgressUs()
. ARenderer
can implement this method to return to ExoPlayer the duration that playback must advance for the renderer to progress. IfExoPlayer
is set withexperimentalSetDynamicSchedulingEnabled()
thenExoPlayer
will call this method when calculating the time to schedule its work task. - Add
MediaCodecAdapter#OnBufferAvailableListener
to alert when input and output buffers are available for use byMediaCodecRenderer
.MediaCodecRenderer
will signalExoPlayer
when receiving these callbacks and ifExoPlayer
is set withexperimentalSetDynamicSchedulingEnabled()
, thenExoPlayer
will schedule its work loop as renderers can make progress. - Use data class for
LoadControl
methods instead of individual parameters. - Add
ExoPlayer.isReleased()
to check whetherExoplayer.release()
has been called. - Add
ExoPlayer.Builder.setMaxSeekToPreviousPositionMs()
to configure the maximum position for whichseekToPrevious()
seeks to the previous item (#1425). - Fix some audio focus inconsistencies, e.g. not reporting full or transient focus loss while the player is paused (#1436).
- Fix potential
IndexOutOfBoundsException
caused by extractors reporting additional tracks after the initial preparation step (#1476). Effects
inExoPlayer.setVideoEffect()
will receive the timestamps with the renderer offset removed (#1098).- Fix potential
IllegalArgumentException
when handling player error that happened while reading ahead into another playlist item (#1483).
- Add
- Transformer:
- Add
audioConversionProcess
andvideoConversionProcess
toExportResult
indicating how the respective track in the output file was made. - Relax trim optimization H.264 level checks.
- Add support for changing between SDR and HDR input media in a sequence.
- Add support for composition-level audio effects.
- Add support for transcoding Ultra HDR images into HDR videos.
- Fix issue where the
DefaultAudioMixer
does not output the correct amount of bytes after being reset and reused. - Work around a decoder bug where the number of audio channels was capped at stereo when handling PCM input.
- When selecting tracks in
ExoPlayerAssetLoader
, ignore audio channel count constraints as they only apply for playback. - Replace
androidx.media3.transformer.Muxer
interface withandroidx.media3.muxer.Muxer
and removeandroidx.media3.transformer.Muxer
. - Fix HEIC image loading from content URI schemes (#1373).
- Adjust audio track duration in
AudioGraphInput
to improve AV sync. - Remove
ExportResult.processedInputs
field. If you use this field for codec details, then useDefaultDecoderFactory.listener
instead. In case of a codec exception, codec details will be available in theExportException.codecInfo
.
- Add
- Extractors:
- MPEG-TS: Roll forward the change ensuring the last frame is rendered by passing the last access unit of a stream to the sample queue (#7909). Incorporating fixes to resolve the issues that emerged in I-frame only HLS streams(#1150) and H.262 HLS streams (#1126).
- MP3: Prefer the data size from an
Info
frame over the size reported by the underlying stream (e.g. file size, or HTTPContent-Length
header). This helps to exclude non-playable trailer data (e.g. album artwork) from constant bitrate seeking calculations, making seeks more accurate (#1376). - MP3: Use the frame count and other data in an
Info
frame (if present) to compute an average bitrate for constant bitrate seeking, rather than extrapolating from the bitrate of the frame after theInfo
frame, which may be artificially small, e.g.PCUT
frame (#1376). - Fix PCM audio format extraction in AVI containers.
- Audio:
- Fix DTS:X Profile 2 encoding attributes for passthrough playback (#1299).
- For offloaded playback, reset the tracking field for stream completion in
DefaultAudioSink
prior to callingAudioTrack.stop()
so thatAudioTrack.StreamEventCallback#onPresentationEnded
correctly identifies when all pending data has been played. - Fix bug in
SilenceSkippingAudioProcessor
where transitions between different audio formats (for example stereo to mono) can cause the processor to throw an exception (#1352). - Implement
MediaCodecAudioRenderer.getDurationToProgressUs()
so that ExoPlayer will dynamically schedule its main work loop to when the MediaCodecAudioRenderer can make progress.
- Video:
- Fix issue where
Listener.onRenderedFirstFrame()
arrives too early when switching surfaces mid-playback. - Fix decoder fallback logic for Dolby Vision to use a compatible AV1 decoder if needed (#1389).
- Fix codec exception that may be caused by enabling a video renderer mid-playback.
- Fix issue where
- Text:
- Fix issue where subtitles starting before a seek position are skipped. This issue was only introduced in Media3 1.4.0-alpha01.
- Change default subtitle parsing behavior so it happens during extraction instead of during rendering (see ExoPlayer's architecture diagram for the difference between extraction and rendering).
- This change can be overridden by calling both
MediaSource.Factory.experimentalParseSubtitlesDuringExtraction(false)
andTextRenderer.experimentalSetLegacyDecodingEnabled(true)
. See the [docs on customization (https://developer.android.com/media/media3/exoplayer/customization) for how to plumb these components into anExoPlayer
instance. These methods (and all support for legacy subtitle decoding) will be removed in a future release. - Apps with custom
SubtitleDecoder
implementations need to update them to implementSubtitleParser
instead (andSubtitleParser.Factory
instead ofSubtitleDecoderFactory
).
- This change can be overridden by calling both
- PGS: Fix run-length decoding to resolve
0
as a color index, instead of a literal color value (#1367). - CEA-708: Ignore
rowLock
value. The CEA-708-E S-2023 spec states thatrowLock
andcolumnLock
should both be assumed to be true, regardless of the values present in the stream (columnLock
support is not implemented, so it's effectively assumed to always be false).- This was originally included in the
1.3.0-alpha01
release notes, but the change was accidentally reverted before the1.3.0-rc01
release. This is now fixed, so the change is present again.
- This was originally included in the
- CEA-708: Avoid duplicate newlines being added by ExoPlayer's naive handling of the 'set pen location' command (#1315).
- Fix an
IllegalArgumentException
fromLegacySubtitleUtil
when a WebVTT subtitle sample contains no cues, e.g. as part of a DASH stream (#1516).
- Metadata:
- Fix mapping of MP4 to ID3 sort tags. Previously the 'album sort' (
soal
), 'artist sort' (soar
) and 'album artist sort' (soaa
) MP4 tags were wrongly mapped to theTSO2
,TSOA
andTSOP
ID3 tags (#1302). - Fix reading of MP4 (/iTunes) numeric
gnre
(genre) andtmpo
(tempo) tags when the value is more than one byte long. - Propagate ID3
TCON
frame toMediaMetadata.genre
(#1305).
- Fix mapping of MP4 to ID3 sort tags. Previously the 'album sort' (
- Image:
- Add support for non-square DASH thumbnail grids (#1300).
- Add support for AVIF for API 34+.
- Allow
null
as parameter forExoPlayer.setImageOutput()
to clear a previously setImageOutput
.
- DataSource:
- Implement support for
android.resource://package/id
raw resource URIs wherepackage
is different to the package of the current application. This wasn't previously documented to work, but is a more efficient way of accessing resources in another package than by name. - Eagerly check
url
is non-null in theDataSpec
constructors. This parameter was already annotated to be non-null. - Allow
ByteArrayDataSource
to resolve a URI to a byte array duringopen()
, instead of being hard-coded at construction (#1405).
- Implement support for
- DRM:
- Allow setting a
LoadErrorHandlingPolicy
onDefaultDrmSessionManagerProvider
(#1271).
- Allow setting a
- Effect:
- Support multiple speed changes within the same
EditedMediaItem
orComposition
inSpeedChangeEffect
. - Support for HLG and PQ output from ultra HDR bitmap input.
- Add support for EGL_GL_COLORSPACE_BT2020_HLG_EXT, which improves HLG surface output in ExoPlayer.setVideoEffect and Transformer's Debug SurfaceView.
- Update Overlay matrix implementation to make it consistent with the documentation by flipping the x and y values applied in
setOverlayFrameAnchor()
. If usingOverlaySettings.Builder.setOverlayFrameAnchor()
, flip their x and y values by multiplying them by-1
. - Fix bug where
TimestampWrapper
crashes when used withExoPlayer#setVideoEffects
(#821). - Change default SDR color working space from linear colors to electrical BT 709 SDR video. Also provide third option to retain the original colorspace.
- Allow defining indeterminate z-order of EditedMediaItemSequences (#1055).
- Maintain a consistent luminance range across different pieces of HDR content (uses the HLG range).
- Add support for Ultra HDR (bitmap) overlays on HDR content.
- Allow
SeparableConvolution
effects to be used before API 26. - Remove unused
OverlaySettings.useHdr
since dynamic range of overlay and frame must match. - Add HDR support for
TextOverlay
. Luminance of the text overlay can be adjusted withOverlaySettings.Builder.setHdrLuminanceMultiplier()
.
- Support multiple speed changes within the same
- IMA extension:
- Promote API that is required for apps to play DAI ad streams to stable.
- Add
replaceAdTagParameters(Map <String, String>)
toImaServerSideAdInsertionMediaSource.AdLoader
that allows replacing ad tag parameters at runtime. - Fix bug where
VideoAdPlayer.VideoAdPlayerCallback.onError()
was not called when a player error happened during ad playback (#1334). - Bump IMA SDK version to 3.33.0 to fix a
NullPointerException
when usingdata://
ad tag URIs (#700).
- Session:
- Change default of
CommandButton.enabled
totrue
and ensure the value can stay false for controllers even if the associated command is available. - Add icon constants for
CommandButton
that should be used instead of custom icon resources. - Add
MediaSessionService.isPlaybackOngoing()
to let apps query whether the service needs to be stopped inonTaskRemoved()
(#1219). - Add
MediaSessionService.pauseAllPlayersAndStopSelf()
that conveniently allows to pause playback of all sessions and callstopSelf()
to terminate the lifecycle of theMediaSessionService
. - Override
MediaSessionService.onTaskRemoved(Intent)
to provide a safe default implementation that keeps the service running in the foreground if playback is ongoing or stops the service otherwise. - Hide seekbar in the media notification for live streams by not setting the duration into the platform session metadata (#1256).
- Align conversion of
MediaMetadata
toMediaDescriptionCompat
, to use the same preferred order and logic when selecting metadata properties as in media1. - Add
MediaSession.sendError()
that allows sending non-fatal errors to Media3 controller. When using the notification controller (seeMediaSession.getMediaNotificationControllerInfo()
), the custom error is used to update thePlaybackState
of the platform session to an error state with the given error information (#543). - Add
MediaSession.Callback.onPlayerInteractionFinished()
to inform sessions when a series of player interactions from a specific controller finished. - Add
SessionError
and use it inSessionResult
andLibraryResult
instead of the error code to provide more information about the error and how to resolve the error if possible. - Publish the code for the media3 controller test app that can be used to test interactions with apps publishing a media session.
- Propagate extras passed to media3's
MediaSession[Builder].setSessionExtras()
to a media1 controller'sPlaybackStateCompat.getExtras()
. - Map fatal and non-fatal errors to and from the platform session. A
PlaybackException
is mapped to a fatal error state of thePlaybackStateCompat
. ASessionError
sent to the media notification controller withMediaSession.sendError(ControllerInfo, SessionError)
is mapped to a non-fatal error inPlaybackStateCompat
which means that error code and message are set but the state of the platform session remains different toSTATE_ERROR
. - Allow the session activity to be set per controller to override the global session activity. The session activity can be defined for a controller at connection time by creating a
ConnectionResult
withAcceptedResultBuilder.setSessionActivivty(PendingIntent)
. Once connected, the session activity can be updated withMediaSession.setSessionActivity(ControllerInfo, PendingIntent)
. - Improve error replication of calls to
MediaLibrarySession.Callback
. Error replication can now be configured by usingMediaLibrarySession.Builder.setLibraryErrorReplicationMode()
for choosing the error type or opt-ing out of error replication which is on by default.
- Change default of
- UI:
- Add image display support to
PlayerView
when connected to anExoPlayer
(#1144). - Add customization of various icons in
PlayerControlView
through xml attributes to allow different drawables perPlayerView
instance, rather than global overrides (#1200). - Work around a platform bug causing stretched/cropped video when using
SurfaceView
inside a ComposeAndroidView
on API 34 (#1237).
- Add image display support to
- Downloads:
- Ensure that
DownloadHelper
does not leak unreleasedRenderer
instances, which can eventually result in an app crashing withIllegalStateException: Too many receivers, total of 1000, registered for pid
([#1224 (https://github.com//issues/1224)).
- Ensure that
- Cronet Extension:
- Fix
SocketTimeoutException
inCronetDataSource
. In some versions of Cronet, the request provided by the callback is not always the same. This leads to callback not completing and request timing out (https://issuetracker.google.com/328442628).
- Fix
- HLS Extension:
- Fix bug where pending EMSG samples waiting for a discontinuity were delegated in
HlsSampleStreamWrapper
with an incorrect offset causing anIndexOutOfBoundsException
or anIllegalArgumentException
(#1002). - Fix bug where non-primary playlists keep reloading for LL-HLS streams (#1240).
- Fix bug where enabling CMCD for HLS with initialization segments resulted in
Source Error
andIllegalArgumentException
. - Fix bug where non-primary playing playlists are not refreshed during live playback (#1240).
- Fix bug where enabling CMCD for HLS live streams causes
ArrayIndexOutOfBoundsException
(#1395).
- Fix bug where pending EMSG samples waiting for a discontinuity were delegated in
- DASH Extension:
- Cast Extension:
- Fix bug that converted the album title of the
MediaQueueItem
to the artist in the Media3 media item (#1255).
- Fix bug that converted the album title of the
- Test Utilities:
- Implement
onInit()
andonRelease()
inFakeRenderer
. - Change
TestPlayerRunHelper.runUntil()/playUntil()
methods to fail on nonfatal errors (e.g. those reported toAnalyticsListener.onVideoCodecError()
). Use the newTestPlayerRunHelper.run(player).ignoringNonFatalErrors().untilXXX()
method chain to disable this behavior.
- Implement
- Demo app:
- Use
DefaultPreloadManager
in the short form demo app. - Allow setting repeat mode with
Intent
arguments from command line (#1266). - Use
HttpEngineDataSource
as theHttpDataSource
when supported by the device.
- Use
- Remove deprecated symbols:
- Remove
CronetDataSourceFactory
. UseCronetDataSource.Factory
instead. - Remove some
DataSpec
constructors. UseDataSpec.Builder
instead. - Remove
setContentTypePredicate(Predicate)
method fromDefaultHttpDataSource
,OkHttpDataSource
andCronetDataSource
. Use the equivalent method on eachXXXDataSource.Factory
instead. - Remove
OkHttpDataSource
constructors andOkHttpDataSourceFactory
. UseOkHttpDataSource.Factory
instead. - Remove
PlayerMessage.setHandler(Handler)
. UsesetLooper(Looper)
instead. - Remove
Timeline.Window.isLive
field. Use theisLive()
method instead. - Remove
DefaultHttpDataSource
constructors. UseDefaultHttpDataSource.Factory
instead. - Remove
DashMediaSource.DEFAULT_LIVE_PRESENTATION_DELAY_MS
. UseDashMediaSource.DEFAULT_FALLBACK_TARGET_LIVE_OFFSET_MS
instead. - Remove
MediaCodecInfo.isSeamlessAdaptationSupported(Format, Format, boolean)
. UseMediaCodecInfo.canReuseCodec(Format, Format)
instead. - Remove
DrmSessionManager.DUMMY
andgetDummyDrmSessionManager()
method. UseDrmSessionManager.DRM_UNSUPPORTED
instead. - Remove
AnalyticsListener.onAudioInputFormatChanged(EventTime, Format)
,AnalyticsListener.onVideoInputFormatChanged(EventTime, Format)
,AudioRendererEventListener.onAudioInputFormatChanged(Format)
,VideoRendererEventListener.onVideoInputFormatChanged(Format)
. Use the overloads that take aDecoderReuseEvaluation
instead. - Remove
RendererSupport.FormatSupport
IntDef andFORMAT_HANDLED
,FORMAT_EXCEEDS_CAPABILITIES
,FORMAT_UNSUPPORTED_DRM
,FORMAT_UNSUPPORTED_SUBTYPE
,FORMAT_UNSUPPORTED_TYPE
constants. Use the equivalent IntDef and constants inandroidx.media3.common.C
instead (e.g.C.FORMAT_HANDLED
). - Remove
Bundleable
interface. This includes removing allBundleable.Creator<Foo> CREATOR
constant fields. Callers should use theBundle toBundle()
andstatic Foo fromBundle(Bundle)
methods on each type instead.
- Remove