Commit graph

170 commits

Author SHA1 Message Date
andrewlewis
ce8bb26802 Fix postroll content complete notifications
On reaching the end of the content we would notify content complete
and skip unplayed ads, causing a timeline change. That timeline change
was handled in a way that caused a further timeline change in the
2.11.6 release, where we don't yet deduplicate no-op Timeline changes,
causing repeated timeline changes indefinitely.

At tip-of-tree, the timeline wouldn't refresh repeatedly. However the
code for sending content complete at the point of transitioning to
play a preloaded postroll ad was not correct in that it didn't mark
previous ads as skipped. Instead they happened to be marked as
skipped later on due to the timeline change handling content
completion code triggering again.

Fix this by only marking ads as skipped when content completes once,
to avoid the duplicate timeline change, and moving the skipped ad
marking so it happens in the same place as notifying content complete.

PiperOrigin-RevId: 318454908
2020-06-26 14:21:57 +01:00
andrewlewis
df10fdf773 Fix handling of postrolls preloading
The IMA SDK now preloads postrolls which is great as we no longer need
to rely on detecting buffering at the end of the stream to trigger
playing postrolls.

Add in the required logic to detect the period transition to playing
the postroll.

Issue: #7518
PiperOrigin-RevId: 317610682
2020-06-23 15:58:42 +01:00
andrewlewis
0ffe747076 Fix incorrect rounding of ad cue points
We currently get float ad cue points from IMA, but store these as
longs in microseconds. The cast from double to long would take the
floor of the value, which could lead to stored ad cue points being
off-by-one. Use Math.round to avoid this.

ImaAdsLoader also has code to map a double AdPodInfo position (which
should match a cue point) onto the corresponding ad group index by
searching the long ad cue points. Match the calculation used where we
map float cue points, including narrowing the position to a float
first to avoid regressions if IMA SDK behavior changes to represent
positions in more than float precision later, and also remove the
requirement that the ad positions match exactly as a defensive
measure.

PiperOrigin-RevId: 317607017
2020-06-23 15:58:36 +01:00
andrewlewis
49951d4f87 Workaround unexpected discard of preloaded ad
After an ad pod coming up has preloaded, if the user seeks before it
plays we get pauseAd/stopAd called for that ad pod. Also, the ad will
not load again. Work around this unexpected behavior by handling
pauseAd/stopAd and discarding the ad.

In future, it's likely that the IMA SDK will stop calling those
methods, and will loadAd again for the preloaded ad that was
unexpectedly discarded. This change should be compatible with that,
because the ad won't be discarded any more due to not calling stopAd.

Issue: #7492
PiperOrigin-RevId: 316873699
2020-06-17 20:36:02 +01:00
andrewlewis
fc76dbfad4 Remove some ad playback state change requirements
Ads can appear due to asynchronous ad tag requests completing after
earlier ads in a pod have loaded, so remove the requirement that the
ad count can't change. The MediaPeriodQueue should handling discarding
buffered content if an ad appears before already buffered content, so
I think this case is actually handled correctly by the core player
already.

Also remove the requirement that an ad URI can't change. This is a
defensive measure for now, but it's likely that a later fix in the IMA
SDK for an issue where loadAd is not called after preloading then
seeking before a preloaded ad plays will result in loadAd being called
more than once, and I think it's possible that the second call to
loadAd may have a different URI. Because the ad URI should only change
after an intermediate seek to another MediaPeriod, there shouldn't be
any problems with buffered data not getting discarded.

Issue: #7477
PiperOrigin-RevId: 316871371
2020-06-17 20:35:31 +01:00
andrewlewis
5fd287b340 Move IMA SDK callbacks into inner class
The release() method was added in the recent IMA API changes for
preloading and now 'collides' with the ExoPlayer AdsLoader release
method. This led to all ads completing being treated as a call to
completely release the ads loader, which meant that the ad playback
state was not updated on resuming after all ads had completed, which
in turn led to playback getting stuck buffering on returning from the
background after all ads played.

Move the IMA callbacks into an inner class to avoid this.

Issue: #7508
PiperOrigin-RevId: 316834561
2020-06-17 20:35:04 +01:00
ibaker
a0e90ce1ff Pull IMA cuePoints -> adGroupTimesUs logic into a helper class
We're then able to use this same helper class from tests, to avoid
running into spurious failures caused by long microseconds being
round-tripped through float seconds.

