RTMP協議中文翻譯(首發)(轉)

 Adobe公司的實時消息傳輸協議

摘要

  此備忘錄描述了 Adobe公司的實時消息傳輸協議(RTMP),此協議從屬于應用層,被設計用來在適合的傳輸協議(如TCP)上復用和打包多媒體傳輸流(如音頻、視頻和互動內容)。

目錄

1.簡介
1.1.術語
2.貢獻者
3.定義
4.字節序,對齊,和時間格式
5.RTMP塊流
5.1.消息格式
5.2.握手
5.2.1.握手序列
5.2.2.C0和S0格式
5.2.3.C1和S1格式
5.2.4.C2和S2格式
5.2.5.握手流程圖
5.3.組塊
5.3.1.塊格式
5.3.1.1.塊的基本頭
5.3.1.2.塊的消息頭
5.3.1.2.1.類型0
5.3.1.2.2.類型1
5.3.1.2.3.類型2
5.3.1.2.4.類型3
5.3.1.2.5.常見的頭字段
5.3.1.3.擴展的時間戳
5.3.2.示例
5.3.2.1.示例1
5.3.2.2.示例2
5.4.協議控制消息
5.4.1.設置塊大小 (1)
5.4.2.中斷消息 (2)
5.4.3.應答 (3)
5.4.4.應答窗口大小 (5)
5.4.5.設置流帶寬 (6)
6.RTMP消息格式
6.1.RTMP消息格式
6.1.1.消息頭
6.1.2.消息有效數據
6.2.用戶控制消息 (4)
7.RTMP命令消息
7.1.消息類型
7.1.1.命令消息 (20, 17)
7.1.2.數據消息 (18, 15)
7.1.3.共享對象消息 (19, 16)
7.1.4.音頻消息 (8)
7.1.5.視頻消息 (9)
7.1.6.集合消息 (22)
7.1.7.用戶控制消息事件
7.2.命令類型
7.2.1.網絡連接命令
7.2.1.1.連接
7.2.1.2.調用
7.2.1.3.創建流
7.2.2.網絡流命令
7.2.2.1.播放
7.2.2.2.播放2
7.2.2.3.刪除流
7.2.2.4.接收音頻
7.2.2.5.接收視頻
7.2.2.6.發布
7.2.2.7.定位
7.2.2.8.暫停
7.3.消息交互示例
7.3.1.發布錄制的視頻
7.3.2.廣播共享對象消息
7.3.3.從錄制的流發布元數據
8.引用
作者的聯系方式

簡介

Adobe公司的實時消息傳輸協議(RTMP)提供了一套全雙工的可靠的多路復用消息服務,類似于TCP協議[RFC0793],用來在一對結點之間并行傳輸帶時間戳的音頻流,視頻流,數據流。通常情況下,不同類型的消息會被分配不同的優先級,當網絡傳輸能力受限時,優先級用來控制消息在網絡底層的排隊順序。

  當前文章描述了實時消息傳輸協議(RTMP)的語法和實現。

術語

當前文章中的這些關鍵字“MUST”“MUST NOT”“REQUIRED”“SHALL”“SHALL NOT”“SHOULD”“SHOULD NOT”“RECOMMENDED”“NOT RECOMMENDED”“MAY”“OPTIONAL”的說明請參照[RFC2119]中對應的描述。

貢獻者

Rajesh Mallipeddi,Adobe公司前員工,是這份規范的原始作者,并且提供了大部分的原始文本。
Mohit Srivastava,Adobe公司員工,為這份規范的完善做出了很大貢獻。

定義

有效數據
RTMP包中的數據,例如音頻采樣、壓縮后的視頻數據。有效數據的格式和說明不在本文中詳述。
備注:有效數據格式的定義請參考FLV定義。


一個數據包包括固定的包頭和有效數據。一些底層協議可能需要封裝包的定義。

端口
傳輸協議使用端口來區分同一個主機上的多個目標地址。TCP/IP協議根據正整數(端口號)來識別端口。OSI傳輸層使用的傳輸選擇器(TSEL)相當于端口。

傳輸地址
一個網絡地址和端口的組合,用來標識傳輸層的一端,例如IP地址和TCP端口。數據包從源地址傳輸到目的地址。

消息流
一個信息流的邏輯通信信道。

消息流ID
每條消息都有一個與之相關聯的ID,用來區分這條消息屬于哪個流。


消息的一個分片。消息在被發送到網絡之前,被分割成更小的部分。塊可以確保在多個流之間,使用基于時間戳的方式,端到端的交付所有消息。

塊流
一個邏輯通信信道,允許塊在一個特定的方向上流動。塊流可以從客戶機傳輸到服務器,也可以反向傳輸。

塊流ID
每個塊都有一個與之相關聯的ID,用來區分塊屬于哪個流。

多路復用
將獨立的音頻或視頻數據組合為連貫的音視頻數據流,使同時傳輸多個視頻和音頻成為可能。

多路分解
多路復用的逆向過程,將混合的音視頻數據拆分成獨立的音頻和視頻數據。

遠程過程調用(RPC)
允許客戶端或服務器請求對端調用程序或子程序。

元數據
描述數據。電影的元數據包括標題、時間、創建日期、等等。

應用實例
當客戶端發送連接請求到服務器時,會在服務器端建立一個應用實例。

動作消息格式(AMF)
一種緊湊的二進制格式,用來序列化AS對象。AMF有兩個版本:AMF0、AMF3。
注: AMF0代表早期的flex對象,AMF3代表flash對象;

字節序,對齊,和時間格式

所有的整形字段使用網絡字節序的方式傳輸,第零字節位于第一位,第零比特是雙字節或字段的標志位。這種節字排序方式通常稱為大端。傳輸順序的描述詳見IP協議[RFC0791]。除非特別聲明,本文中的數字一律為十進制。
注: 網絡字節序為大端排序方式。

除非特別說明,RTMP協議中的數據都以字節對齊。例如,一個16比特數字可能位于奇數偏移字節。涉及到追加數據的,追加字節應該為零。

RTMP的時間戳,是以毫秒為單位的整型數,使用相對時間。通常,每個流以零作為時間戳的起始,但這不是必需的,只要他們的基準時間一樣即可。注意,這意味著,任何同步傳輸的多個流(特別是單一主機)的時間戳需要在RTMP協議外做一些額外處理。

時間戳是一個32位整型數,使用周期為49天17時2分47.296秒。由于,流允許連續傳輸數年時間,RTMP應用程序在處理時間戳時,應該使用序列號算法[RFC1982]。例如,應用程序假設所有相鄰的時間戳都在1到2^32毫秒之間,比如4000000000后面跟著10000,3000000000在4000000000的前面。

時間戳增量是相對于前一個時間戳的無符號整型數。時間戳增量可以是24位或者32位。

RTMP塊流

本講述了實時消息傳遞協議塊流(RTMP塊流)。它作為一款高級多媒體流協議提供了流的多路復用和打包服務。RTMP塊流被設計用來傳輸實時消息協議(第6章),它可以使用任何協議來發送消息流。每個消息都包含時間戳和有效類型標識。RTMP塊流和RTMP適用于各種視聽傳播的應用程序,包括一對一的,和一對多的視頻直播、點播服務、互動會議應用程序。

當使用一個可靠的傳輸協議如TCP[RFC0793]時,RTMP塊流提供了一種可以在多個流中,基于時間戳的端到端交付所有消息的方法。RTMP塊流不提供任何優先級或類似形式的控制,但可以使用更高級別的協議來提供這樣的優先級。例如,一個視頻服務器可以根據發送的時間或確認每個消息的時間,來決定為一個網絡差的用戶丟棄視頻信息,以確保音頻信息的及時接收。

RTMP塊流不僅包含了自己的協議控制信息,同時也提供了一個更高級別的協議機制,用來嵌入用戶自定義控制信息。

消息格式

消息格式可以被分割成多個塊,用來在更高的協議中支持多路復用。在創建塊消息格式時,應該包含以下字段:

時間戳
消息的時間戳。這個字段占用4字節。

長度
消息的有效長度。如果消息頭不能被忽略,它應該包括長度。這個字段在塊頭中占用3字節。

類型ID
各種類型的協議控制消息的ID。這些消息使用RTMP塊流協議和更高級別的協議來傳輸信息。所有其他類型的ID可以用在高級協議,這對于RTMP塊流來說,是不透明的。事實上,RTMP塊流中沒有要求使用這些值作為類型;所有(無協議的)消息可能是相同的類型,或者應用程序使用這個字段來區分多個連接,而不是類型。這個字段在塊頭中占用1字節。

消息流ID
消息流ID可以是任意值。當同一個塊流被復用到不同的消息流中時,可以通過消息流ID來區分它們。另外,對于RTMP塊流而言,這是一個不透明值。該字段占用4字節,使用小端序。

握手

RTMP連接從握手開始。它包含三個固定大小的塊,不像其他的協議,是由頭部大小可變的塊組成的。

客戶端(初始化連接的一端)和服務端發送同樣的三個塊。為了方便描述,客戶端發送的三個塊命名為C0,C1,C2;服務端發送的三個塊命名為S0,S1,S2。

握手序列

客戶端通過發送C0和C1消息來啟動握手過程。客戶端必須接收到S1消息,然后發送C2消息。客戶端必須接收到S2消息,然后發送其他數據。

服務端必須接收到C0或者C1消息,然后發送S0和S1消息。服務端必須接收到C1消息,然后發送S2消息。服務端必須接收到C2消息,然后發送其他數據。

C0和S0格式

C0和S0包由一個字節組成,下面是C0/S0包內的字段:

??????????????????????????????0?1?2?3?4?5?6?7 ?????????????????????????????+-+-+-+-+-+-+-+-+ ?????????????????????????????|???version?????| ?????????????????????????????+-+-+-+-+-+-+-+-+ ??????????????????????????????C0?and?S0?bits

