使用ffmpeg的解码器对多种类型的编码进行解码为pcm,分析各种类型写入decoder之前的数据,如何获取该类型的一个帧。
AAC:aac文件的每一个帧有一个adts头,需要对其进行解析,获得每个aac frame的大小frameSize,再每一次进行读文件时,读取frameSize大小的数据作为aac的一个帧内容。adtsheader的大小为7个字节。
adts_header_t *adts = (adts_header_t *) aac_frame;
if (adts->syncword_0_to_8 != 0xff ||
adts->syncword_9_to_12 != 0xf) {
W_LOG("demux adts fail, adts header wrong!");
break;
}
int aac_frame_size = adts->frame_length_0_to_1 << 11 |
adts->frame_length_2_to_9 << 3 |
adts->frame_length_10_to_12;
Decoder in out:
in.setInfo(32000, (AVSampleFormat)AV_SAMPLE_FMT_FLTP, 1);
out.*setInfo*(16000, (AVSampleFormat)AV_SAMPLE_FMT_S16, 1);
PCMA: 在PCMA编解码中有一个pcmaTimeSeg,这个相当于pcma的取包间隔。需要进行手动设置,同时在读文件的时候设置chrono的毫秒间隔略大于pcmaTimeSeg,这个原因还不清楚,如果等于pcmaTimeSeg会出现BufferOverFlow的情况。同时读取的大小也要略大于frameSize才可以。
in.setInfo(16000, (AVSampleFormat)AV_SAMPLE_FMT_S16, 1, 30.0);
out.setInfo(16000, (AVSampleFormat)AV_SAMPLE_FMT_S16, 1);
AMRNB: 有6个字节的文件头"#!AMR\n",每个帧又有一个字节的帧头,在读的时候只需要去掉文件头,后面都是连续的音频数据。
in.setInfo(8000, (AVSampleFormat)AV_SAMPLE_FMT_FLT, 1, 12200);
out.setInfo(8000, (AVSampleFormat)AV_SAMPLE_FMT_S16, 1, 12200);
AMRWB: 与AMRNB有很多相似的地方,它的文件头为9个字节的”#!AMR-WB\n“,同样每个帧有一个帧头,在计算的时候需要将其加上。
in.setInfo(16000, (AVSampleFormat)AV_SAMPLE_FMT_FLT, 1, 23850);
out.setInfo(16000, (AVSampleFormat)AV_SAMPLE_FMT_S16, 1);