Add field object type (ot)
Added this CMCD-Object field to Common Media Client Data (CMCD) logging. #minor-release PiperOrigin-RevId: 554843305
This commit is contained in:
parent
cba027c3b4
commit
3ec462d1cf
@ -37,7 +37,8 @@
|
||||
(([#33](https://github.com/androidx/media/issues/33)),([#9978](https://github.com/google/ExoPlayer/issues/9978))).
|
||||
* Add additional fields to Common Media Client Data (CMCD) logging:
|
||||
streaming format (sf), stream type (st), version (v), top birate (tb),
|
||||
object duration (d) and measured throughput (mtp).
|
||||
object duration (d), measured throughput (mtp) and object type(ot)
|
||||
([#8699](https://github.com/google/ExoPlayer/issues/8699)).
|
||||
* Rename `MimeTypes.TEXT_EXOPLAYER_CUES` to
|
||||
`MimeTypes.APPLICATION_MEDIA3_CUES`.
|
||||
* Add `PngExtractor` that sends and reads a whole png file into the the
|
||||
|
@ -66,7 +66,8 @@ public final class CmcdConfiguration {
|
||||
KEY_VERSION,
|
||||
KEY_TOP_BITRATE,
|
||||
KEY_OBJECT_DURATION,
|
||||
KEY_MEASURED_THROUGHPUT
|
||||
KEY_MEASURED_THROUGHPUT,
|
||||
KEY_OBJECT_TYPE
|
||||
})
|
||||
@Documented
|
||||
@Target(TYPE_USE)
|
||||
@ -90,6 +91,7 @@ public final class CmcdConfiguration {
|
||||
public static final String KEY_TOP_BITRATE = "tb";
|
||||
public static final String KEY_OBJECT_DURATION = "d";
|
||||
public static final String KEY_MEASURED_THROUGHPUT = "mtp";
|
||||
public static final String KEY_OBJECT_TYPE = "ot";
|
||||
|
||||
/**
|
||||
* Factory for {@link CmcdConfiguration} instances.
|
||||
@ -291,4 +293,12 @@ public final class CmcdConfiguration {
|
||||
public boolean isMeasuredThroughputLoggingAllowed() {
|
||||
return requestConfig.isKeyAllowed(KEY_MEASURED_THROUGHPUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether logging object type is allowed based on the {@linkplain RequestConfig request
|
||||
* configuration}.
|
||||
*/
|
||||
public boolean isObjectTypeLoggingAllowed() {
|
||||
return requestConfig.isKeyAllowed(KEY_OBJECT_TYPE);
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,8 @@ import android.text.TextUtils;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringDef;
|
||||
import androidx.media3.common.C;
|
||||
import androidx.media3.common.C.TrackType;
|
||||
import androidx.media3.common.MimeTypes;
|
||||
import androidx.media3.common.TrackGroup;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.common.util.Util;
|
||||
@ -45,6 +47,33 @@ import java.lang.annotation.Target;
|
||||
@UnstableApi
|
||||
public final class CmcdHeadersFactory {
|
||||
|
||||
/**
|
||||
* Retrieves the object type value from the given {@link ExoTrackSelection}.
|
||||
*
|
||||
* @param trackSelection The {@link ExoTrackSelection} from which to retrieve the object type.
|
||||
* @return The object type value as a String if {@link TrackType} can be mapped to one of the
|
||||
* object types specified by {@link ObjectType} annotation, or {@code null}.
|
||||
* @throws IllegalArgumentException if the provided {@link ExoTrackSelection} is {@code null}.
|
||||
*/
|
||||
@Nullable
|
||||
public static @ObjectType String getObjectType(ExoTrackSelection trackSelection) {
|
||||
checkArgument(trackSelection != null);
|
||||
@C.TrackType
|
||||
int trackType = MimeTypes.getTrackType(trackSelection.getSelectedFormat().sampleMimeType);
|
||||
if (trackType == C.TRACK_TYPE_UNKNOWN) {
|
||||
trackType = MimeTypes.getTrackType(trackSelection.getSelectedFormat().containerMimeType);
|
||||
}
|
||||
|
||||
if (trackType == C.TRACK_TYPE_AUDIO) {
|
||||
return OBJECT_TYPE_AUDIO_ONLY;
|
||||
} else if (trackType == C.TRACK_TYPE_VIDEO) {
|
||||
return OBJECT_TYPE_VIDEO_ONLY;
|
||||
} else {
|
||||
// Track type cannot be mapped to a known object type.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** Indicates the streaming format used for media content. */
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@StringDef({STREAMING_FORMAT_DASH, STREAMING_FORMAT_HLS, STREAMING_FORMAT_SS})
|
||||
@ -59,6 +88,18 @@ public final class CmcdHeadersFactory {
|
||||
@Target(TYPE_USE)
|
||||
public @interface StreamType {}
|
||||
|
||||
/** Indicates the media type of current object being requested. */
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@StringDef({
|
||||
OBJECT_TYPE_INIT_SEGMENT,
|
||||
OBJECT_TYPE_AUDIO_ONLY,
|
||||
OBJECT_TYPE_VIDEO_ONLY,
|
||||
OBJECT_TYPE_MUXED_AUDIO_AND_VIDEO
|
||||
})
|
||||
@Documented
|
||||
@Target(TYPE_USE)
|
||||
public @interface ObjectType {}
|
||||
|
||||
/** Represents the Dynamic Adaptive Streaming over HTTP (DASH) format. */
|
||||
public static final String STREAMING_FORMAT_DASH = "d";
|
||||
|
||||
@ -74,12 +115,25 @@ public final class CmcdHeadersFactory {
|
||||
/** Represents the Live Streaming stream type. */
|
||||
public static final String STREAM_TYPE_LIVE = "l";
|
||||
|
||||
/** Represents the object type for an initialization segment in a media container. */
|
||||
public static final String OBJECT_TYPE_INIT_SEGMENT = "i";
|
||||
|
||||
/** Represents the object type for audio-only content in a media container. */
|
||||
public static final String OBJECT_TYPE_AUDIO_ONLY = "a";
|
||||
|
||||
/** Represents the object type for video-only content in a media container. */
|
||||
public static final String OBJECT_TYPE_VIDEO_ONLY = "v";
|
||||
|
||||
/** Represents the object type for muxed audio and video content in a media container. */
|
||||
public static final String OBJECT_TYPE_MUXED_AUDIO_AND_VIDEO = "av";
|
||||
|
||||
private final CmcdConfiguration cmcdConfiguration;
|
||||
private final ExoTrackSelection trackSelection;
|
||||
private final long bufferedDurationUs;
|
||||
private final @StreamingFormat String streamingFormat;
|
||||
private final boolean isLive;
|
||||
private long chunkDurationUs;
|
||||
private @Nullable @ObjectType String objectType;
|
||||
|
||||
/**
|
||||
* Creates an instance.
|
||||
@ -122,6 +176,18 @@ public final class CmcdHeadersFactory {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the object type of the current object being requested. Must be one of the allowed object
|
||||
* types specified by the {@link ObjectType} annotation.
|
||||
*
|
||||
* <p>Default is {@code null}.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public CmcdHeadersFactory setObjectType(@Nullable @ObjectType String objectType) {
|
||||
this.objectType = objectType;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Creates and returns a new {@link ImmutableMap} containing the CMCD HTTP request headers. */
|
||||
public ImmutableMap<@CmcdConfiguration.HeaderKey String, String> createHttpRequestHeaders() {
|
||||
ImmutableMap<@CmcdConfiguration.HeaderKey String, String> customData =
|
||||
@ -130,24 +196,30 @@ public final class CmcdHeadersFactory {
|
||||
|
||||
CmcdObject.Builder cmcdObject =
|
||||
new CmcdObject.Builder().setCustomData(customData.get(CmcdConfiguration.KEY_CMCD_OBJECT));
|
||||
if (cmcdConfiguration.isBitrateLoggingAllowed()) {
|
||||
cmcdObject.setBitrateKbps(bitrateKbps);
|
||||
}
|
||||
if (cmcdConfiguration.isTopBitrateLoggingAllowed()) {
|
||||
TrackGroup trackGroup = trackSelection.getTrackGroup();
|
||||
int topBitrate = trackSelection.getSelectedFormat().bitrate;
|
||||
for (int i = 0; i < trackGroup.length; i++) {
|
||||
topBitrate = max(topBitrate, trackGroup.getFormat(i).bitrate);
|
||||
if (!getIsInitSegment()) {
|
||||
if (cmcdConfiguration.isBitrateLoggingAllowed()) {
|
||||
cmcdObject.setBitrateKbps(bitrateKbps);
|
||||
}
|
||||
if (cmcdConfiguration.isTopBitrateLoggingAllowed()) {
|
||||
TrackGroup trackGroup = trackSelection.getTrackGroup();
|
||||
int topBitrate = trackSelection.getSelectedFormat().bitrate;
|
||||
for (int i = 0; i < trackGroup.length; i++) {
|
||||
topBitrate = max(topBitrate, trackGroup.getFormat(i).bitrate);
|
||||
}
|
||||
cmcdObject.setTopBitrateKbps(Util.ceilDivide(topBitrate, 1000));
|
||||
}
|
||||
if (cmcdConfiguration.isObjectDurationLoggingAllowed() && chunkDurationUs != C.TIME_UNSET) {
|
||||
cmcdObject.setObjectDurationMs(chunkDurationUs / 1000);
|
||||
}
|
||||
cmcdObject.setTopBitrateKbps(Util.ceilDivide(topBitrate, 1000));
|
||||
}
|
||||
if (cmcdConfiguration.isObjectDurationLoggingAllowed() && chunkDurationUs != C.TIME_UNSET) {
|
||||
cmcdObject.setObjectDurationMs(chunkDurationUs / 1000);
|
||||
|
||||
if (cmcdConfiguration.isObjectTypeLoggingAllowed()) {
|
||||
cmcdObject.setObjectType(objectType);
|
||||
}
|
||||
|
||||
CmcdRequest.Builder cmcdRequest =
|
||||
new CmcdRequest.Builder().setCustomData(customData.get(CmcdConfiguration.KEY_CMCD_REQUEST));
|
||||
if (cmcdConfiguration.isBufferLengthLoggingAllowed()) {
|
||||
if (!getIsInitSegment() && cmcdConfiguration.isBufferLengthLoggingAllowed()) {
|
||||
cmcdRequest.setBufferLengthMs(bufferedDurationUs / 1000);
|
||||
}
|
||||
if (cmcdConfiguration.isMeasuredThroughputLoggingAllowed()
|
||||
@ -186,6 +258,10 @@ public final class CmcdHeadersFactory {
|
||||
return httpRequestHeaders.buildOrThrow();
|
||||
}
|
||||
|
||||
private boolean getIsInitSegment() {
|
||||
return objectType != null && objectType.equals(OBJECT_TYPE_INIT_SEGMENT);
|
||||
}
|
||||
|
||||
/** Keys whose values vary with the object being requested. Contains CMCD fields: {@code br}. */
|
||||
private static final class CmcdObject {
|
||||
|
||||
@ -194,6 +270,7 @@ public final class CmcdHeadersFactory {
|
||||
private int bitrateKbps;
|
||||
private int topBitrateKbps;
|
||||
private long objectDurationMs;
|
||||
@Nullable private @ObjectType String objectType;
|
||||
@Nullable private String customData;
|
||||
|
||||
/** Creates a new instance with default values. */
|
||||
@ -231,6 +308,13 @@ public final class CmcdHeadersFactory {
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Sets the {@link CmcdObject#objectType}. The default value is {@code null}. */
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setObjectType(@Nullable @ObjectType String objectType) {
|
||||
this.objectType = objectType;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Sets the {@link CmcdObject#customData}. The default value is {@code null}. */
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setCustomData(@Nullable String customData) {
|
||||
@ -268,6 +352,14 @@ public final class CmcdHeadersFactory {
|
||||
*/
|
||||
public final long objectDurationMs;
|
||||
|
||||
/**
|
||||
* The media type of the current object being requested , or {@code null} if unset. Must be one
|
||||
* of the allowed object types specified by the {@link ObjectType} annotation.
|
||||
*
|
||||
* <p>If the object type being requested is unknown, then this key MUST NOT be used.
|
||||
*/
|
||||
@Nullable public final @ObjectType String objectType;
|
||||
|
||||
/**
|
||||
* Custom data where the values of the keys vary with the object being requested, or {@code
|
||||
* null} if unset.
|
||||
@ -281,6 +373,7 @@ public final class CmcdHeadersFactory {
|
||||
this.bitrateKbps = builder.bitrateKbps;
|
||||
this.topBitrateKbps = builder.topBitrateKbps;
|
||||
this.objectDurationMs = builder.objectDurationMs;
|
||||
this.objectType = builder.objectType;
|
||||
this.customData = builder.customData;
|
||||
}
|
||||
|
||||
@ -306,6 +399,10 @@ public final class CmcdHeadersFactory {
|
||||
Util.formatInvariant(
|
||||
"%s=%d,", CmcdConfiguration.KEY_OBJECT_DURATION, objectDurationMs));
|
||||
}
|
||||
if (!TextUtils.isEmpty(objectType)) {
|
||||
headerValue.append(
|
||||
Util.formatInvariant("%s=%s,", CmcdConfiguration.KEY_OBJECT_TYPE, objectType));
|
||||
}
|
||||
if (!TextUtils.isEmpty(customData)) {
|
||||
headerValue.append(Util.formatInvariant("%s,", customData));
|
||||
}
|
||||
@ -377,6 +474,10 @@ public final class CmcdHeadersFactory {
|
||||
* The buffer length in milliseconds associated with the media object being requested, or {@link
|
||||
* C#TIME_UNSET} if unset.
|
||||
*
|
||||
* <p>This key SHOULD only be sent with an {@link CmcdObject#objectType} of {@link
|
||||
* #OBJECT_TYPE_AUDIO_ONLY}, {@link #OBJECT_TYPE_VIDEO_ONLY} or {@link
|
||||
* #OBJECT_TYPE_MUXED_AUDIO_AND_VIDEO}.
|
||||
*
|
||||
* <p>This value MUST be rounded to the nearest 100 ms.
|
||||
*/
|
||||
public final long bufferLengthMs;
|
||||
@ -531,15 +632,16 @@ public final class CmcdHeadersFactory {
|
||||
@Nullable public final String sessionId;
|
||||
|
||||
/**
|
||||
* The streaming format that defines the current request. d = MPEG DASH, h = HTTP Live Streaming
|
||||
* (HLS), s = Smooth Streaming and o = other. If the streaming format being requested is
|
||||
* unknown, then this key MUST NOT be used.
|
||||
* The streaming format that defines the current request , or {@code null} if unset. Must be one
|
||||
* of the allowed streaming formats specified by the {@link StreamingFormat} annotation.
|
||||
*
|
||||
* <p>If the streaming format being requested is unknown, then this key MUST NOT be used.
|
||||
*/
|
||||
@Nullable public final @StreamingFormat String streamingFormat;
|
||||
|
||||
/**
|
||||
* Type of stream. v = all segments are available – e.g., VOD and l = segments become available
|
||||
* over time – e.g., LIVE.
|
||||
* Type of stream, or {@code null} if unset. Must be one of the allowed stream types specified
|
||||
* by the {@link StreamType} annotation.
|
||||
*/
|
||||
@Nullable public final @StreamType String streamType;
|
||||
|
||||
|
@ -662,7 +662,9 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
||||
ImmutableMap<@CmcdConfiguration.HeaderKey String, String> httpRequestHeaders =
|
||||
cmcdHeadersFactory == null
|
||||
? ImmutableMap.of()
|
||||
: cmcdHeadersFactory.createHttpRequestHeaders();
|
||||
: cmcdHeadersFactory
|
||||
.setObjectType(CmcdHeadersFactory.OBJECT_TYPE_INIT_SEGMENT)
|
||||
.createHttpRequestHeaders();
|
||||
DataSpec dataSpec =
|
||||
DashUtil.buildDataSpec(
|
||||
representation,
|
||||
@ -706,6 +708,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
||||
? ImmutableMap.of()
|
||||
: cmcdHeadersFactory
|
||||
.setChunkDurationUs(endTimeUs - startTimeUs)
|
||||
.setObjectType(CmcdHeadersFactory.getObjectType(trackSelection))
|
||||
.createHttpRequestHeaders();
|
||||
DataSpec dataSpec =
|
||||
DashUtil.buildDataSpec(
|
||||
@ -755,6 +758,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
||||
? ImmutableMap.of()
|
||||
: cmcdHeadersFactory
|
||||
.setChunkDurationUs(endTimeUs - startTimeUs)
|
||||
.setObjectType(CmcdHeadersFactory.getObjectType(trackSelection))
|
||||
.createHttpRequestHeaders();
|
||||
DataSpec dataSpec =
|
||||
DashUtil.buildDataSpec(
|
||||
|
@ -314,7 +314,7 @@ public class DefaultDashChunkSourceTest {
|
||||
assertThat(output.chunk.dataSpec.httpRequestHeaders)
|
||||
.containsExactly(
|
||||
"CMCD-Object",
|
||||
"br=700,tb=1300,d=4000",
|
||||
"br=700,tb=1300,d=4000,ot=v",
|
||||
"CMCD-Request",
|
||||
"bl=0,mtp=1000",
|
||||
"CMCD-Session",
|
||||
@ -359,7 +359,7 @@ public class DefaultDashChunkSourceTest {
|
||||
assertThat(output.chunk.dataSpec.httpRequestHeaders)
|
||||
.containsExactly(
|
||||
"CMCD-Object",
|
||||
"br=700,tb=1300,d=4000",
|
||||
"br=700,tb=1300,d=4000,ot=v",
|
||||
"CMCD-Request",
|
||||
"bl=0,mtp=1000",
|
||||
"CMCD-Session",
|
||||
@ -405,7 +405,7 @@ public class DefaultDashChunkSourceTest {
|
||||
assertThat(output.chunk.dataSpec.httpRequestHeaders)
|
||||
.containsExactly(
|
||||
"CMCD-Object",
|
||||
"br=700,tb=1300,d=4000,key1=value1",
|
||||
"br=700,tb=1300,d=4000,ot=v,key1=value1",
|
||||
"CMCD-Request",
|
||||
"bl=0,mtp=1000,key2=\"stringValue\"",
|
||||
"CMCD-Session",
|
||||
|
@ -27,6 +27,7 @@ import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.media3.common.C;
|
||||
import androidx.media3.common.Format;
|
||||
import androidx.media3.common.MimeTypes;
|
||||
import androidx.media3.common.TrackGroup;
|
||||
import androidx.media3.common.util.TimestampAdjuster;
|
||||
import androidx.media3.common.util.UriUtil;
|
||||
@ -486,25 +487,31 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
cmcdConfiguration == null
|
||||
? null
|
||||
: new CmcdHeadersFactory(
|
||||
cmcdConfiguration,
|
||||
trackSelection,
|
||||
bufferedDurationUs,
|
||||
/* streamingFormat= */ CmcdHeadersFactory.STREAMING_FORMAT_HLS,
|
||||
/* isLive= */ !playlist.hasEndTag);
|
||||
cmcdConfiguration,
|
||||
trackSelection,
|
||||
bufferedDurationUs,
|
||||
/* streamingFormat= */ CmcdHeadersFactory.STREAMING_FORMAT_HLS,
|
||||
/* isLive= */ !playlist.hasEndTag)
|
||||
.setObjectType(
|
||||
getIsMuxedAudioAndVideo()
|
||||
? CmcdHeadersFactory.OBJECT_TYPE_MUXED_AUDIO_AND_VIDEO
|
||||
: CmcdHeadersFactory.getObjectType(trackSelection));
|
||||
|
||||
// Check if the media segment or its initialization segment are fully encrypted.
|
||||
@Nullable
|
||||
Uri initSegmentKeyUri =
|
||||
getFullEncryptionKeyUri(playlist, segmentBaseHolder.segmentBase.initializationSegment);
|
||||
out.chunk =
|
||||
maybeCreateEncryptionChunkFor(initSegmentKeyUri, selectedTrackIndex, cmcdHeadersFactory);
|
||||
maybeCreateEncryptionChunkFor(
|
||||
initSegmentKeyUri, selectedTrackIndex, /* isInitSegment= */ true, cmcdHeadersFactory);
|
||||
if (out.chunk != null) {
|
||||
return;
|
||||
}
|
||||
@Nullable
|
||||
Uri mediaSegmentKeyUri = getFullEncryptionKeyUri(playlist, segmentBaseHolder.segmentBase);
|
||||
out.chunk =
|
||||
maybeCreateEncryptionChunkFor(mediaSegmentKeyUri, selectedTrackIndex, cmcdHeadersFactory);
|
||||
maybeCreateEncryptionChunkFor(
|
||||
mediaSegmentKeyUri, selectedTrackIndex, /* isInitSegment= */ false, cmcdHeadersFactory);
|
||||
if (out.chunk != null) {
|
||||
return;
|
||||
}
|
||||
@ -543,6 +550,13 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
cmcdHeadersFactory);
|
||||
}
|
||||
|
||||
private boolean getIsMuxedAudioAndVideo() {
|
||||
Format format = trackGroup.getFormat(trackSelection.getSelectedIndex());
|
||||
String audioMimeType = MimeTypes.getAudioMediaMimeType(format.codecs);
|
||||
String videoMimeType = MimeTypes.getVideoMediaMimeType(format.codecs);
|
||||
return audioMimeType != null && videoMimeType != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static SegmentBaseHolder getNextSegmentHolder(
|
||||
HlsMediaPlaylist mediaPlaylist, long nextMediaSequence, int nextPartIndex) {
|
||||
@ -850,6 +864,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
private Chunk maybeCreateEncryptionChunkFor(
|
||||
@Nullable Uri keyUri,
|
||||
int selectedTrackIndex,
|
||||
boolean isInitSegment,
|
||||
@Nullable CmcdHeadersFactory cmcdHeadersFactory) {
|
||||
if (keyUri == null) {
|
||||
return null;
|
||||
@ -863,10 +878,15 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
keyCache.put(keyUri, encryptionKey);
|
||||
return null;
|
||||
}
|
||||
|
||||
ImmutableMap<@CmcdConfiguration.HeaderKey String, String> httpRequestHeaders =
|
||||
cmcdHeadersFactory == null
|
||||
? ImmutableMap.of()
|
||||
: cmcdHeadersFactory.createHttpRequestHeaders();
|
||||
ImmutableMap.of();
|
||||
if (cmcdHeadersFactory != null) {
|
||||
if (isInitSegment) {
|
||||
cmcdHeadersFactory.setObjectType(CmcdHeadersFactory.OBJECT_TYPE_INIT_SEGMENT);
|
||||
}
|
||||
httpRequestHeaders = cmcdHeadersFactory.createHttpRequestHeaders();
|
||||
}
|
||||
DataSpec dataSpec =
|
||||
new DataSpec.Builder()
|
||||
.setUri(keyUri)
|
||||
|
@ -141,8 +141,19 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
? getEncryptionIvArray(Assertions.checkNotNull(initSegment.encryptionIV))
|
||||
: null;
|
||||
Uri initSegmentUri = UriUtil.resolveToUri(mediaPlaylist.baseUri, initSegment.url);
|
||||
ImmutableMap<@CmcdConfiguration.HeaderKey String, String> initHttpRequestHeaders =
|
||||
cmcdHeadersFactory == null
|
||||
? ImmutableMap.of()
|
||||
: cmcdHeadersFactory
|
||||
.setObjectType(CmcdHeadersFactory.OBJECT_TYPE_INIT_SEGMENT)
|
||||
.createHttpRequestHeaders();
|
||||
initDataSpec =
|
||||
new DataSpec(initSegmentUri, initSegment.byteRangeOffset, initSegment.byteRangeLength);
|
||||
new DataSpec.Builder()
|
||||
.setUri(initSegmentUri)
|
||||
.setPosition(initSegment.byteRangeOffset)
|
||||
.setLength(initSegment.byteRangeLength)
|
||||
.setHttpRequestHeaders(initHttpRequestHeaders)
|
||||
.build();
|
||||
initDataSource = buildDataSource(dataSource, initSegmentKey, initSegmentIv);
|
||||
}
|
||||
|
||||
|
@ -210,7 +210,7 @@ public class HlsChunkSourceTest {
|
||||
assertThat(output.chunk.dataSpec.httpRequestHeaders)
|
||||
.containsExactly(
|
||||
"CMCD-Object",
|
||||
"br=800,tb=800,d=4000",
|
||||
"br=800,tb=800,d=4000,ot=v",
|
||||
"CMCD-Request",
|
||||
"bl=0",
|
||||
"CMCD-Session",
|
||||
@ -256,7 +256,7 @@ public class HlsChunkSourceTest {
|
||||
assertThat(output.chunk.dataSpec.httpRequestHeaders)
|
||||
.containsExactly(
|
||||
"CMCD-Object",
|
||||
"br=800,tb=800,d=4000",
|
||||
"br=800,tb=800,d=4000,ot=v",
|
||||
"CMCD-Request",
|
||||
"bl=0",
|
||||
"CMCD-Session",
|
||||
@ -303,7 +303,7 @@ public class HlsChunkSourceTest {
|
||||
assertThat(output.chunk.dataSpec.httpRequestHeaders)
|
||||
.containsExactly(
|
||||
"CMCD-Object",
|
||||
"br=800,tb=800,d=4000,key1=value1",
|
||||
"br=800,tb=800,d=4000,ot=v,key1=value1",
|
||||
"CMCD-Request",
|
||||
"bl=0,key2=\"stringValue\"",
|
||||
"CMCD-Session",
|
||||
|
@ -290,7 +290,8 @@ public class DefaultSsChunkSource implements SsChunkSource {
|
||||
bufferedDurationUs,
|
||||
/* streamingFormat= */ CmcdHeadersFactory.STREAMING_FORMAT_SS,
|
||||
/* isLive= */ manifest.isLive)
|
||||
.setChunkDurationUs(chunkEndTimeUs - chunkStartTimeUs);
|
||||
.setChunkDurationUs(chunkEndTimeUs - chunkStartTimeUs)
|
||||
.setObjectType(CmcdHeadersFactory.getObjectType(trackSelection));
|
||||
|
||||
out.chunk =
|
||||
newMediaChunk(
|
||||
|
@ -64,7 +64,7 @@ public class DefaultSsChunkSourceTest {
|
||||
assertThat(output.chunk.dataSpec.httpRequestHeaders)
|
||||
.containsExactly(
|
||||
"CMCD-Object",
|
||||
"br=308,tb=1536,d=1968",
|
||||
"br=308,tb=1536,d=1968,ot=v",
|
||||
"CMCD-Request",
|
||||
"bl=0,mtp=1000",
|
||||
"CMCD-Session",
|
||||
@ -109,7 +109,7 @@ public class DefaultSsChunkSourceTest {
|
||||
assertThat(output.chunk.dataSpec.httpRequestHeaders)
|
||||
.containsExactly(
|
||||
"CMCD-Object",
|
||||
"br=308,tb=1536,d=1968",
|
||||
"br=308,tb=1536,d=1968,ot=v",
|
||||
"CMCD-Request",
|
||||
"bl=0,mtp=1000",
|
||||
"CMCD-Session",
|
||||
@ -155,7 +155,7 @@ public class DefaultSsChunkSourceTest {
|
||||
assertThat(output.chunk.dataSpec.httpRequestHeaders)
|
||||
.containsExactly(
|
||||
"CMCD-Object",
|
||||
"br=308,tb=1536,d=1968,key1=value1",
|
||||
"br=308,tb=1536,d=1968,ot=v,key1=value1",
|
||||
"CMCD-Request",
|
||||
"bl=0,mtp=1000,key2=\"stringValue\"",
|
||||
"CMCD-Session",
|
||||
|
Loading…
x
Reference in New Issue
Block a user