Fix player state transitions for postroll ads

Before this change, the player state would be STATE_ENDED then
STATE_BUFFERING (when the postroll ad was marked as played) then
STATE_ENDED again.

Queueing a final content media period with start point equal to
the content duration after a postroll ensures that the player
state doesn't change to STATE_ENDED transiently.

Switch from using C.TIME_END_OF_SOURCE to C.TIME_UNSET for media
periods that should not have an end point and are not followed
by an ad.

Content media periods before postrolls have end position
C.TIME_END_OF_SOURCE. If the postroll ad loads, its content
position is set to the content duration, which should be known
at the point of loading the postroll, then a final 'empty'
content media period with start position equal to its duration
is queued. If the postroll fails to load, this empty content
media period is queued up directly after the preceding content
media period.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=219443683
This commit is contained in:
andrewlewis 2018-10-31 02:42:14 -07:00 committed by Oliver Woodman
parent 4b9530c214
commit 1094da2b61
72 changed files with 443 additions and 164 deletions

View File

@ -666,7 +666,8 @@ public final class ImaAdsLoader
// until MAXIMUM_PRELOAD_DURATION_MS before the ad so that an ad group load error delivered
// just after an ad group isn't incorrectly attributed to the next ad group.
int nextAdGroupIndex =
adPlaybackState.getAdGroupIndexAfterPositionUs(C.msToUs(contentPositionMs));
adPlaybackState.getAdGroupIndexAfterPositionUs(
C.msToUs(contentPositionMs), C.msToUs(contentDurationMs));
if (nextAdGroupIndex != expectedAdGroupIndex && nextAdGroupIndex != C.INDEX_UNSET) {
long nextAdGroupTimeMs = C.usToMs(adPlaybackState.adGroupTimesUs[nextAdGroupIndex]);
if (nextAdGroupTimeMs == C.TIME_END_OF_SOURCE) {

View File

@ -20,6 +20,7 @@ import com.google.android.exoplayer2.source.ClippingMediaPeriod;
import com.google.android.exoplayer2.source.EmptySampleStream;
import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.TrackSelection;
@ -88,16 +89,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
this.info = info;
sampleStreams = new SampleStream[rendererCapabilities.length];
mayRetainStreamFlags = new boolean[rendererCapabilities.length];
MediaPeriod mediaPeriod = mediaSource.createPeriod(info.id, allocator);
if (info.id.endPositionUs != C.TIME_END_OF_SOURCE) {
mediaPeriod =
new ClippingMediaPeriod(
mediaPeriod,
/* enableInitialDiscontinuity= */ true,
/* startUs= */ 0,
info.id.endPositionUs);
}
this.mediaPeriod = mediaPeriod;
mediaPeriod = createMediaPeriod(info.id, mediaSource, allocator);
}
/**
@ -302,16 +294,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
public void release() {
disableTrackSelectionsInResult();
trackSelectorResult = null;
try {
if (info.id.endPositionUs != C.TIME_END_OF_SOURCE) {
mediaSource.releasePeriod(((ClippingMediaPeriod) mediaPeriod).mediaPeriod);
} else {
mediaSource.releasePeriod(mediaPeriod);
}
} catch (RuntimeException e) {
// There's nothing we can do.
Log.e(TAG, "Period release failed.", e);
}
releaseMediaPeriod(info.id, mediaSource, mediaPeriod);
}
/**
@ -413,4 +396,34 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
private boolean isLoadingMediaPeriod() {
return next == null;
}
/** Returns a media period corresponding to the given {@code id}. */
private static MediaPeriod createMediaPeriod(
MediaPeriodId id, MediaSource mediaSource, Allocator allocator) {
MediaPeriod mediaPeriod = mediaSource.createPeriod(id, allocator);
if (id.endPositionUs != C.TIME_UNSET && id.endPositionUs != C.TIME_END_OF_SOURCE) {
mediaPeriod =
new ClippingMediaPeriod(
mediaPeriod,
/* enableInitialDiscontinuity= */ true,
/* startUs= */ 0,
id.endPositionUs);
}
return mediaPeriod;
}
/** Releases the given {@code mediaPeriod}, logging and suppressing any errors. */
private static void releaseMediaPeriod(
MediaPeriodId id, MediaSource mediaSource, MediaPeriod mediaPeriod) {
try {
if (id.endPositionUs != C.TIME_UNSET && id.endPositionUs != C.TIME_END_OF_SOURCE) {
mediaSource.releasePeriod(((ClippingMediaPeriod) mediaPeriod).mediaPeriod);
} else {
mediaSource.releasePeriod(mediaPeriod);
}
} catch (RuntimeException e) {
// There's nothing we can do.
Log.e(TAG, "Period release failed.", e);
}
}
}

View File

