class frame_producer_remover\r
{\r
executor executor_;\r
+ tbb::atomic<int> count_;\r
\r
void do_remove(safe_ptr<frame_producer>& producer)\r
{\r
- auto name = producer->print();\r
- CASPAR_LOG(info) << "removing: " << name;\r
producer = frame_producer::empty();\r
- CASPAR_LOG(info) << "removed: " << name;\r
+ CASPAR_LOG(info) << L"frame_remover[" + boost::lexical_cast<std::wstring>(--count_) + L"] removed: " << producer->print();\r
}\r
public:\r
\r
frame_producer_remover()\r
{\r
executor_.start();\r
+ count_ = 0;\r
}\r
\r
void remove(safe_ptr<frame_producer>&& producer)\r
{\r
CASPAR_ASSERT(producer.unique());\r
- CASPAR_ASSERT(executor_.empty());\r
+ CASPAR_LOG(info) << L"frame_remover[" + boost::lexical_cast<std::wstring>(++count_) + L"] removing: " << producer->print();\r
executor_.begin_invoke(std::bind(&frame_producer_remover::do_remove, this, std::move(producer)));\r
}\r
};\r
{\r
background_->set_leading_producer(foreground_);\r
foreground_ = background_;\r
+ CASPAR_LOG(info) << foreground_->print() << L" started";\r
background_ = frame_producer::empty();\r
}\r
is_paused_ = false;\r
following->set_leading_producer(foreground_);\r
g_remover.remove(std::move(foreground_));\r
foreground_ = following;\r
+ CASPAR_LOG(info) << foreground_->print() << L" started";\r
\r
last_frame_ = receive();\r
}\r
safe_ptr<frame_producer> source_producer_;\r
\r
std::shared_ptr<frame_factory> frame_factory_;\r
+ video_format_desc format_desc_;\r
+\r
+ std::vector<safe_ptr<draw_frame>> frame_buffer_;\r
\r
implementation(const safe_ptr<frame_producer>& dest, const transition_info& info) \r
: current_frame_(0)\r
, dest_producer_(dest)\r
, source_producer_(frame_producer::empty())\r
{\r
+ frame_buffer_.push_back(draw_frame::empty());\r
}\r
\r
void initialize(const safe_ptr<frame_factory>& frame_factory)\r
{\r
dest_producer_->initialize(frame_factory);\r
frame_factory_ = frame_factory;\r
+ format_desc_ = frame_factory_->get_video_format_desc();\r
}\r
\r
safe_ptr<frame_producer> get_following_producer() const\r
{\r
CASPAR_LOG_CURRENT_EXCEPTION();\r
producer = frame_producer::empty();\r
- CASPAR_LOG(warning) << "Failed to receive frame. Removed producer from transition.";\r
+ CASPAR_LOG(warning) << print() << " Failed to receive frame. Removed producer from transition.";\r
}\r
\r
if(frame == draw_frame::eof())\r
{\r
CASPAR_LOG_CURRENT_EXCEPTION();\r
producer = frame_producer::empty();\r
- CASPAR_LOG(warning) << "Failed to initialize following producer.";\r
+ CASPAR_LOG(warning) << print() << " Failed to initialize following producer.";\r
}\r
\r
return render_sub_frame(producer);\r
return src_frame != draw_frame::eof() ? src_frame : draw_frame::empty();\r
\r
double alpha = static_cast<double>(current_frame_)/static_cast<double>(info_.duration);\r
+ double half_alpha_step = 0.5*1.0/static_cast<double>(info_.duration);\r
+ \r
+ double dir = info_.direction == transition_direction::from_left ? 1.0 : -1.0; \r
+ \r
+ // For interalced transitions; seperate fields into seperate frames which are transitioned accordingly.\r
\r
- auto my_src_frame = draw_frame(src_frame);\r
- auto my_dest_frame = draw_frame(dest_frame);\r
+ auto s_frame1 = make_safe<draw_frame>(src_frame);\r
+ auto s_frame2 = make_safe<draw_frame>(src_frame);\r
\r
- my_src_frame.get_audio_transform().set_gain(1.0-alpha);\r
- my_dest_frame.get_audio_transform().set_gain(alpha);\r
+ s_frame1->get_audio_transform().set_gain(0);\r
+ s_frame2->get_audio_transform().set_gain(1.0-alpha);\r
\r
- double dir = info_.direction == transition_direction::from_left ? 1.0 : -1.0; \r
+ auto d_frame1 = make_safe<draw_frame>(dest_frame);\r
+ auto d_frame2 = make_safe<draw_frame>(dest_frame);\r
\r
+ d_frame1->get_audio_transform().set_gain(0);\r
+ d_frame2->get_audio_transform().set_gain(alpha);\r
+\r
if(info_.type == transition::mix)\r
- my_dest_frame.get_image_transform().set_opacity(alpha); \r
- else if(info_.type == transition::slide) \r
- my_dest_frame.get_image_transform().set_image_translation((-1.0+alpha)*dir, 0.0); \r
+ {\r
+ d_frame1->get_image_transform().set_opacity(alpha-half_alpha_step); \r
+ d_frame2->get_image_transform().set_opacity(alpha); \r
+ }\r
+ else if(info_.type == transition::slide)\r
+ {\r
+ d_frame1->get_image_transform().set_image_translation((-1.0+alpha-half_alpha_step)*dir, 0.0); \r
+ d_frame2->get_image_transform().set_image_translation((-1.0+alpha)*dir, 0.0); \r
+ }\r
else if(info_.type == transition::push)\r
{\r
- my_dest_frame.get_image_transform().set_image_translation((-1.0+alpha)*dir, 0.0);\r
- my_src_frame.get_image_transform().set_image_translation((0.0+alpha)*dir, 0.0); \r
+ d_frame1->get_image_transform().set_image_translation((-1.0+alpha-half_alpha_step)*dir, 0.0);\r
+ d_frame2->get_image_transform().set_image_translation((-1.0+alpha)*dir, 0.0);\r
+\r
+ s_frame1->get_image_transform().set_image_translation((0.0+alpha-half_alpha_step)*dir, 0.0); \r
+ s_frame2->get_image_transform().set_image_translation((0.0+alpha)*dir, 0.0); \r
}\r
else if(info_.type == transition::wipe) \r
- my_dest_frame.get_image_transform().set_mask_scale(alpha, 1.0); \r
-\r
- return draw_frame(std::move(my_src_frame), std::move(my_dest_frame));\r
+ {\r
+ d_frame1->get_image_transform().set_mask_scale(alpha-half_alpha_step, 1.0); \r
+ d_frame2->get_image_transform().set_mask_scale(alpha, 1.0); \r
+ }\r
+ \r
+ return draw_frame(draw_frame::interlace(s_frame1, s_frame2, format_desc_.mode), draw_frame::interlace(d_frame1, d_frame2, format_desc_.mode));\r
}\r
\r
std::wstring print() const\r
{\r
- return L"transition[" + (dest_producer_->print()) + L"]";\r
+ return L"transition[" + source_producer_->print() + L"->" + dest_producer_->print() + L"]";\r
}\r
};\r
\r