<ClInclude Include="producer\frame\frame_factory.h">\r
<Filter>producer\frame</Filter>\r
</ClInclude>\r
- <ClInclude Include="mixer\frame_mixer_device.h">\r
- <Filter>mixer</Filter>\r
- </ClInclude>\r
<ClInclude Include="mixer\image\image_kernel.h">\r
<Filter>mixer\image</Filter>\r
</ClInclude>\r
<ClInclude Include="mixer\write_frame.h">\r
<Filter>mixer</Filter>\r
</ClInclude>\r
+ <ClInclude Include="mixer\frame_mixer_device.h">\r
+ <Filter>mixer</Filter>\r
+ </ClInclude>\r
</ItemGroup>\r
<ItemGroup>\r
<ClCompile Include="producer\transition\transition_producer.cpp">\r
{\r
transform_stack_.push(core::audio_transform());\r
\r
- // 2 frames delay\r
- audio_data_.push_back(std::vector<short>());\r
+ // frame delay\r
audio_data_.push_back(std::vector<short>());\r
}\r
\r
diag_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f));\r
diag_->set_color("tick-time", diagnostics::color(0.1f, 0.7f, 0.8f));\r
diag_->set_color("input-buffer", diagnostics::color(1.0f, 1.0f, 0.0f)); \r
- executor_.set_capacity(2); \r
+ executor_.set_capacity(1); \r
executor_.begin_invoke([]\r
{\r
SetThreadPriority(GetCurrentThread(), ABOVE_NORMAL_PRIORITY_CLASS);\r
\r
void send(const std::map<int, safe_ptr<core::basic_frame>>& frames)\r
{ \r
- executor_.begin_invoke([=]\r
+ executor_.invoke([=]\r
{ \r
diag_->set_value("input-buffer", static_cast<float>(executor_.size())/static_cast<float>(executor_.capacity())); \r
frame_timer_.restart();\r
\r
- auto image_future = mix_image(frames);\r
+ auto image = mix_image(frames);\r
auto audio = mix_audio(frames);\r
- auto image = image_future.get();\r
\r
diag_->update_value("frame-time", static_cast<float>(frame_timer_.elapsed()*format_desc_.fps*0.5));\r
\r
std::vector<std::vector<render_item>> render_queue_;\r
\r
image_kernel kernel_;\r
- \r
- safe_ptr<host_buffer> read_buffer_;\r
- \r
+ \r
safe_ptr<device_buffer> draw_buffer_;\r
safe_ptr<device_buffer> write_buffer_;\r
\r
public:\r
implementation(const core::video_format_desc& format_desc) \r
: format_desc_(format_desc)\r
- , read_buffer_(ogl_device::create_host_buffer(format_desc_.size, host_buffer::read_only))\r
, draw_buffer_(ogl_device::create_device_buffer(format_desc.width, format_desc.height, 4))\r
, write_buffer_ (ogl_device::create_device_buffer(format_desc.width, format_desc.height, 4))\r
, local_key_buffer_(ogl_device::create_device_buffer(format_desc.width, format_desc.height, 1))\r
\r
boost::unique_future<safe_ptr<const host_buffer>> render()\r
{\r
- auto result = ogl_device::begin_invoke([=]() -> safe_ptr<const host_buffer>\r
- {\r
- read_buffer_->map(); // Might block.\r
- return read_buffer_;\r
- });\r
- \r
+ auto result = ogl_device::create_host_buffer(format_desc_.size, host_buffer::read_only);\r
+ \r
ogl_device::begin_invoke([=]\r
{\r
local_key_ = false;\r
\r
// Start transfer from device to host.\r
\r
- read_buffer_ = ogl_device::create_host_buffer(format_desc_.size, host_buffer::read_only);\r
- draw_buffer_->write(*read_buffer_);\r
+ draw_buffer_->write(*result);\r
\r
std::swap(draw_buffer_, write_buffer_);\r
});\r
-\r
- return std::move(result);\r
+ \r
+ return ogl_device::begin_invoke([=]() -> safe_ptr<const host_buffer>\r
+ {\r
+ result->map(); // Might block.\r
+ return result;\r
+ });\r
}\r
\r
void draw(const render_item& item)\r
\r
struct read_frame::implementation : boost::noncopyable\r
{\r
- safe_ptr<const host_buffer> image_data_;\r
+ boost::unique_future<safe_ptr<const host_buffer>> image_data_;\r
std::vector<short> audio_data_;\r
\r
public:\r
- implementation(safe_ptr<const host_buffer>&& image_data, std::vector<short>&& audio_data) \r
+ implementation(boost::unique_future<safe_ptr<const host_buffer>>&& image_data, std::vector<short>&& audio_data) \r
: image_data_(std::move(image_data))\r
, audio_data_(std::move(audio_data)){} \r
};\r
\r
-read_frame::read_frame(safe_ptr<const host_buffer>&& image_data, std::vector<short>&& audio_data) : impl_(new implementation(std::move(image_data), std::move(audio_data))){}\r
+read_frame::read_frame(boost::unique_future<safe_ptr<const host_buffer>>&& image_data, std::vector<short>&& audio_data) \r
+ : impl_(new implementation(std::move(image_data), std::move(audio_data))){}\r
+read_frame::read_frame(safe_ptr<const host_buffer>&& image_data, std::vector<short>&& audio_data) \r
+{\r
+ boost::promise<safe_ptr<const host_buffer>> p;\r
+ p.set_value(std::move(image_data));\r
+ impl_.reset(new implementation(std::move(p.get_future()), std::move(audio_data)));\r
+}\r
\r
const boost::iterator_range<const unsigned char*> read_frame::image_data() const\r
{\r
- if(!impl_->image_data_->data())\r
+ if(!impl_->image_data_.get()->data())\r
return boost::iterator_range<const unsigned char*>();\r
- auto ptr = static_cast<const unsigned char*>(impl_->image_data_->data());\r
- return boost::iterator_range<const unsigned char*>(ptr, ptr + impl_->image_data_->size());\r
+ auto ptr = static_cast<const unsigned char*>(impl_->image_data_.get()->data());\r
+ return boost::iterator_range<const unsigned char*>(ptr, ptr + impl_->image_data_.get()->size());\r
}\r
const boost::iterator_range<const short*> read_frame::audio_data() const\r
{\r
\r
#include <boost/noncopyable.hpp>\r
#include <boost/range/iterator_range.hpp>\r
+#include <boost/thread.hpp>\r
\r
#include <memory>\r
#include <vector>\r
{\r
read_frame(){}\r
public:\r
+ read_frame(boost::unique_future<safe_ptr<const host_buffer>>&& image_data, std::vector<short>&& audio_data);\r
read_frame(safe_ptr<const host_buffer>&& image_data, std::vector<short>&& audio_data);\r
\r
virtual const boost::iterator_range<const unsigned char*> image_data() const;\r
void read_file()\r
{ \r
if(audio_stream_.size() > 4 && video_stream_.size() > 4)\r
- boost::this_thread::yield(); // There are enough packets, no hurry.\r
+ Sleep(5); // There are enough packets, no hurry.\r
\r
try\r
{\r
\r
void thread_free(AVCodecContext* s)\r
{\r
+ if(!s->thread_opaque)\r
+ return;\r
+\r
s->thread_opaque = nullptr;\r
\r
CASPAR_LOG(info) << "Released ffmpeg tbb context.";\r