Commit fd060619 by rohks Committed by Tianyi Feng

Add CMCD logging when requesting initialization chunk for DASH and HLS

Additionally, two existing methods to `buildDataSpec` in `DashUtil` have been deprecated, while a new method has been added that allows the inclusion of `httpRequestHeaders`.

Issue: google/ExoPlayer#8699

#minor-release

PiperOrigin-RevId: 540594444
(cherry picked from commit c69b6fe41d065175dacc22b1b30efed91b8102f1)
parent 593590c0
...@@ -36,8 +36,10 @@ import com.google.android.exoplayer2.upstream.DataSpec; ...@@ -36,8 +36,10 @@ import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.ParsingLoadable; import com.google.android.exoplayer2.upstream.ParsingLoadable;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.common.collect.ImmutableMap;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* Utility methods for DASH streams. * Utility methods for DASH streams.
...@@ -58,33 +60,47 @@ public final class DashUtil { ...@@ -58,33 +60,47 @@ public final class DashUtil {
* @param requestUri The {@link RangedUri} of the data to request. * @param requestUri The {@link RangedUri} of the data to request.
* @param flags Flags to be set on the returned {@link DataSpec}. See {@link * @param flags Flags to be set on the returned {@link DataSpec}. See {@link
* DataSpec.Builder#setFlags(int)}. * DataSpec.Builder#setFlags(int)}.
* @param httpRequestHeaders The {@link DataSpec#httpRequestHeaders}.
* @return The {@link DataSpec}. * @return The {@link DataSpec}.
*/ */
public static DataSpec buildDataSpec( public static DataSpec buildDataSpec(
Representation representation, String baseUrl, RangedUri requestUri, int flags) { Representation representation,
String baseUrl,
RangedUri requestUri,
int flags,
Map<String, String> httpRequestHeaders) {
return new DataSpec.Builder() return new DataSpec.Builder()
.setUri(requestUri.resolveUri(baseUrl)) .setUri(requestUri.resolveUri(baseUrl))
.setPosition(requestUri.start) .setPosition(requestUri.start)
.setLength(requestUri.length) .setLength(requestUri.length)
.setKey(resolveCacheKey(representation, requestUri)) .setKey(resolveCacheKey(representation, requestUri))
.setFlags(flags) .setFlags(flags)
.setHttpRequestHeaders(httpRequestHeaders)
.build(); .build();
} }
/** /**
* Builds a {@link DataSpec} for a given {@link RangedUri} belonging to {@link Representation}. * @deprecated Use {@link #buildDataSpec(Representation, String, RangedUri, int, Map)} instead.
* */
* <p>Uses the first base URL of the representation to build the data spec. @Deprecated
* public static DataSpec buildDataSpec(
* @param representation The {@link Representation} to which the request belongs. Representation representation, String baseUrl, RangedUri requestUri, int flags) {
* @param requestUri The {@link RangedUri} of the data to request. return buildDataSpec(
* @param flags Flags to be set on the returned {@link DataSpec}. See {@link representation, baseUrl, requestUri, flags, /* httpRequestHeaders= */ ImmutableMap.of());
* DataSpec.Builder#setFlags(int)}. }
* @return The {@link DataSpec}.
/**
* @deprecated Use {@link #buildDataSpec(Representation, String, RangedUri, int, Map)} instead.
*/ */
@Deprecated
public static DataSpec buildDataSpec( public static DataSpec buildDataSpec(
Representation representation, RangedUri requestUri, int flags) { Representation representation, RangedUri requestUri, int flags) {
return buildDataSpec(representation, representation.baseUrls.get(0).url, requestUri, flags); return buildDataSpec(
representation,
representation.baseUrls.get(0).url,
requestUri,
flags,
/* httpRequestHeaders= */ ImmutableMap.of());
} }
/** /**
...@@ -298,7 +314,8 @@ public final class DashUtil { ...@@ -298,7 +314,8 @@ public final class DashUtil {
representation, representation,
representation.baseUrls.get(baseUrlIndex).url, representation.baseUrls.get(baseUrlIndex).url,
requestUri, requestUri,
/* flags= */ 0); /* flags= */ 0,
/* httpRequestHeaders= */ ImmutableMap.of());
InitializationChunk initializationChunk = InitializationChunk initializationChunk =
new InitializationChunk( new InitializationChunk(
dataSource, dataSource,
......
...@@ -376,6 +376,13 @@ public class DefaultDashChunkSource implements DashChunkSource { ...@@ -376,6 +376,13 @@ public class DefaultDashChunkSource implements DashChunkSource {
trackSelection.updateSelectedTrack( trackSelection.updateSelectedTrack(
playbackPositionUs, bufferedDurationUs, availableLiveDurationUs, queue, chunkIterators); playbackPositionUs, bufferedDurationUs, availableLiveDurationUs, queue, chunkIterators);
@Nullable
CmcdLog cmcdLog =
cmcdConfiguration == null
? null
: CmcdLog.createInstance(
cmcdConfiguration, trackSelection, playbackPositionUs, loadPositionUs);
RepresentationHolder representationHolder = RepresentationHolder representationHolder =
updateSelectedBaseUrl(trackSelection.getSelectedIndex()); updateSelectedBaseUrl(trackSelection.getSelectedIndex());
if (representationHolder.chunkExtractor != null) { if (representationHolder.chunkExtractor != null) {
...@@ -398,7 +405,8 @@ public class DefaultDashChunkSource implements DashChunkSource { ...@@ -398,7 +405,8 @@ public class DefaultDashChunkSource implements DashChunkSource {
trackSelection.getSelectionReason(), trackSelection.getSelectionReason(),
trackSelection.getSelectionData(), trackSelection.getSelectionData(),
pendingInitializationUri, pendingInitializationUri,
pendingIndexUri); pendingIndexUri,
cmcdLog);
return; return;
} }
} }
...@@ -451,13 +459,6 @@ public class DefaultDashChunkSource implements DashChunkSource { ...@@ -451,13 +459,6 @@ public class DefaultDashChunkSource implements DashChunkSource {
} }
} }
@Nullable
CmcdLog cmcdLog =
cmcdConfiguration == null
? null
: CmcdLog.createInstance(
cmcdConfiguration, trackSelection, playbackPositionUs, loadPositionUs);
long seekTimeUs = queue.isEmpty() ? loadPositionUs : C.TIME_UNSET; long seekTimeUs = queue.isEmpty() ? loadPositionUs : C.TIME_UNSET;
out.chunk = out.chunk =
newMediaChunk( newMediaChunk(
...@@ -645,7 +646,8 @@ public class DefaultDashChunkSource implements DashChunkSource { ...@@ -645,7 +646,8 @@ public class DefaultDashChunkSource implements DashChunkSource {
@C.SelectionReason int trackSelectionReason, @C.SelectionReason int trackSelectionReason,
@Nullable Object trackSelectionData, @Nullable Object trackSelectionData,
@Nullable RangedUri initializationUri, @Nullable RangedUri initializationUri,
@Nullable RangedUri indexUri) { @Nullable RangedUri indexUri,
@Nullable CmcdLog cmcdLog) {
Representation representation = representationHolder.representation; Representation representation = representationHolder.representation;
@Nullable RangedUri requestUri; @Nullable RangedUri requestUri;
if (initializationUri != null) { if (initializationUri != null) {
...@@ -659,9 +661,15 @@ public class DefaultDashChunkSource implements DashChunkSource { ...@@ -659,9 +661,15 @@ public class DefaultDashChunkSource implements DashChunkSource {
} else { } else {
requestUri = indexUri; requestUri = indexUri;
} }
ImmutableMap<@CmcdConfiguration.HeaderKey String, String> httpRequestHeaders =
cmcdLog == null ? ImmutableMap.of() : cmcdLog.getHttpRequestHeaders();
DataSpec dataSpec = DataSpec dataSpec =
DashUtil.buildDataSpec( DashUtil.buildDataSpec(
representation, representationHolder.selectedBaseUrl.url, requestUri, /* flags= */ 0); representation,
representationHolder.selectedBaseUrl.url,
requestUri,
/* flags= */ 0,
httpRequestHeaders);
return new InitializationChunk( return new InitializationChunk(
dataSource, dataSource,
dataSpec, dataSpec,
...@@ -697,8 +705,11 @@ public class DefaultDashChunkSource implements DashChunkSource { ...@@ -697,8 +705,11 @@ public class DefaultDashChunkSource implements DashChunkSource {
: DataSpec.FLAG_MIGHT_NOT_USE_FULL_NETWORK_SPEED; : DataSpec.FLAG_MIGHT_NOT_USE_FULL_NETWORK_SPEED;
DataSpec dataSpec = DataSpec dataSpec =
DashUtil.buildDataSpec( DashUtil.buildDataSpec(
representation, representationHolder.selectedBaseUrl.url, segmentUri, flags); representation,
dataSpec = dataSpec.buildUpon().setHttpRequestHeaders(httpRequestHeaders).build(); representationHolder.selectedBaseUrl.url,
segmentUri,
flags,
httpRequestHeaders);
return new SingleSampleMediaChunk( return new SingleSampleMediaChunk(
dataSource, dataSource,
dataSpec, dataSpec,
...@@ -737,8 +748,11 @@ public class DefaultDashChunkSource implements DashChunkSource { ...@@ -737,8 +748,11 @@ public class DefaultDashChunkSource implements DashChunkSource {
: DataSpec.FLAG_MIGHT_NOT_USE_FULL_NETWORK_SPEED; : DataSpec.FLAG_MIGHT_NOT_USE_FULL_NETWORK_SPEED;
DataSpec dataSpec = DataSpec dataSpec =
DashUtil.buildDataSpec( DashUtil.buildDataSpec(
representation, representationHolder.selectedBaseUrl.url, segmentUri, flags); representation,
dataSpec = dataSpec.buildUpon().setHttpRequestHeaders(httpRequestHeaders).build(); representationHolder.selectedBaseUrl.url,
segmentUri,
flags,
httpRequestHeaders);
long sampleOffsetUs = -representation.presentationTimeOffsetUs; long sampleOffsetUs = -representation.presentationTimeOffsetUs;
return new ContainerMediaChunk( return new ContainerMediaChunk(
dataSource, dataSource,
...@@ -809,7 +823,8 @@ public class DefaultDashChunkSource implements DashChunkSource { ...@@ -809,7 +823,8 @@ public class DefaultDashChunkSource implements DashChunkSource {
representationHolder.representation, representationHolder.representation,
representationHolder.selectedBaseUrl.url, representationHolder.selectedBaseUrl.url,
segmentUri, segmentUri,
flags); flags,
/* httpRequestHeaders= */ ImmutableMap.of());
} }
@Override @Override
......
...@@ -38,6 +38,7 @@ import com.google.android.exoplayer2.upstream.ParsingLoadable.Parser; ...@@ -38,6 +38,7 @@ import com.google.android.exoplayer2.upstream.ParsingLoadable.Parser;
import com.google.android.exoplayer2.upstream.cache.CacheDataSource; import com.google.android.exoplayer2.upstream.cache.CacheDataSource;
import com.google.android.exoplayer2.util.RunnableFutureTask; import com.google.android.exoplayer2.util.RunnableFutureTask;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.common.collect.ImmutableMap;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
...@@ -231,7 +232,13 @@ public final class DashDownloader extends SegmentDownloader<DashManifest> { ...@@ -231,7 +232,13 @@ public final class DashDownloader extends SegmentDownloader<DashManifest> {
private Segment createSegment( private Segment createSegment(
Representation representation, String baseUrl, long startTimeUs, RangedUri rangedUri) { Representation representation, String baseUrl, long startTimeUs, RangedUri rangedUri) {
DataSpec dataSpec = DashUtil.buildDataSpec(representation, baseUrl, rangedUri, /* flags= */ 0); DataSpec dataSpec =
DashUtil.buildDataSpec(
representation,
baseUrl,
rangedUri,
/* flags= */ 0,
/* httpRequestHeaders= */ ImmutableMap.of());
return new Segment(startTimeUs, dataSpec); return new Segment(startTimeUs, dataSpec);
} }
......
...@@ -50,6 +50,7 @@ import com.google.android.exoplayer2.util.TimestampAdjuster; ...@@ -50,6 +50,7 @@ import com.google.android.exoplayer2.util.TimestampAdjuster;
import com.google.android.exoplayer2.util.UriUtil; import com.google.android.exoplayer2.util.UriUtil;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.primitives.Ints; import com.google.common.primitives.Ints;
import java.io.IOException; import java.io.IOException;
...@@ -486,17 +487,24 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -486,17 +487,24 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
seenExpectedPlaylistError = false; seenExpectedPlaylistError = false;
expectedPlaylistUrl = null; expectedPlaylistUrl = null;
@Nullable
CmcdLog cmcdLog =
cmcdConfiguration == null
? null
: CmcdLog.createInstance(
cmcdConfiguration, trackSelection, playbackPositionUs, loadPositionUs);
// Check if the media segment or its initialization segment are fully encrypted. // Check if the media segment or its initialization segment are fully encrypted.
@Nullable @Nullable
Uri initSegmentKeyUri = Uri initSegmentKeyUri =
getFullEncryptionKeyUri(playlist, segmentBaseHolder.segmentBase.initializationSegment); getFullEncryptionKeyUri(playlist, segmentBaseHolder.segmentBase.initializationSegment);
out.chunk = maybeCreateEncryptionChunkFor(initSegmentKeyUri, selectedTrackIndex); out.chunk = maybeCreateEncryptionChunkFor(initSegmentKeyUri, selectedTrackIndex, cmcdLog);
if (out.chunk != null) { if (out.chunk != null) {
return; return;
} }
@Nullable @Nullable
Uri mediaSegmentKeyUri = getFullEncryptionKeyUri(playlist, segmentBaseHolder.segmentBase); Uri mediaSegmentKeyUri = getFullEncryptionKeyUri(playlist, segmentBaseHolder.segmentBase);
out.chunk = maybeCreateEncryptionChunkFor(mediaSegmentKeyUri, selectedTrackIndex); out.chunk = maybeCreateEncryptionChunkFor(mediaSegmentKeyUri, selectedTrackIndex, cmcdLog);
if (out.chunk != null) { if (out.chunk != null) {
return; return;
} }
...@@ -512,13 +520,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -512,13 +520,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
return; return;
} }
@Nullable
CmcdLog cmcdLog =
cmcdConfiguration == null
? null
: CmcdLog.createInstance(
cmcdConfiguration, trackSelection, playbackPositionUs, loadPositionUs);
out.chunk = out.chunk =
HlsMediaChunk.createInstance( HlsMediaChunk.createInstance(
extractorFactory, extractorFactory,
...@@ -846,7 +847,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -846,7 +847,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
} }
@Nullable @Nullable
private Chunk maybeCreateEncryptionChunkFor(@Nullable Uri keyUri, int selectedTrackIndex) { private Chunk maybeCreateEncryptionChunkFor(
@Nullable Uri keyUri, int selectedTrackIndex, @Nullable CmcdLog cmcdLog) {
if (keyUri == null) { if (keyUri == null) {
return null; return null;
} }
...@@ -859,8 +861,14 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -859,8 +861,14 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
keyCache.put(keyUri, encryptionKey); keyCache.put(keyUri, encryptionKey);
return null; return null;
} }
ImmutableMap<@CmcdConfiguration.HeaderKey String, String> httpRequestHeaders =
cmcdLog == null ? ImmutableMap.of() : cmcdLog.getHttpRequestHeaders();
DataSpec dataSpec = DataSpec dataSpec =
new DataSpec.Builder().setUri(keyUri).setFlags(DataSpec.FLAG_ALLOW_GZIP).build(); new DataSpec.Builder()
.setUri(keyUri)
.setFlags(DataSpec.FLAG_ALLOW_GZIP)
.setHttpRequestHeaders(httpRequestHeaders)
.build();
return new EncryptionKeyChunk( return new EncryptionKeyChunk(
encryptionDataSource, encryptionDataSource,
dataSpec, dataSpec,
......
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