Switch to snapshot Robolectric to pick up the latest version of shadows
required by MediaCodecVideoRendererTest and MediaCodecAudioRendererTest.
PiperOrigin-RevId: 312030332
Detect stuck buffering cases in ImaAdsLoader, and discard the ad group after
a timeout. This is intended to make the IMA extension more robust in the case
where an ad group unexpectedly doesn't load.
The timing out behavior is enabled by default but apps can choose to retain
the old behavior by setting an unset timeout on ImaAdsLoader.Builder.
PiperOrigin-RevId: 311729798
EventTime contains information about when an event happened and where
it belongs to. Both places can be fully described using timeline, window
index, media period id and position.
Right now, only the information for where the event belongs to is fully
contained in EventTime, whereas the time when the event happened only has
the position, and none of the other information (timeline, window, period).
This change adds the missing information, so that the EventTime can easily
be used without having access to the Player. This also ensures Event
metadata is self-contained and can be stored and reused later.
issue:#7332
PiperOrigin-RevId: 311727004
The only reason to require a context for creating an instance of
DefaultMediaSourceFactory is creating a user agent. DownloadHelper
has a bunch of static methods that need to instantiate a
DefaultMediaSourceFactory without a Context. By adding a setter for
the user agent we can remove that restriction and use a default user
agent.
PiperOrigin-RevId: 311291603
We aim for all SinglePeriodTimelines to set window.mediaItem and hence want to eliminate all constructors not passing a media item. The constructor removed in this CL is the easiest one to remove and fix in google3. It is still a breaking change for external ExoPlayer user who provide a custom media source with this timeline.
PiperOrigin-RevId: 311291493
FFmpeg requires input buffers to be sized larger than the size
of the data they contain. This is to allow optimized decoder
implementations that read data in fixed size chunks, without
the risk of such decoders reading beyond the end of the buffer.
Issue: #2159
PiperOrigin-RevId: 310946866
The tts:textAlign property only applies to <p> elements, which
correspond 1:1 with ExoPlayer Cue objects, so we can use
Cue.textAlignment to store this info instead of encoding it in
the span-styled text.
This will mean that TTML subtitles used with
SubtitleView#setApplyEmbeddedStyles(false) will start respecting
the tts:textAlign properties from the source data (currently this
information is stripped when we remove all span styling). I think this
is working-as-intended, we respect alignment of other subtitle types
(e.g. WebVTT) when applyEmbeddedStyles=false. We also respect all other
'positioning' related properties in this case e.g. Cue.position and
Cue.line.
PiperOrigin-RevId: 310895499
When operating the MediaCodec in asynchronous mode, we are seeing
NPEs raised from the DefaultAudioSink because output buffers are pushed
to the DefaultAudioSink with the DefaultAudioSink not configured yet.
This is possible to happen if an output buffer is passed with
MediaCodecAudioRenderer.processOutputBuffer() before an output format
change.
One possible code path to trigger this is when an output format change
is pending and we flush MediaCodec (e.g. for a seek): the callback is
waiting in the looper's queue but we ignore all currently queued
callbacks after a flush().
This commit checks for a pending output format change during a flush():
if one exists, and the next MediaCodec output callback right after the
flush() is an output buffer (and not a new output format), then the
pending output format is propagated first.
The only adapter that needs to change is the
AsynchronousMediaCodecAdapter which previsouly deleted all pending
callbacks immediately on flush(). The AsynchronousMediaCodecAdapter now
needs to also handle every enqueued callback in order to identify is
there's a pending output format change.
Testing: added unit tests for the new code. I have verified that if we
pass an output buffer to the audio renderer before the output format, it
will result on the specific NPE, but I cannot reproduce the base
scenario (an output format change is pending when flushing) on a real
device because we can't know if an output format is indeed pending.
PiperOrigin-RevId: 310885283
This allows properties to propagate when switching view types
(e.g. bottomPaddingFraction).
It also allows the style-stripping code to be pushed up to SubtitleView
and therefore shared.
PiperOrigin-RevId: 310353534
Fixes AsynchronousMediaCodecBufferEnqueuerTest broken tests by
enqueueing input buffers that have previously been dequeued from the
MediaCodec.
The test assumes that the shadow MediaCodec implementation can dequeue
at least 10 input buffers before queueing them back. Although fragile,
it seems to work with the current robolectric shadow MediaCodec. This is
at the moment preferred compared to making the test more complicated.
PiperOrigin-RevId: 310325096
If the condition isn't fulfilled, they currently block until the
test runner times out the test. Our usual approach is to timeout
in the test itself so that the error message is clearly showing the
blocked condition.
Also clean-up some documentation.
PiperOrigin-RevId: 309930198
Now that MediaCodec is not use in passthrough, no
MediaCodec should be created in this mode.
Additionally, do not instantiate a MediaCodec in passthrough
#exo-offload
PiperOrigin-RevId: 309916131
- Stop throwing InterruptedException from CacheUtil. When a CacheUtil operation
throws or returns, the caller should always check its own state to determine
whether they canceled the operation. If a caller is trying to catch
InterruptedException separately to IOException to do something different in
that case, they're probably doing the wrong thing. So it's simpler, and probably
less error prone, just to throw an IOException in the case of interruption.
- Throwing InterruptedIOException is also consistent with what our Extractor and
DataSource implementations do.
Issue: #5978
PiperOrigin-RevId: 309411556
We keep an index hint for the next pending player message. This hint
wasn't updated correctly when messages are removed due to a timeline
update.
This change makes sure to only use the hint locally in one method so
that it doesn't need to be updated anywhere else and also adds the "hint"
suffix to the variable name to make it clearer that it's just a hint and
there are no guarantees this index actually exists anymore.
issue:#7278
PiperOrigin-RevId: 309217614
testSubtitleEventTimes/IndicesHelper make assertions that only happen
to be the same because values in two different constants match up. It
seems much better to explicitly put the assertions in each test.
The other assert methods are just obscuring the underlying call to
Truth.
PiperOrigin-RevId: 309022044
Steps 4-10 of https://www.w3.org/TR/webvtt1/#cue-computed-line
This part is harder to fit into our code structure because it depends on
how many cues are simultaneously visible - so it has to go in
WebvttSubtitle not WebvttCueParser (which only deals with individual
cues in isolation).
This removes the `isNormal()` method that was trying to approximate
the correct behaviour.
PiperOrigin-RevId: 309021686
The player's initial PlaylistTimeline has no ad cue points, so its first
MediaPeriodId has no nextAdGroupIndex. When the AdsMediaSource provides its
first timeline, the cue points become known. For the case where a preroll cue
point appeared, the preroll was detected due to isAd changing on the
MediaPeriodId. For the case where a midroll/postroll cue point appeared, the
MediaPeriodId was actually treated as the same, which leads to keeping the
unclipped original MediaPeriod.
Fix this behavior by checking for nextAdGroupIndex becoming set or decreasing.
PiperOrigin-RevId: 308974490
Its only real purpose is to encapsulate a download ID, but it doesn't actually save
any code, and arguably makes it more complicated by having multiple lists of
Downloader instances, indexed by key, and also because it's another (undocumented)
class to understand.
This CL retains the multiple Downloader lists, but they will be flattened in a
child CL.
PiperOrigin-RevId: 308838026
DownloadRunner.getDownloader was creating Downloader instances before the actual
DownloadManager under test would have created them. Tests were then asserting and
manipulating these Downloader instances, which is quite confusing. In particular
FakeDownloader.assertDoesNotStart() is an assertion on a Downloader instance that
only makes sense when called on an instance that DownloadManager would not have
created by itself.
This change replaces FakeDownloader.assertDoesNotStart() with an assertion on
DownloadRunner that no Downloader instance has been created.
PiperOrigin-RevId: 308822398
- Assertion chaining is generally discouraged. For example, because it's harder
to determine which assertion failed given a line number.
- Also removed chaining of the form obj.actionX().assertY(), because it's easy
for someone editing the test to accidentally delete actionX() when deleting
assertY(), where-as actionX() may often be important for subsequent assertions.
PiperOrigin-RevId: 308820503
- Remove assertReleased and replace it with a proper condition variable
that's opened when Downloader.download or Download.remove finish. As
far as I can tell assertReleased was basically implementing "sleep for
10 seconds after the Downloader starts". Note fixing this properly
also makes the tests run much faster!
- Use ConditionVariable instead of CountDownLatch(1).
- Use AtomicInteger instead of volatile int because it's clearer and
allows removal of explanatory comments.
PiperOrigin-RevId: 308819204
- Improve documentation explaining the benefits of ExoPlayer's ConditionVariable
over the one that the platform provides
- Allow Clock injection
- Create TestUtil method for obtaining a ConditionVariable whose block(long)
method times out correctly when used in a Robolectric test
- Add basic unit tests for ConditionVariable
PiperOrigin-RevId: 308812698
Currently, this method is only supposed to be called before removing
the listener from the player or when releasing the player.
If called at other times, it will throw an exception later when
a playback session is ended automatically.
issue:#7193
PiperOrigin-RevId: 308254993
The first session should only be created once we have the media items
and/or called prepare. Otherwise the first session is created with
an EventTime having an empty timeline making it less useful.
issue:#7193
PiperOrigin-RevId: 308100555