\r
struct read_frame::implementation : boost::noncopyable\r
{\r
- safe_ptr<host_buffer> image_data_;\r
+ std::shared_ptr<host_buffer> image_data_;\r
std::vector<int16_t> audio_data_;\r
\r
public:\r
+ implementation(){}\r
+\r
implementation(safe_ptr<host_buffer>&& image_data, std::vector<int16_t>&& audio_data) \r
: image_data_(std::move(image_data))\r
, audio_data_(std::move(audio_data)){} \r
\r
const boost::iterator_range<const uint8_t*> image_data()\r
{\r
+ if(!image_data_)\r
+ return boost::iterator_range<const uint8_t*>();\r
+\r
auto ptr = static_cast<const uint8_t*>(image_data_->data());\r
return boost::iterator_range<const uint8_t*>(ptr, ptr + image_data_->size());\r
}\r
\r
read_frame::read_frame(safe_ptr<host_buffer>&& image_data, std::vector<int16_t>&& audio_data) \r
: impl_(new implementation(std::move(image_data), std::move(audio_data))){}\r
-\r
+read_frame::read_frame()\r
+ : impl_(new implementation()){}\r
const boost::iterator_range<const uint8_t*> read_frame::image_data() const{return impl_->image_data();}\r
const boost::iterator_range<const int16_t*> read_frame::audio_data() const{return impl_->audio_data();}\r
\r
-safe_ptr<const read_frame> read_frame::empty()\r
-{\r
- struct empty : public read_frame\r
- { \r
- virtual const boost::iterator_range<const uint8_t*> image_data() const {return boost::iterator_range<const uint8_t*>();}\r
- virtual const boost::iterator_range<const int16_t*> audio_data() const {return boost::iterator_range<const int16_t*>();}\r
- virtual int number() const{return -1;}\r
- };\r
- static safe_ptr<const empty> frame;\r
- return frame;\r
-}\r
-\r
}}
\ No newline at end of file
#include <common/diagnostics/graph.h>\r
#include <common/utility/timer.h>\r
\r
-#include <boost/thread.hpp>\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
\r
- size_t square_width_;\r
- size_t square_height_;\r
+ boost::circular_buffer<safe_ptr<const core::read_frame>> frame_buffer_;\r
\r
- executor executor_;\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
+ , frame_buffer_(CONSUMER_BUFFER_DEPTH)\r
, executor_(print())\r
{ \r
- executor_.set_capacity(3);\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
\r
format_desc_ = format_desc;\r
\r
#endif \r
executor_.invoke([=]\r
{\r
+ if(!GLEE_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
void render(const safe_ptr<const 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
+\r
void send(const safe_ptr<const core::read_frame>& frame)\r
{\r
+ frame_buffer_.push_back(frame);\r
+\r
+ if(frame_buffer_.full())\r
+ do_send(frame_buffer_.front());\r
+ }\r
+ \r
+ void do_send(const safe_ptr<const core::read_frame>& frame)\r
+ { \r
executor_.try_begin_invoke([=]\r
{\r
perf_timer_.restart();\r