Exemplo n.º 1
0
	~print_producer_proxy()
	{		
		auto str = producer_->print();
		CASPAR_LOG(trace) << str << L" Uninitializing.";
		producer_.reset();
		CASPAR_LOG(info) << str << L" Uninitialized.";
	}
Exemplo n.º 2
0
	void wait(ogl_device& ogl)
	{	
		int delay = 0;
		if(!ogl.invoke([this]{return ready();}, high_priority))
		{
			while(!ogl.invoke([this]{return ready();}, normal_priority) && delay < 20)
			{
				delay += 2;
				Sleep(2);
			}
		}
		
		static tbb::atomic<size_t> count;
		static tbb::atomic<bool> warned;
		
		if(delay > 2 && ++count > 50)
		{
			if(!warned.fetch_and_store(true))
			{
				CASPAR_LOG(warning) << L"[fence] Performance warning. GPU was not ready during requested host read-back. Delayed by atleast: " << delay << L" ms. Further warnings are sent to trace log level."
									<< L" You can ignore this warning if you do not notice any problems with output video. This warning is caused by insufficent support or performance of your graphics card for OpenGL based memory transfers. "
									<< L" Please try to update your graphics drivers or update your graphics card, see recommendations on (www.casparcg.com)."
									<< L" Further help is available at (www.casparcg.com/forum).";
			}
			else
				CASPAR_LOG(trace) << L"[fence] Performance warning. GPU was not ready during requested host read-back. Delayed by atleast: " << delay << L" ms.";
		}
	}
Exemplo n.º 3
0
	void execute(const safe_ptr<read_frame>& frame)
	{			
		if(!has_synchronization_clock())
			timer_.tick(1.0/channel_.get_format_desc().fps);

		if(frame->image_size() != channel_.get_format_desc().size)
		{
			timer_.tick(1.0/channel_.get_format_desc().fps);
			return;
		}
		
		auto it = consumers_.begin();
		while(it != consumers_.end())
		{
			auto consumer = it->second;

			if(consumer->get_video_format_desc() != channel_.get_format_desc())
				consumer->initialize(channel_.get_format_desc());

			try
			{
				if(consumer->send(frame))
					++it;
				else
					consumers_.erase(it++);
			}
			catch(...)
			{
				CASPAR_LOG_CURRENT_EXCEPTION();
				CASPAR_LOG(warning) << "Trying to restart consumer: " << consumer->print() << L".";
				try
				{
					consumer->initialize(channel_.get_format_desc());
					consumer->send(frame);
				}
				catch(...)
				{	
					CASPAR_LOG_CURRENT_EXCEPTION();	
					CASPAR_LOG(warning) << "Consumer restart failed, trying to restart channel: " << consumer->print() << L".";	

					try
					{
						restart_channel_();
						consumer->initialize(channel_.get_format_desc());
						consumer->send(frame);
					}
					catch(...)
					{
						CASPAR_LOG_CURRENT_EXCEPTION();
						CASPAR_LOG(error) << "Failed to recover consumer: " << consumer->print() << L". Removing it.";
						consumers_.erase(it++);
					}
				}
			}
		}
	}
