diff --git a/1.- BLIM.cmd b/1.- BLIM.cmd
new file mode 100644
index 0000000..574a68a
--- /dev/null
+++ b/1.- BLIM.cmd
@@ -0,0 +1,4 @@
+python bad37.py --url https://www.blim.com/asset/10199 -c playready -s 7 -e 9
+python bad37.py --url https://www.blim.com/asset/24336 -c playready -s 7 -e 8
+python bad37.py --url https://www.blim.com/asset/24336 -c playready -s 7 -e 9
+pause
\ No newline at end of file
diff --git a/2.- HBO.cmd b/2.- HBO.cmd
new file mode 100644
index 0000000..6f052bf
--- /dev/null
+++ b/2.- HBO.cmd
@@ -0,0 +1,2 @@
+python bad37.py --url https://play.hbomax.com/page/urn:hbo:page:GYSAr8wiBN8IqpAEAAAAE:type:series --alang es-la en --slang en en-sdh es-la es-la-sdh --flang es-la-forced
+pause
\ No newline at end of file
diff --git a/KEYS/HBOMAX.txt b/KEYS/HBOMAX.txt
new file mode 100644
index 0000000..1a9a3f3
--- /dev/null
+++ b/KEYS/HBOMAX.txt
@@ -0,0 +1,542 @@
+##### One KEY per line. #####
+Sex and the City S01E01 - Sex and the City
+010077f9feb0ab3feaa14533fad3db02:4680777ac43b9698b7ab0ab7e8dc215d
+01051810dad40547af6417cd3923ad15:ffa4387c9044429d58c7173824e448e1
+0102a3562b2a4ca6f558e75d9e2e5a69:44742f93fa531725d1058900aa07cb5e
+01018b9daf7dbcacdd3ed46c0a200375:d0bd3272ad478ee9d7c2dccd68ad73fc
+MulherMaravilha 1984 (2020)
+01004200311580d98790817b5e4bba85:f36e16ff4a972e47404ca57ffa4419f7
+010518ff7f06ac32c4600a4c3d58f47e:8331bb0fa3c544b5d7c5bb7c34f5a589
+010191111658e773667a025a991f4d8a:68f8ffaa759b0a2f76ab9f298ec91a3a
+01039abe393e5a2c7fb219d2cb4709d7:2c4f6c7cf29e844145a4dd41fd612d64
+Game of Thrones S01E01 - Winter Is Coming
+0100e34e7b880c7b9dde35f77c4bc1cb:593bf887f900ebfd6fea887fe4500ce4
+01055f0f6ff8175cf7722cdfa2b74d7f:5da0b5ebf4fe112aa0e567cd42f9a164
+010274d4c60b0c31d6f886c1f4f3e9ac:96087cbd0f95970ce414bac741b66fcd
+0101c9735891941ecf7a306ca73727fe:f4a6f54a423f19e4954d5163f83acc48
+Game of Thrones S01E01 - Winter Is Coming
+0100e34e7b880c7b9dde35f77c4bc1cb:593bf887f900ebfd6fea887fe4500ce4
+01055f0f6ff8175cf7722cdfa2b74d7f:5da0b5ebf4fe112aa0e567cd42f9a164
+010274d4c60b0c31d6f886c1f4f3e9ac:96087cbd0f95970ce414bac741b66fcd
+0101c9735891941ecf7a306ca73727fe:f4a6f54a423f19e4954d5163f83acc48
+MulherMaravilha 1984 (2020)
+01004200311580d98790817b5e4bba85:f36e16ff4a972e47404ca57ffa4419f7
+010518ff7f06ac32c4600a4c3d58f47e:8331bb0fa3c544b5d7c5bb7c34f5a589
+010191111658e773667a025a991f4d8a:68f8ffaa759b0a2f76ab9f298ec91a3a
+01039abe393e5a2c7fb219d2cb4709d7:2c4f6c7cf29e844145a4dd41fd612d64
+MulherMaravilha 1984 (2020)
+01004200311580d98790817b5e4bba85:f36e16ff4a972e47404ca57ffa4419f7
+010518ff7f06ac32c4600a4c3d58f47e:8331bb0fa3c544b5d7c5bb7c34f5a589
+010191111658e773667a025a991f4d8a:68f8ffaa759b0a2f76ab9f298ec91a3a
+01039abe393e5a2c7fb219d2cb4709d7:2c4f6c7cf29e844145a4dd41fd612d64
+Fatale (2020)
+0100100f83ba50be7f20cbe8095b422c:55dd470924f512b407ce2672c6751d9a
+0105068f5057fe88847899662ecf452d:0a0bdb3381f733fca1ce94ef3be74a2f
+010173ef657a0ecf2db35888f3b890cf:144877fc1cc4029711691e3dc002d262
+Fatale (2020)
+0100100f83ba50be7f20cbe8095b422c:55dd470924f512b407ce2672c6751d9a
+0105068f5057fe88847899662ecf452d:0a0bdb3381f733fca1ce94ef3be74a2f
+010173ef657a0ecf2db35888f3b890cf:144877fc1cc4029711691e3dc002d262
+Young Rock S01E01 - Mantendo o Personagem
+0100ddf2bc8a779a1f09c368c7eca060:e3fb2ac8d1d1fa1e11e0218593f93450
+01056abbb53e5805462797aeca5568bf:35edf555765b230b1e9d7a9658d0933e
+0102c666058817aa543b63d1adfa904e:d1daa5eb5d51893aa6f9e9080800b136
+010193bbf7085e54cb9d573392abd865:9516e1c184cc999e64146e097b9bcab3
+Young Rock S01E02 - Na Estrada Novamente
+010054d60dcaeb448e0c5b3b49059a46:1f7c10dc5271f1a9c46c778c7657fbe9
+0105af2e162b824e925309c3260b5ada:0c17e76e4df2153bb39f004c28b1d5ad
+0102395832e1996319c8e03e3f63f0e7:261dc43e10427363a792e29ea72e47f2
+01015b51902146490c49e0faa2c8f5e1:fc53613bec2f69a2f4863665ff4b741e
+Young Rock S01E03 - Para a Frente Juntos
+01009d1877cfecb8779ef756af54f261:41ddba734a634ea37d9b892ae35aef3f
+01056412baea7fcd45997fdfc8771469:965d3890435d8c40e557ab5d8d49f27d
+01025e81393bb17ff3a3489fc50c7c46:053031f07db98f55187671c7cc16dfaf
+010115fd9ecf07c2e3a285dd33bca839:276eec8ce47e55586df5c781de9848e6
+Young Rock S01E04 - Cuide da Mente
+010007a3b2ebc6199cf73b41268aeb9a:5172f924aeb1877d90b6278349122a4c
+0105fc4abfd949f28fe016e9ae7d4705:771c1eccd020d940e2cb84075d242f8e
+01020d726386ce862f39738cdf54f6e0:5bcac6d1c1d5ae01573729c2f808cc42
+0101022b2d8f78a467289d744dd353b9:1ba2b246cda4daf91e22a0939f4a834c
+Young Rock S01E05 - Nao Parta Meu Coracao
+01008831029c6986c24f628cf885bdd4:a4d32c771e739fcb6d17e180d5c68080
+01058e6f1a11719c9aff718b10f72908:666b8a60b9651836c7d4787e9076e6cf
+01028536b69cd182d50a48750c1de6a8:6e63166da194d1136a4d70ed05606b41
+010161db8c5f7cefb1e577cc203165f5:3cbde197496a08230b8b5600cceb40ea
+Young Rock S01E06 - Meu Dia com Andre
+01006934cd9d4691f1dac14d1588efed:d89cfd9560fdb02dfee41b1aa5623bae
+0105681340b87f63875ed5afd9a0e458:ea4579a55ec782bf66e1727cb191ac86
+010240c33b9dd9053f77c44abc27b5d6:6238bc382509068fdc0833420cb34837
+01011e8893da248109987ac7c91b7b7d:eb07db5dde37d5653b6bf738f84c5a34
+Young Rock S01E07 - Johnson & Hopkins
+01001147f7ddd528c77cd170638d587d:42afcdaaf53b96d9dd1e4bd2b04b1e1e
+0105e3c0aec6474fca13d6802af9da30:462347dbfc08a64b4d92a8cff5f55e1f
+0102e7fb80d82e6cfbf2120b2d4eba31:2d7c93942bcc0b948046bbab3674473b
+0101b04ea21a8f9bfddb60d36d2b13b9:36a721f0dbd971913fe1b3d9125d5645
+Young Rock S01E08 - Meu Amor So Bebe do Bom
+01000a6d4324864de7e290de76c1c067:7f9f618043e3e6cfb03716366f1701ea
+01051631670ae66add688e3d06ecf1ed:19833d7a112bda41f308f830138386de
+0102dfb48a5c39b890a78273f4f38d89:7e7788797f6085409b73cba34db9beff
+0101f7462056c8453965361c27512236:ab27725060282d191763446df2bf735d
+Young Rock S01E09 - Uma Moca Chamada Star Search
+0100bec4cca40cd831dea8f8562543bf:cdb4be6be45890a2eaaed1b8b65d1fac
+01053e113d278ce468b8a73d68aba62a:134a0f7242f9b334c036c2c4e4a01e55
+01021b615ea10a68711529293255eeae:8f4358e37f160d291e51e8498ca0b3aa
+010121855d16b95c99be619cb4191a69:a23ebe421ef522f7fcef557989e17b7c
+Young Rock S01E10 - Bom X Otimo
+01003074cab5dba7a5d6f9941adadd22:56ca1b6eb1c12d806082d6e7926d26ea
+0105830951b04527ec8addf62adecc58:08fe9afc6df88a9589b5affeef461bf1
+0102d84a6e425c9d9043f9ec3132fdcf:3ecad14b703a0e79204dc046b2cffb4c
+0101cd0beb4e6daf0046655564d3758d:98f0b583564e05ab1d4567a1f836d248
+Young Rock S01E11 - Dia da Eleicao
+01000b3f384a6c956873de8c0c009660:b21b2586f7ae3c90945d776387c52e10
+010546ef4e8ffb90ec97cf5bd64645e0:4f440e174ef3bbc21e39cd2de0201563
+01026dcd7e1fe32bdf8444e1fa3eba59:d96172bb34c4b8b7ec95a52fc4978617
+0101b932547501a932fac39db1295730:640e397bcf3be27ee2b8cee05d7e3790
+Trem Infinito S01E01 - O Vagao Quadriculado
+0100a77dce692561487a5005f7575347:57b156f46b561b4def470eee03b13c5e
+0105547b931ba9da5d9ab6a8fdbfd889:3a6748fc91f05df721106b23d25e0329
+010202a90117e06472004dbc8a80103a:14c7e92589036df2dd44ca95e2519c60
+0101ec922d17a4ad84ca1bb7799f2ae5:9faf3568d138ce4432da19a09b6c86f1
+Trem Infinito S01E02 - O Vagao Da Praia
+0100f31da89cc5012fabe99622f791b6:e272cf736d9d15d5ef5920052dad7283
+0105bfc3f6d641726800af1885de4788:d2738c8b11bd0600cb7f09914d2b6ace
+0102bff9aa6d56cb536145488ce8f50f:73c53f333ef7b588953e5bcfae1320ae
+010117c7b84f8219057dcfd54a9a1225:bb6a7315adc4904daf7acbef2aa22e81
+Trem Infinito S01E03 - O Vagao Dos Corgis
+010017051096026c8b6f5392c21348fa:0ae10a3c856d925d0afe0cb2e695ad14
+0105e8680f697fa79cd9cdd11041fb54:577235ff95e21fcfe54943a82488b0f2
+01025dd8b75ebbb2cc7d8607d8f37391:17630cb656ae82646fb99df8a4ef1ebf
+01016a60ee89ff2797a08a492ddb701c:b25106fc8cd73268c7eeddf7fbd4983e
+Trem Infinito S01E04 - O Vagao De Cristal
+0100353052bae99ce777975a7ed8d154:50d3a6169f5c6bcf08771a805360dd83
+0105cf66d19e66efd2fc13179d826309:ff5d674d1af75240bfffe08b7a75e7dc
+010225fdbcac74d1cc0a00b735a5eaff:e03454aea5f613b846f4f6ce7b74c0ba
+0101c3c577164f0ff324ff45abe9d361:2c31beb7f600b2a92bedd789db906833
+Trem Infinito S01E05 - O Vagao Da Gata
+01008a2a43298ea495606c95ecbcf051:269c70959604d6732ab9015e673a6394
+010525204496216c89154119f1a296fa:cb9983c0480616b7cbbe935cb8d0e6e5
+0102deaa3e89a1e494f8337de127c30f:86feec4fe39392186d8b57c63d8fc57f
+01014b794bb65176fc3653ca830e74e6:3467d4bdb231cf3aaab4543e3b48e1f8
+Trem Infinito S01E06 - O Vagao Inacabado
+01000226c535f9b8b32102d7d385508a:fbaf4aba3cb5f83f5426fdc62cbbe333
+01056221bc8de2e19d3884aa8a910f11:9d20db6955d7eec5712f013e8d412e1f
+0102caa64ecb830002e7387bb2e62849:d5a5c77e2d547f3b0b993db3c079e899
+01016197bd7508424e470fc783490f25:5ceabff47db742c0f93d7946657f5787
+Trem Infinito S01E07 - O Vagao Cromado
+01005be6bdcd2f9854ae56e1a089d3ce:9ef241bd6b028b55e43da5690c92a34b
+010543c09f148951a86d4e6ed8af6ddd:fee9fd1c396e9e5d95c0394d308460d8
+01025b588cb1c2ca1ba60b398fc88b32:5d36ea74b93f1f56268176c4553653cc
+01016c002ff53ca43c3261086abbc1c1:645a42f7debd2c214ca7b7a49f7410bf
+Trem Infinito S01E08 - O Vagao Da Piscina De Bolinha
+01003b7bcc03d8b69e5baad3031c70ff:9228dd4a52fe088cc49659a09ce0d4b6
+01055eceb5e2d3710422ccc34c312e90:a4563d84c953d524ce3518ce30e73545
+010264903a38e874b827e568ec124651:104d1fbe42ae1ff2aa1d04c00da9c997
+01019456ff260170b4f015ea9da9d784:58a2deb06f144ed9811eabb7a653209d
+Trem Infinito S01E09 - O Vagao Do Passado
+0100db06533c68827d006f368f208736:2ec9b461f67ae4dc3c8c46cda7b20f4e
+0105fe417480ddbb404a2d95980880c6:06d1048a8d1b886d60adbae283d84cc2
+0102b6dc723d382dc21d1cd12a8ba60e:eed57ae5479ab01ba9c7e35d52a2814b
+0101d5defb3393e8abc0b0362e857946:1696c981048bec66da4b0d371b56b580
+Trem Infinito S01E10 - O Motor
+01006a7ac2b6dea3b0bb3974524e1f0a:1ce438bc6c63e3abccf414709a6f90f5
+0105e4d74df83d7bf31b294eb40ee8d5:b46f4c476d627b29ce811b45970ba158
+010259058d0738265a135144a4294975:86c5a4bdac322a1de44245f72e5f5676
+010141c5681e02b71a975a23fe6d7987:e18c666c0803946c2b048a6f86574e28
+Trem Infinito S02E01 - O Vagao Do Mercado Paralelo
+01002dfa703eeaa6cb5e5ae5093d94c7:c2b3954c3fc65692d89d961cb42bbf12
+0105a1165f4c0124fb76e121d2144638:2d42412c29fad222d366166298eb007f
+01029c9174ed36d7b6b72c389a3644a5:4d8769cf9e6a459701513d1945fb2e5b
+01011dcd22e68d659c2d23f276096fd2:21865df21586af74d729b0483aecb657
+Trem Infinito S02E02 - O Vagao Da Arvore Genealogica
+01002d58928076e7dea3900272147e79:0e39a701d95a378c9de92e7337463ebf
+010535472acdf450593a023515944584:865210e56cd0908059ea248a738112d6
+010262b79da0386cb678214505bb6873:d58bd63f5cf80cdd745abe185aea4b0d
+010102183d0dfbc01afa52892a0550f8:cdd3250250e140922c9299da953d5907
+Trem Infinito S02E03 - O Vagao Do Mapa
+01004aeaaeb8bce805287772a47edb12:efdb877fbe4db39c5dbb4a51654794ad
+0105a9b3efb90ea678a89aa75f34175f:78e807073c54fa54730d23d58c170bba
+0102c8f406595c39afe8299f09c1b12c:5f10994e8555257bd508dfe9f92ce5c9
+01011a42102c2e0c31a93ab911798c59:39e05b417eca455c93f070908948b3f0
+Trem Infinito S02E04 - O Vagao Do Sapo
+010021d75117232c1531b24c18c3122d:61c0b08791d579d6f097d149c1b0f98b
+0105c6fe22256997a0158b97e2edf65f:f572dc2f62f0b909c48fb35a5decdfd8
+0102bc953b2b207b48682c6a86b9cf69:2017e4aa3045f4e49917d73dea36040f
+0101e4542963aee71ba634c47e4e3ad2:d0ac221842b618756c19336a65c70bdb
+Trem Infinito S02E05 - O Vagao Do Parasita
+0100c5fa4542136889e6ced9d66e111a:4481fb0cb48a9d1b55d943c0616c21ba
+010501421ebf739079fba48102efd643:625fee92af72edbf0e8e30db0c647318
+010282fa32ba05153dd193d313257690:d7dc5686161142a65776d281db2ab489
+0101630bb5df9827a68c5f937120514e:96094bf48358db542bcfcb36fa49646a
+Trem Infinito S02E06 - O Vagao Da Gata Da Sorte
+0100777b4c0c4c60cdf58293db9ff60f:aca59bdbaeb29a3a9e026cbe91de5d66
+01053823d2474187ce998a4649b98c6a:9b3c97891ec0562429a408525e908e3f
+010283f3d55bdcdb99a066c62187f93b:be20d5d05bda12aefc7ad462db603098
+0101f39695f770603e7cd7233e718fff:305073711a17feccc2c3e2675fdead2b
+Trem Infinito S02E07 - O Vagao Do Shopping
+0100eebb18bda31f550616a663d70411:9a88c41b1e6154e419c71db608a04e53
+010565dc99b5a55c94af10a2f658d966:db26db5151d6c72c514038f37593503d
+0102f0656816f9d96ca7d9cf561b7720:8389365e462ab1e76bbac4349b57324f
+010186d41936f14c983a1a5781fbfe4e:14cc38f2c63f8cc104cfa64bd887deae
+Trem Infinito S02E08 - O Terreno Baldio
+01002cbbb07c5f0a59bb03fb1b5f2634:f2ec5c57801b81805a949b943e9f899e
+01056718328b80acc408b3910e4c632d:79ffc596e2f2c33add5dff53f57c7a8d
+01026c0d04247377689ec90fc46ba9cd:c307b0503666cc2b7e6374d90df9fd92
+0101896f0d5c7e8bf8240b9fca4aee8b:fa2d0fe28aadaea36774389d95a47e1e
+Trem Infinito S02E09 - O Vagao Da Fita
+0100ee249145422c84529aa22c15a851:789cb1df47813973702d683a0ceef6eb
+0105f6ba2fbe04c0dfc5e679b8fa9ce7:0727567596ee8c592e620c6404bf1bbf
+0102ea29eee03937b5a41acb01ed5f85:1a4ec821f2c6498ef9c2825eff5b01a2
+010184aa9fe7bb861e9db755d1a43dea:a0822e2bd15a90f6b7bdbdd18777ddd4
+Trem Infinito S02E10 - O Vagao Do Numero
+01008dcd958a85c59a205f8447b27b51:4551fc782cb6fdc2b99786c157c8ec0d
+01056532383cc4e8ffa067475a777c31:3b233156f07b72c99b2df3be3a96ac38
+010248b15295de961488e53707f8032e:42cf3ac0207b9bfff3f604a55411d6ac
+01017a526e4dbeef40ef0d0e68ba29db:4deae4f4aa8300ce26e7f1cda2c016f6
+Fahrenheit 451 (2018)
+0100189566132b2da3d324d04e84d757:1f38f71f9edbe5d0242c6205d64dd4c8
+0105067bd0dc8bd67598b206e0ac78c6:27a97050e2c22de05d61791d6d022943
+010277d957a83acb82845914bd603bf5:28aa523197bb9c44c989bd285d2b623e
+0101c3a540d39664f59cc44006be6fab:8fe6dcdbb11158344f66acccf178892b
+Roswell New Mexico S01E01 - Pilot
+010009f9459677f87e91d91dfec31221:7a6a0b3f555dbfbb14690454ae1d6dda
+0105a7bdb64bc304a4c5c0e4220c1c85:b3bf946609894e3143164b4f29a3ac2c
+0102c99421c06470517caa1b2d8500b8:8841f7ec433dc436cb83b1cabbf94cf4
+010105371ec1c248d4f7347a92327330:5d3b50f6537f990e4ad15064fb042989
+Roswell New Mexico S01E02 - So Much For The Afterglow
+0100c202620f26048584caa2790c67f6:99231c27dbc6958cbce31243de701a51
+0105091941943a3576a829da07d60f54:eac89d7b0edc8096fbf70f73999b4600
+010295b284ed83de4b5db7d7e767808d:f2094c7f0aa86b30206e4731be4b4032
+0101c6d44427b80c5feb165286a2f384:7fc62481b1e0977b64824c5aa826cd7b
+Roswell New Mexico S01E03 - Tearin Up My Heart
+0100732c14dcac70132458695a826dc7:61a36d4fcfd520143264f00853e9d066
+01050520af2782e19014630b1af9dfd7:4e824715a431bf47a0dfcd0f8413cde0
+01024fbdbdc97ffe5b38635540abfaa3:c800360caca6e40bd5ab4b4bf6aa2251
+0101d5c7a1d21b0f94d853a80b47ce19:b16dba1bd2df03cef6677b3445eafaac
+Roswell New Mexico S01E04 - Where Have All The Cowboys Gone
+0100cee62e1961f807c4795c926657a0:f0ad552ea5081fe544e21ee39c895d7d
+010510a3efc687d07301794678dd3b8a:f719c0f1f1d6728f15f82b710e8dd188
+01029279f9c0c0f142c8b3d8129c66d8:b33c26bd3c5fa2c50c513dfe9a42a852
+01015f70674d18165d8244f996123849:67936765750aa5b0855611de7d360e9c
+Roswell New Mexico S01E05 - Dont Speak
+01009721246d2a52b6160b6f9e42fdb4:28aca89cafc55bd9ee739069b6a4b1d2
+01053286f3c8c35291605cdc2710e153:713c08c3b78bbc39dac51c0dae89a5b9
+0102d51ff0130b48b9e065e00db828dd:0872228085548c2f9a293d5ff47f6c73
+0101a1c965f2662ebc1f399a7bb5b333:c7bd6b01746b9579f6a552a8e5dd4f8a
+Batwoman S01E01 - Pilot
+0100390773530bf551cfae7f6c8ee52d:186ea907c5c0de6038cc742c9fcd3a44
+01052bbc9724dc441ce3d984bf56432a:47755fddfe9f998aa284bc888a15dd3c
+0102ccf2dae2f4d80f8816fc3beff750:132f2f07be39786b01f4df0fe69863bc
+010127ffab8a64c8ffb3960388dbb505:894aab24f219a9abcd0911c912aeedd3
+Batwoman S01E02 - The Rabbit Hole
+0100804fbc7b6f49261c9a508d7baef8:d8026406cc8cb742ba811a10dc14435d
+0105cfb4c89bb5e75c0d1572dd5f4aab:1219ec71cbdc695cbaf7ea6192bc6c5b
+0102738070d60901250e0c4f534597a8:a8bbf3dde2a424b7a495c37868bf0d82
+0101f11b648c20a22985fdfb237184da:987e687746d81dc8f1e8fd533976c237
+Batwoman S01E03 - Down Down Down
+01001ef87f6933c2526d88da2066ceea:ff92bf6e210dac502a36f69f561bc339
+01051581acf80d10802b57e01c13334a:0e54706121b12aeaf7da634befbfc20f
+0102002b3307ed4720978bfa95217c59:bdd60deb40bc130141d24693b7275f7b
+0101977f3a31d0a594728b47637d994b:4545d72c7fd25d725f8c804925dea370
+Batwoman S01E04 - Who Are You
+0100249e976bca0d47f4355599227440:eacd7c594dd1e14439b4a2a316b9b3b8
+010532d3833836b5c8c22fdc92aa744b:d4ac953baff4587470b97e1db1b477e3
+01024b61a179615d2a98cd272f9fc7f3:333a5197f1ccc33d277e89d90919515a
+01013e95d9feaa9e3d57e0a1339e003e:f9c89721192c53b48a13ebbe953c8943
+Batwoman S01E05 - Mine Is a Long and Sad Tale
+0100a0e4aebe8d034cbbf28f2a8179f9:0fb674861e64570ebc6eec9ce32280cf
+0105f44247ffa9b64002eff95af28c73:53bf76187a190337ad17767a4e698db2
+0102bcb91c6cff38cab1e465d9630ccb:2354d918be9e715906f12dad6903123b
+01017a016043b17c55fa43b2c5c18f3e:2968f774c80e64a3c13bea2056e75f51
+Los Nobles Quando os Ricos Quebram a Cara (2013)
+01000de616bcbccf4eb5600fb90ac44e:5d950c00ddc4c20b3e00d95e0e3a5079
+010583bbff43327262f4f2eb6e833c64:8ddf8340464b7a21c38383f4bf11ab74
+01023ec68c3630fd49a3dfe4603f9b45:f9da1c37e95e0977fcbb3b050d91cb1b
+01016ba7aab5f1f5e7dbefb6bbc5f50f:2eadf2c51e1fd012fab77c6ade66ea02
+Academia de Vampiros O Beijo das Sombras (2014)
+0100bbde78dacd6a020c71194a37ab69:28b79e31b93ffb2169b2df43b7273936
+01058880ae67aded89986d9b3fd791b8:4c290e959d61881e870d43be24114ff6
+01027cfd8a17e5ce73838197c9ade68d:11216a23f9eeb2656552a46a5f075830
+01018037f262cb1a342786b186debfe8:010353bfefc7f4137c52ae145c2a210a
+Constantine (2005)
+0100a28fc8e0342fa86e9069c71d38cf:c56618c167dab5c70394266af0fe1620
+0105cbc8989234e5aaff9d526152b0a1:bda3bb5e4f5258198dc81335d5f9cda2
+01019ad2190d5dc33d03abac524a18cd:7645205622d965e678cc215b7e95f89d
+V De Vinganca (2006)
+010096cb1ee693ccb48bd8bc490e9751:b96c4609105c2cef2f905a41906f1877
+0105520057217819b40d1936bc713ebf:76587f94092cdbde301ba0ebd81d5848
+01010666fe412705fa771636f89c0fc8:2dafcf73e2c62eeacd0f6df443d40327
+Roswell New Mexico S01E01 - Pilot
+010009f9459677f87e91d91dfec31221:7a6a0b3f555dbfbb14690454ae1d6dda
+0105a7bdb64bc304a4c5c0e4220c1c85:b3bf946609894e3143164b4f29a3ac2c
+0102c99421c06470517caa1b2d8500b8:8841f7ec433dc436cb83b1cabbf94cf4
+010105371ec1c248d4f7347a92327330:5d3b50f6537f990e4ad15064fb042989
+Roswell New Mexico S01E06 - Smells Like Teen Spirit
+010034443f4e7bc81b5a406b3a4b5163:926f97e2d93584efa27041fec0f549d1
+0105a746eaf16eaab8df5c4308a5d63b:0412fa441d6f1cd44ca92ea014f07a11
+0102323a46e8b950b01b534a43a3fbc5:fc8d9449d0fa3bb19a952443f6ce70fd
+0101379f3ee6ceffbf11323803a81176:cca7ead90ee511ef0e38c2b59017804a
+Roswell New Mexico S01E07 - I Saw The Sign
+01007d4a6ea40d8c5be14b4cb37fa60a:94e005d1b0f02254f18cc8b3f6dcdb69
+0105b60a05f571c44553320aecbbae19:59ec4a87cba2fc2df042486c4e1501c9
+01020524d0e5a38ef18932e46d365969:eb71d5e0d4ce5667bc795e8e819e1330
+0101b918f70f4b6faa9f2f398d22f00d:e6e8bead456741b747e720bd57b9d6da
+Roswell New Mexico S01E08 - Barely Breathing
+0100782e5f39937f061d233438013591:9a65b3b177ba184180068511fa234174
+010564ea37554c7432227b31d2b8e405:04ef7d92f2c7c0fa3020f5763827e2b7
+0102002f74ffa263d7c9fc24e9774896:5fa1647d6dab73d65508b9bca11726be
+010161303ce5b78c279f02846f2f4805:eeccb06b757604d50ad7c7c7fa58b4f8
+Roswell New Mexico S01E09 - Songs About Texas
+0100b9738d03173c982180911b0b8950:387282e8cccd4955baa5d28166e84065
+0105612a51be75d205e5081c26a31898:77134361436e3d6759e856d249d6c173
+0102664f8ef4015db568a7dade8b9957:3b934aafcb07bc45ba1c6539f43e80fd
+010103e49729c908b66086f1482ed1d2:1b72c8fda103607a20e8bf033588bbc8
+Roswell New Mexico S01E10 - I Dont Want To Miss A Thing
+0100a2e059ca2ad0c9e97b3434ecaba0:aaa4a9285197d54b3889eea9bec4eb39
+01055c61e9b0afe4c4acb6e57feef77b:f8468d15eb82088ad0a927eaf19b1f2c
+0102e5094f19e36fbdf79ebdd064b905:0e3b9badc03ec540c63e894c46cbc7ab
+01019f2d0cae2be25cc2e7aa3a6b7c30:b5e0b5d687677a8706cd25ddcdab8840
+Roswell New Mexico S01E11 - Champagne Supernova
+01005b94358a875f8d6617779bec40ac:ad37e726fac17480cb4a85a34046c752
+010523fb3e0e2bce86427b3a39738f96:4a49ad96a833ddb32d6ce863ea5e3300
+01029b07ecbcff2ffdd601a7f21e0594:5e020da6eb0b3787292e4fca71b638da
+01011dbaddf66721ec26e83de8fc5a9a:dceebce554e274dd2f8f3db354e37997
+Roswell New Mexico S01E12 - Creep
+0100cac8353d3c6787e054c2b488f2af:ba47001f333895161ecb15710228ec48
+0105800191f10bf4804198709e825e78:9992fb4023ac7c3232fea229eadb7247
+01029c8b7bbccc661a00965e5c3f9825:3bf0049865751ea48ade9b3d12512f2e
+0101516d7b235ddcd0f6f09df2c9386f:fd7e04d4a74540213b98a072c671a4c1
+Roswell New Mexico S01E13 - Recovering the Satellites
+0100f2351021ae7dd608b4cb49d89174:c8de71653719fb128a11f55384bcfc55
+010593faace129e34978202ed76f40a2:056130c72c5cbfa8861d6429c8e9ad3b
+010245a904a8da7ae2e0dcaca3eada0e:867df482bc59b05edc184d7dc8230e64
+0101a5cfc82dee23ccb5f755690d02e7:37b8160904d675fed201ce6f28d9e58a
+Roswell New Mexico S02E01 - Stay I Missed You
+010055e93ba1d37f640ff15831420cb4:f1ffba9635c9ba8736e74d11664f3861
+010583d603a8ecc72c4ae5cd0b8df6d3:e8c9da174ea524f1d21e79170064c23c
+010282ca77c5c6e9706850c5f9c4a935:33f5f604a36af1340a6c37ae0039c39a
+0101042ea1a5c2ff8a01b865d468e29e:3a17fb9ef920f2dcb97c55791ba2ff54
+Roswell New Mexico S02E02 - Ladies and Gentlemen We Are Floating in Space
+010000ac254ee1626d6784b34792b67e:5adecbefeb06305e2159d0227519b875
+0105bfa934bbf4977bce5ebb3e06e06c:1c693045499ace70660465480483f8a6
+010253d663e0b7bf99a9aa36c9618ab5:342709a8d38f5d465261b629df184aef
+0101686551fb96dc2f3d85ef609c53c5:1edec050dfceaa348ad8b1086a5a8f18
+Roswell New Mexico S02E03 - Good Mother
+01001d6f712eeae283179ab38e5603ab:783250752649649564daa266fed62211
+0105402438b79202cbb0684f3927c5b1:46be973eb922160f7bc3dffd58e7ffb7
+01023fe7621a1cd99b3630f07d98e187:ea65b608358103e9488fa1d031ad5319
+0101802d9b5715dd523dd73fea64292c:5043808db6b3dc251c7b43696a93065a
+Roswell New Mexico S02E04 - What If God Was One Of Us
+01009751d7168cde6f9e3dc3cadafe23:32f5a338462392131a89e163150e96ad
+0105832d4f2d2d08211abeb798aa60a7:d287ef2a28616a9e03b176e8e5c9ffcd
+01023650f1ea9b8505d7b25ff9ddd9ba:fa2ec0df5ea493e982b024e839a14d2f
+0101a58a6c0cc0fe1d8b9eb79c75c84d:034775c84ef646caf593547bbd027160
+Roswell New Mexico S02E05 - Ill Stand By You
+01003c170610acdc145705925c75dc8b:4e03ed142b3d3afd6ede3e8222469de0
+01053fa90075e56507d2f08d07418453:43a859f3a0c609909e3ef97836f6a089
+010247764dfd8b01bd94d35996268f2e:cef69b6a979225da5db5a6a9b004fa1c
+01018a1da07eb10957df4f08badb212e:5f61c40d86ca117d1c000779c5fce26b
+Roswell New Mexico S02E06 - Sex and Candy
+0100c9859aa41447c281fbee144eb3ca:40b2ad310838bd37717d1dc0d6d2eca3
+010525ba85b6a8424e336f0be886c611:82f7e7b28558bed9fc40f9c8511a1e10
+0102d639e7b1f52df71d4f65825a7de6:8c20b5ff3ed796731ee921cd97542f08
+010182bce7a49e69c13b86cf9150d5ea:584a366522669f1d8e7659b6d6029fd3
+Roswell New Mexico S02E07 - Como La Flor
+01001b413d2ccb50474f0d880745f3c4:d292e5f949d34d90fdb945ea00740098
+010529a8174856d7cad1a986209bb5c7:65b41e85079359df44d5d6ff718fddd4
+0102618670e1aa05e4c9c46b0d5f3fd9:43a21bcbd6f5eec2671c1d0fbadadeb5
+010157d4d2eb11cb63f7213e34f063ed:a5c9fe3cc669f3f5859101c2f1bf3307
+Roswell New Mexico S02E08 - Say It Aint So
+0100bedd87f02e11a747c43ef356b72e:2503e4ab728e5cde26857e76d00365df
+0105d127239b734a806f233384c6c9df:8f85088049d0f6bfa1f5198b37366136
+01027b32a815863e1e6fa75716275f9d:6a3c68b3128041e1ac1ebb755421c8d3
+010123fb1757ec91b45ed56957113074:6e5ced55be74e7e033d88e4a3a7534c6
+Roswell New Mexico S02E09 - The Diner
+0100e1f297458d05a76eaed3cf707eb7:1ca521fa6dfb6fe1cb60f0747a37affe
+0105ff7a4f71564cbc06f14dc1eb8449:e5a065a6c12461e2b07a6e9203946d60
+01027f165b3eea634c9133e0c9e0b393:277b885c14ea631fd257a9a411f2d66b
+0101ad07886f6daa9b75e5529f2959bc:1857d8bcbeebc47fc205c8b93d08a404
+Roswell New Mexico S02E10 - American Woman
+0100d36028910f5f9b24a643e1698fcd:1088bd62e153f23d8043d24a3509380a
+0105c9dc1361ab8600255fba8af57296:68be26b8fc07a78e63a7d3debf810c64
+0102427c557dfcc23459d547a8a44d73:65c3e1667bb8508319e42af3851e6684
+0101b4daf13d1e085154921bc5337d59:ecfb22dbd453fe88b10d2eb55a170e6c
+Roswell New Mexico S02E11 - Linger
+010016090cfe549f0643884b39e3eee5:8f9ae671bf9386e77acbe911280cfc23
+01056e0953089b990bc39acca0232bcf:c3d86b7ca874e710444dec12d3cc5859
+0102bbe47be3edb9b89e21817f31a3a9:80e294ade70dfacf27276ea5dfdd902f
+0101dd3d866e9543a4f8f85db766310b:c385ede674dc33e30ec640745ec9f843
+Roswell New Mexico S02E12 - Crash Into Me
+0100012a101dc5708561a136b086d145:7ce8957327b017415fa40673deb088ee
+01052ec32bc339314664e7b99ed2f5be:1bb4e43ccda18143ade33be872b4d311
+010251ac1b67c50cb4d7c95e083a09f7:2a893ffba30e18bb9327eb2977a1d3dc
+01018cc4c476b5aa25290c03480933bc:372ede34c3519699f338c27a7088b19a
+Roswell New Mexico S02E13 - Mr. Jones
+0100e12f3fe7b6a545324f33d951caed:1afb8cb18d7874b3acece3c6c07df860
+0105d249d96c6fab93d1c3e313effcf0:459830b4933df00de270b92c5a883bdc
+01024b21ea6e6ea711ace86d1a55e4f1:97977e8d89f138055aef5ccf86d09bf6
+01018e618a3607c17602f97fe730b053:13f6347051f503712b89bf4737f73532
+Batwoman S01E06 - Ill Be Judge Ill Be Jury
+0100035d436fd3a38a4c67f52573795a:1070f9f940999f6668bf84ecd35bc25c
+01051df4f69aa25f62357fa6ab29998a:564637292b4cb57a8ead1b82cb477962
+01021af52e84005c77165fa8f5d5dba2:1d20fa6ac6811bd928a63e7c61fd532f
+01016d45285579f0b6e18f99c3cfe39c:32e8db3b1cf4c6e055efd19c089d7c1d
+Batwoman S01E07 - Tell Me the Truth
+0100d25d1d3f643e1375ba89566b6278:5d5fac6df13d4971d02df9abcefe7643
+0105e8ed57956430dbdf6c1e81cc294b:6ec6a00938e5b5e636bbb3539cb272ce
+01027f276f8031e04ab0b4ec6428bb41:853f4d05533edbd3cd68a5e5895e2919
+01013a9c3e68630d14e4229f8390e780:41fc467d248521addd83c91f53694253
+Batwoman S01E08 - A Mad TeaParty
+01009c66f4d085d088a2ab296a77e236:69d15a1be1d1af6ed8b59f9e9b070d2d
+0105c96898605d53d193e3ccea19eb2c:ae7e989db4d7d3557b7b809faab52e47
+01029dfd6f8068ca2d5b9e59ef221d45:5f9c617ccc9b998c8286c8ce1301c84a
+010134898d8d9e2ac6628fde4539e65a:3ffac8954cf5ceadfcb3b876eac90d6d
+Batwoman S01E09 - Crisis on Infinite Earths Part Two
+01004886cd5197e5cc90675b5d28b9fe:46ded550117402ce124db576452bb76c
+01058f4e3f078e386b61f565a967b07a:44b226f2f5b8d473b9ff73674e1d3f57
+01029ab729da9b7830eadc016b508f13:293dd873bc8bae539982c502a6ba7ce7
+01011c4340d1e63b831278f3a4d2bba0:078c67fdee03973ec6a990dbcf7cc0fb
+Batwoman S01E10 - How Queer Everything Is Today
+01000a64cb11f470025f7861dfea245a:6d200458ea6e5c76d745cd5f0e829362
+01055d2a5362c6782c7ffd323486a09a:1e9b76a5767be9a3e0f2c80a40cfea20
+0102d86a5d895f8f2ba83d37b79a2091:1782f785676eeecacff742ed2b7f208b
+01016c2da7936118823143f0326ecd02:fd262e5c19d05ee5b23b4e82069dfd4e
+Batwoman S01E11 - An UnBirthday Present
+01002ab23a6dc8570cee971720a9120d:22a4d9f94995210a6c91c200f042882c
+010578fadc01321fc91ed35208ca320b:db1d7713b323aea2ebd251679a82f42a
+010257259922aaa29c1a1b716ac3b639:213f968b7422156f264ee58ff7ece5a7
+010180a020a440a1bfd411119a29b287:f2d98d47a554dc590372c21c6104b0fa
+Batwoman S01E12 - Take Your Choice
+01000e9a1e5204c71cc677de16fd933f:cdb3b3ba7db9084fb878d90821d30f64
+01053f10dcb1eaad286c6532b422ddf8:57a5a7fd74fe851b20a4050f179bae67
+01025d50b1578f95e994b19582efd860:202007c453cae0148fa14ac0095b3af6
+01015d239cb82d487d3e5636bbfad079:629438e17c8671607fee73e8ede4ab22
+Batwoman S01E13 - Drink Me
+0100884863936f6672128402a9acd8c5:8a453eeb7af6d8d51a8b7068ccfe6641
+010581ee86847d2e3c818d47fe1b30fe:7c052539028c5b6a74ceb06aa1f8ebb4
+01025805daff8af753dd39dc68ec1815:a1f0b35fbc5719243274d6e706e176f6
+0101b8adc416982e92eacee5a4b18f1f:37ef15b8d35efd9228905a7070bad093
+Batwoman S01E14 - Grinning From Ear to Ear
+010008d0e901958c2082ff2ce6088099:86b5d84862abe0a0a3f572c5c46cc5a2
+01057f104e7198972975ba84b6b541b8:ddbfa02956875473a716475c571dae5d
+010201e7e0ea9ed068fb3e0453184e35:37e23fb6384249d0697aae659ef0ed90
+0101cbf0440eb922dcf5fcccf0570767:4d47c2da04240526c5b25a196626c5c3
+Batwoman S01E15 - Off With Her Head
+0100eea2f5e0a428730c95806f7249cd:e2e6db528dafac89b3e7962fab63908b
+010535f25a3256ab232c5ddbeb81f012:41c2cb9451c329001c0a18b80c43d298
+010229edd2c096e619fa7f927caf97cf:ae3653fa959da30955ea6f8c83c403cc
+0101e4f72b01eb1cb4715784f07ceece:2a76eb4a2c4236dcc98837f04066842a
+Batwoman S01E16 - Through the LookingGlass
+010027922226ebb00a92105c085f4c4d:5c05d0608c14e86b88da68892b427706
+0105544adf7cf66b8ad8e9fe8a702047:1726c1ae555e855b157cf0157881f499
+0102719b3c51b0326d5c30f5a8946416:ec9b8f2d4eebc2673a496cad0afd5439
+0101d6eb53f4e0347945fba8c9130d2d:a78547c8c6cb47f035cee5d56e00be63
+Batwoman S01E17 - A Narrow Escape
+0100278fd6667cec4d1a631cdf796384:948d90a2e4dde44c954485f5b5ea80dc
+0105bd0d61743eba7c3cf5b04fb7bcdc:2a8b0e496aa7ad94a3a4d1bdc98ab35f
+0102830aad98fd995bbb9681f3a1f7d7:a8469b7875bd80a1ee7aef95279ede4b
+0101d894d56bca027d036d1164af4126:062fb193e464618a7d7e6a4bd7080d83
+Batwoman S01E18 - If You Believe In Me Ill Believe In You
+0100e7d1cc7d2f4fbc326ab64732c614:5dccf502aaa33bc9207e686df509f9ba
+01053d5a7f6bcca4ec10ea3a7b98e10f:ef28d2f6c0e14331fe618ce0e800655b
+0102fa83cf3a4825ba712cce81bacc41:5920b927611a8ed73ac62c7d7e5ba62a
+0101c622ab93565ca301835ec0f2511b:7b0b5c4004620f45ab0f042763696e3c
+Batwoman S01E19 - A Secret Kept From All the Rest
+01009499add899323e56c93a3b6cacf4:b1adf953667c7f87722ef95002b3a7e7
+0105295e8784d92b43eba52bebce3925:2d6582ec207ef31d1449ac56eaba83bb
+01029b257bd6d060d1f3a3e3de3aefe6:be4e0463eaa8ca6422b05290d77b6e53
+0101ea890c84392a4e54245cedab0c48:7ea76ac53dd68d01687e25c3f995659c
+Batwoman S01E20 - O Mouse
+01007f429a8a95178d08da9f0c2dee9b:5bf08eeb0fd96f063090f1ea1e2cd456
+0105eb376ad767a419ce1654a0a49e25:e196f8a0561331d57c6401877e10bcfd
+0102e2eef8c3d3de5ba578df060159f3:bd0147fd33459dde65e0802a21271be1
+0101215a2e0e22edb5c1cdbedbcfde23:28e09a6d987a52ec5df8dd3bbfd786f3
+Batwoman S02E01 - Whatever Happened to Kate Kane
+0100195fc40e55337ebe9e2c5c9f6b18:fdaecc6a251271b6421bed72c78b7d55
+0105c89526a76a69a36d8ec66a1184bd:a62bc8fedf13935496e284f5778a497d
+0102f7735eef546b3ba225515caa1ed3:1a4f9e4054189570cbf99aa7762e9f4b
+0101195a7385e588dd2455e36e8a5e3f:eab66efb9557ac3fdd85df45f437f989
+Batwoman S02E02 - Prior Criminal History
+0100b4d9d53f3633b9cc9e7a21fbc556:ef5851feffe14998c2cc4bd0e0bc055d
+010549a2945d735bba3dd43274939b8e:9872e4151ff3f95ece2a2067f5bb1caf
+010275c53a546b20bf7647a73fe98494:37196cd33af243279ef2722b38b3f26c
+0101b7694404a788549527493393762f:2f946a6f792be8529dd5f1db221937a6
+Batwoman S02E03 - Bat Girl Magic
+0100a5706a179fee0f576bbc429c269f:8144bcc919ae18b34ae2e2177912a11b
+01050d66178688aa7b254603127889ca:551a411ead678cfb7ffe7197a31aadb0
+01027d7a7dd4464bca3b4b4229a8a848:38e455dff11b4a340c25966ef8e94b59
+0101c978bb80268c723564c703c48eb2:af4a79ebf0b2fe7a8fa1d5ef4ed1b841
+Batwoman S02E04 - Fair Skin Blue Eyes
+0100c9d92ae6eb9a8d054f5c64dbc7f3:0897f739796e0b3d8a5098a58804763b
+0105a6d106a9caac09c7990cbe6922d4:ae8ed94d6a0dbfc2d87907fcbd208988
+01027727be2becb3801bb23ca5f82030:cd169d2316ae7c8cc1b5ace5105802f7
+0101c7e2f00526422737ecaec7cfbfd1:068ccaa9ba41121bdf9a671a6f6b76a2
+Batwoman S02E05 - Gore on Canvas
+0100785a4a08f4670ea51d3a27e58cf9:769874aab85443e8f3f748d5df91a18f
+01050c76675bb6ce29da708944bf6784:d75a72be1c65efc811473f5c5e2bdfb8
+010239a841c096e7bcdda365dacbb7b2:48445f8c87883bfcfef0fc36ae6534ab
+010185d38aa8b1f82a91a0a23ffff890:3e914a141727f9711a1c7525a9b24552
+Batwoman S02E06 - Do Not Resuscitate
+010067302a677a674b9be4be621102f0:ffd8ad6826e7f6d61850945a92d43632
+010566dee26f7208094d4733918fde49:72fcab9cfe718de35f1974a4a70c34cc
+010249de755d9eeb5339dc587e366ff3:b46bf47aea22e546a3723fd6eed3c99b
+0101f27f0727a7c31b71008c7675b7aa:0671dd811f889beaa942a56df1b1b406
+Batwoman S02E07 - Its Best You Stop Digging
+01001ccca8ef2d5dbdb860c8f1ce5c61:75e69bda9b37058dcbda7da681c89c1f
+0105b856318d8610a2e93852c4a06c2b:dfa1886f3e7806547f220626879ff261
+01027c26e9750fef7aa25d3210872d64:2f3870c689616032d949c9db19985d51
+0101cd39afdcbcc06956ab9ae342ac63:2ae5e2a56f53660c4a54b553c5b2d6a2
+Batwoman S02E08 - Survived Much Worse
+010038429c900119a5837907df39e84c:56a45e9a47b31325f99f11278c59cf50
+010531e02e2f828a4e878ee57fe1aa36:ba75877b0c84eab324d9728853d7cf35
+0102dd204092dc81083e0ae685fbbbcb:b1ee9175b3e1f368c3900e3ff529b492
+010146121de7b4e8145707a9c1e4ca1a:f300e28d1808d53dc21695373e47b63b
+Batwoman S02E09 - Rule 1
+010075d63eb37e1c8cefb01fe1480bc1:45de633f9841312698535cce35b89e69
+010544c8ef36126b4ef2d23691348687:22268c051049c705538ef008923c6fea
+010212d6be72ea1061b0ecc51030d37c:13c731c1e293bfecd99d53f3f9365a12
+010137223021b950c1f0f6c9c490ba85:4c2abd22a6230d15959fedbcd6279bb6
+Batwoman S02E10 - Time Off for Good Behavior
+010085342cff58ddfedaf55d11b5e7b3:b6b52880e492c945e876d873b66cf65e
+010587e645752c67b65c55ed2edd2e9e:33975f1b9a5d240de589b405e6e5747d
+01020d63aeee2f671edbe5095245f0f4:ae95ccaf09ecff58ee85b9bd0f7d0cdb
+0101ce423176a0c35b8bf3ae2f3f5d23:25ddd879474fa73d33c60ce6737e5c29
+Batwoman S02E11 - Arrive Alive
+01007f4ec4b3d8b75800804c17b592ea:668c05c2794fa19f0b04b1f892b7dc42
+0105802fecfb861e1d9737d131532114:9e3c7395dd581298526ebcb61a7c92fd
+010239033eb000df46e69eb432549eb0:a08ee9f02ab8888f364d13e157f448ef
+01015bb29f71f8ff1b7b144a8ab05bc0:8c99cdc981fe0e1f9f8e8a71bccffaff
+Batwoman S02E12 - Initiate SelfDestruct
+01004d5bbd5243775c78166fa0b89df6:16516f29315498b6f2e9560307fda7a1
+0105de80a6ff76c7eaef30a72d56cdc8:19a58cf6c3e652ee9bd48642c176d86e
+010202d7403ad7de57669411bec8f6f1:3fc4d134442ebf69feb06df300b5d016
+010196bb776270cc0572ba965646d6b5:f7862b33719a782397e78b9f247aad4e
+Batwoman S02E13 - Ill Give You a Clue
+0100fb47d5ca8cdfb21bb659e262bee5:10f38081af0bda73c82443328cb49703
+0105af1b452522d5f5440768bfd0d56b:254be27bb967020e68c9a5d5d73e38d5
+0102ec412eefb75828dc9a72e583009c:da566dfaaeee1ece0af84f6d30f0edc4
+0101cb4d2d717d2253c43ee8d9b60a04:4d0076282cf7a9be56995a8c0f8d8bfe
+Batwoman S02E14 - And Justice for All
+01008877409569af4a2ead433f5af718:6ccaffc68f3a6aa2aaf98b8496b0ecbb
+0105fa00a369032379aa208fb46fc303:99121febd1ae9cdf2c472a68cc1b8e5b
+0102e3230f21c8bff8004740d89645cb:751687d4340d81c174d0f712d5dbcae0
+0101ebdbd11b670e91c268874c3109b0:7e4f10f5a0790c62ebe9dc4d5de9d33e
+Batwoman S02E15 - Armed Suspect
+01006ba0ea1f70084983e770c630bb36:c5f58a392516ac21ea1300ea04a669e5
+01055bd10b9f06d738e3d9a2b13edc7c:d492ed34fa7149844c7bf03c8ae47721
+0102b306556fb84582aa409ac4b6a584:281d9dd82d8843ca41f7092670d48800
+010152228cd2e39ea973f88d973dcd62:d93bdeb9dde3737e90a8fafc4df21427
+Batwoman S02E16 - Rebirth
+010021bc64ac431f4df958583a483201:086f250bf075edd18a24e8fa6f8ed65b
+01052ab94f1f64018300d1bb3077802d:91d163a8aacc0544e70f7eea763b3833
+0102089519e709cba16179a3ca398904:e0a082c1b0e34fd3cabc73265993ffd2
+010108362bd69113b4d27d7d986eb055:c683ed40543517865cdcf850c7ca5822
+Batwoman S02E17 - Kane Kate
+0100e13e59e28292dfe6e08991c0e61e:24f3a32b3ef62df60777e75baf540cde
+01056dce7c173e82c3eca7ed6f1d2b75:91ab12140d5c3ccaf4561fb3eab4213d
+010246b98e624bf1bb31458f857c22a8:97f45fd8d9c60d1e6b6f5591abae8d1c
+0101f682ea4a056ba5511f777c82fd0d:f6f9b45c4ad53548fafc97d1e309e5cc
+Batwoman S02E18 - Power
+0100c5624fc4fa47b5c771ba1f0879de:d5410e4831ba98d33ff18303aee40227
+0105eb5c07d078585c774abe909ca767:d3e9ddd1ec2bba81db00179c251571b5
+01028220ac9cd86cf7bbd47c6393b597:e329fc2c41fc6221a8eb84964c9f1c85
+0101b59a867c9c344c33bb9564a7812c:ff99c5cbca7e80dffedb4148bc21e5d5
diff --git a/KEYS/PARAMOUNTPLUS.txt b/KEYS/PARAMOUNTPLUS.txt
new file mode 100644
index 0000000..d8f1be5
--- /dev/null
+++ b/KEYS/PARAMOUNTPLUS.txt
@@ -0,0 +1,31 @@
+##### One KEY per line. #####
+Un Lugar en Silencio (2018)
+32c7ac2797ae4ca8990cdb917f418a28:9363b26f7c599512db7f33b2eda3eeae
+Un Lugar en Silencio (2018)
+32c7ac2797ae4ca8990cdb917f418a28:9363b26f7c599512db7f33b2eda3eeae
+Sabrina the Teenage Witch - Piloto S01E01 - Piloto
+540009bd9b0f4e1bb4655cf7c0a30ab6:bbbc41bb980fbf4134eec5d9288d676d
+Sabrina the Teenage Witch - Viernes De Panque S01E02 - Viernes De Panque
+78fa06031ee94c2f9b1a7feebefd9dd1:86d96275eb806d5f3156ca1a45c30251
+Sabrina the Teenage Witch - Viernes De Panque S01E02 - Viernes De Panque
+78fa06031ee94c2f9b1a7feebefd9dd1:86d96275eb806d5f3156ca1a45c30251
+Sabrina the Teenage Witch - Viernes De Panque S01E02 - Viernes De Panque
+78fa06031ee94c2f9b1a7feebefd9dd1:86d96275eb806d5f3156ca1a45c30251
+Familias De La Mafia S01E02 - Parte II
+69e84b2e7fee46bc9630c7b4e8256d79:247b446e06c2d83d1ec70cb5cb2b50a2
+Familias De La Mafia S01E01 - Parte I
+db6595d6f64444208e0e0cc2080f2d50:89ad3c24568875c667293edb841eb74b
+Familias De La Mafia S01E01 - Parte I
+db6595d6f64444208e0e0cc2080f2d50:89ad3c24568875c667293edb841eb74b
+Los Padrinos Mágicos S05E01 - Día De Mudanzas Secreto De Familia
+4805cc1c5c554ec7b009c5203f559e50:066732c2c49451ecc13c3e1a68c4a376
+Los Padrinos Mágicos S05E02 - Mi Hermano Mayor Qué Diferencia Hay
+5634bd83530a4352a9eb05cbe3a17807:8ac3a06198dff4e5ec4155fd30b76841
+Los Padrinos Mágicos S05E03 - Un Ataque De Inteligencia La Academia Del Ocio
+f204b48ccb08400e87c3ec1b76a4954e:6adabdf7f867be3a42b0690d4b390739
+iCarly! S01E101 - Un Nuevo Comienzo
+41432623869945ee962c02bcac0109ea:baf729e875fb5431a2f2059189c54e60
+Acapulco Shore S08E14 - Invitadas Sorpresa
+873043e2654246fd9fc51fea9833b0c5:fc6e03c6222a77d760dbeff5869960eb
+Acapulco Shore S08E15 - La Fiesta Final
+31a46457e5784ceba40fe333b093d758:d1cd078dd97676c2fc787976882c72ec
diff --git a/PARAMETROS GENERALES_muestra como descarga.txt b/PARAMETROS GENERALES_muestra como descarga.txt
new file mode 100644
index 0000000..87993ea
--- /dev/null
+++ b/PARAMETROS GENERALES_muestra como descarga.txt
@@ -0,0 +1,6 @@
+python bad37.py --url httpsplay.hbomax.comfeatureurnhbofeatureGX9KHPw1OIMPCJgEAAAAD --alang es-la en --slang es-la en -q 1080p
+pause
+
+para blim descargar la mejor calidad es el comando asi
+
+python bad37.py --url https://www.blim.com/asset/7607 -s 10 -c playready -e 1
\ No newline at end of file
diff --git a/README.md b/README.md
index 7f4c6b9..f141133 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,38 @@
-# HBO-MAX 4k Downloader
- Download from HMAX
+
+
#HBO MAX- BlimTV -Paramount plus 4K Downloader
+
+
+ Tool To download 4K HDR DV SDR from HBO MAX- BlimTV -Paramount plus
+
+
+
+
+
+
+ Hello Fellow < Developers/ >!
+
+
+
+
+
+ Hi! My name is WVDUMP. I am Leaking the scripts to punish few idiots :smile:
+
+
+ About Me
+
+
+
+- 🔭 I’m currently working on Java scripts
+
+- 🌱 I’m currently learning Python
+
+- 👯 Sharing is caring
+
+
+- ⚡ CDM IS NOT INCLUDED BUY it from wvfuck@cyberfiends.net ⚡
+
+
+
+
+
+
diff --git a/bad37.py b/bad37.py
new file mode 100644
index 0000000..9907b7c
--- /dev/null
+++ b/bad37.py
@@ -0,0 +1,128 @@
+# -*- coding: utf-8 -*-
+# Module: BAD Project
+# Created on: 01-06-2021
+# Authors: JUNi
+# Version: 1.0
+
+import argparse
+import os
+import sys
+
+
+parser = argparse.ArgumentParser()
+#Common:
+parser.add_argument("content", nargs="?", help="Content URL or ID")
+parser.add_argument("--url", dest="url_season", help="If set, it will download all assets from the season provided.")
+parser.add_argument("--tqdm", dest="tqmd_mode", help="If set, will download with threading", action="store_true")
+parser.add_argument("--nv", "--no-video", dest="novideo", help="If set, don't download video", action="store_true")
+parser.add_argument("--na", "--no-audio", dest="noaudio", help="If set, don't download audio", action="store_true")
+parser.add_argument("--ns", "--no-subs", dest="nosubs", help="If set, don't download subs", action="store_true")
+parser.add_argument("--all-season", dest="all_season", help="If set, active download mode.", action="store_true")
+parser.add_argument("-e", "--episode", dest="episodeStart", help="If set, it will start downloading the season from that episode.")
+parser.add_argument("-s", dest="season", help="If set, it will download all assets from the season provided.")
+parser.add_argument("--tag", type=str, required=False, help="Release group tag to use for filenames")
+parser.add_argument("-q", "--quality", dest="customquality", type=lambda x: [x.rstrip('p')], help="For configure quality of video.", default=[])
+parser.add_argument("-o", "--output", dest="output", default="downloads", help="If set, it will download all assets to directory provided.")
+parser.add_argument("--keep", dest="keep", help="If set, it will list all formats available.", action="store_true")
+parser.add_argument("--info", help="If set, it will print manifest infos and exit.", action="store_true")
+parser.add_argument("--no-mux", dest="nomux", help="If set, dont mux.", action="store_true")
+#parser.add_argument("--force-mux", dest="force_mux", nargs=1, help="If set, force mux.", default=[])
+#parser.add_argument("--langtag", dest="langtag", nargs=1, help="For configure language tag of MKV.", default=[])
+parser.add_argument("--only-2ch-audio", dest="only_2ch_audio", help="If set, no clean tag subtitles.", action="store_true")
+parser.add_argument("--alang", "--audio-language", dest="audiolang", nargs="*", help="If set, download only selected audio languages", default=[])
+parser.add_argument("--slang", "--subtitle-language", dest="sublang", nargs="*", help="If set, download only selected subtitle languages", default=[])
+parser.add_argument("--flang", "--forced-language", dest="forcedlang", nargs="*", help="If set, download only selected forced subtitle languages", default=[])
+parser.add_argument("--no-cleansubs", dest="nocleansubs", help="If set, no clean tag subtitles.", action="store_true")
+parser.add_argument("--hevc", dest="hevc", help="If set, it will return HEVC manifest", action="store_true")
+parser.add_argument("--uhd", dest="uhd", help="If set, it will return UHD manifest", action="store_true")
+parser.add_argument("--license", dest="license", help="Only print keys, don't download", action="store_true")
+parser.add_argument("-licenses-as-json", help="Save the wv keys as json instead", action="store_true")
+parser.add_argument("--debug", action="store_true", help="Enable debug logging")
+parser.add_argument("--aformat-51ch", "--audio-format-51ch", dest="aformat_51ch", help="For configure format of audio.")
+parser.add_argument("--nc", "--no-chapters", dest="nochpaters", help="If set, don't download chapters", action="store_true")
+parser.add_argument("-c", "--codec", choices=["widevine", "playready"], help="Video type to download", default="widevine")
+
+parser.add_argument("--only-keys", dest="onlykeys", help="Only print keys, don't download", action="store_true")
+
+#HBOMAX
+parser.add_argument("--atmos", dest="atmos", help="If set, it will return Atmos MPDs", action="store_true")
+parser.add_argument("--ad", "--desc-audio", action="store_true", dest="desc_audio", help="Download descriptive audio instead of normal dialogue")
+parser.add_argument("--hdr", dest="hdr", help="If set, it will return HDR manifest", action="store_true")
+parser.add_argument("-r", "--region", choices=["la", "us"], help="HBO Max video region", default="la")
+parser.add_argument("--vp", dest="videocodec", default="h264", choices=["h264", "hevc", "hdr"], help="video codec profile")
+
+#Clarovideo:
+parser.add_argument("--m3u8", dest="m3u8mode", help="If set, it will return M3U8 manifest", action="store_true")
+parser.add_argument("--file", dest="txtpath", help="If set, it will download links of an txt file")
+
+#DisneyPlus:
+parser.add_argument("--tlang", "--title-language", dest="titlelang", nargs=1, help="If set, it will change title language", default="es-la")
+parser.add_argument("--scenario", dest="scenario", help="Video API from DisneyPlus", default="chromecast-drm-cbcs")
+
+#PROXY:
+parser.add_argument("--proxy", dest="proxy", help="Proxy URL to use for both fetching metadata and downloading")
+#proxy format: http://email@email:password@host:port
+args = parser.parse_args()
+
+
+if args.debug:
+ import logging
+ logging.basicConfig(level=logging.DEBUG)
+
+currentFile = '__main__'
+realPath = os.path.realpath(currentFile)
+dirPath = os.path.dirname(realPath)
+dirName = os.path.basename(dirPath)
+
+if __name__ == "__main__":
+ if args.content:
+ args.url_season = args.content
+
+ if not args.url_season:
+ print('Please specify the URL of the content to download.')
+ sys.exit(1)
+
+ if (args.url_season and 'hbomax' in args.url_season):
+ mode = 'hbomax'
+ import hbomax
+ hbomax.main(args)
+ elif (args.url_season and 'clarovideo' in args.url_season):
+ mode = 'clarovideo'
+ import clarovideo
+ clarovideo.main(args)
+ elif (args.url_season and 'blim' in args.url_season):
+ mode = 'blimtv'
+ import blimtv
+ blimtv.main(args)
+ elif (args.url_season and 'nowonline' in args.url_season):
+ mode = 'nowonline'
+ import nowonline
+ nowonline.main(args)
+ elif (args.url_season and 'globo' in args.url_season):
+ mode = 'globoplay'
+ import globoplay
+ globoplay.main(args)
+ elif (args.url_season and 'paramountplus.com' in args.url_season):
+ mode = 'paramountplus'
+ import paramountplus
+ paramountplus.main(args)
+ elif (args.url_season and 'disneyplus' in args.url_season):
+ mode = 'disneyplus'
+ import disneyplus
+ disneyplus.main(args)
+ elif (args.url_season and 'prende.tv' in args.url_season):
+ mode = 'prendetv'
+ import prendetv
+ prendetv.main(args)
+ elif (args.url_season and 'tv.apple.com' in args.url_season):
+ mode = 'appletv'
+ import appletv
+ appletv.main(args)
+ elif (args.url_season and 'wink' in args.url_season):
+ mode = 'wink'
+ import wink
+ wink.main(args)
+
+ else:
+ print("Error! This url or mode is not recognized.")
+ sys.exit(0)
diff --git a/blimtv.py b/blimtv.py
new file mode 100644
index 0000000..bdc2010
--- /dev/null
+++ b/blimtv.py
@@ -0,0 +1,594 @@
+# -*- coding: utf-8 -*-
+# Module: Blim Downloader
+# Created on: 26-11-2020
+# Authors: JUNi
+# Version: 3.5
+
+import requests
+import subprocess
+import xmltodict
+import ffmpy
+import time, shutil
+import glob, json
+import sys, os, re
+import isodate
+import oauthlib
+from oauthlib import oauth1
+from subprocess import Popen
+from titlecase import titlecase
+from unidecode import unidecode
+from pymediainfo import MediaInfo
+from os.path import isfile, join
+
+import pywidevine.clients.blim.manifest_parse as manifestParse
+import pywidevine.clients.blim.client as blim_client
+import pywidevine.clients.blim.config as blim_cfg
+from pywidevine.clients.proxy_config import ProxyConfig
+from pywidevine.muxer.muxer import Muxer
+
+from pywidevine.clients.blim.downloader_pr import PrDownloader
+from pywidevine.clients.blim.downloader_wv import WvDownloader
+from pywidevine.clients.blim.config import PrDownloaderConfig
+from pywidevine.clients.blim.config import WvDownloaderConfig
+
+currentFile = 'blimtv'
+realPath = os.path.realpath(currentFile)
+dirPath = os.path.dirname(realPath)
+
+def main(args):
+
+ SubtitleEditexe = shutil.which("subtitleedit") or shutil.which("SubtitleEdit")
+
+ proxies = {}
+ proxy_meta = args.proxy
+ if proxy_meta == 'none':
+ proxies['meta'] = {'http': None, 'https': None}
+ elif proxy_meta:
+ proxies['meta'] = {'http': proxy_meta, 'https': proxy_meta}
+ SESSION = requests.Session()
+ SESSION.proxies = proxies.get('meta')
+ proxy_cfg = ProxyConfig(proxies)
+
+ def alphanumericSort(l):
+ def convert(text):
+ if text.isdigit():
+ return int(text)
+ else:
+ return text
+
+ def alphanum_key(key):
+ return [convert(c) for c in re.split('([0-9]+)', key)]
+
+ return sorted(l, key=alphanum_key)
+
+ def convert_size(size_bytes):
+ if size_bytes == 0:
+ return '0bps'
+ else:
+ s = round(size_bytes / 1000, 0)
+ return '%ikbps' % s
+
+ def get_size(size):
+ power = 1024
+ n = 0
+ Dic_powerN = {0:'', 1:'K', 2:'M', 3:'G', 4:'T'}
+ while size > power:
+ size /= power
+ n += 1
+ return str(round(size, 2)) + Dic_powerN[n] + 'B'
+
+ def find_str(s, char):
+ index = 0
+ if char in s:
+ c = char[0]
+ for ch in s:
+ if ch == c:
+ if s[index:index + len(char)] == char:
+ return index
+ index += 1
+
+ return -1
+
+ def getKeyId(name):
+ mp4dump = subprocess.Popen([blim_cfg.MP4DUMP, name], stdout=(subprocess.PIPE))
+ mp4dump = str(mp4dump.stdout.read())
+ A = find_str(mp4dump, 'default_KID')
+ KEY_ID_ORI = ''
+ KEY_ID_ORI = mp4dump[A:A + 63].replace('default_KID = ', '').replace('[', '').replace(']', '').replace(' ', '')
+ if KEY_ID_ORI == '' or KEY_ID_ORI == "'":
+ KEY_ID_ORI = 'nothing'
+ return KEY_ID_ORI
+
+ def replace_words(x):
+ x = re.sub(r'[]¡!"#$%\'()*+,:;<=>¿?@\\^_`{|}~[-]', '', x)
+ return unidecode(x)
+
+ def downloadFile2(link, file_name):
+ with open(file_name, 'wb') as (f):
+ print('\nDownloading %s' % file_name)
+ response = requests.get(link, stream=True)
+ total_length = response.headers.get('content-length')
+ if total_length is None:
+ f.write(response.content)
+ else:
+ dl = 0
+ total_length = int(total_length)
+ for data in response.iter_content(chunk_size=4096):
+ dl += len(data)
+ f.write(data)
+ done = int(50 * dl / total_length)
+ sys.stdout.write('\r[%s%s]' % ('=' * done, ' ' * (50 - done)))
+ sys.stdout.flush()
+
+ global folderdownloader
+ if args.output:
+ if not os.path.exists(args.output):
+ os.makedirs(args.output)
+ os.chdir(args.output)
+ if ":" in str(args.output):
+ folderdownloader = str(args.output).replace('/','\\').replace('.\\','\\')
+ else:
+ folderdownloader = dirPath + str(args.output).replace('/','\\').replace('.\\','\\')
+ else:
+ folderdownloader = dirPath.replace('/','\\').replace('.\\','\\')
+
+ def manifest_parse(manifest_url):
+ r = SESSION.get(url=manifest_url)
+ r.raise_for_status()
+ xml = xmltodict.parse(r.text)
+ manifest = json.loads(json.dumps(xml))
+ if '.mpd' in manifest_url:
+ length, video_list, audio_list, subs_list = manifestParse.get_mpd_list(manifest)
+ base_url = manifest['MPD']['Period']['BaseURL']
+ else:
+ length, video_list, audio_list, subs_list = manifestParse.get_ism_list(manifest)
+ base_url = manifest_url.split('Manifest')[0]
+
+ video_list = sorted(video_list, key=(lambda k: int(k['Bandwidth'])))
+ height_all = []
+ for x in video_list:
+ height_all.append(x['Height'])
+
+ try:
+ while args.customquality != [] and int(video_list[(-1)]['Height']) > int(args.customquality[0]):
+ video_list.pop(-1)
+ except Exception:
+ video_list = []
+
+ if video_list == []:
+ video_list = video_list
+ args.novideo = True
+
+ audio_list = sorted(audio_list, key=(lambda k: (int(k['Bandwidth']), str(k['Language']))), reverse=True)
+ BitrateList = []
+ AudioLanguageList = []
+ for x in audio_list:
+ BitrateList.append(x['Bandwidth'])
+ AudioLanguageList.append(x['Language'])
+
+ BitrateList = alphanumericSort(list(set(BitrateList)))
+ AudioLanguageList = alphanumericSort(list(set(AudioLanguageList)))
+ audioList_new = []
+ audio_Dict_new = {}
+ for y in AudioLanguageList:
+ counter = 0
+ for x in audio_list:
+ if x['Language'] == y and counter == 0:
+ audio_Dict_new = {
+ 'Language':x['Language'],
+ 'Bandwidth':x['Bandwidth'],
+ 'ID':x['ID'],
+ 'Codec': x['Codec']}
+ audioList_new.append(audio_Dict_new)
+ counter = counter + 1
+
+ audioList = audioList_new
+ audio_list = sorted(audioList, key=(lambda k: (int(k['Bandwidth']), str(k['Language']))))
+
+ subs_list = []
+ subsList_new = []
+ if args.sublang:
+ for x in subs_list:
+ langAbbrev = x['Language']
+ if langAbbrev in list(args.sublang):
+ subsList_new.append(x)
+ subs_list = subsList_new
+
+ return base_url, length, video_list, audio_list, subs_list, manifest
+
+ def get_episodes(ep_str, num_eps):
+ eps = ep_str.split(',')
+ eps_final = []
+
+ for ep in eps:
+ if '-' in ep:
+ (start, end) = ep.split('-')
+ start = int(start)
+ end = int(end or num_eps)
+ eps_final += list(range(start, end + 1))
+ else:
+ eps_final.append(int(ep))
+
+ return eps_final
+
+ tokenIsOk = False
+ os.makedirs(blim_cfg.COOKIES_FOLDER, exist_ok=True)
+ BLIMLOGINDATA_FILE = join(blim_cfg.COOKIES_FOLDER, 'blim_login_data.json')
+ SESSION, costumer_key, access_key_secret = blim_client.login(SESSION)
+
+ def get_auth_header(api_url):
+ client = oauthlib.oauth1.Client(costumer_key, client_secret=access_key_secret)
+ uri, auth_header, body = client.sign(api_url)
+ return auth_header
+
+ def get_season(blim_id):
+ season_req = requests.get(url=blim_cfg.ENDPOINTS['seasons'] + str(blim_id)).json()['data']
+
+ if 'episode' in season_req['category'] and args.season:
+ blim_id = season_req['parentShow']['id']
+ season_req = requests.get(url=blim_cfg.ENDPOINTS['seasons'] + str(blim_id)).json()['data']
+
+ if not args.season:
+ args.season = 'all'
+
+ seasons = []
+ if args.season:
+ if args.season == 'all':
+ seasons = 'all'
+ elif ',' in args.season:
+ seasons = [int(x) for x in args.season.split(',')]
+ elif '-' in args.season:
+ (start, end) = args.season.split('-')
+ seasons = list(range(int(start), int(end) + 1))
+ else:
+ seasons = [int(args.season)]
+
+ if 'series' in season_req['category']:
+ if seasons == 'all':
+ seasons = [x['number'] for x in season_req['seasons']]
+
+ for season_num in seasons:
+ episode_list = season_req['seasons'][int(season_num) - 1]['episodes']
+ episodes_list_new = []
+ for num, ep in enumerate(episode_list, start=1):
+ episodes_list_new.insert(num - 0, {
+ 'id': ep['id'],
+ 'episode_num': num
+ })
+ episode_list = sorted(episodes_list_new, key=lambda x: x['episode_num'])
+
+ if args.episodeStart:
+ eps = get_episodes(args.episodeStart, len(episode_list))
+ episode_list = [x for x in episode_list if x['episode_num'] in eps]
+
+ for episode in episode_list:
+ get_metadata(blim_id=episode['id'])
+
+ else:
+ get_metadata(blim_id)
+
+ def get_metadata(blim_id):
+ content_url = blim_cfg.ENDPOINTS['content'] + str(blim_id)
+ info_json = requests.get(url=content_url, headers=get_auth_header(content_url), proxies=proxy_cfg.get_proxy('meta')).json()
+ if 'episode' in info_json['data']['category']:
+ blimType = "show"
+ seriesTitles = info_json['data']['parentShow']['titleEditorial']
+ seasonNumber = info_json['data']['parentSeason']['number']
+ episodeNumber = info_json['data']['episodeNumber']
+ episodeTitle = info_json['data']['titleEditorial']
+
+ if 'movie' in info_json['data']['category']:
+ blimType = "movie"
+ seriesTitles = info_json['data']['titleEditorial']
+ releaseYearSearch = info_json['data']['airDate']
+ releaseYear = re.search(r"^[0-9]{4}", releaseYearSearch)
+
+ if blimType=="movie":
+ seriesName = replace_words(seriesTitles) + ' (' + releaseYear.group() + ')'
+ folderName = None
+
+ if blimType=="show":
+ seriesName = f'{replace_words(seriesTitles)} S{seasonNumber:02}E{episodeNumber:02} - {replace_words(episodeTitle)}'
+ folderName = f'{replace_words(seriesTitles)} S{seasonNumber:02}'
+
+ start_process(get_manifest_url(info_json), seriesName, folderName, blimType)
+
+ codec = "mpd" if args.codec == "widevine" else "ss"
+
+ def get_manifest_url(api_json):
+ video_json = api_json['data']['videos'][0]['files']
+ for x in video_json:
+ if x['type'] == codec:
+ videoURL = x['path'].replace("AVOD.", "")
+ if 'ss_629d09c4372f297f2760c820711c4d4737b14f26c25c55e58f1147819005089e' in videoURL or "468842.mpd" in videoURL:
+ print("Lo sentimos, por el momento Blim no está disponible en tu país")
+ sys.exit(0)
+ break
+ return videoURL
+
+ def get_drm_info(): # não está utilizando
+ resp = requests.get(url=blim_cfg.ENDPOINTS['config'], proxies=proxy_cfg.get_proxy('meta')).json()
+ wvlic = resp['widevineLicenseServer']
+ wvcert = resp['widevineCertificateServer']
+ return wvlic, wvcert
+
+ def start_process(manifest_url, seriesName, folderName, blimType):
+ base_url, length, video_list, audio_list, subs_list, xml = manifest_parse(manifest_url)
+ video_bandwidth = dict(video_list[(-1)])['Bandwidth']
+ video_height = str(dict(video_list[(-1)])['Height'])
+ video_width = str(dict(video_list[(-1)])['Width'])
+ video_codec = str(dict(video_list[(-1)])['Codec'])
+ video_format_id = str(dict(video_list[(-1)])['ID'])
+ if not args.novideo:
+ print('\nVIDEO - Bitrate: ' + convert_size(int(video_bandwidth)) + ' - Profile: ' + video_codec.split('=')[0] + ' - Size: ' + get_size(length * float(video_bandwidth) * 0.125) + ' - Dimensions: ' + video_width + 'x' + video_height)
+ print()
+
+ if not args.noaudio:
+ if audio_list != []:
+ for x in audio_list:
+ audio_bandwidth = x['Bandwidth']
+ audio_representation_id = str(x['Codec'])
+ audio_lang = x['Language']
+ print('AUDIO - Bitrate: ' + convert_size(int(audio_bandwidth)) + ' - Profile: ' + audio_representation_id.split('=')[0] + ' - Size: ' + get_size(length * float(audio_bandwidth) * 0.125) + ' - Language: ' + audio_lang)
+ print()
+
+ if not args.nosubs:
+ if subs_list != []:
+ for z in subs_list:
+ sub_lang = str(dict(z)['Language'])
+ print('SUBTITLE - Profile: Normal - Language: ' + sub_lang)
+ print()
+
+ print('Name: ' + seriesName)
+
+ if blimType == 'show':
+ CurrentName = seriesName
+ CurrentHeigh = str(video_height)
+ outputName = folderdownloader + '\\' + str(folderName) + str(CurrentName) + ' [' + str(CurrentHeigh) + 'p].mkv'
+ else:
+ CurrentName = seriesName
+ CurrentHeigh = str(video_height)
+ outputName = folderdownloader + str(CurrentName) + ' [' + str(CurrentHeigh) + 'p].mkv'
+
+ if 'ism' in manifest_url:
+ if video_height == "1080":
+ init_url = blim_cfg.init_files["1080p"]
+ elif video_height == "480":
+ init_url = blim_cfg.init_files["480p"]
+
+ if not os.path.isfile(outputName):
+
+ if not args.novideo:
+ inputVideo = seriesName + ' [' + str(CurrentHeigh) + 'p].mp4'
+ if os.path.isfile(inputVideo):
+ print('\n' + inputVideo + '\nFile has already been successfully downloaded previously.\n')
+ else:
+ if args.codec == 'playready':
+ prdl_cfg = PrDownloaderConfig(xml, base_url, inputVideo, video_bandwidth, init_url, 'video')
+ downloader = PrDownloader(prdl_cfg)
+ else:
+ wvdl_cfg = WvDownloaderConfig(xml, base_url, inputVideo, video_format_id, 'video/mp4')
+ downloader = WvDownloader(wvdl_cfg)
+ downloader.run()
+
+ if not args.noaudio:
+ for x in audio_list:
+ audio_lang = x['Language']
+ inputAudio = seriesName + ' ' + '(' + audio_lang + ')' + '.mp4'
+ inputAudio_demuxed = seriesName + ' ' + '(' + audio_lang + ')' + '.m4a'
+ if os.path.isfile(inputAudio) or os.path.isfile(inputAudio_demuxed):
+ print('\n' + inputAudio + '\nFile has already been successfully downloaded previously.\n')
+ else:
+ if args.codec == 'playready':
+ prdl_cfg = PrDownloaderConfig(xml, base_url, inputAudio, x['Bandwidth'], blim_cfg.init_files["audio"], 'audio')
+ downloader = PrDownloader(prdl_cfg)
+ else:
+ wvdl_cfg = WvDownloaderConfig(xml, base_url, inputAudio, x['ID'], 'audio/mp4')
+ downloader = WvDownloader(wvdl_cfg)
+ downloader.run()
+
+ if not args.nosubs:
+ if subs_list != []:
+ for z in subs_list:
+ langAbbrev = str(dict(z)['Language'])
+ inputSub = seriesName + " " + "(" + langAbbrev + ")"
+ if os.path.isfile(inputSub + ".vtt") or os.path.isfile(inputSub + ".srt"):
+ print("\n" + inputSub + "\nFile has already been successfully downloaded previously.\n")
+ else:
+ downloadFile2(str(dict(z)['File_URL']), inputSub + ".vtt")
+ print('\nConverting subtitles...')
+ SubtitleEdit_process = subprocess.Popen([SubtitleEditexe, "/convert", inputSub + ".vtt", "srt", "/fixcommonerrors", "/encoding:utf-8", "/RemoveLineBreaks"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).wait()
+ for f in glob.glob(inputSub + ".vtt"):
+ os.remove(f)
+ print("Done!")
+ else:
+ print ("\nNo subtitles available.")
+
+ CorrectDecryptVideo = False
+ if not args.novideo:
+ inputVideo = seriesName + ' [' + str(CurrentHeigh) + 'p].mp4'
+ if os.path.isfile(inputVideo):
+ CorrectDecryptVideo = DecryptVideo(inputVideo=inputVideo, keys_video=blim_cfg.protection_keys)
+ else:
+ CorrectDecryptVideo = True
+
+ CorrectDecryptAudio = False
+ if not args.noaudio:
+ for x in audio_list:
+ audio_lang = x['Language']
+ inputAudio = seriesName + ' ' + '(' + audio_lang + ')' + '.mp4'
+ if os.path.isfile(inputAudio):
+ CorrectDecryptAudio = DecryptAudio(inputAudio=inputAudio, keys_audio=blim_cfg.protection_keys)
+ else:
+ CorrectDecryptAudio = True
+
+ if not args.nomux:
+ if not args.novideo:
+ if not args.noaudio:
+ if CorrectDecryptVideo == True:
+ if CorrectDecryptAudio == True:
+ print('\nMuxing...')
+
+ if blimType=="show":
+ MKV_Muxer=Muxer(CurrentName=CurrentName,
+ SeasonFolder=folderName,
+ CurrentHeigh=CurrentHeigh,
+ Type=blimType,
+ mkvmergeexe=blim_cfg.MKVMERGE)
+
+ else:
+ MKV_Muxer=Muxer(CurrentName=CurrentName,
+ SeasonFolder=None,
+ CurrentHeigh=CurrentHeigh,
+ Type=blimType,
+ mkvmergeexe=blim_cfg.MKVMERGE)
+
+ MKV_Muxer.mkvmerge_muxer(lang="English")
+
+ if args.tag:
+ inputName = CurrentName + ' [' + CurrentHeigh + 'p].mkv'
+ release_group(base_filename=inputName,
+ default_filename=CurrentName,
+ folder_name=folderName,
+ type=blimType,
+ video_height=CurrentHeigh)
+
+ if not args.keep:
+ for f in os.listdir():
+ if re.fullmatch(re.escape(CurrentName) + r'.*\.(mp4|m4a|h264|h265|eac3|srt|txt|avs|lwi|mpd)', f):
+ os.remove(f)
+ print("Done!")
+ else:
+ print("\nFile '" + str(outputName) + "' already exists.")
+
+ def release_group(base_filename, default_filename, folder_name, type, video_height):
+ if type=='show':
+ video_mkv = os.path.join(folder_name, base_filename)
+ else:
+ video_mkv = base_filename
+
+ mediainfo = MediaInfo.parse(video_mkv)
+ video_info = next(x for x in mediainfo.tracks if x.track_type == "Video")
+ video_format = video_info.format
+
+ video_codec = ''
+ if video_format == "AVC":
+ video_codec = 'H.264'
+ elif video_format == "HEVC":
+ video_codec = 'H.265'
+
+ audio_info = next(x for x in mediainfo.tracks if x.track_type == "Audio")
+ codec_name = audio_info.format
+ channels_number = int(audio_info.other_channel_positions[0].split('/')[0])
+
+ audio_codec = ''
+ audio_channels = ''
+ if codec_name == "AAC":
+ audio_codec = "AAC"
+ elif codec_name == "AC-3":
+ audio_codec = "DD"
+ elif codec_name == "E-AC-3":
+ audio_codec = "DDP"
+ elif codec_name == "E-AC-3 JOC":
+ audio_codec = "ATMOS"
+
+ if channels_number == "2":
+ audio_channels = "2.0"
+ elif channels_number == "6":
+ audio_channels = "5.1"
+
+ audio_ = audio_codec + audio_channels
+
+ # renomear arquivo
+ default_filename = default_filename.replace('&', '.and.')
+ default_filename = re.sub(r'[]!"#$%\'()*+,:;<=>?@\\^_`{|}~[-]', '', default_filename)
+ default_filename = default_filename.replace(' ', '.')
+ default_filename = re.sub(r'\.{2,}', '.', default_filename)
+ default_filename = unidecode(default_filename)
+
+ output_name = '{}.{}p.BLIM.WEB-DL.{}.{}-{}'.format(default_filename, video_height, audio_, video_codec, args.tag)
+ if type=='show':
+ outputName = os.path.join(folder_name, output_name + '.mkv')
+ else:
+ outputName = output_name + '.mkv'
+
+ os.rename(video_mkv, outputName)
+ print("{} -> {}".format(base_filename, output_name))
+
+ def DecryptAudio(inputAudio, keys_audio):
+ key_audio_id_original = getKeyId(inputAudio)
+ outputAudioTemp = inputAudio.replace(".mp4", "_dec.mp4")
+ if key_audio_id_original != "nothing":
+ for key in keys_audio:
+ key_id=key[0:32]
+ if key_id == key_audio_id_original:
+ print("\nDecrypting audio...")
+ print ("Using KEY: " + key)
+ wvdecrypt_process = subprocess.Popen([blim_cfg.MP4DECRYPT, "--show-progress", "--key", key, inputAudio, outputAudioTemp])
+ stdoutdata, stderrdata = wvdecrypt_process.communicate()
+ wvdecrypt_process.wait()
+ time.sleep (50.0/1000.0)
+ os.remove(inputAudio)
+ print("\nDemuxing audio...")
+ mediainfo = MediaInfo.parse(outputAudioTemp)
+ audio_info = next(x for x in mediainfo.tracks if x.track_type == "Audio")
+ codec_name = audio_info.format
+
+ ext = ''
+ if codec_name == "AAC":
+ ext = '.m4a'
+ elif codec_name == "E-AC-3":
+ ext = ".eac3"
+ elif codec_name == "AC-3":
+ ext = ".ac3"
+ outputAudio = outputAudioTemp.replace("_dec.mp4", ext)
+ print("{} -> {}".format(outputAudioTemp, outputAudio))
+ ff = ffmpy.FFmpeg(executable=blim_cfg.FFMPEG, inputs={outputAudioTemp: None}, outputs={outputAudio: '-c copy'}, global_options="-y -hide_banner -loglevel warning")
+ ff.run()
+ time.sleep (50.0/1000.0)
+ os.remove(outputAudioTemp)
+ print("Done!")
+ return True
+
+ elif key_audio_id_original == "nothing":
+ return True
+
+ def DecryptVideo(inputVideo, keys_video):
+ key_video_id_original = getKeyId(inputVideo)
+ inputVideo = inputVideo
+ outputVideoTemp = inputVideo.replace('.mp4', '_dec.mp4')
+ outputVideo = inputVideo
+ if key_video_id_original != 'nothing':
+ for key in keys_video:
+ key_id = key[0:32]
+ if key_id == key_video_id_original:
+ print('\nDecrypting video...')
+ print('Using KEY: ' + key)
+ wvdecrypt_process = subprocess.Popen([blim_cfg.MP4DECRYPT, '--show-progress', '--key', key, inputVideo, outputVideoTemp])
+ stdoutdata, stderrdata = wvdecrypt_process.communicate()
+ wvdecrypt_process.wait()
+ print('\nRemuxing video...')
+ ff = ffmpy.FFmpeg(executable=blim_cfg.FFMPEG, inputs={outputVideoTemp: None}, outputs={outputVideo: '-c copy'}, global_options='-y -hide_banner -loglevel warning')
+ ff.run()
+ time.sleep(0.05)
+ os.remove(outputVideoTemp)
+ print('Done!')
+ return True
+
+ elif key_video_id_original == 'nothing':
+ return True
+
+ def id_parse(x):
+ if 'player' in args.url_season:
+ id_ = args.url_season.split('/')[-2]
+ else:
+ id_ = args.url_season.split('/')[-1]
+ return id_
+
+ blim_id = id_parse(args.url_season)
+
+ if 'player' in args.url_season:
+ get_metadata(blim_id)
+ else:
+ get_season(blim_id)
+
diff --git a/cookies/cookies.txt b/cookies/cookies.txt
new file mode 100644
index 0000000..e69de29
diff --git a/hbomax.py b/hbomax.py
new file mode 100644
index 0000000..d436d69
--- /dev/null
+++ b/hbomax.py
@@ -0,0 +1,949 @@
+# -*- coding: utf-8 -*-
+# Module: HBO Max Downloader
+# Created on: 04-11-2020
+# Version: 3.5
+
+import sys, os
+import subprocess, re, base64, requests
+import xmltodict, isodate
+import time, glob, uuid, ffmpy, json
+import shutil, urllib.parse
+
+from unidecode import unidecode
+
+import pywidevine.clients.hbomax.config as HMAXConfig
+import pywidevine.clients.hbomax.client as HMAXClient
+
+from pywidevine.clients.hbomax.config import HMAXRegion
+from pywidevine.clients.proxy_config import ProxyConfig
+from pywidevine.muxer.muxer import Muxer
+from os.path import join, isfile
+
+currentFile = 'hbomax'
+realPath = os.path.realpath(currentFile)
+dirPath = os.path.dirname(realPath)
+SESSION = requests.session()
+USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36"
+
+def main(args):
+
+ proxies = {}
+ proxy_meta = args.proxy
+ if proxy_meta == 'none':
+ proxies['meta'] = {'http': None, 'https': None}
+ elif proxy_meta:
+ proxies['meta'] = {'http': proxy_meta, 'https': proxy_meta}
+ SESSION.proxies = proxies.get('meta')
+ proxy_cfg = ProxyConfig(proxies)
+
+ if not os.path.exists(dirPath + '/KEYS'):
+ os.makedirs(dirPath + '/KEYS')
+ else:
+ keys_file = dirPath + '/KEYS/HBOMAX.txt'
+ try:
+ keys_file_hbomax = open(keys_file, 'r', encoding='utf8')
+ keys_file_txt = keys_file_hbomax.readlines()
+ except Exception:
+ with open(keys_file, 'a', encoding='utf8') as (file):
+ file.write('##### One KEY per line. #####\n')
+ keys_file_hbomax = open(keys_file, 'r', encoding='utf8')
+ keys_file_txt = keys_file_hbomax.readlines()
+
+ global folderdownloader
+ if args.output:
+ if not os.path.exists(args.output):
+ os.makedirs(args.output)
+ os.chdir(args.output)
+ if ":" in str(args.output):
+ folderdownloader = str(args.output).replace('/','\\').replace('.\\','\\')
+ else:
+ folderdownloader = dirPath + '\\' + str(args.output).replace('/','\\').replace('.\\','\\')
+ else:
+ folderdownloader = dirPath.replace('/','\\').replace('.\\','\\')
+
+ def downloadFile(aria2c_infile):
+ aria2c_opts = [
+ HMAXConfig.ARIA2C,
+ '--allow-overwrite=true',
+ '--download-result=hide',
+ '--console-log-level=warn',
+ '--enable-color=false',
+ '-x16', '-s16', '-j16',
+ '-i', aria2c_infile]
+ subprocess.run(aria2c_opts, check=True)
+
+ def downloadFile2(link, file_name):
+ with open(file_name, 'wb') as (f):
+ print(file_name)
+ response = SESSION.get(link, stream=True)
+ total_length = response.headers.get('content-length')
+ if total_length is None:
+ f.write(response.content)
+ else:
+ dl = 0
+ total_length = int(total_length)
+ for data in response.iter_content(chunk_size=4096):
+ dl += len(data)
+ f.write(data)
+
+ def find_str(s, char):
+ index = 0
+
+ if char in s:
+ c = char[0]
+ for ch in s:
+ if ch == c:
+ if s[index:index+len(char)] == char:
+ return index
+
+ index += 1
+
+ return -1
+
+ def getKeyId(name):
+ mp4dump = subprocess.Popen([HMAXConfig.MP4DUMP, name], stdout=subprocess.PIPE)
+ mp4dump = str(mp4dump.stdout.read())
+ A=find_str(mp4dump, "default_KID")
+ KEY_ID_ORI=mp4dump[A:A+63].replace("default_KID = ", "").replace("[", "").replace("]", "").replace(" ", "")
+ if KEY_ID_ORI == "":
+ KEY_ID_ORI = "nothing"
+ return KEY_ID_ORI
+
+ def mediainfo_(file):
+ mediainfo_output = subprocess.Popen([HMAXConfig.MEDIAINFO, '--Output=JSON', '-f', file], stdout=subprocess.PIPE)
+ mediainfo_json = json.load(mediainfo_output.stdout)
+ return mediainfo_json
+
+ def replace_words(x):
+ x = re.sub(r'[]¡!"#$%\'()*+,:;<=>¿?@\\^_`{|}~[-]', '', x)
+ x = x.replace('\\', '').replace('/', ' & ')
+ return unidecode(x)
+
+ def ReplaceCodeLanguages(X):
+ X = X.lower()
+ X = X.replace('_subtitle_dialog_0', '').replace('_narrative_dialog_0', '').replace('_caption_dialog_0', '').replace('_dialog_0', '').replace('_descriptive_0', '_descriptive').replace('_descriptive', '_descriptive').replace('_sdh', '-sdh').replace('es-es', 'es').replace('SPA', 'es').replace('en-es', 'es').replace('kn-in', 'kn').replace('gu-in', 'gu').replace('ja-jp', 'ja').replace('mni-in', 'mni').replace('si-in', 'si').replace('as-in', 'as').replace('ml-in', 'ml').replace('sv-se', 'sv').replace('hy-hy', 'hy').replace('sv-sv', 'sv').replace('da-da', 'da').replace('fi-fi', 'fi').replace('nb-nb', 'nb').replace('is-is', 'is').replace('uk-uk', 'uk').replace('hu-hu', 'hu').replace('bg-bg', 'bg').replace('hr-hr', 'hr').replace('lt-lt', 'lt').replace('et-et', 'et').replace('el-el', 'el').replace('he-he', 'he').replace('ar-ar', 'ar').replace('fa-fa', 'fa').replace('ENG', 'en').replace('ro-ro', 'ro').replace('sr-sr', 'sr').replace('cs-cs', 'cs').replace('sk-sk', 'sk').replace('mk-mk', 'mk').replace('hi-hi', 'hi').replace('bn-bn', 'bn').replace('ur-ur', 'ur').replace('pa-pa', 'pa').replace('ta-ta', 'ta').replace('te-te', 'te').replace('mr-mr', 'mr').replace('kn-kn', 'kn').replace('gu-gu', 'gu').replace('ml-ml', 'ml').replace('si-si', 'si').replace('as-as', 'as').replace('mni-mni', 'mni').replace('tl-tl', 'tl').replace('id-id', 'id').replace('ms-ms', 'ms').replace('vi-vi', 'vi').replace('th-th', 'th').replace('km-km', 'km').replace('ko-ko', 'ko').replace('zh-zh', 'zh').replace('ja-ja', 'ja').replace('ru-ru', 'ru').replace('tr-tr', 'tr').replace('it-it', 'it').replace('es-mx', 'es-la').replace('ar-sa', 'ar').replace('zh-cn', 'zh').replace('nl-nl', 'nl').replace('pl-pl', 'pl').replace('pt-pt', 'pt').replace('hi-in', 'hi').replace('mr-in', 'mr').replace('bn-in', 'bn').replace('te-in', 'te').replace('POR', 'pt').replace('cmn-hans', 'zh-hans').replace('cmn-hant', 'zh-hant').replace('ko-kr', 'ko').replace('en-au', 'en').replace('es-419', 'es-la').replace('es-us', 'es-la').replace('en-us', 'en').replace('en-gb', 'en').replace('fr-fr', 'fr').replace('de-de', 'de').replace('las-419', 'es-la').replace('ar-ae', 'ar').replace('da-dk', 'da').replace('yue-hant', 'yue').replace('bn-in', 'bn').replace('ur-in', 'ur').replace('ta-in', 'ta').replace('sl-si', 'sl').replace('cs-cz', 'cs').replace('hi-jp', 'hi').replace('-001', '').replace('en-US', 'en').replace('deu', 'de').replace('eng', 'en').replace('ca-es', 'cat').replace('fil-ph', 'fil').replace('en-ca', 'en').replace('eu-es', 'eu').replace('ar-eg', 'ar').replace('he-il', 'he').replace('el-gr', 'he').replace('nb-no', 'nb').replace('es-ar', 'es-la').replace('en-ph', 'en').replace('sq-al', 'sq').replace('bs-ba', 'bs')
+ return X
+
+ def alphanumericSort(l):
+ def convert(text):
+ if text.isdigit():
+ return int(text)
+ else:
+ return text
+
+ def alphanum_key(key):
+ return [convert(c) for c in re.split('([0-9]+)', key)]
+
+ return sorted(l, key=alphanum_key)
+
+ def convert_size(size_bytes):
+ if size_bytes == 0:
+ return '0bps'
+ else:
+ s = round(size_bytes / 1000, 0)
+ return '%ikbps' % s
+
+ def get_size(size):
+ power = 1024
+ n = 0
+ Dic_powerN = {0:'', 1:'K', 2:'M', 3:'G', 4:'T'}
+ while size > power:
+ size /= power
+ n += 1
+ return str(round(size, 2)) + Dic_powerN[n] + 'B'
+
+ global auth_url, content_url, license_wv
+
+ if args.region == "la":
+ auth_url, content_url, license_wv = HMAXRegion.configHBOMaxLatam()
+
+ if args.region == "us":
+ auth_url, content_url, license_wv = HMAXRegion.configHBOMaxUS()
+
+ def get_authorization_header(TOKEN):
+ headers = HMAXConfig.get_user_headers()['headers']
+
+ headers = {
+ "accept": "application/vnd.hbo.v9.full+json",
+ "accept-encoding": "gzip, deflate, br",
+ "accept-language": str(args.titlelang),
+ "Authorization": f"Bearer {TOKEN}",
+ "user-agent": HMAXConfig.UA,
+ "x-hbo-client-version": "Hadron/50.40.0.111 desktop (DESKTOP)",
+ "x-hbo-device-name": "desktop",
+ "x-hbo-device-os-version": "undefined"
+ }
+ return headers
+
+ os.makedirs(HMAXConfig.COOKIES_FOLDER, exist_ok=True)
+ HMAXTOKEN_FILE = join(HMAXConfig.COOKIES_FOLDER, 'hmax_login_data.json')
+ if not isfile(HMAXTOKEN_FILE):
+ access_token = HMAXClient.login(SESSION, auth_url, content_url)
+
+ def refresh_token():
+ content = None
+ TOKEN = False
+ with open(HMAXTOKEN_FILE,'rb') as f:
+ content = f.read().decode('utf-8')
+ jso = json.loads(content)
+ token_exp = int(time.time()) - jso["EXPIRATION_TIME"]
+ if int(token_exp/60) > 15:
+ TOKEN = False
+ elif int(token_exp/60) < 15:
+ TOKEN = True
+
+ if TOKEN:
+ access_token = jso['ACCESS_TOKEN']
+
+ if not TOKEN:
+ access_token = HMAXClient.login(SESSION, auth_url, content_url)
+ return get_authorization_header(access_token)
+
+ def mpd_parse(mpd_url):
+ if args.atmos:
+ mpd_url = mpd_url.replace('_noatmos', '')
+ base_url = mpd_url.rsplit('/', 1)[0] + '/'
+ r = SESSION.get(url=mpd_url)
+ xml = xmltodict.parse(r.text, force_list={
+ 'Period', 'AdaptationSet', 'ContentProtection'
+ })
+ mpd = json.loads(json.dumps(xml))
+ period = mpd['MPD']['Period']
+ tracks = []
+ for pb in period:
+ tracks = tracks + pb['AdaptationSet']
+
+ def get_height(width, height):
+ if width == '1920':
+ return '1080'
+ elif width in ('1280', '1248'):
+ return '720'
+ else:
+ return height
+
+ def force_instance(x):
+ if isinstance(x['Representation'], list):
+ X = x['Representation']
+ else:
+ X = [x['Representation']]
+ return X
+
+ def get_pssh(track):
+ pssh = ''
+ for t in track.get('ContentProtection', {}):
+ if (t['@schemeIdUri'].lower() == 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed'
+ and t.get('pssh', {}).get('#text')):
+ pssh = t.get('pssh', {}).get('#text')
+ return pssh
+
+ video_list = []
+ for video_tracks in tracks:
+ if video_tracks['@contentType'] == 'video':
+ for x in video_tracks['Representation']:
+ videoDict = {
+ 'Height':get_height(x['@width'], x['@height']),
+ 'Width':x['@width'],
+ 'Bandwidth':x['@bandwidth'],
+ 'ID':x['@id'],
+ 'Codec':x['@codecs'],
+ 'File_URL':x['BaseURL']}
+ video_list.append(videoDict)
+ video_list = sorted(video_list, key=(lambda k: int(k['Bandwidth'])))
+
+ if args.videocodec:
+ if args.videocodec == 'h264':
+ codec_s = 'avc1'
+ if args.videocodec == 'hevc':
+ codec_s = 'hvc1'
+ if args.videocodec == 'hdr':
+ codec_s = 'dvh1'
+
+ video_list_tmp = []
+ for x in video_list:
+ if codec_s in x['Codec']:
+ video_list_tmp.append(x)
+ video_list = video_list_tmp
+
+ while args.customquality != [] and int(video_list[(-1)]['Height']) > int(args.customquality[0]):
+ video_list.pop(-1)
+
+
+ audio_list = []
+ for audio_tracks in tracks:
+ if audio_tracks['@contentType'] == 'audio':
+ isAD = False
+ pssh = get_pssh(audio_tracks)
+ try:
+ if audio_tracks['Role']['@value']:
+ isAD = True
+ except KeyError:
+ isAD = False
+
+ if isAD:
+ lang_id = ReplaceCodeLanguages(audio_tracks["@lang"]) + '-ad'
+ else:
+ lang_id = ReplaceCodeLanguages(audio_tracks["@lang"])
+
+ for x in force_instance(audio_tracks):
+ audio_dict = {
+ 'Bandwidth':x['@bandwidth'],
+ 'ID':x['@id'],
+ 'Language':lang_id,
+ 'Codec':x['@codecs'],
+ 'Channels':x['AudioChannelConfiguration']['@value'],
+ 'File_URL':x['BaseURL'],
+ 'isAD':isAD}
+ audio_list.append(audio_dict)
+
+ audio_list = sorted(audio_list, key=(lambda k: (int(k['Bandwidth']), str(k['Language']))), reverse=True)
+
+ if args.only_2ch_audio:
+ c = 0
+ while c != len(audio_list):
+ if '-3' in audio_list[c]['Codec'].split('=')[0]:
+ audio_list.remove(audio_list[c])
+ else:
+ c += 1
+
+ if args.desc_audio:
+ c = 0
+ while c != len(audio_list):
+ if not audio_list[c]['isAD']:
+ audio_list.remove(audio_list[c])
+ else:
+ c += 1
+ else:
+ c = 0
+ while c != len(audio_list):
+ if audio_list[c]['isAD']:
+ audio_list.remove(audio_list[c])
+ else:
+ c += 1
+
+ BitrateList = []
+ AudioLanguageList = []
+ for x in audio_list:
+ BitrateList.append(x['Bandwidth'])
+ AudioLanguageList.append(x['Language'])
+
+ BitrateList = alphanumericSort(list(set(BitrateList)))
+ AudioLanguageList = alphanumericSort(list(set(AudioLanguageList)))
+ audioList_new = []
+ audio_Dict_new = {}
+ for y in AudioLanguageList:
+ counter = 0
+ for x in audio_list:
+ if x['Language'] == y and counter == 0:
+ audio_Dict_new = {
+ 'Language':x['Language'],
+ 'Bandwidth':x['Bandwidth'],
+ 'Codec': x['Codec'],
+ 'Channels': x['Channels'],
+ 'File_URL':x['File_URL'],
+ 'isAD':x['isAD']
+ }
+ audioList_new.append(audio_Dict_new)
+ counter = counter + 1
+
+ audioList = audioList_new
+ audio_list = sorted(audioList, key=(lambda k: (int(k['Bandwidth']), str(k['Language']))))
+
+ audioList_new = []
+ if args.audiolang:
+ for x in audio_list:
+ langAbbrev = x['Language']
+ if langAbbrev in list(args.audiolang):
+ audioList_new.append(x)
+ audio_list = audioList_new
+
+ return (video_list, audio_list, pssh, base_url)
+
+ def get_episodes(ep_str, num_eps):
+ eps = ep_str.split(',')
+ eps_final = []
+
+ for ep in eps:
+ if '-' in ep:
+ (start, end) = ep.split('-')
+ start = int(start)
+ end = int(end or num_eps)
+ eps_final += list(range(start, end + 1))
+ else:
+ eps_final.append(int(ep))
+
+ return eps_final
+
+ def get_season(series_id):
+ seasons = []
+ if args.season:
+ if args.season == 'all':
+ seasons = 'all'
+ elif ',' in args.season:
+ seasons = [int(x) for x in args.season.split(',')]
+ elif '-' in args.season:
+ (start, end) = args.season.split('-')
+ seasons = list(range(int(start), int(end) + 1))
+ else:
+ seasons = [int(args.season)]
+
+ season_req = SESSION.post(url=content_url, headers=refresh_token(), json=[{"id":series_id}], proxies=proxy_cfg.get_proxy('meta')).json()[0]['body']
+ try:
+ if seasons == 'all':
+ seasons = [num for num, season in enumerate(season_req['references']['seasons'], start=1)]
+ except KeyError:
+ pass
+
+ for season_num in seasons:
+ if args.all_season:
+ episode_list = season_req['references']['episodes']
+ else:
+ try:
+ season_id = season_req['references']['seasons'][int(season_num)-1]
+ episode_req = SESSION.post(url=content_url, headers=refresh_token(), json=[{"id":season_id}], proxies=proxy_cfg.get_proxy('meta')).json()[0]['body']
+ episode_list = episode_req['references']['episodes']
+ except KeyError:
+ episode_list = season_req['references']['episodes']
+
+ episodes_list_new = []
+ for num, ep in enumerate(episode_list, start=1):
+ episodes_list_new.insert(num - 0, {
+ 'id': ep,
+ 'episode_num': num})
+ episode_list = sorted(episodes_list_new, key=lambda x: x['episode_num'])
+
+ if args.episodeStart:
+ eps = get_episodes(args.episodeStart, len(episode_list))
+ episode_list = [x for x in episode_list if x['episode_num'] in eps]
+
+ for episode in episode_list:
+ get_metadata(content_id=episode['id'])
+
+ def get_video_id(content_id):
+ video_id = 'preview'
+ while 'preview' in video_id:
+ video_resp = SESSION.post(url=content_url, headers=refresh_token(), json=HMAXClient.get_video_payload(content_id)).json()
+ if video_resp[0]["statusCode"] > 200:
+ print(video_resp[0]['body']['message'])
+ exit(1)
+ video_id = [item['body']['references']['video'] for (i, item) in enumerate(video_resp) if 'video' in item['body']['references']][0]
+ mpd_url, length, subs_list, chapters = get_infos(video_id)
+ return video_resp[0]['body'], mpd_url, length, subs_list, chapters
+
+ def get_infos(video_id):
+ video_json = SESSION.post(url=content_url, headers=refresh_token(), json=HMAXClient.get_video_payload(video_id)).json()[0]['body']
+ try:
+ mpd_url = video_json['fallbackManifest']
+ except KeyError:
+ mpd_url = video_json['manifest']
+ for x in video_json['videos']:
+ if x['type'] == 'urn:video:main':
+ length = float(x['duration'])
+ return mpd_url, length, get_subtitles(video_json), get_chapters(video_json)
+
+ def get_chapters(video_json):
+ chapters = []
+ for x in video_json['videos']:
+ if 'annotations' in x:
+ for (i, chapter) in enumerate(x['annotations']):
+ secs, ms = divmod(chapter['start'], 1)
+ mins, secs = divmod(secs, 60)
+ hours, mins = divmod(mins, 60)
+ ms = ms * 10000;
+ chapter_time = '%02d:%02d:%02d.%04d' % (hours, mins, secs, ms)
+ chapters.append({'TEXT':chapter['secondaryType'], 'TIME': chapter_time})
+ return chapters
+
+ def get_subtitles(video_json):
+ subs_list = []
+ for x in video_json['videos']:
+ if x['type'] == 'urn:video:main':
+ if 'textTracks' in x:
+ for sub in x['textTracks']:
+
+ isCC = False
+ if 'ClosedCaptions' in sub["type"]:
+ isCC = True
+ isNormal = False
+ if isCC:
+ lang_id = ReplaceCodeLanguages(sub['language']) + '-sdh'
+ trackType = 'SDH'
+ else:
+ lang_id = ReplaceCodeLanguages(sub['language'])
+ isNormal = True
+ trackType = 'NORMAL'
+ isForced = False
+ if sub["type"] == "Forced":
+ isForced = True
+ isNormal = False
+ trackType = 'FORCED'
+ lang_id = ReplaceCodeLanguages(sub['language']) + '-forced'
+ subsDict = {
+ 'Language':lang_id,
+ 'URL':sub['url'],
+ 'isCC':isCC,
+ 'isForced':isForced,
+ 'isNormal':isNormal,
+ 'Type':trackType}
+ subs_list.append(subsDict)
+
+ subs_list_new = []
+ subs_for_list_new = []
+ for subs in subs_list:
+ isForced = subs['isForced']
+ if isForced:
+ subs_for_list_new.append(subs)
+ else:
+ subs_list_new.append(subs)
+
+ subs_for_list = []
+ for subs in subs_for_list_new:
+ lang = subs['Language']
+ if args.forcedlang:
+ if lang in args.forcedlang:
+ subs_for_list.append(subs)
+ else:
+ subs_for_list.append(subs)
+
+ subs_list = []
+ for subs in subs_list_new:
+ lang = subs['Language']
+ if args.sublang:
+ if lang in args.sublang:
+ subs_list.append(subs)
+ else:
+ subs_list.append(subs)
+
+ subs_list_new = []
+ subs_list_new = subs_list + subs_for_list
+ subs_list = subs_list_new
+
+ return subs_list
+
+ def get_metadata(content_id):
+ meta_resp, mpd_url, length, subs_list, chapters = get_video_id(content_id)
+
+ if 'feature' in args.url_season:
+ hbomaxType = "movie"
+ releaseYear = meta_resp['releaseYear']
+ seriesTitles = meta_resp['titles']['full']
+ episodeTitle = meta_resp['titles']['full']
+
+ if 'numberInSeries' in meta_resp:
+ hbomaxType = "show"
+ numberInSeries = meta_resp['numberInSeries']
+ seriesTitles = meta_resp['seriesTitles']['full']
+ episodeTitle = meta_resp['titles']['full']
+
+ if 'numberInSeason' in meta_resp:
+ hbomaxType = "show"
+ seriesTitles = meta_resp['seriesTitles']['full']
+ seasonNumber = meta_resp['seasonNumber']
+ episodeNumber = meta_resp['numberInSeason']
+ episodeTitle = meta_resp['titles']['full']
+
+ if hbomaxType=="movie":
+ seriesName = f'{replace_words(episodeTitle)} ({releaseYear})'
+ folderName = None
+
+ if hbomaxType=="show":
+ try:
+ seriesName = f'{replace_words(seriesTitles)} S{seasonNumber:02}E{episodeNumber:02} - {replace_words(episodeTitle)}'
+ folderName = f'{replace_words(seriesTitles)} S{seasonNumber:02}'
+ except UnboundLocalError:
+ seriesName = f'{replace_words(seriesTitles)} E{numberInSeries:02} - {replace_words(episodeTitle)}'
+ folderName = f'{replace_words(seriesTitles)}'
+
+ start_process(seriesName, folderName, subs_list, mpd_url, length, chapters, hbomaxType)
+
+ def start_process(seriesName, folderName, subs_list, mpd_url, length, chapters, hbomaxType):
+ video_list, audio_list, pssh, base_url = mpd_parse(mpd_url)
+ video_bandwidth = dict(video_list[(-1)])['Bandwidth']
+ video_height = str(dict(video_list[(-1)])['Height'])
+ video_width = str(dict(video_list[(-1)])['Width'])
+ video_codec = str(dict(video_list[(-1)])['Codec'])
+ if not args.license:
+ if not args.novideo:
+ print('\nVIDEO - Bitrate: ' + convert_size(int(video_bandwidth)) + ' - Profile: ' + video_codec.split('=')[0] + ' - Size: ' + get_size(length * float(video_bandwidth) * 0.125) + ' - Dimensions: ' + video_width + 'x' + video_height)
+ print()
+ if not args.noaudio:
+ if audio_list != []:
+ for x in audio_list:
+ audio_bandwidth = x['Bandwidth']
+ audio_representation_id = str(x['Codec'])
+ audio_lang = x['Language']
+ print('AUDIO - Bitrate: ' + convert_size(int(audio_bandwidth)) + ' - Profile: ' + audio_representation_id.split('=')[0] + ' - Size: ' + get_size(length * float(audio_bandwidth) * 0.125) + ' - Language: ' + audio_lang)
+ print()
+ if not args.nosubs:
+ if subs_list != []:
+ for z in subs_list:
+ sub_lang = str(dict(z)['Language'])
+ sub_profile = str(dict(z)['Type'])
+ print('SUBTITLE - Profile: '+ sub_profile +' - Language: ' + sub_lang)
+ print()
+ print('Name: ' + seriesName + '\n')
+
+ if args.license:
+ format_mpd = ""
+ if 'hvc1' in video_codec:
+ format_mpd = "HEVC KEYS"
+ keys_all = get_keys(pssh)
+ with open(keys_file, 'a', encoding='utf8') as (file):
+ file.write(seriesName + format_mpd + '\n')
+ for key in keys_all:
+ with open(keys_file, 'a', encoding='utf8') as (file):
+ file.write(key + '\n')
+ print('\n' + seriesName + ' ' + format_mpd + '\n' + key)
+
+ else:
+ '''
+ if args.tag:
+ from pywidevine.clients.dictionary import get_release_tag
+ for x in audio_list:
+ isDual = False
+ audio_total = len(audio_list)
+ if audio_total > 1:
+ isDual = True
+ seriesName = get_release_tag(seriesName, video_codec, video_height, x['Codec'], x['Channels'], x['Bandwidth'], 'HMAX', str(args.tag), isDual)
+ '''
+
+ if hbomaxType == 'show':
+ CurrentName = seriesName
+ CurrentHeigh = str(video_height)
+ if 'hvc1' in video_codec:
+ VideoOutputName = folderdownloader + '\\' + str(folderName) + str(CurrentName) + ' [' + str(CurrentHeigh) + 'p] [HEVC].mkv'
+ if 'dvh1' in video_codec:
+ VideoOutputName = folderdownloader + '\\' + str(folderName) + str(CurrentName) + ' [' + str(CurrentHeigh) + 'p] [HDR].mkv'
+ else:
+ VideoOutputName = folderdownloader + '\\' + str(folderName) + str(CurrentName) + ' [' + str(CurrentHeigh) + 'p].mkv'
+
+ else:
+ CurrentName = seriesName
+ CurrentHeigh = str(video_height)
+ if 'hvc1' in video_codec:
+ VideoOutputName = str(CurrentName) + ' [' + str(CurrentHeigh) + 'p] [HEVC].mkv'
+ if 'dvh1' in video_codec:
+ VideoOutputName = str(CurrentName) + ' [' + str(CurrentHeigh) + 'p] [HDR].mkv'
+ else:
+ VideoOutputName = str(CurrentName) + ' [' + str(CurrentHeigh) + 'p].mkv'
+
+ if not args.novideo or (not args.noaudio):
+ print("Getting KEYS...")
+ keys_all = get_keys(pssh)
+ if not keys_all:
+ print('License request failed, using keys from txt')
+ keys_all = keys_file_txt
+ if args.licenses_as_json:
+ with open(keys_file, "a", encoding="utf8") as file:
+ file.write(seriesName + "\n")
+ for key in keys_all:
+ with open(keys_file, "a", encoding="utf8") as file:
+ file.write(key + "\n")
+ print("Done!\n")
+
+ if not os.path.isfile(VideoOutputName):
+
+ print('Downloading video & audio')
+ aria2c_input = ''
+ if not args.novideo:
+ if 'hvc1' in video_codec:
+ inputVideo = seriesName + ' [' + str(CurrentHeigh) + 'p] [HEVC].mp4'
+ if 'dvh1' in video_codec:
+ inputVideo = seriesName + ' [' + str(CurrentHeigh) + 'p] [HDR].mp4'
+ else:
+ inputVideo = seriesName + ' [' + str(CurrentHeigh) + 'p].mp4'
+ if os.path.isfile(inputVideo) and not os.path.isfile(inputVideo + '.aria2'):
+ print('\n' + inputVideo + '\nFile has already been successfully downloaded previously.\n')
+ else:
+ url = urllib.parse.urljoin(base_url, video_list[(-1)]['File_URL'])
+ aria2c_input += f'{url}\n'
+ aria2c_input += f'\tdir={folderdownloader}\n'
+ aria2c_input += f'\tout={inputVideo}\n'
+
+ #downloadFile(base_url + video_list[(-1)]['File_URL'], inputVideo)
+
+ if not args.noaudio:
+ for x in audio_list:
+ langAbbrev = x['Language']
+ inputAudio = seriesName + ' ' + '(' + langAbbrev + ')' + '.mp4'
+ inputAudio_ac3 = seriesName + ' ' + '(' + langAbbrev + ')' + '.ac3'
+ inputAudio_eac3 = seriesName + ' ' + '(' + langAbbrev + ')' + '.eac3'
+ inputAudio_m4a = seriesName + ' ' + '(' + langAbbrev + ')' + '.m4a'
+ if os.path.isfile(inputAudio) and not os.path.isfile(inputAudio + '.aria2') or os.path.isfile(inputAudio_ac3) or os.path.isfile(inputAudio_m4a) or os.path.isfile(inputAudio_eac3):
+ print('\n' + inputAudio + '\nFile has already been successfully downloaded previously.\n')
+ else:
+ url = urllib.parse.urljoin(base_url, x['File_URL'])
+ aria2c_input += f'{url}\n'
+ aria2c_input += f'\tdir={folderdownloader}\n'
+ aria2c_input += f'\tout={inputAudio}\n'
+
+ aria2c_infile = os.path.join(folderdownloader, 'aria2c_infile.txt')
+ with open(aria2c_infile, 'w') as fd:
+ fd.write(aria2c_input)
+ aria2c_opts = [
+ HMAXConfig.ARIA2C,
+ '--allow-overwrite=true',
+ '--download-result=hide',
+ '--console-log-level=warn',
+ '-x16', '-s16', '-j16',
+ '-i', aria2c_infile]
+ subprocess.run(aria2c_opts, check=True)
+
+ if not args.nosubs:
+ if subs_list != []:
+ for z in subs_list:
+ langAbbrev = str(dict(z)['Language'])
+ inputSubtitle = seriesName + " " + "(" + langAbbrev + ")"
+ if os.path.isfile(inputSubtitle + ".xml") or os.path.isfile(inputSubtitle + ".srt"):
+ print("\n" + inputSubtitle + "\nFile has already been successfully downloaded previously.\n")
+ else:
+ downloadFile2(str(dict(z)['URL']), inputSubtitle + ".xml")
+ SubtitleEdit_process = subprocess.Popen([HMAXConfig.SUBTITLE_EDIT, "/convert", inputSubtitle + ".xml", "srt", "/fixcommonerrors", "/encoding:utf-8", "/RemoveLineBreaks"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).wait()
+ for f in glob.glob(inputSubtitle + ".xml"):
+ os.remove(f)
+ print("Done!\n")
+ else:
+ print ("\nNo subtitles available.")
+
+ if not args.nochpaters:
+ if chapters != []:
+ print('\nGenerating chapters file...')
+ if os.path.isfile(seriesName + ' Chapters.txt'):
+ print(seriesName + " Chapters.txt" + " has already been successfully downloaded previously.")
+ else:
+ counter = 1
+ with open(seriesName + ' Chapters.txt', 'a', encoding='utf-8') as f:
+ for x in chapters:
+ f.write("CHAPTER" + f'{counter:02}' + "=" + x["TIME"] + "\n" + "CHAPTER" + f'{counter:02}' + "NAME=" + x["TEXT"] + "\n")
+ counter = counter + 1
+ print('Done!\n')
+ else:
+ print("\nNo chapters available.")
+
+ #~NOTE: aqui faz de tudo! Extrai as keys, faz decrypt e muxa os arquivos
+
+ CorrectDecryptVideo = False
+ if not args.novideo:
+ if 'hvc1' in video_codec:
+ inputVideo = seriesName + ' [' + str(CurrentHeigh) + 'p] [HEVC].mp4'
+ if 'dvh1' in video_codec:
+ inputVideo = seriesName + ' [' + str(CurrentHeigh) + 'p] [HDR].mp4'
+ else:
+ inputVideo = seriesName + ' [' + str(CurrentHeigh) + 'p].mp4'
+ if os.path.isfile(inputVideo):
+ CorrectDecryptVideo = DecryptVideo(inputVideo=inputVideo, keys_video=keys_all)
+ else:
+ CorrectDecryptVideo = True
+
+ CorrectDecryptAudio = False
+ if not args.noaudio:
+ for x in audio_list:
+ langAbbrev = x['Language']
+ inputAudio = seriesName + ' ' + '(' + langAbbrev + ')' + '.mp4'
+ if os.path.isfile(inputAudio):
+ CorrectDecryptAudio = DecryptAudio(inputAudio=inputAudio, keys_audio=keys_all)
+ else:
+ CorrectDecryptAudio = True
+
+ if not args.nomux:
+ if not args.novideo:
+ if not args.noaudio:
+ if CorrectDecryptVideo == True:
+ if CorrectDecryptAudio == True:
+ print('\nMuxing...')
+
+ if hbomaxType=="show":
+ MKV_Muxer=Muxer(CurrentName=CurrentName,
+ SeasonFolder=folderName,
+ CurrentHeigh=CurrentHeigh,
+ Type=hbomaxType,
+ mkvmergeexe=HMAXConfig.MKVMERGE)
+
+ else:
+ MKV_Muxer=Muxer(CurrentName=CurrentName,
+ SeasonFolder=None,
+ CurrentHeigh=CurrentHeigh,
+ Type=hbomaxType,
+ mkvmergeexe=HMAXConfig.MKVMERGE)
+
+ MKV_Muxer.mkvmerge_muxer(lang="English")
+
+ if args.tag:
+ if 'hvc1' in video_codec:
+ inputName = CurrentName + ' [' + CurrentHeigh + 'p] [HEVC].mkv'
+ if 'dvh1' in video_codec:
+ inputName = seriesName + ' [' + str(CurrentHeigh) + 'p] [HDR].mkv'
+ else:
+ inputName = CurrentName + ' [' + CurrentHeigh + 'p].mkv'
+
+ release_group(base_filename=inputName,
+ default_filename=CurrentName,
+ folder_name=folderName,
+ type=hbomaxType,
+ video_height=CurrentHeigh)
+
+ if not args.keep:
+ for f in os.listdir():
+ if re.fullmatch(re.escape(CurrentName) + r'.*\.(mp4|m4a|h264|h265|eac3|ac3|srt|txt|avs|lwi|mpd)', f):
+ os.remove(f)
+ print('Done!')
+ else:
+ print("File '" + str(VideoOutputName) + "' already exists.")
+
+ def title_parse(x):
+ m = re.match(r'https?://(play\.hbomax\.com/|(?:www\.)hbomax\.com/)(?:page|feature|series|episode)/(urn?:hbo?:(?:feature|series|page|episode):.+?$)', x)
+ if m:
+ if 'type' in m[2] and 'series' in m[2]:
+ m = 'urn:hbo:series:{}'.format(m[2].split(':')[-3])
+ elif 'type' in m[2] and 'feature' in m[2]:
+ m = 'urn:hbo:feature:{}'.format(m[2].split(':')[-3])
+ elif 'type' in m[2] and 'episode' in m[2]:
+ m = 'urn:hbo:episode:{}'.format(m[2].split(':')[-3])
+ else:
+ m = m[2]
+ return m
+
+ from pywidevine.decrypt.wvdecryptcustom import WvDecrypt
+ from pywidevine.cdm import cdm, deviceconfig
+
+ def get_keys(pssh):
+ device = deviceconfig.device_android_generic
+ wvdecrypt = WvDecrypt(init_data_b64=bytes(pssh.encode()), cert_data_b64=None, device=device)
+
+ license_req = SESSION.post(url=license_wv, headers=refresh_token(), data=wvdecrypt.get_challenge()).content
+ license_b64 = base64.b64encode(license_req)
+
+ wvdecrypt.update_license(license_b64)
+ status, keys = wvdecrypt.start_process()
+ return keys
+
+ def release_group(base_filename, default_filename, folder_name, type, video_height):
+ if type=='show':
+ video_mkv = os.path.join(folder_name, base_filename)
+ else:
+ video_mkv = base_filename
+
+ mediainfo = mediainfo_(video_mkv)
+ for v in mediainfo['media']['track']: # mediainfo do video
+ if v['@type'] == 'Video':
+ video_format = v['Format']
+
+ video_codec = ''
+ if video_format == "AVC":
+ video_codec = 'H.264'
+ elif video_format == "HEVC":
+ video_codec = 'H.265'
+
+ for m in mediainfo['media']['track']: # mediainfo do audio
+ if m['@type'] == 'Audio':
+ codec_name = m['Format']
+ channels_number = m['Channels']
+
+ audio_codec = ''
+ audio_channels = ''
+ if codec_name == "AAC":
+ audio_codec = 'AAC'
+ elif codec_name == "AC-3":
+ audio_codec = "DD"
+ elif codec_name == "E-AC-3":
+ audio_codec = "DDP"
+ elif codec_name == "E-AC-3 JOC":
+ audio_codec = "Atmos"
+
+ if channels_number == "2":
+ audio_channels = "2.0"
+ elif channels_number == "6":
+ audio_channels = "5.1"
+
+ audio_ = audio_codec + audio_channels
+
+ # renomear arquivo
+ default_filename = default_filename.replace('&', '.and.')
+ default_filename = re.sub(r'[]!"#$%\'()*+,:;<=>?@\\^_`{|}~[-]', '', default_filename)
+ default_filename = default_filename.replace(' ', '.')
+ default_filename = re.sub(r'\.{2,}', '.', default_filename)
+
+ output_name = '{}.{}p.HMAX.WEB-DL.{}.{}-{}'.format(default_filename, video_height, audio_, video_codec, args.tag)
+ if type=='show':
+ outputName = os.path.join(folder_name, output_name + '.mkv')
+ else:
+ outputName = output_name + '.mkv'
+
+ os.rename(video_mkv, outputName)
+ print("{} -> {}".format(base_filename, output_name))
+
+ def DecryptAudio(inputAudio, keys_audio):
+ key_audio_id_original = getKeyId(inputAudio)
+ outputAudioTemp = inputAudio.replace('.mp4', '_dec.mp4')
+ if key_audio_id_original != 'nothing':
+ for key in keys_audio:
+ key_id = key[0:32]
+ if key_id == key_audio_id_original:
+ print('\nDecrypting audio...')
+ print('Using KEY: ' + key)
+ wvdecrypt_process = subprocess.Popen([HMAXConfig.MP4DECRYPT, '--show-progress', '--key', key, inputAudio, outputAudioTemp])
+ stdoutdata, stderrdata = wvdecrypt_process.communicate()
+ wvdecrypt_process.wait()
+ time.sleep(0.05)
+ os.remove(inputAudio)
+ print('\nDemuxing audio...')
+ mediainfo = mediainfo_(outputAudioTemp)
+ for m in mediainfo['media']['track']:
+ if m['@type'] == 'Audio':
+ codec_name = m['Format']
+ try:
+ codec_tag_string = m['Format_Commercial_IfAny']
+ except Exception:
+ codec_tag_string = ''
+ ext = ''
+ if codec_name == "AAC":
+ ext = '.m4a'
+ elif codec_name == "E-AC-3":
+ ext = ".eac3"
+ elif codec_name == "AC-3":
+ ext = ".ac3"
+ outputAudio = outputAudioTemp.replace("_dec.mp4", ext)
+ print("{} -> {}".format(outputAudioTemp, outputAudio))
+ ff = ffmpy.FFmpeg(executable=HMAXConfig.FFMPEG, inputs={outputAudioTemp: None}, outputs={outputAudio: '-c copy'}, global_options="-y -hide_banner -loglevel warning")
+ ff.run()
+ time.sleep (50.0/1000.0)
+ os.remove(outputAudioTemp)
+ print("Done!")
+ return True
+
+ elif key_audio_id_original == "nothing":
+ return True
+
+ def DecryptVideo(inputVideo, keys_video):
+ key_video_id_original = getKeyId(inputVideo)
+ inputVideo = inputVideo
+ outputVideoTemp = inputVideo.replace('.mp4', '_dec.mp4')
+ outputVideo = inputVideo
+ if key_video_id_original != 'nothing':
+ for key in keys_video:
+ key_id = key[0:32]
+ if key_id == key_video_id_original:
+ print('\nDecrypting video...')
+ print('Using KEY: ' + key)
+ wvdecrypt_process = subprocess.Popen([HMAXConfig.MP4DECRYPT, '--show-progress', '--key', key, inputVideo, outputVideoTemp])
+ stdoutdata, stderrdata = wvdecrypt_process.communicate()
+ wvdecrypt_process.wait()
+ print('\nRemuxing video...')
+ ff = ffmpy.FFmpeg(executable=HMAXConfig.FFMPEG, inputs={outputVideoTemp: None}, outputs={outputVideo: '-c copy'}, global_options='-y -hide_banner -loglevel warning')
+ ff.run()
+ time.sleep(0.05)
+ os.remove(outputVideoTemp)
+ print('Done!')
+ return True
+
+ elif key_video_id_original == 'nothing':
+ return True
+
+ global content_id
+ content_id = title_parse(args.url_season)
+
+ if 'series' in args.url_season:
+ if not args.season:
+ args.season = 'all'
+ get_season(content_id)
+ elif 'feature' or 'episode':
+ get_metadata(content_id=content_id)
diff --git a/parametros de descargas.txt b/parametros de descargas.txt
new file mode 100644
index 0000000..58be986
--- /dev/null
+++ b/parametros de descargas.txt
@@ -0,0 +1,84 @@
+-h, --help show this help message and exit
+ -t TITLE, --title TITLE
+ title id
+ -wids [WATCH_IDS [WATCH_IDS ...]], --watch-ids [WATCH_IDS [WATCH_IDS ...]]
+ episode / watch id, extract it straight from an
+ episode/extra url
+ --trailers download trailers for the specified title
+ -o [OUTPUTFILE], --outputfile [OUTPUTFILE]
+ output filename (no extension)
+ -q {sd,sd-baseline,sd-main,720p,1080p,2160p,best}, --quality {sd,sd-baseline,sd-main,720p,1080p,2160p,best}
+ video resolution
+ -a AUDIOLANG, --audiolang AUDIOLANG
+ audio language
+ -c CODEC, --codec CODEC
+ video type to download
+ -k, --skip-cleanup skip cleanup step
+ -dm, --dont-mux move unmuxed tracks instead of muxing
+ -i, --info print track information and exit
+ -d, --debug print debug statements
+ -n {once,every,off}, --notify {once,every,off}
+ choose notification mode
+ -S, --subs-only download subtitles and exit
+ -sl SUB_LANG, --sub-lang SUB_LANG
+ subtitle languages to download
+ -st {dfxp,vtt,none}, --sub-type {dfxp,vtt,none}
+ subtitle format to download
+ -sc {srt,ass,none}, --sub-convert {srt,ass,none}
+ subtitle format to convert to
+ -A, --audio-only download audio and exit
+ -sA, --skip-audio do NOT download any audio tracks
+ -ad, --audio-description
+ download audio description tracks instead of regular
+ ones
+ -at, --all-tracks download and merge ALL tracks
+ -s SEASON, --season SEASON
+ lookup and download season from title id
+ -E EPISODE, --episode EPISODE
+ rip only specified episode(s) in season mode
+ -e EPISODE_START, --episode_start EPISODE_START
+ Recursively rip season number that provided viewable
+ ID belongs to, starting at the episode provided
+ --skip SKIP skip episodes in season mode
+ --web-login
+ --no-web-login use web login method instead of Android API login
+ method
+ --license do license request and print decryption keys only
+ --licenses-as-json, -laj
+ save the licenses as json instead
+ --licenses-json-name LICENSES_JSON_NAME, -ljn LICENSES_JSON_NAME
+ save the licenses-json to a specific name (will be
+ "keys{name}.json")
+ --licenses-json-overwrite, -ljo
+ always overwrite keys.json if it exists (dangerous)
+ --create-dl-info-json, -dij
+ Create a JSON file with all metadata + track URLs
+ (IIRC expire after 24 hours) + working VPN address (if
+ any found in proxydata.json)
+ --dl-info-json-name, -ijn
+ Name of the json stored when using --create-dl-info-
+ json/-dij
+ -m, --store-meta store the metadata of the movies (json)
+ --proxy PROXY proxy URL to use for both fetching metadata and
+ downloading
+ --proxy-meta PROXY_META
+ proxy URL to use for fetching metadata
+ --proxy-dl PROXY_DL proxy URL to use for downloading
+
+ -r us donde us es la region para estados unidos
+
+
+
+[-h] [--url URL_SEASON] [--tqdm] [--nv] [--na] [--ns]
+ [--all-season] [-e EPISODESTART] [-s SEASON] [--tag TAG]
+ [-q CUSTOMQUALITY] [-o OUTPUT] [--keep] [--no-mux]
+ [--only-2ch-audio] [--alang [AUDIOLANG [AUDIOLANG ...]]]
+ [--slang [SUBLANG [SUBLANG ...]]]
+ [--flang [FORCEDLANG [FORCEDLANG ...]]] [--hevc] [--uhd]
+ [--only-keys] [--debug] [--aformat-51ch AFORMAT_51CH] [--nc]
+ [-c {widevine,playready}] [--atmos] [--ad] [--hdr]
+ [-r {la,us}] [--m3u8] [--file TXTPATH] [--tlang TITLELANG]
+ [--scenario SCENARIO] [--proxy PROXY]
+ [content]
+
+
diff --git a/paramountplus.py b/paramountplus.py
new file mode 100644
index 0000000..fa4cfb6
--- /dev/null
+++ b/paramountplus.py
@@ -0,0 +1,788 @@
+# -*- coding: utf-8 -*-
+# Module: Paramount Plus Downloader
+# Created on: 19-02-2021
+# Authors: JUNi
+# Version: 2.0
+
+import urllib.parse
+import re, base64, requests, sys, os
+import subprocess, shutil
+import xmltodict, isodate
+import json, ffmpy
+import http, html, time
+
+from unidecode import unidecode
+from http.cookiejar import MozillaCookieJar
+from titlecase import titlecase
+from pymediainfo import MediaInfo
+
+import pywidevine.clients.paramountplus.config as pmnp_cfg
+from pywidevine.clients.proxy_config import ProxyConfig
+from pywidevine.muxer.muxer import Muxer
+
+from pywidevine.clients.paramountplus.downloader import WvDownloader
+from pywidevine.clients.paramountplus.config import WvDownloaderConfig
+
+
+currentFile = 'paramountplus'
+realPath = os.path.realpath(currentFile)
+dirPath = os.path.dirname(realPath)
+USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36'
+SESSION = requests.Session()
+
+def main(args):
+ global _id
+
+ proxies = {}
+ proxy_meta = args.proxy
+ if proxy_meta == 'none':
+ proxies['meta'] = {'http': None, 'https': None}
+ elif proxy_meta:
+ proxies['meta'] = {'http': proxy_meta, 'https': proxy_meta}
+ SESSION.proxies = proxies.get('meta')
+ proxy_cfg = ProxyConfig(proxies)
+
+ if not os.path.exists(dirPath + '/KEYS'):
+ os.makedirs(dirPath + '/KEYS')
+ else:
+ keys_file = dirPath + '/KEYS/PARAMOUNTPLUS.txt'
+ try:
+ keys_file_pmnp = open(keys_file, 'r')
+ keys_file_txt = keys_file_pmnp.readlines()
+ except Exception:
+ with open(keys_file, 'a', encoding='utf8') as (file):
+ file.write('##### One KEY per line. #####\n')
+ keys_file_pmnp = open(keys_file, 'r', encoding='utf8')
+ keys_file_txt = keys_file_pmnp.readlines()
+
+ def alphanumericSort(l):
+ def convert(text):
+ if text.isdigit():
+ return int(text)
+ else:
+ return text
+
+ def alphanum_key(key):
+ return [convert(c) for c in re.split('([0-9]+)', key)]
+
+ return sorted(l, key=alphanum_key)
+
+ def convert_size(size_bytes):
+ if size_bytes == 0:
+ return '0bps'
+ else:
+ s = round(size_bytes / 1000, 0)
+ return '%ikbps' % s
+
+ def get_size(size):
+ power = 1024
+ n = 0
+ Dic_powerN = {0:'', 1:'K', 2:'M', 3:'G', 4:'T'}
+ while size > power:
+ size /= power
+ n += 1
+ return str(round(size, 2)) + Dic_powerN[n] + 'B'
+
+ def getKeyId(name):
+ mp4dump = subprocess.Popen([pmnp_cfg.MP4DUMP, name], stdout=(subprocess.PIPE))
+ mp4dump = str(mp4dump.stdout.read())
+ A = find_str(mp4dump, 'default_KID')
+ KEY_ID_ORI = ''
+ KEY_ID_ORI = mp4dump[A:A + 63].replace('default_KID = ', '').replace('[', '').replace(']', '').replace(' ', '')
+ if KEY_ID_ORI == '' or KEY_ID_ORI == "'":
+ KEY_ID_ORI = 'nothing'
+ return KEY_ID_ORI
+
+ def find_str(s, char):
+ index = 0
+ if char in s:
+ c = char[0]
+ for ch in s:
+ if ch == c:
+ if s[index:index + len(char)] == char:
+ return index
+ index += 1
+
+ return -1
+
+ def mediainfo_(file):
+ mediainfo_output = subprocess.Popen([MediaInfo_exe, '--Output=JSON', '-f', file], stdout=(subprocess.PIPE))
+ mediainfo_json = json.load(mediainfo_output.stdout)
+ return mediainfo_json
+
+ def ReplaceDontLikeWord(X):
+ try:
+ X = X.replace(" : ", " - ").replace(": ", " - ").replace(":", " - ").replace("&", "and").replace("+", "").replace(";", "").replace("ó", "o").\
+ replace("[", "").replace("'", "").replace("]", "").replace("/", "").replace("//", "").\
+ replace("’", "'").replace("*", "x").replace("<", "").replace(">", "").replace("|", "").\
+ replace("~", "").replace("#", "").replace("%", "").replace("{", "").replace("}", "").replace(",", "").\
+ replace("?","").replace("¿","")
+ except Exception:
+ X = X.replace(" : ", " - ").replace(": ", " - ").replace(":", " - ").replace("&", "and").replace("+", "").replace(";", "").\
+ replace("ó", "o").replace("[", "").replace("'", "").replace("]", "").replace("/", "").\
+ replace("//", "").replace("’", "'").replace("*", "x").replace("<", "").replace(">", "").replace("|", "").\
+ replace("~", "").replace("#", "").replace("%", "").replace("{", "").replace("}", "").replace(",", "").\
+ replace("?","").replace("¿","")
+
+ return titlecase(X)
+
+ def replace_code_lang(X):
+ X = X.lower()
+ X = X.replace('es-mx', 'es-la').replace('pt-BR', 'pt-br').replace('dolby digital', 'en').replace('dd+', 'en')
+ return X
+
+ def get_cookies(file_path):
+ try:
+ cj = http.cookiejar.MozillaCookieJar(file_path)
+ cj.load()
+ except Exception:
+ print('\nCookies not found! Please dump the cookies with the Chrome extension https://chrome.google.com/webstore/detail/cookiestxt/njabckikapfpffapmjgojcnbfjonfjfg and place the generated file in ' + file_path)
+ print('\nWarning, do not click on "download all cookies", you have to click on "click here".\n')
+ sys.exit(0)
+
+ cookies = str()
+ for cookie in cj:
+ cookie.value = urllib.parse.unquote(html.unescape(cookie.value))
+ cookies = cookies + cookie.name + '=' + cookie.value + ';'
+
+ cookies = list(cookies)
+ del cookies[-1]
+ cookies = ''.join(cookies)
+ return cookies
+
+ cookies_file = 'cookies_pmnp.txt'
+ cookies = get_cookies(dirPath + '/cookies/' + cookies_file)
+ pmnp_headers = {
+ 'Accept':'application/json, text/plain, */*',
+ 'Access-Control-Allow-Origin':'*',
+ 'cookie':cookies,
+ 'User-Agent':USER_AGENT
+ }
+
+ def mpd_parsing(mpd_url):
+ base_url = mpd_url.split('stream.mpd')[0]
+ r = SESSION.get(url=mpd_url)
+ r.raise_for_status()
+ xml = xmltodict.parse(r.text)
+ mpdf = json.loads(json.dumps(xml))
+ length = isodate.parse_duration(mpdf['MPD']['@mediaPresentationDuration']).total_seconds()
+ tracks = mpdf['MPD']['Period']['AdaptationSet']
+
+ def get_pssh(track):
+ pssh = ''
+ for t in track["ContentProtection"]:
+ if t['@schemeIdUri'].lower() == 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed':
+ pssh = t["cenc:pssh"]
+ return pssh
+
+ def force_instance(x):
+ if isinstance(x['Representation'], list):
+ X = x['Representation']
+ else:
+ X = [x['Representation']]
+ return X
+
+ video_list = []
+ for video_tracks in tracks:
+ if video_tracks['@contentType'] == 'video':
+ pssh = get_pssh(video_tracks)
+ for x in force_instance(video_tracks):
+ try:
+ codecs = x['@codecs']
+ except (KeyError, TypeError):
+ codecs = video_tracks['@codecs']
+ video_dict = {
+ 'Height':x['@height'],
+ 'Width':x['@width'],
+ 'Bandwidth':x['@bandwidth'],
+ 'ID':x['@id'],
+ 'TID':video_tracks['@id'],
+ 'Codec':codecs}
+ video_list.append(video_dict)
+
+ video_list = sorted(video_list, key=(lambda k: int(k['Bandwidth'])))
+
+ while args.customquality != [] and int(video_list[(-1)]['Height']) > int(args.customquality[0]):
+ video_list.pop(-1)
+
+ audio_list = []
+ for audio_tracks in tracks:
+ if audio_tracks['@contentType'] == 'audio':
+ for x in force_instance(audio_tracks):
+ try:
+ codecs = x['@codecs']
+ except (KeyError, TypeError):
+ codecs = audio_tracks['@codecs']
+ audio_dict = {
+ 'Bandwidth':x['@bandwidth'],
+ 'ID':x['@id'],
+ 'TID':audio_tracks['@id'],
+ 'Language':replace_code_lang(audio_tracks['@lang']),
+ 'Codec':codecs}
+ audio_list.append(audio_dict)
+
+ audio_list = sorted(audio_list, key=(lambda k: (int(k['Bandwidth']), str(k['Language']))), reverse=True)
+ if args.only_2ch_audio:
+ c = 0
+ while c != len(audio_list):
+ if '-3' in audio_list[c]['Codec'].split('=')[0]:
+ audio_list.remove(audio_list[c])
+ else:
+ c += 1
+
+ BitrateList = []
+ AudioLanguageList = []
+ for x in audio_list:
+ BitrateList.append(x['Bandwidth'])
+ AudioLanguageList.append(x['Language'])
+
+ BitrateList = alphanumericSort(list(set(BitrateList)))
+ AudioLanguageList = alphanumericSort(list(set(AudioLanguageList)))
+ audioList_new = []
+ audio_Dict_new = {}
+ for y in AudioLanguageList:
+ counter = 0
+ for x in audio_list:
+ if x['Language'] == y and counter == 0:
+ audio_Dict_new = {
+ 'Language':x['Language'],
+ 'Bandwidth':x['Bandwidth'],
+ 'Codec': x['Codec'],
+ 'TID':x['TID'],
+ 'ID':x['ID']}
+ audioList_new.append(audio_Dict_new)
+ counter = counter + 1
+
+ audioList = audioList_new
+ audio_list = sorted(audioList, key=(lambda k: (int(k['Bandwidth']), str(k['Language']))))
+
+ audioList_new = []
+ if args.audiolang:
+ for x in audio_list:
+ langAbbrev = x['Language']
+ if langAbbrev in list(args.audiolang):
+ audioList_new.append(x)
+ audio_list = audioList_new
+
+ return base_url, length, video_list, audio_list, [], pssh, mpdf
+
+ def get_episodes(ep_str, num_eps):
+ eps = ep_str.split(',')
+ eps_final = []
+
+ for ep in eps:
+ if '-' in ep:
+ (start, end) = ep.split('-')
+ start = int(start)
+ end = int(end or num_eps)
+ eps_final += list(range(start, end + 1))
+ else:
+ eps_final.append(int(ep))
+
+ return eps_final
+
+ _id = args.url_season.split('/')[-2]
+ if '/video/' in args.url_season:
+ content_regex = r'(\/shows\/)([\w-]+)(\/video\/)([\w-]+)'
+ url_match = re.search(content_regex, args.url_season)
+ _id = url_match[2]
+
+ def get_content_info():
+ if 'shows' in args.url_season:
+ pmnp_season_url = 'https://www.paramountplus.com/shows/{}/xhr/episodes/page/0/size/100/xs/0/season/{}/'.format(_id, '')
+ season_req = requests.get(url=pmnp_season_url, headers=pmnp_headers, proxies=proxy_cfg.get_proxy('meta'))
+
+ if not args.season:
+ args.season = 'all'
+
+ seasons = []
+ if args.season:
+ if args.season == 'all':
+ seasons = 'all'
+ elif ',' in args.season:
+ seasons = [int(x) for x in args.season.split(',')]
+ elif '-' in args.season:
+ (start, end) = args.season.split('-')
+ seasons = list(range(int(start), int(end) + 1))
+ else:
+ seasons = [int(args.season)]
+
+ if seasons == 'all':
+ seasons_list = [x['season_number'] for x in season_req.json()['result']['data']]
+ seasons = sorted(set(seasons_list))
+
+ for season_num in seasons:
+ pmnp_season_url = 'https://www.paramountplus.com/shows/{}/xhr/episodes/page/0/size/500/xs/0/season/{}/'.format(_id, season_num)
+ season_req = requests.get(url=pmnp_season_url, headers=pmnp_headers, proxies=proxy_cfg.get_proxy('meta'))
+ if season_req.json()['result']['total'] < 1:
+ print('This season doesnt exist!')
+ exit()
+
+ for num, ep in enumerate(season_req.json()['result']['data'], start=1):
+ episodeNumber = ep['episode_number']
+ seasonNumber = ep['season_number']
+ seriesTitle = ReplaceDontLikeWord(ep['series_title'])
+ episodeTitle = ReplaceDontLikeWord(ep['label'])
+ seriesName = f'{seriesTitle} S{seasonNumber:0>2}E{episodeNumber:0>2} - {episodeTitle}'
+ folderName = f'{seriesTitle} S{seasonNumber:0>2}'
+ raw_url = urllib.parse.urljoin('https://www.paramountplus.com', ep['metaData']['contentUrl'])
+
+ episodes_list_new = []
+ episodes_dict = {
+ 'id': ep['content_id'],
+ 'raw_url': raw_url,
+ 'pid':ep['metaData']['pid'],
+ 'seriesName':seriesName,
+ 'folderName':folderName,
+ 'episodeNumber': num,
+ 'seasonNumber':seasonNumber,
+ 'pmnpType': 'show'}
+ episodes_list_new.append(episodes_dict)
+ episodes_list = []
+ for x in episodes_list_new:
+ episodes_list.append(x)
+ #episodes_list = sorted(episodes_list, key=lambda x: x['episodeNumber'])
+
+ if args.episodeStart:
+ eps = get_episodes(args.episodeStart, len(episodes_list))
+ episodes_list = [x for x in episodes_list if x['episodeNumber'] in eps]
+
+ if 'video' in args.url_season:
+ episodes_list = [x for x in episodes_list if x['id'] in url_match.group(4)]
+
+ for content_json in episodes_list:
+ start_process(content_json)
+
+ if 'movies' in args.url_season:
+ while 1:
+ resp = requests.get(url=args.url_season + '/', headers=pmnp_headers, proxies=proxy_cfg.get_proxy('meta'))
+ if resp.ok:
+ break
+
+ html_data = resp
+ html_data = html_data.text.replace('\r\n', '').replace('\n', '').replace('\r', '').replace('\t', '').replace(' ', '')
+ html_data_list = re.split('()(?i)', html_data)
+ json_web = []
+ for div in html_data_list:
+ if 'player.paramsVO.adCallParams' in div:
+ print()
+ rg = re.compile('(player.metaData = )(.*)(;player.tms_program_id)')
+ m = rg.search(div)
+ if m:
+ json_web = m.group(2)
+ json_web = json.loads(json_web)
+
+ content_dict = {}
+ episodes_list = []
+ year_regex = r'(\d{4})'
+ movieTitle = ReplaceDontLikeWord(json_web['seriesTitle'])
+ try:
+ r = re.search(year_regex, json_web['airdate'])
+ except KeyError:
+ r = re.search(year_regex, json_web['airdate_tv'])
+ seriesName = f'{movieTitle} ({r.group(0)})'
+
+ content_dict = {
+ 'id':json_web['contentId'],
+ 'raw_url': str(args.url_season),
+ 'pid': json_web['pid'],
+ 'seriesName':seriesName,
+ 'folderName':None,
+ 'episodeNumber':1,
+ 'seasonNumber':1,
+ 'pmnpType': 'movie'}
+ episodes_list.append(content_dict)
+
+ for content_json in episodes_list:
+ start_process(content_json)
+
+ def get_license(id_json):
+ while 1:
+ resp = requests.get(url=id_json['raw_url'], headers=pmnp_headers, proxies=proxy_cfg.get_proxy('meta'))
+ if resp.ok:
+ break
+
+ html_data = resp
+ html_data = html_data.text.replace('\r\n', '').replace('\n', '').replace('\r', '').replace('\t', '').replace(' ', '')
+ html_data_list = re.split('()(?i)', html_data)
+ json_web = []
+ for div in html_data_list:
+ if '(!window.CBS.Registry.drmPromise) {' in div:
+ rg = re.compile('(player.drm = )(.*)(;}player.enableCP)')
+ m = rg.search(div)
+ if m:
+ json_web = m.group(2)
+ json_web = json.loads(json_web)
+
+ lic_url = json_web['widevine']['url']
+ header_auth = json_web['widevine']['header']['Authorization']
+ if not lic_url:
+ print('Too many requests...')
+ return lic_url, header_auth
+
+ global folderdownloader
+ if args.output:
+ if not os.path.exists(args.output):
+ os.makedirs(args.output)
+ os.chdir(args.output)
+ if ":" in str(args.output):
+ folderdownloader = str(args.output).replace('/','\\').replace('.\\','\\')
+ else:
+ folderdownloader = dirPath + str(args.output).replace('/','\\').replace('.\\','\\')
+ else:
+ folderdownloader = dirPath.replace('/','\\').replace('.\\','\\')
+
+ def get_manifest(id_json):
+ api_manifest = 'https://link.theplatform.com/s/dJ5BDC/{}?format=SMIL&manifest=m3u&Tracking=true&mbr=true'.format(id_json['pid'])
+ r = requests.get(url=api_manifest, headers=pmnp_headers, proxies=proxy_cfg.get_proxy('meta'))
+ xmls = xmltodict.parse(r.text)
+ smil = json.loads(json.dumps(xmls))
+ videoSrc = []
+ try:
+ for x in smil['smil']['body']['seq']['switch']:
+ videoSrc = x['video']['@src']
+ except Exception:
+ videoSrc = smil['smil']['body']['seq']['switch']['video']['@src']
+ lic_url, header_auth = get_license(id_json)
+ return {'mpd_url': videoSrc, 'license': lic_url, 'lic_header': header_auth}
+
+ def start_process(content_info):
+ drm_info = get_manifest(content_info)
+ base_url, length, video_list, audio_list, subs_list, pssh, xml = mpd_parsing(drm_info['mpd_url'])
+ video_bandwidth = dict(video_list[(-1)])['Bandwidth']
+ video_height = str(dict(video_list[(-1)])['Height'])
+ video_width = str(dict(video_list[(-1)])['Width'])
+ video_codec = str(dict(video_list[(-1)])['Codec'])
+ video_format_id = str(dict(video_list[(-1)])['ID'])
+ video_track_id = str(dict(video_list[(-1)])['TID'])
+ if not args.onlykeys:
+ if not args.novideo:
+ print('\nVIDEO - Bitrate: ' + convert_size(int(video_bandwidth)) + ' - Profile: ' + video_codec.split('=')[0] + ' - Size: ' + get_size(length * float(video_bandwidth) * 0.125) + ' - Dimensions: ' + video_width + 'x' + video_height)
+ print()
+
+ if not args.noaudio:
+ if audio_list != []:
+ for x in audio_list:
+ audio_bandwidth = x['Bandwidth']
+ audio_representation_id = str(x['Codec'])
+ audio_lang = x['Language']
+ print('AUDIO - Bitrate: ' + convert_size(int(audio_bandwidth)) + ' - Profile: ' + audio_representation_id.split('=')[0] + ' - Size: ' + get_size(length * float(audio_bandwidth) * 0.125) + ' - Language: ' + audio_lang)
+ print()
+
+ if not args.nosubs:
+ if subs_list != []:
+ for z in subs_list:
+ sub_lang = z['Language']
+ print('SUBTITLE - Profile: Normal - Language: ' + sub_lang)
+ print()
+
+ print('Name: ' + content_info['seriesName'])
+
+ if content_info['pmnpType'] == 'show':
+ CurrentName = content_info['seriesName']
+ CurrentHeigh = str(video_height)
+ VideoOutputName = folderdownloader + '\\' + str(content_info['folderName']) + '\\' + str(CurrentName) + ' [' + str(CurrentHeigh) + 'p].mkv'
+ else:
+ CurrentName = content_info['seriesName']
+ CurrentHeigh = str(video_height)
+ VideoOutputName = folderdownloader + '\\' + str(CurrentName) + '\\' + ' [' + str(CurrentHeigh) + 'p].mkv'
+
+ if args.onlykeys:
+ keys_all = get_keys(drm_info, pssh)
+ with open(keys_file, 'a', encoding='utf8') as (file):
+ file.write(CurrentName + '\n')
+ print('\n' + CurrentName)
+ for key in keys_all:
+ with open(keys_file, 'a', encoding='utf8') as (file):
+ file.write(key + '\n')
+ print(key)
+
+ else:
+
+ if not args.novideo or (not args.noaudio):
+ print("\nGetting KEYS...")
+
+ try:
+ keys_all = get_keys(drm_info, pssh)
+ except KeyError:
+ print('License request failed, using keys from txt')
+ keys_all = keys_file_txt
+ else:
+ with open(keys_file, "a", encoding="utf8") as file:
+ file.write(CurrentName + "\n")
+ for key in keys_all:
+ with open(keys_file, "a", encoding="utf8") as file:
+ file.write(key + "\n")
+ print("Done!")
+
+ if not os.path.isfile(VideoOutputName):
+
+ if not args.novideo:
+ inputVideo = CurrentName + ' [' + str(CurrentHeigh) + 'p].mp4'
+ if os.path.isfile(inputVideo):
+ print('\n' + inputVideo + '\nFile has already been successfully downloaded previously.\n')
+ else:
+ wvdl_cfg = WvDownloaderConfig(xml, base_url, inputVideo, video_track_id, video_format_id)
+ wvdownloader = WvDownloader(wvdl_cfg)
+ wvdownloader.run()
+
+ if not args.noaudio:
+ for x in audio_list:
+ langAbbrev = x['Language']
+ format_id = x['ID']
+ inputAudio = CurrentName + ' ' + '(' + langAbbrev + ').mp4'
+ inputAudio_demuxed = CurrentName + ' ' + '(' + langAbbrev + ')' + '.m4a'
+ if os.path.isfile(inputAudio) or os.path.isfile(inputAudio_demuxed):
+ print('\n' + inputAudio + '\nFile has already been successfully downloaded previously.\n')
+ else:
+ wvdl_cfg = WvDownloaderConfig(xml, base_url, inputAudio, x['TID'], x['ID'])
+ wvdownloader = WvDownloader(wvdl_cfg)
+ wvdownloader.run()
+
+ CorrectDecryptVideo = False
+ if not args.novideo:
+ inputVideo = CurrentName + ' [' + str(CurrentHeigh) + 'p].mp4'
+ if os.path.isfile(inputVideo):
+ CorrectDecryptVideo = DecryptVideo(inputVideo=inputVideo, keys_video=keys_all)
+ else:
+ CorrectDecryptVideo = True
+
+ CorrectDecryptAudio = False
+ if not args.noaudio:
+ for x in audio_list:
+ langAbbrev = x['Language']
+ inputAudio = CurrentName + ' ' + '(' + langAbbrev + ')' + '.mp4'
+ if os.path.isfile(inputAudio):
+ CorrectDecryptAudio = DecryptAudio(inputAudio=inputAudio, keys_audio=keys_all)
+ else:
+ CorrectDecryptAudio = True
+
+ if not args.nomux:
+ if not args.novideo:
+ if not args.noaudio:
+ if CorrectDecryptVideo == True:
+ if CorrectDecryptAudio == True:
+ print('\nMuxing...')
+
+ pmnpType = content_info['pmnpType']
+ folderName = content_info['folderName']
+
+ if pmnpType=="show":
+ MKV_Muxer=Muxer(CurrentName=CurrentName,
+ SeasonFolder=folderName,
+ CurrentHeigh=CurrentHeigh,
+ Type=pmnpType,
+ mkvmergeexe=pmnp_cfg.MKVMERGE)
+
+ else:
+ MKV_Muxer=Muxer(CurrentName=CurrentName,
+ SeasonFolder=None,
+ CurrentHeigh=CurrentHeigh,
+ Type=pmnpType,
+ mkvmergeexe=pmnp_cfg.MKVMERGE)
+
+ MKV_Muxer.mkvmerge_muxer(lang="English")
+
+ if args.tag:
+ inputName = CurrentName + ' [' + CurrentHeigh + 'p].mkv'
+ release_group(base_filename=inputName,
+ default_filename=CurrentName,
+ folder_name=folderName,
+ type=pmnpType,
+ video_height=CurrentHeigh)
+
+ if not args.keep:
+ for f in os.listdir():
+ if re.fullmatch(re.escape(CurrentName) + r'.*\.(mp4|m4a|h264|h265|eac3|srt|txt|avs|lwi|mpd)', f):
+ os.remove(f)
+ print("Done!")
+ else:
+ print("\nFile '" + str(VideoOutputName) + "' already exists.")
+
+ def release_group(base_filename, default_filename, folder_name, type, video_height):
+ if type=='show':
+ video_mkv = os.path.join(folder_name, base_filename)
+ else:
+ video_mkv = base_filename
+
+ mediainfo = mediainfo_(video_mkv)
+ for v in mediainfo['media']['track']: # mediainfo do video
+ if v['@type'] == 'Video':
+ video_format = v['Format']
+
+ video_codec = ''
+ if video_format == "AVC":
+ video_codec = 'H.264'
+ elif video_format == "HEVC":
+ video_codec = 'H.265'
+
+ for m in mediainfo['media']['track']: # mediainfo do audio
+ if m['@type'] == 'Audio':
+ codec_name = m['Format']
+ channels_number = m['Channels']
+
+ audio_codec = ''
+ audio_channels = ''
+ if codec_name == "AAC":
+ audio_codec = 'AAC'
+ elif codec_name == "AC-3":
+ audio_codec = "DD"
+ elif codec_name == "E-AC-3":
+ audio_codec = "DDP"
+ elif codec_name == "E-AC-3 JOC":
+ audio_codec = "ATMOS"
+
+ if channels_number == "2":
+ audio_channels = "2.0"
+ elif channels_number == "6":
+ audio_channels = "5.1"
+
+ audio_ = audio_codec + audio_channels
+
+ # renomear arquivo
+ default_filename = default_filename.replace('&', '.and.')
+ default_filename = re.sub(r'[]!"#$%\'()*+,:;<=>?@\\^_`{|}~[-]', '', default_filename)
+ default_filename = default_filename.replace(' ', '.')
+ default_filename = re.sub(r'\.{2,}', '.', default_filename)
+ default_filename = unidecode(default_filename)
+
+ output_name = '{}.{}p.PMNP.WEB-DL.{}.{}-{}'.format(default_filename, video_height, audio_, video_codec, args.tag)
+ if type=='show':
+ outputName = os.path.join(folder_name, output_name + '.mkv')
+ else:
+ outputName = output_name + '.mkv'
+
+ os.rename(video_mkv, outputName)
+ print("{} -> {}".format(base_filename, output_name))
+
+ from pywidevine.decrypt.wvdecryptcustom import WvDecrypt
+ from pywidevine.cdm import cdm, deviceconfig
+
+ def do_decrypt(init_data_b64, cert_data_b64, device, licurl, licheader):
+ wvdecrypt = WvDecrypt(init_data_b64=init_data_b64, cert_data_b64=cert_data_b64, device=deviceconfig.device_android_generic)
+ chal = wvdecrypt.get_challenge()
+ headers = {
+ 'authorization': licheader
+ }
+
+ try:
+ license_res = requests.Session().post(url=licurl, data=chal, headers=headers, proxies=proxy_cfg.get_proxy('meta'))
+ license_base64 = base64.b64encode(license_res.content)
+ except Exception:
+ print(license_res.text)
+ license_base64 = "Error"
+ return license_base64
+ if license_base64 != 'Error':
+ wvdecrypt.update_license(license_base64)
+ wvdecrypt.start_process()
+ Correct, keyswvdecrypt = wvdecrypt.start_process()
+ return Correct, keyswvdecrypt
+ else:
+ keyswvdecrypt = []
+ Correct = True
+ return Correct, keyswvdecrypt
+
+ def get_keys(lic_info, pssh):
+ Correct = False
+ keys_new = []
+ device = deviceconfig.DeviceConfig(deviceconfig.device_android_generic)
+ while Correct is False:
+ Correct, keys_new = do_decrypt(init_data_b64=bytes(pssh.encode()), cert_data_b64=None, device=device, licurl=lic_info['license'], licheader=lic_info['lic_header'])
+ return keys_new
+
+ def DecryptAudio(inputAudio, keys_audio):
+ key_audio_id_original = getKeyId(inputAudio)
+ outputAudioTemp = inputAudio.replace(".mp4", "_dec.mp4")
+ if key_audio_id_original != "nothing":
+ for key in keys_audio:
+ key_id=key[0:32]
+ if key_id == key_audio_id_original:
+ print("\nDecrypting audio...")
+ print ("Using KEY: " + key)
+ wvdecrypt_process = subprocess.Popen([pmnp_cfg.MP4DECRYPT, "--show-progress", "--key", key, inputAudio, outputAudioTemp])
+ stdoutdata, stderrdata = wvdecrypt_process.communicate()
+ wvdecrypt_process.wait()
+ time.sleep (50.0/1000.0)
+ os.remove(inputAudio)
+ print("\nDemuxing audio...")
+ mediainfo = MediaInfo.parse(outputAudioTemp)
+ audio_info = next(x for x in mediainfo.tracks if x.track_type == "Audio")
+ codec_name = audio_info.format
+
+ ext = ''
+ if codec_name == "AAC":
+ ext = '.m4a'
+ elif codec_name == "E-AC-3":
+ ext = ".eac3"
+ elif codec_name == "AC-3":
+ ext = ".ac3"
+ outputAudio = outputAudioTemp.replace("_dec.mp4", ext)
+ print("{} -> {}".format(outputAudioTemp, outputAudio))
+ ff = ffmpy.FFmpeg(executable=pmnp_cfg.FFMPEG, inputs={outputAudioTemp: None}, outputs={outputAudio: '-c copy'}, global_options="-y -hide_banner -loglevel warning")
+ ff.run()
+ time.sleep (50.0/1000.0)
+ os.remove(outputAudioTemp)
+ print("Done!")
+ return True
+
+ elif key_audio_id_original == "nothing":
+ return True
+
+ def DecryptVideo(inputVideo, keys_video):
+ key_video_id_original = getKeyId(inputVideo)
+ inputVideo = inputVideo
+ outputVideoTemp = inputVideo.replace('.mp4', '_dec.mp4')
+ outputVideo = inputVideo
+ if key_video_id_original != 'nothing':
+ for key in keys_video:
+ key_id = key[0:32]
+ if key_id == key_video_id_original:
+ print('\nDecrypting video...')
+ print('Using KEY: ' + key)
+ wvdecrypt_process = subprocess.Popen([pmnp_cfg.MP4DECRYPT, '--show-progress', '--key', key, inputVideo, outputVideoTemp])
+ stdoutdata, stderrdata = wvdecrypt_process.communicate()
+ wvdecrypt_process.wait()
+ print('\nRemuxing video...')
+ ff = ffmpy.FFmpeg(executable=pmnp_cfg.FFMPEG, inputs={outputVideoTemp: None}, outputs={outputVideo: '-c copy'}, global_options='-y -hide_banner -loglevel warning')
+ ff.run()
+ time.sleep(0.05)
+ os.remove(outputVideoTemp)
+ print('Done!')
+ return True
+
+ elif key_video_id_original == 'nothing':
+ return True
+
+ def DemuxAudio(inputAudio):
+ if os.path.isfile(inputAudio):
+ print('\nDemuxing audio...')
+ mediainfo = mediainfo_(inputAudio)
+ for m in mediainfo['media']['track']:
+ if m['@type'] == 'Audio':
+ codec_name = m['Format']
+ try:
+ codec_tag_string = m['Format_Commercial_IfAny']
+ except Exception:
+ codec_tag_string = ''
+
+ ext = ''
+ if codec_name == 'AAC':
+ ext = '.m4a'
+ else:
+ if codec_name == 'E-AC-3':
+ ext = '.eac3'
+ else:
+ if codec_name == 'AC-3':
+ ext = '.ac3'
+ outputAudio = inputAudio.replace('.mp4', ext)
+ print('{} -> {}'.format(inputAudio, outputAudio))
+ ff = ffmpy.FFmpeg(executable=pmnp_cfg.FFMPEG,
+ inputs={inputAudio: None},
+ outputs={outputAudio: '-c copy'},
+ global_options='-y -hide_banner -loglevel warning')
+ ff.run()
+ time.sleep(0.05)
+ os.remove(inputAudio)
+ print('Done!')
+
+ get_content_info()
diff --git a/paramountplus_original.py b/paramountplus_original.py
new file mode 100644
index 0000000..24423aa
--- /dev/null
+++ b/paramountplus_original.py
@@ -0,0 +1,789 @@
+# -*- coding: utf-8 -*-
+# Module: Paramount Plus Downloader
+# Created on: 19-02-2021
+# Authors: JUNi
+# Version: 2.0
+
+import urllib.parse
+import re, base64, requests, sys, os
+import subprocess, shutil
+import xmltodict, isodate
+import json, ffmpy
+import http, html, time
+
+from unidecode import unidecode
+from http.cookiejar import MozillaCookieJar
+from titlecase import titlecase
+
+from pywidevine.clients.proxy_config import ProxyConfig
+from pywidevine.muxer.muxer import Muxer
+
+from pywidevine.clients.paramountplus.downloader import WvDownloader
+from pywidevine.clients.paramountplus.config import WvDownloaderConfig
+
+
+currentFile = 'paramountplus'
+realPath = os.path.realpath(currentFile)
+dirPath = os.path.dirname(realPath)
+USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36'
+SESSION = requests.Session()
+
+def main(args):
+ global _id
+
+ mp4decryptexe = "mp4decrypt"
+ mp4dumptexe = "mp4dump"
+ ffmpegpath = "ffmpeg"
+ mkvmergeexe = "mkvmerge"
+ MediaInfo_exe = shutil.which("mediainfo") or shutil.which("MediaInfo")
+
+ proxies = {}
+ proxy_meta = args.proxy
+ if proxy_meta == 'none':
+ proxies['meta'] = {'http': None, 'https': None}
+ elif proxy_meta:
+ proxies['meta'] = {'http': proxy_meta, 'https': proxy_meta}
+ SESSION.proxies = proxies.get('meta')
+ proxy_cfg = ProxyConfig(proxies)
+
+ if not os.path.exists(dirPath + '/KEYS'):
+ os.makedirs(dirPath + '/KEYS')
+ else:
+ keys_file = dirPath + '/KEYS/PARAMOUNTPLUS.txt'
+ try:
+ keys_file_pmnp = open(keys_file, 'r')
+ keys_file_txt = keys_file_pmnp.readlines()
+ except Exception:
+ with open(keys_file, 'a', encoding='utf8') as (file):
+ file.write('##### One KEY per line. #####\n')
+ keys_file_pmnp = open(keys_file, 'r', encoding='utf8')
+ keys_file_txt = keys_file_pmnp.readlines()
+
+ def alphanumericSort(l):
+ def convert(text):
+ if text.isdigit():
+ return int(text)
+ else:
+ return text
+
+ def alphanum_key(key):
+ return [convert(c) for c in re.split('([0-9]+)', key)]
+
+ return sorted(l, key=alphanum_key)
+
+ def convert_size(size_bytes):
+ if size_bytes == 0:
+ return '0bps'
+ else:
+ s = round(size_bytes / 1000, 0)
+ return '%ikbps' % s
+
+ def get_size(size):
+ power = 1024
+ n = 0
+ Dic_powerN = {0:'', 1:'K', 2:'M', 3:'G', 4:'T'}
+ while size > power:
+ size /= power
+ n += 1
+ return str(round(size, 2)) + Dic_powerN[n] + 'B'
+
+ def getKeyId(name):
+ mp4dump = subprocess.Popen([mp4dumptexe, name], stdout=(subprocess.PIPE))
+ mp4dump = str(mp4dump.stdout.read())
+ A = find_str(mp4dump, 'default_KID')
+ KEY_ID_ORI = ''
+ KEY_ID_ORI = mp4dump[A:A + 63].replace('default_KID = ', '').replace('[', '').replace(']', '').replace(' ', '')
+ if KEY_ID_ORI == '' or KEY_ID_ORI == "'":
+ KEY_ID_ORI = 'nothing'
+ return KEY_ID_ORI
+
+ def find_str(s, char):
+ index = 0
+ if char in s:
+ c = char[0]
+ for ch in s:
+ if ch == c:
+ if s[index:index + len(char)] == char:
+ return index
+ index += 1
+
+ return -1
+
+ def mediainfo_(file):
+ mediainfo_output = subprocess.Popen([MediaInfo_exe, '--Output=JSON', '-f', file], stdout=(subprocess.PIPE))
+ mediainfo_json = json.load(mediainfo_output.stdout)
+ return mediainfo_json
+
+ def ReplaceDontLikeWord(X):
+ try:
+ X = X.replace(" : ", " - ").replace(": ", " - ").replace(":", " - ").replace("&", "and").replace("+", "").replace(";", "").replace("ó", "o").\
+ replace("[", "").replace("'", "").replace("]", "").replace("/", "").replace("//", "").\
+ replace("’", "'").replace("*", "x").replace("<", "").replace(">", "").replace("|", "").\
+ replace("~", "").replace("#", "").replace("%", "").replace("{", "").replace("}", "").replace(",", "").\
+ replace("?","").replace("¿","")
+ except Exception:
+ X = X.replace(" : ", " - ").replace(": ", " - ").replace(":", " - ").replace("&", "and").replace("+", "").replace(";", "").\
+ replace("ó", "o").replace("[", "").replace("'", "").replace("]", "").replace("/", "").\
+ replace("//", "").replace("’", "'").replace("*", "x").replace("<", "").replace(">", "").replace("|", "").\
+ replace("~", "").replace("#", "").replace("%", "").replace("{", "").replace("}", "").replace(",", "").\
+ replace("?","").replace("¿","")
+
+ return titlecase(X)
+
+ def replace_code_lang(X):
+ X = X.lower()
+ X = X.replace('es-mx', 'es-la').replace('pt-BR', 'pt-br').replace('dolby digital', 'en').replace('dd+', 'en')
+ return X
+
+ def get_cookies(file_path):
+ try:
+ cj = http.cookiejar.MozillaCookieJar(file_path)
+ cj.load()
+ except Exception:
+ print('\nCookies not found! Please dump the cookies with the Chrome extension https://chrome.google.com/webstore/detail/cookiestxt/njabckikapfpffapmjgojcnbfjonfjfg and place the generated file in ' + file_path)
+ print('\nWarning, do not click on "download all cookies", you have to click on "click here".\n')
+ sys.exit(0)
+
+ cookies = str()
+ for cookie in cj:
+ cookie.value = urllib.parse.unquote(html.unescape(cookie.value))
+ cookies = cookies + cookie.name + '=' + cookie.value + ';'
+
+ cookies = list(cookies)
+ del cookies[-1]
+ cookies = ''.join(cookies)
+ return cookies
+
+ cookies_file = 'cookies_pmnp.txt'
+ cookies = get_cookies(dirPath + '/cookies/' + cookies_file)
+ pmnp_headers = {
+ 'Accept':'application/json, text/plain, */*',
+ 'Access-Control-Allow-Origin':'*',
+ 'cookie':cookies,
+ 'User-Agent':USER_AGENT
+ }
+
+ def mpd_parsing(mpd_url):
+ base_url = mpd_url.split('stream.mpd')[0]
+ r = SESSION.get(url=mpd_url)
+ r.raise_for_status()
+ xml = xmltodict.parse(r.text)
+ mpdf = json.loads(json.dumps(xml))
+ length = isodate.parse_duration(mpdf['MPD']['@mediaPresentationDuration']).total_seconds()
+ tracks = mpdf['MPD']['Period']['AdaptationSet']
+
+ def get_pssh(track):
+ pssh = ''
+ for t in track["ContentProtection"]:
+ if t['@schemeIdUri'].lower() == 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed':
+ pssh = t["cenc:pssh"]
+ return pssh
+
+ def force_instance(x):
+ if isinstance(x['Representation'], list):
+ X = x['Representation']
+ else:
+ X = [x['Representation']]
+ return X
+
+ video_list = []
+ for video_tracks in tracks:
+ if video_tracks['@contentType'] == 'video':
+ pssh = get_pssh(video_tracks)
+ for x in force_instance(video_tracks):
+ try:
+ codecs = x['@codecs']
+ except (KeyError, TypeError):
+ codecs = video_tracks['@codecs']
+ video_dict = {
+ 'Height':x['@height'],
+ 'Width':x['@width'],
+ 'Bandwidth':x['@bandwidth'],
+ 'ID':x['@id'],
+ 'TID':video_tracks['@id'],
+ 'Codec':codecs}
+ video_list.append(video_dict)
+
+ video_list = sorted(video_list, key=(lambda k: int(k['Bandwidth'])))
+
+ while args.customquality != [] and int(video_list[(-1)]['Height']) > int(args.customquality[0]):
+ video_list.pop(-1)
+
+ audio_list = []
+ for audio_tracks in tracks:
+ if audio_tracks['@contentType'] == 'audio':
+ for x in force_instance(audio_tracks):
+ try:
+ codecs = x['@codecs']
+ except (KeyError, TypeError):
+ codecs = audio_tracks['@codecs']
+ audio_dict = {
+ 'Bandwidth':x['@bandwidth'],
+ 'ID':audio_tracks['@id'],
+ 'TID':audio_tracks['@id'],
+ 'Language':replace_code_lang(audio_tracks['@lang']),
+ 'Codec':codecs}
+ audio_list.append(audio_dict)
+
+ audio_list = sorted(audio_list, key=(lambda k: (int(k['Bandwidth']), str(k['Language']))), reverse=True)
+ if args.only_2ch_audio:
+ c = 0
+ while c != len(audio_list):
+ if '-3' in audio_list[c]['Codec'].split('=')[0]:
+ audio_list.remove(audio_list[c])
+ else:
+ c += 1
+
+ BitrateList = []
+ AudioLanguageList = []
+ for x in audio_list:
+ BitrateList.append(x['Bandwidth'])
+ AudioLanguageList.append(x['Language'])
+
+ BitrateList = alphanumericSort(list(set(BitrateList)))
+ AudioLanguageList = alphanumericSort(list(set(AudioLanguageList)))
+ audioList_new = []
+ audio_Dict_new = {}
+ for y in AudioLanguageList:
+ counter = 0
+ for x in audio_list:
+ if x['Language'] == y and counter == 0:
+ audio_Dict_new = {
+ 'Language':x['Language'],
+ 'Bandwidth':x['Bandwidth'],
+ 'Codec': x['Codec'],
+ 'TID':x['TID'],
+ 'ID':x['ID']}
+ audioList_new.append(audio_Dict_new)
+ counter = counter + 1
+
+ audioList = audioList_new
+ audio_list = sorted(audioList, key=(lambda k: (int(k['Bandwidth']), str(k['Language']))))
+
+ audioList_new = []
+ if args.audiolang:
+ for x in audio_list:
+ langAbbrev = x['Language']
+ if langAbbrev in list(args.audiolang):
+ audioList_new.append(x)
+ audio_list = audioList_new
+
+ return base_url, length, video_list, audio_list, pssh, xml
+
+ def get_episodes(ep_str, num_eps):
+ eps = ep_str.split(',')
+ eps_final = []
+
+ for ep in eps:
+ if '-' in ep:
+ (start, end) = ep.split('-')
+ start = int(start)
+ end = int(end or num_eps)
+ eps_final += list(range(start, end + 1))
+ else:
+ eps_final.append(int(ep))
+
+ return eps_final
+
+ _id = args.url_season.split('/')[-2]
+ if '/video/' in args.url_season:
+ content_regex = r'(\/shows\/)([\w-]+)(\/video\/)([\w-]+)'
+ url_match = re.search(content_regex, args.url_season)
+ _id = url_match[2]
+
+ def get_content_info():
+ if 'shows' in args.url_season:
+ pmnp_season_url = 'https://www.paramountplus.com/shows/{}/xhr/episodes/page/0/size/100/xs/0/season/{}/'.format(_id, '')
+ season_req = requests.get(url=pmnp_season_url, headers=pmnp_headers, proxies=proxy_cfg.get_proxy('meta'))
+
+ if not args.season:
+ args.season = 'all'
+
+ seasons = []
+ if args.season:
+ if args.season == 'all':
+ seasons = 'all'
+ elif ',' in args.season:
+ seasons = [int(x) for x in args.season.split(',')]
+ elif '-' in args.season:
+ (start, end) = args.season.split('-')
+ seasons = list(range(int(start), int(end) + 1))
+ else:
+ seasons = [int(args.season)]
+
+ if seasons == 'all':
+ seasons_list = [x['season_number'] for x in season_req.json()['result']['data']]
+ seasons = sorted(set(seasons_list))
+
+ for season_num in seasons:
+ pmnp_season_url = 'https://www.paramountplus.com/shows/{}/xhr/episodes/page/0/size/500/xs/0/season/{}/'.format(_id, season_num)
+ season_req = requests.get(url=pmnp_season_url, headers=pmnp_headers, proxies=proxy_cfg.get_proxy('meta'))
+ if season_req.json()['result']['total'] < 1:
+ print('This season doesnt exist!')
+ exit()
+
+ for num, ep in enumerate(season_req.json()['result']['data'], start=1):
+ episodeNumber = ep['episode_number']
+ seasonNumber = ep['season_number']
+ seriesTitle = ReplaceDontLikeWord(ep['series_title'])
+ episodeTitle = ReplaceDontLikeWord(ep['label'])
+ seriesName = f'{seriesTitle} S{seasonNumber:0>2}E{episodeNumber:0>2} - {episodeTitle}'
+ folderName = f'{seriesTitle} S{seasonNumber:0>2}'
+ raw_url = urllib.parse.urljoin('https://www.paramountplus.com', ep['metaData']['contentUrl'])
+
+ episodes_list_new = []
+ episodes_dict = {
+ 'id': ep['content_id'],
+ 'raw_url': raw_url,
+ 'pid':ep['metaData']['pid'],
+ 'seriesName':seriesName,
+ 'folderName':folderName,
+ 'episodeNumber': num,
+ 'seasonNumber':seasonNumber,
+ 'pmnpType': 'show'}
+ episodes_list_new.append(episodes_dict)
+ episodes_list = []
+ for x in episodes_list_new:
+ episodes_list.append(x)
+ #episodes_list = sorted(episodes_list, key=lambda x: x['episodeNumber'])
+
+ if args.episodeStart:
+ eps = get_episodes(args.episodeStart, len(episodes_list))
+ episodes_list = [x for x in episodes_list if x['episodeNumber'] in eps]
+
+ if 'video' in args.url_season:
+ episodes_list = [x for x in episodes_list if x['id'] in url_match.group(4)]
+
+ for content_json in episodes_list:
+ start_process(content_json)
+
+ if 'movies' in args.url_season:
+ while 1:
+ resp = requests.get(url=args.url_season + '/', headers=pmnp_headers, proxies=proxy_cfg.get_proxy('meta'))
+ if resp.ok:
+ break
+
+ html_data = resp
+ html_data = html_data.text.replace('\r\n', '').replace('\n', '').replace('\r', '').replace('\t', '').replace(' ', '')
+ html_data_list = re.split('()(?i)', html_data)
+ json_web = []
+ for div in html_data_list:
+ if 'player.paramsVO.adCallParams' in div:
+ print()
+ rg = re.compile('(player.metaData = )(.*)(;player.tms_program_id)')
+ m = rg.search(div)
+ if m:
+ json_web = m.group(2)
+ json_web = json.loads(json_web)
+
+ content_dict = {}
+ episodes_list = []
+ year_regex = r'(\d{4})'
+ movieTitle = ReplaceDontLikeWord(json_web['seriesTitle'])
+ try:
+ r = re.search(year_regex, json_web['airdate'])
+ except KeyError:
+ r = re.search(year_regex, json_web['airdate_tv'])
+ seriesName = f'{movieTitle} ({r.group(0)})'
+
+ content_dict = {
+ 'id':json_web['contentId'],
+ 'raw_url': str(args.url_season),
+ 'pid': json_web['pid'],
+ 'seriesName':seriesName,
+ 'folderName':None,
+ 'episodeNumber':1,
+ 'seasonNumber':1,
+ 'pmnpType': 'movie'}
+ episodes_list.append(content_dict)
+
+ for content_json in episodes_list:
+ start_process(content_json)
+
+ def get_license(id_json):
+ while 1:
+ resp = requests.get(url=id_json['raw_url'], headers=pmnp_headers, proxies=proxy_cfg.get_proxy('meta'))
+ if resp.ok:
+ break
+
+ html_data = resp
+ html_data = html_data.text.replace('\r\n', '').replace('\n', '').replace('\r', '').replace('\t', '').replace(' ', '')
+ html_data_list = re.split('()(?i)', html_data)
+ json_web = []
+ for div in html_data_list:
+ if '(!window.CBS.Registry.drmPromise) {' in div:
+ rg = re.compile('(player.drm = )(.*)(;}player.enableCP)')
+ m = rg.search(div)
+ if m:
+ json_web = m.group(2)
+ json_web = json.loads(json_web)
+
+ lic_url = json_web['widevine']['url']
+ header_auth = json_web['widevine']['header']['Authorization']
+ if not lic_url:
+ print('Too many requests...')
+ return lic_url, header_auth
+
+ global folderdownloader
+ if args.output:
+ if not os.path.exists(args.output):
+ os.makedirs(args.output)
+ os.chdir(args.output)
+ if ":" in str(args.output):
+ folderdownloader = str(args.output).replace('/','\\').replace('.\\','\\')
+ else:
+ folderdownloader = dirPath + str(args.output).replace('/','\\').replace('.\\','\\')
+ else:
+ folderdownloader = dirPath.replace('/','\\').replace('.\\','\\')
+
+ def get_manifest(id_json):
+ api_manifest = 'https://link.theplatform.com/s/dJ5BDC/{}?format=SMIL&manifest=m3u&Tracking=true&mbr=true'.format(id_json['pid'])
+ r = requests.get(url=api_manifest, headers=pmnp_headers, proxies=proxy_cfg.get_proxy('meta'))
+ xmls = xmltodict.parse(r.text)
+ smil = json.loads(json.dumps(xmls))
+ videoSrc = []
+ try:
+ for x in smil['smil']['body']['seq']['switch']:
+ videoSrc = x['video']['@src']
+ except Exception:
+ videoSrc = smil['smil']['body']['seq']['switch']['video']['@src']
+ lic_url, header_auth = get_license(id_json)
+ return {'mpd_url': videoSrc, 'license': lic_url, 'lic_header': header_auth}
+
+ def start_process(content_info):
+ drm_info = get_manifest(content_info)
+ base_url, length, video_list, audio_list, pssh, xml = mpd_parsing(drm_info['mpd_url'])
+ video_bandwidth = dict(video_list[(-1)])['Bandwidth']
+ video_height = str(dict(video_list[(-1)])['Height'])
+ video_width = str(dict(video_list[(-1)])['Width'])
+ video_codec = str(dict(video_list[(-1)])['Codec'])
+ video_format_id = str(dict(video_list[(-1)])['ID'])
+ video_track_id = str(dict(video_list[(-1)])['TID'])
+ if not args.onlykeys:
+ if not args.novideo:
+ print('\nVIDEO - Bitrate: ' + convert_size(int(video_bandwidth)) + ' - Profile: ' + video_codec.split('=')[0] + ' - Size: ' + get_size(length * float(video_bandwidth) * 0.125) + ' - Dimensions: ' + video_width + 'x' + video_height)
+ print()
+
+ if not args.noaudio:
+ if audio_list != []:
+ for x in audio_list:
+ audio_bandwidth = x['Bandwidth']
+ audio_representation_id = str(x['Codec'])
+ audio_lang = x['Language']
+ print('AUDIO - Bitrate: ' + convert_size(int(audio_bandwidth)) + ' - Profile: ' + audio_representation_id.split('=')[0] + ' - Size: ' + get_size(length * float(audio_bandwidth) * 0.125) + ' - Language: ' + audio_lang)
+ print()
+
+ print('Name: ' + content_info['seriesName'])
+
+ if content_info['pmnpType'] == 'show':
+ CurrentName = content_info['seriesName']
+ CurrentHeigh = str(video_height)
+ VideoOutputName = folderdownloader + '\\' + str(content_info['folderName']) + '\\' + str(CurrentName) + ' [' + str(CurrentHeigh) + 'p].mkv'
+ else:
+ CurrentName = content_info['seriesName']
+ CurrentHeigh = str(video_height)
+ VideoOutputName = folderdownloader + '\\' + str(CurrentName) + '\\' + ' [' + str(CurrentHeigh) + 'p].mkv'
+
+ if args.onlykeys:
+ keys_all = get_keys(drm_info, pssh)
+ with open(keys_file, 'a', encoding='utf8') as (file):
+ file.write(CurrentName + '\n')
+ print('\n' + CurrentName)
+ for key in keys_all:
+ with open(keys_file, 'a', encoding='utf8') as (file):
+ file.write(key + '\n')
+ print(key)
+
+ else:
+
+ if not args.novideo or (not args.noaudio):
+ print("\nGetting KEYS...")
+
+ try:
+ keys_all = get_keys(drm_info, pssh)
+ except KeyError:
+ print('License request failed, using keys from txt')
+ keys_all = keys_file_txt
+ else:
+ with open(keys_file, "a", encoding="utf8") as file:
+ file.write(CurrentName + "\n")
+ for key in keys_all:
+ with open(keys_file, "a", encoding="utf8") as file:
+ file.write(key + "\n")
+ print("Done!")
+
+ if not os.path.isfile(VideoOutputName):
+
+ if not args.novideo:
+ inputVideo = CurrentName + ' [' + str(CurrentHeigh) + 'p].mp4'
+ if os.path.isfile(inputVideo):
+ print('\n' + inputVideo + '\nFile has already been successfully downloaded previously.\n')
+ else:
+ wvdl_cfg = WvDownloaderConfig(xml, base_url, inputVideo, video_track_id, video_format_id, 'video')
+ wvdownloader = WvDownloader(wvdl_cfg)
+ wvdownloader.run()
+
+ if not args.noaudio:
+ for x in audio_list:
+ langAbbrev = x['Language']
+ format_id = x['ID']
+ inputAudio = CurrentName + ' ' + '(' + langAbbrev + ').mp4'
+ inputAudio_demuxed = CurrentName + ' ' + '(' + langAbbrev + ')' + '.m4a'
+ if os.path.isfile(inputAudio) or os.path.isfile(inputAudio_demuxed):
+ print('\n' + inputAudio + '\nFile has already been successfully downloaded previously.\n')
+ else:
+ wvdl_cfg = WvDownloaderConfig(xml, base_url, inputAudio, x['TID'], x['ID'], 'audio')
+ wvdownloader = WvDownloader(wvdl_cfg)
+ wvdownloader.run()
+
+ CorrectDecryptVideo = False
+ if not args.novideo:
+ inputVideo = CurrentName + ' [' + str(CurrentHeigh) + 'p].mp4'
+ if os.path.isfile(inputVideo):
+ CorrectDecryptVideo = DecryptVideo(inputVideo=inputVideo, keys_video=keys_all)
+ else:
+ CorrectDecryptVideo = True
+
+ CorrectDecryptAudio = False
+ if not args.noaudio:
+ for x in audio_list:
+ langAbbrev = x['Language']
+ inputAudio = CurrentName + ' ' + '(' + langAbbrev + ')' + '.mp4'
+ if os.path.isfile(inputAudio):
+ CorrectDecryptAudio = DecryptAudio(inputAudio=inputAudio, keys_audio=keys_all)
+ else:
+ CorrectDecryptAudio = True
+
+ if not args.nomux:
+ if not args.novideo:
+ if not args.noaudio:
+ if CorrectDecryptVideo == True:
+ if CorrectDecryptAudio == True:
+ print('\nMuxing...')
+
+ pmnpType = content_info['pmnpType']
+ folderName = content_info['folderName']
+
+ if pmnpType=="show":
+ MKV_Muxer=Muxer(CurrentName=CurrentName,
+ SeasonFolder=folderName,
+ CurrentHeigh=CurrentHeigh,
+ Type=pmnpType,
+ mkvmergeexe=mkvmergeexe)
+
+ else:
+ MKV_Muxer=Muxer(CurrentName=CurrentName,
+ SeasonFolder=None,
+ CurrentHeigh=CurrentHeigh,
+ Type=pmnpType,
+ mkvmergeexe=mkvmergeexe)
+
+ MKV_Muxer.mkvmerge_muxer(lang="English")
+
+ if args.tag:
+ inputName = CurrentName + ' [' + CurrentHeigh + 'p].mkv'
+ release_group(base_filename=inputName,
+ default_filename=CurrentName,
+ folder_name=folderName,
+ type=pmnpType,
+ video_height=CurrentHeigh)
+
+ if not args.keep:
+ for f in os.listdir():
+ if re.fullmatch(re.escape(CurrentName) + r'.*\.(mp4|m4a|h264|h265|eac3|srt|txt|avs|lwi|mpd)', f):
+ os.remove(f)
+ print("Done!")
+ else:
+ print("\nFile '" + str(VideoOutputName) + "' already exists.")
+
+ def release_group(base_filename, default_filename, folder_name, type, video_height):
+ if type=='show':
+ video_mkv = os.path.join(folder_name, base_filename)
+ else:
+ video_mkv = base_filename
+
+ mediainfo = mediainfo_(video_mkv)
+ for v in mediainfo['media']['track']: # mediainfo do video
+ if v['@type'] == 'Video':
+ video_format = v['Format']
+
+ video_codec = ''
+ if video_format == "AVC":
+ video_codec = 'H.264'
+ elif video_format == "HEVC":
+ video_codec = 'H.265'
+
+ for m in mediainfo['media']['track']: # mediainfo do audio
+ if m['@type'] == 'Audio':
+ codec_name = m['Format']
+ channels_number = m['Channels']
+
+ audio_codec = ''
+ audio_channels = ''
+ if codec_name == "AAC":
+ audio_codec = 'AAC'
+ elif codec_name == "AC-3":
+ audio_codec = "DD"
+ elif codec_name == "E-AC-3":
+ audio_codec = "DDP"
+ elif codec_name == "E-AC-3 JOC":
+ audio_codec = "ATMOS"
+
+ if channels_number == "2":
+ audio_channels = "2.0"
+ elif channels_number == "6":
+ audio_channels = "5.1"
+
+ audio_ = audio_codec + audio_channels
+
+ # renomear arquivo
+ default_filename = default_filename.replace('&', '.and.')
+ default_filename = re.sub(r'[]!"#$%\'()*+,:;<=>?@\\^_`{|}~[-]', '', default_filename)
+ default_filename = default_filename.replace(' ', '.')
+ default_filename = re.sub(r'\.{2,}', '.', default_filename)
+ default_filename = unidecode(default_filename)
+
+ output_name = '{}.{}p.PMNP.WEB-DL.{}.{}-{}'.format(default_filename, video_height, audio_, video_codec, args.tag)
+ if type=='show':
+ outputName = os.path.join(folder_name, output_name + '.mkv')
+ else:
+ outputName = output_name + '.mkv'
+
+ os.rename(video_mkv, outputName)
+ print("{} -> {}".format(base_filename, output_name))
+
+ from pywidevine.decrypt.wvdecryptcustom import WvDecrypt
+ from pywidevine.cdm import cdm, deviceconfig
+
+ def do_decrypt(init_data_b64, cert_data_b64, device, licurl, licheader):
+ wvdecrypt = WvDecrypt(init_data_b64=init_data_b64, cert_data_b64=cert_data_b64, device=deviceconfig.device_android_generic)
+ chal = wvdecrypt.get_challenge()
+ headers = {
+ 'authorization': licheader
+ }
+
+ try:
+ license_res = requests.Session().post(url=licurl, data=chal, headers=headers, proxies=proxy_cfg.get_proxy('meta'))
+ license_base64 = base64.b64encode(license_res.content)
+ except Exception:
+ print(license_res.text)
+ license_base64 = "Error"
+ return license_base64
+ if license_base64 != 'Error':
+ wvdecrypt.update_license(license_base64)
+ wvdecrypt.start_process()
+ Correct, keyswvdecrypt = wvdecrypt.start_process()
+ return Correct, keyswvdecrypt
+ else:
+ keyswvdecrypt = []
+ Correct = True
+ return Correct, keyswvdecrypt
+
+ def get_keys(lic_info, pssh):
+ Correct = False
+ keys_new = []
+ device = deviceconfig.device_android_generic
+ while Correct is False:
+ Correct, keys_new = do_decrypt(init_data_b64=bytes(pssh.encode()), cert_data_b64=None, device=device, licurl=lic_info['license'], licheader=lic_info['lic_header'])
+ return keys_new
+
+ def DecryptAudio(inputAudio, keys_audio):
+ key_audio_id_original = getKeyId(inputAudio)
+ outputAudioTemp = inputAudio.replace('.mp4', '_dec.mp4')
+ if key_audio_id_original != 'nothing':
+ for key in keys_audio:
+ key_id = key[0:32]
+ if key_id == key_audio_id_original:
+ print('\nDecrypting audio...')
+ print('Using KEY: ' + key)
+ wvdecrypt_process = subprocess.Popen([mp4decryptexe, '--show-progress', '--key', key, inputAudio, outputAudioTemp])
+ stdoutdata, stderrdata = wvdecrypt_process.communicate()
+ wvdecrypt_process.wait()
+ time.sleep(0.05)
+ os.remove(inputAudio)
+ print('\nDemuxing audio...')
+ mediainfo = mediainfo_(outputAudioTemp)
+ for m in mediainfo['media']['track']:
+ if m['@type'] == 'Audio':
+ codec_name = m['Format']
+ try:
+ codec_tag_string = m['Format_Commercial_IfAny']
+ except Exception:
+ codec_tag_string = ''
+ ext = ''
+ if codec_name == "AAC":
+ ext = '.m4a'
+ elif codec_name == "E-AC-3":
+ ext = ".eac3"
+ elif codec_name == "AC-3":
+ ext = ".ac3"
+ outputAudio = outputAudioTemp.replace("_dec.mp4", ext)
+ print("{} -> {}".format(outputAudioTemp, outputAudio))
+ ff = ffmpy.FFmpeg(executable=ffmpegpath, inputs={outputAudioTemp: None}, outputs={outputAudio: '-c copy'}, global_options="-y -hide_banner -loglevel warning")
+ ff.run()
+ time.sleep (50.0/1000.0)
+ os.remove(outputAudioTemp)
+ print("Done!")
+ return True
+
+ elif key_audio_id_original == "nothing":
+ return True
+
+ def DecryptVideo(inputVideo, keys_video):
+ key_video_id_original = getKeyId(inputVideo)
+ inputVideo = inputVideo
+ outputVideoTemp = inputVideo.replace('.mp4', '_dec.mp4')
+ outputVideo = inputVideo
+ if key_video_id_original != 'nothing':
+ for key in keys_video:
+ key_id = key[0:32]
+ if key_id == key_video_id_original:
+ print('\nDecrypting video...')
+ print('Using KEY: ' + key)
+ wvdecrypt_process = subprocess.Popen([mp4decryptexe, '--show-progress', '--key', key, inputVideo, outputVideoTemp])
+ stdoutdata, stderrdata = wvdecrypt_process.communicate()
+ wvdecrypt_process.wait()
+ print('\nRemuxing video...')
+ ff = ffmpy.FFmpeg(executable=ffmpegpath, inputs={outputVideoTemp: None}, outputs={outputVideo: '-c copy'}, global_options='-y -hide_banner -loglevel warning')
+ ff.run()
+ time.sleep(0.05)
+ os.remove(outputVideoTemp)
+ print('Done!')
+ return True
+
+ elif key_video_id_original == 'nothing':
+ return True
+
+ def DemuxAudio(inputAudio):
+ if os.path.isfile(inputAudio):
+ print('\nDemuxing audio...')
+ mediainfo = mediainfo_(inputAudio)
+ for m in mediainfo['media']['track']:
+ if m['@type'] == 'Audio':
+ codec_name = m['Format']
+ try:
+ codec_tag_string = m['Format_Commercial_IfAny']
+ except Exception:
+ codec_tag_string = ''
+
+ ext = ''
+ if codec_name == 'AAC':
+ ext = '.m4a'
+ else:
+ if codec_name == 'E-AC-3':
+ ext = '.eac3'
+ else:
+ if codec_name == 'AC-3':
+ ext = '.ac3'
+ outputAudio = inputAudio.replace('.mp4', ext)
+ print('{} -> {}'.format(inputAudio, outputAudio))
+ ff = ffmpy.FFmpeg(executable=ffmpegpath,
+ inputs={inputAudio: None},
+ outputs={outputAudio: '-c copy'},
+ global_options='-y -hide_banner -loglevel warning')
+ ff.run()
+ time.sleep(0.05)
+ os.remove(inputAudio)
+ print('Done!')
+
+ get_content_info()
\ No newline at end of file
diff --git a/pywidevine/__init__.py b/pywidevine/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/pywidevine/cdm/__init__.py b/pywidevine/cdm/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/pywidevine/cdm/cdm.py b/pywidevine/cdm/cdm.py
new file mode 100644
index 0000000..ac0e597
--- /dev/null
+++ b/pywidevine/cdm/cdm.py
@@ -0,0 +1,364 @@
+import base64
+
+import os
+import time
+import binascii
+
+from google.protobuf.message import DecodeError
+from google.protobuf import text_format
+
+from pywidevine.cdm.formats import wv_proto2_pb2 as wv_proto2
+from pywidevine.cdm.session import Session
+from pywidevine.cdm.key import Key
+from Cryptodome.Random import get_random_bytes
+from Cryptodome.Random import random
+from Cryptodome.Cipher import PKCS1_OAEP, AES
+from Cryptodome.Hash import CMAC, SHA256, HMAC, SHA1
+from Cryptodome.PublicKey import RSA
+from Cryptodome.Signature import pss
+from Cryptodome.Util import Padding
+import logging
+
+class Cdm:
+ def __init__(self):
+ self.logger = logging.getLogger(__name__)
+ self.sessions = {}
+
+ def open_session(self, init_data_b64, device, raw_init_data = None, offline=False):
+ self.logger.debug("open_session(init_data_b64={}, device={}".format(init_data_b64, device))
+ self.logger.info("opening new cdm session")
+ if device.session_id_type == 'android':
+ # format: 16 random hexdigits, 2 digit counter, 14 0s
+ rand_ascii = ''.join(random.choice('ABCDEF0123456789') for _ in range(16))
+ counter = '01' # this resets regularly so its fine to use 01
+ rest = '00000000000000'
+ session_id = rand_ascii + counter + rest
+ session_id = session_id.encode('ascii')
+ elif device.session_id_type == 'chrome':
+ rand_bytes = get_random_bytes(16)
+ session_id = rand_bytes
+ else:
+ # other formats NYI
+ self.logger.error("device type is unusable")
+ return 1
+ if raw_init_data and isinstance(raw_init_data, (bytes, bytearray)):
+ # used for NF key exchange, where they don't provide a valid PSSH
+ init_data = raw_init_data
+ self.raw_pssh = True
+ else:
+ init_data = self._parse_init_data(init_data_b64)
+ self.raw_pssh = False
+
+ if init_data:
+ new_session = Session(session_id, init_data, device, offline)
+ else:
+ self.logger.error("unable to parse init data")
+ return 1
+ self.sessions[session_id] = new_session
+ self.logger.info("session opened and init data parsed successfully")
+ return session_id
+
+ def _parse_init_data(self, init_data_b64):
+ parsed_init_data = wv_proto2.WidevineCencHeader()
+ try:
+ self.logger.debug("trying to parse init_data directly")
+ parsed_init_data.ParseFromString(base64.b64decode(init_data_b64)[32:])
+ except DecodeError:
+ self.logger.debug("unable to parse as-is, trying with removed pssh box header")
+ try:
+ id_bytes = parsed_init_data.ParseFromString(base64.b64decode(init_data_b64)[32:])
+ except DecodeError:
+ self.logger.error("unable to parse, unsupported init data format")
+ return None
+ self.logger.debug("init_data:")
+ for line in text_format.MessageToString(parsed_init_data).splitlines():
+ self.logger.debug(line)
+ return parsed_init_data
+
+ def close_session(self, session_id):
+ self.logger.debug("close_session(session_id={})".format(session_id))
+ self.logger.info("closing cdm session")
+ if session_id in self.sessions:
+ self.sessions.pop(session_id)
+ self.logger.info("cdm session closed")
+ return 0
+ else:
+ self.logger.info("session {} not found".format(session_id))
+ return 1
+
+ def set_service_certificate(self, session_id, cert_b64):
+ self.logger.debug("set_service_certificate(session_id={}, cert={})".format(session_id, cert_b64))
+ self.logger.info("setting service certificate")
+
+ if session_id not in self.sessions:
+ self.logger.error("session id doesn't exist")
+ return 1
+
+ session = self.sessions[session_id]
+
+ message = wv_proto2.SignedMessage()
+
+ try:
+ message.ParseFromString(base64.b64decode(cert_b64))
+ except DecodeError:
+ self.logger.error("failed to parse cert as SignedMessage")
+
+ service_certificate = wv_proto2.SignedDeviceCertificate()
+
+
+ if message.Type:
+ self.logger.debug("service cert provided as signedmessage")
+ try:
+ service_certificate.ParseFromString(message.Msg)
+
+ except DecodeError:
+ self.logger.error("failed to parse service certificate")
+ return 1
+ else:
+ self.logger.debug("service cert provided as signeddevicecertificate")
+ try:
+ service_certificate.ParseFromString(base64.b64decode(cert_b64))
+ except DecodeError:
+ self.logger.error("failed to parse service certificate")
+ return 1
+
+ self.logger.debug("service certificate:")
+ for line in text_format.MessageToString(service_certificate).splitlines():
+ self.logger.debug(line)
+
+ session.service_certificate = service_certificate
+ session.privacy_mode = True
+
+ return 0
+
+ def get_license_request(self, session_id):
+ self.logger.debug("get_license_request(session_id={})".format(session_id))
+ self.logger.info("getting license request")
+
+ if session_id not in self.sessions:
+ self.logger.error("session ID does not exist")
+ return 1
+
+ session = self.sessions[session_id]
+
+ # raw pssh will be treated as bytes and not parsed
+ if self.raw_pssh:
+ license_request = wv_proto2.SignedLicenseRequestRaw()
+ else:
+ license_request = wv_proto2.SignedLicenseRequest()
+ client_id = wv_proto2.ClientIdentification()
+
+ if not os.path.exists(session.device_config.device_client_id_blob_filename):
+ self.logger.error("no client ID blob available for this device")
+ return 1
+
+ with open(session.device_config.device_client_id_blob_filename, "rb") as f:
+ try:
+ cid_bytes = client_id.ParseFromString(f.read())
+ except DecodeError:
+ self.logger.error("client id failed to parse as protobuf")
+ return 1
+
+ self.logger.debug("building license request")
+ if not self.raw_pssh:
+ license_request.Type = wv_proto2.SignedLicenseRequest.MessageType.Value('LICENSE_REQUEST')
+ license_request.Msg.ContentId.CencId.Pssh.CopyFrom(session.init_data)
+ else:
+ license_request.Type = wv_proto2.SignedLicenseRequestRaw.MessageType.Value('LICENSE_REQUEST')
+ license_request.Msg.ContentId.CencId.Pssh = session.init_data # bytes
+
+ if session.offline:
+ license_type = wv_proto2.LicenseType.Value('OFFLINE')
+ else:
+ license_type = wv_proto2.LicenseType.Value('DEFAULT')
+ license_request.Msg.ContentId.CencId.LicenseType = license_type
+ license_request.Msg.ContentId.CencId.RequestId = session_id
+ license_request.Msg.Type = wv_proto2.LicenseRequest.RequestType.Value('NEW')
+ license_request.Msg.RequestTime = int(time.time())
+ license_request.Msg.ProtocolVersion = wv_proto2.ProtocolVersion.Value('CURRENT')
+ if session.device_config.send_key_control_nonce:
+ license_request.Msg.KeyControlNonce = random.randrange(1, 2**31)
+
+ if session.privacy_mode:
+ if session.device_config.vmp:
+ self.logger.debug("vmp required, adding to client_id")
+ self.logger.debug("reading vmp hashes")
+ vmp_hashes = wv_proto2.FileHashes()
+ with open(session.device_config.device_vmp_blob_filename, "rb") as f:
+ try:
+ vmp_bytes = vmp_hashes.ParseFromString(f.read())
+ except DecodeError:
+ self.logger.error("vmp hashes failed to parse as protobuf")
+ return 1
+ client_id._FileHashes.CopyFrom(vmp_hashes)
+ self.logger.debug("privacy mode & service certificate loaded, encrypting client id")
+ self.logger.debug("unencrypted client id:")
+ for line in text_format.MessageToString(client_id).splitlines():
+ self.logger.debug(line)
+ cid_aes_key = get_random_bytes(16)
+ cid_iv = get_random_bytes(16)
+
+ cid_cipher = AES.new(cid_aes_key, AES.MODE_CBC, cid_iv)
+
+ encrypted_client_id = cid_cipher.encrypt(Padding.pad(client_id.SerializeToString(), 16))
+
+ service_public_key = RSA.importKey(session.service_certificate._DeviceCertificate.PublicKey)
+
+ service_cipher = PKCS1_OAEP.new(service_public_key)
+
+ encrypted_cid_key = service_cipher.encrypt(cid_aes_key)
+
+ encrypted_client_id_proto = wv_proto2.EncryptedClientIdentification()
+
+ encrypted_client_id_proto.ServiceId = session.service_certificate._DeviceCertificate.ServiceId
+ encrypted_client_id_proto.ServiceCertificateSerialNumber = session.service_certificate._DeviceCertificate.SerialNumber
+ encrypted_client_id_proto.EncryptedClientId = encrypted_client_id
+ encrypted_client_id_proto.EncryptedClientIdIv = cid_iv
+ encrypted_client_id_proto.EncryptedPrivacyKey = encrypted_cid_key
+
+ license_request.Msg.EncryptedClientId.CopyFrom(encrypted_client_id_proto)
+ else:
+ license_request.Msg.ClientId.CopyFrom(client_id)
+
+ if session.device_config.private_key_available:
+ key = RSA.importKey(open(session.device_config.device_private_key_filename).read())
+ session.device_key = key
+ else:
+ self.logger.error("need device private key, other methods unimplemented")
+ return 1
+
+ self.logger.debug("signing license request")
+
+ hash = SHA1.new(license_request.Msg.SerializeToString())
+ signature = pss.new(key).sign(hash)
+
+ license_request.Signature = signature
+
+ session.license_request = license_request
+
+ self.logger.debug("license request:")
+ for line in text_format.MessageToString(session.license_request).splitlines():
+ self.logger.debug(line)
+ self.logger.info("license request created")
+ self.logger.debug("license request b64: {}".format(base64.b64encode(license_request.SerializeToString())))
+ return license_request.SerializeToString()
+
+ def provide_license(self, session_id, license_b64):
+ self.logger.debug("provide_license(session_id={}, license_b64={})".format(session_id, license_b64))
+ self.logger.info("decrypting provided license")
+
+ if session_id not in self.sessions:
+ self.logger.error("session does not exist")
+ return 1
+
+ session = self.sessions[session_id]
+
+ if not session.license_request:
+ self.logger.error("generate a license request first!")
+ return 1
+
+ license = wv_proto2.SignedLicense()
+ try:
+ license.ParseFromString(base64.b64decode(license_b64))
+ except DecodeError:
+ self.logger.error("unable to parse license - check protobufs")
+ return 1
+
+ session.license = license
+
+ self.logger.debug("license:")
+ for line in text_format.MessageToString(license).splitlines():
+ self.logger.debug(line)
+
+ self.logger.debug("deriving keys from session key")
+
+ oaep_cipher = PKCS1_OAEP.new(session.device_key)
+
+ session.session_key = oaep_cipher.decrypt(license.SessionKey)
+
+ lic_req_msg = session.license_request.Msg.SerializeToString()
+
+ enc_key_base = b"ENCRYPTION\000" + lic_req_msg + b"\0\0\0\x80"
+ auth_key_base = b"AUTHENTICATION\0" + lic_req_msg + b"\0\0\2\0"
+
+ enc_key = b"\x01" + enc_key_base
+ auth_key_1 = b"\x01" + auth_key_base
+ auth_key_2 = b"\x02" + auth_key_base
+ auth_key_3 = b"\x03" + auth_key_base
+ auth_key_4 = b"\x04" + auth_key_base
+
+ cmac_obj = CMAC.new(session.session_key, ciphermod=AES)
+ cmac_obj.update(enc_key)
+
+ enc_cmac_key = cmac_obj.digest()
+
+ cmac_obj = CMAC.new(session.session_key, ciphermod=AES)
+ cmac_obj.update(auth_key_1)
+ auth_cmac_key_1 = cmac_obj.digest()
+
+ cmac_obj = CMAC.new(session.session_key, ciphermod=AES)
+ cmac_obj.update(auth_key_2)
+ auth_cmac_key_2 = cmac_obj.digest()
+
+ cmac_obj = CMAC.new(session.session_key, ciphermod=AES)
+ cmac_obj.update(auth_key_3)
+ auth_cmac_key_3 = cmac_obj.digest()
+
+ cmac_obj = CMAC.new(session.session_key, ciphermod=AES)
+ cmac_obj.update(auth_key_4)
+ auth_cmac_key_4 = cmac_obj.digest()
+
+ auth_cmac_combined_1 = auth_cmac_key_1 + auth_cmac_key_2
+ auth_cmac_combined_2 = auth_cmac_key_3 + auth_cmac_key_4
+
+ session.derived_keys['enc'] = enc_cmac_key
+ session.derived_keys['auth_1'] = auth_cmac_combined_1
+ session.derived_keys['auth_2'] = auth_cmac_combined_2
+
+ self.logger.debug('verifying license signature')
+
+ lic_hmac = HMAC.new(session.derived_keys['auth_1'], digestmod=SHA256)
+ lic_hmac.update(license.Msg.SerializeToString())
+
+ self.logger.debug("calculated sig: {} actual sig: {}".format(lic_hmac.hexdigest(), binascii.hexlify(license.Signature)))
+
+ if lic_hmac.digest() != license.Signature:
+ self.logger.info("license signature doesn't match - writing bin so they can be debugged")
+ with open("original_lic.bin", "wb") as f:
+ f.write(base64.b64decode(license_b64))
+ with open("parsed_lic.bin", "wb") as f:
+ f.write(license.SerializeToString())
+ self.logger.info("continuing anyway")
+
+ self.logger.debug("key count: {}".format(len(license.Msg.Key)))
+ for key in license.Msg.Key:
+ if key.Id:
+ key_id = key.Id
+ else:
+ key_id = wv_proto2.License.KeyContainer.KeyType.Name(key.Type).encode('utf-8')
+ encrypted_key = key.Key
+ iv = key.Iv
+ type = wv_proto2.License.KeyContainer.KeyType.Name(key.Type)
+
+ cipher = AES.new(session.derived_keys['enc'], AES.MODE_CBC, iv=iv)
+ decrypted_key = cipher.decrypt(encrypted_key)
+ if type == "OPERATOR_SESSION":
+ permissions = []
+ perms = key._OperatorSessionKeyPermissions
+ for (descriptor, value) in perms.ListFields():
+ if value == 1:
+ permissions.append(descriptor.name)
+ print(permissions)
+ else:
+ permissions = []
+ session.keys.append(Key(key_id, type, Padding.unpad(decrypted_key, 16), permissions))
+
+ self.logger.info("decrypted all keys")
+ return 0
+
+ def get_keys(self, session_id):
+ if session_id in self.sessions:
+ return self.sessions[session_id].keys
+ else:
+ self.logger.error("session not found")
+ return 1
diff --git a/pywidevine/cdm/deviceconfig.py b/pywidevine/cdm/deviceconfig.py
new file mode 100644
index 0000000..981adae
--- /dev/null
+++ b/pywidevine/cdm/deviceconfig.py
@@ -0,0 +1,53 @@
+import os
+
+device_android_generic = {
+ 'name': 'android_generic',
+ 'description': 'android generic l3',
+ 'security_level': 3,
+ 'session_id_type': 'android',
+ 'private_key_available': True,
+ 'vmp': False,
+ 'send_key_control_nonce': True
+}
+
+devices_available = [device_android_generic]
+
+FILES_FOLDER = 'devices'
+
+class DeviceConfig:
+ def __init__(self, device):
+ self.device_name = device['name']
+ self.description = device['description']
+ self.security_level = device['security_level']
+ self.session_id_type = device['session_id_type']
+ self.private_key_available = device['private_key_available']
+ self.vmp = device['vmp']
+ self.send_key_control_nonce = device['send_key_control_nonce']
+
+ if 'keybox_filename' in device:
+ self.keybox_filename = os.path.join(os.path.dirname(__file__), FILES_FOLDER, device['name'], device['keybox_filename'])
+ else:
+ self.keybox_filename = os.path.join(os.path.dirname(__file__), FILES_FOLDER, device['name'], 'keybox')
+
+ if 'device_cert_filename' in device:
+ self.device_cert_filename = os.path.join(os.path.dirname(__file__), FILES_FOLDER, device['name'], device['device_cert_filename'])
+ else:
+ self.device_cert_filename = os.path.join(os.path.dirname(__file__), FILES_FOLDER, device['name'], 'device_cert')
+
+ if 'device_private_key_filename' in device:
+ self.device_private_key_filename = os.path.join(os.path.dirname(__file__), FILES_FOLDER, device['name'], device['device_private_key_filename'])
+ else:
+ self.device_private_key_filename = os.path.join(os.path.dirname(__file__), FILES_FOLDER, device['name'], 'device_private_key')
+
+ if 'device_client_id_blob_filename' in device:
+ self.device_client_id_blob_filename = os.path.join(os.path.dirname(__file__), FILES_FOLDER, device['name'], device['device_client_id_blob_filename'])
+ else:
+ self.device_client_id_blob_filename = os.path.join(os.path.dirname(__file__), FILES_FOLDER, device['name'], 'device_client_id_blob')
+
+ if 'device_vmp_blob_filename' in device:
+ self.device_vmp_blob_filename = os.path.join(os.path.dirname(__file__), FILES_FOLDER, device['name'], device['device_vmp_blob_filename'])
+ else:
+ self.device_vmp_blob_filename = os.path.join(os.path.dirname(__file__), FILES_FOLDER, device['name'], 'device_vmp_blob')
+
+ def __repr__(self):
+ return "DeviceConfig(name={}, description={}, security_level={}, session_id_type={}, private_key_available={}, vmp={})".format(self.device_name, self.description, self.security_level, self.session_id_type, self.private_key_available, self.vmp)
diff --git a/pywidevine/cdm/devices/android_generic/device_client_id_blob b/pywidevine/cdm/devices/android_generic/device_client_id_blob
new file mode 100644
index 0000000..cc32780
Binary files /dev/null and b/pywidevine/cdm/devices/android_generic/device_client_id_blob differ
diff --git a/pywidevine/cdm/devices/android_generic/device_private_key b/pywidevine/cdm/devices/android_generic/device_private_key
new file mode 100644
index 0000000..8eab693
--- /dev/null
+++ b/pywidevine/cdm/devices/android_generic/device_private_key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEA4sUKDpvMG/idF8oCH5AVSwFd5Mk+rEwOBsLZMYdliXWe1hn9
+mdE6u9pjsr+bLrZjlKxMFqPPxbIUcC1Ii7BFSje2Fd8kxnaIprQWxDPgK+NSSx7v
+Un452TyB1L9lx39ZBt0PlRfwjkCodX+I9y+oBga73NRh7hPbtLzXe/r/ubFBaEu+
+aRkDZBwYPqHgH1RoFLuyFNMjfqGcPosGxceDtvPysmBxB93Hk2evml5fjdYGg6tx
+z510g+XFPDFv7GSy1KuWqit83MqzPls9qAQMkwUc05ggjDhGCKW4/p97fn23WDFE
+3TzSSsQvyJLKA3s9oJbtJCD/gOHYqDvnWn8zPwIDAQABAoIBAQDCWe1Mp+o+7sx0
+XwWC15HoPruiIXg9YtGCqexLrqcvMEd5Z70Z32BfL8TSpbTyTA78lM6BeNPRs9Yg
+bi8GyYQZH7ZG+IAkN+LWPPJmJa+y7ZjSGSkzoksiC+GZ3I/2cwZyA3Qfa+0XfgLi
+8PMKJyXyREMt+DgWO57JQC/OakhRdCR19mM6NKd+ynd/IEz/NIbjMLDVKwW8HEPx
+N3r5CU9O96nr62DI68KVj3jwUR3cDi/5xfhosYhCQjHJuobNbeFR18dY2nQNLWYd
+S0wtskla1fl9eYHwYAzwru4wHT4WJC7+V4pscfCI0YZB6PslxDKrv73l5H1tz4cf
+Vy58NRSBAoGBAPSmjoVtQzTvQ6PZIs81SF1ulJI9kUpyFaBoSSgt+2ZkeNtF6Hih
+Zm7OVJ9wg9sfjpB3SFBUjuhXz/ts/t6dkA2PgCbrvhBMRKSGbfyhhtM2gRf002I4
+bJ7Y0C/ont4WzC/XbXEkAmh+fG2/JRvbdVQaIdyS6MmVHtCtRsHEQZS5AoGBAO1K
+IXOKAFA+320+Hkbqskfevmxrv+JHIdetliaREZwQH+VYUUM8u5/Kt3oyMat+mH90
+rZOKQK2zM8cz4tKclTUT54nrtICxeo6UHVc56FqXZ6sVvVgm8Cnvt1md4XwG4FwQ
+r/OlaM6Hr5HRf8dkzuzqm4ZQYRHGzZ6AMphj8Xu3AoGAdmo7p5dIJVH98kuCDrsi
+iJ6iaNpF/buUfiyb5EfFXD0bRj7jE6hDdTSHPxjtqVzv2zrxFHipJwqBz5dlEYlA
+FWA0ziHiv+66dsveZp4kLQ0/lMHaorre0E/vDJFSe/qa4DksbsvYIo2+WjxfkMk7
+U/bGFwZAiHmWDbkg+16rw3kCgYEAyyodWf9eJVavlakJ404vNrnP8KSQtfyRTUii
+toKewTBNHuBvM1JckoPOdCFlxZ+ukfIka56DojU8r+IM4qaOWdOg+sWE1mses9S9
+CmHaPzZC3IjQhRlRp5ZHNcOnu7lnf2wKOmH1Sl+CQydMcDwvr0lvv6AyfDXq9zps
+F2365CECgYEAmYgs/qwnh9m0aGDw/ZGrASoE0TxlpizPvsVDGx9t9UGC2Z+5QvAE
+ZcQeKoLCbktr0BnRLI+W1g+KpXQGcnSF9VX/qwUlf72XA6C6kobQvW+Yd/H/IN5d
+jPqoL/m41rRzm+J+9/Tfc8Aiy1kkllUYnVJdC5QLAIswuhI8lkaFTN4=
+-----END RSA PRIVATE KEY-----
diff --git a/pywidevine/cdm/formats/__init__.py b/pywidevine/cdm/formats/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/pywidevine/cdm/formats/__pycache__/__init__.cpython-37.pyc b/pywidevine/cdm/formats/__pycache__/__init__.cpython-37.pyc
new file mode 100644
index 0000000..1106698
Binary files /dev/null and b/pywidevine/cdm/formats/__pycache__/__init__.cpython-37.pyc differ
diff --git a/pywidevine/cdm/formats/__pycache__/__init__.cpython-38.pyc b/pywidevine/cdm/formats/__pycache__/__init__.cpython-38.pyc
new file mode 100644
index 0000000..8bbdeb3
Binary files /dev/null and b/pywidevine/cdm/formats/__pycache__/__init__.cpython-38.pyc differ
diff --git a/pywidevine/cdm/formats/__pycache__/wv_proto2_pb2.cpython-37.pyc b/pywidevine/cdm/formats/__pycache__/wv_proto2_pb2.cpython-37.pyc
new file mode 100644
index 0000000..7c01ee9
Binary files /dev/null and b/pywidevine/cdm/formats/__pycache__/wv_proto2_pb2.cpython-37.pyc differ
diff --git a/pywidevine/cdm/formats/__pycache__/wv_proto2_pb2.cpython-38.pyc b/pywidevine/cdm/formats/__pycache__/wv_proto2_pb2.cpython-38.pyc
new file mode 100644
index 0000000..84af63f
Binary files /dev/null and b/pywidevine/cdm/formats/__pycache__/wv_proto2_pb2.cpython-38.pyc differ
diff --git a/pywidevine/cdm/formats/wv_proto2.proto b/pywidevine/cdm/formats/wv_proto2.proto
new file mode 100644
index 0000000..04c9809
--- /dev/null
+++ b/pywidevine/cdm/formats/wv_proto2.proto
@@ -0,0 +1,466 @@
+syntax = "proto2";
+
+// from x86 (partial), most of it from the ARM version:
+message ClientIdentification {
+ enum TokenType {
+ KEYBOX = 0;
+ DEVICE_CERTIFICATE = 1;
+ REMOTE_ATTESTATION_CERTIFICATE = 2;
+ }
+ message NameValue {
+ required string Name = 1;
+ required string Value = 2;
+ }
+ message ClientCapabilities {
+ enum HdcpVersion {
+ HDCP_NONE = 0;
+ HDCP_V1 = 1;
+ HDCP_V2 = 2;
+ HDCP_V2_1 = 3;
+ HDCP_V2_2 = 4;
+ }
+ optional uint32 ClientToken = 1;
+ optional uint32 SessionToken = 2;
+ optional uint32 VideoResolutionConstraints = 3;
+ optional HdcpVersion MaxHdcpVersion = 4;
+ optional uint32 OemCryptoApiVersion = 5;
+ }
+ required TokenType Type = 1;
+ //optional bytes Token = 2; // by default the client treats this as blob, but it's usually a DeviceCertificate, so for usefulness sake, I'm replacing it with this one:
+ optional SignedDeviceCertificate Token = 2; // use this when parsing, "bytes" when building a client id blob
+ repeated NameValue ClientInfo = 3;
+ optional bytes ProviderClientToken = 4;
+ optional uint32 LicenseCounter = 5;
+ optional ClientCapabilities _ClientCapabilities = 6; // how should we deal with duped names? will have to look at proto docs later
+ optional FileHashes _FileHashes = 7; // vmp blob goes here
+}
+
+message DeviceCertificate {
+ enum CertificateType {
+ ROOT = 0;
+ INTERMEDIATE = 1;
+ USER_DEVICE = 2;
+ SERVICE = 3;
+ }
+ required CertificateType Type = 1; // the compiled code reused this as ProvisionedDeviceInfo.WvSecurityLevel, however that is incorrect (compiler aliased it as they're both identical as a structure)
+ optional bytes SerialNumber = 2;
+ optional uint32 CreationTimeSeconds = 3;
+ optional bytes PublicKey = 4;
+ optional uint32 SystemId = 5;
+ optional uint32 TestDeviceDeprecated = 6; // is it bool or int?
+ optional bytes ServiceId = 7; // service URL for service certificates
+}
+
+// missing some references,
+message DeviceCertificateStatus {
+ enum CertificateStatus {
+ VALID = 0;
+ REVOKED = 1;
+ }
+ optional bytes SerialNumber = 1;
+ optional CertificateStatus Status = 2;
+ optional ProvisionedDeviceInfo DeviceInfo = 4; // where is 3? is it deprecated?
+}
+
+message DeviceCertificateStatusList {
+ optional uint32 CreationTimeSeconds = 1;
+ repeated DeviceCertificateStatus CertificateStatus = 2;
+}
+
+message EncryptedClientIdentification {
+ required string ServiceId = 1;
+ optional bytes ServiceCertificateSerialNumber = 2;
+ required bytes EncryptedClientId = 3;
+ required bytes EncryptedClientIdIv = 4;
+ required bytes EncryptedPrivacyKey = 5;
+}
+
+// todo: fill (for this top-level type, it might be impossible/difficult)
+enum LicenseType {
+ ZERO = 0;
+ DEFAULT = 1; // 1 is STREAMING/temporary license; on recent versions may go up to 3 (latest x86); it might be persist/don't persist type, unconfirmed
+ OFFLINE = 2;
+}
+
+// todo: fill (for this top-level type, it might be impossible/difficult)
+// this is just a guess because these globals got lost, but really, do we need more?
+enum ProtocolVersion {
+ CURRENT = 21; // don't have symbols for this
+}
+
+
+message LicenseIdentification {
+ optional bytes RequestId = 1;
+ optional bytes SessionId = 2;
+ optional bytes PurchaseId = 3;
+ optional LicenseType Type = 4;
+ optional uint32 Version = 5;
+ optional bytes ProviderSessionToken = 6;
+}
+
+
+message License {
+ message Policy {
+ optional bool CanPlay = 1; // changed from uint32 to bool
+ optional bool CanPersist = 2;
+ optional bool CanRenew = 3;
+ optional uint32 RentalDurationSeconds = 4;
+ optional uint32 PlaybackDurationSeconds = 5;
+ optional uint32 LicenseDurationSeconds = 6;
+ optional uint32 RenewalRecoveryDurationSeconds = 7;
+ optional string RenewalServerUrl = 8;
+ optional uint32 RenewalDelaySeconds = 9;
+ optional uint32 RenewalRetryIntervalSeconds = 10;
+ optional bool RenewWithUsage = 11; // was uint32
+ }
+ message KeyContainer {
+ enum KeyType {
+ SIGNING = 1;
+ CONTENT = 2;
+ KEY_CONTROL = 3;
+ OPERATOR_SESSION = 4;
+ }
+ enum SecurityLevel {
+ SW_SECURE_CRYPTO = 1;
+ SW_SECURE_DECODE = 2;
+ HW_SECURE_CRYPTO = 3;
+ HW_SECURE_DECODE = 4;
+ HW_SECURE_ALL = 5;
+ }
+ message OutputProtection {
+ enum CGMS {
+ COPY_FREE = 0;
+ COPY_ONCE = 2;
+ COPY_NEVER = 3;
+ CGMS_NONE = 0x2A; // PC default!
+ }
+ optional ClientIdentification.ClientCapabilities.HdcpVersion Hdcp = 1; // it's most likely a copy of Hdcp version available here, but compiler optimized it away
+ optional CGMS CgmsFlags = 2;
+ }
+ message KeyControl {
+ required bytes KeyControlBlock = 1; // what is this?
+ required bytes Iv = 2;
+ }
+ message OperatorSessionKeyPermissions {
+ optional uint32 AllowEncrypt = 1;
+ optional uint32 AllowDecrypt = 2;
+ optional uint32 AllowSign = 3;
+ optional uint32 AllowSignatureVerify = 4;
+ }
+ message VideoResolutionConstraint {
+ optional uint32 MinResolutionPixels = 1;
+ optional uint32 MaxResolutionPixels = 2;
+ optional OutputProtection RequiredProtection = 3;
+ }
+ optional bytes Id = 1;
+ optional bytes Iv = 2;
+ optional bytes Key = 3;
+ optional KeyType Type = 4;
+ optional SecurityLevel Level = 5;
+ optional OutputProtection RequiredProtection = 6;
+ optional OutputProtection RequestedProtection = 7;
+ optional KeyControl _KeyControl = 8; // duped names, etc
+ optional OperatorSessionKeyPermissions _OperatorSessionKeyPermissions = 9; // duped names, etc
+ repeated VideoResolutionConstraint VideoResolutionConstraints = 10;
+ }
+ optional LicenseIdentification Id = 1;
+ optional Policy _Policy = 2; // duped names, etc
+ repeated KeyContainer Key = 3;
+ optional uint32 LicenseStartTime = 4;
+ optional uint32 RemoteAttestationVerified = 5; // bool?
+ optional bytes ProviderClientToken = 6;
+ // there might be more, check with newer versions (I see field 7-8 in a lic)
+ // this appeared in latest x86:
+ optional uint32 ProtectionScheme = 7; // type unconfirmed fully, but it's likely as WidevineCencHeader describesit (fourcc)
+}
+
+message LicenseError {
+ enum Error {
+ INVALID_DEVICE_CERTIFICATE = 1;
+ REVOKED_DEVICE_CERTIFICATE = 2;
+ SERVICE_UNAVAILABLE = 3;
+ }
+ //LicenseRequest.RequestType ErrorCode; // clang mismatch
+ optional Error ErrorCode = 1;
+}
+
+message LicenseRequest {
+ message ContentIdentification {
+ message CENC {
+ //optional bytes Pssh = 1; // the client's definition is opaque, it doesn't care about the contents, but the PSSH has a clear definition that is understood and requested by the server, thus I'll replace it with:
+ optional WidevineCencHeader Pssh = 1;
+ optional LicenseType LicenseType = 2; // unfortunately the LicenseType symbols are not present, acceptable value seems to only be 1 (is this persist/don't persist? look into it!)
+ optional bytes RequestId = 3;
+ }
+ message WebM {
+ optional bytes Header = 1; // identical to CENC, aside from PSSH and the parent field number used
+ optional LicenseType LicenseType = 2;
+ optional bytes RequestId = 3;
+ }
+ message ExistingLicense {
+ optional LicenseIdentification LicenseId = 1;
+ optional uint32 SecondsSinceStarted = 2;
+ optional uint32 SecondsSinceLastPlayed = 3;
+ optional bytes SessionUsageTableEntry = 4; // interesting! try to figure out the connection between the usage table blob and KCB!
+ }
+ optional CENC CencId = 1;
+ optional WebM WebmId = 2;
+ optional ExistingLicense License = 3;
+ }
+ enum RequestType {
+ NEW = 1;
+ RENEWAL = 2;
+ RELEASE = 3;
+ }
+ optional ClientIdentification ClientId = 1;
+ optional ContentIdentification ContentId = 2;
+ optional RequestType Type = 3;
+ optional uint32 RequestTime = 4;
+ optional bytes KeyControlNonceDeprecated = 5;
+ optional ProtocolVersion ProtocolVersion = 6; // lacking symbols for this
+ optional uint32 KeyControlNonce = 7;
+ optional EncryptedClientIdentification EncryptedClientId = 8;
+}
+
+// raw pssh hack
+message LicenseRequestRaw {
+ message ContentIdentification {
+ message CENC {
+ optional bytes Pssh = 1; // the client's definition is opaque, it doesn't care about the contents, but the PSSH has a clear definition that is understood and requested by the server, thus I'll replace it with:
+ //optional WidevineCencHeader Pssh = 1;
+ optional LicenseType LicenseType = 2; // unfortunately the LicenseType symbols are not present, acceptable value seems to only be 1 (is this persist/don't persist? look into it!)
+ optional bytes RequestId = 3;
+ }
+ message WebM {
+ optional bytes Header = 1; // identical to CENC, aside from PSSH and the parent field number used
+ optional LicenseType LicenseType = 2;
+ optional bytes RequestId = 3;
+ }
+ message ExistingLicense {
+ optional LicenseIdentification LicenseId = 1;
+ optional uint32 SecondsSinceStarted = 2;
+ optional uint32 SecondsSinceLastPlayed = 3;
+ optional bytes SessionUsageTableEntry = 4; // interesting! try to figure out the connection between the usage table blob and KCB!
+ }
+ optional CENC CencId = 1;
+ optional WebM WebmId = 2;
+ optional ExistingLicense License = 3;
+ }
+ enum RequestType {
+ NEW = 1;
+ RENEWAL = 2;
+ RELEASE = 3;
+ }
+ optional ClientIdentification ClientId = 1;
+ optional ContentIdentification ContentId = 2;
+ optional RequestType Type = 3;
+ optional uint32 RequestTime = 4;
+ optional bytes KeyControlNonceDeprecated = 5;
+ optional ProtocolVersion ProtocolVersion = 6; // lacking symbols for this
+ optional uint32 KeyControlNonce = 7;
+ optional EncryptedClientIdentification EncryptedClientId = 8;
+}
+
+
+message ProvisionedDeviceInfo {
+ enum WvSecurityLevel {
+ LEVEL_UNSPECIFIED = 0;
+ LEVEL_1 = 1;
+ LEVEL_2 = 2;
+ LEVEL_3 = 3;
+ }
+ optional uint32 SystemId = 1;
+ optional string Soc = 2;
+ optional string Manufacturer = 3;
+ optional string Model = 4;
+ optional string DeviceType = 5;
+ optional uint32 ModelYear = 6;
+ optional WvSecurityLevel SecurityLevel = 7;
+ optional uint32 TestDevice = 8; // bool?
+}
+
+
+// todo: fill
+message ProvisioningOptions {
+}
+
+// todo: fill
+message ProvisioningRequest {
+}
+
+// todo: fill
+message ProvisioningResponse {
+}
+
+message RemoteAttestation {
+ optional EncryptedClientIdentification Certificate = 1;
+ optional string Salt = 2;
+ optional string Signature = 3;
+}
+
+// todo: fill
+message SessionInit {
+}
+
+// todo: fill
+message SessionState {
+}
+
+// todo: fill
+message SignedCertificateStatusList {
+}
+
+message SignedDeviceCertificate {
+
+ //optional bytes DeviceCertificate = 1; // again, they use a buffer where it's supposed to be a message, so we'll replace it with what it really is:
+ optional DeviceCertificate _DeviceCertificate = 1; // how should we deal with duped names? will have to look at proto docs later
+ optional bytes Signature = 2;
+ optional SignedDeviceCertificate Signer = 3;
+}
+
+
+// todo: fill
+message SignedProvisioningMessage {
+}
+
+// the root of all messages, from either server or client
+message SignedMessage {
+ enum MessageType {
+ LICENSE_REQUEST = 1;
+ LICENSE = 2;
+ ERROR_RESPONSE = 3;
+ SERVICE_CERTIFICATE_REQUEST = 4;
+ SERVICE_CERTIFICATE = 5;
+ }
+ optional MessageType Type = 1; // has in incorrect overlap with License_KeyContainer_SecurityLevel
+ optional bytes Msg = 2; // this has to be casted dynamically, to LicenseRequest, License or LicenseError (? unconfirmed), for Request, no other fields but Type need to be present
+ // for SERVICE_CERTIFICATE, only Type and Msg are present, and it's just a DeviceCertificate with CertificateType set to SERVICE
+ optional bytes Signature = 3; // might be different type of signatures (ex. RSA vs AES CMAC(??), unconfirmed for now)
+ optional bytes SessionKey = 4; // often RSA wrapped for licenses
+ optional RemoteAttestation RemoteAttestation = 5;
+}
+
+
+
+// This message is copied from google's docs, not reversed:
+message WidevineCencHeader {
+ enum Algorithm {
+ UNENCRYPTED = 0;
+ AESCTR = 1;
+ };
+ optional Algorithm algorithm = 1;
+ repeated bytes key_id = 2;
+
+ // Content provider name.
+ optional string provider = 3;
+
+ // A content identifier, specified by content provider.
+ optional bytes content_id = 4;
+
+ // Track type. Acceptable values are SD, HD and AUDIO. Used to
+ // differentiate content keys used by an asset.
+ optional string track_type_deprecated = 5;
+
+ // The name of a registered policy to be used for this asset.
+ optional string policy = 6;
+
+ // Crypto period index, for media using key rotation.
+ optional uint32 crypto_period_index = 7;
+
+ // Optional protected context for group content. The grouped_license is a
+ // serialized SignedMessage.
+ optional bytes grouped_license = 8;
+
+ // Protection scheme identifying the encryption algorithm.
+ // Represented as one of the following 4CC values:
+ // 'cenc' (AESCTR), 'cbc1' (AESCBC),
+ // 'cens' (AESCTR subsample), 'cbcs' (AESCBC subsample).
+ optional uint32 protection_scheme = 9;
+
+ // Optional. For media using key rotation, this represents the duration
+ // of each crypto period in seconds.
+ optional uint32 crypto_period_seconds = 10;
+}
+
+
+// remove these when using it outside of protoc:
+
+// from here on, it's just for testing, these messages don't exist in the binaries, I'm adding them to avoid detecting type programmatically
+message SignedLicenseRequest {
+ enum MessageType {
+ LICENSE_REQUEST = 1;
+ LICENSE = 2;
+ ERROR_RESPONSE = 3;
+ SERVICE_CERTIFICATE_REQUEST = 4;
+ SERVICE_CERTIFICATE = 5;
+ }
+ optional MessageType Type = 1; // has in incorrect overlap with License_KeyContainer_SecurityLevel
+ optional LicenseRequest Msg = 2; // this has to be casted dynamically, to LicenseRequest, License or LicenseError (? unconfirmed), for Request, no other fields but Type need to be present
+ // for SERVICE_CERTIFICATE, only Type and Msg are present, and it's just a DeviceCertificate with CertificateType set to SERVICE
+ optional bytes Signature = 3; // might be different type of signatures (ex. RSA vs AES CMAC(??), unconfirmed for now)
+ optional bytes SessionKey = 4; // often RSA wrapped for licenses
+ optional RemoteAttestation RemoteAttestation = 5;
+}
+
+// hack
+message SignedLicenseRequestRaw {
+ enum MessageType {
+ LICENSE_REQUEST = 1;
+ LICENSE = 2;
+ ERROR_RESPONSE = 3;
+ SERVICE_CERTIFICATE_REQUEST = 4;
+ SERVICE_CERTIFICATE = 5;
+ }
+ optional MessageType Type = 1; // has in incorrect overlap with License_KeyContainer_SecurityLevel
+ optional LicenseRequestRaw Msg = 2; // this has to be casted dynamically, to LicenseRequest, License or LicenseError (? unconfirmed), for Request, no other fields but Type need to be present
+ // for SERVICE_CERTIFICATE, only Type and Msg are present, and it's just a DeviceCertificate with CertificateType set to SERVICE
+ optional bytes Signature = 3; // might be different type of signatures (ex. RSA vs AES CMAC(??), unconfirmed for now)
+ optional bytes SessionKey = 4; // often RSA wrapped for licenses
+ optional RemoteAttestation RemoteAttestation = 5;
+}
+
+
+message SignedLicense {
+ enum MessageType {
+ LICENSE_REQUEST = 1;
+ LICENSE = 2;
+ ERROR_RESPONSE = 3;
+ SERVICE_CERTIFICATE_REQUEST = 4;
+ SERVICE_CERTIFICATE = 5;
+ }
+ optional MessageType Type = 1; // has in incorrect overlap with License_KeyContainer_SecurityLevel
+ optional License Msg = 2; // this has to be casted dynamically, to LicenseRequest, License or LicenseError (? unconfirmed), for Request, no other fields but Type need to be present
+ // for SERVICE_CERTIFICATE, only Type and Msg are present, and it's just a DeviceCertificate with CertificateType set to SERVICE
+ optional bytes Signature = 3; // might be different type of signatures (ex. RSA vs AES CMAC(??), unconfirmed for now)
+ optional bytes SessionKey = 4; // often RSA wrapped for licenses
+ optional RemoteAttestation RemoteAttestation = 5;
+}
+
+message SignedServiceCertificate {
+ enum MessageType {
+ LICENSE_REQUEST = 1;
+ LICENSE = 2;
+ ERROR_RESPONSE = 3;
+ SERVICE_CERTIFICATE_REQUEST = 4;
+ SERVICE_CERTIFICATE = 5;
+ }
+ optional MessageType Type = 1; // has in incorrect overlap with License_KeyContainer_SecurityLevel
+ optional SignedDeviceCertificate Msg = 2; // this has to be casted dynamically, to LicenseRequest, License or LicenseError (? unconfirmed), for Request, no other fields but Type need to be present
+ // for SERVICE_CERTIFICATE, only Type and Msg are present, and it's just a DeviceCertificate with CertificateType set to SERVICE
+ optional bytes Signature = 3; // might be different type of signatures (ex. RSA vs AES CMAC(??), unconfirmed for now)
+ optional bytes SessionKey = 4; // often RSA wrapped for licenses
+ optional RemoteAttestation RemoteAttestation = 5;
+}
+
+//vmp support
+message FileHashes {
+ message Signature {
+ optional string filename = 1;
+ optional bool test_signing = 2; //0 - release, 1 - testing
+ optional bytes SHA512Hash = 3;
+ optional bool main_exe = 4; //0 for dlls, 1 for exe, this is field 3 in file
+ optional bytes signature = 5;
+ }
+ optional bytes signer = 1;
+ repeated Signature signatures = 2;
+}
diff --git a/pywidevine/cdm/formats/wv_proto2_pb2.py b/pywidevine/cdm/formats/wv_proto2_pb2.py
new file mode 100644
index 0000000..4c2a6d1
--- /dev/null
+++ b/pywidevine/cdm/formats/wv_proto2_pb2.py
@@ -0,0 +1,3324 @@
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: pywidevine/cdm/formats/wv_proto2.proto
+
+import sys
+_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
+from google.protobuf.internal import enum_type_wrapper
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import message as _message
+from google.protobuf import reflection as _reflection
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf import descriptor_pb2
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor.FileDescriptor(
+ name='pywidevine/cdm/formats/wv_proto2.proto',
+ package='',
+ syntax='proto2',
+ serialized_pb=_b('\n&pywidevine/cdm/formats/wv_proto2.proto\"\xe7\x05\n\x14\x43lientIdentification\x12-\n\x04Type\x18\x01 \x02(\x0e\x32\x1f.ClientIdentification.TokenType\x12\'\n\x05Token\x18\x02 \x01(\x0b\x32\x18.SignedDeviceCertificate\x12\x33\n\nClientInfo\x18\x03 \x03(\x0b\x32\x1f.ClientIdentification.NameValue\x12\x1b\n\x13ProviderClientToken\x18\x04 \x01(\x0c\x12\x16\n\x0eLicenseCounter\x18\x05 \x01(\r\x12\x45\n\x13_ClientCapabilities\x18\x06 \x01(\x0b\x32(.ClientIdentification.ClientCapabilities\x12 \n\x0b_FileHashes\x18\x07 \x01(\x0b\x32\x0b.FileHashes\x1a(\n\tNameValue\x12\x0c\n\x04Name\x18\x01 \x02(\t\x12\r\n\x05Value\x18\x02 \x02(\t\x1a\xa4\x02\n\x12\x43lientCapabilities\x12\x13\n\x0b\x43lientToken\x18\x01 \x01(\r\x12\x14\n\x0cSessionToken\x18\x02 \x01(\r\x12\"\n\x1aVideoResolutionConstraints\x18\x03 \x01(\r\x12L\n\x0eMaxHdcpVersion\x18\x04 \x01(\x0e\x32\x34.ClientIdentification.ClientCapabilities.HdcpVersion\x12\x1b\n\x13OemCryptoApiVersion\x18\x05 \x01(\r\"T\n\x0bHdcpVersion\x12\r\n\tHDCP_NONE\x10\x00\x12\x0b\n\x07HDCP_V1\x10\x01\x12\x0b\n\x07HDCP_V2\x10\x02\x12\r\n\tHDCP_V2_1\x10\x03\x12\r\n\tHDCP_V2_2\x10\x04\"S\n\tTokenType\x12\n\n\x06KEYBOX\x10\x00\x12\x16\n\x12\x44\x45VICE_CERTIFICATE\x10\x01\x12\"\n\x1eREMOTE_ATTESTATION_CERTIFICATE\x10\x02\"\x9b\x02\n\x11\x44\x65viceCertificate\x12\x30\n\x04Type\x18\x01 \x02(\x0e\x32\".DeviceCertificate.CertificateType\x12\x14\n\x0cSerialNumber\x18\x02 \x01(\x0c\x12\x1b\n\x13\x43reationTimeSeconds\x18\x03 \x01(\r\x12\x11\n\tPublicKey\x18\x04 \x01(\x0c\x12\x10\n\x08SystemId\x18\x05 \x01(\r\x12\x1c\n\x14TestDeviceDeprecated\x18\x06 \x01(\r\x12\x11\n\tServiceId\x18\x07 \x01(\x0c\"K\n\x0f\x43\x65rtificateType\x12\x08\n\x04ROOT\x10\x00\x12\x10\n\x0cINTERMEDIATE\x10\x01\x12\x0f\n\x0bUSER_DEVICE\x10\x02\x12\x0b\n\x07SERVICE\x10\x03\"\xc4\x01\n\x17\x44\x65viceCertificateStatus\x12\x14\n\x0cSerialNumber\x18\x01 \x01(\x0c\x12:\n\x06Status\x18\x02 \x01(\x0e\x32*.DeviceCertificateStatus.CertificateStatus\x12*\n\nDeviceInfo\x18\x04 \x01(\x0b\x32\x16.ProvisionedDeviceInfo\"+\n\x11\x43\x65rtificateStatus\x12\t\n\x05VALID\x10\x00\x12\x0b\n\x07REVOKED\x10\x01\"o\n\x1b\x44\x65viceCertificateStatusList\x12\x1b\n\x13\x43reationTimeSeconds\x18\x01 \x01(\r\x12\x33\n\x11\x43\x65rtificateStatus\x18\x02 \x03(\x0b\x32\x18.DeviceCertificateStatus\"\xaf\x01\n\x1d\x45ncryptedClientIdentification\x12\x11\n\tServiceId\x18\x01 \x02(\t\x12&\n\x1eServiceCertificateSerialNumber\x18\x02 \x01(\x0c\x12\x19\n\x11\x45ncryptedClientId\x18\x03 \x02(\x0c\x12\x1b\n\x13\x45ncryptedClientIdIv\x18\x04 \x02(\x0c\x12\x1b\n\x13\x45ncryptedPrivacyKey\x18\x05 \x02(\x0c\"\x9c\x01\n\x15LicenseIdentification\x12\x11\n\tRequestId\x18\x01 \x01(\x0c\x12\x11\n\tSessionId\x18\x02 \x01(\x0c\x12\x12\n\nPurchaseId\x18\x03 \x01(\x0c\x12\x1a\n\x04Type\x18\x04 \x01(\x0e\x32\x0c.LicenseType\x12\x0f\n\x07Version\x18\x05 \x01(\r\x12\x1c\n\x14ProviderSessionToken\x18\x06 \x01(\x0c\"\xa1\x0e\n\x07License\x12\"\n\x02Id\x18\x01 \x01(\x0b\x32\x16.LicenseIdentification\x12 \n\x07_Policy\x18\x02 \x01(\x0b\x32\x0f.License.Policy\x12\"\n\x03Key\x18\x03 \x03(\x0b\x32\x15.License.KeyContainer\x12\x18\n\x10LicenseStartTime\x18\x04 \x01(\r\x12!\n\x19RemoteAttestationVerified\x18\x05 \x01(\r\x12\x1b\n\x13ProviderClientToken\x18\x06 \x01(\x0c\x12\x18\n\x10ProtectionScheme\x18\x07 \x01(\r\x1a\xbb\x02\n\x06Policy\x12\x0f\n\x07\x43\x61nPlay\x18\x01 \x01(\x08\x12\x12\n\nCanPersist\x18\x02 \x01(\x08\x12\x10\n\x08\x43\x61nRenew\x18\x03 \x01(\x08\x12\x1d\n\x15RentalDurationSeconds\x18\x04 \x01(\r\x12\x1f\n\x17PlaybackDurationSeconds\x18\x05 \x01(\r\x12\x1e\n\x16LicenseDurationSeconds\x18\x06 \x01(\r\x12&\n\x1eRenewalRecoveryDurationSeconds\x18\x07 \x01(\r\x12\x18\n\x10RenewalServerUrl\x18\x08 \x01(\t\x12\x1b\n\x13RenewalDelaySeconds\x18\t \x01(\r\x12#\n\x1bRenewalRetryIntervalSeconds\x18\n \x01(\r\x12\x16\n\x0eRenewWithUsage\x18\x0b \x01(\x08\x1a\xf9\t\n\x0cKeyContainer\x12\n\n\x02Id\x18\x01 \x01(\x0c\x12\n\n\x02Iv\x18\x02 \x01(\x0c\x12\x0b\n\x03Key\x18\x03 \x01(\x0c\x12+\n\x04Type\x18\x04 \x01(\x0e\x32\x1d.License.KeyContainer.KeyType\x12\x32\n\x05Level\x18\x05 \x01(\x0e\x32#.License.KeyContainer.SecurityLevel\x12\x42\n\x12RequiredProtection\x18\x06 \x01(\x0b\x32&.License.KeyContainer.OutputProtection\x12\x43\n\x13RequestedProtection\x18\x07 \x01(\x0b\x32&.License.KeyContainer.OutputProtection\x12\x35\n\x0b_KeyControl\x18\x08 \x01(\x0b\x32 .License.KeyContainer.KeyControl\x12[\n\x1e_OperatorSessionKeyPermissions\x18\t \x01(\x0b\x32\x33.License.KeyContainer.OperatorSessionKeyPermissions\x12S\n\x1aVideoResolutionConstraints\x18\n \x03(\x0b\x32/.License.KeyContainer.VideoResolutionConstraint\x1a\xdb\x01\n\x10OutputProtection\x12\x42\n\x04Hdcp\x18\x01 \x01(\x0e\x32\x34.ClientIdentification.ClientCapabilities.HdcpVersion\x12>\n\tCgmsFlags\x18\x02 \x01(\x0e\x32+.License.KeyContainer.OutputProtection.CGMS\"C\n\x04\x43GMS\x12\r\n\tCOPY_FREE\x10\x00\x12\r\n\tCOPY_ONCE\x10\x02\x12\x0e\n\nCOPY_NEVER\x10\x03\x12\r\n\tCGMS_NONE\x10*\x1a\x31\n\nKeyControl\x12\x17\n\x0fKeyControlBlock\x18\x01 \x02(\x0c\x12\n\n\x02Iv\x18\x02 \x02(\x0c\x1a|\n\x1dOperatorSessionKeyPermissions\x12\x14\n\x0c\x41llowEncrypt\x18\x01 \x01(\r\x12\x14\n\x0c\x41llowDecrypt\x18\x02 \x01(\r\x12\x11\n\tAllowSign\x18\x03 \x01(\r\x12\x1c\n\x14\x41llowSignatureVerify\x18\x04 \x01(\r\x1a\x99\x01\n\x19VideoResolutionConstraint\x12\x1b\n\x13MinResolutionPixels\x18\x01 \x01(\r\x12\x1b\n\x13MaxResolutionPixels\x18\x02 \x01(\r\x12\x42\n\x12RequiredProtection\x18\x03 \x01(\x0b\x32&.License.KeyContainer.OutputProtection\"J\n\x07KeyType\x12\x0b\n\x07SIGNING\x10\x01\x12\x0b\n\x07\x43ONTENT\x10\x02\x12\x0f\n\x0bKEY_CONTROL\x10\x03\x12\x14\n\x10OPERATOR_SESSION\x10\x04\"z\n\rSecurityLevel\x12\x14\n\x10SW_SECURE_CRYPTO\x10\x01\x12\x14\n\x10SW_SECURE_DECODE\x10\x02\x12\x14\n\x10HW_SECURE_CRYPTO\x10\x03\x12\x14\n\x10HW_SECURE_DECODE\x10\x04\x12\x11\n\rHW_SECURE_ALL\x10\x05\"\x98\x01\n\x0cLicenseError\x12&\n\tErrorCode\x18\x01 \x01(\x0e\x32\x13.LicenseError.Error\"`\n\x05\x45rror\x12\x1e\n\x1aINVALID_DEVICE_CERTIFICATE\x10\x01\x12\x1e\n\x1aREVOKED_DEVICE_CERTIFICATE\x10\x02\x12\x17\n\x13SERVICE_UNAVAILABLE\x10\x03\"\xac\x07\n\x0eLicenseRequest\x12\'\n\x08\x43lientId\x18\x01 \x01(\x0b\x32\x15.ClientIdentification\x12\x38\n\tContentId\x18\x02 \x01(\x0b\x32%.LicenseRequest.ContentIdentification\x12)\n\x04Type\x18\x03 \x01(\x0e\x32\x1b.LicenseRequest.RequestType\x12\x13\n\x0bRequestTime\x18\x04 \x01(\r\x12!\n\x19KeyControlNonceDeprecated\x18\x05 \x01(\x0c\x12)\n\x0fProtocolVersion\x18\x06 \x01(\x0e\x32\x10.ProtocolVersion\x12\x17\n\x0fKeyControlNonce\x18\x07 \x01(\r\x12\x39\n\x11\x45ncryptedClientId\x18\x08 \x01(\x0b\x32\x1e.EncryptedClientIdentification\x1a\xa2\x04\n\x15\x43ontentIdentification\x12:\n\x06\x43\x65ncId\x18\x01 \x01(\x0b\x32*.LicenseRequest.ContentIdentification.CENC\x12:\n\x06WebmId\x18\x02 \x01(\x0b\x32*.LicenseRequest.ContentIdentification.WebM\x12\x46\n\x07License\x18\x03 \x01(\x0b\x32\x35.LicenseRequest.ContentIdentification.ExistingLicense\x1a_\n\x04\x43\x45NC\x12!\n\x04Pssh\x18\x01 \x01(\x0b\x32\x13.WidevineCencHeader\x12!\n\x0bLicenseType\x18\x02 \x01(\x0e\x32\x0c.LicenseType\x12\x11\n\tRequestId\x18\x03 \x01(\x0c\x1aL\n\x04WebM\x12\x0e\n\x06Header\x18\x01 \x01(\x0c\x12!\n\x0bLicenseType\x18\x02 \x01(\x0e\x32\x0c.LicenseType\x12\x11\n\tRequestId\x18\x03 \x01(\x0c\x1a\x99\x01\n\x0f\x45xistingLicense\x12)\n\tLicenseId\x18\x01 \x01(\x0b\x32\x16.LicenseIdentification\x12\x1b\n\x13SecondsSinceStarted\x18\x02 \x01(\r\x12\x1e\n\x16SecondsSinceLastPlayed\x18\x03 \x01(\r\x12\x1e\n\x16SessionUsageTableEntry\x18\x04 \x01(\x0c\"0\n\x0bRequestType\x12\x07\n\x03NEW\x10\x01\x12\x0b\n\x07RENEWAL\x10\x02\x12\x0b\n\x07RELEASE\x10\x03\"\xa9\x07\n\x11LicenseRequestRaw\x12\'\n\x08\x43lientId\x18\x01 \x01(\x0b\x32\x15.ClientIdentification\x12;\n\tContentId\x18\x02 \x01(\x0b\x32(.LicenseRequestRaw.ContentIdentification\x12,\n\x04Type\x18\x03 \x01(\x0e\x32\x1e.LicenseRequestRaw.RequestType\x12\x13\n\x0bRequestTime\x18\x04 \x01(\r\x12!\n\x19KeyControlNonceDeprecated\x18\x05 \x01(\x0c\x12)\n\x0fProtocolVersion\x18\x06 \x01(\x0e\x32\x10.ProtocolVersion\x12\x17\n\x0fKeyControlNonce\x18\x07 \x01(\r\x12\x39\n\x11\x45ncryptedClientId\x18\x08 \x01(\x0b\x32\x1e.EncryptedClientIdentification\x1a\x96\x04\n\x15\x43ontentIdentification\x12=\n\x06\x43\x65ncId\x18\x01 \x01(\x0b\x32-.LicenseRequestRaw.ContentIdentification.CENC\x12=\n\x06WebmId\x18\x02 \x01(\x0b\x32-.LicenseRequestRaw.ContentIdentification.WebM\x12I\n\x07License\x18\x03 \x01(\x0b\x32\x38.LicenseRequestRaw.ContentIdentification.ExistingLicense\x1aJ\n\x04\x43\x45NC\x12\x0c\n\x04Pssh\x18\x01 \x01(\x0c\x12!\n\x0bLicenseType\x18\x02 \x01(\x0e\x32\x0c.LicenseType\x12\x11\n\tRequestId\x18\x03 \x01(\x0c\x1aL\n\x04WebM\x12\x0e\n\x06Header\x18\x01 \x01(\x0c\x12!\n\x0bLicenseType\x18\x02 \x01(\x0e\x32\x0c.LicenseType\x12\x11\n\tRequestId\x18\x03 \x01(\x0c\x1a\x99\x01\n\x0f\x45xistingLicense\x12)\n\tLicenseId\x18\x01 \x01(\x0b\x32\x16.LicenseIdentification\x12\x1b\n\x13SecondsSinceStarted\x18\x02 \x01(\r\x12\x1e\n\x16SecondsSinceLastPlayed\x18\x03 \x01(\r\x12\x1e\n\x16SessionUsageTableEntry\x18\x04 \x01(\x0c\"0\n\x0bRequestType\x12\x07\n\x03NEW\x10\x01\x12\x0b\n\x07RENEWAL\x10\x02\x12\x0b\n\x07RELEASE\x10\x03\"\xa6\x02\n\x15ProvisionedDeviceInfo\x12\x10\n\x08SystemId\x18\x01 \x01(\r\x12\x0b\n\x03Soc\x18\x02 \x01(\t\x12\x14\n\x0cManufacturer\x18\x03 \x01(\t\x12\r\n\x05Model\x18\x04 \x01(\t\x12\x12\n\nDeviceType\x18\x05 \x01(\t\x12\x11\n\tModelYear\x18\x06 \x01(\r\x12=\n\rSecurityLevel\x18\x07 \x01(\x0e\x32&.ProvisionedDeviceInfo.WvSecurityLevel\x12\x12\n\nTestDevice\x18\x08 \x01(\r\"O\n\x0fWvSecurityLevel\x12\x15\n\x11LEVEL_UNSPECIFIED\x10\x00\x12\x0b\n\x07LEVEL_1\x10\x01\x12\x0b\n\x07LEVEL_2\x10\x02\x12\x0b\n\x07LEVEL_3\x10\x03\"\x15\n\x13ProvisioningOptions\"\x15\n\x13ProvisioningRequest\"\x16\n\x14ProvisioningResponse\"i\n\x11RemoteAttestation\x12\x33\n\x0b\x43\x65rtificate\x18\x01 \x01(\x0b\x32\x1e.EncryptedClientIdentification\x12\x0c\n\x04Salt\x18\x02 \x01(\t\x12\x11\n\tSignature\x18\x03 \x01(\t\"\r\n\x0bSessionInit\"\x0e\n\x0cSessionState\"\x1d\n\x1bSignedCertificateStatusList\"\x86\x01\n\x17SignedDeviceCertificate\x12.\n\x12_DeviceCertificate\x18\x01 \x01(\x0b\x32\x12.DeviceCertificate\x12\x11\n\tSignature\x18\x02 \x01(\x0c\x12(\n\x06Signer\x18\x03 \x01(\x0b\x32\x18.SignedDeviceCertificate\"\x1b\n\x19SignedProvisioningMessage\"\x9b\x02\n\rSignedMessage\x12(\n\x04Type\x18\x01 \x01(\x0e\x32\x1a.SignedMessage.MessageType\x12\x0b\n\x03Msg\x18\x02 \x01(\x0c\x12\x11\n\tSignature\x18\x03 \x01(\x0c\x12\x12\n\nSessionKey\x18\x04 \x01(\x0c\x12-\n\x11RemoteAttestation\x18\x05 \x01(\x0b\x32\x12.RemoteAttestation\"}\n\x0bMessageType\x12\x13\n\x0fLICENSE_REQUEST\x10\x01\x12\x0b\n\x07LICENSE\x10\x02\x12\x12\n\x0e\x45RROR_RESPONSE\x10\x03\x12\x1f\n\x1bSERVICE_CERTIFICATE_REQUEST\x10\x04\x12\x17\n\x13SERVICE_CERTIFICATE\x10\x05\"\xc5\x02\n\x12WidevineCencHeader\x12\x30\n\talgorithm\x18\x01 \x01(\x0e\x32\x1d.WidevineCencHeader.Algorithm\x12\x0e\n\x06key_id\x18\x02 \x03(\x0c\x12\x10\n\x08provider\x18\x03 \x01(\t\x12\x12\n\ncontent_id\x18\x04 \x01(\x0c\x12\x1d\n\x15track_type_deprecated\x18\x05 \x01(\t\x12\x0e\n\x06policy\x18\x06 \x01(\t\x12\x1b\n\x13\x63rypto_period_index\x18\x07 \x01(\r\x12\x17\n\x0fgrouped_license\x18\x08 \x01(\x0c\x12\x19\n\x11protection_scheme\x18\t \x01(\r\x12\x1d\n\x15\x63rypto_period_seconds\x18\n \x01(\r\"(\n\tAlgorithm\x12\x0f\n\x0bUNENCRYPTED\x10\x00\x12\n\n\x06\x41\x45SCTR\x10\x01\"\xba\x02\n\x14SignedLicenseRequest\x12/\n\x04Type\x18\x01 \x01(\x0e\x32!.SignedLicenseRequest.MessageType\x12\x1c\n\x03Msg\x18\x02 \x01(\x0b\x32\x0f.LicenseRequest\x12\x11\n\tSignature\x18\x03 \x01(\x0c\x12\x12\n\nSessionKey\x18\x04 \x01(\x0c\x12-\n\x11RemoteAttestation\x18\x05 \x01(\x0b\x32\x12.RemoteAttestation\"}\n\x0bMessageType\x12\x13\n\x0fLICENSE_REQUEST\x10\x01\x12\x0b\n\x07LICENSE\x10\x02\x12\x12\n\x0e\x45RROR_RESPONSE\x10\x03\x12\x1f\n\x1bSERVICE_CERTIFICATE_REQUEST\x10\x04\x12\x17\n\x13SERVICE_CERTIFICATE\x10\x05\"\xc3\x02\n\x17SignedLicenseRequestRaw\x12\x32\n\x04Type\x18\x01 \x01(\x0e\x32$.SignedLicenseRequestRaw.MessageType\x12\x1f\n\x03Msg\x18\x02 \x01(\x0b\x32\x12.LicenseRequestRaw\x12\x11\n\tSignature\x18\x03 \x01(\x0c\x12\x12\n\nSessionKey\x18\x04 \x01(\x0c\x12-\n\x11RemoteAttestation\x18\x05 \x01(\x0b\x32\x12.RemoteAttestation\"}\n\x0bMessageType\x12\x13\n\x0fLICENSE_REQUEST\x10\x01\x12\x0b\n\x07LICENSE\x10\x02\x12\x12\n\x0e\x45RROR_RESPONSE\x10\x03\x12\x1f\n\x1bSERVICE_CERTIFICATE_REQUEST\x10\x04\x12\x17\n\x13SERVICE_CERTIFICATE\x10\x05\"\xa5\x02\n\rSignedLicense\x12(\n\x04Type\x18\x01 \x01(\x0e\x32\x1a.SignedLicense.MessageType\x12\x15\n\x03Msg\x18\x02 \x01(\x0b\x32\x08.License\x12\x11\n\tSignature\x18\x03 \x01(\x0c\x12\x12\n\nSessionKey\x18\x04 \x01(\x0c\x12-\n\x11RemoteAttestation\x18\x05 \x01(\x0b\x32\x12.RemoteAttestation\"}\n\x0bMessageType\x12\x13\n\x0fLICENSE_REQUEST\x10\x01\x12\x0b\n\x07LICENSE\x10\x02\x12\x12\n\x0e\x45RROR_RESPONSE\x10\x03\x12\x1f\n\x1bSERVICE_CERTIFICATE_REQUEST\x10\x04\x12\x17\n\x13SERVICE_CERTIFICATE\x10\x05\"\xcb\x02\n\x18SignedServiceCertificate\x12\x33\n\x04Type\x18\x01 \x01(\x0e\x32%.SignedServiceCertificate.MessageType\x12%\n\x03Msg\x18\x02 \x01(\x0b\x32\x18.SignedDeviceCertificate\x12\x11\n\tSignature\x18\x03 \x01(\x0c\x12\x12\n\nSessionKey\x18\x04 \x01(\x0c\x12-\n\x11RemoteAttestation\x18\x05 \x01(\x0b\x32\x12.RemoteAttestation\"}\n\x0bMessageType\x12\x13\n\x0fLICENSE_REQUEST\x10\x01\x12\x0b\n\x07LICENSE\x10\x02\x12\x12\n\x0e\x45RROR_RESPONSE\x10\x03\x12\x1f\n\x1bSERVICE_CERTIFICATE_REQUEST\x10\x04\x12\x17\n\x13SERVICE_CERTIFICATE\x10\x05\"\xb5\x01\n\nFileHashes\x12\x0e\n\x06signer\x18\x01 \x01(\x0c\x12)\n\nsignatures\x18\x02 \x03(\x0b\x32\x15.FileHashes.Signature\x1al\n\tSignature\x12\x10\n\x08\x66ilename\x18\x01 \x01(\t\x12\x14\n\x0ctest_signing\x18\x02 \x01(\x08\x12\x12\n\nSHA512Hash\x18\x03 \x01(\x0c\x12\x10\n\x08main_exe\x18\x04 \x01(\x08\x12\x11\n\tsignature\x18\x05 \x01(\x0c*1\n\x0bLicenseType\x12\x08\n\x04ZERO\x10\x00\x12\x0b\n\x07\x44\x45\x46\x41ULT\x10\x01\x12\x0b\n\x07OFFLINE\x10\x02*\x1e\n\x0fProtocolVersion\x12\x0b\n\x07\x43URRENT\x10\x15')
+)
+_sym_db.RegisterFileDescriptor(DESCRIPTOR)
+
+_LICENSETYPE = _descriptor.EnumDescriptor(
+ name='LicenseType',
+ full_name='LicenseType',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='ZERO', index=0, number=0,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='DEFAULT', index=1, number=1,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='OFFLINE', index=2, number=2,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=8362,
+ serialized_end=8411,
+)
+_sym_db.RegisterEnumDescriptor(_LICENSETYPE)
+
+LicenseType = enum_type_wrapper.EnumTypeWrapper(_LICENSETYPE)
+_PROTOCOLVERSION = _descriptor.EnumDescriptor(
+ name='ProtocolVersion',
+ full_name='ProtocolVersion',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='CURRENT', index=0, number=21,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=8413,
+ serialized_end=8443,
+)
+_sym_db.RegisterEnumDescriptor(_PROTOCOLVERSION)
+
+ProtocolVersion = enum_type_wrapper.EnumTypeWrapper(_PROTOCOLVERSION)
+ZERO = 0
+DEFAULT = 1
+OFFLINE = 2
+CURRENT = 21
+
+
+_CLIENTIDENTIFICATION_CLIENTCAPABILITIES_HDCPVERSION = _descriptor.EnumDescriptor(
+ name='HdcpVersion',
+ full_name='ClientIdentification.ClientCapabilities.HdcpVersion',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='HDCP_NONE', index=0, number=0,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='HDCP_V1', index=1, number=1,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='HDCP_V2', index=2, number=2,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='HDCP_V2_1', index=3, number=3,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='HDCP_V2_2', index=4, number=4,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=617,
+ serialized_end=701,
+)
+_sym_db.RegisterEnumDescriptor(_CLIENTIDENTIFICATION_CLIENTCAPABILITIES_HDCPVERSION)
+
+_CLIENTIDENTIFICATION_TOKENTYPE = _descriptor.EnumDescriptor(
+ name='TokenType',
+ full_name='ClientIdentification.TokenType',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='KEYBOX', index=0, number=0,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='DEVICE_CERTIFICATE', index=1, number=1,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='REMOTE_ATTESTATION_CERTIFICATE', index=2, number=2,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=703,
+ serialized_end=786,
+)
+_sym_db.RegisterEnumDescriptor(_CLIENTIDENTIFICATION_TOKENTYPE)
+
+_DEVICECERTIFICATE_CERTIFICATETYPE = _descriptor.EnumDescriptor(
+ name='CertificateType',
+ full_name='DeviceCertificate.CertificateType',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='ROOT', index=0, number=0,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='INTERMEDIATE', index=1, number=1,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='USER_DEVICE', index=2, number=2,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='SERVICE', index=3, number=3,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=997,
+ serialized_end=1072,
+)
+_sym_db.RegisterEnumDescriptor(_DEVICECERTIFICATE_CERTIFICATETYPE)
+
+_DEVICECERTIFICATESTATUS_CERTIFICATESTATUS = _descriptor.EnumDescriptor(
+ name='CertificateStatus',
+ full_name='DeviceCertificateStatus.CertificateStatus',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='VALID', index=0, number=0,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='REVOKED', index=1, number=1,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=1228,
+ serialized_end=1271,
+)
+_sym_db.RegisterEnumDescriptor(_DEVICECERTIFICATESTATUS_CERTIFICATESTATUS)
+
+_LICENSE_KEYCONTAINER_OUTPUTPROTECTION_CGMS = _descriptor.EnumDescriptor(
+ name='CGMS',
+ full_name='License.KeyContainer.OutputProtection.CGMS',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='COPY_FREE', index=0, number=0,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='COPY_ONCE', index=1, number=2,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='COPY_NEVER', index=2, number=3,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='CGMS_NONE', index=3, number=42,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=2949,
+ serialized_end=3016,
+)
+_sym_db.RegisterEnumDescriptor(_LICENSE_KEYCONTAINER_OUTPUTPROTECTION_CGMS)
+
+_LICENSE_KEYCONTAINER_KEYTYPE = _descriptor.EnumDescriptor(
+ name='KeyType',
+ full_name='License.KeyContainer.KeyType',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='SIGNING', index=0, number=1,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='CONTENT', index=1, number=2,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='KEY_CONTROL', index=2, number=3,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='OPERATOR_SESSION', index=3, number=4,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=3351,
+ serialized_end=3425,
+)
+_sym_db.RegisterEnumDescriptor(_LICENSE_KEYCONTAINER_KEYTYPE)
+
+_LICENSE_KEYCONTAINER_SECURITYLEVEL = _descriptor.EnumDescriptor(
+ name='SecurityLevel',
+ full_name='License.KeyContainer.SecurityLevel',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='SW_SECURE_CRYPTO', index=0, number=1,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='SW_SECURE_DECODE', index=1, number=2,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='HW_SECURE_CRYPTO', index=2, number=3,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='HW_SECURE_DECODE', index=3, number=4,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='HW_SECURE_ALL', index=4, number=5,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=3427,
+ serialized_end=3549,
+)
+_sym_db.RegisterEnumDescriptor(_LICENSE_KEYCONTAINER_SECURITYLEVEL)
+
+_LICENSEERROR_ERROR = _descriptor.EnumDescriptor(
+ name='Error',
+ full_name='LicenseError.Error',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='INVALID_DEVICE_CERTIFICATE', index=0, number=1,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='REVOKED_DEVICE_CERTIFICATE', index=1, number=2,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='SERVICE_UNAVAILABLE', index=2, number=3,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=3608,
+ serialized_end=3704,
+)
+_sym_db.RegisterEnumDescriptor(_LICENSEERROR_ERROR)
+
+_LICENSEREQUEST_REQUESTTYPE = _descriptor.EnumDescriptor(
+ name='RequestType',
+ full_name='LicenseRequest.RequestType',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='NEW', index=0, number=1,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='RENEWAL', index=1, number=2,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='RELEASE', index=2, number=3,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=4599,
+ serialized_end=4647,
+)
+_sym_db.RegisterEnumDescriptor(_LICENSEREQUEST_REQUESTTYPE)
+
+_LICENSEREQUESTRAW_REQUESTTYPE = _descriptor.EnumDescriptor(
+ name='RequestType',
+ full_name='LicenseRequestRaw.RequestType',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='NEW', index=0, number=1,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='RENEWAL', index=1, number=2,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='RELEASE', index=2, number=3,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=4599,
+ serialized_end=4647,
+)
+_sym_db.RegisterEnumDescriptor(_LICENSEREQUESTRAW_REQUESTTYPE)
+
+_PROVISIONEDDEVICEINFO_WVSECURITYLEVEL = _descriptor.EnumDescriptor(
+ name='WvSecurityLevel',
+ full_name='ProvisionedDeviceInfo.WvSecurityLevel',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='LEVEL_UNSPECIFIED', index=0, number=0,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='LEVEL_1', index=1, number=1,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='LEVEL_2', index=2, number=2,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='LEVEL_3', index=3, number=3,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=5805,
+ serialized_end=5884,
+)
+_sym_db.RegisterEnumDescriptor(_PROVISIONEDDEVICEINFO_WVSECURITYLEVEL)
+
+_SIGNEDMESSAGE_MESSAGETYPE = _descriptor.EnumDescriptor(
+ name='MessageType',
+ full_name='SignedMessage.MessageType',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='LICENSE_REQUEST', index=0, number=1,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='LICENSE', index=1, number=2,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='ERROR_RESPONSE', index=2, number=3,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='SERVICE_CERTIFICATE_REQUEST', index=3, number=4,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='SERVICE_CERTIFICATE', index=4, number=5,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=6450,
+ serialized_end=6575,
+)
+_sym_db.RegisterEnumDescriptor(_SIGNEDMESSAGE_MESSAGETYPE)
+
+_WIDEVINECENCHEADER_ALGORITHM = _descriptor.EnumDescriptor(
+ name='Algorithm',
+ full_name='WidevineCencHeader.Algorithm',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='UNENCRYPTED', index=0, number=0,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='AESCTR', index=1, number=1,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=6863,
+ serialized_end=6903,
+)
+_sym_db.RegisterEnumDescriptor(_WIDEVINECENCHEADER_ALGORITHM)
+
+_SIGNEDLICENSEREQUEST_MESSAGETYPE = _descriptor.EnumDescriptor(
+ name='MessageType',
+ full_name='SignedLicenseRequest.MessageType',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='LICENSE_REQUEST', index=0, number=1,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='LICENSE', index=1, number=2,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='ERROR_RESPONSE', index=2, number=3,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='SERVICE_CERTIFICATE_REQUEST', index=3, number=4,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='SERVICE_CERTIFICATE', index=4, number=5,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=6450,
+ serialized_end=6575,
+)
+_sym_db.RegisterEnumDescriptor(_SIGNEDLICENSEREQUEST_MESSAGETYPE)
+
+_SIGNEDLICENSEREQUESTRAW_MESSAGETYPE = _descriptor.EnumDescriptor(
+ name='MessageType',
+ full_name='SignedLicenseRequestRaw.MessageType',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='LICENSE_REQUEST', index=0, number=1,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='LICENSE', index=1, number=2,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='ERROR_RESPONSE', index=2, number=3,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='SERVICE_CERTIFICATE_REQUEST', index=3, number=4,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='SERVICE_CERTIFICATE', index=4, number=5,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=6450,
+ serialized_end=6575,
+)
+_sym_db.RegisterEnumDescriptor(_SIGNEDLICENSEREQUESTRAW_MESSAGETYPE)
+
+_SIGNEDLICENSE_MESSAGETYPE = _descriptor.EnumDescriptor(
+ name='MessageType',
+ full_name='SignedLicense.MessageType',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='LICENSE_REQUEST', index=0, number=1,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='LICENSE', index=1, number=2,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='ERROR_RESPONSE', index=2, number=3,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='SERVICE_CERTIFICATE_REQUEST', index=3, number=4,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='SERVICE_CERTIFICATE', index=4, number=5,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=6450,
+ serialized_end=6575,
+)
+_sym_db.RegisterEnumDescriptor(_SIGNEDLICENSE_MESSAGETYPE)
+
+_SIGNEDSERVICECERTIFICATE_MESSAGETYPE = _descriptor.EnumDescriptor(
+ name='MessageType',
+ full_name='SignedServiceCertificate.MessageType',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='LICENSE_REQUEST', index=0, number=1,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='LICENSE', index=1, number=2,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='ERROR_RESPONSE', index=2, number=3,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='SERVICE_CERTIFICATE_REQUEST', index=3, number=4,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='SERVICE_CERTIFICATE', index=4, number=5,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=6450,
+ serialized_end=6575,
+)
+_sym_db.RegisterEnumDescriptor(_SIGNEDSERVICECERTIFICATE_MESSAGETYPE)
+
+
+_CLIENTIDENTIFICATION_NAMEVALUE = _descriptor.Descriptor(
+ name='NameValue',
+ full_name='ClientIdentification.NameValue',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='Name', full_name='ClientIdentification.NameValue.Name', index=0,
+ number=1, type=9, cpp_type=9, label=2,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Value', full_name='ClientIdentification.NameValue.Value', index=1,
+ number=2, type=9, cpp_type=9, label=2,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=366,
+ serialized_end=406,
+)
+
+_CLIENTIDENTIFICATION_CLIENTCAPABILITIES = _descriptor.Descriptor(
+ name='ClientCapabilities',
+ full_name='ClientIdentification.ClientCapabilities',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='ClientToken', full_name='ClientIdentification.ClientCapabilities.ClientToken', index=0,
+ number=1, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='SessionToken', full_name='ClientIdentification.ClientCapabilities.SessionToken', index=1,
+ number=2, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='VideoResolutionConstraints', full_name='ClientIdentification.ClientCapabilities.VideoResolutionConstraints', index=2,
+ number=3, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='MaxHdcpVersion', full_name='ClientIdentification.ClientCapabilities.MaxHdcpVersion', index=3,
+ number=4, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='OemCryptoApiVersion', full_name='ClientIdentification.ClientCapabilities.OemCryptoApiVersion', index=4,
+ number=5, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ _CLIENTIDENTIFICATION_CLIENTCAPABILITIES_HDCPVERSION,
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=409,
+ serialized_end=701,
+)
+
+_CLIENTIDENTIFICATION = _descriptor.Descriptor(
+ name='ClientIdentification',
+ full_name='ClientIdentification',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='Type', full_name='ClientIdentification.Type', index=0,
+ number=1, type=14, cpp_type=8, label=2,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Token', full_name='ClientIdentification.Token', index=1,
+ number=2, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='ClientInfo', full_name='ClientIdentification.ClientInfo', index=2,
+ number=3, type=11, cpp_type=10, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='ProviderClientToken', full_name='ClientIdentification.ProviderClientToken', index=3,
+ number=4, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='LicenseCounter', full_name='ClientIdentification.LicenseCounter', index=4,
+ number=5, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='_ClientCapabilities', full_name='ClientIdentification._ClientCapabilities', index=5,
+ number=6, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='_FileHashes', full_name='ClientIdentification._FileHashes', index=6,
+ number=7, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[_CLIENTIDENTIFICATION_NAMEVALUE, _CLIENTIDENTIFICATION_CLIENTCAPABILITIES, ],
+ enum_types=[
+ _CLIENTIDENTIFICATION_TOKENTYPE,
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=43,
+ serialized_end=786,
+)
+
+
+_DEVICECERTIFICATE = _descriptor.Descriptor(
+ name='DeviceCertificate',
+ full_name='DeviceCertificate',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='Type', full_name='DeviceCertificate.Type', index=0,
+ number=1, type=14, cpp_type=8, label=2,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='SerialNumber', full_name='DeviceCertificate.SerialNumber', index=1,
+ number=2, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='CreationTimeSeconds', full_name='DeviceCertificate.CreationTimeSeconds', index=2,
+ number=3, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='PublicKey', full_name='DeviceCertificate.PublicKey', index=3,
+ number=4, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='SystemId', full_name='DeviceCertificate.SystemId', index=4,
+ number=5, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='TestDeviceDeprecated', full_name='DeviceCertificate.TestDeviceDeprecated', index=5,
+ number=6, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='ServiceId', full_name='DeviceCertificate.ServiceId', index=6,
+ number=7, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ _DEVICECERTIFICATE_CERTIFICATETYPE,
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=789,
+ serialized_end=1072,
+)
+
+
+_DEVICECERTIFICATESTATUS = _descriptor.Descriptor(
+ name='DeviceCertificateStatus',
+ full_name='DeviceCertificateStatus',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='SerialNumber', full_name='DeviceCertificateStatus.SerialNumber', index=0,
+ number=1, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Status', full_name='DeviceCertificateStatus.Status', index=1,
+ number=2, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='DeviceInfo', full_name='DeviceCertificateStatus.DeviceInfo', index=2,
+ number=4, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ _DEVICECERTIFICATESTATUS_CERTIFICATESTATUS,
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=1075,
+ serialized_end=1271,
+)
+
+
+_DEVICECERTIFICATESTATUSLIST = _descriptor.Descriptor(
+ name='DeviceCertificateStatusList',
+ full_name='DeviceCertificateStatusList',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='CreationTimeSeconds', full_name='DeviceCertificateStatusList.CreationTimeSeconds', index=0,
+ number=1, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='CertificateStatus', full_name='DeviceCertificateStatusList.CertificateStatus', index=1,
+ number=2, type=11, cpp_type=10, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=1273,
+ serialized_end=1384,
+)
+
+
+_ENCRYPTEDCLIENTIDENTIFICATION = _descriptor.Descriptor(
+ name='EncryptedClientIdentification',
+ full_name='EncryptedClientIdentification',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='ServiceId', full_name='EncryptedClientIdentification.ServiceId', index=0,
+ number=1, type=9, cpp_type=9, label=2,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='ServiceCertificateSerialNumber', full_name='EncryptedClientIdentification.ServiceCertificateSerialNumber', index=1,
+ number=2, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='EncryptedClientId', full_name='EncryptedClientIdentification.EncryptedClientId', index=2,
+ number=3, type=12, cpp_type=9, label=2,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='EncryptedClientIdIv', full_name='EncryptedClientIdentification.EncryptedClientIdIv', index=3,
+ number=4, type=12, cpp_type=9, label=2,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='EncryptedPrivacyKey', full_name='EncryptedClientIdentification.EncryptedPrivacyKey', index=4,
+ number=5, type=12, cpp_type=9, label=2,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=1387,
+ serialized_end=1562,
+)
+
+
+_LICENSEIDENTIFICATION = _descriptor.Descriptor(
+ name='LicenseIdentification',
+ full_name='LicenseIdentification',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='RequestId', full_name='LicenseIdentification.RequestId', index=0,
+ number=1, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='SessionId', full_name='LicenseIdentification.SessionId', index=1,
+ number=2, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='PurchaseId', full_name='LicenseIdentification.PurchaseId', index=2,
+ number=3, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Type', full_name='LicenseIdentification.Type', index=3,
+ number=4, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Version', full_name='LicenseIdentification.Version', index=4,
+ number=5, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='ProviderSessionToken', full_name='LicenseIdentification.ProviderSessionToken', index=5,
+ number=6, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=1565,
+ serialized_end=1721,
+)
+
+
+_LICENSE_POLICY = _descriptor.Descriptor(
+ name='Policy',
+ full_name='License.Policy',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='CanPlay', full_name='License.Policy.CanPlay', index=0,
+ number=1, type=8, cpp_type=7, label=1,
+ has_default_value=False, default_value=False,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='CanPersist', full_name='License.Policy.CanPersist', index=1,
+ number=2, type=8, cpp_type=7, label=1,
+ has_default_value=False, default_value=False,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='CanRenew', full_name='License.Policy.CanRenew', index=2,
+ number=3, type=8, cpp_type=7, label=1,
+ has_default_value=False, default_value=False,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RentalDurationSeconds', full_name='License.Policy.RentalDurationSeconds', index=3,
+ number=4, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='PlaybackDurationSeconds', full_name='License.Policy.PlaybackDurationSeconds', index=4,
+ number=5, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='LicenseDurationSeconds', full_name='License.Policy.LicenseDurationSeconds', index=5,
+ number=6, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RenewalRecoveryDurationSeconds', full_name='License.Policy.RenewalRecoveryDurationSeconds', index=6,
+ number=7, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RenewalServerUrl', full_name='License.Policy.RenewalServerUrl', index=7,
+ number=8, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RenewalDelaySeconds', full_name='License.Policy.RenewalDelaySeconds', index=8,
+ number=9, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RenewalRetryIntervalSeconds', full_name='License.Policy.RenewalRetryIntervalSeconds', index=9,
+ number=10, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RenewWithUsage', full_name='License.Policy.RenewWithUsage', index=10,
+ number=11, type=8, cpp_type=7, label=1,
+ has_default_value=False, default_value=False,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=1958,
+ serialized_end=2273,
+)
+
+_LICENSE_KEYCONTAINER_OUTPUTPROTECTION = _descriptor.Descriptor(
+ name='OutputProtection',
+ full_name='License.KeyContainer.OutputProtection',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='Hdcp', full_name='License.KeyContainer.OutputProtection.Hdcp', index=0,
+ number=1, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='CgmsFlags', full_name='License.KeyContainer.OutputProtection.CgmsFlags', index=1,
+ number=2, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ _LICENSE_KEYCONTAINER_OUTPUTPROTECTION_CGMS,
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=2797,
+ serialized_end=3016,
+)
+
+_LICENSE_KEYCONTAINER_KEYCONTROL = _descriptor.Descriptor(
+ name='KeyControl',
+ full_name='License.KeyContainer.KeyControl',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='KeyControlBlock', full_name='License.KeyContainer.KeyControl.KeyControlBlock', index=0,
+ number=1, type=12, cpp_type=9, label=2,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Iv', full_name='License.KeyContainer.KeyControl.Iv', index=1,
+ number=2, type=12, cpp_type=9, label=2,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=3018,
+ serialized_end=3067,
+)
+
+_LICENSE_KEYCONTAINER_OPERATORSESSIONKEYPERMISSIONS = _descriptor.Descriptor(
+ name='OperatorSessionKeyPermissions',
+ full_name='License.KeyContainer.OperatorSessionKeyPermissions',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='AllowEncrypt', full_name='License.KeyContainer.OperatorSessionKeyPermissions.AllowEncrypt', index=0,
+ number=1, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='AllowDecrypt', full_name='License.KeyContainer.OperatorSessionKeyPermissions.AllowDecrypt', index=1,
+ number=2, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='AllowSign', full_name='License.KeyContainer.OperatorSessionKeyPermissions.AllowSign', index=2,
+ number=3, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='AllowSignatureVerify', full_name='License.KeyContainer.OperatorSessionKeyPermissions.AllowSignatureVerify', index=3,
+ number=4, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=3069,
+ serialized_end=3193,
+)
+
+_LICENSE_KEYCONTAINER_VIDEORESOLUTIONCONSTRAINT = _descriptor.Descriptor(
+ name='VideoResolutionConstraint',
+ full_name='License.KeyContainer.VideoResolutionConstraint',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='MinResolutionPixels', full_name='License.KeyContainer.VideoResolutionConstraint.MinResolutionPixels', index=0,
+ number=1, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='MaxResolutionPixels', full_name='License.KeyContainer.VideoResolutionConstraint.MaxResolutionPixels', index=1,
+ number=2, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RequiredProtection', full_name='License.KeyContainer.VideoResolutionConstraint.RequiredProtection', index=2,
+ number=3, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=3196,
+ serialized_end=3349,
+)
+
+_LICENSE_KEYCONTAINER = _descriptor.Descriptor(
+ name='KeyContainer',
+ full_name='License.KeyContainer',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='Id', full_name='License.KeyContainer.Id', index=0,
+ number=1, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Iv', full_name='License.KeyContainer.Iv', index=1,
+ number=2, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Key', full_name='License.KeyContainer.Key', index=2,
+ number=3, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Type', full_name='License.KeyContainer.Type', index=3,
+ number=4, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=1,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Level', full_name='License.KeyContainer.Level', index=4,
+ number=5, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=1,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RequiredProtection', full_name='License.KeyContainer.RequiredProtection', index=5,
+ number=6, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RequestedProtection', full_name='License.KeyContainer.RequestedProtection', index=6,
+ number=7, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='_KeyControl', full_name='License.KeyContainer._KeyControl', index=7,
+ number=8, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='_OperatorSessionKeyPermissions', full_name='License.KeyContainer._OperatorSessionKeyPermissions', index=8,
+ number=9, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='VideoResolutionConstraints', full_name='License.KeyContainer.VideoResolutionConstraints', index=9,
+ number=10, type=11, cpp_type=10, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[_LICENSE_KEYCONTAINER_OUTPUTPROTECTION, _LICENSE_KEYCONTAINER_KEYCONTROL, _LICENSE_KEYCONTAINER_OPERATORSESSIONKEYPERMISSIONS, _LICENSE_KEYCONTAINER_VIDEORESOLUTIONCONSTRAINT, ],
+ enum_types=[
+ _LICENSE_KEYCONTAINER_KEYTYPE,
+ _LICENSE_KEYCONTAINER_SECURITYLEVEL,
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=2276,
+ serialized_end=3549,
+)
+
+_LICENSE = _descriptor.Descriptor(
+ name='License',
+ full_name='License',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='Id', full_name='License.Id', index=0,
+ number=1, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='_Policy', full_name='License._Policy', index=1,
+ number=2, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Key', full_name='License.Key', index=2,
+ number=3, type=11, cpp_type=10, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='LicenseStartTime', full_name='License.LicenseStartTime', index=3,
+ number=4, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RemoteAttestationVerified', full_name='License.RemoteAttestationVerified', index=4,
+ number=5, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='ProviderClientToken', full_name='License.ProviderClientToken', index=5,
+ number=6, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='ProtectionScheme', full_name='License.ProtectionScheme', index=6,
+ number=7, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[_LICENSE_POLICY, _LICENSE_KEYCONTAINER, ],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=1724,
+ serialized_end=3549,
+)
+
+
+_LICENSEERROR = _descriptor.Descriptor(
+ name='LicenseError',
+ full_name='LicenseError',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='ErrorCode', full_name='LicenseError.ErrorCode', index=0,
+ number=1, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=1,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ _LICENSEERROR_ERROR,
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=3552,
+ serialized_end=3704,
+)
+
+
+_LICENSEREQUEST_CONTENTIDENTIFICATION_CENC = _descriptor.Descriptor(
+ name='CENC',
+ full_name='LicenseRequest.ContentIdentification.CENC',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='Pssh', full_name='LicenseRequest.ContentIdentification.CENC.Pssh', index=0,
+ number=1, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='LicenseType', full_name='LicenseRequest.ContentIdentification.CENC.LicenseType', index=1,
+ number=2, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RequestId', full_name='LicenseRequest.ContentIdentification.CENC.RequestId', index=2,
+ number=3, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=4268,
+ serialized_end=4363,
+)
+
+_LICENSEREQUEST_CONTENTIDENTIFICATION_WEBM = _descriptor.Descriptor(
+ name='WebM',
+ full_name='LicenseRequest.ContentIdentification.WebM',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='Header', full_name='LicenseRequest.ContentIdentification.WebM.Header', index=0,
+ number=1, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='LicenseType', full_name='LicenseRequest.ContentIdentification.WebM.LicenseType', index=1,
+ number=2, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RequestId', full_name='LicenseRequest.ContentIdentification.WebM.RequestId', index=2,
+ number=3, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=4365,
+ serialized_end=4441,
+)
+
+_LICENSEREQUEST_CONTENTIDENTIFICATION_EXISTINGLICENSE = _descriptor.Descriptor(
+ name='ExistingLicense',
+ full_name='LicenseRequest.ContentIdentification.ExistingLicense',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='LicenseId', full_name='LicenseRequest.ContentIdentification.ExistingLicense.LicenseId', index=0,
+ number=1, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='SecondsSinceStarted', full_name='LicenseRequest.ContentIdentification.ExistingLicense.SecondsSinceStarted', index=1,
+ number=2, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='SecondsSinceLastPlayed', full_name='LicenseRequest.ContentIdentification.ExistingLicense.SecondsSinceLastPlayed', index=2,
+ number=3, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='SessionUsageTableEntry', full_name='LicenseRequest.ContentIdentification.ExistingLicense.SessionUsageTableEntry', index=3,
+ number=4, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=4444,
+ serialized_end=4597,
+)
+
+_LICENSEREQUEST_CONTENTIDENTIFICATION = _descriptor.Descriptor(
+ name='ContentIdentification',
+ full_name='LicenseRequest.ContentIdentification',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='CencId', full_name='LicenseRequest.ContentIdentification.CencId', index=0,
+ number=1, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='WebmId', full_name='LicenseRequest.ContentIdentification.WebmId', index=1,
+ number=2, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='License', full_name='LicenseRequest.ContentIdentification.License', index=2,
+ number=3, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[_LICENSEREQUEST_CONTENTIDENTIFICATION_CENC, _LICENSEREQUEST_CONTENTIDENTIFICATION_WEBM, _LICENSEREQUEST_CONTENTIDENTIFICATION_EXISTINGLICENSE, ],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=4051,
+ serialized_end=4597,
+)
+
+_LICENSEREQUEST = _descriptor.Descriptor(
+ name='LicenseRequest',
+ full_name='LicenseRequest',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='ClientId', full_name='LicenseRequest.ClientId', index=0,
+ number=1, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='ContentId', full_name='LicenseRequest.ContentId', index=1,
+ number=2, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Type', full_name='LicenseRequest.Type', index=2,
+ number=3, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=1,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RequestTime', full_name='LicenseRequest.RequestTime', index=3,
+ number=4, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='KeyControlNonceDeprecated', full_name='LicenseRequest.KeyControlNonceDeprecated', index=4,
+ number=5, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='ProtocolVersion', full_name='LicenseRequest.ProtocolVersion', index=5,
+ number=6, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=21,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='KeyControlNonce', full_name='LicenseRequest.KeyControlNonce', index=6,
+ number=7, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='EncryptedClientId', full_name='LicenseRequest.EncryptedClientId', index=7,
+ number=8, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[_LICENSEREQUEST_CONTENTIDENTIFICATION, ],
+ enum_types=[
+ _LICENSEREQUEST_REQUESTTYPE,
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=3707,
+ serialized_end=4647,
+)
+
+
+_LICENSEREQUESTRAW_CONTENTIDENTIFICATION_CENC = _descriptor.Descriptor(
+ name='CENC',
+ full_name='LicenseRequestRaw.ContentIdentification.CENC',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='Pssh', full_name='LicenseRequestRaw.ContentIdentification.CENC.Pssh', index=0,
+ number=1, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='LicenseType', full_name='LicenseRequestRaw.ContentIdentification.CENC.LicenseType', index=1,
+ number=2, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RequestId', full_name='LicenseRequestRaw.ContentIdentification.CENC.RequestId', index=2,
+ number=3, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=5229,
+ serialized_end=5303,
+)
+
+_LICENSEREQUESTRAW_CONTENTIDENTIFICATION_WEBM = _descriptor.Descriptor(
+ name='WebM',
+ full_name='LicenseRequestRaw.ContentIdentification.WebM',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='Header', full_name='LicenseRequestRaw.ContentIdentification.WebM.Header', index=0,
+ number=1, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='LicenseType', full_name='LicenseRequestRaw.ContentIdentification.WebM.LicenseType', index=1,
+ number=2, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RequestId', full_name='LicenseRequestRaw.ContentIdentification.WebM.RequestId', index=2,
+ number=3, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=4365,
+ serialized_end=4441,
+)
+
+_LICENSEREQUESTRAW_CONTENTIDENTIFICATION_EXISTINGLICENSE = _descriptor.Descriptor(
+ name='ExistingLicense',
+ full_name='LicenseRequestRaw.ContentIdentification.ExistingLicense',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='LicenseId', full_name='LicenseRequestRaw.ContentIdentification.ExistingLicense.LicenseId', index=0,
+ number=1, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='SecondsSinceStarted', full_name='LicenseRequestRaw.ContentIdentification.ExistingLicense.SecondsSinceStarted', index=1,
+ number=2, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='SecondsSinceLastPlayed', full_name='LicenseRequestRaw.ContentIdentification.ExistingLicense.SecondsSinceLastPlayed', index=2,
+ number=3, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='SessionUsageTableEntry', full_name='LicenseRequestRaw.ContentIdentification.ExistingLicense.SessionUsageTableEntry', index=3,
+ number=4, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=4444,
+ serialized_end=4597,
+)
+
+_LICENSEREQUESTRAW_CONTENTIDENTIFICATION = _descriptor.Descriptor(
+ name='ContentIdentification',
+ full_name='LicenseRequestRaw.ContentIdentification',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='CencId', full_name='LicenseRequestRaw.ContentIdentification.CencId', index=0,
+ number=1, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='WebmId', full_name='LicenseRequestRaw.ContentIdentification.WebmId', index=1,
+ number=2, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='License', full_name='LicenseRequestRaw.ContentIdentification.License', index=2,
+ number=3, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[_LICENSEREQUESTRAW_CONTENTIDENTIFICATION_CENC, _LICENSEREQUESTRAW_CONTENTIDENTIFICATION_WEBM, _LICENSEREQUESTRAW_CONTENTIDENTIFICATION_EXISTINGLICENSE, ],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=5003,
+ serialized_end=5537,
+)
+
+_LICENSEREQUESTRAW = _descriptor.Descriptor(
+ name='LicenseRequestRaw',
+ full_name='LicenseRequestRaw',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='ClientId', full_name='LicenseRequestRaw.ClientId', index=0,
+ number=1, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='ContentId', full_name='LicenseRequestRaw.ContentId', index=1,
+ number=2, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Type', full_name='LicenseRequestRaw.Type', index=2,
+ number=3, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=1,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RequestTime', full_name='LicenseRequestRaw.RequestTime', index=3,
+ number=4, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='KeyControlNonceDeprecated', full_name='LicenseRequestRaw.KeyControlNonceDeprecated', index=4,
+ number=5, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='ProtocolVersion', full_name='LicenseRequestRaw.ProtocolVersion', index=5,
+ number=6, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=21,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='KeyControlNonce', full_name='LicenseRequestRaw.KeyControlNonce', index=6,
+ number=7, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='EncryptedClientId', full_name='LicenseRequestRaw.EncryptedClientId', index=7,
+ number=8, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[_LICENSEREQUESTRAW_CONTENTIDENTIFICATION, ],
+ enum_types=[
+ _LICENSEREQUESTRAW_REQUESTTYPE,
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=4650,
+ serialized_end=5587,
+)
+
+
+_PROVISIONEDDEVICEINFO = _descriptor.Descriptor(
+ name='ProvisionedDeviceInfo',
+ full_name='ProvisionedDeviceInfo',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='SystemId', full_name='ProvisionedDeviceInfo.SystemId', index=0,
+ number=1, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Soc', full_name='ProvisionedDeviceInfo.Soc', index=1,
+ number=2, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Manufacturer', full_name='ProvisionedDeviceInfo.Manufacturer', index=2,
+ number=3, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Model', full_name='ProvisionedDeviceInfo.Model', index=3,
+ number=4, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='DeviceType', full_name='ProvisionedDeviceInfo.DeviceType', index=4,
+ number=5, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='ModelYear', full_name='ProvisionedDeviceInfo.ModelYear', index=5,
+ number=6, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='SecurityLevel', full_name='ProvisionedDeviceInfo.SecurityLevel', index=6,
+ number=7, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='TestDevice', full_name='ProvisionedDeviceInfo.TestDevice', index=7,
+ number=8, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ _PROVISIONEDDEVICEINFO_WVSECURITYLEVEL,
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=5590,
+ serialized_end=5884,
+)
+
+
+_PROVISIONINGOPTIONS = _descriptor.Descriptor(
+ name='ProvisioningOptions',
+ full_name='ProvisioningOptions',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=5886,
+ serialized_end=5907,
+)
+
+
+_PROVISIONINGREQUEST = _descriptor.Descriptor(
+ name='ProvisioningRequest',
+ full_name='ProvisioningRequest',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=5909,
+ serialized_end=5930,
+)
+
+
+_PROVISIONINGRESPONSE = _descriptor.Descriptor(
+ name='ProvisioningResponse',
+ full_name='ProvisioningResponse',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=5932,
+ serialized_end=5954,
+)
+
+
+_REMOTEATTESTATION = _descriptor.Descriptor(
+ name='RemoteAttestation',
+ full_name='RemoteAttestation',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='Certificate', full_name='RemoteAttestation.Certificate', index=0,
+ number=1, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Salt', full_name='RemoteAttestation.Salt', index=1,
+ number=2, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Signature', full_name='RemoteAttestation.Signature', index=2,
+ number=3, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=5956,
+ serialized_end=6061,
+)
+
+
+_SESSIONINIT = _descriptor.Descriptor(
+ name='SessionInit',
+ full_name='SessionInit',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=6063,
+ serialized_end=6076,
+)
+
+
+_SESSIONSTATE = _descriptor.Descriptor(
+ name='SessionState',
+ full_name='SessionState',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=6078,
+ serialized_end=6092,
+)
+
+
+_SIGNEDCERTIFICATESTATUSLIST = _descriptor.Descriptor(
+ name='SignedCertificateStatusList',
+ full_name='SignedCertificateStatusList',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=6094,
+ serialized_end=6123,
+)
+
+
+_SIGNEDDEVICECERTIFICATE = _descriptor.Descriptor(
+ name='SignedDeviceCertificate',
+ full_name='SignedDeviceCertificate',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='_DeviceCertificate', full_name='SignedDeviceCertificate._DeviceCertificate', index=0,
+ number=1, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Signature', full_name='SignedDeviceCertificate.Signature', index=1,
+ number=2, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Signer', full_name='SignedDeviceCertificate.Signer', index=2,
+ number=3, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=6126,
+ serialized_end=6260,
+)
+
+
+_SIGNEDPROVISIONINGMESSAGE = _descriptor.Descriptor(
+ name='SignedProvisioningMessage',
+ full_name='SignedProvisioningMessage',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=6262,
+ serialized_end=6289,
+)
+
+
+_SIGNEDMESSAGE = _descriptor.Descriptor(
+ name='SignedMessage',
+ full_name='SignedMessage',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='Type', full_name='SignedMessage.Type', index=0,
+ number=1, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=1,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Msg', full_name='SignedMessage.Msg', index=1,
+ number=2, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Signature', full_name='SignedMessage.Signature', index=2,
+ number=3, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='SessionKey', full_name='SignedMessage.SessionKey', index=3,
+ number=4, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RemoteAttestation', full_name='SignedMessage.RemoteAttestation', index=4,
+ number=5, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ _SIGNEDMESSAGE_MESSAGETYPE,
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=6292,
+ serialized_end=6575,
+)
+
+
+_WIDEVINECENCHEADER = _descriptor.Descriptor(
+ name='WidevineCencHeader',
+ full_name='WidevineCencHeader',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='algorithm', full_name='WidevineCencHeader.algorithm', index=0,
+ number=1, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='key_id', full_name='WidevineCencHeader.key_id', index=1,
+ number=2, type=12, cpp_type=9, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='provider', full_name='WidevineCencHeader.provider', index=2,
+ number=3, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='content_id', full_name='WidevineCencHeader.content_id', index=3,
+ number=4, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='track_type_deprecated', full_name='WidevineCencHeader.track_type_deprecated', index=4,
+ number=5, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='policy', full_name='WidevineCencHeader.policy', index=5,
+ number=6, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='crypto_period_index', full_name='WidevineCencHeader.crypto_period_index', index=6,
+ number=7, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='grouped_license', full_name='WidevineCencHeader.grouped_license', index=7,
+ number=8, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='protection_scheme', full_name='WidevineCencHeader.protection_scheme', index=8,
+ number=9, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='crypto_period_seconds', full_name='WidevineCencHeader.crypto_period_seconds', index=9,
+ number=10, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ _WIDEVINECENCHEADER_ALGORITHM,
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=6578,
+ serialized_end=6903,
+)
+
+
+_SIGNEDLICENSEREQUEST = _descriptor.Descriptor(
+ name='SignedLicenseRequest',
+ full_name='SignedLicenseRequest',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='Type', full_name='SignedLicenseRequest.Type', index=0,
+ number=1, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=1,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Msg', full_name='SignedLicenseRequest.Msg', index=1,
+ number=2, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Signature', full_name='SignedLicenseRequest.Signature', index=2,
+ number=3, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='SessionKey', full_name='SignedLicenseRequest.SessionKey', index=3,
+ number=4, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RemoteAttestation', full_name='SignedLicenseRequest.RemoteAttestation', index=4,
+ number=5, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ _SIGNEDLICENSEREQUEST_MESSAGETYPE,
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=6906,
+ serialized_end=7220,
+)
+
+
+_SIGNEDLICENSEREQUESTRAW = _descriptor.Descriptor(
+ name='SignedLicenseRequestRaw',
+ full_name='SignedLicenseRequestRaw',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='Type', full_name='SignedLicenseRequestRaw.Type', index=0,
+ number=1, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=1,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Msg', full_name='SignedLicenseRequestRaw.Msg', index=1,
+ number=2, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Signature', full_name='SignedLicenseRequestRaw.Signature', index=2,
+ number=3, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='SessionKey', full_name='SignedLicenseRequestRaw.SessionKey', index=3,
+ number=4, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RemoteAttestation', full_name='SignedLicenseRequestRaw.RemoteAttestation', index=4,
+ number=5, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ _SIGNEDLICENSEREQUESTRAW_MESSAGETYPE,
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=7223,
+ serialized_end=7546,
+)
+
+
+_SIGNEDLICENSE = _descriptor.Descriptor(
+ name='SignedLicense',
+ full_name='SignedLicense',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='Type', full_name='SignedLicense.Type', index=0,
+ number=1, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=1,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Msg', full_name='SignedLicense.Msg', index=1,
+ number=2, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Signature', full_name='SignedLicense.Signature', index=2,
+ number=3, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='SessionKey', full_name='SignedLicense.SessionKey', index=3,
+ number=4, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RemoteAttestation', full_name='SignedLicense.RemoteAttestation', index=4,
+ number=5, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ _SIGNEDLICENSE_MESSAGETYPE,
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=7549,
+ serialized_end=7842,
+)
+
+
+_SIGNEDSERVICECERTIFICATE = _descriptor.Descriptor(
+ name='SignedServiceCertificate',
+ full_name='SignedServiceCertificate',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='Type', full_name='SignedServiceCertificate.Type', index=0,
+ number=1, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=1,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Msg', full_name='SignedServiceCertificate.Msg', index=1,
+ number=2, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Signature', full_name='SignedServiceCertificate.Signature', index=2,
+ number=3, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='SessionKey', full_name='SignedServiceCertificate.SessionKey', index=3,
+ number=4, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RemoteAttestation', full_name='SignedServiceCertificate.RemoteAttestation', index=4,
+ number=5, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ _SIGNEDSERVICECERTIFICATE_MESSAGETYPE,
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=7845,
+ serialized_end=8176,
+)
+
+
+_FILEHASHES_SIGNATURE = _descriptor.Descriptor(
+ name='Signature',
+ full_name='FileHashes.Signature',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='filename', full_name='FileHashes.Signature.filename', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='test_signing', full_name='FileHashes.Signature.test_signing', index=1,
+ number=2, type=8, cpp_type=7, label=1,
+ has_default_value=False, default_value=False,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='SHA512Hash', full_name='FileHashes.Signature.SHA512Hash', index=2,
+ number=3, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='main_exe', full_name='FileHashes.Signature.main_exe', index=3,
+ number=4, type=8, cpp_type=7, label=1,
+ has_default_value=False, default_value=False,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='signature', full_name='FileHashes.Signature.signature', index=4,
+ number=5, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=8252,
+ serialized_end=8360,
+)
+
+_FILEHASHES = _descriptor.Descriptor(
+ name='FileHashes',
+ full_name='FileHashes',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='signer', full_name='FileHashes.signer', index=0,
+ number=1, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='signatures', full_name='FileHashes.signatures', index=1,
+ number=2, type=11, cpp_type=10, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[_FILEHASHES_SIGNATURE, ],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto2',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=8179,
+ serialized_end=8360,
+)
+
+_CLIENTIDENTIFICATION_NAMEVALUE.containing_type = _CLIENTIDENTIFICATION
+_CLIENTIDENTIFICATION_CLIENTCAPABILITIES.fields_by_name['MaxHdcpVersion'].enum_type = _CLIENTIDENTIFICATION_CLIENTCAPABILITIES_HDCPVERSION
+_CLIENTIDENTIFICATION_CLIENTCAPABILITIES.containing_type = _CLIENTIDENTIFICATION
+_CLIENTIDENTIFICATION_CLIENTCAPABILITIES_HDCPVERSION.containing_type = _CLIENTIDENTIFICATION_CLIENTCAPABILITIES
+_CLIENTIDENTIFICATION.fields_by_name['Type'].enum_type = _CLIENTIDENTIFICATION_TOKENTYPE
+_CLIENTIDENTIFICATION.fields_by_name['Token'].message_type = _SIGNEDDEVICECERTIFICATE
+_CLIENTIDENTIFICATION.fields_by_name['ClientInfo'].message_type = _CLIENTIDENTIFICATION_NAMEVALUE
+_CLIENTIDENTIFICATION.fields_by_name['_ClientCapabilities'].message_type = _CLIENTIDENTIFICATION_CLIENTCAPABILITIES
+_CLIENTIDENTIFICATION.fields_by_name['_FileHashes'].message_type = _FILEHASHES
+_CLIENTIDENTIFICATION_TOKENTYPE.containing_type = _CLIENTIDENTIFICATION
+_DEVICECERTIFICATE.fields_by_name['Type'].enum_type = _DEVICECERTIFICATE_CERTIFICATETYPE
+_DEVICECERTIFICATE_CERTIFICATETYPE.containing_type = _DEVICECERTIFICATE
+_DEVICECERTIFICATESTATUS.fields_by_name['Status'].enum_type = _DEVICECERTIFICATESTATUS_CERTIFICATESTATUS
+_DEVICECERTIFICATESTATUS.fields_by_name['DeviceInfo'].message_type = _PROVISIONEDDEVICEINFO
+_DEVICECERTIFICATESTATUS_CERTIFICATESTATUS.containing_type = _DEVICECERTIFICATESTATUS
+_DEVICECERTIFICATESTATUSLIST.fields_by_name['CertificateStatus'].message_type = _DEVICECERTIFICATESTATUS
+_LICENSEIDENTIFICATION.fields_by_name['Type'].enum_type = _LICENSETYPE
+_LICENSE_POLICY.containing_type = _LICENSE
+_LICENSE_KEYCONTAINER_OUTPUTPROTECTION.fields_by_name['Hdcp'].enum_type = _CLIENTIDENTIFICATION_CLIENTCAPABILITIES_HDCPVERSION
+_LICENSE_KEYCONTAINER_OUTPUTPROTECTION.fields_by_name['CgmsFlags'].enum_type = _LICENSE_KEYCONTAINER_OUTPUTPROTECTION_CGMS
+_LICENSE_KEYCONTAINER_OUTPUTPROTECTION.containing_type = _LICENSE_KEYCONTAINER
+_LICENSE_KEYCONTAINER_OUTPUTPROTECTION_CGMS.containing_type = _LICENSE_KEYCONTAINER_OUTPUTPROTECTION
+_LICENSE_KEYCONTAINER_KEYCONTROL.containing_type = _LICENSE_KEYCONTAINER
+_LICENSE_KEYCONTAINER_OPERATORSESSIONKEYPERMISSIONS.containing_type = _LICENSE_KEYCONTAINER
+_LICENSE_KEYCONTAINER_VIDEORESOLUTIONCONSTRAINT.fields_by_name['RequiredProtection'].message_type = _LICENSE_KEYCONTAINER_OUTPUTPROTECTION
+_LICENSE_KEYCONTAINER_VIDEORESOLUTIONCONSTRAINT.containing_type = _LICENSE_KEYCONTAINER
+_LICENSE_KEYCONTAINER.fields_by_name['Type'].enum_type = _LICENSE_KEYCONTAINER_KEYTYPE
+_LICENSE_KEYCONTAINER.fields_by_name['Level'].enum_type = _LICENSE_KEYCONTAINER_SECURITYLEVEL
+_LICENSE_KEYCONTAINER.fields_by_name['RequiredProtection'].message_type = _LICENSE_KEYCONTAINER_OUTPUTPROTECTION
+_LICENSE_KEYCONTAINER.fields_by_name['RequestedProtection'].message_type = _LICENSE_KEYCONTAINER_OUTPUTPROTECTION
+_LICENSE_KEYCONTAINER.fields_by_name['_KeyControl'].message_type = _LICENSE_KEYCONTAINER_KEYCONTROL
+_LICENSE_KEYCONTAINER.fields_by_name['_OperatorSessionKeyPermissions'].message_type = _LICENSE_KEYCONTAINER_OPERATORSESSIONKEYPERMISSIONS
+_LICENSE_KEYCONTAINER.fields_by_name['VideoResolutionConstraints'].message_type = _LICENSE_KEYCONTAINER_VIDEORESOLUTIONCONSTRAINT
+_LICENSE_KEYCONTAINER.containing_type = _LICENSE
+_LICENSE_KEYCONTAINER_KEYTYPE.containing_type = _LICENSE_KEYCONTAINER
+_LICENSE_KEYCONTAINER_SECURITYLEVEL.containing_type = _LICENSE_KEYCONTAINER
+_LICENSE.fields_by_name['Id'].message_type = _LICENSEIDENTIFICATION
+_LICENSE.fields_by_name['_Policy'].message_type = _LICENSE_POLICY
+_LICENSE.fields_by_name['Key'].message_type = _LICENSE_KEYCONTAINER
+_LICENSEERROR.fields_by_name['ErrorCode'].enum_type = _LICENSEERROR_ERROR
+_LICENSEERROR_ERROR.containing_type = _LICENSEERROR
+_LICENSEREQUEST_CONTENTIDENTIFICATION_CENC.fields_by_name['Pssh'].message_type = _WIDEVINECENCHEADER
+_LICENSEREQUEST_CONTENTIDENTIFICATION_CENC.fields_by_name['LicenseType'].enum_type = _LICENSETYPE
+_LICENSEREQUEST_CONTENTIDENTIFICATION_CENC.containing_type = _LICENSEREQUEST_CONTENTIDENTIFICATION
+_LICENSEREQUEST_CONTENTIDENTIFICATION_WEBM.fields_by_name['LicenseType'].enum_type = _LICENSETYPE
+_LICENSEREQUEST_CONTENTIDENTIFICATION_WEBM.containing_type = _LICENSEREQUEST_CONTENTIDENTIFICATION
+_LICENSEREQUEST_CONTENTIDENTIFICATION_EXISTINGLICENSE.fields_by_name['LicenseId'].message_type = _LICENSEIDENTIFICATION
+_LICENSEREQUEST_CONTENTIDENTIFICATION_EXISTINGLICENSE.containing_type = _LICENSEREQUEST_CONTENTIDENTIFICATION
+_LICENSEREQUEST_CONTENTIDENTIFICATION.fields_by_name['CencId'].message_type = _LICENSEREQUEST_CONTENTIDENTIFICATION_CENC
+_LICENSEREQUEST_CONTENTIDENTIFICATION.fields_by_name['WebmId'].message_type = _LICENSEREQUEST_CONTENTIDENTIFICATION_WEBM
+_LICENSEREQUEST_CONTENTIDENTIFICATION.fields_by_name['License'].message_type = _LICENSEREQUEST_CONTENTIDENTIFICATION_EXISTINGLICENSE
+_LICENSEREQUEST_CONTENTIDENTIFICATION.containing_type = _LICENSEREQUEST
+_LICENSEREQUEST.fields_by_name['ClientId'].message_type = _CLIENTIDENTIFICATION
+_LICENSEREQUEST.fields_by_name['ContentId'].message_type = _LICENSEREQUEST_CONTENTIDENTIFICATION
+_LICENSEREQUEST.fields_by_name['Type'].enum_type = _LICENSEREQUEST_REQUESTTYPE
+_LICENSEREQUEST.fields_by_name['ProtocolVersion'].enum_type = _PROTOCOLVERSION
+_LICENSEREQUEST.fields_by_name['EncryptedClientId'].message_type = _ENCRYPTEDCLIENTIDENTIFICATION
+_LICENSEREQUEST_REQUESTTYPE.containing_type = _LICENSEREQUEST
+_LICENSEREQUESTRAW_CONTENTIDENTIFICATION_CENC.fields_by_name['LicenseType'].enum_type = _LICENSETYPE
+_LICENSEREQUESTRAW_CONTENTIDENTIFICATION_CENC.containing_type = _LICENSEREQUESTRAW_CONTENTIDENTIFICATION
+_LICENSEREQUESTRAW_CONTENTIDENTIFICATION_WEBM.fields_by_name['LicenseType'].enum_type = _LICENSETYPE
+_LICENSEREQUESTRAW_CONTENTIDENTIFICATION_WEBM.containing_type = _LICENSEREQUESTRAW_CONTENTIDENTIFICATION
+_LICENSEREQUESTRAW_CONTENTIDENTIFICATION_EXISTINGLICENSE.fields_by_name['LicenseId'].message_type = _LICENSEIDENTIFICATION
+_LICENSEREQUESTRAW_CONTENTIDENTIFICATION_EXISTINGLICENSE.containing_type = _LICENSEREQUESTRAW_CONTENTIDENTIFICATION
+_LICENSEREQUESTRAW_CONTENTIDENTIFICATION.fields_by_name['CencId'].message_type = _LICENSEREQUESTRAW_CONTENTIDENTIFICATION_CENC
+_LICENSEREQUESTRAW_CONTENTIDENTIFICATION.fields_by_name['WebmId'].message_type = _LICENSEREQUESTRAW_CONTENTIDENTIFICATION_WEBM
+_LICENSEREQUESTRAW_CONTENTIDENTIFICATION.fields_by_name['License'].message_type = _LICENSEREQUESTRAW_CONTENTIDENTIFICATION_EXISTINGLICENSE
+_LICENSEREQUESTRAW_CONTENTIDENTIFICATION.containing_type = _LICENSEREQUESTRAW
+_LICENSEREQUESTRAW.fields_by_name['ClientId'].message_type = _CLIENTIDENTIFICATION
+_LICENSEREQUESTRAW.fields_by_name['ContentId'].message_type = _LICENSEREQUESTRAW_CONTENTIDENTIFICATION
+_LICENSEREQUESTRAW.fields_by_name['Type'].enum_type = _LICENSEREQUESTRAW_REQUESTTYPE
+_LICENSEREQUESTRAW.fields_by_name['ProtocolVersion'].enum_type = _PROTOCOLVERSION
+_LICENSEREQUESTRAW.fields_by_name['EncryptedClientId'].message_type = _ENCRYPTEDCLIENTIDENTIFICATION
+_LICENSEREQUESTRAW_REQUESTTYPE.containing_type = _LICENSEREQUESTRAW
+_PROVISIONEDDEVICEINFO.fields_by_name['SecurityLevel'].enum_type = _PROVISIONEDDEVICEINFO_WVSECURITYLEVEL
+_PROVISIONEDDEVICEINFO_WVSECURITYLEVEL.containing_type = _PROVISIONEDDEVICEINFO
+_REMOTEATTESTATION.fields_by_name['Certificate'].message_type = _ENCRYPTEDCLIENTIDENTIFICATION
+_SIGNEDDEVICECERTIFICATE.fields_by_name['_DeviceCertificate'].message_type = _DEVICECERTIFICATE
+_SIGNEDDEVICECERTIFICATE.fields_by_name['Signer'].message_type = _SIGNEDDEVICECERTIFICATE
+_SIGNEDMESSAGE.fields_by_name['Type'].enum_type = _SIGNEDMESSAGE_MESSAGETYPE
+_SIGNEDMESSAGE.fields_by_name['RemoteAttestation'].message_type = _REMOTEATTESTATION
+_SIGNEDMESSAGE_MESSAGETYPE.containing_type = _SIGNEDMESSAGE
+_WIDEVINECENCHEADER.fields_by_name['algorithm'].enum_type = _WIDEVINECENCHEADER_ALGORITHM
+_WIDEVINECENCHEADER_ALGORITHM.containing_type = _WIDEVINECENCHEADER
+_SIGNEDLICENSEREQUEST.fields_by_name['Type'].enum_type = _SIGNEDLICENSEREQUEST_MESSAGETYPE
+_SIGNEDLICENSEREQUEST.fields_by_name['Msg'].message_type = _LICENSEREQUEST
+_SIGNEDLICENSEREQUEST.fields_by_name['RemoteAttestation'].message_type = _REMOTEATTESTATION
+_SIGNEDLICENSEREQUEST_MESSAGETYPE.containing_type = _SIGNEDLICENSEREQUEST
+_SIGNEDLICENSEREQUESTRAW.fields_by_name['Type'].enum_type = _SIGNEDLICENSEREQUESTRAW_MESSAGETYPE
+_SIGNEDLICENSEREQUESTRAW.fields_by_name['Msg'].message_type = _LICENSEREQUESTRAW
+_SIGNEDLICENSEREQUESTRAW.fields_by_name['RemoteAttestation'].message_type = _REMOTEATTESTATION
+_SIGNEDLICENSEREQUESTRAW_MESSAGETYPE.containing_type = _SIGNEDLICENSEREQUESTRAW
+_SIGNEDLICENSE.fields_by_name['Type'].enum_type = _SIGNEDLICENSE_MESSAGETYPE
+_SIGNEDLICENSE.fields_by_name['Msg'].message_type = _LICENSE
+_SIGNEDLICENSE.fields_by_name['RemoteAttestation'].message_type = _REMOTEATTESTATION
+_SIGNEDLICENSE_MESSAGETYPE.containing_type = _SIGNEDLICENSE
+_SIGNEDSERVICECERTIFICATE.fields_by_name['Type'].enum_type = _SIGNEDSERVICECERTIFICATE_MESSAGETYPE
+_SIGNEDSERVICECERTIFICATE.fields_by_name['Msg'].message_type = _SIGNEDDEVICECERTIFICATE
+_SIGNEDSERVICECERTIFICATE.fields_by_name['RemoteAttestation'].message_type = _REMOTEATTESTATION
+_SIGNEDSERVICECERTIFICATE_MESSAGETYPE.containing_type = _SIGNEDSERVICECERTIFICATE
+_FILEHASHES_SIGNATURE.containing_type = _FILEHASHES
+_FILEHASHES.fields_by_name['signatures'].message_type = _FILEHASHES_SIGNATURE
+DESCRIPTOR.message_types_by_name['ClientIdentification'] = _CLIENTIDENTIFICATION
+DESCRIPTOR.message_types_by_name['DeviceCertificate'] = _DEVICECERTIFICATE
+DESCRIPTOR.message_types_by_name['DeviceCertificateStatus'] = _DEVICECERTIFICATESTATUS
+DESCRIPTOR.message_types_by_name['DeviceCertificateStatusList'] = _DEVICECERTIFICATESTATUSLIST
+DESCRIPTOR.message_types_by_name['EncryptedClientIdentification'] = _ENCRYPTEDCLIENTIDENTIFICATION
+DESCRIPTOR.message_types_by_name['LicenseIdentification'] = _LICENSEIDENTIFICATION
+DESCRIPTOR.message_types_by_name['License'] = _LICENSE
+DESCRIPTOR.message_types_by_name['LicenseError'] = _LICENSEERROR
+DESCRIPTOR.message_types_by_name['LicenseRequest'] = _LICENSEREQUEST
+DESCRIPTOR.message_types_by_name['LicenseRequestRaw'] = _LICENSEREQUESTRAW
+DESCRIPTOR.message_types_by_name['ProvisionedDeviceInfo'] = _PROVISIONEDDEVICEINFO
+DESCRIPTOR.message_types_by_name['ProvisioningOptions'] = _PROVISIONINGOPTIONS
+DESCRIPTOR.message_types_by_name['ProvisioningRequest'] = _PROVISIONINGREQUEST
+DESCRIPTOR.message_types_by_name['ProvisioningResponse'] = _PROVISIONINGRESPONSE
+DESCRIPTOR.message_types_by_name['RemoteAttestation'] = _REMOTEATTESTATION
+DESCRIPTOR.message_types_by_name['SessionInit'] = _SESSIONINIT
+DESCRIPTOR.message_types_by_name['SessionState'] = _SESSIONSTATE
+DESCRIPTOR.message_types_by_name['SignedCertificateStatusList'] = _SIGNEDCERTIFICATESTATUSLIST
+DESCRIPTOR.message_types_by_name['SignedDeviceCertificate'] = _SIGNEDDEVICECERTIFICATE
+DESCRIPTOR.message_types_by_name['SignedProvisioningMessage'] = _SIGNEDPROVISIONINGMESSAGE
+DESCRIPTOR.message_types_by_name['SignedMessage'] = _SIGNEDMESSAGE
+DESCRIPTOR.message_types_by_name['WidevineCencHeader'] = _WIDEVINECENCHEADER
+DESCRIPTOR.message_types_by_name['SignedLicenseRequest'] = _SIGNEDLICENSEREQUEST
+DESCRIPTOR.message_types_by_name['SignedLicenseRequestRaw'] = _SIGNEDLICENSEREQUESTRAW
+DESCRIPTOR.message_types_by_name['SignedLicense'] = _SIGNEDLICENSE
+DESCRIPTOR.message_types_by_name['SignedServiceCertificate'] = _SIGNEDSERVICECERTIFICATE
+DESCRIPTOR.message_types_by_name['FileHashes'] = _FILEHASHES
+DESCRIPTOR.enum_types_by_name['LicenseType'] = _LICENSETYPE
+DESCRIPTOR.enum_types_by_name['ProtocolVersion'] = _PROTOCOLVERSION
+
+ClientIdentification = _reflection.GeneratedProtocolMessageType('ClientIdentification', (_message.Message,), dict(
+
+ NameValue = _reflection.GeneratedProtocolMessageType('NameValue', (_message.Message,), dict(
+ DESCRIPTOR = _CLIENTIDENTIFICATION_NAMEVALUE,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:ClientIdentification.NameValue)
+ ))
+ ,
+
+ ClientCapabilities = _reflection.GeneratedProtocolMessageType('ClientCapabilities', (_message.Message,), dict(
+ DESCRIPTOR = _CLIENTIDENTIFICATION_CLIENTCAPABILITIES,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:ClientIdentification.ClientCapabilities)
+ ))
+ ,
+ DESCRIPTOR = _CLIENTIDENTIFICATION,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:ClientIdentification)
+ ))
+_sym_db.RegisterMessage(ClientIdentification)
+_sym_db.RegisterMessage(ClientIdentification.NameValue)
+_sym_db.RegisterMessage(ClientIdentification.ClientCapabilities)
+
+DeviceCertificate = _reflection.GeneratedProtocolMessageType('DeviceCertificate', (_message.Message,), dict(
+ DESCRIPTOR = _DEVICECERTIFICATE,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:DeviceCertificate)
+ ))
+_sym_db.RegisterMessage(DeviceCertificate)
+
+DeviceCertificateStatus = _reflection.GeneratedProtocolMessageType('DeviceCertificateStatus', (_message.Message,), dict(
+ DESCRIPTOR = _DEVICECERTIFICATESTATUS,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:DeviceCertificateStatus)
+ ))
+_sym_db.RegisterMessage(DeviceCertificateStatus)
+
+DeviceCertificateStatusList = _reflection.GeneratedProtocolMessageType('DeviceCertificateStatusList', (_message.Message,), dict(
+ DESCRIPTOR = _DEVICECERTIFICATESTATUSLIST,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:DeviceCertificateStatusList)
+ ))
+_sym_db.RegisterMessage(DeviceCertificateStatusList)
+
+EncryptedClientIdentification = _reflection.GeneratedProtocolMessageType('EncryptedClientIdentification', (_message.Message,), dict(
+ DESCRIPTOR = _ENCRYPTEDCLIENTIDENTIFICATION,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:EncryptedClientIdentification)
+ ))
+_sym_db.RegisterMessage(EncryptedClientIdentification)
+
+LicenseIdentification = _reflection.GeneratedProtocolMessageType('LicenseIdentification', (_message.Message,), dict(
+ DESCRIPTOR = _LICENSEIDENTIFICATION,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:LicenseIdentification)
+ ))
+_sym_db.RegisterMessage(LicenseIdentification)
+
+License = _reflection.GeneratedProtocolMessageType('License', (_message.Message,), dict(
+
+ Policy = _reflection.GeneratedProtocolMessageType('Policy', (_message.Message,), dict(
+ DESCRIPTOR = _LICENSE_POLICY,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:License.Policy)
+ ))
+ ,
+
+ KeyContainer = _reflection.GeneratedProtocolMessageType('KeyContainer', (_message.Message,), dict(
+
+ OutputProtection = _reflection.GeneratedProtocolMessageType('OutputProtection', (_message.Message,), dict(
+ DESCRIPTOR = _LICENSE_KEYCONTAINER_OUTPUTPROTECTION,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:License.KeyContainer.OutputProtection)
+ ))
+ ,
+
+ KeyControl = _reflection.GeneratedProtocolMessageType('KeyControl', (_message.Message,), dict(
+ DESCRIPTOR = _LICENSE_KEYCONTAINER_KEYCONTROL,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:License.KeyContainer.KeyControl)
+ ))
+ ,
+
+ OperatorSessionKeyPermissions = _reflection.GeneratedProtocolMessageType('OperatorSessionKeyPermissions', (_message.Message,), dict(
+ DESCRIPTOR = _LICENSE_KEYCONTAINER_OPERATORSESSIONKEYPERMISSIONS,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:License.KeyContainer.OperatorSessionKeyPermissions)
+ ))
+ ,
+
+ VideoResolutionConstraint = _reflection.GeneratedProtocolMessageType('VideoResolutionConstraint', (_message.Message,), dict(
+ DESCRIPTOR = _LICENSE_KEYCONTAINER_VIDEORESOLUTIONCONSTRAINT,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:License.KeyContainer.VideoResolutionConstraint)
+ ))
+ ,
+ DESCRIPTOR = _LICENSE_KEYCONTAINER,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:License.KeyContainer)
+ ))
+ ,
+ DESCRIPTOR = _LICENSE,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:License)
+ ))
+_sym_db.RegisterMessage(License)
+_sym_db.RegisterMessage(License.Policy)
+_sym_db.RegisterMessage(License.KeyContainer)
+_sym_db.RegisterMessage(License.KeyContainer.OutputProtection)
+_sym_db.RegisterMessage(License.KeyContainer.KeyControl)
+_sym_db.RegisterMessage(License.KeyContainer.OperatorSessionKeyPermissions)
+_sym_db.RegisterMessage(License.KeyContainer.VideoResolutionConstraint)
+
+LicenseError = _reflection.GeneratedProtocolMessageType('LicenseError', (_message.Message,), dict(
+ DESCRIPTOR = _LICENSEERROR,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:LicenseError)
+ ))
+_sym_db.RegisterMessage(LicenseError)
+
+LicenseRequest = _reflection.GeneratedProtocolMessageType('LicenseRequest', (_message.Message,), dict(
+
+ ContentIdentification = _reflection.GeneratedProtocolMessageType('ContentIdentification', (_message.Message,), dict(
+
+ CENC = _reflection.GeneratedProtocolMessageType('CENC', (_message.Message,), dict(
+ DESCRIPTOR = _LICENSEREQUEST_CONTENTIDENTIFICATION_CENC,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:LicenseRequest.ContentIdentification.CENC)
+ ))
+ ,
+
+ WebM = _reflection.GeneratedProtocolMessageType('WebM', (_message.Message,), dict(
+ DESCRIPTOR = _LICENSEREQUEST_CONTENTIDENTIFICATION_WEBM,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:LicenseRequest.ContentIdentification.WebM)
+ ))
+ ,
+
+ ExistingLicense = _reflection.GeneratedProtocolMessageType('ExistingLicense', (_message.Message,), dict(
+ DESCRIPTOR = _LICENSEREQUEST_CONTENTIDENTIFICATION_EXISTINGLICENSE,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:LicenseRequest.ContentIdentification.ExistingLicense)
+ ))
+ ,
+ DESCRIPTOR = _LICENSEREQUEST_CONTENTIDENTIFICATION,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:LicenseRequest.ContentIdentification)
+ ))
+ ,
+ DESCRIPTOR = _LICENSEREQUEST,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:LicenseRequest)
+ ))
+_sym_db.RegisterMessage(LicenseRequest)
+_sym_db.RegisterMessage(LicenseRequest.ContentIdentification)
+_sym_db.RegisterMessage(LicenseRequest.ContentIdentification.CENC)
+_sym_db.RegisterMessage(LicenseRequest.ContentIdentification.WebM)
+_sym_db.RegisterMessage(LicenseRequest.ContentIdentification.ExistingLicense)
+
+LicenseRequestRaw = _reflection.GeneratedProtocolMessageType('LicenseRequestRaw', (_message.Message,), dict(
+
+ ContentIdentification = _reflection.GeneratedProtocolMessageType('ContentIdentification', (_message.Message,), dict(
+
+ CENC = _reflection.GeneratedProtocolMessageType('CENC', (_message.Message,), dict(
+ DESCRIPTOR = _LICENSEREQUESTRAW_CONTENTIDENTIFICATION_CENC,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:LicenseRequestRaw.ContentIdentification.CENC)
+ ))
+ ,
+
+ WebM = _reflection.GeneratedProtocolMessageType('WebM', (_message.Message,), dict(
+ DESCRIPTOR = _LICENSEREQUESTRAW_CONTENTIDENTIFICATION_WEBM,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:LicenseRequestRaw.ContentIdentification.WebM)
+ ))
+ ,
+
+ ExistingLicense = _reflection.GeneratedProtocolMessageType('ExistingLicense', (_message.Message,), dict(
+ DESCRIPTOR = _LICENSEREQUESTRAW_CONTENTIDENTIFICATION_EXISTINGLICENSE,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:LicenseRequestRaw.ContentIdentification.ExistingLicense)
+ ))
+ ,
+ DESCRIPTOR = _LICENSEREQUESTRAW_CONTENTIDENTIFICATION,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:LicenseRequestRaw.ContentIdentification)
+ ))
+ ,
+ DESCRIPTOR = _LICENSEREQUESTRAW,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:LicenseRequestRaw)
+ ))
+_sym_db.RegisterMessage(LicenseRequestRaw)
+_sym_db.RegisterMessage(LicenseRequestRaw.ContentIdentification)
+_sym_db.RegisterMessage(LicenseRequestRaw.ContentIdentification.CENC)
+_sym_db.RegisterMessage(LicenseRequestRaw.ContentIdentification.WebM)
+_sym_db.RegisterMessage(LicenseRequestRaw.ContentIdentification.ExistingLicense)
+
+ProvisionedDeviceInfo = _reflection.GeneratedProtocolMessageType('ProvisionedDeviceInfo', (_message.Message,), dict(
+ DESCRIPTOR = _PROVISIONEDDEVICEINFO,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:ProvisionedDeviceInfo)
+ ))
+_sym_db.RegisterMessage(ProvisionedDeviceInfo)
+
+ProvisioningOptions = _reflection.GeneratedProtocolMessageType('ProvisioningOptions', (_message.Message,), dict(
+ DESCRIPTOR = _PROVISIONINGOPTIONS,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:ProvisioningOptions)
+ ))
+_sym_db.RegisterMessage(ProvisioningOptions)
+
+ProvisioningRequest = _reflection.GeneratedProtocolMessageType('ProvisioningRequest', (_message.Message,), dict(
+ DESCRIPTOR = _PROVISIONINGREQUEST,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:ProvisioningRequest)
+ ))
+_sym_db.RegisterMessage(ProvisioningRequest)
+
+ProvisioningResponse = _reflection.GeneratedProtocolMessageType('ProvisioningResponse', (_message.Message,), dict(
+ DESCRIPTOR = _PROVISIONINGRESPONSE,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:ProvisioningResponse)
+ ))
+_sym_db.RegisterMessage(ProvisioningResponse)
+
+RemoteAttestation = _reflection.GeneratedProtocolMessageType('RemoteAttestation', (_message.Message,), dict(
+ DESCRIPTOR = _REMOTEATTESTATION,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:RemoteAttestation)
+ ))
+_sym_db.RegisterMessage(RemoteAttestation)
+
+SessionInit = _reflection.GeneratedProtocolMessageType('SessionInit', (_message.Message,), dict(
+ DESCRIPTOR = _SESSIONINIT,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:SessionInit)
+ ))
+_sym_db.RegisterMessage(SessionInit)
+
+SessionState = _reflection.GeneratedProtocolMessageType('SessionState', (_message.Message,), dict(
+ DESCRIPTOR = _SESSIONSTATE,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:SessionState)
+ ))
+_sym_db.RegisterMessage(SessionState)
+
+SignedCertificateStatusList = _reflection.GeneratedProtocolMessageType('SignedCertificateStatusList', (_message.Message,), dict(
+ DESCRIPTOR = _SIGNEDCERTIFICATESTATUSLIST,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:SignedCertificateStatusList)
+ ))
+_sym_db.RegisterMessage(SignedCertificateStatusList)
+
+SignedDeviceCertificate = _reflection.GeneratedProtocolMessageType('SignedDeviceCertificate', (_message.Message,), dict(
+ DESCRIPTOR = _SIGNEDDEVICECERTIFICATE,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:SignedDeviceCertificate)
+ ))
+_sym_db.RegisterMessage(SignedDeviceCertificate)
+
+SignedProvisioningMessage = _reflection.GeneratedProtocolMessageType('SignedProvisioningMessage', (_message.Message,), dict(
+ DESCRIPTOR = _SIGNEDPROVISIONINGMESSAGE,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:SignedProvisioningMessage)
+ ))
+_sym_db.RegisterMessage(SignedProvisioningMessage)
+
+SignedMessage = _reflection.GeneratedProtocolMessageType('SignedMessage', (_message.Message,), dict(
+ DESCRIPTOR = _SIGNEDMESSAGE,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:SignedMessage)
+ ))
+_sym_db.RegisterMessage(SignedMessage)
+
+WidevineCencHeader = _reflection.GeneratedProtocolMessageType('WidevineCencHeader', (_message.Message,), dict(
+ DESCRIPTOR = _WIDEVINECENCHEADER,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:WidevineCencHeader)
+ ))
+_sym_db.RegisterMessage(WidevineCencHeader)
+
+SignedLicenseRequest = _reflection.GeneratedProtocolMessageType('SignedLicenseRequest', (_message.Message,), dict(
+ DESCRIPTOR = _SIGNEDLICENSEREQUEST,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:SignedLicenseRequest)
+ ))
+_sym_db.RegisterMessage(SignedLicenseRequest)
+
+SignedLicenseRequestRaw = _reflection.GeneratedProtocolMessageType('SignedLicenseRequestRaw', (_message.Message,), dict(
+ DESCRIPTOR = _SIGNEDLICENSEREQUESTRAW,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:SignedLicenseRequestRaw)
+ ))
+_sym_db.RegisterMessage(SignedLicenseRequestRaw)
+
+SignedLicense = _reflection.GeneratedProtocolMessageType('SignedLicense', (_message.Message,), dict(
+ DESCRIPTOR = _SIGNEDLICENSE,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:SignedLicense)
+ ))
+_sym_db.RegisterMessage(SignedLicense)
+
+SignedServiceCertificate = _reflection.GeneratedProtocolMessageType('SignedServiceCertificate', (_message.Message,), dict(
+ DESCRIPTOR = _SIGNEDSERVICECERTIFICATE,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:SignedServiceCertificate)
+ ))
+_sym_db.RegisterMessage(SignedServiceCertificate)
+
+FileHashes = _reflection.GeneratedProtocolMessageType('FileHashes', (_message.Message,), dict(
+
+ Signature = _reflection.GeneratedProtocolMessageType('Signature', (_message.Message,), dict(
+ DESCRIPTOR = _FILEHASHES_SIGNATURE,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:FileHashes.Signature)
+ ))
+ ,
+ DESCRIPTOR = _FILEHASHES,
+ __module__ = 'pywidevine.cdm.formats.wv_proto2_pb2'
+ # @@protoc_insertion_point(class_scope:FileHashes)
+ ))
+_sym_db.RegisterMessage(FileHashes)
+_sym_db.RegisterMessage(FileHashes.Signature)
+
+
+# @@protoc_insertion_point(module_scope)
diff --git a/pywidevine/cdm/formats/wv_proto3.proto b/pywidevine/cdm/formats/wv_proto3.proto
new file mode 100644
index 0000000..7861b02
--- /dev/null
+++ b/pywidevine/cdm/formats/wv_proto3.proto
@@ -0,0 +1,389 @@
+// beware proto3 won't show missing fields it seems, need to change to "proto2" and add "optional" before every field, and remove all the dummy enum members I added:
+syntax = "proto3";
+
+// from x86 (partial), most of it from the ARM version:
+message ClientIdentification {
+ enum TokenType {
+ KEYBOX = 0;
+ DEVICE_CERTIFICATE = 1;
+ REMOTE_ATTESTATION_CERTIFICATE = 2;
+ }
+ message NameValue {
+ string Name = 1;
+ string Value = 2;
+ }
+ message ClientCapabilities {
+ enum HdcpVersion {
+ HDCP_NONE = 0;
+ HDCP_V1 = 1;
+ HDCP_V2 = 2;
+ HDCP_V2_1 = 3;
+ HDCP_V2_2 = 4;
+ }
+ uint32 ClientToken = 1;
+ uint32 SessionToken = 2;
+ uint32 VideoResolutionConstraints = 3;
+ HdcpVersion MaxHdcpVersion = 4;
+ uint32 OemCryptoApiVersion = 5;
+ }
+ TokenType Type = 1;
+ //bytes Token = 2; // by default the client treats this as blob, but it's usually a DeviceCertificate, so for usefulness sake, I'm replacing it with this one:
+ SignedDeviceCertificate Token = 2;
+ repeated NameValue ClientInfo = 3;
+ bytes ProviderClientToken = 4;
+ uint32 LicenseCounter = 5;
+ ClientCapabilities _ClientCapabilities = 6; // how should we deal with duped names? will have to look at proto docs later
+}
+
+message DeviceCertificate {
+ enum CertificateType {
+ ROOT = 0;
+ INTERMEDIATE = 1;
+ USER_DEVICE = 2;
+ SERVICE = 3;
+ }
+ //ProvisionedDeviceInfo.WvSecurityLevel Type = 1; // is this how one is supposed to call it? (it's an enum) there might be a bug here, with CertificateType getting confused with WvSecurityLevel, for now renaming it (verify against other binaries)
+ CertificateType Type = 1;
+ bytes SerialNumber = 2;
+ uint32 CreationTimeSeconds = 3;
+ bytes PublicKey = 4;
+ uint32 SystemId = 5;
+ uint32 TestDeviceDeprecated = 6; // is it bool or int?
+ bytes ServiceId = 7; // service URL for service certificates
+}
+
+// missing some references,
+message DeviceCertificateStatus {
+ enum CertificateStatus {
+ VALID = 0;
+ REVOKED = 1;
+ }
+ bytes SerialNumber = 1;
+ CertificateStatus Status = 2;
+ ProvisionedDeviceInfo DeviceInfo = 4; // where is 3? is it deprecated?
+}
+
+message DeviceCertificateStatusList {
+ uint32 CreationTimeSeconds = 1;
+ repeated DeviceCertificateStatus CertificateStatus = 2;
+}
+
+message EncryptedClientIdentification {
+ string ServiceId = 1;
+ bytes ServiceCertificateSerialNumber = 2;
+ bytes EncryptedClientId = 3;
+ bytes EncryptedClientIdIv = 4;
+ bytes EncryptedPrivacyKey = 5;
+}
+
+// todo: fill (for this top-level type, it might be impossible/difficult)
+enum LicenseType {
+ ZERO = 0;
+ DEFAULT = 1; // do not know what this is either, but should be 1; on recent versions may go up to 3 (latest x86)
+}
+
+// todo: fill (for this top-level type, it might be impossible/difficult)
+// this is just a guess because these globals got lost, but really, do we need more?
+enum ProtocolVersion {
+ DUMMY = 0;
+ CURRENT = 21; // don't have symbols for this
+}
+
+
+message LicenseIdentification {
+ bytes RequestId = 1;
+ bytes SessionId = 2;
+ bytes PurchaseId = 3;
+ LicenseType Type = 4;
+ uint32 Version = 5;
+ bytes ProviderSessionToken = 6;
+}
+
+
+message License {
+ message Policy {
+ uint32 CanPlay = 1;
+ uint32 CanPersist = 2;
+ uint32 CanRenew = 3;
+ uint32 RentalDurationSeconds = 4;
+ uint32 PlaybackDurationSeconds = 5;
+ uint32 LicenseDurationSeconds = 6;
+ uint32 RenewalRecoveryDurationSeconds = 7;
+ string RenewalServerUrl = 8;
+ uint32 RenewalDelaySeconds = 9;
+ uint32 RenewalRetryIntervalSeconds = 10;
+ uint32 RenewWithUsage = 11;
+ uint32 UnknownPolicy12 = 12;
+ }
+ message KeyContainer {
+ enum KeyType {
+ _NOKEYTYPE = 0; // dummy, added to satisfy proto3, not present in original
+ SIGNING = 1;
+ CONTENT = 2;
+ KEY_CONTROL = 3;
+ OPERATOR_SESSION = 4;
+ }
+ enum SecurityLevel {
+ _NOSECLEVEL = 0; // dummy, added to satisfy proto3, not present in original
+ SW_SECURE_CRYPTO = 1;
+ SW_SECURE_DECODE = 2;
+ HW_SECURE_CRYPTO = 3;
+ HW_SECURE_DECODE = 4;
+ HW_SECURE_ALL = 5;
+ }
+ message OutputProtection {
+ enum CGMS {
+ COPY_FREE = 0;
+ COPY_ONCE = 2;
+ COPY_NEVER = 3;
+ CGMS_NONE = 0x2A; // PC default!
+ }
+ ClientIdentification.ClientCapabilities.HdcpVersion Hdcp = 1; // it's most likely a copy of Hdcp version available here, but compiler optimized it away
+ CGMS CgmsFlags = 2;
+ }
+ message KeyControl {
+ bytes KeyControlBlock = 1; // what is this?
+ bytes Iv = 2;
+ }
+ message OperatorSessionKeyPermissions {
+ uint32 AllowEncrypt = 1;
+ uint32 AllowDecrypt = 2;
+ uint32 AllowSign = 3;
+ uint32 AllowSignatureVerify = 4;
+ }
+ message VideoResolutionConstraint {
+ uint32 MinResolutionPixels = 1;
+ uint32 MaxResolutionPixels = 2;
+ OutputProtection RequiredProtection = 3;
+ }
+ bytes Id = 1;
+ bytes Iv = 2;
+ bytes Key = 3;
+ KeyType Type = 4;
+ SecurityLevel Level = 5;
+ OutputProtection RequiredProtection = 6;
+ OutputProtection RequestedProtection = 7;
+ KeyControl _KeyControl = 8; // duped names, etc
+ OperatorSessionKeyPermissions _OperatorSessionKeyPermissions = 9; // duped names, etc
+ repeated VideoResolutionConstraint VideoResolutionConstraints = 10;
+ }
+ LicenseIdentification Id = 1;
+ Policy _Policy = 2; // duped names, etc
+ repeated KeyContainer Key = 3;
+ uint32 LicenseStartTime = 4;
+ uint32 RemoteAttestationVerified = 5; // bool?
+ bytes ProviderClientToken = 6;
+ // there might be more, check with newer versions (I see field 7-8 in a lic)
+ // this appeared in latest x86:
+ uint32 ProtectionScheme = 7; // type unconfirmed fully, but it's likely as WidevineCencHeader describesit (fourcc)
+ bytes UnknownHdcpDataField = 8;
+}
+
+message LicenseError {
+ enum Error {
+ DUMMY_NO_ERROR = 0; // dummy, added to satisfy proto3
+ INVALID_DEVICE_CERTIFICATE = 1;
+ REVOKED_DEVICE_CERTIFICATE = 2;
+ SERVICE_UNAVAILABLE = 3;
+ }
+ //LicenseRequest.RequestType ErrorCode; // clang mismatch
+ Error ErrorCode = 1;
+}
+
+message LicenseRequest {
+ message ContentIdentification {
+ message CENC {
+ // bytes Pssh = 1; // the client's definition is opaque, it doesn't care about the contents, but the PSSH has a clear definition that is understood and requested by the server, thus I'll replace it with:
+ WidevineCencHeader Pssh = 1;
+ LicenseType LicenseType = 2; // unfortunately the LicenseType symbols are not present, acceptable value seems to only be 1
+ bytes RequestId = 3;
+ }
+ message WebM {
+ bytes Header = 1; // identical to CENC, aside from PSSH and the parent field number used
+ LicenseType LicenseType = 2;
+ bytes RequestId = 3;
+ }
+ message ExistingLicense {
+ LicenseIdentification LicenseId = 1;
+ uint32 SecondsSinceStarted = 2;
+ uint32 SecondsSinceLastPlayed = 3;
+ bytes SessionUsageTableEntry = 4;
+ }
+ CENC CencId = 1;
+ WebM WebmId = 2;
+ ExistingLicense License = 3;
+ }
+ enum RequestType {
+ DUMMY_REQ_TYPE = 0; // dummy, added to satisfy proto3
+ NEW = 1;
+ RENEWAL = 2;
+ RELEASE = 3;
+ }
+ ClientIdentification ClientId = 1;
+ ContentIdentification ContentId = 2;
+ RequestType Type = 3;
+ uint32 RequestTime = 4;
+ bytes KeyControlNonceDeprecated = 5;
+ ProtocolVersion ProtocolVersion = 6; // lacking symbols for this
+ uint32 KeyControlNonce = 7;
+ EncryptedClientIdentification EncryptedClientId = 8;
+}
+
+message ProvisionedDeviceInfo {
+ enum WvSecurityLevel {
+ LEVEL_UNSPECIFIED = 0;
+ LEVEL_1 = 1;
+ LEVEL_2 = 2;
+ LEVEL_3 = 3;
+ }
+ uint32 SystemId = 1;
+ string Soc = 2;
+ string Manufacturer = 3;
+ string Model = 4;
+ string DeviceType = 5;
+ uint32 ModelYear = 6;
+ WvSecurityLevel SecurityLevel = 7;
+ uint32 TestDevice = 8; // bool?
+}
+
+
+// todo: fill
+message ProvisioningOptions {
+}
+
+// todo: fill
+message ProvisioningRequest {
+}
+
+// todo: fill
+message ProvisioningResponse {
+}
+
+message RemoteAttestation {
+ EncryptedClientIdentification Certificate = 1;
+ string Salt = 2;
+ string Signature = 3;
+}
+
+// todo: fill
+message SessionInit {
+}
+
+// todo: fill
+message SessionState {
+}
+
+// todo: fill
+message SignedCertificateStatusList {
+}
+
+message SignedDeviceCertificate {
+
+ //bytes DeviceCertificate = 1; // again, they use a buffer where it's supposed to be a message, so we'll replace it with what it really is:
+ DeviceCertificate _DeviceCertificate = 1; // how should we deal with duped names? will have to look at proto docs later
+ bytes Signature = 2;
+ SignedDeviceCertificate Signer = 3;
+}
+
+
+// todo: fill
+message SignedProvisioningMessage {
+}
+
+// the root of all messages, from either server or client
+message SignedMessage {
+ enum MessageType {
+ DUMMY_MSG_TYPE = 0; // dummy, added to satisfy proto3
+ LICENSE_REQUEST = 1;
+ LICENSE = 2;
+ ERROR_RESPONSE = 3;
+ SERVICE_CERTIFICATE_REQUEST = 4;
+ SERVICE_CERTIFICATE = 5;
+ }
+ MessageType Type = 1; // has in incorrect overlap with License_KeyContainer_SecurityLevel
+ bytes Msg = 2; // this has to be casted dynamically, to LicenseRequest, License or LicenseError (? unconfirmed), for Request, no other fields but Type need to be present
+ // for SERVICE_CERTIFICATE, only Type and Msg are present, and it's just a DeviceCertificate with CertificateType set to SERVICE
+ bytes Signature = 3; // might be different type of signatures (ex. RSA vs AES CMAC(??), unconfirmed for now)
+ bytes SessionKey = 4; // often RSA wrapped for licenses
+ RemoteAttestation RemoteAttestation = 5;
+}
+
+
+
+// This message is copied from google's docs, not reversed:
+message WidevineCencHeader {
+ enum Algorithm {
+ UNENCRYPTED = 0;
+ AESCTR = 1;
+ };
+ Algorithm algorithm = 1;
+ repeated bytes key_id = 2;
+
+ // Content provider name.
+ string provider = 3;
+
+ // A content identifier, specified by content provider.
+ bytes content_id = 4;
+
+ // Track type. Acceptable values are SD, HD and AUDIO. Used to
+ // differentiate content keys used by an asset.
+ string track_type_deprecated = 5;
+
+ // The name of a registered policy to be used for this asset.
+ string policy = 6;
+
+ // Crypto period index, for media using key rotation.
+ uint32 crypto_period_index = 7;
+
+ // Optional protected context for group content. The grouped_license is a
+ // serialized SignedMessage.
+ bytes grouped_license = 8;
+
+ // Protection scheme identifying the encryption algorithm.
+ // Represented as one of the following 4CC values:
+ // 'cenc' (AESCTR), 'cbc1' (AESCBC),
+ // 'cens' (AESCTR subsample), 'cbcs' (AESCBC subsample).
+ uint32 protection_scheme = 9;
+
+ // Optional. For media using key rotation, this represents the duration
+ // of each crypto period in seconds.
+ uint32 crypto_period_seconds = 10;
+}
+
+
+
+
+// from here on, it's just for testing, these messages don't exist in the binaries, I'm adding them to avoid detecting type programmatically
+message SignedLicenseRequest {
+ enum MessageType {
+ DUMMY_MSG_TYPE = 0; // dummy, added to satisfy proto3
+ LICENSE_REQUEST = 1;
+ LICENSE = 2;
+ ERROR_RESPONSE = 3;
+ SERVICE_CERTIFICATE_REQUEST = 4;
+ SERVICE_CERTIFICATE = 5;
+ }
+ MessageType Type = 1; // has in incorrect overlap with License_KeyContainer_SecurityLevel
+ LicenseRequest Msg = 2; // this has to be casted dynamically, to LicenseRequest, License or LicenseError (? unconfirmed), for Request, no other fields but Type need to be present
+ // for SERVICE_CERTIFICATE, only Type and Msg are present, and it's just a DeviceCertificate with CertificateType set to SERVICE
+ bytes Signature = 3; // might be different type of signatures (ex. RSA vs AES CMAC(??), unconfirmed for now)
+ bytes SessionKey = 4; // often RSA wrapped for licenses
+ RemoteAttestation RemoteAttestation = 5;
+}
+
+message SignedLicense {
+ enum MessageType {
+ DUMMY_MSG_TYPE = 0; // dummy, added to satisfy proto3
+ LICENSE_REQUEST = 1;
+ LICENSE = 2;
+ ERROR_RESPONSE = 3;
+ SERVICE_CERTIFICATE_REQUEST = 4;
+ SERVICE_CERTIFICATE = 5;
+ }
+ MessageType Type = 1; // has in incorrect overlap with License_KeyContainer_SecurityLevel
+ License Msg = 2; // this has to be casted dynamically, to LicenseRequest, License or LicenseError (? unconfirmed), for Request, no other fields but Type need to be present
+ // for SERVICE_CERTIFICATE, only Type and Msg are present, and it's just a DeviceCertificate with CertificateType set to SERVICE
+ bytes Signature = 3; // might be different type of signatures (ex. RSA vs AES CMAC(??), unconfirmed for now)
+ bytes SessionKey = 4; // often RSA wrapped for licenses
+ RemoteAttestation RemoteAttestation = 5;
+}
\ No newline at end of file
diff --git a/pywidevine/cdm/formats/wv_proto3_pb2.py b/pywidevine/cdm/formats/wv_proto3_pb2.py
new file mode 100644
index 0000000..11ae09f
--- /dev/null
+++ b/pywidevine/cdm/formats/wv_proto3_pb2.py
@@ -0,0 +1,2686 @@
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: wv_proto3.proto
+
+import sys
+_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
+from google.protobuf.internal import enum_type_wrapper
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import message as _message
+from google.protobuf import reflection as _reflection
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf import descriptor_pb2
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor.FileDescriptor(
+ name='wv_proto3.proto',
+ package='',
+ syntax='proto3',
+ serialized_pb=_b('\n\x0fwv_proto3.proto\"\xc5\x05\n\x14\x43lientIdentification\x12-\n\x04Type\x18\x01 \x01(\x0e\x32\x1f.ClientIdentification.TokenType\x12\'\n\x05Token\x18\x02 \x01(\x0b\x32\x18.SignedDeviceCertificate\x12\x33\n\nClientInfo\x18\x03 \x03(\x0b\x32\x1f.ClientIdentification.NameValue\x12\x1b\n\x13ProviderClientToken\x18\x04 \x01(\x0c\x12\x16\n\x0eLicenseCounter\x18\x05 \x01(\r\x12\x45\n\x13_ClientCapabilities\x18\x06 \x01(\x0b\x32(.ClientIdentification.ClientCapabilities\x1a(\n\tNameValue\x12\x0c\n\x04Name\x18\x01 \x01(\t\x12\r\n\x05Value\x18\x02 \x01(\t\x1a\xa4\x02\n\x12\x43lientCapabilities\x12\x13\n\x0b\x43lientToken\x18\x01 \x01(\r\x12\x14\n\x0cSessionToken\x18\x02 \x01(\r\x12\"\n\x1aVideoResolutionConstraints\x18\x03 \x01(\r\x12L\n\x0eMaxHdcpVersion\x18\x04 \x01(\x0e\x32\x34.ClientIdentification.ClientCapabilities.HdcpVersion\x12\x1b\n\x13OemCryptoApiVersion\x18\x05 \x01(\r\"T\n\x0bHdcpVersion\x12\r\n\tHDCP_NONE\x10\x00\x12\x0b\n\x07HDCP_V1\x10\x01\x12\x0b\n\x07HDCP_V2\x10\x02\x12\r\n\tHDCP_V2_1\x10\x03\x12\r\n\tHDCP_V2_2\x10\x04\"S\n\tTokenType\x12\n\n\x06KEYBOX\x10\x00\x12\x16\n\x12\x44\x45VICE_CERTIFICATE\x10\x01\x12\"\n\x1eREMOTE_ATTESTATION_CERTIFICATE\x10\x02\"\x9b\x02\n\x11\x44\x65viceCertificate\x12\x30\n\x04Type\x18\x01 \x01(\x0e\x32\".DeviceCertificate.CertificateType\x12\x14\n\x0cSerialNumber\x18\x02 \x01(\x0c\x12\x1b\n\x13\x43reationTimeSeconds\x18\x03 \x01(\r\x12\x11\n\tPublicKey\x18\x04 \x01(\x0c\x12\x10\n\x08SystemId\x18\x05 \x01(\r\x12\x1c\n\x14TestDeviceDeprecated\x18\x06 \x01(\r\x12\x11\n\tServiceId\x18\x07 \x01(\x0c\"K\n\x0f\x43\x65rtificateType\x12\x08\n\x04ROOT\x10\x00\x12\x10\n\x0cINTERMEDIATE\x10\x01\x12\x0f\n\x0bUSER_DEVICE\x10\x02\x12\x0b\n\x07SERVICE\x10\x03\"\xc4\x01\n\x17\x44\x65viceCertificateStatus\x12\x14\n\x0cSerialNumber\x18\x01 \x01(\x0c\x12:\n\x06Status\x18\x02 \x01(\x0e\x32*.DeviceCertificateStatus.CertificateStatus\x12*\n\nDeviceInfo\x18\x04 \x01(\x0b\x32\x16.ProvisionedDeviceInfo\"+\n\x11\x43\x65rtificateStatus\x12\t\n\x05VALID\x10\x00\x12\x0b\n\x07REVOKED\x10\x01\"o\n\x1b\x44\x65viceCertificateStatusList\x12\x1b\n\x13\x43reationTimeSeconds\x18\x01 \x01(\r\x12\x33\n\x11\x43\x65rtificateStatus\x18\x02 \x03(\x0b\x32\x18.DeviceCertificateStatus\"\xaf\x01\n\x1d\x45ncryptedClientIdentification\x12\x11\n\tServiceId\x18\x01 \x01(\t\x12&\n\x1eServiceCertificateSerialNumber\x18\x02 \x01(\x0c\x12\x19\n\x11\x45ncryptedClientId\x18\x03 \x01(\x0c\x12\x1b\n\x13\x45ncryptedClientIdIv\x18\x04 \x01(\x0c\x12\x1b\n\x13\x45ncryptedPrivacyKey\x18\x05 \x01(\x0c\"\x9c\x01\n\x15LicenseIdentification\x12\x11\n\tRequestId\x18\x01 \x01(\x0c\x12\x11\n\tSessionId\x18\x02 \x01(\x0c\x12\x12\n\nPurchaseId\x18\x03 \x01(\x0c\x12\x1a\n\x04Type\x18\x04 \x01(\x0e\x32\x0c.LicenseType\x12\x0f\n\x07Version\x18\x05 \x01(\r\x12\x1c\n\x14ProviderSessionToken\x18\x06 \x01(\x0c\"\xfa\x0e\n\x07License\x12\"\n\x02Id\x18\x01 \x01(\x0b\x32\x16.LicenseIdentification\x12 \n\x07_Policy\x18\x02 \x01(\x0b\x32\x0f.License.Policy\x12\"\n\x03Key\x18\x03 \x03(\x0b\x32\x15.License.KeyContainer\x12\x18\n\x10LicenseStartTime\x18\x04 \x01(\r\x12!\n\x19RemoteAttestationVerified\x18\x05 \x01(\r\x12\x1b\n\x13ProviderClientToken\x18\x06 \x01(\x0c\x12\x18\n\x10ProtectionScheme\x18\x07 \x01(\r\x12\x1c\n\x14UnknownHdcpDataField\x18\x08 \x01(\x0c\x1a\xd4\x02\n\x06Policy\x12\x0f\n\x07\x43\x61nPlay\x18\x01 \x01(\r\x12\x12\n\nCanPersist\x18\x02 \x01(\r\x12\x10\n\x08\x43\x61nRenew\x18\x03 \x01(\r\x12\x1d\n\x15RentalDurationSeconds\x18\x04 \x01(\r\x12\x1f\n\x17PlaybackDurationSeconds\x18\x05 \x01(\r\x12\x1e\n\x16LicenseDurationSeconds\x18\x06 \x01(\r\x12&\n\x1eRenewalRecoveryDurationSeconds\x18\x07 \x01(\r\x12\x18\n\x10RenewalServerUrl\x18\x08 \x01(\t\x12\x1b\n\x13RenewalDelaySeconds\x18\t \x01(\r\x12#\n\x1bRenewalRetryIntervalSeconds\x18\n \x01(\r\x12\x16\n\x0eRenewWithUsage\x18\x0b \x01(\r\x12\x17\n\x0fUnknownPolicy12\x18\x0c \x01(\r\x1a\x9b\n\n\x0cKeyContainer\x12\n\n\x02Id\x18\x01 \x01(\x0c\x12\n\n\x02Iv\x18\x02 \x01(\x0c\x12\x0b\n\x03Key\x18\x03 \x01(\x0c\x12+\n\x04Type\x18\x04 \x01(\x0e\x32\x1d.License.KeyContainer.KeyType\x12\x32\n\x05Level\x18\x05 \x01(\x0e\x32#.License.KeyContainer.SecurityLevel\x12\x42\n\x12RequiredProtection\x18\x06 \x01(\x0b\x32&.License.KeyContainer.OutputProtection\x12\x43\n\x13RequestedProtection\x18\x07 \x01(\x0b\x32&.License.KeyContainer.OutputProtection\x12\x35\n\x0b_KeyControl\x18\x08 \x01(\x0b\x32 .License.KeyContainer.KeyControl\x12[\n\x1e_OperatorSessionKeyPermissions\x18\t \x01(\x0b\x32\x33.License.KeyContainer.OperatorSessionKeyPermissions\x12S\n\x1aVideoResolutionConstraints\x18\n \x03(\x0b\x32/.License.KeyContainer.VideoResolutionConstraint\x1a\xdb\x01\n\x10OutputProtection\x12\x42\n\x04Hdcp\x18\x01 \x01(\x0e\x32\x34.ClientIdentification.ClientCapabilities.HdcpVersion\x12>\n\tCgmsFlags\x18\x02 \x01(\x0e\x32+.License.KeyContainer.OutputProtection.CGMS\"C\n\x04\x43GMS\x12\r\n\tCOPY_FREE\x10\x00\x12\r\n\tCOPY_ONCE\x10\x02\x12\x0e\n\nCOPY_NEVER\x10\x03\x12\r\n\tCGMS_NONE\x10*\x1a\x31\n\nKeyControl\x12\x17\n\x0fKeyControlBlock\x18\x01 \x01(\x0c\x12\n\n\x02Iv\x18\x02 \x01(\x0c\x1a|\n\x1dOperatorSessionKeyPermissions\x12\x14\n\x0c\x41llowEncrypt\x18\x01 \x01(\r\x12\x14\n\x0c\x41llowDecrypt\x18\x02 \x01(\r\x12\x11\n\tAllowSign\x18\x03 \x01(\r\x12\x1c\n\x14\x41llowSignatureVerify\x18\x04 \x01(\r\x1a\x99\x01\n\x19VideoResolutionConstraint\x12\x1b\n\x13MinResolutionPixels\x18\x01 \x01(\r\x12\x1b\n\x13MaxResolutionPixels\x18\x02 \x01(\r\x12\x42\n\x12RequiredProtection\x18\x03 \x01(\x0b\x32&.License.KeyContainer.OutputProtection\"Z\n\x07KeyType\x12\x0e\n\n_NOKEYTYPE\x10\x00\x12\x0b\n\x07SIGNING\x10\x01\x12\x0b\n\x07\x43ONTENT\x10\x02\x12\x0f\n\x0bKEY_CONTROL\x10\x03\x12\x14\n\x10OPERATOR_SESSION\x10\x04\"\x8b\x01\n\rSecurityLevel\x12\x0f\n\x0b_NOSECLEVEL\x10\x00\x12\x14\n\x10SW_SECURE_CRYPTO\x10\x01\x12\x14\n\x10SW_SECURE_DECODE\x10\x02\x12\x14\n\x10HW_SECURE_CRYPTO\x10\x03\x12\x14\n\x10HW_SECURE_DECODE\x10\x04\x12\x11\n\rHW_SECURE_ALL\x10\x05\"\xac\x01\n\x0cLicenseError\x12&\n\tErrorCode\x18\x01 \x01(\x0e\x32\x13.LicenseError.Error\"t\n\x05\x45rror\x12\x12\n\x0e\x44UMMY_NO_ERROR\x10\x00\x12\x1e\n\x1aINVALID_DEVICE_CERTIFICATE\x10\x01\x12\x1e\n\x1aREVOKED_DEVICE_CERTIFICATE\x10\x02\x12\x17\n\x13SERVICE_UNAVAILABLE\x10\x03\"\xc0\x07\n\x0eLicenseRequest\x12\'\n\x08\x43lientId\x18\x01 \x01(\x0b\x32\x15.ClientIdentification\x12\x38\n\tContentId\x18\x02 \x01(\x0b\x32%.LicenseRequest.ContentIdentification\x12)\n\x04Type\x18\x03 \x01(\x0e\x32\x1b.LicenseRequest.RequestType\x12\x13\n\x0bRequestTime\x18\x04 \x01(\r\x12!\n\x19KeyControlNonceDeprecated\x18\x05 \x01(\x0c\x12)\n\x0fProtocolVersion\x18\x06 \x01(\x0e\x32\x10.ProtocolVersion\x12\x17\n\x0fKeyControlNonce\x18\x07 \x01(\r\x12\x39\n\x11\x45ncryptedClientId\x18\x08 \x01(\x0b\x32\x1e.EncryptedClientIdentification\x1a\xa2\x04\n\x15\x43ontentIdentification\x12:\n\x06\x43\x65ncId\x18\x01 \x01(\x0b\x32*.LicenseRequest.ContentIdentification.CENC\x12:\n\x06WebmId\x18\x02 \x01(\x0b\x32*.LicenseRequest.ContentIdentification.WebM\x12\x46\n\x07License\x18\x03 \x01(\x0b\x32\x35.LicenseRequest.ContentIdentification.ExistingLicense\x1a_\n\x04\x43\x45NC\x12!\n\x04Pssh\x18\x01 \x01(\x0b\x32\x13.WidevineCencHeader\x12!\n\x0bLicenseType\x18\x02 \x01(\x0e\x32\x0c.LicenseType\x12\x11\n\tRequestId\x18\x03 \x01(\x0c\x1aL\n\x04WebM\x12\x0e\n\x06Header\x18\x01 \x01(\x0c\x12!\n\x0bLicenseType\x18\x02 \x01(\x0e\x32\x0c.LicenseType\x12\x11\n\tRequestId\x18\x03 \x01(\x0c\x1a\x99\x01\n\x0f\x45xistingLicense\x12)\n\tLicenseId\x18\x01 \x01(\x0b\x32\x16.LicenseIdentification\x12\x1b\n\x13SecondsSinceStarted\x18\x02 \x01(\r\x12\x1e\n\x16SecondsSinceLastPlayed\x18\x03 \x01(\r\x12\x1e\n\x16SessionUsageTableEntry\x18\x04 \x01(\x0c\"D\n\x0bRequestType\x12\x12\n\x0e\x44UMMY_REQ_TYPE\x10\x00\x12\x07\n\x03NEW\x10\x01\x12\x0b\n\x07RENEWAL\x10\x02\x12\x0b\n\x07RELEASE\x10\x03\"\xa6\x02\n\x15ProvisionedDeviceInfo\x12\x10\n\x08SystemId\x18\x01 \x01(\r\x12\x0b\n\x03Soc\x18\x02 \x01(\t\x12\x14\n\x0cManufacturer\x18\x03 \x01(\t\x12\r\n\x05Model\x18\x04 \x01(\t\x12\x12\n\nDeviceType\x18\x05 \x01(\t\x12\x11\n\tModelYear\x18\x06 \x01(\r\x12=\n\rSecurityLevel\x18\x07 \x01(\x0e\x32&.ProvisionedDeviceInfo.WvSecurityLevel\x12\x12\n\nTestDevice\x18\x08 \x01(\r\"O\n\x0fWvSecurityLevel\x12\x15\n\x11LEVEL_UNSPECIFIED\x10\x00\x12\x0b\n\x07LEVEL_1\x10\x01\x12\x0b\n\x07LEVEL_2\x10\x02\x12\x0b\n\x07LEVEL_3\x10\x03\"\x15\n\x13ProvisioningOptions\"\x15\n\x13ProvisioningRequest\"\x16\n\x14ProvisioningResponse\"i\n\x11RemoteAttestation\x12\x33\n\x0b\x43\x65rtificate\x18\x01 \x01(\x0b\x32\x1e.EncryptedClientIdentification\x12\x0c\n\x04Salt\x18\x02 \x01(\t\x12\x11\n\tSignature\x18\x03 \x01(\t\"\r\n\x0bSessionInit\"\x0e\n\x0cSessionState\"\x1d\n\x1bSignedCertificateStatusList\"\x86\x01\n\x17SignedDeviceCertificate\x12.\n\x12_DeviceCertificate\x18\x01 \x01(\x0b\x32\x12.DeviceCertificate\x12\x11\n\tSignature\x18\x02 \x01(\x0c\x12(\n\x06Signer\x18\x03 \x01(\x0b\x32\x18.SignedDeviceCertificate\"\x1b\n\x19SignedProvisioningMessage\"\xb0\x02\n\rSignedMessage\x12(\n\x04Type\x18\x01 \x01(\x0e\x32\x1a.SignedMessage.MessageType\x12\x0b\n\x03Msg\x18\x02 \x01(\x0c\x12\x11\n\tSignature\x18\x03 \x01(\x0c\x12\x12\n\nSessionKey\x18\x04 \x01(\x0c\x12-\n\x11RemoteAttestation\x18\x05 \x01(\x0b\x32\x12.RemoteAttestation\"\x91\x01\n\x0bMessageType\x12\x12\n\x0e\x44UMMY_MSG_TYPE\x10\x00\x12\x13\n\x0fLICENSE_REQUEST\x10\x01\x12\x0b\n\x07LICENSE\x10\x02\x12\x12\n\x0e\x45RROR_RESPONSE\x10\x03\x12\x1f\n\x1bSERVICE_CERTIFICATE_REQUEST\x10\x04\x12\x17\n\x13SERVICE_CERTIFICATE\x10\x05\"\xc5\x02\n\x12WidevineCencHeader\x12\x30\n\talgorithm\x18\x01 \x01(\x0e\x32\x1d.WidevineCencHeader.Algorithm\x12\x0e\n\x06key_id\x18\x02 \x03(\x0c\x12\x10\n\x08provider\x18\x03 \x01(\t\x12\x12\n\ncontent_id\x18\x04 \x01(\x0c\x12\x1d\n\x15track_type_deprecated\x18\x05 \x01(\t\x12\x0e\n\x06policy\x18\x06 \x01(\t\x12\x1b\n\x13\x63rypto_period_index\x18\x07 \x01(\r\x12\x17\n\x0fgrouped_license\x18\x08 \x01(\x0c\x12\x19\n\x11protection_scheme\x18\t \x01(\r\x12\x1d\n\x15\x63rypto_period_seconds\x18\n \x01(\r\"(\n\tAlgorithm\x12\x0f\n\x0bUNENCRYPTED\x10\x00\x12\n\n\x06\x41\x45SCTR\x10\x01\"\xcf\x02\n\x14SignedLicenseRequest\x12/\n\x04Type\x18\x01 \x01(\x0e\x32!.SignedLicenseRequest.MessageType\x12\x1c\n\x03Msg\x18\x02 \x01(\x0b\x32\x0f.LicenseRequest\x12\x11\n\tSignature\x18\x03 \x01(\x0c\x12\x12\n\nSessionKey\x18\x04 \x01(\x0c\x12-\n\x11RemoteAttestation\x18\x05 \x01(\x0b\x32\x12.RemoteAttestation\"\x91\x01\n\x0bMessageType\x12\x12\n\x0e\x44UMMY_MSG_TYPE\x10\x00\x12\x13\n\x0fLICENSE_REQUEST\x10\x01\x12\x0b\n\x07LICENSE\x10\x02\x12\x12\n\x0e\x45RROR_RESPONSE\x10\x03\x12\x1f\n\x1bSERVICE_CERTIFICATE_REQUEST\x10\x04\x12\x17\n\x13SERVICE_CERTIFICATE\x10\x05\"\xba\x02\n\rSignedLicense\x12(\n\x04Type\x18\x01 \x01(\x0e\x32\x1a.SignedLicense.MessageType\x12\x15\n\x03Msg\x18\x02 \x01(\x0b\x32\x08.License\x12\x11\n\tSignature\x18\x03 \x01(\x0c\x12\x12\n\nSessionKey\x18\x04 \x01(\x0c\x12-\n\x11RemoteAttestation\x18\x05 \x01(\x0b\x32\x12.RemoteAttestation\"\x91\x01\n\x0bMessageType\x12\x12\n\x0e\x44UMMY_MSG_TYPE\x10\x00\x12\x13\n\x0fLICENSE_REQUEST\x10\x01\x12\x0b\n\x07LICENSE\x10\x02\x12\x12\n\x0e\x45RROR_RESPONSE\x10\x03\x12\x1f\n\x1bSERVICE_CERTIFICATE_REQUEST\x10\x04\x12\x17\n\x13SERVICE_CERTIFICATE\x10\x05*$\n\x0bLicenseType\x12\x08\n\x04ZERO\x10\x00\x12\x0b\n\x07\x44\x45\x46\x41ULT\x10\x01*)\n\x0fProtocolVersion\x12\t\n\x05\x44UMMY\x10\x00\x12\x0b\n\x07\x43URRENT\x10\x15\x62\x06proto3')
+)
+
+_LICENSETYPE = _descriptor.EnumDescriptor(
+ name='LicenseType',
+ full_name='LicenseType',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='ZERO', index=0, number=0,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='DEFAULT', index=1, number=1,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=6713,
+ serialized_end=6749,
+)
+_sym_db.RegisterEnumDescriptor(_LICENSETYPE)
+
+LicenseType = enum_type_wrapper.EnumTypeWrapper(_LICENSETYPE)
+_PROTOCOLVERSION = _descriptor.EnumDescriptor(
+ name='ProtocolVersion',
+ full_name='ProtocolVersion',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='DUMMY', index=0, number=0,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='CURRENT', index=1, number=21,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=6751,
+ serialized_end=6792,
+)
+_sym_db.RegisterEnumDescriptor(_PROTOCOLVERSION)
+
+ProtocolVersion = enum_type_wrapper.EnumTypeWrapper(_PROTOCOLVERSION)
+ZERO = 0
+DEFAULT = 1
+DUMMY = 0
+CURRENT = 21
+
+
+_CLIENTIDENTIFICATION_CLIENTCAPABILITIES_HDCPVERSION = _descriptor.EnumDescriptor(
+ name='HdcpVersion',
+ full_name='ClientIdentification.ClientCapabilities.HdcpVersion',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='HDCP_NONE', index=0, number=0,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='HDCP_V1', index=1, number=1,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='HDCP_V2', index=2, number=2,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='HDCP_V2_1', index=3, number=3,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='HDCP_V2_2', index=4, number=4,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=560,
+ serialized_end=644,
+)
+_sym_db.RegisterEnumDescriptor(_CLIENTIDENTIFICATION_CLIENTCAPABILITIES_HDCPVERSION)
+
+_CLIENTIDENTIFICATION_TOKENTYPE = _descriptor.EnumDescriptor(
+ name='TokenType',
+ full_name='ClientIdentification.TokenType',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='KEYBOX', index=0, number=0,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='DEVICE_CERTIFICATE', index=1, number=1,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='REMOTE_ATTESTATION_CERTIFICATE', index=2, number=2,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=646,
+ serialized_end=729,
+)
+_sym_db.RegisterEnumDescriptor(_CLIENTIDENTIFICATION_TOKENTYPE)
+
+_DEVICECERTIFICATE_CERTIFICATETYPE = _descriptor.EnumDescriptor(
+ name='CertificateType',
+ full_name='DeviceCertificate.CertificateType',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='ROOT', index=0, number=0,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='INTERMEDIATE', index=1, number=1,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='USER_DEVICE', index=2, number=2,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='SERVICE', index=3, number=3,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=940,
+ serialized_end=1015,
+)
+_sym_db.RegisterEnumDescriptor(_DEVICECERTIFICATE_CERTIFICATETYPE)
+
+_DEVICECERTIFICATESTATUS_CERTIFICATESTATUS = _descriptor.EnumDescriptor(
+ name='CertificateStatus',
+ full_name='DeviceCertificateStatus.CertificateStatus',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='VALID', index=0, number=0,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='REVOKED', index=1, number=1,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=1171,
+ serialized_end=1214,
+)
+_sym_db.RegisterEnumDescriptor(_DEVICECERTIFICATESTATUS_CERTIFICATESTATUS)
+
+_LICENSE_KEYCONTAINER_OUTPUTPROTECTION_CGMS = _descriptor.EnumDescriptor(
+ name='CGMS',
+ full_name='License.KeyContainer.OutputProtection.CGMS',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='COPY_FREE', index=0, number=0,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='COPY_ONCE', index=1, number=2,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='COPY_NEVER', index=2, number=3,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='CGMS_NONE', index=3, number=42,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=2947,
+ serialized_end=3014,
+)
+_sym_db.RegisterEnumDescriptor(_LICENSE_KEYCONTAINER_OUTPUTPROTECTION_CGMS)
+
+_LICENSE_KEYCONTAINER_KEYTYPE = _descriptor.EnumDescriptor(
+ name='KeyType',
+ full_name='License.KeyContainer.KeyType',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='_NOKEYTYPE', index=0, number=0,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='SIGNING', index=1, number=1,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='CONTENT', index=2, number=2,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='KEY_CONTROL', index=3, number=3,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='OPERATOR_SESSION', index=4, number=4,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=3349,
+ serialized_end=3439,
+)
+_sym_db.RegisterEnumDescriptor(_LICENSE_KEYCONTAINER_KEYTYPE)
+
+_LICENSE_KEYCONTAINER_SECURITYLEVEL = _descriptor.EnumDescriptor(
+ name='SecurityLevel',
+ full_name='License.KeyContainer.SecurityLevel',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='_NOSECLEVEL', index=0, number=0,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='SW_SECURE_CRYPTO', index=1, number=1,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='SW_SECURE_DECODE', index=2, number=2,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='HW_SECURE_CRYPTO', index=3, number=3,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='HW_SECURE_DECODE', index=4, number=4,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='HW_SECURE_ALL', index=5, number=5,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=3442,
+ serialized_end=3581,
+)
+_sym_db.RegisterEnumDescriptor(_LICENSE_KEYCONTAINER_SECURITYLEVEL)
+
+_LICENSEERROR_ERROR = _descriptor.EnumDescriptor(
+ name='Error',
+ full_name='LicenseError.Error',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='DUMMY_NO_ERROR', index=0, number=0,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='INVALID_DEVICE_CERTIFICATE', index=1, number=1,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='REVOKED_DEVICE_CERTIFICATE', index=2, number=2,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='SERVICE_UNAVAILABLE', index=3, number=3,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=3640,
+ serialized_end=3756,
+)
+_sym_db.RegisterEnumDescriptor(_LICENSEERROR_ERROR)
+
+_LICENSEREQUEST_REQUESTTYPE = _descriptor.EnumDescriptor(
+ name='RequestType',
+ full_name='LicenseRequest.RequestType',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='DUMMY_REQ_TYPE', index=0, number=0,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='NEW', index=1, number=1,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='RENEWAL', index=2, number=2,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='RELEASE', index=3, number=3,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=4651,
+ serialized_end=4719,
+)
+_sym_db.RegisterEnumDescriptor(_LICENSEREQUEST_REQUESTTYPE)
+
+_PROVISIONEDDEVICEINFO_WVSECURITYLEVEL = _descriptor.EnumDescriptor(
+ name='WvSecurityLevel',
+ full_name='ProvisionedDeviceInfo.WvSecurityLevel',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='LEVEL_UNSPECIFIED', index=0, number=0,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='LEVEL_1', index=1, number=1,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='LEVEL_2', index=2, number=2,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='LEVEL_3', index=3, number=3,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=4937,
+ serialized_end=5016,
+)
+_sym_db.RegisterEnumDescriptor(_PROVISIONEDDEVICEINFO_WVSECURITYLEVEL)
+
+_SIGNEDMESSAGE_MESSAGETYPE = _descriptor.EnumDescriptor(
+ name='MessageType',
+ full_name='SignedMessage.MessageType',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='DUMMY_MSG_TYPE', index=0, number=0,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='LICENSE_REQUEST', index=1, number=1,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='LICENSE', index=2, number=2,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='ERROR_RESPONSE', index=3, number=3,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='SERVICE_CERTIFICATE_REQUEST', index=4, number=4,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='SERVICE_CERTIFICATE', index=5, number=5,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=5583,
+ serialized_end=5728,
+)
+_sym_db.RegisterEnumDescriptor(_SIGNEDMESSAGE_MESSAGETYPE)
+
+_WIDEVINECENCHEADER_ALGORITHM = _descriptor.EnumDescriptor(
+ name='Algorithm',
+ full_name='WidevineCencHeader.Algorithm',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='UNENCRYPTED', index=0, number=0,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='AESCTR', index=1, number=1,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=6016,
+ serialized_end=6056,
+)
+_sym_db.RegisterEnumDescriptor(_WIDEVINECENCHEADER_ALGORITHM)
+
+_SIGNEDLICENSEREQUEST_MESSAGETYPE = _descriptor.EnumDescriptor(
+ name='MessageType',
+ full_name='SignedLicenseRequest.MessageType',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='DUMMY_MSG_TYPE', index=0, number=0,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='LICENSE_REQUEST', index=1, number=1,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='LICENSE', index=2, number=2,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='ERROR_RESPONSE', index=3, number=3,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='SERVICE_CERTIFICATE_REQUEST', index=4, number=4,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='SERVICE_CERTIFICATE', index=5, number=5,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=5583,
+ serialized_end=5728,
+)
+_sym_db.RegisterEnumDescriptor(_SIGNEDLICENSEREQUEST_MESSAGETYPE)
+
+_SIGNEDLICENSE_MESSAGETYPE = _descriptor.EnumDescriptor(
+ name='MessageType',
+ full_name='SignedLicense.MessageType',
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name='DUMMY_MSG_TYPE', index=0, number=0,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='LICENSE_REQUEST', index=1, number=1,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='LICENSE', index=2, number=2,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='ERROR_RESPONSE', index=3, number=3,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='SERVICE_CERTIFICATE_REQUEST', index=4, number=4,
+ options=None,
+ type=None),
+ _descriptor.EnumValueDescriptor(
+ name='SERVICE_CERTIFICATE', index=5, number=5,
+ options=None,
+ type=None),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=5583,
+ serialized_end=5728,
+)
+_sym_db.RegisterEnumDescriptor(_SIGNEDLICENSE_MESSAGETYPE)
+
+
+_CLIENTIDENTIFICATION_NAMEVALUE = _descriptor.Descriptor(
+ name='NameValue',
+ full_name='ClientIdentification.NameValue',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='Name', full_name='ClientIdentification.NameValue.Name', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Value', full_name='ClientIdentification.NameValue.Value', index=1,
+ number=2, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=309,
+ serialized_end=349,
+)
+
+_CLIENTIDENTIFICATION_CLIENTCAPABILITIES = _descriptor.Descriptor(
+ name='ClientCapabilities',
+ full_name='ClientIdentification.ClientCapabilities',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='ClientToken', full_name='ClientIdentification.ClientCapabilities.ClientToken', index=0,
+ number=1, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='SessionToken', full_name='ClientIdentification.ClientCapabilities.SessionToken', index=1,
+ number=2, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='VideoResolutionConstraints', full_name='ClientIdentification.ClientCapabilities.VideoResolutionConstraints', index=2,
+ number=3, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='MaxHdcpVersion', full_name='ClientIdentification.ClientCapabilities.MaxHdcpVersion', index=3,
+ number=4, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='OemCryptoApiVersion', full_name='ClientIdentification.ClientCapabilities.OemCryptoApiVersion', index=4,
+ number=5, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ _CLIENTIDENTIFICATION_CLIENTCAPABILITIES_HDCPVERSION,
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=352,
+ serialized_end=644,
+)
+
+_CLIENTIDENTIFICATION = _descriptor.Descriptor(
+ name='ClientIdentification',
+ full_name='ClientIdentification',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='Type', full_name='ClientIdentification.Type', index=0,
+ number=1, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Token', full_name='ClientIdentification.Token', index=1,
+ number=2, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='ClientInfo', full_name='ClientIdentification.ClientInfo', index=2,
+ number=3, type=11, cpp_type=10, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='ProviderClientToken', full_name='ClientIdentification.ProviderClientToken', index=3,
+ number=4, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='LicenseCounter', full_name='ClientIdentification.LicenseCounter', index=4,
+ number=5, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='_ClientCapabilities', full_name='ClientIdentification._ClientCapabilities', index=5,
+ number=6, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[_CLIENTIDENTIFICATION_NAMEVALUE, _CLIENTIDENTIFICATION_CLIENTCAPABILITIES, ],
+ enum_types=[
+ _CLIENTIDENTIFICATION_TOKENTYPE,
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=20,
+ serialized_end=729,
+)
+
+
+_DEVICECERTIFICATE = _descriptor.Descriptor(
+ name='DeviceCertificate',
+ full_name='DeviceCertificate',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='Type', full_name='DeviceCertificate.Type', index=0,
+ number=1, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='SerialNumber', full_name='DeviceCertificate.SerialNumber', index=1,
+ number=2, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='CreationTimeSeconds', full_name='DeviceCertificate.CreationTimeSeconds', index=2,
+ number=3, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='PublicKey', full_name='DeviceCertificate.PublicKey', index=3,
+ number=4, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='SystemId', full_name='DeviceCertificate.SystemId', index=4,
+ number=5, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='TestDeviceDeprecated', full_name='DeviceCertificate.TestDeviceDeprecated', index=5,
+ number=6, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='ServiceId', full_name='DeviceCertificate.ServiceId', index=6,
+ number=7, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ _DEVICECERTIFICATE_CERTIFICATETYPE,
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=732,
+ serialized_end=1015,
+)
+
+
+_DEVICECERTIFICATESTATUS = _descriptor.Descriptor(
+ name='DeviceCertificateStatus',
+ full_name='DeviceCertificateStatus',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='SerialNumber', full_name='DeviceCertificateStatus.SerialNumber', index=0,
+ number=1, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Status', full_name='DeviceCertificateStatus.Status', index=1,
+ number=2, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='DeviceInfo', full_name='DeviceCertificateStatus.DeviceInfo', index=2,
+ number=4, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ _DEVICECERTIFICATESTATUS_CERTIFICATESTATUS,
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=1018,
+ serialized_end=1214,
+)
+
+
+_DEVICECERTIFICATESTATUSLIST = _descriptor.Descriptor(
+ name='DeviceCertificateStatusList',
+ full_name='DeviceCertificateStatusList',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='CreationTimeSeconds', full_name='DeviceCertificateStatusList.CreationTimeSeconds', index=0,
+ number=1, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='CertificateStatus', full_name='DeviceCertificateStatusList.CertificateStatus', index=1,
+ number=2, type=11, cpp_type=10, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=1216,
+ serialized_end=1327,
+)
+
+
+_ENCRYPTEDCLIENTIDENTIFICATION = _descriptor.Descriptor(
+ name='EncryptedClientIdentification',
+ full_name='EncryptedClientIdentification',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='ServiceId', full_name='EncryptedClientIdentification.ServiceId', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='ServiceCertificateSerialNumber', full_name='EncryptedClientIdentification.ServiceCertificateSerialNumber', index=1,
+ number=2, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='EncryptedClientId', full_name='EncryptedClientIdentification.EncryptedClientId', index=2,
+ number=3, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='EncryptedClientIdIv', full_name='EncryptedClientIdentification.EncryptedClientIdIv', index=3,
+ number=4, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='EncryptedPrivacyKey', full_name='EncryptedClientIdentification.EncryptedPrivacyKey', index=4,
+ number=5, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=1330,
+ serialized_end=1505,
+)
+
+
+_LICENSEIDENTIFICATION = _descriptor.Descriptor(
+ name='LicenseIdentification',
+ full_name='LicenseIdentification',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='RequestId', full_name='LicenseIdentification.RequestId', index=0,
+ number=1, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='SessionId', full_name='LicenseIdentification.SessionId', index=1,
+ number=2, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='PurchaseId', full_name='LicenseIdentification.PurchaseId', index=2,
+ number=3, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Type', full_name='LicenseIdentification.Type', index=3,
+ number=4, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Version', full_name='LicenseIdentification.Version', index=4,
+ number=5, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='ProviderSessionToken', full_name='LicenseIdentification.ProviderSessionToken', index=5,
+ number=6, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=1508,
+ serialized_end=1664,
+)
+
+
+_LICENSE_POLICY = _descriptor.Descriptor(
+ name='Policy',
+ full_name='License.Policy',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='CanPlay', full_name='License.Policy.CanPlay', index=0,
+ number=1, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='CanPersist', full_name='License.Policy.CanPersist', index=1,
+ number=2, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='CanRenew', full_name='License.Policy.CanRenew', index=2,
+ number=3, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RentalDurationSeconds', full_name='License.Policy.RentalDurationSeconds', index=3,
+ number=4, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='PlaybackDurationSeconds', full_name='License.Policy.PlaybackDurationSeconds', index=4,
+ number=5, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='LicenseDurationSeconds', full_name='License.Policy.LicenseDurationSeconds', index=5,
+ number=6, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RenewalRecoveryDurationSeconds', full_name='License.Policy.RenewalRecoveryDurationSeconds', index=6,
+ number=7, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RenewalServerUrl', full_name='License.Policy.RenewalServerUrl', index=7,
+ number=8, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RenewalDelaySeconds', full_name='License.Policy.RenewalDelaySeconds', index=8,
+ number=9, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RenewalRetryIntervalSeconds', full_name='License.Policy.RenewalRetryIntervalSeconds', index=9,
+ number=10, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RenewWithUsage', full_name='License.Policy.RenewWithUsage', index=10,
+ number=11, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='UnknownPolicy12', full_name='License.Policy.UnknownPolicy12', index=11,
+ number=12, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=1931,
+ serialized_end=2271,
+)
+
+_LICENSE_KEYCONTAINER_OUTPUTPROTECTION = _descriptor.Descriptor(
+ name='OutputProtection',
+ full_name='License.KeyContainer.OutputProtection',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='Hdcp', full_name='License.KeyContainer.OutputProtection.Hdcp', index=0,
+ number=1, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='CgmsFlags', full_name='License.KeyContainer.OutputProtection.CgmsFlags', index=1,
+ number=2, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ _LICENSE_KEYCONTAINER_OUTPUTPROTECTION_CGMS,
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=2795,
+ serialized_end=3014,
+)
+
+_LICENSE_KEYCONTAINER_KEYCONTROL = _descriptor.Descriptor(
+ name='KeyControl',
+ full_name='License.KeyContainer.KeyControl',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='KeyControlBlock', full_name='License.KeyContainer.KeyControl.KeyControlBlock', index=0,
+ number=1, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Iv', full_name='License.KeyContainer.KeyControl.Iv', index=1,
+ number=2, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=3016,
+ serialized_end=3065,
+)
+
+_LICENSE_KEYCONTAINER_OPERATORSESSIONKEYPERMISSIONS = _descriptor.Descriptor(
+ name='OperatorSessionKeyPermissions',
+ full_name='License.KeyContainer.OperatorSessionKeyPermissions',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='AllowEncrypt', full_name='License.KeyContainer.OperatorSessionKeyPermissions.AllowEncrypt', index=0,
+ number=1, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='AllowDecrypt', full_name='License.KeyContainer.OperatorSessionKeyPermissions.AllowDecrypt', index=1,
+ number=2, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='AllowSign', full_name='License.KeyContainer.OperatorSessionKeyPermissions.AllowSign', index=2,
+ number=3, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='AllowSignatureVerify', full_name='License.KeyContainer.OperatorSessionKeyPermissions.AllowSignatureVerify', index=3,
+ number=4, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=3067,
+ serialized_end=3191,
+)
+
+_LICENSE_KEYCONTAINER_VIDEORESOLUTIONCONSTRAINT = _descriptor.Descriptor(
+ name='VideoResolutionConstraint',
+ full_name='License.KeyContainer.VideoResolutionConstraint',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='MinResolutionPixels', full_name='License.KeyContainer.VideoResolutionConstraint.MinResolutionPixels', index=0,
+ number=1, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='MaxResolutionPixels', full_name='License.KeyContainer.VideoResolutionConstraint.MaxResolutionPixels', index=1,
+ number=2, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RequiredProtection', full_name='License.KeyContainer.VideoResolutionConstraint.RequiredProtection', index=2,
+ number=3, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=3194,
+ serialized_end=3347,
+)
+
+_LICENSE_KEYCONTAINER = _descriptor.Descriptor(
+ name='KeyContainer',
+ full_name='License.KeyContainer',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='Id', full_name='License.KeyContainer.Id', index=0,
+ number=1, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Iv', full_name='License.KeyContainer.Iv', index=1,
+ number=2, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Key', full_name='License.KeyContainer.Key', index=2,
+ number=3, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Type', full_name='License.KeyContainer.Type', index=3,
+ number=4, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Level', full_name='License.KeyContainer.Level', index=4,
+ number=5, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RequiredProtection', full_name='License.KeyContainer.RequiredProtection', index=5,
+ number=6, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RequestedProtection', full_name='License.KeyContainer.RequestedProtection', index=6,
+ number=7, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='_KeyControl', full_name='License.KeyContainer._KeyControl', index=7,
+ number=8, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='_OperatorSessionKeyPermissions', full_name='License.KeyContainer._OperatorSessionKeyPermissions', index=8,
+ number=9, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='VideoResolutionConstraints', full_name='License.KeyContainer.VideoResolutionConstraints', index=9,
+ number=10, type=11, cpp_type=10, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[_LICENSE_KEYCONTAINER_OUTPUTPROTECTION, _LICENSE_KEYCONTAINER_KEYCONTROL, _LICENSE_KEYCONTAINER_OPERATORSESSIONKEYPERMISSIONS, _LICENSE_KEYCONTAINER_VIDEORESOLUTIONCONSTRAINT, ],
+ enum_types=[
+ _LICENSE_KEYCONTAINER_KEYTYPE,
+ _LICENSE_KEYCONTAINER_SECURITYLEVEL,
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=2274,
+ serialized_end=3581,
+)
+
+_LICENSE = _descriptor.Descriptor(
+ name='License',
+ full_name='License',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='Id', full_name='License.Id', index=0,
+ number=1, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='_Policy', full_name='License._Policy', index=1,
+ number=2, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Key', full_name='License.Key', index=2,
+ number=3, type=11, cpp_type=10, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='LicenseStartTime', full_name='License.LicenseStartTime', index=3,
+ number=4, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RemoteAttestationVerified', full_name='License.RemoteAttestationVerified', index=4,
+ number=5, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='ProviderClientToken', full_name='License.ProviderClientToken', index=5,
+ number=6, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='ProtectionScheme', full_name='License.ProtectionScheme', index=6,
+ number=7, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='UnknownHdcpDataField', full_name='License.UnknownHdcpDataField', index=7,
+ number=8, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[_LICENSE_POLICY, _LICENSE_KEYCONTAINER, ],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=1667,
+ serialized_end=3581,
+)
+
+
+_LICENSEERROR = _descriptor.Descriptor(
+ name='LicenseError',
+ full_name='LicenseError',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='ErrorCode', full_name='LicenseError.ErrorCode', index=0,
+ number=1, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ _LICENSEERROR_ERROR,
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=3584,
+ serialized_end=3756,
+)
+
+
+_LICENSEREQUEST_CONTENTIDENTIFICATION_CENC = _descriptor.Descriptor(
+ name='CENC',
+ full_name='LicenseRequest.ContentIdentification.CENC',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='Pssh', full_name='LicenseRequest.ContentIdentification.CENC.Pssh', index=0,
+ number=1, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='LicenseType', full_name='LicenseRequest.ContentIdentification.CENC.LicenseType', index=1,
+ number=2, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RequestId', full_name='LicenseRequest.ContentIdentification.CENC.RequestId', index=2,
+ number=3, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=4320,
+ serialized_end=4415,
+)
+
+_LICENSEREQUEST_CONTENTIDENTIFICATION_WEBM = _descriptor.Descriptor(
+ name='WebM',
+ full_name='LicenseRequest.ContentIdentification.WebM',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='Header', full_name='LicenseRequest.ContentIdentification.WebM.Header', index=0,
+ number=1, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='LicenseType', full_name='LicenseRequest.ContentIdentification.WebM.LicenseType', index=1,
+ number=2, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RequestId', full_name='LicenseRequest.ContentIdentification.WebM.RequestId', index=2,
+ number=3, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=4417,
+ serialized_end=4493,
+)
+
+_LICENSEREQUEST_CONTENTIDENTIFICATION_EXISTINGLICENSE = _descriptor.Descriptor(
+ name='ExistingLicense',
+ full_name='LicenseRequest.ContentIdentification.ExistingLicense',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='LicenseId', full_name='LicenseRequest.ContentIdentification.ExistingLicense.LicenseId', index=0,
+ number=1, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='SecondsSinceStarted', full_name='LicenseRequest.ContentIdentification.ExistingLicense.SecondsSinceStarted', index=1,
+ number=2, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='SecondsSinceLastPlayed', full_name='LicenseRequest.ContentIdentification.ExistingLicense.SecondsSinceLastPlayed', index=2,
+ number=3, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='SessionUsageTableEntry', full_name='LicenseRequest.ContentIdentification.ExistingLicense.SessionUsageTableEntry', index=3,
+ number=4, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=4496,
+ serialized_end=4649,
+)
+
+_LICENSEREQUEST_CONTENTIDENTIFICATION = _descriptor.Descriptor(
+ name='ContentIdentification',
+ full_name='LicenseRequest.ContentIdentification',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='CencId', full_name='LicenseRequest.ContentIdentification.CencId', index=0,
+ number=1, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='WebmId', full_name='LicenseRequest.ContentIdentification.WebmId', index=1,
+ number=2, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='License', full_name='LicenseRequest.ContentIdentification.License', index=2,
+ number=3, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[_LICENSEREQUEST_CONTENTIDENTIFICATION_CENC, _LICENSEREQUEST_CONTENTIDENTIFICATION_WEBM, _LICENSEREQUEST_CONTENTIDENTIFICATION_EXISTINGLICENSE, ],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=4103,
+ serialized_end=4649,
+)
+
+_LICENSEREQUEST = _descriptor.Descriptor(
+ name='LicenseRequest',
+ full_name='LicenseRequest',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='ClientId', full_name='LicenseRequest.ClientId', index=0,
+ number=1, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='ContentId', full_name='LicenseRequest.ContentId', index=1,
+ number=2, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Type', full_name='LicenseRequest.Type', index=2,
+ number=3, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RequestTime', full_name='LicenseRequest.RequestTime', index=3,
+ number=4, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='KeyControlNonceDeprecated', full_name='LicenseRequest.KeyControlNonceDeprecated', index=4,
+ number=5, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='ProtocolVersion', full_name='LicenseRequest.ProtocolVersion', index=5,
+ number=6, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='KeyControlNonce', full_name='LicenseRequest.KeyControlNonce', index=6,
+ number=7, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='EncryptedClientId', full_name='LicenseRequest.EncryptedClientId', index=7,
+ number=8, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[_LICENSEREQUEST_CONTENTIDENTIFICATION, ],
+ enum_types=[
+ _LICENSEREQUEST_REQUESTTYPE,
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=3759,
+ serialized_end=4719,
+)
+
+
+_PROVISIONEDDEVICEINFO = _descriptor.Descriptor(
+ name='ProvisionedDeviceInfo',
+ full_name='ProvisionedDeviceInfo',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='SystemId', full_name='ProvisionedDeviceInfo.SystemId', index=0,
+ number=1, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Soc', full_name='ProvisionedDeviceInfo.Soc', index=1,
+ number=2, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Manufacturer', full_name='ProvisionedDeviceInfo.Manufacturer', index=2,
+ number=3, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Model', full_name='ProvisionedDeviceInfo.Model', index=3,
+ number=4, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='DeviceType', full_name='ProvisionedDeviceInfo.DeviceType', index=4,
+ number=5, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='ModelYear', full_name='ProvisionedDeviceInfo.ModelYear', index=5,
+ number=6, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='SecurityLevel', full_name='ProvisionedDeviceInfo.SecurityLevel', index=6,
+ number=7, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='TestDevice', full_name='ProvisionedDeviceInfo.TestDevice', index=7,
+ number=8, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ _PROVISIONEDDEVICEINFO_WVSECURITYLEVEL,
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=4722,
+ serialized_end=5016,
+)
+
+
+_PROVISIONINGOPTIONS = _descriptor.Descriptor(
+ name='ProvisioningOptions',
+ full_name='ProvisioningOptions',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=5018,
+ serialized_end=5039,
+)
+
+
+_PROVISIONINGREQUEST = _descriptor.Descriptor(
+ name='ProvisioningRequest',
+ full_name='ProvisioningRequest',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=5041,
+ serialized_end=5062,
+)
+
+
+_PROVISIONINGRESPONSE = _descriptor.Descriptor(
+ name='ProvisioningResponse',
+ full_name='ProvisioningResponse',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=5064,
+ serialized_end=5086,
+)
+
+
+_REMOTEATTESTATION = _descriptor.Descriptor(
+ name='RemoteAttestation',
+ full_name='RemoteAttestation',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='Certificate', full_name='RemoteAttestation.Certificate', index=0,
+ number=1, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Salt', full_name='RemoteAttestation.Salt', index=1,
+ number=2, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Signature', full_name='RemoteAttestation.Signature', index=2,
+ number=3, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=5088,
+ serialized_end=5193,
+)
+
+
+_SESSIONINIT = _descriptor.Descriptor(
+ name='SessionInit',
+ full_name='SessionInit',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=5195,
+ serialized_end=5208,
+)
+
+
+_SESSIONSTATE = _descriptor.Descriptor(
+ name='SessionState',
+ full_name='SessionState',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=5210,
+ serialized_end=5224,
+)
+
+
+_SIGNEDCERTIFICATESTATUSLIST = _descriptor.Descriptor(
+ name='SignedCertificateStatusList',
+ full_name='SignedCertificateStatusList',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=5226,
+ serialized_end=5255,
+)
+
+
+_SIGNEDDEVICECERTIFICATE = _descriptor.Descriptor(
+ name='SignedDeviceCertificate',
+ full_name='SignedDeviceCertificate',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='_DeviceCertificate', full_name='SignedDeviceCertificate._DeviceCertificate', index=0,
+ number=1, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Signature', full_name='SignedDeviceCertificate.Signature', index=1,
+ number=2, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Signer', full_name='SignedDeviceCertificate.Signer', index=2,
+ number=3, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=5258,
+ serialized_end=5392,
+)
+
+
+_SIGNEDPROVISIONINGMESSAGE = _descriptor.Descriptor(
+ name='SignedProvisioningMessage',
+ full_name='SignedProvisioningMessage',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=5394,
+ serialized_end=5421,
+)
+
+
+_SIGNEDMESSAGE = _descriptor.Descriptor(
+ name='SignedMessage',
+ full_name='SignedMessage',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='Type', full_name='SignedMessage.Type', index=0,
+ number=1, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Msg', full_name='SignedMessage.Msg', index=1,
+ number=2, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Signature', full_name='SignedMessage.Signature', index=2,
+ number=3, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='SessionKey', full_name='SignedMessage.SessionKey', index=3,
+ number=4, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RemoteAttestation', full_name='SignedMessage.RemoteAttestation', index=4,
+ number=5, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ _SIGNEDMESSAGE_MESSAGETYPE,
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=5424,
+ serialized_end=5728,
+)
+
+
+_WIDEVINECENCHEADER = _descriptor.Descriptor(
+ name='WidevineCencHeader',
+ full_name='WidevineCencHeader',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='algorithm', full_name='WidevineCencHeader.algorithm', index=0,
+ number=1, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='key_id', full_name='WidevineCencHeader.key_id', index=1,
+ number=2, type=12, cpp_type=9, label=3,
+ has_default_value=False, default_value=[],
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='provider', full_name='WidevineCencHeader.provider', index=2,
+ number=3, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='content_id', full_name='WidevineCencHeader.content_id', index=3,
+ number=4, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='track_type_deprecated', full_name='WidevineCencHeader.track_type_deprecated', index=4,
+ number=5, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='policy', full_name='WidevineCencHeader.policy', index=5,
+ number=6, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='crypto_period_index', full_name='WidevineCencHeader.crypto_period_index', index=6,
+ number=7, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='grouped_license', full_name='WidevineCencHeader.grouped_license', index=7,
+ number=8, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='protection_scheme', full_name='WidevineCencHeader.protection_scheme', index=8,
+ number=9, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='crypto_period_seconds', full_name='WidevineCencHeader.crypto_period_seconds', index=9,
+ number=10, type=13, cpp_type=3, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ _WIDEVINECENCHEADER_ALGORITHM,
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=5731,
+ serialized_end=6056,
+)
+
+
+_SIGNEDLICENSEREQUEST = _descriptor.Descriptor(
+ name='SignedLicenseRequest',
+ full_name='SignedLicenseRequest',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='Type', full_name='SignedLicenseRequest.Type', index=0,
+ number=1, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Msg', full_name='SignedLicenseRequest.Msg', index=1,
+ number=2, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Signature', full_name='SignedLicenseRequest.Signature', index=2,
+ number=3, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='SessionKey', full_name='SignedLicenseRequest.SessionKey', index=3,
+ number=4, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RemoteAttestation', full_name='SignedLicenseRequest.RemoteAttestation', index=4,
+ number=5, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ _SIGNEDLICENSEREQUEST_MESSAGETYPE,
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=6059,
+ serialized_end=6394,
+)
+
+
+_SIGNEDLICENSE = _descriptor.Descriptor(
+ name='SignedLicense',
+ full_name='SignedLicense',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='Type', full_name='SignedLicense.Type', index=0,
+ number=1, type=14, cpp_type=8, label=1,
+ has_default_value=False, default_value=0,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Msg', full_name='SignedLicense.Msg', index=1,
+ number=2, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='Signature', full_name='SignedLicense.Signature', index=2,
+ number=3, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='SessionKey', full_name='SignedLicense.SessionKey', index=3,
+ number=4, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ _descriptor.FieldDescriptor(
+ name='RemoteAttestation', full_name='SignedLicense.RemoteAttestation', index=4,
+ number=5, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ options=None),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ _SIGNEDLICENSE_MESSAGETYPE,
+ ],
+ options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=6397,
+ serialized_end=6711,
+)
+
+_CLIENTIDENTIFICATION_NAMEVALUE.containing_type = _CLIENTIDENTIFICATION
+_CLIENTIDENTIFICATION_CLIENTCAPABILITIES.fields_by_name['MaxHdcpVersion'].enum_type = _CLIENTIDENTIFICATION_CLIENTCAPABILITIES_HDCPVERSION
+_CLIENTIDENTIFICATION_CLIENTCAPABILITIES.containing_type = _CLIENTIDENTIFICATION
+_CLIENTIDENTIFICATION_CLIENTCAPABILITIES_HDCPVERSION.containing_type = _CLIENTIDENTIFICATION_CLIENTCAPABILITIES
+_CLIENTIDENTIFICATION.fields_by_name['Type'].enum_type = _CLIENTIDENTIFICATION_TOKENTYPE
+_CLIENTIDENTIFICATION.fields_by_name['Token'].message_type = _SIGNEDDEVICECERTIFICATE
+_CLIENTIDENTIFICATION.fields_by_name['ClientInfo'].message_type = _CLIENTIDENTIFICATION_NAMEVALUE
+_CLIENTIDENTIFICATION.fields_by_name['_ClientCapabilities'].message_type = _CLIENTIDENTIFICATION_CLIENTCAPABILITIES
+_CLIENTIDENTIFICATION_TOKENTYPE.containing_type = _CLIENTIDENTIFICATION
+_DEVICECERTIFICATE.fields_by_name['Type'].enum_type = _DEVICECERTIFICATE_CERTIFICATETYPE
+_DEVICECERTIFICATE_CERTIFICATETYPE.containing_type = _DEVICECERTIFICATE
+_DEVICECERTIFICATESTATUS.fields_by_name['Status'].enum_type = _DEVICECERTIFICATESTATUS_CERTIFICATESTATUS
+_DEVICECERTIFICATESTATUS.fields_by_name['DeviceInfo'].message_type = _PROVISIONEDDEVICEINFO
+_DEVICECERTIFICATESTATUS_CERTIFICATESTATUS.containing_type = _DEVICECERTIFICATESTATUS
+_DEVICECERTIFICATESTATUSLIST.fields_by_name['CertificateStatus'].message_type = _DEVICECERTIFICATESTATUS
+_LICENSEIDENTIFICATION.fields_by_name['Type'].enum_type = _LICENSETYPE
+_LICENSE_POLICY.containing_type = _LICENSE
+_LICENSE_KEYCONTAINER_OUTPUTPROTECTION.fields_by_name['Hdcp'].enum_type = _CLIENTIDENTIFICATION_CLIENTCAPABILITIES_HDCPVERSION
+_LICENSE_KEYCONTAINER_OUTPUTPROTECTION.fields_by_name['CgmsFlags'].enum_type = _LICENSE_KEYCONTAINER_OUTPUTPROTECTION_CGMS
+_LICENSE_KEYCONTAINER_OUTPUTPROTECTION.containing_type = _LICENSE_KEYCONTAINER
+_LICENSE_KEYCONTAINER_OUTPUTPROTECTION_CGMS.containing_type = _LICENSE_KEYCONTAINER_OUTPUTPROTECTION
+_LICENSE_KEYCONTAINER_KEYCONTROL.containing_type = _LICENSE_KEYCONTAINER
+_LICENSE_KEYCONTAINER_OPERATORSESSIONKEYPERMISSIONS.containing_type = _LICENSE_KEYCONTAINER
+_LICENSE_KEYCONTAINER_VIDEORESOLUTIONCONSTRAINT.fields_by_name['RequiredProtection'].message_type = _LICENSE_KEYCONTAINER_OUTPUTPROTECTION
+_LICENSE_KEYCONTAINER_VIDEORESOLUTIONCONSTRAINT.containing_type = _LICENSE_KEYCONTAINER
+_LICENSE_KEYCONTAINER.fields_by_name['Type'].enum_type = _LICENSE_KEYCONTAINER_KEYTYPE
+_LICENSE_KEYCONTAINER.fields_by_name['Level'].enum_type = _LICENSE_KEYCONTAINER_SECURITYLEVEL
+_LICENSE_KEYCONTAINER.fields_by_name['RequiredProtection'].message_type = _LICENSE_KEYCONTAINER_OUTPUTPROTECTION
+_LICENSE_KEYCONTAINER.fields_by_name['RequestedProtection'].message_type = _LICENSE_KEYCONTAINER_OUTPUTPROTECTION
+_LICENSE_KEYCONTAINER.fields_by_name['_KeyControl'].message_type = _LICENSE_KEYCONTAINER_KEYCONTROL
+_LICENSE_KEYCONTAINER.fields_by_name['_OperatorSessionKeyPermissions'].message_type = _LICENSE_KEYCONTAINER_OPERATORSESSIONKEYPERMISSIONS
+_LICENSE_KEYCONTAINER.fields_by_name['VideoResolutionConstraints'].message_type = _LICENSE_KEYCONTAINER_VIDEORESOLUTIONCONSTRAINT
+_LICENSE_KEYCONTAINER.containing_type = _LICENSE
+_LICENSE_KEYCONTAINER_KEYTYPE.containing_type = _LICENSE_KEYCONTAINER
+_LICENSE_KEYCONTAINER_SECURITYLEVEL.containing_type = _LICENSE_KEYCONTAINER
+_LICENSE.fields_by_name['Id'].message_type = _LICENSEIDENTIFICATION
+_LICENSE.fields_by_name['_Policy'].message_type = _LICENSE_POLICY
+_LICENSE.fields_by_name['Key'].message_type = _LICENSE_KEYCONTAINER
+_LICENSEERROR.fields_by_name['ErrorCode'].enum_type = _LICENSEERROR_ERROR
+_LICENSEERROR_ERROR.containing_type = _LICENSEERROR
+_LICENSEREQUEST_CONTENTIDENTIFICATION_CENC.fields_by_name['Pssh'].message_type = _WIDEVINECENCHEADER
+_LICENSEREQUEST_CONTENTIDENTIFICATION_CENC.fields_by_name['LicenseType'].enum_type = _LICENSETYPE
+_LICENSEREQUEST_CONTENTIDENTIFICATION_CENC.containing_type = _LICENSEREQUEST_CONTENTIDENTIFICATION
+_LICENSEREQUEST_CONTENTIDENTIFICATION_WEBM.fields_by_name['LicenseType'].enum_type = _LICENSETYPE
+_LICENSEREQUEST_CONTENTIDENTIFICATION_WEBM.containing_type = _LICENSEREQUEST_CONTENTIDENTIFICATION
+_LICENSEREQUEST_CONTENTIDENTIFICATION_EXISTINGLICENSE.fields_by_name['LicenseId'].message_type = _LICENSEIDENTIFICATION
+_LICENSEREQUEST_CONTENTIDENTIFICATION_EXISTINGLICENSE.containing_type = _LICENSEREQUEST_CONTENTIDENTIFICATION
+_LICENSEREQUEST_CONTENTIDENTIFICATION.fields_by_name['CencId'].message_type = _LICENSEREQUEST_CONTENTIDENTIFICATION_CENC
+_LICENSEREQUEST_CONTENTIDENTIFICATION.fields_by_name['WebmId'].message_type = _LICENSEREQUEST_CONTENTIDENTIFICATION_WEBM
+_LICENSEREQUEST_CONTENTIDENTIFICATION.fields_by_name['License'].message_type = _LICENSEREQUEST_CONTENTIDENTIFICATION_EXISTINGLICENSE
+_LICENSEREQUEST_CONTENTIDENTIFICATION.containing_type = _LICENSEREQUEST
+_LICENSEREQUEST.fields_by_name['ClientId'].message_type = _CLIENTIDENTIFICATION
+_LICENSEREQUEST.fields_by_name['ContentId'].message_type = _LICENSEREQUEST_CONTENTIDENTIFICATION
+_LICENSEREQUEST.fields_by_name['Type'].enum_type = _LICENSEREQUEST_REQUESTTYPE
+_LICENSEREQUEST.fields_by_name['ProtocolVersion'].enum_type = _PROTOCOLVERSION
+_LICENSEREQUEST.fields_by_name['EncryptedClientId'].message_type = _ENCRYPTEDCLIENTIDENTIFICATION
+_LICENSEREQUEST_REQUESTTYPE.containing_type = _LICENSEREQUEST
+_PROVISIONEDDEVICEINFO.fields_by_name['SecurityLevel'].enum_type = _PROVISIONEDDEVICEINFO_WVSECURITYLEVEL
+_PROVISIONEDDEVICEINFO_WVSECURITYLEVEL.containing_type = _PROVISIONEDDEVICEINFO
+_REMOTEATTESTATION.fields_by_name['Certificate'].message_type = _ENCRYPTEDCLIENTIDENTIFICATION
+_SIGNEDDEVICECERTIFICATE.fields_by_name['_DeviceCertificate'].message_type = _DEVICECERTIFICATE
+_SIGNEDDEVICECERTIFICATE.fields_by_name['Signer'].message_type = _SIGNEDDEVICECERTIFICATE
+_SIGNEDMESSAGE.fields_by_name['Type'].enum_type = _SIGNEDMESSAGE_MESSAGETYPE
+_SIGNEDMESSAGE.fields_by_name['RemoteAttestation'].message_type = _REMOTEATTESTATION
+_SIGNEDMESSAGE_MESSAGETYPE.containing_type = _SIGNEDMESSAGE
+_WIDEVINECENCHEADER.fields_by_name['algorithm'].enum_type = _WIDEVINECENCHEADER_ALGORITHM
+_WIDEVINECENCHEADER_ALGORITHM.containing_type = _WIDEVINECENCHEADER
+_SIGNEDLICENSEREQUEST.fields_by_name['Type'].enum_type = _SIGNEDLICENSEREQUEST_MESSAGETYPE
+_SIGNEDLICENSEREQUEST.fields_by_name['Msg'].message_type = _LICENSEREQUEST
+_SIGNEDLICENSEREQUEST.fields_by_name['RemoteAttestation'].message_type = _REMOTEATTESTATION
+_SIGNEDLICENSEREQUEST_MESSAGETYPE.containing_type = _SIGNEDLICENSEREQUEST
+_SIGNEDLICENSE.fields_by_name['Type'].enum_type = _SIGNEDLICENSE_MESSAGETYPE
+_SIGNEDLICENSE.fields_by_name['Msg'].message_type = _LICENSE
+_SIGNEDLICENSE.fields_by_name['RemoteAttestation'].message_type = _REMOTEATTESTATION
+_SIGNEDLICENSE_MESSAGETYPE.containing_type = _SIGNEDLICENSE
+DESCRIPTOR.message_types_by_name['ClientIdentification'] = _CLIENTIDENTIFICATION
+DESCRIPTOR.message_types_by_name['DeviceCertificate'] = _DEVICECERTIFICATE
+DESCRIPTOR.message_types_by_name['DeviceCertificateStatus'] = _DEVICECERTIFICATESTATUS
+DESCRIPTOR.message_types_by_name['DeviceCertificateStatusList'] = _DEVICECERTIFICATESTATUSLIST
+DESCRIPTOR.message_types_by_name['EncryptedClientIdentification'] = _ENCRYPTEDCLIENTIDENTIFICATION
+DESCRIPTOR.message_types_by_name['LicenseIdentification'] = _LICENSEIDENTIFICATION
+DESCRIPTOR.message_types_by_name['License'] = _LICENSE
+DESCRIPTOR.message_types_by_name['LicenseError'] = _LICENSEERROR
+DESCRIPTOR.message_types_by_name['LicenseRequest'] = _LICENSEREQUEST
+DESCRIPTOR.message_types_by_name['ProvisionedDeviceInfo'] = _PROVISIONEDDEVICEINFO
+DESCRIPTOR.message_types_by_name['ProvisioningOptions'] = _PROVISIONINGOPTIONS
+DESCRIPTOR.message_types_by_name['ProvisioningRequest'] = _PROVISIONINGREQUEST
+DESCRIPTOR.message_types_by_name['ProvisioningResponse'] = _PROVISIONINGRESPONSE
+DESCRIPTOR.message_types_by_name['RemoteAttestation'] = _REMOTEATTESTATION
+DESCRIPTOR.message_types_by_name['SessionInit'] = _SESSIONINIT
+DESCRIPTOR.message_types_by_name['SessionState'] = _SESSIONSTATE
+DESCRIPTOR.message_types_by_name['SignedCertificateStatusList'] = _SIGNEDCERTIFICATESTATUSLIST
+DESCRIPTOR.message_types_by_name['SignedDeviceCertificate'] = _SIGNEDDEVICECERTIFICATE
+DESCRIPTOR.message_types_by_name['SignedProvisioningMessage'] = _SIGNEDPROVISIONINGMESSAGE
+DESCRIPTOR.message_types_by_name['SignedMessage'] = _SIGNEDMESSAGE
+DESCRIPTOR.message_types_by_name['WidevineCencHeader'] = _WIDEVINECENCHEADER
+DESCRIPTOR.message_types_by_name['SignedLicenseRequest'] = _SIGNEDLICENSEREQUEST
+DESCRIPTOR.message_types_by_name['SignedLicense'] = _SIGNEDLICENSE
+DESCRIPTOR.enum_types_by_name['LicenseType'] = _LICENSETYPE
+DESCRIPTOR.enum_types_by_name['ProtocolVersion'] = _PROTOCOLVERSION
+_sym_db.RegisterFileDescriptor(DESCRIPTOR)
+
+ClientIdentification = _reflection.GeneratedProtocolMessageType('ClientIdentification', (_message.Message,), dict(
+
+ NameValue = _reflection.GeneratedProtocolMessageType('NameValue', (_message.Message,), dict(
+ DESCRIPTOR = _CLIENTIDENTIFICATION_NAMEVALUE,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:ClientIdentification.NameValue)
+ ))
+ ,
+
+ ClientCapabilities = _reflection.GeneratedProtocolMessageType('ClientCapabilities', (_message.Message,), dict(
+ DESCRIPTOR = _CLIENTIDENTIFICATION_CLIENTCAPABILITIES,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:ClientIdentification.ClientCapabilities)
+ ))
+ ,
+ DESCRIPTOR = _CLIENTIDENTIFICATION,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:ClientIdentification)
+ ))
+_sym_db.RegisterMessage(ClientIdentification)
+_sym_db.RegisterMessage(ClientIdentification.NameValue)
+_sym_db.RegisterMessage(ClientIdentification.ClientCapabilities)
+
+DeviceCertificate = _reflection.GeneratedProtocolMessageType('DeviceCertificate', (_message.Message,), dict(
+ DESCRIPTOR = _DEVICECERTIFICATE,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:DeviceCertificate)
+ ))
+_sym_db.RegisterMessage(DeviceCertificate)
+
+DeviceCertificateStatus = _reflection.GeneratedProtocolMessageType('DeviceCertificateStatus', (_message.Message,), dict(
+ DESCRIPTOR = _DEVICECERTIFICATESTATUS,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:DeviceCertificateStatus)
+ ))
+_sym_db.RegisterMessage(DeviceCertificateStatus)
+
+DeviceCertificateStatusList = _reflection.GeneratedProtocolMessageType('DeviceCertificateStatusList', (_message.Message,), dict(
+ DESCRIPTOR = _DEVICECERTIFICATESTATUSLIST,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:DeviceCertificateStatusList)
+ ))
+_sym_db.RegisterMessage(DeviceCertificateStatusList)
+
+EncryptedClientIdentification = _reflection.GeneratedProtocolMessageType('EncryptedClientIdentification', (_message.Message,), dict(
+ DESCRIPTOR = _ENCRYPTEDCLIENTIDENTIFICATION,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:EncryptedClientIdentification)
+ ))
+_sym_db.RegisterMessage(EncryptedClientIdentification)
+
+LicenseIdentification = _reflection.GeneratedProtocolMessageType('LicenseIdentification', (_message.Message,), dict(
+ DESCRIPTOR = _LICENSEIDENTIFICATION,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:LicenseIdentification)
+ ))
+_sym_db.RegisterMessage(LicenseIdentification)
+
+License = _reflection.GeneratedProtocolMessageType('License', (_message.Message,), dict(
+
+ Policy = _reflection.GeneratedProtocolMessageType('Policy', (_message.Message,), dict(
+ DESCRIPTOR = _LICENSE_POLICY,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:License.Policy)
+ ))
+ ,
+
+ KeyContainer = _reflection.GeneratedProtocolMessageType('KeyContainer', (_message.Message,), dict(
+
+ OutputProtection = _reflection.GeneratedProtocolMessageType('OutputProtection', (_message.Message,), dict(
+ DESCRIPTOR = _LICENSE_KEYCONTAINER_OUTPUTPROTECTION,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:License.KeyContainer.OutputProtection)
+ ))
+ ,
+
+ KeyControl = _reflection.GeneratedProtocolMessageType('KeyControl', (_message.Message,), dict(
+ DESCRIPTOR = _LICENSE_KEYCONTAINER_KEYCONTROL,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:License.KeyContainer.KeyControl)
+ ))
+ ,
+
+ OperatorSessionKeyPermissions = _reflection.GeneratedProtocolMessageType('OperatorSessionKeyPermissions', (_message.Message,), dict(
+ DESCRIPTOR = _LICENSE_KEYCONTAINER_OPERATORSESSIONKEYPERMISSIONS,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:License.KeyContainer.OperatorSessionKeyPermissions)
+ ))
+ ,
+
+ VideoResolutionConstraint = _reflection.GeneratedProtocolMessageType('VideoResolutionConstraint', (_message.Message,), dict(
+ DESCRIPTOR = _LICENSE_KEYCONTAINER_VIDEORESOLUTIONCONSTRAINT,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:License.KeyContainer.VideoResolutionConstraint)
+ ))
+ ,
+ DESCRIPTOR = _LICENSE_KEYCONTAINER,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:License.KeyContainer)
+ ))
+ ,
+ DESCRIPTOR = _LICENSE,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:License)
+ ))
+_sym_db.RegisterMessage(License)
+_sym_db.RegisterMessage(License.Policy)
+_sym_db.RegisterMessage(License.KeyContainer)
+_sym_db.RegisterMessage(License.KeyContainer.OutputProtection)
+_sym_db.RegisterMessage(License.KeyContainer.KeyControl)
+_sym_db.RegisterMessage(License.KeyContainer.OperatorSessionKeyPermissions)
+_sym_db.RegisterMessage(License.KeyContainer.VideoResolutionConstraint)
+
+LicenseError = _reflection.GeneratedProtocolMessageType('LicenseError', (_message.Message,), dict(
+ DESCRIPTOR = _LICENSEERROR,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:LicenseError)
+ ))
+_sym_db.RegisterMessage(LicenseError)
+
+LicenseRequest = _reflection.GeneratedProtocolMessageType('LicenseRequest', (_message.Message,), dict(
+
+ ContentIdentification = _reflection.GeneratedProtocolMessageType('ContentIdentification', (_message.Message,), dict(
+
+ CENC = _reflection.GeneratedProtocolMessageType('CENC', (_message.Message,), dict(
+ DESCRIPTOR = _LICENSEREQUEST_CONTENTIDENTIFICATION_CENC,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:LicenseRequest.ContentIdentification.CENC)
+ ))
+ ,
+
+ WebM = _reflection.GeneratedProtocolMessageType('WebM', (_message.Message,), dict(
+ DESCRIPTOR = _LICENSEREQUEST_CONTENTIDENTIFICATION_WEBM,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:LicenseRequest.ContentIdentification.WebM)
+ ))
+ ,
+
+ ExistingLicense = _reflection.GeneratedProtocolMessageType('ExistingLicense', (_message.Message,), dict(
+ DESCRIPTOR = _LICENSEREQUEST_CONTENTIDENTIFICATION_EXISTINGLICENSE,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:LicenseRequest.ContentIdentification.ExistingLicense)
+ ))
+ ,
+ DESCRIPTOR = _LICENSEREQUEST_CONTENTIDENTIFICATION,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:LicenseRequest.ContentIdentification)
+ ))
+ ,
+ DESCRIPTOR = _LICENSEREQUEST,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:LicenseRequest)
+ ))
+_sym_db.RegisterMessage(LicenseRequest)
+_sym_db.RegisterMessage(LicenseRequest.ContentIdentification)
+_sym_db.RegisterMessage(LicenseRequest.ContentIdentification.CENC)
+_sym_db.RegisterMessage(LicenseRequest.ContentIdentification.WebM)
+_sym_db.RegisterMessage(LicenseRequest.ContentIdentification.ExistingLicense)
+
+ProvisionedDeviceInfo = _reflection.GeneratedProtocolMessageType('ProvisionedDeviceInfo', (_message.Message,), dict(
+ DESCRIPTOR = _PROVISIONEDDEVICEINFO,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:ProvisionedDeviceInfo)
+ ))
+_sym_db.RegisterMessage(ProvisionedDeviceInfo)
+
+ProvisioningOptions = _reflection.GeneratedProtocolMessageType('ProvisioningOptions', (_message.Message,), dict(
+ DESCRIPTOR = _PROVISIONINGOPTIONS,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:ProvisioningOptions)
+ ))
+_sym_db.RegisterMessage(ProvisioningOptions)
+
+ProvisioningRequest = _reflection.GeneratedProtocolMessageType('ProvisioningRequest', (_message.Message,), dict(
+ DESCRIPTOR = _PROVISIONINGREQUEST,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:ProvisioningRequest)
+ ))
+_sym_db.RegisterMessage(ProvisioningRequest)
+
+ProvisioningResponse = _reflection.GeneratedProtocolMessageType('ProvisioningResponse', (_message.Message,), dict(
+ DESCRIPTOR = _PROVISIONINGRESPONSE,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:ProvisioningResponse)
+ ))
+_sym_db.RegisterMessage(ProvisioningResponse)
+
+RemoteAttestation = _reflection.GeneratedProtocolMessageType('RemoteAttestation', (_message.Message,), dict(
+ DESCRIPTOR = _REMOTEATTESTATION,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:RemoteAttestation)
+ ))
+_sym_db.RegisterMessage(RemoteAttestation)
+
+SessionInit = _reflection.GeneratedProtocolMessageType('SessionInit', (_message.Message,), dict(
+ DESCRIPTOR = _SESSIONINIT,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:SessionInit)
+ ))
+_sym_db.RegisterMessage(SessionInit)
+
+SessionState = _reflection.GeneratedProtocolMessageType('SessionState', (_message.Message,), dict(
+ DESCRIPTOR = _SESSIONSTATE,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:SessionState)
+ ))
+_sym_db.RegisterMessage(SessionState)
+
+SignedCertificateStatusList = _reflection.GeneratedProtocolMessageType('SignedCertificateStatusList', (_message.Message,), dict(
+ DESCRIPTOR = _SIGNEDCERTIFICATESTATUSLIST,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:SignedCertificateStatusList)
+ ))
+_sym_db.RegisterMessage(SignedCertificateStatusList)
+
+SignedDeviceCertificate = _reflection.GeneratedProtocolMessageType('SignedDeviceCertificate', (_message.Message,), dict(
+ DESCRIPTOR = _SIGNEDDEVICECERTIFICATE,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:SignedDeviceCertificate)
+ ))
+_sym_db.RegisterMessage(SignedDeviceCertificate)
+
+SignedProvisioningMessage = _reflection.GeneratedProtocolMessageType('SignedProvisioningMessage', (_message.Message,), dict(
+ DESCRIPTOR = _SIGNEDPROVISIONINGMESSAGE,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:SignedProvisioningMessage)
+ ))
+_sym_db.RegisterMessage(SignedProvisioningMessage)
+
+SignedMessage = _reflection.GeneratedProtocolMessageType('SignedMessage', (_message.Message,), dict(
+ DESCRIPTOR = _SIGNEDMESSAGE,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:SignedMessage)
+ ))
+_sym_db.RegisterMessage(SignedMessage)
+
+WidevineCencHeader = _reflection.GeneratedProtocolMessageType('WidevineCencHeader', (_message.Message,), dict(
+ DESCRIPTOR = _WIDEVINECENCHEADER,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:WidevineCencHeader)
+ ))
+_sym_db.RegisterMessage(WidevineCencHeader)
+
+SignedLicenseRequest = _reflection.GeneratedProtocolMessageType('SignedLicenseRequest', (_message.Message,), dict(
+ DESCRIPTOR = _SIGNEDLICENSEREQUEST,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:SignedLicenseRequest)
+ ))
+_sym_db.RegisterMessage(SignedLicenseRequest)
+
+SignedLicense = _reflection.GeneratedProtocolMessageType('SignedLicense', (_message.Message,), dict(
+ DESCRIPTOR = _SIGNEDLICENSE,
+ __module__ = 'wv_proto3_pb2'
+ # @@protoc_insertion_point(class_scope:SignedLicense)
+ ))
+_sym_db.RegisterMessage(SignedLicense)
+
+
+# @@protoc_insertion_point(module_scope)
diff --git a/pywidevine/cdm/key.py b/pywidevine/cdm/key.py
new file mode 100644
index 0000000..0f0b956
--- /dev/null
+++ b/pywidevine/cdm/key.py
@@ -0,0 +1,14 @@
+import binascii
+
+class Key:
+ def __init__(self, kid, type, key, permissions=[]):
+ self.kid = kid
+ self.type = type
+ self.key = key
+ self.permissions = permissions
+
+ def __repr__(self):
+ if self.type == "OPERATOR_SESSION":
+ return "key(kid={}, type={}, key={}, permissions={})".format(self.kid, self.type, binascii.hexlify(self.key), self.permissions)
+ else:
+ return "key(kid={}, type={}, key={})".format(self.kid, self.type, binascii.hexlify(self.key))
diff --git a/pywidevine/cdm/session.py b/pywidevine/cdm/session.py
new file mode 100644
index 0000000..0f7295c
--- /dev/null
+++ b/pywidevine/cdm/session.py
@@ -0,0 +1,18 @@
+class Session:
+ def __init__(self, session_id, init_data, device_config, offline):
+ self.session_id = session_id
+ self.init_data = init_data
+ self.offline = offline
+ self.device_config = device_config
+ self.device_key = None
+ self.session_key = None
+ self.derived_keys = {
+ 'enc': None,
+ 'auth_1': None,
+ 'auth_2': None
+ }
+ self.license_request = None
+ self.license = None
+ self.service_certificate = None
+ self.privacy_mode = False
+ self.keys = []
diff --git a/pywidevine/cdm/vmp.py b/pywidevine/cdm/vmp.py
new file mode 100644
index 0000000..42ab1bf
--- /dev/null
+++ b/pywidevine/cdm/vmp.py
@@ -0,0 +1,102 @@
+try:
+ from google.protobuf.internal.decoder import _DecodeVarint as _di # this was tested to work with protobuf 3, but it's an internal API (any varint decoder might work)
+except ImportError:
+ # this is generic and does not depend on pb internals, however it will decode "larger" possible numbers than pb decoder which has them fixed
+ def LEB128_decode(buffer, pos, limit = 64):
+ result = 0
+ shift = 0
+ while True:
+ b = buffer[pos]
+ pos += 1
+ result |= ((b & 0x7F) << shift)
+ if not (b & 0x80):
+ return (result, pos)
+ shift += 7
+ if shift > limit:
+ raise Exception("integer too large, shift: {}".format(shift))
+ _di = LEB128_decode
+
+
+class FromFileMixin:
+ @classmethod
+ def from_file(cls, filename):
+ """Load given a filename"""
+ with open(filename,"rb") as f:
+ return cls(f.read())
+
+# the signatures use a format internally similar to
+# protobuf's encoding, but without wire types
+class VariableReader(FromFileMixin):
+ """Protobuf-like encoding reader"""
+
+ def __init__(self, buf):
+ self.buf = buf
+ self.pos = 0
+ self.size = len(buf)
+
+ def read_int(self):
+ """Read a variable length integer"""
+ # _DecodeVarint will take care of out of range errors
+ (val, nextpos) = _di(self.buf, self.pos)
+ self.pos = nextpos
+ return val
+
+ def read_bytes_raw(self, size):
+ """Read size bytes"""
+ b = self.buf[self.pos:self.pos+size]
+ self.pos += size
+ return b
+
+ def read_bytes(self):
+ """Read a bytes object"""
+ size = self.read_int()
+ return self.read_bytes_raw(size)
+
+ def is_end(self):
+ return (self.size == self.pos)
+
+
+class TaggedReader(VariableReader):
+ """Tagged reader, needed for implementing a WideVine signature reader"""
+
+ def read_tag(self):
+ """Read a tagged buffer"""
+ return (self.read_int(), self.read_bytes())
+
+ def read_all_tags(self, max_tag=3):
+ tags = {}
+ while (not self.is_end()):
+ (tag, bytes) = self.read_tag()
+ if (tag > max_tag):
+ raise IndexError("tag out of bound: got {}, max {}".format(tag, max_tag))
+
+ tags[tag] = bytes
+ return tags
+
+class WideVineSignatureReader(FromFileMixin):
+ """Parses a widevine .sig signature file."""
+
+ SIGNER_TAG = 1
+ SIGNATURE_TAG = 2
+ ISMAINEXE_TAG = 3
+
+ def __init__(self, buf):
+ reader = TaggedReader(buf)
+ self.version = reader.read_int()
+ if (self.version != 0):
+ raise Exception("Unsupported signature format version {}".format(self.version))
+ self.tags = reader.read_all_tags()
+
+ self.signer = self.tags[self.SIGNER_TAG]
+ self.signature = self.tags[self.SIGNATURE_TAG]
+
+ extra = self.tags[self.ISMAINEXE_TAG]
+ if (len(extra) != 1 or (extra[0] > 1)):
+ raise Exception("Unexpected 'ismainexe' field value (not '\\x00' or '\\x01'), please check: {0}".format(extra))
+
+ self.mainexe = bool(extra[0])
+
+ @classmethod
+ def get_tags(cls, filename):
+ """Return a dictionary of each tag in the signature file"""
+ return cls.from_file(filename).tags
diff --git a/pywidevine/clients/blim/__pycache__/client.cpython-37.pyc b/pywidevine/clients/blim/__pycache__/client.cpython-37.pyc
new file mode 100644
index 0000000..aa11f3d
Binary files /dev/null and b/pywidevine/clients/blim/__pycache__/client.cpython-37.pyc differ
diff --git a/pywidevine/clients/blim/__pycache__/config.cpython-37.pyc b/pywidevine/clients/blim/__pycache__/config.cpython-37.pyc
new file mode 100644
index 0000000..a4b361d
Binary files /dev/null and b/pywidevine/clients/blim/__pycache__/config.cpython-37.pyc differ
diff --git a/pywidevine/clients/blim/__pycache__/downloader.cpython-37.pyc b/pywidevine/clients/blim/__pycache__/downloader.cpython-37.pyc
new file mode 100644
index 0000000..24d62de
Binary files /dev/null and b/pywidevine/clients/blim/__pycache__/downloader.cpython-37.pyc differ
diff --git a/pywidevine/clients/blim/__pycache__/downloader_pr.cpython-37.pyc b/pywidevine/clients/blim/__pycache__/downloader_pr.cpython-37.pyc
new file mode 100644
index 0000000..11fdb00
Binary files /dev/null and b/pywidevine/clients/blim/__pycache__/downloader_pr.cpython-37.pyc differ
diff --git a/pywidevine/clients/blim/__pycache__/downloader_wv.cpython-37.pyc b/pywidevine/clients/blim/__pycache__/downloader_wv.cpython-37.pyc
new file mode 100644
index 0000000..9a994be
Binary files /dev/null and b/pywidevine/clients/blim/__pycache__/downloader_wv.cpython-37.pyc differ
diff --git a/pywidevine/clients/blim/__pycache__/manifest_parse.cpython-37.pyc b/pywidevine/clients/blim/__pycache__/manifest_parse.cpython-37.pyc
new file mode 100644
index 0000000..1616c3a
Binary files /dev/null and b/pywidevine/clients/blim/__pycache__/manifest_parse.cpython-37.pyc differ
diff --git a/pywidevine/clients/blim/client.py b/pywidevine/clients/blim/client.py
new file mode 100644
index 0000000..a3d01f6
--- /dev/null
+++ b/pywidevine/clients/blim/client.py
@@ -0,0 +1,27 @@
+import json, sys, time
+import pywidevine.clients.blim.config as blim_cfg
+from os.path import join
+
+BLIMLOGINDATA_FILE = join(blim_cfg.COOKIES_FOLDER, 'blim_login_data.json')
+
+login_cfg = {
+ 'email': 'teste@blim.com',
+ 'password': 'teste1234'
+}
+
+def login(SESSION, save_login=False):
+ post_data = {"email": login_cfg['email'], "password": login_cfg['password'], "remember": True, "clientId":5}
+ login_resp = SESSION.post(url=blim_cfg.ENDPOINTS['login'], json=post_data)
+ if login_resp.json()['data'] == []:
+ print(login_resp.json()['messages'][0]['value'])
+ sys.exit(1)
+
+ costumer_key = login_resp.json()['data']['sessionId']
+ access_key_secret = login_resp.json()['data']['accessToken']
+ login_data = {'COSTUMER_KEY': costumer_key, 'SECRET_KEY': access_key_secret}
+ if save_login:
+ with open(BLIMLOGINDATA_FILE, 'w', encoding='utf-8') as f:
+ f.write(json.dumps(login_data, indent=4))
+ f.close()
+
+ return SESSION, costumer_key, access_key_secret
diff --git a/pywidevine/clients/blim/config.py b/pywidevine/clients/blim/config.py
new file mode 100644
index 0000000..567f986
--- /dev/null
+++ b/pywidevine/clients/blim/config.py
@@ -0,0 +1,59 @@
+from shutil import which
+from os.path import dirname, realpath, join
+from os import pathsep, environ
+
+ENDPOINTS = {
+ 'login': 'https://api.blim.com/account/login',
+ 'seasons': 'https://api.blim.com/asset/',
+ 'content': 'https://api.blim.com/play/resume/',
+ 'config': 'https://www.blim.com/secure/play/resume/configuration?config_token=portal-config'
+}
+
+protection_keys = {
+ '094af042a17556c5b28a176deffdd4a7:14319c175eb145071fe189d2b1da8634',
+ '4ae10c2357e250e088bb8a5ab044dd50:e7f47e2b948e9222cf4d24b51881ec04',
+ 'b6e16839eebd4ff6ab768d482d8d2b6a:ad6c675e0810741538f7f2f0b4099d9e'
+}
+
+init_files = {
+ '1080p': 'https://cdn.discordapp.com/attachments/686581369249333291/857062526856200252/video_init_1920x1080.bin',
+ '480p': 'https://cdn.discordapp.com/attachments/686581369249333291/857062525421092944/video_640x480.bin',
+ 'audio': 'https://cdn.discordapp.com/attachments/686581369249333291/857104327742193735/audio_init.bin'
+}
+
+SCRIPT_PATH = dirname(realpath('blimtv'))
+
+BINARIES_FOLDER = join(SCRIPT_PATH, 'binaries')
+COOKIES_FOLDER = join(SCRIPT_PATH, 'cookies')
+
+MP4DECRYPT_BINARY = 'mp4decrypt'
+MP4DUMP_BINARY = 'mp4dump'
+MKVMERGE_BINARY = 'mkvmerge'
+FFMPEG_BINARY = 'ffmpeg'
+ARIA2C_BINARY = 'aria2c'
+
+# Add binaries folder to PATH as the first item
+environ['PATH'] = pathsep.join([BINARIES_FOLDER, environ['PATH']])
+
+MP4DECRYPT = which(MP4DECRYPT_BINARY)
+MP4DUMP = which(MP4DUMP_BINARY)
+MKVMERGE = which(MKVMERGE_BINARY)
+FFMPEG = which(FFMPEG_BINARY)
+ARIA2C = which(ARIA2C_BINARY)
+
+class PrDownloaderConfig(object):
+ def __init__(self, ism, base_url, output_file, bitrate, init_url, file_type):
+ self.ism = ism
+ self.base_url = base_url
+ self.output_file = output_file
+ self.bitrate = bitrate
+ self.init_url = init_url
+ self.file_type = file_type
+
+class WvDownloaderConfig(object):
+ def __init__(self, mpd, base_url, output_file, format_id, file_type):
+ self.mpd = mpd
+ self.base_url = base_url
+ self.output_file = output_file
+ self.format_id = format_id
+ self.file_type = file_type
\ No newline at end of file
diff --git a/pywidevine/clients/blim/downloader_pr.py b/pywidevine/clients/blim/downloader_pr.py
new file mode 100644
index 0000000..6be5a0d
--- /dev/null
+++ b/pywidevine/clients/blim/downloader_pr.py
@@ -0,0 +1,117 @@
+import threading, isodate
+import requests
+import math
+import urllib.parse
+
+from requests.sessions import session
+from tqdm import tqdm
+from queue import Queue
+
+dlthreads = 24
+
+class PrDownloader(object):
+ def __init__(self, config):
+ self.ism = config.ism
+ self.output_file = config.output_file
+ self.bitrate = config.bitrate
+ self.base_url = config.base_url
+ self.init_url = config.init_url
+ self.config = config
+
+ def process_url_templace(self, template, representation_id, bandwidth, time, number):
+ if representation_id is not None: result = template.replace('$RepresentationID$', representation_id)
+ if number is not None:
+ nstart = result.find('$Number')
+ if nstart >= 0:
+ nend = result.find('$', nstart+1)
+ if nend >= 0:
+ var = result[nstart+1 : nend]
+ if 'Number%' in var:
+ value = var[6:] % (int(number))
+ else:
+ value = number
+ result = result.replace('$'+var+'$', value)
+ if bandwidth is not None: result = result.replace('$Bandwidth$', bandwidth)
+ if time is not None: result = result.replace('$Time$', time)
+ result = result.replace('$$', '$').replace('../', '')
+ return result
+
+ def generate_segments(self):
+ quality_level = self.get_quality_level()
+ return self.get_segments(quality_level)
+
+ def get_segments(self, stream_index):
+ urls = []
+ urls.append(self.init_url)
+ t = 0
+ for seg in stream_index["c"]:
+ if '@t' in seg:
+ t = seg['@t']
+ for i in range(int(seg.get('@r', 0)) + 1):
+ path = stream_index['@Url'].format(**{
+ 'bitrate': self.bitrate,
+ 'start time': t})
+ url = urllib.parse.urljoin(self.base_url, path)
+ urls.append(url)
+ t += int(seg['@d'])
+ return urls
+
+ def get_quality_level(self):
+ X = [item for (i, item) in enumerate(self.ism['SmoothStreamingMedia']['StreamIndex']) if self.config.file_type in item.get('@Type')][0]
+ return X
+
+ def run(self):
+ urls = self.generate_segments()
+ work_q = Queue()
+ result_q = Queue()
+
+ print('\n' + self.output_file)
+ pool = [WorkerThread(work_q=work_q, result_q=result_q) for i in range(dlthreads)]
+ for thread in pool:
+ thread.start()
+
+ work_count = 0
+ for seg_url in urls:
+ work_q.put((work_count, seg_url))
+ work_count += 1
+ results = []
+
+ for _ in tqdm(range(work_count)):
+ results.append(result_q.get())
+ outfile = open(self.output_file , 'wb+')
+ sortedr = sorted(results, key=lambda v: v[0])
+ for r in sortedr:
+ outfile.write(r[1])
+ outfile.close()
+ del results
+ print('Done!')
+
+class Downloader:
+ def __init__(self):
+ self.session = requests.Session()
+
+ def DownloadSegment(self, url):
+ resp = self.session.get(url, stream=True)
+ resp.raw.decode_content = True
+ data = resp.raw.read()
+ return data
+
+class WorkerThread(threading.Thread):
+ def __init__(self, work_q, result_q):
+ super(WorkerThread, self).__init__()
+ self.work_q = work_q
+ self.result_q = result_q
+ self.stoprequest = threading.Event()
+ self.downloader = Downloader()
+
+ def run(self):
+ while not self.stoprequest.isSet():
+ try:
+ (seq, url) = self.work_q.get(True, 0.05)
+ self.result_q.put((seq, self.downloader.DownloadSegment(url)))
+ except:
+ continue
+
+ def join(self, timeout=None):
+ self.stoprequest.set()
+ super(WorkerThread, self).join(timeout)
diff --git a/pywidevine/clients/blim/downloader_wv.py b/pywidevine/clients/blim/downloader_wv.py
new file mode 100644
index 0000000..0264fc9
--- /dev/null
+++ b/pywidevine/clients/blim/downloader_wv.py
@@ -0,0 +1,155 @@
+import threading, isodate
+import requests
+import math
+
+from requests.sessions import session
+from tqdm import tqdm
+from queue import Queue
+
+dlthreads = 24
+
+class WvDownloader(object):
+ def __init__(self, config):
+ self.mpd = config.mpd
+ self.output_file = config.output_file
+ self.mimetype = config.file_type
+ self.formatId = config.format_id
+ self.config = config
+
+ def process_url_templace(self, template, representation_id, bandwidth, time, number):
+ if representation_id is not None: result = template.replace('$RepresentationID$', representation_id)
+ if number is not None:
+ nstart = result.find('$Number')
+ if nstart >= 0:
+ nend = result.find('$', nstart+1)
+ if nend >= 0:
+ var = result[nstart+1 : nend]
+ if 'Number%' in var:
+ value = var[6:] % (int(number))
+ else:
+ value = number
+ result = result.replace('$'+var+'$', value)
+ if bandwidth is not None: result = result.replace('$Bandwidth$', bandwidth)
+ if time is not None: result = result.replace('$Time$', time)
+ result = result.replace('$$', '$').replace('../', '')
+ return result
+
+ def generate_segments(self):
+ segment_template = self.get_segment_template()
+ return self.get_segments(segment_template)
+
+ def get_segments(self, segment_template):
+ urls = []
+ urls.append(self.config.base_url + segment_template['@initialization'].replace('$RepresentationID$', self.config.format_id))
+ print(urls)
+ try:
+ current_number = int(segment_template.get("@startNumber", 0))
+ period_duration = self.get_duration()
+ segment_duration = int(segment_template["@duration"]) / int(segment_template["@timescale"])
+ total_segments = math.ceil(period_duration / segment_duration)
+ for _ in range(current_number, current_number + total_segments):
+ urls.append(self.config.base_url + self.process_url_templace(segment_template['@media'],
+ representation_id=self.config.format_id,
+ bandwidth=None, time="0", number=str(current_number)))
+ current_number += 1
+ except KeyError:
+ current_number = 0
+ current_time = 0
+ for seg in segment_template["SegmentTimeline"]["S"]:
+ if '@t' in seg:
+ current_time = seg['@t']
+ for i in range(int(seg.get('@r', 0)) + 1):
+ urls.append(self.config.base_url + self.process_url_templace(segment_template['@media'],
+ representation_id=self.config.format_id,
+ bandwidth=None, time=str(current_time), number=str(current_number)))
+ current_number += 1
+ current_time += seg['@d']
+ return urls
+
+ def get_duration(self):
+ media_duration = self.mpd["MPD"]["@mediaPresentationDuration"]
+ return isodate.parse_duration(media_duration).total_seconds()
+
+ def get_segment_template(self):
+ tracks = self.mpd['MPD']['Period']['AdaptationSet']
+
+ segment_template = []
+ if self.mimetype == "video/mp4":
+ for video_track in tracks:
+ if video_track["@mimeType"] == self.mimetype:
+ for v in video_track["Representation"]:
+ segment_template = v["SegmentTemplate"]
+
+ if self.mimetype == "audio/mp4":
+ for audio_track in tracks:
+ if audio_track["@mimeType"] == self.mimetype:
+ try:
+ segment_template = audio_track["SegmentTemplate"]
+ except (KeyError, TypeError):
+ for a in self.list_representation(audio_track):
+ segment_template = a["SegmentTemplate"]
+
+ return segment_template
+
+ def list_representation(self, x):
+ if isinstance(x['Representation'], list):
+ X = x['Representation']
+ else:
+ X = [x['Representation']]
+ return X
+
+ def run(self):
+ urls = self.generate_segments()
+ work_q = Queue()
+ result_q = Queue()
+
+ print('\n' + self.output_file)
+ pool = [WorkerThread(work_q=work_q, result_q=result_q) for i in range(dlthreads)]
+ for thread in pool:
+ thread.start()
+
+ work_count = 0
+ for seg_url in urls:
+ work_q.put((work_count, seg_url))
+ work_count += 1
+ results = []
+
+ for _ in tqdm(range(work_count)):
+ results.append(result_q.get())
+ outfile = open(self.output_file , 'wb+')
+ sortedr = sorted(results, key=lambda v: v[0])
+ for r in sortedr:
+ outfile.write(r[1])
+ outfile.close()
+ del results
+ print('Done!')
+
+class Downloader:
+ def __init__(self):
+ self.session = requests.Session()
+
+ def DownloadSegment(self, url):
+ resp = self.session.get(url, stream=True)
+ resp.raw.decode_content = True
+ data = resp.raw.read()
+ return data
+
+class WorkerThread(threading.Thread):
+ def __init__(self, work_q, result_q):
+ super(WorkerThread, self).__init__()
+ self.work_q = work_q
+ self.result_q = result_q
+ self.stoprequest = threading.Event()
+ self.downloader = Downloader()
+
+ def run(self):
+ while not self.stoprequest.isSet():
+ try:
+ (seq, url) = self.work_q.get(True, 0.05)
+ self.result_q.put((seq, self.downloader.DownloadSegment(url)))
+ except:
+ continue
+
+ def join(self, timeout=None):
+ self.stoprequest.set()
+ super(WorkerThread, self).join(timeout)
diff --git a/pywidevine/clients/blim/manifest_parse.py b/pywidevine/clients/blim/manifest_parse.py
new file mode 100644
index 0000000..9e545dd
--- /dev/null
+++ b/pywidevine/clients/blim/manifest_parse.py
@@ -0,0 +1,104 @@
+import isodate
+
+def get_mpd_list(mpd):
+ def get_height(width, height):
+ if width == '1920':
+ return '1080'
+ elif width in ('1280', '1248'):
+ return '720'
+ else:
+ return height
+
+ length = isodate.parse_duration(mpd['MPD']['@mediaPresentationDuration']).total_seconds()
+ period = mpd['MPD']['Period']
+ base_url = period['BaseURL']
+ tracks = period['AdaptationSet']
+
+ video_list = []
+ for video_tracks in tracks:
+ if video_tracks['@mimeType'] == 'video/mp4':
+ for x in video_tracks['Representation']:
+ try:
+ codecs = x['@codecs']
+ except KeyError:
+ codecs = video_tracks['@codecs']
+
+ videoDict = {
+ 'Height':get_height(x['@width'], x['@height']),
+ 'Width':x['@width'],
+ 'Bandwidth':x['@bandwidth'],
+ 'ID':x['@id'],
+ 'Codec':codecs}
+ video_list.append(videoDict)
+
+ def list_representation(x):
+ if isinstance(x['Representation'], list):
+ X = x['Representation']
+ else:
+ X = [x['Representation']]
+ return X
+
+ def replace_code_lang(x):
+ X = x.replace('es', 'es-la').replace('en', 'es-la')
+ return X
+
+ audio_list = []
+ for audio_tracks in tracks:
+ if audio_tracks['@mimeType'] == 'audio/mp4':
+ for x in list_representation(audio_tracks):
+ try:
+ codecs = x['@codecs']
+ except KeyError:
+ codecs = audio_tracks['@codecs']
+ audio_dict = {
+ 'Bandwidth':x['@bandwidth'],
+ 'ID':x['@id'],
+ 'Language':audio_tracks["@lang"],
+ 'Codec':codecs}
+ audio_list.append(audio_dict)
+
+ subs_list = []
+ for subs_tracks in tracks:
+ if subs_tracks['@mimeType'] == 'text/vtt':
+ for x in list_representation(subs_tracks):
+ subs_dict = {
+ 'ID':x['@id'],
+ 'Language':replace_code_lang(subs_tracks["@lang"]),
+ 'Codec':subs_tracks['@mimeType'],
+ 'File_URL':base_url + x['BaseURL'].replace('../', '')}
+ subs_list.append(subs_dict)
+
+ return length, video_list, audio_list, subs_list
+
+def get_ism_list(ism):
+ length = float(ism['SmoothStreamingMedia']['@Duration'][:-7])
+ tracks = ism['SmoothStreamingMedia']["StreamIndex"]
+
+ video_list = []
+ for video_tracks in tracks:
+ if video_tracks['@Type'] == 'video':
+ for x in video_tracks['QualityLevel']:
+ videoDict = {
+ 'Height':x['@MaxHeight'],
+ 'Width':x['@MaxWidth'],
+ 'ID':'0',
+ 'Bandwidth':x['@Bitrate'],
+ 'Codec':x["@FourCC"]}
+ video_list.append(videoDict)
+
+ def replace_code_lang(x):
+ X = x.replace('255', 'es-la')
+ return X
+
+ audio_list = []
+ for audio_tracks in tracks:
+ if audio_tracks['@Type'] == 'audio':
+ for x in audio_tracks["QualityLevel"]:
+ audio_dict = {
+ 'Bandwidth':x['@Bitrate'],
+ 'ID':'0',
+ 'Language':replace_code_lang(x["@AudioTag"]),
+ 'Codec':x["@FourCC"]}
+ audio_list.append(audio_dict)
+
+ return length, video_list, audio_list, []
diff --git a/pywidevine/clients/dictionary.py b/pywidevine/clients/dictionary.py
new file mode 100644
index 0000000..b22e939
--- /dev/null
+++ b/pywidevine/clients/dictionary.py
@@ -0,0 +1,42 @@
+import re
+from unidecode import unidecode
+
+def get_release_tag(default_filename, vcodec, video_height, acodec, channels, bitrate, module, tag, isDual):
+ video_codec = ''
+
+ if 'avc' in vcodec:
+ video_codec = 'H.264'
+ if 'hvc' in vcodec:
+ video_codec = 'H.265'
+ elif 'dvh' in vcodec:
+ video_codec = 'HDR'
+
+ if isDual==False:
+ audio_codec = ''
+ if 'mp4a' in acodec:
+ audio_codec = 'AAC'
+ if acodec == 'ac-3':
+ audio_codec = 'DD'
+ if acodec == 'ec-3':
+ audio_codec = 'DDP'
+ elif acodec == 'ec-3' and bitrate > 700000:
+ audio_codec = 'Atmos'
+
+ audio_channels = ''
+ if channels == '2':
+ audio_channels = '2.0'
+ elif channels == '6':
+ audio_channels = '5.1'
+ audio_format = audio_codec + audio_channels
+ else:
+ audio_format = 'DUAL'
+
+
+ default_filename = default_filename.replace('&', '.and.')
+ default_filename = re.sub(r'[]!"#$%\'()*+,:;<=>?@\\^_`{|}~[-]', '', default_filename)
+ default_filename = default_filename.replace(' ', '.')
+ default_filename = re.sub(r'\.{2,}', '.', default_filename)
+ default_filename = unidecode(default_filename)
+
+ output_name = '{}.{}p.{}.WEB-DL.{}.{}-{}'.format(default_filename, video_height, str(module), audio_format, video_codec, tag)
+ return output_name
\ No newline at end of file
diff --git a/pywidevine/clients/hbomax/__pycache__/authHelper.cpython-37.pyc b/pywidevine/clients/hbomax/__pycache__/authHelper.cpython-37.pyc
new file mode 100644
index 0000000..9e51aa9
Binary files /dev/null and b/pywidevine/clients/hbomax/__pycache__/authHelper.cpython-37.pyc differ
diff --git a/pywidevine/clients/hbomax/__pycache__/authHelper.cpython-38.pyc b/pywidevine/clients/hbomax/__pycache__/authHelper.cpython-38.pyc
new file mode 100644
index 0000000..4625214
Binary files /dev/null and b/pywidevine/clients/hbomax/__pycache__/authHelper.cpython-38.pyc differ
diff --git a/pywidevine/clients/hbomax/__pycache__/client.cpython-37.pyc b/pywidevine/clients/hbomax/__pycache__/client.cpython-37.pyc
new file mode 100644
index 0000000..e191c2e
Binary files /dev/null and b/pywidevine/clients/hbomax/__pycache__/client.cpython-37.pyc differ
diff --git a/pywidevine/clients/hbomax/__pycache__/client.cpython-38.pyc b/pywidevine/clients/hbomax/__pycache__/client.cpython-38.pyc
new file mode 100644
index 0000000..65e4c6f
Binary files /dev/null and b/pywidevine/clients/hbomax/__pycache__/client.cpython-38.pyc differ
diff --git a/pywidevine/clients/hbomax/__pycache__/client_.cpython-37.pyc b/pywidevine/clients/hbomax/__pycache__/client_.cpython-37.pyc
new file mode 100644
index 0000000..a0dae52
Binary files /dev/null and b/pywidevine/clients/hbomax/__pycache__/client_.cpython-37.pyc differ
diff --git a/pywidevine/clients/hbomax/__pycache__/config.cpython-37.pyc b/pywidevine/clients/hbomax/__pycache__/config.cpython-37.pyc
new file mode 100644
index 0000000..11a9add
Binary files /dev/null and b/pywidevine/clients/hbomax/__pycache__/config.cpython-37.pyc differ
diff --git a/pywidevine/clients/hbomax/__pycache__/constants.cpython-37.pyc b/pywidevine/clients/hbomax/__pycache__/constants.cpython-37.pyc
new file mode 100644
index 0000000..7760ff3
Binary files /dev/null and b/pywidevine/clients/hbomax/__pycache__/constants.cpython-37.pyc differ
diff --git a/pywidevine/clients/hbomax/client.py b/pywidevine/clients/hbomax/client.py
new file mode 100644
index 0000000..100d8e7
--- /dev/null
+++ b/pywidevine/clients/hbomax/client.py
@@ -0,0 +1,106 @@
+import base64, time, requests, os, json
+import pywidevine.clients.hbomax.config as hmaxcfg
+from os.path import join
+
+SESSION = requests.Session()
+HMAXTOKEN_FILE = join(hmaxcfg.COOKIES_FOLDER, 'hmax_login_data.json')
+
+
+login_config = {
+ 'username': 'rivas909@me.com',
+ 'password': 'NoCambieselPass.12345'
+}
+
+def login(SESSION, login_endpoint, content_url, save_login=True):
+ def get_free_token(token_url):
+ token_data = hmaxcfg.get_token_info()
+ free_token = requests.post(url=token_url, headers=token_data['headers'], json=token_data['data'])
+ if int(free_token.status_code) != 200:
+ print(free_token.json()['message'])
+ exit(1)
+ return free_token.json()['access_token']
+ free_access_tk = get_free_token(login_endpoint)
+ auth_data = hmaxcfg.get_auth_token_info(login_config)
+ headers = auth_data['headers']
+ headers['authorization'] = "Bearer {}".format(free_access_tk)
+ auth_rep = SESSION.post(url=login_endpoint, headers=headers, json=auth_data['data'])
+ if int(auth_rep.status_code) != 200:
+ print(auth_rep.json()['message'])
+ exit(1)
+
+ access_token_js = auth_rep.json()
+
+ login_grant_access = [
+ {
+ "id": "urn:hbo:privacy-settings:mined",
+ "id": "urn:hbo:profiles:mined",
+ "id": "urn:hbo:query:lastplayed",
+ "id": "urn:hbo:user:me"}
+ ]
+ user_grant_access = {
+ "accept": "application/vnd.hbo.v9.full+json",
+ "accept-encoding": "gzip, deflate, br",
+ "accept-language": hmaxcfg.metadata_language,
+ "user-agent": hmaxcfg.UA,
+ "x-hbo-client-version": "Hadron/50.40.0.111 desktop (DESKTOP)",
+ "x-hbo-device-name": "desktop",
+ "x-hbo-device-os-version": "undefined",
+ "Authorization": f"Bearer {access_token_js['refresh_token']}"
+ }
+ user_grant_req = SESSION.post(content_url, json=login_grant_access, headers=user_grant_access)
+
+ if int(user_grant_req.status_code) != 207:
+ print("failed to list profiles")
+
+ user_grant_js = user_grant_req.json()
+ user_grant_id = ""
+
+ for profile in user_grant_js:
+ if profile['id'] == "urn:hbo:profiles:mine":
+ if len(profile['body']['profiles']) > 0:
+ user_grant_id = profile['body']['profiles'][0]['profileId']
+ else:
+ print("no profiles found, create one on hbomax and try again")
+ exit(1)
+
+ profile_headers = {
+ "accept": "application/vnd.hbo.v9.full+json",
+ "accept-encoding": "gzip, deflate, br",
+ "accept-language": hmaxcfg.metadata_language,
+ "user-agent": hmaxcfg.UA,
+ "x-hbo-client-version": "Hadron/50.40.0.111 desktop (DESKTOP)",
+ "x-hbo-device-name": "desktop",
+ "x-hbo-device-os-version": "undefined",
+ "referer": "https://play.hbomax.com/profileSelect",
+ "Authorization": f"Bearer {free_access_tk}" #~ free token
+ }
+
+ user_profile = {
+ "grant_type": "user_refresh_profile",
+ "profile_id": user_grant_id,
+ "refresh_token": f"{access_token_js['refresh_token']}",
+ }
+
+ user_profile_req = SESSION.post(login_endpoint, json=user_profile, headers=profile_headers)
+
+ if int(user_profile_req.status_code) != 200:
+ error_msg = "failed to obatin the final token"
+ print(error_msg)
+
+ user_profile_js = user_profile_req.json()
+
+ refresh_token = user_profile_js['refresh_token']
+
+ login_data = {'ACCESS_TOKEN': refresh_token, 'EXPIRATION_TIME': int(time.time())}
+ if save_login:
+ with open(HMAXTOKEN_FILE, 'w', encoding='utf-8') as f:
+ f.write(json.dumps(login_data, indent=4))
+ f.close()
+ return auth_rep.json()['access_token']
+
+
+def get_video_payload(urn):
+ headers = hmaxcfg.generate_payload()
+ payload = []
+ payload.append({"id":urn, "headers": headers['headers']})
+ return payload
diff --git a/pywidevine/clients/hbomax/config.py b/pywidevine/clients/hbomax/config.py
new file mode 100644
index 0000000..befd2c0
--- /dev/null
+++ b/pywidevine/clients/hbomax/config.py
@@ -0,0 +1,125 @@
+import uuid, sys
+import configparser
+
+from shutil import which
+from os.path import dirname, realpath, join
+from os import pathsep, environ
+
+def generate_device():
+ return str(uuid.uuid4())
+_uuid = generate_device() #traceid
+
+user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36'
+config = {}
+
+config['la'] = {
+ 'tokens': 'https://gateway-latam.api.hbo.com/auth/tokens',
+ 'content': 'https://comet-latam.api.hbo.com/content',
+ 'license_wv': 'https://comet-latam.api.hbo.com/drm/license/widevine?keygen=playready&drmKeyVersion=2'
+}
+
+config['us'] = {
+ 'tokens': 'https://gateway.api.hbo.com/auth/tokens',
+ 'content': 'https://comet.api.hbo.com/content',
+ 'license_wv': 'https://comet.api.hbo.com/drm/license/widevine?keygen=playready&drmKeyVersion=2'
+}
+
+metadata_language = 'en-US'
+
+UA = 'Mozilla/5.0 (Linux; Android 7.1.1; SHIELD Android TV Build/LMY47D) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/84.0.4147.135 Safari/537.36'
+
+login_headers = {
+ "accept": "application/vnd.hbo.v9.full+json",
+ "accept-encoding": "gzip, deflate, br",
+ "accept-language": metadata_language,
+ "user-agent": UA,
+ "x-hbo-client-version": "Hadron/50.40.0.111 desktop (DESKTOP)",
+ "x-hbo-device-name": "desktop",
+ "x-hbo-device-os-version": "undefined",
+}
+
+login_json = {
+ "client_id": '24fa5e36-3dc4-4ed0-b3f1-29909271b63d',
+ "client_secret": '24fa5e36-3dc4-4ed0-b3f1-29909271b63d',
+ "scope":"browse video_playback_free",
+ "grant_type":"client_credentials",
+ "deviceSerialNumber": 'b394a2da-b3a7-429d-8f70-5c4eae50a678',
+ "clientDeviceData":{
+ "paymentProviderCode":"apple"
+ }
+}
+
+payload = {
+ 'x-hbo-device-model':user_agent,
+ 'x-hbo-video-features':'server-stitched-playlist,mlp',
+ 'x-hbo-session-id':_uuid,
+ 'x-hbo-video-player-version':'QUANTUM_BROWSER/50.30.0.249',
+ 'x-hbo-device-code-override':'ANDROIDTV',
+ 'x-hbo-video-mlp':True,
+}
+
+SCRIPT_PATH = dirname(realpath('hbomax'))
+
+BINARIES_FOLDER = join(SCRIPT_PATH, 'binaries')
+COOKIES_FOLDER = join(SCRIPT_PATH, 'cookies')
+
+MP4DECRYPT_BINARY = 'mp4decrypt'
+MEDIAINFO_BINARY = 'mediainfo'
+MP4DUMP_BINARY = 'mp4dump'
+MKVMERGE_BINARY = 'mkvmerge'
+FFMPEG_BINARY = 'ffmpeg'
+FFMPEG_BINARY = 'ffmpeg'
+ARIA2C_BINARY = 'aria2c'
+SUBTITLE_EDIT_BINARY = 'subtitleedit'
+
+# Add binaries folder to PATH as the first item
+environ['PATH'] = pathsep.join([BINARIES_FOLDER, environ['PATH']])
+
+MP4DECRYPT = which(MP4DECRYPT_BINARY)
+MEDIAINFO = which(MEDIAINFO_BINARY)
+MP4DUMP = which(MP4DUMP_BINARY)
+MKVMERGE = which(MKVMERGE_BINARY)
+FFMPEG = which(FFMPEG_BINARY)
+ARIA2C = which(ARIA2C_BINARY)
+SUBTITLE_EDIT = which(SUBTITLE_EDIT_BINARY)
+
+def get_token_info():
+ return {'headers': login_headers, 'data': login_json}
+
+def get_user_headers():
+ headers = {
+ 'origin': 'https://play.hbomax.com',
+ 'referer': 'https://play.hbomax.com/',
+ 'x-b3-traceid': f'{_uuid}-{_uuid}',
+ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36',
+ 'accept': 'application/vnd.hbo.v9.full+json',
+ 'content-type': 'application/json; charset=utf-8',
+ 'x-hbo-client-version': 'Hadron/50.50.0.85 desktop (DESKTOP)',
+ 'x-hbo-device-name': 'desktop',
+ 'x-hbo-device-os-version': 'undefined'}
+ return {'headers': headers}
+
+def get_auth_token_info(cfg):
+ data = {
+ "grant_type": "user_name_password",
+ "scope": "browse video_playback device elevated_account_management",
+ "username": cfg['username'],
+ "password": cfg['password'],
+ }
+ return {'headers': login_headers, 'data': data, 'device_id': _uuid}
+
+def generate_payload():
+ return {"headers": payload}
+
+class HMAXRegion(object):
+ def configHBOMaxLatam():
+ tokens = config['la']['tokens']
+ content = config['la']['content']
+ license_wv = config['la']['license_wv']
+ return tokens, content, license_wv
+
+ def configHBOMaxUS():
+ tokens = config['us']['tokens']
+ content = config['us']['content']
+ license_wv = config['us']['license_wv']
+ return tokens, content, license_wv
diff --git a/pywidevine/clients/paramountplus/__pycache__/config.cpython-37.pyc b/pywidevine/clients/paramountplus/__pycache__/config.cpython-37.pyc
new file mode 100644
index 0000000..08e16c9
Binary files /dev/null and b/pywidevine/clients/paramountplus/__pycache__/config.cpython-37.pyc differ
diff --git a/pywidevine/clients/paramountplus/__pycache__/downloader.cpython-37.pyc b/pywidevine/clients/paramountplus/__pycache__/downloader.cpython-37.pyc
new file mode 100644
index 0000000..5f0a1b9
Binary files /dev/null and b/pywidevine/clients/paramountplus/__pycache__/downloader.cpython-37.pyc differ
diff --git a/pywidevine/clients/paramountplus/config.py b/pywidevine/clients/paramountplus/config.py
new file mode 100644
index 0000000..e840559
--- /dev/null
+++ b/pywidevine/clients/paramountplus/config.py
@@ -0,0 +1,30 @@
+from shutil import which
+from os.path import dirname, realpath, join
+from os import pathsep, environ
+
+SCRIPT_PATH = dirname(realpath('paramountplus'))
+
+BINARIES_FOLDER = join(SCRIPT_PATH, 'binaries')
+
+MP4DECRYPT_BINARY = 'mp4decrypt'
+MP4DUMP_BINARY = 'mp4dump'
+MKVMERGE_BINARY = 'mkvmerge'
+FFMPEG_BINARY = 'ffmpeg'
+ARIA2C_BINARY = 'aria2c'
+
+# Add binaries folder to PATH as the first item
+environ['PATH'] = pathsep.join([BINARIES_FOLDER, environ['PATH']])
+
+MP4DECRYPT = which(MP4DECRYPT_BINARY)
+MP4DUMP = which(MP4DUMP_BINARY)
+MKVMERGE = which(MKVMERGE_BINARY)
+FFMPEG = which(FFMPEG_BINARY)
+ARIA2C = which(ARIA2C_BINARY)
+
+class WvDownloaderConfig(object):
+ def __init__(self, xml, base_url, output_file, track_id, format_id):
+ self.xml = xml
+ self.base_url = base_url
+ self.output_file = output_file
+ self.track_id = track_id
+ self.format_id = format_id
diff --git a/pywidevine/clients/paramountplus/config_orignal.py b/pywidevine/clients/paramountplus/config_orignal.py
new file mode 100644
index 0000000..ad6bfdc
--- /dev/null
+++ b/pywidevine/clients/paramountplus/config_orignal.py
@@ -0,0 +1,9 @@
+
+class WvDownloaderConfig(object):
+ def __init__(self, xml, base_url, output_file, track_id, format_id, file_type):
+ self.xml = xml
+ self.base_url = base_url
+ self.output_file = output_file
+ self.track_id = track_id
+ self.format_id = format_id
+ self.file_type = file_type
\ No newline at end of file
diff --git a/pywidevine/clients/paramountplus/downloader.py b/pywidevine/clients/paramountplus/downloader.py
new file mode 100644
index 0000000..396c1f9
--- /dev/null
+++ b/pywidevine/clients/paramountplus/downloader.py
@@ -0,0 +1,116 @@
+import requests, pathlib
+import math, subprocess
+import os, sys, shutil
+
+class WvDownloader(object):
+ def __init__(self, config):
+ self.xml = config.xml
+ self.output_file = config.output_file
+ self.config = config
+
+ def download_track(self, aria2c_infile, file_name):
+ aria2c_opts = [
+ 'aria2c',
+ '--enable-color=false',
+ '--allow-overwrite=true',
+ '--summary-interval=0',
+ '--download-result=hide',
+ '--async-dns=false',
+ '--check-certificate=false',
+ '--auto-file-renaming=false',
+ '--file-allocation=none',
+ '--console-log-level=warn',
+ '-x16', '-s16', '-j16',
+ '-i', aria2c_infile]
+ subprocess.run(aria2c_opts, check=True)
+
+ source_files = pathlib.Path(temp_folder).rglob(r'./*.mp4')
+ with open(file_name, mode='wb') as (destination):
+ for file in source_files:
+ with open(file, mode='rb') as (source):
+ shutil.copyfileobj(source, destination)
+ if os.path.exists(temp_folder):
+ shutil.rmtree(temp_folder)
+ os.remove(aria2c_infile)
+ print('\nDone!')
+
+ def process_url_templace(self, template, representation_id, bandwidth, time, number):
+ if representation_id is not None: result = template.replace('$RepresentationID$', representation_id)
+ if number is not None:
+ nstart = result.find('$Number')
+ if nstart >= 0:
+ nend = result.find('$', nstart+1)
+ if nend >= 0:
+ var = result[nstart+1 : nend]
+ if 'Number%' in var:
+ value = var[6:] % (int(number))
+ else:
+ value = number
+ result = result.replace('$'+var+'$', value)
+ if bandwidth is not None: result = result.replace('$Bandwidth$', bandwidth)
+ if time is not None: result = result.replace('$Time$', time)
+ result = result.replace('$$', '$').replace('../', '')
+ return result
+
+ def generate_segments(self):
+ segment_template = self.get_segment_template()
+ return self.get_segments(segment_template)
+
+ def get_segments(self, segment_template):
+ urls = []
+ urls.append(self.config.base_url + segment_template['@initialization'].replace('$RepresentationID$', self.config.format_id))
+ current_number = 1
+ for seg in self.force_segmentimeline(segment_template):
+ if '@t' in seg:
+ current_time = seg['@t']
+ for i in range(int(seg.get('@r', 0)) + 1):
+ urls.append(self.config.base_url + self.process_url_templace(segment_template['@media'],
+ representation_id=self.config.format_id,
+ bandwidth=None, time=str(current_time), number=str(current_number)))
+ current_number += 1
+ current_time += seg['@d']
+ return urls
+
+ def force_segmentimeline(self, segment_timeline):
+ if isinstance(segment_timeline['SegmentTimeline']['S'], list):
+ x16 = segment_timeline['SegmentTimeline']['S']
+ else:
+ x16 = [segment_timeline['SegmentTimeline']['S']]
+ return x16
+
+ def force_instance(self, x):
+ if isinstance(x['Representation'], list):
+ X = x['Representation']
+ else:
+ X = [x['Representation']]
+ return X
+
+ def get_segment_template(self):
+ x = [item for (i, item) in enumerate(self.xml['MPD']['Period']['AdaptationSet']) if self.config.track_id == item["@id"]][0]
+ segment_level = [item['SegmentTemplate'] for (i, item) in enumerate(self.force_instance(x)) if self.config.format_id == item["@id"]][0]
+ return segment_level
+
+ def run(self):
+ urls = self.generate_segments()
+
+ print('\n' + self.output_file)
+ global temp_folder
+ aria2c_infile = 'aria2c_infile.txt'
+ if os.path.isfile(aria2c_infile):
+ os.remove(aria2c_infile)
+ temp_folder = self.output_file.replace('.mp4', '')
+ if os.path.exists(temp_folder):
+ shutil.rmtree(temp_folder)
+ if not os.path.exists(temp_folder):
+ os.makedirs(temp_folder)
+
+ if len(urls) > 1:
+ num_segments = int(math.log10(len(urls))) + 1
+ with open(aria2c_infile, 'a', encoding='utf8') as (file):
+ for (i, url) in enumerate(urls):
+ file.write(f'{url}\n')
+ file.write(f'\tout={temp_folder}.{i:0{num_segments}d}.mp4\n')
+ file.write(f'\tdir={temp_folder}\n')
+ file.flush()
+ self.download_track(aria2c_infile, self.output_file)
+ print('Done!')
diff --git a/pywidevine/clients/paramountplus/downloader_oringal.py b/pywidevine/clients/paramountplus/downloader_oringal.py
new file mode 100644
index 0000000..906f1ce
--- /dev/null
+++ b/pywidevine/clients/paramountplus/downloader_oringal.py
@@ -0,0 +1,110 @@
+import requests, pathlib
+import math, subprocess
+import os, sys, shutil
+
+class WvDownloader(object):
+ def __init__(self, config):
+ self.xml = config.xml
+ self.output_file = config.output_file
+ self.config = config
+
+ def download_track(self, aria2c_infile, file_name):
+ aria2c_opts = [
+ 'aria2c',
+ '--allow-overwrite=true',
+ '--download-result=hide',
+ '--console-log-level=warn',
+ '-x16', '-s16', '-j16',
+ '-i', aria2c_infile]
+ subprocess.run(aria2c_opts, check=True)
+
+ source_files = pathlib.Path(temp_folder).rglob(r'./*.mp4')
+ with open(file_name, mode='wb') as (destination):
+ for file in source_files:
+ with open(file, mode='rb') as (source):
+ shutil.copyfileobj(source, destination)
+ if os.path.exists(temp_folder):
+ shutil.rmtree(temp_folder)
+ os.remove(aria2c_infile)
+ print('\nDone!')
+
+ def process_url_templace(self, template, representation_id, bandwidth, time, number):
+ if representation_id is not None: result = template.replace('$RepresentationID$', representation_id)
+ if number is not None:
+ nstart = result.find('$Number')
+ if nstart >= 0:
+ nend = result.find('$', nstart+1)
+ if nend >= 0:
+ var = result[nstart+1 : nend]
+ if 'Number%' in var:
+ value = var[6:] % (int(number))
+ else:
+ value = number
+ result = result.replace('$'+var+'$', value)
+ if bandwidth is not None: result = result.replace('$Bandwidth$', bandwidth)
+ if time is not None: result = result.replace('$Time$', time)
+ result = result.replace('$$', '$').replace('../', '')
+ return result
+
+ def generate_segments(self):
+ segment_template = self.get_segment_template()
+ return self.get_segments(segment_template)
+
+ def get_segments(self, segment_template):
+ urls = []
+ urls.append(self.config.base_url + segment_template['@initialization'].replace('$RepresentationID$', self.config.format_id))
+ current_number = 1
+ for seg in self.force_segmentimeline(segment_template):
+ if '@t' in seg:
+ current_time = seg['@t']
+ for i in range(int(seg.get('@r', 0)) + 1):
+ urls.append(self.config.base_url + self.process_url_templace(segment_template['@media'],
+ representation_id=self.config.format_id,
+ bandwidth=None, time=str(current_time), number=str(current_number)))
+ current_number += 1
+ current_time += seg['@d']
+ return urls
+
+ def force_segmentimeline(self, segment_timeline):
+ if isinstance(segment_timeline['SegmentTimeline']['S'], list):
+ x16 = segment_timeline['SegmentTimeline']['S']
+ else:
+ x16 = [segment_timeline['SegmentTimeline']['S']]
+ return x16
+
+ def force_instance(self, x):
+ if isinstance(x['Representation'], list):
+ X = x['Representation']
+ else:
+ X = [x['Representation']]
+ return X
+
+ def get_segment_template(self):
+ x = [item for (i, item) in enumerate(self.xml['MPD']['Period']['AdaptationSet']) if self.config.track_id in item["@id"]][0]
+ segment_level = [item['SegmentTemplate'] for (i, item) in enumerate(self.force_instance(x)) if self.config.format_id in item["@id"]][0]
+ return segment_level
+
+ def run(self):
+ urls = self.generate_segments()
+
+ print('\n' + self.output_file)
+ global temp_folder
+ aria2c_infile = 'aria2c_infile.txt'
+ if os.path.isfile(aria2c_infile):
+ os.remove(aria2c_infile)
+ temp_folder = self.output_file.replace('.mp4', '')
+ if os.path.exists(temp_folder):
+ shutil.rmtree(temp_folder)
+ if not os.path.exists(temp_folder):
+ os.makedirs(temp_folder)
+
+ if len(urls) > 1:
+ num_segments = int(math.log10(len(urls))) + 1
+ with open(aria2c_infile, 'a', encoding='utf8') as (file):
+ for (i, url) in enumerate(urls):
+ file.write(f'{url}\n')
+ file.write(f'\tout={temp_folder}.{i:0{num_segments}d}.mp4\n')
+ file.write(f'\tdir={temp_folder}\n')
+ file.flush()
+ self.download_track(aria2c_infile, self.output_file)
+ print('Done!')
diff --git a/pywidevine/clients/paramountplus/paramountplus.rar b/pywidevine/clients/paramountplus/paramountplus.rar
new file mode 100644
index 0000000..16d4c3e
Binary files /dev/null and b/pywidevine/clients/paramountplus/paramountplus.rar differ
diff --git a/pywidevine/clients/proxy_config.py b/pywidevine/clients/proxy_config.py
new file mode 100644
index 0000000..73f003d
--- /dev/null
+++ b/pywidevine/clients/proxy_config.py
@@ -0,0 +1,15 @@
+
+config = {
+ 'proxies': {
+ 'none': None
+ },
+}
+
+class ProxyConfig(object):
+ def __init__(self, proxies):
+ self.config = config
+ self.config['proxies'] = proxies
+
+ def get_proxy(self, proxy):
+ return self.config['proxies'].get(proxy)
+
diff --git a/pywidevine/decrypt/wvdecrypt.py b/pywidevine/decrypt/wvdecrypt.py
new file mode 100644
index 0000000..effe6e8
--- /dev/null
+++ b/pywidevine/decrypt/wvdecrypt.py
@@ -0,0 +1,55 @@
+import logging, subprocess, re, base64
+from pywidevine.cdm import cdm, deviceconfig
+
+class WvDecrypt(object):
+ WV_SYSTEM_ID = [
+ 237, 239, 139, 169, 121, 214, 74, 206, 163, 200, 39, 220, 213, 29, 33, 237]
+
+ def __init__(self, init_data_b64, cert_data_b64, device):
+ self.init_data_b64 = init_data_b64
+ self.cert_data_b64 = cert_data_b64
+ self.device = device
+ self.cdm = cdm.Cdm()
+
+ def check_pssh(pssh_b64):
+ pssh = base64.b64decode(pssh_b64)
+ if not pssh[12:28] == bytes(self.WV_SYSTEM_ID):
+ new_pssh = bytearray([0, 0, 0])
+ new_pssh.append(32 + len(pssh))
+ new_pssh[4:] = bytearray(b'pssh')
+ new_pssh[8:] = [0, 0, 0, 0]
+ new_pssh[13:] = self.WV_SYSTEM_ID
+ new_pssh[29:] = [0, 0, 0, 0]
+ new_pssh[31] = len(pssh)
+ new_pssh[32:] = pssh
+ return base64.b64encode(new_pssh)
+ else:
+ return pssh_b64
+
+ self.session = self.cdm.open_session(check_pssh(self.init_data_b64), deviceconfig.DeviceConfig(self.device))
+ if self.cert_data_b64:
+ self.cdm.set_service_certificate(self.session, self.cert_data_b64)
+
+ def log_message(self, msg):
+ return '{}'.format(msg)
+
+ def start_process(self):
+ keyswvdecrypt = []
+ try:
+ for key in self.cdm.get_keys(self.session):
+ if key.type == 'CONTENT':
+ keyswvdecrypt.append(self.log_message('{}:{}'.format(key.kid.hex(), key.key.hex())))
+
+ except Exception:
+ return (
+ False, keyswvdecrypt)
+ else:
+ return (
+ True, keyswvdecrypt)
+
+ def get_challenge(self):
+ return self.cdm.get_license_request(self.session)
+
+ def update_license(self, license_b64):
+ self.cdm.provide_license(self.session, license_b64)
+ return True
\ No newline at end of file
diff --git a/pywidevine/decrypt/wvdecryptcustom.py b/pywidevine/decrypt/wvdecryptcustom.py
new file mode 100644
index 0000000..9c19f0f
--- /dev/null
+++ b/pywidevine/decrypt/wvdecryptcustom.py
@@ -0,0 +1,59 @@
+# uncompyle6 version 3.7.3
+# Python bytecode 3.6 (3379)
+# Decompiled from: Python 3.7.8 (tags/v3.7.8:4b47a5b6ba, Jun 28 2020, 08:53:46) [MSC v.1916 64 bit (AMD64)]
+# Embedded file name: pywidevine\decrypt\wvdecryptcustom.py
+import logging, subprocess, re, base64
+from pywidevine.cdm import cdm, deviceconfig
+
+class WvDecrypt(object):
+ WV_SYSTEM_ID = [
+ 237, 239, 139, 169, 121, 214, 74, 206, 163, 200, 39, 220, 213, 29, 33, 237]
+
+ def __init__(self, init_data_b64, cert_data_b64, device):
+ self.init_data_b64 = init_data_b64
+ self.cert_data_b64 = cert_data_b64
+ self.device = device
+ self.cdm = cdm.Cdm()
+
+ def check_pssh(pssh_b64):
+ pssh = base64.b64decode(pssh_b64)
+ if not pssh[12:28] == bytes(self.WV_SYSTEM_ID):
+ new_pssh = bytearray([0, 0, 0])
+ new_pssh.append(32 + len(pssh))
+ new_pssh[4:] = bytearray(b'pssh')
+ new_pssh[8:] = [0, 0, 0, 0]
+ new_pssh[13:] = self.WV_SYSTEM_ID
+ new_pssh[29:] = [0, 0, 0, 0]
+ new_pssh[31] = len(pssh)
+ new_pssh[32:] = pssh
+ return base64.b64encode(new_pssh)
+ else:
+ return pssh_b64
+
+ self.session = self.cdm.open_session(check_pssh(self.init_data_b64), deviceconfig.DeviceConfig(self.device))
+ if self.cert_data_b64:
+ self.cdm.set_service_certificate(self.session, self.cert_data_b64)
+
+ def log_message(self, msg):
+ return '{}'.format(msg)
+
+ def start_process(self):
+ keyswvdecrypt = []
+ try:
+ for key in self.cdm.get_keys(self.session):
+ if key.type == 'CONTENT':
+ keyswvdecrypt.append(self.log_message('{}:{}'.format(key.kid.hex(), key.key.hex())))
+
+ except Exception:
+ return (
+ False, keyswvdecrypt)
+ else:
+ return (
+ True, keyswvdecrypt)
+
+ def get_challenge(self):
+ return self.cdm.get_license_request(self.session)
+
+ def update_license(self, license_b64):
+ self.cdm.provide_license(self.session, license_b64)
+ return True
\ No newline at end of file
diff --git a/pywidevine/downloader/__init__.py b/pywidevine/downloader/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/pywidevine/downloader/tracks.py b/pywidevine/downloader/tracks.py
new file mode 100644
index 0000000..f39657a
--- /dev/null
+++ b/pywidevine/downloader/tracks.py
@@ -0,0 +1,72 @@
+import pywidevine.downloader.wvdownloaderconfig as wvdl_cfg
+
+class VideoTrack(object):
+ def __init__(self, encrypted, size, id, url, codec, bitrate, width, height):
+ self.encrypted = encrypted
+ self.size = size
+ self.id = id
+ self.url = url
+ self.codec = codec
+ self.bitrate = bitrate
+ self.width = width
+ self.height = height
+
+ def get_type(self):
+ return "video"
+
+ def __repr__(self):
+ return "(encrypted={}, size={}, id={}, url={}, codec={}, bitrate={}, width={}, height={})"\
+ .format(self.encrypted, self.size, self.id, self.url, self.codec, self.bitrate, self.width, self.height)
+
+ def get_filename(self, filename, decrypted=False, fixed=False):
+ if not self.encrypted or decrypted:
+ fn = wvdl_cfg.DECRYPTED_FILENAME
+ else:
+ fn = wvdl_cfg.ENCRYPTED_FILENAME
+ if fixed:
+ fn = fn + '_fixed.mkv'
+ return fn.format(filename=filename, track_type="video", track_no=self.id)
+
+
+
+class AudioTrack(object):
+ def __init__(self, encrypted, size, id, url, codec, bitrate, language):
+ self.encrypted = encrypted
+ self.size = size
+ self.id = id
+ self.url = url
+ self.codec = codec
+ self.bitrate = bitrate
+ self.language = language
+
+ def get_type(self):
+ return "audio"
+
+ def __repr__(self):
+ return "(encrypted={}, size={}, id={}, url={}, codec={}, bitrate={})"\
+ .format(self.encrypted, self.size, self.id, self.url, self.codec, self.bitrate)
+
+ def get_filename(self, filename, decrypted=False, fixed=False):
+ if not self.encrypted or decrypted:
+ fn = wvdl_cfg.DECRYPTED_FILENAME
+ else:
+ fn = wvdl_cfg.ENCRYPTED_FILENAME
+ if fixed:
+ fn = fn + '_fixed.mka'
+ return fn.format(filename=filename, track_type="audio", track_no=self.id)
+
+
+class SubtitleTrack(object):
+ def __init__(self, id, name, language_code, default, url, type):
+ self.id = id
+ self.name = name
+ self.language_code = language_code
+ self.url = url
+ self.type = type
+ self.default = default
+
+ def __repr__(self):
+ return "(id={}, name={}, language_code={}, url={}, type={})".format(self.id, self.name, self.language_code, self.url, self.type)
+
+ def get_filename(self, filename, subtitle_format):
+ return wvdl_cfg.SUBTITLES_FILENAME.format(filename=filename, language_code=self.language_code, id=self.id, subtitle_type=subtitle_format)
diff --git a/pywidevine/downloader/wvdownloader.py b/pywidevine/downloader/wvdownloader.py
new file mode 100644
index 0000000..1deffc8
--- /dev/null
+++ b/pywidevine/downloader/wvdownloader.py
@@ -0,0 +1,199 @@
+
+import threading
+import os
+import requests
+import math
+import shutil
+import pathlib, sys, subprocess
+
+from requests.sessions import session
+from tqdm import tqdm
+from queue import Queue
+
+dlthreads = 24
+
+class WvDownloader(object):
+ def __init__(self, config):
+ self.xml = config.xml
+ self.output_file = config.output_file
+ self.tqdm_mode = config.tqdm_mode
+ self.cookies = config.cookies
+ self.config = config
+
+ def download_track(self, aria_input, file_name):
+ aria_command = ['aria2c', '-i', aria_input,
+ '--enable-color=false',
+ '--allow-overwrite=true',
+ '--summary-interval=0',
+ '--download-result=hide',
+ '--async-dns=false',
+ '--check-certificate=false',
+ '--auto-file-renaming=false',
+ '--file-allocation=none',
+ '--console-log-level=warn',
+ '-x16', '-j16', '-s16']
+ if sys.version_info >= (3, 5):
+ aria_out = subprocess.run(aria_command)
+ aria_out.check_returncode()
+
+ source_files = pathlib.Path(temp_folder).rglob(r'./*.mp4')
+ with open(file_name, mode='wb') as (destination):
+ for file in source_files:
+ with open(file, mode='rb') as (source):
+ shutil.copyfileobj(source, destination)
+ if os.path.exists(temp_folder):
+ shutil.rmtree(temp_folder)
+ os.remove(aria_input)
+ print('\nDone!')
+
+ def process_url_templace(self, template, representation_id, bandwidth, time, number):
+ if representation_id is not None: result = template.replace('$RepresentationID$', representation_id)
+ if number is not None:
+ nstart = result.find('$Number')
+ if nstart >= 0:
+ nend = result.find('$', nstart+1)
+ if nend >= 0:
+ var = result[nstart+1 : nend]
+ if 'Number%' in var:
+ value = var[6:] % (int(number))
+ else:
+ value = number
+ result = result.replace('$'+var+'$', value)
+ if bandwidth is not None: result = result.replace('$Bandwidth$', bandwidth)
+ if time is not None: result = result.replace('$Time$', time)
+ result = result.replace('$$', '$').replace('../', '')
+ return result
+
+ def generate_segments(self):
+ segs = self.get_representation_number()
+ return self.get_segments(segs)
+
+ def get_segments(self, segment_level):
+ media = segment_level['@media']
+ current_number = 1
+ current_time = 0
+ for seg in self.force_segment_level(segment_level):
+ if '@t' in seg:
+ current_time = seg['@t']
+ for _ in range(int(seg.get('@r', 0)) + 1):
+ url = self.process_url_templace(media, representation_id=self.config.format_id, bandwidth=self.config.bandwidth, time=str(current_time), number=str(current_number))
+ current_number += 1
+ current_time += int(seg['@d'])
+ yield url
+
+ def force_segment_level(self, segment_level):
+ if isinstance(segment_level['SegmentTimeline']['S'], list):
+ segment_level = segment_level['SegmentTimeline']['S']
+ else:
+ segment_level = [segment_level['SegmentTimeline']['S']]
+ return segment_level
+
+ def get_representation_number(self):
+ x = []
+ for [idx, item] in enumerate(self.xml['MPD']['Period']['AdaptationSet']):
+ try:
+ if self.config.file_type in item.get('@mimeType'):
+ x = idx
+ except TypeError:
+ if self.config.file_type in item.get('@contentType'):
+ x = idx
+
+ y = []
+ if 'video' in self.config.file_type:
+ for [number, rep] in enumerate(self.xml['MPD']['Period']['AdaptationSet'][x]['Representation']):
+ if self.config.format_id == rep.get('@id'):
+ y = number
+
+ mpd = self.xml['MPD']['Period']
+ try:
+ segment_level = mpd['AdaptationSet'][x]['SegmentTemplate']
+ except TypeError:
+ segment_level = mpd['AdaptationSet'][x]['SegmentTemplate']
+
+ return segment_level
+
+ def run(self):
+ segment_list = self.generate_segments()
+ urls = []
+ for seg_url in segment_list:
+ url = self.config.base_url + '/' + seg_url
+ urls.append(url)
+
+ print('\n' + self.output_file)
+ # download por aria2c
+ if not self.tqdm_mode:
+ global temp_folder
+ aria2c_infile = 'aria2c_infile.txt'
+ if os.path.isfile(aria2c_infile):
+ os.remove(aria2c_infile)
+ temp_folder = self.output_file.replace('.mp4', '')
+ if os.path.exists(temp_folder):
+ shutil.rmtree(temp_folder)
+ if not os.path.exists(temp_folder):
+ os.makedirs(temp_folder)
+
+ if len(urls) > 1:
+ num_segments = int(math.log10(len(urls))) + 1
+ with open(aria2c_infile, 'a', encoding='utf8') as (file):
+ for (i, url) in enumerate(urls):
+ file.write(f'{url}\n')
+ file.write(f'\tout={temp_folder}.{i:0{num_segments}d}.mp4\n')
+ file.write(f'\tdir={temp_folder}\n')
+ file.flush()
+ self.download_track(aria2c_infile, self.output_file)
+ else:
+ # download por thread
+ work_q = Queue()
+ result_q = Queue()
+
+ pool = [WorkerThread(work_q=work_q, result_q=result_q, cookies=self.cookies) for i in range(dlthreads)]
+ for thread in pool:
+ thread.start()
+
+ work_count = 0
+ for seg_url in urls:
+ url = seg_url
+ work_q.put((work_count, url, self.cookies))
+ work_count += 1
+ results = []
+
+ for _ in tqdm(range(work_count)):
+ results.append(result_q.get())
+ outfile = open(self.output_file , 'wb+')
+ sortedr = sorted(results, key=lambda v: v[0])
+ for r in sortedr:
+ outfile.write(r[1])
+ outfile.close()
+ del results
+ print('Done!')
+
+class Downloader:
+ def __init__(self):
+ self.session = requests.Session()
+
+ def DownloadSegment(self, url, cookies):
+ resp = self.session.get(url, cookies=cookies, stream=True)
+ resp.raw.decode_content = True
+ data = resp.raw.read()
+ return data
+
+class WorkerThread(threading.Thread):
+ def __init__(self, work_q, result_q, cookies):
+ super(WorkerThread, self).__init__()
+ self.work_q = work_q
+ self.result_q = result_q
+ self.cookies = cookies
+ self.stoprequest = threading.Event()
+ self.downloader = Downloader()
+
+ def run(self):
+ while not self.stoprequest.isSet():
+ try:
+ (seq, url, cookies) = self.work_q.get(True, 0.05)
+ self.result_q.put((seq, self.downloader.DownloadSegment(url, cookies)))
+ except:
+ continue
+
+ def join(self, timeout=None):
+ self.stoprequest.set()
+ super(WorkerThread, self).join(timeout)
diff --git a/pywidevine/downloader/wvdownloaderconfig.py b/pywidevine/downloader/wvdownloaderconfig.py
new file mode 100644
index 0000000..6e7a481
--- /dev/null
+++ b/pywidevine/downloader/wvdownloaderconfig.py
@@ -0,0 +1,14 @@
+import re
+import os
+import platform
+
+class WvDownloaderConfig(object):
+ def __init__(self, xml, base_url, output_file, format_id, bandwidth, cookies, file_type, tqdm_mode):
+ self.xml = xml
+ self.output_file = output_file
+ self.base_url = base_url
+ self.format_id = format_id
+ self.bandwidth = bandwidth
+ self.cookies = cookies
+ self.file_type = file_type
+ self.tqdm_mode = tqdm_mode
diff --git a/pywidevine/muxer/muxer.py b/pywidevine/muxer/muxer.py
new file mode 100644
index 0000000..fe2aa74
--- /dev/null
+++ b/pywidevine/muxer/muxer.py
@@ -0,0 +1,271 @@
+# -*- coding: utf-8 -*-
+import os
+import subprocess
+
+class Muxer(object):
+ def __init__(self, CurrentName, SeasonFolder, CurrentHeigh, Type, mkvmergeexe):
+ self.CurrentName = CurrentName
+ self.SeasonFolder = SeasonFolder
+ self.CurrentHeigh = CurrentHeigh
+ self.Type = Type
+ self.mkvmergeexe = mkvmergeexe
+
+ def mkvmerge_muxer(self, lang):
+ VideoInputNoExist = False
+ if os.path.isfile(self.CurrentName + ' [' + self.CurrentHeigh + 'p] [CBR].h264'):
+ VideoInputName = self.CurrentName + ' [' + self.CurrentHeigh + 'p] [CBR].h264'
+ if self.Type == "show":
+ VideoOutputName = os.path.join(self.SeasonFolder, self.CurrentName + ' [' + self.CurrentHeigh + 'p] [CBR].mkv')
+ else:
+ VideoOutputName = self.CurrentName + ' [' + self.CurrentHeigh + 'p] [CBR].mkv'
+
+ if os.path.isfile(self.CurrentName + ' [' + self.CurrentHeigh + 'p].h264'):
+ VideoInputName = self.CurrentName + ' [' + self.CurrentHeigh + 'p].h264'
+ if self.Type == "show":
+ VideoOutputName = os.path.join(self.SeasonFolder, self.CurrentName + ' [' + self.CurrentHeigh + 'p].mkv')
+ else:
+ VideoOutputName = self.CurrentName + ' [' + self.CurrentHeigh + 'p].mkv'
+
+ elif os.path.isfile(self.CurrentName + ' [' + self.CurrentHeigh + 'p] [HEVC].mp4'):
+ VideoInputName = self.CurrentName + ' [' + self.CurrentHeigh + 'p] [HEVC].mp4'
+ if self.Type == "show":
+ VideoOutputName = os.path.join(self.SeasonFolder, self.CurrentName + ' [' + self.CurrentHeigh + 'p] [HEVC].mkv')
+ else:
+ VideoOutputName = self.CurrentName + ' [' + self.CurrentHeigh + 'p] [HEVC].mkv'
+
+ elif os.path.isfile(self.CurrentName + ' [' + self.CurrentHeigh + 'p] [HEVC].h265'):
+ VideoInputName = self.CurrentName + ' [' + self.CurrentHeigh + 'p] [HEVC].h265'
+ if self.Type == "show":
+ VideoOutputName = os.path.join(self.SeasonFolder, self.CurrentName + ' [' + self.CurrentHeigh + 'p] [HEVC].mkv')
+ else:
+ VideoOutputName = self.CurrentName + ' [' + self.CurrentHeigh + 'p] [HEVC].mkv'
+
+ elif os.path.isfile(self.CurrentName + ' [' + self.CurrentHeigh + 'p] [VP9].mp4'):
+ VideoInputName = self.CurrentName + ' [' + self.CurrentHeigh + 'p] [VP9].mp4'
+ if self.Type == "show":
+ VideoOutputName = os.path.join(self.SeasonFolder, self.CurrentName + ' [' + self.CurrentHeigh + 'p] [VP9].mkv')
+ else:
+ VideoOutputName = self.CurrentName + ' [' + self.CurrentHeigh + 'p] [VP9].mkv'
+
+ elif os.path.isfile(self.CurrentName + ' [' + self.CurrentHeigh + 'p] [VP9].vp9'):
+ VideoInputName = self.CurrentName + ' [' + self.CurrentHeigh + 'p] [VP9].vp9'
+ if self.Type == "show":
+ VideoOutputName = os.path.join(self.SeasonFolder, self.CurrentName + ' [' + self.CurrentHeigh + 'p] [VP9].mkv')
+ else:
+ VideoOutputName = self.CurrentName + ' [' + self.CurrentHeigh + 'p] [VP9].mkv'
+
+ elif os.path.isfile(self.CurrentName + ' [' + self.CurrentHeigh + 'p] [HDR].mp4'):
+ VideoInputName = self.CurrentName + ' [' + self.CurrentHeigh + 'p] [HDR].mp4'
+ if self.Type == "show":
+ VideoOutputName = os.path.join(self.SeasonFolder, self.CurrentName + ' [' + self.CurrentHeigh + 'p] [HDR].mkv')
+ else:
+ VideoOutputName = self.CurrentName + ' [' + self.CurrentHeigh + 'p] [HDR].mkv'
+
+ elif os.path.isfile(self.CurrentName + ' [' + self.CurrentHeigh + 'p] [HDR].h265'):
+ VideoInputName = self.CurrentName + ' [' + self.CurrentHeigh + 'p] [HDR].h265'
+ if self.Type == "show":
+ VideoOutputName = os.path.join(self.SeasonFolder, self.CurrentName + ' [' + self.CurrentHeigh + 'p] [HDR].mkv')
+ else:
+ VideoOutputName = self.CurrentName + ' [' + self.CurrentHeigh + 'p] [HDR].mkv'
+
+ elif os.path.isfile(self.CurrentName + ' [' + self.CurrentHeigh + 'p] [AVC HIGH].mp4'):
+ VideoInputName = self.CurrentName + ' [' + self.CurrentHeigh + 'p] [AVC HIGH].mp4'
+ if self.Type == "show":
+ VideoOutputName = os.path.join(self.SeasonFolder, self.CurrentName + ' [' + self.CurrentHeigh + 'p] [AVC HIGH].mkv')
+ else:
+ VideoOutputName = self.CurrentName + ' [' + self.CurrentHeigh + 'p] [AVC HIGH].mkv'
+
+ elif os.path.isfile(self.CurrentName + ' [' + self.CurrentHeigh + 'p] [AVC HIGH].h264'):
+ VideoInputName = self.CurrentName + ' [' + self.CurrentHeigh + 'p] [AVC HIGH].h264'
+ if self.Type == "show":
+ VideoOutputName = os.path.join(self.SeasonFolder, self.CurrentName + ' [' + self.CurrentHeigh + 'p] [AVC HIGH].mkv')
+ else:
+ VideoOutputName = self.CurrentName + ' [' + self.CurrentHeigh + 'p] [AVC HIGH].mkv'
+
+ elif os.path.isfile(self.CurrentName + ' [' + self.CurrentHeigh + 'p] [CBR].mp4'):
+ VideoInputName = self.CurrentName + ' [' + self.CurrentHeigh + 'p] [CBR].mp4'
+ if self.Type == "show":
+ VideoOutputName = os.path.join(self.SeasonFolder, self.CurrentName + ' [' + self.CurrentHeigh + 'p] [CBR].mkv')
+ else:
+ VideoOutputName = self.CurrentName + ' [' + self.CurrentHeigh + 'p] [CBR].mkv'
+
+ elif os.path.isfile(self.CurrentName + ' [' + self.CurrentHeigh + 'p].mp4'):
+ VideoInputName = self.CurrentName + ' [' + self.CurrentHeigh + 'p].mp4'
+ if self.Type == "show":
+ VideoOutputName = os.path.join(self.SeasonFolder, self.CurrentName + ' [' + self.CurrentHeigh + 'p].mkv')
+ else:
+ VideoOutputName = self.CurrentName + ' [' + self.CurrentHeigh + 'p].mkv'
+ else:
+ VideoInputNoExist = True
+
+ if VideoInputNoExist == False:
+ AudioExtensionsList=[
+ ".ac3",
+ ".mka",
+ ".eac3",
+ ".m4a",
+ ".dts",
+ ".mp3",
+ ".aac"
+ ]
+
+ SubsExtensionsList= [
+ ".srt",
+ ".ass",
+ ]
+
+ if lang == "English":
+ language_tag = "English"
+
+ if language_tag == "English":
+ subs_forced = 'Forced'
+ subs_sdh = 'SDH'
+ #["en", "en", "eng", "English", "yes", "yes"]
+ #[audio_language, subs_language, language_id, language_name, audio_default, subs_default]
+ LanguageList = [
+ ["es-la", "es-la", "spa", "Spanish", "yes", "no"],
+ ["en", "en", "eng", "English", "no", "no"],
+ ["pt-br", "pt-br", "por", "Brazilian Portuguese", "no", "no"],
+ ["es", "es", "spa", "Castilian", "no", "no"],
+ ["cat", "cat", "cat", "Catalan", "no", "no"],
+ ["eu", "eu", "baq", "Basque", "no", "no"],
+ ["fr", "fr", "fre", "French", "no", "no"],
+ ["fr-bg", "fr-bg", "fre", "French (Belgium)", "no", "no"],
+ ["fr-lu", "fr-lu", "fre", "French (Luxembourg)", "no", "no"],
+ ["fr-ca", "fr-ca", "fre", "French (Canada)", "no", "no"],
+ ["de", "de", "ger", "German", "no", "no"],
+ ["it", "it", "ita", "Italian", "no", "no"],
+ ["pl", "pl", "pol", "Polish", "no", "no"],
+ ["tr", "tr", "tur", "Turkish", "no", "no"],
+ ["hy", "hy", "arm", "Armenian", "no", "no"],
+ ["sv", "sv", "swe", "Swedish", "no", "no"],
+ ["da", "da", "dan", "Danish", "no", "no"],
+ ["fi", "fi", "fin", "Finnish", "no", "no"],
+ ["nl", "nl", "dut", "Dutch", "no", "no"],
+ ["nl-be", "nl-be", "dut", "Flemish", "no", "no"],
+ ["no", "no", "nor", "Norwegian", "no", "no"],
+ ["lv", "lv", "lav", "Latvian", "no", "no"],
+ ["is", "is", "ice", "Icelandic", "no", "no"],
+ ["ru", "ru", "rus", "Russian", "no", "no"],
+ ["uk", "uk", "ukr", "Ukrainian", "no", "no"],
+ ["hu", "hu", "hun", "Hungarian", "no", "no"],
+ ["bg", "bg", "bul", "Bulgarian", "no", "no"],
+ ["hr", "hr", "hrv", "Croatian", "no", "no"],
+ ["lt", "lt", "lit", "Lithuanian", "no", "no"],
+ ["et", "et", "est", "Estonian", "no", "no"],
+ ["el", "el", "gre", "Greek", "no", "no"],
+ ["he", "he", "heb", "Hebrew", "no", "no"],
+ ["ar", "ar", "ara", "Arabic", "no", "no"],
+ ["fa", "fa", "per", "Persian", "no", "no"],
+ ["ro", "ro", "rum", "Romanian", "no", "no"],
+ ["sr", "sr", "srp", "Serbian", "no", "no"],
+ ["cs", "cs", "cze", "Czech", "no", "no"],
+ ["sk", "sk", "slo", "Slovak", "no", "no"],
+ ["sl", "sl", "slv", "Slovenian", "no", "no"],
+ ["sq", "sq", "alb", "Albanian", "no", "no"],
+ ["bs", "bs", "bos", "Bosnian", "no", "no"],
+ ["mk", "mk", "mac", "Macedonian", "no", "no"],
+ ["hi", "hi", "hin", "Hindi", "no", "no"],
+ ["bn", "bn", "ben", "Bengali", "no", "no"],
+ ["ur", "ur", "urd", "Urdu", "no", "no"],
+ ["pa", "pa", "pan", "Punjabi", "no", "no"],
+ ["ta", "ta", "tam", "Tamil", "no", "no"],
+ ["te", "te", "tel", "Telugu", "no", "no"],
+ ["mr", "mr", "mar", "Marathi", "no", "no"],
+ ["kn", "kn", "kan", "Kannada (India)", "no", "no"],
+ ["gu", "gu", "guj", "Gujarati", "no", "no"],
+ ["ml", "ml", "mal", "Malayalam", "no", "no"],
+ ["si", "si", "sin", "Sinhala", "no", "no"],
+ ["as", "as", "asm", "Assamese", "no", "no"],
+ ["mni", "mni", "mni", "Manipuri", "no", "no"],
+ ["tl", "tl", "tgl", "Tagalog", "no", "no"],
+ ["id", "id", "ind", "Indonesian", "no", "no"],
+ ["ms", "ms", "may", "Malay", "no", "no"],
+ ["fil", "fil", "fil", "Filipino", "no", "no"],
+ ["vi", "vi", "vie", "Vietnamese", "no", "no"],
+ ["th", "th", "tha", "Thai", "no", "no"],
+ ["km", "km", "khm", "Khmer", "no", "no"],
+ ["ko", "ko", "kor", "Korean", "no", "no"],
+ ["zh", "zh", "chi", "Mandarin", "no", "no"],
+ ["yue", "yue", "chi", "Cantonese", "no", "no"],
+ ["zh-hans", "zh-hans", "chi", "Chinese (Simplified)", "no", "no"],
+ ["zh-hant", "zh-hant", "chi", "Chinese (Traditional)", "no", "no"],
+ ["zh-hk", "zh-hk", "chi", "Chinese (Simplified)", "no", "no"],
+ ["zh-tw", "zh-tw", "chi", "Chinese (Traditional)", "no", "no"],
+ ["zh-sg", "zh-sg", "chi", "Chinese (Singapore)", "no", "no"],
+ ["ja", "ja", "jpn", "Japanese", "no", "no"],
+ ["tlh", "tlh", "tlh", "Klingon", "no", "no"],
+ ["zxx", "zxx", "zxx", "No Dialogue", "no", "no"]
+ ]
+
+ ALLAUDIOS = []
+ default_active_audio = False
+ for audio_language, subs_language, language_id, language_name, audio_default, subs_default in LanguageList:
+ for AudioExtension in AudioExtensionsList:
+ if os.path.isfile(self.CurrentName + ' (' + audio_language + ')' + AudioExtension):
+ if default_active_audio == True: audio_default = "no"
+ ALLAUDIOS = ALLAUDIOS + ['--language', '0:' + language_id, '--track-name', '0:' + language_name, '--default-track', '0:' + audio_default, '(', self.CurrentName + ' (' + audio_language + ')' + AudioExtension, ')']
+ if audio_default == "yes": default_active_audio = True
+
+ for audio_language, subs_language, language_id, language_name, audio_default, subs_default in LanguageList:
+ for AudioExtension in AudioExtensionsList:
+ if os.path.isfile(self.CurrentName + ' (' + audio_language + '-ad)' + AudioExtension):
+ if default_active_audio == True: audio_default = "no"
+ ALLAUDIOS = ALLAUDIOS + ['--language', '0:' + language_id, '--track-name', '0:' + language_name + ' (Audio Description)', '--default-track', '0:no', '(', self.CurrentName + ' (' + audio_language + '-ad)' + AudioExtension, ')']
+ if audio_default == "yes": default_active_audio = True
+
+ OnlyOneLanguage = False
+ if len(ALLAUDIOS) == 9:
+ OnlyOneLanguage = True
+
+ elif len(ALLAUDIOS) == 18:
+ if ALLAUDIOS[1] == ALLAUDIOS[10]:
+ if '-ad' in ALLAUDIOS[7] or '-ad' in ALLAUDIOS[16]:
+ OnlyOneLanguage = True
+ else:
+ OnlyOneLanguage = False
+
+
+ ALLSUBS = []
+ default_active_subs = False
+ for audio_language, subs_language, language_id, language_name, audio_default, subs_default in LanguageList:
+ for SubsExtension in SubsExtensionsList:
+ if os.path.isfile(self.CurrentName + ' (' + subs_language + '-forced)' + SubsExtension):
+ if subs_default == "yes": default_active_subs = True
+ ALLSUBS = ALLSUBS + ['--language', '0:' + language_id, '--track-name', '0:' + subs_forced, '--forced-track', '0:yes', '--default-track', '0:' + subs_default, '--compression', '0:none', '(', self.CurrentName + ' (' + subs_language + '-forced)' + SubsExtension, ')']
+
+ if OnlyOneLanguage == True:
+ if default_active_subs == True: subs_default = "no"
+ if os.path.isfile(self.CurrentName + ' (' + subs_language + ')' + SubsExtension):
+ ALLSUBS = ALLSUBS + ['--language', '0:' + language_id, '--forced-track', '0:no', '--default-track', '0:' + subs_default, '--compression', '0:none', '(', self.CurrentName + ' (' + subs_language + ')' + SubsExtension, ')']
+
+ else:
+ if os.path.isfile(self.CurrentName + ' (' + subs_language + ')' + SubsExtension):
+ ALLSUBS = ALLSUBS + ['--language', '0:' + language_id, '--forced-track', '0:no', '--default-track', '0:no', '--compression', '0:none', '(', self.CurrentName + ' (' + subs_language + ')' + SubsExtension, ')']
+
+ if os.path.isfile(self.CurrentName + ' (' + subs_language + '-sdh)' + SubsExtension):
+ ALLSUBS = ALLSUBS + ['--language', '0:' + language_id, '--track-name', '0:' + subs_sdh, '--forced-track', '0:no', '--default-track', '0:no', '--compression', '0:none', '(', self.CurrentName + ' (' + subs_language + '-sdh)' + SubsExtension, ')']
+
+ #(Chapters)
+ if os.path.isfile(self.CurrentName+' Chapters.txt'):
+ CHAPTERS=['--chapter-charset', 'UTF-8', '--chapters', self.CurrentName + ' Chapters.txt']
+ else:
+ CHAPTERS=[]
+
+
+ mkvmerge_command_video = [self.mkvmergeexe,
+ '-q',
+ '--output',
+ VideoOutputName,
+ '--language',
+ '0:und',
+ '--default-track',
+ '0:yes',
+ '(',
+ VideoInputName,
+ ')']
+
+
+
+ mkvmerge_command = mkvmerge_command_video + ALLAUDIOS + ALLSUBS + CHAPTERS
+ mkvmerge_process = subprocess.run(mkvmerge_command)
diff --git a/requeriments.txt b/requeriments.txt
new file mode 100644
index 0000000..971086f
--- /dev/null
+++ b/requeriments.txt
@@ -0,0 +1,28 @@
+astroid>=1.5.3
+beautifulsoup4>=4.4.1
+certifi>=2017.4.17
+chardet>=3.0.3
+colorama>=0.3.9
+cssutils>=1.0.2
+dnspython>=1.15.0
+future>=0.16.0
+idna>=2.5
+isort>=4.2.14
+lazy-object-proxy>=1.3.1
+lxml>=4.2.4
+mccabe>=0.6.1
+pathvalidate>=0.22.0
+protobuf>=3.0.0b2
+pycountry>=18.5.26
+pycryptodomex>=3.4.6
+pymsl>=1.2
+pylint>=1.7.1
+pysubs2>=0.2.1
+requests>=2.17.3
+six>=1.10.0
+tqdm>=4.14.0
+unidecode>=1.0.23
+urllib3>=1.21.1
+win10toast>=0.9; sys_platform == 'win32'
+wrapt>=1.10.10
+xmltodict>=0.11.0