ffmpeg aac s16 encode_audio.c

用ffmpeg库时,用代码对pcm内容采用aac编码进行压缩,出现如下错误。

aac @ 000002bc5edc6e40\] Format aac detected only with low score of 1, misdetection possible! \[aac @ 000002bc5edc8140\] Error decoding AAC frame header. \[aac @ 000002bc5edc8140\] More than one AAC RDB per ADTS frame is not implemented. Update your FFmpeg version to the newest one from Git. If the problem still occurs, it means that your file has a feature which has not been implemented. \[aac @ 000002bc5edc8140\] Multiple frames in a packet. \[aac @ 000002bc5edc8140\] Sample rate index in program config element does not match the sample rate index configured by the container. \[aac @ 000002bc5edc8140\] Too large remapped id is not implemented. Update your FFmpeg version to the newest one from Git. If the problem still occurs, it means that your file has a feature which has not been implemented. \[aac @ 000002bc5edc8140\] If you want to help, upload a sample of this file to https://streams.videolan.org/upload/ and contact the ffmpeg-devel mailing list. (ffmpeg-devel@ffmpeg.org) \[aac @ 000002bc5edc8140\] Sample rate index in program config element does not match the sample rate index configured by the container. \[aac @ 000002bc5edc8140\] channel element 1.3 is not allocated \[aac @ 000002bc5edc8140\] SBR was found before the first channel element. \[aac @ 000002bc5edc8140\] channel element 3.6 is not allocated \[aac @ 000002bc5edc8140\] channel element 2.12 is not allocated \[aac @ 000002bc5edc8140\] Assuming an incorrectly encoded 7.1 channel layout instead of a spec-compliant 7.1(wide) layout, use -strict 1 to decode according to the specification instead. \[aac @ 000002bc5edc8140\] channel element 3.12 is not allocated \[aac @ 000002bc5edc6e40\] Packet corrupt (stream = 0, dts = NOPTS). \[aac @ 000002bc5edc8140\] channel element 1.9 is not allocated \[aac @ 000002bc5edc6e40\] Estimating duration from bitrate, this may be inaccurate \[aac @ 000002bc5edc6e40\] Could not find codec parameters for stream 0 (Audio: aac (LTP), 3.0, fltp, 505 kb/s): unspecified sample rate Consider increasing the value for the 'analyzeduration' (0) and 'probesize' (5000000) options ![](https://i-blog.csdnimg.cn/direct/d8e619bee13141de98bbfc2a9ba19fbe.png) 过程分析: 数据源是无压缩的pcm数据(cr:44100, cn=2(stereo) , format:s16 ) 。 同样的内容如果使用命令行进行压缩 ffmpeg -i E:/video/out.pcm -ar 44100 -b 128K -ac 2 -c:a aac_mf E:/video/out1.aac -y 进行压缩,发现能进行播放。 (ffmpeg中的aac不支持s16格式数据,aac_mf才支持,可以用ffmpeg -h encoder=aac 查看) 使用代码进行压缩出现上图右边的错误。测试代码是从**ffmpeg/doc/example/encode_audio.c** 上进行更改的。 没有进入ffmpeg源码进行调试,只能从现有的结果进行分析,发现代码生成的内容大小是没有问题的,但是被ffmpeg错误解析。猜测应该是数据包头解析错误。但是因为之前没有做过aac编码,真是瞎子摸象,一句一句的修改测试,无果。 最后在网上找到一个能运行的demo才解决问题:[FFmpeg简单使用:音频编码 ---- pcm转aac_avframe 音频 aac-CSDN博客](https://blog.csdn.net/huabiaochen/article/details/128455086 "FFmpeg简单使用:音频编码 ---- pcm转aac_avframe 音频 aac-CSDN博客") 最后发现原因是aac编码后的数据包写入文件时需要额外写入数据包头,而demo中的代码太简单,根本没有这个步骤,下面是代码示例: static void get_adts_header(AVCodecContext *ctx, uint8_t *adts_header, int aac_length) { uint8_t freq_idx = 0; //0: 96000 Hz 3: 48000 Hz 4: 44100 Hz switch (ctx->sample_rate) { case 96000: freq_idx = 0; break; case 88200: freq_idx = 1; break; case 64000: freq_idx = 2; break; case 48000: freq_idx = 3; break; case 44100: freq_idx = 4; break; case 32000: freq_idx = 5; break; case 24000: freq_idx = 6; break; case 22050: freq_idx = 7; break; case 16000: freq_idx = 8; break; case 12000: freq_idx = 9; break; case 11025: freq_idx = 10; break; case 8000: freq_idx = 11; break; case 7350: freq_idx = 12; break; default: freq_idx = 4; break; } uint8_t chanCfg = ctx->channels; uint32_t frame_length = aac_length + 7; adts_header[0] = 0xFF; adts_header[1] = 0xF1; adts_header[2] = ((ctx->profile) << 6) + (freq_idx << 2) + (chanCfg >> 2); adts_header[3] = (((chanCfg & 3) << 6) + (frame_length >> 11)); adts_header[4] = ((frame_length & 0x7FF) >> 3); adts_header[5] = (((frame_length & 7) << 5) + 0x1F); adts_header[6] = 0xFC; } static void encode(AVCodecContext *ctx, AVFrame *frame, AVPacket *pkt, FILE *output) { int ret; /* send the frame for encoding */ ret = avcodec_send_frame(ctx, frame); if (ret < 0) { fprintf(stderr, "Error sending the frame to the encoder\n"); exit(1); } /* read all the available output packets (in general there may be any * number of them */ while (ret >= 0) { ret = avcodec_receive_packet(ctx, pkt); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) return; else if (ret < 0) { fprintf(stderr, "Error encoding audio frame\n"); exit(1); } //额外写入包头 uint8_t aac_header[7]; get_adts_header(ctx, aac_header, pkt->size); size_t len = 0; len = fwrite(aac_header, 1, 7, output); if(len != 7) { fprintf(stderr, "fwrite aac_header failed\n"); return -1; } // printf("%d:%d\n",count++,pkt->pts); fwrite(pkt->data, 1, pkt->size, output); //av_packet_unref(pkt); } } int main(int argc, char **argv) { const char *filename; const AVCodec *codec; AVCodecContext *c= NULL; AVFrame *frame; AVPacket *pkt; int i, j, k, ret; FILE *f; uint16_t *samples; float t, tincr; filename="E:/video/out.aac"; /* find the MP2 encoder */ //codec = avcodec_find_encoder(AV_CODEC_ID_MP2); //codec = avcodec_find_encoder(AV_CODEC_ID_AAC); //printf("%s\n",avcodec_get_id( AV_CODEC_ID_AAC_LATM)); codec = avcodec_find_encoder_by_name("aac_mf"); if (!codec) { fprintf(stderr, "Codec not found\n"); exit(1); } c = avcodec_alloc_context3(codec); if (!c) { fprintf(stderr, "Could not allocate audio codec context\n"); exit(1); } /* put sample parameters */ c->bit_rate = 64000; /* check that the encoder supports s16 pcm input */ c->sample_fmt = AV_SAMPLE_FMT_S16; if (!check_sample_fmt(codec, c->sample_fmt)) { fprintf(stderr, "Encoder does not support sample format %s", av_get_sample_fmt_name(c->sample_fmt)); exit(1); } //c->profile = FF_PROFILE_AAC_LOW; c->bit_rate为0,c->profile设置才会有效 /* select other audio parameters supported by the encoder */ c->sample_rate = select_sample_rate(codec); ret = select_channel_layout(codec, &c->ch_layout); if (ret < 0) exit(1); c->channels = c->ch_layout.nb_channels; //sample_rate(cr)=44100,表示1秒钟有44100个采样点。格式为s16 + stereo表示双通道,每通道16位(short) packed格式,(S16P 表示双通道通道16位planar格式) //也就是一个采样点需要4个字节来保存。这里的frame_size 表示采样点个数。 c->frame_size=512;//手动设置frame_size // 声音的timebase设置为采样率或其倍数,因为PTS是int64的。如果timebase刚好等于sample_rate, // 那么更具pts计算公式 audio_pts = n*frame_size*timebase/sample_rate = n*frame_size // 这样对时间的pts设置极为方便。 c->time_base=av_make_q(c->sample_rate,1);//手动设置time_base, /* open it */ if (avcodec_open2(c, codec, NULL) < 0) { fprintf(stderr, "Could not open codec\n"); exit(1); } f = fopen(filename, "wb"); if (!f) { fprintf(stderr, "Could not open %s\n", filename); exit(1); } /* packet for holding encoded output */ pkt = av_packet_alloc(); if (!pkt) { fprintf(stderr, "could not allocate the packet\n"); exit(1); } /* frame containing input raw audio */ frame = av_frame_alloc(); if (!frame) { fprintf(stderr, "Could not allocate audio frame\n"); exit(1); } frame->nb_samples = c->frame_size; frame->format = c->sample_fmt; ret = av_channel_layout_copy(&frame->ch_layout, &c->ch_layout); if (ret < 0) exit(1); frame->channels = c->channels; frame->pts = 0; //初始化pts //音频的packed格式的数据,都存在data[0]中,并且是连续的;stereo planer格式才会将左右两个通道分开在data[0]和data[1]中存放,av_frame_get_buffer会为frame按照参数申请缓存。 //packed :LLRRLLRRLLRRLLRR //planer :LLLLLLLL....RRRRRRRRR.... /* allocate the data buffers */ ret = av_frame_get_buffer(frame, 0); if (ret < 0) { fprintf(stderr, "Could not allocate audio data buffers\n"); exit(1); } /* encode a single tone sound */ t = 0; uint8_t *buffer = malloc(frame->nb_samples*frame->ch_layout.nb_channels*av_get_bytes_per_sample(frame->format)); tincr = 2 * M_PI * 440.0 / c->sample_rate; for (i = 0; i < 200; i++) { /* make sure the frame is writable -- makes a copy if the encoder * kept a reference internally */ ret = av_frame_make_writable(frame); if (ret < 0) exit(1); samples = (uint16_t*)buffer; for (j = 0; j < c->frame_size; j++) { samples[2*j] = (int)(sin(t) * 10000); for (k = 1; k < c->ch_layout.nb_channels; k++) samples[2*j + k] = samples[2*j]; t += tincr; } ret = av_samples_fill_arrays(frame->data, frame->linesize, buffer, frame->channels,frame->nb_samples, frame->format, 0); frame->pts += frame->nb_samples; encode(c, frame, pkt, f); } /* flush the encoder */ encode(c, NULL, pkt, f); free(buffer); fclose(f); av_frame_free(&frame); av_packet_free(&pkt); avcodec_free_context(&c); return 0; } ![](https://i-blog.csdnimg.cn/direct/382ac449aaa34d14b07b15894a28d2e3.png) [7-5ADTS格式_哔哩哔哩_bilibili](https://www.bilibili.com/video/BV1p94y1778H?spm_id_from=333.788.videopod.episodes&vd_source=9e1f9783ae86062970e9bb3cefa72b9d&p=45 "7-5ADTS格式_哔哩哔哩_bilibili") [AAC ADTS格式分析\&AAC编码(adts_header详解)_adts header-CSDN博客](https://blog.csdn.net/qq_34588804/article/details/137744256 "AAC ADTS格式分析&AAC编码(adts_header详解)_adts header-CSDN博客")

