From: Robert Nagy Date: Mon, 16 Dec 2013 18:46:25 +0000 (+0100) Subject: ffmpeg: Cleanup and bug fixes. X-Git-Tag: 2.0.7_Beta~14^2~4 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=7c91b44030d47b6a6c2c8d5617a60c2e2587479b;hp=5de2f6934e840f7577be4a150d4acd59a99c5438;p=casparcg ffmpeg: Cleanup and bug fixes. --- diff --git a/modules/ffmpeg/ffmpeg.vcxproj b/modules/ffmpeg/ffmpeg.vcxproj index 63980cd0b..303f39ae5 100644 --- a/modules/ffmpeg/ffmpeg.vcxproj +++ b/modules/ffmpeg/ffmpeg.vcxproj @@ -1,4 +1,4 @@ - + @@ -300,12 +300,6 @@ ../../StdAfx.h ../../StdAfx.h - - ../../StdAfx.h - ../../StdAfx.h - ../../StdAfx.h - ../../StdAfx.h - ../../StdAfx.h ../../StdAfx.h @@ -358,7 +352,6 @@ - diff --git a/modules/ffmpeg/ffmpeg.vcxproj.filters b/modules/ffmpeg/ffmpeg.vcxproj.filters index 540b4acef..2c75f48d3 100644 --- a/modules/ffmpeg/ffmpeg.vcxproj.filters +++ b/modules/ffmpeg/ffmpeg.vcxproj.filters @@ -1,4 +1,4 @@ - + @@ -46,9 +46,6 @@ source\producer\filter - - source\producer\filter - source\producer\audio @@ -97,9 +94,6 @@ source\producer\filter - - source\producer\filter - source\producer\audio diff --git a/modules/ffmpeg/producer/filter/filter.cpp b/modules/ffmpeg/producer/filter/filter.cpp index 38ec37404..5c608e978 100644 --- a/modules/ffmpeg/producer/filter/filter.cpp +++ b/modules/ffmpeg/producer/filter/filter.cpp @@ -23,8 +23,6 @@ #include "filter.h" -#include "parallel_yadif.h" - #include "../../ffmpeg_error.h" #include @@ -64,58 +62,9 @@ extern "C" namespace caspar { namespace ffmpeg { -//static int query_formats_444(AVFilterContext *ctx) -//{ -// static const int pix_fmts[] = {PIX_FMT_YUV444P, PIX_FMT_NONE}; -// avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts)); -// return 0; -//} -// -//static int query_formats_422(AVFilterContext *ctx) -//{ -// static const int pix_fmts[] = {PIX_FMT_YUV422P, PIX_FMT_NONE}; -// avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts)); -// return 0; -//} -// -//static int query_formats_420(AVFilterContext *ctx) -//{ -// static const int pix_fmts[] = {PIX_FMT_YUV420P, PIX_FMT_NONE}; -// avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts)); -// return 0; -//} -// -//static int query_formats_420a(AVFilterContext *ctx) -//{ -// static const int pix_fmts[] = {PIX_FMT_YUVA420P, PIX_FMT_NONE}; -// avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts)); -// return 0; -//} -// -//static int query_formats_411(AVFilterContext *ctx) -//{ -// static const int pix_fmts[] = {PIX_FMT_YUV411P, PIX_FMT_NONE}; -// avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts)); -// return 0; -//} -// -//static int query_formats_410(AVFilterContext *ctx) -//{ -// static const int pix_fmts[] = {PIX_FMT_YUV410P, PIX_FMT_NONE}; -// avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(pix_fmts)); -// return 0; -//} - struct filter::implementation { - std::wstring filters_; - //std::shared_ptr graph_; - //AVFilterContext* buffersink_ctx_; - //AVFilterContext* buffersrc_ctx_; - //std::shared_ptr parallel_yadif_ctx_; - std::vector pix_fmts_; - //std::queue> bypass_; - + std::string filtergraph_; std::shared_ptr video_graph_; AVFilterContext* video_graph_in_; AVFilterContext* video_graph_out_; @@ -129,10 +78,11 @@ struct filter::implementation AVPixelFormat in_pix_fmt, std::vector out_pix_fmts, const std::string& filtergraph) + : filtergraph_(boost::to_lower_copy(filtergraph)) { if(out_pix_fmts.empty()) { - pix_fmts_ = boost::assign::list_of + out_pix_fmts = boost::assign::list_of (AV_PIX_FMT_YUVA420P) (AV_PIX_FMT_YUV444P) (AV_PIX_FMT_YUV422P) @@ -157,14 +107,6 @@ struct filter::implementation video_graph_->nb_threads = boost::thread::hardware_concurrency(); video_graph_->thread_type = AVFILTER_THREAD_SLICE; - //const auto sample_aspect_ratio = - // boost::rational( - // in_video_format_.square_width, - // in_video_format_.square_height) / - // boost::rational( - // in_video_format_.width, - // in_video_format_.height); - const auto vsrc_options = (boost::format("video_size=%1%x%2%:pix_fmt=%3%:time_base=%4%/%5%:pixel_aspect=%6%/%7%:frame_rate=%8%/%9%") % in_width % in_height % in_pix_fmt @@ -176,7 +118,7 @@ struct filter::implementation FF(avfilter_graph_create_filter( &filt_vsrc, avfilter_get_by_name("buffer"), - "ffmpeg_consumer_buffer", + "filter_buffer", vsrc_options.c_str(), nullptr, video_graph_.get())); @@ -185,7 +127,7 @@ struct filter::implementation FF(avfilter_graph_create_filter( &filt_vsink, avfilter_get_by_name("buffersink"), - "ffmpeg_consumer_buffersink", + "filter_buffersink", nullptr, nullptr, video_graph_.get())); @@ -204,7 +146,7 @@ struct filter::implementation configure_filtergraph( *video_graph_, - filtergraph, + filtergraph_, *filt_vsrc, *filt_vsink); @@ -301,184 +243,6 @@ struct filter::implementation return filt_frame; } - -// void push(const std::shared_ptr& frame) -// { -// if(!frame) -// return; -// -// if(frame->data[0] == nullptr || frame->width < 1) -// BOOST_THROW_EXCEPTION(invalid_argument()); -// -// if(filters_.empty()) -// { -// bypass_.push(make_safe_ptr(frame)); -// return; -// } -// -// try -// { -// if(!graph_) -// { -// try -// { -// graph_.reset(avfilter_graph_alloc(), [](AVFilterGraph* p){avfilter_graph_free(&p);}); -// -// // Input -// std::stringstream args; -// args << frame->width << ":" << frame->height << ":" << frame->format << ":" << 0 << ":" << 0 << ":" << 0 << ":" << 0; // don't care about pts and aspect_ratio -// THROW_ON_ERROR2(avfilter_graph_create_filter(&buffersrc_ctx_, avfilter_get_by_name("buffer"), "src", args.str().c_str(), NULL, graph_.get()), "[filter]"); -// -//#if FF_API_OLD_VSINK_API -// THROW_ON_ERROR2(avfilter_graph_create_filter(&buffersink_ctx_, avfilter_get_by_name("buffersink"), "out", NULL, pix_fmts_.data(), graph_.get()), "[filter]"); -//#else -// safe_ptr buffersink_params(av_buffersink_params_alloc(), av_free); -// 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.get(), graph_.get()), "[filter]"); -//#endif -// AVFilterInOut* inputs = avfilter_inout_alloc(); -// AVFilterInOut* outputs = avfilter_inout_alloc(); -// -// outputs->name = av_strdup("in"); -// outputs->filter_ctx = buffersrc_ctx_; -// outputs->pad_idx = 0; -// outputs->next = nullptr; -// -// inputs->name = av_strdup("out"); -// inputs->filter_ctx = buffersink_ctx_; -// inputs->pad_idx = 0; -// inputs->next = nullptr; -// -// std::string filters = boost::to_lower_copy(narrow(filters_)); -// THROW_ON_ERROR2(avfilter_graph_parse(graph_.get(), filters.c_str(), &inputs, &outputs, NULL), "[filter]"); -// -// auto yadif_filter = boost::adaptors::filtered([&](AVFilterContext* p){return strstr(p->name, "yadif") != 0;}); -// -// BOOST_FOREACH(auto filter_ctx, boost::make_iterator_range(graph_->filters, graph_->filters + graph_->filter_count) | yadif_filter) -// { -// // Don't trust that libavfilter chooses optimal format. -// filter_ctx->filter->query_formats = [&]() -> int (*)(AVFilterContext*) -// { -// switch(frame->format) -// { -// case PIX_FMT_YUV444P16: -// case PIX_FMT_YUV444P10: -// case PIX_FMT_YUV444P9: -// case PIX_FMT_YUV444P: -// case PIX_FMT_BGR24: -// case PIX_FMT_RGB24: -// return query_formats_444; -// case PIX_FMT_YUV422P16: -// case PIX_FMT_YUV422P10: -// case PIX_FMT_YUV422P9: -// case PIX_FMT_YUV422P: -// case PIX_FMT_UYVY422: -// case PIX_FMT_YUYV422: -// return query_formats_422; -// case PIX_FMT_YUV420P16: -// case PIX_FMT_YUV420P10: -// case PIX_FMT_YUV420P9: -// case PIX_FMT_YUV420P: -// return query_formats_420; -// case PIX_FMT_YUVA420P: -// case PIX_FMT_BGRA: -// case PIX_FMT_RGBA: -// case PIX_FMT_ABGR: -// case PIX_FMT_ARGB: -// return query_formats_420a; -// case PIX_FMT_UYYVYY411: -// case PIX_FMT_YUV411P: -// return query_formats_411; -// case PIX_FMT_YUV410P: -// return query_formats_410; -// default: -// return filter_ctx->filter->query_formats; -// } -// }(); -// } -// -// THROW_ON_ERROR2(avfilter_graph_config(graph_.get(), NULL), "[filter]"); -// -// BOOST_FOREACH(auto filter_ctx, boost::make_iterator_range(graph_->filters, graph_->filters + graph_->filter_count) | yadif_filter) -// parallel_yadif_ctx_ = make_parallel_yadif(filter_ctx); -// } -// catch(...) -// { -// graph_ = nullptr; -// throw; -// } -// } -// -// THROW_ON_ERROR2(av_vsrc_buffer_add_frame(buffersrc_ctx_, frame.get(), 0), "[filter]"); -// } -// catch(ffmpeg_error&) -// { -// throw; -// } -// catch(...) -// { -// BOOST_THROW_EXCEPTION(ffmpeg_error() << boost::errinfo_nested_exception(boost::current_exception())); -// } -// } -// -// std::shared_ptr poll() -// { -// if(filters_.empty()) -// { -// if(bypass_.empty()) -// return nullptr; -// auto frame = bypass_.front(); -// bypass_.pop(); -// return frame; -// } -// -// if(!graph_) -// return nullptr; -// -// try -// { -// if(avfilter_poll_frame(buffersink_ctx_->inputs[0])) -// { -// AVFilterBufferRef *picref; -// THROW_ON_ERROR2(av_buffersink_get_buffer_ref(buffersink_ctx_, &picref, 0), "[filter]"); -// -// if (!picref) -// return nullptr; -// -// safe_ptr frame(avcodec_alloc_frame(), [=](AVFrame* p) -// { -// av_free(p); -// avfilter_unref_buffer(picref); -// }); -// -// avcodec_get_frame_defaults(frame.get()); -// -// memcpy(frame->data, picref->data, sizeof(frame->data)); -// memcpy(frame->linesize, picref->linesize, sizeof(frame->linesize)); -// frame->format = picref->format; -// frame->width = picref->video->w; -// frame->height = picref->video->h; -// frame->pkt_pos = picref->pos; -// frame->interlaced_frame = picref->video->interlaced; -// frame->top_field_first = picref->video->top_field_first; -// frame->key_frame = picref->video->key_frame; -// frame->pict_type = picref->video->pict_type; -// frame->sample_aspect_ratio = picref->video->sample_aspect_ratio; -// -// return frame; -// } -// -// return nullptr; -// } -// catch(ffmpeg_error&) -// { -// throw; -// } -// catch(...) -// { -// BOOST_THROW_EXCEPTION(ffmpeg_error() << boost::errinfo_nested_exception(boost::current_exception())); -// } -// } }; filter::filter( @@ -503,7 +267,7 @@ filter::filter(filter&& other) : impl_(std::move(other.impl_)){} filter& filter::operator=(filter&& other){impl_ = std::move(other.impl_); return *this;} void filter::push(const std::shared_ptr& frame){impl_->push(frame);} std::shared_ptr filter::poll(){return impl_->poll();} -std::wstring filter::filter_str() const{return impl_->filters_;} +std::wstring filter::filter_str() const{return widen(impl_->filtergraph_);} std::vector> filter::poll_all() { std::vector> frames; diff --git a/modules/ffmpeg/producer/filter/parallel_yadif.cpp b/modules/ffmpeg/producer/filter/parallel_yadif.cpp deleted file mode 100644 index 915f82b97..000000000 --- a/modules/ffmpeg/producer/filter/parallel_yadif.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/* -* Copyright 2013 Sveriges Television AB http://casparcg.com/ -* -* This file is part of CasparCG (www.casparcg.com). -* -* CasparCG is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* CasparCG is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with CasparCG. If not, see . -* -* Author: Robert Nagy, ronag89@gmail.com -*/ - -#include "../../StdAfx.h" - -#include "parallel_yadif.h" - -#include - -#if defined(_MSC_VER) -#pragma warning (push) -#pragma warning (disable : 4244) -#endif -extern "C" -{ - #include -} -#if defined(_MSC_VER) -#pragma warning (pop) -#endif - -#include -#include - -#include - -typedef struct { - int mode; - int parity; - int frame_pending; - int auto_enable; - AVFilterBufferRef *cur; - AVFilterBufferRef *next; - AVFilterBufferRef *prev; - AVFilterBufferRef *out; - void (*filter_line)(uint8_t *dst, - uint8_t *prev, uint8_t *cur, uint8_t *next, - int w, int prefs, int mrefs, int parity, int mode); - //const AVPixFmtDescriptor *csp; -} YADIFContext; - -struct parallel_yadif_context -{ - struct arg - { - uint8_t *dst; - uint8_t *prev; - uint8_t *cur; - uint8_t *next; - int w; - int prefs; - int mrefs; - int parity; - int mode; - }; - - arg args[1080]; - int index; - int last_index; - - parallel_yadif_context() : index(0){} -}; - -void (*org_yadif_filter_line)(uint8_t *dst, uint8_t *prev, uint8_t *cur, uint8_t *next, int w, int prefs, int mrefs, int parity, int mode) = 0; - -void parallel_yadif_filter_line(parallel_yadif_context& ctx, uint8_t *dst, uint8_t *prev, uint8_t *cur, uint8_t *next, int w, int prefs, int mrefs, int parity, int mode) -{ - parallel_yadif_context::arg arg = {dst, prev, cur, next, w, prefs, mrefs, parity, mode}; - ctx.args[ctx.index++] = arg; - - if(ctx.index == ctx.last_index) - { - tbb::parallel_for(tbb::blocked_range(0, ctx.index), [=](const tbb::blocked_range& r) - { - for(auto n = r.begin(); n != r.end(); ++n) - org_yadif_filter_line(ctx.args[n].dst, ctx.args[n].prev, ctx.args[n].cur, ctx.args[n].next, ctx.args[n].w, ctx.args[n].prefs, ctx.args[n].mrefs, ctx.args[n].parity, ctx.args[n].mode); - }); - ctx.index = 0; - } -} - -namespace caspar { namespace ffmpeg { - -tbb::concurrent_bounded_queue parallel_line_func_pool; -std::array ctxs; - -#define RENAME(a) f ## a - -#define ff(x) \ -void RENAME(x)(uint8_t *dst, uint8_t *prev, uint8_t *cur, uint8_t *next, int w, int prefs, int mrefs, int parity, int mode) \ -{\ - parallel_yadif_filter_line(ctxs[x], dst, prev, cur, next, w, prefs, mrefs, parity, mode);\ -} - -ff(0); ff(1); ff(2); ff(3); ff(4); ff(5); ff(6); ff(7); ff(8); ff(9); ff(10); ff(11); ff(12); ff(13); ff(14); ff(15); ff(16); ff(17); - -void (*fs[])(uint8_t *dst, uint8_t *prev, uint8_t *cur, uint8_t *next, int w, int prefs, int mrefs, int parity, int mode) = -{f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17}; - - -void init_pool() -{ - for(int n = 0; n < sizeof(fs)/sizeof(fs[0]); ++n) - parallel_line_func_pool.push(fs[n]); -} - -void return_parallel_yadif(void* func) -{ - if(func != nullptr) - parallel_line_func_pool.push(reinterpret_cast(func)); -} - -std::shared_ptr make_parallel_yadif(AVFilterContext* ctx) -{ - static boost::once_flag flag = BOOST_ONCE_INIT; - boost::call_once(&init_pool, flag); - - YADIFContext* yadif = (YADIFContext*)ctx->priv; - org_yadif_filter_line = yadif->filter_line; // Data race is not a problem. - - decltype(org_yadif_filter_line) func = nullptr; - if(!parallel_line_func_pool.try_pop(func)) - CASPAR_LOG(warning) << "Not enough scalable-yadif context instances. Running non-scalable"; - else - { - int index = 0; - while(index < sizeof(fs)/sizeof(fs[0]) && fs[index] != func) - ++index; - - ctxs[index].last_index = 0; - for (int y = 0; y < ctx->inputs[0]->h; y++) - { - if ((y ^ yadif->parity) & 1) - ++ctxs[index].last_index; - } - - yadif->filter_line = func; - } - - return std::shared_ptr(func, return_parallel_yadif); -} - -}} \ No newline at end of file diff --git a/modules/ffmpeg/producer/filter/parallel_yadif.h b/modules/ffmpeg/producer/filter/parallel_yadif.h deleted file mode 100644 index 8d0f60500..000000000 --- a/modules/ffmpeg/producer/filter/parallel_yadif.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -* Copyright 2013 Sveriges Television AB http://casparcg.com/ -* -* This file is part of CasparCG (www.casparcg.com). -* -* CasparCG is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* CasparCG is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with CasparCG. If not, see . -* -* Author: Robert Nagy, ronag89@gmail.com -*/ - -#pragma once - -#include - -struct AVFilterContext; - -namespace caspar { namespace ffmpeg { - -std::shared_ptr make_parallel_yadif(AVFilterContext* ctx); - -}} \ No newline at end of file diff --git a/modules/ffmpeg/producer/filter/scalable_yadif/scalable_yadif.cpp b/modules/ffmpeg/producer/filter/scalable_yadif/scalable_yadif.cpp deleted file mode 100644 index aa35e0aa4..000000000 --- a/modules/ffmpeg/producer/filter/scalable_yadif/scalable_yadif.cpp +++ /dev/null @@ -1,429 +0,0 @@ -#include "../../../StdAfx.h" - -#include "scalable_yadif.h" - - -/* - * Copyright (C) 2006-2010 Michael Niedermayer - * 2010 James Darnley - * - * FFmpeg is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with FFmpeg; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#pragma warning(push, 0) - - -#undef NDEBUG -#include - -typedef struct { - /** - * 0: send 1 frame for each frame - * 1: send 1 frame for each field - * 2: like 0 but skips spatial interlacing check - * 3: like 1 but skips spatial interlacing check - */ - int mode; - - /** - * 0: bottom field first - * 1: top field first - * -1: auto-detection - */ - int parity; - - int frame_pending; - - /** - * 0: deinterlace all frames - * 1: only deinterlace frames marked as interlaced - */ - int auto_enable; - - AVFilterBufferRef *cur; - AVFilterBufferRef *next; - AVFilterBufferRef *prev; - AVFilterBufferRef *out; - void (*filter_line)(uint8_t *dst, - uint8_t *prev, uint8_t *cur, uint8_t *next, - int w, int prefs, int mrefs, int parity, int mode); - - const AVPixFmtDescriptor *csp; -} YADIFContext; - -#define CHECK(j)\ - { int score = FFABS(cur[mrefs-1+(j)] - cur[prefs-1-(j)])\ - + FFABS(cur[mrefs +(j)] - cur[prefs -(j)])\ - + FFABS(cur[mrefs+1+(j)] - cur[prefs+1-(j)]);\ - if (score < spatial_score) {\ - spatial_score= score;\ - spatial_pred= (cur[mrefs +(j)] + cur[prefs -(j)])>>1;\ - -#define FILTER \ - for (x = 0; x < w; x++) { \ - int c = cur[mrefs]; \ - int d = (prev2[0] + next2[0])>>1; \ - int e = cur[prefs]; \ - int temporal_diff0 = FFABS(prev2[0] - next2[0]); \ - int temporal_diff1 =(FFABS(prev[mrefs] - c) + FFABS(prev[prefs] - e) )>>1; \ - int temporal_diff2 =(FFABS(next[mrefs] - c) + FFABS(next[prefs] - e) )>>1; \ - int diff = FFMAX3(temporal_diff0>>1, temporal_diff1, temporal_diff2); \ - int spatial_pred = (c+e)>>1; \ - int spatial_score = FFABS(cur[mrefs-1] - cur[prefs-1]) + FFABS(c-e) \ - + FFABS(cur[mrefs+1] - cur[prefs+1]) - 1; \ - \ - CHECK(-1) CHECK(-2) }} }} \ - CHECK( 1) CHECK( 2) }} }} \ - \ - if (mode < 2) { \ - int b = (prev2[2*mrefs] + next2[2*mrefs])>>1; \ - int f = (prev2[2*prefs] + next2[2*prefs])>>1; \ - int max = FFMAX3(d-e, d-c, FFMIN(b-c, f-e)); \ - int min = FFMIN3(d-e, d-c, FFMAX(b-c, f-e)); \ - \ - diff = FFMAX3(diff, min, -max); \ - } \ - \ - if (spatial_pred > d + diff) \ - spatial_pred = d + diff; \ - else if (spatial_pred < d - diff) \ - spatial_pred = d - diff; \ - \ - dst[0] = spatial_pred; \ - \ - dst++; \ - cur++; \ - prev++; \ - next++; \ - prev2++; \ - next2++; \ - } - -void filter_line_c(uint8_t *dst, - uint8_t *prev, uint8_t *cur, uint8_t *next, - int w, int prefs, int mrefs, int parity, int mode) -{ - int x; - uint8_t *prev2 = parity ? prev : cur ; - uint8_t *next2 = parity ? cur : next; - - FILTER -} - -void filter_line_c_16bit(uint16_t *dst, - uint16_t *prev, uint16_t *cur, uint16_t *next, - int w, int prefs, int mrefs, int parity, int mode) -{ - int x; - uint16_t *prev2 = parity ? prev : cur ; - uint16_t *next2 = parity ? cur : next; - mrefs /= 2; - prefs /= 2; - - FILTER -} - -void filter(AVFilterContext *ctx, AVFilterBufferRef *dstpic, - int parity, int tff) -{ - YADIFContext *yadif = (YADIFContext*)ctx->priv; - int y, i; - - for (i = 0; i < yadif->csp->nb_components; i++) { - int w = dstpic->video->w; - int h = dstpic->video->h; - int refs = yadif->cur->linesize[i]; - int df = (yadif->csp->comp[i].depth_minus1+1) / 8; - - if (i) { - /* Why is this not part of the per-plane description thing? */ - w >>= yadif->csp->log2_chroma_w; - h >>= yadif->csp->log2_chroma_h; - } - - for (y = 0; y < h; y++) { - if ((y ^ parity) & 1) { - uint8_t *prev = &yadif->prev->data[i][y*refs]; - uint8_t *cur = &yadif->cur ->data[i][y*refs]; - uint8_t *next = &yadif->next->data[i][y*refs]; - uint8_t *dst = &dstpic->data[i][y*dstpic->linesize[i]]; - int mode = y==1 || y+2==h ? 2 : yadif->mode; - yadif->filter_line(dst, prev, cur, next, w, y+1data[i][y*dstpic->linesize[i]], - &yadif->cur->data[i][y*refs], w*df); - } - } - } - //__asm__ volatile("emms \n\t" : : : "memory"); -} - -AVFilterBufferRef *get_video_buffer(AVFilterLink *link, int perms, int w, int h) -{ - AVFilterBufferRef *picref; - int width = FFALIGN(w, 32); - int height= FFALIGN(h+2, 32); - int i; - - picref = avfilter_default_get_video_buffer(link, perms, width, height); - - picref->video->w = w; - picref->video->h = h; - - for (i = 0; i < 3; i++) - picref->data[i] += picref->linesize[i]; - - return picref; -} - -void return_frame(AVFilterContext *ctx, int is_second) -{ - YADIFContext *yadif = (YADIFContext*)ctx->priv; - AVFilterLink *link= ctx->outputs[0]; - int tff; - - if (yadif->parity == -1) { - tff = yadif->cur->video->interlaced ? - yadif->cur->video->top_field_first : 1; - } else { - tff = yadif->parity^1; - } - - if (is_second) - yadif->out = avfilter_get_video_buffer(link, AV_PERM_WRITE | AV_PERM_PRESERVE | - AV_PERM_REUSE, link->w, link->h); - - if (!yadif->csp) - yadif->csp = &av_pix_fmt_descriptors[link->format]; - if (yadif->csp->comp[0].depth_minus1 == 15) - yadif->filter_line = (decltype(yadif->filter_line))filter_line_c_16bit; - - filter(ctx, yadif->out, tff ^ !is_second, tff); - - if (is_second) { - if (yadif->next->pts != AV_NOPTS_VALUE && - yadif->cur->pts != AV_NOPTS_VALUE) { - yadif->out->pts = - (yadif->next->pts&yadif->cur->pts) + - ((yadif->next->pts^yadif->cur->pts)>>1); - } else { - yadif->out->pts = AV_NOPTS_VALUE; - } - avfilter_start_frame(ctx->outputs[0], yadif->out); - } - avfilter_draw_slice(ctx->outputs[0], 0, link->h, 1); - avfilter_end_frame(ctx->outputs[0]); - - yadif->frame_pending = (yadif->mode&1) && !is_second; -} - -void start_frame(AVFilterLink *link, AVFilterBufferRef *picref) -{ - AVFilterContext *ctx = link->dst; - YADIFContext *yadif = (YADIFContext*)ctx->priv; - - if (yadif->frame_pending) - return_frame(ctx, 1); - - if (yadif->prev) - avfilter_unref_buffer(yadif->prev); - yadif->prev = yadif->cur; - yadif->cur = yadif->next; - yadif->next = picref; - - if (!yadif->cur) - return; - - if (yadif->auto_enable && !yadif->cur->video->interlaced) { - yadif->out = avfilter_ref_buffer(yadif->cur, AV_PERM_READ); - avfilter_unref_buffer(yadif->prev); - yadif->prev = NULL; - avfilter_start_frame(ctx->outputs[0], yadif->out); - return; - } - - if (!yadif->prev) - yadif->prev = avfilter_ref_buffer(yadif->cur, AV_PERM_READ); - - yadif->out = avfilter_get_video_buffer(ctx->outputs[0], AV_PERM_WRITE | AV_PERM_PRESERVE | - AV_PERM_REUSE, link->w, link->h); - - avfilter_copy_buffer_ref_props(yadif->out, yadif->cur); - yadif->out->video->interlaced = 0; - avfilter_start_frame(ctx->outputs[0], yadif->out); -} - -void end_frame(AVFilterLink *link) -{ - AVFilterContext *ctx = link->dst; - YADIFContext *yadif = (YADIFContext*)ctx->priv; - - if (!yadif->out) - return; - - if (yadif->auto_enable && !yadif->cur->video->interlaced) { - avfilter_draw_slice(ctx->outputs[0], 0, link->h, 1); - avfilter_end_frame(ctx->outputs[0]); - return; - } - - return_frame(ctx, 0); -} - -int request_frame(AVFilterLink *link) -{ - AVFilterContext *ctx = link->src; - YADIFContext *yadif = (YADIFContext*)ctx->priv; - - if (yadif->frame_pending) { - return_frame(ctx, 1); - return 0; - } - - do { - int ret; - ret = avfilter_request_frame(link->src->inputs[0]); - if (ret) - return ret; - } while (!yadif->cur); - - return 0; -} - -int poll_frame(AVFilterLink *link) -{ - YADIFContext *yadif = (YADIFContext*)link->src->priv; - int ret, val; - - if (yadif->frame_pending) - return 1; - - val = avfilter_poll_frame(link->src->inputs[0]); - - if (val==1 && !yadif->next) { //FIXME change API to not requre this red tape - if ((ret = avfilter_request_frame(link->src->inputs[0])) < 0) - return ret; - val = avfilter_poll_frame(link->src->inputs[0]); - } - assert(yadif->next || !val); - - if (yadif->auto_enable && yadif->next && !yadif->next->video->interlaced) - return val; - - return val * ((yadif->mode&1)+1); -} - -void uninit(AVFilterContext *ctx) -{ - YADIFContext *yadif = (YADIFContext*)ctx->priv; - - if (yadif->prev) avfilter_unref_buffer(yadif->prev); - if (yadif->cur ) avfilter_unref_buffer(yadif->cur ); - if (yadif->next) avfilter_unref_buffer(yadif->next); -} - -int query_formats(AVFilterContext *ctx) -{ - static const enum PixelFormat pix_fmts[] = { - PIX_FMT_YUV420P, - PIX_FMT_YUV422P, - PIX_FMT_YUV444P, - PIX_FMT_YUV410P, - PIX_FMT_YUV411P, - PIX_FMT_GRAY8, - PIX_FMT_YUVJ420P, - PIX_FMT_YUVJ422P, - PIX_FMT_YUVJ444P, - AV_NE( PIX_FMT_GRAY16BE, PIX_FMT_GRAY16LE ), - PIX_FMT_YUV440P, - PIX_FMT_YUVJ440P, - AV_NE( PIX_FMT_YUV420P16BE, PIX_FMT_YUV420P16LE ), - AV_NE( PIX_FMT_YUV422P16BE, PIX_FMT_YUV422P16LE ), - AV_NE( PIX_FMT_YUV444P16BE, PIX_FMT_YUV444P16LE ), - PIX_FMT_NONE - }; - - avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list((const int*)pix_fmts)); - - return 0; -} - -int init(AVFilterContext *ctx, const char *args, void *opaque) -{ - YADIFContext *yadif = (YADIFContext*)ctx->priv; - av_unused int cpu_flags = av_get_cpu_flags(); - - yadif->mode = 0; - yadif->parity = -1; - yadif->auto_enable = 0; - yadif->csp = NULL; - - if (args) sscanf(args, "%d:%d:%d", &yadif->mode, &yadif->parity, &yadif->auto_enable); - - - auto module = LoadLibrary(L"avfilter-2.dll"); - static std::shared_ptr lib(module, FreeLibrary); - yadif->filter_line = (decltype(yadif->filter_line))(GetProcAddress(module, "ff_yadif_filter_line_ssse3")); - - //yadif->filter_line = filter_line_c; - //if (HAVE_SSSE3 && cpu_flags & AV_CPU_FLAG_SSSE3) - // yadif->filter_line = ff_yadif_filter_line_ssse3; - //else if (HAVE_SSE && cpu_flags & AV_CPU_FLAG_SSE2) - // yadif->filter_line = ff_yadif_filter_line_sse2; - //else if (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) - // yadif->filter_line = ff_yadif_filter_line_mmx; - - av_log(ctx, AV_LOG_INFO, "mode:%d parity:%d auto_enable:%d\n", yadif->mode, yadif->parity, yadif->auto_enable); - - return 0; -} - -void null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) { } - -void register_scalable_yadif() -{ - static AVFilter avfilter_vf_syadif; - avfilter_vf_syadif.name = "syadif"; - avfilter_vf_syadif .description = "Deinterlace the input image"; - - avfilter_vf_syadif.priv_size = sizeof(YADIFContext); - avfilter_vf_syadif.init = init; - avfilter_vf_syadif.uninit = uninit; - avfilter_vf_syadif.query_formats = query_formats; - - static AVFilterPad inputs[2]; - - inputs[0].name = "default"; - inputs[0].type = AVMEDIA_TYPE_VIDEO, - inputs[0].start_frame = start_frame; - inputs[0].get_video_buffer = get_video_buffer; - inputs[0].draw_slice = null_draw_slice; - inputs[0].end_frame = end_frame; - inputs[1].name = nullptr; - - avfilter_vf_syadif.inputs = inputs; - - static AVFilterPad outputs[2]; - - outputs[0].name = "default"; - outputs[0].type = AVMEDIA_TYPE_VIDEO; - outputs[0].poll_frame = poll_frame; - outputs[0].request_frame = request_frame; - outputs[1].name = nullptr; - - avfilter_vf_syadif.outputs = outputs; - - avfilter_register(&avfilter_vf_syadif); -}; diff --git a/modules/ffmpeg/producer/filter/scalable_yadif/scalable_yadif.h b/modules/ffmpeg/producer/filter/scalable_yadif/scalable_yadif.h deleted file mode 100644 index e73405744..000000000 --- a/modules/ffmpeg/producer/filter/scalable_yadif/scalable_yadif.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -extern "C" -{ - #define __STDC_CONSTANT_MACROS - #define __STDC_LIMIT_MACROS - #include - #include - #include - #include -} - -int init(AVFilterContext *ctx, const char *args, void *opaque); -void uninit(AVFilterContext *ctx); -int query_formats(AVFilterContext *ctx); -int poll_frame(AVFilterLink *link); -int request_frame(AVFilterLink *link); -void start_frame(AVFilterLink *link, AVFilterBufferRef *picref); -void end_frame(AVFilterLink *link); -void return_frame(AVFilterContext *ctx, int is_second); -AVFilterBufferRef *get_video_buffer(AVFilterLink *link, int perms, int w, int h); - -void register_scalable_yadif(); \ No newline at end of file