当前位置: 首页 > news >正文

第四篇 DirectShow 采集调用结构关系

第一篇: DirectShow视频采集_会头痛的可达鸭的博客-CSDN博客

一、GraphBuilder

1、IFilterGraph2、IGraphBuilder、ICaptureGraphBuiler2

(1)、CLSID

IFilterGraph           CLSID_FilterGraphIFilterGraph2          CLSID_CaptureGraphBuilderIGraphBuilder          CLSID_CaptureGraphBuilderICaptureGraphBuiler2   CLSID_CaptureGraphBuilder2

(2)、IFilterGraph2还有一个IFilterGraph,IFilterGraph3.

继承关系:

IFilterGraph——>IGraphBuilder——>IFilterGraph2——>IFilterGraph3

(3)、如果仅仅只需要预览 USB Video, 可以只使用IFilterGraph2

通过

pFilterGraph2->AddSourceFilterForMoniker()

用Moniker指针将filter添加到graph,则不必创建IcaptureGraphBuiler2这个接口。

如果需要需要视频流,则需要使用IFilterGraph

ICaptureGraphBuilder2->SetFiltergraph(IFilterGraph)

(4)、ICaptureGraphBuiler2是一个专门用来进行视频,音频捕捉的增强型接口;如果要特别的编解码,用它就很方便

创建了IcaptureGraphBuiler2,仍然需要创建IGraphBuilder ​ 因为在预览视频时处理播放,暂停,停止这些动作,需要用到IGraphBuilder,而这些功能IcaptureGraphBuiler2 ​ 是没有的,所以需要而这协调处理。 ​ IcaptureGraphBuiler2创建后,要将IGraphBuilder的指针与他关联:

pCaptureGraphBuiler2->captureGraphBuiler2(pGraphBuilder).

2、绑定并获取基础过滤器

