What is the point of gst_element_link_filtered() ?

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

What is the point of gst_element_link_filtered() ?

wally_bkg
I'm coming to the conclusion that v4l2 and gstreamer is fatally flawed.  Every time I get a new v4l2 capture device something breaks.

I've a new device (Sensoray 2255S) and it was simple to get it to work, but not with code that doesn't break when using some other v4l2 device!

At the end of the day I need a 640x480 grayscale buffer coming out of my appsink.  The problem is how do I define a pipeline to work around the various conversions I need when I don't get a error until the pipeline tries to play?

I was expecting  link_ok = gst_element_link_filtered (source, capsfilter, caps_gray)   to fail on a card that doesn't support grayscale, when the caps filter is set to caps_gray, but it doesn't.  I don't know anything is wrong until I set the pipeline to playing but then its too late!

Perhaps I can best illustrate the problem with a few gst-launch examples, although without the same hardware you likely can't duplicate the problems.


For the device that can't do gray scale directly, this pipeline works:
gst-launch -v v4l2src device=/dev/video6 ! ffmpegcolorspace ! video/x-raw-gray, framerate=\(fraction\)30000/1001, width=640, height=480 ! ffmpegcolorspace ! xvimagesink

It negotiates:
 ffmpegcsp0.GstPad:sink: caps = video/x-raw-yuv, format=(fourcc)I420, framerate=(fraction)30000/1001, width=(int)640, height=(int)480

ffmpegcsp0.GstPad:src: caps = video/x-raw-gray, width=(int)640, height=(int)480, framerate=(fraction)30000/1001, bpp=(int)8, depth=(int)8

The second ffmpegcolor space just fixes the fact that xvimagesink can't do grayscale, but is not relevant to my programmatic appsink pipeline.



For the Sensoray device:
gst-launch -v v4l2src device=/dev/video2 ! ffmpegcolorspace ! video/x-raw-gray, framerate=\(fraction\)30000/1001, width=640, height=480 ! ffmpegcolorspace ! xvimagesink

negotiates:
ffmpegcsp0.GstPad:sink: caps = video/x-raw-yuv, format=(fourcc)I420, framerate=(fraction)30000/1001, width=(int)640, height=(int)480 and all would seem well, except the video has a black bar in the middle because of a bug in either the Sensoray drive, v4l2, or gstreamer the negotiation is incorrect because I420 is not supported in the driver according to v4l-info:

inputs
    VIDIOC_ENUMINPUT(0)
    index                   : 0
    name                    : "Composite"
    type                    : CAMERA
    audioset                : 0
    tuner                   : 0
    std                     : 0xb0ff [PAL_B,PAL_B1,PAL_G,PAL_H,PAL_I,PAL_D,PAL_D1,PAL_K,NTSC_M,NTSC_M_JP,?]
    status                  : 0x0 []

video capture
    VIDIOC_ENUM_FMT(0,VIDEO_CAPTURE)
    index                   : 0
    type                    : VIDEO_CAPTURE
    flags                   : 0
    description             : "4:2:2, planar, YUV422P"
    pixelformat             : 0x50323234 [422P]
    VIDIOC_ENUM_FMT(1,VIDEO_CAPTURE)
    index                   : 1
    type                    : VIDEO_CAPTURE
    flags                   : 0
    description             : "4:2:2, packed, YUYV"
    pixelformat             : 0x56595559 [YUYV]
    VIDIOC_ENUM_FMT(2,VIDEO_CAPTURE)
    index                   : 2
    type                    : VIDEO_CAPTURE
    flags                   : 0
    description             : "4:2:2, packed, UYVY"
    pixelformat             : 0x59565955 [UYVY]
    VIDIOC_ENUM_FMT(3,VIDEO_CAPTURE)
    index                   : 3
    type                    : VIDEO_CAPTURE
    flags                   : 0
    description             : "8bpp GREY"
    pixelformat             : 0x59455247 [GREY]
    VIDIOC_ENUM_FMT(4,VIDEO_CAPTURE)
    index                   : 4
    type                    : VIDEO_CAPTURE
    flags                   : 0
    description             : "JPG"
    pixelformat             : 0x4745504a [JPEG]
    VIDIOC_ENUM_FMT(5,VIDEO_CAPTURE)
    index                   : 5
    type                    : VIDEO_CAPTURE
    flags                   : 0
    description             : "MJPG"
    pixelformat             : 0x47504a4d [MJPG]
    VIDIOC_G_FMT(VIDEO_CAPTURE)
    type                    : VIDEO_CAPTURE
    fmt.pix.width           : 640
    fmt.pix.height          : 480
    fmt.pix.pixelformat     : 0x4745504a [JPEG]
    fmt.pix.field           : INTERLACED
    fmt.pix.bytesperline    : 1920
    fmt.pix.sizeimage       : 921600
    fmt.pix.colorspace      : unknown
    fmt.pix.priv            : 0



