在windows下录制遇到问题

来源:9-10 实战从视频设备上采集数据2

邓丹俊

2024-12-22

在windows下ffmpeg7.1遇到问题
real-time buffer [Surface Camera Front] [video input] too full or near too full (62% of size: 304128000 [rtbufsize parameter])! frame dropped!

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:/video.yuv”, std::ios::trunc);
if (!file)
return - 1;
file << “”;
file.close();
file = ofstream(“D:/video.yuv”, std::ios::app);
if (!file)
return -1;

avdevice_register_all();

auto fmt = av_find_input_format("dshow");
if (!fmt)
{
	cout << "av_find_input_format fail\n";
	return -1;
}

AVFormatContext *ps{};
const char *url{ u8"video=Surface Camera Front" };
AVDictionary *options{};

ret = av_dict_set(&options, "video_size", "640x480", 0);
if (ret < 0)
{
	av_strerror(ret, err, 1024);
	cout << "av_dict_set: " << ret << " : " << err << '\n';
}
ret = av_dict_set(&options, "framerate", "20", 0);
if (ret < 0)
{
	av_strerror(ret, err, 1024);
	cout << "av_dict_set: " << ret << " : " << err << '\n';
}
ret = av_dict_set(&options, "pix_fmts", "yuv420p", 0);
if (ret < 0)
{
	av_strerror(ret, err, 1024);
	cout << "av_dict_set: " << ret << " : " << err << '\n';
}

ret = avformat_open_input(&ps,url,fmt,&options);
if (ret < 0)
{
	av_strerror(ret, err, 1024);
	cout << "avformat_open_input: " << ret << " : " << err << '\n';
}

/////////////////////////////////////////////////////////
AVPacket *pkt;
pkt = av_packet_alloc();
if (!pkt)
{
	cout << "av_packet_alloc pkt fail\n";
	return -1;
}
while (1)
{
	ret = av_read_frame(ps, pkt);
	if (ret < 0)
	{
		av_strerror(ret, err, 1024);
		cout << "av_read_frame: " << ret << " : " << err << '\n';
	}
	if (!ret && ++count != 100)
	{
		file.write((char*)pkt->data, 614400);
	}
	

	av_packet_unref(pkt);

	if (count == 100)
	{
		break;
	}

	
}

av_packet_free(&pkt);
file.close();
avformat_close_input(&ps);

av_log_set_level(AV_LOG_DEBUG);
av_log(nullptr, AV_LOG_DEBUG, "finish\n");

return 0;

}
图片描述
网上查了资料说可以这么解决
图片描述

曲线救国的解决代码:
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
#include

using std::string;
using std::copy;
using std::ofstream;
using std::cout;

int main()
{
int ret{}, count{};
char err[1024];
ofstream file;
file = ofstream(“D:/video.yuv”, std::ios::trunc);
if (!file)
return - 1;
file << “”;
file.close();
file = ofstream(“D:/video.yuv”, std::ios::app);
if (!file)
return -1;

avdevice_register_all();

auto fmt = av_find_input_format("dshow");

AVFormatContext *ps{};
const char *url{ u8"video=Surface Camera Front" };
AVDictionary *options{};
int rtbufsize{ 304128000 };  //每循环av_read_frame 100次之后重设rtbufsize,就可以曲线救国地将real time buffer刷新一遍
string str;



AVPacket *pkt;
pkt = av_packet_alloc();
while (1)
{
	cout << "start:\n";

	ret = av_dict_set(&options, "video_size", "640x480", 0);
	if (ret < 0)
	{
		av_strerror(ret, err, 1024);
		cout << "av_dict_set : " << ret << " : " << err << '\n';
	}

	ret = av_dict_set(&options, "framerate", "30", 0);
	if (ret < 0)
	{
		av_strerror(ret, err, 1024);
		cout << "av_dict_set : " << ret << " : " << err << '\n';
	}

	//每循环av_read_frame 100次之后重设rtbufsize,每次比之前设置的加1,
	//就可以曲线救国地将real time buffer刷新一遍
	++rtbufsize;
	str = std::to_string(rtbufsize);
	ret = av_dict_set(&options, "rtbufsize", str.c_str(), 0);
	if (ret < 0)
	{
		av_strerror(ret, err, 1024);
		cout << "av_dict_set : " << ret << " : " << err << '\n';
	}

	ret = avformat_open_input(&ps, url, fmt, &options);
	if (ret < 0)
	{
		av_strerror(ret, err, 1024);
		cout << "avformat_open_input : " << ret << " : " << err << '\n';
	}

	for (int i = 0; i != 100; ++i)
	{
		ret = av_read_frame(ps, pkt);
		if (ret < 0)
		{
			av_strerror(ret, err, 1024);
			cout << "av_read_frame : " << ret << " : " << err << '\n';
		}

		file.write(reinterpret_cast<char*>(pkt->data), 460800);
	}

	av_packet_unref(pkt);

	avformat_close_input(&ps);

	ps = nullptr;

}

file.close();
av_packet_free(&pkt);

av_log_set_level(AV_LOG_DEBUG);
av_log(nullptr, AV_LOG_DEBUG, "finish\n");

return 0;

}

写回答

1回答

李超

2024-12-23

你偿试设置rtbufsize的大小之后,这个问题解决了吗?

0
7
李超
回复
邓丹俊
更好的做法是用一个单独的线程做编码,然后采集线程主管读数据写到队列里去,编码线程从队列取数据编码,然后再写文件就不会有问题了。你现在这个阶段还没必要搞那么复杂,继续往后学吧。等你学习 ffmpeg 精讲那门课的时候就会学到这些知识了
2024-12-23
共7条回复

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

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

2317 学习 · 813 问题

查看课程