1300 Commits

Author SHA1 Message Date
kimvde
8271a5f920 Rename CompositingVideoSinkProvider and PreviewAudioPipeline
The components are mirror components for video and audio so they should
have a matching name

PiperOrigin-RevId: 673357081
2024-09-11 05:49:35 -07:00
jbibik
8bfa7e2de1 Make StreamVolumeManager take streamType in constructor
Avoids the dispatch of listener notifications of stream type/device volume change during construction of ExoPlayer. That was problematic because we end up blocking on `constructorFinished.blockUninterruptible()`

Issue: androidx/media#1692
PiperOrigin-RevId: 672965552
2024-09-10 08:05:21 -07:00
sheenachhabra
327b1c8ad8 Move getCodecProfileAndLevel to CodecSpecificDataUtil
`Muxer` module needs to use this method, hence moved to common.

This CL also makes `getHevcProfileAndLevel` public because this is used
in `MediaCodecUtil`.

PiperOrigin-RevId: 671739166
2024-09-06 06:52:29 -07:00
ibaker
0933f561b7 Move MCR CryptoException handling to top-level render() method
Handling for `MediaCodec.CryptoException` was originally added only
around calls to `MediaCodec.queueSecureInputBuffer` and
`queueInputBuffer` (because these are the only methods that can throw
this exception). When asynchronous interaction with `MediaCodec` was
added in <unknown commit>, exceptions from `MediaCodec` started being stored
and bubbled out of **later** interactions with `MediaCodecAdapter`. This
means that `MediaCodecRenderer` can now see `CryptoException` thrown
from a different method, like
`MediaCodecAdapter.dequeueInputBufferIndex()`, and this ends up missing
the `catch (CryptoException)` code in `MediaCodecRenderer`. This results
in an "unexpected runtime error" stack trace like [A].

This change fixes the stack trace to:
1. Make it a "renderer exception" instead of "unexpected runtime error"
2. Include the correct DRM error code -> `@PlaybackException.ErrorCode`
   mapping.

You can see the corrected stack trace below [B].

-----

[A] (synthesized from manually throwing a `CryptoException` from
`AsynchronousMediaCodecBufferEnqueuer#doQueueSecureInputBuffer`)

```
playerFailed [eventTime=11.56, mediaPos=10.35, window=0, period=0, errorCode=ERROR_CODE_UNSPECIFIED
  androidx.media3.exoplayer.ExoPlaybackException: Unexpected runtime error
      at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:729)
      at android.os.Handler.dispatchMessage(Handler.java:103)
      at android.os.Looper.loopOnce(Looper.java:232)
      at android.os.Looper.loop(Looper.java:317)
      at android.os.HandlerThread.run(HandlerThread.java:85)
  Caused by: android.media.MediaCodec$CryptoException: Test error message
      at androidx.media3.exoplayer.mediacodec.AsynchronousMediaCodecBufferEnqueuer.doQueueSecureInputBuffer(AsynchronousMediaCodecBufferEnqueuer.java:232)
      at androidx.media3.exoplayer.mediacodec.AsynchronousMediaCodecBufferEnqueuer.doHandleMessage(AsynchronousMediaCodecBufferEnqueuer.java:196)
      at androidx.media3.exoplayer.mediacodec.AsynchronousMediaCodecBufferEnqueuer.access$000(AsynchronousMediaCodecBufferEnqueuer.java:47)
      at androidx.media3.exoplayer.mediacodec.AsynchronousMediaCodecBufferEnqueuer$1.handleMessage(AsynchronousMediaCodecBufferEnqueuer.java:93)
      at android.os.Handler.dispatchMessage(Handler.java:107)
      at android.os.Looper.loopOnce(Looper.java:232) 
      at android.os.Looper.loop(Looper.java:317) 
      at android.os.HandlerThread.run(HandlerThread.java:85) 
```

[B]

