• Android Overlay学习


    前文仅了解了overlay HAL的架构,下面继续看看系统层是如何调用Overlay模块。

    1、 测试代码

    frameworks/base/libs/surfaceflinger/tests/overlays/overlays.cpp提供了一个简单的overlay调用流程,可惜这个测试程序有错误,
        在sp<Surface> surface = client->createSurface(getpid(), 0, 320, 240, PIXEL_FORMAT_UNKNOWN, ISurfaceComposer::ePushBuffers);
    这句话编译不过去,错误在Surface的申请,和overlay无关。

    我们来看看这段代码:

    int main(int argc, char** argv)
    {
        // set up the thread-pool 建立线程池
        sp<ProcessState> proc(ProcessState::self());
        ProcessState::self()->startThreadPool();

        // create a client to surfaceflinger 创建一个SurfaceFlinger client
        sp<SurfaceComposerClient> client = new SurfaceComposerClient();
       
        // create pushbuffer surface 创建一个surface,最后那个参数是类型?
        sp<Surface> surface = client->createSurface(getpid(), 0, 320, 240,
                PIXEL_FORMAT_UNKNOWN, ISurfaceComposer::ePushBuffers);

        // get to the isurface 取得isurface接口
        sp<ISurface> isurface = Test::getISurface(surface);
        printf("isurface = %p/n", isurface.get());
       
        // now request an overlay 创建一个overlay
        sp<OverlayRef> ref = isurface->createOverlay(320, 240, PIXEL_FORMAT_RGB_565);
        sp<Overlay> overlay = new Overlay(ref);
       
        /*
         * here we can use the overlay API 创建好overlay后,即可使用overlay的API,这些都对应到overlay HAL的具体实现
         */
       
        overlay_buffer_t buffer;
        overlay->dequeueBuffer(&buffer);
        printf("buffer = %p/n", buffer);
       
        void* address = overlay->getBufferAddress(buffer);
        printf("address = %p/n", address);

        overlay->queueBuffer(buffer);//最重要的操作就是通过queueBuffer将buffer列队

        return 0;
    }

    2、Android系统创建中Overlay(调用createOverlay)

    1)摄像头相关 CameraService.cpp (frameworks/base/camera/libcameraservice)
    setPreviewDisplay()、startPreviewMode()
    |
    setOverlay()
    |
    creatOverlay()

    2)界面相关 ISurface.cpp (frameworks/base/libs/ui)
    LayerBaseClient::Surface::onTransact() <--该函数位于LayerBase.cpp,好像是用于ibind进程通讯的函数
    |
    BnSurface::onTransact() //有5种方式,只有确定有overlay硬件支持时才会调用case CREATE_OVERLAY
    |
    ... ...
    switch(code) {
            case REQUEST_BUFFER: {
                CHECK_INTERFACE(ISurface, data, reply);
                int bufferIdx = data.readInt32();
                int usage = data.readInt32();
                sp<GraphicBuffer> buffer(requestBuffer(bufferIdx, usage));
                return GraphicBuffer::writeToParcel(reply, buffer.get());
            }
            case REGISTER_BUFFERS: {
                CHECK_INTERFACE(ISurface, data, reply);
                BufferHeap buffer;
                buffer.w = data.readInt32();
                buffer.h = data.readInt32();
                buffer.hor_stride = data.readInt32();
                buffer.ver_stride= data.readInt32();
                buffer.format = data.readInt32();
                buffer.transform = data.readInt32();
                buffer.flags = data.readInt32();
                buffer.heap = interface_cast<IMemoryHeap>(data.readStrongBinder());
                status_t err = registerBuffers(buffer);
                reply->writeInt32(err);
                return NO_ERROR;
            } break;
            case UNREGISTER_BUFFERS: {
                CHECK_INTERFACE(ISurface, data, reply);
                unregisterBuffers();
                return NO_ERROR;
            } break;
            case POST_BUFFER: {
                CHECK_INTERFACE(ISurface, data, reply);
                ssize_t offset = data.readInt32();
                postBuffer(offset);
                return NO_ERROR;
            } break;
            case CREATE_OVERLAY: {
                CHECK_INTERFACE(ISurface, data, reply);
                int w = data.readInt32();
                int h = data.readInt32();
                int f = data.readInt32();
                sp<OverlayRef> o = createOverlay(w, h, f);
                return OverlayRef::writeToParcel(reply, o);
            } break;
            default:
                return BBinder::onTransact(code, data, reply, flags);
    ... ...


    3)LayerBuffer.cpp (frameworks/base/libs/surfaceflinger) 这儿其实是createOverlay的实现
    sp<OverlayRef> LayerBuffer::SurfaceLayerBuffer::createOverlay(uint32_t w, uint32_t h, int32_t format)
    |
    sp<OverlayRef> LayerBuffer::createOverlay(uint32_t w, uint32_t h, int32_t f)
    |
    sp<OverlaySource> source = new OverlaySource(*this, &result, w, h, f); //通过OverlaySource来创建overlay

    LayerBuffer::OverlaySource::OverlaySource()//该函数调用了Overlay HAL的API createOverlay
    {
        overlay_control_device_t* overlay_dev = mLayer.mFlinger->getOverlayEngine();//get HAL
        overlay_t* overlay = overlay_dev->createOverlay(overlay_dev, w, h, format);//HAL API

        // enable dithering...
        overlay_dev->setParameter(overlay_dev, overlay, OVERLAY_DITHER, OVERLAY_ENABLE);
    //设置参数,初始化OverlayRef类,OverlayRef的构造函数在Overlay.cpp中
        mOverlay = overlay;
        mWidth = overlay->w;
        mHeight = overlay->h;
        mFormat = overlay->format;
        mWidthStride = overlay->w_stride;
        mHeightStride = overlay->h_stride;
        mInitialized = false;
    ... ...
        *overlayRef = new OverlayRef(mOverlayHandle, channel,mWidth, mHeight, mFormat, mWidthStride, mHeightStride);
    }

    3、Overlay HAL模块管理
    Overlay.cpp (frameworks/base/libs/ui)负责管理overlay HAL,并对HAL的API进行封装

    1)打开Overlay HAL模块
    Overlay::Overlay(const sp<OverlayRef>& overlayRef)
        : mOverlayRef(overlayRef), mOverlayData(0), mStatus(NO_INIT)
    {
        mOverlayData = NULL;
        hw_module_t const* module;
        if (overlayRef != 0) {
            if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) {
                if (overlay_data_open(module, &mOverlayData) == NO_ERROR) {
                    mStatus = mOverlayData->initialize(mOverlayData,
                            overlayRef->mOverlayHandle);
                }
            }
        }
    }

    2)Overlay HAL的初始化
    参考上一段,overlayRef = new OverlayRef(mOverlayHandle, channel,mWidth, mHeight, mFormat, mWidthStride, mHeightStride);

    构造函数位于Overlay.cpp
    OverlayRef::OverlayRef(overlay_handle_t handle, const sp<IOverlay>& channel,
             uint32_t w, uint32_t h, int32_t f, uint32_t ws, uint32_t hs)
        : mOverlayHandle(handle), mOverlayChannel(channel),
        mWidth(w), mHeight(h), mFormat(f), mWidthStride(ws), mHeightStride(hs),
        mOwnHandle(false)
    {
    }

    3)封装了很多的API,但是没有查到那儿有调用,看来还需要大改框架才能真正将overlay利用起来
    比如TI自己写的opencore函数中到时有用到,主要负责视频输出。
    Android_surface_output_omap34xx.cpp (hardware/ti/omap3/libopencorehw)

    4、总结
    Overlay的输出对象有两种,一种是视频(主要是YUV格式,调用系统的V4L2),另外一个是ISurface的一些图像数据(RGB格式,直接写framebuffer)
    从代码实现角度看,目前Android系统默认并没有使用Overlay功能,虽然提供了Skeleton的Overlay HAL,并对其进行封装,但是上层几乎没有调用到封装的API。
    如果要用好Overlay HAL,需要大量修改上层框架,这对视屏播放可能比较重要,可参考TI的Android_surface_output_omap34xx.cpp。
    此外Surface实现的Overlay功能和Copybit的功能有部分重复,从TI的代码看主要是实现V4L2的Overlay功能。

    http://hi.baidu.com/aokikyon/blog/item/6e4e622c4fdaaae18a1399d4.html

  • 相关阅读:
    产品 | What's产品经理
    产品 | 互联网+“加油”
    微信小程序 | 未来O2O电商的“阴谋”
    推荐书籍 | 产品必备书籍
    iOS | NSProxy
    iOS | 解决中文乱码
    HTML DOM addEventListener() 方法
    给每个对象加上新的属性
    vue.config.js基础配置
    SEO要点
  • 原文地址:https://www.cnblogs.com/eustoma/p/2415841.html
Copyright © 2020-2023  润新知