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