\r
#include "color_producer.h"\r
\r
-#include <mixer/frame/draw_frame.h>\r
+#include <mixer/frame/write_frame.h>\r
\r
#include <sstream>\r
\r
#include <common/utility/printer.h>\r
\r
#include <mixer/frame/draw_frame.h>\r
-#include <mixer/frame_factory.h>\r
+#include <mixer/frame/frame_factory.h>\r
\r
#include <boost/noncopyable.hpp>\r
\r
#include "frame_producer_device.h"\r
\r
#include <mixer/frame/draw_frame.h>\r
-#include <mixer/frame_factory.h>\r
+#include <mixer/frame/frame_factory.h>\r
\r
#include "layer.h"\r
\r
#include "audio_mixer.h"\r
#include "audio_transform.h"\r
\r
+#include "../frame/draw_frame.h"\r
+#include "../frame/write_frame.h"\r
+\r
namespace caspar { namespace core {\r
\r
struct audio_mixer::implementation\r
{\r
transform_stack_.push(audio_transform());\r
}\r
-\r
- void begin(const audio_transform& transform)\r
+ \r
+ void begin(const draw_frame& frame)\r
{\r
- transform_stack_.push(transform_stack_.top()*transform);\r
+ transform_stack_.push(transform_stack_.top()*frame.get_audio_transform());\r
}\r
\r
- void process(const std::vector<short>& audio_data, int tag)\r
- { \r
+ void visit(const write_frame& frame)\r
+ {\r
if(!transform_stack_.top().get_has_audio())\r
return;\r
\r
+ auto& audio_data = frame.audio_data();\r
+ auto tag = frame.tag();\r
+\r
if(audio_data_.empty())\r
audio_data_.resize(audio_data.size(), 0);\r
\r
}\r
}\r
);\r
+ }\r
+\r
\r
+ void begin(const audio_transform& transform)\r
+ {\r
+ transform_stack_.push(transform_stack_.top()*transform);\r
}\r
- \r
+ \r
void end()\r
{\r
transform_stack_.pop();\r
};\r
\r
audio_mixer::audio_mixer() : impl_(new implementation()){}\r
-void audio_mixer::begin(const audio_transform& transform){impl_->begin(transform);}\r
-void audio_mixer::process(const std::vector<short>& audio_data, int tag){impl_->process(audio_data, tag);}\r
+void audio_mixer::begin(const draw_frame& frame){impl_->begin(frame);}\r
+void audio_mixer::visit(write_frame& frame){impl_->visit(frame);}\r
void audio_mixer::end(){impl_->end();}\r
std::vector<short> audio_mixer::begin_pass(){return impl_->begin_pass();} \r
void audio_mixer::end_pass(){impl_->end_pass();}\r
#pragma once\r
\r
-#include <tbb/spin_mutex.h>\r
+#include "../frame/frame_visitor.h"\r
\r
namespace caspar { namespace core {\r
\r
class audio_transform;\r
\r
-class audio_mixer\r
+class audio_mixer : public frame_visitor\r
{\r
public:\r
audio_mixer();\r
\r
- void begin(const audio_transform& transform);\r
- void process(const std::vector<short>& audio_data, int tag);\r
- void end();\r
+ virtual void begin(const draw_frame& frame);\r
+ virtual void visit(write_frame& frame);\r
+ virtual void end();\r
\r
std::vector<short> begin_pass();\r
void end_pass();\r
audio_transform audio_transform_;\r
\r
int index_;\r
+\r
public:\r
implementation(const std::vector<safe_ptr<draw_frame>>& frames) \r
: frames_(frames)\r
: frames_(std::move(frames))\r
, index_(std::numeric_limits<int>::min()) {}\r
\r
- void process_image(image_mixer& mixer)\r
- {\r
- mixer.begin(image_transform_);\r
- BOOST_FOREACH(auto frame, frames_)\r
- frame->process_image(mixer);\r
- mixer.end();\r
- }\r
-\r
- void process_audio(audio_mixer& mixer)\r
+ void accept(draw_frame& self, frame_visitor& visitor)\r
{\r
- mixer.begin(audio_transform_);\r
+ visitor.begin(self);\r
BOOST_FOREACH(auto frame, frames_)\r
- frame->process_audio(mixer);\r
- mixer.end();\r
+ frame->accept(visitor);\r
+ visitor.end();\r
} \r
};\r
\r
temp.swap(*this);\r
return *this;\r
}\r
-void draw_frame::process_image(image_mixer& mixer){impl_->process_image(mixer);}\r
-void draw_frame::process_audio(audio_mixer& mixer){impl_->process_audio(mixer);}\r
+void draw_frame::accept(frame_visitor& visitor){impl_->accept(*this, visitor);}\r
\r
const image_transform& draw_frame::get_image_transform() const { return impl_->image_transform_;}\r
image_transform& draw_frame::get_image_transform() { return impl_->image_transform_;}\r
\r
#include "../fwd.h"\r
\r
-#include "draw_frame.h"\r
+#include "frame_visitor.h"\r
\r
#include <common/memory/safe_ptr.h>\r
#include <core/video_format.h>\r
void remove_audio();\r
void remove_image();\r
\r
- virtual void process_image(image_mixer& mixer);\r
- virtual void process_audio(audio_mixer& mixer);\r
+ virtual void accept(frame_visitor& visitor);\r
\r
void set_layer_index(int index);\r
int get_layer_index() const;\r
*/\r
#pragma once\r
\r
-#include "fwd.h"\r
+#include "../fwd.h"\r
\r
-#include "frame/write_frame.h"\r
-#include "frame/pixel_format.h"\r
+#include "pixel_format.h"\r
\r
#include <common/memory/safe_ptr.h>\r
\r
+#include <core/video_format.h>\r
+\r
namespace caspar { namespace core {\r
- \r
+ \r
struct frame_factory : boost::noncopyable\r
{\r
virtual safe_ptr<write_frame> create_frame(const pixel_format_desc& desc) = 0;\r
--- /dev/null
+#pragma once\r
+\r
+namespace caspar{ namespace core{\r
+\r
+class draw_frame;\r
+class write_frame;\r
+\r
+struct frame_visitor\r
+{\r
+ virtual void begin(const draw_frame& frame) = 0;\r
+ virtual void visit(write_frame& frame) = 0;\r
+ virtual void end() = 0;\r
+};\r
+\r
+}}
\ No newline at end of file
\r
struct write_frame::implementation : boost::noncopyable\r
{ \r
- write_frame& self_;\r
std::vector<safe_ptr<host_buffer>> buffers_;\r
std::vector<short> audio_data_;\r
const pixel_format_desc desc_;\r
int tag_;\r
\r
public:\r
- implementation(write_frame& self, const pixel_format_desc& desc, std::vector<safe_ptr<host_buffer>> buffers) \r
- : self_(self)\r
- , desc_(desc)\r
+ implementation(const pixel_format_desc& desc, std::vector<safe_ptr<host_buffer>> buffers) \r
+ : desc_(desc)\r
, buffers_(buffers)\r
, tag_(std::numeric_limits<int>::min()){}\r
\r
- void process_image(image_mixer& mixer)\r
+ void accept(write_frame& self, frame_visitor& visitor)\r
{\r
- mixer.begin(self_.get_image_transform());\r
- mixer.process(desc_, buffers_);\r
- mixer.end();\r
- }\r
-\r
- void process_audio(audio_mixer& mixer)\r
- {\r
- mixer.begin(self_.get_audio_transform());\r
- mixer.process(audio_data_, tag_);\r
- mixer.end();\r
+ visitor.begin(self);\r
+ visitor.visit(self);\r
+ visitor.end();\r
}\r
\r
boost::iterator_range<unsigned char*> image_data(size_t index)\r
return boost::iterator_range<const unsigned char*>(ptr, ptr+buffers_[index]->size());\r
}\r
};\r
-\r
-#ifdef _MSC_VER\r
-#pragma warning(disable : 4355) // 'this' : used in base member initializer list\r
-#endif\r
\r
-write_frame::write_frame(const pixel_format_desc& desc, std::vector<safe_ptr<host_buffer>> buffers) : impl_(new implementation(*this, desc, buffers)){}\r
+write_frame::write_frame(const pixel_format_desc& desc, std::vector<safe_ptr<host_buffer>> buffers) : impl_(new implementation(desc, buffers)){}\r
write_frame::write_frame(write_frame&& other) : impl_(std::move(other.impl_)){}\r
void write_frame::swap(write_frame& other){impl_.swap(other.impl_);}\r
write_frame& write_frame::operator=(write_frame&& other)\r
temp.swap(*this);\r
return *this;\r
}\r
-void write_frame::process_image(image_mixer& mixer){impl_->process_image(mixer);}\r
-void write_frame::process_audio(audio_mixer& mixer){impl_->process_audio(mixer);}\r
+void write_frame::accept(frame_visitor& visitor){impl_->accept(*this, visitor);}\r
boost::iterator_range<unsigned char*> write_frame::image_data(size_t index){return impl_->image_data(index);}\r
std::vector<short>& write_frame::audio_data() { return impl_->audio_data_; }\r
+boost::iterator_range<const unsigned char*> write_frame::image_data(size_t index) const{return impl_->image_data(index);}\r
+const std::vector<short>& write_frame::audio_data() const { return impl_->audio_data_; }\r
void write_frame::tag(int tag) { impl_->tag_ = tag;}\r
int write_frame::tag() const {return impl_->tag_;}\r
+const pixel_format_desc& write_frame::get_pixel_format_desc() const{return impl_->desc_;}\r
+std::vector<safe_ptr<host_buffer>>& write_frame::buffers(){return impl_->buffers_;}\r
}}
\ No newline at end of file
\r
boost::iterator_range<unsigned char*> image_data(size_t index = 0); \r
std::vector<short>& audio_data();\r
+ \r
+ boost::iterator_range<const unsigned char*> image_data(size_t index = 0) const;\r
+ const std::vector<short>& audio_data() const;\r
\r
- virtual void process_image(image_mixer& mixer);\r
- virtual void process_audio(audio_mixer& mixer);\r
+ virtual void accept(frame_visitor& visitor);\r
\r
void tag(int tag);\r
int tag() const;\r
+\r
+ const pixel_format_desc& get_pixel_format_desc() const;\r
+ std::vector<safe_ptr<host_buffer>>& buffers();\r
\r
private:\r
struct implementation;\r
frame2->get_image_transform() = root_image_transform_.fetch_and_tick(1)*image_transforms_[frame->get_layer_index()].fetch_and_tick(1);\r
\r
if(frame1->get_image_transform() != frame2->get_image_transform())\r
- draw_frame::interlace(frame1, frame2, format_desc_.mode)->process_image(image_mixer_);\r
+ draw_frame::interlace(frame1, frame2, format_desc_.mode)->accept(image_mixer_);\r
else\r
- frame2->process_image(image_mixer_);\r
+ frame2->accept(image_mixer_);\r
}\r
else\r
{\r
auto frame1 = make_safe<draw_frame>(frame);\r
frame1->get_image_transform() = root_image_transform_.fetch_and_tick(1)*image_transforms_[frame->get_layer_index()].fetch_and_tick(1);\r
- frame1->process_image(image_mixer_);\r
+ frame1->accept(image_mixer_);\r
}\r
}\r
image_mixer_.end_pass();\r
\r
auto frame1 = make_safe<draw_frame>(frame);\r
frame1->get_audio_transform() = root_audio_transform_.fetch_and_tick(num)*audio_transforms_[frame->get_layer_index()].fetch_and_tick(num);\r
- frame1->process_audio(audio_mixer_);\r
+ frame1->accept(audio_mixer_);\r
}\r
audio_mixer_.end_pass();\r
return audio;\r
\r
#include "fwd.h"\r
\r
-#include "frame_factory.h"\r
+#include "frame/frame_factory.h"\r
\r
#include "image/image_mixer.h"\r
#include "audio/audio_mixer.h"\r
#include <common/memory/safe_ptr.h>\r
#include <common/utility/printer.h>\r
\r
+#include <core/video_format.h>\r
+\r
#include <boost/signals2.hpp>\r
\r
#include <functional>\r
#include "image_kernel.h"\r
#include "image_transform.h"\r
\r
+#include "../frame/draw_frame.h"\r
+#include "../frame/write_frame.h"\r
+\r
#include "../gpu/ogl_device.h"\r
#include "../gpu/host_buffer.h"\r
#include "../gpu/device_buffer.h"\r
glDeleteFramebuffersEXT(1, &fbo_);\r
}\r
\r
- void begin(const image_transform& transform)\r
+ void begin(const draw_frame& frame)\r
{\r
- transform_stack_.push(transform_stack_.top()*transform);\r
+ transform_stack_.push(transform_stack_.top()*frame.get_image_transform());\r
}\r
\r
- void render(const pixel_format_desc& desc, std::vector<safe_ptr<host_buffer>>& buffers)\r
+ void visit(write_frame& frame)\r
{\r
+ auto& desc = frame.get_pixel_format_desc();\r
+ auto& buffers = frame.buffers();\r
+\r
auto transform = transform_stack_.top();\r
context_->begin_invoke([=]\r
{\r
};\r
\r
image_mixer::image_mixer(const video_format_desc& format_desc) : impl_(new implementation(format_desc)){}\r
-void image_mixer::begin(const image_transform& transform) { impl_->begin(transform);}\r
-void image_mixer::process(const pixel_format_desc& desc, std::vector<safe_ptr<host_buffer>>& buffers){ impl_->render(desc, buffers);}\r
+void image_mixer::begin(const draw_frame& frame){impl_->begin(frame);}\r
+void image_mixer::visit(write_frame& frame){impl_->visit(frame);}\r
void image_mixer::end(){impl_->end();}\r
boost::unique_future<safe_ptr<const host_buffer>> image_mixer::begin_pass(){ return impl_->begin_pass();}\r
void image_mixer::end_pass(){impl_->end_pass();}\r
#pragma once\r
\r
+#include "../frame/frame_visitor.h"\r
+\r
#include "../gpu/host_buffer.h"\r
\r
#include <core/video_format.h>\r
struct pixel_format_desc; \r
class image_transform;\r
\r
-class image_mixer : boost::noncopyable\r
+class image_mixer : public frame_visitor, boost::noncopyable\r
{\r
public:\r
image_mixer(const video_format_desc& format_desc);\r
-\r
- void begin(const image_transform& transform);\r
- void process(const pixel_format_desc& desc, std::vector<safe_ptr<host_buffer>>& buffers);\r
- void end();\r
+ \r
+ virtual void begin(const draw_frame& frame);\r
+ virtual void visit(write_frame& frame);\r
+ virtual void end();\r
\r
boost::unique_future<safe_ptr<const host_buffer>> begin_pass();\r
void end_pass();\r
<ClInclude Include="audio\audio_mixer.h" />\r
<ClInclude Include="audio\audio_transform.h" />\r
<ClInclude Include="frame\draw_frame.h" />\r
+ <ClInclude Include="frame\frame_factory.h" />\r
+ <ClInclude Include="frame\frame_visitor.h" />\r
<ClInclude Include="frame\pixel_format.h" />\r
<ClInclude Include="frame\read_frame.h" />\r
<ClInclude Include="frame\write_frame.h" />\r
- <ClInclude Include="frame_factory.h" />\r
<ClInclude Include="frame_mixer_device.h" />\r
<ClInclude Include="fwd.h" />\r
<ClInclude Include="gpu\device_buffer.h" />\r
<ClCompile Include="frame\write_frame.cpp">\r
<Filter>frame</Filter>\r
</ClCompile>\r
- <ClCompile Include="frame\draw_frame.cpp">\r
- <Filter>frame</Filter>\r
- </ClCompile>\r
<ClCompile Include="frame_mixer_device.cpp" />\r
<ClCompile Include="StdAfx.cpp" />\r
<ClCompile Include="image\image_kernel.cpp">\r
<ClCompile Include="image\image_transform.cpp">\r
<Filter>image</Filter>\r
</ClCompile>\r
+ <ClCompile Include="frame\draw_frame.cpp">\r
+ <Filter>frame</Filter>\r
+ </ClCompile>\r
</ItemGroup>\r
<ItemGroup>\r
<ClInclude Include="audio\audio_mixer.h">\r
<ClInclude Include="gpu\ogl_device.h">\r
<Filter>gpu</Filter>\r
</ClInclude>\r
- <ClInclude Include="frame\draw_frame.h">\r
- <Filter>frame</Filter>\r
- </ClInclude>\r
<ClInclude Include="frame\pixel_format.h">\r
<Filter>frame</Filter>\r
</ClInclude>\r
<Filter>frame</Filter>\r
</ClInclude>\r
<ClInclude Include="StdAfx.h" />\r
- <ClInclude Include="frame_factory.h" />\r
<ClInclude Include="frame_mixer_device.h" />\r
<ClInclude Include="fwd.h" />\r
<ClInclude Include="image\image_transform.h">\r
<ClInclude Include="image\image_mixer.h">\r
<Filter>image</Filter>\r
</ClInclude>\r
+ <ClInclude Include="frame\frame_visitor.h">\r
+ <Filter>frame</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="frame\draw_frame.h">\r
+ <Filter>frame</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="frame\frame_factory.h">\r
+ <Filter>frame</Filter>\r
+ </ClInclude>\r
</ItemGroup>\r
</Project>
\ No newline at end of file
\r
#include "decklink_producer.h"\r
\r
-#include <mixer/frame/draw_frame.h>\r
#include "../interop/DeckLinkAPI_h.h" // TODO: Change this\r
#include "../util/util.h" // TODO: Change this\r
\r
#include <common/exception/exceptions.h>\r
#include <common/utility/timer.h>\r
\r
+#include <mixer/frame/write_frame.h>\r
+\r
#include <tbb/concurrent_queue.h>\r
#include <tbb/atomic.h>\r
\r
\r
#include <core/video_format.h>\r
\r
-#include <mixer/frame/draw_frame.h>\r
-#include <mixer/frame_factory.h>\r
+#include <mixer/frame/write_frame.h>\r
+#include <mixer/frame/frame_factory.h>\r
\r
#include <common/concurrency/executor.h>\r
#include <common/env.h>\r