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"])

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(
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