This allows MediaSources to accept MediaItem updates after creation.
This CL adds the handling and plumbing logic in `ExoPlayerImpl`,
`ExoPlayerImplInternal`, `MediaSourceList` and `MaskingMediaSource`.
It also updates all forwarding/wrapping sources to forward these calls
to their wrapped instance.
The actual functionality is only added to `FakeMediaSource` instances in
tests so far.
PiperOrigin-RevId: 545450210
We introduced truncation to 32 chars in <unknown commit>
and included indent and offset in the calculation. I think this is
technically correct, but it causes problems with the content in
Issue: google/ExoPlayer#11019 and it doesn't seem a problem to only truncate actual
cue text (i.e. ignore offset and indent).
#minor-release
PiperOrigin-RevId: 544677965
Auto-resume playback when the removal of playback suppression due to unsuitable output is conveyed via change in playback suppression to Player.PLAYBACK_SUPPRESSION_REASON_NONE within a configurable timeout defaulting to 5 minutes.
PiperOrigin-RevId: 544411987
Instead of playing or pausing itself, the ExoPlayer implementation should only update the playback suppression reason as and when audio outputs are added or removed dynamically.
PiperOrigin-RevId: 544379033
*** Original commit ***
Mark output sample as decode-only based on start time
We currently do the same check on the input timestamps and
expect the output timestamps to match. Some codecs produce
samples with modified timestamps and the logic is a lot safer
when the comparison with the start time is done on the output
side of the codec.
Issue: google/ExoPlayer#11000
***
PiperOrigin-RevId: 543379665
This change uses this new method everywhere we currently `instanceof`
check an `Extractor` directly. This allows us to introduce
wrapping/delegating `Extractor` instances - because the `instanceof`
checks will continue to operate on the underlying instance.
HLS is a slightly different case, because it directly re-instantiates
`Extractor` instances, which is not compatible with an arbitrary
wrapping structure. Luckily the only `Extractor` instances that HLS
re-instantiates do not support muxed subtitles, so won't be wrapped
in the first place (although future changes might use the
delegating-`Extractor` pattern for other purposes, which might affect
HLS).
PiperOrigin-RevId: 542550928
Devices pre-API 33 are not able to comprehend the position reset that occurs by the HAL in offloaded gapless track transitions.
PiperOrigin-RevId: 542503662
Some events may arrive after the playlist is cleared (e.g. load
cancellation). In this case, the DefaultPlaybackSessionManager may
create a new session for the already removed item.
We already have checks in place that ignore events with old
windowSequenceNumbers, but these checks only work if the current
session is set (i.e. the playlist is non-empty). The fix is to add
the same check for empty playlists by keeping note of the last
removed window sequence number.
PiperOrigin-RevId: 541870812
FakeClock currently doesn't work well with Espresso and Compose UI
tests because view interactions in both frameworks intentionally idle
the main looper to handle pending UI effects. However, this also
advances playback progress even though we want to deterministically
trigger progress from the test itself.
To solve this problem, we can detect the idling Robolectric call and
postpone any further updates until we leave this state.
PiperOrigin-RevId: 541831050
Add a Wear OS specific implementation of 'Player.Listener' to help resolving the playback suppression due to unsuitable output by launching a system media output switcher dialog.
PiperOrigin-RevId: 541698125
The APIs /related fields for playback suppression due to unsuitable output should be renamed from '..SuppressPlaybackWhenNoSuitableOutputAvailable' to '..SuppressPlaybackOnUnsuitableOutput'
PiperOrigin-RevId: 540555715
The existing NullableType has been deprecated 5 years ago and causes
crashes in Kotlin apps because Kotlin doesn't recognize this annotation
as a nullable type annotation.
While we can't align on a single @Nullable annotation yet, we can at
least replace this one by JSR305's @Nonnull(MAYBE) as it fulfils all
requirements, including full Kotlin compatiblity. To avoid the
cumbersome name, we can redefine it as our own @NullableType
annotation. (We can't use @Nullable to avoid name clashes with the main
@Nullable annotation from AndroidX)
Issue: google/ExoPlayer#6792
PiperOrigin-RevId: 540497469
We currently do the same check on the input timestamps and
expect the output timestamps to match. Some codecs produce
samples with modified timestamps and the logic is a lot safer
when the comparison with the start time is done on the output
side of the codec.
Issue: google/ExoPlayer#11000
PiperOrigin-RevId: 540228209
With playback suppression in place, the devices can be added when the playback on ExoPlayer is in the suppression state. Also, it is quite possible that a suitable audio output device on which playback is ongoing gets removed requiring the Player to pause the playback. These requirements can be fullfilled using AudioDeviceCallbacks which has been implemented with this change.
PiperOrigin-RevId: 539559193
Add `HlsMediaSource.Factory.setTimestampAdjusterInitializationTimeoutMs(long)` to set the timeout for the loading thread to wait for the `TimestampAdjuster` to initialize. If the initialization doesn't complete before the timeout, a `PlaybackException` is thrown to avoid the playback endless stalling. The timeout is set to zero by default.
This can avoid HLS playback endlessly stalls when manifest has missing discontinuities. According to the HLS spec, all variants and renditions have discontinuities at the same points in time. If not, the one with discontinuities will have a new `TimestampAdjuster` not shared by the others. When the loading thread of that variant is waiting for the other threads to initialize the timestamp and hits the timeout, the playback will stall.
Issue: androidx/media#323
#minor-release
PiperOrigin-RevId: 539108886
When the source is prepared again after stop, the period uid
is calculated by subtracting the `firstPeriodId` from the
period uid that is passed in to `createPeriod`. When this
happens after stop, the uid from the old period uid that
is still stored and has the value of the last played uid.
Hence the `firstPeriodId` must not be reset when released.
Issue: google/ExoPlayer#10838
PiperOrigin-RevId: 539028570
Add support for including Common Media Client Data (CMCD) in the outgoing requests of adaptive streaming formats DASH, HLS, and SmoothStreaming.
API structure and API methods:
* CMCD logging is disabled by default, use `MediaSource.Factory.setCmcdConfigurationFactory(CmcdConfiguration.Factory cmcdConfigurationFactory)` to enable it.
* All keys are enabled by default, override `CmcdConfiguration.RequestConfig.isKeyAllowed(String key)` to filter out which keys are logged.
* Override `CmcdConfiguration.RequestConfig.getCustomData()` to enable custom key logging.
NOTE: Only the following fields have been implemented: `br`, `bl`, `cid`, `rtp`, and `sid`.
Issue: google/ExoPlayer#8699
#minor-release
PiperOrigin-RevId: 539021056
This CL introduces the new public API setSuppressPlaybackWhenUnsuitableOutput which if set to TRUE will cause suppression of a requested playback if that is going to happen on an unsuitable audio output (e.g. builtin speaker on a WearOS device).
PiperOrigin-RevId: 538867212
This change is for Android 12 and below, where the buttons are derived from the actions added with the notification. From Android 13 (https://developer.android.com/about/versions/13/behavior-changes-13#playback-controls), the system derives media controls from `PlaybackState` actions.
When adding the actions onto the notification, the logic will iterate all the command buttons. The `COMMAND_KEY_CONPACT_VIEW_INDEX` extra will be checked for each button. If that extra is set for the three buttons on the compact view, then the customized buttons and their order will be used. Otherwise, the compact view will be "seekPrev" (if any), "play/pause" (if any), "seekNext" (if any) buttons (in such order).
Issue: androidx/media#410
PiperOrigin-RevId: 538797874
The sample timestamp carried by the emsg box can have a significant delta when comparing to the earliest presentation timestamp of the segment. Using this timestamp to intialize the timestamp offset in TimestampAdjuster will cause the media sample to have a wrong adjusted timestamp. So we should defer adjusting the metadata sample timestamp until the TimestampAdjuster is initialized with a real media sample.
PiperOrigin-RevId: 538172841
When initiated by MediaController, it should be possible for `MediaSession` to pass `MediaItems` to the `Player` if they have `LocalConfiguration`. In such case, it is not required to override `MediaSession.Callback.onAddMediaItems`, because the new current default implementation will handle it.
However, in other cases, MediaItem.toBundle() will continue to strip the LocalConfiguration information.
Issue: androidx/media#282
#minor-release
PiperOrigin-RevId: 537993460
With `AudioOffloadModePreference` `AUDIO_OFFLOAD_MODE_PREFERENCE_REQUIRED`, the `DefaultTrackSelector` will select a single audio track that it finds is offload compatible. If not any audio track is supported in offload, then no track will be selected.
PiperOrigin-RevId: 537877183
This is a breaking change, but the alternatives seem either equally
breaking or worse, since the only way to make this non-breaking is
to add the `Throwable` overloads as `default` methods. It's then
unclear how we would ever migrate to these being the 'only' methods
or whether we'd have to keep both forms forever (which results in
duplication in the `Logger` implementations).
The clean break here also makes it clear that the `message` parameter
of `Log.Logger.{d,i,w,w}()` no longer automatically includes any info
from the `Throwable` passed to the static `Log.{d,i,w,e}() methods.
----
This CL also cleans up the javadoc on the static `Log.{d,w,i,e}` methods
since they no longer necessarily call straight through to the
corresponding `android.util.Log` methods (and haven't since <unknown commit>
and Issue: google/ExoPlayer#10185).
PiperOrigin-RevId: 537817974
*** Original commit ***
ExoPlayer: Add setVideoFrameProcessorFactory().
This allows apps to use a custom VideoFrameProcessor implementation for video
playback. This may be useful, for example, when outputting to a texture.
***
PiperOrigin-RevId: 536391597
Deprecated field `MediaItem.playbackProperties` remains for backwards compatibility, but its type is changed from `MediaItem.PlaybackProperties` to `MediaItem.LocalConfiguration`. The private `MediaItem` constructor will now also take in a `LocalConfiguration` argument instead.
PiperOrigin-RevId: 535648420
This change removes it from `Player.Listener` and `AnalyticsListener`,
use `onPositionDiscontinuity` with `DISCONTINUITY_REASON_SEEK` instead.
#minor-release
PiperOrigin-RevId: 534757426
Added piping to present offload support from the audio sink to the renderer and track selection. Applications can set offload mode preference and with both sink support and compatible track selection, renderer will be configured for offload.
PiperOrigin-RevId: 534450534
This change merges some duplicate sections, moves some items to more
appropriate sections and removes unnecessary items (deprecations are
self-documenting, so don't need to be included here).
#minor-release
PiperOrigin-RevId: 534363065
This change deprecates `PlayerView.setUseArtwork(boolean)` and
introduces `setArtworkDisplayMode(mode)` and
`artworkDisplayMode="off|fit|fill"` instead.
- off: no artwork is displayed (like deprecated useArtwork=false)
- fit: letterbox like media (like deprecated useArtwork=true)
- fill: scales the artwork to fill the entire width/weight of the player view
#minor-release
PiperOrigin-RevId: 534167226
Fix a bug when seeking in an opus container. The calculations inside
DefaultOggSeeker may overflow a long primitive.
Issue: androidx/media#391
#minor-release
PiperOrigin-RevId: 534128513
This allows apps to use a custom VideoFrameProcessor implementation for video
playback. This may be useful, for example, when outputting to a texture.
PiperOrigin-RevId: 534044831
In terms of MCVR with a `VideoRendererEventListener`, the video size is set to
0/0 right after `onVideoDisabled()` is called and is set to the actual size as
soon as the video size is known after 'onVideoEnabled()`.
For ExoPlayer and in terms of the `Player` interface, `Player.getVideoSize()`
returns a video size of 0/0 when `Player.getCurrentTracks()` does not support
`C.TRACK_TYPE_VIDEO`. This is ensured by the masking behavior of
`ExoPlayerImpl` that sets an empty track selection result when the playing
period changes due to a seek or timeline removal.
When transitioning playback from a video media item to the next, or when
seeking within the same video media item, the renderer is not disabled.
#minor-release
PiperOrigin-RevId: 533479600
This is useful for cases where only certain types (e.g. only video)
from a source are needed and other tracks should be filtered out
completely to avoid later track selection issues.
#minor-release
PiperOrigin-RevId: 533394658
Use Kotlin Charsets from the `kotlin.text` package, the `java.nio.charset.StandardCharsets` or the `com.google.common.base.Charsets` instead.
#minor-release
PiperOrigin-RevId: 532469103
Use a non deprecated constructor that includes the option to provide a `channelDescriptionResourceId` parameter.
#minor-release
PiperOrigin-RevId: 532450975
This change enables the IMA extension to play live DASH streams
with DAI support. Samples streams can be found and played in the
main demo app.
Issue: google/ExoPlayer#10912
#minor-release
PiperOrigin-RevId: 532407708
Use a non-deprecated constructor that accepts additional fields(`cause`, `responseBody`) to enhance error logging.
#minor-release
PiperOrigin-RevId: 532190896
This methods allows to replace single items or a range of items directly
without using separate operations for add and remove. The advantage is
more readable code for apps and the potential for player
implementations to optimize this process (e.g. only replace values
without interrupting playback).
The current change just introduces the API with its default behavior.
The default logic will be removed again in the future in favor of
better logic in the Player implementations.
Issue: google/ExoPlayer#8046
PiperOrigin-RevId: 532151471
The periodic updates are only meant to happen while we are in the
same period or ad. This was already guaranteed except for two cases:
1. The Player in a session has updated its state without yet calling
its listeners
2. The session scheduled a PlayerInfo update that hasn't been sent yet
... and in both cases, the following happened:
- The change updated the mediaItemIndex to an index that didn't exist
in a previous Timeline known to the Controller
- One of the period position updates happened to be sent at exactly
this time
This problem can be avoided by only scheduling the update if we are
still in the same period/ad and haven't scheduled a normal PlayerInfo
update already.
Since new MediaControllers may still connect to old sessons with this
bug, we need an equivalent change on the controller side to ignore such
buggy updates.
PiperOrigin-RevId: 532089328
Adding items to an empty playlist is slightly different from adding
items to a non-empty playlist, because the former usually requires to
handle a change in the current item, position and playback state,
while the latter is not expected to affect the current item, position
or state.
The current ExoPlayer and SimpleBasePlayer code doesn't account for
this difference, leading to inconsistent behavior between
setMediaItem(s) and addMediaItem(s) when called on an empty playlist.
PiperOrigin-RevId: 530549928
The media button has API support with
`Callback.getPlaybackResumption()` that apps need to override to provide
a playlist to resume playback with.
Issue: androidx/media#167
PiperOrigin-RevId: 529495845
* Implement RendererCapabilities.Listener in DefaultTrackSelector.
* Add new methods TrackSelector.invalidateForRendererCapabilitiesChange and TrackSelector.InvalidateListener.onRendererCapabilitiesChanged.
* Add new field allowInvalidateSelectionsOnRendererCapabilitiesChange to DefaultTrackSelector.Parameter to allow opt-in of the renderer capabilities detection feature.
* Add logics of triggering track reselection when renderer capabilities change.
PiperOrigin-RevId: 529067433
Systems accepting URIs should treat schemes as case-insensitive
([RFC 3986 Section 3.1](https://www.rfc-editor.org/rfc/rfc3986#section-3.1)):
> An implementation should accept uppercase letters as equivalent to
> lowercase in scheme names (e.g., allow "HTTP" as well as "http") for
> the sake of robustness
PiperOrigin-RevId: 528735287
References to the service are kept from MediaSessionStub
and from a long-delayed Handler messages in ConnectionTimeoutHandler.
Remove strong references from these places by making the timeout
handler static and ensuring ConnectedControllersManager only keeps
a weak reference to the service (as it's part of MediaSessionStub).
Issue: androidx/media#346
PiperOrigin-RevId: 527543396
To reliably reject the System UI playback resumption notification on
all API levels (specifically API 30), the backward compatibility layer
needs to return `null` for the library root.
This is not possible in the Media3 implementation. This change allows
an app to return a `LibraryResult.ofError(RESULT_ERROR_NOT_SUPPORTED)`
that then is translated to return null by the backwards compatibility
layer.
Issue: androidx/media#355
Issue: androidx/media#167
Issue: androidx/media#27
See https://developer.android.com/guide/topics/media/media-controls#mediabrowserservice_implementation
PiperOrigin-RevId: 527276529
This is a helper method that can used to obtain information about
the controller that is currently calling a Player method.
PiperOrigin-RevId: 527268994
This simplifies the addition of new fields in the future.
Also do some misc clean up for the volume limit values:
- Add some documentation to mention assumed defaults
- Add the IntRange annotations to match the ones we have in Player
already
- Mention the limits in the relevant Player methods
- Avoid bundling default values
- Improve range checks for masking in MediaController
PiperOrigin-RevId: 526029619
This is a bug currently, where commands are created once but never
updated again if the actions in MediaSessionCompat are changed.
PiperOrigin-RevId: 525999084
If the limited number of input buffers causes reading of all samples except the last one conveying end of stream, then the last frame will not be rendered.
PiperOrigin-RevId: 525974445
`findDecoder/EncoderForFormat` seem to be more restrictive than querying
`MediaCodecList` as done for playback, and it's not clear that the cases where
no codec is found correspond to actual cases that would fail given that it
seems this returns an empty string for many cases in production.
Switch to using `MediaCodecUtil` and `EncoderUtil` for querying codecs instead.
PiperOrigin-RevId: 525078321
The sessions may have different application threads for their players,
and the service with its notification provider runs on the main thread.
To ensure everything runs on the correct thread, this change labels
methods where needed and fixes thread access in some places.
Issue: androidx/media#318
PiperOrigin-RevId: 524849598
This check was a leftover from when the metadata was generated from
the MediaItem only. Since we moved to the actual MediaMetadata fields,
the check is completely unnecessary and prevents accessing metadata
when the GET_CURRENT_MEDIA_ITEM command is not available.
#minor-release
PiperOrigin-RevId: 524837587
In `ExternalTextureManager` in seemingly rare cases end of stream is signaled
at the point where a frame is currently pending processing. In that case the
video end of stream signal was lost. If the muxer timeout was enabled this
case would result in throwing an exception, but otherwise the operation would
get stuck
Add code to signal end of stream in `onInputFrameProcessed` as well, so that we
signal end of stream when the pending frame is handled.
Tested by running
`TransformerEndToEndTest.loopingTranscodedVideo_producesExpectedResult` several
times.
PiperOrigin-RevId: 524361069
The overrides specified by a MediaController may not use the exact
same TrackGroup instances as known to the Player because the groups
have been bundled to and from the controller. This bundling may
alter the instance slightly depending on the version used on each
side of the communication and the fields set (e.g. Format.metadata
is not supported for bundling).
This issue can be solved by creating unique track group ids for
each group on the session side before bundling. On the way back,
the groups in the track selection parameters can be mapped backed
to their original instances based on this id.
#minor-release
Issue: androidx/media#296
PiperOrigin-RevId: 523986626
Previously, ExoPlayerImpl had volume flags hardcoded to SHOW_UI, but now the developer can choose what happens on volume change. The old methods have been deprecated.
PiperOrigin-RevId: 523974358
The setter command is only used for setPlaylistMetadata and can
be named COMMAND_SET_PLAYLIST_METADATA. The getter commnad is
used to access getMediaMetadata and getPlaylistMetadata and can
be better named COMMAND_GET_METADATA to reflect this usage.
PiperOrigin-RevId: 523673286
Previously `ChannelMixingAudioProcessor` output float because it was
implemented using the audio mixer's float mixing support.
Move the implementation over to just using the `ChannelMixingMatrix` and make
it publicly visible in the common module so it can be used by apps for both
playback and export.
Also resolve a TODO that no longer had a bug attached by implementing support
for putting multiple mixing matrices to handle different input audio channel
counts, and fix some nits in the test code.
Tested via unit tests and manually configuring a `ChannelMixingAudioProcessor`
in the transformer demo app and playing an audio stream that identifies
channels, and verifying that they are remapped as expected.
PiperOrigin-RevId: 523653901
It is not possible to provide a safe deprecation path because
BaseTrackSelection can't easily know which of the methods is
implemented by subclasses.
PiperOrigin-RevId: 523471578
`sed` has a different in-place command line syntax in FreeBsd
than GNU tools. This change makes the `sed` commands work with
FreeBSD `sed` on OSX in bash and zsh shells.
Issue: androidx/media#217
PiperOrigin-RevId: 522043938
MediaItems are not meant to be unique in a playlist. If a legacy
session publishes multiple items that get converted to equal MediaItems,
the current code fails because we look up queue ids in a Map (that
doesn't allow duplicate entries).
Fix this by storing a simple list of items with additional data.
#minor-release
Issue: androidx/media#290
PiperOrigin-RevId: 521993802
* Add a new event `onAudioCapabilitiesChanged` in `AudioSink.Listener` interface.
* Add an interface `RendererCapabilities.Listener`, which will listen to `onRendererCapabilitiesChanged` events from the renderer.
* Add `getRendererCapabilitiesReceiver` method for `TrackSelector`, and register/unregister the `TrackSelector` as the `RendererCapabilitiesReceiver` (if implemented) when the `ExoPlayer` is initialized/released.
* Trigger the `AudioSink.Listener.onAudioCapabilitiesChanged` and further `RendererCapabilities.Listener.onRendererCapabilitiesChanged` events when the audio capabilities changes are detected in `DefaultAudioSink`.
PiperOrigin-RevId: 521427567
The `DashMediaSource` wrongly added an offset to the media times set
to the `MediaLoadData`. With this the `startTimeMS` and `endTimeMs`
don't represent the positions in the period but in the stream.
`DashMediaSource` was the only call site that was setting the offset
to a non-zero value. So if we are using 0 for the `DashMediaSource`
as well, the offset is redundant and we can remove it everywhere.
PiperOrigin-RevId: 520682026
For multi-period live streams the content timeline for
which the global ad playback state has been split needs
to be kept together to not run into a race between
timeline refreshes and ad events.
PiperOrigin-RevId: 520358964
If RTSP Setup Request with UDP receives HTTP Error Status 461 UnsupportedTransport, then client will retry with TCP.
Issue: google/ExoPlayer#11069
PiperOrigin-RevId: 518807829
* Add `release` method to Renderer and AudioSink interfaces.
* Call the `release` method for renderers when the ExoPlayer is going to be released.
PiperOrigin-RevId: 517135677
While playback thread is 'asleep' during audio offload playback, the playbackInfo.positionUs is not being constantly updated. During this time, the returned value from getCurrentPosition should return an estimate based on the most recent value and playback speed.
PiperOrigin-RevId: 516550509
The value returned by `player.getContentPosition()` is calculated
in the timeline based on the position of the first period in the
window. In a single period live stream this position is advanced
when the live window advances on timeline refresh.
This calculation has produced slightly varying values below 1000
us which are likely caused by us/ms truncations for public API
values that we use in the IMASSAIMediaSource.
However, `AdGroup.timeUs` is the (recorded) content position at the
moment when the first ad of the an ad group has been inserted. While
playing an ad, we can always use this value instead of
`getContentPosition()` to not require recalculation.
#minor-release
PiperOrigin-RevId: 515093177
Segment timelines are technically allowed to be empty, but not all places
add the necessary checks.
Issue: google/ExoPlayer#11014
PiperOrigin-RevId: 514722205
Playback parameter signalling can be quite complex because
(a) the renderer clock often has a delay before it realizes
that it doesn't support a previously set speed and
(b) the speed set on media clock sometimes intentionally
differs from the one surfaced to the user, e.g. during
live speed adjustment or when overriding ad playback
speed to 1.0f.
This change fixes two problems related to this signalling:
1. When resetting the media clock speed at a period transition,
we don't currently tell the renderers that this happened.
2. When a delayed speed change update from the media clock is
pending and the renderer for this media clock is disabled
before the change can be handled, the pending update becomes
stale but it still applied later and overrides any other valid
speed set in the meantime.
Both edge cases are also covered by extended or new player tests.
Issue: google/ExoPlayer#10882
#minor-release
PiperOrigin-RevId: 512658918
MediaCodecRenderer currently has two independent paths to trigger
events at stream changes:
1. Detection of the last output buffer of the old stream to trigger
onProcessedStreamChange and setting the new output stream offset.
2. Detection of the first input buffer of the new stream to trigger
onOutputFormatChanged.
Both events are identical for most media. However, there are two
problematic cases:
A. (1) happens after (2). This may happen if the declared media
duration is shorter than the actual last sample timestamp.
B. (2) is too late and there are output samples between (1) and (2).
This can happen if the new media outputs samples with a timestamp
less than the first input timestamp.
This can be made more robust by:
- Keeping a separate formatQueue for each stream to avoid case A.
- Force outputting the first format after a stream change to
avoid case B.
Issue: google/ExoPlayer#8594
#minor-release
PiperOrigin-RevId: 512586838
Some devices were reported to have wrong PerformancePoint sets
that cause 60 fps to be marked as unsupported even though they
are supported.
Issue: google/ExoPlayer#10898
#minor-release
PiperOrigin-RevId: 512580395
Protected system broadcasts should not specify the export flag.
Marking them as NOT_EXPORTED breaks sticky broadcasts in some
cases.
Issue: google/ExoPlayer#10970
#minor-release
PiperOrigin-RevId: 512020154
In parsing Describe RTSP response messages, IllegalArgumentExceptions are thrown for invalid parameters and values. These exceptions were not caught and crashed the Playback thread. Now these exceptions will be caught and their errors forwarded to the proper error handling listeners.
#minor-release
Issue: google/ExoPlayer#10971
PiperOrigin-RevId: 509207881
`TrackSelectorResult.rendererConfigurations` can contain null elements:
> A null entry indicates the corresponding renderer should be disabled.
This wasn't caught by the nullness checker because `ExoPlayerImpl` is
currently excluded from analysis.
#minor-release
Issue: google/ExoPlayer#10977
PiperOrigin-RevId: 508619169
Can be used to combine multiple media items into a single timeline window.
Issue: androidx/media#247
Issue: google/ExoPlayer#4868
PiperOrigin-RevId: 506283307
This change fixes an issue that can be reproduced when
a controller `onConnect` creates a `QueueTimeline` out
of the state of a legacy session and then `prepare` is called.
`activeQueueItemId`, `metadata` and the `queue` of the legacy
session are used when a `QueueTimeline` is created. The change
adds unit tests to cover the different combinatoric cases these
properties being set or unset.
PiperOrigin-RevId: 505731288
ParcelFileDescriptor is quite specific and removing it allows to have
less overloads of startTransformation.
A follow-up CL will undeprecate the overload that takes a MediaItem.
PiperOrigin-RevId: 505670321
When seeking in fMP4, we try to extract as little samples as possible
by only starting at the preceding sync frame. This comparison should
use <= to allow sync frames at exactly the seek position.
Issue: google/ExoPlayer#10941
#minor-release
PiperOrigin-RevId: 505098172
Added onSetMediaItems callback listener to allow the session to modify/set MediaItem list, starting index and position before call to Player.setMediaItem(s).
Added conditional check in MediaSessionStub.setMediaItem methods to only call player.setMediaItem rather than setMediaItems if player does not support COMMAND_CHANGE_MEDIA_ITEMS
PiperOrigin-RevId: 503427927
Starting with API 33 the POST_NOTIFICATION permission needs to be
requested at runtime or the notification is not shown.
Note that with an app with targetSdkVersion < 33
but on a device with API 33 the notification permission is automatically
requested when the app starts for the first time. If the user does not
grant the permission, requesting the permission at runtime result in
an empty array of grant results.
Issue: google/ExoPlayer#10884
PiperOrigin-RevId: 501320632
For TV devices the skip button needs to have the focus to be accessible with
the remote control. This property makes this configurable while being set to
true by default.
PiperOrigin-RevId: 501077608
When audio processors are enabled during tunneling, they must produce
output immediately, ensuring that the timestamps of the output samples
correspond to the input and that no additional samples are produced.
This requirement is documented in the Javadoc of DefaultAudioSink.
However, this alone doesn't guarantee all buffers are immediately
written to the AudioTrack, because the AudioTrack writes are
non-blocking and may need multiple attempts.
When draining the audio sink at the end of the stream, we currently
fail in this situation because we assert that the timestamp must be
set (=the drain operation is a no-op). But this may not be true when
the previous non-blocking write wasn't fully handled. We can fix this
by saving the last timestamp and reusing it during draining.
Issue: google/ExoPlayer#10847
PiperOrigin-RevId: 500943891
There are two overloads of this method due to a type 'rename' from
`PlayerControlView.VisibilityListener` to
`PlayerView.ControllerVisibilityListener`. Currently when you call one
overload it passes `null` to the other one (to clear the other listener).
Unfortunately this results in it clearing itself, because it receives
a null call back!
This change tweaks the documentation to clarify that the 'other'
listener is only cleared if you pass a non-null listener in. This solves
the recursive problem, and allows the 'legacy' visibility listener to be
successfully registered.
Issue: androidx/media#229
#minor-release
PiperOrigin-RevId: 496876397
The MediaSourceFactory won't be used by the other AssetLoaders
In order to do that, ExoPlayerAssetLoader has been made public, and the
DefaultAssetLoaderFactory has become a wrapper around
ExoPlayerAssetLoader.
PiperOrigin-RevId: 496386853
These are the remaining setter operations. They all share the same
logic that handles playlist and/or position changes. The logic to
create the placeholder state is mostly copied from ExoPlayerImpl's
maskTimelineAndPosition and getPeriodPositonUsAfterTimelineChanged.
PiperOrigin-RevId: 496364712
BasePlayer simplifies implementations by handling all the various
seek methods and forwarding to a single method that can then be
implemented by subclasses. However, this loses the information about
the concrete entry point used for seeking, which is relevant when
the subclass wants to verify or filter by Player.Command. This
can be improved by adding the command as a new parameter. Since
we have to change the method anyway, we can also incorporate the
boolean flag about whether the current item is repeated to avoid
the separate method.
PiperOrigin-RevId: 494948094
The folder type has a mix of information about the item. It shows
whether the item is browsable (type != FOLDER_TYPE_NONE) and
which Bluetooth folder type to set for legacy session information.
It's a lot clearer to split this into a boolean isBrowsable and
use the existing mediaType to map back to the bluetooth folder type
where required.
folderType is not marked as deprecated yet as this would be an API
change, which will be done later.
PiperOrigin-RevId: 493544589
Discovered while investigating Issue: google/ExoPlayer#10823
Example stack trace with the previous code (I added the index value for
debugging):
```
playerFailed [eventTime=44.07, mediaPos=44.01, window=0, period=0, errorCode=ERROR_CODE_FAILED_RUNTIME_CHECK
androidx.media3.exoplayer.ExoPlaybackException: Unexpected runtime error
at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:635)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loopOnce(Looper.java:202)
at android.os.Looper.loop(Looper.java:291)
at android.os.HandlerThread.run(HandlerThread.java:67)
Caused by: java.lang.IllegalArgumentException: index=-1
at androidx.media3.common.util.Assertions.checkArgument(Assertions.java:55)
at androidx.media3.extractor.text.webvtt.WebvttSubtitle.getEventTime(WebvttSubtitle.java:62)
at androidx.media3.extractor.text.SubtitleOutputBuffer.getEventTime(SubtitleOutputBuffer.java:56)
at androidx.media3.exoplayer.text.TextRenderer.getCurrentEventTimeUs(TextRenderer.java:435)
at androidx.media3.exoplayer.text.TextRenderer.render(TextRenderer.java:268)
at androidx.media3.exoplayer.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:1008)
at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:509)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loopOnce(Looper.java:202)
at android.os.Looper.loop(Looper.java:291)
at android.os.HandlerThread.run(HandlerThread.java:67)
]
```
#minor-release
PiperOrigin-RevId: 492464180
Use the bitrate of the audio format (when available) in
DefaultAudioSink.AudioTrackBufferSizeProvider.getBufferSizeInBytes() to
calculate accurate buffer sizes for direct (passthrough) playbacks.
#minor-release
PiperOrigin-RevId: 491628530
This avoids that apps have to depend on the legacy compat support
library when they want to make this conversion.
Also add a version to both helper methods that takes a Looper to
give apps the option to use an existing Looper, which should be
much faster than spinning up a new thread for every method call.
Issue: androidx/media#171
PiperOrigin-RevId: 490441913
The method allows clients to specify a pre-existing thread
to use for playback. This can be used to run multiple ExoPlayer
instances on the same playback thread.
PiperOrigin-RevId: 488980749
Util.getAudioTrackChannelConfig() maps a channel count to a
channel mask that is passed to AudioTrack. The method expected that
playback of 8-channel audio is possible from Android 5.1 and playback of
12-channel audio is only possible from Android 12L. However, there is no
restriction on the upper number of channels that can be passed to the
AudioTrack. google/ExoPlayer#10701 is an example where the audio decoder
outputs 12 channels on an Android 10.
This change removes the restrictions for 8 and 12 channels. Note, we still
do not support playback of arbitrary number of channels as it would require
further changes to DefaultAudioSink.
#minor-release
Issue: google/ExoPlayer#10701
PiperOrigin-RevId: 488659831
When we currently trigger the iteration finished event during the
release, we don't mark the event as triggered. This means that
someone can trigger another release from within the callback,
which then tries to resend the event.
Issue: google/ExoPlayer#10758
#minor-release
PiperOrigin-RevId: 488645089
We currently skip this calculation entirely, but it can be added by
calculating the window duration using the wrapped window's duration
and the provided AdPlaybackState.
Issue: google/ExoPlayer#10764
PiperOrigin-RevId: 488614767
Added new method to check if codec just functionally supports a format. Changed getDecoderInfosSortedByFormatSupport to use new function to order by functional support. This allows decoders that only support functionally and are more preferred by the MediaCodecSelector to keep their preferred position in the sorted list.
UnitTests included
-Two MediaCodecVideoRenderer tests that verify hw vs sw does not have an effect on sort of the decoder list, it is only based on functional support
Issue: google/ExoPlayer#10604
PiperOrigin-RevId: 487779284
The connection to a legacy MediaSession may receive additional
onSessionReady callbacks that are treated as additional state updates.
We currently also set the "notifyConnected" flag for these updates
even though we are connected already, causing an IllegalStateException.
Fix the exception by not setting this flag.
We can also remove the wording about "locked" updates since this class
operates everything on a single application thread.
Issue: androidx/media#49
PiperOrigin-RevId: 487487286
If an app sets a compileSdkVersion that is lower than the one used to
create AARs of its dependencies, the build process may produce invalid
outputs, for example by stripping methods from the APK that are only
called when the app is running on a new API version.
To avoid this issue, we can enforce that the compileSdk of apps or
libraries depending on ExoPlayer/Media3 is at least the same as the
one we used for compilation when creating the AAR.
Issue: google/ExoPlayer#10684
PiperOrigin-RevId: 485100067
From ANSI-CTA-608-E R-2014 section 8.4:
> When closed captioning is used on line 21, field 2, it shall conform
> to all of the applicable specifications and recommended practices as
> defined for field 1 services with the following differences:
> 1. The non-printing character of the miscellaneous control-character
> pairs that fall in the range of 0x14, 0x20 to 0x14, 0x2F in field 1,
> shall be replaced with 0x15, 0x20 to 0x15, 0x2F when used in field
> 2.
> 2. The non-printing character of the miscellaneous control-character
> pairs that fall in the range of 0x1C, 0x20 to 0x1C, 0x2F in field
> 1, shall be replaced with 0x1D, 0x20 to 0x1D, 0x2F when used in
> field 2.
This basically means that `cc1=0x15` in field 2 should be interpreted as
`cc1=0x14` in field 1, and same for `0x1D -> 0x1C`.
The `isMiscCode` method above already handles this by ignoring the LSB
(the only difference between `0x14` and `0x15`, and `0x1C` and `0x1D`)
by AND-ing with `0xF6` instead of `0xF7`. This change uses the same
trick in `isServiceSwitchCommand`.
Issue: google/ExoPlayer#10666
#minor-release
PiperOrigin-RevId: 483927506
Currently, repeating the same item (via seekNext/Previous) implicitly
results in a seek to the default position of the current item, which
looks exactly the same as a direct seek. As a result, we don't send
onMediaItemTransition as we would for every other seekNext/Previous
call.
This can be fixed by explicitly marking the repeat case in the internal
BasePlayer/ExoPlayerImpl methods, so that the callback can be triggered.
Issue: google/ExoPlayer#10667
PiperOrigin-RevId: 481951788
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
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
A follow up to stopping speaker playback with a Player decorator from
https://github.com/androidx/media/issues/15.
It looks like we will need to change to using playback suppression to avoid
errors like https://github.com/androidx/media/issues/167, when we don't start
a foreground service.
We may not have this implemented by 1.0, but would like it in the API and it seems to be appropriate.
PiperOrigin-RevId: 478835686
`PlaybackStateCompat.toKeyCode(command)` was replaced by our
own implementation of `toKeyCode()`. The legacy implementation used PLAY and PAUSE, while the new implementation uses PLAY_PAUSE. This made `pause` a pending intent that attempt to start the service in the foreground, but `service.startForeground()` won't be called in `MediaNotificationManager.updateNotificationInternal` when paused.
PiperOrigin-RevId: 476895752
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 assertion asserts against a `Period` and an `AdPlaybackState` which actually
asserts against a resolved ad which is what `ExoPlayerImplInternal` does later and
what gives us a `SEEK_ADJUSTMENT`. However, this assertion is not required at the
moment of masking, because we are sure that the resolved seek results in a content
period and never an ad period.
#minor-release
Issue: androidx/media#122
PiperOrigin-RevId: 471827072
The specified CMake version doesn't work with the latest
Android Studio releases. Updating to a more recent version
fixes the problem.
Issue: google/ExoPlayer#9933
PiperOrigin-RevId: 467634063
When the player finishes playback and reaches the STATE_ENDED,
the notification remains visible with a pause button and the
service is kept in the foreground. This is a bug.
With this change, when the player reaches the STATE_ENDED, the
service is stopped from the foreground and a notification is shown
with a play button. If the play icon is tapped, the player will restart
playback of the last played item. Playing the last played item again
is the existing behavior when play/pause commands are received from
the legacy MediaSession (e.g. BT headset buttons).
#minor-release
Issue: google/ExoPlayer#112
PiperOrigin-RevId: 467231509
From NDK 23.1.7779620 and above, the arm64-v8a ABI needs additional
build flags to correctly link the ffmpeg libraries.
Issue: google/ExoPlayer#9933
PiperOrigin-RevId: 467161973
In some cases, the IMA SDK fails to call the expected loadAd
event to load the next ad to play. This is (potentially) the
only remaining case where playback can get stuck due to missing
calls from IMA as the player doesn't even have a MediaSource at
this stage and is only waiting for IMA to provide the ad URL.
We can reuse the existing adPreloadTimeoutMs that was added for
a similar purpose (when preloading the first ad in the group).
The JavaDoc matches this purpose as well and the default timeout
is appropriate since we expect to get the loadAd call immediately.
Issue: google/ExoPlayer#10510
PiperOrigin-RevId: 466953617
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
Also rearranged release notes to correctly show when the changes were released.
#minor-release
PiperOrigin-RevId: 462361982
(cherry picked from commit c6e69a35a8)
We currently clear all pending messages, including the one that flushes
pending commands to the MediaSession. To ensure all commands that have
been called before controller.release() are still sent, we can manually
trigger the flush message from the release call.
Related to handling the final flush because disconnecting the controller,
MediaSessionStub didn't post the removal of the controller to the
session thread, creating a race condition between removing the controller
and actually handling the flush.
Issue: androidx/media#99
PiperOrigin-RevId: 462342860
Add a Builder to constructor DefaultMediaNotificationProvider. The
Builder can also set the provider's:
- notification ID
- notification channel ID
- notification channel name
The change adds an API for apps to set the small icon in notifications.
#minor-release
Issue: androidx/media#104
PiperOrigin-RevId: 462111536
Some commands are run asynchronously and subsequent commands need
to wait until the previous one finished. This can be supported
by returning a Future for each command and using the existing
command execution logic to wait for each Future to complete.
As some MediaSessionStub code is now executed delayed to when it
was originally created, we also need to check if the session is
not released before triggering any actions or sending result codes.
Issue: androidx/media#85
PiperOrigin-RevId: 462101136