Ubuntu有點折騰人....但是在折騰之后發現它更加方便,而且懂得更多的東西
最近在調試一個視頻采集芯片的驅動,主要是接收vga輸入和hdmi輸入,在實驗的過程中遇到了一個惱火的問題,就是同一台電腦(我的聯想筆記本y400),在win8的vga輸出的1360768分辨率我的采集芯片能識別到,但是ubuntu下,同樣的分辨率卻無法識別到,采集芯片識別到參數和VESA上的標准似乎不一致...問題到底出現在哪里呢?另外一個問題,win8的vga輸出多了好幾個分辨率比如說19201080@60...而ubuntu卻沒有,最大只到1360*768..
我的ubuntu的顯卡驅動有安裝啊...難道是英偉達區別對待??我不相信...應用開發商不開發應用這我沒辦法,但是硬件應該是可以保持功能上的一致。下面就來說我是如何解決這個問題的。
必須知道的一些視頻知識
vga視頻信號是模擬信號,一開始它(VGA)表示一個視頻分辨率640*480后面也通常表示為一個視頻接口(硬件接口,規定引腳功能和電平等),我們知道顯示分辨率有非常多種,見下圖:
即使同一分辨率但是他們的時序不一定一樣的,這個時序規定什么呢?視頻信號除了有效圖像數據還有消隱區,這個消隱區存在的理由是因為:
行場消隱信號,是針對老式顯像管的成像掃描電路而言的。電子槍所發出的電子束從屏幕的左上角開始向右掃描,一行掃完需將電子束從右邊移回到左邊以便掃描第 二行。在移動期間就必須有一個信號加到電路上,使得電子束不能發出,不然這個回掃線會破壞屏幕圖像。這個阻止回掃線產生的信號就叫作消隱信號,場信號的消隱也是一個道理。
除了消隱區之外,還有一個東西是必備的,那就是同步信號。
幾乎所有通信都需要同步信號,無線通信(3G、4G),TCP/IP通信等。
視頻信號的同步,有可以分為外同步和內嵌同步,同步信號又分為:數據使能信號(DE)、水平同步信號(HS),垂直同步信號(VS)/場同步信號(Filed)
用下面一幅圖來說明這些同步信號在傳輸視頻中的位置:
如上圖所示,上半部分是者視頻一行之內的信號,而下半部分是視頻整體同步信號情況,data enable就是DE信號它指示了有效數據開始的時候,在視頻處理中,只要知道這個信號我們就可以取出有效數據了.
然后是hs信號,它的作用就是上面提到的消隱區問題,它決定了行消隱區插入的時刻,如果是內嵌同步信號的話,也決定了EAV和SAV信號的插入時刻。
VS信號的作用是決定場消隱信號的插入時刻...
不同視頻標准同樣分辨率下時序的不同就體現在,諸如VS,HS寬度不同,HS到有效數據之間長度(顯示后沿:148),HS離上一行結束的長度(顯示前沿:88)
內嵌同步信號出現的原因是我的猜想是解決並行的干擾,或者少幾條線吧..就是在數據線中傳輸同步信號,然后接受方檢測頭...內嵌同步的情況是這樣滴:
一行從參考時序EAV(有效視頻結尾)開始,EAV后面就是水消隱白區,水消隱白區的結尾是SAV。有SAV后面緊跟的就是有效視頻區。有效視頻區的樣本就是真正顯示在屏幕上的點,而空白區對應的就是模擬視頻信號中的消隱區效視頻開始)
這就是內嵌同步下一行視頻的情況...
其中,SAV是有效視頻行的開始標志,占4個字,前三個是3FF、000、000第四個字是XYZ,包含主要的時序信息。EAV表示有效視頻行的結束,同SAV格式相同。
其中,F表示該行屬於哪一個場,F=0表示場1,F=1表示場2。V表示該行是否為場消隱區的行,H用於區分EAV和SAV,H=0表示SAV,H=1表示EAV。
P3=V⊕h、P2=F⊕H、P1=F⊕V、P0=F⊕V⊕H
EAV之后的兩個字LN,表示該視頻行在特定的視頻格式中所處的行數,色度和亮度信息中的LN是相同的。
LN后面的兩個字是前一行的循環冗余碼(CRC)
由於接收端需要,我的視頻采集芯片配置都是內嵌同步模式..需要根據視頻標准指定上面提到的同步信號的一些信息,比如和說一行之中總共像素,有效像素,一行所用時間,hs和vs的寬度,hs或者vs的顯示前沿和顯示后沿的寬度,這些信號的有效電平是高還是低等等。
視頻標准
關於視頻標准,真是五代十國般混亂,所謂視頻標准就是規定上面說的這些時序..我們知道視頻信號有模擬的,數字的,高清的,非高清的,還有各種各樣的視頻接口:hdmi、vga、S-vdieo、DVI、DP等,串行的並行的...無論它們怎么傳,它們傳的視頻信號都是按照上面說的形式來組織的。
首先是VESA:
視頻電子標准協會(Video Electronics Standards Association, VESA)是由代表來自世界各地的、享有投票權利的140多家成員公司的董事會領導的非盈利國際組織,總部設立於加利福尼亞州的Milpitas,自1989年創立以來,一直致力於制訂並推廣顯示相關標准
VESA這個組織總共弄了三個標准:GTF、DMT和CVT。
gtf和cvt准確的說都是一套公式用於計算視頻時序..你只要給出視頻長寬和幀率就能按照其公式算出相關時序。
Generalized Timing Formula (GTF) is a method of generating industry standard timings used by a wide variety of display products
而cvt是:
Coordinated Video Timings (CVT) were released on March 2003 as the newest VESA standard for generating display timings
cvt是gtf的代替者。
dmt是啥?我們知道網絡通信的OSI分為七層,這是專家們制定的標准,但是最后采用的卻是TCP/IP的4層結構...原因就是市場往往是是否采用某個標准的決定性原因.
dmt就是這樣的一個視頻時序集,它是在市面上早已采用的視頻標准集,這些視頻格式大部分不兼容cvt和gtf公式,但是它卻被市場所采納。
Display Monitor Timings (DMT) are a list of VESA standard pre-defined timings which are commonly used within the Computer industry
這兩年高清視頻很火,可是高清視頻的標准是另外一個制定的(==!),但是后來VESA的dmt也收集部分高清視頻格式並標明是取至哪個標准.
比如說:CEA/EIA
Electronic Industries Alliance (EIA-861B) refers to a CEA/EIA standard which consists of display timing and formats supported by Digital Television
這貨是專門制定數字視頻標准的,難道模擬信號的vga就不能輸出1080p@60的視頻嗎,我們的電腦最后處理和顯示都是數字信號,模擬信號都需要經過ADC轉換的,所以答案是:可以。
比如在VESA DMT 12p3標准中:對1080p@60視頻格式有這樣注明:
關於內嵌同步的標准有bt.656和bt.1120這樣的標准,關於輸入顏色空間有bt.601和bt.709這樣的標准,關於視頻接口比如說hdmi或者sdi又有各自的標准,我們做信號采集和處理的(用fpga、dsp或者專用芯片)必須仔細查看這些標准才能准確解出視頻信號然后才能處理..
ubuntu的vga輸出分辨率問題
有了上面的知識,現在知道為啥同樣分辨率同樣的幀率,同樣的硬件,為什么在win8可以檢測到,而在ubuntu檢測不到的答案嗎?梳理了一遍知識,發現很大可能是采用的標准不同導致的!!
ubuntu自帶了兩個命令:cvt
和gtf
。
這兩個命令根據輸入的分辨率和幀率得到相應的時序...
比如說
cvt 1366 768 60
# 1360x768 59.80 Hz (CVT) hsync: 47.72 kHz; pclk: 84.75 MHz
Modeline "1360x768_60.00" 84.75 1360 1432 1568 1776 768 771 781 798 -hsync +vsync
gtf 1360 768 60
# 1360x768 @ 60.00 Hz (GTF) hsync: 47.70 kHz; pclk: 84.72 MHz
Modeline "1360x768_60.00" 84.72 1360 1424 1568 1776 768 769 772 795 -HSync +Vsync
值得注意,在VESA制定視頻標准中,同樣視頻分辨率和會分為normal blanking和reduced blanking這兩種類型的視頻格式,這是由於當今時代的顯示器不再需要像以前那樣用電子槍掃了...所以場消隱,行消隱其實沒啥意義而且浪費帶寬..所以催生了一種reduced blanking的視頻格式,意在減少視頻信號在帶寬的占用...
cvt 1360 768 60 -r
# 1360x768 59.96 Hz (CVT) hsync: 47.37 kHz; pclk: 72.00 MHz
Modeline "1360x768R" 72.00 1360 1408 1440 1520 768 771 781 790 +hsync -vsync
以上,ubuntu可能使用cvt的1360768@60或者gtf的1360768@60或者使用rb(reduced blanking)的1360*768@60。
而在win8上的1360*768@60則是按照dmt來輸出的,因為我是按照dmt中的參數來設置視頻采集芯片的。
所以在不改變視頻采集芯片的前提下,是想辦法讓ubuntu可以輸出dmt中指定的視頻信號。
上面命令Modeline
一行可以用於xorg的配置,至於xorg的配置文件作用和語法請看這個鏈接: Linux系統中xorg.conf文件簡介 ,這里猜想這個東西可以用於規定分辨率相關東東,在Ubuntu14.04中已經沒有xorg.conf這個文件,而是分為多個文件了,放在/usr/share/X11/xorg.conf.d
中。
首先搞清楚上面的命令輸出的意思:我對照dmt似乎不能找到啥規律:
然后后來我找到一個計算cvt的程序,源文件鏈接如下:cvt.c
下載后執行gcc cvt.c -O2 -o cvt -lm -Wall
就行了
這個cvt命令能輸出更多的信息..借鑒這些信息之后我就知道Modeline
那一行的意義了:
./cvt 1360 768 60 -v
1: [V FIELD RATE RQD] : 60.000000
2: [H PIXELS RND] : 1360.000000
2.5: [ASPECT_RATIO] : 16:9
2.5: [V SYNC] : 5.000000
3: [LEFT MARGIN (PIXELS)] : 0.000000
3: [RIGHT MARGIN (PIXELS)] : 0.000000
4: [TOTAL ACTIVE PIXELS] : 1360.000000
5: [V LINES RND] : 768.000000
6: [TOP MARGIN (LINES)] : 0.000000
6: [BOT MARGIN (LINES)] : 0.000000
7: [INTERLACE] : 0.000000
8: [H PERIOD EST] : 20.903589
9: [Actual V_SYNC_BP] : 26.311272
9: [Estimated V_SYNC_BP] : 27.000000
9: [V_SYNC_BP] : 27.000000
10: [Back porch] : 22.000000
11: [TOTAL V LINES] : 798.000000
12: [IDEAL DUTY CYCLE] : 23.728924
13: [H BLANK] : 416.000000
14: [TOTAL PIXELS] : 1776.000000
15: [Non-rounded PIXEL FREQ] : 84.961487
15: [ACT PIXEL FREQ] : 84.750000
16: [ACT H FREQ] : 47.719593
17: [ACT FIELD RATE] : 59.798988
18: [ACT FRAME RATE] : 59.798988
20: [H BACK PORCH] : 208.000000
21: [H SYNC RND] : 136.000000
22: [H FRONT PORCH] : 72.000000
23: [V FRONT PORCH] : 3.000000
# 1360x768 @ 60.00 Hz (CVT)
# field rate 59.80 Hz; hsync: 47.72 kHz; pclk: 84.75 MHz
Modeline "1360x768_60.00" 84.75 1360 1432 1568 1776 768 771 776 798 -HSync +Vsync
經過對照dmt中的參數,Modeline
那一行中,84.75是像素始終對應dmt中的Pixel Clock
,1360對應Hor Pixels
,1432對應Hor Pixels
+H Front Porch(像素)
,1568對應Hor Pixels
+H Back Porch(像素)
,1766對應Hor Total Time
中對應的象素,768對應Ver Pixels
,771對應Ver Pixels
+V Front Porch(行數)
,
776對應Ver Pixels
+V Front Porch(行數)
+Ver Sync Time(行數)
,798對應Ver Total Time(行數)
,-HSync指的是hs信號為負,+表示為正,對應dmt中的Hor Sync Polarity
和Ver Sync Polarity
有了這些理解,我們就可以創造出自己的Modeline
了.根據dmt中的1360*768@60 normal blanking描述:得到這樣Modeline
:
Modeline "1360x768_60.00" 85.50 1360 1424 1616 1792 768 771 777 795 +hsync +vsync
看吧和cvt計算出來的差別還是有滴,hs極性都不同...
怎么將這個分辨率添加到vga輸出呢,有一種臨時的方法(注銷后失效),還有一種永久性的方法(就是xorg配置文件)。
先介紹臨時方法,主要命令是xrandr
命令,
xrandr - primitive command line interface to RandR extension
其中RandR是:
RandR is a communications protocol written as an extension to the X11[2] and Wayland[3] protocols for display servers. Both, XRandR and WRandR facilitate the ability to resize, rotate and reflect the root window of a screen.
反正就是控制display server的命令就對啦...它能控制屏幕分辨率,旋轉大小等...當然顯示服務器的下面必須有顯卡驅動,顯卡驅動下面必須有顯卡這個硬件,顯示服務器上面必須有顯示器或者其它視頻接收設備,不然這個命令不會起作用。
執行xrandr輸出相關硬件信息:
xrandr
Screen 0: minimum 8 x 8, current 1366 x 768, maximum 16384 x 16384
VGA-0 disconnected (normal left inverted right x axis y axis)
LVDS-0 connected primary 1366x768+0+0 (normal left inverted right x axis y axis) 310mm x 174mm
1366x768 60.0*+
1024x768 60.0
960x540 60.0
840x525 59.9
800x600 60.3
800x512 60.2
720x450 59.9
700x525 60.0
680x384 60.0 59.8
640x512 60.0
640x480 59.9 60.0
576x432 60.1
512x384 60.0
400x300 60.3
320x240 60.1
HDMI-0 disconnected (normal left inverted right x axis y axis)
上面說明了,我的筆記本有一個顯示器處於連接狀態(廢話==!),還有一個VGA口和hdmi口處於未連接狀態,這和我的硬件是相符合的,在輸出信息中歐你那個需要記住:Screen 0,VGA-0和LVDS-0這樣的名字。
加新分辨率的一般過程如下:
# 得到某一分辨率的modeline
cvt 1680 1050 60
# 1680x1050 59.95 Hz (CVT 1.76MA) hsync: 65.29 kHz; pclk: 146.25 MHz
Modeline "1680x1050_60.00" 146.25 1680 1784 1960 2240 1050 1053 1059 1089 -hsync +vsync
# 增加一個模式
sudo xrandr --newmode "1680x1050_60.00" 146.25 1680 1784 1960 2240 1050 1053 1059 1089 -hsync +vsync
# 將這個模式添加到硬件上,注意VGA-0可根據需要改成LCDS-0或者HDMI-0等
sudo xrandr --addmode VGA-0 "1680x1050_60.00"
#在指定硬件輸出指定模式
xrandr --output VGA --mode 1680x1050_60.00
關於1360*768,上面命令中只需要改變modeline參數和模式名字,就行了,實踐結果是吻合上面猜想的.
接下來讓它用久生效:
在/usr/share/X11/xorg.conf.d
新建一個文件:10-monitor.conf然后輸入以下內容,保存然后注銷,然后測試:
#Modeline 像素時鍾 HP HP+HFP HP+HBP HTP VP VP+VFP VP+VFP+VSW VTL HS有效電平 VS信號的有效電平
Section "Monitor"
Identifier "Monitor0"
HorizSync 30.0 - 83.0
VertRefresh 56.0 - 75.0
Option "DPMS"
Option "VendorName" "Nvidia Proprietary Driver"
Modeline "1366x768_60.00" 85.50 1366 1436 1579 1792 768 771 774 798 +hsync +vsync
Modeline "1360x768_60.00" 85.50 1360 1424 1616 1792 768 771 777 795 +hsync +vsync
Modeline "1920x1080_60.00" 148.50 1920 2008 2068 2200 1080 1084 1089 1125 +hsync +vsync
Modeline "1440x900_60.00" 106.50 1440 1528 1672 1904 900 903 909 934 -hsync +vsync
Modeline "1600x1200_60.00" 162.00 1600 1664 1904 2160 1200 1201 1204 1250 +hsync +vsync
Modeline "1280x720_60.00" 74.25 1280 1390 1500 1650 720 725 730 750 +hsync +vsync
Modeline "1600x900_60R" 108.00 1600 1624 1696 1800 900 901 904 1000 +hsync +vsync
EndSection
Section "Screen"
Identifier "Screen0"
Device "VGA-0"
Monitor "Monitor0"
Option "ModeValidation" "AllowNonEdidModes, NoVirtualSizeCheck, NoMaxPClkCheck, NoWidthAlignmentCheck, NoExtendedGpuCapabilitiesCheck"
DefaultDepth 24
SubSection "Display"
Depth 24
Modes "1366x768_60.00" "1360x768_60.00" "1920x1080_60.00" "1440x900_60.00" "1600x1200_60.00" "1280x720_60.00" "1600x900_60R"
EndSubSection
EndSection
Section "Screen"
Identifier "Screen0"
Device "LVDS-0"
Monitor "Monitor0"
Option "ModeValidation" "AllowNonEdidModes, NoVirtualSizeCheck, NoMaxPClkCheck, NoWidthAlignmentCheck, NoExtendedGpuCapabilitiesCheck"
DefaultDepth 24
SubSection "Display"
Depth 24
Modes "1366x768_60.00"
EndSubSection
EndSection
注銷后會發現VGA輸出了多了好多分辨率,而且我指定的分辨率都是我想要的時序,也就是你能隨意的創造出自己的想要的視頻信號時序,這就是ubuntu的魅力!!!
嘿嘿,最后還是要潑下冷水,英偉達的確區別對待了Linux和windwos...在ubuntu中的nvidia的控制面板上找不到任何關於添加自定義分辨率的選項,而在win8上卻找到了,而且是傻瓜式,也就是說上面說的,win8也可以做到嘿嘿.:
但是,起碼證明了一點ubuntu也可以做到..而且在折騰過程中學到更多...
一些截圖: