Android 13 - Media框架(25)- OMXNodeInstance(二)

上一节我们了解了 OMXNodeInstance 的创建过程,以及 IOmx 服务和 OMXNodeInstance、OMX组件之间的联系。接下来我们将一起了解 ACodec 是如何通过 OMXNodeInstance 这个中间层进行端口定义设置,以及端口Buffer分配的。

OMXNodeInstance 的代码还是比较长的,我们需要重点抓住和 Buffer 相关的内容,也就是端口定义、Buffer分配以及 Buffer 传递,了解了 Buffer 那我们对 OpenMax 的学习就会很轻松了。

1、setPortMode

我们之前在学习 ACodec configureCodec 流程时看到有很多 portMode,端口类型确定之后就会调用 setPortMode 方法将端口模式设定给 OMXNode,最终设置给 OMX 组件。

status_t ACodec::setPortMode(int32_t portIndex, IOMX::PortMode mode) {
   
    status_t err = mOMXNode->setPortMode(portIndex, mode);
    if (err != OK) {
   
        ALOGE("[%s] setPortMode on %s to %s failed w/ err %d",
                mComponentName.c_str(),
                portIndex == kPortIndexInput ? "input" : "output",
                asString(mode),
                err);
        return err;
    }

    mPortMode[portIndex] = mode;
    return OK;
}

OMXNodeInstance 会根据设定的内容对 OMX 组件进行配置,我们这里暂时只研究解码的情况,一般解码流程可能会涉及到如下几种 port Mode:

  • in Port
    • non-secure:kPortModePresetByteBuffer,上层可以直接读写buffer;
    • secure:kPortModePresetSecureBuffer,上层需要用特殊的方式读写buffer;
  • out Port
    • has native window
      • tunnel mode:上层不需要接收 output buffer;
      • non tunnel mode:kPortModeDynamicANWBuffer,使用动态的native window;
    • no native window
      • non-secure: kPortModePresetByteBuffer,上层可以直接读写buffer;
      • secure:error,不允许这种情况。

1.1、kPortModePresetByteBuffer

之前我们讲过,Preset 是预设的意思,表示这块buffer是预先分配好的,之后使用过程中就不会发生变化了;ByteBuffer 指的是普通的buffer,我们通过指针就可以读写buffer中的内容。

kPortModePresetByteBuffer 会在两个情况下使用:

  • 普通解码的 input buffer;
  • 普通解码且无surface的 output buffer;

这两种情况下是可以通过指针读写 buffer 中内容的,也就意味着内容是不受保护的。

status_t OMXNodeInstance::setPortMode(OMX_U32 portIndex, IOMX::PortMode mode) {
   
    case IOMX::kPortModePresetByteBuffer:
    {
   
        // Disable secure buffer, native buffer and metadata.
        (void)enableNativeBuffers_l(portIndex, OMX_TRUE /*graphic*/, OMX_FALSE);
        (void)enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_FALSE);
        (void)storeMetaDataInBuffers_l(portIndex, OMX_FALSE, NULL);
        break;
    }
}

从注释中我们可以看出来,需要关闭端口的 secure buffer,native buffer以及metadata功能,这里的native buffer指的应该就是graphic buffer。

从这里我们可以猜测,OMX 组件端口使用的buffer可能有3种,默认使用普通buffer:

  • 普通buffer;
  • secure buffer;
  • graphic buffer;

1.1.1、enableNativeBuffers_l

使用普通 buffer 就要把另外两个配置关闭,这里可以通过enableNativeBuffers_l方法来完成,之所以通过一个方法(并且方法名为 native buffer),是因为这些buffer本身都应该是由 native 层分配。由于OMXNodeInstance 把 secure buffer, graphic buffer的设置放到一起了,所以enableNativeBuffers_l容易把人看晕,把他拆成两部分:

先看 native buffer(graphic buffer)的配置部分,除了调用OMX_SetParameter对组件进行设定外,还将 mGraphicBufferEnabled 数组置为了 true/false,用于标记端口是否使用graphic buffer,如果使用了就置为true,没有使用就置为false。

		OMX_STRING name = "OMX.google.android.index.enableAndroidNativeBuffers"
        EnableAndroidNativeBuffersParams params;
        InitOMXParams(&params);
        params.nPortIndex = portIndex;
        params.enable = enable;

        err = OMX_SetParameter(mHandle, index, &params);
        CLOG_IF_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d", name, index,
                      portString(portIndex), portIndex, enable);
        if (err == OMX_ErrorNone) {
   
            mGraphicBufferEnabled[portIndex] = enable;
        } else if (enable) {
   
            mGraphicBufferEnabled[portIndex] = false;
        }

再看 secure buffer 的配置部分,secure buffer 对应的配置名称为 native handle,这是因为native层分配的buffer会以handle的形式回传上层,从而保护buffer。

		OMX_STRING name = "OMX.google.android.index.allocateNativeHandle"
        EnableAndroidNativeBuffersParams params;
        InitOMXParams(&params);
        params.nPortIndex = portIndex;
        params.enable = enable;

        err = OMX_SetParameter(mHandle, index, &params);
        CLOG_IF_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d", name, index,
                      portString(portIndex), portIndex, enable);
        if (!graphic) {
   
            if (err == OMX_ErrorNone) {
   
                mSecureBufferType[portIndex] =
                    enable ? kSecureBufferTypeNativeHandle : kSecureBufferTypeOpaque;
            } else if (mSecureBufferType[portIndex] == kSecureBufferTypeUnknown) {
   
                mSecureBufferType[portIndex] = kSecureBufferTypeOpaque;
            }
        }

如果 secure buffer 设置成功,那么 mSecureBufferType 会被设置为 kSecureBufferTypeNativeHandle,否则置为 kSecureBufferTypeOpaque。

我们这里大概知道:

  • secure buffer -> Native Handle;
  • graphic buffer -> Native Buffer;

1.1.2、storeMetaDataInBuffers_l

除了以上两项配置外,还有额外的meta data type需要配置,我们前面了解过graphic buffer需要和metadata 搭配使用,但是metadata也有不同的类型,我们需要告知 OMX 组件使用哪一种 metaData,运行过程中OMX组件就会根据类型来解析metaData了:

status_t OMXNodeInstance::storeMetaDataInBuffers_l(
        OMX_U32 portIndex, OMX_BOOL enable, MetadataBufferType *type) {
   
    OMX_INDEXTYPE index;
    OMX_STRING name = const_cast<OMX_STRING>(
            "OMX.google.android.index.storeMetaDataInBuffers");

    OMX_STRING nativeBufferName = const_cast<OMX_STRING>(
            "OMX.google.android.index.storeANWBufferInMetadata");
    MetadataBufferType negotiatedType;
    // 如果参数type不指定具体类型,那么默认使用kMetadataBufferTypeANWBuffer
    MetadataBufferType requestedType = type != NULL ? *type : kMetadataBufferTypeANWBuffer;

    StoreMetaDataInBuffersParams params;
    InitOMXParams(&params);
    params.nPortIndex = portIndex;
    params.bStoreMetaData = enable;
	// 接下来是尝试设置 meta data type,如果设置不成功就设置另外一种
    OMX_ERRORTYPE err =
        requestedType == kMetadataBufferTypeANWBuffer
                ? OMX_GetExtensionIndex(mHandle, nativeBufferName, &index)
                : OMX_ErrorUnsupportedIndex;
    OMX_ERRORTYPE xerr = err;
    if (err == OMX_ErrorNone) {
   
        err = OMX_SetParameter(mHandle, index, &params);
        if (err == OMX_ErrorNone) {
   
            name = nativeBufferName; // set name for debugging
            negotiatedType = requestedType;
        }
    }
    if (err != OMX_ErrorNone) {
   
        err = OMX_GetExtensionIndex(mHandle, name, &index);
        xerr = err;
        if (err == OMX_ErrorNone) {
   
            negotiatedType =
                requestedType == kMetadataBufferTypeANWBuffer
                        ? kMetadataBufferTypeGrallocSource : requestedType;
            err = OMX_SetParameter(mHandle, index, &params);
        }
        if (err == OMX_ErrorBadParameter) {
   
            err = OMX_ErrorUnsupportedIndex;
        }
    }
...
 else {
   
        if (!enable) {
   
            negotiatedType = kMetadataBufferTypeInvalid;
        }
        mMetadataType[portIndex] = negotiatedType;
    }

    if (type != NULL) {
   
        *type = negotiatedType;
    }

    return StatusFromOMXError(err);
}

storeMetaDataInBuffers_l 的代码比较长,主要是因为由两种meta data,一种是 kMetadataBufferTypeANWBuffer,另一种是kMetadataBufferTypeGrallocSource

默认情况下storeMetaDataInBuffers_l的第三个参数不填类型,默认使用 kMetadataBufferTypeANWBuffer,也就是于 graphic buffer 搭配使用的 meta data类型。设置的 meta data类型会被记录到 mMetadataType 中,后续还会使用到。

如果是用的普通 buffer (Byte Buffer),那么就不需要meta data了,mMetadataType会被设置为 kMetadataBufferTypeInvalid

1.1.3、总结

综上:
当使用 Byte Buffer时,端口定义设置如下:

  • native handle(secure):disabled;
  • native buffer(graphic):disabled;
    • meta data:invaild;

1.2、kPortModeDynamicANWBuffer

有了上面内容的学习,设定端口为DynamicANWBuffer就很简单了:

    case IOMX::kPortModeDynamicANWBuffer:
    {
   
        if (portIndex == kPortIndexOutput) {
   
            if (mLegacyAdaptiveExperiment) {
   
                CLOG_INTERNAL(setPortMode, "Legacy adaptive experiment: "
                        "not setting port mode to %s(%d) on output",
                        asString(mode), mode);
                err = StatusFromOMXError(OMX_ErrorUnsupportedIndex);
                break;
            }

            err = enableNativeBuffers_l(
                    portIndex, OMX_TRUE /*graphic*/, OMX_TRUE);
            if (err != OK) {
   
                break;
            }
        }
        (void)enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_FALSE);
        err = storeMetaDataInBuffers_l(portIndex, OMX_TRUE, NULL);
        break;
    }

需要开启 grapihc buffer,关闭 secure buffer,使用 meta data,具体的端口设定如下:

  • native handle(secure):disabled;
  • native buffer(graphic):enabled;
    • meta data:kMetadataBufferTypeANWBuffer;

1.3、kPortModePresetSecureBuffer

secure buffer的设定同样很简单,需要关闭 grapihc buffer,开启 secure buffer,不使用 meta data,具体的端口设定如下:

  • native handle(secure):enabled;
  • native buffer(graphic):disabled;
    • meta data:invaild;
      这里我们要注意的是,secure buffer是不需要meta data的。
    case IOMX::kPortModePresetSecureBuffer:
    {
   
        // Allow on both input and output.
        (void)storeMetaDataInBuffers_l(portIndex, OMX_FALSE, NULL);
        (void)enableNativeBuffers_l(portIndex, OMX_TRUE /*graphic*/, OMX_FALSE);
        err = enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_TRUE);
        break;
    }

相关推荐

  1. Android 13 - Media框架25)- OMXNodeInstance

    2023-12-22 23:44:02       37 阅读
  2. Android 13 - Media框架20)- ACodec(

    2023-12-22 23:44:02       30 阅读
  3. Android 13 - Media框架22)- ACodecBufferChannel

    2023-12-22 23:44:02       24 阅读
  4. Android 13 - Media框架21)- ACodec(三)

    2023-12-22 23:44:02       34 阅读
  5. Android 13 - Media框架22)- ACodec(四)

    2023-12-22 23:44:02       83 阅读
  6. Android 13 - Media框架22)- MediaCodec(三)

    2023-12-22 23:44:02       38 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-22 23:44:02       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-22 23:44:02       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-22 23:44:02       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-22 23:44:02       18 阅读

热门阅读

  1. 基于YALMIP求解含SOP+阶锥的配电网重构附Matlab代码

    2023-12-22 23:44:02       43 阅读
  2. 单元测试优化实践总结

    2023-12-22 23:44:02       33 阅读
  3. 使用MATLAB中的`xlswrite`函数将数据写入Excel文件

    2023-12-22 23:44:02       46 阅读
  4. 傅里叶变换全息图 Matlab

    2023-12-22 23:44:02       47 阅读
  5. Python---案例-多任务版TCP服务端程序开发

    2023-12-22 23:44:02       35 阅读
  6. LeetCode刷题(文章链接汇总)

    2023-12-22 23:44:02       47 阅读
  7. linux RCU 使用实例

    2023-12-22 23:44:02       31 阅读
  8. 卸载anaconda报错Error: Unable to move .anaconda

    2023-12-22 23:44:02       41 阅读
  9. Halcon DL-Model相关算子

    2023-12-22 23:44:02       33 阅读
  10. MATLAB中的协方差函数

    2023-12-22 23:44:02       34 阅读
  11. 楼宇对讲门铃的芯片构成分析

    2023-12-22 23:44:02       37 阅读
  12. 代码随想录 279. 完全平方数

    2023-12-22 23:44:02       34 阅读