Skip to content

feat(FFmpeg): add V4L2 zero-copy support - #781

Merged
ReenigneArcher merged 1 commit into
LizardByte:masterfrom
GenshinImpactStarts:feat-v4l2-encoder
Sep 24, 2026
Merged

ReenigneArcher merged 1 commit into
LizardByte:masterfrom
GenshinImpactStarts:feat-v4l2-encoder

Conversation

@GenshinImpactStarts

Copy link
Copy Markdown
Contributor

Description

This PR adds two FFmpeg patches required for Sunshine's upcoming V4L2 M2M hardware encoder support (H.264/HEVC/AV1) on Linux.

To achieve true zero-copy, Sunshine needs to import DMA-BUFs directly into FFmpeg's V4L2 output buffers. FFmpeg's current v4l2_m2m implementation uses a memcpy path, so two patches are needed to expose the required private headers/symbols to downstream consumers and adapt the buffer handling for Sunshine.

Patch details

  • 01-expose-function.patch: Exposes static/private functions so consumers can explicitly stop the encoder, reclaim output buffers, and set V4L2 extended controls.
  • 02-specify-buffer.patch: Adds additional fields and conditional logic to work with buffers that Sunshine has already written.

Scope and behavior

  • Applies by default only on Linux and FreeBSD amd64.
  • Explicitly disabled on Windows, macOS, and FreeBSD aarch64.
  • Zero-copy is an opt-in per-context switch, so existing FFmpeg consumers remain unaffected.

Screenshot

Issues Fixed or Closed

Roadmap Issues

Type of Change

  • feat: New feature (non-breaking change which adds functionality)
  • fix: Bug fix (non-breaking change which fixes an issue)
  • docs: Documentation only changes
  • style: Changes that do not affect the meaning of the code (white-space, formatting, missing semicolons, etc.)
  • refactor: Code change that neither fixes a bug nor adds a feature
  • perf: Code change that improves performance
  • test: Adding missing tests or correcting existing tests
  • build: Changes that affect the build system or external dependencies
  • ci: Changes to CI configuration files and scripts
  • chore: Other changes that don't modify src or test files
  • revert: Reverts a previous commit
  • BREAKING CHANGE: Introduces a breaking change (can be combined with any type above)

Checklist

  • Code follows the style guidelines of this project
  • Code has been self-reviewed
  • Code has been commented, particularly in hard-to-understand areas
  • Code docstring/documentation-blocks for new or existing methods/components have been added or updated
  • Unit tests have been added or updated for any new or modified functionality

AI Usage

See our AI usage policy.

  • None: No AI tools were used in creating this PR
  • Light: AI provided minor assistance (formatting, simple suggestions)
  • Moderate: AI helped with code generation or debugging specific parts
  • Heavy: AI generated most or all of the code changes

@ReenigneArcher ReenigneArcher left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can these patches be prepared for, and sent to upstream?

Generally, we like to do that to avoid maintaining patches forever.

Comment thread cmake/ffmpeg/ffmpeg.cmake Outdated
@GenshinImpactStarts

Copy link
Copy Markdown
Contributor Author

Can these patches be prepared for, and sent to upstream?

Generally, we like to do that to avoid maintaining patches forever.

That’s a good suggestion. I hadn’t considered upstreaming these changes initially, but after looking into FFmpeg’s current V4L2 M2M implementation, I don’t think these patches are a good fit for upstream in their current form.

The patches mainly expose some V4L2 M2M internals and add a path for the case where an internal V4L2 buffer has already been modified externally.

The issue is that, with the current V4L2 M2M design, FFmpeg cannot reasonably expose those internal input buffers to callers. If callers are not expected to access or modify those buffers, adding an upstream code path specifically to handle them being modified externally would also break that abstraction.

DMABUF would provide a cleaner way to integrate V4L2 M2M with FFmpeg's existing hardware-frame model. There is already an upstream PR working in that direction:

https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23471

However, it looks like that PR has not been updated for about two months.

Technical details on why the input buffers cannot currently be accessed

Normally, as Sunshine does for other hardware backends, the flow is roughly:

device_ctx -> hw_frames_ctx -> avcodec_open2()

The hardware frame context defines the input frame format and creates the hardware frame pool, so Sunshine can later obtain frames for encoding through av_hwframe_get_buffer().

The current V4L2 M2M implementation, however, uses MMAP-backed buffers rather than externally provided DMABUF-backed buffers. With MMAP, the buffers can only be allocated after the input/output formats have been configured and the V4L2 session has been fully initialized, which happens during avcodec_open2().

After avcodec_open2() completes, FFmpeg does not provide an API for retrieving the input buffers internally allocated by the V4L2 encoder. Because of that, the normal hw_frames_ctx / av_hwframe_get_buffer() approach cannot be used with the MMAP path.

So if V4L2 support in Sunshine is not particularly urgent, I'm fine with either keeping this PR around for now or handling it differently if you prefer.

@sonarqubecloud

Copy link
Copy Markdown

@ReenigneArcher

Copy link
Copy Markdown
Member

Don't worry about the trailing space errors in the patches

@ReenigneArcher
ReenigneArcher merged commit 202e90a into LizardByte:master Sep 24, 2026
18 of 19 checks passed
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.

2 participants