forked from google/ExoPlayer
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Impr/doris 1281 cmcd base (#56) * cmcd: base architecture and basic functionality. * cmcd: have CMCD be default off, be able to activate it easily through single API call. * cmcd: implement manifest cmcd payload collector of HLS/DASH/SS. (#57) * cmcd: Implement cmcd payload collector of HLS chunk request. (#58) * cmcd: Implement cmcd payload collector of DASH chunk request. (#59) * cmcd: Implement cmcd payload collector of SS chunk request. (#60) * cmcd: Implement cmcd payload collector of progressive and side-loaded subtitle request. (#61)
- Loading branch information
Showing
32 changed files
with
1,626 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
190 changes: 190 additions & 0 deletions
190
library/common/src/main/java/com/google/android/exoplayer2/endeavor/cmcd/CMCDCollector.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
package com.google.android.exoplayer2.endeavor.cmcd; | ||
|
||
import android.net.Uri; | ||
import com.google.android.exoplayer2.endeavor.DebugBase; | ||
import com.google.android.exoplayer2.endeavor.WebUtil; | ||
import com.google.android.exoplayer2.endeavor.cmcd.CMCDType.CMCDKey; | ||
import com.google.android.exoplayer2.endeavor.cmcd.CMCDType.CMCDObjectType; | ||
import com.google.android.exoplayer2.util.Log; | ||
import java.util.EnumMap; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
public class CMCDCollector { | ||
|
||
private final CMCDContext context; | ||
private final EnumMap<CMCDKey, Object> dataMap; | ||
|
||
public CMCDCollector(CMCDContext context) { | ||
this.context = context; | ||
this.dataMap = new EnumMap<>(CMCDKey.class); | ||
} | ||
|
||
// Public method. | ||
|
||
public void updateEncodedBitrate(int encodedBitrate) { | ||
if (encodedBitrate > 0) { | ||
setPayload(CMCDKey.ENCODED_BITRATE, encodedBitrate); | ||
} | ||
} | ||
|
||
public void updateObjectDuration(int objectDuration) { | ||
setPayload(CMCDKey.OBJECT_DURATION, objectDuration); | ||
} | ||
|
||
public void updateNextObjectRequest(String nextObjectRequest) { | ||
setPayload(CMCDKey.NEXT_OBJECT_REQUEST, nextObjectRequest); | ||
} | ||
|
||
public void updateNextRangeRequest(String nextRangeRequest) { | ||
setPayload(CMCDKey.NEXT_RANGE_REQUEST, nextRangeRequest); | ||
} | ||
|
||
public void updateObjectType(CMCDObjectType objectType) { | ||
setPayload(CMCDKey.OBJECT_TYPE, objectType == null ? null : objectType.getToken()); | ||
} | ||
|
||
public void updateRequestedThroughput(int requestedThroughput) { | ||
setPayload(CMCDKey.REQUESTED_MAXIMUM_THROUGHPUT, requestedThroughput); | ||
} | ||
|
||
public void updateStartup(boolean startup) { | ||
setPayload(CMCDKey.STARTUP, startup ? "" : null); | ||
} | ||
|
||
public void updateTopBitrate(int topBitrate) { | ||
context.updateTopBitrate(topBitrate); | ||
} | ||
|
||
public Map<String, String> buildHeaders(Uri dataSpecUri) { | ||
boolean isAudioVideoType = CMCDObjectType.isAudioVideo(getPayload(CMCDKey.OBJECT_TYPE)); | ||
Map<String, String> headers = new HashMap<>(); | ||
for (CMCDKey key : CMCDKey.values()) { | ||
buildPayload(isAudioVideoType, key, headers); | ||
} | ||
|
||
if (DebugBase.debug_cmcd) { | ||
StringBuilder message = new StringBuilder("CMCDHeader"); | ||
for (Map.Entry<String, String> entry : headers.entrySet()) { | ||
message.append("; ").append(entry); | ||
} | ||
message.append("; dataSpecUrl ").append(dataSpecUri); | ||
Log.d(WebUtil.DEBUG, message.toString()); | ||
} | ||
|
||
return headers; | ||
} | ||
|
||
// Internal method. | ||
|
||
private void buildPayload(boolean isAudioVideoType, CMCDKey key, Map<String, String> headers) { | ||
// Find payload from collector and context. | ||
Object payload = getAdjustedPayload(isAudioVideoType, key); | ||
if (payload == null) { | ||
return; | ||
} | ||
|
||
// Convert payload value. | ||
String strValue = null; | ||
switch (key) { | ||
case ENCODED_BITRATE: | ||
case OBJECT_DURATION: | ||
case TOP_BITRATE: | ||
strValue = CMCDType.intToString((int) payload); | ||
break; | ||
case BUFFER_LENGTH: | ||
case DEADLINE: | ||
case MEASURED_THROUGHPUT: | ||
case REQUESTED_MAXIMUM_THROUGHPUT: | ||
strValue = CMCDType.intRoundToString((int) payload); | ||
break; | ||
case BUFFER_STARVATION: | ||
strValue = (String) payload; | ||
context.finishBufferStarvation(); | ||
break; | ||
case CONTENT_ID: | ||
case NEXT_RANGE_REQUEST: | ||
case SESSION_ID: | ||
strValue = CMCDType.toQuoteString((String) payload); | ||
break; | ||
case NEXT_OBJECT_REQUEST: | ||
strValue = CMCDType.toEncodeString((String) payload); | ||
break; | ||
case OBJECT_TYPE: | ||
case STREAM_FORMAT: | ||
case STREAM_TYPE: | ||
case STARTUP: | ||
strValue = (String) payload; | ||
break; | ||
case PLAYBACK_RATE: | ||
strValue = CMCDType.speedToString((double) payload); | ||
break; | ||
case VERSION: | ||
strValue = CMCDType.versionToString((int) payload); | ||
break; | ||
} | ||
if (strValue == null) { | ||
return; | ||
} | ||
|
||
// Put the payload pair to header map. | ||
String payloadName = key.getKey(); | ||
String headerName = key.getHeader().getKey(); | ||
String headerValue = headers.containsKey(headerName) ? headers.get(headerName) + "," + payloadName : payloadName; | ||
if (strValue.length() > 0) { | ||
headerValue += "=" + strValue; | ||
} | ||
headers.put(headerName, headerValue); | ||
} | ||
|
||
private Object getAdjustedPayload(boolean isAudioVideoType, CMCDKey key) { | ||
if (!isAudioVideoType) { | ||
switch (key) { | ||
case BUFFER_LENGTH: | ||
case BUFFER_STARVATION: | ||
case DEADLINE: | ||
return null; | ||
} | ||
} | ||
boolean isDeadLine = (key == CMCDKey.DEADLINE); | ||
Object payload = getPayload(isDeadLine ? CMCDKey.BUFFER_LENGTH : key); | ||
if (payload == null) { | ||
return null; | ||
} | ||
if (isDeadLine) { | ||
Object obj = getPayload(CMCDKey.PLAYBACK_RATE); | ||
double speed = (obj == null ? 0 : (double) obj); | ||
if (speed == 0) { | ||
return null; | ||
} | ||
payload = (int) Math.round(((int) payload) / speed); | ||
} | ||
return payload; | ||
} | ||
|
||
protected synchronized Object getPayload(CMCDKey key) { | ||
Object payload = dataMap.get(key); | ||
if (payload == null) { | ||
payload = context.getPayload(key); | ||
} | ||
return payload; | ||
} | ||
|
||
private synchronized void setPayload(CMCDKey key, Object value) { | ||
if (context.config.isActive(key)) { | ||
dataMap.put(key, value); | ||
} | ||
} | ||
|
||
public boolean isActiveNextPayload() { | ||
return context.config.isActive(CMCDKey.NEXT_OBJECT_REQUEST) || context.config.isActive(CMCDKey.NEXT_RANGE_REQUEST); | ||
} | ||
|
||
public synchronized void release() { | ||
dataMap.clear(); | ||
} | ||
|
||
public static CMCDCollector createCollector(CMCDCollector cmcdCollector) { | ||
return (cmcdCollector == null ? null : CMCDContext.createCollector(cmcdCollector.context)); | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
library/common/src/main/java/com/google/android/exoplayer2/endeavor/cmcd/CMCDConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package com.google.android.exoplayer2.endeavor.cmcd; | ||
|
||
import com.google.android.exoplayer2.endeavor.cmcd.CMCDType.CMCDKey; | ||
import java.util.EnumMap; | ||
|
||
public class CMCDConfig { | ||
|
||
private final EnumMap<CMCDKey, Boolean> activationMap; | ||
|
||
public CMCDConfig() { | ||
this.activationMap = new EnumMap<>(CMCDKey.class); | ||
} | ||
|
||
public void setActivation(CMCDKey key, boolean activation) { | ||
activationMap.put(key, activation); | ||
} | ||
|
||
public boolean isActive(CMCDKey key) { | ||
Boolean activation = activationMap.get(key); | ||
return activation != null && activation; | ||
} | ||
} |
Oops, something went wrong.