Linux 的應用(刊載於 PC2000 雜誌八月號)-- Video Streaming 探討 (3)

jollen 發表於 July 17, 2001 6:49 AM

本期的重點在介紹影像擷取卡與影像擷取卡常見的 BT848/BT878 晶片。除了介紹影像擷取卡外, 也會來看 xawtv 這個有名的 video4linux/BTTV 應用程式。

作者: 陳俊宏 (www.jollen.org)

什麼是影像擷取卡

影像擷取卡的主要功能當然就是做影像的擷取了, 一張影像擷取卡應該擁有底下的基本功能。

影像擷取

影像擷取卡可擷取的影像頁框 (frame) 的大小是很重要的, 本文第一篇裡提到的幾個基本影像頁框大小都應該要支援, 包含 NTSC (640x480) 與 PAL (768x576)。

影像擷取卡所捕捉的畫面都是屬於動態的畫面, 影像的來源則要看所支援的視訊系統與所有的視訊裝置。

支援的視訊系統

大部份影像擷取卡都會具備一組視訊輸入端子, 即 S-Video (Y/C) 端子或 Composite 端子。

在台灣的標準當然是 NTSC 系統, 一般而言, 我們是希望一張影像擷取卡可以支援越多視訊系統越好, 包括: NTSC/PAL/PALN/PLAM/SECAM。

可使用的視訊裝置有較常見的 CCD, 或是家用 V8、Hi8 皆可, 一般而言我們也是希望一張影像擷取卡可以接越多視訊裝置越好。

安裝影像擷取卡

以筆者的影像擷取卡為例,使用的是 Chronos Video Shuttle I 的卡,所以只要安裝 bttv 模組即可,同時,bttv 模組在 Linux kernel 2.2.17 下也會用到 i2c-old 與 videodev 兩個模組,所以也要一併安裝。在命令列下,安裝這三個模組的命令為:

linux# insmod i2c-old
linux# insmod videodev
linux# insmod bttv

當然要確定 Linux kernel 有編譯這三個模組的支援,然後再把這三個模組加到 /etc/modules.conf (Red Hat 7.0) 裡。

如果是使用 Linux kernel 2.4.x (如 Red Hat Linux 7.1), 也可以直接在 /etc/modules.conf 裡加上一行:

alias char-major-81 bttv

就可以了。然後再利用上一篇文章 (2) 的程式來做初始化, 可以看到底下的訊息:

/dev/video0: initialization OK... BT878(Chronos Video Shuttle I)
3 channels
3 audios

OK!

BT878 晶片初始化成功, 影象擷取卡名稱為 Chronos Video Shuttle I, 成功找到並初始化 3 個 channel。

bttv 模組就是底下會提到的 BTTV 軀動程式, 主要用途是軀動影像擷取卡上的 BT848/BT878 晶片。

影像擷取卡的應用

在 PC 上加裝影像擷取卡, 就可以利用 PC 做影片剪輯的工作, 例如可以將類比的 V8 影片轉換成數位影像, 並且儲存到電腦裡, 或製作成光碟保存。

配合這類的軟體, 我們還可以 DIY 做影像的特效、轉場特效、字幕、旁白等等。利用 PC 做影像剪輯的工是很耗電腦資源的, 所以不能用太陽春的 PC, 不然可以會很累人的!

壓縮比

壓縮比是判斷一張影像擷取卡優劣的主要關鍵所在, 由於動態的影像所佔用的空間相當大, 所以如果一張影像擷取卡無法有效將擷取出來的影像做壓縮, 所需的硬碟空間都會相當驚人。

壓縮比越好的影像擷取卡, 其工作效能越佳, 一般壓縮比大約是 4:1, 使用壓縮比越好的晶片, 當然也就越貴, 所以影像擷取卡是一分錢一分貨的。

BT 878 晶片

目前大部份的數位影像擷取卡大部份都是以 BT878 單顆晶片為影像擷取卡之中心。BT878 運作方式是以軟體來進行影像解壓縮工作, BT878 晶片負責將擷取之影像丟給 Linux 做影像處理, 而 BTTV 則是 Linux kernel 的 BT878 晶片軀動程式。

由於影像是利用 BT878 擷取後交由軟體來做影像處理, 因此在處理效能上自然就會比較差。如果是經由網路來傳送影像的話, 我們就會再利用影像壓縮技術 (H.261/H.263...等等) 來做影像處理。

什麼是 BTTV

BTTV 是 Linux 上的 Bt848/849/878/879 晶片的軀動程式, 主要功能是做頁框
的截取 (frame grabber)。

