GStreamer launch pipeline to code with different result

26 views Asked by At

I do have a gstreamer pipeline string running with gst-launch (CreateVideoPipelineSinkWithLaunch).

Now I want to build the same pipeline in code with go-gst (golang bindings). The resulting pipeline (CreateVideoPipelineSink) does run, but for some reason the webrtc frontend is showing a frame every 30s only.

Have tried to run it with GST_DEBUG=*:3 but this does not show any meaningful (The same warnings are logged with the string launch).

0:00:50.268410257 109844 0x75003c000f70 WARN                    v4l2 gstv4l2object.c:4721:gst_v4l2_object_set_crop:<v4l2src0:src> VIDIOC_S_CROP failed
0:00:50.278151417 109844 0x75003c000f70 WARN                    v4l2 gstv4l2object.c:3429:gst_v4l2_object_reset_compose_region:<v4l2src0:src> Failed to get default compose rectangle with VIDIOC_G_SELECTION: Invalid argument

I had this problem many times that just writing the same as in a launch string, does result in trouble and I would understand why.

func CreateVideoPipelineSinkWithLaunch(_ *zap.Logger) (*gst.Pipeline, <-chan media.Sample, error) {
    pipeline, err := gst.NewPipelineFromString(`v4l2src device=/dev/video4 ! capsfilter caps="video/x-raw,width=(int)320,height=(int)240" ! videoconvert ! queue ! capsfilter caps="video/x-raw,format=(string)I420" ! x264enc speed-preset=ultrafast tune=zerolatency key-int-max=20 ! capsfilter caps="video/x-h264,stream-format=(string)byte-stream" ! appsink name=appsink`)
    if err != nil {
        return nil, nil, err
    }

    elem, err := pipeline.GetElementByName("appsink")
    if err != nil {
        return nil, nil, err
    }

    appsink := app.SinkFromElement(elem)
    ch := make(chan media.Sample, 100)
    setCallback(appsink, ch)

    return pipeline, ch, nil
}

func CreateVideoPipelineSink(lg *zap.Logger) (*gst.Pipeline, <-chan media.Sample, error) {
    // Create a pipeline
    pipeline, err := gst.NewPipeline("pion-video-pipeline")
    if err != nil {
        return nil, nil, err
    }

    elems := make([]*gst.Element, 0)

    // Create the src
    src, err := gst.NewElement("v4l2src")
    if err != nil {
        return nil, nil, err
    }
    elems = append(elems, src)

    src.Set("device", "/dev/video4")

    filter1, err := gst.NewElement("capsfilter")
    if err != nil {
        return nil, nil, err
    }
    elems = append(elems, filter1)

    c := gst.NewEmptySimpleCaps("video/x-raw")
    c.SetValue("width", int(320))
    c.SetValue("height", int(240))
    lg.Info("capsfilter", zap.String("caps", c.String()))
    err = filter1.SetProperty("caps", c)
    if err != nil {
        return nil, nil, err
    }

    // just to be on the save side
    conv, err := gst.NewElement("videoconvert")
    if err != nil {
        return nil, nil, err
    }
    elems = append(elems, conv)

    // add a queue
    queue, err := gst.NewElement("queue")
    if err != nil {
        return nil, nil, err
    }
    elems = append(elems, queue)

    // add a filter before enc
    filterIn, err := gst.NewElement("capsfilter")
    if err != nil {
        return nil, nil, err
    }
    elems = append(elems, filterIn)

    cIn := gst.NewEmptySimpleCaps("video/x-raw")
    cIn.SetValue("format", "I420")
    lg.Info("capsfilter", zap.String("caps", cIn.String()))
    err = filterIn.SetProperty("caps", cIn)
    if err != nil {
        return nil, nil, err
    }

    // Create the enc
    enc, err := gst.NewElement("x264enc")
    if err != nil {
        return nil, nil, err
    }
    elems = append(elems, enc)

    enc.SetProperty("speed-preset", "ultrafast")
    enc.SetProperty("tune", "zerolatency")
    enc.SetProperty("key-int-max", 20)
    //enc.SetProperty("bitrate", 300)

    // add a filter after enc
    filterOut, err := gst.NewElement("capsfilter")
    if err != nil {
        return nil, nil, err
    }
    elems = append(elems, filterOut)

    cOut := gst.NewEmptySimpleCaps("video/x-h264")
    cOut.SetValue("stream-format", "byte-stream")
    lg.Info("capsfilter", zap.String("caps", cOut.String()))
    err = filterOut.SetProperty("caps", cOut)
    if err != nil {
        return nil, nil, err
    }

    // Create the sink
    appsink, err := app.NewAppSink()
    if err != nil {
        return nil, nil, err
    }
    elems = append(elems, appsink.Element)

    ch := make(chan media.Sample, 100)
    setCallback(appsink, ch)

    // Add the elements to the pipeline
    pipeline.AddMany(elems...)

    // link the elements
    gst.ElementLinkMany(elems...)

    return pipeline, ch, nil
}
0

There are 0 answers