This uses a 'bundled' extractor (`SubtitleExtractor`) because
`MediaParser` doesn't support transcoding subtitles to
`application/x-media3-cues`. This transcoding is required to support
non-legacy subtitle handling where they are parsed during extraction,
instead of during rendering.
PiperOrigin-RevId: 665282298
This is only used as part of legacy subtitle decoding. If any apps are
using it directly (rather than via `DashMediaSource` or `SsMediaSource`)
they probably need to enable legacy decoding in `TextRenderer` to avoid
playback failures.
PiperOrigin-RevId: 663740343
The method currently has two ways of operating with a complicated
contract:
1. outputBuffer == null -> sets a new outputBuffer and starts
draining it as far as possible.
2. outputBuffer != null -> continues draining a previous buffer,
requires that the input parameter is the same as outputBuffer.
This contract can be made cleaner by splitting the logic into
(1) setting a new output buffer and (2) draining the output buffer.
Only one parameter is needed for each method and there is no
requirement to pass in the same argument as before because we already
know what we are draining. This also means the caller of the method
doesn't have to keep track of the actual outputBuffer, allowing
further processing steps in the future that change the drained
instance.
PiperOrigin-RevId: 663316251
Previous to this change, `FrameworkMediaDrm.requiresSecureDecoder`
ignores its `sessionId` parameter on API 31+, and uses only the
`mimeType` parameter. This means the result [assumes the session is
opened at the 'default security
level'](https://developer.android.com/reference/android/media/MediaDrm#requiresSecureDecoder(java.lang.String)):
> The default security level is defined as the highest security level
> supported on the device.
This change is a no-op in all (?) cases, because the `ExoMediaDrm`
interface only exposes the zero-arg `openSession()` method, which in the
framework case **also** assumes the highest security level is preferred:
> By default, sessions are opened at the native security level of the
> device.
However, it seems more obviously correct to only make this
"highest/native security level" assumption in one place
(`openSession()`), and check the session's **actual** security level
everywhere else.
Issue: androidx/media#1603
PiperOrigin-RevId: 662872860
This method was added in API 31 (S) but it's non-functional
(incorrectly, silently, returns `false`) on the Widevine plugin version
(`16.0`) from R (API 30), which some devices up to at least API 34 are
still using.
This results in ExoPlayer incorrectly selecting an insecure decoder for
L1 secure content, and subsequently calling
`MediaCodec.queueInputBuffer` instead of `queueSecureInputBuffer`,
which is not supported and generates the following error:
> Operation not supported in this configuration: ERROR_DRM_CANNOT_HANDLE
Issue: androidx/media#1603
#cherrypick
PiperOrigin-RevId: 662852176
When there is an exception thrown from the `LoadTask`, the `Loader` will call `Loader.Callback.onLoadError`. Some implementations of `onLoadError` method may call `MediaPeriod.onContinueLoadingRequested`, and in the `PreloadMediaSource`, its `PreloadMediaPeriodCallback` will be triggered and then it can further call `continueLoading` if it finds needed. However the above process is currently done synchronously, which will cause problem. By calling `continueLoading`, the `Loader` is set with a `currentTask`, and when that long sync logic in `Loader.Callback.onLoadError` ends, the `Loader` will immediately retry, and then a non-null `currentTask` will cause the `IllegalStateException`.
Issue: androidx/media#1568
#cherrypick
PiperOrigin-RevId: 662550622
Check if the output device supports spatialization for the requested output format. If so, return a stream decoded for 6 channels in a 5.1 layout. Otherwise, return a stream decoded for 2 channels in a binaural layout.
PiperOrigin-RevId: 662546818
This is an additional signal that legacy subtitle support needs to be
explicitly enabled, and is going away at some point.
PiperOrigin-RevId: 661305694
The integration with external libraries like Glide or Coil is
currently extremely complicated. Providing the boilerplate code
to handle the ImageDecoder interface and a better hook for custom
image decoders in DefaultRenderersFactory allows apps to easily
inject their own logic for external image loading libraries.
PiperOrigin-RevId: 659508914
This API allows users to retrieve the sample size, ensuring they can allocate sufficient buffer capacity before utilizing the `readSampleData(ByteBuffer buffer, int offset)` method to read data.
PiperOrigin-RevId: 658772408
Refactor to replace instances of `RuntimeException` with `IllegalStateException`.
This change ensures exceptions can be handled more specifically without
unintended catches of unrelated exceptions.
PiperOrigin-RevId: 658337459
Added a new data source which acts an adapter to read media data from platform `MediaDataSource`. This enables adding the `setDataSource(MediaDataSource)` API to `MediaExtractorCompat`.
PiperOrigin-RevId: 657564901
Added three `setDataSource` APIs in `MediaExtractorCompat`:
- `setDataSource(Context context, Uri uri, @Nullable Map<String, String> headers)` to set data source with a content URI and optional headers.
- `setDataSource(String path)` to set data source using a file path or HTTP URL.
- `setDataSource(String path, @Nullable Map<String, String> headers)` to set data source using a file path or HTTP URL with optional headers.
PiperOrigin-RevId: 657563973
The builtin speaker is to be supported as a suitable output when that is deliberately selected for the media playback by the user in Wear OS.
PiperOrigin-RevId: 655950824
The DefaultPreloadManagerTest didn't to catch this because we use main looper as the preload looper in the tests. This CL also improves the tests by assigning the preload looper with one that corresponds to a different thread.
PiperOrigin-RevId: 655664189
This is following a renaming of registerInputFrame to handleInputFrame.
- queueInputBitmap is renamed to handleInputBitmap for consistency with
handleInputFrame.
- registerInputStream is renamed to onInputStreamChanged for consistency
with media3 method names.
PiperOrigin-RevId: 655529699
Aligns `MediaExtractorCompat` with platform behavior by using `getDeclaredLength()`
instead of `getLength()` when setting the data source. This ensures compatibility
with asset files where the length is not predefined, even though it may result
in reading across multiple logical files when backed by the same physical file.
PiperOrigin-RevId: 655153390
AudioTrack automatically ramps down volume when pausing. However,
when this happens as part of a AudioSink.flush() operation, we
need to postpone the actual flush() until the ramp down finished
in the audio system. Otherwise audio is just cut off, creating pop
sounds.
Delaying the release is fine now, because DefaultAudioSink starts
creating a new track immediately without waiting for the previous
track to be released.
Also using the opportunity to add more comments about related quirks
of the AudioTrack flush/release handling for more context.
PiperOrigin-RevId: 654794818
We currently wait until a previous AudioTrack from the same
DefaultAudioSink is released on a background thread before attempting
to initialize a new AudioTrack. This is done to avoid issues where
the releasing track blocks some shared audio memory, preventing a new
track from being created.
The current solution has two main shortcomings:
- In most cases, the system can easily handle multiple AudioTracks
and waiting for the release just causes unnecessary delays (e.g.
when seeking).
- It only waits for a previous track from the same DefaultAudioSink,
not accounting for any other tracks that may be in the process of
being released from other players.
To improve on both shortcomings, we can
(1) move the check for "is releasing tracks and thus may block shared
memory" to the static release infrastructure to be shared across all
player instances.
(2) optimistically create a new AudioTrack immediately without waiting
for the previous one to be fully released.
(3) extend the existing retry logic that already retries failed
attempts for 100ms to only start the timer when ongoing releases are
done. This ensures we really waited until we have all shared resources
we can get before giving up completely. This also acts as a replacement
for change (2) to handle situations where creating a second track is
genuinely not possible. Also increase threshold to 200ms as the new
unit test is falky on a real device with just 100ms (highlighting that
the device needed more than 100ms to clean up internal resources).
PiperOrigin-RevId: 654053123