Commit c7454d8df7 for ffmpeg
commit c7454d8df7676c9a5ce64b6a4159f292ed0793f6
Author: ArgaAAL <argalumunon9@gmail.com>
Date: Thu Sep 24 19:37:34 2026 +0000
avcodec/mfenc: set the current length of DXGI input buffers
Set the current length of the media buffer wrapping each D3D11 input
surface before adding it to the sample. On the tested Qualcomm H.264
Media Foundation encoder, the existing path fails in ProcessInput with
E_INVALIDARG, while the system-memory input path succeeds.
Query the surface buffer's maximum length and use it as its current
length, matching Chromium's approach for Qualcomm encoder interoperability:
https://chromium.googlesource.com/chromium/src/media/+/4d9f97945a34124faa4cd745dd6b1a7e015ef549/gpu/windows/media_foundation_video_encode_accelerator_win.cc#1147
Release the buffer and sample if either operation fails. The successful
ownership flow and the system-memory input path are unchanged.
Matched H.264 NV12 builds on bf9cb9f396c3 were tested on a Snapdragon 860
Windows ARM64 device, using moving 2560x1600 input at 60 fps and requested
CBR 20 Mbps with the Qualcomm hardware transform required. Unpatched D3D11
input failed with 0x80070057 and no output. Patched D3D11 and both
system-memory controls produced byte-identical streams with 120 nonempty
packets and 120 independently CPU-decoded frames. The four-case test was
repeated with the same result. Seven selected sample-free FATE tests passed
on the patched ARM64 build; this was not the full FATE suite.
At requested 1 Mbps, all three working paths produced 59 empty packets
and only 61 decoded frames, including unpatched system-memory input. That
separate limitation is not fixed by this change.
The proposed change and its test analysis were developed with substantial
AI assistance. This draft has not received human code review.
Signed-off-by: ArgaAAL <argalumunon9@gmail.com>
diff --git a/libavcodec/mfenc.c b/libavcodec/mfenc.c
index db3c1e10a3..27476bda6b 100644
--- a/libavcodec/mfenc.c
+++ b/libavcodec/mfenc.c
@@ -365,6 +365,7 @@ static int process_d3d11_frame(AVCodecContext *avctx, const AVFrame *frame, IMFS
ID3D11Texture2D *d3d11_texture = NULL;
IMFSample *sample = NULL;
IMFMediaBuffer *buffer = NULL;
+ DWORD buffer_length;
int subIdx = 0;
HRESULT hr;
@@ -399,6 +400,26 @@ static int process_d3d11_frame(AVCodecContext *avctx, const AVFrame *frame, IMFS
return AVERROR_EXTERNAL;
}
+ hr = IMFMediaBuffer_GetMaxLength(buffer, &buffer_length);
+ if (FAILED(hr)) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Failed to get DXGI surface buffer length: %s\n",
+ ff_hr_str(hr));
+ IMFMediaBuffer_Release(buffer);
+ IMFSample_Release(sample);
+ return AVERROR_EXTERNAL;
+ }
+
+ hr = IMFMediaBuffer_SetCurrentLength(buffer, buffer_length);
+ if (FAILED(hr)) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Failed to set DXGI surface buffer length: %s\n",
+ ff_hr_str(hr));
+ IMFMediaBuffer_Release(buffer);
+ IMFSample_Release(sample);
+ return AVERROR_EXTERNAL;
+ }
+
hr = IMFSample_AddBuffer(sample, buffer);
if (FAILED(hr)) {
av_log(avctx, AV_LOG_ERROR, "Failed to add buffer to sample: %s\n", ff_hr_str(hr));