Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions base/cvd/MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,28 @@ bazel_dep(name = "hedron_compile_commands", dev_dependency = True)

bazel_dep(name = "abseil-cpp", version = "20260107.0")
bazel_dep(name = "aspect_bazel_lib", version = "2.22.0")

bazel_dep(name = "hermetic_cc_toolchain", version = "4.0.1")

# Hermetic C/C++ toolchain using zig cc for cross-compilation and GLIBC targeting.
# Use with: bazel build ... --extra_toolchains=@zig_sdk//toolchain:linux_amd64_gnu.2.36
zig_toolchains = use_extension("@hermetic_cc_toolchain//toolchain:ext.bzl", "toolchains")
use_repo(zig_toolchains, "zig_sdk")

# CUDA support for NVENC (hermetic headers via redist_json, runtime dlopen)
bazel_dep(name = "rules_cuda", version = "0.3.0")
git_override(
module_name = "rules_cuda",
commit = "e10b718bc8d37abcb4c18d721806ef8ad74aa324",
remote = "https://github.com/bazel-contrib/rules_cuda.git",
)
cuda = use_extension("@rules_cuda//cuda:extensions.bzl", "toolchain")
cuda.redist_json(
name = "cuda_redist",
version = "12.6.3",
)
cuda.toolkit(name = "cuda")
use_repo(cuda, "cuda")
bazel_dep(name = "boringssl", version = "0.20241024.0")
bazel_dep(name = "buildifier_prebuilt", version = "8.5.1.2")
bazel_dep(name = "brotli")
Expand Down Expand Up @@ -64,3 +86,15 @@ include("//toolchain:buildifier.MODULE.bazel")
include("//toolchain:llvm.MODULE.bazel")
include("//toolchain:python.MODULE.bazel")
include("//toolchain:rust.MODULE.bazel")

# NVENC video encoding headers (nv-codec-headers SDK 12.1)
http_archive = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "nv_codec_headers",
build_file = "//build_external/nv_codec_headers:BUILD.nv_codec_headers.bazel",
strip_prefix = "nv-codec-headers-n12.1.14.0",
urls = [
"https://github.com/FFmpeg/nv-codec-headers/archive/refs/tags/n12.1.14.0.tar.gz",
],
sha256 = "2fefaa227d2a3b4170797796425a59d1dd2ed5fd231db9b4244468ba327acd0b",
)
1 change: 1 addition & 0 deletions base/cvd/build_external/build_external.MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ include("//build_external/bzip2:bzip2.MODULE.bazel")
include("//build_external/c-ares:c-ares.MODULE.bazel")
include("//build_external/casimir:casimir.MODULE.bazel")
include("//build_external/crc32c:crc32c.MODULE.bazel")
include("//build_external/dav1d:dav1d.MODULE.bazel")
include("//build_external/curl:curl.MODULE.bazel")
include("//build_external/crosvm:crosvm.MODULE.bazel")
include("//build_external/dosfstools:dosfstools.MODULE.bazel")
Expand Down
1 change: 1 addition & 0 deletions base/cvd/build_external/dav1d/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Empty BUILD file (package marker for Bazel)
73 changes: 73 additions & 0 deletions base/cvd/build_external/dav1d/BUILD.dav1d.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"],

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.

This seems backwards: shouldn't the target with hdrs be the one that is included elsewhere, and it can internally have deps on other targets that provide the sources?

Copy link
Copy Markdown
Collaborator

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.c has #include "dav1d/dav1d.h" and #include "dav1d/data.h")...And those includes only resolve through :dav1d_api's strip_include_prefix = "include". So afaik :dav1d (srcs) needs :dav1d_api (hdrs) to compile.

