[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Linphone-developers] oRTP multi-duplex-streams-application
From: |
Машкин С В |
Subject: |
[Linphone-developers] oRTP multi-duplex-streams-application |
Date: |
Thu, 25 Oct 2007 19:51:04 +0400 |
Hi!
(Sorry for my sometimes "invalid" English.)
I am "green" in oRTP, so I have problems (I think, in my mind, not in oRTP lib.)
About 1 year ago I've read RTP RFCs, made own RTP functions (in ADSP-21xx asm).
But now my task needs oRTP usage. (I use oRTP 0.13.1)
As it was recommended in oRTP documentation, I've started with oRTP
examples mrtprecv.c, mrtpsend.c and so on. Then read oRTP docs, generated with
Doxygen (sometimes generated docs are very full, THANKS! But sometimes there are
"black-holes"... Even in comments, which are not used for documentation
generating).
My task is to open number of duplex rtp-streams
(at Blackfin platform, and at PC platform for debug).
So, I decide to use "sessionset.h" function session_set_select().
I use scheduled,nonblocking modes,
open rtpsessions in connected mode,
use adaptive jitter compensation.
When there is one stream, sound receiving and transmitting are good,
but when there are two, three or more streams - sound is corrupted
(in most cases - only in last opened streams...)
As "Ethereal"-sniffer showes numbers of input and output packets are different.
(In some my experiments with my aplication code number of output packets is
more than of input ones, in others experiments - number of input packets is
larger.)
First of all I read linphone pipermail... And found descriptions of
like-my situations (Something connected with #ifdef ORTP_IPVER6 and REENTRANT).
I though, that was my case, but I was wrong...
Now I have no ONE RIGHT questions...
so
I can only ask for good simple multi-duplex-session example
(with usage of "session_set_select" function in one thread
and scheduler working in other thread)
or
ask Do I correctly use oRTP lib in my application?
My application (and some other questions - see in comments) are
(some unimportant code and check details are absent):
--------------------------------------------------------------
//============================================================
//Global variables
//============================================================
#define RTP_CHANNELS 16 //Number of RTP-sessions in application
RtpSession * session[RTP_CHANNELS];
uint32_t session_rts[RTP_CHANNELS]; //timestamps
uint32_t session_tts[RTP_CHANNELS];
uint32_t session_drts[RTP_CHANNELS]; //increments
uint32_t session_dtts[RTP_CHANNELS];
char * session_ptlist[RTP_CHANNELS]; //payload types of session
SessionSet * rset; //set for receiving events
SessionSet * tset; //set for transiving events
int active_sessions; //number of active sessions
char * sup_ptlist = " 3 0 8 "; //Supported payload types
//in preferenced order:
//GSM=3,PCMU=0,PCMA=8
//============================================================
// timestampjump-event handler
//============================================================
void timestampjump_handler(RtpSession* session)
{
//QUESTION : Is this good realization of the handler?
rtp_session_reset(session);
#if 0
//QUESTION : It is good idea to flush sockets buffers
// in the handler?
rtp_session_flush_sockets(session);
#endif
}
//============================================================
// ssrcchanged-event handler
//============================================================
void ssrcchanged_handler(RtpSession* session)
{
//QUESTION : Is this good realization of the handler?
rtp_session_reset(session);
}
//============================================================
//Initialisation of RTP-level
//============================================================
int rtp_layer_init(void)
{
int i;
//init rtp-lib
ortp_init();
//init rtp-scheduler
ortp_scheduler_init();
//log level
ortp_set_log_level_mask(ORTP_DEBUG|ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR);
ortp_set_log_file(stdout);
//no rtp-session yet - clear array of sessions
for(i=0;i<RTP_CHANNELS;i++)
{
session[i] = NULL;
}
active_sessions = 0;
//create session-set
rset = session_set_new(); //receive session set
tset = session_set_new(); //transive session set
//init sound devices
init_sound_devices(); //overall sound-devices initialization
return(0);
}
//============================================================
//Uninitialization of rtp-layer
//============================================================
void rtp_layer_exit(void)
{
int i;
//delete sessions
for(i=0;i<RTP_CHANNELS;i++)
{
if(session[i]!=NULL)
{
rtp_session_destroy(session[i]);
}
rtp_close_sound_device(i);
}
active_sessions = 0;
//delete rset & tset
session_set_destroy(rset);
session_set_destroy(tset);
//exit oRTP-lib
ortp_exit();
//show rtp-statistics
ortp_global_stats_display();
printf(" RET rtp_layer_exit\n");
return;
}
//============================================================
//Open rtp-connection (Add session)
//============================================================
//returns: 0 = ok
// -1 = error
int rtp_connection_open(int chan, //number of rtp-channel
char *payload_types, //"0 1 13 101"
char *remoteaddr, //"192.168.1.122"
char *remoteport, //"2222"
char *localaddr, //"192.168.1.133"
char *localport) //"3333"
{
int ptype;
int err;
char * ptlist;
//check if every payload_types is supported and make ptlist string
//from payload_types string
ptlist_from_str(&ptlist, sup_ptlist, payload_types); //my function
//close current rtp-session on the channel (if it is present)
rtp_connection_close(chan);
//remember payload_types for the session
session_ptlist[chan] = ptlist;
//get the best payload type
ptype = ptlist_best_ptn(session_ptlist[chan], sup_ptlist); //my function
//open sound device (one sound-device is connected with one rtp-session)
rtp_open_sound_device(chan); //my function
//create new session on rtpchan channel:
session[chan] = rtp_session_new( RTP_SESSION_SENDRECV ); //duplex session
//settings:
rtp_session_set_scheduling_mode( session[chan], 1 );
rtp_session_set_blocking_mode( session[chan], 0 );
rtp_session_set_remote_addr( session[chan], remoteaddr, atoi(remoteport) );
rtp_session_set_local_addr( session[chan], localaddr, atoi(localport) );
rtp_session_enable_adaptive_jitter_compensation( session[chan], TRUE );
rtp_session_set_jitter_compensation( session[chan], RTP_RV_JITTER_COMP );
rtp_session_set_recv_buf_size( session[chan], 2000 ); //(default
recv_buf_size is 65535)
rtp_session_set_connected_mode( session[chan], TRUE );
rtp_session_set_payload_type( session[chan], ptype );
//rtp_session_set_SSRC( session[chan], SSRC );
//QUESTION : can you recommend some "intro"-documentation on
// jitter compensation algorithm, which is used
// in oRTP?
//init session timestamps
session_rts[chan] = 0;
session_tts[chan] = 0;
//init session timestamps increments
session_drts[chan] = payload_type_dts(ptype); //my function
session_dtts[chan] = payload_type_dts(ptype); //my function
//oRTP events-handlers
rtp_session_signal_connect(session[chan], "timestamp_jump",
(RtpCallback)timestampjump_handler, 0);
rtp_session_signal_connect(session[chan], "ssrc_changed",
(RtpCallback)ssrcchanged_handler, 0);
//increment number of active sessions
active_sessions++;
return(0); //ok: rtp-connection was opened
}
//============================================================
//Close rtp-connection (Remove session)
//============================================================
void rtp_connection_close(int chan)
{
int chan;
if( session[chan] != NULL )
{
rtp_close_sound_device( chan );
free( session_ptlist[chan] );
session_ptlist[chan] = NULL;
rtp_session_destroy( session[chan] );
session[chan] = NULL;
//decrement number of active sessions
active_sessions--;
}
return;
}
//============================================================
//Wait for rtp-events and process them
//============================================================
int rtp_layer_wait(void)
{
int i;
int rtpevents; //number of rtp-events
//session's sets init
//QUESTION : Really I have to do this here or this is made
// automatically?
session_set_init(rset);
session_set_init(tset);
//add all existing sessions to rset and tset
for(i=0;i<RTP_CHANNELS;i++)
{
if(session[i]!=NULL)
{
session_set_set(rset,session[i]);
session_set_set(tset,session[i]);
}
}
//wait and process rtp-events
if( active_sessions > 0 )
{
//sessions select
rtpevents = session_set_select(rset,tset,NULL);
//QUESTION : What is eset events examples?
if(rtpevents > 0)
{
//search for rset's events
for(i=0;i<RTP_CHANNELS;i++)
{
if(session[i]!=NULL) //check only for existing sessions
{
if(session_set_is_set(rset,session[i]))
{//new data received
//QUESTION : If we are here - does this mean, that it is time
// to receive next rtp-packet (so, we can receive
// NULL packets in silence periods)?
// Or we are here only when right-timestamp-packet
// is available in rtp-layer received packets queue.
mblk_t *mp;
int len;
int err;
int rvptype;
//QUESTION : If I don't have mistake, in
"mediastreamer/msrtprecv.c"
// in function ms_rtp_recv_process() at the point
// WHILE instead IF is used. Why? - Can oRTP generate
// receive-event for one session in
session_set_select()
// for which rtp_session_recvm_with_ts() can return
// more than one packets? (not only NULL or one
packet)
if( (mp =
rtp_session_recvm_with_ts(session[i],session_rts[i]))!=NULL ) //! or while(...)
?
{
//data received
len = mp->b_cont->b_wptr - mp->b_cont->b_rptr; //length of
payload data
if(len>0)
{
//get current payload type
rvptype = rtp_session_get_recv_payload_type(session[i]);
//play_payload() decodes and plays received data
//(then frees payload data - body of the packet)
err = play_payload(i, rvptype, mp->b_cont->b_rptr, len);
//my function
}
freemsg(mp); //free the packet (its header)
}
else
{//silence period? - play nothing
//...
//play_nothing();
}
//increment rts
//QUESTION : It seems, that this is too simple way to
// calculate new value of session_rts[i]?
// May be use rtp_session_get_current_recv_ts()
// function? If yes, how?
session_rts[i] = session_rts[i] + session_drts[i];
}
}
}
//search for tset's events
for(i=0;i<RTP_CHANNELS;i++)
{
if(session[i]!=NULL) //check only for existing sessions
{
if(session_set_is_set(tset,session[i]))
{//need new data to transmit
//QUESTION : Does this tset-event arise when last execute of
// rtp_session_sendm_with_ts() was finished,
// i.e. last rtp-packet was sended (i.e.
// was written to socket)?
// Or this event has place, only when it is
// time to send next rtp-packet?
//
// In some of my experiments I saw, that tset-events
// arised more frequently than with 20ms interval
// (If we use GSM-payload-packets, for example).
mblk_t *mp;
unsigned char *payload_buf;
int payload_len;
int sended_bytes;
int err;
int trptype;
int trptype_fact;
uint32_t tts_now;
//get current payload type
trptype = rtp_session_get_send_payload_type(session[i]);
//form_payload() forms payload (allocates payload_buf
//and fills it with encoded audio data)
//trptype_fact - is needed, if we use silence suppression
//and comfort noise generation
form_payload(i, trptype, &payload_buf, &payload_len,
&trptype_fact);
//create rtp-packet
mp =
rtp_session_create_packet_with_data(session[i],payload_buf,payload_len,NULL);
//send rtp-packet (and free its header)
sended_bytes =
rtp_session_sendm_with_ts(session[i],mp,session_tts[i]);
if(payload_buf!=NULL)
{
free(payload_buf); //free payload-body of sended packet
}
//increment tts
//QUESTION : Is this correct way to increment the timestamp?
// Or it is better to use
rtp_session_get_current_send_ts()?
// If yes, how?
session_tts[i] = session_tts[i] + session_dtts[i];
//QUESTION : When I wrote rtp-layer for ADSP-21xx
// rtp-packet-need-to-be-send event generates
// when enough audio data (sampled with 8000 Hz)
// was collected. But with oRTP I can't use
// such principle... So, what principle may
// you recommend? (Use audio-data-flow or timer?
// Use own timers, or timers of oRTP? What timers?)
// So
// What is the good way to calculate ts value for
// rtp_session_sendm_with_ts() ?
}
}
}
}
else
{
//error: no events
//..
}
}
return(0);
}
--------------------------------------------------------------
P.S.: QUESTION: Are there some oRTP-based multi-duplex-rtp-streams
application examples (open source) in which
session_set_select() is used?
Serg Ma.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Linphone-developers] oRTP multi-duplex-streams-application,
Машкин С В <=