```
Playback error
  androidx.media3.exoplayer.ExoPlaybackException: MediaCodecAudioRenderer error, index=1, format=Format(0, null, null, audio/mp4a-latm, mp4a.40.2, 134359, en, [-1, -1, -1.0, null], [2, 44100]), format_supported=YES
      at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:649)
      at android.os.Handler.dispatchMessage(Handler.java:103)
      at android.os.Looper.loopOnce(Looper.java:232)
      at android.os.Looper.loop(Looper.java:317)
      at android.os.HandlerThread.run(HandlerThread.java:85)
  Caused by: android.media.MediaCodec$CryptoException: Test error message
      at androidx.media3.exoplayer.mediacodec.AsynchronousMediaCodecBufferEnqueuer.doQueueSecureInputBuffer(AsynchronousMediaCodecBufferEnqueuer.java:232)
      at androidx.media3.exoplayer.mediacodec.AsynchronousMediaCodecBufferEnqueuer.doHandleMessage(AsynchronousMediaCodecBufferEnqueuer.java:196)
      at androidx.media3.exoplayer.mediacodec.AsynchronousMediaCodecBufferEnqueuer.access$000(AsynchronousMediaCodecBufferEnqueuer.java:47)
      at androidx.media3.exoplayer.mediacodec.AsynchronousMediaCodecBufferEnqueuer$1.handleMessage(AsynchronousMediaCodecBufferEnqueuer.java:93)
      at android.os.Handler.dispatchMessage(Handler.java:107)
      at android.os.Looper.loopOnce(Looper.java:232) 
      at android.os.Looper.loop(Looper.java:317) 
      at android.os.HandlerThread.run(HandlerThread.java:85) 
```

PiperOrigin-RevId: 670951229
2024-09-04 06:44:21 -07:00
rohks
6e1bab03bd Add Mp4PlaybackTest for sample with edit list (edts box)
PiperOrigin-RevId: 670572646
2024-09-03 08:43:33 -07:00
dancho
1c61fbadf7 Downscale bitmaps during decoding in Transformer
Limit input image size in Transformer to be less than 4096x4096.
For very large images, this can reduce memory usage substantially,
and stays away from `GL_MAX_TEXTURE_SIZE` - often 4096

PiperOrigin-RevId: 670555939
2024-09-03 07:53:13 -07:00
Copybara-Service
854566dbfe Merge pull request #1371 from v-novaltd:dsparano-exo207
PiperOrigin-RevId: 669352191
2024-08-30 09:35:32 -07:00
microkatz
f1654732a6 Added release note for change 2024-08-30 13:47:43 +00:00
tonihei
41a56daab7 Code formatting 2024-08-29 13:48:41 +01:00
Colin Kho
a509033a5c Correct grammar and format javadoc on DrmUtil.executePost 2024-08-29 13:19:27 +01:00
Colin Kho
4ee34cc00e Refactor HttpMediaDrmCallback's executePost into a shared utility method within DrmUtil 2024-08-29 13:19:27 +01:00
tonihei
e8664dbc8e Report initial discontinuity for DASH periods that require preroll
DASH periods don't have to start at the beginning of a segment. In
these cases, they should report an initial discontinuity to let the
player know it needs to expect preroll data (e.g. to flush renderers)

This information is only available in the ChunkSampleStream after
loading the initialization data, so we need to check the sample
streams and tell them to only report discontinuities at the very
beginning of playback. All other position resets are triggered by
the player itself and don't need this method.

Issue: androidx/media#1440
PiperOrigin-RevId: 668831563
2024-08-29 01:57:15 -07:00
kimvde
8367e420ad Import correct nullable annotation
PiperOrigin-RevId: 668521379
2024-08-28 10:54:29 -07:00
tianyifeng
c2e81052e8 Fix flakiness in ExoPlayerTest
In the flaky test `ExoPlayerTest.loading_withLargeAllocationCausingOom_playsRemainingMediaAndThenThrows`, it is indeterministic that when the message `MSG_IO_EXCEPTION` from the loader thread will arrive on the playback looper. If it arrives after `MSG_PERIOD_PREPARED`, then the period can continue loading and get the three samples written to the `SampleQueue` before the intentional OOM surfacing to the `ExoPlayerImplInternal`, otherwise, the OOM will be detected by `ExoPlayerImplInternal` very early and the player disallows to load three samples, which will cause the assertion to fail.

