X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=core%2Fproducer%2Fframe_producer.cpp;h=de25a488e792be9a12a95192375557188a4634e4;hb=06bdd05d8ec7da072de717d5e1fcb462a1d8ee56;hp=dacf09203e4ecfab346fb92071c1481b843eeb55;hpb=47b4091b5dfa963d7e4f809ce2bad080d39492c0;p=casparcg diff --git a/core/producer/frame_producer.cpp b/core/producer/frame_producer.cpp index dacf09203..de25a488e 100644 --- a/core/producer/frame_producer.cpp +++ b/core/producer/frame_producer.cpp @@ -22,12 +22,12 @@ #include "../StdAfx.h" #include "frame_producer.h" +#include "cg_proxy.h" #include "../frame/draw_frame.h" #include "../frame/frame_transform.h" #include "color/color_producer.h" -#include "draw/freehand_producer.h" #include "separated/separated_producer.h" #include "variable.h" @@ -40,11 +40,10 @@ #include namespace caspar { namespace core { - struct frame_producer_registry::impl { std::vector producer_factories; - std::vector thumbnail_factories; + std::vector thumbnail_producers; spl::shared_ptr help_repo; impl(spl::shared_ptr help_repo) @@ -64,20 +63,22 @@ void frame_producer_registry::register_producer_factory(std::wstring name, const impl_->help_repo->register_item({ L"producer" }, std::move(name), describer); } -void frame_producer_registry::register_thumbnail_producer_factory(const producer_factory_t& factory) +void frame_producer_registry::register_thumbnail_producer(const thumbnail_producer_t& thumbnail_producer) { - impl_->thumbnail_factories.push_back(factory); + impl_->thumbnail_producers.push_back(thumbnail_producer); } frame_producer_dependencies::frame_producer_dependencies( const spl::shared_ptr& frame_factory, const std::vector>& channels, const video_format_desc& format_desc, - const spl::shared_ptr producer_registry) + const spl::shared_ptr producer_registry, + const spl::shared_ptr cg_registry) : frame_factory(frame_factory) , channels(channels) , format_desc(format_desc) , producer_registry(producer_registry) + , cg_registry(cg_registry) { } @@ -104,7 +105,7 @@ struct frame_producer_base::impl frame_number_ = 0; paused_ = false; } - + draw_frame receive() { if(paused_) @@ -128,10 +129,6 @@ struct frame_producer_base::impl { return draw_frame::still(last_frame_); } - draw_frame create_thumbnail_frame() - { - return draw_frame::empty(); - } }; frame_producer_base::frame_producer_base() : impl_(new impl(*this)) @@ -152,12 +149,8 @@ draw_frame frame_producer_base::last_frame() { return impl_->last_frame(); } -draw_frame frame_producer_base::create_thumbnail_frame() -{ - return impl_->create_thumbnail_frame(); -} -std::future frame_producer_base::call(const std::vector&) +std::future frame_producer_base::call(const std::vector&) { CASPAR_THROW_EXCEPTION(not_supported()); } @@ -174,7 +167,7 @@ uint32_t frame_producer_base::frame_number() const variable& frame_producer_base::get_variable(const std::wstring& name) { - CASPAR_THROW_EXCEPTION(caspar_exception() + CASPAR_THROW_EXCEPTION(user_error() << msg_info(L"No variable called " + name + L" found in " + print())); } @@ -185,7 +178,7 @@ const std::vector& frame_producer_base::get_variables() const return empty; } -const spl::shared_ptr& frame_producer::empty() +const spl::shared_ptr& frame_producer::empty() { class empty_frame_producer : public frame_producer { @@ -195,16 +188,15 @@ const spl::shared_ptr& frame_producer::empty() void paused(bool value) override{} uint32_t nb_frames() const override {return 0;} std::wstring print() const override { return L"empty";} - monitor::subject& monitor_output() override {static monitor::subject monitor_subject(""); return monitor_subject;} + monitor::subject& monitor_output() override {static monitor::subject monitor_subject(""); return monitor_subject;} std::wstring name() const override {return L"empty";} uint32_t frame_number() const override {return 0;} - std::future call(const std::vector& params) override{CASPAR_THROW_EXCEPTION(not_supported());} - variable& get_variable(const std::wstring& name) override { CASPAR_THROW_EXCEPTION(not_supported()); } + std::future call(const std::vector& params) override{CASPAR_THROW_EXCEPTION(not_implemented());} + variable& get_variable(const std::wstring& name) override { CASPAR_THROW_EXCEPTION(not_implemented()); } const std::vector& get_variables() const override { static std::vector empty; return empty; } draw_frame last_frame() {return draw_frame::empty();} - draw_frame create_thumbnail_frame() {return draw_frame::empty();} constraints& pixel_constraints() override { static constraints c; return c; } - + boost::property_tree::wptree info() const override { boost::property_tree::wptree info; @@ -217,6 +209,18 @@ const spl::shared_ptr& frame_producer::empty() return producer; } +std::shared_ptr& producer_destroyer() +{ + static auto destroyer = [] + { + auto result = std::make_shared(L"Producer destroyer"); + result->set_capacity(std::numeric_limits::max()); + return result; + }();; + + return destroyer; +} + tbb::atomic& destroy_producers_in_separate_thread() { static tbb::atomic state; @@ -227,13 +231,15 @@ tbb::atomic& destroy_producers_in_separate_thread() void destroy_producers_synchronously() { destroy_producers_in_separate_thread() = false; + // Join destroyer, executing rest of producers in queue synchronously. + producer_destroyer().reset(); } class destroy_producer_proxy : public frame_producer -{ +{ std::shared_ptr producer_; public: - destroy_producer_proxy(spl::shared_ptr&& producer) + destroy_producer_proxy(spl::shared_ptr&& producer) : producer_(std::move(producer)) { destroy_producers_in_separate_thread() = true; @@ -241,32 +247,31 @@ public: virtual ~destroy_producer_proxy() { - static tbb::atomic counter; - static std::once_flag counter_init_once; - std::call_once(counter_init_once, []{ counter = 0; }); - if(producer_ == core::frame_producer::empty() || !destroy_producers_in_separate_thread()) return; - ++counter; - CASPAR_VERIFY(counter < 8); - + auto destroyer = producer_destroyer(); + + if (!destroyer) + return; + + CASPAR_VERIFY(destroyer->size() < 8); + auto producer = new spl::shared_ptr(std::move(producer_)); - boost::thread([=] + + destroyer->begin_invoke([=] { std::unique_ptr> pointer_guard(producer); auto str = (*producer)->print(); try { - ensure_gpf_handler_installed_for_thread(u8(L"Destroyer: " + str).c_str()); - if (!producer->unique()) - CASPAR_LOG(trace) << str << L" Not destroyed on asynchronous destruction thread: " << producer->use_count(); + CASPAR_LOG(debug) << str << L" Not destroyed on asynchronous destruction thread: " << producer->use_count(); else - CASPAR_LOG(trace) << str << L" Destroying on asynchronous destruction thread."; + CASPAR_LOG(debug) << str << L" Destroying on asynchronous destruction thread."; } catch(...){} - + try { pointer_guard.reset(); @@ -276,11 +281,9 @@ public: { CASPAR_LOG_CURRENT_EXCEPTION(); } - - --counter; - }).detach(); + }); } - + draw_frame receive() override {return producer_->receive();} std::wstring print() const override {return producer_->print();} void paused(bool value) override {producer_->paused(value);} @@ -293,8 +296,7 @@ public: void leading_producer(const spl::shared_ptr& producer) override {return producer_->leading_producer(producer);} uint32_t nb_frames() const override {return producer_->nb_frames();} draw_frame last_frame() {return producer_->last_frame();} - draw_frame create_thumbnail_frame() {return producer_->create_thumbnail_frame();} - monitor::subject& monitor_output() override {return producer_->monitor_output();} + monitor::subject& monitor_output() override {return producer_->monitor_output();} bool collides(double x, double y) const override {return producer_->collides(x, y);} void on_interaction(const interaction_event::ptr& event) override {return producer_->on_interaction(event);} constraints& pixel_constraints() override {return producer_->pixel_constraints();} @@ -308,8 +310,8 @@ spl::shared_ptr create_destroy_proxy(spl::shared_ptr do_create_producer(const frame_producer_dependencies& dependencies, const std::vector& params, const std::vector& factories, bool throw_on_fail = false) { if(params.empty()) - CASPAR_THROW_EXCEPTION(invalid_argument() << arg_name_info("params") << arg_value_info("")); - + CASPAR_THROW_EXCEPTION(invalid_argument() << msg_info("params cannot be empty")); + auto producer = frame_producer::empty(); std::any_of(factories.begin(), factories.end(), [&](const producer_factory_t& factory) -> bool { @@ -317,6 +319,10 @@ spl::shared_ptr do_create_producer(const frame_producer_de { producer = factory(dependencies, params); } + catch (user_error&) + { + throw; + } catch(...) { if(throw_on_fail) @@ -330,71 +336,74 @@ spl::shared_ptr do_create_producer(const frame_producer_de if(producer == frame_producer::empty()) producer = create_color_producer(dependencies.frame_factory, params); - if (producer == frame_producer::empty()) - producer = create_freehand_producer(dependencies.frame_factory, params); - if(producer == frame_producer::empty()) return producer; - + return producer; } -spl::shared_ptr frame_producer_registry::create_thumbnail_producer(const frame_producer_dependencies& dependencies, const std::wstring& media_file) const +draw_frame do_create_thumbnail_frame( + const frame_producer_dependencies& dependencies, + const std::wstring& media_file, + const std::vector& thumbnail_producers) { - auto& thumbnail_factories = impl_->thumbnail_factories; + for (auto& thumbnail_producer : thumbnail_producers) + { + auto frame = thumbnail_producer(dependencies, media_file); + + if (frame != draw_frame::empty()) + return frame; + } + + return draw_frame::empty(); +} + +draw_frame frame_producer_registry::create_thumbnail(const frame_producer_dependencies& dependencies, const std::wstring& media_file) const +{ + auto& thumbnail_producers = impl_->thumbnail_producers; std::vector params; params.push_back(media_file); - auto producer = do_create_producer(dependencies, params, thumbnail_factories, true); - auto key_producer = frame_producer::empty(); - - try // to find a key file. - { - auto params_copy = params; - if (params_copy.size() > 0) - { - params_copy[0] += L"_A"; - key_producer = do_create_producer(dependencies, params_copy, thumbnail_factories, true); - if (key_producer == frame_producer::empty()) - { - params_copy[0] += L"LPHA"; - key_producer = do_create_producer(dependencies, params_copy, thumbnail_factories, true); - } - } - } - catch(...){} + auto fill_frame = do_create_thumbnail_frame(dependencies, media_file, thumbnail_producers); + auto key_frame = do_create_thumbnail_frame(dependencies, media_file + L"_A", thumbnail_producers); - if (producer != frame_producer::empty() && key_producer != frame_producer::empty()) - return create_separated_producer(producer, key_producer); - - return producer; + if (key_frame == draw_frame::empty()) + key_frame = do_create_thumbnail_frame(dependencies, media_file + L"_ALPHA", thumbnail_producers); + + if (fill_frame != draw_frame::empty() && key_frame != draw_frame::empty()) + return draw_frame::mask(fill_frame, key_frame); + + return fill_frame; } spl::shared_ptr frame_producer_registry::create_producer(const frame_producer_dependencies& dependencies, const std::vector& params) const -{ +{ auto& producer_factories = impl_->producer_factories; auto producer = do_create_producer(dependencies, params, producer_factories); auto key_producer = frame_producer::empty(); - - try // to find a key file. + + if (!params.empty() && !boost::contains(params.at(0), L"://")) { - auto params_copy = params; - if(params_copy.size() > 0) + try // to find a key file. { - params_copy[0] += L"_A"; - key_producer = do_create_producer(dependencies, params_copy, producer_factories); - if(key_producer == frame_producer::empty()) + auto params_copy = params; + if (params_copy.size() > 0) { - params_copy[0] += L"LPHA"; + params_copy[0] += L"_A"; key_producer = do_create_producer(dependencies, params_copy, producer_factories); + if (key_producer == frame_producer::empty()) + { + params_copy[0] += L"LPHA"; + key_producer = do_create_producer(dependencies, params_copy, producer_factories); + } } } + catch (...) {} } - catch(...){} if(producer != frame_producer::empty() && key_producer != frame_producer::empty()) return create_separated_producer(producer, key_producer); - + if(producer == frame_producer::empty()) { std::wstring str; @@ -415,5 +424,4 @@ spl::shared_ptr frame_producer_registry::create_producer(c std::copy(iterator(iss), iterator(), std::back_inserter(tokens)); return create_producer(dependencies, tokens); } - }}