From 9481cd1a14d4da007dbb09232f2aad860700027d Mon Sep 17 00:00:00 2001 From: Dimitry Ishenko Date: Thu, 19 Sep 2024 21:23:11 -0400 Subject: [PATCH] ffmpeg_producer: implement scaling modes --- src/modules/ffmpeg/producer/av_producer.cpp | 14 ++++++++++---- src/modules/ffmpeg/producer/av_producer.h | 4 +++- src/modules/ffmpeg/producer/ffmpeg_producer.cpp | 15 ++++++++++----- src/modules/ffmpeg/util/av_util.cpp | 6 +++++- src/modules/ffmpeg/util/av_util.h | 4 +++- 5 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/modules/ffmpeg/producer/av_producer.cpp b/src/modules/ffmpeg/producer/av_producer.cpp index 64a06172d0..9cdc62ba47 100644 --- a/src/modules/ffmpeg/producer/av_producer.cpp +++ b/src/modules/ffmpeg/producer/av_producer.cpp @@ -665,6 +665,7 @@ struct AVProducer::Impl std::string vfilter_; int seekable_ = 2; + core::frame_geometry::scale_mode scale_mode_; int64_t frame_count_ = 0; bool frame_flush_ = true; int64_t frame_time_ = AV_NOPTS_VALUE; @@ -694,7 +695,8 @@ struct AVProducer::Impl std::optional seek, std::optional duration, bool loop, - int seekable) + int seekable, + core::frame_geometry::scale_mode scale_mode) : frame_factory_(frame_factory) , format_desc_(format_desc) , format_tb_({format_desc.duration, format_desc.time_scale * format_desc.field_count}) @@ -707,6 +709,7 @@ struct AVProducer::Impl , afilter_(afilter) , vfilter_(vfilter) , seekable_(seekable) + , scale_mode_(scale_mode) , video_executor_(L"video-executor") , audio_executor_(L"audio-executor") { @@ -913,7 +916,8 @@ struct AVProducer::Impl } frame.frame = core::draw_frame( - make_frame(this, *frame_factory_, frame.video, frame.audio, get_color_space(frame.video))); + make_frame(this, *frame_factory_, frame.video, frame.audio, get_color_space(frame.video), scale_mode_) + ); frame.frame_count = frame_count_++; graph_->set_value("decode-time", decode_timer.elapsed() * format_desc_.fps * 0.5); @@ -1237,7 +1241,8 @@ AVProducer::AVProducer(std::shared_ptr frame_factory, std::optional seek, std::optional duration, std::optional loop, - int seekable) + int seekable, + core::frame_geometry::scale_mode scale_mode) : impl_(new Impl(std::move(frame_factory), std::move(format_desc), std::move(name), @@ -1248,7 +1253,8 @@ AVProducer::AVProducer(std::shared_ptr frame_factory, std::move(seek), std::move(duration), std::move(loop.value_or(false)), - seekable)) + seekable, + scale_mode)) { } diff --git a/src/modules/ffmpeg/producer/av_producer.h b/src/modules/ffmpeg/producer/av_producer.h index 87b35dd9de..a5d8946889 100644 --- a/src/modules/ffmpeg/producer/av_producer.h +++ b/src/modules/ffmpeg/producer/av_producer.h @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -24,7 +25,8 @@ class AVProducer std::optional seek, std::optional duration, std::optional loop, - int seekable); + int seekable, + core::frame_geometry::scale_mode scale_mode); core::draw_frame prev_frame(const core::video_field field); core::draw_frame next_frame(const core::video_field field); diff --git a/src/modules/ffmpeg/producer/ffmpeg_producer.cpp b/src/modules/ffmpeg/producer/ffmpeg_producer.cpp index 57eb7b6179..7c43bdf58b 100644 --- a/src/modules/ffmpeg/producer/ffmpeg_producer.cpp +++ b/src/modules/ffmpeg/producer/ffmpeg_producer.cpp @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -73,7 +74,8 @@ struct ffmpeg_producer : public core::frame_producer std::optional seek, std::optional duration, std::optional loop, - int seekable) + int seekable, + core::frame_geometry::scale_mode scale_mode) : filename_(filename) , frame_factory_(frame_factory) , format_desc_(format_desc) @@ -87,9 +89,9 @@ struct ffmpeg_producer : public core::frame_producer seek, duration, loop, - seekable)) - { - } + seekable, + scale_mode)) + { } ~ffmpeg_producer() { @@ -317,6 +319,8 @@ spl::shared_ptr create_producer(const core::frame_producer auto filter_str = get_param(L"FILTER", params, L""); + auto scale_mode = core::scale_mode_from_string(get_param(L"SCALE_MODE", params, L"STRETCH")); + boost::ireplace_all(filter_str, L"DEINTERLACE_BOB", L"YADIF=1:-1"); boost::ireplace_all(filter_str, L"DEINTERLACE_LQ", L"SEPARATEFIELDS"); boost::ireplace_all(filter_str, L"DEINTERLACE", L"YADIF=0:-1"); @@ -350,7 +354,8 @@ spl::shared_ptr create_producer(const core::frame_producer seek2, duration, loop, - seekable); + seekable, + scale_mode); return core::create_destroy_proxy(std::move(producer)); } catch (...) { CASPAR_LOG_CURRENT_EXCEPTION(); diff --git a/src/modules/ffmpeg/util/av_util.cpp b/src/modules/ffmpeg/util/av_util.cpp index cf88307b40..c719ad3bd1 100644 --- a/src/modules/ffmpeg/util/av_util.cpp +++ b/src/modules/ffmpeg/util/av_util.cpp @@ -47,7 +47,8 @@ core::mutable_frame make_frame(void* tag, core::frame_factory& frame_factory, std::shared_ptr video, std::shared_ptr audio, - core::color_space color_space) + core::color_space color_space, + core::frame_geometry::scale_mode scale_mode) { std::vector data_map; // TODO(perf) when using data_map, avoid uploading duplicate planes @@ -57,6 +58,9 @@ core::mutable_frame make_frame(void* tag, : core::pixel_format_desc(core::pixel_format::invalid); auto frame = frame_factory.create_frame(tag, pix_desc); + if (scale_mode != core::frame_geometry::scale_mode::stretch) { + frame.geometry() = core::frame_geometry::get_default(scale_mode); + } tbb::parallel_invoke( [&]() { diff --git a/src/modules/ffmpeg/util/av_util.h b/src/modules/ffmpeg/util/av_util.h index 6680a380b2..84fcdb60cb 100644 --- a/src/modules/ffmpeg/util/av_util.h +++ b/src/modules/ffmpeg/util/av_util.h @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -31,7 +32,8 @@ core::mutable_frame make_frame(void* tag, core::frame_factory& frame_factory, std::shared_ptr video, std::shared_ptr audio, - core::color_space color_space = core::color_space::bt709); + core::color_space color_space = core::color_space::bt709, + core::frame_geometry::scale_mode = core::frame_geometry::scale_mode::stretch); std::shared_ptr make_av_video_frame(const core::const_frame& frame, const core::video_format_desc& format_des); std::shared_ptr make_av_audio_frame(const core::const_frame& frame, const core::video_format_desc& format_des);