OBS 源码分析- 采集方案之二 (摄像头采集)

2024-04-25 20:58

本文主要是介绍OBS 源码分析- 采集方案之二 (摄像头采集),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 1、OBS采集方案
  • 2、OBS 摄像头采集
    • 2.1 DirectShow 基础
    • 2.2 OBS 的实现

1、OBS采集方案

obs的视屏录制主要分3种:
窗口采集:采集应用程序窗口
显示器采集:也叫全屏采集,可以采集整个屏幕,当有多个显示器时,可以设置采集其中一个显示器
游戏采集:可以采集游戏窗口

extern struct obs_source_info duplicator_capture_info;
extern struct obs_source_info monitor_capture_info;
extern struct obs_source_info window_capture_info;
extern struct obs_source_info game_capture_info;

2、OBS 摄像头采集

obs 的方案采用 directshow 的方案,如果需要查看源码需要下载submodule, 因为在另外一个仓库。
在这里插入图片描述

2.1 DirectShow 基础

DirectShow 其主要设计目标是通过将应用程序与数据传输的复杂性、硬件差异和同步隔离,简化在 Windows 平台上创建数字媒体应用程序的任务 ,DirectShow简化媒体播放、格式转换和捕获任务

下图显示了应用程序、DirectShow组件以及应用程序支持的一些硬件和软件DirectShow之间的关系。
在这里插入图片描述
在这里插入图片描述
Filter是DirectShow技术体系中最基本的概念。如上图所示,DirectShow中的Filter分成三大类:Source Filter、Transform Filter、Render Filter。Source Filter就是提供数据源的Filter,所有的数据都是从Source Filter流出去的。不管是多媒体文件还是多媒体设备,Source Filter都进行了封装统一了接口,在使用方式上保持了一致。Transform Filter则是对数据进行操作处理的Filter,所有的图像操作都应该在这里进行。而Render Filter则是用来渲染图像的Filter,不管是保存到文件还是输出到其他地方,都由这个Render Filter来实现。Windows系统本身提供了非常多的Filter,我们在开发的时候可以直接使用。

下面是UI 界面配置directshow 软件(graphstudionext)的示意图,通过拖动就可以配置,filter 的概念。而整个图就 Filter Graph。如果需要就向 Filter Graph 添加filter , 并且链接 pin(引脚)
在这里插入图片描述

2.2 OBS 的实现

由于OBS 封装了dshow ,如果比较了解dshow ,那obs也是比较简单的,大家可以看下我整理的类图,帮助理解
类图
在这里插入图片描述

这边只说下,回调的数据接口在什么位置吧。回调接口是通过配置中callback 传进入的。 回调接口是DShowInput::OnVideoData

