Backend Development 34 min read

Implementing MediaDecoderConfig API in Chromium to Expose Video and Audio Decoder Information

This article explains how to extend Chromium's media internals by implementing a MediaDecoderConfig API that exposes detailed video and audio decoder parameters, including bitrate, codec, resolution, color space, and HDR metadata, through new HTMLMediaElement properties and a mediaconfigchange event.

ByteFE
ByteFE
ByteFE
Implementing MediaDecoderConfig API in Chromium to Expose Video and Audio Decoder Information

The article begins by describing the need for statistical data about video streams, such as codec, resolution, and bitrate, which browsers do not expose through standard HTMLVideoElement attributes. It proposes leveraging Chromium's internal Media Internals debugging page (chrome://media-internal) to capture decoder configuration data directly from the renderer process.

It then details the internal routing logic of Media Internals, showing how the URL is mapped to the MediaInternalsUI class and how the WebUI data source is created. The source code snippets illustrate the creation of the MediaInternalsHTMLSource and the handling of media logs.

To provide a public API, the article introduces a new MediaDecoderConfig class in Blink, along with corresponding C++ structures for VideoDecoderConfig and AudioDecoderConfig . These classes are extended with methods to retrieve human‑readable strings for each field, such as GetHumanReadableTotalBitrate() , GetHumanReadableCodecName() , and many HDR‑related getters.

struct VideoDecoderConfig {
  int totalStreamBitrate_ = 0;
  int videoStreamBitrate_ = 0;
  std::string AsHumanReadableString() const;
  int GetHumanReadableTotalBitrate() const;
  int GetHumanReadableVideoBitrate() const;
  std::string GetHumanReadableCodecName() const;
  // ... other getters for profile, level, color space, etc.
};

struct AudioDecoderConfig {
  int totalStreamBitrate_ = 0;
  int audioStreamBitrate_ = 0;
  std::string AsHumanReadableString() const;
  int GetHumanReadableTotalBitrate() const;
  int GetHumanReadableAudioBitrate() const;
  std::string GetHumanReadableCodecName() const;
  // ... other getters for channel layout, sample format, etc.
};

These structures are integrated into the media pipeline: the FFmpegDemuxer now calculates per‑stream bitrates and populates the new fields via SetAudioBitrate and SetVideoBitrate . The HTMLMediaElement class is modified to store the latest VideoDecoderConfig and AudioDecoderConfig objects, expose them through read‑only attributes videoConfig and audioConfig , and provide a getMediaConfig() method that returns a MediaDecoderConfig instance.

class HTMLMediaElement : public HTMLElement {
 public:
  String videoConfig() const;
  String audioConfig() const;
  MediaDecoderConfig* getMediaConfig();
  void OnVideoConfigChange(const media::VideoDecoderConfig& config) override;
  void OnAudioConfigChange(const media::AudioDecoderConfig& config) override;
  void OnMediaConfigChange(bool has_video, bool has_audio) override;
 private:
  MediaDecoderConfig media_config_;
  bool has_video_ = false;
  bool has_audio_ = false;
  media::VideoDecoderConfig video_config_;
  media::AudioDecoderConfig audio_config_;
};

To make the API accessible from JavaScript, a new IDL file media_decoder_config.idl defines the MediaDecoderConfig interface with read‑only attributes for each field. The Blink bindings are generated, and the mediaconfigchange event is added to the global event handlers, allowing developers to listen for updates:

const media = document.createElement('video');
media.addEventListener('mediaconfigchange', e => {
  console.log('Media config changed', media.getMediaConfig());
});
media.src = 'https://example.com/video.mp4';

The article concludes with a summary of the steps required to implement such a feature in Chromium: identify a concrete use case, understand the Chromium build and debugging workflow, locate the appropriate modules (media pipeline, Blink UI, and IDL), and iteratively compile and test the changes.

chromiumAudioDecoderBrowserInternalsMediaDecoderConfigVideoDecoder
ByteFE
Written by

ByteFE

Cutting‑edge tech, article sharing, and practical insights from the ByteDance frontend team.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.