X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=core%2Fproducer%2Fframe_producer.cpp;h=cae3c0bcf2c56c5578e7a00492a562acab5d4d87;hb=2cfe40e47c46a652eed324a73cd68bc23bbcf4b7;hp=d1ffab291489ec2d657d52cd260eca0aae5069c1;hpb=2f5ecd52bbf1aa3615a645ccd358fd212640ef5c;p=casparcg diff --git a/core/producer/frame_producer.cpp b/core/producer/frame_producer.cpp index d1ffab291..cae3c0bcf 100644 --- a/core/producer/frame_producer.cpp +++ b/core/producer/frame_producer.cpp @@ -22,56 +22,112 @@ #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; + +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."; + + // 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; + }); + } -const safe_ptr& frame_producer::empty() // nothrow + 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 create_destroy_producer_proxy(executor& destroy_context, const safe_ptr& producer) +{ + return make_safe(destroy_context, producer); +} + +class last_frame_producer : public frame_producer { - struct empty_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()) { - virtual safe_ptr receive(){return basic_frame::empty();} - virtual void set_frame_factory(const safe_ptr&){} - virtual std::wstring print() const { return L"empty";} - }; + } + + 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) +safe_ptr receive_and_follow(safe_ptr& producer, int hints) { - if(producer == frame_producer::empty()) - return basic_frame::eof(); - - auto frame = basic_frame::eof(); - try - { - frame = producer->receive(); - } - catch(...) - { - 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(...){} - } - + 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); + if(following != frame_producer::empty()) + { + following->set_leading_producer(producer); + producer = std::move(following); + } + else + producer = make_safe(producer); - return receive_and_follow(producer); + return receive_and_follow(producer, hints); } return frame; } @@ -102,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; } @@ -122,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; }