HLS with Widevine for Android

As of the version of 2.6.0, ExoPlayer started supporting Widevine + HLS playback. WideVine is the one of the DRM schemes defined by Google. There are other schemes like FairPlay by Apple, PlayReady by Microsoft too.

The image shown below is how Widevine contents are delivered and played on a device. A key is stored on a license server, and the player gets the key from a license server to play. As you see in the picture, player has to have a Widevine CDM embedded on the device to decrypt the content.

ecosystem

Widevine for Android

To play Widevine contents on ExoPlayer, the Android OS needs to be API level +19 for cenc mode, +25 for cbcs mode.

support format for HLS

protection scheme

You might have wondered what are cenc mode and cbcs mode. Those are about how contents are encrypted and there are actually four types of protection scheme.

  1. cenc mode: AES-CTR mode and Full-Sample encryption
  2. cbc1 mode: AES-CBC mode and Full-Sample encryption
  3. cens mode: AES-CTR mode and Sub-Sample encryption
  4. cbcs mode: AES-CBC mode and Sub-Sample encryption

CTR and CBC are AES encryption mode and Full-Sample encryption means video samples are all encrypted with the specified AES mode, on the other hand Sub-Sample encryption encrypts the partial of each sample. It seems like ExoPlayer only support cenc mode and cbcs mode for now.

HLS Playlist

The easiest way to create a content of HLS +fMp4 + Widevine is to use shaka-packager. I wrote a post about making Widevine contents, so please check it out if you are interested.

Anyways, a HLS playlist created for a Widevine content would be like this below.

HLS playlist

video/init.mp4 is an initialization file for the initialization, it would be used to keep track of the position of the media files, and also contains information about the track.

video/1.mp4 , video/2.mp4 , video/3.mp4 … are video files, but you might have noticed that EXT-X-KEY is in between video/1.mp4 and video/2.mp4 . The reason why video/1.mp4 is before EXT-X-KEY is because video/1.mp4 is not encrypted and video files after that are all encrypted with Widevine. Media segments are encrypted with sample-AES, so it is possible not to encrypt all the content, and the first content may or may not be encrypted.

Let’s look at the EXT-X-KEY tag which shows how the segments are encrypted.

METHOD : This indicates the encryption method. For a Widevine content, it would be SAMPLE-AES-CTR , which means cenc mode, or SAMPLE-AES , which is cbcs mode.

KEYFORMATVERSION : This defines key format version, and the value would be 1.

KEYID : This is a default key identifier that uniquely identifies the key to decrypt samples.

KEYFORMAT : This describes the UUID for Widevine, which is known as SystemID. Each DRM scheme has their own UUID, and for Widevine the value would be edef8ba9–79d6–4ace-a3c8–27dcd51d21ed. If you are interested in what others are, this site would be helpful for you

URI : This is a base64 encoded PSSH box. PSSH box is the one of the boxes defined for mp4 file, and the initialization file like init.mp4 has the same information as well.

I hope this could help someone try to play widevine contents on Android.

thanks.

References

Widevine DRM for HLS: https://storage.googleapis.com/wvdocs/Widevine_DRM_HLS.pdf

Getting Started with Widevine DRM: https://storage.googleapis.com/wvdocs/Widevine_DRM_Getting_Started.pdf

Common Encryption API for Widevine DRM: https://storage.googleapis.com/wvdocs/Widevine_DRM_Encryption_API.pdf