Remove mediaTimeOffsetMs from EventDispatcher
The `DashMediaSource` wrongly added an offset to the media times set to the `MediaLoadData`. With this the `startTimeMS` and `endTimeMs` don't represent the positions in the period but in the stream. `DashMediaSource` was the only call site that was setting the offset to a non-zero value. So if we are using 0 for the `DashMediaSource` as well, the offset is redundant and we can remove it everywhere. PiperOrigin-RevId: 520682026
This commit is contained in:
parent
104cfc322c
commit
d7010da614
@ -21,6 +21,13 @@
|
||||
AdPlaybackState>)` by adding a timeline parameter that contains the
|
||||
periods with the UIDs used as keys in the map. This is required to avoid
|
||||
concurrency issues with multi-period live streams.
|
||||
* Deprecate `EventDispatcher.withParameters(int windowIndex, @Nullable
|
||||
MediaPeriodId mediaPeriodId, long mediaTimeOffsetMs)` and
|
||||
`BaseMediaSource.createEventDispatcher(..., long mediaTimeOffsetMs)`.
|
||||
The variant of the methods without the `mediaTimeOffsetUs` can be called
|
||||
instead. Note that even for the deprecated variants, the offset is not
|
||||
anymore added to `startTimeUs` and `endTimeUs` of the `MediaLoadData`
|
||||
objects that are dispatched by the dispatcher.
|
||||
* Audio:
|
||||
* Fix bug where some playbacks fail when tunneling is enabled and
|
||||
`AudioProcessors` are active, e.g. for gapless trimming
|
||||
@ -52,6 +59,8 @@
|
||||
* DASH:
|
||||
* Fix handling of empty segment timelines
|
||||
([#11014](https://github.com/google/ExoPlayer/issues/11014)).
|
||||
* Remove the media time offset from `MediaLoadData.startTimeMs` and
|
||||
`MediaLoadData.endTimeMs` for multi period DASH streams.
|
||||
* RTSP:
|
||||
* Retry with TCP if RTSP Setup with UDP fails with RTSP Error 461
|
||||
UnsupportedTransport
|
||||
|
@ -101,37 +101,46 @@ public abstract class BaseMediaSource implements MediaSource {
|
||||
*/
|
||||
protected final MediaSourceEventListener.EventDispatcher createEventDispatcher(
|
||||
@Nullable MediaPeriodId mediaPeriodId) {
|
||||
return eventDispatcher.withParameters(
|
||||
/* windowIndex= */ 0, mediaPeriodId, /* mediaTimeOffsetMs= */ 0);
|
||||
return eventDispatcher.withParameters(/* windowIndex= */ 0, mediaPeriodId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link MediaSourceEventListener.EventDispatcher} which dispatches all events to the
|
||||
* registered listeners with the specified {@link MediaPeriodId} and time offset.
|
||||
*
|
||||
* @param mediaPeriodId The {@link MediaPeriodId} to be reported with the events.
|
||||
* @param mediaTimeOffsetMs The offset to be added to all media times, in milliseconds.
|
||||
* @return An event dispatcher with pre-configured media period id and time offset.
|
||||
*/
|
||||
protected final MediaSourceEventListener.EventDispatcher createEventDispatcher(
|
||||
MediaPeriodId mediaPeriodId, long mediaTimeOffsetMs) {
|
||||
Assertions.checkNotNull(mediaPeriodId);
|
||||
return eventDispatcher.withParameters(/* windowIndex= */ 0, mediaPeriodId, mediaTimeOffsetMs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link MediaSourceEventListener.EventDispatcher} which dispatches all events to the
|
||||
* registered listeners with the specified window index, {@link MediaPeriodId} and time offset.
|
||||
* registered listeners with the specified window index and {@link MediaPeriodId}.
|
||||
*
|
||||
* @param windowIndex The timeline window index to be reported with the events.
|
||||
* @param mediaPeriodId The {@link MediaPeriodId} to be reported with the events. May be null, if
|
||||
* the events do not belong to a specific media period.
|
||||
* @param mediaTimeOffsetMs The offset to be added to all media times, in milliseconds.
|
||||
* @return An event dispatcher with pre-configured media period id and time offset.
|
||||
* @return An event dispatcher with pre-configured media period id.
|
||||
*/
|
||||
protected final MediaSourceEventListener.EventDispatcher createEventDispatcher(
|
||||
int windowIndex, @Nullable MediaPeriodId mediaPeriodId) {
|
||||
return eventDispatcher.withParameters(windowIndex, mediaPeriodId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: The {@code mediaTimeOffsetMs} passed to this method is ignored and not added to media
|
||||
* times in any way.
|
||||
*
|
||||
* @deprecated Use {@link #createEventDispatcher(MediaPeriodId)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
protected final MediaSourceEventListener.EventDispatcher createEventDispatcher(
|
||||
MediaPeriodId mediaPeriodId, long mediaTimeOffsetMs) {
|
||||
Assertions.checkNotNull(mediaPeriodId);
|
||||
return eventDispatcher.withParameters(/* windowIndex= */ 0, mediaPeriodId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: The {@code mediaTimeOffsetMs} passed to this method is ignored and not added to media
|
||||
* times in any way.
|
||||
*
|
||||
* @deprecated Use {@link #createEventDispatcher(int, MediaPeriodId)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
protected final MediaSourceEventListener.EventDispatcher createEventDispatcher(
|
||||
int windowIndex, @Nullable MediaPeriodId mediaPeriodId, long mediaTimeOffsetMs) {
|
||||
return eventDispatcher.withParameters(windowIndex, mediaPeriodId, mediaTimeOffsetMs);
|
||||
return eventDispatcher.withParameters(windowIndex, mediaPeriodId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -357,8 +357,7 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource {
|
||||
int windowIndex = getWindowIndexForChildWindowIndex(id, childWindowIndex);
|
||||
if (mediaSourceEventDispatcher.windowIndex != windowIndex
|
||||
|| !Util.areEqual(mediaSourceEventDispatcher.mediaPeriodId, mediaPeriodId)) {
|
||||
mediaSourceEventDispatcher =
|
||||
createEventDispatcher(windowIndex, mediaPeriodId, /* mediaTimeOffsetMs= */ 0);
|
||||
mediaSourceEventDispatcher = createEventDispatcher(windowIndex, mediaPeriodId);
|
||||
}
|
||||
if (drmEventDispatcher.windowIndex != windowIndex
|
||||
|| !Util.areEqual(drmEventDispatcher.mediaPeriodId, mediaPeriodId)) {
|
||||
|
@ -16,6 +16,7 @@
|
||||
package androidx.media3.exoplayer.source;
|
||||
|
||||
import static androidx.media3.common.util.Util.postOrRun;
|
||||
import static androidx.media3.common.util.Util.usToMs;
|
||||
|
||||
import android.os.Handler;
|
||||
import androidx.annotation.CheckResult;
|
||||
@ -26,7 +27,6 @@ import androidx.media3.common.Format;
|
||||
import androidx.media3.common.Player;
|
||||
import androidx.media3.common.util.Assertions;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.common.util.Util;
|
||||
import androidx.media3.exoplayer.source.MediaSource.MediaPeriodId;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
@ -152,26 +152,22 @@ public interface MediaSourceEventListener {
|
||||
@Nullable public final MediaPeriodId mediaPeriodId;
|
||||
|
||||
private final CopyOnWriteArrayList<ListenerAndHandler> listenerAndHandlers;
|
||||
private final long mediaTimeOffsetMs;
|
||||
|
||||
/** Creates an event dispatcher. */
|
||||
public EventDispatcher() {
|
||||
this(
|
||||
/* listenerAndHandlers= */ new CopyOnWriteArrayList<>(),
|
||||
/* windowIndex= */ 0,
|
||||
/* mediaPeriodId= */ null,
|
||||
/* mediaTimeOffsetMs= */ 0);
|
||||
/* mediaPeriodId= */ null);
|
||||
}
|
||||
|
||||
private EventDispatcher(
|
||||
CopyOnWriteArrayList<ListenerAndHandler> listenerAndHandlers,
|
||||
int windowIndex,
|
||||
@Nullable MediaPeriodId mediaPeriodId,
|
||||
long mediaTimeOffsetMs) {
|
||||
@Nullable MediaPeriodId mediaPeriodId) {
|
||||
this.listenerAndHandlers = listenerAndHandlers;
|
||||
this.windowIndex = windowIndex;
|
||||
this.mediaPeriodId = mediaPeriodId;
|
||||
this.mediaTimeOffsetMs = mediaTimeOffsetMs;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -180,14 +176,24 @@ public interface MediaSourceEventListener {
|
||||
*
|
||||
* @param windowIndex The timeline window index to be reported with the events.
|
||||
* @param mediaPeriodId The {@link MediaPeriodId} to be reported with the events.
|
||||
* @param mediaTimeOffsetMs The offset to be added to all media times, in milliseconds.
|
||||
* @return A view of the event dispatcher with the pre-configured parameters.
|
||||
*/
|
||||
@CheckResult
|
||||
public EventDispatcher withParameters(int windowIndex, @Nullable MediaPeriodId mediaPeriodId) {
|
||||
return new EventDispatcher(listenerAndHandlers, windowIndex, mediaPeriodId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: The {@code mediaTimeOffsetMs} passed to this method is ignored and not added to media
|
||||
* times in any way.
|
||||
*
|
||||
* @deprecated Use {@link #withParameters(int, MediaPeriodId)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@CheckResult
|
||||
public EventDispatcher withParameters(
|
||||
int windowIndex, @Nullable MediaPeriodId mediaPeriodId, long mediaTimeOffsetMs) {
|
||||
return new EventDispatcher(
|
||||
listenerAndHandlers, windowIndex, mediaPeriodId, mediaTimeOffsetMs);
|
||||
return new EventDispatcher(listenerAndHandlers, windowIndex, mediaPeriodId);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -246,8 +252,8 @@ public interface MediaSourceEventListener {
|
||||
trackFormat,
|
||||
trackSelectionReason,
|
||||
trackSelectionData,
|
||||
adjustMediaTime(mediaStartTimeUs),
|
||||
adjustMediaTime(mediaEndTimeUs)));
|
||||
usToMs(mediaStartTimeUs),
|
||||
usToMs(mediaEndTimeUs)));
|
||||
}
|
||||
|
||||
/** Dispatches {@link #onLoadStarted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */
|
||||
@ -291,8 +297,8 @@ public interface MediaSourceEventListener {
|
||||
trackFormat,
|
||||
trackSelectionReason,
|
||||
trackSelectionData,
|
||||
adjustMediaTime(mediaStartTimeUs),
|
||||
adjustMediaTime(mediaEndTimeUs)));
|
||||
usToMs(mediaStartTimeUs),
|
||||
usToMs(mediaEndTimeUs)));
|
||||
}
|
||||
|
||||
/** Dispatches {@link #onLoadCompleted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */
|
||||
@ -337,8 +343,8 @@ public interface MediaSourceEventListener {
|
||||
trackFormat,
|
||||
trackSelectionReason,
|
||||
trackSelectionData,
|
||||
adjustMediaTime(mediaStartTimeUs),
|
||||
adjustMediaTime(mediaEndTimeUs)));
|
||||
usToMs(mediaStartTimeUs),
|
||||
usToMs(mediaEndTimeUs)));
|
||||
}
|
||||
|
||||
/** Dispatches {@link #onLoadCanceled(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */
|
||||
@ -397,8 +403,8 @@ public interface MediaSourceEventListener {
|
||||
trackFormat,
|
||||
trackSelectionReason,
|
||||
trackSelectionData,
|
||||
adjustMediaTime(mediaStartTimeUs),
|
||||
adjustMediaTime(mediaEndTimeUs)),
|
||||
usToMs(mediaStartTimeUs),
|
||||
usToMs(mediaEndTimeUs)),
|
||||
error,
|
||||
wasCanceled);
|
||||
}
|
||||
@ -431,8 +437,8 @@ public interface MediaSourceEventListener {
|
||||
/* trackFormat= */ null,
|
||||
C.SELECTION_REASON_ADAPTIVE,
|
||||
/* trackSelectionData= */ null,
|
||||
adjustMediaTime(mediaStartTimeUs),
|
||||
adjustMediaTime(mediaEndTimeUs)));
|
||||
usToMs(mediaStartTimeUs),
|
||||
usToMs(mediaEndTimeUs)));
|
||||
}
|
||||
|
||||
/** Dispatches {@link #onUpstreamDiscarded(int, MediaPeriodId, MediaLoadData)}. */
|
||||
@ -460,7 +466,7 @@ public interface MediaSourceEventListener {
|
||||
trackFormat,
|
||||
trackSelectionReason,
|
||||
trackSelectionData,
|
||||
adjustMediaTime(mediaTimeUs),
|
||||
usToMs(mediaTimeUs),
|
||||
/* mediaEndTimeMs= */ C.TIME_UNSET));
|
||||
}
|
||||
|
||||
@ -474,11 +480,6 @@ public interface MediaSourceEventListener {
|
||||
}
|
||||
}
|
||||
|
||||
private long adjustMediaTime(long mediaTimeUs) {
|
||||
long mediaTimeMs = Util.usToMs(mediaTimeUs);
|
||||
return mediaTimeMs == C.TIME_UNSET ? C.TIME_UNSET : mediaTimeOffsetMs + mediaTimeMs;
|
||||
}
|
||||
|
||||
private static final class ListenerAndHandler {
|
||||
|
||||
public Handler handler;
|
||||
|
@ -517,8 +517,7 @@ public class DownloadHelperTest {
|
||||
trackGroupArrays[periodIndex],
|
||||
allocator,
|
||||
TEST_TIMELINE.getWindow(0, new Timeline.Window()).positionInFirstPeriodUs,
|
||||
new EventDispatcher()
|
||||
.withParameters(/* windowIndex= */ 0, id, /* mediaTimeOffsetMs= */ 0)) {
|
||||
new EventDispatcher().withParameters(/* windowIndex= */ 0, id)) {
|
||||
@Override
|
||||
public List<StreamKey> getStreamKeys(List<ExoTrackSelection> trackSelections) {
|
||||
List<StreamKey> result = new ArrayList<>();
|
||||
|
@ -246,10 +246,7 @@ public final class MergingMediaPeriodTest {
|
||||
new FakeMediaPeriodWithSelectionParameters(
|
||||
new TrackGroupArray(trackGroups),
|
||||
new EventDispatcher()
|
||||
.withParameters(
|
||||
/* windowIndex= */ i,
|
||||
new MediaPeriodId(/* periodUid= */ i),
|
||||
/* mediaTimeOffsetMs= */ 0),
|
||||
.withParameters(/* windowIndex= */ i, new MediaPeriodId(/* periodUid= */ i)),
|
||||
/* trackDataFactory= */ (unusedFormat, unusedMediaPeriodId) ->
|
||||
ImmutableList.of(
|
||||
oneByteSample(definition.singleSampleTimeUs, C.BUFFER_FLAG_KEY_FRAME),
|
||||
|
@ -69,7 +69,7 @@ public final class ProgressiveMediaPeriodTest {
|
||||
.withParameters(/* windowIndex= */ 0, mediaPeriodId),
|
||||
new DefaultLoadErrorHandlingPolicy(),
|
||||
new MediaSourceEventListener.EventDispatcher()
|
||||
.withParameters(/* windowIndex= */ 0, mediaPeriodId, /* mediaTimeOffsetMs= */ 0),
|
||||
.withParameters(/* windowIndex= */ 0, mediaPeriodId),
|
||||
sourceInfoRefreshListener,
|
||||
new DefaultAllocator(/* trimOnReset= */ true, C.DEFAULT_BUFFER_SEGMENT_SIZE),
|
||||
/* customCacheKey= */ null,
|
||||
|
@ -469,8 +469,7 @@ public final class DashMediaSource extends BaseMediaSource {
|
||||
@Override
|
||||
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) {
|
||||
int periodIndex = (Integer) id.periodUid - firstPeriodId;
|
||||
MediaSourceEventListener.EventDispatcher periodEventDispatcher =
|
||||
createEventDispatcher(id, manifest.getPeriod(periodIndex).startMs);
|
||||
MediaSourceEventListener.EventDispatcher periodEventDispatcher = createEventDispatcher(id);
|
||||
DrmSessionEventListener.EventDispatcher drmEventDispatcher = createDrmEventDispatcher(id);
|
||||
DashMediaPeriod mediaPeriod =
|
||||
new DashMediaPeriod(
|
||||
|
@ -216,7 +216,7 @@ public final class DashMediaPeriodTest {
|
||||
.withParameters(/* windowIndex= */ 0, mediaPeriodId),
|
||||
mock(LoadErrorHandlingPolicy.class),
|
||||
new MediaSourceEventListener.EventDispatcher()
|
||||
.withParameters(/* windowIndex= */ 0, mediaPeriodId, /* mediaTimeOffsetMs= */ 0),
|
||||
.withParameters(/* windowIndex= */ 0, mediaPeriodId),
|
||||
/* elapsedRealtimeOffsetMs= */ 0,
|
||||
mock(LoaderErrorThrower.class),
|
||||
mock(Allocator.class),
|
||||
|
@ -89,7 +89,7 @@ public final class HlsMediaPeriodTest {
|
||||
.withParameters(/* windowIndex= */ 0, mediaPeriodId),
|
||||
mock(LoadErrorHandlingPolicy.class),
|
||||
new MediaSourceEventListener.EventDispatcher()
|
||||
.withParameters(/* windowIndex= */ 0, mediaPeriodId, /* mediaTimeOffsetMs= */ 0),
|
||||
.withParameters(/* windowIndex= */ 0, mediaPeriodId),
|
||||
mock(Allocator.class),
|
||||
mock(CompositeSequenceableLoaderFactory.class),
|
||||
/* allowChunklessPreparation= */ true,
|
||||
|
@ -72,7 +72,7 @@ public class SsMediaPeriodTest {
|
||||
.withParameters(/* windowIndex= */ 0, mediaPeriodId),
|
||||
mock(LoadErrorHandlingPolicy.class),
|
||||
new MediaSourceEventListener.EventDispatcher()
|
||||
.withParameters(/* windowIndex= */ 0, mediaPeriodId, /* mediaTimeOffsetMs= */ 0),
|
||||
.withParameters(/* windowIndex= */ 0, mediaPeriodId),
|
||||
mock(LoaderErrorThrower.class),
|
||||
mock(Allocator.class));
|
||||
};
|
||||
|
@ -239,7 +239,7 @@ public class FakeMediaSource extends BaseMediaSource {
|
||||
Assertions.checkArgument(periodIndex != C.INDEX_UNSET);
|
||||
Period period = timeline.getPeriod(periodIndex, new Period());
|
||||
MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher =
|
||||
createEventDispatcher(period.windowIndex, id, period.getPositionInWindowMs());
|
||||
createEventDispatcher(period.windowIndex, id);
|
||||
DrmSessionEventListener.EventDispatcher drmEventDispatcher =
|
||||
createDrmEventDispatcher(period.windowIndex, id);
|
||||
MediaPeriod mediaPeriod =
|
||||
|
Loading…
x
Reference in New Issue
Block a user