obs directx11

创建逻辑

obs 在windows 下分为Opengl 和 directx 两种渲染模式,默认使用的是directx ,兼容性更好;

代码路径:

E:\opensrc\obs_studio_src\obs-studio\UI\obs-app.cpp  选择渲染模式

const char* OBSApp::GetRenderModule() const {const char* renderer = config_get_string(appConfig, "Video", "Renderer");return (astrcmpi(renderer, "Direct3D 11") == 0) ? DL_D3D11 : DL_OPENGL;
}

 在ResetVideo中通过obs_video_info ovi 参数graphics_module 传递到底层

int OBSBasic::ResetVideo()
{if (outputHandler && outputHandler->Active())return OBS_VIDEO_CURRENTLY_ACTIVE;ProfileScope("OBSBasic::ResetVideo");struct obs_video_info ovi;int ret;GetConfigFPS(ovi.fps_num, ovi.fps_den);const char *colorFormat = config_get_string(activeConfiguration, "Video", "ColorFormat");const char *colorSpace = config_get_string(activeConfiguration, "Video", "ColorSpace");const char *colorRange = config_get_string(activeConfiguration, "Video", "ColorRange");ovi.graphics_module = App()->GetRenderModule();

 gs_create(&video->graphics, ovi->graphics_module, ovi->adapter) 通过graphics_module load对应的动态库

static int obs_init_graphics(struct obs_video_info *ovi)
{struct obs_core_video *video = &obs->video;uint8_t transparent_tex_data[2 * 2 * 4] = {0};const uint8_t *transparent_tex = transparent_tex_data;struct gs_sampler_info point_sampler = {0};bool success = true;int errorcode;profile_start(obs_init_graphics_name);errorcode = gs_create(&video->graphics, ovi->graphics_module, ovi->adapter);

gs_create 完成设备的创建

int gs_create(graphics_t **pgraphics, const char *module, uint32_t adapter)
{int errcode = GS_ERROR_FAIL;graphics_t *graphics = bzalloc(sizeof(struct graphics_subsystem));pthread_mutex_init_value(&graphics->mutex);pthread_mutex_init_value(&graphics->effect_mutex);//动态库  libobs-d3d11.dllgraphics->module = os_dlopen(module);if (!graphics->module) {errcode = GS_ERROR_MODULE_NOT_FOUND;goto error;}if (!load_graphics_imports(&graphics->exports, graphics->module, module))goto error;//创建设备errcode = graphics->exports.device_create(&graphics->device, adapter);if (errcode != GS_SUCCESS)goto error;if (!graphics_init(graphics)) {errcode = GS_ERROR_FAIL;goto error;}*pgraphics = graphics;return errcode;error:gs_destroy(graphics);return errcode;
}

E:\opensrc\obs_studio_src\obs-studio\libobs-d3d11\d3d11-subsystem.cpp

走到d3d11 走的创建设备逻辑

int device_create(gs_device_t **p_device, uint32_t adapter)
{gs_device *device = NULL;int errorcode = GS_SUCCESS;try {blog(LOG_INFO, "---------------------------------");blog(LOG_INFO, "Initializing D3D11...");LogD3DAdapters();CreateShaderCacheDirectory();device = new gs_device(adapter);} catch (const UnsupportedHWError &error) {blog(LOG_ERROR, "device_create (D3D11): %s (%08lX)", error.str, error.hr);errorcode = GS_ERROR_NOT_SUPPORTED;} catch (const HRError &error) {blog(LOG_ERROR, "device_create (D3D11): %s (%08lX)", error.str, error.hr);errorcode = GS_ERROR_FAIL;}*p_device = device;return errorcode;
}
gs_device::gs_device(uint32_t adapterIdx) : curToplogy(D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED)
{matrix4_identity(&curProjMatrix);matrix4_identity(&curViewMatrix);matrix4_identity(&curViewProjMatrix);memset(&viewport, 0, sizeof(viewport));for (size_t i = 0; i < GS_MAX_TEXTURES; i++) {curTextures[i] = NULL;curSamplers[i] = NULL;}InitFactory();InitAdapter(adapterIdx);InitDevice(adapterIdx);device_set_render_target(this, NULL, NULL);
}

渲染逻辑

通过qtobsdisplay 的CreateDisplay获得到原生窗口句柄 ;并且将句柄最终设置到交换链中desc.OutputWindow = hwnd

static inline enum gs_color_space make_swap_desc(gs_device *device, DXGI_SWAP_CHAIN_DESC &desc,const gs_init_data *data, DXGI_SWAP_EFFECT effect, UINT flags)
{const HWND hwnd = (HWND)data->window.hwnd;const enum gs_color_space space = get_next_space(device, hwnd, effect);const gs_color_format format = get_swap_format_from_space(space, data->format);memset(&desc, 0, sizeof(desc));desc.BufferDesc.Width = data->cx;desc.BufferDesc.Height = data->cy;desc.BufferDesc.Format = ConvertGSTextureFormatView(format);desc.SampleDesc.Count = 1;desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;desc.BufferCount = data->num_backbuffers;desc.OutputWindow = hwnd;desc.Windowed = TRUE;desc.SwapEffect = effect;desc.Flags = flags;return space;
}

OBSQTDisplay  中通过  OBSDisplay display;

using OBSDisplay = OBSPtr<obs_display_t *, obs_display_destroy>;

与底层沟通:

void OBSQTDisplay::CreateDisplay()
{if (display)return;if (destroying)return;if (!windowHandle()->isExposed())return;QSize size = GetPixelSize(this);gs_init_data info = {};info.cx = size.width();info.cy = size.height();info.format = GS_BGRA;info.zsformat = GS_ZS_NONE;if (!QTToGSWindow(windowHandle(), info.window))return;//创建 displaydisplay = obs_display_create(&info, backgroundColor);emit DisplayCreated(this);
}obs_display_t *obs_display_create(const struct gs_init_data *graphics_data, uint32_t background_color)
{struct obs_display *display = bzalloc(sizeof(struct obs_display));gs_enter_context(obs->video.graphics);display->background_color = background_color;//创建交换链if (!obs_display_init(display, graphics_data)) {obs_display_destroy(display);display = NULL;} else {pthread_mutex_lock(&obs->data.displays_mutex);display->prev_next = &obs->data.first_display;display->next = obs->data.first_display;obs->data.first_display = display;if (display->next)display->next->prev_next = &display->next;pthread_mutex_unlock(&obs->data.displays_mutex);}gs_leave_context();return display;
}

当发生原生创建的resizeEvent事件时:

void OBSQTDisplay::resizeEvent(QResizeEvent *event)
{QWidget::resizeEvent(event);CreateDisplay();if (isVisible() && display) {QSize size = GetPixelSize(this);obs_display_resize(display, size.width(), size.height());}emit DisplayResized();
}

通过obs_display_resize 接口更新渲染尺寸

void obs_display_resize(obs_display_t *display, uint32_t cx, uint32_t cy)
{if (!display)return;pthread_mutex_lock(&display->draw_info_mutex);display->next_cx = cx;display->next_cy = cy;pthread_mutex_unlock(&display->draw_info_mutex);
}

因此在graphics thread线程的render_display函数中

void render_display(struct obs_display *display)
{uint32_t cx, cy;bool update_color_space;if (!display || !display->enabled)return;/* -------------------------------------------- */pthread_mutex_lock(&display->draw_info_mutex);//渲染尺寸cx = display->next_cx;cy = display->next_cy;update_color_space = display->update_color_space;display->update_color_space = false;pthread_mutex_unlock(&display->draw_info_mutex);/* -------------------------------------------- *///d3d 渲染接口if (render_display_begin(display, cx, cy, update_color_space)) {GS_DEBUG_MARKER_BEGIN(GS_DEBUG_COLOR_DISPLAY, "obs_display");pthread_mutex_lock(&display->draw_callbacks_mutex);for (size_t i = 0; i < display->draw_callbacks.num; i++) {struct draw_callback *callback;callback = display->draw_callbacks.array + i;//上层回调通知callback->draw(callback->param, cx, cy);}pthread_mutex_unlock(&display->draw_callbacks_mutex);render_display_end();GS_DEBUG_MARKER_END();gs_present();}
}最终调用到 render_display_begin 设置渲染视口
void device_set_viewport(gs_device_t *device, int x, int y, int width, int height)
{D3D11_VIEWPORT vp;memset(&vp, 0, sizeof(vp));vp.MaxDepth = 1.0f;vp.TopLeftX = (float)x;vp.TopLeftY = (float)y;vp.Width = (float)width;vp.Height = (float)height;device->context->RSSetViewports(1, &vp);device->viewport.x = x;device->viewport.y = y;device->viewport.cx = width;device->viewport.cy = height;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/891946.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QT实现 端口扫描暂停和继续功能 3

上篇QT给端口扫描工程增加线程2-CSDN博客 为按钮pushButton_Stop添加clicked事件&#xff0c;功能为暂停扫描&#xff0c;并在暂停后显示继续按钮&#xff0c;点击继续按钮之后继续扫描 1.更新UI 添加继续按钮 点击转到槽则会自动声明 2. 更新 MainWindow.h 需要新增的部分…

nginx-限流(请求/并发量)

一. 简述&#xff1a; 在做日常的web运维工作中&#xff0c;难免会遇到服务器流量异常&#xff0c;负载过大等情况。恶意攻击访问/爬虫等非正常性请求&#xff0c;会带来带宽的浪费&#xff0c;服务器压力增大&#xff0c;影响业务质量。 二. 限流方案&#xff1a; 对于这种情…

分布式ID生成-雪花算法实现无状态

雪花算法这里不再赘述&#xff0c;其缺点是有状态&#xff08;多副本隔离时&#xff0c;依赖手动配置workId和datacenterId&#xff09;&#xff0c;代码如下&#xff1a; /*** 雪花算法ID生成器*/ public class SnowflakeIdWorker {/*** 开始时间截 (2017-01-01)*/private st…

Edge SCDN高效防护与智能加速

当今数字化时代&#xff0c;网络安全和内容分发效率已成为企业业务发展的关键因素。酷盾安全推出了Edge SCDN解决方案&#xff0c;为企业提供全方位的安全防护和高效的内容分发服务。 一、卓越的安全防护能力 1.DDoS攻击的精准防御&#xff1a;Edge SCDN具备强大的DDoS攻击检测…

在vscode上

第一步 安装插件 &#xff08;1&#xff09;从菜单处打开vscode&#xff0c;之后点击左侧“拓展”&#xff0c;在搜索栏输入“platform”&#xff0c;安装这个插件。 注&#xff1a;安装过程可能会慢一点&#xff0c;可以尝试连接自己的热点 &#xff08;2&#xff09;安装完…

产品心、用户脑、押重注......解读vivo穿越周期之道

出品 | 何玺 排版 | 叶媛 国内科技企业中&#xff0c;vivo绝对算个“异类”。给人以平和谦逊、稳健踏实的印象&#xff0c;却极具实力&#xff01; 回望vivo发展历程&#xff0c;这家拥有近30年历史的超大型全球化产业科技生态型公司&#xff0c;从功能机到智能机一路走来&am…

jenkins入门4 --window执行execute shell

1、启动关闭jenkins 在Windows环境下&#xff0c;如果你需要关闭Jenkins服务&#xff0c;可以通过以下几种方式&#xff1a; 1、使用Windows服务管理器&#xff1a; 打开“运行”对话框&#xff08;Win R&#xff09;&#xff0c;输入services.msc&#xff0c;然后回车。 在服…

矩阵碰一碰发视频源码搭建全解析,支持OEM

在数字化营销与互动体验需求日益增长的当下&#xff0c;矩阵碰一碰发视频功能以其独特的交互性和高效的信息传播能力&#xff0c;正逐渐成为吸引用户、提升品牌影响力的有力工具。本文将深入探讨如何搭建矩阵碰一碰发视频的源码&#xff0c;帮助开发者实现这一创新功能。 一、技…

软件确认测试和验收测试有什么区别?

在当今快速发展的软件行业中&#xff0c;软件确认测试与验收测试是软件产品生产周期中的重要步骤&#xff0c;但很多人容易混淆&#xff0c;那么这两者之间究竟有什么区别呢? 软件确认测试是一个旨在确保软件产品符合用户需求规格的过程。它对软件的功能、性能和可用性进行深…

cat命令详解

cat 是 Linux/Unix 中的一个非常常用的命令&#xff0c;主要用于 连接 文件并显示文件内容。它的名称来源于 concatenate&#xff08;连接&#xff09;&#xff0c;不仅可以查看文件内容&#xff0c;还能将多个文件合并为一个文件&#xff0c;或用作其他数据流操作。 以下是对 …

[sdx12] Qualcomm SDX12查看基线版本

about.html文件 Build部分 Product SDX12.LE.1.0-00263-NBOOT.NEFS.PROD-1.90789.1 Distribution SDX12.LE.1.0|AMSS|Standard|OEM: Build Components部分 从以上截图可以看到以下模块的版本号及格式 BOOT 基线版本号 BOOT.BF.3.1.c3-00010-SDX12AAAAANAZB-1 Distr…

基于CLIP和DINOv2实现图像相似性方面的比较

概述 在人工智能领域&#xff0c;CLIP和DINOv2是计算机视觉领域的两大巨头。CLIP彻底改变了图像理解&#xff0c;而DINOv2为自监督学习带来了新的方法。 在本文中&#xff0c;我们将踏上一段旅程&#xff0c;揭示定义CLIP和DINOv2的优势和微妙之处。我们的目标是发现这些模型…

LS1046 XFI网口接近10Gbps

硬件平台&#xff1a; CPU LS1046A 1.8GHZ 软件平台&#xff1a; LINUX 4.19.32 BUILDROOT 测试软件&#xff1a; ipferf 整个过程比较曲折&#xff0c;网口默认不能达到这个速度&#xff0c;只有2Gbps以内。需要FMC配置后才能达到9.4Gbps。

一则问答:211集成电路专业,转互联网还是FPGA?

问&#xff1a; 我于2016年毕业于西安电子科技大学集成电路设计与集成系统专业。毕业后&#xff0c;我在一家不知名私企从事PCB绘制和单片机调试工作&#xff0c;持续了一年半。之后&#xff0c;我受律师职业光鲜外表的吸引&#xff0c;尝试了两年的司法考试&#xff0c;但未能…

嵌入式linux系统中QT信号与槽实现

第一:Qt中信号与槽简介 信号与槽是Qt编程的基础。因为有了信号与槽的编程机制,在Qt中处理界面各个组件的交互操作时变得更加直观和简单。 槽函数与一般的函数不同的是:槽函数可以与一个信号关联,当信号被发射时,关联的槽函数被自动执行。 案例操作与实现: #ifndef …

Java Web开发进阶——Spring Boot基础

Spring Boot是基于Spring框架的新一代开发框架&#xff0c;旨在通过自动化配置和简化的开发方式提升生产效率。它将复杂的配置抽象化&#xff0c;让开发者专注于业务逻辑实现&#xff0c;而无需关注繁琐的基础配置。 1. Spring Boot简介与优势 Spring Boot 是 Spring 家族中的…

探索 ES6 Set:用法与实战

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

使用SSH建立内网穿透,能够访问内网的web服务器

搞了一个晚上&#xff0c;终于建立了一个内网穿透。和AI配合&#xff0c;还是得自己思考&#xff0c;AI配合才能搞定&#xff0c;不思考只依赖AI也不行。内网服务器只是简单地使用了python -m http.server 8899&#xff0c;但是对于Gradio建立的服务器好像不行&#xff0c;会出…

回归预测 | MATLAB实现CNN-BiLSTM-Attention多输入单输出回归预测

回归预测 | MATLAB实现CNN-BiLSTM-Attention多输入单输出回归预测 目录 回归预测 | MATLAB实现CNN-BiLSTM-Attention多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 一、方法概述 CNN-BiLSTM-Attention多输入单输出回归预测方法旨在通过融合CNN的局…

动态库dll与静态库lib编程4:MFC规则DLL讲解

文章目录 前言一、说明二、具体实现2.1新建项目2.2 模块切换的演示 总结 前言 动态库dll与静态库lib编程4&#xff1a;MFC规则DLL讲解。 一、说明 1.前面介绍的均为Win32DLL&#xff0c;即不使用MFC的DLL。 2.MFC规则DLL的特点&#xff1a;DLL内部可以使用MFC类库、可以被其他…