之前学习了surfaceflinger和stagefright 两大模块,
这两大模块之间联系最大的地方,就是surfaceflinger 管理显示buffer,然后stagefright 如何用这个buffer
这里总结一下这一块自己学习的知识点
平台samsung exynos ,android 4.4
实际上本文想研究的就是三个问题:
(1)如何获取显示buffer,并且怎么把它告诉给OMX
(2)解码的时候,OMX如何把这个buffer告诉给解码器,作为视频数据输出的buffer
(3)有了buffer了,buffer里面有了数据了,如何显示出来
下面对这三点分开讨论
本文参考了大牛 http://blog.youkuaiyun.com/gzzaigcn/article/category/2135451 的一些分析。
在此文章基础上做了扩展。感谢前人的肩膀。
一,如何申请显示output buffer,以及如何设置给OMX来使用
1.来看解码输出缓存在surfaceflinger下的缓存申请:
2.allocateOutputBuffersFromNativeWindow的实现
SurfaceFlinger架构下的Buffer申请机制可以看前面提到的博文,
先贴代码,已经去除一些细枝末节的代码:
这两大模块之间联系最大的地方,就是surfaceflinger 管理显示buffer,然后stagefright 如何用这个buffer
这里总结一下这一块自己学习的知识点
平台samsung exynos ,android 4.4
实际上本文想研究的就是三个问题:
(1)如何获取显示buffer,并且怎么把它告诉给OMX
(2)解码的时候,OMX如何把这个buffer告诉给解码器,作为视频数据输出的buffer
(3)有了buffer了,buffer里面有了数据了,如何显示出来
下面对这三点分开讨论
本文参考了大牛 http://blog.youkuaiyun.com/gzzaigcn/article/category/2135451 的一些分析。
在此文章基础上做了扩展。感谢前人的肩膀。
一,如何申请显示output buffer,以及如何设置给OMX来使用
1.来看解码输出缓存在surfaceflinger下的缓存申请:
status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) {
if (mNativeWindow != NULL && portIndex == kPortIndexOutput)
{
return allocateOutputBuffersFromNativeWindow();//使用surface渲染,为输出分配图形缓存GraphicBuffer
}
可以看到当申请的是NativeWindow形式的buffer,这说明了输出的buffer是需要去直接完成render的,所以输出缓存区要从本地窗口buffer进行申请:
2.allocateOutputBuffersFromNativeWindow的实现
SurfaceFlinger架构下的Buffer申请机制可以看前面提到的博文,
先贴代码,已经去除一些细枝末节的代码:
status_t OMXCodec::allocateOutputBuffersFromNativeWindow()
{
status_t err = mOMX->getParameter(
mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
if (err != OK) {
CODEC_LOGE("getParameter failed: %d", err);
return err;
}
err = native_window_set_buffers_geometry(
mNativeWindow.get(),
def.format.video.nFrameWidth,
def.format.video.nFrameHeight,
def.format.video.eColorFormat);
// Set up the native window.
OMX_U32 usage = 0;
err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage);
ALOGV("native_window_set_usage usage=0x%lx", usage);
err = native_window_set_usage(
mNativeWindow.get(), usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP);
if (err != 0) {
ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err);
return err;
}
err = native_window_set_buffer_count(
mNativeWindow.get(), def.nBufferCountActual);
if (err != 0) {
ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
-err);
return err;
}
// Dequeue buffers and send them to OMX
for (OMX_U32 i = 0; i < def.nBufferCountActual; i++) {
ANativeWindowBuffer* buf;
err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf);
if (err != 0) {
ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
break;
}
sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
BufferInfo info;
info.mData = NULL;
info.mSize = def.nBufferSize;
info.mStatus = OWNED_BY_US;
info.mMem = NULL;
info.mMediaBuffer = new MediaBuffer(graphicBuffer);
info.mMediaBuffer->setObserver(this);
mPortBuffers[kPortIndexOutput].push(info);
IOMX::buffer_id bufferId;
err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer,
&bufferId);
if (err != 0) {
CODEC_LOGE("registering GraphicBuffer with OMX IL compo