linphone-developers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Linphone-developers] Voice quality on 3G and EDGE


From: Simon Morlat
Subject: Re: [Linphone-developers] Voice quality on 3G and EDGE
Date: Thu, 09 Sep 2010 21:42:46 +0200

Hi Vadim,

Here are my thoughs about your suggestions:

1) doesn't make sense unless you meant "start transmitting duplicated
packets" (I guess it was your idea). This has the drawback of increasing
bandwidth usage.
2) packing more audio per packet significally reduces bandwidth, this is
useful as packet drops are very often caused by bandwidth overflow. In
mediastreamer2 it is easy to do thanks to the "ptime" parameter you can
give to encoders, either using MS_FILTER_ADD_FMTP or MS_FILTER_ADD_ATTR,
as you noticed.

3) I would refine saying: stop sending unecessary media: for example
stop transmit silences. This indeed allows the channel to purge old
packets and restart on better basis. Also using speex with vbr=on (like
in linphone) is interesting: the speex codec will automatically adapt
the bitrate to what is needed to properly encode the voice segment.
Enabling the speex vad feature is even better, but I never implemented
in linphone.

I would also distinguish between 3G and EDGE. On 3G you often have a
very good internet, with very low packet losses, though problems start
to occur when the 3G signal received by the phone becomes too low:
packet losses, and bandwidth reduced. 
On the opposite, edge is simply too bad. It can be compared as 15 years
old internet: high delay (ping not less than 300 ms) and ridiculous
bandwidth.
I think there is no way to make good VoIP on edge networks. EDGE is just
good enough to receive and send small emails... 

Simon

