Commit a8865b89 authored by jehan's avatar jehan

add support of multicast ip

parent fa00ae8c
......@@ -259,7 +259,7 @@ MS2_PUBLIC void media_stream_iterate(MediaStream * stream);
MS2_PUBLIC bool_t media_stream_alive(MediaStream *stream, int timeout_seconds);
/**
* @return curret streams tate
* @return current streams state
* */
MS2_PUBLIC MSStreamState media_stream_get_state(const MediaStream *stream);
......@@ -275,6 +275,8 @@ typedef enum EqualizerLocation {
MSEqualizerMic
} EqualizerLocation;
struct _AudioStream
{
MediaStream ms;
......@@ -387,6 +389,16 @@ MS2_PUBLIC void audio_stream_play_received_dtmfs(AudioStream *st, bool_t yesno);
**/
MS2_PUBLIC AudioStream *audio_stream_new(int loc_rtp_port, int loc_rtcp_port, bool_t ipv6);
/**
* Creates an AudioStream object listening on a RTP port for a dedicated address.
* @param loc_ip the local ip to listen for RTP packets. Can be ::, O.O.O.O or any ip4/6 addresses
* @param loc_rtp_port the local UDP port to listen for RTP packets.
* @param loc_rtcp_port the local UDP port to listen for RTCP packets
* @return a new AudioStream.
**/
MS2_PUBLIC AudioStream *audio_stream_new2(const char* ip, int loc_rtp_port, int loc_rtcp_port);
/**Creates an AudioStream object from initialized MSMediaStreamSessions.
* @param sessions the MSMediaStreamSessions
* @return a new AudioStream
......@@ -644,6 +656,15 @@ typedef struct _VideoStream VideoStream;
MS2_PUBLIC VideoStream *video_stream_new(int loc_rtp_port, int loc_rtcp_port, bool_t use_ipv6);
/**
* Creates an VideoStream object listening on a RTP port for a dedicated address.
* @param loc_ip the local ip to listen for RTP packets. Can be ::, O.O.O.O or any ip4/6 addresses
* @param [in] loc_rtp_port the local UDP port to listen for RTP packets.
* @param [in] loc_rtcp_port the local UDP port to listen for RTCP packets
* @return a new AudioStream.
**/
MS2_PUBLIC VideoStream *video_stream_new2(const char* ip, int loc_rtp_port, int loc_rtcp_port);
MS2_PUBLIC VideoStream *video_stream_new_with_sessions(const MSMediaStreamSessions *sessions);
MS2_PUBLIC void video_stream_set_direction(VideoStream *vs, VideoStreamDir dir);
static MS2_INLINE void video_stream_enable_adaptive_bitrate_control(VideoStream *stream, bool_t enabled) {
......@@ -859,7 +880,7 @@ MS2_PUBLIC MSFilter* video_preview_stop_reuse_source(VideoPreview *stream);
* @}
**/
MS2_PUBLIC bool_t ms_is_ipv6(const char *address);
#ifdef __cplusplus
......
......@@ -287,6 +287,19 @@ MS2_PUBLIC unsigned int ms_get_cpu_count(void);
*/
MS2_PUBLIC void ms_sound_device_description_add(const char *manufacturer, const char *model, const char *platform, unsigned int flags, int delay, int recommended_rate);
/**
* @return TRUE if address is ipv6
*/
MS2_PUBLIC bool_t ms_is_ipv6(const char *address);
/**
* @return TRUE if address is multicast
*/
bool_t ms_is_multicast_addr(const struct sockaddr *address);
/**
* @return TRUE if address is multicast
*/
MS2_PUBLIC bool_t ms_is_multicast(const char *address);
/** @} */
#ifdef __cplusplus
......
......@@ -60,7 +60,10 @@ static void send_stun_packet(RtpSession *s)
mblk_t *mp;
char buf[STUN_MAX_MESSAGE_SIZE];
int len = STUN_MAX_MESSAGE_SIZE;
if (ms_is_multicast_addr((const struct sockaddr *)&s->rtcp.gs.loc_addr)) {
ms_debug("Stun packet not sent for session [%p] because of multicast",s);
return;
}
memset(&msg, 0, sizeof(StunMessage));
stunBuildReqSimple(&msg, NULL, FALSE, FALSE, 1);
len = stunEncodeMessage(&msg, buf, len, NULL);
......
......@@ -1144,14 +1144,17 @@ AudioStream *audio_stream_new_with_sessions(const MSMediaStreamSessions *session
}
AudioStream *audio_stream_new(int loc_rtp_port, int loc_rtcp_port, bool_t ipv6){
return audio_stream_new2( ipv6 ? "::" : "0.0.0.0", loc_rtp_port, loc_rtcp_port);
}
AudioStream *audio_stream_new2(const char* ip, int loc_rtp_port, int loc_rtcp_port) {
AudioStream *obj;
MSMediaStreamSessions sessions={0};
sessions.rtp_session=create_duplex_rtpsession(loc_rtp_port,loc_rtcp_port,ipv6);
sessions.rtp_session=create_duplex_rtpsession(ip,loc_rtp_port,loc_rtcp_port);
obj=audio_stream_new_with_sessions(&sessions);
obj->ms.owns_sessions=TRUE;
return obj;
}
void audio_stream_play_received_dtmfs(AudioStream *st, bool_t yesno){
st->play_dtmfs=yesno;
}
......
......@@ -135,7 +135,7 @@ MSTickerPrio __ms_get_default_prio(bool_t is_video) {
#endif
}
RtpSession * create_duplex_rtpsession(int loc_rtp_port, int loc_rtcp_port, bool_t ipv6) {
RtpSession * create_duplex_rtpsession(const char* local_ip, int loc_rtp_port, int loc_rtcp_port) {
RtpSession *rtpr;
rtpr = rtp_session_new(RTP_SESSION_SENDRECV);
......@@ -144,11 +144,12 @@ RtpSession * create_duplex_rtpsession(int loc_rtp_port, int loc_rtcp_port, bool_
rtp_session_set_blocking_mode(rtpr, 0);
rtp_session_enable_adaptive_jitter_compensation(rtpr, TRUE);
rtp_session_set_symmetric_rtp(rtpr, TRUE);
rtp_session_set_local_addr(rtpr, ipv6 ? "::" : "0.0.0.0", loc_rtp_port, loc_rtcp_port);
rtp_session_set_local_addr(rtpr, local_ip, loc_rtp_port, loc_rtcp_port);
rtp_session_signal_connect(rtpr, "timestamp_jump", (RtpCallback)rtp_session_resync, NULL);
rtp_session_signal_connect(rtpr, "ssrc_changed", (RtpCallback)rtp_session_resync, NULL);
rtp_session_set_ssrc_changed_threshold(rtpr, 0);
rtp_session_set_rtcp_report_interval(rtpr, 2500); /* At the beginning of the session send more reports. */
rtp_session_set_multicast_loopback(rtpr,TRUE); /*very useful, specially for testing purposes*/
disable_checksums(rtp_session_get_rtp_socket(rtpr));
return rtpr;
}
......@@ -275,6 +276,37 @@ bool_t ms_is_ipv6(const char *remote) {
return ret;
}
bool_t ms_is_multicast_addr(const struct sockaddr *addr) {
switch (addr->sa_family) {
case AF_INET:
return IN_MULTICAST(ntohl(((struct sockaddr_in *) addr)->sin_addr.s_addr));
case AF_INET6:
return IN6_IS_ADDR_MULTICAST(&(((struct sockaddr_in6 *) addr)->sin6_addr));
default:
return FALSE;
}
}
bool_t ms_is_multicast(const char *address) {
bool_t ret = FALSE;
struct addrinfo hints, *res0;
int err;
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
err = getaddrinfo(address,"8000", &hints, &res0);
if (err != 0) {
ms_warning("get_local_addr_for: %s", gai_strerror(err));
return FALSE;
}
ret = ms_is_multicast_addr(res0->ai_addr);
freeaddrinfo(res0);
return ret;
}
bool_t mediastream_payload_type_changed(RtpSession *session, unsigned long data) {
MediaStream *stream = (MediaStream *)data;
int pt = rtp_session_get_recv_payload_type(stream->sessions.rtp_session);
......
......@@ -48,7 +48,7 @@ extern "C"
MSTickerPrio __ms_get_default_prio(bool_t is_video);
MEDIASTREAMER2_INTERNAL_EXPORT RtpSession * create_duplex_rtpsession(int loc_rtp_port, int loc_rtcp_port, bool_t ipv6);
MEDIASTREAMER2_INTERNAL_EXPORT RtpSession * create_duplex_rtpsession(const char* local_ip,int loc_rtp_port, int loc_rtcp_port);
void media_stream_start_ticker(MediaStream *stream);
......
......@@ -232,9 +232,13 @@ static float video_stream_get_rtcp_xr_average_lq_quality_rating(unsigned long us
VideoStream *video_stream_new(int loc_rtp_port, int loc_rtcp_port, bool_t use_ipv6){
return video_stream_new2( use_ipv6 ? "::" : "0.0.0.0", loc_rtp_port, loc_rtcp_port);
}
VideoStream *video_stream_new2(const char* ip, int loc_rtp_port, int loc_rtcp_port) {
MSMediaStreamSessions sessions={0};
VideoStream *obj;
sessions.rtp_session=create_duplex_rtpsession(loc_rtp_port,loc_rtcp_port,use_ipv6);
sessions.rtp_session=create_duplex_rtpsession(ip,loc_rtp_port,loc_rtcp_port);
obj=video_stream_new_with_sessions(&sessions);
obj->ms.owns_sessions=TRUE;
return obj;
......
......@@ -70,6 +70,7 @@ static int tester_cleanup(void) {
#define RECORDED_8K_1S_FILE "sounds/recorded_hello8000-1s.wav"
#define RECORDED_16K_1S_FILE "sounds/recorded_hello16000-1s.wav"
#define MULTICAST_IP "224.1.2.3"
typedef struct _stats_t {
rtp_stats_t rtp;
......@@ -95,10 +96,15 @@ static void notify_cb(void *user_data, MSFilter *f, unsigned int event, void *ev
}
static void basic_audio_stream() {
AudioStream * marielle = audio_stream_new (MARIELLE_RTP_PORT, MARIELLE_RTCP_PORT,FALSE);
static void basic_audio_stream_base( const char* marielle_local_ip
, int marielle_local_rtp_port
, int marielle_local_rtcp_port
, const char* margaux_local_ip
, int margaux_local_rtp_port
, int margaux_local_rtcp_port) {
AudioStream * marielle = audio_stream_new2 (marielle_local_ip, marielle_local_rtp_port, marielle_local_rtcp_port);
stats_t marielle_stats;
AudioStream * margaux = audio_stream_new (MARGAUX_RTP_PORT,MARGAUX_RTCP_PORT, FALSE);
AudioStream * margaux = audio_stream_new2 (margaux_local_ip, margaux_local_rtp_port,margaux_local_rtcp_port);
stats_t margaux_stats;
RtpProfile* profile = rtp_profile_new("default profile");
char* hello_file = ms_strdup_printf("%s/%s", mediastreamer2_tester_get_file_root(), HELLO_8K_1S_FILE);
......@@ -112,10 +118,10 @@ static void basic_audio_stream() {
CU_ASSERT_EQUAL(audio_stream_start_full(margaux
, profile
, MARIELLE_IP
, MARIELLE_RTP_PORT
, MARIELLE_IP
, MARIELLE_RTCP_PORT
, ms_is_multicast(margaux_local_ip)?margaux_local_ip:marielle_local_ip
, ms_is_multicast(margaux_local_ip)?margaux_local_rtp_port:marielle_local_rtp_port
, marielle_local_ip
, marielle_local_rtcp_port
, 0
, 50
, NULL
......@@ -126,10 +132,10 @@ static void basic_audio_stream() {
CU_ASSERT_EQUAL(audio_stream_start_full(marielle
, profile
, MARGAUX_IP
, MARGAUX_RTP_PORT
, MARGAUX_IP
, MARGAUX_RTCP_PORT
, margaux_local_ip
, margaux_local_rtp_port
, margaux_local_ip
, margaux_local_rtcp_port
, 0
, 50
, hello_file
......@@ -155,6 +161,15 @@ static void basic_audio_stream() {
ms_free(recorded_file);
ms_free(hello_file);
}
static void basic_audio_stream() {
basic_audio_stream_base(MARIELLE_IP,MARIELLE_RTP_PORT,MARIELLE_RTCP_PORT
,MARGAUX_IP, MARGAUX_RTP_PORT, MARGAUX_RTCP_PORT);
}
static void multicast_audio_stream() {
basic_audio_stream_base("0.0.0.0",MARIELLE_RTP_PORT, 0
,MULTICAST_IP, MARGAUX_RTP_PORT, 0);
}
static void encrypted_audio_stream() {
AudioStream * marielle = audio_stream_new (MARIELLE_RTP_PORT, MARIELLE_RTCP_PORT,FALSE);
......@@ -267,6 +282,7 @@ static void audio_stream_dtmf(int codec_payload, int initial_bitrate,int target_
static test_t tests[] = {
{ "Basic audio stream", basic_audio_stream },
{ "Multicast audio stream", multicast_audio_stream },
{ "Encrypted audio stream", encrypted_audio_stream },
};
......
......@@ -159,7 +159,7 @@ static void dtmfgen_enc_rtp_dec_tonedet(void) {
ms_tester_codec_mime = "pcmu";
ms_tester_create_filters(filter_mask);
ms_filter_add_notify_callback(ms_tester_tonedet, (MSFilterNotifyFunc)tone_detected_cb, NULL,TRUE);
rtps = create_duplex_rtpsession(50060, 0, FALSE);
rtps = create_duplex_rtpsession("0.0.0.0", 50060, 0);
rtp_session_set_remote_addr_full(rtps, "127.0.0.1", 50060, "127.0.0.1", 50061);
rtp_session_set_payload_type(rtps, 8);
rtp_session_enable_rtcp(rtps,FALSE);
......
......@@ -135,8 +135,18 @@ static void test_video_processing (void) {
}
#endif
static void test_is_multicast(void) {
CU_ASSERT_TRUE(ms_is_multicast("224.1.2.3"));
CU_ASSERT_TRUE(ms_is_multicast("239.0.0.0"));
CU_ASSERT_TRUE(ms_is_multicast("ff02::3:2"));
CU_ASSERT_FALSE(ms_is_multicast("192.68.0.1"));
CU_ASSERT_FALSE(ms_is_multicast("::1"));
}
static test_t tests[] = {
{ "Multiple ms_voip_init", filter_register_tester }
{ "Multiple ms_voip_init", filter_register_tester }
, { "Is multicast", test_is_multicast}
#ifdef VIDEO_ENABLED
, { "Video processing function", test_video_processing}
#endif
......
......@@ -52,14 +52,14 @@ static int tester_cleanup(void) {
}
#ifdef VIDEO_ENABLED
#define MARIELLE_RTP_PORT 2564
/*#define MARIELLE_RTP_PORT 2564
#define MARIELLE_RTCP_PORT 2565
#define MARIELLE_IP "127.0.0.1"
#define MARGAUX_RTP_PORT 9864
#define MARGAUX_RTCP_PORT 9865
#define MARGAUX_IP "127.0.0.1"
*/
typedef struct _video_stream_tester_stats_t {
OrtpEvQueue *q;
......@@ -82,14 +82,37 @@ typedef struct _video_stream_tester_t {
VideoStream *vs;
video_stream_tester_stats_t stats;
MSVideoConfiguration* vconf;
char* local_ip;
int local_rtp;
int local_rtcp;
} video_stream_tester_t;
void video_stream_tester_set_local_ip(video_stream_tester_t* obj,const char*ip) {
char* new_ip = ip?ms_strdup(ip):NULL;
if (obj->local_ip) ms_free(obj->local_ip);
obj->local_ip=new_ip;
}
video_stream_tester_t* video_stream_tester_new() {
return ms_new0(video_stream_tester_t,1);
video_stream_tester_t* vst = ms_new0(video_stream_tester_t,1);
video_stream_tester_set_local_ip(vst,"127.0.0.1");
vst->local_rtp=-1; /*random*/
vst->local_rtcp=-1; /*random*/
return vst;
}
video_stream_tester_t* video_stream_tester_create(const char* local_ip, int local_rtp, int local_rtcp) {
video_stream_tester_t *vst = video_stream_tester_new();
if (local_ip)
video_stream_tester_set_local_ip(vst,local_ip);
vst->local_rtp=local_rtp;
vst->local_rtcp=local_rtcp;
return vst;
}
void video_stream_tester_destroy(video_stream_tester_t* obj) {
if (obj->vconf) ms_free(obj->vconf);
if(obj->local_ip) ms_free(obj->local_ip);
ms_free(obj);
}
......@@ -165,8 +188,12 @@ static void init_video_streams(video_stream_tester_t *marielle, video_stream_tes
MSWebCam *no_webcam = ms_web_cam_manager_get_cam(ms_web_cam_manager_get(), "StaticImage: Static picture");
MSWebCam *default_webcam = ms_web_cam_manager_get_default_cam(ms_web_cam_manager_get());
/* MSWebCam *default_webcam = ms_web_cam_manager_get_cam(ms_web_cam_manager_get(), "QT Capture: Logitech Camera #2");*/
marielle->vs = video_stream_new(MARIELLE_RTP_PORT, MARIELLE_RTCP_PORT, FALSE);
margaux->vs = video_stream_new(MARGAUX_RTP_PORT, MARGAUX_RTCP_PORT, FALSE);
marielle->vs = video_stream_new2(marielle->local_ip,marielle->local_rtp, marielle->local_rtcp);
marielle->local_rtp=rtp_session_get_local_port(marielle->vs->ms.sessions.rtp_session);
marielle->local_rtcp=rtp_session_get_local_rtcp_port(marielle->vs->ms.sessions.rtp_session);
margaux->vs = video_stream_new2(margaux->local_ip, margaux->local_rtp, margaux->local_rtcp);
margaux->local_rtp=rtp_session_get_local_port(margaux->vs->ms.sessions.rtp_session);
margaux->local_rtcp=rtp_session_get_local_rtcp_port(margaux->vs->ms.sessions.rtp_session);
reset_stats(&marielle->stats);
reset_stats(&margaux->stats);
......@@ -207,7 +234,7 @@ static void init_video_streams(video_stream_tester_t *marielle, video_stream_tes
}
CU_ASSERT_EQUAL(
video_stream_start(marielle->vs, &rtp_profile, MARGAUX_IP, MARGAUX_RTP_PORT, MARGAUX_IP, MARGAUX_RTCP_PORT, payload_type, 50, no_webcam),
video_stream_start(marielle->vs, &rtp_profile, margaux->local_ip, margaux->local_rtp, margaux->local_ip, margaux->local_rtcp, payload_type, 50, no_webcam),
0);
if (margaux->vconf) {
......@@ -218,7 +245,7 @@ static void init_video_streams(video_stream_tester_t *marielle, video_stream_tes
}
CU_ASSERT_EQUAL(
video_stream_start(margaux->vs, &rtp_profile, MARIELLE_IP, MARIELLE_RTP_PORT, MARIELLE_IP, MARIELLE_RTCP_PORT, payload_type, 50, default_webcam),
video_stream_start(margaux->vs, &rtp_profile, marielle->local_ip, marielle->local_rtp, marielle->local_ip, marielle->local_rtcp, payload_type, 50, default_webcam),
0);
}
......@@ -281,6 +308,29 @@ static void basic_one_way_video_stream(void) {
video_stream_tester_destroy(margaux);
}
static void multicast_video_stream(void) {
video_stream_tester_t* marielle=video_stream_tester_new();
video_stream_tester_set_local_ip(marielle,"224.1.2.3");
marielle->local_rtcp=0; /*no rtcp*/
video_stream_tester_t* margaux=video_stream_tester_new();
video_stream_tester_set_local_ip(margaux,"0.0.0.0");
bool_t supported = ms_filter_codec_supported("vp8");
if (supported) {
init_video_streams(marielle, margaux, FALSE, TRUE, NULL,VP8_PAYLOAD_TYPE);
CU_ASSERT_TRUE(wait_for_until_with_parse_events(&marielle->vs->ms, &margaux->vs->ms, &margaux->stats.number_of_SR, 2, 15000, event_queue_cb, &marielle->stats, event_queue_cb, &margaux->stats));
video_stream_get_local_rtp_stats(marielle->vs, &marielle->stats.rtp);
video_stream_get_local_rtp_stats(margaux->vs, &margaux->stats.rtp);
uninit_video_streams(marielle, margaux);
} else {
ms_error("VP8 codec is not supported!");
}
video_stream_tester_destroy(marielle);
video_stream_tester_destroy(margaux);
}
static void avpf_video_stream(void) {
video_stream_tester_t* marielle=video_stream_tester_new();
video_stream_tester_t* margaux=video_stream_tester_new();
......@@ -437,6 +487,7 @@ static void video_configuration_stream(void) {
static test_t tests[] = {
{ "Basic video stream", basic_video_stream },
{ "Multicast video stream",multicast_video_stream},
{ "Basic one-way video stream", basic_one_way_video_stream },
{ "AVPF video stream", avpf_video_stream },
{ "AVPF high-loss video stream", avpf_high_loss_video_stream },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment