12
12
13
13
// No. of vertices to draw a 3D QUAD
14
14
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
+ };
15
20
16
21
using namespace rtc ;
17
22
namespace owt {
@@ -42,6 +47,12 @@ void WebrtcVideoRendererD3D11Impl::FillSwapChainDesc(
42
47
43
48
void WebrtcVideoRendererD3D11Impl::OnFrame (
44
49
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
+
45
56
if (video_frame.video_frame_buffer ()->type () ==
46
57
webrtc::VideoFrameBuffer::Type::kNative ) {
47
58
D3D11ImageHandle* native_handle =
@@ -68,15 +79,10 @@ void WebrtcVideoRendererD3D11Impl::OnFrame(
68
79
else
69
80
return ;
70
81
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
-
77
82
width_ = width;
78
83
height_ = height;
79
84
85
+
80
86
if (render_device != d3d11_device_) {
81
87
d3d11_device_ = render_device;
82
88
need_swapchain_recreate_ = true ;
@@ -99,10 +105,147 @@ void WebrtcVideoRendererD3D11Impl::OnFrame(
99
105
RenderToBackbuffer (array_slice);
100
106
}
101
107
} 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
+ }
102
181
}
103
182
return ;
104
183
}
105
184
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
+
106
249
// Method to create the necessary 3D pipeline objects to render a textured 3D
107
250
// QUAD
108
251
HRESULT WebrtcVideoRendererD3D11Impl::CreateRenderPipeline () {
0 commit comments