To override this change, and go back to parsing during rendering,
apps must make two method calls:
1. `MediaSource.Factory.experimentalParseSubtitlesDuringExtraction(false)`
2. `TextRenderer.experimentalSetLegacyDecodingEnabled(true)`
PiperOrigin-RevId: 634262798
This means the content source is 'prepared' instantly with a
placeholder, enabling all further preparation steps (e.g. loading
preroll ads) while the actual content is still preparing. This
improvement can speed up the start time for prerolls in manifest-based
content that doesn't have a zero-time preparation step like progressive
media.
Issue: androidx/media#1358
PiperOrigin-RevId: 633640746
This treats heic as a separate mimetype to heif (even though heic files are a subset of heif files). This is in line with other platform classes like android.content.ContentResolver
https://developer.android.com/media/platform/supported-formats#image-formats was updated to include avif support or API level 34, so added this MimeType as well and updated our associated util.
solves Issue: androidx/media#1373
PiperOrigin-RevId: 633616214
This allows apps to better detect when the platform
reclaims a codec. This requires adding the error code
to MediaCodecDecoderException.
PiperOrigin-RevId: 633588914
The class currently tracks the input format itself, updating it too
early in onConfigure() instead of onFlush(). This causes issues when
the format changes and the new values are applied to the silence
skipping logic of the old format. The fix is to use the base class
input format handling instead.
Issue: androidx/media#1352
PiperOrigin-RevId: 633232368
The same doSomeWork iteration that triggers the silence skipping
discontinuity may already have another discontinuities (like
AUTO_TRANSITION), which should take precedence over the silence
skipping.
PiperOrigin-RevId: 632432851
When the period has loaded to the end of the source, the `period.getBufferedPositionUs` will be set to `C.TIME_END_OF_SOURCE`, which is a negative value. Thus, the original `continueLoadingPredicate` will never turn to `false`, as the `bufferedPositionUs` is definitely less than the target preload position that is expected to be positive.
In this change, we added `PreloadMediaSource.PreloadControl.onLoadedToTheEndOfSource(PreloadMediaSource)` to indicate that the source has loaded to the end. This allows the `DefaultPreloadManager` and the custom `PreloadMediaSource.PreloadControl` implementations to preload the next source or take other actions.
This bug was not revealed by the the `DefaultPreloadManagerTest` because the related tests were all using the `FakeMediaSource` and only setting the preload target to `STAGE_TIMELINE_REFRESHED`. Thus, the tests for testing the `invalidate()` behaviors were modified to use the real progressive media whenever possible, unless we have to use `FakeMediaSource` to squeeze a chance to do more operations between the preloading of sources to test some special scenarios.
PiperOrigin-RevId: 631776442
For offloaded playback, reset the tracking field for stream completion in `DefaultAudioSink` prior to calling `AudioTrack.stop()` so that `AudioTrack.StreamEventCallback#onPresentationEnded` correctly identifies when all pending data has been played.
#minor-release
PiperOrigin-RevId: 631744805
When converting `MediaMetadata` to the legacy `MediaDescriptionCompat`
the selection and order of properties to use has been aligned with the
behavior of media1. This selection is relevant for users that use a
platform or legacy controller or browser. Before and up to the current
API version 34, this includes System UI, Android Auto/Automotive and
AVRCP (Bluetooth).
PiperOrigin-RevId: 630999535
The second stage of the changes remove the conversion to linear colors in the SDR effects pipeline by default.
also resolves Issue: androidx/media#1050
PiperOrigin-RevId: 630108296
When the AdTagLoader is deactivated because of a player error, the
error callback is already pending on the app's main thread, but not
yet executed. This means the VideoAdPlayerCallback instances
registered in AdTagLoader won't receive this error event if the
Player.Listener is immediately removed from AdTagLoader.
This can be fixed by postponing the deregistration until after
already pending messages have been handled. As this means other
callbacks can be triggered now with player==null, this check needs
to be added to other callbacks to avoid handling stale events.
Issue: androidx/media#1334
PiperOrigin-RevId: 630068222
The last rebuffer time was being updated erroneously, even in the absence of rebuffering events, resulting in incorrect `bs` (buffer starvation) key in CMCD.
Issue: androidx/media#1124
PiperOrigin-RevId: 629731796
These subtitles were skipped because they are marked as shouldBeSkipped
based on their timestamps. The fix removes this flag entirely in
SimpleSubtitleDecoder because TextRenderer handles potential skipping
if needed.
PiperOrigin-RevId: 629717970
This lets apps update the task manager priority and send the
priority message to all renderers so that they can adjust their
resources if needed.
PiperOrigin-RevId: 629426058
This change also includes mapping the numeric ID3v1 codes to their
string equivalents before setting them into `MediaMetadata`. This
mapping already existed, but it was previously only used when parsing
MP4 `gnre` atoms.
Issue: androidx/media#1305
PiperOrigin-RevId: 629113480
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.
The fix changes from having one `UrlRequestCallback` per `CronetDataSource` to one `UrlRequestCallback` per `UrlRequest`. Everytime a current request is canceled, the current callback is closed.
PiperOrigin-RevId: 627379153
For LL-HLS, the non-primary playlists originally keep reloading even after the primary playlist has been changed to another one. The reason being this is to check if the hinted(#EXT-X-PRELOAD-HINT) resource has been published or removed. If removed, the loading of it should be canceled, per the suggestion in the HLS spec:
"A Client SHOULD cancel a request for a hinted resource if it is not present in a subsequent Playlist update, such as in an EXT-X-PRELOAD-HINT tag or as part of another tag such as EXT-X-PART. The client SHOULD ignore the results of such requests."
However, keeping the non-primary playlists reloading is not optimal. As a solution, we trigger the playlist reloading only when there is a preload chunk loading instead of every time after we have processed the playlist. Compared to the original implementation, this will save the requests of reloading non-primary playlist after we have taken action upon the preload chunk being published or removed.
Issue: androidx/media#1240
PiperOrigin-RevId: 626038032
Transformer's input shouldn't be constrained to the number of playable audio channels on the current device because the media may be edited (to mix channels for example) or encoded for playback on another device (a server for example).
PiperOrigin-RevId: 625604243
The raw audio decoder's output audio format is stereo when the number of input
channels is (for example) 10 channels. Add a temporary workaround that uses the
input channel count for raw audio. This code should be removed in future when
we bypass the decoder entirely for raw audio.
Tested manually on a WAVE file with 18 audio channels.
PiperOrigin-RevId: 625307624
Some seek operations are currently filtered in the base classes if
the target index is not explicitly specified and the implicitly
assumed operation doesn't have an obvious target index. (Example:
calling seekToNext() at the last item in a playlist)
This is too opinionated because the actual player implementation
using this base class may be able to handle this seek request (e.g.
by adding new items on the fly or using other logic to select
the most suitable next item).
This can be solved by forwarding all seek requests to the respective
handler methods even if they are a presumed no-op. Also clarify the
Javadoc that the provided index is just an assumption if it wasn't
provided explicitly in the method call.
PiperOrigin-RevId: 624887116
A live window with changing duration can't be properly
displayed in a media notification. The duration constantly
changes and creates a nervous jumping seekbar that is not
really useful.
This change sets the duration for live streams to `C.TIME_UNSET`
when publishing the player state to the platform session. This
way no duration is sent to the platform session which prevents
media controls from drawing a seekbar.
Issue: androidx/media#1256
PiperOrigin-RevId: 624112541
When delegating EMSG samples in `HlsSampleStreamWrapper`,
the offset passed into `sampleMetadata(..)` of the delegate
`TrackOutput` must be zero because it is called immediately
after `sampleData(..)` is called.
The condition to trigger this issue is that more than one
metadata samples are pending in `pendingMetadataSampleInfos`
of `FragmentedMp4Extractor` which produces non-zero offsets.
Issue: androidx/media#1002
Issue: androidx/media#1203
PiperOrigin-RevId: 623210835
Compared to `release`, the `reset` method doesn't release the preload manager instance. This applies to the use case that an app wants to discard all the sources but keep the preload manager active for later usage.
Also rename the `releaseSourceInternal` to `removeSourceInternal`, as the latter sounds more generic for different preload manager implementations.
PiperOrigin-RevId: 623148723
In offloaded audio playback, the `DefaultAudioSink` should use the `AudioTrack.StreamEventCallback` `onPresentationEnded` to note whether the AudioTrack has completed playing all pending data.
PiperOrigin-RevId: 622885399
Both `remove(MediaItem)` and `remove(MediaSource)` return a boolean suggesting that whether the preload manager is holding the corresponding `MediaSource` and it has been removed.
PiperOrigin-RevId: 622185427
The join mode is used for two cases: surface switching and mid-playback
enabling of video.
In both cases, we want to pretend to be ready despite not having rendered
a new "first frame". So far, we also avoided force-rendering the first
frame immediately because it causes a stuttering effect for the
mid-playback enable case. The surface switch case doesn't have this
stuttering issue as the same codec is used without interruption. Not
force-rendering the frame immediately causes the first-frame rendered
callback to arrive too early though, which may lead to cases where
apps hide shutter views too quickly.
This problem can be solved by only avoiding the force-render for the
mid-playback enabling case, but not for the surface switching case.
PiperOrigin-RevId: 622105916
This API additions help an app to implement the lifecycle of a MediaSessionService
properly and in consistency with the `MediaSessionService` being in the foreground
or not.
Not properly implementing `onTaskRemoved` is the main reason for crashes and
confusion. This change provides `MediaSessionService` with a default
implementation that avoids crashes of the service. This default implementation
uses the new API provided with this change just as an app can do.
Issue: androidx/media#1219
PiperOrigin-RevId: 621874838
Makes OverlayFrameAnchor works as described in the OverlaySettings documentation. Currently the code does the opposite e.g setting the anchor to (+1,-1) makes the code anchor to the top left rather than the bottom right.
PiperOrigin-RevId: 621585558
If the mixer is reset without resetting maxPositionOfRemovedSources and
then reused, the value of maxPositionOfRemovedSources can be outdated,
leading to an incorrect number of bytes being output by the mixer.
PiperOrigin-RevId: 619832502
This ensures MediaMetadata with just non-null extras is not
considered equal to MediaMetadata.EMPTY. This makes sure the
contents are bundled when a controller sets the extras in a
new MediaItem
Issue: androidx/media#1176
#minor-release
PiperOrigin-RevId: 618876642
Some media can read color info values from the bitstream
and may partially set some of the SDR default values in
Format.ColorInfo. Setting these default values for SDR can
confuse some codecs and may also prevent adaptive ABR
switches if not all ColorInfo values are set in exactly the
same way.
We can avoid any influence of HDR color info handling by
disabling setting the color info MediaFormat keys for SDR
video and also avoid codec reset at format changes if both
formats are SDR with slightly different ColorInfo settings.
To identify "SDR" ColorInfo instances, we need to do some
fuzzy matching as many of the default values are assumed to
match the SDR profile even if not set.
Issue: androidx/media#1158
PiperOrigin-RevId: 617473937
Confirmed that the HLG extension displays properly on Pixel 7 Pro, API 34 and Samsung S24, API 34. On these devices, this fixes the washed out HLG preview issue on API 34, where the PQ ext had a washed out look, and where the HLG ext is supported (this bug didn't occur on API 33, only 34).
More info on manual tests done to sanity-check:
* Test cases: Transformer debug SurfaceView and ExoPlayer.setVideoEffects
* Test inputs: HLG and PQ
* Test devices: Pixel 7 Pro (API 33 & 34), Samsung Galaxy S24 (API 34)
* Added debugging: Logging colorInfo used in GlUtil.createEglSurface
No regressions were seen. HLG extension is used more in API 34, and behavior stays the same on API 33. Only human-visible change without logging is that HLG content looks better on API 34, for Samsung S24 and Pixel 7 Pro.
PiperOrigin-RevId: 616131192
It's a bit arguable whether the `Subtitle` implementation supports
zero-duration events, since `getEventTimeCount` is documented as
effectively "the number of times the cues returns by `getCues(long)`
changes", and zero-duration events violate that. However, the current
`WebvttSubtitle` impl **does** produce zero-duration events, so it
seems safer to handle them gracefully here and then, as a possible
follow-up, fix the `WebvttSubtitle` impl (or remove it completely).
Issue: androidx/media#1177
#minor-release
PiperOrigin-RevId: 616095798
This should already be the default, but some devices seem
to not adhere to this contract and assume the default is unset.
Issue: androidx/media#1169
PiperOrigin-RevId: 614697283
Having a default icon available allows apps to only specify the
icon constant without having to define an icon drawable themselves
as Media3 can fill in the icon resource for backwards compatibility.
The switch util method allows R8 to easily remove unused icons, so
having default icons won't affect APK size unless the constants are
used to set up the CommandButtons.
PiperOrigin-RevId: 614623909
This check is already present in `DataSpec.Builder.build()` but there
are many public constructors which bypass the builder (only some of
which are deprecated), so this adds an additional check.
PiperOrigin-RevId: 613908358
Renderers may be enabled for subsequent media items as soon as the current media item's renderer's isEnded() returns true. When a renderer is being enabled and the player is 'playing', that renderer is also started. When playing a mixed playlist of images and content with audio & video, the player may skip some image items because the early-starting of the audio renderer causes a clock update.
A solution is to only start the "early-enabled" renderers at the point of media transition and add a condition on DefaultMediaClock to use the standalone clock when reading-ahead and the renderer clock source is not in a started state.
Issue: androidx/media#1017
PiperOrigin-RevId: 613231227
The old methods are deprecated and are called from the new
method for backwards compatibility of custom implementations.
'DefaultLoadControl' is unchanged, but `ExoPlayerImplInternal`
already calls the new methods passing in the `PlayerId`,
PiperOrigin-RevId: 613197190
We currently update this value for controllers to match the
availability of the associated command. This however makes it
impossible to mark a button as unavailable if the command is
available. This can be refined by only setting the 'enabled'
field to false if the command is not available, not the other
way round. And we should also enable the button by default as
disabling is the unusual case not many apps will use.
In addition, this change fixes missing update logic when the
player commands changed and it adds some additional test coverage
for all these cases.
PiperOrigin-RevId: 612881016
`BasePreloadManager` coordinates the preloading for multiple sources based on the priorities defined by their `rankingData`. Customization is possible by extending this class. Apps will implement `TargetPreloadStatusControl` to return preload manager the target preload status for a given `rankingData` of the source.
`DefaultPreloadManager` extends from the above base class and uses `PreloadMediaSource` to preload media samples of the sources into memory. It also uses an integer `rankingData` that indicates the index of an item on the UI, and the priority of the items is determined by their adjacency to the current playing item. Apps can set the index of current playing item via `DefaultPreloadManager.setCurrentPlayingIndex` when the user swiping is detected.
PiperOrigin-RevId: 612829642
When the controller replaces the current item, the masking position will be changed to the default position of the new item for a short while, before the correct position comes from the session. This will interrupt the current position fetched from the controller when the playback doesn't interrupted by the item replacing.
Issue: androidx/media#951
#minor-release
PiperOrigin-RevId: 611417539
This change aims to prioritise tracks that have a 'smooth enough for
video' frame rate, without always selecting the track with the highest
frame rate.
In particular MP4 files extracted from motion photos sometimes have two
HEVC tracks, with the higher-res one having a very low frame rate (not
intended for use in video playback). Before this change
`DefaultTrackSelector` would pick the low-fps, high-res track.
This change adds a somewhat arbitrary 10fps threshold for "smooth video
playback", meaning any tracks above this threshold are selected in
preference to tracks below it. Within the tracks above the threshold
other attributes are used to select the preferred track. We deliberately
don't pick the highest-fps track (over pixel count and bitrate), because
most users would prefer to see a 30fps 4k track over a 60fps 720p track.
This change also includes a test MP4 file, extracted from the existing
`jpeg/pixel-motion-photo-2-hevc-tracks.jpg` file by logging
`mp4StartPosition` in
[`MotionPhotoDescription.getMotionPhotoMetadata`](b930b40a16/libraries/extractor/src/main/java/androidx/media3/extractor/jpeg/MotionPhotoDescription.java (L123))
and then using `dd`:
```
mp4StartPosition=2603594
$ dd if=jpeg/pixel-motion-photo-2-hevc-tracks.jpg \
of=mp4/pixel-motion-photo-2-hevc-tracks.mp4 \
bs=1 \
skip=2603594
```
----
This solution is in addition to the `JpegMotionPhotoExtractor` change
made specifically for these two-track motion photos in
5266c71b3a.
We will keep both changes, even though that change is not strictly
needed after this one, because adding the role flags helps to
communicate more clearly the intended usage of these tracks. This
change to consider FPS seems like a generally useful improvement to
`DefaultTrackSelector`, since it seems unlikely we would prefer a 5fps
video track over a 30fps one.
Issue: androidx/media#1051
PiperOrigin-RevId: 611015459
Some devices supporting Performance Points for decoder coverage are missing coverage over the CDD requirements for H264. For these cases ExoPlayer should fall back to legacy resolution and frame rate support checks. If there is a stream evaluated as a PerformancePointCoverageResult of COVERAGE_RESULT_NO, then ExoPlayer checks for coverage of the 720p H264 CDD requirement.
Issue: google/ExoPlayer#10898
Issue: androidx/media#693
Issue: androidx/media#966
PiperOrigin-RevId: 609740128
If the reading period has already advanced and a track reselection procs that only affects the reading period media, then ExoPlayer may try and apply the reading period's track selection incorrectly unto the playing period. ExoPlayer should apply the playing period's track selection to the playing period instead.
PiperOrigin-RevId: 609375077
If render error occurs due to AudioTrack initialization failure in offload mode, then ExoPlayer should allow retry as subsequent attempt will be with DefaultAudioSink disabling offload.
PiperOrigin-RevId: 609304897
The `PreloadMediaPeriod.selectTracksForPreloading` can be called for multiple times at the preloading stage (before the period is being played). For example, when the period resumes preloading. This change fix the assertion failure in `ProgressiveMediaPeriod.selectTracks` caused by the wrong implementation of `PreloadMediaPeriod.selectTracksForPreloading` when it is trying to retain the previously preloaded streams.
Also the `TrackSelectorResult` parameter is changed to a list of `ExoTrackSelection`. We should compare the selections only rather than considering the `RendererConfiguration` in the `TrackSelectorResult` to decide whether to retain the streams, as for preloading case the renderers haven't consumed the samples yet.
PiperOrigin-RevId: 609126868
Previously, the track format was used in VideoSampleExporter. Now, we use a
simulated decoder output format.
As the last expected change for this bug, also adds release notes
PiperOrigin-RevId: 609080629
Also introduce a fluent API that allows callers to ignore non-fatal
errors (while avoiding adding boolean overloads for every method).
**Most** tests want to fail on non-fatal errors (since they likely
indicate user-visible issues like codec errors etc), only tests
explicitly testing fallback in error scenarios should want to ignore
them.
Before this change there were a few `playUntilXXX` methods. These can
now all be triggered via `play(player).untilXXX`, which means
effectively every 'until' condition is available in a 'play until'
variant that calls `play` just before waiting for the condition.
PiperOrigin-RevId: 608988234
MediaCodec docs already allude to potentially mismatching H.264 level
between container and bitstream. Relax the initialization data check to
reflect this.
PiperOrigin-RevId: 608942322