相关推荐
阿里巴啦1 天前
python+yt-dlp开源项目,支持 YouTube, Bilibili, TikTok/抖音,快手 等多个平台的视频/音频/字幕下载/ai摘要等功能
python·ffmpeg·whisper·音视频·视频处理·ai摘要·音视频转录
来鸟 鸣间2 天前
linux下ffmpeg源码编译
linux·运维·ffmpeg
Echo_NGC22372 天前
【FFmpeg使用指南】Part 2:滤镜图架构与信号处理
架构·ffmpeg·音视频·信号处理
Echo_NGC22372 天前
【FFmpeg使用指南】Part 1:核心架构与媒体流处理
ffmpeg·音视频·媒体·视频
ssxueyi2 天前
用 Claude Code 从零开发自己的Direct3D 硬件加速播放器
ffmpeg·ai编程·directx·视频播放器·从零开始·claude code·csdn征文活动
Yan_uuu2 天前
ubuntu18.04 安装 x264、ffmpeg、nv-codec-hearers 支持GPU硬件加速
c++·图像处理·ubuntu·ffmpeg
runner365.git3 天前
做一个基于ffmpeg的AI Agent智能体
人工智能·ffmpeg·大模型
彷徨而立3 天前
【FFmpeg】理解 av_packet_from_data 和 av_packet_unref 接口
ffmpeg
runner365.git3 天前
ffmpeg8.0合入whisper,语音识别模型终于进入ffmpeg
ffmpeg·whisper·语音识别
小徐敲java4 天前
视频推流服务器与FFmpeg 安装配置
服务器·ffmpeg·音视频