Skip to content

Add wmf h265 support#133

Open
Bernini0 wants to merge 1 commit intowebrtc-sdk:mainfrom
Bernini0:wmf_h265
Open

Add wmf h265 support#133
Bernini0 wants to merge 1 commit intowebrtc-sdk:mainfrom
Bernini0:wmf_h265

Conversation

@Bernini0
Copy link
Copy Markdown
Contributor

Summary

Add H.265 (HEVC) hardware-accelerated encoding and decoding support on Windows
using the Media Foundation Transform (MFT) pipeline. This enables H.265 codec
negotiation and media processing through the OS-provided HEVC MFTs, which
delegate to GPU vendor hardware (NVENC/NVDEC, Intel QSV, AMD AMF) transparently.

Motivation

WebRTC M137 includes H.265 SDP/RTP infrastructure (rtc_use_h265=true) but
ships no encoder/decoder implementations. This PR fills that gap on Windows
without introducing any third-party codec dependencies.

Changes

New files (src/win/)

  • wmf_h265_encoder.h/.ccVideoEncoder implementation using HEVC encoder MFT
  • wmf_h265_decoder.h/.ccVideoDecoder implementation using HEVC decoder MFT
  • wmf_h265_factory.h/.cc — Decorator factories that add H.265 to the builtin codec list

Modified files

  • BUILD.gn — Conditionally compile WMF sources when is_win && !libwebrtc_intel_media_sdk && rtc_use_h265
  • src/rtc_peerconnection_factory_impl.cc — Wire WMF factories into CreatePeerConnectionFactory

Implementation details

  • Codec discovery: MFTEnumEx with MFT_ENUM_FLAG_HARDWARE | MFT_ENUM_FLAG_SORTANDFILTER to prefer HW-accelerated MFTs
  • Pixel format: I420 → NV12 conversion via libyuv (input), NV12/I420 → I420 (output)
  • Rate control: CBR mode via CODECAPI_AVEncCommonRateControlMode; dynamic bitrate updates via CODECAPI_AVEncCommonMeanBitRate
  • Keyframe requests: Forced IDR via CODECAPI_AVEncVideoForceKeyFrame
  • Low latency: MF_LOW_LATENCY attribute set on both encoder and decoder MFTs
  • QP reporting: H265BitstreamParser extracts per-frame QP into EncodedImage::qp_
  • Resolution alignment: Reports requested_resolution_alignment = 2 (NV12 requirement)
  • COM safety: CoInitializeEx is called in IsSupported() and InitMediaFoundation() so the code works regardless of whether the calling thread has COM initialized
  • Dynamic resolution change: Decoder handles MF_E_TRANSFORM_STREAM_CHANGE and updates cached dimensions from the new output media type
  • SDP parameters: Advertises Main profile (profile-id=1), Main tier (tier-flag=0), Level 4.0 (level-id=120)
  • Hardware acceleration: Both GetEncoderInfo() and GetDecoderInfo() report is_hardware_accelerated = true

Build flags

rtc_use_h265=true
proprietary_codecs=true
ffmpeg_branding="Chrome"

No additional flags required. The WMF path activates automatically on Windows when libwebrtc_intel_media_sdk is not set (default).

Requirements

  • Windows 10 1709+ with HEVC Video Extensions (free from Microsoft Store for OEMs, or $0.99 for HEVC Video Extensions from Device Manufacturer)
  • GPU with HEVC encode/decode support (NVIDIA Kepler+, Intel Skylake+, AMD Polaris+)

@orchidflower
Copy link
Copy Markdown

@Bernini0 Hi, thank you for providing this patch. I tried it with webrtc m137, it worked. :)

But when I tried to compile it with webrtc m144, it failed. Can you provide new patch to fix this? Thanks!

Here is the error messages:

