X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Freroute%2Fproducer%2Freroute_producer.cpp;h=d334a4365e0494e1132503b7c7f9fd53fa25b7ab;hb=a9baf9ba1e7e4b94b5e08385328441de6607ad23;hp=83d4d87b83dc4775ee54374c53c480c2e921dd2e;hpb=b0a6986ce56a18a56e67be266d6d253af7cdcbb5;p=casparcg diff --git a/modules/reroute/producer/reroute_producer.cpp b/modules/reroute/producer/reroute_producer.cpp index 83d4d87b8..d334a4365 100644 --- a/modules/reroute/producer/reroute_producer.cpp +++ b/modules/reroute/producer/reroute_producer.cpp @@ -22,114 +22,95 @@ #include "../stdafx.h" #include "reroute_producer.h" +#include "layer_producer.h" +#include "channel_producer.h" + +#include #include -#include -#include -#include -#include #include -#include - -#include -#include -#include -#include - -#include - -#include +#include +#include -#include -#include -#include -#include -#include -#include - -#include +#include +#include namespace caspar { namespace reroute { - -class reroute_producer : public reactive::observer> - , public core::frame_producer_base + +void describe_producer(core::help_sink& sink, const core::help_repository& repository) { - core::monitor::subject monitor_subject_; - - core::constraints constraints_; - const spl::shared_ptr graph_; - - tbb::concurrent_bounded_queue> input_buffer_; -public: - explicit reroute_producer() - { - graph_->set_color("late-frame", diagnostics::color(0.6f, 0.3f, 0.3f)); - graph_->set_color("dropped-frame", diagnostics::color(0.3f, 0.6f, 0.3f)); - graph_->set_text(print()); - diagnostics::register_graph(graph_); + sink.short_description(L"Reroutes a complete channel or a layer to another layer."); + sink.syntax(L"route://[source_channel:int]{-[source_layer:int]} {FRAMES_DELAY [frames_delay:int]} {[no_auto_deinterlace:NO_AUTO_DEINTERLACE]}"); + sink.para()->text(L"Reroutes the composited video of a channel or the untransformed video of a layer."); + sink.para() + ->text(L"If ")->code(L"source_layer")->text(L" is specified, only the video of the source layer is rerouted. ") + ->text(L"If on the other hand only ")->code(L"source_channel")->text(L" is specified, the video of the complete channel is rerouted."); + sink.para() + ->text(L"An optional additional delay can be specified with the ")->code(L"frames_delay") + ->text(L" parameter."); + sink.para() + ->text(L"For channel routing an optional ")->code(L"no_auto_deinterlace") + ->text(L" parameter can be specified, when performance is more important than good quality output."); + sink.para()->text(L"Examples:"); + sink.example(L">> PLAY 1-10 route://1-11", L"Play the contents of layer 1-11 on layer 1-10 as well."); + sink.example(L">> PLAY 1-10 route://2", L"Play the composited contents of channel 2 on layer 1-10 as well."); + sink.example(L">> PLAY 1-10 route://2 NO_AUTO_DEINTERLACE"); + sink.example( + L">> MIXER 1-10 FILL 0.02 0.01 0.9 0.9\n" + L">> PLAY 1-10 route://1\n" + L">> PLAY 1-9 AMB LOOP", L"Play the composited contents of channel 1 on layer 1-10. Since the source and destination channel is the same, an \"infinity\" effect is created."); + sink.example(L">> PLAY 1-10 route://1-11 FRAMES_DELAY 10", L"Play the contents of layer 1-11 on layer 1-10 as well with an added 10 frames delay."); + sink.para() + ->text(L"Always expect a few frames delay on the routed-to layer in addition to the optionally specified ") + ->code(L"frames_delay")->text(L" parameter."); +} - input_buffer_.set_capacity(1); - } - - // observable +spl::shared_ptr create_producer( + const core::frame_producer_dependencies& dependencies, + const std::vector& params) +{ + static const std::wstring PREFIX = L"route://"; - void on_next(const std::map& frames) + if (params.empty() || + !boost::starts_with(params.at(0), PREFIX) || + boost::ends_with(params.at(0), L"_A") || + boost::ends_with(params.at(0), L"_ALPHA")) { - if(!input_buffer_.try_push(frames)) - graph_->set_tag("dropped-frame"); + return core::frame_producer::empty(); } - // frame_producer - - core::draw_frame receive_impl() override - { - std::map frames; - if(!input_buffer_.try_pop(frames)) - { - graph_->set_tag("late-frame"); - return core::draw_frame::late(); - } - - return boost::accumulate(frames | boost::adaptors::map_values, core::draw_frame::empty(), core::draw_frame::over); - } + auto& url = params.at(0); + auto channel_layer_spec = url.substr(PREFIX.length()); + auto dash = channel_layer_spec.find(L"-"); + bool has_layer_spec = dash != std::wstring::npos; + int channel_id; - core::constraints& pixel_constraints() override - { - return constraints_; - } - - std::wstring print() const override - { - return L"reroute[]"; - } + if (has_layer_spec) + channel_id = boost::lexical_cast(channel_layer_spec.substr(0, dash)); + else + channel_id = boost::lexical_cast(channel_layer_spec); - std::wstring name() const override - { - return L"reroute"; - } + auto found_channel = boost::find_if(dependencies.channels, [=](spl::shared_ptr ch) { return ch->index() == channel_id; }); + + if (found_channel == dependencies.channels.end()) + CASPAR_THROW_EXCEPTION(user_error() << msg_info(L"No channel with id " + boost::lexical_cast(channel_id))); + + auto params2 = params; + params2.erase(params2.begin()); - boost::property_tree::wptree info() const override + auto frames_delay = get_param(L"FRAMES_DELAY", params2, 0); + bool no_auto_deinterlace = contains_param(L"NO_AUTO_DEINTERLACE", params2); + + if (has_layer_spec) { - boost::property_tree::wptree info; - info.add(L"type", L"rerotue-producer"); - return info; + auto layer = boost::lexical_cast(channel_layer_spec.substr(dash + 1)); + + return create_layer_producer(*found_channel, layer, frames_delay, dependencies.format_desc); } - - core::monitor::subject& monitor_output() + else { - return monitor_subject_; + return create_channel_producer(dependencies, *found_channel, frames_delay, no_auto_deinterlace); } -}; - -spl::shared_ptr create_producer(core::video_channel& channel) -{ - auto producer = spl::make_shared(); - - std::weak_ptr>> o = producer; - - //channel.stage().monitor_output().link_target.subscribe(o); - - return producer; } -}} \ No newline at end of file +}}