update media layer.

This commit is contained in:
bossiel 2010-05-12 00:00:06 +00:00
parent 7113453686
commit fffaac33e4
17 changed files with 620 additions and 74 deletions

View File

@ -33,6 +33,7 @@
/* == tinyMEDIA == */
#include "tinymedia/tmedia_codec_dummy.h"
#include "tinymedia/tmedia_session_dummy.h"
#include "tinymedia/tmedia_session_ghost.h"
/* == tinySAK == */
#include "tsk.h"

View File

@ -149,15 +149,16 @@ typedef struct tmedia_codec_plugin_def_s
const char* format;
//! whether the pay. type is dyn. or not
tsk_bool_t dyn;
int32_t rate;
struct{
int32_t rate;
int8_t channels;
/* ...to be continued */
} audio;
struct{
int32_t rate;
unsigned width;
unsigned height;
/* ...to be continued */
} video;

View File

@ -32,20 +32,25 @@
#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 = 0,
tmedia_none = 0x00,
tmedia_ghost = (0x01 << 0),
tmedia_audio = (0x01 << 0),
tmedia_video = (0x01 << 1),
tmedia_msrp = (0x01 << 2),
tmedia_t38 = (0x01 << 3)
tmedia_audio = (0x01 << 1),
tmedia_video = (0x01 << 2),
tmedia_msrp = (0x01 << 3),
tmedia_t38 = (0x01 << 4)
}
tmedia_type_t;
tmedia_type_t tmedia_type_from_sdp(const tsdp_message_t* sdp);
int tmedia_parse_rtpmap(const char* rtpmap, char** name, int32_t* rate, int32_t* channels);
TMEDIA_END_DECLS

View File

