Android 12(S) 图像显示系统 - Surface 一点补充知识(十二)


必读:

Android 12(S) 图像显示系统 - 开篇


 

一、前言


因为个人工作主要是Android多媒体播放的内容,在工作中查看源码或设计程序经常会遇到调用API:

static inline int native_window_api_connect(struct ANativeWindow* window, int api)
static inline int native_window_api_disconnect(struct ANativeWindow* window, int api)

所以也一直好奇这两个方法都做了什么事情?这篇文章就来一探究竟。

 

二、native_window_api_connect 解析


Android系统中,开始播放视频并设置Surface后,都会做一次 connectToSurface 的操作,比如MediaCodec中,在初始化阶段setSurface后就会调用方法:

status_t MediaCodec::connectToSurface(const sp<Surface> &surface) {
    ...
    err = nativeWindowConnect(surface.get(), "connectToSurface");
    ...
}

这里就是去调用了 /frameworks/av/media/libstagefright/SurfaceUtils.cpp  中的方法:

status_t nativeWindowConnect(ANativeWindow *surface, const char *reason) {
    ALOGD("connecting to surface %p, reason %s", surface, reason);

    status_t err = native_window_api_connect(surface, NATIVE_WINDOW_API_MEDIA);
    ALOGE_IF(err != OK, "Failed to connect to surface %p, err %d", surface, err);

    return err;
}

是不是看到了 native_window_api_connect ,其中参数 NATIVE_WINDOW_API_MEDIA 表明 video decoder会作为生产者来生成buffer数据。

再接着往下走,看看到底做了什么?

大体的调用流程如下:

 /frameworks/native/libs/gui/Surface.cpp

 /frameworks/native/libs/gui/BufferQueueProducer.cpp


>>> static inline int native_window_api_connect(struct ANativeWindow* window, int api)

>>> int Surface::hook_perform(ANativeWindow* window, int operation, ...)

>>> int Surface::perform(int operation, va_list args)

>>> int Surface::dispatchConnect(va_list args)

>>> int Surface::connect(int api)

>>> int Surface::connect(int api, const sp<IProducerListener>& listener)

>>> int Surface::connect(int api, const sp<IProducerListener>& listener, bool reportBufferRemoval)

>>> status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
                int api, bool producerControlledByApp, QueueBufferOutput *output) 


最终进入到了BufferQueueProducer::connect函数中,看起来这里应该就是做具体事情的地方了

老规矩,看源码:

status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
        int api, bool producerControlledByApp, QueueBufferOutput *output) {
    ATRACE_CALL();
    std::lock_guard<std::mutex> lock(mCore->mMutex);
    mConsumerName = mCore->mConsumerName; // 消费者名字
    BQ_LOGV("connect: api=%d producerControlledByApp=%s", api,
            producerControlledByApp ? "true" : "false");
    // 对一些条件进行判断,必要时直接返回return
    if (mCore->mIsAbandoned) {
        BQ_LOGE("connect: BufferQueue has been abandoned");
        return NO_INIT;
    }

    if (mCore->mConsumerListener == nullptr) {
        BQ_LOGE("connect: BufferQueue has no consumer");
        return NO_INIT;
    }

    if (output == nullptr) {
        BQ_LOGE("connect: output was NULL");
        return BAD_VALUE;
    }

    if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
        BQ_LOGE("connect: already connected (cur=%d req=%d)",
                mCore->mConnectedApi, api);
        return BAD_VALUE;
    }

    int delta = mCore->getMaxBufferCountLocked(mCore->mAsyncMode,
            mDequeueTimeout < 0 ?
            mCore->mConsumerControlledByApp && producerControlledByApp : false,
            mCore->mMaxBufferCount) -
            mCore->getMaxBufferCountLocked();
    if (!mCore->adjustAvailableSlotsLocked(delta)) {
        BQ_LOGE("connect: BufferQueue failed to adjust the number of available "
                "slots. Delta = %d", delta);
        return BAD_VALUE;
    }

    int status = NO_ERROR;
    switch (api) {
        case NATIVE_WINDOW_API_EGL:
        case NATIVE_WINDOW_API_CPU:
        case NATIVE_WINDOW_API_MEDIA:
        case NATIVE_WINDOW_API_CAMERA:
            mCore->mConnectedApi = api;

            output->width = mCore->mDefaultWidth;
            output->height = mCore->mDefaultHeight;
            output->transformHint = mCore->mTransformHintInUse = mCore->mTransformHint;
            output->numPendingBuffers =
                    static_cast<uint32_t>(mCore->mQueue.size());
            output->nextFrameNumber = mCore->mFrameCounter + 1;
            output->bufferReplaced = false;
            output->maxBufferCount = mCore->mMaxBufferCount;

            if (listener != nullptr) {
                // Set up a death notification so that we can disconnect
                // automatically if the remote producer dies
#ifndef NO_BINDER
                if (IInterface::asBinder(listener)->remoteBinder() != nullptr) {
                    status = IInterface::asBinder(listener)->linkToDeath(
                            static_cast<IBinder::DeathRecipient*>(this));
                    if (status != NO_ERROR) {
                        BQ_LOGE("connect: linkToDeath failed: %s (%d)",
                                strerror(-status), status);
                    }
                    mCore->mLinkedToDeath = listener;
                }
#endif
                mCore->mConnectedProducerListener = listener; // 设置producer listener
                mCore->mBufferReleasedCbEnabled = listener->needsReleaseNotify();
            }
            break;
        default:
            BQ_LOGE("connect: unknown API %d", api);
            status = BAD_VALUE;
            break;
    }
    mCore->mConnectedPid = BufferQueueThreadState::getCallingPid();
    mCore->mBufferHasBeenQueued = false;
    mCore->mDequeueBufferCannotBlock = false;
    mCore->mQueueBufferCanDrop = false;
    mCore->mLegacyBufferDrop = true;
    if (mCore->mConsumerControlledByApp && producerControlledByApp) {
        mCore->mDequeueBufferCannotBlock = mDequeueTimeout < 0;
        mCore->mQueueBufferCanDrop = mDequeueTimeout <= 0;
    }

    mCore->mAllowAllocation = true; // 允许分配 graphic buffer
    VALIDATE_CONSISTENCY();
    return status;
}

我才疏学浅,按我理解,就是完成了一些初始化的操作,貌似也没啥了,这之后应该produder就可以 dequeue buffer 了

另外一点,这里有设置producer listener,之前文章中也讲过,貌似也没啥作用(也许我错了)

    mCore->mConnectedProducerListener = listener;
    mCore->mBufferReleasedCbEnabled = listener->needsReleaseNotify();

三、native_window_api_disconnect 解析


disconnect的调用流程和connect的流程类似。

 

 

 

 

关注公众号 Android元宇宙 继续阅读相关文章!

posted on 2022-03-24 09:41  二的次方  阅读(5764)  评论(4编辑  收藏  举报