I haven’t updated the video development article for a long time before for various reasons. I just flew back from China today and updated it over the weekend. However, DRM is rarely used by general developers, and the development of DRM requires close cooperation between the front and back ends, so it can be said that the work of the back ends accounts for most of the work. In fact, the API packaging of the front end of Android DRM is already in place, but there is not much documentation because few people have contacted with it. So this article is just to give you the concept, I will go into a little less detail. Leave a message if you have specific questions,

Today, I will mainly explain the DRM of Android video development. DRM is the abbreviation of Digital Rights Management, which can be understood as copyright protection. It is well known that video and audio piracy is a big problem for publishers, because piracy can directly reduce their profits. What can publishers do about online/offline multimedia content, like on PC or mobile?

For example, TV shows like “Night and Day”, which is very popular on Youku recently,

VIP members can enjoy offline viewing. If this type of file is not copyrighted, or encrypted, then the membership mechanism can easily be disabled (I can sign up for a membership and then copy and paste the file from the SD card and send it online).

So generally speaking, for this kind of premiere content(because our company is also doing TV series, the boss called it so, Chinese translation should be said to be paid content??) , the current file, such as audio or video track, needs to be encrypted, but metadata is not encrypted. Only after the user logs in and authenticates does a key pass to decrypt the video.

So here’s the question

How to do DRM analysis of video on Android platform?

Before we answer that question, let’s take a look at some of the current concepts of DRM on mobile.


1.DRM platform

The DRM platform can be understood as the DRM service provider, which provides a complete set of DRM service solutions from the front end to the back end. This service can be understood as a set of SDK with quotes. Different providers require different data transmission formats on the server side and client side. Depending on the platform, Android devices generally have Widevine as a service (at the framework level) that Was acquired by Google in recent years.

As you can see from the figure above, there are not many mature DRM platforms, and android speakers generally use the first one.


2. How does DRM work?

To put it simply, the DRM backend, the server side, is not that different from most video distribution backend, except that it requires proper encryption of the video data (we won’t discuss encryption algorithms here).

The client needs to obtain the corresponding decryption secret key to decrypt the video content. It is worth noting that in DRM, the secret key is usually called license rather than key. The whole process can be explained by the following flow chart.


3. General DRM platform provider tasks

In this section, we will take a closer look at the tasks of DRM platform providers (of course, platform providers are not required, if the enterprise is capable of creating a complete solution, that’s ok, but you can skip the whole article at 😁).

Take the background of Widevine as an example. After being acquired by Google, Widevine has developed its background into a PASS service similar to cloud platform. Enterprise background can purchase Widevine service, which provides encrypted API group and database capacity to store enterprise video licenses. Decrypting the secret key. As for authentication ah and so on functions are left to the enterprise background to complete. The following diagram provides an overview of Widevine’s DRM process

In the process after the fourth step, the enterprise background will return a URL to request the license from the Widevine database according to the player’s request, and the player can start playing after obtaining the VIDEO URL and license URL.

This is the most naive implementation. The reason is that video services now appear a lot of middlemen… :cat:

Intermediate involves many steps. As a result, many small companies decide not to have to deal with Google Widevine server, but to some video service intermediaries to do this thing, then do the authentication and the intermediaries, it was a lot of trouble, API is relatively simple, disadvantages, of course, is to pay more…

Anyway, the whole point of DRM video on Android is to get the VIDEO URL plus the license to decrypt it. It’s that simple


4. DRM instance code of Android

Said so much, finally to the key of Android, how to write the code ?????

DRM on Android is a pain because the code is completely different for developers using the MediaCodec API group and the native MediaPlayer API. Because there are so few DRM developers, Google’s official documentation is incomplete and hard to understand, and IT took me a long time to figure it out.

Let’s start with the DRM of the MediaCodec API:

4.1 DRM processing of MediaCodec API group

The configure() method needs to pass MediaCrypto if MediaCodec is used for decode

First we need to create a MediaDrm object and call its openSession method, which returns a sessionID identifying the decoding effort.

The second step is to create a MediaCrypto object for the MediaCodec object. It requires a UUID and initdata. The UUID is the Widevine Scheme ID, which can be seen in the Exoplayer source code, in c. Java. InitData is the sessionID mentioned above.

public static final UUID WIDEVINE_UUID = new UUID(0xEDEF8BA979D64ACEL.0xA3C827DCD51D21EDL);