Exemplo n.º 4
0
spl::shared_ptr<shader> get_image_shader(bool& blend_modes)
{
	tbb::mutex::scoped_lock lock(g_shader_mutex);

	if(g_shader)
	{
		blend_modes = g_blend_modes;
		return spl::make_shared_ptr(g_shader);
	}
		
	try
	{				
		g_blend_modes  = glTextureBarrierNV ? env::properties().get(L"configuration.blend-modes", true) : false;
		g_shader.reset(new shader(get_vertex(), get_fragment(g_blend_modes)));
	}
	catch(...)
	{
		CASPAR_LOG_CURRENT_EXCEPTION();
		CASPAR_LOG(warning) << "Failed to compile shader. Trying to compile without blend-modes.";
				
		g_blend_modes = false;
		g_shader.reset(new shader(get_vertex(), get_fragment(g_blend_modes)));
	}
						
	//if(!g_blend_modes)
	//{
	//	ogl.blend_func(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
	//	CASPAR_LOG(info) << L"[shader] Blend-modes are disabled.";
	//}

	blend_modes = g_blend_modes;
	return spl::make_shared_ptr(g_shader);
}
Exemplo n.º 5
0
	implementation(size_t output_channels, size_t input_channels, size_t output_sample_rate, size_t input_sample_rate, AVSampleFormat output_sample_format, AVSampleFormat input_sample_format)
		: output_channels_(output_channels)
		, output_sample_format_(output_sample_format)
		, input_channels_(input_channels)
		, input_sample_format_(input_sample_format)
	{
		if(input_channels		!= output_channels || 
		   input_sample_rate	!= output_sample_rate ||
		   input_sample_format	!= output_sample_format)
		{	
			auto resampler = av_audio_resample_init(output_channels,		input_channels,
													output_sample_rate,		input_sample_rate,
													output_sample_format,	input_sample_format,
													16, 10, 0, 0.8);

			buffer2_.resize(AVCODEC_MAX_AUDIO_FRAME_SIZE*2);

			char sample_fmt_string[200];
			av_get_sample_fmt_string(sample_fmt_string, 200, input_sample_format);

			CASPAR_LOG(warning) << L"[audio-resampler]"		
								<< L" sample-rate: "	<< input_sample_rate 
								<< L" channels: "		<< input_channels 
								<< L" sample-fmt: "		<< widen(sample_fmt_string);

			if(resampler)
				resampler_.reset(resampler, audio_resample_close);
			else
				BOOST_THROW_EXCEPTION(caspar_exception());
		}		
	}
Exemplo n.º 6
0
	void tick()
	{
		if(!window_)
			return;

		sf::Event e;
		while(window_->GetEvent(e))
		{
			if(e.Type == sf::Event::Closed)
			{
				window_.reset();
				return;
			}
		}		

		try
		{
			glClear(GL_COLOR_BUFFER_BIT);
			window_->Draw(*this);
			window_->Display();
			boost::this_thread::sleep(boost::posix_time::milliseconds(10));
		}
		catch (...)
		{
			CASPAR_LOG_CURRENT_EXCEPTION();
			CASPAR_LOG(error)
					<< L"Closing diag window due to error during rendering";
			window_.reset();
			return;
		}

		executor_.begin_invoke([this]{tick();});
	}
Exemplo n.º 7
0
	std::shared_ptr<AVFrame> decode(safe_ptr<AVPacket> pkt)
	{
		std::shared_ptr<AVFrame> decoded_frame(avcodec_alloc_frame(), av_free);

		int frame_finished = 0;
		THROW_ON_ERROR2(avcodec_decode_video2(codec_context_.get(), decoded_frame.get(), &frame_finished, pkt.get()), "[video_decoder]");
		
		// If a decoder consumes less then the whole packet then something is wrong
		// that might be just harmless padding at the end, or a problem with the
		// AVParser or demuxer which puted more then one frame in a AVPacket.

		if(frame_finished == 0)	
			return nullptr;

		is_progressive_ = !decoded_frame->interlaced_frame;

		if(decoded_frame->repeat_pict > 0)
			CASPAR_LOG(warning) << "[video_decoder] Field repeat_pict not implemented.";
		
		++file_frame_number_;

		// This ties the life of the decoded_frame to the packet that it came from. For the
		// current version of ffmpeg (0.8 or c17808c) the RAW_VIDEO codec returns frame data
		// owned by the packet.
		return std::shared_ptr<AVFrame>(decoded_frame.get(), [decoded_frame, pkt](AVFrame*){});
	}
Exemplo n.º 8
0
	~destroy_producer_proxy()
	{		
		static auto destroyers = std::make_shared<tbb::concurrent_bounded_queue<std::shared_ptr<executor>>>();
		static tbb::atomic<int> destroyer_count;

		try
		{
			std::shared_ptr<executor> destroyer;
			if(!destroyers->try_pop(destroyer))
			{
				destroyer.reset(new executor(L"destroyer"));
				destroyer->set_priority_class(below_normal_priority_class);
				if(++destroyer_count > 16)
					CASPAR_LOG(warning) << L"Potential destroyer dead-lock detected.";
				CASPAR_LOG(trace) << "Created destroyer: " << destroyer_count;
			}
				
			auto producer = producer_.release();
			auto pool	  = destroyers;
			destroyer->begin_invoke([=]
			{
				std::unique_ptr<std::shared_ptr<frame_producer>> producer2(producer);

				auto str = (*producer2)->print();
				try
				{
					if(!producer->unique())
						CASPAR_LOG(trace) << str << L" Not destroyed on asynchronous destruction thread: " << producer->use_count();
					else
						CASPAR_LOG(trace) << str << L" Destroying on asynchronous destruction thread.";
				}
				catch(...){}
								
				producer2.reset();
				pool->push(destroyer);
			}); 
		}
		catch(...)
		{
			CASPAR_LOG_CURRENT_EXCEPTION();
			try
			{
				producer_.reset();
			}
			catch(...){}
		}
	}
