void adts_header(char *aac_header, int profile, int sample_rate, int channels, int frame_len) { int sampling_frequency_index = 4; //44100
//sync word
aac_header[0] = 0xff; //syncword:0xfff 高8bits
aac_header[1] = 0xf0; //syncword:0xfff 低4bits
//ID
aac_header[1] |= (0 << 3); //ID : 0 for MPEG-4 ; 1 for MPEG-2
//layer
aac_header[1] |= (0 << 1); //Layer:0 always:00
//protection absent
aac_header[1] |= 1; //protection absent:1 前两个字节的最低位为 1
// also : aac_header[0] = 0xff; aac_header[1] = 0xf1;
//profile
aac_header[2] = (profile) << 6; //profile:profile 2bits
//sampling_frequency_index
aac_header[2] |= (sampling_frequency_index & 0x0f) << 2; //sampling_frequency_index 4bits 只有4bit要 &0x0f,清空高4位
//private_bit
aac_header[2] |= (0 << 1); //private_bit: 0 1bits
//channels
aac_header[2] |= (channels & 0x04) >> 2; //channel 高1bit: &0000 0100取channels的最高位
aac_header[3] |= (channels & 0x03) << 6; //&0000 0011取channels的低2位
aac_header[3] |= (0 << 5); //original:0 1bit
aac_header[3] |= (0 << 4); //home:0 1bit
aac_header[3] |= (0 << 3); //copyright id bit:0 1bit
aac_header[3] |= (0 << 2); //copyright id start:0 1bit
//frame len 一个ADTS帧的长度包括ADTS头和AAC原始流
int adtsLen = frame_len + 7;
aac_header[3] |= ((adtsLen & 0x1800) >> 11); //frame length:value 高2bits
aac_header[4] = (uint8_t)((adtsLen & 0x7f8) >> 3); //frame length:value 中间8bits
aac_header[5] = (uint8_t)((adtsLen & 0x7) << 5); //frame length:value 低3bits
//buffer fullness 0x1FF 说明是码率可变的码流
aac_header[5] |= 0x1f; //buffer fullness:0x1ff 高5bits
aac_header[6] = 0xfc; //111111 00 //buffer fullness:0x1ff 低6bits
//buffer fullness = 1FF, number_of_raw_data_blocks_in_frame = 0, 表示说ADTS帧中有一个AAC数据块
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;
av_log_set_level(AV_LOG_INFO);
av_register_all();
//1、read two params from console
if (argc < 3) {
av_log(NULL, AV_LOG_ERROR, "the count of params should be more than three!\n");
return -1;
}
src = argv[1];
dst = argv[2];
if (src == NULL || dst == NULL) {
av_log(NULL, AV_LOG_ERROR, "src or dst is null!\n");
return -1;
}
ret = avformat_open_input(&fmt_ctx, src, NULL, NULL);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Can't open file: %s\n", av_err2str(ret));
return -1;
}
av_dump_format(fmt_ctx, 0, "./test.mp4", 0);
FILE *dst_fd = fopen(dst, "wb");
if (!dst_fd) {
av_log(NULL, AV_LOG_ERROR, "Can't open out file !\n");
avformat_close_input(&fmt_ctx);
return -1;
}
//2、get frame
ret = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0); //第2个参数是获取流的类型;第3个参数是流的索引号,不知道直接写-1;第4个参数是相关的流的索引号,比如音频对应的视频流的索引号,不知道直接写-1;第5个参数是对应的编解码器,不知道直接写NULL
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Can't find the best stream!\n");
avformat_close_input(&fmt_ctx);
fclose(dst_fd);
return -1;
}
audio_index = ret;
av_init_packet(&pkt);
while (av_read_frame(fmt_ctx, &pkt) >= 0) {
if (pkt.stream_index == audio_index) {
//3、write audio data to aac file
char adts_header_buf[7] = {0};
adts_header(adts_header_buf, 2, 44100, 2, pkt.size);
fwrite(adts_header_buf, 1, 7, dst_fd);
len = fwrite(pkt.data, 1, pkt.size, dst_fd);
if (len != pkt.size) {
av_log(NULL, AV_LOG_WARNING, "warning, length of data is not equal size of pkt!\n");
}
}
av_packet_unref(&pkt);
}
av_packet_unref(&pkt);
if (fmt_ctx) {
avformat_close_input(&fmt_ctx);
}
if (dst_fd) {
fclose(dst_fd);
}
return 0;
}
编译: gcc -lavutil -lavformat -lavcodec ``` 注:mp4里的aac数据没有adts,从MP4里抽取的aac数据需要自己添加adts头。