Clarify timebase of media times in MediaLoadData.
Also fix unncessary adjustment done in ClippingMediaSource. #minor-release PiperOrigin-RevId: 372080724
This commit is contained in:
parent
837826c735
commit
b71c47f0dd
@ -87,7 +87,7 @@ public abstract class BaseMediaSource implements MediaSource {
|
||||
|
||||
/**
|
||||
* Returns a {@link MediaSourceEventListener.EventDispatcher} which dispatches all events to the
|
||||
* registered listeners with the specified media period id.
|
||||
* registered listeners with the specified {@link MediaPeriodId}.
|
||||
*
|
||||
* @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.
|
||||
@ -101,7 +101,7 @@ public abstract class BaseMediaSource implements MediaSource {
|
||||
|
||||
/**
|
||||
* Returns a {@link MediaSourceEventListener.EventDispatcher} which dispatches all events to the
|
||||
* registered listeners with the specified media period id and time offset.
|
||||
* 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.
|
||||
@ -115,7 +115,7 @@ public abstract class BaseMediaSource implements MediaSource {
|
||||
|
||||
/**
|
||||
* Returns a {@link MediaSourceEventListener.EventDispatcher} which dispatches all events to the
|
||||
* registered listeners with the specified window index, media period id and time offset.
|
||||
* registered listeners with the specified window index, {@link MediaPeriodId} and time offset.
|
||||
*
|
||||
* @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
|
||||
@ -130,7 +130,7 @@ public abstract class BaseMediaSource implements MediaSource {
|
||||
|
||||
/**
|
||||
* Returns a {@link DrmSessionEventListener.EventDispatcher} which dispatches all events to the
|
||||
* registered listeners with the specified media period id.
|
||||
* registered listeners with the specified {@link MediaPeriodId}
|
||||
*
|
||||
* @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.
|
||||
@ -143,7 +143,7 @@ public abstract class BaseMediaSource implements MediaSource {
|
||||
|
||||
/**
|
||||
* Returns a {@link DrmSessionEventListener.EventDispatcher} which dispatches all events to the
|
||||
* registered listeners with the specified window index and media period id.
|
||||
* 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
|
||||
|
@ -293,19 +293,6 @@ public final class ClippingMediaSource extends CompositeMediaSource<Void> {
|
||||
refreshSourceInfo(clippingTimeline);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long getMediaTimeForChildMediaTime(Void id, long mediaTimeMs) {
|
||||
if (mediaTimeMs == C.TIME_UNSET) {
|
||||
return C.TIME_UNSET;
|
||||
}
|
||||
long startMs = C.usToMs(startUs);
|
||||
long clippedTimeMs = max(0, mediaTimeMs - startMs);
|
||||
if (endUs != C.TIME_END_OF_SOURCE) {
|
||||
clippedTimeMs = min(C.usToMs(endUs) - startMs, clippedTimeMs);
|
||||
}
|
||||
return clippedTimeMs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a clipped view of a specified timeline.
|
||||
*/
|
||||
|
@ -184,12 +184,15 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the media time in the composite source corresponding to the specified media time in a
|
||||
* child source. The default implementation does not change the media time.
|
||||
* Returns the media time in the {@link MediaPeriod} of the composite source corresponding to the
|
||||
* specified media time in the {@link MediaPeriod} of the child source. The default implementation
|
||||
* does not change the media time.
|
||||
*
|
||||
* @param id The unique id used to prepare the child source.
|
||||
* @param mediaTimeMs A media time of the child source, in milliseconds.
|
||||
* @return The corresponding media time in the composite source, in milliseconds.
|
||||
* @param mediaTimeMs A media time in the {@link MediaPeriod} of the child source, in
|
||||
* milliseconds.
|
||||
* @return The corresponding media time in the {@link MediaPeriod} of the composite source, in
|
||||
* milliseconds.
|
||||
*/
|
||||
protected long getMediaTimeForChildMediaTime(@UnknownNull T id, long mediaTimeMs) {
|
||||
return mediaTimeMs;
|
||||
|
@ -19,7 +19,7 @@ import androidx.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
|
||||
/** Descriptor for data being loaded or selected by a media source. */
|
||||
/** Descriptor for data being loaded or selected by a {@link MediaSource}. */
|
||||
public final class MediaLoadData {
|
||||
|
||||
/** One of the {@link C} {@code DATA_TYPE_*} constants defining the type of data. */
|
||||
@ -45,13 +45,13 @@ public final class MediaLoadData {
|
||||
*/
|
||||
@Nullable public final Object trackSelectionData;
|
||||
/**
|
||||
* The start time of the media, or {@link C#TIME_UNSET} if the data does not belong to a specific
|
||||
* media period.
|
||||
* The start time of the media in the {@link MediaPeriod}, or {@link C#TIME_UNSET} if the data
|
||||
* does not belong to a specific {@link MediaPeriod}.
|
||||
*/
|
||||
public final long mediaStartTimeMs;
|
||||
/**
|
||||
* The end time of the media, or {@link C#TIME_UNSET} if the data does not belong to a specific
|
||||
* media period or the end time is unknown.
|
||||
* The end time of the media in the {@link MediaPeriod}, or {@link C#TIME_UNSET} if the data does
|
||||
* not belong to a specific {@link MediaPeriod} or the end time is unknown.
|
||||
*/
|
||||
public final long mediaEndTimeMs;
|
||||
|
||||
|
@ -94,9 +94,9 @@ public interface MediaSourceEventListener {
|
||||
* <p>This method being called does not indicate that playback has failed, or that it will fail.
|
||||
* The player may be able to recover from the error. Hence applications should <em>not</em>
|
||||
* implement this method to display a user visible error or initiate an application level retry.
|
||||
* {@link Player.EventListener#onPlayerError} is the appropriate place to implement such behavior.
|
||||
* This method is called to provide the application with an opportunity to log the error if it
|
||||
* wishes to do so.
|
||||
* {@link Player.Listener#onPlayerError} is the appropriate place to implement such behavior. This
|
||||
* method is called to provide the application with an opportunity to log the error if it wishes
|
||||
* to do so.
|
||||
*
|
||||
* @param windowIndex The window index in the timeline of the media source this load belongs to.
|
||||
* @param mediaPeriodId The {@link MediaPeriodId} this load belongs to. Null if the load does not
|
||||
|
@ -19,7 +19,6 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import android.net.Uri;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.MediaItem;
|
||||
@ -27,8 +26,6 @@ import com.google.android.exoplayer2.Player;
|
||||
import com.google.android.exoplayer2.Timeline;
|
||||
import com.google.android.exoplayer2.Timeline.Period;
|
||||
import com.google.android.exoplayer2.Timeline.Window;
|
||||
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
|
||||
import com.google.android.exoplayer2.drm.DrmSessionManager;
|
||||
import com.google.android.exoplayer2.source.ClippingMediaSource.IllegalClippingException;
|
||||
import com.google.android.exoplayer2.source.MaskingMediaSource.PlaceholderTimeline;
|
||||
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
|
||||
@ -37,9 +34,6 @@ import com.google.android.exoplayer2.testutil.FakeTimeline;
|
||||
import com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition;
|
||||
import com.google.android.exoplayer2.testutil.MediaSourceTestRunner;
|
||||
import com.google.android.exoplayer2.testutil.TimelineAsserts;
|
||||
import com.google.android.exoplayer2.upstream.Allocator;
|
||||
import com.google.android.exoplayer2.upstream.TransferListener;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
import java.io.IOException;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@ -56,7 +50,7 @@ public final class ClippingMediaSourceTest {
|
||||
private Period period;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
public void setUp() {
|
||||
window = new Timeline.Window();
|
||||
period = new Timeline.Period();
|
||||
}
|
||||
@ -485,140 +479,6 @@ public final class ClippingMediaSourceTest {
|
||||
TimelineAsserts.assertNextWindowIndices(clippedTimeline, Player.REPEAT_MODE_ALL, false, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void eventTimeWithinClippedRange() throws IOException {
|
||||
MediaLoadData mediaLoadData =
|
||||
getClippingMediaSourceMediaLoadData(
|
||||
/* clippingStartUs= */ TEST_CLIP_AMOUNT_US,
|
||||
/* clippingEndUs= */ TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US,
|
||||
/* eventStartUs= */ TEST_CLIP_AMOUNT_US + 1000,
|
||||
/* eventEndUs= */ TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US - 1000);
|
||||
assertThat(C.msToUs(mediaLoadData.mediaStartTimeMs)).isEqualTo(1000);
|
||||
assertThat(C.msToUs(mediaLoadData.mediaEndTimeMs))
|
||||
.isEqualTo(TEST_PERIOD_DURATION_US - 2 * TEST_CLIP_AMOUNT_US - 1000);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void eventTimeOutsideClippedRange() throws IOException {
|
||||
MediaLoadData mediaLoadData =
|
||||
getClippingMediaSourceMediaLoadData(
|
||||
/* clippingStartUs= */ TEST_CLIP_AMOUNT_US,
|
||||
/* clippingEndUs= */ TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US,
|
||||
/* eventStartUs= */ TEST_CLIP_AMOUNT_US - 1000,
|
||||
/* eventEndUs= */ TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US + 1000);
|
||||
assertThat(C.msToUs(mediaLoadData.mediaStartTimeMs)).isEqualTo(0);
|
||||
assertThat(C.msToUs(mediaLoadData.mediaEndTimeMs))
|
||||
.isEqualTo(TEST_PERIOD_DURATION_US - 2 * TEST_CLIP_AMOUNT_US);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unsetEventTime() throws IOException {
|
||||
MediaLoadData mediaLoadData =
|
||||
getClippingMediaSourceMediaLoadData(
|
||||
/* clippingStartUs= */ TEST_CLIP_AMOUNT_US,
|
||||
/* clippingEndUs= */ TEST_PERIOD_DURATION_US - TEST_CLIP_AMOUNT_US,
|
||||
/* eventStartUs= */ C.TIME_UNSET,
|
||||
/* eventEndUs= */ C.TIME_UNSET);
|
||||
assertThat(C.msToUs(mediaLoadData.mediaStartTimeMs)).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(C.msToUs(mediaLoadData.mediaEndTimeMs)).isEqualTo(C.TIME_UNSET);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void eventTimeWithUnsetDuration() throws IOException {
|
||||
MediaLoadData mediaLoadData =
|
||||
getClippingMediaSourceMediaLoadData(
|
||||
/* clippingStartUs= */ TEST_CLIP_AMOUNT_US,
|
||||
/* clippingEndUs= */ C.TIME_END_OF_SOURCE,
|
||||
/* eventStartUs= */ TEST_CLIP_AMOUNT_US,
|
||||
/* eventEndUs= */ TEST_CLIP_AMOUNT_US + 1_000_000);
|
||||
assertThat(C.msToUs(mediaLoadData.mediaStartTimeMs)).isEqualTo(0);
|
||||
assertThat(C.msToUs(mediaLoadData.mediaEndTimeMs)).isEqualTo(1_000_000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps a timeline of duration {@link #TEST_PERIOD_DURATION_US} in a {@link ClippingMediaSource},
|
||||
* sends a media source event from the child source and returns the reported {@link MediaLoadData}
|
||||
* for the clipping media source.
|
||||
*
|
||||
* @param clippingStartUs The start time of the media source clipping, in microseconds.
|
||||
* @param clippingEndUs The end time of the media source clipping, in microseconds.
|
||||
* @param eventStartUs The start time of the media source event (before clipping), in
|
||||
* microseconds.
|
||||
* @param eventEndUs The end time of the media source event (before clipping), in microseconds.
|
||||
* @return The reported {@link MediaLoadData} for that event.
|
||||
*/
|
||||
private static MediaLoadData getClippingMediaSourceMediaLoadData(
|
||||
long clippingStartUs, long clippingEndUs, final long eventStartUs, final long eventEndUs)
|
||||
throws IOException {
|
||||
Timeline timeline =
|
||||
new SinglePeriodTimeline(
|
||||
TEST_PERIOD_DURATION_US,
|
||||
/* isSeekable= */ true,
|
||||
/* isDynamic= */ false,
|
||||
/* useLiveConfiguration= */ false,
|
||||
/* manifest= */ null,
|
||||
MediaItem.fromUri(Uri.EMPTY));
|
||||
FakeMediaSource fakeMediaSource =
|
||||
new FakeMediaSource(timeline) {
|
||||
@Override
|
||||
protected MediaPeriod createMediaPeriod(
|
||||
MediaPeriodId id,
|
||||
TrackGroupArray trackGroupArray,
|
||||
Allocator allocator,
|
||||
MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher,
|
||||
DrmSessionManager drmSessionManager,
|
||||
DrmSessionEventListener.EventDispatcher drmEventDispatcher,
|
||||
@Nullable TransferListener transferListener) {
|
||||
mediaSourceEventDispatcher.downstreamFormatChanged(
|
||||
new MediaLoadData(
|
||||
C.DATA_TYPE_MEDIA,
|
||||
C.TRACK_TYPE_UNKNOWN,
|
||||
/* trackFormat= */ null,
|
||||
C.SELECTION_REASON_UNKNOWN,
|
||||
/* trackSelectionData= */ null,
|
||||
C.usToMs(eventStartUs),
|
||||
C.usToMs(eventEndUs)));
|
||||
return super.createMediaPeriod(
|
||||
id,
|
||||
trackGroupArray,
|
||||
allocator,
|
||||
mediaSourceEventDispatcher,
|
||||
drmSessionManager,
|
||||
drmEventDispatcher,
|
||||
transferListener);
|
||||
}
|
||||
};
|
||||
final ClippingMediaSource clippingMediaSource =
|
||||
new ClippingMediaSource(fakeMediaSource, clippingStartUs, clippingEndUs);
|
||||
MediaSourceTestRunner testRunner =
|
||||
new MediaSourceTestRunner(clippingMediaSource, /* allocator= */ null);
|
||||
final MediaLoadData[] reportedMediaLoadData = new MediaLoadData[1];
|
||||
try {
|
||||
testRunner.runOnPlaybackThread(
|
||||
() ->
|
||||
clippingMediaSource.addEventListener(
|
||||
Util.createHandlerForCurrentLooper(),
|
||||
new MediaSourceEventListener() {
|
||||
@Override
|
||||
public void onDownstreamFormatChanged(
|
||||
int windowIndex,
|
||||
@Nullable MediaPeriodId mediaPeriodId,
|
||||
MediaLoadData mediaLoadData) {
|
||||
reportedMediaLoadData[0] = mediaLoadData;
|
||||
}
|
||||
}));
|
||||
testRunner.prepareSource();
|
||||
// Create period to send the test event configured above.
|
||||
testRunner.createPeriod(
|
||||
new MediaPeriodId(
|
||||
timeline.getUidOfPeriod(/* periodIndex= */ 0), /* windowSequenceNumber= */ 0));
|
||||
assertThat(reportedMediaLoadData[0]).isNotNull();
|
||||
} finally {
|
||||
testRunner.release();
|
||||
}
|
||||
return reportedMediaLoadData[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the specified timeline in a {@link ClippingMediaSource} and returns the clipped timeline.
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user