linphone-developers
[Top][All Lists]
Advanced

[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.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]