E:\work\libwebrtc_m144\src>ninja -C out-release/Windows-x64 libwebrtc ninja: Entering directory out-release/Windows-x64'
[4339/4347] CXX obj/libwebrtc/libwebrtc/wmf_h265_encoder.obj
FAILED: [code=1] obj/libwebrtc/libwebrtc/wmf_h265_encoder.obj
....\third_party\llvm-build\Release+Asserts\bin\clang-cl.exe /c ../../libwebrtc/src/win/wmf_h265_encoder.cc /Foobj/libwebrtc/libwebrtc/wmf_h265_encoder.obj /nologo /showIncludes:user "-imsvcC:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\include" "-imsvcC:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\ATLMFC\include" "-imsvcC:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\VS\include" "-imsvcC:\Program Files (x86)\Windows Kits\10\include\10.0.26100.0\ucrt" "-imsvcC:\Program Files (x86)\Windows Kits\10\include\10.0.26100.0\um" "-imsvcC:\Program Files (x86)\Windows Kits\10\include\10.0.26100.0\shared" "-imsvcC:\Program Files (x86)\Windows Kits\10\include\10.0.26100.0\winrt" "-imsvcC:\Program Files (x86)\Windows Kits\10\include\10.0.26100.0\cppwinrt" "-imsvcC:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um" -DUSE_LIBYUV -DWEBRTC_INCLUDE_INTERNAL_AUDIO_DEVICE -DLIB_WEBRTC_API_EXPORTS -DWEBRTC_WIN -DRTC_DESKTOP_DEVICE -D_HAS_NODISCARD -D_CRT_NONSTDC_NO_WARNINGS -D_WINSOCK_DEPRECATED_NO_WARNINGS "-DCR_CLANG_REVISION="llvmorg-22-init-14273-gea10026b-2"" -D_LIBCPP_HARDENING_MODE=LIBCPP_HARDENING_MODE_EXTENSIVE -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS -D_LIBCPP_INSTRUMENTED_WITH_ASAN=0 -DCR_LIBCXX_REVISION=fa224989fd9c52f68042d7fd6824302c33cb68c0 -D__STD_C -D_CRT_RAND_S -D_CRT_SECURE_NO_DEPRECATE -D_SCL_SECURE_NO_DEPRECATE -D_ATL_NO_OPENGL -D_WINDOWS -DCERT_CHAIN_PARA_HAS_EXTRA_FIELDS -DPSAPI_VERSION=2 -DWIN32 -D_SECURE_ATL -DWINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP -DUSE_AURA=1 -DWIN32_LEAN_AND_MEAN -DNOMINMAX -D_UNICODE -DUNICODE -DNTDDI_VERSION=NTDDI_WIN11_GE -D_WIN32_WINNT=0x0A00 -DWINVER=0x0A00 -DNDEBUG -DNVALGRIND -DDYNAMIC_ANNOTATIONS_ENABLED=0 -DWEBRTC_ENABLE_PROTOBUF=1 -DWEBRTC_STRICT_FIELD_TRIALS=0 -DRTC_ENABLE_VP9 -DRTC_ENABLE_H265 -DRTC_DAV1D_IN_INTERNAL_DECODER_FACTORY -DWEBRTC_HAVE_SCTP -DWEBRTC_USE_H264 -DWEBRTC_ENCODER_PSNR_STATS -DPROTOBUF_ENABLE_DEBUG_LOGGING_MAY_LEAK_PII=0 -DWEBRTC_ENABLE_AVX2 -DRTC_ENABLE_WIN_WGC -DWEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0 -DABSL_ALLOCATOR_NOTHROW=1 -DLIB_WEBRTC_API_DLL -DCHROMIUM -DLIBYUV_DISABLE_NEON -DLIBYUV_DISABLE_SVE -DLIBYUV_DISABLE_SME -DLIBYUV_DISABLE_LSX -DLIBYUV_DISABLE_LASX -DHAVE_WEBRTC_VIDEO -DMANGLE_JPEG_NAMES -I../../libwebrtc -I../../libwebrtc/include -I../.. -Igen -I../../buildtools/third_party/libc++ -I../../third_party/abseil-cpp -I../../third_party/perfetto/include -Igen/third_party/perfetto/build_config -Igen/third_party/perfetto -I../../third_party/libyuv/include -I../../third_party/boringssl/src/include -I../../third_party/libjpeg_turbo/src -Wno-microsoft-extra-qualification -Wno-reorder /W4 -Wimplicit-fallthrough -Wextra-semi -Wunreachable-code-aggressive -Wgnu -Wno-gnu-anonymous-struct -Wno-gnu-conditional-omitted-operand -Wno-gnu-include-next -Wno-gnu-label-as-value -Wno-gnu-redeclared-enum -Wno-gnu-statement-expression -Wno-gnu-zero-variadic-macro-arguments -Wno-zero-length-array -Wthread-safety -Wno-missing-field-initializers -Wno-unused-parameter -Wno-psabi -Wloop-analysis -Wno-unneeded-internal-declaration -Wno-cast-function-type -Wno-thread-safety-reference-return -Wno-nontrivial-memcall -Wno-uninitialized-const-pointer -Wno-nonportable-include-path -Wshadow /WX -fno-delete-null-pointer-checks /clang:-fno-strict-overflow -fno-ident /clang:-fno-math-errno -fcolor-diagnostics -fmerge-all-constants /Zc:sizedDealloc- -fcrash-diagnostics-dir=../../out/clang-crashreports -mllvm -instcombine-lower-dbg-declare=0 -mllvm -split-threshold-for-reg-with-hint=0 /clang:-ffp-contract=off -fcomplete-member-pointers /Gy /FS /bigobj /utf-8 /Zc:twoPhase -ffile-reproducible /D__WRL_ENABLE_FUNCTION_STATICS_ -fmsc-version=1934 -m64 -msse3 /Brepro -Wno-builtin-macro-redefined -D__DATE__= -D__TIME__= -D__TIMESTAMP__= -ffile-compilation-dir=. -no-canonical-prefixes -ftrivial-auto-var-init=pattern /O2 /clang:-O2 /Oy- /Zc:inline /Gw /Z7 -gno-codeview-command-line -mllvm -pick-merged-source-locations -gcodeview-ghash -gomit-unreferenced-methods -Xclang -fuse-ctor-homing -fsanitize=array-bounds -fsanitize-trap=array-bounds /guard:cf /MT -Wheader-hygiene -Wstring-conversion -Wtautological-overlap-compare -Wshadow -Wctad-maybe-unsupported -Wc++11-narrowing -Wundef -Wunused-lambda-capture /TP -Wno-invalid-offsetof -Wenum-compare-conditional -Wno-nullability-completeness /std:c++20 -Wno-trigraphs /GR- -I../../third_party/libc++/src/include /Fd"obj/libwebrtc/libwebrtc_cc.pdb"
../../libwebrtc/src/win/wmf_h265_encoder.cc(313,3): error: use of undeclared identifier 'rtc'
313 | rtc::scoped_refptr i420_buffer =
| ^
../../libwebrtc/src/win/wmf_h265_encoder.cc(313,22): error: 'I420BufferInterface' does not refer to a value
313 | rtc::scoped_refptr i420_buffer =
| ^
../..\api/video/video_frame_buffer.h(183,18): note: declared here
183 | class RTC_EXPORT I420BufferInterface : public PlanarYuv8Buffer {
| ^
../../libwebrtc/src/win/wmf_h265_encoder.cc(313,43): error: use of undeclared identifier 'i420_buffer'
313 | rtc::scoped_refptr i420_buffer =
| ^~~~~~~~~~~
../../libwebrtc/src/win/wmf_h265_encoder.cc(316,18): error: use of undeclared identifier 'i420_buffer'
316 | int y_stride = i420_buffer->StrideY();
| ^~~~~~~~~~~
../../libwebrtc/src/win/wmf_h265_encoder.cc(317,18): error: use of undeclared identifier 'i420_buffer'
317 | int u_stride = i420_buffer->StrideU();
| ^~~~~~~~~~~
../../libwebrtc/src/win/wmf_h265_encoder.cc(318,18): error: use of undeclared identifier 'i420_buffer'
318 | int v_stride = i420_buffer->StrideV();
| ^~~~~~~~~~~
../../libwebrtc/src/win/wmf_h265_encoder.cc(325,7): error: use of undeclared identifier 'i420_buffer'
325 | i420_buffer->DataY(), y_stride, i420_buffer->DataU(), u_stride,
| ^~~~~~~~~~~
../../libwebrtc/src/win/wmf_h265_encoder.cc(325,39): error: use of undeclared identifier 'i420_buffer'
325 | i420_buffer->DataY(), y_stride, i420_buffer->DataU(), u_stride,
| ^~~~~~~~~~~
../../libwebrtc/src/win/wmf_h265_encoder.cc(326,7): error: use of undeclared identifier 'i420_buffer'
326 | i420_buffer->DataV(), v_stride, nv12_buffer_.data(), width_,
| ^~~~~~~~~~~
../../libwebrtc/src/win/wmf_h265_encoder.cc(492,9): error: use of undeclared identifier 'rtc'
492 | rtc::ArrayView(data, data_length));
| ^
../../libwebrtc/src/win/wmf_h265_encoder.cc(492,24): error: expected expression
492 | rtc::ArrayView(data, data_length));
| ^
11 errors generated.
[4340/4347] CXX obj/libwebrtc/libwebrtc/wmf_h265_decoder.obj
FAILED: [code=1] obj/libwebrtc/libwebrtc/wmf_h265_decoder.obj
....\third_party\llvm-build\Release+Asserts\bin\clang-cl.exe /c ../../libwebrtc/src/win/wmf_h265_decoder.cc /Foobj/libwebrtc/libwebrtc/wmf_h265_decoder.obj /nologo /showIncludes:user "-imsvcC:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\include" "-imsvcC:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\ATLMFC\include" "-imsvcC:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\VS\include" "-imsvcC:\Program Files (x86)\Windows Kits\10\include\10.0.26100.0\ucrt" "-imsvcC:\Program Files (x86)\Windows Kits\10\include\10.0.26100.0\um" "-imsvcC:\Program Files (x86)\Windows Kits\10\include\10.0.26100.0\shared" "-imsvcC:\Program Files (x86)\Windows Kits\10\include\10.0.26100.0\winrt" "-imsvcC:\Program Files (x86)\Windows Kits\10\include\10.0.26100.0\cppwinrt" "-imsvcC:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um" -DUSE_LIBYUV -DWEBRTC_INCLUDE_INTERNAL_AUDIO_DEVICE -DLIB_WEBRTC_API_EXPORTS -DWEBRTC_WIN -DRTC_DESKTOP_DEVICE -D_HAS_NODISCARD -D_CRT_NONSTDC_NO_WARNINGS -D_WINSOCK_DEPRECATED_NO_WARNINGS "-DCR_CLANG_REVISION="llvmorg-22-init-14273-gea10026b-2"" -D_LIBCPP_HARDENING_MODE=LIBCPP_HARDENING_MODE_EXTENSIVE -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS -D_LIBCPP_INSTRUMENTED_WITH_ASAN=0 -DCR_LIBCXX_REVISION=fa224989fd9c52f68042d7fd6824302c33cb68c0 -D__STD_C -D_CRT_RAND_S -D_CRT_SECURE_NO_DEPRECATE -D_SCL_SECURE_NO_DEPRECATE -D_ATL_NO_OPENGL -D_WINDOWS -DCERT_CHAIN_PARA_HAS_EXTRA_FIELDS -DPSAPI_VERSION=2 -DWIN32 -D_SECURE_ATL -DWINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP -DUSE_AURA=1 -DWIN32_LEAN_AND_MEAN -DNOMINMAX -D_UNICODE -DUNICODE -DNTDDI_VERSION=NTDDI_WIN11_GE -D_WIN32_WINNT=0x0A00 -DWINVER=0x0A00 -DNDEBUG -DNVALGRIND -DDYNAMIC_ANNOTATIONS_ENABLED=0 -DWEBRTC_ENABLE_PROTOBUF=1 -DWEBRTC_STRICT_FIELD_TRIALS=0 -DRTC_ENABLE_VP9 -DRTC_ENABLE_H265 -DRTC_DAV1D_IN_INTERNAL_DECODER_FACTORY -DWEBRTC_HAVE_SCTP -DWEBRTC_USE_H264 -DWEBRTC_ENCODER_PSNR_STATS -DPROTOBUF_ENABLE_DEBUG_LOGGING_MAY_LEAK_PII=0 -DWEBRTC_ENABLE_AVX2 -DRTC_ENABLE_WIN_WGC -DWEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0 -DABSL_ALLOCATOR_NOTHROW=1 -DLIB_WEBRTC_API_DLL -DCHROMIUM -DLIBYUV_DISABLE_NEON -DLIBYUV_DISABLE_SVE -DLIBYUV_DISABLE_SME -DLIBYUV_DISABLE_LSX -DLIBYUV_DISABLE_LASX -DHAVE_WEBRTC_VIDEO -DMANGLE_JPEG_NAMES -I../../libwebrtc -I../../libwebrtc/include -I../.. -Igen -I../../buildtools/third_party/libc++ -I../../third_party/abseil-cpp -I../../third_party/perfetto/include -Igen/third_party/perfetto/build_config -Igen/third_party/perfetto -I../../third_party/libyuv/include -I../../third_party/boringssl/src/include -I../../third_party/libjpeg_turbo/src -Wno-microsoft-extra-qualification -Wno-reorder /W4 -Wimplicit-fallthrough -Wextra-semi -Wunreachable-code-aggressive -Wgnu -Wno-gnu-anonymous-struct -Wno-gnu-conditional-omitted-operand -Wno-gnu-include-next -Wno-gnu-label-as-value -Wno-gnu-redeclared-enum -Wno-gnu-statement-expression -Wno-gnu-zero-variadic-macro-arguments -Wno-zero-length-array -Wthread-safety -Wno-missing-field-initializers -Wno-unused-parameter -Wno-psabi -Wloop-analysis -Wno-unneeded-internal-declaration -Wno-cast-function-type -Wno-thread-safety-reference-return -Wno-nontrivial-memcall -Wno-uninitialized-const-pointer -Wno-nonportable-include-path -Wshadow /WX -fno-delete-null-pointer-checks /clang:-fno-strict-overflow -fno-ident /clang:-fno-math-errno -fcolor-diagnostics -fmerge-all-constants /Zc:sizedDealloc- -fcrash-diagnostics-dir=../../out/clang-crashreports -mllvm -instcombine-lower-dbg-declare=0 -mllvm -split-threshold-for-reg-with-hint=0 /clang:-ffp-contract=off -fcomplete-member-pointers /Gy /FS /bigobj /utf-8 /Zc:twoPhase -ffile-reproducible /D__WRL_ENABLE_FUNCTION_STATICS_ -fmsc-version=1934 -m64 -msse3 /Brepro -Wno-builtin-macro-redefined -D__DATE__= -D__TIME__= -D__TIMESTAMP__= -ffile-compilation-dir=. -no-canonical-prefixes -ftrivial-auto-var-init=pattern /O2 /clang:-O2 /Oy- /Zc:inline /Gw /Z7 -gno-codeview-command-line -mllvm -pick-merged-source-locations -gcodeview-ghash -gomit-unreferenced-methods -Xclang -fuse-ctor-homing -fsanitize=array-bounds -fsanitize-trap=array-bounds /guard:cf /MT -Wheader-hygiene -Wstring-conversion -Wtautological-overlap-compare -Wshadow -Wctad-maybe-unsupported -Wc++11-narrowing -Wundef -Wunused-lambda-capture /TP -Wno-invalid-offsetof -Wenum-compare-conditional -Wno-nullability-completeness /std:c++20 -Wno-trigraphs /GR- -I../../third_party/libc++/src/include /Fd"obj/libwebrtc/libwebrtc_cc.pdb"
../../libwebrtc/src/win/wmf_h265_decoder.cc(401,3): error: use of undeclared identifier 'rtc'
401 | rtc::scoped_refptr i420_buffer =
| ^
../../libwebrtc/src/win/wmf_h265_decoder.cc(401,22): error: 'I420Buffer' does not refer to a value
401 | rtc::scoped_refptr i420_buffer =
| ^
../..\api/video/i420_buffer.h(27,18): note: declared here
27 | class RTC_EXPORT I420Buffer : public I420BufferInterface {
| ^
../../libwebrtc/src/win/wmf_h265_decoder.cc(401,34): error: use of undeclared identifier 'i420_buffer'
401 | rtc::scoped_refptr i420_buffer =
| ^~~~~~~~~~~
../../libwebrtc/src/win/wmf_h265_decoder.cc(407,24): error: use of undeclared identifier 'i420_buffer'
407 | i420_buffer->MutableDataY(), i420_buffer->StrideY(),
| ^~~~~~~~~~~
../../libwebrtc/src/win/wmf_h265_decoder.cc(407,53): error: use of undeclared identifier 'i420_buffer'
407 | i420_buffer->MutableDataY(), i420_buffer->StrideY(),
| ^~~~~~~~~~~
../../libwebrtc/src/win/wmf_h265_decoder.cc(408,24): error: use of undeclared identifier 'i420_buffer'
408 | i420_buffer->MutableDataU(), i420_buffer->StrideU(),
| ^~~~~~~~~~~
../../libwebrtc/src/win/wmf_h265_decoder.cc(408,53): error: use of undeclared identifier 'i420_buffer'
408 | i420_buffer->MutableDataU(), i420_buffer->StrideU(),
| ^~~~~~~~~~~
../../libwebrtc/src/win/wmf_h265_decoder.cc(409,24): error: use of undeclared identifier 'i420_buffer'
409 | i420_buffer->MutableDataV(), i420_buffer->StrideV(),
| ^~~~~~~~~~~
../../libwebrtc/src/win/wmf_h265_decoder.cc(409,53): error: use of undeclared identifier 'i420_buffer'
409 | i420_buffer->MutableDataV(), i420_buffer->StrideV(),
| ^~~~~~~~~~~
../../libwebrtc/src/win/wmf_h265_decoder.cc(418,22): error: use of undeclared identifier 'i420_buffer'
418 | i420_buffer->MutableDataY(), i420_buffer->StrideY(),
| ^~~~~~~~~~~
../../libwebrtc/src/win/wmf_h265_decoder.cc(418,51): error: use of undeclared identifier 'i420_buffer'
418 | i420_buffer->MutableDataY(), i420_buffer->StrideY(),
| ^~~~~~~~~~~
../../libwebrtc/src/win/wmf_h265_decoder.cc(419,22): error: use of undeclared identifier 'i420_buffer'
419 | i420_buffer->MutableDataU(), i420_buffer->StrideU(),
| ^~~~~~~~~~~
../../libwebrtc/src/win/wmf_h265_decoder.cc(419,51): error: use of undeclared identifier 'i420_buffer'
419 | i420_buffer->MutableDataU(), i420_buffer->StrideU(),
| ^~~~~~~~~~~
../../libwebrtc/src/win/wmf_h265_decoder.cc(420,22): error: use of undeclared identifier 'i420_buffer'
420 | i420_buffer->MutableDataV(), i420_buffer->StrideV(),
| ^~~~~~~~~~~
../../libwebrtc/src/win/wmf_h265_decoder.cc(420,51): error: use of undeclared identifier 'i420_buffer'
420 | i420_buffer->MutableDataV(), i420_buffer->StrideV(),
| ^~~~~~~~~~~
../../libwebrtc/src/win/wmf_h265_decoder.cc(437,37): error: use of undeclared identifier 'i420_buffer'
437 | .set_video_frame_buffer(i420_buffer)
| ^~~~~~~~~~~
16 errors generated.
[4346/4347] CXX obj/libwebrtc/libwebrtc/rtc_desktop_media_list_impl.obj
ninja: build stopped: subcommand failed.`

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