6088 Commits

Author SHA1 Message Date
ibaker
fd24449e7e Add param comments to untilPosition calls in ExoPlayerScrubbingTest
Follow-up to 9073c2b28d

PiperOrigin-RevId: 756295111
2025-05-08 07:04:17 -07:00
dancho
5a7d545fd6 Fix flaky clearkeyPlayback_..._dropsInputBuffers test
Increase the input media duration to be sufficiently longer than
OFFSET_FROM_RESET_POSITION_TO_ALLOW_INPUT_BUFFER_DROPPING_US

PiperOrigin-RevId: 756283253
2025-05-08 06:20:48 -07:00
ibaker
9073c2b28d Deflake ExoPlayerScrubbingTest
Instead of waiting for pending commands to complete as a proxy for
'the requested seek(s) completed', we wait until the corresponding
playback position.

PiperOrigin-RevId: 756276867
2025-05-08 05:59:20 -07:00
kimvde
81e4488f0a MultipleInputVideoGraph: propagate Compositor output size changes
PiperOrigin-RevId: 756260135
2025-05-08 04:58:09 -07:00
ibaker
ce5e61e26f Annotate AIDL files with @RestrictTo to remove them from DAC
PiperOrigin-RevId: 756258872
2025-05-08 04:53:22 -07:00
ivanbuper
4669476353 Implement hasPendingData() in AudioGraphInputAudioSink
hasPendingData() should signal whether the final audio sink still
holds unconsumed frames so that the renderer can accurately detect a
buffering state.

Before this change, a media item transition could incorrectly trigger
a buffering state in the internal sequence players and cause
CompositionPlayer to interrupt playback. See Issue: androidx/media#2228.

PiperOrigin-RevId: 756252645
2025-05-08 04:28:39 -07:00
dancho
f5ae1b68fd Have CompositionPlayerSeekTest respect test timeout
Calls to release() can lead to player errors -> move release()
in the test body instead of tearDown()

The resettable count down latch was error-prone:
* Calling reset() swaps out the CountDownLatch and anything waiting on
the previous latch times out
* Calling unblock() after reset(INT_MAX) hangs the test

Replace the resettable count down latch with a normal CountDownLatch.

PiperOrigin-RevId: 756249512
2025-05-08 04:17:27 -07:00
ivanbuper
ba95585bef Do not queue flush operations when BufferingVideoSink#videoSink is null
Prewarming relies on two BufferingVideoSinks controlling the same
underlying video sink. If BufferingVideoSink queues a flush operation
caused by a prewarming renderer, when we transition between renderers
the BufferingVideoSink will flush ongoing playback and will cause
unwanted stuttering.

Flushing the video sink causes a chain reaction of making the video
renderer not ready, triggering a player BUFFERING state, and having
CompositionPlayer disable all renderers and pausing the final audio sink
as a result.

This is a partial fix for Issue: androidx/media#2228. The pending part of the fix is
to implement AudioGraphInputAudioSink#hasPendingData() to report an
accurate value.

PiperOrigin-RevId: 756238558
2025-05-08 03:36:53 -07:00
shahddaghash
30f645e073 Document motion photo imageDurationMs changes
Added documentation and release notes for using `imageDurationMs` to determine image asset loading in `DefaultAssetLoaderFactory`.

PiperOrigin-RevId: 756228166
2025-05-08 02:56:53 -07:00
kimvde
f5ff9672e2 Handle export ended after internal thread is quit
Export can be ended twice if an exception is thrown before Transformer
was fully released.

Also add a lock to make sure the released variable doesn't become true
right after its value is checked.

PiperOrigin-RevId: 756196139
2025-05-08 01:07:18 -07:00
sheenachhabra
db1c478dad Remove duplicate muxer test util methods
PiperOrigin-RevId: 756168918
2025-05-07 23:33:55 -07:00
sheenachhabra
2e18e5073c Implement Muxer interface in MP4 and Fragmented MP4 muxers
PiperOrigin-RevId: 755945054
2025-05-07 11:52:04 -07:00
tonihei
38ac6ba711 Fix onAudioPositionAdvancing callback
The logic has always been broken for multiple different reasons:
 - It applied usToMs twice, essentially making all calculations
   for the actual start time meaningless.
 - It compared against the fist observed timestamp after calling
   AudioTrack.play(), which may already include some advanced
   position.
 - The callback was falsely triggered after speed changes (when
   AudioTrack playback params are used).
 - It used the potentially smoothed position from different sources
   instead of using the latest reliable source
 - It did not wait until the getTimestamp source is reliable
   before triggering this callback (instead always relying on the
   more error-prone getPlaybackHeadPosition).

As a result it has always reported the system time when we first
observed a timestamp that was different from a previous one.

