[FFmpeg-devel] [PATCH] v4l2: read the correct time per frame from devices that support a standard

Giorgio Vazzana mywing81 at gmail.com
Mon Jan 28 18:09:30 CET 2013


2013/1/25 Stefano Sabatini <stefasab at gmail.com>:
> Bravo! This is what I call a good commit message :-).

Thanks! :D

>> +        if (input.std) {
>> +            av_log(s1, AV_LOG_DEBUG, "Setting V4L2 driver standard: %s\n",
>> +                   s->standard);
>> +            /* set tv standard */
>> +            for(i = 0; ; i++) {
>> +                standard.index = i;
>> +                ret = v4l2_ioctl(s->fd, VIDIOC_ENUMSTD, &standard);
>
> v4l2_ioctl() returns -1 in case of error, to get a meaningful error
> code (which is propagated to the caller function), you need to do:
> ret = AVERROR(errno);
> just after the call.

Fixed.

>> +                if (ret < 0 || !av_strcasecmp(standard.name, s->standard))
>> +                    break;
>> +            }
>> +            if (ret < 0) {
>> +                av_log(s1, AV_LOG_ERROR, "Unknown standard '%s'\n", s->standard);
>> +                return ret;
>> +            }
>> +
>
>> +            if (v4l2_ioctl(s->fd, VIDIOC_S_STD, &standard.id) < 0) {
>> +                av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl set standard failed\n");
>> +                return AVERROR(EIO);
>
> Here you can return AVERROR(errno) to provide a more meaningful error
> code (you should also set ret before av_log(), or alternatively:
>
> v4l2_ioctl(s->fd, VIDIOC_S_STD, &standard.id);
> if ((ret = AVERROR(errno)) < 0) {
> ...
> return ret;
> }

Fixed.

>> +            }
>> +        } else {
>> +            av_log(s1, AV_LOG_WARNING,
>> +                   "The V4L2 driver does not allow to change standard\n");
>
> Not sure if we should rather fail here, leave as is if in doubt.

This means the user requested a specific standard, but he is using for
example a webcam, so I'd say we can just print a warning he'll
hopefully notice, and keep going. So, left as it was.

>> +        }
>> +    }
>> +
>> +    /* get standard */
>> +    if (v4l2_ioctl(s->fd, VIDIOC_G_STD, &std_id) == 0) {
>> +        tpf = &standard.frameperiod;
>> +        for (i = 0; ; i++) {
>>              standard.index = i;
>>              ret = v4l2_ioctl(s->fd, VIDIOC_ENUMSTD, &standard);
>> -            if (ret < 0 || !av_strcasecmp(standard.name, s->standard))
>> +            if (ret < 0) {
>> +                av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl enum standard failed\n");
>> +                return ret;
>> +            }
>
> ditto for errno

Ok, changed.

>> +            if (standard.id == std_id) {
>> +                av_log(s1, AV_LOG_DEBUG,
>> +                       "Current standard: %s, id: %"PRIu64", frameperiod: %d/%d\n",
>> +                       standard.name, standard.id, tpf->numerator, tpf->denominator);
>>                  break;
>> +            }
>
>> +            standard.index++;
>
> seems redundant

Hmm, if the user does not request a standard on the command line, then
we need to get the current standard, and enumerate the supported
standards one by one until one matches. When we find a match, we can
retrieve the time per frame. So, it should not be redundant.

>>          }
>> -        if (ret < 0) {
>> -            av_log(s1, AV_LOG_ERROR, "Unknown standard '%s'\n", s->standard);
>> -            return ret;
>> -        }
>> +    } else {
>> +        std_id = 0;
>> +        tpf = &streamparm.parm.capture.timeperframe;
>> +    }
>>
>> -        av_log(s1, AV_LOG_DEBUG,
>> -               "The V4L2 driver set standard: %s, id: %"PRIu64"\n",
>> -               s->standard, (uint64_t)standard.id);
>> -        if (v4l2_ioctl(s->fd, VIDIOC_S_STD, &standard.id) < 0) {
>> -            av_log(s1, AV_LOG_ERROR,
>> -                   "The V4L2 driver ioctl set standard(%s) failed\n",
>> -                   s->standard);
>> -            return AVERROR(EIO);
>> -        }
>
>> +    streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
>> +    if (v4l2_ioctl(s->fd, VIDIOC_G_PARM, &streamparm) != 0) {
>> +        av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_G_PARM): %s\n", strerror(errno));
>> +        return AVERROR(errno);
>
> usual considerations on errno

Fixed.

>>      }
>>
>>      if (framerate_q.num && framerate_q.den) {
>> -        av_log(s1, AV_LOG_DEBUG, "Setting time per frame to %d/%d\n",
>> -               framerate_q.den, framerate_q.num);
>> -        tpf->numerator   = framerate_q.den;
>> -        tpf->denominator = framerate_q.num;
>> -
>> -        if (v4l2_ioctl(s->fd, VIDIOC_S_PARM, &streamparm) != 0) {
>> -            av_log(s1, AV_LOG_ERROR,
>> -                   "ioctl set time per frame(%d/%d) failed\n",
>> +        if (streamparm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) {
>> +            tpf = &streamparm.parm.capture.timeperframe;
>> +
>> +            av_log(s1, AV_LOG_DEBUG, "Setting time per frame to %d/%d\n",
>>                     framerate_q.den, framerate_q.num);
>> -            return AVERROR(EIO);
>> -        }
>> +            tpf->numerator   = framerate_q.den;
>> +            tpf->denominator = framerate_q.num;
>>
>> -        if (framerate_q.num != tpf->denominator ||
>> -            framerate_q.den != tpf->numerator) {
>> -            av_log(s1, AV_LOG_INFO,
>> -                   "The driver changed the time per frame from "
>> -                   "%d/%d to %d/%d\n",
>> -                   framerate_q.den, framerate_q.num,
>> -                   tpf->numerator, tpf->denominator);
>> -        }
>> -    } else {
>> -        if (v4l2_ioctl(s->fd, VIDIOC_G_PARM, &streamparm) != 0) {
>> -            av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_G_PARM): %s\n",
>> -                   strerror(errno));
>> -            return AVERROR(errno);
>
>> +            if (v4l2_ioctl(s->fd, VIDIOC_S_PARM, &streamparm) != 0) {
>> +                av_log(s1, AV_LOG_ERROR, "ioctl set time per frame failed\n");
>> +                return AVERROR(EIO);
>> +            }
>
> ditto about error code (alternatively return always EIO and we'll fix
> it later globally)

Fixed.

New patch attached.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-lavd-v4l2-read-the-correct-time-per-frame-from-devic.patch
Type: application/octet-stream
Size: 7436 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20130128/a6a7d1fe/attachment.obj>


More information about the ffmpeg-devel mailing list