Ejemplo n.º 1
0
//cette fonction est un thread, ne pas l'appeler !
void* video_routine(void* args) {
	ssize_t pack_size = 0;
	int nb_img = 0;
	pthread_mutex_lock(&mutex_stopped);
	while(!stopped) {
		pthread_mutex_unlock(&mutex_stopped);
		//Wait for the drone to send data on the video socket
		if (select(sock_video+1, &vid_fd_set, NULL, NULL, &video_timeout) < 0) {
			perror("Error select()");
			video_set_stopped();
		}
		else if(FD_ISSET(sock_video, &vid_fd_set)) {

			/*receive the video data from the drone. Only BASE_SIZE, since
			TCP_SIZE may be larger on purpose.*/
			pack_size = recv(sock_video, tcp_buf, BASE_VIDEO_BUF_SIZE, 0);
			if(pack_size == 0) {
				printf("Stream ended by server. Ending the video thread.\n");
				video_set_stopped();
			}
			else if(pack_size < 0)
				perror("Error recv()");
			else {
				//we actually got some data, send it for decoding !
				nb_img = video_decode_packet(tcp_buf, pack_size);
				if(nb_img < 0) {
					fprintf(stderr, "Error processing frame !\n");
					video_set_stopped();
				}
			}
		}
		else {
			printf("Video : data reception has timed out. Ending the video thread now.\n");
			video_set_stopped();
		}
		//reset the timeout and the FDSET entry
		video_timeout.tv_sec = VIDEO_TIMEOUT;
		FD_ZERO(&vid_fd_set);
		FD_SET(sock_video, &vid_fd_set);

		pthread_mutex_lock(&mutex_stopped);
	}
	pthread_mutex_unlock(&mutex_stopped);
	//there's no reason to keep stuff that's needed for our video thread once it's ended, so clean it now.
	video_clean();
	pthread_mutex_lock(&mutex_terminated);
	terminated = 1;
	printf("Video thread terminated.\n");
	pthread_mutex_unlock(&mutex_terminated);
	pthread_exit(NULL);
}
Ejemplo n.º 2
0
int jakopter_init_video() {
	pthread_mutex_lock(&mutex_init);
	//do not try to initialize the thread if it's already running !
	pthread_mutex_lock(&mutex_terminated);
	if(!terminated) {
		pthread_mutex_unlock(&mutex_terminated);
		fprintf(stderr, "Video thread already running.\n");
		pthread_mutex_unlock(&mutex_init);
		return -1;
	}
	pthread_mutex_unlock(&mutex_terminated);
	
	//make the thread detached so that it can close itself without us having
	//to join with it in order to free its resources.
	pthread_attr_t thread_attribs;
	pthread_attr_init(&thread_attribs);
	pthread_attr_setdetachstate(&thread_attribs, PTHREAD_CREATE_DETACHED);

	addr_drone_video.sin_family      = AF_INET;
	addr_drone_video.sin_addr.s_addr = inet_addr(WIFI_ARDRONE_IP);
	addr_drone_video.sin_port        = htons(PORT_VIDEO);
	
	//initialiser le fdset
	FD_ZERO(&vid_fd_set);
	
	/* NOT NEEDED NOW
	//initialize the video buffer's extremity to zero to prevent
	//possible errors during the decoding process by ffmpeg.
	//Do not reference FF_INPUT_BUFFER_PADDING_SIZE directly to keep tasks as separated as possible.
	memset(tcp_buf+BASE_VIDEO_BUF_SIZE, 0, TCP_VIDEO_BUF_SIZE-BASE_VIDEO_BUF_SIZE);
	*/
	
	//initialize the video decoder
	if(video_init_decoder() < 0) {
		fprintf(stderr, "Error initializing decoder, aborting.\n");
		pthread_attr_destroy(&thread_attribs);
		pthread_mutex_unlock(&mutex_init);
		return -1;
	}

	sock_video = socket(AF_INET, SOCK_STREAM, 0);
	if(sock_video < 0) {
		fprintf(stderr, "Error : couldn't bind TCP socket.\n");
		video_stop_decoder();
		pthread_attr_destroy(&thread_attribs);
		pthread_mutex_unlock(&mutex_init);
		return -1;
	}

	//bind du socket client pour le forcer sur le port choisi
	if(connect(sock_video, (struct sockaddr*)&addr_drone_video, sizeof(addr_drone_video)) < 0) {
		perror("Error connecting to video stream");
		video_clean();
		pthread_attr_destroy(&thread_attribs);
		pthread_mutex_unlock(&mutex_init);
		return -1;
	}
	//ajouter le socket au set pour select
	FD_SET(sock_video, &vid_fd_set);
	
	stopped = 0;
	terminated = 0;
	//démarrer la réception des packets vidéo
	if(pthread_create(&video_thread, &thread_attribs, video_routine, NULL) < 0) {
		perror("Error creating the main video thread");
		stopped = 1;
		terminated = 1;
		video_clean();
		pthread_attr_destroy(&thread_attribs);
		pthread_mutex_unlock(&mutex_init);
		return -1;
	}
	pthread_attr_destroy(&thread_attribs);
	//now that we're done initializing, release the lock.
	pthread_mutex_unlock(&mutex_init);
	return 0;
}
Ejemplo n.º 3
0
void* video_routine(void* args)
{
	//TCP segment of encoded video received from the drone
	static uint8_t tcp_buf[TCP_VIDEO_BUF_SIZE];
	//size of this segment in bytes
	ssize_t pack_size = 0;
	//set to 1 by the decoding function if a decoded video frame is available
	int got_frame = 0;
	//structure that will hold our latest decoded video frame
	jakopter_video_frame_t decoded_frame;
	
	pthread_mutex_lock(&mutex_stopped);
	while(!stopped) {
		pthread_mutex_unlock(&mutex_stopped);
		//Wait for the drone to send data on the video socket
		if (select(sock_video+1, &vid_fd_set, NULL, NULL, &video_timeout) < 0) {
			perror("Error select()");
			video_set_stopped();
		}
		else if(FD_ISSET(sock_video, &vid_fd_set)) {
			/*receive the video data from the drone. Only BASE_SIZE, since
			TCP_SIZE may be larger on purpose.*/
			pack_size = recv(sock_video, tcp_buf, BASE_VIDEO_BUF_SIZE, 0);
			if(pack_size == 0) {
				printf("Stream ended by server. Ending the video thread.\n");
				video_set_stopped();
			}
			else if(pack_size < 0)
				perror("Error recv()");
			else {
				//we actually got some data, send it for decoding !
				got_frame = video_decode_packet(tcp_buf, pack_size, &decoded_frame);
				if(got_frame < 0) {
					fprintf(stderr, "Error decoding video !\n");
					video_set_stopped();
				}
				//if we have a complete decoded frame, push it onto the queue for decoding
				else if(got_frame == 1)
					video_queue_push_frame(&decoded_frame);
			}
		}
		else {
			printf("Video : data reception has timed out. Ending the video thread now.\n");
			video_set_stopped();
		}
		//reset the timeout and the FDSET entry
		video_timeout.tv_sec = VIDEO_TIMEOUT;
		FD_ZERO(&vid_fd_set);
		FD_SET(sock_video, &vid_fd_set);

		pthread_mutex_lock(&mutex_stopped);
	}
	pthread_mutex_unlock(&mutex_stopped);
	/*push an empty frame on the queue so the processing
	thread knows it has to stop*/
	video_queue_push_frame(&VIDEO_QUEUE_END);
	pthread_join(processing_thread, NULL);
	//there's no reason to keep stuff that's needed for our video thread once it's ended, so clean it now.
	video_clean();
	pthread_exit(NULL);
}
Ejemplo n.º 4
0
int jakopter_init_video()
{
	//do not try to initialize the thread if it's already running !
	pthread_mutex_lock(&mutex_stopped);
	if(!stopped) {
		fprintf(stderr, "Video thread already running.\n");
		pthread_mutex_unlock(&mutex_stopped);
		return -1;
	}
	//make sure the thread is terminated
	video_join_thread();
	
	addr_drone_video.sin_family      = AF_INET;
	addr_drone_video.sin_addr.s_addr = inet_addr(WIFI_ARDRONE_IP);
	addr_drone_video.sin_port        = htons(PORT_VIDEO);
	
	//initialize the fdset
	FD_ZERO(&vid_fd_set);
	
	//initialize the video decoder
	if(video_init_decoder() < 0) {
		fprintf(stderr, "Error initializing decoder, aborting.\n");
		pthread_mutex_unlock(&mutex_stopped);
		return -1;
	}

	sock_video = socket(AF_INET, SOCK_STREAM, 0);
	if(sock_video < 0) {
		fprintf(stderr, "Error : couldn't bind TCP socket.\n");
		video_stop_decoder();
		pthread_mutex_unlock(&mutex_stopped);
		return -1;
	}

	//bind the client socket to force it on the drone's port
	if(connect(sock_video, (struct sockaddr*)&addr_drone_video, sizeof(addr_drone_video)) < 0) {
		perror("Error connecting to video stream");
		video_clean();
		pthread_mutex_unlock(&mutex_stopped);
		return -1;
	}
	//add the socket to the set, for use with select()
	FD_SET(sock_video, &vid_fd_set);
	
	//initialize the queue structure that handles decoding->processing data passing	
	video_queue_init();
	//start the threads responsible for video processing and reception
	if(pthread_create(&processing_thread, NULL, processing_routine, NULL) < 0) {
		perror("Error creating the video processing thread");
		video_clean();
		pthread_mutex_unlock(&mutex_stopped);
		return -1;
	}
	//make the reception thread detached so that it can close itself without us having
	//to join with it in order to free its resources.
	/*pthread_attr_t thread_attribs;
	pthread_attr_init(&thread_attribs);
	pthread_attr_setdetachstate(&thread_attribs, PTHREAD_CREATE_DETACHED);*/
	if(pthread_create(&video_thread, NULL, video_routine, NULL) < 0) {
		perror("Error creating the main video thread");
		video_clean();
		//pthread_attr_destroy(&thread_attribs);
		pthread_mutex_unlock(&mutex_stopped);
		return -1;
	}
	//pthread_attr_destroy(&thread_attribs);
	//Initialization went OK -> set the guard variables so that the threads can start.
	if(frame_processing_init != NULL)
		frame_processing_init();
	stopped = 0;
	terminated = 0;
	pthread_mutex_unlock(&mutex_stopped);
	return 0;
}