Conversation
|
Hi @CastagnaIT , What session info do you need to make your addon complaint for the new manifest? I am not expert on DRM, but network and IT related, so I could get a solution. ;) Cheers |
|
is visible in the code changes: from what i understand to get these data, there should be an opportunity to initialise the DRM session before requesting the manifest, but currently ISA works differently and not allow it, |
|
@CastagnaIT I think what we are looking for is the following items to be exposed from the CDM Host interface: Somehow, back to a python binding. From what I could follow you initiate a platform challenge, which sends some data to the licensing server to be signed, and the CDM Host Interface executes the callback OnPlatformChallengeResponse with the signed data. I am not quite sure how this is invoked, was looking through Chromium source code to see, but it's a bit of a rabbit hole. Looking at ISA, it appears SendPlatformChallenge is a no-op function in the CdmAdapter. What do you think? This stuff is a bit layered, so it's not easy to understand I guess without working with it. I don't know if logging Encrypted Media Extension calls in Chrome would help, but there is a logger extension. I also forget the scenario where this came up, wasn't it that we need to sign some bits of data before the manifest? |
2da4eeb to
ba18914
Compare
|
i have updated the description on top with my updates, but SendPlatformChallenge seem used to send, not to get the challenge, ->User run video play but i do not know how to make this (if possible) |
OnPlatformChallengeResponse would return a signature of the platform challenge. I think this is the issue we had with the 540p on ARM, and when I ran mitm-proxy on RPi we found it sent back a payload with CDM platform data that Netflix required to playback 1080p. Do we have any reference what this data looks like? Because in the case of issue #655 I am pretty sure that payload was the platform challenge. And I think SendPlatformChallenge generates part of the payload, but the other part of input is a service_id and challenge which probably come from Netflix, and that message is sent to the Widevine CDM server for signing and returned via OnPlatformChallengeResponse the signed data, signature, and certificate, and sent back to Netflix which at that point they could verify the signature and the service_id/challenge data matches what they sent. I tried tracing through the DRM Interface, it's a rabbit hole that calls JNI-based code in Android called MediaDrm. You can read more about that at: |
|
Hmm, so I think I see what your saying. I was looking back at the payload captured with mitm, and it is the same payload/size of the ".challenge" file that ISA writes out to the profile folder. It's curious, how Android does this when the CDM interface doesn't seem to support it. The session in the CDM layer is initiated by CreateSessionAndRequest, and it bubbles back to OnSessionMessage to set the session id & challenge. In order for that function to fire (which is called from WV_CencSingleSampleDecrypter constructor) it requires pssh and key id, as mentioned in the ISA ticket. So I think it comes down to figuring out how Android does this, and how RPi4 / ChromeOS does this. I think we should see something in the EME Logger (https://developers.google.com/web/updates/2015/09/eme-logger), since as I understand it is Netflix player has to work through EME (Encrypted Media Extensions) to access the CDM layer. When I play a video, it seems like it does initiate multiple sessions through EME, so maybe if we understand what's going on there it might give a clue on how the CDM layer needs to be called in ISA. |
|
The challenge is generated by widevinecdm at some point after initialization and is captured in this callback here: |
|
@glennguy I noticed with ISA you offer an initial manifest fetch which afterwards CreateSessionAndGenerateRequest is called and at that point the session ID & challenge is available, so I am wondering if this should align to prefetch/manifest in Netflix. And then ISA offers inputstream.adaptive.manifest_update_parameter which could be a URL and I wonder if at this point you would call licensedManifest in Netlifx passing the established session id & challenge. What I don't understand is if the first chunk (video segment) is already started at this point. In other words, perhaps the first chunk is low res, but subsequent chunks would be 1080p with the updated manifest. @CastangaIT not sure if this would solve the problem, but it would seem to me for Android you can probably go directly to licensedManifest but on other platforms maybe it's 2-step process. I know on ARM devices the problem is if we don't have the challenge then the manifest will not report 1080p chunks. The basic idea is whether we can have ISA prefetch the manfiest to establish the session & challenge, and then immediately after request a manifest update passing the session & challenge and then parsing the manifest to start downloading & playing segments. |
|
@wagnerchthe do not take in account of the current "prefetch/manifest" we will use only "licensedManifest" type (the website not use anymore the old version except for some non-drm videos), |
@CastagnaIT agreed. So have you figured out on which platforms/videos require this new manifest request? I guess what I can do is, if it still works on the RPI4, is run the proxy (netflix-mitm-proxy) plus EME Logger and see what happens there, if that will be helpful. The reason I bring up this idea, even on RPi4 when I bring up a direct /watch/ url in the browser I can see 3 separate calls to GenerateSessionCall, with the same pssh and 3 different session id's as output. So I don't know if that is to deal with this problem, or it's prefetching previews, or what is happening there. There is also 3 MessageEvent, with 3 separate license-request message type (which is what we are calling "challenge" in the manifest request). |
|
Looks like netflix-mitm-proxy isn't working on Windows w/ Firefox (get a error when trying to play a video). But I do see it's using licensedManifest. |
|
Think I might have something. So Netflix actually pre-generates the pssh initialization data and embeds it in cadmium-player.js, so what they are doing is an EME generateRequest, pass the license data into the licensedManifest MSL call, and then generating the MPD and playing the video. So we would need something from ISA to pre-call CreateSessionAndGenerateRequest with our pre-generated pssh initialization data, and then generate the manifest and resume as normal. This is what it looks like in cadmium player, the c.prototype.tyb is deciding based on (r) passed into the promise resolve (which is an integer 0, 1, 2 that indicates the DRM type playready, widevine, etc), and returns the pre-generated initialization data used by generateRequest. The real bear is how the heck do you parse this out, is it static for everyone, or is this JS file dynamically generated for everyone? EDIT: Ycb is the one for widevine. Maybe searching for "AAAANHBzc2g", I think that portion is a fixed header. 00000000 00 00 00 34 70 73 73 68 00 00 00 00 ed ef 8b a9 |...4pssh........| |
|
https://www.w3.org/TR/eme-initdata-cenc/#common-system I think if I understand this we have to parse it from JS. Because there is at least one KID embedded in there. Perhaps we have to look for an RE "['[^']+']" and parse each B64 payload looking for pssh w/ SystemID for Widevine? |
|
Here is a kludgy routine to scavenge the pssh from cadmium-player: also, here is a Pssh box implementation in Python that can parse this binary data. https://github.com/google/shaka-packager/blob/master/packager/tools/pssh/pssh-box.py |
|
@wagnerch wow you have found many things looking at the format specifications for pssh seem that on ISA we have already one parser that can be copied and reused, here: |
Yeah, I was looking at this yesterday, so the basic call flow through ISA is: -> CInputStreamAdaptive::Open What needs to happen is WVDecrypter::OpenDRMSystem has to be moved earlier, to just after Session::GetSupportedDecrypterURN, I didn't fully flush out dependencies but I think that can be cleanly moved. But WVDecyrpter::OpenDRMSystem is what instantiates the CDM adapter for Widevine. The next problem is splitting apart or copying bits of WVDecrypter::CreateSingleSampleDecrypter && WV_CencSingleSampleDecrypter::WV_CencSingleSampleDecrypter. The constructor of WV_CencSingleSampleDecrypter would need to be changed and moved before adaptive::DASHTree::open, because adaptive::DASHTree::open is where the manifest callback URL is opened and parsed. But this part of the change would only occur if we pass in that initialization data. There is a lot of interconnect bits to look after, so I don't know how easy it is to change. But getting the additional list item property in is easy, it's the moving up of creating the session & request via CDM that is tricky. Based on the code it also does re-keying of the pssh. So I am guessing what should happen is we pass in the pssh, it is used for the initial CreateSessionAndGenerateRequest, and then it will call the callback manifest url passing the license data & session id as arguments to the GET, which we would embed in the licensedManifest convert to DASH MPD form which includes the pssh again (maybe different?), and then ISA would treat that as a re-key if the session is already created -- if it isn't already created then it would setup the session, and life goes on as normal. There are 4 or so major components in ISA:
|
|
i agree, i also suspect that it may be necessary to update with new pssh (of the converted manifest) |
|
i have tried to do some experiment with ISA, i have tried to use then i have converted the PSSH base 64 Last line should cointains the sections: KID_count, KID data (one or more), Size of Data |
|
@CastagnaIT My impression of this spec is it's for a specific system id ("common" system id). I don't know the details, but Widevine doesn't follow this specific spec document you referenced. Widevine's PSSH Box version is 0, it doesn't have Key ID's in this format. Instead you have to parse the PSSH data payload, and run that through a protobuf parser to get the result.
You can see that in action here: This is what I get: Here is the hack script I am using: And here is the compiled protobuf to Python, |
|
yes i had compiled the whole package shaka I was able to continue making changes to ISA and at first glance I managed to initialize the DRM session and get the session id and the challenge value to pass in the manifest proxy callback, seem without ripercussions to the playback but i will need to test on the ARM device to see if this changes really works to get the 1080P resolutions |
|
@wagnerch i am trying to add a new property to parse here: but the new property is not listed from |
|
solved found in the addon.xml on key |
ba18914 to
2eff0f1
Compare
|
after many hours of f##king building problems with ISA binary I will need to improve the changes on ISA before making a draft PR, I will also have to do tests on all other operative systems |
|
Is there any way to test this changes? My arm devices all dropped to playing 540p resolution limitation when before last week they all played 1080p without any problem. |
|
I'll try later, just a question, is it normal to ESN be just blank? I messed with it because it was, at first. |
Did some quick tests on my VIM3 and reinstalling widevine didn't work. Tried your new ISA and on the first reboot it disappeared. Reinstalled and rebooted and the first video plays always. The second throws the same error. I'll produce logs later tonight. |
|
@CastagnaIT I had debug enabled in NF addon but not in Kodi. Here is updated log: http://ix.io/3rGD ISA & NF from #1129 < ERROR The 4 different scenarios were provided as a frame of reference. |
|
Reinstallwidevine.log Now with latest widevine. It plays one time (not always) and then it stops playing. |
|
thanks for the report, |
|
Can you share some wip ISA that works partially @CastagnaIT ? |
|
@CastagnaIT for what it is worth: I can run tests and benchmarks on several ARM devices from SoC S905X to S905X3. |
|
ATM other tests are not needed |
|
Finally thanks to glennguy seem i have fixed the bug fixed files: ISA CoreELEC ARM: isa-linux-armv8-matrix-fixed.zip if yours feedback are good i will recompile fixed ISA for the others operative systems |
|
Just did a quick test with 4 videos and all played without problems at 1080p. Seems fine to me but will test more during the day. |
ebe3352 to
05a43a0
Compare
|
i have fixed another problem, these are all the definitive builds: inputstream.adaptive-coreelec-armv8-matrix.zip plugin.video.netflix_1.16.1+matrix.1_20210704.zip PS: On linux / coreelec / android remember to reboot the device after updated the addons mainly i need someone test of CoreELEC ARM device and Android (Widevine L1) with 4K support |
05a43a0 to
b7df2f4
Compare
|
I tried on CoreELEC nightly 10 times of play/stop and all good with 1080p. |
|
I tested thoroughly on SoC S905X & S905X3 (lowest and highest SoC supported by CE Matrix) running CoreELEC Matrix 19.2 RC2 The combination of NF and IS.A for CoreELEC Matrix:
works on both test devices. Here are screenshot and log from S905X3 device for your reference. |
|
I tried in the Firestick but the ISA version isn't compatible. |
|
@vascobraga41 i have add in the list android-armv7 zip version i hope this works |
|
@CastagnaIT: You don't have Kodi freezes anymore? |
|
@vpeter4 I didn't have time to do any more tests |
|
@CastagnaIT i can confirm that in firestick i get the videos in Dolby Vision, 4k, etc and also compared with the tv app and the resolutions match. So I think android is also solved. |
|
thank you perfect |
|
I can confirm. It works. Coreelec last nighthly. Well done. |
ATM is possible make the manifest request also without DRM data, then we take advantage to allow a soft transition
b7df2f4 to
1d61f42
Compare

Check if this PR fulfills these requirements:
Types of changes
Description
There are new changes to the video manifest request, that require DRM info of the current session, the problem is always the same we do not know if the DRM info will be mandatory to add, this could be a big problem for the future of this addon...
Required info to add to netflix manifeste request:
Android case
These changes can be done in "easy way" for Android system case thanks to Kodi DRM interfacebut currently is lack of a method to get the session ID.
[UPDATE] i have tried to add the support to get the session ID to Kodi interface (commit: CastagnaIT/xbmc@2ac2de1) but currently i have not tested need to build kodi android apk.
The only question is: the Kodi DRM interface provide a DRM session ID for crypting data, i suspect that it is different from the DRM session opened by ISA for video playback, this could be a problem? need testing (for HD content)All other systems (Windows/Linux/Mac)
How to get DRM session info on these platforms?1) Kodi provide a DRM interface but only for Android2) InputStreamAdaptive do not allow to provide any DRM info and seem that the DRM session is constructed only after the manifest callback (if i understand is inside Session::InitializeDRM() method https://github.com/xbmc/inputstream.adaptive/blob/Matrix/src/main.cpp#L2258)I have no idea on how to proceed, it is not easy situation (at least to me...i am not a widevine guru)we can hope that netflix not cut out the old manifest request way (that we use) in short
Currently netflix also accepts to not specify the session ID, but we do not know if this option will be removed in the future...
I don't think i will be able to solve this situation on my ownrequire changes to Kodi core and/or InputStreamAdaptive (opened Issue xbmc/inputstream.adaptive#666)I will try to do some experiments i can't say any more at the moment
UPDATE 28/06/2021:
based on the suggestions i was able to make the necessary changes to ISA follow PR: xbmc/inputstream.adaptive#725
Tests on my ARM device are running at 1080P with success
but is needed tests also on android devices with L3 and L1i can provide ISA binary to make tests on various platforms next days
all tests are ok!
In case of Feature change / Breaking change:
Describe the current behavior
Make the video manifest request as done until now could be obsolete in near future
Describe the new behavior
Make the video manifest request with DRM session info
Screenshots (if appropriate):