Camera3BufferManager registerStream

Camera3BufferManager 内部含有一组 Map,它们的关系如下:

StreamSetMap是一组StreamSet合集,StreamSet下含有一组 Map、streamInfoMap、handoutBufferCountMap 以及 attachedBufferCountMap。

加入知识星球与更多Camera同学交流
– 星球名称:深入浅出Android Camera
– 星球ID: 17296815

  • 第一,handout buffer Map是给client使用的buffer的集合。
  • 第二,freeBuffers 是属于特定某个buffer set的所有buffer的合集,由returnBufferForStream返回,待使用的buffer。
  • 第三,attached buffer可以是handout的,也可以是free的,它实际上是这两种的合集。

Camera3BufferManager

registerStream就是为这个streamInfo建立一组StreamSet。

  • StreamSet内部的Map也建立起来,并初始化为(key=streamId,val=0)。
  • 最后把StreamSet以key是streamSetId加到mStreamSetMap中。
  • 把stream以key为streamId加到mStreamMap中。

下面这段代码描述了这个逻辑:

status_t Camera3BufferManager::registerStream(wp<Camera3OutputStream>& stream,
        const StreamInfo& streamInfo) {
    ATRACE_CALL();

    int streamId = streamInfo.streamId;
    int streamSetId = streamInfo.streamSetId; 
    /* 分别拿到sTream的id以及setId.一个set含有三个Map,描述streamid的streamInfoMap,给stream的buf个数handoutBufferCountMap,stream attached的attachedBufferCountMap.*/

    Mutex::Autolock l(mLock);// 这是个利用构造析构的mutex锁.包了pthread_mutext.
    // 先尝试,一组StreamSetMap的StreamMap中找是否有streamid的stream.一个streamSetMap含有多个StreamSet.一个StreamSet含有多个Stream.
     for (size_t i = 0; i < mStreamSetMap.size(); i++) {
        ssize_t streamIdx = mStreamSetMap[i].streamInfoMap.indexOfKey(streamId);
    }
    // 根据StreamSetId在streamSetMap中找是否已经注册过了.如果找不到,我们需要new出一个StreamSet.
    // 并把这个新的StreamSet和StreamSetId关联到mStreamSetMap中.
    ssize_t setIdx = mStreamSetMap.indexOfKey(streamSetId);
    if (setIdx == NAME_NOT_FOUND) {/*没找到,怎么办?new出一个*/
        StreamSet newStreamSet;
        setIdx = mStreamSetMap.add(streamSetId, newStreamSet);
    }
    // 拿到刚才新的StreamSet,并取出其streamid.这里需要对StreamSet的handout ,attached的Map清零.
    StreamSet& currentStreamSet = mStreamSetMap.editValueAt(setIdx);//currentStreamSet是个友元
ssize_t streamIdx = currentStreamSet.streamInfoMap.indexOfKey(streamId);

currentStreamSet.streamInfoMap.add(streamId, streamInfo);
    currentStreamSet.handoutBufferCountMap.add(streamId, 0);
    currentStreamSet.attachedBufferCountMap.add(streamId, 0);
    mStreamMap.add(streamId, stream);
   return OK;
}

registerStream 的调用时机是什么?

根据 buf 的尺寸以及 buf 有何用途,针对性的生成一个 StreamInfo 结构,此时会利用 registerStream 注册进 mStreamSetMap 中。

下面这段代码体现了 registerStream 是如何使用的。

status_t Camera3OutputStream::configureQueueLocked() {// 虽然没有传参,但是内部基本上是调用成员变量的函数
    // 配置consumer侧的 ANativeWidow接口.consumer一般是Surface类.此时还要把一个listener注册进consumer.以便consumer在release时候可以及时通知Camera3BufferManager做一些release的buf管理.
    res = mConsumer->connect(NATIVE_WINDOW_API_CAMERA, /*listener*/mBufferReleasedListener);

    if (mBufferManager != 0 && mSetId > CAMERA3_STREAM_SET_ID_INVALID) {
        uint32_t consumerUsage = 0;
        getEndpointUsage(&consumerUsage);
        // 先生成描述这个stream的streaminfo
        // stream info依赖,这个stream描述的buf的宽,高,格式(yuv与否),数据空间.以及这块buf的用途.android系统把待显示的区域用不同的属性描述.
        StreamInfo streamInfo(getId(), getStreamSetId(), getWidth(), getHeight(), getFormat(), getDataSpace(),camera3_stream::usage | consumerUsage, mTotalBufferCount,                /*isConfigured*/true);
        wp<Camera3OutputStream> weakThis(this);
        // 把streaminfo注册进去,这里的this就是Camera3OutputStream类本身.
        res = mBufferManager->registerStream(weakThis,
                streamInfo);
        if (res == OK) {
            //此时先进值GraphicBuffer的产生.因为对于创建多大的GraphicBuffer是由Camera3BufferManager负责的.
            mConsumer->getIGraphicBufferProducer()->allowAllocation(false);
            mUseBufferManager = true;
        }
    }
}

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程