*/\r
\r
#define NOMINMAX\r
+#define WIN32_LEAN_AND_MEAN\r
\r
#include <windows.h>\r
-#include <Glee.h>\r
+#include <GL/glew.h>\r
#include <SFML/Window.hpp>\r
\r
#include "ogl_consumer.h"\r
\r
-#include <core/video_format.h>\r
-#include <core/mixer/read_frame.h>\r
-\r
#include <common/gl/gl_check.h>\r
#include <common/concurrency/executor.h>\r
#include <common/memory/safe_ptr.h>\r
#include <common/diagnostics/graph.h>\r
#include <common/utility/timer.h>\r
\r
-#include <boost/thread.hpp>\r
+#include <core/video_format.h>\r
+#include <core/mixer/read_frame.h>\r
+#include <core/consumer/frame_consumer.h>\r
+\r
#include <boost/timer.hpp>\r
+#include <boost/circular_buffer.hpp>\r
\r
#include <algorithm>\r
#include <array>\r
\r
struct ogl_consumer : boost::noncopyable\r
{ \r
- boost::unique_future<void> active_;\r
- \r
- float width_;\r
- float height_;\r
+ float width_;\r
+ float height_;\r
\r
- GLuint texture_;\r
- std::array<GLuint, 2> pbos_;\r
+ GLuint texture_;\r
+ std::array<GLuint, 2> pbos_;\r
\r
- const bool windowed_;\r
- unsigned int screen_width_;\r
- unsigned int screen_height_;\r
- const unsigned int screen_index_;\r
+ const bool windowed_;\r
+ unsigned int screen_width_;\r
+ unsigned int screen_height_;\r
+ const unsigned int screen_index_;\r
\r
- const stretch stretch_;\r
+ const stretch stretch_;\r
core::video_format_desc format_desc_;\r
\r
- sf::Window window_;\r
+ sf::Window window_;\r
\r
safe_ptr<diagnostics::graph> graph_;\r
- boost::timer perf_timer_;\r
+ boost::timer perf_timer_;\r
\r
- size_t square_width_;\r
- size_t square_height_;\r
+ size_t square_width_;\r
+ size_t square_height_;\r
\r
- executor executor_;\r
+ boost::circular_buffer<safe_ptr<core::read_frame>> input_buffer_;\r
+ tbb::concurrent_bounded_queue<safe_ptr<core::read_frame>> frame_buffer_;\r
+\r
+ executor executor_;\r
public:\r
ogl_consumer(unsigned int screen_index, stretch stretch, bool windowed, const core::video_format_desc& format_desc) \r
: stretch_(stretch)\r
, screen_index_(screen_index)\r
, format_desc_(format_desc_)\r
, graph_(diagnostics::create_graph(narrow(print())))\r
+ , input_buffer_(core::consumer_buffer_depth()-1)\r
, executor_(print())\r
{ \r
- executor_.set_capacity(3);\r
+ frame_buffer_.set_capacity(2);\r
+\r
graph_->add_guide("frame-time", 0.5);\r
graph_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f));\r
- if(!GLEE_VERSION_2_1)\r
- BOOST_THROW_EXCEPTION(not_supported() << msg_info("Missing OpenGL 2.1 support."));\r
+ graph_->set_color("dropped-frame", diagnostics::color(0.3f, 0.6f, 0.3f));\r
\r
format_desc_ = format_desc;\r
\r
#endif \r
executor_.invoke([=]\r
{\r
+ if(!GLEW_VERSION_2_1)\r
+ BOOST_THROW_EXCEPTION(not_supported() << msg_info("Missing OpenGL 2.1 support."));\r
+\r
window_.Create(sf::VideoMode(screen_width_, screen_height_, 32), narrow(print()), windowed_ ? sf::Style::Resize : sf::Style::Fullscreen);\r
window_.ShowMouseCursor(false);\r
window_.SetPosition(devmode.dmPosition.x, devmode.dmPosition.y);\r
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);\r
});\r
CASPAR_LOG(info) << print() << " Sucessfully Initialized.";\r
+\r
+ executor_.begin_invoke([this]{tick();});\r
+ }\r
+\r
+ ~ogl_consumer()\r
+ {\r
+ executor_.stop();\r
+ frame_buffer_.push(make_safe<core::read_frame>());\r
}\r
\r
+ const core::video_format_desc& get_video_format_desc() const\r
+ {\r
+ return format_desc_;\r
+ }\r
+\r
void calculate_aspect()\r
{\r
if(windowed_)\r
return std::make_pair(width, height);\r
}\r
\r
- void render(const safe_ptr<const core::read_frame>& frame)\r
+ void render(const safe_ptr<core::read_frame>& frame)\r
{ \r
glBindTexture(GL_TEXTURE_2D, texture_);\r
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbos_[0]);\r
\r
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbos_[0]);\r
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, format_desc_.width, format_desc_.height, GL_BGRA, GL_UNSIGNED_BYTE, 0);\r
\r
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbos_[1]);\r
-\r
glBufferData(GL_PIXEL_UNPACK_BUFFER, format_desc_.size, 0, GL_STREAM_DRAW);\r
\r
auto ptr = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);\r
\r
std::rotate(pbos_.begin(), pbos_.begin() + 1, pbos_.end());\r
}\r
- \r
- void send(const safe_ptr<const core::read_frame>& frame)\r
+\r
+ void send(const safe_ptr<core::read_frame>& frame)\r
{\r
- if(executor_.size() >= executor_.capacity()-1)\r
- return;\r
+ input_buffer_.push_back(frame);\r
\r
- executor_.begin_invoke([=]\r
+ if(input_buffer_.full())\r
+ {\r
+ if(!frame_buffer_.try_push(input_buffer_.front()))\r
+ graph_->add_tag("dropped-frame");\r
+ }\r
+ }\r
+ \r
+ std::wstring print() const\r
+ { \r
+ return L"ogl[" + boost::lexical_cast<std::wstring>(screen_index_) + L"|" + format_desc_.name + L"]";\r
+ }\r
+\r
+ void tick()\r
+ {\r
+ try\r
{\r
perf_timer_.restart();\r
sf::Event e;\r
+ \r
+ safe_ptr<core::read_frame> frame;\r
+\r
while(window_.GetEvent(e))\r
{\r
if(e.Type == sf::Event::Resized)\r
- calculate_aspect();\r
+ calculate_aspect();\r
}\r
- render(frame);\r
- window_.Display();\r
- graph_->update_value("frame-time", static_cast<float>(perf_timer_.elapsed()*format_desc_.fps*0.5));\r
- });\r
- }\r
\r
- std::wstring print() const\r
- { \r
- return L"ogl[" + boost::lexical_cast<std::wstring>(screen_index_) + L"|" + format_desc_.name + L"]";\r
- }\r
+ frame_buffer_.pop(frame);\r
+\r
+ if(!frame->image_data().empty())\r
+ render(frame);\r
\r
- size_t buffer_depth() const{return 2;}\r
+ window_.Display();\r
+ graph_->update_value("frame-time", static_cast<float>(perf_timer_.elapsed()*format_desc_.fps*0.5)); \r
+ }\r
+ catch(...)\r
+ {\r
+ CASPAR_LOG_CURRENT_EXCEPTION();\r
+ }\r
+ executor_.begin_invoke([=]{tick();});\r
+ }\r
};\r
\r
\r
consumer_.reset(new ogl_consumer(screen_index_, stretch_, windowed_, format_desc));\r
}\r
\r
- virtual void send(const safe_ptr<const core::read_frame>& frame)\r
+ virtual bool send(const safe_ptr<core::read_frame>& frame)\r
{\r
consumer_->send(frame);\r
+ return true;\r
}\r
\r
virtual std::wstring print() const\r
{\r
return key_only_;\r
}\r
+\r
+ virtual bool has_synchronization_clock() const \r
+ {\r
+ return false;\r
+ }\r
+\r
+ virtual const core::video_format_desc& get_video_format_desc() const\r
+ {\r
+ return consumer_->get_video_format_desc();\r
+ }\r
}; \r
\r
safe_ptr<core::frame_consumer> create_ogl_consumer(const std::vector<std::wstring>& params)\r
{\r
- if(params.size() < 1 || params[0] != L"OGL")\r
+ if(params.size() < 1 || params[0] != L"SCREEN")\r
return core::frame_consumer::empty();\r
\r
size_t screen_index = 0;\r