【轉】Android上HDMI介紹(基於高通平臺)

轉自:http://hi.baidu.com/leowenj/blog/item/7942f05fd3de754cfaf2c005.html

作者:LeoWenJ

本文重點針對HDMI在android上的應用,而比較相關的就是overlay機制。overlay在這裏只是簡單的介紹,後續會有文章再專門詳述。

我沒記錯的話,高通從7X30開始,平臺就可以支持HDMI(1.3)輸出了。只不過在7x30上通過RGB接口外接一顆HDMI的transmitter來實現;而到了8系列(8x60),高通把這顆IC也集成了,直接就提供HDMI的輸出了。(這樣下去,以後漸漸的把外圍器件都集成了,做底層的估計要失業了,做硬件的似乎工作量也沒多少了)。

先來看看HW的能力,下圖是MDP4.0的結構圖:

1
可以看到,MDP4內部有4個overlay pipe,2個是for UI(RGB)的,2個VG是for video和graphics的;另外有2個mixer,mixer1是for primary display的(可以是MDDI接口的,也可以是RGB接口的lcd、oled等);mixer2是for external display的,如通過RGB interface2外接HDMI transmitter到TV,也可以是NTSC/PAL等模擬電視信號。

        Note:VG1和RGB1被mixer1混合到primary lcd,VG2和RGB2被mixer2混合到external LCD(如HDMI TV)

如果是MDP4.1的話,MDDI接口被移除了,另外RGB接口只有一個,另一個內部集成爲HDMI接口了。

上面提到的是硬件平臺相關的,就是說硬件有支持HDMI輸出的能力,但是軟件的狀況呢?我們來看看Android和高通的狀況。

關於HDMI本身,我就不介紹了,網上隨便找找都可以看明白。

研究過Android的都知道,surfacefinger負責管理應用程序的顯示窗口,每個窗口可以由多個surface組成,surfaceflinger通過OpenGL(可以通過HW,也可以是SW)把所有的surface合成後,通過調用gralloc模塊或是overlay模塊(MDP4.X才支持)把整屏數據送到顯示設備上。可是Android(截止到2.2,3.0的狀況還未知)上目前只支持一個顯示設備,也就是說在surfaceflinger只能固定一個顯示設備,那麼HDMI這個應用在android手機上如何應用呢?

這裏介紹2個做法,一個是高通給做好的,叫做UI mirroring和video mirroring;另一個就是我們自己添加接口,AP自己來實現想要的功能。

先來看高通在android中的做法,根據字面不難理解,UI mirroring和video mirroring其實就是把原來顯示在primary LCD上的數據mirror到HDMI接口。下圖爲軟件框架圖:

無標題

先來看看HDMI的控制方面,上圖的右側,user空間中有一個HDMI service,包含一個listener(都是java的),當HDMI cable插入後,底層HDMI的驅動檢測到(HPD)後,通過kobject_uevent傳送給HDMI daemon,daemon再把event發送給HDMI service,HDMI service除了判斷這個event(cable狀態),另外還要判斷qualcomm setting中HDMI的on/off選項,然後把判斷結果broadcast給各個AP,各個AP也就知道當前是否要開啓HDMI輸出了

接着先看UI mirroring(不含video的狀況)的實現,它針對的是界面的操作,數據爲RGB格式。我們知道在kernel中每個顯示設備都對應一個fb,初始化時都會分配framebuffer,在這裏,primary lcd對應fb0設備,HDMI對應fb1設備。正常情況下,surfaceflinger合成好一個main surface後,通過post buffer(gralloc模塊)把數據放入fb0,然後,通過overlay(kernel下做的,上層看到的還是通過IOCRL-FBIOPUT_VSCREENINFO命令實現)輸出到primary lcd;當平臺支持HDMI並且UI mirroring開啓時,gralloc中(framebuffer.cpp)初始化時會多創建一個task(hdmi_ui_loop),並新建一個overlay(主要是控制和數據,參考overlaylib.h),這個overlay對應的channel固定爲fb1,src fd就是fb0,也就是說這個overlay的源數據就是fb0,也就是primary lcd上的數據,通過rotator進行旋轉(電視是橫屏),然後在overlay中再scale up後再通過HDMI送到TV。這樣看來,送到HDMI上的數據其實就是把fb0中的數據copybit了一份並放大,多少會有些失真的,但對於UI界面來說是可以接受的。上述整個過程,surfaceflinger是不參與的。