bool DShowInput::UpdateVideoConfig(obs_data_t *settings) {
videoConfig.name = id.name;videoConfig.path = id.path;videoConfig.useDefaultConfig = resType == ResType_Preferred;videoConfig.cx = cx;videoConfig.cy_abs = abs(cy);videoConfig.cy_flip = cy < 0;videoConfig.frameInterval = interval;videoConfig.internalFormat = format;deviceHasAudio = dev.audioAttached;deviceHasSeparateAudioFilter = dev.separateAudioFilter;//设置回调函数videoConfig.callback = std::bind(&DShowInput::OnVideoData, this,placeholders::_1, placeholders::_2,placeholders::_3, placeholders::_4,placeholders::_5, placeholders::_6);videoConfig.format = videoConfig.internalFormat;if (!device.SetVideoConfig(&videoConfig)) {blog(LOG_WARNING, "%s: device.SetVideoConfig failed",obs_source_get_name(source));return false;}}

最终数据存放到source->async_frames,

static void
obs_source_output_video_internal(obs_source_t *source,const struct obs_source_frame *frame)
{if (!obs_source_valid(source, "obs_source_output_video"))return;if (!frame) {source->async_active = false;return;}struct obs_source_frame *output = cache_video(source, frame);/* ------------------------------------------- */pthread_mutex_lock(&source->async_mutex);if (output) {if (os_atomic_dec_long(&output->refs) == 0) {obs_source_frame_destroy(output);output = NULL;} else {da_push_back(source->async_frames, &output);source->async_active = true;}}pthread_mutex_unlock(&source->async_mutex);
}

在 tick_sources 中 循环调用所有source , obs_source_video_tick中获取视频frame,等待渲染使用

tick_sources ->obs_source_video_tick ->async_tick

static void async_tick(obs_source_t *source)
{uint64_t sys_time = obs->video.video_time;pthread_mutex_lock(&source->async_mutex);if (deinterlacing_enabled(source)) {deinterlace_process_last_frame(source, sys_time);} else {if (source->cur_async_frame) {remove_async_frame(source, source->cur_async_frame);source->cur_async_frame = NULL;}source->cur_async_frame = get_closest_frame(source, sys_time);}source->last_sys_timestamp = sys_time;pthread_mutex_unlock(&source->async_mutex);if (source->cur_async_frame)source->async_update_texture =set_async_texture_size(source, source->cur_async_frame);
}

在这里插入图片描述

这篇关于OBS 源码分析- 采集方案之二 (摄像头采集)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/935770

相关文章

Dubbo之SPI机制的实现原理和优势分析

《Dubbo之SPI机制的实现原理和优势分析》:本文主要介绍Dubbo之SPI机制的实现原理和优势,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Dubbo中SPI机制的实现原理和优势JDK 中的 SPI 机制解析Dubbo 中的 SPI 机制解析总结Dubbo中

C#继承之里氏替换原则分析

《C#继承之里氏替换原则分析》:本文主要介绍C#继承之里氏替换原则,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#里氏替换原则一.概念二.语法表现三.类型检查与转换总结C#里氏替换原则一.概念里氏替换原则是面向对象设计的基本原则之一:核心思想:所有引py

利用Python实现可回滚方案的示例代码

《利用Python实现可回滚方案的示例代码》很多项目翻车不是因为不会做,而是走错了方向却没法回头,技术选型失败的风险我们都清楚,但真正能提前规划“回滚方案”的人不多,本文从实际项目出发,教你如何用Py... 目录描述题解答案(核心思路)题解代码分析第一步:抽象缓存接口第二步:实现两个版本第三步:根据 Fea

SpringBoot实现接口数据加解密的三种实战方案

《SpringBoot实现接口数据加解密的三种实战方案》在金融支付、用户隐私信息传输等场景中,接口数据若以明文传输,极易被中间人攻击窃取,SpringBoot提供了多种优雅的加解密实现方案,本文将从原... 目录一、为什么需要接口数据加解密?二、核心加解密算法选择1. 对称加密(AES)2. 非对称加密(R

基于Go语言实现Base62编码的三种方式以及对比分析

《基于Go语言实现Base62编码的三种方式以及对比分析》Base62编码是一种在字符编码中使用62个字符的编码方式,在计算机科学中,,Go语言是一种静态类型、编译型语言,它由Google开发并开源,... 目录一、标准库现状与解决方案1. 标准库对比表2. 解决方案完整实现代码(含边界处理)二、关键实现细

MySQL精准控制Binlog日志数量的三种方案

《MySQL精准控制Binlog日志数量的三种方案》作为数据库管理员,你是否经常为服务器磁盘爆满而抓狂?Binlog就像数据库的“黑匣子”,默默记录着每一次数据变动,但若放任不管,几天内这些日志文件就... 目录 一招修改配置文件:永久生效的控制术1.定位my.cnf文件2.添加核心参数不重启热更新:高手应

PostgreSQL 序列(Sequence) 与 Oracle 序列对比差异分析

《PostgreSQL序列(Sequence)与Oracle序列对比差异分析》PostgreSQL和Oracle都提供了序列(Sequence)功能,但在实现细节和使用方式上存在一些重要差异,... 目录PostgreSQL 序列(Sequence) 与 oracle 序列对比一 基本语法对比1.1 创建序

MySQL中like模糊查询的优化方案

《MySQL中like模糊查询的优化方案》在MySQL中,like模糊查询是一种常用的查询方式,但在某些情况下可能会导致性能问题,本文将介绍八种优化MySQL中like模糊查询的方法,需要的朋友可以参... 目录1. 避免以通配符开头的查询2. 使用全文索引(Full-text Index)3. 使用前缀索

Python解决雅努斯问题实例方案详解

《Python解决雅努斯问题实例方案详解》:本文主要介绍Python解决雅努斯问题实例方案,雅努斯问题是指AI生成的3D对象在不同视角下出现不一致性的问题,即从不同角度看物体时,物体的形状会出现不... 目录一、雅努斯简介二、雅努斯问题三、示例代码四、解决方案五、完整解决方案一、雅努斯简介雅努斯(Janu

Android实现一键录屏功能(附源码)

《Android实现一键录屏功能(附源码)》在Android5.0及以上版本,系统提供了MediaProjectionAPI,允许应用在用户授权下录制屏幕内容并输出到视频文件,所以本文将基于此实现一个... 目录一、项目介绍二、相关技术与原理三、系统权限与用户授权四、项目架构与流程五、环境配置与依赖六、完整