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回答

李超

2024-12-18

如果你用系统默认的AAC,那编码器需要f32类型的数据,它与fdk_AAC 编码器的参数是不一样的,你需要查看一下默认AAC编码器的编码参数,如果你采集的数据与它的规格不一致,你需要使用convert 把你的原始音频数据转成它需要的规格

0
0

音视频小白系统入门课 音视频基础+ffmpeg原理

掌握音视频采集、编解码、RTMP传输协议等核心基础

2326 学习 · 813 问题

查看课程