@ -55,6 +55,7 @@ typedef struct tmedia_session_s
tmedia_codecs_L_t* codecs;
//! whether the session has been prepared
tsk_bool_t prepared;
unsigned initialized:1;
struct{
tsdp_header_M_t* lo;
@ -92,6 +93,7 @@ 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 int tmedia_session_deinit(tmedia_session_t* self);

View File

@ -0,0 +1,53 @@
/*
* Copyright (C) 2009 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 */

View File

@ -55,7 +55,6 @@ int tmedia_codec_init(tmedia_codec_t* self, tmedia_type_t type, const char* name
return -1;
}
self->type = type;
self->dyn = tsk_true; /* this is the default value. up to the caller to update it */
tsk_strupdate(&self->name, name);
tsk_strupdate(&self->desc,desc);
tsk_strupdate(&self->format, format);
@ -167,7 +166,7 @@ tmedia_codec_t* tmedia_codec_create(const char* format)
/* initialize the newly created codec */
codec->dyn = plugin->dyn;
codec->plugin = plugin;
switch(codec->type){
switch(plugin->type){
case tmedia_audio:
{ /* Audio codec */
tmedia_codec_audio_t* audio = TMEDIA_CODEC_AUDIO(codec);
@ -218,7 +217,7 @@ char* tmedia_codec_get_rtpmap(const tmedia_codec_t* self)
{ /* 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->format, self->name, self->plugin->audio.rate, self->plugin->audio.channels);
tsk_sprintf(&rtpmap, "%s %s/%d/%d", self->format, self->name, self->plugin->rate, self->plugin->audio.channels);
}
else{
tsk_sprintf(&rtpmap, "%s %s/%d", self->format, self->name, self->plugin->audio);
@ -228,7 +227,7 @@ char* tmedia_codec_get_rtpmap(const tmedia_codec_t* self)
case tmedia_video:
{ /* video codecs */
/* const tmedia_codec_video_t* videoCodec = (const tmedia_codec_video_t*)self; */
tsk_sprintf(&rtpmap, "%s %s/%d", self->format, self->name, self->plugin->video.rate);
tsk_sprintf(&rtpmap, "%s %s/%d", self->format, self->name, self->plugin->rate);
break;
}
/* all others */

View File

@ -88,14 +88,14 @@ static const tmedia_codec_plugin_def_t tmedia_codec_dpcmu_plugin_def_s =
"Dummy G.711u codec",
TMEDIA_CODEC_FORMAT_G711u,
tsk_false,
8000, // rate
{ /* audio */
8000, // rate
1 // channels
},
/* video */
{ tsk_null },
{{0}},
tmedia_codec_dpcmu_fmtp_match,
tmedia_codec_dpcmu_fmtp_get,
@ -145,14 +145,14 @@ static const tmedia_codec_plugin_def_t tmedia_codec_dpcma_plugin_def_s =
"Dummy G.711a codec",
TMEDIA_CODEC_FORMAT_G711a,
tsk_false,
8000, // rate
{ /* audio */
8000, // rate
1 // channels
},
/* video */
{ tsk_null },
{{0}},
tmedia_codec_dpcma_fmtp_match,
tmedia_codec_dpcma_fmtp_get,

View File

@ -0,0 +1,94 @@
/*
* Copyright (C) 2009 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((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 */
size_t len;
if(tsk_strnullORempty(rtpmap)){
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
*name = tsk_null;
*rate = *channels = 0;
len = tsk_strlen(rtpmap);
/* e.g. AMR-WB/16000/2 */
if(sscanf(rtpmap, "%*s/%*d/%*d")){
int index = tsk_strindexOf(rtpmap, len, "/");
*name = tsk_strndup(rtpmap, index);
sscanf(&rtpmap[index+1], "%d/%d", rate, channels);
}
/* e.g. AMR-WB/16000 */
else if(sscanf(rtpmap, "%*s/%*d")){
int index = tsk_strindexOf(rtpmap, len, "/");
*name = tsk_strndup(rtpmap, index);
*rate = atoi(&rtpmap[index+1]);
}
/* e.g. AMR-WB */
else{
*name = tsk_strdup(rtpmap);
return 0;
}
return -2;
}

View File

@ -29,6 +29,8 @@
*/
#include "tinymedia/tmedia_session.h"
#include "tinymedia/tmedia_session_ghost.h"
#include "tsk_memory.h"
#include "tsk_debug.h"
@ -43,10 +45,21 @@ const tmedia_session_plugin_def_t* __tmedia_session_plugins[TMED_SESSION_MAX_PLU
/* === local functions === */
int tmedia_session_mgr_prepare(tmedia_session_mgr_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);
const tsdp_header_M_t* tmedia_session_get_no(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((tmedia_session_t *)item->data), (const char*)media);
}
return -1;
}
/**@ingroup tmedia_session_group
* Initializes a newly created media session.
* @param self the media session to initialize.
@ -60,8 +73,11 @@ int tmedia_session_init(tmedia_session_t* self, tmedia_type_t type)
return -1;
}
/* set values */
self->type = type;
if(!self->initialized){
/* set values */
self->type = type;
self->initialized = tsk_true;
}
return 0;
}
@ -106,6 +122,27 @@ int tmedia_session_plugin_register(const tmedia_session_plugin_def_t* plugin)
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.
@ -157,7 +194,9 @@ tmedia_session_t* tmedia_session_create(tmedia_type_t type)
while((i < TMED_SESSION_MAX_PLUGINS) && (plugin = __tmedia_session_plugins[i++])){
if(plugin->objdef && (plugin->type == type)){
if((session = tsk_object_new(plugin->objdef))){
tmedia_session_init(session, type);
if(!session->initialized){
tmedia_session_init(session, type);
}
session->plugin = plugin;
}
break;
@ -180,6 +219,22 @@ int tmedia_session_prepare_lo(tmedia_session_t* self)
return self->plugin->prepare(self);
}
/* 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)
{
@ -262,6 +317,77 @@ int _tmedia_session_load_codecs(tmedia_session_t* self)
return 0;
}
/* internal function used to match a codec */
const tmedia_codec_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;
const tsdp_fmt_t* fmt;
const tsk_list_item_t *it1, *it2;
tsk_bool_t found = tsk_false;
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))){
char* name = tsk_null;
int32_t rate, channels;
/* parse rtpmap */
if(tmedia_parse_rtpmap(rtpmap, &name, &rate, &channels)){
TSK_FREE(name);
TSK_DEBUG_ERROR("Failed to parse rtpmap(%s)", rtpmap);
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;
}
}
/* free strings and try next */
goto next;
compare_fmtp:
if((fmtp = tsdp_header_M_get_fmtp(M, fmt->value))){ /* have fmtp? */
if(tmedia_codec_match_fmtp(codec, fmtp)){ /* fmtp matches? */
found = tsk_true;
}
}
else{ /* no fmtp -> always match */
found = tsk_true;
}
next:
TSK_FREE(fmtp);
TSK_FREE(rtpmap);
if(found){
return codec;
}
}
}
return tsk_null;
}
/**@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).
@ -360,10 +486,10 @@ tsdp_message_t* tmedia_session_mgr_get_no(tmedia_session_mgr_t* self)
*/
int tmedia_session_mgr_set_ro(tmedia_session_mgr_t* self, const tsdp_message_t* sdp)
{
const tsk_list_item_t* it1, *it2;
const tmedia_session_t* ms;
const tmedia_codec_t* codec;
const tsdp_header_M_t* M;
tsk_size_t index = 0;
tsk_bool_t found;
if(!self || !sdp){
TSK_DEBUG_ERROR("Invalid parameter");
@ -374,7 +500,8 @@ int tmedia_session_mgr_set_ro(tmedia_session_mgr_t* self, const tsdp_message_t*
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) */
/* prepare the session manager if not already done (create all sessions with their codecs)
* if net-initiated: think about tmedia_type_from_sdp() before creating the manager */
if(!self->prepared){
if(tmedia_session_mgr_prepare(self)){
TSK_DEBUG_ERROR("Failed to prepare the session manager");
@ -382,37 +509,63 @@ int tmedia_session_mgr_set_ro(tmedia_session_mgr_t* self, const tsdp_message_t*
}
}
tsk_list_foreach(it1, sdp->headers){
if(!(it1->data) || (TSDP_HEADER(it1->data)->type != tsdp_htype_M)){
continue;
}
M = (const tsdp_header_M_t*)(it1->data);
}
/* foreach session */
tsk_list_foreach(it1, self->sessions){
if(!(ms = it1->data)){
continue;
/* 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_data_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;
}
}
/* for each codec in the curr. session */
tsk_list_foreach(it2, ms->codecs){
if(!(codec = it2->data)){
if(!found){
/* Session not supported ==> 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;
}
/* Codec with fixed payload type */
if(!codec->dyn){
}
/* codec with dyn. payload type */
else{
}
}
}
/* update negociated offer */
if(self->sdp.lo && self->sdp.ro){
TSK_OBJECT_SAFE_FREE(self->sdp.no);
//...
}
///* foreach session */
//tsk_list_foreach(it1, self->sessions){
// if(!(ms = it1->data)){
// continue;
// }
//
//
// /* foreach codec in the curr. session */
// tsk_list_foreach(it2, ms->codecs){
// if(!(codec = it2->data)){
// continue;
// }
// /* Codec with fixed payload type */
// if(!codec->dyn){
//
// }
// /* codec with dyn. payload type */
// else{
// }
// }
//
//}
return 0;
}
@ -423,13 +576,16 @@ int tmedia_session_mgr_prepare(tmedia_session_mgr_t* self)
tmedia_session_t* session;
const tmedia_session_plugin_def_t* plugin;
/* 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));
if(!self->prepared){
/* 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));
}
}
}
self->prepared = tsk_true;
}
return 0;
}

View File

@ -33,6 +33,7 @@
#include "tsk_debug.h"
extern int _tmedia_session_load_codecs(tmedia_session_t* self);
extern const tmedia_codec_t* _tmedia_session_match_codec(tmedia_session_t* self, const tsdp_header_M_t* M);
/* ============ Audio Session ================= */
@ -132,8 +133,18 @@ const tsdp_header_M_t* tmedia_session_daudio_get_no(tmedia_session_t* self)
int tmedia_session_daudio_set_ro(tmedia_session_t* self, const tsdp_header_M_t* m)
{
const tmedia_codec_t* codec;
TSK_DEBUG_INFO("tmedia_session_daudio_set_ro");
return tsk_null;
if((codec = _tmedia_session_match_codec(self, m))){
/* update remote offer */
TSK_OBJECT_SAFE_FREE(self->M.ro);
self->M.ro = tsk_object_ref((void*)m);
return 0;
}
return -1;
}
/* ============ Video Session ================= */
@ -147,19 +158,19 @@ int tmedia_session_dvideo_prepare(tmedia_session_t* self)
int tmedia_session_dvideo_start(tmedia_session_t* self)
{
TSK_DEBUG_INFO("tmedia_session_dvideo_start");
return 0;
return -1;
}
int tmedia_session_dvideo_stop(tmedia_session_t* self)
{
TSK_DEBUG_INFO("tmedia_session_dvideo_stop");
return 0;
return -1;
}
int tmedia_session_dvideo_pause(tmedia_session_t* self)
{
TSK_DEBUG_INFO("tmedia_session_dvideo_pause");
return 0;
return -1;
}
const tsdp_header_M_t* tmedia_session_dvideo_get_lo(tmedia_session_t* self)
@ -177,7 +188,7 @@ const tsdp_header_M_t* tmedia_session_dvideo_get_no(tmedia_session_t* self)
int tmedia_session_dvideo_set_ro(tmedia_session_t* self, const tsdp_header_M_t* m)
{
TSK_DEBUG_INFO("tmedia_session_dvideo_set_ro");
return tsk_null;
return -1;
}
/* ============ Msrp Session ================= */
@ -185,25 +196,25 @@ int tmedia_session_dvideo_set_ro(tmedia_session_t* self, const tsdp_header_M_t*
int tmedia_session_dmsrp_prepare(tmedia_session_t* self)
{
TSK_DEBUG_INFO("tmedia_session_dmsrp_prepare");
return 0;
return -1;
}
int tmedia_session_dmsrp_start(tmedia_session_t* self)
{
TSK_DEBUG_INFO("tmedia_session_dmsrp_start");
return 0;
return -1;
}
int tmedia_session_dmsrp_stop(tmedia_session_t* self)
{
TSK_DEBUG_INFO("tmedia_session_dmsrp_stop");
return 0;
return -1;
}
int tmedia_session_dmsrp_pause(tmedia_session_t* self)
{
TSK_DEBUG_INFO("tmedia_session_dmsrp_pause");
return 0;
return -1;
}
const tsdp_header_M_t* tmedia_session_dmsrp_get_lo(tmedia_session_t* self)
@ -221,7 +232,7 @@ const tsdp_header_M_t* tmedia_session_dmsrp_get_no(tmedia_session_t* self)
int tmedia_session_dmsrp_set_ro(tmedia_session_t* self, const tsdp_header_M_t* m)
{
TSK_DEBUG_INFO("tmedia_session_dmsrp_set_ro");
return tsk_null;
return -1;
}
//=================================================================================================
@ -243,6 +254,7 @@ 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 */
}
@ -295,6 +307,7 @@ 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 */
}
@ -347,6 +360,7 @@ 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 */
}

View File

@ -0,0 +1,136 @@
/*
* Copyright (C) 2009 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)
{
TSK_DEBUG_INFO("tmedia_session_ghost_prepare");
return 0;
}
int tmedia_session_ghost_start(tmedia_session_t* self)
{
TSK_DEBUG_INFO("tmedia_session_ghost_start");
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)
{
TSK_DEBUG_INFO("tmedia_session_ghost_pause");
return 0;
}
const tsdp_header_M_t* tmedia_session_ghost_get_lo(tmedia_session_t* self)
{
TSK_DEBUG_INFO("tmedia_session_ghost_get_lo");
return tsk_null;
}
const tsdp_header_M_t* tmedia_session_ghost_get_no(tmedia_session_t* self)
{
TSK_DEBUG_INFO("tmedia_session_ghost_get_no");
return tsk_null;
}
int tmedia_session_ghost_set_ro(tmedia_session_t* self, const tsdp_header_M_t* m)
{
TSK_DEBUG_INFO("tmedia_session_ghost_set_ro");
return tsk_null;
}
//=================================================================================================
// 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",
tmedia_session_ghost_prepare,
tmedia_session_ghost_start,
tmedia_session_ghost_stop,
tmedia_session_ghost_pause,
tmedia_session_ghost_get_lo,
tmedia_session_ghost_get_no,
tmedia_session_ghost_set_ro
};
const tmedia_session_plugin_def_t *tmedia_session_ghost_plugin_def_t = &tmedia_session_ghost_plugin_def_s;

View File

@ -30,7 +30,7 @@
#define RUN_TEST_LOOP 1
#define RUN_TEST_ALL 0
#define RUN_TEST_CODECS 1
#define RUN_TEST_CODECS 0
#define RUN_TEST_SESSIONS 1
void test_register_dummy_plugins();
@ -75,6 +75,9 @@ void test_register_dummy_plugins()
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))){

View File

@ -22,6 +22,46 @@
#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 0 8 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:0 PCMU/8000\r\n" \
"a=rtpmap:8 PCMA/8000\r\n" \
"a=rtpmap:97 iLBC/8000\r\n" \
"a=rtpmap:98 AMR-WB/16000\r\n" \
"a=fmtp:98 octet-align=1\r\n" \
"m=video 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" \
"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()
{
tmedia_session_mgr_t* mgr;
@ -33,12 +73,18 @@ void test_sessions()
mgr = tmedia_session_mgr_create((tmedia_audio | tmedia_video | tmedia_msrp | tmedia_t38),
"192.168.16.82", tsk_false);
/* get local sdp */
/* 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);
}
TSK_OBJECT_SAFE_FREE(mgr);
}

View File

@ -178,6 +178,10 @@
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"
>
@ -206,6 +210,10 @@
RelativePath=".\include\tinymedia\tmedia_session_dummy.h"
>
</File>
<File
RelativePath=".\include\tinymedia\tmedia_session_ghost.h"
>
</File>
</Filter>
<Filter
Name="source(*.c)"
@ -224,6 +232,10 @@
RelativePath=".\src\tmedia_codec_dummy.c"
>
</File>
<File
RelativePath=".\src\tmedia_common.c"
>
</File>
<File
RelativePath=".\src\tmedia_session.c"
>
@ -232,6 +244,10 @@
RelativePath=".\src\tmedia_session_dummy.c"
>
</File>
<File
RelativePath=".\src\tmedia_session_ghost.c"
>
</File>
</Filter>
</Files>
<Globals>

View File

@ -395,6 +395,7 @@ const tsk_list_item_t* tsk_list_find_item_by_data(const tsk_list_t* list, const
* @param predicate the predicate against which to test each item
* @param data data passed to the predicate function for comparaison
* @retval the item which match the criteria and NULL otherwise
* @sa @ref tsk_list_find_data_by_pred
*/
const tsk_list_item_t* tsk_list_find_item_by_pred(const tsk_list_t* list, tsk_list_func_predicate predicate, const void* data)
{
@ -412,6 +413,25 @@ const tsk_list_item_t* tsk_list_find_item_by_pred(const tsk_list_t* list, tsk_li
return tsk_null;
}
/**@ingroup tsk_list_group
* Find first item matching criteria defined by the @a predicate.
* @param list the list to query
* @param predicate the predicate against which to test each item
* @param data data passed to the predicate function for comparaison
* @retval the data holded by the item which match the criteria and NULL otherwise
* @sa @ref tsk_list_find_item_by_pred
*/
const tsk_object_t* tsk_list_find_data_by_pred(const tsk_list_t* list, tsk_list_func_predicate predicate, const void* data)
{
const tsk_list_item_t *item;
if((item = tsk_list_find_item_by_pred(list, predicate, data))){
return item->data;
}
else{
return tsk_null;
}
}
/**@ingroup tsk_list_group
* Counts the number of item matching the predicate.
* @param list The list containing the items to count

View File

@ -114,6 +114,7 @@ TINYSAK_API int tsk_list_push_filtered_data(tsk_list_t* list, void** data, tsk_b
TINYSAK_API const tsk_list_item_t* tsk_list_find_item_by_data(const tsk_list_t* list, const tsk_object_t * tskobj);
TINYSAK_API const tsk_list_item_t* tsk_list_find_item_by_pred(const tsk_list_t* list, tsk_list_func_predicate predicate, const void* data);
TINYSAK_API const tsk_object_t* tsk_list_find_data_by_pred(const tsk_list_t* list, tsk_list_func_predicate predicate, const void* data);
TINYSAK_API tsk_size_t tsk_list_count(const tsk_list_t* list, tsk_list_func_predicate predicate, const void* data);
TINYSAK_GEXTERN const tsk_object_def_t *tsk_list_def_t;

View File

@ -35,6 +35,8 @@
#include "tinysdp/headers/tsdp_header_T.h"
#include "tinysdp/headers/tsdp_header_V.h"
#include "tsk_debug.h"
#define TSDP_LINE_S_VALUE_DEFAULT "-" /* as per RFC 3264 subclause 5 */
#define TSDP_LINE_O_USERNAME_DEFAULT "doubango"
@ -44,8 +46,7 @@
/*== Predicate function to find tsdp_header_t object by type. */
int __pred_find_header_by_type(const tsk_list_item_t *item, const void *tsdp_htype)
{
if(item && item->data)
{
if(item && item->data){
tsdp_header_t *header = item->data;
tsdp_header_type_t htype = *((tsdp_header_type_t*)tsdp_htype);
return (header->type - htype);
@ -56,8 +57,7 @@ int __pred_find_header_by_type(const tsk_list_item_t *item, const void *tsdp_hty
/*== Predicate function to find tsdp_header_t object by name. */
int __pred_find_header_by_name(const tsk_list_item_t *item, const void *name)
{
if(item && item->data && name)
{
if(item && item->data && name){
tsdp_header_t *header = item->data;
return tsdp_header_get_nameex(header) - *((const char*)name);
}
@ -67,8 +67,7 @@ int __pred_find_header_by_name(const tsk_list_item_t *item, const void *name)
/*== Predicate function to find media object by name. */
int __pred_find_media_by_name(const tsk_list_item_t *item, const void *name)
{
if(item && item->data && name)
{
if(item && item->data && name){
tsdp_header_t *header = item->data;
if(header->type == tsdp_htype_M){
return tsk_stricmp(((tsdp_header_M_t*)header)->media, (const char*)name);
@ -171,13 +170,13 @@ const tsdp_header_t *tsdp_message_get_header(const tsdp_message_t *self, tsdp_he
const tsdp_header_t *tsdp_message_get_headerByName(const tsdp_message_t *self, char name)
{
if(self && self->headers){
const tsk_list_item_t* item;
if((item = tsk_list_find_item_by_pred(self->headers, __pred_find_header_by_name, &name))){
return item->data;
}
if(self){
return tsk_list_find_data_by_pred(self->headers, __pred_find_header_by_name, &name);
}
else{
TSK_DEBUG_ERROR("Invalid parameter");
return tsk_null;
}
return tsk_null;
}
int tsdp_message_serialize(const tsdp_message_t *self, tsk_buffer_t *output)