[FFmpeg-devel] [PATCH 3/3] lavd/avfoundation: improve default behavior around video output

Rodger Combs rodger.combs at gmail.com
Tue Apr 19 08:28:03 CEST 2016


- Use the highest resolution available, rather than the first listed
- Use the first listed (often the only) frame rate, rather than forcing NTSC
- Use the first listed pixel format, rather than forcing yuv420p
- Don't log when automatically overriding the defaults

This allows the defaults to give higher-quality output, and fixes the defaults
failing on devices without yuv420p or NTSC support.
---
 libavdevice/avfoundation.m | 33 ++++++++++++++++++++++-----------
 1 file changed, 22 insertions(+), 11 deletions(-)

diff --git a/libavdevice/avfoundation.m b/libavdevice/avfoundation.m
index 8132278..89b7648 100644
--- a/libavdevice/avfoundation.m
+++ b/libavdevice/avfoundation.m
@@ -289,6 +289,7 @@ static int configure_video_device(AVFormatContext *s, AVCaptureDevice *video_dev
     NSObject *format = nil;
     NSObject *selected_range = nil;
     NSObject *selected_format = nil;
+    CMVideoDimensions selected_dimensions = {0};
 
     for (format in [video_device valueForKey:@"formats"]) {
         CMFormatDescriptionRef formatDescription;
@@ -297,7 +298,10 @@ static int configure_video_device(AVFormatContext *s, AVCaptureDevice *video_dev
         formatDescription = (CMFormatDescriptionRef) [format performSelector:@selector(formatDescription)];
         dimensions = CMVideoFormatDescriptionGetDimensions(formatDescription);
 
-        if ((ctx->width == 0 && ctx->height == 0) ||
+        if ((ctx->width == 0 && ctx->height == 0 &&
+             (!selected_range ||
+              dimensions.width  > selected_dimensions.width ||
+              dimensions.height > selected_dimensions.height)) ||
             (dimensions.width == ctx->width && dimensions.height == ctx->height)) {
 
             selected_format = format;
@@ -306,8 +310,9 @@ static int configure_video_device(AVFormatContext *s, AVCaptureDevice *video_dev
                 double max_framerate;
 
                 [[range valueForKey:@"maxFrameRate"] getValue:&max_framerate];
-                if (fabs (framerate - max_framerate) < 0.01) {
+                if (ctx->framerate.den == 0 || fabs (framerate - max_framerate) < 0.01) {
                     selected_range = range;
+                    selected_dimensions = dimensions;
                     break;
                 }
             }
@@ -424,7 +429,8 @@ static int add_video_device(AVFormatContext *s, AVCaptureDevice *video_device)
     }
 
     // check if selected pixel format is supported by AVFoundation
-    if (pxl_fmt_spec.ff_id == AV_PIX_FMT_NONE) {
+    if (pxl_fmt_spec.ff_id == AV_PIX_FMT_NONE &&
+        ctx->pixel_format != AV_PIX_FMT_NONE) {
         av_log(s, AV_LOG_ERROR, "Selected pixel format (%s) is not supported by AVFoundation.\n",
                av_get_pix_fmt_name(pxl_fmt_spec.ff_id));
         return 1;
@@ -432,12 +438,15 @@ static int add_video_device(AVFormatContext *s, AVCaptureDevice *video_device)
 
     // check if the pixel format is available for this device
     if ([[ctx->video_output availableVideoCVPixelFormatTypes] indexOfObject:[NSNumber numberWithInt:pxl_fmt_spec.avf_id]] == NSNotFound) {
-        av_log(s, AV_LOG_ERROR, "Selected pixel format (%s) is not supported by the input device.\n",
-               av_get_pix_fmt_name(pxl_fmt_spec.ff_id));
+        int log = (ctx->pixel_format != AV_PIX_FMT_NONE);
+        if (log)
+            av_log(s, AV_LOG_ERROR, "Selected pixel format (%s) is not supported by the input device.\n",
+                   av_get_pix_fmt_name(pxl_fmt_spec.ff_id));
 
         pxl_fmt_spec.ff_id = AV_PIX_FMT_NONE;
 
-        av_log(s, AV_LOG_ERROR, "Supported pixel formats:\n");
+        if (log)
+            av_log(s, AV_LOG_ERROR, "Supported pixel formats:\n");
         for (NSNumber *pxl_fmt in [ctx->video_output availableVideoCVPixelFormatTypes]) {
             struct AVFPixelFormatSpec pxl_fmt_dummy;
             pxl_fmt_dummy.ff_id = AV_PIX_FMT_NONE;
@@ -449,7 +458,8 @@ static int add_video_device(AVFormatContext *s, AVCaptureDevice *video_device)
             }
 
             if (pxl_fmt_dummy.ff_id != AV_PIX_FMT_NONE) {
-                av_log(s, AV_LOG_ERROR, "  %s\n", av_get_pix_fmt_name(pxl_fmt_dummy.ff_id));
+                if (log)
+                    av_log(s, AV_LOG_ERROR, "  %s\n", av_get_pix_fmt_name(pxl_fmt_dummy.ff_id));
 
                 // select first supported pixel format instead of user selected (or default) pixel format
                 if (pxl_fmt_spec.ff_id == AV_PIX_FMT_NONE) {
@@ -462,8 +472,9 @@ static int add_video_device(AVFormatContext *s, AVCaptureDevice *video_device)
         if (pxl_fmt_spec.ff_id == AV_PIX_FMT_NONE) {
             return 1;
         } else {
-            av_log(s, AV_LOG_WARNING, "Overriding selected pixel format to use %s instead.\n",
-                   av_get_pix_fmt_name(pxl_fmt_spec.ff_id));
+            if (log)
+                av_log(s, AV_LOG_WARNING, "Overriding selected pixel format to use %s instead.\n",
+                       av_get_pix_fmt_name(pxl_fmt_spec.ff_id));
         }
     }
 
@@ -1020,8 +1031,8 @@ static const AVOption options[] = {
     { "false", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "list_devices" },
     { "video_device_index", "select video device by index for devices with same name (starts at 0)", offsetof(AVFContext, video_device_index), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
     { "audio_device_index", "select audio device by index for devices with same name (starts at 0)", offsetof(AVFContext, audio_device_index), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
-    { "pixel_format", "set pixel format", offsetof(AVFContext, pixel_format), AV_OPT_TYPE_PIXEL_FMT, {.i64 = AV_PIX_FMT_YUV420P}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM},
-    { "framerate", "set frame rate", offsetof(AVFContext, framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "ntsc"}, 0, 0, AV_OPT_FLAG_DECODING_PARAM },
+    { "pixel_format", "set pixel format", offsetof(AVFContext, pixel_format), AV_OPT_TYPE_PIXEL_FMT, {.i64 = AV_PIX_FMT_NONE}, -1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM},
+    { "framerate", "set frame rate", offsetof(AVFContext, framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = NULL}, 0, 0, AV_OPT_FLAG_DECODING_PARAM },
     { "video_size", "set video size", offsetof(AVFContext, width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, AV_OPT_FLAG_DECODING_PARAM },
     { "capture_cursor", "capture the screen cursor", offsetof(AVFContext, capture_cursor), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM },
     { "capture_mouse_clicks", "capture the screen mouse clicks", offsetof(AVFContext, capture_mouse_clicks), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM },
-- 
2.7.3



More information about the ffmpeg-devel mailing list