From e954e8630896028c3477d0491aa719f576b441ab Mon Sep 17 00:00:00 2001 From: Michael Fabian 'Xaymar' Dirks Date: Sun, 7 Nov 2021 07:20:17 +0100 Subject: [PATCH] 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 --- source/encoders/encoder-ffmpeg.cpp | 13 ++++--------- source/ffmpeg/tools.cpp | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/source/encoders/encoder-ffmpeg.cpp b/source/encoders/encoder-ffmpeg.cpp index 024cd7f7..bf32a0f2 100644 --- a/source/encoders/encoder-ffmpeg.cpp +++ b/source/encoders/encoder-ffmpeg.cpp @@ -436,11 +436,6 @@ void ffmpeg_instance::initialize_sw(obs_data_t* settings) _context->height = static_cast(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(_context->width), static_cast(_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 buffer; - size_t len = static_cast(snprintf(buffer.data(), buffer.size(), - "Initializing hardware context failed with error: %s (%" PRIu32 ")", - ::streamfx::ffmpeg::tools::get_error_description(res), res)); + std::array 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 diff --git a/source/ffmpeg/tools.cpp b/source/ffmpeg/tools.cpp index 6c7b823c..00dfe41c 100644 --- a/source/ffmpeg/tools.cpp +++ b/source/ffmpeg/tools.cpp @@ -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)