1-4B 版本

版本(8比特)
在C0包內,這個字段代表客戶端請求的RTMP版本號。在S0包內,這個字段代表服務端選擇的RTMP版本號。此文檔使用的版本是3。版本0-2用在早期的產品中,現在已經被棄用;版本4-31被預留用于后續產品;版本32-255(為了區分RTMP協議和文本協議,文本協議通常以可打印字符開始)不允許使用。如果服務器無法識別客戶端的版本號,應該回復版本3。客戶端可以選擇降低到版本3,或者中止握手過程。

C1和S1格式

C1和S1包長度為1536字節,包含以下字段:

??????0???????????????????1???????????????????2???????????????????30?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 ?????+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ?????|????????????????????????time?(4?bytes)?????????????????????????| ?????+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ?????|????????????????????????zero?(4?bytes)?????????????????????????| ?????+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ?????|????????????????????????random?bytes???????????????????????????| ?????+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ?????|?????????????????????????random?bytes??????????????????????????| ?????|????????????????????????????(cont)?????????????????????????????| ?????|?????????????????????????????....??????????????????????????????| ?????+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ??????????????????????????????C1?and?S1?bits

1-4B 時間
5-8B 零
9-1536B 其他數據

時間(4字節)
本字段包含一個時間戳,客戶端應該使用此字段來標識所有流塊的時刻。時間戳取值可以為零或其他任意值。為了同步多個塊流,客戶端可能希望多個塊流使用相同的時間戳。

零(4字節)
本字段必須為零。

隨機數據(1528字節)
本字段可以包含任意數據。由于握手的雙方需要區分另一端,此字段填充的數據必須足夠隨機(以防止與其他握手端混淆)。不過沒必要為此使用加密數據或動態數據。

C2和S2格式

C2和S2包長度為1536字節,作為C1和S1的回應,包含以下字段:

??????0???????????????????1???????????????????2???????????????????30?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 ?????+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ?????|????????????????????????time?(4?bytes)?????????????????????????| ?????+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ?????|???????????????????????time2?(4?bytes)?????????????????????????| ?????+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ?????|????????????????????????random?echo????????????????????????????| ?????+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ?????|?????????????????????????random?echo???????????????????????????| ?????|????????????????????????????(cont)?????????????????????????????| ?????|?????????????????????????????....??????????????????????????????| ?????+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ??????????????????????????????C2?and?S2?bits

1-4B 時間
5-8B 時間
9-1536B 其他數據

時間(4字節)
本字段必須包含對端發送的時間戳。

時間(4字節)
本字段必須包含時間戳,取值為接收對端發送過來的握手包的時刻。

隨機數據(1528字節)
本字段必須包含對端發送過來的隨機數據。握手的雙方可以使用時間1和時間2字段來估算網絡連接的帶寬和/或延遲,但是不一定有用。

握手過程示意圖

         +-------------+                           +-------------+|    Client   |       TCP/IP Network | Server | +-------------+ | +-------------+ | | | Uninitialized | Uninitialized | C0 | | |------------------->| C0 | | |-------------------->| | C1 | | |------------------->| S0 | | |<--------------------| | | S1 | Version sent |<--------------------| | S0 | | |<-------------------| | | S1 | | |<-------------------| Version sent | | C1 | | |-------------------->| | C2 | | |------------------->| S2 | | |<--------------------| Ack sent | Ack Sent | S2 | | |<-------------------| | | | C2 | | |-------------------->| Handshake Done | Handshake Done | | | Pictorial Representation of Handshake [譯]握手示意圖

下面是握手示意圖中提到的狀態:

未初始化
協議版本號在此階段發送。客戶端和服務器均處于未初始化狀態。客戶端發送攜帶協議版本號的C0包。如果服務器支持此版本,回復S0和S1包。如果服務器不支持此版本,使用適當的動作回復。在RTMP協議中,此動作是中止連接。
注: 在"C0和S0格式"章節中提及,如果服務器不支持客戶端的版本號,可以選擇降到版本3或中止。

發送版本
客戶端和服務器雙方在未初始化狀態后,會進入發送版本狀態。之后,客戶端等待S1包,服務器等待C1包。待接收到數據包,客戶端發送C2包,服務器發送S2包。然后,雙方都進入答復狀態。客戶端等待C2的答復,服務器等待S2的答復。

握手完成
客戶端和服務器交換消息。

組塊

握手完成之后,此連接可以復用于一到多個塊流。每個塊流攜帶一個消息流的某種類型的消息。塊通過網絡進行傳輸。傳輸過程中,每個塊必須被完整的發送后,才能發送下一個塊。接收端接收完成之后,根據塊流ID把塊組裝成完整的消息。

塊允許把高級協議的大消息分割成更小的消息分片,例如為了防止低優先級的大消息(如視頻消息)阻礙高優先級的小消息(如音頻和控制消息)。

塊允許以更少的開銷來發送小消息,減少開銷的方法是壓縮必須攜帶的塊頭的數據。

塊的大小是可配置的。配置的方法詳見5.4.1章節的設置塊大小控制消息。大的塊消息可以減少CPU使用率,但是在帶寬比較小時會導致其他內容的延遲。小的塊消息不利于高碼率流的傳輸。流的每一個方向都可以配置獨立的塊大小。

塊格式

每一個塊包含了頭和數據。塊頭包含了三個部分:

   +--------------+----------------+--------------------+--------------+| Basic Header | Message Header | Extended Timestamp | Chunk Data | +--------------+----------------+--------------------+--------------+ | | |<------------------- Chunk Header ----------------->| Chunk Format

基本頭(1-3字節)
這個字段包含塊流ID和塊類型。塊類型決定了編碼過的消息頭的格式。這個字段是一個變長字段,長度取決于塊流ID。

消息頭(0,3,7,11字節)
這個字段包含被發送的消息信息(無論是全部,還是部分)。字段長度由塊頭中的塊類型來決定。

擴展時間戳(0,4字節)
這個字段是否存在取決于塊消息頭中編碼的時間戳。更多詳情參考5.3.1.3章節。

塊數據(可變大小)
當前塊的有效數據,上限為配置的最大塊大小。

塊的基本頭

塊的基本頭包含塊流ID和塊類型(下面的fmt字段)。塊類型代表了編碼過的消息頭的格式。此字段根據塊流ID的不同,長度可能為1,2或3字節。

在實現協議時,此字段應該使用可以容納ID的最小長度。

此協議支持最多65597個流,ID從3到65599。0,1,2這三個為保留ID。當塊的基本頭長度為2字節時,第3-8比特取值為0。當長度為3字節時,第3-8比特取值為1。塊流ID為2時保留作為低級協議的控制消息和命令消息。

1字節長度的基本頭包含了2到63的塊流ID。

                              0 1 2 3 4 5 6 7 +-+-+-+-+-+-+-+-+ |fmt| cs id | +-+-+-+-+-+-+-+-+ Chunk basic header 1

2字節長度的基本頭包含了64到319的塊流ID。塊流ID的計算方法為,第2個字節加上64。

                      0                   10 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |fmt| 0 | cs id - 64 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Chunk basic header 2

3字節長度的基本頭包含了64到65599的塊流ID。塊流ID的計算方法為,第3個字節乘以256,加上第2個字節,再加上64。

          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |fmt| 1 | cs id - 64 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Chunk basic header 3

塊流ID(6比特)
本字段包含了從2到63的塊流ID。當塊的基本頭長度為2字節時,此字段取值為0。當塊的基本頭長度為3字節時,此字段取值為1。

類型(2比特)
本字段標識了塊消息頭的類型。塊消息頭的4種類型,會在下一小節中說明。

塊流ID(8或16比特)
本字段的取值為塊流ID減去64。例如,塊流ID為365的存儲方式為,第3-8比特為1,第9-24比特為301。

64-319之間的塊流ID,既可以使用2字節頭長度,也可以使用3頭長度。不過前面曾經提到過“在實現協議時,此字段應該使用可以容納ID的最小長度”,因此應該選擇使用2字節頭長度。

塊的消息頭

根據塊的基本頭中類型字段的取值不同,塊的消息頭有4種類型。

在實現協議時,此字段應該使用可以容納消息頭的最小長度。

類型0

類型為0的消息頭長度為11字節。塊流必須以這種類型的消息開始,當塊流的時間戳回環時,也必須以這種類型的消息開始。

      0                   1                   2                   30 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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | timestamp |message length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | message length (cont) |message type id| msg stream id | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | message stream id (cont) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Chunk Message Header - Type 0

時間戳(3字節)
類型為0的塊,此字段必須為絕對時間戳。如果時間戳大于等于16777215(0xFFFFFF),此字段的取值必須為16777215,并且與擴展時間戳一起組成32比特的完整時間戳。如果時間戳小于16777215,那么此字段代表了完整的時間戳。

類型1

類型為1的消息頭長度為7字節。不包含消息流ID;當前塊和上一個塊使用相同的流ID。擁有可變大小消息(視頻數據)的流應該首個消息之后,在每個消息的第1個塊使用這種類型。

      0                   1                   2                   30 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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | timestamp delta |message length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | message length (cont) |message type id| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Chunk Message Header - Type 1
類型2

類型為2的消息頭長度為3字節。不包含消息流ID或消息長度;當前塊和上一個塊使用相同的流ID和流長度。擁有固定大小消息(音頻或其他數據)的流應該在首個消息之后,在每個消息的第1個塊使用這種類型。

              0                   1                   20 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | timestamp delta | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Chunk Message Header - Type 2
類型3

類型為3的塊沒有消息頭。消息頭內的相關字段都不存在。當前塊和上一個塊使用相同的流ID,長度和時間間隔。

當一個獨立的消息被分割成塊時,從第二個塊開始使用這種類型。第5.3.2.2章節的示例2展示了這種情況。