PiperOrigin-RevId: 316435084
2020-06-17 20:33:53 +01:00
andrewlewis
f1197d8af3 Handle errors in all VideoAdPlayer callbacks
Some but not all VideoAdPlayer callbacks from the IMA SDK included
defensive handling of unexpected cases. Add the remaining ones.

Issue: #7492
PiperOrigin-RevId: 316082651
2020-06-17 20:26:30 +01:00
andrewlewis
8ab3fab4c1 Fix catch type in ImaAdsLoader defensive checks
PiperOrigin-RevId: 316079131
2020-06-17 20:25:21 +01:00
andrewlewis
e261b8d0ef Allow skipping the ad before the start position
PiperOrigin-RevId: 315867160
2020-06-17 20:20:33 +01:00
andrewlewis
80f4197e0f Separate ads rendering and AdsManager init
In a later change it will be necessary to be able to destroy the ads
manager if all ads are skipped while creating ads rendering settings.
This change prepares for doing that by not having the ads manager
passed into the method (so the caller can null or initialize it).

PiperOrigin-RevId: 315488830
2020-06-17 20:15:52 +01:00
andrewlewis
5d74fced1d Add tests for resuming ad playbacks
This is in preparation for refactoring the logic to support not
playing an ad before the resume position (optionally).

PiperOrigin-RevId: 315431483
2020-06-17 20:15:46 +01:00
andrewlewis
28c5fa665f Improve ImaAdsLoaderTest ad duration handling
Previously the fake ads loader listener would always pass the same ad
durations to the fake player, but actually the known ad durations can
change during playback.

Make the fake behavior more realistic by only exposing durations for
ads that have loaded.

PiperOrigin-RevId: 314956223
2020-06-17 20:15:34 +01:00
andrewlewis
51a3f214ed Fix handling of fetch errors for post-rolls
The ad break time in seconds from IMA was "-1" for postrolls, but this didn't
match C.TIME_END_OF_SOURCE in the ad group times array.

Handle an ad break time of -1 directly by mapping it onto the last ad group,
instead of trying to look it up in the array.

PiperOrigin-RevId: 312064886
2020-05-29 22:29:29 +01:00
andrewlewis
51b2a0f7a9 Add support for timing out ad preloading
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
2020-05-29 22:29:14 +01:00
andrewlewis
e482aa2be8 Fix method ordering in ImaAdsLoader
Put static methods at the end.

Also add a couple of missing parameter name comments.

PiperOrigin-RevId: 311077684
2020-05-29 22:18:15 +01:00
andrewlewis
929b60e209 Improve DEBUG logging in ImaAdsLoader
Log content progress events, as these are helpful to debug triggering of events
based on the content progress.

Don't log AD_PROGRESS events as they occur several times per second while ads
are playing, and the verbosity makes logs difficult to read.

PiperOrigin-RevId: 311077302
2020-05-29 22:17:51 +01:00
andrewlewis
5529c124fe Remove deprecated symbols in ImaAdsLoader
PiperOrigin-RevId: 310901647
2020-05-29 22:17:24 +01:00
andrewlewis
3b99a84dae Migrate to new IMA preloading APIs
issue:#6429
PiperOrigin-RevId: 309906760
2020-05-29 22:15:30 +01:00
andrewlewis
de03e389c0 Enable nullness checking for the IMA extension
adPlaybackState is now non-null, and the uninitialized case is covered by a new
boolean hasAdPlaybackState. Position progress updates are now non-null and
initialized with IMA's VIDEO_TIME_NOT_READY constant.

Also fix some misc code issues:
- Remove empty branch for SmoothStreaming (Android Studio warns about this).
- Tidy onTimelineChanged and onPositionDiscontinuity and the methods they call
  to improve naming.
- Remove logging for IMA events after release, as these methods are expected to
  be called in the current IMA SDK behavior.

PiperOrigin-RevId: 308977116
2020-05-29 21:58:59 +01:00
andrewlewis
6e66dc02fb Replace IMA ad tag fakes with mocks
The mocking setup is quite messy/unclear compared to the fakes, but it seems
worth switching over because IMA API changes have already required changes
to fakes in the past, and there are more API changes in the version we are
about to upgrade to. This change should generally remove the need to keep
the fakes up-to-date.

PiperOrigin-RevId: 308819176
2020-05-29 21:58:46 +01:00
tonihei
67d1b728d3 Clarify/fix position reference points for AdPlaybackState.
The positions were interchangeably used with window and period
positions. This change more clearly ensures that all positions in the
AdPlaybackState are based on periods and that we use the right adjustments
for all usages.

