从视频设备上采集数据,求指教

前期介绍:
对于Mac笔记本
*devicename = “0”;为采集视频
:0为只采集音频
0:0为同时采集音视频
0 代表机器摄像头
1 代表桌面

相关命令

查看设备支持格式:啊,简直了

ffmpeg -f dshow -i video="Lenovo EasyCamera"

在这里插入图片描述

实战

调用lenovo EasyCamera设备录像出错,就从开始菜单用它来录视频,然后打印录制完成的视频信息,结果
从视频设备上采集数据,求指教_第1张图片

代码,没成功,

yuv保存下来为花屏,没影像,pkt.size改成640x320或是其两倍,指教为0大小的yuv,用pkt.size才有雪花数据

#define __STDC_CONSTANT_MACROS
extern "C"
{
#include 
#include 
#include 
}

#include 
#include 
#include 
#include 

#pragma comment(lib, "avutil.lib")
#pragma comment(lib, "avdevice.lib")
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avcodec.lib")

#pragma comment(lib, "Winmm.lib")

using std::vector;
using std::string;
using std::shared_ptr;

void capture_audio()
{
	/*
	//windows api 获取音频设备列表(ffmpeg 好像没有提供获取音视频设备的api)
	int nDeviceNum =  waveInGetNumDevs();
	vector vecDeviceName;
	for (int i = 0; i < nDeviceNum; ++i)
	{
		WAVEINCAPS wic;
		waveInGetDevCaps(i, &wic, sizeof(wic));

		//转成utf-8
		int nSize = WideCharToMultiByte(CP_UTF8, 0, wic.szPname, wcslen(wic.szPname), NULL, 0, NULL, NULL);
		shared_ptr spDeviceName(new char[nSize + 1]);
		memset(spDeviceName.get(), 0, nSize + 1);
		WideCharToMultiByte(CP_UTF8, 0, wic.szPname, wcslen(wic.szPname), spDeviceName.get(), nSize, NULL, NULL);
		vecDeviceName.push_back(spDeviceName.get());
		av_log(NULL, AV_LOG_DEBUG, "video input device : %s \n", spDeviceName.get());
		//printf("%s \n", spDeviceName.get());
	}
	
	if (vecDeviceName.size() <= 0)
	{
		av_log(NULL, AV_LOG_ERROR, "not find video input device.\n");
		return;
	}
	*/
	string sDeviceName = "video=Lenovo EasyCamera";
	//printf("--z中-----%s \n", sDeviceName);

	AVDictionary *options = NULL;

	//ffmpeg
	avdevice_register_all(); //注册所有输入输出设备
	AVInputFormat* ifmt = av_find_input_format("dshow");    //设置采集方式 dshow,此为windows下

	av_dict_set(&options, "video_size", "640x320", 0);
	av_dict_set(&options, "framerate", "30", 0);//帧率
	//av_dict_set(&options, "pixel_format", "30", 0);//帧率

	if (ifmt == NULL)
	{
		av_log(NULL, AV_LOG_ERROR, "av_find_input_format for dshow fail.\n");
		return;
	}

	AVFormatContext* fmt_ctx = NULL;                    //format 上下文
	int ret = avformat_open_input(&fmt_ctx, sDeviceName.c_str(), ifmt, NULL); //"video=Lenovo EasyCamera"打开音频设备 sDeviceName.c_str()
	if (ret != 0)
	{
		av_log(NULL, AV_LOG_ERROR, "avformat_open_input fail. return %d.\n", ret);
		return;
	}

	AVPacket pkt;
	FILE* fp = fopen("dst.yuv", "wb+");
	int count = 0;
	printf("--------------------------Record video is begin \n");
	while (count++ < 60)
	{
		ret = av_read_frame(fmt_ctx, &pkt);
		if (ret != 0)
		{
			av_log(NULL, AV_LOG_ERROR, "av_read_frame fail, return %d .\n", ret);
			break;
		}
		printf("wxd_____pkt.size is %d \n",pkt.size);
		//av_log(NULL, AV_LOG_INFO, "packet size is %d(%p)\n", pkt.size, pkt.data);
		fwrite(pkt.data, 1, 409600, fp);//这里 pkt.size是相对音频,要改204800
		
		av_packet_unref(&pkt);//必须释放pkt申请的内存,否则会内存泄露
	}
	printf("---------------------------Record video is over \n");
	fflush(fp);//刷新文件io输出缓冲区
	fclose(fp);

	avformat_close_input(&fmt_ctx);
}

int main(int argc, char** argv)
{
	av_log_set_level(AV_LOG_DEBUG); //设置ffmpeg日志库等级
	printf("中文显示, chinese display \n");
	capture_audio();

	Sleep(1);
	return 0;
}

bug解决

1.报错:无法查找或打开 PDB 文件,要仅加载指定符号
参考:https://blog.csdn.net/weixin_37662982/article/details/86631124

https://blog.csdn.net/sinat_33205914/article/details/87870378

其他注意:

-s 1280x720参数一定要在-i sample.yuv的前面,否则会报"Picture size 0x0 is invalid "的错误
删除或调小水印参考:https://blog.csdn.net/weixin_41217917/article/details/103274974
查看平台下的设备支持:https://blog.csdn.net/lwj_zeal/article/details/86564659

你可能感兴趣的:(ffmpeg)