\r
#include "../../ffmpeg_error.h"\r
\r
-#include <common/exception/exceptions.h>\r
-#include <core/producer/frame/basic_frame.h>\r
-#include <core/producer/frame/frame_factory.h>\r
-#include <core/mixer/write_frame.h>\r
-\r
-#include <boost/circular_buffer.hpp>\r
-\r
-#include <tbb/task_group.h>\r
+#include <boost/assign.hpp>\r
\r
#include <cstdio>\r
#include <sstream>\r
\r
+#if defined(_MSC_VER)\r
+#pragma warning (push)\r
+#pragma warning (disable : 4244)\r
+#endif\r
extern "C" \r
{\r
- #define __STDC_CONSTANT_MACROS\r
- #define __STDC_LIMIT_MACROS\r
#include <libavutil/avutil.h>\r
#include <libavutil/imgutils.h>\r
#include <libavfilter/avfilter.h>\r
#include <libavfilter/avcodec.h>\r
#include <libavfilter/avfiltergraph.h>\r
- #include <libavfilter/vsink_buffer.h>\r
+ #include <libavfilter/buffersink.h>\r
#include <libavfilter/vsrc_buffer.h>\r
}\r
+#if defined(_MSC_VER)\r
+#pragma warning (pop)\r
+#endif\r
\r
-namespace caspar {\r
+namespace caspar { namespace ffmpeg {\r
\r
-PixelFormat pix_fmts[] = \r
-{\r
- PIX_FMT_YUV420P,\r
- PIX_FMT_YUVA420P,\r
- PIX_FMT_YUV422P,\r
- PIX_FMT_YUV444P,\r
- PIX_FMT_YUV411P,\r
- PIX_FMT_ARGB, \r
- PIX_FMT_RGBA,\r
- PIX_FMT_ABGR,\r
- PIX_FMT_GRAY8,\r
- PIX_FMT_NONE\r
-}; \r
-\r
struct filter::implementation\r
{\r
std::string filters_;\r
AVFilterContext* buffersink_ctx_;\r
AVFilterContext* buffersrc_ctx_;\r
std::shared_ptr<void> parallel_yadif_ctx_;\r
+ std::vector<PixelFormat> pix_fmts_;\r
\r
- implementation(const std::wstring& filters) \r
+ implementation(const std::wstring& filters, const std::vector<PixelFormat>& pix_fmts) \r
: filters_(narrow(filters))\r
, parallel_yadif_ctx_(nullptr)\r
+ , pix_fmts_(pix_fmts)\r
{\r
+ if(pix_fmts_.empty())\r
+ {\r
+ pix_fmts_.push_back(PIX_FMT_YUV420P);\r
+ pix_fmts_.push_back(PIX_FMT_YUVA420P);\r
+ pix_fmts_.push_back(PIX_FMT_YUV422P);\r
+ pix_fmts_.push_back(PIX_FMT_YUV444P);\r
+ pix_fmts_.push_back(PIX_FMT_YUV411P);\r
+ pix_fmts_.push_back(PIX_FMT_ARGB);\r
+ pix_fmts_.push_back(PIX_FMT_RGBA);\r
+ pix_fmts_.push_back(PIX_FMT_ABGR);\r
+ pix_fmts_.push_back(PIX_FMT_GRAY8);\r
+ pix_fmts_.push_back(PIX_FMT_NONE);\r
+ }\r
+ else\r
+ pix_fmts_.push_back(PIX_FMT_NONE);\r
+\r
std::transform(filters_.begin(), filters_.end(), filters_.begin(), ::tolower);\r
}\r
\r
\r
void push(const std::shared_ptr<AVFrame>& frame)\r
{ \r
- int errn = 0; \r
-\r
if(!graph_)\r
{\r
graph_.reset(avfilter_graph_alloc(), [](AVFilterGraph* p){avfilter_graph_free(&p);});\r
// Input\r
std::stringstream args;\r
args << frame->width << ":" << frame->height << ":" << frame->format << ":" << 0 << ":" << 0 << ":" << 0 << ":" << 0; // don't care about pts and aspect_ratio\r
- errn = avfilter_graph_create_filter(&buffersrc_ctx_, avfilter_get_by_name("buffer"), "src", args.str().c_str(), NULL, graph_.get());\r
- if(errn < 0)\r
- {\r
- BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(av_error_str(errn)) <<\r
- boost::errinfo_api_function("avfilter_graph_create_filter") << boost::errinfo_errno(AVUNERROR(errn)));\r
- }\r
+ THROW_ON_ERROR2(avfilter_graph_create_filter(&buffersrc_ctx_, avfilter_get_by_name("buffer"), "src", args.str().c_str(), NULL, graph_.get()), "[filter]");\r
\r
// OPIX_FMT_BGRAutput\r
- errn = avfilter_graph_create_filter(&buffersink_ctx_, avfilter_get_by_name("buffersink"), "out", NULL, pix_fmts, graph_.get());\r
- if(errn < 0)\r
- {\r
- BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(av_error_str(errn)) <<\r
- boost::errinfo_api_function("avfilter_graph_create_filter") << boost::errinfo_errno(AVUNERROR(errn)));\r
- }\r
+ AVBufferSinkParams *buffersink_params = av_buffersink_params_alloc();\r
+ buffersink_params->pixel_fmts = pix_fmts_.data();\r
+ THROW_ON_ERROR2(avfilter_graph_create_filter(&buffersink_ctx_, avfilter_get_by_name("buffersink"), "out", NULL, buffersink_params, graph_.get()), "[filter]");\r
\r
AVFilterInOut* outputs = avfilter_inout_alloc();\r
AVFilterInOut* inputs = avfilter_inout_alloc();\r
-\r
+ \r
outputs->name = av_strdup("in");\r
outputs->filter_ctx = buffersrc_ctx_;\r
outputs->pad_idx = 0;\r
inputs->pad_idx = 0;\r
inputs->next = NULL;\r
\r
- errn = avfilter_graph_parse(graph_.get(), filters_.c_str(), &inputs, &outputs, NULL);\r
-\r
+ THROW_ON_ERROR2(avfilter_graph_parse(graph_.get(), filters_.c_str(), &inputs, &outputs, NULL), "[filter]");\r
+ \r
avfilter_inout_free(&inputs);\r
avfilter_inout_free(&outputs);\r
\r
- if(errn < 0)\r
- {\r
- BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(av_error_str(errn)) <<\r
- boost::errinfo_api_function("avfilter_graph_parse") << boost::errinfo_errno(AVUNERROR(errn)));\r
- }\r
- \r
- errn = avfilter_graph_config(graph_.get(), NULL);\r
- if(errn < 0)\r
- {\r
- BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(av_error_str(errn)) \r
- << boost::errinfo_api_function("avfilter_graph_config") << boost::errinfo_errno(AVUNERROR(errn)));\r
- }\r
+ THROW_ON_ERROR2(avfilter_graph_config(graph_.get(), NULL), "[filter]"); \r
\r
for(size_t n = 0; n < graph_->filter_count; ++n)\r
{\r
}\r
}\r
\r
- errn = av_vsrc_buffer_add_frame(buffersrc_ctx_, frame.get(), 0);\r
- if(errn < 0)\r
- {\r
- BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(av_error_str(errn)) <<\r
- boost::errinfo_api_function("av_vsrc_buffer_add_frame") << boost::errinfo_errno(AVUNERROR(errn)));\r
- }\r
+ THROW_ON_ERROR2(av_vsrc_buffer_add_frame(buffersrc_ctx_, frame.get(), 0), "[filter]");\r
}\r
\r
std::vector<safe_ptr<AVFrame>> poll()\r
while (avfilter_poll_frame(buffersink_ctx_->inputs[0])) \r
{\r
AVFilterBufferRef *picref;\r
- av_vsink_buffer_get_video_buffer_ref(buffersink_ctx_, &picref, 0);\r
+ THROW_ON_ERROR2(av_buffersink_get_buffer_ref(buffersink_ctx_, &picref, 0), "[filter]");\r
+\r
if (picref) \r
{ \r
safe_ptr<AVFrame> frame(avcodec_alloc_frame(), [=](AVFrame* p)\r
}\r
};\r
\r
-filter::filter(const std::wstring& filters) : impl_(new implementation(filters)){}\r
+filter::filter(const std::wstring& filters, const std::vector<PixelFormat>& pix_fmts) : impl_(new implementation(filters, pix_fmts)){}\r
+filter::filter(filter&& other) : impl_(std::move(other.impl_)){}\r
+filter& filter::operator=(filter&& other){impl_ = std::move(other.impl_); return *this;}\r
std::vector<safe_ptr<AVFrame>> filter::execute(const std::shared_ptr<AVFrame>& frame) {return impl_->execute(frame);}\r
-}
\ No newline at end of file
+\r
+}}
\ No newline at end of file