1疼进、Gstreamer design Overview
概括性介紹GStreamer的架構(gòu)及Gstreamer內(nèi)部工作機(jī)制运准。詳細(xì)內(nèi)容可以查看Gstreamer doc/markdown
1.1 Introduction
GStreamer由一些列庫(kù)和插件組成,可用于實(shí)現(xiàn)各種多媒體應(yīng)用:桌面播放器汞幢、音視頻解碼器、多媒體服務(wù)器、音視頻轉(zhuǎn)碼器等俩块。
上述應(yīng)用通過(guò)pipeline構(gòu)建,而pipeline又由單元(elements)構(gòu)成浓领。
單元是在多媒體流中執(zhí)行一系列動(dòng)作的對(duì)象:
- 讀文件
- 不同格式之間的編解碼
- 從硬件設(shè)備捕獲圖像
- 輸出給硬件設(shè)備
- 多媒體流的混合或復(fù)用(mix or multiplex)
每個(gè)單元都有輸入pads玉凯、輸出pads,分別叫sink pads联贩、source pads漫仆,單元之間通過(guò)pads連接構(gòu)成pipeline,下面示例是ogg/vorbis 播放的pipeline:
+-----------------------------------------------------------+
| ----------> downstream -------------------> |
| |
| pipeline |
| +---------+ +----------+ +-----------+ +----------+ |
| | filesrc | | oggdemux | | vorbisdec | | alsasink | |
| | src-sink src-sink src-sink | |
| +---------+ +----------+ +-----------+ +----------+ |
| |
| <---------< upstream <-------------------< |
+-----------------------------------------------------------+
filesrc讀取來(lái)自磁盤(pán)上的文件撑蒜,oggdemux單元對(duì)數(shù)據(jù)解復(fù)用(demultiplexes 1轉(zhuǎn)多)歹啼,將壓縮的音頻數(shù)據(jù)流發(fā)送給vorbisdec單元,vorbisdec單元對(duì)壓縮的數(shù)據(jù)解碼并發(fā)送給alsasink單元座菠,alsasink將解碼后的數(shù)據(jù)發(fā)送給聲卡播放狸眼。
Downstream、Upstream用于描述pipeline的方向浴滴,從source端到sink端傳遞叫Downstream拓萌,反之稱(chēng)為Upstream,數(shù)據(jù)流總是Downstream(source到sink端)
應(yīng)用的本質(zhì)是使用上述存在的單元構(gòu)成pipeline升略,這在pipeline topic中有詳細(xì)介紹微王。
應(yīng)用不用去管理復(fù)雜的數(shù)據(jù)流/解碼/轉(zhuǎn)換/同步,只需調(diào)用pipeline對(duì)象的高層函數(shù)如:播放/暫停/停止品嚣。
應(yīng)用還接受來(lái)自pipeline的消息和通知炕倘,如metadata,warning翰撑,error罩旋,EOS消息。
若應(yīng)用需要對(duì)圖像更多的控制眶诈,可以直接訪問(wèn)pipeline中的單元和pads涨醋。
1.2 Design overview
GStreamer設(shè)計(jì)目標(biāo):
- 對(duì)大量數(shù)據(jù)的快速處理
- 允許同時(shí)多線程處理
- 多種多媒體格式的支持能力
- 不同數(shù)據(jù)流之間的同步
- 應(yīng)對(duì)多個(gè)硬件設(shè)備的處理能力
應(yīng)用的能力依賴(lài)于構(gòu)成單元的數(shù)量以及各單元在系統(tǒng)中的功能。
GStreamer core主要用于media agnostic逝撬,但仍可以提供一些單元特性用于描述media format浴骂。
1.3 單元(Elements)
pipeline最小構(gòu)成為單元,每個(gè)單元提供一定數(shù)目的pads宪潮,可以是source 或sink pads溯警。source pads提供數(shù)據(jù)趣苏,sink pads接收數(shù)據(jù),下面是oggdemux單元由一個(gè)接收數(shù)據(jù)的sink pads愧膀,兩個(gè)提供數(shù)據(jù)的source pads組成拦键。
+-----------+
| oggdemux |
| src0
sink src1
+-----------+
單元包含四種狀態(tài):NULL
, READY
, PAUSED
, PLAYING
。NULL
和READY
狀態(tài)下檩淋,單元不會(huì)處理數(shù)據(jù)芬为。PLAYING
狀態(tài)下處理數(shù)據(jù),中間態(tài)PAUSED
用于在pipeline中預(yù)裝載數(shù)據(jù)蟀悦,使用gst_element_set_state()
函數(shù)改變狀態(tài)媚朦。
單元狀態(tài)之間的變換需要經(jīng)過(guò)中間態(tài),即處于READY
狀態(tài)想要變換為PLAYING
狀態(tài)日戈,需要先變?yōu)橹虚g態(tài)PAUSED
询张。
當(dāng)單元狀態(tài)變?yōu)?code>PAUSED,將激活單元的pads浙炼。首先激活的是source pads份氧,然后sink pads。pads激活后弯屈,會(huì)調(diào)用激活函數(shù)蜗帜,有些pads將開(kāi)啟GstTask線程或其它的機(jī)制,開(kāi)始發(fā)送和接收數(shù)據(jù)(producing and consuming data
)
PAUSED
比較特別资厉,因?yàn)樗枰獙?shù)據(jù)預(yù)裝載(preroll)到pipeline中厅缺,目的是用數(shù)據(jù)填充pipeline中的所有的連接單元以使得接下來(lái)的PLAYING
狀態(tài)快速完成,有些單元甚至?xí)霈F(xiàn)已經(jīng)接收完所有數(shù)據(jù)宴偿,但還沒(méi)有完成PAUSED
狀態(tài)的轉(zhuǎn)換湘捎。
詳細(xì)的單元狀態(tài)的轉(zhuǎn)變見(jiàn):states
單元的分類(lèi):
source elements: pipeline中不接收數(shù)據(jù),僅提供數(shù)據(jù)的單元
sink elements:不輸出數(shù)據(jù)給其它單元窄刘,僅接收數(shù)據(jù)提供給外部設(shè)備窥妇。
transform elements: 需要完成數(shù)據(jù)流之間轉(zhuǎn)變的單元,如編碼器/解碼器/轉(zhuǎn)換器娩践。
demuxer elements: 一個(gè)數(shù)據(jù)流變成多個(gè)數(shù)據(jù)流秩伞。
mixer/muxer elements: 多個(gè)數(shù)據(jù)流組合成單個(gè)數(shù)據(jù)流。
單元的其它分類(lèi)方式 (see klass).
1.4 Bins
bin是單元的子類(lèi)欺矫,其作用是作為其它單元的容器,這樣多個(gè)單元可以組成一個(gè)單元展氓。組成的一個(gè)單元叫bin穆趴。
bin相配合的子狀態(tài)改變稍后給出解釋?zhuān)琤in也會(huì)給單元分配事件和各種函數(shù)。
bin可以有自己的source 和 sink pads遇汞,通過(guò)鏡像一個(gè)或多個(gè)自身的子pads未妹。
如下圖簿废,有兩個(gè)單元的bin,bin的sink pad由一個(gè)單元的sink pad鏡像而來(lái)络它。
+---------------------------+
| bin |
| +--------+ +-------+ |
| | | | | |
| /sink src-sink | |
sink +--------+ +-------+ |
+---------------------------+
1.5 Pipeline
pipeline 特殊的bin子類(lèi)族檬,為其小孩提供下面特性:
- 為其所有小孩選擇和管理全局時(shí)鐘。
- 管理
running_time
化戳,Running_time是pipeline消耗在PLAYING
狀態(tài)以及用于同步的時(shí)間单料。 - 管理pipeline的延遲。
- 為單元提供與應(yīng)用之間的通訊手段:
GstBus
- 管理單元的全局狀態(tài)点楼,如Errors扫尖、EOS
一般情況下,應(yīng)用創(chuàng)建一個(gè)pipeline來(lái)管理應(yīng)用中的所有單元掠廓。
1.6 Dataflow and buffers
GStreamer支持兩種可能類(lèi)型的數(shù)據(jù)流换怖,push and pull model,push model蟀瞧,upstream單元通過(guò)調(diào)用sinkpad的方法發(fā)送數(shù)據(jù)給downstream單元沉颂;pull model,downstream單元通過(guò)調(diào)用source pad的方法向upstream單元請(qǐng)求數(shù)據(jù)悦污。
大都數(shù)數(shù)據(jù)流的方式是push model铸屉,pull model可用于demuxer單元,也用于低延遲的音頻應(yīng)用中塞关。
在pads之間傳輸?shù)臄?shù)據(jù)存儲(chǔ)在Buffer中抬探,buffer包含指向存儲(chǔ)區(qū)域的指針以及對(duì)存儲(chǔ)區(qū)域的描述metadata。
metadata包含:
數(shù)據(jù)的時(shí)間戳帆赢,何時(shí)捕捉的數(shù)據(jù)小压,何時(shí)播放數(shù)據(jù)...
數(shù)據(jù)的偏置,音頻小樣椰于,視頻幀..
數(shù)據(jù)持續(xù)時(shí)間怠益。
數(shù)據(jù)其它特性的描述符號(hào),如discontinuities or delta units.
其它仲裁metadata
通過(guò)連接單元之間的pad發(fā)送buffer瘾婿,push model下蜻牢,通過(guò) gst_pad_push()
函數(shù)將buffer推送給相對(duì)應(yīng)的pad;pull model下偏陪,通過(guò)gst_pad_pull_range()
函數(shù)向upstream的pad請(qǐng)求數(shù)據(jù)抢呆。
push model單元在發(fā)送buffer前,需要確認(rèn)相配對(duì)的單元能夠理解buffer的內(nèi)容笛谦。詢(xún)問(wèn)相配對(duì)單元能夠支持的格式抱虐,選擇合適的格式,發(fā)送buffer前饥脑,通過(guò)CAPS事件先發(fā)送選擇的格式恳邀。buffer發(fā)送之間的握手詳見(jiàn):negotiation
配對(duì)單元接收CAPS事件懦冰,將會(huì)檢查其是否能夠理解媒體類(lèi)型(media type),當(dāng)媒體類(lèi)型不被接受時(shí)谣沸,配對(duì)單元將拒絕接受buffer刷钢。
gst_pad_push()
和gst_pad_pull_range()
函數(shù)都有返回值指示操作是否成功,返回值錯(cuò)誤表示數(shù)據(jù)發(fā)送or數(shù)據(jù)接收沒(méi)有成功乳附,線程中初始化數(shù)據(jù)流的source單元將停止處理線程内地。
buffer的創(chuàng)建:gst_buffer_new()
或從buffer pool中請(qǐng)求可用的buffer:gst_buffer_pool_acquire_buffer()
,當(dāng)使用第二種方法時(shí)许溅,配對(duì)單元可以執(zhí)行定制化的buffer分配算法瓤鼻。
The process of selecting a media type is called caps negotiation.
選擇媒體類(lèi)型的過(guò)程叫:caps negotiation
1.7 Caps
媒體類(lèi)型(Caps)的描述使用包含key/value對(duì)的列表,key類(lèi)型是string贤重,value類(lèi)型是single/list/range of int/float/string茬祷。
帶有變量的Caps也可用于描述可能的媒體類(lèi)型--可被pad處理。
1.8 Dataflow and events
數(shù)據(jù)流并行是一個(gè)事件流并蝗,不同于buffer祭犯,事件可在upstream和downstream之間同時(shí)傳遞,有些事件僅傳送給upstream或downstream滚停。
事件可用于指代數(shù)據(jù)流的特別條件沃粗,如EOS、通知插件的一些具體事件如 flushing or seeking键畴。
一些事件必須用buffer流序列化最盅,序列化的事件在buffer之間插入,沒(méi)有序列化的事件跳到當(dāng)前處理的任何buffer前面起惕。
序列化事件的示例是TAG事件:buffer之間插入TAG事件來(lái)標(biāo)識(shí)這些buffer的metadata涡贱。
非序列化事件的例子:FLUSH事件。
1.9 Pipeline construction
使用gst_pipeline_new()
創(chuàng)建pipeline惹想,使用gst_bin_add()
and gst_bin_remove()
在pipeline中添加和刪除單元
增加單元后问词,通過(guò)gst_element_get_pad()
函數(shù)找回單元的pads纽帖,使用gst_pad_link()
函數(shù)完成pads之間的連接衔统。
當(dāng)真實(shí)的數(shù)據(jù)流出現(xiàn)在pipeline中,一些單元會(huì)創(chuàng)建新的pads橘蜜,當(dāng)單元?jiǎng)?chuàng)建新的pad時(shí)锋叨,g_signal_connect()
函數(shù)會(huì)接收到一個(gè)通知垄分,而后新創(chuàng)建的pads才能連接到其它未連接的pads上。
一些單元不能連接娃磺,因?yàn)樗麄兊臄?shù)據(jù)類(lèi)型不一樣锋喜, gst_pad_get_caps()
函數(shù)可以找回pad支持的數(shù)據(jù)類(lèi)型。
下面創(chuàng)建了一個(gè)MP3播放器的pipeline,后續(xù)的example中將會(huì)使用該示例嘿般。
+-------------------------------------------+
| pipeline |
| +---------+ +----------+ +----------+ |
| | filesrc | | mp3dec | | alsasink | |
| | src-sink src-sink | |
| +---------+ +----------+ +----------+ |
+-------------------------------------------+
1.10 Pipeline clock
pipeline的一個(gè)重要作用:為所有的單元選擇全局時(shí)鐘。
該時(shí)鐘的目的是提供嚴(yán)格的每秒增加值GST_SECOND
涯冠,各單元使用該時(shí)鐘同步數(shù)據(jù)的播放炉奴。
在pipeline狀態(tài)設(shè)置為PLAYING
前,pipeline會(huì)詢(xún)問(wèn)每個(gè)單元是否能提供時(shí)鐘蛇更,時(shí)鐘以下面的順序選擇:
- 應(yīng)用選擇時(shí)鐘瞻赶。
- source單元提供時(shí)鐘。
- 其他單元提供時(shí)鐘派任,從sink開(kāi)始砸逊。
- 如果沒(méi)有單元提供始終,使用pipeline的默認(rèn)系統(tǒng)時(shí)鐘掌逛。
對(duì)典型的播放pipeline师逸,算法將會(huì)選擇sink單元提供的時(shí)鐘,如audio sink豆混。
對(duì)捕捉pipeline篓像,典型地使用數(shù)據(jù)產(chǎn)生器的時(shí)鐘,大都數(shù)情況下不能控制其產(chǎn)生數(shù)據(jù)的數(shù)據(jù)率皿伺。
1.11 Pipeline states
當(dāng)所有pads员辩、所有信號(hào)連接好,pipeline可以放在PAUSED
狀態(tài)以開(kāi)始數(shù)據(jù)流鸵鸥。
當(dāng)bin開(kāi)始轉(zhuǎn)變狀態(tài)奠滑,將改變其所有孩子的狀態(tài)。pipeline將從sink單元到source單元逐步改變孩子的狀態(tài)妒穴,這將確保upstream單元發(fā)送數(shù)據(jù)給其它單元時(shí)宋税,不會(huì)發(fā)生該單元還沒(méi)有準(zhǔn)備好接收的情況。
對(duì)MP3播放pipeline宰翅,單元的狀態(tài)改變依次為alsasink,mp3dec,filesrc弃甥。
下面列出MP3 pipeline中各個(gè)單元的所有中間態(tài)轉(zhuǎn)變,導(dǎo)致下面狀態(tài)改變:
- alsasink 轉(zhuǎn)變?yōu)?code>READY:音頻設(shè)備已準(zhǔn)備好(probed)汁讼。
- mp3dec轉(zhuǎn)變?yōu)?code>READY:Nothing happens
- filesrc轉(zhuǎn)變?yōu)?code>READY:文件已準(zhǔn)備好
- alsasink 轉(zhuǎn)變?yōu)?code>PAUSED:音頻設(shè)備已打開(kāi)淆攻,alsasink作為sink,將返回
ASYNC
(因?yàn)檫€不能接收數(shù)據(jù)) - mp3dec to
PAUSED
: mp3dec轉(zhuǎn)變?yōu)?PAUSED
:解碼庫(kù)已完成初始化嘿架。 - filesrc 轉(zhuǎn)變?yōu)?code>PAUSED:文件已打開(kāi)瓶珊,線程已開(kāi)始push數(shù)據(jù)到mp3dec。
至此耸彪,數(shù)據(jù)流從filesrc--mp3dec--alsasink伞芹,因?yàn)閙p3dec處于PAUSED
狀態(tài),其接收來(lái)自filesrc sinkpad端的數(shù)據(jù),并對(duì)此壓縮的數(shù)據(jù)進(jìn)行解碼為原始音頻格式唱较。
mp3解碼器計(jì)算原始音頻數(shù)據(jù)的采樣率扎唾,信道數(shù)以及其他音頻特性,并發(fā)送媒體類(lèi)型的caps事件南缓。
Alsasink接收該caps事件胸遇,解析caps,并完成自身配置汉形,以能夠處理媒體類(lèi)型纸镊。
mp3dec 將解碼后samples放到Buffer中,繼而給buffer發(fā)送給下一個(gè)單元概疆。
Alsasink接收帶有samples的buffer逗威,因?yàn)樗邮誷amples的第一個(gè)buffer,完成狀態(tài)轉(zhuǎn)變?yōu)镻AUSED狀態(tài)岔冀,pipeline已prerolled凯旭,所有的單元都有samples
,此時(shí)Alsasink有能力提供時(shí)鐘給pipeline楣颠。
alsasink處于PAUSED
狀態(tài)尽纽,接收第一個(gè)buffer數(shù)據(jù),alsasink blocks童漩。mp3dec 和filesrc 在 gst_pad_push()
中也是blocks弄贿。
所有單元gst_element_get_state()
函數(shù)返回SUCCESS
,pipeline可以變?yōu)?code>PLAYING狀態(tài)矫膨。
在進(jìn)入PLAYING
之前差凹,pipeline會(huì)選擇一時(shí)鐘,采樣時(shí)鐘的當(dāng)前時(shí)間侧馅,成為base_time
危尿,將該時(shí)間分配給所有單元,各單元利用該時(shí)鐘的 running_time
base_time
實(shí)現(xiàn)同步馁痴,詳見(jiàn):synchronisation
而后發(fā)生下面的狀態(tài)轉(zhuǎn)變:
alsasink to
PLAYING
: 解碼后的數(shù)據(jù)在音頻設(shè)備中播放谊娇。mp3dec 轉(zhuǎn)變?yōu)?code>PLAYING:Nothing Happens。
轉(zhuǎn)變?yōu)?code>PLAYING:Nothing Happens
1.12 Pipeline status
pipeline通過(guò)bus給應(yīng)用發(fā)具體事件罗晕,bus是pipieline提供的一個(gè)對(duì)象济欢,可通過(guò)gst_pipeline_get_bus()
配置。
bus能夠被polled 或增加到glib mainloop小渊。
bus分布在所有單元中法褥,單元使用bus往上層推送消息,消息類(lèi)型主要有:ERRORS
, WARNINGS
, EOS
, STATE_CHANGED
等酬屉。
pipeline以一特別的方式來(lái)處理來(lái)自單元的EOS
消息半等,當(dāng)所有sink單元向上推送EOS
消息時(shí)揍愁,僅發(fā)送第一條給應(yīng)用。
其他的獲取pipeline狀態(tài)包括:詢(xún)問(wèn)功能(Query functionality)杀饵,通過(guò)執(zhí)行函數(shù) gst_element_query()
獲取狀態(tài)莽囤,詢(xún)問(wèn)的類(lèi)型對(duì)于獲取pipeline的位置及總時(shí)間信息是非常有用的,也可以用于詢(xún)問(wèn)支持的seeking格式和范圍凹髓。
1.13 Pipeline EOS
當(dāng)source濾波器遇到數(shù)據(jù)流的結(jié)束部分烁登,將發(fā)出EOS事件給配對(duì)的單元,該事件將會(huì)通知downstream單元以及與其連接的所有單元蔚舀,配對(duì)端sink pad收到EOS事件后,將不會(huì)接收任何數(shù)據(jù)锨络。
單元在發(fā)送完EOS
事件后赌躺,將停止提供流線程。
EOS事件最終會(huì)到達(dá)sink單元羡儿,sink單元將在bus上發(fā)送EOS
消息礼患,以通知pipeline一個(gè)特別的數(shù)據(jù)流已經(jīng)完成。當(dāng)所有的sink都向上發(fā)送EOS消息掠归,pipeline僅向應(yīng)用發(fā)送第一條EOS
消息缅叠。EOS
消息僅在PLAYING
狀態(tài)下發(fā)送給應(yīng)用。
當(dāng)處于EOS
虏冻,pipeline保持PLAYING
狀態(tài)肤粱,這是應(yīng)用的職責(zé)對(duì)于PAUSE
or READY
pipeline。應(yīng)用還可以發(fā)布seek厨相。
1.14 Pipeline READY
當(dāng)運(yùn)行的pipeline從 PLAYING
變?yōu)?code>READY狀態(tài)领曼,pipeline接下來(lái)將發(fā)生:
alsasink轉(zhuǎn)為 PAUSED
,alsasink將在下一個(gè)樣本完成狀態(tài)改變蛮穿,若單元之前是EOS
庶骄,將不會(huì)等待樣本完成狀態(tài)轉(zhuǎn)變。
- mp3dec to
PAUSED
: Nothing. - filesrc to
PAUSED
: Nothing
轉(zhuǎn)換到中間態(tài)PAUSED
践磅,將阻止所有的單元( _push()
函數(shù))单刁,這是由于sink單元接收完第一個(gè)buffer后阻止后面的數(shù)據(jù)傳輸。
Some elements might be performing blocking operations in the PLAYING
state that must be unblocked when they go into the PAUSED state. This makes sure that the state change happens very fast.
有些單元在PLAYING
狀態(tài)下也會(huì)出現(xiàn)阻止操作府适,在這些單元進(jìn)入到PAUSED狀態(tài)時(shí)羔飞,必須放開(kāi)。確保狀態(tài)能夠快速轉(zhuǎn)變细溅。
下一個(gè)PAUSED
到READY
狀態(tài)的改變褥傍,pipeline關(guān)閉,所有流線程需停止數(shù)據(jù)傳輸喇聊,過(guò)程如下:
- alsasink轉(zhuǎn)為
READY
:alsasink放開(kāi)(_chain()
函數(shù))恍风,函數(shù)FLUSHING
返回值發(fā)送給配對(duì)的單元,sinkpad此時(shí)為非激活狀態(tài)不能用于發(fā)送數(shù)據(jù)。 - mp3dec轉(zhuǎn)為
READY
:pads進(jìn)入非激活狀態(tài)朋贬,當(dāng)mp3dec離開(kāi)_chain()
函數(shù)后完成狀態(tài)變化凯楔。 - filesrc轉(zhuǎn)為
READY
:pads進(jìn)入非激活狀態(tài),線程停止锦募。
由于downstream單元返回一個(gè)錯(cuò)誤代碼(_push()
返回FLUSHING
)摆屯,upstream單元完成_chain()
函數(shù)。這個(gè)錯(cuò)誤代碼最終會(huì)反饋開(kāi)始流線程的單元(filesrc)糠亩,filesrc將停止線程并完成狀態(tài)改變虐骑。
這個(gè)事件的順序使得所有的單元放開(kāi),所有的流線程停止赎线。
1.15 Pipeline seeking
pipeline seeking需要嚴(yán)格的操作步驟廷没,以確保單元保持同步,seek以最小的延遲運(yùn)行垂寥。
應(yīng)用通過(guò)單元gst_element_send_event()
函數(shù)觸發(fā)pipeline上seek事件颠黎,該事件可以是單元支持的任何格式的seek事件。
pipeline暫停pipeline以加速seek操作滞项。
pipeline繼而將seek事件發(fā)送給所有sink單元狭归。sink前傳seek事件給upstream直到某個(gè)單元對(duì)seek事件進(jìn)行操作。所有的中間單元可以給seek偏置轉(zhuǎn)為另外的格式文判,由此过椎,解碼器單元能夠?qū)eek轉(zhuǎn)為時(shí)間戳的幀數(shù)。
當(dāng)seek事件到達(dá)一個(gè)單元律杠,將執(zhí)行seek操作潭流,單元相應(yīng)地執(zhí)行下面步驟:
- 發(fā)送
FLUSH_START
事件給配對(duì)的所有downstream和upstream單元。 - 確保流線程沒(méi)有運(yùn)行柜去,因?yàn)椴襟E1灰嫉,流線程將一直是停止。
- 執(zhí)行seek操作嗓奢。
- 發(fā)送
FLUSH
完成事件給所有配對(duì)的downstream和upstream讼撒。 - 發(fā)送
SEGMENT
事件通知新位置的所有的單元,完成seek操作股耽。
步驟1中所有的downstream單元必須從所有的阻塞操作返回根盒,必須拒絕接下來(lái)的任何buffer或者除FLUSH
外的其它事件。
第一個(gè)步驟確保流線程最終解除阻塞物蝙,繼而第二步可以操作炎滞,此時(shí)pipeline的數(shù)據(jù)流全面停止。
步驟3诬乞,單元執(zhí)行請(qǐng)求位置的seek操作册赛。
步驟4钠导,所有的配對(duì)單元又能夠接收數(shù)據(jù),新位置的數(shù)據(jù)流能夠連續(xù)森瘪,F(xiàn)LUSH完成事件發(fā)送給所有配對(duì)單元牡属,配對(duì)單元也能夠接收新的數(shù)據(jù),開(kāi)啟其數(shù)據(jù)流線程扼睬。
步驟5逮栅,通知新位置的所有單元,事件函數(shù)返回應(yīng)用窗宇,流線程開(kāi)始處理新的數(shù)據(jù)措伐。
因?yàn)閜ipeline仍然處于PAUSED
狀態(tài),這將在sink端預(yù)處理下一個(gè)媒體樣本军俊,應(yīng)用可以用_get_state()
函數(shù)等待預(yù)處理完成废士。
seek操作的最后一步是調(diào)節(jié)pipeline流的running_time
=0,設(shè)置pipeline返回PLAYING
狀態(tài)蝇完。
MP3播放器示例中的seek事件順序:
| a) seek on pipeline
| b) PAUSE pipeline
+----------------------------------V--------+
| pipeline | c) seek on sink
| +---------+ +----------+ +---V------+ |
| | filesrc | | mp3dec | | alsasink | |
| | src-sink src-sink | |
| +---------+ +----------+ +----|-----+ |
+-----------------------------------|-------+
<------------------------+
d) seek travels upstream
--------------------------> 1) FLUSH event
| 2) stop streaming
| 3) perform seek
--------------------------> 4) FLUSH done event
--------------------------> 5) SEGMENT event
| e) update running_time to 0
| f) PLAY pipeline