Bug 1038926 - implement window sharing in webrtc/getUserMedia r=jesup,gcp,smaug
authorRandell Jesup <rjesup@jesup.org>
Thu, 17 Jul 2014 22:23:00 -0400
changeset 216734 0f969f1ac011ff681230056c764f5264a7f38487
parent 216733 bc39c9162ca97497980230168798c1f8c14f215a
child 216735 2b3118f75b54bf6318ef5594f0a0772803ebeee5
push id515
push userraliiev@mozilla.com
push dateMon, 06 Oct 2014 12:51:51 +0000
treeherdermozilla-release@267c7a481bef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjesup, gcp, smaug
bugs1038926
milestone33.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1038926 - implement window sharing in webrtc/getUserMedia r=jesup,gcp,smaug
content/media/webrtc/MediaEngineWebRTC.cpp
content/media/webrtc/MediaEngineWebRTC.h
dom/webidl/Constraints.webidl
media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_device_info.cc
media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_device_info.h
media/webrtc/trunk/webrtc/modules/desktop_capture/mac/desktop_device_info_mac.mm
media/webrtc/trunk/webrtc/modules/desktop_capture/win/desktop_device_info_win.cc
media/webrtc/trunk/webrtc/modules/desktop_capture/x11/desktop_device_info_x11.cc
media/webrtc/trunk/webrtc/video_engine/desktop_capture_impl.cc
media/webrtc/trunk/webrtc/video_engine/desktop_capture_impl.h
media/webrtc/trunk/webrtc/video_engine/vie_capturer.cc
media/webrtc/trunk/webrtc/video_engine/vie_input_manager.cc
--- a/content/media/webrtc/MediaEngineWebRTC.cpp
+++ b/content/media/webrtc/MediaEngineWebRTC.cpp
@@ -42,16 +42,17 @@ GetUserMediaLog()
 #undef LOG
 #define LOG(args) PR_LOG(GetUserMediaLog(), PR_LOG_DEBUG, args)
 
 namespace mozilla {
 
 MediaEngineWebRTC::MediaEngineWebRTC(MediaEnginePrefs &aPrefs)
     : mMutex("mozilla::MediaEngineWebRTC")
     , mScreenEngine(nullptr)
+    , mWinEngine(nullptr)
     , mAppEngine(nullptr)
     , mVideoEngine(nullptr)
     , mVoiceEngine(nullptr)
     , mVideoEngineInit(false)
     , mAudioEngineInit(false)
     , mScreenEngineInit(false)
     , mAppEngineInit(false)
 {
@@ -132,16 +133,27 @@ MediaEngineWebRTC::EnumerateVideoDevices
 
   if (webrtc::VideoEngine::SetAndroidObjects(jvm) != 0) {
     LOG(("VieCapture:SetAndroidObjects Failed"));
     return;
   }
 #endif
 
   switch (aMediaSource) {
+    case dom::MediaSourceEnum::Window:
+      mWinEngineConfig.Set<webrtc::CaptureDeviceInfo>(
+          new webrtc::CaptureDeviceInfo(webrtc::CaptureDeviceType::Window));
+      if (!mWinEngine) {
+        if (!(mWinEngine = webrtc::VideoEngine::Create(mWinEngineConfig))) {
+          return;
+        }
+      }
+      videoEngine = mWinEngine;
+      videoEngineInit = &mWinEngineInit;
+      break;
     case dom::MediaSourceEnum::Application:
       mAppEngineConfig.Set<webrtc::CaptureDeviceInfo>(
           new webrtc::CaptureDeviceInfo(webrtc::CaptureDeviceType::Application));
       if (!mAppEngine) {
         if (!(mAppEngine = webrtc::VideoEngine::Create(mAppEngineConfig))) {
           return;
         }
       }
--- a/content/media/webrtc/MediaEngineWebRTC.h
+++ b/content/media/webrtc/MediaEngineWebRTC.h
@@ -405,28 +405,31 @@ private:
   }
 
   nsCOMPtr<nsIThread> mThread;
 
   Mutex mMutex;
 
   // protected with mMutex:
   webrtc::VideoEngine* mScreenEngine;
+  webrtc::VideoEngine* mWinEngine;
   webrtc::VideoEngine* mAppEngine;
   webrtc::VideoEngine* mVideoEngine;
   webrtc::VoiceEngine* mVoiceEngine;
 
   // specialized configurations
   webrtc::Config mAppEngineConfig;
+  webrtc::Config mWinEngineConfig;
   webrtc::Config mScreenEngineConfig;
 
   // Need this to avoid unneccesary WebRTC calls while enumerating.
   bool mVideoEngineInit;
   bool mAudioEngineInit;
   bool mScreenEngineInit;
+  bool mWinEngineInit;
   bool mAppEngineInit;
   bool mHasTabVideoSource;
 
   // Store devices we've already seen in a hashtable for quick return.
   // Maps UUID to MediaEngineSource (one set for audio, one for video).
   nsRefPtrHashtable<nsStringHashKey, MediaEngineWebRTCVideoSource > mVideoSources;
   nsRefPtrHashtable<nsStringHashKey, MediaEngineWebRTCAudioSource > mAudioSources;
 };
--- a/dom/webidl/Constraints.webidl
+++ b/dom/webidl/Constraints.webidl
@@ -12,17 +12,18 @@ enum VideoFacingModeEnum {
     "environment",
     "left",
     "right"
 };
 
 enum MediaSourceEnum {
     "camera",
     "screen",
-    "application"
+    "application",
+    "window"
 };
 
 dictionary ConstrainLongRange {
     long min = -2147483647; // +1 works around windows compiler bug
     long max = 2147483647;
 };
 
 dictionary ConstrainDoubleRange {
--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_device_info.cc
+++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_device_info.cc
@@ -1,15 +1,18 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "webrtc/modules/desktop_capture/desktop_device_info.h"
+#include "webrtc/modules/desktop_capture/window_capturer.h"
 
 #include <cstddef>
+#include <cstdlib>
+#include <cstdio>
 #include <cstring>
 
 namespace webrtc {
 
 static inline void SetStringMember(char **member, const char *value) {
   if (!value) {
     return;
   }
@@ -133,29 +136,33 @@ DesktopApplication& DesktopApplication::
 
 DesktopDeviceInfoImpl::DesktopDeviceInfoImpl() {
 }
 
 DesktopDeviceInfoImpl::~DesktopDeviceInfoImpl() {
   std::map<intptr_t,DesktopDisplayDevice*>::iterator iterDevice;
   for (iterDevice=desktop_display_list_.begin(); iterDevice!=desktop_display_list_.end(); iterDevice++){
     DesktopDisplayDevice * pDesktopDisplayDevice = iterDevice->second;
-    if (pDesktopDisplayDevice) {
-      delete pDesktopDisplayDevice;
-    }
+    delete pDesktopDisplayDevice;
     iterDevice->second = NULL;
   }
   desktop_display_list_.clear();
 
+  std::map<intptr_t, DesktopDisplayDevice *>::iterator itrWindow;
+  for (itrWindow = desktop_window_list_.begin(); itrWindow != desktop_window_list_.end(); itrWindow++) {
+    DesktopDisplayDevice *pWindow = itrWindow->second;
+    delete pWindow;
+    itrWindow->second = NULL;
+  }
+  desktop_window_list_.clear();
+
   std::map<intptr_t,DesktopApplication*>::iterator iterApp;
   for (iterApp=desktop_application_list_.begin(); iterApp!=desktop_application_list_.end(); iterApp++){
     DesktopApplication * pDesktopApplication = iterApp->second;
-    if (pDesktopApplication) {
-      delete pDesktopApplication;
-    }
+    delete pDesktopApplication;
     iterApp->second = NULL;
   }
   desktop_application_list_.clear();
 }
 
 int32_t DesktopDeviceInfoImpl::getDisplayDeviceCount() {
   return desktop_display_list_.size();
 }
@@ -171,16 +178,36 @@ int32_t DesktopDeviceInfoImpl::getDeskto
   DesktopDisplayDevice * pDesktopDisplayDevice = iter->second;
   if(pDesktopDisplayDevice) {
     desktopDisplayDevice = (*pDesktopDisplayDevice);
   }
 
   return 0;
 }
 
+int32_t DesktopDeviceInfoImpl::getWindowCount() {
+  return desktop_window_list_.size();
+}
+int32_t DesktopDeviceInfoImpl::getWindowInfo(int32_t nIndex,
+                                             DesktopDisplayDevice &windowDevice) {
+  if (nIndex < 0 || nIndex >= desktop_window_list_.size()) {
+    return -1;
+  }
+
+  std::map<intptr_t, DesktopDisplayDevice *>::iterator itr = desktop_window_list_.begin();
+  std::advance(itr, nIndex);
+  DesktopDisplayDevice *pWindow = itr->second;
+  if (!pWindow) {
+    return -1;
+  }
+
+  windowDevice = (*pWindow);
+  return 0;
+}
+
 int32_t DesktopDeviceInfoImpl::getApplicationCount() {
   return desktop_application_list_.size();
 }
 
 int32_t DesktopDeviceInfoImpl::getApplicationInfo(int32_t nIndex,
                                                   DesktopApplication & desktopApplication) {
   if(nIndex < 0 || nIndex >= desktop_application_list_.size()) {
     return -1;
@@ -191,9 +218,37 @@ int32_t DesktopDeviceInfoImpl::getApplic
   DesktopApplication * pDesktopApplication = iter->second;
   if (pDesktopApplication) {
     desktopApplication = (*pDesktopApplication);
   }
 
   return 0;
 }
 
+int32_t DesktopDeviceInfoImpl::initializeWindowList() {
+  WindowCapturer *pWinCap = WindowCapturer::Create();
+  WindowCapturer::WindowList list;
+  if (pWinCap && pWinCap->GetWindowList(&list)) {
+    WindowCapturer::WindowList::iterator itr;
+    for (itr = list.begin(); itr != list.end(); itr++) {
+      DesktopDisplayDevice *pWinDevice = new DesktopDisplayDevice;
+      if (!pWinDevice) {
+        continue;
+      }
+
+      pWinDevice->setScreenId(itr->id);
+      pWinDevice->setDeviceName(itr->title.c_str());
+
+      char idStr[64];
+#if XP_WIN
+      _snprintf_s(idStr, sizeof(idStr), sizeof(idStr) - 1, "\\win\\%ld", pWinDevice->getScreenId());
+#else
+      snprintf(idStr, BUFSIZ, "\\win\\%ld", pWinDevice->getScreenId());
+#endif
+      pWinDevice->setUniqueIdName(idStr);
+      desktop_window_list_[pWinDevice->getScreenId()] = pWinDevice;
+    }
+  }
+
+  return 0;
 }
+
+}
--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_device_info.h
+++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_device_info.h
@@ -62,34 +62,43 @@ typedef std::map<intptr_t,DesktopApplica
 class DesktopDeviceInfo {
 public:
   virtual ~DesktopDeviceInfo() {};
 
   virtual int32_t Init() = 0;
   virtual int32_t getDisplayDeviceCount() = 0;
   virtual int32_t getDesktopDisplayDeviceInfo(int32_t nIndex,
                                               DesktopDisplayDevice & desktopDisplayDevice) = 0;
+  virtual int32_t getWindowCount() = 0;
+  virtual int32_t getWindowInfo(int32_t nindex,
+                                DesktopDisplayDevice &windowDevice) = 0;
   virtual int32_t getApplicationCount() = 0;
   virtual int32_t getApplicationInfo(int32_t nIndex,
                                      DesktopApplication & desktopApplication) = 0;
 };
 
 class DesktopDeviceInfoImpl : public DesktopDeviceInfo {
 public:
   DesktopDeviceInfoImpl();
   ~DesktopDeviceInfoImpl();
 
   virtual int32_t getDisplayDeviceCount();
   virtual int32_t getDesktopDisplayDeviceInfo(int32_t nIndex,
                                               DesktopDisplayDevice & desktopDisplayDevice);
+  virtual int32_t getWindowCount();
+  virtual int32_t getWindowInfo(int32_t nindex,
+                                DesktopDisplayDevice &windowDevice);
   virtual int32_t getApplicationCount();
   virtual int32_t getApplicationInfo(int32_t nIndex,
                                      DesktopApplication & desktopApplication);
 
   static DesktopDeviceInfo * Create();
 
 protected:
   DesktopDisplayDeviceList desktop_display_list_;
+  DesktopDisplayDeviceList desktop_window_list_;
   DesktopApplicationList desktop_application_list_;
+
+  int32_t initializeWindowList();
 };
 };
 
 #endif
--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/mac/desktop_device_info_mac.mm
+++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/mac/desktop_device_info_mac.mm
@@ -29,12 +29,15 @@ int32_t DesktopDeviceInfoMac::Init() {
   DesktopDisplayDevice *pDesktopDeviceInfo = new DesktopDisplayDevice;
   if(pDesktopDeviceInfo) {
     pDesktopDeviceInfo->setScreenId(0);
     pDesktopDeviceInfo->setDeviceName("Primary Monitor");
     pDesktopDeviceInfo->setUniqueIdName("\\screen\\monitor#1");
     desktop_display_list_[pDesktopDeviceInfo->getScreenId()] = pDesktopDeviceInfo;
   }
 #endif
+
+  initializeWindowList();
+
   return 0;
 }
 
 } //namespace webrtc
--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/win/desktop_device_info_win.cc
+++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/win/desktop_device_info_win.cc
@@ -27,12 +27,15 @@ int32_t DesktopDeviceInfoWin::Init() {
   if (pDesktopDeviceInfo) {
     pDesktopDeviceInfo->setScreenId(0);
     pDesktopDeviceInfo->setDeviceName("Primary Monitor");
     pDesktopDeviceInfo->setUniqueIdName("\\screen\\monitor#1");
 
     desktop_display_list_[pDesktopDeviceInfo->getScreenId()] = pDesktopDeviceInfo;
   }
 #endif
+
+  initializeWindowList();
+
   return 0;
 }
 
 } //namespace webrtc
