Commit d7010da6 by bachinger Committed by Marc Baechinger

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
parent 104cfc32
...@@ -21,6 +21,13 @@ ...@@ -21,6 +21,13 @@
AdPlaybackState>)` by adding a timeline parameter that contains the AdPlaybackState>)` by adding a timeline parameter that contains the
periods with the UIDs used as keys in the map. This is required to avoid periods with the UIDs used as keys in the map. This is required to avoid
concurrency issues with multi-period live streams. 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: * Audio:
* Fix bug where some playbacks fail when tunneling is enabled and * Fix bug where some playbacks fail when tunneling is enabled and
`AudioProcessors` are active, e.g. for gapless trimming `AudioProcessors` are active, e.g. for gapless trimming
...@@ -52,6 +59,8 @@ ...@@ -52,6 +59,8 @@
* DASH: * DASH:
* Fix handling of empty segment timelines * Fix handling of empty segment timelines
([#11014](https://github.com/google/ExoPlayer/issues/11014)). ([#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: * RTSP:
* Retry with TCP if RTSP Setup with UDP fails with RTSP Error 461 * Retry with TCP if RTSP Setup with UDP fails with RTSP Error 461
UnsupportedTransport UnsupportedTransport
......
...@@ -101,37 +101,46 @@ public abstract class BaseMediaSource implements MediaSource { ...@@ -101,37 +101,46 @@ public abstract class BaseMediaSource implements MediaSource {
*/ */
protected final MediaSourceEventListener.EventDispatcher createEventDispatcher( protected final MediaSourceEventListener.EventDispatcher createEventDispatcher(
@Nullable MediaPeriodId mediaPeriodId) { @Nullable MediaPeriodId mediaPeriodId) {
return eventDispatcher.withParameters( return eventDispatcher.withParameters(/* windowIndex= */ 0, mediaPeriodId);
/* windowIndex= */ 0, mediaPeriodId, /* mediaTimeOffsetMs= */ 0);
} }
/** /**
* Returns a {@link MediaSourceEventListener.EventDispatcher} which dispatches all events to the * Returns a {@link MediaSourceEventListener.EventDispatcher} which dispatches all events to the
* registered listeners with the specified {@link MediaPeriodId} and time offset. * registered listeners with the specified window index and {@link MediaPeriodId}.
* *
* @param mediaPeriodId The {@link MediaPeriodId} to be reported with the events. * @param windowIndex The timeline window index to be reported with the events.
* @param mediaTimeOffsetMs The offset to be added to all media times, in milliseconds. * @param mediaPeriodId The {@link MediaPeriodId} to be reported with the events. May be null, if
* @return An event dispatcher with pre-configured media period id and time offset. * the events do not belong to a specific media period.
* @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( protected final MediaSourceEventListener.EventDispatcher createEventDispatcher(
MediaPeriodId mediaPeriodId, long mediaTimeOffsetMs) { MediaPeriodId mediaPeriodId, long mediaTimeOffsetMs) {
Assertions.checkNotNull(mediaPeriodId); Assertions.checkNotNull(mediaPeriodId);
return eventDispatcher.withParameters(/* windowIndex= */ 0, mediaPeriodId, mediaTimeOffsetMs); return eventDispatcher.withParameters(/* windowIndex= */ 0, mediaPeriodId);
} }
/** /**
* Returns a {@link MediaSourceEventListener.EventDispatcher} which dispatches all events to the * Note: The {@code mediaTimeOffsetMs} passed to this method is ignored and not added to media
* registered listeners with the specified window index, {@link MediaPeriodId} and time offset. * times in any way.
* *
* @param windowIndex The timeline window index to be reported with the events. * @deprecated Use {@link #createEventDispatcher(int, MediaPeriodId)} instead.
* @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.
*/ */
@Deprecated
protected final MediaSourceEventListener.EventDispatcher createEventDispatcher( protected final MediaSourceEventListener.EventDispatcher createEventDispatcher(
int windowIndex, @Nullable MediaPeriodId mediaPeriodId, long mediaTimeOffsetMs) { 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 { ...@@ -357,8 +357,7 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource {
int windowIndex = getWindowIndexForChildWindowIndex(id, childWindowIndex); int windowIndex = getWindowIndexForChildWindowIndex(id, childWindowIndex);
if (mediaSourceEventDispatcher.windowIndex != windowIndex if (mediaSourceEventDispatcher.windowIndex != windowIndex
|| !Util.areEqual(mediaSourceEventDispatcher.mediaPeriodId, mediaPeriodId)) { || !Util.areEqual(mediaSourceEventDispatcher.mediaPeriodId, mediaPeriodId)) {
mediaSourceEventDispatcher = mediaSourceEventDispatcher = createEventDispatcher(windowIndex, mediaPeriodId);
createEventDispatcher(windowIndex, mediaPeriodId, /* mediaTimeOffsetMs= */ 0);
} }
if (drmEventDispatcher.windowIndex != windowIndex if (drmEventDispatcher.windowIndex != windowIndex
|| !Util.areEqual(drmEventDispatcher.mediaPeriodId, mediaPeriodId)) { || !Util.areEqual(drmEventDispatcher.mediaPeriodId, mediaPeriodId)) {
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
package androidx.media3.exoplayer.source; package androidx.media3.exoplayer.source;
import static androidx.media3.common.util.Util.postOrRun; import static androidx.media3.common.util.Util.postOrRun;
import static androidx.media3.common.util.Util.usToMs;
import android.os.Handler; import android.os.Handler;
import androidx.annotation.CheckResult; import androidx.annotation.CheckResult;
...@@ -26,7 +27,6 @@ import androidx.media3.common.Format; ...@@ -26,7 +27,6 @@ import androidx.media3.common.Format;
import androidx.media3.common.Player; import androidx.media3.common.Player;
import androidx.media3.common.util.Assertions; import androidx.media3.common.util.Assertions;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util;
import androidx.media3.exoplayer.source.MediaSource.MediaPeriodId; import androidx.media3.exoplayer.source.MediaSource.MediaPeriodId;
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
...@@ -152,26 +152,22 @@ public interface MediaSourceEventListener { ...@@ -152,26 +152,22 @@ public interface MediaSourceEventListener {
@Nullable public final MediaPeriodId mediaPeriodId; @Nullable public final MediaPeriodId mediaPeriodId;
private final CopyOnWriteArrayList<ListenerAndHandler> listenerAndHandlers; private final CopyOnWriteArrayList<ListenerAndHandler> listenerAndHandlers;
private final long mediaTimeOffsetMs;
/** Creates an event dispatcher. */ /** Creates an event dispatcher. */
public EventDispatcher() { public EventDispatcher() {
this( this(
/* listenerAndHandlers= */ new CopyOnWriteArrayList<>(), /* listenerAndHandlers= */ new CopyOnWriteArrayList<>(),
/* windowIndex= */ 0, /* windowIndex= */ 0,
/* mediaPeriodId= */ null, /* mediaPeriodId= */ null);
/* mediaTimeOffsetMs= */ 0);
} }
private EventDispatcher( private EventDispatcher(
CopyOnWriteArrayList<ListenerAndHandler> listenerAndHandlers, CopyOnWriteArrayList<ListenerAndHandler> listenerAndHandlers,
int windowIndex, int windowIndex,
@Nullable MediaPeriodId mediaPeriodId, @Nullable MediaPeriodId mediaPeriodId) {
long mediaTimeOffsetMs) {
this.listenerAndHandlers = listenerAndHandlers; this.listenerAndHandlers = listenerAndHandlers;
this.windowIndex = windowIndex; this.windowIndex = windowIndex;
this.mediaPeriodId = mediaPeriodId; this.mediaPeriodId = mediaPeriodId;
this.mediaTimeOffsetMs = mediaTimeOffsetMs;
} }
/** /**
...@@ -180,14 +176,24 @@ public interface MediaSourceEventListener { ...@@ -180,14 +176,24 @@ public interface MediaSourceEventListener {
* *
* @param windowIndex The timeline window index to be reported with the events. * @param windowIndex The timeline window index to be reported with the events.
* @param mediaPeriodId The {@link MediaPeriodId} 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. * @return A view of the event dispatcher with the pre-configured parameters.
*/ */
@CheckResult @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( public EventDispatcher withParameters(
int windowIndex, @Nullable MediaPeriodId mediaPeriodId, long mediaTimeOffsetMs) { int windowIndex, @Nullable MediaPeriodId mediaPeriodId, long mediaTimeOffsetMs) {
return new EventDispatcher( return new EventDispatcher(listenerAndHandlers, windowIndex, mediaPeriodId);
listenerAndHandlers, windowIndex, mediaPeriodId, mediaTimeOffsetMs);
} }
/** /**
...@@ -246,8 +252,8 @@ public interface MediaSourceEventListener { ...@@ -246,8 +252,8 @@ public interface MediaSourceEventListener {
trackFormat, trackFormat,
trackSelectionReason, trackSelectionReason,
trackSelectionData, trackSelectionData,
adjustMediaTime(mediaStartTimeUs), usToMs(mediaStartTimeUs),
adjustMediaTime(mediaEndTimeUs))); usToMs(mediaEndTimeUs)));
} }
/** Dispatches {@link #onLoadStarted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */ /** Dispatches {@link #onLoadStarted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */
...@@ -291,8 +297,8 @@ public interface MediaSourceEventListener { ...@@ -291,8 +297,8 @@ public interface MediaSourceEventListener {
trackFormat, trackFormat,
trackSelectionReason, trackSelectionReason,
trackSelectionData, trackSelectionData,
adjustMediaTime(mediaStartTimeUs), usToMs(mediaStartTimeUs),
adjustMediaTime(mediaEndTimeUs))); usToMs(mediaEndTimeUs)));
} }
/** Dispatches {@link #onLoadCompleted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */ /** Dispatches {@link #onLoadCompleted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */
...@@ -337,8 +343,8 @@ public interface MediaSourceEventListener { ...@@ -337,8 +343,8 @@ public interface MediaSourceEventListener {
trackFormat, trackFormat,
trackSelectionReason, trackSelectionReason,
trackSelectionData, trackSelectionData,
adjustMediaTime(mediaStartTimeUs), usToMs(mediaStartTimeUs),
adjustMediaTime(mediaEndTimeUs))); usToMs(mediaEndTimeUs)));
} }
/** Dispatches {@link #onLoadCanceled(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */ /** Dispatches {@link #onLoadCanceled(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */
...@@ -397,8 +403,8 @@ public interface MediaSourceEventListener { ...@@ -397,8 +403,8 @@ public interface MediaSourceEventListener {
trackFormat, trackFormat,
trackSelectionReason, trackSelectionReason,
trackSelectionData, trackSelectionData,
adjustMediaTime(mediaStartTimeUs), usToMs(mediaStartTimeUs),
adjustMediaTime(mediaEndTimeUs)), usToMs(mediaEndTimeUs)),
error, error,
wasCanceled); wasCanceled);
} }
...@@ -431,8 +437,8 @@ public interface MediaSourceEventListener { ...@@ -431,8 +437,8 @@ public interface MediaSourceEventListener {
/* trackFormat= */ null, /* trackFormat= */ null,
C.SELECTION_REASON_ADAPTIVE, C.SELECTION_REASON_ADAPTIVE,
/* trackSelectionData= */ null, /* trackSelectionData= */ null,
adjustMediaTime(mediaStartTimeUs), usToMs(mediaStartTimeUs),
adjustMediaTime(mediaEndTimeUs))); usToMs(mediaEndTimeUs)));
} }
/** Dispatches {@link #onUpstreamDiscarded(int, MediaPeriodId, MediaLoadData)}. */ /** Dispatches {@link #onUpstreamDiscarded(int, MediaPeriodId, MediaLoadData)}. */
...@@ -460,7 +466,7 @@ public interface MediaSourceEventListener { ...@@ -460,7 +466,7 @@ public interface MediaSourceEventListener {
trackFormat, trackFormat,
trackSelectionReason, trackSelectionReason,
trackSelectionData, trackSelectionData,
adjustMediaTime(mediaTimeUs), usToMs(mediaTimeUs),
/* mediaEndTimeMs= */ C.TIME_UNSET)); /* mediaEndTimeMs= */ C.TIME_UNSET));
} }
...@@ -474,11 +480,6 @@ public interface MediaSourceEventListener { ...@@ -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 { private static final class ListenerAndHandler {
public Handler handler; public Handler handler;
......
...@@ -517,8 +517,7 @@ public class DownloadHelperTest { ...@@ -517,8 +517,7 @@ public class DownloadHelperTest {
trackGroupArrays[periodIndex], trackGroupArrays[periodIndex],
allocator, allocator,
TEST_TIMELINE.getWindow(0, new Timeline.Window()).positionInFirstPeriodUs, TEST_TIMELINE.getWindow(0, new Timeline.Window()).positionInFirstPeriodUs,
new EventDispatcher() new EventDispatcher().withParameters(/* windowIndex= */ 0, id)) {
.withParameters(/* windowIndex= */ 0, id, /* mediaTimeOffsetMs= */ 0)) {
@Override @Override
public List<StreamKey> getStreamKeys(List<ExoTrackSelection> trackSelections) { public List<StreamKey> getStreamKeys(List<ExoTrackSelection> trackSelections) {
List<StreamKey> result = new ArrayList<>(); List<StreamKey> result = new ArrayList<>();
......
...@@ -246,10 +246,7 @@ public final class MergingMediaPeriodTest { ...@@ -246,10 +246,7 @@ public final class MergingMediaPeriodTest {
new FakeMediaPeriodWithSelectionParameters( new FakeMediaPeriodWithSelectionParameters(
new TrackGroupArray(trackGroups), new TrackGroupArray(trackGroups),
new EventDispatcher() new EventDispatcher()
.withParameters( .withParameters(/* windowIndex= */ i, new MediaPeriodId(/* periodUid= */ i)),
/* windowIndex= */ i,
new MediaPeriodId(/* periodUid= */ i),
/* mediaTimeOffsetMs= */ 0),
/* trackDataFactory= */ (unusedFormat, unusedMediaPeriodId) -> /* trackDataFactory= */ (unusedFormat, unusedMediaPeriodId) ->
ImmutableList.of( ImmutableList.of(
oneByteSample(definition.singleSampleTimeUs, C.BUFFER_FLAG_KEY_FRAME), oneByteSample(definition.singleSampleTimeUs, C.BUFFER_FLAG_KEY_FRAME),
......
...@@ -69,7 +69,7 @@ public final class ProgressiveMediaPeriodTest { ...@@ -69,7 +69,7 @@ public final class ProgressiveMediaPeriodTest {
.withParameters(/* windowIndex= */ 0, mediaPeriodId), .withParameters(/* windowIndex= */ 0, mediaPeriodId),
new DefaultLoadErrorHandlingPolicy(), new DefaultLoadErrorHandlingPolicy(),
new MediaSourceEventListener.EventDispatcher() new MediaSourceEventListener.EventDispatcher()
.withParameters(/* windowIndex= */ 0, mediaPeriodId, /* mediaTimeOffsetMs= */ 0), .withParameters(/* windowIndex= */ 0, mediaPeriodId),
sourceInfoRefreshListener, sourceInfoRefreshListener,
new DefaultAllocator(/* trimOnReset= */ true, C.DEFAULT_BUFFER_SEGMENT_SIZE), new DefaultAllocator(/* trimOnReset= */ true, C.DEFAULT_BUFFER_SEGMENT_SIZE),
/* customCacheKey= */ null, /* customCacheKey= */ null,
......
...@@ -469,8 +469,7 @@ public final class DashMediaSource extends BaseMediaSource { ...@@ -469,8 +469,7 @@ public final class DashMediaSource extends BaseMediaSource {
@Override @Override
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) { public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) {
int periodIndex = (Integer) id.periodUid - firstPeriodId; int periodIndex = (Integer) id.periodUid - firstPeriodId;
MediaSourceEventListener.EventDispatcher periodEventDispatcher = MediaSourceEventListener.EventDispatcher periodEventDispatcher = createEventDispatcher(id);
createEventDispatcher(id, manifest.getPeriod(periodIndex).startMs);
DrmSessionEventListener.EventDispatcher drmEventDispatcher = createDrmEventDispatcher(id); DrmSessionEventListener.EventDispatcher drmEventDispatcher = createDrmEventDispatcher(id);
DashMediaPeriod mediaPeriod = DashMediaPeriod mediaPeriod =
new DashMediaPeriod( new DashMediaPeriod(
......
...@@ -216,7 +216,7 @@ public final class DashMediaPeriodTest { ...@@ -216,7 +216,7 @@ public final class DashMediaPeriodTest {
.withParameters(/* windowIndex= */ 0, mediaPeriodId), .withParameters(/* windowIndex= */ 0, mediaPeriodId),
mock(LoadErrorHandlingPolicy.class), mock(LoadErrorHandlingPolicy.class),
new MediaSourceEventListener.EventDispatcher() new MediaSourceEventListener.EventDispatcher()
.withParameters(/* windowIndex= */ 0, mediaPeriodId, /* mediaTimeOffsetMs= */ 0), .withParameters(/* windowIndex= */ 0, mediaPeriodId),
/* elapsedRealtimeOffsetMs= */ 0, /* elapsedRealtimeOffsetMs= */ 0,
mock(LoaderErrorThrower.class), mock(LoaderErrorThrower.class),
mock(Allocator.class), mock(Allocator.class),
......
...@@ -89,7 +89,7 @@ public final class HlsMediaPeriodTest { ...@@ -89,7 +89,7 @@ public final class HlsMediaPeriodTest {
.withParameters(/* windowIndex= */ 0, mediaPeriodId), .withParameters(/* windowIndex= */ 0, mediaPeriodId),
mock(LoadErrorHandlingPolicy.class), mock(LoadErrorHandlingPolicy.class),
new MediaSourceEventListener.EventDispatcher() new MediaSourceEventListener.EventDispatcher()
.withParameters(/* windowIndex= */ 0, mediaPeriodId, /* mediaTimeOffsetMs= */ 0), .withParameters(/* windowIndex= */ 0, mediaPeriodId),
mock(Allocator.class), mock(Allocator.class),
mock(CompositeSequenceableLoaderFactory.class), mock(CompositeSequenceableLoaderFactory.class),
/* allowChunklessPreparation= */ true, /* allowChunklessPreparation= */ true,
......
...@@ -72,7 +72,7 @@ public class SsMediaPeriodTest { ...@@ -72,7 +72,7 @@ public class SsMediaPeriodTest {
.withParameters(/* windowIndex= */ 0, mediaPeriodId), .withParameters(/* windowIndex= */ 0, mediaPeriodId),
mock(LoadErrorHandlingPolicy.class), mock(LoadErrorHandlingPolicy.class),
new MediaSourceEventListener.EventDispatcher() new MediaSourceEventListener.EventDispatcher()
.withParameters(/* windowIndex= */ 0, mediaPeriodId, /* mediaTimeOffsetMs= */ 0), .withParameters(/* windowIndex= */ 0, mediaPeriodId),
mock(LoaderErrorThrower.class), mock(LoaderErrorThrower.class),
mock(Allocator.class)); mock(Allocator.class));
}; };
......
...@@ -239,7 +239,7 @@ public class FakeMediaSource extends BaseMediaSource { ...@@ -239,7 +239,7 @@ public class FakeMediaSource extends BaseMediaSource {
Assertions.checkArgument(periodIndex != C.INDEX_UNSET); Assertions.checkArgument(periodIndex != C.INDEX_UNSET);
Period period = timeline.getPeriod(periodIndex, new Period()); Period period = timeline.getPeriod(periodIndex, new Period());
MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher = MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher =
createEventDispatcher(period.windowIndex, id, period.getPositionInWindowMs()); createEventDispatcher(period.windowIndex, id);
DrmSessionEventListener.EventDispatcher drmEventDispatcher = DrmSessionEventListener.EventDispatcher drmEventDispatcher =
createDrmEventDispatcher(period.windowIndex, id); createDrmEventDispatcher(period.windowIndex, id);
MediaPeriod mediaPeriod = MediaPeriod mediaPeriod =
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment