SkeyeLive中DirectShow采集音视频流程及几种采集方式介绍

本文介绍了Windows下使用DirectShow进行音视频采集的流程,包括枚举设备、Capture Graph Builder的应用、采集参数设置、视频渲染器的创建以及预览数据的实现。同时,讨论了DirectShow的线程模式和回调模式,分析了两种模式的优缺点。
摘要由CSDN通过智能技术生成

前段时间SkeyeLive开放了DirectShow采集库,这个库底层采用DirectShow SDK的接口实现音视频的预览(播放)和采集;很多人可能还不太了解这个封装库的回调方式和之前的DShow线程采集方式有什么不同,或者说对DirectShow的采集流程还不太熟悉,下面我将就Windows平台下用使用DirectShow的过滤器(滤波器)进行流媒体开发的前端采集部分进行简要介绍,如果大家想深入的学习和探索,推荐大家去看看《Visual C++音频/视频处理技术及工程实践》这本书,第9章有详细的流程讲解。

一、枚举采集设备

使用采集设备前,需要首先确定系统已经安装的采集设备:视频、音频采集设备。系统设备枚举器为按类型枚举已注册在系统中的滤波器提供了统一的方法。而且它能够区分不同的硬件设备,即便是同一个滤波器支持它们。这对那些使用Windows驱动模型、KSProxy Filter的设备来说是非常有用的,系统设备枚举器对它们按不同的设备实例进行对待。

当利用系统设备枚举器查询设备的时候,系统设备枚举器为特定类型的设备(如音频捕获和视频压缩)生成了一张枚举表(Enumerator)。类型枚举器(Category Enumerator)为每个这种类型的设备返回一个Moniker,类型枚举器自动把每种即插即用的设备包含在内。

调用标准方法CoCreateInstance生成系统设备枚举器(Device Enumerator),类标识(CLSID)为CLSID_SystemDeviceEnum,方法如下:

CAMERA_LIST_T *CCameraDS::GetCameraList()
{
	if (NULL != cameraList.pCamera || cameraList.count > 0)
	{
		return &cameraList;
	}

	if (NULL == cameraList.pCamera)
	{
		cameraList.count = 0;

	   // enumerate all video capture devices
		CComPtr<ICreateDevEnum> pCreateDevEnum;
		HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
										IID_ICreateDevEnum, (void**)&pCreateDevEnum);

		CComPtr<IEnumMoniker> pEm;
		hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEm, 0);
		if (hr != NOERROR) 
		{
			return &cameraList;
		}

		pEm->Reset();

		CAMERA_INFO_T	*pCameraList = cameraList.pCamera;
		CAMERA_INFO_T	*pCameraInfo = NULL;

		ULONG cFetched;
		IMoniker *pM = NULL;
		while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK)
		{
			pCameraInfo = new CAMERA_INFO_T;
			memset(pCameraInfo, 0x00, sizeof(CAMERA_INFO_T));

            IPropertyBag *pBag=0;
            hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
            if(SUCCEEDED(hr))
            {
                VARIANT var;
                var.vt = VT_BSTR;
                hr = pBag->Read(L"FriendlyName", &var, NULL); //还有其他属性,像描述信息等等...
                if(hr == NOERROR)
                {
                    //获取设备名称
                    WideCharToMultiByte(CP_ACP,0,var.bstrVal,-1,pCameraInfo->friendlyName, sizeof(pCameraInfo->friendlyName) ,"",NULL);
                    SysFreeString(var.bstrVal);                
                }
                pBag->Release();
				cameraList.count++;

				{
					pCameraList = cameraList.pCamera;

					if (NULL == cameraList.pCamera)	cameraList.pCamera = pCameraInfo;
					else
					{
						while (NULL != pCameraList->pNext)
						{
							pCameraList = pCameraList->pNext;
						}
						pCameraList->pNext = pCameraInfo;
					}
				}
            }

			pM->Release();
		}

		pCreateDevEnum = NULL;
		pEm = NULL;
	}
	return &cameraList;
}

这是视频设备枚举部分,当然音频也是一样的,只需要把CreateClassEnumerator函数的第一个参数换成CLSID_AudioInputDeviceCategory即可。
注意:调用ICreateDevEnum::CreateClassEnumerator方法生成类型枚举器,参数为用户想要得到的类的ID(CLSID),该方法返回一个IEnumMoniker接口指针。如果指定的类型是空的或不存在,则函数ICreateDevEnum::CreateClassEnumerator将返回S_FALSE而不是错误代码,同时IEnumMoniker指针也是空的,这就要求我们在调用CreateClassEnumerator的时候明确用S_OK进行比较而不使用宏SUCCEEDED;(扯远了…)而在SkeyeLive中还提供了另外一种枚举音频设备的方式,那就是采用DirectSound的枚举方式:DirectSoundCaptureEnumerate这个函数来实现的,需要注意,这个函数枚举出的设备GUID有可能是空的,设备名称可能表象为”声卡主设备驱动“,经测试

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SwordTwelve

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值