【音视频】摄像头采集-dshow(2-1)

从本篇开始,作者的音视频编程之旅即将进入第二阶段,在之前采集桌面、麦克风、扬声器写成mp4|mkv等可播放文件的基础上,添加了摄像头的采集,可以将摄像头替换桌面作为视频端输入源,也可以将摄像头和桌面两股视频流混合作为一股视频输入源。

技术简介

采集摄像头,应该有人马上会想起dshow,是的,不过我用到了ffmpeg里面的dshow技术,ffmpeg集成了dshow使得使用更加方便了,不过要得到更详细的摄像头设备信息,还是需要使用到com知识。

使用模块(库)

主要使用的是ffmpeg的format、device库以及windows系统库

主要流程和代码

1、初始化摄像头采集模块。首先一定要调用avdevice_register_all和avformat_network_all,才可以初始化dshow的AVInputFormat

int CameraCaptor::init(const std::string& deviceId, const int fps)
{
   
	int err = ERROR_CODE_OK;
	if (m_inited) {
   
		return err;
	}

	do {
   
		m_deviceId = deviceId;

		avdevice_register_all();
		avformat_network_init();
		m_inputFmt = av_find_input_format("dshow");
		if (m_inputFmt == nullptr) {
   
			err = ERROR_CODE_FFMPEG_FIND_INPUT_FORMAT_FAILED;
			break;
		}

		std::string camera;
		int number;
		err = findCameraById(camera, number);
		HCMDR_ERROR_CODE_BREAK(err);

		std::map<std::string, std::multimap<AVCodecID, DEVICE::VIDEO_MEDIADATA>> mediadataList;
		err = DEVICE::VideoDevice::getCameraMediadataList(mediadataList);
		HCMDR_ERROR_CODE_BREAK(err);

		size_t captureId;
		std::multimap<AVCodecID, DEVICE::VIDEO_MEDIADATA>::const_iterator it;
		auto mediadatas = mediadataList.at(m_deviceId);
		for (captureId = 0; captureId < m_captureCodecs.size(); captureId++) {
   
			auto itBeg = mediadatas.lower_bound(m_captureCodecs.at(captureId));
			auto itEnd = mediadatas.upper_bound(m_captureCodecs.at(captureId));
			for (it = itBeg; it != itEnd; it++) {
   
				if (it->second.isDefault) {
   
					std::string resolution;
					resolution.assign(std::to_string(it->second.width)).append("x").append(std::to_string(it->second.height));
					err = initCamera(camera, number, resolution, it->second.fps, it->first);
					break;
				}
			}
			if (err == ERROR_CODE_OK) {
   
				break;
			}
		}
		if (err != ERROR_CODE_OK) {
   
			break;
		}

		m_fps = it->second.fps;
		m_rect = {
    0, 0, it->second.width, it->second.height };
		m_pixelFmt = m_capturePixFmts.at(captureId);
		m_inited = true;
	} while (0);

	if (err != ERROR_CODE_OK) {
   
		LOGGER::Logger::log(LOGGER::LOG_TYPE_ERROR, "[%s] init camera captor error: %s, last error: %lu",
			__FUNCTION__, HCMDR_GET_ERROR_DESC(err), GetLastError());
		cleanup();
	}

	return err;
}

接着根据设备id找到摄像头设备,如何获取设备id可以看《【音视频】获取视频设备-MMDeviceAPI&MONITORINFOEX(2-3)》这篇文章,这里同样获取了设备列表跟设备id比对拿到摄像头名称camera以及摄像头序号number,number表示该摄像头是同名摄像头的第几个

int CameraCaptor::findCameraById(std::string& camera, int& number)
{
   
	int err = ERROR_CODE_OK;

	do {
   
		std::list<DEVICE::VIDEO_DEVICE> devices;
		err = DEVICE::VideoDevice::getCameraDevices(
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值