Enhance getNextChunk() API to allow passing more information
Modifies the `ChunkSource.getNextChunk(long, long, List, ChunkHolder)` method in the `ChunkSource` interface to `ChunkSource.getNextChunk(LoadingInfo, long, List, ChunkHolder)`. LoadingInfo contains additional parameters, including `playbackRate` and `lastRebufferRealtimeMs` in addition to the existing `playbackPositionUs`. The additional parameters will allow us to pass these information to Common Media Client Data (CMCD) logging. PiperOrigin-RevId: 555148768
This commit is contained in:
parent
bf5c4d8078
commit
cf9f048a3d
@ -49,6 +49,9 @@
|
||||
`LoadingInfo` contains additional parameters, including `playbackSpeed`
|
||||
and `lastRebufferRealtimeMs` in addition to the existing
|
||||
`playbackPositionUs`.
|
||||
* Enhance `ChunkSource.getNextChunk(long, long, List, ChunkHolder)` method
|
||||
in the `ChunkSource` interface to `ChunkSource.getNextChunk(LoadingInfo,
|
||||
long, List, ChunkHolder)`.
|
||||
* Transformer:
|
||||
* Parse EXIF rotation data for image inputs.
|
||||
* Remove `TransformationRequest.HdrMode` annotation type and its
|
||||
|
@ -577,8 +577,7 @@ public class ChunkSampleStream<T extends ChunkSource>
|
||||
chunkQueue = readOnlyMediaChunks;
|
||||
loadPositionUs = getLastMediaChunk().endTimeUs;
|
||||
}
|
||||
chunkSource.getNextChunk(
|
||||
loadingInfo.playbackPositionUs, loadPositionUs, chunkQueue, nextChunkHolder);
|
||||
chunkSource.getNextChunk(loadingInfo, loadPositionUs, chunkQueue, nextChunkHolder);
|
||||
boolean endOfStream = nextChunkHolder.endOfStream;
|
||||
@Nullable Chunk loadable = nextChunkHolder.chunk;
|
||||
nextChunkHolder.clear();
|
||||
|
@ -16,6 +16,7 @@
|
||||
package androidx.media3.exoplayer.source.chunk;
|
||||
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.SeekParameters;
|
||||
import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy;
|
||||
import java.io.IOException;
|
||||
@ -76,10 +77,7 @@ public interface ChunkSource {
|
||||
* been reached then {@link ChunkHolder#endOfStream} is set. If a chunk is not available but the
|
||||
* end of the stream has not been reached, the {@link ChunkHolder} is not modified.
|
||||
*
|
||||
* @param playbackPositionUs The current playback position in microseconds. If playback of the
|
||||
* period to which this chunk source belongs has not yet started, the value will be the
|
||||
* starting position in the period minus the duration of any media in previous periods still
|
||||
* to be played.
|
||||
* @param loadingInfo The {@link LoadingInfo} when loading request is made.
|
||||
* @param loadPositionUs The current load position in microseconds. If {@code queue} is empty,
|
||||
* this is the starting position from which chunks should be provided. Else it's equal to
|
||||
* {@link MediaChunk#endTimeUs} of the last chunk in the {@code queue}.
|
||||
@ -87,7 +85,7 @@ public interface ChunkSource {
|
||||
* @param out A holder to populate.
|
||||
*/
|
||||
void getNextChunk(
|
||||
long playbackPositionUs,
|
||||
LoadingInfo loadingInfo,
|
||||
long loadPositionUs,
|
||||
List<? extends MediaChunk> queue,
|
||||
ChunkHolder out);
|
||||
@ -111,8 +109,8 @@ public interface ChunkSource {
|
||||
* handling the load error.
|
||||
* @return Whether the load should be canceled so that a replacement chunk can be loaded instead.
|
||||
* Must be {@code false} if {@code cancelable} is {@code false}. If {@code true}, {@link
|
||||
* #getNextChunk(long, long, List, ChunkHolder)} will be called to obtain the replacement
|
||||
* chunk.
|
||||
* #getNextChunk(LoadingInfo, long, List, ChunkHolder)} will be called to obtain the
|
||||
* replacement chunk.
|
||||
*/
|
||||
boolean onChunkLoadError(
|
||||
Chunk chunk,
|
||||
|
@ -30,6 +30,7 @@ import androidx.media3.datasource.DataSource;
|
||||
import androidx.media3.datasource.DataSpec;
|
||||
import androidx.media3.datasource.HttpDataSource.InvalidResponseCodeException;
|
||||
import androidx.media3.datasource.TransferListener;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.SeekParameters;
|
||||
import androidx.media3.exoplayer.analytics.PlayerId;
|
||||
import androidx.media3.exoplayer.dash.PlayerEmsgHandler.PlayerTrackEmsgHandler;
|
||||
@ -315,7 +316,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
||||
|
||||
@Override
|
||||
public void getNextChunk(
|
||||
long playbackPositionUs,
|
||||
LoadingInfo loadingInfo,
|
||||
long loadPositionUs,
|
||||
List<? extends MediaChunk> queue,
|
||||
ChunkHolder out) {
|
||||
@ -323,6 +324,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
||||
return;
|
||||
}
|
||||
|
||||
long playbackPositionUs = loadingInfo.playbackPositionUs;
|
||||
long bufferedDurationUs = loadPositionUs - playbackPositionUs;
|
||||
long presentationPositionUs =
|
||||
Util.msToUs(manifest.availabilityStartTimeMs)
|
||||
|
@ -30,6 +30,7 @@ import androidx.media3.common.util.Assertions;
|
||||
import androidx.media3.common.util.Util;
|
||||
import androidx.media3.datasource.DataSpec;
|
||||
import androidx.media3.datasource.HttpDataSource;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.analytics.PlayerId;
|
||||
import androidx.media3.exoplayer.dash.manifest.DashManifest;
|
||||
import androidx.media3.exoplayer.dash.manifest.DashManifestParser;
|
||||
@ -107,7 +108,9 @@ public class DefaultDashChunkSourceTest {
|
||||
ChunkHolder output = new ChunkHolder();
|
||||
|
||||
chunkSource.getNextChunk(
|
||||
/* playbackPositionUs= */ nowInPeriodUs - 5 * C.MICROS_PER_SECOND,
|
||||
new LoadingInfo.Builder()
|
||||
.setPlaybackPositionUs(nowInPeriodUs - 5 * C.MICROS_PER_SECOND)
|
||||
.build(),
|
||||
/* loadPositionUs= */ nowInPeriodUs - 5 * C.MICROS_PER_SECOND,
|
||||
/* queue= */ ImmutableList.of(),
|
||||
output);
|
||||
@ -115,7 +118,7 @@ public class DefaultDashChunkSourceTest {
|
||||
.isEqualTo(0);
|
||||
|
||||
chunkSource.getNextChunk(
|
||||
/* playbackPositionUs= */ nowInPeriodUs,
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(nowInPeriodUs).build(),
|
||||
/* loadPositionUs= */ nowInPeriodUs,
|
||||
/* queue= */ ImmutableList.of(),
|
||||
output);
|
||||
@ -155,7 +158,7 @@ public class DefaultDashChunkSourceTest {
|
||||
|
||||
ChunkHolder output = new ChunkHolder();
|
||||
chunkSource.getNextChunk(
|
||||
/* playbackPositionUs= */ 0,
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(0).build(),
|
||||
/* loadPositionUs= */ 0,
|
||||
/* queue= */ ImmutableList.of(),
|
||||
output);
|
||||
@ -183,7 +186,7 @@ public class DefaultDashChunkSourceTest {
|
||||
boolean requestReplacementChunk = true;
|
||||
while (requestReplacementChunk) {
|
||||
chunkSource.getNextChunk(
|
||||
/* playbackPositionUs= */ 0,
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(0).build(),
|
||||
/* loadPositionUs= */ 0,
|
||||
/* queue= */ ImmutableList.of(),
|
||||
output);
|
||||
@ -213,7 +216,7 @@ public class DefaultDashChunkSourceTest {
|
||||
output.chunk.dataSpec, /* httpResponseCode= */ 404, /* errorCount= */ 1),
|
||||
loadErrorHandlingPolicy);
|
||||
chunkSource.getNextChunk(
|
||||
/* playbackPositionUs= */ 0,
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(0).build(),
|
||||
/* loadPositionUs= */ 0,
|
||||
/* queue= */ ImmutableList.of(),
|
||||
output);
|
||||
@ -241,7 +244,7 @@ public class DefaultDashChunkSourceTest {
|
||||
boolean requestReplacementChunk = true;
|
||||
while (requestReplacementChunk) {
|
||||
chunkSource.getNextChunk(
|
||||
/* playbackPositionUs= */ 0,
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(0).build(),
|
||||
/* loadPositionUs= */ 0,
|
||||
/* queue= */ ImmutableList.of(),
|
||||
output);
|
||||
@ -280,7 +283,7 @@ public class DefaultDashChunkSourceTest {
|
||||
createDashChunkSource(/* numberOfTracks= */ 2, /* cmcdConfiguration= */ null);
|
||||
ChunkHolder output = new ChunkHolder();
|
||||
chunkSource.getNextChunk(
|
||||
/* playbackPositionUs= */ 0,
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(0).build(),
|
||||
/* loadPositionUs= */ 0,
|
||||
/* queue= */ ImmutableList.of(),
|
||||
output);
|
||||
@ -307,7 +310,7 @@ public class DefaultDashChunkSourceTest {
|
||||
ChunkHolder output = new ChunkHolder();
|
||||
|
||||
chunkSource.getNextChunk(
|
||||
/* playbackPositionUs= */ 0,
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(0).build(),
|
||||
/* loadPositionUs= */ 0,
|
||||
/* queue= */ ImmutableList.of(),
|
||||
output);
|
||||
@ -352,7 +355,7 @@ public class DefaultDashChunkSourceTest {
|
||||
ChunkHolder output = new ChunkHolder();
|
||||
|
||||
chunkSource.getNextChunk(
|
||||
/* playbackPositionUs= */ 0,
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(0).build(),
|
||||
/* loadPositionUs= */ 0,
|
||||
/* queue= */ ImmutableList.of(),
|
||||
output);
|
||||
@ -398,7 +401,7 @@ public class DefaultDashChunkSourceTest {
|
||||
ChunkHolder output = new ChunkHolder();
|
||||
|
||||
chunkSource.getNextChunk(
|
||||
/* playbackPositionUs= */ 0,
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(0).build(),
|
||||
/* loadPositionUs= */ 0,
|
||||
/* queue= */ ImmutableList.of(),
|
||||
output);
|
||||
@ -447,7 +450,7 @@ public class DefaultDashChunkSourceTest {
|
||||
ChunkHolder output = new ChunkHolder();
|
||||
// Populate with last available media chunk
|
||||
chunkSource.getNextChunk(
|
||||
/* playbackPositionUs= */ 0,
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(0).build(),
|
||||
/* loadPositionUs= */ 0,
|
||||
/* queue= */ ImmutableList.of(),
|
||||
output);
|
||||
@ -456,7 +459,7 @@ public class DefaultDashChunkSourceTest {
|
||||
|
||||
// Request another chunk
|
||||
chunkSource.getNextChunk(
|
||||
/* playbackPositionUs= */ 0,
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(0).build(),
|
||||
/* loadPositionUs= */ 4_000_000,
|
||||
/* queue= */ ImmutableList.of((MediaChunk) previousChunk),
|
||||
output);
|
||||
@ -496,7 +499,7 @@ public class DefaultDashChunkSourceTest {
|
||||
ChunkHolder output = new ChunkHolder();
|
||||
// Populate with last media chunk
|
||||
chunkSource.getNextChunk(
|
||||
/* playbackPositionUs= */ 0,
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(0).build(),
|
||||
/* loadPositionUs= */ 4_000_000,
|
||||
/* queue= */ ImmutableList.of(),
|
||||
output);
|
||||
@ -505,7 +508,7 @@ public class DefaultDashChunkSourceTest {
|
||||
|
||||
// Request next chunk
|
||||
chunkSource.getNextChunk(
|
||||
/* playbackPositionUs= */ 0,
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(0).build(),
|
||||
/* loadPositionUs= */ 8_000_000,
|
||||
/* queue= */ ImmutableList.of((MediaChunk) previousChunk),
|
||||
output);
|
||||
|
@ -35,6 +35,7 @@ import androidx.media3.common.util.Util;
|
||||
import androidx.media3.datasource.DataSource;
|
||||
import androidx.media3.datasource.DataSpec;
|
||||
import androidx.media3.datasource.TransferListener;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.SeekParameters;
|
||||
import androidx.media3.exoplayer.analytics.PlayerId;
|
||||
import androidx.media3.exoplayer.hls.playlist.HlsMediaPlaylist;
|
||||
@ -364,10 +365,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
* but the end of the stream has not been reached, {@link HlsChunkHolder#playlistUrl} is set to
|
||||
* contain the {@link Uri} that refers to the playlist that needs refreshing.
|
||||
*
|
||||
* @param playbackPositionUs The current playback position relative to the period start in
|
||||
* microseconds. If playback of the period to which this chunk source belongs has not yet
|
||||
* started, the value will be the starting position in the period minus the duration of any
|
||||
* media in previous periods still to be played.
|
||||
* @param loadingInfo The {@link LoadingInfo} when loading request is made.
|
||||
* @param loadPositionUs The current load position relative to the period start in microseconds.
|
||||
* @param queue The queue of buffered {@link HlsMediaChunk}s.
|
||||
* @param allowEndOfStream Whether {@link HlsChunkHolder#endOfStream} is allowed to be set for
|
||||
@ -376,13 +374,14 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
* @param out A holder to populate.
|
||||
*/
|
||||
public void getNextChunk(
|
||||
long playbackPositionUs,
|
||||
LoadingInfo loadingInfo,
|
||||
long loadPositionUs,
|
||||
List<HlsMediaChunk> queue,
|
||||
boolean allowEndOfStream,
|
||||
HlsChunkHolder out) {
|
||||
@Nullable HlsMediaChunk previous = queue.isEmpty() ? null : Iterables.getLast(queue);
|
||||
int oldTrackIndex = previous == null ? C.INDEX_UNSET : trackGroup.indexOf(previous.trackFormat);
|
||||
long playbackPositionUs = loadingInfo.playbackPositionUs;
|
||||
long bufferedDurationUs = loadPositionUs - playbackPositionUs;
|
||||
long timeToLiveEdgeUs = resolveTimeToLiveEdgeUs(playbackPositionUs);
|
||||
if (previous != null && !independentSegments) {
|
||||
|
@ -761,7 +761,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
}
|
||||
nextChunkHolder.clear();
|
||||
chunkSource.getNextChunk(
|
||||
loadingInfo.playbackPositionUs,
|
||||
loadingInfo,
|
||||
loadPositionUs,
|
||||
chunkQueue,
|
||||
/* allowEndOfStream= */ prepared || !chunkQueue.isEmpty(),
|
||||
|
@ -26,6 +26,7 @@ import androidx.media3.common.C;
|
||||
import androidx.media3.common.Format;
|
||||
import androidx.media3.common.MediaItem;
|
||||
import androidx.media3.common.MimeTypes;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.SeekParameters;
|
||||
import androidx.media3.exoplayer.analytics.PlayerId;
|
||||
import androidx.media3.exoplayer.hls.playlist.HlsMediaPlaylist;
|
||||
@ -201,7 +202,7 @@ public class HlsChunkSourceTest {
|
||||
HlsChunkSource.HlsChunkHolder output = new HlsChunkSource.HlsChunkHolder();
|
||||
|
||||
testChunkSource.getNextChunk(
|
||||
/* playbackPositionUs= */ 0,
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(0).build(),
|
||||
/* loadPositionUs= */ 0,
|
||||
/* queue= */ ImmutableList.of(),
|
||||
/* allowEndOfStream= */ true,
|
||||
@ -247,7 +248,7 @@ public class HlsChunkSourceTest {
|
||||
HlsChunkSource.HlsChunkHolder output = new HlsChunkSource.HlsChunkHolder();
|
||||
|
||||
testChunkSource.getNextChunk(
|
||||
/* playbackPositionUs= */ 0,
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(0).build(),
|
||||
/* loadPositionUs= */ 0,
|
||||
/* queue= */ ImmutableList.of(),
|
||||
/* allowEndOfStream= */ true,
|
||||
@ -294,7 +295,7 @@ public class HlsChunkSourceTest {
|
||||
HlsChunkSource.HlsChunkHolder output = new HlsChunkSource.HlsChunkHolder();
|
||||
|
||||
testChunkSource.getNextChunk(
|
||||
/* playbackPositionUs= */ 0,
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(0).build(),
|
||||
/* loadPositionUs= */ 0,
|
||||
/* queue= */ ImmutableList.of(),
|
||||
/* allowEndOfStream= */ true,
|
||||
|
@ -26,6 +26,7 @@ import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.datasource.DataSource;
|
||||
import androidx.media3.datasource.DataSpec;
|
||||
import androidx.media3.datasource.TransferListener;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.SeekParameters;
|
||||
import androidx.media3.exoplayer.smoothstreaming.manifest.SsManifest;
|
||||
import androidx.media3.exoplayer.smoothstreaming.manifest.SsManifest.StreamElement;
|
||||
@ -224,7 +225,7 @@ public class DefaultSsChunkSource implements SsChunkSource {
|
||||
|
||||
@Override
|
||||
public final void getNextChunk(
|
||||
long playbackPositionUs,
|
||||
LoadingInfo loadingInfo,
|
||||
long loadPositionUs,
|
||||
List<? extends MediaChunk> queue,
|
||||
ChunkHolder out) {
|
||||
@ -258,6 +259,7 @@ public class DefaultSsChunkSource implements SsChunkSource {
|
||||
return;
|
||||
}
|
||||
|
||||
long playbackPositionUs = loadingInfo.playbackPositionUs;
|
||||
long bufferedDurationUs = loadPositionUs - playbackPositionUs;
|
||||
long timeToLiveEdgeUs = resolveTimeToLiveEdgeUs(playbackPositionUs);
|
||||
|
||||
|
@ -23,6 +23,7 @@ import androidx.media3.common.Format;
|
||||
import androidx.media3.common.MediaItem;
|
||||
import androidx.media3.common.TrackGroup;
|
||||
import androidx.media3.common.util.Assertions;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.smoothstreaming.manifest.SsManifest;
|
||||
import androidx.media3.exoplayer.smoothstreaming.manifest.SsManifestParser;
|
||||
import androidx.media3.exoplayer.source.chunk.ChunkHolder;
|
||||
@ -56,7 +57,7 @@ public class DefaultSsChunkSourceTest {
|
||||
ChunkHolder output = new ChunkHolder();
|
||||
|
||||
chunkSource.getNextChunk(
|
||||
/* playbackPositionUs= */ 0,
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(0).build(),
|
||||
/* loadPositionUs= */ 0,
|
||||
/* queue= */ ImmutableList.of(),
|
||||
output);
|
||||
@ -101,7 +102,7 @@ public class DefaultSsChunkSourceTest {
|
||||
ChunkHolder output = new ChunkHolder();
|
||||
|
||||
chunkSource.getNextChunk(
|
||||
/* playbackPositionUs= */ 0,
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(0).build(),
|
||||
/* loadPositionUs= */ 0,
|
||||
/* queue= */ ImmutableList.of(),
|
||||
output);
|
||||
@ -147,7 +148,7 @@ public class DefaultSsChunkSourceTest {
|
||||
ChunkHolder output = new ChunkHolder();
|
||||
|
||||
chunkSource.getNextChunk(
|
||||
/* playbackPositionUs= */ 0,
|
||||
new LoadingInfo.Builder().setPlaybackPositionUs(0).build(),
|
||||
/* loadPositionUs= */ 0,
|
||||
/* queue= */ ImmutableList.of(),
|
||||
output);
|
||||
|
@ -25,6 +25,7 @@ import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.datasource.DataSource;
|
||||
import androidx.media3.datasource.DataSpec;
|
||||
import androidx.media3.datasource.TransferListener;
|
||||
import androidx.media3.exoplayer.LoadingInfo;
|
||||
import androidx.media3.exoplayer.SeekParameters;
|
||||
import androidx.media3.exoplayer.source.chunk.Chunk;
|
||||
import androidx.media3.exoplayer.source.chunk.ChunkHolder;
|
||||
@ -108,10 +109,11 @@ public class FakeChunkSource implements ChunkSource {
|
||||
|
||||
@Override
|
||||
public void getNextChunk(
|
||||
long playbackPositionUs,
|
||||
LoadingInfo loadingInfo,
|
||||
long loadPositionUs,
|
||||
List<? extends MediaChunk> queue,
|
||||
ChunkHolder out) {
|
||||
long playbackPositionUs = loadingInfo.playbackPositionUs;
|
||||
long bufferedDurationUs = loadPositionUs - playbackPositionUs;
|
||||
int chunkIndex =
|
||||
queue.isEmpty()
|
||||
|
Loading…
x
Reference in New Issue
Block a user