The test is flaky because the decoding process in the renderer
depends on some timing from MediaCodec beyond our control and
the new keyframe added in the test is sometimes 'dropped' when
it arrives too late.
We can fix this by controlling the test progress a bit more
tightly: first rendering with the same current time until the
key frame is processed and then start increasing the time
until we've reached the end.
#cherrypick
PiperOrigin-RevId: 646064352
Some cases are not handled correctly at the moment:
- Pausing during suppressed playback should not clear the
suppression state.
- Transient focus loss while paused should be reported as
a playback suppression.
Issue: androidx/media#1436
#cherrypick
PiperOrigin-RevId: 644971218
Sometimes the reason for the current state may change. If we don't
report this again, users have no way of knowing that the reason
changed.
Also adjust ExoPlayerImpl and MediaControllerImplBase accordingly.
SimpleBasePlayer already adheres to this logic.
#cherrypick
PiperOrigin-RevId: 644970236
This helps to keep the reason always together with the state it
is referring to, avoiding any side channels and making sure there
are no accidental inconsistencies.
#cherrypick
PiperOrigin-RevId: 644969317
The 'player commands' returned to ExoPlayerImpl instruct the
player on how to treat the current audio focus state.
The current return value when playWhenReady==false is misleading
because it implies we are definitely not allowed to play as if
we've lost focus. Instead, we should return the actual player
command corresponding to the focus state we are in.
This has no practical effect in ExoPlayerImpl as we already
ignore the 'player command' completely when playWhenReady=false.
To facilitate this change, we also introduce a new internal
state for FOCUS_NOT_REQUESTED to distinguish it from the state
in which we lost focus.
#cherrypick
PiperOrigin-RevId: 644416586
There are a lot of tests for AudioFocusManager in isolation,
but almost none for the handling in ExoPlayer.
Add test coverage for all the common cases, including some
currently broken behavior that is indicated by TODOs.
PiperOrigin-RevId: 644319251
This method allows customizing the maximum position when using `Player.seekToPrevious()`.
This commit also adds two new methods to `TestExoPlayerBuilder`:
- `setMaxSeekToPreviousPosition(long)`
- `getMaxSeekToPreviousPosition()`
This change introduces a new class in Media3 `MediaExtractorCompat`, designed to be a drop-in replacement for platform `MediaExtractor`. While not all APIs are currently supported, the core functionality for the most common use cases of `MediaExtractor` is now available. Full API compatibility will be achieved in the future.
PiperOrigin-RevId: 643045429
When deselecting the single sample track and later re-selecting this
track, the current shortcuts in ProgressiveMediaPeriod don't handle
this case correctly and cause assertion failures.
In particular, this change fixes 3 issues:
1. When re-selecting the single sample track, we have cleared the
SampleQueue and need to reload the sample. The existing shortcut
should only be applied to avoid the reload when starting from a
non-zero position.
2. When de-selecting the track, ProgressiveMediaPeriod is left in
an inconsistent state where the sample queues are empty but
loadingFinished is still true. Fix this by resetting
loadingFinished to false.
3. When seeking, we avoid reloading the stream if we can keep
inside the existing samples. This logic assumes that all
remaining samples will continue to be loaded in the queue.
This condition isn't true though for single sample tracks
that have been de-selected. They appear to support the seek
inside the queue (=no seek necessary, always supported), but
still require a new load if there is no ongoing one to load
the sample. Fix this by checking this implicit assumption
(still loading, or loading finished).
PiperOrigin-RevId: 642650248
A fatal `PlaybackException` is mapped to a legacy playback state
in state `STATE_ERROR` with error code, message and extras. A
non-fatal error sent to controllers with `MediaSession.sendError`
is synced to the legacy session by setting error code and message
and merging the extras while preserving the rest of the state in
sync with the session player.
Vice versa, a `MediaController` connected to a legacy session receives
fatal errors through `Player.onPlayerErrorChanged()` and non-fatal errors
through `MediaController.Listener.onError()`.
Error codes are mapped in `LegacyConversions`. Values of error codes
in `@SessionError.ErrorCode` come from `@PlaybackExceptino.ErrorCode`
with the exception of `@SessionError.ERROR_IO` and
`@SessionError.ERROR_UNKNOWN`. These already exist in
`@PlaybackException.ErrorCode` and are mapped accordingly to avoid
semantic duplicates.
PiperOrigin-RevId: 642595517
- Video release should check for buffer timestamp (which is renderer-offsetted), rather than the frame timestamp
- ImageRenderer should report ended after all of it's outputs are released, rather than when finished consuming its input.
Add tests for timestamp handling
PiperOrigin-RevId: 642587290
It's currently not possible to remove a previously set image output
on ExoPlayer, although the underlying renderer already supports
receiving null to clear the output. Marking the parameter as
nullable allows apps to clear it as well.
PiperOrigin-RevId: 642569081
In order to do that, make the VideoSink nullable in MCVR.
We want to avoid calling VideoFrameReleaseControl.setClock directly
from MCVR when the sink is enabled. The goal is to handle all the
communication with the release control from the sink/sink provider.
PiperOrigin-RevId: 642542063
These are no longer needed now that the `Bundleable` interface has been
removed. Public methods are deprecated, package-private ones are
removed. Callers are migrated in both cases (except where tests
explicitly exist for the deprecated method).
PiperOrigin-RevId: 642294451
This interface is not used in the library. Callers can use the
`Bundle toBundle()` and `static Foo fromBundle(Bundle)` methods
defined directly on each type instead.
PiperOrigin-RevId: 642271609
The previous wording suggested that `setVideoEffects()` may **only** be
called before `prepare()`, i.e. the effect cannot be changed during
playback. The intent is instead that `setVideoEffects()` must be called
once before playback in order to configure the effects pipeline, but
the effect can then be changed during playback by further calls to
`setVideoEffects()`.
Issue: androidx/media#1393
PiperOrigin-RevId: 641853629
Before, the listener was set in onReadyToInitializeCodec, which means
that it was reset every time a new codec was used.
We need to set the listener every time MCVR is enabled (not only the
first time), because it might have been set by another renderer.
PiperOrigin-RevId: 641825717
Before this change, the timestamps output from composition playback is offset
with the renderer offset. After this change, the offset is removed and the
timestamp behaviour converges with Transformer, that is, the timestamps of
video/images frames will follow that of the composition. For example, with a
composition of two 10-s items, clipping the first with 2s at the start, the
timestamp of the first frame in the second item, will be 8s.
PiperOrigin-RevId: 641121358
When the frame release control invalidates a buffer and returns that
the buffer must be ignored, we need to exit early before performing
additional checks that may result in method calls using the invalid
buffer.
PiperOrigin-RevId: 640555688
Usages removed in this CL are:
- onProcessedStreamChange, which was already called from the VideoSink
(via VideoFrameRenderControl)
- setOutputSurface, which was also already called from the VideoSink
- setFrameRate, which this CL now sets in the VideoSink
PiperOrigin-RevId: 640530903
Before this CL, we were checking whether the video sink was initialized
to determine whether it should be used. In the meantime,
shouldUseVideoSink has been introduced. Use this boolean to check
whether to use the video sink as it's a clearer signal.
PiperOrigin-RevId: 640499147
This avoids having to add AnalyticsListener and catching the `onPlayerReleased` callback.
The `Exoplayer.release()` method is blocking and one can be sure that the player is released if the call returned. However, the method is useful for UI testing and asserting that the player is released after a certain UI action, e.g. closing the activity or detaching a window.
PiperOrigin-RevId: 640114416
The CMCD data was incorrectly added to the `dataSpec` of the media segment instead of the init segment.
Also relaxed the condition for playbackRate to be C.RATE_UNSET when creating an instance of CmcdData.Factory as there was nothing enforcing this check.
#minor-release
PiperOrigin-RevId: 639046080
When running in asynchronous mode, MediaCodec will be running the CPU to signal input and output buffers being made available for use by the player. With ExoPlayer.experimentalSetDynamicSchedulingEnabled set to true, ExoPlayer will wakeup to make rendering progress when MediaCodec raises these signals. In this way, ExoPlayer work will align more closely with CPU wake-cycles.
PiperOrigin-RevId: 638962108
Currently ExoPlayer schedules its main work loop on a 10 ms interval. When renderers cannot make any more progress (ex: hardware buffers are fully written with audio data), ExoPlayer should be able to schedule the next work task further than 10ms out into the future.
Through `experimentalSetDynamicSchedulingEnabled` and these changes to `MediaCodecAudioRenderer`, ExoPlayer can use the data provided by the audio renderer to dynamically schedule its work tasks based on when it is expected that progress can be made.
PiperOrigin-RevId: 638677454
Currently ExoPlayer schedules its main work loop on a 10 ms interval. When renderers cannot make any more progress(ex: hardware buffers are fully written with audio data), ExoPlayer should be able to schedule the next work task further than 10Ms out.
Through `experimentalSetDynamicSchedulingEnabled`, ExoPlayer will dynamically schedule its work tasks based on when renderers are expected to be able to make progress.
PiperOrigin-RevId: 638676318