Bug 1300468 - implement mediaDevices.ondevicechange for Windows; r=jesup draft
authorMunro Mengjue Chiang <mchiang@mozilla.com>
Tue, 04 Oct 2016 17:33:25 +0800
changeset 421065 5cac11f44455da8191b8893d606b6e691c447f65
parent 420379 c8a660c5f105e60ad536ddde0c3edd637ab5b7c1
child 532969 81d286e78ef296f2e5361b1a4e179c532046f3ed
push id31377
push userbmo:mchiang@mozilla.com
push dateWed, 05 Oct 2016 08:12:59 +0000
reviewersjesup
bugs1300468
milestone52.0a1
Bug 1300468 - implement mediaDevices.ondevicechange for Windows; r=jesup MozReview-Commit-ID: LD6eiGZEgYP
dom/media/tests/mochitest/mochitest.ini
media/webrtc/trunk/webrtc/modules/video_capture/windows/device_info_ds.cc
media/webrtc/trunk/webrtc/modules/video_capture/windows/device_info_ds.h
--- a/dom/media/tests/mochitest/mochitest.ini
+++ b/dom/media/tests/mochitest/mochitest.ini
@@ -36,17 +36,17 @@ skip-if = toolkit == 'gonk' || buildapp 
 [test_dataChannel_basicVideo.html]
 skip-if = toolkit == 'gonk' || buildapp == 'mulet' || android_version == '18' # b2g(Bug 960442, video support for WebRTC is disabled on b2g), android(Bug 1189784, timeouts on 4.3 emulator)
 [test_dataChannel_bug1013809.html]
 skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g emulator seems to be too slow (Bug 1016498 and 1008080)
 [test_dataChannel_noOffer.html]
 [test_enumerateDevices.html]
 skip-if = buildapp == 'mulet'
 [test_ondevicechange.html]
-skip-if = toolkit == 'gonk' || buildapp == 'mulet' || os == 'win' || os == 'android'
+skip-if = toolkit == 'gonk' || buildapp == 'mulet' || os == 'android'
 [test_getUserMedia_audioCapture.html]
 skip-if = toolkit == 'gonk' || buildapp == 'mulet' || android_version == '18' # b2g emulator seems to be too slow (Bug 1016498 and 1008080), android(Bug 1189784, timeouts on 4.3 emulator)
 [test_getUserMedia_addTrackRemoveTrack.html]
 skip-if = (toolkit == 'gonk' || buildapp == 'mulet' && debug) # debug-only failure
 [test_getUserMedia_addtrack_removetrack_events.html]
 [test_getUserMedia_basicAudio.html]
 skip-if = (toolkit == 'gonk' || buildapp == 'mulet' && debug) # debug-only failure
 [test_getUserMedia_basicVideo.html]
--- a/media/webrtc/trunk/webrtc/modules/video_capture/windows/device_info_ds.cc
+++ b/media/webrtc/trunk/webrtc/modules/video_capture/windows/device_info_ds.cc
@@ -12,16 +12,18 @@
 
 #include "webrtc/modules/video_capture/video_capture_config.h"
 #include "webrtc/modules/video_capture/video_capture_delay.h"
 #include "webrtc/modules/video_capture/windows/help_functions_ds.h"
 #include "webrtc/system_wrappers/interface/ref_count.h"
 #include "webrtc/system_wrappers/interface/trace.h"
 
 #include <Dvdmedia.h>
