introduce -framerate
Use framerate of device's activeFormat if not provided.
framerate value must be in the range of available framerate of the device.
---
 libavdevice/avfoundation_dec.m | 69 ++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 67 insertions(+), 2 deletions(-)

diff --git a/libavdevice/avfoundation_dec.m b/libavdevice/avfoundation_dec.m
index ce04f33..2c92b31 100644
--- a/libavdevice/avfoundation_dec.m
+++ b/libavdevice/avfoundation_dec.m
@@ -95,9 +95,12 @@ typedef struct AVFoundationCaptureContext {
     int list_formats;
     char* pixel_format;
     char *video_size;   /* String describing video size */
+    char *framerate;    /* String describing the framerate */
+
 
     int video_stream_index;
     int width, height;
+    AVRational internal_framerate;
 
     int64_t first_pts;
     int frames_captured;
@@ -125,6 +128,7 @@ static const AVOption options[] = {
     { "list_formats", "List available formats and exit", OFFSET(list_formats), 
AV_OPT_TYPE_INT,    {.i64 = 0 },             0, INT_MAX, DEC, "list_formats" },
     { "pixel_format", "Preferred pixel format",          OFFSET(pixel_format), 
AV_OPT_TYPE_STRING, {.str = NULL},           0, 0, DEC},
     { "video_size",   "A string describing frame size, such as 640x480 or 
hd720.", OFFSET(video_size), AV_OPT_TYPE_STRING, {.str = NULL},  0, 0, DEC },
+    { "framerate",    "A string representing desired framerate", 
OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = NULL},       0, 0, DEC },
     { NULL },
 };
 
@@ -237,6 +241,9 @@ static bool configure_video_device(AVFormatContext *s, 
AVCaptureDevice *video_de
 {
     AVFoundationCaptureContext *ctx = s->priv_data;
     AVCaptureDeviceFormat* selected_format = nil;
+    AVFrameRateRange* selected_range = nil;
+    double framerate = av_q2d(ctx->internal_framerate);
+    double epsilon = 0.00000001;
 
     for (AVCaptureDeviceFormat* format in [video_device formats]) {
         CMFormatDescriptionRef formatDescription;
@@ -248,12 +255,29 @@ static bool configure_video_device(AVFormatContext *s, 
AVCaptureDevice *video_de
         if ((ctx->width == 0 && ctx->height == 0) ||
             (dimensions.width == ctx->width && dimensions.height == 
ctx->height)) {
 
-            av_log(s, AV_LOG_INFO, "Video size (%dx%d) supported\n",
+            av_log(s, AV_LOG_INFO, "Trying video size %dx%d\n",
                 dimensions.width, dimensions.height);
             ctx->width = dimensions.width;
             ctx->height = dimensions.height;
             selected_format = format;
-            break;
+            if (framerate) {
+                av_log(s, AV_LOG_INFO, "Checking support for framerate %f\n",
+                    framerate);
+                for (AVFrameRateRange* range in 
format.videoSupportedFrameRateRanges) {
+                        if (range.minFrameRate <= (framerate + epsilon) &&
+                                range.maxFrameRate >= (framerate - epsilon)) {
+                        selected_range = range;
+                        break;
+                    }
+                }
+            } else {
+                selected_range = format.videoSupportedFrameRateRanges[0];
+                framerate = selected_range.maxFrameRate;
+                break;
+            }
+
+            if (selected_format && selected_range)
+                break;
         }
     }
 
@@ -266,8 +290,19 @@ static bool configure_video_device(AVFormatContext *s, 
AVCaptureDevice *video_de
             ctx->width, ctx->height);
     }
 
+    if (framerate && !selected_range) {
+        av_log(s, AV_LOG_ERROR, "Selected framerate (%f) is not supported by 
the device\n",
+            framerate);
+        return false;
+    } else {
+        av_log(s, AV_LOG_INFO, "Setting framerate to %f\n",
+            framerate);
+    }
+
     if ([video_device lockForConfiguration:NULL] == YES) {
         [video_device setActiveFormat:selected_format];
+        [video_device setActiveVideoMinFrameDuration:CMTimeMake(1, framerate)];
+        [video_device setActiveVideoMaxFrameDuration:CMTimeMake(1, framerate)];
     } else {
         av_log(s, AV_LOG_ERROR, "Could not lock device for configuration");
         return false;
@@ -275,6 +310,24 @@ static bool configure_video_device(AVFormatContext *s, 
AVCaptureDevice *video_de
     return true;
 }
 
+static void print_supported_formats(AVFormatContext *s, AVCaptureDevice 
*device)
+{
+    av_log(s, AV_LOG_WARNING, "Supported modes:\n");
+    for (AVCaptureDeviceFormat* format in [device formats]) {
+        CMFormatDescriptionRef formatDescription;
+        CMVideoDimensions dimensions;
+
+        formatDescription = (CMFormatDescriptionRef) format.formatDescription;
+        dimensions = CMVideoFormatDescriptionGetDimensions(formatDescription);
+
+        for (AVFrameRateRange* range in format.videoSupportedFrameRateRanges) {
+            av_log(s, AV_LOG_WARNING, "  %dx%d@[%f %f]fps\n",
+                dimensions.width, dimensions.height,
+                range.minFrameRate, range.maxFrameRate);
+        }
+    }
+}
+
 static int setup_stream(AVFormatContext *s, AVCaptureDevice *device)
 {
     av_log(s, AV_LOG_INFO, "Setting up stream for device %s\n", [[device 
uniqueID] UTF8String]);
@@ -288,6 +341,7 @@ static int setup_stream(AVFormatContext *s, AVCaptureDevice 
*device)
 
     if (!configure_video_device(s, device)) {
         av_log(s, AV_LOG_ERROR, "device configuration failed\n");
+        print_supported_formats(s, device);
         return AVERROR(EINVAL);
     }
 
@@ -535,6 +589,10 @@ static int avfoundation_read_header(AVFormatContext *s)
 {
     AVFoundationCaptureContext *ctx = s->priv_data;
     ctx->first_pts = av_gettime();
+
+    AVRational framerate_q = { 0 , 1 };
+    ctx->internal_framerate = framerate_q;
+
     if (ctx->list_devices)
         return avfoundation_list_capture_devices(s);
     if (ctx->list_formats) {
@@ -556,6 +614,13 @@ static int avfoundation_read_header(AVFormatContext *s)
         return AVERROR(EINVAL);
     }
 
+    if (ctx->framerate &&
+        (av_parse_video_rate(&ctx->internal_framerate, ctx->framerate)) < 0) {
+        av_log(s, AV_LOG_ERROR, "Could not parse framerate '%s'.\n",
+               ctx->framerate);
+        return AVERROR(EINVAL);
+    }
+
     return setup_streams(s);
 }
 
-- 
2.6.2

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to