We already have logic to end all session except the current one if the
current one doesn't have a MediaPeriodId yet. This is assuming that this
only happens after a seek on the app side where the player doesn't have
detailled knowledge about the MediaPeriodIds yet.
Currently this logic isn't triggered if the window we are coming from
doesn't have its MediaPeriodId either as we run into another check that
keeps sessions around until we have a valid windowSequenceNumber.
Swapping both conditions fixes this case without breaking any of the
other known transition scenarios.
Issue: androidx/media#180
PiperOrigin-RevId: 480866465
We currently use the literal -1 (=NO_VALUE) when adding up the
total. Tracks without known bitrate can be ignored in the
calculation, but we should use an explicit value of 0.
#minor-release
Issue: google/ExoPlayer#10664
PiperOrigin-RevId: 480048126
If the sample type is Dolby Vision and the display does not support Dolby Vision, then the capabilities DecoderSupport flag is set to DECODER_SUPPORT_FALLBACK_MIMETYPE. This denotes that the renderer will use a decoder for a fallback mimetype if possible. This alters track selection as tracks with DecoderSupport DECODER_SUPPORT_PRIMARY are preferred.
UnitTests included
-DefaultTrackSelector test that checks track selection reordering with DECODER_SUPPORT_FALLBACK_MIMETYPE
-MediaCodecVideoRenderer test that checks setting of DecoderSupport flag based on Display's Dolby Vision support
Issue: google/ExoPlayer#8944
PiperOrigin-RevId: 480040876
* Add `setOutputStreamOffsetUs(long)` method in `AudioSink`.
* Add private methods `setOutputStreamOffsetUs(long)` method in `MediaCodecRenderer` and `DecoderAudioRenderer`.
* Add protected method `onOutputStreamOffsetUs(long)` method in `MediaCodecRenderer`, in which:
* `MediaCodecRenderer` itself will be no-op for this method.
* `MediaCodecAudioRenderer` will propagate this value to its `audioSink`.
* Add logics in `DecoderAudioRenderer` to calculate `outputStreamOffsetUs`.
PiperOrigin-RevId: 479265429
This allows to access the associated functionality of AudioTrack and
fills a feature gap to MediaPlayer, which has a similar method.
Issue: androidx/media#135
PiperOrigin-RevId: 476398964
If the sample type is dolby vision and the following conditions match
a)There is a supported alternative codec mimetype
b)Display does not support Dolby Vision
Then getDecoderInfos will return the alternative types.
Issue: google/ExoPlayer#9794
PiperOrigin-RevId: 476356223
The ClearKey CDM will attach an 'invalid' URL in `KeyRequest` objects,
when the documentation states this should be an empty string if a
default URL is not known.
#minor-release
PiperOrigin-RevId: 476113513
If the back buffer is using too much memory, there is a risk
playback could get stuck because LoadControl refuses to load
further data. This eventually results in a stuck-buffering
playback error.
We can detect this case, clear the back buffer and then ask
the LoadControl again to avoid failing playback in such a case.
PiperOrigin-RevId: 472679797
The stream offset is used to calculate the presentation time of
a metadata object when reading and later when playing, to calculate
the current presentation time to decide whether to send the metadata
to the output.
Accordingly, the presentation time of a pending metadata that has been
calculated with a given offset needs to be recalculated when the
stream offset changes.
#minor-release
PiperOrigin-RevId: 472499943
* Non-standard parameter comment; prefer `/* paramName= */ arg`
(see http://go/bugpattern/ParameterComment) (3 times)
This CL looks good? Just LGTM and Approve it!
This CL doesn’t look good? This is what you can do:
* Revert this CL, by replying "REVERT: <provide reason>"
* File a bug under go/error-prone-bug for category ErrorProneStyle if there's an issue with the CL content.
* File a bug under go/rosie-bug if there's an issue with how the CL was managed.
* Revert this CL and not get a CL that cleans up these paths in the future by
replying "BLOCKLIST: <provide reason>". This is not reversible! We recommend to
opt out the respective paths in your CL Robot configuration instead:
go/clrobot-opt-out.
This CL was generated by CL Robot - a tool that cleans up code findings
(go/clrobot). The affected code paths have been enabled for CL Robot in //depot/google3/java/com/google/android/libraries/media/METADATA which is reachable following include_presubmits from //depot/google3/third_party/java_src/android_libs/media/METADATA.
Anything wrong with the signup? File a bug at go/clrobot-bug.
#codehealth
Tested:
Local presubmit tests passed.
PiperOrigin-RevId: 472254253
* Non-standard parameter comment; prefer `/* paramName= */ arg`
(see http://go/bugpattern/ParameterComment) (19 times)
This CL looks good? Just LGTM and Approve it!
This CL doesn’t look good? This is what you can do:
* Revert this CL, by replying "REVERT: <provide reason>"
* File a bug under go/error-prone-bug for category ErrorProneStyle if there's an issue with the CL content.
* File a bug under go/rosie-bug if there's an issue with how the CL was managed.
* Revert this CL and not get a CL that cleans up these paths in the future by
replying "BLOCKLIST: <provide reason>". This is not reversible! We recommend to
opt out the respective paths in your CL Robot configuration instead:
go/clrobot-opt-out.
This CL was generated by CL Robot - a tool that cleans up code findings
(go/clrobot). The affected code paths have been enabled for CL Robot in //depot/google3/java/com/google/android/libraries/media/METADATA which is reachable following include_presubmits from //depot/google3/third_party/java_src/android_libs/media/METADATA.
Anything wrong with the signup? File a bug at go/clrobot-bug.
#codehealth
Tested:
Local presubmit tests passed.
PiperOrigin-RevId: 471022923
We create an empty CueGroup in many places as default or
where none is needed. Instead, we can define a constant
for this purpose and reuse it.
PiperOrigin-RevId: 467944841
Increase the estimated max sample size for HEVC by 2x, and set a minimum
size of 2MB. The 2MB will be applied for resolutions up to 1080p, after
which the new calculation takes effect. This is in par with the
platform's HEVC software decoder.
PiperOrigin-RevId: 467641494
Adds a new event to AudioOffloadListener to get the offload state of the track, which indicates when software decoding is taking place.
PiperOrigin-RevId: 465264362
Avoids disabling Offload on a write error, and instead relies on this being disabled on the AudioTrack init. It will no longer recover by disabling offload.
PiperOrigin-RevId: 465248917
* Sets KEY_HDR_STATIC_INFO from MediaFormat in the DefaultCodec.
* Adds checks in mediaparser to ensure color space, range, and transfer are valid
values.
PiperOrigin-RevId: 463921325
Despite unregistering the callback and clearing pending Handler
messages, the callback may still receive pending calls if they
are already triggered by the AudioTrack. Instead of asserting
that the track is correct, we should gracefully ignore stale
events.
PiperOrigin-RevId: 463851393
This will help developers self-diagnose issues like Issue: google/ExoPlayer#10392
where the NPE occurs far from the original null value because a field
gets assigned to null.
This change aims to ensure that every stable method on Player,
ExoPlayer and ExoPlayer.Builder that takes a non-null type will fail
with an NPE before returning.
#minor-release
PiperOrigin-RevId: 461846580
The call doesn't currently reset the already loaded suppliers and
factories. Also fix the supplier loading code to use a local copy
of the current dataSourceFactory to avoid leaking an updated
instance to a later invocation.
Issue: androidx/media#116
#minor-release
PiperOrigin-RevId: 460721541
We currently start a simple Thread to release AudioTracks
asynchronously. If many AudioTracks are released at the same
time, this may lead to OOM situations because we attempt to
create multiple new threads.
This can be improved by using a shared SingleThreadExecutor.
In the simple case of one simmultaneous release, it's exactly
the same behavior as before: create a thread and release it
as soon as it's done. For multiple simultanous releases we
get the advantage of sharing a single thread to avoid creating
more than one at the same time.
Issue: google/ExoPlayer#10057
PiperOrigin-RevId: 460698942
Some calls to handleBuffer return false while a previous
flush is still handled in the background.
Fix this by either asserting the method returns true if
we don't expect any delay, or calling it repeatedly until
it returns true (within a timeout).
PiperOrigin-RevId: 460474419
I don't think it's useful to keep these in numerical order, it makes
more sense to keep them grouped into a 'logical' ordering.
#minor-release
PiperOrigin-RevId: 460453464
We wait until a previous AudioTrack has been released before
creating a new one. This is currently done with a thread
block operation, which may cause ANRs in the extreme case
when someone attempts to release the player while this is
still blocked.
The problem can be avoided by just returning false from
DefaultAudioSink.handleBuffer to try again until the previous
AudioTrack is released.
Reproduction steps to force the issue:
1. Add Thread.sleep(10000); to the AudioTrack release thread.
2. Add this to the demo app:
private int positionMs = 0;
Handler handler = new Handler();
handler.post(new Runnable() {
@Override
public void run() {
player.seekTo(positionMs++);
if (positionMs == 10) {
player.release();
} else {
handler.postDelayed(this, 1000);
}
}
3. Observe Player release timeout exception.
These steps can't be easily captured in a unit test as we can't
artifically delay the AudioTrack release from the test.
Issue: google/ExoPlayer#10057
PiperOrigin-RevId: 459468912
ProgressiveMediaPeriod loads all available tracks into SampleStreams
(because it needs to read the data anyway and it allows easy activation
of tracks without reloading). However, the SampleStreams for disabled
tracks are not read and no one if waiting for them.
The buffered position is used for user-visible state (e.g. in the UI)
and to check how much data is already buffered to decide when to stop
buffering (using LoadControl). Both values benefit from only
using the actually enabled tracks to better reflect what is available
for playback at the moment.
Issue:Issue: google/ExoPlayer#10361
PiperOrigin-RevId: 458475038
Previously two timelines that differed only in shuffle order were
considered equal, which resulted in no call to
Player.Listener.onTimelineChanged when calling
ExoPlayer.setShuffleOrder. This in turn resulted in no call to
MediaControllerCompat.Callback.onQueueChanged.
Also make a small fix inside ExoPlayerImpl.setShuffleOrder, to ensure
that the new shuffle order is used when constructing the masked
timeline.
Issue: google/ExoPlayer#9889
#minor-release
PiperOrigin-RevId: 457703727
NoUidTimeline still exists as a private detail of TestUtil, but it no
longer extends ForwardingTimeline because the interactions are quite
hard to reason about.
#minor-release
PiperOrigin-RevId: 457703593
1. The offloadSchedulingEnabled value doesn't need to be in
PlaybackInfo because it's never updated in EPII.
2. The sleepingForOffload value in EPII wasn't updated explicitly
(just via the return value of a method). It was also only
meant to be enabled while the player is actively playing, but
confusingly triggered from a path where the player may
theoretically be buffering as well.
3. The offload sleeping (=not scheduling doSomeWork) was interwoven
into the actual scheduling code making it slightly hard to follow.
This can be improved slightly by keeping the offload sleeping
decision and the scheduling separate.
PiperOrigin-RevId: 457427293
The offload sleeping stops as soon as a new DO_SOME_WORK message
is handled (because this indicates an expected change in rendering
and we want to stop sleeping until we know it's safe to do so).
Every exit path from doSomeWork needs to clear other pending
DO_SOME_WORK messages as these requests have already been handled by
the current method invocation. This currently doesn't happen from the
offload sleeping return path and a previously queued DO_SOME_WORK
message can immediately wake up the rendering loop again.
Fix this by moving the message removal to the beginning of the
doSomeWork method (as it prevents forgetting it in one of the
exit paths later).
PiperOrigin-RevId: 456259715
The default constructor is only allowed to be called on
API < 32 and the test should use the defined UNSET constant
to be API independent.
#minor-release
PiperOrigin-RevId: 454568893
`codecDrainAction` is set to `DRAIN_ACTION_NONE` in 3 places in
`MediaCodecRenderer`:
* The constructor (so there's no prior state to worry about)
* `updateDrmSessionV23()`: Where `mediaCrypto` is reconfigured based
on `sourceDrmSession` and `codecDrmSession` is also updated to
`sourceDrmSession`.
* `resetCodecStateForFlush()`: Where (before this change) the action
is unconditionally set back to `DRAIN_ACTION_NONE` and so any
required updated implied by
`DRAIN_ACTION_FLUSH_AND_UPDATE_DRM_SESSION` is not done.
This change ensures that `flushOrReleaseCodec()` handles
`DRAIN_ACTION_FLUSH_AND_UPDATE_DRM_SESSION` before calling .
This probably also resolves Issue: google/ExoPlayer#10274
#minor-release
PiperOrigin-RevId: 454114428
Transformer always enabled glAssertionsEnabled, so there should
be no functional change.
ExoPlayer previously disabled glAssertionsEnabled, so GlUtil logged
GlExceptions instead of throwing them. The GlExceptions are now
caught and logged by the callers so that there should also be no
functional change overall.
This change also replaces EGLSurfaceTexture#GlException with
GlUtil#GlException.
PiperOrigin-RevId: 453963741
The track selector will select multi-channel formats when those can be
spatialized, otherwise the selector will prefer stereo/mono audio
tracks. When the device supports audio spatialization (Android 12L+),
the DefaultTrackSelector will monitor for changes in the platform
Spatializer and trigger a new track selection upon a
Spatializer change event.
Devices with a `television` UI mode are excluded from audio channel
count constraints.
#minor-release
PiperOrigin-RevId: 453957269
Some Player implementations have no playlist capability but can still
set a MediaItem for playback. Examples are a MediaController connected
to a legacy MediaSession, ExoPlayer up to 2.12 or MediaPlayer.
To indicate this capability, we need an allowed command in addition
to COMMAND_CHANGE_MEDIA_ITEMS that just allows to set a single item
that replaces everything that is currently played.
#minor-release
PiperOrigin-RevId: 453879626
With HLS chunkless preparation, audio formats may have no value
for channel count. In this case, the DefaultAudioSink will either query
the platform for a supported channel count (API 29+) or assume a max
channel count based on the encoding spec in order to decide whether the
audio format can be played with audio passthrough.
Issue: google/ExoPlayer#10204
#minor-release
PiperOrigin-RevId: 453644548
The current setup with distinct, private `keyForField` implementations,
leaves open the (theoretical) possibility of a clash in the `Bundle`
keys used by the superclass and subclass. This change brings
consistency with our only other extensible `Bundleable` type
(`PlaybackException`).
#minor-release
PiperOrigin-RevId: 453385875
We generally nest the `Builder` for `Foo` inside `Foo`. In this case,
there's already a `DefaultTrackSelector.Parameters.Builder` type visible
to a developer, it just happens to be the 'common'
`TrackSelectorParameters.Builder`, so using it is a bit weird. For
example this code snippet doesn't compile because
`DefaultTrackSelector.Parameters.Builder#build()` returns
`TrackSelectionParameters`. This CL fixes that problem and the code
snippet now compiles.
```java
DefaultTrackSelector.Parameters params =
new DefaultTrackSelector.Parameters.Builder(context).build()
```
#minor-release
PiperOrigin-RevId: 453215702
Unconditionally sleep for offload, if the audio buffer is full.
Previously ExoPlayer would not sleep if the expected wake-up was
in 2s. This was to prevent underrun if the wake-up was delayed.
Experiments have shown that the wakup audio buffer is far more
than 2s (around 1min). Additionally,
the metric was incorrect because it measured both,
AudioTrack + DSP.
Finally, this metric was erroneous after a gapless transition,
when the head position would reset to 0 and thus the computed
delay until next wakeup was too large.
PiperOrigin-RevId: 451383701
*** Original commit ***
Rollback of 07302a23bd
*** Original commit ***
Remove `@Nullable` from `MediaSource.Factory` setters
The null-behaviour of these methods creates a minimization footgun,
because **any** call to these setters will prevent R8 from removing
the default implementation (even if it's never used by the app) - this
is because R8 can't tell the default imple...
***
PiperOrigin-RevId: 450453325
AudioTrack.setOffloadEndOfStream should be called after a track
has been buffered. Additionally, the AudioTrack must be playing.
It has been observed that for very short media (<1s), the AudioTrack
might not have started immediately after the read that buffered
the audio.
In such a situation, calling AudioTrack.setOffloadEndOfStream throws
and playback fails.
Avoid this failure by checking that the AudioTrack is playing before
calling setOffloadEndOfStream.
This means that very short gapless media will not be gapless, this was
deemed acceptable given that such very short media should be very rare
in offload.
PiperOrigin-RevId: 450431146
*** Original commit ***
Remove `@Nullable` from `MediaSource.Factory` setters
The null-behaviour of these methods creates a minimization footgun,
because **any** call to these setters will prevent R8 from removing
the default implementation (even if it's never used by the app) - this
is because R8 can't tell the default implementation is only used if the
parameter is `null`.
PiperOrigin-RevId: 450410833
The null-behaviour of these methods creates a minimization footgun,
because **any** call to these setters will prevent R8 from removing
the default implementation (even if it's never used by the app) - this
is because R8 can't tell the default implementation is only used if the
parameter is `null`.
PiperOrigin-RevId: 450386627
This detection relies on an unsupported workaround and may trigger
permission warnings in tools analyzing permission usage although
no permission is needed or requested by app code.
Given the majority of 5G-NSA playbacks are on API 31+ by now,
we can remove this path to avoid the permission confusion and the
unsupported detection workaround.
PiperOrigin-RevId: 450382586
This causes a bug where the forwarded selections are no longer
assumed equal and the child MediaPeriods will think they need
to reset streams even though the selection stayed the same.
Issue: Issue: google/ExoPlayer#10248
PiperOrigin-RevId: 449454038
We need to pass timestamp for the list of cues so we are defining a new class CueGroup which will store both cues and timestamp.
PiperOrigin-RevId: 449212054
Network type detection on these API levels couldn't be tested
yet because of a missing Robolectric feature. This was fixed by
the recent Robolectric upgrade and the restrictions can be removed.
This also requires to replicate the platform hack we rely on on
these API levels.
PiperOrigin-RevId: 448240431
The TrackSelector is released when the player is released. The
TrackSelector can be reused if TrackSelector.init() is called again.
PiperOrigin-RevId: 446439717
Some APIs from Android 12L were used either via reflection or
constants values were hard-coded. We can now use these APIs directly
since we upgraded the compile SDK version to 32.
PiperOrigin-RevId: 446167543
Overriding any methods of AnalyticsListener requires using the unstable
API. In future we can incrementally add AnalyticsListener methods to the
stable API.
PiperOrigin-RevId: 445420361