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
3cc1d06b
authored
Mar 17, 2022
by
bachinger
Committed by
Ian Baker
Mar 17, 2022
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Remove rounding errors of ad durations when converting from double
#minor-release PiperOrigin-RevId: 435360232
parent
7eb01e21
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
53 additions
and
33 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
library/common/src/main/java/com/google/android/exoplayer2/util/Util.java
extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaServerSideAdInsertionMediaSource.java
View file @
3cc1d06b
...
@@ -17,6 +17,8 @@ package com.google.android.exoplayer2.ext.ima;
...
@@ -17,6 +17,8 @@ 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
.
getAdGroupAndIndexInMultiPeriodWindow
;
import
static
com
.
google
.
android
.
exoplayer2
.
ext
.
ima
.
ImaUtil
.
secToMsRounded
;
import
static
com
.
google
.
android
.
exoplayer2
.
ext
.
ima
.
ImaUtil
.
secToUsRounded
;
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
;
...
@@ -24,7 +26,6 @@ import static com.google.android.exoplayer2.source.ads.ServerSideAdInsertionUtil
...
@@ -24,7 +26,6 @@ import static com.google.android.exoplayer2.source.ads.ServerSideAdInsertionUtil
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
.
msToUs
;
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
;
import
static
java
.
lang
.
Math
.
min
;
import
static
java
.
lang
.
Math
.
min
;
...
@@ -659,19 +660,29 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
...
@@ -659,19 +660,29 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
private
static
AdPlaybackState
setVodAdGroupPlaceholders
(
private
static
AdPlaybackState
setVodAdGroupPlaceholders
(
List
<
CuePoint
>
cuePoints
,
AdPlaybackState
adPlaybackState
)
{
List
<
CuePoint
>
cuePoints
,
AdPlaybackState
adPlaybackState
)
{
// TODO(b/192231683) Use getEndTimeMs()/getStartTimeMs() after jar target was removed
for
(
int
i
=
0
;
i
<
cuePoints
.
size
();
i
++)
{
for
(
int
i
=
0
;
i
<
cuePoints
.
size
();
i
++)
{
CuePoint
cuePoint
=
cuePoints
.
get
(
i
);
CuePoint
cuePoint
=
cuePoints
.
get
(
i
);
long
fromPositionUs
=
msToUs
(
secToMsRounded
(
cuePoint
.
getStartTime
()));
adPlaybackState
=
adPlaybackState
=
addAdGroupToAdPlaybackState
(
addAdGroupToAdPlaybackState
(
adPlaybackState
,
adPlaybackState
,
/* fromPositionUs= */
secToUs
(
cuePoint
.
getStartTime
())
,
/* fromPositionUs= */
fromPositionUs
,
/* contentResumeOffsetUs= */
0
,
/* contentResumeOffsetUs= */
0
,
// TODO(b/192231683) Use getEndTimeMs()/getStartTimeMs() after jar target was removed
/* adDurationsUs...= */
getAdDuration
(
/* adDurationsUs...= */
secToUs
(
cuePoint
.
getEndTime
()
-
cuePoint
.
getStartTime
()));
/* startTimeSeconds= */
cuePoint
.
getStartTime
(),
/* endTimeSeconds= */
cuePoint
.
getEndTime
()));
}
}
return
adPlaybackState
;
return
adPlaybackState
;
}
}
private
static
long
getAdDuration
(
double
startTimeSeconds
,
double
endTimeSeconds
)
{
// startTimeSeconds and endTimeSeconds that are coming from the SDK, only have a precision of
// milliseconds so everything that is below a millisecond can be safely considered as coming
// from rounding issues.
return
msToUs
(
secToMsRounded
(
endTimeSeconds
-
startTimeSeconds
));
}
private
static
AdPlaybackState
setVodAdInPlaceholder
(
Ad
ad
,
AdPlaybackState
adPlaybackState
)
{
private
static
AdPlaybackState
setVodAdInPlaceholder
(
Ad
ad
,
AdPlaybackState
adPlaybackState
)
{
AdPodInfo
adPodInfo
=
ad
.
getAdPodInfo
();
AdPodInfo
adPodInfo
=
ad
.
getAdPodInfo
();
// Handle post rolls that have a podIndex of -1.
// Handle post rolls that have a podIndex of -1.
...
@@ -683,9 +694,9 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
...
@@ -683,9 +694,9 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
adPlaybackState
=
adPlaybackState
=
expandAdGroupPlaceholder
(
expandAdGroupPlaceholder
(
adGroupIndex
,
adGroupIndex
,
/* adGroupDurationUs= */
secToUs
(
adPodInfo
.
getMaxDuration
(
)),
/* adGroupDurationUs= */
msToUs
(
secToMsRounded
(
adPodInfo
.
getMaxDuration
()
)),
adIndexInAdGroup
,
adIndexInAdGroup
,
/* adDurationUs= */
secToUs
(
ad
.
getDuration
(
)),
/* adDurationUs= */
msToUs
(
secToMsRounded
(
ad
.
getDuration
()
)),
/* adsInAdGroupCount= */
adPodInfo
.
getTotalAds
(),
/* adsInAdGroupCount= */
adPodInfo
.
getTotalAds
(),
adPlaybackState
);
adPlaybackState
);
}
else
if
(
adIndexInAdGroup
<
adGroup
.
count
-
1
)
{
}
else
if
(
adIndexInAdGroup
<
adGroup
.
count
-
1
)
{
...
@@ -693,7 +704,7 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
...
@@ -693,7 +704,7 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
updateAdDurationInAdGroup
(
updateAdDurationInAdGroup
(
adGroupIndex
,
adGroupIndex
,
adIndexInAdGroup
,
adIndexInAdGroup
,
/* adDurationUs= */
secToUs
(
ad
.
getDuration
(
)),
/* adDurationUs= */
msToUs
(
secToMsRounded
(
ad
.
getDuration
()
)),
adPlaybackState
);
adPlaybackState
);
}
}
return
adPlaybackState
;
return
adPlaybackState
;
...
@@ -702,7 +713,7 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
...
@@ -702,7 +713,7 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
private
AdPlaybackState
addLiveAdBreak
(
private
AdPlaybackState
addLiveAdBreak
(
Ad
ad
,
long
currentPeriodPositionUs
,
AdPlaybackState
adPlaybackState
)
{
Ad
ad
,
long
currentPeriodPositionUs
,
AdPlaybackState
adPlaybackState
)
{
AdPodInfo
adPodInfo
=
ad
.
getAdPodInfo
();
AdPodInfo
adPodInfo
=
ad
.
getAdPodInfo
();
long
adDurationUs
=
secToUs
(
ad
.
getDuration
());
long
adDurationUs
=
secToUs
Rounded
(
ad
.
getDuration
());
int
adIndexInAdGroup
=
adPodInfo
.
getAdPosition
()
-
1
;
int
adIndexInAdGroup
=
adPodInfo
.
getAdPosition
()
-
1
;
// TODO(b/208398934) Support seeking backwards.
// TODO(b/208398934) Support seeking backwards.
if
(
adIndexInAdGroup
==
0
||
adPlaybackState
.
adGroupCount
==
1
)
{
if
(
adIndexInAdGroup
==
0
||
adPlaybackState
.
adGroupCount
==
1
)
{
...
@@ -716,7 +727,7 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
...
@@ -716,7 +727,7 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
new
long
[
adCount
],
new
long
[
adCount
],
adIndexInAdGroup
,
adIndexInAdGroup
,
adDurationUs
,
adDurationUs
,
secToUs
(
adPodInfo
.
getMaxDuration
(
)));
msToUs
(
secToMsRounded
(
adPodInfo
.
getMaxDuration
()
)));
adPlaybackState
=
adPlaybackState
=
addAdGroupToAdPlaybackState
(
addAdGroupToAdPlaybackState
(
adPlaybackState
,
adPlaybackState
,
...
...
extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaUtil.java
View file @
3cc1d06b
...
@@ -54,7 +54,10 @@ import com.google.android.exoplayer2.upstream.DataSpec;
...
@@ -54,7 +54,10 @@ import com.google.android.exoplayer2.upstream.DataSpec;
import
com.google.android.exoplayer2.util.Util
;
import
com.google.android.exoplayer2.util.Util
;
import
com.google.common.collect.ImmutableList
;
import
com.google.common.collect.ImmutableList
;
import
com.google.common.collect.ImmutableMap
;
import
com.google.common.collect.ImmutableMap
;
import
com.google.common.math.DoubleMath
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.math.BigDecimal
;
import
java.math.RoundingMode
;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
java.util.Collection
;
import
java.util.Collection
;
import
java.util.HashMap
;
import
java.util.HashMap
;
...
@@ -398,17 +401,13 @@ import java.util.Set;
...
@@ -398,17 +401,13 @@ 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
);
// TODO(b/192231683) Remove subtracted US from ad group time when we can upgrade the SDK.
if
(
totalElapsedContentDurationUs
<
adGroup
.
timeUs
)
{
// 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
;
// TODO(b/192231683) Remove additional US when we can upgrade the SDK.
if
(
periodStartUs
+
period
.
durationUs
<=
adGroup
.
timeUs
+
adGroupDurationUs
)
{
// 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 (Note: A VOD ad
// 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).
// reported by the IMA SDK spans multiple periods before the LOADED event arrives).
adPlaybackStates
.
put
(
adPlaybackStates
.
put
(
...
@@ -490,16 +489,12 @@ import java.util.Set;
...
@@ -490,16 +489,12 @@ 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
);
// TODO(b/192231683) Remove subtracted US from ad group time when we can upgrade the SDK.
if
(
totalElapsedContentDurationUs
<
adGroup
.
timeUs
)
{
// 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.
totalElapsedContentDurationUs
+=
period
.
durationUs
;
totalElapsedContentDurationUs
+=
period
.
durationUs
;
}
else
{
}
else
{
long
periodStartUs
=
totalElapsedContentDurationUs
+
elapsedAdGroupAdDurationUs
;
long
periodStartUs
=
totalElapsedContentDurationUs
+
elapsedAdGroupAdDurationUs
;
// TODO(b/192231683) Remove additional US when we can upgrade the SDK.
if
(
periodStartUs
+
period
.
durationUs
<=
adGroup
.
timeUs
+
adGroupDurationUs
)
{
// 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.
// The period ends before the end of the ad group, so it is an ad period.
if
(
j
==
adPeriodIndex
)
{
if
(
j
==
adPeriodIndex
)
{
return
new
Pair
<>(
/* adGroupIndex= */
i
,
adIndexInAdGroup
);
return
new
Pair
<>(
/* adGroupIndex= */
i
,
adIndexInAdGroup
);
...
@@ -518,5 +513,31 @@ import java.util.Set;
...
@@ -518,5 +513,31 @@ import java.util.Set;
throw
new
IllegalStateException
();
throw
new
IllegalStateException
();
}
}
/**
* Converts a time in seconds to the corresponding time in microseconds.
*
* <p>Fractional values are rounded to the nearest microsecond using {@link RoundingMode#HALF_UP}.
*
* @param timeSec The time in seconds.
* @return The corresponding time in microseconds.
*/
public
static
long
secToUsRounded
(
double
timeSec
)
{
return
DoubleMath
.
roundToLong
(
BigDecimal
.
valueOf
(
timeSec
).
scaleByPowerOfTen
(
6
).
doubleValue
(),
RoundingMode
.
HALF_UP
);
}
/**
* Converts a time in seconds to the corresponding time in milliseconds.
*
* <p>Fractional values are rounded to the nearest millisecond using {@link RoundingMode#HALF_UP}.
*
* @param timeSec The time in seconds.
* @return The corresponding time in milliseconds.
*/
public
static
long
secToMsRounded
(
double
timeSec
)
{
return
DoubleMath
.
roundToLong
(
BigDecimal
.
valueOf
(
timeSec
).
scaleByPowerOfTen
(
3
).
doubleValue
(),
RoundingMode
.
HALF_UP
);
}
private
ImaUtil
()
{}
private
ImaUtil
()
{}
}
}
library/common/src/main/java/com/google/android/exoplayer2/util/Util.java
View file @
3cc1d06b
...
@@ -1142,18 +1142,6 @@ public final class Util {
...
@@ -1142,18 +1142,6 @@ public final class Util {
}
}
/**
/**
* Converts a time in seconds to the corresponding time in microseconds.
*
* @param timeSec The time in seconds.
* @return The corresponding time in microseconds.
*/
public
static
long
secToUs
(
double
timeSec
)
{
return
BigDecimal
.
valueOf
(
timeSec
)
.
multiply
(
BigDecimal
.
valueOf
(
C
.
MICROS_PER_SECOND
))
.
longValue
();
}
/**
* Parses an xs:duration attribute value, returning the parsed duration in milliseconds.
* Parses an xs:duration attribute value, returning the parsed duration in milliseconds.
*
*
* @param value The attribute value to decode.
* @param value The attribute value to decode.
...
...
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