]> git.sesse.net Git - casparcg/blobdiff - core/producer/transition/transition_producer.cpp
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches...
[casparcg] / core / producer / transition / transition_producer.cpp
index 58ca77579137913e952178600d90a5387397ed8b..8951293399a93e87561e8b381e3746223b874c62 100644 (file)
 \r
 #include "transition_producer.h"\r
 \r
-#include "../../frame/frame_format.h"\r
-#include "../../frame/gpu_frame.h"\r
-#include "../../frame/gpu_composite_frame.h"\r
-#include "../../frame/frame_factory.h"\r
+#include "../../format/video_format.h"\r
+#include "../../processor/draw_frame.h"\r
+#include "../../processor/composite_frame.h"\r
+#include "../../processor/transform_frame.h"\r
+#include "../../processor/frame_processor_device.h"\r
 \r
-#include "../../../common/utility/memory.h"\r
-#include "../../renderer/render_device.h"\r
+#include "../../producer/frame_producer_device.h"\r
 \r
 #include <boost/range/algorithm/copy.hpp>\r
 \r
@@ -35,132 +35,136 @@ namespace caspar { namespace core {
 \r
 struct transition_producer::implementation : boost::noncopyable\r
 {\r
-       implementation(const frame_producer_ptr& dest, const transition_info& info, const frame_format_desc& format_desc) \r
-               : current_frame_(0), info_(info), format_desc_(format_desc), dest_(dest)\r
-       {\r
-               if(!dest)\r
-                       BOOST_THROW_EXCEPTION(null_argument() << arg_name_info("dest"));\r
-       }\r
+       implementation(const safe_ptr<frame_producer>& dest, const transition_info& info) : current_frame_(0), info_(info), \r
+               dest_producer_(dest), source_producer_(frame_producer::empty())\r
+       {}\r
                \r
-       frame_producer_ptr get_following_producer() const\r
+       safe_ptr<frame_producer> get_following_producer() const\r
        {\r
-               return dest_;\r
+               return dest_producer_;\r
        }\r
        \r
-       void set_leading_producer(const frame_producer_ptr& producer)\r
+       void set_leading_producer(const safe_ptr<frame_producer>& producer)\r
        {\r
-               source_ = producer;\r
+               source_producer_ = producer;\r
        }\r
                \r
-       gpu_frame_ptr get_frame()\r
+       safe_ptr<draw_frame> receive()\r
        {\r
-               return ++current_frame_ >= info_.duration ? nullptr : compose(get_producer_frame(dest_), get_producer_frame(source_));\r
+               if(current_frame_++ >= info_.duration)\r
+                       return draw_frame::eof();\r
+\r
+               auto source = draw_frame::empty();\r
+               auto dest = draw_frame::empty();\r
+\r
+               tbb::parallel_invoke\r
+               (\r
+                       [&]{dest   = receive(dest_producer_);},\r
+                       [&]{source = receive(source_producer_);}\r
+               );\r
+\r
+               return compose(dest, source);\r
        }\r
 \r
-       gpu_frame_ptr get_producer_frame(frame_producer_ptr& producer)\r
+       safe_ptr<draw_frame> receive(safe_ptr<frame_producer>& producer)\r
        {\r
-               if(producer == nullptr)\r
-               {       \r
-                       auto frame = factory_->create_frame(format_desc_);\r
-                       common::clear(frame->data(), frame->size());\r
-                       return frame;\r
-               }\r
+               if(producer == frame_producer::empty())\r
+                       return draw_frame::eof();\r
 \r
-               gpu_frame_ptr frame;\r
+               auto frame = draw_frame::eof();\r
                try\r
                {\r
-                       frame = producer->get_frame();\r
+                       frame = producer->receive();\r
                }\r
                catch(...)\r
                {\r
                        CASPAR_LOG_CURRENT_EXCEPTION();\r
-                       producer = nullptr;\r
-                       CASPAR_LOG(warning) << "Removed renderer from transition.";\r
+                       CASPAR_LOG(warning) << "Failed to receive frame. Removed producer from transition.";\r
                }\r
 \r
-               if(frame == nullptr && producer != nullptr && producer->get_following_producer() != nullptr)\r
+               if(frame == draw_frame::eof())\r
                {\r
-                       auto following = producer->get_following_producer();\r
-                       following->initialize(factory_);\r
-                       following->set_leading_producer(producer);\r
-                       producer = following;\r
-                       return get_producer_frame(producer);\r
+                       try\r
+                       {\r
+                               auto following = producer->get_following_producer();\r
+                               following->initialize(safe_ptr<frame_processor_device>(frame_processor_));\r
+                               following->set_leading_producer(producer);\r
+                               producer = std::move(following);\r
+                       }\r
+                       catch(...)\r
+                       {\r
+                               CASPAR_LOG_CURRENT_EXCEPTION();\r
+                               CASPAR_LOG(warning) << "Failed to initialize following producer.";\r
+                       }\r
+\r
+                       return receive(producer);\r
                }\r
                return frame;\r
        }\r
-                       \r
-       gpu_frame_ptr compose(const gpu_frame_ptr& dest_frame, const gpu_frame_ptr& src_frame) \r
+                                       \r
+       safe_ptr<draw_frame> compose(const safe_ptr<draw_frame>& dest_frame, const safe_ptr<draw_frame>& src_frame) \r
        {       \r
-               if(!src_frame)\r
-                       return dest_frame;\r
+               if(dest_frame == draw_frame::eof() && src_frame == draw_frame::eof())\r
+                       return draw_frame::eof();\r
+\r
+               if(info_.type == transition::cut)               \r
+                       return src_frame != draw_frame::eof() ? src_frame : draw_frame::empty();\r
+                                                                               \r
+               double alpha = static_cast<double>(current_frame_)/static_cast<double>(info_.duration);\r
+\r
+               auto my_src_frame = transform_frame(src_frame);\r
+               auto my_dest_frame = transform_frame(dest_frame);\r
 \r
-               if(info_.type == transition_type::cut || !dest_frame)           \r
-                       return src_frame;\r
+               my_src_frame.audio_volume(1.0-alpha);\r
+               my_dest_frame.audio_volume(alpha);\r
+\r
+               double dir = info_.direction == transition_direction::from_left ? 1.0 : -1.0;           \r
                \r
-               int volume = static_cast<int>(static_cast<double>(current_frame_)/static_cast<double>(info_.duration)*256.0);\r
-                               \r
-               for(size_t n = 0; n < dest_frame->audio_data().size(); ++n)\r
-                       dest_frame->audio_data()[n] = static_cast<short>((static_cast<int>(dest_frame->audio_data()[n])*volume)>>8);\r
-\r
-               for(size_t n = 0; n < src_frame->audio_data().size(); ++n)\r
-                       src_frame->audio_data()[n] = static_cast<short>((static_cast<int>(src_frame->audio_data()[n])*(256-volume))>>8);\r
-                               \r
-               float alpha = static_cast<float>(current_frame_)/static_cast<float>(info_.duration);\r
-               auto composite = std::make_shared<gpu_composite_frame>();\r
-               composite->add(src_frame);\r
-               composite->add(dest_frame);\r
-               if(info_.type == transition_type::mix)\r
-               {\r
-                       src_frame->alpha(1.0f-alpha);\r
-                       dest_frame->alpha(alpha);\r
-               }\r
-               else if(info_.type == transition_type::slide)\r
+               if(info_.type == transition::mix)\r
+                       my_dest_frame.alpha(alpha);             \r
+               else if(info_.type == transition::slide)                        \r
+                       my_dest_frame.translate((-1.0+alpha)*dir, 0.0);                 \r
+               else if(info_.type == transition::push)\r
                {\r
-                       if(info_.direction == transition_direction::from_left)                  \r
-                               dest_frame->translate(-1.0f+alpha, 0.0f);                       \r
-                       else if(info_.direction == transition_direction::from_right)\r
-                               dest_frame->translate(1.0f-alpha, 0.0f);                        \r
+                       my_dest_frame.translate((-1.0+alpha)*dir, 0.0);\r
+                       my_src_frame.translate((0.0+alpha)*dir, 0.0);\r
                }\r
-               else if(info_.type == transition_type::push)\r
+               else if(info_.type == transition::wipe)\r
                {\r
-                       if(info_.direction == transition_direction::from_left)          \r
-                       {\r
-                               dest_frame->translate(-1.0f+alpha, 0.0f);\r
-                               src_frame->translate(0.0f+alpha, 0.0f);\r
-                       }\r
-                       else if(info_.direction == transition_direction::from_right)\r
-                       {\r
-                               dest_frame->translate(1.0f-alpha, 0.0f);\r
-                               src_frame->translate(0.0f-alpha, 0.0f);\r
-                       }\r
+                       my_dest_frame.translate((-1.0+alpha)*dir, 0.0);                 \r
+                       my_dest_frame.texcoord((-1.0+alpha)*dir, 0.0, 0.0-(1.0-alpha)*dir, 0.0);                                \r
                }\r
-               return composite;\r
+\r
+               return composite_frame(std::move(my_src_frame), std::move(my_dest_frame));\r
        }\r
                \r
-       void initialize(const frame_factory_ptr& factory)\r
+       void initialize(const safe_ptr<frame_processor_device>& frame_processor)\r
        {\r
-               dest_->initialize(factory);\r
-               factory_ = factory;\r
+               dest_producer_->initialize(frame_processor);\r
+               frame_processor_ = frame_processor;\r
        }\r
 \r
-       const frame_format_desc format_desc_;\r
-\r
-       frame_producer_ptr              source_;\r
-       frame_producer_ptr              dest_;\r
+       std::wstring print() const\r
+       {\r
+               return L"transition_producer. dest: " + (dest_producer_->print()) + L" src: " + (source_producer_->print());\r
+       }\r
+       \r
+       safe_ptr<frame_producer>        source_producer_;\r
+       safe_ptr<frame_producer>        dest_producer_;\r
        \r
-       unsigned short                  current_frame_;\r
+       unsigned short                          current_frame_;\r
        \r
-       const transition_info   info_;\r
-       frame_factory_ptr               factory_;\r
+       const transition_info           info_;\r
+       std::shared_ptr<frame_processor_device> frame_processor_;\r
 };\r
 \r
-transition_producer::transition_producer(const frame_producer_ptr& dest, const transition_info& info, const frame_format_desc& format_desc) \r
-       : impl_(new implementation(dest, info, format_desc)){}\r
-gpu_frame_ptr transition_producer::get_frame(){return impl_->get_frame();}\r
-frame_producer_ptr transition_producer::get_following_producer() const{return impl_->get_following_producer();}\r
-void transition_producer::set_leading_producer(const frame_producer_ptr& producer) { impl_->set_leading_producer(producer); }\r
-const frame_format_desc& transition_producer::get_frame_format_desc() const { return impl_->format_desc_; } \r
-void transition_producer::initialize(const frame_factory_ptr& factory) { impl_->initialize(factory);}\r
+transition_producer::transition_producer(transition_producer&& other) : impl_(std::move(other.impl_)){}\r
+transition_producer::transition_producer(const safe_ptr<frame_producer>& dest, const transition_info& info) : impl_(new implementation(dest, info)){}\r
+safe_ptr<draw_frame> transition_producer::receive(){return impl_->receive();}\r
+safe_ptr<frame_producer> transition_producer::get_following_producer() const{return impl_->get_following_producer();}\r
+void transition_producer::set_leading_producer(const safe_ptr<frame_producer>& producer) { impl_->set_leading_producer(producer); }\r
+void transition_producer::initialize(const safe_ptr<frame_processor_device>& frame_processor) { impl_->initialize(frame_processor);}\r
+std::wstring transition_producer::print() const { return impl_->print();}\r
 \r
 }}\r
 \r