@ -15,8 +15,10 @@
*/
package com.google.android.exoplayer2;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.util.Util;
/** Stores the information required to load and play a {@link MediaPeriod}. */
/* package */ final class MediaPeriodInfo {
@ -32,8 +34,8 @@ import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
public final long contentPositionUs;
/**
* The duration of the media period, like {@link MediaPeriodId#endPositionUs} but with {@link
* C#TIME_END_OF_SOURCE} resolved to the timeline period duration. May be {@link C#TIME_UNSET} if
* the end position is not known.
* C#TIME_END_OF_SOURCE} and {@link C#TIME_UNSET} resolved to the timeline period duration if
* known.
*/
public final long durationUs;
/**
@ -72,4 +74,33 @@ import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
isLastInTimelinePeriod,
isFinal);
}
@Override
public boolean equals(@Nullable Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
MediaPeriodInfo that = (MediaPeriodInfo) o;
return startPositionUs == that.startPositionUs
&& contentPositionUs == that.contentPositionUs
&& durationUs == that.durationUs
&& isLastInTimelinePeriod == that.isLastInTimelinePeriod
&& isFinal == that.isFinal
&& Util.areEqual(id, that.id);
}
@Override
public int hashCode() {
int result = 17;
result = 31 * result + id.hashCode();
result = 31 * result + (int) startPositionUs;
result = 31 * result + (int) contentPositionUs;
result = 31 * result + (int) durationUs;
result = 31 * result + (isLastInTimelinePeriod ? 1 : 0);
result = 31 * result + (isFinal ? 1 : 0);
return result;
}
}

View File

@ -351,17 +351,18 @@ import com.google.android.exoplayer2.util.Assertions;
* @return The updated media period info for the current timeline.
*/
public MediaPeriodInfo getUpdatedMediaPeriodInfo(MediaPeriodInfo info) {
boolean isLastInPeriod = isLastInPeriod(info.id);
boolean isLastInTimeline = isLastInTimeline(info.id, isLastInPeriod);
MediaPeriodId id = info.id;
boolean isLastInPeriod = isLastInPeriod(id);
boolean isLastInTimeline = isLastInTimeline(id, isLastInPeriod);
timeline.getPeriodByUid(info.id.periodUid, period);
long durationUs =
info.id.isAd()
? period.getAdDurationUs(info.id.adGroupIndex, info.id.adIndexInAdGroup)
: (info.id.endPositionUs == C.TIME_END_OF_SOURCE
id.isAd()
? period.getAdDurationUs(id.adGroupIndex, id.adIndexInAdGroup)
: (id.endPositionUs == C.TIME_UNSET || id.endPositionUs == C.TIME_END_OF_SOURCE
? period.getDurationUs()
: info.id.endPositionUs);
: id.endPositionUs);
return new MediaPeriodInfo(
info.id,
id,
info.startPositionUs,
info.contentPositionUs,
durationUs,
@ -404,7 +405,7 @@ import com.google.android.exoplayer2.util.Assertions;
int nextAdGroupIndex = period.getAdGroupIndexAfterPositionUs(positionUs);
long endPositionUs =
nextAdGroupIndex == C.INDEX_UNSET
? C.TIME_END_OF_SOURCE
? C.TIME_UNSET
: period.getAdGroupTimeUs(nextAdGroupIndex);
return new MediaPeriodId(periodUid, windowSequenceNumber, endPositionUs);
} else {
@ -580,7 +581,8 @@ import com.google.android.exoplayer2.util.Assertions;
}
MediaPeriodId periodId =
resolveMediaPeriodIdForAds(nextPeriodUid, startPositionUs, windowSequenceNumber);
return getMediaPeriodInfo(periodId, startPositionUs, startPositionUs);
return getMediaPeriodInfo(
periodId, /* contentPositionUs= */ startPositionUs, startPositionUs);
}
MediaPeriodId currentPeriodId = mediaPeriodInfo.id;
@ -626,14 +628,14 @@ import com.google.android.exoplayer2.util.Assertions;
return getMediaPeriodInfoForContent(
currentPeriodId.periodUid, startPositionUs, currentPeriodId.windowSequenceNumber);
}
} else if (mediaPeriodInfo.id.endPositionUs != C.TIME_END_OF_SOURCE) {
} else {
// Play the next ad group if it's available.
int nextAdGroupIndex = period.getAdGroupIndexForPositionUs(mediaPeriodInfo.id.endPositionUs);
if (nextAdGroupIndex == C.INDEX_UNSET) {
// The next ad group can't be played. Play content from the ad group position instead.
// The next ad group can't be played. Play content from the previous end position instead.
return getMediaPeriodInfoForContent(
currentPeriodId.periodUid,
mediaPeriodInfo.id.endPositionUs,
/* startPositionUs= */ mediaPeriodInfo.durationUs,
currentPeriodId.windowSequenceNumber);
}
int adIndexInAdGroup = period.getFirstAdIndexToPlay(nextAdGroupIndex);
@ -643,30 +645,8 @@ import com.google.android.exoplayer2.util.Assertions;
currentPeriodId.periodUid,
nextAdGroupIndex,
adIndexInAdGroup,
mediaPeriodInfo.id.endPositionUs,
/* contentPositionUs= */ mediaPeriodInfo.durationUs,
currentPeriodId.windowSequenceNumber);
} else {
// Check if the postroll ad should be played.
int adGroupCount = period.getAdGroupCount();
if (adGroupCount == 0) {
return null;
}
int adGroupIndex = adGroupCount - 1;
if (period.getAdGroupTimeUs(adGroupIndex) != C.TIME_END_OF_SOURCE
|| period.hasPlayedAdGroup(adGroupIndex)) {
return null;
}
int adIndexInAdGroup = period.getFirstAdIndexToPlay(adGroupIndex);
if (!period.isAdAvailable(adGroupIndex, adIndexInAdGroup)) {
return null;
}
long contentDurationUs = period.getDurationUs();
return getMediaPeriodInfoForAd(
currentPeriodId.periodUid,
adGroupIndex,
adIndexInAdGroup,
contentDurationUs,
currentPeriodId.windowSequenceNumber);
}
}
@ -696,8 +676,6 @@ import com.google.android.exoplayer2.util.Assertions;
long windowSequenceNumber) {
MediaPeriodId id =
new MediaPeriodId(periodUid, adGroupIndex, adIndexInAdGroup, windowSequenceNumber);
boolean isLastInPeriod = isLastInPeriod(id);
boolean isLastInTimeline = isLastInTimeline(id, isLastInPeriod);
long durationUs =
timeline
.getPeriodByUid(id.periodUid, period)
@ -711,49 +689,35 @@ import com.google.android.exoplayer2.util.Assertions;
startPositionUs,
contentPositionUs,
durationUs,
isLastInPeriod,
isLastInTimeline);
/* isLastInTimelinePeriod= */ false,
/* isFinal= */ false);
}
private MediaPeriodInfo getMediaPeriodInfoForContent(
Object periodUid, long startPositionUs, long windowSequenceNumber) {
int nextAdGroupIndex = period.getAdGroupIndexAfterPositionUs(startPositionUs);
long endPositionUs =
nextAdGroupIndex == C.INDEX_UNSET
? C.TIME_END_OF_SOURCE
: period.getAdGroupTimeUs(nextAdGroupIndex);
nextAdGroupIndex != C.INDEX_UNSET
? period.getAdGroupTimeUs(nextAdGroupIndex)
: C.TIME_UNSET;
MediaPeriodId id = new MediaPeriodId(periodUid, windowSequenceNumber, endPositionUs);
timeline.getPeriodByUid(id.periodUid, period);
boolean isLastInPeriod = isLastInPeriod(id);
boolean isLastInTimeline = isLastInTimeline(id, isLastInPeriod);
long durationUs =
endPositionUs == C.TIME_END_OF_SOURCE ? period.getDurationUs() : endPositionUs;
endPositionUs == C.TIME_UNSET || endPositionUs == C.TIME_END_OF_SOURCE
? period.durationUs
: endPositionUs;
return new MediaPeriodInfo(
id, startPositionUs, C.TIME_UNSET, durationUs, isLastInPeriod, isLastInTimeline);
id,
startPositionUs,
/* contentPositionUs= */ C.TIME_UNSET,
durationUs,
isLastInPeriod,
isLastInTimeline);
}
private boolean isLastInPeriod(MediaPeriodId id) {
int adGroupCount = timeline.getPeriodByUid(id.periodUid, period).getAdGroupCount();
if (adGroupCount == 0) {
return true;
}
int lastAdGroupIndex = adGroupCount - 1;
boolean isAd = id.isAd();
if (period.getAdGroupTimeUs(lastAdGroupIndex) != C.TIME_END_OF_SOURCE) {
// There's no postroll ad.
return !isAd && id.endPositionUs == C.TIME_END_OF_SOURCE;
}
int postrollAdCount = period.getAdCountInAdGroup(lastAdGroupIndex);
if (postrollAdCount == C.LENGTH_UNSET) {
// We won't know if this is the last ad until we know how many postroll ads there are.
return false;
}
boolean isLastAd =
isAd && id.adGroupIndex == lastAdGroupIndex && id.adIndexInAdGroup == postrollAdCount - 1;
return isLastAd || (!isAd && period.getFirstAdIndexToPlay(lastAdGroupIndex) == postrollAdCount);
return !id.isAd() && id.endPositionUs == C.TIME_UNSET;
}
private boolean isLastInTimeline(MediaPeriodId id, boolean isLastMediaPeriodInPeriod) {

View File

@ -441,7 +441,7 @@ public abstract class Timeline {
* @return The index of the ad group, or {@link C#INDEX_UNSET}.
*/
public int getAdGroupIndexAfterPositionUs(long positionUs) {
return adPlaybackState.getAdGroupIndexAfterPositionUs(positionUs);
return adPlaybackState.getAdGroupIndexAfterPositionUs(positionUs, durationUs);
}
/**

View File

@ -89,11 +89,10 @@ public interface MediaSource {
public final long windowSequenceNumber;
/**
* The end position of the media to play within the media period, in microseconds, or {@link
* C#TIME_END_OF_SOURCE} if the end position is the end of the media period.
*
* <p>Note that this only applies if the media period is for content (i.e., not for an ad) and
* is clipped to the position of the next ad group.
* The end position to which the media period's content is clipped in order to play a following
* ad group, in microseconds, or {@link C#TIME_UNSET} if there is no following ad group or if
* this media period is an ad. The value {@link C#TIME_END_OF_SOURCE} indicates that a postroll
* ad follows at the end of this content media period.
*/
public final long endPositionUs;
@ -115,7 +114,7 @@ public interface MediaSource {
* windows this media period is part of.
*/
public MediaPeriodId(Object periodUid, long windowSequenceNumber) {
this(periodUid, C.INDEX_UNSET, C.INDEX_UNSET, windowSequenceNumber, C.TIME_END_OF_SOURCE);
this(periodUid, C.INDEX_UNSET, C.INDEX_UNSET, windowSequenceNumber, C.TIME_UNSET);
}
/**
@ -143,7 +142,7 @@ public interface MediaSource {
*/
public MediaPeriodId(
Object periodUid, int adGroupIndex, int adIndexInAdGroup, long windowSequenceNumber) {
this(periodUid, adGroupIndex, adIndexInAdGroup, windowSequenceNumber, C.TIME_END_OF_SOURCE);
this(periodUid, adGroupIndex, adIndexInAdGroup, windowSequenceNumber, C.TIME_UNSET);
}
private MediaPeriodId(

View File

@ -310,7 +310,9 @@ public final class AdPlaybackState {
* unplayed. Returns {@link C#INDEX_UNSET} if the ad group at or before {@code positionUs} has no
* ads remaining to be played, or if there is no such ad group.
*
* @param positionUs The position at or before which to find an ad group, in microseconds.
* @param positionUs The position at or before which to find an ad group, in microseconds, or
* {@link C#TIME_END_OF_SOURCE} for the end of the stream (in which case the index of any
* unplayed postroll ad group will be returned).
* @return The index of the ad group, or {@link C#INDEX_UNSET}.
*/
public int getAdGroupIndexForPositionUs(long positionUs) {
@ -327,10 +329,18 @@ public final class AdPlaybackState {
* Returns the index of the next ad group after {@code positionUs} that has ads remaining to be
* played. Returns {@link C#INDEX_UNSET} if there is no such ad group.
*
* @param positionUs The position after which to find an ad group, in microseconds.
* @param positionUs The position after which to find an ad group, in microseconds, or {@link
* C#TIME_END_OF_SOURCE} for the end of the stream (in which case there can be no ad group
* after the position).
* @param periodDurationUs The duration of the containing period in microseconds, or {@link
* C#TIME_UNSET} if not known.
* @return The index of the ad group, or {@link C#INDEX_UNSET}.
*/
public int getAdGroupIndexAfterPositionUs(long positionUs) {
public int getAdGroupIndexAfterPositionUs(long positionUs, long periodDurationUs) {
if (positionUs == C.TIME_END_OF_SOURCE
|| (periodDurationUs != C.TIME_UNSET && positionUs >= periodDurationUs)) {
return C.INDEX_UNSET;
}
// Use a linear search as the array elements may not be increasing due to TIME_END_OF_SOURCE.
// In practice we expect there to be few ad groups so the search shouldn't be expensive.
int index = 0;
@ -457,6 +467,10 @@ public final class AdPlaybackState {
}
private boolean isPositionBeforeAdGroup(long positionUs, int adGroupIndex) {
if (positionUs == C.TIME_END_OF_SOURCE) {
// The end of the content is at (but not before) any postroll ad, and after any other ads.
return false;
}
long adGroupPositionUs = adGroupTimesUs[adGroupIndex];
if (adGroupPositionUs == C.TIME_END_OF_SOURCE) {
return contentDurationUs == C.TIME_UNSET || positionUs < contentDurationUs;

View File

@ -0,0 +1,257 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.mock;
import android.net.Uri;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.SinglePeriodTimeline;
import com.google.android.exoplayer2.source.ads.AdPlaybackState;
import com.google.android.exoplayer2.source.ads.SinglePeriodAdTimeline;
import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.upstream.Allocator;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
/** Unit tests for {@link MediaPeriodQueue}. */
@RunWith(RobolectricTestRunner.class)
public final class MediaPeriodQueueTest {
private static final long CONTENT_DURATION_US = 30 * C.MICROS_PER_SECOND;
private static final long FIRST_AD_START_TIME_US = 10 * C.MICROS_PER_SECOND;
private static final long SECOND_AD_START_TIME_US = 20 * C.MICROS_PER_SECOND;
private static final Timeline CONTENT_TIMELINE =
new SinglePeriodTimeline(CONTENT_DURATION_US, /* isSeekable= */ true, /* isDynamic= */ false);
private static final Uri AD_URI = Uri.EMPTY;
private MediaPeriodQueue mediaPeriodQueue;
private AdPlaybackState adPlaybackState;
private Timeline timeline;
private Object periodUid;
private PlaybackInfo playbackInfo;
private RendererCapabilities[] rendererCapabilities;
private TrackSelector trackSelector;
private Allocator allocator;
private MediaSource mediaSource;
@Before
public void setUp() {
mediaPeriodQueue = new MediaPeriodQueue();
mediaSource = mock(MediaSource.class);
rendererCapabilities = new RendererCapabilities[0];
trackSelector = mock(TrackSelector.class);
allocator = mock(Allocator.class);
}
@Test
public void testGetNextMediaPeriodInfo_withoutAds_returnsLastMediaPeriodInfo() {
setupInitialTimeline(/* initialPositionUs= */ 0);
assertGetNextMediaPeriodInfoReturnsContentMediaPeriod(
/* startPositionUs= */ 0,
/* endPositionUs= */ C.TIME_UNSET,
/* durationUs= */ CONTENT_DURATION_US,
/* isLast= */ true);
}
@Test
public void testGetNextMediaPeriodInfo_withPrerollAd_returnsCorrectMediaPeriodInfos() {
setupInitialTimeline(/* initialPositionUs= */ 0, /* adGroupTimesUs= */ 0);
setAdGroupLoaded(/* adGroupIndex= */ 0);
assertNextMediaPeriodInfoIsAd(/* adGroupIndex= */ 0, /* contentPositionUs= */ 0);
advance();
assertGetNextMediaPeriodInfoReturnsContentMediaPeriod(
/* startPositionUs= */ 0,
/* endPositionUs= */ C.TIME_UNSET,
/* durationUs= */ CONTENT_DURATION_US,
/* isLast= */ true);
}
@Test
public void testGetNextMediaPeriodInfo_withMidrollAds_returnsCorrectMediaPeriodInfos() {
setupInitialTimeline(
/* initialPositionUs= */ 0,
/* adGroupTimesUs= */ FIRST_AD_START_TIME_US,
SECOND_AD_START_TIME_US);
assertGetNextMediaPeriodInfoReturnsContentMediaPeriod(
/* startPositionUs= */ 0,
/* endPositionUs= */ FIRST_AD_START_TIME_US,
/* durationUs= */ FIRST_AD_START_TIME_US,
/* isLast= */ false);
// The next media period info should be null as we haven't loaded the ad yet.
advance();
assertNull(getNextMediaPeriodInfo());
setAdGroupLoaded(/* adGroupIndex= */ 0);
assertNextMediaPeriodInfoIsAd(
/* adGroupIndex= */ 0, /* contentPositionUs= */ FIRST_AD_START_TIME_US);
advance();
assertGetNextMediaPeriodInfoReturnsContentMediaPeriod(
/* startPositionUs= */ FIRST_AD_START_TIME_US,
/* endPositionUs= */ SECOND_AD_START_TIME_US,
/* durationUs= */ SECOND_AD_START_TIME_US,
/* isLast= */ false);
advance();
setAdGroupLoaded(/* adGroupIndex= */ 1);
assertNextMediaPeriodInfoIsAd(
/* adGroupIndex= */ 1, /* contentPositionUs= */ SECOND_AD_START_TIME_US);
advance();
assertGetNextMediaPeriodInfoReturnsContentMediaPeriod(
/* startPositionUs= */ SECOND_AD_START_TIME_US,
/* endPositionUs= */ C.TIME_UNSET,
/* durationUs= */ CONTENT_DURATION_US,
/* isLast= */ true);
}
@Test
public void testGetNextMediaPeriodInfo_withMidrollAndPostroll_returnsCorrectMediaPeriodInfos() {
setupInitialTimeline(
/* initialPositionUs= */ 0,
/* adGroupTimesUs= */ FIRST_AD_START_TIME_US,
C.TIME_END_OF_SOURCE);
assertGetNextMediaPeriodInfoReturnsContentMediaPeriod(
/* startPositionUs= */ 0,
/* endPositionUs= */ FIRST_AD_START_TIME_US,
/* durationUs= */ FIRST_AD_START_TIME_US,
/* isLast= */ false);
advance();
setAdGroupLoaded(/* adGroupIndex= */ 0);
assertNextMediaPeriodInfoIsAd(
/* adGroupIndex= */ 0, /* contentPositionUs= */ FIRST_AD_START_TIME_US);
advance();
assertGetNextMediaPeriodInfoReturnsContentMediaPeriod(
/* startPositionUs= */ FIRST_AD_START_TIME_US,
/* endPositionUs= */ C.TIME_END_OF_SOURCE,
/* durationUs= */ CONTENT_DURATION_US,
/* isLast= */ false);
advance();
setAdGroupLoaded(/* adGroupIndex= */ 1);
assertNextMediaPeriodInfoIsAd(
/* adGroupIndex= */ 1, /* contentPositionUs= */ CONTENT_DURATION_US);
advance();
assertGetNextMediaPeriodInfoReturnsContentMediaPeriod(
/* startPositionUs= */ CONTENT_DURATION_US,
/* endPositionUs= */ C.TIME_UNSET,
/* durationUs= */ CONTENT_DURATION_US,
/* isLast= */ true);
}
@Test
public void testGetNextMediaPeriodInfo_withPostrollLoadError_returnsEmptyFinalMediaPeriodInfo() {
setupInitialTimeline(/* initialPositionUs= */ 0, /* adGroupTimesUs= */ C.TIME_END_OF_SOURCE);
assertGetNextMediaPeriodInfoReturnsContentMediaPeriod(
/* startPositionUs= */ 0,
/* endPositionUs= */ C.TIME_END_OF_SOURCE,
/* durationUs= */ CONTENT_DURATION_US,
/* isLast= */ false);
advance();
setAdGroupFailedToLoad(/* adGroupIndex= */ 0);
assertGetNextMediaPeriodInfoReturnsContentMediaPeriod(
/* startPositionUs= */ CONTENT_DURATION_US,
/* endPositionUs= */ C.TIME_UNSET,
/* durationUs= */ CONTENT_DURATION_US,
/* isLast= */ true);
}
private void setupInitialTimeline(long initialPositionUs, long... adGroupTimesUs) {
adPlaybackState =
new AdPlaybackState(adGroupTimesUs).withContentDurationUs(CONTENT_DURATION_US);
timeline = new SinglePeriodAdTimeline(CONTENT_TIMELINE, adPlaybackState);
periodUid = timeline.getUidOfPeriod(/* periodIndex= */ 0);
mediaPeriodQueue.setTimeline(timeline);
playbackInfo =
new PlaybackInfo(
timeline,
/* manifest= */ null,
mediaPeriodQueue.resolveMediaPeriodIdForAds(periodUid, initialPositionUs),
/* startPositionUs= */ 0,
/* contentPositionUs= */ 0,
Player.STATE_READY,
/* isLoading= */ false,
/* trackGroups= */ null,
/* trackSelectorResult= */ null,
/* loadingMediaPeriodId= */ null,
/* bufferedPositionUs= */ 0,
/* totalBufferedDurationUs= */ 0,
/* positionUs= */ 0);
}
private void advance() {
mediaPeriodQueue.enqueueNextMediaPeriod(
rendererCapabilities, trackSelector, allocator, mediaSource, getNextMediaPeriodInfo());
mediaPeriodQueue.advancePlayingPeriod();
}
private MediaPeriodInfo getNextMediaPeriodInfo() {
return mediaPeriodQueue.getNextMediaPeriodInfo(/* rendererPositionUs= */ 0, playbackInfo);
}
private void setAdGroupLoaded(int adGroupIndex) {
adPlaybackState =
adPlaybackState
.withAdCount(adGroupIndex, /* adCount= */ 1)
.withAdUri(adGroupIndex, /* adIndexInAdGroup= */ 0, AD_URI);
updateTimeline();
}
private void setAdGroupFailedToLoad(int adGroupIndex) {
adPlaybackState =
adPlaybackState
.withAdCount(adGroupIndex, /* adCount= */ 1)
.withAdLoadError(adGroupIndex, /* adIndexInAdGroup= */ 0);
updateTimeline();
}
private void updateTimeline() {
timeline = new SinglePeriodAdTimeline(CONTENT_TIMELINE, adPlaybackState);
mediaPeriodQueue.setTimeline(timeline);
}
private void assertGetNextMediaPeriodInfoReturnsContentMediaPeriod(
long startPositionUs, long endPositionUs, long durationUs, boolean isLast) {
assertThat(getNextMediaPeriodInfo())
.isEqualTo(
new MediaPeriodInfo(
new MediaPeriodId(periodUid, /* windowSequenceNumber= */ 0, endPositionUs),
startPositionUs,
/* contentPositionUs= */ C.TIME_UNSET,
durationUs,
/* isLastInTimelinePeriod= */ isLast,
/* isFinal= */ isLast));
}
private void assertNextMediaPeriodInfoIsAd(int adGroupIndex, long contentPositionUs) {
assertThat(getNextMediaPeriodInfo())
.isEqualTo(
new MediaPeriodInfo(
new MediaPeriodId(
periodUid,
adGroupIndex,
/* adIndexInAdGroup= */ 0,
/* windowSequenceNumber= */ 0),
/* startPositionUs= */ 0,
contentPositionUs,
/* durationUs= */ C.TIME_UNSET,
/* isLastInTimelinePeriod= */ false,
/* isFinal= */ false));
}
}

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Herhaal alles</string>
<string name="exo_controls_shuffle_description">Skommel</string>
<string name="exo_controls_fullscreen_description">Volskermmodus</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">VR-modus</string>
<string name="exo_download_description">Aflaai</string>
<string name="exo_download_notification_channel_name">Aflaaie</string>
<string name="exo_download_downloading">Laai tans af</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">ሁሉንም ድገም</string>
<string name="exo_controls_shuffle_description">በውዝ</string>
<string name="exo_controls_fullscreen_description">የሙሉ ማያ ሁነታ</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">የቪአር ሁነታ</string>
<string name="exo_download_description">አውርድ</string>
<string name="exo_download_notification_channel_name">የወረዱ</string>
<string name="exo_download_downloading">በማውረድ ላይ</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">تكرار الكل</string>
<string name="exo_controls_shuffle_description">ترتيب عشوائي</string>
<string name="exo_controls_fullscreen_description">وضع ملء الشاشة</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">وضع VR</string>
<string name="exo_download_description">تنزيل</string>
<string name="exo_download_notification_channel_name">التنزيلات</string>
<string name="exo_download_downloading">جارٍ التنزيل.</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Hamısı təkrarlansın</string>
<string name="exo_controls_shuffle_description">Qarışdırın</string>
<string name="exo_controls_fullscreen_description">Tam ekran rejimi</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">VR rejimi</string>
<string name="exo_download_description">Endirin</string>
<string name="exo_download_notification_channel_name">Endirmələr</string>
<string name="exo_download_downloading">Endirilir</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Ponovi sve</string>
<string name="exo_controls_shuffle_description">Pusti nasumično</string>
<string name="exo_controls_fullscreen_description">Režim celog ekrana</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">VR režim</string>
<string name="exo_download_description">Preuzmi</string>
<string name="exo_download_notification_channel_name">Preuzimanja</string>
<string name="exo_download_downloading">Preuzima se</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Паўтарыць усе</string>
<string name="exo_controls_shuffle_description">Перамяшаць</string>
<string name="exo_controls_fullscreen_description">Поўнаэкранны рэжым</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">VR-рэжым</string>
<string name="exo_download_description">Спампаваць</string>
<string name="exo_download_notification_channel_name">Спампоўкі</string>
<string name="exo_download_downloading">Спампоўваецца</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Повтаряне на всички</string>
<string name="exo_controls_shuffle_description">Разбъркване</string>
<string name="exo_controls_fullscreen_description">Режим на цял екран</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">режим за VR</string>
<string name="exo_download_description">Изтегляне</string>
<string name="exo_download_notification_channel_name">Изтегляния</string>
<string name="exo_download_downloading">Изтегля се</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Ponovi sve</string>
<string name="exo_controls_shuffle_description">Izmiješaj</string>
<string name="exo_controls_fullscreen_description">Način rada preko cijelog ekrana</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">VR način rada</string>
<string name="exo_download_description">Preuzmi</string>
<string name="exo_download_notification_channel_name">Preuzimanja</string>
<string name="exo_download_downloading">Preuzimanje</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Repeteix tot</string>
<string name="exo_controls_shuffle_description">Reprodueix aleatòriament</string>
<string name="exo_controls_fullscreen_description">Mode de pantalla completa</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">Mode RV</string>
<string name="exo_download_description">Baixa</string>
<string name="exo_download_notification_channel_name">Baixades</string>
<string name="exo_download_downloading">S\'està baixant</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Opakovat vše</string>
<string name="exo_controls_shuffle_description">Náhodně</string>
<string name="exo_controls_fullscreen_description">Režim celé obrazovky</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">Režim VR</string>
<string name="exo_download_description">Stáhnout</string>
<string name="exo_download_notification_channel_name">Stahování</string>
<string name="exo_download_downloading">Stahování</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Gentag alle</string>
<string name="exo_controls_shuffle_description">Bland</string>
<string name="exo_controls_fullscreen_description">Fuld skærm</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">VR-tilstand</string>
<string name="exo_download_description">Download</string>
<string name="exo_download_notification_channel_name">Downloads</string>
<string name="exo_download_downloading">Downloader</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Alle wiederholen</string>
<string name="exo_controls_shuffle_description">Zufallsmix</string>
<string name="exo_controls_fullscreen_description">Vollbildmodus</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">VR-Modus</string>
<string name="exo_download_description">Herunterladen</string>
<string name="exo_download_notification_channel_name">Downloads</string>
<string name="exo_download_downloading">Wird heruntergeladen</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Επανάληψη όλων</string>
<string name="exo_controls_shuffle_description">Τυχαία αναπαραγωγή</string>
<string name="exo_controls_fullscreen_description">Λειτουργία πλήρους οθόνης</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">Λειτουργία VR mode</string>
<string name="exo_download_description">Λήψη</string>
<string name="exo_download_notification_channel_name">Λήψεις</string>
<string name="exo_download_downloading">Λήψη</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Repetir todo</string>
<string name="exo_controls_shuffle_description">Reproducir aleatoriamente</string>
<string name="exo_controls_fullscreen_description">Modo de pantalla completa</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">Modo RV</string>
<string name="exo_download_description">Descargar</string>
<string name="exo_download_notification_channel_name">Descargas</string>
<string name="exo_download_downloading">Descargando</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Repetir todo</string>
<string name="exo_controls_shuffle_description">Reproducir aleatoriamente</string>
<string name="exo_controls_fullscreen_description">Modo de pantalla completa</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">Modo RV</string>
<string name="exo_download_description">Descargar</string>
<string name="exo_download_notification_channel_name">Descargas</string>
<string name="exo_download_downloading">Descargando</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Korda kõiki</string>
<string name="exo_controls_shuffle_description">Esita juhuslikus järjekorras</string>
<string name="exo_controls_fullscreen_description">Täisekraani režiim</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">VR-režiim</string>
<string name="exo_download_description">Allalaadimine</string>
<string name="exo_download_notification_channel_name">Allalaadimised</string>
<string name="exo_download_downloading">Allalaadimine</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Errepikatu guztiak</string>
<string name="exo_controls_shuffle_description">Erreproduzitu ausaz</string>
<string name="exo_controls_fullscreen_description">Pantaila osoko modua</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">EB modua</string>
<string name="exo_download_description">Deskargak</string>
<string name="exo_download_notification_channel_name">Deskargak</string>
<string name="exo_download_downloading">Deskargatzen</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">تکرار همه</string>
<string name="exo_controls_shuffle_description">درهم</string>
<string name="exo_controls_fullscreen_description">حالت تمام‌صفحه</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">حالت واقعیت مجازی</string>
<string name="exo_download_description">بارگیری</string>
<string name="exo_download_notification_channel_name">بارگیری‌ها</string>
<string name="exo_download_downloading">درحال بارگیری</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Toista kaikki uudelleen</string>
<string name="exo_controls_shuffle_description">Satunnaistoisto</string>
<string name="exo_controls_fullscreen_description">Koko näytön tila</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">VR-tila</string>
<string name="exo_download_description">Lataa</string>
<string name="exo_download_notification_channel_name">Lataukset</string>
<string name="exo_download_downloading">Ladataan</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Tout lire en boucle</string>
<string name="exo_controls_shuffle_description">Lecture aléatoire</string>
<string name="exo_controls_fullscreen_description">Mode Plein écran</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">Mode RV</string>
<string name="exo_download_description">Télécharger</string>
<string name="exo_download_notification_channel_name">Téléchargements</string>
<string name="exo_download_downloading">Téléchargement en cours…</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Tout lire en boucle</string>
<string name="exo_controls_shuffle_description">Aléatoire</string>
<string name="exo_controls_fullscreen_description">Mode plein écran</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">Mode RV</string>
<string name="exo_download_description">Télécharger</string>
<string name="exo_download_notification_channel_name">Téléchargements</string>
<string name="exo_download_downloading">Téléchargement…</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Repetir todas as pistas</string>
<string name="exo_controls_shuffle_description">Reprodución aleatoria</string>
<string name="exo_controls_fullscreen_description">Modo de pantalla completa</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">Modo RV</string>
<string name="exo_download_description">Descargar</string>
<string name="exo_download_notification_channel_name">Descargas</string>
<string name="exo_download_downloading">Descargando</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">सभी को दोहराएं</string>
<string name="exo_controls_shuffle_description">शफ़ल करें</string>
<string name="exo_controls_fullscreen_description">फ़ुलस्क्रीन मोड</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">VR मोड</string>
<string name="exo_download_description">डाउनलोड करें</string>
<string name="exo_download_notification_channel_name">डाउनलोड की गई मीडिया फ़ाइलें</string>
<string name="exo_download_downloading">डाउनलोड हो रहा है</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Ponovi sve</string>
<string name="exo_controls_shuffle_description">Reproduciraj nasumično</string>
<string name="exo_controls_fullscreen_description">Prikaz na cijelom zaslonu</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">VR način</string>
<string name="exo_download_description">Preuzmi</string>
<string name="exo_download_notification_channel_name">Preuzimanja</string>
<string name="exo_download_downloading">Preuzimanje</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Összes szám ismétlése</string>
<string name="exo_controls_shuffle_description">Keverés</string>
<string name="exo_controls_fullscreen_description">Teljes képernyős mód</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">VR-mód</string>
<string name="exo_download_description">Letöltés</string>
<string name="exo_download_notification_channel_name">Letöltések</string>
<string name="exo_download_downloading">Letöltés folyamatban</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Կրկնել բոլորը</string>
<string name="exo_controls_shuffle_description">Խառնել</string>
<string name="exo_controls_fullscreen_description">Լիաէկրան ռեժիմ</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">VR ռեժիմ</string>
<string name="exo_download_description">Ներբեռնել</string>
<string name="exo_download_notification_channel_name">Ներբեռնումներ</string>
<string name="exo_download_downloading">Ներբեռնում</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Ulangi semua</string>
<string name="exo_controls_shuffle_description">Acak</string>
<string name="exo_controls_fullscreen_description">Mode layar penuh</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">Mode VR</string>
<string name="exo_download_description">Download</string>
<string name="exo_download_notification_channel_name">Download</string>
<string name="exo_download_downloading">Mendownload</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Endurtaka allt</string>
<string name="exo_controls_shuffle_description">Stokka</string>
<string name="exo_controls_fullscreen_description">Allur skjárinn</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">sýndarveruleikastilling</string>
<string name="exo_download_description">Sækja</string>
<string name="exo_download_notification_channel_name">Niðurhal</string>
<string name="exo_download_downloading">Sækir</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Ripeti tutto</string>
<string name="exo_controls_shuffle_description">Riproduzione casuale</string>
<string name="exo_controls_fullscreen_description">Modalità a schermo intero</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">Modalità VR</string>
<string name="exo_download_description">Scarica</string>
<string name="exo_download_notification_channel_name">Download</string>
<string name="exo_download_downloading">Download…</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">全曲をリピート</string>
<string name="exo_controls_shuffle_description">シャッフル</string>
<string name="exo_controls_fullscreen_description">全画面モード</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">VR モード</string>
<string name="exo_download_description">ダウンロード</string>
<string name="exo_download_notification_channel_name">ダウンロード</string>
<string name="exo_download_downloading">ダウンロードしています</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">ყველას გამეორება</string>
<string name="exo_controls_shuffle_description">არეულად დაკვრა</string>
<string name="exo_controls_fullscreen_description">სრულეკრანიანი რეჟიმი</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">VR რეჟიმი</string>
<string name="exo_download_description">ჩამოტვირთვა</string>
<string name="exo_download_notification_channel_name">ჩამოტვირთვები</string>
<string name="exo_download_downloading">მიმდინარეობს ჩამოტვირთვა</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Барлығын қайталау</string>
<string name="exo_controls_shuffle_description">Араластыру</string>
<string name="exo_controls_fullscreen_description">Толық экран режимі</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">VR режимі</string>
<string name="exo_download_description">Жүктеп алу</string>
<string name="exo_download_notification_channel_name">Жүктеп алынғандар</string>
<string name="exo_download_downloading">Жүктеп алынуда</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">លេង​ឡើងវិញ​ទាំងអស់</string>
<string name="exo_controls_shuffle_description">ច្របល់</string>
<string name="exo_controls_fullscreen_description">មុខងារពេញ​អេក្រង់</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">មុខងារ VR</string>
<string name="exo_download_description">ទាញយក</string>
<string name="exo_download_notification_channel_name">ទាញយក</string>
<string name="exo_download_downloading">កំពុង​ទាញ​យក</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">모두 반복</string>
<string name="exo_controls_shuffle_description">셔플</string>
<string name="exo_controls_fullscreen_description">전체화면 모드</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">가상 현실 모드</string>
<string name="exo_download_description">다운로드</string>
<string name="exo_download_notification_channel_name">다운로드</string>
<string name="exo_download_downloading">다운로드 중</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Баарын кайталоо</string>
<string name="exo_controls_shuffle_description">Аралаштыруу</string>
<string name="exo_controls_fullscreen_description">Толук экран режими</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">VR режими</string>
<string name="exo_download_description">Жүктөп алуу</string>
<string name="exo_download_notification_channel_name">Жүктөлүп алынгандар</string>
<string name="exo_download_downloading">Жүктөлүп алынууда</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Kartoti viską</string>
<string name="exo_controls_shuffle_description">Maišyti</string>
<string name="exo_controls_fullscreen_description">Viso ekrano režimas</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">VR režimas</string>
<string name="exo_download_description">Atsisiųsti</string>
<string name="exo_download_notification_channel_name">Atsisiuntimai</string>
<string name="exo_download_downloading">Atsisiunčiama</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Atkārtot visu</string>
<string name="exo_controls_shuffle_description">Atskaņot jauktā secībā</string>
<string name="exo_controls_fullscreen_description">Pilnekrāna režīms</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">VR režīms</string>
<string name="exo_download_description">Lejupielādēt</string>
<string name="exo_download_notification_channel_name">Lejupielādes</string>
<string name="exo_download_downloading">Notiek lejupielāde</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Повтори ги сите</string>
<string name="exo_controls_shuffle_description">Измешај</string>
<string name="exo_controls_fullscreen_description">Режим на цел екран</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">Режим на VR</string>
<string name="exo_download_description">Преземи</string>
<string name="exo_download_notification_channel_name">Преземања</string>
<string name="exo_download_downloading">Се презема</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Бүгдийг нь дахин тоглуулах</string>
<string name="exo_controls_shuffle_description">Холих</string>
<string name="exo_controls_fullscreen_description">Бүтэн дэлгэцийн горим</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">VR горим</string>
<string name="exo_download_description">Татах</string>
<string name="exo_download_notification_channel_name">Татaлт</string>
<string name="exo_download_downloading">Татаж байна</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">सर्व रीपीट करा</string>
<string name="exo_controls_shuffle_description">शफल करा</string>
<string name="exo_controls_fullscreen_description">फुल स्क्रीन मोड</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">VR मोड</string>
<string name="exo_download_description">डाउनलोड करा</string>
<string name="exo_download_notification_channel_name">डाउनलोड</string>
<string name="exo_download_downloading">डाउनलोड होत आहे</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Ulang semua</string>
<string name="exo_controls_shuffle_description">Rombak</string>
<string name="exo_controls_fullscreen_description">Mod skrin penuh</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">Mod VR</string>
<string name="exo_download_description">Muat turun</string>
<string name="exo_download_notification_channel_name">Muat turun</string>
<string name="exo_download_downloading">Memuat turun</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">အားလုံး ပြန်ကျော့ရန်</string>
<string name="exo_controls_shuffle_description">ရောသမမွှေ</string>
<string name="exo_controls_fullscreen_description">မျက်နှာပြင်အပြည့် မုဒ်</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">VR မုဒ်</string>
<string name="exo_download_description">ဒေါင်းလုဒ် လုပ်ရန်</string>
<string name="exo_download_notification_channel_name">ဒေါင်းလုဒ်များ</string>
<string name="exo_download_downloading">ဒေါင်းလုဒ်လုပ်နေသည်</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Gjenta alle</string>
<string name="exo_controls_shuffle_description">Tilfeldig rekkefølge</string>
<string name="exo_controls_fullscreen_description">Fullskjermmodus</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">VR-modus</string>
<string name="exo_download_description">Last ned</string>
<string name="exo_download_notification_channel_name">Nedlastinger</string>
<string name="exo_download_downloading">Laster ned</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Alles herhalen</string>
<string name="exo_controls_shuffle_description">Shuffle</string>
<string name="exo_controls_fullscreen_description">Modus \'Volledig scherm\'</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">VR-modus</string>
<string name="exo_download_description">Downloaden</string>
<string name="exo_download_notification_channel_name">Downloads</string>
<string name="exo_download_downloading">Downloaden</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Powtórz wszystkie</string>
<string name="exo_controls_shuffle_description">Odtwarzanie losowe</string>
<string name="exo_controls_fullscreen_description">Tryb pełnoekranowy</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">Tryb VR</string>
<string name="exo_download_description">Pobierz</string>
<string name="exo_download_notification_channel_name">Pobieranie</string>
<string name="exo_download_downloading">Pobieram</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Repetir tudo</string>
<string name="exo_controls_shuffle_description">Reproduzir aleatoriamente</string>
<string name="exo_controls_fullscreen_description">Modo de ecrã inteiro</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">Modo de RV</string>
<string name="exo_download_description">Transferir</string>
<string name="exo_download_notification_channel_name">Transferências</string>
<string name="exo_download_downloading">A transferir…</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Repetir tudo</string>
<string name="exo_controls_shuffle_description">Aleatório</string>
<string name="exo_controls_fullscreen_description">Modo de tela cheia</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">Modo RV</string>
<string name="exo_download_description">Fazer o download</string>
<string name="exo_download_notification_channel_name">Downloads</string>
<string name="exo_download_downloading">Fazendo o download</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Repetați-le pe toate</string>
<string name="exo_controls_shuffle_description">Redați aleatoriu</string>
<string name="exo_controls_fullscreen_description">Modul Ecran complet</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">Mod RV</string>
<string name="exo_download_description">Descărcați</string>
<string name="exo_download_notification_channel_name">Descărcări</string>
<string name="exo_download_downloading">Se descarcă</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Повторять все</string>
<string name="exo_controls_shuffle_description">Перемешать</string>
<string name="exo_controls_fullscreen_description">Полноэкранный режим</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">VR-режим</string>
<string name="exo_download_description">Скачать</string>
<string name="exo_download_notification_channel_name">Скачивания</string>
<string name="exo_download_downloading">Скачивание…</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Opakovať všetko</string>
<string name="exo_controls_shuffle_description">Náhodne prehrávať</string>
<string name="exo_controls_fullscreen_description">Režim celej obrazovky</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">režim VR</string>
<string name="exo_download_description">Stiahnuť</string>
<string name="exo_download_notification_channel_name">Stiahnuté</string>
<string name="exo_download_downloading">Sťahuje sa</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Ponavljanje vseh</string>
<string name="exo_controls_shuffle_description">Naključno predvajanje</string>
<string name="exo_controls_fullscreen_description">Celozaslonski način</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">Način VR</string>
<string name="exo_download_description">Prenos</string>
<string name="exo_download_notification_channel_name">Prenosi</string>
<string name="exo_download_downloading">Prenašanje</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Përsërit të gjitha</string>
<string name="exo_controls_shuffle_description">Përziej</string>
<string name="exo_controls_fullscreen_description">Modaliteti me ekran të plotë</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">Modaliteti RV</string>
<string name="exo_download_description">Shkarko</string>
<string name="exo_download_notification_channel_name">Shkarkimet</string>
<string name="exo_download_downloading">Po shkarkohet</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Понови све</string>
<string name="exo_controls_shuffle_description">Пусти насумично</string>
<string name="exo_controls_fullscreen_description">Режим целог екрана</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">ВР режим</string>
<string name="exo_download_description">Преузми</string>
<string name="exo_download_notification_channel_name">Преузимања</string>
<string name="exo_download_downloading">Преузима се</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Upprepa alla</string>
<string name="exo_controls_shuffle_description">Blanda spår</string>
<string name="exo_controls_fullscreen_description">Helskärmsläge</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">VR-läge</string>
<string name="exo_download_description">Ladda ned</string>
<string name="exo_download_notification_channel_name">Nedladdningar</string>
<string name="exo_download_downloading">Laddar ned</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Rudia zote</string>
<string name="exo_controls_shuffle_description">Changanya</string>
<string name="exo_controls_fullscreen_description">Hali ya skrini nzima</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">Hali ya Uhalisia Pepe</string>
<string name="exo_download_description">Pakua</string>
<string name="exo_download_notification_channel_name">Vipakuliwa</string>
<string name="exo_download_downloading">Inapakua</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">เล่นซ้ำทั้งหมด</string>
<string name="exo_controls_shuffle_description">สุ่ม</string>
<string name="exo_controls_fullscreen_description">โหมดเต็มหน้าจอ</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">โหมด VR</string>
<string name="exo_download_description">ดาวน์โหลด</string>
<string name="exo_download_notification_channel_name">ดาวน์โหลด</string>
<string name="exo_download_downloading">กำลังดาวน์โหลด</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Tümünü tekrarla</string>
<string name="exo_controls_shuffle_description">Karıştır</string>
<string name="exo_controls_fullscreen_description">Tam ekran modu</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">VR modu</string>
<string name="exo_download_description">İndir</string>
<string name="exo_download_notification_channel_name">İndirilenler</string>
<string name="exo_download_downloading">İndiriliyor</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Повторити всі</string>
<string name="exo_controls_shuffle_description">Перемішати</string>
<string name="exo_controls_fullscreen_description">Повноекранний режим</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">Режим віртуальної реальності</string>
<string name="exo_download_description">Завантажити</string>
<string name="exo_download_notification_channel_name">Завантаження</string>
<string name="exo_download_downloading">Завантажується</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Hammasini takrorlash</string>
<string name="exo_controls_shuffle_description">Aralash</string>
<string name="exo_controls_fullscreen_description">Butun ekran rejimi</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">VR rejimi</string>
<string name="exo_download_description">Yuklab olish</string>
<string name="exo_download_notification_channel_name">Yuklanmalar</string>
<string name="exo_download_downloading">Yuklab olinmoqda</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Lặp lại tất cả</string>
<string name="exo_controls_shuffle_description">Phát ngẫu nhiên</string>
<string name="exo_controls_fullscreen_description">Chế độ toàn màn hình</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">Chế độ thực tế ảo</string>
<string name="exo_download_description">Tải xuống</string>
<string name="exo_download_notification_channel_name">Tài nguyên đã tải xuống</string>
<string name="exo_download_downloading">Đang tải xuống</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">全部重复播放</string>
<string name="exo_controls_shuffle_description">随机播放</string>
<string name="exo_controls_fullscreen_description">全屏模式</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">VR 模式</string>
<string name="exo_download_description">下载</string>
<string name="exo_download_notification_channel_name">下载内容</string>
<string name="exo_download_downloading">正在下载</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">全部重複播放</string>
<string name="exo_controls_shuffle_description">隨機播放</string>
<string name="exo_controls_fullscreen_description">全螢幕模式</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">虛擬現實模式</string>
<string name="exo_download_description">下載</string>
<string name="exo_download_notification_channel_name">下載內容</string>
<string name="exo_download_downloading">正在下載</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">重複播放所有項目</string>
<string name="exo_controls_shuffle_description">隨機播放</string>
<string name="exo_controls_fullscreen_description">全螢幕模式</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">虛擬實境模式</string>
<string name="exo_download_description">下載</string>
<string name="exo_download_notification_channel_name">下載</string>
<string name="exo_download_downloading">下載中</string>

View File

@ -12,7 +12,7 @@
<string name="exo_controls_repeat_all_description">Phinda konke</string>
<string name="exo_controls_shuffle_description">Shova</string>
<string name="exo_controls_fullscreen_description">Imodi yesikrini esigcwele</string>
<string name="exo_controls_vr_description">VR mode</string>
<string name="exo_controls_vr_description">Inqubo ye-VR</string>
<string name="exo_download_description">Landa</string>
<string name="exo_download_notification_channel_name">Ukulandwa</string>
<string name="exo_download_downloading">Iyalanda</string>