\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
\r
struct transition_producer::implementation : boost::noncopyable\r
{\r
- implementation(const frame_producer_ptr& dest, const transition_info& info, \r
- const frame_format_desc& format_desc) \r
- : current_frame_(0), info_(info), format_desc_(format_desc), dest_producer_(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_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_ = producer;\r
}\r
\r
- gpu_frame_ptr get_frame()\r
+ safe_ptr<draw_frame> receive()\r
{\r
- if(++current_frame_ >= info_.duration)\r
- return nullptr;\r
+ if(current_frame_++ >= info_.duration)\r
+ return draw_frame::eof();\r
\r
- gpu_frame_ptr source;\r
- gpu_frame_ptr dest;\r
+ auto source = draw_frame::empty();\r
+ auto dest = draw_frame::empty();\r
\r
tbb::parallel_invoke\r
(\r
- [&]{dest = get_frame(dest_producer_);},\r
- [&]{source = get_frame(source_producer_);}\r
+ [&]{dest = receive(dest_producer_);},\r
+ [&]{source = receive(source_producer_);}\r
);\r
\r
return compose(dest, source);\r
}\r
\r
- gpu_frame_ptr get_frame(frame_producer_ptr& producer)\r
+ safe_ptr<draw_frame> receive(safe_ptr<frame_producer>& producer)\r
{\r
- if(producer == nullptr)\r
- return nullptr;\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_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
- void set_volume(const gpu_frame_ptr& frame, int volume)\r
- {\r
- if(!frame)\r
- return;\r
-\r
- for(size_t n = 0; n < frame->audio_data().size(); ++n)\r
- frame->audio_data()[n] = static_cast<short>((static_cast<int>(frame->audio_data()[n])*volume)>>8);\r
- }\r
- \r
-\r
- gpu_frame_ptr compose(const gpu_frame_ptr& dest_frame, 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(info_.type == transition_type::cut) \r
- return src_frame;\r
+ if(dest_frame == draw_frame::eof() && src_frame == draw_frame::eof())\r
+ return draw_frame::eof();\r
\r
- if(!dest_frame)\r
- return nullptr;\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
- int volume = static_cast<int>(static_cast<double>(current_frame_)/static_cast<double>(info_.duration)*256.0);\r
- \r
- tbb::parallel_invoke\r
- (\r
- [&]{set_volume(dest_frame, volume);},\r
- [&]{set_volume(src_frame, 256-volume);}\r
- );\r
- \r
- auto composite = std::make_shared<gpu_composite_frame>();\r
- if(src_frame)\r
- composite->add(src_frame);\r
- else\r
- src_frame = std::make_shared<gpu_frame>(0, 0);\r
- composite->add(dest_frame);\r
-\r
- if(info_.type == transition_type::mix)\r
- dest_frame->alpha(alpha); \r
- else if(info_.type == transition_type::slide)\r
- {\r
- if(info_.direction == transition_direction::from_left) \r
- dest_frame->translate(-1.0+alpha, 0.0); \r
- else if(info_.direction == transition_direction::from_right)\r
- dest_frame->translate(1.0-alpha, 0.0); \r
- }\r
- else if(info_.type == transition_type::push)\r
+\r
+ auto my_src_frame = transform_frame(src_frame);\r
+ auto my_dest_frame = transform_frame(dest_frame);\r
+\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
+ 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
- {\r
- dest_frame->translate(-1.0+alpha, 0.0);\r
- src_frame->translate(0.0+alpha, 0.0);\r
- }\r
- else if(info_.direction == transition_direction::from_right)\r
- {\r
- dest_frame->translate(1.0-alpha, 0.0);\r
- src_frame->translate(0.0-alpha, 0.0);\r
- }\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::wipe)\r
+ else if(info_.type == transition::wipe)\r
{\r
- if(info_.direction == transition_direction::from_left) \r
- {\r
- dest_frame->translate(-1.0+alpha, 0.0);\r
- dest_frame->texcoords(rectangle(-1.0+alpha, 1.0, alpha, 0.0));\r
- }\r
- else if(info_.direction == transition_direction::from_right)\r
- {\r
- dest_frame->translate(1.0-alpha, 0.0);\r
- dest_frame->texcoords(rectangle(1.0-alpha, 1.0, 2.0-alpha, 0.0));\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
\r
- return composite;\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_producer_->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_producer_;\r
- frame_producer_ptr dest_producer_;\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
\r
const transition_info info_;\r
- frame_factory_ptr factory_;\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