xbmc / inputstream.adaptive

kodi inputstream addon for several manifest types
Other
454 stars 242 forks source link

[Bug] ORF ON DRM Streams not working on Android Devices #1585

Open s0faking opened 4 months ago

s0faking commented 4 months ago

Describe the problem

The livestreams for the ORF On Addon cannot be played on Android devices (Tested on Nvidia Shield and Pixel 8 with GrapheneOS). The stream works flawless on Linux/Win

Possible fix

No response

Steps to reproduce

  1. Enable the "Timeshift" option for the ORF ON Addon
  2. Open "Livestream" and "ORF 2"

Alternatively use this in a strm file

#KODIPROP:inputstream=inputstream.adaptive
#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha
#KODIPROP:inputstream.adaptive.license_url=https://drm.ors.at/acquire-license/widevine
#KODIPROP:inputstream.adaptive.license_key=|Content-Type=application/octet-stream|R{SSM}|R
#KODIPROP:inputstream.adaptive.license_url_append=?BrandGuid=319f2ca9-0d0c-4e5b-bb70-72efae61dad7&userToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJraWQiOlsiKiJdLCJleHAiOjE3MjAwMTc4ODZ9.gcYTr_2cKlQYR-OH9Ca1C6DKKhrFsLbY_VVzetwZ2Bo
https://orf2-247.mdn.ors.at/orf/orf2/drmqxa-247/manifest.mpd?offset=5&begin=20240619T141239|user-agent=Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36

Debug log

drm_kodi.log

Stream manifest file(s)

manifest.txt

Additional info

The stream has a geolock so it might be hard to debug without an austrian ip. Let me know if I can help with any other logs/files/etc

Operating system(s)

Android

Operating system version(s)

Android 11|Android 14

InputStream Adaptive version(s)

21.4.9

Kodi version(s)

21.0.1

CastagnaIT commented 4 months ago

in the manifest url https://orf2-247.mdn.ors.at/orf/orf2/drmqxa-247/manifest.mpd?offset=5&begin=20240619T141239|user-agent=Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 you should avoid pipe injection since its not supported by ISAdaptive

you must set the user agent with the appropriate ISA properties see wiki DRM encrypted video stream example for license: https://github.com/xbmc/inputstream.adaptive/wiki/Integration and the manifest_headers and stream_headers props

after this if the situation is the same, from this

06-19 17:48:09.672  1083  1083 E WVCdm   : [policy_engine.cpp(57):CanDecryptContent] Provided content key is not in license: key_id = 8447520F829A46368344ABFDB257E896
06-19 17:48:09.672  1083  1083 E WVCdm   : Decrypt error in session sid21 during a sample with protected data: 5
06-19 17:48:09.672 25351  6533 E CryptoHalAidl: Failed on decrypt, error description:Status(-8, EX_SERVICE_SPECIFIC): '1: {"cdmError":5,"errorMessage":"Error decrypting data: requested key has not been loaded"}'
06-19 17:48:09.673 25351  6533 I CCodecBufferChannel: [c2.exynos.h264.decoder.secure#591] decrypt failed: result=-2001
06-19 17:48:09.673 25351  6533 W MediaCodec: Log queueSecureInputBuffer error: -2001
06-19 17:48:09.675 25351  6542 D CryptoHalAidl: framework logs size 14; plugin logs size 100
06-19 17:48:09.682 25351  6542 W System.err: android.media.MediaCodec$CryptoException: Error decrypting data: requested key has not been loaded: ERROR_DRM_NO_LICENSE

seem the server dont provide the key, maybe dont support android platform? i have no idea

s0faking commented 4 months ago

thanks for the quick reply. i tried it with the headers in place but still the same result on android. with chrome widevine (win/linux) it works either way

`#KODIPROP:inputstream=inputstream.adaptive

KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha

KODIPROP:inputstream.adaptive.license_url=https://drm.ors.at/acquire-license/widevine

KODIPROP:inputstream.adaptive.license_key=|Content-Type=application/octet-stream&User-Agent=Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36|R{SSM}|R

KODIPROP:inputstream.adaptive.license_url_append=?BrandGuid=319f2ca9-0d0c-4e5b-bb70-72efae61dad7&userToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJraWQiOlsiKiJdLCJleHAiOjE3MjAwMTc4ODZ9.gcYTr_2cKlQYR-OH9Ca1C6DKKhrFsLbY_VVzetwZ2Bo

KODIPROP:inputstream.adaptive.manifest_headers=User-Agent=Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36

KODIPROP:inputstream.adaptive.stream_headers=User-Agent=Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36

https://orf2-247.mdn.ors.at/orf/orf2/drmqxa-247/manifest.mpd`

the offical android app for ORF ON uses the same license server and manifest. i decompiled the apk and as far as i can tell the parameters are the same. the app uses exoplayer2, could there be a difference how exoplayer handles the drm stuff? afaik the hardware decoder handles the drm decoding on android, so there shouldn't be a difference, right?

CastagnaIT commented 4 months ago

the user agent use mozilla on android? usually on android there is a android device user agent

i think should better if you use a web proxy to debug the network while using the official app this could allow you to see how headers are set on http requests

could there be a difference how exoplayer handles the drm stuff?

exoplayer is much more complex and advanced than ISAdaptive and supports many things not supported here, its not so comparable

from my pov if there is no license key there is something wrong in how you configure the license request

s0faking commented 4 months ago

i tried that and appended the correct UA the official app is using but without any luck.

`#KODIPROP:inputstream=inputstream.adaptive

KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha

KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=319f2ca9-0d0c-4e5b-bb70-72efae61dad7&userToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJraWQiOlsiKiJdLCJleHAiOjE3MjAxNjc5MjJ9.9d9EfR3uEg1cZa5lI9R1MNVF-yMUKUwuejsotnw7VTw|Content-Type=application/octet-stream&User-Agent=ORF ON/6.0.2-mobile (Linux;Android 14) ExoPlayerLib/2.18.4|R{SSM}|

KODIPROP:inputstream.adaptive.manifest_headers=User-Agent=ORF ON/6.0.2-mobile (Linux;Android 14) ExoPlayerLib/2.18.4

KODIPROP:inputstream.adaptive.stream_headers=User-Agent=ORF ON/6.0.2-mobile (Linux;Android 14) ExoPlayerLib/2.18.4

https://orf2-247.mdn.ors.at/orf/orf2/drmqxa-247/manifest.mpd`

the app requests for license key are exactly the same except for the UA

Screenshot 2024-06-21 122944

shield.log

mtr81 commented 4 months ago

I noticed that there are different KIDs for adaptation sets/content types. In Windows ISA gets license for each one, but in Android only for first (in that case - for audio segments). Is this correct behavior?

s0faking commented 4 months ago

When i change the inputstream.adaptive config to audio only the audio plays fine. Could the different KIDs be the problem as @mtr81 pointed out? Here's a logfile when the audio plays

shield_audio.log

s0faking commented 4 months ago

i've tried to save a local copy of the manifest and modified it a bit. I've removed the first two adaptionsets (audio tracks) and tried to play it and the video plays fine (without audio of course). it also works vice versa, so when i only keep the first two adaption sets (audio tracks) the audio plays fine.

CastagnaIT commented 4 months ago

try to see if this test build works: https://jenkins.kodi.tv/blue/organizations/jenkins/xbmc%2Finputstream.adaptive/detail/PR-1587/1/artifacts if works please provide a new log (disable Curl debug logging that spam a lot the log)

mtr81 commented 4 months ago

First of all ver. 21.4.10 should be fixed because it crashes Kodi. Last line in log before crash: 2024-06-25 14:21:43.331 T:5412 debug <general>: AddOnLog: inputstream.adaptive: media::CdmAdapter::Initialize: CDM version: 4.10.2710.0 Kodi ver: 21.0 (21.0.0) Git:20240406-60c4500054 System: Windows NT x86 64-bit version 10.0 (0x0A00000B)

s0faking commented 4 months ago

mille grazie @CastagnaIT :) it works with this version. only tested the android build (on my nvidia shield) though so i can't verify the crash @mtr81 has reported right now. here's the log

