encoder/ffmpeg: libOBS samples Chroma at Top, not Center

This bug predates the merge into StreamFX and was present in the original release as a separate plugin. libOBS has never sampled Chroma at Center as far as I can look back into its history.

Fixes #676
This commit is contained in:
Michael Fabian 'Xaymar' Dirks 2021-11-07 07:20:17 +01:00
parent adc38738f7
commit e954e86308
2 changed files with 23 additions and 9 deletions

View file

@ -436,11 +436,6 @@ void ffmpeg_instance::initialize_sw(obs_data_t* settings)
_context->height = static_cast<int>(obs_encoder_get_height(_self));
_context->pix_fmt = pix_fmt_target;
// Prevent pixelation by sampling "center" instead of corners. This creates
// a smoother look, which may not be H.264/AVC standard compliant, however it
// provides better support for scaling algorithms, such as Bicubic.
_context->chroma_sample_location = AVCHROMA_LOC_CENTER;
_scaler.set_source_size(static_cast<uint32_t>(_context->width), static_cast<uint32_t>(_context->height));
_scaler.set_source_color(_context->color_range == AVCOL_RANGE_JPEG, _context->colorspace);
_scaler.set_source_format(pix_fmt_source);
@ -490,10 +485,10 @@ void ffmpeg_instance::initialize_hw(obs_data_t*)
ctx->format = _context->pix_fmt;
ctx->sw_format = _context->sw_pix_fmt;
if (int32_t res = av_hwframe_ctx_init(_context->hw_frames_ctx); res < 0) {
std::array<char, 2048> buffer;
size_t len = static_cast<size_t>(snprintf(buffer.data(), buffer.size(),
"Initializing hardware context failed with error: %s (%" PRIu32 ")",
::streamfx::ffmpeg::tools::get_error_description(res), res));
std::array<char, 4096> buffer;
int len = snprintf(buffer.data(), buffer.size(), "Failed initialize hardware context: %s (%" PRIu32 ")",
::streamfx::ffmpeg::tools::get_error_description(res), res);
throw std::runtime_error(std::string(buffer.data(), buffer.data() + len));
}
#endif

View file

@ -255,6 +255,25 @@ void tools::context_setup_from_obs(const video_output_info* voi, AVCodecContext*
context->colorspace = obs_to_av_color_space(voi->colorspace);
context->color_primaries = obs_to_av_color_primary(voi->colorspace);
context->color_trc = obs_to_av_color_transfer_characteristics(voi->colorspace);
// Chroma Location
switch (context->pix_fmt) {
case AV_PIX_FMT_NV12:
case AV_PIX_FMT_YUV420P:
case AV_PIX_FMT_YUVA420P:
case AV_PIX_FMT_YUV422P:
case AV_PIX_FMT_YUVA422P:
case AV_PIX_FMT_YVYU422:
case AV_PIX_FMT_YUYV422:
case AV_PIX_FMT_UYVY422:
// libOBS merges Chroma at "Top", see H.264 specification.
context->chroma_sample_location = AVCHROMA_LOC_TOP;
break;
default:
// All other cases are unspecified.
context->chroma_sample_location = AVCHROMA_LOC_UNSPECIFIED;
break;
}
}
const char* tools::get_std_compliance_name(int compliance)