ffmpeg音频编码学习std::vector<uint8_t> convert_pcm_to_alaw(uint8_t *pcm_data, int pcm_size, int input_sample_rate,
AVSampleFormat input_fmt,
const AVChannelLayout &input_ch_layout) {
std::vector<uint8_t> audio_data;
//-----------------------------
// 1. 初始化编码器(G.711 A-law)
//-----------------------------
const AVCodec *enc_codec = avcodec_find_encoder(AV_CODEC_ID_PCM_ALAW);
AVCodecContext *enc_ctx = avcodec_alloc_context3(enc_codec);
enc_ctx->sample_rate = 8000; // 目标采样率
enc_ctx->sample_fmt = AV_SAMPLE_FMT_S16; // 编码器支持的输入格式
av_channel_layout_copy(&enc_ctx->ch_layout, &AV_CHANNEL_LAYOUT_MONO); // 单声道
avcodec_open2(enc_ctx, enc_codec, nullptr);
//-----------------------------
// 2. 初始化重采样器(SwrContext)
//-----------------------------
SwrContext *swr = swr_alloc();
av_opt_set_chlayout(swr, "in_chlayout", &input_ch_layout, 0);
av_opt_set_int(swr, "in_sample_rate", input_sample_rate, 0);
av_opt_set_sample_fmt(swr, "in_sample_fmt", input_fmt, 0);
av_opt_set_chlayout(swr, "out_chlayout", &enc_ctx->ch_layout, 0);
av_opt_set_int(swr, "out_sample_rate", enc_ctx->sample_rate, 0);
av_opt_set_sample_fmt(swr, "out_sample_fmt", enc_ctx->sample_fmt, 0);
swr_init(swr);
//-----------------------------
// 3. 将输入的PCM数据封装到AVFrame
//-----------------------------
AVFrame *input_frame = av_frame_alloc(); // 更名:避免"解码"歧义
input_frame->format = input_fmt;
av_channel_layout_copy(&input_frame->ch_layout, &input_ch_layout);
input_frame->nb_samples =
pcm_size / (av_get_bytes_per_sample(input_fmt) * input_ch_layout.nb_channels);
av_frame_get_buffer(input_frame, 0);
memcpy(input_frame->data[0], pcm_data, pcm_size);
//-----------------------------
// 4. 重采样到目标格式(8kHz单声道S16)
//-----------------------------
AVFrame *resampled_frame = av_frame_alloc();
resampled_frame->nb_samples = swr_get_out_samples(swr, input_frame->nb_samples);
resampled_frame->format = enc_ctx->sample_fmt;
av_channel_layout_copy(&resampled_frame->ch_layout, &enc_ctx->ch_layout);
av_frame_get_buffer(resampled_frame, 0);
swr_convert(swr, resampled_frame->data, resampled_frame->nb_samples,
(const uint8_t **)input_frame->data, input_frame->nb_samples);
//-----------------------------
// 5. 编码为G.711 A-law
//-----------------------------
AVPacket *enc_pkt = av_packet_alloc();
avcodec_send_frame(enc_ctx, resampled_frame);
while (avcodec_receive_packet(enc_ctx, enc_pkt) >= 0) {
audio_data.insert(audio_data.end(), enc_pkt->data, enc_pkt->data + enc_pkt->size);
av_packet_unref(enc_pkt);
}
//-----------------------------
// 6. 释放资源
//-----------------------------
av_frame_free(&input_frame);
av_frame_free(&resampled_frame);
av_packet_free(&enc_pkt);
avcodec_free_context(&enc_ctx);
swr_free(&swr);
return audio_data;
}
这段代码有啥问题吗?
最新发布