V4L2文檔翻譯(一)

相關資料

https://www.kernel.org/doc/Documentation/zh_CN/video4linux/v4l2-framework.txt
http://linuxtv.org/downloads/v4l-dvb-apis/

第一節:常見API原理


打開和關閉設備

  • 設備命名
  • 相關設備
  • 多重打開
  • 共享數據流
  • 功能

設備命名

V4L2驅動以內核模塊形式存在,可以被系統管理員手動加載或當發現設備時自動加載。驅動被編入videodev模塊,其提供幫助函數以及在此文檔的一個常用應用接口描述。

每一個驅動註冊一個或多個設備節點後他們的主設備號都是81,而子設備號在0~255之間。除非通過CONFIG_VIDEO_FIXED_MINOR_RANGES編譯選項編譯內核,否則子設備號是動態分配的。而且,子設備號分配範圍與設備節點類型有關(video、radio等)。

很多驅動支持通過video_nr,radio_nr或vbi_nr模塊設置來選擇特殊的video/radio/vbi節點號。這就允許用戶申請指定的設備節點名稱,如/dev/video5而不是交給系統生成。當驅動支持多個同類設備有多餘一個設備節點號時候,可如下:

>modprobe mydriver video_nr=0,1 radio_nr=0,1

在/etc/modules.conf中可以這樣寫:

options mydriver video_nr=0,1 radio_nr=0,1

如果在模塊設置中沒有給定設備節點號則驅動會默認進行分配。

通常情況下udev會爲你在/dev下自動創建設備節點。如果udev沒有安裝,那麼你需要使能CONFIG_VIDEO_FIXED_MINOR_RANGES內核選項,這樣就可以將子設備號設定爲設備節點號了,即子設備號5同樣會使設備節點名爲video5。此特性會使不同類型設備擁有不同範圍的子設備號。這些範圍在第四節:接口中將給出。(不繞彎子了,我這裏給直接列出來)

類型 範圍
video 0~63
vbi 224~255
vtx 192~223
radio 64~127
SDR 0~255

特殊文件的創建(用mknod)是一個特殊操作,而且這些設備不能通過主設備號和子設備號打開。這意味着應用程序不能掃描加載上的或安裝上的驅動。用戶必須敲入一個設備名,或者說應用程序可以嘗試使用常規的設備名稱。

相關設備

設備可以支持好幾個功能,如視頻捕捉、VBI捕捉以及無線廣播。

V4L2 API爲這些功能分別創建不同的設備節點。

V4L2 API被設計成一個設備節點可以支持所有功能。不過實際上這卻從來沒有奏效過:應用程序從來沒有使用過這項特性,而且許多驅動也沒有支持此特性,就算他們支持了也從來沒有被測試過。另外,在不同功能間切換設備節點只是在使用流數據IO API時需要,並不能用read()/write() API。

如今每個設備節點只支持一個功能。

除了視頻輸入、輸出外硬件還可能同時支持聲音取樣和播放。如果這樣的話,這些功能要以ALSA PCM設備形式存在。

所有這些設備有一個問題,就是V4L2 API並沒有提供找到相關設備的規則。有些確實很複雜的設備使用多媒體控制器來達到這個目的。但是大多數設備並不用它,現存的一些代碼表示他們使用sysfs來發現相關設備,還沒有一個庫可以爲使用多媒體控制器的設備和沒使用的設備提供一個單一的API。如果你想來從事這個工作的話請先寫一封郵件到此郵件列表:http://www.linuxtv.org/lists.php

多重打開

V4L2設備可以被打開超過一次。一旦驅動支持這樣做,用戶就可以像這樣使用:開啓一個錶盤程序來控制比如亮度或聲音音量,然後另一個程序來捕捉視頻和音頻。換句話說,就是錶盤程序相當於ALSA聲音混合程序。只是打開一個V4L2設備並不會改變設備的狀態。

當一個應用程序因爲需要流數據而申請了內存空間後(通過VIDIOC_REQBUFS或VIDIOC_CREATE_BUFS ioctl,或通過read()或write()函數)這個程序(文件句柄)就成爲了此設備的擁有者。再不會允許對內存空間大小做改動的動作(VIDIOC_S_FMT ioctl動作),而且其他應用再不被允許申請內存或開始、停止數據流,一旦這樣做了會返回EBUSY錯誤代碼。

只是打開V4L2設備不會允許獨佔訪問。無論對請求類型數據分配的權限是讀還是寫,初始化數據都會發生交換,而且對文件句柄來說還會改變相關屬性。應用程序可以通過使用優先級機制請求附加特選。

共享數據流

V4L2驅動不支持多個應用通過拷貝緩存的方式在同一設備上讀寫同一數據流,或時間複用,或其他類似方式。在用戶空間使用代理程序處理這種情況會更好。

功能

應用程序可以使用open()和close()對V4L2設備執行打開和關閉操作。設備可以通過ioctl編程來完成接下來的章節所講述的內容。

功能查詢

因爲V4L2涵蓋了各種各樣的設備,但並不是所有類型的設備都可以使用各種API。此外,相同類型的設備也可能擁有不同的功能以及允許省略一點複雜或並不太重要的API。

VIDIOC_QUERYCAP ioctl命令可以查看內核設備對規範的兼容有效性,查詢功能和IO方法都是需要設備支持的。

從內核版本3.1開始,VIDIOC_QUERYCAP將會返回V4L2 API版本,通常是與內核版本匹配的。沒有必要通過VIDIOC_QUERTCAP檢查一個特殊的ioctl是否支持,如果驅動不支持V4L2會返回ENOTTY錯誤碼。

可以通過不同的ioctl查詢其他特性,如通過VIDIOC_ENUMINPUT查詢設備視頻連接器的數量、類型及名字。儘管API的目的主要是抽象,VIDIOC_QUERYCAP ioctl仍然允許驅動透過特殊應用程序來實現個性化。

所有V4L2驅動都必須支持VIDIOC_QUERYCAP,應用程序往往在打開設備後就執行這個ioctl。

程序優先級

當多個應用程序共享同一個設備時,需要給他們分配不同的優先級。相反的一個視頻錄製應用程序執行如rm -rf /這類命令可能會阻塞其他程序改變視頻控制或切換當前TV頻道。另一個目的是允許低優先級應用程序工作在後臺,這樣用戶控制程序就可以優先並能夠在稍後自動恢復設備控制。

由於這些特性不能在完全在用戶空間施行,所以V4L2定義了VIDIOC_G_PRIORITY和VIDIOC_S_PRIORITY ioctl來通過文件描述符申請和查詢准入優先級。驅動不支持這些ioctl的情況下,打開一個設備會分配一箇中等級優先級,這與早起版本的V4L2兼容。當應用程序通過VIDIOC_QUERYCAP ioctl查詢完功能後可以通過VIDIOC_S_PRIORITY請求不同的優先級。

如VIDIOC_S_INPUT等這種會改變驅動屬性的ioctl在其他程序申請了更高的優先級後會返回EBUSY錯誤碼。

視頻輸入和輸出

視頻輸入輸出一個設備的物理連線。如RF連線(天線、電纜),視頻連線,或RGB連線。視頻和VBI捕捉設備需要輸入,而視頻和VBI輸出設備需要輸出,至少各一個。Radio無限通訊設備並沒有視頻輸入輸出。

應用程序可以通過VIDIOC_ENUMINPUT和VIDIOC_ENUMOUTPUT ioctl來查看有效輸入和輸出的數量和屬性。VIDIOC_ENUMINPUT ioctl會返回v4l2_input結構體,也會返回被查詢的視頻輸入設備的狀態信息。

VIDIOC_G_INPUT和VIDIOC_G_OUTPUT ioctl將會返回當前視頻輸入或輸出的索引。應用程序可以通過VIDIOC_S_INPUT和VIDIOC_S_OUTPUT ioctl來選擇不同輸入或輸出。設備若擁有一個或多個的輸入、輸出,則必須在驅動中聲明所有的輸入、輸出ioctl。

例 1.1 當前視頻輸入的信息

struct v4l2_input input;
int index;

if (-1 == ioctl(fd, VIDIOC_G_INPUT, &index)) {
    perror("VIDIOC_G_INPUT");
    exit(EXIT_FAILURE);
}

memset(&input, 0, sizeof(input));
input.index = index;

if (-1 == ioctl(fd, VIDIOC_ENUMINPUT, &input)) {
    perror("VIDIOC_ENUMINPUT");
    exit(EXIT_FAILURE);
}

printf("Current input: %s\n", input.name);

例 1.2 切換到第一個視頻輸入

int index;

index = 0;

if (-1 == ioctl(fd, VIDIOC_S_INPUT, &index)) {
    perror("VIDIOC_S_INPUT");
    exit(EXIT_FAILURE);
}

音頻輸入和輸出

音頻輸入和輸出是設備的物理連線。視頻捕捉設備會有輸入,輸出設備會有輸出,零個或每個多個。Radio無線通訊設備沒有聲音輸入和輸出。他們都會擁有正好一個調諧器,事實上就是一個聲源,但是API只將視頻輸入或輸出與調諧器關聯起來,而radio設備沒有。TV卡上用來接收聲音信號給聲卡的連接器並不被視爲是聲音輸出。

聲音和視頻輸入輸出是相互關聯的。選擇一個視頻源的同時也會選擇一個聲音源。當視頻和聲音的源是一個調諧器的時候這就最明顯不過了。將來聲音連機器將會和一個以上的視頻輸入或輸出結合。假設有兩個混合的視頻輸入和兩個音頻輸入存在,就會有最多四種有效組合。關於視頻和聲音的聯繫在結構體v4l2_input或v4l2_output的audioset中有所體現,每一位代表一個索引號,從0開始。

應用程序通過VIDIOC_ENUMAUDIO和VIDIOC_ENUMAUDOUT ioctl來列舉關於有效輸入輸出的數量和屬性。VIDIOC_ENUMAUDIO ioctl返回結構體v4l2_audio,同時包含當前所查詢的音頻輸入信號狀態。

VIDIOC_G_AUDIO和VIDIOC_G_AUDOUT ioctl會報告當前音頻輸入和輸出。這裏需要注意,VIDIOC_ENUMAUDIO和VIDIOC_ENUMAUDOUT所做的並不像VIDIOC_G_INPUT和VIDIOC_G_OUTPUT只是返回索引而已。

應用程序可以通過VIDIOC_S_AUDIO ioctl來選擇音頻輸入以及改變它的屬性。VIDIOC_S_AUDOUT ioctl應用選擇音頻輸出(目前沒有什麼可以改變的屬性)。

當設備應用多個可選擇的音頻輸入和輸出時必須在驅動中聲明所有聲音輸入、輸出ioctl。若設備擁有任何音頻輸入或輸入的話,驅動必須在v4l2_capability中設置V4L2_CAP_AUDIO標籤,這樣可以被VIDIOC_QUERYCAP ioctl查詢到。

例 1.3 當前聲音輸入相關信息

struct v4l2_audio audio;

memset(&audio, 0, sizeof(audio));

if (-1 == ioctl(fd, VIDIOC_G_AUDIO, &audio)) {
    perror("VIDIOC_G_AUDIO");
    exit(EXIT_FAILURE);
}

printf("Current input: %s\n", audio.name);

例 1.4 切換到第一個音頻輸入

struct v4l2_audio audio;

memset(&audio, 0, sizeof(audio)); /* clear audio.mode, audio.reserved */

audio.index = 0;

if (-1 == ioctl(fd, VIDIOC_S_AUDIO, &audio)) {
    perror("VIDIOC_S_AUDIO");
    exit(EXIT_FAILURE);
}

調諧器和調製器

調諧器

視頻輸入設備可以擁有一個或多個調諧器來解調一個RF信號。每個調諧器關聯一個或多個視頻輸入,這依賴於調諧器的RF連線數量。通過VIDIOC_ENUMINPUT ioctl返回的v4l2_input結構體中中的type成員是V4L2_INPUT_TYPE_TUNER,tuner成員包含了調諧器的索引號。

Radio無線通訊輸入設備有一個調諧器,索引號爲0,沒有任何視頻輸入。

應用程序可以通過VIDIOC_G_TUNER和VIDIOC_S_TUNER ioctl來查詢和改變調諧器屬性。噹噹前視頻或radio輸入被查詢時,VIDIOC_G_TUNER所返回的v4l2_tuner結構體也包含了信號狀態信息。注意,當擁有一個以上調諧器的時候,VIDIOC_S_TUNER並不會切換當前調諧器。使用哪個調諧器只由當前視頻輸入決定。若設備擁有一個或以上的調諧器的時候,必須支持這些ioctl,且要在v4l2_capability結構體中設置V4L2_CAP_TUNER標籤。

調製器

視頻輸出設備可以有一個或以上的調製器,調製TV天線接收或者視頻錄製的視頻信號。每個調製器可跟一個或多個視頻輸出關聯,這取決於調製器上有多少個RF連接線。通過VIDIOC_ENUMOUTPUT ioctl返回的v4l2_output結構體中type成員代表V4L2_OUTPUT_TYPE_MODULATOR,modulator成員包含調製器的索引。

Radio輸出設備有一個索引號爲0的調製器,沒有視頻輸出。

一個視頻或無線設備不可能同時支持調製器和調諧器。這樣的硬件需要兩個完全分開的設備節點,一個支持調諧器功能,另一個支持調製器功能。這樣的原因是因爲通過VIDIOC_S_FREQUENCY ioctl的頻率將無法判斷是調製器的還是調諧器的。

應用程序可以使用VIDIOC_G_MODULATOR和VIDIOC_S_MODULATOR ioctl來查詢和改變調製器屬性。當有一個以上調製器的時候,VIDIOC_S_MODULATOR並不會進行切換。當前的視頻輸出決定使用哪個調製器。若設備擁有一個或以上的調製器,則其驅動必須支持這些ioctl,並在v4l2_capability結構體中設置V4L2_CAP_MODULATOR標籤。

Radio頻率

應用程序可以通過VIDIOC_G_FREQUENCY和VIDIOC_S_FREQUENCY ioctl來獲取和設置調諧器或調製器的無線頻率,其參數均爲v4l2_frequency結構體。對TV和Radio設備這些ioctl使用方法一樣。當調製器或調諧器的ioctl被支持,或是當設備是一個radio無線設備的話,驅動必須支持這些ioctl。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章