![François Beaufort](https://web.dev/images/authors/beaufortfrancois.jpg) François Beaufort [GitHub](https://github.com/beaufortfrancois)

<br />

- Chrome supports [AV1 video decoding](https://developer.chrome.com/blog/media-updates-in-chrome-69.md.txt#av1).
- Querying [which encryption schemes are supported](https://developer.chrome.com/blog/media-updates-in-chrome-69.md.txt#encryption_scheme) through EME is now available.
- Web developers can experiment with [querying whether a certain HDCP policy can be enforced](https://developer.chrome.com/blog/media-updates-in-chrome-69.md.txt#hdcp).
- Media Source Extensions now use [PTS for buffered ranges and duration values](https://developer.chrome.com/blog/media-updates-in-chrome-69.md.txt#pts).
- Android Go users can [open downloaded audio, video and images in Chrome](https://developer.chrome.com/blog/media-updates-in-chrome-69.md.txt#media_intent_handler).
- [Stalled events](https://developer.chrome.com/blog/media-updates-in-chrome-69.md.txt#stalled) for media elements using MSE are removed.

## AV1 video decoder

> [!NOTE]
> **Note:** AV1 video decoder support had to be pushed back to \[Chrome 70\] because of changes to the MP4 binding.

[Chromestatus Tracker](https://www.chromestatus.com/feature/5729898442260480) \|
[Chromium Bug](https://bugs.chromium.org/p/chromium/issues/detail?id=838380)

## EME: Querying encryption scheme support

Some platforms or key systems only support [CENC mode](https://www.iso.org/obp/ui/#iso:std:iso-iec:23001:-7:ed-2:v1:en), while others only support
[CBCS mode](https://www.iso.org/obp/ui/#iso:std:iso-iec:23001:-7:ed-3:v1:en). Still others are able to support both. These two encryption schemes
are incompatible, so web developers must be able to make intelligent choices
about what content to serve.

To avoid having to determine which platform they're on to check for "known"
encryption scheme support, a new `encryptionScheme` key is [added](https://github.com/WICG/encrypted-media-encryption-scheme/blob/main/explainer.md) in
`MediaKeySystemMediaCapability` [dictionary](https://w3c.github.io/encrypted-media/#idl-def-mediakeysystemmediacapability) to allow websites to specify
which encryption scheme could be used in [Encrypted Media Extensions (EME)](https://w3c.github.io/encrypted-media/).

The new `encryptionScheme` key can be one of two values:

- `'cenc'` AES-CTR mode full sample and video NAL subsample encryption.
- `'cbcs'` AES-CBC mode partial video NAL pattern encryption.

If not specified, it indicates that any encryption scheme is acceptable. Note
that [Clear Key](https://www.w3.org/TR/encrypted-media/#clear-key) always supports the `'cenc'` scheme.

The example below shows how to query two configurations with different
encryption schemes. In this case, only one will be chosen.

```javascript
await navigator.requestMediaKeySystemAccess('org.w3.clearkey', [
    {
      label: 'configuration using the "cenc" encryption scheme',
      videoCapabilities: [{
        contentType: 'video/mp4; codecs="avc1.640028"',
        encryptionScheme: 'cenc'
      }],
      audioCapabilities: [{
        contentType: 'audio/mp4; codecs="mp4a.40.2"',
        encryptionScheme: 'cenc'
      }],
      initDataTypes: ['keyids']
    },
    {
      label: 'configuration using the "cbcs" encryption scheme',
      videoCapabilities: [{
        contentType: 'video/mp4; codecs="avc1.640028"',
        encryptionScheme: 'cbcs'
      }],
      audioCapabilities: [{
        contentType: 'audio/mp4; codecs="mp4a.40.2"',
        encryptionScheme: 'cbcs'
      }],
      initDataTypes: ['keyids']
    },
  ]);
```

In the example below, only one configuration with two different encryption
schemes is queried. In that case, Chrome will discard any capabilities object
it cannot support, so the accumulated configuration may contain one encryption
scheme or both.

```javascript
await navigator.requestMediaKeySystemAccess('org.w3.clearkey', [{
    videoCapabilities: [
      { // A video capability using the "cenc" encryption scheme
        contentType: 'video/mp4; codecs="avc1.640028"',
        encryptionScheme: 'cenc'
      },
      { // A video capability using the "cbcs" encryption scheme
        contentType: 'video/mp4; codecs="avc1.640028"',
        encryptionScheme: 'cbcs'
      },
    ],
    audioCapabilities: [
      { // An audio capability using the "cenc" encryption scheme
        contentType: 'audio/mp4; codecs="mp4a.40.2"',
        encryptionScheme: 'cenc'
      },
      { // An audio capability using the "cbcs" encryption scheme
        contentType: 'audio/mp4; codecs="mp4a.40.2"',
        encryptionScheme: 'cbcs'
      },
    ],
    initDataTypes: ['keyids']
  }]);
```

[Intent to Implement](https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/lMUKOaohUTY) \|
[Chromestatus Tracker](https://www.chromestatus.com/feature/5184416120832000) \|
[Chromium Bug](https://bugs.chromium.org/p/chromium/issues/detail?id=838416)

## EME: HDCP policy check

Nowadays [HDCP](https://en.wikipedia.org/wiki/High-bandwidth_Digital_Content_Protection) is a common policy requirement for streaming high resolutions
of [protected content](https://developers.google.com/web/fundamentals/media/eme). And web developers who want to enforce an HDCP policy
must either wait for the license exchange to complete or start streaming
content at a low resolution. This, is a sad situation that the [HDCP Policy
Check API](https://github.com/WICG/hdcp-detection/blob/main/explainer.md) aims to solve.

This proposed API allows web developers to query whether a certain HDCP policy
can be enforced so that playback can be started at the optimum resolution for
the best user experience. It consists of a simple method to query the status of
a hypothetical key associated with an HDCP policy, without the need to create a
`MediaKeySession` or fetch a real license. It does not require `MediaKeys` to be
attached to any audio or video elements either.

The HDCP Policy Check API works simply by calling
`mediaKeys.getStatusForPolicy()` with an object that has a `minHdcpVersion` key
and a valid value. If HDCP is available at the specified version, the returned
promise resolves with a `MediaKeyStatus` of `'usable'`. Otherwise, the promise
resolves with [other error values](https://w3c.github.io/encrypted-media/#dom-mediakeystatus) of `MediaKeyStatus` such as
`'output-restricted'` or `'output-downscaled'`. If the key system does not
support HDCP Policy Check at all (e.g. Clear Key System), the promise rejects.

In a nutshell, here's how the API works for now. Check out the [official sample](https://googlechrome.github.io/samples/hdcp-detection/)
to try out all versions of HDCP.

```javascript
const config = [{
  videoCapabilities: [{
    contentType: 'video/webm; codecs="vp09.00.10.08"',
    robustness: 'SW_SECURE_DECODE' // Widevine L3
  }]
}];

navigator.requestMediaKeySystemAccess('com.widevine.alpha', config)
.then(mediaKeySystemAccess => mediaKeySystemAccess.createMediaKeys())
.then(mediaKeys => {

  // Get status for HDCP 2.2
  return mediaKeys.getStatusForPolicy({ minHdcpVersion: '2.2' })
  .then(status => {
    if (status !== 'usable')
      return Promise.reject(status);

    console.log('HDCP 2.2 can be enforced.');
    // TODO: Fetch high resolution protected content...
  });
})
.catch(error => {
  // TODO: Fallback to fetch license or stream low-resolution content...
});
```

### Available for origin trials

To get feedback from web developers, we've previously added the HDCP Policy
Check API feature in Chrome 69 for Desktop (ChromeOS, Linux, Mac, and Windows).

The trial successfully ended in November 2018.

[Intent to Experiment](https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/ITzZ_yx4bF8) \|
[Chromestatus Tracker](https://www.chromestatus.com/feature/5652917147140096) \|
[Chromium Bug](https://crbug.com/709348)

## MSE PTS/DTS compliance

Buffered ranges and duration values are now reported by Presentation Time Stamp
(PTS) intervals, rather than by Decode Time Stamp (DTS) intervals in [Media
Source Extensions (MSE)](https://developers.google.com/web/fundamentals/media/mse/basics).

When MSE was new, Chrome's implementation was tested against WebM and MP3, some
media stream formats where there was no distinction between PTS and DTS. And
it was working fine until ISO BMFF (aka MP4) was added. This container
frequently contains out-of-order presentation versus decode time streams (for
codecs like H.264 for example) causing DTS and PTS to differ. That caused
Chrome to report (usually just slightly) different buffered ranges and duration
values than expected. This new behavior will roll out gradually in Chrome 69
and make its MSE implementation compliant with the [MSE specification](https://w3c.github.io/media-source/).
![PTS/DTS](https://developer.chrome.com/static/blog/media-updates-in-chrome-69/image/ptsdts-a029a068bdd9b.png) PTS/DTS

This change affects `MediaSource.duration` (and consequently
`HTMLMediaElement.duration`), `SourceBuffer.buffered` (and consequently
`HTMLMediaElement.buffered)`, and `SourceBuffer.remove(start, end)`.

If you're not sure which method is used to report buffered ranges and duration
values, you can go to the internal `chrome://media-internals` page and search for
"ChunkDemuxer: buffering by PTS" or "ChunkDemuxer: buffering by DTS" in the
logs.

[Intent to Implement](https://groups.google.com/a/chromium.org/d/msg/blink-dev/I6oGJLym-Tk/Z46le9l4CQAJ) \|
[Chromium Bug](https://crbug.com/718641)

## Handling of media view intents on Android Go

[Android Go](https://www.android.com/versions/oreo-8-0/go-edition/) is a lightweight version of Android designed for entry-level
smartphones. To that end, it does not necessarily ship with some media-viewing
applications, so if a user tries to open a downloaded video for instance, they
won't have any applications to handle that intent.

To fix this, Chrome 69 on Android Go now listens for media-viewing intents so
users can view downloaded audio, videos, and images. In other words, it takes
the place of the missing viewing applications.
![ALT_TEXT_HERE](https://developer.chrome.com/static/blog/media-updates-in-chrome-69/image/alttexthere-0d5b0859fc0e3.png) Media intent handler

Note that this Chrome feature is enabled on all Android devices running Android
O and onwards with 1 GB of RAM or less.

[Chromium Bug](https://crbug.com/718641)

## Removal of "stalled" events for media elements using MSE

A "stalled" event is raised on a media element if downloading media data has
failed to progress for about 3 seconds. When using [Media Source Extensions
(MSE)](https://developers.google.com/web/fundamentals/media/mse/basics), the web app manages the download and the media element is not aware of
its progress. This caused Chrome to raise "stalled" events at inappropriate
times whenever the website has not appended new media data chunks with
`SourceBuffer.appendBuffer()` in the last 3 seconds.

As websites may decide to append large chunks of data at a low frequency, this
is not a useful signal about buffering health. Removing "stalled" events for
media elements using MSE clears up confusion and brings Chrome more in line
with the MSE specification. Note that media elements that don't use MSE will
continue to raise "stalled" events as they do today.

[Intent to Deprecate and Remove](https://groups.google.com/a/chromium.org/d/msg/blink-dev/x54XtrTyOP8/4-5QZlZzDAAJ) \|
[Chromestatus Tracker](https://www.chromestatus.com/feature/6338037575319552) \|
[Chromium Bug](https://bugs.chromium.org/p/chromium/issues/detail?id=836951)