mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Add a setting for enabling continuous playback
Issue: #3750 PiperOrigin-RevId: 346079830
This commit is contained in:
parent
dd782ef9b4
commit
6796c4d01c
5 changed files with 76 additions and 0 deletions
|
|
@ -45,6 +45,8 @@
|
||||||
([#3750](https://github.com/google/ExoPlayer/issues/3750)).
|
([#3750](https://github.com/google/ExoPlayer/issues/3750)).
|
||||||
* Fix a condition where playback can get stuck before an empty ad
|
* Fix a condition where playback can get stuck before an empty ad
|
||||||
([#8205](https://github.com/google/ExoPlayer/issues/8205)).
|
([#8205](https://github.com/google/ExoPlayer/issues/8205)).
|
||||||
|
* Add `ImaAdsLoader.Builder.setEnableContinuousPlayback` for setting
|
||||||
|
whether to request ads for continuous playback.
|
||||||
* Metadata retriever:
|
* Metadata retriever:
|
||||||
* Parse Google Photos HEIC motion photos metadata.
|
* Parse Google Photos HEIC motion photos metadata.
|
||||||
* FFmpeg extension:
|
* FFmpeg extension:
|
||||||
|
|
|
||||||
|
|
@ -517,6 +517,9 @@ import java.util.Map;
|
||||||
}
|
}
|
||||||
pendingAdRequestContext = new Object();
|
pendingAdRequestContext = new Object();
|
||||||
request.setUserRequestContext(pendingAdRequestContext);
|
request.setUserRequestContext(pendingAdRequestContext);
|
||||||
|
if (configuration.enableContinuousPlayback != null) {
|
||||||
|
request.setContinuousPlayback(configuration.enableContinuousPlayback);
|
||||||
|
}
|
||||||
if (configuration.vastLoadTimeoutMs != TIMEOUT_UNSET) {
|
if (configuration.vastLoadTimeoutMs != TIMEOUT_UNSET) {
|
||||||
request.setVastLoadTimeout(configuration.vastLoadTimeoutMs);
|
request.setVastLoadTimeout(configuration.vastLoadTimeoutMs);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,7 @@ public final class ImaAdsLoader implements Player.EventListener, AdsLoader {
|
||||||
@Nullable private List<String> adMediaMimeTypes;
|
@Nullable private List<String> adMediaMimeTypes;
|
||||||
@Nullable private Set<UiElement> adUiElements;
|
@Nullable private Set<UiElement> adUiElements;
|
||||||
@Nullable private Collection<CompanionAdSlot> companionAdSlots;
|
@Nullable private Collection<CompanionAdSlot> companionAdSlots;
|
||||||
|
@Nullable private Boolean enableContinuousPlayback;
|
||||||
private long adPreloadTimeoutMs;
|
private long adPreloadTimeoutMs;
|
||||||
private int vastLoadTimeoutMs;
|
private int vastLoadTimeoutMs;
|
||||||
private int mediaLoadTimeoutMs;
|
private int mediaLoadTimeoutMs;
|
||||||
|
|
@ -235,6 +236,20 @@ public final class ImaAdsLoader implements Player.EventListener, AdsLoader {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether to enable continuous playback. Pass {@code true} if content videos will be
|
||||||
|
* played continuously, similar to a TV broadcast. This setting may modify the ads request but
|
||||||
|
* does not affect ad playback behavior. The requested value is unknown by default.
|
||||||
|
*
|
||||||
|
* @param enableContinuousPlayback Whether to enable continuous playback.
|
||||||
|
* @return This builder, for convenience.
|
||||||
|
* @see AdsRequest#setContinuousPlayback(boolean)
|
||||||
|
*/
|
||||||
|
public Builder setEnableContinuousPlayback(boolean enableContinuousPlayback) {
|
||||||
|
this.enableContinuousPlayback = enableContinuousPlayback;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the duration in milliseconds for which the player must buffer while preloading an ad
|
* Sets the duration in milliseconds for which the player must buffer while preloading an ad
|
||||||
* group before that ad group is skipped and marked as having failed to load. Pass {@link
|
* group before that ad group is skipped and marked as having failed to load. Pass {@link
|
||||||
|
|
@ -354,6 +369,7 @@ public final class ImaAdsLoader implements Player.EventListener, AdsLoader {
|
||||||
focusSkipButtonWhenAvailable,
|
focusSkipButtonWhenAvailable,
|
||||||
playAdBeforeStartPosition,
|
playAdBeforeStartPosition,
|
||||||
mediaBitrate,
|
mediaBitrate,
|
||||||
|
enableContinuousPlayback,
|
||||||
adMediaMimeTypes,
|
adMediaMimeTypes,
|
||||||
adUiElements,
|
adUiElements,
|
||||||
companionAdSlots,
|
companionAdSlots,
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,7 @@ import java.util.Set;
|
||||||
public final boolean focusSkipButtonWhenAvailable;
|
public final boolean focusSkipButtonWhenAvailable;
|
||||||
public final boolean playAdBeforeStartPosition;
|
public final boolean playAdBeforeStartPosition;
|
||||||
public final int mediaBitrate;
|
public final int mediaBitrate;
|
||||||
|
@Nullable public final Boolean enableContinuousPlayback;
|
||||||
@Nullable public final List<String> adMediaMimeTypes;
|
@Nullable public final List<String> adMediaMimeTypes;
|
||||||
@Nullable public final Set<UiElement> adUiElements;
|
@Nullable public final Set<UiElement> adUiElements;
|
||||||
@Nullable public final Collection<CompanionAdSlot> companionAdSlots;
|
@Nullable public final Collection<CompanionAdSlot> companionAdSlots;
|
||||||
|
|
@ -105,6 +106,7 @@ import java.util.Set;
|
||||||
boolean focusSkipButtonWhenAvailable,
|
boolean focusSkipButtonWhenAvailable,
|
||||||
boolean playAdBeforeStartPosition,
|
boolean playAdBeforeStartPosition,
|
||||||
int mediaBitrate,
|
int mediaBitrate,
|
||||||
|
@Nullable Boolean enableContinuousPlayback,
|
||||||
@Nullable List<String> adMediaMimeTypes,
|
@Nullable List<String> adMediaMimeTypes,
|
||||||
@Nullable Set<UiElement> adUiElements,
|
@Nullable Set<UiElement> adUiElements,
|
||||||
@Nullable Collection<CompanionAdSlot> companionAdSlots,
|
@Nullable Collection<CompanionAdSlot> companionAdSlots,
|
||||||
|
|
@ -119,6 +121,7 @@ import java.util.Set;
|
||||||
this.focusSkipButtonWhenAvailable = focusSkipButtonWhenAvailable;
|
this.focusSkipButtonWhenAvailable = focusSkipButtonWhenAvailable;
|
||||||
this.playAdBeforeStartPosition = playAdBeforeStartPosition;
|
this.playAdBeforeStartPosition = playAdBeforeStartPosition;
|
||||||
this.mediaBitrate = mediaBitrate;
|
this.mediaBitrate = mediaBitrate;
|
||||||
|
this.enableContinuousPlayback = enableContinuousPlayback;
|
||||||
this.adMediaMimeTypes = adMediaMimeTypes;
|
this.adMediaMimeTypes = adMediaMimeTypes;
|
||||||
this.adUiElements = adUiElements;
|
this.adUiElements = adUiElements;
|
||||||
this.companionAdSlots = companionAdSlots;
|
this.companionAdSlots = companionAdSlots;
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
|
||||||
import static com.google.android.exoplayer2.ext.ima.ImaUtil.getAdGroupTimesUsForCuePoints;
|
import static com.google.android.exoplayer2.ext.ima.ImaUtil.getAdGroupTimesUsForCuePoints;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||||
import static org.mockito.ArgumentMatchers.anyDouble;
|
import static org.mockito.ArgumentMatchers.anyDouble;
|
||||||
import static org.mockito.Mockito.atLeastOnce;
|
import static org.mockito.Mockito.atLeastOnce;
|
||||||
import static org.mockito.Mockito.doAnswer;
|
import static org.mockito.Mockito.doAnswer;
|
||||||
|
|
@ -1128,6 +1129,57 @@ public final class ImaAdsLoaderTest {
|
||||||
.isEqualTo(new AdPlaybackState(secondAdsId, /* adGroupTimesUs...= */ 0));
|
.isEqualTo(new AdPlaybackState(secondAdsId, /* adGroupTimesUs...= */ 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void buildWithDefaultEnableContinuousPlayback_doesNotSetAdsRequestProperty() {
|
||||||
|
imaAdsLoader =
|
||||||
|
new ImaAdsLoader.Builder(getApplicationContext())
|
||||||
|
.setImaFactory(mockImaFactory)
|
||||||
|
.setImaSdkSettings(mockImaSdkSettings)
|
||||||
|
.build();
|
||||||
|
imaAdsLoader.setPlayer(fakePlayer);
|
||||||
|
adsMediaSource =
|
||||||
|
new AdsMediaSource(
|
||||||
|
new FakeMediaSource(CONTENT_TIMELINE),
|
||||||
|
TEST_DATA_SPEC,
|
||||||
|
TEST_ADS_ID,
|
||||||
|
new DefaultMediaSourceFactory((Context) getApplicationContext()),
|
||||||
|
imaAdsLoader,
|
||||||
|
adViewProvider);
|
||||||
|
when(mockAdsManager.getAdCuePoints()).thenReturn(PREROLL_CUE_POINTS_SECONDS);
|
||||||
|
|
||||||
|
imaAdsLoader.setSupportedContentTypes(C.TYPE_OTHER);
|
||||||
|
imaAdsLoader.start(
|
||||||
|
adsMediaSource, TEST_DATA_SPEC, TEST_ADS_ID, adViewProvider, adsLoaderListener);
|
||||||
|
|
||||||
|
verify(mockAdsRequest, never()).setContinuousPlayback(anyBoolean());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void buildWithEnableContinuousPlayback_setsAdsRequestProperty() {
|
||||||
|
imaAdsLoader =
|
||||||
|
new ImaAdsLoader.Builder(getApplicationContext())
|
||||||
|
.setEnableContinuousPlayback(true)
|
||||||
|
.setImaFactory(mockImaFactory)
|
||||||
|
.setImaSdkSettings(mockImaSdkSettings)
|
||||||
|
.build();
|
||||||
|
imaAdsLoader.setPlayer(fakePlayer);
|
||||||
|
adsMediaSource =
|
||||||
|
new AdsMediaSource(
|
||||||
|
new FakeMediaSource(CONTENT_TIMELINE),
|
||||||
|
TEST_DATA_SPEC,
|
||||||
|
TEST_ADS_ID,
|
||||||
|
new DefaultMediaSourceFactory((Context) getApplicationContext()),
|
||||||
|
imaAdsLoader,
|
||||||
|
adViewProvider);
|
||||||
|
when(mockAdsManager.getAdCuePoints()).thenReturn(PREROLL_CUE_POINTS_SECONDS);
|
||||||
|
|
||||||
|
imaAdsLoader.setSupportedContentTypes(C.TYPE_OTHER);
|
||||||
|
imaAdsLoader.start(
|
||||||
|
adsMediaSource, TEST_DATA_SPEC, TEST_ADS_ID, adViewProvider, adsLoaderListener);
|
||||||
|
|
||||||
|
verify(mockAdsRequest).setContinuousPlayback(true);
|
||||||
|
}
|
||||||
|
|
||||||
private void setupMocks() {
|
private void setupMocks() {
|
||||||
ArgumentCaptor<Object> userRequestContextCaptor = ArgumentCaptor.forClass(Object.class);
|
ArgumentCaptor<Object> userRequestContextCaptor = ArgumentCaptor.forClass(Object.class);
|
||||||
doNothing().when(mockAdsRequest).setUserRequestContext(userRequestContextCaptor.capture());
|
doNothing().when(mockAdsRequest).setUserRequestContext(userRequestContextCaptor.capture());
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue