Skip to content
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

Open
wants to merge 4 commits into
base: dev-v2
Choose a base branch
from

Conversation

TakuSemba
Copy link
Contributor

@TakuSemba TakuSemba commented Apr 25, 2018

Im trying to play a HLS content, which has a DRM content and a non-DRM content separated by #EXT-X-DISCONTINUITY, it seems like ExoPlayer uses secure decoder even when playing non-DRM content.

I think it is because ExoPlayer holds a single drmInitData.

I fixed to let ExoPlayer have drmInitData per #EXT-X-DISCONTINUITY, and I confirmed ExoPlayer switches decoder between a DRM content and a non-DRM content.

You can use the hls url that I prepared, but this would only work after successfully these my pull requests merged.

I hope this pr would be acceptable.

@@ -358,7 +358,7 @@ public void getNextChunk(HlsMediaChunk previous, long playbackPositionUs, long l
isTimestampMaster,
timestampAdjuster,
previous,
mediaPlaylist.drmInitData,
mediaPlaylist.drmInitData.get(segment.relativeDiscontinuitySequence),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think more than one drm init data can map to a single discontinuity sequence.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for taking a look at this pr.

more than one drm init data can map to a single discontinuity sequence

I coundn’t think of the situation of multiple init data in a single discontinuity sequence
Could you tell me how the playlist look like?
Do you mean we have to apply drmInitData until the next #EXT-X-KEY or the end of the playlist?

And one more thing.
As you explained here, you don’t want to use SparseArray?
If so, how do you want me to implement it?

@TakuSemba
Copy link
Contributor Author

TakuSemba commented May 8, 2018

@AquilesCanta
seeing you implemented multiple EXT-X-MAP tags here (ddef32c), I also implemented this in the same way as each segment has each drmInitData.

@AquilesCanta
Copy link
Contributor

Hi @TakuSemba, thanks for the PR. Will look into this as soon as I have some time, I promise. Hopefully we can get it pulled from. Sorry for the delay.

@@ -42,6 +42,11 @@
* 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
Copy link
Contributor

Choose a reason for hiding this comment

The 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.

@@ -81,7 +86,7 @@
* @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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit (not sure it applies): Lines should not exceed 100 chars.

@@ -17,6 +17,7 @@

import android.net.Uri;
import android.util.Base64;
import android.util.SparseArray;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a stray import?

@@ -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(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we leave this as before?

@@ -360,7 +360,7 @@ public void getNextChunk(HlsMediaChunk previous, long playbackPositionUs, long l
isTimestampMaster,
timestampAdjuster,
previous,
mediaPlaylist.drmInitData,
segment.drmInitData,
Copy link
Contributor

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.

Copy link
Contributor Author

@TakuSemba TakuSemba May 22, 2018

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. 🤔

#EXTM3U
#EXT-X-VERSION:6
#EXT-X-TARGETDURATION:18
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-MAP:URI="video_init.mp4"
#EXTINF:13.583,
video_1.m4s
#EXT-X-DISCONTINUITY
#EXT-X-KEY:METHOD=SAMPLE-AES-CTR,URI="data:text/…
#EXTINF:10.417,
video_2.m4s
#EXTINF:7.417,
video_3.m4s
…

Copy link
Contributor

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.

Copy link
Contributor Author

@TakuSemba TakuSemba May 22, 2018

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.

will be propagated as the track's format.

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.

Copy link
Contributor

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.

Copy link
Contributor Author

@TakuSemba TakuSemba May 24, 2018

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.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does your suggestion mean HlsMediaPlaylist should hold a single DrmInitData with null SchemeData#data

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.

Im playing the content, which has the first non-encrypted segment and the other widevine-encrypted segments

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.

Copy link
Contributor Author

@TakuSemba TakuSemba May 27, 2018

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!.

The tracks exposed by the MediaPeriod will not contain DRM data

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.

2018-05-24 19 42 26

http://160.16.54.236:8081/drmtest/media/drm/180p/master.m3u8 is the stream that I tested .

{
  "name": "HLS Plain (180p)",
  "uri": "http://160.16.54.236:8081/drmtest/media/plain/180p/master.m3u8"
},
{
  "name": "HLS DRM (180p)",
  "uri": "http://160.16.54.236:8081/drmtest/media/drm/180p/master.m3u8",
  "drm_scheme": "widevine",
  "drm_license_url": "https://proxy.uat.widevine.com/proxy"
},
{
  "name": "HLS Plain (180p) -> DRM (180p)",
  "uri": "http://160.16.54.236:8081/drmtest/playlist/plain180p-drm180p/master.m3u8",
  "drm_scheme": "widevine",
  "drm_license_url": "https://proxy.uat.widevine.com/proxy"
},

And your solution is not clear to me yet.

keeping a DrmInitData in the media playlist which contains SchemeData's with null SchemeData#data

does your suggestion mean keeping an another DrmInitData only for the first segment like ↓?

  private static HlsMediaPlaylist parseMediaPlaylist(LineIterator iterator, String baseUri)
      throws IOException {
    ...
    String encryptionKeyUri = null;
    String encryptionIV = null;
    DrmInitData drmInitData = null;
    DrmInitData drmInitDataforFirstSegment = // drmInitData which contains SchemeData's with null SchemeData#data;

    String line;
    while (iterator.hasNext()) {
      line = iterator.next();
        ...
    }
  }

ojw28 pushed a commit that referenced this pull request Aug 13, 2018
Also add support for parsing PlayReady DRM information

Issue:#4180

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=208094290
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants