RTP stream replay


RTP is network protocol mainly used for transferring multimedia streams in real-time streaming system. Most popular streaming protocols that use RTP are RTSP and SIP. One RTP stream can only be used for one type of media, for example: one RTP stream is used for video, another one is used for audio.

Most common transfer protocol for RTP is UDP. Although TCP can be used, it is often not suitable because guaranteed delivery prevents low latency real-time streaming.

Why

When debugging issues with stream (for example corrupted image in video player), it is useful to be able to replay stream that caused the issue.

This guide covers the simplest scenario - replaying single RTP UDP stream.

Requirements

  1. Basic knowledge of using Wireshark.
  2. One more Linux machine (for example Virtual Machine) to act as fake source 1.

Creating replay file

Capture network traffic

In order to replay RTP stream, we must first capture it. Most common programs for capturing network traffic are Wireshark and tcpdump.

Capture network traffic to the file that Wireshark can open (most common formats are pcap and pcapng).

Filter RTP packets

We need to edit capture file so that it includes only packets of desired RTP stream. Note: Wireshark version 2.0.1 (Qt) is used in this guide, other versions may have different interface.

  1. Open capture file in Wireshark
  2. From menu bar, choose Telephony -> RTP -> RTP Streams
  3. Select desired stream (by Source and Destination address)
  4. Click Prepare Filter -> Close
  5. From menu bar, choose File -> Export Specified Packets… -> Export as: -> pcap
  6. Enter filename (e.g. rtpstream) and click Save
  7. Copy saved file to fake source machine

Modify RTP packets in capture file

For replaying RTP stream, we will use program “tcpreplay”.

Tcpreplay reads packets from pcap capture file and repeats them.

Wireshark has nice summary of packet data separated by network layer:

In order to replay captured RTP stream, the IP and MAC addresses in RTP stream packets have to be changed to match the machines we are using for debugging.

The following script will create new capture file with edited packets. Save the script as “modify-pcap.sh” on fake source machine.

#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o errtrace
set -o pipefail

REPLAY_DST_IP="${1}"
IN_PCAP_FILE="${2}"
OUT_PCAP_FILE="${3:-rtp-for-replay.pcap}"
OUT_SDP_FILE="${4:-sdp}"

REPLAY_SRC_IP=$(ip route get "${REPLAY_DST_IP}" | sed -n -r "s/.* src (\S*).*/\1/p")
REPLAY_SRC_DEV=$(ip route get "${REPLAY_DST_IP}" | sed -n -r "s/.* dev (\S*).*/\1/p")
REPLAY_SRC_MAC=$(ip link show "${REPLAY_SRC_DEV}" | sed -n -r "s/.*\/ether (\S*).*/\1/p")
if [ -z "${REPLAY_SRC_MAC}" ]
then
  echo "Error reading source MAC address. Make sure that the destination IP does not belong to this machine".
fi
ping -q -c 1 -- "${REPLAY_DST_IP}" > /dev/null
ARP_PATH=$(which arp)

if [ -x "${ARP_PATH}" ]
then
  ARP_CMD="${ARP_PATH}"
else
  ARP_CMD="sudo ${ARP_PATH}"
fi
REPLAY_DST_MAC=$(${ARP_CMD} -an -- "${REPLAY_DST_IP}" | sed -n -r "s/.* at (\S*).*/\1/p")

read ORIG_SRC_IP ORIG_SRC_MAC ORIG_DST_IP ORIG_DST_MAC RTP_DST_PORT <<<$(\
    tshark -T fields -e ip.src -e eth.src -e ip.dst -e eth.dst -e udp.dstport -c 1 -r "${IN_PCAP_FILE}")

tcprewrite \
    --fixcsum \
    --srcipmap=${ORIG_SRC_IP}/32:${REPLAY_SRC_IP}/32 \
    --enet-smac=${REPLAY_SRC_MAC} \
    --dstipmap=${ORIG_DST_IP}/32:${REPLAY_DST_IP}/32 \
    --enet-dmac=${REPLAY_DST_MAC} \
    --infile="${IN_PCAP_FILE}" \
    --outfile="${OUT_PCAP_FILE}"

echo "c=IN IP4 ${REPLAY_SRC_IP}
m=video ${RTP_DST_PORT} RTP/AVP 96
a=rtpmap:96 H264/90000" > "${OUT_SDP_FILE}"

echo "Copy file \"$(readlink -e ${OUT_SDP_FILE})\" to player machine, open it in player, then execute:"
echo "  sudo tcpreplay --intf1=${REPLAY_SRC_DEV} '${OUT_PCAP_FILE}'"

The script requires tcpreplay, tshark and net-tools packets to be installed. To install them on Debian Linux and its derivates, execute the following command:

$ sudo apt-get install tcpreplay tshark net-tools

Script argument syntax:

$ bash modify-pcap.sh <player machine ip> <input pcap file> [<output pcap file>] [<output sdp file>]

Where <input pcap file> is pcap file that contains only one RTP stream (that was produced at the end of Filter RTP packets section).

For example:

$ bash modify-pcap.sh 192.168.0.10 rtpstream.pcap

Replaying RTP stream

RTP stream does not contain information about how video is encoded, so we need to supply that information to the player.

That is done by SDP (Session Description Protocol) file.

Script “modify-pcap.sh” generates minimal SDP file for H264 encoded video stream.

That file can be copied to player machine and opened in player, for example:

$ ffplay sdp

The player now waits for stream to start.

In order to start playback, we need to start replaying the RTP stream.

To do so, on fake source machine, execute command printed at the end of execution of “modify-pcap.sh” script.

Troubleshooting

If there are playback issues using provided SDP file, additional information has to be added to the SDP file 1.

To do so, save the following script as “sdp-fmtp-data.sh” on machine that has tshark installed and capture file:

#!/usr/bin/env bash
set -o errexit
set -o nounset
IN_FILE="${1}"
echo "a=fmtp:96 $(tshark -E aggregator=';' -Y sdp.fmtp.parameter -T fields -e sdp.fmtp.parameter -r "${IN_FILE}")"

Run it using the following syntax:

$ bash sdp-fmtp-data.sh <input capture file>

Where <input capture file> is capture file that contains all captured traffic.

Then open SDP file in text editor, append output of script to the end of the file content and try playing again.

1: http://tcpreplay.appneta.com/wiki/faq.html#can-i-send-packets-on-the-same-computer-running-tcpreplay

2: http://stackoverflow.com/questions/20634476/is-sprop-parameter-sets-or-profile-level-id-the-sdp-parameter-required-to-decode