gpt4 book ai didi

c++ - 如何使用最新版本的 ffmpeg 创建立体声 mp3 文件?

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:59:00 25 4
gpt4 key购买 nike

我正在将我的代码从旧版本的 ffmpeg (53) 更新到新版本 (54/55)。有效的代码现在已被弃用或删除,因此我在更新它时遇到问题。

以前我可以使用名为以下的示例格式创建立体声 MP3 文件:

SAMPLE_FMT_S16

这与我的源流完美匹配。现在已替换为

AV_SAMPLE_FMT_S16

这对于单声道录音效果很好,但是当我尝试创建立体声 MP3 文件时,它会在 avcodec_open2 处出现错误:

“不支持指定的 sample_fmt。”

通过反复试验我发现使用

AV_SAMPLE_FMT_S16P

...被 avcodec_open2 接受,但是当我通过并创建 MP3 文件时,声音非常失真 - 听起来比平时低 2 个 Octave ,背景中有巨大的嗡嗡声 - 这是一个示例录音:

http://hosting.ispyconnect.com/example.mp3

ffmpeg 的人告诉我这是因为我现在需要在调用之前手动解交错我的字节流:

avcodec_fill_audio_frame

我该怎么做?我试过使用 swrescale 库但没有成功,我试过手动将 L/R 数据输入 avcodec_fill_audio_frame 但我得到的结果听起来与没有交错时完全一样。

这是我的编码代码:

void add_audio_sample( AudioWriterPrivateData^ data, BYTE* soundBuffer, int soundBufferSize)
{
libffmpeg::AVCodecContext* c = data->AudioStream->codec;
memcpy(data->AudioBuffer + data->AudioBufferSizeCurrent, soundBuffer, soundBufferSize);
data->AudioBufferSizeCurrent += soundBufferSize;
uint8_t* pSoundBuffer = (uint8_t *)data->AudioBuffer;
DWORD nCurrentSize = data->AudioBufferSizeCurrent;

libffmpeg::AVFrame *frame;

int got_packet;
int ret;
int size = libffmpeg::av_samples_get_buffer_size(NULL, c->channels,
data->AudioInputSampleSize,
c->sample_fmt, 1);

while( nCurrentSize >= size) {

frame=libffmpeg::avcodec_alloc_frame();
libffmpeg::avcodec_get_frame_defaults(frame);

frame->nb_samples = data->AudioInputSampleSize;

ret = libffmpeg::avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt, pSoundBuffer, size, 1);
if (ret<0)
{
throw gcnew System::IO::IOException("error filling audio");
}
//audio_pts = (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den;

libffmpeg::AVPacket pkt = { 0 };
libffmpeg::av_init_packet(&pkt);

ret = libffmpeg::avcodec_encode_audio2(c, &pkt, frame, &got_packet);

if (ret<0)
throw gcnew System::IO::IOException("error encoding audio");
if (got_packet) {
pkt.stream_index = data->AudioStream->index;

if (pkt.pts != AV_NOPTS_VALUE)
pkt.pts = libffmpeg::av_rescale_q(pkt.pts, c->time_base, c->time_base);
if (pkt.duration > 0)
pkt.duration = av_rescale_q(pkt.duration, c->time_base, c->time_base);

pkt.flags |= AV_PKT_FLAG_KEY;

if (libffmpeg::av_interleaved_write_frame(data->FormatContext, &pkt) != 0)
throw gcnew System::IO::IOException("unable to write audio frame.");


}
nCurrentSize -= size;
pSoundBuffer += size;
}
memcpy(data->AudioBuffer, data->AudioBuffer + data->AudioBufferSizeCurrent - nCurrentSize, nCurrentSize);
data->AudioBufferSizeCurrent = nCurrentSize;

}

很想听听任何想法 - 我已经尝试让它工作 3 天了:(

最佳答案

如果帧尚未完全编码(例如,got_packet 未设置为 true),您不想增加 pSoundBuffer,因为尚未写入内存。此外,您在每个循环期间分配一个帧:没有必要,您可以重复使用相同的 AVFrame。您的代码也会泄漏,因为您从未释放 AVFrame。

我编写了一个代码作为 MythTV 的一部分,将音频编码为 AC3。这也可以满足您的需求:对内容进行去交错处理。 https://github.com/MythTV/mythtv/blob/476b2a826d43fca5e658ebe787c3cb1ec2334f98/mythtv/libs/libmyth/audio/audiooutputdigitalencoder.cpp#L178

关于c++ - 如何使用最新版本的 ffmpeg 创建立体声 mp3 文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12967730/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com