From 2f549904ed6da11061fa914fc99f0e0acdd90357 Mon Sep 17 00:00:00 2001 From: Ronag Date: Sun, 21 Aug 2011 13:45:03 +0000 Subject: [PATCH] 2.0. mixer: Refactored transforms, merged image and audio transform. git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.0.0.2@1247 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d --- core/core.vcxproj | 11 +- core/core.vcxproj.filters | 18 +- core/mixer/audio/audio_mixer.cpp | 125 ++++++---- core/mixer/image/image_kernel.cpp | 58 +++-- core/mixer/image/image_kernel.h | 4 +- core/mixer/image/image_mixer.cpp | 24 +- core/mixer/mixer.cpp | 141 ++++------- core/mixer/mixer.h | 12 +- core/producer/frame/audio_transform.cpp | 75 ------ core/producer/frame/audio_transform.h | 56 ----- core/producer/frame/basic_frame.cpp | 30 +-- core/producer/frame/basic_frame.h | 14 +- core/producer/frame/frame_transform.cpp | 129 ++++++++++ core/producer/frame/frame_transform.h | 80 ++++++ core/producer/frame/image_transform.cpp | 234 ------------------ core/producer/frame/image_transform.h | 113 --------- core/producer/frame_producer.cpp | 2 +- .../transition/transition_producer.cpp | 43 ++-- core/video_format.h | 2 +- modules/decklink/interop/DeckLinkAPI_h.h | 2 +- modules/decklink/interop/DeckLinkAPI_i.c | 2 +- .../decklink/producer/decklink_producer.cpp | 6 +- modules/ffmpeg/producer/frame_muxer.cpp | 16 +- modules/ffmpeg/producer/util.cpp | 2 +- .../ffmpeg/producer/video/video_decoder.cpp | 2 +- modules/flash/producer/flash_producer.cpp | 2 +- .../image/producer/image_scroll_producer.cpp | 13 +- protocol/amcp/AMCPCommandsImpl.cpp | 107 ++++---- protocol/cii/CIIProtocolStrategy.cpp | 2 +- shell/casparcg.config | 1 + 30 files changed, 521 insertions(+), 805 deletions(-) delete mode 100644 core/producer/frame/audio_transform.cpp delete mode 100644 core/producer/frame/audio_transform.h create mode 100644 core/producer/frame/frame_transform.cpp create mode 100644 core/producer/frame/frame_transform.h delete mode 100644 core/producer/frame/image_transform.cpp delete mode 100644 core/producer/frame/image_transform.h diff --git a/core/core.vcxproj b/core/core.vcxproj index 64d8785a9..7d45ded8e 100644 --- a/core/core.vcxproj +++ b/core/core.vcxproj @@ -266,11 +266,10 @@ - - + @@ -383,19 +382,13 @@ ../../StdAfx.h ../../StdAfx.h - - ../../StdAfx.h - ../../StdAfx.h - ../../StdAfx.h - ../../StdAfx.h - ../../StdAfx.h ../../StdAfx.h ../../StdAfx.h ../../StdAfx.h - + ../../StdAfx.h ../../StdAfx.h ../../StdAfx.h diff --git a/core/core.vcxproj.filters b/core/core.vcxproj.filters index 24ab83665..5103014d7 100644 --- a/core/core.vcxproj.filters +++ b/core/core.vcxproj.filters @@ -51,15 +51,9 @@ source\producer - - source\producer\frame - source\producer\frame - - source\producer\frame - source\producer\frame @@ -130,6 +124,9 @@ source\mixer\image + + source\producer\frame + @@ -150,12 +147,6 @@ source\producer\frame - - source\producer\frame - - - source\producer\frame - source\mixer\image @@ -214,5 +205,8 @@ source\mixer\image + + source\producer\frame + \ No newline at end of file diff --git a/core/mixer/audio/audio_mixer.cpp b/core/mixer/audio/audio_mixer.cpp index cea17e4a1..a241ad397 100644 --- a/core/mixer/audio/audio_mixer.cpp +++ b/core/mixer/audio/audio_mixer.cpp @@ -22,7 +22,7 @@ #include "audio_mixer.h" #include -#include +#include #include @@ -30,79 +30,59 @@ #include namespace caspar { namespace core { + +struct audio_item +{ + const void* tag; + frame_transform transform; + std::vector audio_data; +}; struct audio_mixer::implementation { - std::deque> audio_data_; - std::stack transform_stack_; + std::stack transform_stack_; - std::map prev_audio_transforms_; - std::map next_audio_transforms_; + std::map prev_frame_transforms_; + std::map next_frame_transforms_; const core::video_format_desc format_desc_; + std::vector items; + public: implementation(const core::video_format_desc& format_desc) : format_desc_(format_desc) { - transform_stack_.push(core::audio_transform()); - audio_data_.push_back(std::vector()); // One frame delay + transform_stack_.push(core::frame_transform()); } void begin(core::basic_frame& frame) { - transform_stack_.push(transform_stack_.top()*frame.get_audio_transform()); + transform_stack_.push(transform_stack_.top()*frame.get_frame_transform()); } void visit(const core::write_frame& frame) { - if(!transform_stack_.top().get_has_audio() || frame.audio_data().empty()) + // We only care about the last field. + if(format_desc_.field_mode == field_mode::upper && transform_stack_.top().field_mode == field_mode::upper) return; - const auto& audio_data = frame.audio_data(); - const auto tag = frame.tag(); // Get the identifier for the audio-stream. - - const auto next = transform_stack_.top(); - auto prev = next; - - const auto it = prev_audio_transforms_.find(tag); - if(it != prev_audio_transforms_.end()) - prev = it->second; - - next_audio_transforms_[tag] = next; // Store all active tags, inactive tags will be removed in end_pass. - - if(next.get_volume() < 0.001 && prev.get_volume() < 0.001) + if(format_desc_.field_mode == field_mode::lower && transform_stack_.top().field_mode == field_mode::lower) return; - - static const int BASE = 1<<15; - - const auto next_volume = static_cast(next.get_volume()*BASE); - const auto prev_volume = static_cast(prev.get_volume()*BASE); - - const int n_samples = audio_data_.back().size(); - - const auto in_size = static_cast(audio_data.size()); - CASPAR_VERIFY(in_size == 0 || in_size == audio_data_.back().size()); - if(in_size > audio_data_.back().size()) + // Skip empty audio. + if(transform_stack_.top().volume < 0.002 || frame.audio_data().empty()) return; - tbb::parallel_for - ( - tbb::blocked_range(0, audio_data.size()), - [&](const tbb::blocked_range& r) - { - for(size_t n = r.begin(); n < r.end(); ++n) - { - const int sample_volume = (prev_volume - (prev_volume * n)/n_samples) + (next_volume * n)/n_samples; - const int sample = (static_cast(audio_data[n])*sample_volume)/BASE; - audio_data_.back()[n] = static_cast((static_cast(audio_data_.back()[n]) + sample) & 0xFFFF); - } - } - ); + audio_item item; + item.tag = frame.tag(); + item.transform = transform_stack_.top(); + item.audio_data = std::vector(frame.audio_data().begin(), frame.audio_data().end()); + + items.push_back(item); } - void begin(const core::audio_transform& transform) + void begin(const core::frame_transform& transform) { transform_stack_.push(transform_stack_.top()*transform); } @@ -114,10 +94,53 @@ public: std::vector mix() { - prev_audio_transforms_ = std::move(next_audio_transforms_); - auto result = std::move(audio_data_.front()); - audio_data_.pop_front(); - audio_data_.push_back(std::vector(format_desc_.audio_samples_per_frame)); + auto result = std::vector(format_desc_.audio_samples_per_frame); + + BOOST_FOREACH(auto& item, items) + { + const auto next = item.transform; + auto prev = next; + + const auto it = prev_frame_transforms_.find(item.tag); + if(it != prev_frame_transforms_.end()) + prev = it->second; + + next_frame_transforms_[item.tag] = next; // Store all active tags, inactive tags will be removed at the end. + + if(next.volume < 0.001 && prev.volume < 0.001) + continue; + + static const int BASE = 1<<15; + + const auto next_volume = static_cast(next.volume*BASE); + const auto prev_volume = static_cast(prev.volume*BASE); + + const int n_samples = result.size(); + + const auto in_size = static_cast(item.audio_data.size()); + CASPAR_VERIFY(in_size == 0 || in_size == result.size()); + + if(in_size > result.size()) + continue; + + tbb::parallel_for + ( + tbb::blocked_range(0, item.audio_data.size()), + [&](const tbb::blocked_range& r) + { + for(size_t n = r.begin(); n < r.end(); ++n) + { + const int sample_volume = (prev_volume - (prev_volume * n)/n_samples) + (next_volume * n)/n_samples; + const int sample = (static_cast(item.audio_data[n])*sample_volume)/BASE; + result[n] = static_cast((static_cast(result[n]) + sample) & 0xFFFF); + } + } + ); + } + + items.clear(); + prev_frame_transforms_ = std::move(next_frame_transforms_); + return std::move(result); } }; diff --git a/core/mixer/image/image_kernel.cpp b/core/mixer/image/image_kernel.cpp index 2765f09b9..5c0dc5682 100644 --- a/core/mixer/image/image_kernel.cpp +++ b/core/mixer/image/image_kernel.cpp @@ -34,7 +34,7 @@ #include #include -#include +#include #include @@ -74,7 +74,7 @@ struct image_kernel::implementation : boost::noncopyable if(item.textures.empty()) return; - if(item.transform.get_opacity() < epsilon) + if(item.transform.opacity < epsilon) return; if(!std::all_of(item.textures.begin(), item.textures.end(), std::mem_fn(&device_buffer::ready))) @@ -111,11 +111,11 @@ struct image_kernel::implementation : boost::noncopyable shader_->set("has_local_key", local_key); shader_->set("has_layer_key", layer_key); shader_->set("pixel_format", item.pix_desc.pix_fmt); - shader_->set("opacity", item.transform.get_is_key() ? 1.0 : item.transform.get_opacity()); + shader_->set("opacity", item.transform.is_key ? 1.0 : item.transform.opacity); // Setup blend_func - if(item.transform.get_is_key()) + if(item.transform.is_key) item.blend_mode = blend_mode::normal; if(blend_modes_) @@ -140,49 +140,47 @@ struct image_kernel::implementation : boost::noncopyable } // Setup image-adjustements - - auto levels = item.transform.get_levels(); - - if(levels.min_input > epsilon || - levels.max_input < 1.0-epsilon || - levels.min_output > epsilon || - levels.max_output < 1.0-epsilon || - std::abs(levels.gamma - 1.0) > epsilon) + + if(item.transform.levels.min_input > epsilon || + item.transform.levels.max_input < 1.0-epsilon || + item.transform.levels.min_output > epsilon || + item.transform.levels.max_output < 1.0-epsilon || + std::abs(item.transform.levels.gamma - 1.0) > epsilon) { shader_->set("levels", true); - shader_->set("min_input", levels.min_input); - shader_->set("max_input", levels.max_input); - shader_->set("min_output", levels.min_output); - shader_->set("max_output", levels.max_output); - shader_->set("gamma", levels.gamma); + shader_->set("min_input", item.transform.levels.min_input); + shader_->set("max_input", item.transform.levels.max_input); + shader_->set("min_output", item.transform.levels.min_output); + shader_->set("max_output", item.transform.levels.max_output); + shader_->set("gamma", item.transform.levels.gamma); } else shader_->set("levels", false); - if(std::abs(item.transform.get_brightness() - 1.0) > epsilon || - std::abs(item.transform.get_saturation() - 1.0) > epsilon || - std::abs(item.transform.get_contrast() - 1.0) > epsilon) + if(std::abs(item.transform.brightness - 1.0) > epsilon || + std::abs(item.transform.saturation - 1.0) > epsilon || + std::abs(item.transform.contrast - 1.0) > epsilon) { shader_->set("csb", true); - shader_->set("brt", item.transform.get_brightness()); - shader_->set("sat", item.transform.get_saturation()); - shader_->set("con", item.transform.get_contrast()); + shader_->set("brt", item.transform.brightness); + shader_->set("sat", item.transform.saturation); + shader_->set("con", item.transform.contrast); } else shader_->set("csb", false); // Setup interlacing - if(item.transform.get_field_mode() == core::field_mode::progressive) + if(item.transform.field_mode == core::field_mode::progressive) ogl.disable(GL_POLYGON_STIPPLE); else { ogl.enable(GL_POLYGON_STIPPLE); - if(item.transform.get_field_mode() == core::field_mode::upper) + if(item.transform.field_mode == core::field_mode::upper) ogl.stipple_pattern(upper_pattern); - else if(item.transform.get_field_mode() == core::field_mode::lower) + else if(item.transform.field_mode == core::field_mode::lower) ogl.stipple_pattern(lower_pattern); } @@ -190,8 +188,8 @@ struct image_kernel::implementation : boost::noncopyable ogl.viewport(0, 0, background.width(), background.height()); - auto m_p = item.transform.get_clip_translation(); - auto m_s = item.transform.get_clip_scale(); + auto m_p = item.transform.clip_translation; + auto m_s = item.transform.clip_scale; bool scissor = m_p[0] > std::numeric_limits::epsilon() || m_p[1] > std::numeric_limits::epsilon() && m_s[0] < 1.0 - std::numeric_limits::epsilon() || m_s[1] < 1.0 - std::numeric_limits::epsilon(); @@ -205,8 +203,8 @@ struct image_kernel::implementation : boost::noncopyable ogl.scissor(static_cast(m_p[0]*w), static_cast(m_p[1]*h), static_cast(m_s[0]*w), static_cast(m_s[1]*h)); } - auto f_p = item.transform.get_fill_translation(); - auto f_s = item.transform.get_fill_scale(); + auto f_p = item.transform.fill_translation; + auto f_s = item.transform.fill_scale; // Set render target diff --git a/core/mixer/image/image_kernel.h b/core/mixer/image/image_kernel.h index ea81f75a8..2e6051fef 100644 --- a/core/mixer/image/image_kernel.h +++ b/core/mixer/image/image_kernel.h @@ -24,7 +24,7 @@ #include #include -#include +#include #include @@ -37,7 +37,7 @@ struct render_item { pixel_format_desc pix_desc; std::vector> textures; - image_transform transform; + frame_transform transform; blend_mode::type blend_mode; }; diff --git a/core/mixer/image/image_mixer.cpp b/core/mixer/image/image_mixer.cpp index 363f47aa3..5ed421e7e 100644 --- a/core/mixer/image/image_mixer.cpp +++ b/core/mixer/image/image_mixer.cpp @@ -33,7 +33,7 @@ #include #include -#include +#include #include #include @@ -111,12 +111,12 @@ private: BOOST_FOREACH(auto& item, layer) { - if(layer_draw_buffer.first & item.transform.get_field_mode()) + if(layer_draw_buffer.first & item.transform.field_mode) item.blend_mode = blend_mode::normal; // Disable blending and just merge, it will be used when merging back into render stack. else { item.blend_mode = blend_mode::replace; // Target field is empty, no blending, just copy - layer_draw_buffer.first |= item.transform.get_field_mode(); + layer_draw_buffer.first |= item.transform.field_mode; } draw_item(std::move(item), *layer_draw_buffer.second, local_key_buffer, layer_key_buffer); @@ -126,7 +126,7 @@ private: item.pix_desc.pix_fmt = pixel_format::bgra; item.pix_desc.planes = list_of(pixel_format_desc::plane(channel_.get_format_desc().width, channel_.get_format_desc().height, 4)); item.textures = list_of(layer_draw_buffer.second); - item.transform = image_transform(); + item.transform = frame_transform(); item.blend_mode = layer_blend_mode; kernel_.draw(channel_.ogl(), std::move(item), *draw_buffer, nullptr, nullptr); @@ -147,7 +147,7 @@ private: std::pair>& local_key_buffer, std::shared_ptr& layer_key_buffer) { - if(item.transform.get_is_key()) + if(item.transform.is_key) { if(!local_key_buffer.second) { @@ -155,13 +155,13 @@ private: local_key_buffer.second = create_device_buffer(1); } - local_key_buffer.first |= item.transform.get_field_mode(); // Add field to flag. + local_key_buffer.first |= item.transform.field_mode; // Add field to flag. kernel_.draw(channel_.ogl(), std::move(item), *local_key_buffer.second, nullptr, nullptr); } else { kernel_.draw(channel_.ogl(), std::move(item), draw_buffer, local_key_buffer.second, layer_key_buffer); - local_key_buffer.first ^= item.transform.get_field_mode(); // Remove field from flag. + local_key_buffer.first ^= item.transform.field_mode; // Remove field from flag. if(local_key_buffer.first == 0) // If all fields from key has been used, reset it { @@ -175,12 +175,12 @@ private: { auto upper_count = boost::range::count_if(layer, [&](const render_item& item) { - return item.transform.get_field_mode() | field_mode::upper; + return item.transform.field_mode | field_mode::upper; }); auto lower_count = boost::range::count_if(layer, [&](const render_item& item) { - return item.transform.get_field_mode() | field_mode::lower; + return item.transform.field_mode | field_mode::lower; }); return upper_count > 1 || lower_count > 1; @@ -199,7 +199,7 @@ struct image_mixer::implementation : boost::noncopyable { ogl_device& ogl_; image_renderer renderer_; - std::vector transform_stack_; + std::vector transform_stack_; blend_mode::type active_blend_mode_; std::deque> layers_; // layer/stream/items public: @@ -219,12 +219,12 @@ public: void begin(core::basic_frame& frame) { - transform_stack_.push_back(transform_stack_.back()*frame.get_image_transform()); + transform_stack_.push_back(transform_stack_.back()*frame.get_frame_transform()); } void visit(core::write_frame& frame) { - if(transform_stack_.back().get_field_mode() == field_mode::empty) + if(transform_stack_.back().field_mode == field_mode::empty) return; core::render_item item; diff --git a/core/mixer/mixer.cpp b/core/mixer/mixer.cpp index c663d7d22..9041b2803 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,7 @@ 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; - - boost::fusion::map, - boost::fusion::pair> transforms_; - + std::unordered_map> transforms_; std::unordered_map blend_modes_; std::queue>, std::vector>> buffer_; @@ -120,14 +114,45 @@ public: { 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); + + if(channel_.get_format_desc().field_mode != core::field_mode::progressive) + { + auto frame1 = make_safe(frame.second); + frame1->get_frame_transform() = transforms_[frame.first].fetch_and_tick(1); + + auto frame2 = make_safe(frame.second); + frame2->get_frame_transform() = transforms_[frame.first].fetch_and_tick(1); + + if(frame1->get_frame_transform() != frame2->get_frame_transform()) + frame2 = core::basic_frame::interlace(frame1, frame2, channel_.get_format_desc().field_mode); + + frame2->accept(audio_mixer_); + frame2->accept(image_mixer_); + } + else + { + auto frame2 = make_safe(frame.second); + frame2->get_frame_transform() = transforms_[frame.first].fetch_and_tick(1); + + // Audio + frame2->accept(audio_mixer_); + + // Video + auto blend_it = blend_modes_.find(frame.first); + image_mixer_.begin_layer(blend_it != blend_modes_.end() ? blend_it->second : blend_mode::normal); + + frame2->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(); buffer_.push(std::make_pair(std::move(image), audio)); @@ -150,41 +175,31 @@ public: { 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); }); } - 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); }); } + + void clear_transforms() + { + channel_.execution().invoke([&]{transforms_.clear();}); + } void set_blend_mode(int index, blend_mode::type value) { @@ -195,52 +210,6 @@ public: { return L"mixer"; } - -private: - - boost::unique_future> mix_image(std::map> frames) - { - auto& image_transforms = boost::fusion::at_key(transforms_); - - 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_image_transform() = image_transforms[frame.first].fetch_and_tick(1); - - if(channel_.get_format_desc().mode != core::field_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(); - } - - std::vector mix_audio(const std::map>& frames) - { - auto& audio_transforms = boost::fusion::at_key(transforms_); - - BOOST_FOREACH(auto& frame, frames) - { - const unsigned int num = channel_.get_format_desc().mode == core::field_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(); - } }; mixer::mixer(video_channel_context& video_channel) : impl_(new implementation(video_channel)){} @@ -255,10 +224,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 diff --git a/core/mixer/mixer.h b/core/mixer/mixer.h index 198935c87..f7bd73efe 100644 --- a/core/mixer/mixer.h +++ b/core/mixer/mixer.h @@ -36,8 +36,8 @@ namespace core { class read_frame; class write_frame; class basic_frame; -class audio_transform; -class image_transform; +struct frame_transform; +struct frame_transform; class video_channel_context;; struct pixel_format; @@ -54,12 +54,10 @@ public: core::video_format_desc get_video_format_desc() const; // nothrow - void reset_transforms(); - void set_image_transform(int index, const core::image_transform& transform, unsigned int mix_duration = 0, const std::wstring& tween = L"linear"); - void set_audio_transform(int index, const core::audio_transform& transform, unsigned int mix_duration = 0, const std::wstring& tween = L"linear"); - void apply_image_transform(int index, const std::function& transform, unsigned int mix_duration = 0, const std::wstring& tween = L"linear"); - void apply_audio_transform(int index, const std::function& transform, unsigned int mix_duration = 0, const std::wstring& tween = L"linear"); + void set_frame_transform(int index, const core::frame_transform& transform, unsigned int mix_duration = 0, const std::wstring& tween = L"linear"); + void apply_frame_transform(int index, const std::function& transform, unsigned int mix_duration = 0, const std::wstring& tween = L"linear"); + void clear_transforms(); void set_blend_mode(int index, blend_mode::type value); diff --git a/core/producer/frame/audio_transform.cpp b/core/producer/frame/audio_transform.cpp deleted file mode 100644 index 4c85093eb..000000000 --- a/core/producer/frame/audio_transform.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* -* copyright (c) 2010 Sveriges Television AB -* -* This file is part of CasparCG. -* -* CasparCG is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* CasparCG is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. - -* You should have received a copy of the GNU General Public License -* along with CasparCG. If not, see . -* -*/ -#include "../../stdafx.h" - -#include "audio_transform.h" - -namespace caspar { namespace core { - -audio_transform::audio_transform() - : volume_(1.0) - , has_audio_(true){} - -void audio_transform::set_volume(double value) -{ - volume_ = std::max(0.0, value); -} - -double audio_transform::get_volume() const -{ - return volume_; -} - -void audio_transform::set_has_audio(bool value) -{ - has_audio_ = value; -} - -bool audio_transform::get_has_audio() const -{ - return has_audio_; -} - -audio_transform& audio_transform::operator*=(const audio_transform &other) -{ - volume_ *= other.volume_; - has_audio_ &= other.has_audio_; - return *this; -} - -const audio_transform audio_transform::operator*(const audio_transform &other) const -{ - return audio_transform(*this) *= other; -} - -audio_transform tween(double time, const audio_transform& source, const audio_transform& dest, double duration, const tweener_t& tweener) -{ - auto do_tween = [](double time, double source, double dest, double duration, const tweener_t& tweener) - { - return tweener(time, source, dest-source, duration); - }; - - audio_transform result; - result.set_volume(do_tween(time, source.get_volume(), dest.get_volume(), duration, tweener)); - result.set_has_audio(source.get_has_audio() || dest.get_has_audio()); - return result; -} - -}} \ No newline at end of file diff --git a/core/producer/frame/audio_transform.h b/core/producer/frame/audio_transform.h deleted file mode 100644 index 596c106d4..000000000 --- a/core/producer/frame/audio_transform.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -* copyright (c) 2010 Sveriges Television AB -* -* This file is part of CasparCG. -* -* CasparCG is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* CasparCG is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. - -* You should have received a copy of the GNU General Public License -* along with CasparCG. If not, see . -* -*/ -#pragma once - -#include - -namespace caspar { namespace core { - -class audio_transform -{ -public: - audio_transform(); - - void set_volume(double value); - double get_volume() const; - - void set_has_audio(bool value); - bool get_has_audio() const; - - audio_transform& operator*=(const audio_transform &other); - const audio_transform operator*(const audio_transform &other) const; -private: - double volume_; - bool has_audio_; -}; - -audio_transform tween(double time, const audio_transform& source, const audio_transform& dest, double duration, const tweener_t& tweener); - -inline bool operator==(const audio_transform& lhs, const audio_transform& rhs) -{ - return memcmp(&lhs, &rhs, sizeof(audio_transform)) == 0; -} - -inline bool operator!=(const audio_transform& lhs, const audio_transform& rhs) -{ - return !(lhs == rhs); -} - -}} \ No newline at end of file diff --git a/core/producer/frame/basic_frame.cpp b/core/producer/frame/basic_frame.cpp index c2669c0f9..cd3c1212d 100644 --- a/core/producer/frame/basic_frame.cpp +++ b/core/producer/frame/basic_frame.cpp @@ -21,8 +21,7 @@ #include "basic_frame.h" -#include "image_transform.h" -#include "audio_transform.h" +#include "frame_transform.h" #include "../../video_format.h" #include @@ -33,8 +32,7 @@ struct basic_frame::implementation { std::vector> frames_; - image_transform image_transform_; - audio_transform audio_transform_; + frame_transform frame_transform_; public: implementation(const std::vector>& frames) : frames_(frames) @@ -91,10 +89,8 @@ basic_frame& basic_frame::operator=(basic_frame&& other) } void basic_frame::swap(basic_frame& other){impl_.swap(other.impl_);} -const image_transform& basic_frame::get_image_transform() const { return impl_->image_transform_;} -image_transform& basic_frame::get_image_transform() { return impl_->image_transform_;} -const audio_transform& basic_frame::get_audio_transform() const { return impl_->audio_transform_;} -audio_transform& basic_frame::get_audio_transform() { return impl_->audio_transform_;} +const frame_transform& basic_frame::get_frame_transform() const { return impl_->frame_transform_;} +frame_transform& basic_frame::get_frame_transform() { return impl_->frame_transform_;} std::wstring basic_frame::print() const{return impl_->print();} void basic_frame::accept(frame_visitor& visitor){impl_->accept(*this, visitor);} @@ -114,13 +110,13 @@ safe_ptr basic_frame::interlace(const safe_ptr& frame1 auto my_frame2 = make_safe(frame2); if(mode == field_mode::upper) { - my_frame1->get_image_transform().set_field_mode(field_mode::upper); - my_frame2->get_image_transform().set_field_mode(field_mode::lower); - } - else - { - my_frame1->get_image_transform().set_field_mode(field_mode::lower); - my_frame2->get_image_transform().set_field_mode(field_mode::upper); + my_frame1->get_frame_transform().field_mode = field_mode::upper; + my_frame2->get_frame_transform().field_mode = field_mode::lower; + } + else + { + my_frame1->get_frame_transform().field_mode = field_mode::lower; + my_frame2->get_frame_transform().field_mode = field_mode::upper; } std::vector> frames; @@ -152,7 +148,7 @@ safe_ptr basic_frame::fill_and_key(const safe_ptr& fil return basic_frame::empty(); std::vector> frames; - key->get_image_transform().set_is_key(true); + key->get_frame_transform().is_key = true; frames.push_back(key); frames.push_back(fill); return basic_frame(std::move(frames)); @@ -161,7 +157,7 @@ safe_ptr basic_frame::fill_and_key(const safe_ptr& fil safe_ptr disable_audio(const safe_ptr& frame) { basic_frame frame2 = frame; - frame2.get_audio_transform().set_has_audio(false); + frame2.get_frame_transform().volume = 0.0; return std::move(frame2); } diff --git a/core/producer/frame/basic_frame.h b/core/producer/frame/basic_frame.h index d68d8e4f6..cd6926d48 100644 --- a/core/producer/frame/basic_frame.h +++ b/core/producer/frame/basic_frame.h @@ -31,9 +31,8 @@ namespace caspar { namespace core { -class image_transform; -class audio_transform; - +struct frame_transform; + class basic_frame { basic_frame(std::vector>&& frames); @@ -50,12 +49,9 @@ public: void swap(basic_frame& other); - const image_transform& get_image_transform() const; - image_transform& get_image_transform(); - - const audio_transform& get_audio_transform() const; - audio_transform& get_audio_transform(); - + const frame_transform& get_frame_transform() const; + frame_transform& get_frame_transform(); + static safe_ptr interlace(const safe_ptr& frame1, const safe_ptr& frame2, field_mode::type mode); static safe_ptr combine(const safe_ptr& frame1, const safe_ptr& frame2); static safe_ptr fill_and_key(const safe_ptr& fill, const safe_ptr& key); diff --git a/core/producer/frame/frame_transform.cpp b/core/producer/frame/frame_transform.cpp new file mode 100644 index 000000000..e4be8d527 --- /dev/null +++ b/core/producer/frame/frame_transform.cpp @@ -0,0 +1,129 @@ +/* +* copyright (c) 2010 Sveriges Television AB +* +* This file is part of CasparCG. +* +* CasparCG is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* CasparCG is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. + +* You should have received a copy of the GNU General Public License +* along with CasparCG. If not, see . +* +*/ +// TODO: Move layer specific stuff out of frame related classes. +#include "../../stdafx.h" + +#include "frame_transform.h" + +#include + +namespace caspar { namespace core { + +frame_transform::frame_transform() + : volume(1.0) + , opacity(1.0) + , brightness(1.0) + , contrast(1.0) + , saturation(1.0) + , is_key(false) + , field_mode(field_mode::progressive) +{ + std::fill(fill_translation.begin(), fill_translation.end(), 0.0); + std::fill(fill_scale.begin(), fill_scale.end(), 1.0); + std::fill(clip_translation.begin(), clip_translation.end(), 0.0); + std::fill(clip_scale.begin(), clip_scale.end(), 1.0); +} + +frame_transform& frame_transform::operator*=(const frame_transform &other) +{ + volume *= other.volume; + opacity *= other.opacity; + brightness *= other.brightness; + contrast *= other.contrast; + saturation *= other.saturation; + levels.min_input = std::max(levels.min_input, other.levels.min_input); + levels.max_input = std::min(levels.max_input, other.levels.max_input); + levels.min_output = std::max(levels.min_output, other.levels.min_output); + levels.max_output = std::min(levels.max_output, other.levels.max_output); + levels.gamma *= other.levels.gamma; + field_mode = static_cast(field_mode & other.field_mode); + is_key |= other.is_key; + fill_translation[0] += other.fill_translation[0]*fill_scale[0]; + fill_translation[1] += other.fill_translation[1]*fill_scale[1]; + fill_scale[0] *= other.fill_scale[0]; + fill_scale[1] *= other.fill_scale[1]; + clip_translation[0] += other.clip_translation[0]*clip_scale[0]; + clip_translation[1] += other.clip_translation[1]*clip_scale[1]; + clip_scale[0] *= other.clip_scale[0]; + clip_scale[1] *= other.clip_scale[1]; + return *this; +} + +frame_transform frame_transform::operator*(const frame_transform &other) const +{ + return frame_transform(*this) *= other; +} + +frame_transform tween(double time, const frame_transform& source, const frame_transform& dest, double duration, const tweener_t& tweener) +{ + auto do_tween = [](double time, double source, double dest, double duration, const tweener_t& tweener) + { + return tweener(time, source, dest-source, duration); + }; + + frame_transform result; + result.is_key = source.is_key | dest.is_key; + result.field_mode = static_cast(source.field_mode & dest.field_mode); + result.volume = do_tween(time, source.volume, dest.volume, duration, tweener); + result.brightness = do_tween(time, source.brightness, dest.brightness, duration, tweener); + result.contrast = do_tween(time, source.contrast, dest.contrast, duration, tweener); + result.saturation = do_tween(time, source.saturation, dest.saturation, duration, tweener); + result.opacity = do_tween(time, source.opacity, dest.opacity, duration, tweener); + + result.fill_translation[0] = do_tween(time, source.fill_translation[0], dest.fill_translation[0], duration, tweener), + result.fill_translation[1] = do_tween(time, source.fill_translation[1], dest.fill_translation[1], duration, tweener); + + result.fill_scale[0] = do_tween(time, source.fill_scale[0], dest.fill_scale[0], duration, tweener), + result.fill_scale[1] = do_tween(time, source.fill_scale[1], dest.fill_scale[1], duration, tweener); + + result.clip_translation[0] = do_tween(time, source.clip_translation[0], dest.clip_translation[0], duration, tweener), + result.clip_translation[1] = do_tween(time, source.clip_translation[1], dest.clip_translation[1], duration, tweener); + + result.clip_scale[0] = do_tween(time, source.clip_scale[0], dest.clip_scale[0], duration, tweener), + result.clip_scale[1] = do_tween(time, source.clip_scale[1], dest.clip_scale[1], duration, tweener); + + auto s_levels = source.levels; + auto d_levels = dest.levels; + + result.levels.max_input = do_tween(time, s_levels.max_input, d_levels.max_input, duration, tweener); + result.levels.min_input = do_tween(time, s_levels.min_input, d_levels.min_input, duration, tweener); + result.levels.max_output = do_tween(time, s_levels.max_output, d_levels.max_output, duration, tweener); + result.levels.min_output = do_tween(time, s_levels.min_output, d_levels.min_output, duration, tweener); + result.levels.gamma = do_tween(time, s_levels.gamma, d_levels.gamma, duration, tweener); + + return result; +} + +bool operator<(const frame_transform& lhs, const frame_transform& rhs) +{ + return memcmp(&lhs, &rhs, sizeof(frame_transform)) < 0; +} + +bool operator==(const frame_transform& lhs, const frame_transform& rhs) +{ + return memcmp(&lhs, &rhs, sizeof(frame_transform)) == 0; +} + +bool operator!=(const frame_transform& lhs, const frame_transform& rhs) +{ + return !(lhs == rhs); +} + +}} \ No newline at end of file diff --git a/core/producer/frame/frame_transform.h b/core/producer/frame/frame_transform.h new file mode 100644 index 000000000..512e9a20e --- /dev/null +++ b/core/producer/frame/frame_transform.h @@ -0,0 +1,80 @@ +/* +* copyright (c) 2010 Sveriges Television AB +* +* This file is part of CasparCG. +* +* CasparCG is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* CasparCG is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. + +* You should have received a copy of the GNU General Public License +* along with CasparCG. If not, see . +* +*/ +#pragma once + +#include +#include + +#include +#include + +namespace caspar { namespace core { + +struct pixel_format_desc; + +struct levels +{ + levels() + : min_input(0.0) + , max_input(1.0) + , gamma(1.0) + , min_output(0.0) + , max_output(1.0) + { + } + double min_input; + double max_input; + double gamma; + double min_output; + double max_output; +}; + +struct frame_transform +{ +public: + + frame_transform(); + + double volume; + double opacity; + double gain; + double contrast; + double brightness; + double saturation; + levels levels; + boost::array fill_translation; + boost::array fill_scale; + boost::array clip_translation; + boost::array clip_scale; + + field_mode::type field_mode; + bool is_key; + + frame_transform& frame_transform::operator*=(const frame_transform &other); + frame_transform frame_transform::operator*(const frame_transform &other) const; +}; + +frame_transform tween(double time, const frame_transform& source, const frame_transform& dest, double duration, const tweener_t& tweener); + +bool operator<(const frame_transform& lhs, const frame_transform& rhs); +bool operator==(const frame_transform& lhs, const frame_transform& rhs); +bool operator!=(const frame_transform& lhs, const frame_transform& rhs); + +}} \ No newline at end of file diff --git a/core/producer/frame/image_transform.cpp b/core/producer/frame/image_transform.cpp deleted file mode 100644 index 9d78faa7b..000000000 --- a/core/producer/frame/image_transform.cpp +++ /dev/null @@ -1,234 +0,0 @@ -/* -* copyright (c) 2010 Sveriges Television AB -* -* This file is part of CasparCG. -* -* CasparCG is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* CasparCG is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. - -* You should have received a copy of the GNU General Public License -* along with CasparCG. If not, see . -* -*/ -// TODO: Move layer specific stuff out of frame related classes. -#include "../../stdafx.h" - -#include "image_transform.h" - -#include - -namespace caspar { namespace core { - -image_transform::image_transform() - : opacity_(1.0) - , brightness_(1.0) - , contrast_(1.0) - , saturation_(1.0) - , is_key_(false) - , field_mode_(field_mode::progressive) -{ - std::fill(fill_translation_.begin(), fill_translation_.end(), 0.0); - std::fill(fill_scale_.begin(), fill_scale_.end(), 1.0); - std::fill(clip_translation_.begin(), clip_translation_.end(), 0.0); - std::fill(clip_scale_.begin(), clip_scale_.end(), 1.0); -} - -void image_transform::set_opacity(double value) -{ - opacity_ = std::max(value, 0.0); -} - -double image_transform::get_opacity() const -{ - return opacity_; -} - -void image_transform::set_brightness(double value) -{ - brightness_ = std::max(0.0, value); -} - -double image_transform::get_brightness() const -{ - return brightness_; -} - -void image_transform::set_contrast(double value) -{ - contrast_ = std::max(0.0, value); -} - -double image_transform::get_contrast() const -{ - return contrast_; -} - -void image_transform::set_saturation(double value) -{ - saturation_ = std::max(0.0, value); -} - -double image_transform::get_saturation() const -{ - return saturation_; -} - -void image_transform::set_levels(const image_transform::levels& value) -{ - levels_ = value; -} - -image_transform::levels image_transform::get_levels() const -{ - return levels_; -} - - -void image_transform::set_fill_translation(double x, double y) -{ - fill_translation_[0] = x; - fill_translation_[1] = y; -} - -void image_transform::set_fill_scale(double x, double y) -{ - fill_scale_[0] = x; - fill_scale_[1] = y; -} - -std::array image_transform::get_fill_translation() const -{ - return fill_translation_; -} - -std::array image_transform::get_fill_scale() const -{ - return fill_scale_; -} - -void image_transform::set_clip_translation(double x, double y) -{ - clip_translation_[0] = x; - clip_translation_[1] = y; -} - -void image_transform::set_clip_scale(double x, double y) -{ - clip_scale_[0] = x; - clip_scale_[1] = y; -} - -std::array image_transform::get_clip_translation() const -{ - return clip_translation_; -} - -std::array image_transform::get_clip_scale() const -{ - return clip_scale_; -} - -void image_transform::set_field_mode(field_mode::type field_mode) -{ - field_mode_ = field_mode; -} - -field_mode::type image_transform::get_field_mode() const -{ - return field_mode_; -} - -image_transform& image_transform::operator*=(const image_transform &other) -{ - opacity_ *= other.opacity_; - brightness_ *= other.brightness_; - contrast_ *= other.contrast_; - saturation_ *= other.saturation_; - - levels_.min_input = std::max(levels_.min_input, other.levels_.min_input); - levels_.max_input = std::min(levels_.max_input, other.levels_.max_input); - - levels_.min_output = std::max(levels_.min_output, other.levels_.min_output); - levels_.max_output = std::min(levels_.max_output, other.levels_.max_output); - - levels_.gamma *= other.levels_.gamma; - - field_mode_ = static_cast(field_mode_ & other.field_mode_); - is_key_ |= other.is_key_; - fill_translation_[0] += other.fill_translation_[0]*fill_scale_[0]; - fill_translation_[1] += other.fill_translation_[1]*fill_scale_[1]; - fill_scale_[0] *= other.fill_scale_[0]; - fill_scale_[1] *= other.fill_scale_[1]; - clip_translation_[0] += other.clip_translation_[0]*clip_scale_[0]; - clip_translation_[1] += other.clip_translation_[1]*clip_scale_[1]; - clip_scale_[0] *= other.clip_scale_[0]; - clip_scale_[1] *= other.clip_scale_[1]; - return *this; -} - -const image_transform image_transform::operator*(const image_transform &other) const -{ - return image_transform(*this) *= other; -} - -void image_transform::set_is_key(bool value){is_key_ = value;} -bool image_transform::get_is_key() const{return is_key_;} - -image_transform tween(double time, const image_transform& source, const image_transform& dest, double duration, const tweener_t& tweener) -{ - auto do_tween = [](double time, double source, double dest, double duration, const tweener_t& tweener) - { - return tweener(time, source, dest-source, duration); - }; - - image_transform result; - result.set_is_key (source.get_is_key() | dest.get_is_key()); - result.set_field_mode (static_cast(source.get_field_mode() & dest.get_field_mode())); - result.set_brightness (do_tween(time, source.get_brightness(), dest.get_brightness(), duration, tweener)); - result.set_contrast (do_tween(time, source.get_contrast(), dest.get_contrast(), duration, tweener)); - result.set_saturation (do_tween(time, source.get_saturation(), dest.get_saturation(), duration, tweener)); - result.set_opacity (do_tween(time, source.get_opacity(), dest.get_opacity(), duration, tweener)); - result.set_fill_translation (do_tween(time, source.get_fill_translation()[0], dest.get_fill_translation()[0], duration, tweener), do_tween(time, source.get_fill_translation()[1], dest.get_fill_translation()[1], duration, tweener)); - result.set_fill_scale (do_tween(time, source.get_fill_scale()[0], dest.get_fill_scale()[0], duration, tweener), do_tween(time, source.get_fill_scale()[1], dest.get_fill_scale()[1], duration, tweener)); - result.set_clip_translation (do_tween(time, source.get_clip_translation()[0], dest.get_clip_translation()[0], duration, tweener), do_tween(time, source.get_clip_translation()[1], dest.get_clip_translation()[1], duration, tweener)); - result.set_clip_scale (do_tween(time, source.get_clip_scale()[0], dest.get_clip_scale()[0], duration, tweener), do_tween(time, source.get_clip_scale()[1], dest.get_clip_scale()[1], duration, tweener)); - - auto s_levels = source.get_levels(); - auto d_levels = dest.get_levels(); - - d_levels.max_input = do_tween(time, s_levels.max_input, d_levels.max_input, duration, tweener); - d_levels.min_input = do_tween(time, s_levels.min_input, d_levels.min_input, duration, tweener); - - d_levels.max_output = do_tween(time, s_levels.max_output, d_levels.max_output, duration, tweener); - d_levels.min_output = do_tween(time, s_levels.min_output, d_levels.min_output, duration, tweener); - - d_levels.gamma = do_tween(time, s_levels.gamma, d_levels.gamma, duration, tweener); - - result.set_levels(d_levels); - - return result; -} - -bool operator<(const image_transform& lhs, const image_transform& rhs) -{ - return memcmp(&lhs, &rhs, sizeof(image_transform)) < 0; -} - -bool operator==(const image_transform& lhs, const image_transform& rhs) -{ - return memcmp(&lhs, &rhs, sizeof(image_transform)) == 0; -} - -bool operator!=(const image_transform& lhs, const image_transform& rhs) -{ - return !(lhs == rhs); -} - -}} \ No newline at end of file diff --git a/core/producer/frame/image_transform.h b/core/producer/frame/image_transform.h deleted file mode 100644 index 385aeb094..000000000 --- a/core/producer/frame/image_transform.h +++ /dev/null @@ -1,113 +0,0 @@ -/* -* copyright (c) 2010 Sveriges Television AB -* -* This file is part of CasparCG. -* -* CasparCG is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* CasparCG is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. - -* You should have received a copy of the GNU General Public License -* along with CasparCG. If not, see . -* -*/ -#pragma once - -#include -#include - -#include -#include - -namespace caspar { namespace core { - -struct pixel_format_desc; - -class image_transform -{ -public: - - struct levels - { - levels() - : min_input(0.0) - , max_input(1.0) - , gamma(1.0) - , min_output(0.0) - , max_output(1.0) - { - } - double min_input; - double max_input; - double gamma; - double min_output; - double max_output; - }; - - image_transform(); - - void set_opacity(double value); - double get_opacity() const; - - void set_brightness(double value); - double get_brightness() const; - - void set_contrast(double value); - double get_contrast() const; - - void set_saturation(double value); - double get_saturation() const; - - void set_levels(const levels& value); - levels get_levels() const; - - void set_fill_translation(double x, double y); - std::array get_fill_translation() const; - - void set_fill_scale(double x, double y); - std::array get_fill_scale() const; - - void set_clip_translation(double x, double y); - std::array get_clip_translation() const; - - void set_clip_scale(double x, double y); - std::array get_clip_scale() const; - - image_transform& operator*=(const image_transform &other); - const image_transform operator*(const image_transform &other) const; - - void set_is_key(bool value); - bool get_is_key() const; - - void set_field_mode(field_mode::type field_mode); - field_mode::type get_field_mode() const; - -private: - double opacity_; - double gain_; - double contrast_; - double brightness_; - double saturation_; - double desaturation_; - levels levels_; - std::array fill_translation_; - std::array fill_scale_; - std::array clip_translation_; - std::array clip_scale_; - field_mode::type field_mode_; - bool is_key_; -}; - -image_transform tween(double time, const image_transform& source, const image_transform& dest, double duration, const tweener_t& tweener); - -bool operator<(const image_transform& lhs, const image_transform& rhs); -bool operator==(const image_transform& lhs, const image_transform& rhs); -bool operator!=(const image_transform& lhs, const image_transform& rhs); - -}} \ No newline at end of file diff --git a/core/producer/frame_producer.cpp b/core/producer/frame_producer.cpp index 9b187d834..da08185ac 100644 --- a/core/producer/frame_producer.cpp +++ b/core/producer/frame_producer.cpp @@ -22,7 +22,7 @@ #include "frame_producer.h" #include "frame/basic_frame.h" -#include "frame/audio_transform.h" +#include "frame/frame_transform.h" #include "color/color_producer.h" #include "separated/separated_producer.h" diff --git a/core/producer/transition/transition_producer.cpp b/core/producer/transition/transition_producer.cpp index 204eb084f..ccbfa757c 100644 --- a/core/producer/transition/transition_producer.cpp +++ b/core/producer/transition/transition_producer.cpp @@ -24,11 +24,14 @@ #include #include -#include -#include +#include #include +#include + +using namespace boost::assign; + namespace caspar { namespace core { struct transition_producer : public frame_producer @@ -120,44 +123,44 @@ struct transition_producer : public frame_producer auto s_frame1 = make_safe(src_frame); auto s_frame2 = make_safe(src_frame); - s_frame1->get_audio_transform().set_has_audio(false); - s_frame2->get_audio_transform().set_volume(1.0-delta2); + s_frame1->get_frame_transform().volume = 0.0; + s_frame2->get_frame_transform().volume = 1.0-delta2; auto d_frame1 = make_safe(dest_frame); auto d_frame2 = make_safe(dest_frame); - d_frame1->get_audio_transform().set_has_audio(false); - d_frame2->get_audio_transform().set_volume(delta2); + d_frame1->get_frame_transform().volume = 0.0; + d_frame2->get_frame_transform().volume = delta2; //if(info_.type == transition::mix) //{ - // d_frame1->get_image_transform().set_opacity(delta1); - // d_frame2->get_image_transform().set_opacity(delta2); + // d_frame1->get_frame_transform().set_opacity(delta1); + // d_frame2->get_frame_transform().set_opacity(delta2); - // s_frame1->get_image_transform().set_opacity(1.0-delta1); - // s_frame2->get_image_transform().set_opacity(1.0-delta2); + // s_frame1->get_frame_transform().set_opacity(1.0-delta1); + // s_frame2->get_frame_transform().set_opacity(1.0-delta2); //} if(info_.type == transition::slide) { - d_frame1->get_image_transform().set_fill_translation((-1.0+delta1)*dir, 0.0); - d_frame2->get_image_transform().set_fill_translation((-1.0+delta2)*dir, 0.0); + d_frame1->get_frame_transform().fill_translation[0] = (-1.0+delta1)*dir; + d_frame2->get_frame_transform().fill_translation[0] = (-1.0+delta2)*dir; } else if(info_.type == transition::push) { - d_frame1->get_image_transform().set_fill_translation((-1.0+delta1)*dir, 0.0); - d_frame2->get_image_transform().set_fill_translation((-1.0+delta2)*dir, 0.0); + d_frame1->get_frame_transform().fill_translation[0] = (-1.0+delta1)*dir; + d_frame2->get_frame_transform().fill_translation[0] = (-1.0+delta2)*dir; - s_frame1->get_image_transform().set_fill_translation((0.0+delta1)*dir, 0.0); - s_frame2->get_image_transform().set_fill_translation((0.0+delta2)*dir, 0.0); + s_frame1->get_frame_transform().fill_translation[0] = (0.0+delta1)*dir; + s_frame2->get_frame_transform().fill_translation[0] = (0.0+delta2)*dir; } else if(info_.type == transition::wipe) { - d_frame1->get_image_transform().set_clip_scale(delta1, 1.0); - d_frame2->get_image_transform().set_clip_scale(delta2, 1.0); + d_frame1->get_frame_transform().clip_scale[0] = delta1; + d_frame2->get_frame_transform().clip_scale[0] = delta2; } - const auto s_frame = s_frame1->get_image_transform() == s_frame2->get_image_transform() ? s_frame2 : basic_frame::interlace(s_frame1, s_frame2, mode_); - const auto d_frame = d_frame1->get_image_transform() == d_frame2->get_image_transform() ? d_frame2 : basic_frame::interlace(d_frame1, d_frame2, mode_); + const auto s_frame = s_frame1->get_frame_transform() == s_frame2->get_frame_transform() ? s_frame2 : basic_frame::interlace(s_frame1, s_frame2, mode_); + const auto d_frame = d_frame1->get_frame_transform() == d_frame2->get_frame_transform() ? d_frame2 : basic_frame::interlace(d_frame1, d_frame2, mode_); last_frame_ = basic_frame::combine(s_frame2, d_frame2); diff --git a/core/video_format.h b/core/video_format.h index da8a6565a..2d8250c5b 100644 --- a/core/video_format.h +++ b/core/video_format.h @@ -83,7 +83,7 @@ struct video_format_desc size_t width; // output frame width size_t height; // output frame height - field_mode::type mode; // progressive, interlaced upper field first, interlaced lower field first + field_mode::type field_mode; // progressive, interlaced upper field first, interlaced lower field first double fps; // actual framerate, e.g. i50 = 25 fps, p50 = 50 fps size_t time_scale; size_t duration; diff --git a/modules/decklink/interop/DeckLinkAPI_h.h b/modules/decklink/interop/DeckLinkAPI_h.h index 03b03d3b6..2aefce8c5 100644 --- a/modules/decklink/interop/DeckLinkAPI_h.h +++ b/modules/decklink/interop/DeckLinkAPI_h.h @@ -4,7 +4,7 @@ /* File created by MIDL compiler version 7.00.0555 */ -/* at Fri Aug 19 23:43:33 2011 +/* at Sun Aug 21 14:54:35 2011 */ /* Compiler settings for interop\DeckLinkAPI.idl: Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 7.00.0555 diff --git a/modules/decklink/interop/DeckLinkAPI_i.c b/modules/decklink/interop/DeckLinkAPI_i.c index d90511728..3555647ec 100644 --- a/modules/decklink/interop/DeckLinkAPI_i.c +++ b/modules/decklink/interop/DeckLinkAPI_i.c @@ -6,7 +6,7 @@ /* File created by MIDL compiler version 7.00.0555 */ -/* at Fri Aug 19 23:43:33 2011 +/* at Sun Aug 21 14:54:35 2011 */ /* Compiler settings for interop\DeckLinkAPI.idl: Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 7.00.0555 diff --git a/modules/decklink/producer/decklink_producer.cpp b/modules/decklink/producer/decklink_producer.cpp index c8304bddf..595413364 100644 --- a/modules/decklink/producer/decklink_producer.cpp +++ b/modules/decklink/producer/decklink_producer.cpp @@ -36,7 +36,7 @@ #include #include -#include +#include #include #include @@ -184,8 +184,8 @@ public: av_frame->format = PIX_FMT_UYVY422; av_frame->width = video->GetWidth(); av_frame->height = video->GetHeight(); - av_frame->interlaced_frame = format_desc_.mode != core::field_mode::progressive; - av_frame->top_field_first = format_desc_.mode == core::field_mode::upper ? 1 : 0; + av_frame->interlaced_frame = format_desc_.field_mode != core::field_mode::progressive; + av_frame->top_field_first = format_desc_.field_mode == core::field_mode::upper ? 1 : 0; BOOST_FOREACH(auto& av_frame2, filter_.execute(av_frame)) muxer_.push(av_frame2); diff --git a/modules/ffmpeg/producer/frame_muxer.cpp b/modules/ffmpeg/producer/frame_muxer.cpp index ff32adb44..99a9ab5e5 100644 --- a/modules/ffmpeg/producer/frame_muxer.cpp +++ b/modules/ffmpeg/producer/frame_muxer.cpp @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include #include @@ -188,9 +188,9 @@ struct frame_muxer::implementation : boost::noncopyable if(auto_transcode_) { auto in_mode = get_mode(*video_frame); - display_mode_ = get_display_mode(in_mode, in_fps_, format_desc_.mode, format_desc_.fps); + display_mode_ = get_display_mode(in_mode, in_fps_, format_desc_.field_mode, format_desc_.fps); - if(display_mode_ == display_mode::simple && in_mode != core::field_mode::progressive && format_desc_.mode != core::field_mode::progressive && video_frame->height != static_cast(format_desc_.height)) + if(display_mode_ == display_mode::simple && in_mode != core::field_mode::progressive && format_desc_.field_mode != core::field_mode::progressive && video_frame->height != static_cast(format_desc_.height)) display_mode_ = display_mode::deinterlace_bob_reinterlace; // The frame will most likely be scaled, we need to deinterlace->reinterlace if(display_mode_ == display_mode::deinterlace) @@ -225,10 +225,10 @@ struct frame_muxer::implementation : boost::noncopyable auto frame = make_write_frame(this, av_frame, frame_factory_, hints); // Fix field-order if needed - if(frame->get_type() == core::field_mode::lower && format_desc_.mode == core::field_mode::upper) - frame->get_image_transform().set_fill_translation(0.0f, 0.5/static_cast(frame->get_pixel_format_desc().planes[0].height)); - else if(frame->get_type() == core::field_mode::upper && format_desc_.mode == core::field_mode::lower) - frame->get_image_transform().set_fill_translation(0.0f, -0.5/static_cast(frame->get_pixel_format_desc().planes[0].height)); + if(frame->get_type() == core::field_mode::lower && format_desc_.field_mode == core::field_mode::upper) + frame->get_frame_transform().fill_translation[1] += 0.5/static_cast(frame->get_pixel_format_desc().planes[0].height); + else if(frame->get_type() == core::field_mode::upper && format_desc_.field_mode == core::field_mode::lower) + frame->get_frame_transform().fill_translation[1] -= 0.5/static_cast(frame->get_pixel_format_desc().planes[0].height); video_streams_.back().push(frame); ++video_frame_count_; @@ -388,7 +388,7 @@ struct frame_muxer::implementation : boost::noncopyable auto frame2 = pop_video(); - dest.push_back(core::basic_frame::interlace(frame1, frame2, format_desc_.mode)); + dest.push_back(core::basic_frame::interlace(frame1, frame2, format_desc_.field_mode)); } int64_t calc_nb_frames(int64_t nb_frames) const diff --git a/modules/ffmpeg/producer/util.cpp b/modules/ffmpeg/producer/util.cpp index 5336aca50..6d67bfaf2 100644 --- a/modules/ffmpeg/producer/util.cpp +++ b/modules/ffmpeg/producer/util.cpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include #include #include diff --git a/modules/ffmpeg/producer/video/video_decoder.cpp b/modules/ffmpeg/producer/video/video_decoder.cpp index 5dba7c2f7..f365a7c96 100644 --- a/modules/ffmpeg/producer/video/video_decoder.cpp +++ b/modules/ffmpeg/producer/video/video_decoder.cpp @@ -27,7 +27,7 @@ #include "../../ffmpeg_error.h" #include "../../tbb_avcodec.h" -#include +#include #include #include diff --git a/modules/flash/producer/flash_producer.cpp b/modules/flash/producer/flash_producer.cpp index 2eac9084f..da4572f7e 100644 --- a/modules/flash/producer/flash_producer.cpp +++ b/modules/flash/producer/flash_producer.cpp @@ -362,7 +362,7 @@ public: { auto frame1 = context_->render_frame(frame_buffer_.size() < frame_buffer_.capacity()); auto frame2 = context_->render_frame(frame_buffer_.size() < frame_buffer_.capacity()); - frame_buffer_.push(core::basic_frame::interlace(frame1, frame2, format_desc.mode)); + frame_buffer_.push(core::basic_frame::interlace(frame1, frame2, format_desc.field_mode)); } else if(abs(context_->fps()- format_desc.fps/2.0) < 2.0) // format == 2 * flash -> duplicate { diff --git a/modules/image/producer/image_scroll_producer.cpp b/modules/image/producer/image_scroll_producer.cpp index cb48246b4..c722ae9b2 100644 --- a/modules/image/producer/image_scroll_producer.cpp +++ b/modules/image/producer/image_scroll_producer.cpp @@ -28,7 +28,7 @@ #include #include -#include +#include #include #include @@ -41,6 +41,7 @@ #include #include +#include using namespace boost::assign; @@ -164,7 +165,10 @@ struct image_scroll_producer : public core::frame_producer return core::basic_frame::eof(); for(size_t n = 0; n < frames_.size(); ++n) - frames_[n]->get_image_transform().set_fill_translation(start_offset_[0], start_offset_[1] -0.5*(n+1) + delta_ * 0.5/static_cast(format_desc_.height)); + { + frames_[n]->get_frame_transform().fill_translation[0] = start_offset_[0]; + frames_[n]->get_frame_transform().fill_translation[0] = start_offset_[1] -0.5*(n+1) + delta_ * 0.5/static_cast(format_desc_.height); + } } else { @@ -172,7 +176,10 @@ struct image_scroll_producer : public core::frame_producer return core::basic_frame::eof(); for(size_t n = 0; n < frames_.size(); ++n) - frames_[n]->get_image_transform().set_fill_translation(start_offset_[0] -0.5*(n+1) + delta_ * 0.5/static_cast(format_desc_.height), start_offset_[1]); + { + frames_[n]->get_frame_transform().fill_translation[0] = start_offset_[0] -0.5*(n+1) + delta_ * 0.5/static_cast(format_desc_.height); + frames_[n]->get_frame_transform().fill_translation[1] = start_offset_[1]; + } } return last_frame_ = core::basic_frame(frames_); diff --git a/protocol/amcp/AMCPCommandsImpl.cpp b/protocol/amcp/AMCPCommandsImpl.cpp index db1683286..b9f6d5e0c 100644 --- a/protocol/amcp/AMCPCommandsImpl.cpp +++ b/protocol/amcp/AMCPCommandsImpl.cpp @@ -20,6 +20,10 @@ #include "../StdAfx.h" +#if defined(_MSC_VER) +#pragma warning (push, 1) // TODO: Legacy code, just disable warnings +#endif + #include "AMCPCommandsImpl.h" #include "AMCPProtocolStrategy.h" @@ -30,8 +34,7 @@ #include #include #include -#include -#include +#include #include #include #include @@ -53,10 +56,6 @@ #include #include -#if defined(_MSC_VER) -#pragma warning (push, 1) // TODO: Legacy code, just disable warnings -#endif - /* Return codes 100 [action] Information om att något har hänt @@ -224,14 +223,14 @@ bool MixerCommand::DoExecute() if(_parameters[0] == L"KEYER") { bool value = lexical_cast_or_default(_parameters.at(1), false); - auto transform = [=](image_transform transform) -> image_transform + auto transform = [=](frame_transform transform) -> frame_transform { - transform.set_is_key(value); + transform.is_key = value; return transform; }; int layer = GetLayerIndex(); - GetChannel()->mixer()->apply_image_transform(GetLayerIndex(), transform); + GetChannel()->mixer()->apply_frame_transform(GetLayerIndex(), transform); } else if(_parameters[0] == L"OPACITY") { @@ -240,14 +239,14 @@ bool MixerCommand::DoExecute() double value = boost::lexical_cast(_parameters.at(1)); - auto transform = [=](image_transform transform) -> image_transform + auto transform = [=](frame_transform transform) -> frame_transform { - transform.set_opacity(value); + transform.opacity = value; return transform; }; int layer = GetLayerIndex(); - GetChannel()->mixer()->apply_image_transform(GetLayerIndex(), transform, duration, tween); + GetChannel()->mixer()->apply_frame_transform(GetLayerIndex(), transform, duration, tween); } else if(_parameters[0] == L"FILL") { @@ -258,19 +257,23 @@ bool MixerCommand::DoExecute() double x_s = boost::lexical_cast(_parameters.at(3)); double y_s = boost::lexical_cast(_parameters.at(4)); - auto transform = [=](image_transform transform) -> image_transform + auto transform = [=](frame_transform transform) mutable -> frame_transform { - transform.set_fill_translation(x, y); - transform.set_fill_scale(x_s, y_s); - transform.set_clip_translation(x, y); - transform.set_clip_scale(x_s, y_s); + transform.fill_translation[0] = x; + transform.fill_translation[1] = y; + transform.fill_scale[0] = x_s; + transform.fill_scale[1] = y_s; + transform.clip_translation[0] = x; + transform.clip_translation[1] = y; + transform.clip_scale[0] = x_s; + transform.clip_scale[1] = y_s; return transform; }; int layer = GetLayerIndex(); - GetChannel()->mixer()->apply_image_transform(GetLayerIndex(), transform, duration, tween); + GetChannel()->mixer()->apply_frame_transform(GetLayerIndex(), transform, duration, tween); } - else if(_parameters[0] == L"MASK") + else if(_parameters[0] == L"CLIP") { int duration = _parameters.size() > 5 ? lexical_cast_or_default(_parameters[5], 0) : 0; std::wstring tween = _parameters.size() > 6 ? _parameters[6] : L"linear"; @@ -279,15 +282,17 @@ bool MixerCommand::DoExecute() double x_s = boost::lexical_cast(_parameters.at(3)); double y_s = boost::lexical_cast(_parameters.at(4)); - auto transform = [=](image_transform transform) -> image_transform + auto transform = [=](frame_transform transform) -> frame_transform { - transform.set_clip_translation(x, y); - transform.set_clip_scale(x_s, y_s); + transform.clip_translation[0] = x; + transform.clip_translation[1] = y; + transform.clip_scale[0] = x_s; + transform.clip_scale[1] = y_s; return transform; }; int layer = GetLayerIndex(); - GetChannel()->mixer()->apply_image_transform(GetLayerIndex(), transform, duration, tween); + GetChannel()->mixer()->apply_frame_transform(GetLayerIndex(), transform, duration, tween); } else if(_parameters[0] == L"GRID") { @@ -300,15 +305,19 @@ bool MixerCommand::DoExecute() for(int y = 0; y < n; ++y) { int index = x+y*n+1; - auto transform = [=](image_transform transform) -> image_transform - { - transform.set_fill_translation(x*delta, y*delta); - transform.set_fill_scale(delta, delta); - transform.set_clip_translation(x*delta, y*delta); - transform.set_clip_scale(delta, delta); + auto transform = [=](frame_transform transform) -> frame_transform + { + transform.fill_translation[0] = x*delta; + transform.fill_translation[1] = y*delta; + transform.fill_scale[0] = delta; + transform.fill_scale[1] = delta; + transform.clip_translation[0] = x*delta; + transform.clip_translation[1] = y*delta; + transform.clip_scale[0] = delta; + transform.clip_scale[1] = delta; return transform; }; - GetChannel()->mixer()->apply_image_transform(index, transform, duration, tween); + GetChannel()->mixer()->apply_frame_transform(index, transform, duration, tween); } } } @@ -323,46 +332,46 @@ bool MixerCommand::DoExecute() auto value = boost::lexical_cast(_parameters.at(1)); int duration = _parameters.size() > 2 ? lexical_cast_or_default(_parameters[2], 0) : 0; std::wstring tween = _parameters.size() > 3 ? _parameters[3] : L"linear"; - auto transform = [=](image_transform transform) -> image_transform + auto transform = [=](frame_transform transform) -> frame_transform { - transform.set_brightness(value); + transform.brightness = value; return transform; }; int layer = GetLayerIndex(); - GetChannel()->mixer()->apply_image_transform(GetLayerIndex(), transform, duration, tween); + GetChannel()->mixer()->apply_frame_transform(GetLayerIndex(), transform, duration, tween); } else if(_parameters[0] == L"SATURATION") { auto value = boost::lexical_cast(_parameters.at(1)); int duration = _parameters.size() > 2 ? lexical_cast_or_default(_parameters[2], 0) : 0; std::wstring tween = _parameters.size() > 3 ? _parameters[3] : L"linear"; - auto transform = [=](image_transform transform) -> image_transform + auto transform = [=](frame_transform transform) -> frame_transform { - transform.set_saturation(value); + transform.saturation = value; return transform; }; int layer = GetLayerIndex(); - GetChannel()->mixer()->apply_image_transform(GetLayerIndex(), transform, duration, tween); + GetChannel()->mixer()->apply_frame_transform(GetLayerIndex(), transform, duration, tween); } else if(_parameters[0] == L"CONTRAST") { auto value = boost::lexical_cast(_parameters.at(1)); int duration = _parameters.size() > 2 ? lexical_cast_or_default(_parameters[2], 0) : 0; std::wstring tween = _parameters.size() > 3 ? _parameters[3] : L"linear"; - auto transform = [=](image_transform transform) -> image_transform + auto transform = [=](frame_transform transform) -> frame_transform { - transform.set_contrast(value); + transform.contrast = value; return transform; }; int layer = GetLayerIndex(); - GetChannel()->mixer()->apply_image_transform(GetLayerIndex(), transform, duration, tween); + GetChannel()->mixer()->apply_frame_transform(GetLayerIndex(), transform, duration, tween); } else if(_parameters[0] == L"LEVELS") { - image_transform::levels value; + levels value; value.min_input = boost::lexical_cast(_parameters.at(1)); value.max_input = boost::lexical_cast(_parameters.at(2)); value.gamma = boost::lexical_cast(_parameters.at(3)); @@ -371,14 +380,14 @@ bool MixerCommand::DoExecute() int duration = _parameters.size() > 6 ? lexical_cast_or_default(_parameters[6], 0) : 0; std::wstring tween = _parameters.size() > 7 ? _parameters[7] : L"linear"; - auto transform = [=](image_transform transform) -> image_transform + auto transform = [=](frame_transform transform) -> frame_transform { - transform.set_levels(value); + transform.levels = value; return transform; }; int layer = GetLayerIndex(); - GetChannel()->mixer()->apply_image_transform(GetLayerIndex(), transform, duration, tween); + GetChannel()->mixer()->apply_frame_transform(GetLayerIndex(), transform, duration, tween); } else if(_parameters[0] == L"VOLUME") { @@ -386,18 +395,18 @@ bool MixerCommand::DoExecute() std::wstring tween = _parameters.size() > 3 ? _parameters[3] : L"linear"; double value = boost::lexical_cast(_parameters[1]); - auto transform = [=](audio_transform transform) -> audio_transform + auto transform = [=](frame_transform transform) -> frame_transform { - transform.set_volume(value); + transform.volume = value; return transform; }; int layer = GetLayerIndex(); - GetChannel()->mixer()->apply_audio_transform(GetLayerIndex(), transform, duration, tween); + GetChannel()->mixer()->apply_frame_transform(GetLayerIndex(), transform, duration, tween); } - else if(_parameters[0] == L"RESET") + else if(_parameters[0] == L"CLEAR") { - GetChannel()->mixer()->reset_transforms(); + GetChannel()->mixer()->clear_transforms(); } else { @@ -640,7 +649,7 @@ bool LoadbgCommand::DoExecute() bool auto_play = std::find(_parameters.begin(), _parameters.end(), L"AUTO") != _parameters.end(); - auto pFP2 = create_transition_producer(GetChannel()->get_video_format_desc().mode, pFP, transitionInfo); + auto pFP2 = create_transition_producer(GetChannel()->get_video_format_desc().field_mode, pFP, transitionInfo); GetChannel()->stage()->load(GetLayerIndex(), pFP2, false, auto_play ? transitionInfo.duration : -1); // TODO: LOOP CASPAR_LOG(info) << "Loaded " << _parameters[0] << TEXT(" successfully to background"); diff --git a/protocol/cii/CIIProtocolStrategy.cpp b/protocol/cii/CIIProtocolStrategy.cpp index d934a0fa9..1bf718356 100644 --- a/protocol/cii/CIIProtocolStrategy.cpp +++ b/protocol/cii/CIIProtocolStrategy.cpp @@ -214,7 +214,7 @@ void CIIProtocolStrategy::DisplayMediaFile(const std::wstring& filename) transition.duration = 12; auto pFP = create_producer(GetChannel()->mixer(), boost::assign::list_of(filename)); - auto pTransition = create_transition_producer(GetChannel()->get_video_format_desc().mode, pFP, transition); + auto pTransition = create_transition_producer(GetChannel()->get_video_format_desc().field_mode, pFP, transition); try { diff --git a/shell/casparcg.config b/shell/casparcg.config index 0b6b9a6ca..02ce7a9a8 100644 --- a/shell/casparcg.config +++ b/shell/casparcg.config @@ -54,6 +54,7 @@ false + -- 2.39.2