Index: webrtc/modules/video_render/windows/video_render_direct3d9.cc |
diff --git a/webrtc/modules/video_render/windows/video_render_direct3d9.cc b/webrtc/modules/video_render/windows/video_render_direct3d9.cc |
deleted file mode 100644 |
index b59b944e483405818db95708c5793ac8cdc28ede..0000000000000000000000000000000000000000 |
--- a/webrtc/modules/video_render/windows/video_render_direct3d9.cc |
+++ /dev/null |
@@ -1,1160 +0,0 @@ |
-/* |
- * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
- * |
- * Use of this source code is governed by a BSD-style license |
- * that can be found in the LICENSE file in the root of the source |
- * tree. An additional intellectual property rights grant can be found |
- * in the file PATENTS. All contributing project authors may |
- * be found in the AUTHORS file in the root of the source tree. |
- */ |
- |
-// Own include file |
-#include "webrtc/modules/video_render/windows/video_render_direct3d9.h" |
- |
-// System include files |
-#include <windows.h> |
- |
-// WebRtc include files |
-#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" |
-#include "webrtc/system_wrappers/include/critical_section_wrapper.h" |
-#include "webrtc/system_wrappers/include/event_wrapper.h" |
-#include "webrtc/system_wrappers/include/trace.h" |
- |
-namespace webrtc { |
- |
-// A structure for our custom vertex type |
-struct CUSTOMVERTEX |
-{ |
- FLOAT x, y, z; |
- DWORD color; // The vertex color |
- FLOAT u, v; |
-}; |
- |
-// Our custom FVF, which describes our custom vertex structure |
-#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1) |
- |
-/* |
- * |
- * D3D9Channel |
- * |
- */ |
-D3D9Channel::D3D9Channel(LPDIRECT3DDEVICE9 pd3DDevice, |
- CriticalSectionWrapper* critSect, |
- Trace* trace) : |
- _width(0), |
- _height(0), |
- _pd3dDevice(pd3DDevice), |
- _pTexture(NULL), |
- _bufferIsUpdated(false), |
- _critSect(critSect), |
- _streamId(0), |
- _zOrder(0), |
- _startWidth(0), |
- _startHeight(0), |
- _stopWidth(0), |
- _stopHeight(0) |
-{ |
- |
-} |
- |
-D3D9Channel::~D3D9Channel() |
-{ |
- //release the texture |
- if (_pTexture != NULL) |
- { |
- _pTexture->Release(); |
- _pTexture = NULL; |
- } |
-} |
- |
-void D3D9Channel::SetStreamSettings(uint16_t streamId, |
- uint32_t zOrder, |
- float startWidth, |
- float startHeight, |
- float stopWidth, |
- float stopHeight) |
-{ |
- _streamId = streamId; |
- _zOrder = zOrder; |
- _startWidth = startWidth; |
- _startHeight = startHeight; |
- _stopWidth = stopWidth; |
- _stopHeight = stopHeight; |
-} |
- |
-int D3D9Channel::GetStreamSettings(uint16_t streamId, |
- uint32_t& zOrder, |
- float& startWidth, |
- float& startHeight, |
- float& stopWidth, |
- float& stopHeight) |
-{ |
- streamId = _streamId; |
- zOrder = _zOrder; |
- startWidth = _startWidth; |
- startHeight = _startHeight; |
- stopWidth = _stopWidth; |
- stopHeight = _stopHeight; |
- return 0; |
-} |
- |
-int D3D9Channel::GetTextureWidth() |
-{ |
- return _width; |
-} |
- |
-int D3D9Channel::GetTextureHeight() |
-{ |
- return _height; |
-} |
- |
-// Called from video engine when a the frame size changed |
-int D3D9Channel::FrameSizeChange(int width, int height, int numberOfStreams) |
-{ |
- WEBRTC_TRACE(kTraceInfo, kTraceVideo, -1, |
- "FrameSizeChange, wifth: %d, height: %d, streams: %d", width, |
- height, numberOfStreams); |
- |
- CriticalSectionScoped cs(_critSect); |
- _width = width; |
- _height = height; |
- |
- //clean the previous texture |
- if (_pTexture != NULL) |
- { |
- _pTexture->Release(); |
- _pTexture = NULL; |
- } |
- |
- HRESULT ret = E_POINTER; |
- |
- if (_pd3dDevice) |
- ret = _pd3dDevice->CreateTexture(_width, _height, 1, 0, D3DFMT_A8R8G8B8, |
- D3DPOOL_MANAGED, &_pTexture, NULL); |
- |
- if (FAILED(ret)) |
- { |
- _pTexture = NULL; |
- return -1; |
- } |
- |
- return 0; |
-} |
- |
-int32_t D3D9Channel::RenderFrame(const uint32_t streamId, |
- const VideoFrame& videoFrame) { |
- CriticalSectionScoped cs(_critSect); |
- if (_width != videoFrame.width() || _height != videoFrame.height()) |
- { |
- if (FrameSizeChange(videoFrame.width(), videoFrame.height(), 1) == -1) |
- { |
- return -1; |
- } |
- } |
- return DeliverFrame(videoFrame); |
-} |
- |
-// Called from video engine when a new frame should be rendered. |
-int D3D9Channel::DeliverFrame(const VideoFrame& videoFrame) { |
- WEBRTC_TRACE(kTraceStream, kTraceVideo, -1, |
- "DeliverFrame to D3D9Channel"); |
- |
- CriticalSectionScoped cs(_critSect); |
- |
- // FIXME if _bufferIsUpdated is still true (not be renderred), do we want to |
- // update the texture? probably not |
- if (_bufferIsUpdated) { |
- WEBRTC_TRACE(kTraceStream, kTraceVideo, -1, |
- "Last frame hasn't been rendered yet. Drop this frame."); |
- return -1; |
- } |
- |
- if (!_pd3dDevice) { |
- WEBRTC_TRACE(kTraceError, kTraceVideo, -1, |
- "D3D for rendering not initialized."); |
- return -1; |
- } |
- |
- if (!_pTexture) { |
- WEBRTC_TRACE(kTraceError, kTraceVideo, -1, |
- "Texture for rendering not initialized."); |
- return -1; |
- } |
- |
- D3DLOCKED_RECT lr; |
- |
- if (FAILED(_pTexture->LockRect(0, &lr, NULL, 0))) { |
- WEBRTC_TRACE(kTraceError, kTraceVideo, -1, |
- "Failed to lock a texture in D3D9 Channel."); |
- return -1; |
- } |
- UCHAR* pRect = (UCHAR*) lr.pBits; |
- |
- ConvertFromI420(videoFrame, kARGB, 0, pRect); |
- |
- if (FAILED(_pTexture->UnlockRect(0))) { |
- WEBRTC_TRACE(kTraceError, kTraceVideo, -1, |
- "Failed to unlock a texture in D3D9 Channel."); |
- return -1; |
- } |
- |
- _bufferIsUpdated = true; |
- return 0; |
-} |
- |
-// Called by d3d channel owner to indicate the frame/texture has been rendered off |
-int D3D9Channel::RenderOffFrame() |
-{ |
- WEBRTC_TRACE(kTraceStream, kTraceVideo, -1, |
- "Frame has been rendered to the screen."); |
- CriticalSectionScoped cs(_critSect); |
- _bufferIsUpdated = false; |
- return 0; |
-} |
- |
-// Called by d3d channel owner to check if the texture is updated |
-int D3D9Channel::IsUpdated(bool& isUpdated) |
-{ |
- CriticalSectionScoped cs(_critSect); |
- isUpdated = _bufferIsUpdated; |
- return 0; |
-} |
- |
-// Called by d3d channel owner to get the texture |
-LPDIRECT3DTEXTURE9 D3D9Channel::GetTexture() |
-{ |
- CriticalSectionScoped cs(_critSect); |
- return _pTexture; |
-} |
- |
-int D3D9Channel::ReleaseTexture() |
-{ |
- CriticalSectionScoped cs(_critSect); |
- |
- //release the texture |
- if (_pTexture != NULL) |
- { |
- _pTexture->Release(); |
- _pTexture = NULL; |
- } |
- _pd3dDevice = NULL; |
- return 0; |
-} |
- |
-int D3D9Channel::RecreateTexture(LPDIRECT3DDEVICE9 pd3DDevice) |
-{ |
- CriticalSectionScoped cs(_critSect); |
- |
- _pd3dDevice = pd3DDevice; |
- |
- if (_pTexture != NULL) |
- { |
- _pTexture->Release(); |
- _pTexture = NULL; |
- } |
- |
- HRESULT ret; |
- |
- ret = _pd3dDevice->CreateTexture(_width, _height, 1, 0, D3DFMT_A8R8G8B8, |
- D3DPOOL_MANAGED, &_pTexture, NULL); |
- |
- if (FAILED(ret)) |
- { |
- _pTexture = NULL; |
- return -1; |
- } |
- |
- return 0; |
-} |
- |
-/* |
- * |
- * VideoRenderDirect3D9 |
- * |
- */ |
-VideoRenderDirect3D9::VideoRenderDirect3D9(Trace* trace, |
- HWND hWnd, |
- bool fullScreen) : |
- _refD3DCritsect(*CriticalSectionWrapper::CreateCriticalSection()), |
- _trace(trace), |
- _hWnd(hWnd), |
- _fullScreen(fullScreen), |
- _pTextureLogo(NULL), |
- _pVB(NULL), |
- _pd3dDevice(NULL), |
- _pD3D(NULL), |
- _d3dChannels(), |
- _d3dZorder(), |
- _screenUpdateEvent(NULL), |
- _logoLeft(0), |
- _logoTop(0), |
- _logoRight(0), |
- _logoBottom(0), |
- _pd3dSurface(NULL), |
- _totalMemory(0), |
- _availableMemory(0) |
-{ |
- _screenUpdateThread.reset(new rtc::PlatformThread( |
- ScreenUpdateThreadProc, this, "ScreenUpdateThread")); |
- _screenUpdateEvent = EventTimerWrapper::Create(); |
- SetRect(&_originalHwndRect, 0, 0, 0, 0); |
-} |
- |
-VideoRenderDirect3D9::~VideoRenderDirect3D9() |
-{ |
- //NOTE: we should not enter CriticalSection in here! |
- |
- // Signal event to exit thread, then delete it |
- rtc::PlatformThread* tmpPtr = _screenUpdateThread.release(); |
- if (tmpPtr) |
- { |
- _screenUpdateEvent->Set(); |
- _screenUpdateEvent->StopTimer(); |
- |
- tmpPtr->Stop(); |
- delete tmpPtr; |
- } |
- delete _screenUpdateEvent; |
- |
- //close d3d device |
- CloseDevice(); |
- |
- // Delete all channels |
- std::map<int, D3D9Channel*>::iterator it = _d3dChannels.begin(); |
- while (it != _d3dChannels.end()) |
- { |
- delete it->second; |
- it = _d3dChannels.erase(it); |
- } |
- // Clean the zOrder map |
- _d3dZorder.clear(); |
- |
- if (_fullScreen) |
- { |
- // restore hwnd to original size and position |
- ::SetWindowPos(_hWnd, HWND_NOTOPMOST, _originalHwndRect.left, |
- _originalHwndRect.top, _originalHwndRect.right |
- - _originalHwndRect.left, |
- _originalHwndRect.bottom - _originalHwndRect.top, |
- SWP_FRAMECHANGED); |
- ::RedrawWindow(_hWnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW |
- | RDW_ERASE); |
- ::RedrawWindow(NULL, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW |
- | RDW_ERASE); |
- } |
- |
- delete &_refD3DCritsect; |
-} |
- |
-DWORD VideoRenderDirect3D9::GetVertexProcessingCaps() |
-{ |
- D3DCAPS9 caps; |
- DWORD dwVertexProcessing = D3DCREATE_SOFTWARE_VERTEXPROCESSING; |
- if (SUCCEEDED(_pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, |
- &caps))) |
- { |
- if ((caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) |
- == D3DDEVCAPS_HWTRANSFORMANDLIGHT) |
- { |
- dwVertexProcessing = D3DCREATE_HARDWARE_VERTEXPROCESSING; |
- } |
- } |
- return dwVertexProcessing; |
-} |
- |
-int VideoRenderDirect3D9::InitializeD3D(HWND hWnd, |
- D3DPRESENT_PARAMETERS* pd3dpp) |
-{ |
- // initialize Direct3D |
- if (NULL == (_pD3D = Direct3DCreate9(D3D_SDK_VERSION))) |
- { |
- return -1; |
- } |
- |
- // determine what type of vertex processing to use based on the device capabilities |
- DWORD dwVertexProcessing = GetVertexProcessingCaps(); |
- |
- // get the display mode |
- D3DDISPLAYMODE d3ddm; |
- _pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm); |
- pd3dpp->BackBufferFormat = d3ddm.Format; |
- |
- // create the D3D device |
- if (FAILED(_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, |
- dwVertexProcessing | D3DCREATE_MULTITHREADED |
- | D3DCREATE_FPU_PRESERVE, pd3dpp, |
- &_pd3dDevice))) |
- { |
- //try the ref device |
- if (FAILED(_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, |
- hWnd, dwVertexProcessing |
- | D3DCREATE_MULTITHREADED |
- | D3DCREATE_FPU_PRESERVE, |
- pd3dpp, &_pd3dDevice))) |
- { |
- return -1; |
- } |
- } |
- |
- return 0; |
-} |
- |
-int VideoRenderDirect3D9::ResetDevice() |
-{ |
- WEBRTC_TRACE(kTraceInfo, kTraceVideo, -1, |
- "VideoRenderDirect3D9::ResetDevice"); |
- |
- CriticalSectionScoped cs(&_refD3DCritsect); |
- |
- //release the channel texture |
- std::map<int, D3D9Channel*>::iterator it; |
- it = _d3dChannels.begin(); |
- while (it != _d3dChannels.end()) |
- { |
- if (it->second) |
- { |
- it->second->ReleaseTexture(); |
- } |
- it++; |
- } |
- |
- //close d3d device |
- if (CloseDevice() != 0) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceVideo, -1, |
- "VideoRenderDirect3D9::ResetDevice failed to CloseDevice"); |
- return -1; |
- } |
- |
- //reinit d3d device |
- if (InitDevice() != 0) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceVideo, -1, |
- "VideoRenderDirect3D9::ResetDevice failed to InitDevice"); |
- return -1; |
- } |
- |
- //recreate channel texture |
- it = _d3dChannels.begin(); |
- while (it != _d3dChannels.end()) |
- { |
- if (it->second) |
- { |
- it->second->RecreateTexture(_pd3dDevice); |
- } |
- it++; |
- } |
- |
- return 0; |
-} |
- |
-int VideoRenderDirect3D9::InitDevice() |
-{ |
- // Set up the structure used to create the D3DDevice |
- ZeroMemory(&_d3dpp, sizeof(_d3dpp)); |
- _d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; |
- _d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8; |
- if (GetWindowRect(_hWnd, &_originalHwndRect) == 0) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceVideo, -1, |
- "VideoRenderDirect3D9::InitDevice Could not get window size"); |
- return -1; |
- } |
- if (!_fullScreen) |
- { |
- _winWidth = _originalHwndRect.right - _originalHwndRect.left; |
- _winHeight = _originalHwndRect.bottom - _originalHwndRect.top; |
- _d3dpp.Windowed = TRUE; |
- _d3dpp.BackBufferHeight = 0; |
- _d3dpp.BackBufferWidth = 0; |
- } |
- else |
- { |
- _winWidth = (LONG) ::GetSystemMetrics(SM_CXSCREEN); |
- _winHeight = (LONG) ::GetSystemMetrics(SM_CYSCREEN); |
- _d3dpp.Windowed = FALSE; |
- _d3dpp.BackBufferWidth = _winWidth; |
- _d3dpp.BackBufferHeight = _winHeight; |
- _d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; |
- } |
- |
- if (InitializeD3D(_hWnd, &_d3dpp) == -1) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceVideo, -1, |
- "VideoRenderDirect3D9::InitDevice failed in InitializeD3D"); |
- return -1; |
- } |
- |
- // Turn off culling, so we see the front and back of the triangle |
- _pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); |
- |
- // Turn off D3D lighting, since we are providing our own vertex colors |
- _pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE); |
- |
- // Settings for alpha blending |
- _pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); |
- _pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); |
- _pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); |
- |
- _pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); |
- _pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); |
- _pd3dDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR ); |
- |
- // Initialize Vertices |
- CUSTOMVERTEX Vertices[] = { |
- //front |
- { -1.0f, -1.0f, 0.0f, 0xffffffff, 0, 1 }, { -1.0f, 1.0f, 0.0f, |
- 0xffffffff, 0, 0 }, |
- { 1.0f, -1.0f, 0.0f, 0xffffffff, 1, 1 }, { 1.0f, 1.0f, 0.0f, |
- 0xffffffff, 1, 0 } }; |
- |
- // Create the vertex buffer. |
- if (FAILED(_pd3dDevice->CreateVertexBuffer(sizeof(Vertices), 0, |
- D3DFVF_CUSTOMVERTEX, |
- D3DPOOL_DEFAULT, &_pVB, NULL ))) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceVideo, -1, |
- "Failed to create the vertex buffer."); |
- return -1; |
- } |
- |
- // Now we fill the vertex buffer. |
- VOID* pVertices; |
- if (FAILED(_pVB->Lock(0, sizeof(Vertices), (void**) &pVertices, 0))) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceVideo, -1, |
- "Failed to lock the vertex buffer."); |
- return -1; |
- } |
- memcpy(pVertices, Vertices, sizeof(Vertices)); |
- _pVB->Unlock(); |
- |
- return 0; |
-} |
- |
-int32_t VideoRenderDirect3D9::Init() |
-{ |
- WEBRTC_TRACE(kTraceInfo, kTraceVideo, -1, |
- "VideoRenderDirect3D9::Init"); |
- |
- CriticalSectionScoped cs(&_refD3DCritsect); |
- |
- // Start rendering thread... |
- if (!_screenUpdateThread) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceVideo, -1, "Thread not created"); |
- return -1; |
- } |
- _screenUpdateThread->Start(); |
- _screenUpdateThread->SetPriority(rtc::kRealtimePriority); |
- |
- // Start the event triggering the render process |
- unsigned int monitorFreq = 60; |
- DEVMODE dm; |
- // initialize the DEVMODE structure |
- ZeroMemory(&dm, sizeof(dm)); |
- dm.dmSize = sizeof(dm); |
- if (0 != EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm)) |
- { |
- monitorFreq = dm.dmDisplayFrequency; |
- } |
- _screenUpdateEvent->StartTimer(true, 1000 / monitorFreq); |
- |
- return InitDevice(); |
-} |
- |
-int32_t VideoRenderDirect3D9::ChangeWindow(void* window) |
-{ |
- WEBRTC_TRACE(kTraceError, kTraceVideo, -1, "Not supported."); |
- return -1; |
-} |
- |
-int VideoRenderDirect3D9::UpdateRenderSurface() |
-{ |
- CriticalSectionScoped cs(&_refD3DCritsect); |
- |
- // Check if there are any updated buffers |
- bool updated = false; |
- std::map<int, D3D9Channel*>::iterator it; |
- it = _d3dChannels.begin(); |
- while (it != _d3dChannels.end()) |
- { |
- |
- D3D9Channel* channel = it->second; |
- channel->IsUpdated(updated); |
- if (updated) |
- { |
- break; |
- } |
- it++; |
- } |
- //nothing is updated, continue |
- if (!updated) |
- return -1; |
- |
- // Clear the backbuffer to a black color |
- _pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, |
- 0); |
- |
- // Begin the scene |
- if (SUCCEEDED(_pd3dDevice->BeginScene())) |
- { |
- _pd3dDevice->SetStreamSource(0, _pVB, 0, sizeof(CUSTOMVERTEX)); |
- _pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX); |
- |
- //draw all the channels |
- //get texture from the channels |
- LPDIRECT3DTEXTURE9 textureFromChannel = NULL; |
- DWORD textureWidth, textureHeight; |
- |
- std::multimap<int, unsigned int>::reverse_iterator it; |
- it = _d3dZorder.rbegin(); |
- while (it != _d3dZorder.rend()) |
- { |
- // loop through all channels and streams in Z order |
- int channel = it->second & 0x0000ffff; |
- |
- std::map<int, D3D9Channel*>::iterator ddIt; |
- ddIt = _d3dChannels.find(channel); |
- if (ddIt != _d3dChannels.end()) |
- { |
- // found the channel |
- D3D9Channel* channelObj = ddIt->second; |
- if (channelObj) |
- { |
- textureFromChannel = channelObj->GetTexture(); |
- textureWidth = channelObj->GetTextureWidth(); |
- textureHeight = channelObj->GetTextureHeight(); |
- |
- uint32_t zOrder; |
- float startWidth, startHeight, stopWidth, stopHeight; |
- channelObj->GetStreamSettings(0, zOrder, startWidth, |
- startHeight, stopWidth, |
- stopHeight); |
- |
- //draw the video stream |
- UpdateVerticeBuffer(_pVB, 0, startWidth, startHeight, |
- stopWidth, stopHeight); |
- _pd3dDevice->SetTexture(0, textureFromChannel); |
- _pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); |
- |
- //Notice channel that this frame as been rendered |
- channelObj->RenderOffFrame(); |
- } |
- } |
- it++; |
- } |
- |
- //draw the logo |
- if (_pTextureLogo) |
- { |
- UpdateVerticeBuffer(_pVB, 0, _logoLeft, _logoTop, _logoRight, |
- _logoBottom); |
- _pd3dDevice->SetTexture(0, _pTextureLogo); |
- _pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); |
- } |
- |
- // End the scene |
- _pd3dDevice->EndScene(); |
- } |
- |
- // Present the backbuffer contents to the display |
- _pd3dDevice->Present(NULL, NULL, NULL, NULL ); |
- |
- return 0; |
-} |
- |
-//set the alpha value of the pixal with a particular colorkey as 0 |
-int VideoRenderDirect3D9::SetTransparentColor(LPDIRECT3DTEXTURE9 pTexture, |
- DDCOLORKEY* transparentColorKey, |
- DWORD width, |
- DWORD height) |
-{ |
- D3DLOCKED_RECT lr; |
- if (!pTexture) |
- return -1; |
- |
- CriticalSectionScoped cs(&_refD3DCritsect); |
- if (SUCCEEDED(pTexture->LockRect(0, &lr, NULL, D3DLOCK_DISCARD))) |
- { |
- for (DWORD y = 0; y < height; y++) |
- { |
- DWORD dwOffset = y * width; |
- |
- for (DWORD x = 0; x < width; x) |
- { |
- DWORD temp = ((DWORD*) lr.pBits)[dwOffset + x]; |
- if ((temp & 0x00FFFFFF) |
- == transparentColorKey->dwColorSpaceLowValue) |
- { |
- temp &= 0x00FFFFFF; |
- } |
- else |
- { |
- temp |= 0xFF000000; |
- } |
- ((DWORD*) lr.pBits)[dwOffset + x] = temp; |
- x++; |
- } |
- } |
- pTexture->UnlockRect(0); |
- return 0; |
- } |
- return -1; |
-} |
- |
-/* |
- * |
- * Rendering process |
- * |
- */ |
-bool VideoRenderDirect3D9::ScreenUpdateThreadProc(void* obj) |
-{ |
- return static_cast<VideoRenderDirect3D9*> (obj)->ScreenUpdateProcess(); |
-} |
- |
-bool VideoRenderDirect3D9::ScreenUpdateProcess() |
-{ |
- _screenUpdateEvent->Wait(100); |
- |
- if (!_screenUpdateThread) |
- { |
- //stop the thread |
- return false; |
- } |
- if (!_pd3dDevice) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceVideo, -1, |
- "d3dDevice not created."); |
- return true; |
- } |
- |
- HRESULT hr = _pd3dDevice->TestCooperativeLevel(); |
- |
- if (SUCCEEDED(hr)) |
- { |
- UpdateRenderSurface(); |
- } |
- |
- if (hr == D3DERR_DEVICELOST) |
- { |
- //Device is lost and cannot be reset yet |
- |
- } |
- else if (hr == D3DERR_DEVICENOTRESET) |
- { |
- //Lost but we can reset it now |
- //Note: the standard way is to call Reset, however for some reason doesn't work here. |
- //so we will release the device and create it again. |
- ResetDevice(); |
- } |
- |
- return true; |
-} |
- |
-int VideoRenderDirect3D9::CloseDevice() |
-{ |
- CriticalSectionScoped cs(&_refD3DCritsect); |
- WEBRTC_TRACE(kTraceInfo, kTraceVideo, -1, |
- "VideoRenderDirect3D9::CloseDevice"); |
- |
- if (_pTextureLogo != NULL) |
- { |
- _pTextureLogo->Release(); |
- _pTextureLogo = NULL; |
- } |
- |
- if (_pVB != NULL) |
- { |
- _pVB->Release(); |
- _pVB = NULL; |
- } |
- |
- if (_pd3dDevice != NULL) |
- { |
- _pd3dDevice->Release(); |
- _pd3dDevice = NULL; |
- } |
- |
- if (_pD3D != NULL) |
- { |
- _pD3D->Release(); |
- _pD3D = NULL; |
- } |
- |
- if (_pd3dSurface != NULL) |
- _pd3dSurface->Release(); |
- return 0; |
-} |
- |
-D3D9Channel* VideoRenderDirect3D9::GetD3DChannel(int channel) |
-{ |
- std::map<int, D3D9Channel*>::iterator ddIt; |
- ddIt = _d3dChannels.find(channel & 0x0000ffff); |
- D3D9Channel* ddobj = NULL; |
- if (ddIt != _d3dChannels.end()) |
- { |
- ddobj = ddIt->second; |
- } |
- if (ddobj == NULL) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceVideo, -1, |
- "Direct3D render failed to find channel"); |
- return NULL; |
- } |
- return ddobj; |
-} |
- |
-int32_t VideoRenderDirect3D9::DeleteChannel(const uint32_t streamId) |
-{ |
- CriticalSectionScoped cs(&_refD3DCritsect); |
- |
- |
- std::multimap<int, unsigned int>::iterator it; |
- it = _d3dZorder.begin(); |
- while (it != _d3dZorder.end()) |
- { |
- if ((streamId & 0x0000ffff) == (it->second & 0x0000ffff)) |
- { |
- it = _d3dZorder.erase(it); |
- break; |
- } |
- it++; |
- } |
- |
- std::map<int, D3D9Channel*>::iterator ddIt; |
- ddIt = _d3dChannels.find(streamId & 0x0000ffff); |
- if (ddIt != _d3dChannels.end()) |
- { |
- delete ddIt->second; |
- _d3dChannels.erase(ddIt); |
- return 0; |
- } |
- return -1; |
-} |
- |
-VideoRenderCallback* VideoRenderDirect3D9::CreateChannel(const uint32_t channel, |
- const uint32_t zOrder, |
- const float left, |
- const float top, |
- const float right, |
- const float bottom) |
-{ |
- CriticalSectionScoped cs(&_refD3DCritsect); |
- |
- //FIXME this should be done in VideoAPIWindows? stop the frame deliver first |
- //remove the old channel |
- DeleteChannel(channel); |
- |
- D3D9Channel* d3dChannel = new D3D9Channel(_pd3dDevice, |
- &_refD3DCritsect, _trace); |
- d3dChannel->SetStreamSettings(0, zOrder, left, top, right, bottom); |
- |
- // store channel |
- _d3dChannels[channel & 0x0000ffff] = d3dChannel; |
- |
- // store Z order |
- // default streamID is 0 |
- _d3dZorder.insert( |
- std::pair<int, unsigned int>(zOrder, channel & 0x0000ffff)); |
- |
- return d3dChannel; |
-} |
- |
-int32_t VideoRenderDirect3D9::GetStreamSettings(const uint32_t channel, |
- const uint16_t streamId, |
- uint32_t& zOrder, |
- float& left, float& top, |
- float& right, float& bottom) |
-{ |
- std::map<int, D3D9Channel*>::iterator ddIt; |
- ddIt = _d3dChannels.find(channel & 0x0000ffff); |
- D3D9Channel* ddobj = NULL; |
- if (ddIt != _d3dChannels.end()) |
- { |
- ddobj = ddIt->second; |
- } |
- if (ddobj == NULL) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceVideo, -1, |
- "Direct3D render failed to find channel"); |
- return -1; |
- } |
- // Only allow one stream per channel, demuxing is |
- return ddobj->GetStreamSettings(0, zOrder, left, top, right, bottom); |
-} |
- |
-int VideoRenderDirect3D9::UpdateVerticeBuffer(LPDIRECT3DVERTEXBUFFER9 pVB, |
- int offset, |
- float startWidth, |
- float startHeight, |
- float stopWidth, |
- float stopHeight) |
-{ |
- if (pVB == NULL) |
- return -1; |
- |
- float left, right, top, bottom; |
- |
- //update the vertice buffer |
- //0,1 => -1,1 |
- left = startWidth * 2 - 1; |
- right = stopWidth * 2 - 1; |
- |
- //0,1 => 1,-1 |
- top = 1 - startHeight * 2; |
- bottom = 1 - stopHeight * 2; |
- |
- CUSTOMVERTEX newVertices[] = { |
- //logo |
- { left, bottom, 0.0f, 0xffffffff, 0, 1 }, { left, top, 0.0f, |
- 0xffffffff, 0, 0 }, |
- { right, bottom, 0.0f, 0xffffffff, 1, 1 }, { right, top, 0.0f, |
- 0xffffffff, 1, 0 }, }; |
- // Now we fill the vertex buffer. |
- VOID* pVertices; |
- if (FAILED(pVB->Lock(sizeof(CUSTOMVERTEX) * offset, sizeof(newVertices), |
- (void**) &pVertices, 0))) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceVideo, -1, |
- "Failed to lock the vertex buffer."); |
- return -1; |
- } |
- memcpy(pVertices, newVertices, sizeof(newVertices)); |
- pVB->Unlock(); |
- |
- return 0; |
-} |
- |
-int32_t VideoRenderDirect3D9::StartRender() |
-{ |
- WEBRTC_TRACE(kTraceError, kTraceVideo, -1, "Not supported."); |
- return 0; |
-} |
- |
-int32_t VideoRenderDirect3D9::StopRender() |
-{ |
- WEBRTC_TRACE(kTraceError, kTraceVideo, -1, "Not supported."); |
- return 0; |
-} |
- |
-bool VideoRenderDirect3D9::IsFullScreen() |
-{ |
- return _fullScreen; |
-} |
- |
-int32_t VideoRenderDirect3D9::SetCropping(const uint32_t channel, |
- const uint16_t streamId, |
- const float left, const float top, |
- const float right, const float bottom) |
-{ |
- WEBRTC_TRACE(kTraceError, kTraceVideo, -1, "Not supported."); |
- return 0; |
-} |
- |
-int32_t VideoRenderDirect3D9::SetTransparentBackground( |
- const bool enable) |
-{ |
- WEBRTC_TRACE(kTraceError, kTraceVideo, -1, "Not supported."); |
- return 0; |
-} |
- |
-int32_t VideoRenderDirect3D9::SetText(const uint8_t textId, |
- const uint8_t* text, |
- const int32_t textLength, |
- const uint32_t colorText, |
- const uint32_t colorBg, |
- const float left, const float top, |
- const float rigth, const float bottom) |
-{ |
- WEBRTC_TRACE(kTraceError, kTraceVideo, -1, "Not supported."); |
- return 0; |
-} |
- |
-int32_t VideoRenderDirect3D9::SetBitmap(const void* bitMap, |
- const uint8_t pictureId, |
- const void* colorKey, |
- const float left, const float top, |
- const float right, const float bottom) |
-{ |
- if (!bitMap) |
- { |
- if (_pTextureLogo != NULL) |
- { |
- _pTextureLogo->Release(); |
- _pTextureLogo = NULL; |
- } |
- WEBRTC_TRACE(kTraceInfo, kTraceVideo, -1, "Remove bitmap."); |
- return 0; |
- } |
- |
- // sanity |
- if (left > 1.0f || left < 0.0f || |
- top > 1.0f || top < 0.0f || |
- right > 1.0f || right < 0.0f || |
- bottom > 1.0f || bottom < 0.0f) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceVideo, -1, |
- "Direct3D SetBitmap invalid parameter"); |
- return -1; |
- } |
- |
- if ((bottom <= top) || (right <= left)) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceVideo, -1, |
- "Direct3D SetBitmap invalid parameter"); |
- return -1; |
- } |
- |
- CriticalSectionScoped cs(&_refD3DCritsect); |
- |
- unsigned char* srcPtr; |
- HGDIOBJ oldhand; |
- BITMAPINFO pbi; |
- BITMAP bmap; |
- HDC hdcNew; |
- hdcNew = CreateCompatibleDC(0); |
- // Fill out the BITMAP structure. |
- GetObject((HBITMAP)bitMap, sizeof(bmap), &bmap); |
- //Select the bitmap handle into the new device context. |
- oldhand = SelectObject(hdcNew, (HGDIOBJ) bitMap); |
- // we are done with this object |
- DeleteObject(oldhand); |
- pbi.bmiHeader.biSize = 40; |
- pbi.bmiHeader.biWidth = bmap.bmWidth; |
- pbi.bmiHeader.biHeight = bmap.bmHeight; |
- pbi.bmiHeader.biPlanes = 1; |
- pbi.bmiHeader.biBitCount = bmap.bmBitsPixel; |
- pbi.bmiHeader.biCompression = BI_RGB; |
- pbi.bmiHeader.biSizeImage = bmap.bmWidth * bmap.bmHeight * 3; |
- srcPtr = new unsigned char[bmap.bmWidth * bmap.bmHeight * 4]; |
- // the original un-stretched image in RGB24 |
- int pixelHeight = GetDIBits(hdcNew, (HBITMAP)bitMap, 0, bmap.bmHeight, srcPtr, &pbi, |
- DIB_RGB_COLORS); |
- if (pixelHeight == 0) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceVideo, -1, |
- "Direct3D failed to GetDIBits in SetBitmap"); |
- delete[] srcPtr; |
- return -1; |
- } |
- DeleteDC(hdcNew); |
- if (pbi.bmiHeader.biBitCount != 24 && pbi.bmiHeader.biBitCount != 32) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceVideo, -1, |
- "Direct3D failed to SetBitmap invalid bit depth"); |
- delete[] srcPtr; |
- return -1; |
- } |
- |
- HRESULT ret; |
- //release the previous logo texture |
- if (_pTextureLogo != NULL) |
- { |
- _pTextureLogo->Release(); |
- _pTextureLogo = NULL; |
- } |
- ret = _pd3dDevice->CreateTexture(bmap.bmWidth, bmap.bmHeight, 1, 0, |
- D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, |
- &_pTextureLogo, NULL); |
- if (FAILED(ret)) |
- { |
- _pTextureLogo = NULL; |
- delete[] srcPtr; |
- return -1; |
- } |
- if (!_pTextureLogo) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceVideo, -1, |
- "Texture for rendering not initialized."); |
- delete[] srcPtr; |
- return -1; |
- } |
- |
- D3DLOCKED_RECT lr; |
- if (FAILED(_pTextureLogo->LockRect(0, &lr, NULL, 0))) |
- { |
- delete[] srcPtr; |
- return -1; |
- } |
- unsigned char* dstPtr = (UCHAR*) lr.pBits; |
- int pitch = bmap.bmWidth * 4; |
- |
- if (pbi.bmiHeader.biBitCount == 24) |
- { |
- ConvertRGB24ToARGB(srcPtr, dstPtr, bmap.bmWidth, bmap.bmHeight, 0); |
- } |
- else |
- { |
- unsigned char* srcTmp = srcPtr + (bmap.bmWidth * 4) * (bmap.bmHeight - 1); |
- for (int i = 0; i < bmap.bmHeight; ++i) |
- { |
- memcpy(dstPtr, srcTmp, bmap.bmWidth * 4); |
- srcTmp -= bmap.bmWidth * 4; |
- dstPtr += pitch; |
- } |
- } |
- |
- delete[] srcPtr; |
- if (FAILED(_pTextureLogo->UnlockRect(0))) |
- { |
- return -1; |
- } |
- |
- if (colorKey) |
- { |
- DDCOLORKEY* ddColorKey = |
- static_cast<DDCOLORKEY*> (const_cast<void*> (colorKey)); |
- SetTransparentColor(_pTextureLogo, ddColorKey, bmap.bmWidth, |
- bmap.bmHeight); |
- } |
- |
- //update the vertice buffer |
- //0,1 => -1,1 |
- _logoLeft = left; |
- _logoRight = right; |
- |
- //0,1 => 1,-1 |
- _logoTop = top; |
- _logoBottom = bottom; |
- |
- return 0; |
- |
-} |
- |
-int32_t VideoRenderDirect3D9::GetGraphicsMemory(uint64_t& totalMemory, |
- uint64_t& availableMemory) |
-{ |
- totalMemory = _totalMemory; |
- availableMemory = _availableMemory; |
- return 0; |
-} |
- |
-int32_t VideoRenderDirect3D9::ConfigureRenderer(const uint32_t channel, |
- const uint16_t streamId, |
- const unsigned int zOrder, |
- const float left, |
- const float top, |
- const float right, |
- const float bottom) |
-{ |
- std::map<int, D3D9Channel*>::iterator ddIt; |
- ddIt = _d3dChannels.find(channel & 0x0000ffff); |
- D3D9Channel* ddobj = NULL; |
- if (ddIt != _d3dChannels.end()) |
- { |
- ddobj = ddIt->second; |
- } |
- if (ddobj == NULL) |
- { |
- WEBRTC_TRACE(kTraceError, kTraceVideo, -1, |
- "Direct3D render failed to find channel"); |
- return -1; |
- } |
- // Only allow one stream per channel, demuxing is |
- ddobj->SetStreamSettings(0, zOrder, left, top, right, bottom); |
- |
- return 0; |
-} |
- |
-} // namespace webrtc |