Skip to content

Commit 2cadb6c

Browse files
committed
feat: support AV1 hardware encoding on Jetson
1 parent 3527e35 commit 2cadb6c

File tree

5 files changed

+87
-34
lines changed

5 files changed

+87
-34
lines changed

src/codecs/jetson/jetson_encoder.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ bool JetsonEncoder::CreateVideoEncoder() {
5757
if (ret < 0)
5858
ORIGINATE_ERROR("Could not set capture plane format");
5959

60+
if (dst_pix_fmt_ == V4L2_PIX_FMT_AV1) {
61+
ret = DisableAV1IVF();
62+
if (ret < 0)
63+
ORIGINATE_ERROR("Could not disable IVF headers for AV1 codec");
64+
}
65+
6066
ret = encoder_->setOutputPlaneFormat(src_pix_fmt_, width_, height_);
6167
if (ret < 0)
6268
ORIGINATE_ERROR("Could not set output plane format");
@@ -340,3 +346,20 @@ void JetsonEncoder::SendEOS() {
340346
ERROR_PRINT("Failed to qBuffer at encoder while sending eos");
341347
}
342348
}
349+
350+
uint32_t JetsonEncoder::DisableAV1IVF() {
351+
struct v4l2_ext_control control;
352+
struct v4l2_ext_controls ctrls;
353+
354+
memset(&control, 0, sizeof(control));
355+
memset(&ctrls, 0, sizeof(ctrls));
356+
357+
control.id = V4L2_CID_MPEG_VIDEOENC_AV1_HEADERS_WITH_FRAME;
358+
control.value = 0;
359+
360+
ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
361+
ctrls.count = 1;
362+
ctrls.controls = &control;
363+
364+
return encoder_->setExtControls(ctrls);
365+
}

src/codecs/jetson/jetson_encoder.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class JetsonEncoder : public IFrameProcessor {
4242
NvBuffer *shared_buffer, void *arg);
4343
void ConvertI420ToYUV420M(NvBuffer *nv_buffer,
4444
rtc::scoped_refptr<webrtc::I420BufferInterface> i420_buffer);
45+
uint32_t DisableAV1IVF();
4546
};
4647

4748
#endif

src/codecs/jetson/jetson_h264_encoder.cpp renamed to src/codecs/jetson/jetson_video_encoder.cpp

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
1-
#include "codecs/jetson/jetson_h264_encoder.h"
1+
#include "codecs/jetson/jetson_video_encoder.h"
22
#include "common/logging.h"
33
#include "common/v4l2_frame_buffer.h"
44

