const std::string res_dir = "./x64/Debug/";const std::string input_file = res_dir + "input_8k16bits.pcm";const std::string output_file = res_dir + "test.aac";
int AudioEncoder::Run(){
int ret = 0; // 创建编码器 const AVCodec* codec; codec = avcodec_find_encoder(AV_CODEC_ID_AAC); if (!codec) { fprintf(stderr, "avcodec_find_encoder failed\n"); return -1; }
// 配置编码器上下文 AVCodecContext* ac = NULL; ac = avcodec_alloc_context3(codec); if (!ac) { fprintf(stderr, "avcodec_alloc_context3 failed\n"); return -1; }
// 设置采样率 ac->sample_rate = 64000; ac->channels = 2; ac->sample_fmt = AVSampleFormat::AV_SAMPLE_FMT_FLTP; ac->bit_rate = 64000; // 设置声道类型 ac->channel_layout = AV_CH_LAYOUT_STEREO;
if (!check_sample_fmt(codec, ac->sample_fmt)) { fprintf(stderr, "Encoder does not support sample format %s", av_get_sample_fmt_name(ac->sample_fmt)); return -1; } // 打开编码器 ret = avcodec_open2(ac, codec, NULL); if (ret != 0) { fprintf(stderr, "avcodec_open2 failed"); return -1; }
// 打开pcm 文件 FILE* fp = fopen(input_file.c_str(),"rb"); if (!fp) { fprintf(stderr, "fopen failed"); return -1; }
//创建接收pcm 数据的帧,并设置参数 AVFrame* frame = av_frame_alloc(); if (!frame) { fprintf(stderr, "av_frame_alloc failed"); return -1; } frame->format = ac->sample_fmt; frame->channels = 2; frame->channel_layout = ac->channel_layout; frame->nb_samples = ac->frame_size;
//为frame 分配空间 ret = av_frame_get_buffer(frame, 0); if (ret < 0) { fprintf(stderr, "av_frame_get_buffer failed\n"); return -1; }
// 创建接收编码码数据的packet AVPacket* pkt = av_packet_alloc(); if (!pkt) { fprintf(stderr, "av_packet_alloc failed"); return -1; } int read_size = frame->nb_samples * 2; char* pcms = new char[read_size];
// 创建重采样上下文 SwrContext* swr_ctx = NULL; swr_ctx = swr_alloc(); if (!swr_ctx) { fprintf(stderr, "swr_alloc failed\n"); return -1; } // 设置重采样上下文输出参数 av_opt_set_int(swr_ctx, "out_channel_layout", ac->channel_layout, 0); av_opt_set_int(swr_ctx, "out_sample_rate", ac->sample_rate, 0); av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", ac->sample_fmt, 0);
// 设置重采样上下文输入参数 av_opt_set_int(swr_ctx, "in_channel_layout", AV_CH_LAYOUT_MONO, 0); av_opt_set_int(swr_ctx, "in_sample_rate", 8000, 0); av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
// 初始化重采样上下文 if ((ret = swr_init(swr_ctx)) < 0) { fprintf(stderr, "Failed to initialize the resampling context\n"); return -1; }
// 创建AVFormatContext,并设置参数 AVFormatContext* oc = NULL; //初始化输出码流的 AVFormatContext avformat_alloc_output_context2(&oc, NULL, NULL, output_file.c_str()); if (!oc) { fprintf(stderr, "avformat_alloc_output_context2 failed\n"); return -1; }
//创建AVStream,并与AVFormatContext 进行关联 AVStream* st = avformat_new_stream(oc, NULL); st->codecpar->codec_tag = 0; avcodec_parameters_from_context(st->codecpar, ac); av_dump_format(oc, 0, output_file.c_str(), 1); ret = avio_open(&oc->pb, output_file.c_str(), AVIO_FLAG_WRITE); if (ret < 0) { fprintf(stderr, "avio_open failed\n"); return -1; }
avformat_write_header(oc, NULL); for (;;) { size_t len = fread(pcms, 1, read_size, fp); if (len < 0) break;
// 重采样pcm 数据 const uint8_t* data[1]; data[0] = (uint8_t*)pcms; ret = swr_convert(swr_ctx, frame->data, frame->nb_samples, (const uint8_t**)data, frame->nb_samples); if (ret < 0) { fprintf(stderr, "swr_convert failed\n"); return -1; }
// 编码并写入文件 Encoder(ac, frame, pkt,oc); }
// 释放资源 delete[] pcms; av_write_trailer(oc); avio_close(oc->pb); avcodec_close(ac); avcodec_free_context(&ac); avformat_free_context(oc); return 0;}
bool AudioEncoder::check_sample_fmt(const AVCodec* codec, enum AVSampleFormat sample_fmt){ const enum AVSampleFormat* p = codec->sample_fmts; while (*p != AV_SAMPLE_FMT_NONE) { if (*p == sample_fmt) return 1; p++; } return 0;}
void AudioEncoder::Encoder(AVCodecContext* ctx, AVFrame* frame, AVPacket* pkt, AVFormatContext* oc){ int ret; // 开始编码 ret = avcodec_send_frame(ctx, frame); if (ret < 0) { fprintf(stderr, "Error sending the frame to the encoder\n"); exit(1); }
// 接收编码出的数据 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); }
// 写入aac 文件 pkt->stream_index = 0; // 表示音频流 av_interleaved_write_frame(oc, pkt); av_packet_unref(pkt); }}
评论