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
7 changes: 7 additions & 0 deletions base/cvd/BUILD.nv_codec_headers.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package(default_visibility = ["//visibility:public"])
Copy link
Member

Choose a reason for hiding this comment

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

Please move file into the build_external subdirectory.


cc_library(
name = "nv_headers",
hdrs = glob(["include/ffnvcodec/*.h"]),
includes = ["include/ffnvcodec"],
)
32 changes: 32 additions & 0 deletions base/cvd/MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,26 @@
###############################################################################

bazel_dep(name = "abseil-cpp", version = "20260107.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
bazel_dep(name = "rules_cuda", version = "0.2.5")
git_override(
module_name = "rules_cuda",
commit = "32414222a7997ee66035d51404fc5427df94c699",
remote = "https://github.com/bazel-contrib/rules_cuda.git",
)
cuda = use_extension("@rules_cuda//cuda:extensions.bzl", "toolchain")
cuda.local_toolchain(
Copy link
Member

Choose a reason for hiding this comment

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

I believe we'll need to make all of the nvenc providers dependent on cuda being available or not and to provide some kind of bazel flag to toggle it on.

As is, running

cd <my github checkout>
git fetch upstream pull/2240/head:nvenc
git switch nvenc
cd base/cvd
bazel run //cuttlefish/package:cvd -- create --host_substitutions=all

on a freshly re-imaged machine (and I imagine in CI will be similar) shows

ERROR: <PATH>/.cache/bazel/_bazel_natsu/7a91ee12fa7dab792b551f47ba02ef4f/external/rules_cuda++toolchain+local_cuda/BUILD: no such target '@@rules_cuda++toolchain+local_cuda//:cuda_runtime': target 'cuda_runtime' not declared in package '' defined by <PATH>/.cache/bazel/_bazel_natsu/7a91ee12fa7dab792b551f47ba02ef4f/external/rules_cuda++toolchain+local_cuda/BUILD

It looks like https://github.com/bazel-contrib/rules_cuda/tree/main/examples/if_cuda provides a mechanism.

For peer_connection_utils, you can have

    deps = [
       ...
    ] + select({
        "@rules_cuda//cuda:is_enabled": [
            ":av1_nvenc_encoder_provider",
            ":av1_nvenc_decoder_provider",
        ],
        "//conditions:default": [],
    }),

and then potentially add target_compatible_with = requires_cuda(), to all of the other *nvenc* targets.

I believe you would also have to add build -@rules_cuda//cuda:enable=False to the .bazelrc to set a default to keep all of the existing flows working.

name = "local_cuda",
toolkit_path = "",
)
use_repo(cuda, cuda = "local_cuda")
bazel_dep(name = "aspect_bazel_lib", version = "2.19.3")
bazel_dep(name = "aspect_rules_lint", version = "1.4.4", dev_dependency = True)
bazel_dep(name = "bazel_skylib", version = "1.8.2", dev_dependency = True)
Expand Down Expand Up @@ -65,3 +85,15 @@ include("//toolchain:bazel.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.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",
)
2 changes: 2 additions & 0 deletions base/cvd/cuttlefish/host/frontend/webrtc/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ cf_cc_binary(
"client_server.h",
"connection_observer.cpp",
"connection_observer.h",
"cvd_abgr_video_frame_buffer.cpp",
"cvd_abgr_video_frame_buffer.h",
"cvd_video_frame_buffer.cpp",
"cvd_video_frame_buffer.h",
"display_handler.cpp",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (C) 2025 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 <cstring>

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) {
// Allocate buffer: height * stride
size_t size = height * stride;
data_.resize(size);
if (data) {
std::memcpy(data_.data(), data, size);
}
}

std::unique_ptr<VideoFrameBuffer> CvdAbgrVideoFrameBuffer::Clone() const {
return std::make_unique<CvdAbgrVideoFrameBuffer>(*this);
}

} // namespace cuttlefish
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2025 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.
*/

#pragma once

#include <cstdint>
#include <vector>

#include "cuttlefish/host/libs/screen_connector/video_frame_buffer.h"

namespace cuttlefish {

class CvdAbgrVideoFrameBuffer : public VideoFrameBuffer {
public:
CvdAbgrVideoFrameBuffer(int width, int height, uint32_t format, int stride,
const uint8_t* data);
~CvdAbgrVideoFrameBuffer() override = default;

int width() const override { return width_; }
int height() const override { return height_; }

uint8_t* Data() const override { return const_cast<uint8_t*>(data_.data()); }
int Stride() const override { return stride_; }
std::size_t DataSize() const override { return data_.size(); }
uint32_t PixelFormat() const override { return format_; }

std::unique_ptr<VideoFrameBuffer> Clone() const override;

private:
int width_;
int height_;
uint32_t format_;
int stride_;
std::vector<uint8_t> data_;
};

} // namespace cuttlefish
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,8 @@ int CvdVideoFrameBuffer::StrideV() const {
return AlignStride((width_ + 1) / 2);
}

