RTPを少し調べた

GoRTPのサンプルコードを使って中身に目を通しつつ仕様を勉強してみた。 調べた直接のきっかけは転職活動だけど、もともと負荷分散とか低レイテンシ化が好きだ。

とりあえず

  1. 実験: まず馴染みのあるGoでパケットを流してみてWiresharkで確認する
  2. 資料となるRFC(一次資料とInformation)
  3. 概要や用語
  4. 応用されたプロトコルの紹介

という流れで書く。

実験: Wiresharkで確認する

検索して一番上に来ていたGoRTPを使った。 サンプルコードから読み始めるのが早い。 使ってキャプチャすると下のようになる。

図: RTPパケット 図: RTPパケット
図: RTCPパケット 図: RTCPパケット

別のRTP上で動くRTSPのGo実装であるgithub.com/beatgammit/rtspも読んだが、 RTCPのハンドラは未実装だったりととても雑だった。

概してGo言語での実装でしっかりしたものは今のところなさそう。

資料となるRFC(一次資料とInformation)

概要(Information)

用語が複雑なので整理してくれているInformationたちを並べる。

RFC Last update Title
RFC7656 NOVEMBER 2015 A Taxonomy of Semantics and Mechanisms for Real-Time Transport Protocol (RTP) Sources
RFC7667 NOVEMBER 2015 RTP Topologies

仕様(一次資料)

RTPはリアルタイムアプリケーションに向けられたプロトコル。 通信品質の管理が重要となりTCPの外側でマルチキャストもサポートする。 そのため関連する話題がとても多い。

関連項目をざっと並べると、 ヘッダ圧縮、QoSのシグナリング、TCPとの共存(輻輳制御)、 マルチキャストのルーティング、パケットロス検知、パケットロス補間(音声・映像)、サンプルのインタリーブ、バッファリング、 符号訂正、多重化、クロック変更、ループ検知、セッション確立、 メディア同期、暗号化、SSRC衝突、などがある。

プロトコルの基礎部分

RTPはリアルタイム通信を扱う。 音声や動画の配信、アナログ電波の転送など品質管理は配信するコンテンツによって大きく変わってくる。 そのためTCPと異なり、RTPは再送制御などを画一的には提供しない。

どういうことかというとRTPはリアルタイム通信を行う基本的なプロトコルとフレームワークとしての役割を持つ。 実際のコンテンツに合わせた品質管理や制御はプロファイルとして定義しておき、実際の制御はアプリケーションが行う。

代表的なプロファイルがRFC3551で定義されている。 現在は、そのうちのDIV4は望ましくないとしてRFC7007で取り除かれている。

RFC Last update Title
RFC3550 JULY 2003 RTP: A Transport Protocol for Real-Time Applications
RFC3551 JULY 2003 RTP Profile for Audio and Video Conferences with Minimal Control

RTPペイロードの動的割付と多重化などの部分

プロファイルは定義されているものの他にも柔軟に定義したくなる。 そこでSession Description Protocol(SDP)を使って動的に適用するプロファイルを決るようになっている。

ここではSDP自体の定義やRTPでの利用、そして単一RTPセッションに複数RTPストリームを載せる拡張定義に関するリンクを載せる。

RFC Last update Title
RFC3264 JUNE 2002 An Offer/Answer Model with Session Description Protocol (SDP)
RFC4566 JULY 2006 SDP: Session Description Protocol
RFC5761 APRIL 2010 Multiplexing RTP Data and Control Packets on a Single Port
RFC8035 NOVEMBER 2016 Session Description Protocol (SDP) Offer/Answer Clarifications for RTP/RTCP Multiplexing
RFC8108 MARCH 2017 Sending Multiple RTP Streams in a Single RTP Session

RTPの通信品質の制御などについて

前述の通り、RTPの輻輳制御(品質管理)はアプリケーションに任されている。 このアルゴリズムはスタンダードが確立されてない。 またまともに実装してない処理系が多いためネットワークを溢れさせやすい。 その問題への対応として最低限必要なcircuit breaker機構が以下で定義されている。

RFC Last update Title
RFC8083 March 2017 Multimedia Congestion Control: Circuit Breakers for Unicast RTP Sessions

RTPプロトコルの概要

RTPは(主に)UDP上で動くストリーム型通信を提供するプロトコルだ。 ストリーム型通信と一緒に求められる事が多いマルチキャストもサポートしている。

