Decrypt PlayReady-encrypted VOD content with the Wowza Streaming Engine Java API

This article describes how to use the Wowza Streaming Engine™ Java API to decrypt Microsoft PlayReady–encrypted MP4 files before streaming.

Important: Prerequisites include installing the Wowza IDE and understanding how server-side programming works.

The following code represents a module that intercepts all file open requests and provides a key to facilitate PlayReady decryption on the fly.

package com.wowza.wms.plugin.test.module;

import com.wowza.util.*;
import com.wowza.wms.application.*;
import com.wowza.wms.drm.playready.*;
import com.wowza.wms.mediareader.h264.*;
import com.wowza.wms.module.*;
import com.wowza.wms.stream.*;

public class ModuleMP4PlayReadyKeyProvider extends ModuleBase
{
	class MediaReaderListener implements IMediaReaderActionNotify
	{
		public void onMediaReaderCreate(IMediaReader mediaReader)
		{
		}

		public void onMediaReaderInit(IMediaReader mediaReader, IMediaStream stream)
		{
		}

		public void onMediaReaderOpen(IMediaReader mediaReader, IMediaStream stream)
		{
			getLogger().info("ModuleMP4PlayReadyKeyProvider#MediaReaderListener.onMediaReaderOpen["+stream.getName()+"]");

			if (mediaReader instanceof IMediaReaderEncInfo)
			{
				PlayReadySampleInfo videoSampleInfo = ((MediaReaderH264)mediaReader).getPlayReadyAudioTrackInfo(((MediaReaderH264)mediaReader).getTrackIndexAudio());
				if (videoSampleInfo != null && videoSampleInfo.getKeyID() != null)
					getLogger().info("ModuleMP4PlayReadyKeyProvider#MediaReaderListener.onMediaReaderOpen["+stream.getName()+"]: video.keyId:"+BufferUtils.encodeHexString(videoSampleInfo.getKeyID()));

				PlayReadySampleInfo audioSampleInfo = ((MediaReaderH264)mediaReader).getPlayReadyAudioTrackInfo(((MediaReaderH264)mediaReader).getTrackIndexAudio());
				if (audioSampleInfo != null && audioSampleInfo.getKeyID() != null)
					getLogger().info("ModuleMP4PlayReadyKeyProvider#MediaReaderListener.onMediaReaderOpen["+stream.getName()+"]: audio.keyId:"+BufferUtils.encodeHexString(audioSampleInfo.getKeyID()));

				MediaReaderEncInfo encInfo = ((IMediaReaderEncInfo)mediaReader).getEncInfo();

				PlayReadyKeyInfo decryptorKey = new PlayReadyKeyInfo();
				decryptorKey.setContentKey(Base64.decode("Tc2cQBPC/paTkftvaITCSQ=="));

				encInfo.setEncMethod(MediaReaderEncInfo.METHOD_SAMPLE_PLAYREADY);
				encInfo.addPlayReadyDecryptorKey(decryptorKey);
			}
		}

		public void onMediaReaderExtractMetaData(IMediaReader mediaReader, IMediaStream stream)
		{
		}

		public void onMediaReaderClose(IMediaReader mediaReader, IMediaStream stream)
		{
		}
	}

	public void onAppStart(IApplicationInstance appInstance)
	{
		getLogger().info("ModuleMP4PlayReadyKeyProvider.onAppStart["+appInstance.getContextStr()+"]");
		appInstance.addMediaReaderListener(new MediaReaderListener());
	}

}

In onAppStart, an IMediaReaderActionNotify interface is added to the application instance to listen for MediaReader events such as file open and close. In the onMediaReaderOpen event, Wowza Streaming Engine checks to see if the MediaReader implementation includes decryption key support. If it does, Wowza Streaming Engine provides the PlayReady key information for the file. For decryption, only the decryption key is needed.

This module only serves as a simple example of how the decryption API works. In real-world usage, this module will most likely be integrated with your PlayReady key server to set decryption keys on a per-file basis.

To add this module to an application, open [install-dir]/conf/[application]/Application.xml in a text editor and add the following module definition:

<Module>
	<Name>ModuleMP4PlayReadyKeyProvider</Name>
	<Description>ModuleMP4PlayReadyKeyProvider</Description>
	<Class>com.wowza.wms.plugin.test.module.ModuleMP4PlayReadyKeyProvider</Class>
</Module>