As we are expecting the three samples to play until the playback fails, we should assume that the `Loader` encounters the OOM after those samples loaded, thus we need to put this trigger a bit later until the `SampleStreamItem`s are handled by the `FakeSampleStream`. This could be checked by the return value of `FakeMediaPeriod.continueLoading` (super class implementation). However, `FakeMediaPeriod.continueLoading` originally always returns `true`, which is not aligned with the javadoc of `MediaPeriod.continueLoading`:

"return `true` if progress was made, meaning that `getNextLoadPositionUs()` will return a different value than prior to the call, `false` otherwise."

then we should also modify that logic.

PiperOrigin-RevId: 668438316
2024-08-28 07:16:29 -07:00
microkatz
0ac26c4004 Format with google-java-format 2024-08-28 12:41:49 +00:00
Daniele Sparano
7473156853 Fix output pixel aspect ratio and add test for it 2024-08-28 12:41:49 +00:00
Daniele Sparano
f0463bff8a Set pixel aspect ratio from output media format if set 2024-08-28 12:41:49 +00:00
tonihei
d0676245b5 Add AnalyticsListener.onRendererReadyChanged
This callback allows listeners to track when individual renderers
allow or prevent playback from being ready. For example, this is useful
to figure out which renderer blocked the playback the longest.

PiperOrigin-RevId: 667970933
2024-08-27 07:08:42 -07:00
kimvde
a4d0735d4c Fix player hanging when seeking at MediaItem transition
Before this CL, the video sink was stuck if a flush was executed:
- after VideoSink.onInputStreamChanged, which is setting
  pendingInputStreamBufferPresentationTimeUs and
- before the previous stream was fully rendered.

This is because pendingInputStreamBufferPresentationTimeUs was not reset
to TIME_UNSET when flushing the sink, so that the sink was still waiting
for the last frame of the previous stream to be rendered in
handleInputFrame/Bitmap.

PiperOrigin-RevId: 667924517
2024-08-27 04:00:46 -07:00
tonihei
6f0cb539d0 Add util method BaseRenderer.getStreamOffsetUs
This simplifies the common pattern of saving this offset in
onStreamChanged to use it at a later point.

PiperOrigin-RevId: 666226263
2024-08-22 00:53:04 -07:00
tianyifeng
410b26fba1 Detect SampleStream error after PreloadMediaPeriod has prepared
Per the javadoc, the method `MediaPeriod.maybeThrowPrepareError` is only allowed to be called before the period has completed preparation. For later errors in loading the streams, `SampleStream.maybeThrowError` will be called instead.

PiperOrigin-RevId: 665831430
2024-08-21 05:16:42 -07:00
tianyifeng
351593a250 Allow playback regardless buffered duration when loading fails
It is possible for playback to be stuck when there is failure in loading further data, while the player is required to load more due to the buffered duration being under `DefaultLoadControl.bufferForPlayback`. Therefore, we check if there is any loading error in `isLoadingPossible`, so that the player will allow the playback of the existing data rather than waiting forever for the data that can never be loaded.