如果流由完全相同大小的消息,流ID,間隔時間組成時,應該在類型為2的塊之后使用這種類型。第5.3.2.1章節的示例1展示了這種情況。

如果第一個和第二個消息之間的時間間隔和第一個消息的時間戳相同,那么類型為0的塊后面跟隨類型為3的塊,沒有必要再使用類型為2的塊來標識時間間隔。

如果類型為0的塊后面跟隨著類型為3的塊,那么類型為3的塊的時間間隔與類型為1的塊的時間戳相同。

常見的頭字段

塊消息頭里面的每個字段的描述:

時間間隔(3字節)
類型為1或2的塊里,本字段代表當前塊和上一個塊的時間戳之差。如果時間間隔大于等于16777215(0xFFFFFF),此字段的取值必須為16777215,并且與擴展時間戳一起組成32比特的完整時間戳。如果時間戳小于16777215,那么此字段代表了完整的時間戳。

消息長度(3字節)
類型為0或1的塊里,本字段代表消息的長度。這個值通常情況下跟塊的有效數據長度是不相等的。塊的有效數據長度是塊大小的最大值。

消息類型ID(1字節)
類型為0或1的塊里,本字段代表消息的類型。

消息流ID(4字節)
類型為0的塊里,本字段代表消息流的ID。并使用小端方式存儲。通常情況下,相同塊流里面的消息來自于相同的消息流。由于消息頭的壓縮,可能導致獨立的消息流被混合到相同的塊流。無論如何,如果關閉了一個消息流,又打開了另一個,那么已經存在的塊流不能被用于發送新的類型為0的塊。

擴展的時間戳

擴展的時間戳字段用來表示時間戳或時間間隔取值大于16777215(0xFFFFFF)的。也就是說,類型為0或1或2的塊中,時間戳或時間間隔的取值超出了24比特。本字段與之前的時間字段一起構成完整的32比特時間戳或時間間隔。完整時間值的前一部分(24比特)位于類型為0的塊的時間戳字段,或類型為1或2的時間間隔字段,取值為16777215(0xFFFFFF)。類型為3的塊中,擴展時間戳字段與上一個塊中(可能為類型0或1或2)的擴展時間戳相等。

示例

示例1

本示例展示了一個音頻消息流。流中包含有冗余信息。

     +---------+-----------------+-----------------+-----------------+|         |Message Stream ID| Message Type ID | Time  | Length  |+---------+-----------------+-----------------+-------+---------+| Msg # 1 |    12345        |         8 | 1000 | 32 | +---------+-----------------+-----------------+-------+---------+ | Msg # 2 | 12345 | 8 | 1020 | 32 | +---------+-----------------+-----------------+-------+---------+ | Msg # 3 | 12345 | 8 | 1040 | 32 | +---------+-----------------+-----------------+-------+---------+ | Msg # 4 | 12345 | 8 | 1060 | 32 | +---------+-----------------+-----------------+-------+---------+ Sample audio messages to be made into chunks

下面的表格展示了由此音頻流產生的塊信息。從第3條消息開始,數據傳輸達到最大優化。每條消息的頭部只增加了1字節長度。

      +--------+---------+-----+------------+------- ---+------------+|        | Chunk   |Chunk|Header Data |No.of Bytes|Total No.of | | |Stream ID|Type | | After |Bytes in the| | | | | |Header |Chunk | +--------+---------+-----+------------+-----------+------------+ |Chunk#1 | 3 | 0 | delta: 1000| 32 | 44 | | | | | length: 32,| | | | | | | type: 8, | | | | | | | stream ID: | | | | | | | 12345 (11 | | | | | | | bytes) | | | +--------+---------+-----+------------+-----------+------------+ |Chunk#2 | 3 | 2 | 20 (3 | 32 | 36 | | | | | bytes) | | | +--------+---------+-----+----+-------+-----------+------------+ |Chunk#3 | 3 | 3 | none (0 | 32 | 33 | | | | | bytes) | | | +--------+---------+-----+------------+-----------+------------+ |Chunk#4 | 3 | 3 | none (0 | 32 | 33 | | | | | bytes) | | | +--------+---------+-----+------------+-----------+------------+ Format of each of the chunks of audio messages

示例2

本示例展示了一條長消息,由于消息的長度超過了塊的最大長度(128字節),此消息在傳輸時將被分割成若干個塊。

   +-----------+-------------------+-----------------+-----------------+|           | Message Stream ID | Message Type ID | Time  | Length  |+-----------+-------------------+-----------------+-----------------+| Msg # 1   |       12346       |    9 (video)    | 1000  |   307   |+-----------+-------------------+-----------------+-----------------+Sample Message to be broken to chunks

下面是消息分割后產生的塊:

       +-------+------+-----+-------------+-----------+------------+|       |Chunk |Chunk|Header       |No. of |Total No. of| | |Stream| Type|Data |Bytes after| bytes in | | | ID | | | Header | the chunk | +-------+------+-----+-------------+-----------+------------+ |Chunk#1| 4 | 0 | delta: 1000 | 128 | 140 | | | | | length: 307 | | | | | | | type: 9, | | | | | | | stream ID: | | | | | | | 12346 (11 | | | | | | | bytes) | | | +-------+------+-----+-------------+-----------+------------+ |Chunk#2| 4 | 3 | none (0 | 128 | 129 | | | | | bytes) | | | +-------+------+-----+-------------+-----------+------------+ |Chunk#3| 4 | 3 | none (0 | 51 | 52 | | | | | bytes) | | | +-------+------+-----+-------------+-----------+------------+ Format of each of the chunks

第一個塊的頭數據顯示了消息的長度為307字節。

在這兩個示例中,類型為3的塊有兩種使用方式。第一種是說明消息的繼續。第二種是說明新消息的頭信息可以由前面已經存在的消息推導出來。

協議控制消息

RTMP塊流使用消息類型ID 1、2、3、5、6作為控制消息。這些消息包含了必要的RTMP塊流協議信息。

這些協議控制消息必須使用0作為消息流ID(作為已知的控制流ID),同時使用2作為塊流ID。協議控制消息接收立即生效;解析時,時間戳字段被忽略。

設置塊大小 (1)

協議控制消息(1),設置塊大小,被用來通知對方新的最大的塊大小。

默認最大的塊大小為128字節,客戶端和服務器可以使用此消息來修改默認的塊大小。例如,假設客戶端想要發送的音頻數據大小為131字節,而塊大小為128字節。在這種情況下,客戶端可以通知服務器新的塊大小為131字節,然后就可以使用一個塊來發送完整的音頻數據了。

最大的塊大小至少為128字節,塊至少攜帶1個字節的內容。通信的每一個方向(例如從客戶端到服務器)擁有獨立的塊大小設置。

      0                   1                   2                   30 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+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|0|                     chunk size (31 bits)                    |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+Payload for the ‘Set Chunk Size’ protocol message

0
當前比特位必須為零。

chunk size (31 bits): This field holds the new maximum chunk size,
in bytes, which will be used for all of the sender’s subsequent
chunks until further notice. Valid sizes are 1 to 2147483647
(0x7FFFFFFF) inclusive; however, all sizes greater than 16777215
(0xFFFFFF) are equivalent since no chunk is larger than one
message, and no message is larger than 16777215 bytes.
塊大小(31比特)
本字段標識了新的最大塊大小,以字節為單位,發送端之后將使用此值作為最大的塊大小。本字段的有效值為1-2147483647(0x7FFFFFFF),由于消息的最大長度為16777215(0xFFFFFF),而一個塊最多只能攜帶一條消息,因此本字段的實際有效值為1-16777215(0xFFFFFF)。

中斷消息 (2)

協議控制消息(2),中斷消息,用來通知通信的對方,如果正在等待一條消息的部分塊(已經接收了一部分),那么可以丟棄之前已經接收到的塊。通信的一方將接收到塊流ID作為當前協議消息的有效數據。應用程序可以發送此消息來通知對方,當前正在傳輸的消息沒有必要再處理了。

      0                   1                   2                   30 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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | chunk stream id (32 bits) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Payload for the ‘Abort Message’ protocol message

塊流ID(32比特)
本字段包含了塊流ID,用來標識哪個塊流ID的消息將被丟棄。

應答 (3)

客戶端和服務器在接收到與接收窗口大小相等的數據后,必須發送答應消息給對方。窗口大小的定義為發送方在接收到接收方的任何應答前,可以發送的最大數據量。本消息包含了序列號,序列號為截止目前接收到的數據總和,以字節為單位。

      0                   1                   2                   30 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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | sequence number (4 bytes) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Payload for the ‘Acknowledgement’ protocol message

序列號(32比特)
本字段包含了截止目前接收到的數據總和,以字節為單位。

應答窗口大小 (5)

客戶端和服務器發送這個消息來通知對方答應窗口的大小。發送方在發送了等于窗口大小的數據之后,等待接收對方的應答消息(在接收到答應之前停止發送數據)。接收方必須發送應答消息,在會話開始時,或從上一次發送應答之后接收到了等于窗口大小的數據。

      0                   1                   2                   30 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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Acknowledgement Window size (4 bytes) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Payload for the ‘Window Acknowledgement Size’ protocol message

設置流帶寬 (6)

客戶端和服務器發送此消息來說明對方的出口帶寬限制。接收方以此來限制自己的出口帶寬,即限制未被答應的消息數據大小。接收到此消息的一方,如果窗口大小與上次發送的不一致,應該回復答應窗口大小的消息。

      0                   1                   2                   30 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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Acknowledgement Window size | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Limit Type | +-+-+-+-+-+-+-+-+ Payload for the ‘Set Peer Bandwidth’ protocol message

限制類型的取值為下面之一:

硬限制(0)
應該限制出口帶寬為指明的窗口大小。

軟限制(1)
應該限制出口帶寬為指明的窗口大小,或已經生效的小一點的窗口大小。

動態限制(2)
如果上一次為硬限制,此消息被視為硬限制,否則忽略此消息。

RTMP消息格式

本章描述了RTMP消息的格式,使用網絡傳輸層在兩個實體端之間做數據傳輸,例如RTMP塊流。由于RTMP協議基于RTMP塊流,因此可以適配任何傳輸協議。RTMP塊流和RTMP相結合,可以廣泛的使用于音視頻應用,點對點,點對多的廣播應用,點播服務,以及交互式會議應用。

RTMP消息格式

服務器和客戶端通過網絡發送RTMP消息來和對方交流。消息可以包含音頻,視頻,或其他消息。

RTMP消息有兩部分組成,頭部和有效數據。

消息頭

消息頭部包含以下字段:

消息類型
消息類型,1字節長度。從1到6的ID被保留用于協議控制消息。

長度
消息的有效數據大小,3字節長度。使用大端方式。

時間戳
消息的時間戳,4字節長度。使用大端方式。

消息流ID
消息流標識,3字節長度。使用大端方式。

      0                   1                   2                   30 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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Message Type | Payload length | | (1 byte) | (3 bytes) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Timestamp | | (4 bytes) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Stream ID | | (3 bytes) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Message Header

消息的有效數據

RTMP消息的另一部分是有效數據,存放的是真正的消息數據內容。例如,一些音頻采樣,或壓縮過的視頻數據。有關數據的格式和解釋不在本章節說明。

用戶控制消息 (4)

用戶控制消息的類型為4。此消息位于RTMP協議流層。RTMP塊流使用消息類型ID 1、2、3、5、6作為控制消息(見第5.4章)。

用戶控制消息應該使用0作為消息流ID,當通過RTMP塊流發送此消息時,塊流ID為2。RTMP流中的用戶控制消息在接收時立即生效,消息中的時間戳被忽略。

客戶端或服務器發送此消息用來通知對方用戶控制事件。此消息包含事件類型和事件數據。

         +------------------------------+------------------------|     Event Type (16 bits)     | Event Data+------------------------------+-------------------------Payload for the ‘User Control’ protocol message

用戶控制消息的前2個字節數據用來標識事件類型。事件類型后面是事件數據。事件數據字段是可變的。由于此消息是通過RTMP塊流層發送的,塊大小的最大值(第5.4.1章節)應該滿足在一個塊里包含此消息。

有關事件類型和事件數據格式的說明見第7.1.7章節。

RTMP命令消息

這部分描述了服務器和客戶端之間交互使用到的不同類型的消息和命令。

服務器和客戶端之間交互的消息類型包括:用于發送音頻數據的音頻消息,用于發送視頻數據的視頻消息,用于發送用戶自定義數據、共享對象和命令的數據消息。共享對象提供了一種通用的方式來管理多個客戶端和服務器之間的分布式消息。命令消息使用AMF編碼的命令在客戶端和服務器之間交互。客戶端或服務器可以通請求遠程過程調用(RPC),使用命令消息和對方交流。

消息類型

服務器和客戶端通過網絡進行消息交互。消息可以是音頻消息、視頻消息、命令消息、共享對象消息、數據消息和用戶自定義消息。

命令消息(20, 17)

服務器和客戶端之間使用AMF編碼的命令消息交互。命令消息在AMF0編碼中,類型為20;在AMF3編碼中,類型為17。一些命令消息被用來發送操作指令,比如connect, createStream, publish, play, pause。另外一些命令消息被用來通知發送方請求命令的狀態,比如onstatus, result等。一條命令消息包括命令名稱、交互ID、包含相關參數的命令對象。服務器和客戶端通過在創建的流中遠程調用的方式,使用命令消息來進行交互。

數據消息 (18, 15)

客戶端或服務器使用此消息來發送元數據或其他用戶數據。元數據包含了(音視頻)數據的細節信息,像流的創建時間,時間點,主題等等。數據消息在AMF0編碼中,類型為18;在AMF3編碼中,類型為15。

共享對象消息 (19, 16)

共享對象是Flash對象,可以通過多客戶端,實例同步傳輸。在AMF0編碼中,類型為19;在AMF3編碼中,類型為16。每個消息可以包含多個事件。

   +------+------+-------+-----+-----+------+-----+ +-----+------+-----+|Header|Shared|Current|Flags|Event|Event |Event|.|Event|Event |Event| | |Object|Version| |Type |data |data |.|Type |data |data | | |Name | | | |length| |.| |length| | +------+------+-------+-----+-----+------+-----+ +-----+------+-----+ | | |<- - - - - - - - - - - - - - - - - - - - - - - - - - - - - >| | AMF Shared Object Message body | The shared object message format

下面是共享消息支持的事件類型:

    +---------------+--------------------------------------------------+|    Event      |                   Description                    |+---------------+--------------------------------------------------+| Use(=1)       | The client sends this event to inform the server | | | about the creation of a named shared object. | +---------------+--------------------------------------------------+ | Release(=2) | The client sends this event to the server when | | | the shared object is deleted on the client side. | +---------------+--------------------------------------------------+ | Request Change| The client sends this event to request that the | | (=3) | change the value associated with a named | | | parameter of the shared object. | +---------------+--------------------------------------------------+ | Change (=4) | The server sends this event to notify all | | | clients, except the client originating the | | | request, of a change in the value of a named | | | parameter. | +---------------+--------------------------------------------------+ | Success (=5) | The server sends this event to the requesting | | | client in response to RequestChange event if the | | | request is accepted. | +---------------+--------------------------------------------------+ | SendMessage | The client sends this event to the server to | | (=6) | broadcast a message. On receiving this event, | | | the server broadcasts a message to all the | | | clients, including the sender. | +---------------+--------------------------------------------------+ | Status (=7) | The server sends this event to notify clients | | | about error conditions. | +---------------+--------------------------------------------------+ | Clear (=8) | The server sends this event to the client to | | | clear a shared object. The server also sends | | | this event in response to Use event that the | | | client sends on connect. | +---------------+--------------------------------------------------+ | Remove (=9) | The server sends this event to have the client | | | delete a slot. | +---------------+--------------------------------------------------+ | Request Remove| The client sends this event to have the client | | (=10) | delete a slot. | +---------------+--------------------------------------------------+ | Use Success | The server sends this event to the client on a | | (=11) | successful connection. | +---------------+--------------------------------------------------+

音頻消息 (8)

客戶端或服務器使用此消息來發送音頻消息。此消息的類型為8。

視頻消息 (9)

客戶端或服務器使用此消息來發送視頻消息。此消息的類型為9。

集合消息 (22)

集合消息是一個獨立消息,包含了一系列的RTMP消息,格式描述見6.1章。此消息的類型為22。

集合消息由消息頭和消息內容組成。
消息內容由子消息組成,子消息由消息頭,消息數據,回放指針組成。

                   +---------+-------------------------+| Header  | Aggregate Message body  |+---------+-------------------------+The Aggregate Message format+--------+-------+---------+--------+-------+---------+ - - - -|Header 0|Message|Back     |Header 1|Message|Back     ||        |Data 0 |Pointer 0| |Data 1 |Pointer 1| +--------+-------+---------+--------+-------+---------+ - - - - The Aggregate Message body format

集合消息的消息流ID覆蓋此消息內的子消息流的ID。

集合消息和第一個子消息的時間戳之間的偏移量,用來將子消息的時間戳處理為流的時間刻度。每個子消息的時間戳可以通過添加偏移量來處理為正常的流時間。第一個子消息的時間戳應該和集合消息的時間戳相同,因此偏移量應該為零。

反向指針包含了以前的消息(包含頭信息)的大小。集合消息包含此字段,一是為了適配FLV文件格式,二是為了回放定位。

使用集合消息有如下幾個優勢:

塊流在一個塊內至多可以攜帶一條完整的消息。使用集合消息之后,不僅可以增加塊大小,同時還減少了發送的塊數量。

集合消息的子消息可以連續的存儲在內存中。當系統調用網絡發送數據時更高效。

用戶控制消息事件

客戶端或服務器通過發送此消息來通知對方用戶控制事件。此消息的格式信息詳見第6.2章節。

用戶控制事件支持如下類型:

流開始事件(0)

    +---------------+--------------------------------------------------+|     Event     |                   Description                    |+---------------+--------------------------------------------------+|Stream Begin   | The server sends this event to notify the client | | (=0) | that a stream has become functional and can be | | | used for communication. By default, this event | | | is sent on ID 0 after the application connect | | | command is successfully received from the | | | client. The event data is 4-byte and represents | | | the stream ID of the stream that became | | | functional. | +---------------+--------------------------------------------------+ | Stream EOF | The server sends this event to notify the client | | (=1) | that the playback of data is over as requested | | | on this stream. No more data is sent without | | | issuing additional commands. The client discards | | | the messages received for the stream. The | | | 4 bytes of event data represent the ID of the | | | stream on which playback has ended. | +---------------+--------------------------------------------------+ | StreamDry | The server sends this event to notify the client | | (=2) | that there is no more data on the stream. If the | | | server does not detect any message for a time | | | period, it can notify the subscribed clients | | | that the stream is dry. The 4 bytes of event | | | data represent the stream ID of the dry stream. | +---------------+--------------------------------------------------+ | SetBuffer | The client sends this event to inform the server | | Length (=3) | of the buffer size (in milliseconds) that is | | | used to buffer any data coming over a stream. | | | This event is sent before the server starts | | | processing the stream. The first 4 bytes of the | | | event data represent the stream ID and the next | | | 4 bytes represent the buffer length, in | | | milliseconds. | +---------------+--------------------------------------------------+ | StreamIs | The server sends this event to notify the client | | Recorded (=4) | that the stream is a recorded stream. The | | | 4 bytes event data represent the stream ID of | | | the recorded stream. | +---------------+--------------------------------------------------+ | PingRequest | The server sends this event to test whether the | | (=6) | client is reachable. Event data is a 4-byte | | | timestamp, representing the local server time | | | when the server dispatched the command. The | | | client responds with PingResponse on receiving | | | MsgPingRequest. | +---------------+--------------------------------------------------+ | PingResponse | The client sends this event to the server in | | (=7) | response to the ping request. The event data is | | | a 4-byte timestamp, which was received with the | | | PingRequest request. | +---------------+--------------------------------------------------+

命令類型

客戶端和服務器通過AMF編碼的數據交換命令。發送者發送包含命令名稱,事務ID,包含相關參數的命令對象的消息。例如,通過連接命令中包含的APP參數來告訴服務器連接的對方是哪個客戶端。接收方處理命令消息,并使用相同的事務ID應答。應答字符串為_result或_error或方法名,例如verifyClient或contactExternalServer。事務ID標明了應答指向的命令。事務ID相當于IMAP協議或其他協議中的標簽。命令字符串中的方法名,表明了發送端想要在接收端執行的方法。

下面的類對象被用來發送各種命令:

NetConnection
服務器和客戶端之間進行網絡連接的一種高級表示形式。

NetStream
代表了發送音頻流,視頻流,或其他相關數據的頻道。當然還有一些像播放,暫停之類的命令,用來控制數據流。

網絡連接命令

網絡連接管理著客戶端和服務器之初是的雙向連接。另外,它也支持異步遠程命令調用。
網絡連接允許使用以下的命令:
連接 connect
調用 call
停止 close
創建流 createStream

連接

客戶端發送連接命令給服務器,來獲取一個和服務器通信的實例。客戶端發送給服務器的命令結構如下:

    +----------------+---------+---------------------------------------+|  Field Name    |  Type   |           Description                 |+--------------- +---------+---------------------------------------+| Command Name   | String  | Name of the command. Set to "connect".| +----------------+---------+---------------------------------------+ | Transaction ID | Number | Always set to 1. | +----------------+---------+---------------------------------------+ | Command Object | Object | Command information object which has | | | | the name-value pairs. | +----------------+---------+---------------------------------------+ | Optional User | Object | Any optional information | | Arguments | | | +----------------+---------+---------------------------------------+

下面是連接命令的命令對象里包含的鍵值對的說明:

   +-----------+--------+-----------------------------+----------------+| Property  |  Type  |        Description          | Example Value | +-----------+--------+-----------------------------+----------------+ | app | String | The Server application name | testapp | | | | the client is connected to. | | +-----------+--------+-----------------------------+----------------+ | flashver | String | Flash Player version. It is | FMSc/1.0 | | | | the same string as returned | | | | | by the ApplicationScript | | | | | getversion () function. | | +-----------+--------+-----------------------------+----------------+ | swfUrl | String | URL of the source SWF file | file://C:/ | | | | making the connection. | FlvPlayer.swf | +-----------+--------+-----------------------------+----------------+ | tcUrl | String | URL of the Server. | rtmp://local | | | | It has the following format.| host:1935/test | | | | protocol://servername:port/ | app/instance1 | | | | appName/appInstance | | +-----------+--------+-----------------------------+----------------+ | fpad | Boolean| True if proxy is being used.| true or false | +-----------+--------+-----------------------------+----------------+ |audioCodecs| Number | Indicates what audio codecs | SUPPORT_SND | | | | the client supports. | _MP3 | +-----------+--------+-----------------------------+----------------+ |videoCodecs| Number | Indicates what video codecs | SUPPORT_VID | | | | are supported. | _SORENSON | +-----------+--------+-----------------------------+----------------+ |videoFunct-| Number | Indicates what special video| SUPPORT_VID | |ion | | functions are supported. | _CLIENT_SEEK | +-----------+--------+-----------------------------+----------------+ | pageUrl | String | URL of the web page from | http:// | | | | where the SWF file was | somehost/ | | | | loaded. | sample.html | +-----------+--------+-----------------------------+----------------+ | object | Number | AMF encoding method. | AMF3 | | Encoding | | | | +-----------+--------+-----------------------------+----------------+

音頻編碼屬性的可選值:
原始PCM,ADPCM,MP3,NellyMoser(5,8,11,16,22,44kHz),AAC,Speex。

    +----------------------+----------------------------+--------------+|      Codec Flag      |          Usage             |     Value    |+----------------------+----------------------------+--------------+|  SUPPORT_SND_NONE    | Raw sound, no compression  |    0x0001    |+----------------------+----------------------------+--------------+|  SUPPORT_SND_ADPCM   | ADPCM compression          |    0x0002 | +----------------------+----------------------------+--------------+ | SUPPORT_SND_MP3 | mp3 compression | 0x0004 | +----------------------+----------------------------+--------------+ | SUPPORT_SND_INTEL | Not used | 0x0008 | +----------------------+----------------------------+--------------+ | SUPPORT_SND_UNUSED | Not used | 0x0010 | +----------------------+----------------------------+--------------+ | SUPPORT_SND_NELLY8 | NellyMoser at 8-kHz | 0x0020 | | | compression | | +----------------------+----------------------------+--------------+ | SUPPORT_SND_NELLY | NellyMoser compression | 0x0040 | | | (5, 11, 22, and 44 kHz) | | +----------------------+----------------------------+--------------+ | SUPPORT_SND_G711A | G711A sound compression | 0x0080 | | | (Flash Media Server only) | | +----------------------+----------------------------+--------------+ | SUPPORT_SND_G711U | G711U sound compression | 0x0100 | | | (Flash Media Server only) | | +----------------------+----------------------------+--------------+ | SUPPORT_SND_NELLY16 | NellyMouser at 16-kHz | 0x0200 | | | compression | | +----------------------+----------------------------+--------------+ | SUPPORT_SND_AAC | Advanced audio coding | 0x0400 | | | (AAC) codec | | +----------------------+----------------------------+--------------+ | SUPPORT_SND_SPEEX | Speex Audio | 0x0800 | +----------------------+----------------------------+--------------+ | SUPPORT_SND_ALL | All RTMP-supported audio | 0x0FFF | | | codecs | | +----------------------+----------------------------+--------------+

視頻編碼屬性的可選值:
Sorenson,V1,On2,V2,H264。

    +----------------------+----------------------------+--------------+|      Codec Flag      |            Usage           |    Value     |+----------------------+----------------------------+--------------+|  SUPPORT_VID_UNUSED  | Obsolete value             |    0x0001    |+----------------------+----------------------------+--------------+|  SUPPORT_VID_JPEG    | Obsolete value             |    0x0002 | +----------------------+----------------------------+--------------+ | SUPPORT_VID_SORENSON | Sorenson Flash video | 0x0004 | +----------------------+----------------------------+--------------+ | SUPPORT_VID_HOMEBREW | V1 screen sharing | 0x0008 | +----------------------+----------------------------+--------------+ | SUPPORT_VID_VP6 (On2)| On2 video (Flash 8+) | 0x0010 | +----------------------+----------------------------+--------------+ | SUPPORT_VID_VP6ALPHA | On2 video with alpha | 0x0020 | | (On2 with alpha | channel | | | channel) | | | +----------------------+----------------------------+--------------+ | SUPPORT_VID_HOMEBREWV| Screen sharing version 2 | 0x0040 | | (screensharing v2) | (Flash 8+) | | +----------------------+----------------------------+--------------+ | SUPPORT_VID_H264 | H264 video | 0x0080 | +----------------------+----------------------------+--------------+ | SUPPORT_VID_ALL | All RTMP-supported video | 0x00FF | | | codecs | | +----------------------+----------------------------+--------------+

視頻函數屬性的可選值:

    +----------------------+----------------------------+--------------+|    Function Flag     |           Usage            |     Value    |+----------------------+----------------------------+--------------+| SUPPORT_VID_CLIENT   | Indicates that the client  |       1      || _SEEK                | can perform frame-accurate |              ||                      | seeks.                     |              |+----------------------+----------------------------+--------------+

對象編碼屬性的可選值:

    +----------------------+----------------------------+--------------+|    Encoding Type     |           Usage            |    Value     |+----------------------+----------------------------+--------------+|        AMF0          | AMF0 object encoding       |      0       ||                      | supported by Flash 6 and | | | | later | | +----------------------+----------------------------+--------------+ | AMF3 | AMF3 encoding from | 3 | | | Flash 9 (AS3) | | +----------------------+----------------------------+--------------+

服務器發送給客戶端的命令結構如下:

    +--------------+----------+----------------------------------------+| Field Name   |   Type   |             Description                |+--------------+----------+----------------------------------------+| Command Name |  String  | _result or _error; indicates whether   ||              |          | the response is result or error.       |+--------------+----------+----------------------------------------+| Transaction  |  Number  | Transaction ID is 1 for connect        || ID           |          | responses                              ||              |          |                                        |+--------------+----------+----------------------------------------+| Properties   |  Object  | Name-value pairs that describe the | | | | properties(fmsver etc.) of the | | | | connection. | +--------------+----------+----------------------------------------+ | Information | Object | Name-value pairs that describe the | | | | response from|the server. ’code’, | | | | ’level’, ’description’ are names of few| | | | among such information. | +--------------+----------+----------------------------------------+
       +--------------+                              +-------------+|    Client    |             |                |    Server   |+------+-------+             |                +------+------+|              Handshaking done | | | | | | | | | | | | | |----------- Command Message(connect) ------->| | | |<------- Window Acknowledgement Size --------| | | |<----------- Set Peer Bandwidth -------------| | | |-------- Window Acknowledgement Size ------->| | | |<------ User Control Message(StreamBegin) ---| | | |<------------ Command Message ---------------| | (_result- connect response) | | | Message flow in the connect command

命令執行過程中的消息流如下:
客戶端發送連接命令給服務器,獲得與服務器連接的實例。
服務器在接收到連接命令后,發送應答窗口大小的消息給客戶端。同時與連接命令中接到的應用建立連接。
服務器發送設置流帶寬消息給客戶端。
客戶端在接收并處理了設置流帶寬的消息后,發送應答窗口大小的消息給服務器。
服務器接著發送開始流的用戶控制消息給客戶端。
服務器發送result命令消息給客戶端,通知連接狀態是成功或失敗。命令消息中包含了事務ID。消息中還包含了像FMS版本之類的屬性,以及級別,編碼,描述,對象編碼等信息。

調用

網絡連接對象中包含的call方法,會在接收端執行遠程過程調用(RPC)。被調用的RPC方法名作為call方法的參數傳輸。

從發送端到接收端的命令結構如下:

    +--------------+----------+----------------------------------------+|Field Name    |   Type   |             Description                |+--------------+----------+----------------------------------------+| Procedure    |  String  | Name of the remote procedure that is   || Name         |          | called.                                |+--------------+----------+----------------------------------------+| Transaction  |  Number  | If a response is expected we give a | | | | transaction Id. Else we pass a value of| | ID | | 0 | +--------------+----------+----------------------------------------+ | Command | Object | If there exists any command info this | | Object | | is set, else this is set to null type. | +--------------+----------+----------------------------------------+ | Optional | Object | Any optional arguments to be provided | | Arguments | | | +--------------+----------+----------------------------------------+

應答的命令結構如下:

    +--------------+----------+----------------------------------------+| Field Name   |   Type   |             Description                |+--------------+----------+----------------------------------------+| Command Name |  String  | Name of the command.                   ||              |          |                                        |+--------------+----------+----------------------------------------+| Transaction  |  Number  | ID of the command, to which the        || ID           |          | response belongs.+--------------+----------+----------------------------------------+| Command      |  Object | If there exists any command info this | | Object | | is set, else this is set to null type. | +--------------+----------+----------------------------------------+ | Response | Object | Response from the method that was | | | | called. | +------------------------------------------------------------------+
創建流

客戶端通過發送此消息給服務器來創建一個用于消息交互的邏輯通道。音頻,視頻,和元數據都是通過createStream命令創建的流通道發布出去的。

NetConnection是默認的交互通道,流ID為0。協議和一部分命令消息,包含createStream,都是使用默認的交互通道發布的。

從客戶端發送給服務器的命令結構如下:

    +--------------+----------+----------------------------------------+| Field Name   |   Type   |             Description                |+--------------+----------+----------------------------------------+| Command Name |  String  | Name of the command. Set to            ||              |          | "createStream". | +--------------+----------+----------------------------------------+ | Transaction | Number | Transaction ID of the command. | | ID | | | +--------------+----------+----------------------------------------+ | Command | Object | If there exists any command info this | | Object | | is set, else this is set to null type. | +--------------+----------+----------------------------------------+

從服務器發送給客戶端的命令結構:

    +--------------+----------+----------------------------------------+| Field Name   |   Type   |             Description                |+--------------+----------+----------------------------------------+| Command Name |  String  | _result or _error; indicates whether   ||              |          | the response is result or error.       |+--------------+----------+----------------------------------------+| Transaction  |  Number  | ID of the command that response belongs|| ID           |          | to.                                    |+--------------+----------+----------------------------------------+| Command      |  Object  | If there exists any command info this  || Object       |          | is set, else this is set to null type. | +--------------+----------+----------------------------------------+ | Stream | Number | The return value is either a stream ID | | ID | | or an error information object. | +--------------+----------+----------------------------------------+

網絡流命令

網絡流定義了通過網絡連接把音頻,視頻和數據消息流在客戶端和服務器之間進行交換的通道。一個網絡連接對象可以多個網絡流,進而支持多個數據流。

客戶端可以通過網絡流發送到服務器的命令如下:

播放 play
播放2 play2
刪除流 deleteStream
關閉流 closeStream
接收音頻 receiveAudio
接收視頻 receiveVideo
發布 publish
定位 seek
暫停 pause

服務器通過發送onStatus命令給客戶端來通知網絡流狀態的更新。

    +--------------+----------+----------------------------------------+| Field Name   |   Type   |             Description                |+--------------+----------+----------------------------------------+| Command Name |  String  | The command name "onStatus".           |+--------------+----------+----------------------------------------+| Transaction  |  Number  | Transaction ID set to 0. | | ID | | | +--------------+----------+----------------------------------------+ | Command | Null | There is no command object for | | Object | | onStatus messages. | +--------------+----------+----------------------------------------+ | Info Object | Object | An AMF object having at least the | | | | following three properties: "level" | | | | (String): the level for this message, | | | | one of "warning", "status", or "error";| | | | "code" (String): the message code, for | | | | example "NetStream.Play.Start"; and | | | | "description" (String): a human- | | | | readable description of the message. | | | | The Info object MAY contain other | | | | properties as appropriate to the code. | +--------------+----------+----------------------------------------+ Format of NetStream status message commands.
播放

客戶端發送此命令來通知服務器開始播放流。多次使用此命令可以創建一個播放列表。如果想要創建一個動態播放列表來在不同的直播或點播流之間切換,可以通過多次調用播放命令,同時將Reset字段設置為false。相反,如果想要立即播放指定的流,先清理掉之前的播放隊列,再調用播放命令,同時將Reset字段設置為true。

