本文轉載自許野平的博客
版權聲明:本文爲博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
他的博客有很多關於GStreamer的好文章,並非官網文檔翻譯,基本是按照他自己的理解來寫,適合理解
1
話說 gst-launch-1.0 這條命令老牛掰了,看是很複雜的媒體流,用這條命令,一行代碼就搞定了。看看下面這行代碼,區區幾十個字符,就建立了測試視頻流:
gst-launch-1.0 videotestsrc ! autovideosink
- 1
運行後可以在屏幕上顯示視頻測試圖案,大概就是下面這個樣子:
那些包含視頻、音頻,甚至用戶定製信號的複雜媒體流,也能用 gst-launch-1.0 這樣子玩嗎?當然沒問題。我們接下來聊聊如何構建複雜媒體流管道。
2
在剛纔的例子中,我們的管道描述串是 videotestsrc ! autovideosink
,它包括了三個部分:
- 管道起始點:
videotestsrc
- 管道的終點:
autovideosink
- 起點和終點的連接:
!
這個管道描述串的意思是,把元素 videotestsrc
連接到元素 autovideosink
上。
說到這裏,很多人很納悶,不是說元素之間只能通過 Pad 鏈接嗎?這裏怎麼直接連接元素呢?實際上這是一個簡化用法,因爲 videotestsrc
只有一個輸出 Pad,autovideosink
也只有一個輸入 Pad,這種情況下,就不需要再說明怎麼樣用 Pad 連接了。不過,上面這個例子完整的說明應該如下:
gst-launch-1.0 videotestsrc name=a a.src ! b.sink autovideosink name=b
- 1
看暈了吧?其實不復雜,聽我繼續道來…
3
gst-launch-1.0 的基本語法是
gst-launch-1.0 元素名稱 屬性=... 元素名稱 屬性=... ... 元素.SrcPad名稱 ! 元素.SinkPad名稱
- 1
所以,根據我們上面的例子,可以寫出下面的命令行:
gst-launch-1.0 videotestsrc autovideosink
- 1
沒看錯吧?元素之間竟然沒有 !
符號。沒錯,命令行運行後並沒出現語法錯誤,只是這個管道並不會工作,因爲沒有鏈接。此時,管道描述符包含兩個部分:
- 第一個元素:
videotestsrc
- 第二個元素:
autovideosink
要建立連接,就需要給元素命名:
gst-launch-1.0 videotestsrc name=a autovideosink name=b
- 1
當然,因爲還沒加入鏈接,當然還是不工作。此時,管道描述符仍然只包含兩個部分:
- 第一個元素:
videotestsrc name=a
- 第二個元素:
autovideosink name=b
下面加入鏈接:
gst-launch-1.0 videotestsrc name=a autovideosink name=b a.src ! b.sink
- 1
運行一下,OK,很完美。
4
注意到沒有,這次連接的位置竟然與剛纔的例子不一樣。其實,gst-launch-1.0 不在乎排列順序。這個例子中,管道描述串包括三個部分:
- 第一個元素:
videotestsrc name=a
- 第二個元素:
autovideosink name=b
- 連接:
a.src ! b.sink
這三個部分可以任意排列。這三個部分之間並沒有標點符號,會不會弄混?仔細分析一下就能發現,不會。因爲元素名稱前後都是空格,沒有其他符號。元素的屬性賦值(比如 name=a)有等號連接,連接描述有感嘆號連接。所以,儘管描述串很複雜,而且無序,但不會弄錯。
所以,前面看到的那個例子,管道描述串中也是由上面三個部分構成,只是順序調整了一下,讓人覺得很神的樣子。你看一下能分出來三個部分嗎?
gst-launch-1.0 videotestsrc name=a a.src ! b.sink autovideosink name=b
- 1
5
我們怎麼能知道 videotestsrc
的 Pad 名稱是 src
?這個不難,用命令 gst-inspect-1.0 videotestsrc
查看即可。gst-inspect-1.0 是研究插件庫的好工具,一定要用好!
使用 gst-inspect-1.0 我們發現, videotestsrc
有一個叫做 pattern 的屬性,默認值是 0,最大值可以取到 24。接下來我們改成 1 看看:
gst-launch-1.0 videotestsrc pattern=1 ! autovideosink
- 1
正如 gst-inspect-1.0 說的那樣,這個是雪花 snow 模式!
6
剛纔的例子,分辨率太低了,能不能轉換成高清視頻?當然沒問題,我們利用 CAPS 轉換,強迫 Pad 之間的連接通過我們指定的 CAPS 進行。看下面的例子:
gst-launch-1.0 videotestsrc ! video/x-raw, width=1920, height=1080 ! autovideosink
- 1
也可以:
gst-launch-1.0 videotestsrc name=a autovideosink name=b a.src ! video/x-raw, width=1920, height=1080 ! b.sink
- 1
需要注意兩點:
a.src ! video/x-raw, width=1920, height=1080 ! b.sink
是一個鏈接,不可亂序video/x-raw, width=1920, height=1080
是 CAPS 說明,其中的屬性之間用逗號隔開。這個表示方法與元素是不一樣的,元素的屬性是用空格隔開的。
7
因爲 CAPS 的屬性可能很複雜,比如 video/x-raw(memory:NVMM), width=(int)1920, height=(int)1080, format=(string)NV12
這種裏面帶括號的,無法直接放到 gst-launch-1.0。另外,CAPS標識如果太簡單也可能與元素無法區別。於是,這類 CAPS 必須用單引號或雙引號括起來,明確告訴 gst-launch-1.0 這是一個 CAPS 說明。所以下面的例子也是合法的:
gst-launch-1.0 videotestsrc ! 'video/x-raw, width=1920, height=1080' ! autovideosink
gst-launch-1.0 videotestsrc ! "video/x-raw, width=1920, height=1080" ! autovideosink
- 1
- 2
到此爲止,我覺得建立管道描述串的知識應該夠用了,我不能再講了,否則你知道的就太多了,哈哈哈哈!
謝謝閱讀,如果有用,請點贊收藏,如有問題,歡迎留言!
================
補充知識:GStreamer 插件體系簡介
GStreamer 系統一個很重要的想法就是把媒體流拆解成了插件,插件通過連接組合,構造出複雜的媒體流管道。
GStreamer 的插件是以動態庫,也就是 .so 形式發佈,原則上我們不需要其源代碼。這些插件在 GStreamer 系統中註冊以後,我們就可以通過其註冊名稱找到它們,也可以通過其名稱加載 .so 庫代碼,並調用相關功能。
建立一個這樣的註冊體系是一個很複雜的事情,但是我們用起來卻省了很多事。我們可以在沒有這些插件源代碼的情況下,靈活運用這些插件。用一個簡單的字符串,構造出通常需要成千上萬行代碼才能寫出的系統。前面的那一條例子,如果用 C 語言寫代碼實現的話,即使同樣利用這些插件,也需要幾十行甚至數百行代碼才能實現。
所以, gst-launch-1.0 這條命令,實際上扮演了一個解釋程序的角色,可以把管道描述字符串翻譯成複雜的代碼,最終按照要求爲我們構建的媒體流管道。
在我開發用的 Jetson Nano 上,GStreamer 的插件安裝在目錄 /usr/lib/aarch64-linux-gnu/gstreamer-1.0
下,文件名是:libgstvideotestsrc.so
。參見下面的截圖:
可以用 gst-inspect-1.0 命令查看 GStreamer 系統註冊的插件。當然,我們也可以自己編寫插件,最基本的入門參見:
- 《編寫 GStreamer 插件1:概述》
- 《編寫 GStreamer 插件2:編寫插件的基礎知識(一)》
- 《編寫 GStreamer 插件2:編寫插件的基礎知識(二)》
- 《在 Jetson Nano 上編寫 GStreamer 插件 ——實現自己的第一個作品》
參考資料