DEFINE_THREAD_ROUTINE(video_stage, data) {
    C_RESULT res;

    vp_api_io_pipeline_t pipeline;
    vp_api_io_data_t out;
    
    vp_api_io_stage_t * stages;
    video_stage_merge_slices_config_t merge_slices_cfg;
    
    uint8_t i;
    
    specific_parameters_t * params = (specific_parameters_t *)(data);

    if (1 == params->needSetPriority)
    {
      CHANGE_THREAD_PRIO (video_stage, params->priority);
    }
    
    vp_os_memset(&icc_tcp, 0, sizeof ( icc_tcp));
    vp_os_memset(&icc_udp, 0, sizeof ( icc_udp));
    
    // Video Communication config
    icc_tcp.com = COM_VIDEO();
    icc_tcp.buffer_size = (1024*1024);
    icc_tcp.protocol = VP_COM_TCP;
    COM_CONFIG_SOCKET_VIDEO(&icc_tcp.socket, VP_COM_CLIENT, VIDEO_PORT, wifi_ardrone_ip);
    
    // Video Communication config
    icc_udp.com = COM_VIDEO();
    icc_udp.buffer_size = (1024*1024);
    icc_udp.protocol = VP_COM_UDP;
    COM_CONFIG_SOCKET_VIDEO(&icc_udp.socket, VP_COM_CLIENT, VIDEO_PORT, wifi_ardrone_ip);

    icc.nb_sockets = 2;
    icc.configs = icc_tab;
    icc.forceNonBlocking = &(tcpConf.tcpStageHasMoreData);
    icc_tab[1]  = &icc_tcp;
    icc_tab[0]  = &icc_udp;
    
    icc.buffer_size = (1024*1024);
    
     vp_os_memset(&vec, 0, sizeof ( vec));

     stages = (vp_api_io_stage_t*) (vp_os_calloc(
        NB_STAGES + params->pre_processing_stages_list->length + params->post_processing_stages_list->length,
        sizeof (vp_api_io_stage_t)
    ));
    
    vec.src_picture = params->in_pic;
    vec.dst_picture = params->out_pic;
    
    vp_os_memset(&tcpConf, 0, sizeof ( tcpConf));
    tcpConf.maxPFramesPerIFrame = 30;
    tcpConf.frameMeanSize = 160*1024;
    tcpConf.tcpStageHasMoreData = FALSE;
    tcpConf.latencyDrop = 1;

	pipeline.name = "video_stage_pipeline";
    pipeline.nb_stages = 0;
    pipeline.stages = &stages[0];

    //ENCODED FRAME PROCESSING STAGES
    stages[pipeline.nb_stages].type    = VP_API_INPUT_SOCKET;
    stages[pipeline.nb_stages].cfg     = (void *) &icc;
    stages[pipeline.nb_stages++].funcs = video_com_multisocket_funcs;
	printf("thread_video_stage: adding multisocket_funcs as %d th stage (input type) to video_pipeline of AR.Drone with version %d.%d.%d\n", pipeline.nb_stages, ardroneVersion.majorVersion, ardroneVersion.minorVersion, ardroneVersion.revision );

    stages[pipeline.nb_stages].type    = VP_API_FILTER_DECODER;
    stages[pipeline.nb_stages].cfg     = (void *) &tcpConf;
    stages[pipeline.nb_stages++].funcs = video_stage_tcp_funcs;
	printf("thread_video_stage: adding tcp_funcs to video_pipeline as %d nd stage (filter type) of AR.Drone\n", pipeline.nb_stages );
    
    // Record Encoded video
    if(1 == ARDRONE_VERSION())
    {

        ardrone_academy_stage_recorder_config.dest.pipeline = video_pipeline_handle;
        ardrone_academy_stage_recorder_config.dest.stage    = pipeline.nb_stages;
        stages[pipeline.nb_stages].type    = VP_API_FILTER_DECODER;
        stages[pipeline.nb_stages].cfg     = (void*)&ardrone_academy_stage_recorder_config;
        stages[pipeline.nb_stages++].funcs = ardrone_academy_stage_recorder_funcs;
		printf("thread_video_stage: adding academy_recorder_funcs to video_pipeline as %d rd stage (filter type) of AR.Drone\n", pipeline.nb_stages );

    }
    else
    {
      // Nothing to do for AR.Drone 2 as we have a separated thread for recording
    }

    //PRE-DECODING STAGES ==> recording, ...
    for(i=0;i<params->pre_processing_stages_list->length;i++){
        stages[pipeline.nb_stages].type    = params->pre_processing_stages_list->stages_list[i].type;
        stages[pipeline.nb_stages].cfg     = params->pre_processing_stages_list->stages_list[i].cfg;
        stages[pipeline.nb_stages++].funcs = params->pre_processing_stages_list->stages_list[i].funcs;
    }
	printf("thread_video_stage: adding pre_processing_stages_list to video_pipeline (now %d stages) of AR.Drone\n", pipeline.nb_stages );

    stages[pipeline.nb_stages].type    = VP_API_FILTER_DECODER;
    stages[pipeline.nb_stages].cfg     = (void *)&merge_slices_cfg;
    stages[pipeline.nb_stages++].funcs = video_stage_merge_slices_funcs;
	printf("thread_video_stage: adding merge_slices_funcs to video_pipeline (now %d stages) of AR.Drone\n", pipeline.nb_stages );

    //DECODING STAGES
    stages[pipeline.nb_stages].type    = VP_API_FILTER_DECODER;
    stages[pipeline.nb_stages].cfg     = (void*) &vec;
    stages[pipeline.nb_stages++].funcs = video_decoding_funcs;
	printf("thread_video_stage: adding video_decoding_funcs to video_pipeline (now %d stages) of AR.Drone\n", pipeline.nb_stages );

    //POST-DECODING STAGES ==> transformation, display, ...
    for(i=0;i<params->post_processing_stages_list->length;i++){
        stages[pipeline.nb_stages].type    = params->post_processing_stages_list->stages_list[i].type;
        stages[pipeline.nb_stages].cfg     = params->post_processing_stages_list->stages_list[i].cfg;
        stages[pipeline.nb_stages++].funcs = params->post_processing_stages_list->stages_list[i].funcs;
    }
	printf("thread_video_stage: adding post_processing_stages_list to video_pipeline (now %d stages) of AR.Drone\n", pipeline.nb_stages );


    if (!ardrone_tool_exit()) {
        PRINT("\nvideo stage thread initialisation\n\n");

        res = vp_api_open(&pipeline, &video_pipeline_handle);

        if (SUCCEED(res)) {
            int loop = SUCCESS;
            out.status = VP_API_STATUS_PROCESSING;

            while (!ardrone_tool_exit() && (loop == SUCCESS)) {
                if (video_stage_in_pause) {
                    vp_os_mutex_lock(&video_stage_mutex);
                    icc.num_retries = VIDEO_MAX_RETRIES;
                    vp_os_cond_wait(&video_stage_condition);
                    vp_os_mutex_unlock(&video_stage_mutex);
                }

                if (SUCCEED(vp_api_run(&pipeline, &out))) {
                    if ((out.status == VP_API_STATUS_PROCESSING || out.status == VP_API_STATUS_STILL_RUNNING)) {
                        loop = SUCCESS;
                    }
                } else loop = -1; // Finish this thread
            }
            
            vp_os_free(params->pre_processing_stages_list->stages_list);
            vp_os_free(params->post_processing_stages_list->stages_list);
            vp_os_free(params->pre_processing_stages_list);
            vp_os_free(params->post_processing_stages_list);
            
            vp_os_free(params->in_pic);
            vp_os_free(params->out_pic);
            
            vp_os_free(params);
            
            vp_api_close(&pipeline, &video_pipeline_handle);
        }
    }

    PRINT("\nvideo stage thread ended\n\n");

    return (THREAD_RET) 0;
}
DEFINE_THREAD_ROUTINE(video_recorder, data)
{
  if (1 >= ARDRONE_VERSION ()) // Run only for ARDrone 2 and upper
    {
      return (THREAD_RET)0;
    }
  C_RESULT res = C_OK;
    
  vp_api_io_pipeline_t pipeline;
  vp_api_io_data_t out;
  vp_api_io_stage_t stages[3];
  PIPELINE_HANDLE video_recorder_pipeline_handle;
  video_recorder_thread_param_t *video_recorder_thread_param = (video_recorder_thread_param_t *)data;

  video_stage_tcp_config_t tcpConf;
    
  if(video_recorder_thread_param != NULL)
  {
      CHANGE_THREAD_PRIO(video_recorder, video_recorder_thread_param->priority);
      video_stage_encoded_recorder_config.finish_callback = video_recorder_thread_param->finish_callback; 
  }
    
  vp_os_memset (&record_icc, 0x0, sizeof (record_icc));
  record_icc.com = COM_VIDEO ();
  record_icc.buffer_size = (8*1024);
  record_icc.protocol = VP_COM_TCP;
  record_icc.forceNonBlocking = &tcpConf.tcpStageHasMoreData;
  COM_CONFIG_SOCKET_VIDEO (&record_icc.socket, VP_COM_CLIENT, VIDEO_RECORDER_PORT, wifi_ardrone_ip);
  record_icc.timeoutFunc = &video_stage_encoded_recorder_com_timeout;
  record_icc.timeoutFuncAfterSec = 10;
  
  vp_os_memset (&tcpConf, 0, sizeof (tcpConf));
  tcpConf.maxPFramesPerIFrame = 30;
  tcpConf.frameMeanSize = 160*1024;
  tcpConf.latencyDrop = 0;
    
  pipeline.nb_stages = 0;
  pipeline.stages = &stages[0];
    
  // Com
  stages[pipeline.nb_stages].type = VP_API_INPUT_SOCKET;
  stages[pipeline.nb_stages].cfg  = (void *)&record_icc;
  stages[pipeline.nb_stages++].funcs = video_com_funcs;

  // TCP
  stages[pipeline.nb_stages].type = VP_API_FILTER_DECODER;
  stages[pipeline.nb_stages].cfg  = (void *) &tcpConf;
  stages[pipeline.nb_stages++].funcs = video_stage_tcp_funcs;
    
  // Record
  stages[pipeline.nb_stages].type = VP_API_FILTER_DECODER;
  stages[pipeline.nb_stages].cfg  = (void *) &video_stage_encoded_recorder_config;
  stages[pipeline.nb_stages++].funcs = video_encoded_recorder_funcs;
    
  while (FALSE == isInit)
    {
        printf ("Waiting for init\n");
    }
    
  if (! ardrone_tool_exit ())
    {
      PRINT ("Video recorder thread initialisation\n");
      res = vp_api_open (&pipeline, &video_recorder_pipeline_handle);
        
      if (SUCCEED (res))
        {
          int loop = SUCCESS;
          out.status = VP_API_STATUS_PROCESSING;
            
          while (! ardrone_tool_exit () && (SUCCESS == loop))
            {
              if (video_recorder_in_pause)
                {
                  vp_os_mutex_lock (&video_recorder_mutex);
                  record_icc.num_retries = VIDEO_MAX_RETRIES;
                  vp_os_cond_wait (&video_recorder_condition);
                  vp_os_mutex_unlock (&video_recorder_mutex);
                }

              if (SUCCEED (vp_api_run (&pipeline, &out)))
                {
                  if ((VP_API_STATUS_PROCESSING == out.status) ||
                      (VP_API_STATUS_STILL_RUNNING == out.status))
                    {
                      loop = SUCCESS;
                    }
                  else loop = -1;
                }
              else loop = -1;
            }
          vp_api_close (&pipeline, &video_recorder_pipeline_handle);
        }
    }
  PRINT ("Video recorder thread ended\n");
    
  return (THREAD_RET)res;
}
Example #3
0
DEFINE_THREAD_ROUTINE(app_main, data)
{

	C_RESULT res = C_FAIL;
	vp_com_wifi_config_t* config = NULL;

	JNIEnv* env = NULL;

	if (g_vm) {
		(*g_vm)->AttachCurrentThread (g_vm, (JNIEnv **) &env, NULL);
	}

	bContinue = TRUE;
	mobile_main_param_t *param = data;

    video_recorder_thread_param_t video_recorder_param;
    video_recorder_param.priority = VIDEO_RECORDER_THREAD_PRIORITY;
    video_recorder_param.finish_callback = param->academy_download_callback_func;

	vp_os_memset(&ardrone_info, 0x0, sizeof(ardrone_info_t));

	while ((config = (vp_com_wifi_config_t *)wifi_config()) != NULL && strlen(config->itfName) == 0)
	{
		//Waiting for wifi initialization
		vp_os_delay(250);

		if (ardrone_tool_exit() == TRUE) {
			if (param != NULL && param->callback != NULL) {
				param->callback(env, param->obj, ARDRONE_MESSAGE_DISCONNECTED);
			}
			return 0;
		}
	}



	vp_os_memcpy(&ardrone_info.drone_address[0], config->server, strlen(config->server));


    while (-1 == getDroneVersion (param->root_dir, &ardrone_info.drone_address[0], &ardroneVersion))
    {
        LOGD (TAG, "Getting AR.Drone version");
        vp_os_delay (250);
    }

    sprintf(&ardrone_info.drone_version[0], "%u.%u.%u", ardroneVersion.majorVersion, ardroneVersion.minorVersion, ardroneVersion.revision);

    LOGD (TAG, "ARDrone Version : %s\n", &ardrone_info.drone_version[0]);
	LOGI(TAG, "Drone Family: %d", ARDRONE_VERSION());

	res = ardrone_tool_setup_com( NULL );

	if( FAILED(res) )
	{
		LOGII("Setup com failed");
		LOGW(TAG, "Wifi initialization failed. It means either:");
		LOGW(TAG, "\t* you're not root (it's mandatory because you can set up wifi connection only as root)\n");
		LOGW(TAG, "\t* wifi device is not present (on your pc or on your card)\n");
		LOGW(TAG, "\t* you set the wrong name for wifi interface (for example rausb0 instead of wlan0) \n");
		LOGW(TAG, "\t* ap is not up (reboot card or remove wifi usb dongle)\n");
		LOGW(TAG, "\t* wifi device has no antenna\n");

		if (param != NULL && param->callback != NULL) {
			param->callback(env, param->obj, ARDRONE_MESSAGE_ERR_NO_WIFI);
		}
	}
	else
	{
		LOGII("ardrone_tool_setup_com [OK]");
		#define NB_IPHONE_PRE_STAGES 0

		#define NB_IPHONE_POST_STAGES 2

        //Alloc structs
        specific_parameters_t * params         = (specific_parameters_t *)vp_os_calloc(1, sizeof(specific_parameters_t));
        specific_stages_t * iphone_pre_stages  = (specific_stages_t*)vp_os_calloc(1, sizeof(specific_stages_t));
        specific_stages_t * iphone_post_stages = (specific_stages_t*)vp_os_calloc(1, sizeof(specific_stages_t));
        vp_api_picture_t  * in_picture         = (vp_api_picture_t*) vp_os_calloc(1, sizeof(vp_api_picture_t));
        vp_api_picture_t  * out_picture        = (vp_api_picture_t*) vp_os_calloc(1, sizeof(vp_api_picture_t));


        in_picture->width          = STREAM_WIDTH;
        in_picture->height         = STREAM_HEIGHT;

        out_picture->framerate     = 20;
        out_picture->format        = PIX_FMT_RGB565;
        out_picture->width         = STREAM_WIDTH;
        out_picture->height        = STREAM_HEIGHT;

        out_picture->y_buf         = vp_os_malloc( STREAM_WIDTH * STREAM_HEIGHT * 2 );
        out_picture->cr_buf        = NULL;
        out_picture->cb_buf        = NULL;

        out_picture->y_line_size   = STREAM_WIDTH * 2;
        out_picture->cb_line_size  = 0;
        out_picture->cr_line_size  = 0;

        //Define the list of stages size
        iphone_pre_stages->length  = NB_IPHONE_PRE_STAGES;
        iphone_post_stages->length = NB_IPHONE_POST_STAGES;

        //Alloc the lists
        iphone_pre_stages->stages_list  = NULL;
        iphone_post_stages->stages_list = (vp_api_io_stage_t*)vp_os_calloc(iphone_post_stages->length,sizeof(vp_api_io_stage_t));

        //Fill the POST-stages------------------------------------------------------
        int postStageNumber = 0;

        vp_os_memset (&vlat, 0x0, sizeof (vlat));
        vlat.state = 0;
        vlat.last_decoded_frame_info= (void *)&vec;
        iphone_post_stages->stages_list[postStageNumber].type  = VP_API_FILTER_DECODER;
        iphone_post_stages->stages_list[postStageNumber].cfg   = (void *)&vlat;
        iphone_post_stages->stages_list[postStageNumber++].funcs = vp_stages_latency_estimation_funcs;

        vp_os_memset (&ovsc, 0x0, sizeof (ovsc));
        ovsc.video_decoder = &vec;
        iphone_post_stages->stages_list[postStageNumber].type  = VP_API_OUTPUT_LCD;
        iphone_post_stages->stages_list[postStageNumber].cfg   = (void *)&ovsc;
        iphone_post_stages->stages_list[postStageNumber++].funcs = opengl_video_stage_funcs;

        params->in_pic = in_picture;
        params->out_pic = out_picture;
        params->pre_processing_stages_list = iphone_pre_stages;
        params->post_processing_stages_list = iphone_post_stages;

#if USE_THREAD_PRIORITIES
        params->needSetPriority = 1;
        params->priority = VIDEO_THREAD_PRIORITY;
#else
        params->needSetPriority = 0;
        params->priority = 0;
#endif


		START_THREAD(video_stage, params);

        if (IS_LEAST_ARDRONE2)
        {
            START_THREAD (video_recorder, (void *)&video_recorder_param);
            LOGD(TAG, "Video recorder thread start [OK]");
        }



		res = ardrone_tool_init(&ardrone_info.drone_address[0], strlen(&ardrone_info.drone_address[0]), NULL, param->app_name, param->user_name, param->root_dir, param->flight_dir, param->flight_storing_size, param->academy_download_callback_func);

		if(SUCCEED(res))
		{

			ardrone_tool_input_add(&virtual_gamepad);

			if (param != NULL && param->callback != NULL) {
				param->callback(env, param->obj, ARDRONE_MESSAGE_CONNECTED_OK);
			}
		} else {
			if (param != NULL && param->callback != NULL) {
				param->callback(env, param->obj, ARDRONE_MESSAGE_UNKNOWN_ERR);
			}

			bContinue = FALSE;
		}

		res = ardrone_tool_set_refresh_time(1000 / kAPS);

#if USE_THREAD_PRIORITIES
        CHANGE_THREAD_PRIO (app_main, AT_THREAD_PRIORITY);
        CHANGE_THREAD_PRIO (navdata_update, NAVDATA_THREAD_PRIORITY);
        CHANGE_THREAD_PRIO (ardrone_control, NAVDATA_THREAD_PRIORITY);
#endif

		while( SUCCEED(res) && bContinue == TRUE )
		{
			ardrone_tool_update();
		}

		JOIN_THREAD(video_stage);

        if (IS_LEAST_ARDRONE2)
        {
            JOIN_THREAD (video_recorder);
        }

	    /* Unregistering for the current device */
	    ardrone_tool_input_remove( &virtual_gamepad );

		res = ardrone_tool_shutdown();
		LOGD(TAG, "AR.Drone tool shutdown [OK]");

		if (param != NULL && param->callback != NULL) {
			param->callback(env, param->obj, ARDRONE_MESSAGE_DISCONNECTED);
		}
	}

	vp_os_free (data);
	data = NULL;

	(*env)->DeleteGlobalRef(env, param->obj);

	if (g_vm) {
		(*g_vm)->DetachCurrentThread (g_vm);
	}

	LOGI(TAG, "app_main thread has been stopped.");

	return (THREAD_RET) res;
}