Upgrading to Parrot SDK 2.0.1

Esse commit está contido em:
Mani Monajjemi
2013-10-21 11:07:21 -07:00
commit a3f9cff1a6
68 arquivos alterados com 3072 adições e 3166 exclusões
+1 -1
Ver Arquivo
@@ -13,7 +13,7 @@ else
RELEASE_OPT="debug" RELEASE_OPT="debug"
endif endif
FFMPEG_CONFIG=decoder FFMPEG_CONFIG=both
FFMPEG_DIR_EXIST=$(shell bash -c "if [ -d ffmpeg ]; then echo \"YES\"; else echo \"NO\"; fi") FFMPEG_DIR_EXIST=$(shell bash -c "if [ -d ffmpeg ]; then echo \"YES\"; else echo \"NO\"; fi")
Arquivo binário não exibido.
+8 -8
Ver Arquivo
@@ -65,10 +65,10 @@ ifdef PC_TARGET
OS_DEFINE=GNU_LINUX OS_DEFINE=GNU_LINUX
else else
ifeq ("$(USE_LINUX)","yes") ifeq ("$(USE_LINUX)","yes")
OS_DEFINE=GNU_LINUX OS_DEFINE=GNU_LINUX
else else
TARGET:=$(TARGET).exe TARGET:=$(TARGET).exe
OS_DEFINE=WINDOW OS_DEFINE=WINDOW
endif endif
endif endif
@@ -110,8 +110,8 @@ ifdef PC_TARGET
ifeq ("$(IPHONE_MODE)","yes") ifeq ("$(IPHONE_MODE)","yes")
SDK_FLAGS+="USE_IPHONE=yes" SDK_FLAGS+="USE_IPHONE=yes"
SDK_FLAGS+="FFMPEG_SUPPORT=no" SDK_FLAGS+="FFMPEG_SUPPORT=yes"
SDK_FLAGS+="ITTIAM_SUPPORT=yes" SDK_FLAGS+="ITTIAM_SUPPORT=no"
SDK_FLAGS+="USE_VIDEO_TCP=yes" SDK_FLAGS+="USE_VIDEO_TCP=yes"
SDK_FLAGS+="USE_VIDEO_HD=no" SDK_FLAGS+="USE_VIDEO_HD=no"
else else
@@ -127,10 +127,10 @@ ifdef PC_TARGET
ifeq ("$(USE_ANDROID)","yes") ifeq ("$(USE_ANDROID)","yes")
SDK_FLAGS+="USE_ANDROID=yes" SDK_FLAGS+="USE_ANDROID=yes"
SDK_FLAGS+="TOOLCHAIN_VERSION=arm-linux-androideabi-4.4.3" SDK_FLAGS+="TOOLCHAIN_VERSION=arm-linux-androideabi-4.6"
SDK_FLAGS+="NDK_PLATFORM_VERSION=android-8" SDK_FLAGS+="NDK_PLATFORM_VERSION=android-8"
SDK_FLAGS+="FFMPEG_SUPPORT=yes" SDK_FLAGS+="FFMPEG_SUPPORT=yes"
SDK_FLAGS+="ITTIAM_SUPPORT=yes" SDK_FLAGS+="ITTIAM_SUPPORT=no"
SDK_FLAGS+="USE_VIDEO_TCP=yes" SDK_FLAGS+="USE_VIDEO_TCP=yes"
SDK_FLAGS+="USE_VIDEO_HD=no" SDK_FLAGS+="USE_VIDEO_HD=no"
else else
+1 -1
Ver Arquivo
@@ -14,7 +14,7 @@ ifndef USE_ANDROID
USE_ANDROID = no USE_ANDROID = no
endif endif
ifndef USE_LINUX ifndef USE_LINUX
USE_LINUX = yes USE_LINUX = no
endif endif
ifndef PROJECT ifndef PROJECT
# set default to ardrone2 for video TCP com. # set default to ardrone2 for video TCP com.
+1 -1
Ver Arquivo
@@ -44,6 +44,6 @@ typedef struct _academy_user_t_
} academy_user_t; } academy_user_t;
typedef void (*academy_callback)(academy_state_t state); typedef void (*academy_callback)(academy_state_t state);
typedef void (*academy_download_new_media)(const char *mediaPath); typedef void (*academy_download_new_media)(const char *mediaPath, bool_t addToQueue);
#endif // _ACADEMY_COMMON_H_ #endif // _ACADEMY_COMMON_H_
-16
Ver Arquivo
@@ -359,22 +359,6 @@ typedef enum
FLYING_MODE_HOVER_ON_TOP_OF_ORIENTED_ROUNDEL = 1 << 1, /**< Commands are disabled, drones hovers on top of an oriented roundel - oriented roundel detection MUST be activated by the user with 'detect_type' configuration. */ FLYING_MODE_HOVER_ON_TOP_OF_ORIENTED_ROUNDEL = 1 << 1, /**< Commands are disabled, drones hovers on top of an oriented roundel - oriented roundel detection MUST be activated by the user with 'detect_type' configuration. */
} FLYING_MODE; } FLYING_MODE;
/*
* @enum TRAVELLING_MODE
* @brief Values for the CONTROL:travelling_mode configuration.
*/
typedef enum
{
TRAVELLING_MODE_TRANSLATION = 0, /**< Travelling translation mode */
TRAVELLING_MODE_CIRCULAR, /**< Travelling circular mode */
TRAVELLING_MODE_SWING, /**/
TRAVELLING_MODE_WHEEL_FRONT, /**/
TRAVELLING_MODE_WHEEL_SIDE, /**/
TRAVELLING_MODE_GUSH, /**/
TRAVELLING_MODE_PLANAR_WHEEL,/**/
TRAVELLING_MODE_NUM,
} TRAVELLING_MODE;
/** /**
* @enum WIFI_MODE * @enum WIFI_MODE
* @brief Values for the NETWORK:wifi_mode configuration, who set the wifi mode when drone start * @brief Values for the NETWORK:wifi_mode configuration, who set the wifi mode when drone start
-51
Ver Arquivo
@@ -1,51 +0,0 @@
/*
* Automatically generated C config: don't edit
* Linux kernel version:
* Thu Nov 5 18:06:01 2009
*/
#define AUTOCONF_INCLUDED
#define PAL_TRACE_THREAD_VAL 0
#define PAL_ASSERT 1
#define MODIF_VERSION_NUMBER 0
#define PAL_BUTTON_LONG_PRESS_TIME 2000
#define PAL_BUTTON_DRIVER 1
#define PAL_I2C_DRIVER 1
#define MAJOR_VERSION_NUMBER 1
#define PAL_TRACE_SEM_VAL 0
#define MINOR_VERSION_NUMBER 0
#define PAL_TRACE_SYS_VAL 0
#define PAL_SUP_NB_TIMERS 18
#define PAL_TRACE_HWALARM_VAL 0
#define PAL_PWM_DRIVER 1
#define PAL_I2C_DEVICES 1
#define EXTENDED_VERSION_INFO RC0
#define PAL_SUP_NB_MOD 32
#define PAL_TRACE_FLAG_VAL 0
#define PAL_TRACE_COND_VAL 0
#define PAL_DEBUG_LEVEL 1
#define PAL_TRACE_GPIO_VAL 0
#define PAL_TRACE_TIME_VAL 0
#define PAL_TRACE_MBOX_VAL 0
#define PAL_TRACE_UART_VAL 0
#define PAL_GPIO_DRIVER 1
#define PAL_P6MU_ADC_DEVICE 1
#define PAL_P6MU_CODEC_DEVICE 1
#define BUILD_PAL 1
#define PAL_SUP_PRIO_P1 18
#define PAL_SUP_PRIO_P2 20
#define PAL_SUP_PRIO_P3 22
#define PAL_SUP_PRIO_P4 24
#define PAL_SUP_PRIO_P5 26
#define PAL_UARTS_COUNT 4
#define PAL_LINUX_NOSMP 1
#define PAL_TRACE_ALARM_VAL 0
#define PAL_SUP_MAX_MES 60
#define CONFIG_PAL_USER_ASSERT 1
#define TRUC_POURRI_YMM 1
#define UNAME_RELEASE 2.6.28-16-generic
#define PAL_BUTTON_MAX_HW_DRIVERS 1
#define PAL_TRACE_MUTEX_VAL 0
#define PAL_BUTTON_MAX_BUTTONS 32
#define PAL_STACKSIZE 6144
#define PAL_POSIX_MIX_PRIO 1
#define PAL_POSIX_RT_PRIO_THRESHOLD 10
-1
Ver Arquivo
@@ -14,7 +14,6 @@
#include <win32_custom.h> #include <win32_custom.h>
#else #else
#include <generated_custom.h> #include <generated_custom.h>
#include <autoconf.h>
#endif #endif
#undef ARDRONE_PIC_VERSION #undef ARDRONE_PIC_VERSION
-4
Ver Arquivo
@@ -157,8 +157,6 @@ extern const float32_t default_magneto_radius;
#define ARDRONE_DEFAULT_DATE "19700101_000000" #define ARDRONE_DEFAULT_DATE "19700101_000000"
#define ARDRONE_EMPTY_STRING "" #define ARDRONE_EMPTY_STRING ""
#define ARDRONE_DEFAULT_TRAVELLING_MODE "0,10,1500,0,1000"
#define CUSTOM_CONFIGURATION_DELETE_ALL_CMD "all" #define CUSTOM_CONFIGURATION_DELETE_ALL_CMD "all"
@@ -283,8 +281,6 @@ ARDRONE_CONFIG_KEY_IMM_a10("control", outdoor_control_yaw, INI_FLOAT,
ARDRONE_CONFIG_KEY_IMM_a10("control", flying_mode, INI_INT, int32_t, int32_t*, (K_READ|K_WRITE|K_NOBIND|K_SHALLOW), (K_READ|K_WRITE), 0, flying_mode_config_callback,CAT_SESSION) ARDRONE_CONFIG_KEY_IMM_a10("control", flying_mode, INI_INT, int32_t, int32_t*, (K_READ|K_WRITE|K_NOBIND|K_SHALLOW), (K_READ|K_WRITE), 0, flying_mode_config_callback,CAT_SESSION)
ARDRONE_CONFIG_KEY_IMM_a10("control", hovering_range, INI_INT, int32_t, int32_t*, (K_READ|K_WRITE|K_NOBIND|K_SHALLOW), (K_READ|K_WRITE), 1000, default_config_callback, CAT_SESSION) ARDRONE_CONFIG_KEY_IMM_a10("control", hovering_range, INI_INT, int32_t, int32_t*, (K_READ|K_WRITE|K_NOBIND|K_SHALLOW), (K_READ|K_WRITE), 1000, default_config_callback, CAT_SESSION)
ARDRONE_CONFIG_KEY_STR_a10("control", flight_anim, INI_STRING, string_t, char*, (K_READ|K_WRITE|K_NOBIND|K_SHALLOW), 0, "0,0", flight_animation_selection_callback,CAT_COMMON) ARDRONE_CONFIG_KEY_STR_a10("control", flight_anim, INI_STRING, string_t, char*, (K_READ|K_WRITE|K_NOBIND|K_SHALLOW), 0, "0,0", flight_animation_selection_callback,CAT_COMMON)
ARDRONE_CONFIG_KEY_STR_a10("control", travelling_mode, INI_STRING, string_t, char*, (K_READ|K_WRITE), (K_READ|K_WRITE), ARDRONE_DEFAULT_TRAVELLING_MODE, travelling_mode_selection_callback,CAT_USER)
ARDRONE_CONFIG_KEY_IMM_a10("control", travelling_enable, INI_BOOLEAN, bool_t, bool_t*, (K_READ|K_WRITE|K_NOBIND|K_SHALLOW), 0, FALSE, travelling_enable_callback, CAT_COMMON)
ARDRONE_CONFIG_KEY_STR_a10("network", ssid_single_player, INI_STRING, string_t, char*, (K_READ|K_WRITE), 0, WIFI_NETWORK_NAME, default_config_callback, CAT_COMMON) ARDRONE_CONFIG_KEY_STR_a10("network", ssid_single_player, INI_STRING, string_t, char*, (K_READ|K_WRITE), 0, WIFI_NETWORK_NAME, default_config_callback, CAT_COMMON)
ARDRONE_CONFIG_KEY_STR_a10("network", ssid_multi_player, INI_STRING, string_t, char*, (K_READ|K_WRITE), 0, WIFI_NETWORK_NAME, default_config_callback, CAT_COMMON) ARDRONE_CONFIG_KEY_STR_a10("network", ssid_multi_player, INI_STRING, string_t, char*, (K_READ|K_WRITE), 0, WIFI_NETWORK_NAME, default_config_callback, CAT_COMMON)
+1 -1
Ver Arquivo
@@ -72,7 +72,7 @@ typedef enum {
CVAR( FLYING_ALT_OUT_ZONE ), CVAR( FLYING_ALT_OUT_ZONE ),
CVAR( FLYING_COMBINED_YAW ), CVAR( FLYING_COMBINED_YAW ),
CVAR( FLYING_BRAKE ), CVAR( FLYING_BRAKE ),
CVAR( FLYING_NO_VISION ) CVAR( FLYING_NO_VISION ),
#ifndef CTRL_STATES_STRING #ifndef CTRL_STATES_STRING
} FLYING_STATES; } FLYING_STATES;
#else #else
+3 -4
Ver Arquivo
@@ -210,7 +210,7 @@ static const int32_t MAYDAY_TIMEOUT[ARDRONE_NB_ANIM_MAYDAY] = {
#define NAVDATA_HEADER 0x55667788 #define NAVDATA_HEADER 0x55667788
#define NAVDATA_MAX_SIZE 2048 #define NAVDATA_MAX_SIZE 4096
#define NAVDATA_MAX_CUSTOM_TIME_SAVE 20 #define NAVDATA_MAX_CUSTOM_TIME_SAVE 20
/* !!! Warning !!! - changing the value below would break compatibility with older applications /* !!! Warning !!! - changing the value below would break compatibility with older applications
@@ -355,7 +355,6 @@ typedef struct _navdata_raw_measures_t {
uint16_t nb_echo; uint16_t nb_echo;
uint32_t sum_echo; uint32_t sum_echo;
int32_t alt_temp_raw; int32_t alt_temp_raw;
int16_t gradient; int16_t gradient;
}_ATTRIBUTE_PACKED_ navdata_raw_measures_t; }_ATTRIBUTE_PACKED_ navdata_raw_measures_t;
@@ -395,8 +394,8 @@ typedef struct _navdata_wind_speed_t {
uint16_t tag; uint16_t tag;
uint16_t size; uint16_t size;
float32_t wind_speed; float32_t wind_speed; // estimated wind speed [m/s]
float32_t wind_angle; float32_t wind_angle; // estimated wind direction in North-East frame [rad] e.g. if wind_angle is pi/4, wind is from South-West to North-East
float32_t wind_compensation_theta; float32_t wind_compensation_theta;
float32_t wind_compensation_phi; float32_t wind_compensation_phi;
float32_t state_x1; float32_t state_x1;
+4 -4
Ver Arquivo
@@ -31,10 +31,10 @@ NAVDATA_OPTION( navdata_watchdog_t , navdata_watchdog , NAVDATA_WATC
NAVDATA_OPTION( navdata_adc_data_frame_t, navdata_adc_data_frame , NAVDATA_ADC_DATA_FRAME_TAG ) NAVDATA_OPTION( navdata_adc_data_frame_t, navdata_adc_data_frame , NAVDATA_ADC_DATA_FRAME_TAG )
NAVDATA_OPTION( navdata_video_stream_t, navdata_video_stream , NAVDATA_VIDEO_STREAM_TAG ) NAVDATA_OPTION( navdata_video_stream_t, navdata_video_stream , NAVDATA_VIDEO_STREAM_TAG )
NAVDATA_OPTION( navdata_games_t, navdata_games , NAVDATA_GAMES_TAG ) NAVDATA_OPTION( navdata_games_t, navdata_games , NAVDATA_GAMES_TAG )
NAVDATA_OPTION( navdata_pressure_raw_t, navdata_pressure_raw , NAVDATA_PRESSURE_RAW_TAG ) NAVDATA_OPTION( navdata_pressure_raw_t, navdata_pressure_raw , NAVDATA_PRESSURE_RAW_TAG )
NAVDATA_OPTION( navdata_magneto_t, navdata_magneto , NAVDATA_MAGNETO_TAG ) NAVDATA_OPTION( navdata_magneto_t, navdata_magneto , NAVDATA_MAGNETO_TAG )
NAVDATA_OPTION( navdata_wind_speed_t, navdata_wind_speed , NAVDATA_WIND_TAG ) NAVDATA_OPTION( navdata_wind_speed_t, navdata_wind_speed , NAVDATA_WIND_TAG )
NAVDATA_OPTION( navdata_kalman_pressure_t,navdata_kalman_pressure , NAVDATA_KALMAN_PRESSURE_TAG ) NAVDATA_OPTION( navdata_kalman_pressure_t,navdata_kalman_pressure , NAVDATA_KALMAN_PRESSURE_TAG )
NAVDATA_OPTION( navdata_hdvideo_stream_t ,navdata_hdvideo_stream , NAVDATA_HDVIDEO_STREAM_TAG ) NAVDATA_OPTION( navdata_hdvideo_stream_t ,navdata_hdvideo_stream , NAVDATA_HDVIDEO_STREAM_TAG )
NAVDATA_OPTION( navdata_wifi_t ,navdata_wifi , NAVDATA_WIFI_TAG ) NAVDATA_OPTION( navdata_wifi_t ,navdata_wifi , NAVDATA_WIFI_TAG )
+5 -1
Ver Arquivo
@@ -77,6 +77,10 @@ GENERIC_LIBRARY_SOURCE_FILES+= \
$(ARDRONE_TOOL_DIR)/Video/video_stage_decoder.c \ $(ARDRONE_TOOL_DIR)/Video/video_stage_decoder.c \
$(ARDRONE_TOOL_DIR)/Video/video_recorder_pipeline.c \ $(ARDRONE_TOOL_DIR)/Video/video_recorder_pipeline.c \
$(ARDRONE_TOOL_DIR)/Video/video_stage.c $(ARDRONE_TOOL_DIR)/Video/video_stage.c
ifeq ($(USE_ANDROID),yes)
GENERIC_LIBRARY_SOURCE_FILES+= \
$(UTILS_DIR)/AR_Ftw.c
endif
endif endif
ifneq ($(CONTROL_DLL),yes) ifneq ($(CONTROL_DLL),yes)
@@ -165,7 +169,7 @@ export GENERIC_BINARIES_SOURCE_ENTRYPOINTS=
all $(MAKECMDGOALS): all $(MAKECMDGOALS):
@if [ '$(MAKECMDGOALS)' != 'clean' ]; then echo "$(OK_COLOR)Building ARDroneTool/Lib$(NO_COLOR)"; fi @if [ '$(MAKECMDGOALS)' != 'clean' ]; then echo "$(OK_COLOR)Building ARDroneTool/Lib$(NO_COLOR)"; fi
@$(MAKE) -C ../../../VP_SDK/Build $(TMP_SDK_FLAGS) $(SDK_FLAGS) $(MAKECMDGOALS) @$(MAKE) -C ../../../VP_SDK/Build $(TMP_SDK_FLAGS) $(SDK_FLAGS) $(MAKECMDGOALS)
makefileverbose: makefileverbose:
@echo "Dump compilation flags:" @echo "Dump compilation flags:"
@echo "GENERIC_CFLAGS : $(GENERIC_CFLAGS)" @echo "GENERIC_CFLAGS : $(GENERIC_CFLAGS)"
+5 -4
Ver Arquivo
@@ -1,4 +1,5 @@
#include <VP_Os/vp_os_assert.h> #include <VP_Os/vp_os_assert.h>
#include <VP_Os/vp_os_print.h>
#include <VP_Os/vp_os_malloc.h> #include <VP_Os/vp_os_malloc.h>
#include <Maths/matrices.h> #include <Maths/matrices.h>
@@ -223,12 +224,12 @@ bool_t normalize_vec( vector31_t* v )
void display_matrix33(matrix33_t *m1) void display_matrix33(matrix33_t *m1)
{ {
printf("( %f\t%f\t%f )\n( %f\t%f\t%f )\n( %f\t%f\t%f )\n",m1->m11,m1->m12,m1->m13,m1->m21,m1->m22,m1->m23,m1->m31,m1->m32,m1->m33); PRINT("( %f\t%f\t%f )\n( %f\t%f\t%f )\n( %f\t%f\t%f )\n",m1->m11,m1->m12,m1->m13,m1->m21,m1->m22,m1->m23,m1->m31,m1->m32,m1->m33);
} }
void display_vector31(vector31_t *v1) void display_vector31(vector31_t *v1)
{ {
printf("( %f\t%f\t%f )\n", v1->x ,v1->y, v1->z); PRINT("( %f\t%f\t%f )\n", v1->x ,v1->y, v1->z);
} }
// matrix of size 4 // matrix of size 4
@@ -408,12 +409,12 @@ void inv_mat44(matrix44_t *out, matrix44_t* m1)
void display_matrix44(matrix44_t *m1) void display_matrix44(matrix44_t *m1)
{ {
printf("( %f\t%f\t%f\t%f )\n( %f\t%f\t%f\t%f )\n( %f\t%f\t%f\t%f )\n( %f\t%f\t%f\t%f )\n",m1->m11,m1->m12,m1->m13,m1->m14,m1->m21,m1->m22,m1->m23,m1->m24,m1->m31,m1->m32,m1->m33,m1->m34,m1->m41,m1->m42,m1->m43,m1->m44); PRINT("( %f\t%f\t%f\t%f )\n( %f\t%f\t%f\t%f )\n( %f\t%f\t%f\t%f )\n( %f\t%f\t%f\t%f )\n",m1->m11,m1->m12,m1->m13,m1->m14,m1->m21,m1->m22,m1->m23,m1->m24,m1->m31,m1->m32,m1->m33,m1->m34,m1->m41,m1->m42,m1->m43,m1->m44);
} }
void display_vector41(vector41_t *v1) void display_vector41(vector41_t *v1)
{ {
printf("( %f\t%f\t%f\t%f )\n", v1->x1 ,v1->x2, v1->x3, v1->x4); PRINT("( %f\t%f\t%f\t%f )\n", v1->x1 ,v1->x2, v1->x3, v1->x4);
} }
+1 -1
Ver Arquivo
@@ -146,7 +146,7 @@ C_RESULT matrix3d_orientation(matrix3d_t* m, const vector31_t* pos, const vector
return C_OK; return C_OK;
} }
#define MATRIX_EXCHANGE( out, in ) temp = out; out = in; in = out #define MATRIX_EXCHANGE( out, in ) temp = out; out = in; in = temp
C_RESULT matrix3d_transpose(matrix3d_t* out, matrix3d_t* in) C_RESULT matrix3d_transpose(matrix3d_t* out, matrix3d_t* in)
{ {
@@ -20,6 +20,7 @@
#include <VP_Os/vp_os_print.h> #include <VP_Os/vp_os_print.h>
#include <ardrone_tool/Com/config_com.h> #include <ardrone_tool/Com/config_com.h>
#include <ardrone_tool/ardrone_tool.h> #include <ardrone_tool/ardrone_tool.h>
#include <ardrone_tool/ardrone_version.h>
//Common //Common
#include <ardrone_api.h> #include <ardrone_api.h>
@@ -160,16 +161,27 @@ AT_CODEC_ERROR_CODE host_open( void )
PRINT ("Error setting SND_BUF for AT socket\n"); PRINT ("Error setting SND_BUF for AT socket\n");
} }
int opt = IPTOS_PREC_NETCONTROL; /*
int res = setsockopt((int)at_socket.priv, IPPROTO_IP, IP_TOS, &opt, (socklen_t)sizeof(opt)); * On android, with IP_TOS set, certain devices can't connect to AR.Drone 1
if (res) * So we just disable this functionnality to avoid these cases.
*/
#ifdef USE_ANDROID
if (IS_ARDRONE2)
{ {
perror("AT stage - setting Live video socket IP Type Of Service : "); #endif
} int opt = IPTOS_PREC_NETCONTROL;
else int res = setsockopt((int)at_socket.priv, IPPROTO_IP, IP_TOS, &opt, (socklen_t)sizeof(opt));
{ if (res)
printf ("Set IP_TOS ok\n"); {
perror("AT stage - setting Live video socket IP Type Of Service : ");
}
else
{
printf ("Set IP_TOS ok\n");
}
#ifdef USE_ANDROID
} }
#endif
@@ -306,6 +318,7 @@ void ardrone_at_set_flat_trim(void)
{ {
if (!at_init) if (!at_init)
return; return;
vp_os_mutex_lock(&at_mutex); vp_os_mutex_lock(&at_mutex);
ATcodec_Queue_Message_valist( ids.AT_MSG_ATCMD_FTRIM_EXE, ATcodec_Queue_Message_valist( ids.AT_MSG_ATCMD_FTRIM_EXE,
++nb_sequence ); ++nb_sequence );
@@ -219,7 +219,7 @@ DEFINE_THREAD_ROUTINE(academy, data)
academy.flight_sum = 0; academy.flight_sum = 0;
academy.flight_oldest_date[0] = '\0'; academy.flight_oldest_date[0] = '\0';
if(!ftw(flight_dir, &academy_compute_memory_used, 1)) if(!ftw(flight_dir, &academy_compute_memory_used, ACADEMY_MAX_FD_FOR_FTW))
{ {
if(academy.flight_sum > MBYTE_TO_BYTE(academy.flight_max_storing_size)) if(academy.flight_sum > MBYTE_TO_BYTE(academy.flight_max_storing_size))
{ {
@@ -229,17 +229,21 @@ DEFINE_THREAD_ROUTINE(academy, data)
// remove oldest flight // remove oldest flight
PA_WARNING("Too much memory used %d MB > %d MB, removing oldest flight %s...", BYTE_TO_MBYTE(academy.flight_sum), academy.flight_max_storing_size, remove_dir); PA_WARNING("Too much memory used %d MB > %d MB, removing oldest flight %s...", BYTE_TO_MBYTE(academy.flight_sum), academy.flight_max_storing_size, remove_dir);
if(!ftw(remove_dir, &academy_remove, 1)) if(!ftw(remove_dir, &academy_remove, ACADEMY_MAX_FD_FOR_FTW))
{ {
rmdir(remove_dir); rmdir(remove_dir);
PA_WARNING("OK.\n"); PA_WARNING("OK.\n");
} }
} }
else else
{
needToCheckMemory = FALSE; needToCheckMemory = FALSE;
}
} }
else else
{
needToCheckMemory = FALSE; needToCheckMemory = FALSE;
}
} }
} }
@@ -17,11 +17,17 @@
#include <utils/ardrone_ftp.h> #include <utils/ardrone_ftp.h>
#include <VP_Os/vp_os_delay.h> #include <VP_Os/vp_os_delay.h>
#include <VP_Os/vp_os_thread.h> #include <VP_Os/vp_os_thread.h>
#include <VP_Os/vp_os_print.h>
#include <VP_Os/vp_os_malloc.h> #include <VP_Os/vp_os_malloc.h>
#include <VP_Os/vp_os_signal.h> #include <VP_Os/vp_os_signal.h>
#include <stdio.h> #include <stdio.h>
#include <dirent.h> #include <dirent.h>
#ifndef USE_ANDROID
#include <ftw.h> #include <ftw.h>
#else
#include <utils/AR_Ftw.h>
#endif
#include <time.h> #include <time.h>
#ifndef _WIN32 #ifndef _WIN32
@@ -40,6 +46,7 @@
#define ACADEMY_MAX_LIST 1024 #define ACADEMY_MAX_LIST 1024
#define ACADEMY_MAX_LINE 128 #define ACADEMY_MAX_LINE 128
#define ACADEMY_MAX_FILENAME 256 #define ACADEMY_MAX_FILENAME 256
#define ACADEMY_MAX_FD_FOR_FTW 20
#define PA_PREFIX "PA : " #define PA_PREFIX "PA : "
@@ -47,26 +54,26 @@
#define PA_DEBUG(...) \ #define PA_DEBUG(...) \
do \ do \
{ \ { \
printf (PA_PREFIX); \ PRINT (PA_PREFIX); \
printf (__VA_ARGS__); \ PRINT (__VA_ARGS__); \
} while (0) } while (0)
#define PA_WARNING(...) \ #define PA_WARNING(...) \
do \ do \
{ \ { \
printf (PA_PREFIX); \ PRINT (PA_PREFIX); \
printf (__VA_ARGS__); \ PRINT (__VA_ARGS__); \
} while (0) } while (0)
#else #else
#define PA_DEBUG(...) #define PA_DEBUG(...)
#define PA_WARNING(...) \ #define PA_WARNING(...) \
do \ do \
{ \ { \
printf (PA_PREFIX); \ PRINT (PA_PREFIX); \
printf (__VA_ARGS__); \ PRINT (__VA_ARGS__); \
} while (0) } while (0)
#endif #endif
#define ACADEMY_SERVERNAME "" #define ACADEMY_SERVERNAME "parrot01.nyx.emencia.net"
#define ACADEMY_PORT 21 #define ACADEMY_PORT 21
#define BYTE_TO_MBYTE(a) (a / 1048576) #define BYTE_TO_MBYTE(a) (a / 1048576)
#define MBYTE_TO_BYTE(a) (a * 1048576) #define MBYTE_TO_BYTE(a) (a * 1048576)
@@ -12,8 +12,8 @@
typedef struct _academy_download_t_ typedef struct _academy_download_t_
{ {
academy_callback callback; academy_callback callback;
academy_download_new_media new_media_callback; academy_download_new_media new_media_callback;
academy_state_t state; academy_state_t state;
} academy_download_t; } academy_download_t;
PROTO_THREAD_ROUTINE(academy_download, data); PROTO_THREAD_ROUTINE(academy_download, data);
@@ -27,120 +27,120 @@ static vp_os_cond_t academy_download_cond;
static void academy_download_private_callback(academy_state_t state) static void academy_download_private_callback(academy_state_t state)
{ {
static char msg[DISPLAY_STRING_LENGTH] = { 0 }; static char msg[DISPLAY_STRING_LENGTH] = { 0 };
switch(state.result) switch(state.result)
{ {
case ACADEMY_RESULT_NONE: case ACADEMY_RESULT_NONE:
switch(state.state) switch(state.state)
{ {
case ACADEMY_STATE_CONNECTION: case ACADEMY_STATE_CONNECTION:
snprintf (msg, DISPLAY_STRING_LENGTH, "Connecting to %s...", &wifi_ardrone_ip[0]); snprintf (msg, DISPLAY_STRING_LENGTH, "Connecting to %s...", &wifi_ardrone_ip[0]);
break; break;
case ACADEMY_STATE_PREPARE_PROCESS: case ACADEMY_STATE_PREPARE_PROCESS:
snprintf (msg, DISPLAY_STRING_LENGTH, "Preparing download from %s to local directory...", &wifi_ardrone_ip[0]); snprintf (msg, DISPLAY_STRING_LENGTH, "Preparing download from %s to local directory...", &wifi_ardrone_ip[0]);
break; break;
case ACADEMY_STATE_PROCESS: case ACADEMY_STATE_PROCESS:
snprintf (msg, DISPLAY_STRING_LENGTH, "Downloading from %s to local directory...", &wifi_ardrone_ip[0]); snprintf (msg, DISPLAY_STRING_LENGTH, "Downloading from %s to local directory...", &wifi_ardrone_ip[0]);
break; break;
case ACADEMY_STATE_FINISH_PROCESS: case ACADEMY_STATE_FINISH_PROCESS:
snprintf (msg, DISPLAY_STRING_LENGTH, "Finishing download from %s to local directory...", &wifi_ardrone_ip[0]); snprintf (msg, DISPLAY_STRING_LENGTH, "Finishing download from %s to local directory...", &wifi_ardrone_ip[0]);
break; break;
case ACADEMY_STATE_DISCONNECTION: case ACADEMY_STATE_DISCONNECTION:
snprintf (msg, DISPLAY_STRING_LENGTH, "Disconnection to %s...", &wifi_ardrone_ip[0]); snprintf (msg, DISPLAY_STRING_LENGTH, "Disconnection to %s...", &wifi_ardrone_ip[0]);
break; break;
case ACADEMY_STATE_NONE: case ACADEMY_STATE_NONE:
strncpy(msg, "", DISPLAY_STRING_LENGTH); strncpy(msg, "", DISPLAY_STRING_LENGTH);
break; break;
default: default:
strncpy(msg, "", DISPLAY_STRING_LENGTH); strncpy(msg, "", DISPLAY_STRING_LENGTH);
break; break;
} }
break; break;
case ACADEMY_RESULT_OK: case ACADEMY_RESULT_OK:
strncat(msg, "OK", DISPLAY_STRING_LENGTH - strlen (msg)); strncat(msg, "OK", DISPLAY_STRING_LENGTH - strlen (msg));
break; break;
case ACADEMY_RESULT_FAILED: case ACADEMY_RESULT_FAILED:
strncat(msg, "FAILED", DISPLAY_STRING_LENGTH - strlen (msg)); strncat(msg, "FAILED", DISPLAY_STRING_LENGTH - strlen (msg));
break; break;
} }
if(strlen(msg) != 0) if(strlen(msg) != 0)
PA_DEBUG("===========> %s\n", msg); PA_DEBUG("===========> %s\n", msg);
} }
static void academy_download_resetState(academy_download_t *academy) static void academy_download_resetState(academy_download_t *academy)
{ {
academy_resetState(&academy->state); academy_resetState(&academy->state);
if(academy->callback) if(academy->callback)
academy->callback(academy->state); academy->callback(academy->state);
} }
static void academy_download_nextState(academy_download_t *academy) static void academy_download_nextState(academy_download_t *academy)
{ {
academy_nextState(&academy->state); academy_nextState(&academy->state);
if(academy->callback) if(academy->callback)
academy->callback(academy->state); academy->callback(academy->state);
} }
static void academy_download_stateOK(academy_download_t *academy) static void academy_download_stateOK(academy_download_t *academy)
{ {
academy_stateOK(&academy->state); academy_stateOK(&academy->state);
if(academy->callback) if(academy->callback)
academy->callback(academy->state); academy->callback(academy->state);
} }
static void academy_download_stateERROR(academy_download_t *academy) static void academy_download_stateERROR(academy_download_t *academy)
{ {
academy_stateERROR(&academy->state); academy_stateERROR(&academy->state);
if(academy->callback) if(academy->callback)
academy->callback(academy->state); academy->callback(academy->state);
academy_download_resetState(academy); academy_download_resetState(academy);
} }
void academy_download_init(academy_download_new_media academy_download_callback_func) void academy_download_init(academy_download_new_media academy_download_callback_func)
{ {
if(!academy_download_started) if(!academy_download_started)
{ {
vp_os_mutex_init (&academy_download_mutex); vp_os_mutex_init (&academy_download_mutex);
vp_os_cond_init (&academy_download_cond, &academy_download_mutex); vp_os_cond_init (&academy_download_cond, &academy_download_mutex);
academy_download_started = TRUE; academy_download_started = TRUE;
vp_os_thread_create(thread_academy_download, (THREAD_PARAMS)academy_download_callback_func, &academy_download_thread); vp_os_thread_create(thread_academy_download, (THREAD_PARAMS)academy_download_callback_func, &academy_download_thread);
} }
} }
void academy_download_shutdown(void) void academy_download_shutdown(void)
{ {
if(academy_download_started) if(academy_download_started)
{ {
academy_download_started = FALSE; academy_download_started = FALSE;
academy_download_resume (); academy_download_resume ();
vp_os_thread_join(academy_download_thread); vp_os_thread_join(academy_download_thread);
} }
} }
DEFINE_THREAD_ROUTINE(academy_download, data) DEFINE_THREAD_ROUTINE(academy_download, data)
{ {
char *directoryList = NULL; char *directoryList = NULL;
bool_t shouldGoInPause = FALSE; bool_t shouldGoInPause = FALSE;
char *fileList = NULL; char *fileList = NULL;
char process_dirname[ACADEMY_MAX_FILENAME]; char process_dirname[ACADEMY_MAX_FILENAME];
_ftp_t *academy_ftp = NULL; _ftp_t *academy_ftp = NULL;
_ftp_status academy_status; _ftp_status academy_status;
struct stat statbuf; struct stat statbuf;
char *ptr = NULL; char *ptr = NULL;
academy_download_t academy; academy_download_t academy;
academy.new_media_callback = (academy_download_new_media)data; academy.new_media_callback = (academy_download_new_media)data;
academy.callback = academy_download_private_callback; academy.callback = academy_download_private_callback;
printf("Start thread %s \n", __FUNCTION__); PRINT("Start thread %s \n", __FUNCTION__);
do do
{ {
academy_download_resetState(&academy); academy_download_resetState(&academy);
@@ -148,257 +148,264 @@ DEFINE_THREAD_ROUTINE(academy_download, data)
if (TRUE == academy_download_in_pause) if (TRUE == academy_download_in_pause)
{ {
vp_os_mutex_lock (&academy_download_mutex); vp_os_mutex_lock (&academy_download_mutex);
printf ("Academy download stage paused\n"); PRINT ("Academy download stage paused\n");
vp_os_cond_wait (&academy_download_cond); vp_os_cond_wait (&academy_download_cond);
vp_os_mutex_unlock (&academy_download_mutex); vp_os_mutex_unlock (&academy_download_mutex);
} }
academy_download_pause(); academy_download_pause();
printf ("Academy download stage resumed\n"); PRINT ("Academy download stage resumed\n");
academy_download_nextState(&academy); academy_download_nextState(&academy);
while( academy_download_started && !shouldGoInPause)
{
academy_status = FTP_FAIL;
switch(academy.state.state) while( academy_download_started && !shouldGoInPause)
{
academy_status = FTP_FAIL;
switch(academy.state.state)
{ {
case ACADEMY_STATE_NONE: case ACADEMY_STATE_NONE:
academy_status = FTP_SUCCESS;
break;
case ACADEMY_STATE_CONNECTION:
if(academy_ftp == NULL)
academy_ftp = ftpConnect(&wifi_ardrone_ip[0], ACADEMY_PORT, "anonymous", "", &academy_status);
if(academy_ftp != NULL)
academy_status = FTP_SUCCESS; academy_status = FTP_SUCCESS;
break; break;
case ACADEMY_STATE_CONNECTION:
if(academy_ftp == NULL)
academy_ftp = ftpConnect(&wifi_ardrone_ip[0], ACADEMY_PORT, "anonymous", "", &academy_status);
if(academy_ftp != NULL) case ACADEMY_STATE_PREPARE_PROCESS:
academy_status = FTP_SUCCESS; academy_status = ftpCd(academy_ftp, "/boxes");
break; if(FTP_SUCCEDED(academy_status))
{
char *next_dir = NULL;
PA_DEBUG("Enter to boxes directory\n");
academy_status = ftpList(academy_ftp, &directoryList, NULL);
case ACADEMY_STATE_PREPARE_PROCESS: // If directory is empty, we consider that it is an error
academy_status = ftpCd(academy_ftp, "/boxes"); if(academy_status == FTP_SAMESIZE)
if(FTP_SUCCEDED(academy_status)) academy_status = FTP_FAIL;
{
char *next_dir = NULL;
PA_DEBUG("Enter to boxes directory\n");
academy_status = ftpList(academy_ftp, &directoryList, NULL);
// If directory is empty, we consider that it is an error if(FTP_SUCCEDED(academy_status))
if(academy_status == FTP_SAMESIZE) {
academy_status = FTP_FAIL; char local_dir[ACADEMY_MAX_FILENAME];
// Search if it stay ftpremove_* directories to continue removing
if(FTP_SUCCEDED(academy_status)) PA_DEBUG("Get directory list :\n%s", directoryList);
{ while(FTP_SUCCEDED(academy_status) && (ptr = academy_get_next_item_with_prefix(directoryList, &next_dir, "ftpremove_downloading_", TRUE)))
char local_dir[ACADEMY_MAX_FILENAME]; {
// Search if it stay ftpremove_* directories to continue removing char remove_dirname[ACADEMY_MAX_FILENAME];
PA_DEBUG("Get directory list :\n%s", directoryList);
while(FTP_SUCCEDED(academy_status) && (ptr = academy_get_next_item_with_prefix(directoryList, &next_dir, "ftpremove_downloading_", TRUE)))
{
char remove_dirname[ACADEMY_MAX_FILENAME];
strncpy(remove_dirname, ptr, ACADEMY_MAX_FILENAME); strncpy(remove_dirname, ptr, ACADEMY_MAX_FILENAME);
academy_status = academy_remove_ftp_directory(academy_ftp, remove_dirname); academy_status = academy_remove_ftp_directory(academy_ftp, remove_dirname);
} }
academy_status = FTP_FAIL; academy_status = FTP_FAIL;
next_dir = NULL; next_dir = NULL;
// Search if it stay downloading_flight_* file to continue downloading. // Search if it stay downloading_flight_* file to continue downloading.
ptr = academy_get_next_item_with_prefix(directoryList, &next_dir, "downloading_flight_", TRUE); ptr = academy_get_next_item_with_prefix(directoryList, &next_dir, "downloading_flight_", TRUE);
// Check if transfer was in progress // Check if transfer was in progress
if(ptr != NULL) if(ptr != NULL)
{ {
// Transfer was in progress // Transfer was in progress
PA_DEBUG("Transfer was in progress\n"); PA_DEBUG("Transfer was in progress\n");
strncpy(process_dirname, ptr, ACADEMY_MAX_FILENAME); strncpy(process_dirname, ptr, ACADEMY_MAX_FILENAME);
snprintf(local_dir, ACADEMY_MAX_FILENAME, "%s/%s", flight_dir, process_dirname); snprintf(local_dir, ACADEMY_MAX_FILENAME, "%s/%s", flight_dir, process_dirname);
if((stat(local_dir, &statbuf) == 0) && S_ISDIR(statbuf.st_mode)) if((stat(local_dir, &statbuf) == 0) && S_ISDIR(statbuf.st_mode))
{ {
// Transfer was in progress by current device // Transfer was in progress by current device
PA_DEBUG("Transfer was in progress by current device\n"); PA_DEBUG("Transfer was in progress by current device\n");
academy_status = FTP_SUCCESS; academy_status = FTP_SUCCESS;
} }
else else
{ {
// Transfer was in progress by an other device => Create local directory // Transfer was in progress by an other device => Create local directory
PA_DEBUG("Transfer was in progress by an other device\n"); PA_DEBUG("Transfer was in progress by an other device\n");
printf("Creating local directory %s\n", local_dir); PRINT("Creating local directory %s\n", local_dir);
if(mkdir(local_dir, 0777) >= 0) if(mkdir(local_dir, 0777) >= 0)
{ {
PA_DEBUG("Create local directory %s\n", local_dir); PA_DEBUG("Create local directory %s\n", local_dir);
academy_status = FTP_SUCCESS; academy_status = FTP_SUCCESS;
} }
} }
} }
else else
{ {
PA_DEBUG(" Transfer was not in progress\n"); PA_DEBUG(" Transfer was not in progress\n");
// Transfer was not in progress => Get oldest flight, rename remote directory and create local directory // Transfer was not in progress => Get oldest flight, rename remote directory and create local directory
next_dir = NULL; next_dir = NULL;
ptr = academy_get_next_item_with_prefix(directoryList, &next_dir, "flight_", TRUE); ptr = academy_get_next_item_with_prefix(directoryList, &next_dir, "flight_", TRUE);
if(ptr != NULL) if(ptr != NULL)
{ {
// Prepare to process new transfer // Prepare to process new transfer
PA_DEBUG("Prepare to process new transfer\n"); PA_DEBUG("Prepare to process new transfer\n");
snprintf(process_dirname, ACADEMY_MAX_FILENAME, "downloading_%s", ptr); snprintf(process_dirname, ACADEMY_MAX_FILENAME, "downloading_%s", ptr);
academy_status = ftpRename(academy_ftp, ptr, process_dirname); academy_status = ftpRename(academy_ftp, ptr, process_dirname);
if(FTP_SUCCEDED(academy_status)) if(FTP_SUCCEDED(academy_status))
{ {
PA_DEBUG("Rename %s to %s directory\n", ptr, process_dirname); PA_DEBUG("Rename %s to %s directory\n", ptr, process_dirname);
snprintf(local_dir, ACADEMY_MAX_FILENAME, "%s/%s", flight_dir, process_dirname); snprintf(local_dir, ACADEMY_MAX_FILENAME, "%s/%s", flight_dir, process_dirname);
if((stat(local_dir, &statbuf) != 0) && (mkdir(local_dir, 0777) >= 0)) if((stat(local_dir, &statbuf) != 0) && (mkdir(local_dir, 0777) >= 0))
PA_DEBUG("Create local directory %s if not exist\n", local_dir); PA_DEBUG("Create local directory %s if not exist\n", local_dir);
academy_status = FTP_SUCCESS; academy_status = FTP_SUCCESS;
}
}
else
{
shouldGoInPause = TRUE;
} }
} }
else
{
shouldGoInPause = TRUE;
}
}
if(directoryList != NULL) if(directoryList != NULL)
{ {
vp_os_free(directoryList); vp_os_free(directoryList);
directoryList = NULL; directoryList = NULL;
} }
} }
} }
break; break;
case ACADEMY_STATE_PROCESS: case ACADEMY_STATE_PROCESS:
academy_status = ftpCd(academy_ftp, process_dirname); academy_status = ftpCd(academy_ftp, process_dirname);
if(FTP_SUCCEDED(academy_status)) if(FTP_SUCCEDED(academy_status))
{ {
PA_DEBUG("Enter to %s directory\n", process_dirname); PA_DEBUG("Enter to %s directory\n", process_dirname);
academy_status = ftpList(academy_ftp, &fileList, NULL); academy_status = ftpList(academy_ftp, &fileList, NULL);
if(FTP_SUCCEDED(academy_status)) if(FTP_SUCCEDED(academy_status))
{ {
char *next_file = NULL; char *next_file = NULL;
char media_dirname[ACADEMY_MAX_FILENAME]; char media_dirname[ACADEMY_MAX_FILENAME];
char local_filename[ACADEMY_MAX_FILENAME]; char local_filename[ACADEMY_MAX_FILENAME];
bool_t userbox_ready = FALSE; bool_t userbox_ready = FALSE;
PA_DEBUG("Get file list :\n%s", fileList); PA_DEBUG("Get file list :\n%s", fileList);
ptr = academy_get_next_item_with_prefix(fileList, &next_file, "userbox_", FALSE); ptr = academy_get_next_item_with_prefix(fileList, &next_file, "userbox_", FALSE);
if(ptr != NULL) if(ptr != NULL)
{ {
snprintf(local_filename, ACADEMY_MAX_FILENAME, "%s/%s/%s", flight_dir, process_dirname, ptr); snprintf(local_filename, ACADEMY_MAX_FILENAME, "%s/%s/%s", flight_dir, process_dirname, ptr);
PA_DEBUG("Get %s from drone to local directory...", local_filename); PA_DEBUG("Get %s from drone to local directory...", local_filename);
academy_status = ftpGet (academy_ftp, ptr, local_filename, 1, NULL); academy_status = ftpGet (academy_ftp, ptr, local_filename, 1, NULL);
if(FTP_SUCCEDED(academy_status)) if(FTP_SUCCEDED(academy_status))
{ {
userbox_ready = TRUE; userbox_ready = TRUE;
PA_DEBUG("OK\n"); PA_DEBUG("OK\n");
} }
else else
PA_DEBUG("ERROR\n"); PA_DEBUG("ERROR\n");
} }
snprintf(media_dirname, ACADEMY_MAX_FILENAME, "%s/media_%s", flight_dir, process_dirname + (strlen("downloading_flight_"))); snprintf(media_dirname, ACADEMY_MAX_FILENAME, "%s/media_%s", flight_dir, process_dirname + (strlen("downloading_flight_")));
//printf("medias directory : %s\n", media_dirname); //PRINT("medias directory : %s\n", media_dirname);
next_file = NULL; next_file = NULL;
while(FTP_SUCCEDED(academy_status) && (ptr = academy_get_next_item_with_prefix(fileList, &next_file, "picture_", FALSE))) while(FTP_SUCCEDED(academy_status) && (ptr = academy_get_next_item_with_prefix(fileList, &next_file, "picture_", FALSE)))
{ {
if((stat(media_dirname, &statbuf) != 0) && (mkdir(media_dirname, 0777) >= 0)) if((stat(media_dirname, &statbuf) != 0) && (mkdir(media_dirname, 0777) >= 0))
PA_DEBUG("Create local media directory %s if not exist\n", media_dirname); PA_DEBUG("Create local media directory %s if not exist\n", media_dirname);
sprintf(local_filename, "%s/%s", media_dirname, ptr); sprintf(local_filename, "%s/%s", media_dirname, ptr);
PA_DEBUG("Get %s from drone to local directory...", local_filename); PA_DEBUG("Get %s from drone to local directory...", local_filename);
academy_status = ftpGet (academy_ftp, ptr, local_filename, 1, NULL); academy_status = ftpGet (academy_ftp, ptr, local_filename, 1, NULL);
if(FTP_SUCCEDED(academy_status)) if(FTP_SUCCEDED(academy_status))
{ {
academy.new_media_callback((const char *)local_filename); if (NULL != academy.new_media_callback)
PA_DEBUG("OK\n"); {
} academy.new_media_callback((const char *)local_filename, TRUE);
else }
{ PA_DEBUG("OK\n");
PA_DEBUG("ERROR\n"); }
} else
} {
PA_DEBUG("ERROR\n");
}
}
if (NULL != academy.new_media_callback)
{
academy.new_media_callback((const char *)NULL, FALSE);
}
if(FTP_SUCCEDED(academy_status) && !userbox_ready) if(FTP_SUCCEDED(academy_status) && !userbox_ready)
{ {
char local_dirname[ACADEMY_MAX_FILENAME]; char local_dirname[ACADEMY_MAX_FILENAME];
snprintf(local_dirname, ACADEMY_MAX_FILENAME, "%s/%s", flight_dir, process_dirname); snprintf(local_dirname, ACADEMY_MAX_FILENAME, "%s/%s", flight_dir, process_dirname);
remove(local_dirname); remove(local_dirname);
} }
} }
if(FTP_SUCCEDED(academy_status)) if(FTP_SUCCEDED(academy_status))
ftpCd(academy_ftp, ".."); ftpCd(academy_ftp, "..");
} }
break; break;
case ACADEMY_STATE_FINISH_PROCESS: case ACADEMY_STATE_FINISH_PROCESS:
{ {
char remove_dirname[ACADEMY_MAX_FILENAME]; char remove_dirname[ACADEMY_MAX_FILENAME];
char src[ACADEMY_MAX_FILENAME]; char src[ACADEMY_MAX_FILENAME];
char dest[ACADEMY_MAX_FILENAME]; char dest[ACADEMY_MAX_FILENAME];
// Rename local directory from downloading_flight_* to flight_* // Rename local directory from downloading_flight_* to flight_*
snprintf(src, ACADEMY_MAX_FILENAME, "%s/%s", flight_dir, process_dirname); snprintf(src, ACADEMY_MAX_FILENAME, "%s/%s", flight_dir, process_dirname);
snprintf(dest, ACADEMY_MAX_FILENAME, "%s/%s", flight_dir, process_dirname + strlen("downloading_")); snprintf(dest, ACADEMY_MAX_FILENAME, "%s/%s", flight_dir, process_dirname + strlen("downloading_"));
rename(src, dest); rename(src, dest);
// Rename ftp remote directory from downloading_flight_* to ftpremove_downloading_flight_* // Rename ftp remote directory from downloading_flight_* to ftpremove_downloading_flight_*
snprintf(remove_dirname, ACADEMY_MAX_FILENAME, "ftpremove_%s", process_dirname); snprintf(remove_dirname, ACADEMY_MAX_FILENAME, "ftpremove_%s", process_dirname);
academy_status = ftpRename(academy_ftp, process_dirname, remove_dirname); academy_status = ftpRename(academy_ftp, process_dirname, remove_dirname);
// Delete ftpremove_downloading_flight_* // Delete ftpremove_downloading_flight_*
if(FTP_SUCCEDED(academy_status)) if(FTP_SUCCEDED(academy_status))
academy_status = academy_remove_ftp_directory(academy_ftp, remove_dirname); academy_status = academy_remove_ftp_directory(academy_ftp, remove_dirname);
} }
break; break;
case ACADEMY_STATE_DISCONNECTION: case ACADEMY_STATE_DISCONNECTION:
if(academy_ftp != NULL) if(academy_ftp != NULL)
ftpClose(&academy_ftp); ftpClose(&academy_ftp);
academy_check_memory(); academy_check_memory();
academy_status = FTP_SUCCESS; academy_status = FTP_SUCCESS;
break; break;
default: default:
// Nothing to do // Nothing to do
PA_DEBUG("THIS CASE SHOULD NOT HAPPEN\n"); PA_DEBUG("THIS CASE SHOULD NOT HAPPEN\n");
break; break;
} }
if(FTP_SUCCEDED(academy_status)) if(FTP_SUCCEDED(academy_status))
{ {
PA_DEBUG("continue state from %d to %d\n", academy.state.state, (academy.state.state + 1) % ACADEMY_STATE_MAX); PA_DEBUG("continue state from %d to %d\n", academy.state.state, (academy.state.state + 1) % ACADEMY_STATE_MAX);
academy_download_stateOK(&academy); academy_download_stateOK(&academy);
academy_download_nextState(&academy); academy_download_nextState(&academy);
} }
else else
{ {
PA_DEBUG("stop\n"); PA_DEBUG("stop\n");
shouldGoInPause = TRUE; shouldGoInPause = TRUE;
academy_download_stateERROR(&academy); academy_download_stateERROR(&academy);
if(fileList != NULL)
{
vp_os_free(fileList);
fileList = NULL;
}
if(academy_ftp) if(fileList != NULL)
ftpClose(&academy_ftp); {
} vp_os_free(fileList);
} fileList = NULL;
}
if(fileList != NULL) if(academy_ftp)
{ ftpClose(&academy_ftp);
vp_os_free(fileList); }
fileList = NULL; }
}
if(academy_ftp) if(fileList != NULL)
ftpClose(&academy_ftp); {
vp_os_free(fileList);
} fileList = NULL;
}
if(academy_ftp)
ftpClose(&academy_ftp);
}
while(academy_download_started && !ardrone_tool_exit()); while(academy_download_started && !ardrone_tool_exit());
vp_os_cond_destroy(&academy_download_cond); vp_os_cond_destroy(&academy_download_cond);
vp_os_mutex_destroy(&academy_download_mutex); vp_os_mutex_destroy(&academy_download_mutex);
THREAD_RETURN(C_OK); THREAD_RETURN(C_OK);
} }
void academy_download_pause (void) void academy_download_pause (void)
@@ -20,6 +20,10 @@
extern char flight_dir[]; extern char flight_dir[];
#endif #endif
#define ACADEMY_MEDIA_DIRPATH_FORMAT "%s/media_%s"
#define ACADEMY_MEDIA_VIDEO_FILEPATH_FORMAT "%s/video_%s.%s"
#define ACADEMY_MEDIA_DIR_ACCESS_RIGHT 0777
static void ardrone_academy_stage_recorder_internal_close(ardrone_academy_stage_recorder_config_t *cfg); static void ardrone_academy_stage_recorder_internal_close(ardrone_academy_stage_recorder_config_t *cfg);
ardrone_academy_stage_recorder_config_t ardrone_academy_stage_recorder_config; ardrone_academy_stage_recorder_config_t ardrone_academy_stage_recorder_config;
@@ -53,14 +57,15 @@ ardrone_academy_stage_recorder_handle (ardrone_academy_stage_recorder_config_t *
char media_dirname[ACADEMY_MAX_FILENAME]; char media_dirname[ACADEMY_MAX_FILENAME];
struct stat statbuf; struct stat statbuf;
sprintf(media_dirname, "%s/media_%s", ACADEMY_FILE_DEFAULT_PATH, date); sprintf(media_dirname, ACADEMY_MEDIA_DIRPATH_FORMAT, ACADEMY_FILE_DEFAULT_PATH, date);
if((stat(media_dirname, &statbuf) != 0) && (mkdir(media_dirname, 0777) >= 0)) if((stat(media_dirname, &statbuf) != 0) && (mkdir(media_dirname, ACADEMY_MEDIA_DIR_ACCESS_RIGHT) >= 0))
PA_DEBUG("Create local media directory %s if not exist\n", media_dirname); PA_DEBUG("Create local media directory %s if not exist\n", media_dirname);
// NO ELSE, the local directory already exists
t = time(NULL); t = time(NULL);
ardrone_time2date(t, ARDRONE_FILE_DATE_FORMAT, date); ardrone_time2date(t, ARDRONE_FILE_DATE_FORMAT, date);
sprintf(cfg->video_filename, "%s/video_%s.%s", sprintf(cfg->video_filename, ACADEMY_MEDIA_VIDEO_FILEPATH_FORMAT,
media_dirname, media_dirname,
date, date,
ACADEMY_RECORD_FILE_EXTENSION); ACADEMY_RECORD_FILE_EXTENSION);
@@ -81,6 +86,7 @@ ardrone_academy_stage_recorder_handle (ardrone_academy_stage_recorder_config_t *
printf ("Can't open file %s\n", video_filename); printf ("Can't open file %s\n", video_filename);
} }
} }
// NO ELSE - The record is already started or is starting
break; break;
case PIPELINE_MSG_STOP: case PIPELINE_MSG_STOP:
@@ -89,14 +95,16 @@ ardrone_academy_stage_recorder_handle (ardrone_academy_stage_recorder_config_t *
cfg->startRec = ACADEMY_RECORD_STOP; cfg->startRec = ACADEMY_RECORD_STOP;
printf("Stop recording %s\n", cfg->video_filename); printf("Stop recording %s\n", cfg->video_filename);
ardrone_academy_stage_recorder_internal_close(cfg); ardrone_academy_stage_recorder_internal_close(cfg);
result = C_OK;
} }
// NO ELSE - Record is already stopped.
break; break;
default: default:
break; break;
} }
return (VP_SUCCESS); return (result);
} }
void ardrone_academy_stage_recorder_enable(bool_t enable, uint32_t timestamp) void ardrone_academy_stage_recorder_enable(bool_t enable, uint32_t timestamp)
@@ -136,7 +144,7 @@ C_RESULT ardrone_academy_stage_recorder_transform(ardrone_academy_stage_recorder
out->indexBuffer = 0; out->indexBuffer = 0;
out->lineSize = NULL; out->lineSize = NULL;
} }
// NO ELSE - We need to initialize the number of buffers and the index of buffer in first.
out->size = in->size; out->size = in->size;
out->status = in->status; out->status = in->status;
out->buffers = in->buffers; out->buffers = in->buffers;
@@ -159,6 +167,11 @@ C_RESULT ardrone_academy_stage_recorder_transform(ardrone_academy_stage_recorder
fwrite(&in->size, 1, sizeof(int32_t), cfg->fp); fwrite(&in->size, 1, sizeof(int32_t), cfg->fp);
fwrite(in->buffers[in->indexBuffer], 1, in->size, cfg->fp); fwrite(in->buffers[in->indexBuffer], 1, in->size, cfg->fp);
} }
// NO ELSE because :
// If the descriptor file is NULL, we can't to write data.
// If data size to write is 0, we don't have data to write.
// If the status is not processing, it means the record is stopping.
// If startRec is not start, it means the record is stopping or is starting.
vp_os_mutex_unlock( &out->lock ); vp_os_mutex_unlock( &out->lock );
#endif #endif
@@ -171,5 +184,8 @@ C_RESULT ardrone_academy_stage_recorder_close(ardrone_academy_stage_recorder_con
{ {
ardrone_academy_stage_recorder_internal_close(cfg); ardrone_academy_stage_recorder_internal_close(cfg);
} }
// NO ELSE because :
// If the descriptor file is NULL, we can't to write data.
return C_OK; return C_OK;
} }
@@ -117,18 +117,9 @@ static void academy_upload_private_callback(academy_state_t state)
case ACADEMY_RESULT_OK: case ACADEMY_RESULT_OK:
strcat(msg, "OK"); strcat(msg, "OK");
// time_to_process += state.time_in_ms;
// if(state.state == ACADEMY_STATE_DRONE_DISCONNECTION)
// {
// sprintf(msg, "%s in %d ms\n", msg, time_to_process);
// time_to_process = 0;
// }
break; break;
case ACADEMY_RESULT_FAILED: case ACADEMY_RESULT_FAILED:
// if(state.state == ACADEMY_STATE_DRONE_PREPARE_DOWNLOAD)
// time_to_process = 0;
strcat(msg, "FAILED"); strcat(msg, "FAILED");
break; break;
} }
@@ -231,7 +222,6 @@ DEFINE_THREAD_ROUTINE(academy_upload, data)
struct dirent *dirent = NULL; struct dirent *dirent = NULL;
DIR *dir = NULL; DIR *dir = NULL;
academy_status = FTP_FAIL; academy_status = FTP_FAIL;
// Check if flight_* directory exist in local dir // Check if flight_* directory exist in local dir
if((dir = opendir(flight_dir)) != NULL) if((dir = opendir(flight_dir)) != NULL)
{ {
@@ -350,7 +340,7 @@ DEFINE_THREAD_ROUTINE(academy_upload, data)
// Penser à supprimer le fichier local // Penser à supprimer le fichier local
academy_status = FTP_FAIL; academy_status = FTP_FAIL;
sprintf(local_dir, "%s/%s", flight_dir, dirname); sprintf(local_dir, "%s/%s", flight_dir, dirname);
if(!ftw(local_dir, &academy_remove, 1)) if(!ftw(local_dir, &academy_remove, ACADEMY_MAX_FD_FOR_FTW))
{ {
rmdir(local_dir); rmdir(local_dir);
academy_status = FTP_SUCCESS; academy_status = FTP_SUCCESS;
@@ -38,74 +38,69 @@ static vp_os_mutex_t event_queue_mutex;
C_RESULT ardrone_control_init(void) C_RESULT ardrone_control_init(void)
{ {
COM_CONFIG_SOCKET_CONTROL(&control_socket, VP_COM_CLIENT, CONTROL_PORT, wifi_ardrone_ip); COM_CONFIG_SOCKET_CONTROL(&control_socket, VP_COM_CLIENT, CONTROL_PORT, wifi_ardrone_ip);
control_waited = FALSE;
ardrone_state = 0;
control_waited = FALSE; vp_os_mutex_init(&control_mutex);
ardrone_state = 0; vp_os_cond_init(&control_cond, &control_mutex);
vp_os_mutex_init(&control_mutex); vp_os_mutex_init(&event_queue_mutex);
vp_os_cond_init(&control_cond, &control_mutex);
vp_os_mutex_init(&event_queue_mutex); start_index_in_queue = 0;
end_index_in_queue = (start_index_in_queue - 1) & (ARDRONE_CONTROL_MAX_NUM_EVENTS_IN_QUEUE - 1);
start_index_in_queue = 0; return C_OK;
end_index_in_queue = (start_index_in_queue - 1) & (ARDRONE_CONTROL_MAX_NUM_EVENTS_IN_QUEUE - 1);
return C_OK;
} }
C_RESULT ardrone_control_shutdown(void) C_RESULT ardrone_control_shutdown(void)
{ {
ardrone_control_resume_on_navdata_received(0); ardrone_control_resume_on_navdata_received(0);
/*BUG FIX : Dont destroy the mutexes here, /*BUG FIX : Dont destroy the mutexes here,
they are still being used by the ardrone_control thread, they are still being used by the ardrone_control thread,
while this function is called by another thread.*/ while this function is called by another thread.*/
#ifdef THIS_IS_A_BUG
vp_os_mutex_destroy(&event_queue_mutex);
vp_os_cond_destroy(&control_cond);
vp_os_mutex_destroy(&control_mutex);*/
#endif
bContinue = FALSE; bContinue = FALSE;
return C_OK; return C_OK;
} }
C_RESULT ardrone_control_connect_to_drone() C_RESULT ardrone_control_connect_to_drone()
{ {
int res_open_socket; int res_open_socket;
#ifdef _WIN32 #ifdef _WIN32
int timeout_windows=1000;/*milliseconds*/ int timeout_windows=1000;/*milliseconds*/
#else #else
struct timeval tv; struct timeval tv;
#endif #endif
res_open_socket = vp_com_open(COM_CONTROL(), &control_socket, &control_read, &control_write); res_open_socket = vp_com_open(COM_CONTROL(), &control_socket, &control_read, &control_write);
if( VP_SUCCEEDED(res_open_socket) ) if( VP_SUCCEEDED(res_open_socket) )
{ {
tv.tv_sec = 1; tv.tv_sec = 1;
tv.tv_usec = 0; tv.tv_usec = 0;
setsockopt((int32_t)control_socket.priv, setsockopt((int32_t)control_socket.priv,
SOL_SOCKET, SOL_SOCKET,
SO_RCVTIMEO, SO_RCVTIMEO,
#ifdef _WIN32 #ifdef _WIN32
(const char*)&timeout_windows, sizeof(timeout_windows) (const char*)&timeout_windows, sizeof(timeout_windows)
#else #else
(const char*)&tv, sizeof(tv) (const char*)&tv, sizeof(tv)
#endif #endif
); );
control_socket.is_disable = FALSE; control_socket.is_disable = FALSE;
return C_OK; return C_OK;
} }
else else
{ {
DEBUG_PRINT_SDK("VP_Com : Failed to open socket for control\n"); DEBUG_PRINT_SDK("VP_Com : Failed to open socket for control\n");
perror("FTOSFC"); perror("FTOSFC");
return C_FAIL; return C_FAIL;
} }
} }
@@ -115,201 +110,201 @@ C_RESULT ardrone_control_connect_to_drone()
*/ */
C_RESULT ardrone_control_resume_on_navdata_received(uint32_t new_ardrone_state) C_RESULT ardrone_control_resume_on_navdata_received(uint32_t new_ardrone_state)
{ {
vp_os_mutex_lock(&control_mutex); vp_os_mutex_lock(&control_mutex);
if( control_waited ) if( control_waited )
{ {
ardrone_state = new_ardrone_state; ardrone_state = new_ardrone_state;
vp_os_cond_signal(&control_cond); vp_os_cond_signal(&control_cond);
} }
vp_os_mutex_unlock(&control_mutex); vp_os_mutex_unlock(&control_mutex);
return C_OK; return C_OK;
} }
C_RESULT ardrone_control_read(uint8_t* buffer, int32_t* size) C_RESULT ardrone_control_read(uint8_t* buffer, int32_t* size)
{ {
C_RESULT res = C_FAIL; C_RESULT res = C_FAIL;
if( control_read != NULL ) if( control_read != NULL )
{ {
res = control_read(&control_socket, buffer, size); res = control_read(&control_socket, buffer, size);
if(*size == 0) if(*size == 0)
{ {
res = C_FAIL; res = C_FAIL;
} }
} }
return res; return res;
} }
C_RESULT ardrone_control_write(const uint8_t* buffer, int32_t* size) C_RESULT ardrone_control_write(const uint8_t* buffer, int32_t* size)
{ {
C_RESULT res = C_FAIL; C_RESULT res = C_FAIL;
if( control_write != NULL ) if( control_write != NULL )
{ {
res = control_write(&control_socket, buffer, size); res = control_write(&control_socket, buffer, size);
} }
return res; return res;
} }
C_RESULT ardrone_control_send_event( ardrone_control_event_t* event ) C_RESULT ardrone_control_send_event( ardrone_control_event_t* event )
{ {
C_RESULT res; C_RESULT res;
int32_t next_index_in_queue; int32_t next_index_in_queue;
res = C_FAIL; res = C_FAIL;
vp_os_mutex_lock(&event_queue_mutex); vp_os_mutex_lock(&event_queue_mutex);
next_index_in_queue = (start_index_in_queue + 1) & (ARDRONE_CONTROL_MAX_NUM_EVENTS_IN_QUEUE - 1); next_index_in_queue = (start_index_in_queue + 1) & (ARDRONE_CONTROL_MAX_NUM_EVENTS_IN_QUEUE - 1);
if( next_index_in_queue != end_index_in_queue ) if( next_index_in_queue != end_index_in_queue )
{ {
ardrone_control_event_queue[start_index_in_queue] = event; ardrone_control_event_queue[start_index_in_queue] = event;
start_index_in_queue = next_index_in_queue; start_index_in_queue = next_index_in_queue;
res = C_OK; res = C_OK;
} }
vp_os_mutex_unlock(&event_queue_mutex); vp_os_mutex_unlock(&event_queue_mutex);
return res; return res;
} }
DEFINE_THREAD_ROUTINE( ardrone_control, nomParams ) DEFINE_THREAD_ROUTINE( ardrone_control, nomParams )
{ {
C_RESULT res_wait_navdata = C_OK; C_RESULT res_wait_navdata = C_OK;
C_RESULT res = C_OK; C_RESULT res = C_OK;
uint32_t retry, current_ardrone_state; uint32_t retry, current_ardrone_state;
int32_t next_index_in_queue; int32_t next_index_in_queue;
ardrone_control_event_ptr_t current_event; ardrone_control_event_ptr_t current_event;
retry = 0; retry = 0;
current_event = NULL; current_event = NULL;
DEBUG_PRINT_SDK("Thread control in progress...\n"); DEBUG_PRINT_SDK("Thread control in progress...\n");
control_socket.is_disable = TRUE; control_socket.is_disable = TRUE;
ardrone_control_connect_to_drone(); ardrone_control_connect_to_drone();
while( bContinue while( bContinue
&& !ardrone_tool_exit() ) && !ardrone_tool_exit() )
{ {
vp_os_mutex_lock(&control_mutex); vp_os_mutex_lock(&control_mutex);
control_waited = TRUE; control_waited = TRUE;
/* Wait for new navdata to be received. */ /* Wait for new navdata to be received. */
res_wait_navdata = vp_os_cond_timed_wait(&control_cond, 1000); res_wait_navdata = vp_os_cond_timed_wait(&control_cond, 1000);
vp_os_mutex_unlock(&control_mutex); vp_os_mutex_unlock(&control_mutex);
/* /*
* In case of timeout on the navdata, we assume that there was a problem * In case of timeout on the navdata, we assume that there was a problem
* with the Wifi connection. * with the Wifi connection.
* It is then safer to close and reopen the control socket (TCP 5559) since * It is then safer to close and reopen the control socket (TCP 5559) since
* some OS might stop giving data but not signal any disconnection. * some OS might stop giving data but not signal any disconnection.
*/ */
if(VP_FAILED(res_wait_navdata)) if(VP_FAILED(res_wait_navdata))
{ {
if (FALSE == control_socket.is_disable) if (FALSE == control_socket.is_disable)
{ {
DEBUG_PRINT_SDK("Timeout while waiting for new navdata.\n"); DEBUG_PRINT_SDK("Timeout while waiting for new navdata.\n");
vp_com_close(COM_CONTROL(), &control_socket); vp_com_close(COM_CONTROL(), &control_socket);
control_socket.is_disable = TRUE; control_socket.is_disable = TRUE;
} }
} }
else else
{ {
if(control_socket.is_disable) if(control_socket.is_disable)
{ {
ardrone_control_connect_to_drone(); ardrone_control_connect_to_drone();
} }
if(VP_SUCCEEDED(res_wait_navdata) && (!control_socket.is_disable)) if(VP_SUCCEEDED(res_wait_navdata) && (!control_socket.is_disable))
{ {
vp_os_mutex_lock(&control_mutex); vp_os_mutex_lock(&control_mutex);
current_ardrone_state = ardrone_state; current_ardrone_state = ardrone_state;
control_waited = FALSE; control_waited = FALSE;
vp_os_mutex_unlock(&control_mutex); vp_os_mutex_unlock(&control_mutex);
if( ardrone_tool_exit() ) // Test if we received a signal because we are quitting the application if( ardrone_tool_exit() ) // Test if we received a signal because we are quitting the application
THREAD_RETURN( res ); THREAD_RETURN( res );
if( current_event == NULL ) if( current_event == NULL )
{ {
vp_os_mutex_lock(&event_queue_mutex); vp_os_mutex_lock(&event_queue_mutex);
next_index_in_queue = (end_index_in_queue + 1) & (ARDRONE_CONTROL_MAX_NUM_EVENTS_IN_QUEUE - 1); next_index_in_queue = (end_index_in_queue + 1) & (ARDRONE_CONTROL_MAX_NUM_EVENTS_IN_QUEUE - 1);
if( next_index_in_queue != start_index_in_queue ) if( next_index_in_queue != start_index_in_queue )
{ // There's an event to process { // There's an event to process
current_event = ardrone_control_event_queue[next_index_in_queue]; current_event = ardrone_control_event_queue[next_index_in_queue];
if( current_event != NULL ) if( current_event != NULL )
{ {
if( current_event->ardrone_control_event_start != NULL ) if( current_event->ardrone_control_event_start != NULL )
{ {
current_event->ardrone_control_event_start( current_event ); current_event->ardrone_control_event_start( current_event );
} }
} }
end_index_in_queue = next_index_in_queue; end_index_in_queue = next_index_in_queue;
retry = 0; retry = 0;
}
vp_os_mutex_unlock(&event_queue_mutex);
}
if( current_event != NULL )
{
switch( current_event->event )
{
case CFG_GET_CONTROL_MODE:
case CUSTOM_CFG_GET_CONTROL_MODE: /* multiconfiguration support */
res = ardrone_control_configuration_run( current_ardrone_state, (ardrone_control_configuration_event_t*) current_event );
break;
case ACK_CONTROL_MODE:
res = ardrone_control_ack_run( current_ardrone_state, (ardrone_control_ack_event_t *) current_event);
break;
default:
break;
}
if( VP_FAILED(res) )
{
retry ++;
if( retry > current_event->num_retries)
current_event->status = ARDRONE_CONTROL_EVENT_FINISH_FAILURE;
}
else
{
retry = 0;
}
if( current_event->status & ARDRONE_CONTROL_EVENT_FINISH )
{
if( current_event->ardrone_control_event_end != NULL )
current_event->ardrone_control_event_end( current_event );
/* Make the thread read a new event on the next loop iteration */
current_event = NULL;
}
else
{
/* Not changing 'current_event' makes the loop process the same
* event when the next navdata packet arrives. */
} }
}
}
}
}// while
vp_os_mutex_unlock(&event_queue_mutex); /*Bug fix - mutexes were previously detroyed by another thread,
} which made ardrone_control crash.*/
vp_os_mutex_destroy(&event_queue_mutex);
vp_os_cond_destroy(&control_cond);
vp_os_mutex_destroy(&control_mutex);
if( current_event != NULL ) vp_com_close(COM_CONTROL(), &control_socket);
{
switch( current_event->event )
{
case CFG_GET_CONTROL_MODE:
case CUSTOM_CFG_GET_CONTROL_MODE: /* multiconfiguration support */
res = ardrone_control_configuration_run( current_ardrone_state, (ardrone_control_configuration_event_t*) current_event );
break;
case ACK_CONTROL_MODE: THREAD_RETURN( res );
res = ardrone_control_ack_run( current_ardrone_state, (ardrone_control_ack_event_t *) current_event);
break;
default:
break;
}
if( VP_FAILED(res) )
{
retry ++;
if( retry > current_event->num_retries)
current_event->status = ARDRONE_CONTROL_EVENT_FINISH_FAILURE;
}
else
{
retry = 0;
}
if( current_event->status & ARDRONE_CONTROL_EVENT_FINISH )
{
if( current_event->ardrone_control_event_end != NULL )
current_event->ardrone_control_event_end( current_event );
/* Make the thread read a new event on the next loop iteration */
current_event = NULL;
}
else
{
/* Not changing 'current_event' makes the loop process the same
* event when the next navdata packet arrives. */
}
}
}
}
}// while
/* Stephane : Bug fix - mutexes were previously detroyed by another thread,
which made ardrone_control crash.*/
vp_os_mutex_destroy(&event_queue_mutex);
vp_os_cond_destroy(&control_cond);
vp_os_mutex_destroy(&control_mutex);
vp_com_close(COM_CONTROL(), &control_socket);
THREAD_RETURN( res );
} }
@@ -24,61 +24,61 @@
typedef enum typedef enum
{ {
SCREENSHOT_STATE_IDLE, SCREENSHOT_STATE_IDLE,
SCREENSHOT_STATE_NEEDED, SCREENSHOT_STATE_NEEDED,
SCREENSHOT_STATE_INPROGRESS, SCREENSHOT_STATE_INPROGRESS,
} SCREENSHOT_STATE; } SCREENSHOT_STATE;
typedef enum typedef enum
{ {
TAKEOFF_STATE_IDLE, TAKEOFF_STATE_IDLE,
TAKEOFF_STATE_NEEDED, TAKEOFF_STATE_NEEDED,
TAKEOFF_STATE_WAIT_USERBOX, TAKEOFF_STATE_WAIT_USERBOX,
TAKEOFF_STATE_CANCELLING, TAKEOFF_STATE_CANCELLING,
} TAKEOFF_STATE; } TAKEOFF_STATE;
typedef enum typedef enum
{ {
RECORD_STATE_IDLE, RECORD_STATE_IDLE,
RECORD_STATE_NEEDED, RECORD_STATE_NEEDED,
RECORD_STATE_WAIT_USERBOX, RECORD_STATE_WAIT_USERBOX,
} RECORD_STATE; } RECORD_STATE;
typedef enum typedef enum
{ {
USERBOX_STATE_STARTING, USERBOX_STATE_STARTING,
USERBOX_STATE_STARTED, USERBOX_STATE_STARTED,
USERBOX_STATE_STOPPING, USERBOX_STATE_STOPPING,
USERBOX_STATE_STOPPED, USERBOX_STATE_STOPPED,
} USERBOX_STATE; } USERBOX_STATE;
typedef struct typedef struct
{ {
/** /**
* variable to know if setting is needed * variable to know if setting is needed
*/ */
bool_t wasEmergency; bool_t wasEmergency;
bool_t needSetEmergency; bool_t needSetEmergency;
TAKEOFF_STATE takeoff_state; TAKEOFF_STATE takeoff_state;
time_t takeoff_time; time_t takeoff_time;
RECORD_STATE record_state; RECORD_STATE record_state;
USERBOX_STATE userbox_state; USERBOX_STATE userbox_state;
SCREENSHOT_STATE screenshot_state; SCREENSHOT_STATE screenshot_state;
time_t userbox_time; time_t userbox_time;
vp_os_mutex_t aan_mutex; vp_os_mutex_t aan_mutex;
uint32_t usbFreeTime; uint32_t usbFreeTime;
bool_t droneStoppedUsbRecording; bool_t droneStoppedUsbRecording;
bool_t takeOffWasCancelled; bool_t takeOffWasCancelled;
/** /**
* Strings to display in interface * Strings to display in interface
*/ */
bool_t isTakeOff; bool_t isTakeOff;
bool_t isEmergency; bool_t isEmergency;
uint32_t lastState; uint32_t lastState;
bool_t cameraIsReady; bool_t cameraIsReady;
bool_t usbIsReady; bool_t usbIsReady;
bool_t usbRecordInProgress; bool_t usbRecordInProgress;
bool_t internalRecordInProgress; bool_t internalRecordInProgress;
} ardrone_academy_navdata_state_t; } ardrone_academy_navdata_state_t;
@@ -97,10 +97,10 @@ bool_t ardrone_academy_navdata_takeoff(void)
bool_t shouldNotDo = (TRUE == isBatteryLow && FALSE == navdata_state.isTakeOff) ? TRUE : FALSE; bool_t shouldNotDo = (TRUE == isBatteryLow && FALSE == navdata_state.isTakeOff) ? TRUE : FALSE;
if(navdata_state.takeoff_state == TAKEOFF_STATE_IDLE && if(navdata_state.takeoff_state == TAKEOFF_STATE_IDLE &&
FALSE == shouldNotDo) FALSE == shouldNotDo)
{ {
LOCK_ND_MUTEX (); LOCK_ND_MUTEX ();
navdata_state.takeoff_state = TAKEOFF_STATE_NEEDED; navdata_state.takeoff_state = TAKEOFF_STATE_NEEDED;
navdata_state.takeoff_time = time (NULL); navdata_state.takeoff_time = time (NULL);
UNLOCK_ND_MUTEX (); UNLOCK_ND_MUTEX ();
result = TRUE; result = TRUE;
} }
@@ -110,20 +110,20 @@ bool_t ardrone_academy_navdata_takeoff(void)
bool_t ardrone_academy_navdata_emergency(void) bool_t ardrone_academy_navdata_emergency(void)
{ {
bool_t result = TRUE; bool_t result = TRUE;
LOCK_ND_MUTEX (); LOCK_ND_MUTEX ();
navdata_state.needSetEmergency = TRUE; navdata_state.needSetEmergency = TRUE;
UNLOCK_ND_MUTEX (); UNLOCK_ND_MUTEX ();
return result; return result;
} }
bool_t ardrone_academy_navdata_record(void) bool_t ardrone_academy_navdata_record(void)
{ {
bool_t result = FALSE; bool_t result = FALSE;
if(navdata_state.record_state == RECORD_STATE_IDLE) if(navdata_state.record_state == RECORD_STATE_IDLE)
{ {
LOCK_ND_MUTEX (); LOCK_ND_MUTEX ();
navdata_state.record_state = RECORD_STATE_NEEDED; navdata_state.record_state = RECORD_STATE_NEEDED;
UNLOCK_ND_MUTEX (); UNLOCK_ND_MUTEX ();
result = TRUE; result = TRUE;
} }
return result; return result;
@@ -132,11 +132,11 @@ bool_t ardrone_academy_navdata_record(void)
bool_t ardrone_academy_navdata_screenshot(void) bool_t ardrone_academy_navdata_screenshot(void)
{ {
bool_t result = FALSE; bool_t result = FALSE;
if(navdata_state.screenshot_state == SCREENSHOT_STATE_IDLE) if(navdata_state.screenshot_state == SCREENSHOT_STATE_IDLE)
{ {
LOCK_ND_MUTEX (); LOCK_ND_MUTEX ();
navdata_state.screenshot_state = SCREENSHOT_STATE_NEEDED; navdata_state.screenshot_state = SCREENSHOT_STATE_NEEDED;
UNLOCK_ND_MUTEX (); UNLOCK_ND_MUTEX ();
result = TRUE; result = TRUE;
} }
return result; return result;
@@ -144,40 +144,40 @@ bool_t ardrone_academy_navdata_screenshot(void)
bool_t ardrone_academy_navdata_get_camera_state(void) bool_t ardrone_academy_navdata_get_camera_state(void)
{ {
return (navdata_state.cameraIsReady && (navdata_state.screenshot_state == SCREENSHOT_STATE_IDLE)); return (navdata_state.cameraIsReady && (navdata_state.screenshot_state == SCREENSHOT_STATE_IDLE));
} }
bool_t ardrone_academy_navdata_get_usb_state(void) bool_t ardrone_academy_navdata_get_usb_state(void)
{ {
return navdata_state.usbIsReady; return navdata_state.usbIsReady;
} }
bool_t ardrone_academy_navdata_get_takeoff_state(void) bool_t ardrone_academy_navdata_get_takeoff_state(void)
{ {
return navdata_state.isTakeOff; return navdata_state.isTakeOff;
} }
bool_t ardrone_academy_navdata_get_record_ready(void) bool_t ardrone_academy_navdata_get_record_ready(void)
{ {
bool_t result = FALSE; bool_t result = FALSE;
if(1 == ARDRONE_VERSION()) if(1 == ARDRONE_VERSION())
{ {
result = ardrone_academy_stage_recorder_state(); result = ardrone_academy_stage_recorder_state();
} }
else if(2 == ARDRONE_VERSION()) else if(2 == ARDRONE_VERSION())
{ {
#if defined (RECORD_ENCODED_VIDEO) #if defined (RECORD_ENCODED_VIDEO)
result = (video_stage_encoded_recorder_state() || navdata_state.usbRecordInProgress); result = (video_stage_encoded_recorder_state() || navdata_state.usbRecordInProgress);
#else #else
printf("ARDRONE VERSION 2 NEEDS RECORD_ENCODED_VIDEO MACRO!!!\n"); PRINT("ARDRONE VERSION 2 NEEDS RECORD_ENCODED_VIDEO MACRO!!!\n");
#endif #endif
} }
else else
{ {
printf("ARDRONE VERSION NOT INITIALIZED !!!\n"); PRINT("ARDRONE VERSION NOT INITIALIZED !!!\n");
} }
return result; return result;
} }
bool_t ardrone_academy_navdata_get_record_state(void) bool_t ardrone_academy_navdata_get_record_state(void)
@@ -196,19 +196,19 @@ bool_t ardrone_academy_navdata_get_record_state(void)
( VIDEO_ENCODED_STOPPED != recState && ( VIDEO_ENCODED_STOPPED != recState &&
VIDEO_ENCODED_WAITING_STREAM_END != recState); VIDEO_ENCODED_WAITING_STREAM_END != recState);
#else #else
printf("ARDRONE VERSION 2 NEEDS RECORD_ENCODED_VIDEO MACRO!!!\n"); PRINT("ARDRONE VERSION 2 NEEDS RECORD_ENCODED_VIDEO MACRO!!!\n");
#endif #endif
} }
else else
{ {
printf("ARDRONE VERSION NOT INITIALIZED !!!\n"); PRINT("ARDRONE VERSION NOT INITIALIZED !!!\n");
} }
return result; return result;
} }
bool_t ardrone_academy_navdata_get_emergency_state(void) bool_t ardrone_academy_navdata_get_emergency_state(void)
{ {
return navdata_state.isEmergency; return navdata_state.isEmergency;
} }
uint32_t ardrone_academy_navdata_get_remaining_usb_time (void) uint32_t ardrone_academy_navdata_get_remaining_usb_time (void)
@@ -236,154 +236,154 @@ bool_t ardrone_academy_navdata_check_takeoff_cancelled (void)
void ardrone_academy_navdata_recorder_enable(bool_t enable, uint32_t timestamp) void ardrone_academy_navdata_recorder_enable(bool_t enable, uint32_t timestamp)
{ {
if(1 == ARDRONE_VERSION()) if(1 == ARDRONE_VERSION())
{ {
ardrone_academy_stage_recorder_enable(enable, timestamp); ardrone_academy_stage_recorder_enable(enable, timestamp);
} }
else if(2 == ARDRONE_VERSION()) else if(2 == ARDRONE_VERSION())
{ {
#if defined (RECORD_ENCODED_VIDEO) #if defined (RECORD_ENCODED_VIDEO)
if (1 == enable) if (1 == enable)
{ {
/* /*
Calling this function to disable the recorder is to be made outside Calling this function to disable the recorder is to be made outside
a navdata handler, so we can finish a video even if the drone is a navdata handler, so we can finish a video even if the drone is
disconnected (battery removed, or out of wifi range) disconnected (battery removed, or out of wifi range)
The disable call is made inside the UI "button press" callbacks The disable call is made inside the UI "button press" callbacks
*/ */
video_stage_encoded_recorder_enable(enable, timestamp); video_stage_encoded_recorder_enable(enable, timestamp);
} }
#else #else
printf("ARDRONE VERSION 2 NEEDS RECORD_ENCODED_VIDEO MACRO!!!\n"); PRINT("ARDRONE VERSION 2 NEEDS RECORD_ENCODED_VIDEO MACRO!!!\n");
#endif #endif
} }
else else
{ {
printf("ARDRONE VERSION NOT INITIALIZED !!!\n"); PRINT("ARDRONE VERSION NOT INITIALIZED !!!\n");
} }
} }
FLYING_STATE ardrone_academy_navdata_get_flying_state(const navdata_unpacked_t* data) FLYING_STATE ardrone_academy_navdata_get_flying_state(const navdata_unpacked_t* data)
{ {
FLYING_STATE tmp_state; FLYING_STATE tmp_state;
switch ((data->navdata_demo.ctrl_state >> 16)) switch ((data->navdata_demo.ctrl_state >> 16))
{ {
case CTRL_FLYING: case CTRL_FLYING:
case CTRL_HOVERING: case CTRL_HOVERING:
case CTRL_TRANS_GOTOFIX: case CTRL_TRANS_GOTOFIX:
case CTRL_TRANS_LOOPING: case CTRL_TRANS_LOOPING:
tmp_state = FLYING_STATE_FLYING; tmp_state = FLYING_STATE_FLYING;
break; break;
case CTRL_TRANS_TAKEOFF: case CTRL_TRANS_TAKEOFF:
tmp_state = FLYING_STATE_TAKING_OFF; tmp_state = FLYING_STATE_TAKING_OFF;
break; break;
case CTRL_TRANS_LANDING: case CTRL_TRANS_LANDING:
tmp_state = FLYING_STATE_LANDING; tmp_state = FLYING_STATE_LANDING;
break; break;
case CTRL_DEFAULT: case CTRL_DEFAULT:
case CTRL_LANDED: case CTRL_LANDED:
default: default:
tmp_state = FLYING_STATE_LANDED; tmp_state = FLYING_STATE_LANDED;
break; break;
} }
return tmp_state; return tmp_state;
} }
void ardrone_academy_navdata_userbox_cb(bool_t result) void ardrone_academy_navdata_userbox_cb(bool_t result)
{ {
if(result) if(result)
{ {
LOCK_ND_MUTEX (); LOCK_ND_MUTEX ();
if(navdata_state.userbox_state == USERBOX_STATE_STARTING) if(navdata_state.userbox_state == USERBOX_STATE_STARTING)
{ {
printf("Userbox started\n"); PRINT("Userbox started\n");
navdata_state.userbox_state = USERBOX_STATE_STARTED; navdata_state.userbox_state = USERBOX_STATE_STARTED;
switch (navdata_state.takeoff_state) switch (navdata_state.takeoff_state)
{ {
case TAKEOFF_STATE_WAIT_USERBOX: case TAKEOFF_STATE_WAIT_USERBOX:
navdata_state.takeoff_state = TAKEOFF_STATE_IDLE; navdata_state.takeoff_state = TAKEOFF_STATE_IDLE;
ardrone_tool_set_ui_pad_start(1); ardrone_tool_set_ui_pad_start(1);
break; break;
case TAKEOFF_STATE_CANCELLING: case TAKEOFF_STATE_CANCELLING:
navdata_state.takeoff_state = TAKEOFF_STATE_IDLE; navdata_state.takeoff_state = TAKEOFF_STATE_IDLE;
ardrone_tool_set_ui_pad_start(0); ardrone_tool_set_ui_pad_start(0);
break; break;
default: default:
break; break;
} }
if(navdata_state.record_state == RECORD_STATE_WAIT_USERBOX) if(navdata_state.record_state == RECORD_STATE_WAIT_USERBOX)
{ {
navdata_state.record_state = RECORD_STATE_IDLE; navdata_state.record_state = RECORD_STATE_IDLE;
if (FALSE == navdata_state.usbRecordInProgress) if (FALSE == navdata_state.usbRecordInProgress)
{ {
ardrone_academy_navdata_recorder_enable(TRUE, navdata_state.userbox_time); ardrone_academy_navdata_recorder_enable(TRUE, navdata_state.userbox_time);
}
} }
} }
else if(navdata_state.userbox_state == USERBOX_STATE_STOPPING) }
else if(navdata_state.userbox_state == USERBOX_STATE_STOPPING)
{ {
printf("Userbox stopped\n"); PRINT("Userbox stopped\n");
academy_download_resume (); academy_download_resume ();
if(navdata_state.takeoff_state == TAKEOFF_STATE_WAIT_USERBOX || if(navdata_state.takeoff_state == TAKEOFF_STATE_WAIT_USERBOX ||
TAKEOFF_STATE_CANCELLING == navdata_state.takeoff_state) TAKEOFF_STATE_CANCELLING == navdata_state.takeoff_state)
{ {
navdata_state.takeoff_state = TAKEOFF_STATE_IDLE; navdata_state.takeoff_state = TAKEOFF_STATE_IDLE;
ardrone_tool_set_ui_pad_start(0); ardrone_tool_set_ui_pad_start(0);
} }
if(navdata_state.record_state == RECORD_STATE_WAIT_USERBOX) if(navdata_state.record_state == RECORD_STATE_WAIT_USERBOX)
{ {
navdata_state.record_state = RECORD_STATE_IDLE; navdata_state.record_state = RECORD_STATE_IDLE;
ardrone_academy_navdata_recorder_enable(FALSE, navdata_state.userbox_time); ardrone_academy_navdata_recorder_enable(FALSE, navdata_state.userbox_time);
navdata_state.usbRecordInProgress = FALSE; navdata_state.usbRecordInProgress = FALSE;
} }
navdata_state.userbox_state = USERBOX_STATE_STOPPED; navdata_state.userbox_state = USERBOX_STATE_STOPPED;
} }
UNLOCK_ND_MUTEX (); UNLOCK_ND_MUTEX ();
} }
} }
void ardrone_academy_navdata_screenshot_cb(bool_t result) void ardrone_academy_navdata_screenshot_cb(bool_t result)
{ {
if(result) if(result)
{ {
LOCK_ND_MUTEX (); LOCK_ND_MUTEX ();
if(navdata_state.screenshot_state == SCREENSHOT_STATE_INPROGRESS) if(navdata_state.screenshot_state == SCREENSHOT_STATE_INPROGRESS)
{ {
navdata_state.screenshot_state = SCREENSHOT_STATE_IDLE; navdata_state.screenshot_state = SCREENSHOT_STATE_IDLE;
} }
UNLOCK_ND_MUTEX (); UNLOCK_ND_MUTEX ();
} }
} }
void ardrone_academy_check_take_off_timeout (void) void ardrone_academy_check_take_off_timeout (void)
{ {
static char cancelCommand[ARDRONE_DATE_MAXSIZE]; static char cancelCommand[ARDRONE_DATE_MAXSIZE];
time_t elapsedTime = time (NULL) - navdata_state.takeoff_time; time_t elapsedTime = time (NULL) - navdata_state.takeoff_time;
if (TAKEOFF_TIMEOUT_SEC < elapsedTime) if (TAKEOFF_TIMEOUT_SEC < elapsedTime)
{ {
switch (navdata_state.takeoff_state) switch (navdata_state.takeoff_state)
{ {
case TAKEOFF_STATE_WAIT_USERBOX: case TAKEOFF_STATE_WAIT_USERBOX:
snprintf (cancelCommand, ARDRONE_DATE_MAXSIZE-1, "%d", USERBOX_CMD_CANCEL); snprintf (cancelCommand, ARDRONE_DATE_MAXSIZE-1, "%d", USERBOX_CMD_CANCEL);
navdata_state.userbox_state = USERBOX_STATE_STOPPING; navdata_state.userbox_state = USERBOX_STATE_STOPPING;
navdata_state.takeoff_state = TAKEOFF_STATE_CANCELLING; navdata_state.takeoff_state = TAKEOFF_STATE_CANCELLING;
ARDRONE_TOOL_CONFIGURATION_ADDEVENT (userbox_cmd, cancelCommand, ardrone_academy_navdata_userbox_cb); ARDRONE_TOOL_CONFIGURATION_ADDEVENT (userbox_cmd, cancelCommand, ardrone_academy_navdata_userbox_cb);
navdata_state.takeOffWasCancelled = TRUE; navdata_state.takeOffWasCancelled = TRUE;
break; break;
case TAKEOFF_STATE_NEEDED: case TAKEOFF_STATE_NEEDED:
navdata_state.takeoff_state = TAKEOFF_STATE_IDLE; navdata_state.takeoff_state = TAKEOFF_STATE_IDLE;
navdata_state.takeOffWasCancelled = TRUE; navdata_state.takeOffWasCancelled = TRUE;
break; break;
default: default:
break; break;
} }
} }
} }
@@ -391,58 +391,58 @@ void ardrone_academy_check_take_off_timeout (void)
void ardrone_academy_navdata_userbox_switch(void) void ardrone_academy_navdata_userbox_switch(void)
{ {
static char param[ARDRONE_DATE_MAXSIZE + 8]; static char param[ARDRONE_DATE_MAXSIZE + 8];
static char date[ARDRONE_DATE_MAXSIZE]; static char date[ARDRONE_DATE_MAXSIZE];
if(navdata_state.userbox_state == USERBOX_STATE_STOPPED) if(navdata_state.userbox_state == USERBOX_STATE_STOPPED)
{ {
navdata_state.userbox_time = time(NULL); navdata_state.userbox_time = time(NULL);
ardrone_time2date(navdata_state.userbox_time, ARDRONE_FILE_DATE_FORMAT, date); ardrone_time2date(navdata_state.userbox_time, ARDRONE_FILE_DATE_FORMAT, date);
sprintf(param, "%d,%s", USERBOX_CMD_START, date); sprintf(param, "%d,%s", USERBOX_CMD_START, date);
navdata_state.userbox_state = USERBOX_STATE_STARTING; navdata_state.userbox_state = USERBOX_STATE_STARTING;
ARDRONE_TOOL_CONFIGURATION_ADDEVENT(userbox_cmd, param, ardrone_academy_navdata_userbox_cb); ARDRONE_TOOL_CONFIGURATION_ADDEVENT(userbox_cmd, param, ardrone_academy_navdata_userbox_cb);
} }
else if(navdata_state.userbox_state == USERBOX_STATE_STARTED) else if(navdata_state.userbox_state == USERBOX_STATE_STARTED)
{ {
sprintf(param, "%d", USERBOX_CMD_STOP); sprintf(param, "%d", USERBOX_CMD_STOP);
navdata_state.userbox_state = USERBOX_STATE_STOPPING; navdata_state.userbox_state = USERBOX_STATE_STOPPING;
ARDRONE_TOOL_CONFIGURATION_ADDEVENT(userbox_cmd, param, ardrone_academy_navdata_userbox_cb); ARDRONE_TOOL_CONFIGURATION_ADDEVENT(userbox_cmd, param, ardrone_academy_navdata_userbox_cb);
} }
} }
C_RESULT ardrone_academy_navdata_init(void* data) C_RESULT ardrone_academy_navdata_init(void* data)
{ {
navdata_state.wasEmergency = FALSE; navdata_state.wasEmergency = FALSE;
navdata_state.needSetEmergency = FALSE; navdata_state.needSetEmergency = FALSE;
navdata_state.takeoff_state = TAKEOFF_STATE_IDLE; navdata_state.takeoff_state = TAKEOFF_STATE_IDLE;
navdata_state.record_state = TAKEOFF_STATE_IDLE; navdata_state.record_state = TAKEOFF_STATE_IDLE;
navdata_state.userbox_state = USERBOX_STATE_STOPPED; navdata_state.userbox_state = USERBOX_STATE_STOPPED;
navdata_state.isTakeOff = FALSE; navdata_state.isTakeOff = FALSE;
navdata_state.isEmergency = FALSE; navdata_state.isEmergency = FALSE;
navdata_state.cameraIsReady = FALSE; navdata_state.cameraIsReady = FALSE;
navdata_state.usbIsReady = FALSE; navdata_state.usbIsReady = FALSE;
navdata_state.usbRecordInProgress = FALSE; navdata_state.usbRecordInProgress = FALSE;
navdata_state.userbox_time = (time_t)0; navdata_state.userbox_time = (time_t)0;
navdata_state.takeoff_time = (time_t)0; navdata_state.takeoff_time = (time_t)0;
navdata_state.usbFreeTime = 0; navdata_state.usbFreeTime = 0;
navdata_state.droneStoppedUsbRecording = FALSE; navdata_state.droneStoppedUsbRecording = FALSE;
navdata_state.takeOffWasCancelled = FALSE; navdata_state.takeOffWasCancelled = FALSE;
navdata_state.internalRecordInProgress = FALSE; navdata_state.internalRecordInProgress = FALSE;
navdata_state.lastState = 0; navdata_state.lastState = 0;
vp_os_mutex_init (&navdata_state.aan_mutex); vp_os_mutex_init (&navdata_state.aan_mutex);
return C_OK; return C_OK;
} }
C_RESULT ardrone_academy_navdata_process( const navdata_unpacked_t* const pnd ) C_RESULT ardrone_academy_navdata_process( const navdata_unpacked_t* const pnd )
{ {
static bool_t prevCameraIsReady = FALSE; static bool_t prevCameraIsReady = FALSE;
static bool_t prevDroneUsbRecording = FALSE; static bool_t prevDroneUsbRecording = FALSE;
if (C_OK == TRYLOCK_ND_MUTEX ()) if (C_OK == TRYLOCK_ND_MUTEX ())
{ {
input_state_t* input_state = ardrone_tool_input_get_state(); input_state_t* input_state = ardrone_tool_input_get_state();
bool_t recordIsReady = ! ardrone_academy_navdata_get_record_ready(); bool_t recordIsReady = ! ardrone_academy_navdata_get_record_ready();
bool_t recordIsInProgress = ardrone_academy_navdata_get_record_state(); bool_t recordIsInProgress = ardrone_academy_navdata_get_record_state();
// Save ARDrone State // Save ARDrone State
navdata_state.lastState = pnd->ardrone_state; navdata_state.lastState = pnd->ardrone_state;
@@ -462,80 +462,80 @@ C_RESULT ardrone_academy_navdata_process( const navdata_unpacked_t* const pnd )
} }
prevDroneUsbRecording = currentDroneUsbRecording; prevDroneUsbRecording = currentDroneUsbRecording;
ardrone_academy_check_take_off_timeout (); ardrone_academy_check_take_off_timeout ();
// Take off and Emergency management // Take off and Emergency management
if(navdata_state.takeoff_state == TAKEOFF_STATE_NEEDED) if(navdata_state.takeoff_state == TAKEOFF_STATE_NEEDED)
{ {
if(pnd->ardrone_state & ARDRONE_EMERGENCY_MASK) if(pnd->ardrone_state & ARDRONE_EMERGENCY_MASK)
{ {
navdata_state.needSetEmergency = TRUE; navdata_state.needSetEmergency = TRUE;
} }
else else
{ {
if(recordIsInProgress) if(recordIsInProgress)
{ {
if(!(pnd->ardrone_state & ARDRONE_USER_FEEDBACK_START)) if(!(pnd->ardrone_state & ARDRONE_USER_FEEDBACK_START))
ardrone_tool_set_ui_pad_start(1); ardrone_tool_set_ui_pad_start(1);
else else
ardrone_tool_set_ui_pad_start(0); ardrone_tool_set_ui_pad_start(0);
navdata_state.takeoff_state = TAKEOFF_STATE_IDLE; navdata_state.takeoff_state = TAKEOFF_STATE_IDLE;
} }
else else
{ {
navdata_state.takeoff_state = TAKEOFF_STATE_WAIT_USERBOX; navdata_state.takeoff_state = TAKEOFF_STATE_WAIT_USERBOX;
ardrone_academy_navdata_userbox_switch(); ardrone_academy_navdata_userbox_switch();
} }
} }
} }
if(navdata_state.needSetEmergency) if(navdata_state.needSetEmergency)
{ {
ardrone_tool_set_ui_pad_select(1); ardrone_tool_set_ui_pad_select(1);
navdata_state.needSetEmergency = FALSE; navdata_state.needSetEmergency = FALSE;
} }
if(pnd->ardrone_state & ARDRONE_EMERGENCY_MASK) if(pnd->ardrone_state & ARDRONE_EMERGENCY_MASK)
{ {
if(!navdata_state.wasEmergency && (input_state->user_input & (1 << ARDRONE_UI_BIT_SELECT))) if(!navdata_state.wasEmergency && (input_state->user_input & (1 << ARDRONE_UI_BIT_SELECT)))
{ {
ardrone_tool_set_ui_pad_select(0); ardrone_tool_set_ui_pad_select(0);
} }
navdata_state.isEmergency = TRUE; navdata_state.isEmergency = TRUE;
navdata_state.isTakeOff = FALSE; navdata_state.isTakeOff = FALSE;
if(!navdata_state.internalRecordInProgress && !navdata_state.usbRecordInProgress && (navdata_state.userbox_state == USERBOX_STATE_STARTED)) if(!navdata_state.internalRecordInProgress && !navdata_state.usbRecordInProgress && (navdata_state.userbox_state == USERBOX_STATE_STARTED))
{ {
printf("Emergency !! Stopping userbox...\n"); PRINT("Emergency !! Stopping userbox...\n");
ardrone_academy_navdata_userbox_switch(); ardrone_academy_navdata_userbox_switch();
} }
ardrone_tool_input_start_reset(); ardrone_tool_input_start_reset();
} }
else // Not emergency landing else // Not emergency landing
{ {
if(navdata_state.wasEmergency && (input_state->user_input & (1 << ARDRONE_UI_BIT_SELECT))) if(navdata_state.wasEmergency && (input_state->user_input & (1 << ARDRONE_UI_BIT_SELECT)))
{ {
ardrone_tool_set_ui_pad_select(0); ardrone_tool_set_ui_pad_select(0);
} }
if(!(pnd->ardrone_state & ARDRONE_TIMER_ELAPSED))
navdata_state.isEmergency = FALSE;
if(!(pnd->ardrone_state & ARDRONE_TIMER_ELAPSED)) if(input_state->user_input & (1 << ARDRONE_UI_BIT_START))
navdata_state.isEmergency = FALSE;
if(input_state->user_input & (1 << ARDRONE_UI_BIT_START))
{ {
navdata_state.isTakeOff = (pnd->ardrone_state & ARDRONE_USER_FEEDBACK_START) ? TRUE : FALSE; navdata_state.isTakeOff = (pnd->ardrone_state & ARDRONE_USER_FEEDBACK_START) ? TRUE : FALSE;
} }
else else
{ {
navdata_state.isTakeOff = FALSE; navdata_state.isTakeOff = FALSE;
} }
} }
navdata_state.wasEmergency = (pnd->ardrone_state & ARDRONE_EMERGENCY_MASK) ? TRUE : FALSE; navdata_state.wasEmergency = (pnd->ardrone_state & ARDRONE_EMERGENCY_MASK) ? TRUE : FALSE;
// Video record management // Video record management
bool_t usbRecordEnable = FALSE; bool_t usbRecordEnable = FALSE;
if(navdata_state.record_state == RECORD_STATE_NEEDED && if(navdata_state.record_state == RECORD_STATE_NEEDED &&
@@ -544,34 +544,34 @@ C_RESULT ardrone_academy_navdata_process( const navdata_unpacked_t* const pnd )
bool_t continueRecord = TRUE; bool_t continueRecord = TRUE;
bool_t nextInternalRecordState = FALSE; bool_t nextInternalRecordState = FALSE;
if (IS_LEAST_ARDRONE2) if (IS_LEAST_ARDRONE2)
{ {
static codec_type_t oldCodec; static codec_type_t oldCodec;
codec_type_t cancelCodec; codec_type_t cancelCodec;
if (recordIsReady && ! navdata_state.usbRecordInProgress && !navdata_state.internalRecordInProgress) // We want to enable recording if (recordIsReady && ! navdata_state.usbRecordInProgress && !navdata_state.internalRecordInProgress) // We want to enable recording
{ {
if ((ARDRONE_USB_MASK == (pnd->ardrone_state & ARDRONE_USB_MASK)) && if ((ARDRONE_USB_MASK == (pnd->ardrone_state & ARDRONE_USB_MASK)) &&
(0 < pnd->navdata_hdvideo_stream.usbkey_remaining_time) && (0 < pnd->navdata_hdvideo_stream.usbkey_remaining_time) &&
(TRUE == ardrone_control_config.video_on_usb)) (TRUE == ardrone_control_config.video_on_usb))
{ {
usbRecordEnable = TRUE; usbRecordEnable = TRUE;
} }
// Set the "non-record codec" to the codec defined as the application default // Set the "non-record codec" to the codec defined as the application default
oldCodec = ardrone_application_default_config.video_codec; oldCodec = ardrone_application_default_config.video_codec;
cancelCodec = oldCodec; cancelCodec = oldCodec;
ardrone_control_config.video_codec = (TRUE == usbRecordEnable) ? usbRecordCodec : deviceWifiRecordCodec; ardrone_control_config.video_codec = (TRUE == usbRecordEnable) ? usbRecordCodec : deviceWifiRecordCodec;
printf ("Set codec %d -> %d\n", oldCodec, ardrone_control_config.video_codec); PRINT ("Set codec %d -> %d\n", oldCodec, ardrone_control_config.video_codec);
nextInternalRecordState = TRUE; nextInternalRecordState = TRUE;
} }
else // We want to disable recording else // We want to disable recording
{ {
cancelCodec = ardrone_control_config.video_codec; cancelCodec = ardrone_control_config.video_codec;
ardrone_control_config.video_codec = oldCodec; ardrone_control_config.video_codec = oldCodec;
printf ("Reset codec %d -> %d\n", cancelCodec, oldCodec); PRINT ("Reset codec %d -> %d\n", cancelCodec, oldCodec);
} }
bool_t addEventSucceeded = ARDRONE_TOOL_CONFIGURATION_ADDEVENT (video_codec, &ardrone_control_config.video_codec, NULL); bool_t addEventSucceeded = ARDRONE_TOOL_CONFIGURATION_ADDEVENT (video_codec, &ardrone_control_config.video_codec, NULL);
if (FALSE == addEventSucceeded) if (FALSE == addEventSucceeded)
{ {
printf ("Unable to send codec switch ... retry later\n"); PRINT ("Unable to send codec switch ... retry later\n");
ardrone_control_config.video_codec = cancelCodec; ardrone_control_config.video_codec = cancelCodec;
continueRecord = FALSE; continueRecord = FALSE;
} }
@@ -584,93 +584,93 @@ C_RESULT ardrone_academy_navdata_process( const navdata_unpacked_t* const pnd )
if (TRUE == continueRecord) if (TRUE == continueRecord)
{ {
navdata_state.internalRecordInProgress = nextInternalRecordState; navdata_state.internalRecordInProgress = nextInternalRecordState;
switch (navdata_state.userbox_state) switch (navdata_state.userbox_state)
{ {
case USERBOX_STATE_STOPPED: case USERBOX_STATE_STOPPED:
navdata_state.record_state = RECORD_STATE_WAIT_USERBOX; navdata_state.record_state = RECORD_STATE_WAIT_USERBOX;
navdata_state.usbRecordInProgress = usbRecordEnable; navdata_state.usbRecordInProgress = usbRecordEnable;
ardrone_academy_navdata_userbox_switch(); ardrone_academy_navdata_userbox_switch();
break; break;
case USERBOX_STATE_STARTED: case USERBOX_STATE_STARTED:
if(navdata_state.isTakeOff) if(navdata_state.isTakeOff)
{ {
if(! recordIsReady) if(! recordIsReady)
{ {
printf("Userbox is started and record is started => Stop record\n"); PRINT("Userbox is started and record is started => Stop record\n");
ardrone_academy_navdata_recorder_enable(FALSE, navdata_state.userbox_time); ardrone_academy_navdata_recorder_enable(FALSE, navdata_state.userbox_time);
navdata_state.usbRecordInProgress = FALSE; navdata_state.usbRecordInProgress = FALSE;
} }
else else
{ {
printf("Userbox is started and record is stopped => Start record\n"); PRINT("Userbox is started and record is stopped => Start record\n");
if (FALSE == usbRecordEnable) if (FALSE == usbRecordEnable)
{ {
// Only activate the local recorder if we don't record on USB // Only activate the local recorder if we don't record on USB
ardrone_academy_navdata_recorder_enable(TRUE, navdata_state.userbox_time); ardrone_academy_navdata_recorder_enable(TRUE, navdata_state.userbox_time);
navdata_state.usbRecordInProgress = FALSE; navdata_state.usbRecordInProgress = FALSE;
} }
else else
{ {
navdata_state.usbRecordInProgress = TRUE; navdata_state.usbRecordInProgress = TRUE;
}
} }
}
navdata_state.record_state = RECORD_STATE_IDLE; navdata_state.record_state = RECORD_STATE_IDLE;
} }
else else
{ {
navdata_state.record_state = RECORD_STATE_WAIT_USERBOX; navdata_state.record_state = RECORD_STATE_WAIT_USERBOX;
ardrone_academy_navdata_userbox_switch(); ardrone_academy_navdata_userbox_switch();
} }
break; break;
case USERBOX_STATE_STARTING: case USERBOX_STATE_STARTING:
navdata_state.usbRecordInProgress = usbRecordEnable; navdata_state.usbRecordInProgress = usbRecordEnable;
navdata_state.record_state = RECORD_STATE_WAIT_USERBOX; navdata_state.record_state = RECORD_STATE_WAIT_USERBOX;
break; break;
case USERBOX_STATE_STOPPING: case USERBOX_STATE_STOPPING:
navdata_state.usbRecordInProgress = usbRecordEnable; navdata_state.usbRecordInProgress = usbRecordEnable;
// Should never be here // Should never be here
PRINT ("Don't know what to do for USERBOX_STATE_STOPPING\n"); PRINT ("Don't know what to do for USERBOX_STATE_STOPPING\n");
VP_OS_ASSERT (0 == 1); // Debug handler VP_OS_ASSERT (0 == 1); // Debug handler
break; break;
} }
} }
} }
// Screenshot management // Screenshot management
prevCameraIsReady = navdata_state.cameraIsReady; prevCameraIsReady = navdata_state.cameraIsReady;
navdata_state.cameraIsReady = (pnd->ardrone_state & ARDRONE_CAMERA_MASK) ? TRUE : FALSE; navdata_state.cameraIsReady = (pnd->ardrone_state & ARDRONE_CAMERA_MASK) ? TRUE : FALSE;
if (TRUE == navdata_state.cameraIsReady && FALSE == prevCameraIsReady) if (TRUE == navdata_state.cameraIsReady && FALSE == prevCameraIsReady)
{ {
academy_download_resume (); academy_download_resume ();
} }
if((navdata_state.screenshot_state == SCREENSHOT_STATE_NEEDED) && navdata_state.cameraIsReady) if((navdata_state.screenshot_state == SCREENSHOT_STATE_NEEDED) && navdata_state.cameraIsReady)
{ {
char param[ARDRONE_DATE_MAXSIZE + 64]; static char param[ARDRONE_DATE_MAXSIZE + 64];
char date[ARDRONE_DATE_MAXSIZE]; static char date[ARDRONE_DATE_MAXSIZE];
time_t t = time(NULL); time_t t = time(NULL);
ardrone_time2date(t, ARDRONE_FILE_DATE_FORMAT, date); ardrone_time2date(t, ARDRONE_FILE_DATE_FORMAT, date);
navdata_state.screenshot_state = SCREENSHOT_STATE_INPROGRESS; navdata_state.screenshot_state = SCREENSHOT_STATE_INPROGRESS;
sprintf(param, "%d,%d,%d,%s", USERBOX_CMD_SCREENSHOT, 0, 0, date); sprintf(param, "%d,%d,%d,%s", USERBOX_CMD_SCREENSHOT, 0, 0, date);
ARDRONE_TOOL_CONFIGURATION_ADDEVENT(userbox_cmd, (char*)param, ardrone_academy_navdata_screenshot_cb); ARDRONE_TOOL_CONFIGURATION_ADDEVENT(userbox_cmd, param, ardrone_academy_navdata_screenshot_cb);
} }
// USB management // USB management
navdata_state.usbIsReady = (pnd->ardrone_state & ARDRONE_USB_MASK) ? TRUE : FALSE; navdata_state.usbIsReady = (pnd->ardrone_state & ARDRONE_USB_MASK) ? TRUE : FALSE;
UNLOCK_ND_MUTEX (); UNLOCK_ND_MUTEX ();
} }
return C_OK; return C_OK;
} }
C_RESULT ardrone_academy_navdata_release( void ) C_RESULT ardrone_academy_navdata_release( void )
{ {
if(ardrone_academy_navdata_get_record_state()) if(ardrone_academy_navdata_get_record_state())
{ {
ardrone_academy_navdata_recorder_enable(FALSE, navdata_state.userbox_time); ardrone_academy_navdata_recorder_enable(FALSE, navdata_state.userbox_time);
} }
vp_os_mutex_destroy (&navdata_state.aan_mutex); vp_os_mutex_destroy (&navdata_state.aan_mutex);
return C_OK; return C_OK;
} }
void ardrone_academy_navdata_set_wifi_record_codec (codec_type_t newCodec) void ardrone_academy_navdata_set_wifi_record_codec (codec_type_t newCodec)
@@ -35,11 +35,11 @@ static inline int versionSupportsMulticonfiguration (const char *currentString)
#define _GENERAL_NAVDATA_DEBUG_PREFIX "General Navdata : " #define _GENERAL_NAVDATA_DEBUG_PREFIX "General Navdata : "
#if _GENERAL_NAVDATA_DEBUG || defined (DEBUG) #if _GENERAL_NAVDATA_DEBUG || defined (DEBUG)
#define PRINTDBG(...) \ #define PRINTDBG(...) \
do \ do \
{ \ { \
printf ("[%d] %s", __LINE__, _GENERAL_NAVDATA_DEBUG_PREFIX); \ printf ("[%d] %s", __LINE__, _GENERAL_NAVDATA_DEBUG_PREFIX); \
printf (__VA_ARGS__); \ printf (__VA_ARGS__); \
printf ("\n"); \ printf ("\n"); \
} while (0) } while (0)
#else #else
#define PRINTDBG(...) #define PRINTDBG(...)
@@ -50,7 +50,7 @@ static void sendInitConfigurations(void)
} }
static void switchToSession(void) static void switchToSession(void)
{ {
ARDRONE_TOOL_CONFIGURATION_ADDEVENT (session_id, ses_id, NULL); ARDRONE_TOOL_CONFIGURATION_ADDEVENT (session_id, ses_id, NULL);
} }
@@ -142,7 +142,7 @@ C_RESULT ardrone_general_navdata_process( const navdata_unpacked_t* const pnd )
navdata_mode_t current_navdata_state = NAVDATA_BOOTSTRAP; navdata_mode_t current_navdata_state = NAVDATA_BOOTSTRAP;
/* Makes sure the navdata stream will be resumed if the drone is disconnected and reconnected. /* Makes sure the navdata stream will be resumed if the drone is disconnected and reconnected.
* Allows changing the drone battery during debugging sessions. */ * Allows changing the drone battery during debugging sessions. */
if( ardrone_get_mask_from_state(pnd->ardrone_state, ARDRONE_NAVDATA_BOOTSTRAP) ) if( ardrone_get_mask_from_state(pnd->ardrone_state, ARDRONE_NAVDATA_BOOTSTRAP) )
{ {
current_navdata_state = NAVDATA_BOOTSTRAP; current_navdata_state = NAVDATA_BOOTSTRAP;
@@ -154,7 +154,16 @@ C_RESULT ardrone_general_navdata_process( const navdata_unpacked_t* const pnd )
if (current_navdata_state == NAVDATA_BOOTSTRAP && configState == MULTICONFIG_IDLE && navdataState == NAVDATA_REQUEST_IDLE) if (current_navdata_state == NAVDATA_BOOTSTRAP && configState == MULTICONFIG_IDLE && navdataState == NAVDATA_REQUEST_IDLE)
{ {
navdataState = NAVDATA_REQUEST_NEEDED; if ((0 != strncmp(ardrone_control_config.application_id, app_id, APPLI_NAME_SIZE)) ||
(0 != strncmp(ardrone_control_config.profile_id, usr_id, USER_NAME_SIZE)) ||
(0 != strncmp(ardrone_control_config.session_id, ses_id, SESSION_NAME_SIZE)))
{
configState = MULTICONFIG_NEEDED;
}
else
{
navdataState = NAVDATA_REQUEST_NEEDED;
}
} }
/* Multiconfig settings */ /* Multiconfig settings */
@@ -318,14 +327,14 @@ C_RESULT ardrone_general_navdata_process( const navdata_unpacked_t* const pnd )
navdataState = NAVDATA_REQUEST_IN_PROGRESS; navdataState = NAVDATA_REQUEST_IN_PROGRESS;
switchToSession(); // Resend session id when reconnecting. switchToSession(); // Resend session id when reconnecting.
sendInitConfigurations(); sendInitConfigurations();
ARDRONE_TOOL_CONFIGURATION_ADDEVENT(navdata_demo, &ardrone_application_default_config.navdata_demo, NULL); ARDRONE_TOOL_CONFIGURATION_ADDEVENT (navdata_demo, &ardrone_application_default_config.navdata_demo, NULL);
ARDRONE_TOOL_CONFIGURATION_ADDEVENT (navdata_options, &ardrone_application_default_config.navdata_options, navdataCallback); ARDRONE_TOOL_CONFIGURATION_ADDEVENT (navdata_options, &ardrone_application_default_config.navdata_options, navdataCallback);
break; break;
case NAVDATA_REQUEST_DONE: case NAVDATA_REQUEST_DONE:
// Refresh configuration file // Refresh configuration file
PRINTDBG ("Refreshing from NAVDATA FSM"); PRINTDBG ("Refreshing from NAVDATA FSM");
navdataState = NAVDATA_REQUEST_IDLE; navdataState = NAVDATA_REQUEST_IDLE;
ARDRONE_TOOL_CONFIGURATION_GET (NULL); ARDRONE_TOOL_CONFIGURATION_GET (NULL);
break; break;
case NAVDATA_REQUEST_IN_PROGRESS: case NAVDATA_REQUEST_IN_PROGRESS:
case NAVDATA_REQUEST_IDLE: case NAVDATA_REQUEST_IDLE:
@@ -421,6 +430,7 @@ ardrone_users_t *ardrone_get_user_list(void)
if (NULL == retVal->userList) if (NULL == retVal->userList)
{ {
vp_os_free (retVal); vp_os_free (retVal);
retVal = NULL;
return NULL; return NULL;
} }
strncpy (retVal->userList[validUserCount-1].ident, available_configurations[CAT_USER].list[configIndex].id, MULTICONFIG_ID_SIZE); strncpy (retVal->userList[validUserCount-1].ident, available_configurations[CAT_USER].list[configIndex].id, MULTICONFIG_ID_SIZE);
@@ -438,6 +448,7 @@ void ardrone_free_user_list (ardrone_users_t **users)
if (NULL != (*users)->userList) if (NULL != (*users)->userList)
{ {
vp_os_free ((*users)->userList); vp_os_free ((*users)->userList);
(*users)->userList = NULL;
} }
vp_os_free (*users); vp_os_free (*users);
*users = NULL; *users = NULL;
@@ -18,35 +18,35 @@
// Handler to resume control thread is mandatory // Handler to resume control thread is mandatory
#define BEGIN_NAVDATA_HANDLER_TABLE \ #define BEGIN_NAVDATA_HANDLER_TABLE \
ardrone_navdata_handler_t ardrone_navdata_handler_table[] = { \ ardrone_navdata_handler_t ardrone_navdata_handler_table[] = { \
{ ardrone_navdata_control_init, ardrone_navdata_control_process, ardrone_navdata_control_release, NULL }, \ { ardrone_navdata_control_init, ardrone_navdata_control_process, ardrone_navdata_control_release, NULL }, \
{ ardrone_general_navdata_init, ardrone_general_navdata_process, ardrone_general_navdata_release, NULL }, \ { ardrone_general_navdata_init, ardrone_general_navdata_process, ardrone_general_navdata_release, NULL }, \
{ video_navdata_handler_init, video_navdata_handler_process, video_navdata_handler_release, NULL }, \ { video_navdata_handler_init, video_navdata_handler_process, video_navdata_handler_release, NULL }, \
{ ardrone_academy_navdata_init, ardrone_academy_navdata_process, ardrone_academy_navdata_release, NULL }, { ardrone_academy_navdata_init, ardrone_academy_navdata_process, ardrone_academy_navdata_release, NULL },
#define END_NAVDATA_HANDLER_TABLE \ #define END_NAVDATA_HANDLER_TABLE \
{ NULL, NULL, NULL, NULL } \ { NULL, NULL, NULL, NULL } \
}; };
#define NAVDATA_HANDLER_TABLE_ENTRY( init, process, release, init_data_ptr ) \ #define NAVDATA_HANDLER_TABLE_ENTRY( init, process, release, init_data_ptr ) \
{ (ardrone_navdata_handler_init_t)init, process, release, init_data_ptr }, { (ardrone_navdata_handler_init_t)init, process, release, init_data_ptr },
typedef C_RESULT (*ardrone_navdata_handler_init_t)( void* data ); typedef C_RESULT (*ardrone_navdata_handler_init_t)( void* data );
typedef C_RESULT (*ardrone_navdata_handler_process_t)( const navdata_unpacked_t* const navdata ); typedef C_RESULT (*ardrone_navdata_handler_process_t)( const navdata_unpacked_t* const navdata );
typedef C_RESULT (*ardrone_navdata_handler_release_t)( void ); typedef C_RESULT (*ardrone_navdata_handler_release_t)( void );
typedef struct _ardrone_navdata_handler_t { typedef struct _ardrone_navdata_handler_t {
ardrone_navdata_handler_init_t init; ardrone_navdata_handler_init_t init;
ardrone_navdata_handler_process_t process; ardrone_navdata_handler_process_t process;
ardrone_navdata_handler_release_t release; ardrone_navdata_handler_release_t release;
void* data; // Data used during initialization void* data; // Data used during initialization
} ardrone_navdata_handler_t; } ardrone_navdata_handler_t;
typedef enum typedef enum
{ {
NAVDATA_BOOTSTRAP = 0, NAVDATA_BOOTSTRAP = 0,
NAVDATA_DEMO, NAVDATA_DEMO,
NAVDATA_FULL NAVDATA_FULL
} navdata_mode_t; } navdata_mode_t;
extern ardrone_navdata_handler_t ardrone_navdata_handler_table[] WEAK; extern ardrone_navdata_handler_t ardrone_navdata_handler_table[] WEAK;
@@ -49,6 +49,11 @@ navdata_option_t* ardrone_navdata_search_option( navdata_option_t* navdata_optio
{ {
ptr = (uint8_t*) navdata_options_ptr; ptr = (uint8_t*) navdata_options_ptr;
ptr += navdata_options_ptr->size; ptr += navdata_options_ptr->size;
if (0 == navdata_options_ptr->size)
{
navdata_options_ptr = NULL;
break;
}
navdata_options_ptr = (navdata_option_t*) ptr; navdata_options_ptr = (navdata_option_t*) ptr;
} }
@@ -28,9 +28,9 @@ typedef int socklen_t;
#define PDBG(...) \ #define PDBG(...) \
do \ do \
{ \ { \
printf ("V_COM_STAGE: %s:%d : ", __FUNCTION__, __LINE__); \ PRINT ("V_COM_STAGE: %s:%d : ", __FUNCTION__, __LINE__); \
printf (__VA_ARGS__); \ PRINT (__VA_ARGS__); \
printf ("\n"); \ PRINT ("\n"); \
} while (0) } while (0)
#else #else
#define PDBG(...) #define PDBG(...)
@@ -116,20 +116,20 @@ C_RESULT video_com_stage_connect (video_com_config_t *cfg)
if( cfg->protocol == VP_COM_PROBE) if( cfg->protocol == VP_COM_PROBE)
{ {
printf("\n\nPROBING\n"); PRINT("\n\nPROBING\n");
cfg->socket.protocol = VP_COM_TCP; cfg->socket.protocol = VP_COM_TCP;
res = vp_com_open(cfg->com, &cfg->socket, &cfg->read, &cfg->write); res = vp_com_open(cfg->com, &cfg->socket, &cfg->read, &cfg->write);
if( VP_SUCCEEDED(res) ) if( VP_SUCCEEDED(res) )
{ {
printf("\n\nTCP\n"); PRINT("\n\nTCP\n");
vp_com_close (cfg->com, &cfg->socket); vp_com_close (cfg->com, &cfg->socket);
cfg->protocol = VP_COM_TCP; cfg->protocol = VP_COM_TCP;
} }
else else
{ {
printf("\n\nUDP\n"); PRINT("\n\nUDP\n");
cfg->protocol = VP_COM_UDP; cfg->protocol = VP_COM_UDP;
} }
} }
@@ -230,11 +230,11 @@ C_RESULT video_com_multisocket_stage_open(video_com_multisocket_config_t *cfg)
cfg->configs[i]->mustReconnect = 0; cfg->configs[i]->mustReconnect = 0;
} }
printf("Video multisocket : init %i sockets\n",cfg->nb_sockets); PRINT("Video multisocket : init %i sockets\n",cfg->nb_sockets);
for(i=0;i<cfg->nb_sockets;i++) for(i=0;i<cfg->nb_sockets;i++)
{ {
printf("Video multisocket : connecting socket %d on port %d %s\n", PRINT("Video multisocket : connecting socket %d on port %d %s\n",
i, i,
cfg->configs[i]->socket.port, cfg->configs[i]->socket.port,
(cfg->configs[i]->protocol==VP_COM_TCP)?"TCP":"UDP"); (cfg->configs[i]->protocol==VP_COM_TCP)?"TCP":"UDP");
@@ -242,7 +242,7 @@ C_RESULT video_com_multisocket_stage_open(video_com_multisocket_config_t *cfg)
cfg->configs[i]->connected = FALSE; cfg->configs[i]->connected = FALSE;
res = video_com_stage_connect(cfg->configs[i]); res = video_com_stage_connect(cfg->configs[i]);
if (!VP_SUCCEEDED(res)) { if (!VP_SUCCEEDED(res)) {
printf(" - Connection failed\n"); PRINT(" - Connection failed\n");
nb_failed_connections++; nb_failed_connections++;
} }
@@ -266,9 +266,9 @@ C_RESULT video_com_stage_transform(video_com_config_t *cfg, vp_api_io_data_t *in
if (1 == cfg->mustReconnect) if (1 == cfg->mustReconnect)
{ {
PDBG ("Will call connect"); PDBG ("Will call connect");
printf ("Reconnecting ... "); PRINT ("Reconnecting ... ");
res = video_com_stage_connect (cfg); res = video_com_stage_connect (cfg);
printf ("%s\n", (VP_FAILED (res) ? "FAIL" : "OK")); PRINT ("%s\n", (VP_FAILED (res) ? "FAIL" : "OK"));
cfg->mustReconnect = 0; cfg->mustReconnect = 0;
} }
@@ -313,10 +313,10 @@ C_RESULT video_com_stage_transform(video_com_config_t *cfg, vp_api_io_data_t *in
PDBG ("%s [%d] : status set to error !\n", __FUNCTION__, __LINE__); PDBG ("%s [%d] : status set to error !\n", __FUNCTION__, __LINE__);
perror ("Video_com_stage"); perror ("Video_com_stage");
cfg->mustReconnect = 1; cfg->mustReconnect = 1;
out->size = 0; out->size = 0;
vp_os_mutex_unlock (&out->lock); vp_os_mutex_unlock (&out->lock);
return C_OK; return C_OK;
} }
if( out->size == 0) if( out->size == 0)
{ {
@@ -377,7 +377,7 @@ C_RESULT video_com_stage_transform(video_com_config_t *cfg, vp_api_io_data_t *in
C_RESULT video_com_multisocket_stage_transform(video_com_multisocket_config_t *cfg, vp_api_io_data_t *in, vp_api_io_data_t *out) C_RESULT video_com_multisocket_stage_transform(video_com_multisocket_config_t *cfg, vp_api_io_data_t *in, vp_api_io_data_t *out)
{ {
C_RESULT res,res2; C_RESULT res;
fd_set rfds; fd_set rfds;
int retval; int retval;
int fs,maxfs; int fs,maxfs;
@@ -394,10 +394,10 @@ C_RESULT video_com_multisocket_stage_transform(video_com_multisocket_config_t *c
if (1 == cfg->configs[i]->mustReconnect) if (1 == cfg->configs[i]->mustReconnect)
{ {
PDBG ("Will call connect"); PDBG ("Will call connect");
printf ("Reconnecting ... "); PRINT ("Reconnecting ... ");
res = C_FAIL; res = C_FAIL;
res = video_com_stage_connect (cfg->configs[i]); res = video_com_stage_connect (cfg->configs[i]);
printf ("%s\n", (VP_FAILED (res) ? "FAIL" : "OK")); PRINT ("%s\n", (VP_FAILED (res) ? "FAIL" : "OK"));
cfg->configs[i]->mustReconnect = 0; cfg->configs[i]->mustReconnect = 0;
} }
} }
@@ -480,20 +480,20 @@ C_RESULT video_com_multisocket_stage_transform(video_com_multisocket_config_t *c
if(i == cfg->nb_sockets) if(i == cfg->nb_sockets)
{ {
printf("%s:%d BUG !!!!!", __FUNCTION__, __LINE__); PRINT("%s:%d BUG !!!!!", __FUNCTION__, __LINE__);
selectTimeout = TRUE; selectTimeout = TRUE;
} }
} }
} }
else else
{ {
DEBUG_PRINT_SDK("%s\n",(retval==0) ? "timeout" : "error"); DEBUG_PRINT_SDK("%s\n",(retval==0)?"timeout":"error");
selectTimeout = TRUE; selectTimeout = TRUE;
} }
if (FALSE == selectTimeout) if (FALSE == selectTimeout)
{ {
DEBUG_PRINT_SDK ("Will read on socket %d\n", i); // DEBUG_PRINT_SDK ("Will read on socket %d\n", i);
// Actual first time read // Actual first time read
res = cfg->configs[i]->read(&cfg->configs[i]->socket, out->buffers[0], &out->size); res = cfg->configs[i]->read(&cfg->configs[i]->socket, out->buffers[0], &out->size);
if (VP_FAILED (res)) if (VP_FAILED (res))
@@ -504,7 +504,7 @@ C_RESULT video_com_multisocket_stage_transform(video_com_multisocket_config_t *c
out->size = 0; out->size = 0;
vp_os_mutex_unlock (&out->lock); vp_os_mutex_unlock (&out->lock);
return C_OK; return C_OK;
} }
// Loop read to empty the socket buffers if needed // Loop read to empty the socket buffers if needed
cfg->configs[i]->socket.block = VP_COM_DONTWAIT; cfg->configs[i]->socket.block = VP_COM_DONTWAIT;
@@ -512,14 +512,14 @@ C_RESULT video_com_multisocket_stage_transform(video_com_multisocket_config_t *c
int32_t readSize = cfg->configs[i]->buffer_size - out->size; int32_t readSize = cfg->configs[i]->buffer_size - out->size;
while (TRUE == bContinue) while (TRUE == bContinue)
{ {
DEBUG_PRINT_SDK ("Will read %d octets from socket %d\n", readSize, i); // DEBUG_PRINT_SDK ("Will read %d octets from socket %d\n", readSize, i);
res = cfg->configs[i]->read(&cfg->configs[i]->socket, &(out->buffers[0][out->size]), &readSize); res = cfg->configs[i]->read(&cfg->configs[i]->socket, &(out->buffers[0][out->size]), &readSize);
if (VP_FAILED (res)) if (VP_FAILED (res))
{ {
PDBG ("%s [%d] : status set to error !\n", __FUNCTION__, __LINE__); PDBG ("%s [%d] : status set to error !\n", __FUNCTION__, __LINE__);
perror ("Video_com_stage"); perror ("Video_com_stage");
cfg->configs[i]->mustReconnect = 1; cfg->configs[i]->mustReconnect = 1;
out->size = 0; out->size = 0;
vp_os_mutex_unlock (&out->lock); vp_os_mutex_unlock (&out->lock);
return C_OK; return C_OK;
} }
@@ -551,7 +551,7 @@ C_RESULT video_com_multisocket_stage_transform(video_com_multisocket_config_t *c
DEBUG_PRINT_SDK("Video multisocket : sending connection byte on port %s %d\n", DEBUG_PRINT_SDK("Video multisocket : sending connection byte on port %s %d\n",
(cfg->configs[i]->socket.protocol==VP_COM_TCP)?"TCP":"UDP",cfg->configs[i]->socket.port); (cfg->configs[i]->socket.protocol==VP_COM_TCP)?"TCP":"UDP",cfg->configs[i]->socket.port);
res2 = cfg->configs[i]->write(&cfg->configs[i]->socket, (uint8_t*) &flag, &len); cfg->configs[i]->write(&cfg->configs[i]->socket, (uint8_t*) &flag, &len);
} }
} }
} }
@@ -566,7 +566,7 @@ C_RESULT video_com_multisocket_stage_transform(video_com_multisocket_config_t *c
if((selectTimeout == TRUE) && cfg->forceNonBlocking && *(cfg->forceNonBlocking)==TRUE) if((selectTimeout == TRUE) && cfg->forceNonBlocking && *(cfg->forceNonBlocking)==TRUE)
{ {
//printf("Debug %s:%d\n",__FUNCTION__,__LINE__); //PRINT("Debug %s:%d\n",__FUNCTION__,__LINE__);
/* No data are available here, but some are available in the next stage */ /* No data are available here, but some are available in the next stage */
/* out->size=0 would restart the pipeline */ /* out->size=0 would restart the pipeline */
@@ -61,7 +61,7 @@ DEFINE_THREAD_ROUTINE(video_recorder, data)
vp_api_io_stage_t stages[3]; vp_api_io_stage_t stages[3];
PIPELINE_HANDLE video_recorder_pipeline_handle; PIPELINE_HANDLE video_recorder_pipeline_handle;
video_recorder_thread_param_t *video_recorder_thread_param = (video_recorder_thread_param_t *)data; video_recorder_thread_param_t *video_recorder_thread_param = (video_recorder_thread_param_t *)data;
video_stage_tcp_config_t tcpConf; video_stage_tcp_config_t tcpConf;
if(video_recorder_thread_param != NULL) if(video_recorder_thread_param != NULL)
@@ -197,14 +197,21 @@ DEFINE_THREAD_ROUTINE(video_stage, data) {
} }
vp_os_free(params->pre_processing_stages_list->stages_list); vp_os_free(params->pre_processing_stages_list->stages_list);
params->pre_processing_stages_list->stages_list = NULL;
vp_os_free(params->post_processing_stages_list->stages_list); vp_os_free(params->post_processing_stages_list->stages_list);
params->post_processing_stages_list->stages_list = NULL;
vp_os_free(params->pre_processing_stages_list); vp_os_free(params->pre_processing_stages_list);
params->pre_processing_stages_list = NULL;
vp_os_free(params->post_processing_stages_list); vp_os_free(params->post_processing_stages_list);
params->post_processing_stages_list = NULL;
vp_os_free(params->in_pic); vp_os_free(params->in_pic);
params->in_pic = NULL;
vp_os_free(params->out_pic); vp_os_free(params->out_pic);
params->out_pic = NULL;
vp_os_free(params); vp_os_free(params);
params = NULL;
vp_api_close(&pipeline, &video_pipeline_handle); vp_api_close(&pipeline, &video_pipeline_handle);
} }
@@ -11,6 +11,7 @@
#include <ardrone_tool/Video/video_stage_decoder.h> #include <ardrone_tool/Video/video_stage_decoder.h>
#include <video_encapsulation.h> #include <video_encapsulation.h>
#include <VP_Os/vp_os_malloc.h> #include <VP_Os/vp_os_malloc.h>
#include <VP_Os/vp_os_print.h>
#include <stdio.h> #include <stdio.h>
#ifndef USE_ANDROID #ifndef USE_ANDROID
@@ -18,19 +19,22 @@
# define mp4h264_open ittiam_stage_decoding_open # define mp4h264_open ittiam_stage_decoding_open
# define mp4h264_transform ittiam_stage_decoding_transform # define mp4h264_transform ittiam_stage_decoding_transform
# define mp4h264_close ittiam_stage_decoding_close # define mp4h264_close ittiam_stage_decoding_close
static const int resetDecoderOnStreamChange = 1;
# else // FFMPEG # else // FFMPEG
# define mp4h264_open ffmpeg_stage_decoding_open # define mp4h264_open ffmpeg_stage_decoding_open
# define mp4h264_transform ffmpeg_stage_decoding_transform # define mp4h264_transform ffmpeg_stage_decoding_transform
# define mp4h264_close ffmpeg_stage_decoding_close # define mp4h264_close ffmpeg_stage_decoding_close
static const int resetDecoderOnStreamChange = 0;
# endif # endif
#else #else // ANDROID
typedef enum { typedef enum {
NEON_SUPPORT_UNKNOWN = 0, NEON_SUPPORT_UNKNOWN = 0,
NEON_SUPPORT_OK, NEON_SUPPORT_OK,
NEON_SUPPORT_FAIL, NEON_SUPPORT_FAIL,
} neon_status_t; } neon_status_t;
static neon_status_t neonStatus = NEON_SUPPORT_UNKNOWN; static neon_status_t neonStatus = NEON_SUPPORT_FAIL; // <<< FORCE FFMPEG <<<
static int resetDecoderOnStreamChange = 0; // NON CONST as it will be set at runtime
C_RESULT mp4h264_open (mp4h264_config_t *cfg); C_RESULT mp4h264_open (mp4h264_config_t *cfg);
C_RESULT mp4h264_transform (mp4h264_config_t *cfg, vp_api_io_data_t *in, vp_api_io_data_t *out); C_RESULT mp4h264_transform (mp4h264_config_t *cfg, vp_api_io_data_t *in, vp_api_io_data_t *out);
@@ -48,19 +52,19 @@ float DEBUG_decodingTimeUsec = 0.0;
#define ENABLE_VIDEO_STAGE_DECODER_DEBUG (0) #define ENABLE_VIDEO_STAGE_DECODER_DEBUG (0)
const vp_api_stage_funcs_t video_decoding_funcs = { const vp_api_stage_funcs_t video_decoding_funcs = {
(vp_api_stage_handle_msg_t) NULL, (vp_api_stage_handle_msg_t) NULL,
(vp_api_stage_open_t) video_stage_decoder_open, (vp_api_stage_open_t) video_stage_decoder_open,
(vp_api_stage_transform_t) video_stage_decoder_transform, (vp_api_stage_transform_t) video_stage_decoder_transform,
(vp_api_stage_close_t) video_stage_decoder_close (vp_api_stage_close_t) video_stage_decoder_close
}; };
#if ENABLE_VIDEO_STAGE_DECODER_DEBUG || defined (DEBUG) #if ENABLE_VIDEO_STAGE_DECODER_DEBUG || defined (DEBUG)
#define PDBG(...) \ #define PDBG(...) \
do \ do \
{ \ { \
printf ("VIDEO_STAGE_DECODER (%s@%d) : ", __FUNCTION__, __LINE__); \ printf ("VIDEO_STAGE_DECODER (%s@%d) : ", __FUNCTION__, __LINE__); \
printf (__VA_ARGS__); \ printf (__VA_ARGS__); \
printf ("\n"); \ printf ("\n"); \
} while (0) } while (0)
#else #else
#define PDBG(...) #define PDBG(...)
@@ -68,13 +72,13 @@ const vp_api_stage_funcs_t video_decoding_funcs = {
#define ALLOC_CHECK(POINTER, SIZE) \ #define ALLOC_CHECK(POINTER, SIZE) \
do \ do \
{ \ { \
POINTER = vp_os_calloc (SIZE, 1); \ POINTER = vp_os_calloc (SIZE, 1); \
if (NULL == POINTER) \ if (NULL == POINTER) \
{ \ { \
printf ("Unable to alloc %s\n", #POINTER); \ printf ("Unable to alloc %s\n", #POINTER); \
return C_FAIL; \ return C_FAIL; \
} \ } \
} while (0) } while (0)
@@ -88,286 +92,295 @@ parrot_video_encapsulation_codecs_t video_stage_decoder_lastDetectedCodec = 0;
C_RESULT video_stage_decoder_open (video_decoder_config_t *cfg) C_RESULT video_stage_decoder_open (video_decoder_config_t *cfg)
{ {
// Allocate internal datas // Allocate internal datas
ALLOC_CHECK (cfg->vlibConf, sizeof (vlib_stage_decoding_config_t)); ALLOC_CHECK (cfg->vlibConf, sizeof (vlib_stage_decoding_config_t));
ALLOC_CHECK (cfg->vlibOut, sizeof (vp_api_io_data_t)); ALLOC_CHECK (cfg->vlibOut, sizeof (vp_api_io_data_t));
ALLOC_CHECK (cfg->mp4h264Conf, sizeof (mp4h264_config_t)); ALLOC_CHECK (cfg->mp4h264Conf, sizeof (mp4h264_config_t));
ALLOC_CHECK (cfg->mp4h264Out, sizeof (vp_api_io_data_t)); ALLOC_CHECK (cfg->mp4h264Out, sizeof (vp_api_io_data_t));
// Fill alloc'd structs with data from cfg // Fill alloc'd structs with data from cfg
// --> MPEG4 / H264 // --> MPEG4 / H264
cfg->mp4h264Conf->dst_picture.format = cfg->dst_picture->format; cfg->mp4h264Conf->dst_picture.format = cfg->dst_picture->format;
// --> VLIB // --> VLIB
cfg->vlibConf->width = cfg->dst_picture->width; cfg->vlibConf->width = cfg->dst_picture->width;
cfg->vlibConf->height = cfg->dst_picture->height; cfg->vlibConf->height = cfg->dst_picture->height;
cfg->vlibConf->picture = cfg->dst_picture; cfg->vlibConf->picture = cfg->dst_picture;
cfg->vlibConf->luma_only = FALSE; cfg->vlibConf->luma_only = FALSE;
cfg->vlibConf->block_mode_enable = TRUE; cfg->vlibConf->block_mode_enable = TRUE;
switch (cfg->dst_picture->format) switch (cfg->dst_picture->format)
{ {
case PIX_FMT_RGB565: case PIX_FMT_RGB565:
cfg->bpp=2; cfg->bpp=2;
break; break;
case PIX_FMT_RGB24: case PIX_FMT_RGB24:
cfg->bpp=3; cfg->bpp=3;
break; break;
default: default:
cfg->bpp=0; cfg->bpp=0;
break; break;
} }
vlib_stage_decoding_open (cfg->vlibConf);
mp4h264_open (cfg->mp4h264Conf);
return C_OK;
vlib_stage_decoding_open (cfg->vlibConf);
mp4h264_open (cfg->mp4h264Conf);
return C_OK;
} }
static inline bool_t havePaVE (uint8_t *buffer) static inline bool_t havePaVE (uint8_t *buffer)
{ {
if (buffer [0] == 'P' && if (buffer [0] == 'P' &&
buffer [1] == 'a' && buffer [1] == 'a' &&
buffer [2] == 'V' && buffer [2] == 'V' &&
buffer [3] == 'E') buffer [3] == 'E')
{ {
return TRUE; return TRUE;
} }
else else
{ {
return FALSE; return FALSE;
} }
} }
C_RESULT video_stage_decoder_transform (video_decoder_config_t *cfg, vp_api_io_data_t *in, vp_api_io_data_t *out) C_RESULT video_stage_decoder_transform (video_decoder_config_t *cfg, vp_api_io_data_t *in, vp_api_io_data_t *out)
{ {
C_RESULT retVal = C_OK; C_RESULT retVal = C_OK;
bool_t useVlib = FALSE; bool_t useVlib = FALSE;
bool_t useMP4H264 = FALSE; bool_t useMP4H264 = FALSE;
vp_api_io_data_t *outToCopy = NULL; vp_api_io_data_t *outToCopy = NULL;
uint8_t *buffer = in->buffers[in->indexBuffer]; uint8_t *buffer = in->buffers[in->indexBuffer];
static int lastDecodedStreamID = -1; static int lastDecodedStreamID = -1;
#if defined(TARGET_OS_IPHONE) || defined (TARGET_OS_IPHONE_SIMULATOR) #if defined(TARGET_OS_IPHONE) || defined (TARGET_OS_IPHONE_SIMULATOR)
uint64_t startTime = 0; uint64_t startTime = 0;
uint64_t stopTime = 0; uint64_t stopTime = 0;
uint64_t elapsedNano = 0; uint64_t elapsedNano = 0;
static mach_timebase_info_data_t sTimebaseInfo; static mach_timebase_info_data_t sTimebaseInfo;
if (0 == sTimebaseInfo.denom) if (0 == sTimebaseInfo.denom)
{ {
mach_timebase_info (&sTimebaseInfo); mach_timebase_info (&sTimebaseInfo);
} }
startTime = mach_absolute_time (); startTime = mach_absolute_time ();
#endif #endif
// Check for PaVE // Check for PaVE
if (havePaVE (buffer)) if (havePaVE (buffer))
{ {
parrot_video_encapsulation_t *PaVE = (parrot_video_encapsulation_t *)buffer; parrot_video_encapsulation_t *PaVE = (parrot_video_encapsulation_t *)buffer;
video_stage_decoder_lastDetectedCodec = PaVE->video_codec;
if (lastDecodedStreamID!=-1 && lastDecodedStreamID!=PaVE->stream_id) video_stage_decoder_lastDetectedCodec = PaVE->video_codec;
if (lastDecodedStreamID!=-1 && lastDecodedStreamID!=PaVE->stream_id && 1 == resetDecoderOnStreamChange)
{ {
printf("Resetting the video decoder.\n"); PRINT("Resetting the video decoder.\n");
video_stage_decoder_close(cfg); video_stage_decoder_close(cfg);
video_stage_decoder_open(cfg); video_stage_decoder_open(cfg);
} }
lastDecodedStreamID=PaVE->stream_id; lastDecodedStreamID=PaVE->stream_id;
if (CODEC_VLIB == PaVE->video_codec || if (CODEC_VLIB == PaVE->video_codec ||
CODEC_P264 == PaVE->video_codec) CODEC_P264 == PaVE->video_codec)
{ {
useVlib = TRUE; useVlib = TRUE;
} }
else if (CODEC_MPEG4_VISUAL == PaVE->video_codec || else if (CODEC_MPEG4_VISUAL == PaVE->video_codec ||
CODEC_MPEG4_AVC == PaVE->video_codec) CODEC_MPEG4_AVC == PaVE->video_codec)
{ {
useMP4H264 = TRUE; useMP4H264 = TRUE;
} }
else else
{ {
// Unknown codec // Unknown codec
return C_FAIL; return C_FAIL;
} }
} }
else if ( ((*(uint32_t*)buffer) & 0xFFFE7C00 )== 0 ) /* true if a UVLC or P264 header is present */ else if ( ((*(uint32_t*)buffer) & 0xFFFE7C00 )== 0 ) /* true if a UVLC or P264 header is present */
{ {
/* Test bits 15 and 16 of the header to differenciate UVLC and P264 */ /* Test bits 15 and 16 of the header to differenciate UVLC and P264 */
video_stage_decoder_lastDetectedCodec = ( ((*(uint32_t*)buffer) & 0x8000 )== 0x8000 ) ? CODEC_VLIB : CODEC_P264; video_stage_decoder_lastDetectedCodec = ( ((*(uint32_t*)buffer) & 0x8000 )== 0x8000 ) ? CODEC_VLIB : CODEC_P264;
// No PaVE -> give to VLIB // No PaVE -> give to VLIB
useVlib = TRUE; useVlib = TRUE;
} }
else else
{ {
// Unknown codec // Unknown codec
printf(" -- Critical error : unrecognized codec (first bytes : %x %x %x %x %x) --\n", printf(" -- Critical error : unrecognized codec (first bytes : %x %x %x %x %x) --\n",
buffer[0],buffer[1],buffer[2],buffer[3],buffer[4]); buffer[0],buffer[1],buffer[2],buffer[3],buffer[4]);
return C_FAIL; return C_FAIL;
} }
if (useVlib) if (useVlib)
{ {
cfg->vlibConf->num_picture_decoded = cfg->num_picture_decoded; cfg->vlibConf->num_picture_decoded = cfg->num_picture_decoded;
retVal = vlib_stage_decoding_transform (cfg->vlibConf, in, cfg->vlibOut); retVal = vlib_stage_decoding_transform (cfg->vlibConf, in, cfg->vlibOut);
if (C_FAIL == retVal) if (C_FAIL == retVal)
{ {
return retVal; return retVal;
} }
cfg->num_picture_decoded = cfg->vlibConf->num_picture_decoded; cfg->num_picture_decoded = cfg->vlibConf->num_picture_decoded;
cfg->num_frames = cfg->vlibConf->controller.num_frames; cfg->num_frames = cfg->vlibConf->controller.num_frames;
cfg->src_picture->height = cfg->vlibConf->controller.height; cfg->src_picture->height = cfg->vlibConf->controller.height;
cfg->src_picture->width = cfg->vlibConf->controller.width; cfg->src_picture->width = cfg->vlibConf->controller.width;
cfg->rowstride = cfg->dst_picture->width * cfg->bpp; // Size of the buffer we got for VLIB cfg->rowstride = cfg->dst_picture->width * cfg->bpp; // Size of the buffer we got for VLIB
cfg->vlibOut->size = cfg->rowstride * cfg->dst_picture->height; cfg->vlibOut->size = cfg->rowstride * cfg->dst_picture->height;
outToCopy = cfg->vlibOut; outToCopy = cfg->vlibOut;
} }
if (useMP4H264) if (useMP4H264)
{ {
parrot_video_encapsulation_t *PaVE = (parrot_video_encapsulation_t *)buffer; parrot_video_encapsulation_t *PaVE = (parrot_video_encapsulation_t *)buffer;
cfg->mp4h264Conf->num_picture_decoded = cfg->num_picture_decoded; cfg->mp4h264Conf->num_picture_decoded = cfg->num_picture_decoded;
retVal = mp4h264_transform (cfg->mp4h264Conf, in, cfg->mp4h264Out); retVal = mp4h264_transform (cfg->mp4h264Conf, in, cfg->mp4h264Out);
if (C_FAIL == retVal) if (C_FAIL == retVal)
{ {
return retVal; return retVal;
} }
cfg->num_picture_decoded = cfg->mp4h264Conf->num_picture_decoded; cfg->num_picture_decoded = cfg->mp4h264Conf->num_picture_decoded;
cfg->num_frames = PaVE->frame_number; cfg->num_frames = PaVE->frame_number;
cfg->dst_picture->height = cfg->mp4h264Conf->dst_picture.height; cfg->dst_picture->height = cfg->mp4h264Conf->dst_picture.height;
cfg->dst_picture->width = cfg->mp4h264Conf->dst_picture.width; cfg->dst_picture->width = cfg->mp4h264Conf->dst_picture.width;
cfg->src_picture->height = cfg->mp4h264Conf->src_picture.height; cfg->src_picture->height = cfg->mp4h264Conf->src_picture.height;
cfg->src_picture->width = cfg->mp4h264Conf->src_picture.width; cfg->src_picture->width = cfg->mp4h264Conf->src_picture.width;
cfg->rowstride = cfg->dst_picture->width * cfg->bpp; // Size of the actual picture, alloc'd by MPEG4 / H264 stage cfg->rowstride = cfg->dst_picture->width * cfg->bpp; // Size of the actual picture, alloc'd by MPEG4 / H264 stage
outToCopy = cfg->mp4h264Out; outToCopy = cfg->mp4h264Out;
} }
if (NULL == outToCopy) if (NULL == outToCopy)
{ {
retVal = C_FAIL; retVal = C_FAIL;
} }
else else
{ {
out->numBuffers = outToCopy->numBuffers; out->numBuffers = outToCopy->numBuffers;
out->buffers = outToCopy->buffers; out->buffers = outToCopy->buffers;
out->indexBuffer = outToCopy->indexBuffer; out->indexBuffer = outToCopy->indexBuffer;
out->size = outToCopy->size; out->size = outToCopy->size;
out->lineSize = outToCopy->lineSize; out->lineSize = outToCopy->lineSize;
out->status = outToCopy->status; out->status = outToCopy->status;
retVal = C_OK; retVal = C_OK;
} }
#if defined(TARGET_OS_IPHONE) || defined (TARGET_OS_IPHONE_SIMULATOR) #if defined(TARGET_OS_IPHONE) || defined (TARGET_OS_IPHONE_SIMULATOR)
stopTime = mach_absolute_time (); stopTime = mach_absolute_time ();
elapsedNano = (stopTime - startTime) * sTimebaseInfo.numer / sTimebaseInfo.denom; elapsedNano = (stopTime - startTime) * sTimebaseInfo.numer / sTimebaseInfo.denom;
if (0.0 == DEBUG_decodingTimeUsec) if (0.0 == DEBUG_decodingTimeUsec)
{ {
DEBUG_decodingTimeUsec = elapsedNano / 1000.0; DEBUG_decodingTimeUsec = elapsedNano / 1000.0;
} }
else else
{ {
DEBUG_decodingTimeUsec = 0.9 * DEBUG_decodingTimeUsec + (0.1 * elapsedNano / 1000.0); DEBUG_decodingTimeUsec = 0.9 * DEBUG_decodingTimeUsec + (0.1 * elapsedNano / 1000.0);
} }
#endif #endif
#ifdef USE_LINUX #ifdef USE_LINUX
usleep(video_stage_decoder_fakeLatency * 1000); usleep(video_stage_decoder_fakeLatency * 1000);
#endif #endif
return retVal; return retVal;
} }
C_RESULT video_stage_decoder_close (video_decoder_config_t *cfg) C_RESULT video_stage_decoder_close (video_decoder_config_t *cfg)
{ {
C_RESULT res, resVlib, resMp4h264; C_RESULT res, resVlib, resMp4h264;
resVlib = vlib_stage_decoding_close (cfg->vlibConf); resVlib = vlib_stage_decoding_close (cfg->vlibConf);
resMp4h264 = mp4h264_close (cfg->mp4h264Conf); resMp4h264 = mp4h264_close (cfg->mp4h264Conf);
res = (C_OK == resVlib && C_OK == resMp4h264 ) ? C_OK : C_FAIL; res = (C_OK == resVlib && C_OK == resMp4h264 ) ? C_OK : C_FAIL;
vp_os_free (cfg->vlibConf); vp_os_free (cfg->vlibConf);
cfg->vlibConf = NULL; cfg->vlibConf = NULL;
vp_os_free (cfg->vlibOut); vp_os_free (cfg->vlibOut);
cfg->vlibOut = NULL; cfg->vlibOut = NULL;
vp_os_free (cfg->mp4h264Conf); vp_os_free (cfg->mp4h264Conf);
cfg->mp4h264Conf = NULL; cfg->mp4h264Conf = NULL;
vp_os_free (cfg->mp4h264Out); vp_os_free (cfg->mp4h264Out);
cfg->mp4h264Out = NULL; cfg->mp4h264Out = NULL;
return res; return res;
} }
#ifdef USE_ANDROID #ifdef USE_ANDROID
#define NEONCHECK_BUFFER_STRING_SIZE (512) #define NEONCHECK_BUFFER_STRING_SIZE (512)
void checkNeonSupport () void checkNeonSupport ()
{ {
neon_status_t loc_neonStat = NEON_SUPPORT_FAIL; neon_status_t loc_neonStat = NEON_SUPPORT_FAIL;
FILE *cpuInfo = fopen ("/proc/cpuinfo", "r"); resetDecoderOnStreamChange = 0;
if (NULL == cpuInfo) FILE *cpuInfo = fopen ("/proc/cpuinfo", "r");
if (NULL == cpuInfo)
{ {
return; return;
} }
char *neonCheckStrBuf = vp_os_malloc (NEONCHECK_BUFFER_STRING_SIZE * sizeof (char)); char *neonCheckStrBuf = vp_os_malloc (NEONCHECK_BUFFER_STRING_SIZE * sizeof (char));
if (NULL == neonCheckStrBuf) if (NULL == neonCheckStrBuf)
{ {
fclose (cpuInfo); fclose (cpuInfo);
return; return;
} }
while (NULL != fgets (neonCheckStrBuf, NEONCHECK_BUFFER_STRING_SIZE, cpuInfo)) while (NULL != fgets (neonCheckStrBuf, NEONCHECK_BUFFER_STRING_SIZE, cpuInfo))
{ {
char *supportTest = strstr (neonCheckStrBuf, "neon"); char *supportTest = strstr (neonCheckStrBuf, "neon");
if (NULL != supportTest) if (NULL != supportTest)
{ {
loc_neonStat = NEON_SUPPORT_OK; loc_neonStat = NEON_SUPPORT_OK;
break; resetDecoderOnStreamChange = 1;
break;
} }
} }
vp_os_free (neonCheckStrBuf);
fclose (cpuInfo);
neonStatus = loc_neonStat; vp_os_free (neonCheckStrBuf);
neonCheckStrBuf = NULL;
fclose (cpuInfo);
neonStatus = loc_neonStat;
} }
C_RESULT mp4h264_open (mp4h264_config_t *cfg) C_RESULT mp4h264_open (mp4h264_config_t *cfg)
{ {
if (NEON_SUPPORT_UNKNOWN == neonStatus) #if ITTIAM_SUPPORT
checkNeonSupport (); if (NEON_SUPPORT_UNKNOWN == neonStatus)
if (NEON_SUPPORT_OK == neonStatus) checkNeonSupport ();
return ittiam_stage_decoding_open (cfg); if (NEON_SUPPORT_OK == neonStatus)
else return ittiam_stage_decoding_open ((ittiam_stage_decoding_config_t *)cfg);
return ffmpeg_stage_decoding_open (cfg); else
#endif
return ffmpeg_stage_decoding_open (cfg);
} }
C_RESULT mp4h264_transform (mp4h264_config_t *cfg, vp_api_io_data_t *in, vp_api_io_data_t *out) C_RESULT mp4h264_transform (mp4h264_config_t *cfg, vp_api_io_data_t *in, vp_api_io_data_t *out)
{ {
if (NEON_SUPPORT_UNKNOWN == neonStatus) #if ITTIAM_SUPPORT
checkNeonSupport (); if (NEON_SUPPORT_UNKNOWN == neonStatus)
if (NEON_SUPPORT_OK == neonStatus) checkNeonSupport ();
return ittiam_stage_decoding_transform (cfg, in, out); if (NEON_SUPPORT_OK == neonStatus)
else return ittiam_stage_decoding_transform ((ittiam_stage_decoding_config_t *)cfg, in, out);
return ffmpeg_stage_decoding_transform (cfg, in, out); else
#endif
return ffmpeg_stage_decoding_transform (cfg, in, out);
} }
C_RESULT mp4h264_close (mp4h264_config_t *cfg) C_RESULT mp4h264_close (mp4h264_config_t *cfg)
{ {
if (NEON_SUPPORT_UNKNOWN == neonStatus) #if ITTIAM_SUPPORT
checkNeonSupport (); if (NEON_SUPPORT_UNKNOWN == neonStatus)
if (NEON_SUPPORT_OK == neonStatus) checkNeonSupport ();
return ittiam_stage_decoding_close (cfg); if (NEON_SUPPORT_OK == neonStatus)
else return ittiam_stage_decoding_close ((ittiam_stage_decoding_config_t *)cfg);
return ffmpeg_stage_decoding_close (cfg); else
#endif
return ffmpeg_stage_decoding_close (cfg);
} }
#endif #endif
@@ -11,18 +11,17 @@
#ifndef __VIDEO_STAGE_DECODER_H__ #ifndef __VIDEO_STAGE_DECODER_H__
#define __VIDEO_STAGE_DECODER_H__ #define __VIDEO_STAGE_DECODER_H__
#ifndef TARGET_OS_ANDROID #ifdef FFMPEG_SUPPORT
# ifdef ITTIAM_SUPPORT
# define mp4h264_config_t ittiam_stage_decoding_config_t
# include <ardrone_tool/Video/video_stage_ittiam_decoder.h>
# else // FFMPEG
# define mp4h264_config_t ffmpeg_stage_decoding_config_t
# endif
#else
# define mp4h264_config_t ffmpeg_stage_decoding_config_t # define mp4h264_config_t ffmpeg_stage_decoding_config_t
# include <ardrone_tool/Video/video_stage_ittiam_decoder.h> #elif defined (ITTIAM_SUPPORT)
# define mp4h264_config_t ittiam_stage_decoding_config_t
#else
# error Either FFMPEG_SUPPORT or ITTIAM_SUPPORT must be defined
#endif #endif
#ifdef ITTIAM_SUPPORT
# include <ardrone_tool/Video/video_stage_ittiam_decoder.h>
#endif
#ifdef FFMPEG_SUPPORT #ifdef FFMPEG_SUPPORT
# include <ardrone_tool/Video/video_stage_ffmpeg_decoder.h> # include <ardrone_tool/Video/video_stage_ffmpeg_decoder.h>
@@ -17,10 +17,6 @@
#include <ardrone_tool/Video/video_navdata_handler.h> #include <ardrone_tool/Video/video_navdata_handler.h>
#ifdef USE_ELINUX
#define VIDEO_ENCODED_FILE_DEFAULT_PATH "/data/video/usb/"
#endif
#define VIDEO_ENCODED_RECORDER_VERBOSE (1) #define VIDEO_ENCODED_RECORDER_VERBOSE (1)
#if defined(DEBUG) || VIDEO_ENCODED_RECORDER_VERBOSE #if defined(DEBUG) || VIDEO_ENCODED_RECORDER_VERBOSE
@@ -58,468 +54,269 @@ extern char flight_dir[];
#endif #endif
const vp_api_stage_funcs_t video_encoded_recorder_funcs = { const vp_api_stage_funcs_t video_encoded_recorder_funcs = {
(vp_api_stage_handle_msg_t) video_stage_encoded_recorder_handle, (vp_api_stage_handle_msg_t) video_stage_encoded_recorder_handle,
(vp_api_stage_open_t) video_stage_encoded_recorder_open, (vp_api_stage_open_t) video_stage_encoded_recorder_open,
(vp_api_stage_transform_t) video_stage_encoded_recorder_transform, (vp_api_stage_transform_t) video_stage_encoded_recorder_transform,
(vp_api_stage_close_t) video_stage_encoded_recorder_close (vp_api_stage_close_t) video_stage_encoded_recorder_close
}; };
video_stage_encoded_recorder_config_t video_stage_encoded_recorder_config; video_stage_encoded_recorder_config_t video_stage_encoded_recorder_config;
#ifdef USE_ELINUX
DEFINE_THREAD_ROUTINE_STACK(video_stage_encoded_recorder,param,VIDEO_STAGE_ENCODED_RECORDER_STACK_SIZE)
{
int res;
video_stage_encoded_recorder_config_t *cfg = (video_stage_encoded_recorder_config_t *)param;
video_stage_encoded_recorder_msg_t msg;
char errBuf [50] = {0};
ardrone_video_error_t vError = ARDRONE_VIDEO_NO_ERROR;
parrot_video_encapsulation_t *PaVE;
//int counter = 0;
/* TODO : check if mutual exclusion with the main thread is needed */
while(1)
{
/* Read the address of a new slice to write in the video file */
res = read(cfg->com_pipe[0],&msg,sizeof(msg));
if (res!=sizeof(msg)) { sleep(1); continue; }
//printf("----> Reading %p %d bytes\n",msg.slice,msg.sliceSize);
PaVE = (parrot_video_encapsulation_t *) msg.slice;
if (msg.slice!=NULL)
{
/* Create a new MP4 file if necessary */
if (NULL==cfg->video)
{
cfg->video = ardrone_video_start (cfg->video_filename, cfg->fps, VIDEO_FORMAT, &vError);
if (ARDRONE_VIDEO_SUCCEEDED (vError) && NULL != cfg->video)
{
cfg->currentStreamId = PaVE->stream_id;
}
else
{
VER_PRINT ("An error occured when creating video");
cfg->startRec=VIDEO_ENCODED_STOPPED;
}
}
if (NULL!=cfg->video)
{
ardrone_video_error_t vError = ardrone_video_addSlice (cfg->video, msg.slice);
if (ARDRONE_VIDEO_FAILED (vError))
{
ardrone_video_error_string (vError, errBuf, 50);
VER_PRINT ("Error while recording frame : %s", errBuf);
ardrone_video_cleanup (&(cfg->video));
cfg->startRec = VIDEO_ENCODED_STOPPED;
}
if (1 == frameIsLastFrame(msg.slice))
{
VER_PRINT ("Received last frame for current stream, finishing video\n");
video_stage_encoded_recorder_finish (cfg);
}
//counter++; if (counter%16) { sync(); }
}
/* Free the data bloc which was just written */
vp_os_free(msg.slice);
}
else /* the data pointer is NULL to signal the end of the recording */
{
video_stage_encoded_recorder_finish (cfg);
}
}/*while 1*/
}
#endif
C_RESULT video_stage_encoded_recorder_finish (video_stage_encoded_recorder_config_t *cfg) C_RESULT video_stage_encoded_recorder_finish (video_stage_encoded_recorder_config_t *cfg)
{ {
C_RESULT retVal = C_OK; C_RESULT retVal = C_OK;
#ifndef USE_ELINUX endRetreiving ();
endRetreiving ();
#endif
cfg->lastStreamId = cfg->currentStreamId; cfg->lastStreamId = cfg->currentStreamId;
ardrone_video_error_t vError = ardrone_video_finish (&(cfg->video)); ardrone_video_error_t vError = ardrone_video_finish (&(cfg->video));
if (ARDRONE_VIDEO_SUCCEEDED (vError)) if (ARDRONE_VIDEO_SUCCEEDED (vError))
{ {
VER_PRINT ("Video %s successfully written", cfg->video_filename); VER_PRINT ("Video %s successfully written", cfg->video_filename);
if(cfg->finish_callback != NULL) if(cfg->finish_callback != NULL)
cfg->finish_callback((const char *)cfg->video_filename); cfg->finish_callback((const char *)cfg->video_filename, FALSE);
} }
else else
{ {
VER_PRINT ("Error while completing video"); VER_PRINT ("Error while completing video");
retVal = C_FAIL; retVal = C_FAIL;
} }
// Erase filename // Erase filename
vp_os_memset (cfg->video_filename, 0x0, VIDEO_ENCODED_FILENAME_LENGTH); vp_os_memset (cfg->video_filename, 0x0, VIDEO_ENCODED_FILENAME_LENGTH);
cfg->startRec = VIDEO_ENCODED_STOPPED; cfg->startRec = VIDEO_ENCODED_STOPPED;
#ifdef USE_ELINUX return retVal;
ardrone_video_system_cleanup();
#endif
return retVal;
} }
C_RESULT video_stage_encoded_recorder_handle (video_stage_encoded_recorder_config_t * cfg, PIPELINE_MSG msg_id, void *callback, void *param) C_RESULT video_stage_encoded_recorder_handle (video_stage_encoded_recorder_config_t * cfg, PIPELINE_MSG msg_id, void *callback, void *param)
{ {
#ifdef USE_ELINUX vp_os_mutex_lock (&cfg->videoMutex);
/* Handling the asynchronous mode */
video_stage_encoded_recorder_msg_t asyn_msg;
#endif
void (*recorder_callback)(video_stage_encoded_recorder_config_t*) = callback;
#ifndef USE_ELINUX
vp_os_mutex_lock (&cfg->videoMutex); switch (msg_id)
#endif
void (*recorder_callback)(video_stage_encoded_recorder_config_t*) = callback;
switch (msg_id)
{ {
case PIPELINE_MSG_START: // video start case PIPELINE_MSG_START: // video start
if(cfg->startRec==VIDEO_ENCODED_STOPPED) if(cfg->startRec==VIDEO_ENCODED_STOPPED)
{ {
time_t t; cfg->startRec = VIDEO_ENCODED_START_RECORD;
char date[ARDRONE_DATE_MAXSIZE]; time_t t;
ardrone_time2date(*((uint32_t*)param), ARDRONE_FILE_DATE_FORMAT, date); char date[ARDRONE_DATE_MAXSIZE];
char media_dirname[VIDEO_ENCODED_FILENAME_LENGTH]; ardrone_time2date(*((uint32_t*)param), ARDRONE_FILE_DATE_FORMAT, date);
struct stat statbuf; char media_dirname[VIDEO_ENCODED_FILENAME_LENGTH];
struct stat statbuf;
snprintf(media_dirname, VIDEO_ENCODED_FILENAME_LENGTH, "%s/media_%s", VIDEO_ENCODED_FILE_DEFAULT_PATH, date); snprintf(media_dirname, VIDEO_ENCODED_FILENAME_LENGTH, "%s/media_%s", VIDEO_ENCODED_FILE_DEFAULT_PATH, date);
if((stat(media_dirname, &statbuf) != 0) && (mkdir(media_dirname, 0777) >= 0)) if((stat(media_dirname, &statbuf) != 0) && (mkdir(media_dirname, 0777) >= 0))
VER_PRINT("Create local media directory %s if not exist\n", media_dirname); VER_PRINT("Create local media directory %s if not exist\n", media_dirname);
t = time(NULL); t = time(NULL);
ardrone_time2date(t, ARDRONE_FILE_DATE_FORMAT, date); ardrone_time2date(t, ARDRONE_FILE_DATE_FORMAT, date);
snprintf(cfg->video_filename, snprintf(cfg->video_filename,
VIDEO_ENCODED_FILENAME_LENGTH, VIDEO_ENCODED_FILENAME_LENGTH,
"%s/video_%s.%s", "%s/video_%s.%s",
media_dirname, media_dirname,
date, date,
MOVIE_FILE_EXTENSION); MOVIE_FILE_EXTENSION);
cfg->startRec = VIDEO_ENCODED_START_RECORD;
} }
break; break;
case PIPELINE_MSG_STOP: // video stop case PIPELINE_MSG_STOP: // video stop
if (cfg->startRec==VIDEO_ENCODED_START_RECORD) if (cfg->startRec==VIDEO_ENCODED_START_RECORD)
{ {
cfg->startRec=VIDEO_ENCODED_STOPPED; cfg->startRec=VIDEO_ENCODED_STOPPED;
} }
else if (cfg->startRec==VIDEO_ENCODED_RECORDING) else if (cfg->startRec==VIDEO_ENCODED_RECORDING)
{ {
cfg->startRec = VIDEO_ENCODED_WAITING_STREAM_END; cfg->startRec = VIDEO_ENCODED_WAITING_STREAM_END;
#ifndef USE_ELINUX startRetreiving ();
startRetreiving ();
#endif
} }
break; break;
case PIPELINE_MSG_SUSPEND: // Force stop case PIPELINE_MSG_SUSPEND: // Force stop
if (cfg->startRec==VIDEO_ENCODED_START_RECORD) if (cfg->startRec==VIDEO_ENCODED_START_RECORD)
{ {
cfg->startRec=VIDEO_ENCODED_STOPPED; cfg->startRec=VIDEO_ENCODED_STOPPED;
} }
else if (cfg->startRec==VIDEO_ENCODED_RECORDING || else if (cfg->startRec==VIDEO_ENCODED_RECORDING ||
cfg->startRec==VIDEO_ENCODED_WAITING_STREAM_END) cfg->startRec==VIDEO_ENCODED_WAITING_STREAM_END)
{ {
#ifdef USE_ELINUX video_stage_encoded_recorder_finish (cfg);
if (cfg->use_asynchronous_mode)
{
/* Send an empty slice to the asynchronous thread */
asyn_msg.sliceSize = 0;
asyn_msg.slice = NULL;
write(cfg->com_pipe[1],&asyn_msg,sizeof(asyn_msg));
}
else
{
#endif
video_stage_encoded_recorder_finish (cfg);
#ifdef USE_ELINUX
}
#endif
} }
break; break;
default: default:
break; break;
}
if (recorder_callback!=NULL) {
recorder_callback(cfg);
} }
if (recorder_callback!=NULL) {
recorder_callback(cfg);
}
vp_os_mutex_unlock (&cfg->videoMutex);
#ifndef USE_ELINUX return (VP_SUCCESS);
vp_os_mutex_unlock (&cfg->videoMutex);
#endif
return (VP_SUCCESS);
} }
bool_t video_stage_encoded_recorder_state(void) bool_t video_stage_encoded_recorder_state(void)
{ {
return (video_stage_encoded_recorder_config.startRec != VIDEO_ENCODED_STOPPED); return (video_stage_encoded_recorder_config.startRec != VIDEO_ENCODED_STOPPED);
} }
video_encoded_record_state video_stage_encoded_complete_recorder_state (void) video_encoded_record_state video_stage_encoded_complete_recorder_state (void)
{ {
return video_stage_encoded_recorder_config.startRec; return video_stage_encoded_recorder_config.startRec;
} }
void video_stage_encoded_recorder_enable(bool_t enable, uint32_t timestamp) void video_stage_encoded_recorder_enable(bool_t enable, uint32_t timestamp)
{ {
printf("Recording %s...\n", enable ? "started" : "stopped"); printf("Recording %s...\n", enable ? "started" : "stopped");
video_stage_encoded_recorder_handle (&video_stage_encoded_recorder_config, (enable ? PIPELINE_MSG_START : PIPELINE_MSG_STOP), NULL, &timestamp); video_stage_encoded_recorder_handle (&video_stage_encoded_recorder_config, (enable ? PIPELINE_MSG_START : PIPELINE_MSG_STOP), NULL, &timestamp);
} }
void video_stage_encoded_recorder_com_timeout (void) void video_stage_encoded_recorder_com_timeout (void)
{ {
if (VIDEO_ENCODED_WAITING_STREAM_END == video_stage_encoded_recorder_config.startRec) if (VIDEO_ENCODED_WAITING_STREAM_END == video_stage_encoded_recorder_config.startRec)
{ {
video_stage_encoded_recorder_force_stop (); video_stage_encoded_recorder_force_stop ();
} }
} }
void video_stage_encoded_recorder_force_stop (void) void video_stage_encoded_recorder_force_stop (void)
{ {
printf ("Force recording stop\n"); printf ("Force recording stop\n");
video_stage_encoded_recorder_handle (&video_stage_encoded_recorder_config, PIPELINE_MSG_SUSPEND, NULL, NULL); video_stage_encoded_recorder_handle (&video_stage_encoded_recorder_config, PIPELINE_MSG_SUSPEND, NULL, NULL);
} }
C_RESULT video_stage_encoded_recorder_open(video_stage_encoded_recorder_config_t *cfg) C_RESULT video_stage_encoded_recorder_open(video_stage_encoded_recorder_config_t *cfg)
{ {
if (0 == cfg->fps) if (0 == cfg->fps)
{ {
cfg->fps = 30; cfg->fps = 30;
} }
cfg->startRec=VIDEO_ENCODED_STOPPED; cfg->startRec=VIDEO_ENCODED_STOPPED;
cfg->lastStreamId = UINT16_MAX; cfg->lastStreamId = UINT16_MAX;
cfg->currentStreamId = UINT16_MAX; cfg->currentStreamId = UINT16_MAX;
cfg->video = NULL; cfg->video = NULL;
#ifndef USE_ELINUX
vp_os_mutex_init (&cfg->videoMutex);
ardrone_video_remove_all (VIDEO_ENCODED_FILE_DEFAULT_PATH);
#endif
#ifdef USE_ELINUX vp_os_mutex_init (&cfg->videoMutex);
if (cfg->use_asynchronous_mode){ ardrone_video_remove_all (VIDEO_ENCODED_FILE_DEFAULT_PATH);
/* Create a pipe to send video slices to the recording thread */
pipe((int*)(&cfg->com_pipe));
/* Create the above-mentioned thread */ return C_OK;
vp_os_thread_create(thread_video_stage_encoded_recorder,
(void*)cfg,
&cfg->thread_handle,
cfg->thread_priority,
"VideoFlashRec",
(void*)stack_video_stage_encoded_recorder,
sizeof(stack_video_stage_encoded_recorder),
&cfg->thread );
}
#endif
return C_OK;
} }
int frameIsLastFrame (uint8_t *data) int frameIsLastFrame (uint8_t *data)
{ {
int retVal = 0; int retVal = 0;
if (PAVE_CHECK (data)) if (PAVE_CHECK (data))
{ {
parrot_video_encapsulation_t *PaVE = (parrot_video_encapsulation_t *)data; parrot_video_encapsulation_t *PaVE = (parrot_video_encapsulation_t *)data;
if (PAVE_CTRL_LAST_FRAME_IN_STREAM & PaVE->control) if (PAVE_CTRL_LAST_FRAME_IN_STREAM & PaVE->control)
{ {
retVal = 1; retVal = 1;
} }
} }
return retVal; return retVal;
} }
#ifdef USE_ELINUX
int ardrone_video_usb_key_get_free_space(void);
#endif
C_RESULT video_stage_encoded_recorder_transform(video_stage_encoded_recorder_config_t *cfg, vp_api_io_data_t *in, vp_api_io_data_t *out) C_RESULT video_stage_encoded_recorder_transform(video_stage_encoded_recorder_config_t *cfg, vp_api_io_data_t *in, vp_api_io_data_t *out)
{ {
#ifdef USE_ELINUX vp_os_mutex_lock (&out->lock);
/* Handling the asynchronous mode */ vp_os_mutex_lock (&cfg->videoMutex);
video_stage_encoded_recorder_msg_t asyn_msg;
#endif
vp_os_mutex_lock (&out->lock); // Copy in to out
if (NULL != in && NULL != out)
#ifndef USE_ELINUX
vp_os_mutex_lock (&cfg->videoMutex);
#endif
// Copy in to out
if (NULL != in && NULL != out)
{ {
out->numBuffers = in->numBuffers; out->numBuffers = in->numBuffers;
out->indexBuffer = in->indexBuffer; out->indexBuffer = in->indexBuffer;
out->lineSize = in->lineSize; out->lineSize = in->lineSize;
out->size = in->size; out->size = in->size;
out->status = in->status; out->status = in->status;
out->buffers = in->buffers; out->buffers = in->buffers;
out->status = VP_API_STATUS_PROCESSING; out->status = VP_API_STATUS_PROCESSING;
} }
#ifdef USE_ELINUX uint8_t *slice = in->buffers[in->indexBuffer];
/* The drone pipeline may call the recorder with an empty input */ parrot_video_encapsulation_t *PaVE = (parrot_video_encapsulation_t *)slice;
if (NULL==in || NULL==in->buffers || in->size<1) { vp_os_mutex_unlock (&out->lock); return C_OK; } if (cfg->lastStreamId == PaVE->stream_id)
#endif
uint8_t *slice = in->buffers[in->indexBuffer];
parrot_video_encapsulation_t *PaVE = (parrot_video_encapsulation_t *)slice;
if (cfg->lastStreamId == PaVE->stream_id)
{ {
VER_PRINT ("Got a video slice from an old stream, skipping\n"); VER_PRINT ("Got a video slice from an old stream, skipping\n");
#ifndef USE_ELINUX vp_os_mutex_unlock (&cfg->videoMutex);
vp_os_mutex_unlock (&cfg->videoMutex); vp_os_mutex_unlock (&out->lock);
#endif return C_OK;
vp_os_mutex_unlock (&out->lock);
return C_OK;
} }
if(cfg->startRec == VIDEO_ENCODED_START_RECORD) if(cfg->startRec == VIDEO_ENCODED_START_RECORD)
{ {
ardrone_video_error_t vError = ARDRONE_VIDEO_NO_ERROR; ardrone_video_error_t vError = ARDRONE_VIDEO_NO_ERROR;
#ifdef USE_ELINUX
/* Determine the amount of video data we can store */
cfg->quota = ardrone_video_usb_key_get_free_space() /* kbytes */ - ( 100 * 1024 ); /* Keep 100 megabytes free */
if(cfg->quota<0) { cfg->quota = 0; }
printf("Flash video recording : available space : %dkb (time est. %d\'%d\") - (keeping a 100Mb margin on %s)\n",
cfg->quota,(cfg->quota>>10)/60,(cfg->quota>>10)%60,
VIDEO_ENCODED_FILE_DEFAULT_PATH);
if (cfg->use_asynchronous_mode) cfg->video = ardrone_video_start (cfg->video_filename, cfg->fps, VIDEO_FORMAT, &vError);
if (ARDRONE_VIDEO_SUCCEEDED (vError) && NULL != cfg->video)
{ {
cfg->startRec=VIDEO_ENCODED_RECORDING; cfg->startRec=VIDEO_ENCODED_RECORDING;
cfg->currentStreamId = PaVE->stream_id;
} }
else{ else
#endif {
VER_PRINT ("An error occured when creating video");
cfg->video = ardrone_video_start (cfg->video_filename, cfg->fps, VIDEO_FORMAT, &vError); cfg->startRec=VIDEO_ENCODED_STOPPED;
if (ARDRONE_VIDEO_SUCCEEDED (vError) && NULL != cfg->video)
{
cfg->startRec=VIDEO_ENCODED_RECORDING;
cfg->currentStreamId = PaVE->stream_id;
}
else
{
VER_PRINT ("An error occured when creating video");
cfg->startRec=VIDEO_ENCODED_STOPPED;
}
#ifdef USE_ELINUX
} }
#endif
} }
if((cfg->startRec == VIDEO_ENCODED_RECORDING) || if((cfg->startRec == VIDEO_ENCODED_RECORDING) ||
(cfg->startRec == VIDEO_ENCODED_WAITING_STREAM_END)) (cfg->startRec == VIDEO_ENCODED_WAITING_STREAM_END))
{ {
#if USE_LINUX #if USE_LINUX
/* Quick and dirty debugging inside AR.Drone Navigation */ /* Quick and dirty debugging inside AR.Drone Navigation */
if (PAVE_CHECK(slice)) if (PAVE_CHECK(slice))
{ {
parrot_video_encapsulation_t * pave = (parrot_video_encapsulation_t*) slice; parrot_video_encapsulation_t * pave = (parrot_video_encapsulation_t*) slice;
printf("Recording frame %dx%d num %d \n\033[1A",pave->display_width,pave->display_height,pave->frame_number); printf("Recording frame %dx%d num %d \n\033[1A",pave->display_width,pave->display_height,pave->frame_number);
if (pave->control & PAVE_CTRL_LAST_FRAME_IN_STREAM) { if (pave->control & PAVE_CTRL_LAST_FRAME_IN_STREAM) {
printf("\n\nEnd of stream PaVE received !\n\n"); printf("\n\nEnd of stream PaVE received !\n\n");
} }
} }
#endif #endif
ardrone_video_error_t vError = ardrone_video_addSlice (cfg->video, slice);
#ifdef USE_ELINUX if (ARDRONE_VIDEO_FAILED (vError))
if (( ( in->size /*bytes*/ ) >>10 ) > cfg->quota )
{ {
printf("Flash video recording : out of disk space.\n"); char errBuf [50] = {0};
cfg->startRec=VIDEO_ENCODED_STOPPED; ardrone_video_error_string (vError, errBuf, 50);
VER_PRINT ("Error while recording frame : %s", errBuf);
ardrone_video_cleanup (&(cfg->video));
cfg->startRec = VIDEO_ENCODED_STOPPED;
} }
else
if (1 == frameIsLastFrame (slice))
{ {
cfg->quota /*kbytes*/ -= ( ( in->size /*bytes*/ ) >>10 ); VER_PRINT ("Received last frame for current stream, finishing video\n");
navdata_set_hdvideo_usbkey_freespace(cfg->quota); video_stage_encoded_recorder_finish (cfg);
if (cfg->use_asynchronous_mode)
{
/* Create a RAM buffer to hold a temporary copy of the slice to write */
asyn_msg.sliceSize = in->size;
asyn_msg.slice = vp_os_malloc(asyn_msg.sliceSize);
if (asyn_msg.slice){
vp_os_memcpy(asyn_msg.slice,slice,asyn_msg.sliceSize);
/* Send the copy to thread which does the actual writing */
//printf("----> Writing %p %d bytes\n",asyn_msg.slice,asyn_msg.sliceSize);
write(cfg->com_pipe[1],&asyn_msg,sizeof(asyn_msg));
}
else
{
printf("Flash video recording : out of RAM - dropping frame.\n");
}
}
else
{
#endif
ardrone_video_error_t vError = ardrone_video_addSlice (cfg->video, slice);
if (ARDRONE_VIDEO_FAILED (vError))
{
char errBuf [50] = {0};
ardrone_video_error_string (vError, errBuf, 50);
VER_PRINT ("Error while recording frame : %s", errBuf);
ardrone_video_cleanup (&(cfg->video));
cfg->startRec = VIDEO_ENCODED_STOPPED;
}
if (1 == frameIsLastFrame (slice))
{
VER_PRINT ("Received last frame for current stream, finishing video\n");
video_stage_encoded_recorder_finish (cfg);
}
#ifdef USE_ELINUX
}
} }
#endif
} }
#ifndef USE_ELINUX vp_os_mutex_unlock (&cfg->videoMutex);
vp_os_mutex_unlock (&cfg->videoMutex); vp_os_mutex_unlock (&out->lock);
#endif return C_OK;
vp_os_mutex_unlock (&out->lock);
return C_OK;
} }
C_RESULT video_stage_encoded_recorder_close(video_stage_encoded_recorder_config_t *cfg) C_RESULT video_stage_encoded_recorder_close(video_stage_encoded_recorder_config_t *cfg)
{ {
if (NULL != cfg->video) if (NULL != cfg->video)
{ {
ardrone_video_finish (&(cfg->video)); ardrone_video_finish (&(cfg->video));
} }
return C_OK; return C_OK;
} }
@@ -18,7 +18,7 @@ typedef enum
} video_encoded_record_state; } video_encoded_record_state;
#endif #endif
typedef void (*video_stage_encoded_recorder_callback)(const char *mediaPath); typedef void (*video_stage_encoded_recorder_callback)(const char *mediaPath, bool_t addToQueue);
typedef struct _video_stage_encoded_recorder_config_t typedef struct _video_stage_encoded_recorder_config_t
{ {
@@ -214,19 +214,18 @@ void ffmpeg_decoder_dumpPave (parrot_video_encapsulation_t *PaVE)
static inline bool_t check_and_copy_PaVE (parrot_video_encapsulation_t *PaVE, vp_api_io_data_t *data, parrot_video_encapsulation_t *prevPaVE, bool_t *dimChanged) static inline bool_t check_and_copy_PaVE (parrot_video_encapsulation_t *PaVE, vp_api_io_data_t *data, parrot_video_encapsulation_t *prevPaVE, bool_t *dimChanged)
{ {
parrot_video_encapsulation_t *localPaVE = (parrot_video_encapsulation_t *)data->buffers[data->indexBuffer]; parrot_video_encapsulation_t *localPaVE = (parrot_video_encapsulation_t *)data->buffers[data->indexBuffer];
if (localPaVE->signature[0] == 'P' && if (localPaVE->signature[0] == 'P' &&
localPaVE->signature[1] == 'a' && localPaVE->signature[1] == 'a' &&
localPaVE->signature[2] == 'V' && localPaVE->signature[2] == 'V' &&
localPaVE->signature[3] == 'E') localPaVE->signature[3] == 'E')
{ {
//FFMPEG_DEBUG("Found a PaVE"); //FFMPEG_DEBUG("Found a PaVE");
vp_os_memcpy (prevPaVE, PaVE, sizeof (parrot_video_encapsulation_t)); // Make a backup of previous PaVE so we can check if things have changed vp_os_memcpy (prevPaVE, PaVE, sizeof (parrot_video_encapsulation_t)); // Make a backup of previous PaVE so we can check if things have changed
vp_os_memcpy (PaVE, localPaVE, sizeof (parrot_video_encapsulation_t)); // Copy PaVE to our local one vp_os_memcpy (PaVE, localPaVE, sizeof (parrot_video_encapsulation_t)); // Copy PaVE to our local one
#if __FFMPEG_DEBUG_ENABLED #if __FFMPEG_DEBUG_ENABLED
printf ("------------------------------------\n"); printf ("------------------------------------\n");
printf ("PREV : "); printf ("PREV : ");
@@ -291,7 +290,8 @@ C_RESULT ffmpeg_stage_decoding_transform(ffmpeg_stage_decoding_config_t *cfg, vp
int frameFinished = 0; int frameFinished = 0;
bool_t frameDimChanged = FALSE; bool_t frameDimChanged = FALSE;
static parrot_video_encapsulation_t PaVE, prevPaVE; static parrot_video_encapsulation_t __attribute__ ((aligned (4))) PaVE;
static parrot_video_encapsulation_t __attribute__ ((aligned (4))) prevPaVE;
#if WAIT_FOR_I_FRAME #if WAIT_FOR_I_FRAME
static bool_t waitForIFrame = TRUE; static bool_t waitForIFrame = TRUE;
@@ -300,7 +300,7 @@ C_RESULT ffmpeg_stage_decoding_transform(ffmpeg_stage_decoding_config_t *cfg, vp
#ifdef NUM_SAMPLES #ifdef NUM_SAMPLES
static struct timeval start_time, start_time2; static struct timeval start_time, start_time2;
static int numsamples = 0; static int numsamples = 0;
#endif #endif
if (0 == in->size) // No frame if (0 == in->size) // No frame
{ {
@@ -387,6 +387,7 @@ C_RESULT ffmpeg_stage_decoding_transform(ffmpeg_stage_decoding_config_t *cfg, vp
} }
#endif #endif
if(out->status == VP_API_STATUS_PROCESSING && (!waitForIFrame || (PaVE.frame_type == FRAME_TYPE_IDR_FRAME) || (PaVE.frame_type == FRAME_TYPE_I_FRAME))) // Processing code if(out->status == VP_API_STATUS_PROCESSING && (!waitForIFrame || (PaVE.frame_type == FRAME_TYPE_IDR_FRAME) || (PaVE.frame_type == FRAME_TYPE_I_FRAME))) // Processing code
{ {
waitForIFrame = FALSE; waitForIFrame = FALSE;
@@ -398,6 +399,7 @@ C_RESULT ffmpeg_stage_decoding_transform(ffmpeg_stage_decoding_config_t *cfg, vp
packet.data = ((unsigned char*)in->buffers[in->indexBuffer]); packet.data = ((unsigned char*)in->buffers[in->indexBuffer]);
packet.size = in->size; packet.size = in->size;
FFMPEG_DEBUG("Size : %d", packet.size); FFMPEG_DEBUG("Size : %d", packet.size);
#ifdef NUM_SAMPLES #ifdef NUM_SAMPLES
struct timeval end_time; struct timeval end_time;
@@ -443,6 +445,11 @@ C_RESULT ffmpeg_stage_decoding_transform(ffmpeg_stage_decoding_config_t *cfg, vp
} }
else else
{ {
/* Skip frames are usually 7 bytes long
* and make FFMPEG return an error. It is however normal to get
* skip frames from the drone.
*/
if (7!=PaVE.payload_size)
printf ("Decoding failed for a %s\n", (PaVE.frame_type == FRAME_TYPE_P_FRAME) ? "P Frame" : "I Frame"); printf ("Decoding failed for a %s\n", (PaVE.frame_type == FRAME_TYPE_P_FRAME) ? "P Frame" : "I Frame");
} }
@@ -795,7 +795,9 @@ C_RESULT ittiam_stage_decoding_close(ittiam_stage_decoding_config_t *cfg) {
} }
vp_os_free(h264_mem_rec); vp_os_free(h264_mem_rec);
h264_mem_rec = NULL;
vp_os_free(h264_ps_it_mem); vp_os_free(h264_ps_it_mem);
h264_ps_it_mem = NULL;
} else if (current_PaVE.video_codec == CODEC_MPEG4_VISUAL) { } else if (current_PaVE.video_codec == CODEC_MPEG4_VISUAL) {
//MPEG4 //MPEG4
@@ -820,7 +822,9 @@ C_RESULT ittiam_stage_decoding_close(ittiam_stage_decoding_config_t *cfg) {
} }
vp_os_free(mpeg4_mem_rec); vp_os_free(mpeg4_mem_rec);
mpeg4_mem_rec = NULL;
vp_os_free(mpeg4_ps_it_mem); vp_os_free(mpeg4_ps_it_mem);
mpeg4_ps_it_mem = NULL;
} }
old_num_frame = cfg->num_picture_decoded; old_num_frame = cfg->num_picture_decoded;
ITTIAM_DEBUG_PRINT("ITTIAM CLEAN"); ITTIAM_DEBUG_PRINT("ITTIAM CLEAN");
@@ -404,7 +404,10 @@ C_RESULT video_stage_tcp_transform(video_stage_tcp_config_t *cfg, vp_api_io_data
C_RESULT video_stage_tcp_close(video_stage_tcp_config_t *cfg) C_RESULT video_stage_tcp_close(video_stage_tcp_config_t *cfg)
{ {
vp_os_free (cfg->bufferPointer); vp_os_free (cfg->bufferPointer);
cfg->bufferPointer = NULL;
vp_os_free (cfg->globalBuffer); vp_os_free (cfg->globalBuffer);
cfg->globalBuffer = NULL;
vp_os_free (cfg->frameBuffer); vp_os_free (cfg->frameBuffer);
cfg->frameBuffer = NULL;
return C_OK; return C_OK;
} }
@@ -18,6 +18,7 @@ C_RESULT vlib_stage_decoding_open(vlib_stage_decoding_config_t *cfg)
video_controller_set_format( &cfg->controller, ACQ_WIDTH, ACQ_HEIGHT ); video_controller_set_format( &cfg->controller, ACQ_WIDTH, ACQ_HEIGHT );
vp_os_free( cfg->controller.in_stream.bytes ); vp_os_free( cfg->controller.in_stream.bytes );
cfg->controller.in_stream.bytes = NULL;
return C_OK; return C_OK;
} }
+3 -5
Ver Arquivo
@@ -275,7 +275,7 @@ C_RESULT ardrone_tool_shutdown()
ardrone_navdata_client_shutdown(); ardrone_navdata_client_shutdown();
ardrone_control_shutdown(); ardrone_control_shutdown();
ardrone_tool_input_shutdown(); ardrone_tool_input_shutdown();
JOIN_THREAD(ardrone_control); JOIN_THREAD(ardrone_control);
JOIN_THREAD(navdata_update); JOIN_THREAD(navdata_update);
@@ -332,14 +332,11 @@ int ardrone_tool_main(int argc, char **argv)
argc--; argv++; argc--; argv++;
} }
// Making the driver ROS compatible
/*
if( show_usage || (argc != 0) ) if( show_usage || (argc != 0) )
{ {
ardrone_tool_usage( appname ); ardrone_tool_usage( appname );
exit(-1); exit(-1);
} }
*/
/* After a first analysis, the arguments are restored so they can be passed to the user-defined functions */ /* After a first analysis, the arguments are restored so they can be passed to the user-defined functions */
argc=argc_backup; argc=argc_backup;
@@ -351,7 +348,6 @@ int ardrone_tool_main(int argc, char **argv)
{ {
PRINT("You have to install new locales in your dev environment! (avoid the need of conv_coma_to_dot)\n"); PRINT("You have to install new locales in your dev environment! (avoid the need of conv_coma_to_dot)\n");
PRINT("As root, do a \"dpkg-reconfigure locales\" and add en_GB.UTF8 to your locale settings\n"); PRINT("As root, do a \"dpkg-reconfigure locales\" and add en_GB.UTF8 to your locale settings\n");
PRINT("If you have any problem, feel free to contact Pierre Eline (pierre.eline@parrot.com)\n");
} }
else else
{ {
@@ -407,10 +403,12 @@ int ardrone_tool_main(int argc, char **argv)
appname = &argv[0][lastSlashPos+1]; appname = &argv[0][lastSlashPos+1];
ardrone_gen_appid (appname, __SDK_VERSION__, app_id, app_name, sizeof (app_name)); ardrone_gen_appid (appname, __SDK_VERSION__, app_id, app_name, sizeof (app_name));
res = ardrone_tool_init(wifi_ardrone_ip, strlen(wifi_ardrone_ip), NULL, appname, NULL, NULL, NULL, MAX_FLIGHT_STORING_SIZE, NULL); res = ardrone_tool_init(wifi_ardrone_ip, strlen(wifi_ardrone_ip), NULL, appname, NULL, NULL, NULL, MAX_FLIGHT_STORING_SIZE, NULL);
while( SUCCEED(res) && ardrone_tool_exit() == FALSE ) while( SUCCEED(res) && ardrone_tool_exit() == FALSE )
{ {
res = ardrone_tool_update(); res = ardrone_tool_update();
} }
res = ardrone_tool_shutdown(); res = ardrone_tool_shutdown();
} }
+1 -1
Ver Arquivo
@@ -66,7 +66,7 @@ C_RESULT ardrone_tool_shutdown(void);
void ardrone_tool_init_timers_and_mutex(); void ardrone_tool_init_timers_and_mutex();
void ardrone_tool_send_com_watchdog(void); // To send it only once void ardrone_tool_send_com_watchdog(void); // To send it only once
//int main(); int main();
// There because not defined in embedded // There because not defined in embedded
void api_configuration_get_ctrl_mode(void); void api_configuration_get_ctrl_mode(void);
@@ -226,9 +226,15 @@ static void ardrone_tool_configuration_event_configure_end(struct _ardrone_contr
} }
if (NULL!=ardrone_tool_configuration_data[ardrone_tool_configuration_current_index].value) if (NULL!=ardrone_tool_configuration_data[ardrone_tool_configuration_current_index].value)
{
vp_os_free(ardrone_tool_configuration_data[ardrone_tool_configuration_current_index].value); vp_os_free(ardrone_tool_configuration_data[ardrone_tool_configuration_current_index].value);
ardrone_tool_configuration_data[ardrone_tool_configuration_current_index].value = NULL;
}
if (NULL!=ardrone_tool_configuration_data[ardrone_tool_configuration_current_index].event) if (NULL!=ardrone_tool_configuration_data[ardrone_tool_configuration_current_index].event)
{
vp_os_free(ardrone_tool_configuration_data[ardrone_tool_configuration_current_index].event); vp_os_free(ardrone_tool_configuration_data[ardrone_tool_configuration_current_index].event);
ardrone_tool_configuration_data[ardrone_tool_configuration_current_index].event = NULL;
}
ardrone_tool_configuration_data[ardrone_tool_configuration_current_index].event = NULL; ardrone_tool_configuration_data[ardrone_tool_configuration_current_index].event = NULL;
ardrone_tool_configuration_data[ardrone_tool_configuration_current_index].value = NULL; ardrone_tool_configuration_data[ardrone_tool_configuration_current_index].value = NULL;
ardrone_tool_configuration_current_index = (ardrone_tool_configuration_current_index + 1) % ARDRONE_TOOL_CONFIGURATION_MAX_EVENT; ardrone_tool_configuration_current_index = (ardrone_tool_configuration_current_index + 1) % ARDRONE_TOOL_CONFIGURATION_MAX_EVENT;
@@ -269,7 +275,9 @@ static void ardrone_tool_configuration_event_configure(void)
ardrone_control_ack_event_t *event = NULL; ardrone_control_ack_event_t *event = NULL;
if (ardrone_tool_configuration_data[ardrone_tool_configuration_current_index].callback) if (ardrone_tool_configuration_data[ardrone_tool_configuration_current_index].callback)
{
ardrone_tool_configuration_data[ardrone_tool_configuration_current_index].callback(ardrone_tool_configuration_data[ardrone_tool_configuration_current_index].value, ses_id, usr_id, app_id); ardrone_tool_configuration_data[ardrone_tool_configuration_current_index].callback(ardrone_tool_configuration_data[ardrone_tool_configuration_current_index].value, ses_id, usr_id, app_id);
}
if(ardrone_tool_configuration_data[ardrone_tool_configuration_current_index].event == NULL) if(ardrone_tool_configuration_data[ardrone_tool_configuration_current_index].event == NULL)
ardrone_tool_configuration_data[ardrone_tool_configuration_current_index].event = vp_os_malloc(sizeof(ardrone_control_ack_event_t)); ardrone_tool_configuration_data[ardrone_tool_configuration_current_index].event = vp_os_malloc(sizeof(ardrone_control_ack_event_t));
@@ -6,6 +6,8 @@
#include <stdio.h> #include <stdio.h>
#ifndef USE_ELINUX
int int
compareVersions (ardrone_version_t *v1, ardrone_version_t *v2) compareVersions (ardrone_version_t *v1, ardrone_version_t *v2)
{ {
@@ -53,6 +55,7 @@ getDroneVersion (const char *tempPath, const char *droneIp, ardrone_version_t *v
if (FTP_FAILED (status)) if (FTP_FAILED (status))
{ {
vp_os_free (localName); vp_os_free (localName);
localName = NULL;
ftpClose (&ftp); ftpClose (&ftp);
return -1; return -1;
} }
@@ -64,6 +67,7 @@ getDroneVersion (const char *tempPath, const char *droneIp, ardrone_version_t *v
{ {
remove (localName); remove (localName);
vp_os_free (localName); vp_os_free (localName);
localName = NULL;
return -1; return -1;
} }
@@ -73,12 +77,14 @@ getDroneVersion (const char *tempPath, const char *droneIp, ardrone_version_t *v
fclose (versionFile); fclose (versionFile);
remove (localName); remove (localName);
vp_os_free (localName); vp_os_free (localName);
localName = NULL;
return -1; return -1;
} }
fclose (versionFile); fclose (versionFile);
remove (localName); remove (localName);
vp_os_free (localName); vp_os_free (localName);
localName = NULL;
version->majorVersion = maj; version->majorVersion = maj;
version->minorVersion = min; version->minorVersion = min;
@@ -86,3 +92,5 @@ getDroneVersion (const char *tempPath, const char *droneIp, ardrone_version_t *v
return 0; return 0;
} }
#endif
@@ -59,6 +59,8 @@ int getDroneVersion (const char *tempPath, const char *droneIp, ardrone_version_
# define ARDRONE_VERSION() 1 # define ARDRONE_VERSION() 1
# endif # endif
#define getDroneVersion(...) ARDRONE_VERSION()
#endif #endif
#define IS_ARDRONE1 (1 == ARDRONE_VERSION()) // Drone 1 #define IS_ARDRONE1 (1 == ARDRONE_VERSION()) // Drone 1
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+1
Ver Arquivo
@@ -61,6 +61,7 @@ typedef struct _ftp_s
int abortCurrentOp; int abortCurrentOp;
_ftp_status lastStatus; _ftp_status lastStatus;
char *lastFileList; char *lastFileList;
void * tag; // Allows to put any pointer to some useful data that is associated with this ftp connectionS
} _ftp_t; } _ftp_t;
/** /**
+39 -39
Ver Arquivo
@@ -3,16 +3,16 @@
#include <utils/ardrone_time.h> #include <utils/ardrone_time.h>
#if defined(_WIN32) #if defined(_WIN32)
#include <sys/timeb.h> #include <sys/timeb.h>
static int _gettimeofday (struct timeval *tp, void *tz) static int _gettimeofday (struct timeval *tp, void *tz)
{ {
struct _timeb timebuffer; struct _timeb timebuffer;
_ftime (&timebuffer); _ftime (&timebuffer);
tp->tv_sec = (long)timebuffer.time; tp->tv_sec = (long)timebuffer.time;
tp->tv_usec = (long)timebuffer.millitm * 1000; tp->tv_usec = (long)timebuffer.millitm * 1000;
return 0; return 0;
} }
#elif defined(TARGET_OS_IPHONE) || defined(TARGET_OS_SIMULATOR) #elif defined(TARGET_OS_IPHONE) || defined(TARGET_OS_SIMULATOR)
#include <mach/mach_time.h> #include <mach/mach_time.h>
static int _gettimeofday (struct timeval *tp, void *tz) static int _gettimeofday (struct timeval *tp, void *tz)
@@ -20,13 +20,13 @@ static int _gettimeofday (struct timeval *tp, void *tz)
mach_timebase_info_data_t sTimebaseInfo; mach_timebase_info_data_t sTimebaseInfo;
uint64_t mtime = mach_absolute_time(); uint64_t mtime = mach_absolute_time();
uint64_t useconds; uint64_t useconds;
mach_timebase_info(&sTimebaseInfo); mach_timebase_info(&sTimebaseInfo);
useconds = (mtime * (sTimebaseInfo.numer / sTimebaseInfo.denom) / 1000); useconds = (mtime * (sTimebaseInfo.numer / sTimebaseInfo.denom) / 1000);
tp->tv_sec = (long)(useconds / 1000000); tp->tv_sec = (long)(useconds / 1000000);
tp->tv_usec = (long)(useconds % 1000000); tp->tv_usec = (long)(useconds % 1000000);
return 0; return 0;
} }
#else #else
@@ -36,21 +36,21 @@ static int _gettimeofday (struct timeval *tp, void *tz)
C_RESULT ardrone_timer_reset(ardrone_timer_t* timer) C_RESULT ardrone_timer_reset(ardrone_timer_t* timer)
{ {
vp_os_memset(timer, 0, sizeof(ardrone_timer_t)); vp_os_memset(timer, 0, sizeof(ardrone_timer_t));
return C_OK; return C_OK;
} }
C_RESULT ardrone_timer_update(ardrone_timer_t* timer) C_RESULT ardrone_timer_update(ardrone_timer_t* timer)
{ {
C_RESULT retVal = C_OK; C_RESULT retVal = C_OK;
if( timer->init == FALSE ) if( timer->init == FALSE )
{ {
_gettimeofday(&timer->tv_init, NULL); _gettimeofday(&timer->tv_init, NULL);
timer->init = TRUE; timer->init = TRUE;
} }
_gettimeofday(&timer->tv, NULL); _gettimeofday(&timer->tv, NULL);
if (timer->tv.tv_usec >= timer->tv_init.tv_usec) if (timer->tv.tv_usec >= timer->tv_init.tv_usec)
{ {
timer->tv.tv_usec -= timer->tv_init.tv_usec; timer->tv.tv_usec -= timer->tv_init.tv_usec;
@@ -69,19 +69,19 @@ C_RESULT ardrone_timer_update(ardrone_timer_t* timer)
} }
timer->tv.tv_sec -= timer->tv_init.tv_sec; timer->tv.tv_sec -= timer->tv_init.tv_sec;
return C_OK; return retVal;
} }
uint64_t ardrone_timer_elapsed_ms(ardrone_timer_t* timer) uint64_t ardrone_timer_elapsed_ms(ardrone_timer_t* timer)
{ {
uint64_t time; uint64_t time;
time = -1; time = -1;
if( timer->init ) if( timer->init )
{ {
time = (1000ll * (uint64_t)timer->tv.tv_sec) + ((uint64_t)timer->tv.tv_usec / 1000ll); time = (1000ll * (uint64_t)timer->tv.tv_sec) + ((uint64_t)timer->tv.tv_usec / 1000ll);
} }
return time; return time;
} }
@@ -90,22 +90,22 @@ uint64_t ardrone_timer_elapsed_us(ardrone_timer_t* timer)
{ {
uint64_t time; uint64_t time;
time = -1; time = -1;
if( timer->init ) if( timer->init )
{ {
time = (1000000ll * (uint64_t)timer->tv.tv_sec) + ((uint64_t)timer->tv.tv_usec); time = (1000000ll * (uint64_t)timer->tv.tv_sec) + ((uint64_t)timer->tv.tv_usec);
} }
return time; return time;
} }
uint64_t ardrone_timer_delta_ms(ardrone_timer_t* timer) uint64_t ardrone_timer_delta_ms(ardrone_timer_t* timer)
{ {
ardrone_timer_t timer_current; ardrone_timer_t timer_current;
timer_current.init = TRUE; timer_current.init = TRUE;
timer_current.tv_init = timer->tv_init; timer_current.tv_init = timer->tv_init;
uint64_t retVal = 0; uint64_t retVal = 0;
if (C_OK == ardrone_timer_update(&timer_current)) if (C_OK == ardrone_timer_update(&timer_current))
@@ -118,16 +118,16 @@ uint64_t ardrone_timer_delta_ms(ardrone_timer_t* timer)
uint64_t ardrone_timer_delta_us(ardrone_timer_t* timer) uint64_t ardrone_timer_delta_us(ardrone_timer_t* timer)
{ {
ardrone_timer_t timer_current; ardrone_timer_t timer_current;
timer_current.init = TRUE; timer_current.init = TRUE;
timer_current.tv_init = timer->tv_init; timer_current.tv_init = timer->tv_init;
uint64_t retVal = 0; uint64_t retVal = 0;
if (C_OK == ardrone_timer_update(&timer_current)) if (C_OK == ardrone_timer_update(&timer_current))
{ {
retVal = ardrone_timer_elapsed_us(&timer_current) - ardrone_timer_elapsed_us(timer); retVal = ardrone_timer_elapsed_us(&timer_current) - ardrone_timer_elapsed_us(timer);
} }
return retVal; return retVal;
} }
+3
Ver Arquivo
@@ -7,6 +7,9 @@
#include <VP_Os/vp_os_types.h> #include <VP_Os/vp_os_types.h>
#define ARDRONE_TIME_SEC_TO_MSEC(x) ((x)*1000.f)
#define ARDRONE_TIME_MSEC_TO_SEC(x) ((x)/1000.f)
typedef struct _ardrone_timer_t typedef struct _ardrone_timer_t
{ {
bool_t init; bool_t init;
+331 -308
Ver Arquivo
@@ -84,49 +84,51 @@
movie_atom_t *atomFromData (uint32_t data_size, const char *_tag, const uint8_t *_data) movie_atom_t *atomFromData (uint32_t data_size, const char *_tag, const uint8_t *_data)
{ {
movie_atom_t *retAtom = ATOM_MALLOC (sizeof (movie_atom_t)); movie_atom_t *retAtom = ATOM_MALLOC (sizeof (movie_atom_t));
if (NULL == retAtom) if (NULL == retAtom)
{ {
return retAtom; return retAtom;
} }
retAtom->size = data_size + 8; retAtom->size = data_size + 8;
strncpy (retAtom->tag, _tag, 4); strncpy (retAtom->tag, _tag, 4);
retAtom->data = NULL; retAtom->data = NULL;
if (NULL != _data && data_size > 0) if (NULL != _data && data_size > 0)
{ {
retAtom->data = ATOM_MALLOC (data_size); retAtom->data = ATOM_MALLOC (data_size);
if (NULL == retAtom->data) if (NULL == retAtom->data)
{ {
ATOM_FREE (retAtom); ATOM_FREE (retAtom);
return NULL; retAtom = NULL;
return NULL;
} }
ATOM_MEMCOPY (retAtom->data, _data, data_size); ATOM_MEMCOPY (retAtom->data, _data, data_size);
} }
retAtom->wide = 0; retAtom->wide = 0;
return retAtom; return retAtom;
} }
void insertAtomIntoAtom (movie_atom_t *container, movie_atom_t **leaf) void insertAtomIntoAtom (movie_atom_t *container, movie_atom_t **leaf)
{ {
uint32_t new_container_size = container->size - 8 + (*leaf)->size; uint32_t new_container_size = container->size - 8 + (*leaf)->size;
container->data = ATOM_REALLOC (container->data, new_container_size); container->data = ATOM_REALLOC (container->data, new_container_size);
if (NULL == container->data) if (NULL == container->data)
{ {
fprintf (stderr, "Alloc error for atom insertion\n"); fprintf (stderr, "Alloc error for atom insertion\n");
return; return;
} }
uint32_t leafSizeNetworkEndian = htonl ((*leaf)->size); uint32_t leafSizeNetworkEndian = htonl ((*leaf)->size);
ATOM_MEMCOPY (&container->data[container->size - 8], &leafSizeNetworkEndian, sizeof (uint32_t)); ATOM_MEMCOPY (&container->data[container->size - 8], &leafSizeNetworkEndian, sizeof (uint32_t));
ATOM_MEMCOPY (&container->data[container->size - 4], (*leaf)->tag, 4); ATOM_MEMCOPY (&container->data[container->size - 4], (*leaf)->tag, 4);
if (NULL != (*leaf)->data) if (NULL != (*leaf)->data)
{ {
ATOM_MEMCOPY (&container->data[container->size], (*leaf)->data, ((*leaf)->size - 8)); ATOM_MEMCOPY (&container->data[container->size], (*leaf)->data, ((*leaf)->size - 8));
container->size = new_container_size + 8; container->size = new_container_size + 8;
} }
ATOM_FREE ((*leaf)->data); ATOM_FREE ((*leaf)->data);
ATOM_FREE (*leaf); (*leaf)->data = NULL;
*leaf = NULL; ATOM_FREE (*leaf);
*leaf = NULL;
} }
int writeAtomToFile (movie_atom_t **_atom, FILE *file) int writeAtomToFile (movie_atom_t **_atom, FILE *file)
@@ -135,108 +137,123 @@ int writeAtomToFile (movie_atom_t **_atom, FILE *file)
{ {
return -1; return -1;
} }
uint32_t networkEndianSize = htonl ((*_atom)->size); uint32_t networkEndianSize = htonl ((*_atom)->size);
if (4 != fwrite (&networkEndianSize, 1, 4, file)) if (4 != fwrite (&networkEndianSize, 1, 4, file))
{ {
return -1; return -1;
} }
if (4 != fwrite ((*_atom)->tag, 1, 4, file)) if (4 != fwrite ((*_atom)->tag, 1, 4, file))
{ {
return -1; return -1;
} }
if (NULL != (*_atom)->data) if (NULL != (*_atom)->data)
{ {
uint32_t atom_data_size = 0; uint32_t atom_data_size = 0;
if (1 == (*_atom)->wide) if (1 == (*_atom)->wide)
{ {
atom_data_size = 8; atom_data_size = 8;
} }
else else
{ {
atom_data_size = (*_atom)->size - 8; atom_data_size = (*_atom)->size - 8;
} }
if (atom_data_size != fwrite ((*_atom)->data, 1, atom_data_size, file)) if (atom_data_size != fwrite ((*_atom)->data, 1, atom_data_size, file))
{ {
return -1; return -1;
} }
} }
ATOM_FREE ((*_atom)->data); ATOM_FREE ((*_atom)->data);
ATOM_FREE (*_atom); (*_atom)->data = NULL;
*_atom = NULL; ATOM_FREE (*_atom);
*_atom = NULL;
return 0;
}
return 0; void freeAtom (movie_atom_t **_atom)
{
if ((NULL != _atom) &&
(NULL != *_atom))
{
if (NULL != (*_atom)->data)
{
ATOM_FREE ((*_atom)->data);
}
ATOM_FREE (*_atom);
*_atom = NULL;
}
} }
movie_atom_t *ftypAtomForFormatAndCodecWithOffset (ardrone_video_type_t format, parrot_video_encapsulation_codecs_t codec, uint32_t *offset, movie_atom_t **wideAtom) movie_atom_t *ftypAtomForFormatAndCodecWithOffset (ardrone_video_type_t format, parrot_video_encapsulation_codecs_t codec, uint32_t *offset, movie_atom_t **wideAtom)
{ {
if (NULL == offset || NULL == wideAtom) if (NULL == offset || NULL == wideAtom)
{ {
return NULL; return NULL;
} }
movie_atom_t *retAtom = NULL; movie_atom_t *retAtom = NULL;
if (ARDRONE_VIDEO_MP4 == format) if (ARDRONE_VIDEO_MP4 == format)
{ {
uint8_t data [24] = {'i', 's', 'o', 'm', uint8_t data [24] = {'i', 's', 'o', 'm',
0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,
'i', 's', 'o', 'm', 'i', 's', 'o', 'm',
'i', 's', 'o', '2', 'i', 's', 'o', '2',
'a', 'v', 'c', '1', 'a', 'v', 'c', '1',
'm', 'p', '4', '1'}; 'm', 'p', '4', '1'};
retAtom = atomFromData (24, "ftyp", data); retAtom = atomFromData (24, "ftyp", data);
*offset = 48; *offset = 48;
} }
else if (ARDRONE_VIDEO_MOV == format) else if (ARDRONE_VIDEO_MOV == format)
{ {
uint8_t data [12] = {'q', 't', ' ', ' ', uint8_t data [12] = {'q', 't', ' ', ' ',
0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,
'q', 't', ' ', ' '}; 'q', 't', ' ', ' '};
retAtom = atomFromData (12, "ftyp", data); retAtom = atomFromData (12, "ftyp", data);
uint8_t wideData [4] = {0}; uint8_t wideData [4] = {0};
*wideAtom = atomFromData (4, "wide", wideData); *wideAtom = atomFromData (4, "wide", wideData);
*offset = 48; *offset = 48;
} }
return retAtom; return retAtom;
} }
movie_atom_t *mdatAtomForFormatWithVideoSize (ardrone_video_type_t format, uint64_t videoSize) movie_atom_t *mdatAtomForFormatWithVideoSize (ardrone_video_type_t format, uint64_t videoSize)
{ {
movie_atom_t *retAtom = NULL; movie_atom_t *retAtom = NULL;
if (videoSize <= INT32_MAX) if (videoSize <= INT32_MAX)
{ {
// Free/wide atom + mdat // Free/wide atom + mdat
uint8_t data [8] = {0x00, 0x00, 0x00, 0x00, uint8_t data [8] = {0x00, 0x00, 0x00, 0x00,
'm', 'd', 'a', 't'}; 'm', 'd', 'a', 't'};
uint32_t sizeNe = htonl ((uint32_t) videoSize); uint32_t sizeNe = htonl ((uint32_t) videoSize);
ATOM_MEMCOPY (data, &sizeNe, sizeof (uint32_t)); ATOM_MEMCOPY (data, &sizeNe, sizeof (uint32_t));
if (ARDRONE_VIDEO_MP4 == format) if (ARDRONE_VIDEO_MP4 == format)
{ {
retAtom = atomFromData (8, "free", data); retAtom = atomFromData (8, "free", data);
retAtom->size = 8; retAtom->size = 8;
retAtom->wide = 1; retAtom->wide = 1;
} }
else else
{ {
retAtom = atomFromData (8, "wide", data); retAtom = atomFromData (8, "wide", data);
retAtom->size = 8; retAtom->size = 8;
retAtom->wide = 1; retAtom->wide = 1;
} }
} }
else else
{ {
// 64bit wide mdat atom // 64bit wide mdat atom
uint8_t data [8] = {0}; uint8_t data [8] = {0};
uint32_t highSize = (videoSize >> 32); uint32_t highSize = (videoSize >> 32);
uint32_t lowSize = (videoSize & 0xffffffff); uint32_t lowSize = (videoSize & 0xffffffff);
uint32_t highSizeNe = htonl (highSize); uint32_t highSizeNe = htonl (highSize);
uint32_t lowSizeNe = htonl (lowSize); uint32_t lowSizeNe = htonl (lowSize);
ATOM_MEMCOPY (data, &highSizeNe, sizeof (uint32_t)); ATOM_MEMCOPY (data, &highSizeNe, sizeof (uint32_t));
ATOM_MEMCOPY (&data[4], &lowSizeNe, sizeof (uint32_t)); ATOM_MEMCOPY (&data[4], &lowSizeNe, sizeof (uint32_t));
retAtom = atomFromData (8, "mdat", data); retAtom = atomFromData (8, "mdat", data);
retAtom->size = 0; retAtom->size = 0;
retAtom->wide = 1; retAtom->wide = 1;
} }
return retAtom; return retAtom;
} }
movie_atom_t *mvhdAtomFromFpsNumFramesAndDate (uint32_t fps, uint32_t nbFrames, time_t date) movie_atom_t *mvhdAtomFromFpsNumFramesAndDate (uint32_t fps, uint32_t nbFrames, time_t date)
@@ -280,6 +297,7 @@ movie_atom_t *mvhdAtomFromFpsNumFramesAndDate (uint32_t fps, uint32_t nbFrames,
movie_atom_t *retAtom = atomFromData (100, "mvhd", data); movie_atom_t *retAtom = atomFromData (100, "mvhd", data);
ATOM_FREE (data); ATOM_FREE (data);
data = NULL;
return retAtom; return retAtom;
} }
@@ -321,6 +339,7 @@ movie_atom_t *tkhdAtomWithResolutionNumFramesFpsAndDate (uint32_t w, uint32_t h,
movie_atom_t *retAtom = atomFromData (84, "tkhd", data); movie_atom_t *retAtom = atomFromData (84, "tkhd", data);
ATOM_FREE (data); ATOM_FREE (data);
data = NULL;
return retAtom; return retAtom;
} }
@@ -343,278 +362,281 @@ movie_atom_t *mdhdAtomFromFpsNumFramesAndDate (uint32_t fps, uint32_t nbFrames,
movie_atom_t *retAtom = atomFromData (24, "mdhd", data); movie_atom_t *retAtom = atomFromData (24, "mdhd", data);
ATOM_FREE (data); ATOM_FREE (data);
data = NULL;
return retAtom; return retAtom;
} }
movie_atom_t *hdlrAtomForMdia () movie_atom_t *hdlrAtomForMdia ()
{ {
uint8_t data [37] = {0x00, 0x00, 0x00, 0x00, uint8_t data [37] = {0x00, 0x00, 0x00, 0x00,
'm', 'h', 'l', 'r', 'm', 'h', 'l', 'r',
'v', 'i', 'd', 'e', 'v', 'i', 'd', 'e',
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0c, 'V', 'i', 'd', 0x0c, 'V', 'i', 'd',
'e', 'o', 'H', 'a', 'e', 'o', 'H', 'a',
'n', 'd', 'l', 'e', 'n', 'd', 'l', 'e',
'r'}; 'r'};
return atomFromData (37, "hdlr", data); return atomFromData (37, "hdlr", data);
} }
movie_atom_t *vmhdAtomGen () movie_atom_t *vmhdAtomGen ()
{ {
uint8_t data [12] = {0x00, 0x00, 0x00, 0x01, uint8_t data [12] = {0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00}; 0x00, 0x00, 0x00, 0x00};
return atomFromData (12, "vmhd", data); return atomFromData (12, "vmhd", data);
} }
movie_atom_t *hdlrAtomForMinf () movie_atom_t *hdlrAtomForMinf ()
{ {
uint8_t data [36] = {0x00, 0x00, 0x00, 0x00, uint8_t data [36] = {0x00, 0x00, 0x00, 0x00,
'd', 'h', 'l', 'r', 'd', 'h', 'l', 'r',
'u', 'r', 'l', ' ', 'u', 'r', 'l', ' ',
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0b, 'D', 'a', 't', 0x0b, 'D', 'a', 't',
'a', 'H', 'a', 'n', 'a', 'H', 'a', 'n',
'd', 'l', 'e', 'r'}; 'd', 'l', 'e', 'r'};
return atomFromData (36, "hdlr", data); return atomFromData (36, "hdlr", data);
} }
movie_atom_t *drefAtomGen () movie_atom_t *drefAtomGen ()
{ {
uint8_t data [20] = {0x00, 0x00, 0x00, 0x00, uint8_t data [20] = {0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0C,
0x75, 0x72, 0x6c, 0x20, 0x75, 0x72, 0x6c, 0x20,
0x00, 0x00, 0x00, 0x01}; 0x00, 0x00, 0x00, 0x01};
return atomFromData (20, "dref", data); return atomFromData (20, "dref", data);
} }
movie_atom_t *stsdAtomWithResolutionAndCodec (uint32_t w, uint32_t h, parrot_video_encapsulation_codecs_t codec) movie_atom_t *stsdAtomWithResolutionAndCodec (uint32_t w, uint32_t h, parrot_video_encapsulation_codecs_t codec)
{ {
if (CODEC_MPEG4_AVC == codec) if (CODEC_MPEG4_AVC == codec)
{ {
uint8_t data [128] = {0x00, 0x00, 0x00, 0x00, uint8_t data [128] = {0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78,
'a', 'v', 'c', '1', // vse type 'a', 'v', 'c', '1', // vse type
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
'A', 'R', '.', 'D', // Muxer string 'A', 'R', '.', 'D', // Muxer string
0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,
0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00,// 40 -> width | 42 -> height 0x00, 0x00, 0x00, 0x00,// 40 -> width | 42 -> height
0x00, 0x48, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00,
0x00, 0x48, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18,
0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
0x00, 0x22, 0x61, 0x76, 0x00, 0x22, 0x61, 0x76,
0x63, 0x43, 0x01, 0x42, 0x63, 0x43, 0x01, 0x42,
0x80, 0x1e, 0xff, 0xe1, 0x80, 0x1e, 0xff, 0xe1,
0x00, 0x09, 0x67, 0x42, 0x00, 0x09, 0x67, 0x42,
0x80, 0x1e, 0x8b, 0x68, 0x80, 0x1e, 0x8b, 0x68,
0x0a, 0x02, 0xf1, 0x01, 0x0a, 0x02, 0xf1, 0x01,
0x00, 0x06, 0x68, 0xce, 0x00, 0x06, 0x68, 0xce,
0x01, 0xa8, 0x77, 0x20}; 0x01, 0xa8, 0x77, 0x20};
uint16_t neW = htons ((uint16_t) w); uint16_t neW = htons ((uint16_t) w);
uint16_t neH = htons ((uint16_t) h); uint16_t neH = htons ((uint16_t) h);
ATOM_MEMCOPY(&data[40], &neW, sizeof (uint16_t)); ATOM_MEMCOPY(&data[40], &neW, sizeof (uint16_t));
ATOM_MEMCOPY(&data[42], &neH, sizeof (uint16_t)); ATOM_MEMCOPY(&data[42], &neH, sizeof (uint16_t));
return atomFromData (128, "stsd", data); return atomFromData (128, "stsd", data);
} }
else if (CODEC_MPEG4_VISUAL == codec) else if (CODEC_MPEG4_VISUAL == codec)
{ {
uint8_t data [187] = {0x00, 0x00, 0x00, 0x00, uint8_t data [187] = {0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0xb3, 0x00, 0x00, 0x00, 0xb3,
'm', 'p', '4', 'v', // vse type 'm', 'p', '4', 'v', // vse type
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
'A', 'R', '.', 'D', // Muxer string 'A', 'R', '.', 'D', // Muxer string
0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,
0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00,// 40 -> width | 42 -> height 0x00, 0x00, 0x00, 0x00,// 40 -> width | 42 -> height
0x00, 0x48, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00,
0x00, 0x48, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x05, 'm', 0x00, 0x01, 0x05, 'm',
'p', 'e', 'g', '4', 'p', 'e', 'g', '4',
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18,
0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
0x00, 0x5d, 0x65, 0x73, 0x00, 0x5d, 0x65, 0x73,
0x64, 0x73, 0x00, 0x00, 0x64, 0x73, 0x00, 0x00,
0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80,
0x80, 0x80, 0x4c, 0x00, 0x80, 0x80, 0x4c, 0x00,
0x01, 0x00, 0x04, 0x80, 0x01, 0x00, 0x04, 0x80,
0x80, 0x80, 0x3e, 0x20, 0x80, 0x80, 0x3e, 0x20,
0x11, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
0x00, 0x07, 0xac, 0xda, 0x00, 0x07, 0xac, 0xda,
0x00, 0x07, 0xac, 0xda, 0x00, 0x07, 0xac, 0xda,
0x05, 0x80, 0x80, 0x80, 0x05, 0x80, 0x80, 0x80,
0x2c, 0x00, 0x00, 0x01, 0x2c, 0x00, 0x00, 0x01,
0xb0, 0x01, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00,
0x01, 0xb5, 0x89, 0x13, 0x01, 0xb5, 0x89, 0x13,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x01, 0x20,
0x00, 0xc4, 0x8d, 0x88, 0x00, 0xc4, 0x8d, 0x88,
0x00, 0xf5, 0x14, 0x04, 0x00, 0xf5, 0x14, 0x04,
0x2e, 0x14, 0x63, 0x00, 0x2e, 0x14, 0x63, 0x00,
0x00, 0x01, 0xb2, 'A', 0x00, 0x01, 0xb2, 'A',
'R', '.', 'D', 'r', 'R', '.', 'D', 'r',
'o', 'n', 'e', '_', 'o', 'n', 'e', '_',
'2', 0x06, 0x80, 0x80, '2', 0x06, 0x80, 0x80,
0x80, 0x01, 0x02}; 0x80, 0x01, 0x02};
uint16_t neW = htons ((uint16_t) w); uint16_t neW = htons ((uint16_t) w);
uint16_t neH = htons ((uint16_t) h); uint16_t neH = htons ((uint16_t) h);
ATOM_MEMCOPY(&data[40], &neW, sizeof (uint16_t)); ATOM_MEMCOPY(&data[40], &neW, sizeof (uint16_t));
ATOM_MEMCOPY(&data[42], &neH, sizeof (uint16_t)); ATOM_MEMCOPY(&data[42], &neH, sizeof (uint16_t));
return atomFromData (187, "stsd", data); return atomFromData (187, "stsd", data);
} }
else else
{ {
return atomFromData (0, "stsd", NULL); return atomFromData (0, "stsd", NULL);
} }
} }
movie_atom_t *stsdAtomWithResolutionCodecSpsAndPps (uint32_t w, uint32_t h, parrot_video_encapsulation_codecs_t codec, uint8_t *sps, uint32_t spsSize, uint8_t *pps, uint32_t ppsSize) movie_atom_t *stsdAtomWithResolutionCodecSpsAndPps (uint32_t w, uint32_t h, parrot_video_encapsulation_codecs_t codec, uint8_t *sps, uint32_t spsSize, uint8_t *pps, uint32_t ppsSize)
{ {
if (NULL == sps || NULL == pps || CODEC_MPEG4_AVC != codec) if (NULL == sps || NULL == pps || CODEC_MPEG4_AVC != codec)
{ {
return stsdAtomWithResolutionAndCodec (w, h, codec); return stsdAtomWithResolutionAndCodec (w, h, codec);
} }
uint32_t avcCSize = 19 + spsSize + ppsSize; uint32_t avcCSize = 19 + spsSize + ppsSize;
uint32_t vse_size = avcCSize + 86; uint32_t vse_size = avcCSize + 86;
uint32_t dataSize = vse_size + 8; uint32_t dataSize = vse_size + 8;
uint8_t *data = ATOM_MALLOC (dataSize); uint8_t *data = ATOM_MALLOC (dataSize);
if (NULL == data) if (NULL == data)
{ {
return NULL; return NULL;
} }
uint32_t currentIndex = 0; uint32_t currentIndex = 0;
ATOM_WRITE_U32 (0); /* version / flags */ ATOM_WRITE_U32 (0); /* version / flags */
ATOM_WRITE_U32 (1); /* entry count */ ATOM_WRITE_U32 (1); /* entry count */
ATOM_WRITE_U32 (vse_size); /* video sample entry size */ ATOM_WRITE_U32 (vse_size); /* video sample entry size */
ATOM_WRITE_4CC ('a', 'v', 'c', '1'); /* VSE type */ ATOM_WRITE_4CC ('a', 'v', 'c', '1'); /* VSE type */
ATOM_WRITE_U32 (0); /* Reserved */ ATOM_WRITE_U32 (0); /* Reserved */
ATOM_WRITE_U16 (0); /* Reserved */ ATOM_WRITE_U16 (0); /* Reserved */
ATOM_WRITE_U16 (1); /* Data reference index */ ATOM_WRITE_U16 (1); /* Data reference index */
ATOM_WRITE_U16 (0); /* Codec stream version */ ATOM_WRITE_U16 (0); /* Codec stream version */
ATOM_WRITE_U16 (0); /* Codec stream revision */ ATOM_WRITE_U16 (0); /* Codec stream revision */
ATOM_WRITE_4CC ('A', 'R', '.', 'D'); /* Muxer name */ ATOM_WRITE_4CC ('A', 'R', '.', 'D'); /* Muxer name */
ATOM_WRITE_U32 (0x200); /* Temporal quality */ ATOM_WRITE_U32 (0x200); /* Temporal quality */
ATOM_WRITE_U32 (0x200); /* Spatial quality */ ATOM_WRITE_U32 (0x200); /* Spatial quality */
ATOM_WRITE_U16 (w); /* Width */ ATOM_WRITE_U16 (w); /* Width */
ATOM_WRITE_U16 (h); /* Height */ ATOM_WRITE_U16 (h); /* Height */
ATOM_WRITE_U32 (0x00480000); /* Horiz DPI : 72dpi */ ATOM_WRITE_U32 (0x00480000); /* Horiz DPI : 72dpi */
ATOM_WRITE_U32 (0x00480000); /* Vert DPI : 72dpi */ ATOM_WRITE_U32 (0x00480000); /* Vert DPI : 72dpi */
ATOM_WRITE_U32 (0); /* Data size */ ATOM_WRITE_U32 (0); /* Data size */
ATOM_WRITE_U16 (1); /* Frame count */ ATOM_WRITE_U16 (1); /* Frame count */
ATOM_WRITE_U32 (0); /* Compressor name ... 32 octets of zeros */ ATOM_WRITE_U32 (0); /* Compressor name ... 32 octets of zeros */
ATOM_WRITE_U32 (0); /* Compressor name ... 32 octets of zeros */ ATOM_WRITE_U32 (0); /* Compressor name ... 32 octets of zeros */
ATOM_WRITE_U32 (0); /* Compressor name ... 32 octets of zeros */ ATOM_WRITE_U32 (0); /* Compressor name ... 32 octets of zeros */
ATOM_WRITE_U32 (0); /* Compressor name ... 32 octets of zeros */ ATOM_WRITE_U32 (0); /* Compressor name ... 32 octets of zeros */
ATOM_WRITE_U32 (0); /* Compressor name ... 32 octets of zeros */ ATOM_WRITE_U32 (0); /* Compressor name ... 32 octets of zeros */
ATOM_WRITE_U32 (0); /* Compressor name ... 32 octets of zeros */ ATOM_WRITE_U32 (0); /* Compressor name ... 32 octets of zeros */
ATOM_WRITE_U32 (0); /* Compressor name ... 32 octets of zeros */ ATOM_WRITE_U32 (0); /* Compressor name ... 32 octets of zeros */
ATOM_WRITE_U32 (0); /* Compressor name ... 32 octets of zeros */ ATOM_WRITE_U32 (0); /* Compressor name ... 32 octets of zeros */
ATOM_WRITE_U16 (0x18); /* Reserved */ ATOM_WRITE_U16 (0x18); /* Reserved */
ATOM_WRITE_U16 (0xffff); /* Reserved */ ATOM_WRITE_U16 (0xffff); /* Reserved */
/* avcC tag */ /* avcC tag */
ATOM_WRITE_U32 (avcCSize); /* Size */ ATOM_WRITE_U32 (avcCSize); /* Size */
ATOM_WRITE_4CC ('a', 'v', 'c', 'C'); /* avcC header */ ATOM_WRITE_4CC ('a', 'v', 'c', 'C'); /* avcC header */
ATOM_WRITE_U8 (1); /* version */ ATOM_WRITE_U8 (1); /* version */
ATOM_WRITE_U8 (sps[1]); /* profile */ ATOM_WRITE_U8 (sps[1]); /* profile */
ATOM_WRITE_U8 (sps[2]); /* profile compat */ ATOM_WRITE_U8 (sps[2]); /* profile compat */
ATOM_WRITE_U8 (sps[3]); /* level */ ATOM_WRITE_U8 (sps[3]); /* level */
ATOM_WRITE_U8 (0xff); /* Reserved (6bits) -- NAL size length - 1 (2bits) */ ATOM_WRITE_U8 (0xff); /* Reserved (6bits) -- NAL size length - 1 (2bits) */
ATOM_WRITE_U8 (0xe1); /* Reserved (3 bits) -- Number of SPS (5 bits) */ ATOM_WRITE_U8 (0xe1); /* Reserved (3 bits) -- Number of SPS (5 bits) */
ATOM_WRITE_U16 (spsSize); /* Size of SPS */ ATOM_WRITE_U16 (spsSize); /* Size of SPS */
ATOM_WRITE_BYTES (sps, spsSize); /* SPS header */ ATOM_WRITE_BYTES (sps, spsSize); /* SPS header */
ATOM_WRITE_U8 (1); /* Number of PPS */ ATOM_WRITE_U8 (1); /* Number of PPS */
ATOM_WRITE_U16 (ppsSize); /* Size of PPS */ ATOM_WRITE_U16 (ppsSize); /* Size of PPS */
ATOM_WRITE_BYTES (pps, ppsSize); /* PPS Header */ ATOM_WRITE_BYTES (pps, ppsSize); /* PPS Header */
movie_atom_t *retAtom = atomFromData (dataSize, "stsd", data); movie_atom_t *retAtom = atomFromData (dataSize, "stsd", data);
ATOM_FREE (data); ATOM_FREE (data);
return retAtom; data = NULL;
return retAtom;
} }
movie_atom_t *sttsAtomWithNumFrames (uint32_t nbFrames) movie_atom_t *sttsAtomWithNumFrames (uint32_t nbFrames)
{ {
uint8_t data [16] = {0x00, 0x00, 0x00, 0x00, uint8_t data [16] = {0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01}; 0x00, 0x00, 0x00, 0x01};
uint32_t networkEndianFrames = htonl (nbFrames); uint32_t networkEndianFrames = htonl (nbFrames);
ATOM_MEMCOPY( &data[8], &networkEndianFrames, sizeof (uint32_t)); ATOM_MEMCOPY( &data[8], &networkEndianFrames, sizeof (uint32_t));
return atomFromData (16, "stts", data); return atomFromData (16, "stts", data);
} }
movie_atom_t *stscAtomGen () movie_atom_t *stscAtomGen ()
{ {
uint8_t data [20] = {0x00, 0x00, 0x00, 0x00, uint8_t data [20] = {0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x01}; 0x00, 0x00, 0x00, 0x01};
return atomFromData (20, "stsc", data); return atomFromData (20, "stsc", data);
} }
movie_atom_t *metadataAtomFromTagAndValue (const char *tag, const char *value) movie_atom_t *metadataAtomFromTagAndValue (const char *tag, const char *value)
{ {
movie_atom_t *retAtom = NULL; movie_atom_t *retAtom = NULL;
char locTag [4] = {0}; char locTag [4] = {0};
/* If tag have a length of 3 chars, the (c) sign is added by this function */ /* If tag have a length of 3 chars, the (c) sign is added by this function */
if (3 == strlen (tag)) if (3 == strlen (tag))
{ {
locTag[0] = '\251'; // (c) sign locTag[0] = '\251'; // (c) sign
strncpy (&locTag[1], tag, 3); strncpy (&locTag[1], tag, 3);
} }
/* Custom tag */ /* Custom tag */
else if (4 == strlen (tag)) else if (4 == strlen (tag))
{ {
strncpy (locTag, tag, 4); strncpy (locTag, tag, 4);
} }
/* Continue only if we got a valid tag */ /* Continue only if we got a valid tag */
if (0 != locTag [0]) if (0 != locTag [0])
{ {
uint16_t valLen = (uint16_t) strlen (value); uint16_t valLen = (uint16_t) strlen (value);
uint16_t langCode = 0x55c4; /* 5-bit ascii for "und", undefined */ uint16_t langCode = 0x55c4; /* 5-bit ascii for "und", undefined */
uint32_t currentIndex = 0; uint32_t currentIndex = 0;
uint32_t dataSize = valLen + 4; uint32_t dataSize = valLen + 4;
uint8_t *data = ATOM_MALLOC (dataSize); uint8_t *data = ATOM_MALLOC (dataSize);
if (NULL != data) if (NULL != data)
{ {
ATOM_WRITE_U16 (valLen); /* Length of the value field */ ATOM_WRITE_U16 (valLen); /* Length of the value field */
ATOM_WRITE_U16 (langCode); /* Language code, set to "und" (undefined) */ ATOM_WRITE_U16 (langCode); /* Language code, set to "und" (undefined) */
ATOM_WRITE_BYTES (value, valLen); /* Actual value */ ATOM_WRITE_BYTES (value, valLen); /* Actual value */
retAtom = atomFromData (dataSize, locTag, data); retAtom = atomFromData (dataSize, locTag, data);
ATOM_FREE (data); ATOM_FREE (data);
data = NULL;
} }
} }
return retAtom; return retAtom;
} }
movie_atom_t *ardtAtomFromPathAndDroneVersion(const char *path, uint8_t droneVersion) movie_atom_t *ardtAtomFromPathAndDroneVersion(const char *path, uint8_t droneVersion)
@@ -627,14 +649,14 @@ movie_atom_t *ardtAtomFromPathAndDroneVersion(const char *path, uint8_t droneVer
{ {
pathLength = strlen(path); pathLength = strlen(path);
} }
uint32_t dataSize = pathLength + versionStringLen + 4; // 2 for version + 2 for string size without '\0' uint32_t dataSize = pathLength + versionStringLen + 4; // 2 for version + 2 for string size without '\0'
uint8_t *data = ATOM_MALLOC(dataSize); uint8_t *data = ATOM_MALLOC(dataSize);
if (NULL != data) if (NULL != data)
{ {
uint32_t currentIndex = 0; uint32_t currentIndex = 0;
ATOM_WRITE_U16 (0); /* Version */ ATOM_WRITE_U16 (0); /* Version */
ATOM_WRITE_U16 (pathLength + versionStringLen); /* length of string */ ATOM_WRITE_U16 (pathLength + versionStringLen); /* length of string */
ATOM_WRITE_U8 ('0' + ((droneVersion / 100) % 10)); /* Drone version number */ ATOM_WRITE_U8 ('0' + ((droneVersion / 100) % 10)); /* Drone version number */
@@ -647,8 +669,9 @@ movie_atom_t *ardtAtomFromPathAndDroneVersion(const char *path, uint8_t droneVer
} }
retAtom = atomFromData (dataSize, "ardt", data); retAtom = atomFromData (dataSize, "ardt", data);
ATOM_FREE (data); ATOM_FREE (data);
data = NULL;
} }
// NO ELSE - malloc failed // NO ELSE - malloc failed
return retAtom; return retAtom;
} }
@@ -61,6 +61,7 @@ ardt -> specific
movie_atom_t *atomFromData (uint32_t data_size, const char *_tag, const uint8_t *_data); movie_atom_t *atomFromData (uint32_t data_size, const char *_tag, const uint8_t *_data);
void insertAtomIntoAtom (movie_atom_t *container, movie_atom_t **leaf); // will free leaf void insertAtomIntoAtom (movie_atom_t *container, movie_atom_t **leaf); // will free leaf
int writeAtomToFile (movie_atom_t **_atom, FILE *file); // Will free _atom int writeAtomToFile (movie_atom_t **_atom, FILE *file); // Will free _atom
void freeAtom (movie_atom_t **_atom);
/* SPECIFIC */ /* SPECIFIC */
movie_atom_t *ftypAtomForFormatAndCodecWithOffset (ardrone_video_type_t format, parrot_video_encapsulation_codecs_t codec, uint32_t *offset, movie_atom_t **freeAtom); movie_atom_t *ftypAtomForFormatAndCodecWithOffset (ardrone_video_type_t format, parrot_video_encapsulation_codecs_t codec, uint32_t *offset, movie_atom_t **freeAtom);
@@ -28,10 +28,15 @@
#include <Winsock2.h> #include <Winsock2.h>
#else #else
#include <arpa/inet.h> #include <arpa/inet.h>
#ifndef USE_ANDROID
#include <ftw.h> // For file cleanup in subdirs #include <ftw.h> // For file cleanup in subdirs
#else
#include <utils/AR_Ftw.h>
#endif
#endif #endif
#define ENCAPSULER_SMALL_STRING_SIZE (30) #define ENCAPSULER_SMALL_STRING_SIZE (30)
#define ENCAPSULER_INFODATA_MAX_SIZE (256)
/* The structure is initialised to an invalid value /* The structure is initialised to an invalid value
so we won't set any position in videos unless we got a so we won't set any position in videos unless we got a
@@ -141,6 +146,7 @@ ardrone_video_t *ardrone_video_start (const char *videoPath, int fps, ardrone_vi
*error = ARDRONE_VIDEO_GENERIC_ERROR; *error = ARDRONE_VIDEO_GENERIC_ERROR;
vp_os_mutex_unlock(&retVideo->mutex); vp_os_mutex_unlock(&retVideo->mutex);
vp_os_free (retVideo); vp_os_free (retVideo);
retVideo = NULL;
return NULL; return NULL;
} }
@@ -160,6 +166,7 @@ ardrone_video_t *ardrone_video_start (const char *videoPath, int fps, ardrone_vi
fclose (retVideo->infoFile); fclose (retVideo->infoFile);
vp_os_mutex_unlock(&retVideo->mutex); vp_os_mutex_unlock(&retVideo->mutex);
vp_os_free (retVideo); vp_os_free (retVideo);
retVideo = NULL;
return NULL; return NULL;
} }
retVideo->framesCount = 0; retVideo->framesCount = 0;
@@ -270,8 +277,16 @@ ardrone_video_error_t ardrone_video_addFrame (ardrone_video_t *video, uint8_t *f
if (NULL == video->sps || NULL == video->pps) if (NULL == video->sps || NULL == video->pps)
{ {
ENCAPSULER_ERROR ("Unable to allocate SPS/PPS buffers"); ENCAPSULER_ERROR ("Unable to allocate SPS/PPS buffers");
if (NULL != video->sps) vp_os_free (video->sps); if (NULL != video->sps)
if (NULL != video->pps) vp_os_free (video->pps); {
vp_os_free (video->sps);
video->sps = NULL;
}
if (NULL != video->pps)
{
vp_os_free (video->pps);
video->pps = NULL;
}
vp_os_mutex_unlock(&video->mutex); vp_os_mutex_unlock(&video->mutex);
return ARDRONE_VIDEO_GENERIC_ERROR; return ARDRONE_VIDEO_GENERIC_ERROR;
} }
@@ -290,6 +305,7 @@ ardrone_video_error_t ardrone_video_addFrame (ardrone_video_t *video, uint8_t *f
if (NULL != freeAtomIfNeeded) if (NULL != freeAtomIfNeeded)
{ {
vp_os_free (freeAtomIfNeeded); vp_os_free (freeAtomIfNeeded);
freeAtomIfNeeded = NULL;
} }
return ARDRONE_VIDEO_GENERIC_ERROR; return ARDRONE_VIDEO_GENERIC_ERROR;
} }
@@ -300,6 +316,7 @@ ardrone_video_error_t ardrone_video_addFrame (ardrone_video_t *video, uint8_t *f
if (NULL != freeAtomIfNeeded) if (NULL != freeAtomIfNeeded)
{ {
vp_os_free (freeAtomIfNeeded); vp_os_free (freeAtomIfNeeded);
freeAtomIfNeeded = NULL;
} }
return ARDRONE_VIDEO_FILE_ERROR; return ARDRONE_VIDEO_FILE_ERROR;
} }
@@ -356,7 +373,7 @@ ardrone_video_error_t ardrone_video_addFrame (ardrone_video_t *video, uint8_t *f
} }
} }
// Normal operation : file pointer is at end of file // Normal operation : file pointer is at end of file
if (video->videoCodec != PaVE->video_codec || if (video->videoCodec != PaVE->video_codec ||
video->width != PaVE->display_width || video->width != PaVE->display_width ||
video->height != PaVE->display_height) video->height != PaVE->display_height)
@@ -386,7 +403,7 @@ ardrone_video_error_t ardrone_video_addFrame (ardrone_video_t *video, uint8_t *f
return ARDRONE_VIDEO_GENERIC_ERROR; return ARDRONE_VIDEO_GENERIC_ERROR;
} }
vp_os_memcpy (myData, data, frameSize); vp_os_memcpy (myData, data, frameSize);
// Modify frames before writing // Modify frames before writing
if (FRAME_TYPE_I_FRAME != PaVE->frame_type && if (FRAME_TYPE_I_FRAME != PaVE->frame_type &&
FRAME_TYPE_IDR_FRAME != PaVE->frame_type) FRAME_TYPE_IDR_FRAME != PaVE->frame_type)
{ {
@@ -418,6 +435,7 @@ ardrone_video_error_t ardrone_video_addFrame (ardrone_video_t *video, uint8_t *f
if (frameSize != fwrite (myData, 1, frameSize, video->outFile)) if (frameSize != fwrite (myData, 1, frameSize, video->outFile))
{ {
vp_os_free (myData); vp_os_free (myData);
myData = NULL;
ENCAPSULER_ERROR ("Unable to write frame into data file"); ENCAPSULER_ERROR ("Unable to write frame into data file");
vp_os_mutex_unlock(&video->mutex); vp_os_mutex_unlock(&video->mutex);
return ARDRONE_VIDEO_FILE_ERROR; return ARDRONE_VIDEO_FILE_ERROR;
@@ -427,15 +445,16 @@ ardrone_video_error_t ardrone_video_addFrame (ardrone_video_t *video, uint8_t *f
ENCAPSULER_FFLUSH (video->outFile); ENCAPSULER_FFLUSH (video->outFile);
} }
vp_os_free (myData); vp_os_free (myData);
myData = NULL;
char infoData [50] = {0}; char infoData [ENCAPSULER_INFODATA_MAX_SIZE] = {0};
char fTypeChar = 'p'; char fTypeChar = 'p';
if (FRAME_TYPE_I_FRAME == PaVE->frame_type || if (FRAME_TYPE_I_FRAME == PaVE->frame_type ||
FRAME_TYPE_IDR_FRAME == PaVE->frame_type) FRAME_TYPE_IDR_FRAME == PaVE->frame_type)
{ {
fTypeChar = 'i'; fTypeChar = 'i';
} }
snprintf (infoData, 50, ARDRONE_VIDEO_INFO_PATTERN, frameSize, fTypeChar); snprintf (infoData, ENCAPSULER_INFODATA_MAX_SIZE, ARDRONE_VIDEO_INFO_PATTERN, frameSize, fTypeChar);
uint32_t infoLen = strlen (infoData); uint32_t infoLen = strlen (infoData);
if (infoLen != fwrite (infoData, 1, infoLen, video->infoFile)) if (infoLen != fwrite (infoData, 1, infoLen, video->infoFile))
{ {
@@ -552,8 +571,17 @@ ardrone_video_error_t ardrone_video_addSlice (ardrone_video_t *video, uint8_t *s
if (NULL == video->sps || NULL == video->pps) if (NULL == video->sps || NULL == video->pps)
{ {
ENCAPSULER_ERROR ("Unable to allocate SPS/PPS buffers"); ENCAPSULER_ERROR ("Unable to allocate SPS/PPS buffers");
if (NULL != video->sps) vp_os_free (video->sps); if (NULL != video->sps)
if (NULL != video->pps) vp_os_free (video->pps); {
vp_os_free (video->sps);
video->sps = NULL;
}
if (NULL != video->pps)
{
vp_os_free (video->pps);
video->pps = NULL;
}
vp_os_mutex_unlock(&video->mutex); vp_os_mutex_unlock(&video->mutex);
return ARDRONE_VIDEO_GENERIC_ERROR; return ARDRONE_VIDEO_GENERIC_ERROR;
} }
@@ -572,6 +600,7 @@ ardrone_video_error_t ardrone_video_addSlice (ardrone_video_t *video, uint8_t *s
if (NULL != freeAtomIfNeeded) if (NULL != freeAtomIfNeeded)
{ {
vp_os_free (freeAtomIfNeeded); vp_os_free (freeAtomIfNeeded);
freeAtomIfNeeded = NULL;
} }
return ARDRONE_VIDEO_GENERIC_ERROR; return ARDRONE_VIDEO_GENERIC_ERROR;
} }
@@ -582,6 +611,7 @@ ardrone_video_error_t ardrone_video_addSlice (ardrone_video_t *video, uint8_t *s
if (NULL != freeAtomIfNeeded) if (NULL != freeAtomIfNeeded)
{ {
vp_os_free (freeAtomIfNeeded); vp_os_free (freeAtomIfNeeded);
freeAtomIfNeeded = NULL;
} }
return ARDRONE_VIDEO_FILE_ERROR; return ARDRONE_VIDEO_FILE_ERROR;
} }
@@ -655,14 +685,14 @@ ardrone_video_error_t ardrone_video_addSlice (ardrone_video_t *video, uint8_t *s
{ {
if (FRAME_TYPE_UNKNNOWN != video->lastFrameType) if (FRAME_TYPE_UNKNNOWN != video->lastFrameType)
{ {
char infoData [50] = {0}; char infoData [ENCAPSULER_INFODATA_MAX_SIZE] = {0};
char fTypeChar = 'p'; char fTypeChar = 'p';
if (FRAME_TYPE_I_FRAME == video->lastFrameType || if (FRAME_TYPE_I_FRAME == video->lastFrameType ||
FRAME_TYPE_IDR_FRAME == video->lastFrameType) FRAME_TYPE_IDR_FRAME == video->lastFrameType)
{ {
fTypeChar = 'i'; fTypeChar = 'i';
} }
snprintf (infoData, 50, ARDRONE_VIDEO_INFO_PATTERN, video->currentFrameSize, fTypeChar); snprintf (infoData, ENCAPSULER_INFODATA_MAX_SIZE, ARDRONE_VIDEO_INFO_PATTERN, video->currentFrameSize, fTypeChar);
uint32_t infoLen = strlen (infoData); uint32_t infoLen = strlen (infoData);
if (infoLen != fwrite (infoData, 1, infoLen, video->infoFile)) if (infoLen != fwrite (infoData, 1, infoLen, video->infoFile))
{ {
@@ -788,6 +818,7 @@ ardrone_video_error_t ardrone_video_finish (ardrone_video_t **video)
if (0 == myVideo->width) if (0 == myVideo->width)
{ {
// Video was not initialized // Video was not initialized
ENCAPSULER_ERROR ("video was not initialized");
localError = ARDRONE_VIDEO_BAD_ARGS; localError = ARDRONE_VIDEO_BAD_ARGS;
} // No else } // No else
} }
@@ -799,14 +830,14 @@ ardrone_video_error_t ardrone_video_finish (ardrone_video_t **video)
{ {
if (FRAME_TYPE_UNKNNOWN != myVideo->lastFrameType) if (FRAME_TYPE_UNKNNOWN != myVideo->lastFrameType)
{ {
char infoData [50] = {0}; char infoData [ENCAPSULER_INFODATA_MAX_SIZE] = {0};
char fTypeChar = 'p'; char fTypeChar = 'p';
if (FRAME_TYPE_I_FRAME == myVideo->lastFrameType || if (FRAME_TYPE_I_FRAME == myVideo->lastFrameType ||
FRAME_TYPE_IDR_FRAME == myVideo->lastFrameType) FRAME_TYPE_IDR_FRAME == myVideo->lastFrameType)
{ {
fTypeChar = 'i'; fTypeChar = 'i';
} }
snprintf (infoData, 50, ARDRONE_VIDEO_INFO_PATTERN, myVideo->currentFrameSize, fTypeChar); snprintf (infoData, ENCAPSULER_INFODATA_MAX_SIZE, ARDRONE_VIDEO_INFO_PATTERN, myVideo->currentFrameSize, fTypeChar);
uint32_t infoLen = strlen (infoData); uint32_t infoLen = strlen (infoData);
if (infoLen != fwrite (infoData, 1, infoLen, myVideo->infoFile)) if (infoLen != fwrite (infoData, 1, infoLen, myVideo->infoFile))
@@ -847,10 +878,15 @@ ardrone_video_error_t ardrone_video_finish (ardrone_video_t **video)
{ {
ENCAPSULER_ERROR ("Unable to allocate buffers for video finish"); ENCAPSULER_ERROR ("Unable to allocate buffers for video finish");
vp_os_free (frameSizeBuffer); vp_os_free (frameSizeBuffer);
frameSizeBuffer = NULL;
vp_os_free (frameSizeBufferNE); vp_os_free (frameSizeBufferNE);
frameSizeBufferNE = NULL;
vp_os_free (frameOffsetBuffer); vp_os_free (frameOffsetBuffer);
frameOffsetBuffer = NULL;
vp_os_free (iFrameIndexBuffer); vp_os_free (iFrameIndexBuffer);
iFrameIndexBuffer = NULL;
vp_os_free (frameIsIFrame); vp_os_free (frameIsIFrame);
frameIsIFrame = NULL;
vp_os_mutex_unlock(&myVideo->mutex); vp_os_mutex_unlock(&myVideo->mutex);
localError = ARDRONE_VIDEO_GENERIC_ERROR; localError = ARDRONE_VIDEO_GENERIC_ERROR;
} }
@@ -877,7 +913,7 @@ ardrone_video_error_t ardrone_video_finish (ardrone_video_t **video)
{ {
fseek (myVideo->infoFile, descriptorSize, SEEK_CUR); fseek (myVideo->infoFile, descriptorSize, SEEK_CUR);
} }
while (! feof (myVideo->infoFile) && nbFrames <= myVideo->framesCount) while (! feof (myVideo->infoFile) && nbFrames < myVideo->framesCount)
{ {
uint32_t fSize = -1; uint32_t fSize = -1;
char fType = 'a'; char fType = 'a';
@@ -901,12 +937,13 @@ ardrone_video_error_t ardrone_video_finish (ardrone_video_t **video)
// create atoms // create atoms
// Generating Atoms // Generating Atoms
tzset (); tzset ();
struct tm *nowTm = localtime (&myVideo->creationTime);
EMPTY_ATOM(moov); EMPTY_ATOM(moov);
movie_atom_t *mvhdAtom = mvhdAtomFromFpsNumFramesAndDate (myVideo->fps, nbFrames, myVideo->creationTime - timezone); movie_atom_t *mvhdAtom = mvhdAtomFromFpsNumFramesAndDate (myVideo->fps, nbFrames, myVideo->creationTime - timezone + (3600 * nowTm->tm_isdst));
EMPTY_ATOM(trak); EMPTY_ATOM(trak);
movie_atom_t *tkhdAtom = tkhdAtomWithResolutionNumFramesFpsAndDate (myVideo->width, myVideo->height, nbFrames, myVideo->fps, myVideo->creationTime - timezone); movie_atom_t *tkhdAtom = tkhdAtomWithResolutionNumFramesFpsAndDate (myVideo->width, myVideo->height, nbFrames, myVideo->fps, myVideo->creationTime - timezone + (3600 * nowTm->tm_isdst));
EMPTY_ATOM(mdia); EMPTY_ATOM(mdia);
movie_atom_t *mdhdAtom = mdhdAtomFromFpsNumFramesAndDate (myVideo->fps, nbFrames, myVideo->creationTime - timezone); movie_atom_t *mdhdAtom = mdhdAtomFromFpsNumFramesAndDate (myVideo->fps, nbFrames, myVideo->creationTime - timezone + (3600 * nowTm->tm_isdst));
movie_atom_t *hdlrAtom = hdlrAtomForMdia (); movie_atom_t *hdlrAtom = hdlrAtomForMdia ();
EMPTY_ATOM(minf); EMPTY_ATOM(minf);
movie_atom_t *vmhdAtom = vmhdAtomGen (); movie_atom_t *vmhdAtom = vmhdAtomGen ();
@@ -925,6 +962,7 @@ ardrone_video_error_t ardrone_video_finish (ardrone_video_t **video)
memcpy (&stssBuffer[8], iFrameIndexBuffer, nbIFrames * sizeof (uint32_t)); memcpy (&stssBuffer[8], iFrameIndexBuffer, nbIFrames * sizeof (uint32_t));
movie_atom_t *stssAtom = atomFromData (stssDataLen, "stss", stssBuffer); movie_atom_t *stssAtom = atomFromData (stssDataLen, "stss", stssBuffer);
vp_os_free (stssBuffer); vp_os_free (stssBuffer);
stssBuffer = NULL;
movie_atom_t *stscAtom = stscAtomGen (); movie_atom_t *stscAtom = stscAtomGen ();
@@ -936,6 +974,7 @@ ardrone_video_error_t ardrone_video_finish (ardrone_video_t **video)
memcpy (&stszBuffer[12], frameSizeBufferNE, nbFrames * sizeof (uint32_t)); memcpy (&stszBuffer[12], frameSizeBufferNE, nbFrames * sizeof (uint32_t));
movie_atom_t *stszAtom = atomFromData (stszDataLen, "stsz", stszBuffer); movie_atom_t *stszAtom = atomFromData (stszDataLen, "stsz", stszBuffer);
vp_os_free (stszBuffer); vp_os_free (stszBuffer);
stszBuffer = NULL;
// Generate stco atom from frameOffsetBuffer and nbFrames // Generate stco atom from frameOffsetBuffer and nbFrames
uint32_t stcoDataLen = (8 + (nbFrames * sizeof (uint32_t))); uint32_t stcoDataLen = (8 + (nbFrames * sizeof (uint32_t)));
@@ -944,12 +983,12 @@ ardrone_video_error_t ardrone_video_finish (ardrone_video_t **video)
memcpy (&stcoBuffer[8], frameOffsetBuffer, nbFrames * sizeof (uint32_t)); memcpy (&stcoBuffer[8], frameOffsetBuffer, nbFrames * sizeof (uint32_t));
movie_atom_t *stcoAtom = atomFromData (stcoDataLen, "stco", stcoBuffer); movie_atom_t *stcoAtom = atomFromData (stcoDataLen, "stco", stcoBuffer);
vp_os_free (stcoBuffer); vp_os_free (stcoBuffer);
stcoBuffer = NULL;
EMPTY_ATOM (udta); EMPTY_ATOM (udta);
movie_atom_t *swrAtom = metadataAtomFromTagAndValue ("swr", "AR.Drone 2.0"); movie_atom_t *swrAtom = metadataAtomFromTagAndValue ("swr", "AR.Drone 2.0");
char dateInfoString[ENCAPSULER_SMALL_STRING_SIZE] = {0}; char dateInfoString[ENCAPSULER_SMALL_STRING_SIZE] = {0};
struct tm *nowTm = localtime (&myVideo->creationTime);
snprintf (dateInfoString, ENCAPSULER_SMALL_STRING_SIZE, "%04d-%02d-%02dT%02d:%02d:%02d%+03d%02d", snprintf (dateInfoString, ENCAPSULER_SMALL_STRING_SIZE, "%04d-%02d-%02dT%02d:%02d:%02d%+03d%02d",
nowTm->tm_year + 1900, nowTm->tm_year + 1900,
nowTm->tm_mon + 1, nowTm->tm_mon + 1,
@@ -957,7 +996,7 @@ ardrone_video_error_t ardrone_video_finish (ardrone_video_t **video)
nowTm->tm_hour, nowTm->tm_hour,
nowTm->tm_min, nowTm->tm_min,
nowTm->tm_sec, nowTm->tm_sec,
(int)(-timezone / 3600), (int)(-timezone / 3600) + nowTm->tm_isdst,
(int)((-timezone % 3600) / 60)); (int)((-timezone % 3600) / 60));
movie_atom_t *dayAtom = metadataAtomFromTagAndValue ("day", dateInfoString); movie_atom_t *dayAtom = metadataAtomFromTagAndValue ("day", dateInfoString);
@@ -965,10 +1004,17 @@ ardrone_video_error_t ardrone_video_finish (ardrone_video_t **video)
int gpsIsValid = generateGpsString (gpsInfoString, ENCAPSULER_SMALL_STRING_SIZE); int gpsIsValid = generateGpsString (gpsInfoString, ENCAPSULER_SMALL_STRING_SIZE);
ENCAPSULER_DEBUG ("Valid : %d, Gps info string : %s\n", gpsIsValid, gpsInfoString); ENCAPSULER_DEBUG ("Valid : %d, Gps info string : %s\n", gpsIsValid, gpsInfoString);
movie_atom_t *xyzAtom = NULL; movie_atom_t *xyzAtom = NULL;
/**
* Android 4.0.3 and later don't support the (c)xyz atom in the videos
* We won't generate it for any android versions
*/
#ifndef USE_ANDROID
if (1 == gpsIsValid) if (1 == gpsIsValid)
{ {
xyzAtom = metadataAtomFromTagAndValue ("xyz", gpsInfoString); xyzAtom = metadataAtomFromTagAndValue ("xyz", gpsInfoString);
} }
#endif
// Create atom tree // Create atom tree
insertAtomIntoAtom (udtaAtom, &swrAtom); insertAtomIntoAtom (udtaAtom, &swrAtom);
@@ -1043,6 +1089,7 @@ ardrone_video_error_t ardrone_video_finish (ardrone_video_t **video)
localError = ARDRONE_VIDEO_FILE_ERROR; localError = ARDRONE_VIDEO_FILE_ERROR;
} }
vp_os_free (mediaPath); vp_os_free (mediaPath);
mediaPath = NULL;
} }
else else
{ {
@@ -1084,21 +1131,32 @@ ardrone_video_error_t ardrone_video_finish (ardrone_video_t **video)
vp_os_mutex_unlock(&myVideo->mutex); vp_os_mutex_unlock(&myVideo->mutex);
vp_os_free (myVideo); vp_os_free (myVideo);
myVideo = NULL;
*video = NULL; *video = NULL;
vp_os_free (frameSizeBuffer); vp_os_free (frameSizeBuffer);
frameSizeBuffer = NULL;
vp_os_free (frameSizeBufferNE); vp_os_free (frameSizeBufferNE);
frameSizeBufferNE = NULL;
vp_os_free (frameOffsetBuffer); vp_os_free (frameOffsetBuffer);
frameOffsetBuffer = NULL;
vp_os_free (iFrameIndexBuffer); vp_os_free (iFrameIndexBuffer);
iFrameIndexBuffer = NULL;
vp_os_free (frameIsIFrame); vp_os_free (frameIsIFrame);
frameIsIFrame = NULL;
} }
else else
{ {
vp_os_free (frameSizeBuffer); vp_os_free (frameSizeBuffer);
frameSizeBuffer = NULL;
vp_os_free (frameSizeBufferNE); vp_os_free (frameSizeBufferNE);
frameSizeBufferNE = NULL;
vp_os_free (frameOffsetBuffer); vp_os_free (frameOffsetBuffer);
frameOffsetBuffer = NULL;
vp_os_free (iFrameIndexBuffer); vp_os_free (iFrameIndexBuffer);
iFrameIndexBuffer = NULL;
vp_os_free (frameIsIFrame); vp_os_free (frameIsIFrame);
frameIsIFrame = NULL;
vp_os_mutex_unlock(&myVideo->mutex); vp_os_mutex_unlock(&myVideo->mutex);
ardrone_video_cleanup (video); ardrone_video_cleanup (video);
} }
@@ -1494,10 +1552,13 @@ bool_t ardrone_video_try_fix (const char *infoFilePath)
{ {
ENCAPSULER_DEBUG ("Freeing local copies"); ENCAPSULER_DEBUG ("Freeing local copies");
ENCAPSULER_CLEANUP (vp_os_free, video->sps); ENCAPSULER_CLEANUP (vp_os_free, video->sps);
video->sps = NULL;
ENCAPSULER_CLEANUP (vp_os_free, video->pps); ENCAPSULER_CLEANUP (vp_os_free, video->pps);
video->pps = NULL;
ENCAPSULER_CLEANUP (fclose, video->infoFile); ENCAPSULER_CLEANUP (fclose, video->infoFile);
ENCAPSULER_CLEANUP (fclose, video->outFile); ENCAPSULER_CLEANUP (fclose, video->outFile);
ENCAPSULER_CLEANUP (vp_os_free ,video); ENCAPSULER_CLEANUP (vp_os_free ,video);
video = NULL;
} }
if (NULL != infoFile) if (NULL != infoFile)
@@ -30,12 +30,12 @@
#define ARDRONE_VIDEO_NUM_MATCH_PATTERN (2) #define ARDRONE_VIDEO_NUM_MATCH_PATTERN (2)
typedef enum { typedef enum {
ARDRONE_VIDEO_NO_ERROR = 0, ARDRONE_VIDEO_NO_ERROR = 0,
ARDRONE_VIDEO_GENERIC_ERROR, ARDRONE_VIDEO_GENERIC_ERROR,
ARDRONE_VIDEO_BAD_CODEC, ARDRONE_VIDEO_BAD_CODEC,
ARDRONE_VIDEO_FILE_ERROR, ARDRONE_VIDEO_FILE_ERROR,
ARDRONE_VIDEO_WAITING_FOR_IFRAME, ARDRONE_VIDEO_WAITING_FOR_IFRAME,
ARDRONE_VIDEO_BAD_ARGS, ARDRONE_VIDEO_BAD_ARGS,
} ardrone_video_error_t; } ardrone_video_error_t;
#if COUNT_WAITING_FOR_IFRAME_AS_AN_ERROR #if COUNT_WAITING_FOR_IFRAME_AS_AN_ERROR
@@ -44,62 +44,62 @@ typedef enum {
#else #else
static inline int ARDRONE_VIDEO_FAILED (ardrone_video_error_t error) static inline int ARDRONE_VIDEO_FAILED (ardrone_video_error_t error)
{ {
if (ARDRONE_VIDEO_NO_ERROR == error || if (ARDRONE_VIDEO_NO_ERROR == error ||
ARDRONE_VIDEO_WAITING_FOR_IFRAME == error) ARDRONE_VIDEO_WAITING_FOR_IFRAME == error)
{ {
return 0; return 0;
} }
return 1; return 1;
} }
static inline int ARDRONE_VIDEO_SUCCEEDED (ardrone_video_error_t error) static inline int ARDRONE_VIDEO_SUCCEEDED (ardrone_video_error_t error)
{ {
if (ARDRONE_VIDEO_NO_ERROR == error || if (ARDRONE_VIDEO_NO_ERROR == error ||
ARDRONE_VIDEO_WAITING_FOR_IFRAME == error) ARDRONE_VIDEO_WAITING_FOR_IFRAME == error)
{ {
return 1; return 1;
} }
return 0; return 0;
} }
#endif // COUNT_WAITING_FOR_IFRAME_AS_AN_ERROR #endif // COUNT_WAITING_FOR_IFRAME_AS_AN_ERROR
typedef enum { typedef enum {
ARDRONE_VIDEO_MOV = 0, ARDRONE_VIDEO_MOV = 0,
ARDRONE_VIDEO_QUICKTIME = ARDRONE_VIDEO_MOV, // Alias for mov file ARDRONE_VIDEO_QUICKTIME = ARDRONE_VIDEO_MOV, // Alias for mov file
ARDRONE_VIDEO_MP4, ARDRONE_VIDEO_MP4,
} ardrone_video_type_t; } ardrone_video_type_t;
typedef struct _ardrone_video_t { typedef struct _ardrone_video_t {
uint32_t version; uint32_t version;
// Provided to constructor // Provided to constructor
uint32_t fps; uint32_t fps;
ardrone_video_type_t videoType; ardrone_video_type_t videoType;
// Read from frames PaVE // Read from frames PaVE
parrot_video_encapsulation_codecs_t videoCodec; parrot_video_encapsulation_codecs_t videoCodec;
uint16_t width; uint16_t width;
uint16_t height; uint16_t height;
// Private datas // Private datas
char infoFilePath [ARDRONE_VIDEO_PATH_MAX_SIZE]; // Keep this so we can delete the file char infoFilePath [ARDRONE_VIDEO_PATH_MAX_SIZE]; // Keep this so we can delete the file
char outFilePath [ARDRONE_VIDEO_PATH_MAX_SIZE]; // Keep this so we can rename the output file char outFilePath [ARDRONE_VIDEO_PATH_MAX_SIZE]; // Keep this so we can rename the output file
char tempFilePath [ARDRONE_VIDEO_PATH_MAX_SIZE]; // Keep this so we can rename the output file char tempFilePath [ARDRONE_VIDEO_PATH_MAX_SIZE]; // Keep this so we can rename the output file
FILE *infoFile; FILE *infoFile;
FILE *outFile; FILE *outFile;
uint32_t framesCount; // Number of frames uint32_t framesCount; // Number of frames
uint32_t mdatAtomOffset; uint32_t mdatAtomOffset;
uint32_t framesDataOffset; uint32_t framesDataOffset;
/* H.264 only values */ /* H.264 only values */
uint8_t *sps; uint8_t *sps;
uint8_t *pps; uint8_t *pps;
uint16_t spsSize; uint16_t spsSize;
uint16_t ppsSize; uint16_t ppsSize;
/* Slices recording values */ /* Slices recording values */
uint32_t lastFrameNumber; uint32_t lastFrameNumber;
parrot_video_encapsulation_frametypes_t lastFrameType; parrot_video_encapsulation_frametypes_t lastFrameType;
uint32_t currentFrameSize; uint32_t currentFrameSize;
vp_os_mutex_t mutex; vp_os_mutex_t mutex;
time_t creationTime; time_t creationTime;
uint32_t droneVersion; uint32_t droneVersion;
} ardrone_video_t; } ardrone_video_t;
@@ -187,6 +187,7 @@ void ardrone_video_set_gps_infos (double latitude, double longitude, double alti
/** /**
* Try fo fix an MP4 infovid file. * Try fo fix an MP4 infovid file.
* @param infoFilePath Full path to the .infovid file. * @param infoFilePath Full path to the .infovid file.
* @return TRUE on success, FALSE on failure
*/ */
bool_t ardrone_video_try_fix (const char *infoFilePath); bool_t ardrone_video_try_fix (const char *infoFilePath);
+2
Ver Arquivo
@@ -57,6 +57,8 @@ void p263_codec_free( video_controller_t* controller )
p263_codec_t* p263_codec = (p263_codec_t*) controller->video_codec; p263_codec_t* p263_codec = (p263_codec_t*) controller->video_codec;
vp_os_free( p263_codec ); vp_os_free( p263_codec );
controller->video_codec = NULL;
} }
static INLINE video_macroblock_t* p263_unquantize_idct( video_controller_t* controller, video_macroblock_t* mb, int32_t num_macro_blocks ) static INLINE video_macroblock_t* p263_unquantize_idct( video_controller_t* controller, video_macroblock_t* mb, int32_t num_macro_blocks )
+17 -10
Ver Arquivo
@@ -94,9 +94,16 @@ void p264_codec_free( video_controller_t* controller )
if( p264_codec != NULL ) if( p264_codec != NULL )
{ {
if (p264_codec->ref_picture.y_buf != NULL) if (p264_codec->ref_picture.y_buf != NULL)
{
vp_os_free(p264_codec->ref_picture.y_buf); vp_os_free(p264_codec->ref_picture.y_buf);
p264_codec->ref_picture.y_buf = NULL;
}
if (p264_codec->decoded_picture.y_buf != NULL) if (p264_codec->decoded_picture.y_buf != NULL)
{
vp_os_free(p264_codec->decoded_picture.y_buf); vp_os_free(p264_codec->decoded_picture.y_buf);
p264_codec->decoded_picture.y_buf = NULL;
}
vp_os_free( p264_codec ); vp_os_free( p264_codec );
controller->video_codec = NULL; controller->video_codec = NULL;
} }
@@ -300,17 +307,17 @@ C_RESULT p264_unpack_controller( video_controller_t* controller )
// new picture // new picture
p264_read_picture_layer( controller, stream ); p264_read_picture_layer( controller, stream );
if (((controller->num_frames == (last_frame_decoded + 1)) && (controller->last_frame_decoded == TRUE)) if (((controller->num_frames == (last_frame_decoded + 1)) && (controller->last_frame_decoded == TRUE))
|| (controller->picture_type == VIDEO_PICTURE_INTRA)) || (controller->picture_type == VIDEO_PICTURE_INTRA))
{ {
// new picture is decodable because it's an I frame or previous frame was decodable // new picture is decodable because it's an I frame or previous frame was decodable
controller->last_frame_decoded = TRUE; controller->last_frame_decoded = TRUE;
}
else
{
controller->last_frame_decoded = FALSE;
} }
else
{
controller->last_frame_decoded = FALSE;
}
p264_realloc_ref(controller); p264_realloc_ref(controller);
picture_layer->gobs = (p264_gob_layer_t*) controller->gobs; picture_layer->gobs = (p264_gob_layer_t*) controller->gobs;
gob = &picture_layer->gobs[controller->blockline]; gob = &picture_layer->gobs[controller->blockline];
@@ -2,13 +2,6 @@
#ifdef HAS_UVLC_WRITE_BLOCK #ifdef HAS_UVLC_WRITE_BLOCK
#ifdef _ECOS
#include "config-tcm.h"
.section ".text.itcm","ax"
#endif // ! _ECOS
.global uvlc_write_block .global uvlc_write_block
.type uvlc_write_block, %function .type uvlc_write_block, %function
@@ -2,12 +2,6 @@
#ifdef HAS_DO_QUANTIZE_INTRA_MB #ifdef HAS_DO_QUANTIZE_INTRA_MB
#ifdef _ECOS
#include "config-tcm.h"
.section ".text.itcm","ax"
#endif // ! _ECOS
.global do_quantize_intra_mb .global do_quantize_intra_mb
.type do_quantize_intra_mb, %function .type do_quantize_intra_mb, %function
+1 -1
Ver Arquivo
@@ -235,7 +235,7 @@ C_RESULT uvlc_unpack_controller( video_controller_t* controller )
{ {
// new picture // new picture
uvlc_read_picture_layer( controller, stream ); uvlc_read_picture_layer( controller, stream );
controller->last_frame_decoded = TRUE; controller->last_frame_decoded = TRUE;
picture_layer->gobs = (uvlc_gob_layer_t*) controller->gobs; picture_layer->gobs = (uvlc_gob_layer_t*) controller->gobs;
gob = &picture_layer->gobs[controller->blockline]; gob = &picture_layer->gobs[controller->blockline];
+2 -2
Ver Arquivo
@@ -257,8 +257,8 @@ C_RESULT video_decode_blockline( video_controller_t* controller, vp_api_picture_
if (C_OK == isCodecOK && if (C_OK == isCodecOK &&
NULL != controller->video_codec) NULL != controller->video_codec)
{ {
return controller->video_codec->decode_blockline( controller, blockline, got_image ); return controller->video_codec->decode_blockline( controller, blockline, got_image );
} }
else else
{ {
return C_FAIL; return C_FAIL;
+1
Ver Arquivo
@@ -123,6 +123,7 @@ C_RESULT video_controller_cleanup( video_controller_t* controller )
{ {
gob = &controller->gobs[0]; gob = &controller->gobs[0];
vp_os_free(gob->macroblocks); vp_os_free(gob->macroblocks);
gob->macroblocks = NULL;
vp_os_free( controller->gobs ); vp_os_free( controller->gobs );
controller->gobs = NULL; controller->gobs = NULL;
} }
+1
Ver Arquivo
@@ -19,6 +19,7 @@ huffman_tree_t* huffman_alloc( int32_t num_max_codes, int32_t max_code_length )
void huffman_free( huffman_tree_t* tree ) void huffman_free( huffman_tree_t* tree )
{ {
vp_os_free( tree ); vp_os_free( tree );
tree = NULL;
} }
C_RESULT huffman_add_codes( huffman_tree_t* tree, huffman_code_t* codes, int32_t num_codes ) C_RESULT huffman_add_codes( huffman_tree_t* tree, huffman_code_t* codes, int32_t num_codes )
+8 -8
Ver Arquivo
@@ -295,7 +295,7 @@ ATcodec_Add_Defined_Message_Tree (ATcodec_Tree_t *tree, const char *str)
void void
ATcodec_Init_Library (AT_CODEC_FUNCTIONS_PTRS *funcs) ATcodec_Init_Library (AT_CODEC_FUNCTIONS_PTRS *funcs)
{ {
ATcodec_Init_Library_Tree (&default_tree, funcs); ATcodec_Init_Library_Tree (&default_tree, funcs);
} }
void void
@@ -341,7 +341,7 @@ ATcodec_Init_Library_Tree (ATcodec_Tree_t *tree, AT_CODEC_FUNCTIONS_PTRS *func
void void
ATcodec_Shutdown_Library (void) ATcodec_Shutdown_Library (void)
{ {
ATcodec_Shutdown_Library_Tree(&default_tree); ATcodec_Shutdown_Library_Tree(&default_tree);
} }
@@ -699,15 +699,15 @@ ATcodec_Send_Messages()
if(!atcodec_lib_init_ok) if(!atcodec_lib_init_ok)
return ATCODEC_FALSE; return ATCODEC_FALSE;
vp_os_mutex_lock(&ATcodec_cond_mutex); vp_os_mutex_lock(&ATcodec_cond_mutex);
if(ATcodec_Message_len > INTERNAL_BUFFER_SIZE) if(ATcodec_Message_len > INTERNAL_BUFFER_SIZE)
printf("ATcodec_Send_Messages : buf=%s, len=%d\n", &ATcodec_Message_Buffer[0], ATcodec_Message_len); PRINT("ATcodec_Send_Messages : buf=%s, len=%d\n", &ATcodec_Message_Buffer[0], ATcodec_Message_len);
if(ATcodec_Message_len && func_ptrs.write((uint8_t*)&ATcodec_Message_Buffer[0], (int32_t*)&ATcodec_Message_len) != AT_CODEC_WRITE_OK) if(ATcodec_Message_len && func_ptrs.write((uint8_t*)&ATcodec_Message_Buffer[0], (int32_t*)&ATcodec_Message_len) != AT_CODEC_WRITE_OK)
res = ATCODEC_FALSE; res = ATCODEC_FALSE;
ATcodec_Message_len = 0; ATcodec_Message_len = 0;
vp_os_mutex_unlock(&ATcodec_cond_mutex); vp_os_mutex_unlock(&ATcodec_cond_mutex);
+1 -4
Ver Arquivo
@@ -83,7 +83,7 @@ before_check:
#------------------------------------------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------------------------------------------
TARGETS=vlib parrotOS_core parrotOS_utils parrotOS_drivers parrotOS_devs parrotOS_codec libplf sdk lib app TARGETS=vlib libplf sdk lib app
# When building on Ubuntu, only the final application (USE_APP) depends on the above-mentioned libraries. # When building on Ubuntu, only the final application (USE_APP) depends on the above-mentioned libraries.
# The iPhone applications do not use USE_APP; the above-mentioned libraries must therefore be built # The iPhone applications do not use USE_APP; the above-mentioned libraries must therefore be built
@@ -105,9 +105,6 @@ define ADD_RULE_TEMPLATE
ifeq ($(USE_ANDROID),yes) ifeq ($(USE_ANDROID),yes)
build_lib: build_$(1) build_lib: build_$(1)
endif endif
ifeq ($(USE_LINUX), yes)
build_lib: build_$(1)
endif
endif endif
endif endif
endif endif
+1 -86
Ver Arquivo
@@ -19,47 +19,10 @@ USE_VLIB=yes
SWING_VERSION=head SWING_VERSION=head
# Check validity of script usage. # Check validity of script usage.
if [ $1 ] && [ $1 = ecos ] ; then if [ $1 ] && [ $1 = elinux ] ; then
if [ ! $QUIET_BUILD = yes ] ; then
echo ; echo "BUILD FOR ECOS" ; echo
fi
USE_ECOS=yes
USE_LINUX=no
USE_ELINUX=no
USE_NDS=no
USE_IPHONE=no
# head ecos-stable-2006-11-21 ecos-stable-2007-07-23 CK5300_Version_20070928_Beta5
ECOS_VERSION=Mykonos_Version_20090212
PROJECT=mykonos_p5p
MODE_TARGET=rls_ram_wifi_ap
CUSTOM_PRIORITIES=$ALL_SOURCES/video/$SDK_VERSION/Video/VP_SDK/VP_Os/ecos/task_priorities.h
# gnutools_2008_03_28 gnutools_2007_02_07 gnutools_2005_05_20
GNUTOOLS_VERSION=gnutools_2008_03_28
USE_ECOS_RELEASE=no
NO_COM=no
USE_BONJOUR=no
USE_BLUES32=no
# Stable_20070307 Stable_20060922 Stable_20061129_Blues_3_6_4 Version_KEA_1_00_RC5_200701131
BLUES32_VERSION=Stable_20060922
COMMONSOFT_VERSION=head
USE_PVSP=yes
USE_SOUL=no
SOUL_VERSION=Stable_20070307
USE_TANGO=no
# Stable_20061222 Stable_20070509
TANGO_VERSION=Stable_20070509
DONT_USE_TTS=yes
USE_CK5050=no
CK5050_VERSION=head
USE_BLUEZ=no
# P5 Intel smdk2412
FF_ARCH=P5
USE_PARROTOS_CORE=no
elif [ $1 ] && [ $1 = elinux ] ; then
if [ ! $QUIET_BUILD = yes ] ; then if [ ! $QUIET_BUILD = yes ] ; then
echo ; echo "BUILD FOR EMBEDDED LINUX" ; echo echo ; echo "BUILD FOR EMBEDDED LINUX" ; echo
fi fi
USE_ECOS=no
USE_LINUX=no USE_LINUX=no
USE_ELINUX=yes USE_ELINUX=yes
USE_NDS=no USE_NDS=no
@@ -80,7 +43,6 @@ elif [ $1 ] && [ $1 = linux ] ; then
if [ ! $QUIET_BUILD = yes ] ; then if [ ! $QUIET_BUILD = yes ] ; then
echo ; echo "BUILD FOR LINUX" ; echo echo ; echo "BUILD FOR LINUX" ; echo
fi fi
USE_ECOS=no
USE_LINUX=yes USE_LINUX=yes
USE_ELINUX=no USE_ELINUX=no
USE_NDS=no USE_NDS=no
@@ -96,7 +58,6 @@ elif [ $1 ] && [ $1 = nds ] ; then
if [ ! $QUIET_BUILD = yes ] ; then if [ ! $QUIET_BUILD = yes ] ; then
echo ; echo "BUILD FOR NINTENDO DS" ; echo echo ; echo "BUILD FOR NINTENDO DS" ; echo
fi fi
USE_ECOS=no
USE_LINUX=no USE_LINUX=no
USE_ELINUX=no USE_ELINUX=no
USE_NDS=yes USE_NDS=yes
@@ -112,7 +73,6 @@ elif [ $1 ] && [ ${1:0:6} = iphone ] ; then
if [ ! $QUIET_BUILD = yes ] ; then if [ ! $QUIET_BUILD = yes ] ; then
echo ; echo "BUILD FOR IPHONE with platform $1 $IPHONE_SDK_VERSION" ; echo echo ; echo "BUILD FOR IPHONE with platform $1 $IPHONE_SDK_VERSION" ; echo
fi fi
USE_ECOS=no
USE_LINUX=no USE_LINUX=no
USE_ELINUX=no USE_ELINUX=no
USE_NDS=no USE_NDS=no
@@ -135,7 +95,6 @@ FLAGS="USE_APP=$USE_APP"
FLAGS="IPHONE_SDK_VERSION=$IPHONE_SDK_VERSION $FLAGS" FLAGS="IPHONE_SDK_VERSION=$IPHONE_SDK_VERSION $FLAGS"
FLAGS="NO_EXAMPLES=$NO_EXAMPLES $FLAGS" FLAGS="NO_EXAMPLES=$NO_EXAMPLES $FLAGS"
FLAGS="GNUTOOLS_VERSION=$GNUTOOLS_VERSION $FLAGS" FLAGS="GNUTOOLS_VERSION=$GNUTOOLS_VERSION $FLAGS"
FLAGS="USE_ECOS=$USE_ECOS $FLAGS"
FLAGS="USE_LINUX=$USE_LINUX $FLAGS" FLAGS="USE_LINUX=$USE_LINUX $FLAGS"
FLAGS="USE_ELINUX=$USE_ELINUX $FLAGS" FLAGS="USE_ELINUX=$USE_ELINUX $FLAGS"
FLAGS="USE_NDS=$USE_NDS $FLAGS" FLAGS="USE_NDS=$USE_NDS $FLAGS"
@@ -160,8 +119,6 @@ FLAGS="QUIET_BUILD=$QUIET_BUILD $FLAGS"
FLAGS="RELEASE_BUILD=$RELEASE_BUILD $FLAGS" FLAGS="RELEASE_BUILD=$RELEASE_BUILD $FLAGS"
FLAGS="SDK_VERSION=$SDK_VERSION $FLAGS" FLAGS="SDK_VERSION=$SDK_VERSION $FLAGS"
FLAGS="USE_ECOS_RELEASE=$USE_ECOS_RELEASE $FLAGS"
FLAGS="ECOS_VERSION=$ECOS_VERSION $FLAGS"
FLAGS="ELINUX_VERSION=$ELINUX_VERSION $FLAGS" FLAGS="ELINUX_VERSION=$ELINUX_VERSION $FLAGS"
FLAGS="PROJECT=$PROJECT $FLAGS" FLAGS="PROJECT=$PROJECT $FLAGS"
FLAGS="MODE_TARGET=$MODE_TARGET $FLAGS" FLAGS="MODE_TARGET=$MODE_TARGET $FLAGS"
@@ -181,17 +138,10 @@ FLAGS="USE_IWLIB=$USE_IWLIB $FLAGS"
FLAGS="USE_PARROTOS_CORE=$USE_PARROTOS_CORE $FLAGS" FLAGS="USE_PARROTOS_CORE=$USE_PARROTOS_CORE $FLAGS"
FLAGS="COMMONSOFT_VERSION=$COMMONSOFT_VERSION $FLAGS" FLAGS="COMMONSOFT_VERSION=$COMMONSOFT_VERSION $FLAGS"
if [ $USE_ECOS = yes ] ; then
FLAGS="CUSTOM_PRIORITIES=$CUSTOM_PRIORITIES $FLAGS"
fi
if [ $USE_ELINUX = yes ] ; then if [ $USE_ELINUX = yes ] ; then
FLAGS="CONFIG_PARROTOS=$CONFIG_PARROTOS $FLAGS" FLAGS="CONFIG_PARROTOS=$CONFIG_PARROTOS $FLAGS"
fi fi
if [ $USE_ECOS = yes ] && [ $2 ] && ! [ $2 = check ] && ! [ $2 = clean ] || [ $USE_ECOS = yes ] && ! [ $2 ] ; then
CHOOSE=yes
fi
if [ $2 ] && [ $2 = check ] ; then if [ $2 ] && [ $2 = check ] ; then
CHECK=yes CHECK=yes
fi fi
@@ -212,38 +162,3 @@ if [ $CHECK ] && [ $CHECK = yes ] ; then
else else
make -f Makefile $FLAGS $* 2>&1 make -f Makefile $FLAGS $* 2>&1
fi fi
#####################
# Choose example ?
#####################
if [ $CHOOSE ] && [ $CHOOSE = yes ] ; then
j=1 ; for i in $( find . -type d -name "*Examples" | grep arm ) ; do j=$( expr $j + 1 ) ; done
if [ $j = 1 ] ; then
echo No example directory found
exit
fi
if ! [ $j = 2 ] ; then
j=1 ; for i in $( find . -type d -name "*Examples" | grep arm ) ; do echo -e "\t$j\t$i" ; j=$( expr $j + 1 ) ; done
echo -n -e "\nChoose directory : "
read var
j=1 ; for i in $( find . -type d -name "*Examples" | grep arm ) ; do if [ $j = $var ] ; then ex_dir=$i ; fi ; j=$( expr $j + 1 ) ; done
else
ex_dir=$( find . -type d -name "*Examples" | grep arm )
fi
echo -e "\nDirectory $ex_dir :"
j=1 ; for i in $( find $ex_dir -type f -exec basename \{\} \; ) ; do echo -e "\t$j\t$i" ; j=$( expr $j + 1 ) ; done
echo -n -e "\nChoose example : "
read var
j=1 ; for i in $( find $ex_dir -type f ) ; do if [ $j = $var ] ; then ex_file=$i ; fi ; j=$( expr $j + 1 ) ; done
if [ ! -z $ex_file ] && [ -f $ex_file ] ; then
cp $ex_file /srv/tftp/program.elf && echo -e "\n$ex_file copied to /srv/tftp/program.elf"
else
echo -e "\nBad choice !"
fi
fi
@@ -66,7 +66,6 @@ vp_os_cond_wait(vp_os_cond_t *cond)
pthread_cond_wait(&cond->cond, (pthread_mutex_t *)cond->mutex); pthread_cond_wait(&cond->cond, (pthread_mutex_t *)cond->mutex);
} }
C_RESULT C_RESULT
vp_os_cond_timed_wait(vp_os_cond_t *cond, uint32_t ms) vp_os_cond_timed_wait(vp_os_cond_t *cond, uint32_t ms)
{ {
+3 -1
Ver Arquivo
@@ -86,11 +86,13 @@ vp_os_cond_timed_wait(vp_os_cond_t *cond, uint32_t ms)
gettimeofday(&tv, NULL); gettimeofday(&tv, NULL);
TIMEVAL_TO_TIMESPEC(&tv, &ts); TIMEVAL_TO_TIMESPEC(&tv, &ts);
ts.tv_sec += ms/1000; ts.tv_sec += ms/1000;
ts.tv_nsec += (ms%1000)*1000; ts.tv_nsec += (ms%1000)*1000000;
if (ts.tv_nsec>1000000000) { ts.tv_sec++, ts.tv_nsec-=1000000000; }
return ( pthread_cond_timedwait(&cond->cond, (pthread_mutex_t *)cond->mutex, &ts) == ETIMEDOUT ? FAIL : SUCCESS ); return ( pthread_cond_timedwait(&cond->cond, (pthread_mutex_t *)cond->mutex, &ts) == ETIMEDOUT ? FAIL : SUCCESS );
} }
void void
vp_os_cond_signal(vp_os_cond_t *cond) vp_os_cond_signal(vp_os_cond_t *cond)
{ {
+13 -5
Ver Arquivo
@@ -23,20 +23,28 @@
#endif // __MACOSX__ #endif // __MACOSX__
#ifdef USE_ANDROID #ifdef USE_ANDROID
#include <android/log.h> #include <android/log.h>
#undef PRINT #undef PRINT
#define PRINT(_fmt_, args...) \ #ifdef DEBUG_MODE
#define PRINT(_fmt_, args...) \
__android_log_print(ANDROID_LOG_INFO, "ARDrone", _fmt_, ##args) __android_log_print(ANDROID_LOG_INFO, "ARDrone", _fmt_, ##args)
#else
#define PRINT(...)
#endif //DEBUG_MODE
#endif // USE_ANDROID
#ifndef PRINT
#define PRINT printf
#endif #endif
#ifdef DEBUG_MODE #ifdef DEBUG_MODE
#define DEBUG_PRINT_SDK(...) printf(__VA_ARGS__) #define DEBUG_PRINT_SDK(...) PRINT(__VA_ARGS__)
#else #else
#define DEBUG_PRINT_SDK(...) #define DEBUG_PRINT_SDK(...)
#endif #endif
#ifdef DEBUG_MODE #ifdef DEBUG_MODE
#define DEBUG_PRINT(...) printf(__VA_ARGS__) #define DEBUG_PRINT(...) PRINT(__VA_ARGS__)
#else #else
#define DEBUG_PRINT(...) #define DEBUG_PRINT(...)
#endif #endif
@@ -2,9 +2,6 @@
#include <VP_Stages/vp_stages_frame_pipe.h> #include <VP_Stages/vp_stages_frame_pipe.h>
#include <VP_Os/vp_os_print.h> #include <VP_Os/vp_os_print.h>
#ifdef USE_ELINUX
#include <VP_Os/elinux/vp_os_ltt.h>
#endif
// Sender function // Sender function
C_RESULT C_RESULT
vp_stages_frame_pipe_sender_open(vp_stages_frame_pipe_config_t *cfg) vp_stages_frame_pipe_sender_open(vp_stages_frame_pipe_config_t *cfg)
@@ -185,6 +182,7 @@ C_RESULT
vp_stages_frame_pipe_receiver_close(vp_stages_frame_pipe_config_t *cfg) vp_stages_frame_pipe_receiver_close(vp_stages_frame_pipe_config_t *cfg)
{ {
vp_os_free (cfg->outPicture.raw); vp_os_free (cfg->outPicture.raw);
cfg->outPicture.raw = NULL;
vp_os_cond_destroy (&(cfg->buffer_sent)); vp_os_cond_destroy (&(cfg->buffer_sent));
vp_os_mutex_destroy (&(cfg->pipe_mut)); vp_os_mutex_destroy (&(cfg->pipe_mut));
return C_OK; return C_OK;
@@ -99,7 +99,10 @@ vp_stages_output_buffer_stage_transform(vp_stages_output_buffer_config_t *cfg, v
} }
if(in->status == VP_API_STATUS_ENDED) if(in->status == VP_API_STATUS_ENDED)
vp_os_free(out->buffers); {
vp_os_free(out->buffers);
out->buffers = NULL;
}
out->status = in->status; out->status = in->status;
+13 -11
Ver Arquivo
@@ -96,7 +96,7 @@ vp_stages_input_file_stage_open(vp_stages_input_file_config_t *cfg)
cfg->buffers = vp_os_malloc(sizeof(*cfg->buffers)*cfg->nb_buffers); cfg->buffers = vp_os_malloc(sizeof(*cfg->buffers)*cfg->nb_buffers);
if (cfg->buffers==NULL) if (cfg->buffers==NULL)
{ {
printf("%s:%d - Failed preloading %s : not enough memory for buffer pointers(required %d pointers)\n", PRINT("%s:%d - Failed preloading %s : not enough memory for buffer pointers(required %d pointers)\n",
__FUNCTION__,__LINE__, __FUNCTION__,__LINE__,
cfg->name,cfg->nb_buffers/(1024*1024)); cfg->name,cfg->nb_buffers/(1024*1024));
} }
@@ -113,7 +113,7 @@ vp_stages_input_file_stage_open(vp_stages_input_file_config_t *cfg)
#endif #endif
if (cfg->data==NULL) if (cfg->data==NULL)
{ {
printf("Failed preloading %s : not enough memory (required %d MB)\n", PRINT("Failed preloading %s : not enough memory (required %d MB)\n",
cfg->name,cfg->buffer_size*cfg->nb_buffers/(1024*1024)); cfg->name,cfg->buffer_size*cfg->nb_buffers/(1024*1024));
} }
@@ -124,10 +124,12 @@ vp_stages_input_file_stage_open(vp_stages_input_file_config_t *cfg)
if (cfg->data && cfg->preload!=0) if (cfg->data && cfg->preload!=0)
{ {
printf("Preloading file %s to memory ...\n",cfg->name); PRINT("Preloading file %s to memory ...\n",cfg->name);
for (i=0;i<cfg->nb_buffers;i++) for (i=0;i<cfg->nb_buffers;i++)
{ {
printf("."); fflush(stdout); #ifndef USE_ELINUX
PRINT("."); fflush(stdout);
#endif
res = fread(cfg->buffers[i], cfg->buffer_size , 1 , cfg->f); res = fread(cfg->buffers[i], cfg->buffer_size , 1 , cfg->f);
if (res<1) if (res<1)
{ {
@@ -135,14 +137,14 @@ vp_stages_input_file_stage_open(vp_stages_input_file_config_t *cfg)
cfg->nb_buffers=i; /* Store the number of successfully read frames */ cfg->nb_buffers=i; /* Store the number of successfully read frames */
} }
} }
printf("ok.\n"); PRINT("ok.\n");
fclose(cfg->f); fclose(cfg->f);
cfg->f=NULL; cfg->f=NULL;
} }
cfg->current_buffer=0; cfg->current_buffer=0;
printf("Using %s input file %s\n resolution %dx%d\n total size : %d MB\n", PRINT("Using %s input file %s\n resolution %dx%d\n total size : %d MB\n",
(PIX_FMT_YUV420P==cfg->vp_api_picture.format)?"420P":"422", (PIX_FMT_YUV420P==cfg->vp_api_picture.format)?"420P":"422",
cfg->name, cfg->name,
cfg->width,cfg->height,filesize/(1024*1024)); cfg->width,cfg->height,filesize/(1024*1024));
@@ -156,7 +158,7 @@ vp_stages_input_file_stage_transform(vp_stages_input_file_config_t *cfg, vp_api_
vp_os_mutex_lock(&out->lock); vp_os_mutex_lock(&out->lock);
#ifdef VERBOSE #ifdef VERBOSE
printf("%s:%d Reading a frame from YUV file %s ...\n",__FUNCTION__,__LINE__,cfg->name); PRINT("%s:%d Reading a frame from YUV file %s ...\n",__FUNCTION__,__LINE__,cfg->name);
#endif #endif
/* Init */ /* Init */
@@ -170,7 +172,7 @@ vp_stages_input_file_stage_transform(vp_stages_input_file_config_t *cfg, vp_api_
#ifdef VERBOSE #ifdef VERBOSE
printf("%s:%d Frames stored at address %p.\n",__FUNCTION__,__LINE__,cfg->data); PRINT("%s:%d Frames stored at address %p.\n",__FUNCTION__,__LINE__,cfg->data);
#endif #endif
} }
@@ -197,7 +199,7 @@ vp_stages_input_file_stage_transform(vp_stages_input_file_config_t *cfg, vp_api_
/* Read a frame from the disk file */ /* Read a frame from the disk file */
#ifdef VERBOSE #ifdef VERBOSE
printf("%s:%d Requesting %d bytes ...\n",__FUNCTION__,__LINE__,cfg->buffer_size); PRINT("%s:%d Requesting %d bytes ...\n",__FUNCTION__,__LINE__,cfg->buffer_size);
#endif #endif
out->buffers=cfg->buffers; out->buffers=cfg->buffers;
@@ -205,7 +207,7 @@ vp_stages_input_file_stage_transform(vp_stages_input_file_config_t *cfg, vp_api_
out->size = fread(out->buffers[0], cfg->buffer_size, 1 , cfg->f); out->size = fread(out->buffers[0], cfg->buffer_size, 1 , cfg->f);
#ifdef VERBOSE #ifdef VERBOSE
printf("%s:%d Read %d bytes ...\n",__FUNCTION__,__LINE__,out->size); PRINT("%s:%d Read %d bytes ...\n",__FUNCTION__,__LINE__,out->size);
#endif #endif
/* Go back at the beginning of the file if we reached the end of the video */ /* Go back at the beginning of the file if we reached the end of the video */
@@ -282,7 +284,7 @@ vp_stages_output_file_stage_open(vp_stages_output_file_config_t *cfg)
cfg->f = fopen(cfg->name, "wb"); cfg->f = fopen(cfg->name, "wb");
if(NULL == cfg->f) if(NULL == cfg->f)
{ {
printf("%s:%d - Error opening file %s\n",__FUNCTION__,__LINE__,cfg->name);perror(""); PRINT("%s:%d - Error opening file %s\n",__FUNCTION__,__LINE__,cfg->name);perror("");
return VP_FAILURE; return VP_FAILURE;
} }
return (VP_SUCCESS); return (VP_SUCCESS);
+3 -2
Ver Arquivo
@@ -355,10 +355,11 @@ vp_stages_output_sdl_stage_transform(vp_stages_output_sdl_config_t *cfg, vp_api_
// not managed // not managed
if(in->status == VP_API_STATUS_ENDED) if(in->status == VP_API_STATUS_ENDED)
{ {
pipeline_opened = 0; pipeline_opened = 0;
vp_os_free(out->buffers); vp_os_free(out->buffers);
} out->buffers = NULL;
}
vp_os_mutex_unlock(&out->lock); vp_os_mutex_unlock(&out->lock);