Merge pull request #1947 from totallyunknown:fix/dash-playlist-infinite-loop

PiperOrigin-RevId: 712494399
This commit is contained in:
Copybara-Service 2025-01-06 05:28:26 -08:00
commit 871c15946b
2 changed files with 22 additions and 6 deletions

View File

@ -41,6 +41,9 @@
* RTMP Extension: * RTMP Extension:
* HLS Extension: * HLS Extension:
* DASH Extension: * DASH Extension:
* Fix issue when calculating the update interval for ad insertion in
multi-period live streams
([#1698](https://github.com/androidx/media/issues/1698)).
* Smooth Streaming Extension: * Smooth Streaming Extension:
* RTSP Extension: * RTSP Extension:
* Decoder Extensions (FFmpeg, VP9, AV1, etc.): * Decoder Extensions (FFmpeg, VP9, AV1, etc.):

View File

@ -18,6 +18,7 @@ package androidx.media3.exoplayer.dash;
import static androidx.media3.common.util.Assertions.checkNotNull; import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.Assertions.checkState; import static androidx.media3.common.util.Assertions.checkState;
import static androidx.media3.common.util.Util.constrainValue; import static androidx.media3.common.util.Util.constrainValue;
import static androidx.media3.common.util.Util.msToUs;
import static androidx.media3.common.util.Util.usToMs; import static androidx.media3.common.util.Util.usToMs;
import static java.lang.Math.max; import static java.lang.Math.max;
import static java.lang.Math.min; import static java.lang.Math.min;
@ -399,11 +400,12 @@ public final class DashMediaSource extends BaseMediaSource {
public static final long MIN_LIVE_DEFAULT_START_POSITION_US = 5_000_000; public static final long MIN_LIVE_DEFAULT_START_POSITION_US = 5_000_000;
/** /**
* The interval in milliseconds between invocations of {@link * The maximum interval in microseconds between invocations of {@link
* MediaSourceCaller#onSourceInfoRefreshed(MediaSource, Timeline)} when the source's {@link * MediaSourceCaller#onSourceInfoRefreshed(MediaSource, Timeline)} where the {@link Timeline} is
* Timeline} is changing dynamically (for example, for incomplete live streams). * changing dynamically (for example, for incomplete live streams) and a better estimate for the
* next update cannot be determined.
*/ */
private static final long DEFAULT_NOTIFY_MANIFEST_INTERVAL_MS = 5000; private static final long DEFAULT_NOTIFY_MANIFEST_INTERVAL_US = 5_000_000;
private static final String TAG = "DashMediaSource"; private static final String TAG = "DashMediaSource";
@ -1137,7 +1139,11 @@ public final class DashMediaSource extends BaseMediaSource {
long periodDurationUs = manifest.getPeriodDurationUs(periodIndex); long periodDurationUs = manifest.getPeriodDurationUs(periodIndex);
long nowUnixTimeUs = Util.msToUs(nowUnixTimeMs); long nowUnixTimeUs = Util.msToUs(nowUnixTimeMs);
long availabilityStartTimeUs = Util.msToUs(manifest.availabilityStartTimeMs); long availabilityStartTimeUs = Util.msToUs(manifest.availabilityStartTimeMs);
long intervalUs = Util.msToUs(DEFAULT_NOTIFY_MANIFEST_INTERVAL_MS); long intervalUs = DEFAULT_NOTIFY_MANIFEST_INTERVAL_US;
long minUpdatePeriodUs = msToUs(manifest.minUpdatePeriodMs);
if (minUpdatePeriodUs != C.TIME_UNSET && minUpdatePeriodUs < intervalUs) {
intervalUs = minUpdatePeriodUs;
}
for (int i = 0; i < period.adaptationSets.size(); i++) { for (int i = 0; i < period.adaptationSets.size(); i++) {
List<Representation> representations = period.adaptationSets.get(i).representations; List<Representation> representations = period.adaptationSets.get(i).representations;
if (representations.isEmpty()) { if (representations.isEmpty()) {
@ -1150,7 +1156,14 @@ public final class DashMediaSource extends BaseMediaSource {
+ periodStartUs + periodStartUs
+ index.getNextSegmentAvailableTimeUs(periodDurationUs, nowUnixTimeUs); + index.getNextSegmentAvailableTimeUs(periodDurationUs, nowUnixTimeUs);
long requiredIntervalUs = nextSegmentShiftUnixTimeUs - nowUnixTimeUs; long requiredIntervalUs = nextSegmentShiftUnixTimeUs - nowUnixTimeUs;
// Avoid multiple refreshes within a very small amount of time. if (requiredIntervalUs <= 0) {
// The existing manifest might be stale and hasn't updated as expected. Ignore this
// adaptation set and fall back to the default update interval.
// See https://github.com/androidx/media/issues/1698.
continue;
}
// Avoid multiple refreshes within a very small amount of time by either reducing the
// interval to a significantly lower value, or the maximum among two close intervals.
if (requiredIntervalUs < intervalUs - 100_000 if (requiredIntervalUs < intervalUs - 100_000
|| (requiredIntervalUs > intervalUs && requiredIntervalUs < intervalUs + 100_000)) { || (requiredIntervalUs > intervalUs && requiredIntervalUs < intervalUs + 100_000)) {
intervalUs = requiredIntervalUs; intervalUs = requiredIntervalUs;