We can make the callback more useful by fixing these points:
 - Wait until the getTimestamp source is reliably advancing or
   definitely can't be used (by which point we should also have a
   more reliable playbackHeadPosition value).
 - Calculate the start time using the latest position before
   applying any smoothing.
 - Save the "from" position in start() before AudioTrack.play()
   is called. This also avoid triggering the callback after speed
   changes.
 - Don't apply usToMs twice.

PiperOrigin-RevId: 755927465
2025-05-07 11:09:34 -07:00
tonihei
90ca35b4bb Remove invalid prefixes from variables in session.legacy package
PiperOrigin-RevId: 755914708
2025-05-07 10:39:39 -07:00
dancho
2a274e9608 Allow changing SeekParameters for FrameExtractor
Add a new getFrame() overload that takes SeekParameters.

PiperOrigin-RevId: 755905876
2025-05-07 10:18:49 -07:00
Googler
88f1c64907 Internal Changes
PiperOrigin-RevId: 755903085
2025-05-07 10:12:03 -07:00
sheenachhabra
04b999914a Use muxer.BufferInfo class in Muxer.java
This is to remove dependency on `MediaCodec` from `muxer module`.

PiperOrigin-RevId: 755885374
2025-05-07 09:27:40 -07:00
tonihei
b03b22575f More safely clean potential dangling references from binder stubs
Binder stubs are GC roots and may be accidentally kept long after
the surrounding objects are gone (this is partially outside our
control, e.g. another app keeps a MediaController).

To prevent memory leaks, these binder stubs need to stop referencing
other instances whose data may be kept as well.

 - All stubs except one already use a WeakReference for the main
   owning class, which is cleared as soon as the class is released.
   - This change replace the AtomicReference in ExtraSession with
     a WeakReference to make it safer.
 - If the stub holds lists of data, these should be all cleared when
   released. This wasn't done in all cases yet.
 - Some local fields for MediaSessionManager can be removed entirely
   by just accessing the static variable on demand.

PiperOrigin-RevId: 755879020
2025-05-07 09:10:27 -07:00
ibaker
1cef4ed9df Log non-square pixel aspect ratio in EventLogger
Also include `w=` and `h=` in video and surface size logging.

PiperOrigin-RevId: 755821356
2025-05-07 06:09:57 -07:00
kimvde
a5346600a2 MultipleInputVideoGraph: rely on queueInputTexture() return value
Before, we were using a boolean to wait for the input stream to be
fully registered to the CompositionVideoFrameProcessor before queueing
an input texture. This should instead be done by checking the return
value of queueInputTexture().

Also fix a few small stylistic issues.

PiperOrigin-RevId: 755770940
2025-05-07 03:15:07 -07:00
kimvde
c628027b6b Remove usage of deprecated RENDER_OUTPUT_FRAME_IMMEDIATELY
PiperOrigin-RevId: 755766598
2025-05-07 03:01:25 -07:00
Googler
faa0644ed1 Add an AndroidTest for FinalShaderProgramWrapper
PiperOrigin-RevId: 755389859
2025-05-06 08:51:31 -07:00
Googler
cc8992410a Add cause constructor to GlException
PiperOrigin-RevId: 755383268
2025-05-06 08:31:47 -07:00
tonihei
fbee549f74 Improve detection of advancing timestamp in AudioTimestampPoller
We currently accept any difference in reported frame position
as an "advancing timestamp". However, we don't check if the
resulting position is actually advancing or was only slightly
corrected, but is not yet advancing reliably.

This results in AV sync issues if the timestamp is used too early
while it's not actually advancing yet, and the potential correction
is only read 10 seconds later when we query the timestamp again.