// 写法1: 将视频设备绑定到基础过滤器上
IBaseFilter* GetDeviceFilter(const char* deviceUniqueIdUTF8,char* productUniqueIdUTF8,uint32_t productUniqueIdUTF8Length) 
{const int32_t deviceUniqueIdUTF8Length = (int32_t)strlen((char*)deviceUniqueIdUTF8);  // UTF8 is also NULL terminatedif (deviceUniqueIdUTF8Length >= kVideoCaptureUniqueNameLength) {RTC_LOG(LS_INFO) << "Device name too long";return NULL;}
​// enumerate all video capture devicesRELEASE_AND_CLEAR(_dsMonikerDevEnum);HRESULT hr = _dsDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&_dsMonikerDevEnum, 0);if (hr != NOERROR) {RTC_LOG(LS_INFO) << "Failed to enumerate CLSID_SystemDeviceEnum, error 0x"<< rtc::ToHex(hr) << ". No webcam exist?";return 0;}_dsMonikerDevEnum->Reset();ULONG cFetched;IMoniker* pM;
​IBaseFilter* captureFilter = NULL;bool deviceFound = false;while (S_OK == _dsMonikerDevEnum->Next(1, &pM, &cFetched) && !deviceFound) {IPropertyBag* pBag;hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pBag);if (S_OK == hr) {// Find the description or friendly name.VARIANT varName;VariantInit(&varName);if (deviceUniqueIdUTF8Length > 0) {hr = pBag->Read(L"DevicePath", &varName, 0);if (FAILED(hr)) {hr = pBag->Read(L"Description", &varName, 0);if (FAILED(hr)) {hr = pBag->Read(L"FriendlyName", &varName, 0);}}if (SUCCEEDED(hr)) {char tempDevicePathUTF8[256];tempDevicePathUTF8[0] = 0;WideCharToMultiByte(CP_UTF8, 0, varName.bstrVal, -1,tempDevicePathUTF8, sizeof(tempDevicePathUTF8),NULL, NULL);if (strncmp(tempDevicePathUTF8, (const char*)deviceUniqueIdUTF8,deviceUniqueIdUTF8Length) == 0) {// We have found the requested devicedeviceFound = true;hr = pM->BindToObject(0, 0, IID_IBaseFilter, (void**)&captureFilter);if(FAILED(hr)){RTC_LOG(LS_ERROR) << "Failed to bind to the selected ""capture device " << hr;}
​if (productUniqueIdUTF8 &&productUniqueIdUTF8Length > 0)  // Get the device name{GetProductId(deviceUniqueIdUTF8, productUniqueIdUTF8,productUniqueIdUTF8Length);}}}}VariantClear(&varName);pBag->Release();}pM->Release();}return captureFilter;
}
​
//写法2:枚举设备并绑定设备
BOOL BindToVideoDev(int deviceId, IBaseFilter **pFilter)
{if (deviceId < 0){return FALSE;}CComPtr<ICreateDevEnum> pCreateDevEnum;HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,IID_ICreateDevEnum, (void**)&pCreateDevEnum);if (hr != NOERROR){//ERR_DEBUG("Instance DeviceEnum Failed");return FALSE;}CComPtr<IEnumMoniker> pEm;hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEm, 0);if (hr != NOERROR){//ERR_DEBUG("Enum VideoInputDeviceCategory Failed");return FALSE;}pEm->Reset();ULONG cFetched;IMoniker *pM=NULL;
​int index = 0;while((( pEm->Next(1, &pM, &cFetched))==S_OK)&&( index <= deviceId)){IPropertyBag *pBag=NULL;if (pM==NULL){break;}hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);if(pBag!=NULL) {VARIANT var;var.vt = VT_BSTR;hr = pBag->Read(L"FriendlyName", &var, NULL);if (hr == NOERROR) {if (index == deviceId){//将视频设备绑定到基础过滤器上pM->BindToObject(0, 0, IID_IBaseFilter, (void**)pFilter);}SysFreeString(var.bstrVal);pBag->Release();}}pM->Release();index++;}return TRUE;
}
// 添加到过滤器
// AddFilter调用过滤器的IBaseFilter::JoinFilterGraph方法来通知过滤器它已被添加
// AddFilter必须在尝试使用IGraphBuilder::Connect、IFilterGraph::ConnectDirect或IGraphBuilder::Render
// 方法连接或渲染属于添加的过滤器的引脚之前调用
IFilterGraph->AddFilter(IBaseFilter, "name");
// 获取InputPin
IPin* GetInputPin(IBaseFilter* filter)
{IPin* pin = NULL;IEnumPins* pPinEnum = NULL;filter->EnumPins(&pPinEnum);if (pPinEnum == NULL) {return NULL;}// get first unconnected pinpPinEnum->Reset();  // set to first pin
​while (S_OK == pPinEnum->Next(1, &pin, NULL)) {PIN_DIRECTION pPinDir;pin->QueryDirection(&pPinDir);if (PINDIR_INPUT == pPinDir)  // This is an input pin{IPin* tempPin = NULL;if (S_OK != pin->ConnectedTo(&tempPin))  // The pint is not connected{pPinEnum->Release();return pin;}}pin->Release();}pPinEnum->Release();return NULL;
}

3、设置采集的分辨率

HRESULT SetVideoSize(int nPreview,CString strRGBBytes,int nFrameRate,int iWidth , int iHeight)
{HRESULT hr=E_FAIL;if(m_pCaptureGraphBulid==NULL)return hr;
​IAMStreamConfig *pAMStreamConfig=NULL;if(nPreview==0){hr = m_pCaptureGraphBulid->FindInterface(&PIN_CATEGORY_PREVIEW,&MEDIATYPE_Video,m_pBaseFilter,IID_IAMStreamConfig,(void **)&pAMStreamConfig);}else{hr = m_pCaptureGraphBulid->FindInterface(&PIN_CATEGORY_CAPTURE,&MEDIATYPE_Video,m_pBaseFilter,IID_IAMStreamConfig,(void **)&pAMStreamConfig);}
​if(FAILED( hr )){SAFE_RELEASE(pAMStreamConfig);return hr;}//得到视频格式大小AM_MEDIA_TYPE *pmt;pAMStreamConfig->GetFormat(&pmt);
​//设置视频格式pmt->majortype = MEDIATYPE_Video;pmt->subtype  = GetMediaTypeGuid(strRGBBytes);
​
​VIDEOINFOHEADER *pvih = reinterpret_cast<VIDEOINFOHEADER *>(pmt->pbFormat);//设置回去int nDefualWidth = pvih->bmiHeader.biWidth;int nDefualHeight = pvih->bmiHeader.biHeight;
​pvih->bmiHeader.biWidth = iWidth; pvih->bmiHeader.biHeight = iHeight;pvih->bmiHeader.biSizeImage = pmt->lSampleSize = iWidth*iHeight*pvih->bmiHeader.biPlanes*pvih->bmiHeader.biBitCount/8;pvih->AvgTimePerFrame = (LONGLONG)(10000000/nFrameRate);
​hr = pAMStreamConfig->SetFormat(pmt);if(FAILED(hr)){//如果设置失败可以选用默认的,但运用之后,小屏幕初始化时会出现闪动的情况   pvih->bmiHeader.biWidth = nDefualWidth; pvih->bmiHeader.biHeight = nDefualHeight;pvih->bmiHeader.biSizeImage = pmt->lSampleSize = nDefualWidth*nDefualHeight*pvih->bmiHeader.biPlanes*pvih->bmiHeader.biBitCount/8;hr = pAMStreamConfig->SetFormat(pmt);if(FAILED(hr)){SAFE_RELEASE(pAMStreamConfig);FreeMediaType(*pmt);//ERR_DEBUG("初始化设置视频格式失败");return hr;}}SAFE_RELEASE(pAMStreamConfig);FreeMediaType(*pmt);//return hr;
}

4、流程

(1)、创建CLSID_FilterGraph---- CoCreateInstance--- IFilterGraph

(2)、创建IID_IMediaControl --- IFilterGraph->QueryInterface --- IMediaControl

(3)、获取并连接:IBaseFilter---GetDeviceFilter---BindToObject

IFilterGraph->AddFilter(IBaseFilter, L"VideoCaptureFilter")

(4)、创建自定义的IBaseFilter(成员有IPin)---CaptureSinkFilter

IFilterGraph->AddFilter(CaptureSinkFilter)

(5)、获取InputPin,通过自定义的CaptureSinkFilter,并连接CaptureInputPin::ConnectedTo

(6)、连接OutputPin和InputPin(直接连接两个引脚, 无需中间滤波器)

IFilterGraph->ConnectDirect(OutputPin, InputPin, NULL)

三、VideoCaptureDS

1、初始化

// 基类: VideoCaptureImpl
VideoCaptureDS :public VideoCaptureImpl
// 初始化并且创建:
// IBaseFilter          DirectShow主要过滤器     
// IGraphBuilder        DirectShow图形生成器
// IMediaControl        DirectShow媒体控制器
// CaptureSinkFilter
// IPin
VideoCaptureDS::Init  

2、CaptureSinkFilter

// 基类
// 创建 CaptureInputPin
CaptureSinkFilter : public IBaseFilter 

3、CaptureInputPin

// Input Pin--->camera input
// 负责绑定: receive_pin 和 媒体类型
// 接受视频数据发送给observer
class CaptureInputPin : public IMemInputPin, public IPin 

4、DeviceInfoDS

// 主要提供设备能力、获取设备信息、获取Filter
DeviceInfoDS : public DeviceInfoImpl

相关文章:

第四篇 DirectShow 采集调用结构关系

第一篇: DirectShow视频采集_会头痛的可达鸭的博客-CSDN博客 一、GraphBuilder 1、IFilterGraph2、IGraphBuilder、ICaptureGraphBuiler2 (1)、CLSID IFilterGraph CLSID_FilterGraphIFilterGraph2 CLSID_CaptureGraphBuilderIGraphBuilder CL…...

2605. 从两个数字数组里生成最小数字

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;枚举比较法方法二&#xff1a;集合的位运算表示法 写在最后 Tag 【贪心】【位运算】【数组】 题目来源 2605. 从两个数字数组里生成最小数字 题目解读 给定两个各自只包含数字 1 到 9 的两个数组&#xff0c;每个数组…...

服务器发送事件Server-sent events详解与示例

Server-sent events 服务端进行数据推送除了WebSocket之外&#xff0c;还可以使用Server-Send-Event方案。 与 WebSocket不同的是&#xff0c;服务器发送事件是单向的。数据消息只能从服务端到发送到客户端&#xff08;如用户的浏览器&#xff09;。这使其成为不需要从客户端…...

SOLIDWORKS 多实体的建模方式

SOLIDWORKS多实体是SOLIDWORKS中一个非常有用的功能。在SOLIDWORKS中&#xff0c;对于模型的设定通常被大家所熟知的有以下几种类型&#xff1a;零件、装配体以及工程图。 其实还有一种划分&#xff0c;就是多实体。严格意义上来说&#xff0c;多实体既不属于零件也不属于装配体…...

NSSCTF web 刷题记录1

文章目录 前言题目[GXYCTF 2019]禁止套娃方法一方法二 [NCTF 2019]Fake XML cookbook[NSSRound#7 Team]ec_RCE[NCTF 2018]Flask PLUS 前言 今天是2023.9.3&#xff0c;大二开学前的最后一天。老实说ctf的功力还是不太够做的题目太少&#xff0c;新学期新气象。不可急于求成&am…...

遥感指数数据库

目前遥感指数多种多样&#xff0c;那怎么针对不同的应用领域选择合适的植被指数&#xff1f;不同卫星又有哪些可以反演的指数&#xff1f; Henrich等人开发了Index Database(网址&#xff1a;https://www.indexdatabase.de/)&#xff0c;总结了目前主流的遥感指数&#xff0c;…...

如何让insert程序速度快,可以试试联合SQL(insert 和 select 一起使用)?

查询添加可选择SQL执行&#xff0c;速度远超程序执行 insert 和 select案例 insert into 表1(列1,列2,列3,...) select 列1,列2,列3,...from表2(GROUP BY 列)116511 条数据 耗时45秒&#xff0c; 如果是程序查询然后再insert&#xff0c;则需要30分钟左右&#xff01;&#x…...

IP地址、网关、网络/主机号、子网掩码关系

一、IP地址 IP地址组成 IP地址分为两个部分&#xff1a;网络号和主机号 &#xff08;1&#xff09;网络号:标识网段&#xff0c;保证相互连接的两个网段具有不同的标识。 &#xff08;2&#xff09;主机号:标识主机&#xff0c;同一网段内&#xff0c;主机之间具有相同的网…...

使用skvideo.io.vread读取avi视频,报错“No way to determine width or height from video...”

问题描述&#xff1a; 一开始安装sk-video&#xff0c;在使用skvideo.io.vread读取avi视频&#xff0c;报错“No way to determine width or height from video. Need -s in inputdict. Consult documentation on I/O.” 解决方案&#xff1a; 1. 卸载sk-video pip uninsta…...

Nomad 系列-安装

系列文章 Nomad 系列文章 Nomad 简介 开新坑&#xff01;近期算是把自己的家庭实验室环境初步搞好了&#xff0c;终于可以开始进入正题研究了。 首先开始的是 HashiCorp Nomad 系列&#xff0c;欢迎阅读。 关于 Nomad 的简介&#xff0c;之前在 大规模 IoT 边缘容器集群管…...

网络版五子棋C++实现

目录 1.项目介绍 2.开发环境 3.核心技术 4.环境搭建 5.WebSocketpp介绍 5.1WebSocketpp是什么 5.2为什么使用WebSocketpp 5.3原理解析&#xff1a; 5.4WebSocketpp主要特性 6.WebSocketpp使用 7.JsonCpp使用 8.MySQL API 9.项目模块设计以及流程图 10.封装日志宏…...

项目招标投标公众号小程序开源版开发

项目招标投标公众号小程序开源版开发 以下是一个招标投标公众号小程序的功能列表&#xff1a; 用户注册与登录&#xff1a;用户可以注册账号并登录公众号小程序。项目发布&#xff1a;用户可以发布招标项目的详细信息&#xff0c;包括项目名称、招标单位、项目描述、招标要求…...

华为OD机试-机器人走迷宫

题目描述 机器人走一个迷宫,给出迷宫的x和y(x*y的迷宫)并且迷宫中有障碍物,输入k表示障碍物有k个,并且会将障碍物的坐标挨个输入. 机器人从0,0的位置走到x,y的位置并且只能向x,y增加的方向走,不能回退. 如代码类注释展示的样子,#表示可以走的方格,0代表障碍,机器人从0,0的位置…...

Jenkins搭建步骤Linux环境

1、进入目标目录开始准备环境 安装jdk 安装maven 安装tomcat 安装node 下载Jenkins.war并且拷贝进tomcat的webapp的文件夹下。 环境变量配置如下自行更改&#xff1a; #--------------For JDK---------------- export JAVA_HOME/usr/local/java/jdk1.8.0_192 export PATH/usr…...

2023 AZ900备考

文章目录 如何学习最近准备考AZ900考试&#xff0c;找了一圈文档&#xff0c;结果发现看那么多文档&#xff0c;不如直接看官方的教程https://learn.microsoft.com/zh-cn/certifications/exams/az-900/ &#xff0c;简单直接&#xff0c;突然想到纳瓦尔宝典中提到多花时间进行思…...

青翼科技基于VITA57.1的16路数据收发处理平台产品手册

FMC211是一款基于VITA57.1标准规范的实现16路LVDS数据采集、1路光纤数据收发处理FMC子卡模块。 该板卡支持2路CVBS&#xff08;复合视频&#xff09;视频输入&#xff0c;能够自动检测标准的模拟基带电视信号&#xff0c;并将其转变为8位ITU-R.656接口信号或者4:2:2分量视频信…...

Ansible_自动化运维实战(一)

1.DELL的一款服务器的价格、型号、配置&#xff08;CPU&#xff0c;内存、硬盘、支持的RAID功能&#xff09; DELL 服务器的定价、型号和配置因型号而异&#xff0c;可以通过访问 DELL 官方网站或联系 DELL 客户服务获取具体信息。一种示例是 DELL PowerEdge R740&#xff0c;其…...

说说Flink中的State

分析&回答 基本类型划分 在Flink中&#xff0c;按照基本类型&#xff0c;对State做了以下两类的划分&#xff1a; Keyed State&#xff0c;和Key有关的状态类型&#xff0c;它只能被基于KeyedStream之上的操作&#xff0c;方法所使用。我们可以从逻辑上理解这种状态是一…...

适合心理法律在线咨询预约含视频图文电话咨询功能的小程序开发

目前智能手机普及&#xff0c;很多以前需要线下咨询的场景都被搬到了线上&#xff0c;这样既可以使咨询者更方便&#xff0c;也可以使被咨询者接待效率更高&#xff0c;服务更多咨询者。基于此我们开发了专门的一款具有线上咨询功能的小程序&#xff0c;同时为了方便被咨询者服…...

Redis-Cluster集群操作--添加节点、删除节点

一、环境部署 部署好Redis-Cluster集群&#xff0c;参考上个本人的博客&#xff1a;Redis-Cluster集群的部署&#xff08;详细步骤&#xff09;_是胡也是福的博客-CSDN博客 新准备一台机器&#xff0c;修改主机名&#xff0c;关闭防火墙和selinux&#xff0c;参考&#xff1a…...

【STM32】幻尔16路舵机控制板串口协议解析与实战编程

1. 幻尔16路舵机控制板基础认知 第一次拿到幻尔16路舵机控制板时&#xff0c;我盯着密密麻麻的接口有点发懵。这块巴掌大的绿色电路板&#xff0c;居然能同时控制16个舵机&#xff1f;经过半年多的项目实战&#xff0c;我可以负责任地说&#xff1a;这绝对是多舵机项目的开发神…...

《算法竞赛从入门到国奖》算法基础:动态规划-最长子序列

&#x1f4a1;Yupureki:个人主页 ✨个人专栏:《C》 《算法》《Linux系统编程》《高并发内存池》《MySQL数据库》 《个人在线OJ平台》 &#x1f338;Yupureki&#x1f338;的简介: 目录 1. 最长上升子序列 算法原理 代码示例 2. 合唱队形 算法原理 代码示例 3. 最长公共…...

循环冷却水流量示意图设计 建筑水流量示意图绘制教程

一、引言 在建筑给排水、暖通空调及工业循环水系统设计中&#xff0c;循环冷却水流量示意图与建筑水流量示意图是核心技术图纸之一&#xff0c;其作用是直观呈现水流路径、管径规格、流量分配、设备连接关系及压力节点参数&#xff0c;为系统施工、调试、运维及故障排查提供可…...

大疆诉影石创新专利侵权,FTO综合分析筑牢研发风控屏障

3月23日&#xff0c;全球无人机巨头大疆对同行影石创新提起专利权属纠纷诉讼&#xff0c;涉案6项专利聚焦无人机飞行控制、结构设计、影像处理等核心技术领域&#xff0c;这场行业龙头间的知识产权纠纷&#xff0c;成为近日行业关注焦点。职务发明权属成为争议关键本次纠纷由大…...

向量化计算落地难?揭秘阿里/腾讯内部正在用的7个Java Vector API高危避坑场景

第一章&#xff1a;Java Vector API向量化计算落地的现实困境Java Vector API&#xff08;JEP 338、414、426、448&#xff09;虽在JDK 16起逐步成熟&#xff0c;但实际工程化部署仍面临多重结构性约束。其核心矛盾在于&#xff1a;API设计高度抽象&#xff0c;而底层硬件适配、…...

利用快马平台十分钟快速构建开源项目网站原型:以openclaw101为例

作为一个经常参与开源项目的开发者&#xff0c;我深知快速验证想法的重要性。最近在尝试为开源项目openclaw101搭建网站时&#xff0c;发现InsCode(快马)平台能完美解决从零搭建的繁琐过程。下面分享如何用十分钟完成一个具备完整功能的项目网站原型。 明确需求与功能规划 首先…...

DevOps实践:如何让开发、测试、运维不再“打架”?

质量不再是孤岛在追求快速迭代的现代软件开发中&#xff0c;开发、测试与运维团队之间的隔阂与摩擦&#xff0c;常常被戏称为“部门战争”。开发团队渴望快速交付新功能&#xff0c;测试团队需要足够的时间来保障质量&#xff0c;而运维团队则首要追求系统的稳定与可靠。当发布…...

Deep-Live-Cam性能优化指南:从环境配置到实时换脸全流程解决方案

Deep-Live-Cam性能优化指南&#xff1a;从环境配置到实时换脸全流程解决方案 【免费下载链接】Deep-Live-Cam real time face swap and one-click video deepfake with only a single image 项目地址: https://gitcode.com/GitHub_Trending/de/Deep-Live-Cam Deep-Live-…...

告别照相馆!AI头像生成器教你免费制作高质量职业头像

告别照相馆&#xff01;AI头像生成器教你免费制作高质量职业头像 1. 为什么选择AI生成职业头像&#xff1f; 在当今数字化求职环境中&#xff0c;一张专业的头像照片已经成为简历不可或缺的部分。传统照相馆拍摄存在三个主要痛点&#xff1a; 成本高昂&#xff1a;专业摄影工…...

专业级foobar2000个性化配置方案:提升音乐管理效率的foobox-cn

专业级foobar2000个性化配置方案&#xff1a;提升音乐管理效率的foobox-cn 【免费下载链接】foobox-cn DUI 配置 for foobar2000 项目地址: https://gitcode.com/GitHub_Trending/fo/foobox-cn foobox-cn是一套针对foobar2000音乐播放器的专业级DUI&#xff08;DirectUI…...