- 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 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel