Skip to content
This repository was archived by the owner on Oct 25, 2024. It is now read-only.

Commit f697bf6

Browse files
committed
Use D3D9 for rendering if source is SW decoder.
1 parent c6c35d8 commit f697bf6

File tree

5 files changed

+185
-20
lines changed

5 files changed

+185
-20
lines changed

talk/owt/sdk/base/win/msdkvideodecoderfactory.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,11 @@ std::unique_ptr<webrtc::VideoDecoder> MSDKVideoDecoderFactory::CreateVideoDecode
8686
}
8787
#endif
8888
}
89-
if (absl::EqualsIgnoreCase(format.name, cricket::kVp9CodecName) && !vp9_hw) {
89+
if (absl::EqualsIgnoreCase(format.name, cricket::kVp9CodecName) /*&& !vp9_hw*/) {
9090
return webrtc::VP9Decoder::Create();
9191
} else if (absl::EqualsIgnoreCase(format.name, cricket::kVp8CodecName) &&
9292
!vp8_hw) {
93+
RTC_LOG(LS_ERROR) << "Not supporting HW VP8 decoder. Requesting SW:";
9394
return webrtc::VP8Decoder::Create();
9495
} else if (absl::EqualsIgnoreCase(format.name, cricket::kH264CodecName) && !h264_hw) {
9596
return webrtc::H264Decoder::Create();

talk/owt/sdk/base/win/msdkvideoencoderfactory.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ std::unique_ptr<webrtc::VideoEncoder> MSDKVideoEncoderFactory::CreateVideoEncode
9191
if (absl::EqualsIgnoreCase(format.name, cricket::kVp8CodecName) && !vp8_hw)
9292
return webrtc::VP8Encoder::Create();
9393
// VP9 encoding will only be enabled on ICL+;
94-
else if (absl::EqualsIgnoreCase(format.name, cricket::kVp9CodecName) &&
95-
!vp9_hw)
94+
else if (absl::EqualsIgnoreCase(format.name, cricket::kVp9CodecName)/* &&
95+
!vp9_hw*/)
9696
return webrtc::VP9Encoder::Create(cricket::VideoCodec(format));
9797
// TODO: Replace with AV1 HW encoder post TGL.
9898
else if (absl::EqualsIgnoreCase(format.name, cricket::kAv1CodecName) &&

talk/owt/sdk/base/win/videorendererd3d11.cc

Lines changed: 149 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@
1212

1313
// No. of vertices to draw a 3D QUAD
1414
static const UINT num_vertices = 6;
15+
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_TEX1)
16+
struct D3dCustomVertex {
17+
float x, y, z;
18+
float u, v;
19+
};
1520

1621
using namespace rtc;
1722
namespace owt {
@@ -42,6 +47,12 @@ void WebrtcVideoRendererD3D11Impl::FillSwapChainDesc(
4247

4348
void WebrtcVideoRendererD3D11Impl::OnFrame(
4449
const webrtc::VideoFrame& video_frame) {
50+
uint16_t width = video_frame.video_frame_buffer()->width();
51+
uint16_t height = video_frame.video_frame_buffer()->height();
52+
53+
if (width == 0 || height == 0)
54+
return;
55+
4556
if (video_frame.video_frame_buffer()->type() ==
4657
webrtc::VideoFrameBuffer::Type::kNative) {
4758
D3D11ImageHandle* native_handle =
@@ -68,15 +79,10 @@ void WebrtcVideoRendererD3D11Impl::OnFrame(
6879
else
6980
return;
7081

71-
uint16_t width = video_frame.video_frame_buffer()->width();
72-
uint16_t height = video_frame.video_frame_buffer()->height();
73-
74-
if (width == 0 || height == 0)
75-
return;
76-
7782
width_ = width;
7883
height_ = height;
7984

85+
8086
if (render_device != d3d11_device_) {
8187
d3d11_device_ = render_device;
8288
need_swapchain_recreate_ = true;
@@ -99,10 +105,147 @@ void WebrtcVideoRendererD3D11Impl::OnFrame(
99105
RenderToBackbuffer(array_slice);
100106
}
101107
} else { // I420 frame passed.
108+
if (!d3d9_inited_for_raw_) {
109+
m_d3d_ = Direct3DCreate9(D3D_SDK_VERSION);
110+
if (!m_d3d_)
111+
return;
112+
113+
D3DPRESENT_PARAMETERS d3d_params = {};
114+
115+
d3d_params.Windowed = true;
116+
d3d_params.SwapEffect = D3DSWAPEFFECT_COPY;
117+
118+
IDirect3DDevice9* d3d_device;
119+
if (m_d3d_->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd_,
120+
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3d_params,
121+
&d3d_device) != D3D_OK) {
122+
Destroy();
123+
return;
124+
}
125+
m_d3d_device_ = d3d_device;
126+
d3d_device->Release();
127+
128+
IDirect3DVertexBuffer9* vertex_buffer;
129+
const int kRectVertices = 4;
130+
if (m_d3d_device_->CreateVertexBuffer(
131+
kRectVertices * sizeof(D3dCustomVertex), 0, D3DFVF_CUSTOMVERTEX,
132+
D3DPOOL_MANAGED, &vertex_buffer, nullptr) != D3D_OK) {
133+
Destroy();
134+
return;
135+
}
136+
m_vertex_buffer_ = vertex_buffer;
137+
vertex_buffer->Release();
138+
139+
m_d3d_device_->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
140+
m_d3d_device_->SetRenderState(D3DRS_LIGHTING, FALSE);
141+
ResizeD3D9RenderPipeline(video_frame.width(), video_frame.height());
142+
d3d9_inited_for_raw_ = true;
143+
} else {
144+
HRESULT hr = m_d3d_device_->TestCooperativeLevel();
145+
if (FAILED(hr)) {
146+
if (hr == D3DERR_DEVICELOST) {
147+
RTC_LOG(LS_WARNING) << "Device lost.";
148+
} else if (hr == D3DERR_DEVICENOTRESET) {
149+
Destroy();
150+
RTC_LOG(LS_WARNING) << "Device try to reinit.";
151+
} else {
152+
RTC_LOG(LS_WARNING) << "Device driver internal error.";
153+
}
154+
155+
return;
156+
}
157+
158+
if (static_cast<size_t>(video_frame.width()) != width_ ||
159+
static_cast<size_t>(video_frame.height()) != height_) {
160+
ResizeD3D9RenderPipeline(static_cast<size_t>(video_frame.width()),
161+
static_cast<size_t>(video_frame.height()));
162+
}
163+
D3DLOCKED_RECT lock_rect;
164+
if (m_texture_->LockRect(0, &lock_rect, nullptr, 0) != D3D_OK)
165+
return;
166+
167+
ConvertFromI420(video_frame, webrtc::VideoType::kARGB, 0,
168+
static_cast<uint8_t*>(lock_rect.pBits));
169+
m_texture_->UnlockRect(0);
170+
171+
m_d3d_device_->BeginScene();
172+
m_d3d_device_->SetFVF(D3DFVF_CUSTOMVERTEX);
173+
m_d3d_device_->SetStreamSource(0, m_vertex_buffer_, 0,
174+
sizeof(D3dCustomVertex));
175+
m_d3d_device_->SetTexture(0, m_texture_);
176+
m_d3d_device_->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
177+
m_d3d_device_->EndScene();
178+
179+
m_d3d_device_->Present(nullptr, nullptr, wnd_, nullptr);
180+
}
102181
}
103182
return;
104183
}
105184

185+
void WebrtcVideoRendererD3D11Impl::ResizeD3D9RenderPipeline(size_t width, size_t height) {
186+
width_ = width;
187+
height_ = height;
188+
IDirect3DTexture9* texture;
189+
m_d3d_device_->CreateTexture(static_cast<UINT>(width_),
190+
static_cast<UINT>(height_), 1, 0, D3DFMT_A8R8G8B8,
191+
D3DPOOL_MANAGED, &texture, nullptr);
192+
m_texture_ = texture;
193+
texture->Release();
194+
195+
// Vertices for the video frame to be rendered to.
196+
static const D3dCustomVertex rect[] = {
197+
{-1.0f, -1.0f, 0.0f, 0.0f, 1.0f},
198+
{-1.0f, 1.0f, 0.0f, 0.0f, 0.0f},
199+
{1.0f, -1.0f, 0.0f, 1.0f, 1.0f},
200+
{1.0f, 1.0f, 0.0f, 1.0f, 0.0f},
201+
};
202+
203+
void* buf_data = nullptr;
204+
if (m_vertex_buffer_->Lock(0, 0, &buf_data, 0) != D3D_OK)
205+
return;
206+
207+
CopyMemory(buf_data, &rect, sizeof(rect));
208+
m_vertex_buffer_->Unlock();
209+
}
210+
211+
HRESULT WebrtcVideoRendererD3D11Impl::CreateD3D11Device() {
212+
HRESULT hr = S_OK;
213+
214+
static D3D_FEATURE_LEVEL feature_levels[] = {
215+
D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1,
216+
D3D_FEATURE_LEVEL_10_1};
217+
D3D_FEATURE_LEVEL feature_levels_out;
218+
219+
hr = D3D11CreateDevice(
220+
nullptr, D3D_DRIVER_TYPE_UNKNOWN, nullptr, 0, feature_levels,
221+
sizeof(feature_levels) / sizeof(feature_levels[0]), D3D11_SDK_VERSION,
222+
&d3d11_device_, &feature_levels_out, &d3d11_device_context_);
223+
if (FAILED(hr)) {
224+
RTC_LOG(LS_ERROR) << "Failed to create d3d11 device for decoder";
225+
return false;
226+
}
227+
228+
// Create the surface to copy NV12 image to.
229+
D3D11_TEXTURE2D_DESC texture_desc;
230+
memset(&texture_desc, 0, sizeof(texture_desc));
231+
texture_desc.Format = DXGI_FORMAT_NV12;
232+
texture_desc.Width = width_;
233+
texture_desc.Height = height_;
234+
texture_desc.ArraySize = 1;
235+
texture_desc.MipLevels = 1;
236+
texture_desc.Usage = D3D11_USAGE_DYNAMIC;
237+
texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
238+
texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
239+
240+
hr = d3d11_device_->CreateTexture2D(&texture_desc, nullptr,
241+
&sw_shared_texture_);
242+
if (FAILED(hr)) {
243+
RTC_LOG(LS_ERROR)
244+
<< "Failed to create shared texture to copy nv12 frame to.";
245+
return hr;
246+
}
247+
}
248+
106249
// Method to create the necessary 3D pipeline objects to render a textured 3D
107250
// QUAD
108251
HRESULT WebrtcVideoRendererD3D11Impl::CreateRenderPipeline() {

talk/owt/sdk/base/win/videorendererd3d11.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,14 @@
88
#include <windows.h>
99
#include <atlbase.h>
1010
#include <combaseapi.h>
11+
#include <d3d9.h>
12+
#include <d3d9types.h>
1113
#include <d3d11.h>
1214
#include <d3d11_1.h>
1315
#include <dxgi1_2.h>
1416
#include <dxgi1_4.h>
1517
#include <dxgi1_5.h>
18+
#include <dxgiformat.h>
1619
#include <psapi.h>
1720
#include "talk/owt/sdk/base/win/shader.h"
1821
#include <vector>
@@ -57,8 +60,11 @@ class WebrtcVideoRendererD3D11Impl
5760
void Destroy();
5861
void FillSwapChainDesc(DXGI_SWAP_CHAIN_DESC1& scd);
5962
void ResetTextureViews();
63+
HRESULT CreateD3D11Device();
64+
void WriteNV12ToTexture();
6065
HRESULT CreateRenderPipeline();
6166
HRESULT ResizeRenderPipeline();
67+
void ResizeD3D9RenderPipeline(size_t width, size_t height);
6268
HRESULT CreateTextureView(ID3D11Texture2D* texture, int array_slice);
6369
void RenderToBackbuffer(int array_slice);
6470
void InitializeSRVDesc(D3D11_SHADER_RESOURCE_VIEW_DESC& desc,
@@ -95,6 +101,14 @@ class WebrtcVideoRendererD3D11Impl
95101
ID3D11PixelShader* pixel_shader_ = nullptr;
96102
ID3D11InputLayout* input_layout_ = nullptr;
97103
ID3D11Buffer* vertex_buffer_ = nullptr;
104+
ID3D11Texture2D* sw_shared_texture_ = nullptr;
105+
106+
// Using D3D9 for rendering SW frames.
107+
bool d3d9_inited_for_raw_ = false;
108+
rtc::scoped_refptr<IDirect3D9> m_d3d_;
109+
rtc::scoped_refptr<IDirect3DDevice9> m_d3d_device_;
110+
rtc::scoped_refptr<IDirect3DTexture9> m_texture_;
111+
rtc::scoped_refptr<IDirect3DVertexBuffer9> m_vertex_buffer_;
98112
UINT views_count = 0;
99113
};
100114
} // namespace base

talk/owt/sdk/p2p/p2ppeerconnectionchannel.cc

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -475,16 +475,6 @@ void P2PPeerConnectionChannel::OnMessageSignal(Json::Value& message) {
475475
RTC_LOG(LS_ERROR) << "Error parsing local description.";
476476
RTC_DCHECK(false);
477477
}
478-
std::vector<AudioCodec> audio_codecs;
479-
for (auto& audio_enc_param : configuration_.audio) {
480-
audio_codecs.push_back(audio_enc_param.codec.name);
481-
}
482-
sdp_string = SdpUtils::SetPreferAudioCodecs(sdp_string, audio_codecs);
483-
std::vector<VideoCodec> video_codecs;
484-
for (auto& video_enc_param : configuration_.video) {
485-
video_codecs.push_back(video_enc_param.codec.name);
486-
}
487-
sdp_string = SdpUtils::SetPreferVideoCodecs(sdp_string, video_codecs);
488478
std::unique_ptr<webrtc::SessionDescriptionInterface> new_desc(
489479
webrtc::CreateSessionDescription(desc->type(), sdp_string, nullptr));
490480
// Sychronous call. After done, will invoke OnSetRemoteDescription. If
@@ -757,7 +747,24 @@ void P2PPeerConnectionChannel::OnCreateSessionDescriptionSuccess(
757747
std::bind(
758748
&P2PPeerConnectionChannel::OnSetLocalSessionDescriptionFailure,
759749
this, std::placeholders::_1));
760-
peer_connection_->SetLocalDescription(observer, desc);
750+
std::string sdp_string;
751+
if (!desc->ToString(&sdp_string)) {
752+
RTC_LOG(LS_ERROR) << "Error parsing local description.";
753+
RTC_DCHECK(false);
754+
}
755+
std::vector<AudioCodec> audio_codecs;
756+
for (auto& audio_enc_param : configuration_.audio) {
757+
audio_codecs.push_back(audio_enc_param.codec.name);
758+
}
759+
sdp_string = SdpUtils::SetPreferAudioCodecs(sdp_string, audio_codecs);
760+
std::vector<VideoCodec> video_codecs;
761+
for (auto& video_enc_param : configuration_.video) {
762+
video_codecs.push_back(video_enc_param.codec.name);
763+
}
764+
sdp_string = SdpUtils::SetPreferVideoCodecs(sdp_string, video_codecs);
765+
webrtc::SessionDescriptionInterface* new_desc(
766+
webrtc::CreateSessionDescription(desc->type(), sdp_string, nullptr));
767+
peer_connection_->SetLocalDescription(observer, new_desc);
761768
}
762769
void P2PPeerConnectionChannel::OnCreateSessionDescriptionFailure(
763770
const std::string& error) {

0 commit comments

Comments
 (0)