[asterisk-dev] RTP packet throttling

Matt Fredrickson creslin at digium.com
Mon Feb 27 15:50:44 CST 2017


Hey Kal,

On Sun, Feb 26, 2017 at 8:14 AM, b17 c0de <b17c0de at gmail.com> wrote:
> Hi Asterisk Community,
> Is it possible to have Asterisk trottle outgoing RTP packets when
> received to-be-forwarded samples are from packets with a larger ptime?
> I am using Asterisk as SIP proxy between two devices. When the sending
> device uses a ptime larger than the receiving device, Asterisk
> forwards the samples in bursts soon after a packet is received.
>
> For example, consider the following setup:
>
> [Device A] == ptime=300ms ==> [Asterisk] == ptime=20ms ==> [Device B]
>
> As soon as Asterisk receives a packet (300ms) from Device A it
> transcodes 300ms worth of samples and sends 15 Packets (20 ms) to
> Device B. This is a problem when Device B has a small buffer. My
> testing shows that typical SIP phones cannot handle this case.
>
> What is the best solution to this problem? Is there a way to enable
> clocked/throttled RTP packet transmission? If this is currently not
> possible, can someone point me in the right direction as to where I
> need to patch Asterisk to get this to work? I am willing to upstream
> any changes I make to support this.
>
> I am currently using Asterisk 12.3.

I don't think that Asterisk currently has a way of spacing out the
delivery times on the relayed packets in your example above.

My guess is that you'll want to work on it in res/res_rtp_asterisk.c,
starting in ast_rtp_write().  There is a smoother that is created
dependent on the ptime (framing_ms):

        if (!rtp->smoother && ast_format_can_be_smoothed(format)) {
                unsigned int framing_ms =
ast_rtp_codecs_get_framing(ast_rtp_instance_get_codecs(instance));
                int is_slinear = ast_format_cache_is_slinear(format);

                if (!framing_ms && is_slinear) {
                        framing_ms = ast_format_get_default_ms(format);
                }

                if (framing_ms) {
                        rtp->smoother = ast_smoother_new((framing_ms *
ast_format_get_minimum_bytes(format)) /
ast_format_get_minimum_ms(format));
                        if (!rtp->smoother) {
                                ast_log(LOG_WARNING, "Unable to create
smoother: format %s ms: %u len: %u\n",
                                        ast_format_get_name(format),
framing_ms, ast_format_get_minimum_bytes(format));
                                return -1;
                        }
                        if (is_slinear) {
                                ast_smoother_set_flags(rtp->smoother,
AST_SMOOTHER_FLAG_BE);
                        }
                }
        }

A smoother is basically a circular buffer that input data of any size
is placed into (i.e. 300 ms packets), and repacketized output data
(i.e. 20 ms packets) is pulled from.

The end of ast_rtp_write() has a piece of code:

        /* Feed audio frames into the actual function that will create
a frame and send it */

        if (rtp->smoother) {
                struct ast_frame *f;

                if (ast_smoother_test_flag(rtp->smoother,
AST_SMOOTHER_FLAG_BE)) {
                        ast_smoother_feed_be(rtp->smoother, frame);
                } else {
                        ast_smoother_feed(rtp->smoother, frame);
                }

                while ((f = ast_smoother_read(rtp->smoother)) &&
(f->data.ptr)) {
                                ast_rtp_raw_write(instance, f, codec);
                }

The culprit of your fast write timing is probably the
ast_rtp_raw_write inside the while loop.  You'll need to think about
ways to asynchronously space out the transmission.  You don't want to
do it by blocking in that function IMHO, due to potentially blocking
other things from happening in Asterisk that aren't expecting
ast_rtp_write to block.

Sounds like a fun problem, by the way :-)  Best wishes, and good luck
on it!  If you have any more questions, feel free to ask them here, or
frequently we inhabit the #asterisk-dev IRC channel on
irc.freenode.net.

-- 
Matthew Fredrickson
Digium, Inc. | Engineering Manager
445 Jan Davis Drive NW - Huntsville, AL 35806 - USA



More information about the asterisk-dev mailing list