Previously, we had separate MSG_SET_SURFACE and
MSG_SET_VIDEO_DECODER_OUTPUT_BUFFER_RENDERER messages for
setting different types of supported output. Use of these
constants to switch between outputs during use of a player
was confusing because not all video renderers support both
message types.
To switch from VideoDecoderOutputBufferRenderer to a Surface,
it was sufficient just to send MSG_SET_SURFACE, since all
video renderers support this and clear any other output that
might be set. Conversely, to switch in the opposite direction,
just sending a MSG_SET_VIDEO_DECODER_OUTPUT_BUFFER_RENDERER was
not sufficient, because not all video renderers handle this
message to clear any previous output. Hence it was necessary to
explicitly clear a previously set surface using a separate
MSG_SET_SURFACE message. Passing two messages to switch the
output may prevent renderers from implementing the output switch
efficiently.
This change passes all outputs using a single message type, and
requires that all renderers treat unsupported outputs as though
null were passed (i.e., they clear any existing output). There
are some other miscellaneous improvements:
1. Non-surface outputs are now passed to onRenderedFirstFrame.
This fixes a bug in SimpleExoPlayer's onRenderedFirstFrame,
where previously it could not correctly equality check the
output corresponding to the event to its current output in
the VideoDecoderOutputBufferRenderer case.
2. Fix SimpleExoPlayer to report surface size changes for the
VideoDecoderOutputBufferRenderer case. Even though the
surface is rendered to indirectly in this case, we can still
query (and listen to changes to) the surface's size.
PiperOrigin-RevId: 368215850
If this condition isn't true, the player may enter a cycle of discarding
and reloading the same format. As minDurationToRetainAfterDiscard is a
parameter likely left at its default, and minDurationForQualityIncrease
is likely adjusted more often, we correct the value in the problematic
case and log a warning instead of asserting it outright to prevent
unnecessary app breakages.
Issue: #8807
PiperOrigin-RevId: 368207417
This is the right thing to do, as per the GLSurfaceView documentation.
This adds (previously omitted) calls to VideoDecoderGLSurfaceView.
PiperOrigin-RevId: 368202523
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
There is no use case left where we couldn't use a better
alternative (either looping in the player, using the Player
playlist API, or ConcatenatingMediaSource for advanced cases)
PiperOrigin-RevId: 367990981
Prior to this change, there were some unrealistic quirks in
our Robolectric tests. For example, onRenderedFirstFrame would
be called when using FakeVideoRenderer, despite no output to
render the frame to ever being set. This change improves the
realism of these tests. These changes are required for some
improvements being made to how outputs are set on video
renderers.
PiperOrigin-RevId: 367652169
This was added in 9609af3c23 as part of a LSC.
The RequiresNonNull annotation doesn't work anymore (it doesn't
recognize the outer class member and instead tries to find
the same variable on the inner class). So instead of suppressing
the warning of the non-fulfilled precondition, we can just
check the non-nullness directly and remove the precondition.
PiperOrigin-RevId: 367593941
The main change here is that VideoDecoderGLSurfaceView now implements
VideoDecoderOutputBufferRenderer directly. This avoids SimpleExoPlayer
having to cast to VideoDecoderGLSurfaceView, which will be necessary
if VideoDecoderGLSurfaceView is moved to the UI module. Instead, the
player can cast directly to VideoDecoderOutputBufferRenderer, which
could be moved to the Common module.
The renderer is also moved to be an inner class, since it's not used
anywhere else and since doing this makes it a little easier to move
things around.
PiperOrigin-RevId: 367398147
We added a source that allows mixed placeholder and non-placeholder
periods, but have no way to denote that in the Timeline because the
placeholder flag only exists on Window level. This causes a bug if
the first item in a concatenation has a window-period offset and the
player can't detect whether it's still a placeholder or not.
Adding this flag to Period allows the player to detect this reliably.
In addition we need to make sure that re-resolving pending positions
only happens for the first placeholder period where the window-offset
can actually change. As all subsequent periods have to start at position
0, so they don't need to be re-resolved (and shouldn't).
PiperOrigin-RevId: 367171518
* @Nullable is not a TYPE_USE annotation, so should appear before any modifiers and after Javadocs.
(see go/java-style#s4.8.5-annotations)
This CL looks good? Just LGTM and Approve it!
This CL doesn’t look good? This is what you can do:
* Suggest a fix on the CL (go/how-to-suggest-fix).
* Revert this CL, by replying "REVERT: <provide reason>"
* File a bug under go/error-prone-bug for category ErrorProneStyle if the change looks generally problematic.
* Revert this CL and not get a CL that cleans up these paths in the future by
replying "BLOCKLIST: <provide reason>". This is not reversible! We recommend to
opt out the respective paths in your CL Robot configuration instead:
go/clrobot-opt-out.
This CL was generated by CL Robot - a tool that cleans up code findings
(go/clrobot). The affected code paths have been enabled for CL Robot in //depot/google3/java/com/google/android/libraries/exoplayer/METADATA which is reachable following include_presubmits from //depot/google3/third_party/java_src/android_libs/exoplayer/METADATA.
Anything wrong with the signup? File a bug at go/clrobot-bug.
#codehealth
PiperOrigin-RevId: 367053059
- 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 reverts
<unknown commit>
Which was a temporary workaround for Issue: #1874
Also add a loop to ensure we process as many metadata items as
applicable in each render() call.
PiperOrigin-RevId: 366965504
LSC: go/checker-lsc
Tested:
Sample tests for this CL passed, but some tests failed during the TGP run. Test failures are believed to be unrelated to this CL
PiperOrigin-RevId: 366804637
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
The condition is meant to be unblocked whenever the constructor is
left. This should include unchecked exceptions (that may be thrown
due to bugs in the dependent components, or user-inhected factories)
PiperOrigin-RevId: 366235361
The new onPositionDiscontinuity callback contains sufficient information, so
that this former workaround to obtain the position before a seek is no longer
needed.
PiperOrigin-RevId: 365993937
Aims to achieve visibility parity with MediaCodecRenderer#onQueueInputBuffer.
Allows measuring the time when the codec queue the first input buffer in the codec. Which means the Codec has been initialized and is about to start decoding.
It also allows measuring how long it takes for the Codec to render its first frame.
PiperOrigin-RevId: 365906756
If the player is created on a background thread (which is allowed
as the only exception to the access-on-one-thread-only rule), it
may happen that a callback on the main thread tries to access the
player before the constructor even finished. This is dangerous and
can cause exceptions due to uninitialized variables.
To solve this, we can make sure that every player access is blocked
until the constructor finished. Blocking is safe because the
constructor itself is not doing any blocking work or acquiring locks.
The thread verification method is already called on every entry
point to the player, so we can reuse the same method for checking.
PiperOrigin-RevId: 365792949
The extended onPositionDiscontinuity callback can be used to improve some
listener classes:
- Listening to onTimelineChanged to detect discontinuities is no longer needed.
- Listening to onSeekStarted is no longer needed as the start position is part
of the onPositionDiscontinuty callback.
- The exact old position is also useful for media time history logging.
As a side effect, removing onSeekStarted handling from PlaybackStatsListener
fixes Issue: #8675 that was caused by the special EventTime handling for
onSeekStarted.
PiperOrigin-RevId: 365558959
A TrackGroup must contain the same content in all Formats (except for
the quality, encoding etc). Verify that the language and role flags
are the same and log an error if don't match. Don't throw to avoid
breaking existing use cases that just happen to work by chance.
PiperOrigin-RevId: 365539240
The hacky workaround for APIs 29/30 doesn't work on API 31. Instead,
we can use the onDisplayInfoChanged callback, that is accessible from
API 31.
PiperOrigin-RevId: 364997282
The BasePlayer implementation of add/remove
Listener knows about Components.
As those are removed from the Player
interface, the implementation of those
methods needs to be moved down in Player
implementations.
This commit makes no functional change.
PiperOrigin-RevId: 364985291
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
The main user of the Util method is the bandwidth meter to set the
initial network type. If this is the first call to the
NetworkTypeObserver, then we should also allow the first update to
a known network type even if no reset on network type is activated.
The other uses are analytics listeners that check the network type
at certain events. This can just use the lookup method of the
NetworkTypeObserver.
PiperOrigin-RevId: 363670771
- Update the three `HttpDataSource` implementations to use the
Content-Range response header to determine when this is the
case. The Content-Range header is included when the status
code is 416. See [here](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/416).
- Update `ByteArrayDataSource` to conform to the requirement.
- Update `DataSourceContractTest` to enforce the requirement.
PiperOrigin-RevId: 363642114
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
- SampleQueue.peek is replaced with SampleQueue.read with
FLAG_PEEK. This also exposes peek functionality through
SampleStream.
- Use of DecoderInputBuffer.isFlagsOnly is replaced with
FLAG_OMIT_SAMPLE_DATA. This flag can be used with or
without FLAG_PEEK, where-as previously the read position
would never be advanced for an isFlagsOnly buffer.
- formatRequired is replaced with FLAG_FORMAT_REQUIRED.
PiperOrigin-RevId: 363460105
In order to detect 5G-NSA, we need to remove Util.getNetworkType
and replace it with a class that is actively listening to changes.
The network type observation in DefaultBandwidthMeter already provides
the right framework to integrate this and in order to facilitate
further changes we move it to a separate Util class.
The overall effect of this change should be a complete no-op.
PiperOrigin-RevId: 363384567
Assert that opening the DataSource at the end of the resource
results in only RESULT_END_OF_INPUT being read.
open() and read() are still permitted to throw, although this
permissiveness will be removed in subsequent commits.
PiperOrigin-RevId: 362905314
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
When comparing stream bitrate with available (allocated) bandwidth,
we need to take the playback speed into account. In the current
calculation, this can happen on both sides of the equation, but we
take the time to first byte into account, we need to move the speed
into the available, allocated bandwidth.
This change moves the speed adjustment to the bandwidth calculation
side in AdaptiveTrackSelection.
PiperOrigin-RevId: 362540071
If none of the extractors successfully sniff the content then we will fall back
to inferred file types in the following order:
- Webvtt if the media comes from a SUBTITLE EXT-X-MEDIA.
- The type of media declared in the HTTP "Content-Type" header.
- The type of the media according to the file extension.
- Transport stream.
Issue: #8700
PiperOrigin-RevId: 362519769
Part of aligning HttpDataSource behavior will require adding
logic that's common across the DataSource implementations. This
change establishes a util class to house it, and moves a bit of
existing logic that's related and can be easily shared into it.
There is one small behavior change in this CL, which is that our
handling of Content-Range response headers can now parse the body
length if the "document size" part of the Content-Range is unknown,
for example "bytes 5-9/*". Previously the pattern we were matching
to required the "size" part to be set, for example "bytes 5-9/100",
despite the fact we don't need or use it.
PiperOrigin-RevId: 362396976
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
Add additional assertions to try to figure out why
the tests are flaky when run in the test harness.
Failure could not be reproduced locally even after 4000 run.
PiperOrigin-RevId: 362282251
TransferListener has the contract to have exactly one onTransferEnd per
onTransferStart, so the test can both assert that onTransferInitializing
is called, but not onTransferEnd (even after calling close).
PiperOrigin-RevId: 362262078
It's more flexible to use FakeDataSource, since it allows to testing
different upstream behaviors (e.g., upstream not being able to resolve
the content length).
PiperOrigin-RevId: 362072899
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
- Split text emphasis mark and style into two IntDefs
- Represent textEmphasis="none" with a span rather than null
- Fixed bugs in the style parsing logic
- Refactor TextEmphasis class to support different ordering of styles
- Merge RubySpan.Position and TextEmphasisSpan.Position
- Remove TTML constructs from Spanned classes
exp (ExoPlayer prepare)
ffr (First Frame Rendered)
psr (Player State Ready).
2) Modifies aci/acc vci/vcc to report timing from ExoPlayer Playback thread.
3) Fix to report pvri and pari for every playback.
and other minor bug fixes.
PiperOrigin-RevId: 360228206
Includes fixes for the HTTP implementations, which previously
broke this contract specifically in the case when a server
responds to a range request with a HTTP 200 response. To fix
this case, skipping to the requested position is moved from
read() to open(). As a side effect, this nicely simplifies
CronetDataSource!
PiperOrigin-RevId: 359737301
The API is a lot more useful if apps can rely on the fact
that the gain is linear and applied to all channels.
This is already guaranty by AudioTrack and should be too
by any reasonable implementation.
PiperOrigin-RevId: 359706113
Given we're proposing to make reading from the end a non-error case,
it's important to check that we return the right thing from open(),
and that we read the right thing (i.e., nothing) once opened.
For now, this test allows quite a bit of permissiveness, in line
with other related tests. This will be tightened up in due course.
PiperOrigin-RevId: 359504075
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 constant values are the same, so this is a no-op, but for
correctness, we should pass the defined constant that the API
documents itself to accept.
PiperOrigin-RevId: 359293471
The new name reflects that it also waits for previously-used renderers
to be disabled.
Also fix some broken javadoc. These methods changed signature in
ea347a464a
PiperOrigin-RevId: 359253177
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
Currently, this only asserts that *if* an exception is thrown, it
must be a position-out-of-range exception as determined by
DataSourceException.isCausedByPositionOutOfRange.
Issue: #7326
PiperOrigin-RevId: 359092124
- 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
Assert that an exception is not thrown from DataSource.open
if the DataSpec's start position is valid but its end position
extends beyond the end of the data.
HTTP based DataSource implementations have no good way of
knowing when this is the case, so it makes sense to make this
the required behaviour, rather than requiring an exception to
be thrown or allowing both.
There are also use cases where the caller may want to use the
end position as an upper bound, without knowing for sure how
long the content is. An example of this use case is wanting to
pre-cache the first N bytes of a stream. This implies that any
exception should be thrown after reading to the end of the
data, rather than preemptively in open.
Issue: #7326
PiperOrigin-RevId: 359063721
- 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
- Make it a property of the DataSource, not of the resource.
- Apply it only when a contract test reads using an
unbounded DataSpec.
PiperOrigin-RevId: 358997735
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 a no-op assuming the class is always used correctly.
When release causes referenceCount to reach zero there can be at most
one EventDispatcher still connected (which is the one that must be
passed to that final release() call), so we can always pass the event
directly to the EventDispatcher passed in to release().
PiperOrigin-RevId: 358794004
There are two different patterns we use at the moment:
1. Call both deprecated and non-deprecated method from call site with
no default method implementation body.
2. Use default method of non-deprecated method to call deprecated
method.
Pattern 1 is easier to reason about as it makes the calls more explicit,
so changing all usages of pattern 2 to pattern 1.
PiperOrigin-RevId: 358769803
This adds an optional DrmSessionManager#preacquireSession() method
and implements it on DefaultDrmSessionManager.
The manager doesn't promise to keep the preacquired sessions alive, and
will proactively release them if a ResourceBusyException suggests the
device is running out of available sessions in the underlying framework.
In a future change, SampleQueue will preacquire sessions on the loading
thread and keep track of preacquired 'references', releasing them
when seeking or clearing the queue.
Issue: #4133
PiperOrigin-RevId: 358381616
We already report these errors through callbacks to interested listeners.
However, to ease debugging with bugreports and local error detection,
it's helpful to also log these non-fatal execptions to logcat. Otherwise
nothing in logcat indicates that the player recovered from an exception.
Issue: #6384
PiperOrigin-RevId: 357923899
This is preferable to just logging to LogCat so that listeners can
report this to analytics systems if required.
Issue: #6384
PiperOrigin-RevId: 357906079
The SampleStream.readData contract is that when reading a sample
with a flags-only buffer, the buffer timestamp and flags should
be set and the read position should not be advanced.
#minor-release
PiperOrigin-RevId: 357842130
This type is different to the selection reason, which is
dynamic (i.e., corresponds to the individual selected track,
which can change during playback). The static type is
exposed via TrackSelection, where-as the selection reason
will be internal to the core (i.e., player) module.
PiperOrigin-RevId: 357578201
These have limited value, and are confusing because they're only
actually used if the override only selects a single track (if the
override is an adaptive selection then the values are never used).
The simpliest path forward is to remove them.
PiperOrigin-RevId: 357573186
It allows Bundleable classes throw a RuntimeException which is broader
than IAE. Now, Bundleable implementation may utilize checkNotNull for
brevity.
PiperOrigin-RevId: 357546375
The source can be used in compositions (in fact, every source is
automatically used in an internal composition when constructing the
playlist), and there is not really a concept of top-level media source
any more since the Player supports playlists.
The actual restriction is that the content media source needs to have
exactly one period to be able to create a SinglePeriodAdTimeline.
#minor-release
PiperOrigin-RevId: 357544191
The previous logic was changed under the assumption that the first box
inside a meta box was not always an hdlr box, but this is not true.
#minor-release
PiperOrigin-RevId: 357200713
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
It's used by the UI and mediasession modules. We may be able to move
it into the UI module if/when the mediasession module goes away.
PiperOrigin-RevId: 356734939
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
ControlDispatcher and DefaultControlDispatcher also need
to move to common for the UI module. As does PlaybackPreparer,
although that will be removed entirely in a future release.
PiperOrigin-RevId: 356467394
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
We currently block the loading thread until the calculated load
time has past and then unblock again by a message sent from the
playback thread. However, because the loading thread itself is not
using a Looper and runs freely, we don't control when the short
calculations on the loader thread that determine how long we have
to wait are happening, and we also don't control how long it takes
to start and stop this thread.
To solve these problems and to make the playback deterministic we
can
1. Send a message on the playback thread to block until the loader
thread has started.
2. Block the playback thread whenever a loading thread is doing its
short calculation of wait times. The playback thread knows when it
can continue because loading either enter a new waiting state for
a simulated load time or loading is finished completely.
3. Also wait on the playback thread until the loader has shut down.
As this is waiting for a message on the playback thread, we can
achieve this by sending messages to ourselves at the current time
until the loader is shut down.
All 3 steps together ensure that the loading thread interaction is
compeltely deterministic when simulating bandwidth profiles with the
BandwidthProfileDataSource. As we need to notify the source before and
after the load started/finished, we also need a small wrapper for the
chunk source when running the playback.
PiperOrigin-RevId: 355810408
- When throwing a recoverable error from a renderer, it's important to understand
exactly how the player will attempt recovery. Clarify the documentation to
make this explicit.
- Rename some methods/constants to make it clear that error recovery is specific
to renderer errors. The current recovery mechanism only makes sense for
renderer errors. Making the naming renderer specific avoids reader doubt that
the implementation doesn't appear to be generic enough for other types of
errors.
PiperOrigin-RevId: 355650945
It's for classes to clearly denote they support bundling and it gives
us a good place to document the best practice to implement fromBundle.
PiperOrigin-RevId: 355609942