shaka-project / shaka-player

JavaScript player library / DASH & HLS client / MSE-EME player
Apache License 2.0
7.04k stars 1.33k forks source link

Query support for PlayReady IV size in DASH #1813

Closed PaulChira46 closed 7 months ago

PaulChira46 commented 5 years ago

Hi,

We are facing some issues while trying to stream UHD (H265/HEVC) contents that were CENC-encrypted (Playready) using 16 byte Initialization Vector during the encryption process. We are using the player on Microsoft Edge, and the streaming fails with an error code 3016 (microsoft hexcode 8004b8d2). After a lot of analysis we found out that if encryption is done using an 8 byte Initialization Vector, then the streaming works fine.

We are now wondering whether the issue is related to some bug or missing support on Edge CDM side (as far as we know, CDM handles decryption of media fragments, performing the license request and using the initialization vector extracted from the senc/tenc encryption boxes of the media fragment), or it is related to some logic inside the player core that breaks under these circumstances.

Is possible that the player makes some assumptions on the media fragment encryption box sizes or moof box size, and then it somehow breaks in case of 16 byte IV ?

We already performed some tests with 8 byte IV encrypted contents, and in that case streaming works fine.

Best Regards,

Paul

johnsim commented 5 years ago

This appears to be a bug in Windows.

PlayReady does support 16 bytes IV, version 4.0 and greater, but the Windows Input Trust Authority (ITA) which provides platform-level content protection for the PlayReady CDM in Windows is erroneously returning the error MSPR_E_AES_SIXTEEN_BYTE_IVS_NOT_SUPPORTED.

Could you provide me a rights-free piece of content (e.g. Big Buck Bunny) encrypted with your tools with an IV of 16 bytes? We need that to test our fix, to ensure that fix doesn't break something else.

John

PaulChira46 commented 5 years ago

Hi John,

Many thanks for your availability and fast feedback. Unfortunately is quite complicated to provide you samples of these contents, on one side because they expose sensitive information that requires authorization, on the other because the environment (encryption, streaming server, licenser) is closed and whitelisted. Nonetheless we are asking authorization in order to understand if is possible to share with you a couple of test contents along with their encryption info. Of course in case we receive authorization I will have to send you this information using a private thread.

At the meanwhile, may I ask if you can share with us the fix/workaround that you applied ? In this way I would try to put it in place on our player version and check if it solves the issue.

Best Regards,

Paul

johnsim commented 5 years ago

Hi Paul - you can contact me directly at johnsim@microsoft.com.

joeyparrish commented 5 years ago

I believe the fix @johnsim referred to was to fix Windows / PlayReady, not the player.

johnsim commented 5 years ago

@joeyparrish is correct. This is a bug in Windows.

I understand the content issue well. What would be helpful is encoding/encrypting something like “big buck bunny” with the same tool. If you don’t have access to the tool because you only work on the player side, perhaps you can put me in touch with your packaging partner.

PaulChira46 commented 5 years ago

Just to give an update, I'm currently in contact with John via mail and I've provided some samples of contents encrypted with 8 and 16 IVs in order to allow him to test the fix on Windows side.

EnricoFincons commented 5 years ago

Hello @johnsim, any news about a possible fix date for this issue on Windows? thanks a lot.

joeyparrish commented 4 years ago

Closing this stale external (non-Shaka) issue. If you disagree, please reply with @shaka-bot reopen, and it will be automatically reopened.

mc0re commented 4 years ago

@shaka-bot Looks like the issue is still not fixed, I'm getting 8004B8D2 as well. Also CENC and 16-bit IV.

joeyparrish commented 4 years ago

Earlier in the thread someone from Microsoft confirmed that it's a bug in Windows rather than in Shaka Player. So there's not much we can do as far as we know.

mc0re commented 4 years ago

Earlier in the thread someone from Microsoft confirmed that it's a bug in Windows rather than in Shaka Player. So there's not much we can do as far as we know.

Okay, reported to Microsoft :-)

joeyparrish commented 4 years ago

Thanks!

swenkeratmicrosoft commented 4 years ago

@shaka-bot reopen

This is not a bug in Windows. This is by design.

Specifically, the underlying Hardware (or firmware) on your system does not support 16 byte IVs and you are running in Hardware DRM mode (e.g. you are using com.microsoft.playready.recommendation.3000). Thus, this error code is returned.

The player needs to query support for this content before starting playback just like querying for things like codec support.

Presumably, the code is already using the MediaSource.isTypeSupported API to determine whether the content is supported. If you include the following in the query string, it will also check whether 16 byte IVs are supported.

"encryption-type=cenc,encryption-iv-size=16"

Note that this query (in HWDRM mode) is only supported in the Windows 10 April 2018 Update and higher.