+#include <dbt.h>
+#include <ks.h>
 
 namespace webrtc
 {
 namespace videocapturemodule
 {
 const int32_t NoWindowsCaptureDelays = 1;
 const DelayValues WindowsCaptureDelays[NoWindowsCaptureDelays] = {
   "Microsoft LifeCam Cinema",
@@ -36,16 +38,29 @@ const DelayValues WindowsCaptureDelays[N
     {160,120,109},
     {1280,720,166},
     {960,544,126},
     {800,448,120},
     {800,600,127}
   },
 };
 
+LRESULT CALLBACK WndProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
+{
+    if (uiMsg == WM_DEVICECHANGE)
+    {
+        DeviceInfoDS* dsInfo = DeviceInfoDSSingleton::GetInfo();
+        if (dsInfo != NULL)
+        {
+            dsInfo->DeviceChange();
+        }
+        return 0;
+    }
+    return DefWindowProc(hWnd, uiMsg, wParam, lParam);
+}
 
 void _FreeMediaType(AM_MEDIA_TYPE& mt)
 {
     if (mt.cbFormat != 0)
     {
         CoTaskMemFree((PVOID)mt.pbFormat);
         mt.cbFormat = 0;
         mt.pbFormat = NULL;
@@ -56,23 +71,26 @@ void _FreeMediaType(AM_MEDIA_TYPE& mt)
         mt.pUnk->Release();
         mt.pUnk = NULL;
     }
 }
 
 // static
 DeviceInfoDS* DeviceInfoDS::Create(const int32_t id)
 {
-    DeviceInfoDS* dsInfo = new DeviceInfoDS(id);
-    if (!dsInfo || dsInfo->Init() != 0)
-    {
-        delete dsInfo;
-        dsInfo = NULL;
+    if (!DeviceInfoDSSingleton::GetInfo()) {
+        DeviceInfoDS* dsInfo = new DeviceInfoDS(id);
+        if (!dsInfo || dsInfo->Init() != 0)
+        {
+            delete dsInfo;
+            dsInfo = NULL;
+        }
+        DeviceInfoDSSingleton::GetInfo() = dsInfo;
     }
-    return dsInfo;
+    return DeviceInfoDSSingleton::GetInfo();
 }
 
 DeviceInfoDS::DeviceInfoDS(const int32_t id)
     : DeviceInfoImpl(id), _dsDevEnum(NULL),
       _CoUninitializeIsRequired(true)
 {
     // 1) Initialize the COM library (make Windows load the DLLs).
     //
@@ -107,25 +125,42 @@ DeviceInfoDS::DeviceInfoDS(const int32_t
             //
             WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCapture, _id,
                          "VideoCaptureWindowsDSInfo::VideoCaptureWindowsDSInfo "
                          "CoInitializeEx(NULL, COINIT_APARTMENTTHREADED) => "
                          "RPC_E_CHANGED_MODE, error 0x%x",
                          hr);
         }
     }
+
+    _hInstance = reinterpret_cast<HINSTANCE>(GetModuleHandle(NULL));
+    _wndClass = {0};
+    _wndClass.lpfnWndProc = &WndProc;
+    _wndClass.lpszClassName = TEXT("DeviceInfoDS");
+    _wndClass.hInstance = _hInstance;
+
+    if (RegisterClass(&_wndClass))
+    {
+        _hwnd = CreateWindow(_wndClass.lpszClassName, NULL, 0, CW_USEDEFAULT,
+            CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, _hInstance, NULL);
+    }
 }
 
 DeviceInfoDS::~DeviceInfoDS()
 {
     RELEASE_AND_CLEAR(_dsDevEnum);
     if (_CoUninitializeIsRequired)
     {
         CoUninitialize();
     }
+    if (_hwnd != NULL)
+    {
+        DestroyWindow(_hwnd);
+    }
+    UnregisterClass(_wndClass.lpszClassName, _hInstance);
 }
 
 int32_t DeviceInfoDS::Init()
 {
     HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,
                                   IID_ICreateDevEnum, (void **) &_dsDevEnum);
     if (hr != NOERROR)
     {
--- a/media/webrtc/trunk/webrtc/modules/video_capture/windows/device_info_ds.h
+++ b/media/webrtc/trunk/webrtc/modules/video_capture/windows/device_info_ds.h
@@ -8,18 +8,20 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
 #ifndef WEBRTC_MODULES_VIDEO_CAPTURE_MAIN_SOURCE_WINDOWS_DEVICE_INFO_DS_H_
 #define WEBRTC_MODULES_VIDEO_CAPTURE_MAIN_SOURCE_WINDOWS_DEVICE_INFO_DS_H_
 
 #include "webrtc/modules/video_capture/device_info_impl.h"
 #include "webrtc/modules/video_capture/video_capture_impl.h"
+#include "base/singleton.h"
 
 #include <Dshow.h>
+#include <windows.h>
 
 namespace webrtc
 {
 namespace videocapturemodule
 {
 struct VideoCaptureCapabilityWindows: public VideoCaptureCapability
 {
     uint32_t directShowCapabilityIndex;
@@ -95,12 +97,30 @@ protected:
 
     virtual int32_t
         CreateCapabilityMap(const char* deviceUniqueIdUTF8);
 
 private:
     ICreateDevEnum* _dsDevEnum;
     bool _CoUninitializeIsRequired;
     std::vector<VideoCaptureCapabilityWindows> _captureCapabilitiesWindows;
+    HWND _hwnd;
+    WNDCLASS _wndClass;
+    HINSTANCE _hInstance;
 };
+
+class DeviceInfoDSSingleton {
+public:
+  DeviceInfoDSSingleton::DeviceInfoDSSingleton()
+    : mDeviceInfoDS(nullptr) {}
+
+  static DeviceInfoDS*& GetInfo() {
+    return gTheInstance.get()->mDeviceInfoDS;
+  }
+
+private:
+  static Singleton<DeviceInfoDSSingleton> gTheInstance;
+  DeviceInfoDS* mDeviceInfoDS;
+};
+
 }  // namespace videocapturemodule
 }  // namespace webrtc
 #endif // WEBRTC_MODULES_VIDEO_CAPTURE_MAIN_SOURCE_WINDOWS_DEVICE_INFO_DS_H_