shield_update.log

CastagnaIT commented 4 months ago

good! this confirm what i found theproblem is that on android we open only a single drm session shared for all keyid's, should be opened a drm session for each keyid so that drm will make a license request for each keyid (but i think it would be possible to avoid opening multiple sessions for the same keyid)

i found that one player do what explained above: https://players.castlabs.com/android/latest/docs/build/html/drm.html#multi-key-playbacks and provide also a setting to force a single drm session

explanations on how widevine works are quite fragmentary on the web and i know very little about it too but i think we should follow castlabs player way cc @glennguy

no idea about crashes i tested over windows/android with no problems, but there are too many use cases to test so idk atm

glennguy commented 4 months ago

I think we've flipped between single/multi a few times now. @matthuisman also knows about this.

Maybe it could be an advanced setting plus Kodi prop for overriding?

CastagnaIT commented 4 months ago

what the reason behind to have reverted to one session?

EDIT: ok i found the PR #1165

matthuisman commented 4 months ago

Is the fix to remember which keys have session.

Return false the first time a key is requested, and then return true next time called for that key?

Multiple sessions but only single session per key?

On Wed, 26 Jun 2024, 23:20 Stefano Gottardo, @.***> wrote:

what the reason behind to have reverted to one session?

— Reply to this email directly, view it on GitHub https://github.com/xbmc/inputstream.adaptive/issues/1585#issuecomment-2191447835, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABPQAKPML3HYBZKGUCINWS3ZJKPXXAVCNFSM6AAAAABJSLV5FGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCOJRGQ2DOOBTGU . You are receiving this because you were mentioned.Message ID: @.***>

matthuisman commented 4 months ago

(or that logic the other way around , but you get the point)

matthuisman commented 4 months ago

Id be keen to try multiple sessions again either way. Pretty sure it fixes some audio issues as well (maybe that guys Disney+ 5.1 audio issues)

If it could be disabled for a Kodi property (or enabled) that would be handy for any add-ons that don't like it

glennguy commented 4 months ago

Ideally getting just separate audio/video sessions will be enough, and this loop ensures that we don't keep going back for keys that we already have (often license requests will return multiple keys): https://github.com/xbmc/inputstream.adaptive/blob/d7159ecfe1e3238bcff9b20c73ee61cc17df77e6/src/Session.cpp#L485-L500

CastagnaIT commented 4 months ago

Ideally getting just separate audio/video sessions will be enough, and this loop ensures that we don't keep going back for keys that we already have (often license requests will return multiple keys):

yes but HasLicenseKey method on android return fake value its needed find a way to solve it

i agree a kodi property its needed for sure

s0faking commented 2 months ago

any progress on this issue?

CastagnaIT commented 2 months ago

its required some changes on decrypters and im already working to rework part of decrypters session code, that can solve also this problem, but its a big task that will require not weeks but months, depends how much will be delayed my works

it could be possible add a kind of workaround with a specific property but even doing this, means spending time on implementation/releasing/documentation affected addons must apply the changes and make new releases, all this for a temporary solution that at the end more likely will be removed

so from my part i will not work on this until the code rework