Gstreamer多路流同步

(Original: http://blog.csdn.net/niehanzi/article/details/6614841)

Gstreamer多路流同步(翻譯自part-synchronisation.txt)


    該篇文檔描述了gstreamer多路流的同步技術的概要。
    GstPipeline的同步用如下的3個組件完成:
    1)GstClock,在GstPipeline中對所有元素來說是全局的。
    2)GstBuffer的Timestamps。
    3)在發送buffer(數據流)之前的NEW_SEGMENT。

A GstClock 
~~~~~~~~~~
    GstClock單位是納秒,一個計數器,描述了當前的時間,該值也是絕對時間。
    如下的幾個源可以提供時間計數器:
    1)系統時間,微妙級的精度,用g_get_current_time函數獲取。
    2)音頻設備(基於採樣率)。
    3)一個網絡源,例如RTP源,RTP包中帶有時間戳。
    ......
    在Gstreamer中,任何元素提供的GstClock對象都可以用到pipeline中。GstPipeline對象將從時鐘提供者中選擇一個分發給所有其它的元素。
    GstClock總是向上遞增的,不一定要從0開始。

Running time 
~~~~~~~~~~~~
    當pipeline選擇了一個時鐘,它將基於選定的時鐘維護running_time,running_time表示處於PLAYING狀態的總的時間,按照如下方式計算:
    1)如果pipeline的狀態是NULL/READY,running_time是未定義的。
    2)在PAUSED狀態,running_time保持在暫停的時間。如果pipeline是第一次暫停,running_time是0。
    3)在PLAYING狀態,running_time是absolute_time和base_time的差值。當處於PLAYING狀態時, base_time = absolute_time - running_time。
    4)在執行了flushing seek,running_time被設置成0,base_time被重新設置,相當於重新開始。
    當pipeline從PLAYING -> PAUSED狀態時,保存住running_time;當恢復成PLAYING狀態時,重新開始計算running_time。當pipeline是PAUSED狀態時,不論選定時鐘是否繼續穩步增加,都不會影響到running_time的計算。
    時鐘和pipeline用running_time爲所有的元素進行同步。在PLAYING狀態下,running_time能夠在每一個元素中被觀察到,計算公式如下:
    C.running_time = absolute_time - base_time
    C.running_time也就是running_time,該值以時鐘的速率單調遞增。

Timestamps
~~~~~~~~~~
    GstBuffer timestamps和在buffer(數據流)之前的NEW_SEGMENT event定義了一個轉換從buffer timestamps到running_time,計算如下:
定義:
B.running_time:running_time
B: GstBuffer 
   - B.timestamp:buffer timestamp (GST_BUFFER_TIMESTAMP) 
NS: NEWSEGMENT event
  - NS.start: start field in the NEWSEGMENT event
  - NS.stop: stop field in the NEWSEGMENT event
  - NS.rate: rate field of NEWSEGMENT event
  - NS.abs_rate: absolute value of rate field of NEWSEGMENT event
  - NS.time: time field in the NEWSEGMENT event
  - NS.accum: total accumulated time of all previous NEWSEGMENT events. This field is kept in the GstSegment structure.
    滿足B.timestamp >= NS.start && B.timestamp <= NS.stop的GstBuffer實例是有效的,在這個範圍之外的其它buffer將被丟棄。
    B.timestamp到B.running_time的轉換公式如下:
    if (NS.rate > 0.0) 
        B.running_time = (B.timestamp - NS.start) / NS.abs_rate + NS.accum 
    else 
        B.running_time = (NS.stop - B.timestamp) / NS.abs_rate + NS.accum
     由於B.running_time就是running_time,所以running_time是從NEWSEGMENT event和buffer而來的。
     所以根據第一個有效地buffer計算出來的running_time爲0,既然B.timestamp == NS.start and NS.accum == 0。

Synchronisation 
~~~~~~~~~~~~~~~
    我們可以用如下方法得到running_time:
    1)用選定的時鐘和元素的base_time:
    C.running_time = absolute_time - base_time
    2)用buffer timestamp和之前的NEWSEGMENT event(假定播放速率爲正):
    B.running_time = (B.timestamp - NS.start) / NS.abs_rate + NS.accum
    running_time的前綴C和B表示兩種不同的計算方法。
    同步播放就是要確保:當播放一個時間戳是B.running_time的buffer時,時鐘必須達到了C.running_time,也就是說當:
                          B.running_time = C.running_time時,
播放buffer裏面的數據。因此可以擴展到如下的公式:
                          B.running_time = absolute_time - base_time
或者
                          absolute_time = B.running_time + base_time
記B.sync_time爲buffer應該被播放時的絕對時間,因此得到:
                          B.sync_time = B.running_time + base_time
    對於多路流來說,擁有同樣的running_time的buffers將被同時播放。demuxer元素在它的所有的src pad上發送NEWSEGMENT消息來確保同步的buffer具有同樣的時間戳。

Stream time 
~~~~~~~~~~~
    Stream time是流的位置,值介於0和媒體文件的長度(時間爲單位)。有如下作用:
    1)POSITION查詢
    2)seek事件中的position的設置
    3)the position used to synchronize controller values
    可以按照如下的方式來計算stream time,推導過程如下:

    C.running_time = absolute_time - base_time 
    B.running_time = (B.timestamp - NS.start) / NS.abs_rate + NS.accum
=>
    (B.timestamp - NS.start) / NS.abs_rate + NS.accum = absolute_time - base_time;
=>
    (B.timestamp - NS.start) / NS.abs_rate = absolute_time - base_time - NS.accum;
=>
    (B.timestamp - NS.start) = (absolute_time - base_time - NS.accum) * NS.abs_rate
    又因爲
    stream_time = (B.timestamp - NS.start) * NS.abs_applied_rate + NS.time
=>
    stream_time = (absolute_time - base_time - NS.accum) * NS.abs_rate * NS.abs_applied_rate + NS.time
     最後得到的公式常被用來在sink元素中查詢當前播放的位置。

     需要注意的是:stream time從來沒有參與多路流的時鐘同步。

-----------------------------------------------------------------------------------------------------------------------------------------
終於翻譯完這篇了。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章