Skip to content

feat: encode and decode H.265, and decode AV1, in hardware on macOS - #351

Closed
devopvoid wants to merge 1 commit into
feat/webrtc-h265from
feat/macos-hevc-codecs
Closed

devopvoid wants to merge 1 commit into
feat/webrtc-h265from
feat/macos-hevc-codecs

Conversation

@devopvoid

Copy link
Copy Markdown
Owner

Summary

Stacked on #346 (H.265 in the WebRTC build), and based on its branch until that is merged.

The hardware codec factories now use VideoToolbox for the codecs WebRTC's macOS factories lack, where the Mac has the hardware for them:

  • H.265 (Main profile), encoding and decoding. The sessions are required to be hardware ones (RequireHardwareAccelerated…) and are checked to be, so H.265 is never encoded or decoded in software; a Mac without a hardware HEVC encoder or decoder does not offer it. The encoder works in real time, without frame reordering, with a key frame only on request. CVPixelBuffers (camera, VideoToolbox decoders) go in as they are, other frames are converted to NV12. Its output is turned from length-prefixed NAL units into Annex B and goes through EncoderOutputProcessor, which puts the parameter sets in front of each key frame. The decoder makes its session from the VPS, SPS and PPS of key frames. With no software codec to fall back to, a failing encoder makes WebRTC switch to the next negotiated codec, and a failing decoder asks for key frames.
  • AV1 decoding (profile 0, 8 bit) on Macs with an AV1 decoder, Apple M3 and newer. The session is made from the sequence header, which is parsed for the AV1 configuration box (av1C). High bit depth, monochrome and spatial layers go to dav1d, as does a decoder that keeps failing.
  • The VP9 decoder now shares a VTVideoDecoder base with them: session, hardware check, range-matched NV12 output, failure handling. The process-wide session limit applies only to codecs that have a software decoder to go to.
  • H.265 is offered after the default codecs, which keep their order. The SDP format (H265Format) and the H.265 handling in EncoderOutputProcessor are taken over from feat: encode and decode H.265 in hardware on Windows #347 unchanged, as are its test helpers, so that the two merge cleanly; the docs, the Javadoc and a few test lines will conflict with feat: encode and decode H.265 in hardware on Windows #347.
  • The factory Javadoc and the codec guide describe macOS.

Testing

On an Apple M2, macOS 14.5, after WebRTC was rebuilt with rtc_use_h265 (incremental, about 2 minutes), with webrtc.test.hardwareH265Encoder, webrtc.test.hardwareH265Decoder and webrtc.test.hardwareDecoder set so that the tests fail rather than skip:

  • The H.265 tests from feat: encode and decode H.265 in hardware on Windows #347 now run on macOS: hardwareEncodesH265, hardwareDecodesH265, hardwareCropsPaddedH265, hardwareKeepsCodecs.
  • New: h265EncodesOddSize, h265FollowsResolutionChange, h265FollowsBitrateCap, h265RestartsCleanly, and softwareOffersNoH265 (the default factories never offer H.265). The H.265 call tests also check that the call is still in H.265 (TestMediaCall.getSentVideoCodec()), since on macOS a fallback to H.264 would also report a VideoToolbox implementation.
  • The VP9 decoder tests pass on the new base class.
  • The full webrtc test suite: 280 tests, no failures. The 12 skipped are Windows/Linux-only or need an AV1 decoder.
  • The AV1 sequence header parser was checked against dav1d's on 9 libaom configurations (default, timing info, decoder model, full range BT.709, monochrome, reduced still picture header, 1080p level, spatial and temporal layers): every field matches, and the format description is created for the supported ones.
  • A format description made from HEVC parameter sets carries the full range flag of the VUI, so the decoder outputs in the range of the stream.

Not verified

  • AV1 decoding on an actual M3 or newer; there is none here. Run with -Dwebrtc.test.hardwareAv1Decoder=true there.
  • Intel Macs.
  • The webrtc-java-media tests: the configure step stops before them because this branch is behind main by feat: decode with Vulkan Video on Linux in the media player #345, and the FFmpeg install in ~/ffmpeg was built by main with other components. Nothing in that module changes here.

The hardware codec factories now use VideoToolbox for the codecs WebRTC's
macOS factories lack, where the Mac has the hardware for them:

- H.265 (Main profile), encoded and decoded on the media engine. The
  sessions are required to be hardware ones and checked to be, so H.265 is
  never encoded or decoded in software; a Mac without a hardware HEVC
  encoder or decoder does not offer it. The encoder works in real time,
  without frame reordering, with a key frame only on request, and takes
  CVPixelBuffers as they are and converts other frames to NV12. Its output
  goes through EncoderOutputProcessor, which puts the parameter sets in
  front of each key frame. The decoder makes its session from the
  VPS, SPS and PPS of key frames.
- AV1 (profile 0, 8 bit), decoded on Macs with an AV1 decoder (Apple M3
  and newer). The session is made from the sequence header, which is
  parsed for the AV1 configuration box; high bit depth, monochrome and
  spatial layers go to dav1d, as does a decoder that keeps failing.

The VP9 decoder shares a new VTVideoDecoder base with them, which holds
the session, the hardware check and the output. The session limit of the
process applies only to codecs with a software decoder to go to.

H.265 is offered after the default codecs, which keep their order, with
the SDP format and the EncoderOutputProcessor support of #347, taken over
as they are there. Tests that a call in H.265 is encoded and decoded in
hardware run on macOS now, check that the call is still in H.265 rather
than in a codec WebRTC switched to, and cover odd sizes, a resolution
change, a bitrate cap and restarts; the software factories are checked to
offer no H.265.
@devopvoid
devopvoid deleted the branch feat/webrtc-h265 October 11, 2026 18:25
@devopvoid devopvoid closed this Oct 11, 2026
@devopvoid devopvoid reopened this Oct 11, 2026
@devopvoid

Copy link
Copy Markdown
Owner Author

Closing: this change is already on main. feat/windows-hevc-codecs was stacked on this commit (f26624f), so it landed with #347 (19f7b1c).

@devopvoid devopvoid closed this Oct 11, 2026
@devopvoid
devopvoid deleted the feat/macos-hevc-codecs branch October 11, 2026 20:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant