From 93d319a5826a2e682fbc4a7457bca2f7462a829b Mon Sep 17 00:00:00 2001 From: Giorgio Vazzana Date: Sat, 26 Jan 2013 13:37:37 +0100 Subject: [PATCH] lavd/v4l2: select input immediately after opening the device After opening the device, the first thing we should do is selecting the input. This is because the image formats (VIDIOC_ENUM_FMT ioctl) and the standards (VIDIOC_ENUMSTD ioctl) supported may depend on the selected input ([1] and [2]). [1] http://linuxtv.org/downloads/v4l-dvb-apis/vidioc-enum-fmt.html [2] http://linuxtv.org/downloads/v4l-dvb-apis/vidioc-enumstd.html Signed-off-by: Stefano Sabatini --- libavdevice/v4l2.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c index d1d05623e9..f6b72bd51a 100644 --- a/libavdevice/v4l2.c +++ b/libavdevice/v4l2.c @@ -112,6 +112,7 @@ struct video_data { void **buf_start; unsigned int *buf_len; char *standard; + v4l2_std_id std_id; int channel; char *pixel_format; /**< Set by a private option. */ int list_format; /**< Set by a private option. */ @@ -655,7 +656,6 @@ static void mmap_close(struct video_data *s) static int v4l2_set_parameters(AVFormatContext *s1) { struct video_data *s = s1->priv_data; - struct v4l2_input input = { 0 }; struct v4l2_standard standard = { 0 }; struct v4l2_streamparm streamparm = { 0 }; struct v4l2_fract *tpf = &streamparm.parm.capture.timeperframe; @@ -671,22 +671,6 @@ static int v4l2_set_parameters(AVFormatContext *s1) return ret; } - /* set tv video input */ - input.index = s->channel; - if (v4l2_ioctl(s->fd, VIDIOC_ENUMINPUT, &input) < 0) { - av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl enum input failed:\n"); - return AVERROR(EIO); - } - - av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set input_id: %d, input: %s\n", - s->channel, input.name); - if (v4l2_ioctl(s->fd, VIDIOC_S_INPUT, &input.index) < 0) { - av_log(s1, AV_LOG_ERROR, - "The V4L2 driver ioctl set input(%d) failed\n", - s->channel); - return AVERROR(EIO); - } - if (s->standard) { av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set standard: %s\n", s->standard); @@ -807,6 +791,7 @@ static int v4l2_read_header(AVFormatContext *s1) uint32_t desired_format; enum AVCodecID codec_id = AV_CODEC_ID_NONE; enum AVPixelFormat pix_fmt = AV_PIX_FMT_NONE; + struct v4l2_input input = { 0 }; st = avformat_new_stream(s1, NULL); if (!st) @@ -816,6 +801,24 @@ static int v4l2_read_header(AVFormatContext *s1) if (s->fd < 0) return s->fd; + /* set tv video input */ + av_log(s1, AV_LOG_DEBUG, "Selecting input_channel: %d\n", s->channel); + if (v4l2_ioctl(s->fd, VIDIOC_S_INPUT, &s->channel) < 0) { + res = errno; + av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_S_INPUT): %s\n", strerror(errno)); + return AVERROR(res); + } + + input.index = s->channel; + if (v4l2_ioctl(s->fd, VIDIOC_ENUMINPUT, &input) < 0) { + res = errno; + av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_ENUMINPUT): %s\n", strerror(errno)); + return AVERROR(res); + } + s->std_id = input.std; + av_log(s1, AV_LOG_DEBUG, "input_channel: %d, input_name: %s\n", + s->channel, input.name); + if (s->list_format) { list_formats(s1, s->fd, s->list_format); return AVERROR_EXIT;