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.
- The
send_telephone_event
method to simulate a caller keypad press/release. - 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.
- A FIRST(Mark), non-END event packet is sent at
T = start-time + interval
- A non-Mark, non-END event packet is sent at
T = start-time + 2 * interval
- Repeat while
(start-time + N * interval) < duration
- After the last non-END event, send
end_count
END event packets, at periods ofinterval
.
E.g. for duration = 200, interval = 50, end_count = 3 the following packets are sent.
- Time + 50 => Mark, non-End (400 frames = 50 ms)
- Time + 100 => non-End (800 frames = 100 ms)
- Time + 150 => non-End (1200 frames = 150 ms)
- Time + 200 => non-End (1600 frames = 200 ms)
- Time + 250 => End (1600 frames = 200 ms)
- Time + 300 => End (1600 frames = 200 ms)
- 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 }
}
}
})