diff --git a/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoader.java b/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoader.java index cc621c6218..71bc048902 100644 --- a/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoader.java +++ b/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoader.java @@ -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) { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodHolder.java b/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodHolder.java index 4fc21475d9..7becac7b55 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodHolder.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodHolder.java @@ -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); + } + } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodInfo.java b/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodInfo.java index ba19b54c3f..e57100931e 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodInfo.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodInfo.java @@ -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; + } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodQueue.java b/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodQueue.java index 40bc658953..de09fc13a1 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodQueue.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodQueue.java @@ -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) { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/Timeline.java b/library/core/src/main/java/com/google/android/exoplayer2/Timeline.java index 1639920aaa..61a31f7db5 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/Timeline.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/Timeline.java @@ -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); } /** diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/MediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/MediaSource.java index 2a94e884a6..d8335131f9 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/MediaSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/MediaSource.java @@ -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. - * - *

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( diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdPlaybackState.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdPlaybackState.java index 41adb78906..fc1355df6a 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdPlaybackState.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdPlaybackState.java @@ -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; diff --git a/library/core/src/test/java/com/google/android/exoplayer2/MediaPeriodQueueTest.java b/library/core/src/test/java/com/google/android/exoplayer2/MediaPeriodQueueTest.java new file mode 100644 index 0000000000..e8f43e3fe6 --- /dev/null +++ b/library/core/src/test/java/com/google/android/exoplayer2/MediaPeriodQueueTest.java @@ -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)); + } +} diff --git a/library/ui/src/main/res/values-af/strings.xml b/library/ui/src/main/res/values-af/strings.xml index 5b24387028..729d3b9609 100644 --- a/library/ui/src/main/res/values-af/strings.xml +++ b/library/ui/src/main/res/values-af/strings.xml @@ -12,7 +12,7 @@ Herhaal alles Skommel Volskermmodus - VR mode + VR-modus Aflaai Aflaaie Laai tans af diff --git a/library/ui/src/main/res/values-am/strings.xml b/library/ui/src/main/res/values-am/strings.xml index 933019ac9f..bae3776e35 100644 --- a/library/ui/src/main/res/values-am/strings.xml +++ b/library/ui/src/main/res/values-am/strings.xml @@ -12,7 +12,7 @@ ሁሉንም ድገም በውዝ የሙሉ ማያ ሁነታ - VR mode + የቪአር ሁነታ አውርድ የወረዱ በማውረድ ላይ diff --git a/library/ui/src/main/res/values-ar/strings.xml b/library/ui/src/main/res/values-ar/strings.xml index ec79ce48e9..c78aac1e65 100644 --- a/library/ui/src/main/res/values-ar/strings.xml +++ b/library/ui/src/main/res/values-ar/strings.xml @@ -12,7 +12,7 @@ تكرار الكل ترتيب عشوائي وضع ملء الشاشة - VR mode + وضع VR تنزيل التنزيلات جارٍ التنزيل. diff --git a/library/ui/src/main/res/values-az/strings.xml b/library/ui/src/main/res/values-az/strings.xml index 3a80bab572..c2f208e54e 100644 --- a/library/ui/src/main/res/values-az/strings.xml +++ b/library/ui/src/main/res/values-az/strings.xml @@ -12,7 +12,7 @@ Hamısı təkrarlansın Qarışdırın Tam ekran rejimi - VR mode + VR rejimi Endirin Endirmələr Endirilir diff --git a/library/ui/src/main/res/values-b+sr+Latn/strings.xml b/library/ui/src/main/res/values-b+sr+Latn/strings.xml index 23e1463725..6e90860a9c 100644 --- a/library/ui/src/main/res/values-b+sr+Latn/strings.xml +++ b/library/ui/src/main/res/values-b+sr+Latn/strings.xml @@ -12,7 +12,7 @@ Ponovi sve Pusti nasumično Režim celog ekrana - VR mode + VR režim Preuzmi Preuzimanja Preuzima se diff --git a/library/ui/src/main/res/values-be/strings.xml b/library/ui/src/main/res/values-be/strings.xml index 33ae18711a..f0b28d9b2e 100644 --- a/library/ui/src/main/res/values-be/strings.xml +++ b/library/ui/src/main/res/values-be/strings.xml @@ -12,7 +12,7 @@ Паўтарыць усе Перамяшаць Поўнаэкранны рэжым - VR mode + VR-рэжым Спампаваць Спампоўкі Спампоўваецца diff --git a/library/ui/src/main/res/values-bg/strings.xml b/library/ui/src/main/res/values-bg/strings.xml index 50ffac7b0a..fd2b21efce 100644 --- a/library/ui/src/main/res/values-bg/strings.xml +++ b/library/ui/src/main/res/values-bg/strings.xml @@ -12,7 +12,7 @@ Повтаряне на всички Разбъркване Режим на цял екран - VR mode + режим за VR Изтегляне Изтегляния Изтегля се diff --git a/library/ui/src/main/res/values-bs/strings.xml b/library/ui/src/main/res/values-bs/strings.xml index 942921f28e..fce36435fd 100644 --- a/library/ui/src/main/res/values-bs/strings.xml +++ b/library/ui/src/main/res/values-bs/strings.xml @@ -12,7 +12,7 @@ Ponovi sve Izmiješaj Način rada preko cijelog ekrana - VR mode + VR način rada Preuzmi Preuzimanja Preuzimanje diff --git a/library/ui/src/main/res/values-ca/strings.xml b/library/ui/src/main/res/values-ca/strings.xml index c787ff0194..2875ccfe83 100644 --- a/library/ui/src/main/res/values-ca/strings.xml +++ b/library/ui/src/main/res/values-ca/strings.xml @@ -12,7 +12,7 @@ Repeteix tot Reprodueix aleatòriament Mode de pantalla completa - VR mode + Mode RV Baixa Baixades S\'està baixant diff --git a/library/ui/src/main/res/values-cs/strings.xml b/library/ui/src/main/res/values-cs/strings.xml index 31451856fc..7964068543 100644 --- a/library/ui/src/main/res/values-cs/strings.xml +++ b/library/ui/src/main/res/values-cs/strings.xml @@ -12,7 +12,7 @@ Opakovat vše Náhodně Režim celé obrazovky - VR mode + Režim VR Stáhnout Stahování Stahování diff --git a/library/ui/src/main/res/values-da/strings.xml b/library/ui/src/main/res/values-da/strings.xml index 6a446b0963..03409e1cdd 100644 --- a/library/ui/src/main/res/values-da/strings.xml +++ b/library/ui/src/main/res/values-da/strings.xml @@ -12,7 +12,7 @@ Gentag alle Bland Fuld skærm - VR mode + VR-tilstand Download Downloads Downloader diff --git a/library/ui/src/main/res/values-de/strings.xml b/library/ui/src/main/res/values-de/strings.xml index d2b162ba72..a096211b00 100644 --- a/library/ui/src/main/res/values-de/strings.xml +++ b/library/ui/src/main/res/values-de/strings.xml @@ -12,7 +12,7 @@ Alle wiederholen Zufallsmix Vollbildmodus - VR mode + VR-Modus Herunterladen Downloads Wird heruntergeladen diff --git a/library/ui/src/main/res/values-el/strings.xml b/library/ui/src/main/res/values-el/strings.xml index 6eb9fbc6de..598d1c45dc 100644 --- a/library/ui/src/main/res/values-el/strings.xml +++ b/library/ui/src/main/res/values-el/strings.xml @@ -12,7 +12,7 @@ Επανάληψη όλων Τυχαία αναπαραγωγή Λειτουργία πλήρους οθόνης - VR mode + Λειτουργία VR mode Λήψη Λήψεις Λήψη diff --git a/library/ui/src/main/res/values-es-rUS/strings.xml b/library/ui/src/main/res/values-es-rUS/strings.xml index 92604c5e34..1bfc2513ba 100644 --- a/library/ui/src/main/res/values-es-rUS/strings.xml +++ b/library/ui/src/main/res/values-es-rUS/strings.xml @@ -12,7 +12,7 @@ Repetir todo Reproducir aleatoriamente Modo de pantalla completa - VR mode + Modo RV Descargar Descargas Descargando diff --git a/library/ui/src/main/res/values-es/strings.xml b/library/ui/src/main/res/values-es/strings.xml index 4c6fcf7aa7..d424331765 100644 --- a/library/ui/src/main/res/values-es/strings.xml +++ b/library/ui/src/main/res/values-es/strings.xml @@ -12,7 +12,7 @@ Repetir todo Reproducir aleatoriamente Modo de pantalla completa - VR mode + Modo RV Descargar Descargas Descargando diff --git a/library/ui/src/main/res/values-et/strings.xml b/library/ui/src/main/res/values-et/strings.xml index d631499a78..38ee173bec 100644 --- a/library/ui/src/main/res/values-et/strings.xml +++ b/library/ui/src/main/res/values-et/strings.xml @@ -12,7 +12,7 @@ Korda kõiki Esita juhuslikus järjekorras Täisekraani režiim - VR mode + VR-režiim Allalaadimine Allalaadimised Allalaadimine diff --git a/library/ui/src/main/res/values-eu/strings.xml b/library/ui/src/main/res/values-eu/strings.xml index efdee2239d..8bc5f0670c 100644 --- a/library/ui/src/main/res/values-eu/strings.xml +++ b/library/ui/src/main/res/values-eu/strings.xml @@ -12,7 +12,7 @@ Errepikatu guztiak Erreproduzitu ausaz Pantaila osoko modua - VR mode + EB modua Deskargak Deskargak Deskargatzen diff --git a/library/ui/src/main/res/values-fa/strings.xml b/library/ui/src/main/res/values-fa/strings.xml index 50e52edd84..bef2aebcfe 100644 --- a/library/ui/src/main/res/values-fa/strings.xml +++ b/library/ui/src/main/res/values-fa/strings.xml @@ -12,7 +12,7 @@ تکرار همه درهم حالت تمام‌صفحه - VR mode + حالت واقعیت مجازی بارگیری بارگیری‌ها درحال بارگیری diff --git a/library/ui/src/main/res/values-fi/strings.xml b/library/ui/src/main/res/values-fi/strings.xml index 72819a376e..3280dff99b 100644 --- a/library/ui/src/main/res/values-fi/strings.xml +++ b/library/ui/src/main/res/values-fi/strings.xml @@ -12,7 +12,7 @@ Toista kaikki uudelleen Satunnaistoisto Koko näytön tila - VR mode + VR-tila Lataa Lataukset Ladataan diff --git a/library/ui/src/main/res/values-fr-rCA/strings.xml b/library/ui/src/main/res/values-fr-rCA/strings.xml index 6b8d459117..ce125f7d06 100644 --- a/library/ui/src/main/res/values-fr-rCA/strings.xml +++ b/library/ui/src/main/res/values-fr-rCA/strings.xml @@ -12,7 +12,7 @@ Tout lire en boucle Lecture aléatoire Mode Plein écran - VR mode + Mode RV Télécharger Téléchargements Téléchargement en cours… diff --git a/library/ui/src/main/res/values-fr/strings.xml b/library/ui/src/main/res/values-fr/strings.xml index 487007f573..b143832ca1 100644 --- a/library/ui/src/main/res/values-fr/strings.xml +++ b/library/ui/src/main/res/values-fr/strings.xml @@ -12,7 +12,7 @@ Tout lire en boucle Aléatoire Mode plein écran - VR mode + Mode RV Télécharger Téléchargements Téléchargement… diff --git a/library/ui/src/main/res/values-gl/strings.xml b/library/ui/src/main/res/values-gl/strings.xml index a5420df692..c321d28bec 100644 --- a/library/ui/src/main/res/values-gl/strings.xml +++ b/library/ui/src/main/res/values-gl/strings.xml @@ -12,7 +12,7 @@ Repetir todas as pistas Reprodución aleatoria Modo de pantalla completa - VR mode + Modo RV Descargar Descargas Descargando diff --git a/library/ui/src/main/res/values-hi/strings.xml b/library/ui/src/main/res/values-hi/strings.xml index a94462b4d9..373c0f4303 100644 --- a/library/ui/src/main/res/values-hi/strings.xml +++ b/library/ui/src/main/res/values-hi/strings.xml @@ -12,7 +12,7 @@ सभी को दोहराएं शफ़ल करें फ़ुलस्क्रीन मोड - VR mode + VR मोड डाउनलोड करें डाउनलोड की गई मीडिया फ़ाइलें डाउनलोड हो रहा है diff --git a/library/ui/src/main/res/values-hr/strings.xml b/library/ui/src/main/res/values-hr/strings.xml index 624d7f04fe..9958f9b4dc 100644 --- a/library/ui/src/main/res/values-hr/strings.xml +++ b/library/ui/src/main/res/values-hr/strings.xml @@ -12,7 +12,7 @@ Ponovi sve Reproduciraj nasumično Prikaz na cijelom zaslonu - VR mode + VR način Preuzmi Preuzimanja Preuzimanje diff --git a/library/ui/src/main/res/values-hu/strings.xml b/library/ui/src/main/res/values-hu/strings.xml index e1f4d77e96..f517ef6212 100644 --- a/library/ui/src/main/res/values-hu/strings.xml +++ b/library/ui/src/main/res/values-hu/strings.xml @@ -12,7 +12,7 @@ Összes szám ismétlése Keverés Teljes képernyős mód - VR mode + VR-mód Letöltés Letöltések Letöltés folyamatban diff --git a/library/ui/src/main/res/values-hy/strings.xml b/library/ui/src/main/res/values-hy/strings.xml index 390d848aff..d3060b06c4 100644 --- a/library/ui/src/main/res/values-hy/strings.xml +++ b/library/ui/src/main/res/values-hy/strings.xml @@ -12,7 +12,7 @@ Կրկնել բոլորը Խառնել Լիաէկրան ռեժիմ - VR mode + VR ռեժիմ Ներբեռնել Ներբեռնումներ Ներբեռնում diff --git a/library/ui/src/main/res/values-in/strings.xml b/library/ui/src/main/res/values-in/strings.xml index 5ac1696c8b..06c55fc020 100644 --- a/library/ui/src/main/res/values-in/strings.xml +++ b/library/ui/src/main/res/values-in/strings.xml @@ -12,7 +12,7 @@ Ulangi semua Acak Mode layar penuh - VR mode + Mode VR Download Download Mendownload diff --git a/library/ui/src/main/res/values-is/strings.xml b/library/ui/src/main/res/values-is/strings.xml index 4f0fbf0975..4a0b84db2f 100644 --- a/library/ui/src/main/res/values-is/strings.xml +++ b/library/ui/src/main/res/values-is/strings.xml @@ -12,7 +12,7 @@ Endurtaka allt Stokka Allur skjárinn - VR mode + sýndarveruleikastilling Sækja Niðurhal Sækir diff --git a/library/ui/src/main/res/values-it/strings.xml b/library/ui/src/main/res/values-it/strings.xml index 6d070c6aa9..84da9905b2 100644 --- a/library/ui/src/main/res/values-it/strings.xml +++ b/library/ui/src/main/res/values-it/strings.xml @@ -12,7 +12,7 @@ Ripeti tutto Riproduzione casuale Modalità a schermo intero - VR mode + Modalità VR Scarica Download Download… diff --git a/library/ui/src/main/res/values-ja/strings.xml b/library/ui/src/main/res/values-ja/strings.xml index eea78b2fb5..e159292348 100644 --- a/library/ui/src/main/res/values-ja/strings.xml +++ b/library/ui/src/main/res/values-ja/strings.xml @@ -12,7 +12,7 @@ 全曲をリピート シャッフル 全画面モード - VR mode + VR モード ダウンロード ダウンロード ダウンロードしています diff --git a/library/ui/src/main/res/values-ka/strings.xml b/library/ui/src/main/res/values-ka/strings.xml index 16f3bea5bf..ff879c5dd8 100644 --- a/library/ui/src/main/res/values-ka/strings.xml +++ b/library/ui/src/main/res/values-ka/strings.xml @@ -12,7 +12,7 @@ ყველას გამეორება არეულად დაკვრა სრულეკრანიანი რეჟიმი - VR mode + VR რეჟიმი ჩამოტვირთვა ჩამოტვირთვები მიმდინარეობს ჩამოტვირთვა diff --git a/library/ui/src/main/res/values-kk/strings.xml b/library/ui/src/main/res/values-kk/strings.xml index 26fe5d6019..f634579932 100644 --- a/library/ui/src/main/res/values-kk/strings.xml +++ b/library/ui/src/main/res/values-kk/strings.xml @@ -12,7 +12,7 @@ Барлығын қайталау Араластыру Толық экран режимі - VR mode + VR режимі Жүктеп алу Жүктеп алынғандар Жүктеп алынуда diff --git a/library/ui/src/main/res/values-km/strings.xml b/library/ui/src/main/res/values-km/strings.xml index ce88214f35..17476b16d1 100644 --- a/library/ui/src/main/res/values-km/strings.xml +++ b/library/ui/src/main/res/values-km/strings.xml @@ -12,7 +12,7 @@ លេង​ឡើងវិញ​ទាំងអស់ ច្របល់ មុខងារពេញ​អេក្រង់ - VR mode + មុខងារ VR ទាញយក ទាញយក កំពុង​ទាញ​យក diff --git a/library/ui/src/main/res/values-ko/strings.xml b/library/ui/src/main/res/values-ko/strings.xml index d61346ff90..a4096711f2 100644 --- a/library/ui/src/main/res/values-ko/strings.xml +++ b/library/ui/src/main/res/values-ko/strings.xml @@ -12,7 +12,7 @@ 모두 반복 셔플 전체화면 모드 - VR mode + 가상 현실 모드 다운로드 다운로드 다운로드 중 diff --git a/library/ui/src/main/res/values-ky/strings.xml b/library/ui/src/main/res/values-ky/strings.xml index ee7a90ede7..c85b70f108 100644 --- a/library/ui/src/main/res/values-ky/strings.xml +++ b/library/ui/src/main/res/values-ky/strings.xml @@ -12,7 +12,7 @@ Баарын кайталоо Аралаштыруу Толук экран режими - VR mode + VR режими Жүктөп алуу Жүктөлүп алынгандар Жүктөлүп алынууда diff --git a/library/ui/src/main/res/values-lt/strings.xml b/library/ui/src/main/res/values-lt/strings.xml index b3d296b4d8..12710e41fd 100644 --- a/library/ui/src/main/res/values-lt/strings.xml +++ b/library/ui/src/main/res/values-lt/strings.xml @@ -12,7 +12,7 @@ Kartoti viską Maišyti Viso ekrano režimas - VR mode + VR režimas Atsisiųsti Atsisiuntimai Atsisiunčiama diff --git a/library/ui/src/main/res/values-lv/strings.xml b/library/ui/src/main/res/values-lv/strings.xml index ed61a7a27f..a55570112f 100644 --- a/library/ui/src/main/res/values-lv/strings.xml +++ b/library/ui/src/main/res/values-lv/strings.xml @@ -12,7 +12,7 @@ Atkārtot visu Atskaņot jauktā secībā Pilnekrāna režīms - VR mode + VR režīms Lejupielādēt Lejupielādes Notiek lejupielāde diff --git a/library/ui/src/main/res/values-mk/strings.xml b/library/ui/src/main/res/values-mk/strings.xml index 4ed15c3913..f4382aaeae 100644 --- a/library/ui/src/main/res/values-mk/strings.xml +++ b/library/ui/src/main/res/values-mk/strings.xml @@ -12,7 +12,7 @@ Повтори ги сите Измешај Режим на цел екран - VR mode + Режим на VR Преземи Преземања Се презема diff --git a/library/ui/src/main/res/values-mn/strings.xml b/library/ui/src/main/res/values-mn/strings.xml index 81c90f34c5..9d8fb29408 100644 --- a/library/ui/src/main/res/values-mn/strings.xml +++ b/library/ui/src/main/res/values-mn/strings.xml @@ -12,7 +12,7 @@ Бүгдийг нь дахин тоглуулах Холих Бүтэн дэлгэцийн горим - VR mode + VR горим Татах Татaлт Татаж байна diff --git a/library/ui/src/main/res/values-mr/strings.xml b/library/ui/src/main/res/values-mr/strings.xml index 7b698e5bcf..d1ee83be30 100644 --- a/library/ui/src/main/res/values-mr/strings.xml +++ b/library/ui/src/main/res/values-mr/strings.xml @@ -12,7 +12,7 @@ सर्व रीपीट करा शफल करा फुल स्क्रीन मोड - VR mode + VR मोड डाउनलोड करा डाउनलोड डाउनलोड होत आहे diff --git a/library/ui/src/main/res/values-ms/strings.xml b/library/ui/src/main/res/values-ms/strings.xml index cfe822f2b8..3b3fc3109f 100644 --- a/library/ui/src/main/res/values-ms/strings.xml +++ b/library/ui/src/main/res/values-ms/strings.xml @@ -12,7 +12,7 @@ Ulang semua Rombak Mod skrin penuh - VR mode + Mod VR Muat turun Muat turun Memuat turun diff --git a/library/ui/src/main/res/values-my/strings.xml b/library/ui/src/main/res/values-my/strings.xml index 34e69c2977..68c1f27056 100644 --- a/library/ui/src/main/res/values-my/strings.xml +++ b/library/ui/src/main/res/values-my/strings.xml @@ -12,7 +12,7 @@ အားလုံး ပြန်ကျော့ရန် ရောသမမွှေ မျက်နှာပြင်အပြည့် မုဒ် - VR mode + VR မုဒ် ဒေါင်းလုဒ် လုပ်ရန် ဒေါင်းလုဒ်များ ဒေါင်းလုဒ်လုပ်နေသည် diff --git a/library/ui/src/main/res/values-nb/strings.xml b/library/ui/src/main/res/values-nb/strings.xml index 5f8e862f5d..e24dcbf959 100644 --- a/library/ui/src/main/res/values-nb/strings.xml +++ b/library/ui/src/main/res/values-nb/strings.xml @@ -12,7 +12,7 @@ Gjenta alle Tilfeldig rekkefølge Fullskjermmodus - VR mode + VR-modus Last ned Nedlastinger Laster ned diff --git a/library/ui/src/main/res/values-nl/strings.xml b/library/ui/src/main/res/values-nl/strings.xml index a3401a0114..18dd96ed9e 100644 --- a/library/ui/src/main/res/values-nl/strings.xml +++ b/library/ui/src/main/res/values-nl/strings.xml @@ -12,7 +12,7 @@ Alles herhalen Shuffle Modus \'Volledig scherm\' - VR mode + VR-modus Downloaden Downloads Downloaden diff --git a/library/ui/src/main/res/values-pl/strings.xml b/library/ui/src/main/res/values-pl/strings.xml index adb81b5779..66eb7d81c7 100644 --- a/library/ui/src/main/res/values-pl/strings.xml +++ b/library/ui/src/main/res/values-pl/strings.xml @@ -12,7 +12,7 @@ Powtórz wszystkie Odtwarzanie losowe Tryb pełnoekranowy - VR mode + Tryb VR Pobierz Pobieranie Pobieram diff --git a/library/ui/src/main/res/values-pt-rPT/strings.xml b/library/ui/src/main/res/values-pt-rPT/strings.xml index f5d8092723..5d199683d9 100644 --- a/library/ui/src/main/res/values-pt-rPT/strings.xml +++ b/library/ui/src/main/res/values-pt-rPT/strings.xml @@ -12,7 +12,7 @@ Repetir tudo Reproduzir aleatoriamente Modo de ecrã inteiro - VR mode + Modo de RV Transferir Transferências A transferir… diff --git a/library/ui/src/main/res/values-pt/strings.xml b/library/ui/src/main/res/values-pt/strings.xml index 2e86dd7acd..151d235554 100644 --- a/library/ui/src/main/res/values-pt/strings.xml +++ b/library/ui/src/main/res/values-pt/strings.xml @@ -12,7 +12,7 @@ Repetir tudo Aleatório Modo de tela cheia - VR mode + Modo RV Fazer o download Downloads Fazendo o download diff --git a/library/ui/src/main/res/values-ro/strings.xml b/library/ui/src/main/res/values-ro/strings.xml index a0bd5a0a16..93f5129d13 100644 --- a/library/ui/src/main/res/values-ro/strings.xml +++ b/library/ui/src/main/res/values-ro/strings.xml @@ -12,7 +12,7 @@ Repetați-le pe toate Redați aleatoriu Modul Ecran complet - VR mode + Mod RV Descărcați Descărcări Se descarcă diff --git a/library/ui/src/main/res/values-ru/strings.xml b/library/ui/src/main/res/values-ru/strings.xml index a45022ffb4..77d96f0bc0 100644 --- a/library/ui/src/main/res/values-ru/strings.xml +++ b/library/ui/src/main/res/values-ru/strings.xml @@ -12,7 +12,7 @@ Повторять все Перемешать Полноэкранный режим - VR mode + VR-режим Скачать Скачивания Скачивание… diff --git a/library/ui/src/main/res/values-sk/strings.xml b/library/ui/src/main/res/values-sk/strings.xml index 2d3997ed89..ae6c0fbb12 100644 --- a/library/ui/src/main/res/values-sk/strings.xml +++ b/library/ui/src/main/res/values-sk/strings.xml @@ -12,7 +12,7 @@ Opakovať všetko Náhodne prehrávať Režim celej obrazovky - VR mode + režim VR Stiahnuť Stiahnuté Sťahuje sa diff --git a/library/ui/src/main/res/values-sl/strings.xml b/library/ui/src/main/res/values-sl/strings.xml index 01fa00320a..16d9a6af03 100644 --- a/library/ui/src/main/res/values-sl/strings.xml +++ b/library/ui/src/main/res/values-sl/strings.xml @@ -12,7 +12,7 @@ Ponavljanje vseh Naključno predvajanje Celozaslonski način - VR mode + Način VR Prenos Prenosi Prenašanje diff --git a/library/ui/src/main/res/values-sq/strings.xml b/library/ui/src/main/res/values-sq/strings.xml index 29007fa20e..fcef9643e8 100644 --- a/library/ui/src/main/res/values-sq/strings.xml +++ b/library/ui/src/main/res/values-sq/strings.xml @@ -12,7 +12,7 @@ Përsërit të gjitha Përziej Modaliteti me ekran të plotë - VR mode + Modaliteti RV Shkarko Shkarkimet Po shkarkohet diff --git a/library/ui/src/main/res/values-sr/strings.xml b/library/ui/src/main/res/values-sr/strings.xml index 659fb113bc..19018f0bac 100644 --- a/library/ui/src/main/res/values-sr/strings.xml +++ b/library/ui/src/main/res/values-sr/strings.xml @@ -12,7 +12,7 @@ Понови све Пусти насумично Режим целог екрана - VR mode + ВР режим Преузми Преузимања Преузима се diff --git a/library/ui/src/main/res/values-sv/strings.xml b/library/ui/src/main/res/values-sv/strings.xml index d9c48aaebe..1f3e7db320 100644 --- a/library/ui/src/main/res/values-sv/strings.xml +++ b/library/ui/src/main/res/values-sv/strings.xml @@ -12,7 +12,7 @@ Upprepa alla Blanda spår Helskärmsläge - VR mode + VR-läge Ladda ned Nedladdningar Laddar ned diff --git a/library/ui/src/main/res/values-sw/strings.xml b/library/ui/src/main/res/values-sw/strings.xml index 83e6b7bc47..b699116dd7 100644 --- a/library/ui/src/main/res/values-sw/strings.xml +++ b/library/ui/src/main/res/values-sw/strings.xml @@ -12,7 +12,7 @@ Rudia zote Changanya Hali ya skrini nzima - VR mode + Hali ya Uhalisia Pepe Pakua Vipakuliwa Inapakua diff --git a/library/ui/src/main/res/values-th/strings.xml b/library/ui/src/main/res/values-th/strings.xml index 454a0f361d..7827c99d93 100644 --- a/library/ui/src/main/res/values-th/strings.xml +++ b/library/ui/src/main/res/values-th/strings.xml @@ -12,7 +12,7 @@ เล่นซ้ำทั้งหมด สุ่ม โหมดเต็มหน้าจอ - VR mode + โหมด VR ดาวน์โหลด ดาวน์โหลด กำลังดาวน์โหลด diff --git a/library/ui/src/main/res/values-tr/strings.xml b/library/ui/src/main/res/values-tr/strings.xml index 43bf4f885f..d47ca1e2aa 100644 --- a/library/ui/src/main/res/values-tr/strings.xml +++ b/library/ui/src/main/res/values-tr/strings.xml @@ -12,7 +12,7 @@ Tümünü tekrarla Karıştır Tam ekran modu - VR mode + VR modu İndir İndirilenler İndiriliyor diff --git a/library/ui/src/main/res/values-uk/strings.xml b/library/ui/src/main/res/values-uk/strings.xml index 0b00dbbe82..5f3097a256 100644 --- a/library/ui/src/main/res/values-uk/strings.xml +++ b/library/ui/src/main/res/values-uk/strings.xml @@ -12,7 +12,7 @@ Повторити всі Перемішати Повноекранний режим - VR mode + Режим віртуальної реальності Завантажити Завантаження Завантажується diff --git a/library/ui/src/main/res/values-uz/strings.xml b/library/ui/src/main/res/values-uz/strings.xml index b5cea1f59e..9427fc4149 100644 --- a/library/ui/src/main/res/values-uz/strings.xml +++ b/library/ui/src/main/res/values-uz/strings.xml @@ -12,7 +12,7 @@ Hammasini takrorlash Aralash Butun ekran rejimi - VR mode + VR rejimi Yuklab olish Yuklanmalar Yuklab olinmoqda diff --git a/library/ui/src/main/res/values-vi/strings.xml b/library/ui/src/main/res/values-vi/strings.xml index d5299d3e6d..ae6abb90f5 100644 --- a/library/ui/src/main/res/values-vi/strings.xml +++ b/library/ui/src/main/res/values-vi/strings.xml @@ -12,7 +12,7 @@ Lặp lại tất cả Phát ngẫu nhiên Chế độ toàn màn hình - VR mode + Chế độ thực tế ảo Tải xuống Tài nguyên đã tải xuống Đang tải xuống diff --git a/library/ui/src/main/res/values-zh-rCN/strings.xml b/library/ui/src/main/res/values-zh-rCN/strings.xml index ad3e4fe68d..cfb9a6fb11 100644 --- a/library/ui/src/main/res/values-zh-rCN/strings.xml +++ b/library/ui/src/main/res/values-zh-rCN/strings.xml @@ -12,7 +12,7 @@ 全部重复播放 随机播放 全屏模式 - VR mode + VR 模式 下载 下载内容 正在下载 diff --git a/library/ui/src/main/res/values-zh-rHK/strings.xml b/library/ui/src/main/res/values-zh-rHK/strings.xml index f538231146..be96b852f5 100644 --- a/library/ui/src/main/res/values-zh-rHK/strings.xml +++ b/library/ui/src/main/res/values-zh-rHK/strings.xml @@ -12,7 +12,7 @@ 全部重複播放 隨機播放 全螢幕模式 - VR mode + 虛擬現實模式 下載 下載內容 正在下載 diff --git a/library/ui/src/main/res/values-zh-rTW/strings.xml b/library/ui/src/main/res/values-zh-rTW/strings.xml index da4b01cc93..c17c9e44ed 100644 --- a/library/ui/src/main/res/values-zh-rTW/strings.xml +++ b/library/ui/src/main/res/values-zh-rTW/strings.xml @@ -12,7 +12,7 @@ 重複播放所有項目 隨機播放 全螢幕模式 - VR mode + 虛擬實境模式 下載 下載 下載中 diff --git a/library/ui/src/main/res/values-zu/strings.xml b/library/ui/src/main/res/values-zu/strings.xml index 4b80136a85..70eccd3c36 100644 --- a/library/ui/src/main/res/values-zu/strings.xml +++ b/library/ui/src/main/res/values-zu/strings.xml @@ -12,7 +12,7 @@ Phinda konke Shova Imodi yesikrini esigcwele - VR mode + Inqubo ye-VR Landa Ukulandwa Iyalanda