Skip to content

Commit

Permalink
Continue implementing yuv444 encoding
Browse files Browse the repository at this point in the history
  • Loading branch information
ns6089 committed Oct 7, 2023
1 parent 78a6e26 commit dc0fb83
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 8 deletions.
6 changes: 4 additions & 2 deletions src/nvenc/nvenc_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ namespace nvenc {
};

auto buffer_is_yuv444 = [&]() {
return buffer_format == NV_ENC_BUFFER_FORMAT_YUV444 || buffer_format == NV_ENC_BUFFER_FORMAT_YUV444_10BIT;
return buffer_format == NV_ENC_BUFFER_FORMAT_AYUV || buffer_format == NV_ENC_BUFFER_FORMAT_YUV444_10BIT;
};

{
Expand Down Expand Up @@ -306,7 +306,9 @@ namespace nvenc {
auto &format_config = enc_config.encodeCodecConfig.av1Config;
format_config.repeatSeqHdr = 1;
format_config.idrPeriod = NVENC_INFINITE_GOPLENGTH;
format_config.chromaFormatIDC = 1; // YUV444 not supported by NVENC yet
if (buffer_is_yuv444()) {
format_config.chromaFormatIDC = 3;
}
format_config.enableBitstreamPadding = config.insert_filler_data;
if (buffer_is_10bit()) {
format_config.inputPixelBitDepthMinus8 = 2;
Expand Down
1 change: 1 addition & 0 deletions src/nvenc/nvenc_d3d11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ namespace nvenc {
D3D11_TEXTURE2D_DESC desc = {};
desc.Width = encoder_params.width;
desc.Height = encoder_params.height;
if (encoder_params.buffer_format == NV_ENC_BUFFER_FORMAT_YUV444_10BIT) desc.Height *= 3;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = dxgi_format_from_nvenc_format(encoder_params.buffer_format);
Expand Down
12 changes: 12 additions & 0 deletions src/nvenc/nvenc_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ namespace nvenc {
case NV_ENC_BUFFER_FORMAT_NV12:
return DXGI_FORMAT_NV12;

case NV_ENC_BUFFER_FORMAT_AYUV:
return DXGI_FORMAT_AYUV;

case NV_ENC_BUFFER_FORMAT_YUV444_10BIT:
return DXGI_FORMAT_R16_UNORM;

default:
return DXGI_FORMAT_UNKNOWN;
}
Expand All @@ -27,6 +33,12 @@ namespace nvenc {
case platf::pix_fmt_e::p010:
return NV_ENC_BUFFER_FORMAT_YUV420_10BIT;

case platf::pix_fmt_e::ayuv:
return NV_ENC_BUFFER_FORMAT_AYUV;

case platf::pix_fmt_e::yuv10_planar:
return NV_ENC_BUFFER_FORMAT_YUV444_10BIT;

default:
return NV_ENC_BUFFER_FORMAT_UNDEFINED;
}
Expand Down
4 changes: 4 additions & 0 deletions src/platform/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ namespace platf {
yuv420p10,
nv12,
p010,
ayuv,
yuv10_planar,
unknown
};

Expand All @@ -210,6 +212,8 @@ namespace platf {
_CONVERT(yuv420p10);
_CONVERT(nv12);
_CONVERT(p010);
_CONVERT(ayuv);
_CONVERT(yuv10_planar);
_CONVERT(unknown);
}
#undef _CONVERT
Expand Down
2 changes: 2 additions & 0 deletions src/rtsp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,7 @@ namespace rtsp_stream {
args.try_emplace("x-nv-video[0].encoderCscMode"sv, "0"sv);
args.try_emplace("x-nv-vqos[0].bitStreamFormat"sv, "0"sv);
args.try_emplace("x-nv-video[0].dynamicRangeMode"sv, "0"sv);
args.try_emplace("x-nv-video[0].chromaSubsampling"sv, "0"sv);
args.try_emplace("x-nv-aqos.packetDuration"sv, "5"sv);
args.try_emplace("x-nv-general.useReliableUdp"sv, "1"sv);
args.try_emplace("x-nv-vqos[0].fec.minRequiredFecPackets"sv, "0"sv);
Expand Down Expand Up @@ -686,6 +687,7 @@ namespace rtsp_stream {
config.monitor.encoderCscMode = util::from_view(args.at("x-nv-video[0].encoderCscMode"sv));
config.monitor.videoFormat = util::from_view(args.at("x-nv-vqos[0].bitStreamFormat"sv));
config.monitor.dynamicRange = util::from_view(args.at("x-nv-video[0].dynamicRangeMode"sv));
config.monitor.chromaSubsampling = util::from_view(args.at("x-nv-video[0].chromaSubsampling"sv));
}
catch (std::out_of_range &) {
respond(sock, &option, 400, "BAD REQUEST", req->sequenceNumber, {});
Expand Down
28 changes: 22 additions & 6 deletions src/video.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,8 @@ namespace video {
virtual ~encoder_platform_formats_t() = default;
platf::mem_type_e dev_type;
platf::pix_fmt_e pix_fmt_8bit, pix_fmt_10bit;
std::optional<platf::pix_fmt_e> pix_fmt_444_8bit;
std::optional<platf::pix_fmt_e> pix_fmt_444_10bit;
};

struct encoder_platform_formats_avcodec: encoder_platform_formats_t {
Expand Down Expand Up @@ -311,10 +313,14 @@ namespace video {
encoder_platform_formats_nvenc(
const platf::mem_type_e &dev_type,
const platf::pix_fmt_e &pix_fmt_8bit,
const platf::pix_fmt_e &pix_fmt_10bit) {
const platf::pix_fmt_e &pix_fmt_10bit,
const platf::pix_fmt_e &pix_fmt_444_8bit,
const platf::pix_fmt_e &pix_fmt_444_10bit) {
encoder_platform_formats_t::dev_type = dev_type;
encoder_platform_formats_t::pix_fmt_8bit = pix_fmt_8bit;
encoder_platform_formats_t::pix_fmt_10bit = pix_fmt_10bit;
encoder_platform_formats_t::pix_fmt_444_8bit = pix_fmt_444_8bit;
encoder_platform_formats_t::pix_fmt_444_10bit = pix_fmt_444_10bit;
}
};

Expand Down Expand Up @@ -570,7 +576,8 @@ namespace video {
"nvenc"sv,
std::make_unique<encoder_platform_formats_nvenc>(
platf::mem_type_e::dxgi,
platf::pix_fmt_e::nv12, platf::pix_fmt_e::p010),
platf::pix_fmt_e::nv12, platf::pix_fmt_e::p010,
platf::pix_fmt_e::ayuv, platf::pix_fmt_e::yuv10_planar),
{
// Common options
{},
Expand Down Expand Up @@ -1838,7 +1845,16 @@ namespace video {
std::unique_ptr<platf::encode_device_t> result;

auto colorspace = colorspace_from_client_config(config, disp.is_hdr());
auto pix_fmt = (colorspace.bit_depth == 10) ? encoder.platform_formats->pix_fmt_10bit : encoder.platform_formats->pix_fmt_8bit;
platf::pix_fmt_e pix_fmt;

if (config.chromaSubsampling) {
pix_fmt = (colorspace.bit_depth == 10) ? encoder.platform_formats->pix_fmt_10bit : encoder.platform_formats->pix_fmt_8bit;
}
else {
auto pix_fmt_optional = (colorspace.bit_depth == 10) ? encoder.platform_formats->pix_fmt_444_10bit : encoder.platform_formats->pix_fmt_444_8bit;
if (!pix_fmt_optional) return nullptr;
pix_fmt = *pix_fmt_optional;
}

if (dynamic_cast<const encoder_platform_formats_avcodec *>(encoder.platform_formats.get())) {
result = disp.make_avcodec_encode_device(pix_fmt);
Expand Down Expand Up @@ -2272,8 +2288,8 @@ namespace video {
encoder.av1.capabilities.set();

// First, test encoder viability
config_t config_max_ref_frames { 1920, 1080, 60, 1000, 1, 1, 1, 0, 0 };
config_t config_autoselect { 1920, 1080, 60, 1000, 1, 0, 1, 0, 0 };
config_t config_max_ref_frames { 1920, 1080, 60, 1000, 1, 1, 1, 0, 0, 1 };
config_t config_autoselect { 1920, 1080, 60, 1000, 1, 0, 1, 0, 0, 1 };

// If the encoder isn't supported at all (not even H.264), bail early
reset_display(disp, encoder.platform_formats->dev_type, config::video.output_name, config_autoselect);
Expand Down Expand Up @@ -2381,7 +2397,7 @@ namespace video {
}

std::vector<std::pair<encoder_t::flag_e, config_t>> configs {
{ encoder_t::DYNAMIC_RANGE, { 1920, 1080, 60, 1000, 1, 0, 3, 1, 1 } },
{ encoder_t::DYNAMIC_RANGE, { 1920, 1080, 60, 1000, 1, 0, 3, 1, 1, 1 } },
};

for (auto &[flag, config] : configs) {
Expand Down
2 changes: 2 additions & 0 deletions src/video.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ namespace video {
/* Encoding color depth (bit depth): 0 - 8-bit, 1 - 10-bit
HDR encoding activates when color depth is higher than 8-bit and the display which is being captured is operating in HDR mode */
int dynamicRange;

int chromaSubsampling; // 0 - YUV 4:4:4, 1 - YUV 4:2:0
};

extern int active_hevc_mode;
Expand Down

0 comments on commit dc0fb83

Please sign in to comment.