PiperOrigin-RevId: 297811633
2020-05-29 21:50:07 +01:00
tonihei
d1b900604a Add test to ensure AdsLoader is initialized.
This tests explicitly that initialization happens even if the Timeline
is a placeholder.

No other change is needed. While the Timeline is still a placeholder
ImaAdsLoader.getCurrentPeriodPosition will return 0 and trigger
pre-rolls (intended behaviour) and it doesn't matter whether the
actual initial period position may be somewhere else.

PiperOrigin-RevId: 298833867
2020-05-29 21:42:22 +01:00
Andrew Lewis
03be1551a7 Clean up player event handling
This change is similar to e8293b92d8
but without relying on new player events that haven't been released
yet, to make it easier to merge changes related to ImaAdsLoader on
top.
2020-05-29 21:15:17 +01:00
andrewlewis
b3de2b08d4 Inline ENABLE_PRELOADING
ImaAdsLoader relies on preloading being enabled (it doesn't
work without it) so we may as well remove the constant to
avoid potential confusion.

PiperOrigin-RevId: 284951356
2020-05-29 21:15:17 +01:00
andrewlewis
f052e89a8f Pass app context to the IMA SDK
Notes: this doesn't fix the current issue where the component containing the
ad overlay view leaks, but is good practice anyway.
PiperOrigin-RevId: 308582036
2020-05-27 20:23:57 +01:00
andrewlewis
5f465f770b Remove AdsManager listeners on release
Issue: #6687
PiperOrigin-RevId: 283023548
2019-12-06 22:37:35 +00:00
bachinger
e6e2dcc58d Rollback of 36f8bd78f7
*** Original commit ***

Rollback of 4ad4e3e4fc

*** Original commit ***

Rollback of 3b22db33ba

*** Original commit ***

add top-level playlist API to ExoPlayer

Public design doc:
https://docs.google.com/document/d/11...

***

PiperOrigin-RevId: 275813737
2019-10-30 08:46:42 +00:00
bachinger
36f8bd78f7 Rollback of 4ad4e3e4fc
*** Original commit ***

Rollback of 3b22db33ba

*** Original commit ***

add top-level playlist API to ExoPlayer

Public design doc:
https://docs.google.com/document/d/11h0S91KI5TB3NNZUtsCzg0S7r6nyTnF_tDZZAtmY93g

Issue: #6161

***

***

PiperOrigin-RevId: 275276158
2019-10-18 17:42:03 +01:00
tonihei
dd4f9bcaae Add Timeline.Window.isLive
This flag is currently merged into Window.isDynamic, which isn't always true
because
1. A window can be dynamic for other reasons (e.g. when the duration is still
missing).
2. A live stream can be become non-dynamic when it ends.

Issue:#2668
Issue:#5973
PiperOrigin-RevId: 271999378
2019-10-02 21:28:43 +01:00
bachinger
4ad4e3e4fc Rollback of 3b22db33ba
*** Original commit ***

add top-level playlist API to ExoPlayer

Public design doc:
https://docs.google.com/document/d/11h0S91KI5TB3NNZUtsCzg0S7r6nyTnF_tDZZAtmY93g

Issue: #6161

***

PiperOrigin-RevId: 270728267
2019-10-02 21:25:39 +01:00
bachinger
3b22db33ba add top-level playlist API to ExoPlayer
Public design doc:
https://docs.google.com/document/d/11h0S91KI5TB3NNZUtsCzg0S7r6nyTnF_tDZZAtmY93g

Issue: #6161
PiperOrigin-RevId: 269584512
2019-09-18 23:23:13 +01:00
olly
a02237de20 Fix imports
PiperOrigin-RevId: 266676413
2019-09-01 22:03:52 +01:00
andrewlewis
34cc5f4cb8 Defer adsManager.init until the timeline has loaded
If the app seeks after we get an ads manager but before the player exposes the
timeline with ads, we would end up expecting to play a preroll even after the
seek request arrived. This caused the player to get stuck.

Wait until a non-empty timeline has been exposed via onTimelineChanged before
initializing IMA (at which point it can start polling the player position). Seek
requests are not handled while an ad is playing.

PiperOrigin-RevId: 265058325
2019-08-23 17:04:01 +01:00
tonihei
51476fa2c8 Prevent NPE in ImaAdsLoader onPositionDiscontinuity.
Any seek before the first timeline becomes available will result in a NPE.
Change it to handle that case gracefully.