從客戶端發送給服務器的命令結構如下:

   +--------------+----------+-----------------------------------------+| Field Name   |   Type   |             Description                 |+--------------+----------+-----------------------------------------+| Command Name |  String  | Name of the command. Set to "play". | +--------------+----------+-----------------------------------------+ | Transaction | Number | Transaction ID set to 0. | | ID | | | +--------------+----------+-----------------------------------------+ | Command | Null | Command information does not exist. | | Object | | Set to null type. | +--------------+----------+-----------------------------------------+ | Stream Name | String | Name of the stream to play. | | | | To play video (FLV) files, specify the | | | | name of the stream without a file | | | | extension (for example, "sample"). To | | | | play back MP3 or ID3 tags, you must | | | | precede the stream name with mp3: | | | | (for example, "mp3:sample". To play | | | | H.264/AAC files, you must precede the | | | | stream name with mp4: and specify the | | | | file extension. For example, to play the| | | | file sample.m4v,specify "mp4:sample.m4v"| | | | | +--------------+----------+-----------------------------------------+ | Start | Number | An optional parameter that specifies | | | | the start time in seconds. The default | | | | value is -2, which means the subscriber | | | | first tries to play the live stream | | | | specified in the Stream Name field. If a| | | | live stream of that name is not found,it| | | | plays the recorded stream of the same | | | | name. If there is no recorded stream | | | | with that name, the subscriber waits for| | | | a new live stream with that name and | | | | plays it when available. If you pass -1 | | | | in the Start field, only the live stream| | | | specified in the Stream Name field is | | | | played. If you pass 0 or a positive | | | | number in the Start field, a recorded | | | | stream specified in the Stream Name | | | | field is played beginning from the time | | | | specified in the Start field. If no | | | | recorded stream is found, the next item | | | | in the playlist is played. | +--------------+----------+-----------------------------------------+ | Duration | Number | An optional parameter that specifies the| | | | duration of playback in seconds. The | | | | default value is -1. The -1 value means | | | | a live stream is played until it is no | | | | longer available or a recorded stream is| | | | played until it ends. If you pass 0, it | | | | plays the single frame since the time | | | | specified in the Start field from the | | | | beginning of a recorded stream. It is | | | | assumed that the value specified in | | | | the Start field is equal to or greater | | | | than 0. If you pass a positive number, | | | | it plays a live stream for | | | | the time period specified in the | | | | Duration field. After that it becomes | | | | available or plays a recorded stream | | | | for the time specified in the Duration | | | | field. (If a stream ends before the | | | | time specified in the Duration field, | | | | playback ends when the stream ends.) | | | | If you pass a negative number other | | | | than -1 in the Duration field, it | | | | interprets the value as if it were -1. | +--------------+----------+-----------------------------------------+ | Reset | Boolean | An optional Boolean value or number | | | | that specifies whether to flush any | | | | previous playlist. | +--------------+----------+-----------------------------------------+
             +-------------+                            +----------+| Play Client |             |              |   Server |+------+------+ | +-----+----+ | Handshaking and Application | | connect done | | | | | | | | | | | | | ---+---- |------Command Message(createStream) ----->| Create| | | Stream| | | ---+---- |<---------- Command Message --------------| | (_result- createStream response) | | | ---+---- |------ Command Message (play) ----------->| | | | | |<------------ SetChunkSize --------------| | | | | |<---- User Control (StreamIsRecorded) ----| Play | | | | |<---- User Control (StreamBegin) ---------| | | | | |<--Command Message(onStatus-play reset) --| | | | | |<--Command Message(onStatus-play start) --| | | | | |<-------------Audio Message---------------| | | | | |<-------------Video Message---------------| | | | | | Keep receiving audio and video stream till finishes Message flow in the play command

命令執行過程中的消息流如下:
當客戶端接收到服務器返回的createStream成功的消息時,開始發送播放命令。
服務器接收到播放命令后,發送設置塊大小的消息。
服務器發送一條用戶控制消息,消息內包含了StreamIsRecorded事件和流ID。事件類型位于消息的前2個字節,流ID位于消息的最后4個字節。
服務器發送一條用戶控制消息,消息內包含了StreamBegin事件,用于通知客戶端開始播放流。
如果客戶端已經成功發送了播放命令,那么服務器發送兩條onStatus命令給客戶端,命令的內容為NetStream.Play.Start 和 NetStream.Play.Reset。服務器只有在客戶端發送了設置有重置標簽的播放命令后,才能發送NetStream.Play.Reset命令。如果服務器找不到客戶端請求播放的流,那么發送NetStream.Play.StreamNotFound命令給客戶端。
之后,服務器發送音頻和視頻數據給客戶端。

播放2

與播放命令的不同之處在于,播放2命令可以在不修改播放內容時間線的前提下切換到一個不同碼率的流。服務器包含了多個不同碼率的流文件用于支持客戶端的播放2請求。

    The command structure from the client to the server is as follows:+--------------+----------+----------------------------------------+| Field Name   |   Type   |             Description                |+--------------+----------+----------------------------------------+| Command Name |  String  | Name of the command, set to "play2". | +--------------+----------+----------------------------------------+ | Transaction | Number | Transaction ID set to 0. | | ID | | | +--------------+----------+----------------------------------------+ | Command | Null | Command information does not exist. | | Object | | Set to null type. | +--------------+----------+----------------------------------------+ | Parameters | Object | An AMF encoded object whose properties | | | | are the public properties described | | | | for the flash.net.NetStreamPlayOptions | | | | ActionScript object. | +--------------+----------+----------------------------------------+

有關NetStreamPlayOptions對象的公開屬性的說明詳見AS3語言的文檔。

此命令的消息流如下圖所示:

           +--------------+                          +-------------+| Play2 Client |              |           |    Server   |+--------+-----+ | +------+------+ | Handshaking and Application | | connect done | | | | | | | | | | | | | ---+---- |---- Command Message(createStream) --->| Create | | | Stream | | | ---+---- |<---- Command Message (_result) -------| | | ---+---- |------ Command Message (play) -------->| | | | | |<------------ SetChunkSize ------------| | | | | |<--- UserControl (StreamIsRecorded)----| Play | | | | |<------- UserControl (StreamBegin)-----| | | | | |<--Command Message(onStatus-playstart)-| | | | | |<---------- Audio Message -------------| | | | | |<---------- Video Message -------------| | | | | | ---+---- |-------- Command Message(play2) ------>| | | | | |<------- Audio Message (new rate) -----| Play2 | | | | |<------- Video Message (new rate) -----| | | | | | | | | | Keep receiving audio and video stream till finishes | Message flow in the play2 command
刪除流

如果需要銷毀網絡流對象,可以通過網絡流發送刪除流消息給服務器。

客戶端發送給服務器的命令結構如下:

    The command structure from the client to the server is as follows:+--------------+----------+----------------------------------------+| Field Name   |   Type   |             Description                |+--------------+----------+----------------------------------------+| Command Name |  String  | Name of the command, set to            ||              |          | "deleteStream". | +--------------+----------+----------------------------------------+ | Transaction | Number | Transaction ID set to 0. | | ID | | | +--------------+----------+----------------------------------------+ | Command | Null | Command information object does not | | Object | | exist. Set to null type. | +--------------+----------+----------------------------------------+ | Stream ID | Number | The ID of the stream that is destroyed | | | | on the server. | +--------------+----------+----------------------------------------+

服務器接收到此消息后,不做任何回復。

接收音頻

網絡流發送此消息通知服務器,是否要發送音頻數據給客戶端。

    The command structure from the client to the server is as follows:+--------------+----------+----------------------------------------+| Field Name   |   Type   |             Description                |+--------------+----------+----------------------------------------+| Command Name |  String  | Name of the command, set to            ||              |          | "receiveAudio". | +--------------+----------+----------------------------------------+ | Transaction | Number | Transaction ID set to 0. | | ID | | | +--------------+----------+----------------------------------------+ | Command | Null | Command information object does not | | Object | | exist. Set to null type. | +--------------+----------+----------------------------------------+ | Bool Flag | Boolean | true or false to indicate whether to | | | | receive audio or not. | +--------------+----------+----------------------------------------+

如果服務器接收到帶有flase標簽的消息后,不做任何回復。如果接收到帶有true標簽的消息,服務器回復帶有NetStream.Seek.Notify和NetStream.Play.Start的消息給客戶端。

接收視頻

網絡流發送此消息通知服務器,是否要發送視頻數據給客戶端。

客戶端發送給服務器的命令結構如下:

    +--------------+----------+----------------------------------------+| Field Name   |   Type   |             Description                |+--------------+----------+----------------------------------------+| Command Name |  String  | Name of the command, set to            ||              |          | "receiveVideo". | +--------------+----------+----------------------------------------+ | Transaction | Number | Transaction ID set to 0. | | ID | | | +--------------+----------+----------------------------------------+ | Command | Null | Command information object does not | | Object | | exist. Set to null type. | +--------------+----------+----------------------------------------+ | Bool Flag | Boolean | true or false to indicate whether to | | | | receive video or not. | +--------------+----------+----------------------------------------+

如果服務器接收到帶有flase標簽的消息后,不做任何回復。如果接收到帶有true標簽的消息,服務器回復帶有NetStream.Seek.Notify和NetStream.Play.Start的消息給客戶端。

發布

客戶端發送此消息,用來發布一個有名字的流到服務器。其他客戶端可以使用此流名來播放流,接收發布的音頻,視頻,以及其他數據消息。

客戶端發送給服務器的命令結構如下:

    +--------------+----------+----------------------------------------+| Field Name   |   Type   |             Description                |+--------------+----------+----------------------------------------+| Command Name |  String  | Name of the command, set to "publish". | +--------------+----------+----------------------------------------+ | Transaction | Number | Transaction ID set to 0. | | ID | | | +--------------+----------+----------------------------------------+ | Command | Null | Command information object does not | | Object | | exist. Set to null type. | +--------------+----------+----------------------------------------+ | Publishing | String | Name with which the stream is | | Name | | published. | +--------------+----------+----------------------------------------+ | Publishing | String | Type of publishing. Set to "live", | | Type | | "record", or "append". | | | | record: The stream is published and the| | | | data is recorded to a new file.The file| | | | is stored on the server in a | | | | subdirectory within the directory that | | | | contains the server application. If the| | | | file already exists, it is overwritten.| | | | append: The stream is published and the| | | | data is appended to a file. If no file | | | | is found, it is created. | | | | live: Live data is published without | | | | recording it in a file. | +--------------+----------+----------------------------------------+

服務器接收到此消息后,回復onStatus命令來標記發布的開始。

定位

客戶端發送此消息來定位多媒體文件或播放列表的偏移(以毫秒為單位)。

客戶端發送給服務器的命令結構如下:

    +--------------+----------+----------------------------------------+| Field Name   |   Type   |             Description                |+--------------+----------+----------------------------------------+| Command Name |  String  | Name of the command, set to "seek". | +--------------+----------+----------------------------------------+ | Transaction | Number | Transaction ID set to 0. | | ID | | | +--------------+----------+----------------------------------------+ | Command | Null | There is no command information object | | Object | | for this command. Set to null type. | +--------------+----------+----------------------------------------+ | milliSeconds | Number | Number of milliseconds to seek into | | | | the playlist. | +--------------+----------+----------------------------------------+

當定位完成后,服務器回復NetStream.Seek.Notify狀態消息給客戶端。如果定位失敗,將回復_error消息。

暫停

客戶端發送此消息來通知服務器暫停或開始播放。

客戶端發送給服務器的命令結構如下:

    +--------------+----------+----------------------------------------+| Field Name   |   Type   |             Description                |+--------------+----------+----------------------------------------+| Command Name |  String  | Name of the command, set to "pause". | +--------------+----------+----------------------------------------+ | Transaction | Number | There is no transaction ID for this | | ID | | command. Set to 0. | +--------------+----------+----------------------------------------+ | Command | Null | Command information object does not | | Object | | exist. Set to null type. | +--------------+----------+----------------------------------------+ |Pause/Unpause | Boolean | true or false, to indicate pausing or | | Flag | | resuming play | +--------------+----------+----------------------------------------+ | milliSeconds | Number | Number of milliseconds at which the | | | | the stream is paused or play resumed. | | | | This is the current stream time at the | | | | Client when stream was paused. When the| | | | playback is resumed, the server will | | | | only send messages with timestamps | | | | greater than this value. | +--------------+----------+----------------------------------------+

當流暫停成功,服務器發送NetStream.Pause.Notify狀態消息經給客戶端,如果流未暫停,服務器發送NetStream.Unpause.Notify狀態消息給客戶端。如果暫停失敗,則發送_error消息。

消息交互示例

下面是一些使用RTMP協議交互消息的示例。

發布錄制的視頻

此示例闡述了發布者如何發布視頻流到服務器。其他客戶端可以訂閱并播放此視頻流。

            +--------------------+                     +-----------+|  Publisher Client  |        |            |    Server |+----------+---------+ | +-----+-----+ | Handshaking Done | | | | | | | ---+---- |----- Command Message(connect) ----->| | | | | |<----- Window Acknowledge Size ------| Connect | | | | |<-------Set Peer BandWidth ----------| | | | | |------ Window Acknowledge Size ----->| | | | | |<------User Control(StreamBegin)-----| | | | ---+---- |<---------Command Message -----------| | (_result- connect response) | | | ---+---- |--- Command Message(createStream)--->| Create | | | Stream | | | ---+---- |<------- Command Message ------------| | (_result- createStream response) | | | ---+---- |---- Command Message(publish) ------>| | | | | |<------User Control(StreamBegin)-----| | | | | |-----Data Message (Metadata)-------->| | | | Publishing| |------------ Audio Data ------------>| Content | | | | |------------ SetChunkSize ---------->| | | | | |<----------Command Message ----------| | | (_result- publish result) | | | | | |------------- Video Data ----------->| | | | | | | | | | Until the stream is complete | | | | Message flow in publishing a video stream

廣播共享對象消息

此示例闡述了流創建過程中的消息交換,和共享對象的變換過程。同時還展示了共享對象消息廣播的處理過程。

                     +----------+                       +----------+|  Client  |           |           |  Server  |+-----+----+           |           +-----+----+|   Handshaking and Application    ||          connect done            ||                |                 ||                |                 ||                |                 ||                |                 |Create and ---+---- |---- Shared Object Event(Use)---->| connect | | | Shared Object | | | ---+---- |<---- Shared Object Event---------| | (UseSuccess,Clear) | | | ---+---- |------ Shared Object Event ------>| Shared object | | (RequestChange) | Set Property | | | ---+---- |<------ Shared Object Event ------| | (Success) | | | ---+---- |------- Shared Object Event ----->| Shared object| | (SendMessage) | Message | | | Broadcast ---+---- |<------- Shared Object Event -----| | (SendMessage) | | | | | Shared object message broadcast

從錄制的流發布元數據

本示例展示了發布元數據的消息交換過程。

              +------------------+                       +---------+| Publisher Client |         |             |   FMS   |+---------+--------+         |             +----+----+|     Handshaking and Application     ||            connect done             ||                  |                  ||                  |                  |---+--- |---Command Messsage(createStream) -->|Create |    |                                     |Stream |    |                                     |---+--- |<---------Command Message------------| | (_result - command response) | | | ---+--- |---- Command Message(publish) ------>| Publishing | | | metadata | |<------ UserControl(StreamBegin)-----| from file | | | | |-----Data Message (Metadata) ------->| | | Publishing metadata

轉載于:https://www.cnblogs.com/workhardkangwei/p/6231596.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/259835.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/259835.shtml
英文地址,請注明出處:http://en.pswp.cn/news/259835.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

關卡 動畫 藍圖 運行_UE4入門之路(基礎藍圖篇):藍圖的制作

藍圖系統簡介藍圖系統是UE4中十分有代表性的一個特點&#xff0c;所謂藍圖就是一種可視化的腳本。該系統非常靈活且非常強大&#xff0c;因為它為設計人員提供了一般僅供程序員使用的所有概念及工具。 程序員能夠很方便的創建一個基礎系統&#xff0c;并交給策劃進一步在藍圖中…

overfitting(過度擬合)的概念

來自&#xff1a;http://blog.csdn.net/fengzhe0411/article/details/7165549 最近幾天在看模式識別方面的資料&#xff0c;多次遇到“overfitting”這個概念&#xff0c;最終覺得以下解釋比較容易接受&#xff0c;就拿出來分享下。 overfittingt是這樣一種現象&#xff1a;一個…

虛擬串口服務器zenetmanager,Avocent服務器/串口管理 KVM

MergePoint Unity交換機在單個設備中結合了 KVM over IP和串行控制臺管理技術。這項獨特的結合為IT管理員提供了用于訪問和控制服務器、網絡設備及其他數據中心和分支辦公室設備的完整遠程管理解決方案。MergePoint Unity交換機直接與物理KVM、USB和串行端口進行安全的遠程帶外…

KAFKA分布式消息系統

Kafka[1]是linkedin用于日志處理的分布式消息隊列&#xff0c;linkedin的日志數據容量大&#xff0c;但對可靠性要求不高&#xff0c;其日志數據主要包括用戶行為&#xff08;登錄、瀏覽、點擊、分享、喜歡&#xff09;以及系統運行日志&#xff08;CPU、內存、磁盤、網絡、系統…

jar打包 剔除第三方依賴以及它的依賴_面試官:為什么Spring Boot的jar可以直接運行?...

來源&#xff1a;Gormats Notesfangjian0423.github.io/2017/05/31/springboot-executable-jar/Spring Boot Loader抽象的一些類JarLauncher的執行過程關于自定義的類加載器LaunchedURLClassLoaderSpring Boot Loader的作用SpringBoot提供了一個插件spring-boot-maven-plugin用…

CQRS架構圖

2019獨角獸企業重金招聘Python工程師標準>>> 轉載于:https://my.oschina.net/darkness/blog/814243

SQLite中不支持的sql語法

今天很自然的在寫Sql語句的時候用了Top&#xff0c;一開始沒發現問題&#xff0c;因為我從數據庫讀出的值正好是0&#xff0c;而我習慣變量定義的時候也都賦值0&#xff0c;可是到我不要0的時候我就發現問題了。后來才知道&#xff0c;可愛的小sqlite竟然有不支持的sql語法。 看…

Analyzer普通用戶登錄不了[從網絡訪問此計算機]

問題&#xff1a; 最近客戶諾奇反映說Analyzer普通用戶登錄不了&#xff0c;但是發現管理員又可以登錄&#xff0c;幾經周折發現原來是系統的本地安全策略設置了不讓遠程使用本地賬戶密碼登錄系統導致。解決方案&#xff1a; 修改本地安全策略的“從遠程訪問此計算機”中的用戶…

金蝶系統服務器要求,金蝶服務器安裝及其相關要求.doc

K/3WISE創新管理平臺 V12.2標準部署環境說明目錄1. 多語言部署規則21.1 客戶端多語言部署規則21.2 中間層多語言部署規則31.3 數據庫多語言部署規則31.4 人力資源、管理門戶、CRM多語言部署規則41.5 Citrix遠程接入多語言部署規則42. 多語言部署架構圖52.1 簡體中間層52.2 繁體…

源碼 移植_FreeModbus移植總結

modbus是一項工業上經常用到的通訊協議&#xff0c;而freemodbus是一款開源的從機協議棧。關于它的移植網上已經有了很多的文章&#xff0c;但是大多都只是針對其中部分問題的表述。本文將會把自己在移植freemodbus過程中遇到的問題以及freemodbus的源碼分析盡量表述清楚。&…

expect腳本的簡單應用

expect是一個用來處理交互的命令。借助于expect我們可以把交互過程寫在一個腳本上&#xff0c;使之自動化完成。expect最核心的四個命令&#xff1a;send:用于向進程發送字符串 except:從進程接收字符串 spawn:打開一個新的進程 interact&#xff1a;保持交互的狀態首先一個簡單…

ajax中datatype是json,dataType:'json'vs data:$ .ajax中的JSON.stringify(obj)

我有這個數據結構&#xff1a;var formValues {TemporaryToken: a.userStatus.get("TemporaryToken"),MemorableWordPositionAndValues:[{Position: a.userStatus.get("MemorableWordPositions")[0],Value: this.$([name"login-memorable-character-…

sqlserver 查詢中使用Union或Union All

在 程序人生網站上 看到了 這篇文章 就收藏了 哈 http://www.ourcodelife.com/article-415-1.html 首先&#xff0c;在程序人生網站上&#xff0c;需要負責任的指出的是在SQL Server查詢中使用Union或Union All后Order by排序無效&#xff0c;我不確認是不是微軟的bug&#xf…

word標題大綱級別_快速按標題層級把Word轉Excel—附詳細操作步驟

如何快速把層級分明的word文檔轉換成橫向從屬結構的excel表格一、問題描述文檔如下圖所示。文檔一共三個層次&#xff0c;大綱級別分別是1、2、3級&#xff0c;左則是其文檔結構圖&#xff0c;可以看出文檔層級分明。最終要將文檔轉換成如下橫向從屬結構的表格。一個層次的內容…

生成GUID唯一值的方法匯總(dotnet/javascript/sqlserver)

一、在 .NET 中生成1、直接用.NET Framework 提供的 Guid() 函數&#xff0c;此種方法使用非常廣泛。GUID&#xff08;全局統一標識符&#xff09;是指在一臺機器上生成的數字&#xff0c;它保證對在同一時空中的任何兩臺計算機都不會生成重復的 GUID 值&#xff08;即保證所有…

Thread.CurrentPrincipal HttpContext.Current.User

據說要這樣寫才穩妥 // This principal will flow throughout the request.VoyagerPrincipal principal new VoyagerPrincipal(yada, yada, yada); // Attach the new principal object to the current HttpContext objectHttpContext.Current.User principal; // Make sure …

江森系統設置服務器日期,江森自控METASYS操作手冊

? Alarm? Trend顯示窗口中的按鈕編號 A B按鈕說明允許您編輯所示項目的屬性。選擇Save按鈕可保存修改。 顯示這個窗口中以前顯示過的內容。每個窗口最多可顯示5個歷史項目。顯示已保存的下一個窗口中的內容。鎖定選中的顯示窗口(防止被其他拖拽來的項目覆蓋)。您可調整被鎖定…

servlet中getWriter和getOutputStream的區別

getWriter();getOutputStream();區別&#xff1a;1、getWriter()用于向客戶機回送字符數據2、getOutputStream()返回的對象&#xff0c;可以回送字符數據&#xff0c;也可以回送字節數據&#xff08;二進制數據&#xff09;如何選擇&#xff1a;若果我們回送字符數據&#xff0…

execve系統調用_張凱捷—系統調用分析(3) (基于最新Linux5.0版本系統調用日志收集系統)...

在上一篇文章《系統調用分析(2)》中介紹和分析了32位和64位的快速系統調用指令——sysenter/sysexit和syscall/sysret&#xff0c;以及內核對快速系統調用部分的相關代碼&#xff0c;并追蹤了一個用戶態下的系統調用程序運行過程。本篇中將基于最新的Linux-5.0內核&#xff0c;…

批量下載小說網站上的小說(python爬蟲)

隨便說點什么 因為在學python&#xff0c;所有自然而然的就掉進了爬蟲這個坑里&#xff0c;好吧&#xff0c;主要是因為我覺得爬蟲比較酷&#xff0c;才入坑的。 想想看&#xff0c;你可以批量自動的采集互聯網上海量的資料數據&#xff0c;是多么令人激動啊&#xff01; 所以我…