Пример #1
0
void *VideoStream::StreamingThreadCallback(void *ctx){
	
	Debug( 1, "StreamingThreadCallback started" );
	
    if (ctx == NULL) return NULL;

    VideoStream* videoStream = reinterpret_cast<VideoStream*>(ctx);
	
	const uint64_t nanosecond_multiplier = 1000000000;
	
	uint64_t target_interval_ns = nanosecond_multiplier * ( ((double)videoStream->ost->codec->time_base.num) / (videoStream->ost->codec->time_base.den) );
	uint64_t frame_count = 0;
	timespec start_time;
	clock_gettime(CLOCK_MONOTONIC, &start_time);
	uint64_t start_time_ns = (start_time.tv_sec*nanosecond_multiplier) + start_time.tv_nsec;
	while(videoStream->do_streaming)
	{
		timespec current_time;
		clock_gettime(CLOCK_MONOTONIC, &current_time);
		uint64_t current_time_ns = (current_time.tv_sec*nanosecond_multiplier) + current_time.tv_nsec;
		uint64_t target_ns = start_time_ns + (target_interval_ns * frame_count);
		
		if ( current_time_ns < target_ns )
		{
			// It's not time to render a frame yet.
			usleep( (target_ns - current_time_ns) * 0.001 );
		}
        
        // By sending the last rendered frame we deliver frames to the client more accurate.
        // If we're encoding the frame before sending it there will be lag.
        // Since this lag is not constant the client may skip frames.
        
        // Get the last rendered packet.
        AVPacket *packet = videoStream->packet_buffers[videoStream->packet_index];
        if (packet->size) {
            videoStream->SendPacket(packet);
        }
        av_free_packet(packet);
        videoStream->packet_index = videoStream->packet_index ? 0 : 1;
        
		// Lock buffer and render next frame.
        
		if ( pthread_mutex_lock( videoStream->buffer_copy_lock ) != 0 )
		{
			Fatal( "StreamingThreadCallback: pthread_mutex_lock failed." );
		}
		
		if ( videoStream->buffer_copy )
		{
			// Encode next frame.
			videoStream->ActuallyEncodeFrame( videoStream->buffer_copy, videoStream->buffer_copy_used, videoStream->add_timestamp, videoStream->timestamp );
		}
	
		if ( pthread_mutex_unlock( videoStream->buffer_copy_lock ) != 0 )
		{
			Fatal( "StreamingThreadCallback: pthread_mutex_unlock failed." );
		}
		
		frame_count++;
	}
	
	return 0;
}