gpt4 book ai didi

c++ - 为什么 mp3 解码的输出听起来如此延迟?(使用 ffmpeg mp3lame lib)

转载 作者:行者123 更新时间:2023-12-04 23:17:02 25 4
gpt4 key购买 nike

我正在使用 ffmpeg lib 录制声音并编码为 mp3。然后立即解码mp3数据,播放解码数据,但听起来很延迟。
以下是代码:
函数 encode 第一个参数接受原始 pcm 数据,len = 44100。

编码参数:

cntx_->channels = 1;
cntx_->sample_rate = 44100;
cntx_->sample_fmt = 6;
cntx_->channel_layout = AV_CH_LAYOUT_MONO;
cntx_->bit_rate = 8000;
err_ = avcodec_open2(cntx_, codec_, NULL);

vector<unsigned char> encode(unsigned char* encode_data, unsigned int len)
{
vector<unsigned char> ret;
AVPacket avpkt;
av_init_packet(&avpkt);

unsigned int len_encoded = 0;
int data_left = len / 2;
int miss_c = 0, i = 0;
while (data_left > 0)
{
int sz = data_left > cntx_->frame_size ? cntx_->frame_size : data_left;
mp3_frame_->nb_samples = sz;
mp3_frame_->format = cntx_->sample_fmt;
mp3_frame_->channel_layout = cntx_->channel_layout;

int needed_size = av_samples_get_buffer_size(NULL, 1,
mp3_frame_->nb_samples, cntx_->sample_fmt, 1);

int r = avcodec_fill_audio_frame(mp3_frame_, 1, cntx_->sample_fmt, encode_data + len_encoded, needed_size, 0);

int gotted = -1;

r = avcodec_encode_audio2(cntx_, &avpkt, mp3_frame_, &gotted);
if (gotted){
i++;
ret.insert(ret.end(), avpkt.data, avpkt.data + avpkt.size);
}
else if (gotted == 0){
miss_c++;
}
len_encoded += needed_size;
data_left -= sz;
av_free_packet(&avpkt);
}
return ret;
}

std::vector<unsigned char> decode(unsigned char* data, unsigned int len)
{
std::vector<unsigned char> ret;

AVPacket avpkt;
av_init_packet(&avpkt);
avpkt.data = data;
avpkt.size = len;

AVFrame* pframe = av_frame_alloc();
while (avpkt.size > 0){
int goted = -1;av_frame_unref(pframe);
int used = avcodec_decode_audio4(cntx_, pframe, &goted, &avpkt);
if (goted){
ret.insert(ret.end(), pframe->data[0], pframe->data[0] + pframe->linesize[0]);
avpkt.data += used;
avpkt.size -= used;
avpkt.dts = avpkt.pts = AV_NOPTS_VALUE;
}
else if (goted == 0){
avpkt.data += used;
avpkt.size -= used;
avpkt.dts = avpkt.pts = AV_NOPTS_VALUE;
}
else if(goted < 0){
break;
}
}
av_frame_free(&pframe);
return ret;
}

假设它是第 100 次调用 encode(data, len),这个“帧”将出现在第 150 次或更晚的 decode 调用中,延迟是 Not Acceptable 。 mp3lame 编码器似乎会保留样本数据以供以后使用,但不是我的愿望。
我不知道出了什么问题。感谢您提供任何信息。

今天我再次调试代码并发布一些细节:

encode:每个pcm样本帧len = 23040,是mp3帧大小的10倍,每次调用encode只输出9帧,这个输出导致decode输出20736个样本,丢失1帧(2304字节),声音很嘈杂.

如果 mp3 或 mp2 编码不适合实时语音传输,我应该选择哪种编码器?

最佳答案

Suppose it's the 100th call to encode(data, len), this "frame" would appear in 150th or later in the decode call, the latency is not acceptable.



了解编解码器的工作原理并相应地调整您的期望。

MP3 是一种有损编解码器。它通过将您的时域 PCM 数据转换为频域来工作。仅这种转换就需要时间(因为频率分量在任何时刻都不存在......它们只能存在于一段时间内)。在一个简单的层面上,它然后使用一些算法来确定要保留哪些光谱信息,以及要丢弃哪些信息。每个 MP3 帧的持续时间都是数百个样本。 (576 是您通常可以达到的最低点。这是典型数字的两倍。)

既然您拥有创建帧的最少时间,MP3 还使用所谓的位储存器。如果一个复杂的 channel 需要更多的带宽,它会从相邻帧借用未使用的带宽。为了促进这一点,需要许多帧的缓冲区。

除了所有编解码器的工作之外,FFmpeg 本身还具有缓冲(用于检测输入和其他内容),并且在与 FFmpeg 之间的管道中有缓冲区。我想编解码器本身也可以在输入和输出上使用一般缓冲。

最后,您正在解码流并播放它,这意味着编码中使用的大多数相同类型的缓冲区现在都用于解码。而且,我们甚至没有谈论通过声卡获取音频数据并将模拟输出到扬声器的数百毫秒延迟。

你有一个不切实际的期望,虽然可以调整一些东西来减少延迟(例如禁用比特储存器),但它会导致质量差的流并且无论如何都不会具有低延迟。

关于c++ - 为什么 mp3 解码的输出听起来如此延迟?(使用 ffmpeg mp3lame lib),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22302067/

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