diff --git a/subprojects/gst-plugins-good/sys/v4l2/gstv4l2object.c b/subprojects/gst-plugins-good/sys/v4l2/gstv4l2object.c index 0134de4756..26743967c2 100644 --- a/subprojects/gst-plugins-good/sys/v4l2/gstv4l2object.c +++ b/subprojects/gst-plugins-good/sys/v4l2/gstv4l2object.c @@ -4355,15 +4355,25 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps, goto done; } - /* Note: V4L2 wants the frame interval, we have the frame rate */ - streamparm.parm.capture.timeperframe.numerator = fps_d; - streamparm.parm.capture.timeperframe.denominator = fps_n; + /* Variable framerate is not a V4L2 concept, simply default to 30fps */ + if (fps_n == 0 && fps_d == 1) { + GST_DEBUG_OBJECT (v4l2object->dbg_obj, + "Variable framerate not supported, assuming 30fps"); + streamparm.parm.capture.timeperframe.numerator = 1; + streamparm.parm.capture.timeperframe.denominator = 30; + } else { + /* Note: V4L2 wants the frame interval, we have the frame rate */ + streamparm.parm.capture.timeperframe.numerator = fps_d; + streamparm.parm.capture.timeperframe.denominator = fps_n; + } /* some cheap USB cam's won't accept any change */ if (v4l2object->ioctl (fd, VIDIOC_S_PARM, &streamparm) < 0) goto set_parm_failed; - if (streamparm.parm.capture.timeperframe.numerator > 0 && + if (fps_n == 0 && fps_d == 1) { + /* just keep reporting variable framerate */ + } else if (streamparm.parm.capture.timeperframe.numerator > 0 && streamparm.parm.capture.timeperframe.denominator > 0) { /* get new values */ fps_d = streamparm.parm.capture.timeperframe.numerator; @@ -4398,14 +4408,24 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps, goto done; } - /* Note: V4L2 wants the frame interval, we have the frame rate */ - streamparm.parm.output.timeperframe.numerator = fps_d; - streamparm.parm.output.timeperframe.denominator = fps_n; + /* Variable framerate is not a V4L2 concept, simply default to 30fps */ + if (fps_n == 0 && fps_d == 1) { + GST_DEBUG_OBJECT (v4l2object->dbg_obj, + "Variable framerate not supported, assuming 30fps"); + streamparm.parm.output.timeperframe.numerator = 1; + streamparm.parm.output.timeperframe.denominator = 30; + } else { + /* Note: V4L2 wants the frame interval, we have the frame rate */ + streamparm.parm.output.timeperframe.numerator = fps_d; + streamparm.parm.output.timeperframe.denominator = fps_n; + } if (v4l2object->ioctl (fd, VIDIOC_S_PARM, &streamparm) < 0) goto set_parm_failed; - if (streamparm.parm.output.timeperframe.numerator > 0 && + if (fps_n == 0 && fps_d == 1) { + /* just keep reporting variable framerate */ + } else if (streamparm.parm.output.timeperframe.numerator > 0 && streamparm.parm.output.timeperframe.denominator > 0) { /* get new values */ fps_d = streamparm.parm.output.timeperframe.numerator; diff --git a/subprojects/gst-plugins-good/sys/v4l2/gstv4l2videoenc.c b/subprojects/gst-plugins-good/sys/v4l2/gstv4l2videoenc.c index 83490e13bc..1edb88e646 100644 --- a/subprojects/gst-plugins-good/sys/v4l2/gstv4l2videoenc.c +++ b/subprojects/gst-plugins-good/sys/v4l2/gstv4l2videoenc.c @@ -111,7 +111,7 @@ gst_v4l2_video_enc_open (GstVideoEncoder * encoder) { GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (encoder); GstV4l2Error error = GST_V4L2_ERROR_INIT; - GstCaps *codec_caps; + GstCaps *tmp_caps, *codec_caps; GST_DEBUG_OBJECT (self, "Opening"); @@ -124,6 +124,15 @@ gst_v4l2_video_enc_open (GstVideoEncoder * encoder) self->probed_sinkcaps = gst_v4l2_object_probe_caps (self->v4l2output, gst_v4l2_object_get_raw_caps ()); + /* + * Relax the framerate to always allow 0/1 regardless of what the driver + * wants. This improve compatibility of the encoder with sources which may + * not know the frame rate + */ + tmp_caps = gst_caps_copy (self->probed_sinkcaps); + gst_caps_set_simple (tmp_caps, "framerate", GST_TYPE_FRACTION, 0, 1, NULL); + gst_caps_append (self->probed_sinkcaps, tmp_caps); + if (gst_caps_is_empty (self->probed_sinkcaps)) goto no_raw_format;