X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fffmpeg%2Fproducer%2Ffilter%2Ffilter.cpp;h=0b6b38d54ff1894becb962dc12c0edf6bfafdf03;hb=ca4193194e570781a824519791fa7cbdee032946;hp=d5918f0b97c191a3128654e479716c096bfe2a67;hpb=a05e1442f0a510b205a729ef389692e6bbdba95b;p=casparcg diff --git a/modules/ffmpeg/producer/filter/filter.cpp b/modules/ffmpeg/producer/filter/filter.cpp index d5918f0b9..0b6b38d54 100644 --- a/modules/ffmpeg/producer/filter/filter.cpp +++ b/modules/ffmpeg/producer/filter/filter.cpp @@ -2,36 +2,34 @@ #include "filter.h" -#include "scalable_yadif.h" +#include "parallel_yadif.h" #include "../../ffmpeg_error.h" -#include -#include -#include -#include - -#include - -#include +#include #include #include +#if defined(_MSC_VER) +#pragma warning (push) +#pragma warning (disable : 4244) +#endif extern "C" { - #define __STDC_CONSTANT_MACROS - #define __STDC_LIMIT_MACROS #include #include #include #include #include - #include + #include #include } +#if defined(_MSC_VER) +#pragma warning (pop) +#endif -namespace caspar { +namespace caspar { namespace ffmpeg { struct filter::implementation { @@ -39,33 +37,47 @@ struct filter::implementation std::shared_ptr graph_; AVFilterContext* buffersink_ctx_; AVFilterContext* buffersrc_ctx_; - int scalable_yadif_tag_; + std::shared_ptr parallel_yadif_ctx_; + std::vector pix_fmts_; - implementation(const std::wstring& filters) - : filters_(filters.empty() ? "null" : narrow(filters)) - , scalable_yadif_tag_(-1) + implementation(const std::wstring& filters, const std::vector& pix_fmts) + : filters_(narrow(filters)) + , parallel_yadif_ctx_(nullptr) + , pix_fmts_(pix_fmts) { - std::transform(filters_.begin(), filters_.end(), filters_.begin(), ::tolower); - } + if(pix_fmts_.empty()) + { + pix_fmts_.push_back(PIX_FMT_YUV420P); + pix_fmts_.push_back(PIX_FMT_YUVA420P); + pix_fmts_.push_back(PIX_FMT_YUV422P); + pix_fmts_.push_back(PIX_FMT_YUV444P); + pix_fmts_.push_back(PIX_FMT_YUV411P); + pix_fmts_.push_back(PIX_FMT_ARGB); + pix_fmts_.push_back(PIX_FMT_RGBA); + pix_fmts_.push_back(PIX_FMT_ABGR); + pix_fmts_.push_back(PIX_FMT_GRAY8); + pix_fmts_.push_back(PIX_FMT_NONE); + } + else + pix_fmts_.push_back(PIX_FMT_NONE); - ~implementation() - { - release_scalable_yadif(scalable_yadif_tag_); + std::transform(filters_.begin(), filters_.end(), filters_.begin(), ::tolower); } - + std::vector> execute(const std::shared_ptr& frame) { + if(!frame) + return std::vector>(); + + if(filters_.empty()) + return boost::assign::list_of(frame); + push(frame); return poll(); } void push(const std::shared_ptr& frame) { - if(!frame) - return; - - int errn = 0; - if(!graph_) { graph_.reset(avfilter_graph_alloc(), [](AVFilterGraph* p){avfilter_graph_free(&p);}); @@ -73,37 +85,16 @@ struct filter::implementation // Input std::stringstream args; args << frame->width << ":" << frame->height << ":" << frame->format << ":" << 0 << ":" << 0 << ":" << 0 << ":" << 0; // don't care about pts and aspect_ratio - errn = avfilter_graph_create_filter(&buffersrc_ctx_, avfilter_get_by_name("buffer"), "src", args.str().c_str(), NULL, graph_.get()); - if(errn < 0) - { - BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(av_error_str(errn)) << - boost::errinfo_api_function("avfilter_graph_create_filter") << boost::errinfo_errno(AVUNERROR(errn))); - } + THROW_ON_ERROR2(avfilter_graph_create_filter(&buffersrc_ctx_, avfilter_get_by_name("buffer"), "src", args.str().c_str(), NULL, graph_.get()), "[filter]"); - PixelFormat pix_fmts[] = - { - PIX_FMT_YUV420P, - PIX_FMT_YUVA420P, - PIX_FMT_YUV422P, - PIX_FMT_YUV444P, - PIX_FMT_YUV411P, - PIX_FMT_ARGB, - PIX_FMT_RGBA, - PIX_FMT_ABGR, - PIX_FMT_GRAY8, - PIX_FMT_NONE - }; // OPIX_FMT_BGRAutput - errn = avfilter_graph_create_filter(&buffersink_ctx_, avfilter_get_by_name("buffersink"), "out", NULL, pix_fmts, graph_.get()); - if(errn < 0) - { - BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(av_error_str(errn)) << - boost::errinfo_api_function("avfilter_graph_create_filter") << boost::errinfo_errno(AVUNERROR(errn))); - } + AVBufferSinkParams *buffersink_params = av_buffersink_params_alloc(); + buffersink_params->pixel_fmts = pix_fmts_.data(); + THROW_ON_ERROR2(avfilter_graph_create_filter(&buffersink_ctx_, avfilter_get_by_name("buffersink"), "out", NULL, buffersink_params, graph_.get()), "[filter]"); AVFilterInOut* outputs = avfilter_inout_alloc(); AVFilterInOut* inputs = avfilter_inout_alloc(); - + outputs->name = av_strdup("in"); outputs->filter_ctx = buffersrc_ctx_; outputs->pad_idx = 0; @@ -114,38 +105,22 @@ struct filter::implementation inputs->pad_idx = 0; inputs->next = NULL; - errn = avfilter_graph_parse(graph_.get(), filters_.c_str(), &inputs, &outputs, NULL); - + THROW_ON_ERROR2(avfilter_graph_parse(graph_.get(), filters_.c_str(), &inputs, &outputs, NULL), "[filter]"); + avfilter_inout_free(&inputs); avfilter_inout_free(&outputs); - if(errn < 0) - { - BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(av_error_str(errn)) << - boost::errinfo_api_function("avfilter_graph_parse") << boost::errinfo_errno(AVUNERROR(errn))); - } - - errn = avfilter_graph_config(graph_.get(), NULL); - if(errn < 0) - { - BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(av_error_str(errn)) - << boost::errinfo_api_function("avfilter_graph_config") << boost::errinfo_errno(AVUNERROR(errn))); - } + THROW_ON_ERROR2(avfilter_graph_config(graph_.get(), NULL), "[filter]"); for(size_t n = 0; n < graph_->filter_count; ++n) { auto filter_name = graph_->filters[n]->name; if(strstr(filter_name, "yadif") != 0) - scalable_yadif_tag_ = make_scalable_yadif(graph_->filters[n]); + parallel_yadif_ctx_ = make_parallel_yadif(graph_->filters[n]); } } - errn = av_vsrc_buffer_add_frame(buffersrc_ctx_, frame.get(), 0); - if(errn < 0) - { - BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(av_error_str(errn)) << - boost::errinfo_api_function("av_vsrc_buffer_add_frame") << boost::errinfo_errno(AVUNERROR(errn))); - } + THROW_ON_ERROR2(av_vsrc_buffer_add_frame(buffersrc_ctx_, frame.get(), 0), "[filter]"); } std::vector> poll() @@ -158,7 +133,8 @@ struct filter::implementation while (avfilter_poll_frame(buffersink_ctx_->inputs[0])) { AVFilterBufferRef *picref; - av_vsink_buffer_get_video_buffer_ref(buffersink_ctx_, &picref, 0); + THROW_ON_ERROR2(av_buffersink_get_buffer_ref(buffersink_ctx_, &picref, 0), "[filter]"); + if (picref) { safe_ptr frame(avcodec_alloc_frame(), [=](AVFrame* p) @@ -189,6 +165,9 @@ struct filter::implementation } }; -filter::filter(const std::wstring& filters) : impl_(new implementation(filters)){} +filter::filter(const std::wstring& filters, const std::vector& pix_fmts) : impl_(new implementation(filters, pix_fmts)){} +filter::filter(filter&& other) : impl_(std::move(other.impl_)){} +filter& filter::operator=(filter&& other){impl_ = std::move(other.impl_); return *this;} std::vector> filter::execute(const std::shared_ptr& frame) {return impl_->execute(frame);} -} \ No newline at end of file + +}} \ No newline at end of file