piątek, 18 maja 2012

Silverlight: System.Exception 6028 przy odtwarzaniu materiału PlayReady DRM

Od niedawna sporo czasu spędzam tworząc rozwiązanie w Silverlight. Nałożyło się to częściowo z wydaniem Silverlight w wersji 5, więc mam wątpliwą przyjemność borykać się z masą problemów jakie pojawiają się w aplikacji po zmianie środowiska do najnowszej wersji. W końcu przecież "to powinno działać".

Jednym z problemów, który był niezwykle uciążliwy, a jego rozwiązanie stwarzało sporo problemów jest wyjątek systemowy o numerze 6028 pojawiający się podczas próby odtworzenia materiału zaszyfrowanego PlayReady DRM. Na szczęście problem ten udało mi się w końcu rozwiązać, a ten post ma pomóc innym programistom Silverlight w pozbyciu się go ze swojej aplikacji odtwarzającej zabezpieczone materiały video.

Może od razu powiem, że niestety ten post na nic się zda użytkownikom takich dostawców jak Netflix czy HBO, których odtwarzacze również potrafią generować ten wyjątek. Po stronie użytkownika jedyna możliwość to usunięcie kontenera PlayReady i cache PlayReady z systemu. Oczywiście zawsze można chłopakom z Netflix czy HBO wysłać link do tego posta i poradzić, aby zapłacili mi nieco grosza za zaimplementowanie tego u nich.

Geneza problemu

Nie jestem specem od PlayReady, więc nie znam pełnej genezy problemu, jednak jest proste wyjaśnienie, które udało mi się znaleźć  w sieci. W kontenerze PlayReady na komputerze klienta znajduje się licencja PR, jednak z jakiś powodów jest ona nieużywalna. Teoretycznie w tej sytuacji należy odpytać serwer o nową licencję. Do Silverlight 4 działo się to automatycznie, jednak od Silverlight 5 obsługa tej sytuacji jest przeniesiona na aplikację kliencką, więc pojawia się zdarzenie MediaFailed z wyjątkiem 6028.

Rozwiązanie problemu

Wszystko sprowadza się więc do wykrycia wyjątku 6028 i ręczne wykonanie zapytania do serwera licencji. Najprostsze jest to o dziwo, gdy korzystamy z własnego License Acquirera. Dlatego, że mamy większą kontrolę nad całym procesem pobierania licencji. Kod jest identyczny, jednak sam proces może być znacznie prostszy. Szczególnie, że pobieranie licencji dla materiału zwykle wiąże się z płatnością i ma swoje ograniczenia.

Gdy mamy już obiekt LicenseAcquirera wystarczy użyć jednej metody:
acq.AcquireLicenseAsync(DrmHeaderBin.ToArray())
Gdzie DRMHeaderBin jest nagłówkiem PlayReady pozyskanym z pliku w postaci tablicy byte. Można też skorzystać z metody przeciążonej dostarczając jako parametr obiekt klasy System.IO.Stream będącym strumieniem pliku, dla którego chcemy pozyskać licencję.

Należy pamiętać, że konieczne jest stworzenie nowego obiektu Acquirera i podpięcie go do media elementu. Jest to niezbędne, ponieważ ten, który wywołał błąd, jest w momencie w stanie nie pozwalającym na wykonanie ponownego zapytania do serwera licencji. Trzeba go odpiąć i pozwolić, aby Garbage Collector go sprzątnął.

Rozwiązanie problemu wyjątku 6028 nie jest trudne z perspektywy implementacji. Problem może być jedynie po stronie biznesowej. W końcu trzeba pobrać nową licencję, co czasem może zaburzyć proces płatności. Bo cóż robić jeśli nie zapiszemy odpowiednich parametrów użytkownika po stronie serwera, a on zapyta o nową licencję po 2h, mimo że poprzednia była wydana na 24h.

Czytaj też:

1 komentarz:

  1. U mnie zawsze miałem problemy gdy chciałem stosować tą wtyczkę. Zawsze wyskakiwał jakiś błąd. Na szczęście dziś mam sklep internetowy i stosuję cashbill.pl/integracja/integracja-platnosci-online-sstore i wszystko chodzi jak należy. Bez programowania i z dobrą instrukcją.

    OdpowiedzUsuń