Modifications in PJSUA-LIB to support multiple media streams (multiple audio and/or video) and dynamic creation of media transports. This closed #1185 and closed #1201.
1185: Dynamic creation of media transports ============================================ Done: - media transports are created on demand now Todo: - media transport creation is still blocking 1201: Video support in PJSUA-LIB =================================== Done: - call now supports N media (N audio and M video) - number of audio/video streams is configurable per acc - extra audio stream info in pjsua_call_info to support multiple audio streams in one call - video subsys and ffmpeg initialization in PJSUA-LIB - ability to offer and create video SDP answer - "dq" for more than 1 audio streams - introducing pjsua_state and pjsua_get_state() API change: - on_stream_created() and on_stream_destroyed() callbacks: changed session to stream Todo: - many others features are disabled, just search for DISABLED_FOR_TICKET_1185 macro (these have also been added to ticket #1193 (Issues & Todos)). Notable missing features are: - creation of duplicate SDP m= lines for optional SRTP - mm.. that's it? - whole lot of testings pjsua: =============== - Added --extra-audio and --video options. Specify these more than once and each time an extra audio/video streams will be added. :) git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/projects/2.0-dev@3457 74dad513-b988-da41-8d7b-12977e46ad98
This commit is contained in:
parent
854ec1a682
commit
0bc99a9ca3
32
build.mak.in
32
build.mak.in
|
@ -58,12 +58,43 @@ endif
|
|||
# Additional flags
|
||||
@ac_build_mak_vars@
|
||||
|
||||
#
|
||||
# Video
|
||||
# Note: there are duplicated macros in pjmedia/os-auto.mak.in (and that's not
|
||||
# good!
|
||||
|
||||
# SDL flags
|
||||
SDL_CFLAGS = @ac_sdl_cflags@
|
||||
SDL_LDFLAGS = @ac_sdl_ldflags@
|
||||
|
||||
# FFMPEG dlags
|
||||
FFMPEG_CFLAGS = @ac_ffmpeg_cflags@
|
||||
FFMPEG_LDFLAGS = @ac_ffmpeg_ldflags@
|
||||
|
||||
# Video4Linux2
|
||||
V4L2_CFLAGS = @ac_v4l2_cflags@
|
||||
V4L2_LDFLAGS = @ac_v4l2_ldflags@
|
||||
|
||||
# QT
|
||||
AC_PJMEDIA_VIDEO_HAS_QT = @ac_pjmedia_video_has_qt@
|
||||
QT_CFLAGS = @ac_qt_cflags@
|
||||
|
||||
# iOS
|
||||
IOS_CFLAGS = @ac_ios_cflags@
|
||||
|
||||
# PJMEDIA features exclusion
|
||||
PJ_VIDEO_CFLAGS += $(SDL_CFLAGS) $(FFMPEG_CFLAGS) $(V4L2_CFLAGS) $(QT_CFLAGS) \
|
||||
$(IOS_CFLAGS)
|
||||
PJ_VIDEO_LDFLAGS += $(SDL_LDFLAGS) $(FFMPEG_LDFLAGS) $(V4L2_LDFLAGS)
|
||||
|
||||
|
||||
# CFLAGS, LDFLAGS, and LIBS to be used by applications
|
||||
export PJDIR := @ac_pjdir@
|
||||
export APP_CC := @CC@
|
||||
export APP_CXX := @CXX@
|
||||
export APP_CFLAGS := -DPJ_AUTOCONF=1\
|
||||
@CFLAGS@\
|
||||
$(PJ_VIDEO_CFLAGS) \
|
||||
-I$(PJDIR)/pjlib/include\
|
||||
-I$(PJDIR)/pjlib-util/include\
|
||||
-I$(PJDIR)/pjnath/include\
|
||||
|
@ -76,6 +107,7 @@ export APP_LDFLAGS := -L$(PJDIR)/pjlib/lib\
|
|||
-L$(PJDIR)/pjmedia/lib\
|
||||
-L$(PJDIR)/pjsip/lib\
|
||||
-L$(PJDIR)/third_party/lib\
|
||||
$(PJ_VIDEO_LDFLAGS) \
|
||||
@LDFLAGS@
|
||||
export APP_LDLIBS := -lpjsua-$(TARGET_NAME)\
|
||||
-lpjsip-ua-$(TARGET_NAME)\
|
||||
|
|
|
@ -483,6 +483,9 @@ struct pjmedia_transport
|
|||
|
||||
/** Transport's "virtual" function table. */
|
||||
pjmedia_transport_op *op;
|
||||
|
||||
/** Application/user data */
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -267,7 +267,7 @@ static void usage(void)
|
|||
puts (" --tls-srv-name Specify TLS server name for multihosting server");
|
||||
|
||||
puts ("");
|
||||
puts ("Media Options:");
|
||||
puts ("Audio Options:");
|
||||
puts (" --add-codec=name Manually add codec (default is to enable all)");
|
||||
puts (" --dis-codec=name Disable codec (can be specified multiple times)");
|
||||
puts (" --clock-rate=N Override conference bridge clock rate");
|
||||
|
@ -301,6 +301,11 @@ static void usage(void)
|
|||
puts (" Specify N=0 for instant close when unused.");
|
||||
puts (" --no-tones Disable audible tones");
|
||||
puts (" --jb-max-size Specify jitter buffer maximum size, in frames (default=-1)");
|
||||
puts (" --extra-audio Add one more audio stream");
|
||||
|
||||
puts ("");
|
||||
puts ("Video Options:");
|
||||
puts (" --video Enable video");
|
||||
|
||||
puts ("");
|
||||
puts ("Media Transport Options:");
|
||||
|
@ -540,7 +545,8 @@ static pj_status_t parse_args(int argc, char *argv[],
|
|||
#endif
|
||||
OPT_AUTO_UPDATE_NAT,OPT_USE_COMPACT_FORM,OPT_DIS_CODEC,
|
||||
OPT_NO_FORCE_LR,
|
||||
OPT_TIMER, OPT_TIMER_SE, OPT_TIMER_MIN_SE
|
||||
OPT_TIMER, OPT_TIMER_SE, OPT_TIMER_MIN_SE,
|
||||
OPT_VIDEO, OPT_EXTRA_AUDIO
|
||||
};
|
||||
struct pj_getopt_option long_options[] = {
|
||||
{ "config-file",1, 0, OPT_CONFIG_FILE},
|
||||
|
@ -659,6 +665,8 @@ static pj_status_t parse_args(int argc, char *argv[],
|
|||
{ "timer-se", 1, 0, OPT_TIMER_SE},
|
||||
{ "timer-min-se", 1, 0, OPT_TIMER_MIN_SE},
|
||||
{ "outb-rid", 1, 0, OPT_OUTB_RID},
|
||||
{ "video", 0, 0, OPT_VIDEO},
|
||||
{ "extra-audio",0, 0, OPT_EXTRA_AUDIO},
|
||||
{ NULL, 0, 0, 0}
|
||||
};
|
||||
pj_status_t status;
|
||||
|
@ -1416,6 +1424,12 @@ static pj_status_t parse_args(int argc, char *argv[],
|
|||
cfg->udp_cfg.qos_params.flags = PJ_QOS_PARAM_HAS_DSCP;
|
||||
cfg->udp_cfg.qos_params.dscp_val = 0x18;
|
||||
break;
|
||||
case OPT_VIDEO:
|
||||
++cur_acc->max_video_cnt;
|
||||
break;
|
||||
case OPT_EXTRA_AUDIO:
|
||||
++cur_acc->max_audio_cnt;
|
||||
break;
|
||||
default:
|
||||
PJ_LOG(1,(THIS_FILE,
|
||||
"Argument \"%s\" is not valid. Use --help to see help",
|
||||
|
@ -1660,6 +1674,14 @@ static void write_account_settings(int acc_index, pj_str_t *result)
|
|||
/* MWI */
|
||||
if (acc_cfg->mwi_enabled)
|
||||
pj_strcat2(result, "--mwi\n");
|
||||
|
||||
/* Video & extra audio */
|
||||
for (i=0; i<acc_cfg->max_video_cnt; ++i) {
|
||||
pj_strcat2(result, "--video\n");
|
||||
}
|
||||
for (i=1; i<acc_cfg->max_audio_cnt; ++i) {
|
||||
pj_strcat2(result, "--extra-audio\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -3891,6 +3913,8 @@ void console_app_main(const pj_str_t *uri_to_call)
|
|||
acc_cfg.cred_info[0].data_type = 0;
|
||||
acc_cfg.cred_info[0].data = pj_str(passwd);
|
||||
|
||||
acc_cfg.rtp_cfg = app_config.rtp_cfg;
|
||||
|
||||
status = pjsua_acc_add(&acc_cfg, PJ_TRUE, NULL);
|
||||
if (status != PJ_SUCCESS) {
|
||||
pjsua_perror(THIS_FILE, "Error adding new account", status);
|
||||
|
@ -4928,6 +4952,7 @@ pj_status_t app_init(int argc, char *argv[])
|
|||
|
||||
/* Add accounts */
|
||||
for (i=0; i<app_config.acc_cnt; ++i) {
|
||||
app_config.acc_cfg[i].rtp_cfg = app_config.rtp_cfg;
|
||||
status = pjsua_acc_add(&app_config.acc_cfg[i], PJ_TRUE, NULL);
|
||||
if (status != PJ_SUCCESS)
|
||||
goto on_error;
|
||||
|
@ -4959,8 +4984,10 @@ pj_status_t app_init(int argc, char *argv[])
|
|||
#else
|
||||
if (app_config.ipv6)
|
||||
status = create_ipv6_media_transports();
|
||||
#if DISABLED_FOR_TICKET_1185
|
||||
else
|
||||
status = pjsua_media_transports_create(&app_config.rtp_cfg);
|
||||
#endif
|
||||
#endif
|
||||
if (status != PJ_SUCCESS)
|
||||
goto on_error;
|
||||
|
@ -5295,6 +5322,10 @@ static pj_status_t create_ipv6_media_transports(void)
|
|||
}
|
||||
}
|
||||
|
||||
#if DISABLED_FOR_TICKET_1185
|
||||
return pjsua_media_transports_attach(tp, i, PJ_TRUE);
|
||||
#else
|
||||
return PJ_ENOTSUP;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ export PJSUA_LIB_SRCDIR = ../src/pjsua-lib
|
|||
export PJSUA_LIB_OBJS += $(OS_OBJS) $(M_OBJS) $(CC_OBJS) $(HOST_OBJS) \
|
||||
pjsua_acc.o pjsua_call.o pjsua_core.o \
|
||||
pjsua_im.o pjsua_media.o pjsua_pres.o
|
||||
export PJSUA_LIB_CFLAGS += $(_CFLAGS)
|
||||
export PJSUA_LIB_CFLAGS += $(_CFLAGS) $(PJ_VIDEO_CFLAGS)
|
||||
|
||||
|
||||
export CC_OUT CC AR RANLIB HOST_MV HOST_RM HOST_RMDIR HOST_MKDIR OBJEXT LD LDOUT
|
||||
|
|
|
@ -250,6 +250,9 @@ PJ_BEGIN_DECL
|
|||
/** Constant to identify invalid ID for all sorts of IDs. */
|
||||
#define PJSUA_INVALID_ID (-1)
|
||||
|
||||
/** Disabled features temporarily for media reorganization */
|
||||
#define DISABLED_FOR_TICKET_1185 0
|
||||
|
||||
/** Call identification */
|
||||
typedef int pjsua_call_id;
|
||||
|
||||
|
@ -282,8 +285,6 @@ typedef struct pjsua_msg_data pjsua_msg_data;
|
|||
# define PJSUA_ACC_MAX_PROXIES 8
|
||||
#endif
|
||||
|
||||
#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
|
||||
|
||||
/**
|
||||
* Default value of SRTP mode usage. Valid values are PJMEDIA_SRTP_DISABLED,
|
||||
* PJMEDIA_SRTP_OPTIONAL, and PJMEDIA_SRTP_MANDATORY.
|
||||
|
@ -303,8 +304,6 @@ typedef struct pjsua_msg_data pjsua_msg_data;
|
|||
#define PJSUA_DEFAULT_SRTP_SECURE_SIGNALING 1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Controls whether PJSUA-LIB should add ICE media feature tag
|
||||
* parameter (the ";+sip.ice" parameter) to Contact header if ICE
|
||||
|
@ -326,6 +325,44 @@ typedef struct pjsua_msg_data pjsua_msg_data;
|
|||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* This enumeration represents pjsua state.
|
||||
*/
|
||||
typedef enum pjsua_state
|
||||
{
|
||||
/**
|
||||
* The library has not been initialized.
|
||||
*/
|
||||
PJSUA_STATE_NULL,
|
||||
|
||||
/**
|
||||
* After pjsua_create() is called but before pjsua_init() is called.
|
||||
*/
|
||||
PJSUA_STATE_CREATED,
|
||||
|
||||
/**
|
||||
* After pjsua_init() is called but before pjsua_start() is called.
|
||||
*/
|
||||
PJSUA_STATE_INIT,
|
||||
|
||||
/**
|
||||
* After pjsua_start() is called but before everything is running.
|
||||
*/
|
||||
PJSUA_STATE_STARTING,
|
||||
|
||||
/**
|
||||
* After pjsua_start() is called and before pjsua_destroy() is called.
|
||||
*/
|
||||
PJSUA_STATE_RUNNING,
|
||||
|
||||
/**
|
||||
* After pjsua_destroy() is called but before the function returns.
|
||||
*/
|
||||
PJSUA_STATE_CLOSING
|
||||
|
||||
} pjsua_state;
|
||||
|
||||
|
||||
/**
|
||||
* Logging configuration, which can be (optionally) specified when calling
|
||||
* #pjsua_init(). Application must call #pjsua_logging_config_default() to
|
||||
|
@ -483,7 +520,7 @@ typedef struct pjsua_callback
|
|||
* media port then will be added to the conference bridge instead.
|
||||
*
|
||||
* @param call_id Call identification.
|
||||
* @param sess Media session for the call.
|
||||
* @param strm Media stream.
|
||||
* @param stream_idx Stream index in the media session.
|
||||
* @param p_port On input, it specifies the media port of the
|
||||
* stream. Application may modify this pointer to
|
||||
|
@ -491,7 +528,7 @@ typedef struct pjsua_callback
|
|||
* to the conference bridge.
|
||||
*/
|
||||
void (*on_stream_created)(pjsua_call_id call_id,
|
||||
pjmedia_session *sess,
|
||||
pjmedia_stream *strm,
|
||||
unsigned stream_idx,
|
||||
pjmedia_port **p_port);
|
||||
|
||||
|
@ -500,11 +537,11 @@ typedef struct pjsua_callback
|
|||
* conference bridge and about to be destroyed.
|
||||
*
|
||||
* @param call_id Call identification.
|
||||
* @param sess Media session for the call.
|
||||
* @param strm Media stream.
|
||||
* @param stream_idx Stream index in the media session.
|
||||
*/
|
||||
void (*on_stream_destroyed)(pjsua_call_id call_id,
|
||||
pjmedia_session *sess,
|
||||
pjmedia_stream *strm,
|
||||
unsigned stream_idx);
|
||||
|
||||
/**
|
||||
|
@ -1154,7 +1191,6 @@ typedef struct pjsua_config
|
|||
*/
|
||||
pj_str_t user_agent;
|
||||
|
||||
#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
|
||||
/**
|
||||
* Specify default value of secure media transport usage.
|
||||
* Valid values are PJMEDIA_SRTP_DISABLED, PJMEDIA_SRTP_OPTIONAL, and
|
||||
|
@ -1184,15 +1220,14 @@ typedef struct pjsua_config
|
|||
int srtp_secure_signaling;
|
||||
|
||||
/**
|
||||
* Specify whether SRTP in PJMEDIA_SRTP_OPTIONAL mode should compose
|
||||
* Specify whether SRTP in PJMEDIA_SRTP_OPTIONAL mode should compose
|
||||
* duplicated media in SDP offer, i.e: unsecured and secured version.
|
||||
* Otherwise, the SDP media will be composed as unsecured media but
|
||||
* Otherwise, the SDP media will be composed as unsecured media but
|
||||
* with SDP "crypto" attribute.
|
||||
*
|
||||
* Default: PJ_FALSE
|
||||
*/
|
||||
pj_bool_t srtp_optional_dup_offer;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Disconnect other call legs when more than one 2xx responses for
|
||||
|
@ -1352,6 +1387,14 @@ PJ_DECL(pj_status_t) pjsua_start(void);
|
|||
PJ_DECL(pj_status_t) pjsua_destroy(void);
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve pjsua state.
|
||||
*
|
||||
* @return pjsua state.
|
||||
*/
|
||||
PJ_DECL(pjsua_state) pjsua_get_state(void);
|
||||
|
||||
|
||||
/**
|
||||
* Poll pjsua for events, and if necessary block the caller thread for
|
||||
* the specified maximum interval (in miliseconds).
|
||||
|
@ -2093,7 +2136,6 @@ typedef enum pjsua_call_hold_type
|
|||
# define PJSUA_CALL_HOLD_TYPE_DEFAULT PJSUA_CALL_HOLD_TYPE_RFC3264
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* This structure describes account configuration to be specified when
|
||||
* adding a new account with #pjsua_acc_add(). Application MUST initialize
|
||||
|
@ -2384,7 +2426,29 @@ typedef struct pjsua_acc_config
|
|||
*/
|
||||
pj_str_t ka_data;
|
||||
|
||||
#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
|
||||
/**
|
||||
* Maximum number of simultaneous active audio streams to be allowed
|
||||
* for calls on this account. Setting this to zero will disable audio
|
||||
* in calls on this account.
|
||||
*
|
||||
* Default: 1
|
||||
*/
|
||||
unsigned max_audio_cnt;
|
||||
|
||||
/**
|
||||
* Maximum number of simultaneous active video streams to be allowed
|
||||
* for calls on this account. Setting this to zero will disable video
|
||||
* in calls on this account.
|
||||
*
|
||||
* Default: 0
|
||||
*/
|
||||
unsigned max_video_cnt;
|
||||
|
||||
/**
|
||||
* Media transport config.
|
||||
*/
|
||||
pjsua_transport_config rtp_cfg;
|
||||
|
||||
/**
|
||||
* Specify whether secure media transport should be used for this account.
|
||||
* Valid values are PJMEDIA_SRTP_DISABLED, PJMEDIA_SRTP_OPTIONAL, and
|
||||
|
@ -2408,15 +2472,14 @@ typedef struct pjsua_acc_config
|
|||
int srtp_secure_signaling;
|
||||
|
||||
/**
|
||||
* Specify whether SRTP in PJMEDIA_SRTP_OPTIONAL mode should compose
|
||||
* Specify whether SRTP in PJMEDIA_SRTP_OPTIONAL mode should compose
|
||||
* duplicated media in SDP offer, i.e: unsecured and secured version.
|
||||
* Otherwise, the SDP media will be composed as unsecured media but
|
||||
* Otherwise, the SDP media will be composed as unsecured media but
|
||||
* with SDP "crypto" attribute.
|
||||
*
|
||||
* Default: PJ_FALSE
|
||||
*/
|
||||
pj_bool_t srtp_optional_dup_offer;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Specify interval of auto registration retry upon registration failure
|
||||
|
@ -2920,19 +2983,29 @@ PJ_DECL(pj_status_t) pjsua_acc_set_transport(pjsua_acc_id acc_id,
|
|||
*/
|
||||
typedef enum pjsua_call_media_status
|
||||
{
|
||||
/** Call currently has no media */
|
||||
/**
|
||||
* Call currently has no media, or the media is not used.
|
||||
*/
|
||||
PJSUA_CALL_MEDIA_NONE,
|
||||
|
||||
/** The media is active */
|
||||
/**
|
||||
* The media is active
|
||||
*/
|
||||
PJSUA_CALL_MEDIA_ACTIVE,
|
||||
|
||||
/** The media is currently put on hold by local endpoint */
|
||||
/**
|
||||
* The media is currently put on hold by local endpoint
|
||||
*/
|
||||
PJSUA_CALL_MEDIA_LOCAL_HOLD,
|
||||
|
||||
/** The media is currently put on hold by remote endpoint */
|
||||
/**
|
||||
* The media is currently put on hold by remote endpoint
|
||||
*/
|
||||
PJSUA_CALL_MEDIA_REMOTE_HOLD,
|
||||
|
||||
/** The media has reported error (e.g. ICE negotiation) */
|
||||
/**
|
||||
* The media has reported error (e.g. ICE negotiation)
|
||||
*/
|
||||
PJSUA_CALL_MEDIA_ERROR
|
||||
|
||||
} pjsua_call_media_status;
|
||||
|
@ -2982,12 +3055,32 @@ typedef struct pjsua_call_info
|
|||
/** Call media status. */
|
||||
pjsua_call_media_status media_status;
|
||||
|
||||
/** Media direction */
|
||||
/** Number of active audio streams in this call */
|
||||
unsigned audio_cnt;
|
||||
|
||||
/** Media direction of the first audio stream. */
|
||||
pjmedia_dir media_dir;
|
||||
|
||||
/** The conference port number for the call */
|
||||
/** The conference port number for the first audio stream. */
|
||||
pjsua_conf_port_id conf_slot;
|
||||
|
||||
/** Array of audio media stream information */
|
||||
struct
|
||||
{
|
||||
/** Media index in SDP. */
|
||||
unsigned index;
|
||||
|
||||
/** Call media status. */
|
||||
pjsua_call_media_status media_status;
|
||||
|
||||
/** Media direction. */
|
||||
pjmedia_dir media_dir;
|
||||
|
||||
/** The conference port number for the call. */
|
||||
pjsua_conf_port_id conf_slot;
|
||||
|
||||
} audio[4];
|
||||
|
||||
/** Up-to-date call connected duration (zero when call is not
|
||||
* established)
|
||||
*/
|
||||
|
@ -3082,6 +3175,7 @@ PJ_DECL(pj_bool_t) pjsua_call_is_active(pjsua_call_id call_id);
|
|||
PJ_DECL(pj_bool_t) pjsua_call_has_media(pjsua_call_id call_id);
|
||||
|
||||
|
||||
#if DISABLED_FOR_TICKET_1185
|
||||
/**
|
||||
* Retrieve the media session associated with this call. Note that the media
|
||||
* session may not be available depending on the current call's media status
|
||||
|
@ -3095,7 +3189,6 @@ PJ_DECL(pj_bool_t) pjsua_call_has_media(pjsua_call_id call_id);
|
|||
*/
|
||||
PJ_DECL(pjmedia_session*) pjsua_call_get_media_session(pjsua_call_id call_id);
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the media transport instance that is used for this call.
|
||||
* Application may use the media transport to query more detailed information
|
||||
|
@ -3106,7 +3199,7 @@ PJ_DECL(pjmedia_session*) pjsua_call_get_media_session(pjsua_call_id call_id);
|
|||
* @return Call media transport.
|
||||
*/
|
||||
PJ_DECL(pjmedia_transport*) pjsua_call_get_media_transport(pjsua_call_id cid);
|
||||
|
||||
#endif /* DISABLED_FOR_TICKET_1185 */
|
||||
|
||||
/**
|
||||
* Get the conference port identification associated with the call.
|
||||
|
@ -4882,9 +4975,7 @@ PJ_DECL(pj_status_t) pjsua_codec_get_param( const pj_str_t *codec_id,
|
|||
PJ_DECL(pj_status_t) pjsua_codec_set_param( const pj_str_t *codec_id,
|
||||
const pjmedia_codec_param *param);
|
||||
|
||||
|
||||
|
||||
|
||||
#if DISABLED_FOR_TICKET_1185
|
||||
/**
|
||||
* Create UDP media transports for all the calls. This function creates
|
||||
* one UDP media transport for each call.
|
||||
|
@ -4916,6 +5007,7 @@ PJ_DECL(pj_status_t)
|
|||
pjsua_media_transports_attach( pjsua_media_transport tp[],
|
||||
unsigned count,
|
||||
pj_bool_t auto_delete);
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -43,12 +43,65 @@ typedef enum pjsua_med_tp_st
|
|||
|
||||
} pjsua_med_tp_st;
|
||||
|
||||
/** Forward decl of pjsua call */
|
||||
typedef struct pjsua_call pjsua_call;
|
||||
|
||||
/**
|
||||
* Call's media stream.
|
||||
*/
|
||||
typedef struct pjsua_call_media
|
||||
{
|
||||
pjsua_call *call; /**< Parent call. */
|
||||
pjmedia_type type; /**< Media type. */
|
||||
unsigned idx; /**< This media index in parent call. */
|
||||
pjsua_call_media_status state; /**< Media state. */
|
||||
pjmedia_dir dir; /**< Media direction. */
|
||||
|
||||
/** The stream */
|
||||
union {
|
||||
/** Audio stream */
|
||||
struct {
|
||||
pjmedia_stream *stream; /**< The media session. */
|
||||
int conf_slot; /**< Slot # in conference bridge. */
|
||||
} a;
|
||||
|
||||
/** Video stream */
|
||||
struct {
|
||||
} v;
|
||||
|
||||
} strm;
|
||||
|
||||
pj_uint32_t ssrc; /**< RTP SSRC */
|
||||
pj_uint32_t rtp_tx_ts; /**< Initial RTP timestamp for sender. */
|
||||
pj_uint16_t rtp_tx_seq;/**< Initial RTP sequence for sender. */
|
||||
pj_uint8_t rtp_tx_seq_ts_set;
|
||||
/**< Bitmask flags if initial RTP sequence
|
||||
and/or timestamp for sender are set.
|
||||
bit 0/LSB : sequence flag
|
||||
bit 1 : timestamp flag */
|
||||
|
||||
pjmedia_transport *tp; /**< Current media transport (can be 0) */
|
||||
pj_status_t tp_ready; /**< Media transport status. */
|
||||
pjmedia_transport *tp_orig; /**< Original media transport */
|
||||
pj_bool_t tp_auto_del; /**< May delete media transport */
|
||||
pjsua_med_tp_st tp_st; /**< Media transport state */
|
||||
pj_sockaddr rtp_addr; /**< Current RTP source address
|
||||
(used to update ICE default
|
||||
address) */
|
||||
pjmedia_srtp_use rem_srtp_use; /**< Remote's SRTP usage policy. */
|
||||
} pjsua_call_media;
|
||||
|
||||
/**
|
||||
* Maximum number of SDP "m=" lines to be supported.
|
||||
*/
|
||||
#define PJSUA_MAX_CALL_MEDIA PJMEDIA_MAX_SDP_MEDIA
|
||||
|
||||
/**
|
||||
* Structure to be attached to invite dialog.
|
||||
* Given a dialog "dlg", application can retrieve this structure
|
||||
* by accessing dlg->mod_data[pjsua.mod.id].
|
||||
*/
|
||||
typedef struct pjsua_call
|
||||
struct pjsua_call
|
||||
{
|
||||
unsigned index; /**< Index in pjsua array. */
|
||||
pjsip_inv_session *inv; /**< The invite session. */
|
||||
|
@ -63,31 +116,14 @@ typedef struct pjsua_call
|
|||
int secure_level;/**< Signaling security level. */
|
||||
pjsua_call_hold_type call_hold_type; /**< How to do call hold. */
|
||||
pj_bool_t local_hold;/**< Flag for call-hold by local. */
|
||||
pjsua_call_media_status media_st;/**< Media state. */
|
||||
pjmedia_dir media_dir; /**< Media direction. */
|
||||
pjmedia_session *session; /**< The media session. */
|
||||
int audio_idx; /**< Index of m=audio in SDP. */
|
||||
pj_uint32_t ssrc; /**< RTP SSRC */
|
||||
pj_uint32_t rtp_tx_ts; /**< Initial RTP timestamp for sender. */
|
||||
pj_uint16_t rtp_tx_seq;/**< Initial RTP sequence for sender. */
|
||||
pj_uint8_t rtp_tx_seq_ts_set;
|
||||
/**< Bitmask flags if initial RTP sequence
|
||||
and/or timestamp for sender are set.
|
||||
bit 0/LSB : sequence flag
|
||||
bit 1 : timestamp flag */
|
||||
int conf_slot; /**< Slot # in conference bridge. */
|
||||
|
||||
unsigned med_cnt; /**< Number of media in SDP. */
|
||||
pjsua_call_media media[PJSUA_MAX_CALL_MEDIA]; /**< Array of media */
|
||||
unsigned audio_idx; /**< Selected audio media. */
|
||||
|
||||
pjsip_evsub *xfer_sub; /**< Xfer server subscription, if this
|
||||
call was triggered by xfer. */
|
||||
pjmedia_transport *med_tp; /**< Current media transport. */
|
||||
pj_status_t med_tp_ready;/**< Media transport status. */
|
||||
pjmedia_transport *med_orig; /**< Original media transport */
|
||||
pj_bool_t med_tp_auto_del; /**< May delete media transport */
|
||||
pjsua_med_tp_st med_tp_st; /**< Media transport state */
|
||||
pj_sockaddr med_rtp_addr; /**< Current RTP source address
|
||||
(used to update ICE default
|
||||
address) */
|
||||
pj_stun_nat_type rem_nat_type; /**< NAT type of remote endpoint. */
|
||||
pjmedia_srtp_use rem_srtp_use; /**< Remote's SRTP usage policy. */
|
||||
|
||||
char last_text_buf_[128]; /**< Buffer for last_text. */
|
||||
|
||||
|
@ -99,7 +135,7 @@ typedef struct pjsua_call
|
|||
} lock_codec; /**< Data for codec locking when answer
|
||||
contains multiple codecs. */
|
||||
|
||||
} pjsua_call;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
|
@ -270,6 +306,7 @@ struct pjsua_data
|
|||
pj_caching_pool cp; /**< Global pool factory. */
|
||||
pj_pool_t *pool; /**< pjsua's private pool. */
|
||||
pj_mutex_t *mutex; /**< Mutex protection for this data */
|
||||
pjsua_state state; /**< Library state. */
|
||||
|
||||
/* Logging: */
|
||||
pjsua_logging_config log_cfg; /**< Current logging config. */
|
||||
|
@ -402,6 +439,9 @@ PJ_INLINE(pjsua_im_data*) pjsua_im_data_dup(pj_pool_t *pool,
|
|||
#define PJSUA_UNLOCK()
|
||||
#endif
|
||||
|
||||
/* Core */
|
||||
void pjsua_set_state(pjsua_state new_state);
|
||||
|
||||
/******
|
||||
* STUN resolution
|
||||
*/
|
||||
|
|
|
@ -118,7 +118,8 @@ PJ_DEF(void) pjsua_acc_config_dup( pj_pool_t *pool,
|
|||
|
||||
pjsip_auth_clt_pref_dup(pool, &dst->auth_pref, &src->auth_pref);
|
||||
|
||||
dst->ka_interval = src->ka_interval;
|
||||
pjsua_transport_config_dup(pool, &dst->rtp_cfg, &src->rtp_cfg);
|
||||
|
||||
pj_strdup(pool, &dst->ka_data, &src->ka_data);
|
||||
}
|
||||
|
||||
|
|
|
@ -101,29 +101,19 @@ static void xfer_server_on_evsub_state( pjsip_evsub *sub, pjsip_event *event);
|
|||
static void reset_call(pjsua_call_id id)
|
||||
{
|
||||
pjsua_call *call = &pjsua_var.calls[id];
|
||||
unsigned i;
|
||||
|
||||
pj_bzero(call, sizeof(*call));
|
||||
call->index = id;
|
||||
call->inv = NULL;
|
||||
call->user_data = NULL;
|
||||
call->session = NULL;
|
||||
call->audio_idx = -1;
|
||||
call->ssrc = pj_rand();
|
||||
call->rtp_tx_seq = 0;
|
||||
call->rtp_tx_ts = 0;
|
||||
call->rtp_tx_seq_ts_set = 0;
|
||||
call->xfer_sub = NULL;
|
||||
call->last_code = (pjsip_status_code) 0;
|
||||
call->conf_slot = PJSUA_INVALID_ID;
|
||||
call->last_text.ptr = call->last_text_buf_;
|
||||
call->last_text.slen = 0;
|
||||
call->conn_time.sec = 0;
|
||||
call->conn_time.msec = 0;
|
||||
call->res_time.sec = 0;
|
||||
call->res_time.msec = 0;
|
||||
call->rem_nat_type = PJ_STUN_NAT_TYPE_UNKNOWN;
|
||||
call->rem_srtp_use = PJMEDIA_SRTP_DISABLED;
|
||||
call->local_hold = PJ_FALSE;
|
||||
pj_bzero(&call->lock_codec, sizeof(call->lock_codec));
|
||||
for (i=0; i<PJ_ARRAY_SIZE(call->media); ++i) {
|
||||
pjsua_call_media *call_med = &call->media[i];
|
||||
call_med->ssrc = pj_rand();
|
||||
call_med->strm.a.conf_slot = PJSUA_INVALID_ID;
|
||||
call_med->call = call;
|
||||
call_med->idx = i;
|
||||
call_med->tp_auto_del = PJ_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -823,7 +813,8 @@ pj_bool_t pjsua_call_on_incoming(pjsip_rx_data *rdata)
|
|||
/* Init media channel */
|
||||
status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAS,
|
||||
call->secure_level,
|
||||
rdata->tp_info.pool, offer,
|
||||
rdata->tp_info.pool,
|
||||
offer,
|
||||
&sip_err_code);
|
||||
if (status != PJ_SUCCESS) {
|
||||
pjsua_perror(THIS_FILE, "Error initializing media channel", status);
|
||||
|
@ -1118,12 +1109,14 @@ PJ_DEF(pj_bool_t) pjsua_call_is_active(pjsua_call_id call_id)
|
|||
*/
|
||||
PJ_DEF(pj_bool_t) pjsua_call_has_media(pjsua_call_id call_id)
|
||||
{
|
||||
pjsua_call *call = &pjsua_var.calls[call_id];
|
||||
PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
|
||||
PJ_EINVAL);
|
||||
return pjsua_var.calls[call_id].session != NULL;
|
||||
return call->audio_idx >= 0 && call->media[call->audio_idx].strm.a.stream;
|
||||
}
|
||||
|
||||
|
||||
#if DISABLED_FOR_TICKET_1185
|
||||
/*
|
||||
* Retrieve the media session associated with this call.
|
||||
*/
|
||||
|
@ -1142,9 +1135,9 @@ PJ_DEF(pjmedia_transport*) pjsua_call_get_media_transport(pjsua_call_id cid)
|
|||
{
|
||||
PJ_ASSERT_RETURN(cid>=0 && cid<(int)pjsua_var.ua_cfg.max_calls,
|
||||
NULL);
|
||||
return pjsua_var.calls[cid].med_tp;
|
||||
return pjsua_var.calls[cid].tp;
|
||||
}
|
||||
|
||||
#endif /* Removed in 2.0 */
|
||||
|
||||
/* Acquire lock to the specified call_id */
|
||||
pj_status_t acquire_call(const char *title,
|
||||
|
@ -1238,7 +1231,7 @@ PJ_DEF(pjsua_conf_port_id) pjsua_call_get_conf_port(pjsua_call_id call_id)
|
|||
if (status != PJ_SUCCESS)
|
||||
return PJSUA_INVALID_ID;
|
||||
|
||||
port_id = call->conf_slot;
|
||||
port_id = call->media[call->audio_idx].strm.a.conf_slot;
|
||||
|
||||
pjsip_dlg_dec_lock(dlg);
|
||||
|
||||
|
@ -1255,6 +1248,7 @@ PJ_DEF(pj_status_t) pjsua_call_get_info( pjsua_call_id call_id,
|
|||
{
|
||||
pjsua_call *call;
|
||||
pjsip_dialog *dlg;
|
||||
unsigned mi;
|
||||
pj_status_t status;
|
||||
|
||||
PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,
|
||||
|
@ -1329,13 +1323,28 @@ PJ_DEF(pj_status_t) pjsua_call_get_info( pjsua_call_id call_id,
|
|||
sizeof(info->buf_.last_status_text));
|
||||
}
|
||||
|
||||
/* media status and dir */
|
||||
info->media_status = call->media_st;
|
||||
info->media_dir = call->media_dir;
|
||||
/* Build array of media status and dir */
|
||||
info->audio_cnt = 0;
|
||||
for (mi=0; mi < call->med_cnt &&
|
||||
info->audio_cnt < PJ_ARRAY_SIZE(info->audio); ++mi)
|
||||
{
|
||||
pjsua_call_media *call_med = &call->media[mi];
|
||||
if (call_med->type != PJMEDIA_TYPE_AUDIO)
|
||||
continue;
|
||||
info->audio[info->audio_cnt].index = mi;
|
||||
info->audio[info->audio_cnt].media_status = call_med->state;
|
||||
info->audio[info->audio_cnt].media_dir = call_med->dir;
|
||||
info->audio[info->audio_cnt].conf_slot = call_med->strm.a.conf_slot;
|
||||
++info->audio_cnt;
|
||||
}
|
||||
|
||||
if (info->audio_cnt) {
|
||||
info->media_status = info->audio[0].media_status;
|
||||
info->media_dir = info->audio[0].media_dir;
|
||||
}
|
||||
|
||||
/* conference slot number */
|
||||
info->conf_slot = call->conf_slot;
|
||||
info->conf_slot = call->media[call->audio_idx].strm.a.conf_slot;
|
||||
|
||||
/* calculate duration */
|
||||
if (info->state >= PJSIP_INV_STATE_DISCONNECTED) {
|
||||
|
@ -1959,13 +1968,14 @@ PJ_DEF(pj_status_t) pjsua_call_dial_dtmf( pjsua_call_id call_id,
|
|||
if (status != PJ_SUCCESS)
|
||||
return status;
|
||||
|
||||
if (!call->session) {
|
||||
if (!pjsua_call_has_media(call_id)) {
|
||||
PJ_LOG(3,(THIS_FILE, "Media is not established yet!"));
|
||||
pjsip_dlg_dec_lock(dlg);
|
||||
return PJ_EINVALIDOP;
|
||||
}
|
||||
|
||||
status = pjmedia_session_dial_dtmf( call->session, 0, digits);
|
||||
status = pjmedia_stream_dial_dtmf(
|
||||
call->media[call->audio_idx].strm.a.stream, digits);
|
||||
|
||||
pjsip_dlg_dec_lock(dlg);
|
||||
|
||||
|
@ -2190,16 +2200,12 @@ static void dump_media_session(const char *indent,
|
|||
unsigned i;
|
||||
char *p = buf, *end = buf+maxlen;
|
||||
int len;
|
||||
pjmedia_session_info info;
|
||||
pjmedia_session *session = call->session;
|
||||
pjmedia_transport_info tp_info;
|
||||
|
||||
pjmedia_transport_info_init(&tp_info);
|
||||
|
||||
pjmedia_transport_get_info(call->med_tp, &tp_info);
|
||||
pjmedia_session_get_info(session, &info);
|
||||
|
||||
for (i=0; i<info.stream_cnt; ++i) {
|
||||
for (i=0; i<call->med_cnt; ++i) {
|
||||
pjsua_call_media *call_med = &call->media[i];
|
||||
pjmedia_stream_info info;
|
||||
pjmedia_stream *stream = call_med->strm.a.stream;
|
||||
pjmedia_transport_info tp_info;
|
||||
pjmedia_rtcp_stat stat;
|
||||
char rem_addr_buf[80];
|
||||
const char *rem_addr;
|
||||
|
@ -2208,7 +2214,42 @@ static void dump_media_session(const char *indent,
|
|||
char packets[32], bytes[32], ipbytes[32], avg_bps[32], avg_ipbps[32];
|
||||
pj_time_val media_duration, now;
|
||||
|
||||
pjmedia_session_get_stream_stat(session, i, &stat);
|
||||
/* Check if the stream is deactivated */
|
||||
if (call_med->tp == NULL || stream == NULL) {
|
||||
const char *media_type_str;
|
||||
|
||||
switch (call_med->type) {
|
||||
case PJMEDIA_TYPE_AUDIO:
|
||||
media_type_str = "audio";
|
||||
break;
|
||||
case PJMEDIA_TYPE_VIDEO:
|
||||
media_type_str = "video";
|
||||
break;
|
||||
case PJMEDIA_TYPE_APPLICATION:
|
||||
media_type_str = "application";
|
||||
break;
|
||||
default:
|
||||
media_type_str = "unknown";
|
||||
break;
|
||||
}
|
||||
len = pj_ansi_snprintf(p, end-p,
|
||||
"%s #%d m=%s deactivated\n",
|
||||
indent, i, media_type_str);
|
||||
if (len < 1 || len > end-p) {
|
||||
*p = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
p += len;
|
||||
continue;
|
||||
}
|
||||
|
||||
pjmedia_transport_info_init(&tp_info);
|
||||
pjmedia_transport_get_info(call_med->tp, &tp_info);
|
||||
|
||||
pjmedia_stream_get_info(stream, &info);
|
||||
pjmedia_stream_get_stat(stream, &stat);
|
||||
|
||||
// rem_addr will contain actual address of RTP originator, instead of
|
||||
// remote RTP address specified by stream which is fetched from the SDP.
|
||||
// Please note that we are assuming only one stream per call.
|
||||
|
@ -2222,27 +2263,27 @@ static void dump_media_session(const char *indent,
|
|||
rem_addr = rem_addr_buf;
|
||||
}
|
||||
|
||||
if (call->media_dir == PJMEDIA_DIR_NONE) {
|
||||
if (call_med->dir == PJMEDIA_DIR_NONE) {
|
||||
/* To handle when the stream that is currently being paused
|
||||
* (http://trac.pjsip.org/repos/ticket/1079)
|
||||
*/
|
||||
dir = "inactive";
|
||||
} else if (info.stream_info[i].dir == PJMEDIA_DIR_ENCODING)
|
||||
} else if (info.dir == PJMEDIA_DIR_ENCODING)
|
||||
dir = "sendonly";
|
||||
else if (info.stream_info[i].dir == PJMEDIA_DIR_DECODING)
|
||||
else if (info.dir == PJMEDIA_DIR_DECODING)
|
||||
dir = "recvonly";
|
||||
else if (info.stream_info[i].dir == PJMEDIA_DIR_ENCODING_DECODING)
|
||||
else if (info.dir == PJMEDIA_DIR_ENCODING_DECODING)
|
||||
dir = "sendrecv";
|
||||
else
|
||||
dir = "inactive";
|
||||
|
||||
|
||||
len = pj_ansi_snprintf(buf, end-p,
|
||||
len = pj_ansi_snprintf(p, end-p,
|
||||
"%s #%d %.*s @%dKHz, %s, peer=%s",
|
||||
indent, i,
|
||||
(int)info.stream_info[i].fmt.encoding_name.slen,
|
||||
info.stream_info[i].fmt.encoding_name.ptr,
|
||||
info.stream_info[i].fmt.clock_rate / 1000,
|
||||
(int)info.fmt.encoding_name.slen,
|
||||
info.fmt.encoding_name.ptr,
|
||||
info.fmt.clock_rate / 1000,
|
||||
dir,
|
||||
rem_addr);
|
||||
if (len < 1 || len > end-p) {
|
||||
|
@ -2293,7 +2334,7 @@ static void dump_media_session(const char *indent,
|
|||
"%s IPDV : %7.3f %7.3f %7.3f %7.3f %7.3f"
|
||||
#endif
|
||||
"%s",
|
||||
indent, info.stream_info[i].fmt.pt,
|
||||
indent, info.fmt.pt,
|
||||
last_update,
|
||||
indent,
|
||||
good_number(packets, stat.rx.pkt),
|
||||
|
@ -2370,9 +2411,8 @@ static void dump_media_session(const char *indent,
|
|||
"%s loss period: %7.3f %7.3f %7.3f %7.3f %7.3f\n"
|
||||
"%s jitter : %7.3f %7.3f %7.3f %7.3f %7.3f%s",
|
||||
indent,
|
||||
info.stream_info[i].tx_pt,
|
||||
info.stream_info[i].param->info.frm_ptime *
|
||||
info.stream_info[i].param->setting.frm_per_pkt,
|
||||
info.tx_pt,
|
||||
info.param->info.frm_ptime * info.param->setting.frm_per_pkt,
|
||||
last_update,
|
||||
|
||||
indent,
|
||||
|
@ -2415,7 +2455,7 @@ static void dump_media_session(const char *indent,
|
|||
*p = '\0';
|
||||
|
||||
len = pj_ansi_snprintf(p, end-p,
|
||||
"%s RTT msec : %7.3f %7.3f %7.3f %7.3f %7.3f",
|
||||
"%s RTT msec : %7.3f %7.3f %7.3f %7.3f %7.3f",
|
||||
indent,
|
||||
stat.rtt.min / 1000.0,
|
||||
stat.rtt.mean / 1000.0,
|
||||
|
@ -2470,7 +2510,7 @@ static void dump_media_session(const char *indent,
|
|||
break;
|
||||
}
|
||||
|
||||
clock_rate = info.stream_info[i].fmt.clock_rate;
|
||||
clock_rate = info.fmt.clock_rate;
|
||||
|
||||
len = pj_ansi_snprintf(p, end-p, "\n%s Extended reports:", indent);
|
||||
VALIDATE_PRINT_BUF();
|
||||
|
@ -2943,8 +2983,9 @@ PJ_DEF(pj_status_t) pjsua_call_dump( pjsua_call_id call_id,
|
|||
}
|
||||
|
||||
/* Get and ICE SRTP status */
|
||||
#if DISABLED_FOR_TICKET_1185
|
||||
pjmedia_transport_info_init(&tp_info);
|
||||
pjmedia_transport_get_info(call->med_tp, &tp_info);
|
||||
pjmedia_transport_get_info(call->tp, &tp_info);
|
||||
if (tp_info.specific_info_cnt > 0) {
|
||||
unsigned i;
|
||||
for (i = 0; i < tp_info.specific_info_cnt; ++i) {
|
||||
|
@ -2983,9 +3024,10 @@ PJ_DEF(pj_status_t) pjsua_call_dump( pjsua_call_id call_id,
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif /* DISABLED_FOR_TICKET_1185 */
|
||||
|
||||
/* Dump session statistics */
|
||||
if (with_media && call->session)
|
||||
if (with_media && pjsua_call_has_media(call_id))
|
||||
dump_media_session(indent, p, end-p, call);
|
||||
|
||||
pjsip_dlg_dec_lock(dlg);
|
||||
|
@ -3063,6 +3105,7 @@ static pj_status_t perform_lock_codec(pjsua_call *call)
|
|||
const pjmedia_sdp_session *local_sdp = NULL, *new_sdp;
|
||||
const pjmedia_sdp_media *ref_m;
|
||||
pjmedia_sdp_media *m;
|
||||
pjsua_call_media *call_med = &call->media[call->audio_idx];
|
||||
unsigned i, codec_cnt = 0;
|
||||
pj_bool_t rem_can_update;
|
||||
pjsip_tx_data *tdata;
|
||||
|
@ -3097,9 +3140,9 @@ static pj_status_t perform_lock_codec(pjsua_call *call)
|
|||
return PJMEDIA_SDP_EINVER;
|
||||
|
||||
/* Verify if media is deactivated */
|
||||
if (call->media_st == PJSUA_CALL_MEDIA_NONE ||
|
||||
call->media_st == PJSUA_CALL_MEDIA_ERROR ||
|
||||
call->media_dir == PJMEDIA_DIR_NONE)
|
||||
if (call_med->state == PJSUA_CALL_MEDIA_NONE ||
|
||||
call_med->state == PJSUA_CALL_MEDIA_ERROR ||
|
||||
call_med->dir == PJMEDIA_DIR_NONE)
|
||||
{
|
||||
return PJ_EINVALIDOP;
|
||||
}
|
||||
|
@ -3189,6 +3232,7 @@ static pj_status_t lock_codec(pjsua_call *call)
|
|||
const pjmedia_sdp_session *local_sdp, *remote_sdp;
|
||||
const pjmedia_sdp_media *rem_m, *loc_m;
|
||||
unsigned codec_cnt=0, i;
|
||||
pjsua_call_media *call_med = &call->media[call->audio_idx];
|
||||
pj_time_val delay = {0, 0};
|
||||
const pj_str_t st_update = {"UPDATE", 6};
|
||||
pj_status_t status;
|
||||
|
@ -3206,9 +3250,9 @@ static pj_status_t lock_codec(pjsua_call *call)
|
|||
}
|
||||
|
||||
/* Skip this if the media is inactive or error */
|
||||
if (call->media_st == PJSUA_CALL_MEDIA_NONE ||
|
||||
call->media_st == PJSUA_CALL_MEDIA_ERROR ||
|
||||
call->media_dir == PJMEDIA_DIR_NONE)
|
||||
if (call_med->state == PJSUA_CALL_MEDIA_NONE ||
|
||||
call_med->state == PJSUA_CALL_MEDIA_ERROR ||
|
||||
call_med->dir == PJMEDIA_DIR_NONE)
|
||||
{
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
@ -3524,7 +3568,8 @@ static void call_disconnect( pjsip_inv_session *inv,
|
|||
return;
|
||||
|
||||
/* Add SDP in 488 status */
|
||||
if (call && call->med_tp && tdata->msg->type==PJSIP_RESPONSE_MSG &&
|
||||
#if DISABLED_FOR_TICKET_1185
|
||||
if (call && call->tp && tdata->msg->type==PJSIP_RESPONSE_MSG &&
|
||||
code==PJSIP_SC_NOT_ACCEPTABLE_HERE)
|
||||
{
|
||||
pjmedia_sdp_session *local_sdp;
|
||||
|
@ -3539,6 +3584,7 @@ static void call_disconnect( pjsip_inv_session *inv,
|
|||
&tdata->msg->body);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
pjsip_inv_send_msg(inv, tdata);
|
||||
}
|
||||
|
@ -3654,7 +3700,7 @@ static pj_status_t modify_sdp_of_call_hold(pjsua_call *call,
|
|||
* (See RFC 3264 Section 8.4 and RFC 4317 Section 3.1)
|
||||
*/
|
||||
/* http://trac.pjsip.org/repos/ticket/880
|
||||
if (call->media_dir != PJMEDIA_DIR_ENCODING) {
|
||||
if (call->dir != PJMEDIA_DIR_ENCODING) {
|
||||
*/
|
||||
/* https://trac.pjsip.org/repos/ticket/1142:
|
||||
* configuration to use c=0.0.0.0 for call hold.
|
||||
|
@ -3694,7 +3740,7 @@ static pj_status_t modify_sdp_of_call_hold(pjsua_call *call,
|
|||
pjmedia_sdp_media_remove_all_attr(m, "recvonly");
|
||||
pjmedia_sdp_media_remove_all_attr(m, "inactive");
|
||||
|
||||
if (call->media_dir & PJMEDIA_DIR_ENCODING) {
|
||||
if (call->media[call->audio_idx].dir & PJMEDIA_DIR_ENCODING) {
|
||||
/* Add sendonly attribute */
|
||||
attr = pjmedia_sdp_attr_create(pool, "sendonly", NULL);
|
||||
pjmedia_sdp_media_add_attr(m, attr);
|
||||
|
|
|
@ -103,10 +103,8 @@ PJ_DEF(void) pjsua_config_default(pjsua_config *cfg)
|
|||
cfg->stun_ignore_failure = PJ_TRUE;
|
||||
cfg->force_lr = PJ_TRUE;
|
||||
cfg->enable_unsolicited_mwi = PJ_TRUE;
|
||||
#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
|
||||
cfg->use_srtp = PJSUA_DEFAULT_USE_SRTP;
|
||||
cfg->srtp_secure_signaling = PJSUA_DEFAULT_SRTP_SECURE_SIGNALING;
|
||||
#endif
|
||||
cfg->hangup_forked_call = PJ_TRUE;
|
||||
|
||||
cfg->use_timer = PJSUA_SIP_TIMER_OPTIONAL;
|
||||
|
@ -176,11 +174,11 @@ PJ_DEF(void) pjsua_acc_config_default(pjsua_acc_config *cfg)
|
|||
cfg->timer_setting = pjsua_var.ua_cfg.timer_setting;
|
||||
cfg->ka_interval = 15;
|
||||
cfg->ka_data = pj_str("\r\n");
|
||||
#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
|
||||
cfg->max_audio_cnt = 1;
|
||||
pjsua_transport_config_default(&cfg->rtp_cfg);
|
||||
cfg->use_srtp = pjsua_var.ua_cfg.use_srtp;
|
||||
cfg->srtp_secure_signaling = pjsua_var.ua_cfg.srtp_secure_signaling;
|
||||
cfg->srtp_optional_dup_offer = pjsua_var.ua_cfg.srtp_optional_dup_offer;
|
||||
#endif
|
||||
cfg->reg_retry_interval = PJSUA_REG_RETRY_INTERVAL;
|
||||
cfg->contact_rewrite_method = PJSUA_CONTACT_REWRITE_METHOD;
|
||||
cfg->use_rfc5626 = PJ_TRUE;
|
||||
|
@ -223,7 +221,6 @@ PJ_DEF(void) pjsua_media_config_default(pjsua_media_config *cfg)
|
|||
cfg->turn_conn_type = PJ_TURN_TP_UDP;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* This is a very simple PJSIP module, whose sole purpose is to display
|
||||
* incoming and outgoing messages to log. This module will have priority
|
||||
|
@ -378,6 +375,7 @@ static pj_bool_t options_on_rx_request(pjsip_rx_data *rdata)
|
|||
}
|
||||
|
||||
/* Get media socket info, make sure transport is ready */
|
||||
#if DISABLED_FOR_TICKET_1185
|
||||
if (pjsua_var.calls[0].med_tp) {
|
||||
pjmedia_transport_info_init(&tpinfo);
|
||||
pjmedia_transport_get_info(pjsua_var.calls[0].med_tp, &tpinfo);
|
||||
|
@ -389,8 +387,9 @@ static pj_bool_t options_on_rx_request(pjsip_rx_data *rdata)
|
|||
pjsip_create_sdp_body(tdata->pool, sdp, &tdata->msg->body);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Send response statelessly */
|
||||
/* Send response */
|
||||
pjsip_get_response_addr(tdata->pool, rdata, &res_addr);
|
||||
status = pjsip_endpt_send_response(pjsua_var.endpt, &res_addr, tdata, NULL, NULL);
|
||||
if (status != PJ_SUCCESS)
|
||||
|
@ -659,6 +658,7 @@ PJ_DEF(pj_status_t) pjsua_create(void)
|
|||
&pjsua_var.endpt);
|
||||
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
|
||||
|
||||
pjsua_set_state(PJSUA_STATE_CREATED);
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
@ -918,6 +918,8 @@ PJ_DEF(pj_status_t) pjsua_init( const pjsua_config *ua_cfg,
|
|||
PJ_LOG(3,(THIS_FILE, "pjsua version %s for %s initialized",
|
||||
pj_get_version(), PJ_OS_NAME));
|
||||
|
||||
pjsua_set_state(PJSUA_STATE_INIT);
|
||||
|
||||
return PJ_SUCCESS;
|
||||
|
||||
on_error:
|
||||
|
@ -1275,6 +1277,12 @@ PJ_DEF(pj_status_t) pjsua_destroy(void)
|
|||
{
|
||||
int i; /* Must be signed */
|
||||
|
||||
if (pjsua_var.state > PJSUA_STATE_NULL &&
|
||||
pjsua_var.state < PJSUA_STATE_CLOSING)
|
||||
{
|
||||
pjsua_set_state(PJSUA_STATE_CLOSING);
|
||||
}
|
||||
|
||||
/* Signal threads to quit: */
|
||||
pjsua_var.thread_quit_flag = 1;
|
||||
|
||||
|
@ -1452,10 +1460,34 @@ PJ_DEF(pj_status_t) pjsua_destroy(void)
|
|||
/* Clear pjsua_var */
|
||||
pj_bzero(&pjsua_var, sizeof(pjsua_var));
|
||||
|
||||
pjsua_set_state(PJSUA_STATE_NULL);
|
||||
|
||||
/* Done. */
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
void pjsua_set_state(pjsua_state new_state)
|
||||
{
|
||||
const char *state_name[] = {
|
||||
"NULL",
|
||||
"CREATED",
|
||||
"INIT",
|
||||
"STARTING",
|
||||
"RUNNING",
|
||||
"CLOSING"
|
||||
};
|
||||
pjsua_state old_state = pjsua_var.state;
|
||||
|
||||
pjsua_var.state = new_state;
|
||||
PJ_LOG(4,(THIS_FILE, "PJSUA state changed: %s --> %s",
|
||||
state_name[old_state], state_name[new_state]));
|
||||
}
|
||||
|
||||
/* Get state */
|
||||
PJ_DEF(pjsua_state) pjsua_get_state(void)
|
||||
{
|
||||
return pjsua_var.state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Application is recommended to call this function after all initialization
|
||||
|
@ -1468,6 +1500,8 @@ PJ_DEF(pj_status_t) pjsua_start(void)
|
|||
{
|
||||
pj_status_t status;
|
||||
|
||||
pjsua_set_state(PJSUA_STATE_STARTING);
|
||||
|
||||
status = pjsua_call_subsys_start();
|
||||
if (status != PJ_SUCCESS)
|
||||
return status;
|
||||
|
@ -1480,6 +1514,8 @@ PJ_DEF(pj_status_t) pjsua_start(void)
|
|||
if (status != PJ_SUCCESS)
|
||||
return status;
|
||||
|
||||
pjsua_set_state(PJSUA_STATE_RUNNING);
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -2563,6 +2599,7 @@ PJ_DEF(void) pjsua_dump(pj_bool_t detail)
|
|||
pjmedia_endpt_dump(pjsua_get_pjmedia_endpt());
|
||||
|
||||
PJ_LOG(3,(THIS_FILE, "Dumping media transports:"));
|
||||
#if DISABLED_FOR_TICKET_1185
|
||||
for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) {
|
||||
pjsua_call *call = &pjsua_var.calls[i];
|
||||
pjmedia_transport_info tpinfo;
|
||||
|
@ -2579,6 +2616,7 @@ PJ_DEF(void) pjsua_dump(pj_bool_t detail)
|
|||
pj_sockaddr_print(&tpinfo.sock_info.rtp_addr_name, addr_buf,
|
||||
sizeof(addr_buf), 3)));
|
||||
}
|
||||
#endif
|
||||
|
||||
pjsip_tsx_layer_dump(detail);
|
||||
pjsip_ua_dump(detail);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue