Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(win/qsv): skip unsupported 4:4:4 codecs #3029

Merged
merged 2 commits into from
Aug 19, 2024
Merged
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 src/platform/windows/display_vram.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1871,6 +1871,13 @@ namespace platf::dxgi {
if (!boost::algorithm::ends_with(name, "_qsv")) {
return false;
}
if (config.chromaSamplingType == 1) {
if (config.videoFormat == 0 || config.videoFormat == 2) {
// QSV doesn't support 4:4:4 in H.264 or AV1
return false;
}
// TODO: Blacklist HEVC 4:4:4 based on adapter model
}
}
else if (adapter_desc.VendorId == 0x10de) { // Nvidia
// If it's not an NVENC encoder, it's not compatible with an Nvidia GPU
Expand Down
29 changes: 19 additions & 10 deletions src/video.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1434,9 +1434,7 @@

bool hardware = platform_formats->avcodec_base_dev_type != AV_HWDEVICE_TYPE_NONE;

auto &video_format = config.videoFormat == 0 ? encoder.h264 :
config.videoFormat == 1 ? encoder.hevc :
encoder.av1;
auto &video_format = encoder.codec_from_config(config);
if (!video_format[encoder_t::PASSED] || !disp->is_codec_supported(video_format.name, config)) {
BOOST_LOG(error) << encoder.name << ": "sv << video_format.name << " mode not supported"sv;
return nullptr;
Expand Down Expand Up @@ -1950,10 +1948,7 @@
}

{
auto encoder_name = config.videoFormat == 0 ? encoder.h264.name :
config.videoFormat == 1 ? encoder.hevc.name :
config.videoFormat == 2 ? encoder.av1.name :
"unknown";
auto encoder_name = encoder.codec_from_config(config).name;

BOOST_LOG(info) << "Creating encoder " << logging::bracket(encoder_name);

Expand Down Expand Up @@ -2516,7 +2511,8 @@
// H.264 is special because encoders may support YUV 4:4:4 without supporting 10-bit color depth
if (encoder.flags & YUV444_SUPPORT) {
config_t config_h264_yuv444 { 1920, 1080, 60, 1000, 1, 0, 1, 0, 0, 1 };
encoder.h264[encoder_t::YUV444] = validate_config(disp, encoder, config_h264_yuv444);
encoder.h264[encoder_t::YUV444] = disp->is_codec_supported(encoder.h264.name, config_h264_yuv444) &&
validate_config(disp, encoder, config_h264_yuv444) >= 0;
}
else {
encoder.h264[encoder_t::YUV444] = false;
Expand All @@ -2536,17 +2532,30 @@

if (!flag_map[encoder_t::PASSED]) return;

auto encoder_codec_name = encoder.codec_from_config(config).name;

Check warning on line 2535 in src/video.cpp

View check run for this annotation

Codecov / codecov/patch

src/video.cpp#L2535

Added line #L2535 was not covered by tests

// Test 4:4:4 HDR first. If 4:4:4 is supported, 4:2:0 should also be supported.
config.chromaSamplingType = 1;
if ((encoder.flags & YUV444_SUPPORT) && validate_config(disp, encoder, config) >= 0) {
if ((encoder.flags & YUV444_SUPPORT) &&
disp->is_codec_supported(encoder_codec_name, config) &&
validate_config(disp, encoder, config) >= 0) {
flag_map[encoder_t::DYNAMIC_RANGE] = true;
flag_map[encoder_t::YUV444] = true;
return;
}
else {
flag_map[encoder_t::YUV444] = false;
}

// Test 4:2:0 HDR
config.chromaSamplingType = 0;
flag_map[encoder_t::DYNAMIC_RANGE] = validate_config(disp, encoder, config) >= 0;
if (disp->is_codec_supported(encoder_codec_name, config) &&
validate_config(disp, encoder, config) >= 0) {
flag_map[encoder_t::DYNAMIC_RANGE] = true;
}
else {
flag_map[encoder_t::DYNAMIC_RANGE] = false;
}
};

// HDR is not supported with H.264. Don't bother even trying it.
Expand Down
61 changes: 38 additions & 23 deletions src/video.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,29 @@
struct AVPacket;
namespace video {

/* Encoding configuration requested by remote client */
struct config_t {
int width; // Video width in pixels
int height; // Video height in pixels
int framerate; // Requested framerate, used in individual frame bitrate budget calculation
int bitrate; // Video bitrate in kilobits (1000 bits) for requested framerate
int slicesPerFrame; // Number of slices per frame
int numRefFrames; // Max number of reference frames

/* Requested color range and SDR encoding colorspace, HDR encoding colorspace is always BT.2020+ST2084
Color range (encoderCscMode & 0x1) : 0 - limited, 1 - full
SDR encoding colorspace (encoderCscMode >> 1) : 0 - BT.601, 1 - BT.709, 2 - BT.2020 */
int encoderCscMode;

int videoFormat; // 0 - H.264, 1 - HEVC, 2 - AV1

/* 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 chromaSamplingType; // 0 - 4:2:0, 1 - 4:4:4
};

platf::mem_type_e
map_base_dev_type(AVHWDeviceType type);
platf::pix_fmt_e
Expand Down Expand Up @@ -163,6 +186,21 @@
}
} av1, hevc, h264;

const codec_t &
codec_from_config(const config_t &config) const {
switch (config.videoFormat) {
default:

Check warning on line 192 in src/video.h

View check run for this annotation

Codecov / codecov/patch

src/video.h#L192

Added line #L192 was not covered by tests
BOOST_LOG(error) << "Unknown video format " << config.videoFormat << ", falling back to H.264";
// fallthrough
case 0:
return h264;
case 1:
return hevc;
case 2:
return av1;

Check warning on line 200 in src/video.h

View check run for this annotation

Codecov / codecov/patch

src/video.h#L197-L200

Added lines #L197 - L200 were not covered by tests
}
}

uint32_t flags;
};

Expand Down Expand Up @@ -309,29 +347,6 @@

using hdr_info_t = std::unique_ptr<hdr_info_raw_t>;

/* Encoding configuration requested by remote client */
struct config_t {
int width; // Video width in pixels
int height; // Video height in pixels
int framerate; // Requested framerate, used in individual frame bitrate budget calculation
int bitrate; // Video bitrate in kilobits (1000 bits) for requested framerate
int slicesPerFrame; // Number of slices per frame
int numRefFrames; // Max number of reference frames

/* Requested color range and SDR encoding colorspace, HDR encoding colorspace is always BT.2020+ST2084
Color range (encoderCscMode & 0x1) : 0 - limited, 1 - full
SDR encoding colorspace (encoderCscMode >> 1) : 0 - BT.601, 1 - BT.709, 2 - BT.2020 */
int encoderCscMode;

int videoFormat; // 0 - H.264, 1 - HEVC, 2 - AV1

/* 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 chromaSamplingType; // 0 - 4:2:0, 1 - 4:4:4
};

extern int active_hevc_mode;
extern int active_av1_mode;
extern bool last_encoder_probe_supported_ref_frames_invalidation;
Expand Down
Loading