Inverting it (:dav1d_api as 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 headers
shouldn't be exported via includes/-isystem (it will cause a problem where config.h gets a shadowing conflict with libsrtp2 that this layout avoids). Consumers depend on @dav1d and get the API headers transitively, which also keeps the conventional @dav1d shorthand label working.

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.

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 .h files in its own srcs target as well. That doesn't solve the strip_include_prefix problem though.

Copy link
Copy Markdown
Collaborator

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 srcs and 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...

  • Headers listed in srcs are plain private files. So strip_include_prefix only applies to hdrs...So #include "dav1d/dav1d.h" in the sources won't resolve, only the literal "include/dav1d/dav1d.h" path would.
  • Rewriting the 21 public-header includes across 18 source files to "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.
  • A nonpropagating 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 the dav1d/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.

linkopts = ["-lpthread"],
)
74 changes: 74 additions & 0 deletions base/cvd/build_external/dav1d/dav1d.MODULE.bazel
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",
],
Comment thread
jemoreira marked this conversation as resolved.
sha256 = "e099f53253f6c247580c554d53a13f1040638f2066edc3c740e4c2f15174ce22",
patch_cmds = [

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.

This is a lot for patch_cmds. Is it possible to include the newly defined files as targets of build_external/dav1d that are referenced by the targets created in dav1d?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Well...the commands fall into two groups:

  • The three generated headers (dav1d_config.h, dav1d_vcs_version.h, include/dav1d/version.h) could become checked-in files underbuild_external/dav1d/, copied into the external repo by a small copy_file/genrule in BUILD.dav1d.bazel. That would work, they'd be reviewable as plain files but we have to do some rule plumbing then... (they have to be materialized inside the @dav1d repo for #include "dav1d_config.h" to resolve via -iquote).

  • The mv include/common src/common + sed include rewrites can't be afaik expressed as file targets. They modify the fetched sources. The only alternative is a conventional patches file, but since the rewrite touches an include line in nearly every file under src/, that patch would imho more brittle. The sed commands are at least self describing and survive version bumps.

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'",
],
)
3 changes: 3 additions & 0 deletions base/cvd/build_external/libwebrtc/BUILD.libwebrtc.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,7 @@ cc_library(
"modules/video_capture/video_capture_impl.cc",
"modules/video_coding/chain_diff_calculator.cc",
"modules/video_coding/codecs/av1/av1_svc_config.cc",
"modules/video_coding/codecs/av1/dav1d_decoder.cc",
"modules/video_coding/codecs/h264/h264.cc",
"modules/video_coding/codecs/h264/h264_color_space.cc",
"modules/video_coding/codecs/h264/h264_decoder_impl.cc",
Expand Down Expand Up @@ -3286,6 +3287,7 @@ cc_library(
"WEBRTC_APM_DEBUG_DUMP=0",
"WEBRTC_OPUS_VARIABLE_COMPLEXITY=0",
"USE_X11=1",
"RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY",
] + select({
"@platforms//cpu:arm": [
"HAVE_MM_PREFETCH=0",
Expand Down Expand Up @@ -3324,6 +3326,7 @@ cc_library(
"@crc32c",
"@libevent//:event",
"@libpffft",
"@dav1d",
"@libvpx",
"@libyuv",
"@protobuf",
Expand Down
9 changes: 9 additions & 0 deletions base/cvd/build_external/libwebrtc/PATCH.dav1d_include.patch
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"
5 changes: 4 additions & 1 deletion base/cvd/build_external/libwebrtc/libwebrtc.MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@ git_repository(
commit = "e093c481bf8fd8e141fee4c007d63da488ce0ef5",
build_file = "@//build_external/libwebrtc:BUILD.libwebrtc.bazel",
remote = "https://webrtc.googlesource.com/src/",
patches = ["@//build_external/libwebrtc:PATCH.third_party_libyuv.patch"],
patches = [
"@//build_external/libwebrtc:PATCH.third_party_libyuv.patch",
"@//build_external/libwebrtc:PATCH.dav1d_include.patch",
],
)
1 change: 1 addition & 0 deletions base/cvd/build_external/nv_codec_headers/BUILD.bazel
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"],
)
2 changes: 1 addition & 1 deletion base/cvd/cuttlefish/bazel/rules.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def _cf_cc_library_implementation(name, clang_format_enabled, clang_tidy_enabled
copts = (copts or []) + COPTS,
**kwargs
)
if clang_format_enabled:
if clang_format_enabled and (kwargs.get("srcs") or kwargs.get("hdrs")):
format_test(
name = name + "_format_test",
cc = "//tools/format:clang_format",
Expand Down
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

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.

What does this have to do with nvenc? It looks like this is the only change to vhost_user_input in this PR.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I had some issues with the CI itself...

My understanding is that grpcio-sys depends on libz-sys with features = ["static"]. The static feature makes libz-sys's build script compile zlib from vendored C sources in src/zlib/ ... But that directory is a git submodule that is not afaik included in the crates.io tarball (the published package contains like 13 files). So any build of that crate from a clean state fails.

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 main with a cold cache. This PR's MODULE.bazel changes invalidate that cache, so without the annotation the PR fails CI on a bug I (afaik) didn't introduce.

The annotation disables the broken build script and links the system zlib instead. It lives in vhost_user_input.MODULE.bazel (rather than netsim's or casimir's) because all three crate registries share the same crate_universe extension instance. So one annotation covers all three, and adding it to a second file errors with "duplicate annotation".

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",
Expand Down
15 changes: 15 additions & 0 deletions base/cvd/cuttlefish/host/frontend/webrtc/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,19 @@ proto_library(
deps = ["@googleapis//google/rpc:status_proto"],
)

cf_cc_library(
name = "libcuttlefish_webrtc_cvd_abgr_video_frame_buffer",
srcs = [
"cvd_abgr_video_frame_buffer.cpp",
],
hdrs = [
"cvd_abgr_video_frame_buffer.h",
],
deps = [
"//cuttlefish/host/libs/screen_connector:video_frame_buffer",
],
)

cc_proto_library(
name = "libcuttlefish_webrtc_commands_proto",
deps = [":webrtc_commands_proto"],
Expand Down Expand Up @@ -191,6 +204,7 @@ cf_cc_library(
hdrs = ["display_handler.h"],
depend_on_what_you_use_enabled = False,
deps = [
":libcuttlefish_webrtc_cvd_abgr_video_frame_buffer",
":libcuttlefish_webrtc_cvd_video_frame_buffer",
":libcuttlefish_webrtc_screenshot_handler",
"//cuttlefish/host/frontend/webrtc/libdevice:streamer",
Expand Down Expand Up @@ -351,6 +365,7 @@ cf_cc_binary(
":libcuttlefish_webrtc_command_channel",
":libcuttlefish_webrtc_commands_proto",
":libcuttlefish_webrtc_connection_observer",
":libcuttlefish_webrtc_cvd_abgr_video_frame_buffer",
":libcuttlefish_webrtc_cvd_video_frame_buffer",
":libcuttlefish_webrtc_display_handler",
":libcuttlefish_webrtc_gpx_locations_handler",
Expand Down
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
Loading
Loading