X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=core%2Fvideo_channel.cpp;h=445d612c9eb836f225af9960ef3deedbd5c5d9fe;hb=f7bdcb2dce2800b66d5ad22c14ca040c2280f4e9;hp=1bdf34e0f1e737d5508139236ade590b582ee439;hpb=28d3e7c5efbf12eb494650aeb31d1a379befff21;p=casparcg diff --git a/core/video_channel.cpp b/core/video_channel.cpp index 1bdf34e0f..445d612c9 100644 --- a/core/video_channel.cpp +++ b/core/video_channel.cpp @@ -31,62 +31,86 @@ #include "frame/frame.h" #include "frame/draw_frame.h" #include "frame/frame_factory.h" +#include "frame/audio_channel_layout.h" #include #include #include #include +#include +#include #include +#include #include #include +#include #include namespace caspar { namespace core { -struct video_channel::impl sealed +struct video_channel::impl final { - monitor::subject monitor_subject_; + spl::shared_ptr monitor_subject_; - const int index_; + const int index_; - mutable tbb::spin_mutex format_desc_mutex_; - core::video_format_desc format_desc_; - - const spl::shared_ptr graph_; + mutable tbb::spin_mutex format_desc_mutex_; + core::video_format_desc format_desc_; + mutable tbb::spin_mutex channel_layout_mutex_; + core::audio_channel_layout channel_layout_; - caspar::core::output output_; - spl::shared_ptr image_mixer_; - caspar::core::mixer mixer_; - caspar::core::stage stage_; + const spl::shared_ptr graph_ = [](int index) + { + core::diagnostics::scoped_call_context save; + core::diagnostics::call_context::for_thread().video_channel = index; + return spl::make_shared(); + }(index_); - executor executor_; + caspar::core::output output_; + std::future output_ready_for_frame_ = make_ready_future(); + spl::shared_ptr image_mixer_; + caspar::core::mixer mixer_; + caspar::core::stage stage_; + + executor executor_ { L"video_channel " + boost::lexical_cast(index_) }; public: - impl(int index, const core::video_format_desc& format_desc, std::unique_ptr image_mixer) - : monitor_subject_("/channel" + boost::lexical_cast(index)) + impl( + int index, + const core::video_format_desc& format_desc, + const core::audio_channel_layout& channel_layout, + std::unique_ptr image_mixer) + : monitor_subject_(spl::make_shared( + "/channel/" + boost::lexical_cast(index))) , index_(index) , format_desc_(format_desc) - , output_(graph_, format_desc, index) + , channel_layout_(channel_layout) + , output_(graph_, format_desc, channel_layout, index) , image_mixer_(std::move(image_mixer)) - , mixer_(graph_, image_mixer_) - , stage_(graph_) - , executor_(L"video_channel") + , mixer_(index, graph_, image_mixer_) + , stage_(index, graph_) { - graph_->set_color("tick-time", diagnostics::color(0.0f, 0.6f, 0.9f)); + graph_->set_color("tick-time", caspar::diagnostics::color(0.0f, 0.6f, 0.9f)); graph_->set_text(print()); - diagnostics::register_graph(graph_); - - output_.monitor_output().link_target(&monitor_subject_); - stage_.monitor_output().link_target(&monitor_subject_); + caspar::diagnostics::register_graph(graph_); + + output_.monitor_output().attach_parent(monitor_subject_); + mixer_.monitor_output().attach_parent(monitor_subject_); + stage_.monitor_output().attach_parent(monitor_subject_); executor_.begin_invoke([=]{tick();}); CASPAR_LOG(info) << print() << " Successfully Initialized."; } - + + ~impl() + { + CASPAR_LOG(info) << print() << " Uninitializing."; + } + core::video_format_desc video_format_desc() const { return lock(format_desc_mutex_, [&] @@ -94,7 +118,7 @@ public: return format_desc_; }); } - + void video_format_desc(const core::video_format_desc& format_desc) { lock(format_desc_mutex_, [&] @@ -104,14 +128,32 @@ public: }); } + core::audio_channel_layout audio_channel_layout() const + { + return lock(channel_layout_mutex_, [&] + { + return channel_layout_; + }); + } + + void audio_channel_layout(const core::audio_channel_layout& channel_layout) + { + lock(channel_layout_mutex_, [&] + { + channel_layout_ = channel_layout; + stage_.clear(); + }); + } + void tick() { try { - auto format_desc = video_format_desc(); + auto format_desc = video_format_desc(); + auto channel_layout = audio_channel_layout(); - boost::timer frame_timer; + caspar::timer frame_timer; // Produce @@ -119,15 +161,17 @@ public: // Mix - auto mixed_frame = mixer_(std::move(stage_frames), format_desc); + auto mixed_frame = mixer_(std::move(stage_frames), format_desc, channel_layout); // Consume - - output_(std::move(mixed_frame), format_desc); + + output_ready_for_frame_.get(); + output_ready_for_frame_ = output_(std::move(mixed_frame), format_desc, channel_layout); - graph_->set_value("tick-time", frame_timer.elapsed()*format_desc.fps*0.5); + auto frame_time = frame_timer.elapsed()*format_desc.fps*0.5; + graph_->set_value("tick-time", frame_time); - monitor_subject_ << monitor::message("/profiler/time") % frame_timer.elapsed() % (1.0/format_desc_.fps) + *monitor_subject_ << monitor::message("/profiler/time") % frame_timer.elapsed() % (1.0/format_desc_.fps) << monitor::message("/format") % format_desc.name; } catch(...) @@ -135,7 +179,8 @@ public: CASPAR_LOG_CURRENT_EXCEPTION(); } - executor_.begin_invoke([=]{tick();}); + if (executor_.is_running()) + executor_.begin_invoke([=]{tick();}); } std::wstring print() const @@ -143,6 +188,11 @@ public: return L"video_channel[" + boost::lexical_cast(index_) + L"|" + video_format_desc().name + L"]"; } + int index() const + { + return index_; + } + boost::property_tree::wptree info() const { boost::property_tree::wptree info; @@ -151,27 +201,52 @@ public: auto mixer_info = mixer_.info(); auto output_info = output_.info(); - info.add(L"video-mode", format_desc_.name); + info.add(L"video-mode", video_format_desc().name); + info.add(L"audio-channel-layout", audio_channel_layout().print()); info.add_child(L"stage", stage_info.get()); info.add_child(L"mixer", mixer_info.get()); info.add_child(L"output", output_info.get()); return info; } + + boost::property_tree::wptree delay_info() const + { + boost::property_tree::wptree info; + + auto stage_info = stage_.delay_info(); + auto mixer_info = mixer_.delay_info(); + auto output_info = output_.delay_info(); + + // TODO: because of std::async deferred timed waiting does not work so for now we have to block + info.add_child(L"layers", stage_info.get()); + info.add_child(L"mix-time", mixer_info.get()); + info.add_child(L"output", output_info.get()); + + return info; + } }; -video_channel::video_channel(int index, const core::video_format_desc& format_desc, std::unique_ptr image_mixer) : impl_(new impl(index, format_desc, std::move(image_mixer))){} +video_channel::video_channel( + int index, + const core::video_format_desc& format_desc, + const core::audio_channel_layout& channel_layout, + std::unique_ptr image_mixer) : impl_(new impl(index, format_desc, channel_layout, std::move(image_mixer))){} video_channel::~video_channel(){} -const stage& video_channel::stage() const { return impl_->stage_;} -stage& video_channel::stage() { return impl_->stage_;} -const mixer& video_channel::mixer() const{ return impl_->mixer_;} -mixer& video_channel::mixer() { return impl_->mixer_;} -const output& video_channel::output() const { return impl_->output_;} -output& video_channel::output() { return impl_->output_;} -spl::shared_ptr video_channel::frame_factory() { return impl_->image_mixer_;} +const stage& video_channel::stage() const { return impl_->stage_;} +stage& video_channel::stage() { return impl_->stage_;} +const mixer& video_channel::mixer() const{ return impl_->mixer_;} +mixer& video_channel::mixer() { return impl_->mixer_;} +const output& video_channel::output() const { return impl_->output_;} +output& video_channel::output() { return impl_->output_;} +spl::shared_ptr video_channel::frame_factory() { return impl_->image_mixer_;} core::video_format_desc video_channel::video_format_desc() const{return impl_->video_format_desc();} void core::video_channel::video_format_desc(const core::video_format_desc& format_desc){impl_->video_format_desc(format_desc);} -boost::property_tree::wptree video_channel::info() const{return impl_->info();} -monitor::source& video_channel::monitor_output(){return impl_->monitor_subject_;} - -}} \ No newline at end of file +core::audio_channel_layout video_channel::audio_channel_layout() const { return impl_->audio_channel_layout(); } +void core::video_channel::audio_channel_layout(const core::audio_channel_layout& channel_layout) { impl_->audio_channel_layout(channel_layout); } +boost::property_tree::wptree video_channel::info() const{return impl_->info();} +boost::property_tree::wptree video_channel::delay_info() const { return impl_->delay_info(); } +int video_channel::index() const { return impl_->index(); } +monitor::subject& video_channel::monitor_output(){ return *impl_->monitor_subject_; } + +}}