avcodec_send_frame偶尔会报错: Input contains (near) NaN/+-Inf
来源:8-7 AAC编码器编码1

邓丹俊
2024-12-18
用的是ffmpeg自身的AAC编码器,因为在windows下数据量比较大,所以用了avaduiofifo中转,但是在塞数据给avcodec_send_frame时偶尔会报错
Input contains (near) NaN/±Inf,看了网上的资料说
但是代码里已经设置了,代码如下,有什么办法可以检查AVFrame里面的数据是否异常呢?
extern “C”
{
#define __STDC_CONSTANT_MACROS 1
#include “libavutil/avutil.h”
#include “libavdevice/avdevice.h”
#include “libavformat/avformat.h”
#include “libavcodec/avcodec.h”
#include “libswresample/swresample.h”
#include “libavutil/audio_fifo.h”
}
#include
#include
#include
using std::copy;
using std::ofstream;
using std::cout;
int main()
{
int ret{}, count{}, fCount{};;
char err[1024];
ofstream file;
file = ofstream(“D:/audio.pcm”, std::ios::trunc);
if (!file)
return -1;
file << “”;
file.close();
file = ofstream(“D:/audio.pcm”, std::ios::app);
if (!file)
return -1;
avdevice_register_all();
auto fmt=av_find_input_format("dshow");
AVFormatContext *ps{};
const char *url{ u8"audio=麦克风阵列 (Realtek High Definition Audio)" };
AVDictionary *options{};
ret=avformat_open_input(&ps, url, fmt, &options);
if (ret)
{
av_strerror(ret, err, 1024);
cout << ret << " : " << err << '\n';
}
//打开编码器
const AVCodec *codec=avcodec_find_encoder(AV_CODEC_ID_AAC);
if (!codec)
cout << "avcodec_find_encoder null\n";
//打开编码器上下文
AVCodecContext *codec_ctx=avcodec_alloc_context3(codec);
if(!codec_ctx)
cout << "avcodec_alloc_context3 null\n";
codec_ctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
codec_ctx->sample_rate = 44100;
codec_ctx->ch_layout = AV_CHANNEL_LAYOUT_STEREO;
//打开编码器
ret=avcodec_open2(codec_ctx, codec, nullptr);
if (ret)
{
av_strerror(ret, err, 1024);
cout << ret << " : " << err << '\n';
}
//音频输入数据
AVFrame *frame = av_frame_alloc();
if (!frame)
{
cout << "frame is nullptr\n";
return -1;
}
frame->nb_samples = 11025; //单通道一个音频帧的采样数
frame->format = AV_SAMPLE_FMT_FLTP; //每个采样的大小
frame->ch_layout = AV_CHANNEL_LAYOUT_STEREO; //channel layout
ret = av_frame_get_buffer(frame, 0);
if (ret || !frame->buf[0])
{
av_strerror(ret, err, 1024);
cout << ret << " : " << err << '\n';
}
AVFrame *frame1024 = av_frame_alloc();
if (!frame1024)
{
cout << "frame is nullptr\n";
return -1;
}
frame1024->nb_samples = 1024; //单通道一个音频帧的采样数
frame1024->format = AV_SAMPLE_FMT_FLTP; //每个采样的大小
frame1024->ch_layout = AV_CHANNEL_LAYOUT_STEREO; //channel layout
ret = av_frame_get_buffer(frame1024, 0);
if (ret || !frame1024->buf[0])
{
av_strerror(ret, err, 1024);
cout << ret << " : " << err << '\n';
}
auto fifo = av_audio_fifo_alloc(AV_SAMPLE_FMT_FLTP, 2, 20000);
if (!fifo)
{
cout << "av_audio_fifo_alloc fail\n";
return -1;
}
// 11025 *2 *2=2048
AVPacket *newpkt = av_packet_alloc();
if (!newpkt)
{
cout << "av_packet_alloc nullptr\n";
return -1;
}
SwrContext *swr{};
const AVChannelLayout out_ch_layout = AV_CHANNEL_LAYOUT_STEREO;
enum AVSampleFormat out_sample_fmt = AV_SAMPLE_FMT_FLTP;
int out_sample_rate = 44100;
const AVChannelLayout in_ch_layout = AV_CHANNEL_LAYOUT_STEREO;
enum AVSampleFormat in_sample_fmt = AV_SAMPLE_FMT_S32;
int in_sample_rate = 44100;
ret = swr_alloc_set_opts2(&swr, &out_ch_layout, out_sample_fmt, out_sample_rate,
&in_ch_layout, in_sample_fmt, in_sample_rate, 0, nullptr);
if (ret)
{
av_strerror(ret, err, 1024);
cout << ret << " : " << err << '\n';
}
ret=swr_init(swr);
if (ret)
{
av_strerror(ret, err, 1024);
cout << ret << " : " << err << '\n';
}
uint8_t **src{};
int srcLen{};
//4096/4/2=512
//88200/4/2
av_samples_alloc_array_and_samples(&src, &srcLen, 2, 11025, AV_SAMPLE_FMT_S32, 0);
uint8_t **dst{};
int dstLen{};
av_samples_alloc_array_and_samples(&dst, &dstLen, 2, 11025, AV_SAMPLE_FMT_FLTP, 0);
AVPacket *pkt;
pkt = av_packet_alloc();
if (!pkt)
{
cout << "av_packet_alloc nullptr\n";
return -1;
}
while (1)
{
ret = av_read_frame(ps, pkt);
if (!ret &&++count != 20)
{
copy(pkt->data, pkt->data + pkt->size, src[0]);
ret = swr_convert(swr, dst, 11025, src, 11025);
if (ret < 0)
{
av_strerror(ret, err, 1024);
cout << ret << " : " << err << '\n';
}
else
{
copy(dst[0], dst[0] + dstLen, frame->data[0]);
ret = av_audio_fifo_write(fifo, (void**)frame->data, 11025);
if (ret > 0)
fCount += ret;
while (fCount > 1024)
{
ret = av_audio_fifo_read(fifo, (void**)frame1024->data, 1024);
if (ret > 0)
fCount -= ret;
ret = avcodec_send_frame(codec_ctx, frame1024);
if (ret < 0)
{
av_strerror(ret, err, 1024);
cout << "avcodec_send_frame: " << ret << " : " << err << '\n';
}
while (ret >= 0)
{
ret = avcodec_receive_packet(codec_ctx, newpkt);
if (ret < 0)
break;
file.write(reinterpret_cast<char*>(newpkt->data), newpkt->size);
}
}
}
}
av_packet_unref(pkt);
if (count == 20)
break;
}
av_audio_fifo_free(fifo);
if (src)
av_freep(&src[0]);
av_freep(&src);
if (dst)
av_freep(&dst[0]);
av_freep(&dst);
av_frame_free(&frame);
av_frame_free(&frame1024);
av_packet_free(&newpkt);
av_packet_free(&pkt);
file.close();
avformat_close_input(&ps);
av_log_set_level(AV_LOG_DEBUG);
av_log(nullptr, AV_LOG_DEBUG, "Hello World\n");
return 0;
}
1回答
-
如果你用系统默认的AAC,那编码器需要f32类型的数据,它与fdk_AAC 编码器的参数是不一样的,你需要查看一下默认AAC编码器的编码参数,如果你采集的数据与它的规格不一致,你需要使用convert 把你的原始音频数据转成它需要的规格
00
相似问题