Add video encoding support with SYCL RGB→NV12 kernel and CPU fallback - #103
Add video encoding support with SYCL RGB→NV12 kernel and CPU fallback#103eromomon wants to merge 4 commits into
Conversation
Signed-off-by: Edgar Romo Montiel <edgar.romo.montiel@intel.com>
Signed-off-by: Edgar Romo Montiel <edgar.romo.montiel@intel.com>
Signed-off-by: Edgar Romo Montiel <edgar.romo.montiel@intel.com>
There was a problem hiding this comment.
Pull request overview
Adds an Intel XPU (VAAPI) hardware video encoding path to the torchcodec-xpu plugin, including an on-device SYCL RGB→NV12 conversion kernel with a CPU/libswscale fallback, and updates upstream TorchCodec encoder tests (via patch) to run on XPU as well as CUDA.
Changes:
- Implement XPU encoding overrides in
XpuDeviceInterface(pixel format selection, VAAPI hw_frames_ctx setup, tensor→AVFrame upload path with SYCL fast-path + CPU fallback). - Add SYCL
convertRGBToNV12kernel supporting BT.601/BT.709 and full/limited range, including tiled (Intel Tile-Y) surface handling. - Extend/parameterize upstream encoder tests (patch) to exercise XPU and avoid VAAPI flush-on-empty segfault by priming with a frame.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/torchcodec-xpu/src/torchcodec_xpu/XpuDeviceInterface.h | Declares XPU encoding overrides and helper conversion entry points. |
| packages/torchcodec-xpu/src/torchcodec_xpu/XpuDeviceInterface.cpp | Implements VAAPI frames context setup, VAAPI encoder discovery logic, and SYCL/CPU tensor→NV12 surface conversion. |
| packages/torchcodec-xpu/src/torchcodec_xpu/ColorConversionKernel.h | Exposes the new SYCL RGB→NV12 conversion API. |
| packages/torchcodec-xpu/src/torchcodec_xpu/ColorConversionKernel.cpp | Implements RGB→NV12 SYCL kernel and supporting YUV conversion matrices. |
| packages/torchcodec-xpu/patches/0002-Add-XPU-support-to-video-encoder-tests.patch | Updates upstream TorchCodec encoder tests to include XPU device coverage and VAAPI-specific priming behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Encoder-only fallback: if no VAAPI encoder exists for codecId | ||
| // substitute a HW-capable alternative | ||
| if (!is_decoder) { | ||
| static constexpr AVCodecID kHwEncoderFallbacks[] = { | ||
| AV_CODEC_ID_H264, | ||
| AV_CODEC_ID_HEVC, | ||
| AV_CODEC_ID_AV1, | ||
| }; | ||
| for (AVCodecID fb : kHwEncoderFallbacks) { | ||
| if (fb == codec_id) { | ||
| continue; | ||
| } | ||
| if (const AVCodec* c = findVaapiForId(fb)) { | ||
| VLOG(1) << "No VAAPI encoder for codec id " << codec_id | ||
| << ", substituting " << c->name; | ||
| return c; | ||
| } | ||
| } | ||
| } |
| hwFramesCtx->width = codec_context->width; | ||
| hwFramesCtx->height = codec_context->height; | ||
|
|
||
| // XPU quality is matterially better when using BT.709 color space and full range |
| +import torchcodec | ||
| +import torchcodec_xpu | ||
| + |
| // Disable B-frames (mirrors CUDA/NVENC delay=0) to avoid reorder issues | ||
| // with fragmented containers; callers can restore via extra_options={"bf":"2"}. |
There was a problem hiding this comment.
Reordering is not an issue - that's how media codecs behave. I don't understand what you mean by "fragmented containers", so drop it.
| // Disable B-frames (mirrors CUDA/NVENC delay=0) to avoid reorder issues | |
| // with fragmented containers; callers can restore via extra_options={"bf":"2"}. | |
| // Disable B-frames (mirrors CUDA/NVENC delay=0) to avoid frames reordering. | |
| // Callers can restore via extra_options={"bf": "2"}. |
Question: extra_options is a TorchCodec option?
There was a problem hiding this comment.
Yes, extra_options is a TorchCodec public API parameter on _video_encoder.py
| return c; | ||
| } | ||
|
|
||
| // Encoder-only fallback: if no VAAPI encoder exists for codecId |
There was a problem hiding this comment.
Remind me, please, why do we need this? What will start to fail if we will drop this?
There was a problem hiding this comment.
Removing the fallback here regresses XPU encoding on any FFmpeg build that lacks h264_vaapi. The block is not a CPU fallback: it substitutes a different VAAPI encoder from the same family, so frames continue to be encoded on the Intel Media Engine — only the bitstream codec ID changes, and Encoder.cpp propagates that through codec_context->codec_id = av_codec->id, so the MP4 muxer writes the correct sample entries.
The reason this cannot simply be dropped today is that torchcodec's initialize_video_stream unconditionally invokes our setup_hardware_frame_context_for_encoding, which forces pix_fmt = AV_PIX_FMT_VAAPI and attaches an AVHWFramesContext. When find_codec returns nullopt, torchcodec falls back to avcodec_find_encoder() — a software encoder (e.g. libx264) — and avcodec_open2 then rejects the VAAPI pixel format with AVERROR(EINVAL) ("Invalid argument"), which is exactly the reproduced failure.
RuntimeError: initialize_video_stream, /__w/torchcodec/torchcodec/meta-pytorch/torchcodec/src/torchcodec/_core/Encoder.cpp:500, avcodec_open2 failed: Invalid argument
There was a problem hiding this comment.
When find_codec returns nullopt
This is in the assumption that ffmpeg was built without h264_vaapi, right? find_codec should not return nullopt if ffmpeg was built with h264_vaapi, correct?
…e clarity. Update patch file for test encoding to align with autoloader changes. Signed-off-by: Edgar Romo Montiel <edgar.romo.montiel@intel.com> Co-authored-by: Dmitry Rogozhkin <dmitry.v.rogozhkin@intel.com>
Adds a hardware video encoding path to the torchcodec-xpu plugin (supersedes #58)
What changes:
convert_tensor_to_av_frame_for_encoding dispatching to:
ColorConversionKernel.{h,cpp} — adds convertRGBToNV12 SYCL kernel (BT.601 / BT.709, limited + full range); get_tile_offset reused for encode.
patches/0002-Add-XPU-support-to-video-encoder-tests.patch — parametrizes upstream torchcodec encoder tests over CUDA + XPU, and primes the encoder with one frame in test_write_frames_different_devices_errors (VAAPI segfaults on empty flush; NVENC doesn't). Depends on 0001-Add-XPU-support-to-tests.patch.
Compatibility
No change to decode behavior, plugin loading, or public API.
Testing
Encoder test suite (patches 0001 + 0002) passes on Intel Arc / Battlemage.