首先,分别看一下两者的解码流程,相对来说Bellagio的解码流程较为清晰,而OpenCore的较为复杂,难懂,我认为这是因为OpenCore的层次太多,在参数的传递时比较复杂,不能较直观的看到在buffer处理函数中,是对哪个变量操作的,以及这个变量的赋值,初始化在哪个位置等。
解码流程大体是:上层调用相应格式组件的buffer处理函数,此函数再调用底层的解码库中函数实现解码。
1 Bellagio中的解码流程:
Bellagio中buffer处理函数是BufferMgmtCallback,对于每种格式的组件都会实现此函数,以MP3为例:
omx_maddec_component_BufferMgmtCallback():
Ø 参数:
¨ OMX_COMPONENTTYPE *openmaxStandComp;OpenMax的标准类型,指向一个组件
¨ OMX_BUFFERHEADERTYPE* inputbuffer;标准类型,
¨ OMX_BUFFERHEADERTYPE* outputbuffer;
Ø 返回值:无返回值;
Ø 关键量:omx_maddec_component_Private,就是openmaxStandComp->pComponentPrivate
这个私有数据结构是理解解码函数的关键,因为在接下来的操作几乎全是对此私有类型结构的。
Ø 函数流程:
1) 首先是通过传入的参数读取组件私有数据结构:omx_maddec_component_Private = openmaxStandComp->pComponentPrivate,接下来的操作仅是对此私有类型的处理,这个私有类型很关键,属于内部数据不能被Client使用,这也是用户自己实现的部分,其实现不属于OpenMax的标准内容,在Bellagio中使用c写的,但是采用了面向对象的思想,存在一个继承关系;
2) isNewBuffer指示新的buffer的到达,如果一个输入buffer处理完了,需要重新获取一个新的buffer则需要将此参数值设为1,反之,为0,need_mad_stream指示是否需要新的mad stream,就是是否需要从输入输入buffer中获取数据到临时buffer;
3) 这个私有类型有个成员为temporary_buffer,在组件初始化时,为其分配了一个OMX_BUFFERHEADERTYPE类型空间。
如果isNewBuffer和need_mad_stream的值都不为1,说明不需要更新buffer和数据,直接进入解码环节,进入11);
4) tocopy是MAD_BUFFER_MDLEN(mad.h里定义的),inputbuffer->nFilledLen(输入buffer中的字节数),MAD_BUFFER_MDLEN * 3 - temporary_buffer->nFilledLen,三者的最小值;
注意:结构体OMX_BUFFERHEADERTYPE中的几个成员的意义:
Ø OMX_U8* pBuffer; 指向buffer中的数据块;
Ø OMX_U32 nAllocLen; 此buffer分配的大小,即buffer得最大容量;
Ø OMX_U32 nFilledLen;当前buffer中保存的数据大小;
Ø OMX_U32 nOffset;已经处理的数据的大小,对于输入buffer也就是已经解码了的数据大小;
5) 如果need_mad_stream数值不为1,说明不需要更新临时buffer中的数据,跳到10);
6) 参数temp_input_buffer也是私有类型的成员,在组件初始化时将其保存temporary_buffer->pBuffer的值;
7)memmove将temporary_buffer->pBuffer复制到temp_input_buffer,长度为temporary_buffer->nFilledLen;复制完成后又将temp_input_buffer赋给temporary_buffer->pBuffer,将need_mad_stream值设为0;
在此temp_input_buffer相当于一个中转站,memmove,是转移,原先的不保留。
8)又调用memcpy:(复制,原先的还是要保留的)
memcpy(temporary_buffer->pBuffer+temporary_buffer->nFilledLen,inputbuffer->pBuffer + inputbuffer->nOffs