再來看video mirroring是怎麼做的?

先來看看什麼是video mirroring,其實就是手機播放視頻,同時通過HDMI輸出到TV上,手機上的內容分爲2個部分,一個是視頻本身部分,另一個是UI,這已經佔用2個overlay pipe了(一個VG pipe,一個RGB pipe),TV上視頻部分肯定是需要一個VG pipe的,另外,由於視頻大小問題,視頻不可能正好爲全屏模式,這樣必須還需要一個RGB pipe來實現一個背景(全黑)。4個pipe都被佔用了,沒有多餘的pipe來把UI部分傳到TV上,所以再使用高通平臺時候,進行video mirroring時,TV上只能播放視頻畫面,UI部分(如菜單)在TV上是無法顯示的。

接着來看video部分是怎麼處理的?首先手機端UI部分的處理模式不變,只不過上面提到的hdmi_ui_loop這個task會被停掉(UI不需要送到HDMI,原因上面已經解釋過);video部分的frame通過opencore解碼出來後,首先會通過surfaceflinger來創建overlay(參考layerbuffer.cpp),當系統支持HDMI時通過create overlay都會創建2個通道(這裏是2個VG通道),其中包含2個control channel和2個data channel,它們的HAL層接口都再overlaylib.cpp中,channel0 for fb0;channel1 for fb1,如果需要旋轉,則從系統pmem中再分配對應的內存。AP中overlay基本上的流程是這樣的(可以參考overlays.cpp,裏面不全,我補充了一些):

    sp client = new SurfaceComposerClient();//新建surface客戶端
    // create pushbuffer surface
    sp surface = client->createSurface(getpid(), 0, 320, 240,
            PIXEL_FORMAT_UNKNOWN, ISurfaceComposer::ePushBuffers);//創建一個surface

    // get to the isurface
    sp isurface = Test::getISurface(surface);//得到surface相關接口
    printf("isurface = %p/n", isurface.get());
    // now request an overlay
    sp ref = isurface->createOverlay(320, 240, PIXEL_FORMAT_RGB_565);//創建overlay,並得到控制通道
    sp overlay = new Overlay(ref);//初始化overlay並得到數據通道

    overlay->setFd(mFd);//設置src data的fd

    overlay->setCrop(x,y,w,h);//設置剪裁信息(根據需要)

    overlay->queueBuffer(offset);//設置顯示數據的偏移

這樣video player沒解碼出一個frame,都會調用quene函數把數據送入2個數據通道,overlay engine會把數據送到2個顯示設備。

關於那個背景,暫時在code中還沒發現,也許是因爲目前的版本不是最終版本,後續還會更新。

上面的做法是高通的;但它是有限制的,比如說無法在2個屏幕上顯示不同的內容。如果我們要做,也是可以的,主要就是看AP怎麼定義規則了。另外framework中需要添加接口,主要是提供一個針對fb1設備的控制接口,同樣也是繞過surfaceflinger。比如說手機在播放一個影片,通過HDMI把影片傳送到TV上,同時手機端可以去瀏覽網頁。這個功能可以這樣做,AP背景播放影片,得到的frame不送到primary display上,而是通過新加的接口輸出到fb1設備上,而browser的UI正常顯示即可。如果是在高通平臺去實現的話,需要把qualcomm setting裏面的HDMI選項關掉,否則高通的做法和你自己AP的做法就亂套了。不過目前看,高通提供的方式似乎也可以滿足應用了,但應用是永無止境的,只要user有這樣的需求,developer就要去做,呵呵!

發佈了35 篇原創文章 · 獲贊 13 · 訪問量 27萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章