diff options
Diffstat (limited to 'tinyMEDIA')
51 files changed, 10132 insertions, 0 deletions
diff --git a/tinyMEDIA/droid-makefile b/tinyMEDIA/droid-makefile new file mode 100644 index 0000000..7c7b102 --- /dev/null +++ b/tinyMEDIA/droid-makefile @@ -0,0 +1,44 @@ +APP := lib$(PROJECT)_$(MARCH).$(EXT)
+
+CFLAGS := $(CFLAGS_LIB) -I../tinySAK/src -I../tinyNET/src -I../tinySDP/include -I./include
+LDFLAGS := $(LDFLAGS_LIB) -ltinySAK_$(MARCH) -ltinyNET_$(MARCH) -ltinySDP_$(MARCH) -lm
+
+all: $(APP)
+
+OBJS = \
+ src/tmedia.o \
+ src/tmedia_codec.o \
+ src/tmedia_codec_dummy.o \
+ src/tmedia_common.o \
+ src/tmedia_consumer.o \
+ src/tmedia_denoise.o \
+ src/tmedia_params.o \
+ src/tmedia_producer.o \
+ src/tmedia_qos.o \
+ src/tmedia_session.o \
+ src/tmedia_session_dummy.o \
+ src/tmedia_session_ghost.o \
+ \
+ src/content/tmedia_content.o \
+ src/content/tmedia_content_cpim.o \
+ src/content/tmedia_content_multipart.o \
+ src/content/tmedia_content_sip_frag.o
+
+
+$(APP): $(OBJS)
+ifeq ($(EXT), a)
+ $(AR) rcs $@ $^
+else
+ $(CC) $(LDFLAGS) -o $@ $^
+endif
+
+%.o: %.c
+ $(CC) -c $(INCLUDE) $(CFLAGS) $< -o $@
+
+install: $(APP)
+ $(ANDROID_SDK_ROOT)/tools/adb remount
+ $(ANDROID_SDK_ROOT)/tools/adb push $(APP) $(LIB_DIR)/$(APP)
+ $(ANDROID_SDK_ROOT)/tools/adb shell chmod 777 $(LIB_DIR)/$(APP)
+
+clean:
+ @rm -f $(OBJS) $(APP)
\ No newline at end of file diff --git a/tinyMEDIA/include/tinymedia.h b/tinyMEDIA/include/tinymedia.h new file mode 100644 index 0000000..7abbeb7 --- /dev/null +++ b/tinyMEDIA/include/tinymedia.h @@ -0,0 +1,52 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tinymedia.h
+ * @brief tinyMEDIA API.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TINYMEDIA_TINYMEDIA_H
+#define TINYMEDIA_TINYMEDIA_H
+
+/* == tinyMEDIA == */
+#include "tinymedia/tmedia_codec_dummy.h"
+#include "tinymedia/tmedia_session_dummy.h"
+#include "tinymedia/tmedia_session_ghost.h"
+
+#include "tinymedia/tmedia_common.h"
+#include "tinymedia/tmedia_qos.h"
+
+#include "tinymedia/content/tmedia_content.h"
+#include "tinymedia/content/tmedia_content_cpim.h"
+#include "tinymedia/content/tmedia_content_multipart.h"
+#include "tinymedia/content/tmedia_content_sip_frag.h"
+
+/* == tinyNET == */
+#include "tinynet.h"
+
+/* == tinySDP == */
+#include "tinysdp.h"
+
+#endif /* TINYMEDIA_TINYMEDIA_H */
diff --git a/tinyMEDIA/include/tinymedia/content/tmedia_content.h b/tinyMEDIA/include/tinymedia/content/tmedia_content.h new file mode 100644 index 0000000..d030243 --- /dev/null +++ b/tinyMEDIA/include/tinymedia/content/tmedia_content.h @@ -0,0 +1,126 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tmedia_content.h
+ * @brief Base content object.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ */
+#ifndef TINYMEDIA_CONTENT_H
+#define TINYMEDIA_CONTENT_H
+
+#include "tinymedia_config.h"
+
+#include "tsk_buffer.h"
+#include "tsk_list.h"
+#include "tsk_params.h"
+
+TMEDIA_BEGIN_DECLS
+
+/**Max number of plugins (content types) we can create */
+#define TMEDIA_CONTENT_MAX_PLUGINS 0x0F
+
+/** cast any pointer to @ref tmedia_content_t* object */
+#define TMEDIA_CONTENT(self) ((tmedia_content_t*)(self))
+
+/** Base object for all contents */
+typedef struct tmedia_content_s
+{
+ TSK_DECLARE_OBJECT;
+
+ const char* type;
+ //! plugin used to create the codec
+ const struct tmedia_content_plugin_def_s* plugin;
+}
+tmedia_content_t;
+
+/** Virtual table used to define a content plugin */
+typedef struct tmedia_content_plugin_def_s
+{
+ //! object definition used to create an instance of the codec
+ const tsk_object_def_t* objdef;
+
+ //! e.g. 'message/CPIM'
+ const char* type;
+
+ int (*parse) (tmedia_content_t*, const void* in_data, tsk_size_t in_size);
+ tsk_buffer_t* (*get_data) (tmedia_content_t*);
+}
+tmedia_content_plugin_def_t;
+
+/** List of @ref tmedia_codec_t elements */
+typedef tsk_list_t tmedia_contents_L_t;
+
+/**< Declare base class as content */
+#define TMEDIA_DECLARE_CONTENT tmedia_content_t __content__
+
+TINYMEDIA_API int tmedia_content_plugin_register(const char* type, const tmedia_content_plugin_def_t* plugin);
+TINYMEDIA_API int tmedia_content_plugin_unregister(const char* type, const tmedia_content_plugin_def_t* plugin);
+TINYMEDIA_API int tmedia_content_plugin_unregister_all();
+
+TINYMEDIA_API tmedia_content_t* tmedia_content_create(const char* type);
+TINYMEDIA_API tmedia_content_t* tmedia_content_parse(const void* data, tsk_size_t size, const char* type);
+
+TINYMEDIA_API int tmedia_content_init(tmedia_content_t* self);
+TINYMEDIA_API int tmedia_content_deinit(tmedia_content_t* self);
+TINYMEDIA_API tsk_buffer_t* tmedia_content_get_data(tmedia_content_t* self);
+
+/** dummy content */
+typedef struct tmedia_content_dummy_s
+{
+ TMEDIA_DECLARE_CONTENT;
+
+ tsk_buffer_t* data;
+}
+tmedia_content_dummy_t;
+
+#define TMEDIA_CONTENT_DUMMY(self) ((tmedia_content_dummy_t*)(self))
+#define TMEDIA_CONTENT_IS_DUMMY(self) ( (self) && (TMEDIA_CONTENT((self))->plugin==tmedia_content_dummy_plugin_def_t) )
+
+TINYMEDIA_GEXTERN const tmedia_content_plugin_def_t *tmedia_content_dummy_plugin_def_t;
+
+
+/** content header */
+typedef struct tmedia_content_header_s
+{
+ TSK_DECLARE_OBJECT;
+
+ char* name;
+ char* value;
+ tsk_params_L_t* params;
+}
+tmedia_content_header_t;
+
+tmedia_content_header_t* tmedia_content_header_create(const char* name, const char* value);
+int tmedia_content_header_deinit(tmedia_content_header_t* self);
+char* tmedia_content_header_tostring(const tmedia_content_header_t* self);
+
+#define TMEDIA_CONTENT_HEADER(self) ((tmedia_content_header_t*)(self))
+#define TMEDIA_DECLARE_CONTENT_HEADER tmedia_content_header_t __content_header__
+typedef tsk_list_t tmedia_content_headers_L_t;
+
+TINYMEDIA_GEXTERN const tsk_object_def_t *tmedia_content_header_def_t;
+
+TMEDIA_END_DECLS
+
+#endif /* TINYMEDIA_CONTENT_H */
diff --git a/tinyMEDIA/include/tinymedia/content/tmedia_content_cpim.h b/tinyMEDIA/include/tinymedia/content/tmedia_content_cpim.h new file mode 100644 index 0000000..b3538e9 --- /dev/null +++ b/tinyMEDIA/include/tinymedia/content/tmedia_content_cpim.h @@ -0,0 +1,59 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tmedia_content_cpim.h
+ * @brief Common Presence and Instant Messaging (CPIM): Message Format (RFC 3862)
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ */
+#ifndef TINYMEDIA_CONTENT_CPIM_H
+#define TINYMEDIA_CONTENT_CPIM_H
+
+#include "tinymedia_config.h"
+
+#include "tmedia_content.h"
+
+TMEDIA_BEGIN_DECLS
+
+#define TMEDIA_CONTENT_CPIM_TYPE "message/CPIM"
+
+/** message/CPIM content */
+typedef struct tmedia_content_cpim_s
+{
+ TMEDIA_DECLARE_CONTENT;
+
+ tmedia_content_headers_L_t* m_headers; /**< MIME headers for the overall message */
+ tmedia_content_headers_L_t* h_headers; /**< message headers */
+ tsk_buffer_t* e; /**< encapsulated MIME object containing the message content */
+ tsk_buffer_t* x; /**< MIME security multipart message wrapper */
+}
+tmedia_content_cpim_t;
+
+#define TMEDIA_CONTENT_CPIM(self) ((tmedia_content_cpim_t*)(self))
+#define TMEDIA_CONTENT_IS_CPIM(self) ( (self) && (TMEDIA_CONTENT((self))->plugin==tmedia_content_cpim_plugin_def_t) )
+
+TINYMEDIA_GEXTERN const tmedia_content_plugin_def_t *tmedia_content_cpim_plugin_def_t;
+
+TMEDIA_END_DECLS
+
+#endif /* TINYMEDIA_CONTENT_CPIM_H */
diff --git a/tinyMEDIA/include/tinymedia/content/tmedia_content_multipart.h b/tinyMEDIA/include/tinymedia/content/tmedia_content_multipart.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tinyMEDIA/include/tinymedia/content/tmedia_content_multipart.h diff --git a/tinyMEDIA/include/tinymedia/content/tmedia_content_sip_frag.h b/tinyMEDIA/include/tinymedia/content/tmedia_content_sip_frag.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tinyMEDIA/include/tinymedia/content/tmedia_content_sip_frag.h diff --git a/tinyMEDIA/include/tinymedia/tmedia.h b/tinyMEDIA/include/tinymedia/tmedia.h new file mode 100644 index 0000000..5ebebbd --- /dev/null +++ b/tinyMEDIA/include/tinymedia/tmedia.h @@ -0,0 +1,121 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tmedia.h
+ * @brief Base media object.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TINYMEDIA_TMEDIA_H
+#define TINYMEDIA_TMEDIA_H
+
+#include "tinymedia_config.h"
+
+#include "tinysdp/tsdp_message.h"
+
+#include "tnet_socket.h"
+
+#include "tsk_params.h"
+
+TMEDIA_BEGIN_DECLS
+
+
+#if 0
+
+#define TMEDIA_VA_ARGS(name, host, socket_type) tmedia_def_t, (const char*) name, (const char*) host, (tnet_socket_type_t) socket_type
+
+#define TMEDIA(self) ((tmedia_t*)(self))
+
+typedef enum tmedia_action_e
+{
+ // Dummy
+ tma_dummy_say_hello,
+
+ // MSRP
+ tma_msrp_send_data,
+ tma_msrp_send_file,
+
+ // Audio / Video
+
+ // T.38
+}
+tmedia_action_t;
+
+typedef struct tmedia_s
+{
+ TSK_DECLARE_OBJECT;
+
+ const struct tmedia_plugin_def_s* plugin;
+
+ char* name;
+ uint32_t port;
+ char* protocol;
+}
+tmedia_t;
+typedef tsk_list_t tmedias_L_t;
+
+#define TMED_DECLARE_MEDIA tmedia_t media
+
+typedef struct tmedia_plugin_def_s
+{
+ const tsk_object_def_t* objdef;
+ const char* name;
+ const char* media;
+
+ int (* start) (tmedia_t* );
+ int (* pause) (tmedia_t* );
+ int (* stop) (tmedia_t* );
+
+ const tsdp_header_M_t* (* get_local_offer) (tmedia_t* , va_list* );
+ const tsdp_header_M_t* (* get_negotiated_offer) (tmedia_t* );
+ int (* set_remote_offer) (tmedia_t* , const tsdp_message_t* );
+
+ int (* perform) (tmedia_t* , tmedia_action_t action, const tsk_params_L_t* );
+}
+tmedia_plugin_def_t;
+
+TINYMEDIA_API int tmedia_init(tmedia_t* self, const char* name);
+TINYMEDIA_API int tmedia_deinit(tmedia_t* self);
+
+TINYMEDIA_API int tmedia_plugin_register(const tmedia_plugin_def_t* def);
+TINYMEDIA_API tmedia_t* tmedia_factory_create(const char* name, const char* host, tnet_socket_type_t socket_type);
+
+TINYMEDIA_API int tmedia_start(tmedia_t* );
+TINYMEDIA_API int tmedia_pause(tmedia_t* );
+TINYMEDIA_API int tmedia_stop(tmedia_t* );
+
+TINYMEDIA_API const tsdp_header_M_t* tmedia_get_local_offer(tmedia_t* , ...);
+TINYMEDIA_API const tsdp_header_M_t* tmedia_get_negotiated_offer(tmedia_t* );
+TINYMEDIA_API int tmedia_set_remote_offer(tmedia_t* , const tsdp_message_t* );
+
+TINYMEDIA_API int tmedia_perform(tmedia_t* , tmedia_action_t, ... );
+
+TINYMEDIA_GEXTERN const void *tmedia_def_t;
+
+#endif
+
+TMEDIA_END_DECLS
+
+
+#endif /* TINYMEDIA_TMEDIA_H */
diff --git a/tinyMEDIA/include/tinymedia/tmedia_codec.h b/tinyMEDIA/include/tinymedia/tmedia_codec.h new file mode 100644 index 0000000..46435d9 --- /dev/null +++ b/tinyMEDIA/include/tinymedia/tmedia_codec.h @@ -0,0 +1,310 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tmedia_codec.h
+ * @brief Base codec object.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TINYMEDIA_CODEC_H
+#define TINYMEDIA_CODEC_H
+
+#include "tinymedia_config.h"
+
+#include "tmedia_common.h"
+
+#include "tsk_list.h"
+
+TMEDIA_BEGIN_DECLS
+
+/* =====
+* http://www.iana.org/assignments/rtp-parameters
+* http://www.networksorcery.com/enp/protocol/rtp.htm
+=====*/
+/******* Fixed Payload Type *************/
+#define TMEDIA_CODEC_FORMAT_G711u "0"
+#define TMEDIA_CODEC_FORMAT_1016 "1"
+#define TMEDIA_CODEC_FORMAT_G721 "2"
+#define TMEDIA_CODEC_FORMAT_GSM "3"
+#define TMEDIA_CODEC_FORMAT_G723 "4"
+#define TMEDIA_CODEC_FORMAT_DVI4_8000 "5"
+#define TMEDIA_CODEC_FORMAT_DVI4_16000 "6"
+#define TMEDIA_CODEC_FORMAT_LPC "7"
+#define TMEDIA_CODEC_FORMAT_G711a "8"
+#define TMEDIA_CODEC_FORMAT_G722 "9"
+#define TMEDIA_CODEC_FORMAT_L16_STEREO "10"
+#define TMEDIA_CODEC_FORMAT_L16 "11"
+#define TMEDIA_CODEC_FORMAT_QCELP "12"
+#define TMEDIA_CODEC_FORMAT_CN "13"
+#define TMEDIA_CODEC_FORMAT_MPA "14"
+#define TMEDIA_CODEC_FORMAT_G728 "15"
+#define TMEDIA_CODEC_FORMAT_DVI4_11025 "16"
+#define TMEDIA_CODEC_FORMAT_DVI4_22050 "17"
+#define TMEDIA_CODEC_FORMAT_G729 "18"
+
+#define TMEDIA_CODEC_FORMAT_CELLB "25"
+#define TMEDIA_CODEC_FORMAT_JPEG "26"
+#define TMEDIA_CODEC_FORMAT_NV "28"
+
+#define TMEDIA_CODEC_FORMAT_H261 "31"
+#define TMEDIA_CODEC_FORMAT_MPV "32"
+#define TMEDIA_CODEC_FORMAT_MP2T "33"
+#define TMEDIA_CODEC_FORMAT_H263 "34"
+
+/******* Dynamic Payload Type **********/
+
+#define TMEDIA_CODEC_FORMAT_ILBC "96"
+
+#define TMEDIA_CODEC_FORMAT_SPEEX_NB "97"
+#define TMEDIA_CODEC_FORMAT_SPEEX_WB "98"
+#define TMEDIA_CODEC_FORMAT_SPEEX_UWB "99"
+
+#define TMEDIA_CODEC_FORMAT_DTMF "101"
+
+#define TMEDIA_CODEC_FORMAT_H263_2000 "102"
+#define TMEDIA_CODEC_FORMAT_H263_1998 "103" // for stupid clients, should be equal to "103"
+#define TMEDIA_CODEC_FORMAT_H264_BP10 "104"
+#define TMEDIA_CODEC_FORMAT_H264_BP20 "105"
+#define TMEDIA_CODEC_FORMAT_H264_BP30 "106"
+
+
+#define TMEDIA_CODEC_FORMAT_AMR_WBP_BE "107"
+#define TMEDIA_CODEC_FORMAT_AMR_WBP_OA "108"
+#define TMEDIA_CODEC_FORMAT_AAC "109"
+#define TMEDIA_CODEC_FORMAT_AACPLUS "110"
+
+#define TMEDIA_CODEC_FORMAT_AMR_NB_BE "111"
+#define TMEDIA_CODEC_FORMAT_AMR_NB_OA "112"
+#define TMEDIA_CODEC_FORMAT_AMR_WB_BE "113"
+#define TMEDIA_CODEC_FORMAT_AMR_WB_OA "114"
+
+#define TMEDIA_CODEC_FORMAT_BV16 "115"
+
+#define TMEDIA_CODEC_FORMAT_MP4V_ES "121"
+#define TMEDIA_CODEC_FORMAT_FFV1 "122"
+#define TMEDIA_CODEC_FORMAT_FFVHUFF "123"
+#define TMEDIA_CODEC_FORMAT_HUFFYUV "124"
+//--> ONE MORE
+#define TMEDIA_CODEC_FORMAT_THEORA "126"
+
+
+#define TMEDIA_CODEC_FORMAT_MSRP "*"
+
+/**Max number of plugins (codec types) we can create */
+#define TMED_CODEC_MAX_PLUGINS 0xFF
+
+/** cast any pointer to @ref tmedia_codec_t* object */
+#define TMEDIA_CODEC(self) ((tmedia_codec_t*)(self))
+
+#define TMEDIA_CODEC_PCM_FRAME_SIZE(self) ((TMEDIA_CODEC((self))->plugin->audio.ptime * TMEDIA_CODEC((self))->plugin->rate)/1000)
+#define TMEDIA_CODEC_RATE(self) (TMEDIA_CODEC((self))->plugin->rate)
+//#define TMEDIA_CODEC_FRAMES_COUNT(buff_size) (((buff_size))/TMEDIA_CODEC_FRAME_SIZE(self))
+
+/** callback for video codecs */
+typedef int (*tmedia_codec_video_rtpcb_f)(const void* callback_data, const void* buffer, tsk_size_t size, uint32_t duration, tsk_bool_t marker);
+
+/** Base object for all Codecs */
+typedef struct tmedia_codec_s
+{
+ TSK_DECLARE_OBJECT;
+
+ //! the type of the codec
+ tmedia_type_t type;
+ //! whether the codec is opened
+ tsk_bool_t opened;
+ //! whether the pay. type is dyn. or not
+ tsk_bool_t dyn;
+ //! the name of the codec. e.g. "G.711U" or "G.711A" etc used in the sdp
+ char* name;
+ //! full description
+ char* desc;
+ //! the format. e.g. "0" for PCMU or "8" for PCMA or "*" for MSRP.
+ char* format;
+ //! bandwidth level
+ tmedia_bandwidth_level_t bl;
+ //! the negociated format (only useful for codecs with dyn. payload type)
+ char* neg_format;
+ //! plugin used to create the codec
+ const struct tmedia_codec_plugin_def_s* plugin;
+}
+tmedia_codec_t;
+
+/** Virtual table used to define a codec plugin */
+typedef struct tmedia_codec_plugin_def_s
+{
+ //! object definition used to create an instance of the codec
+ const tsk_object_def_t* objdef;
+
+ //! the type of the codec
+ tmedia_type_t type;
+ //! the name of the codec. e.g. "G.711U" or "G.711A" etc using in the sdp.
+ const char* name;
+ //! full description
+ const char* desc;
+ //! the format. e.g. "0" for PCMU or "8" for PCMA or "*" for MSRP.
+ const char* format;
+ //! whether the pay. type is dyn. or not
+ tsk_bool_t dyn;
+ uint32_t rate;
+
+ /* default values could be updated at any time */
+ struct{
+ int8_t channels;
+ uint8_t ptime;
+ /* ...to be continued */
+ } audio;
+
+ /* default values could be updated at any time */
+ struct{
+ unsigned width;
+ unsigned height;
+ unsigned fps;
+ /* ...to be continued */
+ } video;
+
+ //! open the codec
+ int (*open) (tmedia_codec_t*);
+ //! close the codec
+ int (*close) (tmedia_codec_t*);
+ //! encode data
+ tsk_size_t (*encode) (tmedia_codec_t*, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size);
+ //! decode data
+ tsk_size_t (*decode) (tmedia_codec_t*, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size, const tsk_object_t* proto_hdr);
+ //! whether the codec can handle the fmtp
+ tsk_bool_t (* fmtp_match) (const tmedia_codec_t*, const char* );
+ //! gets fmtp value. e.g. "mode-set=0,2,5,7; mode-change-period=2; mode-change-neighbor=1"
+ char* (* fmtp_get) (const tmedia_codec_t* );
+ //! sets fmtp received from the remote party
+ int (* fmtp_set) (tmedia_codec_t*, const char* );
+}
+tmedia_codec_plugin_def_t;
+
+/** List of @ref tmedia_codec_t elements */
+typedef tsk_list_t tmedia_codecs_L_t;
+
+/**< Declare base class as codec */
+#define TMEDIA_DECLARE_CODEC tmedia_codec_t __codec__
+
+TINYMEDIA_API int tmedia_codec_init(tmedia_codec_t* self, tmedia_type_t type, const char* name, const char* desc, const char* format);
+TINYMEDIA_API int tmedia_codec_open(tmedia_codec_t* self);
+TINYMEDIA_API int tmedia_codec_close(tmedia_codec_t* self);
+TINYMEDIA_API int tmedia_codec_cmp(const tsk_object_t* codec1, const tsk_object_t* codec2);
+TINYMEDIA_API int tmedia_codec_plugin_register(const tmedia_codec_plugin_def_t* plugin);
+TINYMEDIA_API int tmedia_codec_plugin_unregister(const tmedia_codec_plugin_def_t* plugin);
+TINYMEDIA_API tmedia_codec_t* tmedia_codec_create(const char* format);
+TINYMEDIA_API char* tmedia_codec_get_rtpmap(const tmedia_codec_t* self);
+TINYMEDIA_API char* tmedia_codec_get_fmtp(const tmedia_codec_t* self);
+TINYMEDIA_API tsk_bool_t tmedia_codec_match_fmtp(const tmedia_codec_t* self, const char* fmtp);
+TINYMEDIA_API int tmedia_codec_set_remote_fmtp(tmedia_codec_t* self, const char* fmtp);
+TINYMEDIA_API int tmedia_codec_removeAll_exceptThese(tmedia_codecs_L_t* codecs, const tmedia_codecs_L_t * codecs2keep);
+TINYMEDIA_API int tmedia_codec_to_sdp(const tmedia_codecs_L_t* codecs, tsdp_header_M_t* m);
+TINYMEDIA_API tmedia_codec_t* tmedia_codec_find_by_format(tmedia_codecs_L_t* codecs, const char* format);
+TINYMEDIA_API int tmedia_codec_parse_fmtp(const char* fmtp, unsigned* maxbr, unsigned* fps, unsigned *width, unsigned *height);
+TINYMEDIA_API int tmedia_codec_deinit(tmedia_codec_t* self);
+
+/** Audio codec */
+typedef struct tmedia_codec_audio_s
+{
+ TMEDIA_DECLARE_CODEC;
+}
+tmedia_codec_audio_t;
+
+/**@def TMEDIA_DECLARE_CODEC_AUDIO
+* Declares base class as audio codec.
+*/
+/**@def TMEDIA_CODEC_AUDIO
+* Cast any pointer as @ref tmedia_codec_audio_t* object.
+*/
+/**@def tmedia_codec_audio_init
+* Initialize a audio codec.
+*/
+/**@def tmedia_codec_audio_deinit
+* DeInitialize a audio codec.
+*/
+#define TMEDIA_DECLARE_CODEC_AUDIO tmedia_codec_audio_t __audio__
+#define TMEDIA_CODEC_AUDIO(self) ((tmedia_codec_audio_t*)(self))
+#define tmedia_codec_audio_init(self, name, desc, format) tmedia_codec_init(TMEDIA_CODEC(self), tmedia_audio, name, desc, format)
+#define tmedia_codec_audio_deinit(self) tmedia_codec_deinit(TMEDIA_CODEC(self))
+
+/** Video codec */
+typedef struct tmedia_codec_video_s
+{
+ TMEDIA_DECLARE_CODEC;
+
+ unsigned width;
+ unsigned height;
+ unsigned fps;
+ unsigned max_br;
+ unsigned max_mbps;
+
+ tmedia_codec_video_rtpcb_f callback;
+ const void* callback_data;
+}
+tmedia_codec_video_t;
+
+/**@def TMEDIA_DECLARE_CODEC_VIDEO
+* Declares base class as video codec.
+*/
+/**@def TMEDIA_CODEC_VIDEO
+* Cast any pointer as @ref tmedia_codec_video_t* object.
+*/
+/**@def tmedia_codec_video_init
+* Initialize a video codec.
+*/
+/**@def tmedia_codec_video_deinit
+* DeInitialize a video codec.
+*/
+#define TMEDIA_DECLARE_CODEC_VIDEO tmedia_codec_video_t __video__
+#define TMEDIA_CODEC_VIDEO(self) ((tmedia_codec_video_t*)(self))
+#define tmedia_codec_video_init(self, name, desc, format) tmedia_codec_init(TMEDIA_CODEC(self), tmedia_video, name, desc, format)
+TINYMEDIA_API int tmedia_codec_video_set_callback(tmedia_codec_video_t *self, tmedia_codec_video_rtpcb_f callback, const void* callback_data);
+#define tmedia_codec_video_deinit(self) tmedia_codec_deinit(TMEDIA_CODEC(self))
+
+/** MSRP codec */
+typedef struct tmedia_codec_msrp_s
+{
+ TMEDIA_DECLARE_CODEC;
+}
+tmedia_codec_msrp_t;
+
+/**@def TMEDIA_DECLARE_CODEC_MSRP
+* Declares base class as msrp codec.
+*/
+/**@def TMEDIA_CODEC_MSRP
+* Cast any pointer as @ref tmedia_codec_msrp_t* object.
+*/
+/**@def tmedia_codec_msrp_init
+* Initialize a msrp codec.
+*/
+/**@def tmedia_codec_msrp_deinit
+* DeInitialize a msrp codec.
+*/
+#define TMEDIA_DECLARE_CODEC_MSRP tmedia_codec_msrp_t __msrp__
+#define TMEDIA_CODEC_MSRP(self) ((tmedia_codec_msrp_t*)(self))
+#define tmedia_codec_msrp_init(self, name, desc) tmedia_codec_init(TMEDIA_CODEC(self), tmedia_msrp, name, desc, "*")
+#define tmedia_codec_msrp_deinit(self) tmedia_codec_deinit(TMEDIA_CODEC(self))
+
+TMEDIA_END_DECLS
+
+#endif /* TINYMEDIA_CODEC_H */
diff --git a/tinyMEDIA/include/tinymedia/tmedia_codec_dummy.h b/tinyMEDIA/include/tinymedia/tmedia_codec_dummy.h new file mode 100644 index 0000000..8e1d53e --- /dev/null +++ b/tinyMEDIA/include/tinymedia/tmedia_codec_dummy.h @@ -0,0 +1,78 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tmedia_codec_dummy.h
+ * @brief Dummy codecs used for test only.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TINYMEDIA_CODEC_DUMMY_H
+#define TINYMEDIA_CODEC_DUMMY_H
+
+#include "tinymedia_config.h"
+
+#include "tmedia_codec.h"
+
+#include "tsk_object.h"
+
+TMEDIA_BEGIN_DECLS
+
+/** Dummy PCMU codec */
+typedef struct tmedia_codec_dpcmu_s
+{
+ TMEDIA_DECLARE_CODEC_AUDIO;
+}
+tmedia_codec_dpcmu_t;
+
+/** Dummy PCMA codec */
+typedef struct tmedia_codec_dpcma_s
+{
+ TMEDIA_DECLARE_CODEC_AUDIO;
+}
+tmedia_codec_dpcma_t;
+
+/** Dummy H.263 codec */
+typedef struct tmedia_codec_dh263_s
+{
+ TMEDIA_DECLARE_CODEC_VIDEO;
+}
+tmedia_codec_dh263_t;
+
+/** Dummy H.264 codec */
+typedef struct tmedia_codec_dh264_s
+{
+ TMEDIA_DECLARE_CODEC_VIDEO;
+}
+tmedia_codec_dh264_t;
+
+
+TINYMEDIA_GEXTERN const tmedia_codec_plugin_def_t *tmedia_codec_dpcma_plugin_def_t;
+TINYMEDIA_GEXTERN const tmedia_codec_plugin_def_t *tmedia_codec_dpcmu_plugin_def_t;
+
+TINYMEDIA_GEXTERN const tmedia_codec_plugin_def_t *tmedia_codec_dh263_plugin_def_t;
+TINYMEDIA_GEXTERN const tmedia_codec_plugin_def_t *tmedia_codec_dh264_plugin_def_t;
+
+TMEDIA_END_DECLS
+
+#endif /* TINYMEDIA_CODEC_DUMMY_H */
diff --git a/tinyMEDIA/include/tinymedia/tmedia_common.h b/tinyMEDIA/include/tinymedia/tmedia_common.h new file mode 100644 index 0000000..54044be --- /dev/null +++ b/tinyMEDIA/include/tinymedia/tmedia_common.h @@ -0,0 +1,119 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tmedia_common.h
+ * @brief Common functions and definitions.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TINYMEDIA_COMMON_H
+#define TINYMEDIA_COMMON_H
+
+#include "tinymedia_config.h"
+
+#include "tinysdp/tsdp_message.h"
+
+TMEDIA_BEGIN_DECLS
+
+/** List of all supported media types */
+typedef enum tmedia_type_e
+{
+ tmedia_none = 0x00,
+ tmedia_ghost = (0x01 << 0),
+
+ tmedia_audio = (0x01 << 1),
+ tmedia_video = (0x01 << 2),
+ tmedia_chat = (0x01 << 3),
+ tmedia_file = (0x01 << 4),
+ tmedia_t38 = (0x01 << 5),
+
+ tmedia_msrp = (tmedia_chat | tmedia_file),
+ tmedia_audiovideo = (tmedia_audio | tmedia_video),
+
+ tmedia_all = (tmedia_audio | tmedia_video | tmedia_msrp | tmedia_t38)
+}
+tmedia_type_t;
+
+typedef enum tmedia_video_size_type_e
+{
+ tmedia_vst_none,
+ tmedia_vst_sqcif,
+ tmedia_vst_qcif,
+ tmedia_vst_qvga,
+ tmedia_vst_cif,
+ tmedia_vst_vga,
+ tmedia_vst_4cif,
+ tmedia_vst_svga,
+ tmedia_vst_xga,
+ tmedia_vst_sxga,
+ tmedia_vst_16cif,
+ tmedia_vst_hd720p,
+ tmedia_vst_hd1080p,
+
+ tmedia_vst_ios_low,
+ tmedia_vst_ios_high
+}
+tmedia_video_size_type_t;
+
+typedef struct tmedia_video_size_s
+{
+ tmedia_video_size_type_t type;
+ tsk_size_t width;
+ tsk_size_t height;
+}
+tmedia_video_size_t;
+
+
+// used by tinyWRAP
+typedef enum tmedia_chroma_e
+{
+ tmedia_rgb24, // will be stored as bgr24 on x86 (little endians) machines; e.g. WindowsPhone7
+ tmedia_bgr24, // used by windows consumer (DirectShow) -
+ tmedia_rgb32, // used by iOS4 consumer (iPhone and iPod touch)
+ tmedia_rgb565le, // (used by both android and wince consumers)
+ tmedia_rgb565be,
+ tmedia_nv12, // used by iOS4 producer (iPhone and iPod Touch 3GS and 4)
+ tmedia_nv21, // Yuv420 SP (used by android producer)
+ tmedia_yuv422p,
+ tmedia_uyvy422, // used by iOS4 producer (iPhone and iPod Touch 3G)
+ tmedia_yuv420p, // Default
+}
+tmedia_chroma_t;
+
+// used by tinyWRAP
+typedef enum tmedia_bandwidth_level_e
+{
+ tmedia_bl_low,
+ tmedia_bl_medium,
+ tmedia_bl_hight
+}
+tmedia_bandwidth_level_t;
+
+TINYMEDIA_API tmedia_type_t tmedia_type_from_sdp(const tsdp_message_t* sdp);
+TINYMEDIA_API int tmedia_parse_rtpmap(const char* rtpmap, char** name, int32_t* rate, int32_t* channels);
+TINYMEDIA_API const tmedia_video_size_t* tmedia_get_video_size(tmedia_chroma_t chroma, tsk_size_t size);
+
+TMEDIA_END_DECLS
+
+#endif /* TINYMEDIA_COMMON_H */
diff --git a/tinyMEDIA/include/tinymedia/tmedia_consumer.h b/tinyMEDIA/include/tinymedia/tmedia_consumer.h new file mode 100644 index 0000000..3c8fb60 --- /dev/null +++ b/tinyMEDIA/include/tinymedia/tmedia_consumer.h @@ -0,0 +1,116 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tmedia_consumer.h
+ * @brief Base consumer object.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TINYMEDIA_CONSUMER_H
+#define TINYMEDIA_CONSUMER_H
+
+#include "tinymedia_config.h"
+
+#include "tinymedia/tmedia_codec.h"
+#include "tinymedia/tmedia_params.h"
+#include "tmedia_common.h"
+
+TMEDIA_BEGIN_DECLS
+
+/**Max number of plugins (consumer types) we can create */
+#define TMED_CONSUMER_MAX_PLUGINS 0x0F
+
+/** cast any pointer to @ref tmedia_consumer_t* object */
+#define TMEDIA_CONSUMER(self) ((tmedia_consumer_t*)(self))
+
+/** Default Video chroma */
+#define TMEDIA_CONSUMER_CHROMA_DEFAULT tmedia_yuv420p
+
+/** Base object for all Consumers */
+typedef struct tmedia_consumer_s
+{
+ TSK_DECLARE_OBJECT;
+
+ tmedia_type_t type;
+ const char* desc;
+
+ struct{
+ int fps;
+ struct {
+ tmedia_chroma_t chroma;
+ tsk_size_t width;
+ tsk_size_t height;
+ } in;
+ struct {
+ tmedia_chroma_t chroma;
+ tsk_size_t width;
+ tsk_size_t height;
+ tsk_bool_t auto_resize; // auto_resize to "in.width, in.height"
+ } display;
+ } video;
+
+ uint64_t session_id;
+ const struct tmedia_consumer_plugin_def_s* plugin;
+}
+tmedia_consumer_t;
+
+/** Virtual table used to define a consumer plugin */
+typedef struct tmedia_consumer_plugin_def_s
+{
+ //! object definition used to create an instance of the consumer
+ const tsk_object_def_t* objdef;
+
+ //! the type of the consumer
+ tmedia_type_t type;
+ //! full description (usefull for debugging)
+ const char* desc;
+
+ int (*set) (tmedia_consumer_t* , const tmedia_param_t*);
+ int (* prepare) (tmedia_consumer_t*, const tmedia_codec_t* );
+ int (* start) (tmedia_consumer_t* );
+ int (* consume) (tmedia_consumer_t*, void** buffer, tsk_size_t size, const tsk_object_t* proto_hdr);
+ int (* pause) (tmedia_consumer_t* );
+ int (* stop) (tmedia_consumer_t* );
+}
+tmedia_consumer_plugin_def_t;
+
+#define TMEDIA_DECLARE_CONSUMER tmedia_consumer_t __consumer__
+
+TINYMEDIA_API tmedia_consumer_t* tmedia_consumer_create(tmedia_type_t type, uint64_t session_id);
+TINYMEDIA_API int tmedia_consumer_init(tmedia_consumer_t* self);
+TINYMEDIA_API int tmedia_consumer_set(tmedia_consumer_t *self, const tmedia_param_t* param);
+TINYMEDIA_API int tmedia_consumer_prepare(tmedia_consumer_t *self, const tmedia_codec_t* codec);
+TINYMEDIA_API int tmedia_consumer_start(tmedia_consumer_t *self);
+TINYMEDIA_API int tmedia_consumer_consume(tmedia_consumer_t* self, void** buffer, tsk_size_t size, const tsk_object_t* proto_hdr);
+TINYMEDIA_API int tmedia_consumer_pause(tmedia_consumer_t *self);
+TINYMEDIA_API int tmedia_consumer_stop(tmedia_consumer_t *self);
+TINYMEDIA_API int tmedia_consumer_deinit(tmedia_consumer_t* self);
+
+TINYMEDIA_API int tmedia_consumer_plugin_register(const tmedia_consumer_plugin_def_t* plugin);
+TINYMEDIA_API int tmedia_consumer_plugin_unregister(const tmedia_consumer_plugin_def_t* plugin);
+TINYMEDIA_API int tmedia_consumer_plugin_unregister_by_type(tmedia_type_t type);
+
+TMEDIA_END_DECLS
+
+#endif /* TINYMEDIA_CONSUMER_H */
diff --git a/tinyMEDIA/include/tinymedia/tmedia_denoise.h b/tinyMEDIA/include/tinymedia/tmedia_denoise.h new file mode 100644 index 0000000..9fb3d20 --- /dev/null +++ b/tinyMEDIA/include/tinymedia/tmedia_denoise.h @@ -0,0 +1,85 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tmedia_denoise.h
+ * @brief Denoiser (Noise suppression, AGC, AEC, VAD) Plugin
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TINYMEDIA_DENOISE_H
+#define TINYMEDIA_DENOISE_H
+
+#include "tinymedia_config.h"
+
+#include "tsk_object.h"
+
+TMEDIA_BEGIN_DECLS
+
+/** cast any pointer to @ref tmedia_denoise_t* object */
+#define TMEDIA_DENOISE(self) ((tmedia_denoise_t*)(self))
+
+/** Base object for all Denoisers */
+typedef struct tmedia_denoise_s
+{
+ TSK_DECLARE_OBJECT;
+
+ tsk_bool_t opened;
+
+ const struct tmedia_denoise_plugin_def_s* plugin;
+}
+tmedia_denoise_t;
+
+#define TMEDIA_DECLARE_DENOISE tmedia_denoise_t __denoise__
+
+/** Virtual table used to define a consumer plugin */
+typedef struct tmedia_denoise_plugin_def_s
+{
+ //! object definition used to create an instance of the denoiser
+ const tsk_object_def_t* objdef;
+
+ //! full description (usefull for debugging)
+ const char* desc;
+
+ int (* open) (tmedia_denoise_t*, uint32_t frame_size, uint32_t sampling_rate, tsk_bool_t denoise, float agc_level, tsk_bool_t aec, tsk_bool_t vad);
+ int (*echo_playback) (tmedia_denoise_t* self, const void* echo_frame);
+ int (* process) (tmedia_denoise_t*, void* audio_frame, tsk_bool_t* silence_or_noise);
+ int (* close) (tmedia_denoise_t* );
+}
+tmedia_denoise_plugin_def_t;
+
+TINYMEDIA_API int tmedia_denoise_init(tmedia_denoise_t* self);
+TINYMEDIA_API int tmedia_denoise_open(tmedia_denoise_t* self, uint32_t frame_size, uint32_t sampling_rate, tsk_bool_t denoise, float agc_level, tsk_bool_t aec, tsk_bool_t vad);
+TINYMEDIA_API int tmedia_denoise_echo_playback(tmedia_denoise_t* self, const void* echo_frame);
+TINYMEDIA_API int tmedia_denoise_process(tmedia_denoise_t* self, void* audio_frame, tsk_bool_t* silence_or_noise);
+TINYMEDIA_API int tmedia_denoise_close(tmedia_denoise_t* self);
+TINYMEDIA_API int tmedia_denoise_deinit(tmedia_denoise_t* self);
+
+TINYMEDIA_API int tmedia_denoise_plugin_register(const tmedia_denoise_plugin_def_t* plugin);
+TINYMEDIA_API int tmedia_denoise_plugin_unregister();
+TINYMEDIA_API tmedia_denoise_t* tmedia_denoise_create();
+
+TMEDIA_END_DECLS
+
+
+#endif /* TINYMEDIA_DENOISE_H */
diff --git a/tinyMEDIA/include/tinymedia/tmedia_params.h b/tinyMEDIA/include/tinymedia/tmedia_params.h new file mode 100644 index 0000000..2e12a22 --- /dev/null +++ b/tinyMEDIA/include/tinymedia/tmedia_params.h @@ -0,0 +1,114 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tmedia_params.h
+ * @brief Media parameters used to configure any session or plugin.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TINYMEDIA_PARAMS_H
+#define TINYMEDIA_PARAMS_H
+
+#include "tinymedia_config.h"
+
+#include "tinymedia/tmedia_common.h"
+
+#include "tsk_list.h"
+
+TMEDIA_BEGIN_DECLS
+
+#define TMEDIA_PARAM(self) ((tmedia_param_t*)(self))
+
+typedef enum tmedia_param_access_type_e
+{
+ //tmedia_pat_get,
+ tmedia_pat_set
+}
+tmedia_param_access_type_t;
+
+typedef enum tmedia_param_plugin_type_e
+{
+ tmedia_ppt_consumer,
+ tmedia_ppt_producer,
+ tmedia_ppt_codec,
+ tmedia_ppt_session,
+ tmedia_ppt_manager
+}
+tmedia_param_plugin_type_t;
+
+typedef enum tmedia_param_value_type_e
+{
+ tmedia_pvt_int32,
+ tmedia_pvt_pobject,
+ tmedia_pvt_pchar,
+ tmedia_pvt_int64,
+}
+tmedia_param_value_type_t;
+
+#define TMEDIA_PARAM_VALUE_TYPE_IS_PTR(self) ((self) == tmedia_pvt_pobject || (self) == tmedia_pvt_pchar)
+
+typedef struct tmedia_param_s
+{
+ TSK_DECLARE_OBJECT;
+
+ tmedia_param_access_type_t access_type;
+ tmedia_type_t media_type;
+ tmedia_param_plugin_type_t plugin_type;
+ tmedia_param_value_type_t value_type;
+
+ char* key;
+ /* Because setting parameters could be deferred
+ * ==> MUST copy the value for later use.
+ * e.g. TMEDIA_SESSION_MANAGER_SET_INT32("width", 1234); 1234 will be lost when we exit the block code
+ */
+ void* value;
+}
+tmedia_param_t;
+
+typedef tsk_list_t tmedia_params_L_t; /**< List of @ref tsk_param_t elements. */
+
+#define tmedia_params_create() tsk_list_create()
+
+TINYMEDIA_API tmedia_param_t* tmedia_param_create(tmedia_param_access_type_t access_type,
+ tmedia_type_t media_type,
+ tmedia_param_plugin_type_t plugin_type,
+ tmedia_param_value_type_t value_type,
+ const char* key,
+ void* value);
+
+TINYMEDIA_API tmedia_params_L_t* tmedia_params_create_2(va_list *app);
+
+TINYMEDIA_API int tmedia_params_add_param(tmedia_params_L_t **self,
+ tmedia_param_access_type_t access_type,
+ tmedia_type_t media_type,
+ tmedia_param_plugin_type_t plugin_type,
+ tmedia_param_value_type_t value_type,
+ const char* key,
+ void* value);
+
+TINYMEDIA_GEXTERN const tsk_object_def_t *tmedia_param_def_t;
+
+TMEDIA_END_DECLS
+
+#endif /* TINYMEDIA_PARAMS_H */
diff --git a/tinyMEDIA/include/tinymedia/tmedia_producer.h b/tinyMEDIA/include/tinymedia/tmedia_producer.h new file mode 100644 index 0000000..418626a --- /dev/null +++ b/tinyMEDIA/include/tinymedia/tmedia_producer.h @@ -0,0 +1,123 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tmedia_producer.h
+ * @brief Base producer object.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TINYMEDIA_PRODUCER_H
+#define TINYMEDIA_PRODUCER_H
+
+#include "tinymedia_config.h"
+
+#include "tinymedia/tmedia_codec.h"
+#include "tinymedia/tmedia_params.h"
+#include "tmedia_common.h"
+
+TMEDIA_BEGIN_DECLS
+
+/**Max number of plugins (producer types) we can create */
+#define TMED_PRODUCER_MAX_PLUGINS 0x0F
+
+/** cast any pointer to @ref tmedia_producer_t* object */
+#define TMEDIA_PRODUCER(self) ((tmedia_producer_t*)(self))
+
+typedef int (*tmedia_producer_enc_cb_f)(const void* callback_data, const void* buffer, tsk_size_t size);
+typedef int (*tmedia_producer_raw_cb_f)(const void* callback_data, const void* buffer, tsk_size_t size, uint32_t duration, tsk_bool_t marker);
+
+/** Default Video chroma */
+#define TMEDIA_PRODUCER_CHROMA_DEFAULT tmedia_yuv420p
+
+/** Base object for all Producers */
+typedef struct tmedia_producer_s
+{
+ TSK_DECLARE_OBJECT;
+
+ tmedia_type_t type;
+ const char* desc;
+
+ struct{
+ tmedia_chroma_t chroma;
+ int fps;
+ int rotation;
+ tsk_size_t width;
+ tsk_size_t height;
+ } video;
+
+ const struct tmedia_producer_plugin_def_s* plugin;
+
+ uint64_t session_id;
+
+ struct{
+ tmedia_producer_enc_cb_f callback;
+ const void* callback_data;
+ } enc_cb;
+
+ struct{
+ tmedia_producer_raw_cb_f callback;
+ const void* callback_data;
+ } raw_cb;
+}
+tmedia_producer_t;
+
+/** Virtual table used to define a producer plugin */
+typedef struct tmedia_producer_plugin_def_s
+{
+ //! object definition used to create an instance of the producer
+ const tsk_object_def_t* objdef;
+
+ //! the type of the producer
+ tmedia_type_t type;
+ //! full description (usefull for debugging)
+ const char* desc;
+
+ int (*set) (tmedia_producer_t* , const tmedia_param_t*);
+ int (* prepare) (tmedia_producer_t* , const tmedia_codec_t*);
+ int (* start) (tmedia_producer_t* );
+ int (* pause) (tmedia_producer_t* );
+ int (* stop) (tmedia_producer_t* );
+}
+tmedia_producer_plugin_def_t;
+
+#define TMEDIA_DECLARE_PRODUCER tmedia_producer_t __producer__
+
+TINYMEDIA_API tmedia_producer_t* tmedia_producer_create(tmedia_type_t type, uint64_t session_id);
+TINYMEDIA_API int tmedia_producer_init(tmedia_producer_t* self);
+TINYMEDIA_API int tmedia_producer_set_enc_callback(tmedia_producer_t *self, tmedia_producer_enc_cb_f callback, const void* callback_data);
+TINYMEDIA_API int tmedia_producer_set_raw_callback(tmedia_producer_t *self, tmedia_producer_raw_cb_f callback, const void* callback_data);
+TINYMEDIA_API int tmedia_producer_set(tmedia_producer_t* self, const tmedia_param_t* param);
+TINYMEDIA_API int tmedia_producer_prepare(tmedia_producer_t *self, const tmedia_codec_t* codec);
+TINYMEDIA_API int tmedia_producer_start(tmedia_producer_t *self);
+TINYMEDIA_API int tmedia_producer_pause(tmedia_producer_t *self);
+TINYMEDIA_API int tmedia_producer_stop(tmedia_producer_t *self);
+TINYMEDIA_API int tmedia_producer_deinit(tmedia_producer_t* self);
+
+TINYMEDIA_API int tmedia_producer_plugin_register(const tmedia_producer_plugin_def_t* plugin);
+TINYMEDIA_API int tmedia_producer_plugin_unregister(const tmedia_producer_plugin_def_t* plugin);
+TINYMEDIA_API int tmedia_producer_plugin_unregister_by_type(tmedia_type_t type);
+
+TMEDIA_END_DECLS
+
+#endif /* TINYMEDIA_PRODUCER_H */
diff --git a/tinyMEDIA/include/tinymedia/tmedia_qos.h b/tinyMEDIA/include/tinymedia/tmedia_qos.h new file mode 100644 index 0000000..2c9416d --- /dev/null +++ b/tinyMEDIA/include/tinymedia/tmedia_qos.h @@ -0,0 +1,194 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tmedia_qos.h
+ * @brief RFC 3312 (Preconditions) implementation.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TINYMEDIA_QOS_H
+#define TINYMEDIA_QOS_H
+
+#include "tinymedia_config.h"
+
+#include "tinysdp/tsdp_message.h"
+
+#include "tsk_object.h"
+
+TMEDIA_BEGIN_DECLS
+
+#define TMEDIA_QOS_TLINE(self) ((tmedia_qos_tline_t*)(self))
+
+/** List of all supported statues*/
+typedef enum tmedia_qos_status_e
+{
+ //! current-status
+ tmedia_qos_status_curr,
+ //! desired-status
+ tmedia_qos_status_des,
+ //! confirm-status
+ tmedia_qos_status_conf
+}
+tmedia_qos_status_t;
+
+/** List of all supported precondition types */
+typedef enum tmedia_qos_ptype_e
+{
+ tmedia_qos_ptype_qos
+}
+tmedia_qos_ptype_t;
+
+/** List of all supported status types */
+typedef enum tmedia_qos_stype_e
+{
+ tmedia_qos_stype_none,/* not part of the RFC */
+
+ tmedia_qos_stype_segmented,
+ tmedia_qos_stype_e2e,
+}
+tmedia_qos_stype_t;
+
+/** strengths */
+typedef enum tmedia_qos_strength_e
+{
+ /* do no change the order (none -> optional -> manadatory) */
+ tmedia_qos_strength_none,
+ tmedia_qos_strength_failure,
+ tmedia_qos_strength_unknown,
+ tmedia_qos_strength_optional,
+ tmedia_qos_strength_mandatory
+}
+tmedia_qos_strength_t;
+
+/** directions */
+typedef enum tmedia_qos_direction_e
+{
+ tmedia_qos_direction_none = 0x01,
+ tmedia_qos_direction_send = (0x01 << 1),
+ tmedia_qos_direction_recv = (0x01 << 2),
+ tmedia_qos_direction_sendrecv = (tmedia_qos_direction_send | tmedia_qos_direction_recv)
+}
+tmedia_qos_direction_t;
+
+/* QoS table-line */
+typedef struct tmedia_qos_tline_s
+{
+ TSK_DECLARE_OBJECT;
+ tmedia_qos_stype_t type;
+}
+tmedia_qos_tline_t;
+#define TMEDIA_DECLARE_QOS_TLINE tmedia_qos_tline_t __tline__
+
+TINYMEDIA_API tmedia_qos_tline_t* tmedia_qos_tline_create(tmedia_qos_stype_t type, tmedia_qos_strength_t strength);
+TINYMEDIA_API tmedia_qos_stype_t tmedia_qos_get_type(const tsdp_header_M_t* m);
+TINYMEDIA_API tmedia_qos_tline_t* tmedia_qos_tline_from_sdp(const tsdp_header_M_t* m);
+TINYMEDIA_API int tmedia_qos_tline_to_sdp(const tmedia_qos_tline_t* self, tsdp_header_M_t* m);
+TINYMEDIA_API int tmedia_qos_tline_set_ro(tmedia_qos_tline_t* self, const tmedia_qos_tline_t* ro);
+TINYMEDIA_API tsk_bool_t tmedia_qos_tline_canresume(const tmedia_qos_tline_t* self);
+
+/* QoS table-line for E2E type*/
+typedef struct tmedia_qos_tline_e2e_s
+{
+ TMEDIA_DECLARE_QOS_TLINE;
+
+ /* RFC 3312 - 5.1 Generating an offer
+
+ Direction Current Desired Strength
+ ____________________________________
+ send no mandatory
+ recv no mandatory
+ */
+ struct{
+ unsigned current:1;
+ unsigned confirm:1;
+ tmedia_qos_strength_t strength;
+ } send;
+
+ struct{
+ unsigned current:1;
+ unsigned confirm:1;
+ tmedia_qos_strength_t strength;
+ } recv;
+}
+tmedia_qos_tline_e2e_t;
+
+TINYMEDIA_API tmedia_qos_tline_e2e_t* tmedia_qos_tline_e2e_create(tmedia_qos_strength_t strength);
+TINYMEDIA_API tmedia_qos_tline_e2e_t* tmedia_qos_tline_e2e_from_sdp(const tsdp_header_M_t* m);
+TINYMEDIA_API int tmedia_qos_tline_e2e_to_sdp(const tmedia_qos_tline_e2e_t* self, tsdp_header_M_t* m);
+TINYMEDIA_API int tmedia_qos_tline_e2e_set_ro(tmedia_qos_tline_e2e_t* self, const tmedia_qos_tline_e2e_t* ro);
+TINYMEDIA_API tsk_bool_t tmedia_qos_tline_e2e_canresume(const tmedia_qos_tline_e2e_t* self);
+
+/* QoS table-line for Segented type*/
+typedef struct tmedia_qos_tline_segmented_s
+{
+ TMEDIA_DECLARE_QOS_TLINE;
+
+ /* RFC 3312 - 5.1 Generating an offer
+ Direction Current Desired Strength
+ ______________________________________
+ local send no none
+ local recv no none
+ remote send no optional
+ remote recv no none
+ */
+ /* can be done in two lines but I prefer doing it like this (easier) */
+ struct{
+ unsigned current:1;
+ unsigned confirm:1;
+ tmedia_qos_strength_t strength;
+ } local_send;
+
+ struct{
+ unsigned current:1;
+ unsigned confirm:1;
+ tmedia_qos_strength_t strength;
+ } local_recv;
+
+ struct{
+ unsigned current:1;
+ unsigned confirm:1;
+ tmedia_qos_strength_t strength;
+ } remote_send;
+
+ struct{
+ unsigned current:1;
+ unsigned confirm:1;
+ tmedia_qos_strength_t strength;
+ } remote_recv;
+}
+tmedia_qos_tline_segmented_t;
+
+
+TINYMEDIA_API tmedia_qos_tline_segmented_t* tmedia_qos_tline_segmented_create(tmedia_qos_strength_t strength);
+TINYMEDIA_API tmedia_qos_tline_segmented_t* tmedia_qos_tline_segmented_from_sdp(const tsdp_header_M_t* m);
+TINYMEDIA_API int tmedia_qos_tline_segmented_to_sdp(const tmedia_qos_tline_segmented_t* self, tsdp_header_M_t* m);
+TINYMEDIA_API int tmedia_qos_tline_segmented_set_ro(tmedia_qos_tline_segmented_t* self, const tmedia_qos_tline_segmented_t* ro);
+TINYMEDIA_API tsk_bool_t tmedia_qos_tline_segmented_canresume(const tmedia_qos_tline_segmented_t* self);
+
+TINYMEDIA_GEXTERN const tsk_object_def_t *tmedia_qos_tline_segmented_def_t;
+TINYMEDIA_GEXTERN const tsk_object_def_t *tmedia_qos_tline_e2e_def_t;
+
+TMEDIA_END_DECLS
+
+#endif /* TINYMEDIA_QOS_H */
diff --git a/tinyMEDIA/include/tinymedia/tmedia_session.h b/tinyMEDIA/include/tinymedia/tmedia_session.h new file mode 100644 index 0000000..3143204 --- /dev/null +++ b/tinyMEDIA/include/tinymedia/tmedia_session.h @@ -0,0 +1,392 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tmedia_session.h
+ * @brief Base session object.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TINYMEDIA_SESSION_H
+#define TINYMEDIA_SESSION_H
+
+#include "tinymedia_config.h"
+
+#include "tinymedia/tmedia_codec.h"
+#include "tinymedia/tmedia_qos.h"
+#include "tinymedia/tmedia_params.h"
+
+#include "tinysdp/tsdp_message.h"
+
+#include "tinynet.h"
+
+#include "tsk_list.h"
+
+TMEDIA_BEGIN_DECLS
+
+#define TMEDIA_SESSION(self) ((tmedia_session_t*)(self))
+#define TMEDIA_SESSION_AUDIO(self) ((tmedia_session_audio_t*)(self))
+#define TMEDIA_SESSION_VIDEO(self) ((tmedia_session_video_t*)(self))
+#define TMEDIA_SESSION_MSRP(self) ((tmedia_session_msrp_t*)(self))
+
+/**Max number of plugins (session types) we can create */
+#define TMED_SESSION_MAX_PLUGINS 0x0F
+
+/** Base objct used for all media sessions */
+typedef struct tmedia_session_s
+{
+ TSK_DECLARE_OBJECT;
+
+ //! unique id
+ uint64_t id;
+ //! session type
+ tmedia_type_t type;
+ //! list of codecs managed by this session
+ tmedia_codecs_L_t* codecs;
+ //! negociated codec
+ tmedia_codecs_L_t* neg_codecs;
+ //! whether the ro have been prepared (up to the manager to update the value)
+ tsk_bool_t ro_changed;
+ //! whether the session have been initialized (up to the manager to update the value)
+ tsk_bool_t initialized;
+ //! whether the session have been prepared (up to the manager to update the value)
+ tsk_bool_t prepared;
+ //! QoS
+ tmedia_qos_tline_t* qos;
+ //! bandwidth level
+ tmedia_bandwidth_level_t bl;
+
+ struct{
+ tsdp_header_M_t* lo;
+ tsdp_header_M_t* ro;
+ } M;
+
+ //! plugin used to create the session
+ const struct tmedia_session_plugin_def_s* plugin;
+}
+tmedia_session_t;
+
+/** Virtual table used to define a session plugin */
+typedef struct tmedia_session_plugin_def_s
+{
+ //! object definition used to create an instance of the session
+ const tsk_object_def_t* objdef;
+
+ //! the type of the session
+ tmedia_type_t type;
+ //! the media name. e.g. "audio", "video", "message", "image" etc.
+ const char* media;
+
+ int (*set) (tmedia_session_t* , const tmedia_param_t*);
+ int (* prepare) (tmedia_session_t* );
+ int (* start) (tmedia_session_t* );
+ int (* pause) (tmedia_session_t* );
+ int (* stop) (tmedia_session_t* );
+
+ struct{ /* Special case */
+ int (* send_dtmf) (tmedia_session_t*, uint8_t );
+ } audio;
+
+ const tsdp_header_M_t* (* get_local_offer) (tmedia_session_t* );
+ /* return zero if can handle the ro and non-zero otherwise */
+ int (* set_remote_offer) (tmedia_session_t* , const tsdp_header_M_t* );
+}
+tmedia_session_plugin_def_t;
+
+TINYMEDIA_API int tmedia_session_init(tmedia_session_t* self, tmedia_type_t type);
+TINYMEDIA_API int tmedia_session_cmp(const tsk_object_t* sess1, const tsk_object_t* sess2);
+TINYMEDIA_API int tmedia_session_plugin_register(const tmedia_session_plugin_def_t* plugin);
+TINYMEDIA_API const tmedia_session_plugin_def_t* tmedia_session_plugin_find_by_media(const char* media);
+TINYMEDIA_API int tmedia_session_plugin_unregister(const tmedia_session_plugin_def_t* plugin);
+TINYMEDIA_API tmedia_session_t* tmedia_session_create(tmedia_type_t type);
+TINYMEDIA_API tmedia_codecs_L_t* tmedia_session_match_codec(tmedia_session_t* self, const tsdp_header_M_t* M);
+TINYMEDIA_API int tmedia_session_deinit(tmedia_session_t* self);
+typedef tsk_list_t tmedia_sessions_L_t; /**< List of @ref tmedia_session_t objects */
+#define TMEDIA_DECLARE_SESSION tmedia_session_t __session__
+
+/** Audio Session */
+typedef struct tmedia_session_audio_s
+{
+ TMEDIA_DECLARE_SESSION;
+}
+tmedia_session_audio_t;
+#define tmedia_session_audio_init(self) tmedia_session_init(TMEDIA_SESSION(self), tmed_sess_type_audio)
+TINYMEDIA_API int tmedia_session_audio_send_dtmf(tmedia_session_audio_t* self, uint8_t event);
+#define tmedia_session_audio_deinit(self) tmedia_session_deinit(TMEDIA_SESSION(self))
+#define tmedia_session_audio_create() tmedia_session_create(tmed_sess_type_audio)
+#define TMEDIA_DECLARE_SESSION_AUDIO tmedia_session_audio_t __session_audio__
+
+/** Video Session */
+typedef struct tmedia_session_video_s
+{
+ TMEDIA_DECLARE_SESSION;
+}
+tmedia_session_video_t;
+#define tmedia_session_video_init(self) tmedia_session_init(TMEDIA_SESSION(self), tmed_sess_type_video)
+#define tmedia_session_video_deinit(self) tmedia_session_deinit(TMEDIA_SESSION(self))
+#define tmedia_session_video_create() tmedia_session_create(tmed_sess_type_video)
+#define TMEDIA_DECLARE_SESSION_VIDEO tmedia_session_video_t __session_video__
+
+/** Msrp Session */
+struct tmedia_session_msrp_s;
+struct tmsrp_event_s;
+// use "struct tmsrp_event_s" instead of "tmsrp_event_t" to avoid linking aginst tinyMSRP
+typedef int (*tmedia_session_msrp_cb_f)(const struct tmsrp_event_s* event);
+typedef struct tmedia_session_msrp_s
+{
+ TMEDIA_DECLARE_SESSION;
+
+ struct {
+ tmedia_session_msrp_cb_f func;
+ const void* data;
+ } callback;
+
+ int (* send_file) (struct tmedia_session_msrp_s*, const char* path, va_list *app);
+ int (* send_message) (struct tmedia_session_msrp_s*, const void* data, tsk_size_t size, const tmedia_params_L_t *params);
+}
+tmedia_session_msrp_t;
+#define tmedia_session_msrp_init(self) tmedia_session_init(TMEDIA_SESSION(self), tmed_sess_type_msrp)
+#define tmedia_session_msrp_deinit(self) tmedia_session_deinit(TMEDIA_SESSION(self))
+#define tmedia_session_msrp_create() tmedia_session_create(tmed_sess_type_msrp)
+#define TMEDIA_DECLARE_SESSION_MSRP tmedia_session_msrp_t __session_msrp__
+
+/** Session manager */
+typedef struct tmedia_session_mgr_s
+{
+ TSK_DECLARE_OBJECT;
+
+ //! whether we are the offerer or not
+ tsk_bool_t offerer;
+ //! local IP address or FQDN
+ char* addr;
+ //! public IP address or FQDN
+ char* public_addr;
+ //! whether the @a addr is IPv6 or not (useful when @addr is a FQDN)
+ tsk_bool_t ipv6;
+
+ struct{
+ uint32_t lo_ver;
+ tsdp_message_t* lo;
+
+ int32_t ro_ver;
+ tsdp_message_t* ro;
+ } sdp;
+
+ tsk_bool_t started;
+ tsk_bool_t ro_changed;
+ tsk_bool_t state_changed;
+
+ //! session type
+ tmedia_type_t type;
+ //! QoS type
+ struct {
+ tmedia_qos_stype_t type;
+ tmedia_qos_strength_t strength;
+ } qos;
+
+ //! bandwidth level
+ tmedia_bandwidth_level_t bl;
+
+ /* NAT Traversal context */
+ tnet_nat_context_handle_t* natt_ctx;
+
+ //! List of all sessions
+ tmedia_sessions_L_t* sessions;
+
+ //! User's parameters used to confugure plugins
+ tmedia_params_L_t* params;
+}
+tmedia_session_mgr_t;
+
+typedef enum tmedia_session_param_type_e
+{
+ tmedia_sptype_null = 0,
+
+ tmedia_sptype_set,
+ //tmedia_sptype_get
+}
+tmedia_session_param_type_t;
+
+#define TMEDIA_SESSION_SET_PARAM(MEDIA_TYPE_ENUM, PLUGIN_TYPE_ENUM, VALUE_TYPE_ENUM, KEY_STR, VALUE) \
+ tmedia_sptype_set, (tmedia_type_t)MEDIA_TYPE_ENUM, (tmedia_param_plugin_type_t)PLUGIN_TYPE_ENUM, (tmedia_param_value_type_t)VALUE_TYPE_ENUM, \
+ (const char*)KEY_STR, TMEDIA_PARAM_VALUE_TYPE_IS_PTR(VALUE_TYPE_ENUM) ? (void*)VALUE : (void*)&VALUE
+//#define TMEDIA_SESSION_GET_PARAM(MEDIA_TYPE_ENUM, PLUGIN_TYPE_ENUM, VALUE_TYPE_ENUM, KEY_STR, VALUE_PTR) \
+// tmedia_sptype_get, (tmedia_type_t)MEDIA_TYPE_ENUM, (tmedia_param_plugin_type_t)PLUGIN_TYPE_ENUM, (tmedia_param_value_type_t)VALUE_TYPE_ENUM, \
+// (const char*)KEY_STR, (void**)&VALUE_PTR
+/* Manager */
+#define TMEDIA_SESSION_MANAGER_SET_INT32(KEY_STR, VALUE_INT32) TMEDIA_SESSION_SET_PARAM(tmedia_none, tmedia_ppt_manager, tmedia_pvt_int32, KEY_STR, VALUE_INT32)
+#define TMEDIA_SESSION_MANAGER_SET_POBJECT(KEY_STR, VALUE_PTR) TMEDIA_SESSION_SET_PARAM(tmedia_none, tmedia_ppt_manager, tmedia_pvt_pobject, KEY_STR, VALUE_PTR)
+#define TMEDIA_SESSION_MANAGER_SET_STR(KEY_STR, VALUE_STR) TMEDIA_SESSION_SET_PARAM(tmedia_none, tmedia_ppt_manager, tmedia_pvt_pchar, KEY_STR, VALUE_STR)
+#define TMEDIA_SESSION_MANAGER_SET_INT64(KEY_STR, VALUE_INT64) TMEDIA_SESSION_SET_PARAM(tmedia_none, tmedia_ppt_manager, tmedia_pvt_int64, KEY_STR, VALUE_INT64)
+//#define TMEDIA_SESSION_MANAGER_GET_INT32(KEY_STR, VALUE_PINT32) TMEDIA_SESSION_GET_PARAM(tmedia_none, tmedia_ppt_manager, tmedia_pvt_int32, KEY_STR, VALUE_PINT32)
+//#define TMEDIA_SESSION_MANAGER_GET_PVOID(KEY_STR, VALUE_PPTR) TMEDIA_SESSION_GET_PARAM(tmedia_none, tmedia_ppt_manager, tmedia_pvt_pobject, KEY_STR, VALUE_PPTR)
+//#define TMEDIA_SESSION_MANAGER_GET_STR(KEY_STR, VALUE_PSTR) TMEDIA_SESSION_GET_PARAM(tmedia_none, tmedia_ppt_manager, tmedia_pvt_pchar, KEY_STR, VALUE_PSTR)
+//#define TMEDIA_SESSION_MANAGER_GET_INT64(KEY_STR, VALUE_PINT64) TMEDIA_SESSION_GET_PARAM(tmedia_none, tmedia_ppt_manager, tmedia_pvt_int64, KEY_STR, VALUE_PINT64)
+/* Any Session */
+#define TMEDIA_SESSION_SET_INT32(MEDIA_TYPE_ENUM, KEY_STR, VALUE_INT32) TMEDIA_SESSION_SET_PARAM(MEDIA_TYPE_ENUM, tmedia_ppt_session, tmedia_pvt_int32, KEY_STR, VALUE_INT32)
+#define TMEDIA_SESSION_SET_POBJECT(MEDIA_TYPE_ENUM, KEY_STR, VALUE_PTR) TMEDIA_SESSION_SET_PARAM(MEDIA_TYPE_ENUM, tmedia_ppt_session, tmedia_pvt_pobject, KEY_STR, VALUE_PTR)
+#define TMEDIA_SESSION_SET_STR(MEDIA_TYPE_ENUM, KEY_STR, VALUE_STR) TMEDIA_SESSION_SET_PARAM(MEDIA_TYPE_ENUM, tmedia_ppt_session, tmedia_pvt_pchar, KEY_STR, VALUE_STR)
+#define TMEDIA_SESSION_SET_INT64(MEDIA_TYPE_ENUM, KEY_STR, VALUE_INT64) TMEDIA_SESSION_SET_PARAM(MEDIA_TYPE_ENUM, tmedia_ppt_session, tmedia_pvt_int64, KEY_STR, VALUE_INT64)
+//#define TMEDIA_SESSION_GET_INT32(MEDIA_TYPE_ENUM, KEY_STR, VALUE_PINT32) TMEDIA_SESSION_GET_PARAM(MEDIA_TYPE_ENUM, tmedia_ppt_session, tmedia_pvt_int32, KEY_STR, VALUE_PINT32)
+//#define TMEDIA_SESSION_GET_PVOID(MEDIA_TYPE_ENUM, KEY_STR, VALUE_PPTR) TMEDIA_SESSION_GET_PARAM(MEDIA_TYPE_ENUM, tmedia_ppt_session, tmedia_pvt_pobject, KEY_STR, VALUE_PPTR)
+//#define TMEDIA_SESSION_GET_STR(MEDIA_TYPE_ENUM, KEY_STR, VALUE_PSTR) TMEDIA_SESSION_GET_PARAM(MEDIA_TYPE_ENUM, tmedia_ppt_session, tmedia_pvt_pchar, KEY_STR, VALUE_PSTR)
+//#define TMEDIA_SESSION_GET_INT64(MEDIA_TYPE_ENUM, KEY_STR, VALUE_PINT64) TMEDIA_SESSION_GET_PARAM(MEDIA_TYPE_ENUM, tmedia_ppt_session, tmedia_pvt_int64, KEY_STR, VALUE_PINT64)
+/* Audio Session */
+#define TMEDIA_SESSION_AUDIO_SET_INT32(KEY_STR, VALUE_INT32) TMEDIA_SESSION_SET_INT32(tmedia_audio, KEY_STR, VALUE_INT32)
+#define TMEDIA_SESSION_AUDIO_SET_POBJECT(KEY_STR, VALUE_PTR) TMEDIA_SESSION_SET_POBJECT(tmedia_audio, KEY_STR, VALUE_PTR)
+#define TMEDIA_SESSION_AUDIO_SET_STR(KEY_STR, VALUE_STR) TMEDIA_SESSION_SET_STR(tmedia_audio, KEY_STR, VALUE_STR)
+#define TMEDIA_SESSION_AUDIO_SET_INT64(KEY_STR, VALUE_INT64) TMEDIA_SESSION_SET_INT64(tmedia_audio, KEY_STR, VALUE_INT64)
+//#define TMEDIA_SESSION_AUDIO_GET_INT32(KEY_STR, VALUE_PINT32) TMEDIA_SESSION_GET_INT32(tmedia_audio, KEY_STR, VALUE_PINT32)
+//#define TMEDIA_SESSION_AUDIO_GET_PVOID(KEY_STR, VALUE_PPTR) TMEDIA_SESSION_GET_PVOID(tmedia_audio, KEY_STR, VALUE_PPTR)
+//#define TMEDIA_SESSION_AUDIO_GET_STR(KEY_STR, VALUE_PSTR) TMEDIA_SESSION_GET_STR(tmedia_audio, KEY_STR, VALUE_PSTR)
+//#define TMEDIA_SESSION_AUDIO_GET_INT64(KEY_STR, VALUE_PINT64) TMEDIA_SESSION_GET_INT64(tmedia_audio, KEY_STR, VALUE_PINT64)
+/* Video Session */
+#define TMEDIA_SESSION_VIDEO_SET_INT32(KEY_STR, VALUE_INT32) TMEDIA_SESSION_SET_INT32(tmedia_video, KEY_STR, VALUE_INT32)
+#define TMEDIA_SESSION_VIDEO_SET_POBJECT(KEY_STR, VALUE_PTR) TMEDIA_SESSION_SET_POBJECT(tmedia_video, KEY_STR, VALUE_PTR)
+#define TMEDIA_SESSION_VIDEO_SET_STR(KEY_STR, VALUE_STR) TMEDIA_SESSION_SET_STR(tmedia_video, KEY_STR, VALUE_STR)
+#define TMEDIA_SESSION_VIDEO_SET_INT64(KEY_STR, VALUE_INT64) TMEDIA_SESSION_SET_INT64(tmedia_video, KEY_STR, VALUE_INT64)
+//#define TMEDIA_SESSION_VIDEO_GET_INT32(KEY_STR, VALUE_PINT32) TMEDIA_SESSION_GET_INT32(tmedia_video, KEY_STR, VALUE_PINT32)
+//#define TMEDIA_SESSION_VIDEO_GET_PVOID(KEY_STR, VALUE_PPTR) TMEDIA_SESSION_GET_PVOID(tmedia_video, KEY_STR, VALUE_PPTR)
+//#define TMEDIA_SESSION_VIDEO_GET_STR(KEY_STR, VALUE_PSTR) TMEDIA_SESSION_GET_STR(tmedia_video, KEY_STR, VALUE_PSTR)
+//#define TMEDIA_SESSION_VIDEO_GET_INT64(KEY_STR, VALUE_PINT64) TMEDIA_SESSION_GET_INT64(tmedia_video, KEY_STR, VALUE_PINT64)
+/* Msrp Session */
+#define TMEDIA_SESSION_MSRP_SET_INT32(KEY_STR, VALUE_INT32) TMEDIA_SESSION_SET_INT32(tmedia_msrp, KEY_STR, VALUE_INT32)
+#define TMEDIA_SESSION_MSRP_SET_POBJECT(KEY_STR, VALUE_PTR) TMEDIA_SESSION_SET_POBJECT(tmedia_msrp, KEY_STR, VALUE_PTR)
+#define TMEDIA_SESSION_MSRP_SET_STR(KEY_STR, VALUE_STR) TMEDIA_SESSION_SET_STR(tmedia_msrp, KEY_STR, VALUE_STR)
+#define TMEDIA_SESSION_MSRP_SET_INT64(KEY_STR, VALUE_INT64) TMEDIA_SESSION_SET_INT64(tmedia_msrp, KEY_STR, VALUE_INT64)
+//#define TMEDIA_SESSION_MSRP_GET_INT32(KEY_STR, VALUE_PINT32) TMEDIA_SESSION_GET_INT32(tmedia_msrp, KEY_STR, VALUE_PINT32)
+//#define TMEDIA_SESSION_MSRP_GET_PVOID(KEY_STR, VALUE_PPTR) TMEDIA_SESSION_GET_PVOID(tmedia_msrp, KEY_STR, VALUE_PPTR)
+//#define TMEDIA_SESSION_MSRP_GET_STR(KEY_STR, VALUE_PSTR) TMEDIA_SESSION_GET_STR(tmedia_msrp, KEY_STR, VALUE_PSTR)
+//#define TMEDIA_SESSION_MSRP_GET_INT64(KEY_STR, VALUE_PINT64) TMEDIA_SESSION_GET_INT64(tmedia_msrp, KEY_STR, VALUE_PINT64)
+/* Any Consumer */
+#define TMEDIA_SESSION_CONSUMER_SET_INT32(MEDIA_TYPE_ENUM, KEY_STR, VALUE_INT32) TMEDIA_SESSION_SET_PARAM(MEDIA_TYPE_ENUM, tmedia_ppt_consumer, tmedia_pvt_int32, KEY_STR, VALUE_INT32)
+#define TMEDIA_SESSION_CONSUMER_SET_POBJECT(MEDIA_TYPE_ENUM, KEY_STR, VALUE_PTR) TMEDIA_SESSION_SET_PARAM(MEDIA_TYPE_ENUM, tmedia_ppt_consumer, tmedia_pvt_pobject, KEY_STR, VALUE_PTR)
+#define TMEDIA_SESSION_CONSUMER_SET_STR(MEDIA_TYPE_ENUM, KEY_STR, VALUE_STR) TMEDIA_SESSION_SET_PARAM(MEDIA_TYPE_ENUM, tmedia_ppt_consumer, tmedia_pvt_pchar, KEY_STR, VALUE_STR)
+#define TMEDIA_SESSION_CONSUMER_SET_INT64(MEDIA_TYPE_ENUM, KEY_STR, VALUE_INT64) TMEDIA_SESSION_SET_PARAM(MEDIA_TYPE_ENUM, tmedia_ppt_consumer, tmedia_pvt_int64, KEY_STR, VALUE_INT64)
+//#define TMEDIA_SESSION_CONSUMER_GET_INT32(MEDIA_TYPE_ENUM, KEY_STR, VALUE_PINT32) TMEDIA_SESSION_GET_PARAM(MEDIA_TYPE_ENUM, tmedia_ppt_consumer, tmedia_pvt_int32, KEY_STR, VALUE_PINT32)
+//#define TMEDIA_SESSION_CONSUMER_GET_PVOID(MEDIA_TYPE_ENUM, KEY_STR, VALUE_PPTR) TMEDIA_SESSION_GET_PARAM(MEDIA_TYPE_ENUM, tmedia_ppt_consumer, tmedia_pvt_pobject, KEY_STR, VALUE_PPTR)
+//#define TMEDIA_SESSION_CONSUMER_GET_STR(MEDIA_TYPE_ENUM, KEY_STR, VALUE_PSTR) TMEDIA_SESSION_GET_PARAM(MEDIA_TYPE_ENUM, tmedia_ppt_consumer, tmedia_pvt_pchar, KEY_STR, VALUE_PSTR)
+//#define TMEDIA_SESSION_CONSUMER_GET_INT64(MEDIA_TYPE_ENUM, KEY_STR, VALUE_PINT64) TMEDIA_SESSION_GET_PARAM(MEDIA_TYPE_ENUM, tmedia_ppt_consumer, tmedia_pvt_int64, KEY_STR, VALUE_PINT64)
+/* Audio Consumer */
+#define TMEDIA_SESSION_AUDIO_CONSUMER_SET_INT32(KEY_STR, VALUE_INT32) TMEDIA_SESSION_CONSUMER_SET_INT32(tmedia_audio, KEY_STR, VALUE_INT32)
+#define TMEDIA_SESSION_AUDIO_CONSUMER_SET_POBJECT(KEY_STR, VALUE_PTR) TMEDIA_SESSION_CONSUMER_SET_POBJECT(tmedia_audio, KEY_STR, VALUE_PTR)
+#define TMEDIA_SESSION_AUDIO_CONSUMER_SET_STR(KEY_STR, VALUE_STR) TMEDIA_SESSION_CONSUMER_SET_STR(tmedia_audio, KEY_STR, VALUE_STR)
+#define TMEDIA_SESSION_AUDIO_CONSUMER_SET_INT64(KEY_STR, VALUE_INT64) TMEDIA_SESSION_CONSUMER_SET_INT64(tmedia_audio, KEY_STR, VALUE_INT64)
+//#define TMEDIA_SESSION_AUDIO_CONSUMER_GET_INT32(KEY_STR, VALUE_PINT32) TMEDIA_SESSION_CONSUMER_GET_INT32(tmedia_audio, KEY_STR, VALUE_PINT32)
+//#define TMEDIA_SESSION_AUDIO_CONSUMER_GET_PVOID(KEY_STR, VALUE_PPTR) TMEDIA_SESSION_CONSUMER_GET_PVOID(tmedia_audio, KEY_STR, VALUE_PPTR)
+//#define TMEDIA_SESSION_AUDIO_CONSUMER_GET_STR(KEY_STR, VALUE_PSTR) TMEDIA_SESSION_CONSUMER_GET_STR(tmedia_audio, KEY_STR, VALUE_PSTR)
+//#define TMEDIA_SESSION_AUDIO_CONSUMER_GET_INT64(KEY_STR, VALUE_PINT64) TMEDIA_SESSION_CONSUMER_GET_INT64(tmedia_audio, KEY_STR, VALUE_PINT64)
+/* Video Consumer */
+#define TMEDIA_SESSION_VIDEO_CONSUMER_SET_INT32(KEY_STR, VALUE_INT32) TMEDIA_SESSION_CONSUMER_SET_INT32(tmedia_video, KEY_STR, VALUE_INT32)
+#define TMEDIA_SESSION_VIDEO_CONSUMER_SET_POBJECT(KEY_STR, VALUE_PTR) TMEDIA_SESSION_CONSUMER_SET_POBJECT(tmedia_video, KEY_STR, VALUE_PTR)
+#define TMEDIA_SESSION_VIDEO_CONSUMER_SET_STR(KEY_STR, VALUE_STR) TMEDIA_SESSION_CONSUMER_SET_STR(tmedia_video, KEY_STR, VALUE_STR)
+#define TMEDIA_SESSION_VIDEO_CONSUMER_SET_INT64(KEY_STR, VALUE_INT64) TMEDIA_SESSION_CONSUMER_SET_INT64(tmedia_video, KEY_STR, VALUE_INT64)
+//#define TMEDIA_SESSION_VIDEO_CONSUMER_GET_INT32(KEY_STR, VALUE_PINT32) TMEDIA_SESSION_CONSUMER_GET_INT32(tmedia_video, KEY_STR, VALUE_PINT32)
+//#define TMEDIA_SESSION_VIDEO_CONSUMER_GET_PVOID(KEY_STR, VALUE_PPTR) TMEDIA_SESSION_CONSUMER_GET_PVOID(tmedia_video, KEY_STR, VALUE_PPTR)
+//#define TMEDIA_SESSION_VIDEO_CONSUMER_GET_STR(KEY_STR, VALUE_PSTR) TMEDIA_SESSION_CONSUMER_GET_STR(tmedia_video, KEY_STR, VALUE_PSTR)
+//#define TMEDIA_SESSION_VIDEO_CONSUMER_GET_INT64(KEY_STR, VALUE_PINT64) TMEDIA_SESSION_CONSUMER_GET_INT64(tmedia_video, KEY_STR, VALUE_PINT64)
+/* Msrp Consumer */
+#define TMEDIA_SESSION_MSRP_CONSUMER_SET_INT32(KEY_STR, VALUE_INT32) TMEDIA_SESSION_CONSUMER_SET_INT32(tmedia_msrp, KEY_STR, VALUE_INT32)
+#define TMEDIA_SESSION_MSRP_CONSUMER_SET_POBJECT(KEY_STR, VALUE_PTR) TMEDIA_SESSION_CONSUMER_SET_POBJECT(tmedia_msrp, KEY_STR, VALUE_PTR)
+#define TMEDIA_SESSION_MSRP_CONSUMER_SET_STR(KEY_STR, VALUE_STR) TMEDIA_SESSION_CONSUMER_SET_STR(tmedia_msrp, KEY_STR, VALUE_STR)
+#define TMEDIA_SESSION_MSRP_CONSUMER_SET_INT64(KEY_STR, VALUE_INT64) TMEDIA_SESSION_CONSUMER_SET_INT64(tmedia_msrp, KEY_STR, VALUE_INT64)
+//#define TMEDIA_SESSION_MSRP_CONSUMER_GET_INT32(KEY_STR, VALUE_PINT32) TMEDIA_SESSION_CONSUMER_GET_INT32(tmedia_msrp, KEY_STR, VALUE_PINT32)
+//#define TMEDIA_SESSION_MSRP_CONSUMER_GET_PVOID(KEY_STR, VALUE_PPTR) TMEDIA_SESSION_CONSUMER_GET_PVOID(tmedia_msrp, KEY_STR, VALUE_PPTR)
+//#define TMEDIA_SESSION_MSRP_CONSUMER_GET_STR(KEY_STR, VALUE_PSTR) TMEDIA_SESSION_CONSUMER_GET_STR(tmedia_msrp, KEY_STR, VALUE_PSTR)
+//#define TMEDIA_SESSION_MSRP_CONSUMER_GET_INT64(KEY_STR, VALUE_PINT64) TMEDIA_SESSION_CONSUMER_GET_INT64(tmedia_msrp, KEY_STR, VALUE_PINT64)
+/* Any Producer */
+#define TMEDIA_SESSION_PRODUCER_SET_INT32(MEDIA_TYPE_ENUM, KEY_STR, VALUE_INT32) TMEDIA_SESSION_SET_PARAM(MEDIA_TYPE_ENUM, tmedia_ppt_producer, tmedia_pvt_int32, KEY_STR, VALUE_INT32)
+#define TMEDIA_SESSION_PRODUCER_SET_POBJECT(MEDIA_TYPE_ENUM, KEY_STR, VALUE_PTR) TMEDIA_SESSION_SET_PARAM(MEDIA_TYPE_ENUM, tmedia_ppt_producer, tmedia_pvt_pobject, KEY_STR, VALUE_PTR)
+#define TMEDIA_SESSION_PRODUCER_SET_STR(MEDIA_TYPE_ENUM, KEY_STR, VALUE_STR) TMEDIA_SESSION_SET_PARAM(MEDIA_TYPE_ENUM, tmedia_ppt_producer, tmedia_pvt_pchar, KEY_STR, VALUE_STR)
+#define TMEDIA_SESSION_PRODUCER_SET_INT64(MEDIA_TYPE_ENUM, KEY_STR, VALUE_INT64) TMEDIA_SESSION_SET_PARAM(MEDIA_TYPE_ENUM, tmedia_ppt_producer, tmedia_pvt_int64, KEY_STR, VALUE_INT64)
+//#define TMEDIA_SESSION_PRODUCER_GET_INT32(MEDIA_TYPE_ENUM, KEY_STR, VALUE_PINT32) TMEDIA_SESSION_GET_PARAM(MEDIA_TYPE_ENUM, tmedia_ppt_producer, tmedia_pvt_int32, KEY_STR, VALUE_PINT32)
+//#define TMEDIA_SESSION_PRODUCER_GET_PVOID(MEDIA_TYPE_ENUM, KEY_STR, VALUE_PPTR) TMEDIA_SESSION_GET_PARAM(MEDIA_TYPE_ENUM, tmedia_ppt_producer, tmedia_pvt_pobject, KEY_STR, VALUE_PPTR)
+//#define TMEDIA_SESSION_PRODUCER_GET_STR(MEDIA_TYPE_ENUM, KEY_STR, VALUE_PSTR) TMEDIA_SESSION_GET_PARAM(MEDIA_TYPE_ENUM, tmedia_ppt_producer, tmedia_pvt_pchar, KEY_STR, VALUE_PSTR)
+//#define TMEDIA_SESSION_PRODUCER_GET_INT64(MEDIA_TYPE_ENUM, KEY_STR, VALUE_PINT64) TMEDIA_SESSION_GET_PARAM(MEDIA_TYPE_ENUM, tmedia_ppt_producer, tmedia_pvt_int64, KEY_STR, VALUE_PINT64)
+/* Audio Producer */
+#define TMEDIA_SESSION_AUDIO_PRODUCER_SET_INT32(KEY_STR, VALUE_INT32) TMEDIA_SESSION_PRODUCER_SET_INT32(tmedia_audio, KEY_STR, VALUE_INT32)
+#define TMEDIA_SESSION_AUDIO_PRODUCER_SET_POBJECT(KEY_STR, VALUE_PTR) TMEDIA_SESSION_PRODUCER_SET_POBJECT(tmedia_audio, KEY_STR, VALUE_PTR)
+#define TMEDIA_SESSION_AUDIO_PRODUCER_SET_STR(KEY_STR, VALUE_STR) TMEDIA_SESSION_AUDIO_PRODUCER_SET_STR(tmedia_audio, KEY_STR, VALUE_STR)
+#define TMEDIA_SESSION_AUDIO_PRODUCER_SET_INT64(KEY_STR, VALUE_INT64) TMEDIA_SESSION_PRODUCER_SET_INT64(tmedia_audio, KEY_STR, VALUE_INT64)
+//#define TMEDIA_SESSION_AUDIO_PRODUCER_GET_INT32(KEY_STR, VALUE_PINT32) TMEDIA_SESSION_PRODUCER_GET_INT32(tmedia_audio, KEY_STR, VALUE_PINT32)
+//#define TMEDIA_SESSION_AUDIO_PRODUCER_GET_PVOID(KEY_STR, VALUE_PPTR) TMEDIA_SESSION_PRODUCER_GET_PVOID(tmedia_audio, KEY_STR, VALUE_PPTR)
+//#define TMEDIA_SESSION_AUDIO_PRODUCER_GET_STR(KEY_STR, VALUE_PSTR) TMEDIA_SESSION_AUDIO_PRODUCER_GET_STR(tmedia_audio, KEY_STR, VALUE_PSTR)
+//#define TMEDIA_SESSION_AUDIO_PRODUCER_GET_INT64(KEY_STR, VALUE_PINT64) TMEDIA_SESSION_PRODUCER_GET_INT64(tmedia_audio, KEY_STR, VALUE_PINT64)
+/* Video Producer */
+#define TMEDIA_SESSION_VIDEO_PRODUCER_SET_INT32(KEY_STR, VALUE_INT32) TMEDIA_SESSION_PRODUCER_SET_INT32(tmedia_video, KEY_STR, VALUE_INT32)
+#define TMEDIA_SESSION_VIDEO_PRODUCER_SET_POBJECT(KEY_STR, VALUE_PTR) TMEDIA_SESSION_PRODUCER_SET_POBJECT(tmedia_video, KEY_STR, VALUE_PTR)
+#define TMEDIA_SESSION_VIDEO_PRODUCER_SET_STR(KEY_STR, VALUE_STR) TMEDIA_SESSION_AUDIO_PRODUCER_SET_STR(tmedia_video, KEY_STR, VALUE_STR)
+#define TMEDIA_SESSION_VIDEO_PRODUCER_SET_INT64(KEY_STR, VALUE_INT64) TMEDIA_SESSION_PRODUCER_SET_INT64(tmedia_video, KEY_STR, VALUE_INT64)
+//#define TMEDIA_SESSION_VIDEO_PRODUCER_GET_INT32(KEY_STR, VALUE_PINT32) TMEDIA_SESSION_PRODUCER_GET_INT32(tmedia_video, KEY_STR, VALUE_PINT32)
+//#define TMEDIA_SESSION_VIDEO_PRODUCER_GET_PVOID(KEY_STR, VALUE_PPTR) TMEDIA_SESSION_PRODUCER_GET_PVOID(tmedia_video, KEY_STR, VALUE_PPTR)
+//#define TMEDIA_SESSION_VIDEO_PRODUCER_GET_STR(KEY_STR, VALUE_PSTR) TMEDIA_SESSION_AUDIO_PRODUCER_GET_STR(tmedia_video, KEY_STR, VALUE_PSTR)
+//#define TMEDIA_SESSION_VIDEO_PRODUCER_GET_INT64(KEY_STR, VALUE_PINT64) TMEDIA_SESSION_PRODUCER_GET_INT64(tmedia_video, KEY_STR, VALUE_PINT64)
+/* Msrp Producer */
+#define TMEDIA_SESSION_MSRP_PRODUCER_SET_INT32(KEY_STR, VALUE_INT32) TMEDIA_SESSION_PRODUCER_SET_INT32(tmedia_msrp, KEY_STR, VALUE_INT32)
+#define TMEDIA_SESSION_MSRP_PRODUCER_SET_POBJECT(KEY_STR, VALUE_PTR) TMEDIA_SESSION_PRODUCER_SET_POBJECT(tmedia_msrp, KEY_STR, VALUE_PTR)
+#define TMEDIA_SESSION_MSRP_PRODUCER_SET_STR(KEY_STR, VALUE_STR) TMEDIA_SESSION_AUDIO_PRODUCER_SET_STR(tmedia_msrp, KEY_STR, VALUE_STR)
+#define TMEDIA_SESSION_MSRP_PRODUCER_SET_INT64(KEY_STR, VALUE_INT64) TMEDIA_SESSION_PRODUCER_SET_INT64(tmedia_msrp, KEY_STR, VALUE_INT64)
+//#define TMEDIA_SESSION_MSRP_PRODUCER_GET_INT32(KEY_STR, VALUE_PINT32) TMEDIA_SESSION_PRODUCER_GET_INT32(tmedia_msrp, KEY_STR, VALUE_PINT32)
+//#define TMEDIA_SESSION_MSRP_PRODUCER_GET_PVOID(KEY_STR, VALUE_PPTR) TMEDIA_SESSION_PRODUCER_GET_PVOID(tmedia_msrp, KEY_STR, VALUE_PPTR)
+//#define TMEDIA_SESSION_MSRP_PRODUCER_GET_STR(KEY_STR, VALUE_PSTR) TMEDIA_SESSION_AUDIO_PRODUCER_GET_STR(tmedia_msrp, KEY_STR, VALUE_PSTR)
+//#define TMEDIA_SESSION_MSRP_PRODUCER_GET_INT64(KEY_STR, VALUE_PINT64) TMEDIA_SESSION_PRODUCER_GET_INT64(tmedia_msrp, KEY_STR, VALUE_PINT64)
+
+
+#define TMEDIA_SESSION_SET_NULL() tmedia_sptype_null
+//#define TMEDIA_SESSION_GET_NULL() tmedia_sptype_null
+
+//#define TMEDIA_SESSION_SET_REMOTE_IP(IP_STR) tmedia_sptype_remote_ip, (const char*) IP_STR
+//#define TMEDIA_SESSION_SET_LOCAL_IP(IP_STR, IPv6_BOOL) tmedia_sptype_local_ip, (const char*) IP_STR, (tsk_bool_t)IPv6_BOOL
+//#define TMEDIA_SESSION_SET_RTCP(ENABLED_BOOL) tmedia_sptype_set_rtcp, (tsk_bool_t)ENABLED_BOOL
+//#define TMEDIA_SESSION_SET_QOS(TYPE_ENUM, STRENGTH_ENUM) tmedia_sptype_qos, (tmedia_qos_stype_t)TYPE_ENUM, (tmedia_qos_strength_t)STRENGTH_ENUM
+
+
+TINYMEDIA_API tmedia_session_mgr_t* tmedia_session_mgr_create(tmedia_type_t type, const char* addr, tsk_bool_t ipv6, tsk_bool_t offerer);
+TINYMEDIA_API tmedia_session_t* tmedia_session_mgr_find(tmedia_session_mgr_t* self, tmedia_type_t type);
+TINYMEDIA_API int tmedia_session_mgr_set_natt_ctx(tmedia_session_mgr_t* self, tnet_nat_context_handle_t* natt_ctx, const char* public_addr);
+TINYMEDIA_API int tmedia_session_mgr_start(tmedia_session_mgr_t* self);
+TINYMEDIA_API int tmedia_session_mgr_set(tmedia_session_mgr_t* self, ...);
+TINYMEDIA_API int tmedia_session_mgr_set_2(tmedia_session_mgr_t* self, va_list *app);
+TINYMEDIA_API int tmedia_session_mgr_set_3(tmedia_session_mgr_t* self, const tmedia_params_L_t* params);
+TINYMEDIA_API int tmedia_session_mgr_stop(tmedia_session_mgr_t* self);
+TINYMEDIA_API const tsdp_message_t* tmedia_session_mgr_get_lo(tmedia_session_mgr_t* self);
+TINYMEDIA_API int tmedia_session_mgr_set_ro(tmedia_session_mgr_t* self, const tsdp_message_t* sdp);
+TINYMEDIA_API int tmedia_session_mgr_hold(tmedia_session_mgr_t* self, tmedia_type_t type);
+TINYMEDIA_API tsk_bool_t tmedia_session_mgr_is_held(tmedia_session_mgr_t* self, tmedia_type_t type, tsk_bool_t local);
+TINYMEDIA_API int tmedia_session_mgr_resume(tmedia_session_mgr_t* self, tmedia_type_t type);
+TINYMEDIA_API int tmedia_session_mgr_add_media(tmedia_session_mgr_t* self, tmedia_type_t type);
+TINYMEDIA_API int tmedia_session_mgr_remove_media(tmedia_session_mgr_t* self, tmedia_type_t type);
+TINYMEDIA_API int tmedia_session_mgr_set_qos(tmedia_session_mgr_t* self, tmedia_qos_stype_t qos_type, tmedia_qos_strength_t qos_strength);
+TINYMEDIA_API tsk_bool_t tmedia_session_mgr_canresume(tmedia_session_mgr_t* self);
+TINYMEDIA_API tsk_bool_t tmedia_session_mgr_has_active_session(tmedia_session_mgr_t* self);
+TINYMEDIA_API int tmedia_session_mgr_send_dtmf(tmedia_session_mgr_t* self, uint8_t event);
+TINYMEDIA_API int tmedia_session_mgr_send_file(tmedia_session_mgr_t* self, const char* path, ...);
+TINYMEDIA_API int tmedia_session_mgr_send_message(tmedia_session_mgr_t* self, const void* data, tsk_size_t size, const tmedia_params_L_t *params);
+TINYMEDIA_API int tmedia_session_mgr_set_msrp_cb(tmedia_session_mgr_t* self, const void* callback_data, tmedia_session_msrp_cb_f func);
+
+
+TINYMEDIA_GEXTERN const tsk_object_def_t *tmedia_session_mgr_def_t;
+
+TMEDIA_END_DECLS
+
+#endif /* TINYMEDIA_SESSION_H */
diff --git a/tinyMEDIA/include/tinymedia/tmedia_session_dummy.h b/tinyMEDIA/include/tinymedia/tmedia_session_dummy.h new file mode 100644 index 0000000..58a0926 --- /dev/null +++ b/tinyMEDIA/include/tinymedia/tmedia_session_dummy.h @@ -0,0 +1,76 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tmedia_session_dummy.h
+ * @brief Dummy sessions used for test only.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TINYMEDIA_SESSION_DUMMY_H
+#define TINYMEDIA_SESSION_DUMMY_H
+
+#include "tinymedia_config.h"
+
+#include "tmedia_session.h"
+
+#include "tsk_object.h"
+
+TMEDIA_BEGIN_DECLS
+
+/** Dummy Audio session */
+typedef struct tmedia_session_daudio_s
+{
+ TMEDIA_DECLARE_SESSION_AUDIO;
+ uint16_t local_port;
+ uint16_t remote_port;
+}
+tmedia_session_daudio_t;
+
+/** Dummy Video session */
+typedef struct tmedia_session_dvideo_s
+{
+ TMEDIA_DECLARE_SESSION_VIDEO;
+ uint16_t local_port;
+ uint16_t remote_port;
+}
+tmedia_session_dvideo_t;
+
+/** Dummy Msrp session */
+typedef struct tmedia_session_dmsrp_s
+{
+ TMEDIA_DECLARE_SESSION_MSRP;
+ uint16_t local_port;
+ uint16_t remote_port;
+}
+tmedia_session_dmsrp_t;
+
+
+TINYMEDIA_GEXTERN const tmedia_session_plugin_def_t *tmedia_session_daudio_plugin_def_t;
+TINYMEDIA_GEXTERN const tmedia_session_plugin_def_t *tmedia_session_dvideo_plugin_def_t;
+TINYMEDIA_GEXTERN const tmedia_session_plugin_def_t *tmedia_session_dmsrp_plugin_def_t;
+
+TMEDIA_END_DECLS
+
+#endif /* TINYMEDIA_SESSION_DUMMY_H */
+
diff --git a/tinyMEDIA/include/tinymedia/tmedia_session_ghost.h b/tinyMEDIA/include/tinymedia/tmedia_session_ghost.h new file mode 100644 index 0000000..8ae1a21 --- /dev/null +++ b/tinyMEDIA/include/tinymedia/tmedia_session_ghost.h @@ -0,0 +1,53 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tmedia_session_ghost.h
+ * @brief Ghost session.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TINYMEDIA_SESSION_GHOST_H
+#define TINYMEDIA_SESSION_GHOST_H
+
+#include "tinymedia_config.h"
+
+#include "tmedia_session.h"
+
+#include "tsk_object.h"
+
+TMEDIA_BEGIN_DECLS
+
+/** Ghost session */
+typedef struct tmedia_session_ghost_s
+{
+ TMEDIA_DECLARE_SESSION;
+ char* media;
+}
+tmedia_session_ghost_t;
+
+TINYMEDIA_GEXTERN const tmedia_session_plugin_def_t *tmedia_session_ghost_plugin_def_t;
+
+TMEDIA_END_DECLS
+
+#endif /* TINYMEDIA_SESSION_GHOST_H */
diff --git a/tinyMEDIA/include/tinymedia/tmedia_vad.h b/tinyMEDIA/include/tinymedia/tmedia_vad.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tinyMEDIA/include/tinymedia/tmedia_vad.h diff --git a/tinyMEDIA/include/tinymedia_config.h b/tinyMEDIA/include/tinymedia_config.h new file mode 100644 index 0000000..26c2ba5 --- /dev/null +++ b/tinyMEDIA/include/tinymedia_config.h @@ -0,0 +1,78 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+#ifndef TINYMEDIA_CONFIG_H
+#define TINYMEDIA_CONFIG_H
+
+#ifdef __SYMBIAN32__
+#undef _WIN32 /* Because of WINSCW */
+#endif
+
+/* Windows (XP/Vista/7/CE and Windows Mobile) macro definition.
+*/
+#if defined(WIN32)|| defined(_WIN32) || defined(_WIN32_WCE)
+# define TMEDIA_UNDER_WINDOWS 1
+#endif
+
+#if (TMEDIA_UNDER_WINDOWS || defined(__SYMBIAN32__)) && defined(TINYMEDIA_EXPORTS)
+# define TINYMEDIA_API __declspec(dllexport)
+# define TINYMEDIA_GEXTERN __declspec(dllexport)
+#elif (TMEDIA_UNDER_WINDOWS || defined(__SYMBIAN32__)) /*&& defined(TINYMEDIA_IMPORTS)*/
+# define TINYMEDIA_API __declspec(dllimport)
+# define TINYMEDIA_GEXTERN __declspec(dllimport)
+#else
+# define TINYMEDIA_API
+# define TINYMEDIA_GEXTERN extern
+#endif
+
+/* Guards against C++ name mangling
+*/
+#ifdef __cplusplus
+# define TMEDIA_BEGIN_DECLS extern "C" {
+# define TMEDIA_END_DECLS }
+#else
+# define TMEDIA_BEGIN_DECLS
+# define TMEDIA_END_DECLS
+#endif
+
+/* Disable some well-known warnings
+*/
+#ifdef _MSC_VER
+# define _CRT_SECURE_NO_WARNINGS
+#endif
+
+/* Detecting C99 compilers
+ */
+#if (__STDC_VERSION__ == 199901L) && !defined(__C99__)
+# define __C99__
+#endif
+
+#include <stdint.h>
+#ifdef __SYMBIAN32__
+#include <stdlib.h>
+#endif
+
+#if HAVE_CONFIG_H
+ #include "../config.h"
+#endif
+
+#endif // TINYMEDIA_CONFIG_H
diff --git a/tinyMEDIA/ragel.sh b/tinyMEDIA/ragel.sh new file mode 100644 index 0000000..f8339f5 --- /dev/null +++ b/tinyMEDIA/ragel.sh @@ -0,0 +1,8 @@ +# Ragel generator
+# For more information about Ragel: http://www.complang.org/ragel/
+
+export OPTIONS="-C -L -T0"
+#export OPTIONS="-C -L -G2"
+
+# SDP Message parser
+ragel.exe $OPTIONS -o ./src/content/tmedia_content_cpim.c ./ragel/tmedia_content_cpim.rl
\ No newline at end of file diff --git a/tinyMEDIA/ragel/tmedia_content_cpim.rl b/tinyMEDIA/ragel/tmedia_content_cpim.rl new file mode 100644 index 0000000..c43f972 --- /dev/null +++ b/tinyMEDIA/ragel/tmedia_content_cpim.rl @@ -0,0 +1,243 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tmedia_content_cpim.c
+ * @brief Common Presence and Instant Messaging (CPIM): Message Format (RFC 3862)
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ */
+#include "tinymedia/content/tmedia_content_cpim.h"
+
+#include "tsk_debug.h"
+#include "tsk_memory.h"
+#include "tsk_string.h"
+#include "tsk_ragel_state.h"
+
+#include <string.h>
+
+/* RFC 3862 - 2. Overall Message Structure
+A complete message looks something like this:
+
+ m: Content-type: Message/CPIM
+ s:
+ h: (message-metadata-headers)
+ s:
+ e: (encapsulated MIME message-body)
+
+ The end of the message body is defined by the framing mechanism of
+ the protocol used. The tags 'm:', 's:', 'h:', 'e:', and 'x:' are not
+ part of the message format and are used here to indicate the
+ different parts of the message, thus:
+
+ m: MIME headers for the overall message
+ s: a blank separator line
+ h: message headers
+ e: encapsulated MIME object containing the message content
+ x: MIME security multipart message wrapper
+*/
+
+
+
+
+
+/***********************************
+* Ragel state machine.
+*/
+%%{
+ machine tmedia_machine_content_cpim;
+
+ # Includes
+ include tmedia_machine_utils "./ragel/tmedia_machine_utils.rl";
+
+ action tag{
+ tag_start = p;
+ }
+
+ action is_parsing_mime_headers{
+ parsing_mime_headers = tsk_true;
+ }
+
+ action is_parsing_message_headers{
+ parsing_mime_headers = tsk_false;
+ }
+
+ action parse_hname{
+ TSK_PARSER_SET_STRING(hname);
+ }
+
+ action parse_hvalue{
+ tmedia_content_header_t* header;
+ TSK_PARSER_SET_STRING(hvalue);
+ header = tmedia_content_header_create(hname, hvalue);
+ TSK_FREE(hname); TSK_FREE(hvalue);
+
+ if(parsing_mime_headers){
+ if(!TMEDIA_CONTENT_CPIM(self)->m_headers){
+ TMEDIA_CONTENT_CPIM(self)->m_headers = tsk_list_create();
+ }
+ tsk_list_push_back_data(TMEDIA_CONTENT_CPIM(self)->m_headers, (void**)&header);
+ }
+ else{
+ if(!TMEDIA_CONTENT_CPIM(self)->h_headers){
+ TMEDIA_CONTENT_CPIM(self)->h_headers = tsk_list_create();
+ }
+ tsk_list_push_back_data(TMEDIA_CONTENT_CPIM(self)->h_headers, (void**)&header);
+ }
+ }
+
+ action parse_e{
+ int len = (int)(p - tag_start);
+ if(len && tag_start){
+ if(TMEDIA_CONTENT_CPIM(self)->e){
+ TSK_OBJECT_SAFE_FREE(TMEDIA_CONTENT_CPIM(self)->e); \
+ }
+ TMEDIA_CONTENT_CPIM(self)->e = tsk_buffer_create(tag_start, len);
+ }
+ }
+
+ hname = token>tag %parse_hname;
+ hvalue = any*>tag %parse_hvalue;
+
+ Header = hname :>SP*:> ":" SP*<: hvalue :> CRLF;
+ m = Header+ >is_parsing_mime_headers;
+ s = CRLF;
+ h = Header+ >is_parsing_message_headers;
+ e = any*>tag %parse_e;
+
+ # Entry point
+ main := m s h s e;
+}%%
+
+
+static int tmedia_content_cpim_parse(tmedia_content_t* self, const void* in_data, tsk_size_t in_size)
+{
+ int cs = 0;
+ const char *p = in_data;
+ const char *pe = p + in_size;
+ const char *eof = pe;
+
+ const char *tag_start;
+
+ char* hname = tsk_null;
+ char* hvalue = tsk_null;
+ tsk_bool_t parsing_mime_headers = tsk_true;
+
+ %%write data;
+ %%write init;
+ %%write exec;
+
+ TSK_FREE(hname);
+ TSK_FREE(hvalue);
+
+ if( cs < %%{ write first_final; }%% ){
+ TSK_DEBUG_ERROR("Failed to parse CPIM content");
+ return -1;
+ }
+
+ return 0;
+}
+
+static tsk_buffer_t* tmedia_content_cpim_get_data(tmedia_content_t* self)
+{
+ tsk_buffer_t* data = tsk_buffer_create_null();
+ tmedia_content_cpim_t *cpim = TMEDIA_CONTENT_CPIM(self);
+ const tsk_list_item_t* item;
+ /*
+ m: Content-type: Message/CPIM
+ s:
+ h: (message-metadata-headers)
+ s:
+ e: (encapsulated MIME message-body)
+ x: MIME security multipart message wrapper
+ */
+ if(cpim->m_headers){
+ tsk_list_foreach(item, cpim->m_headers){
+ char* hstring = tmedia_content_header_tostring(TMEDIA_CONTENT_HEADER(item->data));
+ tsk_buffer_append_2(data, TSK_LIST_IS_LAST(cpim->m_headers, item) ? "%s\r\n\r\n" : "%s\r\n", hstring);
+ TSK_FREE(hstring);
+ }
+ }
+ if(cpim->h_headers){
+ tsk_list_foreach(item, cpim->h_headers){
+ char* hstring = tmedia_content_header_tostring(TMEDIA_CONTENT_HEADER(item->data));
+ tsk_buffer_append_2(data, TSK_LIST_IS_LAST(cpim->h_headers, item) ? "%s\r\n\r\n" : "%s\r\n", hstring);
+ TSK_FREE(hstring);
+ }
+ }
+ if(cpim->e){
+ tsk_buffer_append(data, TSK_BUFFER_DATA(cpim->e), TSK_BUFFER_SIZE(cpim->e));
+ }
+ if(cpim->x){
+ tsk_buffer_append(data, TSK_BUFFER_DATA(cpim->x), TSK_BUFFER_SIZE(cpim->x));
+ }
+
+ return data;
+}
+
+//=================================================================================================
+// object/plugin definitions
+//
+/* constructor */
+static tsk_object_t* tmedia_content_cpim_ctor(tsk_object_t * self, va_list * app)
+{
+ tmedia_content_cpim_t *cpim = self;
+ if(cpim){
+ /* init base: called by tmedia_content_create() */
+ /* init self */
+ }
+ return self;
+}
+/* destructor */
+static tsk_object_t* tmedia_content_cpim_dtor(tsk_object_t * self)
+{
+ tmedia_content_cpim_t *cpim = self;
+ if(cpim){
+ /* deinit base */
+ tmedia_content_deinit(TMEDIA_CONTENT(cpim));
+ /* deinit self */
+ TSK_OBJECT_SAFE_FREE(cpim->m_headers);
+ TSK_OBJECT_SAFE_FREE(cpim->h_headers);
+ TSK_OBJECT_SAFE_FREE(cpim->e);
+ TSK_OBJECT_SAFE_FREE(cpim->x);
+ }
+
+ return self;
+}
+/* object definition */
+static const tsk_object_def_t tmedia_content_cpim_def_s =
+{
+ sizeof(tmedia_content_cpim_t),
+ tmedia_content_cpim_ctor,
+ tmedia_content_cpim_dtor,
+ tsk_null,
+};
+/* plugin definition*/
+static const tmedia_content_plugin_def_t tmedia_content_cpim_plugin_def_s =
+{
+ &tmedia_content_cpim_def_s,
+
+ TMEDIA_CONTENT_CPIM_TYPE,
+ tmedia_content_cpim_parse,
+ tmedia_content_cpim_get_data
+};
+const tmedia_content_plugin_def_t *tmedia_content_cpim_plugin_def_t = &tmedia_content_cpim_plugin_def_s;
\ No newline at end of file diff --git a/tinyMEDIA/ragel/tmedia_machine_utils.rl b/tinyMEDIA/ragel/tmedia_machine_utils.rl new file mode 100644 index 0000000..e145384 --- /dev/null +++ b/tinyMEDIA/ragel/tmedia_machine_utils.rl @@ -0,0 +1,78 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+/**@file tmedia_machine_utils.rl
+ * @brief Ragel file.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+%%{
+
+ machine tmedia_machine_utils;
+
+ OCTET = "0x"[0-9A-Fa-f]+;
+ CHAR = 0x01..0x7f;
+ VCHAR = 0x21..0x7e;
+ ALPHA = 0x41..0x5a | 0x61..0x7a;
+ DIGIT = 0x30..0x39;
+ CTL = 0x00..0x1f | 0x7f;
+ HTAB = "\t";
+ LF = "\n";
+ CR = "\r";
+ SP = " ";
+ DQUOTE = "\"";
+ BIT = "0" | "1";
+ HEXDIG = DIGIT | "A"i | "B"i | "C"i | "D"i | "E"i | "F"i;
+ CRLF = CR LF;
+ WSP = SP | HTAB;
+ LWSP = ( WSP | ( CRLF WSP ) )*;
+ LWS = ( WSP* CRLF )? WSP+;
+ SWS = LWS?;
+ EQUAL = SWS "=" SWS;
+ LHEX = DIGIT | 0x61..0x66;
+ HCOLON = ( SP | HTAB )* ":" SWS;
+ separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\\" | DQUOTE | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HTAB;
+ STAR = SWS "*" SWS;
+ SLASH = SWS "/" SWS;
+ LPAREN = SWS "(" SWS;
+ RPAREN = SWS ")" SWS;
+ COMMA = SWS "," SWS;
+ SEMI = SWS ";" SWS;
+ COLON = SWS ":" SWS;
+ LAQUOT = SWS "<";
+ LDQUOT = SWS DQUOTE;
+ RAQUOT = ">" SWS;
+ RDQUOT = DQUOTE SWS;
+ UTF8_CONT = 0x80..0xbf;
+ ##### FIXME: UTF8_NONASCII up to 2bytes will fail on Android
+ UTF8_NONASCII = ( 0x80..0xff );
+ #UTF8_NONASCII = ( 0xc0..0xdf UTF8_CONT ) | ( 0xe0..0xef UTF8_CONT{2} ) | ( 0xf0..0xf7 UTF8_CONT{3} ) | ( 0xf8..0xfb UTF8_CONT{4} ) | ( 0xfc..0xfd UTF8_CONT{5} ); ctext = 0x21..0x27 | 0x2a..0x5b | 0x5d..0x7e | UTF8_NONASCII | LWS;
+ qvalue = ( "0" ( "." DIGIT{,3} )? ) | ( "1" ( "." "0"{,3} )? );
+ alphanum = ALPHA | DIGIT;
+ token = ( alphanum | "-" | "." | "!" | "%" | "*" | "_" | "+" | "`" | "'" | "~" )+;
+ ietf_token = token;
+ x_token = "x-"i token;
+ iana_token = token;
+ token_nodot = ( alphanum | "-" | "!" | "%" | "*" | "_" | "+" | "`" | "'" | "~" )+;
+ word = ( alphanum | "-" | "." | "!" | "%" | "*" | "_" | "+" | "`" | "'" | "~" | "(" | ")" | "<" | ">" | ":" | "\\" | DQUOTE | "/" | "[" | "]" | "?" | "{" | "}" )+;
+}%%
diff --git a/tinyMEDIA/src/content/tmedia_content.c b/tinyMEDIA/src/content/tmedia_content.c new file mode 100644 index 0000000..b3522b0 --- /dev/null +++ b/tinyMEDIA/src/content/tmedia_content.c @@ -0,0 +1,362 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tmedia_content.c
+ * @brief Base content object.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ */
+#include "tinymedia/content/tmedia_content.h"
+
+#include "tsk_memory.h"
+#include "tsk_string.h"
+#include "tsk_debug.h"
+
+#include <string.h>
+
+/**@defgroup tmedia_content_group Contents
+*/
+
+typedef struct tmedia_content_plugin_entry_s
+{
+ const char* type;
+ const tmedia_content_plugin_def_t* plugin;
+}
+tmedia_content_plugin_entry_t;
+
+/* pointer to all registered contents */
+tmedia_content_plugin_entry_t __tmedia_content_plugin_entries[TMEDIA_CONTENT_MAX_PLUGINS][1] = { tsk_null };
+
+
+int tmedia_content_plugin_register(const char* type, const tmedia_content_plugin_def_t* plugin)
+{
+ tsk_size_t i;
+ int a = sizeof(__tmedia_content_plugin_entries);
+ if(!plugin || !plugin){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ /* add or replace the plugin */
+ for(i = 0; i<TMEDIA_CONTENT_MAX_PLUGINS; i++){
+ if(!__tmedia_content_plugin_entries[i]->plugin || (__tmedia_content_plugin_entries[i]->plugin == plugin && tsk_striequals(type, __tmedia_content_plugin_entries[i]->type))){
+ __tmedia_content_plugin_entries[i]->type = type;
+ __tmedia_content_plugin_entries[i]->plugin = plugin;
+ return 0;
+ }
+ }
+
+
+ TSK_DEBUG_ERROR("There are already %d plugins.", TMEDIA_CONTENT_MAX_PLUGINS);
+ return -2;
+}
+
+int tmedia_content_plugin_unregister(const char* type, const tmedia_content_plugin_def_t* plugin)
+{
+ tsk_size_t i;
+ tsk_bool_t found = tsk_false;
+ if(!plugin){
+ TSK_DEBUG_ERROR("Invalid Parameter");
+ return -1;
+ }
+
+ /* find the plugin to unregister */
+ for(i = 0; i<TMEDIA_CONTENT_MAX_PLUGINS && __tmedia_content_plugin_entries[i]->plugin; i++){
+ if(__tmedia_content_plugin_entries[i]->plugin == plugin && tsk_striequals(type, __tmedia_content_plugin_entries[i]->type)){
+ __tmedia_content_plugin_entries[i]->type = tsk_null,
+ __tmedia_content_plugin_entries[i]->plugin = tsk_null;
+ found = tsk_true;
+ break;
+ }
+ }
+
+ /* compact */
+ if(found){
+ for(; i<(TMEDIA_CONTENT_MAX_PLUGINS - 1); i++){
+ if(__tmedia_content_plugin_entries[i+1]->plugin){
+ __tmedia_content_plugin_entries[i]->type = __tmedia_content_plugin_entries[i+1]->type,
+ __tmedia_content_plugin_entries[i]->plugin = __tmedia_content_plugin_entries[i+1]->plugin;
+ }
+ else{
+ break;
+ }
+ }
+ __tmedia_content_plugin_entries[i]->type = tsk_null,
+ __tmedia_content_plugin_entries[i]->plugin = tsk_null;
+ }
+ return (found ? 0 : -2);
+}
+
+int tmedia_content_plugin_unregister_all()
+{
+ tsk_size_t i;
+ for(i = 0; i<TMEDIA_CONTENT_MAX_PLUGINS && __tmedia_content_plugin_entries[i]->plugin; i++){
+ __tmedia_content_plugin_entries[i]->type = tsk_null,
+ __tmedia_content_plugin_entries[i]->plugin = tsk_null;
+ }
+ return 0;
+}
+
+tmedia_content_t* tmedia_content_create(const char* type)
+{
+ tmedia_content_t* content = tsk_null;
+ const tmedia_content_plugin_entry_t* entry;
+ tsk_size_t i = 0;
+
+ while(i < TMEDIA_CONTENT_MAX_PLUGINS){
+ entry = __tmedia_content_plugin_entries[i];
+ if(!entry->plugin || !entry->type){
+ break;
+ }
+ if(entry->plugin->objdef && tsk_striequals(entry->type, type)){
+ if((content = tsk_object_new(entry->plugin->objdef))){
+ content->plugin = entry->plugin;
+ content->type = entry->type;
+ return content;
+ }
+ }
+ ++i;
+ }
+
+ TSK_DEBUG_WARN("Failed to find content type (%s) will be added as dummy", type);
+ if(tmedia_content_dummy_plugin_def_t){
+ content = tsk_object_new(tmedia_content_dummy_plugin_def_t->objdef);
+ content->plugin = tmedia_content_dummy_plugin_def_t;
+ content->type = type;
+ }
+
+ return content;
+}
+
+tmedia_content_t* tmedia_content_parse(const void* data, tsk_size_t size, const char* type)
+{
+ tmedia_content_t* content = tmedia_content_create(type);
+ if(content){
+ if(content->plugin->parse){
+ int ret;
+ if((ret = content->plugin->parse(content, data, size))){
+ TSK_DEBUG_ERROR("Failed to parse the content(%d)", ret);
+ TSK_OBJECT_SAFE_FREE(content);
+ return tsk_null;
+ }
+ return content;
+ }
+ else{
+ TSK_DEBUG_ERROR("No parser function for this content (%s)", type);
+ TSK_OBJECT_SAFE_FREE(content);
+ return tsk_null;
+ }
+ }
+ else{
+ TSK_DEBUG_ERROR("Failed to to find content(%s)", type);
+ return tsk_null;
+ }
+}
+
+int tmedia_content_init(tmedia_content_t* self)
+{
+ if(!self || !self->plugin){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ return 0;
+}
+
+int tmedia_content_deinit(tmedia_content_t* self)
+{
+ if(!self || !self->plugin){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ return 0;
+}
+
+tsk_buffer_t* tmedia_content_get_data(tmedia_content_t* self)
+{
+ if(!self || !self->plugin){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_null;
+ }
+ return self->plugin->get_data(self);
+}
+
+
+
+
+static int tmedia_content_dummy_parse(tmedia_content_t* self, const void* in_data, tsk_size_t in_size)
+{
+ tmedia_content_dummy_t *dummy = TMEDIA_CONTENT_DUMMY(self);
+ if(!dummy || dummy->data){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ dummy->data = tsk_buffer_create(in_data, in_size);
+ return 0;
+}
+
+static tsk_buffer_t* tmedia_content_dummy_get_data(tmedia_content_t* self)
+{
+ return tsk_object_ref(TMEDIA_CONTENT_DUMMY(self)->data);
+}
+
+
+
+
+
+
+//=================================================================================================
+// object/plugin definitions
+//
+/* constructor */
+static tsk_object_t* tmedia_content_dummy_ctor(tsk_object_t * self, va_list * app)
+{
+ tmedia_content_dummy_t *dummy = self;
+ if(dummy){
+ /* init base: called by tmedia_content_create() */
+ /* init self */
+ }
+ return self;
+}
+/* destructor */
+static tsk_object_t* tmedia_content_dummy_dtor(tsk_object_t * self)
+{
+ tmedia_content_dummy_t *dummy = self;
+ if(dummy){
+ /* deinit base */
+ tmedia_content_deinit(TMEDIA_CONTENT(dummy));
+ /* deinit self */
+ TSK_OBJECT_SAFE_FREE(dummy->data);
+ }
+
+ return self;
+}
+/* object definition */
+static const tsk_object_def_t tmedia_content_dummy_def_s =
+{
+ sizeof(tmedia_content_dummy_t),
+ tmedia_content_dummy_ctor,
+ tmedia_content_dummy_dtor,
+ tsk_null,
+};
+/* plugin definition*/
+static const tmedia_content_plugin_def_t tmedia_content_dummy_plugin_def_s =
+{
+ &tmedia_content_dummy_def_s,
+
+ "dummy",
+ tmedia_content_dummy_parse,
+ tmedia_content_dummy_get_data
+};
+const tmedia_content_plugin_def_t *tmedia_content_dummy_plugin_def_t = &tmedia_content_dummy_plugin_def_s;
+
+
+
+//=================================================================================================
+// media content header
+//
+
+tmedia_content_header_t* tmedia_content_header_create(const char* name, const char* value)
+{
+ tmedia_content_header_t* header = tsk_object_new(tmedia_content_header_def_t);
+ const char* str;
+
+ if(!header){
+ TSK_DEBUG_ERROR("Failed to create new header object");
+ return tsk_null;
+ }
+ header->name = tsk_strdup(name);
+ if((str = strstr(value, ";"))){
+ header->value = tsk_strndup(value, (str - value));
+ header->params = tsk_params_fromstring((str + 1), ";", tsk_true);
+ }
+ else{
+ header->value = tsk_strdup(value);
+ }
+
+ return header;
+}
+
+int tmedia_content_header_deinit(tmedia_content_header_t* self)
+{
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ TSK_FREE(self->name);
+ TSK_FREE(self->value);
+ TSK_OBJECT_SAFE_FREE(self->params);
+
+ return 0;
+}
+
+char* tmedia_content_header_tostring(const tmedia_content_header_t* self)
+{
+ char* string = tsk_null;
+
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_null;
+ }
+
+ tsk_sprintf(&string, "%s: %s", self->name, self->value);
+ if(self->params){
+ const tsk_list_item_t* item;
+ tsk_list_foreach(item, self->params){
+ tsk_strcat_2(&string, ";%s=%s", TSK_PARAM(item->data)->name, TSK_PARAM(item->data)->value);
+ }
+ }
+
+ return string;
+}
+
+/* constructor */
+static tsk_object_t* tmedia_content_header_ctor(tsk_object_t * self, va_list * app)
+{
+ tmedia_content_header_t *header = self;
+ if(header){
+ }
+ return self;
+}
+/* destructor */
+static tsk_object_t* tmedia_content_header_dtor(tsk_object_t * self)
+{
+ tmedia_content_header_t *header = self;
+ if(header){
+ tmedia_content_header_deinit(header);
+ }
+
+ return self;
+}
+/* object definition */
+static const tsk_object_def_t tmedia_content_header_def_s =
+{
+ sizeof(tmedia_content_header_t),
+ tmedia_content_header_ctor,
+ tmedia_content_header_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tmedia_content_header_def_t = &tmedia_content_header_def_s;
diff --git a/tinyMEDIA/src/content/tmedia_content_cpim.c b/tinyMEDIA/src/content/tmedia_content_cpim.c new file mode 100644 index 0000000..66ec103 --- /dev/null +++ b/tinyMEDIA/src/content/tmedia_content_cpim.c @@ -0,0 +1,448 @@ +
+/* #line 1 "./ragel/tmedia_content_cpim.rl" */
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tmedia_content_cpim.c
+ * @brief Common Presence and Instant Messaging (CPIM): Message Format (RFC 3862)
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ */
+#include "tinymedia/content/tmedia_content_cpim.h"
+
+#include "tsk_debug.h"
+#include "tsk_memory.h"
+#include "tsk_string.h"
+#include "tsk_ragel_state.h"
+
+#include <string.h>
+
+/* RFC 3862 - 2. Overall Message Structure
+A complete message looks something like this:
+
+ m: Content-type: Message/CPIM
+ s:
+ h: (message-metadata-headers)
+ s:
+ e: (encapsulated MIME message-body)
+
+ The end of the message body is defined by the framing mechanism of
+ the protocol used. The tags 'm:', 's:', 'h:', 'e:', and 'x:' are not
+ part of the message format and are used here to indicate the
+ different parts of the message, thus:
+
+ m: MIME headers for the overall message
+ s: a blank separator line
+ h: message headers
+ e: encapsulated MIME object containing the message content
+ x: MIME security multipart message wrapper
+*/
+
+
+
+
+
+/***********************************
+* Ragel state machine.
+*/
+
+/* #line 129 "./ragel/tmedia_content_cpim.rl" */
+
+
+
+static int tmedia_content_cpim_parse(tmedia_content_t* self, const void* in_data, tsk_size_t in_size)
+{
+ int cs = 0;
+ const char *p = in_data;
+ const char *pe = p + in_size;
+ const char *eof = pe;
+
+ const char *tag_start;
+
+ char* hname = tsk_null;
+ char* hvalue = tsk_null;
+ tsk_bool_t parsing_mime_headers = tsk_true;
+
+
+/* #line 88 "./src/content/tmedia_content_cpim.c" */
+static const char _tmedia_machine_content_cpim_actions[] = {
+ 0, 1, 0, 1, 3, 1, 4, 1,
+ 5, 2, 0, 4, 2, 0, 5, 2,
+ 1, 0, 2, 2, 0
+};
+
+static const char _tmedia_machine_content_cpim_key_offsets[] = {
+ 0, 0, 14, 30, 32, 34, 35, 36,
+ 51, 52, 66, 82, 84, 86, 87, 88,
+ 103, 104, 104
+};
+
+static const char _tmedia_machine_content_cpim_trans_keys[] = {
+ 33, 37, 39, 126, 42, 43, 45, 46,
+ 48, 57, 65, 90, 95, 122, 32, 33,
+ 37, 39, 58, 126, 42, 43, 45, 46,
+ 48, 57, 65, 90, 95, 122, 32, 58,
+ 13, 32, 13, 10, 13, 33, 37, 39,
+ 126, 42, 43, 45, 46, 48, 57, 65,
+ 90, 95, 122, 10, 33, 37, 39, 126,
+ 42, 43, 45, 46, 48, 57, 65, 90,
+ 95, 122, 32, 33, 37, 39, 58, 126,
+ 42, 43, 45, 46, 48, 57, 65, 90,
+ 95, 122, 32, 58, 13, 32, 13, 10,
+ 13, 33, 37, 39, 126, 42, 43, 45,
+ 46, 48, 57, 65, 90, 95, 122, 10,
+ 0
+};
+
+static const char _tmedia_machine_content_cpim_single_lengths[] = {
+ 0, 4, 6, 2, 2, 1, 1, 5,
+ 1, 4, 6, 2, 2, 1, 1, 5,
+ 1, 0, 0
+};
+
+static const char _tmedia_machine_content_cpim_range_lengths[] = {
+ 0, 5, 5, 0, 0, 0, 0, 5,
+ 0, 5, 5, 0, 0, 0, 0, 5,
+ 0, 0, 0
+};
+
+static const char _tmedia_machine_content_cpim_index_offsets[] = {
+ 0, 0, 10, 22, 25, 28, 30, 32,
+ 43, 45, 55, 67, 70, 73, 75, 77,
+ 88, 90, 91
+};
+
+static const char _tmedia_machine_content_cpim_indicies[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 2, 3, 3, 3, 4, 3,
+ 3, 3, 3, 3, 3, 1, 5, 6,
+ 1, 8, 6, 7, 10, 9, 11, 1,
+ 12, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 1, 14, 1, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 1, 16,
+ 17, 17, 17, 18, 17, 17, 17, 17,
+ 17, 17, 1, 19, 20, 1, 22, 20,
+ 21, 24, 23, 25, 1, 26, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 1,
+ 28, 1, 29, 30, 0
+};
+
+static const char _tmedia_machine_content_cpim_trans_targs[] = {
+ 2, 0, 3, 2, 4, 3, 4, 5,
+ 6, 5, 6, 7, 8, 2, 9, 10,
+ 11, 10, 12, 11, 12, 13, 14, 13,
+ 14, 15, 16, 10, 17, 18, 18
+};
+
+static const char _tmedia_machine_content_cpim_trans_actions[] = {
+ 15, 0, 3, 0, 3, 0, 0, 1,
+ 9, 0, 5, 0, 0, 1, 0, 18,
+ 3, 0, 3, 0, 0, 1, 9, 0,
+ 5, 0, 0, 1, 0, 1, 0
+};
+
+static const char _tmedia_machine_content_cpim_eof_actions[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 12, 7
+};
+
+static const int tmedia_machine_content_cpim_start = 1;
+static const int tmedia_machine_content_cpim_first_final = 17;
+static const int tmedia_machine_content_cpim_error = 0;
+
+static const int tmedia_machine_content_cpim_en_main = 1;
+
+
+/* #line 146 "./ragel/tmedia_content_cpim.rl" */
+
+/* #line 180 "./src/content/tmedia_content_cpim.c" */
+ {
+ cs = tmedia_machine_content_cpim_start;
+ }
+
+/* #line 147 "./ragel/tmedia_content_cpim.rl" */
+
+/* #line 187 "./src/content/tmedia_content_cpim.c" */
+ {
+ int _klen;
+ unsigned int _trans;
+ const char *_acts;
+ unsigned int _nacts;
+ const char *_keys;
+
+ if ( p == pe )
+ goto _test_eof;
+ if ( cs == 0 )
+ goto _out;
+_resume:
+ _keys = _tmedia_machine_content_cpim_trans_keys + _tmedia_machine_content_cpim_key_offsets[cs];
+ _trans = _tmedia_machine_content_cpim_index_offsets[cs];
+
+ _klen = _tmedia_machine_content_cpim_single_lengths[cs];
+ if ( _klen > 0 ) {
+ const char *_lower = _keys;
+ const char *_mid;
+ const char *_upper = _keys + _klen - 1;
+ while (1) {
+ if ( _upper < _lower )
+ break;
+
+ _mid = _lower + ((_upper-_lower) >> 1);
+ if ( (*p) < *_mid )
+ _upper = _mid - 1;
+ else if ( (*p) > *_mid )
+ _lower = _mid + 1;
+ else {
+ _trans += (_mid - _keys);
+ goto _match;
+ }
+ }
+ _keys += _klen;
+ _trans += _klen;
+ }
+
+ _klen = _tmedia_machine_content_cpim_range_lengths[cs];
+ if ( _klen > 0 ) {
+ const char *_lower = _keys;
+ const char *_mid;
+ const char *_upper = _keys + (_klen<<1) - 2;
+ while (1) {
+ if ( _upper < _lower )
+ break;
+
+ _mid = _lower + (((_upper-_lower) >> 1) & ~1);
+ if ( (*p) < _mid[0] )
+ _upper = _mid - 2;
+ else if ( (*p) > _mid[1] )
+ _lower = _mid + 2;
+ else {
+ _trans += ((_mid - _keys)>>1);
+ goto _match;
+ }
+ }
+ _trans += _klen;
+ }
+
+_match:
+ _trans = _tmedia_machine_content_cpim_indicies[_trans];
+ cs = _tmedia_machine_content_cpim_trans_targs[_trans];
+
+ if ( _tmedia_machine_content_cpim_trans_actions[_trans] == 0 )
+ goto _again;
+
+ _acts = _tmedia_machine_content_cpim_actions + _tmedia_machine_content_cpim_trans_actions[_trans];
+ _nacts = (unsigned int) *_acts++;
+ while ( _nacts-- > 0 )
+ {
+ switch ( *_acts++ )
+ {
+ case 0:
+/* #line 72 "./ragel/tmedia_content_cpim.rl" */
+ {
+ tag_start = p;
+ }
+ break;
+ case 1:
+/* #line 76 "./ragel/tmedia_content_cpim.rl" */
+ {
+ parsing_mime_headers = tsk_true;
+ }
+ break;
+ case 2:
+/* #line 80 "./ragel/tmedia_content_cpim.rl" */
+ {
+ parsing_mime_headers = tsk_false;
+ }
+ break;
+ case 3:
+/* #line 84 "./ragel/tmedia_content_cpim.rl" */
+ {
+ TSK_PARSER_SET_STRING(hname);
+ }
+ break;
+ case 4:
+/* #line 88 "./ragel/tmedia_content_cpim.rl" */
+ {
+ tmedia_content_header_t* header;
+ TSK_PARSER_SET_STRING(hvalue);
+ header = tmedia_content_header_create(hname, hvalue);
+ TSK_FREE(hname); TSK_FREE(hvalue);
+
+ if(parsing_mime_headers){
+ if(!TMEDIA_CONTENT_CPIM(self)->m_headers){
+ TMEDIA_CONTENT_CPIM(self)->m_headers = tsk_list_create();
+ }
+ tsk_list_push_back_data(TMEDIA_CONTENT_CPIM(self)->m_headers, (void**)&header);
+ }
+ else{
+ if(!TMEDIA_CONTENT_CPIM(self)->h_headers){
+ TMEDIA_CONTENT_CPIM(self)->h_headers = tsk_list_create();
+ }
+ tsk_list_push_back_data(TMEDIA_CONTENT_CPIM(self)->h_headers, (void**)&header);
+ }
+ }
+ break;
+/* #line 307 "./src/content/tmedia_content_cpim.c" */
+ }
+ }
+
+_again:
+ if ( cs == 0 )
+ goto _out;
+ if ( ++p != pe )
+ goto _resume;
+ _test_eof: {}
+ if ( p == eof )
+ {
+ const char *__acts = _tmedia_machine_content_cpim_actions + _tmedia_machine_content_cpim_eof_actions[cs];
+ unsigned int __nacts = (unsigned int) *__acts++;
+ while ( __nacts-- > 0 ) {
+ switch ( *__acts++ ) {
+ case 0:
+/* #line 72 "./ragel/tmedia_content_cpim.rl" */
+ {
+ tag_start = p;
+ }
+ break;
+ case 5:
+/* #line 108 "./ragel/tmedia_content_cpim.rl" */
+ {
+ int len = (int)(p - tag_start);
+ if(len && tag_start){
+ if(TMEDIA_CONTENT_CPIM(self)->e){
+ TSK_OBJECT_SAFE_FREE(TMEDIA_CONTENT_CPIM(self)->e); \
+ }
+ TMEDIA_CONTENT_CPIM(self)->e = tsk_buffer_create(tag_start, len);
+ }
+ }
+ break;
+/* #line 341 "./src/content/tmedia_content_cpim.c" */
+ }
+ }
+ }
+
+ _out: {}
+ }
+
+/* #line 148 "./ragel/tmedia_content_cpim.rl" */
+
+ TSK_FREE(hname);
+ TSK_FREE(hvalue);
+
+ if( cs <
+/* #line 355 "./src/content/tmedia_content_cpim.c" */
+17
+/* #line 152 "./ragel/tmedia_content_cpim.rl" */
+ ){
+ TSK_DEBUG_ERROR("Failed to parse CPIM content");
+ return -1;
+ }
+
+ return 0;
+}
+
+static tsk_buffer_t* tmedia_content_cpim_get_data(tmedia_content_t* self)
+{
+ tsk_buffer_t* data = tsk_buffer_create_null();
+ tmedia_content_cpim_t *cpim = TMEDIA_CONTENT_CPIM(self);
+ const tsk_list_item_t* item;
+ /*
+ m: Content-type: Message/CPIM
+ s:
+ h: (message-metadata-headers)
+ s:
+ e: (encapsulated MIME message-body)
+ x: MIME security multipart message wrapper
+ */
+ if(cpim->m_headers){
+ tsk_list_foreach(item, cpim->m_headers){
+ char* hstring = tmedia_content_header_tostring(TMEDIA_CONTENT_HEADER(item->data));
+ tsk_buffer_append_2(data, TSK_LIST_IS_LAST(cpim->m_headers, item) ? "%s\r\n\r\n" : "%s\r\n", hstring);
+ TSK_FREE(hstring);
+ }
+ }
+ if(cpim->h_headers){
+ tsk_list_foreach(item, cpim->h_headers){
+ char* hstring = tmedia_content_header_tostring(TMEDIA_CONTENT_HEADER(item->data));
+ tsk_buffer_append_2(data, TSK_LIST_IS_LAST(cpim->h_headers, item) ? "%s\r\n\r\n" : "%s\r\n", hstring);
+ TSK_FREE(hstring);
+ }
+ }
+ if(cpim->e){
+ tsk_buffer_append(data, TSK_BUFFER_DATA(cpim->e), TSK_BUFFER_SIZE(cpim->e));
+ }
+ if(cpim->x){
+ tsk_buffer_append(data, TSK_BUFFER_DATA(cpim->x), TSK_BUFFER_SIZE(cpim->x));
+ }
+
+ return data;
+}
+
+//=================================================================================================
+// object/plugin definitions
+//
+/* constructor */
+static tsk_object_t* tmedia_content_cpim_ctor(tsk_object_t * self, va_list * app)
+{
+ tmedia_content_cpim_t *cpim = self;
+ if(cpim){
+ /* init base: called by tmedia_content_create() */
+ /* init self */
+ }
+ return self;
+}
+/* destructor */
+static tsk_object_t* tmedia_content_cpim_dtor(tsk_object_t * self)
+{
+ tmedia_content_cpim_t *cpim = self;
+ if(cpim){
+ /* deinit base */
+ tmedia_content_deinit(TMEDIA_CONTENT(cpim));
+ /* deinit self */
+ TSK_OBJECT_SAFE_FREE(cpim->m_headers);
+ TSK_OBJECT_SAFE_FREE(cpim->h_headers);
+ TSK_OBJECT_SAFE_FREE(cpim->e);
+ TSK_OBJECT_SAFE_FREE(cpim->x);
+ }
+
+ return self;
+}
+/* object definition */
+static const tsk_object_def_t tmedia_content_cpim_def_s =
+{
+ sizeof(tmedia_content_cpim_t),
+ tmedia_content_cpim_ctor,
+ tmedia_content_cpim_dtor,
+ tsk_null,
+};
+/* plugin definition*/
+static const tmedia_content_plugin_def_t tmedia_content_cpim_plugin_def_s =
+{
+ &tmedia_content_cpim_def_s,
+
+ TMEDIA_CONTENT_CPIM_TYPE,
+ tmedia_content_cpim_parse,
+ tmedia_content_cpim_get_data
+};
+const tmedia_content_plugin_def_t *tmedia_content_cpim_plugin_def_t = &tmedia_content_cpim_plugin_def_s;
\ No newline at end of file diff --git a/tinyMEDIA/src/content/tmedia_content_multipart.c b/tinyMEDIA/src/content/tmedia_content_multipart.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tinyMEDIA/src/content/tmedia_content_multipart.c diff --git a/tinyMEDIA/src/content/tmedia_content_sip_frag.c b/tinyMEDIA/src/content/tmedia_content_sip_frag.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tinyMEDIA/src/content/tmedia_content_sip_frag.c diff --git a/tinyMEDIA/src/tmedia.c b/tinyMEDIA/src/tmedia.c new file mode 100644 index 0000000..dd57b47 --- /dev/null +++ b/tinyMEDIA/src/tmedia.c @@ -0,0 +1,290 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tmedia.c
+ * @brief Media.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tinymedia/tmedia.h"
+
+#if 0
+
+#include "tsk_string.h"
+#include "tsk_memory.h"
+#include "tsk_debug.h"
+
+#define TMED_MAX_PLUGINS 10
+const tmedia_plugin_def_t* __tmedia_plugins[TMED_MAX_PLUGINS] = {0};
+
+
+tmedia_t* tmedia_create(const char* name, const char* host, tnet_socket_type_t socket_type)
+{
+ return tsk_object_new(TMEDIA_VA_ARGS(name, host, socket_type));
+}
+
+tmedia_t* tmedia_create_null()
+{
+ return tmedia_create(tsk_null, TNET_SOCKET_HOST_ANY, tnet_socket_type_invalid);
+}
+
+int tmedia_init(tmedia_t* self, const char* name)
+{
+ if(!self){
+ return -1;
+ }
+
+ tsk_strupdate(&self->name, name);
+
+ return 0;
+}
+
+int tmedia_deinit(tmedia_t* self)
+{
+ if(!self){
+ return -1;
+ }
+
+ TSK_FREE(self->name);
+ TSK_FREE(self->protocol);
+
+ return 0;
+}
+
+
+int tmedia_plugin_register(const tmedia_plugin_def_t* plugin)
+{
+ tsk_size_t i;
+ if(!plugin){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ for(i=0; i<TMED_MAX_PLUGINS; i++){
+ if(!__tmedia_plugins[i] || __tmedia_plugins[i] == plugin){
+ __tmedia_plugins[i] = plugin;
+ return 0;
+ }
+ }
+
+ TSK_DEBUG_ERROR("There are already %d plugins.", TMED_MAX_PLUGINS);
+ return -2;
+}
+
+tmedia_t* tmedia_factory_create(const char* name, const char* host, tnet_socket_type_t socket_type)
+{
+ tmedia_t* ret = tsk_null;
+ const tmedia_plugin_def_t* plugin;
+ tsk_size_t i = 0;
+
+ while((i < TMED_MAX_PLUGINS) && (plugin = __tmedia_plugins[i++])){
+ if(plugin->objdef && tsk_strequals(plugin->name, name)){
+ if((ret = tsk_object_new(plugin->objdef, name, host, socket_type))){
+ ret->plugin = plugin;
+ break;
+ }
+ }
+ }
+
+ return ret;
+}
+
+int tmedia_start(tmedia_t* self)
+{
+ if(!self || !self->plugin){
+ return -1;
+ }
+
+ if(!self->plugin->start){
+ return -2;
+ }
+ else{
+ return self->plugin->start(self);
+ }
+}
+int tmedia_pause(tmedia_t*self )
+{
+ if(!self || !self->plugin){
+ return -1;
+ }
+
+ if(!self->plugin->pause){
+ return -2;
+ }
+ else{
+ return self->plugin->pause(self);
+ }
+}
+int tmedia_stop(tmedia_t* self)
+{
+ if(!self || !self->plugin){
+ return -1;
+ }
+
+ if(!self->plugin->stop){
+ return -2;
+ }
+ else{
+ return self->plugin->stop(self);
+ }
+}
+
+// Only SDP headers
+const tsdp_header_M_t* tmedia_get_local_offer(tmedia_t* self, ...)
+{
+
+ if(!self || !self->plugin){
+ return tsk_null;
+ }
+
+ if(!self->plugin->get_local_offer){
+ return tsk_null;
+ }
+ else{
+ va_list ap;
+ const tsdp_header_M_t* M;
+ va_start(ap, self);
+ M = self->plugin->get_local_offer(self, &ap);
+ va_end(ap);
+ return M;
+ }
+}
+
+const tsdp_header_M_t* tmedia_get_negotiated_offer(tmedia_t* self)
+{
+ if(!self || !self->plugin){
+ return tsk_null;
+ }
+
+ if(!self->plugin->get_negotiated_offer){
+ return tsk_null;
+ }
+ else{
+ return self->plugin->get_negotiated_offer(self);
+ }
+}
+
+int tmedia_set_remote_offer(tmedia_t* self, const tsdp_message_t* offer)
+{
+ if(!self || !self->plugin){
+ return -1;
+ }
+
+ if(!self->plugin->set_remote_offer){
+ return -2;
+ }
+ else{
+ return self->plugin->set_remote_offer(self, offer);
+ }
+}
+
+int tmedia_perform(tmedia_t* self, tmedia_action_t action, ... )
+{
+ int ret = -1;
+
+ if(!self || !self->plugin){
+ return -1;
+ }
+
+ if(!self->plugin->perform){
+ return -2;
+ }
+ else{
+ const tsk_object_def_t* objdef;
+ tsk_param_t *param;
+ tsk_params_L_t* params;
+ va_list ap;
+
+ va_start(ap, action);
+ params = tsk_list_create();
+ while((objdef = va_arg(ap, const tsk_object_def_t*))){
+ if(objdef != tsk_param_def_t){ // sanity check
+ break;
+ }
+ if((param = tsk_object_new_2(objdef, &ap))){
+ tsk_params_add_param_2(¶ms, param);
+ TSK_OBJECT_SAFE_FREE(param);
+ }
+ }
+
+ // Perform
+ ret = self->plugin->perform(self, action, params);
+
+ TSK_OBJECT_SAFE_FREE(params);
+ va_end(ap);
+
+ return ret;
+ }
+}
+
+//========================================================
+// Media object definition
+//
+
+static void* tmedia_ctor(tsk_object_t *self, va_list * app)
+{
+ tmedia_t *media = self;
+ if(media){
+ const char* name = va_arg(*app, const char*);
+ const char* host = va_arg(*app, const char*);
+ tnet_socket_type_t socket_type = va_arg(*app, tnet_socket_type_t);
+
+ tmedia_init(media, name);
+ }
+ else{
+ TSK_DEBUG_ERROR("Failed to create new media.");
+ }
+ return self;
+}
+
+static void* tmedia_dtor(tsk_object_t *self)
+{
+ tmedia_t *media = self;
+ if(media){
+ tmedia_deinit(media);
+ }
+ else{
+ TSK_DEBUG_ERROR("Null media.");
+ }
+
+ return self;
+}
+
+static int tmedia_cmp(const tsk_object_t *obj1, const tsk_object_t *obj2)
+{
+ return -1;
+}
+
+static const tsk_object_def_t tmedia_def_s =
+{
+ sizeof(tmedia_t),
+ tmedia_ctor,
+ tmedia_dtor,
+ tmedia_cmp
+};
+
+const void *tmedia_def_t = &tmedia_def_s;
+
+#endif /* if 0 => FIXME: Remove this file */
+
diff --git a/tinyMEDIA/src/tmedia_codec.c b/tinyMEDIA/src/tmedia_codec.c new file mode 100644 index 0000000..d0f80ef --- /dev/null +++ b/tinyMEDIA/src/tmedia_codec.c @@ -0,0 +1,599 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tmedia_codec.c
+ * @brief Base codec object.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tinymedia/tmedia_codec.h"
+
+#include "tsk_string.h"
+#include "tsk_memory.h"
+#include "tsk_debug.h"
+
+/**@defgroup tmedia_codec_group Codecs
+*/
+
+/* pointer to all registered codecs */
+const tmedia_codec_plugin_def_t* __tmedia_codec_plugins[TMED_CODEC_MAX_PLUGINS] = {0};
+
+
+/*== Predicate function to find a codec object by format */
+static int __pred_find_codec_by_format(const tsk_list_item_t *item, const void *format)
+{
+ if(item && item->data){
+ return tsk_strcmp(((tmedia_codec_t *)item->data)->format, format);
+ }
+ return -1;
+}
+
+/*== Predicate function to find a codec object by negociated format */
+static int __pred_find_codec_by_neg_format(const tsk_list_item_t *item, const void *format)
+{
+ if(item && item->data){
+ return tsk_strcmp(((tmedia_codec_t *)item->data)->neg_format, format);
+ }
+ return -1;
+}
+
+/**@ingroup tmedia_codec_group
+* Initialize a Codec
+* @param self The codec to initialize. Could be any type of codec (e.g. @ref tmedia_codec_audio_t or @ref tmedia_codec_video_t).
+* @param type
+* @param name the name of the codec. e.g. "G.711u" or "G.711a" etc used in the sdp.
+* @param desc full description.
+* @param format the format. e.g. "0" for G.711.u or "8" for G.711a or "*" for MSRP.
+* @retval Zero if succeed and non-zero error code otherwise.
+*/
+int tmedia_codec_init(tmedia_codec_t* self, tmedia_type_t type, const char* name, const char* desc, const char* format)
+{
+ if(!self || tsk_strnullORempty(name)){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ self->type = type;
+ tsk_strupdate(&self->name, name);
+ tsk_strupdate(&self->desc,desc);
+ tsk_strupdate(&self->format, format);
+
+ return 0;
+}
+
+/**@ingroup tmedia_codec_group
+* Prepares a codec by opening it.
+* @param self The codec to open.
+* @retval Zero if succeed and non-zero error code otherwise.
+* @sa @ref tmedia_codec_close()
+*/
+int tmedia_codec_open(tmedia_codec_t* self)
+{
+ if(!self || !self->plugin){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if(self->opened){
+ TSK_DEBUG_WARN("Codec already opened");
+ return 0;
+ }
+
+ if(self->plugin->open){
+ int ret;
+ if((ret = self->plugin->open(self))){
+ TSK_DEBUG_ERROR("Failed to open [%s] codec", self->plugin->desc);
+ return ret;
+ }
+ else{
+ self->opened = tsk_true;
+ return 0;
+ }
+ }
+ else{
+ self->opened = tsk_true;
+ return 0;
+ }
+}
+
+/**@ingroup tmedia_codec_group
+* UnPrepares a codec by closing it.
+* @param self The codec to close.
+* @retval Zero if succeed and non-zero error code otherwise.
+* @sa @ref tmedia_codec_open()
+*/
+int tmedia_codec_close(tmedia_codec_t* self)
+{
+ if(!self || !self->plugin){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if(!self->opened){
+ TSK_DEBUG_WARN("Codec not opened");
+ return 0;
+ }
+
+ if(self->plugin->close){
+ int ret;
+
+ if((ret = self->plugin->close(self))){
+ TSK_DEBUG_ERROR("Failed to close [%s] codec", self->plugin->desc);
+ return ret;
+ }
+ else{
+ self->opened = tsk_false;
+ return 0;
+ }
+ }
+ else{
+ self->opened = tsk_false;
+ return 0;
+ }
+}
+
+/**@ingroup tmedia_codec_group
+* Generic function to compare two codecs.
+* @param codec1 The first codec to compare.
+* @param codec2 The second codec to compare.
+* @retval Returns an integral value indicating the relationship between the two codecs:
+* <0 : @a codec1 less than @a codec2.<br>
+* 0 : @a codec1 identical to @a codec2.<br>
+* >0 : @a codec1 greater than @a codec2.<br>
+*/
+int tmedia_codec_cmp(const tsk_object_t* codec1, const tsk_object_t* codec2)
+{
+ const tmedia_codec_t* _c1 = codec1;
+ const tmedia_codec_t* _c2 = codec2;
+
+ if((_c1 && _c2) && (_c1->type == _c2->type)){
+ /* Do not compare names. For example, H264 base profile 1.0 will have the
+ * same name than H264 base profile 3.0. */
+ return tsk_stricmp(_c1->format, _c2->format);
+ }
+ else{
+ return -1;
+ }
+}
+
+/**@ingroup tmedia_codec_group
+* Registers a codec plugin.
+* @param plugin the definition of the plugin.
+* @retval Zero if succeed and non-zero error code otherwise.
+* @sa @ref tmedia_codec_create()
+*/
+int tmedia_codec_plugin_register(const tmedia_codec_plugin_def_t* plugin)
+{
+ tsk_size_t i;
+ if(!plugin || tsk_strnullORempty(plugin->name) || tsk_strnullORempty(plugin->format)){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ /* add or replace the plugin */
+ for(i = 0; i<TMED_CODEC_MAX_PLUGINS; i++){
+ if(!__tmedia_codec_plugins[i] || (__tmedia_codec_plugins[i] == plugin)){
+ __tmedia_codec_plugins[i] = plugin;
+ return 0;
+ }
+ }
+
+ TSK_DEBUG_ERROR("There are already %d plugins.", TMED_CODEC_MAX_PLUGINS);
+ return -2;
+}
+
+/**@ingroup tmedia_codec_group
+* UnRegisters a codec plugin.
+* @param plugin the definition of the plugin.
+* @retval Zero if succeed and non-zero error code otherwise.
+*/
+int tmedia_codec_plugin_unregister(const tmedia_codec_plugin_def_t* plugin)
+{
+ tsk_size_t i;
+ tsk_bool_t found = tsk_false;
+ if(!plugin){
+ TSK_DEBUG_ERROR("Invalid Parameter");
+ return -1;
+ }
+
+ /* find the plugin to unregister */
+ for(i = 0; i<TMED_CODEC_MAX_PLUGINS && __tmedia_codec_plugins[i]; i++){
+ if(__tmedia_codec_plugins[i] == plugin){
+ __tmedia_codec_plugins[i] = tsk_null;
+ found = tsk_true;
+ break;
+ }
+ }
+
+ /* compact */
+ if(found){
+ for(; i<(TMED_CODEC_MAX_PLUGINS - 1); i++){
+ if(__tmedia_codec_plugins[i+1]){
+ __tmedia_codec_plugins[i] = __tmedia_codec_plugins[i+1];
+ }
+ else{
+ break;
+ }
+ }
+ __tmedia_codec_plugins[i] = tsk_null;
+ }
+ return (found ? 0 : -2);
+}
+
+/**@ingroup tmedia_codec_group
+* Creates a new codec using an already registered plugin.
+* @param format The format of the codec to create (e.g. "0" for PCMU or "8" for PCMA or "*" for MSRP)
+* @sa @ref tmedia_codec_plugin_register()
+*/
+tmedia_codec_t* tmedia_codec_create(const char* format)
+{
+ tmedia_codec_t* codec = tsk_null;
+ const tmedia_codec_plugin_def_t* plugin;
+ tsk_size_t i = 0;
+
+ while((i < TMED_CODEC_MAX_PLUGINS) && (plugin = __tmedia_codec_plugins[i++])){
+ if(plugin->objdef && tsk_striequals(plugin->format, format)){
+ if((codec = tsk_object_new(plugin->objdef))){
+ /* initialize the newly created codec */
+ codec->dyn = plugin->dyn;
+ codec->plugin = plugin;
+ codec->bl = tmedia_bl_medium;
+ switch(plugin->type){
+ case tmedia_audio:
+ { /* Audio codec */
+ tmedia_codec_audio_t* audio = TMEDIA_CODEC_AUDIO(codec);
+ tmedia_codec_audio_init(TMEDIA_CODEC(audio), plugin->name, plugin->desc, plugin->format);
+ break;
+ }
+ case tmedia_video:
+ { /* Video codec */
+ tmedia_codec_video_t* video = TMEDIA_CODEC_VIDEO(codec);
+ tmedia_codec_video_init(TMEDIA_CODEC(video), plugin->name, plugin->desc, plugin->format);
+ video->width = plugin->video.width;
+ video->height = plugin->video.height;
+ video->fps = plugin->video.fps;
+ break;
+ }
+ case tmedia_msrp:
+ { /* Msrp codec */
+ tmedia_codec_msrp_init(codec, plugin->name, plugin->desc);
+ break;
+ }
+ default:
+ { /* Any other codec */
+ tmedia_codec_init(codec, plugin->type, plugin->name, plugin->desc, plugin->format);
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ return codec;
+}
+
+/**@ingroup tmedia_codec_group
+* Gets the rtpmap attribute associated to this code.
+* @param self the codec for which to get the rtpmap attribute. Should be created using @ref tmedia_codec_create().
+* @retval rtpmap string (e.g. "AMR-WB/16000/2" or "H261/90000") if succeed and Null otherwise. It's up to the caller to free the
+* returned string.
+*/
+char* tmedia_codec_get_rtpmap(const tmedia_codec_t* self)
+{
+ char* rtpmap = tsk_null;
+
+ if(!self || !self->plugin){
+ TSK_DEBUG_ERROR("invalid parameter");
+ return tsk_null;
+ }
+ switch(self->type){
+ case tmedia_audio:
+ { /* audio codecs */
+ /* const tmedia_codec_audio_t* audioCodec = (const tmedia_codec_audio_t*)self; */
+ if(self->plugin->audio.channels > 0){
+ tsk_sprintf(&rtpmap, "%s %s/%d/%d", self->neg_format? self->neg_format : self->format, self->name, self->plugin->rate, self->plugin->audio.channels);
+ }
+ else{
+ tsk_sprintf(&rtpmap, "%s %s/%d", self->neg_format? self->neg_format : self->format, self->name, self->plugin->audio);
+ }
+ }
+ break;
+ case tmedia_video:
+ { /* video codecs */
+ /* const tmedia_codec_video_t* videoCodec = (const tmedia_codec_video_t*)self; */
+ tsk_sprintf(&rtpmap, "%s %s/%d", self->neg_format? self->neg_format : self->format, self->name, self->plugin->rate);
+ break;
+ }
+ /* all others */
+ default:
+ break;
+ }
+
+ return rtpmap;
+}
+
+/**@ingroup tmedia_codec_group
+* Gets the codec's fmtp attribute value.
+* @param self the codec for which to get the fmtp attribute. Should be created using @ref tmedia_codec_create().
+* @retval fmtp attribute string (e.g. "mode-set=0,2,5,7; mode-change-period=2; mode-change-neighbor=1"). It's up to the caller to free the
+* returned string.
+*/
+char* tmedia_codec_get_fmtp(const tmedia_codec_t* self)
+{
+ char* fmtp = tsk_null;
+
+ if(!self || !self->plugin){
+ TSK_DEBUG_ERROR("invalid parameter");
+ return tsk_null;
+ }
+
+ if(self->plugin->fmtp_get){ /* some codecs, like G711, won't produce fmtp */
+ fmtp = self->plugin->fmtp_get(self);
+ }
+
+ return fmtp;
+}
+
+/**@ingroup tmedia_codec_group
+* Indicates whether the codec can handle this fmtp.
+* @param self the codec to match aginst to.
+* @param fmtp the fmtp to match
+* @retval @a tsk_true if the codec can handle this fmtp and @a tsk_false otherwise
+*/
+tsk_bool_t tmedia_codec_match_fmtp(const tmedia_codec_t* self, const char* fmtp)
+{
+ /* checks */
+ if(!self || !self->plugin || !self->plugin->fmtp_match){
+ TSK_DEBUG_ERROR("invalid parameter");
+ return tsk_false;
+ }
+
+ /* if fmtp is null or empty -> always match */
+ if(tsk_strnullORempty(fmtp)){
+ return tsk_true;
+ }
+ else{
+ return self->plugin->fmtp_match(self, fmtp);
+ }
+}
+
+/**@ingroup tmedia_codec_group
+* Sets remote fmtp.
+* @param self codec for which to set the remote fmtp.
+* @param fmtp fmtp received from remote party (e.g. "mode-set=0,2,5,7; mode-change-period=2; mode-change-neighbor=1").
+* @retval Zero if succeed and non-zero error code otherwise.
+*/
+int tmedia_codec_set_remote_fmtp(tmedia_codec_t* self, const char* fmtp)
+{
+ if(!self || !self->plugin){
+ TSK_DEBUG_ERROR("invalid parameter");
+ return -1;
+ }
+
+ if(self->plugin->fmtp_set){
+ return self->plugin->fmtp_set(self, fmtp);
+ }
+ else{ /* some codecs, like G711, could ignore remote fmtp attribute */
+ return 0;
+ }
+}
+
+/**@ingroup tmedia_codec_group
+* Remove all codecs except the specified ones.
+* @param codecs the list of codecs from which to remove codecs.
+* @param codecs2keep the codecs which shall not be removed.
+* @retval zero if succeed (or nothing to do) and non-zero error code otherwise.
+*/
+int tmedia_codec_removeAll_exceptThese(tmedia_codecs_L_t* codecs, const tmedia_codecs_L_t * codecs2keep)
+{
+ tsk_list_item_t* item;
+ if(!codecs || !codecs2keep){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+again:
+ tsk_list_foreach(item, codecs){
+ if(!tsk_list_find_item_by_pred(codecs2keep, __pred_find_codec_by_format, ((tmedia_codec_t*)item->data)->format)){
+ tsk_list_remove_item(codecs, item);
+ goto again;
+ }
+ }
+ return 0;
+}
+
+/**@ingroup tmedia_codec_group
+* Serialize a list of codecs to sdp (m= line) message.<br>
+* Will add: fmt, rtpmap and fmtp.
+* @param codecs The list of codecs to convert
+* @param m The destination
+* @retval Zero if succeed and non-zero error code otherwise
+*/
+int tmedia_codec_to_sdp(const tmedia_codecs_L_t* codecs, tsdp_header_M_t* m)
+{
+ const tsk_list_item_t* item;
+ const tmedia_codec_t* codec;
+ char *fmtp, *rtpmap;
+ int ret;
+
+ if(!m){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ tsk_list_foreach(item, codecs){
+ codec = item->data;
+ /* add fmt */
+ if((ret = tsdp_header_M_add_fmt(m, codec->neg_format? codec->neg_format : codec->format))){
+ TSK_DEBUG_ERROR("Failed to add format");
+ return ret;
+ }
+ if(tsk_striequals(m->media, "audio") || tsk_striequals(m->media, "video")){
+ /* add rtpmap attributes */
+ if((rtpmap = tmedia_codec_get_rtpmap(codec))){
+ tsdp_header_M_add_headers(m,
+ TSDP_HEADER_A_VA_ARGS("rtpmap", rtpmap),
+ tsk_null);
+ TSK_FREE(rtpmap);
+ }
+ /* add fmtp attributes */
+ if((fmtp = tmedia_codec_get_fmtp(codec))){
+ char* temp = tsk_null;
+ tsk_sprintf(&temp, "%s %s", codec->neg_format? codec->neg_format : codec->format, fmtp);
+ tsdp_header_M_add_headers(m,
+ TSDP_HEADER_A_VA_ARGS("fmtp", temp),
+ tsk_null);
+ TSK_FREE(temp);
+ TSK_FREE(fmtp);
+ }
+ }
+ }
+ return 0;
+}
+
+/**@ingroup tmedia_codec_group
+* Finds a codec by format. If the codec has a dyn. payload type, then this function will also compare negociate formats.
+* @param codecs List of codecs from which to retrieve the matching codec.
+* @param format the format of the codec to find.
+* @retval Zero if succeed and non-zero error code otherwise.
+*/
+tmedia_codec_t* tmedia_codec_find_by_format(tmedia_codecs_L_t* codecs, const char* format)
+{
+ const tmedia_codec_t* codec = tsk_null;
+
+ if(!codecs || !format){
+ TSK_DEBUG_ERROR("Inalid parameter");
+ return tsk_null;
+ }
+
+ if((codec = tsk_list_find_object_by_pred(codecs, __pred_find_codec_by_format, format)) ||
+ (codec = tsk_list_find_object_by_pred(codecs, __pred_find_codec_by_neg_format, format))){
+ return tsk_object_ref((void*)codec);
+ }
+ else{
+ return tsk_null;
+ }
+}
+
+/**@ingroup tmedia_codec_group
+*/
+int tmedia_codec_parse_fmtp(const char* fmtp, unsigned* maxbr, unsigned* fps, unsigned *width, unsigned *height)
+{
+ char *copy, *pch;
+ tsk_bool_t found = tsk_false;
+
+ if(tsk_strnullORempty(fmtp)){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ copy = tsk_strdup(fmtp);
+ pch = strtok(copy, "; /");
+
+ while(pch){
+ unsigned div = 0;
+
+ if(sscanf(pch, "QCIF=%u", &div) == 1 && div){
+ *fps = 30/div;
+ *width = 176;
+ *height = 144;
+ found = tsk_true;
+ }
+ else if(sscanf(pch, "CIF=%u", &div) == 1 && div){
+ *fps = 30/div;
+ *width = 352;
+ *height = 288;
+ found = tsk_true;
+ }
+ else if(sscanf(pch, "SQCIF=%u", &div) == 1 && div){
+ *fps = 30/div;
+ *width = 128;
+ *height = 96;
+ found = tsk_true;
+ }
+ else if(sscanf(pch, "QVGA=%u", &div) == 1 && div){
+ *fps = 30/div;
+ *width = 320;
+ *height = 240;
+ found = tsk_true;
+ }
+ // to be continued
+
+ if(found){
+ //found = tsk_false;
+ pch = strtok(tsk_null, "; ");
+ while(pch){
+ if(sscanf(pch, "MaxBR=%u", maxbr) == 1){
+ //found = tsk_true;
+ break;
+ }
+ pch = strtok(tsk_null, "; /");
+ }
+ }
+
+ if(found){
+ break;
+ }
+
+ pch = strtok(tsk_null, "; /");
+ }
+
+ TSK_FREE(copy);
+
+ return found ? 0 : -2;
+}
+
+/**@ingroup tmedia_codec_group
+* DeInitialize a Codec.
+* @param self The codec to deinitialize. Could be any type of codec (e.g. @ref tmedia_codec_audio_t or @ref tmedia_codec_video_t).
+* @retval Zero if succeed and non-zero error code otherwise.
+*/
+int tmedia_codec_deinit(tmedia_codec_t* self)
+{
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if(self->opened){
+ tmedia_codec_close(self);
+ }
+
+ TSK_FREE(self->name);
+ TSK_FREE(self->desc);
+ TSK_FREE(self->format);
+ TSK_FREE(self->neg_format);
+
+ return 0;
+}
+
+int tmedia_codec_video_set_callback(tmedia_codec_video_t *self, tmedia_codec_video_rtpcb_f callback, const void* callback_data)
+{
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ self->callback = callback;
+ self->callback_data = callback_data;
+
+ return 0;
+}
\ No newline at end of file diff --git a/tinyMEDIA/src/tmedia_codec_dummy.c b/tinyMEDIA/src/tmedia_codec_dummy.c new file mode 100644 index 0000000..0390756 --- /dev/null +++ b/tinyMEDIA/src/tmedia_codec_dummy.c @@ -0,0 +1,365 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tmedia_codec_dummy.c
+ * @brief Dummy codecs used for test only.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tinymedia/tmedia_codec_dummy.h"
+
+#include "tsk_debug.h"
+
+//=================================================================================================
+// Dummy G.711u object definition
+//
+
+#define tmedia_codec_dpcmu_fmtp_get tsk_null
+#define tmedia_codec_dpcmu_fmtp_set tsk_null
+#define tmedia_codec_dpcmu_fmtp_encode tsk_null
+#define tmedia_codec_dpcmu_fmtp_decode tsk_null
+
+tsk_bool_t tmedia_codec_dpcmu_fmtp_match(const tmedia_codec_t* codec, const char* fmtp)
+{ /* always match */
+ return tsk_true;
+}
+
+/* constructor */
+static tsk_object_t* tmedia_codec_dpcmu_ctor(tsk_object_t * self, va_list * app)
+{
+ tmedia_codec_dpcmu_t *dpcmu = self;
+ if(dpcmu){
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ }
+ return self;
+}
+/* destructor */
+static tsk_object_t* tmedia_codec_dpcmu_dtor(tsk_object_t * self)
+{
+ tmedia_codec_dpcmu_t *dpcmu = self;
+ if(dpcmu){
+ /* deinit base */
+ tmedia_codec_audio_deinit(dpcmu);
+ /* deinit self */
+ }
+
+ return self;
+}
+/* object definition */
+static const tsk_object_def_t tmedia_codec_dpcmu_def_s =
+{
+ sizeof(tmedia_codec_dpcmu_t),
+ tmedia_codec_dpcmu_ctor,
+ tmedia_codec_dpcmu_dtor,
+ tmedia_codec_cmp,
+};
+/* plugin definition*/
+static const tmedia_codec_plugin_def_t tmedia_codec_dpcmu_plugin_def_s =
+{
+ &tmedia_codec_dpcmu_def_s,
+
+ tmedia_audio,
+ "G.711u",
+ "Dummy G.711u codec",
+ TMEDIA_CODEC_FORMAT_G711u,
+ tsk_false,
+ 8000, // rate
+
+ { /* audio */
+ 1, // channels
+ 20 // ptime
+ },
+
+ /* video */
+ {0},
+
+ tsk_null, // open
+ tsk_null, // close
+ tmedia_codec_dpcmu_fmtp_encode,
+ tmedia_codec_dpcmu_fmtp_decode,
+ tmedia_codec_dpcmu_fmtp_match,
+ tmedia_codec_dpcmu_fmtp_get,
+ tmedia_codec_dpcmu_fmtp_set
+};
+const tmedia_codec_plugin_def_t *tmedia_codec_dpcmu_plugin_def_t = &tmedia_codec_dpcmu_plugin_def_s;
+
+//=================================================================================================
+// Dummy G.711a object definition
+//
+
+#define tmedia_codec_dpcma_fmtp_get tsk_null
+#define tmedia_codec_dpcma_fmtp_set tsk_null
+#define tmedia_codec_dpcma_fmtp_encode tsk_null
+#define tmedia_codec_dpcma_fmtp_decode tsk_null
+
+tsk_bool_t tmedia_codec_dpcma_fmtp_match(const tmedia_codec_t* codec, const char* fmtp)
+{ /* always match */
+ return tsk_true;
+}
+
+/* constructor */
+static tsk_object_t* tmedia_codec_dpcma_ctor(tsk_object_t * self, va_list * app)
+{
+ tmedia_codec_dpcma_t *dpcma = self;
+ if(dpcma){
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ }
+ return self;
+}
+/* destructor */
+static tsk_object_t* tmedia_codec_dpcma_dtor(tsk_object_t * self)
+{
+ tmedia_codec_dpcma_t *dpcma = self;
+ if(dpcma){
+ /* deinit base */
+ tmedia_codec_audio_deinit(dpcma);
+ /* deinit self */
+ }
+
+ return self;
+}
+/* object definition */
+static const tsk_object_def_t tmedia_codec_dpcma_def_s =
+{
+ sizeof(tmedia_codec_dpcma_t),
+ tmedia_codec_dpcma_ctor,
+ tmedia_codec_dpcma_dtor,
+ tmedia_codec_cmp,
+};
+/* plugin definition*/
+static const tmedia_codec_plugin_def_t tmedia_codec_dpcma_plugin_def_s =
+{
+ &tmedia_codec_dpcma_def_s,
+
+ tmedia_audio,
+ "G.711a",
+ "Dummy G.711a codec",
+ TMEDIA_CODEC_FORMAT_G711a,
+ tsk_false,
+ 8000, // rate
+
+ { /* audio */
+ 1, // channels
+ 20 // ptime
+ },
+
+ /* video */
+ {0},
+
+ tsk_null, // open
+ tsk_null, // close
+ tmedia_codec_dpcma_fmtp_encode,
+ tmedia_codec_dpcma_fmtp_decode,
+ tmedia_codec_dpcma_fmtp_match,
+ tmedia_codec_dpcma_fmtp_get,
+ tmedia_codec_dpcma_fmtp_set
+};
+const tmedia_codec_plugin_def_t *tmedia_codec_dpcma_plugin_def_t = &tmedia_codec_dpcma_plugin_def_s;
+
+
+
+//=================================================================================================
+// Dummy H.263 object definition
+//
+
+tsk_size_t tmedia_codec_dh263_fmtp_encode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size)
+{
+ return 0;
+}
+
+tsk_size_t tmedia_codec_dh263_fmtp_decode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size, const tsk_object_t* proto_hdr)
+{
+ return 0;
+}
+
+tsk_bool_t tmedia_codec_dh263_fmtp_match(const tmedia_codec_t* codec, const char* fmtp)
+{
+ /* check whether we can match this fmtp with our local
+ * check size, maxbr, fps ...*/
+ return tsk_true;
+}
+
+char* tmedia_codec_dh263_fmtp_get(const tmedia_codec_t* self)
+{
+ return tsk_strdup("CIF=2/MaxBR=3840;QCIF=2/MaxBR=1920");
+}
+
+int tmedia_codec_dh263_fmtp_set(tmedia_codec_t* self, const char* fmtp)
+{
+ TSK_DEBUG_INFO("remote fmtp=%s", fmtp);
+ return 0;
+}
+
+/* constructor */
+static tsk_object_t* tmedia_codec_dh263_ctor(tsk_object_t * self, va_list * app)
+{
+ tmedia_codec_dh263_t *dh263 = self;
+ if(dh263){
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ }
+ return self;
+}
+/* destructor */
+static tsk_object_t* tmedia_codec_dh263_dtor(tsk_object_t * self)
+{
+ tmedia_codec_dh263_t *dh263 = self;
+ if(dh263){
+ /* deinit base */
+ tmedia_codec_video_deinit(dh263);
+ /* deinit self */
+ }
+
+ return self;
+}
+/* object definition */
+static const tsk_object_def_t tmedia_codec_dh263_def_s =
+{
+ sizeof(tmedia_codec_dh263_t),
+ tmedia_codec_dh263_ctor,
+ tmedia_codec_dh263_dtor,
+ tmedia_codec_cmp,
+};
+/* plugin definition*/
+static const tmedia_codec_plugin_def_t tmedia_codec_dh263_plugin_def_s =
+{
+ &tmedia_codec_dh263_def_s,
+
+ tmedia_video,
+ "H263",
+ "Dummy H.263-1996 codec",
+ TMEDIA_CODEC_FORMAT_H263,
+ tsk_false,
+ 90000, // rate
+
+ /* audio */
+ { 0 },
+
+ /* video */
+ {176, 144},
+
+ tsk_null, // open
+ tsk_null, // close
+ tmedia_codec_dh263_fmtp_encode,
+ tmedia_codec_dh263_fmtp_decode,
+ tmedia_codec_dh263_fmtp_match,
+ tmedia_codec_dh263_fmtp_get,
+ tmedia_codec_dh263_fmtp_set
+};
+const tmedia_codec_plugin_def_t *tmedia_codec_dh263_plugin_def_t = &tmedia_codec_dh263_plugin_def_s;
+
+
+
+
+//=================================================================================================
+// Dummy H.264 (Base profile 10) object definition
+//
+
+tsk_size_t tmedia_codec_dh264_fmtp_encode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size)
+{
+ return 0;
+}
+
+tsk_size_t tmedia_codec_dh264_fmtp_decode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size, const tsk_object_t* proto_hdr)
+{
+ return 0;
+}
+
+tsk_bool_t tmedia_codec_dh264_fmtp_match(const tmedia_codec_t* codec, const char* fmtp)
+{
+ /* check whether we can match this fmtp with our local
+ * check size, maxbr, fps, profile-level-id, packetization-mode ...*/
+ return tsk_true;
+}
+
+char* tmedia_codec_dh264_fmtp_get(const tmedia_codec_t* self)
+{
+ return tsk_strdup("profile-level-id=42A01E;sprop-parameter-sets=Z0IACpZTBYmI,aMljiA==");
+}
+
+int tmedia_codec_dh264_fmtp_set(tmedia_codec_t* self, const char* fmtp)
+{
+ TSK_DEBUG_INFO("remote fmtp=%s", fmtp);
+ return 0;
+}
+
+/* constructor */
+static tsk_object_t* tmedia_codec_dh264_ctor(tsk_object_t * self, va_list * app)
+{
+ tmedia_codec_dh264_t *dh264 = self;
+ if(dh264){
+ /* init base: called by tmedia_codec_create() */
+ /* init self */
+ }
+ return self;
+}
+/* destructor */
+static tsk_object_t* tmedia_codec_dh264_dtor(tsk_object_t * self)
+{
+ tmedia_codec_dh264_t *dh264 = self;
+ if(dh264){
+ /* deinit base */
+ tmedia_codec_video_deinit(dh264);
+ /* deinit self */
+ }
+
+ return self;
+}
+/* object definition */
+static const tsk_object_def_t tmedia_codec_dh264_def_s =
+{
+ sizeof(tmedia_codec_dh264_t),
+ tmedia_codec_dh264_ctor,
+ tmedia_codec_dh264_dtor,
+ tmedia_codec_cmp,
+};
+/* plugin definition*/
+static const tmedia_codec_plugin_def_t tmedia_codec_dh264_plugin_def_s =
+{
+ &tmedia_codec_dh264_def_s,
+
+ tmedia_video,
+ "H264",
+ "Dummy H.264 (base profile 10) codec",
+ TMEDIA_CODEC_FORMAT_H264_BP10,
+ tsk_true,
+ 90000, // rate
+
+ /* audio */
+ { 0 },
+
+ /* video */
+ {176, 144},
+
+ tsk_null, // open
+ tsk_null, // close
+ tmedia_codec_dh264_fmtp_encode,
+ tmedia_codec_dh264_fmtp_decode,
+ tmedia_codec_dh264_fmtp_match,
+ tmedia_codec_dh264_fmtp_get,
+ tmedia_codec_dh264_fmtp_set
+};
+const tmedia_codec_plugin_def_t *tmedia_codec_dh264_plugin_def_t = &tmedia_codec_dh264_plugin_def_s;
diff --git a/tinyMEDIA/src/tmedia_common.c b/tinyMEDIA/src/tmedia_common.c new file mode 100644 index 0000000..49724bf --- /dev/null +++ b/tinyMEDIA/src/tmedia_common.c @@ -0,0 +1,184 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tmedia_common.c
+ * @brief Common functions and definitions.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tinymedia/tmedia_common.h"
+
+#include "tinymedia/tmedia_session.h"
+
+#include "tsk_debug.h"
+
+#include <stdlib.h> /* atoi() */
+
+tmedia_type_t tmedia_type_from_sdp(const tsdp_message_t* sdp)
+{
+ tmedia_type_t type = tmedia_none;
+ const tsdp_header_M_t* M;
+ tsk_size_t index = 0;
+ const tmedia_session_plugin_def_t* plugin;
+
+ if(!sdp){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tmedia_none;
+ }
+
+ while((M = (const tsdp_header_M_t*)tsdp_message_get_headerAt(sdp, tsdp_htype_M, index++))){
+ if(M->port && (plugin = tmedia_session_plugin_find_by_media(M->media))){
+ type |= plugin->type;
+ }
+ }
+ return type;
+}
+
+
+int tmedia_parse_rtpmap(const char* rtpmap, char** name, int32_t* rate, int32_t* channels)
+{
+ /* e.g. AMR-WB/16000/2 */
+
+ int len;
+ int index, pos = 0;
+
+ if(tsk_strnullORempty(rtpmap)){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ *name = tsk_null;
+ *rate = *channels = 0;
+ len = tsk_strlen(rtpmap);
+
+ /* name */
+ if((index = tsk_strindexOf(rtpmap, len, "/")) != -1){
+ *name = tsk_strndup(rtpmap, index);
+ len -= (index + 1), pos = (index + 1);
+ /* rate */
+ if(len>0){
+ if((index = tsk_strindexOf((rtpmap + pos), len, "/")) != -1){
+ *rate = atoi(&rtpmap[pos]);
+ len -= (index + 1), pos += (index + 1);
+ /* channels */
+ if(len>0){
+ *channels = atoi(&rtpmap[pos]);
+ }
+ }
+ else{
+ *rate = atoi(&rtpmap[pos]);
+ }
+ }
+ }
+ else{
+ *name = tsk_strdup(rtpmap);
+ }
+
+ return 0;
+
+ ///* e.g. AMR-WB/16000/2 */
+ //if(sscanf(rtpmap, "%*s/%*d/%*d") != EOF){
+ // int index = tsk_strindexOf(rtpmap, len, "/");
+ // *name = tsk_strndup(rtpmap, index);
+ // sscanf(&rtpmap[index+1], "%d/%d", rate, channels);
+ // return 0;
+ //}
+ ///* e.g. AMR-WB/16000 */
+ //else if(sscanf(rtpmap, "%*s/%*d") != EOF){
+ // int index = tsk_strindexOf(rtpmap, len, "/");
+ // *name = tsk_strndup(rtpmap, index);
+ // *rate = atoi(&rtpmap[index+1]);
+ // return 0;
+ //}
+ ///* e.g. AMR-WB */
+ //else if(sscanf(rtpmap, "%*s") != EOF){
+ // *name = tsk_strdup(rtpmap);
+ // return 0;
+ //}
+ //else{
+ // TSK_DEBUG_ERROR("%s is not a valid rtpmap value", rtpmap);
+ // return -2;
+ //}
+}
+
+static const tmedia_video_size_t tmedia_video_sizes[] =
+{
+ {tmedia_vst_none , 176, 144},
+
+ {tmedia_vst_sqcif, 128, 96},
+ {tmedia_vst_qcif, 176, 144},
+ {tmedia_vst_qvga, 320, 240},
+ {tmedia_vst_cif, 352, 288},
+ {tmedia_vst_vga, 640, 480},
+ {tmedia_vst_4cif, 704, 576},
+ {tmedia_vst_svga, 800, 600},
+ {tmedia_vst_xga, 1024, 768},
+ {tmedia_vst_sxga, 1280, 1024},
+ {tmedia_vst_16cif, 1408, 1152},
+ {tmedia_vst_hd720p, 1280, 720},
+ {tmedia_vst_hd1080p, 1920, 1080},
+
+ {tmedia_vst_ios_low, 200, 152},
+ {tmedia_vst_ios_high, 400, 304},
+};
+
+const tmedia_video_size_t* tmedia_get_video_size(tmedia_chroma_t chroma, tsk_size_t size)
+{
+ float factor = 3.f;
+ tsk_size_t i;
+ switch(chroma)
+ {
+ case tmedia_rgb24:
+ case tmedia_bgr24:
+ factor = 3.f;
+ break;
+ case tmedia_rgb565le:
+ case tmedia_rgb565be:
+ factor = 2.f;
+ break;
+
+ case tmedia_rgb32:
+ factor = 4.f;
+ break;
+
+ case tmedia_nv21:
+ case tmedia_nv12:
+ case tmedia_yuv420p:
+ factor = 1.5f;
+ break;
+
+ case tmedia_yuv422p:
+ case tmedia_uyvy422:
+ factor = 2.f;
+ break;
+ }
+
+ for(i = 1; i< sizeof(tmedia_video_sizes)/sizeof(tmedia_video_size_t); i++){
+ if((((float)(tmedia_video_sizes[i].width * tmedia_video_sizes[i].height)) * factor) == size){
+ return &tmedia_video_sizes[i];
+ }
+ }
+
+ return &tmedia_video_sizes[0];;
+}
\ No newline at end of file diff --git a/tinyMEDIA/src/tmedia_consumer.c b/tinyMEDIA/src/tmedia_consumer.c new file mode 100644 index 0000000..5161615 --- /dev/null +++ b/tinyMEDIA/src/tmedia_consumer.c @@ -0,0 +1,284 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tmedia_consumer.c
+ * @brief Base consumer object.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tinymedia/tmedia_consumer.h"
+
+#include "tsk_debug.h"
+
+/**@defgroup tmedia_consumer_group Producers
+*/
+
+/* pointer to all registered consumers */
+const tmedia_consumer_plugin_def_t* __tmedia_consumer_plugins[TMED_CONSUMER_MAX_PLUGINS] = {0};
+
+/**@ingroup tmedia_consumer_group
+* Initialize the consumer.
+* @param self The consumer to initialize
+* @retval Zero if succeed and non-zero error code otherwise.
+*
+* @sa @ref tmedia_consumer_deinit
+*/
+int tmedia_consumer_init(tmedia_consumer_t* self)
+{
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ self->video.in.chroma = TMEDIA_CONSUMER_CHROMA_DEFAULT;
+ self->video.display.chroma = TMEDIA_CONSUMER_CHROMA_DEFAULT;
+
+ return 0;
+}
+
+/**@ingroup tmedia_consumer_group
+* @retval Zero if succeed and non-zero error code otherwise
+*/
+int tmedia_consumer_set(tmedia_consumer_t *self, const tmedia_param_t* param)
+{
+ if(!self || !self->plugin || !self->plugin->set || !param){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ return self->plugin->set(self, param);
+}
+
+/**@ingroup tmedia_consumer_group
+* Alert the consumer to be prepared to start.
+* @param self the consumer to prepare
+* @param codec Negociated codec
+* @retval Zero if succeed and non-zero error code otherwise
+*/
+int tmedia_consumer_prepare(tmedia_consumer_t *self, const tmedia_codec_t* codec)
+{
+ if(!self || !self->plugin || !self->plugin->prepare || !codec){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ return self->plugin->prepare(self, codec);
+}
+
+/**@ingroup tmedia_consumer_group
+* Starts the consumer
+* @param self The consumer to start
+* @retval Zero if succeed and non-zero error code otherwise
+*/
+int tmedia_consumer_start(tmedia_consumer_t *self)
+{
+ if(!self || !self->plugin || !self->plugin->start){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ return self->plugin->start(self);
+}
+
+/**@ingroup tmedia_consumer_group
+* Consumes data
+* @param self The consumer
+* @param buffer Pointer to the data to consume
+* @param size Size of the data to consume
+*/
+int tmedia_consumer_consume(tmedia_consumer_t* self, void** buffer, tsk_size_t size, const tsk_object_t* proto_hdr)
+{
+ if(!self || !self->plugin || !self->plugin->consume){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ return self->plugin->consume(self, buffer, size, proto_hdr);
+}
+
+/**@ingroup tmedia_consumer_group
+* Pauses the consumer
+* @param self The consumer to pause
+* @retval Zero if succeed and non-zero error code otherwise
+*/
+int tmedia_consumer_pause(tmedia_consumer_t *self)
+{
+ if(!self || !self->plugin || !self->plugin->pause){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ return self->plugin->pause(self);
+}
+
+
+/**@ingroup tmedia_consumer_group
+* Stops the consumer
+* @param self The consumer to stop
+* @retval Zero if succeed and non-zero error code otherwise
+*/
+int tmedia_consumer_stop(tmedia_consumer_t *self)
+{
+ if(!self || !self->plugin || !self->plugin->stop){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ return self->plugin->stop(self);
+}
+
+
+/**@ingroup tmedia_consumer_group
+* DeInitialize the consumer.
+* @param self The consumer to deinitialize
+* @retval Zero if succeed and non-zero error code otherwise.
+*
+* @sa @ref tmedia_consumer_deinit
+*/
+int tmedia_consumer_deinit(tmedia_consumer_t* self)
+{
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ return 0;
+}
+
+/**@ingroup tmedia_consumer_group
+* Creates a new consumer using an already registered plugin.
+* @param type The type of the consumer to create
+* @param session_id
+* @sa @ref tmedia_consumer_plugin_register()
+*/
+tmedia_consumer_t* tmedia_consumer_create(tmedia_type_t type, uint64_t session_id)
+{
+ tmedia_consumer_t* consumer = tsk_null;
+ const tmedia_consumer_plugin_def_t* plugin;
+ tsk_size_t i = 0;
+
+ while((i < TMED_CONSUMER_MAX_PLUGINS) && (plugin = __tmedia_consumer_plugins[i++])){
+ if(plugin->objdef && plugin->type == type){
+ if((consumer = tsk_object_new(plugin->objdef))){
+ /* initialize the newly created consumer */
+ consumer->plugin = plugin;
+ consumer->session_id = session_id;
+ break;
+ }
+ }
+ }
+
+ return consumer;
+}
+
+/**@ingroup tmedia_consumer_group
+* Registers a consumer plugin.
+* @param plugin the definition of the plugin.
+* @retval Zero if succeed and non-zero error code otherwise.
+* @sa @ref tmedia_consumer_create()
+*/
+int tmedia_consumer_plugin_register(const tmedia_consumer_plugin_def_t* plugin)
+{
+ tsk_size_t i;
+ if(!plugin){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ /* add or replace the plugin */
+ for(i = 0; i<TMED_CONSUMER_MAX_PLUGINS; i++){
+ if(!__tmedia_consumer_plugins[i] || (__tmedia_consumer_plugins[i] == plugin)){
+ __tmedia_consumer_plugins[i] = plugin;
+ return 0;
+ }
+ }
+
+ TSK_DEBUG_ERROR("There are already %d plugins.", TMED_CONSUMER_MAX_PLUGINS);
+ return -2;
+}
+
+/**@ingroup tmedia_consumer_group
+* UnRegisters a consumer plugin.
+* @param plugin the definition of the plugin.
+* @retval Zero if succeed and non-zero error code otherwise.
+*/
+int tmedia_consumer_plugin_unregister(const tmedia_consumer_plugin_def_t* plugin)
+{
+ tsk_size_t i;
+ tsk_bool_t found = tsk_false;
+ if(!plugin){
+ TSK_DEBUG_ERROR("Invalid Parameter");
+ return -1;
+ }
+
+ /* find the plugin to unregister */
+ for(i = 0; i<TMED_CONSUMER_MAX_PLUGINS && __tmedia_consumer_plugins[i]; i++){
+ if(__tmedia_consumer_plugins[i] == plugin){
+ __tmedia_consumer_plugins[i] = tsk_null;
+ found = tsk_true;
+ break;
+ }
+ }
+
+ /* compact */
+ if(found){
+ for(; i<(TMED_CONSUMER_MAX_PLUGINS - 1); i++){
+ if(__tmedia_consumer_plugins[i+1]){
+ __tmedia_consumer_plugins[i] = __tmedia_consumer_plugins[i+1];
+ }
+ else{
+ break;
+ }
+ }
+ __tmedia_consumer_plugins[i] = tsk_null;
+ }
+ return (found ? 0 : -2);
+}
+
+/**@ingroup tmedia_consumer_group
+* UnRegisters all consumers matching the given type.
+* @param type the type of the consumers to unregister (e.g. audio|video).
+* @retval Zero if succeed and non-zero error code otherwise.
+*/
+int tmedia_consumer_plugin_unregister_by_type(tmedia_type_t type)
+{
+ tsk_size_t i;
+ tsk_bool_t found = tsk_false;
+
+ /* find the plugin to unregister */
+ for(i = 0; i<TMED_CONSUMER_MAX_PLUGINS && __tmedia_consumer_plugins[i]; i++){
+ if((__tmedia_consumer_plugins[i]->type & type) == __tmedia_consumer_plugins[i]->type){
+ __tmedia_consumer_plugins[i] = tsk_null;
+ found = tsk_true;
+ break;
+ }
+ }
+
+ /* compact */
+ if(found){
+ for(; i<(TMED_CONSUMER_MAX_PLUGINS - 1); i++){
+ if(__tmedia_consumer_plugins[i+1]){
+ __tmedia_consumer_plugins[i] = __tmedia_consumer_plugins[i+1];
+ }
+ else{
+ break;
+ }
+ }
+ __tmedia_consumer_plugins[i] = tsk_null;
+ }
+ return (found ? 0 : -2);
+}
\ No newline at end of file diff --git a/tinyMEDIA/src/tmedia_denoise.c b/tinyMEDIA/src/tmedia_denoise.c new file mode 100644 index 0000000..c9e0731 --- /dev/null +++ b/tinyMEDIA/src/tmedia_denoise.c @@ -0,0 +1,185 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tmedia_denoise.c
+ * @brief Denoiser (Noise suppression, AGC, AEC, VAD) Plugin
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tinymedia/tmedia_denoise.h"
+
+#include "tsk_debug.h"
+
+static const tmedia_denoise_plugin_def_t* __tmedia_denoise_plugin = tsk_null;
+
+int tmedia_denoise_init(tmedia_denoise_t* self)
+{
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ return 0;
+}
+
+int tmedia_denoise_open(tmedia_denoise_t* self, uint32_t frame_size, uint32_t sampling_rate, tsk_bool_t denoise, float agc_level, tsk_bool_t aec, tsk_bool_t vad)
+{
+ if(!self || !self->plugin){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if(self->opened){
+ TSK_DEBUG_WARN("Denoiser already opened");
+ return 0;
+ }
+
+ if(self->plugin->open){
+ int ret;
+ if((ret = self->plugin->open(self, frame_size, sampling_rate, denoise, agc_level, aec, vad))){
+ TSK_DEBUG_ERROR("Failed to open [%s] denoiser", self->plugin->desc);
+ return ret;
+ }
+ else{
+ self->opened = tsk_true;
+ return 0;
+ }
+ }
+ else{
+ self->opened = tsk_true;
+ return 0;
+ }
+}
+
+int tmedia_denoise_echo_playback(tmedia_denoise_t* self, const void* echo_frame)
+{
+ if(!self || !self->plugin){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if(!self->opened){
+ TSK_DEBUG_ERROR("Denoiser not opened");
+ return -2;
+ }
+
+ if(self->plugin->process){
+ return self->plugin->echo_playback(self, echo_frame);
+ }
+ else{
+ return 0;
+ }
+}
+
+
+int tmedia_denoise_process(tmedia_denoise_t* self, void* audio_frame, tsk_bool_t* silence_or_noise)
+{
+ if(!self || !self->plugin || !silence_or_noise){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if(!self->opened){
+ TSK_DEBUG_ERROR("Denoiser not opened");
+ return -2;
+ }
+
+ if(self->plugin->process){
+ return self->plugin->process(self, audio_frame, silence_or_noise);
+ }
+ else{
+ *silence_or_noise = tsk_false;
+ return 0;
+ }
+}
+
+int tmedia_denoise_close(tmedia_denoise_t* self)
+{
+ if(!self || !self->plugin){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if(!self->opened){
+ TSK_DEBUG_WARN("Denoiser not opened");
+ return 0;
+ }
+
+ if(self->plugin->close){
+ int ret;
+
+ if((ret = self->plugin->close(self))){
+ TSK_DEBUG_ERROR("Failed to close [%s] denoiser", self->plugin->desc);
+ return ret;
+ }
+ else{
+ self->opened = tsk_false;
+ return 0;
+ }
+ }
+ else{
+ self->opened = tsk_false;
+ return 0;
+ }
+}
+
+int tmedia_denoise_deinit(tmedia_denoise_t* self)
+{
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if(self->opened){
+ tmedia_denoise_close(self);
+ }
+
+ return 0;
+}
+
+int tmedia_denoise_plugin_register(const tmedia_denoise_plugin_def_t* plugin)
+{
+ if(!plugin){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ __tmedia_denoise_plugin = plugin;
+ return 0;
+}
+
+int tmedia_denoise_plugin_unregister()
+{
+ __tmedia_denoise_plugin = tsk_null;
+ return 0;
+}
+
+tmedia_denoise_t* tmedia_denoise_create()
+{
+ tmedia_denoise_t* denoise = tsk_null;
+
+ if(__tmedia_denoise_plugin){
+ if((denoise = tsk_object_new(__tmedia_denoise_plugin->objdef))){
+ denoise->plugin = __tmedia_denoise_plugin;
+ }
+ }
+ return denoise;
+}
diff --git a/tinyMEDIA/src/tmedia_params.c b/tinyMEDIA/src/tmedia_params.c new file mode 100644 index 0000000..0234839 --- /dev/null +++ b/tinyMEDIA/src/tmedia_params.c @@ -0,0 +1,190 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tmedia_params.c
+ * @brief Media parameters used to configure any session or plugin.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tinymedia/tmedia_params.h"
+
+#include "tinymedia/tmedia_session.h"
+
+#include "tsk_debug.h"
+#include "tsk_memory.h"
+
+tmedia_param_t* tmedia_param_create(tmedia_param_access_type_t access_type,
+ tmedia_type_t media_type,
+ tmedia_param_plugin_type_t plugin_type,
+ tmedia_param_value_type_t value_type,
+ const char* key,
+ void* value)
+{
+ tmedia_param_t* param;
+
+ if(!key ||!value){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_null;
+ }
+
+ if((param = tsk_object_new(tmedia_param_def_t))){
+ param->access_type = access_type;
+ param->media_type = media_type;
+ param->plugin_type = plugin_type;
+ param->value_type = value_type;
+ param->key = tsk_strdup(key);
+ switch(value_type){
+ case tmedia_pvt_int32:
+ if(param->value = tsk_calloc(1, sizeof(int32_t))){
+ memcpy(param->value, value, sizeof(int32_t));
+ //*((int32_t*)param->value) = *((int32_t*)value);
+ }
+ break;
+ case tmedia_pvt_pobject:
+ param->value = tsk_object_ref(value);
+ break;
+ case tmedia_pvt_pchar:
+ param->value = tsk_strdup(value);
+ break;
+ case tmedia_pvt_int64:
+ if(param->value = tsk_calloc(1, sizeof(int64_t))){
+ memcpy(param->value, value, sizeof(int64_t));
+ //*((int64_t*)param->value) = *((int64_t*)value);
+ }
+ break;
+ }
+ }
+ else{
+ TSK_DEBUG_ERROR("Failed to create media parameter");
+ }
+ return param;
+}
+
+tmedia_params_L_t* tmedia_params_create_2(va_list *app)
+{
+ tmedia_session_param_type_t curr;
+ tmedia_params_L_t* params;
+
+ if(!app){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_null;
+ }
+
+ params = tmedia_params_create();
+
+ while((curr = va_arg(*app, tmedia_session_param_type_t)) != tmedia_sptype_null){
+ switch(curr){
+ case tmedia_sptype_set:
+ { /* (tmedia_type_t)MEDIA_TYPE_ENUM, (tmedia_param_plugin_type_t)PLUGIN_TYPE_ENUM, (tmedia_param_value_type_t)VALUE_TYPE_ENUM \
+ (const char*)KEY_STR, (void*)&VALUE */
+ /* IMPORTANT: do not pass va_arg() directly into the function */
+ tmedia_type_t media_type = va_arg(*app, tmedia_type_t);
+ tmedia_param_plugin_type_t plugin_type = va_arg(*app, tmedia_param_plugin_type_t);
+ tmedia_param_value_type_t value_type = va_arg(*app, tmedia_param_value_type_t);
+ const char* key = va_arg(*app, const char*);
+ void* value = va_arg(*app, void*);
+ tmedia_params_add_param(¶ms, tmedia_pat_set,
+ media_type, plugin_type, value_type, key, value);
+ break;
+ }
+ default:
+ { /* va_list will be unsafe => exit */
+ TSK_DEBUG_ERROR("%d NOT a valid pname", curr);
+ break;
+ }
+ }/* switch */
+ }/* while */
+
+ return params;
+}
+
+int tmedia_params_add_param(tmedia_params_L_t **self,
+ tmedia_param_access_type_t access_type,
+ tmedia_type_t media_type,
+ tmedia_param_plugin_type_t plugin_type,
+ tmedia_param_value_type_t value_type,
+ const char* key,
+ void* value)
+{
+ tmedia_param_t *param;
+
+ if(!self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if(!*self){
+ *self = tmedia_params_create();
+ }
+
+ if((param = tmedia_param_create(access_type, media_type, plugin_type, value_type, key, value))){
+ tsk_list_push_back_data(*self, (void**)¶m);
+ }
+ return 0;
+}
+
+
+
+
+//=================================================================================================
+// param object definition
+//
+static tsk_object_t* tmedia_param_ctor(tsk_object_t* self, va_list * app)
+{
+ tmedia_param_t *param = self;
+ if(param){
+ }
+
+ return self;
+}
+
+static tsk_object_t* tmedia_param_dtor(tsk_object_t* self)
+{
+ tmedia_param_t *param = self;
+ if(param){
+ TSK_FREE(param->key);
+ switch(param->value_type){
+ case tmedia_pvt_pobject:
+ TSK_OBJECT_SAFE_FREE(param->value);
+ break;
+ case tmedia_pvt_pchar:
+ case tmedia_pvt_int64:
+ case tmedia_pvt_int32:
+ TSK_FREE(param->value);
+ break;
+ }
+ }
+
+ return self;
+}
+
+static const tsk_object_def_t tmedia_param_def_s =
+{
+ sizeof(tmedia_param_t),
+ tmedia_param_ctor,
+ tmedia_param_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tmedia_param_def_t = &tmedia_param_def_s;
+
diff --git a/tinyMEDIA/src/tmedia_producer.c b/tinyMEDIA/src/tmedia_producer.c new file mode 100644 index 0000000..fb0f83b --- /dev/null +++ b/tinyMEDIA/src/tmedia_producer.c @@ -0,0 +1,301 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tmedia_producer.c
+ * @brief Base producer object.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tinymedia/tmedia_producer.h"
+
+#include "tsk_debug.h"
+
+/**@defgroup tmedia_producer_group Producers
+*/
+
+/* pointer to all registered producers */
+const tmedia_producer_plugin_def_t* __tmedia_producer_plugins[TMED_PRODUCER_MAX_PLUGINS] = {0};
+
+/**@ingroup tmedia_producer_group
+* Initialize the producer.
+* @param self The producer to initialize
+* @retval Zero if succeed and non-zero error code otherwise.
+*
+* @sa @ref tmedia_producer_deinit
+*/
+int tmedia_producer_init(tmedia_producer_t* self)
+{
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ self->video.chroma = TMEDIA_PRODUCER_CHROMA_DEFAULT;
+
+ return 0;
+}
+
+/**@ingroup tmedia_producer_group
+* callback to encode and send() data
+*/
+int tmedia_producer_set_enc_callback(tmedia_producer_t *self, tmedia_producer_enc_cb_f callback, const void* callback_data)
+{
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ self->enc_cb.callback = callback;
+ self->enc_cb.callback_data = callback_data;
+
+ return 0;
+}
+
+/**@ingroup tmedia_producer_group
+* callback to send() data "as is"
+*/
+int tmedia_producer_set_raw_callback(tmedia_producer_t *self, tmedia_producer_raw_cb_f callback, const void* callback_data)
+{
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ self->raw_cb.callback = callback;
+ self->raw_cb.callback_data = callback_data;
+
+ return 0;
+}
+
+/**@ingroup tmedia_producer_group
+* @retval Zero if succeed and non-zero error code otherwise
+*/
+int tmedia_producer_set(tmedia_producer_t* self, const tmedia_param_t* param)
+{
+ if(!self || !self->plugin || !self->plugin->set || !param){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ return self->plugin->set(self, param);
+}
+
+/**@ingroup tmedia_producer_group
+* Alert the producer to be prepared to start.
+* @param self the producer to prepare
+* @param codec The codec to use to prepare the producer
+* @retval Zero if succeed and non-zero error code otherwise
+*/
+int tmedia_producer_prepare(tmedia_producer_t *self, const tmedia_codec_t* codec)
+{
+ if(!self || !self->plugin || !self->plugin->prepare || !codec){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ return self->plugin->prepare(self, codec);
+}
+
+/**@ingroup tmedia_producer_group
+* Starts the producer
+* @param self The producer to start
+* @retval Zero if succeed and non-zero error code otherwise
+*/
+int tmedia_producer_start(tmedia_producer_t *self)
+{
+ if(!self || !self->plugin || !self->plugin->start){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ return self->plugin->start(self);
+}
+
+
+/**@ingroup tmedia_producer_group
+* Pauses the producer
+* @param self The producer to pause
+* @retval Zero if succeed and non-zero error code otherwise
+*/
+int tmedia_producer_pause(tmedia_producer_t *self)
+{
+ if(!self || !self->plugin || !self->plugin->pause){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ return self->plugin->pause(self);
+}
+
+
+/**@ingroup tmedia_producer_group
+* Stops the producer
+* @param self The producer to stop
+* @retval Zero if succeed and non-zero error code otherwise
+*/
+int tmedia_producer_stop(tmedia_producer_t *self)
+{
+ if(!self || !self->plugin || !self->plugin->stop){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ return self->plugin->stop(self);
+}
+
+
+/**@ingroup tmedia_producer_group
+* DeInitialize the producer.
+* @param self The producer to deinitialize
+* @retval Zero if succeed and non-zero error code otherwise.
+*
+* @sa @ref tmedia_producer_deinit
+*/
+int tmedia_producer_deinit(tmedia_producer_t* self)
+{
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ return 0;
+}
+
+/**@ingroup tmedia_producer_group
+* Creates a new producer using an already registered plugin.
+* @param type The type of the producer to create
+* @param session_id
+* @sa @ref tmedia_producer_plugin_register()
+*/
+tmedia_producer_t* tmedia_producer_create(tmedia_type_t type, uint64_t session_id)
+{
+ tmedia_producer_t* producer = tsk_null;
+ const tmedia_producer_plugin_def_t* plugin;
+ tsk_size_t i = 0;
+
+ while((i < TMED_PRODUCER_MAX_PLUGINS) && (plugin = __tmedia_producer_plugins[i++])){
+ if(plugin->objdef && plugin->type == type){
+ if((producer = tsk_object_new(plugin->objdef))){
+ /* initialize the newly created producer */
+ producer->plugin = plugin;
+ producer->session_id = session_id;
+ break;
+ }
+ }
+ }
+
+ return producer;
+}
+
+/**@ingroup tmedia_producer_group
+* Registers a producer plugin.
+* @param plugin the definition of the plugin.
+* @retval Zero if succeed and non-zero error code otherwise.
+* @sa @ref tmedia_producer_create()
+*/
+int tmedia_producer_plugin_register(const tmedia_producer_plugin_def_t* plugin)
+{
+ tsk_size_t i;
+ if(!plugin){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ /* add or replace the plugin */
+ for(i = 0; i<TMED_PRODUCER_MAX_PLUGINS; i++){
+ if(!__tmedia_producer_plugins[i] || (__tmedia_producer_plugins[i] == plugin)){
+ __tmedia_producer_plugins[i] = plugin;
+ return 0;
+ }
+ }
+
+ TSK_DEBUG_ERROR("There are already %d plugins.", TMED_PRODUCER_MAX_PLUGINS);
+ return -2;
+}
+
+/**@ingroup tmedia_producer_group
+* UnRegisters a producer plugin.
+* @param plugin the definition of the plugin.
+* @retval Zero if succeed and non-zero error code otherwise.
+*/
+int tmedia_producer_plugin_unregister(const tmedia_producer_plugin_def_t* plugin)
+{
+ tsk_size_t i;
+ tsk_bool_t found = tsk_false;
+ if(!plugin){
+ TSK_DEBUG_ERROR("Invalid Parameter");
+ return -1;
+ }
+
+ /* find the plugin to unregister */
+ for(i = 0; i<TMED_PRODUCER_MAX_PLUGINS && __tmedia_producer_plugins[i]; i++){
+ if(__tmedia_producer_plugins[i] == plugin){
+ __tmedia_producer_plugins[i] = tsk_null;
+ found = tsk_true;
+ break;
+ }
+ }
+
+ /* compact */
+ if(found){
+ for(; i<(TMED_PRODUCER_MAX_PLUGINS - 1); i++){
+ if(__tmedia_producer_plugins[i+1]){
+ __tmedia_producer_plugins[i] = __tmedia_producer_plugins[i+1];
+ }
+ else{
+ break;
+ }
+ }
+ __tmedia_producer_plugins[i] = tsk_null;
+ }
+ return (found ? 0 : -2);
+}
+
+/**@ingroup tmedia_producer_group
+* UnRegisters all producers matching the given type.
+* @param type the type of the plugins to unregister.
+* @retval Zero if succeed and non-zero error code otherwise.
+*/
+int tmedia_producer_plugin_unregister_by_type(tmedia_type_t type)
+{
+ tsk_size_t i;
+ tsk_bool_t found = tsk_false;
+
+ /* find the plugin to unregister */
+ for(i = 0; i<TMED_PRODUCER_MAX_PLUGINS && __tmedia_producer_plugins[i]; i++){
+ if((__tmedia_producer_plugins[i]->type & type) == __tmedia_producer_plugins[i]->type){
+ __tmedia_producer_plugins[i] = tsk_null;
+ found = tsk_true;
+ break;
+ }
+ }
+
+ /* compact */
+ if(found){
+ for(; i<(TMED_PRODUCER_MAX_PLUGINS - 1); i++){
+ if(__tmedia_producer_plugins[i+1]){
+ __tmedia_producer_plugins[i] = __tmedia_producer_plugins[i+1];
+ }
+ else{
+ break;
+ }
+ }
+ __tmedia_producer_plugins[i] = tsk_null;
+ }
+ return (found ? 0 : -2);
+}
diff --git a/tinyMEDIA/src/tmedia_qos.c b/tinyMEDIA/src/tmedia_qos.c new file mode 100644 index 0000000..e2cac97 --- /dev/null +++ b/tinyMEDIA/src/tmedia_qos.c @@ -0,0 +1,861 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tmedia_qos.c
+ * @brief RFC 3312 (Preconditions) implementation.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tinymedia/tmedia_qos.h"
+
+#include "tsk_memory.h"
+#include "tsk_debug.h"
+
+/* ========================= Internal ==================================*/
+
+static const char* tmedia_qos_strength_tostring(tmedia_qos_strength_t strength)
+{
+ switch(strength){
+ case tmedia_qos_strength_none:
+ return "none";
+ case tmedia_qos_strength_mandatory:
+ return "mandatory";
+ case tmedia_qos_strength_optional:
+ return "optional";
+ case tmedia_qos_strength_failure:
+ return "failure";
+ case tmedia_qos_strength_unknown:
+ default:
+ return "unknown";
+ }
+}
+
+static tmedia_qos_strength_t tmedia_qos_strength_fromstring(const char* strength)
+{
+ if(tsk_strequals(strength, "none")){
+ return tmedia_qos_strength_none;
+ }
+ else if(tsk_strequals(strength, "mandatory")){
+ return tmedia_qos_strength_mandatory;
+ }
+ else if(tsk_strequals(strength, "optional")){
+ return tmedia_qos_strength_optional;
+ }
+ else if(tsk_strequals(strength, "failure")){
+ return tmedia_qos_strength_failure;
+ }
+ else{
+ return tmedia_qos_strength_unknown;
+ }
+}
+
+static tmedia_qos_direction_t tmedia_qos_direction_fromstring(const char* direction)
+{
+ if(tsk_strequals(direction, "send")){
+ return tmedia_qos_direction_send;
+ }
+ else if(tsk_strequals(direction, "recv")){
+ return tmedia_qos_direction_recv;
+ }
+ else if(tsk_strequals(direction, "sendrecv")){
+ return tmedia_qos_direction_sendrecv;
+ }
+ else{
+ return tmedia_qos_direction_none;
+ }
+}
+
+/* ========================= Common ==================================*/
+
+tmedia_qos_tline_t* tmedia_qos_tline_create(tmedia_qos_stype_t type, tmedia_qos_strength_t strength)
+{
+ switch(type){
+ case tmedia_qos_stype_e2e:
+ return (tmedia_qos_tline_t*)tmedia_qos_tline_e2e_create(strength);
+ case tmedia_qos_stype_segmented:
+ return (tmedia_qos_tline_t*)tmedia_qos_tline_segmented_create(strength);
+ }
+ return tsk_null;
+}
+
+tmedia_qos_stype_t tmedia_qos_get_type(const tsdp_header_M_t* m)
+{
+ const tsdp_header_A_t* A;
+ char s0[10];
+
+ if(!m){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tmedia_qos_stype_none;
+ }
+
+ if((A = tsdp_header_M_findA(m, "curr"))){
+ if(sscanf(A->value, "qos %s %*s", s0) != EOF){
+ return tsk_strequals(s0, "e2e") ? tmedia_qos_stype_e2e : tmedia_qos_stype_segmented;
+ }
+ else{
+ TSK_DEBUG_ERROR("Failed to parse a=%s:%s", A->field, A->value);
+ }
+ }
+
+ return tmedia_qos_stype_none;
+}
+
+tmedia_qos_tline_t* tmedia_qos_tline_from_sdp(const tsdp_header_M_t* m)
+{
+ if(!m){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_null;
+ }
+
+ switch(tmedia_qos_get_type(m)){
+ case tmedia_qos_stype_e2e:
+ return (tmedia_qos_tline_t*)tmedia_qos_tline_e2e_from_sdp(m);
+ case tmedia_qos_stype_segmented:
+ return (tmedia_qos_tline_t*)tmedia_qos_tline_segmented_from_sdp(m);
+ default:
+ return tsk_null;
+ }
+}
+
+int tmedia_qos_tline_to_sdp(const tmedia_qos_tline_t* self, tsdp_header_M_t* m)
+{
+ if(!self || !m){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ switch(self->type){
+ case tmedia_qos_stype_e2e:
+ return tmedia_qos_tline_e2e_to_sdp((tmedia_qos_tline_e2e_t*)self, m);
+ case tmedia_qos_stype_segmented:
+ return tmedia_qos_tline_segmented_to_sdp((tmedia_qos_tline_segmented_t*)self, m);
+ default:
+ TSK_DEBUG_ERROR("Invalid type");
+ return -2;
+ }
+}
+
+int tmedia_qos_tline_set_ro(tmedia_qos_tline_t* self, const tmedia_qos_tline_t* ro)
+{
+ if(!self || !ro){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ switch(self->type){
+ case tmedia_qos_stype_e2e:
+ return tmedia_qos_tline_e2e_set_ro((tmedia_qos_tline_e2e_t*)self, (const tmedia_qos_tline_e2e_t*)ro);
+ case tmedia_qos_stype_segmented:
+ return tmedia_qos_tline_segmented_set_ro((tmedia_qos_tline_segmented_t*)self, (const tmedia_qos_tline_segmented_t*)ro);
+ default:
+ TSK_DEBUG_ERROR("Invalid type");
+ return -2;
+ }
+}
+
+tsk_bool_t tmedia_qos_tline_canresume(const tmedia_qos_tline_t* self)
+{
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_true;
+ }
+ switch(self->type){
+ case tmedia_qos_stype_segmented:
+ return tmedia_qos_tline_segmented_canresume((const tmedia_qos_tline_segmented_t*)self);
+ case tmedia_qos_stype_e2e:
+ return tmedia_qos_tline_e2e_canresume((const tmedia_qos_tline_e2e_t*)self);
+ default:
+ return tsk_true;
+ }
+}
+
+/* ========================= E2E ==================================*/
+
+tmedia_qos_tline_e2e_t* tmedia_qos_tline_e2e_create(tmedia_qos_strength_t strength)
+{
+ return tsk_object_new(tmedia_qos_tline_e2e_def_t, strength);
+}
+
+tmedia_qos_tline_e2e_t* tmedia_qos_tline_e2e_from_sdp(const tsdp_header_M_t* m)
+{
+ tmedia_qos_tline_e2e_t* e2e = tsk_null;
+ const tsdp_header_A_t* A;
+ tsk_size_t i;
+
+ char s0[10], s1[10];
+
+ if(!m){
+ TSK_DEBUG_ERROR("invalid parameter");
+ return tsk_null;
+ }
+
+ /* Example
+ a=curr:qos e2e none
+ a=des:qos mandatory e2e sendrecv
+ a=conf:qos e2e recv
+ */
+
+ e2e = tmedia_qos_tline_e2e_create(tmedia_qos_strength_unknown);
+
+ /* curr */
+ for(i = 0; (A = tsdp_header_M_findA_at(m, "curr", i)); i++){
+ if(sscanf(A->value, "qos e2e %10s", s0) != EOF){
+ tmedia_qos_direction_t dir = tmedia_qos_direction_fromstring(s0);
+ switch(dir){
+ case tmedia_qos_direction_send:
+ e2e->send.current = tsk_true;
+ break;
+ case tmedia_qos_direction_recv:
+ e2e->recv.current = tsk_true;
+ break;
+ case tmedia_qos_direction_sendrecv:
+ e2e->send.current = tsk_true;
+ e2e->recv.current = tsk_true;
+ break;
+ case tmedia_qos_direction_none:
+ e2e->send.current = tsk_false;
+ e2e->recv.current = tsk_false;
+ break;
+ default:
+ break;
+ }
+ }
+ else{
+ TSK_DEBUG_ERROR("Failed to parse a=%s:%s", A->field, A->value);
+ }
+ }
+
+ /* des */
+ for(i = 0; (A = tsdp_header_M_findA_at(m, "des", i)); i++){
+ if(sscanf(A->value, "qos %10s e2e %10s", s0, s1) != EOF){
+ tmedia_qos_strength_t strength = tmedia_qos_strength_fromstring(s0);
+ tmedia_qos_direction_t dir = tmedia_qos_direction_fromstring(s1);
+ switch(dir){
+ case tmedia_qos_direction_send:
+ e2e->send.strength = strength;
+ break;
+ case tmedia_qos_direction_recv:
+ e2e->recv.strength = strength;
+ break;
+ case tmedia_qos_direction_sendrecv:
+ e2e->send.strength = strength;
+ e2e->recv.strength = strength;
+ break;
+ default:
+ break;
+ }
+ }
+ else{
+ TSK_DEBUG_ERROR("Failed to parse a=%s:%s", A->field, A->value);
+ }
+ }
+
+ /* conf */
+ for(i = 0; (A = tsdp_header_M_findA_at(m, "conf", i)); i++){
+ if(sscanf(A->value, "qos e2e %10s", s0) != EOF){
+ tmedia_qos_direction_t dir = tmedia_qos_direction_fromstring(s0);
+ switch(dir){
+ case tmedia_qos_direction_send:
+ e2e->send.confirm = tsk_true;
+ break;
+ case tmedia_qos_direction_recv:
+ e2e->recv.confirm = tsk_true;
+ break;
+ case tmedia_qos_direction_sendrecv:
+ e2e->send.confirm = tsk_true;
+ e2e->recv.confirm = tsk_true;
+ break;
+ default:
+ break;
+ }
+ }
+ else{
+ TSK_DEBUG_ERROR("Failed to parse a=%s:%s", A->field, A->value);
+ }
+ }
+
+ return e2e;
+}
+
+int tmedia_qos_tline_e2e_to_sdp(const tmedia_qos_tline_e2e_t* self, tsdp_header_M_t* m)
+{
+ /* RFC 3312 - 5.1.1 SDP encoding
+
+ For the end-to-end status type, the user agent MUST generate one
+ current status line with the tag "e2e" for the media stream. If the
+ strength-tags for both directions are equal (e.g., both "mandatory")
+ in the transaction status table, the user agent MUST add one desired
+ status line with the tag "sendrecv". If both tags are different, the
+ user agent MUST include two desired status lines, one with the tag
+ "send" and the other with the tag "recv".
+ */
+ char* temp = tsk_null;
+
+ if(!self || !m){
+ TSK_DEBUG_ERROR("invalid parameter");
+ return -1;
+ }
+ /* Example
+ a=curr:qos e2e none
+ a=des:qos mandatory e2e sendrecv
+ */
+
+
+ /* curr */
+ tsk_sprintf(&temp, "qos e2e %s", (self->recv.current && self->send.current) ? "sendrecv" : (self->recv.current ? "recv" : (self->send.current ? "send" : "none")));
+ tsdp_header_M_add_headers(m,
+ TSDP_HEADER_A_VA_ARGS("curr", temp),
+ tsk_null);
+ TSK_FREE(temp);
+
+ /* des */
+ if(self->recv.strength == self->send.strength){
+ /* sendrecv */
+ tsk_sprintf(&temp, "qos %s e2e sendrecv", tmedia_qos_strength_tostring(self->recv.strength));
+ tsdp_header_M_add_headers(m,
+ TSDP_HEADER_A_VA_ARGS("des", temp),
+ tsk_null);
+ TSK_FREE(temp);
+ }
+ else{
+ /* send */
+ tsk_sprintf(&temp, "qos %s e2e send", tmedia_qos_strength_tostring(self->send.strength));
+ tsdp_header_M_add_headers(m,
+ TSDP_HEADER_A_VA_ARGS("des", temp),
+ tsk_null);
+ TSK_FREE(temp);
+
+ /* recv */
+ tsk_sprintf(&temp, "qos %s e2e recv", tmedia_qos_strength_tostring(self->recv.strength));
+ tsdp_header_M_add_headers(m,
+ TSDP_HEADER_A_VA_ARGS("des", temp),
+ tsk_null);
+ TSK_FREE(temp);
+ }
+
+ /* conf (should not request confirm on "send" direction)*/
+ if(self->recv.confirm){
+ tsdp_header_M_add_headers(m,
+ TSDP_HEADER_A_VA_ARGS("conf", "qos e2e recv"),
+ tsk_null);
+ }
+ return 0;
+}
+
+int tmedia_qos_tline_e2e_set_ro(tmedia_qos_tline_e2e_t* self, const tmedia_qos_tline_e2e_t* ro)
+{
+ if(!self || !ro){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ /* We were the offerer
+ * Remote asked for confirmation in its "recv" direction?
+ * "recv" direction for remote is our "send" direction
+ * As we don't support RSVP (under the way), confirm immediatly.
+ * "send" direction should not requested for confirmation
+ */
+ if(ro->recv.confirm){
+ self->send.current = tsk_true;
+ goto bail;
+ }
+ if(ro->send.current){
+ self->recv.confirm = tsk_false; /* remote confirmed */
+ self->recv.current = tsk_true; /* because ro confirmed */
+ self->send.current = tsk_true; /* beacuse we don't support RSVP */
+ goto bail;
+ }
+
+ /* We are the answerer
+ * As we don't support RSVP (under the way):
+ * ==> request confirmation for "recv" direction if equal to "none" (not reserved)
+ * =>
+ */
+ if(!self->recv.current){
+ self->recv.confirm = tsk_true;
+ goto bail;
+ }
+
+bail:
+ /* all other cases: success */
+ return 0;
+}
+
+tsk_bool_t tmedia_qos_tline_e2e_canresume(const tmedia_qos_tline_e2e_t* self)
+{
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_true;
+ }
+
+ /* Example
+ a=curr:qos e2e none
+ a=des:qos mandatory e2e sendrecv
+
+ Or
+
+ a=curr:qos e2e send
+ a=des:qos mandatory e2e recv
+ a=des:qos optional e2e send
+ */
+
+ /* only "mandatory" strength should force the application to continue nego. */
+ if(self->recv.strength == tmedia_qos_strength_mandatory && !self->recv.current){
+ return tsk_false;
+ }
+ /*else */if(self->send.strength == tmedia_qos_strength_mandatory && !self->send.current){
+ return tsk_false;
+ }
+
+ /* "optinal" and "none" strengths */
+ return tsk_true;
+}
+
+//
+// E2E QoS line object definition
+//
+static tsk_object_t* tmedia_qos_tline_e2e_ctor(tsk_object_t * self, va_list * app)
+{
+ tmedia_qos_tline_e2e_t *e2e = self;
+ if(e2e){
+ e2e->recv.strength = e2e->send.strength = va_arg(*app, tmedia_qos_strength_t);
+ TMEDIA_QOS_TLINE(e2e)->type = tmedia_qos_stype_e2e;
+ }
+ return self;
+}
+
+static tsk_object_t* tmedia_qos_tline_e2e_dtor(tsk_object_t * self)
+{
+ tmedia_qos_tline_e2e_t *e2e = self;
+ if(e2e){
+ }
+
+ return self;
+}
+
+static const tsk_object_def_t tmedia_qos_tline_e2e_def_s =
+{
+ sizeof(tmedia_qos_tline_e2e_t),
+ tmedia_qos_tline_e2e_ctor,
+ tmedia_qos_tline_e2e_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tmedia_qos_tline_e2e_def_t = &tmedia_qos_tline_e2e_def_s;
+
+
+
+
+
+
+
+
+
+
+/* ========================= Segmented ==================================*/
+
+tmedia_qos_tline_segmented_t* tmedia_qos_tline_segmented_create(tmedia_qos_strength_t strength)
+{
+ return tsk_object_new(tmedia_qos_tline_segmented_def_t, strength);
+}
+
+tmedia_qos_tline_segmented_t* tmedia_qos_tline_segmented_from_sdp(const tsdp_header_M_t* m)
+{
+ tmedia_qos_tline_segmented_t* segmented = tsk_null;
+ const tsdp_header_A_t* A;
+ tsk_size_t i;
+
+ char s0[10], s1[10], s2[10];
+
+ if(!m){
+ TSK_DEBUG_ERROR("invalid parameter");
+ return tsk_null;
+ }
+
+ /* Example
+ a=curr:qos local none
+ a=curr:qos remote none
+ a=des:qos optional remote send
+ a=des:qos none remote recv
+ a=des:qos none local sendrecv
+ a=conf:qos local recv
+ */
+ segmented = tmedia_qos_tline_segmented_create(tmedia_qos_strength_unknown);
+
+ /* curr */
+ for(i = 0; (A = tsdp_header_M_findA_at(m, "curr", i)); i++){
+ if(sscanf(A->value, "qos %10s %10s", s0, s1) != EOF){
+ /* For segmented, s0 should be equal to "local" or "remote" */
+ tmedia_qos_direction_t dir = tmedia_qos_direction_fromstring(s1);
+ if(tsk_strequals(s0, "local")){
+ /* local */
+ switch(dir){
+ case tmedia_qos_direction_send:
+ segmented->local_send.current = tsk_true;
+ break;
+ case tmedia_qos_direction_recv:
+ segmented->local_recv.current = tsk_true;
+ break;
+ case tmedia_qos_direction_sendrecv:
+ segmented->local_send.current = tsk_true;
+ segmented->local_recv.current = tsk_true;
+ break;
+ case tmedia_qos_direction_none:
+ segmented->local_send.current = tsk_false;
+ segmented->local_recv.current = tsk_false;
+ break;
+ default:
+ break;
+ }
+ }
+ else{
+ /* remote */
+ switch(dir){
+ case tmedia_qos_direction_send:
+ segmented->remote_send.current = tsk_true;
+ break;
+ case tmedia_qos_direction_recv:
+ segmented->remote_recv.current = tsk_true;
+ break;
+ case tmedia_qos_direction_sendrecv:
+ segmented->remote_send.current = tsk_true;
+ segmented->remote_recv.current = tsk_true;
+ break;
+ case tmedia_qos_direction_none:
+ segmented->remote_send.current = tsk_false;
+ segmented->remote_recv.current = tsk_false;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ else{
+ TSK_DEBUG_ERROR("Failed to parse a=%s:%s", A->field, A->value);
+ }
+ }
+
+ /* des */
+ for(i = 0; (A = tsdp_header_M_findA_at(m, "des", i)); i++){
+ if(sscanf(A->value, "qos %10s %10s %10s", s0, s1, s2) != EOF){
+ /* For segmented, s1 should be equal to "local" or "remote" */
+ tmedia_qos_strength_t strength = tmedia_qos_strength_fromstring(s0);
+ tmedia_qos_direction_t dir = tmedia_qos_direction_fromstring(s2);
+ if(tsk_strequals(s1, "local")){
+ /* local */
+ switch(dir){
+ case tmedia_qos_direction_send:
+ segmented->local_send.strength = strength;
+ break;
+ case tmedia_qos_direction_recv:
+ segmented->local_recv.strength = strength;
+ break;
+ case tmedia_qos_direction_sendrecv:
+ segmented->local_send.strength = strength;
+ segmented->local_recv.strength = strength;
+ break;
+ default:
+ break;
+ }
+ }
+ else{
+ /* remote */
+ switch(dir){
+ case tmedia_qos_direction_send:
+ segmented->remote_send.strength = strength;
+ break;
+ case tmedia_qos_direction_recv:
+ segmented->remote_recv.strength = strength;
+ break;
+ case tmedia_qos_direction_sendrecv:
+ segmented->remote_send.strength = strength;
+ segmented->remote_recv.strength = strength;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ else{
+ TSK_DEBUG_ERROR("Failed to parse a=%s:%s", A->field, A->value);
+ }
+ }
+
+ /* conf */
+ for(i = 0; (A = tsdp_header_M_findA_at(m, "conf", i)); i++){
+ if(sscanf(A->value, "qos %10s %10s", s0, s1) != EOF){
+ /* For segmented, s0 should be equal to "local" or "remote" */
+ tmedia_qos_direction_t dir = tmedia_qos_direction_fromstring(s1);
+ if(tsk_strequals(s0, "local")){
+ /* local */
+ switch(dir){
+ case tmedia_qos_direction_send:
+ segmented->local_send.confirm = tsk_true;
+ break;
+ case tmedia_qos_direction_recv:
+ segmented->local_recv.confirm = tsk_true;
+ break;
+ case tmedia_qos_direction_sendrecv:
+ segmented->local_send.confirm = tsk_true;
+ segmented->local_recv.confirm = tsk_true;
+ break;
+ default:
+ break;
+ }
+ }
+ else{
+ /* remote */
+ switch(dir){
+ case tmedia_qos_direction_send:
+ segmented->remote_send.confirm = tsk_true;
+ break;
+ case tmedia_qos_direction_recv:
+ segmented->remote_recv.confirm = tsk_true;
+ break;
+ case tmedia_qos_direction_sendrecv:
+ segmented->remote_send.confirm = tsk_true;
+ segmented->remote_recv.confirm = tsk_true;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ else{
+ TSK_DEBUG_ERROR("Failed to parse a=%s:%s", A->field, A->value);
+ }
+ }
+
+ return segmented;
+}
+
+int tmedia_qos_tline_segmented_to_sdp(const tmedia_qos_tline_segmented_t* self, tsdp_header_M_t* m)
+{
+ /* RFC 3312 - 5.1.1 SDP encoding
+
+ For the segmented status type, the user agent MUST generate two
+ current status lines: one with the tag "local" and the other with the
+ tag "remote". The user agent MUST add one or two desired status
+ lines per segment (i.e., local and remote). If, for a particular
+ segment (local or remote), the tags for both directions in the
+ transaction status table are equal (e.g., both "mandatory"), the user
+ agent MUST add one desired status line with the tag "sendrecv". If
+ both tags are different, the user agent MUST include two desired
+ status lines, one with the tag "send" and the other with the tag "recv".
+ */
+ char* temp = tsk_null;
+
+ if(!self || !m){
+ TSK_DEBUG_ERROR("invalid parameter");
+ return -1;
+ }
+
+ /* Example
+ a=curr:qos local none
+ a=curr:qos remote none
+ a=des:qos optional remote send
+ a=des:qos none remote recv
+ a=des:qos none local sendrecv
+ */
+
+ /* curr:local */
+ tsk_sprintf(&temp, "qos local %s", (self->local_recv.current && self->local_send.current) ? "sendrecv" : (self->local_recv.current ? "recv" : (self->local_send.current ? "send" : "none")));
+ tsdp_header_M_add_headers(m,
+ TSDP_HEADER_A_VA_ARGS("curr", temp),
+ tsk_null);
+ TSK_FREE(temp);
+
+ /* curr:remote */
+ tsk_sprintf(&temp, "qos remote %s", (self->remote_recv.current && self->remote_send.current) ? "sendrecv" : (self->remote_recv.current ? "recv" : (self->remote_send.current ? "send" : "none")));
+ tsdp_header_M_add_headers(m,
+ TSDP_HEADER_A_VA_ARGS("curr", temp),
+ tsk_null);
+ TSK_FREE(temp);
+
+
+ /* des:local */
+ if(self->local_recv.strength == self->local_send.strength){
+ /* sendrecv */
+ tsk_sprintf(&temp, "qos %s local sendrecv", tmedia_qos_strength_tostring(self->local_send.strength));
+ tsdp_header_M_add_headers(m,
+ TSDP_HEADER_A_VA_ARGS("des", temp),
+ tsk_null);
+ TSK_FREE(temp);
+ }
+ else{
+ /* send */
+ tsk_sprintf(&temp, "qos %s local send", tmedia_qos_strength_tostring(self->local_send.strength));
+ tsdp_header_M_add_headers(m,
+ TSDP_HEADER_A_VA_ARGS("des", temp),
+ tsk_null);
+ TSK_FREE(temp);
+
+ /* recv */
+ tsk_sprintf(&temp, "qos %s local recv", tmedia_qos_strength_tostring(self->local_recv.strength));
+ tsdp_header_M_add_headers(m,
+ TSDP_HEADER_A_VA_ARGS("des", temp),
+ tsk_null);
+ TSK_FREE(temp);
+ }
+
+
+ /* des:remote */
+ if(self->remote_recv.strength == self->remote_send.strength){
+ /* sendrecv */
+ tsk_sprintf(&temp, "qos %s remote sendrecv", tmedia_qos_strength_tostring(self->remote_send.strength));
+ tsdp_header_M_add_headers(m,
+ TSDP_HEADER_A_VA_ARGS("des", temp),
+ tsk_null);
+ TSK_FREE(temp);
+ }
+ else{
+ /* send */
+ tsk_sprintf(&temp, "qos %s remote send", tmedia_qos_strength_tostring(self->remote_send.strength));
+ tsdp_header_M_add_headers(m,
+ TSDP_HEADER_A_VA_ARGS("des", temp),
+ tsk_null);
+ TSK_FREE(temp);
+
+ /* recv */
+ tsk_sprintf(&temp, "qos %s remote recv", tmedia_qos_strength_tostring(self->remote_recv.strength));
+ tsdp_header_M_add_headers(m,
+ TSDP_HEADER_A_VA_ARGS("des", temp),
+ tsk_null);
+ TSK_FREE(temp);
+ }
+
+ /* conf */
+ if(self->remote_recv.confirm || self->remote_send.confirm){
+ tsk_sprintf(&temp, "qos remote %s", (self->remote_recv.confirm && self->remote_send.confirm) ? "sendrecv" : (self->remote_recv.confirm ? "recv" : (self->remote_send.confirm ? "send" : "none")));
+ tsdp_header_M_add_headers(m,
+ TSDP_HEADER_A_VA_ARGS("conf", temp),
+ tsk_null);
+ TSK_FREE(temp);
+ }
+
+ return 0;
+}
+
+int tmedia_qos_tline_segmented_set_ro(tmedia_qos_tline_segmented_t* self, const tmedia_qos_tline_segmented_t* ro)
+{
+ if(!self || !ro){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ //////////////
+ if(!ro->local_recv.current && !ro->remote_recv.confirm){
+ /* request confirmation */
+ self->remote_recv.confirm = tsk_true;
+ }
+ else{
+ self->remote_recv.confirm = tsk_false;
+ self->local_recv.current = tsk_true;
+ }
+ if(!ro->local_send.current && !ro->remote_send.confirm){
+ /* request confirmation */
+ self->remote_send.confirm = tsk_true;
+ }
+ else{
+ self->remote_send.confirm = tsk_false;
+ self->local_send.current = tsk_true;
+ }
+
+ //////////////
+ if(ro->remote_recv.confirm){
+ self->local_recv.current = tsk_true;
+ }
+ if(ro->remote_send.confirm){
+ self->local_send.current = tsk_true;
+ }
+
+ //////////////
+ if(ro->local_recv.current){
+ self->remote_recv.current = tsk_true;
+ }
+ if(ro->local_send.current){
+ self->remote_send.current = tsk_true;
+ }
+
+ return 0;
+}
+
+tsk_bool_t tmedia_qos_tline_segmented_canresume(const tmedia_qos_tline_segmented_t* self)
+{
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_true;
+ }
+
+ /* == Strength is mandatory == */
+ if(self->local_recv.strength == tmedia_qos_strength_mandatory && !self->local_recv.current){
+ return tsk_false;
+ }
+
+ if(self->local_send.strength == tmedia_qos_strength_mandatory && !self->local_send.current){
+ return tsk_false;
+ }
+
+ if(self->remote_recv.strength == tmedia_qos_strength_mandatory && !self->remote_recv.current){
+ return tsk_false;
+ }
+
+ if(self->remote_send.strength == tmedia_qos_strength_mandatory && !self->remote_send.current){
+ return tsk_false;
+ }
+
+ /* "optinal" and "none" strengths */
+ return tsk_true;
+}
+
+//
+// Segmented QoS line object definition
+//
+static tsk_object_t* tmedia_qos_tline_segmented_ctor(tsk_object_t * self, va_list * app)
+{
+ tmedia_qos_tline_segmented_t *segmented = self;
+ if(segmented){
+ segmented->local_recv.strength = segmented->local_send.strength
+ = segmented->remote_recv.strength = segmented->remote_send.strength = va_arg(*app, tmedia_qos_strength_t);
+ TMEDIA_QOS_TLINE(segmented)->type = tmedia_qos_stype_segmented;
+ }
+ return self;
+}
+
+static tsk_object_t* tmedia_qos_tline_segmented_dtor(tsk_object_t * self)
+{
+ tmedia_qos_tline_segmented_t *segmented = self;
+ if(segmented){
+ }
+
+ return self;
+}
+
+static const tsk_object_def_t tmedia_qos_tline_segmented_def_s =
+{
+ sizeof(tmedia_qos_tline_segmented_t),
+ tmedia_qos_tline_segmented_ctor,
+ tmedia_qos_tline_segmented_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tmedia_qos_tline_segmented_def_t = &tmedia_qos_tline_segmented_def_s;
\ No newline at end of file diff --git a/tinyMEDIA/src/tmedia_session.c b/tinyMEDIA/src/tmedia_session.c new file mode 100644 index 0000000..a8d7627 --- /dev/null +++ b/tinyMEDIA/src/tmedia_session.c @@ -0,0 +1,1304 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tmedia_session.h
+ * @brief Base session object.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tinymedia/tmedia_session.h"
+
+#include "tinymedia/tmedia_session_ghost.h"
+
+#include "tinysdp/headers/tsdp_header_O.h"
+
+#include "tsk_memory.h"
+#include "tsk_debug.h"
+
+/**@defgroup tmedia_session_group Media Session
+* For more information about the SOA, please refer to http://betelco.blogspot.com/2010/03/sdp-offeranswer-soa_2993.html
+*/
+
+#if !defined(va_copy)
+# define va_copy(D, S) ((D) = (S))
+#endif
+
+extern const tmedia_codec_plugin_def_t* __tmedia_codec_plugins[TMED_CODEC_MAX_PLUGINS];
+
+/* pointer to all registered sessions */
+const tmedia_session_plugin_def_t* __tmedia_session_plugins[TMED_SESSION_MAX_PLUGINS] = {0};
+
+/* === local functions === */
+int _tmedia_session_mgr_load_sessions(tmedia_session_mgr_t* self);
+int _tmedia_session_mgr_apply_params(tmedia_session_mgr_t* self);
+int _tmedia_session_prepare_lo(tmedia_session_t* self);
+int _tmedia_session_set_ro(tmedia_session_t* self, const tsdp_header_M_t* m);
+int _tmedia_session_load_codecs(tmedia_session_t* self);
+
+const char* tmedia_session_get_media(const tmedia_session_t* self);
+const tsdp_header_M_t* tmedia_session_get_lo(tmedia_session_t* self);
+int tmedia_session_set_ro(tmedia_session_t* self, const tsdp_header_M_t* m);
+
+
+/*== Predicate function to find session object by media */
+int __pred_find_session_by_media(const tsk_list_item_t *item, const void *media)
+{
+ if(item && item->data){
+ return tsk_stricmp(tmedia_session_get_media((const tmedia_session_t *)item->data), (const char*)media);
+ }
+ return -1;
+}
+
+/*== Predicate function to find session object by type */
+int __pred_find_session_by_type(const tsk_list_item_t *item, const void *type)
+{
+ if(item && item->data){
+ return ((const tmedia_session_t *)item->data)->type - *((tmedia_type_t*)type);
+ }
+ return -1;
+}
+
+/**@ingroup tmedia_session_group
+* Initializes a newly created media session.
+* @param self the media session to initialize.
+* @param type the type of the session to initialize.
+* @retval Zero if succeed and non-zero error code otherwise.
+*/
+int tmedia_session_init(tmedia_session_t* self, tmedia_type_t type)
+{
+ int ret = 0;
+ static uint64_t __UniqueId = 1;
+
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if(!self->initialized){
+ /* set values */
+ self->id = ++__UniqueId;
+ self->type = type;
+ self->initialized = tsk_true;
+ self->bl = tmedia_bl_low;
+ /* load associated codecs */
+ ret = _tmedia_session_load_codecs(self);
+ }
+
+ return 0;
+}
+
+/**@ingroup tmedia_session_group
+* Generic function to compare two sessions.
+* @param sess1 The first session to compare.
+* @param sess2 The second session to compare.
+* @retval Returns an integral value indicating the relationship between the two sessions:
+* <0 : @a sess1 less than @a sess2.<br>
+* 0 : @a sess1 identical to @a sess2.<br>
+* >0 : @a sess1 greater than @a sess2.<br>
+*/
+int tmedia_session_cmp(const tsk_object_t* sess1, const tsk_object_t* sess2)
+{
+ return (TMEDIA_SESSION(sess1) - TMEDIA_SESSION(sess2));
+}
+
+/**@ingroup tmedia_session_group
+* Registers a session plugin.
+* @param plugin the definition of the plugin.
+* @retval Zero if succeed and non-zero error code otherwise.
+* @sa @ref tmedia_session_create()
+*/
+int tmedia_session_plugin_register(const tmedia_session_plugin_def_t* plugin)
+{
+ tsk_size_t i;
+ if(!plugin){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ /* add or replace the plugin */
+ for(i = 0; i<TMED_SESSION_MAX_PLUGINS; i++){
+ if(!__tmedia_session_plugins[i] || (__tmedia_session_plugins[i] == plugin)){
+ __tmedia_session_plugins[i] = plugin;
+ return 0;
+ }
+ }
+
+ TSK_DEBUG_ERROR("There are already %d plugins.", TMED_SESSION_MAX_PLUGINS);
+ return -2;
+}
+
+/**@ingroup tmedia_session_group
+* Finds a plugin by media.
+*/
+const tmedia_session_plugin_def_t* tmedia_session_plugin_find_by_media(const char* media)
+{
+ tsk_size_t i = 0;
+ if(tsk_strnullORempty(media)){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_null;
+ }
+
+ /* add or replace the plugin */
+ while((i<TMED_SESSION_MAX_PLUGINS) && (__tmedia_session_plugins[i])){
+ if(tsk_striequals(__tmedia_session_plugins[i]->media, media)){
+ return __tmedia_session_plugins[i];
+ }
+ i++;
+ }
+ return tsk_null;
+}
+
+/**@ingroup tmedia_session_group
+* UnRegisters a session plugin.
+* @param plugin the definition of the plugin.
+* @retval Zero if succeed and non-zero error code otherwise.
+*/
+int tmedia_session_plugin_unregister(const tmedia_session_plugin_def_t* plugin)
+{
+ tsk_size_t i;
+ tsk_bool_t found = tsk_false;
+ if(!plugin){
+ TSK_DEBUG_ERROR("Invalid Parameter");
+ return -1;
+ }
+
+ /* find the plugin to unregister */
+ for(i = 0; i<TMED_SESSION_MAX_PLUGINS && __tmedia_session_plugins[i]; i++){
+ if(__tmedia_session_plugins[i] == plugin){
+ __tmedia_session_plugins[i] = tsk_null;
+ found = tsk_true;
+ break;
+ }
+ }
+
+ /* compact */
+ if(found){
+ for(; i<(TMED_SESSION_MAX_PLUGINS - 1); i++){
+ if(__tmedia_session_plugins[i+1]){
+ __tmedia_session_plugins[i] = __tmedia_session_plugins[i+1];
+ }
+ else{
+ break;
+ }
+ }
+ __tmedia_session_plugins[i] = tsk_null;
+ }
+ return (found ? 0 : -2);
+}
+
+/**@ingroup tmedia_session_group
+* Creates a new session using an already registered plugin.
+* @param format The type of the codec to create.
+* @sa @ref tmedia_codec_plugin_register()
+*/
+tmedia_session_t* tmedia_session_create(tmedia_type_t type)
+{
+ tmedia_session_t* session = tsk_null;
+ const tmedia_session_plugin_def_t* plugin;
+ tsk_size_t i = 0;
+
+ while((i < TMED_SESSION_MAX_PLUGINS) && (plugin = __tmedia_session_plugins[i++])){
+ if(plugin->objdef && (plugin->type == type)){
+ if((session = tsk_object_new(plugin->objdef))){
+ if(!session->initialized){
+ tmedia_session_init(session, type);
+ }
+ session->plugin = plugin;
+ }
+ break;
+ }
+ }
+ return session;
+}
+
+/* internal funtion: prepare lo */
+int _tmedia_session_prepare_lo(tmedia_session_t* self)
+{
+ int ret;
+ if(!self || !self->plugin || !self->plugin->prepare){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if(self->prepared){
+ TSK_DEBUG_WARN("Session already prepared");
+ return 0;
+ }
+ if((ret = self->plugin->prepare(self))){
+ TSK_DEBUG_ERROR("Failed to prepare the session");
+ }
+ else{
+ self->prepared = tsk_true;
+ }
+ return ret;
+}
+
+/* internal function used to set remote offer */
+int _tmedia_session_set_ro(tmedia_session_t* self, const tsdp_header_M_t* m)
+{
+ int ret;
+ if(!self || !self->plugin || !self->plugin->set_remote_offer){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if(!(ret = self->plugin->set_remote_offer(self, m))){
+ self->ro_changed = tsk_true;
+ }
+ return ret;
+}
+
+/* internal function: get media */
+const char* tmedia_session_get_media(const tmedia_session_t* self)
+{
+ if(!self || !self->plugin){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_null;
+ }
+
+ /* ghost? */
+ if(self->plugin == tmedia_session_ghost_plugin_def_t){
+ return ((const tmedia_session_ghost_t*)self)->media;
+ }
+ else{
+ return self->plugin->media;
+ }
+}
+/* internal function: get local offer */
+const tsdp_header_M_t* tmedia_session_get_lo(tmedia_session_t* self)
+{
+ const tsdp_header_M_t* m;
+
+ if(!self || !self->plugin || !self->plugin->get_local_offer){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_null;
+ }
+
+ if((m = self->plugin->get_local_offer(self))){
+ self->ro_changed = tsk_false; /* we should have a fresh local offer (based on the latest ro) */
+ }
+ return m;
+}
+
+/* Match a codec */
+tmedia_codecs_L_t* tmedia_session_match_codec(tmedia_session_t* self, const tsdp_header_M_t* M)
+{
+ const tmedia_codec_t *codec;
+ char *rtpmap = tsk_null, *fmtp = tsk_null, *name = tsk_null;
+ const tsdp_fmt_t* fmt;
+ const tsk_list_item_t *it1, *it2;
+ tsk_bool_t found = tsk_false;
+ tmedia_codecs_L_t* matchingCodecs = tsk_null;
+
+ if(!self || !M){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_null;
+ }
+
+
+ /* foreach format */
+ tsk_list_foreach(it1, M->FMTs){
+ fmt = it1->data;
+
+ /* foreach codec */
+ tsk_list_foreach(it2, self->codecs){
+ if(!(codec = it2->data) || !codec->plugin){
+ continue;
+ }
+
+ // Dyn. payload type
+ if(codec->dyn && (rtpmap = tsdp_header_M_get_rtpmap(M, fmt->value))){
+ int32_t rate, channels;
+ /* parse rtpmap */
+ if(tmedia_parse_rtpmap(rtpmap, &name, &rate, &channels)){
+ goto next;
+ }
+
+ /* compare name and rate. what about channels? */
+ if(tsk_striequals(name, codec->name) && (!rate || (codec->plugin->rate == rate))){
+ goto compare_fmtp;
+ }
+ }
+ // Fixed payload type
+ else{
+ if(tsk_striequals(fmt->value, codec->format)){
+ goto compare_fmtp;
+ }
+ }
+
+ /* rtpmap do not match: free strings and try next codec */
+ goto next;
+
+compare_fmtp:
+ if((fmtp = tsdp_header_M_get_fmtp(M, fmt->value))){ /* remote have fmtp? */
+ if(tmedia_codec_match_fmtp(codec, fmtp)){ /* fmtp matches? */
+ tsk_strupdate((char**)&codec->neg_format, fmt->value);
+ found = tsk_true;
+ }
+ }
+ else{ /* no fmtp -> always match */
+ tsk_strupdate((char**)&codec->neg_format, fmt->value);
+ found = tsk_true;
+ }
+next:
+ TSK_FREE(name);
+ TSK_FREE(fmtp);
+ TSK_FREE(rtpmap);
+ if(found){
+ tmedia_codec_t * copy;
+ if(!matchingCodecs){
+ matchingCodecs = tsk_list_create();
+ }
+ copy = tsk_object_ref((void*)codec);
+ tsk_list_push_back_data(matchingCodecs, (void**)©);
+
+ found = tsk_false;
+ break;
+ }
+ }
+ }
+
+
+ return matchingCodecs;
+}
+
+
+/**@ingroup tmedia_session_group
+* DeInitializes a media session.
+* @param self the media session to deinitialize.
+* @retval Zero if succeed and non-zero error code otherwise.
+*/
+int tmedia_session_deinit(tmedia_session_t* self)
+{
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ /* free codecs */
+ TSK_OBJECT_SAFE_FREE(self->codecs);
+ TSK_OBJECT_SAFE_FREE(self->neg_codecs);
+
+ /* free lo, no and ro */
+ TSK_OBJECT_SAFE_FREE(self->M.lo);
+ TSK_OBJECT_SAFE_FREE(self->M.ro);
+
+ /* QoS */
+ TSK_OBJECT_SAFE_FREE(self->qos);
+
+ return 0;
+}
+
+/**@ingroup tmedia_session_group
+* Send DTMF event
+* @param self the audio session to use to send a DTMF event
+* @param event the DTMF event to send (should be between 0-15)
+* @retval Zero if succeed and non-zero error code otherwise.
+*/
+int tmedia_session_audio_send_dtmf(tmedia_session_audio_t* self, uint8_t event)
+{
+ if(!self || !TMEDIA_SESSION(self)->plugin || !TMEDIA_SESSION(self)->plugin->audio.send_dtmf){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ return TMEDIA_SESSION(self)->plugin->audio.send_dtmf(TMEDIA_SESSION(self), event);
+}
+
+/* internal function used to prepare a session */
+int _tmedia_session_load_codecs(tmedia_session_t* self)
+{
+ tsk_size_t i = 0;
+ tmedia_codec_t* codec;
+ const tmedia_codec_plugin_def_t* plugin;
+
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ /* remove old codecs */
+ TSK_OBJECT_SAFE_FREE(self->codecs);
+
+ /* for each registered plugin create a session instance */
+ while((i < TMED_CODEC_MAX_PLUGINS) && (plugin = __tmedia_codec_plugins[i++])){
+ if((plugin->type & self->type) == plugin->type){
+ if((codec = tmedia_codec_create(plugin->format))){
+ if(!self->codecs){
+ self->codecs = tsk_list_create();
+ }
+ tsk_list_push_back_data(self->codecs, (void**)(&codec));
+ }
+ }
+ }
+ return 0;
+}
+
+
+/**@ingroup tmedia_session_group
+* Creates new session manager.
+* @param type the type of the session to create. For example, (@ref tmed_sess_type_audio | @ref tmed_sess_type_video).
+* @param addr the local ip address or FQDN to use in the sdp message.
+* @param ipv6 indicates whether @a addr is IPv6 address or not. Useful when @a addr is a FQDN.
+* @param load_sessions Whether the offerer or not.
+* will create an audio/video session.
+* @retval new @ref tmedia_session_mgr_t object
+*/
+tmedia_session_mgr_t* tmedia_session_mgr_create(tmedia_type_t type, const char* addr, tsk_bool_t ipv6, tsk_bool_t offerer)
+{
+ tmedia_session_mgr_t* mgr;
+
+ if(!(mgr = tsk_object_new(tmedia_session_mgr_def_t))){
+ TSK_DEBUG_ERROR("Failed to create Media Session manager");
+ return tsk_null;
+ }
+
+ /* init */
+ mgr->type = type;
+ mgr->addr = tsk_strdup(addr);
+ mgr->ipv6 = ipv6;
+
+ /* load sessions (will allow us to generate lo) */
+ if(offerer){
+ mgr->offerer = tsk_true;
+ if(_tmedia_session_mgr_load_sessions(mgr)){
+ /* Do nothing */
+ TSK_DEBUG_ERROR("Failed to load sessions");
+ }
+ }
+
+ return mgr;
+}
+
+/**@ingroup tmedia_session_group
+*/
+tmedia_session_t* tmedia_session_mgr_find(tmedia_session_mgr_t* self, tmedia_type_t type)
+{
+ tmedia_session_t* session = (tmedia_session_t*)tsk_list_find_object_by_pred(self->sessions, __pred_find_session_by_type, &type);
+ return tsk_object_ref(session);
+}
+
+/**@ingroup tmedia_session_group
+*/
+int tmedia_session_mgr_set_natt_ctx(tmedia_session_mgr_t* self, tnet_nat_context_handle_t* natt_ctx, const char* public_addr)
+{
+ if(!self || !natt_ctx){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ TSK_OBJECT_SAFE_FREE(self->natt_ctx);
+ self->natt_ctx = tsk_object_ref(natt_ctx);
+ tsk_strupdate(&self->public_addr, public_addr);
+
+ tmedia_session_mgr_set(self,
+ TMEDIA_SESSION_SET_POBJECT(self->type, "natt-ctx", self->natt_ctx),
+ TMEDIA_SESSION_SET_NULL());
+ return 0;
+}
+
+/**@ingroup tmedia_session_group
+* Starts the session manager by starting all underlying sessions.
+* You should set both remote and local offers before calling this function.
+* @param self The session manager to start.
+* @retval Zero if succced and non-zero error code otherwise.
+*
+* @sa @ref tmedia_session_mgr_stop
+*/
+int tmedia_session_mgr_start(tmedia_session_mgr_t* self)
+{
+ int ret;
+ tsk_list_item_t* item;
+ tmedia_session_t* session;
+
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if(self->started){
+ TSK_DEBUG_WARN("Session manager already started");
+ return 0;
+ }
+
+ tsk_list_foreach(item, self->sessions){
+ if(!(session = item->data) || !session->plugin || !session->plugin->start){
+ TSK_DEBUG_ERROR("Invalid session");
+ return -2;
+ }
+ if((ret = session->plugin->start(session))){
+ TSK_DEBUG_ERROR("Failed to start %s session", session->plugin->media);
+ continue;
+ }
+ }
+
+ self->started = tsk_true;
+ return 0;
+}
+
+/**@ingroup tmedia_session_group
+* sets parameters for one or several sessions.
+* @param self The session manager
+* @param ... Any TMEDIA_SESSION_SET_*() macros
+* @retval Zero if succeed and non-zero error code otherwise
+*/
+int tmedia_session_mgr_set(tmedia_session_mgr_t* self, ...)
+{
+ va_list ap;
+ int ret;
+
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ va_start(ap, self);
+ ret = tmedia_session_mgr_set_2(self, &ap);
+ va_end(ap);
+
+ return ret;
+}
+
+/**@ingroup tmedia_session_group
+* sets parameters for one or several sessions.
+* @param self The session manager
+* @param app List of parameters.
+* @retval Zero if succeed and non-zero error code otherwise
+*/
+int tmedia_session_mgr_set_2(tmedia_session_mgr_t* self, va_list *app)
+{
+ tmedia_params_L_t* params;
+
+ if(!self || !app){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if((params = tmedia_params_create_2(app))){
+ if(!self->params){
+ self->params = tsk_object_ref(params);
+ }
+ else{
+ tsk_list_pushback_list(self->params, params);
+ }
+ TSK_OBJECT_SAFE_FREE(params);
+ }
+
+ /* load params if we already have sessions */
+ if(!TSK_LIST_IS_EMPTY(self->sessions)){
+ _tmedia_session_mgr_apply_params(self);
+ }
+
+ return 0;
+}
+
+/**@ingroup tmedia_session_group
+* sets parameters for one or several sessions.
+* @param self The session manager
+* @param params List of parameters to set
+* @retval Zero if succeed and non-zero error code otherwise
+*/
+int tmedia_session_mgr_set_3(tmedia_session_mgr_t* self, const tmedia_params_L_t* params)
+{
+ if(!self || !params){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if(!self->params){
+ self->params = tsk_list_create();
+ }
+ tsk_list_pushback_list(self->params, params);
+
+ /* load params if we already have sessions */
+ if(!TSK_LIST_IS_EMPTY(self->sessions)){
+ _tmedia_session_mgr_apply_params(self);
+ }
+
+ return 0;
+}
+
+/**@ingroup tmedia_session_group
+* Stops the session manager by stopping all underlying sessions.
+* @param self The session manager to stop.
+* @retval Zero if succced and non-zero error code otherwise.
+*
+* @sa @ref tmedia_session_mgr_start
+*/
+int tmedia_session_mgr_stop(tmedia_session_mgr_t* self)
+{
+ int ret;
+ tsk_list_item_t* item;
+ tmedia_session_t* session;
+
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if(!self->started){
+ TSK_DEBUG_WARN("Session manager not started");
+ return 0;
+ }
+
+ tsk_list_foreach(item, self->sessions){
+ if(!(session = item->data) || !session->plugin || !session->plugin->stop){
+ TSK_DEBUG_ERROR("Invalid session");
+ return -2;
+ }
+ if((ret = session->plugin->stop(session))){
+ TSK_DEBUG_ERROR("Failed to stop session");
+ return ret;
+ }
+ }
+ self->started = tsk_false;
+ return 0;
+}
+
+/**@ingroup tmedia_session_group
+* Gets local offer.
+*/
+const tsdp_message_t* tmedia_session_mgr_get_lo(tmedia_session_mgr_t* self)
+{
+ const tsk_list_item_t* item;
+ const tmedia_session_t* ms;
+ const tsdp_header_M_t* m;
+
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_null;
+ }
+
+ /* prepare the session manager if not already done (create all sessions) */
+ if(TSK_LIST_IS_EMPTY(self->sessions)){
+ if(_tmedia_session_mgr_load_sessions(self)){
+ TSK_DEBUG_ERROR("Failed to prepare the session manager");
+ return tsk_null;
+ }
+ }
+
+ /* creates local sdp if not already done or update it's value (because of set_ro())*/
+ if((self->ro_changed || self->state_changed) && self->sdp.lo){
+ TSK_OBJECT_SAFE_FREE(self->sdp.lo);
+ self->ro_changed = tsk_false;
+ self->state_changed = tsk_false;
+ }
+
+ if(self->sdp.lo){
+ return self->sdp.lo;
+ }
+ else if((self->sdp.lo = tsdp_message_create_empty(self->public_addr ? self->public_addr : self->addr, self->ipv6, self->sdp.lo_ver++))){
+ /* Set connection "c=" */
+ tsdp_message_add_headers(self->sdp.lo,
+ TSDP_HEADER_C_VA_ARGS("IN", self->ipv6 ? "IP6" : "IP4", self->public_addr ? self->public_addr : self->addr),
+ tsk_null);
+ }else{
+ self->sdp.lo_ver--;
+ TSK_DEBUG_ERROR("Failed to create empty SDP message");
+ return tsk_null;
+ }
+
+ /* gets each "m=" line from the sessions and add them to the local sdp */
+ tsk_list_foreach(item, self->sessions){
+ if(!(ms = item->data) || !ms->plugin){
+ TSK_DEBUG_ERROR("Invalid session");
+ continue;
+ }
+ /* prepare the media session */
+ if(!ms->prepared && (_tmedia_session_prepare_lo(TMEDIA_SESSION(ms)))){
+ TSK_DEBUG_ERROR("Failed to prepare session"); /* should never happen */
+ continue;
+ }
+
+ /* Add QoS lines to our local media */
+ if((self->qos.type != tmedia_qos_stype_none) && !TMEDIA_SESSION(ms)->qos){
+ TMEDIA_SESSION(ms)->qos = tmedia_qos_tline_create(self->qos.type, self->qos.strength);
+ }
+
+ /* add "m=" line from the session to the local sdp */
+ if((m = tmedia_session_get_lo(TMEDIA_SESSION(ms)))){
+ tsdp_message_add_header(self->sdp.lo, TSDP_HEADER(m));
+ }
+ else{
+ TSK_DEBUG_ERROR("Failed to get m= line for [%s] media", ms->plugin->media);
+ }
+ }
+
+ return self->sdp.lo;
+}
+
+
+/**@ingroup tmedia_session_group
+* Sets remote offer.
+*/
+int tmedia_session_mgr_set_ro(tmedia_session_mgr_t* self, const tsdp_message_t* sdp)
+{
+ const tmedia_session_t* ms;
+ const tsdp_header_M_t* M;
+ const tsdp_header_C_t* C; /* global "c=" line */
+ const tsdp_header_O_t* O;
+ tsk_size_t index = 0;
+ tsk_bool_t found;
+ tmedia_qos_stype_t qos_type = tmedia_qos_stype_none;
+
+ if(!self || !sdp){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ /* RFC 3264 subcaluse 8
+ When issuing an offer that modifies the session, the "o=" line of the new SDP MUST be identical to that in the previous SDP,
+ except that the version in the origin field MUST increment by one from the previous SDP. If the version in the origin line
+ does not increment, the SDP MUST be identical to the SDP with that version number. The answerer MUST be prepared to receive
+ an offer that contains SDP with a version that has not changed; this is effectively a no-op.
+ */
+ if((O = (const tsdp_header_O_t*)tsdp_message_get_header(sdp, tsdp_htype_O))){
+ if(self->sdp.ro_ver == (int32_t)O->sess_version){
+ TSK_DEBUG_INFO("Remote offer has not changed");
+ return 0;
+ }
+ self->sdp.ro_ver = (int32_t)O->sess_version;
+ }
+ else{
+ TSK_DEBUG_ERROR("o= line is missing");
+ return -2;
+ }
+
+ /* update remote offer */
+ TSK_OBJECT_SAFE_FREE(self->sdp.ro);
+ self->sdp.ro = tsk_object_ref((void*)sdp);
+
+ /* prepare the session manager if not already done (create all sessions with their codecs)
+ * if network-initiated: think about tmedia_type_from_sdp() before creating the manager */
+ if(TSK_LIST_IS_EMPTY(self->sessions)){
+ if(_tmedia_session_mgr_load_sessions(self)){
+ TSK_DEBUG_ERROR("Failed to prepare the session manager");
+ return -3;
+ }
+ }
+
+ /* get global connection line (common to all sessions)
+ * Each session should override this info if it has a different one in its "m=" line
+ */
+ if((C = (const tsdp_header_C_t*)tsdp_message_get_header(sdp, tsdp_htype_C)) && C->addr){
+ tmedia_session_mgr_set(self,
+ TMEDIA_SESSION_SET_STR(self->type, "remote-ip", C->addr),
+ TMEDIA_SESSION_SET_NULL());
+ }
+
+ /* foreach "m=" line in the remote offer create a session*/
+ while((M = (const tsdp_header_M_t*)tsdp_message_get_headerAt(sdp, tsdp_htype_M, index++))){
+ found = tsk_false;
+ /* Find session by media */
+ if((ms = tsk_list_find_object_by_pred(self->sessions, __pred_find_session_by_media, M->media))){
+ /* set remote ro at session-level */
+ if(_tmedia_session_set_ro(TMEDIA_SESSION(ms), M) == 0){
+ found = tsk_true;
+ }
+ /* set QoS type (only if we are not the offerer) */
+ if(/*!self->offerer ==> we suppose that the remote party respected our demand &&*/ (qos_type == tmedia_qos_stype_none)){
+ tmedia_qos_tline_t* tline = tmedia_qos_tline_from_sdp(M);
+ if(tline){
+ qos_type = tline->type;
+ TSK_OBJECT_SAFE_FREE(tline);
+ }
+ }
+ }
+
+ if(!found && (self->sdp.lo == tsk_null)){
+ /* Session not supported and we are not the initial offerer ==> add ghost session */
+ tmedia_session_ghost_t* ghost;
+ if((ghost = (tmedia_session_ghost_t*)tmedia_session_create(tmedia_ghost))){
+ tsk_strupdate(&ghost->media, M->media); /* copy media */
+ tsk_list_push_back_data(self->sessions, (void**)&ghost);
+ }
+ else{
+ TSK_DEBUG_ERROR("Failed to create ghost session");
+ continue;
+ }
+ }
+ }
+
+ /* Update QoS type */
+ if(!self->offerer && (qos_type != tmedia_qos_stype_none)){
+ self->qos.type = qos_type;
+ }
+
+ /* signal that ro has changed (will be used to update lo) */
+ self->ro_changed = tsk_true;
+
+ return 0;
+}
+
+/**@ingroup tmedia_session_group
+* Holds the session as per 3GPP TS 34.610
+* @param self the session manager managing the session to hold.
+* @param type the type of the sessions to hold (you can combine several medias. e.g. audio|video|msrp).
+* @retval Zero if succeed and non zero error code otherwise.
+* @sa @ref tmedia_session_mgr_resume
+*/
+int tmedia_session_mgr_hold(tmedia_session_mgr_t* self, tmedia_type_t type)
+{
+ const tsk_list_item_t* item;
+
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ tsk_list_foreach(item, self->sessions){
+ tmedia_session_t* session = TMEDIA_SESSION(item->data);
+ if(((session->type & type) == session->type) && session->M.lo){
+ if(!tsdp_header_M_hold(session->M.lo, tsk_true)){
+ self->state_changed = tsk_true;
+ }
+ }
+ }
+ return 0;
+}
+
+/**@ingroup tmedia_session_group
+* Indicates whether the specified medias are held or not.
+* @param self the session manager
+* @param type the type of the medias to check (you can combine several medias. e.g. audio|video|msrp)
+* @param local whether to check local or remote medias
+*/
+tsk_bool_t tmedia_session_mgr_is_held(tmedia_session_mgr_t* self, tmedia_type_t type, tsk_bool_t local)
+{
+ const tsk_list_item_t* item;
+ tsk_bool_t have_these_sessions = tsk_false;
+
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_false;
+ }
+
+ tsk_list_foreach(item, self->sessions){
+ tmedia_session_t* session = TMEDIA_SESSION(item->data);
+ if((session->type & type) == session->type){
+ if(local && session->M.lo){
+ have_these_sessions = tsk_true;
+ if(!tsdp_header_M_is_held(session->M.lo, tsk_true)){
+ return tsk_false;
+ }
+ }
+ else if(!local && session->M.ro){
+ have_these_sessions = tsk_true;
+ if(!tsdp_header_M_is_held(session->M.ro, tsk_false)){
+ return tsk_false;
+ }
+ }
+ }
+ }
+ /* none is held */
+ return have_these_sessions ? tsk_true : tsk_false;
+}
+
+/**@ingroup tmedia_session_group
+* Resumes the session as per 3GPP TS 34.610. Should be previously held
+* by using @ref tmedia_session_mgr_hold.
+* @param self the session manager managing the session to resume.
+* @param type the type of the sessions to resume (you can combine several medias. e.g. audio|video|msrp).
+* @retval Zero if succeed and non zero error code otherwise.
+* @sa @ref tmedia_session_mgr_hold
+*/
+int tmedia_session_mgr_resume(tmedia_session_mgr_t* self, tmedia_type_t type)
+{
+ const tsk_list_item_t* item;
+
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ tsk_list_foreach(item, self->sessions){
+ tmedia_session_t* session = TMEDIA_SESSION(item->data);
+ if(((session->type & type) == session->type) && session->M.lo){
+ if(!tsdp_header_M_resume(session->M.lo, tsk_true)){
+ self->state_changed = tsk_true;
+ }
+ }
+ }
+ return 0;
+}
+
+/**@ingroup tmedia_session_group
+* Adds new medias to the manager. A media will only be added if it is missing
+* or previously removed (slot with port equal to zero).
+* @param self The session manager
+* @param The types of the medias to add (ou can combine several medias. e.g. audio|video|msrp)
+* @retval Zero if succeed and non zero error code otherwise.
+*/
+int tmedia_session_mgr_add_media(tmedia_session_mgr_t* self, tmedia_type_t type)
+{
+ tsk_size_t i = 0;
+ tmedia_session_t* session;
+ const tmedia_session_plugin_def_t* plugin;
+
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ /* for each registered plugin match with the supplied type */
+ while((i < TMED_SESSION_MAX_PLUGINS) && (plugin = __tmedia_session_plugins[i++])){
+ if((plugin->type & type) == plugin->type){
+ /* check whether we already support this media */
+ if((session = (tmedia_session_t*)tsk_list_find_object_by_pred(self->sessions, __pred_find_session_by_type, &plugin->type)) && session->plugin){
+ if(session->prepared){
+ TSK_DEBUG_WARN("[%s] already active", plugin->media);
+ }
+ else{
+ /* exist but unprepared(port=0) */
+ _tmedia_session_prepare_lo(session);
+ if(self->started && session->plugin->start){
+ session->plugin->start(session);
+ }
+ self->state_changed = tsk_true;
+ }
+ }
+ else{
+ /* session not supported */
+ self->state_changed = tsk_true;
+ if((session = tmedia_session_create(plugin->type))){
+ if(self->started && session->plugin->start){
+ session->plugin->start(session);
+ }
+ tsk_list_push_back_data(self->sessions, (void**)(&session));
+ self->state_changed = tsk_true;
+ }
+ }
+ }
+ }
+
+ return self->state_changed ? 0 : -2;
+}
+
+/**@ingroup tmedia_session_group
+* Removes medias from the manager. This action will stop the media and sets it's port value to zero (up to the session).
+* @param self The session manager
+* @param The types of the medias to remove (ou can combine several medias. e.g. audio|video|msrp)
+* @retval Zero if succeed and non zero error code otherwise.
+*/
+int tmedia_session_mgr_remove_media(tmedia_session_mgr_t* self, tmedia_type_t type)
+{
+ const tsk_list_item_t* item;
+
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ tsk_list_foreach(item, self->sessions){
+ tmedia_session_t* session = TMEDIA_SESSION(item->data);
+ if(((session->type & type) == session->type) && session->plugin->stop){
+ if(!session->plugin->stop(session)){
+ self->state_changed = tsk_true;
+ }
+ }
+ }
+ return 0;
+}
+
+/**@ingroup tmedia_session_group
+* Sets QoS type and strength
+* @param self The session manager
+* @param qos_type The QoS type
+* @param qos_strength The QoS strength
+* @retval Zero if succeed and non-zero error code otherwise
+*/
+int tmedia_session_mgr_set_qos(tmedia_session_mgr_t* self, tmedia_qos_stype_t qos_type, tmedia_qos_strength_t qos_strength)
+{
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ self->qos.type = qos_type;
+ self->qos.strength = qos_strength;
+ return 0;
+}
+
+/**@ingroup tmedia_session_group
+* Indicates whether all preconditions are met
+* @param self The session manager
+* @retval @a tsk_true if all preconditions have been met and @a tsk_false otherwise
+*/
+tsk_bool_t tmedia_session_mgr_canresume(tmedia_session_mgr_t* self)
+{
+ const tsk_list_item_t* item;
+
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_true;
+ }
+
+ tsk_list_foreach(item, self->sessions){
+ tmedia_session_t* session = TMEDIA_SESSION(item->data);
+ if(session && session->qos && !tmedia_qos_tline_canresume(session->qos)){
+ return tsk_false;
+ }
+ }
+ return tsk_true;
+}
+
+
+/**@ingroup tmedia_session_group
+* Checks whether the manager holds at least one valid session (media port <> 0)
+*/
+tsk_bool_t tmedia_session_mgr_has_active_session(tmedia_session_mgr_t* self)
+{
+ const tsk_list_item_t* item;
+
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_false;
+ }
+
+ tsk_list_foreach(item, self->sessions){
+ tmedia_session_t* session = TMEDIA_SESSION(item->data);
+ if(session && session->M.lo && session->M.lo->port){
+ return tsk_true;
+ }
+ }
+ return tsk_false;
+}
+
+int tmedia_session_mgr_send_dtmf(tmedia_session_mgr_t* self, uint8_t event)
+{
+ tmedia_session_audio_t* session;
+ tmedia_type_t audio_type = tmedia_audio;
+ int ret = -3;
+
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ session = (tmedia_session_audio_t*)tsk_list_find_object_by_pred(self->sessions, __pred_find_session_by_type, &audio_type);
+ if(session){
+ session = tsk_object_ref(session);
+ ret = tmedia_session_audio_send_dtmf(TMEDIA_SESSION_AUDIO(session), event);
+ TSK_OBJECT_SAFE_FREE(session);
+ }
+ else{
+ TSK_DEBUG_ERROR("No audio session associated to this manager");
+ }
+
+ return ret;
+}
+
+int tmedia_session_mgr_send_file(tmedia_session_mgr_t* self, const char* path, ...)
+{
+ tmedia_session_msrp_t* session;
+ tmedia_type_t msrp_type = tmedia_msrp;
+ int ret = -3;
+
+ if(!self || !path){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ session = (tmedia_session_msrp_t*)tsk_list_find_object_by_pred(self->sessions, __pred_find_session_by_type, &msrp_type);
+ if(session && session->send_file){
+ va_list ap; + va_start(ap, path);
+ session = tsk_object_ref(session);
+ ret = session->send_file(TMEDIA_SESSION_MSRP(session), path, &ap);
+ TSK_OBJECT_SAFE_FREE(session);
+ va_end(ap);
+ }
+ else{
+ TSK_DEBUG_ERROR("No MSRP session associated to this manager or session does not support file transfer");
+ }
+
+ return ret;
+}
+
+int tmedia_session_mgr_send_message(tmedia_session_mgr_t* self, const void* data, tsk_size_t size, const tmedia_params_L_t *params)
+{
+ tmedia_session_msrp_t* session;
+ tmedia_type_t msrp_type = tmedia_msrp;
+ int ret = -3;
+
+ if(!self || !size || !data){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ session = (tmedia_session_msrp_t*)tsk_list_find_object_by_pred(self->sessions, __pred_find_session_by_type, &msrp_type);
+ if(session && session->send_message){
+ session = tsk_object_ref(session);
+ ret = session->send_message(TMEDIA_SESSION_MSRP(session), data, size, params);
+ TSK_OBJECT_SAFE_FREE(session);
+ }
+ else{
+ TSK_DEBUG_ERROR("No MSRP session associated to this manager or session does not support file transfer");
+ }
+
+ return ret;
+}
+
+int tmedia_session_mgr_set_msrp_cb(tmedia_session_mgr_t* self, const void* callback_data, tmedia_session_msrp_cb_f func)
+{
+ tmedia_session_msrp_t* session;
+ tmedia_type_t msrp_type = tmedia_msrp;
+
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if((session = (tmedia_session_msrp_t*)tsk_list_find_object_by_pred(self->sessions, __pred_find_session_by_type, &msrp_type))){
+ session->callback.data = callback_data;
+ session->callback.func = func;
+ return 0;
+ }
+ else{
+ TSK_DEBUG_ERROR("No MSRP session associated to this manager or session does not support file transfer");
+ return -2;
+ }
+}
+
+/** internal function used to load sessions */
+int _tmedia_session_mgr_load_sessions(tmedia_session_mgr_t* self)
+{
+ tsk_size_t i = 0;
+ tmedia_session_t* session;
+ const tmedia_session_plugin_def_t* plugin;
+
+ if(TSK_LIST_IS_EMPTY(self->sessions)){
+ /* for each registered plugin create a session instance */
+ while((i < TMED_SESSION_MAX_PLUGINS) && (plugin = __tmedia_session_plugins[i++])){
+ if((plugin->type & self->type) == plugin->type){
+ if((session = tmedia_session_create(plugin->type))){
+ tsk_list_push_back_data(self->sessions, (void**)(&session));
+ }
+ }
+ }
+ /* set default values */
+ tmedia_session_mgr_set(self,
+ TMEDIA_SESSION_SET_STR(self->type, "local-ip", self->addr),
+ TMEDIA_SESSION_SET_STR(self->type, "local-ipver", self->ipv6 ? "ipv6" : "ipv4"),
+ TMEDIA_SESSION_SET_INT32(self->type, "bandwidth-level", self->bl),
+ TMEDIA_SESSION_SET_NULL());
+
+ /* load params */
+ _tmedia_session_mgr_apply_params(self);
+ }
+ return 0;
+}
+
+/* internal function */
+int _tmedia_session_mgr_apply_params(tmedia_session_mgr_t* self)
+{
+ tsk_list_item_t *it1, *it2;
+ tmedia_param_t* param;
+ tmedia_session_t* session;
+
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ /* If no parameters ==> do nothing (not error) */
+ if(TSK_LIST_IS_EMPTY(self->params)){
+ return 0;
+ }
+
+ tsk_list_lock(self->params);
+
+ tsk_list_foreach(it1, self->params){
+ if(!(param = it1->data)){
+ continue;
+ }
+
+ /* For us */
+ if(param->plugin_type == tmedia_ppt_manager){
+ continue;
+ }
+
+ /* For the session (or consumer or producer or codec) */
+ tsk_list_foreach(it2, self->sessions){
+ if(!(session = it2->data) || !session->plugin){
+ continue;
+ }
+ if((session->type & param->media_type) == session->type && session->plugin->set){
+ session->plugin->set(session, param);
+ }
+ }
+ }
+
+ /* Clean up params */
+ tsk_list_clear_items(self->params);
+
+ tsk_list_unlock(self->params);
+
+ return 0;
+}
+
+//=================================================================================================
+// Media Session Manager object definition
+//
+static tsk_object_t* tmedia_session_mgr_ctor(tsk_object_t * self, va_list * app)
+{
+ tmedia_session_mgr_t *mgr = self;
+ if(mgr){
+ mgr->sessions = tsk_list_create();
+
+ mgr->sdp.lo_ver = TSDP_HEADER_O_SESS_VERSION_DEFAULT;
+ mgr->sdp.ro_ver = -1;
+
+ mgr->qos.type = tmedia_qos_stype_none;
+ mgr->qos.strength = tmedia_qos_strength_optional;
+ mgr->bl = tmedia_bl_low;
+ }
+ return self;
+}
+
+static tsk_object_t* tmedia_session_mgr_dtor(tsk_object_t * self)
+{
+ tmedia_session_mgr_t *mgr = self;
+ if(mgr){
+ TSK_OBJECT_SAFE_FREE(mgr->sessions);
+
+ TSK_OBJECT_SAFE_FREE(mgr->sdp.lo);
+ TSK_OBJECT_SAFE_FREE(mgr->sdp.ro);
+
+ TSK_OBJECT_SAFE_FREE(mgr->params);
+
+ TSK_OBJECT_SAFE_FREE(mgr->natt_ctx);
+ TSK_FREE(mgr->public_addr);
+
+ TSK_FREE(mgr->addr);
+ }
+
+ return self;
+}
+
+static const tsk_object_def_t tmedia_session_mgr_def_s =
+{
+ sizeof(tmedia_session_mgr_t),
+ tmedia_session_mgr_ctor,
+ tmedia_session_mgr_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tmedia_session_mgr_def_t = &tmedia_session_mgr_def_s;
+
diff --git a/tinyMEDIA/src/tmedia_session_dummy.c b/tinyMEDIA/src/tmedia_session_dummy.c new file mode 100644 index 0000000..f77fccd --- /dev/null +++ b/tinyMEDIA/src/tmedia_session_dummy.c @@ -0,0 +1,472 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tmedia_session_dummy.c
+ * @brief Dummy sessions used for test only.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tinymedia/tmedia_session_dummy.h"
+
+#include "tsk_memory.h"
+#include "tsk_debug.h"
+
+/* ============ Audio Session ================= */
+
+int tmedia_session_daudio_set(tmedia_session_t* self, const tmedia_param_t* param)
+{
+ tmedia_session_daudio_t* daudio;
+
+ daudio = (tmedia_session_daudio_t*)self;
+
+ return 0;
+}
+
+int tmedia_session_daudio_prepare(tmedia_session_t* self)
+{
+ tmedia_session_daudio_t* daudio;
+
+ daudio = (tmedia_session_daudio_t*)self;
+
+ /* set local port */
+ daudio->local_port = rand() ^ rand();
+
+ return 0;
+}
+
+int tmedia_session_daudio_start(tmedia_session_t* self)
+{
+ return 0;
+}
+
+int tmedia_session_daudio_stop(tmedia_session_t* self)
+{
+ tmedia_session_daudio_t* daudio;
+
+ daudio = (tmedia_session_daudio_t*)self;
+
+ /* very important */
+ daudio->local_port = 0;
+
+ return 0;
+}
+
+int tmedia_session_daudio_send_dtmf(tmedia_session_t* self, uint8_t event)
+{
+ return 0;
+}
+
+int tmedia_session_daudio_pause(tmedia_session_t* self)
+{
+ return 0;
+}
+
+const tsdp_header_M_t* tmedia_session_daudio_get_lo(tmedia_session_t* self)
+{
+ tmedia_session_daudio_t* daudio;
+ tsk_bool_t changed = tsk_false;
+
+ if(!self || !self->plugin){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_null;
+ }
+
+ daudio = (tmedia_session_daudio_t*)self;
+
+ if(self->ro_changed && self->M.lo){
+ /* Codecs */
+ tsdp_header_A_removeAll_by_field(self->M.lo->Attributes, "fmtp");
+ tsdp_header_A_removeAll_by_field(self->M.lo->Attributes, "rtpmap");
+ tsk_list_clear_items(self->M.lo->FMTs);
+
+ /* QoS */
+ tsdp_header_A_removeAll_by_field(self->M.lo->Attributes, "curr");
+ tsdp_header_A_removeAll_by_field(self->M.lo->Attributes, "des");
+ tsdp_header_A_removeAll_by_field(self->M.lo->Attributes, "conf");
+ }
+
+ changed = (self->ro_changed || !self->M.lo);
+
+ if(!self->M.lo && !(self->M.lo = tsdp_header_M_create(self->plugin->media, daudio->local_port, "RTP/AVP"))){
+ TSK_DEBUG_ERROR("Failed to create lo");
+ return tsk_null;
+ }
+
+ if(changed){
+ /* from codecs to sdp */
+ tmedia_codec_to_sdp(self->neg_codecs ? self->neg_codecs : self->codecs, self->M.lo);
+ /* QoS */
+ if(self->qos){
+ tmedia_qos_tline_t* ro_tline;
+ if(self->M.ro && (ro_tline = tmedia_qos_tline_from_sdp(self->M.ro))){
+ tmedia_qos_tline_set_ro(self->qos, ro_tline);
+ TSK_OBJECT_SAFE_FREE(ro_tline);
+ }
+ tmedia_qos_tline_to_sdp(self->qos, self->M.lo);
+ }
+ }
+
+
+ return self->M.lo;
+}
+
+int tmedia_session_daudio_set_ro(tmedia_session_t* self, const tsdp_header_M_t* m)
+{
+ tmedia_codecs_L_t* neg_codecs;
+
+ if((neg_codecs = tmedia_session_match_codec(self, m))){
+ /* update negociated codecs */
+ TSK_OBJECT_SAFE_FREE(self->neg_codecs);
+ self->neg_codecs = neg_codecs;
+ /* update remote offer */
+ TSK_OBJECT_SAFE_FREE(self->M.ro);
+ self->M.ro = tsk_object_ref((void*)m);
+
+ return 0;
+ }
+ return -1;
+}
+
+/* ============ Video Session ================= */
+
+int tmedia_session_dvideo_set(tmedia_session_t* self, const tmedia_param_t* param)
+{
+ tmedia_session_dvideo_t* dvideo;
+
+ dvideo = (tmedia_session_dvideo_t*)self;
+
+ return 0;
+}
+
+int tmedia_session_dvideo_prepare(tmedia_session_t* self)
+{
+ tmedia_session_dvideo_t* dvideo;
+
+ dvideo = (tmedia_session_dvideo_t*)self;
+
+ /* set local port */
+ dvideo->local_port = rand() ^ rand();
+
+ return 0;
+}
+
+int tmedia_session_dvideo_start(tmedia_session_t* self)
+{
+ return -1;
+}
+
+int tmedia_session_dvideo_stop(tmedia_session_t* self)
+{
+ tmedia_session_dvideo_t* dvideo;
+
+ dvideo = (tmedia_session_dvideo_t*)self;
+
+ /* very important */
+ dvideo->local_port = 0;
+
+ return 0;
+}
+
+int tmedia_session_dvideo_pause(tmedia_session_t* self)
+{
+ return -1;
+}
+
+const tsdp_header_M_t* tmedia_session_dvideo_get_lo(tmedia_session_t* self)
+{
+ tmedia_session_dvideo_t* dvideo;
+ tsk_bool_t changed = tsk_false;
+
+ if(!self || !self->plugin){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_null;
+ }
+
+ dvideo = (tmedia_session_dvideo_t*)self;
+
+ if(self->ro_changed && self->M.lo){
+ /* Codecs */
+ tsdp_header_A_removeAll_by_field(self->M.lo->Attributes, "fmtp");
+ tsdp_header_A_removeAll_by_field(self->M.lo->Attributes, "rtpmap");
+ tsk_list_clear_items(self->M.lo->FMTs);
+
+ /* QoS */
+ tsdp_header_A_removeAll_by_field(self->M.lo->Attributes, "curr");
+ tsdp_header_A_removeAll_by_field(self->M.lo->Attributes, "des");
+ tsdp_header_A_removeAll_by_field(self->M.lo->Attributes, "conf");
+ }
+
+ changed = (self->ro_changed || !self->M.lo);
+
+ if(!self->M.lo && !(self->M.lo = tsdp_header_M_create(self->plugin->media, dvideo->local_port, "RTP/AVP"))){
+ TSK_DEBUG_ERROR("Failed to create lo");
+ return tsk_null;
+ }
+
+ if(changed){
+ /* from codecs to sdp */
+ tmedia_codec_to_sdp(self->neg_codecs ? self->neg_codecs : self->codecs, self->M.lo);
+ /* QoS */
+ if(self->qos){
+ tmedia_qos_tline_t* ro_tline;
+ if(self->M.ro && (ro_tline = tmedia_qos_tline_from_sdp(self->M.ro))){
+ tmedia_qos_tline_set_ro(self->qos, ro_tline);
+ TSK_OBJECT_SAFE_FREE(ro_tline);
+ }
+ tmedia_qos_tline_to_sdp(self->qos, self->M.lo);
+ }
+ }
+
+ return self->M.lo;
+}
+
+int tmedia_session_dvideo_set_ro(tmedia_session_t* self, const tsdp_header_M_t* m)
+{
+ tmedia_codecs_L_t* neg_codecs;
+
+ if((neg_codecs = tmedia_session_match_codec(self, m))){
+ /* update negociated codecs */
+ TSK_OBJECT_SAFE_FREE(self->neg_codecs);
+ self->neg_codecs = neg_codecs;
+ /* update remote offer */
+ TSK_OBJECT_SAFE_FREE(self->M.ro);
+ self->M.ro = tsk_object_ref((void*)m);
+
+ return 0;
+ }
+ return -1;
+}
+
+/* ============ Msrp Session ================= */
+
+int tmedia_session_dmsrp_set(tmedia_session_t* self, const tmedia_param_t* param)
+{
+ tmedia_session_dmsrp_t* dmsrp;
+
+ dmsrp = (tmedia_session_dmsrp_t*)self;
+
+ return 0;
+}
+
+int tmedia_session_dmsrp_prepare(tmedia_session_t* self)
+{
+ return 0;
+}
+
+int tmedia_session_dmsrp_start(tmedia_session_t* self)
+{
+ return 0;
+}
+
+int tmedia_session_dmsrp_stop(tmedia_session_t* self)
+{
+ return 0;
+}
+
+int tmedia_session_dmsrp_pause(tmedia_session_t* self)
+{
+ return 0;
+}
+
+const tsdp_header_M_t* tmedia_session_dmsrp_get_lo(tmedia_session_t* self)
+{
+ if(self->ro_changed){
+ TSK_OBJECT_SAFE_FREE(self->M.lo);
+ }
+
+ return tsk_null;
+}
+
+int tmedia_session_dmsrp_set_ro(tmedia_session_t* self, const tsdp_header_M_t* m)
+{
+ return -1;
+}
+
+//=================================================================================================
+// Dummy Audio session object definition
+//
+/* constructor */
+static tsk_object_t* tmedia_session_daudio_ctor(tsk_object_t * self, va_list * app)
+{
+ tmedia_session_daudio_t *session = self;
+ if(session){
+ /* init base: called by tmedia_session_create() */
+ /* init self */
+ }
+ return self;
+}
+/* destructor */
+static tsk_object_t* tmedia_session_daudio_dtor(tsk_object_t * self)
+{
+ tmedia_session_daudio_t *session = self;
+ if(session){
+ /* deinit base */
+ tmedia_session_deinit(self);
+ /* deinit self */
+ }
+
+ return self;
+}
+/* object definition */
+static const tsk_object_def_t tmedia_session_daudio_def_s =
+{
+ sizeof(tmedia_session_daudio_t),
+ tmedia_session_daudio_ctor,
+ tmedia_session_daudio_dtor,
+ tmedia_session_cmp,
+};
+/* plugin definition*/
+static const tmedia_session_plugin_def_t tmedia_session_daudio_plugin_def_s =
+{
+ &tmedia_session_daudio_def_s,
+
+ tmedia_audio,
+ "audio",
+
+ tmedia_session_daudio_set,
+ tmedia_session_daudio_prepare,
+ tmedia_session_daudio_start,
+ tmedia_session_daudio_pause,
+ tmedia_session_daudio_stop,
+
+ /* Audio part */
+ { tsk_null },
+
+ tmedia_session_daudio_get_lo,
+ tmedia_session_daudio_set_ro
+};
+const tmedia_session_plugin_def_t *tmedia_session_daudio_plugin_def_t = &tmedia_session_daudio_plugin_def_s;
+
+
+//=================================================================================================
+// Dummy Video session object definition
+//
+/* constructor */
+static tsk_object_t* tmedia_session_dvideo_ctor(tsk_object_t * self, va_list * app)
+{
+ tmedia_session_dvideo_t *session = self;
+ if(session){
+ /* init base: called by tmedia_session_create() */
+ /* init self */
+ }
+ return self;
+}
+/* destructor */
+static tsk_object_t* tmedia_session_dvideo_dtor(tsk_object_t * self)
+{
+ tmedia_session_dvideo_t *session = self;
+ if(session){
+ /* deinit base */
+ tmedia_session_deinit(self);
+ /* deinit self */
+ }
+
+ return self;
+}
+/* object definition */
+static const tsk_object_def_t tmedia_session_dvideo_def_s =
+{
+ sizeof(tmedia_session_dvideo_t),
+ tmedia_session_dvideo_ctor,
+ tmedia_session_dvideo_dtor,
+ tmedia_session_cmp,
+};
+/* plugin definition*/
+static const tmedia_session_plugin_def_t tmedia_session_dvideo_plugin_def_s =
+{
+ &tmedia_session_dvideo_def_s,
+
+ tmedia_video,
+ "video",
+
+ tmedia_session_dvideo_set,
+ tmedia_session_dvideo_prepare,
+ tmedia_session_dvideo_start,
+ tmedia_session_dvideo_pause,
+ tmedia_session_dvideo_stop,
+
+ /* Audio part */
+ { tsk_null },
+
+ tmedia_session_dvideo_get_lo,
+ tmedia_session_dvideo_set_ro
+};
+const tmedia_session_plugin_def_t *tmedia_session_dvideo_plugin_def_t = &tmedia_session_dvideo_plugin_def_s;
+
+
+//=================================================================================================
+// Dummy Msrp session object definition
+//
+/* constructor */
+static tsk_object_t* tmedia_session_dmsrp_ctor(tsk_object_t * self, va_list * app)
+{
+ tmedia_session_dmsrp_t *session = self;
+ if(session){
+ /* init base: called by tmedia_session_create() */
+ /* init self */
+ }
+ return self;
+}
+/* destructor */
+static tsk_object_t* tmedia_session_dmsrp_dtor(tsk_object_t * self)
+{
+ tmedia_session_dmsrp_t *session = self;
+ if(session){
+ /* deinit base */
+ tmedia_session_deinit(self);
+ /* deinit self */
+
+ }
+
+ return self;
+}
+/* object definition */
+static const tsk_object_def_t tmedia_session_dmsrp_def_s =
+{
+ sizeof(tmedia_session_dmsrp_t),
+ tmedia_session_dmsrp_ctor,
+ tmedia_session_dmsrp_dtor,
+ tmedia_session_cmp,
+};
+/* plugin definition*/
+static const tmedia_session_plugin_def_t tmedia_session_dmsrp_plugin_def_s =
+{
+ &tmedia_session_dmsrp_def_s,
+
+ tmedia_msrp,
+ "message",
+
+ tmedia_session_dmsrp_set,
+ tmedia_session_dmsrp_prepare,
+ tmedia_session_dmsrp_start,
+ tmedia_session_dmsrp_pause,
+ tmedia_session_dmsrp_stop,
+
+ /* Audio part */
+ { tsk_null },
+
+ tmedia_session_dmsrp_get_lo,
+ tmedia_session_dmsrp_set_ro
+};
+const tmedia_session_plugin_def_t *tmedia_session_dmsrp_plugin_def_t = &tmedia_session_dmsrp_plugin_def_s;
diff --git a/tinyMEDIA/src/tmedia_session_ghost.c b/tinyMEDIA/src/tmedia_session_ghost.c new file mode 100644 index 0000000..d69e307 --- /dev/null +++ b/tinyMEDIA/src/tmedia_session_ghost.c @@ -0,0 +1,141 @@ +/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tmedia_session_ghost.c
+ * @brief Ghost session.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tinymedia/tmedia_session_ghost.h"
+
+#include "tsk_memory.h"
+#include "tsk_debug.h"
+
+/* ============ Ghost Session ================= */
+
+int tmedia_session_ghost_prepare(tmedia_session_t* self)
+{
+ return 0;
+}
+
+int tmedia_session_ghost_start(tmedia_session_t* self)
+{
+ return 0;
+}
+
+int tmedia_session_ghost_stop(tmedia_session_t* self)
+{
+ TSK_DEBUG_INFO("tmedia_session_ghost_stop");
+ return 0;
+}
+
+int tmedia_session_ghost_pause(tmedia_session_t* self)
+{
+ return 0;
+}
+
+const tsdp_header_M_t* tmedia_session_ghost_get_lo(tmedia_session_t* self)
+{
+ tmedia_session_ghost_t* ghost;
+
+ ghost = (tmedia_session_ghost_t*)self;
+
+ if(self->M.lo){
+ return self->M.lo;
+ }
+ else if(!(self->M.lo = tsdp_header_M_create(ghost->media, 0, "RTP/AVP"))){
+ TSK_DEBUG_ERROR("Failed to create lo");
+ return tsk_null;
+ }
+
+ return self->M.lo;
+}
+
+int tmedia_session_ghost_set_ro(tmedia_session_t* self, const tsdp_header_M_t* m)
+{
+ return 0;
+}
+
+
+
+
+
+
+
+//=================================================================================================
+// Ghost session object definition
+//
+/* constructor */
+static tsk_object_t* tmedia_session_ghost_ctor(tsk_object_t * self, va_list * app)
+{
+ tmedia_session_ghost_t *session = self;
+ if(session){
+ /* init base */
+ tmedia_session_init(TMEDIA_SESSION(session), tmedia_none);
+ /* init self */
+ }
+ return self;
+}
+/* destructor */
+static tsk_object_t* tmedia_session_ghost_dtor(tsk_object_t * self)
+{
+ tmedia_session_ghost_t *session = self;
+ if(session){
+ /* deinit base */
+ tmedia_session_deinit(TMEDIA_SESSION(session));
+ /* deinit self */
+ TSK_FREE(session->media);
+ }
+
+ return self;
+}
+/* object definition */
+static const tsk_object_def_t tmedia_session_ghost_def_s =
+{
+ sizeof(tmedia_session_ghost_t),
+ tmedia_session_ghost_ctor,
+ tmedia_session_ghost_dtor,
+ tmedia_codec_cmp,
+};
+/* plugin definition*/
+static const tmedia_session_plugin_def_t tmedia_session_ghost_plugin_def_s =
+{
+ &tmedia_session_ghost_def_s,
+
+ tmedia_ghost,
+ "ghost",
+
+ tsk_null,
+ tmedia_session_ghost_prepare,
+ tmedia_session_ghost_start,
+ tmedia_session_ghost_stop,
+ tmedia_session_ghost_pause,
+
+ /* Audio part */
+ { tsk_null },
+
+ tmedia_session_ghost_get_lo,
+ tmedia_session_ghost_set_ro
+};
+const tmedia_session_plugin_def_t *tmedia_session_ghost_plugin_def_t = &tmedia_session_ghost_plugin_def_s;
diff --git a/tinyMEDIA/src/tmedia_vad.c b/tinyMEDIA/src/tmedia_vad.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tinyMEDIA/src/tmedia_vad.c diff --git a/tinyMEDIA/test/droid-makefile b/tinyMEDIA/test/droid-makefile new file mode 100644 index 0000000..192affd --- /dev/null +++ b/tinyMEDIA/test/droid-makefile @@ -0,0 +1,29 @@ +APP := test
+
+CFLAGS := $(CFLAGS_COMMON) -I../include -I../../tinySAK/src -I../../tinyNET/src -I../../tinySDP/include
+LDFLAGS := $(LDFLAGS_COMMON) -Wl,-Bsymbolic,--whole-archive -l$(PROJECT) -ltinySAK -ltinyNET -ltinySDP -Wl,--entry=main
+
+all: $(APP)
+
+OBJS += $(APP).o \
+ dummy.o
+
+$(APP): $(OBJS)
+ $(CC) $(LDFLAGS) -o $@ $^
+
+%.o: %.c
+ $(CC) -c $(INCLUDE) $(CFLAGS) $< -o $@
+
+install: $(APP)
+ $(ANDROID_SDK_ROOT)/tools/adb push $(APP) $(EXEC_DIR)/$(APP)
+ $(ANDROID_SDK_ROOT)/tools/adb shell chmod 777 $(EXEC_DIR)/$(APP)
+
+run:
+ $(ANDROID_SDK_ROOT)/tools/adb shell $(EXEC_DIR)/$(APP)
+
+#dbg:
+# $(MAKE) $(MAKEFILE) DEBUG="-g -DDEBUG"
+# $(MAKE) $(MAKEFILE) install
+
+clean:
+ @rm -f $(OBJS) $(APP)
\ No newline at end of file diff --git a/tinyMEDIA/test/dummy.c b/tinyMEDIA/test/dummy.c new file mode 100644 index 0000000..18799aa --- /dev/null +++ b/tinyMEDIA/test/dummy.c @@ -0,0 +1,173 @@ +/*
+* Copyright (C) 2009 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)yahoo.fr>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#include "dummy.h"
+
+#include "tsk_string.h"
+#include "tsk_memory.h"
+#include "tsk_debug.h" + +int dummy_start(tmedia_t* self) +{ + dummy_t *dummy = DUMMY(self); + TSK_DEBUG_INFO("dummy_start"); + + return 0; +} + +int dummy_pause(tmedia_t* self) +{ + dummy_t *dummy = DUMMY(self); + TSK_DEBUG_INFO("dummy_pause"); + + return 0; +} + +int dummy_stop(tmedia_t* self) +{ + dummy_t *dummy = DUMMY(self); + TSK_DEBUG_INFO("dummy_stop"); + + return 0; +} + +const tsdp_header_M_t* dummy_get_local_offer(tmedia_t* self, va_list *app) +{ + dummy_t *dummy = DUMMY(self); + const tsk_object_def_t* objdef; + tsdp_header_t* header; + + TSK_DEBUG_INFO("dummy_get_local_offer"); + while((objdef = va_arg(*app, const tsk_object_def_t*))){ + header = tsk_object_new_2(objdef, app); + + TSK_OBJECT_SAFE_FREE(header); + } + + return tsk_null; +} + +const tsdp_header_M_t* dummy_get_negotiated_offer(tmedia_t* self) +{ + dummy_t *dummy = DUMMY(self); + TSK_DEBUG_INFO("dummy_get_negotiated_offer"); + + return tsk_null; +} + +int dummy_set_remote_offer(tmedia_t* self, const tsdp_message_t* offer)
+{
+ dummy_t *dummy = DUMMY(self);
+ TSK_DEBUG_INFO("dummy_set_remote_offer");
+
+ return 0;
+}
+
+int dummy_perform(tmedia_t* self, tmedia_action_t action, const tsk_params_L_t* params) +{ + dummy_t *dummy = DUMMY(self); + + switch(action){ + case tma_dummy_say_hello: + { + TSK_DEBUG_INFO("dummy_perform (hello to \"%s\")", tsk_params_get_param_value(params, "to")); + break; + } + } + + return 0; +}
+
+
+//========================================================
+// Dummy media object definition
+//
+static void* dummy_create(tsk_object_t *self, va_list * app)
+{
+ dummy_t *dummy = self;
+ if(dummy)
+ {
+ // Parameters MUST appear in this order
+ const char* name = va_arg(*app, const char*);
+ const char* host = va_arg(*app, const char*);
+ tnet_socket_type_t socket_type = va_arg(*app, tnet_socket_type_t);
+
+ tmedia_init(TMEDIA(dummy), name);
+
+ TMEDIA(dummy)->protocol = tsk_strdup("TCP/DUMMY");
+ }
+ else{
+ TSK_DEBUG_ERROR("Failed to create new dummy media.");
+ }
+ return self;
+}
+
+static void* dummy_destroy(tsk_object_t *self)
+{
+ dummy_t *dummy = self;
+ if(dummy){
+ tmedia_deinit(TMEDIA(dummy));
+ TSK_FREE(dummy->local_sdp);
+ TSK_FREE(dummy->remote_sdp);
+ TSK_FREE(dummy->negotiated_sdp);
+ }
+ else{
+ TSK_DEBUG_ERROR("Null dummy media.");
+ }
+
+ return self;
+}
+static int dummy_cmp(const tsk_object_t *obj1, const tsk_object_t *obj2)
+{
+ return -1;
+}
+
+static const tsk_object_def_t dummy_def_s =
+{
+ sizeof(dummy_t),
+ dummy_create,
+ dummy_destroy,
+ dummy_cmp
+};
+
+const tsk_object_def_t *dummy_def_t = &dummy_def_s;
+
+//========================================================
+// Dummy media plugin definition
+//
+static const tmedia_plugin_def_t dummy_plugin_def_s =
+{
+ &dummy_def_s,
+ "dummy plugin",
+ "audio",
+
+ dummy_start,
+ dummy_pause,
+ dummy_stop,
+
+ dummy_get_local_offer,
+ dummy_get_negotiated_offer,
+ dummy_set_remote_offer,
+
+ dummy_perform
+};
+const tmedia_plugin_def_t *dummy_plugin_def_t = &dummy_plugin_def_s;
+
diff --git a/tinyMEDIA/test/dummy.h b/tinyMEDIA/test/dummy.h new file mode 100644 index 0000000..a0319e3 --- /dev/null +++ b/tinyMEDIA/test/dummy.h @@ -0,0 +1,43 @@ +/*
+* Copyright (C) 2009 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)yahoo.fr>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#ifndef TEST_MEDIA_DUMMY_H
+#define TEST_MEDIA_DUMMY_H
+
+#include "tinymedia/tmedia.h"
+
+#define DUMMY(self) ((dummy_t*)(self))
+
+typedef struct dummy_s
+{
+ TMED_DECLARE_MEDIA;
+
+ char* local_sdp;
+ char* remote_sdp;
+ char* negotiated_sdp;
+}
+dummy_t;
+
+const tsk_object_def_t *dummy_def_t;
+const tmedia_plugin_def_t *dummy_plugin_def_t;
+
+
+#endif /* TEST_MEDIA_DUMMY_H */
diff --git a/tinyMEDIA/test/test.c b/tinyMEDIA/test/test.c new file mode 100644 index 0000000..8235bd2 --- /dev/null +++ b/tinyMEDIA/test/test.c @@ -0,0 +1,162 @@ +/*
+* Copyright (C) 2009 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)yahoo.fr>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#include "tinymedia/tmedia.h"
+//#include "dummy.h"
+
+#include "tinymedia.h"
+
+#include "test_codecs.h"
+#include "test_sessions.h"
+#include "test_qos.h"
+#include "test_contents.h"
+
+#define RUN_TEST_LOOP 1
+
+#define RUN_TEST_ALL 0
+#define RUN_TEST_CODECS 0
+#define RUN_TEST_SESSIONS 0
+#define RUN_TEST_QOS 0
+#define RUN_TEST_CONTENTS 1
+
+static void test_register_dummy_plugins();
+static void test_register_contents_plugins();
+
+#ifdef _WIN32_WCE
+int _tmain(int argc, _TCHAR* argv[])
+#else
+int main()
+#endif
+{
+ /* Register dummy plugins */
+ test_register_dummy_plugins();
+ /* Register content plugins */
+ test_register_contents_plugins();
+
+ do {
+
+#if RUN_TEST_ALL || RUN_TEST_CODECS
+ test_codecs();
+#endif
+
+#if RUN_TEST_ALL || RUN_TEST_SESSIONS
+ test_sessions();
+#endif
+
+#if RUN_TEST_ALL || RUN_TEST_QOS
+ test_qos();
+#endif
+
+#if RUN_TEST_ALL || RUN_TEST_CONTENTS
+ test_contents();
+#endif
+
+ }
+ while(RUN_TEST_LOOP);
+
+ return 0;
+}
+
+
+void test_register_contents_plugins()
+{
+ tmedia_content_plugin_register("text/html", tmedia_content_dummy_plugin_def_t);
+ tmedia_content_plugin_register("text/plain", tmedia_content_dummy_plugin_def_t);
+ tmedia_content_plugin_register("message/CPIM", tmedia_content_cpim_plugin_def_t);
+}
+
+void test_register_dummy_plugins()
+{
+ int ret;
+
+ /* === Sessions === */
+ if((ret = tmedia_session_plugin_register(tmedia_session_daudio_plugin_def_t))){
+ TSK_DEBUG_ERROR("Failed to register audio plugin");
+ }
+ if((ret = tmedia_session_plugin_register(tmedia_session_dvideo_plugin_def_t))){
+ TSK_DEBUG_ERROR("Failed to register video plugin");
+ }
+ if((ret = tmedia_session_plugin_register(tmedia_session_dmsrp_plugin_def_t))){
+ TSK_DEBUG_ERROR("Failed to register msrp plugin");
+ }
+ if((ret = tmedia_session_plugin_register(tmedia_session_ghost_plugin_def_t))){
+ TSK_DEBUG_ERROR("Failed to register ghost plugin");
+ }
+
+ /* === Codecs === */
+ if((ret = tmedia_codec_plugin_register(tmedia_codec_dpcma_plugin_def_t))){
+ TSK_DEBUG_ERROR("Failed to register G.711a plugin");
+ }
+ if((ret = tmedia_codec_plugin_register(tmedia_codec_dpcmu_plugin_def_t))){
+ TSK_DEBUG_ERROR("Failed to register G.711u plugin");
+ }
+ if((ret = tmedia_codec_plugin_register(tmedia_codec_dh263_plugin_def_t))){
+ TSK_DEBUG_ERROR("Failed to register H.263-1996 plugin");
+ }
+ if((ret = tmedia_codec_plugin_register(tmedia_codec_dh264_plugin_def_t))){
+ TSK_DEBUG_ERROR("Failed to register H.264 (Base profile 10) plugin");
+ }
+}
+
+//#ifdef _WIN32_WCE
+//int _tmain(int argc, _TCHAR* argv[])
+//#else
+//int main()
+//#endif
+//{
+// while(1)
+// {
+// tmedia_t* dummy = tsk_null;
+//
+// // Register dummy media
+// tmedia_plugin_register(dummy_plugin_def_t);
+// // ...if you have another one to register
+// // ...and another
+// // ...again and again
+//
+// // Create dummy media
+// if((dummy = tmedia_factory_create("dummy plugin", "127.0.0.1", tnet_socket_type_udp_ipv4))){
+//
+// tmedia_get_local_offer(dummy,
+// TSDP_HEADER_A_VA_ARGS("file-disposition", "attachment"),
+//
+// tsk_null
+// );
+// tmedia_get_negotiated_offer(dummy);
+// tmedia_set_remote_offer(dummy, tsk_null);
+//
+// tmedia_start(dummy);
+// tmedia_pause(dummy);
+//
+// tmedia_perform(dummy, tma_dummy_say_hello,
+// TSK_PARAM_VA_ARGS("to", "doubango"),
+//
+// tsk_null);
+//
+// tmedia_stop(dummy);
+//
+// TSK_OBJECT_SAFE_FREE(dummy);
+// }
+// }
+//
+// return 0;
+//}
+
diff --git a/tinyMEDIA/test/test.vcproj b/tinyMEDIA/test/test.vcproj new file mode 100644 index 0000000..94a7851 --- /dev/null +++ b/tinyMEDIA/test/test.vcproj @@ -0,0 +1,213 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="test"
+ ProjectGUID="{6ED4F246-C3B7-4DD5-9434-3A3F69CC0AD6}"
+ RootNamespace="test"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""$(DOUBANGO_HOME)\thirdparties\win32\include";"$(SolutionDir)\include";"$(DOUBANGO_HOME)\tinyNET\src";"$(DOUBANGO_HOME)\tinySAK\src";"$(DOUBANGO_HOME)\tinySDP\include""
+ PreprocessorDefinitions="DEBUG_LEVEL=DEBUG_LEVEL_INFO;WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ WarnAsError="true"
+ DebugInformationFormat="4"
+ CompileAs="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="$(OutDir)\tinySAK.lib $(OutDir)\tinyMEDIA.lib $(OutDir)\tinySDP.lib"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ WarnAsError="true"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="source"
+ >
+ <File
+ RelativePath=".\test.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="include"
+ >
+ <File
+ RelativePath=".\dummy.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="tests"
+ >
+ <File
+ RelativePath=".\test_codecs.h"
+ >
+ </File>
+ <File
+ RelativePath=".\test_contents.h"
+ >
+ </File>
+ <File
+ RelativePath=".\test_qos.h"
+ >
+ </File>
+ <File
+ RelativePath=".\test_sessions.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/tinyMEDIA/test/test_codecs.h b/tinyMEDIA/test/test_codecs.h new file mode 100644 index 0000000..2be6c46 --- /dev/null +++ b/tinyMEDIA/test/test_codecs.h @@ -0,0 +1,37 @@ +/*
+* Copyright (C) 2009 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)yahoo.fr>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#ifndef _TEST_CODECS_H_
+#define _TEST_CODECS_H_
+
+void test_codecs()
+{
+ tmedia_codec_t* pcmu, *pcma;
+
+ /* creates codecs */
+ pcmu = tmedia_codec_create(TMEDIA_CODEC_FORMAT_G711u);
+ pcma = tmedia_codec_create(TMEDIA_CODEC_FORMAT_G711a);
+
+ TSK_OBJECT_SAFE_FREE(pcmu);
+ TSK_OBJECT_SAFE_FREE(pcma);
+}
+
+#endif /* _TEST_CODECS_H_ */
diff --git a/tinyMEDIA/test/test_contents.h b/tinyMEDIA/test/test_contents.h new file mode 100644 index 0000000..096d7cf --- /dev/null +++ b/tinyMEDIA/test/test_contents.h @@ -0,0 +1,89 @@ +/*
+* Copyright (C) 2009 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)yahoo.fr>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#ifndef _TEST_CONTENTS_H_
+#define _TEST_CONTENTS_H_
+
+static void test_content_dummy();
+static void test_content_text_plain();
+static void test_content_cpim();
+
+static void test_contents()
+{
+ test_content_dummy();
+ test_content_text_plain();
+ test_content_cpim();
+}
+
+
+static void test_content_dummy()
+{
+#define CONTENT_DUMMY_DATA "salut"
+#define CONTENT_DUMMY_TYPE "cool/ok"
+ tmedia_content_t* content = tmedia_content_parse(CONTENT_DUMMY_DATA, tsk_strlen(CONTENT_DUMMY_DATA), CONTENT_DUMMY_TYPE);
+ if(content){
+ tsk_buffer_t* data = tmedia_content_get_data(content);
+ TSK_DEBUG_INFO("content-type=%s\n\ncontent=%s", TMEDIA_CONTENT(content)->type, TSK_BUFFER_DATA(data));
+ tsk_object_unref(data);
+ }
+
+ TSK_OBJECT_SAFE_FREE(content);
+}
+
+static void test_content_text_plain()
+{
+#define CONTENT_TEXT_PLAIN_DATA "salut comment tu vas?"
+#define CONTENT_TEXT_PLAIN_TYPE "text/plain"
+ tmedia_content_t* content = tmedia_content_parse(CONTENT_TEXT_PLAIN_DATA, tsk_strlen(CONTENT_TEXT_PLAIN_DATA), CONTENT_TEXT_PLAIN_TYPE);
+ if(content){
+ tsk_buffer_t* data = tmedia_content_get_data(content);
+ TSK_DEBUG_INFO("content-type=%s\n\ncontent=%s", TMEDIA_CONTENT(content)->type, TSK_BUFFER_DATA(data));
+ tsk_object_unref(data);
+ }
+
+ TSK_OBJECT_SAFE_FREE(content);
+}
+
+static void test_content_cpim()
+{
+#define CONTENT_CPIM_DATA "To: <sip:test@doubango.org>\r\n" \
+"From: <sip:test@doubango.org>\r\n" \
+"DateTime: 2010-12-17T09:57:32.562Z\r\n" \
+"Content-Disposition: attachment; filename=\"history.xml\"; creation-date=\"2010-12-17T09:19:56.978Z\"; size=3714\r\n" \
+"\r\n" \
+"Content-Type: application/octet-stream\r\n" \
+"Content-ID: <1234567890@doubango.org>\r\n" \
+"\r\n" \
+"salut comment tu vas?\r\n"
+
+#define CONTENT_CPIM_TYPE "message/CPIM"
+ tmedia_content_t* content = tmedia_content_parse(CONTENT_CPIM_DATA, tsk_strlen(CONTENT_CPIM_DATA), CONTENT_CPIM_TYPE);
+ if(content){
+ tsk_buffer_t* data = tmedia_content_get_data(content);
+ TSK_DEBUG_INFO("content-type=%s\n\ncontent=%s", TMEDIA_CONTENT(content)->type, TSK_BUFFER_DATA(data));
+ tsk_object_unref(data);
+ }
+
+ TSK_OBJECT_SAFE_FREE(content);
+}
+
+#endif /* _TEST_CONTENTS_H_ */
+
diff --git a/tinyMEDIA/test/test_qos.h b/tinyMEDIA/test/test_qos.h new file mode 100644 index 0000000..c91b294 --- /dev/null +++ b/tinyMEDIA/test/test_qos.h @@ -0,0 +1,267 @@ +/*
+* Copyright (C) 2009 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)yahoo.fr>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#ifndef _TEST_QOS_H_
+#define _TEST_QOS_H_
+
+char* test_qos_tostring(const tmedia_qos_tline_t* tline)
+{
+ char* ret = tsk_null;
+ tsdp_header_M_t* M;
+
+ if(!tline){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_null;
+ }
+
+ M = tsdp_header_M_create("audio", 20000, "RTP/AVP");
+ tmedia_qos_tline_to_sdp(tline, M);
+
+ ret = tsdp_header_tostring(TSDP_HEADER(M));
+ TSK_OBJECT_SAFE_FREE(M);
+
+ return ret;
+}
+
+void test_qos_parser()
+{
+ tsdp_header_M_t* M;
+ tmedia_qos_tline_e2e_t* e2e;
+ tmedia_qos_tline_segmented_t* segmented;
+ char* temp = tsk_null;
+ tmedia_qos_stype_t type;
+ tsk_bool_t canresume;
+
+ /* test E2E */
+ M = tsdp_header_M_create("audio", 20000, "RTP/AVP");
+ e2e = tmedia_qos_tline_e2e_create(tmedia_qos_strength_mandatory);
+ // to_sdp
+ tmedia_qos_tline_e2e_to_sdp(e2e, M);
+ if((type = tmedia_qos_get_type(M)) != tmedia_qos_stype_e2e){
+ TSK_DEBUG_ERROR("Invalid type");
+ }
+ if((temp = tsdp_header_tostring(TSDP_HEADER(M)))){
+ TSK_DEBUG_INFO("E2E to_sdp: %s", temp);
+ TSK_FREE(temp);
+ }
+ // from_sdp
+ TSK_OBJECT_SAFE_FREE(e2e);
+ e2e = tmedia_qos_tline_e2e_from_sdp(M);
+ canresume = tmedia_qos_tline_e2e_canresume(e2e);
+ tmedia_qos_tline_e2e_to_sdp(e2e, M);
+ if((temp = tsdp_header_tostring(TSDP_HEADER(M)))){
+ TSK_DEBUG_INFO("e2e from_sdp: %s", temp);
+ TSK_FREE(temp);
+ }
+
+
+ TSK_OBJECT_SAFE_FREE(e2e);
+ TSK_OBJECT_SAFE_FREE(M);
+
+ /* test Segmented */
+ M = tsdp_header_M_create("video", 20002, "RTP/AVP");
+ segmented = tmedia_qos_tline_segmented_create(tmedia_qos_strength_none);
+ segmented->remote_send.strength = tmedia_qos_strength_optional;
+ // to_sdp
+ tmedia_qos_tline_segmented_to_sdp(segmented, M);
+ if((type = tmedia_qos_get_type(M)) != tmedia_qos_stype_segmented){
+ TSK_DEBUG_ERROR("Invalid type");
+ }
+ if((temp = tsdp_header_tostring(TSDP_HEADER(M)))){
+ TSK_DEBUG_INFO("Segmented to_sdp: %s", temp);
+ TSK_FREE(temp);
+ }
+ // from_sdp
+ TSK_OBJECT_SAFE_FREE(segmented);
+ segmented = tmedia_qos_tline_segmented_from_sdp(M);
+ canresume = tmedia_qos_tline_segmented_canresume(segmented);
+ tmedia_qos_tline_segmented_to_sdp(segmented, M);
+ if((temp = tsdp_header_tostring(TSDP_HEADER(M)))){
+ TSK_DEBUG_INFO("Segmented from_sdp: %s", temp);
+ TSK_FREE(temp);
+ }
+
+
+
+ TSK_OBJECT_SAFE_FREE(segmented);
+ TSK_OBJECT_SAFE_FREE(M);
+}
+
+
+void test_qos_e2e_neg()
+{
+ tmedia_qos_tline_e2e_t *e2eA = tsk_null, *e2eB = tsk_null;
+ char* temp = tsk_null;
+
+ /* SDP1: A includes end-to-end quality of service preconditions in the
+ initial offer.
+
+ m=audio 20000 RTP/AVP 0
+ c=IN IP4 192.0.2.1
+ a=curr:qos e2e none
+ a=des:qos mandatory e2e sendrecv
+ */
+ e2eA = tmedia_qos_tline_e2e_create(tmedia_qos_strength_mandatory);
+ if((temp = test_qos_tostring((const tmedia_qos_tline_t*)e2eA))){
+ TSK_DEBUG_INFO("SDP1=\n%s", temp);
+ TSK_FREE(temp);
+ }
+
+ /* SDP2: Since B uses RSVP, it can know when resources in its "send"
+ direction are available, because it will receive RESV messages from
+ the network. However, it does not know the status of the
+ reservations in the other direction. B requests confirmation for
+ resource reservations in its "recv" direction to the peer user agent
+ A in its answer.
+
+ m=audio 30000 RTP/AVP 0
+ c=IN IP4 192.0.2.4
+ a=curr:qos e2e none
+ a=des:qos mandatory e2e sendrecv
+ a=conf:qos e2e recv
+ */
+ e2eB = tmedia_qos_tline_e2e_create(tmedia_qos_strength_mandatory);
+ tmedia_qos_tline_e2e_set_ro(e2eB, e2eA);
+ if((temp = test_qos_tostring((const tmedia_qos_tline_t*)e2eB))){
+ TSK_DEBUG_INFO("SDP2=\n%s", temp);
+ TSK_FREE(temp);
+ }
+
+ /* SDP3: When A receives RESV messages, it sends an updated offer (5) to B:
+
+ m=audio 20000 RTP/AVP 0
+ c=IN IP4 192.0.2.1
+ a=curr:qos e2e send
+ a=des:qos mandatory e2e sendrecv
+ */
+ tmedia_qos_tline_e2e_set_ro(e2eA, e2eB);
+ if((temp = test_qos_tostring((const tmedia_qos_tline_t*)e2eA))){
+ TSK_DEBUG_INFO("SDP3=\n%s", temp);
+ TSK_FREE(temp);
+ }
+
+ /* SDP4: B responds with an answer (6) which contains the current status
+ of the resource reservation (i.e., sendrecv):
+
+ m=audio 30000 RTP/AVP 0
+ c=IN IP4 192.0.2.4
+ a=curr:qos e2e sendrecv
+ a=des:qos mandatory e2e sendrecv
+ */
+ tmedia_qos_tline_e2e_set_ro(e2eB, e2eA);
+ if((temp = test_qos_tostring((const tmedia_qos_tline_t*)e2eB))){
+ TSK_DEBUG_INFO("SDP4=\n%s", temp);
+ TSK_FREE(temp);
+ }
+
+ /* A receive B's response */
+ tmedia_qos_tline_e2e_set_ro(e2eA, e2eB);
+ if((temp = test_qos_tostring((const tmedia_qos_tline_t*)e2eA))){
+ TSK_DEBUG_INFO("SDP5=\n%s", temp);
+ TSK_FREE(temp);
+ }
+
+ if(tmedia_qos_tline_e2e_canresume(e2eA)){
+ TSK_DEBUG_INFO("A can resume");
+ }
+ else{
+ TSK_DEBUG_ERROR("A can't resume");
+ }
+
+ if(tmedia_qos_tline_e2e_canresume(e2eB)){
+ TSK_DEBUG_INFO("B can resume");
+ }
+ else{
+ TSK_DEBUG_ERROR("B can't resume");
+ }
+
+ TSK_OBJECT_SAFE_FREE(e2eB);
+ TSK_OBJECT_SAFE_FREE(e2eA);
+}
+
+
+void test_qos_segmented_neg()
+{
+ tmedia_qos_tline_segmented_t *segA = tsk_null, *segB = tsk_null;
+ char* temp = tsk_null;
+
+ /* INVITE
+ a=curr:qos local none
+ a=curr:qos remote none
+ a=des:qos mandatory local sendrecv
+ a=des:qos mandatory remote sendrecv
+ */
+ segA = tmedia_qos_tline_segmented_create(tmedia_qos_strength_mandatory);
+ if((temp = test_qos_tostring((const tmedia_qos_tline_t*)segA))){
+ TSK_DEBUG_INFO("INVITE=\n%s", temp);
+ TSK_FREE(temp);
+ }
+
+ /* 183 Sesson progress
+ a=curr:qos local none
+ a=curr:qos remote none
+ a=des:qos mandatory local sendrecv
+ a=des:qos mandatory remote sendrecv
+ a=conf:qos remote sendrecv
+ */
+ segB = tmedia_qos_tline_segmented_create(tmedia_qos_strength_mandatory);
+ tmedia_qos_tline_segmented_set_ro(segB, segA);
+ if((temp = test_qos_tostring((const tmedia_qos_tline_t*)segB))){
+ TSK_DEBUG_INFO("183=\n%s", temp);
+ TSK_FREE(temp);
+ }
+
+ /* UPDATE
+ a=curr:qos local sendrecv
+ a=curr:qos remote none
+ a=des:qos mandatory local sendrecv
+ a=des:qos mandatory remote sendrecv
+ */
+ tmedia_qos_tline_segmented_set_ro(segA, segB);
+ if((temp = test_qos_tostring((const tmedia_qos_tline_t*)segA))){
+ TSK_DEBUG_INFO("UPDATE=\n%s", temp);
+ TSK_FREE(temp);
+ }
+
+ /* 200 OK
+ a=curr:qos local sendrecv
+ a=curr:qos remote sendrecv
+ a=des:qos mandatory local sendrecv
+ a=des:qos mandatory remote sendrecv
+ */
+ tmedia_qos_tline_segmented_set_ro(segB, segA);
+ if((temp = test_qos_tostring((const tmedia_qos_tline_t*)segB))){
+ TSK_DEBUG_INFO("200OK=\n%s", temp);
+ TSK_FREE(temp);
+ }
+
+ TSK_OBJECT_SAFE_FREE(segA);
+ TSK_OBJECT_SAFE_FREE(segB);
+}
+
+void test_qos()
+{
+ //test_qos_parser();
+ //test_qos_e2e_neg();
+ test_qos_segmented_neg();
+}
+
+#endif /* _TEST_QOS_H_ */
diff --git a/tinyMEDIA/test/test_sessions.h b/tinyMEDIA/test/test_sessions.h new file mode 100644 index 0000000..0807511 --- /dev/null +++ b/tinyMEDIA/test/test_sessions.h @@ -0,0 +1,244 @@ +/*
+* Copyright (C) 2009 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)yahoo.fr>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#ifndef _TEST_SESSIONS_H_
+#define _TEST_SESSIONS_H_
+
+#define SDP_RO \
+ "v=0\r\n" \
+ "o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com\r\n" \
+ "s=\r\n" \
+ "i=A Seminar on the session description protocol\r\n" \
+ "u=http://www.example.com/seminars/sdp.pdf\r\n" \
+ "e=j.doe@example.com (Jane Doe)\r\n" \
+ "p=+1 617 555-6011\r\n" \
+ "c=IN IP4 host.atlanta.example.com\r\n" \
+ "b=X-YZ:128\r\n" \
+ "z=2882844526 -1h 2898848070 0\r\n" \
+ "k=base64:ZWFzdXJlLg==\r\n" \
+ "t=3034423619 3042462419\r\n" \
+ "r=7d 1h 0 25h\r\n" \
+ "r=604800 3600 0 90000\r\n" \
+ "w=my dummy header\r\n" \
+ "m=audio 49170 RTP/AVP 8 0 97 98\r\n" \
+ "i=Audio line\r\n" \
+ "c=IN IP4 otherhost.biloxi.example.com\r\n" \
+ "k=base64:ZWFzdXJlLgdddddddddddddddddddddd==\r\n" \
+ "a=rtpmap:8 PCMA/8000\r\n" \
+ "a=rtpmap:0 PCMU/8000\r\n" \
+ "a=rtpmap:97 iLBC/8000\r\n" \
+ "a=rtpmap:98 AMR-WB/16000\r\n" \
+ "a=curr:qos local none\r\n" \
+ "a=curr:qos remote none\r\n" \
+ "a=des:qos mandatory local sendrecv\r\n" \
+ "a=des:qos mandatory remote sendrecv\r\n" \
+ "a=conf:qos remote sendrecv\r\n" \
+ "a=fmtp:98 octet-align=1\r\n" \
+ "m=video 51372 RTP/AVP 31 32 98\r\n" \
+ "i=Video line\r\n" \
+ "b=A-YZ:92\r\n" \
+ "b=B-YZ:256\r\n" \
+ "a=rtpmap:31 H261/90000\r\n" \
+ "a=rtpmap:32 MPV/90000\r\n" \
+ "a=rtpmap:98 H264/90000\r\n" \
+ "a=fmtp:98 profile-level-id=42A01E\r\n" \
+ "a=recvonly\r\n" \
+ "m=toto 51372 RTP/AVP 31 32\r\n" \
+ "i=Video line\r\n" \
+ "b=A-YZ:92\r\n" \
+ "b=B-YZ:256\r\n" \
+ "a=rtpmap:31 H261/90000\r\n" \
+ "a=rtpmap:32 MPV/90000\r\n" \
+ "a=recvonly\r\n"
+
+void test_sessions_client()
+{
+ tmedia_session_mgr_t* mgr;
+ const tsdp_message_t* sdp_lo;
+ tsdp_message_t* sdp_ro;
+ char* temp;
+ tsk_bool_t canresume;
+ tmedia_type_t media_type = (tmedia_audio | tmedia_video | tmedia_msrp | tmedia_t38);
+
+ int32_t width = 176;
+ int64_t height = 144LL;
+
+
+ /* create manager */
+ mgr = tmedia_session_mgr_create((tmedia_audio | tmedia_video | tmedia_msrp | tmedia_t38),
+ "0.0.0.0", tsk_false, tsk_true);
+ tmedia_session_mgr_set_qos(mgr, tmedia_qos_stype_segmented, tmedia_qos_strength_mandatory);
+
+ tmedia_session_mgr_set(mgr,
+ TMEDIA_SESSION_VIDEO_SET_INT32("width", width),
+ TMEDIA_SESSION_VIDEO_SET_INT64("height", height),
+ TMEDIA_SESSION_VIDEO_SET_STR("description", "This is my session"),
+ TMEDIA_SESSION_AUDIO_SET_INT32("rate", "8000"),
+ TMEDIA_SESSION_SET_STR(tmedia_audio | tmedia_video, "hello", "world"),
+ TMEDIA_SESSION_SET_NULL());
+
+ /* get lo */
+ sdp_lo = tmedia_session_mgr_get_lo(mgr);
+ if((temp = tsdp_message_tostring(sdp_lo))){
+ TSK_DEBUG_INFO("sdp_lo=%s", temp);
+ TSK_FREE(temp);
+ }
+
+ /* set ro */
+ if((sdp_ro = tsdp_message_parse(SDP_RO, tsk_strlen(SDP_RO)))){
+ tmedia_session_mgr_set_ro(mgr, sdp_ro);
+ TSK_OBJECT_SAFE_FREE(sdp_ro);
+ }
+
+ /* get lo */
+ sdp_lo = tmedia_session_mgr_get_lo(mgr);
+ if((temp = tsdp_message_tostring(sdp_lo))){
+ TSK_DEBUG_INFO("sdp_lo=%s", temp);
+ TSK_FREE(temp);
+ }
+
+ canresume = tmedia_session_mgr_canresume(mgr);
+
+ TSK_OBJECT_SAFE_FREE(mgr);
+}
+
+void test_sessions_server()
+{
+ tmedia_session_mgr_t* mgr = tsk_null;
+ const tsdp_message_t* sdp_lo;
+ tsdp_message_t* sdp_ro = tsk_null;
+ char* temp;
+ tmedia_type_t type;
+
+ /* parse ro */
+ if(!(sdp_ro = tsdp_message_parse(SDP_RO, tsk_strlen(SDP_RO)))){
+ TSK_DEBUG_ERROR("Failed to parse ro");
+ return;
+ }
+ else{
+ /* get ro media type */
+ type = tmedia_type_from_sdp(sdp_ro);
+ }
+
+ /* create manager */
+ mgr = tmedia_session_mgr_create(type, "192.168.16.82", tsk_false, tsk_false);
+
+ /* set ro */
+ tmedia_session_mgr_set_ro(mgr, sdp_ro);
+
+ /* get lo */
+ sdp_lo = tmedia_session_mgr_get_lo(mgr);
+ if((temp = tsdp_message_tostring(sdp_lo))){
+ TSK_DEBUG_INFO("sdp_lo=%s", temp);
+ TSK_FREE(temp);
+ }
+
+ TSK_OBJECT_SAFE_FREE(sdp_ro);
+ TSK_OBJECT_SAFE_FREE(mgr);
+}
+
+void test_sessions_hold_resume()
+{
+ tmedia_session_mgr_t* mgr;
+ const tsdp_message_t* sdp_lo;
+ char* temp;
+ tmedia_type_t type = tmedia_audio | tmedia_video | tmedia_msrp | tmedia_t38;
+
+ /* create manager */
+ mgr = tmedia_session_mgr_create(type, "192.168.16.82", tsk_false, tsk_true);
+
+ /* get lo */
+ sdp_lo = tmedia_session_mgr_get_lo(mgr);
+ if((temp = tsdp_message_tostring(sdp_lo))){
+ TSK_DEBUG_INFO("sdp_lo=%s", temp);
+ TSK_FREE(temp);
+ }
+
+ /* hold */
+ tmedia_session_mgr_hold(mgr, type);
+ sdp_lo = tmedia_session_mgr_get_lo(mgr);
+ if((temp = tsdp_message_tostring(sdp_lo))){
+ TSK_DEBUG_INFO("sdp_lo(hold)=%s", temp);
+ TSK_FREE(temp);
+ }
+ TSK_DEBUG_INFO("Hold local=%s and remote=%s",
+ tmedia_session_mgr_is_held(mgr, type, tsk_true) ? "yes" : "no",
+ tmedia_session_mgr_is_held(mgr, type, tsk_false) ? "yes" : "no"
+ );
+
+ /* resume */
+ tmedia_session_mgr_resume(mgr, type);
+ sdp_lo = tmedia_session_mgr_get_lo(mgr);
+ if((temp = tsdp_message_tostring(sdp_lo))){
+ TSK_DEBUG_INFO("sdp_lo(resume)=%s", temp);
+ TSK_FREE(temp);
+ }
+ TSK_DEBUG_INFO("Hold local=%s and remote=%s",
+ tmedia_session_mgr_is_held(mgr, type, tsk_true) ? "yes" : "no",
+ tmedia_session_mgr_is_held(mgr, type, tsk_false) ? "yes" : "no"
+ );
+
+ TSK_OBJECT_SAFE_FREE(mgr);
+}
+
+void test_sessions_add_remove()
+{
+ tmedia_session_mgr_t* mgr = tsk_null;
+ const tsdp_message_t* sdp_lo;
+ tsdp_message_t* sdp_ro = tsk_null;
+ char* temp;
+ tmedia_type_t type;
+
+ /* parse ro */
+ if(!(sdp_ro = tsdp_message_parse(SDP_RO, tsk_strlen(SDP_RO)))){
+ TSK_DEBUG_ERROR("Failed to parse ro");
+ return;
+ }
+ else{
+ /* get ro media type */
+ type = tmedia_type_from_sdp(sdp_ro);
+ }
+
+ /* create manager */
+ mgr = tmedia_session_mgr_create(type, "192.168.16.82", tsk_false, tsk_false);
+
+ /* set ro */
+ tmedia_session_mgr_set_ro(mgr, sdp_ro);
+
+ /* get lo */
+ sdp_lo = tmedia_session_mgr_get_lo(mgr);
+ if((temp = tsdp_message_tostring(sdp_lo))){
+ TSK_DEBUG_INFO("sdp_lo=%s", temp);
+ TSK_FREE(temp);
+ }
+
+ TSK_OBJECT_SAFE_FREE(sdp_ro);
+ TSK_OBJECT_SAFE_FREE(mgr);
+}
+
+void test_sessions()
+{
+ test_sessions_client();
+ //test_sessions_server();
+ //test_sessions_hold_resume();
+}
+
+#endif /* _TEST_SESSIONS_H_ */
diff --git a/tinyMEDIA/tinyMEDIA.sln b/tinyMEDIA/tinyMEDIA.sln new file mode 100644 index 0000000..1d5009c --- /dev/null +++ b/tinyMEDIA/tinyMEDIA.sln @@ -0,0 +1,64 @@ +
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tinyMEDIA", "tinyMEDIA.vcproj", "{52814B0D-7DCA-45B8-9A16-8B147040D619}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tinySAK", "..\tinySAK\tinySAK.vcproj", "{6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test\test.vcproj", "{6ED4F246-C3B7-4DD5-9434-3A3F69CC0AD6}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tinySDP", "..\tinySDP\tinySDP.vcproj", "{E45DB518-6562-4033-80E8-60030F0B169F}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tinyNET", "..\tinyNET\tinyNET.vcproj", "{7522A458-92F4-4259-B906-E84C2A65D9F1}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ Release|Win32 = Release|Win32
+ Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {52814B0D-7DCA-45B8-9A16-8B147040D619}.Debug|Win32.ActiveCfg = Debug|Win32
+ {52814B0D-7DCA-45B8-9A16-8B147040D619}.Debug|Win32.Build.0 = Debug|Win32
+ {52814B0D-7DCA-45B8-9A16-8B147040D619}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Debug|Win32
+ {52814B0D-7DCA-45B8-9A16-8B147040D619}.Release|Win32.ActiveCfg = Release|Win32
+ {52814B0D-7DCA-45B8-9A16-8B147040D619}.Release|Win32.Build.0 = Release|Win32
+ {52814B0D-7DCA-45B8-9A16-8B147040D619}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Release|Win32
+ {6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}.Debug|Win32.ActiveCfg = Debug|Win32
+ {6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}.Debug|Win32.Build.0 = Debug|Win32
+ {6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}.Release|Win32.ActiveCfg = Release|Win32
+ {6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}.Release|Win32.Build.0 = Release|Win32
+ {6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {6BC9B796-10C6-4CF7-A6E4-E2DACCDA84DA}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {6ED4F246-C3B7-4DD5-9434-3A3F69CC0AD6}.Debug|Win32.ActiveCfg = Debug|Win32
+ {6ED4F246-C3B7-4DD5-9434-3A3F69CC0AD6}.Debug|Win32.Build.0 = Debug|Win32
+ {6ED4F246-C3B7-4DD5-9434-3A3F69CC0AD6}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Debug|Win32
+ {6ED4F246-C3B7-4DD5-9434-3A3F69CC0AD6}.Release|Win32.ActiveCfg = Release|Win32
+ {6ED4F246-C3B7-4DD5-9434-3A3F69CC0AD6}.Release|Win32.Build.0 = Release|Win32
+ {6ED4F246-C3B7-4DD5-9434-3A3F69CC0AD6}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Release|Win32
+ {E45DB518-6562-4033-80E8-60030F0B169F}.Debug|Win32.ActiveCfg = Debug|Win32
+ {E45DB518-6562-4033-80E8-60030F0B169F}.Debug|Win32.Build.0 = Debug|Win32
+ {E45DB518-6562-4033-80E8-60030F0B169F}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Debug|Win32
+ {E45DB518-6562-4033-80E8-60030F0B169F}.Release|Win32.ActiveCfg = Release|Win32
+ {E45DB518-6562-4033-80E8-60030F0B169F}.Release|Win32.Build.0 = Release|Win32
+ {E45DB518-6562-4033-80E8-60030F0B169F}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Release|Win32
+ {7522A458-92F4-4259-B906-E84C2A65D9F1}.Debug|Win32.ActiveCfg = Debug|Win32
+ {7522A458-92F4-4259-B906-E84C2A65D9F1}.Debug|Win32.Build.0 = Debug|Win32
+ {7522A458-92F4-4259-B906-E84C2A65D9F1}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {7522A458-92F4-4259-B906-E84C2A65D9F1}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {7522A458-92F4-4259-B906-E84C2A65D9F1}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {7522A458-92F4-4259-B906-E84C2A65D9F1}.Release|Win32.ActiveCfg = Release|Win32
+ {7522A458-92F4-4259-B906-E84C2A65D9F1}.Release|Win32.Build.0 = Release|Win32
+ {7522A458-92F4-4259-B906-E84C2A65D9F1}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {7522A458-92F4-4259-B906-E84C2A65D9F1}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {7522A458-92F4-4259-B906-E84C2A65D9F1}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/tinyMEDIA/tinyMEDIA.vcproj b/tinyMEDIA/tinyMEDIA.vcproj new file mode 100644 index 0000000..0e81493 --- /dev/null +++ b/tinyMEDIA/tinyMEDIA.vcproj @@ -0,0 +1,356 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="tinyMEDIA"
+ ProjectGUID="{52814B0D-7DCA-45B8-9A16-8B147040D619}"
+ RootNamespace="tinyMEDIA"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""..\thirdparties\win32\include";include;"..\tinySAK\src";"..\tinySDP\include";"..\tinyNET\src""
+ PreprocessorDefinitions="DEBUG_LEVEL=DEBUG_LEVEL_INFO;WIN32;_DEBUG;_WINDOWS;_USRDLL;TINYMEDIA_EXPORTS"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ WarnAsError="true"
+ DebugInformationFormat="4"
+ CompileAs="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="$(OutDir)\tinySAK.lib $(OutDir)\tinySDP.lib $(OutDir)\tinyNET.lib"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ EnableIntrinsicFunctions="false"
+ AdditionalIncludeDirectories=""..\thirdparties\win32\include";include;"..\tinySAK\src";"..\tinySDP\include";"..\tinyNET\src""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;TINYMEDIA_EXPORTS"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ WarnAsError="true"
+ DebugInformationFormat="0"
+ CompileAs="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="$(OutDir)\tinySAK.lib $(OutDir)\tinySDP.lib $(OutDir)\tinyNET.lib"
+ LinkIncremental="1"
+ IgnoreDefaultLibraryNames=""
+ GenerateDebugInformation="false"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="0"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="headers(*.h)"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\include\tinymedia.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinymedia_config.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinymedia\tmedia.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinymedia\tmedia_codec.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinymedia\tmedia_codec_dummy.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinymedia\tmedia_common.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinymedia\tmedia_consumer.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinymedia\tmedia_denoise.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinymedia\tmedia_params.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinymedia\tmedia_producer.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinymedia\tmedia_qos.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinymedia\tmedia_session.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinymedia\tmedia_session_dummy.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinymedia\tmedia_session_ghost.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinymedia\tmedia_vad.h"
+ >
+ </File>
+ <Filter
+ Name="content"
+ >
+ <File
+ RelativePath=".\include\tinymedia\content\tmedia_content.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinymedia\content\tmedia_content_cpim.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinymedia\content\tmedia_content_multipart.h"
+ >
+ </File>
+ <File
+ RelativePath=".\include\tinymedia\content\tmedia_content_sip_frag.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="source(*.c)"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\src\tmedia.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\tmedia_codec.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\tmedia_codec_dummy.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\tmedia_common.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\tmedia_consumer.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\tmedia_denoise.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\tmedia_params.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\tmedia_producer.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\tmedia_qos.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\tmedia_session.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\tmedia_session_dummy.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\tmedia_session_ghost.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\tmedia_vad.c"
+ >
+ </File>
+ <Filter
+ Name="content"
+ >
+ <File
+ RelativePath=".\src\content\tmedia_content.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\content\tmedia_content_cpim.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\content\tmedia_content_multipart.c"
+ >
+ </File>
+ <File
+ RelativePath=".\src\content\tmedia_content_sip_frag.c"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="ragel"
+ >
+ <File
+ RelativePath=".\ragel\tmedia_content_cpim.rl"
+ >
+ </File>
+ <File
+ RelativePath=".\ragel\tmedia_machine_utils.rl"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
|