【视音频编程学习】FFmpeg 解码 AAC、PCMa-law、AMRWB、AMRNB

使用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才可以。

    • frameSize = sample_rate / frame_rate (单位:sample)
      • eg: 16000 / (1000ms / 30ms) = 480 samples;
    • Decoder in out:
      • in.setInfo(16000, (AVSampleFormat)AV_SAMPLE_FMT_S16, 1, 30.0);
      • out.setInfo(16000, (AVSampleFormat)AV_SAMPLE_FMT_S16, 1);
  • AMRNB: 有6个字节的文件头"#!AMR\n",每个帧又有一个字节的帧头,在读的时候只需要去掉文件头,后面都是连续的音频数据。

    • frameSize = bit_rate / frame_rate (单位bit)
      • eg: 12200kbit/s / (1000ms / 20ms) = 244bit 约为 31Byte , 加上一个字节的帧头等于32Byte
    • Decoder in out:
      • 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“,同样每个帧有一个帧头,在计算的时候需要将其加上。

    • Decoder in out:
      • in.setInfo(16000, (AVSampleFormat)AV_SAMPLE_FMT_FLT, 1, 23850);
      • out.setInfo(16000, (AVSampleFormat)AV_SAMPLE_FMT_S16, 1);

猜你喜欢

转载自blog.csdn.net/Daibvly/article/details/120972476