--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/x11/desktop_device_info_x11.cc
+++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/x11/desktop_device_info_x11.cc
@@ -28,12 +28,15 @@ int32_t DesktopDeviceInfoX11::Init() {
   if(pDesktopDeviceInfo){
     pDesktopDeviceInfo->setScreenId(0);
     pDesktopDeviceInfo->setDeviceName("Primary Monitor");
     pDesktopDeviceInfo->setUniqueIdName("\\screen\\monitor#1");
 
     desktop_display_list_[pDesktopDeviceInfo->getScreenId()] = pDesktopDeviceInfo;
   }
 #endif
+
+  initializeWindowList();
+
   return 0;
 }
 
 } //namespace webrtc
--- a/media/webrtc/trunk/webrtc/video_engine/desktop_capture_impl.cc
+++ b/media/webrtc/trunk/webrtc/video_engine/desktop_capture_impl.cc
@@ -6,30 +6,32 @@
  *  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.
  */
 
 #include "webrtc/modules/video_capture/video_capture_impl.h"
 
 #include <stdlib.h>
+#include <string>
 
 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
 #include "webrtc/modules/interface/module_common_types.h"
 #include "webrtc/modules/video_capture/video_capture_config.h"
 #include "webrtc/system_wrappers/interface/clock.h"
 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
 #include "webrtc/system_wrappers/interface/ref_count.h"
 #include "webrtc/system_wrappers/interface/tick_util.h"
 #include "webrtc/system_wrappers/interface/trace.h"
 #include "webrtc/system_wrappers/interface/trace_event.h"
 #include "webrtc/video_engine/desktop_capture_impl.h"
 #include "webrtc/modules/desktop_capture/desktop_frame.h"
 #include "webrtc/modules/desktop_capture/desktop_device_info.h"
 #include "webrtc/modules/desktop_capture/app_capturer.h"