Exemplo n.º 9
0
	implementation(const safe_ptr<ogl_device>& ogl)
		: ogl_(ogl)
		, shader_(ogl_->invoke([&]{return get_image_shader(*ogl, blend_modes_, post_processing_);}))
		, supports_texture_barrier_(glTextureBarrierNV != 0)
	{
		if (!supports_texture_barrier_)
			CASPAR_LOG(warning) << L"[image_mixer] TextureBarrierNV not supported. Post processing will not be available";
	}
Exemplo n.º 10
0
safe_ptr<shader> get_image_shader(
		ogl_device& ogl, bool& blend_modes, bool& post_processing)
{
	tbb::mutex::scoped_lock lock(g_shader_mutex);

	if(g_shader)
	{
		blend_modes = g_blend_modes;
		post_processing = g_post_processing;

		return make_safe_ptr(g_shader);
	}
		
	bool chroma_key = env::properties().get(L"configuration.mixer.chroma-key", false);
	bool straight_alpha = env::properties().get(L"configuration.mixer.straight-alpha", false);
	g_post_processing = straight_alpha;

	try
	{				
		g_blend_modes  = glTextureBarrierNV ? env::properties().get(L"configuration.mixer.blend-modes", false) : false;
		g_shader.reset(new shader(get_vertex(), get_fragment(g_blend_modes, chroma_key, g_post_processing)));
	}
	catch(...)
	{
		CASPAR_LOG_CURRENT_EXCEPTION();
		CASPAR_LOG(warning) << "Failed to compile shader. Trying to compile without blend-modes.";
				
		g_blend_modes = false;
		g_shader.reset(new shader(get_vertex(), get_fragment(g_blend_modes, chroma_key, g_post_processing)));
	}
						
	ogl.enable(GL_TEXTURE_2D);

	if(!g_blend_modes)
	{
		ogl.enable(GL_BLEND);
		glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
		CASPAR_LOG(info) << L"[shader] Blend-modes are disabled.";
	}

	blend_modes = g_blend_modes;
	post_processing = g_post_processing;

	return make_safe_ptr(g_shader);
}
Exemplo n.º 11
0
	explicit channel_producer(const safe_ptr<frame_factory>& frame_factory, const safe_ptr<video_channel>& channel) 
		: frame_factory_(frame_factory)
		, consumer_(make_safe<channel_consumer>())
		, last_frame_(basic_frame::empty())
		, frame_number_(0)
	{
		channel->output()->add(consumer_);
		consumer_->block_until_first_frame_available();
		CASPAR_LOG(info) << print() << L" Initialized";
	}
Exemplo n.º 12
0
void AMCPCommandQueue::AddCommand(AMCPCommandPtr pNewCommand)
{
	{
		tbb::mutex::scoped_lock lock(mutex_);

		if(pNewCommand->GetScheduling() == ImmediatelyAndClear) {
			//Clears the queue, objects are deleted automatically
			commands_.clear();

			commands_.push_back(pNewCommand);
			CASPAR_LOG(info) << "Cleared queue and added command";
		}
		else {
			commands_.push_back(pNewCommand);
			CASPAR_LOG(info) << "Added command to end of queue";
		}
	}

	SetEvent(newCommandEvent_);
}
Exemplo n.º 13
0
	~oal_consumer()
	{
		is_running_ = false;
		input_.try_push(std::make_pair(std::shared_ptr<core::read_frame>(), std::make_shared<audio_buffer_16>()));
		input_.try_push(std::make_pair(std::shared_ptr<core::read_frame>(), std::make_shared<audio_buffer_16>()));
		Stop();
		input_.try_push(std::make_pair(std::shared_ptr<core::read_frame>(), std::make_shared<audio_buffer_16>()));
		input_.try_push(std::make_pair(std::shared_ptr<core::read_frame>(), std::make_shared<audio_buffer_16>()));

		CASPAR_LOG(info) << print() << L" Successfully Uninitialized.";	
	}
