const int index_;\r
video_format_desc format_desc_;\r
\r
- safe_ptr<mixer::frame_mixer_device> mixer_;\r
+ safe_ptr<mixer::frame_mixer_device> mixer_; // Mixer must be destroyed last in order to make sure that all frames have been returned to the pool.\r
safe_ptr<frame_consumer_device> consumer_;\r
safe_ptr<frame_producer_device> producer_;\r
\r
\r
#include <common/concurrency/executor.h>\r
#include <common/diagnostics/graph.h>\r
+#include <common/memory/memcpy.h>\r
#include <common/utility/timer.h>\r
\r
#include <tbb/concurrent_queue.h>\r
{\r
try\r
{\r
- std::copy_n(frame->image_data().begin(), frame->image_data().size(), reserved_frames_.front()->image_data());\r
+ fast_memcpy(reserved_frames_.front()->image_data(), frame->image_data().begin(), frame->image_data().size());\r
\r
if(embed_audio_)\r
{ \r
graph_ = diagnostics::create_graph(boost::bind(&ffmpeg_producer::print, this)); \r
graph_->add_guide("frame-time", 0.5);\r
graph_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f));\r
+ graph_->set_color("underflow", diagnostics::color(0.6f, 0.3f, 0.9f)); \r
\r
input_.reset(new input(safe_ptr<diagnostics::graph>(graph_), filename_, loop_));\r
video_decoder_.reset(input_->get_video_codec_context().get() ? new video_decoder(input_->get_video_codec_context().get(), frame_factory) : nullptr);\r
else if(!input_->is_running())\r
result = core::basic_frame::eof();\r
else\r
- graph_->add_tag("lag");\r
+ graph_->add_tag("underflow");\r
\r
return result;\r
}\r
auto decoded = decoded_frame->data[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
{\r
fast_memcpy(result + y*plane.linesize, decoded + y*decoded_linesize, plane.linesize);\r
}\r
else\r
{\r
+ // Uses sws_scale when we don't support the provided color-space.\r
safe_ptr<AVFrame> av_frame(avcodec_alloc_frame(), av_free); \r
avcodec_get_frame_defaults(av_frame.get()); \r
avpicture_fill(reinterpret_cast<AVPicture*>(av_frame.get()), write->image_data().begin(), PIX_FMT_BGRA, width_, height_);\r
sws_scale(sws_context_.get(), decoded_frame->data, decoded_frame->linesize, 0, height_, av_frame->data, av_frame->linesize); \r
} \r
\r
+ // DVVIDEO is in lower field. Make it upper field if needed.\r
if(codec_context_->codec_id == CODEC_ID_DVVIDEO && frame_factory_->get_video_format_desc().mode == core::video_mode::upper)\r
write->get_image_transform().set_fill_translation(0.0f, 1.0/static_cast<double>(height_));\r
\r
#include <common/gl/gl_check.h>\r
#include <common/concurrency/executor.h>\r
#include <common/memory/safe_ptr.h>\r
+#include <common/memory/memcpy.h>\r
#include <common/diagnostics/graph.h>\r
#include <common/utility/timer.h>\r
\r
auto ptr = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);\r
if(ptr)\r
{\r
- std::copy(frame->image_data().begin(), frame->image_data().end(), reinterpret_cast<char*>(ptr));\r
+ fast_memcpy(reinterpret_cast<char*>(ptr), frame->image_data().begin(), frame->image_data().size());\r
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); // release the mapped buffer\r
}\r
\r