1 #include "../StdAfx.h"
\r
3 #include "frame_processor_device.h"
\r
5 #include "frame_renderer.h"
\r
7 #include "composite_frame.h"
\r
9 #include "../video/video_format.h"
\r
11 #include "../../common/exception/exceptions.h"
\r
12 #include "../../common/concurrency/executor.h"
\r
13 #include "../../common/gl/utility.h"
\r
16 #include <SFML/Window.hpp>
\r
18 #include <tbb/concurrent_queue.h>
\r
19 #include <tbb/concurrent_unordered_map.h>
\r
20 #include <tbb/concurrent_vector.h>
\r
22 #include <boost/range/algorithm.hpp>
\r
23 #include <boost/thread.hpp>
\r
25 #include <functional>
\r
27 namespace caspar { namespace core {
\r
29 struct frame_processor_device::implementation : boost::noncopyable
\r
31 implementation(frame_processor_device* self, const video_format_desc& format_desc)
\r
34 boost::promise<frame_ptr> promise;
\r
35 active_frame_ = promise.get_future();
\r
36 promise.set_value(nullptr);
\r
38 input_.set_capacity(2);
\r
39 output_.set_capacity(2);
\r
41 executor_.invoke([=]
\r
43 ogl_context_.reset(new sf::Context());
\r
44 ogl_context_->SetActive(true);
\r
45 GL(glEnable(GL_POLYGON_STIPPLE));
\r
46 GL(glEnable(GL_TEXTURE_2D));
\r
47 GL(glEnable(GL_BLEND));
\r
48 GL(glDisable(GL_DEPTH_TEST));
\r
49 GL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
\r
50 GL(glClearColor(0.0, 0.0, 0.0, 0.0));
\r
51 GL(glViewport(0, 0, format_desc.width, format_desc.height));
\r
54 renderer_ = std::make_shared<frame_renderer>(*self, format_desc);
\r
63 frame_ptr create_frame(const pixel_format_desc& desc, void* tag)
\r
65 size_t key = reinterpret_cast<size_t>(tag);
\r
66 auto& pool = writing_pools_[key];
\r
69 if(!pool.try_pop(my_frame))
\r
71 my_frame = executor_.invoke([&]
\r
73 return std::shared_ptr<frame>(new frame(desc));
\r
77 auto destructor = [=]
\r
80 writing_pools_[key].push(my_frame);
\r
83 return frame_ptr(my_frame.get(), [=](frame*)
\r
85 executor_.begin_invoke(destructor);
\r
89 void release_tag(void* tag)
\r
91 writing_pools_[reinterpret_cast<size_t>(tag)].clear();
\r
94 void send(const frame_ptr& input_frame)
\r
96 input_.push(input_frame);
\r
97 executor_.begin_invoke([=]
\r
101 frame_ptr output_frame;
\r
102 input_.pop(output_frame);
\r
103 output_.push(renderer_->render(output_frame));
\r
107 CASPAR_LOG_CURRENT_EXCEPTION();
\r
112 void receive(frame_ptr& output_frame)
\r
114 output_.pop(output_frame);
\r
117 bool try_receive(frame_ptr& output_frame)
\r
119 return output_.try_pop(output_frame);
\r
122 video_format_desc fmt_;
\r
124 typedef tbb::concurrent_bounded_queue<frame_ptr> frame_queue;
\r
125 tbb::concurrent_unordered_map<size_t, frame_queue> writing_pools_;
\r
126 frame_queue reading_pool_;
\r
128 std::unique_ptr<sf::Context> ogl_context_;
\r
130 boost::unique_future<frame_ptr> active_frame_;
\r
132 common::executor executor_;
\r
134 frame_queue input_;
\r
135 frame_queue output_;
\r
137 frame_renderer_ptr renderer_;
\r
140 #if defined(_MSC_VER)
\r
141 #pragma warning (disable : 4355) // 'this' : used in base member initializer list
\r
144 frame_processor_device::frame_processor_device(const video_format_desc& format_desc)
\r
145 : impl_(new implementation(this, format_desc)){}
\r
146 frame_ptr frame_processor_device::create_frame(const pixel_format_desc& desc, void* tag){return impl_->create_frame(desc, tag);}
\r
147 void frame_processor_device::release_tag(void* tag){impl_->release_tag(tag);}
\r
148 void frame_processor_device::send(const frame_ptr& frame){impl_->send(frame);}
\r
149 void frame_processor_device::receive(frame_ptr& frame){impl_->receive(frame);}
\r
150 bool frame_processor_device::try_receive(frame_ptr& frame){return impl_->try_receive(frame);}
\r
151 const video_format_desc frame_processor_device::get_video_format_desc() const { return impl_->fmt_;}
\r
152 frame_ptr frame_processor_device::create_frame(size_t width, size_t height, void* tag)
\r
154 pixel_format_desc desc;
\r
155 desc.pix_fmt = pixel_format::bgra;
\r
156 desc.planes[0] = pixel_format_desc::plane(width, height, 4);
\r
157 return create_frame(desc, tag);
\r
160 frame_ptr frame_processor_device::create_frame(void* tag)
\r
162 pixel_format_desc desc;
\r
163 desc.pix_fmt = pixel_format::bgra;
\r
164 desc.planes[0] = pixel_format_desc::plane(get_video_format_desc().width, get_video_format_desc().height, 4);
\r
165 return create_frame(desc, tag);
\r