BTTV 是 video4linux 裡重要的軀動程式, 目前分為二個版本:

  • 0.8.x 的發展中版本
  • 0.7.x 的穩定版本

Linux 上可用的影像擷取卡

在http://www.linhardware.com/db/searchproduct.cgi?_catid=17 網頁上可以找到在 Linux 上支援程度比較好的幾張影像擷取卡。而一般 Linux 上較受歡迎的影像擷取卡則是 Hauppauge 的幾張卡, 筆者使用的也是 Hauppauge 的卡。

在 linhardware 網站上可以找到底下六張卡:

  • Hauppauge 401 WinTV-radio dbx-TV stereo
  • Hauppauge WinTV PCI TV Card
  • Hauppauge WinTV-GO PCI TV Card
  • Hauppauge WinTV-PCI Hauppauge
  • Hauppauge WinTV-Radio+NICAM
  • Hauppauge WinTV/PCI TV Card

關於 Linux 對於影像捕捉卡支援的中文文件 (HOWTO) 可以在 CLDP 網站上取得:

http://www.linux.org.tw/CLDP/Hardware-HOWTO-22.html

BTTV 相關軟體 - xawtv

官方網站: http://bytesex.org/xawtv/index.html

安裝方式:

1. linux# ./configure
2. linux# make depend
3. linux# make
4. linux# make install

如果您有 Red Hat Linux 7.1 PowerTools 光碟片的話, 也可以直接由 PowerTools 光碟片安裝 xawtv 套件:

linux# rpm -ivh xawtv-3.34-1.i386.rpm

安裝 xawtv 需要 libjpeg 與 libjpeg-devel 套件, 如果您是使用 Red Hat Linux 7.1 的話, 應該安裝底下二個套件:

libjpeg-6b-15.i386.rpm (Disc 1)
libjpeg-devel-6b-15.i386.rpm (Disc 2)

xawtv 整個架構可以分成 7 個部份如下:

  • xawtv: 主程式部份。
  • fbtv: linux console 模式的 TV 應用程式, 使用 linux kernel 2.2.x 的 framebuffer。
  • set-tv: 命令列模式的工具, 用來設定 video4linux 的參數。
  • streamer: 命令列模式的工具, 用來捉取動態影像與 avi 影像。
  • radio: radio 應用程式。
  • webcam: 將捉取的影像以 FTP 方式上傳到 Web Server 端, 用來設計 Web 即時影像的工具。
  • alevtd: videotext pages 的 Web Server。

xawtv 的 video4linux

xawtv 是相當好的 video4linux 方面的教材, 在上一期我們看過一遍 video4linux 的設計方法後, 接下來我們要先捨棄我們上一期所實作的 video4linux 程式庫!

因為我們將要帶導大家研究 xawtv 裡以 video4linux API 設計的影像捕捉 (grab) 部份的程式碼, 這個程式碼的實作更完整, 因此在開始進入這個主題前, 必須先理解上一期所介紹的內容, 並且懂得我們實作的程式庫內容, 才能順利進入狀況。

取回 xawtv 的原始程式碼解開後, 在 libng/ 目錄下可以看到 grab-v4l.c 的檔案, 另外還有一個 grab-v4l2.c 的檔案, 這是 video4linux2 (version 2) 的版本。這裡我們先介紹 video4linux 的版本 -grab-v4l.c。

grab-v4l.c 的程式碼架構

大略掃瞄過 grab-v4l.c 的程式碼後, 發現 grab-v4l.c 與上一期我們實作的 video4linux 程式庫的架構很像。

其實大多數利用 video4linux 來設計應用程式的軟體, 其 video4linux 的 API 部份大多是自行重寫的, 反而很少利用現成的程式庫, 因此仔細研究別人的程式碼, 再來改進我們自己的 video4linux 程式庫是我們的最終目的。

程式一開始也是宣告了一個 ng_driver 結構的變數 (v4l_driver):

#ifndef __linux__
const struct ng_driver v4l_driver;
#else /* __linux__ */

然後可以看到 open 與 close 二個函數:

static void* v4l_open(char *device);
static int v4l_close(void *handle);

接下來還有許多函數的宣告, 同時還可以看到一些結構的宣告, 例如:

static struct STRTAB norms_v4l[] = {
{ VIDEO_MODE_PAL, "PAL" },
{ VIDEO_MODE_NTSC, "NTSC" },
{ VIDEO_MODE_SECAM, "SECAM" },
{ VIDEO_MODE_AUTO, "AUTO" },
{ -1, NULL }
};

我們可以用來顯示 channel 是 PAL/NTSC/SECAM 或是 AUTO。

