X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=core%2Fmixer%2Fmixer.cpp;h=4fbf8d8a5a451cde9df712d57f920aaebbd25729;hb=2cfe40e47c46a652eed324a73cd68bc23bbcf4b7;hp=f866c0b0e3b27e8378134a3178899e19fd635814;hpb=66b170e5505a74cd54088312ced4b4549e67ba87;p=casparcg diff --git a/core/mixer/mixer.cpp b/core/mixer/mixer.cpp index f866c0b0e..4fbf8d8a5 100644 --- a/core/mixer/mixer.cpp +++ b/core/mixer/mixer.cpp @@ -40,8 +40,7 @@ #include #include #include -#include -#include +#include #include @@ -94,12 +93,9 @@ 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_; @@ -116,114 +112,94 @@ public: safe_ptr execute(const std::map>& frames) { - decltype(mix_image(frames)) image; - decltype(mix_audio(frames)) audio; - - tbb::parallel_invoke - ( - [&]{image = mix_image(frames);}, - [&]{audio = mix_audio(frames);} - ); + try + { + 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(); + } + + auto image = image_mixer_.render(); + auto audio = audio_mixer_.mix(); - buffer_.push(std::make_pair(std::move(image), audio)); + buffer_.push(std::make_pair(std::move(image), audio)); - if(buffer_.size()-1 < buffer_size_) - return make_safe(); + 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)); + 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(...) + { + 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"; } }; @@ -239,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