Пример #1
0
	void tick(const std::weak_ptr<implementation>& self)
	{		
		try
		{
			produce_timer_.restart();

			std::map<int, safe_ptr<basic_frame>> frames;
		
			BOOST_FOREACH(auto& layer, layers_)			
				frames[layer.first] = basic_frame::empty();	

			tbb::parallel_for_each(layers_.begin(), layers_.end(), [&](std::map<int, layer>::value_type& layer) 
			{
				auto transform = transforms_[layer.first].fetch_and_tick(1);

				int hints = frame_producer::NO_HINT;
				if(format_desc_.field_mode != field_mode::progressive)
				{
					hints |= std::abs(transform.fill_scale[1]  - 1.0) > 0.0001 ? frame_producer::DEINTERLACE_HINT : frame_producer::NO_HINT;
					hints |= std::abs(transform.fill_translation[1]) > 0.0001 ? frame_producer::DEINTERLACE_HINT : frame_producer::NO_HINT;
				}

				if(transform.is_key)
					hints |= frame_producer::ALPHA_HINT;

				auto frame = layer.second.receive(hints);	
				
				auto frame1 = make_safe<core::basic_frame>(frame);
				frame1->get_frame_transform() = transform;

				if(format_desc_.field_mode != core::field_mode::progressive)
				{				
					auto frame2 = make_safe<core::basic_frame>(frame);
					frame2->get_frame_transform() = transforms_[layer.first].fetch_and_tick(1);
					frame1 = core::basic_frame::interlace(frame1, frame2, format_desc_.field_mode);
				}

				frames[layer.first] = frame1;
			});
			
			graph_->set_value("produce-time", produce_timer_.elapsed()*format_desc_.fps*0.5);
			
			std::shared_ptr<void> ticket(nullptr, [self](void*)
			{
				auto self2 = self.lock();
				if(self2)				
					self2->executor_.begin_invoke([=]{tick(self);});				
			});

			target_->send(std::make_pair(frames, ticket));

			graph_->set_value("tick-time", tick_timer_.elapsed()*format_desc_.fps*0.5);
			tick_timer_.restart();
		}
		catch(...)
		{
			layers_.clear();
			CASPAR_LOG_CURRENT_EXCEPTION();
		}		
	}
Пример #2
0
	safe_ptr<basic_frame> compose(const safe_ptr<basic_frame>& dest_frame, const safe_ptr<basic_frame>& src_frame) 
	{	
		if(info_.type == transition::cut)		
			return src_frame;
										
		const double delta1 = info_.tweener(current_frame_*2-1, 0.0, 1.0, info_.duration*2);
		const double delta2 = info_.tweener(current_frame_*2, 0.0, 1.0, info_.duration*2);  

		const double dir = info_.direction == transition_direction::from_left ? 1.0 : -1.0;		
		
		// For interlaced transitions. Seperate fields into seperate frames which are transitioned accordingly.
		
		auto s_frame1 = make_safe<basic_frame>(src_frame);
		auto s_frame2 = make_safe<basic_frame>(src_frame);

		s_frame1->get_frame_transform().volume = 0.0;
		s_frame2->get_frame_transform().volume = 1.0-delta2;

		auto d_frame1 = make_safe<basic_frame>(dest_frame);
		auto d_frame2 = make_safe<basic_frame>(dest_frame);
		
		d_frame1->get_frame_transform().volume = 0.0;
		d_frame2->get_frame_transform().volume = delta2;

		if(info_.type == transition::mix)
		{
			d_frame1->get_frame_transform().opacity = delta1;	
			d_frame1->get_frame_transform().is_mix = true;
			d_frame2->get_frame_transform().opacity = delta2;
			d_frame2->get_frame_transform().is_mix = true;

			s_frame1->get_frame_transform().opacity = 1.0-delta1;	
			s_frame1->get_frame_transform().is_mix = true;
			s_frame2->get_frame_transform().opacity = 1.0-delta2;	
			s_frame2->get_frame_transform().is_mix = true;
		}
		if(info_.type == transition::slide)
		{
			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_frame_transform().fill_translation[0] = (-1.0+delta1)*dir;
			d_frame2->get_frame_transform().fill_translation[0] = (-1.0+delta2)*dir;

			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_frame_transform().clip_scale[0] = delta1;	
			d_frame2->get_frame_transform().clip_scale[0] = delta2;			
		}
				
		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);

		return basic_frame::combine(s_frame, d_frame);
	}
Пример #3
0
	void tick(const std::weak_ptr<implementation>& self)
	{		
		try
		{
			produce_timer_.restart();

			std::map<int, safe_ptr<basic_frame>> frames; //fix g++ warning
			//std::map<int, std::shared_ptr<basic_frame>> frames;

			for(auto it = layers_.begin(); it != layers_.end(); ++it)
				frames[it->first] = make_safe<core::basic_frame>(basic_frame::empty());

			tbb::parallel_for_each(layers_.begin(), layers_.end(), [&](std::map<int, std::shared_ptr<layer>>::value_type& layer)
			{
				auto transform = transforms_[layer.first].fetch_and_tick(1);

				int hints = frame_producer::NO_HINT;
				if(format_desc_.field_mode != field_mode::progressive)
				{
					hints |= std::abs(transform.fill_scale[1]  - 1.0) > 0.0001 ? frame_producer::DEINTERLACE_HINT : frame_producer::NO_HINT;
					hints |= std::abs(transform.fill_translation[1]) > 0.0001 ? frame_producer::DEINTERLACE_HINT : frame_producer::NO_HINT;
				}

				if(transform.is_key)
					hints |= frame_producer::ALPHA_HINT;

				auto frame = layer.second->receive(hints);	
				auto layer_consumers_it = layer_consumers_.find(layer.first);
				if (layer_consumers_it != layer_consumers_.end())
				{
					auto consumer_it = (*layer_consumers_it).second | boost::adaptors::map_values;
					tbb::parallel_for_each(consumer_it.begin(), consumer_it.end(), [&](decltype(*consumer_it.begin()) layer_consumer) 
					{
						layer_consumer->send(frame);
					});
				}

				auto frame1 = make_safe<core::basic_frame>(frame);
				frame1->get_frame_transform() = transform;

				if(format_desc_.field_mode != core::field_mode::progressive)
				{				
					auto frame2 = make_safe<core::basic_frame>(frame);
					frame2->get_frame_transform() = transforms_[layer.first].fetch_and_tick(1);
					frame1 = core::basic_frame::interlace(frame1, frame2, format_desc_.field_mode);
				}

				frames[layer.first] = std::move(frame1);
			});

			// Tick the transforms that does not have a corresponding layer.
			BOOST_FOREACH(auto& elem, transforms_)
				if (layers_.find(elem.first) == layers_.end())
					elem.second.fetch_and_tick(format_desc_.field_mode != core::field_mode::progressive ? 2 : 1);
			
			graph_->set_value("produce-time", produce_timer_.elapsed()*format_desc_.fps*0.5);

			std::shared_ptr<void> ticket(nullptr, [=](void*)
			{
				auto self2 = self.lock();
				if(self2)				
					self2->executor_.begin_invoke([=]{tick(self);});
			});

			target_->send(std::make_pair(frames, ticket));
			//comment out due to g++ warning fix */

			graph_->set_value("tick-time", tick_timer_.elapsed()*format_desc_.fps*0.5);
			tick_timer_.restart();
		}
		catch(...)
		{
			layers_.clear();
			CASPAR_LOG_CURRENT_EXCEPTION();
		}		
	}