最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

如何獲取obs視頻幀的二進(jìn)制數(shù)據(jù)

2023-03-20 10:24 作者:Cpp程序員  | 我要投稿

前面幾篇文章梳理了obs的錄屏和推流流程,幾條縱線整理下來,算是基本理清了obs的工作流程。

現(xiàn)在回到第一個(gè)目標(biāo):捕捉桌面的幀數(shù)據(jù),用rendertarget顯示并輸出到UE5材質(zhì)。

那么,幀數(shù)據(jù)到底存放在哪里?如何讀取?

現(xiàn)在錄屏效率最高的方法,是直接調(diào)用gpu方法去從顯存拿數(shù)據(jù),dx下的方法是AcquireNextFrame函數(shù)。

在整個(gè)工程搜索這個(gè)函數(shù),果然obs在windows下是用這個(gè)方法實(shí)現(xiàn)的錄屏

//obs 錄屏核心代碼//用dx截取當(dāng)前屏幕幀EXPORT bool gs_duplicator_update_frame(gs_duplicator_t *d){ DXGI_OUTDUPL_FRAME_INFO info; ComPtr<ID3D11Texture2D> tex; ComPtr<IDXGIResource> 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; } ? ?//關(guān)鍵步驟,這一步調(diào)用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材質(zhì)到d->duplicator->texture copy_texture(d, tex); d->duplicator->ReleaseFrame(); d->updated = true; return true; }

看到這里,明白了怪不得之前所有結(jié)構(gòu)都找不到圖像幀的二進(jìn)制data數(shù)據(jù)。

因?yàn)閛bs用的都是directX或openGL 的texture來存儲(chǔ)data數(shù)據(jù),這樣做的好處是copy和渲染都直接在顯存操作,避免了內(nèi)存和顯存交換數(shù)據(jù)進(jìn)行的效率損耗。

obs是優(yōu)雅了,但太渾然一體了。導(dǎo)致我想開個(gè)口子從obs拿二進(jìn)制數(shù)據(jù)到Unrea5進(jìn)行渲染就不容易做了,最簡單的辦法就是在obs中增加一個(gè)內(nèi)存數(shù)據(jù)desktopdata,直接掛在obs下面,并增加相應(yīng)的訪問接口。

對(duì)應(yīng)的獲取可以用這個(gè)接口,從顯存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<gs_texture_2d *>(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; }

?

但這樣效率肯定不會(huì)高,因?yàn)閛bs調(diào)用顯存接口錄屏之后, 還需要從顯存往內(nèi)存desktopdata copy一次數(shù)據(jù)。

然后我用desktopdata數(shù)據(jù)再從內(nèi)存copy到Unreal5的顯存,這會(huì)中斷unreal5本身的渲染,去等待我這次copy完成。

有貌似完美的解決方法,如果我把desktopdata創(chuàng)建到顯存,去暫存錄屏數(shù)據(jù),讓unreal5直接訪問顯存的desktopdata,去copy材質(zhì),理論上是完美的,但有一個(gè)最大的雷,obs用的是dx11,unreal5.1用的是dx12,這樣copy感覺會(huì)遇到一些不可測(cè)的風(fēng)險(xiǎn)。

剩下的方法有:

1 不用obs的獲取桌面方法,直接在unreal5里用dx12重寫獲取桌面接口,但也意味著無法使用obs的rtmp推流相關(guān)流程和接口,工作量很大。而且obs最厲害的是音頻和視頻多通道混合,這些都是我想用的。

2 幫obs升級(jí)dx12,這個(gè)可以干,但工作量同樣很大,但比1還是簡單一些。


如何獲取obs視頻幀的二進(jìn)制數(shù)據(jù)的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國家法律
安吉县| 保定市| 大连市| 香格里拉县| 铁力市| 武邑县| 海南省| 留坝县| 修武县| 称多县| 陆河县| 会宁县| 龙井市| 伊宁市| 南溪县| 南安市| 梁山县| 宜昌市| 曲阜市| 平潭县| 吴忠市| 化德县| 中卫市| 东城区| 金堂县| 云梦县| 九江县| 萝北县| 盐边县| 西安市| 织金县| 铁力市| 灵山县| 贵定县| 咸宁市| 桂阳县| 喀喇沁旗| 临江市| 伊吾县| 房山区| 通道|