Exemplo n.º 14
0
    void failed_rearrange(const void* tag, const channel_layout& layout)
    {
        if (audio_streams_.find(tag) != audio_streams_.end())
            return; // We don't want to flood the logs.

        CASPAR_LOG(warning)
                << L"[audio_mixer] Could not satisfactory down/upmix from "
                << layout.name << L" to " << channel_layout_.name
                << L" because no mix config was found for "
                << layout.layout_type << L" => " << channel_layout_.layout_type
                << L". This might cause audio to be lost.";
    }
Exemplo n.º 15
0
	void remove(int index)
	{
		channel_.execution().invoke([&]
		{
			auto it = consumers_.find(index);
			if(it != consumers_.end())
			{
				CASPAR_LOG(info) << print() << L" " << it->second->print() << L" Removed.";
				consumers_.erase(it);
			}
		});
	}
Exemplo n.º 16
0
	explicit layer_producer(const safe_ptr<frame_factory>& frame_factory, const safe_ptr<stage>& stage, int layer) 
		: frame_factory_(frame_factory)
		, stage_(stage)
		, consumer_(new layer_consumer())
		, last_frame_(basic_frame::empty())
		, frame_number_(0)
	{
		layer_ = layer;
		stage_->add_layer_consumer(this, layer_, consumer_);
		consumer_->block_until_first_frame_available();
		CASPAR_LOG(info) << print() << L" Initialized";
	}
Exemplo n.º 17
0
fence::fence() 
{
	static bool log_flag = false;

	if(GLEW_ARB_sync)
		impl_.reset(new implementation());
	else if(!log_flag)
	{
		CASPAR_LOG(warning) << "[fence] GL_SYNC not supported, running without fences. This might cause performance degradation when running multiple channels and short buffer depth.";
		log_flag = true;
	}
}
Exemplo n.º 18
0
void AMCPCommandQueue::Run(HANDLE stopEvent)
{
	bool logTemporarilyBadState = true;
	AMCPCommandPtr pCurrentCommand;

	CASPAR_LOG(info) << "AMCP CommandPump started";

	while(WaitForSingleObject(stopEvent, 0) != WAIT_OBJECT_0)
	{
		DWORD waitResult = WaitForSingleObject(newCommandEvent_, 50);
		if(waitResult == WAIT_OBJECT_0) 
		{
			tbb::mutex::scoped_lock lock(mutex_);

			if(commands_.size() > 0)
			{
				CASPAR_LOG(debug) << "Found " << commands_.size() << " commands in queue";

				AMCPCommandPtr pNextCommand = commands_.front();

				if(pCurrentCommand == 0 || pNextCommand->GetScheduling() == ImmediatelyAndClear) {
					pCurrentCommand = pNextCommand;
					commands_.pop_front();
				}
			}
		}

		if(pCurrentCommand != 0) 
		{
			try
			{
				if(pCurrentCommand->Execute()) 
					CASPAR_LOG(info) << "Executed command: " << pCurrentCommand->print();
				else 
					CASPAR_LOG(info) << "Failed to execute command: " << pCurrentCommand->print();
			}
			catch(...)
			{
				CASPAR_LOG_CURRENT_EXCEPTION();
				CASPAR_LOG(info) << "Failed to execute command:" << pCurrentCommand->print();
			}
				
			pCurrentCommand->SendReply();
			pCurrentCommand.reset();

			newCommandEvent_.Set();
			logTemporarilyBadState = true;

			CASPAR_LOG(info) << "Ready for a new command";
		}
	}

	CASPAR_LOG(info) << "CommandPump ended";
}
Exemplo n.º 19
0
	explicit separated_producer(const spl::shared_ptr<frame_producer>& fill, const spl::shared_ptr<frame_producer>& key) 
		: key_event_subject_("keyer")		
		, fill_producer_(fill)
		, key_producer_(key)
		, fill_(core::draw_frame::late())
		, key_(core::draw_frame::late())
	{
		CASPAR_LOG(info) << print() << L" Initialized";

		key_event_subject_.subscribe(event_subject_);

		key_producer_->subscribe(key_event_subject_);
		fill_producer_->subscribe(event_subject_);
	}
