Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
388 additions
and
84 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
#pragma once | ||
#include "IUnityInterface.h" | ||
|
||
#ifndef __OBJC__ | ||
#error metal plugin is objc code. | ||
#endif | ||
#ifndef __clang__ | ||
#error only clang compiler is supported. | ||
#endif | ||
|
||
@class NSBundle; | ||
@protocol MTLDevice; | ||
@protocol MTLCommandBuffer; | ||
@protocol MTLCommandEncoder; | ||
@protocol MTLTexture; | ||
@class MTLRenderPassDescriptor; | ||
|
||
|
||
UNITY_DECLARE_INTERFACE(IUnityGraphicsMetalV1) | ||
{ | ||
NSBundle* (UNITY_INTERFACE_API * MetalBundle)(); | ||
id<MTLDevice>(UNITY_INTERFACE_API * MetalDevice)(); | ||
|
||
id<MTLCommandBuffer>(UNITY_INTERFACE_API * CurrentCommandBuffer)(); | ||
|
||
// for custom rendering support there are two scenarios: | ||
// you want to use current in-flight MTLCommandEncoder (NB: it might be nil) | ||
id<MTLCommandEncoder>(UNITY_INTERFACE_API * CurrentCommandEncoder)(); | ||
// or you might want to create your own encoder. | ||
// In that case you should end unity's encoder before creating your own and end yours before returning control to unity | ||
void(UNITY_INTERFACE_API * EndCurrentCommandEncoder)(); | ||
|
||
// returns MTLRenderPassDescriptor used to create current MTLCommandEncoder | ||
MTLRenderPassDescriptor* (UNITY_INTERFACE_API * CurrentRenderPassDescriptor)(); | ||
|
||
// converting trampoline UnityRenderBufferHandle into native RenderBuffer | ||
UnityRenderBuffer(UNITY_INTERFACE_API * RenderBufferFromHandle)(void* bufferHandle); | ||
|
||
// access to RenderBuffer's texure | ||
// NB: you pass here *native* RenderBuffer, acquired by calling (C#) RenderBuffer.GetNativeRenderBufferPtr | ||
// AAResolvedTextureFromRenderBuffer will return nil in case of non-AA RenderBuffer or if called for depth RenderBuffer | ||
// StencilTextureFromRenderBuffer will return nil in case of no-stencil RenderBuffer or if called for color RenderBuffer | ||
id<MTLTexture>(UNITY_INTERFACE_API * TextureFromRenderBuffer)(UnityRenderBuffer buffer); | ||
id<MTLTexture>(UNITY_INTERFACE_API * AAResolvedTextureFromRenderBuffer)(UnityRenderBuffer buffer); | ||
id<MTLTexture>(UNITY_INTERFACE_API * StencilTextureFromRenderBuffer)(UnityRenderBuffer buffer); | ||
}; | ||
UNITY_REGISTER_INTERFACE_GUID(0x29F8F3D03833465EULL, 0x92138551C15D823DULL, IUnityGraphicsMetalV1) | ||
|
||
|
||
// deprecated: please use versioned interface above | ||
|
||
UNITY_DECLARE_INTERFACE(IUnityGraphicsMetal) | ||
{ | ||
NSBundle* (UNITY_INTERFACE_API * MetalBundle)(); | ||
id<MTLDevice>(UNITY_INTERFACE_API * MetalDevice)(); | ||
|
||
id<MTLCommandBuffer>(UNITY_INTERFACE_API * CurrentCommandBuffer)(); | ||
id<MTLCommandEncoder>(UNITY_INTERFACE_API * CurrentCommandEncoder)(); | ||
void(UNITY_INTERFACE_API * EndCurrentCommandEncoder)(); | ||
MTLRenderPassDescriptor* (UNITY_INTERFACE_API * CurrentRenderPassDescriptor)(); | ||
|
||
UnityRenderBuffer(UNITY_INTERFACE_API * RenderBufferFromHandle)(void* bufferHandle); | ||
|
||
id<MTLTexture>(UNITY_INTERFACE_API * TextureFromRenderBuffer)(UnityRenderBuffer buffer); | ||
id<MTLTexture>(UNITY_INTERFACE_API * AAResolvedTextureFromRenderBuffer)(UnityRenderBuffer buffer); | ||
id<MTLTexture>(UNITY_INTERFACE_API * StencilTextureFromRenderBuffer)(UnityRenderBuffer buffer); | ||
}; | ||
UNITY_REGISTER_INTERFACE_GUID(0x992C8EAEA95811E5ULL, 0x9A62C4B5B9876117ULL, IUnityGraphicsMetal) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
#include "unity_camera_capturer.h" | ||
|
||
namespace sora { | ||
|
||
bool UnityCameraCapturer::D3D11Impl::Init(UnityContext* context, | ||
void* camera_texture, | ||
int width, | ||
int height) { | ||
context_ = context; | ||
camera_texture_ = camera_texture; | ||
width_ = width; | ||
height_ = height; | ||
|
||
auto device = context->GetDevice(); | ||
if (device == nullptr) { | ||
return false; | ||
} | ||
|
||
// ピクセルデータにアクセスする用のテクスチャを用意する | ||
ID3D11Texture2D* texture = nullptr; | ||
D3D11_TEXTURE2D_DESC desc = {0}; | ||
desc.Width = width; | ||
desc.Height = height; | ||
desc.MipLevels = 1; | ||
desc.ArraySize = 1; | ||
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; | ||
desc.SampleDesc.Count = 1; | ||
desc.Usage = D3D11_USAGE_STAGING; | ||
desc.BindFlags = 0; | ||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; | ||
HRESULT hr = device->CreateTexture2D(&desc, NULL, &texture); | ||
if (!SUCCEEDED(hr)) { | ||
RTC_LOG(LS_ERROR) << "ID3D11Device::CreateTexture2D is failed: hr=" << hr; | ||
return false; | ||
} | ||
|
||
frame_texture_ = texture; | ||
return true; | ||
} | ||
|
||
rtc::scoped_refptr<webrtc::I420Buffer> | ||
UnityCameraCapturer::D3D11Impl::Capture() { | ||
D3D11_MAPPED_SUBRESOURCE resource; | ||
|
||
auto dc = context_->GetDeviceContext(); | ||
if (dc == nullptr) { | ||
RTC_LOG(LS_ERROR) << "ID3D11DeviceContext is null"; | ||
return; | ||
} | ||
|
||
// ピクセルデータが取れない(と思う)ので、カメラテクスチャから自前のテクスチャにコピーする | ||
dc->CopyResource((ID3D11Texture2D*)frame_texture_, | ||
(ID3D11Resource*)camera_texture_); | ||
|
||
HRESULT hr = | ||
dc->Map((ID3D11Resource*)frame_texture_, 0, D3D11_MAP_READ, 0, &resource); | ||
if (!SUCCEEDED(hr)) { | ||
RTC_LOG(LS_ERROR) << "ID3D11DeviceContext::Map is failed: hr=" << hr; | ||
return; | ||
} | ||
|
||
// Windows の場合は座標系の関係で上下反転してるので、頑張って元の向きに戻す | ||
// TODO(melpon): Graphics.Blit を使って効率よく反転させる | ||
// (ref: https://github.com/Unity-Technologies/com.unity.webrtc/blob/a526753e0c18d681d20f3eb9878b9c28442e2bfb/Runtime/Scripts/WebRTC.cs#L264-L268) | ||
std::unique_ptr<uint8_t[]> buf(new uint8_t[width_ * height_ * 4]); | ||
for (int i = 0; i < height_; i++) { | ||
std::memcpy(buf.get() + width_ * 4 * i, | ||
((const uint8_t*)resource.pData) + | ||
resource.RowPitch * (height_ - i - 1), | ||
width_ * 4); | ||
} | ||
|
||
// I420 に変換して VideoFrame 作って OnFrame 呼び出し | ||
//RTC_LOG(LS_INFO) << "GOT FRAME: pData=0x" << resource.pData | ||
// << " RowPitch=" << resource.RowPitch | ||
// << " DepthPitch=" << resource.DepthPitch; | ||
rtc::scoped_refptr<webrtc::I420Buffer> i420_buffer = | ||
webrtc::I420Buffer::Create(width_, height_); | ||
//libyuv::ARGBToI420((const uint8_t*)resource.pData, resource.RowPitch, | ||
// i420_buffer->MutableDataY(), i420_buffer->StrideY(), | ||
// i420_buffer->MutableDataU(), i420_buffer->StrideU(), | ||
// i420_buffer->MutableDataV(), i420_buffer->StrideV(), | ||
// width_, height_); | ||
libyuv::ARGBToI420(buf.get(), width_ * 4, i420_buffer->MutableDataY(), | ||
i420_buffer->StrideY(), i420_buffer->MutableDataU(), | ||
i420_buffer->StrideU(), i420_buffer->MutableDataV(), | ||
i420_buffer->StrideV(), width_, height_); | ||
|
||
dc->Unmap((ID3D11Resource*)frame_texture_, 0); | ||
|
||
return i420_buffer; | ||
} | ||
|
||
} // namespace sora |
Oops, something went wrong.