当前位置: 首页 > news >正文

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

1.主题


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

2.参考


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

3.方法


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

4.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这个参数就包含了这一帧数据的偏移、以及时间戳等信息。

5.使用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

6.使用AAC帧时间计算

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

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

原文地址:解决AAC音频编码时间戳的计算问题 - 资料 - 音视频开发中文网 - 构建全国最权威的音视频技术交流分享论坛

★文末名片可以免费领取音视频开发学习资料,内容包括(FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)以及音视频学习路线图等等。

见下方!↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

http://www.lryc.cn/news/23214.html

相关文章:

  • Android 9.0 添加自定义开机广播
  • 第四阶段10-添加类别,类别列表mapper层,service层,controller层
  • linux内核启动分析(一)
  • wireshark常见使用操作讲解以及几个故障解决案例分享
  • 利用逻辑分析仪解析串口通讯数据
  • 新整理的前端面试题
  • 数据仓库-数仓分层
  • 【Linux】Linux根文件系统扩容
  • RPC编程:Hessian RPC一个老的RPC框架(一)
  • 逆向 x蜂窝 zzzghostsigh
  • QML 鼠标事件
  • 极智项目 | 实战pytorch arcface人脸识别
  • 【IP技术】ipv4和ipv6是什么?
  • linux基本功系列之uniq命令实战
  • 六、SpringBoot项目搭建
  • 【LeetCode】2363. 合并相似的物品
  • 华为OD机试题,用 Java 解【出租车计费】问题
  • 【人脸识别】DDL:数据分布知识蒸馏思想,提升困难样本(遮挡、低分辨率等)识别效果
  • 如何管理好仓库/库房?
  • Unity Lighting -- Unity的光源简介
  • Android仿网易云音乐歌单详情页
  • linux基本功系列之free命令实战
  • 华为OD机试模拟题 用 C++ 实现 - 连续子串(2023.Q1)
  • 【软考——系统架构师】UML 建模与架构文档化
  • Spring中常用注解
  • 基于SpringCloud的可靠消息最终一致性06:轮询事务消息
  • Python Flask + Echarts 轻松制作动态酷炫大屏( 附代码)
  • Wepack(1):SourceMap讲解以及使用
  • 华为OD机试题,用 Java 解【最多等和不相交连续子序列】问题
  • Kubernetes06:Controller