std::unique_ptr<VideoFrameBuffer> CvdVideoFrameBuffer::Clone() const {
return std::make_unique<CvdVideoFrameBuffer>(*this);
}

} // namespace cuttlefish
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ class CvdVideoFrameBuffer : public VideoFrameBuffer {
size_t DataSizeU() const override { return u_.size(); }
size_t DataSizeV() const override { return v_.size(); }

std::unique_ptr<VideoFrameBuffer> Clone() const override;

private:
const int width_;
const int height_;
Expand Down
30 changes: 10 additions & 20 deletions base/cvd/cuttlefish/host/frontend/webrtc/display_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <libyuv.h>
#include "absl/log/log.h"

#include "cuttlefish/host/frontend/webrtc/cvd_abgr_video_frame_buffer.h"
#include "cuttlefish/host/frontend/webrtc/libdevice/streamer.h"
#include "cuttlefish/host/libs/screen_connector/composition_manager.h"
#include "cuttlefish/host/libs/screen_connector/video_frame_buffer.h"
Expand Down Expand Up @@ -104,28 +105,18 @@ DisplayHandler::GetScreenConnectorCallback() {
uint32_t frame_fourcc_format, uint32_t frame_stride_bytes,
uint8_t* frame_pixels, WebRtcScProcessedFrame& processed_frame) {
processed_frame.display_number_ = display_number;
processed_frame.buf_ =
std::make_unique<CvdVideoFrameBuffer>(frame_width, frame_height);
if (composition_manager.has_value()) {
composition_manager.value()->OnFrame(
display_number, frame_width, frame_height, frame_fourcc_format,
frame_stride_bytes, frame_pixels);
}
if (frame_fourcc_format == DRM_FORMAT_ARGB8888 ||
frame_fourcc_format == DRM_FORMAT_XRGB8888) {
libyuv::ARGBToI420(
frame_pixels, frame_stride_bytes, processed_frame.buf_->DataY(),
processed_frame.buf_->StrideY(), processed_frame.buf_->DataU(),
processed_frame.buf_->StrideU(), processed_frame.buf_->DataV(),
processed_frame.buf_->StrideV(), frame_width, frame_height);
processed_frame.is_success_ = true;
} else if (frame_fourcc_format == DRM_FORMAT_ABGR8888 ||
frame_fourcc_format == DRM_FORMAT_XBGR8888) {
libyuv::ABGRToI420(
frame_pixels, frame_stride_bytes, processed_frame.buf_->DataY(),
processed_frame.buf_->StrideY(), processed_frame.buf_->DataU(),
processed_frame.buf_->StrideU(), processed_frame.buf_->DataV(),
processed_frame.buf_->StrideV(), frame_width, frame_height);
frame_fourcc_format == DRM_FORMAT_XRGB8888 ||
frame_fourcc_format == DRM_FORMAT_ABGR8888 ||
frame_fourcc_format == DRM_FORMAT_XBGR8888) {
processed_frame.buf_ = std::make_unique<CvdAbgrVideoFrameBuffer>(
frame_width, frame_height, frame_fourcc_format, frame_stride_bytes,
frame_pixels);
processed_frame.is_success_ = true;
} else {
processed_frame.is_success_ = false;
Expand All @@ -138,7 +129,7 @@ DisplayHandler::GetScreenConnectorCallback() {
for (;;) {
auto processed_frame = screen_connector_.OnNextFrame();

std::shared_ptr<CvdVideoFrameBuffer> buffer =
std::shared_ptr<VideoFrameBuffer> buffer =
std::move(processed_frame.buf_);

const uint32_t display_number = processed_frame.display_number_;
Expand All @@ -147,7 +138,7 @@ DisplayHandler::GetScreenConnectorCallback() {
display_last_buffers_[display_number] =
std::make_shared<BufferInfo>(BufferInfo{
.last_sent_time_stamp = std::chrono::system_clock::now(),
.buffer = std::static_pointer_cast<VideoFrameBuffer>(buffer),
.buffer = buffer,
});
}
if (processed_frame.is_success_) {
Expand Down Expand Up @@ -255,8 +246,7 @@ void DisplayHandler::RepeatFramesPeriodically() {
buffer_info->last_sent_time_stamp + kRepeatingInterval) {
if (composition_manager_.has_value()) {
composition_manager_.value()->ComposeFrame(
display_number, std::static_pointer_cast<CvdVideoFrameBuffer>(
buffer_info->buffer));
display_number, buffer_info->buffer);
}
buffers[display_number] = buffer_info;
}
Expand Down
7 changes: 4 additions & 3 deletions base/cvd/cuttlefish/host/frontend/webrtc/display_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,13 @@ class CompositionManager;
*/
struct WebRtcScProcessedFrame : public ScreenConnectorFrameInfo {
// must support move semantic
std::unique_ptr<CvdVideoFrameBuffer> buf_;
std::unique_ptr<VideoFrameBuffer> buf_;
std::unique_ptr<WebRtcScProcessedFrame> Clone() {
// copy internal buffer, not move
CvdVideoFrameBuffer* new_buffer = new CvdVideoFrameBuffer(*(buf_.get()));
auto cloned_frame = std::make_unique<WebRtcScProcessedFrame>();
cloned_frame->buf_ = std::unique_ptr<CvdVideoFrameBuffer>(new_buffer);
if (buf_) {
cloned_frame->buf_ = buf_->Clone();
}
return cloned_frame;
}
};
Expand Down
Loading