Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
SDK
/
exoplayer
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
b911e2ee
authored
Feb 02, 2022
by
bachinger
Committed by
Ian Baker
Feb 04, 2022
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Mark played ads in multi-period VOD streams
#minor-release PiperOrigin-RevId: 425842813
parent
392ec6f3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
161 additions
and
26 deletions
extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaServerSideAdInsertionMediaSource.java
extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaUtil.java
extensions/ima/src/test/java/com/google/android/exoplayer2/ext/ima/ImaUtilTest.java
extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaServerSideAdInsertionMediaSource.java
View file @
b911e2ee
...
@@ -16,12 +16,14 @@
...
@@ -16,12 +16,14 @@
package
com
.
google
.
android
.
exoplayer2
.
ext
.
ima
;
package
com
.
google
.
android
.
exoplayer2
.
ext
.
ima
;
import
static
com
.
google
.
android
.
exoplayer2
.
ext
.
ima
.
ImaUtil
.
expandAdGroupPlaceholder
;
import
static
com
.
google
.
android
.
exoplayer2
.
ext
.
ima
.
ImaUtil
.
expandAdGroupPlaceholder
;
import
static
com
.
google
.
android
.
exoplayer2
.
ext
.
ima
.
ImaUtil
.
getAdGroupAndIndexInMultiPeriodWindow
;
import
static
com
.
google
.
android
.
exoplayer2
.
ext
.
ima
.
ImaUtil
.
splitAdPlaybackStateForPeriods
;
import
static
com
.
google
.
android
.
exoplayer2
.
ext
.
ima
.
ImaUtil
.
splitAdPlaybackStateForPeriods
;
import
static
com
.
google
.
android
.
exoplayer2
.
ext
.
ima
.
ImaUtil
.
updateAdDurationAndPropagate
;
import
static
com
.
google
.
android
.
exoplayer2
.
ext
.
ima
.
ImaUtil
.
updateAdDurationAndPropagate
;
import
static
com
.
google
.
android
.
exoplayer2
.
ext
.
ima
.
ImaUtil
.
updateAdDurationInAdGroup
;
import
static
com
.
google
.
android
.
exoplayer2
.
ext
.
ima
.
ImaUtil
.
updateAdDurationInAdGroup
;
import
static
com
.
google
.
android
.
exoplayer2
.
source
.
ads
.
ServerSideAdInsertionUtil
.
addAdGroupToAdPlaybackState
;
import
static
com
.
google
.
android
.
exoplayer2
.
source
.
ads
.
ServerSideAdInsertionUtil
.
addAdGroupToAdPlaybackState
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Assertions
.
checkNotNull
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Assertions
.
checkNotNull
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Assertions
.
checkState
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Assertions
.
checkState
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Util
.
msToUs
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Util
.
secToUs
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Util
.
secToUs
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Util
.
sum
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Util
.
sum
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Util
.
usToMs
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Util
.
usToMs
;
...
@@ -30,6 +32,7 @@ import static java.lang.Math.min;
...
@@ -30,6 +32,7 @@ import static java.lang.Math.min;
import
android.content.Context
;
import
android.content.Context
;
import
android.net.Uri
;
import
android.net.Uri
;
import
android.os.Handler
;
import
android.os.Handler
;
import
android.util.Pair
;
import
android.view.ViewGroup
;
import
android.view.ViewGroup
;
import
androidx.annotation.MainThread
;
import
androidx.annotation.MainThread
;
import
androidx.annotation.Nullable
;
import
androidx.annotation.Nullable
;
...
@@ -618,18 +621,26 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
...
@@ -618,18 +621,26 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
return
;
return
;
}
}
if
(
oldPosition
.
adGroupIndex
!=
C
.
INDEX_UNSET
&&
newPosition
.
adGroupIndex
==
C
.
INDEX_UNSET
)
{
if
(
oldPosition
.
adGroupIndex
!=
C
.
INDEX_UNSET
)
{
AdPlaybackState
newAdPlaybackState
=
adPlaybackState
;
int
adGroupIndex
=
oldPosition
.
adGroupIndex
;
for
(
int
i
=
0
;
i
<=
oldPosition
.
adIndexInAdGroup
;
i
++)
{
int
adIndexInAdGroup
=
oldPosition
.
adIndexInAdGroup
;
int
state
=
newAdPlaybackState
.
getAdGroup
(
oldPosition
.
adGroupIndex
).
states
[
i
];
Timeline
timeline
=
player
.
getCurrentTimeline
();
if
(
state
!=
AdPlaybackState
.
AD_STATE_SKIPPED
Timeline
.
Window
window
=
&&
state
!=
AdPlaybackState
.
AD_STATE_ERROR
)
{
timeline
.
getWindow
(
oldPosition
.
mediaItemIndex
,
new
Timeline
.
Window
());
newAdPlaybackState
=
if
(
window
.
lastPeriodIndex
>
window
.
firstPeriodIndex
)
{
newAdPlaybackState
.
withPlayedAd
(
// Map adGroupIndex and adIndexInAdGroup to multi-period window.
oldPosition
.
adGroupIndex
,
/* adIndexInAdGroup= */
i
);
Pair
<
Integer
,
Integer
>
adGroupIndexAndAdIndexInAdGroup
=
}
getAdGroupAndIndexInMultiPeriodWindow
(
oldPosition
.
periodIndex
,
adPlaybackState
,
timeline
);
adGroupIndex
=
adGroupIndexAndAdIndexInAdGroup
.
first
;
adIndexInAdGroup
=
adGroupIndexAndAdIndexInAdGroup
.
second
;
}
int
adState
=
adPlaybackState
.
getAdGroup
(
adGroupIndex
).
states
[
adIndexInAdGroup
];
if
(
adState
==
AdPlaybackState
.
AD_STATE_AVAILABLE
||
adState
==
AdPlaybackState
.
AD_STATE_UNAVAILABLE
)
{
setAdPlaybackState
(
adPlaybackState
.
withPlayedAd
(
adGroupIndex
,
/* adIndexInAdGroup= */
adIndexInAdGroup
));
}
}
setAdPlaybackState
(
newAdPlaybackState
);
}
}
}
}
...
@@ -698,8 +709,7 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
...
@@ -698,8 +709,7 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
long
positionInWindowUs
=
long
positionInWindowUs
=
timeline
.
getPeriod
(
player
.
getCurrentPeriodIndex
(),
new
Timeline
.
Period
())
timeline
.
getPeriod
(
player
.
getCurrentPeriodIndex
(),
new
Timeline
.
Period
())
.
positionInWindowUs
;
.
positionInWindowUs
;
long
currentPeriodPosition
=
long
currentPeriodPosition
=
msToUs
(
player
.
getCurrentPosition
())
-
positionInWindowUs
;
Util
.
msToUs
(
player
.
getCurrentPosition
())
-
positionInWindowUs
;
newAdPlaybackState
=
newAdPlaybackState
=
addLiveAdBreak
(
addLiveAdBreak
(
event
.
getAd
(),
event
.
getAd
(),
...
...
extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaUtil.java
View file @
b911e2ee
...
@@ -23,6 +23,7 @@ import static java.lang.Math.max;
...
@@ -23,6 +23,7 @@ import static java.lang.Math.max;
import
android.content.Context
;
import
android.content.Context
;
import
android.os.Looper
;
import
android.os.Looper
;
import
android.util.Pair
;
import
android.view.View
;
import
android.view.View
;
import
android.view.ViewGroup
;
import
android.view.ViewGroup
;
import
androidx.annotation.CheckResult
;
import
androidx.annotation.CheckResult
;
...
@@ -355,14 +356,13 @@ import java.util.Set;
...
@@ -355,14 +356,13 @@ import java.util.Set;
/**
/**
* Splits an {@link AdPlaybackState} into a separate {@link AdPlaybackState} for each period of a
* Splits an {@link AdPlaybackState} into a separate {@link AdPlaybackState} for each period of a
* content timeline. Ad group times are expected to not take previous ad duration into account and
* content timeline.
* needs to be translated to the actual position in the {@code contentTimeline} by adding prior ad
* durations.
*
*
* <p>If a period is enclosed by an ad group, the period is considered an ad period and gets an ad
* <p>If a period is enclosed by an ad group, the period is considered an ad period. Splitting
* playback state assigned with a single ad in a single ad group. The duration of the ad is set to
* results in a separate {@link AdPlaybackState ad playback state} for each period that has either
* the duration of the period. All other periods are considered content periods with an empty ad
* no ads or a single ad. In the latter case, the duration of the single ad is set to the duration
* playback state without any ads.
* of the period consuming the entire duration of the period. Accordingly an ad period does not
* contribute to the duration of the containing window.
*
*
* @param adPlaybackState The ad playback state to be split.
* @param adPlaybackState The ad playback state to be split.
* @param contentTimeline The content timeline for each period of which to create an {@link
* @param contentTimeline The content timeline for each period of which to create an {@link
...
@@ -398,15 +398,19 @@ import java.util.Set;
...
@@ -398,15 +398,19 @@ import java.util.Set;
long
elapsedAdGroupAdDurationUs
=
0
;
long
elapsedAdGroupAdDurationUs
=
0
;
for
(
int
j
=
periodIndex
;
j
<
contentTimeline
.
getPeriodCount
();
j
++)
{
for
(
int
j
=
periodIndex
;
j
<
contentTimeline
.
getPeriodCount
();
j
++)
{
contentTimeline
.
getPeriod
(
j
,
period
,
/* setIds= */
true
);
contentTimeline
.
getPeriod
(
j
,
period
,
/* setIds= */
true
);
if
(
totalElapsedContentDurationUs
<
adGroup
.
timeUs
)
{
// TODO(b/192231683) Remove subtracted US from ad group time when we can upgrade the SDK.
// Subtract one microsecond to work around rounding errors with adGroup.timeUs.
if
(
totalElapsedContentDurationUs
<
adGroup
.
timeUs
-
1
)
{
// Period starts before the ad group, so it is a content period.
// Period starts before the ad group, so it is a content period.
adPlaybackStates
.
put
(
checkNotNull
(
period
.
uid
),
contentOnlyAdPlaybackState
);
adPlaybackStates
.
put
(
checkNotNull
(
period
.
uid
),
contentOnlyAdPlaybackState
);
totalElapsedContentDurationUs
+=
period
.
durationUs
;
totalElapsedContentDurationUs
+=
period
.
durationUs
;
}
else
{
}
else
{
long
periodStartUs
=
totalElapsedContentDurationUs
+
elapsedAdGroupAdDurationUs
;
long
periodStartUs
=
totalElapsedContentDurationUs
+
elapsedAdGroupAdDurationUs
;
if
(
periodStartUs
+
period
.
durationUs
<=
adGroup
.
timeUs
+
adGroupDurationUs
)
{
// TODO(b/192231683) Remove additional US when we can upgrade the SDK.
// The period ends before the end of the ad group, so it is an ad period (Note: An ad
// Add one microsecond to work around rounding errors with adGroup.timeUs.
// reported by the IMA SDK may span multiple periods).
if
(
periodStartUs
+
period
.
durationUs
<=
adGroup
.
timeUs
+
adGroupDurationUs
+
1
)
{
// The period ends before the end of the ad group, so it is an ad period (Note: A VOD ad
// reported by the IMA SDK spans multiple periods before the LOADED event arrives).
adPlaybackStates
.
put
(
adPlaybackStates
.
put
(
checkNotNull
(
period
.
uid
),
checkNotNull
(
period
.
uid
),
splitAdGroupForPeriod
(
adsId
,
adGroup
,
periodStartUs
,
period
.
durationUs
));
splitAdGroupForPeriod
(
adsId
,
adGroup
,
periodStartUs
,
period
.
durationUs
));
...
@@ -430,7 +434,6 @@ import java.util.Set;
...
@@ -430,7 +434,6 @@ import java.util.Set;
private
static
AdPlaybackState
splitAdGroupForPeriod
(
private
static
AdPlaybackState
splitAdGroupForPeriod
(
Object
adsId
,
AdPlaybackState
.
AdGroup
adGroup
,
long
periodStartUs
,
long
periodDurationUs
)
{
Object
adsId
,
AdPlaybackState
.
AdGroup
adGroup
,
long
periodStartUs
,
long
periodDurationUs
)
{
checkState
(
adGroup
.
timeUs
<=
periodStartUs
);
AdPlaybackState
adPlaybackState
=
AdPlaybackState
adPlaybackState
=
new
AdPlaybackState
(
checkNotNull
(
adsId
),
/* adGroupTimesUs...= */
0
)
new
AdPlaybackState
(
checkNotNull
(
adsId
),
/* adGroupTimesUs...= */
0
)
.
withAdCount
(
/* adGroupIndex= */
0
,
/* adCount= */
1
)
.
withAdCount
(
/* adGroupIndex= */
0
,
/* adCount= */
1
)
...
@@ -465,5 +468,54 @@ import java.util.Set;
...
@@ -465,5 +468,54 @@ import java.util.Set;
return
adPlaybackState
;
return
adPlaybackState
;
}
}
/**
* Returns the {@code adGroupIndex} and the {@code adIndexInAdGroup} for the given period index of
* an ad period.
*
* @param adPeriodIndex The period index of the ad period.
* @param adPlaybackState The ad playback state that holds the ad group and ad information.
* @param timeline The timeline that contains the ad period.
* @return A pair with the ad group index (first) and the ad index in that ad group (second).
*/
public
static
Pair
<
Integer
,
Integer
>
getAdGroupAndIndexInMultiPeriodWindow
(
int
adPeriodIndex
,
AdPlaybackState
adPlaybackState
,
Timeline
timeline
)
{
Timeline
.
Period
period
=
new
Timeline
.
Period
();
int
periodIndex
=
0
;
long
totalElapsedContentDurationUs
=
0
;
for
(
int
i
=
adPlaybackState
.
removedAdGroupCount
;
i
<
adPlaybackState
.
adGroupCount
;
i
++)
{
int
adIndexInAdGroup
=
0
;
AdPlaybackState
.
AdGroup
adGroup
=
adPlaybackState
.
getAdGroup
(
/* adGroupIndex= */
i
);
long
adGroupDurationUs
=
sum
(
adGroup
.
durationsUs
);
long
elapsedAdGroupAdDurationUs
=
0
;
for
(
int
j
=
periodIndex
;
j
<
timeline
.
getPeriodCount
();
j
++)
{
timeline
.
getPeriod
(
j
,
period
,
/* setIds= */
true
);
// TODO(b/192231683) Remove subtracted US from ad group time when we can upgrade the SDK.
// Subtract one microsecond to work around rounding errors with adGroup.timeUs.
if
(
totalElapsedContentDurationUs
<
adGroup
.
timeUs
-
1
)
{
// Period starts before the ad group, so it is a content period.
totalElapsedContentDurationUs
+=
period
.
durationUs
;
}
else
{
long
periodStartUs
=
totalElapsedContentDurationUs
+
elapsedAdGroupAdDurationUs
;
// TODO(b/192231683) Remove additional US when we can upgrade the SDK.
// Add one microsecond to work around rounding errors with adGroup.timeUs.
if
(
periodStartUs
+
period
.
durationUs
<=
adGroup
.
timeUs
+
adGroupDurationUs
+
1
)
{
// The period ends before the end of the ad group, so it is an ad period.
if
(
j
==
adPeriodIndex
)
{
return
new
Pair
<>(
/* adGroupIndex= */
i
,
adIndexInAdGroup
);
}
elapsedAdGroupAdDurationUs
+=
period
.
durationUs
;
adIndexInAdGroup
++;
}
else
{
// Period is after the current ad group. Continue with next ad group.
break
;
}
}
// Increment the period index to the next unclassified period.
periodIndex
++;
}
}
throw
new
IllegalStateException
();
}
private
ImaUtil
()
{}
private
ImaUtil
()
{}
}
}
extensions/ima/src/test/java/com/google/android/exoplayer2/ext/ima/ImaUtilTest.java
View file @
b911e2ee
...
@@ -15,6 +15,7 @@
...
@@ -15,6 +15,7 @@
*/
*/
package
com
.
google
.
android
.
exoplayer2
.
ext
.
ima
;
package
com
.
google
.
android
.
exoplayer2
.
ext
.
ima
;
import
static
com
.
google
.
android
.
exoplayer2
.
ext
.
ima
.
ImaUtil
.
getAdGroupAndIndexInMultiPeriodWindow
;
import
static
com
.
google
.
android
.
exoplayer2
.
testutil
.
FakeTimeline
.
TimelineWindowDefinition
.
DEFAULT_WINDOW_DURATION_US
;
import
static
com
.
google
.
android
.
exoplayer2
.
testutil
.
FakeTimeline
.
TimelineWindowDefinition
.
DEFAULT_WINDOW_DURATION_US
;
import
static
com
.
google
.
android
.
exoplayer2
.
testutil
.
FakeTimeline
.
TimelineWindowDefinition
.
DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US
;
import
static
com
.
google
.
android
.
exoplayer2
.
testutil
.
FakeTimeline
.
TimelineWindowDefinition
.
DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US
;
import
static
com
.
google
.
common
.
truth
.
Truth
.
assertThat
;
import
static
com
.
google
.
common
.
truth
.
Truth
.
assertThat
;
...
@@ -27,6 +28,7 @@ import com.google.android.exoplayer2.source.ads.AdPlaybackState;
...
@@ -27,6 +28,7 @@ import com.google.android.exoplayer2.source.ads.AdPlaybackState;
import
com.google.android.exoplayer2.source.ads.ServerSideAdInsertionUtil
;
import
com.google.android.exoplayer2.source.ads.ServerSideAdInsertionUtil
;
import
com.google.android.exoplayer2.testutil.FakeTimeline
;
import
com.google.android.exoplayer2.testutil.FakeTimeline
;
import
com.google.common.collect.ImmutableMap
;
import
com.google.common.collect.ImmutableMap
;
import
org.junit.Assert
;
import
org.junit.Test
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.junit.runner.RunWith
;
...
@@ -463,7 +465,9 @@ public class ImaUtilTest {
...
@@ -463,7 +465,9 @@ public class ImaUtilTest {
AdPlaybackState
adPlaybackState
=
AdPlaybackState
adPlaybackState
=
new
AdPlaybackState
(
new
AdPlaybackState
(
/* adsId= */
"adsId"
,
/* adsId= */
"adsId"
,
DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US
+
periodDurationUs
+
1
)
// TODO(b/192231683) Reduce additional period duration to 1 when rounding work
// around removed.
DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US
+
periodDurationUs
+
2
)
.
withAdCount
(
/* adGroupIndex= */
0
,
1
)
.
withAdCount
(
/* adGroupIndex= */
0
,
1
)
.
withAdDurationsUs
(
/* adGroupIndex= */
0
,
/* adDurationsUs...= */
periodDurationUs
)
.
withAdDurationsUs
(
/* adGroupIndex= */
0
,
/* adDurationsUs...= */
periodDurationUs
)
.
withIsServerSideInserted
(
/* adGroupIndex= */
0
,
true
);
.
withIsServerSideInserted
(
/* adGroupIndex= */
0
,
true
);
...
@@ -724,4 +728,73 @@ public class ImaUtilTest {
...
@@ -724,4 +728,73 @@ public class ImaUtilTest {
assertThat
(
adGroup
.
durationsUs
[
1
]).
isEqualTo
(
5_000_000
);
assertThat
(
adGroup
.
durationsUs
[
1
]).
isEqualTo
(
5_000_000
);
assertThat
(
adGroup
.
durationsUs
[
2
]).
isEqualTo
(
20_000_000
);
assertThat
(
adGroup
.
durationsUs
[
2
]).
isEqualTo
(
20_000_000
);
}
}
@Test
public
void
getAdGroupAndIndexInMultiPeriodWindow_correctAdGroupIndexAndAdIndexInAdGroup
()
{
FakeTimeline
timeline
=
new
FakeTimeline
(
new
FakeTimeline
.
TimelineWindowDefinition
(
/* periodCount= */
9
,
new
Object
()));
long
periodDurationUs
=
DEFAULT_WINDOW_DURATION_US
/
9
;
// [ad, ad, content, ad, ad, ad, content, ad, ad]
AdPlaybackState
adPlaybackState
=
new
AdPlaybackState
(
/* adsId= */
"adsId"
,
0
,
periodDurationUs
,
2
*
periodDurationUs
)
.
withAdCount
(
/* adGroupIndex= */
0
,
2
)
.
withAdCount
(
/* adGroupIndex= */
1
,
3
)
.
withAdCount
(
/* adGroupIndex= */
2
,
2
)
.
withAdDurationsUs
(
/* adGroupIndex= */
0
,
DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US
+
periodDurationUs
,
periodDurationUs
)
.
withAdDurationsUs
(
/* adGroupIndex= */
1
,
periodDurationUs
,
periodDurationUs
,
periodDurationUs
)
.
withAdDurationsUs
(
/* adGroupIndex= */
2
,
periodDurationUs
,
periodDurationUs
)
.
withIsServerSideInserted
(
/* adGroupIndex= */
0
,
true
);
Pair
<
Integer
,
Integer
>
adGroupIndexAndAdIndexInAdGroup
=
getAdGroupAndIndexInMultiPeriodWindow
(
/* adPeriodIndex= */
0
,
adPlaybackState
,
timeline
);
assertThat
(
adGroupIndexAndAdIndexInAdGroup
.
first
).
isEqualTo
(
0
);
assertThat
(
adGroupIndexAndAdIndexInAdGroup
.
second
).
isEqualTo
(
0
);
adGroupIndexAndAdIndexInAdGroup
=
getAdGroupAndIndexInMultiPeriodWindow
(
/* adPeriodIndex= */
1
,
adPlaybackState
,
timeline
);
assertThat
(
adGroupIndexAndAdIndexInAdGroup
.
first
).
isEqualTo
(
0
);
assertThat
(
adGroupIndexAndAdIndexInAdGroup
.
second
).
isEqualTo
(
1
);
Assert
.
assertThrows
(
IllegalStateException
.
class
,
()
->
getAdGroupAndIndexInMultiPeriodWindow
(
/* adPeriodIndex= */
2
,
adPlaybackState
,
timeline
));
adGroupIndexAndAdIndexInAdGroup
=
getAdGroupAndIndexInMultiPeriodWindow
(
/* adPeriodIndex= */
3
,
adPlaybackState
,
timeline
);
assertThat
(
adGroupIndexAndAdIndexInAdGroup
.
first
).
isEqualTo
(
1
);
assertThat
(
adGroupIndexAndAdIndexInAdGroup
.
second
).
isEqualTo
(
0
);
adGroupIndexAndAdIndexInAdGroup
=
getAdGroupAndIndexInMultiPeriodWindow
(
/* adPeriodIndex= */
4
,
adPlaybackState
,
timeline
);
assertThat
(
adGroupIndexAndAdIndexInAdGroup
.
first
).
isEqualTo
(
1
);
assertThat
(
adGroupIndexAndAdIndexInAdGroup
.
second
).
isEqualTo
(
1
);
adGroupIndexAndAdIndexInAdGroup
=
getAdGroupAndIndexInMultiPeriodWindow
(
/* adPeriodIndex= */
5
,
adPlaybackState
,
timeline
);
assertThat
(
adGroupIndexAndAdIndexInAdGroup
.
first
).
isEqualTo
(
1
);
assertThat
(
adGroupIndexAndAdIndexInAdGroup
.
second
).
isEqualTo
(
2
);
Assert
.
assertThrows
(
IllegalStateException
.
class
,
()
->
getAdGroupAndIndexInMultiPeriodWindow
(
/* adPeriodIndex= */
6
,
adPlaybackState
,
timeline
));
adGroupIndexAndAdIndexInAdGroup
=
getAdGroupAndIndexInMultiPeriodWindow
(
/* adPeriodIndex= */
7
,
adPlaybackState
,
timeline
);
assertThat
(
adGroupIndexAndAdIndexInAdGroup
.
first
).
isEqualTo
(
2
);
assertThat
(
adGroupIndexAndAdIndexInAdGroup
.
second
).
isEqualTo
(
0
);
adGroupIndexAndAdIndexInAdGroup
=
getAdGroupAndIndexInMultiPeriodWindow
(
/* adPeriodIndex= */
8
,
adPlaybackState
,
timeline
);
assertThat
(
adGroupIndexAndAdIndexInAdGroup
.
first
).
isEqualTo
(
2
);
assertThat
(
adGroupIndexAndAdIndexInAdGroup
.
second
).
isEqualTo
(
1
);
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment