Metering the Use of Digital Media Content with Windows Media DRM 10

Andrea Pruneda

Jim Travis

Microsoft Corporation

Updated February 2005

 

Applies to:

   Microsoft® Windows Media® Rights Manager 10 SDK

   Microsoft Windows Media Device Manager 10 SDK

   Microsoft Windows Media DRM 10 for Portable Devices
      Porting Kit

 

Summary: Describes the concept of metering the use of protected digital-media content, and explains how a content provider can use the Microsoft Windows Media DRM 10 platform to implement metering.

Contents

Introduction

How Metering Works

Creating the Metering Certificate

Issuing Licenses for Metered Content

Recording and Reporting Metering Data

   Understanding Transaction IDs

   Reporting Metering Data Using a Computer

   Processing Data from a Metering Challenge

Processing the Metering Response

For More Information

Introduction

Metering is a technology that allows digital-media content providers to count the number of times that protected content is used (for example, played or copied). Metering is not used to track the listening habits of individual users. It is a simple tally of how many times a particular content item is used. Microsoft does not use any metering data at any time.

Using the Microsoft® Windows Media® DRM 10 platform, media players on computers and portable devices can meter content that has been protected with Windows Media digital rights management (DRM) technology. Metering provides several benefits, the greatest of which is to reduce royalty fees for those content provider services that license content and then resell it to their customers. Royalty fees are based on the type of sale, such as whether the sale is a permanent transfer or a metered single play. The cost of a metered single play is much less than the cost of a permanent transfer, therefore metering content is often much more economical for the content provider.

Metering also provides other benefits. By metering content, a content provider can:

  • Determine which content is more popular.
  • Identify and pay the artists whose content is played.
  • Track the number of times an advertisement is viewed.

How Metering Works

Metering requires coordination between the content provider service (the content owner and license issuer), a metering aggregation service (a service that collects and processes metering data), and participating device manufacturers.

The basic process of metering is as follows. The numbered steps correspond to numbers in the following diagram:

  1. The metering aggregation service gives the license issuer a metering certificate, which contains a metering ID and a URL indicating where metering data will be reported. Then, the license issuer includes the metering certificate in the licenses for content that requires metering.

  2. End users acquire this content and receive a license for it through the standard license acquisition process.

  3. A media player on a computer or device opens the content license. The DRM component of the player records metering data, which includes a tally of the number of times the content is used, the type of action performed, and the metering ID.

  4. A metering plug-in or application on the computer or device periodically requests metering data for a specific metering ID. This data is provided in a special format, called a metering challenge. The plug-in or application then sends the data to the corresponding metering aggregation service. If a Web-enabled device is used, the device can send metering data directly to the metering aggregation service.

    The metering challenge can be decrypted only by the metering aggregation service that owns the metering certificate containing this ID.

    For example, suppose a user subscribes to two music services and downloads metered content from each. The metering plug-in for one of the services requests metering data for its metering ID. Only metering data for that ID is gathered, and then it is sent to the corresponding metering aggregation service.

  5. After the metering aggregation service receives and processes the metering data, the service returns a metering response to the metering plug-in or application, prompting the player to clear the metering data that was reported.

    Diagram of the metering process

Creating the Metering Certificate

Requirement: Windows Media Rights Manager 10 SDK

Before it can meter content, the metering aggregation service must first create a metering certificate, which identifies the service and contains a metering ID and a URL. License issuers include this certificate in licenses, and then metering data is collected and organized based on the metering ID.

To create a metering certificate, the metering aggregation service generates a public-private key pair (by using the WMRMKeys.GenerateSigningKeys method of the Windows Media Rights Manager 10 SDK) and sends the public key to Microsoft, along with the URL of the metering aggregation service. Microsoft sends back a signed metering certificate, which contains a metering ID and the URL.

The private key is stored securely by the metering aggregation service and is not shared with Microsoft. Metering data that is reported is encrypted with the public key of the metering certificate, but is decrypted with the private key. Therefore, only the metering aggregation service that owns the metering certificate can access the data.

Issuing Licenses for Metered Content

Requirement: Windows Media Rights Manager 10 SDK

When the license issuer generates a license for metered content, the license issuer includes the metering certificate in the license by using the WMRMLicGen.MeteringCertificate property of the Windows Media Rights Manager 10 SDK. The result is that all actions associated with this license will be recorded along with the metering ID from the metering certificate.

Note   When recording metering data, the player records the license key ID as a way to identify the content. So, to accurately meter individual content items, you must use a unique key ID for each content item. Conversely, you could choose to use the same key ID across multiple content items, which would result in metering data accumulating for all content having the same key ID. For more information about key IDs, see the Windows Media Rights Manager SDK documentation.

The following VBScript example code demonstrates how to create the WMRMLicGen object and specify the metering certificate.

Dim LicenseObj    ' Variable to contain the WMRMLicGen object
Dim MeterCert     ' Variable to contain the metering certificate.
MeterCert = "Metering_Certificate"

' Create the object
Set LicenseObj = Server.CreateObject("WMRMObjs.WMRMLicGen")
' Specify the metering certificate.
LicenseObj.MeteringCertificate = MeterCert

In this example, Metering_Certificate is the string for the metering certificate you want to use.

Recording and Reporting Metering Data

Metering data can originate from two sources: a computer data store and a portable device data store. A computer data store contains metering data about protected digital media content the user played on his or her computer. A portable device data store contains metering data about digital media content that the user played using a portable device.

Content can be metered only if the end user uses a media player that supports metering. A media player on a computer must be based on the Windows Media Format 9.5 SDK, such as Windows Media Player 10. A device must be based on the Windows Media DRM 10 for Portable Devices Porting Kit. Metering data is then recorded automatically by the DRM component of the player.

When a player uses content that has a license that requires metering, the count for the action just performed is incremented in the metering section of its data store. The key ID (which is used to identify the content), the metering ID, and a transaction ID are also recorded with the count.

Understanding Transaction IDs

For metering, a transaction begins when you request metering data from the data store and ends when you reset the metering data in the data store. Transaction IDs provide a way to differentiate between transactions. This means that all metered content will be assigned the same transaction ID for the same reporting session. When you request metering data, the metering subsystem saves the transaction ID until the reporting transaction has been completed. If the process of reporting metering data is interrupted, the transaction ID identifies which data the metering subsystem must resend. This ensures that a transaction is complete before clearing the data store.

For example, suppose a metering plug-in requests metering data from a portable device. The metering challenge that the plug-in retrieves contains all the metering information stored since the last completed transaction. All the data in the challenge is associated with a single transaction ID. The player sends the data to the metering aggregation service, the service replies with a response string, and the player resets the data store. At this point, the transaction is complete, so the metering subsystem creates a new transaction ID for all metering data stored until the next reporting transaction is complete.

However, it is possible that, for some reason, the transaction is never completed. For instance, a networking issue could prevent the player from receiving the metering response. When this happens, the next metering challenge sent to the service will contain the previous transaction ID and the metering data will contain all the counts from the previous attempt, plus any new data stored in the meantime. This means that the metering aggregation service must always check the transaction ID to ensure it is not a duplicate. If it is a duplicate, any data stored from the previous transaction must be rolled back and the new values must replace it.

Reporting Metering Data Using a Computer

Requirements:

  • Windows Media DRM 10 for Portable Devices Porting Kit (for metering from devices)
  • Windows Media Device Manager 10 SDK (included with Windows Media Format 9.5 SDK)

When an end user acquires content that requires metering, the content provider service must provide the end user with a metering plug-in or application that periodically collects metering data and reports it to the metering aggregation service.

Important   Microsoft recommends that you notify end users that you will be collecting metering data.

The IWMDRMDeviceApp and IWMDRMDevice interfaces of the Windows Media Device Manager 10 SDK provide methods to request metering data and to process the metering response from the metering aggregation service.

When the plug-in or application requests metering data, the DRM component in the player retrieves the data for a specific metering ID from the data store. The plug-in or application forwards this data as a metering challenge to the corresponding metering aggregation service.

The following example code creates a function that generates a metering challenge. The function takes the canonical name of the device as an argument and returns the URL of the metering aggregation service and the metering challenge through output parameters. To use the function to request a metering challenge from the computer's data store, simply pass an empty BSTR for the first parameter. This will result in a NULL device pointer and, therefore, the challenge will be generated from the computer's data store.

HRESULT GetMeteringChallenge(BSTR bstrCanonicalName, 
                             BSTR *pbstrMeterURL,
                             BSTR *pbstrMeteringChallenge)
{
    HRESULT hr = S_OK;
    CComPtr<IWMDRMDeviceApp> spDeviceApp;
    CComPtr<IWMDeviceManager> spDevMgr;
    CComPtr<IWMDeviceManager2> spDevMgr2;
    CComPtr<IWMDMDevice> spDevice;
    CComBSTR bstrDeviceName;
    CComBSTR bstrMeterCert;

    // The string constant METERCERT is defined 
    // outside this function. It contains the 
    // metering certificate.
    hr = bstrMeterCert.Append(METERCERT);

    if(SUCCEEDED(hr))
    {        
         bstrDeviceName.Append(bstrCanonicalName);
    }
 
    if(SUCCEEDED(hr))
    {
        // Create the WMDRMDeviceApp object.
        hr = spDeviceApp.CoCreateInstance(CLSID_WMDRMDeviceApp, 0, 
                                            CLSCTX_ALL); 
    }    
 
    // Test whether there is a device name.
    if(SUCCEEDED(hr) &&
       bstrDeviceName.Length() > 0)
    {
        // Create the Device Manager object.
        hr = spDevMgr.CoCreateInstance(CLSID_MediaDevMgr, 0, CLSCTX_ALL);
    
        if(SUCCEEDED(hr))
        {
            // QI for IWMDeviceManager2
            hr = spDevMgr.QueryInterface(&spDevMgr2);
        }

        if(SUCCEEDED(hr))
        {   
            // Retrieve a pointer to the device.
            hr = spDevMgr2->GetDeviceFromCanonicalName(bstrDeviceName,
                                                       &spDevice);
        }

        if(SUCCEEDED(hr) && spDevice)
        {
            // Initialize the metering subsystem.
            CComPtr<IWMDMDevice2> spDevice2;
            DWORD dwFlags = 0;

            hr = spDevice->QueryInterface(&spDevice2);

            if(SUCCEEDED(hr))
            {
                hr = spDeviceApp->QueryDeviceStatus(spDevice2, &dwFlags);
            }

            if(SUCCEEDED(hr))
            {
                if(!(dwFlags & WMDRM_DEVICE_ISWMDRM))
                {
                    hr = NS_E_DEVICE_NOT_WMDRM_DEVICE;
                }
            }
        }
    }
   
    if(SUCCEEDED(hr))
    {
        // NULL device pointer means to meter the PC license store.
        hr =  spDeviceApp->GenerateMeterChallenge(spDevice, 
                                                  bstrMeterCert, 
                                                  &bstrMeterURL, 
                                                  pbstrMeteringChallenge);
    }

    return hr;
}

You can use whatever technology you choose to transmit the metering challenge to the metering aggregation service and receive the response. Take care to ensure that the data remains unchanged during transport.

Reporting Metering Data Using a Web-enabled Device

The process of recording metering data on a Web-enabled device, such as a portable media player, is similar to the process on a computer—the device must use a media player that supports metering, and metering data is recorded automatically by the DRM component of the player. To support metering, the device must be based on the Windows Media DRM 10 for Portable Devices Porting Kit.

Web-enabled devices can connect directly to the metering aggregation service to report metering data. This process includes the following two steps:

  1. The device creates a metering challenge and sends it to the metering aggregation service by using the DRM_MGR_GenerateMeterChallenge function from the Windows Media DRM 10 for Portable Devices Porting Kit.
  2. After the metering aggregation service processes the metering data, the service sends the metering response to the device. The device processes the metering response and clears its data store by using the DRM_MGR_ProcessMeterResponse function.

Processing Data from a Metering Challenge

Requirement: Windows Media Rights Manager 10 SDK

The metering aggregation service receives the metering challenge, which has been encrypted using the public key of the metering certificate. The service decrypts the metering challenge with the private key of its metering certificate. Then, the metering data can be extracted into an XML string or into an object. The data is grouped into collections by content item (such as a song), and then further grouped by action type and count. For example, the service can determine that Song A was played 10 times and copied once, Song B was played 20 times, and so on.

After metering data has been collected, the metering aggregation service sends back a response that instructs the player to clear the data store for the items that were just reported. The metering aggregation service uses the WMRMMetering object to generate this response.

The following example code creates an Active Server Page (ASP) that processes metering data. Notice that the example calls a placeholder function, AggregateData, to show when to call a custom function that stores the metering information.

<%@ LANGUAGE="VBScript"%>
<%
Response.Buffer = True
Response.Expires = 0
Do
    On Error Resume Next

    '"""""""""""""""""""""""""""""""""""""""""""""""""""""
    ' Declare variables
    '"""""""""""""""""""""""""""""""""""""""""""""""""""""
    Dim MObj                    ' WMRMMetering object
    Dim MDataObj                ' WMRMMeteringData object
    Dim MContentCollObj         ' WMRMMeteringContentCollection object
    Dim MContentObj             ' WMRMMeteringContent object
    Dim MActionCollObj          ' WMRMMeteringActionCollection object
    Dim MActionObj              ' WMRMMeteringAction object

    Dim MeterChallenge          ' Metering challenge from the client
    Dim MASPrivateKey           ' Private key
    Dim MeterCert               ' Metering certificate
    Dim MeterID                 ' Metering ID
    Dim TransID                 ' Transaction ID
    Dim ContentCollLength       ' Number of items in the 
                                ' content collection
    Dim ContentKeyID            ' Key ID for a content item
    Dim ActionCollLength        ' Number of items in the action collection
    Dim ActionName              ' Action name
    Dim ActionValue             ' Action count
    Dim MeterResponseString     ' Metering response string
    Dim x, y, a, b              ' Counters
    Dim ActionPlay              ' Metered play count
    Dim ActionCopy              ' Metered copy count.

    '"""""""""""""""""""""""""""""""""""""""""""""""""""""
    ' Set variables.
    '"""""""""""""""""""""""""""""""""""""""""""""""""""""
    ' This example assumes that the metering challenge was transmitted
    ' using the name "mchall".
    MeterChallenge = Request.form("mchall")
    MeterCert = "<Replace this with the metering certificate>"
    MASPrivateKey = "<Replace this with the private key.>"

    '"""""""""""""""""""""""""""""""""""""""""""""""""""""
    ' Extract metering data as a WMRMMeteringData object and as a string.
    '"""""""""""""""""""""""""""""""""""""""""""""""""""""
    Set MObj = Server.CreateObject("WMRMObjs.WMRMMetering")
    MObj.ServerPrivateKey = MASPrivateKey
    MObj.Challenge = MeterChallenge
    Set MDataObj = MObj.GetMeteringData
    MeterID = MDataObj.MeteringId
    TransID = MDataObj.TransactionId

    '"""""""""""""""""""""""""""""""""""""""""""""""""""""
    ' Retrieve the collection of content items.
    '"""""""""""""""""""""""""""""""""""""""""""""""""""""
    Set MContentCollObj = MDataObj.ContentCollection
    ContentCollLength = MContentCollObj.length

    '"""""""""""""""""""""""""""""""""""""""""""""""""""""
    ' Retrieve the key ID and action data for each content item.
    '"""""""""""""""""""""""""""""""""""""""""""""""""""""
    For x = 0 To (ContentCollLength - 1)
        ActionPlay = 0
        ActionCopy = 0

        Set MContentObj = MContentCollObj.item(x)
        ContentKeyID = MContentObj.KeyID

        ' Retrieve the collection of actions for the current content item.
        Set MActionCollObj = MContentObj.Actions
        ActionCollLength = MActionCollObj.length

        ' Retrieve each action and its value.
        For y = 0 To ActionCollLength - 1
            Set MActionObj = MActionCollObj.item(y)
            ActionName = MActionObj.Name
            ActionValue = MActionObj.Value
            If (ActionName = "Play") then ActionPlay = ActionValue
            If (ActionName = "Copy") then ActionCopy = ActionValue
        Next
        
        ' AggregateData() is a custom function not implemented
        ' in this example. In practice, this function would 
        ' increment play count and copy count values in a database.
        ' Including the transaction ID ensures that actions
        ' are not counted multiple times. 
        ' You should adjust counts to use the most
        ' recent totals for a given transaction ID.
        AggregateData(ContentKeyID, TransID, ActionPlay, ActionCopy)
    Next

    '"""""""""""""""""""""""""""""""""""""""""""""""""""""
    ' Generate the metering response.
    '"""""""""""""""""""""""""""""""""""""""""""""""""""""
    MObj.MeteringCertificate = MeterCert
    MeterResponseString = MObj.GetMeteringResponse
    response.write MeterResponseString

Loop while false

%>

Processing the Metering Response

Requirements:

  • Windows Media DRM 10 for Portable Devices Porting Kit (for metering from devices)
  • Windows Media Device Manager 10 SDK (included with Windows Media Format 9.5 SDK)

You should recall that the metering aggregation service must return a metering response to the plug-in or application. This response contains information about which items were successfully reported. The plug-in or application uses the Windows Media Device Manager 10 SDK method IWMDRMDeviceApp::ProcessMeterResponse to clear those items from the data store.

The following example code creates a function that processes a metering response. The function takes a pointer to the device and the metering response string as arguments. It returns a Boolean through an output parameter that indicates whether the response is a partial one. In the case of a partial response, your code should meter again, and keep processing challenges and responses until all metering is completed for the session.

HRESULT DoMeteringResponse(IWMDMDevice *pDevice, BSTR bstrMeterResponse,
                           BOOL *pbPartial)
{  
    HRESULT hr = S_OK;
    CComPtr<IWMDRMDeviceApp> spDeviceApp;
    CComPtr<IWMDMDevice> spDevice = pDevice;
    DWORD   dwProcessFlags = 0;

    CComBSTR bstrResponse;
    hr = bstrResponse.Append(bstrMeterResponse);

    ATLASSERT(bstrResponse.Length());

    if(SUCCEEDED(hr))
    {
        // Create the WMDRMDeviceApp object.
        hr = spDeviceApp.CoCreateInstance(CLSID_WMDRMDeviceApp, 0,
                                        CLSCTX_ALL);
    }

        if(SUCCEEDED(hr))
        {
            hr = spDeviceApp->ProcessMeterResponse(spDevice, 
                                                (BYTE*)bstrResponse.m_str, 
                                                bstrResponse.ByteLength(), 
                                                &dwProcessFlags);
        }

        // Inspect the flags and set the output parameter value.
        if(SUCCEEDED(hr))
        {
            if(WMDRM_METER_RESPONSE_PARTIAL & dwProcessFlags)
            {
                *pbPartial = TRUE;
            }
            else
            {
                *pbPartial = FALSE;
            }
    }
    
    return hr;
}

For More Information