When using software DRM (e.g. com.microsoft.playready.recommendation.2000), the above query will, unfortunately, not function properly before the Windows 10 May 2019 Update. It will return 'probably' instead of 'not supported'. 16 byte IVs are not supported in software DRM before the Windows 10 May 2019 update.

I hope that helps,

-Sam Wenker (MSFT)

@mc0re @joeyparrish

joeyparrish commented 4 years ago

If we should append "encryption-type=cenc,encryption-iv-size=16" to the media type in a support query, where will this information come from? How can the IV size be found from a DASH manifest, for example?

swenkeratmicrosoft commented 4 years ago

Unfortunately, if the website doesn't already "know" this information in advance, it is only available within the content file itself. It's not in the manifest.

To get this information from the content file, you will need to parse the MP4 from the Init segment.

Specifically, you obtain the encryption-type from the 'schm' box and the IV size from the 'tenc' box.

This information is per-track (and some tracks may not have the 'tenc' box because they are not encrypted), so you'll need to loop over all tracks specified in the mp4.

The 'schm' box (defined by ISO 14496-12 "ISO base media file format") is straightforward. The scheme_type field should be set to 'cenc' or 'cbcs' (respectively for CTR and CBC encrypted content), and you can directly pass the field's value for the encryption-type.

The 'tenc' box (defined by ISO 23001-7 "Common encryption in ISO base media file format files") is slightly more complex.

The default_Per_Sample_IV_Size field should be 0, 8, or 16. If the default_Per_Sample_IV_Size field is 8 or 16, you can directly pass that for the encryption-iv-size. Otherwise, the default_constant_IV_size field should be 8 or 16, and you can directly pass that for the encryption-iv-size.

Note: It is technically possible that the IV size can change per sample group (specified via the 'seig' box). However, I am personally unaware of any content that does changes the IV size within a track (even test content), and (as a result) I'm not even sure if Windows supports it because it's (most likely) untested.

Since ISO 23001-7 is more obscure, I've copied enough of the Track Encryption Box definition for you to parse it further down.

Hope that helps,

-Sam Wenker (MSFT)

Track Encryption box

Definition Box Type: 'tenc' Container: Scheme Information Box ('schi') Mandatory: No (Yes, for protected tracks) Quantity: Zero or one

Syntax aligned(8) class TrackEncryptionBox extends FullBox('tenc', version, flags=0) { unsigned int(8) reserved = 0; if (version==0) { unsigned int(8) reserved = 0; } else { // version is 1 or greater unsigned int(4) default_crypt_byte_block; unsigned int(4) default_skip_byte_block; } unsigned int(8) default_isProtected; unsigned int(8) default_Per_Sample_IV_Size; unsigned int(8)[16] default_KID; if (default_isProtected ==1 && default_Per_Sample_IV_Size == 0) { unsigned int(8) default_constant_IV_size; unsigned int(8)[default_constant_IV_size] default_constant_IV; } }

joeyparrish commented 4 years ago

We are not likely to jump through all these hoops to parse MP4s and extract the information from init segments. That's an unreasonable thing to ask of JavaScript, IMO.

If we did parse it, the end result would be that we reject the content early as unsupported, rather than failing to generate a license request, so there would be no difference to the end-user.

If DASH some day offers signalling for IV size, we can add it to our support queries and provide a clearer error message for this scenario.

In light of all this, and especially in light of the fact that we can't do anything at all to make 16-byte IVs work on hardware PlayReady, we would advise you to use 8-byte IVs in your content for maximum compatibility.

Sorry we weren't able to help more!

mc0re commented 4 years ago

A programmer-friendly definition of schm can be found here: https://github.com/mc0re/piff-library/blob/151d9a221609390cbef839a35f5ab87f0e68b3bb/Boxes/PiffProtectionSchemaType.cs Though the schema defined there is piff, will be cenc in this case.

joeyparrish commented 4 years ago

In an email thread with Microsoft, they pointed out these docs which have Microsoft-specific extensions to include this info in DASH:

https://docs.microsoft.com/en-us/playready/specifications/mpeg-dash-playready#213-including-track-encryption-box-fields-in-the-mpd

Specifically, the <mspr:IV_size> element would have the IV size. So I'm reopening this as an enhancement. We should parse this element and use it to query for support. If support is missing, we would mark the stream as unplayable, and if all streams are unplayable, playback would fail. If the element is missing, we would not query for IV size at all, and an unsupported IV would cause a failure to generate a license request as it does now.

joeyparrish commented 4 years ago

This feature is not on the list of high-priority features in our roadmap at this time, so if anyone is interested to contribute to this feature, let us know! We can discuss design here, and then you can send a PR. Thanks!

avelad commented 7 months ago

I've been looking and no other open source player implements this, and the parameter to use is not available in MediaCapbilities. So I'm going to close this issue, if anyone has any comments they can leave it here.