BRabbit's Blog

This blog has super rabbit power!

本文重点介绍利用 DirectShow 组件的特性实现在 Windows 平台下”虚拟摄像头”功能的方法, 同时简要介绍与探讨 DirectShow 本身的特性.

绝大多数虚拟摄像头从实现方式上来看可以分为两种思路:

  1. 在驱动层面进行开发, 模拟一个 物理摄像头 . 让 OS 以普通物理摄像头的方式调用虚拟摄像头.
  2. 在 OS 平台通用的媒体组件层面进行开发, 模拟一个 视频流数据源 . 让 OS 层之上的应用以普通摄像头的方式调用虚拟摄像头.

其中方案 1. 的优点在于可以在当前平台下完全伪造一个物理摄像头, 只要用户行为没有脱离 OS 的控制范围, 那么这个摄像头都是可用正常使用的. 缺点是驱动开发的难度和工作量很大, 需要针对不同的硬件平台提供不同的驱动程序.

方案 2. 的优点在于开发难度相对较小, 只要针对不同的 OS 提供不同的软件即可, 无需关心硬件的差别. 缺点在于部分不依赖当前 OS 平台通用媒体组件的应用场景是没办法覆盖到的.

文本采取的方案是后者, 这同时也是 OBS 与 Mevo 等团队采用的方案. 对于我们的目标平台 Windows, 自 2005 年其正式成为 Windows Vista 的组件起至今 (2022 年 Windows 11) 就一直作为 Windows 平台下的通用媒体组件. 我们的工作也将围绕 DirectShow 展开.

阅读全文 »

传统 C++ 提供了很强大的泛型编程功能, 但是这个功能是难以约束的, 导致难读懂. 既然人都不容易看懂, 就更别指望编辑器与编译器能给我们多好的帮助了. 而 C++20 提供的 conceptrequires 则提供了很好的约束模板的方式.

请注意这里的”约束”概念, 如同上文所说的”多态”在 OOP 与 GP 中概念的差异一样, 此处的”约束”也有不同的含义:

  • OOP 中的”约束”是在运行前约束, 使得错误在进入运行期之前就暴露出来.
  • GP 中的”约束”是在编译前进行约束, 使得错误在进入编译期之前就暴露出来.
阅读全文 »

传统 C++ 对泛型编程方式的支持程度, 相对于其他主流语言而言高出很多. 但即便是 C++ 中大量使用模板的工程也很少, 而完全以 GP 的代替 OOP 作为基本逻辑的工程更是寥寥无几. 这里的主要原因还是模板代码不太符合人的直观逻辑, 难以理解. 其次是因为传统 C++ 中依然缺少针对泛型编程的一些基础功能.

在现代 C++ 中添加了很多 GP 的新内容, 这其中既包括了实际的语法功能, 也补全了一些传统 C++ 对 GP 核心功能的缺失.

阅读全文 »

变量类型推导其实在 C++ 中一直存在, 例如我们在使用泛型函数时编译器将帮助我们隐式地推导参数类型 :

1
2
3
template<typename _Type>
void func(_Type value) { /* do something */ }
func(114514); // func<int>(114514);

但直到 C++11 起才允许用户主动要求编译器进行类型推导. 现代 C++ 中提供的主动类型推导功能主要是通过 autodecltype 两个关键字实现.

阅读全文 »

constexpr 关键字在 C++11 中被引入标准, 它用于定义一个常量. 这里常量的含义是编译器即可确定的结果, 这个结果可以是 :

  1. 变量的值
  2. 函数发返回值
  3. 条件分支的判断结果 (C++17 起)

constexpr 与传统 C++ 中名字相似的 const 相比, 二者并不是子集与超集的关系, 但在语义上确有一些交集.

如何定义一个常量?

在传统 C++ 中, 主要分为两个流派: 宏定义 或 常量 const.

1
2
#define CONST_NUMBER 128
const int Const_Number = 128;

而在现代 C++ 中, 更推荐使用 constexpr 定义常量, 以替代宏定义与常量 const .

1
constexpr int Constexpr_Number = 128;
阅读全文 »

本文意在简单梳理现代 C++ 相比于传统 C++ 而言在具体开发中一些常用, 实用的特性/功能.
文中所述特性/功能主要涵盖的范围从 C++11 到 C++20, 我会标注引入标准的版本, 若没有加以备注, 则说明是在 C++11 引入的.
文中大部分示例代码基于 GCC(G++) 9.3.0 -std=c++2a 演示, 部分使用 MSVC(VC++) 演示的代码将标注.

阅读全文 »

写这篇文章的契机是在我重构一段代码的过程中遇到的一个疑惑. 本来的目的是想使用 C++ 标准线程库中的高级异步操作代替 Qt 线程库中的对应功能. 但在测试过程中发现使用了标准库的版本 “似乎” 效率很低, 低到仿佛不是在进行异步操作. 于是便查阅了一些文章并且做了些测试, 最后发现我这里的主观猜测是错误的. 产生这种错误判断的原因在于标准库与 Qt 库指导思想上的差别导致的实现上的差别, 以至于代码上看似相同的操作可能会得到截然不同的结果.

文中 C++ 标准库源码示例参考 GNU GCC 9.3.0 的实现, Qt 线程库源码示例参考 Qt 5.14.2 MSVC 2017 的实现.

阅读全文 »

本文介绍图像毛玻璃效果算法与一些常见的图像模糊算法, 包括原理介绍, 算法实现, 效率测试. 所有算法均提供基于 Qt 的实现方式与基于 OpenCV 的实现方式(或是 OpenCV 原生功能介绍). 持续更新.

阅读全文 »
0%