内容简介:音频是流式数据,并不像视频一样有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 复制代码
已知每一帧的持续时间的话,那么只需要根据当前帧数,即可计算出当前的时间戳。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 音频编码 Audio Converter
- php base64 编码图片,音频,视频
- 音视频入门之音频采集、编码、播放
- LameXP v4.16 发布,多用途音频编码器
- PCM 编码与 Waveform 音频文件 (.wav) 格式详解
- PCM 编码与 Waveform 音频文件 (.wav) 格式详解
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Writing Windows VxDs and Device Drivers, Second Edition
Karen Hazzah / CMP / 1996-01-12 / USD 54.95
Software developer and author Karen Hazzah expands her original treatise on device drivers in the second edition of "Writing Windows VxDs and Device Drivers." The book and companion disk include the a......一起来看看 《Writing Windows VxDs and Device Drivers, Second Edition》 这本书的介绍吧!
SHA 加密
SHA 加密工具
UNIX 时间戳转换
UNIX 时间戳转换