1 #include "../../stdafx.h"
\r
5 #include "parallel_yadif.h"
\r
7 #include "../../ffmpeg_error.h"
\r
9 #include <boost/assign.hpp>
\r
14 #if defined(_MSC_VER)
\r
15 #pragma warning (push)
\r
16 #pragma warning (disable : 4244)
\r
20 #include <libavutil/avutil.h>
\r
21 #include <libavutil/imgutils.h>
\r
22 #include <libavfilter/avfilter.h>
\r
23 #include <libavfilter/avcodec.h>
\r
24 #include <libavfilter/avfiltergraph.h>
\r
25 #include <libavfilter/vsink_buffer.h>
\r
26 #include <libavfilter/vsrc_buffer.h>
\r
28 #if defined(_MSC_VER)
\r
29 #pragma warning (pop)
\r
34 PixelFormat pix_fmts[] =
\r
48 struct filter::implementation
\r
50 std::string filters_;
\r
51 std::shared_ptr<AVFilterGraph> graph_;
\r
52 AVFilterContext* buffersink_ctx_;
\r
53 AVFilterContext* buffersrc_ctx_;
\r
54 std::shared_ptr<void> parallel_yadif_ctx_;
\r
56 implementation(const std::wstring& filters)
\r
57 : filters_(narrow(filters))
\r
58 , parallel_yadif_ctx_(nullptr)
\r
60 std::transform(filters_.begin(), filters_.end(), filters_.begin(), ::tolower);
\r
63 std::vector<safe_ptr<AVFrame>> execute(const std::shared_ptr<AVFrame>& frame)
\r
66 return std::vector<safe_ptr<AVFrame>>();
\r
68 if(filters_.empty())
\r
69 return boost::assign::list_of(frame);
\r
75 void push(const std::shared_ptr<AVFrame>& frame)
\r
80 graph_.reset(avfilter_graph_alloc(), [](AVFilterGraph* p){avfilter_graph_free(&p);});
\r
83 std::stringstream args;
\r
84 args << frame->width << ":" << frame->height << ":" << frame->format << ":" << 0 << ":" << 0 << ":" << 0 << ":" << 0; // don't care about pts and aspect_ratio
\r
85 THROW_ON_ERROR2(avfilter_graph_create_filter(&buffersrc_ctx_, avfilter_get_by_name("buffer"), "src", args.str().c_str(), NULL, graph_.get()), "[filter]");
\r
87 // OPIX_FMT_BGRAutput
\r
88 THROW_ON_ERROR2(avfilter_graph_create_filter(&buffersink_ctx_, avfilter_get_by_name("buffersink"), "out", NULL, pix_fmts, graph_.get()), "[filter]");
\r
90 AVFilterInOut* outputs = avfilter_inout_alloc();
\r
91 AVFilterInOut* inputs = avfilter_inout_alloc();
\r
93 outputs->name = av_strdup("in");
\r
94 outputs->filter_ctx = buffersrc_ctx_;
\r
95 outputs->pad_idx = 0;
\r
96 outputs->next = NULL;
\r
98 inputs->name = av_strdup("out");
\r
99 inputs->filter_ctx = buffersink_ctx_;
\r
100 inputs->pad_idx = 0;
\r
101 inputs->next = NULL;
\r
103 THROW_ON_ERROR2(avfilter_graph_parse(graph_.get(), filters_.c_str(), &inputs, &outputs, NULL), "[filter]");
\r
105 avfilter_inout_free(&inputs);
\r
106 avfilter_inout_free(&outputs);
\r
108 THROW_ON_ERROR2(avfilter_graph_config(graph_.get(), NULL), "[filter]");
\r
110 for(size_t n = 0; n < graph_->filter_count; ++n)
\r
112 auto filter_name = graph_->filters[n]->name;
\r
113 if(strstr(filter_name, "yadif") != 0)
\r
114 parallel_yadif_ctx_ = make_parallel_yadif(graph_->filters[n]);
\r
118 THROW_ON_ERROR2(av_vsrc_buffer_add_frame(buffersrc_ctx_, frame.get(), 0), "[filter]");
\r
121 std::vector<safe_ptr<AVFrame>> poll()
\r
123 std::vector<safe_ptr<AVFrame>> result;
\r
128 while (avfilter_poll_frame(buffersink_ctx_->inputs[0]))
\r
130 AVFilterBufferRef *picref;
\r
131 THROW_ON_ERROR2(av_vsink_buffer_get_video_buffer_ref(buffersink_ctx_, &picref, 0), "[filter]");
\r
135 safe_ptr<AVFrame> frame(avcodec_alloc_frame(), [=](AVFrame* p)
\r
138 avfilter_unref_buffer(picref);
\r
141 avcodec_get_frame_defaults(frame.get());
\r
143 memcpy(frame->data, picref->data, sizeof(frame->data));
\r
144 memcpy(frame->linesize, picref->linesize, sizeof(frame->linesize));
\r
145 frame->format = picref->format;
\r
146 frame->width = picref->video->w;
\r
147 frame->height = picref->video->h;
\r
148 frame->pkt_pos = picref->pos;
\r
149 frame->interlaced_frame = picref->video->interlaced;
\r
150 frame->top_field_first = picref->video->top_field_first;
\r
151 frame->key_frame = picref->video->key_frame;
\r
152 frame->pict_type = picref->video->pict_type;
\r
153 frame->sample_aspect_ratio = picref->video->sample_aspect_ratio;
\r
155 result.push_back(frame);
\r
163 filter::filter(const std::wstring& filters) : impl_(new implementation(filters)){}
\r
164 filter::filter(filter&& other) : impl_(std::move(other.impl_)){}
\r
165 filter& filter::operator=(filter&& other){impl_ = std::move(other.impl_); return *this;}
\r
166 std::vector<safe_ptr<AVFrame>> filter::execute(const std::shared_ptr<AVFrame>& frame) {return impl_->execute(frame);}
\r