ChannelMappingAudioProcessor, TrimmingAudioProcessor and
ToFloatPcmAudioProcessor are currently package-private even
though they might be useful in custom audio processing chains
or custom version of audio sinks.
Issue: androidx/media#2339
PiperOrigin-RevId: 747857815
This is a step towards unifying ShadowMediaCodecConfig structure to accommodate having both ExoPlayer and Transcoding codecs configuration.
This includes:
* Adding ability to configure encoders by calling `addEncoders(CodecInfo...)`
* A new factory method that takes specific encoders and decoders CodecInfos
* A new method `addCodecs(boolean, CodecConfig, CodecInfo...) that configures codecs with specified behavior by passing a `CodecConfig`.
This CL also includes migrating Transformer tests to ShadowMediaCodecConfig.
PiperOrigin-RevId: 747390451
In `PreloadMediaSource` we accesses the `MediaPeriod.getBufferedPositionUs()` when we receive `onContinueLoadingRequested()` from the period. For `ProgressiveMediaPeriod` which requires loading a portion of media file to get it prepared, there is a chance that it needs more than one round of `onContinueLoadingRequested()` -> `continueLoading()` to complete preparation, for example, when the `setContinueLoadingIntervalBytes()` is small enough to not include the full information for preparation. Thus we should avoid `MediaPeriod.getBufferedPositionUs()` being called before period is prepared, as it will fail at `assertPrepared`.
Issue: androidx/media#2315
#cherrypick
PiperOrigin-RevId: 746490375
Some interactions create a default notification provider if
no custom one is set yet (e.g. setForegroundServiceTimeoutMs).
This means a later call to setMediaNotificationProvider will
silently fail to apply the new provider.
This can be fixed by making the media notification provider
updatable.
Issue: androidx/media#2305
PiperOrigin-RevId: 746428193
In `PlayerWrapper.getCurrentTimelineWithCommandCheck()` we
always return `new CurrentMediaItemOnlyTimeline(this)` in
case the wrapped player doesn't have `COMMAND_GET_TIMELINE`
available but has `COMMAND_GET_CURRENT_MEDIA_ITEM`. This is
emulating a single item timeline with a static window count
of 1 which isn't correct when the wrapped player is empty.
Instead, when the wrapped player is empty we need to return
an empty timeline to match the wrapped player.
Issue: androidx/media#2320
PiperOrigin-RevId: 746071237
Currently, a notification may be recreated even if a user dismissed
it as long as the standard conditions for a notification are true.
To avoid this effect, we plumb the dismissal event to the notification
controller, so that it can override its `shouldShowNotification`
decision. The plumbing sets an extra on the media key intent, which
the session forwards as a custom event to the media notification
controller if connected.
Issue: androidx/media#2302
PiperOrigin-RevId: 745989590
The surface must only be used by one player at a time. To ensure
that, we can keep a reference to the previously used player
and clear its surface reference before assigning to a new one.
Note that we do not need to clear the surface in onDispose
of a DisposableEffect because the lifecycle management of the
surface is moved to the Player and the Player takes care of
unregistering its surface reference as soon as the surface is
destroyed (which happens when the AndroidView element is no longer
is the Composable tree).
PiperOrigin-RevId: 745558414
Previously, encrypted media segments did not have the chunk duration set,
causing an assertion failure during `CmcdData` creation. With this change,
the chunk duration is always set, while `CmcdData` ensures it is applied
only for media chunks.
Issue: androidx/media#2312
PiperOrigin-RevId: 745196718
This adds the option to disable certain track types during scrubbing,
with audio and metadata disabled by default.
The tracks are disabled by modifying the `TrackSelectionParameters`,
but in a way that is invisible to
`Player.getTrackSelectionParameters()` and
`Player.Listener.onTrackSelectionParametersChanged`. This allows us to
clearly reason about what should happen if
`Player.setTrackSelectionParameters(...)` is called during scrubbing
mode. The **side effects** of disabling the tracks are all visible
through `Player.Listener` and `AnalyticsListener` (renderer disabled,
decoder released, `onTracksChanged`, etc.).
PiperOrigin-RevId: 743961632
ExoPlayer disables sleeping for offload when the reading period advances and re-evaluates turning it back on when the playing period advances. For playlists of short items where the reading period could advance much further than the playing period, sleeping should still be disabled until the playing period advances to match the current reading period.
Issue: androidx/media#1920
PiperOrigin-RevId: 743503063
The assertion is changed to check that the number of passed
in arrays of durations is always matching `adGroupCount`
according to the behavior of `withRemoveAdGroupCount(int)`.
Issue: androidx/media#2267
PiperOrigin-RevId: 743185176
The proxy classes Android(Embedded)ExternalSurface just provide a
simple API surface around AndroidView wrapping SurfaceView and
TextureView respectively. However, this prevents accessing the
underlying views directly, which is needed for full lifecycle
tracking by the Player and to access surface size updates (which
are not available when the API is reduced to just `Surface`).
Instead of the proxy classes, we can directly use AndroidView from
PlayerSurface. This allows to call the proper Player APIs to set
SurfaceView or TextureView, so that the Player can keep track of
the view lifecycle and update its internal state and size tracking
accordingly. Because the player keeps tracks of the lifecycle,
none of the callback structure in Android(Embedded)ExternalSurface
is needed, nor are the additional setters for options that are
all default.
PiperOrigin-RevId: 743079058
This initial version prevents incoming seeks from pre-empting
in-progress seeks, allowing more seeks to complete when the scrubber
bar is dragged quickly back and forth.
More scrubbing optimizations will be added in follow-up changes.
PiperOrigin-RevId: 743052527
Earlier when gap is at the start of a sequence
it was automatically filled with silent audio.
Now setting forceAudioTrack flag is mandatory to
indicate that the gap at the start of a sequence
must be filled with silent audio.
PiperOrigin-RevId: 742625236
If a recoverable renderer error occurred just before playing period transition(aka media item transition) then the player may enter a continuous loop of retrying to play the previous media item.
This was most easily reproduced in an audio offload scenario where init in offload mode always fails. In initializing the following media, the process would fail with recoverable error to try in non-offload mode. The player would try to recover with playing the previous media item. Most times it would skip to the next track but not always.
Issue: androidx/media#2229
PiperOrigin-RevId: 741213293
If the `RtspMediaSource.Factory` is provided a `MediaItem` containing a uri with the scheme `rtspt`, then the factory will create its `RtspMediaSource` configured to use TCP.
Issue: androidx/media#1484
PiperOrigin-RevId: 740340604
We currently assume SW codecs are capable of playing all resolutions
and frame rates up to their declared supported maximum values, even
though the are likely not able to keep up playback smoothly for higher
resolutions. For HW codecs we can check PerformancePoints to declare
them as EXCEEDS_CAPABILITIES if they technically support a format but
are not performant enough. We can do the same for SW codecs by
checking getAchievableFrameRatesFor.
PiperOrigin-RevId: 739253653
Ideally, we'd find a more targeted exclusion as it may depend on
specific codecs. The current workaround should help with the
reported issues that are limited to Xiaomi and OPPO.
Issue: androidx/media#2059
#cherrypick
PiperOrigin-RevId: 738017969
We currently pretend to be ready when using a placeholder
surface irrespective of whether the renderer is actually
ready to immediately render when a surface is attached.
This causes issues in two ways:
- Apps don't know when a player without a surface can be
connected to a surface and immediately start playing
- A paused player without a surface will use the 1 second
default doSomeWork loop, causing any pending decoding
to be extremely slow (see Issue: androidx/media#1973).
The fix is to let the placeholder surface case use the same
paths as the regular surface and with marking the first
frame as available as soon as the codec output buffer for it
is pending and ready for release.
PiperOrigin-RevId: 737942496
This method allows a single Presentation Effect to resize portrait and landscape videos to a fixed resolution, while maintaining their orientations.
PiperOrigin-RevId: 737652909
Previously we only enable `SeekParameter.*_SYNC` for HLS when `EXT-X-INDEPENDENT-SEGMENTS` is set in the playlist. However, this condition can actually be loosened. To seek in HLS, we need to download the segment in which the resolved seek position locates under any circumstance. If `SeekParameter.PREVIOUS_SYNC` or `SeekParameter.CLOSEST_SYNC` is passed, and that segment happens to start with sync samples, then the seek can be done quicker with that adjusted seek position. And if that segment doesn't start with sync samples, then the behaviour will be the same as we set the adjusted seek position to the exact original position. But we still cannot safely enable `SeekParameter.NEXT_SYNC` as it will potentially cause the seeking to miss more content than seeking to the exact position.
Issue: androidx/media#2209
PiperOrigin-RevId: 737580861
Without this, 32-bit files fail to play with `Playback stuck buffering
and not loading`. With this change, playback works on devices where the
`MediaCodec` FLAC decoder supports 32-bit, and crashes on devices with a
`MediaCodec` FLAC decoder that does not support 32-bit.
A follow-up change will aim to transform the 'unsupported' case from a
crash into a report that the track format is not supported.
32-bit support was only fully incorporated into the spec when RFC 9639
was [published in December
2024](https://xiph.org/flac/2024/12/19/rfc-9639-published.html), and
it was been supported by `libflac` (for encode and decode) [since
September 2022](https://xiph.org/flac/2022/09/09/flac-1-4-0-released.html).
The original version of this `FlacExtractor` was written before either
of these, so only supported up to 24-bit.
Issue: androidx/media#2197
PiperOrigin-RevId: 737559285
The spec technically allows to mark adaptation sets with the switching
property if they allow seamless switching with non-overlapping
segments. This is typically only used for compatible content (e.g.
different codecs), but the spec allows it to be used for other
content as well (e.g. different languages, roles). ExoPlayer's concept
of a TrackGroup only allows formats with the same language and role
flags to be merged, so we should check that before merging.
Issue: androidx/media#2222
#cherrypick
PiperOrigin-RevId: 736564055
This change uses the duration and byte count of the Xing frame, if
they're present, to estimate the bitrate of the stream. The seeking
will still be inaccurate (because we're doing CBR seeking in a VBR
stream), but it will be more accurate than basing the bitrate on the
first MP3 frame we read. It will also mean the duration reported is
accurate.
This change also ensures that if the Xing frame contains the number of
audio bytes but no ToC, the audio data length is still propagated into
the `XingSeeker` (and therefore into the `ConstantBitrateSeeker` too).
Issue: androidx/media#2194
PiperOrigin-RevId: 736100104
We currently combine stopping the FGS and optionally removing the
notification in one method, which unnecessarily gates its logic on
checking the desired foreground state again. This causes a bug where
the notification should be removed (because shouldShowNotification
returns false), but stays visible because the service is allowed
to stay in the foreground and the notification removal code is not
triggered.
#cherrypick
Issue: androidx/media#2211
PiperOrigin-RevId: 735126704
If feature is enabled, MediaCodecVideoRenderer will include the `MediaCodec.BUFFER_FLAG_DECODE_ONLY` flag when queuing decode-only input buffers. This flag will signal the decoder to skip the decode-only buffers thereby resulting in faster seeking.
PiperOrigin-RevId: 734152464
This was requested in Issue: androidx/media#2191 for playback of Opus and Vorbis
files with more than two channels with a float PCM pipeline.
Also, add ChannelMappingAudioProcessorTest.
PiperOrigin-RevId: 733766680
This change exposes a flag in `DefaultAudioMixer#Factory` to set whether
to upmix/downmix using constant power or constant gain mixing matrices.
This is a non-functional change.
PiperOrigin-RevId: 733339367
A state holder that handles interaction with a UI component that toggles through a range of playback speeds.
[demo-compose] Use PlaybackSpeedState to create PlaybackSpeedTextButton
Add the button to the bottom extra controls.
PiperOrigin-RevId: 731449526