函数OpenmaxMp3AO::ProcessData()

函数OpenmaxMp3AO::ProcessData()是omx中MP3格式的数据处理函数,也就是进行解码的函数,它会调用到类Mp3Decoder中的Mp3DecodeAudio函数来实现解码。函数Mp3DecodeAudio的实现就是调用体层的解码库实现了。也就是软解码库的对外接口。

函数流程:

1)分别从输入端口(port)和输出端口中读取pBufferQueue(buffer队列),并保存为pInputQueue和pOutputQueue,两者类型是QueueType*,关于此类型前面讲过;

2)保存输入输出端口;

3)获取&iOmxComponent,用pHandle保存,其类型是OMX_COMPONENTTYPE*(是OpenMax的标准类型);

(上面三步都是参数的传递,算是数据处理前的准备工作)

4)定义了几个变量;在数据处理时会用到。其中有个变量TempInputBufferSize,其定义如下:

OMX_U32 TempInputBufferSize = (2 * sizeof(uint8) * (ipPorts[OMX_PORT_INPUTPORT_INDEX]->PortParam.nBufferSize));数值为36864

看其字面意思是临时输入buffer的大小,可能是在数据处理时并不是直接对传过来的Inputbuffer进行处理,而是先将Inputbuffer传给一个临时的buffer,对临时的buffer进行处理。

5)判断参数iIsInputBufferEnded(用于判断传递输入buffer是否结束?)和iEndofStream(数据流结束标志)这两个参数但是基础组件类的成员量。在构建OmxComponentBase的时候,两者初始化为:

    iIsInputBufferEnded = OMX_TRUE;
    iEndofStream = OMX_FALSE;

满足条件((!iIsInputBufferEnded) || iEndofStream)才有可能进入解码函数。不满足条件,直接退出函数。

6)判断参数iSilenceInsertionInProgress,为真会调用函数DoSilenceInsertion();(函数作用?在整个MP3解码中没有调用到?)

7)判断参数iNewOutBufRequired是否需要新的输出buffer,如果为真,进入8),

                                                                                     如为假,进入14);

8)首先调用函数GetQueueNumElem检查输出buffer队列是否有可用的输出buffer,GetQueueNumElem(QueueType* aQueue)返回aQueue中的当前元素个数。

若有,进入9);

9)调用函数DeQueue,函数DeQueue(QueueType* aQueue),返回aQueue->pFirst->pData,类型转换为

OMX_BUFFERHEADERTYPE*,保存到ipOutputBuffer,就是获取一个指向输出buffer的指针,并将此输出buffer的参数nFilledLen值初始化为0,还有就是时间戳的设置。

10)判断参数iSendOutBufferAfterPortReconfigFlag,若为假,进入14);

{通常第一次进入解码过程时为假,因为这个变量标志着是否在临时输出buffer(ipTempOutBufferForPortReconfig)中存有已经解码过的数据,其实输出buffer的数据传递模式与输入buffer类似,同样是解码函数后先将解码过得数据存到临时输出buffer中,再在下次进入此函数时将临时输出buffer的数据传递给ipOutputBuffer->pBuffer,这样一次次的积累,指导填满,才会将输出buffer中,不过每次的ipOutputBuffer是不一样的啊}

对ipOutputBuffer重新配置,如果指针ipTempOutBufferForPortReconfig指向内容不为空,而且内容长度不会超出输出buffer分配的空间大小,则调用oscl_memcpy(ipOutputBuffer->pBuffer, ipTempOutBufferForPortReconfig, iSizeOutBufferForPortReconfig)

将ipTempOutBufferForPortReconfig(??,存什么数据?)拷贝长度为iSizeOutBufferForPortReconfig的内容到ipOutputBuffer->pBuffer;同时更新输出buffer中的字节数(nFilledLen),设置ipOutputBuffer->nFilledLen(buffer中元素数,也就是已使用的字节数) = iSizeOutBufferForPortReconfig,并设置iSendOutBufferAfterPortReconfigFlag为假。

12)(ipOutputBuffer->nAllocLen - ipOutputBuffer->nFilledLen) < iOutputFrameLength,判断在ipOutputBuffer中剩余的字节数是否能满足输出frame的要求,前者小说明输出buffer已满,则调用函数ReturnOutputBuffer(ipOutputBuffer, pOutPort)(貌似是将输出buffer返回到输出端口),接着free掉ipTempOutBufferForPortReconfig(这个仅是起一个传递作用,过河拆桥);

13)检查参数iNewOutBufRequired,因为前面可能会调用到函数ReturnOutputBuffer()将剩余空间不足的buffer返回到输出端口了,所以要重新判断,如果仍需要新的buffer,则继续将outbuffer出列使用;

14)将ipOutputBuffer中的剩余的buffer保存到pOutBuffer中;并计算了一个值就是OutputLength,是输出buffer中剩余空间的一半;这两个参数都会作为解码函数的参数;

image

15)检查临时输入buffer(ipTempInputBuffer)中有没有数据,以及临时输入buffer(iTempInputBufferLength)的数据长度和当前输入buffer(iInputCurrLength)的数据长度的和是否小于前面分配的TempInputBufferSize,满足条件则将临时输入buffer中的数据也复制到ipFrameDecodeBuffer;

变量ipFrameDecodeBuffer是基础组件类的成员变量,其类型是OMX_U8*,从类型也可以看出同buffer(ipOutputBuffer和ipInputBuffer)中的pBuffer是同一类型,其实这个变量的作用就是保存输入buffer的pBuffer,作为解码函数的参数;

判断参数iTempInputBufferLength是否大于0以及TempInputBufferSize(本函数前面分配的)是否满足(iInputCurrLength + iTempInputBufferLength) < TempInputBufferSize若满足条件,则将ipFrameDecodeBuffer拷贝到ipTempInputBuffer中

16)调用函数Mp3Decoder::Mp3DecodeAudio,进入解码流程;

17)ResizeNeeded(上面解码函数的一个参数)为假,跳到19);

ResizeNeeded标志是否要重新配置每帧的采样数(iSamplesPerFrame),是对输出端口的AudioPcmMode中的nSamplingRate进行配置;

18)为ipTempOutBufferForPortReconfig分配了一段空间,将pOutBuffer的内容复制到其中,复制长度是OutputLength * 2;调用回调函数;

19)更新输出buffer的nFilledLen,加上OutputLength * 2;

20)DecodeReturn(解码函数的返回值)如果为成功,更新输入buffer的nFilledLen,设置为iInputCurrLength,是当前输入buffer中的数据长度,也就是剩下的没有解码处理的数据,在解码函数中更新,所以两值相减可以计算出此次处理了多少数据;

21)如果返回MP3DEC_INCOMPLETE_FRAME,说明ipFrameDecodeBuffer的数据太少,不够一帧,复制到临时buffer中去,供下次解码使用;

22)返回其他的就是解码出错了;

23)判断ipInputBuffer->nFilledLen,如果为零说明输入buffer已经处理完了,调用函数ReturnInputBuffer(ipInputBuffer, pInPort),返回给输入端口;

24)判断输出buffer中的剩余空间是否能满足一个frame的大小要求,如果不满足,调用函数将输出buffer返回给输出端口;

25)结束

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值