Issue:#5831
PiperOrigin-RevId: 264603061
2019-08-23 17:02:26 +01:00
andrewlewis
c361e3abc3 Fix handling of delayed AdsLoader.start
AdsMediaSource posts AdsLoader.start to the main thread during preparation, but
the app may call AdsLoader.setPlayer(null) before it actually runs (e.g., if
initializing then quickly backgrounding the player).

This is valid usage of the API so handle this case instead of asserting. Because
not calling setPlayer at all is a pitfall of the API, track whether setPlayer
has been called and still assert that in AdsLoader.start.

PiperOrigin-RevId: 264329632
2019-08-23 17:01:39 +01:00
tonihei
346f8e670a Turn on non-null-by-default for most extensions.
PiperOrigin-RevId: 261700729
2019-08-05 20:27:43 +01:00
bachinger
49a2e5a5cb add manifest to Timeline.Window
- Remove manifest argument from callbacks of Player.EventListener and
  SourceInfoRefreshListener. Instead make it accessible through
  Player.getCurrentManifest() and Timeline.Window.manifest.
- Fix all MediaSource implementation to include the manifest in the
  Timeline instead of passing it to the SourceInfoRefreshListener.
- Refactor ExoPlayerTestRunner, FakeTimeline, FakeMediaSource to
  reflect these changes and make tests pass.

PiperOrigin-RevId: 257359662
2019-07-14 16:20:45 +01:00
andrewlewis
b1790f9dcc Fix IMA test build issue
PiperOrigin-RevId: 256545951
2019-07-05 17:32:38 +01:00
andrewlewis
9905432546 Fix ad pod index offset calculation without preroll
Issue: #5928
PiperOrigin-RevId: 254379085
2019-06-21 18:23:57 +01:00
olly
f90cbcdffd Add MRC continuous play API to IMA android sdk.
Details in
go/ima-mrc-continuous-play

Corresponding js webcore changes is in <unknown commit>.

NoExternal

PiperOrigin-RevId: 253585186
2019-06-18 17:46:42 +01:00
olly
3afdd7ac5a Put @Nullable annotation in the right place
PiperOrigin-RevId: 249828748
2019-05-30 15:10:55 +01:00
tonihei
33c677846a Use versioned manifest in all Robolectric tests.
We are currently defaulting to targetSdk=1 as no targetSdk is specified. Only
tests which explicitly ask for another SDK use another test SDK. With the
versioned manifest, all tests run using the targetSDK by default.

PiperOrigin-RevId: 249060796
2019-05-21 13:51:43 +01:00
tonihei
819d589b22 Ignore empty timelines in ImaAdsLoader.
We previously only checked whether the reason for the timeline change is
RESET which indicates an empty timeline. Change this to an explicit check
for empty timelines to also ignore empty media or intermittent timeline
changes to an empty timeline which are not marked as RESET.

Issue:#5831
PiperOrigin-RevId: 248499118
2019-05-16 13:40:04 +01:00
tonihei
0bb32a8f09 Add IntDef for Player states.
PiperOrigin-RevId: 245925254
2019-04-30 22:07:47 +01:00
tonihei
8e80acd18f Use androidx.test and extensions.
This replaces the deprecated usages of RobolectricTestRunner and
RuntimeEnvironent and fully migrates the tests to androidx.

PiperOrigin-RevId: 238011667
2019-03-15 04:53:12 +00:00
olly
0622afe170 Migrate to androidx
Issue: #5489
PiperOrigin-RevId: 234507428

Add missing annotation dependency

Issue: #5489
PiperOrigin-RevId: 234566177
2019-02-19 13:22:54 +00:00
tonihei
edabbd52d0 Update Robolectric and Truth.
PiperOrigin-RevId: 233612344
2019-02-18 15:59:32 +00:00
andrewlewis
3a5ed6b889 Skip ad group on unknown load error
PiperOrigin-RevId: 233576600
2019-02-18 15:58:52 +00:00
andrewlewis
56944caa21 Allow registration of control overlays for ad viewability
Switch from passing an ad UI ViewGroup to passing an object that can also
provide information about controls overlays.

Also switch to using a dedicated overlay for ads instead of the overlay frame
layout, which apps have easy access to.

PiperOrigin-RevId: 233393500
2019-02-18 15:58:06 +00:00