Exemple #1
0
void OutputManager::StartFragment() {

	// get fragment number
	unsigned int fragment_number = 0;
	if(m_fragmented) {
		SharedLock lock(&m_shared_data);
		fragment_number = lock->m_fragment_number;
	}

	// create new muxer and encoders
	// we can't hold the lock while doing this because this could take some time
	QString filename;
	if(m_fragmented) {
		filename = GetNewFragmentFile(m_output_settings.file, fragment_number);
	} else {
		filename = m_output_settings.file;
	}
	std::unique_ptr<Muxer> muxer(new Muxer(m_output_settings.container_avname, filename));
	VideoEncoder *video_encoder = NULL;
	AudioEncoder *audio_encoder = NULL;
	if(!m_output_settings.video_codec_avname.isEmpty())
		video_encoder = muxer->AddVideoEncoder(m_output_settings.video_codec_avname, m_output_settings.video_options, m_output_settings.video_kbit_rate * 1024,
											   m_output_settings.video_width, m_output_settings.video_height, m_output_settings.video_frame_rate);
	if(!m_output_settings.audio_codec_avname.isEmpty())
		audio_encoder = muxer->AddAudioEncoder(m_output_settings.audio_codec_avname, m_output_settings.audio_options, m_output_settings.audio_kbit_rate * 1024,
											   m_output_settings.audio_channels, m_output_settings.audio_sample_rate);
	muxer->Start();

	// acquire lock and share the muxer and encoders
	SharedLock lock(&m_shared_data);
	lock->m_muxer = std::move(muxer);
	lock->m_video_encoder = video_encoder;
	lock->m_audio_encoder = audio_encoder;

	// increment fragment number
	// It's important that this is done here (i.e. after the encoders have been set up), because the fragment number
	// acts as a signal to AddVideoFrame/AddAudioFrame that they can pass frames to the encoders.
	++lock->m_fragment_number;

	// push queued frames to the new encoders
	if(m_fragmented) {
		while(!lock->m_video_frame_queue.empty()) {
			int64_t fragment_begin = m_fragment_length * m_output_format.m_video_frame_rate * (lock->m_fragment_number - 1);
			int64_t fragment_end = m_fragment_length * m_output_format.m_video_frame_rate * lock->m_fragment_number;
			if(lock->m_video_frame_queue.front()->GetFrame()->pts >= fragment_end)
				break;
			std::unique_ptr<AVFrameWrapper> frame = std::move(lock->m_video_frame_queue.front());
			lock->m_video_frame_queue.pop_front();
			frame->GetFrame()->pts -= fragment_begin;
			video_encoder->AddFrame(std::move(frame));
		}
		while(!lock->m_audio_frame_queue.empty()) {
			int64_t fragment_begin = m_fragment_length * m_output_format.m_audio_sample_rate * (lock->m_fragment_number - 1);
			int64_t fragment_end = m_fragment_length * m_output_format.m_audio_sample_rate * lock->m_fragment_number;
			if(lock->m_audio_frame_queue.front()->GetFrame()->pts >= fragment_end)
				break;
			std::unique_ptr<AVFrameWrapper> frame = std::move(lock->m_audio_frame_queue.front());
			lock->m_audio_frame_queue.pop_front();
			frame->GetFrame()->pts -= fragment_begin;
			audio_encoder->AddFrame(std::move(frame));
		}
	}

}
void compressFile(string & file_name, string const & ref_file_name, const int num_workers, 
	bool seq_only, bool discard_secondary_alignments) {
	int dictionary_size = 1<<23;
	int match_len_limit = 36; // equivalent to -6 option

	// const int num_workers = num_threads - 1;//max(2, num_threads - 1); // one for parsing
	const int slots_per_worker = 20;
	const int num_slots =
		( ( num_workers > 1 ) ? num_workers * slots_per_worker : 1 );

	Packet_courier courier(num_workers, num_slots);

	// open output streams
	Output_args output_args = initializeOutputStreams(file_name, seq_only, discard_secondary_alignments, &courier);

	// cerr << "Initialized output streams" << endl;

	// from plzip library implementation
	// initialize parsing thread -- pass courier, FDs for output
	Parser_args parser_args;
	parser_args.output = output_args;
	parser_args.file_name = file_name;
	parser_args.ref_file_name = ref_file_name;
	parser_args.courier = &courier;
	parser_args.seq_only = seq_only;
	parser_args.discard_secondary_alignments = discard_secondary_alignments;

	pthread_t * parser_thread = new pthread_t();
	int errcode = pthread_create( parser_thread, 0, parseSAM, &parser_args );
	if ( errcode ) { 
		show_error( "Can't create parser thread", errcode ); cleanup_and_fail(); 
	}

	// initialize worker threads
	Worker_arg worker_arg;
	worker_arg.courier = &courier;
	worker_arg.dictionary_size = dictionary_size;
	worker_arg.match_len_limit = match_len_limit;

	pthread_t * worker_threads = new( std::nothrow ) pthread_t[num_workers];
	if( !worker_threads ) { 
		cleanup_and_fail(); 
	}
	for( int i = 0; i < num_workers; ++i ) {
		errcode = pthread_create( worker_threads + i, 0, cworker, &worker_arg );
		if( errcode ) { 
			show_error( "Can't create worker threads", errcode ); cleanup_and_fail(); 
		}
	}

	// cerr << "launched threads" << endl;

	// concurrently wait for threads to return compressed packets; write them to disk
	muxer(courier);

	// join worker threads
	for( int i = num_workers - 1; i >= 0; --i ) {
		errcode = pthread_join( worker_threads[i], 0 );
		if( errcode ) { 
			show_error( "Can't join worker threads", errcode ); cleanup_and_fail(); 
		}
		else {
			// cerr << "thread " << i << " joined" << endl;
		}
	}
	delete[] worker_threads;

	// join the parser thread
	errcode = pthread_join( *parser_thread, 0 );
	if( errcode ) {
		show_error( "Can't join parser thread", errcode ); cleanup_and_fail(); 
	}

	// destructor in OutputBuffer will close file output streams
};