From 9aede4119d2cfb1d2ca1b721e4a05e325e190951 Mon Sep 17 00:00:00 2001 From: ronag Date: Tue, 2 Nov 2010 15:27:07 +0000 Subject: [PATCH] 2.0.0.2: - Fixed crash bug in AMCP, where invalid layer string crashed the server. - Refactored gpu related code. - Updated layer_test. git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.0.0.2@212 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d --- common/gl/gl_check.h | 4 +- core/consumer/ogl/ogl_consumer.cpp | 20 +-- core/frame/gpu_composite_frame.cpp | 28 ++- core/frame/gpu_composite_frame.h | 16 +- core/frame/gpu_frame.cpp | 167 +++++++++--------- core/frame/gpu_frame_processor.cpp | 147 ++++++++------- .../transition/transition_producer.cpp | 2 +- core/protocol/amcp/AMCPProtocolStrategy.cpp | 16 +- core/renderer/layer.cpp | 13 +- core/renderer/layer.h | 6 +- test/mock/mock_frame_producer.h | 43 +++++ test/test.vcxproj | 14 +- test/test.vcxproj.filters | 23 ++- 13 files changed, 272 insertions(+), 227 deletions(-) create mode 100644 test/mock/mock_frame_producer.h diff --git a/common/gl/gl_check.h b/common/gl/gl_check.h index c8c10a980..00d78c0f6 100644 --- a/common/gl/gl_check.h +++ b/common/gl/gl_check.h @@ -109,14 +109,14 @@ inline void SMFL_GLCheckError(const std::string& expr, const std::string& File, #define CASPAR_GL_EXPR_STR(expr) #expr -#define CASPAR_GL_CHECK(expr) \ +#define GL(expr) \ do \ { \ (expr); \ caspar::common::gl::SMFL_GLCheckError(CASPAR_GL_EXPR_STR(expr), __FILE__, __LINE__);\ }while(0); #else -#define CASPAR_GL_CHECK(expr) expr +#define GL(expr) expr #endif }}} \ No newline at end of file diff --git a/core/consumer/ogl/ogl_consumer.cpp b/core/consumer/ogl/ogl_consumer.cpp index ae9be4b79..968d25fc7 100644 --- a/core/consumer/ogl/ogl_consumer.cpp +++ b/core/consumer/ogl/ogl_consumer.cpp @@ -121,11 +121,11 @@ struct consumer::implementation : boost::noncopyable image_.Create(format_desc_.width, format_desc_.height); sprite_.SetImage(image_); - CASPAR_GL_CHECK(glGenBuffersARB(2, pbos_)); - CASPAR_GL_CHECK(glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, pbos_[0])); - CASPAR_GL_CHECK(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, format_desc_.size, 0, GL_STREAM_DRAW)); - CASPAR_GL_CHECK(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbos_[1])); - CASPAR_GL_CHECK(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, format_desc_.size, 0, GL_STREAM_DRAW)); + GL(glGenBuffersARB(2, pbos_)); + GL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, pbos_[0])); + GL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, format_desc_.size, 0, GL_STREAM_DRAW)); + GL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbos_[1])); + GL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, format_desc_.size, 0, GL_STREAM_DRAW)); pbo_index_ = 0; } @@ -170,22 +170,22 @@ struct consumer::implementation : boost::noncopyable window_.Clear(); image_.Bind(); - CASPAR_GL_CHECK(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbos_[pbo_index_])); - CASPAR_GL_CHECK(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, format_desc_.width, format_desc_.height, GL_BGRA, GL_UNSIGNED_BYTE, 0)); + GL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbos_[pbo_index_])); + GL(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, format_desc_.width, format_desc_.height, GL_BGRA, GL_UNSIGNED_BYTE, 0)); window_.Draw(sprite_); // Update int nextPboIndex = pbo_index_ ^ 1; - CASPAR_GL_CHECK(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbos_[nextPboIndex])); - CASPAR_GL_CHECK(glBufferData(GL_PIXEL_UNPACK_BUFFER, format_desc_.size, NULL, GL_STREAM_DRAW)); + GL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbos_[nextPboIndex])); + GL(glBufferData(GL_PIXEL_UNPACK_BUFFER, format_desc_.size, NULL, GL_STREAM_DRAW)); GLubyte* ptr = static_cast(glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY)); if(ptr != NULL) { common::copy(ptr, frame->data(), frame->size()); - CASPAR_GL_CHECK(glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER)); + GL(glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER)); } // Swap diff --git a/core/frame/gpu_composite_frame.cpp b/core/frame/gpu_composite_frame.cpp index cb08e71a2..17b8faaae 100644 --- a/core/frame/gpu_composite_frame.cpp +++ b/core/frame/gpu_composite_frame.cpp @@ -4,6 +4,8 @@ #include "../../common/gl/gl_check.h" #include "../../common/utility/memory.h" +#include + #include #include @@ -15,29 +17,32 @@ struct gpu_composite_frame::implementation : boost::noncopyable void write_lock() { - std::for_each(frames_.begin(), frames_.end(), std::mem_fn(&gpu_frame::write_lock)); + boost::range::for_each(frames_, std::mem_fn(&gpu_frame::write_lock)); } bool write_unlock() { - return std::all_of(frames_.begin(), frames_.end(), std::mem_fn(&gpu_frame::write_unlock)); + return std::all_of(frames_.begin(), frames_.end(), + std::mem_fn(&gpu_frame::write_unlock)); } void read_lock(GLenum mode) { - std::for_each(frames_.begin(), frames_.end(), std::bind(&gpu_frame::read_lock, std::placeholders::_1, mode)); + boost::range::for_each(frames_, std::bind(&gpu_frame::read_lock, + std::placeholders::_1, mode)); } bool read_unlock() { - return std::all_of(frames_.begin(), frames_.end(), std::mem_fn(&gpu_frame::read_unlock)); + return std::all_of(frames_.begin(), frames_.end(), + std::mem_fn(&gpu_frame::read_unlock)); } void draw() { glPushMatrix(); glTranslated(self_->x()*2.0, self_->y()*2.0, 0.0); - std::for_each(frames_.begin(), frames_.end(), std::mem_fn(&gpu_frame::draw)); + boost::range::for_each(frames_, std::mem_fn(&gpu_frame::draw)); glPopMatrix(); } @@ -50,7 +55,9 @@ struct gpu_composite_frame::implementation : boost::noncopyable else { for(size_t n = 0; n < frame->audio_data().size(); ++n) - self_->audio_data()[n] = static_cast(static_cast(self_->audio_data()[n]) + static_cast(frame->audio_data()[n]) & 0xFFFF); + self_->audio_data()[n] = static_cast( + static_cast(self_->audio_data()[n]) + + static_cast(frame->audio_data()[n]) & 0xFFFF); } } @@ -66,7 +73,8 @@ struct gpu_composite_frame::implementation : boost::noncopyable #pragma warning (disable : 4355) -gpu_composite_frame::gpu_composite_frame(size_t width, size_t height) : gpu_frame(width, height), impl_(new implementation(this)){} +gpu_composite_frame::gpu_composite_frame() + : gpu_frame(0, 0), impl_(new implementation(this)){} void gpu_composite_frame::write_lock(){impl_->write_lock();} bool gpu_composite_frame::write_unlock(){return impl_->write_unlock();} void gpu_composite_frame::read_lock(GLenum mode){impl_->read_lock(mode);} @@ -75,9 +83,11 @@ void gpu_composite_frame::draw(){impl_->draw();} unsigned char* gpu_composite_frame::data(){return impl_->data();} void gpu_composite_frame::add(const gpu_frame_ptr& frame){impl_->add(frame);} -gpu_frame_ptr gpu_composite_frame::interlace(const gpu_frame_ptr& frame1 ,const gpu_frame_ptr& frame2, video_mode mode) +gpu_frame_ptr gpu_composite_frame::interlace(const gpu_frame_ptr& frame1, + const gpu_frame_ptr& frame2, + video_mode mode) { - auto result = std::make_shared(frame1->width(), frame1->height()); + auto result = std::make_shared(); result->add(frame1); result->add(frame2); if(mode == video_mode::upper) diff --git a/core/frame/gpu_composite_frame.h b/core/frame/gpu_composite_frame.h index 504768369..dc7754811 100644 --- a/core/frame/gpu_composite_frame.h +++ b/core/frame/gpu_composite_frame.h @@ -11,20 +11,20 @@ namespace caspar { namespace core { class gpu_composite_frame : public gpu_frame { public: - gpu_composite_frame(size_t width, size_t height); + gpu_composite_frame(); + + void add(const gpu_frame_ptr& frame); + static gpu_frame_ptr interlace(const gpu_frame_ptr& frame1, + const gpu_frame_ptr& frame2, video_mode mode); + +private: + virtual unsigned char* data(); virtual void write_lock(); virtual bool write_unlock(); virtual void read_lock(GLenum mode); virtual bool read_unlock(); virtual void draw(); - - void add(const gpu_frame_ptr& frame); - - static gpu_frame_ptr interlace(const gpu_frame_ptr& frame1 ,const gpu_frame_ptr& frame2, video_mode mode); - -private: - virtual unsigned char* data(); struct implementation; std::shared_ptr impl_; diff --git a/core/frame/gpu_frame.cpp b/core/frame/gpu_frame.cpp index a7f788fbe..7bcbf6db3 100644 --- a/core/frame/gpu_frame.cpp +++ b/core/frame/gpu_frame.cpp @@ -7,65 +7,66 @@ namespace caspar { namespace core { GLubyte progressive_pattern[] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xFF, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xFF, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; GLubyte upper_pattern[] = { - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00}; + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00}; GLubyte lower_pattern[] = { 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff}; - + struct gpu_frame::implementation : boost::noncopyable { implementation(size_t width, size_t height) - : pbo_(0), data_(nullptr), width_(width), height_(height), size_(width*height*4), - reading_(false), texture_(0), alpha_(1.0f), x_(0.0f), y_(0.0f), mode_(video_mode::progressive) + : pbo_(0), data_(nullptr), width_(width), height_(height), + size_(width*height*4), reading_(false), texture_(0), alpha_(1.0f), + x_(0.0f), y_(0.0f), mode_(video_mode::progressive) { } @@ -80,7 +81,7 @@ struct gpu_frame::implementation : boost::noncopyable GLuint pbo() { if(pbo_ == 0) - CASPAR_GL_CHECK(glGenBuffers(1, &pbo_)); + GL(glGenBuffers(1, &pbo_)); return pbo_; } @@ -88,55 +89,58 @@ struct gpu_frame::implementation : boost::noncopyable { if(texture_ == 0) { - CASPAR_GL_CHECK(glGenTextures(1, &texture_)); + GL(glGenTextures(1, &texture_)); - CASPAR_GL_CHECK(glBindTexture(GL_TEXTURE_2D, texture_)); + GL(glBindTexture(GL_TEXTURE_2D, texture_)); - CASPAR_GL_CHECK(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); - CASPAR_GL_CHECK(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); - CASPAR_GL_CHECK(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); - CASPAR_GL_CHECK(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); + GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); + GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); + GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); + GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); - CASPAR_GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width_, height_, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL)); + GL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width_, height_, 0, GL_BGRA, + GL_UNSIGNED_BYTE, NULL)); } - CASPAR_GL_CHECK(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo())); + GL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo())); if(data_ != nullptr) { - CASPAR_GL_CHECK(glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER)); + GL(glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER)); data_ = nullptr; } - CASPAR_GL_CHECK(glBindTexture(GL_TEXTURE_2D, texture_)); - CASPAR_GL_CHECK(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width_, height_, GL_BGRA, GL_UNSIGNED_BYTE, NULL)); - CASPAR_GL_CHECK(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0)); + GL(glBindTexture(GL_TEXTURE_2D, texture_)); + GL(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width_, height_, GL_BGRA, + GL_UNSIGNED_BYTE, NULL)); + GL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0)); } bool write_unlock() { if(data_ != nullptr) return false; - CASPAR_GL_CHECK(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo())); - CASPAR_GL_CHECK(glBufferData(GL_PIXEL_UNPACK_BUFFER, size_, NULL, GL_STREAM_DRAW)); + GL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo())); + GL(glBufferData(GL_PIXEL_UNPACK_BUFFER, size_, NULL, GL_STREAM_DRAW)); void* ptr = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); - CASPAR_GL_CHECK(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0)); + GL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0)); data_ = reinterpret_cast(ptr); if(!data_) - BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("glMapBuffer failed")); + BOOST_THROW_EXCEPTION(invalid_operation() + << msg_info("glMapBuffer failed")); return true; } void read_lock(GLenum mode) { - CASPAR_GL_CHECK(glReadBuffer(mode)); - CASPAR_GL_CHECK(glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo())); + GL(glReadBuffer(mode)); + GL(glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo())); if(data_ != nullptr) { - CASPAR_GL_CHECK(glUnmapBuffer(GL_PIXEL_PACK_BUFFER)); + GL(glUnmapBuffer(GL_PIXEL_PACK_BUFFER)); data_ = nullptr; } - CASPAR_GL_CHECK(glBufferData(GL_PIXEL_PACK_BUFFER, size_, NULL, GL_STREAM_READ)); - CASPAR_GL_CHECK(glReadPixels(0, 0, width_, height_, GL_BGRA, GL_UNSIGNED_BYTE, NULL)); - CASPAR_GL_CHECK(glBindBuffer(GL_PIXEL_PACK_BUFFER, 0)); + GL(glBufferData(GL_PIXEL_PACK_BUFFER, size_, NULL, GL_STREAM_READ)); + GL(glReadPixels(0, 0, width_, height_, GL_BGRA, GL_UNSIGNED_BYTE, NULL)); + GL(glBindBuffer(GL_PIXEL_PACK_BUFFER, 0)); reading_ = true; } @@ -144,9 +148,9 @@ struct gpu_frame::implementation : boost::noncopyable { if(data_ != nullptr || !reading_) return false; - CASPAR_GL_CHECK(glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo())); + GL(glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo())); void* ptr = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY); - CASPAR_GL_CHECK(glBindBuffer(GL_PIXEL_PACK_BUFFER, 0)); + GL(glBindBuffer(GL_PIXEL_PACK_BUFFER, 0)); data_ = reinterpret_cast(ptr); if(!data_) BOOST_THROW_EXCEPTION(std::bad_alloc()); @@ -167,7 +171,7 @@ struct gpu_frame::implementation : boost::noncopyable else if(mode_ == video_mode::lower) glPolygonStipple(lower_pattern); - CASPAR_GL_CHECK(glBindTexture(GL_TEXTURE_2D, texture_)); + GL(glBindTexture(GL_TEXTURE_2D, texture_)); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f); glTexCoord2f(1.0f, 0.0f); glVertex2f( 1.0f, -1.0f); @@ -188,9 +192,9 @@ struct gpu_frame::implementation : boost::noncopyable { audio_data_.clear(); alpha_ = 1.0f; - x_ = 0.0f; - y_ = 0.0f; - mode_ = video_mode::progressive; + x_ = 0.0f; + y_ = 0.0f; + mode_ = video_mode::progressive; } gpu_frame* self_; @@ -209,7 +213,8 @@ struct gpu_frame::implementation : boost::noncopyable video_mode mode_; }; -gpu_frame::gpu_frame(size_t width, size_t height) : impl_(new implementation(width, height)){} +gpu_frame::gpu_frame(size_t width, size_t height) + : impl_(new implementation(width, height)){} void gpu_frame::write_lock(){impl_->write_lock();} bool gpu_frame::write_unlock(){return impl_->write_unlock();} void gpu_frame::read_lock(GLenum mode){impl_->read_lock(mode);} @@ -219,7 +224,7 @@ unsigned char* gpu_frame::data(){return impl_->data();} size_t gpu_frame::size() const { return impl_->size_; } size_t gpu_frame::width() const { return impl_->width_;} size_t gpu_frame::height() const { return impl_->height_;} -const std::vector& gpu_frame::audio_data() const { return impl_->audio_data_; } +const std::vector& gpu_frame::audio_data() const{return impl_->audio_data_;} std::vector& gpu_frame::audio_data() { return impl_->audio_data_; } void gpu_frame::reset(){impl_->reset();} double gpu_frame::alpha() const{ return impl_->alpha_;} diff --git a/core/frame/gpu_frame_processor.cpp b/core/frame/gpu_frame_processor.cpp index 5c260de85..82d674e73 100644 --- a/core/frame/gpu_frame_processor.cpp +++ b/core/frame/gpu_frame_processor.cpp @@ -31,46 +31,10 @@ namespace caspar { namespace core { -class frame_buffer : boost::noncopyable -{ -public: - frame_buffer(size_t width, size_t height) - { - CASPAR_GL_CHECK(glGenTextures(1, &texture_)); - - CASPAR_GL_CHECK(glBindTexture(GL_TEXTURE_2D, texture_)); - - CASPAR_GL_CHECK(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); - CASPAR_GL_CHECK(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); - //CASPAR_GL_CHECK(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); - //CASPAR_GL_CHECK(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); - - CASPAR_GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL)); - - glGenFramebuffersEXT(1, &fbo_); - - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_); - glBindTexture(GL_TEXTURE_2D, texture_); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texture_, 0); - } - - ~frame_buffer() - { - glDeleteFramebuffersEXT(1, &fbo_); - } - - GLuint handle() { return fbo_; } - GLenum attachement() { return GL_COLOR_ATTACHMENT0_EXT; } - -private: - GLuint texture_; - GLuint fbo_; -}; -typedef std::shared_ptr frame_buffer_ptr; - struct gpu_frame_processor::implementation : boost::noncopyable { - implementation(const frame_format_desc& format_desc) : format_desc_(format_desc) + implementation(const frame_format_desc& format_desc) + : format_desc_(format_desc), index_(0) { input_.set_capacity(2); executor_.start(); @@ -78,21 +42,32 @@ struct gpu_frame_processor::implementation : boost::noncopyable { ogl_context_.reset(new sf::Context()); ogl_context_->SetActive(true); - CASPAR_GL_CHECK(glEnable(GL_POLYGON_STIPPLE)); - CASPAR_GL_CHECK(glEnable(GL_TEXTURE_2D)); - CASPAR_GL_CHECK(glEnable(GL_BLEND)); - CASPAR_GL_CHECK(glDisable(GL_DEPTH_TEST)); - CASPAR_GL_CHECK(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); - CASPAR_GL_CHECK(glClearColor(0.0, 0.0, 0.0, 0.0)); - CASPAR_GL_CHECK(glViewport(0, 0, format_desc_.width, format_desc_.height)); - glLoadIdentity(); + GL(glEnable(GL_POLYGON_STIPPLE)); + GL(glEnable(GL_TEXTURE_2D)); + GL(glEnable(GL_BLEND)); + GL(glDisable(GL_DEPTH_TEST)); + GL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); + GL(glClearColor(0.0, 0.0, 0.0, 0.0)); + GL(glViewport(0, 0, format_desc_.width, format_desc_.height)); + glLoadIdentity(); + + // Create and bind a framebuffer + GL(glGenTextures(1, &render_texture_)); + GL(glBindTexture(GL_TEXTURE_2D, render_texture_)); + GL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, format_desc_.width, + format_desc_.height, 0, GL_BGRA, + GL_UNSIGNED_BYTE, NULL)); + GL(glGenFramebuffersEXT(1, &fbo_)); + GL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_)); + GL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, + render_texture_, 0)); - reading_.resize(2, std::make_shared(format_desc_.width, format_desc_.height)); - writing_.resize(2, std::make_shared(format_desc_.width, format_desc_.height)); - fbo_ = std::make_shared(format_desc_.width, format_desc_.height); - output_frame_ = std::make_shared(format_desc_.width, format_desc_.height); - index_ = 0; + writing_.resize(2, std::make_shared()); + output_frame_ = std::make_shared(format_desc_.width, + format_desc_.height); }); + // Fill pipeline composite(std::vector()); composite(std::vector()); composite(std::vector()); @@ -100,6 +75,7 @@ struct gpu_frame_processor::implementation : boost::noncopyable ~implementation() { + glDeleteFramebuffersEXT(1, &fbo_); executor_.stop(); } @@ -107,45 +83,46 @@ struct gpu_frame_processor::implementation : boost::noncopyable { boost::range::remove_erase(frames, nullptr); boost::range::remove_erase(frames, gpu_frame::null()); - auto composite_frame = std::make_shared(format_desc_.width, format_desc_.height); - boost::range::for_each(frames, std::bind(&gpu_composite_frame::add, composite_frame, std::placeholders::_1)); - input_.push(composite_frame); + auto composite_frame = std::make_shared(); + boost::range::for_each(frames, std::bind(&gpu_composite_frame::add, + composite_frame, + std::placeholders::_1)); + input_.push(composite_frame); executor_.begin_invoke([=] { try { - gpu_composite_frame_ptr frame; + gpu_frame_ptr frame; input_.pop(frame); index_ = (index_ + 1) % 2; int next_index = (index_ + 1) % 2; - // 2. Start asynchronous DMA transfer to video memory - // Lock frames and give pointer ownership to OpenGL - writing_[index_] = std::move(reading_[index_]); + // 1. Start asynchronous DMA transfer to video memory. + writing_[index_] = std::move(frame); + // Lock frame and give pointer ownership to OpenGL. writing_[index_]->write_lock(); - // 1. Copy to page-locked memory - reading_[next_index] = std::move(frame); - - // 4. Output to external buffer + // 3. Output to external buffer. if(output_frame_->read_unlock()) output_.push(output_frame_); - // 3. Draw to framebuffer and start asynchronous DMA transfer to page-locked memory - // Clear framebuffer + // Clear framebuffer. glClear(GL_COLOR_BUFFER_BIT); + + // 2. Draw to framebuffer and start asynchronous DMA transfer + // to page-locked memory. writing_[next_index]->draw(); // Create an output frame - output_frame_ = create_frame(format_desc_.width, format_desc_.height); + output_frame_ = create_output_frame(); - // Read from framebuffer into page-locked memory + // Read from framebuffer into page-locked memory. output_frame_->read_lock(GL_COLOR_ATTACHMENT0_EXT); output_frame_->audio_data() = std::move(writing_[next_index]->audio_data()); - // Return frames to pool + // Return frames to pool. writing_[next_index] = nullptr; } catch(...) @@ -154,11 +131,25 @@ struct gpu_frame_processor::implementation : boost::noncopyable } }); } + + gpu_frame_ptr create_output_frame() + { + gpu_frame_ptr frame; + if(!reading_pool_.try_pop(frame)) + frame = std::make_shared(format_desc_.width, + format_desc_.height); + + return gpu_frame_ptr(frame.get(), [=](gpu_frame*) + { + frame->reset(); + reading_pool_.push(frame); + }); + } gpu_frame_ptr create_frame(size_t width, size_t height) { size_t key = width | (height << 16); - auto& pool = reading_frame_pools_[key]; + auto& pool = writing_pools_[key]; gpu_frame_ptr frame; if(!pool.try_pop(frame)) @@ -175,10 +166,10 @@ struct gpu_frame_processor::implementation : boost::noncopyable { frame->write_unlock(); frame->reset(); - reading_frame_pools_[key].push(frame); + writing_pools_[key].push(frame); }; - return gpu_frame_ptr(frame.get(), [=](gpu_frame*) + return gpu_frame_ptr(frame.get(), [=](gpu_frame*) { executor_.begin_invoke(destructor); }); @@ -189,16 +180,15 @@ struct gpu_frame_processor::implementation : boost::noncopyable output_.pop(frame); } - tbb::concurrent_unordered_map> reading_frame_pools_; - - frame_buffer_ptr fbo_; + typedef tbb::concurrent_bounded_queue gpu_frame_queue; + tbb::concurrent_unordered_map writing_pools_; + gpu_frame_queue reading_pool_; - tbb::concurrent_bounded_queue input_; - tbb::concurrent_bounded_queue output_; + gpu_frame_queue input_; + std::vector writing_; + gpu_frame_queue output_; size_t index_; - std::vector reading_; - std::vector writing_; gpu_frame_ptr output_frame_; frame_format_desc format_desc_; @@ -206,6 +196,9 @@ struct gpu_frame_processor::implementation : boost::noncopyable std::unique_ptr ogl_context_; common::executor executor_; + + GLuint render_texture_; + GLuint fbo_; }; gpu_frame_processor::gpu_frame_processor(const frame_format_desc& format_desc) : impl_(new implementation(format_desc)){} diff --git a/core/producer/transition/transition_producer.cpp b/core/producer/transition/transition_producer.cpp index 0dcc110f3..58ca77579 100644 --- a/core/producer/transition/transition_producer.cpp +++ b/core/producer/transition/transition_producer.cpp @@ -106,7 +106,7 @@ struct transition_producer::implementation : boost::noncopyable src_frame->audio_data()[n] = static_cast((static_cast(src_frame->audio_data()[n])*(256-volume))>>8); float alpha = static_cast(current_frame_)/static_cast(info_.duration); - auto composite = std::make_shared(format_desc_.width, format_desc_.height); + auto composite = std::make_shared(); composite->add(src_frame); composite->add(dest_frame); if(info_.type == transition_type::mix) diff --git a/core/protocol/amcp/AMCPProtocolStrategy.cpp b/core/protocol/amcp/AMCPProtocolStrategy.cpp index 9d38e6b4b..a49b27f8a 100644 --- a/core/protocol/amcp/AMCPProtocolStrategy.cpp +++ b/core/protocol/amcp/AMCPProtocolStrategy.cpp @@ -243,11 +243,19 @@ AMCPCommandPtr AMCPProtocolStrategy::InterpretCommandString(const std::wstring& std::vector split; boost::split(split, str, boost::is_any_of("-")); - int channelIndex = boost::lexical_cast(split[0]) - 1; - + int channelIndex = -1; int layerIndex = -1; - if(split.size() > 1) - layerIndex = boost::lexical_cast(split[1]); + try + { + channelIndex = boost::lexical_cast(split[0]) - 1; + + if(split.size() > 1) + layerIndex = boost::lexical_cast(split[1]); + } + catch(...) + { + goto ParseFinnished; + } renderer::render_device_ptr pChannel = GetChannelSafe(channelIndex, channels_); if(pChannel == 0) { diff --git a/core/renderer/layer.cpp b/core/renderer/layer.cpp index f531b87fd..cd854c164 100644 --- a/core/renderer/layer.cpp +++ b/core/renderer/layer.cpp @@ -35,7 +35,7 @@ struct layer::implementation if(background_ != nullptr) { background_->set_leading_producer(active_); - active_ = background_; + active_ = background_; background_ = nullptr; } @@ -49,13 +49,13 @@ struct layer::implementation void stop() { - active_ = nullptr; + active_ = nullptr; last_frame_ = nullptr; } void clear() { - active_ = nullptr; + active_ = nullptr; background_ = nullptr; last_frame_ = nullptr; } @@ -94,19 +94,12 @@ struct layer::implementation layer::layer() : impl_(new implementation()){} layer::layer(layer&& other) : impl_(std::move(other.impl_)){other.impl_ = nullptr;} -layer::layer(const layer& other) : impl_(new implementation(*other.impl_)) {} layer& layer::operator=(layer&& other) { impl_ = std::move(other.impl_); other.impl_ = nullptr; return *this; } -layer& layer::operator=(const layer& other) -{ - layer temp(other); - impl_.swap(temp.impl_); - return *this; -} void layer::load(const frame_producer_ptr& frame_producer, load_option option){return impl_->load(frame_producer, option);} void layer::play(){impl_->play();} void layer::pause(){impl_->pause();} diff --git a/core/renderer/layer.h b/core/renderer/layer.h index b3f944183..ef25788f2 100644 --- a/core/renderer/layer.h +++ b/core/renderer/layer.h @@ -13,14 +13,14 @@ enum load_option class layer { + layer(const layer& other); + layer& operator=(const layer& other); public: layer(); layer(layer&& other); - layer(const layer& other); layer& operator=(layer&& other); - layer& operator=(const layer& other); - void load(const frame_producer_ptr& pProducer, load_option option = load_option::none); + void load(const frame_producer_ptr& producer, load_option option = load_option::none); void play(); void pause(); void stop(); diff --git a/test/mock/mock_frame_producer.h b/test/mock/mock_frame_producer.h new file mode 100644 index 000000000..ebf9671df --- /dev/null +++ b/test/mock/mock_frame_producer.h @@ -0,0 +1,43 @@ +#pragma once + +#include +#include +#include + +using namespace caspar; +using namespace caspar::core; + +class mock_frame_producer : public frame_producer +{ +public: + mock_frame_producer(bool null = false, bool throws = false) + : null_(null), throws_(throws){} + gpu_frame_ptr get_frame() + { + if(throws_) + BOOST_THROW_EXCEPTION(caspar_exception()); + if(leading_) + return leading_->get_frame(); + if(!null_) + return std::make_shared(0, 0); + return nullptr; + } + std::shared_ptr get_following_producer() const + { return following_; } + void set_leading_producer(const std::shared_ptr& leading) + { leading_ = leading; } + const frame_format_desc& get_frame_format_desc() const + { + static frame_format_desc format; + return format(); + } + void initialize(const frame_factory_ptr& factory) + {} + void set_following_producer(const std::shared_ptr& following) + {following_ = following;} +private: + std::shared_ptr following_; + std::shared_ptr leading_; + bool null_; + bool throws_; +}; \ No newline at end of file diff --git a/test/test.vcxproj b/test/test.vcxproj index 9d5b822ab..23bd65c68 100644 --- a/test/test.vcxproj +++ b/test/test.vcxproj @@ -11,20 +11,11 @@ - - NotUsing - - - NotUsing - NotUsing - - - NotUsing - NotUsing NotUsing + @@ -34,6 +25,9 @@ {79388c20-6499-4bf6-b8b9-d8c33d7d4ddd} + + + {8002D74D-4E89-4BD6-8CE8-0FE4DF14CA5D} Win32Proj diff --git a/test/test.vcxproj.filters b/test/test.vcxproj.filters index b607fb2a2..6b0544b29 100644 --- a/test/test.vcxproj.filters +++ b/test/test.vcxproj.filters @@ -4,25 +4,24 @@ {d4a5c843-0e41-4d98-9056-b7f0de0d49a7} - - {6b116fc0-5f04-4952-a54b-06b208d13b1d} - - + {f7f271e6-1741-4d8e-8903-73f6b6363ef4} + + {420ab80e-66c8-477b-b8c6-d8f4ceb08102} + - - Source\core\renderer - Source - - Source\core\renderer - - - Source\core\renderer + + Source\renderer + + + Source\mock + + \ No newline at end of file -- 2.39.2