在音视频变速滤镜代码运行时出现如下错误:
该错误是由于传给mp4的音频编码器时帧内的采样点数量不对引起的(没有浅蓝色字符串的行是自行输出的;采样点数量不对是因为用变速滤镜进行了重采样),mp4中的音频默认用aac编码,而aac编码一帧的采样点为1024,而这里每帧只传入819,因此引发了错误。若要解决,需要将输入的帧修正为1024个采样点的。
解决的方法很多,以我的解决方法为例,将滤镜输出的帧先不输入编码器,而是将帧内采样点放入队列,若队列中的采样点超过1024则生成帧数组,依次输入编码器,没有引起以上错误且变速正常。
#include <vector>
#include <queue>
#include <iostream>
static std::vector<AVFrame*> addSamples(AVFrame *frame)
{
static std::vector<std::queue<int8_t>> channel_samples;
if(channel_samples.size() == 0)
{
channel_samples.insert(channel_samples.end(),
audio_encode_ctx->ch_layout.nb_channels, std::queue<int8_t>());
}
int data_size = av_get_bytes_per_sample(audio_encode_ctx->sample_fmt);
for(int i = 0; i < frame->ch_layout.nb_channels; ++i)
{
for(int j = 0; j < frame->nb_samples; ++j)
{
for(int k = 0; k < data_size; ++k)
{
channel_samples[i].push(frame->data[i][j*data_size+k]);
}
}
}
std::vector<AVFrame*> res;
while(channel_samples[0].size() >= audio_encode_ctx->frame_size * data_size)
{
AVFrame *cur = av_frame_alloc();
cur->nb_samples = audio_encode_ctx->frame_size;//audio_encode_ctx为音频编码器
cur->format = audio_encode_ctx->sample_fmt;
cur->sample_rate = audio_encode_ctx->sample_rate;
cur->ch_layout = frame->ch_layout;
cur->channel_layout = frame->channel_layout;
cur->time_base = frame->time_base;
static int cur_index = -1;
if(av_frame_get_buffer(cur, 0) < 0)
{
std::cerr << "Error: AVFrame could not get buffer.\n";
av_frame_free(&cur);
return res;
}
cur_index++;
// cur->duration = frame->nb_samples*(frame->time_base.den/cur->sample_rate);
cur->pts = cur->nb_samples * cur_index;//设置时间戳,aac帧的pts一般以1024为单位
for(int i = 0; i < cur->ch_layout.nb_channels; ++i)
{
for(int j = 0; j < cur->nb_samples; ++j)
{
for(int k = 0; k < data_size; ++k)
{
cur->data[i][j * data_size + k] = channel_samples[i].front();
channel_samples[i].pop();
}
}
}
res.push_back(cur);
// std::cout << "new frame : " << cur->nb_samples << " samples.\n";
}
return res;
}
上述代码记得在输入编码器后将生成的帧用av_frame_free()释放空间。