-
Notifications
You must be signed in to change notification settings - Fork 222
Reapply "Add NVENC AV1 hardware video encoding for WebRTC" #2863
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| # Empty BUILD file (package marker for Bazel) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| load("@rules_cc//cc:cc_library.bzl", "cc_library") | ||
|
|
||
| package(default_visibility = ["//visibility:public"]) | ||
|
|
||
| # dav1d 1.5.3 AV1 decoder (BSD-2-Clause). Pure C, no ASM, 8-bit only. | ||
| # | ||
| # Internal headers (include/common/, include/compat/) are moved into | ||
| # src/ by patch_cmds in dav1d.MODULE.bazel to avoid leaking -isystem | ||
| # paths that shadow other libraries' headers (e.g. libsrtp2). | ||
| # Public API is exposed via strip_include_prefix. | ||
| cc_library( | ||
| name = "dav1d_api", | ||
| hdrs = glob(["include/dav1d/*.h"]), | ||
| strip_include_prefix = "include", | ||
| ) | ||
|
|
||
| cc_library( | ||
| name = "dav1d", | ||
| srcs = [ | ||
| "dav1d_config.h", | ||
| "dav1d_vcs_version.h", | ||
| "src/cdf.c", | ||
| "src/cpu.c", | ||
| "src/ctx.c", | ||
| "src/data.c", | ||
| "src/decode.c", | ||
| "src/dequant_tables.c", | ||
| "src/getbits.c", | ||
| "src/intra_edge.c", | ||
| "src/itx_1d.c", | ||
| "src/lf_mask.c", | ||
| "src/lib.c", | ||
| "src/log.c", | ||
| "src/mem.c", | ||
| "src/msac.c", | ||
| "src/obu.c", | ||
| "src/pal.c", | ||
| "src/picture.c", | ||
| "src/qm.c", | ||
| "src/ref.c", | ||
| "src/refmvs.c", | ||
| "src/scan.c", | ||
| "src/tables.c", | ||
| "src/thread_task.c", | ||
| "src/warpmv.c", | ||
| "src/wedge.c", | ||
| "src/cdef_apply_tmpl.c", | ||
| "src/cdef_tmpl.c", | ||
| "src/fg_apply_tmpl.c", | ||
| "src/filmgrain_tmpl.c", | ||
| "src/ipred_prepare_tmpl.c", | ||
| "src/ipred_tmpl.c", | ||
| "src/itx_tmpl.c", | ||
| "src/lf_apply_tmpl.c", | ||
| "src/loopfilter_tmpl.c", | ||
| "src/looprestoration_tmpl.c", | ||
| "src/lr_apply_tmpl.c", | ||
| "src/mc_tmpl.c", | ||
| "src/recon_tmpl.c", | ||
| ] + glob([ | ||
| "src/*.h", | ||
| "src/common/*.h", | ||
| "include/compat/*.h", | ||
| ]), | ||
| copts = [ | ||
| "-std=c11", | ||
| "-D_GNU_SOURCE", | ||
| "-DBITDEPTH=8", | ||
| ], | ||
| # No `includes` — internal headers resolve via -iquote only. | ||
| deps = [":dav1d_api"], | ||
| linkopts = ["-lpthread"], | ||
| ) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| http_archive = use_repo_rule( | ||
| "@bazel_tools//tools/build_defs/repo:http.bzl", | ||
| "http_archive", | ||
| ) | ||
|
|
||
| http_archive( | ||
| name = "dav1d", | ||
| build_file = "@//build_external/dav1d:BUILD.dav1d.bazel", | ||
| strip_prefix = "dav1d-1.5.3", | ||
| urls = [ | ||
| "https://code.videolan.org/videolan/dav1d/-/archive/1.5.3/dav1d-1.5.3.tar.bz2", | ||
| ], | ||
|
jemoreira marked this conversation as resolved.
|
||
| sha256 = "e099f53253f6c247580c554d53a13f1040638f2066edc3c740e4c2f15174ce22", | ||
| patch_cmds = [ | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a lot for
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well...the commands fall into two groups:
How do you want to do it? |
||
| # Generate config.h with a dav1d-specific name to avoid | ||
| # shadowing other libraries' config.h (e.g., libsrtp2) via | ||
| # Bazel's transitive -iquote paths. | ||
| """cat > dav1d_config.h << 'ENDOFFILE' | ||
| #ifndef DAV1D_CONFIG_H_ | ||
| #define DAV1D_CONFIG_H_ | ||
| #define ARCH_AARCH64 0 | ||
| #define ARCH_ARM 0 | ||
| #define ARCH_LOONGARCH 0 | ||
| #define ARCH_PPC64LE 0 | ||
| #define ARCH_RISCV 0 | ||
| #define ARCH_X86 0 | ||
| #define ARCH_X86_32 0 | ||
| #define ARCH_X86_64 0 | ||
| #define CONFIG_8BPC 1 | ||
| #define CONFIG_16BPC 0 | ||
| #define CONFIG_LOG 0 | ||
| #define ENDIANNESS_BIG 0 | ||
| #define HAVE_ASM 0 | ||
| #define HAVE_AVX512ICL 0 | ||
| #define HAVE_CLOCK_GETTIME 1 | ||
| #define HAVE_DLSYM 1 | ||
| #define HAVE_POSIX_MEMALIGN 1 | ||
| #define HAVE_UNISTD_H 1 | ||
| #define STACK_ALIGNMENT 16 | ||
| #define UNICODE 0 | ||
| #endif | ||
| ENDOFFILE""", | ||
| # Generate vcs_version.h (also renamed to avoid shadowing) | ||
| """cat > dav1d_vcs_version.h << 'ENDOFFILE' | ||
| #ifndef DAV1D_VCS_VERSION_H_ | ||
| #define DAV1D_VCS_VERSION_H_ | ||
| #define DAV1D_VERSION "1.5.3" | ||
| #endif | ||
| ENDOFFILE""", | ||
| # Generate version.h in the public headers directory | ||
| """cat > include/dav1d/version.h << 'ENDOFFILE' | ||
| #ifndef DAV1D_VERSION_H_ | ||
| #define DAV1D_VERSION_H_ | ||
| #define DAV1D_API_VERSION_MAJOR 7 | ||
| #define DAV1D_API_VERSION_MINOR 0 | ||
| #define DAV1D_API_VERSION_PATCH 0 | ||
| #endif | ||
| ENDOFFILE""", | ||
| # Move include/common/ into src/common/ so that internal | ||
| # headers resolve via Bazel's automatic -iquote <repo_root> | ||
| # without needing includes=["include"] which would leak | ||
| # include/common/ and include/compat/ to all transitive | ||
| # dependents via -isystem, causing header conflicts. | ||
| "mv include/common src/common", | ||
| # Patch #include "common/..." to #include "src/common/..." | ||
| # in all source and header files under src/ (including the | ||
| # just-moved src/common/ headers themselves). | ||
| "find src -name '*.c' -o -name '*.h' | xargs sed -i 's|#include \"common/|#include \"src/common/|g'", | ||
| # Rename config.h and vcs_version.h includes to the | ||
| # dav1d-prefixed names to match the generated files above. | ||
| "find src -name '*.c' -o -name '*.h' | xargs sed -i 's|#include \"config.h\"|#include \"dav1d_config.h\"|g'", | ||
| "find src -name '*.c' -o -name '*.h' | xargs sed -i 's|#include \"vcs_version.h\"|#include \"dav1d_vcs_version.h\"|g'", | ||
| ], | ||
| ) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| diff --git modules/video_coding/codecs/av1/dav1d_decoder.cc modules/video_coding/codecs/av1/dav1d_decoder.cc | ||
| --- modules/video_coding/codecs/av1/dav1d_decoder.cc | ||
| +++ modules/video_coding/codecs/av1/dav1d_decoder.cc | ||
| @@ -30,4 +30,4 @@ | ||
| #include "modules/video_coding/include/video_error_codes.h" | ||
| #include "rtc_base/logging.h" | ||
| -#include "third_party/dav1d/libdav1d/include/dav1d/dav1d.h" | ||
| +#include <dav1d/dav1d.h> | ||
| #include "libyuv/convert.h" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| exports_files(["BUILD.nv_codec_headers.bazel"]) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| load("@rules_cc//cc:defs.bzl", "cc_library") | ||
|
|
||
| package(default_visibility = ["//visibility:public"]) | ||
|
|
||
| cc_library( | ||
| name = "nv_headers", | ||
| hdrs = glob(["include/ffnvcodec/*.h"]), | ||
| includes = ["include/ffnvcodec"], | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,18 @@ | ||
| vhost_user_input_crates = use_extension("@rules_rust//crate_universe:extensions.bzl", "crate") | ||
|
|
||
| # libz-sys with features=["static"] (required by grpcio-sys) tries to compile | ||
| # vendored zlib C sources from src/zlib/, but those sources live in a git | ||
| # submodule that is not included in the crates.io tarball. Disable the build | ||
| # script and link system zlib instead. | ||
| vhost_user_input_crates.annotation( | ||
|
Comment on lines
+3
to
+7
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does this have to do with nvenc? It looks like this is the only change to
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had some issues with the CI itself... My understanding is that The Cuttlefish CI doesn't normally hit this because the build script output is probably kept in the GitHub Actions disk cache. But I got the failure on a fresh clone of unmodified The annotation disables the broken build script and links the system zlib instead. It lives in |
||
| crate = "libz-sys", | ||
| gen_build_script = "off", | ||
| rustc_flags = [ | ||
| "-lz", | ||
| ], | ||
| crate_features = ["libc"], | ||
| ) | ||
|
|
||
| vhost_user_input_crates.from_cargo( | ||
| name = "vhost_user_input_crates", | ||
| cargo_config = "@//build_external/crosvm:crosvm.config.toml", | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| /* | ||
| * Copyright (C) 2026 The Android Open Source Project | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| #include "cuttlefish/host/frontend/webrtc/cvd_abgr_video_frame_buffer.h" | ||
|
|
||
| #include <string.h> | ||
|
|
||
| namespace cuttlefish { | ||
|
|
||
| CvdAbgrVideoFrameBuffer::CvdAbgrVideoFrameBuffer(int width, int height, | ||
| uint32_t format, int stride, | ||
| const uint8_t* data) | ||
| : width_(width), | ||
| height_(height), | ||
| format_(format), | ||
| stride_(stride), | ||
| data_(data, data + height * stride) {} | ||
|
|
||
| std::unique_ptr<VideoFrameBuffer> CvdAbgrVideoFrameBuffer::Clone() const { | ||
| return std::make_unique<CvdAbgrVideoFrameBuffer>(*this); | ||
| } | ||
|
|
||
| } // namespace cuttlefish |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems backwards: shouldn't the target with
hdrsbe the one that is included elsewhere, and it can internally havedepson other targets that provide the sources?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The direction is needed by a real compilation dependency, not just header re-export... dav1d's own sources include the public API headers (e.g.
src/lib.chas#include "dav1d/dav1d.h"and#include "dav1d/data.h")...And those includes only resolve through:dav1d_api'sstrip_include_prefix = "include". So afaik:dav1d(srcs) needs:dav1d_api(hdrs) to compile.Inverting it (
:dav1d_apias the public entry with an internal dep on a sources target) would make the sources target depend on the api target for its includes while the api target depends on it for linkage...Creating a cycle.So the split exists because the two file sets need different include path treatment. The public headers get
strip_include_prefix(consumers write#include <dav1d/dav1d.h>), while the internal headersshouldn't be exported via
includes/-isystem(it will cause a problem whereconfig.hgets a shadowing conflict with libsrtp2 that this layout avoids). Consumers depend on@dav1dand get the API headers transitively, which also keeps the conventional@dav1dshorthand label working.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding of bazel is that the same headers can be attributed to multiple targets, so the api target could have
hdrs, and the implementation target could list all of the.hfiles in its ownsrcstarget as well. That doesn't solve thestrip_include_prefixproblem though.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not by any means an expert on these things... But you're right in that multiple attribution is doable, so the impl target could carry the public headers in its own
srcsand the cycle goes away. But as you note, that still leaves the include path problem and I don't know if there's a clean mechanism for it...srcsare plain private files. Sostrip_include_prefixonly applies tohdrs...So#include "dav1d/dav1d.h"in the sources won't resolve, only the literal"include/dav1d/dav1d.h"path would."include/dav1d/..."via sed would work, but that would grow the patch command surface (which was already large :) )includes = ["include"]on the impl resolves it I think it would propagate-isystem include/to every transitive dependent, exposing the whole directory tree rather than the globbed header list...That would cause a leak similar to the config.h shadowing conflict with libsrtp2 that this layout exists to avoid.copts = ["-iquote", "external/.../include"]needs a hardcoded external repo path, which is brittle under bzlmod's repo name handling.So to me
deps = [":dav1d_api"]seems like the least bad way to hand the impl thedav1d/rooted include paths. Only the declared public headers are reachable, nothing leaks to dependents, and the impl consumes the api through the same contract external consumers do.