10e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// libjingle 20e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Copyright 2004 Google Inc. 30e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 40e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Redistribution and use in source and binary forms, with or without 50e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// modification, are permitted provided that the following conditions are met: 60e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 70e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 1. Redistributions of source code must retain the above copyright notice, 80e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// this list of conditions and the following disclaimer. 90e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 2. Redistributions in binary form must reproduce the above copyright notice, 100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// this list of conditions and the following disclaimer in the documentation 110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// and/or other materials provided with the distribution. 120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 3. The name of the author may not be used to endorse or promote products 130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// derived from this software without specific prior written permission. 140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Implementation of GdiVideoRenderer on Windows 270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#ifdef WIN32 290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/media/devices/gdivideorenderer.h" 310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 32cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "talk/media/base/videocommon.h" 33cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "talk/media/base/videoframe.h" 342a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/scoped_ptr.h" 352a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/thread.h" 362a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/win32window.h" 370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgnamespace cricket { 390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org///////////////////////////////////////////////////////////////////////////// 410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Definition of private class VideoWindow. We use a worker thread to manage 420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// the window. 430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org///////////////////////////////////////////////////////////////////////////// 442a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgclass GdiVideoRenderer::VideoWindow : public rtc::Win32Window { 450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org public: 460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org VideoWindow(int x, int y, int width, int height); 470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org virtual ~VideoWindow(); 480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Called when the video size changes. If it is called the first time, we 500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // create and start the thread. Otherwise, we send kSetSizeMsg to the thread. 510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Context: non-worker thread. 520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool SetSize(int width, int height); 530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Called when a new frame is available. Upon this call, we send 550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // kRenderFrameMsg to the window thread. Context: non-worker thread. It may be 560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // better to pass RGB bytes to VideoWindow. However, we pass VideoFrame to put 570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // all the thread synchronization within VideoWindow. 580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool RenderFrame(const VideoFrame* frame); 590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org protected: 612a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org // Override virtual method of rtc::Win32Window. Context: worker Thread. 620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org virtual bool OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, 630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LRESULT& result); 640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org private: 660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org enum { kSetSizeMsg = WM_USER, kRenderFrameMsg}; 670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 682a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org class WindowThread : public rtc::Thread { 690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org public: 700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org explicit WindowThread(VideoWindow* window) : window_(window) {} 710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 72e5b49108d39835fbab2ae1c29eff4542a57a8ed5wu@webrtc.org virtual ~WindowThread() { 73e5b49108d39835fbab2ae1c29eff4542a57a8ed5wu@webrtc.org Stop(); 74e5b49108d39835fbab2ae1c29eff4542a57a8ed5wu@webrtc.org } 75e5b49108d39835fbab2ae1c29eff4542a57a8ed5wu@webrtc.org 762a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org // Override virtual method of rtc::Thread. Context: worker Thread. 770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org virtual void Run() { 780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Initialize the window 790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!window_ || !window_->Initialize()) { 800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return; 810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Run the message loop 830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org MSG msg; 840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org while (GetMessage(&msg, NULL, 0, 0) > 0) { 850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org TranslateMessage(&msg); 860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org DispatchMessage(&msg); 870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org private: 910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org VideoWindow* window_; 920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org }; 930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Context: worker Thread. 950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool Initialize(); 960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org void OnPaint(); 970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org void OnSize(int width, int height, bool frame_changed); 980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org void OnRenderFrame(const VideoFrame* frame); 990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org BITMAPINFO bmi_; 1012a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org rtc::scoped_ptr<uint8[]> image_; 1022a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org rtc::scoped_ptr<WindowThread> window_thread_; 1030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // The initial position of the window. 1040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int initial_x_; 1050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int initial_y_; 1060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}; 1070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org///////////////////////////////////////////////////////////////////////////// 1090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Implementation of class VideoWindow 1100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org///////////////////////////////////////////////////////////////////////////// 1110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgGdiVideoRenderer::VideoWindow::VideoWindow( 1120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int x, int y, int width, int height) 1130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org : initial_x_(x), 1140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org initial_y_(y) { 1150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org memset(&bmi_.bmiHeader, 0, sizeof(bmi_.bmiHeader)); 1160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bmi_.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 1170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bmi_.bmiHeader.biPlanes = 1; 1180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bmi_.bmiHeader.biBitCount = 32; 1190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bmi_.bmiHeader.biCompression = BI_RGB; 1200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bmi_.bmiHeader.biWidth = width; 1210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bmi_.bmiHeader.biHeight = -height; 1220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bmi_.bmiHeader.biSizeImage = width * height * 4; 1230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org image_.reset(new uint8[bmi_.bmiHeader.biSizeImage]); 1250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgGdiVideoRenderer::VideoWindow::~VideoWindow() { 1280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Context: caller Thread. We cannot call Destroy() since the window was 1290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // created by another thread. Instead, we send WM_CLOSE message. 1300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (handle()) { 1310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SendMessage(handle(), WM_CLOSE, 0, 0); 1320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool GdiVideoRenderer::VideoWindow::SetSize(int width, int height) { 1360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!window_thread_.get()) { 1370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Create and start the window thread. 1380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org window_thread_.reset(new WindowThread(this)); 1390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return window_thread_->Start(); 1400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (width != bmi_.bmiHeader.biWidth || 1410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org height != -bmi_.bmiHeader.biHeight) { 1420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SendMessage(handle(), kSetSizeMsg, 0, MAKELPARAM(width, height)); 1430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 1450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool GdiVideoRenderer::VideoWindow::RenderFrame(const VideoFrame* frame) { 1480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!handle()) { 1490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 1500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SendMessage(handle(), kRenderFrameMsg, reinterpret_cast<WPARAM>(frame), 0); 1530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 1540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool GdiVideoRenderer::VideoWindow::OnMessage(UINT uMsg, WPARAM wParam, 1570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LPARAM lParam, LRESULT& result) { 1580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org switch (uMsg) { 1590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case WM_PAINT: 1600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org OnPaint(); 1610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 1620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case WM_DESTROY: 1640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org PostQuitMessage(0); // post WM_QUIT to end the message loop in Run() 1650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 1660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case WM_SIZE: // The window UI was resized. 1680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org OnSize(LOWORD(lParam), HIWORD(lParam), false); 1690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 1700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case kSetSizeMsg: // The video resolution changed. 1720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org OnSize(LOWORD(lParam), HIWORD(lParam), true); 1730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 1740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case kRenderFrameMsg: 1760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org OnRenderFrame(reinterpret_cast<const VideoFrame*>(wParam)); 1770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 1780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 1800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool GdiVideoRenderer::VideoWindow::Initialize() { 1832a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org if (!rtc::Win32Window::Create( 1840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org NULL, L"Video Renderer", 1850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org WS_OVERLAPPEDWINDOW | WS_SIZEBOX, 1860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org WS_EX_APPWINDOW, 1870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org initial_x_, initial_y_, 1880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bmi_.bmiHeader.biWidth, -bmi_.bmiHeader.biHeight)) { 1890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 1900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org OnSize(bmi_.bmiHeader.biWidth, -bmi_.bmiHeader.biHeight, false); 1920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 1930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid GdiVideoRenderer::VideoWindow::OnPaint() { 1960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org RECT rcClient; 1970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org GetClientRect(handle(), &rcClient); 1980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org PAINTSTRUCT ps; 1990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org HDC hdc = BeginPaint(handle(), &ps); 2000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org StretchDIBits(hdc, 2010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 0, 0, rcClient.right, rcClient.bottom, // destination rect 2020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 0, 0, bmi_.bmiHeader.biWidth, -bmi_.bmiHeader.biHeight, // source rect 2030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org image_.get(), &bmi_, DIB_RGB_COLORS, SRCCOPY); 2040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org EndPaint(handle(), &ps); 2050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid GdiVideoRenderer::VideoWindow::OnSize(int width, int height, 2080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool frame_changed) { 2090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Get window and client sizes 2100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org RECT rcClient, rcWindow; 2110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org GetClientRect(handle(), &rcClient); 2120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org GetWindowRect(handle(), &rcWindow); 2130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Find offset between window size and client size 2150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org POINT ptDiff; 2160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ptDiff.x = (rcWindow.right - rcWindow.left) - rcClient.right; 2170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ptDiff.y = (rcWindow.bottom - rcWindow.top) - rcClient.bottom; 2180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Resize client 2200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org MoveWindow(handle(), rcWindow.left, rcWindow.top, 2210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org width + ptDiff.x, height + ptDiff.y, false); 2220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org UpdateWindow(handle()); 2230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ShowWindow(handle(), SW_SHOW); 2240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (frame_changed && (width != bmi_.bmiHeader.biWidth || 2260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org height != -bmi_.bmiHeader.biHeight)) { 2270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Update the bmi and image buffer 2280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bmi_.bmiHeader.biWidth = width; 2290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bmi_.bmiHeader.biHeight = -height; 2300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bmi_.bmiHeader.biSizeImage = width * height * 4; 2310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org image_.reset(new uint8[bmi_.bmiHeader.biSizeImage]); 2320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid GdiVideoRenderer::VideoWindow::OnRenderFrame(const VideoFrame* frame) { 2360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!frame) { 2370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return; 2380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Convert frame to ARGB format, which is accepted by GDI 2400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org frame->ConvertToRgbBuffer(cricket::FOURCC_ARGB, image_.get(), 2410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bmi_.bmiHeader.biSizeImage, 2420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bmi_.bmiHeader.biWidth * 4); 2430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org InvalidateRect(handle(), 0, 0); 2440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org///////////////////////////////////////////////////////////////////////////// 2470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Implementation of class GdiVideoRenderer 2480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org///////////////////////////////////////////////////////////////////////////// 2490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgGdiVideoRenderer::GdiVideoRenderer(int x, int y) 2500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org : initial_x_(x), 2510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org initial_y_(y) { 2520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgGdiVideoRenderer::~GdiVideoRenderer() {} 2540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool GdiVideoRenderer::SetSize(int width, int height, int reserved) { 2560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!window_.get()) { // Create the window for the first frame 2570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org window_.reset(new VideoWindow(initial_x_, initial_y_, width, height)); 2580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return window_->SetSize(width, height); 2600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool GdiVideoRenderer::RenderFrame(const VideoFrame* frame) { 2630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!frame || !window_.get()) { 2640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 2650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return window_->RenderFrame(frame); 2670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} // namespace cricket 2700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // WIN32 271