\r
struct image_mixer::implementation : boost::noncopyable\r
{ \r
+ typedef std::deque<render_item> stream;\r
+ typedef std::deque<stream> layer;\r
+\r
video_channel_context& channel_;\r
\r
std::stack<core::image_transform> transform_stack_;\r
\r
- std::queue<std::queue<std::deque<render_item>>> render_queue_; // layer/stream/items\r
+ std::queue<layer> layers_; // layer/stream/items\r
\r
std::unique_ptr<image_kernel> kernel_;\r
\r
\r
render_item item = {frame.get_pixel_format_desc(), frame.get_textures(), transform_stack_.top()*frame.get_image_transform(), frame.tag()}; \r
\r
- auto& layer = render_queue_.back();\r
+ auto& layer = layers_.back();\r
\r
- if(layer.empty() || (!layer.back().empty() && layer.back().back().tag != frame.tag()))\r
- layer.push(std::deque<render_item>());\r
- \r
- auto& stream = layer.back();\r
- \r
- if(std::find(stream.begin(), stream.end(), item) == stream.end())\r
- stream.push_back(item);\r
+ auto stream_it = std::find_if(layer.begin(), layer.end(), [&](stream& stream)\r
+ {\r
+ return stream.front().tag == item.tag;\r
+ });\r
+\r
+ if(stream_it == layer.end())\r
+ layer.push_back(stream(1, item));\r
+ else \r
+ {\r
+ if(std::find(stream_it->begin(), stream_it->end(), item) == stream_it->end())\r
+ stream_it->push_back(item); \r
+ }\r
}\r
\r
void end()\r
\r
void begin_layer()\r
{\r
- render_queue_.push(std::queue<std::deque<render_item>>());\r
+ layers_.push(layer());\r
}\r
\r
void end_layer()\r
\r
boost::unique_future<safe_ptr<host_buffer>> render()\r
{ \r
- auto render_queue = std::move(render_queue_);\r
+ auto layers = std::move(layers_);\r
\r
return channel_.ogl().begin_invoke([=]() mutable -> safe_ptr<host_buffer>\r
{ \r
if(channel_.get_format_desc().width != write_buffer_->width() || channel_.get_format_desc().height != write_buffer_->height())\r
initialize_buffers();\r
\r
- return do_render(std::move(render_queue));\r
+ return do_render(std::move(layers));\r
});\r
}\r
\r
- safe_ptr<host_buffer> do_render(std::queue<std::queue<std::deque<render_item>>>&& render_queue)\r
+ safe_ptr<host_buffer> do_render(std::queue<layer>&& layers)\r
{\r
auto read_buffer = channel_.ogl().create_host_buffer(channel_.get_format_desc().size, host_buffer::read_only);\r
\r
bool local_key = false;\r
bool layer_key = false;\r
\r
- while(!render_queue.empty())\r
+ while(!layers.empty())\r
{ \r
stream_key_buffer_[0]->clear();\r
\r
- auto layer = std::move(render_queue.front());\r
- render_queue.pop();\r
+ auto layer = std::move(layers.front());\r
+ layers.pop();\r
\r
while(!layer.empty())\r
{\r
auto stream = std::move(layer.front());\r
- layer.pop();\r
+ layer.pop_front();\r
\r
render(stream, local_key, layer_key);\r
\r
return read_buffer;\r
}\r
\r
- void render(std::deque<render_item>& stream, bool local_key, bool layer_key)\r
+ void render(stream& stream, bool local_key, bool layer_key)\r
{\r
CASPAR_ASSERT(!stream.empty());\r
\r
- if(stream.front().transform.get_is_key())\r
+ if(stream.front().transform.get_is_key())\r
{\r
stream_key_buffer_[1]->attach();\r
\r
#include <core/producer/frame/frame_visitor.h>\r
#include <core/producer/frame/pixel_format.h>\r
\r
+#include <boost/lexical_cast.hpp>\r
+\r
namespace caspar { namespace core {\r
\r
struct write_frame::implementation\r
texture->read(*buffer);\r
}, high_priority);\r
}\r
+\r
+ std::wstring print() const\r
+ {\r
+ return L"write_frame[" + boost::lexical_cast<std::wstring>(tag_) + L"]";\r
+ }\r
};\r
\r
write_frame::write_frame(const void* tag) : impl_(new implementation(tag)){}\r
void write_frame::commit(){impl_->commit();}\r
void write_frame::set_type(const video_mode::type& mode){impl_->mode_ = mode;}\r
core::video_mode::type write_frame::get_type() const{return impl_->mode_;}\r
+std::wstring write_frame::print() const{return impl_->print();}\r
\r
}}
\ No newline at end of file
frame->accept(visitor);\r
visitor.end();\r
} \r
+\r
+ std::wstring print() const\r
+ {\r
+ std::wstring str = L"\tbasic_frame[\n";\r
+ BOOST_FOREACH(auto& frame, frames_)\r
+ str += frame->print() + L"\n";\r
+ str += L"\n]";\r
+ return str;\r
+ }\r
};\r
\r
basic_frame::basic_frame() : impl_(new implementation(std::vector<safe_ptr<basic_frame>>())){}\r
const audio_transform& basic_frame::get_audio_transform() const { return impl_->audio_transform_;}\r
audio_transform& basic_frame::get_audio_transform() { return impl_->audio_transform_;}\r
\r
+std::wstring basic_frame::print() const{return impl_->print();}\r
+\r
safe_ptr<basic_frame> basic_frame::interlace(const safe_ptr<basic_frame>& frame1, const safe_ptr<basic_frame>& frame2, video_mode::type mode)\r
{ \r
if(frame1 == basic_frame::empty() && frame2 == basic_frame::empty())\r