承接上一章节分析:【六】Android MediaPlayer整体架构源码分析 -【start请求播放处理流程】【Part 4】【05】
本系列文章分析的安卓源码版本:【Android 10.0 版本】
【此章节小节编号就接着上一章节排列】
8.3.2.4.2、useGraphicBuffer_l(portIndex, omxBuffer.mGraphicBuffer, buffer)实现分析:
使用图形Buffer
从下面方法上英文注释非常明确该方法的使用提示,它只是个向后兼容方法,一旦OMX实现改变,该方法可以被移除并重命名为useGraphicBuffer2来使用。
// [frameworks/av/media/libstagefright/omx/OMXNodeInstance.cpp]
// XXX: This function is here for backwards compatibility. Once the OMX
// implementations have been updated this can be removed and useGraphicBuffer2
// can be renamed to useGraphicBuffer.
status_t OMXNodeInstance::useGraphicBuffer_l(
OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
IOMX::buffer_id *buffer) {
if (graphicBuffer == NULL || buffer == NULL) {
ALOGE("b/25884056");
return BAD_VALUE;
}
// 首先检查是否使用了媒体元数据模式,我们可以在支持元数据meta的设备上运行一个实验来模拟遗留行为(预分配缓冲区)。
// First, see if we're in metadata mode. We could be running an experiment to simulate
// legacy behavior (preallocated buffers) on devices that supports meta.
if (mMetadataType[portIndex] != kMetadataBufferTypeInvalid) {
// 使用了媒体元数据模式时,使用图形Buffer与元数据
// 见下面的分析
return useGraphicBufferWithMetadata_l(
portIndex, graphicBuffer, buffer);
}
// 该图形Buffer模式下,必须开启了该模式
if (!mGraphicBufferEnabled[portIndex]) {
// Report error if this is not in graphic buffer mode.
ALOGE("b/62948670");
android_errorWriteLog(0x534e4554, "62948670");
return INVALID_OPERATION;
}
// See if the newer version of the extension is present.
OMX_INDEXTYPE index;
// 检查底层组件是否支持该扩展属性功能新版本,并返回其参数索引
// 备注:在所有软编解码器组件中都不支持该属性,该扩展属性功能一般为硬编解码器支持
if (OMX_GetExtensionIndex(
mHandle,
const_cast<OMX_STRING>("OMX.google.android.index.useAndroidNativeBuffer2"),
&index) == OMX_ErrorNone) {
// 支持该扩展属性时
// 使用graphicBuffer
// 见下面分析
return useGraphicBuffer2_l(portIndex, graphicBuffer, buffer);
}
// 该扩展属性功能在软编解码器中也不支持,通常硬Codec可能支持
OMX_STRING name = const_cast<OMX_STRING>(
"OMX.google.android.index.useAndroidNativeBuffer");
OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
if (err != OMX_ErrorNone) {
CLOG_ERROR(getExtensionIndex, err, "%s", name);
return StatusFromOMXError(err);
}
// 同上一样处理
BufferMeta *bufferMeta = new BufferMeta(graphicBuffer, portIndex);
OMX_BUFFERHEADERTYPE *header;
OMX_VERSIONTYPE ver;
ver.s.nVersionMajor = 1;
ver.s.nVersionMinor = 0;
ver.s.nRevision = 0;
ver.s.nStep = 0;
// 创建该扩展属性支持的参数结构对象
UseAndroidNativeBufferParams params = {
sizeof(UseAndroidNativeBufferParams), ver, portIndex, bufferMeta,
&header, graphicBuffer,
};
// 将该扩展属性参数结构配置信息设置给底层组件更新
err = OMX_SetParameter(mHandle, index, ¶ms);
if (err != OMX_ErrorNone) {
CLOG_ERROR(setParameter, err, "%s(%#x): %s:%u meta=%p GB=%p", name, index,
portString(portIndex), portIndex, bufferMeta, graphicBuffer->handle);
delete bufferMeta;
bufferMeta = NULL;
*buffer = 0;
return StatusFromOMXError(err);
}
CHECK_EQ(header->pAppPrivate, bufferMeta);
// 同样是创建新Buffer id和添加到活动buffer队列中
*buffer = makeBufferID(header);
addActiveBuffer(portIndex, *buffer);
CLOG_BUFFER(useGraphicBuffer, NEW_BUFFER_FMT(
*buffer, portIndex, "GB=%p", graphicBuffer->handle));
return OK;
}
useGraphicBufferWithMetadata_l(portIndex, graphicBuffer, buffer)实现分析:
使用了媒体元数据模式时,使用图形Buffer与元数据。该方法只处理输出端口buffer
// [frameworks/av/media/libstagefright/omx/OMXNodeInstance.cpp]
status_t OMXNodeInstance::useGraphicBufferWithMetadata_l(
OMX_U32 portIndex, const sp<GraphicBuffer> &graphicBuffer,
IOMX::buffer_id *buffer) {
// 必须是输出端口索引,否则失败
if (portIndex != kPortIndexOutput) {
return BAD_VALUE;
}
// 必须是这两种媒体元数据Buffer类型,否则失败
if (mMetadataType[portIndex] != kMetadataBufferTypeGrallocSource &&
mMetadataType[portIndex] != kMetadataBufferTypeANWBuffer) {
return BAD_VALUE;
}
// 然后使用该Buffer处理,见此前分析
status_t err = useBuffer_l(portIndex, NULL, NULL, buffer);
if (err != OK) {
return err;
}
// useBuffer_l分配Buffer header头信息成功时,查询Buffer Header头信息结构对象指针
// 见下面分析
OMX_BUFFERHEADERTYPE *header = findBufferHeader(*buffer, portIndex);
// 更新图形Buffer中的元数据
// 见下面分析
return updateGraphicBufferInMeta_l(portIndex, graphicBuffer, *buffer, header);
}
findBufferHeader(*buffer, portIndex)实现分析:
useBuffer_l分配Buffer header头信息成功时,查询Buffer Header头信息结构对象指针
// [frameworks/av/media/libstagefright/omx/OMXNodeInstance.cpp]
OMX_BUFFERHEADERTYPE *OMXNodeInstance::findBufferHeader(
IOMX::buffer_id buffer, OMX_U32 portIndex) {
if (buffer == 0) {
return NULL;
}