摘要:該文闡述了在Linux下,利用V4L以及ALSA,在普通PC上組建視頻音頻采集系統(tǒng)以及遠程傳輸?shù)姆椒ā?/p>
關(guān)鍵詞:Linux;視頻;音頻;V4L;ALSA
中圖分類號:TP311文獻標識碼:A文章編號:1009-3044(2008)22-675-03
A Linux Based General Video and Audio Sampling System
GONG Zhou,KANG Ye
(Department ofChinese-German, Tongji University, Shanghai 200092, China)
Abstract: In this paper, the constraction of video and audio sampling system, which bases on Linux with V4L and AlSA, will be discussed.
Key words: Linux; Video; Audio; V4L; AlSA
1 引言
Linux是一個基于Unix的操作系統(tǒng),它也是Unix家族的一元,與Unix不同的是它可以運行在不同的硬件平臺上。它于1991年誕生于芬蘭的一個為大學生Linus Torvalds手中,不過當時還只是一個雛形,為了不讓自己的這個羽翼未滿的操作系統(tǒng)夭折,Linus將自已的作品Linux通過Internet發(fā)布。從此一大批知名的、不知名的電腦黑客、編程人員加入到開發(fā)過程中來,Linux逐漸成長起來。到目前為止,Linux的內(nèi)核已經(jīng)發(fā)展到了2.6.22,并在此基礎(chǔ)上發(fā)展了數(shù)十種發(fā)行版,其中有經(jīng)過長期發(fā)展洗禮的Redhat(Fedora),也有發(fā)展迅猛使用方便的Ubuntu。
在多媒體技術(shù)中,視頻技術(shù)發(fā)展越來越迅速,比如在遠程教育、在線視頻會議、銀行監(jiān)控、危險地區(qū)探測以及智能家庭安防方面應用越來越廣泛。由于Linux自身的特殊的發(fā)展過程使得它具有了得天獨厚的網(wǎng)絡(luò)性能,加上越來越豐富的視頻支持和開源軟件的優(yōu)勢以及對不同硬件平臺的良好支持,使得Linux成為視頻采集的最佳平臺。
2 系統(tǒng)設(shè)計
2.1 硬件
硬件平臺為PC機,決定圖像的質(zhì)量的一個首要的因素是攝像頭,應該根據(jù)不同的應用場合合理選擇。大體上有兩種方案:普通視頻聊天用USB攝像頭和工業(yè)視頻拍攝用攝像頭。這兩種方案在不同的技術(shù)參數(shù)上各有特點。如果僅僅是用于在線視頻會議,則可以選用USB攝像頭方案。如果是用于高清晰的拍攝監(jiān)控,則需選用工業(yè)的攝像頭,而且由于這種攝像的輸出的是模擬信號,必須接入視頻采集卡才能將模擬信號轉(zhuǎn)換成數(shù)字信號提供給計算機處理。
表1 USB攝像頭與工業(yè)攝像頭比較
■
硬件結(jié)構(gòu)如圖1所示,圖像信號經(jīng)過USB攝像頭采集后,將數(shù)字信號直接提供給計算機進行處理。或者圖像經(jīng)過CCD攝像頭采集,通過同軸電纜傳給視頻采集卡,經(jīng)過視頻采集卡轉(zhuǎn)換成數(shù)字信號然后交給計算機。一般的采集卡會有多個視頻接入口,按照采集能力的高低還可以分為多路實時采集和多路分時采集。如果是多路實時采集則可以在同一時刻輸出多路視頻信號。大多數(shù)的視頻采集卡官方的驅(qū)動并不支持Linux,如果視頻采集卡采用的是Bt8XX(Bt848/849/878/879)的話就沒有問題了,因為Linux內(nèi)核就提供了對Bt8XX很好的支持,其驅(qū)動為bttv(目前最新的版本為0.9),已經(jīng)包含在Linux的2.6的內(nèi)核當中。
■
圖1 硬件結(jié)構(gòu)
本方案采用的是Honeywell GC-755P-A2-G工業(yè)級攝像頭,采用的是微視Microview V110視頻卡。USB攝像頭用的是金河田的GD-202A,Linux本身支持ov511x芯片的USB攝像頭,對于市場上大部分的采用ZC301的攝像頭Linux也能夠很好地支持。隨著Linux的快速發(fā)展,對硬件的支持也越來越好。現(xiàn)在安裝硬件相對于以前來說方便多了。將視頻采集卡插入計算機,重啟進入Linux之后系統(tǒng)會識別出硬件然后加載相應的驅(qū)動模塊,模塊包括bttv、bt878、videodev和tuner。然后安裝Xawtv來預覽,查看視頻畫面質(zhì)量來進行測試。一般來說加載的模塊和參數(shù)都不需要用戶更改,要說明一下的是bttv這個模塊,由的視頻卡插入電腦后運行Xawtv出現(xiàn)的為黑白的畫面,甚至有時候出現(xiàn)的是變形和重影的圖像。這是bttv沒有正確識別出卡的類型導致的,對于本方案中的視頻采集卡可以采用指定卡的型號的方法來解決,首先卸載已經(jīng)加載的模塊 rmmod bt878、rmmod bttv。然后重新加載模塊并附上指定的參數(shù)modprobe bttv card=13。然后重新打開Xawtv來查看圖像,則圖像顯示正常。
表2 芯片類型與號碼,來源:The BTTV Mini HowTo
■
2.2 軟件設(shè)計
Video4Linux是Linux下面為各種視頻設(shè)備提供的統(tǒng)一的API接口,包括市面上常見的視頻采集卡和USB的攝像頭。視頻設(shè)備在Linux下對應的文件為“/dev/video0”,如果視頻卡支持多路視頻輸入或者PC上接了多個USB攝像頭的話,視頻設(shè)備文件會有多個比如“/dev/video1, /dev/video2”等等。
在Linux下面所有設(shè)備統(tǒng)一當作文件處理,要采集視頻首先得打開相應的設(shè)備文件。然后才能對設(shè)備進行設(shè)置和數(shù)據(jù)采集處理。
1)打開視頻設(shè)備
■
圖2 v4l編程流程
static int users = 0;
static int camera_open(stuct video_device *dev, int flags)
{
if(users)
return -EBUSY;
if(request_irq(irq, camera_irq, 0, \"camera\", dev)?? 0)
return -EBUSY;
users++;
MOD_INC_USE_COUNT;
return 0;
}
2) 更改視頻設(shè)備的設(shè)置
ioctl是設(shè)備驅(qū)動中對設(shè)備的I/O通道進行管理的一個函數(shù),所有對設(shè)備屬性的設(shè)置都依靠它來完成。在V4L中還提供了一個額外的ioctl函數(shù)用于對各種視頻操作的控制。其中有:視頻設(shè)備的基本信息,包括:設(shè)備名稱,最大最小分辨率和信號源信息,采集而來的圖像的各種屬性,包括:亮度,對比度和灰度,還有信號源的屬性和內(nèi)存映射的設(shè)置。下面是一個簡單的例子:
static int camera_ioctl(struct video_device *dev, unsigned
int cmd, void *arg)
{
switch(cmd)
{
case VIDIOCGCAP:
{
struct video_capability v;
v.type = VID_TYPE_CAPTURE|
VID_TYPE_CHROMAKEY|
VID_TYPE_SCALES|
VID_TYPE_OVERLAY;
v.channels = 1;
v.audios = 0;
v.maxwidth = 640;
v.minwidth = 16;
v.maxheight = 480;
v.minheight = 16;
strcpy(v.name, \"My Camera\");
if(copy_to_user(arg, v, sizeof(v)))
return -EFAULT;
return 0;
}
3)讀取數(shù)據(jù)
首先我們要保證的是程序要等到下一幀圖像準備好了才能開始讀取,或者一個中斷等待的信號。如果由中斷信號產(chǎn)生就從系統(tǒng)調(diào)用中返回,這樣信號才能傳達到程序中。此外程序還檢查用戶是否實際上不想程序讀取圖像的時候等待,比如采用非阻塞I/O模式在圖像沒有準備好的時候可以繼續(xù)做其他的事情。接下來從視頻卡拷貝圖像,這里的capture_w和capture_h是用來保持采集到的圖像的寬度與高度的。
static long camera_read(struct video_device *dev, char *buf,
unsigned long count)
{
struct wait_queue wait = { current, NULL };
u8 *ptr;
int len;
int i;
add_wait_queue(capture_wait, wait);
while(!capture_ready)
{
if(file->flagsO_NDELAY)
{
remove_wait_queue(capture_wait, wait);
current->state = TASK_RUNNING;
return -EWOULDBLOCK;
}
if(signal_pending(current))
{
remove_wait_queue(capture_wait, wait);
current->state = TASK_RUNNING;
return -ERESTARTSYS;
}
schedule();
current->state = TASK_INTERRUPTIBLE;
}
remove_wait_queue(capture_wait, wait);
current->state = TASK_RUNNING;
capture_ready = 0;
ptr=(u8 *)buf;
len = capture_w * 3 * capture_h; /* 24bit RGB */
if(len>count)
len=count; /* Doesn’t all fit */
for(i=0; i<len; i++)
{
put_user(inb(io+IMAGE_DATA), ptr);
ptr++;
}
hardware_restart_capture();
return i;
}
4)關(guān)閉視頻設(shè)備
關(guān)閉設(shè)備和打開設(shè)備非常相似,下面是一個例子:
static int camera_close(struct video_device *dev)
{
users-;
free_irq(irq, dev);
MOD_DEC_USE_COUNT;
}
2.3 音頻捕捉
對音頻捕捉是通過對聲卡的編程來實現(xiàn)的,聲卡在Linux下對應的設(shè)備文件應為/dev/dsp和/dev/audio,這兩個文件基本一樣,提供/dev/audio是為了與SUN聲音系統(tǒng)兼容。編程的流程與視頻編程非常相似:(下轉(zhuǎn)第698頁)
(上接第677頁)
1)打開聲音設(shè)備文件;
2)對聲卡的采樣量化位和采樣頻率等等進行設(shè)置;
3)讀取聲音數(shù)據(jù);
4)播放。
代碼范例如下:
/* open audio file */
file_fd=fopen(\"test.wav\",\"wb+\");
if(file_fd < 0)
{
perror(\"open of test.wav failed\");
}
/* record from device */
status=read(audio_fd,buf,sizeof(buf));
if(status < 0)
{
perror(\"audio read\");
exit(1);
}
/* play */
status=fwrite(buf,sizeof(buf),1,file_fd);
if(status < 0)
{
perror(\"audio same\");
exit(1);
}
由于篇幅的限制,其中設(shè)置聲音采樣頻率和量化位數(shù)的代碼沒有寫入本文當中。
3 結(jié)束語
該文介紹了利用一臺普通的PC機,利用Linux作為開源軟件所具有的低成本,資源豐富等優(yōu)勢。根據(jù)使用場所的實際需要,可同時對多路的高性能的專業(yè)攝像頭和普通USB攝像頭捕獲的視頻信號以及MIC捕獲的音頻信號進行采集。若結(jié)合多媒體視頻音頻的編碼、解碼技術(shù)和流媒體技術(shù),充分利用現(xiàn)有的網(wǎng)絡(luò)基礎(chǔ),則可以方便的實現(xiàn)監(jiān)控、拍攝和遠程教育等各種功能。
參考文獻:
[1] Stevens W R, Rago S A. Advanced Programming in the UNIX Environment[M].2th ed. Addison Wesley/Pearson, 2006.
[2] 李玉波,朱自強,郭軍. Linux C編程[M].北京:清華大學出版社,2005.
[3] Bill Dirks. Video for Linux Two [EB/OL].(2003-06-26).http://www.thedirks.org/v4l2/