Issue: androidx/media#1571
#cherrypick
PiperOrigin-RevId: 665801674
2024-08-21 03:37:42 -07:00
Copybara-Service
1bb48b1c47 Merge pull request #1616 from colinkho:chmain
PiperOrigin-RevId: 665779059
2024-08-21 02:32:16 -07:00
Copybara-Service
5304f227a7 Merge pull request #1624 from colinkho:comain
PiperOrigin-RevId: 665430514
2024-08-20 10:47:43 -07:00
Ian Baker
9c25845cd7 Restore a couple of blank lines 2024-08-20 17:47:48 +01:00
Ian Baker
a6f5d3daf5 Format with google-java-format 2024-08-20 17:47:48 +01:00
Colin Kho
0a0444b9a5 Use Suppliers.memoize for lazy instantiation of AudioManager 2024-08-20 17:47:47 +01:00
Colin Kho
6af92b0af3 Differ AudioManager retrieval to whenever AudioFocusManagement is required 2024-08-20 17:47:47 +01:00
Copybara-Service
24f3856ea4 Merge pull request #1580 from colinkho:main
PiperOrigin-RevId: 665330328
2024-08-20 06:17:20 -07:00
Ian Baker
41430aaa0c Fix annotation position and clarify javadoc 2024-08-20 13:42:00 +01:00
ibaker
b04b270c2b Use SubtitleExtractor from MediaParserChunkExtractor
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
2024-08-20 03:54:17 -07:00
Ian Baker
af5df6e700 Add retryCount parameter to make it clear onLoadStarted is called for retries too 2024-08-20 11:28:18 +01:00
Colin Kho
33d9b78e21 Fix javadoc of onLoadStarted & remove error information as fields 2024-08-20 11:13:41 +01:00
Colin Kho
1cc1bf02ef Added onLoadStarted callback to Loader's callback 2024-08-20 11:13:41 +01:00
kimvde
266f16823f Remove VideoSink.isFrameDropAllowedOnInput
This is an unnecessary layer

PiperOrigin-RevId: 665267029
2024-08-20 03:09:13 -07:00
Colin Kho
f9f3e67ee2 Include initialization chunk wording in getChunkIndex method 2024-08-19 10:31:34 -07:00
Colin Kho
4a6c5c7598 Cache ChunkIndex once load is done 2024-08-19 10:28:14 -07:00
ibaker
3600d04719 Deprecate SingleSampleMediaChunk
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
2024-08-16 08:36:38 -07:00
Colin Kho
1c1fd4d8b8 Add getter for ChunkIndex on InitializationChunk 2024-08-15 10:00:56 -07:00
tonihei
b58a1d16f7 Split DefaultAudioSink.writeBuffer in two seperate steps
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
2024-08-15 08:33:31 -07:00
ktrajkovski
fc18ad3135 Add LibiamfAudioRenderer's constructor to proguard rules.
Making a change to the `proguard-rules.txt` also requires a test added as `IamfModuleProguard`.

PiperOrigin-RevId: 663239150
2024-08-15 02:55:38 -07:00
ibaker
9d62845c45 Pass explicit securityLevel into MediaDrm.requiresSecureDecoder
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
2024-08-14 04:52:33 -07:00
ibaker
ca455ee858 Check WV version before relying on MediaDrm.requiresSecureDecoder
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
2024-08-14 03:27:50 -07:00
kak
e7f037bff5 Automated Code Change
PiperOrigin-RevId: 662793513
2024-08-13 23:32:49 -07:00
tianyifeng
cd532c5fb2 Handle preload callbacks asynchronously in PreloadMediaSource
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
2024-08-13 09:45:35 -07:00
ktrajkovski
92cff64321 Add spatial effects to IAMF support in Exoplayer.
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
2024-08-13 09:34:50 -07:00
ibaker
0411e1937b Deprecate SingleSampleMediaSource
This is an additional signal that legacy subtitle support needs to be
explicitly enabled, and is going away at some point.

PiperOrigin-RevId: 661305694
2024-08-09 10:07:14 -07:00
kak
2202397758 Automated Code Change
PiperOrigin-RevId: 660491742
2024-08-07 12:28:25 -07:00
tonihei
b00e018697 Add ImageDecoder for external image loading libraries
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
2024-08-05 04:36:16 -07:00
rohks
8aab324fb4 Add the getSampleSize() API to MediaExtractorCompat
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
2024-08-02 06:33:06 -07:00