音频解码流程分析

音频解码流程分析

  • OpenSLES初始化 -> 初始化音频引擎 -> 子线程解码原始数据到SafeQueue<AVPacket *>队列中 -> 解码器返回解码到输出数据到SafeQueue<AVFrame *> frame_queue 队列 -> 转换音频 -> 引擎播放

  • 音频的解码流程与视频很相似。都是操作原始数据先到packet线程,再被压到frame队列。不同的是,audio解码后用到的是opensles来播放,因此开启来一个线程来处理初始化工作。

  • opensles的学习可以参考google-sample/sdk的例子:https://github.com/googlesamples/android-ndk/tree/master/native-audio

  • 先来看下opensles初始化的方法:

    • 配置播放pcm格式的数据
    • 设置缓存队列,把解压的数据回调到播放器中播放
    • 貌似没有什么好讲的,可以查看项目代码注释或者查看google官方例子
  • decode解码

    • SafeQueue<AVPacket *> pkt_queue取数据,通过avcodec_send_packet方法解码,此方法再视频解码解释过了。
    • avcodec_receive_frame()获得解码数据,并根据当前frame_queue队列的情况判断是否压入队列。
  • getPcm取frame队列中的数据转换音频,通过转换回调给播放器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/** Convert audio.
*
* in and in_count can be set to 0 to flush the last few samples out at the
* end.
*
* If more input is provided than output space, then the input will be buffered.
* You can avoid this buffering by using swr_get_out_samples() to retrieve an
* upper bound on the required number of output samples for the given number of
* input samples. Conversion will run directly without copying whenever possible.
*
* @param s allocated Swr context, with parameters set
* @param out output buffers, only the first one need be set in case of packed audio
* @param out_count amount of space available for output in samples per channel
* @param in input buffers, only the first one need to be set in case of packed audio
* @param in_count number of input samples available in one channel
*
* @return number of samples output per channel, negative value on error
*/
int swr_convert(struct SwrContext *s, uint8_t **out, int out_count,
const uint8_t **in , int in_count);

项目链接地址: https://github.com/lgq895767507/QuickPlay