X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=core%2Fproducer%2Fstage.cpp;h=9fe30bbd45b917d03a901138cba211c987a16e9f;hb=a486c25d5e6ce0ebe08e9a2d793a447ff3cb797a;hp=5796d0bc96654d953be7926d6b9f13bfa14b359d;hpb=bbddf6decbe5594355f44b745d88557e7a3a1671;p=casparcg diff --git a/core/producer/stage.cpp b/core/producer/stage.cpp index 5796d0bc9..9fe30bbd4 100644 --- a/core/producer/stage.cpp +++ b/core/producer/stage.cpp @@ -22,60 +22,28 @@ #include "stage.h" -#include "../video_channel_context.h" - #include "layer.h" +#include "../video_channel_context.h" + #include #include #include +#include -#include +#include -#include +#include #include +#include namespace caspar { namespace core { - -void destroy_producer(safe_ptr& producer) -{ - if(!producer.unique()) - CASPAR_LOG(warning) << producer->print() << L" Not destroyed on safe asynchronous destruction thread."; - - producer = frame_producer::empty(); -} - -class destroy_producer_proxy : public frame_producer -{ - safe_ptr producer_; - executor& destroy_context_; -public: - destroy_producer_proxy(executor& destroy_context, const safe_ptr& producer) - : producer_(producer) - , destroy_context_(destroy_context){} - - ~destroy_producer_proxy() - { - if(destroy_context_.size() > 4) - CASPAR_LOG(error) << L" Potential destroyer deadlock."; - - destroy_context_.begin_invoke(std::bind(&destroy_producer, std::move(producer_))); - } - - virtual safe_ptr receive() {return core::receive(producer_);} - virtual std::wstring print() const {return producer_->print();} - virtual void param(const std::wstring& str) {producer_->param(str);} - virtual safe_ptr get_following_producer() const {return producer_->get_following_producer();} - virtual void set_leading_producer(const safe_ptr& producer) {producer_->set_leading_producer(producer);} -}; struct stage::implementation : boost::noncopyable { - std::map layers_; - typedef std::map::value_type layer_t; - + std::map layers_; video_channel_context& channel_; public: implementation(video_channel_context& video_channel) @@ -84,35 +52,34 @@ public: } std::map> execute() - { - std::map> frames; - + { try { - // Allocate placeholders. - BOOST_FOREACH(auto layer, layers_) - frames[layer.first] = basic_frame::empty(); + std::map> frames; + + BOOST_FOREACH(auto& layer, layers_) + frames[layer.first] = basic_frame::empty(); - // Render layers - tbb::parallel_for_each(layers_.begin(), layers_.end(), [&](layer_t& layer) + tbb::parallel_for_each(layers_.begin(), layers_.end(), [&](std::map::value_type& layer) { - frames[layer.first] = layer.second.receive(); + frames[layer.first] = layer.second.receive(); }); + + return frames; } catch(...) { - CASPAR_LOG_CURRENT_EXCEPTION(); - } - - return frames; + CASPAR_LOG(error) << L"[stage] Error detected"; + throw; + } } - void load(int index, const safe_ptr& producer, bool preview) + void load(int index, const safe_ptr& producer, bool preview, int auto_play_delta) { channel_.execution().invoke([&] { - layers_[index].load(make_safe(channel_.destruction(), producer), preview); - }); + layers_[index].load(create_destroy_producer_proxy(channel_.destruction(), producer), preview, auto_play_delta); + }, high_priority); } void pause(int index) @@ -120,7 +87,7 @@ public: channel_.execution().invoke([&] { layers_[index].pause(); - }); + }, high_priority); } void play(int index) @@ -128,7 +95,7 @@ public: channel_.execution().invoke([&] { layers_[index].play(); - }); + }, high_priority); } void stop(int index) @@ -136,7 +103,7 @@ public: channel_.execution().invoke([&] { layers_[index].stop(); - }); + }, high_priority); } void clear(int index) @@ -144,7 +111,7 @@ public: channel_.execution().invoke([&] { layers_.erase(index); - }); + }, high_priority); } void clear() @@ -152,15 +119,15 @@ public: channel_.execution().invoke([&] { layers_.clear(); - }); + }, high_priority); } void swap_layer(int index, size_t other_index) { channel_.execution().invoke([&] { - layers_[index].swap(layers_[other_index]); - }); + std::swap(layers_[index], layers_[other_index]); + }, high_priority); } void swap_layer(int index, size_t other_index, stage& other) @@ -169,12 +136,11 @@ public: swap_layer(index, other_index); else { - if(channel_.get_format_desc() != other.impl_->channel_.get_format_desc() || &channel_.ogl() != &other.impl_->channel_.ogl()) - BOOST_THROW_EXCEPTION(not_supported() << msg_info("Cannot swap between incompatible channels.")); - - auto func = [&]{layers_[index].swap(other.impl_->layers_[other_index]);}; - - channel_.execution().invoke([&]{other.impl_->channel_.execution().invoke(func);}); + auto func = [&] + { + std::swap(layers_[index], other.impl_->layers_[other_index]); + }; + channel_.execution().invoke([&]{other.impl_->channel_.execution().invoke(func, high_priority);}, high_priority); } } @@ -183,34 +149,29 @@ public: if(other.impl_.get() == this) return; - if(channel_.get_format_desc() != other.impl_->channel_.get_format_desc() || &channel_.ogl() != &other.impl_->channel_.ogl()) - BOOST_THROW_EXCEPTION(not_supported() << msg_info("Cannot swap between incompatible channels.")); - auto func = [&] { - auto sel_first = [](const std::pair& pair){return pair.first;}; - - std::set indices; - auto inserter = std::inserter(indices, indices.begin()); - - std::transform(layers_.begin(), layers_.end(), inserter, sel_first); - std::transform(other.impl_->layers_.begin(), other.impl_->layers_.end(), inserter, sel_first); + std::swap(layers_, other.impl_->layers_); + }; + channel_.execution().invoke([&]{other.impl_->channel_.execution().invoke(func, high_priority);}, high_priority); + } - BOOST_FOREACH(auto index, indices) - layers_[index].swap(other.impl_->layers_[index]); - }; - - channel_.execution().invoke([&]{other.impl_->channel_.execution().invoke(func);}); + layer_status get_status(int index) + { + return channel_.execution().invoke([&] + { + return layers_[index].status(); + }, high_priority ); } - boost::unique_future> foreground(int index) + safe_ptr foreground(int index) { - return channel_.execution().begin_invoke([=]{return layers_[index].foreground();}); + return channel_.execution().invoke([=]{return layers_[index].foreground();}, high_priority); } - boost::unique_future> background(int index) + safe_ptr background(int index) { - return channel_.execution().begin_invoke([=]{return layers_[index].background();}); + return channel_.execution().invoke([=]{return layers_[index].background();}, high_priority); } std::wstring print() const @@ -222,7 +183,7 @@ public: stage::stage(video_channel_context& video_channel) : impl_(new implementation(video_channel)){} void stage::swap(stage& other){impl_->swap(other);} -void stage::load(int index, const safe_ptr& producer, bool preview){impl_->load(index, producer, preview);} +void stage::load(int index, const safe_ptr& producer, bool preview, int auto_play_delta){impl_->load(index, producer, preview, auto_play_delta);} void stage::pause(int index){impl_->pause(index);} void stage::play(int index){impl_->play(index);} void stage::stop(int index){impl_->stop(index);} @@ -230,7 +191,8 @@ void stage::clear(int index){impl_->clear(index);} void stage::clear(){impl_->clear();} void stage::swap_layer(int index, size_t other_index){impl_->swap_layer(index, other_index);} void stage::swap_layer(int index, size_t other_index, stage& other){impl_->swap_layer(index, other_index, other);} -boost::unique_future> stage::foreground(size_t index) {return impl_->foreground(index);} -boost::unique_future> stage::background(size_t index) {return impl_->background(index);} +layer_status stage::get_status(int index){return impl_->get_status(index);} +safe_ptr stage::foreground(size_t index) {return impl_->foreground(index);} +safe_ptr stage::background(size_t index) {return impl_->background(index);} std::map> stage::execute(){return impl_->execute();} }} \ No newline at end of file