Abstract | GStreamer 媒體能力協(xié)商 |
---|---|
Authors | Walter Fan |
Category | learning note |
Status | v1.0 |
Updated | 2023-12-10 |
License | CC-BY-NC-ND 4.0 |
概述
在 GStreamer 中晶通, 媒體能力協(xié)商 Capabilities negotiation (縮寫為 Caps negotiation) 是一個決策的過程绒极,用來決定在 GStreamer 管道中數(shù)據(jù)流采用何種合適的媒體格式查库。
GStreamer 的文檔 Negotiation 中對這一塊有詳細(xì)的解釋, 在此我做些翻譯和記錄
有些元件有相對固定的媒體能力凿蒜,有些元件則比較靈活宾袜,有些則不那么靈活叉谜。理想情況下错敢,媒體能力協(xié)商(Capabilities negotiation) 信息將從管道中具有媒體能力的那些元件践樱,傳送到管道中相對靈活的那部分元件中厂画,并受到管道中并不靈活的那部分元件的約束。
基本規(guī)則
以下的基本規(guī)則需要遵守
- 下游元件建議格式
- 上游元件決定格式
在 caps negotiation 中有四種 queries/events
-
GST_QUERY_CAPS
: 獲取可能的 Caps -
GST_QUERY_ACCEPT_CAPS
: 檢查 Caps 是否可行 -
GST_EVENT_CAPS
: 配置 Caps(下游) -
GST_EVENT_RECONFIGURE
: 通知上游可用的新 Caps
查詢 Queries
一個 pad 可以詢問其所連接的 pad 它是不是支持某種格式 GstCaps
, 這就是 CAPS query拷邢。 支持的 caps 列表可用于為數(shù)據(jù)傳輸選擇合適的 GstCaps
袱院。
CAPS 查詢以遞歸方式工作,元件在構(gòu)建可能的 caps 時應(yīng)考慮其對等元件瞭稼。 由于結(jié)果 caps 可能非常大忽洛,因此可以使用過濾器 capsfilter 來限制 caps。 只有與過濾器匹配的 caps 才會作為結(jié)果 caps 返回环肘。 過濾器caps 的順序的按照調(diào)用者的優(yōu)先順序給出欲虚,并考慮下游元件所返回的 caps。
-
filter
(in)GST_TYPE_CAPS
(默認(rèn)為 NULL):- 用于過濾結(jié)果的GstCaps
-
caps
(out)GST_TYPE_CAPS
(默認(rèn) NULL): - 查詢到的 Caps 結(jié)果
pad 可以詢問對等 pad 是否支持給定的 caps 悔雹。 它通過 ACCEPT_CAPS
查詢來執(zhí)行此操作复哆, 這個返回的Caps 是固定。 “ACCEPT_CAPS”查詢不需要遞歸地工作腌零,如果具有這些 caps 的后續(xù) CAPS 事件返回成功梯找,它可以簡單地返回 TRUE。
-
caps
(in)GST_TYPE_CAPS
:- 要檢查的GstCaps
益涧,它是固定的值 -
result
(out)G_TYPE_BOOLEAN
(默認(rèn) FALSE): - 如果 Caps 被接受 則為 TRUE
事件 Events
當(dāng)一個媒體格式協(xié)商成功锈锤,對端的元件就會以 CAPS 事件發(fā)送通知, 此 Caps 是固定的
-
caps
GST_TYPE_CAPS
: - 協(xié)商的GstCaps
, 它必須是固定的
操作 Operation
GStreamer 的兩種調(diào)度模式(推模式和拉模式)適用于不同的機(jī)制來實現(xiàn)此目標(biāo)。 由于推模式更常見久免,我們先描述推模式協(xié)商 Push-mode negotiation浅辙。
Push-mode negotiation
當(dāng)一個元件想要推送緩沖區(qū)并且需要決定媒體格式時,就會發(fā)生推送模式協(xié)商妄壶。 這稱為下游協(xié)商 (downstream negotiation)摔握,因為上游元件決定下游元件的格式寄狼。 這是最常見的情況丁寄。
當(dāng)下游元件想要從上游元件接收另一種數(shù)據(jù)格式時,也可能發(fā)生協(xié)商泊愧。 這稱為上游協(xié)商伊磺。
協(xié)商的基本過程如下:
GstCaps
(see caps) are refcounted before they are pushed as an event to describe the contents of the following buffer.
GstCaps 用來描述媒體數(shù)據(jù)的內(nèi)容 ,它會作為一個事件重新進(jìn)行引用計數(shù)删咱,然后發(fā)送給相連的元件一個元件在處理數(shù)據(jù)緩沖之前收到 CAPS 事件屑埋,它可以重新更改 (reconfigure) 自己的配置為新的媒體格式。如果這個 caps 事件的數(shù)據(jù)類型不可接受痰滋,此元件可以拒絕這個 caps 事件摘能,它同時也會拒絕接下來的數(shù)據(jù)緩沖,方法是在
chain
函數(shù)中返回GST_FLOW_NOT_NEGOTIATED
下游的元件可通過發(fā)送
GST_FLOW_NOT_NEGOTIATED
事件給上游的元件要求媒體流的格式更改
一個 source pad 開始協(xié)商的一般流程如下, 看起來頗有點做生意的討價還價流程
src sink
| |
| querycaps? |
|---------------->|
| caps |
select caps |< - - - - - - - -|
from the | |
candidates | |
| |-.
| accepts? | |
type A |---------------->| | optional
| yes | |
|< - - - - - - - -| |
| |-'
| send_event() |
send CAPS |---------------->| Receive type A, reconfigure to
event A | | process type A.
| |
| push |
push buffer |---------------->| Process buffer of type A
| |
可能的偽代碼實現(xiàn)如下
[element wants to create a buffer]
if not format
# see what we can do
ourcaps = gst_pad_query_caps (srcpad)
# see what the peer can do filtered against our caps
candidates = gst_pad_peer_query_caps (srcpad, ourcaps)
foreach candidate in candidates
# make sure the caps is fixed
fixedcaps = gst_pad_fixate_caps (srcpad, candidate)
# see if the peer accepts it
if gst_pad_peer_accept_caps (srcpad, fixedcaps)
# store the caps as the negotiated caps, this will
# call the setcaps function on the pad
gst_pad_push_event (srcpad, gst_event_new_caps (fixedcaps))
break
endif
done
endif
一個 sink pad 開始重新協(xié)商的一般流程如下,還是討價還價敲街, 只不過這回發(fā)起的是買方(sink pad)
src sink
| |
| accepts? |
|<----------------| type B
| yes |
|- - - - - - - - >|-.
| | | suggest B caps next
| |<'
| |
| push_event() |
mark .-|<----------------| send RECONFIGURE event
renegotiate| | |
'>| |
| querycaps() |
renegotiate |---------------->|
| suggest B |
|< - - - - - - - -|
| |
| send_event() |
send CAPS |---------------->| Receive type B, reconfigure to
event B | | process type B.
| |
| push |
push buffer |---------------->| Process buffer of type B
| |
參考資料
本作品采用知識共享署名-非商業(yè)性使用-禁止演繹 4.0 國際許可協(xié)議進(jìn)行許可团搞。