解决AAC音频编码时间戳的计算问题

栏目: Android · 发布时间: 5年前

内容简介:音频是流式数据,并不像视频一样有P帧和B帧的概念。就像砌墙一样,咔咔往上摞就行了。一般来说,AAC编码中生成文件这一步,如果使用的是OutputStream流写入文件的话,就完全不需要计算时间。但在音视频同步或者使用Android自带的本文所涉及到的计算方法和API,为在Android环境下。使用AudioRecord音频录制,MediaCodeC编码AAC格式音频,同时使用MediaMuxer封装AAC格式音频文件。AAC编码有两种计算时间戳的方式。第一种:使用PCM的数据量来计算;第二种:计算出AAC编

音频是流式数据,并不像视频一样有P帧和B帧的概念。就像砌墙一样,咔咔往上摞就行了。一般来说,AAC编码中生成文件这一步,如果使用的是OutputStream流写入文件的话,就完全不需要计算时间。但在音视频同步或者使用Android自带的 MediaMuxer 来生成音频文件时,就需要计算音频帧的时间戳。

参考

本文所涉及到的计算方法和API,为在Android环境下。使用AudioRecord音频录制,MediaCodeC编码AAC格式音频,同时使用MediaMuxer封装AAC格式音频文件。

方法

AAC编码有两种计算时间戳的方式。第一种:使用PCM的数据量来计算;第二种:计算出AAC编码相应参数配置下,一帧的持续时间,再配合帧数来计算。

AAC编码、MediaMuxer生成文件伪代码

MediaCodeC的AAC编码流程不再赘述,这里用伪代码来代替。主要是为了体现在代码何处设置时间戳:

// MediaCodeC获得可用输入队列
index = codeC.dequeueInputBuffer(......)
// 当获取到可用输出队列时,我们将获取的PCM数据填入
inputBuffer = codec.getInputBuffer(index)
// 将PCM数据(ByteArray)填充到InputBuffer
inputBuffer.put(byteAarray——PCM数据)
codec.queueInputBuffer(index, 0, byteArray的size
                            , presentationTimeUs, 0)
复制代码

在以上的伪代码中,presentationTimeUs就是需要我们设置时间戳的地方

填充PCM数据后,在得到MediaCodeC输出后,使用MedaMuxer写入数据,生成AAC文件。

path = 输出路径。后缀aac、或者mp4
mediaMuxer= MediaMuxer(path, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4)

mediaMuxer.addTrack(音频轨)
mediaMuxer.start()

// codec拿到可用的输出数据。这些数据就是AAC格式的音频数据
id = codec.dequeueOutputBuffer(bufferInfo, 10000)
if(id >= 0){
    outputBuffer = codec.getOutputBuffer(id)
    mediaMuxer.writeSamplet(audioTrack, outputBuffer, bufferInfo)   
}

复制代码

需要注意的是:使用MediaMuxer生成AAC音频文件时,不需要添加AAC头信息,直接写入即可。

MediaMuxer写入文件时,BufferInfo这个参数就包含了这一帧数据的偏移、以及时间戳等信息。

更加完整的音频编码代码,请参考GitHub地址 AudioEncoder

使用PCM的数据量来计算

PCM是没有经过压缩的纯音频数据,我之前写过一篇音频入门的文章初识音频,记录了一些PCM相关的常识问题,感兴趣的可以去看看。

PCM作为最原始的音频数据,可以根据大小来计算出时间,先给出公式:

presentationTimeUs = 1000000L * (totalBytes / 2) / sampleRate
复制代码

这是配置为采样率sampletRate、采样位数为16bit、单声道的PCM文件时间戳计算方式

接下来我们来分析以上公式的计算由来:

假设有一段PCM文件,采样率为 S ,采样位数为 n --(一般 采样位数的选择有4bit、8bit、16bit、32bit),声道为单声道。那么在1s内,这段PCM的大小为:

size = S * n * 1,单位为bit

复制代码

众所周知, 1 Byte = 8bit , 1 Short = 16bit 。那么单位时间内,PCM的大小为:

以byte为单位 = S * n * 1 / 8
以short为单位  = S * n * 1 / 16

复制代码

那么根据以上就可得到,配置参数为采样率sampleRate、16bit、声道为1的PCM文件,当传入编码器的总大小达到totalByte时,时间戳的计算方式:

currents (微妙) = totalByte / (sampleRate * 16 * 1 / 8)
 = totalByte / 2 / sampleRate * 1000000L 

复制代码

当然如果选择以ShortArray来承载PCM数据的话,那么公式则变为:

currents (微妙) = totalShort / (sampleRate * 16 * 1 / 16)
 = totalShort / sampletRate * 1000000L
复制代码

使用AAC帧时间计算

当编码器每输出一次数据,即可视作输出一帧AAC数据。一帧AAC原始数据包括 1024 个sample,那么AAC音频文件1s内的帧数为: sampleRate / 1024 帧 。从而得到一帧AAC的持续时间为:

perFrameTime (微妙) = 1000000L / sampleRate / 1024

复制代码

已知每一帧的持续时间的话,那么只需要根据当前帧数,即可计算出当前的时间戳。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

激荡十年,水大鱼大

激荡十年,水大鱼大

吴晓波 / 中信出版社 / 2017-11-1 / CNY 58.00

【编辑推荐】 知名财经作者吴晓波新作,畅销十年、销量超过两百万册的《激荡三十年》续篇,至此完成改革开放四十年企业史完整记录。 作为时代记录者,吴晓波有意识地从1978年中国改革开放伊始,记录中国翻天覆地的变化和对我们影响至深的人物与事件,串成一部我们每个人的时代激荡史。而最新的这十年,无疑更壮观,也更扑朔迷离。 很多事情,在当时并未有很深很透的感受,回过头来再看,可能命运的轨迹就......一起来看看 《激荡十年,水大鱼大》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

随机密码生成器
随机密码生成器

多种字符组合密码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器