<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
</ClCompile>\r
<ClCompile Include="mixer\image\shader\image_shader.cpp">\r
- <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../../StdAfx.h</PrecompiledHeaderFile>\r
+ <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../../stdafx.h</PrecompiledHeaderFile>\r
+ <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../../stdafx.h</PrecompiledHeaderFile>\r
+ <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../../stdafx.h</PrecompiledHeaderFile>\r
+ <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../../stdafx.h</PrecompiledHeaderFile>\r
</ClCompile>\r
<ClCompile Include="producer\playlist\playlist_producer.cpp">\r
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../stdafx.h</PrecompiledHeaderFile>\r
\r
namespace caspar { namespace core {\r
\r
-template<typename T>\r
-class tweened_transform\r
-{\r
- T source_;\r
- T dest_;\r
- int duration_;\r
- int time_;\r
- tweener_t tweener_;\r
-public: \r
- tweened_transform()\r
- : duration_(0)\r
- , time_(0)\r
- , tweener_(get_tweener(L"linear")){}\r
- tweened_transform(const T& source, const T& dest, int duration, const std::wstring& tween = L"linear")\r
- : source_(source)\r
- , dest_(dest)\r
- , duration_(duration)\r
- , time_(0)\r
- , tweener_(get_tweener(tween)){}\r
- \r
- T fetch()\r
- {\r
- return time_ == duration_ ? dest_ : tween(static_cast<double>(time_), source_, dest_, static_cast<double>(duration_), tweener_);\r
- }\r
-\r
- T fetch_and_tick(int num)\r
- { \r
- time_ = std::min(time_+num, duration_);\r
- return fetch();\r
- }\r
-};\r
-\r
struct mixer::implementation : boost::noncopyable\r
{ \r
safe_ptr<diagnostics::graph> graph_;\r
audio_mixer audio_mixer_;\r
image_mixer image_mixer_;\r
\r
- std::unordered_map<int, tweened_transform<core::frame_transform>> transforms_; \r
std::unordered_map<int, blend_mode::type> blend_modes_;\r
\r
executor executor_;\r
{\r
auto blend_it = blend_modes_.find(frame.first);\r
image_mixer_.begin_layer(blend_it != blend_modes_.end() ? blend_it->second : blend_mode::normal);\r
- \r
- auto frame1 = make_safe<core::basic_frame>(frame.second);\r
- frame1->get_frame_transform() = transforms_[frame.first].fetch_and_tick(1);\r
-\r
- if(format_desc_.field_mode != core::field_mode::progressive)\r
- { \r
- auto frame2 = make_safe<core::basic_frame>(frame.second);\r
- frame2->get_frame_transform() = transforms_[frame.first].fetch_and_tick(1);\r
- frame1 = core::basic_frame::interlace(frame1, frame2, format_desc_.field_mode);\r
- }\r
- \r
- frame1->accept(audio_mixer_); \r
- frame1->accept(image_mixer_);\r
+ \r
+ frame.second->accept(audio_mixer_); \r
+ frame.second->accept(image_mixer_);\r
\r
image_mixer_.end_layer();\r
}\r
{ \r
return make_safe<write_frame>(ogl_, tag, desc);\r
}\r
- \r
- void set_transform(int index, const frame_transform& transform, unsigned int mix_duration, const std::wstring& tween)\r
- {\r
- executor_.begin_invoke([=]\r
- {\r
- auto src = transforms_[index].fetch();\r
- auto dst = transform;\r
- transforms_[index] = tweened_transform<frame_transform>(src, dst, mix_duration, tween);\r
- }, high_priority);\r
- }\r
\r
- void apply_transform(int index, const std::function<frame_transform(frame_transform)>& transform, unsigned int mix_duration, const std::wstring& tween)\r
- {\r
- executor_.begin_invoke([=]\r
- {\r
- auto src = transforms_[index].fetch();\r
- auto dst = transform(src);\r
- transforms_[index] = tweened_transform<frame_transform>(src, dst, mix_duration, tween);\r
- }, high_priority);\r
- }\r
-\r
- void clear_transforms(int index)\r
- {\r
- executor_.begin_invoke([=]\r
- {\r
- transforms_.erase(index);\r
- blend_modes_.erase(index);\r
- }, high_priority);\r
- }\r
-\r
- void clear_transforms()\r
- {\r
- executor_.begin_invoke([=]\r
- {\r
- transforms_.clear();\r
- blend_modes_.clear();\r
- }, high_priority);\r
- }\r
- \r
void set_blend_mode(int index, blend_mode::type value)\r
{\r
executor_.begin_invoke([=]\r
void mixer::send(const std::pair<std::map<int, safe_ptr<core::basic_frame>>, std::shared_ptr<void>>& frames){ impl_->send(frames);}\r
core::video_format_desc mixer::get_video_format_desc() const { return impl_->get_video_format_desc(); }\r
safe_ptr<core::write_frame> mixer::create_frame(const void* tag, const core::pixel_format_desc& desc){ return impl_->create_frame(tag, desc); } \r
-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);}\r
-void mixer::apply_frame_transform(int index, const std::function<core::frame_transform(core::frame_transform)>& transform, unsigned int mix_duration, const std::wstring& tween)\r
-{impl_->apply_transform(index, transform, mix_duration, tween);}\r
-void mixer::clear_transforms(int index){impl_->clear_transforms(index);}\r
-void mixer::clear_transforms(){impl_->clear_transforms();}\r
void mixer::set_blend_mode(int index, blend_mode::type value){impl_->set_blend_mode(index, value);}\r
void mixer::set_video_format_desc(const video_format_desc& format_desc){impl_->set_video_format_desc(format_desc);}\r
boost::unique_future<boost::property_tree::wptree> mixer::info() const{return impl_->info();}\r
\r
core::video_format_desc get_video_format_desc() const; // nothrow\r
void set_video_format_desc(const video_format_desc& format_desc);\r
-\r
- void set_frame_transform(int index, const core::frame_transform& transform, unsigned int mix_duration = 0, const std::wstring& tween = L"linear");\r
- void apply_frame_transform(int index, const std::function<frame_transform(frame_transform)>& transform, unsigned int mix_duration = 0, const std::wstring& tween = L"linear");\r
- void clear_transforms(int index);\r
- void clear_transforms();\r
-\r
+ \r
void set_blend_mode(int index, blend_mode::type value);\r
\r
boost::unique_future<boost::property_tree::wptree> info() const;\r
enum hints\r
{\r
NO_HINT = 0,\r
- ALPHA_HINT = 1\r
+ ALPHA_HINT = 1,\r
+ DEINTERLACE_HINT\r
};\r
\r
virtual ~frame_producer(){} \r
if(preview) // Play the first frame and pause.\r
{ \r
play();\r
- receive();\r
+ receive(frame_producer::NO_HINT);\r
pause();\r
}\r
}\r
is_paused_ = true;\r
}\r
\r
- safe_ptr<basic_frame> receive()\r
+ safe_ptr<basic_frame> receive(int hints)\r
{ \r
try\r
{\r
if(is_paused_)\r
return disable_audio(foreground_->last_frame());\r
\r
- auto frame = receive_and_follow(foreground_, frame_producer::NO_HINT);\r
+ auto frame = receive_and_follow(foreground_, hints);\r
if(frame == core::basic_frame::late())\r
return foreground_->last_frame();\r
\r
if(auto_play_delta_ > -1 && frames_left < 1)\r
{\r
play();\r
- return receive();\r
+ return receive(hints);\r
}\r
\r
return frame;\r
void layer::stop(){impl_->stop();}\r
bool layer::is_paused() const{return impl_->is_paused_;}\r
int64_t layer::frame_number() const{return impl_->frame_number_;}\r
-safe_ptr<basic_frame> layer::receive() {return impl_->receive();}\r
+safe_ptr<basic_frame> layer::receive(int hints) {return impl_->receive(hints);}\r
safe_ptr<frame_producer> layer::foreground() const { return impl_->foreground_;}\r
safe_ptr<frame_producer> layer::background() const { return impl_->background_;}\r
bool layer::empty() const {return impl_->empty();}\r
safe_ptr<frame_producer> foreground() const; // nothrow\r
safe_ptr<frame_producer> background() const; // nothrow\r
\r
- safe_ptr<basic_frame> receive(); // nothrow\r
+ safe_ptr<basic_frame> receive(int hints); // nothrow\r
\r
boost::property_tree::wptree info() const;\r
private:\r
\r
#include <common/concurrency/executor.h>\r
\r
+#include <core/producer/frame/frame_transform.h>\r
+\r
#include <boost/foreach.hpp>\r
#include <boost/timer.hpp>\r
\r
#include <map>\r
\r
namespace caspar { namespace core {\r
+ \r
+template<typename T>\r
+class tweened_transform\r
+{\r
+ T source_;\r
+ T dest_;\r
+ int duration_;\r
+ int time_;\r
+ tweener_t tweener_;\r
+public: \r
+ tweened_transform()\r
+ : duration_(0)\r
+ , time_(0)\r
+ , tweener_(get_tweener(L"linear")){}\r
+ tweened_transform(const T& source, const T& dest, int duration, const std::wstring& tween = L"linear")\r
+ : source_(source)\r
+ , dest_(dest)\r
+ , duration_(duration)\r
+ , time_(0)\r
+ , tweener_(get_tweener(tween)){}\r
+ \r
+ T fetch()\r
+ {\r
+ return time_ == duration_ ? dest_ : tween(static_cast<double>(time_), source_, dest_, static_cast<double>(duration_), tweener_);\r
+ }\r
+\r
+ T fetch_and_tick(int num)\r
+ { \r
+ time_ = std::min(time_+num, duration_);\r
+ return fetch();\r
+ }\r
+};\r
\r
struct stage::implementation : public std::enable_shared_from_this<implementation>\r
, boost::noncopyable\r
boost::timer tick_timer_;\r
\r
std::map<int, layer> layers_; \r
+ std::map<int, tweened_transform<core::frame_transform>> transforms_; \r
\r
executor executor_;\r
public:\r
\r
tbb::parallel_for_each(layers_.begin(), layers_.end(), [&](std::map<int, layer>::value_type& layer) \r
{\r
- frames[layer.first] = layer.second.receive(); \r
+ auto transform = transforms_[layer.first].fetch_and_tick(1);\r
+\r
+ int hints = frame_producer::NO_HINT;\r
+ if(format_desc_.field_mode != field_mode::progressive)\r
+ {\r
+ hints |= std::abs(transform.fill_scale[1] - 1.0) > 0.0001 ? frame_producer::DEINTERLACE_HINT : frame_producer::NO_HINT;\r
+ hints |= std::abs(transform.fill_translation[1]) > 0.0001 ? frame_producer::DEINTERLACE_HINT : frame_producer::NO_HINT;\r
+ }\r
+\r
+ if(transform.is_key)\r
+ hints |= frame_producer::ALPHA_HINT;\r
+\r
+ auto frame = layer.second.receive(hints); \r
+ \r
+ auto frame1 = make_safe<core::basic_frame>(frame);\r
+ frame1->get_frame_transform() = transform;\r
+\r
+ if(format_desc_.field_mode != core::field_mode::progressive)\r
+ { \r
+ auto frame2 = make_safe<core::basic_frame>(frame);\r
+ frame2->get_frame_transform() = transforms_[layer.first].fetch_and_tick(1);\r
+ frame1 = core::basic_frame::interlace(frame1, frame2, format_desc_.field_mode);\r
+ }\r
+\r
+ frames[layer.first] = frame1;\r
});\r
\r
graph_->update_value("produce-time", produce_timer_.elapsed()*format_desc_.fps*0.5);\r
CASPAR_LOG_CURRENT_EXCEPTION();\r
} \r
}\r
+ void set_transform(int index, const frame_transform& transform, unsigned int mix_duration, const std::wstring& tween)\r
+ {\r
+ executor_.begin_invoke([=]\r
+ {\r
+ auto src = transforms_[index].fetch();\r
+ auto dst = transform;\r
+ transforms_[index] = tweened_transform<frame_transform>(src, dst, mix_duration, tween);\r
+ }, high_priority);\r
+ }\r
+ \r
+ void apply_transform(int index, const std::function<frame_transform(frame_transform)>& transform, unsigned int mix_duration, const std::wstring& tween)\r
+ {\r
+ executor_.begin_invoke([=]\r
+ {\r
+ auto src = transforms_[index].fetch();\r
+ auto dst = transform(src);\r
+ transforms_[index] = tweened_transform<frame_transform>(src, dst, mix_duration, tween);\r
+ }, high_priority);\r
+ }\r
\r
+ void clear_transforms(int index)\r
+ {\r
+ executor_.begin_invoke([=]\r
+ {\r
+ transforms_.erase(index);\r
+ }, high_priority);\r
+ }\r
+\r
+ void clear_transforms()\r
+ {\r
+ executor_.begin_invoke([=]\r
+ {\r
+ transforms_.clear();\r
+ }, high_priority);\r
+ }\r
+ \r
void load(int index, const safe_ptr<frame_producer>& producer, bool preview, int auto_play_delta)\r
{\r
executor_.begin_invoke([=]\r
};\r
\r
stage::stage(const safe_ptr<diagnostics::graph>& graph, const safe_ptr<target_t>& target, const video_format_desc& format_desc) : impl_(new implementation(graph, target, format_desc)){}\r
+void stage::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);}\r
+void stage::apply_frame_transform(int index, const std::function<core::frame_transform(core::frame_transform)>& transform, unsigned int mix_duration, const std::wstring& tween){impl_->apply_transform(index, transform, mix_duration, tween);}\r
+void stage::clear_transforms(int index){impl_->clear_transforms(index);}\r
+void stage::clear_transforms(){impl_->clear_transforms();}\r
void stage::spawn_token(){impl_->spawn_token();}\r
void stage::load(int index, const safe_ptr<frame_producer>& producer, bool preview, int auto_play_delta){impl_->load(index, producer, preview, auto_play_delta);}\r
void stage::pause(int index){impl_->pause(index);}\r
#include <boost/property_tree/ptree_fwd.hpp>\r
#include <boost/thread/future.hpp>\r
\r
+#include <functional>\r
+\r
namespace caspar { namespace core {\r
\r
struct video_format_desc;\r
+struct frame_transform;\r
\r
class stage : boost::noncopyable\r
{\r
explicit stage(const safe_ptr<diagnostics::graph>& graph, const safe_ptr<target_t>& target, const video_format_desc& format_desc);\r
\r
// stage\r
+ \r
+ void set_frame_transform(int index, const frame_transform& transform, unsigned int mix_duration = 0, const std::wstring& tween = L"linear");\r
+ void apply_frame_transform(int index, const std::function<frame_transform(frame_transform)>& transform, unsigned int mix_duration = 0, const std::wstring& tween = L"linear");\r
+ void clear_transforms(int index);\r
+ void clear_transforms();\r
\r
void spawn_token();\r
\r
virtual safe_ptr<core::basic_frame> receive(int hints) override\r
{ \r
frame_timer_.restart();\r
+\r
+ // TODO: buffered frame is not deinterlaced.\r
+ muxer_->force_deinterlacing(hints == core::frame_producer::DEINTERLACE_HINT);\r
\r
for(int n = 0; n < 16 && frame_buffer_.size() < 2; ++n)\r
try_decode_frame(hints);\r
std::stringstream args;\r
args << frame->width << ":" << frame->height << ":" << frame->format << ":" << 0 << ":" << 0 << ":" << 0 << ":" << 0; // don't care about pts and aspect_ratio\r
THROW_ON_ERROR2(avfilter_graph_create_filter(&buffersrc_ctx_, avfilter_get_by_name("buffer"), "src", args.str().c_str(), NULL, graph_.get()), "[filter]");\r
-
+ \r
#if FF_API_OLD_VSINK_API\r
THROW_ON_ERROR2(avfilter_graph_create_filter(&buffersink_ctx_, avfilter_get_by_name("buffersink"), "out", NULL, pix_fmts_.data(), graph_.get()), "[filter]");\r
#else\r
filter& filter::operator=(filter&& other){impl_ = std::move(other.impl_); return *this;}\r
void filter::push(const std::shared_ptr<AVFrame>& frame){impl_->push(frame);}\r
std::shared_ptr<AVFrame> filter::poll(){return impl_->poll();}\r
-std::string filter::filter_str() const{return impl_->filters_;}\r
+std::wstring filter::filter_str() const{return widen(impl_->filters_);}\r
std::vector<safe_ptr<AVFrame>> filter::poll_all()\r
{ \r
std::vector<safe_ptr<AVFrame>> frames;\r
if(boost::to_upper_copy(filters).find(L"YADIF") != std::string::npos)\r
return true; \r
return false;\r
+} \r
+ \r
+static int filter_delay(const std::wstring& filters)\r
+{\r
+ if(is_double_rate(filters))\r
+ return 1;\r
+ \r
+ return 0;\r
}\r
\r
static std::wstring append_filter(const std::wstring& filters, const std::wstring& filter)\r
std::shared_ptr<AVFrame> poll();\r
std::vector<safe_ptr<AVFrame>> poll_all();\r
\r
- std::string filter_str() const;\r
+ std::wstring filter_str() const;\r
\r
private:\r
struct implementation;\r
\r
#include <boost/foreach.hpp>\r
#include <boost/range/algorithm_ext/push_back.hpp>\r
+#include <boost/algorithm/string/predicate.hpp>\r
\r
#include <deque>\r
#include <queue>\r
const double in_fps_;\r
const video_format_desc format_desc_;\r
bool auto_transcode_;\r
+ bool auto_deinterlace_;\r
\r
std::vector<size_t> audio_cadence_;\r
-\r
- size_t audio_sample_count_;\r
- size_t video_frame_count_;\r
- \r
+ \r
safe_ptr<core::frame_factory> frame_factory_;\r
\r
filter filter_;\r
- std::wstring filter_str_;\r
+ const std::wstring filter_str_;\r
+ bool force_deinterlacing_;\r
\r
implementation(double in_fps, const safe_ptr<core::frame_factory>& frame_factory, const std::wstring& filter_str)\r
: display_mode_(display_mode::invalid)\r
, in_fps_(in_fps)\r
, format_desc_(frame_factory->get_video_format_desc())\r
, auto_transcode_(env::properties().get("configuration.auto-transcode", true))\r
+ , auto_deinterlace_(env::properties().get("configuration.auto-deinterlace", true))\r
, audio_cadence_(format_desc_.audio_cadence)\r
- , audio_sample_count_(0)\r
- , video_frame_count_(0)\r
, frame_factory_(frame_factory)\r
, filter_str_(filter_str)\r
+ , force_deinterlacing_(false)\r
{\r
video_streams_.push(std::queue<safe_ptr<write_frame>>());\r
audio_streams_.push(core::audio_buffer());\r
\r
if(video_frame == flush_video())\r
{ \r
- video_frame_count_ = 0;\r
video_streams_.push(std::queue<safe_ptr<write_frame>>());\r
}\r
else if(video_frame == empty_video())\r
{\r
video_streams_.back().push(make_safe<core::write_frame>(this));\r
- ++video_frame_count_;\r
display_mode_ = display_mode::simple;\r
}\r
else\r
{\r
if(display_mode_ == display_mode::invalid)\r
- initialize_display_mode(*video_frame);\r
+ update_display_mode(video_frame);\r
\r
if(hints & core::frame_producer::ALPHA_HINT)\r
video_frame->format = make_alpha_format(video_frame->format);\r
av_frame->format = format;\r
\r
video_streams_.back().push(make_write_frame(this, av_frame, frame_factory_, hints));\r
- ++video_frame_count_;\r
}\r
}\r
\r
\r
if(audio == flush_audio())\r
{\r
- audio_sample_count_ = 0;\r
audio_streams_.push(core::audio_buffer());\r
}\r
else if(audio == empty_audio())\r
{\r
boost::range::push_back(audio_streams_.back(), core::audio_buffer(audio_cadence_.front(), 0));\r
- audio_sample_count_ += audio->size();\r
}\r
else\r
{\r
boost::range::push_back(audio_streams_.back(), *audio);\r
- audio_sample_count_ += audio->size();\r
}\r
\r
if(audio_streams_.back().size() > 32*audio_cadence_.front())\r
return samples;\r
}\r
\r
- void initialize_display_mode(const AVFrame& frame)\r
+ void update_display_mode(const std::shared_ptr<AVFrame>& frame)\r
{\r
+ std::wstring filter_str = filter_str_;\r
+\r
display_mode_ = display_mode::simple;\r
if(auto_transcode_)\r
{\r
- auto mode = get_mode(frame);\r
+ auto mode = get_mode(*frame);\r
auto fps = in_fps_;\r
\r
if(is_deinterlacing(filter_str_))\r
\r
display_mode_ = get_display_mode(mode, fps, format_desc_.field_mode, format_desc_.fps);\r
\r
- if((frame.height != 480 || format_desc_.height != 486) && \r
- display_mode_ == display_mode::simple && mode != core::field_mode::progressive && format_desc_.field_mode != core::field_mode::progressive && \r
- frame.height != static_cast<int>(format_desc_.height))\r
+ if(force_deinterlacing_ || \r
+ ((frame->height != 480 || format_desc_.height != 486) && \r
+ display_mode_ == display_mode::simple && mode != core::field_mode::progressive && format_desc_.field_mode != core::field_mode::progressive && \r
+ frame->height != static_cast<int>(format_desc_.height)))\r
{\r
display_mode_ = display_mode::deinterlace_bob_reinterlace; // The frame will most likely be scaled, we need to deinterlace->reinterlace \r
}\r
\r
if(display_mode_ == display_mode::deinterlace)\r
- filter_str_ = append_filter(filter_str_, L"YADIF=0:-1");\r
+ filter_str = append_filter(filter_str, L"YADIF=0:-1");\r
else if(display_mode_ == display_mode::deinterlace_bob || display_mode_ == display_mode::deinterlace_bob_reinterlace)\r
- filter_str_ = append_filter(filter_str_, L"YADIF=1:-1");\r
+ filter_str = append_filter(filter_str, L"YADIF=1:-1");\r
}\r
\r
if(display_mode_ == display_mode::invalid)\r
display_mode_ = display_mode::simple;\r
}\r
\r
- filter_ = filter(filter_str_);\r
+ if(!boost::iequals(filter_.filter_str(), filter_str))\r
+ {\r
+ for(int n = 0; n < filter_delay(filter_.filter_str()); ++n)\r
+ {\r
+ filter_.push(frame);\r
+ auto av_frame = filter_.poll();\r
+ if(av_frame) \r
+ video_streams_.back().push(make_write_frame(this, make_safe_ptr(av_frame), frame_factory_, 0));\r
+ }\r
+ filter_ = filter(filter_str);\r
+ CASPAR_LOG(info) << "[frame_muxer] " << display_mode::print(display_mode_) << L" " << print_mode(frame->width, frame->height, in_fps_, frame->interlaced_frame > 0);\r
+ }\r
+ }\r
+\r
+ void force_deinterlacing(bool value)\r
+ {\r
+ if(!auto_deinterlace_ || value == force_deinterlacing_)\r
+ return;\r
\r
- CASPAR_LOG(info) << "[frame_muxer] " << display_mode::print(display_mode_) << L" " << print_mode(frame.width, frame.height, in_fps_, frame.interlaced_frame > 0);\r
+ force_deinterlacing_ = value;\r
+ display_mode_ = display_mode::invalid;\r
}\r
\r
int64_t calc_nb_frames(int64_t nb_frames) const\r
int64_t frame_muxer::calc_nb_frames(int64_t nb_frames) const {return impl_->calc_nb_frames(nb_frames);}\r
bool frame_muxer::video_ready() const{return impl_->video_ready();}\r
bool frame_muxer::audio_ready() const{return impl_->audio_ready();}\r
+void frame_muxer::force_deinterlacing(bool value){impl_->force_deinterlacing(value);}\r
\r
}}
\ No newline at end of file
\r
int64_t calc_nb_frames(int64_t nb_frames) const;\r
\r
+ void force_deinterlacing(bool value);\r
+\r
private:\r
struct implementation;\r
safe_ptr<implementation> impl_;\r
};\r
\r
int layer = GetLayerIndex();\r
- GetChannel()->mixer()->apply_frame_transform(GetLayerIndex(), transform);\r
+ GetChannel()->stage()->apply_frame_transform(GetLayerIndex(), transform);\r
}\r
else if(_parameters[0] == L"OPACITY")\r
{\r
};\r
\r
int layer = GetLayerIndex();\r
- GetChannel()->mixer()->apply_frame_transform(GetLayerIndex(), transform, duration, tween);\r
+ GetChannel()->stage()->apply_frame_transform(GetLayerIndex(), transform, duration, tween);\r
}\r
else if(_parameters[0] == L"FILL" || _parameters[0] == L"FILL_RECT")\r
{\r
};\r
\r
int layer = GetLayerIndex();\r
- GetChannel()->mixer()->apply_frame_transform(GetLayerIndex(), transform, duration, tween);\r
+ GetChannel()->stage()->apply_frame_transform(GetLayerIndex(), transform, duration, tween);\r
}\r
else if(_parameters[0] == L"CLIP" || _parameters[0] == L"CLIP_RECT")\r
{\r
};\r
\r
int layer = GetLayerIndex();\r
- GetChannel()->mixer()->apply_frame_transform(GetLayerIndex(), transform, duration, tween);\r
+ GetChannel()->stage()->apply_frame_transform(GetLayerIndex(), transform, duration, tween);\r
}\r
else if(_parameters[0] == L"GRID")\r
{\r
transform.clip_scale[1] = delta; \r
return transform;\r
};\r
- GetChannel()->mixer()->apply_frame_transform(index, transform, duration, tween);\r
+ GetChannel()->stage()->apply_frame_transform(index, transform, duration, tween);\r
}\r
}\r
}\r
};\r
\r
int layer = GetLayerIndex();\r
- GetChannel()->mixer()->apply_frame_transform(GetLayerIndex(), transform, duration, tween); \r
+ GetChannel()->stage()->apply_frame_transform(GetLayerIndex(), transform, duration, tween); \r
}\r
else if(_parameters[0] == L"SATURATION")\r
{\r
};\r
\r
int layer = GetLayerIndex();\r
- GetChannel()->mixer()->apply_frame_transform(GetLayerIndex(), transform, duration, tween); \r
+ GetChannel()->stage()->apply_frame_transform(GetLayerIndex(), transform, duration, tween); \r
}\r
else if(_parameters[0] == L"CONTRAST")\r
{\r
};\r
\r
int layer = GetLayerIndex();\r
- GetChannel()->mixer()->apply_frame_transform(GetLayerIndex(), transform, duration, tween); \r
+ GetChannel()->stage()->apply_frame_transform(GetLayerIndex(), transform, duration, tween); \r
}\r
else if(_parameters[0] == L"LEVELS")\r
{\r
};\r
\r
int layer = GetLayerIndex();\r
- GetChannel()->mixer()->apply_frame_transform(GetLayerIndex(), transform, duration, tween); \r
+ GetChannel()->stage()->apply_frame_transform(GetLayerIndex(), transform, duration, tween); \r
}\r
else if(_parameters[0] == L"VOLUME")\r
{\r
};\r
\r
int layer = GetLayerIndex();\r
- GetChannel()->mixer()->apply_frame_transform(GetLayerIndex(), transform, duration, tween);\r
+ GetChannel()->stage()->apply_frame_transform(GetLayerIndex(), transform, duration, tween);\r
}\r
else if(_parameters[0] == L"CLEAR")\r
{\r
int layer = GetLayerIndex(std::numeric_limits<int>::max());\r
if(layer == std::numeric_limits<int>::max())\r
- GetChannel()->mixer()->clear_transforms();\r
+ GetChannel()->stage()->clear_transforms();\r
else\r
- GetChannel()->mixer()->clear_transforms(layer);\r
+ GetChannel()->stage()->clear_transforms(layer);\r
}\r
else\r
{\r
</paths>\r
<channels>\r
<channel>\r
- <video-mode>720p5000</video-mode>\r
+ <video-mode>PAL</video-mode>\r
<consumers>\r
- <screen>\r
- <device>2</device>\r
- </screen>\r
- <system-audio></system-audio>\r
+ <decklink>\r
+ <embedded-audio>true</embedded-audio>\r
+ </decklink>\r
</consumers>\r
</channel>\r
</channels>\r