如何获取obs视频帧的二进制数据

您所在的位置:网站首页 obs捕捉不到 如何获取obs视频帧的二进制数据

如何获取obs视频帧的二进制数据

2023-03-21 14:28| 来源: 网络整理| 查看: 265

前面几篇文章梳理了obs的录屏和推流流程,几条纵线整理下来,算是基本理清了obs的工作流程。

现在回到第一个目标:捕捉桌面的帧数据,用rendertarget显示并输出到UE5材质。

那么,帧数据到底存放在哪里?如何读取?

现在录屏效率最高的方法,是直接调用gpu方法去从显存拿数据,dx下的方法是AcquireNextFrame函数。

在整个工程搜索这个函数,果然obs在windows下是用这个方法实现的录屏

//obs 录屏核心代码 //用dx截取当前屏幕帧 EXPORT bool gs_duplicator_update_frame(gs_duplicator_t *d) { DXGI_OUTDUPL_FRAME_INFO info; ComPtr tex; ComPtr res; HRESULT hr; if (!d->duplicator) { return false; } if (d->updated) { return true; } hr = d->duplicator->AcquireNextFrame(0, &info, res.Assign()); if (hr == DXGI_ERROR_ACCESS_LOST) { return false; } else if (hr == DXGI_ERROR_WAIT_TIMEOUT) { return true; } else if (FAILED(hr)) { blog(LOG_ERROR, "gs_duplicator_update_frame: Failed to update " "frame (%08lX)", hr); return true; } //关键步骤,这一步调用dx查询接口,将屏幕帧写入tex hr = res->QueryInterface(__uuidof(ID3D11Texture2D), (void **)tex.Assign()); if (FAILED(hr)) { blog(LOG_ERROR, "gs_duplicator_update_frame: Failed to query " "ID3D11Texture2D (%08lX)", hr); d->duplicator->ReleaseFrame(); return true; } //copy材质到d->duplicator->texture copy_texture(d, tex); d->duplicator->ReleaseFrame(); d->updated = true; return true; }

看到这里,明白了怪不得之前所有结构都找不到图像帧的二进制data数据。

因为obs用的都是directX或openGL 的texture来存储data数据,这样做的好处是copy和渲染都直接在显存操作,避免了内存和显存交换数据进行的效率损耗。

obs是优雅了,但太浑然一体了。导致我想开个口子从obs拿二进制数据到Unrea5进行渲染就不容易做了,最简单的办法就是在obs中增加一个内存数据desktopdata,直接挂在obs下面,并增加相应的访问接口。

对应的获取可以用这个接口,从显存map地址可供cpu访问

bool gs_texture_map(gs_texture_t *tex, uint8_t **ptr, uint32_t *linesize) { HRESULT hr; if (tex->type != GS_TEXTURE_2D) return false; gs_texture_2d *tex2d = static_cast(tex); D3D11_MAPPED_SUBRESOURCE map; hr = tex2d->device->context->Map(tex2d->texture, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); if (FAILED(hr)) return false; *ptr = (uint8_t *)map.pData; *linesize = map.RowPitch; return true; }

 

但这样效率肯定不会高,因为obs调用显存接口录屏之后, 还需要从显存往内存desktopdata copy一次数据。

然后我用desktopdata数据再从内存copy到Unreal5的显存,这会中断unreal5本身的渲染,去等待我这次copy完成。

有貌似完美的解决方法,如果我把desktopdata创建到显存,去暂存录屏数据,让unreal5直接访问显存的desktopdata,去copy材质,理论上是完美的,但有一个最大的雷,obs用的是dx11,unreal5.1用的是dx12,这样copy感觉会遇到一些不可测的风险。

剩下的方法有:

1 不用obs的获取桌面方法,直接在unreal5里用dx12重写获取桌面接口,但也意味着无法使用obs的rtmp推流相关流程和接口,工作量很大。而且obs最厉害的是音频和视频多通道混合,这些都是我想用的。

2 帮obs升级dx12,这个可以干,但工作量同样很大,但比1还是简单一些。

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3