免责声明:仅供研究讨论,未经确认,内容与提供之源码,严禁商用!!!
先提一些题外话,在微软关于DirectShow的官网上有如下说明:
https://docs.microsoft.com/zh-cn/windows/win32/directshow/directshow
所以我这里去Windows官网下载Sdk,从中获取新版的DirectShow,但microsoft似乎对DirectShow后续改动其实并没有特别多,
https://developer.microsoft.com/en-us/windows/downloads/sdk-archive
因为目前我用的系统是Win7,所以我暂时下载的如下版本的SDk。
安装完成后,我这里在C:\Program Files\Microsoft SDKs\Windows\v7.1\Samples\multimedia\directshow中有directshow相关的SDK包。
回归正题,通常DirectShow原始SDK包没有自带驱动H264/H265流格式摄像头的filter。
但是通过查找Github上的开源项目libde265(https://github.com/strukturag/libde265),在其README.md说明中可以翻看到如下一段。
Libde265 has been integrated into these applications:
- gstreamer plugin, [source](https://github.com/strukturag/gstreamer-libde265), [binary packages](https://launchpad.net/~strukturag/+archive/libde265).
- VLC plugin [source](https://github.com/strukturag/vlc-libde265), [binary packages](https://launchpad.net/~strukturag/+archive/libde265).
- Windows DirectShow filters, https://github.com/strukturag/LAVFilters/releases
- ffmpeg fork, https://github.com/farindk/ffmpeg
- ffmpeg decoder [source](https://github.com/strukturag/libde265-ffmpeg)
- libde265.js JavaScript decoder [source](https://github.com/strukturag/libde265.js), [demo](https://strukturag.github.io/libde265.js/).
由上,我们可以直接下载上述DirectShow的第三方filter导入即可拿来解码H265码流,由于目前小编手头还没有H265格式输出的UVC摄像头,现以H264为例。
介绍如何导入新的Filter,以及如何使用第三方filter完成解码操作。这里我将采用sourceforge上的另一个开源Filter(http://hax264.sourceforge.net/)项目,箭头处可进入下载页面下载相关开源的源码和Release包。
下载好Hax264_setup_1_0_0.exe后,安装,你将会得到以下文件。
接下来我们要做的是注册组件,filter实际就是COM组件,可使用命令行注册,这里由于上述路径中有空格,我将其移到了D盘,此外运行cmd.exe时,要以管理员身份运行,如下:
补充一点,以上注册组件的这个步骤要特别注意,这个路径一旦确定以后,里面的库等资源就不要移动到别的地方去了,否则,会导致运行我们的解码程序时找不到资源模块,这不但会导致你的程序Crash,在使用GraphEdit添加Filter时,也会提示找不到模块。
接下来打开DirectShow的GraphEdit.exe可以发现在枚举系统的DirectShow Filters时,多了我们刚刚注册的Filter,如下:
接下来,由于我的摄像头有多个输出pin及多种输出格式,我配置我的UVC摄像头输出格式为H264-1080P输出,如下图:
在H264 DS Filter上右击配置属性,我们有两种输出格式可以配置如下:
以上已经可以点亮摄像头,接下来,我们通过代码去实现上述Com连接,并取样图像。
首先我们在代码中创建该Filter时,需要一个唯一ID,我们可以通过在Insert Filter页面查看:
该处后面的ID中即有我们需要的ID,于是可新增定义如下:
#define MYDEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
EXTERN_C const GUID DECLSPEC_SELECTANY name \
= { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
// 43FC6785-8E56-4ED6-9CCC-9F3556AC9D24
MYDEFINE_GUID(CLSID_H264DS,0x43FC6785, 0x8E56, 0x4ED6, 0x9C, 0xCC, 0x9F, 0x35, 0x56, 0xAC, 0x9D, 0x24);
// H.264 compressed video stream
// 34363248-0000-0010-8000-00AA00389B71 'H264' == MEDIASUBTYPE_H264
MYDEFINE_GUID(MEDIASUBTYPE_H264,0x34363248, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
// 创建H264解码接口
IBaseFilter *m_pH264Filter;
hr = CoCreateInstance(CLSID_H264DS,0,CLSCTX_INPROC,IID_IBaseFilter,
(void**)&m_pH264Filter);//声明第二个filter
if(hr == S_FALSE) return hr;
//添加H264 Filter到Graph中
hr = m_pGraphFilter->AddFilter(m_pH264Filter,L"H264 DS Filter");
if (hr == S_FALSE) return hr;
这里上传了一个我编写的示例程序资源:
https://download.csdn.net/download/tanjiaqi2554/11691879
以上资源可驱动点亮该格式输出的UVC摄像头,编译的时候需要正确设置你的DirectShow的包含头文件目录路径和库路径,如下:
以上可能报错,如果是7.0A版本以后的DirectShow可能缺少Qedit.h,没关系【它在老版本9.0中是有的】,这个文件我也单独上传了,直接复制到DirectShow头文件目录下即可,如下: