title = “RTP Sending” weight = 3 +++

Introduction

These methods in from TestRtpLuaAgent Lua API are used to send RTP packets to the remote end of the RTP test stream. Before using these methods, the test application must use the connect method on the stream to specify the remote IP and UDP port number.

The currently supported send methods are.

  1. The send_telephone_event method to simulate a caller keypad press/release.
  2. The send_amr_cmr method to modify AMR-WB stream attributes.

Setup API

.send_telephone_event [Synchronous]

The send_telephone_event method requests the TestRtpApp to send telephone-event RTP packets to the remote endpoint. A single call to this method will generate two or more RTP packets, being at least one “Start” telephone-event packet and at at least one “End” telephone-event packet.

The Lua script does not have direct control over the individual packets. The arguments to the method determine the nature of the events, the count of the packets sent, and the timing between the sending of each packet.

The method returns immediately after sending the initiation instructions to the TestRtpApp. It does not wait for the TestRtpApp to confirm the instructions, and does not wait for any of the telephone event packets to be sent.

The arguments to the method are:

Argument Type Description
payload_type 0 - 127 [Required] The payload type number for a telephone-event payload as negotiated in the SDP exchange.
event_code 0 - 255 [Required] The event type number, indicating which key was pressed/released, typically as per RFC 4733.
duration 10 - 5000 [Required] The duration of the key press is milliseconds.
volume 0 - 63 The volume of the keypress.
(Default = 20).
interval 10 - 1000 The interval between sending of RTP telephone-event packets associated with this keypress.
(Default = 50).
end_count 0 - 10 The number of times that an "End" event should be sent for this sequence.
Specifying a value of 0 is permitted, it means "do not send any End event", which is useful for the purpose of testing keypress detection timeout on the media server. (Default = 3).

The logic for the timing of key press events is as follows.

E.g. for duration = 200, interval = 50, end_count = 3 the following packets are sent.

  1. Time + 50 => Mark, non-End (400 frames = 50 ms)
  2. Time + 100 => non-End (800 frames = 100 ms)
  3. Time + 150 => non-End (1200 frames = 150 ms)
  4. Time + 200 => non-End (1600 frames = 200 ms)
  5. Time + 250 => End (1600 frames = 200 ms)
  6. Time + 300 => End (1600 frames = 200 ms)
  7. Time + 350 => End (1600 frames = 200 ms)

The method returns true.

Example sending seven digits with varying durations:

truo.send_telephone_event (102, truo.DIGIT_CODES['8'], 200)
truo.send_telephone_event (102, truo.DIGIT_CODES['9'], 210)
truo.send_telephone_event (102, truo.DIGIT_CODES['#'], 210)
truo.send_telephone_event (102, truo.DIGIT_CODES['1'], 200)
truo.send_telephone_event (102, truo.DIGIT_CODES['2'], 210)
truo.send_telephone_event (102, truo.DIGIT_CODES['3'], 190)
truo.send_telephone_event (102, truo.DIGIT_CODES['*'], 990)
...

.send_amr_cmr [Synchronous]

The send_amr_cmr method requests the TestRtpApp to send an adaptive multi-rate codec mode request to the remote endpoint. The AMR-WB supports 9 wide band speech coding modes with respective bit rates ranging from 6.6 to 23.85 kbps. See RFC 3267 for the specification of AMR-WB modes.

The method returns immediately after sending the initiation instructions to the TestRtpApp. It does not wait for the TestRtpApp to confirm the instructions, and does not wait for the codec mode request to be sent.

The arguments to the method are:

Argument Type Description
payload_type 0 - 127 [Required] The payload type number for the AMR payload as negotiated in the SDP exchange.
codec_mode 0 - 8 [Required] The mode number as per RFC 3267.
This should be one of the negotiated modes from the SDP Answer, although for testing purposes it is possible to send a mode which is not one of the negotiated supported mode numbers.
octet_align Boolean Set true to use octet-aligned framing, false to use bandwidth-efficient framing.
(Default = true use octet-aligned framing).

Example negotiating AMR-WB and requesting mode change while streaming:

-- Attempt to establish a RTP listener that we can direct RTP packets at and store for comparison.
local register_result = truo.register ()

-- Static for our call.
local endpoints = tsuo.default_endpoints ({ local_rtp_port = register_result.local_port })
local calling_party = '665566'
local called_party = '4000'
local encoding = 'AMR/8000'

-- Get a SIP outcall context from our helper library.
local context = tsuo.invite_context (endpoints, calling_party, called_party)

-- Construct the SDP.
local sdp_session_id = os.time () % 10000
local sdp_session_version = math.random (1000) - 1
local sdp_offer =
"v=0\
o=" .. calling_party .. " " .. sdp_session_id .. " " .. sdp_session_version .. " IN IP4 " .. endpoints.local_rtp_ip .. "\
s=-\
c=IN IP4 " .. endpoints.local_rtp_ip .. "\
t=0 0\
m=audio " .. endpoints.local_rtp_port .. " RTP/AVP 96 102\
a=rtpmap:96 AMR/8000\
a=fmtp:96 mode-set=2,4,7;mode-change-neighbor=1;mode-change-period=2;octet-align=1\
a=rtpmap:102 telephone-event/8000"

-- Construct and Send INVITE Request.
tsuo.invite_send_request (context, sdp_offer)

-- Expect Trying & Ringing.
tsuo.invite_expect_response (context, 100, "Trying", { ['User-Agent'] = "N-Squared LHO" })
tsuo.invite_expect_response (context, 180, "Ringing")
tv = match.elapsed ("Ring Notification (immediate)", tv, 0.0)

-- Expect INVITE Answer Response (200 OK) after 2 seconds.
local invite_response = tsuo.invite_expect_response (context, 200, "OK", nil, { sdp_media = tsuo.SDP_MEDIA_N2_AMRNB_OA })
tv = match.elapsed ("Call Answered (2.0s)", tv, 1.99)

-- Request our RTP tester to connect to the far-end IP/port.  Now we can send RTP as well as receive it.
truo.connect (invite_response.sdp.connection.ip4.address, invite_response.sdp.media.audio.port)

-- Send an AMR CMR before we ACK to ensure streaming uses the desired mode.
truo.send_amr_cmr (96, 2)

-- Try to ENSURE the CMR goes on the wire before the ACK. Without this,
-- sometimes the ACK wins.
n2svcd.wait (0.02)

-- ACK the 200.
tsuo.invite_send_2xx_ack (context)

-- Voice call in progress.
-- The "Goodbye" announcement is 0.65 seconds and it is played twice before hangup.

-- Request to go to mode 7. The mode change restrictions will cause us to
-- send two mode 4 frames before our requested change will be applied.
n2svcd.wait (0.2)
truo.send_amr_cmr (96, 7)

-- ...and back to mode 2.
n2svcd.wait (0.2)
truo.send_amr_cmr (96, 2)

n2svcd.wait (0.1)

-- Send BYE from our side.
tsuo.bye_send_request (context)
tv = match.elapsed ("Send BYE (0.5s)", tv, 0.5)

-- Expect immediate acknowledgement.
tsuo.bye_expect_response (context, 200, "OK")
tv = match.elapsed ("BYE Confirmed (immediate)", tv, 0.0)

-- Trigger a collection of RTP packets and match against the expected configuration.
truo.fetch_and_match ({
    encoding = encoding, 
    fragments = {
        { files = { 'English/announcements/Goodbye.amr' }, min = 0.5, max = 0.65 }, 
        { silence_min = 0, silence_max = 0.1 }

    }, amr = {
        modes = {
            { mode = 2, min = 0.15, max = 0.25 },
            { mode = 4, min = 0.04, max = 0.04 },
            { mode = 7, min = 0.15, max = 0.25 },
            { mode = 4, min = 0.04, max = 0.04 },
            { mode = 2 }
        }
    }
})