From 5330bed3a2561cb356dbe530c5deb71ade0802e2 Mon Sep 17 00:00:00 2001 From: ronag Date: Sat, 6 Nov 2010 11:33:45 +0000 Subject: [PATCH] 2.0.0.2: - Colorspace transform on GPU. git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.0.0.2@237 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d --- common/common.vcxproj | 1 - common/common.vcxproj.filters | 3 - common/concurrency/function_task.h | 66 ------ common/gl/pixel_buffer_object.cpp | 48 +++- common/gl/pixel_buffer_object.h | 6 +- common/utility/memory.cpp | 6 +- common/utility/memory.h | 1 + .../decklink/DecklinkVideoConsumer.cpp | 2 +- core/consumer/ogl/ogl_consumer.cpp | 2 +- core/core.vcxproj | 5 + core/core.vcxproj.filters | 12 +- core/frame/frame_factory.h | 11 +- core/frame/gpu_composite_frame.cpp | 10 +- core/frame/gpu_composite_frame.h | 4 +- core/frame/gpu_frame.cpp | 76 ++++--- core/frame/gpu_frame.h | 19 +- core/frame/gpu_frame_processor.cpp | 43 +++- core/frame/gpu_frame_processor.h | 6 +- core/frame/gpu_frame_transform.cpp | 211 ++++++++++++++++++ core/frame/gpu_frame_transform.h | 29 +++ core/producer/color/color_producer.cpp | 11 +- .../ffmpeg/video/video_transformer.cpp | 126 +++++++++-- core/producer/flash/flash_producer.cpp | 7 +- core/producer/image/image_producer.cpp | 12 +- core/producer/image/image_scroll_producer.cpp | 10 +- .../transition/transition_producer.cpp | 47 ++-- shell/My Amplifier Results/r000hs/r000hs.ampl | 13 ++ shell/My Amplifier Results/r001hs/r001hs.ampl | 13 ++ shell/My Amplifier Results/r002hs/r002hs.ampl | 13 ++ shell/shell.vcxproj | 3 + shell/shell.vcxproj.filters | 14 ++ .../transition/transition_producer_test.cpp | 2 +- 32 files changed, 630 insertions(+), 202 deletions(-) delete mode 100644 common/concurrency/function_task.h create mode 100644 core/frame/gpu_frame_transform.cpp create mode 100644 core/frame/gpu_frame_transform.h create mode 100644 shell/My Amplifier Results/r000hs/r000hs.ampl create mode 100644 shell/My Amplifier Results/r001hs/r001hs.ampl create mode 100644 shell/My Amplifier Results/r002hs/r002hs.ampl diff --git a/common/common.vcxproj b/common/common.vcxproj index 347e08e8d..cf5c53be6 100644 --- a/common/common.vcxproj +++ b/common/common.vcxproj @@ -92,7 +92,6 @@ - diff --git a/common/common.vcxproj.filters b/common/common.vcxproj.filters index ea6f5f56d..f874e8fff 100644 --- a/common/common.vcxproj.filters +++ b/common/common.vcxproj.filters @@ -87,9 +87,6 @@ Source\concurrency - - Source\concurrency - Source diff --git a/common/concurrency/function_task.h b/common/concurrency/function_task.h deleted file mode 100644 index 8d32f1979..000000000 --- a/common/concurrency/function_task.h +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace caspar { namespace common { namespace function_task { - -namespace detail { - - template - class packaged_task : public tbb::task - { - public: - packaged_task(boost::packaged_task&& task) : task_(std::forward>(task)) {} - - private: - tbb::task* execute() - { - task_(); - return nullptr; - } - - boost::packaged_task task_; - }; - - template - class internal_function_task : public tbb::task - { - public: - internal_function_task(Func&& func) : func_(std::forward(func)) {} - private: - tbb::task* execute() - { - func_(); - return nullptr; - } - - Func func_; - }; -} - -template -void enqueue(Func&& func) -{ - tbb::task::enqueue(*new(tbb::task::allocate_root()) detail::internal_function_task(std::forward(func))); -} - -template -auto begin_invoke(Func&& func) -> boost::unique_future -{ - auto task = boost::packaged_task(std::forward(func)); - auto future = task.get_future(); - tbb::task::enqueue(*new(tbb::task::allocate_root()) detail::packaged_task(boost::move(task))); - return std::move(future); -} - -template -auto invoke(Func&& func) -> decltype(func()) -{ - return function_task::begin_invoke(std::forward(func)).get(); -} - -}; - -}} \ No newline at end of file diff --git a/common/gl/pixel_buffer_object.cpp b/common/gl/pixel_buffer_object.cpp index e3e6b7aa3..5ce272c9f 100644 --- a/common/gl/pixel_buffer_object.cpp +++ b/common/gl/pixel_buffer_object.cpp @@ -10,9 +10,34 @@ namespace caspar { namespace common { namespace gl { struct pixel_buffer_object::implementation : boost::noncopyable { - implementation(size_t width, size_t height) - : width_(width), height_(height), size_(width*height*4), pbo_(0), - texture_(0), writing_(false), reading_(false), mapped_(false){} + implementation(size_t width, size_t height, GLenum format) + : width_(width), height_(height), pbo_(0), format_(format), + texture_(0), writing_(false), reading_(false), mapped_(false) + { + switch(format) + { + case GL_RGBA: + case GL_BGRA: + internal_ = GL_RGBA8; + size_ = width*height*4; + break; + case GL_BGR: + internal_ = GL_RGB8; + size_ = width*height*3; + break; + case GL_LUMINANCE_ALPHA: + internal_ = GL_LUMINANCE_ALPHA; + size_ = width*height*2; + break; + case GL_LUMINANCE: + case GL_ALPHA: + internal_ = GL_LUMINANCE; + size_ = width*height*1; + break; + default: + BOOST_THROW_EXCEPTION(invalid_argument() << msg_info("format")); + } + } ~implementation() { @@ -45,7 +70,7 @@ struct pixel_buffer_object::implementation : boost::noncopyable 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)); - GL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width_, height_, 0, GL_BGRA, + GL(glTexImage2D(GL_TEXTURE_2D, 0, internal_, width_, height_, 0, format_, GL_UNSIGNED_BYTE, NULL)); } GL(glBindTexture(GL_TEXTURE_2D, texture_)); @@ -58,7 +83,7 @@ struct pixel_buffer_object::implementation : boost::noncopyable GL(glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER)); mapped_ = false; bind_texture(); - GL(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width_, height_, GL_BGRA, + GL(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width_, height_, format_, GL_UNSIGNED_BYTE, NULL)); unbind_pbo(GL_PIXEL_UNPACK_BUFFER); writing_ = true; @@ -118,14 +143,17 @@ struct pixel_buffer_object::implementation : boost::noncopyable bool mapped_; bool writing_; bool reading_; + + GLint internal_; + GLenum format_; }; pixel_buffer_object::pixel_buffer_object(){} -pixel_buffer_object::pixel_buffer_object(size_t width, size_t height) - : impl_(new implementation(width, height)){} -void pixel_buffer_object::create(size_t width, size_t height) +pixel_buffer_object::pixel_buffer_object(size_t width, size_t height, GLenum format) + : impl_(new implementation(width, height, format)){} +void pixel_buffer_object::create(size_t width, size_t height, GLenum format) { - impl_.reset(new implementation(width, height)); + impl_.reset(new implementation(width, height, format)); } void pixel_buffer_object::begin_write() { impl_->begin_write();} void* pixel_buffer_object::end_write() {return impl_->end_write();} @@ -133,7 +161,7 @@ void pixel_buffer_object::begin_read() { impl_->begin_read();} void* pixel_buffer_object::end_read(){return impl_->end_read();} void pixel_buffer_object::bind_texture() {impl_->bind_texture();} size_t pixel_buffer_object::width() const {return impl_->width_;} -size_t pixel_buffer_object::heigth() const {return impl_->height_;} +size_t pixel_buffer_object::height() const {return impl_->height_;} size_t pixel_buffer_object::size() const {return impl_->size_;} bool pixel_buffer_object::is_reading() const { return impl_->reading_;} bool pixel_buffer_object::is_writing() const { return impl_->writing_;} diff --git a/common/gl/pixel_buffer_object.h b/common/gl/pixel_buffer_object.h index 858c24456..65b0a6a36 100644 --- a/common/gl/pixel_buffer_object.h +++ b/common/gl/pixel_buffer_object.h @@ -15,8 +15,8 @@ class pixel_buffer_object : boost::noncopyable { public: pixel_buffer_object(); - pixel_buffer_object(size_t width, size_t height); - void create(size_t width, size_t height); + pixel_buffer_object(size_t width, size_t height, GLenum format = GL_BGRA); + void create(size_t width, size_t height, GLenum format = GL_BGRA); ~pixel_buffer_object(){} void begin_write(); @@ -28,7 +28,7 @@ public: void bind_texture(); size_t width() const; - size_t heigth() const; + size_t height() const; size_t size() const; bool is_reading() const; diff --git a/common/utility/memory.cpp b/common/utility/memory.cpp index 7f6d38391..704dc7044 100644 --- a/common/utility/memory.cpp +++ b/common/utility/memory.cpp @@ -9,7 +9,7 @@ namespace caspar { namespace common { -void* memcpy_SSE2(void* dest, const void* source, size_t num) +void* aligned_memcpy(void* dest, const void* source, size_t num) { __asm { @@ -53,14 +53,14 @@ void* memcpy_SSE2(void* dest, const void* source, size_t num) return dest; } -void* aligned_memcpy(void* dest, const void* source, size_t num) +void* aligned_parallel_memcpy(void* dest, const void* source, size_t num) { if(num < 128) return memcpy(dest, source, num); tbb::parallel_for(tbb::blocked_range(0, num/128), [&](const tbb::blocked_range& r) { - memcpy_SSE2(reinterpret_cast(dest) + r.begin()*128, reinterpret_cast(source) + r.begin()*128, r.size()*128); + aligned_memcpy(reinterpret_cast(dest) + r.begin()*128, reinterpret_cast(source) + r.begin()*128, r.size()*128); }, tbb::affinity_partitioner()); return dest; diff --git a/common/utility/memory.h b/common/utility/memory.h index 56ff5a17a..477b59ccf 100644 --- a/common/utility/memory.h +++ b/common/utility/memory.h @@ -3,6 +3,7 @@ namespace caspar { namespace common { void* aligned_memcpy(void* dest, const void* source, size_t size); +void* aligned_parallel_memcpy(void* dest, const void* source, size_t size); void* clear(void* dest, size_t size); }} \ No newline at end of file diff --git a/core/consumer/decklink/DecklinkVideoConsumer.cpp b/core/consumer/decklink/DecklinkVideoConsumer.cpp index 36de5f8e0..24c64f4f1 100644 --- a/core/consumer/decklink/DecklinkVideoConsumer.cpp +++ b/core/consumer/decklink/DecklinkVideoConsumer.cpp @@ -129,7 +129,7 @@ struct DecklinkVideoConsumer::Implementation : public IDeckLinkVideoOutputCallba std::shared_ptr pTempFrame = GetReservedFrame(); if(pTempFrame && frame->size() == pTempFrame->size()) { - common::aligned_memcpy(pTempFrame->data(), frame->data(), pTempFrame->size()); + common::aligned_parallel_memcpy(pTempFrame->data(), frame->data(), pTempFrame->size()); DoRender(pTempFrame); } else diff --git a/core/consumer/ogl/ogl_consumer.cpp b/core/consumer/ogl/ogl_consumer.cpp index f6396ee93..b7658ca4d 100644 --- a/core/consumer/ogl/ogl_consumer.cpp +++ b/core/consumer/ogl/ogl_consumer.cpp @@ -165,7 +165,7 @@ struct consumer::implementation : boost::noncopyable int next_index = (index_ + 1) % 2; auto ptr = pbos_[index_].end_write(); - common::aligned_memcpy(ptr, frame->data(), frame->size()); + common::aligned_parallel_memcpy(ptr, frame->data(), frame->size()); GL(glClear(GL_COLOR_BUFFER_BIT)); pbos_[next_index].bind_texture(); diff --git a/core/core.vcxproj b/core/core.vcxproj index f25dfe256..1938e7df4 100644 --- a/core/core.vcxproj +++ b/core/core.vcxproj @@ -168,6 +168,7 @@ + @@ -246,6 +247,10 @@ ../stdafx.h ../stdafx.h + + ../stdafx.h + ../stdafx.h + ../../StdAfx.h ../../StdAfx.h diff --git a/core/core.vcxproj.filters b/core/core.vcxproj.filters index 7fe4acaf1..aa91590a2 100644 --- a/core/core.vcxproj.filters +++ b/core/core.vcxproj.filters @@ -132,9 +132,6 @@ Source\consumer\decklink\interop - - Source\consumer - Source\producer\color @@ -234,6 +231,12 @@ Source + + Source\frame\gpu + + + Source\consumer + @@ -350,6 +353,9 @@ Source\renderer + + Source\frame\gpu + diff --git a/core/frame/frame_factory.h b/core/frame/frame_factory.h index ee0c55bdf..ba799a339 100644 --- a/core/frame/frame_factory.h +++ b/core/frame/frame_factory.h @@ -4,16 +4,19 @@ #include "frame_format.h" #include +#include namespace caspar { namespace core { - + struct frame_factory { virtual ~frame_factory(){} - virtual gpu_frame_ptr create_frame(size_t width, size_t height) = 0; - gpu_frame_ptr create_frame(const frame_format_desc format_desc) + virtual void release_frames(void* tag) = 0; + virtual gpu_frame_ptr create_frame(size_t width, size_t height, void* tag) = 0; + virtual gpu_frame_ptr create_frame(const planar_frame_dimension& data_size, void* tag) = 0; + gpu_frame_ptr create_frame(const frame_format_desc format_desc, void* tag) { - return create_frame(format_desc.width, format_desc.height); + return create_frame(format_desc.width, format_desc.height, tag); } }; diff --git a/core/frame/gpu_composite_frame.cpp b/core/frame/gpu_composite_frame.cpp index 917fb1f34..9ee2951ea 100644 --- a/core/frame/gpu_composite_frame.cpp +++ b/core/frame/gpu_composite_frame.cpp @@ -37,11 +37,11 @@ struct gpu_composite_frame::implementation : boost::noncopyable boost::range::for_each(frames_, std::mem_fn(&gpu_frame::end_read)); } - void draw() + void draw(const gpu_frame_transform_ptr& transform) { glPushMatrix(); glTranslated(self_->x()*2.0, self_->y()*2.0, 0.0); - boost::range::for_each(frames_, std::mem_fn(&gpu_frame::draw)); + boost::range::for_each(frames_, std::bind(&gpu_frame::draw, std::placeholders::_1, transform)); glPopMatrix(); } @@ -69,7 +69,7 @@ struct gpu_composite_frame::implementation : boost::noncopyable } } - unsigned char* data() + unsigned char* data(size_t index) { BOOST_THROW_EXCEPTION(invalid_operation()); } @@ -87,8 +87,8 @@ void gpu_composite_frame::begin_write(){impl_->begin_write();} void gpu_composite_frame::end_write(){impl_->end_write();} void gpu_composite_frame::begin_read(){impl_->begin_read();} void gpu_composite_frame::end_read(){impl_->end_read();} -void gpu_composite_frame::draw(){impl_->draw();} -unsigned char* gpu_composite_frame::data(){return impl_->data();} +void gpu_composite_frame::draw(const gpu_frame_transform_ptr& transform){impl_->draw(transform);} +unsigned char* gpu_composite_frame::data(size_t index){return impl_->data(index);} 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, diff --git a/core/frame/gpu_composite_frame.h b/core/frame/gpu_composite_frame.h index e9f76a250..9071282bc 100644 --- a/core/frame/gpu_composite_frame.h +++ b/core/frame/gpu_composite_frame.h @@ -19,12 +19,12 @@ public: const gpu_frame_ptr& frame2, video_mode mode); private: - virtual unsigned char* data(); + virtual unsigned char* data(size_t index); virtual void begin_write(); virtual void end_write(); virtual void begin_read(); virtual void end_read(); - virtual void draw(); + virtual void draw(const gpu_frame_transform_ptr& transform); struct implementation; std::shared_ptr impl_; diff --git a/core/frame/gpu_frame.cpp b/core/frame/gpu_frame.cpp index f66b35815..b659a5b3d 100644 --- a/core/frame/gpu_frame.cpp +++ b/core/frame/gpu_frame.cpp @@ -64,40 +64,55 @@ GLubyte lower_pattern[] = { struct gpu_frame::implementation : boost::noncopyable { - implementation(size_t width, size_t height) - : pbo_(width, height), data_(nullptr), width_(width), height_(height), - size_(width*height*4), reading_(false), alpha_(1.0f), - x_(0.0f), y_(0.0f), mode_(video_mode::progressive), - texcoords_(0.0, 1.0, 1.0, 0.0), writing_(false), mapped_(false) - { + implementation(size_t width, size_t height) + : reading_(false), alpha_(1.0f), x_(0.0f), y_(0.0f), mode_(video_mode::progressive), + texcoords_(0.0, 1.0, 1.0, 0.0), writing_(false), mapped_(false), pix_format_(pixel_format::bgra) + { + data_.resize(1, 0); + pbo_.push_back(std::make_shared(width, height, GL_BGRA)); if(width > 0 && height > 0) end_write(); } + + implementation(const planar_frame_dimension& data_size) + : reading_(false), alpha_(1.0f), x_(0.0f), y_(0.0f), mode_(video_mode::progressive), + texcoords_(0.0, 1.0, 1.0, 0.0), writing_(false), mapped_(false), pix_format_(pixel_format::bgra) + { + data_.resize(data_size.size(), 0); + for(size_t n = 0; n < data_size.size() && data_size[n].first > 0 && data_size[n].second > 0; ++n) + pbo_.push_back(std::make_shared(data_size[n].first, data_size[n].second, GL_LUMINANCE)); + end_write(); + } void begin_write() { - data_ = nullptr; - pbo_.begin_write(); + data_ = std::vector(4, 0); + for(size_t n = 0; n < pbo_.size(); ++n) + pbo_[n]->begin_write(); } void end_write() { - data_ = static_cast(pbo_.end_write()); + for(size_t n = 0; n < pbo_.size(); ++n) + data_[n] = static_cast(pbo_[n]->end_write()); } void begin_read() { - data_ = nullptr; - pbo_.begin_read(); + data_ = std::vector(4, 0); + for(size_t n = 0; n < pbo_.size(); ++n) + pbo_[n]->begin_read(); } void end_read() { - data_ = static_cast(pbo_.end_read()); + for(size_t n = 0; n < pbo_.size(); ++n) + data_[n] = static_cast(pbo_[n]->end_read()); } - void draw() + void draw(const gpu_frame_transform_ptr& transform) { + transform->set_pixel_format(pix_format_); glPushMatrix(); glTranslated(x_*2.0, y_*2.0, 0.0); glColor4d(1.0, 1.0, 1.0, alpha_); @@ -109,7 +124,11 @@ struct gpu_frame::implementation : boost::noncopyable else if(mode_ == video_mode::lower) glPolygonStipple(lower_pattern); - pbo_.bind_texture(); + for(size_t n = 0; n < pbo_.size(); ++n) + { + glActiveTexture(GL_TEXTURE0+n); + pbo_[n]->bind_texture(); + } glBegin(GL_QUADS); glTexCoord2d(texcoords_.left, texcoords_.bottom); glVertex2d(-1.0, -1.0); glTexCoord2d(texcoords_.right, texcoords_.bottom); glVertex2d( 1.0, -1.0); @@ -119,11 +138,11 @@ struct gpu_frame::implementation : boost::noncopyable glPopMatrix(); } - unsigned char* data() + unsigned char* data(size_t index) { - if(data_ == nullptr) + if(pbo_.size() < index || data_[index] == nullptr) BOOST_THROW_EXCEPTION(invalid_operation()); - return data_; + return data_[index]; } void reset() @@ -136,12 +155,10 @@ struct gpu_frame::implementation : boost::noncopyable mode_ = video_mode::progressive; } - common::gl::pixel_buffer_object pbo_; + std::vector pbo_; + std::vector data_; + gpu_frame* self_; - unsigned char* data_; - size_t width_; - size_t height_; - size_t size_; bool reading_; bool writing_; @@ -154,20 +171,23 @@ struct gpu_frame::implementation : boost::noncopyable double y_; video_mode mode_; rectangle texcoords_; + pixel_format pix_format_; }; gpu_frame::gpu_frame(size_t width, size_t height) : impl_(new implementation(width, height)){} +gpu_frame::gpu_frame(const planar_frame_dimension& data_size) + : impl_(new implementation(data_size)){} void gpu_frame::begin_write(){impl_->begin_write();} void gpu_frame::end_write(){impl_->end_write();} void gpu_frame::begin_read(){impl_->begin_read();} void gpu_frame::end_read(){impl_->end_read();} -void gpu_frame::draw(){impl_->draw();} -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_;} +void gpu_frame::draw(const gpu_frame_transform_ptr& transform){impl_->draw(transform);} +void gpu_frame::set_pixel_format(pixel_format format) {impl_->pix_format_ = format;} +unsigned char* gpu_frame::data(size_t index){return impl_->data(index);} +size_t gpu_frame::size(size_t index) const { return impl_->pbo_.at(index)->size(); } +size_t gpu_frame::width(size_t index) const { return impl_->pbo_.at(index)->width();} +size_t gpu_frame::height(size_t index) const { return impl_->pbo_.at(index)->height();} 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.h b/core/frame/gpu_frame.h index fffe00c89..6eb42474b 100644 --- a/core/frame/gpu_frame.h +++ b/core/frame/gpu_frame.h @@ -2,7 +2,10 @@ #include "frame_format.h" +#include "gpu_frame_transform.h" + #include +#include #include @@ -12,6 +15,8 @@ namespace caspar { namespace core { +typedef std::array, 4> planar_frame_dimension; + struct rectangle { rectangle(double left, double top, double right, double bottom) @@ -28,12 +33,11 @@ class gpu_frame : boost::noncopyable public: virtual ~gpu_frame(){} - virtual unsigned char* data(); - virtual size_t size() const; - virtual size_t width() const; - virtual size_t height() const; + virtual unsigned char* data(size_t index = 0); + virtual size_t size(size_t index = 0) const; + virtual size_t width(size_t index = 0) const; + virtual size_t height(size_t index = 0) const; - virtual const std::vector& audio_data() const; virtual std::vector& audio_data(); virtual double alpha() const; @@ -47,6 +51,8 @@ public: virtual void mode(video_mode mode); virtual video_mode mode() const; + virtual void set_pixel_format(pixel_format format); + static std::shared_ptr null() { static auto my_null_frame = std::shared_ptr(new gpu_frame(0,0)); @@ -55,6 +61,7 @@ public: protected: gpu_frame(size_t width, size_t height); + gpu_frame(const planar_frame_dimension& data_size); friend class gpu_frame_processor; @@ -62,7 +69,7 @@ protected: virtual void end_write(); virtual void begin_read(); virtual void end_read(); - virtual void draw(); + virtual void draw(const gpu_frame_transform_ptr& transform); virtual void reset(); private: diff --git a/core/frame/gpu_frame_processor.cpp b/core/frame/gpu_frame_processor.cpp index 73183644a..bbc3ec359 100644 --- a/core/frame/gpu_frame_processor.cpp +++ b/core/frame/gpu_frame_processor.cpp @@ -2,6 +2,7 @@ #include "gpu_frame_processor.h" +#include "gpu_frame_transform.h" #include "gpu_frame.h" #include "gpu_composite_frame.h" #include "frame_format.h" @@ -29,6 +30,7 @@ #include #include #include +#include namespace caspar { namespace core { @@ -60,6 +62,8 @@ struct gpu_frame_processor::implementation : boost::noncopyable // Fill pipeline for(int n = 0; n < 2; ++n) composite(std::vector()); + + transform_ = std::make_shared(); }); } @@ -105,7 +109,7 @@ struct gpu_frame_processor::implementation : boost::noncopyable // 2. Draw to framebuffer and start asynchronous DMA transfer // to page-locked memory. - writing_[next_index]->draw(); + writing_[next_index]->draw(transform_); // Create an output frame auto temp_frame = create_output_frame(); @@ -140,9 +144,8 @@ struct gpu_frame_processor::implementation : boost::noncopyable }); } - gpu_frame_ptr create_frame(size_t width, size_t height) + gpu_frame_ptr do_create_frame(size_t key, const std::function& constructor) { - size_t key = width | (height << 16); auto& pool = writing_pools_[key]; gpu_frame_ptr frame; @@ -150,7 +153,7 @@ struct gpu_frame_processor::implementation : boost::noncopyable { frame = executor_.invoke([&] { - return std::shared_ptr(new gpu_frame(width, height)); + return std::shared_ptr(constructor()); }); } @@ -165,12 +168,35 @@ struct gpu_frame_processor::implementation : boost::noncopyable executor_.begin_invoke(destructor); }); } + + gpu_frame_ptr create_frame(size_t width, size_t height, void* tag) + { + size_t key = reinterpret_cast(tag); + return do_create_frame(key, [&] + { + return new gpu_frame(width, height); + }); + } + + gpu_frame_ptr create_frame(const planar_frame_dimension& data_size, void* tag) + { + size_t key = reinterpret_cast(tag); + return do_create_frame(key, [&] + { + return new gpu_frame(data_size); + }); + } void pop(gpu_frame_ptr& frame) { output_.pop(frame); } - + + void release_frames(void* tag) + { + writing_pools_[reinterpret_cast(tag)].clear(); + } + typedef tbb::concurrent_bounded_queue gpu_frame_queue; tbb::concurrent_unordered_map writing_pools_; gpu_frame_queue reading_pool_; @@ -189,11 +215,14 @@ struct gpu_frame_processor::implementation : boost::noncopyable common::executor executor_; common::gl::frame_buffer_object fbo_; + + gpu_frame_transform_ptr transform_; }; gpu_frame_processor::gpu_frame_processor(const frame_format_desc& format_desc) : impl_(new implementation(format_desc)){} void gpu_frame_processor::push(const std::vector& frames){ impl_->composite(frames);} void gpu_frame_processor::pop(gpu_frame_ptr& frame){impl_->pop(frame);} -gpu_frame_ptr gpu_frame_processor::create_frame(size_t width, size_t height){return impl_->create_frame(width, height);} - +gpu_frame_ptr gpu_frame_processor::create_frame(size_t width, size_t height, void* tag){return impl_->create_frame(width, height, tag);} +gpu_frame_ptr gpu_frame_processor::create_frame(const planar_frame_dimension& data_size, void* tag){return impl_->create_frame(data_size, tag);} +void gpu_frame_processor::release_frames(void* tag){impl_->release_frames(tag);} }} \ No newline at end of file diff --git a/core/frame/gpu_frame_processor.h b/core/frame/gpu_frame_processor.h index f9d4d0905..c586eda50 100644 --- a/core/frame/gpu_frame_processor.h +++ b/core/frame/gpu_frame_processor.h @@ -34,8 +34,10 @@ public: void push(const std::vector& frames); void pop(gpu_frame_ptr& frame); - - gpu_frame_ptr create_frame(size_t width, size_t height); + + void release_frames(void* tag); + gpu_frame_ptr create_frame(size_t width, size_t height, void* tag); + gpu_frame_ptr create_frame(const planar_frame_dimension& data_size, void* tag); private: struct implementation; std::shared_ptr impl_; diff --git a/core/frame/gpu_frame_transform.cpp b/core/frame/gpu_frame_transform.cpp new file mode 100644 index 000000000..e92660060 --- /dev/null +++ b/core/frame/gpu_frame_transform.cpp @@ -0,0 +1,211 @@ +#include "../StdAfx.h" + +#include "gpu_frame_transform.h" + +#include "../../common/exception/exceptions.h" +#include "../../common/gl/gl_check.h" + +#include + +#include +#include + +namespace caspar { namespace core { + +class shader_program +{ +public: + shader_program(const std::string& fragment_source_str) + { + try + { + const char* fragment_source = fragment_source_str.c_str(); + static const char* vertex_source = + "void main()" + "{" + "gl_TexCoord[0] = gl_MultiTexCoord0;" + "gl_FrontColor = gl_Color;" + "gl_Position = ftransform();" + "}"; + + program_ = glCreateProgramObjectARB(); + + auto vertex_shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); + auto fragmemt_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); + + GL(glShaderSourceARB(vertex_shader, 1, &vertex_source, NULL)); + GL(glShaderSourceARB(fragmemt_shader, 1, &fragment_source, NULL)); + GL(glCompileShaderARB(vertex_shader)); + GL(glCompileShaderARB(fragmemt_shader)); + + GLint success; + GL(glGetObjectParameterivARB(vertex_shader, GL_OBJECT_COMPILE_STATUS_ARB, &success)); + if (success == GL_FALSE) + { + char log[1024]; + GL(glGetInfoLogARB(vertex_shader, sizeof(log), 0, log)); + GL(glDeleteObjectARB(vertex_shader)); + GL(glDeleteObjectARB(fragmemt_shader)); + GL(glDeleteObjectARB(program_)); + std::stringstream str; + str << "Failed to compile vertex shader:" << std::endl << log << std::endl; + BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(str.str())); + } + GL(glGetObjectParameterivARB(fragmemt_shader, GL_OBJECT_COMPILE_STATUS_ARB, &success)); + if (success == GL_FALSE) + { + char log[1024]; + GL(glGetInfoLogARB(fragmemt_shader, sizeof(log), 0, log)); + GL(glDeleteObjectARB(vertex_shader)); + GL(glDeleteObjectARB(fragmemt_shader)); + GL(glDeleteObjectARB(program_)); + std::stringstream str; + str << "Failed to compile fragment shader:" << std::endl << log << std::endl; + BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(str.str())); + } + + GL(glAttachObjectARB(program_, vertex_shader)); + GL(glAttachObjectARB(program_, fragmemt_shader)); + + GL(glDeleteObjectARB(vertex_shader)); + GL(glDeleteObjectARB(fragmemt_shader)); + + GL(glLinkProgramARB(program_)); + + GL(glGetObjectParameterivARB(program_, GL_OBJECT_LINK_STATUS_ARB, &success)); + if (success == GL_FALSE) + { + char log[1024]; + GL(glGetInfoLogARB(program_, sizeof(log), 0, log)); + CASPAR_LOG(warning) << "Failed to link shader:" << std::endl + << log << std::endl; + GL(glDeleteObjectARB(program_)); + BOOST_THROW_EXCEPTION(caspar_exception()); + } + GL(glUseProgramObjectARB(program_)); + glUniform1i(glGetUniformLocation(program_, "tex0"), 0); + glUniform1i(glGetUniformLocation(program_, "tex1"), 1); + glUniform1i(glGetUniformLocation(program_, "tex2"), 2); + glUniform1i(glGetUniformLocation(program_, "tex3"), 3); + } + catch(...) + { + CASPAR_LOG_CURRENT_EXCEPTION(); + throw; + } + } + + void use() + { + GL(glUseProgramObjectARB(program_)); + } + +private: + GLuint program_; +}; +typedef std::shared_ptr shader_program_ptr; + +struct gpu_frame_transform::implementation +{ + implementation() : current_(pixel_format::invalid_pixel_format) + { + std::string common = + "uniform sampler2D tex0;" + "uniform sampler2D tex1;" + "uniform sampler2D tex2;" + "uniform sampler2D tex3;" + + "vec4 yuva_to_bgra(float y, float u, float v, float a)" + "{" + "vec4 color;" + + "u -= 0.5;" + "v -= 0.5;" + + "color.r = clamp(y + 1.370705 * v, 0.0 , 1.0);" + "color.g = clamp(y - 0.698001 * v - 0.337633 * u, 0.0 , 1.0);" + "color.b = clamp(y + 1.732446 * u, 0.0 , 1.0);" + "color.a = a;" + + " return color;" + "}"; + + shaders_[pixel_format::abgr] = std::make_shared + ( + common + + + "void main()" + "{" + "gl_FragColor = texture2D(tex0, gl_TexCoord[0].st).argb * gl_Color;" + "}" + ); + shaders_[pixel_format::argb] = std::make_shared + ( + common + + + "void main()" + "{" + "gl_FragColor = texture2D(tex0, gl_TexCoord[0].st).grab * gl_Color;" + "}" + ); + shaders_[pixel_format::bgra] = std::make_shared + ( + common + + + "void main()" + "{" + "gl_FragColor = texture2D(tex0, gl_TexCoord[0].st).rgba * gl_Color;" + "}" + ); + shaders_[pixel_format::rgba] = std::make_shared + ( + common + + + "void main()" + "{" + "gl_FragColor = texture2D(tex0, gl_TexCoord[0].st).bgra * gl_Color;" + "}" + ); + shaders_[pixel_format::yuv] = std::make_shared + ( + common + + + "void main()" + "{" + "float y = texture2D(tex0, gl_TexCoord[0].st).r;" + "float u = texture2D(tex1, gl_TexCoord[0].st).r;" + "float v = texture2D(tex2, gl_TexCoord[0].st).r;" + "gl_FragColor = yuva_to_bgra(y, u , v, 1.0) * gl_Color;" + "}" + ); + shaders_[pixel_format::yuva] = std::make_shared + ( + common + + + "void main()" + "{" + "float y = texture2D(tex0, gl_TexCoord[0].st).r;" + "float u = texture2D(tex1, gl_TexCoord[0].st).r;" + "float v = texture2D(tex2, gl_TexCoord[0].st).r;" + "float a = texture2D(tex3, gl_TexCoord[0].st).r;" + "gl_FragColor = yuva_to_bgra(y, u, v, a) * gl_Color;" + "}" + ); + } + + void set_pixel_format(pixel_format format) + { + if(current_ == format) + return; + current_ = format; + shaders_[format]->use(); + } + + pixel_format current_; + std::map shaders_; +}; + +gpu_frame_transform::gpu_frame_transform() : impl_(new implementation()){} +void gpu_frame_transform::set_pixel_format(pixel_format format){impl_->set_pixel_format(format);} + +}} \ No newline at end of file diff --git a/core/frame/gpu_frame_transform.h b/core/frame/gpu_frame_transform.h new file mode 100644 index 000000000..54e998d2e --- /dev/null +++ b/core/frame/gpu_frame_transform.h @@ -0,0 +1,29 @@ +#pragma once + +#include + +enum pixel_format +{ + bgra = 1, + rgba, + argb, + abgr, + yuv, + yuva, + invalid_pixel_format, +}; + +namespace caspar { namespace core { + +class gpu_frame_transform +{ +public: + gpu_frame_transform(); + void set_pixel_format(pixel_format format); +private: + struct implementation; + std::shared_ptr impl_; +}; +typedef std::shared_ptr gpu_frame_transform_ptr; + +}} \ No newline at end of file diff --git a/core/producer/color/color_producer.cpp b/core/producer/color/color_producer.cpp index 58d2fd531..d6a48a9eb 100644 --- a/core/producer/color/color_producer.cpp +++ b/core/producer/color/color_producer.cpp @@ -35,18 +35,27 @@ public: explicit color_producer(unsigned int color_value, const frame_format_desc& format_desc) : color_value_(color_value), format_desc_(format_desc){} + ~color_producer() + { + if(factory_) + factory_->release_frames(this); + } + gpu_frame_ptr get_frame() { return frame_; } + const frame_format_desc& get_frame_format_desc() const { return format_desc_; } void initialize(const frame_factory_ptr& factory) { - frame_ = factory->create_frame(format_desc_); + factory_ = factory; + frame_ = factory->create_frame(format_desc_, this); __stosd(reinterpret_cast(frame_->data()), color_value_, frame_->size() / sizeof(unsigned long)); } + frame_factory_ptr factory_; frame_format_desc format_desc_; gpu_frame_ptr frame_; unsigned int color_value_; diff --git a/core/producer/ffmpeg/video/video_transformer.cpp b/core/producer/ffmpeg/video/video_transformer.cpp index 78bb54961..cfe763453 100644 --- a/core/producer/ffmpeg/video/video_transformer.cpp +++ b/core/producer/ffmpeg/video/video_transformer.cpp @@ -14,6 +14,8 @@ #include #include +#include + #if defined(_MSC_VER) #pragma warning (push) #pragma warning (disable : 4244) @@ -30,38 +32,126 @@ extern "C" namespace caspar { namespace core { namespace ffmpeg{ +pixel_format get_pixel_format(PixelFormat pix_fmt) +{ + switch(pix_fmt) + { + case PIX_FMT_BGRA: return pixel_format::bgra; + case PIX_FMT_ARGB: return pixel_format::argb; + case PIX_FMT_RGBA: return pixel_format::rgba; + case PIX_FMT_ABGR: return pixel_format::abgr; + case PIX_FMT_YUV444P: return pixel_format::yuv; + case PIX_FMT_YUV422P: return pixel_format::yuv; + case PIX_FMT_YUV420P: return pixel_format::yuv; + case PIX_FMT_YUV411P: return pixel_format::yuv; + case PIX_FMT_YUV410P: return pixel_format::yuv; + case PIX_FMT_YUVA420P: return pixel_format::yuva; + default: return pixel_format::invalid_pixel_format; + } +} + struct video_transformer::implementation : boost::noncopyable { + ~implementation() + { + if(factory_) + factory_->release_frames(this); + } + video_packet_ptr execute(const video_packet_ptr video_packet) { assert(video_packet); - size_t width = video_packet->codec_context->width; - size_t height = video_packet->codec_context->height; + int width = video_packet->codec_context->width; + int height = video_packet->codec_context->height; auto pix_fmt = video_packet->codec_context->pix_fmt; + video_packet->decoded_frame; - if(!sws_context_) + switch(pix_fmt) { - double param; - sws_context_.reset(sws_getContext(width, height, pix_fmt, width, height, - PIX_FMT_BGRA, SWS_BILINEAR, nullptr, nullptr, ¶m), sws_freeContext); - } + case PIX_FMT_BGRA: + case PIX_FMT_ARGB: + case PIX_FMT_RGBA: + case PIX_FMT_ABGR: + { + video_packet->frame = factory_->create_frame(width, height, this); + tbb::parallel_for(0, height, 1, [&](int y) + { + common::aligned_memcpy( + video_packet->frame->data()+y*width*4, + video_packet->decoded_frame->data[0] + y*video_packet->decoded_frame->linesize[0], + width*4); + }); + video_packet->frame->set_pixel_format(get_pixel_format(pix_fmt)); + + break; + } + case PIX_FMT_YUV444P: + case PIX_FMT_YUV422P: + case PIX_FMT_YUV420P: + case PIX_FMT_YUV411P: + case PIX_FMT_YUV410P: + case PIX_FMT_YUVA420P: + { + // Get linesizes + AVPicture dummy_pict; + avpicture_fill(&dummy_pict, nullptr, pix_fmt, width, height); + + // Find chroma height + size_t size2 = dummy_pict.data[2] - dummy_pict.data[1]; + size_t h2 = size2/dummy_pict.linesize[1]; - //size_t pic_size = avpicture_get_size(PIX_FMT_YUV411P, width, height); + planar_frame_dimension data_size; + data_size[0] = std::make_pair(dummy_pict.linesize[0], height); + data_size[1] = std::make_pair(dummy_pict.linesize[1], h2); + data_size[2] = std::make_pair(dummy_pict.linesize[2], h2); + data_size[3] = std::make_pair(0, 0); - //size_t pic_size_sqr = static_cast(sqrt(static_cast(pic_size)))/4; - //pic_size_sqr += pic_size_sqr % 2; + if(pix_fmt == PIX_FMT_YUVA420P) + data_size[3] = std::make_pair(dummy_pict.linesize[3], height); - video_packet->frame = factory_->create_frame(width, height); - AVFrame av_frame; - avcodec_get_frame_defaults(&av_frame); - size_t size = avpicture_fill(reinterpret_cast(&av_frame), video_packet->frame->data(), PIX_FMT_BGRA, width, height); + video_packet->frame = factory_->create_frame(data_size, this); + video_packet->frame->set_pixel_format(get_pixel_format(pix_fmt)); + + tbb::parallel_for(0, static_cast(data_size.size()), 1, [&](int n) + { + tbb::parallel_for(0, static_cast(data_size[n].second), 1, [&](int y) + { + memcpy( + video_packet->frame->data(n)+y*dummy_pict.linesize[n], + video_packet->decoded_frame->data[n] + y*video_packet->decoded_frame->linesize[n], + dummy_pict.linesize[n]); + }); + }); + break; + } + default: + { + video_packet->frame = factory_->create_frame(width, height, this); + video_packet->frame->set_pixel_format(pixel_format::bgra); + + AVFrame av_frame; + avcodec_get_frame_defaults(&av_frame); + avpicture_fill(reinterpret_cast(&av_frame), video_packet->frame->data(), PIX_FMT_BGRA, width, height); + + if(!sws_context_) + { + double param; + sws_context_.reset(sws_getContext(width, height, pix_fmt, width, height, PIX_FMT_BGRA, SWS_BILINEAR, nullptr, nullptr, ¶m), sws_freeContext); + } - sws_scale(sws_context_.get(), video_packet->decoded_frame->data, video_packet->decoded_frame->linesize, 0, height, av_frame.data, av_frame.linesize); - + sws_scale(sws_context_.get(), video_packet->decoded_frame->data, video_packet->decoded_frame->linesize, 0, height, av_frame.data, av_frame.linesize); + } + } + if(video_packet->codec->id == CODEC_ID_DVVIDEO) // Move up one field video_packet->frame->translate(0.0f, 1.0/static_cast(video_packet->format_desc.height)); - return video_packet; + return video_packet; + } + + void initialize(const frame_factory_ptr& factory) + { + factory_ = factory; } frame_factory_ptr factory_; @@ -70,5 +160,5 @@ struct video_transformer::implementation : boost::noncopyable video_transformer::video_transformer() : impl_(new implementation()){} video_packet_ptr video_transformer::execute(const video_packet_ptr& video_packet){return impl_->execute(video_packet);} -void video_transformer::initialize(const frame_factory_ptr& factory){impl_->factory_ = factory; } +void video_transformer::initialize(const frame_factory_ptr& factory){impl_->initialize(factory); } }}} \ No newline at end of file diff --git a/core/producer/flash/flash_producer.cpp b/core/producer/flash/flash_producer.cpp index eddbe023f..9b1f114d3 100644 --- a/core/producer/flash/flash_producer.cpp +++ b/core/producer/flash/flash_producer.cpp @@ -33,7 +33,6 @@ #include "../../../common/utility/find_file.h" #include "../../server.h" #include "../../../common/concurrency/executor.h" -#include "../../../common/concurrency/function_task.h" #include "../../../common/utility/memory.h" #include "../../../common/utility/scope_exit.h" @@ -72,6 +71,8 @@ struct flash_producer::implementation ~implementation() { stop(); + if(factory_) + factory_->release_frames(this); } void start(bool force = true) @@ -267,8 +268,8 @@ struct flash_producer::implementation }); } - auto frame = factory_->create_frame(format_desc_); - common::aligned_memcpy(frame->data(), current_frame_->data(), current_frame_->size()); + auto frame = factory_->create_frame(format_desc_, this); + common::aligned_parallel_memcpy(frame->data(), current_frame_->data(), current_frame_->size()); return frame; } diff --git a/core/producer/image/image_producer.cpp b/core/producer/image/image_producer.cpp index 07135b9ae..19013f04e 100644 --- a/core/producer/image/image_producer.cpp +++ b/core/producer/image/image_producer.cpp @@ -19,10 +19,17 @@ struct image_producer : public frame_producer { image_producer(const std::wstring& filename, const frame_format_desc& format_desc) : format_desc_(format_desc), filename_(filename) {} + ~image_producer() + { + if(factory_) + factory_->release_frames(this); + } + gpu_frame_ptr get_frame(){return frame_;} void initialize(const frame_factory_ptr& factory) { + factory_ = factory; auto bitmap = load_image(filename_); if(FreeImage_GetWidth(bitmap.get()) != format_desc_.width || FreeImage_GetHeight(bitmap.get()) == format_desc_.height) { @@ -32,12 +39,13 @@ struct image_producer : public frame_producer } FreeImage_FlipVertical(bitmap.get()); - frame_ = factory->create_frame(format_desc_); - common::aligned_memcpy(frame_->data(), FreeImage_GetBits(bitmap.get()), frame_->size()); + frame_ = factory->create_frame(format_desc_, this); + common::aligned_parallel_memcpy(frame_->data(), FreeImage_GetBits(bitmap.get()), frame_->size()); } const frame_format_desc& get_frame_format_desc() const { return format_desc_; } + frame_factory_ptr factory_; std::wstring filename_; frame_format_desc format_desc_; gpu_frame_ptr frame_; diff --git a/core/producer/image/image_scroll_producer.cpp b/core/producer/image/image_scroll_producer.cpp index ee1243a32..605b9472f 100644 --- a/core/producer/image/image_scroll_producer.cpp +++ b/core/producer/image/image_scroll_producer.cpp @@ -63,6 +63,12 @@ struct image_scroll_producer : public frame_producer speed_ = static_cast(abs(static_cast(speed_) / format_desc.fps)); } + + ~image_scroll_producer() + { + if(factory_) + factory_->release_frames(this); + } void load_and_pad_image(const std::wstring& filename) { @@ -80,12 +86,12 @@ struct image_scroll_producer : public frame_producer unsigned char* pBits = FreeImage_GetBits(pBitmap.get()); for (size_t i = 0; i < height; ++i) - common::aligned_memcpy(&image_.get()[i * image_width_ * 4], &pBits[i* width * 4], width * 4); + common::aligned_parallel_memcpy(&image_.get()[i * image_width_ * 4], &pBits[i* width * 4], width * 4); } gpu_frame_ptr render_frame() { - gpu_frame_ptr frame = factory_->create_frame(format_desc_); + gpu_frame_ptr frame = factory_->create_frame(format_desc_, this); common::clear(frame->data(), frame->size()); const int delta_x = direction_ == direction::Left ? speed_ : -speed_; diff --git a/core/producer/transition/transition_producer.cpp b/core/producer/transition/transition_producer.cpp index 81b86af1d..efacceefd 100644 --- a/core/producer/transition/transition_producer.cpp +++ b/core/producer/transition/transition_producer.cpp @@ -35,8 +35,7 @@ namespace caspar { namespace core { struct transition_producer::implementation : boost::noncopyable { - implementation(const frame_producer_ptr& dest, const transition_info& info, - const frame_format_desc& format_desc) + implementation(const frame_producer_ptr& dest, const transition_info& info, const frame_format_desc& format_desc) : current_frame_(0), info_(info), format_desc_(format_desc), dest_producer_(dest) { if(!dest) @@ -87,7 +86,8 @@ struct transition_producer::implementation : boost::noncopyable CASPAR_LOG(warning) << "Removed renderer from transition."; } - if(frame == nullptr && producer != nullptr && producer->get_following_producer() != nullptr) + if(frame == nullptr && producer != nullptr && + producer->get_following_producer() != nullptr) { auto following = producer->get_following_producer(); following->initialize(factory_); @@ -106,8 +106,7 @@ struct transition_producer::implementation : boost::noncopyable for(size_t n = 0; n < frame->audio_data().size(); ++n) frame->audio_data()[n] = static_cast((static_cast(frame->audio_data()[n])*volume)>>8); } - - + gpu_frame_ptr compose(const gpu_frame_ptr& dest_frame, gpu_frame_ptr src_frame) { if(info_.type == transition_type::cut) @@ -124,24 +123,18 @@ struct transition_producer::implementation : boost::noncopyable [&]{set_volume(dest_frame, volume);}, [&]{set_volume(src_frame, 256-volume);} ); - - auto composite = std::make_shared(); - if(src_frame) - composite->add(src_frame); - composite->add(dest_frame); - - switch(info_.type) - { - case transition_type::mix: - dest_frame->alpha(alpha); - break; - case transition_type::slide: + + if(info_.type == transition_type::mix) + dest_frame->alpha(alpha); + else if(info_.type == transition_type::slide) + { if(info_.direction == transition_direction::from_left) dest_frame->translate(-1.0+alpha, 0.0); else if(info_.direction == transition_direction::from_right) dest_frame->translate(1.0-alpha, 0.0); - break; - case transition_type::push: + } + else if(info_.type == transition_type::push) + { if(info_.direction == transition_direction::from_left) { dest_frame->translate(-1.0+alpha, 0.0); @@ -154,16 +147,6 @@ struct transition_producer::implementation : boost::noncopyable if(src_frame) src_frame->translate(0.0-alpha, 0.0); } - break; - } - - if(info_.type == transition_type::mix) - dest_frame->alpha(alpha); - else if(info_.type == transition_type::slide) - { - } - else if(info_.type == transition_type::push) - { } else if(info_.type == transition_type::wipe) { @@ -178,7 +161,11 @@ struct transition_producer::implementation : boost::noncopyable dest_frame->texcoords(rectangle(1.0-alpha, 1.0, 2.0-alpha, 0.0)); } } - + + auto composite = std::make_shared(); + if(src_frame) + composite->add(src_frame); + composite->add(dest_frame); return composite; } diff --git a/shell/My Amplifier Results/r000hs/r000hs.ampl b/shell/My Amplifier Results/r000hs/r000hs.ampl new file mode 100644 index 000000000..fd613d9b3 --- /dev/null +++ b/shell/My Amplifier Results/r000hs/r000hs.ampl @@ -0,0 +1,13 @@ + + + + 114808 + vaxtestcaspar + windows + Intel® Parallel Amplifier 2011 + 1288973781 + + hs + + + diff --git a/shell/My Amplifier Results/r001hs/r001hs.ampl b/shell/My Amplifier Results/r001hs/r001hs.ampl new file mode 100644 index 000000000..a4578ca99 --- /dev/null +++ b/shell/My Amplifier Results/r001hs/r001hs.ampl @@ -0,0 +1,13 @@ + + + + 114808 + vaxtestcaspar + windows + Intel® Parallel Amplifier 2011 + 1289002710 + + hs + + + diff --git a/shell/My Amplifier Results/r002hs/r002hs.ampl b/shell/My Amplifier Results/r002hs/r002hs.ampl new file mode 100644 index 000000000..7b3969ccc --- /dev/null +++ b/shell/My Amplifier Results/r002hs/r002hs.ampl @@ -0,0 +1,13 @@ + + + + 114808 + vaxtestcaspar + windows + Intel® Parallel Amplifier 2011 + 1289002916 + + hs + + + diff --git a/shell/shell.vcxproj b/shell/shell.vcxproj index 37c152990..bdcff40fc 100644 --- a/shell/shell.vcxproj +++ b/shell/shell.vcxproj @@ -28,6 +28,9 @@ Designer + + + {8C26C94F-8092-4769-8D84-DEA479721C5B} diff --git a/shell/shell.vcxproj.filters b/shell/shell.vcxproj.filters index 9f8c384ba..5abbbd16a 100644 --- a/shell/shell.vcxproj.filters +++ b/shell/shell.vcxproj.filters @@ -5,5 +5,19 @@ + + My Amplifier Results + + + My Amplifier Results + + + My Amplifier Results + + + + + {4df636fc-0183-410c-8d76-2d0e06c29ca3} + \ No newline at end of file diff --git a/test/producer/transition/transition_producer_test.cpp b/test/producer/transition/transition_producer_test.cpp index d80cd06e9..6adc817a7 100644 --- a/test/producer/transition/transition_producer_test.cpp +++ b/test/producer/transition/transition_producer_test.cpp @@ -59,7 +59,7 @@ TEST(transition_producer, null_source_get_frame_cut) ASSERT_TRUE(producer.get_frame() == nullptr); } -TEST(transition_producer, initialize) +TEST(transition_producer, initialize) { auto dest = std::make_shared(); -- 2.39.2