The fix is to check whether the timestamp is actually advancing
as expected (the resulting position from the previous and the
current snapshot don't differ by more than 1ms). To avoid
permanent polling in 10ms intervals for devices that never report
a reliable timestamp, we introduce another timeout after which we
give up.

PiperOrigin-RevId: 755373666
2025-05-06 08:04:19 -07:00
tonihei
0dc5ed19e2 Improve timestamp smoothing in AudioTrackPositionTracker
The position tracker has two different position sources,
getPlaybackHeadPosition and getTimestamp. Whenever we switch
between these sources, we smooth out the position differences
over a period of one second.

This has two problems:

 1. The smoothing duration is 1 sec regardless of the actual
    position difference. So for small differences, assuming
    the new timestamp is more correct, we needlessly keep
    the tracker with a position offset for longer. For large
    differences, the smoothing may result in an extremely
    large speedup (up to 5x in theory, for a max allowed diff
    of 5 seconds smoothed over a 1 second real time period).

    The solution to this issue is to adjust the smoothing
    period to the actual difference by using a maximum
    speedup/slowdown set to 10% at the moment. Smaller
    differences are corrected faster and larger differences
    are corrected in a slightly smoother way without speeding
    up drastically. We still need an upper bound though (set
    to 1 second difference) where plainly jumping to the correct
    position is likely a better user experience than having a lenghty
    smoothing.

 2. The smoothing is only applied when switching between position
    sources. That means any position drift or jump coming from the
    same source is always taken as it is without any smoothing. This
    is problematic for the getTimstamp-based position in particular
    as it is only sampled every 10 seconds.

    The solution to this problem is to entirely remove the condition
    that smoothing only happens when switching between position
    sources. Instead we can always check whether the position drift
    compared to the last known position is more than the maximum allowed
    speedup/slowdown of 10% and if so, start applying smoothing.

    This helps to smooth out the position progress at the start of
    playback and after resumption when we switch between the position
    sources and both sources are not super reliable yet and it also
    helps for unexpected jumps in the position of getTimestamp later
    on during playback.

PiperOrigin-RevId: 755348271
2025-05-06 06:36:10 -07:00
dancho
07b278a884 Read spsData.decodedWidth and decodedHeight for MPEG-TS and H.265
Disables codec reuse and adaptation when the crop rect,
but not the decoded resolution changes.

PiperOrigin-RevId: 755315182
2025-05-06 04:37:14 -07:00
dancho
e9b2ded810 Rollback of a78d0c3994
PiperOrigin-RevId: 755302920
2025-05-06 03:54:45 -07:00
tonihei
ffb8d3ca66 Refactor AudioTimestampPoller to a smaller API surface
This moves the position estimation and plausibility checks inside
the class.

Mostly a no-op change, except that the plausible checks now use
the estimated timestamp from getTimestamp and the playback head
position to make them actually comparable. Before, we were comparing
the last snapshot states which may not necessarily be close together.
Given the large error threshold of 5 seconds, this shouldn't make
a practical difference though, just avoids noise and confusion.

PiperOrigin-RevId: 754035464
2025-05-02 09:44:43 -07:00
claincly
def4794d96 Split initializing CompositionPlayerInternal and setting composition
PiperOrigin-RevId: 753976959
2025-05-02 06:18:20 -07:00
dancho
ef39fc70d9 Disable codec reuse when only crop rect changes
Work around a bug where MediaCodec fails to adapt between
formats that have the same decoded picture resolution but
different crop.

Add a playlist of two MP4 files that reproduce the issue.

This CL implements the workaround for H.265 and Mp4

PiperOrigin-RevId: 753976872
2025-05-02 06:16:11 -07:00
michaelkatz
52d9cfdcb7 Add plumbing of ScrubbingModeParameters from ExoPlayer to Renderers
PiperOrigin-RevId: 753959866
2025-05-02 05:09:04 -07:00
tonihei
aabf840d1d Update Uri shared to platform mediasession to only use RequestMetadata
This already the case for the platform Queue's MediaDescription, but
we currently use the localConfiguration.uri for the platform
MediaMetadata field even though we intentionally strip locaConfiguration
fields before sharing with other apps.

PiperOrigin-RevId: 753952733
2025-05-02 04:35:58 -07:00
ivanbuper
bd24ec08d1 Add test to catch single asset audio sequence underruns
This test previews a composition containing only a single audio asset
sequence. The audio asset is a 1s, stereo, locally available WAV file.
Catching an underrun in this test is a likely indication of something
being seriously wrong with the device's state or a performance
regression on the audio pipeline.

This test is a verification of the fix in 2e20d35c3d. Without this fix
the newly added test fails because MediaCodecAudioRenderer attempts to
use dynamic scheduling with AudioGraphInputAudioSync
(which is unsupported) after EoS is signalled.

PiperOrigin-RevId: 753552825
2025-05-01 05:33:15 -07:00
ivanbuper
e06e9b4cc9 Detect underruns with AudioTrack#getUnderrunCount() in DefaultAudioSink
Prior to this change, DefaultAudioSink (via AudioTrackPositionTracker)
would use best-effort logic to infer underruns in the underlying
AudioTrack. This logic would miss underrun events (e.g. newly added test
fails if run without any changes to AudioTrackPositionTracker).

This change should help more accurately detect regressions in the audio
pipeline.

PiperOrigin-RevId: 753550187
2025-05-01 05:20:02 -07:00
tonihei
8bcef5df6d Add static completion ratio to media resumption
This allows to show a seekbar on the resumption notification
after reboot.

PiperOrigin-RevId: 753538903
2025-05-01 04:30:29 -07:00
sheenachhabra
d2fcf0c4eb Make Muxer interface extend AutoCloseable
PiperOrigin-RevId: 753534910
2025-05-01 04:15:29 -07:00
shahddaghash
7c13204c3b Use imageDurationMs to determine image asset loading
Updated the createAssetLoader method to directly use the `mediaItem.localConfiguration.imageDurationMs` to determine if an ImageAssetLoader should be created for an image. This is specifically used for determining whether a motion photo should be treated as an image or as a video.

PiperOrigin-RevId: 753235616
2025-04-30 11:03:33 -07:00
Copybara-Service
acdc71bb63 Merge pull request #2386 from DolbyLaboratories:dlb/cmcd/nullable-configuration
PiperOrigin-RevId: 753210729
2025-04-30 10:04:01 -07:00
sheenachhabra
bfb8c5c237 Fix muxer interface java doc
PiperOrigin-RevId: 753203794
2025-04-30 09:45:50 -07:00
ibaker
8dc8003afc Deprecate Util.compareLong in favour of Long.compare
The `Long` method was only added in API 19, so wasn't previously
usable when ExoPlayer's minSdk was 16.

PiperOrigin-RevId: 753185351
2025-04-30 08:50:22 -07:00
Copybara-Service
df41f6b041 Merge pull request #2387 from DolbyLaboratories:dlb/cmcd/pr-key-not-allowed
PiperOrigin-RevId: 753181724
2025-04-30 08:40:00 -07:00
ibaker
c137d27850 Add support for S_TEXT/SSA CodecId in MKV files
This change renames the existing `sample_with_ssa_subtitles.mkv` test
file (with `S_TEXT/ASS` codec ID) to `sample_with_ass_subtitles.mkv`
(so the file name matches the codec ID), and forks a new test file
called `sample_with_ssa_subtitles.mkv` with the `S_TEXT/SSA` codec ID.
`MatroskaExtractorTest` then asserts that both these files produce
identical dump files.

Issue: androidx/media#2384
PiperOrigin-RevId: 753164883
2025-04-30 07:48:25 -07:00
Copybara-Service
e4b23f6b6c Merge pull request #2377 from bubenheimer:handleSetDeviceVolume_flags
PiperOrigin-RevId: 753132783
2025-04-30 05:52:20 -07:00
jbibik
49d929b212 [ui-compose] Eliminate race condition in PresentationState
PresentationState creation and listener registration are not an atomic operation. This happens because the LaunchedEffect which starts the listen-to-Player-Events coroutine can be pre-empted with other side effects, including the ones that change something in the Player.

rememberPresentationState function creates a PresentationState object and initialises it with the correct fresh values pulled out of the Player. The subscription to Player events with a registration of a Listener (via PresentationState.observe()) is not immediate. It *returns* immediately, but is instead scheduled to happen later, although within the same Handler message. Other LaunchedEffects could have been scheduled earlier and could take place between the button state creation and listener subscription.

This is not a problem if no changes to the player happen, but if we miss the relevant player events, we might end up with a UI that is out of sync with reality. The way to fix this is to pull the latest values out of the Player on demand upon starting to listen to Player events.

PiperOrigin-RevId: 753129489
2025-04-30 05:39:15 -07:00
Mattias Buelens
ec01011374 Fix CMCD sending pr=0.00 even when key is not allowed 2025-04-30 14:28:20 +02:00
Mattias Buelens
a019de887c Allow CmcdConfiguration.Factory to return null to disable CMCD 2025-04-30 14:19:20 +02:00
tonihei
deb466c496 Add artwork to stored preferences
This allows it to be displayed after reboot when we can't reload
it safely over network.

PiperOrigin-RevId: 753122948
2025-04-30 05:13:05 -07:00
sheenachhabra
8d87a69351 Rollback of a31c7ad9a8
PiperOrigin-RevId: 753104435
2025-04-30 04:01:19 -07:00
jbibik
16c071109a [ui-compose] Make PlayerSurface accept a nullable Player
`PlayerSurface` is just an `AndroidView` composable wrapping `SurfaceView` and `TextureView`. It uses the `Player` passed to it to set the `SurfaceHolder`s from those `SurfaceView`/`TextureView` objects. However, it does not technically need the Player to be created - the result will just be an empty Surface.

Add an optimisation to PlayerSurfaceInternal that avoids preemptive clearing of the Surface on the old Player. This helps avoid a costly creation of a surface placeholder right before (potentially) assigning the new Surface to that player.

PiperOrigin-RevId: 752840145
2025-04-29 12:34:35 -07:00
Uli Bubenheimer
0d2b831c94 Add missing @C.VolumeFlags for SimpleBasePlayer.handleSetDeviceVolume 2025-04-29 17:27:54 +01:00