オーディオおよびビデオRTMPプロトコル分析

エンディアンを理解する

エンディアンモード
はエンディアンを高く評価しました

リトルエンディアンとは、下位バイトがメモリの下位アドレス側に配置され、上位バイトがメモリの上位アドレス側に配置されることを意味します。ビッグエンディアンとは、上位バイトが配置されることを意味します。メモリの下位アドレス側に配置され、下位バイトはメモリの上位アドレス側に配置されます。

  • たとえば、メモリ内の数値0x12 34 5678の表現は次のとおりです。

    • ビッグエンディアンモード:
      ローアドレス----------------->ハイアドレス
      0x12 | 0x34 | 0x56 | 0x78
    • リトルエンディアンモード:
      ローアドレス------------------>ハイアドレス
      0x78 | 0x56 | 0x34 | 0x12
      が表示され、ビッグエンディアンモードと文字列ストレージモードは類似しています。
  • RTMPはビッグエンディアンモードであるため、データ、ヘッダー、およびインタラクティブメッセージを送信するときにビッグエンディアンモードに入力する必要がありますが、リトルエンディアンモードになっているのはstreamIDのみです。

RMTPとは

RTMPプロトコルであるRealTime Messaging Protocol(Real Time Messaging Protocol)は、情報送信の信頼性を確保するために、基盤となる信頼性の高いトランスポート層プロトコル(TCP、UDP)に依存するアプリケーション層プロトコルです。

トランスポート層でRTMPが正常に確立された後、ハンドシェイク、RTMP接続の確立、ストリームCreateStreamの確立、および再生/送信の4つのステップがあります。

リンク確立フェーズでは、クライアントとサーバーの間に「ネットワークリンク」を確立します。
フロー確立フェーズは、クライアントとサーバー間の「ネットワークフロー」を確立するために使用されます。
再生/送信ステージは、オーディオおよびビデオデータを送信するために使用されます。

公式文書

伝説

握手

クライアントは3つのチャンクC0、C1、C2を(順番に)サーバーに送信する必要があり、サーバーは3つのチャンクS0、S1、S2を(順番に)クライアントに送信すると、効果的な情報送信を実行できます。RTMPプロトコル自体は、これら6つの
メッセージの特定の送信シーケンスを指定しませんが、RTMPプロトコルの実装者は、これらのポイントを確認する必要があります。クライアントは、
S2を受信した後にC2クライアントが他のメッセージを送信する前にS1が送信されるのを待つ必要があります(制御情報や実際のオーディオとビデオなどのデータ)
サーバーはS1を送信する前にC0が受信さ
れるまで待機する必要があります。サーバーはS2を送信する前にC1が受信される
まで待機する必要があります。サーバーは他の情報(制御情報)を送信する前にC2が受信されるまで待機する必要があります。および実際のオーディオとビデオ)データを待つ)
ハンドシェイクチャンクが毎回送信される場合、ハンドシェイクシーケンスは次のようになります。
握手の絵画的表現

実際の実装では、ハンドシェイクの認証機能を確保することで通信数を可能な限り減らすために、一般的な送信シーケンスは次のようになります。これは、wiresharkでffmpegプッシュパケットをキャプチャすることで確認できます
。クライアント/サーバー@ @
--- C0 + C1->
* - <-S0 + S1 + S2 - *
---- C2 ---->_

プルストリーム

playコマンドのメッセージフロー

プッシュエンド

ビデオストリームの公開におけるメッセージフロー

RTMP用語の定義

  • ペイロード:
    パケットに含まれるデータ(オーディオサンプルや圧縮ビデオデータなど)。ペイロードの形式と解釈は、このドキュメントの範囲を超えています。

  • パケット:
    データパケットは、固定ヘッダーとペイロードデータで構成されます。一部の基盤となるプロトコルでは、パケットのカプセル化を定義する必要がある場合があります。

  • メッセージストリーム:
    メッセージが流れる論理的な通信チャネル。

  • チャンク:
    メッセージの断片。メッセージは小さな部分に分割され、ネットワーク経由で送信される前にインターリーブされます。チャンクは、複数のストリームにわたって、タイムスタンプ順に並べられたすべてのメッセージのエンドツーエンド配信を保証します。

  • チャンクストリーム:
    特定の方向へのチャンクのフローを可能にする通信の論理チャネル。チャンクストリームは、クライアントからサーバーに移動し、その逆を行うことができます。

  • 多重化:
    個別のオーディオ/ビデオデータを1つのコヒーレントオーディオ/ビデオストリームに作成するプロセス。これにより、複数のビデオとオーディオを同時に送信できます。

  • アクションメッセージフォーマット(AMF):
    ActionScriptオブジェクトグラフをシリアル化するために使用されるコンパクトなバイナリフォーマット。AMFには、AMF 0 [AMF0]とAMF3 [AMF3]の2つのバージョンがあります。

詳細な握手合意

C0、S0フォーマット

C0では、このフィールドはクライアントによって要求されたRTMPバージョンを識別します。S0では、このフィールドはサーバーによって選択されたRTMPバージョンを識別します。この仕様で定義されているバージョンは3です。
占一バイト节、表达バージョン、一般是3。
C0およびS0ビット

C1、S1フォーマット

C1とS1は、長さが1536バイト、時間が4バイト、0が4バイト、ランダムデータが1528バイトです。
C1およびS1ビット

C2、S2フォーマット

C2とS2の長さは1536バイト、4バイトの時間はTime、4バイトの時間はTime2(S1、C1によって読み取られる時間)、1528バイトのランダムエコーには上記のランダムデータが含まれています。

C2およびS2ビット

RTMPチャンクストリーム

  • RTMPプロトコルは、送信時にデータ自体をフォーマットします。このフォーマットのメッセージはRTMPメッセージと呼ばれます。

  • 実際の送信では、情報の多重化、サブパッケージ化、および公平性を向上させるために、送信者はメッセージをメッセージIDを持つチャンクに分割します。各チャンクは個別のメッセージまたはメッセージの場合があります。一部として、受信側情報の送受信を実現するために、チャンクに含まれるデータの長さ、messageID、メッセージの長さに応じて、チャンクを完全なメッセージに復元します。

  • 分割することで、大量のデータを含むメッセージを小さな「メッセージ」に分割できます。これにより、優先度の低いメッセージが優先度の高いデータを継続的に送信およびブロックするのを防ぐことができます。たとえば、ビデオ送信中に、ビデオフレーム、オーディオが含まれます。フレームとRTMP制御情報。オーディオデータまたは制御データを送信し続けると、ビデオフレームがブロックされ、ビデオを視聴するときに最も厄介な遅延が発生する可能性があります。同時に、データ量が少ないメッセージの場合、チャンクヘッダーのフィールドを介して情報を圧縮できるため、情報の送信量を減らすことができます。

  • チャンクのデフォルトサイズは128バイトです。
    送信処理中、チャンクデータの最大量は、チャンクサイズの設定と呼ばれる制御情報を介して設定できます。送信側と受信側はそれぞれチャンクサイズを維持します。この値を設定して、自分で送信するチャンクを変更できます。最大サイズ。
    チャンクが大きいほど、各チャンクの計算時間が短縮され、CPU使用率が低下しますが、送信に時​​間がかかります。特に低帯域幅のネットワークの場合、後で送信するより重要な情報がブロックされる可能性があります。
    チャンクを小さくすると、この輻輳の問題を減らすことができますが、チャンクを小さくすると、追加情報が多すぎて(チャンクのヘッダー)、複数の送信が少ないと、送信が中断され、高帯域幅を十分に活用できなくなる可能性があります。したがって、高ビットレートのストリームでの送信には適していません。
    実際の送信では、送信するデータに異なるチャンクサイズを使用し、パケットキャプチャ分析などの方法で適切なチャンクサイズを取得し、現在の帯域幅情報とのサイズに応じてチャンクサイズを動的に調整する必要があります。送信中の実際の情報。CPU使用率を最大化し、情報がブロックされる可能性を減らすためのサイズ。

1.RTMPメッセージブロック

次の図に示すように、各チャンクはチャンクヘッダー+チャンクデータで
構成され、チャンクヘッダーは基本ヘッダー+メッセージヘッダー+拡張タイムスタンプで構成されます。

チャンクフォーマット

チャンク基本ヘッダー、1〜3バイト

  • このフィールドは、チャンクストリームIDとチャンクタイプをエンコードします。
    チャンクタイプは、エンコードされたメッセージヘッダーの形式を決定します。
    長さは、可変長フィールドであるチャンクストリームIDに完全に依存します。
    根チャンクストリームID来决定チャンク基本ヘッダーTTL度、1バイト节NL到3字节

  • プロトコルは、ID 3〜65599の最大65597ストリームをサポートします。ID0、1、および2は予約されています。値2のチャンクストリームIDは、低レベルのプロトコル制御メッセージおよびコマンド用に予約されています
    。RTMPプロトコルは3〜65599のみをサポートします。。複数のchunkID、合計65597ストリーム。0、1、2は予約されており、他のプロトコルの制御コマンドです。

  • 値0は、2バイト形式と64〜319(2番目のバイト+ 64)の範囲のIDを示します。
    値1は、3バイト形式と64〜65599((3番目のバイト)* 256 +2番目のバイト+64)の範囲のIDを示します。
    3〜63の範囲の値は、完全なストリームIDを表します。
    0表示2バイト节、1表示3バイト节、∥バイト表示1バイト节。

  • チャンクストリームID2-63は、このフィールドの1バイトバージョンでエンコードできます。
    1バイト

  • チャンクストリームID64〜319は、2バイト形式のヘッダーでエンコードできます。IDは次のように計算されます(2番目のバイト+ 64、即2 ^ 8 + 64)
    2バイト

  • チャンクストリームID64〜65599は、このフィールドの3バイトバージョンでエンコードできます。IDは((3番目のバイト)* 256 +(2番目のバイト)+ 64、即2 ^ 16 +64)として計算されます。
    3バイト

チャンクメッセージヘッダー、0、3、7、11バイト

  • このフィールドは、送信されているメッセージに関する情報を(全体的または部分的に)エンコードします。
    長さは、チャンク基本ヘッダーの「fmt」フィールドで決定できます。

  • fmt = 0、11バイト。
    このタイプは、チャンクストリーム
    の開始点であるチャンクストリームの開始時に使用する必要があります。
    タイプ0

  • fmt = 1、7バイト
    メッセージストリームIDは含まれません。このチャンクは、前のチャンクと同じストリームIDを取ります。
    streamIDのないチャンクデータは、前のチャンクのstreamIDと同じです。
    type1

  • fmt = 2、3バイト
    ストリームIDもメッセージ長も含まれていません。このチャンクのストリームIDとメッセージ長は前のチャンクと同じです。前のチャンク
    のstreamIDと長さは同じです。
    type3

  • fmt = 3、0バイト
    単一のメッセージがチャンクに分割される場合、最初のメッセージを除くメッセージのすべてのチャンクはこのタイプを使用する必要が
    ありますメッセージが最初のチャンクを除く複数のチャンクに分割される場合は、このタイプを使用します。

  • 注:オーディオおよびビデオデータを送信するときのメッセージタイプID

    • ヘッダーMessageTypeIDが0x8または0x9の場合、データ(チャンクデータ)はflvタグデータ(タグヘッダーなし)です。flv形式のカプセル化については、FLV形式の分析を参照してください。
    • 新しいタイプのMessageTypeIDを0x16として使用することもでき、データ(チャンクデータ)は完全なflvタグ(タグヘッダー+タグデータ)です。
    • メッセージストリームIDはリトルエンディアンストレージを使用します
    • RTMPはビッグエンディアンモードであるため、データ、ヘッダー、およびインタラクティブメッセージを送信するときにビッグエンディアンモードに入力する必要がありますが、リトルエンディアンモードになっているのはstreamIDのみです。

拡張タイムスタンプ、0または4バイト

Extended Timestampフィールドは、16777215(0xFFFFFF)より大きいタイムスタンプまたはタイムスタンプデルタをエンコードするために使用されます。
長さが3バイトを超える場合は、このヘッダーを使用します。

デルタがより大きいか(16進0xFFFFFFの)16777215に等しい場合、このフィールドは16777215、フル32ビットのデルタを符号化するために、拡張タイムスタンプフィールドの存在を指示していなければなりません。そうでない場合、このフィールドは、実際のデルタであるべきである。
場合は、読み取り3バイトのタイムスタンプは0xFFFFFF以上であり、拡張タイムスタンプが追加されているため、4バイトのタイムスタンプを再度読み取る必要があります。

チャンクデータ

構成された最大チャンクサイズまでのこのチャンクのペイロード。
このチャンクの実際のデータは、合意で合意された値です。
これは、Set Chunk Sizeプロトコル制御メッセージによって設定された値であり、デフォルト値は128バイトです。

2.RTMPメッセージ分類RTMPコマンドメッセージ

すべてのリファレンス:rtmp(4)プロトコル実装分析の深い理解

1.プロトコル制御メッセージ

  • MessageTypeの範囲は1〜7です。
    チャンクプロトコルの場合は1〜2
    、rtmpプロトコル自体の場合は3〜6、プロトコル制御メッセージが必要です。

  • メッセージストリームID = 0和チャンクストリームID = 2

    • MessageType = 1、チャンクサイズの設定ブロックサイズを設定し、新しいブロックサイズ(合計4バイト)を使用するようにピアに通知します。デフォルトのサイズは128バイトです
    • MessageType = 2、Abort Messageキャンセルメッセージは、ブロックの受信を待機しているピアに通知してメッセージを完了し、ブロックストリームの受信部分を破棄して、メッセージの処理をキャンセルするために使用されます(合計4バイト)。
    • MessageType = 3、Acknowledgement Acknowledgementメッセージ。クライアントまたはサーバーは、ウィンドウサイズに等しいバイト数を受信した後、相手に確認メッセージを送信します。ウィンドウサイズは、受信者から送信された確認メッセージが受信されない前に送信される最大バイト数です。サーバーは、接続の確立後にウィンドウサイズを送信します。このメッセージはシリアル番号を指定します。シリアル番号は、現在までに受信したバイト数です。合計4バイト。
    • MessageType = 4、ユーザー制御メッセージユーザー制御メッセージ。クライアントまたはサーバーはこのメッセージを送信して、他のユーザーに制御イベントを通知します。このメッセージには、イベントタイプとイベントデータが含まれています。メッセージデータの最初の2バイトは、イベントタイプを識別するために使用されます。イベントタイプの後はイベントデータです。イベントデータフィールドは可変長です。
    • MessageType = 5、Window Acknowledgement Size確認ウィンドウサイズ。クライアントまたはサーバーはこのメッセージを送信して、確認メッセージウィンドウサイズの合計4バイトを送信するように相手に通知します。
    • MessageType = 6、Set Peer Bandwidthピア帯域幅を設定します。クライアントまたはサーバーはこのメッセージを送信して、ピアの出力帯域幅を更新します。送信者は、制限タイプフィールド(1バイト)でメッセージをハード(0)、ソフト(1)、またはダイナミック(2)としてマークできます。ハード制限の場合、ピアは提供された帯域幅に従ってデータを送信する必要があります。ソフト制限の場合、ピアは帯域幅を柔軟に決定でき、送信者は帯域幅を制限できますか?動的制限の場合、帯域幅はハード制限またはソフト制限のいずれかになります。

2.音声メッセージ

MessageType = 8、オーディオメッセージ:
クライアントまたはサーバーは、オーディオデータを送信するためにこのメッセージを送信します。メッセージタイプ8、音声メッセージとして予約

3.ビデオメッセージ

MessageType = 9、ビデオメッセージ:
クライアントまたはサーバーは、このメッセージを使用してビデオデータを相手に送信します。メッセージタイプの値は9で、ビデオメッセージとして予約されています。

4.データメッセージ

MessageType = 15または18、データメッセージ:
クライアントまたはサーバーは、このメッセージを介してメタデータとユーザーデータを相手に送信します。
メタデータには、データの作成時間、期間、件名などの詳細が含まれます。
18のメッセージタイプはAMF0でコード化され、15のメッセージタイプはAMF3でコード化されます。

5.共有オブジェクトメッセージ

MessageType = 16または19、共有オブジェクトメッセージ:
共有オブジェクトは、複数のクライアントとインスタンス間で同期されるFLASHオブジェクト(名前と値のペアのコレクション)です。

6.コマンドメッセージ

MessageType = 17または20、コマンドメッセージ:
コマンドメッセージはすべてAMFでエンコードされます。AMFにはAMF0とAMF3の2つのタイプがあります。
コマンドメッセージは、コマンド名、送信ID、および名前付きオブジェクトで構成されます。名前付きオブジェクトは、一連のパラメーターで構成されています。

コマンドメッセージの種類は次のとおりです。

1. NetConnectionコマンド(接続レイヤーコマンド)

サーバーとクライアント間の接続を表す上位レベルのオブジェクト。4つのコマンドタイプが含まれています。

  • connect
    コマンドは最初にクライアントからサーバーに送信されます。つまり、接続したいのですが、接続を確立できますか?サーバーは「_result」または「_error」を含むコマンド名を返し、「_ result」を返します。これは、サーバーがサービスを提供でき、クライアントが次のステップに進むことができることを示します。「_Error」、サーバーがサービスを提供できないことは明らかです。

  • NetConnectionオブジェクトの呼び出しのcallメソッドは、受信側でリモートプロシージャコールを実行します。リモートメソッドの名前は、callコマンドのパラメータとして使用されます。
  • 閉じる
  • createStream
    クライアントは、このコマンドをサーバーに送信して、メッセージ通信用の論理チャネルを作成します。オーディオ、ビデオ、およびメタデータの配信は、createstreamコマンドによって確立されたストリームチャネルによって実行されます。

RTMPハンドシェイク後、最初に接続コマンドメッセージを送信します。コマンドに含まれる内容はプロトコルで指定されていません。実際の通信では、一部のコーデック情報を指定してAMF形式で送信する必要があります。
サーバーは_resultコマンドタイプのメッセージを返します。このメッセージのペイロードの長さは通常128バイト以下ですが、最新のnginx-rtmpで返されるメッセージの長さは128バイトを超えます。
メッセージのtransactionIDは、コマンドタイプメッセージを識別するために使用されます。サーバーから返された_resultメッセージは、transactionIDによってコマンドへの応答を区別するために使用できます。connectコマンドを送信した後、他のコマンドメッセージを送信する必要があります。それらのtransactionIDは同じではありません。

2. NetStreamコマンド(ストリーム接続のコマンド)

Netstreamは、NetConnectionに基づいて構築され、NetConnectionのcreateStreamコマンドによって作成され、特定のオーディオ、ビデオ、およびその他の情報を送信するために使用されます。
トランスポート層プロトコルに接続できるNetConnectionは1つだけですが、1つのNetConnectionが複数のNetStreamを確立して、データを送信するための異なるストリーミングチャネルを確立できます。
以下に、一般的に使用されるNetStreamコマンドの一覧を示します。コマンドを受信すると、サーバーはonStatusコマンドでクライアントに応答し、現在のNetStreamステータスを示します。
onStatusコマンドのメッセージ構造は次のとおりです。

  • プレイ
    プレイ
  • play2
    play2コマンドは、再生されたコンテンツのタイムラインを変更せずに、別のビットレートに切り替えることができます。サーバーは、play2コマンドで要求できる複数のコードレートの複数のファイルを維持します。
  • deleteStream
    は、NetStreamオブジェクトが破棄されると、ストリームの削除コマンドを送信します。
  • closeStream
  • receiveAudio
    NetStreamオブジェクトは、オーディオメッセージを送受信して、クライアントにオーディオを送信するかどうかをサーバーに通知します。
  • receiveVideo
    NetStreamオブジェクトは、receiveVideoメッセージを送信して、クライアントにビデオを送信するかどうかをサーバーに通知します。
  • 公開
    プッシュストリームの準備作業の最後のステップは、公開コマンドメッセージをサーバーに送信する公開ストリームです。このコマンドのメッセージストリームIDは、上記の作成ストリームの後にサーバーから返されるストリームIDです。これを送信した後コマンドを使用すると、通常、サーバーからの応答を待つ必要はありません。オーディオおよびビデオタイプのRTMPパケットを直接送信するだけです。
    一部のrtmpライブラリもsetMetaDataメッセージを送信します。このメッセージは送信することも送信しないこともできます。ビデオの解像度など、オーディオおよびビデオのメタデータ情報が含まれています。

  • ミリ秒単位で、ビデオまたはオーディオ内の位置を探します。クライアントは検索コマンドを送信して、メディアファイルまたはプレイリスト内のオフセットを検索します。
  • 一時停止
    クライアントはサーバーに再生を停止または再開するように指示し、クライアントは一時停止コマンドを送信してサーバーにコマンドを一時停止または開始するように指示します。

クライアントは、コマンドメッセージのreleaseStreamコマンドをサーバーに
送信します。クライアントは、コマンドメッセージのFCPublishコマンドをサーバーに
送信します。クライアントは、コマンドメッセージの「createStream」コマンドをサーバーに送信します。
サーバーは「createstream」コマンドを受信すると、コマンドメッセージで「result」(_ result)を送信して、クライアントにストリームのステータスを通知します。
サーバーから返されたメッセージを解析すると、ストリームIDが取得されます。これは、将来サーバーと通信されるメッセージストリームIDです。通常、1を返し、固定されていません。

7.メッセージの集約

MessageType = 22、Aggregate message、:
Aggregate messageは、メッセージリストを含む一種のメッセージです。メッセージタイプの値は22で、集約メッセージ用に予約されています。

3.コマンドメッセージフィードバック結果の受信ResponseCommand

ブロックメッセージによって運ばれるデータはメッセージコンテンツにスプライスされ、メッセージコンテンツはAMFを介して解釈されます
RTMPResponseCommandType

キャプチャー

パケットをキャプチャし、プロトコルとソースコードを比較することで、プロトコルをより明確に確認し、理解を深めることができます。
キャプチャー
image.png

総括する

この記事では、コードの理解を容易にするために、RTMPプロトコル関連の形式を整理します。

参考:徹底的に理解して
RTMP
RTMPはのIn学習ストリーミングプロトコル
RTMPの深い理解(4)プロトコルの実装分析
RTMP仕様の簡単な分析
公式ドキュメント
SRS-はlibrtmpを

おすすめ

転載: blog.csdn.net/u014099894/article/details/107976783