xawtv 實作出來的 v4l_open() 函數可精彩了, 除了有設計函數應該要有的嚴謹的錯誤檢查外, v4l_open 也對硬體做了一些檢查。

xawtv 的 v4l 程式庫也有 v4l_close() 函數, 用來關閉已開啟的 video4linux 裝置。

在影像頁框擷取方面, 共有底下 5 個函數:

static int v4l_setformat(void *handle, struct ng_video_fmt *fmt);
static int v4l_startvideo(void *handle, int fps, int buffers);
static void v4l_stopvideo(void *handle);
static struct ng_video_buf* v4l_nextframe(void *handle);
static struct ng_video_buf* v4l_getimage(void *handle);

函數的名稱已經將其功能表達的很清楚了, 因此不再重覆解釋。另外比較特別的是, xawtv 的 video4linux 也支援了 framebuffer, 主要函數為:

int v4l_setupfb(void *handle, struct ng_video_fmt *fmt, void *base)

xawtv 的 video4linux 程式庫整體架構相當明白簡單, 程式碼也很好懂, 剩下的重點在於如何利用 video4linux 的 mmap 模式來擷取二頁的影像, xawtv 的 video4linux 程式庫的使用方式我們只要了解這一點即可。
xawtv 的 video4linux 其中對影像擷取卡做初始化的方法我們已經會了, 再來就是做影象擷取的部份。

mmap 方式我們將在下一期再做介紹。接下來的部份將瀏覽一下 xawtv 的功能架構與使用界面, 以利我們去研究 xawtv 的程式碼, 並且還會介紹一個 Linux 下的 MP3 撥放程式 --, 會介紹 xxx 的原因是因為 xxx 也用到了 streaming 的技術來撥放 MP3 檔案。

xawtv 的功能

底下我們將展示以 CCD (Composite 端子) 視訊裝置輸入影像, 並且利用 xawtv 顯示動態影象的設定方式。

xawtv 的輸出結果


圖 1

這是 xawtv 顯示動態影象的結果, 我們利用的是 CCD 視訊裝置, 視訊來源為 Composite, TV Norm 為 NTSC。

要有正確的顯示結果, 必須正確地設定 TV Norm 與 Video Source 兩個項目。

xawtv 的設定選單

在 xawtv 的主畫面按二下滑鼠右鍵後, 就會出現圖 2 的視窗。幾個常用的功能說明如下:

  • Full Screen on/off: 切換是否要全螢幕顯示, 不過影像的大小則是跟視訊裝置有關。
  • Grab Image: 將目前的畫面存成圖檔 (ppm 或 jpeg)。
  • Record Movie (avi): 錄製 avi 的電影檔。
  • Bright/Hue/Contrast/Color: 調整視訊的對比、亮度、顏色。


圖2

設定 TV Norm

點取 TV Norm 項目後, 將 TV Norm 設定在正確的參數, 筆者使用的是 NTSC 的 CCD, 因此必須將這個項目設成 NTSC。

#圖: xawtv-03.tif
圖 3

設定 Video Source

點取 Video Source 後, 再選取正確的視訊來源, 大部份的 CCD 都是 Compoiste 端子, 因此選擇 Composite1。

#圖: xawtv-04.tif
圖 4

xawtv 會列出目前影像擷取卡可用的視訊來源, 我們只要將視訊裝置接到正確的視訊來源, 並完成 TV Norm 與 Video Source 的設定後就可以正確顯示動態影像了。

利用 video4linux 來初始化影像擷取卡的方法在上一篇文章 (2) 中已列出完整範例程式碼, 並且做了詳細的說明。下一期我們將會更進一步來撰寫設定 TV Norm 與 Video Source 的程式碼。

配合介紹如何設計 TV Norm 與 Video Source 的設定程式碼, 我們還會根據 xawtv 的幾個功能並配合 video4linux 來實作 xawtv 上的功能 (frame grab), 並且會列出完整的程式碼範例做說明。

xawtv 也提供針對 FreeBSD 與 OpenBSD 的 BT848/BT878 軀動程式 (bktr) 所設計的影像擷取功能, 原始程式碼放在 xawtv 裡的 libng/ 目錄, 檔名為 grab-bsd.c 檔案。

(MP3 - streaming 部份...)

Jollen's Blog 使用 Github issues 與讀者交流討論。請點擊上方的文章專屬 issue,或 open a new issue

您可透過電子郵件 jollen@jollen.org,或是 Linkedin 與我連絡。更歡迎使用微信,請搜尋 WeChat ID:jollentw