- Common Library:
- Reduce
C.DEFAULT_BUFFER_SEGMENT_SIZEfrom65536to65520so each buffer allocation (including itsbyte[]object header) fits in whole OS pages in ART's large object space, reducing sample buffer memory usage by ~6% on 4 KiB-page devices and ~20% on 16 KiB-page devices. - Replace
androidx.media3.common.util.NullableTypewith JSpecifyorg.jspecify.annotations.Nullable. - Remove
androidx.media3.common.util.UnknownNullin favor of JSpecify nullness annotations. Kotlin subclasses ofRunnableFutureTaskwith a nullable result type (such asVoid?) must specify a nullable type argument (e.g.,RunnableFutureTask<Void?, Exception>). - Add
AdViewProvider.getAdVideoView()to provide the video containerViewthat can be resized during ad playback. - Map the
mlpaRFC 6381 codec string toMimeTypes.AUDIO_TRUEHDinMimeTypes.getMediaMimeType, fixing missing muxed Dolby TrueHD audio tracks during HLS chunkless preparation (#3485). - Fix
AdPlaybackState.withAdDurationsUsto copy the passed array andAdPlaybackState.fromAdPlaybackStateto copy all array fields of the ad groups, so that an instance can no longer be modified through retained or shared arrays. - Fix
IllegalStateException("Player is accessed on the wrong thread.") whenPlayer.listenorPlayer.listenTois cancelled from a thread other than the player's application thread (for example, during Compose UI test teardown) (#3005).
- Reduce
- ExoPlayer:
- Fix an issue where a renderer enabled early for an upcoming media period could start rendering before playback transitions to that period.
- Kotlin subclasses of
CompositeMediaSourcethat use nullable child source IDs (such asVoid?) must specify a nullable type argument (e.g.,CompositeMediaSource<Void?>). - Verify in
AdsMediaSourcethatAdPlaybackState.removedAdGroupCountdoes not decrease acrossAdPlaybackStateupdates. - Fix an issue where transitioning between media periods that use different renderers could prematurely enable the incoming renderer before the outgoing renderer finished rendering (for example, throwing
IllegalStateException("Multiple renderer media clocks enabled.")) whenFlags.FLAG_PER_STREAM_MEDIA_PROGRESSIONis enabled. - Fix an issue where transitioning to an ad at a custom playback speed could delay advancing all renderers to the ad period when
Flags.FLAG_PER_STREAM_MEDIA_PROGRESSIONis enabled. - Fix issues with pre-warming renderers during media period transitions and track reselections.
- Add
MediaPeriod.supportsStreamPrerollFlags()(defaulting tofalse) so that customMediaPeriodimplementations can opt in to reporting initial discontinuities usingSampleStream.getFlags(), falling back toMediaPeriod.readDiscontinuity()when not supported andFlags.FLAG_PER_STREAM_MEDIA_PROGRESSIONis enabled. - Fix an issue where skipping an ad followed by another ad in the same ad group was reported with
DISCONTINUITY_REASON_AUTO_TRANSITIONinstead ofDISCONTINUITY_REASON_SKIP, or not reported at all whenAdsMediaSourceuses lazy content source preparation.
- Transformer:
- Add CodecDB (
androidx.media3.transformer.codecdb), which recommends video encoder configurations (codec, encoder settings and bitrate) for the current device from measured encoder quality data.
- Add CodecDB (
- Extractors:
- ADTS: Fix
AdtsExtractorderiving the audio format from a false sync word in the payload of a partial first frame, which could cause playback of live AAC streams joined mid-frame to fail or stall (#3464). - Fix
ArrayIndexOutOfBoundsExceptioninFragmentedMp4Extractorwhen a fragment contains atrunbox with no samples (#3471). - ADTS: Add
FLAG_DISABLE_ID3_METADATAtoAdtsExtractorto stop ID3 data in the stream from being output as anapplication/id3track. - MP4: Fix gapless playback of AAC tracks whose muxer (such as FFmpeg) shortens the last
sttsentry to exclude the encoder padding, which caused the padding to be derived as 0 from theelstedit list and the end of the last frame to be played (#3489). - Fix large upfront peek buffer allocations and
OutOfMemoryErrorwhen sniffing corrupt or non-media files that start withID3(#3502).
- ADTS: Fix
- Inspector:
- Fix an issue where cancelling the future returned by
MetadataRetriever.retrieveDurationUs()preventedclose()from releasing the underlyingMediaSource(#3468). - Fix
MediaExtractorCompatto returnMediaFormat.KEY_FRAME_RATEas an integer, matching the platformMediaExtractor.
- Fix an issue where cancelling the future returned by
- Audio:
- Fix an issue where buffered skipped silence was included in
AudioSink.getCurrentPositionUs(boolean)and reported usingAudioSink.Listener.onSilenceSkipped()before playback reached the skipped region (#3472). - Set codec provenance using
AudioTrack.Builder.setCodecProvenanceon API 37+ when playing spatialized multichannel PCM audio decoded from a compressed format. - Fix
AudioTrackinitialization retries being skipped when 1 second of audio is at least as large as the initial buffer size, which made DTS-HD passthrough fail on devices with limited audio memory (#3487).
- Fix an issue where buffered skipped silence was included in
- Video:
- Allow falling back to an H.265/HEVC decoder for backward-compatible Dolby Vision Profile 7 streams, and no longer fall back to an AV1 decoder for Profile 10 streams whose base layer signals full range with unspecified transfer characteristics (#3486).
- Fix decoder selection in
MediaCodecUtilto avoid selecting primary decoders that don't functionally support the format's profile (such as a Dolby Vision decoder for a different profile) when no decoder fully supports the format (#3486).
- Text:
- Reduce memory usage in
DvbParserby rendering subtitle regions directly into region-sized bitmaps instead of retaining a full-screen scratch bitmap.
- Reduce memory usage in
- Effect:
- Muxers:
- Validate the track
Formatwhen adding a track toMp4MuxerorFragmentedMp4Muxer, instead of failing later when writing samples or closing the muxer. - Make repeated calls to
Muxer.close()a no-op in all libraryMuxerimplementations, and treat the muxer as closed even ifclose()throws. Calling any other method afterclose()now throws anIllegalStateException.
- Validate the track
- IMA extension:
- Support the IMA SDK's
ResizablePlayerinterface to allow interactive ads to resize and reposition the video player view within the ad container, and addImaAdsLoader.requestAds(DataSpec, Object, AdViewProvider)(deprecatingImaAdsLoader.requestAds(DataSpec, Object, ViewGroup)).
- Support the IMA SDK's
- Session:
- Stabilize media button preferences APIs.
- Reduce memory usage by no longer retaining compressed artwork data in
CacheBitmapLoader. - Avoid redundant
MediaSession.setQueue(null)calls on timeline updates when the platform session queue is alreadynull(for example, whenPlayer.COMMAND_GET_TIMELINEis unavailable). - Fix an issue where
MediaSessionServicedid not let a service implementation the option to recover properly by not attempting to create a new session (#3490). - Report
Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATEinstead ofPlayer.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGEDwhen a legacyMediaSessionCompatmetadata update modifies the active queue item's metadata or duration without changing the queue. - Fix missing artwork for legacy sessions that set a
nullMETADATA_KEY_DISPLAY_ICON(or artwork URI) alongside a validMETADATA_KEY_ALBUM_ART: null artwork values are now skipped when converting legacy metadata.
- UI:
- Add a
subtitlesComposable slot toContentFrameandPlayer, with default support inmedia3-ui-compose-material3for rendering bitmap and horizontal text subtitle cues. - Add
SubtitleView.setTextDirectionHeuristicto allow customizing the text direction heuristic used for bidirectional subtitle text wrapping (#3454). - Animate all control slots in
Playerinmedia3-ui-compose-material3, including custom ones, and remove thevisibleparameter fromPlayerDefaults.TopControls,CenterControlsandBottomControls. This is a breaking change on an unstable API. - Support
AdViewProvider.getAdVideoView()inPlayerViewby wrappingexo_content_frameinexo_content_frame_container. - Reduce memory usage in
SubtitleViewby releasing cached subtitle bitmaps and text layouts when cues are cleared, and fix an issue where stale subtitle text could remain visible when a cue has insufficient width to lay out.
- Add a
- HLS extension:
- Fix issues where reloading a failed or canceled HLS media chunk could retain partially buffered samples without discarding or splicing, or reset the load position to an outdated seek position (#3362).
- Fix
IllegalStateExceptionwhen seeking to the start of a buffered segment after an adaptive track switch. - Fix several playback issues when switching pathways with HLS Content Steering (#3465).
- DASH extension:
- Fix duplicated or garbled CEA-608 subtitles when a stream has multiple embedded caption tracks (#887).
- Cast extension:
- Fix an issue where
RemoteCastPlayerload requests were dropped by Android TV receivers (#3462). - Update
com.google.android.gms:play-services-cast-frameworkdependency to23.0.0. - Add
CastParams.Builder.setSystemOutputSwitcherEnabled(boolean)to configure whether Cast devices appear in the system output switcher without requiringMediaTransferReceiverto be declared inAndroidManifest.xml, and enable the system output switcher by default for apps targeting API 37+ on devices running API 37+. - Support predefined Cast
MediaMetadatafields inDefaultMediaItemConverterby mapping fields without a dedicatedMediaItem.mediaMetadataproperty to and fromMediaItem.mediaMetadata.extras, and preserve custom extras inMediaInfo.customData. - Stop throwing exceptions in
DefaultMediaItemConverterwhen a playback URI is missing or conversion fails, preserving the media ID and metadata in theCastPlayertimeline for Cast queue items without a playback URI. - Add
SessionAvailabilityListener.onCastSessionAvailable(boolean)to indicate whether an available Cast session was started using intent to join, and preserve remote playback state instead of overwriting it with local player state when joining a Cast session using intent to join inCastPlayer. - Populate
MediaInfoand timeline durations fromMediaMetadata.durationMsfor non-live items inDefaultMediaItemConverterandRemoteCastPlayer, and retain receiver-resolved durations and livestream status across queue seeks.
- Fix an issue where
- Demo app:
- Allow reordering playlist items by dragging in the session demo app.
- Remove deprecated symbols:
- Remove
androidx.media3.transformer.TextureAssetLoader. Useandroidx.media3.transformer.RawAssetLoaderinstead. - Remove public
DefaultDecoderFactoryconstructors. UseDefaultDecoderFactory.Builderinstead. - Remove
DefaultLoadErrorHandlingPolicy.DEFAULT_TRACK_BLACKLIST_MS. UseDefaultLoadErrorHandlingPolicy.DEFAULT_TRACK_EXCLUSION_MSinstead. - Remove
DefaultVideoFrameProcessor.Factory.Builder.setRequireRegisteringAllInputFrames(boolean). UseVideoFrameProcessor.INPUT_TYPE_SURFACE_AUTOMATIC_FRAME_REGISTRATIONinstead. - Remove
EditedMediaItemSequence.Builder.experimentalSetForceAudioTrack(boolean)andEditedMediaItemSequence.Builder.experimentalSetForceVideoTrack(boolean). UseEditedMediaItemSequence.Builder(Set)instead. - Remove
EditedMediaItemSequence.forceAudioTrack. UsetrackTypes.contains(C.TRACK_TYPE_AUDIO)instead. - Remove
EditedMediaItemSequence.forceVideoTrack. UsetrackTypes.contains(C.TRACK_TYPE_VIDEO)instead. - Remove
ExportResult.durationMsandExportResult.Builder.setDurationMs. UseExportResult.approximateDurationMsandExportResult.Builder.setApproximateDurationMsinstead. - Remove
SilenceSkippingAudioProcessor.DEFAULT_PADDING_SILENCE_US. Specify silence behavior usingsilenceRetentionRatioinstead. - Remove
Timeline.getPeriodPosition(Window, Period, int, long, long). UseTimeline.getPeriodPositionUs(Window, Period, int, long, long)instead.
- Remove