此函数是bellagio中mad组件的MP3解码函数。其参数是:
OMX_COMPONENTTYPE *openmaxStandComp,指向OpenMax的标准类型;
OMX_BUFFERHEADERTYPE* inputbuffer, 输入huffer,包含要解码的MP3数据;
OMX_BUFFERHEADERTYPE* outputbuffer,输出buffer,包含pcm内容。
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,则进入12);
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,跳到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->nOffset, tocopy)
完成复制后要接着更新temporary_buffer->nFilledLen的数值加上tocopy;
inputbuffer->nFilledLen -= tocopy;也将输入buffer中数据长度更新。 现存的减少,
inputbuffer->nOffset += tocopy;已经处理的增加。
9)isNewBuffer设置为0;
调用mad的函数mad_stream_buffer,无返回值,此函数的参数:
stream指向mad.h的结构体mad_stream;
temporary_buffer->pBuffer,临时buffer中的存储数据的buffer指针;
temporary_buffer->nFilledLen,长度。
这个函数是将temporary_buffer->pBuffer的数据保存到mad_stream中,供后面的解码处理(?觉得是这样,具体以后再看)
10) 如果inputbuffer->nFilledLen为0,说明当前输入buffer已经处理完了,下次需要新的输入buffer,将isNewBuffer设置为1;inputbuffer->nOffset置为0;
11) 调用mad_header_decode,解码头,返回值类型是int,属于libmad中的API函数,
参数:
&(frame->header):header(mad_header)的地址;
stream:指向mad_stream的指针。如果返回出错则调用相应的错误处理函数mad_stream_errorstr
12) 调用mad_frame_decode,返回值类型是int,解码mad_stream中的数据,属于libmad中的API函数;
参数:
frame和stream,想要移植libmad,必须实现这两个并正确配置参数;
13) 如果没出错(返回值不为-1),跳到14),错误类型是在libmad中定义的:
13.1
如果错误代码是MAD_ERROR_BUFLEN,说明输入的buffer太小,
A:判断temporary_buffer->pBuffer和stream->next_frame是否相等,如果相等,将need_mad_stream置为1,函数返回(return);
B:如果不相等,检查consumed的值(stream->next_frame-temporary_buffer->pBuffer),(怎么理解consumed?目前是已经解码的字节数)并更新数目,函数返回(return);
13.2
如果错误代码是MAD_ERROR_LOSTSYNC,说明同步丢失了,
调用函数id3_tag_query(stream->this_frame, stream->bufend - stream->this_frame),返回tagsize(signed long);
再调用mad_stream_skip(stream, tagsize)貌似是跳过擦长度为tagsize部分啊
14) 获取nsamples(采样率)和nchannels(声道),并判断是否与私有类型中的pAudioMp3和pAudioPcmMode对应值是否相等,如果不等,则更新pAudioMp3和pAudioPcmMode中的对应值;
15) mad_synth_frame,libmad的API函数,函数参数是:
Ø synth
Ø frame
此函数是将解码后的音频数据合成为PCM采样;
16) 根据声道数,对输出buffer进行赋值;
17) 计算解码的字节数,并更新临时buffer中的长度量,函数结束。