• av_init_packet()
  • av_find_best_stream()
  • av_read_frame()/av_pack_unref() ```cpp

    include

    include

    include

void adts_header(char *aac_header, int profile, int sample_rate, int channels, int frame_len) { int sampling_frequency_index = 4; //44100

  1. //sync word
  2. aac_header[0] = 0xff; //syncword:0xfff 高8bits
  3. aac_header[1] = 0xf0; //syncword:0xfff 低4bits
  4. //ID
  5. aac_header[1] |= (0 << 3); //ID : 0 for MPEG-4 ; 1 for MPEG-2
  6. //layer
  7. aac_header[1] |= (0 << 1); //Layer:0 always:00
  8. //protection absent
  9. aac_header[1] |= 1; //protection absent:1 前两个字节的最低位为 1
  10. // also : aac_header[0] = 0xff; aac_header[1] = 0xf1;
  11. //profile
  12. aac_header[2] = (profile) << 6; //profile:profile 2bits
  13. //sampling_frequency_index
  14. aac_header[2] |= (sampling_frequency_index & 0x0f) << 2; //sampling_frequency_index 4bits 只有4bit要 &0x0f,清空高4位
  15. //private_bit
  16. aac_header[2] |= (0 << 1); //private_bit: 0 1bits
  17. //channels
  18. aac_header[2] |= (channels & 0x04) >> 2; //channel 高1bit: &0000 0100取channels的最高位
  19. aac_header[3] |= (channels & 0x03) << 6; //&0000 0011取channels的低2位
  20. aac_header[3] |= (0 << 5); //original:0 1bit
  21. aac_header[3] |= (0 << 4); //home:0 1bit
  22. aac_header[3] |= (0 << 3); //copyright id bit:0 1bit
  23. aac_header[3] |= (0 << 2); //copyright id start:0 1bit
  24. //frame len 一个ADTS帧的长度包括ADTS头和AAC原始流
  25. int adtsLen = frame_len + 7;
  26. aac_header[3] |= ((adtsLen & 0x1800) >> 11); //frame length:value 高2bits
  27. aac_header[4] = (uint8_t)((adtsLen & 0x7f8) >> 3); //frame length:value 中间8bits
  28. aac_header[5] = (uint8_t)((adtsLen & 0x7) << 5); //frame length:value 低3bits
  29. //buffer fullness 0x1FF 说明是码率可变的码流
  30. aac_header[5] |= 0x1f; //buffer fullness:0x1ff 高5bits
  31. aac_header[6] = 0xfc; //111111 00 //buffer fullness:0x1ff 低6bits
  32. //buffer fullness = 1FF, number_of_raw_data_blocks_in_frame = 0, 表示说ADTS帧中有一个AAC数据块
  33. return;

}

int main(int argc, char argv[]) { char src = NULL; char dst = NULL; int ret = -1; int audio_index = -1; int len = 0; AVPacket pkt; AVFormatContext fmt_ctx = NULL;

  1. av_log_set_level(AV_LOG_INFO);
  2. av_register_all();
  3. //1、read two params from console
  4. if (argc < 3) {
  5. av_log(NULL, AV_LOG_ERROR, "the count of params should be more than three!\n");
  6. return -1;
  7. }
  8. src = argv[1];
  9. dst = argv[2];
  10. if (src == NULL || dst == NULL) {
  11. av_log(NULL, AV_LOG_ERROR, "src or dst is null!\n");
  12. return -1;
  13. }
  14. ret = avformat_open_input(&fmt_ctx, src, NULL, NULL);
  15. if (ret < 0) {
  16. av_log(NULL, AV_LOG_ERROR, "Can't open file: %s\n", av_err2str(ret));
  17. return -1;
  18. }
  19. av_dump_format(fmt_ctx, 0, "./test.mp4", 0);
  20. FILE *dst_fd = fopen(dst, "wb");
  21. if (!dst_fd) {
  22. av_log(NULL, AV_LOG_ERROR, "Can't open out file !\n");
  23. avformat_close_input(&fmt_ctx);
  24. return -1;
  25. }
  26. //2、get frame
  27. ret = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0); //第2个参数是获取流的类型;第3个参数是流的索引号,不知道直接写-1;第4个参数是相关的流的索引号,比如音频对应的视频流的索引号,不知道直接写-1;第5个参数是对应的编解码器,不知道直接写NULL
  28. if (ret < 0) {
  29. av_log(NULL, AV_LOG_ERROR, "Can't find the best stream!\n");
  30. avformat_close_input(&fmt_ctx);
  31. fclose(dst_fd);
  32. return -1;
  33. }
  34. audio_index = ret;
  35. av_init_packet(&pkt);
  36. while (av_read_frame(fmt_ctx, &pkt) >= 0) {
  37. if (pkt.stream_index == audio_index) {
  38. //3、write audio data to aac file
  39. char adts_header_buf[7] = {0};
  40. adts_header(adts_header_buf, 2, 44100, 2, pkt.size);
  41. fwrite(adts_header_buf, 1, 7, dst_fd);
  42. len = fwrite(pkt.data, 1, pkt.size, dst_fd);
  43. if (len != pkt.size) {
  44. av_log(NULL, AV_LOG_WARNING, "warning, length of data is not equal size of pkt!\n");
  45. }
  46. }
  47. av_packet_unref(&pkt);
  48. }
  49. av_packet_unref(&pkt);
  50. if (fmt_ctx) {
  51. avformat_close_input(&fmt_ctx);
  52. }
  53. if (dst_fd) {
  54. fclose(dst_fd);
  55. }
  56. return 0;

}

编译: gcc -lavutil -lavformat -lavcodec ``` 注:mp4里的aac数据没有adts,从MP4里抽取的aac数据需要自己添加adts头。