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

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

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

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


        可以看到,MDP4內部有4個overlay pipe,2個是for UI(RGB)的,2個VG是forvideo和graphics的;另外有2個mixer,mixer1是for primarydisplay的(可以是MDDI接口的,也可以是RGB接口的lcd、oled等);mixer2是for externaldisplay的,如通過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空間中有一個HDMIservice,包含一個listener(都是java的),當HDMIcable插入後,底層HDMI的驅動檢測到(HPD)後,通過kobject_uevent傳送給HDMIdaemon,daemon再把event發送給HDMI service,HDMIservice除了判斷這個event(cable狀態),另外還要判斷qualcommsetting中HDMI的on/off選項,然後把判斷結果broadcast給各個AP,各個AP也就知道當前是否要開啓HDMI輸出了

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

       再來看video mirroring是怎麼做的?

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

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


    sp<SurfaceComposerClient> client = new SurfaceComposerClient();//新建surface客戶端

    // create pushbuffer surface
    sp<Surface> surface = client->createSurface(getpid(), 0, 320, 240,
            PIXEL_FORMAT_UNKNOWN, ISurfaceComposer::ePushBuffers);//創建一個surface

    // get to the isurface
    sp<ISurface> isurface = Test::getISurface(surface);//得到surface相關接口
printf("isurface = %p\n", isurface.get());
   
    // now request an overlay
    sp<OverlayRef> ref = isurface->createOverlay(320, 240, PIXEL_FORMAT_RGB_565);//創建overlay,並得到控制通道
sp<Overlay> 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不送到primarydisplay上,而是通過新加的接口輸出到fb1設備上,而browser的UI正常顯示即可。如果是在高通平臺去實現的話,需要把qualcommsetting裏面的HDMI選項關掉,否則高通的做法和你自己AP的做法就亂套了。不過目前看,高通提供的方式似乎也可以滿足應用了,但應用是永無止境的,只要user有這樣的需求,developer就要去做,呵呵!



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