diff --git a/contrib/src/libav/osx.patch b/contrib/src/libav/osx.patch
index a4be9a98e89062a6898d78bc3202249eaf75c560..4f885fd6d14fe20309ff7304a90618ad39dac25d 100644
--- a/contrib/src/libav/osx.patch
+++ b/contrib/src/libav/osx.patch
@@ -242,10 +242,10 @@ index 5dbe277..8439b5b 100644
      REGISTER_INDEV   (FBDEV,            fbdev);
 diff --git a/libavdevice/avfoundation_dec.m b/libavdevice/avfoundation_dec.m
 new file mode 100644
-index 0000000..581f845
+index 0000000..f1b9c03
 --- /dev/null
 +++ b/libavdevice/avfoundation_dec.m
-@@ -0,0 +1,449 @@
+@@ -0,0 +1,447 @@
 +/*
 + * AVFoundation input device
 + * Copyright (c) 2015 Luca Barbato
@@ -406,7 +406,7 @@ index 0000000..581f845
 +
 +@end
 +
-+NSString *pat = @"(\b[A-Z0-9]+\b)";
++NSString *pat = @"\\[[^\\].]*\\]";
 +
 +static int setup_stream(AVFormatContext *s, AVCaptureDevice *device)
 +{
@@ -491,7 +491,6 @@ index 0000000..581f845
 +    // Take stream info from the first frame.
 +    while (ctx->frames_captured < 1) {
 +        CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, YES);
-+        av_log(s, AV_LOG_ERROR, "Waiting for incoming frame\n");
 +    }
 +
 +    lock_frames(ctx);
@@ -586,8 +585,7 @@ index 0000000..581f845
 +        if (matches.count > 0) {
 +            for (NSTextCheckingResult *match in matches) {
 +                NSRange range = [match rangeAtIndex:0];
-+                NSString *uniqueID = [filename substringWithRange:range];
-+                av_log(s, AV_LOG_INFO, "opening device with ID: %s\n",[uniqueID UTF8String]);
++                NSString *uniqueID = [filename substringWithRange:NSMakeRange(range.location + 1, range.length-2)];                av_log(s, AV_LOG_INFO, "opening device with ID: %s\n",[uniqueID UTF8String]);
 +                if (!(device = [AVCaptureDevice deviceWithUniqueID:uniqueID])) {
 +                    // report error
 +                    av_log(s, AV_LOG_ERROR, "Device with name %s not found",[filename UTF8String]);
diff --git a/src/media/video/osxvideo/video_device_impl.mm b/src/media/video/osxvideo/video_device_impl.mm
index 7d491f98e8f2394e8440fadf112cca0091d41169..ffb26eb5440dc4152a9a756c32a2e1f66930c5ae 100644
--- a/src/media/video/osxvideo/video_device_impl.mm
+++ b/src/media/video/osxvideo/video_device_impl.mm
@@ -154,13 +154,13 @@ std::vector<std::string>
 VideoDeviceImpl::getRateList(const std::string& channel, const std::string& size) const
 {
     auto format = [avDevice_ activeFormat];
-    auto frameRate = (AVFrameRateRange*)
-                    [format.videoSupportedFrameRateRanges objectAtIndex:0];
-
     std::vector<std::string> v;
-    std::stringstream ss;
-    ss << frameRate.maxFrameRate;
-    v.push_back(ss.str());
+
+    for (AVFrameRateRange* frameRateRange in format.videoSupportedFrameRateRanges) {
+      std::stringstream ss;
+        ss << frameRateRange.maxFrameRate;
+        v.push_back(ss.str());
+    }
     return v;
 }
 
@@ -169,14 +169,12 @@ VideoDeviceImpl::getSizeList(const std::string& channel) const
 {
     std::vector<std::string> v;
 
-    auto format = [avDevice_ activeFormat];
-    auto dimensions =
-                CMVideoFormatDescriptionGetDimensions(format.formatDescription);
-
-    std::stringstream ss;
-    ss << dimensions.width << "x" << dimensions.height;
-    v.push_back(ss.str());
-
+    for (AVCaptureDeviceFormat* format in avDevice_.formats) {
+      std::stringstream ss;
+      auto dimensions = CMVideoFormatDescriptionGetDimensions(format.formatDescription);
+        ss << dimensions.width << "x" << dimensions.height;
+        v.push_back(ss.str());
+    }
     return v;
 }
 
diff --git a/src/media/video/osxvideo/video_device_monitor_impl.mm b/src/media/video/osxvideo/video_device_monitor_impl.mm
index eb3242be7a87f91fceec284d5de67b99f35d6a48..2eeee8e0f487aaa7d8bfe627b38ae60b90b94bcf 100644
--- a/src/media/video/osxvideo/video_device_monitor_impl.mm
+++ b/src/media/video/osxvideo/video_device_monitor_impl.mm
@@ -66,19 +66,12 @@ class VideoDeviceMonitorImpl {
         NON_COPYABLE(VideoDeviceMonitorImpl);
 
         VideoDeviceMonitor* monitor_;
-
-        void run();
-
-        mutable std::mutex mutex_;
-        std::atomic_bool probing_;
-        std::thread thread_;
+        NSArray* observers;
 };
 
 
 VideoDeviceMonitorImpl::VideoDeviceMonitorImpl(VideoDeviceMonitor* monitor) :
-    monitor_(monitor),
-    mutex_(), probing_(false),
-    thread_()
+    monitor_(monitor)
 {
     /* Enumerate existing devices */
     auto myVideoDevices = [[AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]
@@ -95,7 +88,7 @@ VideoDeviceMonitorImpl::VideoDeviceMonitorImpl(VideoDeviceMonitor* monitor) :
     for ( ivideo = 0; ivideo < deviceCount; ++ivideo )
     {
         AVCaptureDevice* avf_device = [myVideoDevices objectAtIndex:ivideo];
-        RING_DBG("avcapture %lu/%lu %s %s", ivideo,
+        printf("avcapture %d/%d %s %s\n", ivideo + 1,
                                             deviceCount,
                                             [[avf_device modelID] UTF8String],
                                             [[avf_device uniqueID] UTF8String]);
@@ -110,23 +103,31 @@ VideoDeviceMonitorImpl::VideoDeviceMonitorImpl(VideoDeviceMonitor* monitor) :
 
 void VideoDeviceMonitorImpl::start()
 {
-    probing_ = true;
-    //thread_ = std::thread(&VideoDeviceMonitorImpl::run, this);
+    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
+    id deviceWasConnectedObserver = [notificationCenter addObserverForName:AVCaptureDeviceWasConnectedNotification
+                                    object:nil
+                                    queue:[NSOperationQueue mainQueue]
+                                    usingBlock:^(NSNotification *note) {
+                                      AVCaptureDevice* dev = (AVCaptureDevice*)note.object;
+                                      monitor_->addDevice([[dev uniqueID] UTF8String]);
+                                    }];
+    id deviceWasDisconnectedObserver = [notificationCenter addObserverForName:AVCaptureDeviceWasDisconnectedNotification
+                                        object:nil
+                                        queue:[NSOperationQueue mainQueue]
+                                        usingBlock:^(NSNotification *note) {
+                                          AVCaptureDevice* dev = (AVCaptureDevice*)note.object;
+                                          monitor_->removeDevice([[dev uniqueID] UTF8String]);
+                                        }];
+    observers = [[NSArray alloc] initWithObjects:deviceWasConnectedObserver, deviceWasDisconnectedObserver, nil];
 }
 
 VideoDeviceMonitorImpl::~VideoDeviceMonitorImpl()
 {
-    probing_ = false;
-    if (thread_.joinable())
-        thread_.join();
-}
+    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
+    for (id observer in observers)
+        [notificationCenter removeObserver:observer];
 
-void VideoDeviceMonitorImpl::run()
-{
-    while (probing_) {
-        //TODO: Enable detection of new devices
-        sleep(1);
-    }
+    [observers release];
 }
 
 VideoDeviceMonitor::VideoDeviceMonitor() :