使用 Widevine DRM
隨著 Android 越來越普及, DRM 的需求也越來越大。 所以 Google 原生支援的 Widevine DRM 的使用率也越來越高。 這邊就稍微記錄一下如果要播放 Widevine 影片的話,要怎麼取得 Widevine DRM 的 access right 以及如何播放。
基本上播放的流程分為兩個部分
- 利用 VideoView 或任何 SurfaceView 播放串流或是影片檔
- 透過 DrmManagerClient 向 DRM server 取得 Right
特別注意的是,這兩個流程分別是 獨立進行 的,雖然說播放的時候還是會有先後關係(需要先取得 Right 然後才能 decode),但是在執行上是可以分開進行的。(比方說你還在取得串流URL或是準備 Player 相關的元件時,就可以先在背景先去取得 DRM right)
第一個部分利用 VideoView 播放串流/影片檔
這部份跟一般的 MediaPlayer 流程是一模一樣的。
mVideoView = (VideoView) findViewById(R.id.myplaysurface); Uri uri = Uri.parse(videoPath); mVideoView.setVideoURI(uri); mController = new MediaController(this, false); mVideoView.setMediaController(mController); mVideoView.requestFocus(); mVideoView.start();
第二部分則是透過 Android 內建的 DrmManagerClient 取得影片的 Right
首先要先建立 DrmManagerClient 的實體
DrmManagerClient mDrmManagerClient = new DrmManagerClient(context);
mDrmManagerClient.setOnEventListener(mEventListener);
mDrmManagerClient.setOnErrorListener(mErrorListener);
mDrmManagerClient.setOnInfoListener(mInfoListener);
接著註冊並檢查目前的機器是否支援 Widevine
DrmInfoRequest drmInfoRequest = new DrmInfoRequest(DrmInfoRequest.TYPE_REGISTRATION_INFO, "video/wvm"); drmInfoRequest.put("WVPortalKey", mPortalKey); DrmInfo drmInfo = mDrmManagerClient.acquireDrmInfo(drmInfoRequest); int drmInfoRequestStatusKey = Integer.parseInt((String)info.get("WVDrmInfoRequestStatusKey")); switch(drmInfoRequestStatusKey){ case 0: // Device has Hardware Widevine Key (L1) case 1: // Device has no Widevine Key case 2: // Device has Software Widevine Key (L3) }
其中第二行 drmInfoRequest.put("WVPortalKey", mPortalKey)
這部份後面再一起解釋。
透過 acquireDrmInfo
取得的 drmInfoRequestStatusKey 會有3種狀態(0/1/2),可以透過這個值得知目前機器是否有支援 Widevine 以及是什麼等級。
再來如果確認可以播放後,就可以再次透過 DrmManagerClient 來取得 Right
DrmInfoRequest drmRightRequest = new DrmInfoRequest(DrmInfoRequest.TYPE_RIGHTS_ACQUISITION_INFO, "video/wvm"); drmRightRequest.put("WVDRMServerKey", drmServerUri); drmRightRequest.put("WVAssetURIKey", assetUri); drmRightRequest.put("WVDeviceIDKey", deviceId); drmRightRequest.put("WVPortalKey", portalId); drmRightRequest.put("WVCAUserDataKey", userData); int result = mDrmManagerClient.acquireRights(drmRightRequest); if(result == 0) // Success else // Failure
如果回傳的 result 是 0 (DrmManagerClient.ERROR_NONE)的話就表示成功取得 Right 了。 接下來 VideoView 在播放影片時,系統就會自動透過這個 Right 去做解密的動作。
最後解釋一下在建立 DrmInfoRequest
時要放入的參數。
基本上這些參數是發送給 DRM Server 看的,所以實際上要放什麼東西是要看 DRM Server 的實作方式。
但是 Widevine 常見的參數如下
註冊時會用到
drmInfoRequest.put("WVPortalKey", mPortalKey)
在取得 Right 的時候會用到
drmRightRequest.put("WVDRMServerKey", drmServerUri); drmRightRequest.put("WVAssetURIKey", assetUri); drmRightRequest.put("WVDeviceIDKey", deviceId); drmRightRequest.put("WVPortalKey", portalId); drmRightRequest.put("WVCAUserDataKey", userData);
至於裡面的 Value 要塞什麼值,就要看個別 DRM server 的設定了,另外有些 DRM server 可能也會要求在認證或是取得 Right 的時候需要額外的資訊,也會是在這個地方把 Key/Value 放入。
Reference