Repository navigation
(feature): Decode H.264, HEVC and ProRes with VideoToolbox on MacOs. - #359
Open
richardssam wants to merge 1 commit into
Open
richardssam wants to merge 1 commit into
richardssam wants to merge 1 commit into
Conversation
…on macOS
Adds a VideoToolbox decode backend inside FFMpegStream, so on macOS H.264,
HEVC and ProRes video go through Apple's licensed (and mostly hardware)
decoders while libavformat still handles demuxing, seeking, timecode and
audio. AAC uses FFmpeg's AudioToolbox decoder (aac_at) where available.
- New preference /plugin/media_reader/FFMPEG/videotoolbox: off / prefer
(default) / only. 'prefer' falls back to FFmpeg's decoder if a session
can't be created; 'only' reports an error on the frame instead.
- VtDecoder follows avcodec's send/receive/flush contract, so
FFMpegDecoder, thumbnails and caching are unchanged. Frames are reordered
into presentation order using the highest DTS seen.
- Output stays native YCbCr. VideoToolbox's biplanar formats are repacked
by small vectorised loops (vt_repack) into planar formats the existing
shader reads: 8/10 bit 4:2:0/4:2:2/4:4:4, 12 bit 4:2:2/4:4:4, and ProRes
4444 with alpha ('s4as'). 12 bit 4:2:0 HEVC stays on FFmpeg: VideoToolbox's
chroma for it is inaccurate.
- A video stream VideoToolbox decodes no longer needs an FFmpeg decoder to
exist, ready for builds without the patent-encumbered decoders.
- Changing the preference at runtime drops frames decoded under the old mode.
Measured on an M2 Max: H.264/HEVC output bit-exact against FFmpeg, ProRes
within 4 code values; 5-10x less CPU for 4K playback, which now plays
smoothly where software decode stutters.
Also gives gtest targets the __apple__ define the headers rely on to undo
MacTypes.h's 'nil' macro; ffmpeg_test didn't compile on macOS without it.
Tests: ffmpeg_test covers repack loops, decode order, format/colour and
random-access parity with FFmpeg's decoder, fallback, thumbnails, AAC
timing and preference changes, using media from
test/videotoolbox_media/generate.sh (skipped when not generated).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pull Request Decode H.264, HEVC and ProRes with VideoToolbox on MacOs.
Summarize your change.
MacOS has a terrific library videotoolbox that offers hardware decompression of H264 HEVC, Prores and AAC, including licenceses for them. This PR enables the ffmpeg videotoolbox decoders where available. libavformat still does demuxing, seeking, timecode and audio, so every container that works today still works.
The new backend lives inside FFMpegStream and follows avcodec's send/receive/flush behaviour, so FFMpegDecoder, thumbnails and caching are unchanged. Frames stay in native YCbCr, with no RGB conversion by the OS. They're repacked into planar formats the existing YUV shader already reads, so the shader doesn't change.
A new preference, /plugin/media_reader/FFMPEG/videotoolbox, controls it:
Describe the reason for the change.
Describe what you have tested and on which operating system.
macOS 26.6 on an M2 Max, with FFmpeg 8.0.1 from vcpkg.
Add a list of changes, and note any that might need special attention during the review.
vt_decoder.{hpp,cpp}, the VideoToolbox backend. It's built only on Apple, and uses the C APIs, so there's no Objective-C++. Frames are reordered into presentation order using the highest decode timestamp submitted, so there's no SPS parsing.vt_repack.{hpp,cpp}, platform-neutral, vectorised loops that unpack VideoToolbox's two-plane formats into planar ImageBuffers. Each takes 0.4–2.2 ms per 4K frame. They replaced swscale, which took 7.7–9.6 ms.FFMpegStreamconstructor: VideoToolbox is tried beforeavcodec_find_decoder(), andcodec_can now be null for video streams. Uses ofcodec_->idbecamecodecpar->codec_id. The software setup moved intoopen_software_video_decoder()without changing behaviour.prefer: macOS users get VideoToolbox without doing anything. ProRes values differ from FFmpeg'sproresdecoder by up to 4 code values; Apple's decoder is the reference.cmake/macros.cmake: gtest targets now get the same__apple__define as other targets. Without it,ffmpeg_testdidn't compile on macOS, on develop too, because the headers rely on that define to undefine thenilmacro from MacTypes.h.s4as. VideoToolbox's conversion toy416replaces real chroma with neutral values over about 12% of the frame. 12-bit 4:2:0 HEVC stays on FFmpeg, because VideoToolbox's chroma for it is inaccurate.FFMpegMediaReader: on Apple, AAC prefersaac_at. On a preference change, the reader drops its last decoded frame and its decoders. A newvideotoolbox_unavailable_erroris always shown on the frame.XSTUDIO_VIDEOTOOLBOX_FORCE_FAILUREmakes VideoToolbox session creation fail..h264files have no duration and show black..h264.MediaCache.erase()is a no-op, andOffscreenViewport.render_media_frame()uses an undefined variable.Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com