Exemplo n.º 20
0
bool AMCPCommandQueue::OnUnhandledException(const std::exception& ex) throw() 
{
	bool bDoRestart = true;

	try 
	{
		CASPAR_LOG(fatal) << "UNHANDLED EXCEPTION in commandqueue. Message: " << ex.what();
	}
	catch(...)
	{
		bDoRestart = false;
	}

	return bDoRestart;
}
Exemplo n.º 21
0
    void send_to_flash(const std::wstring& data)
    {
        if (!clock_loaded_)
        {
            flash::get_default_cg_producer(channel_)->add(
                0, L"hawrysklocka/clock.ft", true, L"", data);
            clock_loaded_ = true;
        }
        else
        {
            flash::get_default_cg_producer(channel_)->update(0, data);
        }

        CASPAR_LOG(debug) << L"CLK: Clockdata sent: " << data;
    }
Exemplo n.º 22
0
LONG WINAPI UserUnhandledExceptionFilter(EXCEPTION_POINTERS* info)
{
    try
    {
        CASPAR_LOG(fatal) << L"#######################\n UNHANDLED EXCEPTION: \n"
                          << L"Adress:" << info->ExceptionRecord->ExceptionAddress << L"\n"
                          << L"Code:" << info->ExceptionRecord->ExceptionCode << L"\n"
                          << L"Flag:" << info->ExceptionRecord->ExceptionFlags << L"\n"
                          << L"Info:" << info->ExceptionRecord->ExceptionInformation << L"\n"
                          << L"Continuing execution. \n#######################";
    }
    catch(...) {}

    return EXCEPTION_EXECUTE_HANDLER;
}
Exemplo n.º 23
0
    void send_to_flash(const std::wstring& data)
    {
        if (!clock_loaded_) {
            core::frame_producer_dependencies dependencies(
                channel_->frame_factory(), channels_, channel_->video_format_desc(), producer_registry_, cg_registry_);
            cg_registry_
                ->get_or_create_proxy(channel_, dependencies, core::cg_proxy::DEFAULT_LAYER, L"hawrysklocka/clock")
                ->add(0, L"hawrysklocka/clock", true, L"", data);
            clock_loaded_ = true;
        } else {
            cg_registry_->get_proxy(channel_, core::cg_proxy::DEFAULT_LAYER)->update(0, data);
        }

        CASPAR_LOG(info) << L"CLK: Clockdata sent: " << data;
    }
Exemplo n.º 24
0
	void add(int index, safe_ptr<frame_consumer>&& consumer)
	{		
		channel_.execution().invoke([&]
		{
			consumers_.erase(index);
		});

		consumer->initialize(channel_.get_format_desc());

		channel_.execution().invoke([&]
		{
			consumers_.insert(std::make_pair(index, consumer));

			CASPAR_LOG(info) << print() << L" " << consumer->print() << L" Added.";
		});
	}
Exemplo n.º 25
0
	virtual void initialize(
			const core::video_format_desc& format_desc,
			const core::channel_layout& audio_channel_layout,
			int channel_index) override
	{
		format_desc_	= format_desc;		
		channel_index_	= channel_index;
		graph_->set_text(print());

		/*if (Status() != Playing)
		{
			sf::SoundStream::Initialize(2, format_desc_.audio_sample_rate);
		}*/

		CASPAR_LOG(info) << print() << " Sucessfully Initialized.";
	}
Exemplo n.º 26
0
	explicit image_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const std::wstring& filename) 
		: filename_(filename)
		, frame_(core::draw_frame::empty())	
	{
		auto bitmap = load_image(filename_);
		FreeImage_FlipVertical(bitmap.get());
		
		core::pixel_format_desc desc = core::pixel_format::bgra;
		desc.planes.push_back(core::pixel_format_desc::plane(FreeImage_GetWidth(bitmap.get()), FreeImage_GetHeight(bitmap.get()), 4));
		auto frame = frame_factory->create_frame(this, desc);

		std::copy_n(FreeImage_GetBits(bitmap.get()), frame.image_data(0).size(), frame.image_data(0).begin());
		frame_ = core::draw_frame(std::move(frame));

		CASPAR_LOG(info) << print() << L" Initialized";
	}
