Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(176)

Side by Side Diff: webrtc/modules/video_render/windows/video_render_direct3d9.cc

Issue 1912143002: Delete video_render module. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Move -framework flags from legacy_objc_api_tests.gyp to legacy_objc_api.gyp. Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 // Own include file
12 #include "webrtc/modules/video_render/windows/video_render_direct3d9.h"
13
14 // System include files
15 #include <windows.h>
16
17 // WebRtc include files
18 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
19 #include "webrtc/system_wrappers/include/critical_section_wrapper.h"
20 #include "webrtc/system_wrappers/include/event_wrapper.h"
21 #include "webrtc/system_wrappers/include/trace.h"
22
23 namespace webrtc {
24
25 // A structure for our custom vertex type
26 struct CUSTOMVERTEX
27 {
28 FLOAT x, y, z;
29 DWORD color; // The vertex color
30 FLOAT u, v;
31 };
32
33 // Our custom FVF, which describes our custom vertex structure
34 #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
35
36 /*
37 *
38 * D3D9Channel
39 *
40 */
41 D3D9Channel::D3D9Channel(LPDIRECT3DDEVICE9 pd3DDevice,
42 CriticalSectionWrapper* critSect,
43 Trace* trace) :
44 _width(0),
45 _height(0),
46 _pd3dDevice(pd3DDevice),
47 _pTexture(NULL),
48 _bufferIsUpdated(false),
49 _critSect(critSect),
50 _streamId(0),
51 _zOrder(0),
52 _startWidth(0),
53 _startHeight(0),
54 _stopWidth(0),
55 _stopHeight(0)
56 {
57
58 }
59
60 D3D9Channel::~D3D9Channel()
61 {
62 //release the texture
63 if (_pTexture != NULL)
64 {
65 _pTexture->Release();
66 _pTexture = NULL;
67 }
68 }
69
70 void D3D9Channel::SetStreamSettings(uint16_t streamId,
71 uint32_t zOrder,
72 float startWidth,
73 float startHeight,
74 float stopWidth,
75 float stopHeight)
76 {
77 _streamId = streamId;
78 _zOrder = zOrder;
79 _startWidth = startWidth;
80 _startHeight = startHeight;
81 _stopWidth = stopWidth;
82 _stopHeight = stopHeight;
83 }
84
85 int D3D9Channel::GetStreamSettings(uint16_t streamId,
86 uint32_t& zOrder,
87 float& startWidth,
88 float& startHeight,
89 float& stopWidth,
90 float& stopHeight)
91 {
92 streamId = _streamId;
93 zOrder = _zOrder;
94 startWidth = _startWidth;
95 startHeight = _startHeight;
96 stopWidth = _stopWidth;
97 stopHeight = _stopHeight;
98 return 0;
99 }
100
101 int D3D9Channel::GetTextureWidth()
102 {
103 return _width;
104 }
105
106 int D3D9Channel::GetTextureHeight()
107 {
108 return _height;
109 }
110
111 // Called from video engine when a the frame size changed
112 int D3D9Channel::FrameSizeChange(int width, int height, int numberOfStreams)
113 {
114 WEBRTC_TRACE(kTraceInfo, kTraceVideo, -1,
115 "FrameSizeChange, wifth: %d, height: %d, streams: %d", width,
116 height, numberOfStreams);
117
118 CriticalSectionScoped cs(_critSect);
119 _width = width;
120 _height = height;
121
122 //clean the previous texture
123 if (_pTexture != NULL)
124 {
125 _pTexture->Release();
126 _pTexture = NULL;
127 }
128
129 HRESULT ret = E_POINTER;
130
131 if (_pd3dDevice)
132 ret = _pd3dDevice->CreateTexture(_width, _height, 1, 0, D3DFMT_A8R8G8B8,
133 D3DPOOL_MANAGED, &_pTexture, NULL);
134
135 if (FAILED(ret))
136 {
137 _pTexture = NULL;
138 return -1;
139 }
140
141 return 0;
142 }
143
144 int32_t D3D9Channel::RenderFrame(const uint32_t streamId,
145 const VideoFrame& videoFrame) {
146 CriticalSectionScoped cs(_critSect);
147 if (_width != videoFrame.width() || _height != videoFrame.height())
148 {
149 if (FrameSizeChange(videoFrame.width(), videoFrame.height(), 1) == -1)
150 {
151 return -1;
152 }
153 }
154 return DeliverFrame(videoFrame);
155 }
156
157 // Called from video engine when a new frame should be rendered.
158 int D3D9Channel::DeliverFrame(const VideoFrame& videoFrame) {
159 WEBRTC_TRACE(kTraceStream, kTraceVideo, -1,
160 "DeliverFrame to D3D9Channel");
161
162 CriticalSectionScoped cs(_critSect);
163
164 // FIXME if _bufferIsUpdated is still true (not be renderred), do we want to
165 // update the texture? probably not
166 if (_bufferIsUpdated) {
167 WEBRTC_TRACE(kTraceStream, kTraceVideo, -1,
168 "Last frame hasn't been rendered yet. Drop this frame.");
169 return -1;
170 }
171
172 if (!_pd3dDevice) {
173 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
174 "D3D for rendering not initialized.");
175 return -1;
176 }
177
178 if (!_pTexture) {
179 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
180 "Texture for rendering not initialized.");
181 return -1;
182 }
183
184 D3DLOCKED_RECT lr;
185
186 if (FAILED(_pTexture->LockRect(0, &lr, NULL, 0))) {
187 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
188 "Failed to lock a texture in D3D9 Channel.");
189 return -1;
190 }
191 UCHAR* pRect = (UCHAR*) lr.pBits;
192
193 ConvertFromI420(videoFrame, kARGB, 0, pRect);
194
195 if (FAILED(_pTexture->UnlockRect(0))) {
196 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
197 "Failed to unlock a texture in D3D9 Channel.");
198 return -1;
199 }
200
201 _bufferIsUpdated = true;
202 return 0;
203 }
204
205 // Called by d3d channel owner to indicate the frame/texture has been rendered o ff
206 int D3D9Channel::RenderOffFrame()
207 {
208 WEBRTC_TRACE(kTraceStream, kTraceVideo, -1,
209 "Frame has been rendered to the screen.");
210 CriticalSectionScoped cs(_critSect);
211 _bufferIsUpdated = false;
212 return 0;
213 }
214
215 // Called by d3d channel owner to check if the texture is updated
216 int D3D9Channel::IsUpdated(bool& isUpdated)
217 {
218 CriticalSectionScoped cs(_critSect);
219 isUpdated = _bufferIsUpdated;
220 return 0;
221 }
222
223 // Called by d3d channel owner to get the texture
224 LPDIRECT3DTEXTURE9 D3D9Channel::GetTexture()
225 {
226 CriticalSectionScoped cs(_critSect);
227 return _pTexture;
228 }
229
230 int D3D9Channel::ReleaseTexture()
231 {
232 CriticalSectionScoped cs(_critSect);
233
234 //release the texture
235 if (_pTexture != NULL)
236 {
237 _pTexture->Release();
238 _pTexture = NULL;
239 }
240 _pd3dDevice = NULL;
241 return 0;
242 }
243
244 int D3D9Channel::RecreateTexture(LPDIRECT3DDEVICE9 pd3DDevice)
245 {
246 CriticalSectionScoped cs(_critSect);
247
248 _pd3dDevice = pd3DDevice;
249
250 if (_pTexture != NULL)
251 {
252 _pTexture->Release();
253 _pTexture = NULL;
254 }
255
256 HRESULT ret;
257
258 ret = _pd3dDevice->CreateTexture(_width, _height, 1, 0, D3DFMT_A8R8G8B8,
259 D3DPOOL_MANAGED, &_pTexture, NULL);
260
261 if (FAILED(ret))
262 {
263 _pTexture = NULL;
264 return -1;
265 }
266
267 return 0;
268 }
269
270 /*
271 *
272 * VideoRenderDirect3D9
273 *
274 */
275 VideoRenderDirect3D9::VideoRenderDirect3D9(Trace* trace,
276 HWND hWnd,
277 bool fullScreen) :
278 _refD3DCritsect(*CriticalSectionWrapper::CreateCriticalSection()),
279 _trace(trace),
280 _hWnd(hWnd),
281 _fullScreen(fullScreen),
282 _pTextureLogo(NULL),
283 _pVB(NULL),
284 _pd3dDevice(NULL),
285 _pD3D(NULL),
286 _d3dChannels(),
287 _d3dZorder(),
288 _screenUpdateEvent(NULL),
289 _logoLeft(0),
290 _logoTop(0),
291 _logoRight(0),
292 _logoBottom(0),
293 _pd3dSurface(NULL),
294 _totalMemory(0),
295 _availableMemory(0)
296 {
297 _screenUpdateThread.reset(new rtc::PlatformThread(
298 ScreenUpdateThreadProc, this, "ScreenUpdateThread"));
299 _screenUpdateEvent = EventTimerWrapper::Create();
300 SetRect(&_originalHwndRect, 0, 0, 0, 0);
301 }
302
303 VideoRenderDirect3D9::~VideoRenderDirect3D9()
304 {
305 //NOTE: we should not enter CriticalSection in here!
306
307 // Signal event to exit thread, then delete it
308 rtc::PlatformThread* tmpPtr = _screenUpdateThread.release();
309 if (tmpPtr)
310 {
311 _screenUpdateEvent->Set();
312 _screenUpdateEvent->StopTimer();
313
314 tmpPtr->Stop();
315 delete tmpPtr;
316 }
317 delete _screenUpdateEvent;
318
319 //close d3d device
320 CloseDevice();
321
322 // Delete all channels
323 std::map<int, D3D9Channel*>::iterator it = _d3dChannels.begin();
324 while (it != _d3dChannels.end())
325 {
326 delete it->second;
327 it = _d3dChannels.erase(it);
328 }
329 // Clean the zOrder map
330 _d3dZorder.clear();
331
332 if (_fullScreen)
333 {
334 // restore hwnd to original size and position
335 ::SetWindowPos(_hWnd, HWND_NOTOPMOST, _originalHwndRect.left,
336 _originalHwndRect.top, _originalHwndRect.right
337 - _originalHwndRect.left,
338 _originalHwndRect.bottom - _originalHwndRect.top,
339 SWP_FRAMECHANGED);
340 ::RedrawWindow(_hWnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW
341 | RDW_ERASE);
342 ::RedrawWindow(NULL, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW
343 | RDW_ERASE);
344 }
345
346 delete &_refD3DCritsect;
347 }
348
349 DWORD VideoRenderDirect3D9::GetVertexProcessingCaps()
350 {
351 D3DCAPS9 caps;
352 DWORD dwVertexProcessing = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
353 if (SUCCEEDED(_pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
354 &caps)))
355 {
356 if ((caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
357 == D3DDEVCAPS_HWTRANSFORMANDLIGHT)
358 {
359 dwVertexProcessing = D3DCREATE_HARDWARE_VERTEXPROCESSING;
360 }
361 }
362 return dwVertexProcessing;
363 }
364
365 int VideoRenderDirect3D9::InitializeD3D(HWND hWnd,
366 D3DPRESENT_PARAMETERS* pd3dpp)
367 {
368 // initialize Direct3D
369 if (NULL == (_pD3D = Direct3DCreate9(D3D_SDK_VERSION)))
370 {
371 return -1;
372 }
373
374 // determine what type of vertex processing to use based on the device capab ilities
375 DWORD dwVertexProcessing = GetVertexProcessingCaps();
376
377 // get the display mode
378 D3DDISPLAYMODE d3ddm;
379 _pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm);
380 pd3dpp->BackBufferFormat = d3ddm.Format;
381
382 // create the D3D device
383 if (FAILED(_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
384 dwVertexProcessing | D3DCREATE_MULTITHREADED
385 | D3DCREATE_FPU_PRESERVE, pd3dpp,
386 &_pd3dDevice)))
387 {
388 //try the ref device
389 if (FAILED(_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF,
390 hWnd, dwVertexProcessing
391 | D3DCREATE_MULTITHREADED
392 | D3DCREATE_FPU_PRESERVE,
393 pd3dpp, &_pd3dDevice)))
394 {
395 return -1;
396 }
397 }
398
399 return 0;
400 }
401
402 int VideoRenderDirect3D9::ResetDevice()
403 {
404 WEBRTC_TRACE(kTraceInfo, kTraceVideo, -1,
405 "VideoRenderDirect3D9::ResetDevice");
406
407 CriticalSectionScoped cs(&_refD3DCritsect);
408
409 //release the channel texture
410 std::map<int, D3D9Channel*>::iterator it;
411 it = _d3dChannels.begin();
412 while (it != _d3dChannels.end())
413 {
414 if (it->second)
415 {
416 it->second->ReleaseTexture();
417 }
418 it++;
419 }
420
421 //close d3d device
422 if (CloseDevice() != 0)
423 {
424 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
425 "VideoRenderDirect3D9::ResetDevice failed to CloseDevice");
426 return -1;
427 }
428
429 //reinit d3d device
430 if (InitDevice() != 0)
431 {
432 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
433 "VideoRenderDirect3D9::ResetDevice failed to InitDevice");
434 return -1;
435 }
436
437 //recreate channel texture
438 it = _d3dChannels.begin();
439 while (it != _d3dChannels.end())
440 {
441 if (it->second)
442 {
443 it->second->RecreateTexture(_pd3dDevice);
444 }
445 it++;
446 }
447
448 return 0;
449 }
450
451 int VideoRenderDirect3D9::InitDevice()
452 {
453 // Set up the structure used to create the D3DDevice
454 ZeroMemory(&_d3dpp, sizeof(_d3dpp));
455 _d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
456 _d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
457 if (GetWindowRect(_hWnd, &_originalHwndRect) == 0)
458 {
459 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
460 "VideoRenderDirect3D9::InitDevice Could not get window size ");
461 return -1;
462 }
463 if (!_fullScreen)
464 {
465 _winWidth = _originalHwndRect.right - _originalHwndRect.left;
466 _winHeight = _originalHwndRect.bottom - _originalHwndRect.top;
467 _d3dpp.Windowed = TRUE;
468 _d3dpp.BackBufferHeight = 0;
469 _d3dpp.BackBufferWidth = 0;
470 }
471 else
472 {
473 _winWidth = (LONG) ::GetSystemMetrics(SM_CXSCREEN);
474 _winHeight = (LONG) ::GetSystemMetrics(SM_CYSCREEN);
475 _d3dpp.Windowed = FALSE;
476 _d3dpp.BackBufferWidth = _winWidth;
477 _d3dpp.BackBufferHeight = _winHeight;
478 _d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
479 }
480
481 if (InitializeD3D(_hWnd, &_d3dpp) == -1)
482 {
483 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
484 "VideoRenderDirect3D9::InitDevice failed in InitializeD3D") ;
485 return -1;
486 }
487
488 // Turn off culling, so we see the front and back of the triangle
489 _pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
490
491 // Turn off D3D lighting, since we are providing our own vertex colors
492 _pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
493
494 // Settings for alpha blending
495 _pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
496 _pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
497 _pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
498
499 _pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
500 _pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
501 _pd3dDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR );
502
503 // Initialize Vertices
504 CUSTOMVERTEX Vertices[] = {
505 //front
506 { -1.0f, -1.0f, 0.0f, 0xffffffff, 0, 1 }, { -1.0f, 1.0f, 0.0f,
507 0xffffffff, 0, 0 },
508 { 1.0f, -1.0f, 0.0f, 0xffffffff, 1, 1 }, { 1.0f, 1.0f, 0.0f,
509 0xffffffff, 1, 0 } };
510
511 // Create the vertex buffer.
512 if (FAILED(_pd3dDevice->CreateVertexBuffer(sizeof(Vertices), 0,
513 D3DFVF_CUSTOMVERTEX,
514 D3DPOOL_DEFAULT, &_pVB, NULL )))
515 {
516 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
517 "Failed to create the vertex buffer.");
518 return -1;
519 }
520
521 // Now we fill the vertex buffer.
522 VOID* pVertices;
523 if (FAILED(_pVB->Lock(0, sizeof(Vertices), (void**) &pVertices, 0)))
524 {
525 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
526 "Failed to lock the vertex buffer.");
527 return -1;
528 }
529 memcpy(pVertices, Vertices, sizeof(Vertices));
530 _pVB->Unlock();
531
532 return 0;
533 }
534
535 int32_t VideoRenderDirect3D9::Init()
536 {
537 WEBRTC_TRACE(kTraceInfo, kTraceVideo, -1,
538 "VideoRenderDirect3D9::Init");
539
540 CriticalSectionScoped cs(&_refD3DCritsect);
541
542 // Start rendering thread...
543 if (!_screenUpdateThread)
544 {
545 WEBRTC_TRACE(kTraceError, kTraceVideo, -1, "Thread not created");
546 return -1;
547 }
548 _screenUpdateThread->Start();
549 _screenUpdateThread->SetPriority(rtc::kRealtimePriority);
550
551 // Start the event triggering the render process
552 unsigned int monitorFreq = 60;
553 DEVMODE dm;
554 // initialize the DEVMODE structure
555 ZeroMemory(&dm, sizeof(dm));
556 dm.dmSize = sizeof(dm);
557 if (0 != EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm))
558 {
559 monitorFreq = dm.dmDisplayFrequency;
560 }
561 _screenUpdateEvent->StartTimer(true, 1000 / monitorFreq);
562
563 return InitDevice();
564 }
565
566 int32_t VideoRenderDirect3D9::ChangeWindow(void* window)
567 {
568 WEBRTC_TRACE(kTraceError, kTraceVideo, -1, "Not supported.");
569 return -1;
570 }
571
572 int VideoRenderDirect3D9::UpdateRenderSurface()
573 {
574 CriticalSectionScoped cs(&_refD3DCritsect);
575
576 // Check if there are any updated buffers
577 bool updated = false;
578 std::map<int, D3D9Channel*>::iterator it;
579 it = _d3dChannels.begin();
580 while (it != _d3dChannels.end())
581 {
582
583 D3D9Channel* channel = it->second;
584 channel->IsUpdated(updated);
585 if (updated)
586 {
587 break;
588 }
589 it++;
590 }
591 //nothing is updated, continue
592 if (!updated)
593 return -1;
594
595 // Clear the backbuffer to a black color
596 _pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f,
597 0);
598
599 // Begin the scene
600 if (SUCCEEDED(_pd3dDevice->BeginScene()))
601 {
602 _pd3dDevice->SetStreamSource(0, _pVB, 0, sizeof(CUSTOMVERTEX));
603 _pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
604
605 //draw all the channels
606 //get texture from the channels
607 LPDIRECT3DTEXTURE9 textureFromChannel = NULL;
608 DWORD textureWidth, textureHeight;
609
610 std::multimap<int, unsigned int>::reverse_iterator it;
611 it = _d3dZorder.rbegin();
612 while (it != _d3dZorder.rend())
613 {
614 // loop through all channels and streams in Z order
615 int channel = it->second & 0x0000ffff;
616
617 std::map<int, D3D9Channel*>::iterator ddIt;
618 ddIt = _d3dChannels.find(channel);
619 if (ddIt != _d3dChannels.end())
620 {
621 // found the channel
622 D3D9Channel* channelObj = ddIt->second;
623 if (channelObj)
624 {
625 textureFromChannel = channelObj->GetTexture();
626 textureWidth = channelObj->GetTextureWidth();
627 textureHeight = channelObj->GetTextureHeight();
628
629 uint32_t zOrder;
630 float startWidth, startHeight, stopWidth, stopHeight;
631 channelObj->GetStreamSettings(0, zOrder, startWidth,
632 startHeight, stopWidth,
633 stopHeight);
634
635 //draw the video stream
636 UpdateVerticeBuffer(_pVB, 0, startWidth, startHeight,
637 stopWidth, stopHeight);
638 _pd3dDevice->SetTexture(0, textureFromChannel);
639 _pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
640
641 //Notice channel that this frame as been rendered
642 channelObj->RenderOffFrame();
643 }
644 }
645 it++;
646 }
647
648 //draw the logo
649 if (_pTextureLogo)
650 {
651 UpdateVerticeBuffer(_pVB, 0, _logoLeft, _logoTop, _logoRight,
652 _logoBottom);
653 _pd3dDevice->SetTexture(0, _pTextureLogo);
654 _pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
655 }
656
657 // End the scene
658 _pd3dDevice->EndScene();
659 }
660
661 // Present the backbuffer contents to the display
662 _pd3dDevice->Present(NULL, NULL, NULL, NULL );
663
664 return 0;
665 }
666
667 //set the alpha value of the pixal with a particular colorkey as 0
668 int VideoRenderDirect3D9::SetTransparentColor(LPDIRECT3DTEXTURE9 pTexture,
669 DDCOLORKEY* transparentColorKe y,
670 DWORD width,
671 DWORD height)
672 {
673 D3DLOCKED_RECT lr;
674 if (!pTexture)
675 return -1;
676
677 CriticalSectionScoped cs(&_refD3DCritsect);
678 if (SUCCEEDED(pTexture->LockRect(0, &lr, NULL, D3DLOCK_DISCARD)))
679 {
680 for (DWORD y = 0; y < height; y++)
681 {
682 DWORD dwOffset = y * width;
683
684 for (DWORD x = 0; x < width; x)
685 {
686 DWORD temp = ((DWORD*) lr.pBits)[dwOffset + x];
687 if ((temp & 0x00FFFFFF)
688 == transparentColorKey->dwColorSpaceLowValue)
689 {
690 temp &= 0x00FFFFFF;
691 }
692 else
693 {
694 temp |= 0xFF000000;
695 }
696 ((DWORD*) lr.pBits)[dwOffset + x] = temp;
697 x++;
698 }
699 }
700 pTexture->UnlockRect(0);
701 return 0;
702 }
703 return -1;
704 }
705
706 /*
707 *
708 * Rendering process
709 *
710 */
711 bool VideoRenderDirect3D9::ScreenUpdateThreadProc(void* obj)
712 {
713 return static_cast<VideoRenderDirect3D9*> (obj)->ScreenUpdateProcess();
714 }
715
716 bool VideoRenderDirect3D9::ScreenUpdateProcess()
717 {
718 _screenUpdateEvent->Wait(100);
719
720 if (!_screenUpdateThread)
721 {
722 //stop the thread
723 return false;
724 }
725 if (!_pd3dDevice)
726 {
727 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
728 "d3dDevice not created.");
729 return true;
730 }
731
732 HRESULT hr = _pd3dDevice->TestCooperativeLevel();
733
734 if (SUCCEEDED(hr))
735 {
736 UpdateRenderSurface();
737 }
738
739 if (hr == D3DERR_DEVICELOST)
740 {
741 //Device is lost and cannot be reset yet
742
743 }
744 else if (hr == D3DERR_DEVICENOTRESET)
745 {
746 //Lost but we can reset it now
747 //Note: the standard way is to call Reset, however for some reason doesn 't work here.
748 //so we will release the device and create it again.
749 ResetDevice();
750 }
751
752 return true;
753 }
754
755 int VideoRenderDirect3D9::CloseDevice()
756 {
757 CriticalSectionScoped cs(&_refD3DCritsect);
758 WEBRTC_TRACE(kTraceInfo, kTraceVideo, -1,
759 "VideoRenderDirect3D9::CloseDevice");
760
761 if (_pTextureLogo != NULL)
762 {
763 _pTextureLogo->Release();
764 _pTextureLogo = NULL;
765 }
766
767 if (_pVB != NULL)
768 {
769 _pVB->Release();
770 _pVB = NULL;
771 }
772
773 if (_pd3dDevice != NULL)
774 {
775 _pd3dDevice->Release();
776 _pd3dDevice = NULL;
777 }
778
779 if (_pD3D != NULL)
780 {
781 _pD3D->Release();
782 _pD3D = NULL;
783 }
784
785 if (_pd3dSurface != NULL)
786 _pd3dSurface->Release();
787 return 0;
788 }
789
790 D3D9Channel* VideoRenderDirect3D9::GetD3DChannel(int channel)
791 {
792 std::map<int, D3D9Channel*>::iterator ddIt;
793 ddIt = _d3dChannels.find(channel & 0x0000ffff);
794 D3D9Channel* ddobj = NULL;
795 if (ddIt != _d3dChannels.end())
796 {
797 ddobj = ddIt->second;
798 }
799 if (ddobj == NULL)
800 {
801 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
802 "Direct3D render failed to find channel");
803 return NULL;
804 }
805 return ddobj;
806 }
807
808 int32_t VideoRenderDirect3D9::DeleteChannel(const uint32_t streamId)
809 {
810 CriticalSectionScoped cs(&_refD3DCritsect);
811
812
813 std::multimap<int, unsigned int>::iterator it;
814 it = _d3dZorder.begin();
815 while (it != _d3dZorder.end())
816 {
817 if ((streamId & 0x0000ffff) == (it->second & 0x0000ffff))
818 {
819 it = _d3dZorder.erase(it);
820 break;
821 }
822 it++;
823 }
824
825 std::map<int, D3D9Channel*>::iterator ddIt;
826 ddIt = _d3dChannels.find(streamId & 0x0000ffff);
827 if (ddIt != _d3dChannels.end())
828 {
829 delete ddIt->second;
830 _d3dChannels.erase(ddIt);
831 return 0;
832 }
833 return -1;
834 }
835
836 VideoRenderCallback* VideoRenderDirect3D9::CreateChannel(const uint32_t channel,
837 const uint32_t zOrder,
838 const float lef t,
839 const float top ,
840 const float rig ht,
841 const float bot tom)
842 {
843 CriticalSectionScoped cs(&_refD3DCritsect);
844
845 //FIXME this should be done in VideoAPIWindows? stop the frame deliver first
846 //remove the old channel
847 DeleteChannel(channel);
848
849 D3D9Channel* d3dChannel = new D3D9Channel(_pd3dDevice,
850 &_refD3DCritsect, _trace);
851 d3dChannel->SetStreamSettings(0, zOrder, left, top, right, bottom);
852
853 // store channel
854 _d3dChannels[channel & 0x0000ffff] = d3dChannel;
855
856 // store Z order
857 // default streamID is 0
858 _d3dZorder.insert(
859 std::pair<int, unsigned int>(zOrder, channel & 0x0000ffff) );
860
861 return d3dChannel;
862 }
863
864 int32_t VideoRenderDirect3D9::GetStreamSettings(const uint32_t channel,
865 const uint16_t streamId,
866 uint32_t& zOrder,
867 float& left, float& top,
868 float& right, float& bottom)
869 {
870 std::map<int, D3D9Channel*>::iterator ddIt;
871 ddIt = _d3dChannels.find(channel & 0x0000ffff);
872 D3D9Channel* ddobj = NULL;
873 if (ddIt != _d3dChannels.end())
874 {
875 ddobj = ddIt->second;
876 }
877 if (ddobj == NULL)
878 {
879 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
880 "Direct3D render failed to find channel");
881 return -1;
882 }
883 // Only allow one stream per channel, demuxing is
884 return ddobj->GetStreamSettings(0, zOrder, left, top, right, bottom);
885 }
886
887 int VideoRenderDirect3D9::UpdateVerticeBuffer(LPDIRECT3DVERTEXBUFFER9 pVB,
888 int offset,
889 float startWidth,
890 float startHeight,
891 float stopWidth,
892 float stopHeight)
893 {
894 if (pVB == NULL)
895 return -1;
896
897 float left, right, top, bottom;
898
899 //update the vertice buffer
900 //0,1 => -1,1
901 left = startWidth * 2 - 1;
902 right = stopWidth * 2 - 1;
903
904 //0,1 => 1,-1
905 top = 1 - startHeight * 2;
906 bottom = 1 - stopHeight * 2;
907
908 CUSTOMVERTEX newVertices[] = {
909 //logo
910 { left, bottom, 0.0f, 0xffffffff, 0, 1 }, { left, top, 0.0f,
911 0xffffffff, 0, 0 },
912 { right, bottom, 0.0f, 0xffffffff, 1, 1 }, { right, top, 0.0f,
913 0xffffffff, 1, 0 }, };
914 // Now we fill the vertex buffer.
915 VOID* pVertices;
916 if (FAILED(pVB->Lock(sizeof(CUSTOMVERTEX) * offset, sizeof(newVertices),
917 (void**) &pVertices, 0)))
918 {
919 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
920 "Failed to lock the vertex buffer.");
921 return -1;
922 }
923 memcpy(pVertices, newVertices, sizeof(newVertices));
924 pVB->Unlock();
925
926 return 0;
927 }
928
929 int32_t VideoRenderDirect3D9::StartRender()
930 {
931 WEBRTC_TRACE(kTraceError, kTraceVideo, -1, "Not supported.");
932 return 0;
933 }
934
935 int32_t VideoRenderDirect3D9::StopRender()
936 {
937 WEBRTC_TRACE(kTraceError, kTraceVideo, -1, "Not supported.");
938 return 0;
939 }
940
941 bool VideoRenderDirect3D9::IsFullScreen()
942 {
943 return _fullScreen;
944 }
945
946 int32_t VideoRenderDirect3D9::SetCropping(const uint32_t channel,
947 const uint16_t streamId,
948 const float left, const float top,
949 const float right, const float bottom)
950 {
951 WEBRTC_TRACE(kTraceError, kTraceVideo, -1, "Not supported.");
952 return 0;
953 }
954
955 int32_t VideoRenderDirect3D9::SetTransparentBackground(
956 const bool enab le)
957 {
958 WEBRTC_TRACE(kTraceError, kTraceVideo, -1, "Not supported.");
959 return 0;
960 }
961
962 int32_t VideoRenderDirect3D9::SetText(const uint8_t textId,
963 const uint8_t* text,
964 const int32_t textLength,
965 const uint32_t colorText,
966 const uint32_t colorBg,
967 const float left, const float top,
968 const float rigth, const float bottom)
969 {
970 WEBRTC_TRACE(kTraceError, kTraceVideo, -1, "Not supported.");
971 return 0;
972 }
973
974 int32_t VideoRenderDirect3D9::SetBitmap(const void* bitMap,
975 const uint8_t pictureId,
976 const void* colorKey,
977 const float left, const float top,
978 const float right, const float bottom)
979 {
980 if (!bitMap)
981 {
982 if (_pTextureLogo != NULL)
983 {
984 _pTextureLogo->Release();
985 _pTextureLogo = NULL;
986 }
987 WEBRTC_TRACE(kTraceInfo, kTraceVideo, -1, "Remove bitmap.");
988 return 0;
989 }
990
991 // sanity
992 if (left > 1.0f || left < 0.0f ||
993 top > 1.0f || top < 0.0f ||
994 right > 1.0f || right < 0.0f ||
995 bottom > 1.0f || bottom < 0.0f)
996 {
997 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
998 "Direct3D SetBitmap invalid parameter");
999 return -1;
1000 }
1001
1002 if ((bottom <= top) || (right <= left))
1003 {
1004 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
1005 "Direct3D SetBitmap invalid parameter");
1006 return -1;
1007 }
1008
1009 CriticalSectionScoped cs(&_refD3DCritsect);
1010
1011 unsigned char* srcPtr;
1012 HGDIOBJ oldhand;
1013 BITMAPINFO pbi;
1014 BITMAP bmap;
1015 HDC hdcNew;
1016 hdcNew = CreateCompatibleDC(0);
1017 // Fill out the BITMAP structure.
1018 GetObject((HBITMAP)bitMap, sizeof(bmap), &bmap);
1019 //Select the bitmap handle into the new device context.
1020 oldhand = SelectObject(hdcNew, (HGDIOBJ) bitMap);
1021 // we are done with this object
1022 DeleteObject(oldhand);
1023 pbi.bmiHeader.biSize = 40;
1024 pbi.bmiHeader.biWidth = bmap.bmWidth;
1025 pbi.bmiHeader.biHeight = bmap.bmHeight;
1026 pbi.bmiHeader.biPlanes = 1;
1027 pbi.bmiHeader.biBitCount = bmap.bmBitsPixel;
1028 pbi.bmiHeader.biCompression = BI_RGB;
1029 pbi.bmiHeader.biSizeImage = bmap.bmWidth * bmap.bmHeight * 3;
1030 srcPtr = new unsigned char[bmap.bmWidth * bmap.bmHeight * 4];
1031 // the original un-stretched image in RGB24
1032 int pixelHeight = GetDIBits(hdcNew, (HBITMAP)bitMap, 0, bmap.bmHeight, srcPt r, &pbi,
1033 DIB_RGB_COLORS);
1034 if (pixelHeight == 0)
1035 {
1036 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
1037 "Direct3D failed to GetDIBits in SetBitmap");
1038 delete[] srcPtr;
1039 return -1;
1040 }
1041 DeleteDC(hdcNew);
1042 if (pbi.bmiHeader.biBitCount != 24 && pbi.bmiHeader.biBitCount != 32)
1043 {
1044 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
1045 "Direct3D failed to SetBitmap invalid bit depth");
1046 delete[] srcPtr;
1047 return -1;
1048 }
1049
1050 HRESULT ret;
1051 //release the previous logo texture
1052 if (_pTextureLogo != NULL)
1053 {
1054 _pTextureLogo->Release();
1055 _pTextureLogo = NULL;
1056 }
1057 ret = _pd3dDevice->CreateTexture(bmap.bmWidth, bmap.bmHeight, 1, 0,
1058 D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
1059 &_pTextureLogo, NULL);
1060 if (FAILED(ret))
1061 {
1062 _pTextureLogo = NULL;
1063 delete[] srcPtr;
1064 return -1;
1065 }
1066 if (!_pTextureLogo)
1067 {
1068 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
1069 "Texture for rendering not initialized.");
1070 delete[] srcPtr;
1071 return -1;
1072 }
1073
1074 D3DLOCKED_RECT lr;
1075 if (FAILED(_pTextureLogo->LockRect(0, &lr, NULL, 0)))
1076 {
1077 delete[] srcPtr;
1078 return -1;
1079 }
1080 unsigned char* dstPtr = (UCHAR*) lr.pBits;
1081 int pitch = bmap.bmWidth * 4;
1082
1083 if (pbi.bmiHeader.biBitCount == 24)
1084 {
1085 ConvertRGB24ToARGB(srcPtr, dstPtr, bmap.bmWidth, bmap.bmHeight, 0);
1086 }
1087 else
1088 {
1089 unsigned char* srcTmp = srcPtr + (bmap.bmWidth * 4) * (bmap.bmHeight - 1 );
1090 for (int i = 0; i < bmap.bmHeight; ++i)
1091 {
1092 memcpy(dstPtr, srcTmp, bmap.bmWidth * 4);
1093 srcTmp -= bmap.bmWidth * 4;
1094 dstPtr += pitch;
1095 }
1096 }
1097
1098 delete[] srcPtr;
1099 if (FAILED(_pTextureLogo->UnlockRect(0)))
1100 {
1101 return -1;
1102 }
1103
1104 if (colorKey)
1105 {
1106 DDCOLORKEY* ddColorKey =
1107 static_cast<DDCOLORKEY*> (const_cast<void*> (colorKey));
1108 SetTransparentColor(_pTextureLogo, ddColorKey, bmap.bmWidth,
1109 bmap.bmHeight);
1110 }
1111
1112 //update the vertice buffer
1113 //0,1 => -1,1
1114 _logoLeft = left;
1115 _logoRight = right;
1116
1117 //0,1 => 1,-1
1118 _logoTop = top;
1119 _logoBottom = bottom;
1120
1121 return 0;
1122
1123 }
1124
1125 int32_t VideoRenderDirect3D9::GetGraphicsMemory(uint64_t& totalMemory,
1126 uint64_t& availableMemory)
1127 {
1128 totalMemory = _totalMemory;
1129 availableMemory = _availableMemory;
1130 return 0;
1131 }
1132
1133 int32_t VideoRenderDirect3D9::ConfigureRenderer(const uint32_t channel,
1134 const uint16_t streamId,
1135 const unsigned int zOrder,
1136 const float left,
1137 const float top,
1138 const float right,
1139 const float bottom)
1140 {
1141 std::map<int, D3D9Channel*>::iterator ddIt;
1142 ddIt = _d3dChannels.find(channel & 0x0000ffff);
1143 D3D9Channel* ddobj = NULL;
1144 if (ddIt != _d3dChannels.end())
1145 {
1146 ddobj = ddIt->second;
1147 }
1148 if (ddobj == NULL)
1149 {
1150 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
1151 "Direct3D render failed to find channel");
1152 return -1;
1153 }
1154 // Only allow one stream per channel, demuxing is
1155 ddobj->SetStreamSettings(0, zOrder, left, top, right, bottom);
1156
1157 return 0;
1158 }
1159
1160 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698