ffmpeg 教程学习笔记 音频播放不正常问题
文章目录
前言
最近在学习 ffmpeg 官网例程,例程3之后的播放音频部分总是有问题,表现为:代码可以编译通过,但播放时音频都是杂音,隐隐约约能够听出旋律(我哭了。。。)。
经过多方查找终于找到了原因 ------- 没有进行音频重采样!
一、开发环境
ffmpeg 4.1 + sdl 1.2.15 + vs2015
二、修改过程
1.导入头文件
因为是要进行重采样,所以要将相应的头文件包含进来。
#include <libswresample/swresample.h>
2.定义一个全局变量,用于存储重采样的标准(属性)
AVFrame wanted_frame;
3.在设置完 wanted_spec 的属性参数并打开音频文件之后,为上面我们所新定义的采样标准初始化。
wanted_frame.format = AV_SAMPLE_FMT_S16;
wanted_frame.sample_rate = spec.freq;
wanted_frame.channel_layout = av_get_default_channel_layout(spec.channels);
wanted_frame.channels = spec.channels;
4.修改官方例程中的解码函数 audio_decode_frame()
int audio_decode_frame(AVCodecContext *aCodecCtx, uint8_t *audio_buf, int buf_size) {
static AVPacket pkt;
static uint8_t *audio_pkt_data = NULL;
static int audio_pkt_size = 0;
static AVFrame frame;
int len1, data_size = 0;
SwrContext* swr_ctx = nullptr;
for (;;) {
while (audio_pkt_size > 0) {
int got_frame = 0;
len1 = avcodec_decode_audio4(aCodecCtx, &frame, &got_frame, &pkt);
if (len1 < 0) {
/* if error, skip frame */
audio_pkt_size = 0;
break;
}
audio_pkt_data += len1;
audio_pkt_size -= len1;
data_size = 0;
if (got_frame) {
data_size = av_samples_get_buffer_size(NULL,
aCodecCtx->channels,
frame.nb_samples,
aCodecCtx->sample_fmt,
1);
assert(data_size <= buf_size);
memcpy(audio_buf, frame.data[0], data_size);
}
/*****************************这里开始是新添加的重采样相关代码**************************************/
if (frame.channels > 0 && frame.channel_layout == 0)
frame.channel_layout = av_get_default_channel_layout(frame.channels);
else if (frame.channels == 0 && frame.channel_layout > 0)
frame.channels = av_get_channel_layout_nb_channels(frame.channel_layout);
if (swr_ctx)
{
swr_free(&swr_ctx);
swr_ctx = nullptr;
}
swr_ctx = swr_alloc_set_opts(nullptr, wanted_frame.channel_layout, (AVSampleFormat)wanted_frame.format, wanted_frame.sample_rate,
frame.channel_layout, (AVSampleFormat)frame.format, frame.sample_rate, 0, nullptr);
if (!swr_ctx || swr_init(swr_ctx) < 0)
{
cout << "swr_init failed:" << endl;
break;
}
int dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_ctx, frame.sample_rate) + frame.nb_samples,
wanted_frame.sample_rate, wanted_frame.format, AVRounding(1));
int len2 = swr_convert(swr_ctx, &audio_buf, dst_nb_samples,
(const uint8_t**)frame.data, frame.nb_samples);
if (len2 < 0)
{
cout << "swr_convert failed\n";
break;
}
return wanted_frame.channels * len2 * av_get_bytes_per_sample((AVSampleFormat)wanted_frame.format);
/******************************新加的代码至此结束*****************************/
if (data_size <= 0) {
/* No data yet, get more frames */
continue;
}
/* We have data, return it and come back for more later */
return data_size;
}
if (pkt.data)
av_free_packet(&pkt);
if (global_video_state->quit) {
return -1;
}
if (packet_queue_get(&global_video_state->audioq, &pkt, 1) < 0) {
return -1;
}
audio_pkt_data = pkt.data;
audio_pkt_size = pkt.size;
}
}
好啦,这样就算是改完啦。我这里改完之后音频播放就已经正常了。
对了,做好在 main 函数前加一个
#undef main
来解决sdl中也有 main 函数从而导致编译不过的问题。(都是踩过的坑啊,,,眼泪不争气的流了下来)
总结
以上就是关于ffmpeg官方教程中音频播放不正常的解决方法。当然了,这个是在我这边的环境下通过的代码,希望对各位迷路的小伙伴有帮助吧。
新手上路,水平有限。若是本文有什么不妥之处还望各位大牛不吝指出,共同交流,本人在此先谢过啦。
参考资料
https://www.cnblogs.com/wangguchangqing/p/5788805.html
来源:oschina
链接:https://my.oschina.net/u/4394698/blog/4898386