1 Video Class 基礎(chǔ)概念
Usb協(xié)議中,除了通用的軟硬件電氣接口規(guī)范等,還包含了各種各樣的Class協(xié)議,用來為不同的功能定義各自的標(biāo)準(zhǔn)接口和具體的總線上的數(shù)據(jù)交互格式和內(nèi)容。這些Class協(xié)議的數(shù)量非常多,最常見的比如支持U盤功能的Mass Storage Class,以及通用的數(shù)據(jù)交換協(xié)議:CDC class。此外還包括Audio Class, Print Class等等。
理論上說,即使沒有這些Class,通過專用驅(qū)動也能夠?qū)崿F(xiàn)各種各樣的應(yīng)用功能。但是,正如Mass Storage Class的使用,使得各個廠商生產(chǎn)的U盤都能通過操作系統(tǒng)自帶的統(tǒng)一的驅(qū)動程序來使用,對U盤的普及使用起了極大的推動作用,制定其它這些Class也是為了同樣的目的。
Video Class 協(xié)議的目的是給USB接口的視頻設(shè)備提供一個統(tǒng)一的數(shù)據(jù)交換規(guī)范。最初版本是在2003年9月才添加到USB Class規(guī)范中的,1.1的版本更是在2005年才發(fā)布。相比之下,Mass Storage Class 早在1998年就發(fā)布了。支持Video Class協(xié)議的多媒體芯片也是在2005年才陸續(xù)發(fā)布。所以USB 視頻設(shè)備目前的現(xiàn)狀是,在設(shè)備一端,多數(shù)依舊還采用原先的各種包含通用USB功能的多媒體處理芯片,主機端需要安裝專用的驅(qū)動程序,基本上各個產(chǎn)品之間不具備兼容性。甚至對于操作系統(tǒng)而言,也只有在XP的SP2以后,才包含了對通用的Video class協(xié)議的支持。所以即使是某些多媒體設(shè)備(比如Logitech最新的幾款攝像頭)包含了對Video Class的支持,在Win2000等操作系統(tǒng)上依然需要安裝驅(qū)動程序。不過,應(yīng)該說使用Video Class無疑會是一個趨勢,在相應(yīng)的多媒體芯片陸續(xù)投入市場后,支持Video Class的多媒體設(shè)備應(yīng)該會在一兩年內(nèi)會迅速普及開來。
除了在硬件上通過相應(yīng)的多媒體芯片支持Video Class的設(shè)備以外,對于包含了操作系統(tǒng)的智能手機,當(dāng)然也可以在手機端通過驅(qū)動程序來實現(xiàn)對Video Class的支持,就好像原先支持任何一種專用的USB驅(qū)動一樣。只不過數(shù)據(jù)交換的格式不是自己隨意制訂的,而是按照Video Class的規(guī)范來實現(xiàn)的。
由于目前支持Video Class的設(shè)備還很少,所以在Linux上還沒有開源的Video Class的主機端驅(qū)動,設(shè)備端的Video Class驅(qū)動就更沒有見到開源的代碼了。本文在介紹USB Video Class架構(gòu)的基礎(chǔ)上,主要是探討Linux操作系統(tǒng)下設(shè)備端Video Class驅(qū)動的實現(xiàn)。不過在其它平臺下的實現(xiàn)思路應(yīng)該也是類似的。
2 USB Video Class 協(xié)議結(jié)構(gòu)
2.1 設(shè)備拓撲結(jié)構(gòu)
在拓撲結(jié)構(gòu)上Video Class 將視頻設(shè)備抽象為幾個主要的硬件功能模塊:
輸入端點 Input Terminal
輸出端點 Output Terminal
camera端點 Camera Terminal
選擇單元 Selector Unit
處理單元 Processing Unit
拓展單元 Extension Unit
下圖是一幅摘自USB_Video_Example 1.1.pdf (www.usb.org)的拓撲結(jié)構(gòu)示例圖:
圖1 USB Video Camera Topology Example
從sensor和另一個復(fù)合視頻設(shè)備得到的數(shù)據(jù)流由IT 和 CT輸入,經(jīng)SU選擇送PU處理,再由OT綁定到指定的USB端點。最后由USB端點與主機交互將數(shù)據(jù)發(fā)送到host端。在實際設(shè)備中,可能沒有其中的某些功能模塊,也可能其中的幾個模塊都是由同一硬件來完成的。
2.2 協(xié)議層次結(jié)構(gòu)
上圖中,左半部的框架組成了Video Class中的控制接口界面,右半部的框架組成了視頻流傳輸接口界面。這兩部分構(gòu)成了Video Class的主要協(xié)議框架。
2.2.1 Descriptor Layout
與Class相關(guān)的信息,當(dāng)然是主機端通過向設(shè)備端獲取描述符(Descriptor)來得到的, 下圖摘自USB_Video_Class_1.1.pdf , 給出了一個Video Class協(xié)議描述符應(yīng)用示例的Layout。
圖2 Video Camera Descriptor Layout Example
可以看到,在Descriptor Layout中,在標(biāo)準(zhǔn)描述符里,除了Device Descriptor, Configuration Descriptor, Interface Descriptor, Endpoint Descriptor,String Descriptor以外,還有一個USB2.0 協(xié)議中后期才新加的IAD 即 Interface Association Descriptor,用來描述多個相關(guān)Interface之間的關(guān)系,在Video Class中,IAD用來描述VideoControl Interface和VideoStreaming Interface之間的關(guān)系。
圖中深色的部分就是Video Class 協(xié)議相關(guān)的專用描述符(Class Specific Descriptor)了。主要就是對硬件圖像采集和處理模塊的物理拓撲結(jié)構(gòu)和功能的描述,以及對視頻傳輸格式(包括編碼格式,碼率等等視頻圖像相關(guān)參數(shù))的描述。
通過從設(shè)備處獲得這些描述符,主機可以得知視頻設(shè)備端的結(jié)構(gòu)及其所支持的功能。而控制這些功能模塊,對數(shù)據(jù)源和數(shù)據(jù)流進行配置,則需要通過Request來完成。
2.3 Request
Request是由主機向設(shè)備端發(fā)起的功能請求,包括所有USB設(shè)備都需要支持的Standard Device Requests 和與Class相關(guān)的Class Specific Requests :
2.3.1 Standard Device Requests
下圖列出了USB Spec中規(guī)定的標(biāo)準(zhǔn)Request
圖3 Standard Device Requests
這其中,有一部分Request是由USB控制芯片在硬件一級就直接完成的應(yīng)答工作,比如SET_ADDRESS,有些則需要由軟件來做進一步的處理,比如Set_Configuration。軟硬件的這種任務(wù)的劃分還與具體的硬件芯片相關(guān)。因為這部分是標(biāo)準(zhǔn)協(xié)議相關(guān),本文就不詳述。
2.3.2 Class Specific Requests
Class Specific Requests的數(shù)據(jù)結(jié)構(gòu)Layout與標(biāo)準(zhǔn)Request是一樣的,只是內(nèi)容不同而已。VideoClass的Class Specific Requests主要根據(jù)Interface分為兩類,其下又根據(jù)具體功能模塊做進一步的劃分:
? VideoControl Requests
- Camera Terminal Control Requests
- Selector Unit Control Requests
- Processing Unit Control Requests
- Extension Unit Control Requests
? VideoStreaming Requests
- Interface Control Requests
這其中,Interface Control Requests因為是用來在主機和設(shè)備之間協(xié)商數(shù)據(jù)交互格式和分辨率,流量等信息的,所以一般來說是必須實現(xiàn)的。
而Camera Terminal Control Requests 和 Processing Unit Control Requests中的內(nèi)容,則是目前常用的即時通訊軟件如MSN / QQ 等在其視頻控制界面上集成的控制參數(shù)。
其中,Camera Terminal Control Requests包含了對曝光時間,曝光模式,對焦,變焦,平移等sensor獲取數(shù)據(jù)階段時的參數(shù)控制。
而Processing Unit Control Requests中則包含了亮度,增益,色調(diào),對比度,白平衡等等sensor在獲取到圖像數(shù)據(jù)后,圖像處理階段的相關(guān)參數(shù)。
不過實際上,以上兩者的劃分在硬件層次并不是絕對的。很多參數(shù)的控制在sensor硬件級別上是同一層次的。不過,將這些功能抽象成這兩類,正如在硬件的拓撲結(jié)構(gòu)上將功能模塊抽象出來一樣,有利于通用化的程序設(shè)計
3.1 驅(qū)動架構(gòu)
3.1.1 平臺及軟件基礎(chǔ)
本文討論的是USB Video Class在Linux操作系統(tǒng)上的設(shè)備端實現(xiàn)。具體是在Omap平臺上,基于USB Gadget的驅(qū)動架構(gòu)來實現(xiàn)的。
USB Gadget驅(qū)動分為兩層,底層是處理與USB控制芯片硬件相關(guān)的內(nèi)容,對上層屏蔽了大部分硬件相關(guān)的設(shè)置,并處理了一部分標(biāo)準(zhǔn)Request和EP0相關(guān)的標(biāo)準(zhǔn)操作流程。上層則是Class相關(guān)的部分,官方的Gadget驅(qū)動中,已經(jīng)包含了File Storage(U盤功能),RNDIS(USB網(wǎng)卡功能)等的支持??紤]到Video Class的數(shù)據(jù)交換過程與File Storage有很多相似的地方,所以本文在Video Class的實現(xiàn)中,在大的框架上仿照了File Storage驅(qū)動的架構(gòu)。
3.1.2 基本框架和數(shù)據(jù)流程
在本文實現(xiàn)的Video Class驅(qū)動中,整體的框架基本上分為兩大部分。
一部分是負責(zé)處理模塊的初始化過程,并負責(zé)處理Usb總線上的Descriptor和Requests的交互過程。包括USB總線上的控制和查詢包的接收,解釋,分配和應(yīng)答。
另一部分,是在初始化過程中啟動的一個獨立的內(nèi)核線程。負責(zé)具體的控制指令的執(zhí)行和圖像數(shù)據(jù)的獲取及傳輸工作。這其中的許多操作都有可能引起睡眠,或者需要對文件進行操作,因此必須有一個線程做為依托。
模塊的流程基本上是這樣的:
在init函數(shù)中向Gadget底層驅(qū)動注冊VideoClass數(shù)據(jù)結(jié)構(gòu)。所有的描述符都定義為全局結(jié)構(gòu)變量,在模塊初始化過程中,進一步完成對描述符的填充過程,啟動獨立的內(nèi)核線程,并注冊EP0的complete回調(diào)函數(shù)。
在啟動的內(nèi)核線程中打開并初始化camera設(shè)備。將camera設(shè)置為默認的參數(shù)配置。讀取圖像數(shù)據(jù)并將數(shù)據(jù)填充到BUF里而后提交Request到VideoStream Interface里的BULK IN端點中。而后睡眠等待由于數(shù)據(jù)傳送完畢被喚醒或有(異常)Exception發(fā)生被喚醒。
如果是數(shù)據(jù)傳送完畢,則繼續(xù)讀取,填充并發(fā)送圖像數(shù)據(jù),如果有異常發(fā)生,則轉(zhuǎn)而處理異常。
另一方面,哪些情況會引發(fā)異常呢?主要是驅(qū)動程序與BUS總線交互信息的這部分模塊中,如果發(fā)生主機端重新設(shè)置Configuration,改變USB設(shè)備配置,或者發(fā)生總線插拔等引起總線狀態(tài)變化的時候,會產(chǎn)生一個相應(yīng)的異常,等待內(nèi)核線程被喚醒并處理這些異常。
此外,在處理Requests的時候,有時候需要與camera驅(qū)動模塊交互控制信息,同樣需要操作文件句柄,目前的做法是在ep0 request的回調(diào)函數(shù)(context)中啟動一個bottom half task,在Bottom half中完成相應(yīng)的控制。
從總體結(jié)構(gòu)上說,這樣做很難看,理想的話應(yīng)該在上述獨立的內(nèi)核線程中統(tǒng)一處理與Camera模塊相關(guān)的操作,但是目前的架構(gòu),要喚醒該線程,只有兩個途徑,一是數(shù)據(jù)傳輸完畢或被取消,二是有總線狀態(tài)變化相關(guān)的異常發(fā)生。如果硬加一個異常用來處理Requests似乎也很難看,而且對架構(gòu)需要有較大的調(diào)整。所以目前只好簡化的采用了前面所說的方案。
然后關(guān)于什么時候打開設(shè)備,開始往USB總線上放置數(shù)據(jù),目前的處理方式也不是非常理想。目前是在模塊初始化后立即獲取第一幀圖像而后等待主機端讀取,實際上,主機端可能并不馬上安排圖像數(shù)據(jù)的傳輸。但是如果在主機端需要的時候才去讀取數(shù)據(jù)的話,因為sensor獲取數(shù)據(jù)需要一段曝光時間再加上壓縮數(shù)據(jù)所需的時間,不可能立刻響應(yīng),所以在時間上肯定不能滿足開始一段的數(shù)據(jù)傳輸請求。也需要繼續(xù)仔細分析在何時啟動camera模塊最為合適。
3.2 與Camera驅(qū)動和V4L2子系統(tǒng)的配合
在linux內(nèi)核中,2002年12月起發(fā)布了V4L2 (Video For Linux Two ) 0.1版本的規(guī)范,V4l2試圖為所有和視頻相關(guān)的設(shè)備都提供統(tǒng)一的接口,這其中當(dāng)然也就包括了Camera設(shè)備。
而USB Video Class這一部分內(nèi)容恰恰與視頻設(shè)備也是密切相關(guān)的,所以在某些平臺產(chǎn)品的實現(xiàn)中,甚至是在VideoClass中直接包含了Camera的驅(qū)動程序。這樣做對于單一產(chǎn)品來說,可以大大簡化驅(qū)動的層次結(jié)構(gòu),應(yīng)該說是處理Camera的最直接簡潔的辦法。
但是,在本文的實現(xiàn)中,考慮到Linux內(nèi)核中合理的模塊劃分的原則,也是為了符合Gadget驅(qū)動的其他Class實現(xiàn)的一貫風(fēng)格,所以還是盡量使用V4L2的接口來控制Camera模塊。這樣做也有利于代碼的移植。減小不同功能模塊之間的耦合性。
理想的方式自然是所有的與Camera相關(guān)的操作都通過V4L2接口來實現(xiàn),不過目前的實現(xiàn)中還是有些例外,引發(fā)例外的主要因素是效率問題。
由于在USB總線上傳輸圖像,受到總線速度的限制,特別是在非USB2.0接口的芯片中,所以勢必要采用JPEG或MPEG編碼對數(shù)據(jù)進行壓縮。V4L2子系統(tǒng)的框架中,包含了對編碼器的支持,但是,也許是筆者對V4L2子系統(tǒng)的學(xué)習(xí)還不夠深入,其對編碼器的支持應(yīng)該是對硬件編碼芯片的支持,即使如此,也沒有見到相關(guān)的代碼,而且,在實現(xiàn)中使用的手機主板上也沒有硬件的編解碼芯片,所以在實現(xiàn)中Camera驅(qū)動通過V4L2子系統(tǒng)對應(yīng)用層提供的是原始的未經(jīng)編碼的數(shù)據(jù)流,由應(yīng)用程序調(diào)用IJG ( Independent JPEG Group )JPEG庫函數(shù)來實現(xiàn)jpeg的編解碼工作。
所以如果通過V4L2的read接口來獲取數(shù)據(jù),勢必只能得到原始的圖像數(shù)據(jù),而且在V4L2的實現(xiàn)中,通過Read方式獲取的數(shù)據(jù),需要通過多次內(nèi)存拷貝才能到達調(diào)用者處。所以也會很大程度的影響圖像處理的速度。
要對圖像進行壓縮,要不在用戶空間調(diào)用IJG庫,要不在內(nèi)核中再實現(xiàn)一個JPEG壓縮算法。按前者來實現(xiàn)的話,涉及到Video Class如何去啟動一個用戶程序來讀取Camera數(shù)據(jù)并在壓縮后再傳送給內(nèi)核,也不是完全沒法實現(xiàn),但是無疑是一個非常糟糕的實現(xiàn)辦法。
后者的話,涉及到這個JPEG壓縮算法應(yīng)該在什么地方實現(xiàn),以及由誰來調(diào)用的問題(Video Class 還是 V4L2)??紤]到在存在硬件編碼芯片的情況下,該芯片的管理和使用應(yīng)該會納入V4L2子系統(tǒng)中,所以考慮到兼容性,目前實現(xiàn)的方式是將JPEG壓縮算法作為一個獨立的模塊插入內(nèi)核,由V4L2子系統(tǒng)調(diào)用相關(guān)函數(shù)對圖像數(shù)據(jù)進行壓縮,然后再在Camera驅(qū)動中Export一個額外的函數(shù)接口,USB Video Class通過該函數(shù)接口啟動Camera圖像的讀取和壓縮過程,以區(qū)別標(biāo)準(zhǔn)的V4L2子系統(tǒng)的數(shù)據(jù)處理流程。壓縮后的圖像數(shù)據(jù)直接寫入通過指針參數(shù)傳遞進來的內(nèi)存地址空間中,盡可能的減少內(nèi)存拷貝的次數(shù),加速圖像的傳遞。
這樣做帶來的問題就是需要在V4L2架構(gòu)中添加額外的接口,增加了USB Video Class和V4L2子系統(tǒng)之間的耦合性,不能完全將這兩個模塊隔離開來。應(yīng)該還有更好的解決方案。
3.3 JPEG編碼相關(guān)
Jpeg的編解碼,在Linux操作系統(tǒng)中,基本上采用的都是IJG(www.ijg.org)的JPEG庫函數(shù)Libjpeg,這是一個相當(dāng)可靠穩(wěn)定和高效的開源項目,支持JPEG標(biāo)準(zhǔn)(不包括JPEG2000)的絕大多數(shù)編碼方式。如非無奈,確實沒有必要另外再寫一個編碼程序。但是由于需要在內(nèi)核中使用,所以只好自己再編一個了。
JPEG編碼相關(guān)的代碼除了IJG的源代碼以外,在網(wǎng)上還可以搜索到若干,但是無疑IJG的代碼是最完善的。其它我能搜到的代碼,多多少少都有一些BUG,而且也只是實現(xiàn)了JPEG標(biāo)準(zhǔn)的最基本的功能(當(dāng)然,對于Video Class的應(yīng)用來說已經(jīng)是足夠了)。最重要的是,多數(shù)是用浮點數(shù)運算來實現(xiàn)的,撇開速度不說,在本文的實現(xiàn)中OMAP平臺的CPU也不支持浮點數(shù)運算。。。所以,本文實現(xiàn)中,最終是參考了網(wǎng)上搜到的某個算法的流程(主要是IJG的架構(gòu)太復(fù)雜,一來沒有時間精力和能力進行完整的分析,二來也不適合在內(nèi)核中使用如此復(fù)雜的架構(gòu)),在快速離散余弦變化的整數(shù)算法上仿照了IJG庫的算法兩者綜合起來完成的。最終的代碼還有很多需要改進的地方,不過,對于VideoClass來說,應(yīng)該勉強夠用了。這其中的具體問題,打算在另外單獨的文檔中再說明。
3.4 操作系統(tǒng)相關(guān)
說操作系統(tǒng)相關(guān),可能說大了一些,這里主要涉及的內(nèi)容是在本文的實現(xiàn)中,在WIN2000和WINXP平臺的MSN測試中,遇到的一些問題。
由于VideoClass的協(xié)議只是規(guī)定了數(shù)據(jù)傳輸?shù)母袷胶蛢?nèi)容,對具體實現(xiàn)中的一些細節(jié)并沒有作硬性的規(guī)定,所以導(dǎo)致有些細節(jié)可能存在不兼容的實現(xiàn)方式。(當(dāng)然,我想主要還是本文的實現(xiàn),由于能力有限,沒有充分考慮到各種情況下的容錯性,如果驅(qū)動做得好應(yīng)該可以避免出現(xiàn)問題)。所以在WIN2000和WINXP的MSN測試中,遇到了一些平臺相關(guān)的問題,有些功能在2000下能正常工作在XP下存在Bug,有些卻相反。有些已經(jīng)解決,有些只是猜測了可能的原因,羅列如下:
3.4.1 視頻窗口關(guān)閉再打開后,沒有圖像
開始是在XP的MSN上發(fā)現(xiàn)有這樣的問題,2000下沒有,分析BUS數(shù)據(jù)可以看到,XP在關(guān)閉視頻窗口的時候,會執(zhí)行一個Abort Pipe的操作,這個操作應(yīng)該會中斷BULK傳輸,但是在設(shè)備端,Gadget底層驅(qū)動接收不到這個事件(也有可能是Gadget底層驅(qū)動的BUG),所以在VideoClass中無從得知這個傳輸已經(jīng)被取消了,這樣睡眠在等待數(shù)據(jù)傳送完畢或失敗上的線程也就無法被喚醒,自然也就不會繼續(xù)發(fā)送數(shù)據(jù)。造成主機端再度打開視頻窗口時接收不到圖像數(shù)據(jù)。而在2000下的MSN中,關(guān)閉視頻窗口的動作系統(tǒng)不會發(fā)送這個Abort Pipe事件,所以也就沒有問題。
考慮到每次打開視頻窗口的時候,主機端都會設(shè)置Streaming Interface的圖像分辨率,碼率等參數(shù)。而這之后主機端才會讀取圖像數(shù)據(jù),所以后來解決的辦法是在主機端設(shè)置Streaming Interface的時候,將之前已經(jīng)放入BULK IN傳輸節(jié)點的數(shù)據(jù) Dequeue出來,這樣會造成這個傳輸?shù)氖?,從而喚醒睡眠的線程。但是如果僅僅這樣做,XP能夠正常工作了,2000又顯示不了圖像了。分析認為由于部分數(shù)據(jù)丟失,所以造成第一幀圖像的數(shù)據(jù)是不完整的,無法正常解壓縮顯示,但是XP下的MSN有較好的容錯性,能夠丟棄這一幀圖像,繼續(xù)讀取之后的數(shù)據(jù),而2000下的MSN容錯能力較差,無法再正常解讀后面的圖像數(shù)據(jù)。所以最終的解決辦法是在發(fā)現(xiàn)傳輸失敗后,將當(dāng)前這一幀的圖像數(shù)據(jù)從頭開始重新發(fā)送,這樣在XP和2000下就都能正常工作了。
不知道這種解決方案是否僅僅是一種治標(biāo)的方案,有待以后繼續(xù)研究。
3.4.2 某些分辨率下圖像無法正常顯示
在Win2000中如果提供160*120分辨率的圖像,圖像非常容易就停止刷新了,而BUS上實際數(shù)據(jù)還是在發(fā)送的。而在160*112(兩者都是16的整倍數(shù))的分辨率的情況下,就幾乎不會發(fā)生這種情況。如果說這有可能還是JPEG的壓縮算法有點問題,那另外一種情況就一定是XP 和 2000的區(qū)別了:如果設(shè)備這端通過描述符和Streaming Interface申明只能支持160*120 或者 160*112 的分辨率,2000可以接受這種分辨率,而XP根本就不能接受,總線上的控制傳輸就停止了,在界面上則顯示檢測不到Camera或Camera正在被其它設(shè)備打開占用,只有在進一步提供更高的320*240的分辨率的情況下,XP才會承認Camera的存在!其它問題倒不大,就是在本文的實現(xiàn)平臺上,受軟件編碼JPEG速度的限制,320*240的分辨率下,視頻的幀頻會低一些,影響圖像的流暢性。
3.5 其它
3.5.1 特殊效果的控制
應(yīng)該說,VideoClass的Control Request基本上涵蓋了V4L2標(biāo)準(zhǔn)界面提供的大部分控制參數(shù),但是,還是有一部分沒有涵蓋,至于特定驅(qū)動專有的控制就更無法體現(xiàn)了,尤其是在MSN等應(yīng)用程序的界面上,更不可能提供這些參數(shù)的控制了。但是,我們還是可以想辦法trick過這個問題。
比如手機上常見的圖像效果的設(shè)定,雖然不是特別有意義,但是既然是很常見的,為什么不能把它也做到Web Cam中呢?所以,如果一定要做,我們可以利用MSN控制界面上的原有的控制界面,借用其中一兩個控制參數(shù)來實現(xiàn)圖像效果的設(shè)定。
本文的實現(xiàn)中選擇采用色調(diào)來控制圖像效果,因為實際上這個參數(shù)是很不常用的,甚至只能在XP的高級設(shè)定中找到,對于99.9%的用戶我相信都不會去改變這個參數(shù)。而它的字面含義與我們實現(xiàn)的功能也不算一點關(guān)系都沒有,畢竟有很多效果實際上就是改變一下圖像的顏色(當(dāng)然還有一部分例外了)。
類似的可以用一些我們認為常用的設(shè)置替換既有的參數(shù)。這樣做的缺點就是控制參數(shù)的字面含義與實際功能不太吻合,優(yōu)點當(dāng)然就是可以提供給用戶更多更常用的圖像設(shè)置。比如設(shè)置一個黑白,素描之類的圖像的效果,玩玩抽象派視頻聊天。
評論