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
- Use `PlaybackException.ErrorCode` IntDef for `DataSourceException` error code
- Deprecate `DataSourceException.POSITION_OUT_OF_RANGE`
- All other changes are related to replacing the deprecated constant and
constructor
PiperOrigin-RevId: 382683522
In order to use it for error code assignment. Note that these DRM errors
could be thrown on API < 18 (from MediaCodec.CryptoException), which is
the reason we can't put the mapping in FrameworkMediaDrm.
PiperOrigin-RevId: 382512414
PlayerView and StyledPlayerView handled this in
onVideoSizeChanged but it can be omitted.
(e.g. if the player is MediaController)
PiperOrigin-RevId: 382340927
Currently when a HTTP POST request receives a 302, CronetDataSource will change the request method from POST to GET for the redirected request, and drop the post body. This aligns with the behaviours of many user agents, but our use case would like to keep the POST method and the post body.
org.chromium.net.UrlRequest.followRedirect also changes POST to GET for 302, so should be avoided here.
PiperOrigin-RevId: 381233011
A no-op change that changes the signature of the onChunkLoadError method of the ChunkSource. Implementors can get the exclusion duration directly from the LoadErrorHndlingPolicy instead of receiving it as an argument of the callback.
PiperOrigin-RevId: 381102935
No-op change that adds the @FallbackType IntDef and changes the signature of getBlacklistDurationMsFor(LoadErrorInfo) to getExclusionDurationMsFor(@FallbackType, LoadErrorInfo).
PiperOrigin-RevId: 381075496
Previously, a SocketTimeourException is used to signal the end of the stream
that is caused by "no RTP packets received for a while". However, such
signaling is inappropriate under TransferRtpDataChannel, or FakeRtpDataChannel
in RtspPlaybackTests.
Hence, the signaling of end of stream is changed to use RESULT_END_OF_INPUT.
The RtpDataChannel implementations will Still block until a set timeout, but
will return a C.RESULT_END_OF_INPUT should a timeout occur, instead of
throwing a nested SocketTimeoutException.
This also allowed customization of the timeout amount, in
RtspMediaSource.Factory
PiperOrigin-RevId: 380981534
The current FLAG_REQUIRE_FORMAT documentation states: If an end of
stream buffer would be read were the flag not set, then behavior is
unchanged.
PiperOrigin-RevId: 380792251
The current FLAG_REQUIRE_FORMAT documentation states: If an end of
stream buffer would be read were the flag not set, then behavior is
unchanged.
PiperOrigin-RevId: 380781976
After this change, multiple BaseURL elements are parsed, but the player still only uses the first BaseURL element appearing in the manifest and its corresponding availabilityTimeOffsetUs.
PiperOrigin-RevId: 380775256
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
This change parses the entire BaseURL element including DVB extension attributes, stores it in an instance of new BaseUrl class and puts it in a list of base URLs of the resulting Representation. The base url handling itself is still the same, which means that only the first base url is taken into account, just as before this change.
PiperOrigin-RevId: 380609495
Some server will wrongly insert duplicated attributes. We used to treat this as
a unrecoverable error, but it is better to treat the duplicated attributes in
an "over-writable" fashion like HashMaps.
Issue: #9080,
Issue: #9014
PiperOrigin-RevId: 380547079
The test prepare_withSupportedTrack_playsTrackUntilEnded
- sets up the supported AAC track with the RTSP server;
- uses RtpPacketTransmitter to send RTP packets from the server to the client;
- runs the player until the playback has ended, and
- asserts on the data RTSP has received and queued to the SampleQueue.
In the test, it was necessary to create a FakeUdpDataSourceRtpDataChannel. The
reason we cannot reuse TransferRtpDataChannel is, we rely on BlockingQueue.poll
timeout to identify the end of an RTSP stream, but the time out mechanism is
unstable in Robolectric. For example, when the timeout is set to 8,000 ms, the
actual timeout occasionally happens after 2,000,000 ms (in FakeClock).
PiperOrigin-RevId: 380528710
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
In prepare_withSupportedTrack_sendsPlayRequest(), the DESCRIBE includes two
tracks, one AAC and one MP4A-LATM. The test is run until a PLAY is sent, and
asserts on only one SETUP is sent (for AAC).
In prepare_noSupportedTrack_throwsPreparationError(), the DESCRIBE includes one
track: one MP4A-LATM. This format is not supported at the moment, so the player
will throw out an error, on which we assert.
PiperOrigin-RevId: 380131458
More information: go/checker-3130-lsc
Tested:
Some test failures are present, but the CL author has decided to mail the change anyway
PiperOrigin-RevId: 379622938
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
As of [JDK-8247957](https://bugs.openjdk.java.net/browse/JDK-8247957), doclint
no longer supports html4.
Tested:
Some test failures are present, but the CL author has decided to mail the change anyway
PiperOrigin-RevId: 378819179
The size of rtspLoaderWrappers must match the number of tracks exposed by the
RTSP session (a track is exposed if its media description entry appears in
DESCRIBE's SDP response).
When retrying with TCP, the old code will start loading all exposed RTSP
tracks, regardless of whether they are selected.
The fixed code will only start loading selected tracks.
#minor-release
PiperOrigin-RevId: 377931030
The current code does not catch the IAE thrown when building a MediaDescription
or SessionDescription. This CL catches the IAE and propagates it as a
ParserException.
Issue: #9014.
#minor-release
PiperOrigin-RevId: 377544439
The old version's retry logic will not work if using authentication.
Specifically, we use the same authentication parameters from the previous
session, and the RTSP server will reject such parameter.
In this fix, we reset the authentication info on retry. Further, we retry the
last request on receiving a 401 Unauthorized, rather than sending out another
DESCRIBE request.
#minor-release
PiperOrigin-RevId: 377539711
After refactoring MediaCodecAdapter.Factory to create configured and
started MediaCodecAdapters in a single operation, the
AsynchronousMediaCodecAdapter does not need to have separate methods to
configure and start, so they are merged. The CONFIGURED state is
removed.
PiperOrigin-RevId: 377519117
Related to Issue: #8941.
RTSP message body's format is not regulated by the RTSP spec, meaning it can
use either CRLF or LF as its line terminator. The old code assumes every line
ends with CRLF (RTSP message and the message body); the new code will rely on
the Content-Length information to receive the bytes for the message body.
#minor-release
PiperOrigin-RevId: 377475565
`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
Related to: Issue: #9010
Profile-level-id (Format.codecs) can be generated from SPS if SDP does not
include it.
#minor-release
PiperOrigin-RevId: 377251211
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
In a follow-up change I will add an additional test to ensure these
events continue to be correctly handled when DefaultDrmSessionManager
has prepareCount==0 but a non-null ExoMediaDrm instance.
PiperOrigin-RevId: 376190225
This helps to remove old ad groups (e.g. those that fell out
of the live window) to keep the data size of AdPlaybackState small.
Also added this case to some existing unit tests to ensure it's
covered.
PiperOrigin-RevId: 376170653
This allows to decouple the data structure from the access. In
a future change, this allows to completely remove old ad groups
(e.g. for live streams where the number of groups would otherwise
grow forever).
Also move the time into the group itself for better encapsulation.
PiperOrigin-RevId: 376170408
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
The docs on setLicenseUri say it's optional, and it has been since
379cd8a04f
(which should have changed this javadoc too)
#minor-release
PiperOrigin-RevId: 376139158
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
The method openSocket in RtspMessageChannel does not actually open a socket.
The 'open' term refers more to opening the message channel.
#minor-release
PiperOrigin-RevId: 375908999
The callbacks received RTSP messages and RTSP sending errors are now invoked
directly from RtspMessageChannel's internal threads. It's up to the handler
implementation to decide which thread to handle the messages.
#minor-release
PiperOrigin-RevId: 375908282
Previously, RTSP interleaved binary data is posted onto the playback thread
for handling, the playback thread then adds the received data to a queue.
A loader thread will later dequeue the data and process it.
In this CL, the binary data is sent through a separate listener, on
RtspMessageChannel's RTSP receiving thread.
#minor-release
PiperOrigin-RevId: 375907609
Currently acquireSession() fails with an NPE from
checkNotNull(exoMediaDrm). A follow-up change will result in exoMediaDrm
sometimes being non-null while prepareCount==0 (and in this case we
still want acquireSession() to fail).
preacquireSession() doesn't currently fail in a way the caller can
observe - the same NPE is thrown, but asynchronously and it doesn't
propagate out of the background thread. Throwing directly seems
preferable since it's a clear bug to be trying to preacquire sessions
from an unprepared/released manager.
PiperOrigin-RevId: 375906450
Unlike Assertions, the introduced method cannot be disabled and throws
a ParserException instead. This method is meant to replace regular
assertions (which throw RuntimeExceptions) which check input in the
parsing code.
PiperOrigin-RevId: 375085160
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
Preload chunks may still need to be discarded. However, we don't
currently support discarding spliced-in chunks. Thus, we need to
avoid loadng a preload chunk that needs to be spliced-in.
Issue: #8937
#minor-release
PiperOrigin-RevId: 374851661
This media source wraps another source and publishes a Timeline with
ads. The created MediaPeriods for ad and content are mapped back to
the original stream to allow seamless playback.
PiperOrigin-RevId: 374836091
There is a newly added condition to help advancing between SSAI ads
and content in case the ad group position or ad duration changed. The
condition currently doesn't check directly whether it's a SSAI
transition but relies on indrect signals. Making this more direct
helps to understand the purpose and avoid unintentional bugs where
this condition would apply in other cases too.
In addition, we need to exclude TextRenderer from the check because
its read position doesn't correspond to the actual decode position
since the decoding happens in the renderer itself (b/181312195).
PiperOrigin-RevId: 374835985
We can instead just save this information in MediaPeriodInfo, similar
to how we store whether the MediaPeriod is last in the timeline etc.
PiperOrigin-RevId: 374835918
It only covers MediaSession - MediaController
(Does not consider cases that either a legacy session or a legacy controller is involved)
Add PlayerInfo#Builder to clean it up.
PiperOrigin-RevId: 374785779
Notes:
- The only functional change is that createForRemote now assings ERROR_CODE_REMOTE_ERROR.
- createForSource still uses ERROR_CODE_UNSPECIFIED, even though it expects an
IOException. The reason for not using ERROR_CODE_IO_UNSPECIFIED is that the reason for
the error might not be IO. For example, malformed media, or BehindLiveWindowException,
which have non-IO error codes. So using UNSPECIFIED saves a later change in category.
PiperOrigin-RevId: 374390407
When working with SSAI ads, we need to easily convert positions between
the underlying stream and the media model that exposes ad groups. To
simplify this, we can add util methods (that are testable on their own).
In addition, we need an easy way to build AdPlaybackStates for SSAI
inserted ads. The metadata is obtained out-of-band and usually has the
ad group start and end times in the underlying stream only. Hence, we
also add a util method to add a new ad group based on this information.
PiperOrigin-RevId: 374369360
MediaSession default command state contains all
commands.
To avoid having to update MediaSession when a command
is added, allow to create a Commands.Builder that
starts with all commands.
PiperOrigin-RevId: 374183484
Make ForwardingPlayer implement Player and not extend BasePlayer so that
ForwardingPlayer forwards each Player method directly to the wrapped
Player instance.
PiperOrigin-RevId: 374161084
Fix bug where rubies and boutens are missing, tate-chu-yoko is rendered
incorrectly when SubtitleView.setApplyEmbeddedStyles(false). This method
should only affect styling elements and not remove any language features.