プロトコルの概念の紹介や説明はRFC7656にまとめられている。

RTPで扱うデータストリームをRTPストリームと呼び、ストリームを構成するパケットを RTPパケット と呼ぶ。

RTCPはRTPと連携するプロトコル。 RTPはメディアストリームの転送だけを担う。

一方でRTCPは転送状況のレポーティングなど周辺サービスを提供する。 パケットは RTCPパケット と呼ばれます。

プロトコル 役割
RTP ストリーミング配信を頑張る
RTCP ストリーミングの周辺サービスを提供

初期の仕様ではRTP,RTCPは分離されたチャンネル(IP/UDPでは別port)を利用するように設計されていて、 特にIP/UDP上ではRTP(偶数のポート番号),RTCP(RTPのポート番号+1)という制約がありました。 しかし最近はそのようなポート番号の縛りはない。ただし後方互換のために特に理由がない場合は上記の制約を守るのが良い。

RTPの設計方針はApplication Level Framing(ALF) に基づいており、 配信の詳細はアプリケーションが行うべきで、トランスポートでは基本的な転送のみを行うべきという方針を取っている。 そのため RTP,RTCPはアプリケーションに対してストリーミングを提供するためのフレームワークを提供する と言われる。

RTPペイロードの具体的な解釈の仕方や使い方をプロファイルと呼びます。 代表的なプロファイルはRFC3551で定義されておりRFC3550と合わせてRTP/AVPと表示します。

構成

RTPパケット
RTP通信に使われているパケット SSRC, PTフィールドなどを持つ
RTPペイロード
RTPパケットで運ばれるデータ部分
RTPストリーム
配信されている連続メディア SSRCフィールドで識別される
SSRC
RTPストリームの識別子でランダムに作成される 衝突もあるので解消するアルゴリズムなどが定義されている
RTPセッション
RTPストリームが流れる論理単位 SSRCの名前空間 参加者からはエンドポイントで識別される
エンドポイント
RTPパケットの宛先トランスポートアドレス(RTP,RTCP)の組み合わせを指す
マルチメディアセッション
同一の目的を実現するために用いられている複数のRTPセッションを指す
RTCPパケット
BYE,SR,RR,SDESなど用途に対応したパケットが存在する 1つのUDPパケットに複数のRTCPパケットを載せる

RTPパケット

RFC3550からRTPヘッダを引用すると下になる。

The RTP header has the following format:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P|X|  CC   |M|     PT      |       sequence number         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                           timestamp                           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           synchronization source (SSRC) identifier            |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|            contributing source (CSRC) identifiers             |
|                             ....                              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

一部にだけ言及する。

RTPパケットのデータ形式はPTフィールドで識別されます。 SSRCフィールドが一致してPTフィールドが異なるパケットを混在させるのは避けるべきです。 同一データストリーム(SSRCが一致)で複数のPTフィールドの値が混ざると複雑になるため。 (ただし途中で切り替えられる様にする拡張はあるようです)

RTPペイロードの形式の判別

PTフィールドの値から実際のデータ形式(スペック)への対応付は2つの方法があります。

  • プロファイル定義に従い静的に行う
  • 外部のプロトコル(多くの場合はSDP)を通して動的に行う

デフォルトプロファイルはRFC3551でこのプロファイルではdynamic用PTも定義されています。 また各データ形式はRFC3551や他のRFCで定義されています。

代表的な、動的な対応付けはSDP(RFC4566)のOffer/Answerモデルに従うことです。 一般的にはデフォルトプロファイルを用いてdynamic用PT(96-127)を任意のデータ形式に動的に割り当てます。

RFC5761で例に挙げられているSDPによるRTPセッションの記述を下に載せます。

v=0
o=csp 1153134164 1153134164 IN IP6 2001:DB8::211:24ff:fea3:7a2e
s=-
c=IN IP6 2001:DB8::211:24ff:fea3:7a2e
t=1153134164 1153137764
m=audio 49170 RTP/AVP 97
a=rtpmap:97 iLBC/8000
a=rtcp-mux

SDPの各パラメタは以下の様になっている。

SDPパラメタ 内容
v= Protocol Version: 0
o= Origin
c= Connection Data
t= Timing: " “stop-time:-:0:unbounded
m= Media Description
a= Attributes

メディア記述(Media Description)の形式は下の通りです。

m=<media> <port>[/<number of ports>] <proto> <fmt> ...

fmtに利用するPTフィールドの値(97)が記載されている。またプロトコルはRTP/AVPが指定されているのでRFC3551を使うことがわかる。 アトリビュートでrtpmapを用いてPTフィールドの値(97)とデータ形式(iLBC/8000)を紐付けている。

またSDPを用いて動的にセッションを確立する場合、RTP,RTCPを多重化して同一ポートで通信できるように拡張されています。 これは複数ポートでの通信がNAPTなど中継器の管理コスト増加に繋がることへの対処を意図してRFC5761,RFC8108に記載されています。 利用にはセッション確立の際に合意することが必要(MUST)で失敗した場合は利用できません。 前述の例ではa=rtcp-muxがRTP,RTCP多重化を指定しているパラメタになります。

補足ですが、SDPでは通信路は定義されないためアプリケーションが任意の方法でセッション確立します。

RTCPパケット

RFC3550によって以下が定義されている。 RTP転送を邪魔しないようにビットレートや参加者数を用いてRTCPパケットの送信インターバルの計算方法が定義されている。

SR
送信者(参加者の一部)からの統計情報
RR
受信者(参加者の一部)からの統計情報
SDES
ソース定義: CNAMEでssrcと正規リソースを紐付ける
BYE
参加者がRTPセッションから抜けたことを明示するパケット (一定時間の通信がなければ勝手に他の参加者は気付く)
APP
アプリケーション拡張用

マルチメディアセッション

目的を共有して同時に維持されるRTPセッションの集まりを指します。

RTPでは同期ポリシーの異なるメディアは別の転送経路を利用する事が推奨されています。 これはメディアごとに同期ポリシーやネットワーク上での品質管理を最適化できることが望まれるためです。

そのためメディアごとにRTPセッションを分けるためアプリケーションは複数のRTPセッションで構築されることになります。

RTPセッション

RTPで通信する参加者の連携を指す論理的なグループです。 各ノード(参加者)は同時に複数のRTPセッションに参加できます。 RTPストリームの識別子であるSSRCの名前空間であり複数のRTPストリームを束ねたものになっています。

また各参加者は送信先エンドポイント(アドレス, RTP port, RTCP port)によってRTPセッションを識別します。

マルチキャストの場合は複数の参加者は同一の組を持つでしょう。 ユニキャストの場合はRTPセッションは各ペアごとに組みが異なります。 RTPでは複数の送信元から同一のポートで受信することが可能です。

例えば以下の場合はA,B,C,Rは同一セッションに含まれます。

A -(dst: addr(R), pR(R), pRC(R))-> R
B -(dst: addr(R), pR(R), pRC(R))-> R
C -(dst: addr(R), pR(R), pRC(R))-> R

SRCPの名前空間がRTPセッションなので、RからのRR(RTCP)が送信される範囲が同一セッションになります。

RTPでは下位トランスポートプロトコルを用いたストリームの識別などは推奨されていません。 またRTPではユニキャストであってもRTPセッションへの参加者は2人だと想定できません(トランスレータなどで中継されるからです)。 そのため送信元IPでセッションを分けることができず、同一エンドポイントに届くRTPパケットは同一RTPセッションになります。

また、上記のケースではRからA,B,Cへ同一のRR(RTCP)が送信されます。 RTPのトポロジはRFC7667で詳しく説明されている。

RTPストリーム

RTPセッション内で転送されるデータストリームをRTPストリームと呼ぶ。

一般にRTPセッション内は同じ形式のデータが流れることが望ましい。 複数人で会議をしているなど発生源が異なるRTPストリームはSSRCを用いて識別され同一RTPセッションに流されるのが一般的である。 ただしSSRCで識別するものの正規化して扱う際にはCNAMEを持ちいる。これはSSRCがランダムに採用されるためアプリケーションの再起動や他データソースとの衝突などでSSRCが変更されるためSSRCでは一貫性を保てないためである。

RTPストリームはミキサーによって合成される。その場合はSSRCとして別の番号が振られる。CSRCに元になったストリームのSSRCが最大15個記録される。

応用プロトコル

RTPは連続メディアの配信を提供するフレームワークなので他のプロトコルと連携して、よりアプリケーションに近いプロトコルを構成する。

RTSP(RFC7828)
非ブラウザ標準、IETFで標準化
SIP
セッション確立プロトコル
SRTP
DTLSを使って安全にしたRTP
WebRTC
ブラウザ標準P2Pプロトコル
comments powered by Disqus