[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