Now if I simply do:

 gst-launch -v v4l2src device=/dev/video2 ! xvimagesink

it correctly negotiates a 4:2:2 yuv format and works correctly.  Other of my capture devices don't support support any 4:2:2 formats, so this is not a "common" format I could force the captures to.

So how can I detect this problem before I run the pipeline and adjust the pipeline around it?
Or how do I recover from the "can't negotiate" error when setting the pipeline to playing?



_______________________________________________
gstreamer-devel mailing list
[hidden email]
http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: What is the point of gst_element_link_filtered() ?

Wim Taymans
You can set v4l2src to READY and then query the caps, this should give
you all caps supported by the device.

If you link elements in the READY state, it will check the real
supported formats of the device and linking will fail when no format is
possible. Linking in the NULL state will just do some basic checks but
since the device is not opened, it will not be able to check the device
capabilities.

If you want to get a gray format from the sink you would do:

v4l2src ! ffmpegcolorspace ! video/x-raw-gray ! appsink

it is important to specify at little as possible in the filter to let
the device choose what it can do. In this case, we change the format so
we need an ffmpegcolorspace to make convert in case v4l2src doesn't
support gray.

If you add dimensions to the capsfilter you need to add a videoscale:

v4l2src ! ffmpegcolorspace ! videoscale !
video/x-raw-gray,width=640,height=400 ! appsink

If you want to add a framerate you need to add a videorate.

Wim

On 06/16/2011 11:57 PM, wally bkg wrote:

> I'm coming to the conclusion that v4l2 and gstreamer is fatally flawed.
> Every time I get a new v4l2 capture device something breaks.
>
> I've a new device (Sensoray 2255S) and it was simple to get it to work,
> but not with code that doesn't break when using some other v4l2 device!
>
> At the end of the day I need a 640x480 grayscale buffer coming out of my
> appsink.  The problem is how do I define a pipeline to work around the
> various conversions I need when I don't get a error until the pipeline
> tries to play?
>
> I was expecting  link_ok = gst_element_link_filtered (source,
> capsfilter, caps_gray)   to fail on a card that doesn't support
> grayscale, when the caps filter is set to caps_gray, but it doesn't.  I
> don't know anything is wrong until I set the pipeline to playing but
> then its too late!
>
> Perhaps I can best illustrate the problem with a few gst-launch
> examples, although without the same hardware you likely can't duplicate
> the problems.
>
>
> For the device that can't do gray scale directly, this pipeline works:
> gst-launch -v v4l2src device=/dev/video6 ! ffmpegcolorspace !
> video/x-raw-gray, framerate=\(fraction\)30000/1001, width=640,
> height=480 ! ffmpegcolorspace ! xvimagesink
>
> It negotiates:
>   ffmpegcsp0.GstPad:sink: caps = video/x-raw-yuv, format=(fourcc)I420,
> framerate=(fraction)30000/1001, width=(int)640, height=(int)480
>
> ffmpegcsp0.GstPad:src: caps = video/x-raw-gray, width=(int)640,
> height=(int)480, framerate=(fraction)30000/1001, bpp=(int)8, depth=(int)8
>
> The second ffmpegcolor space just fixes the fact that xvimagesink can't
> do grayscale, but is not relevant to my programmatic appsink pipeline.
>
>
>
> For the Sensoray device:
> gst-launch -v v4l2src device=/dev/video2 ! ffmpegcolorspace !
> video/x-raw-gray, framerate=\(fraction\)30000/1001, width=640,
> height=480 ! ffmpegcolorspace ! xvimagesink
>
> negotiates:
> ffmpegcsp0.GstPad:sink: caps = video/x-raw-yuv, format=(fourcc)I420,
> framerate=(fraction)30000/1001, width=(int)640, height=(int)480 and all
> would seem well, except the video has a black bar in the middle because
> of a bug in either the Sensoray drive, v4l2, or gstreamer the
> negotiation is incorrect because I420 is not supported in the driver
> according to v4l-info:
>
> inputs
>      VIDIOC_ENUMINPUT(0)
>      index                   : 0
>      name                    : "Composite"
>      type                    : CAMERA
>      audioset                : 0
>      tuner                   : 0
>      std                     : 0xb0ff
> [PAL_B,PAL_B1,PAL_G,PAL_H,PAL_I,PAL_D,PAL_D1,PAL_K,NTSC_M,NTSC_M_JP,?]
>      status                  : 0x0 []
>
> video capture
>      VIDIOC_ENUM_FMT(0,VIDEO_CAPTURE)
>      index                   : 0
>      type                    : VIDEO_CAPTURE
>      flags                   : 0
>      description             : "4:2:2, planar, YUV422P"
>      pixelformat             : 0x50323234 [422P]
>      VIDIOC_ENUM_FMT(1,VIDEO_CAPTURE)
>      index                   : 1
>      type                    : VIDEO_CAPTURE
>      flags                   : 0
>      description             : "4:2:2, packed, YUYV"
>      pixelformat             : 0x56595559 [YUYV]
>      VIDIOC_ENUM_FMT(2,VIDEO_CAPTURE)
>      index                   : 2
>      type                    : VIDEO_CAPTURE
>      flags                   : 0
>      description             : "4:2:2, packed, UYVY"
>      pixelformat             : 0x59565955 [UYVY]
>      VIDIOC_ENUM_FMT(3,VIDEO_CAPTURE)
>      index                   : 3
>      type                    : VIDEO_CAPTURE
>      flags                   : 0
>      description             : "8bpp GREY"
>      pixelformat             : 0x59455247 [GREY]
>      VIDIOC_ENUM_FMT(4,VIDEO_CAPTURE)
>      index                   : 4
>      type                    : VIDEO_CAPTURE
>      flags                   : 0
>      description             : "JPG"
>      pixelformat             : 0x4745504a [JPEG]
>      VIDIOC_ENUM_FMT(5,VIDEO_CAPTURE)
>      index                   : 5
>      type                    : VIDEO_CAPTURE
>      flags                   : 0
>      description             : "MJPG"
>      pixelformat             : 0x47504a4d [MJPG]
>      VIDIOC_G_FMT(VIDEO_CAPTURE)
>      type                    : VIDEO_CAPTURE
>      fmt.pix.width           : 640
>      fmt.pix.height          : 480
>      fmt.pix.pixelformat     : 0x4745504a [JPEG]
>      fmt.pix.field           : INTERLACED
>      fmt.pix.bytesperline    : 1920
>      fmt.pix.sizeimage       : 921600
>      fmt.pix.colorspace      : unknown
>      fmt.pix.priv            : 0
>
>
>
> Now if I simply do:
>
>   gst-launch -v v4l2src device=/dev/video2 ! xvimagesink
>
> it correctly negotiates a 4:2:2 yuv format and works correctly.  Other
> of my capture devices don't support support any 4:2:2 formats, so this
> is not a "common" format I could force the captures to.
>
> So how can I detect this problem before I run the pipeline and adjust
> the pipeline around it?
> Or how do I recover from the "can't negotiate" error when setting the
> pipeline to playing?
>
>
>
>
> _______________________________________________
> gstreamer-devel mailing list
> [hidden email]
> http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel

_______________________________________________
gstreamer-devel mailing list
[hidden email]
http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: What is the point of gst_element_link_filtered() ?

wally_bkg
In reply to this post by wally_bkg


You can set v4l2src to READY and then query the caps, this should give you all caps supported by the device.

If you link elements in the READY state, it will check the real supported formats of the device and linking will fail when no format is possible. Linking in the NULL state will just do some basic checks but since the device is not opened, it will not be able to check the device capabilities.
 
Thanks for the tip, all the sample code I've seen shows changing the pipeline state happens after the elements have been added and linked.  Changing the state to READY after the gst_bin_add_many() function and then linking the elements individually lets the gst_element_link_filtered() fail so I can go to "plan B" for building the pipeline.  This makes the work-around I was attempting work now.

 Pehaps  section 8.3.2." Creating capabilities for filtering"  of the manual should be updated to point out that
link_ok = gst_element_link_filtered()
will only fail if the pipeline is in the READY state and will always succeed in the NULL state.


 
If you want to get a gray format from the sink you would do:

v4l2src ! ffmpegcolorspace ! video/x-raw-gray ! appsink

it is important to specify at little as possible in the filter to let the device choose what it can do. In this case, we change the format so we need an ffmpegcolorspace to make convert in case v4l2src doesn't support gray.

I'm afraid you've misunderstood my problem.  The v4l2src is accepting a caps that the Sensory device doesn't actually support.  Up to getting this device I could just link the source un-filtered and all the capture devices worked fine with ffmpegcolorspace doing the conversion.  Ideal situation, in theory, until you get a driver-v4l2-gstreamer bug (don't much matter who's bug it is!) that accepts an invalid caps.

But now I need to try to set gray caps first and if it works I'm done.  If not fall back and try the unfiltered caps as before.
I'm not sure if this will be robust against the next v4l2 capture device I try or not.

I think this whole "query and figure out if it can do what I need" is bass-ackward, what should be happening is I say "set mode whatever" and I get either no error and proceed or trap the error and try "plan B" if one is possible.

All the other stuff you mention was basically being done, as my caps filter has the 680x480 frame size and frame rate stuff in it and there is a videoscale in the pipeline (that I left out for clarity) as one of my capture devices can only do 720x480 or higher and videoscale seems smart enough to be a noop if scaling is not required.



_______________________________________________
gstreamer-devel mailing list
[hidden email]
http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel