1260 Commits

Author SHA1 Message Date
Rohit Singh
c8aa122e8a Change from internal review 2024-09-16 13:34:21 +01:00
Rohit Singh
9975175700 Forward default methods 2024-09-16 13:07:36 +01:00
Rohit Singh
3c6f1f1e77 Add copyright text and move test to correct package 2024-09-16 12:36:03 +01:00
Rohit Singh
8ca12338f6 Format with google-java-format 2024-09-16 12:31:48 +01:00
Colin Kho
62aef96b7d Format code using google java format 2024-09-16 12:31:48 +01:00
Colin Kho
72e39c91c4 Denote ForwardingRenderer as subject to change 2024-09-16 12:31:48 +01:00
Colin Kho
72f26d79f6 Added a forwarding class for Renderer to support composing custom behavior on Metadata & Text Renderers 2024-09-16 12:31:48 +01:00
tianyifeng
72ae454f67 Use buffered duration from start position to control preload progress
`PreloadMediaSource` allows to have a `startPositionUs` passed when `preload` is called, then in `PreloadControl.onContinueLoadingRequested`, it can be more intuitive to see the buffered duration rather than the absolute buffered position as the preload progress. Similar in `DefaultPreloadManager`, we haven't allowed the apps to set a custom start position for individual sources though, once we add this support, using the "duration from the start position" than the absolute position will be less error-prone, otherwise, it can run into a case that the position that the apps set is smaller than the start position.

PiperOrigin-RevId: 674251362
2024-09-13 05:05:39 -07:00
claincly
bc8d82355f Block secondary audio processing until primary format is configured
PiperOrigin-RevId: 673961235
2024-09-12 12:42:09 -07:00
rohks
f133e8d1f2 Fix preroll sample handling for non-keyframe media start positions
When processing edit lists in MP4 files, the media start position may be a non-keyframe. To ensure proper playback, the decoder must preroll to the preceding keyframe, as these preroll samples are essential for decoding but are not rendered.

Issue: google/ExoPlayer#1659

#cherrypick

PiperOrigin-RevId: 673457615
2024-09-11 11:02:39 -07:00
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