Copy the code

Finally, we need to call the license server, and the reponse is the license we need. At this time, we just need to call the provideKeyResponse() method of MediaDrm, and the video can automatically start playing.

So to sum up, MediaCodec is responsible for decoding, it needs a MediaCrypto object, and it needs a MediaDrm object, and the former takes the sessionId of the latter and the framework finds the license, The latter saves the license downloaded from the server and provides a unique sessionId to the former. Attach pseudocode


public static final UUID WIDEVINE_UUID = new UUID(0xEDEF8BA979D64ACEL.0xA3C827DCD51D21EDL);
/ / get sessionId
MediaDrm mediaDrm = new MediaDrm();
String sessionId = mediaDrm.openSession();
/ / create MediaCrypto
/** sessionId is the key to concatenating MediaDrm and MediaCrypto **/
MediaCrypto ctypto = new MediaCrypto(WIDEVINE_UUID, sessionId)
// Use the CYPTO object for decryption
MediaCodec codec = new MediaCodec("xxxx") codec.configure(.. . ,ctypto)/** The license does not need to be obtained before configure

// Network connection
byte[] license = HttpUrlConnection.connect().......
mediaDrm.provideKeyResponse(xxx,license);

/** All work finished, the video can play normally. * * /


Copy the code

Relatively complete MediaCodec DRM processing documents, so the question is not big, the specific source or can reference ExoPlayer code, and don’t understand StreamingDrmSessionManager. Java inside the entire process.


4.2 DRM Processing of MediaPlayer API Group

The last difficulty comes, which is the DRM processing of the native player MediaPlayer. This part really bothered me for a long time, because there are few online materials and documents are not complete. If you Google MediaPlayer DRM, you get nothing… Nor would you know that MediaCodec handles DRM any differently than MediaPlayer.

But it paid off. After a lot of hard work, I finally found a clue. First look at the official documentation.

Developer.android.com/reference/a…

Here’s the point:

Something so important… Google just casually mentions it in this document.

MediaPlayer does not need to upload any MediaCrypto objects when playing a video. DrmManagerClient handles the decryption automatically.

Pseudo-code is attached below:

  public static final String WV_DRM_SERVER_KEY = "WVDRMServerKey";
    public static final String WV_ASSET_URI_KEY = "WVAssetURIKey";
    public static final String WV_DEVICE_ID_KEY = "WVDeviceIDKey";
    public static final String WV_PORTAL_KEY = "WVPortalKey";


/** call this method to decrypt, execute successfully ok **/

  public  void acquireKey(a){
        DrmInfoRequest drmInfoRequest = createDrmInfoRequest(assetUrl, infoHolder.getDrmLisenceUrl());
        DrmInfo drmInfo = mDrmManager.acquireDrmInfo(drmInfoRequest);
        int rights = mDrmManager.acquireRights(drmInfoRequest);
    }
    
  
  
  /** licenseServerUri is the HTTP Url used to communicate with the license server **/
  
   private DrmInfoRequest createDrmInfoRequest(String assetUri, String licenseServerUri) {
        DrmInfoRequest rightsAcquisitionInfo;
        rightsAcquisitionInfo = new DrmInfoRequest(DrmInfoRequest.TYPE_RIGHTS_ACQUISITION_INFO,
                WIDEVINE_MIME_TYPE);

        if(licenseServerUri ! =null) {
            rightsAcquisitionInfo.put(WV_DRM_SERVER_KEY, licenseServerUri);
        }
        rightsAcquisitionInfo.put(WV_ASSET_URI_KEY, assetUri);
        rightsAcquisitionInfo.put(WV_DEVICE_ID_KEY, mDeviceId);
        rightsAcquisitionInfo.put(WV_PORTAL_KEY, PORTAL_NAME);

        return rightsAcquisitionInfo;
    }


Copy the code

So MediaPlayer’s DRM is much easier to handle violence… Of course DrmManagerClient also has some other operations, such as callback registration etc…

This is the end of this article, because Drm involves a lot of details, as well as the problem of communicating with the background, HERE I just briefly introduce the concept of Drm and the use of different types of API, I will not elaborate on the specific troubles I met in my work, you can directly leave a message or private message ~

Just returned from the new cold, these days dizzy… It’s time to get some more sleep.

Reference documentation

  • Encoding.com
  • MediaDrm
  • DrmManagerClient