std::shared_ptr<AVFilterGraph> graph_;\r
AVFilterContext* video_in_filter_;\r
AVFilterContext* video_out_filter_;\r
+ size_t delay_;\r
+ size_t count_;\r
\r
implementation(const std::string& filters) \r
: filters_(filters)\r
+ , delay_(0)\r
+ , count_(0)\r
{\r
std::transform(filters_.begin(), filters_.end(), filters_.begin(), ::tolower);\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
+ ++count_;\r
}\r
\r
std::vector<safe_ptr<AVFrame>> poll()\r
{\r
+ std::vector<safe_ptr<AVFrame>> result;\r
+\r
+ if(!graph_)\r
+ return result;\r
+\r
int errn = avfilter_poll_frame(video_out_filter_->inputs[0]);\r
if(errn < 0)\r
{\r
boost::errinfo_api_function("avfilter_poll_frame") << boost::errinfo_errno(AVUNERROR(errn)));\r
}\r
\r
- std::vector<safe_ptr<AVFrame>> result;\r
-\r
+ if(count_ > 0)\r
+ {\r
+ --count_;\r
+ if(errn == 0)\r
+ ++delay_;\r
+ }\r
+ \r
std::generate_n(std::back_inserter(result), errn, [&]{return request_frame();});\r
\r
return result;\r
filter::filter(const std::string& filters) : impl_(new implementation(filters)){}\r
void filter::push(const safe_ptr<AVFrame>& frame) {impl_->push(frame);}\r
std::vector<safe_ptr<AVFrame>> filter::poll() {return impl_->poll();}\r
-bool filter::is_ready() const{return impl_->graph_ != nullptr;}\r
-\r
+size_t filter::delay() const{return impl_->delay_;}\r
}
\ No newline at end of file
\r
void push(const safe_ptr<AVFrame>& frame);\r
std::vector<safe_ptr<AVFrame>> poll();\r
- bool is_ready() const;\r
+ size_t delay() const;\r
\r
private:\r
struct implementation;\r
size_t frame_number_;\r
\r
std::shared_ptr<filter> filter_;\r
- size_t filter_delay_;\r
int eof_count_;\r
\r
std::string filter_str_;\r
, codec_context_(*input_.get_video_codec_context())\r
, frame_number_(0)\r
, filter_(filter_str.empty() ? nullptr : new filter(filter_str))\r
- , filter_delay_(1)\r
, filter_str_(filter_str)\r
, eof_count_(std::numeric_limits<int>::max())\r
{\r
\r
if(!video_packet) // eof\r
{\r
- eof_count_ = frame_number_ + (filter_ ? filter_delay_ : 0);\r
+ eof_count_ = frame_number_ + (filter_ ? filter_->delay()+1 : 0);\r
avcodec_flush_buffers(&codec_context_);\r
return result;\r
} \r
frame = decode_frame(video_packet);\r
},\r
[&]\r
- {\r
- if(filter_->is_ready())\r
- { \r
- boost::range::transform(filter_->poll(), std::back_inserter(result), [&](const safe_ptr<AVFrame>& frame)\r
- {\r
- return std::make_pair(frame_number_, make_write_frame(tag, frame, frame_factory_));\r
- });\r
+ { \r
+ boost::range::transform(filter_->poll(), std::back_inserter(result), [&](const safe_ptr<AVFrame>& frame)\r
+ {\r
+ return std::make_pair(frame_number_, make_write_frame(tag, frame, frame_factory_));\r
+ });\r
\r
- if(!result.empty())\r
- ++frame_number_;\r
- else \r
- ++filter_delay_;\r
- }\r
+ if(!result.empty())\r
+ ++frame_number_;\r
}); \r
\r
if(frame)\r
\r
if(frame_finished == 0) \r
decoded_frame = nullptr;\r
-\r
+ \r
return decoded_frame;\r
}\r
};\r