+#include "webrtc/modules/desktop_capture/window_capturer.h"
 #include "webrtc/modules/desktop_capture/desktop_capture_options.h"
 
 namespace webrtc {
 
 ScreenDeviceInfoImpl::ScreenDeviceInfoImpl(const int32_t id) : _id(id) {
 }
 
 ScreenDeviceInfoImpl::~ScreenDeviceInfoImpl(void) {
@@ -204,82 +206,193 @@ int32_t AppDeviceInfoImpl::GetBestMatche
 
 int32_t AppDeviceInfoImpl::GetOrientation(const char* deviceUniqueIdUTF8,
                                           VideoCaptureRotation& orientation) {
   return 0;
 }
 
 VideoCaptureModule* DesktopCaptureImpl::Create(const int32_t id,
                                                const char* uniqueId,
-                                               const bool bIsApp) {
+                                               const CaptureDeviceType type) {
   RefCountImpl<DesktopCaptureImpl>* capture = new RefCountImpl<DesktopCaptureImpl>(id);
 
   //create real screen capturer.
-  if (capture->Init(uniqueId, bIsApp) != 0) {
+  if (capture->Init(uniqueId, type)) {
     delete capture;
     return NULL;
   }
 
   return capture;
 }
 
+int32_t WindowDeviceInfoImpl::Init() {
+  desktop_device_info_.reset(DesktopDeviceInfoImpl::Create());
+  return 0;
+}
+
+uint32_t WindowDeviceInfoImpl::NumberOfDevices() {
+  return desktop_device_info_->getWindowCount();
+}
+
+int32_t WindowDeviceInfoImpl::GetDeviceName(uint32_t deviceNumber,
+                                            char* deviceNameUTF8,
+                                            uint32_t deviceNameUTF8Length,
+                                            char* deviceUniqueIdUTF8,
+                                            uint32_t deviceUniqueIdUTF8Length,
+                                            char* productUniqueIdUTF8,
+                                            uint32_t productUniqueIdUTF8Length) {
+
+  DesktopDisplayDevice desktopDisplayDevice;
+
+  // always initialize output
+  if (deviceNameUTF8 && deviceNameUTF8Length > 0) {
+    memset(deviceNameUTF8, 0, deviceNameUTF8Length);
+  }
+  if (deviceUniqueIdUTF8 && deviceUniqueIdUTF8Length > 0) {
+    memset(deviceUniqueIdUTF8, 0, deviceUniqueIdUTF8Length);
+  }
+  if (productUniqueIdUTF8 && productUniqueIdUTF8Length > 0) {
+    memset(productUniqueIdUTF8, 0, productUniqueIdUTF8Length);
+  }
+
+  if (desktop_device_info_->getWindowInfo(deviceNumber,
+                                          desktopDisplayDevice) == 0) {
+
+    size_t len;
+
+    const char *deviceName = desktopDisplayDevice.getDeviceName();
+    len = deviceName ? strlen(deviceName) : 0;
+    if (len && deviceNameUTF8 && len <= deviceNameUTF8Length) {
+      memcpy(deviceNameUTF8,
+             deviceName,
+             len);
+    }
+
+    const char *deviceUniqueId = desktopDisplayDevice.getUniqueIdName();
+    len = deviceUniqueId ? strlen(deviceUniqueId) : 0;
+    if (len && deviceUniqueIdUTF8 && len <= deviceUniqueIdUTF8Length) {
+      memcpy(deviceUniqueIdUTF8,
+             deviceUniqueId,
+             len);
+    }
+  }
+
+  return 0;
+}
+
+int32_t WindowDeviceInfoImpl::DisplayCaptureSettingsDialogBox(const char* deviceUniqueIdUTF8,
+                                                              const char* dialogTitleUTF8,
+                                                              void* parentWindow,
+                                                              uint32_t positionX,
+                                                              uint32_t positionY) {
+  // no device properties to change
+  return 0;
+}
+
+int32_t WindowDeviceInfoImpl::NumberOfCapabilities(const char* deviceUniqueIdUTF8) {
+  return 0;
+}
+
+int32_t WindowDeviceInfoImpl::GetCapability(const char* deviceUniqueIdUTF8,
+                                            const uint32_t deviceCapabilityNumber,
+                                            VideoCaptureCapability& capability) {
+  return 0;
+}
+
+int32_t WindowDeviceInfoImpl::GetBestMatchedCapability(const char* deviceUniqueIdUTF8,
+                                                       const VideoCaptureCapability& requested,
+                                                       VideoCaptureCapability& resulting) {
+  return 0;
+}
+
+int32_t WindowDeviceInfoImpl::GetOrientation(const char* deviceUniqueIdUTF8,
+                                             VideoCaptureRotation& orientation) {
+  return 0;
+}
+
 VideoCaptureModule::DeviceInfo* DesktopCaptureImpl::CreateDeviceInfo(const int32_t id,
-                                                                     const bool bIsApp) {
-  if (bIsApp) {
+                                                                     const CaptureDeviceType type) {
+  if (type == Application) {
     AppDeviceInfoImpl * pAppDeviceInfoImpl = new AppDeviceInfoImpl(id);
     if (!pAppDeviceInfoImpl || pAppDeviceInfoImpl->Init()) {
       delete pAppDeviceInfoImpl;
       pAppDeviceInfoImpl = NULL;
     }
     return pAppDeviceInfoImpl;
-  } else {
+  } else if (type == Screen) {
     ScreenDeviceInfoImpl * pScreenDeviceInfoImpl = new ScreenDeviceInfoImpl(id);
     if (!pScreenDeviceInfoImpl || pScreenDeviceInfoImpl->Init()) {
       delete pScreenDeviceInfoImpl;
       pScreenDeviceInfoImpl = NULL;
     }
     return pScreenDeviceInfoImpl;
+  } else if (type == Window) {
+    WindowDeviceInfoImpl * pWindowDeviceInfoImpl = new WindowDeviceInfoImpl(id);
+    if (!pWindowDeviceInfoImpl || pWindowDeviceInfoImpl->Init()) {
+      delete pWindowDeviceInfoImpl;
+      pWindowDeviceInfoImpl = NULL;
+    }
+    return pWindowDeviceInfoImpl;
   }
+  return NULL;
 }
 
 const char* DesktopCaptureImpl::CurrentDeviceName() const {
   return _deviceUniqueId;
 }
 
 int32_t DesktopCaptureImpl::ChangeUniqueId(const int32_t id) {
   _id = id;
   return 0;
 }
 
 int32_t DesktopCaptureImpl::Init(const char* uniqueId,
-                                 const bool bIsApp) {
-  if (bIsApp) {
+                                 const CaptureDeviceType type) {
+  if (type == Application) {
     AppCapturer *pAppCapturer = AppCapturer::Create();
     if (!pAppCapturer) {
       return -1;
     }
 
     // processid hard-coded until implemented.  See Bug 1036653
     ProcessId processid = 0;
     pAppCapturer->SelectApp(processid);
 
     MouseCursorMonitor * pMouseCursorMonitor = MouseCursorMonitor::CreateForScreen(webrtc::DesktopCaptureOptions::CreateDefault(), webrtc::kFullDesktopScreenId);
     desktop_capturer_cursor_composer_.reset(new DesktopAndCursorComposer(pAppCapturer, pMouseCursorMonitor));
-  } else {
+  } else if (type == Screen) {
     ScreenCapturer *pScreenCapturer = ScreenCapturer::Create();
     if (!pScreenCapturer) {
       return -1;
     }
 
     ScreenId screenid = webrtc::kFullDesktopScreenId;
     pScreenCapturer->SelectScreen(screenid);
     pScreenCapturer->SetMouseShapeObserver(this);
 
     MouseCursorMonitor * pMouseCursorMonitor = MouseCursorMonitor::CreateForScreen(webrtc::DesktopCaptureOptions::CreateDefault(), screenid);
     desktop_capturer_cursor_composer_.reset(new DesktopAndCursorComposer(pScreenCapturer, pMouseCursorMonitor));
+  } else if (type == Window) {
+    WindowCapturer *pWindowCapturer = WindowCapturer::Create();
+    if (!pWindowCapturer) {
+      return -1;
+    }
+
+    std::string idStr(uniqueId);
+    const std::string prefix("\\win\\");
+    if (idStr.substr(0, prefix.size()) != prefix) {
+      // invalid id
+      return -1;
+    }
+    WindowId winId;
+    winId = atoi(idStr.substr(prefix.size()).c_str());
+    pWindowCapturer->SelectWindow(winId);
+
+    MouseCursorMonitor * pMouseCursorMonitor = MouseCursorMonitor::CreateForWindow(webrtc::DesktopCaptureOptions::CreateDefault(), winId);
+    desktop_capturer_cursor_composer_.reset(new DesktopAndCursorComposer(pWindowCapturer,pMouseCursorMonitor));
   }
   return 0;
 }
 
 // returns the number of milliseconds until the module want a worker thread to call Process
 int32_t DesktopCaptureImpl::TimeUntilNextProcess() {
   CriticalSectionScoped cs(&_callBackCs);
 
--- a/media/webrtc/trunk/webrtc/video_engine/desktop_capture_impl.h
+++ b/media/webrtc/trunk/webrtc/video_engine/desktop_capture_impl.h
@@ -20,16 +20,17 @@
 #include "webrtc/modules/desktop_capture/screen_capturer.h"
 #include "webrtc/system_wrappers/interface/tick_util.h"
 #include "webrtc/modules/video_capture/video_capture_config.h"
 #include "webrtc/modules/desktop_capture/shared_memory.h"
 #include "webrtc/system_wrappers/interface/thread_wrapper.h"
 #include "webrtc/modules/desktop_capture/mouse_cursor_shape.h"
 #include "webrtc/modules/desktop_capture/desktop_device_info.h"
 #include "webrtc/modules/desktop_capture/desktop_and_cursor_composer.h"
+#include "webrtc/video_engine/include/vie_capture.h"
 
 using namespace webrtc::videocapturemodule;
 
 namespace webrtc {
 
 class CriticalSectionWrapper;
 class VideoCaptureEncodeInterface;
 
@@ -104,31 +105,68 @@ public:
                                            VideoCaptureCapability& resulting);
   virtual int32_t GetOrientation(const char* deviceUniqueIdUTF8,
                                  VideoCaptureRotation& orientation);
 protected:
   int32_t _id;
   scoped_ptr<DesktopDeviceInfo> desktop_device_info_;
 };
 
+class WindowDeviceInfoImpl : public VideoCaptureModule::DeviceInfo {
+public:
+  WindowDeviceInfoImpl(const int32_t id) : _id(id) {};
+  virtual ~WindowDeviceInfoImpl(void) {};
+
+  int32_t Init();
+
+  virtual uint32_t NumberOfDevices();
+  virtual int32_t GetDeviceName(uint32_t deviceNumber,
+                                char* deviceNameUTF8,
+                                uint32_t deviceNameLength,
+                                char* deviceUniqueIdUTF8,
+                                uint32_t deviceUniqueIdUTF8Length,
+                                char* productUniqueIdUTF8,
+                                uint32_t productUniqueIdUTF8Length);
+
+  virtual int32_t DisplayCaptureSettingsDialogBox(const char* deviceUniqueIdUTF8,
+                                                  const char* dialogTitleUTF8,
+                                                  void* parentWindow,
+                                                  uint32_t positionX,
+                                                  uint32_t positionY);
+  virtual int32_t NumberOfCapabilities(const char* deviceUniqueIdUTF8);
+  virtual int32_t GetCapability(const char* deviceUniqueIdUTF8,
+                                const uint32_t deviceCapabilityNumber,
+                                VideoCaptureCapability& capability);
+
+  virtual int32_t GetBestMatchedCapability(const char* deviceUniqueIdUTF8,
+                                           const VideoCaptureCapability& requested,
+                                           VideoCaptureCapability& resulting);
+  virtual int32_t GetOrientation(const char* deviceUniqueIdUTF8,
+                                 VideoCaptureRotation& orientation);
+protected:
+  int32_t _id;
+  scoped_ptr<DesktopDeviceInfo> desktop_device_info_;
+
+};
+
 // Reuses the video engine pipeline for screen sharing.
 // As with video, DesktopCaptureImpl is a proxy for screen sharing
 // and follows the video pipeline design
 class DesktopCaptureImpl: public VideoCaptureModule,
                           public VideoCaptureExternal,
                           public ScreenCapturer::Callback,
                           public ScreenCapturer::MouseShapeObserver
 {
 public:
   /* Create a screen capture modules object
    */
-  static VideoCaptureModule* Create(const int32_t id, const char* uniqueId, const bool bIsApp);
-  static VideoCaptureModule::DeviceInfo* CreateDeviceInfo(const int32_t id, const bool bIsApp);
+  static VideoCaptureModule* Create(const int32_t id, const char* uniqueId, const CaptureDeviceType type);
+  static VideoCaptureModule::DeviceInfo* CreateDeviceInfo(const int32_t id, const CaptureDeviceType type);
 
-  int32_t Init(const char* uniqueId,const bool bIsApp);
+  int32_t Init(const char* uniqueId, const CaptureDeviceType type);
   // Implements Module declared functions.
   virtual int32_t ChangeUniqueId(const int32_t id) OVERRIDE;
 
   //Call backs
   virtual void RegisterCaptureDataCallback(VideoCaptureDataCallback& dataCallback) OVERRIDE;
   virtual void DeRegisterCaptureDataCallback() OVERRIDE;
   virtual void RegisterCaptureCallback(VideoCaptureFeedBack& callBack) OVERRIDE;
   virtual void DeRegisterCaptureCallback() OVERRIDE;
--- a/media/webrtc/trunk/webrtc/video_engine/vie_capturer.cc
+++ b/media/webrtc/trunk/webrtc/video_engine/vie_capturer.cc
@@ -167,29 +167,18 @@ ViECapturer* ViECapturer::CreateViECaptu
 
 int32_t ViECapturer::Init(const char* device_unique_idUTF8,
                           uint32_t device_unique_idUTF8Length) {
   assert(capture_module_ == NULL);
   CaptureDeviceType type = config_.Get<CaptureDeviceInfo>().type;
 
   if(type != CaptureDeviceType::Camera) {
 #if !defined(ANDROID)
-    switch (type) {
-      case CaptureDeviceType::Screen:
-        capture_module_ = DesktopCaptureImpl::Create(
-            ViEModuleId(engine_id_, capture_id_), device_unique_idUTF8, false);
-        break;
-      case CaptureDeviceType::Application:
-        capture_module_ = DesktopCaptureImpl::Create(
-            ViEModuleId(engine_id_, capture_id_), device_unique_idUTF8, true);
-        break;
-      default:
-        // all other non-camera types are not supported
-        return -1;
-    }
+    capture_module_ = DesktopCaptureImpl::Create(
+      ViEModuleId(engine_id_, capture_id_), device_unique_idUTF8, type);
 #endif
   } else if (device_unique_idUTF8 == NULL) {
     capture_module_  = VideoCaptureFactory::Create(
       ViEModuleId(engine_id_, capture_id_), external_capture_module_);
   } else {
     capture_module_ = VideoCaptureFactory::Create(
       ViEModuleId(engine_id_, capture_id_), device_unique_idUTF8);
   }
--- a/media/webrtc/trunk/webrtc/video_engine/vie_input_manager.cc
+++ b/media/webrtc/trunk/webrtc/video_engine/vie_input_manager.cc
@@ -415,25 +415,21 @@ ViECapturer* ViEInputManager::ViECapture
 
 // Create different DeviceInfo by _config;
 VideoCaptureModule::DeviceInfo* ViEInputManager::GetDeviceInfo() {
   CaptureDeviceType type = config_.Get<CaptureDeviceInfo>().type;
 
   if (capture_device_info_ == NULL) {
     switch (type) {
       case CaptureDeviceType::Screen:
+      case CaptureDeviceType::Application:
+      case CaptureDeviceType::Window:
 #if !defined(ANDROID)
         capture_device_info_ = DesktopCaptureImpl::CreateDeviceInfo(ViEModuleId(engine_id_),
-                                                                    false);
-#endif
-        break;
-      case CaptureDeviceType::Application:
-#if !defined(ANDROID)
-        capture_device_info_ = DesktopCaptureImpl::CreateDeviceInfo(ViEModuleId(engine_id_),
-                                                                    true);
+                                                                    type);
 #endif
         break;
       case CaptureDeviceType::Camera:
         capture_device_info_ = VideoCaptureFactory::CreateDeviceInfo(ViEModuleId(engine_id_));
         break;
       default:
         // Don't try to build anything for unknown/unsupported types
         break;