avfvideosrc: add frame rate range to caps
authorIlya Konstantinov <ilya.konstantinov@gmail.com>
Tue, 16 Jun 2015 14:18:52 +0000 (17:18 +0300)
committerSebastian Dröge <sebastian@centricular.com>
Mon, 22 Jun 2015 16:22:57 +0000 (18:22 +0200)
When AVFoundation indicates a supported frame rate range, add it to
the caps. This is important for devices such as the iPhone 6, which
indicate a single AVFrameRateRange of 2fps - 60fps.

https://bugzilla.gnome.org/show_bug.cgi?id=751048

sys/applemedia/avfvideosrc.m

index 00f5c65..a033ac0 100644 (file)
@@ -343,7 +343,6 @@ didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
   });
 }
 
-
 #define GST_AVF_CAPS_NEW(format, w, h, fps_n, fps_d)                  \
     (gst_caps_new_simple ("video/x-raw",                              \
         "width", G_TYPE_INT, w,                                       \
@@ -352,6 +351,14 @@ didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
         "framerate", GST_TYPE_FRACTION, (fps_n), (fps_d),             \
         NULL))
 
+#define GST_AVF_FPS_RANGE_CAPS_NEW(format, w, h, min_fps_n, min_fps_d, max_fps_n, max_fps_d) \
+    (gst_caps_new_simple ("video/x-raw",                              \
+        "width", G_TYPE_INT, w,                                       \
+        "height", G_TYPE_INT, h,                                      \
+        "format", G_TYPE_STRING, gst_video_format_to_string (format), \
+        "framerate", GST_TYPE_FRACTION_RANGE, (min_fps_n), (min_fps_d), (max_fps_n), (max_fps_d), \
+        NULL))
+
 - (GstVideoFormat)getGstVideoFormat:(NSNumber *)pixel_format
 {
   GstVideoFormat gst_format = GST_VIDEO_FORMAT_UNKNOWN;
@@ -419,19 +426,30 @@ didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
     formatDescription = (CMFormatDescriptionRef) [f performSelector:@selector(formatDescription)];
     dimensions = CMVideoFormatDescriptionGetDimensions(formatDescription);
     for (NSObject *rate in [f valueForKey:@"videoSupportedFrameRateRanges"]) {
-      int fps_n, fps_d;
-      gdouble max_fps;
+      int min_fps_n, min_fps_d, max_fps_n, max_fps_d;
+      gdouble min_fps, max_fps;
+
+      [[rate valueForKey:@"minFrameRate"] getValue:&min_fps];
+      gst_util_double_to_fraction (min_fps, &min_fps_n, &min_fps_d);
 
       [[rate valueForKey:@"maxFrameRate"] getValue:&max_fps];
-      gst_util_double_to_fraction (max_fps, &fps_n, &fps_d);
+      gst_util_double_to_fraction (max_fps, &max_fps_n, &max_fps_d);
 
       for (NSNumber *pixel_format in pixel_formats) {
         GstVideoFormat gst_format = [self getGstVideoFormat:pixel_format];
-        if (gst_format != GST_VIDEO_FORMAT_UNKNOWN)
-          gst_caps_append (result, GST_AVF_CAPS_NEW (gst_format, dimensions.width, dimensions.height, fps_n, fps_d));
+        if (gst_format != GST_VIDEO_FORMAT_UNKNOWN) {
+          if (min_fps != max_fps)
+            gst_caps_append (result, GST_AVF_FPS_RANGE_CAPS_NEW (gst_format, dimensions.width, dimensions.height, min_fps_n, min_fps_d, max_fps_n, max_fps_d));
+          else
+            gst_caps_append (result, GST_AVF_CAPS_NEW (gst_format, dimensions.width, dimensions.height, max_fps_n, max_fps_d));
+        }
 
         if (gst_format == GST_VIDEO_FORMAT_BGRA) {
-          GstCaps *rgba_caps = GST_AVF_CAPS_NEW (GST_VIDEO_FORMAT_RGBA, dimensions.width, dimensions.height, fps_n, fps_d);
+          GstCaps *rgba_caps;
+          if (min_fps != max_fps)
+            rgba_caps = GST_AVF_FPS_RANGE_CAPS_NEW (GST_VIDEO_FORMAT_RGBA, dimensions.width, dimensions.height, min_fps_n, min_fps_d, max_fps_n, max_fps_d);
+          else
+            rgba_caps = GST_AVF_CAPS_NEW (GST_VIDEO_FORMAT_RGBA, dimensions.width, dimensions.height, max_fps_n, max_fps_d);
           gst_caps_set_features (rgba_caps, 0, gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_GL_MEMORY, NULL));
           gst_caps_append (result, rgba_caps);
         }
@@ -462,10 +480,12 @@ didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
         found_format = TRUE;
         [device setValue:f forKey:@"activeFormat"];
         for (NSObject *rate in [f valueForKey:@"videoSupportedFrameRateRanges"]) {
-          gdouble max_frame_rate;
+          gdouble min_frame_rate, max_frame_rate;
 
+          [[rate valueForKey:@"minFrameRate"] getValue:&min_frame_rate];
           [[rate valueForKey:@"maxFrameRate"] getValue:&max_frame_rate];
-          if (fabs (framerate - max_frame_rate) < 0.00001) {
+          if ((framerate >= min_frame_rate - 0.00001) &&
+              (framerate <= max_frame_rate + 0.00001)) {
             NSValue *min_frame_duration, *max_frame_duration;
 
             found_framerate = TRUE;