\r
#include <core/video_format.h>\r
#include <core/producer/frame/basic_frame.h>\r
-#include <core/producer/frame/write_frame.h>\r
+#include <core/mixer/write_frame.h>\r
#include <core/producer/frame/image_transform.h>\r
#include <core/producer/frame/pixel_format.h>\r
#include <core/producer/frame/frame_factory.h>\r
#define __STDC_LIMIT_MACROS\r
#include <libswscale/swscale.h>\r
#include <libavformat/avformat.h>\r
+ #include <libavcodec/avcodec.h>\r
}\r
#if defined(_MSC_VER)\r
#pragma warning (pop)\r
const int height_;\r
const PixelFormat pix_fmt_;\r
core::pixel_format_desc desc_;\r
+ std::deque<safe_ptr<core::write_frame>> frames_;\r
+ size_t frame_number_;\r
\r
public:\r
explicit implementation(AVCodecContext& codec_context, const safe_ptr<core::frame_factory>& frame_factory) \r
, height_(codec_context_.height)\r
, pix_fmt_(codec_context_.pix_fmt)\r
, desc_(get_pixel_format_desc(pix_fmt_, width_, height_))\r
+ , frame_number_(0)\r
{\r
if(desc_.pix_fmt == core::pixel_format::invalid)\r
{\r
boost::errinfo_api_function("sws_getContext"));\r
}\r
}\r
- \r
- std::vector<safe_ptr<core::write_frame>> execute(void* tag, const packet& video_packet)\r
- { \r
- std::vector<safe_ptr<core::write_frame>> result;\r
\r
- switch(video_packet.type)\r
- {\r
- case flush_packet:\r
+ void push(const std::shared_ptr<AVPacket>& video_packet)\r
+ { \r
+ if(!video_packet)\r
+ { \r
avcodec_flush_buffers(&codec_context_);\r
- break;\r
- case data_packet: \r
- safe_ptr<AVFrame> decoded_frame(avcodec_alloc_frame(), av_free);\r
+ frame_number_ = 0;\r
+ return;\r
+ }\r
\r
- int frame_finished = 0;\r
- const int errn = avcodec_decode_video(&codec_context_, decoded_frame.get(), &frame_finished, video_packet.data->data(), video_packet.data->size());\r
- \r
- if(errn < 0)\r
- {\r
- BOOST_THROW_EXCEPTION(\r
- invalid_operation() <<\r
- msg_info(av_error_str(errn)) <<\r
- boost::errinfo_api_function("avcodec_decode_video") <<\r
- boost::errinfo_errno(AVUNERROR(errn)));\r
- }\r
+ safe_ptr<AVFrame> decoded_frame(avcodec_alloc_frame(), av_free);\r
+\r
+ int frame_finished = 0;\r
+ const int errn = avcodec_decode_video2(&codec_context_, decoded_frame.get(), &frame_finished, video_packet.get());\r
\r
- if(frame_finished != 0) \r
- result.push_back(make_write_frame(tag, decoded_frame));\r
+ if(errn < 0)\r
+ {\r
+ BOOST_THROW_EXCEPTION(\r
+ invalid_operation() <<\r
+ msg_info(av_error_str(errn)) <<\r
+ boost::errinfo_api_function("avcodec_decode_video") <<\r
+ boost::errinfo_errno(AVUNERROR(errn)));\r
}\r
-\r
- return result;\r
+ \r
+ if(frame_finished != 0) \r
+ frames_.push_back(make_write_frame(decoded_frame));\r
}\r
\r
- safe_ptr<core::write_frame> make_write_frame(void* tag, safe_ptr<AVFrame> decoded_frame)\r
+ safe_ptr<core::write_frame> make_write_frame(safe_ptr<AVFrame> decoded_frame)\r
{ \r
- auto write = frame_factory_->create_frame(tag, desc_);\r
+ auto write = frame_factory_->create_frame(this, desc_);\r
if(sws_context_ == nullptr)\r
{\r
tbb::parallel_for(0, static_cast<int>(desc_.planes.size()), 1, [&](int n)\r
auto decoded_linesize = decoded_frame->linesize[n];\r
\r
// Copy line by line since ffmpeg sometimes pads each line.\r
- tbb::parallel_for(0, static_cast<int>(desc_.planes[n].height), 1, [&](int y)\r
+ tbb::parallel_for(tbb::blocked_range<size_t>(0, static_cast<int>(desc_.planes[n].height)), [&](const tbb::blocked_range<size_t>& r)\r
{\r
- fast_memcpy(result + y*plane.linesize, decoded + y*decoded_linesize, plane.linesize);\r
+ for(size_t y = r.begin(); y != r.end(); ++y)\r
+ memcpy(result + y*plane.linesize, decoded + y*decoded_linesize, plane.linesize);\r
});\r
});\r
}\r
\r
return write;\r
}\r
+\r
+ bool empty() const\r
+ {\r
+ return frames_.empty();\r
+ }\r
+\r
+ safe_ptr<core::write_frame> front()\r
+ {\r
+ return frames_.front();\r
+ }\r
+\r
+ void pop()\r
+ {\r
+ ++frame_number_;\r
+ frames_.pop_front();\r
+ }\r
};\r
\r
video_decoder::video_decoder(AVCodecContext& codec_context, const safe_ptr<core::frame_factory>& frame_factory) : impl_(new implementation(codec_context, frame_factory)){}\r
-std::vector<safe_ptr<core::write_frame>> video_decoder::execute(void* tag, const packet& video_packet){return impl_->execute(tag, video_packet);}\r
+void video_decoder::push(const std::shared_ptr<AVPacket>& video_packet){impl_->push(std::move(video_packet));}\r
+bool video_decoder::empty() const {return impl_->empty();}\r
+safe_ptr<core::write_frame> video_decoder::front() {return impl_->front();}\r
+void video_decoder::pop(){impl_->pop();}\r
+size_t video_decoder::frame_number() const{return impl_->frame_number_;}\r
\r
}
\ No newline at end of file