Android Media Framework
MediaPlayer, MediaCodec, MediaExtractor, MediaCrypto.
The Android media stack at a glance
Before MediaDrm makes sense you need a clear mental model of the four classes that move bytes through the pipeline:
How a frame travels
Why MediaCrypto is separate from MediaDrm
The codec doesn't want to know about DRM sessions, key requests, or the licence server. It only wants "decrypt this sample with this IV, KID, and sub-sample table." MediaCrypto is the narrowest possible API that lets the codec ask. MediaDrm holds everything else.
This split is also why Widevine works with arbitrary codecs — including third-party ones — without each codec needing to be DRM-aware. It just needs to accept a MediaCrypto.
Container scheme: cenc vs cbcs
Each sample's CryptoInfo tells the codec which encryption scheme is in use:
cenc— full-sample AES-CTR. Older Widevine packaging.cbcs— pattern-based AES-CBC (1:9 typical pattern: 1 encrypted block, 9 in the clear). Required for FairPlay; modern Widevine and PlayReady accept it. Lets a single packaging serve all three DRMs.
The codec must support the scheme. Some older HW codecs only support cenc. If you ship cbcs to such a device, you'll see green frames or decode errors.
cbcs is the multi-DRM scheme. cenc is older / Widevine-and-PlayReady-only. Modern packaging defaults to cbcs.
Surfaces and secure decoding
For L1 playback, the surface (the SurfaceView / SurfaceTexture you give the codec) must be a secure surface. The codec writes decoded frames into a region the rich OS can't read. Composition happens through the SurfaceFlinger secure-output path; outputs go via HDMI with HDCP.
Practical effect: if you try to screen-record an L1 protected playback on Android, you get a black frame.
Where ExoPlayer fits
In real apps you almost never wire MediaExtractor + MediaCodec + MediaCrypto by hand. ExoPlayer (now Media3) handles the orchestration:
- It uses its own extractors / loaders.
- It plugs DefaultDrmSessionManager into the renderer.
- The renderer creates MediaCrypto from the session and passes it to the codec.
You bring the licence callback (HttpMediaDrmCallback) and the manifest URL; ExoPlayer drives the rest.