Skip to content

Commit

Permalink
Adding an initial AV1 encoder implementation for CRD
Browse files Browse the repository at this point in the history
This is a simple CL which adds a do-nothing impl and the integration
points needed for instantiating an AV1 encoder instance from the
client. I'm splitting this up as there is a fair amount of overlap
in the logic needed for VPX and AV1 (perhaps not surprising) so I
wanted to get this piece in first and then refactor the VPX encoder
so more of it can be shared between these two SW encoders.

Bug: b:217468304
Change-Id: I51f0cf6248f091332389cc9ddc3d0faa84f59a68
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3633114
Commit-Queue: Joe Downing <joedow@chromium.org>
Reviewed-by: James Zern <jzern@google.com>
Reviewed-by: Lambros Lambrou <lambroslambrou@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1002876}
  • Loading branch information
joedow-42 authored and Chromium LUCI CQ committed May 12, 2022
1 parent 38b715e commit 98f2479
Show file tree
Hide file tree
Showing 11 changed files with 133 additions and 26 deletions.
1 change: 1 addition & 0 deletions remoting/DEPS
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ include_rules = [
"-remoting",
"+remoting/base",
"+remoting/proto",
"+third_party/libaom",
"+third_party/libvpx",
"+third_party/libyuv",
"+third_party/webrtc/api",
Expand Down
3 changes: 3 additions & 0 deletions remoting/codec/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ source_set("encoder") {
"video_encoder_vpx.cc",
"video_encoder_vpx.h",
"webrtc_video_encoder.cc",
"webrtc_video_encoder_av1.cc",
"webrtc_video_encoder_av1.h",
"webrtc_video_encoder_proxy.cc",
"webrtc_video_encoder_proxy.h",
"webrtc_video_encoder_selector.cc",
Expand All @@ -35,6 +37,7 @@ source_set("encoder") {
"//remoting/base:base",
"//remoting/proto",
"//remoting/protocol:session_config",
"//third_party/libaom",
"//third_party/libvpx",
"//third_party/libyuv",
"//third_party/opus",
Expand Down
6 changes: 3 additions & 3 deletions remoting/codec/webrtc_video_encoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,14 @@ class WebrtcVideoEncoder {
// If set to true then the active map passed to the encoder will only
// contain updated_region() from the current frame. Otherwise the active map
// is not cleared before adding updated_region(), which means it will
// contain union of updated_region() from all frames since this flag was
// contain a union of updated_region() from all frames since this flag was
// last set. This flag is used to top-off video quality with VP8.
bool clear_active_map = false;

// Indicates that the encoder should encode this frame as a key frame.
bool key_frame = false;

// Target FPS. < 0 means unset.
// Target FPS. A value less than 0 means unset.
int fps = -1;

// Quantization parameters for the encoder.
Expand Down Expand Up @@ -118,7 +118,7 @@ class WebrtcVideoEncoder {
// there is no work to do. |frame| may be nullptr, which is equivalent to a
// frame with an empty updated_region(). |done| callback may be called
// synchronously. It must not be called if the encoder is destroyed while
// request is pending.
// the request is pending.
virtual void Encode(std::unique_ptr<webrtc::DesktopFrame> frame,
const FrameParams& param,
EncodeCallback done) = 0;
Expand Down
39 changes: 39 additions & 0 deletions remoting/codec/webrtc_video_encoder_av1.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2022 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "remoting/codec/webrtc_video_encoder_av1.h"

#include "base/callback.h"
#include "base/notreached.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"

namespace remoting {

namespace {

void DestroyAomCodecContext(aom_codec_ctx_t* codec_ctx) {
// Codec has been initialized so we need to destroy it.
auto error = aom_codec_destroy(codec_ctx);
DCHECK_EQ(error, AOM_CODEC_OK);
delete codec_ctx;
}

} // namespace

WebrtcVideoEncoderAV1::WebrtcVideoEncoderAV1()
: codec_(nullptr, DestroyAomCodecContext) {}
WebrtcVideoEncoderAV1::~WebrtcVideoEncoderAV1() = default;

void WebrtcVideoEncoderAV1::SetLosslessEncode(bool want_lossless) {}

void WebrtcVideoEncoderAV1::SetLosslessColor(bool want_lossless) {}

void WebrtcVideoEncoderAV1::Encode(std::unique_ptr<webrtc::DesktopFrame> frame,
const FrameParams& params,
EncodeCallback done) {
NOTIMPLEMENTED();
std::move(done).Run(EncodeResult::UNKNOWN_ERROR, nullptr);
}

} // namespace remoting
40 changes: 40 additions & 0 deletions remoting/codec/webrtc_video_encoder_av1.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright 2022 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef REMOTING_CODEC_WEBRTC_VIDEO_ENCODER_AV1_H_
#define REMOTING_CODEC_WEBRTC_VIDEO_ENCODER_AV1_H_

#include "base/callback.h"
#include "remoting/codec/webrtc_video_encoder.h"
#include "third_party/libaom/source/libaom/aom/aom_encoder.h"
#include "third_party/libaom/source/libaom/aom/aomcx.h"

namespace remoting {

// AV1 encoder implementation for WebRTC transport, params are optimized for
// real-time screen sharing.
class WebrtcVideoEncoderAV1 : public WebrtcVideoEncoder {
public:
WebrtcVideoEncoderAV1();
WebrtcVideoEncoderAV1(const WebrtcVideoEncoderAV1&) = delete;
WebrtcVideoEncoderAV1& operator=(const WebrtcVideoEncoderAV1&) = delete;
~WebrtcVideoEncoderAV1() override;

// WebrtcVideoEncoder interface.
void SetLosslessEncode(bool want_lossless) override;
void SetLosslessColor(bool want_lossless) override;
void Encode(std::unique_ptr<webrtc::DesktopFrame> frame,
const FrameParams& params,
EncodeCallback done) override;

private:
using aom_codec_unique_ptr =
std::unique_ptr<aom_codec_ctx_t, void (*)(aom_codec_ctx_t*)>;

aom_codec_unique_ptr codec_;
};

} // namespace remoting

#endif // REMOTING_CODEC_WEBRTC_VIDEO_ENCODER_AV1_H_
4 changes: 4 additions & 0 deletions remoting/protocol/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,10 @@ static_library("protocol") {
]
}

if (is_debug) {
defines += [ "USE_AV1_ENCODER" ]
}

if (enable_remoting_host) {
sources += [
"audio_pump.cc",
Expand Down
33 changes: 16 additions & 17 deletions remoting/protocol/content_description.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@
using jingle_xmpp::QName;
using jingle_xmpp::XmlElement;

namespace remoting {
namespace protocol {
namespace remoting::protocol {

const char ContentDescription::kChromotingContentName[] = "chromoting";

Expand All @@ -41,20 +40,21 @@ const char kVersionAttr[] = "version";
const char kCodecAttr[] = "codec";

const NameMapElement<ChannelConfig::TransportType> kTransports[] = {
{ ChannelConfig::TRANSPORT_STREAM, "stream" },
{ ChannelConfig::TRANSPORT_MUX_STREAM, "mux-stream" },
{ ChannelConfig::TRANSPORT_DATAGRAM, "datagram" },
{ ChannelConfig::TRANSPORT_NONE, "none" },
{ChannelConfig::TRANSPORT_STREAM, "stream"},
{ChannelConfig::TRANSPORT_MUX_STREAM, "mux-stream"},
{ChannelConfig::TRANSPORT_DATAGRAM, "datagram"},
{ChannelConfig::TRANSPORT_NONE, "none"},
};

const NameMapElement<ChannelConfig::Codec> kCodecs[] = {
{ ChannelConfig::CODEC_VERBATIM, "verbatim" },
{ ChannelConfig::CODEC_VP8, "vp8" },
{ ChannelConfig::CODEC_VP9, "vp9" },
{ ChannelConfig::CODEC_H264, "h264" },
{ ChannelConfig::CODEC_ZIP, "zip" },
{ ChannelConfig::CODEC_OPUS, "opus" },
{ ChannelConfig::CODEC_SPEEX, "speex" },
{ChannelConfig::CODEC_VERBATIM, "verbatim"},
{ChannelConfig::CODEC_VP8, "vp8"},
{ChannelConfig::CODEC_VP9, "vp9"},
{ChannelConfig::CODEC_H264, "h264"},
{ChannelConfig::CODEC_ZIP, "zip"},
{ChannelConfig::CODEC_OPUS, "opus"},
{ChannelConfig::CODEC_SPEEX, "speex"},
{ChannelConfig::CODEC_AV1, "av1"},
};

// Format a channel configuration tag for chromotocol session description,
Expand Down Expand Up @@ -171,8 +171,8 @@ XmlElement* ContentDescription::ToXml() const {
}

// static
// Adds the channel configs corresponding to |tag_name|,
// found in |element|, to |configs|.
// Adds the channel configs corresponding to |tag_name|, found in |element|, to
// |configs|.
bool ContentDescription::ParseChannelConfigs(
const XmlElement* const element,
const char tag_name[],
Expand Down Expand Up @@ -232,5 +232,4 @@ std::unique_ptr<ContentDescription> ContentDescription::ParseXml(
std::move(config), std::move(authenticator_message)));
}

} // namespace protocol
} // namespace remoting
} // namespace remoting::protocol
5 changes: 3 additions & 2 deletions remoting/protocol/session_config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,10 @@ std::unique_ptr<SessionConfig> SessionConfig::SelectCommon(

std::list<ChannelConfig> host_video_configs = host_config->video_configs();
host_video_configs.remove_if([](const ChannelConfig& config) {
// Older ICE-based clients do not support VP9 or H.264 so remove them.
// Older ICE-based clients do not support VP9, H.264, or AV1 so remove them.
return config.codec == ChannelConfig::CODEC_H264 ||
config.codec == ChannelConfig::CODEC_VP9;
config.codec == ChannelConfig::CODEC_VP9 ||
config.codec == ChannelConfig::CODEC_AV1;
});

if (!SelectCommonChannelConfig(host_config->control_configs(),
Expand Down
1 change: 1 addition & 0 deletions remoting/protocol/session_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ struct ChannelConfig {
CODEC_H264,
CODEC_OPUS,
CODEC_SPEEX,
CODEC_AV1,
};

// Creates a config with transport field set to TRANSPORT_NONE which indicates
Expand Down
3 changes: 3 additions & 0 deletions remoting/protocol/webrtc_video_encoder_factory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ WebrtcVideoEncoderFactory::WebrtcVideoEncoderFactory()
formats_.push_back(webrtc::SdpVideoFormat("H264"));
}
#endif
#if defined(USE_AV1_ENCODER)
formats_.push_back(webrtc::SdpVideoFormat("AV1"));
#endif
}

WebrtcVideoEncoderFactory::~WebrtcVideoEncoderFactory() = default;
Expand Down
24 changes: 20 additions & 4 deletions remoting/protocol/webrtc_video_encoder_wrapper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,11 @@
#include "remoting/codec/webrtc_video_encoder_gpu.h"
#endif

namespace remoting {
namespace protocol {
#if defined(USE_AV1_ENCODER)
#include "remoting/codec/webrtc_video_encoder_av1.h"
#endif

namespace remoting::protocol {

namespace {

Expand Down Expand Up @@ -116,6 +119,14 @@ WebrtcVideoEncoderWrapper::WebrtcVideoEncoderWrapper(
encoder_ = WebrtcVideoEncoderGpu::CreateForH264();
#else
NOTIMPLEMENTED();
#endif
break;
case webrtc::kVideoCodecAV1:
#if defined(USE_AV1_ENCODER)
VLOG(0) << "Creating AV1 encoder.";
encoder_ = std::make_unique<WebrtcVideoEncoderAV1>();
#else
NOTIMPLEMENTED();
#endif
break;
default:
Expand Down Expand Up @@ -393,6 +404,12 @@ WebrtcVideoEncoderWrapper::ReturnEncodedFrame(
webrtc::H264PacketizationMode::NonInterleaved;
#else
NOTREACHED();
#endif
} else if (frame.codec == webrtc::kVideoCodecAV1) {
#if defined(USE_AV1_ENCODER)
// TODO(joedow): Set codec specific params for AV1 here.
#else
NOTREACHED();
#endif
} else {
NOTREACHED();
Expand Down Expand Up @@ -502,5 +519,4 @@ bool WebrtcVideoEncoderWrapper::ShouldDropQualityForLargeFrame(
return should_drop_quality;
}

} // namespace protocol
} // namespace remoting
} // namespace remoting::protocol

0 comments on commit 98f2479

Please sign in to comment.