macOS: video settings

Sometimes changing of video settings does not work because of
using unsupported framerates. This patch lists framerates depending
of resolution so only supported framerate could be selected.

Change-Id: I779c0a769c9ab611962e689173bed109932b652e
diff --git a/src/media/video/osxvideo/video_device_impl.mm b/src/media/video/osxvideo/video_device_impl.mm
index c3aef15..110c1ad 100644
--- a/src/media/video/osxvideo/video_device_impl.mm
+++ b/src/media/video/osxvideo/video_device_impl.mm
@@ -59,6 +59,8 @@
         AVCaptureDevice* avDevice_;
         std::vector<VideoSize> available_sizes_;
         VideoSize current_size_;
+        FrameRate rate_ {};
+        std::map<VideoSize, std::vector<FrameRate>> available_rates_;
 };
 
 VideoDeviceImpl::VideoDeviceImpl(const std::string& uniqueID)
@@ -73,6 +75,20 @@
     for (AVCaptureDeviceFormat* format in avDevice_.formats) {
         auto dimensions = CMVideoFormatDescriptionGetDimensions(format.formatDescription);
         available_sizes_.emplace_back(dimensions.width, dimensions.height);
+        std::vector<FrameRate> v;
+        v.reserve(format.videoSupportedFrameRateRanges.count);
+        for (AVFrameRateRange* frameRateRange in format.videoSupportedFrameRateRanges) {
+            if(std::find(v.begin(), v.end(), frameRateRange.maxFrameRate) == v.end()) {
+                v.emplace_back(frameRateRange.maxFrameRate);
+            }
+        }
+        // if we have multiple formats with the same resolution use video supported framerates from last one
+        // because this format will be selected by ffmpeg
+        if (available_rates_.find( VideoSize(dimensions.width, dimensions.height) ) == available_rates_.end()) {
+            available_rates_.emplace(VideoSize(dimensions.width, dimensions.height), v);
+        } else {
+            available_rates_.at(VideoSize(dimensions.width, dimensions.height)) = v;
+        }
     }
 }
 
@@ -97,23 +113,17 @@
     DeviceParams params;
     params.name = [[avDevice_ localizedName] UTF8String];
     params.input = params.name;
+    params.framerate = rate_;
     params.format = "avfoundation";
-
     params.width = current_size_.first;
     params.height = current_size_.second;
-
-    auto format = [avDevice_ activeFormat];
-    auto frameRate = (AVFrameRateRange*)
-                    [format.videoSupportedFrameRateRanges objectAtIndex:0];
-    params.framerate = frameRate.maxFrameRate;
     return params;
 }
 
 void
 VideoDeviceImpl::setDeviceParams(const DeviceParams& params)
 {
-//TODO: add framerate
-//    rate_ = size_.getRate(settings["rate"]);
+    rate_ = params.framerate;
     current_size_ = extractSize({params.width, params.height});
 }
 
@@ -126,12 +136,7 @@
 std::vector<FrameRate>
 VideoDeviceImpl::getRateList(const std::string& channel, VideoSize size) const
 {
-    auto format = [avDevice_ activeFormat];
-    std::vector<FrameRate> v;
-    v.reserve(format.videoSupportedFrameRateRanges.count);
-    for (AVFrameRateRange* frameRateRange in format.videoSupportedFrameRateRanges)
-        v.emplace_back(frameRateRange.maxFrameRate);
-    return v;
+    return available_rates_.at(size);
 }
 
 std::vector<VideoSize>