X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=core%2Fproducer%2Fframe_producer.cpp;h=cae3c0bcf2c56c5578e7a00492a562acab5d4d87;hb=c4647c09f2092df9a71635d5866da89dce3a4fef;hp=960fc7f078712057e9a6a4bae787877f66c0bf49;hpb=7375c653d8ffbdd5bd5a4bbd116b00f207b9a4f6;p=casparcg diff --git a/core/producer/frame_producer.cpp b/core/producer/frame_producer.cpp index 960fc7f07..cae3c0bcf 100644 --- a/core/producer/frame_producer.cpp +++ b/core/producer/frame_producer.cpp @@ -22,82 +22,113 @@ #include "frame_producer.h" #include "frame/basic_frame.h" +#include "frame/frame_transform.h" #include "color/color_producer.h" #include "separated/separated_producer.h" #include +#include +#include +#include namespace caspar { namespace core { std::vector g_factories; - -const safe_ptr& frame_producer::empty() // nothrow + +class destroy_producer_proxy : public frame_producer { - struct empty_frame_producer : public frame_producer - { - virtual safe_ptr receive(){return basic_frame::empty();} - virtual void set_frame_factory(const safe_ptr&){} - virtual std::wstring print() const { return L"empty";} - }; - static safe_ptr producer = make_safe(); - return 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."; + + // Hacks to bypass compiler bugs. + auto mov_producer = make_move_on_copy>(std::move(producer_)); + auto empty_producer = frame_producer::empty(); + destroy_context_.begin_invoke([=] + { + //if(!mov_producer.value.unique()) + // CASPAR_LOG(debug) << mov_producer.value->print() << L" Not destroyed on safe asynchronous destruction thread."; + //else + // CASPAR_LOG(debug) << mov_producer.value->print() << L" Destroying on safe asynchronous destruction thread."; + + mov_producer.value = empty_producer; + }); + } -safe_ptr frame_producer::receive_save_last() -{ - auto frame = receive(); - if(frame != core::basic_frame::late()) - { - last_frame_ = make_safe(frame); - last_frame_->get_audio_transform().set_has_audio(false); - } - return frame; -} + virtual safe_ptr receive(int hints) {return producer_->receive(hints);} + virtual safe_ptr last_frame() const {return producer_->last_frame();} + 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);} + virtual int64_t nb_frames() const {return producer_->nb_frames();} +}; -safe_ptr receive(const safe_ptr& producer) +safe_ptr create_destroy_producer_proxy(executor& destroy_context, const safe_ptr& producer) { - return producer->receive_save_last(); + return make_safe(destroy_context, producer); } -safe_ptr receive_and_follow(safe_ptr& producer) -{ - if(producer == frame_producer::empty()) - return basic_frame::eof(); - - auto frame = basic_frame::eof(); - try - { - frame = receive(producer); - } - catch(...) +class last_frame_producer : public frame_producer +{ + const std::wstring print_; + const safe_ptr frame_; + const int64_t nb_frames_; +public: + last_frame_producer(const safe_ptr& producer) + : print_(producer->print()) + , frame_(producer->last_frame() != basic_frame::eof() ? producer->last_frame() : basic_frame::empty()) + , nb_frames_(producer->nb_frames()) { - try - { - // Producer will be removed since frame == basic_frame::eof. - CASPAR_LOG_CURRENT_EXCEPTION(); - CASPAR_LOG(warning) << producer->print() << " Failed to receive frame. Removing producer."; - } - catch(...){} } + + virtual safe_ptr receive(int){return frame_;} + virtual safe_ptr last_frame() const{return frame_;} + virtual std::wstring print() const{return L"dummy[" + print_ + L"]";} + virtual int64_t nb_frames() const {return nb_frames_;} +}; + +struct empty_frame_producer : public frame_producer +{ + virtual safe_ptr receive(int){return basic_frame::empty();} + virtual safe_ptr last_frame() const{return basic_frame::empty();} + virtual void set_frame_factory(const safe_ptr&){} + virtual int64_t nb_frames() const {return 0;} + virtual std::wstring print() const { return L"empty";} +}; +const safe_ptr& frame_producer::empty() // nothrow +{ + static safe_ptr producer = make_safe(); + return producer; +} + +safe_ptr receive_and_follow(safe_ptr& producer, int hints) +{ + auto frame = producer->receive(hints); if(frame == basic_frame::eof()) { CASPAR_LOG(info) << producer->print() << " End Of File."; auto following = producer->get_following_producer(); - following->set_leading_producer(producer); - producer = std::move(following); - - return receive_and_follow(producer); - } - return frame; -} + if(following != frame_producer::empty()) + { + following->set_leading_producer(producer); + producer = std::move(following); + } + else + producer = make_safe(producer); -safe_ptr receive_and_follow_w_last(safe_ptr& producer) -{ - auto frame = receive_and_follow(producer); - if(frame == basic_frame::late()) - frame = producer->last_frame(); + return receive_and_follow(producer, hints); + } return frame; } @@ -127,10 +158,7 @@ safe_ptr do_create_producer(const safe_ptr& if(producer == frame_producer::empty()) producer = create_color_producer(my_frame_factory, params); - - if(producer == frame_producer::empty()) - BOOST_THROW_EXCEPTION(file_not_found() << msg_info("No match found for supplied commands. Check syntax.")); - + return producer; } @@ -147,12 +175,25 @@ safe_ptr create_producer(const safe_ptr& my { params_copy[0] += L"_A"; key_producer = do_create_producer(my_frame_factory, params_copy); + if(key_producer == frame_producer::empty()) + { + params_copy[0] += L"LPHA"; + key_producer = do_create_producer(my_frame_factory, params_copy); + } } } catch(...){} - if(key_producer != frame_producer::empty()) - return create_separated_producer(producer, key_producer); + if(producer != frame_producer::empty() && key_producer != frame_producer::empty()) + producer = create_separated_producer(producer, key_producer); + + if(producer == frame_producer::empty()) + { + std::wstring str; + BOOST_FOREACH(auto& param, params) + str += param + L" "; + BOOST_THROW_EXCEPTION(file_not_found() << msg_info("No match found for supplied commands. Check syntax.") << arg_value_info(narrow(str))); + } return producer; }