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 194816 0f969f1ac011ff681230056c764f5264a7f38487
parent 194815 bc39c9162ca97497980230168798c1f8c14f215a
child 194817 2b3118f75b54bf6318ef5594f0a0772803ebeee5
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersjesup, gcp, smaug
bugs1038926
milestone33.0a1
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;