Commit d98e3312 by rohks Committed by Tianyi Feng

Add fields streaming format(sf), stream type(st) and version(v)

Added these CMCD-Session fields to Common Media Client Data (CMCD) logging.

#minor-release

PiperOrigin-RevId: 547435498
(cherry picked from commit d82a86fba56e23ab5037d281f6586e7aa8f2b237)
parent 6a3c3380
...@@ -66,7 +66,10 @@ public final class CmcdConfiguration { ...@@ -66,7 +66,10 @@ public final class CmcdConfiguration {
KEY_BUFFER_LENGTH, KEY_BUFFER_LENGTH,
KEY_CONTENT_ID, KEY_CONTENT_ID,
KEY_SESSION_ID, KEY_SESSION_ID,
KEY_MAXIMUM_REQUESTED_BITRATE KEY_MAXIMUM_REQUESTED_BITRATE,
KEY_STREAMING_FORMAT,
KEY_STREAM_TYPE,
KEY_VERSION
}) })
@Documented @Documented
@Target(TYPE_USE) @Target(TYPE_USE)
...@@ -84,6 +87,9 @@ public final class CmcdConfiguration { ...@@ -84,6 +87,9 @@ public final class CmcdConfiguration {
public static final String KEY_CONTENT_ID = "cid"; public static final String KEY_CONTENT_ID = "cid";
public static final String KEY_SESSION_ID = "sid"; public static final String KEY_SESSION_ID = "sid";
public static final String KEY_MAXIMUM_REQUESTED_BITRATE = "rtp"; public static final String KEY_MAXIMUM_REQUESTED_BITRATE = "rtp";
public static final String KEY_STREAMING_FORMAT = "sf";
public static final String KEY_STREAM_TYPE = "st";
public static final String KEY_VERSION = "v";
/** /**
* Factory for {@link CmcdConfiguration} instances. * Factory for {@link CmcdConfiguration} instances.
...@@ -205,7 +211,7 @@ public final class CmcdConfiguration { ...@@ -205,7 +211,7 @@ public final class CmcdConfiguration {
} }
/** /**
* Whether logging bitrate is allowed based on the {@linkplain RequestConfig request * Returns whether logging bitrate is allowed based on the {@linkplain RequestConfig request
* configuration}. * configuration}.
*/ */
public boolean isBitrateLoggingAllowed() { public boolean isBitrateLoggingAllowed() {
...@@ -213,7 +219,7 @@ public final class CmcdConfiguration { ...@@ -213,7 +219,7 @@ public final class CmcdConfiguration {
} }
/** /**
* Whether logging buffer length is allowed based on the {@linkplain RequestConfig request * Returns whether logging buffer length is allowed based on the {@linkplain RequestConfig request
* configuration}. * configuration}.
*/ */
public boolean isBufferLengthLoggingAllowed() { public boolean isBufferLengthLoggingAllowed() {
...@@ -221,7 +227,7 @@ public final class CmcdConfiguration { ...@@ -221,7 +227,7 @@ public final class CmcdConfiguration {
} }
/** /**
* Whether logging content ID is allowed based on the {@linkplain RequestConfig request * Returns whether logging content ID is allowed based on the {@linkplain RequestConfig request
* configuration}. * configuration}.
*/ */
public boolean isContentIdLoggingAllowed() { public boolean isContentIdLoggingAllowed() {
...@@ -229,7 +235,7 @@ public final class CmcdConfiguration { ...@@ -229,7 +235,7 @@ public final class CmcdConfiguration {
} }
/** /**
* Whether logging session ID is allowed based on the {@linkplain RequestConfig request * Returns whether logging session ID is allowed based on the {@linkplain RequestConfig request
* configuration}. * configuration}.
*/ */
public boolean isSessionIdLoggingAllowed() { public boolean isSessionIdLoggingAllowed() {
...@@ -237,10 +243,26 @@ public final class CmcdConfiguration { ...@@ -237,10 +243,26 @@ public final class CmcdConfiguration {
} }
/** /**
* Whether logging maximum requested throughput is allowed based on the {@linkplain RequestConfig * Returns whether logging maximum requested throughput is allowed based on the {@linkplain
* request configuration}. * RequestConfig request configuration}.
*/ */
public boolean isMaximumRequestThroughputLoggingAllowed() { public boolean isMaximumRequestThroughputLoggingAllowed() {
return requestConfig.isKeyAllowed(KEY_MAXIMUM_REQUESTED_BITRATE); return requestConfig.isKeyAllowed(KEY_MAXIMUM_REQUESTED_BITRATE);
} }
/**
* Returns whether logging streaming format is allowed based on the {@linkplain RequestConfig
* request configuration}.
*/
public boolean isStreamingFormatLoggingAllowed() {
return requestConfig.isKeyAllowed(KEY_STREAMING_FORMAT);
}
/**
* Returns whether logging stream type is allowed based on the {@linkplain RequestConfig request
* configuration}.
*/
public boolean isStreamTypeLoggingAllowed() {
return requestConfig.isKeyAllowed(KEY_STREAM_TYPE);
}
} }
...@@ -16,14 +16,20 @@ ...@@ -16,14 +16,20 @@
package com.google.android.exoplayer2.upstream; package com.google.android.exoplayer2.upstream;
import static com.google.android.exoplayer2.util.Assertions.checkArgument; import static com.google.android.exoplayer2.util.Assertions.checkArgument;
import static java.lang.annotation.ElementType.TYPE_USE;
import android.text.TextUtils; import android.text.TextUtils;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.StringDef;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection; import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** /**
* Represents the data for CMCD (Common Media Client Data) in adaptive streaming formats DASH, HLS, * Represents the data for CMCD (Common Media Client Data) in adaptive streaming formats DASH, HLS,
...@@ -41,6 +47,35 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; ...@@ -41,6 +47,35 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue;
@Deprecated @Deprecated
public final class CmcdLog { public final class CmcdLog {
/** Indicates the streaming format used for media content. */
@Retention(RetentionPolicy.SOURCE)
@StringDef({STREAMING_FORMAT_DASH, STREAMING_FORMAT_HLS, STREAMING_FORMAT_SS})
@Documented
@Target(TYPE_USE)
public @interface StreamingFormat {}
/** Indicates the type of streaming for media content. */
@Retention(RetentionPolicy.SOURCE)
@StringDef({STREAM_TYPE_VOD, STREAM_TYPE_LIVE})
@Documented
@Target(TYPE_USE)
public @interface StreamType {}
/** Represents the Dynamic Adaptive Streaming over HTTP (DASH) format. */
public static final String STREAMING_FORMAT_DASH = "d";
/** Represents the HTTP Live Streaming (HLS) format. */
public static final String STREAMING_FORMAT_HLS = "h";
/** Represents the Smooth Streaming (SS) format. */
public static final String STREAMING_FORMAT_SS = "s";
/** Represents the Video on Demand (VOD) stream type. */
public static final String STREAM_TYPE_VOD = "v";
/** Represents the Live Streaming stream type. */
public static final String STREAM_TYPE_LIVE = "l";
/** /**
* Creates a new instance. * Creates a new instance.
* *
...@@ -48,11 +83,17 @@ public final class CmcdLog { ...@@ -48,11 +83,17 @@ public final class CmcdLog {
* @param trackSelection The {@linkplain ExoTrackSelection track selection}. * @param trackSelection The {@linkplain ExoTrackSelection track selection}.
* @param bufferedDurationUs The duration of media currently buffered from the current playback * @param bufferedDurationUs The duration of media currently buffered from the current playback
* position, in microseconds. * position, in microseconds.
* @param streamingFormat The streaming format of the media content. Must be one of the allowed
* streaming formats specified by the {@link StreamingFormat} annotation.
* @param isLive {@code true} if the media content is being streamed live, {@code false}
* otherwise.
*/ */
public static CmcdLog createInstance( public static CmcdLog createInstance(
CmcdConfiguration cmcdConfiguration, CmcdConfiguration cmcdConfiguration,
ExoTrackSelection trackSelection, ExoTrackSelection trackSelection,
long bufferedDurationUs) { long bufferedDurationUs,
@StreamingFormat String streamingFormat,
boolean isLive) {
ImmutableMap<@CmcdConfiguration.HeaderKey String, String> customData = ImmutableMap<@CmcdConfiguration.HeaderKey String, String> customData =
cmcdConfiguration.requestConfig.getCustomData(); cmcdConfiguration.requestConfig.getCustomData();
int bitrateKbps = trackSelection.getSelectedFormat().bitrate / 1000; int bitrateKbps = trackSelection.getSelectedFormat().bitrate / 1000;
...@@ -80,6 +121,12 @@ public final class CmcdLog { ...@@ -80,6 +121,12 @@ public final class CmcdLog {
if (cmcdConfiguration.isSessionIdLoggingAllowed()) { if (cmcdConfiguration.isSessionIdLoggingAllowed()) {
cmcdSession.setSessionId(cmcdConfiguration.sessionId); cmcdSession.setSessionId(cmcdConfiguration.sessionId);
} }
if (cmcdConfiguration.isStreamingFormatLoggingAllowed()) {
cmcdSession.setStreamingFormat(streamingFormat);
}
if (cmcdConfiguration.isStreamTypeLoggingAllowed()) {
cmcdSession.setStreamType(isLive ? STREAM_TYPE_LIVE : STREAM_TYPE_VOD);
}
CmcdLog.CmcdStatus.Builder cmcdStatus = CmcdLog.CmcdStatus.Builder cmcdStatus =
new CmcdLog.CmcdStatus.Builder() new CmcdLog.CmcdStatus.Builder()
...@@ -292,6 +339,8 @@ public final class CmcdLog { ...@@ -292,6 +339,8 @@ public final class CmcdLog {
public static final class Builder { public static final class Builder {
@Nullable private String contentId; @Nullable private String contentId;
@Nullable private String sessionId; @Nullable private String sessionId;
@Nullable private String streamingFormat;
@Nullable private String streamType;
@Nullable private String customData; @Nullable private String customData;
/** /**
...@@ -316,6 +365,20 @@ public final class CmcdLog { ...@@ -316,6 +365,20 @@ public final class CmcdLog {
return this; return this;
} }
/** Sets the {@link CmcdSession#streamingFormat}. The default value is {@code null}. */
@CanIgnoreReturnValue
public Builder setStreamingFormat(@Nullable @StreamingFormat String streamingFormat) {
this.streamingFormat = streamingFormat;
return this;
}
/** Sets the {@link CmcdSession#streamType}. The default value is {@code null}. */
@CanIgnoreReturnValue
public Builder setStreamType(@Nullable @StreamType String streamType) {
this.streamType = streamType;
return this;
}
/** Sets the {@link CmcdSession#customData}. The default value is {@code null}. */ /** Sets the {@link CmcdSession#customData}. The default value is {@code null}. */
@CanIgnoreReturnValue @CanIgnoreReturnValue
public CmcdSession.Builder setCustomData(@Nullable String customData) { public CmcdSession.Builder setCustomData(@Nullable String customData) {
...@@ -329,6 +392,13 @@ public final class CmcdLog { ...@@ -329,6 +392,13 @@ public final class CmcdLog {
} }
/** /**
* The version of this specification used for interpreting the defined key names and values. If
* this key is omitted, the client and server MUST interpret the values as being defined by
* version 1. Client SHOULD omit this field if the version is 1.
*/
public static final int VERSION = 1;
/**
* A GUID identifying the current content, or {@code null} if unset. * A GUID identifying the current content, or {@code null} if unset.
* *
* <p>This value is consistent across multiple different sessions and devices and is defined and * <p>This value is consistent across multiple different sessions and devices and is defined and
...@@ -343,6 +413,19 @@ public final class CmcdLog { ...@@ -343,6 +413,19 @@ public final class CmcdLog {
*/ */
@Nullable public final String sessionId; @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.
*/
@Nullable public final String streamingFormat;
/**
* Type of stream. v = all segments are available – e.g., VOD and l = segments become available
* over time – e.g., LIVE.
*/
@Nullable public final String streamType;
/**
* Custom data where the values of the keys are expected to be invariant over the life of the * Custom data where the values of the keys are expected to be invariant over the life of the
* session, or {@code null} if unset. * session, or {@code null} if unset.
* *
...@@ -354,6 +437,8 @@ public final class CmcdLog { ...@@ -354,6 +437,8 @@ public final class CmcdLog {
private CmcdSession(Builder builder) { private CmcdSession(Builder builder) {
this.contentId = builder.contentId; this.contentId = builder.contentId;
this.sessionId = builder.sessionId; this.sessionId = builder.sessionId;
this.streamingFormat = builder.streamingFormat;
this.streamType = builder.streamType;
this.customData = builder.customData; this.customData = builder.customData;
} }
...@@ -374,6 +459,18 @@ public final class CmcdLog { ...@@ -374,6 +459,18 @@ public final class CmcdLog {
headerValue.append( headerValue.append(
Util.formatInvariant("%s=\"%s\",", CmcdConfiguration.KEY_SESSION_ID, sessionId)); Util.formatInvariant("%s=\"%s\",", CmcdConfiguration.KEY_SESSION_ID, sessionId));
} }
if (!TextUtils.isEmpty(this.streamingFormat)) {
headerValue.append(
Util.formatInvariant(
"%s=%s,", CmcdConfiguration.KEY_STREAMING_FORMAT, streamingFormat));
}
if (!TextUtils.isEmpty(this.streamType)) {
headerValue.append(
Util.formatInvariant("%s=%s,", CmcdConfiguration.KEY_STREAM_TYPE, streamType));
}
if (VERSION != 1) {
headerValue.append(Util.formatInvariant("%s=%d,", CmcdConfiguration.KEY_VERSION, VERSION));
}
if (!TextUtils.isEmpty(customData)) { if (!TextUtils.isEmpty(customData)) {
headerValue.append(Util.formatInvariant("%s,", customData)); headerValue.append(Util.formatInvariant("%s,", customData));
} }
......
...@@ -60,7 +60,11 @@ public class CmcdLogTest { ...@@ -60,7 +60,11 @@ public class CmcdLogTest {
.thenReturn(new Format.Builder().setPeakBitrate(840_000).build()); .thenReturn(new Format.Builder().setPeakBitrate(840_000).build());
CmcdLog cmcdLog = CmcdLog cmcdLog =
CmcdLog.createInstance( CmcdLog.createInstance(
cmcdConfiguration, trackSelection, /* bufferedDurationUs= */ 1_760_000); cmcdConfiguration,
trackSelection,
/* bufferedDurationUs= */ 1_760_000,
CmcdLog.STREAMING_FORMAT_DASH,
true);
ImmutableMap<@CmcdConfiguration.HeaderKey String, String> requestHeaders = ImmutableMap<@CmcdConfiguration.HeaderKey String, String> requestHeaders =
cmcdLog.getHttpRequestHeaders(); cmcdLog.getHttpRequestHeaders();
...@@ -72,7 +76,7 @@ public class CmcdLogTest { ...@@ -72,7 +76,7 @@ public class CmcdLogTest {
"CMCD-Request", "CMCD-Request",
"bl=1800,key2=\"stringValue\"", "bl=1800,key2=\"stringValue\"",
"CMCD-Session", "CMCD-Session",
"cid=\"mediaId\",sid=\"sessionId\"", "cid=\"mediaId\",sid=\"sessionId\",sf=d,st=l",
"CMCD-Status", "CMCD-Status",
"rtp=1700"); "rtp=1700");
} }
......
...@@ -380,7 +380,12 @@ public class DefaultDashChunkSource implements DashChunkSource { ...@@ -380,7 +380,12 @@ public class DefaultDashChunkSource implements DashChunkSource {
CmcdLog cmcdLog = CmcdLog cmcdLog =
cmcdConfiguration == null cmcdConfiguration == null
? null ? null
: CmcdLog.createInstance(cmcdConfiguration, trackSelection, bufferedDurationUs); : CmcdLog.createInstance(
cmcdConfiguration,
trackSelection,
bufferedDurationUs,
CmcdLog.STREAMING_FORMAT_DASH,
manifest.dynamic);
RepresentationHolder representationHolder = RepresentationHolder representationHolder =
updateSelectedBaseUrl(trackSelection.getSelectedIndex()); updateSelectedBaseUrl(trackSelection.getSelectedIndex());
......
...@@ -318,7 +318,7 @@ public class DefaultDashChunkSourceTest { ...@@ -318,7 +318,7 @@ public class DefaultDashChunkSourceTest {
"CMCD-Request", "CMCD-Request",
"bl=0", "bl=0",
"CMCD-Session", "CMCD-Session",
"cid=\"mediaId\",sid=\"" + cmcdConfiguration.sessionId + "\""); "cid=\"mediaId\",sid=\"" + cmcdConfiguration.sessionId + "\",sf=d,st=v");
} }
@Test @Test
...@@ -363,7 +363,7 @@ public class DefaultDashChunkSourceTest { ...@@ -363,7 +363,7 @@ public class DefaultDashChunkSourceTest {
"CMCD-Request", "CMCD-Request",
"bl=0", "bl=0",
"CMCD-Session", "CMCD-Session",
"cid=\"mediaIdcontentIdSuffix\"", "cid=\"mediaIdcontentIdSuffix\",sf=d,st=v",
"CMCD-Status", "CMCD-Status",
"rtp=3500"); "rtp=3500");
} }
...@@ -409,7 +409,7 @@ public class DefaultDashChunkSourceTest { ...@@ -409,7 +409,7 @@ public class DefaultDashChunkSourceTest {
"CMCD-Request", "CMCD-Request",
"bl=0,key2=\"stringValue\"", "bl=0,key2=\"stringValue\"",
"CMCD-Session", "CMCD-Session",
"cid=\"mediaId\",sid=\"" + cmcdConfiguration.sessionId + "\",key3=1", "cid=\"mediaId\",sid=\"" + cmcdConfiguration.sessionId + "\",sf=d,st=v,key3=1",
"CMCD-Status", "CMCD-Status",
"key4=5.0"); "key4=5.0");
} }
......
...@@ -491,7 +491,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -491,7 +491,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
CmcdLog cmcdLog = CmcdLog cmcdLog =
cmcdConfiguration == null cmcdConfiguration == null
? null ? null
: CmcdLog.createInstance(cmcdConfiguration, trackSelection, bufferedDurationUs); : CmcdLog.createInstance(
cmcdConfiguration,
trackSelection,
bufferedDurationUs,
CmcdLog.STREAMING_FORMAT_HLS,
!playlist.hasEndTag);
// 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
......
...@@ -214,7 +214,7 @@ public class HlsChunkSourceTest { ...@@ -214,7 +214,7 @@ public class HlsChunkSourceTest {
"CMCD-Request", "CMCD-Request",
"bl=0", "bl=0",
"CMCD-Session", "CMCD-Session",
"cid=\"mediaId\",sid=\"" + cmcdConfiguration.sessionId + "\""); "cid=\"mediaId\",sid=\"" + cmcdConfiguration.sessionId + "\",sf=h,st=v");
} }
@Test @Test
...@@ -260,7 +260,7 @@ public class HlsChunkSourceTest { ...@@ -260,7 +260,7 @@ public class HlsChunkSourceTest {
"CMCD-Request", "CMCD-Request",
"bl=0", "bl=0",
"CMCD-Session", "CMCD-Session",
"cid=\"mediaIdcontentIdSuffix\"", "cid=\"mediaIdcontentIdSuffix\",sf=h,st=v",
"CMCD-Status", "CMCD-Status",
"rtp=4000"); "rtp=4000");
} }
...@@ -307,7 +307,7 @@ public class HlsChunkSourceTest { ...@@ -307,7 +307,7 @@ public class HlsChunkSourceTest {
"CMCD-Request", "CMCD-Request",
"bl=0,key2=\"stringValue\"", "bl=0,key2=\"stringValue\"",
"CMCD-Session", "CMCD-Session",
"cid=\"mediaId\",sid=\"" + cmcdConfiguration.sessionId + "\",key3=1", "cid=\"mediaId\",sid=\"" + cmcdConfiguration.sessionId + "\",sf=h,st=v,key3=1",
"CMCD-Status", "CMCD-Status",
"key4=5.0"); "key4=5.0");
} }
......
...@@ -290,7 +290,12 @@ public class DefaultSsChunkSource implements SsChunkSource { ...@@ -290,7 +290,12 @@ public class DefaultSsChunkSource implements SsChunkSource {
CmcdLog cmcdLog = CmcdLog cmcdLog =
cmcdConfiguration == null cmcdConfiguration == null
? null ? null
: CmcdLog.createInstance(cmcdConfiguration, trackSelection, bufferedDurationUs); : CmcdLog.createInstance(
cmcdConfiguration,
trackSelection,
bufferedDurationUs,
CmcdLog.STREAMING_FORMAT_SS,
manifest.isLive);
out.chunk = out.chunk =
newMediaChunk( newMediaChunk(
......
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