X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=core%2Fmixer%2Fmixer.cpp;h=4fbf8d8a5a451cde9df712d57f920aaebbd25729;hb=2cfe40e47c46a652eed324a73cd68bc23bbcf4b7;hp=a9ab74701be5dceb65db532cdf9038eed76bc19d;hpb=3eec30c622f808037088e60d9c481d561249a53d;p=casparcg diff --git a/core/mixer/mixer.cpp b/core/mixer/mixer.cpp index a9ab74701..4fbf8d8a5 100644 --- a/core/mixer/mixer.cpp +++ b/core/mixer/mixer.cpp @@ -32,14 +32,15 @@ #include #include #include +#include +#include #include #include #include #include #include -#include -#include +#include #include @@ -92,134 +93,113 @@ struct mixer::implementation : boost::noncopyable audio_mixer audio_mixer_; image_mixer image_mixer_; - typedef std::unordered_map> image_transforms; - typedef std::unordered_map> audio_transforms; + std::unordered_map> transforms_; + std::unordered_map blend_modes_; - boost::fusion::map, - boost::fusion::pair> transforms_; + std::queue>, std::vector>> buffer_; + const size_t buffer_size_; + public: implementation(video_channel_context& video_channel) : channel_(video_channel) , audio_mixer_(channel_.get_format_desc()) , image_mixer_(channel_) + , buffer_size_(env::properties().get("configuration.producers.buffer-depth", 1)) { - CASPAR_LOG(info) << print() << L" Successfully initialized."; + CASPAR_LOG(info) << print() << L" Successfully initialized . Buffer-depth: " << buffer_size_; } safe_ptr execute(const std::map>& frames) { try { - decltype(mix_image(frames)) image; - decltype(mix_audio(frames)) audio; + BOOST_FOREACH(auto& frame, frames) + { + auto blend_it = blend_modes_.find(frame.first); + image_mixer_.begin_layer(blend_it != blend_modes_.end() ? blend_it->second : blend_mode::normal); + + auto frame1 = make_safe(frame.second); + frame1->get_frame_transform() = transforms_[frame.first].fetch_and_tick(1); + + if(channel_.get_format_desc().field_mode != core::field_mode::progressive) + { + auto frame2 = make_safe(frame.second); + frame2->get_frame_transform() = transforms_[frame.first].fetch_and_tick(1); + frame1 = core::basic_frame::interlace(frame1, frame2, channel_.get_format_desc().field_mode); + } + + frame1->accept(audio_mixer_); + frame1->accept(image_mixer_); + + image_mixer_.end_layer(); + } - tbb::parallel_invoke( - [&]{image = mix_image(frames);}, - [&]{audio = mix_audio(frames);}); + auto image = image_mixer_.render(); + auto audio = audio_mixer_.mix(); - return make_safe(channel_.ogl(), channel_.get_format_desc().size, std::move(image), std::move(audio)); + buffer_.push(std::make_pair(std::move(image), audio)); + + if(buffer_.size()-1 < buffer_size_) + return make_safe(); + + auto res = std::move(buffer_.front()); + buffer_.pop(); + + return make_safe(channel_.ogl(), channel_.get_format_desc().size, std::move(res.first.get()), std::move(res.second)); } catch(...) { - channel_.ogl().gc().wait(); - image_mixer_ = image_mixer(channel_); - audio_mixer_ = audio_mixer(channel_.get_format_desc()); - channel_.ogl().gc().wait(); - - CASPAR_LOG_CURRENT_EXCEPTION(); - return make_safe(); - } + CASPAR_LOG(error) << L"[mixer] Error detected."; + throw; + } } - + safe_ptr create_frame(const void* tag, const core::pixel_format_desc& desc) { return image_mixer_.create_frame(tag, desc); } - - void reset_transforms() - { - channel_.execution().invoke([&] - { - boost::fusion::at_key(transforms_).clear(); - boost::fusion::at_key(transforms_).clear(); - }); - } - template - void set_transform(int index, const T& transform, unsigned int mix_duration, const std::wstring& tween) + void set_transform(int index, const frame_transform& transform, unsigned int mix_duration, const std::wstring& tween) { channel_.execution().invoke([&] { - auto& transforms = boost::fusion::at_key(transforms_); - - auto src = transforms[index].fetch(); + auto src = transforms_[index].fetch(); auto dst = transform; - transforms[index] = tweened_transform(src, dst, mix_duration, tween); - }); + transforms_[index] = tweened_transform(src, dst, mix_duration, tween); + }, high_priority); } - template - void apply_transform(int index, const std::function& transform, unsigned int mix_duration, const std::wstring& tween) + void apply_transform(int index, const std::function& transform, unsigned int mix_duration, const std::wstring& tween) { channel_.execution().invoke([&] { - auto& transforms = boost::fusion::at_key(transforms_); - - auto src = transforms[index].fetch(); + auto src = transforms_[index].fetch(); auto dst = transform(src); - transforms[index] = tweened_transform(src, dst, mix_duration, tween); - }); + transforms_[index] = tweened_transform(src, dst, mix_duration, tween); + }, high_priority); } - - std::wstring print() const + + void clear_transforms() { - return L"mixer"; + channel_.execution().invoke([&] + { + transforms_.clear(); + blend_modes_.clear(); + }, high_priority); } - -private: - - boost::unique_future> mix_image(std::map> frames) - { - auto& image_transforms = boost::fusion::at_key(transforms_); - BOOST_FOREACH(auto& frame, frames) + void set_blend_mode(int index, blend_mode::type value) + { + channel_.execution().invoke([&] { - image_mixer_.begin_layer(); - - auto frame1 = make_safe(frame.second); - frame1->get_image_transform() = image_transforms[frame.first].fetch_and_tick(1); - - if(channel_.get_format_desc().mode != core::video_mode::progressive) - { - auto frame2 = make_safe(frame.second); - frame2->get_image_transform() = image_transforms[frame.first].fetch_and_tick(1); - if(frame1->get_image_transform() != frame2->get_image_transform()) - frame1 = core::basic_frame::interlace(frame1, frame2, channel_.get_format_desc().mode); - } - - frame1->accept(image_mixer_); - - image_mixer_.end_layer(); - } - - return image_mixer_.render(); + blend_modes_[index] = value; + }, high_priority); } - std::vector mix_audio(const std::map>& frames) + std::wstring print() const { - auto& audio_transforms = boost::fusion::at_key(transforms_); - - BOOST_FOREACH(auto& frame, frames) - { - const unsigned int num = channel_.get_format_desc().mode == core::video_mode::progressive ? 1 : 2; - - auto frame1 = make_safe(frame.second); - frame1->get_audio_transform() = audio_transforms[frame.first].fetch_and_tick(num); - frame1->accept(audio_mixer_); - } - - return audio_mixer_.mix(); + return L"mixer"; } }; @@ -235,10 +215,8 @@ safe_ptr mixer::create_frame(const void* tag, size_t width, s desc.planes.push_back( core::pixel_format_desc::plane(width, height, 4)); return create_frame(tag, desc); } -void mixer::reset_transforms(){impl_->reset_transforms();} -void mixer::set_image_transform(int index, const core::image_transform& transform, unsigned int mix_duration, const std::wstring& tween){impl_->set_transform(index, transform, mix_duration, tween);} -void mixer::set_audio_transform(int index, const core::audio_transform& transform, unsigned int mix_duration, const std::wstring& tween){impl_->set_transform(index, transform, mix_duration, tween);} -void mixer::apply_image_transform(int index, const std::function& transform, unsigned int mix_duration, const std::wstring& tween){impl_->apply_transform(index, transform, mix_duration, tween);} -void mixer::apply_audio_transform(int index, const std::function& transform, unsigned int mix_duration, const std::wstring& tween){impl_->apply_transform(index, transform, mix_duration, tween);} - +void mixer::set_frame_transform(int index, const core::frame_transform& transform, unsigned int mix_duration, const std::wstring& tween){impl_->set_transform(index, transform, mix_duration, tween);} +void mixer::apply_frame_transform(int index, const std::function& transform, unsigned int mix_duration, const std::wstring& tween){impl_->apply_transform(index, transform, mix_duration, tween);} +void mixer::clear_transforms(){impl_->clear_transforms();} +void mixer::set_blend_mode(int index, blend_mode::type value){impl_->set_blend_mode(index, value);} }} \ No newline at end of file