5-
std::unique_ptr<webrtc::VideoEncoder> JetsonH264Encoder::Create(Args args) {
6-
return std::make_unique<JetsonH264Encoder>(args);
5+
#include <modules/video_coding/include/video_codec_interface.h>
6+
7+
std::unique_ptr<webrtc::VideoEncoder> JetsonVideoEncoder::Create(Args args) {
8+
return std::make_unique<JetsonVideoEncoder>(args);
79
}
810

9-
JetsonH264Encoder::JetsonH264Encoder(Args args)
11+
JetsonVideoEncoder::JetsonVideoEncoder(Args args)
1012
: fps_adjuster_(args.fps),
1113
bitrate_adjuster_(.85, 1),
1214
callback_(nullptr) {}
1315

14-
int32_t JetsonH264Encoder::InitEncode(const webrtc::VideoCodec *codec_settings,
15-
const VideoEncoder::Settings &settings) {
16+
int32_t JetsonVideoEncoder::InitEncode(const webrtc::VideoCodec *codec_settings,
17+
const VideoEncoder::Settings &settings) {
1618
codec_ = *codec_settings;
1719
width_ = codec_settings->width;
1820
height_ = codec_settings->height;
@@ -21,25 +23,21 @@ int32_t JetsonH264Encoder::InitEncode(const webrtc::VideoCodec *codec_settings,
2123
encoded_image_.timing_.flags = webrtc::VideoSendTiming::TimingFrameFlags::kInvalid;
2224
encoded_image_.content_type_ = webrtc::VideoContentType::UNSPECIFIED;
2325

24-
if (codec_.codecType != webrtc::kVideoCodecH264) {
25-
return WEBRTC_VIDEO_CODEC_ERROR;
26-
}
27-
2826
return WEBRTC_VIDEO_CODEC_OK;
2927
}
3028

31-
int32_t JetsonH264Encoder::RegisterEncodeCompleteCallback(webrtc::EncodedImageCallback *callback) {
29+
int32_t JetsonVideoEncoder::RegisterEncodeCompleteCallback(webrtc::EncodedImageCallback *callback) {
3230
callback_ = callback;
3331
return WEBRTC_VIDEO_CODEC_OK;
3432
}
3533

36-
int32_t JetsonH264Encoder::Release() {
34+
int32_t JetsonVideoEncoder::Release() {
3735
encoder_.reset();
3836
return WEBRTC_VIDEO_CODEC_OK;
3937
}
4038

41-
int32_t JetsonH264Encoder::Encode(const webrtc::VideoFrame &frame,
42-
const std::vector<webrtc::VideoFrameType> *frame_types) {
39+
int32_t JetsonVideoEncoder::Encode(const webrtc::VideoFrame &frame,
40+
const std::vector<webrtc::VideoFrameType> *frame_types) {
4341
if (!frame_types) {
4442
return WEBRTC_VIDEO_CODEC_NO_OUTPUT;
4543
}
@@ -51,8 +49,12 @@ int32_t JetsonH264Encoder::Encode(const webrtc::VideoFrame &frame,
5149
auto v4l2_frame_buffer = V4L2FrameBufferRef(static_cast<V4L2FrameBuffer *>(frame_buffer.get()));
5250

5351
if (!encoder_) {
52+
auto codec_fmt = GetV4L2CodecFormat(codec_.codecType);
53+
if (codec_fmt == 0) {
54+
return WEBRTC_VIDEO_CODEC_ENCODER_FAILURE;
55+
}
5456
encoder_ =
55-
JetsonEncoder::Create(width_, height_, V4L2_PIX_FMT_H264,
57+
JetsonEncoder::Create(width_, height_, codec_fmt,
5658
frame_buffer->type() == webrtc::VideoFrameBuffer::Type::kNative);
5759
}
5860

@@ -68,7 +70,7 @@ int32_t JetsonH264Encoder::Encode(const webrtc::VideoFrame &frame,
6870
return WEBRTC_VIDEO_CODEC_OK;
6971
}
7072

71-
void JetsonH264Encoder::SetRates(const RateControlParameters &parameters) {
73+
void JetsonVideoEncoder::SetRates(const RateControlParameters &parameters) {
7274
if (parameters.bitrate.get_sum_bps() <= 0 || parameters.framerate_fps <= 0) {
7375
return;
7476
}
@@ -82,22 +84,25 @@ void JetsonH264Encoder::SetRates(const RateControlParameters &parameters) {
8284
encoder_->SetBitrate(bitrate_adjuster_.GetAdjustedBitrateBps());
8385
}
8486

85-
webrtc::VideoEncoder::EncoderInfo JetsonH264Encoder::GetEncoderInfo() const {
87+
webrtc::VideoEncoder::EncoderInfo JetsonVideoEncoder::GetEncoderInfo() const {
8688
EncoderInfo info;
8789
info.supports_native_handle = true;
8890
info.is_hardware_accelerated = true;
89-
info.implementation_name = "Jetson H264 Hardware Encoder";
91+
info.implementation_name = "Jetson Hardware Encoder";
9092
return info;
9193
}
9294

93-
void JetsonH264Encoder::SendFrame(const webrtc::VideoFrame &frame, V4L2Buffer &encoded_buffer) {
95+
void JetsonVideoEncoder::SendFrame(const webrtc::VideoFrame &frame, V4L2Buffer &encoded_buffer) {
9496
auto encoded_image_buffer =
9597
webrtc::EncodedImageBuffer::Create((uint8_t *)encoded_buffer.start, encoded_buffer.length);
9698

9799
webrtc::CodecSpecificInfo codec_specific;
98-
codec_specific.codecType = webrtc::kVideoCodecH264;
99-
codec_specific.codecSpecific.H264.packetization_mode =
100-
webrtc::H264PacketizationMode::NonInterleaved;
100+
codec_specific.codecType = codec_.codecType;
101+
102+
if (codec_specific.codecType == webrtc::kVideoCodecH264) {
103+
codec_specific.codecSpecific.H264.packetization_mode =
104+
webrtc::H264PacketizationMode::NonInterleaved;
105+
}
101106

102107
encoded_image_.SetEncodedData(encoded_image_buffer);
103108
encoded_image_.SetTimestamp(frame.timestamp());
@@ -116,3 +121,18 @@ void JetsonH264Encoder::SendFrame(const webrtc::VideoFrame &frame, V4L2Buffer &e
116121
ERROR_PRINT("Failed to send the frame => %d", result.error);
117122
}
118123
}
124+
125+
uint32_t JetsonVideoEncoder::GetV4L2CodecFormat(webrtc::VideoCodecType type) {
126+
switch (type) {
127+
case webrtc::kVideoCodecVP8:
128+
return V4L2_PIX_FMT_VP8;
129+
case webrtc::kVideoCodecVP9:
130+
return V4L2_PIX_FMT_VP9;
131+
case webrtc::kVideoCodecAV1:
132+
return V4L2_PIX_FMT_AV1;
133+
case webrtc::kVideoCodecH264:
134+
return V4L2_PIX_FMT_H264;
135+
default:
136+
return 0;
137+
}
138+
}

src/codecs/jetson/jetson_h264_encoder.h renamed to src/codecs/jetson/jetson_video_encoder.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
1-
#ifndef JETSON_H264_ENCODER_H_
2-
#define JETSON_H264_ENCODER_H_
1+
#ifndef JETSON_VIDEO_ENCODER_H_
2+
#define JETSON_VIDEO_ENCODER_H_
33

44
// WebRTC
55
#include <api/video_codecs/video_encoder.h>
66
#include <common_video/include/bitrate_adjuster.h>
7-
#include <modules/video_coding/codecs/h264/include/h264.h>
87

98
#include "args.h"
109
#include "codecs/jetson/jetson_encoder.h"
1110

12-
class JetsonH264Encoder : public webrtc::VideoEncoder {
11+
class JetsonVideoEncoder : public webrtc::VideoEncoder {
1312
public:
1413
static std::unique_ptr<webrtc::VideoEncoder> Create(Args args);
15-
JetsonH264Encoder(Args args);
14+
JetsonVideoEncoder(Args args);
1615

1716
int32_t InitEncode(const webrtc::VideoCodec *codec_settings,
1817
const VideoEncoder::Settings &settings) override;
@@ -36,6 +35,9 @@ class JetsonH264Encoder : public webrtc::VideoEncoder {
3635
std::unique_ptr<JetsonEncoder> encoder_;
3736

3837
virtual void SendFrame(const webrtc::VideoFrame &frame, V4L2Buffer &encoded_buffer);
38+
39+
private:
40+
static uint32_t GetV4L2CodecFormat(webrtc::VideoCodecType codec);
3941
};
4042

4143
#endif

src/rtc/customized_video_encoder_factory.cpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#if defined(USE_RPI_HW_ENCODER)
44
#include "codecs/v4l2/v4l2_h264_encoder.h"
55
#elif defined(USE_JETSON_HW_ENCODER)
6-
#include "codecs/jetson/jetson_h264_encoder.h"
6+
#include "codecs/jetson/jetson_video_encoder.h"
77
#endif
88

99
#include <modules/video_coding/codecs/av1/av1_svc_config.h>
@@ -41,6 +41,10 @@ std::vector<webrtc::SdpVideoFormat> CustomizedVideoEncoderFactory::GetSupportedF
4141
webrtc::H264Level::kLevel4, "1"));
4242
supported_codecs.push_back(CreateH264Format(webrtc::H264Profile::kProfileBaseline,
4343
webrtc::H264Level::kLevel4, "0"));
44+
// av1
45+
supported_codecs.push_back(
46+
webrtc::SdpVideoFormat(cricket::kAv1CodecName, webrtc::SdpVideoFormat::Parameters(),
47+
webrtc::LibaomAv1EncoderSupportedScalabilityModes()));
4448
#endif
4549
} else {
4650
// vp8
@@ -64,16 +68,19 @@ std::vector<webrtc::SdpVideoFormat> CustomizedVideoEncoderFactory::GetSupportedF
6468

6569
std::unique_ptr<webrtc::VideoEncoder>
6670
CustomizedVideoEncoderFactory::CreateVideoEncoder(const webrtc::SdpVideoFormat &format) {
71+
#if defined(USE_JETSON_HW_ENCODER)
72+
if (args_.hw_accel) {
73+
return JetsonVideoEncoder::Create(args_);
74+
}
75+
#endif
76+
6777
if (absl::EqualsIgnoreCase(format.name, cricket::kH264CodecName)) {
68-
if (args_.hw_accel) {
6978
#if defined(USE_RPI_HW_ENCODER)
79+
if (args_.hw_accel) {
7080
return V4L2H264Encoder::Create(args_);
71-
#elif defined(USE_JETSON_HW_ENCODER)
72-
return JetsonH264Encoder::Create(args_);
73-
#endif
74-
} else {
75-
return webrtc::H264Encoder::Create(cricket::VideoCodec(format));
7681
}
82+
#endif
83+
return webrtc::H264Encoder::Create(cricket::VideoCodec(format));
7784
} else if (absl::EqualsIgnoreCase(format.name, cricket::kVp8CodecName)) {
7885
return webrtc::VP8Encoder::Create();
7986
} else if (absl::EqualsIgnoreCase(format.name, cricket::kVp9CodecName)) {

0 commit comments

Comments
 (0)