Le mardi 07 septembre 2010 à 09:54 +0200, Vadim Lebedev a écrit :
> Hello folks,
> 
> We're trying to improve mediastreamer behaviour on 3G and EDGE environments.
> For this we use RTCP receiver reports to detect changes in reported 
> jitter, bandwidth and packet losses.
> 
> Once we detect the degradation we can adopt following strategies:
> 
> 1) We can start retransmitting some/all RTP packets
> 2) We can pack more audio per packet
> 3) In case of hard congestion we can stop sending media and wait until 
> congestion resovled
> 
> 
> Strategies 1 and 3  are pretty simple to implement.
> But strategy 2 is less trivial to implement with mediastreamer.
> I'm thinking to hook a reformatting filter just before the encoder this 
> way i'll need no modifiy all aduio input drivers to
> suppport variable payload size per packet.
> 
> Simon what do you think?
> 
> 
> Thanks
> Vadim
> P.S. Meanwhile i'm attaching my QOS change detection patch
> ===============================
> 
> diff -r 2b4d9564be9b oRTP/include/ortp/rtpsession.h
> --- a/oRTP/include/ortp/rtpsession.h    Fri Sep 03 19:53:00 2010 +0200
> +++ b/oRTP/include/ortp/rtpsession.h    Tue Sep 07 09:51:31 2010 +0200
> @@ -167,8 +167,14 @@
>   typedef struct _RtpSession RtpSession;
> 
>   typedef struct _RtpQosInfos {
> -    uint32_t last_reported_jitter;
> -    uint32_t jitter_gradient;
> +    int  curx;
> +    struct {
> +        uint32_t   seqnum;
> +        uint32_t   interval_losses;
> +        uint32_t   remote_jitter;
> +        uint32_t   total_losses;
> +        uint32_t   interval_packets;
> +    } data[2];
>   } RtpQosInfo;
> 
> 
> @@ -202,6 +208,8 @@
>       RtpSignalTable on_timestamp_jump;
>       RtpSignalTable on_network_error;
>       RtpSignalTable on_rtcp_bye;
> +    RtpSignalTable on_qos_event;
> +
>       struct _OList *signal_tables;
>       struct _OList *eventqs;
>       msgb_allocator_t allocator;
> diff -r 2b4d9564be9b oRTP/src/rtcpparse.c
> --- a/oRTP/src/rtcpparse.c    Fri Sep 03 19:53:00 2010 +0200
> +++ b/oRTP/src/rtcpparse.c    Tue Sep 07 09:51:31 2010 +0200
> @@ -287,54 +287,103 @@
>       }
>   }
> 
> +static int big_change(uint32_t v1, uint32_t  v2,  int big_thresold)
> +{
> +    int diff = v1 - v2;
> +    uint32_t mean;
> +
> +    mean = ((v1 + v2) / 2) ;
> +
> +    if (diff < 0)
> +        diff = -diff;
> +
> +    diff = diff*100 / mean;
> +
> +    return diff > big_thresold;
> +
> +}
>   /*old functions: deprecated, but some useful code parts can be reused */
>   /* Start from now this source code file was written by Nicola Baldo as 
> an extension of
>     the oRTP library. Copyright (C) 2005 Nicola Baldo address@hidden/
> 
>   void report_block_parse(RtpSession *session, report_block_t *rb, 
> struct timeval rcv_time_tv)
>   {
> -  rb->ssrc = ntohl(rb->ssrc);
> +    rb->ssrc = ntohl(rb->ssrc);
> 
> -  if ( rb->ssrc != session->snd.ssrc )
> +    if ( rb->ssrc != session->snd.ssrc )
> 
> -    {
> -      ortp_debug("Received rtcp report block related to unknown ssrc 
> (not from us)... discarded");
> -      return;
> -    }
> -
> -  else
> -
> -    {
> -      uint32_t rcv_time_msw;
> -      uint32_t rcv_time_lsw;
> -      uint32_t rcv_time;
> -      double rtt;
> -
> -      rcv_time_msw = rcv_time_tv.tv_sec;
> -#if defined(_WIN32_WCE)
> -      rcv_time_lsw = (uint32_t) 
> ((double)rcv_time_tv.tv_usec*(double)(((uint64_t)1)<<32)*1.0e-6);
> -#else
> -      rcv_time_lsw = (uint32_t) 
> ((double)rcv_time_tv.tv_usec*(double)(1LL<<32)*1.0e-6);
> -#endif
> -      rcv_time = (rcv_time_msw<<16) | (rcv_time_lsw >> 16);
> -
> -/*
> -      rb->cum_num_packet_lost = ntoh24(rb->cum_num_packet_lost);
> -      rb->ext_high_seq_num_rec = ntohl(rb->ext_high_seq_num_rec);
> -      rb->interarrival_jitter = ntohl(rb->interarrival_jitter);
> -      rb->lsr = ntohl(rb->lsr);
> -      rb->delay_snc_last_sr = ntohl(rb->delay_snc_last_sr);
> -*/
> -
> -      /* calculating Round Trip Time*/
> -      if (rb->lsr != 0)
>       {
> -      rtt = (double) (rcv_time - rb->delay_snc_last_sr - rb->lsr);
> -      rtt = rtt/65536;
> -      //printf("RTT = %f s\n",rtt);
> +        ortp_debug("Received rtcp report block related to unknown ssrc 
> (not from us)... discarded");
> +        return;
>       }
> 
> -    }
> +    else
> +
> +    {
> +        uint32_t rcv_time_msw;
> +        uint32_t rcv_time_lsw;
> +        uint32_t rcv_time;
> +        double rtt;
> +        int newx,curx,generate_qos_event = 0;
> +
> +        rcv_time_msw = rcv_time_tv.tv_sec;
> +#if defined(_WIN32_WCE)
> +        rcv_time_lsw = (uint32_t) 
> ((double)rcv_time_tv.tv_usec*(double)(((uint64_t)1)<<32)*1.0e-6);
> +#else
> +        rcv_time_lsw = (uint32_t) 
> ((double)rcv_time_tv.tv_usec*(double)(1LL<<32)*1.0e-6);
> +#endif
> +        rcv_time = (rcv_time_msw<<16) | (rcv_time_lsw >> 16);
> +
> +
> +        rb->fl_cnpl = ntohl(rb->fl_cnpl);
> +
> +        rb->ext_high_seq_num_rec = ntohl(rb->ext_high_seq_num_rec);
> +        rb->interarrival_jitter = ntohl(rb->interarrival_jitter);
> +        rb->lsr = ntohl(rb->lsr);
> +        rb->delay_snc_last_sr = ntohl(rb->delay_snc_last_sr);
> +
> +        curx = session->qos.curx;
> +        newx = (!session->qos.data[curx].seqnum) ? 0 : !curx;
> +        session->qos.data[newx].seqnum = rb->ext_high_seq_num_rec;
> +        session->qos.data[newx].total_losses = rb->fl_cnpl & 0x00FFFFFF;
> +        session->qos.data[newx].remote_jitter = rb->interarrival_jitter;
> +        if (newx != curx) {
> +            session->qos.data[newx].interval_losses =
> +                    session->qos.data[newx].total_losses - 
> session->qos.data[curx].total_losses;
> +
> +            session->qos.data[newx].interval_packets =
> +                    session->qos.data[newx].seqnum - 
> session->qos.data[curx].seqnum;
> +
> +
> +            if (big_change(session->qos.data[newx].interval_losses, 
> session->qos.data[curx].interval_losses, 10 ))
> +                generate_qos_event++;
> +
> +            if (big_change(session->qos.data[newx].remote_jitter, 
> session->qos.data[curx].remote_jitter, 10 ))
> +                generate_qos_event++;
> +
> +            if (big_change(session->qos.data[newx].interval_packets, 
> session->qos.data[curx].interval_packets, 10))
> +                generate_qos_event++;
> +
> +
> +
> +        }
> +
> +
> +
> +        /* calculating Round Trip Time*/
> +        if (rb->lsr != 0)
> +        {
> +            rtt = (double) (rcv_time - rb->delay_snc_last_sr - rb->lsr);
> +            rtt = rtt/65536;
> +            //printf("RTT = %f s\n",rtt);
> +        }
> +
> +        if (generate_qos_event)
> +            rtp_signal_table_emit(&session->on_qos_event);
> +
> +        session->qos.curx = newx;
> +
> +    }
> 
>   }
> 
> diff -r 2b4d9564be9b oRTP/src/rtpsession.c
> --- a/oRTP/src/rtpsession.c    Fri Sep 03 19:53:00 2010 +0200
> +++ b/oRTP/src/rtpsession.c    Tue Sep 07 09:51:31 2010 +0200
> @@ -263,6 +263,8 @@
>       rtp_signal_table_init 
> (&session->on_timestamp_jump,session,"timestamp_jump");
>       rtp_signal_table_init 
> (&session->on_network_error,session,"network_error");
>       rtp_signal_table_init (&session->on_rtcp_bye,session,"rtcp_bye");
> +    rtp_signal_table_init (&session->on_qos_event,session,"qos_event");
> +
>       wait_point_init(&session->snd.wp);
>       wait_point_init(&session->rcv.wp);
>       /*defaults send payload type to 0 (pcmu)*/
> diff -r 2b4d9564be9b oRTP/src/rtpsession_priv.h
> --- a/oRTP/src/rtpsession_priv.h    Fri Sep 03 19:53:00 2010 +0200
> +++ b/oRTP/src/rtpsession_priv.h    Tue Sep 07 09:51:31 2010 +0200
> @@ -51,6 +51,6 @@
> 
>   void rtp_session_dispatch_event(RtpSession *session, OrtpEvent *ev);
> 
> -#define rtp_qos_reset(qos) { (qos)->last_reported_jitter = 0; 
> (qos)->jitter_gradient = 0; }
> +#define rtp_qos_reset(qos) { memset((qos), 0, sizeof(*(qos))); }
> 
>   #endif
> 
> 
> 
> 
> _______________________________________________
> Linphone-developers mailing list
> address@hidden
> http://lists.nongnu.org/mailman/listinfo/linphone-developers





reply via email to

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