Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gst-launch doesn't appear to work with akvcam #20

Closed
jnetman1 opened this issue Apr 20, 2020 · 6 comments
Closed

gst-launch doesn't appear to work with akvcam #20

jnetman1 opened this issue Apr 20, 2020 · 6 comments

Comments

@jnetman1
Copy link

Appears that there is an issue with using gst-launch with akvcam virtual device, as it throws the following, even with the example commands from the wiki:

user@laptop:~$ gst-launch-1.0 -v videotestsrc ! v4l2sink device=/dev/video5
Setting pipeline to PAUSED ...
ERROR: Pipeline doesn't want to pause.
ERROR: from element /GstPipeline:pipeline0/GstV4l2Sink:v4l2sink0: Device '/dev/video5' is not a output device.
Additional debug info:
v4l2_calls.c(636): gst_v4l2_open (): /GstPipeline:pipeline0/GstV4l2Sink:v4l2sink0:
Capabilities: 0x5200001
Setting pipeline to NULL ...
Freeing pipeline ...

Device works fine with webcamoid, just not for anything else...

@illuusio
Copy link

Yes it works as expected if you use correct device. Which is /dev/video4 in this case I think not Capture one.

@jnetman1
Copy link
Author

Interesting. That works with the short command, gst-launch-1.0 -v videotestsrc ! v4l2sink device=/dev/video4

however the long one returns:

gst-launch-1.0 -v videotestsrc ! "video/x-raw,format=RGB,width=640,height=480,framerate=30/1" ! v4l2sink device=/dev/video4
Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
ERROR: from element /GstPipeline:pipeline0/GstVideoTestSrc:videotestsrc0: Internal data stream error.
Additional debug info:
gstbasesrc.c(3072): gst_base_src_loop (): /GstPipeline:pipeline0/GstVideoTestSrc:videotestsrc0:
streaming stopped, reason not-negotiated (-4)
ERROR: pipeline doesn't want to preroll.
Setting pipeline to NULL ...
Freeing pipeline ...

Probably just a tweak to the format to make it work. Would also love to be able to stream a window with something like this:

gst-launch-1.0 ximagesrc xid=0x03200001 ! "video/x-raw,format=RGB,width=640,height=480,framerate=30/1" ! v4l2sink device=/dev/video4
WARNING: erroneous pipeline: could not link ximagesrc0 to v4l2sink0, ximagesrc0 can't handle caps video/x-raw, format=(string)RGB, width=(int)640, height=(int)480, framerate=(fraction)30/1

but that's probably more of an enhancement request :)

@hipersayanX
Copy link
Member

I've tested gst-launch again with all new changes (now akvcam use v4l2 kernel API for managing almost everything), and it get stuck at:

Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
/GstPipeline:pipeline0/GstVideoTestSrc:videotestsrc0.GstPad:src: caps = video/x-raw, format=(string)RGB, width=(int)640, height=(int)480, framerate=(fraction)30/1, multiview-mode=(string)mono, interlace-mode=(string)progressive, colorimetry=(string)1:1:0:0, pixel-aspect-ratio=(fraction)1/1
/GstPipeline:pipeline0/GstV4l2Sink:v4l2sink0.GstPad:sink: caps = video/x-raw, format=(string)RGB, width=(int)640, height=(int)480, framerate=(fraction)30/1, multiview-mode=(string)mono, interlace-mode=(string)progressive, colorimetry=(string)1:1:0:0, pixel-aspect-ratio=(fraction)1/1
Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock
0:00:00.0 / 99:99:99.

akvcam is fully compliant according to v4l2-compliance, and it works fine with cat and ffmpeg, I think is more likely a bug in GStreamer, not sure.

@hipersayanX
Copy link
Member

I give up with this, v4l2sink doesn't work with an akvcam output device. akvcam is fully compliant, so its more like a bug in GStreamer side.

@thebied
Copy link

thebied commented Mar 17, 2023

The issue stems from the fact that akvcam and the v4l2sink GStreamer have 2 different default minimum buffer settings and no common communication link.

GStreamer:
#define GST_V4L2_MIN_BUFFERS 2

https://github.com/GStreamer/gst-plugins-good/blob/master/sys/v4l2/gstv4l2object.c

static void
gst_v4l2_get_driver_min_buffers (GstV4l2Object * v4l2object)
{
struct v4l2_control control = { 0, };

g_return_if_fail (GST_V4L2_IS_OPEN (v4l2object));

if (V4L2_TYPE_IS_OUTPUT (v4l2object->type))
control.id = V4L2_CID_MIN_BUFFERS_FOR_OUTPUT;
else
control.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE;

if (v4l2object->ioctl (v4l2object->video_fd, VIDIOC_G_CTRL, &control) == 0) {
GST_DEBUG_OBJECT (v4l2object->dbg_obj,
"driver requires a minimum of %d buffers", control.value);
v4l2object->min_buffers = control.value;
} else {
v4l2object->min_buffers = 0;
}
}

akvcam:
#define AKVCAM_BUFFERS_MIN 4

https://github.com/webcamoid/akvcam/blob/master/src/ioctl.c
int akvcam_ioctl_g_parm(struct file *file,
void *fh,
struct v4l2_streamparm *param)
{
akvcam_device_t device = video_drvdata(file);
akvcam_format_t format;
__u32 *n_buffers;
UNUSED(fh);

akpr_function();
akpr_debug("Device: /dev/video%d\n", akvcam_device_num(device));

if (param->type != akvcam_device_v4l2_type(device))
    return -EINVAL;

memset(&param->parm, 0, 200);
format = akvcam_device_format(device);

if (param->type == V4L2_BUF_TYPE_VIDEO_OUTPUT
    || param->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
    param->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
    param->parm.output.timeperframe.numerator =
            akvcam_format_frame_rate(format).denominator;
    param->parm.output.timeperframe.denominator =
            akvcam_format_frame_rate(format).numerator;
    n_buffers = &param->parm.output.writebuffers;
} else {
    param->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
    param->parm.capture.timeperframe.numerator =
            akvcam_format_frame_rate(format).denominator;
    param->parm.capture.timeperframe.denominator =
            akvcam_format_frame_rate(format).numerator;
    n_buffers = &param->parm.capture.readbuffers;
}

akvcam_format_delete(format);

if (akvcam_device_rw_mode(device) & AKVCAM_RW_MODE_READWRITE) {
    akvcam_buffers_t buffers = akvcam_device_buffers_nr(device);
    *n_buffers = (__u32) akvcam_buffers_count(buffers);
}

return 0;

}

Currently GStreamer stops rolling as the default outstanding buffer count is defaulted to 2 and akvcam sets the min buffer count to 4. v4l2 never commits the buffers to start streaming.

Adding the appropriate communication either in akvcam or in GStreamer (or both) resolves the issue.

May also be worth considering changing the default in akvcam to match GStreamer unless there's a good reason to keep it at 4.

@hipersayanX hipersayanX reopened this Mar 19, 2023
hipersayanX added a commit that referenced this issue Mar 19, 2023
As suggested in issue #20, gst-launch is now working fine.
@hipersayanX
Copy link
Member

@thebied Tested, working, committed. Thank you very much! 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants