-
Notifications
You must be signed in to change notification settings - Fork 6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
support drm init data per discontinuity #4180
base: dev-v2
Are you sure you want to change the base?
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -42,6 +42,11 @@ public static final class Segment implements Comparable<Long> { | |
* used for all segments that share an EXT-X-MAP tag. | ||
*/ | ||
@Nullable public final Segment initializationSegment; | ||
/** | ||
* DRM initialization data for sample decryption, or null if none of the segment uses sample | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should probably be changed to {@link DrmInitData} for sample decryption, or null if the segment's samples are not DRM-protected. |
||
* encryption. | ||
*/ | ||
@Nullable public final DrmInitData drmInitData; | ||
/** The duration of the segment in microseconds, as defined by #EXTINF. */ | ||
public final long durationUs; | ||
/** | ||
|
@@ -81,7 +86,7 @@ public static final class Segment implements Comparable<Long> { | |
* @param byterangeLength See {@link #byterangeLength}. | ||
*/ | ||
public Segment(String uri, long byterangeOffset, long byterangeLength) { | ||
this(uri, null, 0, -1, C.TIME_UNSET, null, null, byterangeOffset, byterangeLength, false); | ||
this(uri, null, null, 0, -1, C.TIME_UNSET, null, null, byterangeOffset, byterangeLength, false); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit (not sure it applies): Lines should not exceed 100 chars. |
||
} | ||
|
||
/** | ||
|
@@ -99,6 +104,7 @@ public Segment(String uri, long byterangeOffset, long byterangeLength) { | |
public Segment( | ||
String url, | ||
Segment initializationSegment, | ||
@Nullable DrmInitData drmInitData, | ||
long durationUs, | ||
int relativeDiscontinuitySequence, | ||
long relativeStartTimeUs, | ||
|
@@ -109,6 +115,7 @@ public Segment( | |
boolean hasGapTag) { | ||
this.url = url; | ||
this.initializationSegment = initializationSegment; | ||
this.drmInitData = drmInitData; | ||
this.durationUs = durationUs; | ||
this.relativeDiscontinuitySequence = relativeDiscontinuitySequence; | ||
this.relativeStartTimeUs = relativeStartTimeUs; | ||
|
@@ -183,11 +190,6 @@ public int compareTo(@NonNull Long relativeStartTimeUs) { | |
* Whether the playlist contains a #EXT-X-PROGRAM-DATE-TIME tag. | ||
*/ | ||
public final boolean hasProgramDateTime; | ||
/** | ||
* DRM initialization data for sample decryption, or null if none of the segment uses sample | ||
* encryption. | ||
*/ | ||
public final DrmInitData drmInitData; | ||
/** | ||
* The list of segments in the playlist. | ||
*/ | ||
|
@@ -211,7 +213,6 @@ public int compareTo(@NonNull Long relativeStartTimeUs) { | |
* @param hasIndependentSegmentsTag See {@link #hasIndependentSegmentsTag}. | ||
* @param hasEndTag See {@link #hasEndTag}. | ||
* @param hasProgramDateTime See {@link #hasProgramDateTime}. | ||
* @param drmInitData See {@link #drmInitData}. | ||
* @param segments See {@link #segments}. | ||
*/ | ||
public HlsMediaPlaylist( | ||
|
@@ -228,7 +229,6 @@ public HlsMediaPlaylist( | |
boolean hasIndependentSegmentsTag, | ||
boolean hasEndTag, | ||
boolean hasProgramDateTime, | ||
DrmInitData drmInitData, | ||
List<Segment> segments) { | ||
super(baseUri, tags); | ||
this.playlistType = playlistType; | ||
|
@@ -241,7 +241,6 @@ public HlsMediaPlaylist( | |
this.hasIndependentSegmentsTag = hasIndependentSegmentsTag; | ||
this.hasEndTag = hasEndTag; | ||
this.hasProgramDateTime = hasProgramDateTime; | ||
this.drmInitData = drmInitData; | ||
this.segments = Collections.unmodifiableList(segments); | ||
if (!segments.isEmpty()) { | ||
Segment last = segments.get(segments.size() - 1); | ||
|
@@ -309,7 +308,6 @@ public HlsMediaPlaylist copyWith(long startTimeUs, int discontinuitySequence) { | |
hasIndependentSegmentsTag, | ||
hasEndTag, | ||
hasProgramDateTime, | ||
drmInitData, | ||
segments); | ||
} | ||
|
||
|
@@ -337,7 +335,6 @@ public HlsMediaPlaylist copyWithEndTag() { | |
hasIndependentSegmentsTag, | ||
/* hasEndTag= */ true, | ||
hasProgramDateTime, | ||
drmInitData, | ||
segments); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,7 @@ | |
|
||
import android.net.Uri; | ||
import android.util.Base64; | ||
import android.util.SparseArray; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this a stray import? |
||
import com.google.android.exoplayer2.C; | ||
import com.google.android.exoplayer2.Format; | ||
import com.google.android.exoplayer2.ParserException; | ||
|
@@ -424,15 +425,16 @@ private static HlsMediaPlaylist parseMediaPlaylist(LineIterator iterator, String | |
} else if (method != null) { | ||
SchemeData schemeData = parseWidevineSchemeData(line, keyFormat); | ||
if (schemeData != null) { | ||
drmInitData = | ||
new DrmInitData( | ||
drmInitData = new DrmInitData( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we leave this as before? |
||
(METHOD_SAMPLE_AES_CENC.equals(method) | ||
|| METHOD_SAMPLE_AES_CTR.equals(method)) | ||
? C.CENC_TYPE_cenc | ||
: C.CENC_TYPE_cbcs, | ||
schemeData); | ||
} | ||
} | ||
} else { | ||
drmInitData = null; | ||
} | ||
} else if (line.startsWith(TAG_BYTERANGE)) { | ||
String byteRange = parseStringAttr(line, REGEX_BYTERANGE); | ||
|
@@ -475,6 +477,7 @@ private static HlsMediaPlaylist parseMediaPlaylist(LineIterator iterator, String | |
new Segment( | ||
line, | ||
initializationSegment, | ||
drmInitData, | ||
segmentDurationUs, | ||
relativeDiscontinuitySequence, | ||
segmentStartTimeUs, | ||
|
@@ -506,7 +509,6 @@ private static HlsMediaPlaylist parseMediaPlaylist(LineIterator iterator, String | |
hasIndependentSegmentsTag, | ||
hasEndTag, | ||
/* hasProgramDateTime= */ playlistStartTimeUs != 0, | ||
drmInitData, | ||
segments); | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is an issue with this: If the first segment is not encrypted, then the media chunk will expose no DRM init data, and the track selector will think the segment is not encrypted. I'll try to think about a solution for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I coundn't understand your concern.
I know the fact that shaka-packager creates a playlist like ↓ for a Widevine-encrypted content.
In that case, I believe that video_1.m4s is not (and should not be) encrypted and video_2.m4s ~ are encrypted with Widevine.
I think the track selector should think the segment is not encrypted, because it's not encrypted. 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The track selector does not know about specific segments, but rather about tracks. The issue is that the track is indeed encrypted (even if some of the segments are clear), but the first segment's format (unencrypted), as things are now, will be propagated as the track's format.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the replay! I understood what you mean.
but, I could not find the exact place where the track selector thinks the segment is not encrypted or a wrong track's format is propagated.
you want to me to fix it on this PR?
I'm sorry to bother you, but it would be really appreciated if you could tell me the specific point where it's happening.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I suspect might be a solution for this is keeping a DrmInitData in the media playlist which contains SchemeData's with null SchemeData#data, so as to signal that encryption of a specific CDM is eventually there, without tying it to a specific key/pssh. This DrmInitData would then be propagated by the period for the track selector to consume. This field would be populated by the playlist parser after parsing all EXT-X-KEYS present in the playlist.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about what you suggest.
Does your suggestion mean HlsMediaPlaylist should hold a single DrmInitData with null SchemeData#data? (Instead of letting each segment hold a DrmInitData)
and again, Im playing the content, which has the first non-encrypted segment and the other widevine-encrypted segments, and It plays without any problems, and could not find the place where wrong track's formats are created or propagated while breakpointing inside exoplayer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it should contain as many scheme datas as encryption schemes there are in the content. For example, if the media is encrypted using both Widevine and Playready, in would contain two SchemeDatas, one for each.
This issue does not affect playback. We have a similar problem to the one introduced here in chunkless preparation (but unlike here, we cannot do much without downloading extra stuff, which defeats the purpose of chunkless preparation).
The issue is track selection. The tracks exposed by the MediaPeriod will not contain DRM data, so the track selector will assume the content is unencrypted. The resulting behavior is a crash instead of graceful handling of unsupported DRM schemes. In this case, you are playing on a device that supports the used DRM scheme. If it didn't, the player would crash instead (potentially -though rare- with a native crash). Hopefully this is clear.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the explanation!.
I think the place where the MediaPeriod exposes the tracks is here.
But, it seems like the MediaPeriod has the track groups with non-null drmInitData in it.
http://160.16.54.236:8081/drmtest/media/drm/180p/master.m3u8 is the stream that I tested .
And your solution is not clear to me yet.
does your suggestion mean keeping an another DrmInitData only for the first segment like ↓?