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

相关文章

Knife4j+Axios+Redis前后端分离架构下的 API 管理与会话方案(最新推荐)

《Knife4j+Axios+Redis前后端分离架构下的API管理与会话方案(最新推荐)》本文主要介绍了Swagger与Knife4j的配置要点、前后端对接方法以及分布式Session实现原理,... 目录一、Swagger 与 Knife4j 的深度理解及配置要点Knife4j 配置关键要点1.Spri

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

MySQL中的表连接原理分析

《MySQL中的表连接原理分析》:本文主要介绍MySQL中的表连接原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、环境3、表连接原理【1】驱动表和被驱动表【2】内连接【3】外连接【4编程】嵌套循环连接【5】join buffer4、总结1、背景

SQLite3 在嵌入式C环境中存储音频/视频文件的最优方案

《SQLite3在嵌入式C环境中存储音频/视频文件的最优方案》本文探讨了SQLite3在嵌入式C环境中存储音视频文件的优化方案,推荐采用文件路径存储结合元数据管理,兼顾效率与资源限制,小文件可使用B... 目录SQLite3 在嵌入式C环境中存储音频/视频文件的专业方案一、存储策略选择1. 直接存储 vs

python中Hash使用场景分析

《python中Hash使用场景分析》Python的hash()函数用于获取对象哈希值,常用于字典和集合,不可变类型可哈希,可变类型不可,常见算法包括除法、乘法、平方取中和随机数哈希,各有优缺点,需根... 目录python中的 Hash除法哈希算法乘法哈希算法平方取中法随机数哈希算法小结在Python中,

Java Stream的distinct去重原理分析

《JavaStream的distinct去重原理分析》Javastream中的distinct方法用于去除流中的重复元素,它返回一个包含过滤后唯一元素的新流,该方法会根据元素的hashcode和eq... 目录一、distinct 的基础用法与核心特性二、distinct 的底层实现原理1. 顺序流中的去重

Python如何将OpenCV摄像头视频流通过浏览器播放

《Python如何将OpenCV摄像头视频流通过浏览器播放》:本文主要介绍Python如何将OpenCV摄像头视频流通过浏览器播放的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完... 目录方法1:使用Flask + MJPEG流实现代码使用方法优点缺点方法2:使用WebSocket传输视

关于MyISAM和InnoDB对比分析

《关于MyISAM和InnoDB对比分析》:本文主要介绍关于MyISAM和InnoDB对比分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录开篇:从交通规则看存储引擎选择理解存储引擎的基本概念技术原理对比1. 事务支持:ACID的守护者2. 锁机制:并发控制的艺

SpringBoot服务获取Pod当前IP的两种方案

《SpringBoot服务获取Pod当前IP的两种方案》在Kubernetes集群中,SpringBoot服务获取Pod当前IP的方案主要有两种,通过环境变量注入或通过Java代码动态获取网络接口IP... 目录方案一:通过 Kubernetes Downward API 注入环境变量原理步骤方案二:通过

Springboot3+将ID转为JSON字符串的详细配置方案

《Springboot3+将ID转为JSON字符串的详细配置方案》:本文主要介绍纯后端实现Long/BigIntegerID转为JSON字符串的详细配置方案,s基于SpringBoot3+和Spr... 目录1. 添加依赖2. 全局 Jackson 配置3. 精准控制(可选)4. OpenAPI (Spri