const int index_;\r
video_format_desc format_desc_;\r
\r
+ safe_ptr<ogl_device> ogl_;\r
+\r
std::shared_ptr<frame_consumer_device> consumer_;\r
std::shared_ptr<frame_mixer_device> mixer_;\r
std::shared_ptr<frame_producer_device> producer_;\r
\r
public:\r
- implementation(int index, const video_format_desc& format_desc) \r
+ implementation(int index, const video_format_desc& format_desc, const safe_ptr<ogl_device>& ogl) \r
: index_(index)\r
, format_desc_(format_desc)\r
- , consumer_(new frame_consumer_device(format_desc))\r
- , mixer_(new frame_mixer_device(format_desc, [=](const safe_ptr<const read_frame>& frame){consumer_->send(frame);}))\r
+ , ogl_(ogl)\r
+ , consumer_(new frame_consumer_device(format_desc, ogl))\r
+ , mixer_(new frame_mixer_device(format_desc, [=](const safe_ptr<read_frame>& frame){consumer_->send(frame);}, ogl))\r
, producer_(new frame_producer_device(format_desc_, [=](const std::map<int, safe_ptr<basic_frame>>& frames){mixer_->send(frames);})) \r
+\r
{\r
CASPAR_LOG(info) << print() << " Successfully Initialized.";\r
}\r
mixer_.reset();\r
\r
consumer_->set_video_format_desc(format_desc_);\r
- mixer_ = make_safe<frame_mixer_device>(format_desc_, [=](const safe_ptr<const read_frame>& frame){consumer_->send(frame);});\r
- producer_ = make_safe<frame_producer_device>(format_desc_, [=](const std::map<int, safe_ptr<basic_frame>>& frames){mixer_->send(frames);});\r
+ mixer_ = std::make_shared<frame_mixer_device>(format_desc_, [=](const safe_ptr<read_frame>& frame){consumer_->send(frame);}, ogl_);\r
+ producer_ = std::make_shared<frame_producer_device>(format_desc_, [=](const std::map<int, safe_ptr<basic_frame>>& frames){mixer_->send(frames);});\r
}\r
};\r
\r
-channel::channel(int index, const video_format_desc& format_desc) : impl_(new implementation(index, format_desc)){}\r
+channel::channel(int index, const video_format_desc& format_desc, const safe_ptr<ogl_device>& ogl) : impl_(new implementation(index, format_desc, ogl)){}\r
channel::channel(channel&& other) : impl_(std::move(other.impl_)){}\r
safe_ptr<frame_producer_device> channel::producer() { return make_safe(impl_->producer_);} \r
safe_ptr<frame_mixer_device> channel::mixer() { return make_safe(impl_->mixer_);} \r
\r
namespace caspar { namespace core {\r
\r
+class ogl_device;\r
+\r
class channel : boost::noncopyable\r
{\r
public:\r
- explicit channel(int index, const video_format_desc& format_desc);\r
+ explicit channel(int index, const video_format_desc& format_desc, const safe_ptr<ogl_device>& ogl);\r
channel(channel&& other);\r
\r
safe_ptr<frame_producer_device> producer();\r
\r
boost::timer frame_timer_;\r
boost::timer tick_timer_;\r
+\r
+ safe_ptr<ogl_device> ogl_;\r
\r
executor executor_; \r
public:\r
- implementation( const video_format_desc& format_desc) \r
+ implementation( const video_format_desc& format_desc, const safe_ptr<ogl_device>& ogl) \r
: format_desc_(format_desc)\r
, diag_(diagnostics::create_graph(std::string("frame_consumer_device")))\r
+ , ogl_(ogl)\r
, executor_(L"frame_consumer_device")\r
{ \r
diag_->set_color("input-buffer", diagnostics::color(1.0f, 1.0f, 0.0f)); \r
if(has_key_only)\r
{\r
// Currently do key_only transform on cpu. Unsure if the extra 400MB/s (1080p50) overhead is worth it to do it on gpu.\r
- auto key_data = ogl_device::create_host_buffer(frame->image_data().size(), host_buffer::write_only); \r
+ auto key_data = ogl_->create_host_buffer(frame->image_data().size(), host_buffer::write_only); \r
fast_memsfhl(key_data->data(), frame->image_data().begin(), frame->image_data().size(), 0x0F0F0F0F, 0x0B0B0B0B, 0x07070707, 0x03030303);\r
std::vector<int16_t> audio_data(frame->audio_data().begin(), frame->audio_data().end());\r
- return make_safe<const read_frame>(std::move(key_data), std::move(audio_data));\r
+ return make_safe<read_frame>(std::move(key_data), std::move(audio_data));\r
}\r
\r
return read_frame::empty();\r
}\r
\r
- void send(const safe_ptr<const read_frame>& frame)\r
+ void send(const safe_ptr<read_frame>& frame)\r
{ \r
executor_.begin_invoke([=]\r
{\r
\r
diag_->set_value("input-buffer", static_cast<float>(executor_.size())/static_cast<float>(executor_.capacity()));\r
frame_timer_.restart();\r
- \r
+ \r
buffer_.push_back(std::make_pair(frame, get_key_frame(frame)));\r
\r
if(!buffer_.full())\r
}\r
};\r
\r
-frame_consumer_device::frame_consumer_device(const video_format_desc& format_desc) : impl_(new implementation(format_desc)){}\r
+frame_consumer_device::frame_consumer_device(const video_format_desc& format_desc, const safe_ptr<ogl_device>& ogl) \r
+ : impl_(new implementation(format_desc, ogl)){}\r
void frame_consumer_device::add(int index, safe_ptr<frame_consumer>&& consumer){impl_->add(index, std::move(consumer));}\r
void frame_consumer_device::remove(int index){impl_->remove(index);}\r
-void frame_consumer_device::send(const safe_ptr<const read_frame>& future_frame) { impl_->send(future_frame); }\r
+void frame_consumer_device::send(const safe_ptr<read_frame>& future_frame) { impl_->send(future_frame); }\r
void frame_consumer_device::set_video_format_desc(const video_format_desc& format_desc){impl_->set_video_format_desc(format_desc);}\r
}}
\ No newline at end of file
\r
class basic_frame;\r
struct video_format_desc;\r
+class ogl_device;\r
\r
class frame_consumer_device : boost::noncopyable\r
{\r
public:\r
- explicit frame_consumer_device(const video_format_desc& format_desc);\r
+ explicit frame_consumer_device(const video_format_desc& format_desc, const safe_ptr<ogl_device>& ogl);\r
\r
void add(int index, safe_ptr<frame_consumer>&& consumer);\r
void remove(int index);\r
\r
- void send(const safe_ptr<const read_frame>& future_frame); // nothrow\r
+ void send(const safe_ptr<read_frame>& future_frame); // nothrow\r
\r
void set_video_format_desc(const video_format_desc& format_desc);\r
private:\r
audio_mixer audio_mixer_;\r
image_mixer image_mixer_;\r
\r
- std::function<void(const safe_ptr<const core::read_frame>&)> output_;\r
+ output_t output_;\r
\r
typedef std::unordered_map<int, tweened_transform<core::image_transform>> image_transforms;\r
typedef std::unordered_map<int, tweened_transform<core::audio_transform>> audio_transforms;\r
boost::fusion::map<boost::fusion::pair<core::image_transform, tweened_transform<core::image_transform>>,\r
boost::fusion::pair<core::audio_transform, tweened_transform<core::audio_transform>>> root_transforms_;\r
\r
+ safe_ptr<ogl_device> ogl_;\r
+\r
executor executor_;\r
public:\r
- implementation(const core::video_format_desc& format_desc, const std::function<void(const safe_ptr<const core::read_frame>&)>& output) \r
+ implementation(const core::video_format_desc& format_desc, const output_t& output, const safe_ptr<ogl_device>& ogl) \r
: format_desc_(format_desc)\r
, diag_(diagnostics::create_graph(narrow(print())))\r
- , image_mixer_(format_desc)\r
+ , image_mixer_(format_desc, ogl)\r
, output_(output)\r
+ , ogl_(ogl)\r
, executor_(L"frame_mixer_device")\r
{\r
diag_->add_guide("frame-time", 0.5f); \r
\r
auto image = mix_image(frames);\r
auto audio = mix_audio(frames);\r
-\r
+ \r
diag_->update_value("frame-time", static_cast<float>(frame_timer_.elapsed()*format_desc_.fps*0.5));\r
\r
- output_(make_safe<const read_frame>(std::move(image), std::move(audio)));\r
+ output_(make_safe<read_frame>(std::move(image), std::move(audio)));\r
\r
diag_->update_value("tick-time", static_cast<float>(tick_timer_.elapsed()*format_desc_.fps*0.5));\r
tick_timer_.restart();\r
}\r
};\r
\r
-frame_mixer_device::frame_mixer_device(const core::video_format_desc& format_desc, const std::function<void(const safe_ptr<const core::read_frame>&)>& output) : impl_(new implementation(format_desc, output)){}\r
+frame_mixer_device::frame_mixer_device(const core::video_format_desc& format_desc, const output_t& output, const safe_ptr<ogl_device>& ogl)\r
+ : impl_(new implementation(format_desc, output, ogl)){}\r
frame_mixer_device::frame_mixer_device(frame_mixer_device&& other) : impl_(std::move(other.impl_)){}\r
void frame_mixer_device::send(const std::map<int, safe_ptr<core::basic_frame>>& frames){impl_->send(frames);}\r
const core::video_format_desc& frame_mixer_device::get_video_format_desc() const { return impl_->format_desc_; }\r
#include <map>\r
\r
namespace caspar { \r
-\r
+ \r
namespace core {\r
\r
class read_frame;\r
class basic_frame;\r
class audio_transform;\r
class image_transform;\r
+class ogl_device;\r
\r
-}\r
-\r
-namespace core {\r
- \r
class frame_mixer_device : public core::frame_factory\r
{\r
public: \r
- frame_mixer_device(const core::video_format_desc& format_desc, const std::function<void(const safe_ptr<const core::read_frame>&)>& output);\r
+ typedef std::function<void(const safe_ptr<core::read_frame>&)> output_t;\r
+\r
+ frame_mixer_device(const core::video_format_desc& format_desc, const output_t& output, const safe_ptr<ogl_device>& ogl);\r
frame_mixer_device(frame_mixer_device&& other); // nothrow\r
\r
void send(const std::map<int, safe_ptr<core::basic_frame>>& frames); // nothrow\r
GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));\r
GL(glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT[stride_], width_, height_, 0, FORMAT[stride_], GL_UNSIGNED_BYTE, NULL));\r
GL(glBindTexture(GL_TEXTURE_2D, 0));\r
- //CASPAR_LOG(trace) << "[device_buffer] allocated size:" << width*height*stride; \r
+ CASPAR_LOG(trace) << "[device_buffer] allocated size:" << width*height*stride; \r
} \r
\r
~implementation()\r
if(!pbo_)\r
BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Failed to allocate buffer."));\r
\r
- //CASPAR_LOG(trace) << "[host_buffer] allocated size:" << size_ << " usage: " << (usage == write_only ? "write_only" : "read_only");\r
+ CASPAR_LOG(trace) << "[host_buffer] allocated size:" << size_ << " usage: " << (usage == write_only ? "write_only" : "read_only");\r
} \r
\r
~implementation()\r
});\r
}\r
\r
-safe_ptr<device_buffer> ogl_device::do_create_device_buffer(size_t width, size_t height, size_t stride)\r
+safe_ptr<device_buffer> ogl_device::create_device_buffer(size_t width, size_t height, size_t stride)\r
{\r
CASPAR_VERIFY(stride > 0 && stride < 5);\r
CASPAR_VERIFY(width > 0 && height > 0);\r
return safe_ptr<device_buffer>(buffer.get(), [=](device_buffer*){pool->push(buffer);});\r
}\r
\r
-safe_ptr<host_buffer> ogl_device::do_create_host_buffer(size_t size, host_buffer::usage_t usage)\r
+safe_ptr<host_buffer> ogl_device::create_host_buffer(size_t size, host_buffer::usage_t usage)\r
{\r
CASPAR_VERIFY(usage == host_buffer::write_only || usage == host_buffer::read_only);\r
CASPAR_VERIFY(size > 0);\r
});\r
}\r
\r
+void ogl_device::yield()\r
+{\r
+ executor_.yield();\r
+}\r
+\r
std::wstring ogl_device::get_version()\r
{ \r
- return widen(invoke([]{return std::string(reinterpret_cast<const char*>(glGetString(GL_VERSION)));})\r
- + " " + invoke([]{return std::string(reinterpret_cast<const char*>(glGetString(GL_VENDOR)));})); \r
+ static std::wstring ver;\r
+ if(ver.empty())\r
+ {\r
+ ogl_device tmp;\r
+ ver = widen(tmp.invoke([]{return std::string(reinterpret_cast<const char*>(glGetString(GL_VERSION)));})\r
+ + " " + tmp.invoke([]{return std::string(reinterpret_cast<const char*>(glGetString(GL_VENDOR)));})); \r
+ }\r
+ return ver;\r
}\r
\r
}}
\ No newline at end of file
unsigned int fbo_;\r
\r
executor executor_;\r
-\r
+ \r
+public: \r
ogl_device();\r
~ogl_device();\r
-\r
- static ogl_device& get_instance()\r
- {\r
- static ogl_device device;\r
- return device;\r
- }\r
\r
template<typename Func>\r
- auto do_begin_invoke(Func&& func, priority priority) -> boost::unique_future<decltype(func())> // noexcept\r
+ auto begin_invoke(Func&& func, priority priority = normal_priority) -> boost::unique_future<decltype(func())> // noexcept\r
{ \r
return executor_.begin_invoke(std::forward<Func>(func), priority);\r
}\r
\r
template<typename Func>\r
- auto do_invoke(Func&& func, priority priority) -> decltype(func())\r
+ auto invoke(Func&& func, priority priority = normal_priority) -> decltype(func())\r
{\r
return executor_.invoke(std::forward<Func>(func), priority);\r
}\r
\r
- safe_ptr<device_buffer> do_create_device_buffer(size_t width, size_t height, size_t stride);\r
- safe_ptr<host_buffer> do_create_host_buffer(size_t size, host_buffer::usage_t usage);\r
-public: \r
- \r
- template<typename Func>\r
- static auto begin_invoke(Func&& func, priority priority = normal_priority) -> boost::unique_future<decltype(func())> // noexcept\r
- { \r
- return get_instance().do_begin_invoke(std::forward<Func>(func), priority);\r
- }\r
- \r
- template<typename Func>\r
- static auto invoke(Func&& func, priority priority = normal_priority) -> decltype(func())\r
- {\r
- return get_instance().do_invoke(std::forward<Func>(func), priority);\r
- }\r
- \r
- static safe_ptr<device_buffer> create_device_buffer(size_t width, size_t height, size_t stride)\r
- {\r
- return get_instance().do_create_device_buffer(width, height, stride);\r
- }\r
-\r
- static safe_ptr<host_buffer> create_host_buffer(size_t size, host_buffer::usage_t usage)\r
- {\r
- return get_instance().do_create_host_buffer(size, usage);\r
- }\r
-\r
- static void yield()\r
- {\r
- get_instance().executor_.yield();\r
- }\r
+ safe_ptr<device_buffer> create_device_buffer(size_t width, size_t height, size_t stride);\r
+ safe_ptr<host_buffer> create_host_buffer(size_t size, host_buffer::usage_t usage);\r
+ void yield();\r
\r
static std::wstring get_version();\r
};\r
std::queue<std::queue<render_item>> render_queue_;\r
\r
image_kernel kernel_;\r
- \r
+ \r
+ safe_ptr<ogl_device> ogl_;\r
+ \r
safe_ptr<host_buffer> read_buffer_;\r
safe_ptr<device_buffer> draw_buffer_;\r
safe_ptr<device_buffer> write_buffer_;\r
\r
bool local_key_;\r
bool layer_key_;\r
-\r
+ \r
public:\r
- implementation(const core::video_format_desc& format_desc) \r
+ implementation(const core::video_format_desc& format_desc, const safe_ptr<ogl_device>& ogl) \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
- , layer_key_buffer_(ogl_device::create_device_buffer(format_desc.width, format_desc.height, 1))\r
+ , ogl_(ogl)\r
+ , read_buffer_(ogl_->create_host_buffer(format_desc_.size, host_buffer::read_only))\r
+ , draw_buffer_(ogl_->create_device_buffer(format_desc.width, format_desc.height, 4))\r
+ , write_buffer_ (ogl_->create_device_buffer(format_desc.width, format_desc.height, 4))\r
+ , local_key_buffer_(ogl_->create_device_buffer(format_desc.width, format_desc.height, 1))\r
+ , layer_key_buffer_(ogl_->create_device_buffer(format_desc.width, format_desc.height, 1))\r
, local_key_(false)\r
, layer_key_(false)\r
{\r
}\r
\r
boost::unique_future<safe_ptr<host_buffer>> render()\r
- {\r
+ { \r
auto read_buffer = read_buffer_;\r
- \r
+ auto result = ogl_->begin_invoke([=]() -> safe_ptr<host_buffer>\r
+ {\r
+ read_buffer->map();\r
+ return read_buffer;\r
+ });\r
+\r
auto render_queue = std::move(render_queue_);\r
\r
- return ogl_device::begin_invoke([=]() mutable -> safe_ptr<host_buffer>\r
+ ogl_->begin_invoke([=]() mutable\r
{\r
local_key_ = false;\r
layer_key_ = false;\r
{\r
draw(layer.front());\r
layer.pop();\r
- ogl_device::yield(); // Allow quick buffer allocation to execute.\r
+ ogl_->yield(); // Allow quick buffer allocation to execute.\r
}\r
\r
layer_key_ = local_key_; // If there was only key in last layer then use it as key for the entire next layer.\r
std::swap(draw_buffer_, write_buffer_);\r
\r
// Start transfer from device to host. \r
- auto result = ogl_device::create_host_buffer(format_desc_.size, host_buffer::read_only); \r
- write_buffer_->write(*result);\r
-\r
- return result;\r
+ read_buffer_ = ogl_->create_host_buffer(format_desc_.size, host_buffer::read_only); \r
+ write_buffer_->write(*read_buffer_);\r
});\r
+\r
+ return std::move(result);\r
}\r
\r
void draw(const render_item& item)\r
{\r
std::vector<safe_ptr<host_buffer>> buffers;\r
std::vector<safe_ptr<device_buffer>> textures;\r
- ogl_device::invoke([&]\r
+ ogl_->invoke([&]\r
{\r
std::transform(desc.planes.begin(), desc.planes.end(), std::back_inserter(buffers), [&](const core::pixel_format_desc::plane& plane)\r
{\r
- return ogl_device::create_host_buffer(plane.size, host_buffer::write_only);\r
+ return ogl_->create_host_buffer(plane.size, host_buffer::write_only);\r
});\r
std::transform(desc.planes.begin(), desc.planes.end(), std::back_inserter(textures), [&](const core::pixel_format_desc::plane& plane)\r
{\r
- return ogl_device::create_device_buffer(plane.width, plane.height, plane.channels);\r
+ return ogl_->create_device_buffer(plane.width, plane.height, plane.channels);\r
});\r
});\r
\r
- return make_safe<write_frame>(reinterpret_cast<int>(tag), desc, buffers, textures);\r
+ return make_safe<write_frame>(reinterpret_cast<int>(tag), desc, buffers, textures, ogl_);\r
}\r
};\r
\r
-image_mixer::image_mixer(const core::video_format_desc& format_desc) : impl_(new implementation(format_desc)){}\r
+image_mixer::image_mixer(const core::video_format_desc& format_desc, const safe_ptr<ogl_device>& ogl) : impl_(new implementation(format_desc, ogl)){}\r
void image_mixer::begin(const core::basic_frame& frame){impl_->begin(frame);}\r
void image_mixer::visit(core::write_frame& frame){impl_->visit(frame);}\r
void image_mixer::end(){impl_->end();}\r
\r
namespace caspar { namespace core {\r
\r
+class ogl_device;\r
+\r
class image_mixer : public core::frame_visitor, boost::noncopyable\r
{\r
public:\r
- image_mixer(const core::video_format_desc& format_desc);\r
+ image_mixer(const core::video_format_desc& format_desc, const safe_ptr<ogl_device>& ogl);\r
\r
virtual void begin(const core::basic_frame& frame);\r
virtual void visit(core::write_frame& frame);\r
#include "read_frame.h"\r
\r
#include "gpu/host_buffer.h" \r
-#include "gpu/ogl_device.h"\r
\r
namespace caspar { namespace core {\r
\r
{\r
try\r
{\r
- if(!image_data_.get()->data())\r
- {\r
- ogl_device::invoke([&]\r
- {\r
- image_data_.get()->map();\r
- }, high_priority);\r
- }\r
-\r
if(!image_data_.get()->data())\r
return boost::iterator_range<const uint8_t*>();\r
auto ptr = static_cast<const uint8_t*>(image_data_.get()->data());\r
namespace caspar { namespace core {\r
\r
class host_buffer;\r
+class ogl_device;\r
\r
class read_frame : boost::noncopyable\r
{\r
\r
virtual const boost::iterator_range<const uint8_t*> image_data() const;\r
virtual const boost::iterator_range<const int16_t*> audio_data() const;\r
- \r
+ \r
static safe_ptr<const read_frame> empty()\r
{\r
struct empty : public read_frame\r
\r
struct write_frame::implementation : boost::noncopyable\r
{ \r
+ safe_ptr<ogl_device> ogl_;\r
std::vector<safe_ptr<host_buffer>> buffers_;\r
std::vector<safe_ptr<device_buffer>> textures_;\r
std::vector<int16_t> audio_data_;\r
int32_t tag_;\r
\r
public:\r
- implementation(int32_t tag, const core::pixel_format_desc& desc, const std::vector<safe_ptr<host_buffer>>& buffers, const std::vector<safe_ptr<device_buffer>>& textures) \r
- : desc_(desc)\r
+ implementation(int32_t tag, const core::pixel_format_desc& desc, const std::vector<safe_ptr<host_buffer>>& buffers, const std::vector<safe_ptr<device_buffer>>& textures, const safe_ptr<ogl_device> ogl) \r
+ : ogl_(ogl)\r
, buffers_(buffers)\r
, textures_(textures)\r
+ , desc_(desc)\r
, tag_(tag)\r
{}\r
\r
auto texture = textures_[plane_index];\r
auto buffer = std::move(buffers_[plane_index]); // Release buffer once done.\r
\r
- ogl_device::begin_invoke([=]\r
+ ogl_->begin_invoke([=]\r
{\r
texture->read(*buffer);\r
});\r
}\r
};\r
\r
-write_frame::write_frame(int32_t tag, const core::pixel_format_desc& desc, const std::vector<safe_ptr<host_buffer>>& buffers, const std::vector<safe_ptr<device_buffer>>& textures) : impl_(new implementation(tag, desc, buffers, textures)){}\r
+write_frame::write_frame(int32_t tag, const core::pixel_format_desc& desc, const std::vector<safe_ptr<host_buffer>>& buffers, const std::vector<safe_ptr<device_buffer>>& textures, const safe_ptr<ogl_device>& ogl) \r
+ : impl_(new implementation(tag, desc, buffers, textures, ogl)){}\r
void write_frame::accept(core::frame_visitor& visitor){impl_->accept(*this, visitor);}\r
\r
boost::iterator_range<uint8_t*> write_frame::image_data(size_t index){return impl_->image_data(index);}\r
class device_buffer;\r
struct frame_visitor;\r
struct pixel_format_desc;\r
- \r
+class ogl_device; \r
+\r
class write_frame : public core::basic_frame, boost::noncopyable\r
{\r
public: \r
- explicit write_frame(int tag, const core::pixel_format_desc& desc, const std::vector<safe_ptr<host_buffer>>& buffers, const std::vector<safe_ptr<device_buffer>>& textures);\r
+ explicit write_frame(int tag, const core::pixel_format_desc& desc, const std::vector<safe_ptr<host_buffer>>& buffers, const std::vector<safe_ptr<device_buffer>>& textures, const safe_ptr<ogl_device>& ogl);\r
\r
virtual boost::iterator_range<uint8_t*> image_data(size_t plane_index = 0); \r
virtual std::vector<int16_t>& audio_data();\r
core::register_producer_factory(create_ffmpeg_producer);\r
}\r
\r
-std::wstring get_avcodec_version()\r
+std::wstring make_version(unsigned int ver)\r
{\r
std::wstringstream str;\r
- str << ((avcodec_version() >> 16) & 0xFF) << L"." << ((avcodec_version() >> 8) & 0xFF) << L"." << ((avcodec_version() >> 0) & 0xFF);\r
+ str << ((ver >> 16) & 0xFF) << L"." << ((ver >> 8) & 0xFF) << L"." << ((ver >> 0) & 0xFF);\r
return str.str();\r
}\r
\r
+std::wstring get_avcodec_version()\r
+{\r
+ return make_version(avcodec_version());\r
+}\r
+\r
std::wstring get_avformat_version()\r
{\r
- std::wstringstream str;\r
- str << ((avformat_version() >> 16) & 0xFF) << L"." << ((avformat_version() >> 8) & 0xFF) << L"." << ((avformat_version() >> 0) & 0xFF);\r
- return str.str();\r
+ return make_version(avformat_version());\r
}\r
\r
std::wstring get_avutil_version()\r
{\r
- std::wstringstream str;\r
- str << ((avutil_version() >> 16) & 0xFF) << L"." << ((avutil_version() >> 8) & 0xFF) << L"." << ((avutil_version() >> 0) & 0xFF);\r
- return str.str();\r
+ return make_version(avutil_version());\r
}\r
\r
std::wstring get_avfilter_version()\r
{\r
- std::wstringstream str;\r
- str << ((avfilter_version() >> 16) & 0xFF) << L"." << ((avfilter_version() >> 8) & 0xFF) << L"." << ((avfilter_version() >> 0) & 0xFF);\r
- return str.str();\r
+ return make_version(avfilter_version());\r
}\r
\r
std::wstring get_swscale_version()\r
{\r
- std::wstringstream str;\r
- str << ((swscale_version() >> 16) & 0xFF) << L"." << ((swscale_version() >> 8) & 0xFF) << L"." << ((swscale_version() >> 0) & 0xFF);\r
- return str.str();\r
+ return make_version(swscale_version());\r
}\r
\r
}
\ No newline at end of file
#include <common/exception/exceptions.h>\r
#include <common/utility/string.h>\r
\r
+#include <core/mixer/gpu/ogl_device.h>\r
#include <core/channel.h>\r
\r
#include <modules/bluefish/bluefish.h>\r
using namespace core;\r
using namespace protocol;\r
\r
+\r
struct server::implementation : boost::noncopyable\r
{\r
std::vector<safe_ptr<IO::AsyncEventServer>> async_servers_; \r
- std::vector<safe_ptr<channel>> channels_;\r
+ std::vector<safe_ptr<channel>> channels_;\r
+ safe_ptr<ogl_device> ogl_;\r
\r
implementation() \r
{ \r
if(format_desc.format == video_format::invalid)\r
BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Invalid video-mode."));\r
\r
- channels_.push_back(channel(channels_.size(), format_desc));\r
+ channels_.push_back(channel(channels_.size(), format_desc, ogl_));\r
\r
int index = 0;\r
BOOST_FOREACH(auto& xml_consumer, xml_channel.second.get_child("consumers"))\r