Adding a CHANGE_FRAME_RATE_STRATEGY_ALWAYS strategy is
omitted from this commit, since adding it is more complicated
than just plumbing it through and leaving everything else
unchanged. Specifically, VideoFrameReleaseTimeHelper would
need updating to behave differently when such a strategy is
enabled. It currently calls setFrameRate in cases such as
pausing, seeking and re-buffering, on the assumption that
changes to the underlying display refresh rate will only be
made if they can be done seamlessly. For a mode in which
this will not be the case, it makes more sense to stick to
the content frame-rate when these events occur. It may also
make sense to only use explicit content frame-rate values,
and not those inferred from individual frame timestamps.
Finally, for adaptive content containing a mix of frame-rates,
it makes sense to use the maximal frame-rate across all
variants, and to avoid calling setFrameRate on switches from
one variant to another.
Applications that know the frame-rate of their content can
set ExoPlayer's strategy to CHANGE_FRAME_RATE_STRATEGY_OFF and
then use setFrameRate directly on the output surface. Note that
this is likely to be a better option for apps than anything we
could implement in ExoPlayer, because the application layer
most likely knows the frame-rate of the content earlier than
ExoPlayer does (e.g., to perform the disruptive mode switch
at the same time as an activity transition).
Adding CHANGE_FRAME_RATE_STRATEGY_ALWAYS will be deferred
until there's clear demand for it. In the meantime, we'll
recommend the alternative approach above.
PiperOrigin-RevId: 389610965
Issue: #9254
#minor-release
We used to allow only alphanumerical characters in session id. The spec also
allows "$", "-", "_", ".", "+" (RFC2326 Sections 3.4 and 15.1).
PiperOrigin-RevId: 388873742
For audio-only playlists, when formats are communicated to the app with
AnalyticsListener.onDownstreamFormatChanged(), the passed MediaLoadData
do not indicate this is an audio track and therefore the
PlaybackStatsListener cannot derive audio format-related information.
This change sets the main SampleStreamWrappers track type to AUDIO, if
the master playlist contains only audio variants.
Issue: #9175
#minor-release
PiperOrigin-RevId: 388676060
This CL addresses the github issue [#8946](https://github.com/google/ExoPlayer/issues/8964). That issue requests support for `font-size` CSS property in WebVTT subtitle format. This CL:
* Adds support for `font-size` property by extending capabilities of WebVTT `CssParser`. Implementation of `font-size` property value parsing is based on the one in `TtmlDecoder`.
* Adds unit test along with test file containing WebVTT subtitles with all currently supported `font-size` units.
#minor-release
PiperOrigin-RevId: 388423859
Using all lower case RTSP headers is perfectly valid, as the spec mandates case
insensitively. However, some RTSP servers do not implement the RTSP spec
closely and does not recognize the lower case headers. This change aims
at using the header names as defined in the RTSP spec to maximize compatibility.
Issue: #9182
PiperOrigin-RevId: 386224566
Before this fix, if DefaultDrmSessionManager.release() was called while
there was at least one 'external' session reference still active (i.e.
session.referenceCount > 1) then the manager will release it's reference
immediately but when the session's reference count subsequently drops to
1 (due to external references being released) the manager will schedule
a task to release its internal reference *again*.
This change fixes the problem by only scheduling the timed release if
the manager is unreleased. This ensures that the internal references
are only released once.
Issue: #9193
#minor-release
PiperOrigin-RevId: 385580741
* Add release note for `RtspMediaSource.Factory.setTimeoutMs()`
* Remove mention of what we don't support (any such list is necessarily non-exhaustive)
* Remove markdown quote character ('>')
PiperOrigin-RevId: 385143574
This values won't be configurable from the UI anymore once the
DefaultControlDispatcher is removed.
They can be configured in the Player or by using a ForwardingPlayer.
PiperOrigin-RevId: 385113498
Issue: #9183
RFC2326 Section C.1.1 specifies that the URI to identify a track can be either
absolute (like rtsp://example.com/path) or relative (like "path"). Currently
we don't handle absolute URI, and this CL is to add the support.
Note though, we don't currently use the Content-Base or Content-Location
headers for the session URI.
PiperOrigin-RevId: 384649818
Also rename hasPrevious/Next to hasPrevious/NextWindow for consistency.
This makes it clearer what the difference between
seekToPrevious/NextWindow and seekToPrevious/Next is.
PiperOrigin-RevId: 384643373
MediaItem.mediaId used to default to the content URI, but this changed:
cc26a92e07
Before the mediaId change linked above, a playlist of different content
all with the same ad URI would play the ads for every item. After the
change the ad would only play once (because mediaId == "" for every
item, so they're all the same). This change restores roughly the
original behaviour by always considering both mediaId and the content
URI.
#minor-release
Issue: #9106
PiperOrigin-RevId: 382763618
The serialization scheme used here is custom, it doesn't need
to be compatible with emsg-v0 or emsg-v1 (since
97183ef558).
This means that C.TIME_UNSET will propagate correctly through the
serialization.
#minor-release
Issue: #9123
PiperOrigin-RevId: 382762873
Without this annotation it seems that `SimpleExoPlayer` effectively
'un-deprecates' the method, specifically:
* A usage of these methods isn't flagged by Android Studio if the
declared type is `SimpleExoPlayer` (up-casting to e.g.
`ExoPlayer.VideoComponent` results in the warning showing up).
* The `SimpleExoPlayer` javadoc doesn't mention this method is
deprecated:
https://exoplayer.dev/doc/reference/com/google/android/exoplayer2/SimpleExoPlayer.html#addVideoListener(com.google.android.exoplayer2.video.VideoListener)
* The Metalava API output for `SimpleExoPlayer` doesn't show these
methods as deprecated.
PiperOrigin-RevId: 382756174
Until now, we have stuck with the 3.12 long-term branch so as
to keep support for older API levels. However, this means that
the version we're using is 2.5 years old at this point. The
3.12 branch will stop receiving critical updates in December
2021.
Since use of the OkHttp extension is optional anyway, it seems
preferable to move to a modern version of OkHttp at this point.
PiperOrigin-RevId: 381465269
No-op change that adds the @FallbackType IntDef and changes the signature of getBlacklistDurationMsFor(LoadErrorInfo) to getExclusionDurationMsFor(@FallbackType, LoadErrorInfo).
PiperOrigin-RevId: 381075496
The problem occurs when the primary media playlist URL switches
from one whose latest snapshot has not yet got the ended tag, to
one whose latest snapshot already has the ended tag. In this case:
- We trigger a redundant load of the ended playlist.
- When the redundant load completes,
MediaPlaylistBundle.processLoadedPlaylist detects that the
playlist is unchanged from the one it already has, and so
doesn't call onPlaylistUpdated.
- PrimaryPlaylistListener.onPrimaryPlaylistRefreshed is never
called with the new primary. Hence the externally visible primary
is still the one that hasn't ended. HlsMediaSource therefore thinks
the event hasn't ended, which in turn prevents the player from
transitioning to the ended state.
This commit detects when the new primary already has the ended tag.
In this case, we call onPrimaryPlaylistRefreshed directly and remove
the unnecessary playlist load.
Issue: #9067
#minor-release
PiperOrigin-RevId: 380680532
The glitches were introduced in:
https://github.com/google/ExoPlayer/commit/6c31e34528
The problem is that Listener.onEvents is called in a later looper iteration
than the listener methods that were previously used. This created a gap on
the main thread between the UI component dispatching a seek operation to the
player, and onEvents being called to update the progress bar's position.
At the start of this gap the progress bar is rendering the new position,
but its position member variable is still set to the old position. If the
progress bar is re-drawn by another message on the main thread within the
gap, it will briefly show the old position until onEvents is called.
There are multiple possible fixes to this, and the best one is probably to
modify ListenerSet to remove the gap. That's high risk though, so for now we
fix the flicker by always updating the progress immediately after the seek
is dispatched, in addition to when onEvents is called.
Issue: #9049
#minor-release
PiperOrigin-RevId: 380678388
Also change to explicitly track the provisioning session, which makes
the code easier to reason about than always using the zero'th element
of the list.
PiperOrigin-RevId: 380181453
Note that this removes a workaround for malformed content, in which the
track_ID is set incorrectly. It's unclear there was sufficient reason to
implement that workaround, and so it's preferable to remove it, rather
than implementing the concept of unrecognized tracks, which would be
needed to keep it and to also fix this issue.
Issue: #9056
#minor-release
PiperOrigin-RevId: 379506261
`SurfaceTexture` provides a transform matrix with each buffer. Previously
gldemo ignored this but it is important to apply it to have the video render
properly.
The transformation matrix from the surface texture includes flipping so this
change removes the hard-coded flipping from `a_texcoord`.
Issue: #8992
#minor-release
PiperOrigin-RevId: 377271389
Add the `needsReconfiguration` API on the `MediaCodecAdapter` interface so that `MediaCodecRenderer` can reconfigure the `MediaCodec` in case a `MediaCodecAdapter` needs to be reconfigured immediately after being obtained from the `MediaCodecAdapter.Factory`.
PiperOrigin-RevId: 376944334
A renderer is disabled (without being reset) in two situations:
* When transitioning into a period that starts with a discontinuity
* When stopping the player with setForegroundMode(true)
Before this change the behaviour of `MediaCodecRenderer` when disabled
(but not reset) depended on whether the content being decoded had an
associated `DrmSession`:
* For content without an associated DRM session the MediaCodec instance
was kept alive.
* For content with an associated DRM session, the MediaCodec instance
was released. This was to prevent the DRM session from staying alive
and continuing to make license refresh network requests while the
player was stopped in 'foreground mode'.
This change removes the second bullet, and keeps MediaCodec instances
alive in both the secure and insecure case. This will result in the
DRM machinery making occasional license refresh network requests (at
a frequency defined by the license policy) while the player is stopped
and in 'foreground mode'. This network usage is considered to be a
'limited resource' as described by the `ExoPlayer#setForegroundMode`
javadoc.
This means that switches between secure content (or between secure and
clear content when `MediaItem.drmConfiguration.sessionForClearTypes`
indicates a secure decoder should be used for clear content) should
keep the same video decoder, thus avoiding the 'black flash' that occurs
on some devices when switching the surface away from a secure decoder.
Issue: #8842
#minor-release
PiperOrigin-RevId: 376825501
This change introduces a third 'state' for `DefaultDrmSessionManager`:
It's been fully released (prepareCount == 0) but at least one of its
sessions is still active.
In this state new acquisitions are rejected (`(pre)acquireSession()`
calls will fail) but the machinery to support the existing sessions
(ExoMediaDrm and MediaDrmHandler) is kept until they're all released.
This change will allow us to remove the TODO in MediaCodecRenderer
that resolves Issue: #8842.
PiperOrigin-RevId: 376193952
Many of the setters are ignored unless others are set - this change:
* Lists these conditions exhaustively.
* Uses more concise language to avoid overshadowing the main details
of what the setter sets.
* Tweaks the language from 'is ignored' to 'shouldn't be called', to
open up the future possibility of throwing an error if these are
called without the 'required' setter also being present (see
Issue: #8957).
#minor-release
PiperOrigin-RevId: 376162385
Authentication sequence in RTSP:
- Server replies "Unauthorized" to our DESCRIBE request, and includes the
necessary information (i.e. realm, digest nonce, etc) in WWW-Authenticate
header
- After `RtspClient` receives the response, we
- Parse the WWW-Authenticate header, stores the auth info. The info is saved
for all further RTSP requests (that all need to carry authorization headers)
- send the second DESCRIBE request with the Authorization header.
#minor-release
PiperOrigin-RevId: 376116302
We need to avoid reading and skipping into preload chunks as they
may need to be discarded. The current code iterates over all chunks,
but this can be simplified by just checking the last chunk knowing
that the preload chunk must always be the last one.
As a result, we avoid calling getFirstSampleIndex on all chunks. This
is a bug since the method is not allowed to be called for chunks
that have been spliced in. This still leaves the smaller issue of
potentially calling this method for spliced-in preload chunks, which
will be solved separately.
Issue: #8937
#minor-release
PiperOrigin-RevId: 375053638
Gradle warns against passing a relative path to `new File(String)`:
https://docs.gradle.org/current/userguide/working_with_files.html#sec:single_file_paths
This change fixes all usages of `exoplayerRoot` to pass it to Gradle's
`Project.file()` first, which returns an absolute `File`.
To reproduce the problem in Issue: #8927:
1. Checkout ExoPlayer git project, to e.g. `~/ExoPlayer/exoplayer-git`
2. Create a new Android Studio project in e.g. `~/AndroidStudioProjects/exoplayer-test`
3. Edit the new project's `settings.gradle` file as described in
https://github.com/google/ExoPlayer/blob/release-v2/README.md
using a relative path for `exoplayerRoot`:
```
gradle.ext.exoplayerRoot = '../../ExoPlayer/exoplayer-git'
```
4. In a shell:
```bash
$ cd ~/AndroidStudioProjects/exoplayer-test/app
$ ../gradlew build
```
(Step 4 is important, it seems running `./gradlew` from the project root
doesn't trigger the relative path problem)
This change fixes the problem, and also works with `exoplayerRoot` as a
`File` or `Path` object. `String`, `File` and `Path` all work with relative or
absolute paths:
```
gradle.ext.exoplayerRoot = '/home/ibaker/ExoPlayer/exoplayer-git'
gradle.ext.exoplayerRoot = '../../ExoPlayer/exoplayer-git'
gradle.ext.exoplayerRoot = new File('/home/ibaker/ExoPlayer/exoplayer-git')
gradle.ext.exoplayerRoot = new File('../../ExoPlayer/exoplayer-git')
gradle.ext.exoplayerRoot = Paths.get('/home/ibaker/ExoPlayer/exoplayer-git')
gradle.ext.exoplayerRoot = Paths.get('../../ExoPlayer/exoplayer-git')
```
Note: The Path versions above require importing `java.nio.file.Paths`
and changing the `apply from:` line in the project's settings.gradle
file to something like:
```
apply from: file(gradle.ext.exoplayerRoot.resolve('core_settings.gradle'))
```
It's assumed that a project wanting to pass a `Path` will make these
changes.
Issue: #8927
PiperOrigin-RevId: 374421627
In Android 12 mutability flags have to be set on PendingIntents. If they are not, and the app targets Android 12, then the app will be crashed by the system.
PiperOrigin-RevId: 373427591
Content after ad groups currently always resumes at the ad break position (unless
overridden by a seek or similar). In some cases, media inserting ads wants to
specify an offset after the ad group at which playback should resume. A common
example is a live stream that inserts an ad and then wants to continue streaming
at the current live edge.
Support this use case by allowing ad groups to specify a content resume offset
and making sure that the content start position after the ad group uses this offset.
PiperOrigin-RevId: 373393807
The player already supports changing durations of periods and ads.
The only thing not yet supported is a change in ad break positions
which changes the duration of clipped content ending in an ad break.
Adding support for this requires updating the end position in
MediaPeriodInfo and changing the clip end position of the respective
ClippingMediaPeriod.
Issue: #5067
PiperOrigin-RevId: 373139724
All `add*Listener` and `add*Output` methods are
deprecated in favor of `addListener`.
As for the class themselves `VideoListener` and
`AudioListener` are not used internaly by ExoPlayer,
`VideoRendererEventListener`
and `AudioRendererEventListener` are use in their
place.
As a result `VideoListener` and `AudioListener`
can be deprecated in favor `Listener`.
On the other hand `TextOutput` and `MedataOutput`
are used both in the player interface and internally in
renderers.
This means that those class can't be deprecated.
There usage in the public interface are indirectly
deprecated as their is no way to use them without
using the deprecated `add*Output`.
Thus it's not an issue that the class themselves are
not deprecated.
#minor-release
PiperOrigin-RevId: 371318268
Imported from GitHub PR https://github.com/google/ExoPlayer/pull/8858
Fix bug in text alignment inheritance where child does not correctly inherit ancestor's setting
@icbaker
Merge 70eb4bceb73b3f07e2f8d545b4fa7961189ac52a into 45616f916b
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/ExoPlayer/pull/8877 from dlafayet:multirowalign-cue d942b50a40525fea5d11b35a33d3bbc512550960
PiperOrigin-RevId: 371306966
Move VideoSize in the common module and have the Player return it.
`Listener` and `AnalyticsListener` `onVideoSizeChanged` are updated
with the old method deprecated.
`VideoRendererEventListener.onVideoSizeChanged` was also migrated to
`VideoSize` but the old method is removed, not deprecated.
This is because:
- apps calling/listening to this method is a rare and niche use-case.
- it would introduce hard to diagnostic issues where if only the caller
or the callee is updated to use the new method, the event will be lost.
This doesn't occur with the other 2 listeners as the caller is always
in ExoPlayer library and was updated to call both the old and new methods.
VideoSize is used everywhere except in `Format` as this would lead to
too much refactoring and backward compatibility breakage for little gain.
#minor-release
PiperOrigin-RevId: 371087419
Add method getAvailableCommands() in Player interface to return
the available commands. Method isCommandAvailable() moved to
BasePlayer since it can be implelented by calling
getAvailableCommands().
PiperOrigin-RevId: 370059328
A subsequent change will make the UI module access
SphericalGLSurfaceView and VideoDecoderGLSurfaceView
using reflection, now we're at the point where we only
need to reflect the constructors.
PiperOrigin-RevId: 369630102
The protected visibility causes problems in Kotlin (Issue: #8830) and
also prevents a subclass of AdaptiveTrackSelection.Factory that isn't
nested inside a subclass of AdaptiveTrackSelection (in both Java and
Kotlin).
#minor-release
PiperOrigin-RevId: 369468841
The original cl has been fixed by not implementing
VideoListener but Player.Listener in
StyledPlayerView.
VideoFrameMetadataListener and CameraMotionListener are still part
of the Player interface as a good way to break the UI dependency
on them has not yet been finalised.
PiperOrigin-RevId: 369417682
This change moves the responsibility of creating, configuring and starting the MediaCodec from the MediaCodecRender to the MediaCodecAdapter.Factory.
This move allows ExoPlayer's client to decide how and when codecs are created and/or reused.
To allow the move, this CL replaces MediaCodecRenderer.ConfigureCodec with MediaCodecRenderer.getCodecConfiguration
PiperOrigin-RevId: 369273887
*** Original commit ***
Move VideoComponent in ExoPlayer
VideoFrameMetadataListener and CameraMotionListener are still part
of the Player interface as a good way to break the UI dependency
on them has not yet been finalised.
***
PiperOrigin-RevId: 369194309
VideoFrameMetadataListener and CameraMotionListener are still part
of the Player interface as a good way to break the UI dependency
on them has not yet been finalised.
PiperOrigin-RevId: 368863829
Other properties of SphericalGLSurfaceView (e.g., setDefaultStereoMode)
are not plumbed through the PlayerView components, and it doesn't scale
to plumb through all properties of all of the SurfaceView types.
Applications can instead do:
```
((SphericalGLSurfaceView) playerView.getVideoSurfaceView())
.setUseSensorRotation(useSensorRotation);
```
PiperOrigin-RevId: 368196537
This brings in another fix for `NullPointerExceptions` within `WebView` callbacks in the IMA SDK, related to companion ads.
Issue: #8447
#minor-release
PiperOrigin-RevId: 367591047
- Take centerControls padding into account to prevent switching to
minimal mode too soon
- Disable clipping to padding to avoid the edges of controls from
being clipped as the view gets smaller
Issue: #8763
PiperOrigin-RevId: 366966298
This ensures BUFFER_FLAG_DECODE_ONLY is set on samples that are
before the playback start position, in the case that the queue
is created after the start position is set.
#minor-release
PiperOrigin-RevId: 366249188
When playing TrueHD streams, it's possible that the first decoded
buffer is empty, and that the channel count and sample rate are
still unknown. To correct for this, defer determining the format
until a buffer that will actually be output from the decoder has
been obtained, and only then query the channel count and sample
rate.
Issue: #8616
#minor-release
PiperOrigin-RevId: 366246245
The exo_controls_background view is supposed to fill its parent,
and so previously used match_parent to do this. However, if the
parent uses wrap_content for its own dimensions, the constraints
being specified become somewhat ambiguous. The parent is supposed
to be sizing itself to wrap its children, and one of the children
is supposed to be sizing itself to match the parent.
Intuitively for this case, you'd hope that the layout logic would
size the parent to wrap its other children, and that the
match_parent child would then fill the parent with its determined
size. That's not what happens, and instead the parent ends up
expanding to occupy all of the space available to it.
This commit sets the exo_controls_background view's dimensions
to be 0dp in the layout, to stop it from influencing the size of
the parent. It's then expanded to fill the parent in code.
Issue: #8726
#minor-release
PiperOrigin-RevId: 364868301
Null was an alias for DEFAULT. Remove this for nullness
safety in the API.
The ExoPlayer implementation still checks for null and
replaces it by DEFAULT, so this is ABI compatible.
PiperOrigin-RevId: 364370017
This change fixes playback of playlists where segments have the
extension and Content-Type of JPEG pictures (although in reality)
they are transport streams. File inferrence before this change will
cause an exception when assuming the inferred file type is one of
the allowed HLS containers.
#minor-release
Issue: #8733
PiperOrigin-RevId: 363641277
This makes HLS playback less liable to become stuck if discontinuity
tags are inserted at different times across media playlists.
Issue: #8700
Issue: #8372
PiperOrigin-RevId: 362903428
According to the spec (section 8.4.2), high numeric values represent low
priorities, so we need to flip this sort.
Issue: #8704
#minor-release
PiperOrigin-RevId: 362558370
`ImaAdsLoader` clears its `AdPlaybackState` when it's released but this could
cause `AdsMediaSource` to look up information in the ad playback state that is
no longer in bounds.
Issue: #8693
#minor-release
PiperOrigin-RevId: 362556286
Adds a new Listener that extends all other listener.
This is part of the component flattening goal.
After components have been flattened in Player,
and clients transitioned, existing listeners will be deprecated.
PiperOrigin-RevId: 362287507
In a period transition we pass the start time of the next period, for
the final period we pass the duration of the period or timeline, if
known.
This means sideloaded subtitles now respect the end point of
ClippingMediaSource and ensures that content subtitles aren't
incorrectly displayed over mid-roll ads.
When transitioning back into the subtitled content the subtitles still
appear slightly before the video transitions, meaning the first subtitle
of the content is shown with the last few frames of the ad. Resolving
this in a way that doesn't break anything else requires a deeper
investigation.
Issue: #5317
Issue: #8456
#minor-release
PiperOrigin-RevId: 361797118
MaskingMediaSource needs to resolve the prepare position set for a MaskingPeriod
while the source was still unprepared to the first actual prepare position.
It currently assumes that the period-window offset and the default position is
zero. This assumption is correct when a PlaceholderTimeline is used, but it
may not be true if the real timeline is already known (e.g. when re-preparing
a live stream after a playback error).
Fix this by using the known timeline at the time of the preparation.
Also:
- Update a test that should have caught this to use lazy re-preparation.
- Change the demo app code to use the recommended way to restart playback
after a BehindLiveWindowException.
Issue: #8675
PiperOrigin-RevId: 361604191
- Avoid having two onPositionDiscontinuity events (seek and transition)
sent after a seek to another media item.
- Avoid triggering an onPositionDiscontinuity event after a timeline
change.
#minor-release
PiperOrigin-RevId: 361092914
Latest LTS version is better than latest stable version because it will
be supported for longer.
#minor-release
Issue:#8581
PiperOrigin-RevId: 359467482
Allow offload of gapless content even if gapless offload is not known to be supported by the device.
This is not exposed in the high level DefaultRendererFactory as most
users are expected to prefer fidelity to power savings.
PiperOrigin-RevId: 359336407
The concept of Renderers is not needed in the
Player interface. Move it to ExoPlayer.
This should not break most users as they use SimpleExoPlayer.
PiperOrigin-RevId: 359220977
- Ensure consistency between (Styled)PlayerControlView,
PlayerNotificationManager, TimelineQueueNavigator and
DefaultControlDispatcher.
- Handle the case where a live stream has ended when enabling previous
and next actions (window.isLive() is true and window.isDynamic is
false in that case)
#minor-release
PiperOrigin-RevId: 359063793
- If DataSource.close fails then it's unknown whether the underlying file was
written to the cache. We should assume that it has not been.
- Always re-query cachedBytes at the start of CacheWriter.cache, since its
current value may be incorrect if a previous failure was the result of a
file not being written to the cache.
PiperOrigin-RevId: 359039109
When we add DRM pre-acquire support to SampleQueue, we'll dispatch
twice the number of acquire and release events. This is slightly
confusing, since there's the same number of
DrmSessionManager#acquireSession() calls.
We can mitigate this by only dispatching each acquire and release
event to at most one EventDispatcher.
This also changes the events fired when playing a stream with both audio
and video encrypted with the same keys (even without pre-acquisition).
Before: The EventDispatcher would see 2 aquires, 1 key load and 2
release events.
After: The EventDispatcher will see 1 acquire, 1 key load and 1 release.
PiperOrigin-RevId: 358804502
This is preferable to just logging to LogCat so that listeners can
report this to analytics systems if required.
Issue: #6384
PiperOrigin-RevId: 357906079
`ImaAdsLoader` will preload the first ad of a subsequent media item, but the
preloaded ad might not actually play because the user could seek to a non-zero
position in that media item (which could trigger playback of a midroll, not the
preroll). In this case, playback would get stuck because the midroll ad
expected to play after the seek would never load, because the IMA SDK expected
the preroll to play first.
Fix this behavior by discarding the preloaded ad break. If there isn't a seek,
the transition to the next media item is still seamless.
#minor-release
PiperOrigin-RevId: 357682510
Previously it was safe to query the first period in the timeline, but
now we support using the ads loader in concatenations we need to use
the current period index instead.
#minor-release
PiperOrigin-RevId: 357578003
The available end time was accidentally substracted by the start time
of the last period.
To avoid similar time reference confusion in the future, also renaming
many variables and methods to clearly reflect the time reference point.
And to avoid constant conversion, the processManifest method also
attempts to converge to time relative to the start of the window as
quickly as possible.
Issue: #8537
PiperOrigin-RevId: 357001624
If keepalive is disabled the existing code over-eagerly releases
DrmSession instances. This is arguably OK since a (Default)DrmSession
should be released before its (Default)Manager is released
(since the underlying MediaDrm instance might be released when the
manager is released). And if all sessions are released before the
manager is released then `sessions` is empty, so the loop is a no-op.
Issue: #8576
#minor-release
PiperOrigin-RevId: 356955308
The `DrmConfiguration.sessionForClearTypes` property is often used
to ensure a secure decoder is used for clear ads played in encrypted
content. This is because some devices show black frames when switching
decoders.
Before this change the DRM config isn't propagated down when
constructing the ad media source, meaning
`DrmSessionManager.DRM_UNSUPPORTED` is always used, which will
cause playback to switch from secure to clear decoder when transitioning
to an ad break (ignoring the MediaItem `sessionForClearTypes` option.
Issue: #8568
#minor-release
PiperOrigin-RevId: 356951124
Without this a new manager is instantiated for every item in a playlist,
meaning the impact of caching improvements to DefaultDrmSessionManager
are reduced (since the cache doesn't persist across playlist items).
With this change, playlists of items with identical DRM config will use
the same manager instance (and thus share existing sessions).
Issue: #8523
#minor-release
PiperOrigin-RevId: 356690852
Also allow the player's prepared ad media period durations array to exceed the
length of the loaded ad URIs array, as it's possible for the player to buffer
an ad media period fully at the point where it's known that an ad is coming up
but its URI is still unknown.
#minor-release
PiperOrigin-RevId: 356249284
Before, the level was set to null in this case.
MediaCodecUtil.getCodecProfileAndLevel() was therefore returning null
and the fallback to AVC/HEVC was not enabled in MediaCodecVideoRenderer.
Issue:#8530
#minor-release
PiperOrigin-RevId: 355574499
* Move cherrypicked changes from dev-v2 to 2.13.0
* Use a bulleted list instead of comma-separated.
* Standardise everything into present, imperative sentences.
* Remove a couple of mixed-font words (I left cases with a separating
apostrophe, as these seemed visually clearer).
* Merge multiple issue links into a single set of parentheses.
#minor-release
PiperOrigin-RevId: 355180143
Without this no error is currently logged or propagated to EventLogger.
The propagation doesn't happen because
MergingMediaSource.ForwardingEventListener only propagates events
originating from the "main" source in the merge:
<unknown commit>
#minor-release
PiperOrigin-RevId: 354902467
- Fix comparison between a byte and 0xFF to avoid conversion of 0xFF to
byte and to int again (due to numeric promotion).
- Fix addition of int and byte with most significant bit set. The byte
was incorrectly promoted to an int negative value.
Issue:#8496
#minor-release
PiperOrigin-RevId: 353865751
`TrackSelection` had mutation methods which were to be called only
internally by ExoPlayer components but were exposed in the
public `Player` interface.
The mutation methods have been moved out of `TrackSelection`
to a new class `ExoTrackSelection`.
Current track related read-only method have also been moved out,
because they are actually something quite unclear.
Even for a single item playlist, it's the track being buffered rather
than the track being played, which is unclear.
But when you have a playlist it starts to get really confusing,
because if the next item is being buffered, then it's actually
the last track to be buffered in the currently playing item.
As a final aside, the implementations don't do proper thread synchronization
to ensure visibility of updated state by the calling thread.
Exposing those mutable methods in the public `Player` interface
was problematic because they leaking internal concepts of `ExoPlayer`.
This is also required to minimize the `Player` interface for long term
stability.
`ExoTrackSelection` is a subclass of `TrackSelection`.
This is not ideal as an `TrackSelection` implementation could
break the current immutability.
This was done in order for this refactor to be simpler.
A future patch will fully split the two classes.
All `MediaPeriod` and `Sources` had to be updated to use the new
`TrackSelection` dynamic aspect class name.
An alternative would have been to break ExoPlayer's public API, keeping
`TrackSelection` as the dynamic aspect name, and calling the public static
aspect class `TrackSelectionState` or similar.
Nevertheless, while it would have impacted less files, it would have
many more small apps and casual users of ExoPlayer.
#player-to-common
PiperOrigin-RevId: 353637924
`ImaAdsLoader` only loads ad media URLs once playback of the preceding ad (if
any) has started, and this behavior is likely to be similar for other ad loader
implementations due to limits on how long before an ad plays it is meant to be
loaded. This is problematic for very short ads followed by an ad because the ad
will load to the end but load control may not allow playback to start due to
the total buffered duration being low.
Fix this by allowing playback to start regardless of load control if we are
waiting for an ad media period to prepare.
An alternative fix would be to fake the ad progress in the `ImaAdsLoader` to
trigger loading the next ad, but this would only allow one ad to load ahead (so
the problem would remain for two short ads in a row followed by another ad).
Issue: #8492
PiperOrigin-RevId: 353600088
This ensures the message devilery is governed by the clock.
Also replace setting a Handler with a Looper to facilititate this
change.
PiperOrigin-RevId: 353019729
The IMA SDK currently notifies `CONTENT_RESUME_REQUESTED` then
`CONTENT_PAUSE_REQUESTED` quickly afterwards when playing an ad for an initial
seek. This triggered the logic to skip VPAID ads added for Issue: #7832,
causing the ad to be skipped.
This change reverts the fix for that issue and extends the ad preload timeout
logic to cover the case of an initial seek as well. Incompatible VPAID ads will
still be skipped but only after the preload delay (this seems fine given that
they are documented not to be supported, and we are just making the failure
mode less bad on a best-effort basis!).
Issue: #8428
Issue: #7832
PiperOrigin-RevId: 353011270
This prevents trying to post the response to possibly dead threads,
which causes an IllegalStateException to be logged.
Issue: #8328
PiperOrigin-RevId: 352388155
- Once the ability to add debug listeners is removed, analyticsCollector
is the only component that needs to receive the events. Hence it is
called directly.
- It seemed less confusing to do the same thing for (non-debug) video and
audio events, and to have AnalyticsCollector no longer implement
VideoListener and AudioListener directly. This clears up confusion that
arises as a result of the debug and non-debug interfaces defining the
same methods in some cases, and having to be careful not to end up
calling the corresponding AnalyticsCollector method twice.
PiperOrigin-RevId: 351835491