Exemplo n.º 27
0
void AMCPCommandQueue::AddCommand(AMCPCommandPtr pCurrentCommand)
{
	if(!pCurrentCommand)
		return;

	if(pCurrentCommand->GetScheduling() == ImmediatelyAndClear)
		executor_.clear();

	if(executor_.size() > 64)
	{
		try
		{
			CASPAR_LOG(error) << "AMCP Command Queue Overflow.";
			CASPAR_LOG(error) << "Failed to execute command:" << pCurrentCommand->print();
			pCurrentCommand->SetReplyString(L"500 FAILED\r\n");
			pCurrentCommand->SendReply();
		}
		catch(...)
		{
			CASPAR_LOG_CURRENT_EXCEPTION();
		}
	}
	
	executor_.begin_invoke([=]
	{
		try
		{
			try
			{
				if(pCurrentCommand->Execute()) 
					CASPAR_LOG(debug) << "Executed command: " << pCurrentCommand->print();
				else 
					CASPAR_LOG(warning) << "Failed to execute command: " << pCurrentCommand->print();
			}
			catch(...)
			{
				CASPAR_LOG_CURRENT_EXCEPTION();
				CASPAR_LOG(error) << "Failed to execute command:" << pCurrentCommand->print();
				pCurrentCommand->SetReplyString(L"500 FAILED\r\n");
			}
				
			pCurrentCommand->SendReply();
			
			CASPAR_LOG(trace) << "Ready for a new command";
		}
		catch(...)
		{
			CASPAR_LOG_CURRENT_EXCEPTION();
		}
	});
}
Exemplo n.º 28
0
	~ffmpeg_consumer()
	{    
		encode_executor_.stop_execute_rest();
		encode_executor_.join();

		// Flush
		LOG_ON_ERROR2(av_interleaved_write_frame(oc_.get(), nullptr), "[ffmpeg_consumer]");
		
		LOG_ON_ERROR2(av_write_trailer(oc_.get()), "[ffmpeg_consumer]");
		
		if (!key_only_)
			audio_st_.reset();
		video_st_.reset();
			  
		if (!(oc_->oformat->flags & AVFMT_NOFILE)) 
			LOG_ON_ERROR2(avio_close(oc_->pb), "[ffmpeg_consumer]"); // Close the output ffmpeg.

		CASPAR_LOG(info) << print() << L" Successfully Uninitialized.";	
	}
Exemplo n.º 29
0
safe_ptr<basic_frame> receive_and_follow(safe_ptr<frame_producer>& producer, int hints)
{	
	auto frame = producer->receive(hints);
	if(frame == basic_frame::eof())
	{
		CASPAR_LOG(info) << producer->print() << " End Of File.";
		auto following = producer->get_following_producer();
		if(following != frame_producer::empty())
		{
			following->set_leading_producer(producer);
			producer = std::move(following);
		}
		else
			producer = make_safe<last_frame_producer>(producer);

		return receive_and_follow(producer, hints);
	}
	return frame;
}
Exemplo n.º 30
0
	virtual boost::unique_future<bool> send(const safe_ptr<read_frame>& frame) override
	{		
		if(audio_cadence_.size() == 1)
			return consumer_->send(frame);

		boost::unique_future<bool> result = caspar::wrap_as_future(true);
		
		if(boost::range::equal(sync_buffer_, audio_cadence_) && audio_cadence_.front() * frame->num_channels() == static_cast<size_t>(frame->audio_data().size()))
		{	
			// Audio sent so far is in sync, now we can send the next chunk.
			result = consumer_->send(frame);
			boost::range::rotate(audio_cadence_, std::begin(audio_cadence_)+1);
		}
		else
			CASPAR_LOG(trace) << print() << L" Syncing audio.";

		sync_buffer_.push_back(static_cast<size_t>(frame->audio_data().size() / frame->num_channels()));
		
		return std::move(result);
	}