[FFmpeg-devel] [PATCH] lavd/v4l2: sanitize logic of device_try_init(), so that it properly signal errors
Stefano Sabatini
stefasab at gmail.com
Tue Jan 15 12:48:42 CET 2013
Make device_try_init() return an error value, and allow to properly
report errors which are not due to a wrong pixel/codec configuration.
In particular, report intelligible feedback in case of busy device.
---
libavdevice/v4l2.c | 64 ++++++++++++++++++++++++++++------------------------
1 file changed, 34 insertions(+), 30 deletions(-)
diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c
index f5940ad..8387011 100644
--- a/libavdevice/v4l2.c
+++ b/libavdevice/v4l2.c
@@ -742,19 +742,25 @@ static int v4l2_set_parameters(AVFormatContext *s1)
return 0;
}
-static uint32_t device_try_init(AVFormatContext *s1,
- enum AVPixelFormat pix_fmt,
- int *width,
- int *height,
- enum AVCodecID *codec_id)
+static int device_try_init(AVFormatContext *s1,
+ enum AVPixelFormat pix_fmt,
+ int *width,
+ int *height,
+ uint32_t *desired_format,
+ enum AVCodecID *codec_id)
{
- uint32_t desired_format = fmt_ff2v4l(pix_fmt, s1->video_codec_id);
+ int ret, i;
- if (desired_format == 0 ||
- device_init(s1, width, height, desired_format) < 0) {
- int i;
+ *desired_format = fmt_ff2v4l(pix_fmt, s1->video_codec_id);
- desired_format = 0;
+ if (*desired_format) {
+ ret = device_init(s1, width, height, *desired_format);
+ if (ret >= 0 || ret != AVERROR(EINVAL))
+ return ret;
+ }
+
+ /* todo REINDENT */
+ *desired_format = 0;
for (i = 0; i<FF_ARRAY_ELEMS(fmt_conversion_table); i++) {
if (s1->video_codec_id == AV_CODEC_ID_NONE ||
fmt_conversion_table[i].codec_id == s1->video_codec_id) {
@@ -762,21 +768,26 @@ static uint32_t device_try_init(AVFormatContext *s1,
avcodec_get_name(fmt_conversion_table[i].codec_id),
(char *)av_x_if_null(av_get_pix_fmt_name(fmt_conversion_table[i].ff_fmt), "none"));
- desired_format = fmt_conversion_table[i].v4l2_fmt;
- if (device_init(s1, width, height, desired_format) >= 0) {
+ *desired_format = fmt_conversion_table[i].v4l2_fmt;
+ ret = device_init(s1, width, height, *desired_format);
+ if (ret >= 0 || ret != AVERROR(EINVAL))
break;
- }
- desired_format = 0;
+ *desired_format = 0;
}
}
- }
- if (desired_format != 0) {
- *codec_id = fmt_v4l2codec(desired_format);
+ if (*desired_format == 0) {
+ av_log(s1, AV_LOG_ERROR, "Cannot find a proper format for "
+ "codec '%s' (id %d), pixel format '%s' (id %d)\n",
+ avcodec_get_name(s1->video_codec_id), s1->video_codec_id,
+ (char *)av_x_if_null(av_get_pix_fmt_name(pix_fmt), "none"), pix_fmt);
+ ret = AVERROR(EINVAL);
+ } else {
+ *codec_id = fmt_v4l2codec(*desired_format);
av_assert0(*codec_id != AV_CODEC_ID_NONE);
}
- return desired_format;
+ return ret;
}
static int v4l2_read_header(AVFormatContext *s1)
@@ -844,8 +855,11 @@ static int v4l2_read_header(AVFormatContext *s1)
"Setting frame size to %dx%d\n", s->width, s->height);
}
- desired_format = device_try_init(s1, pix_fmt, &s->width, &s->height,
- &codec_id);
+ res = device_try_init(s1, pix_fmt, &s->width, &s->height, &desired_format, &codec_id);
+ if (res < 0) {
+ v4l2_close(s->fd);
+ goto out;
+ }
/* If no pixel_format was specified, the codec_id was not known up
* until now. Set video_codec_id in the context, as codec_id will
@@ -854,16 +868,6 @@ static int v4l2_read_header(AVFormatContext *s1)
if (codec_id != AV_CODEC_ID_NONE && s1->video_codec_id == AV_CODEC_ID_NONE)
s1->video_codec_id = codec_id;
- if (desired_format == 0) {
- av_log(s1, AV_LOG_ERROR, "Cannot find a proper format for "
- "codec '%s' (id %d), pixel format '%s' (id %d)\n",
- avcodec_get_name(s1->video_codec_id), s1->video_codec_id,
- (char *)av_x_if_null(av_get_pix_fmt_name(pix_fmt), "none"), pix_fmt);
- v4l2_close(s->fd);
-
- res = AVERROR(EIO);
- goto out;
- }
if ((res = av_image_check_size(s->width, s->height, 0, s1)) < 0)
goto out;
--
1.7.9.5
More information about the ffmpeg-devel
mailing list