x264enc and variable rate appsrc

David J davywj at gmail.com
Tue Sep 22 11:34:45 UTC 2020


Thanks! I like a simple fix.... autovideosink sync=false fixed it!

FYI I had tried framerate 0/1 - I think this is the default if you don't
set anything manually

On Tue, 22 Sep 2020 at 12:27, Gary Metalle <Gary.Metalle at rvl.co.uk> wrote:

> ​Hi
>
>
> What happens if you use a framerate of 0/1? This is the way to define a
> variable framerate.
>
>
> Maybe the issue is with your decoder pipeline and the not the encoding.
> Have you tried setting 'sync=FALSE' for the video sink you're using?
> ------------------------------
> *From:* gstreamer-devel <gstreamer-devel-bounces at lists.freedesktop.org>
> on behalf of David J <davywj at gmail.com>
> *Sent:* 22 September 2020 12:21
> *To:* Discussion of the development of and with GStreamer
> *Subject:* x264enc and variable rate appsrc
>
> I have created a test pipeline (see code below) using a custom appsrc that
> creates an h264 stream and sends over rtp.
>
> I am testing it with the following command line to receive and play the
> video stream:
> gst-launch-1.0 -v udpsrc port=5000 caps = "application/x-rtp,
> media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264,
> payload=(int)96" ! rtph264depay ! decodebin ! videoconvert ! autovideosink
>
> The command-line inside the application looks like this:
> appsrc name=MyAppSrc ! video/x-raw,width=640,height=360,framerate=10/1 !
> videoconvert ! identity name=ident ! x264enc zerolatency=true
> speed-preset=superfast ! rtph264pay ! udpsink host=127.0.0.1 port=5000
>
> At the moment the appsrc is generating frames at precisely 10fps and I set
> the buffer timestamps correctly. However, unless I also specify the
> framerate (in the caps string following the appsrc) as 10/1 the client
> viewer constantly complains of:
> WARNING: from element
> /GstPipeline:pipeline0/GstAutoVideoSink:autovideosink0/GstD3D11VideoSinkBin:autovideosink0-actual-sink-d3d11video/GstD3D11VideoSink:d3d11videosink0:
> A lot of buffers are being dropped.
> Additional debug info:
> ../libs/gst/base/gstbasesink.c(3134): gst_base_sink_is_too_late ():
> /GstPipeline:pipeline0/GstAutoVideoSink:autovideosink0/GstD3D11VideoSinkBin:autovideosink0-actual-sink-d3d11video/GstD3D11VideoSink:d3d11videosink0:
> There may be a timestamping problem, or this computer is too slow.
>
>
> *The problem is:*
> In the real application, the appsrc will produce frames at a variable rate
> - between about 2 and 20 fps. How can I get this to work if I'm required to
> set a fixed framerate?
>
> Provided the buffer timestamps are set, why does the framerate property
> have any bearing on the pipeine?
>
> Here is the application code:
>
> // NativeBasicPipeline.cpp : This file contains the 'main' function.
> Program execution begins and ends there.
> //
>
> #include <gst/gst.h>
> #include <gst/app/gstappsrc.h>
>
> GTimer* timer;
>
> GstAppSrc* appSrc;
>
> guint sourceid = 0;
>
> int width = 1;
>
> int colour = 255;
>
> bool read_data()
> {
>     static GstClockTime time = 0;
>     static guint64 offset = 0;
>
>     GstFlowReturn ret;
>     auto ms = g_timer_elapsed(timer, NULL);
>
>     if (ms > 1.0 / 10.0) {
>         auto size = 640 * 3 * 360;
>
>         gpointer copy = g_malloc(size);
>
>         memset(copy, colour % 255, size);
>
>         colour += 10;
>
>         GstBuffer* buffer = gst_buffer_new_wrapped(copy, size);
>
>
>         //GST_BUFFER_TIMESTAMP(buffer) = pts;
>         GST_BUFFER_PTS(buffer) = time;
>         GST_BUFFER_DTS(buffer) = time;
>         GST_BUFFER_DURATION(buffer) = 100 * GST_MSECOND;
>
>         GST_BUFFER_OFFSET(buffer) = offset++;
>         GST_BUFFER_OFFSET_END(buffer) = offset;
>
>         time += 100 * GST_MSECOND;
>
>         g_signal_emit_by_name(appSrc, "push-buffer", buffer, &ret);
>
>         //ret = gst_app_src_push_buffer(appSrc, buffer);
>         gst_buffer_unref(buffer);
>
>         g_timer_start(timer);
>
>         return TRUE;
>     }
>
>     return TRUE;
> }
>
> void start_feed(GstElement* pipeline, guint size, void* unused)
> {
>     if (sourceid == 0) {
>         sourceid = g_idle_add((GSourceFunc)read_data, 0);
>     }
> }
>
> void stop_feed(GstElement* pipeline, void* unused)
> {
>     if (sourceid != 0) {
>         g_source_remove(sourceid);
>         sourceid = 0;
>     }
> }
>
> static gboolean print_field(GQuark field, const GValue* value, gpointer
> pfx) {
>     gchar* str = gst_value_serialize(value);
>
>     g_print("%s  %15s: %s\n", (gchar*)pfx, g_quark_to_string(field), str);
>     g_free(str);
>     return TRUE;
> }
>
> static void print_caps(const GstCaps* caps, const gchar* pfx) {
>     guint i;
>
>     g_return_if_fail(caps != NULL);
>
>     if (gst_caps_is_any(caps)) {
>         g_print("%sANY\n", pfx);
>         return;
>     }
>     if (gst_caps_is_empty(caps)) {
>         g_print("%sEMPTY\n", pfx);
>         return;
>     }
>
>     for (i = 0; i < gst_caps_get_size(caps); i++) {
>         GstStructure* structure = gst_caps_get_structure(caps, i);
>
>         g_print("%s%s\n", pfx, gst_structure_get_name(structure));
>         gst_structure_foreach(structure, print_field, (gpointer)pfx);
>     }
> }
>
> void handoff(GstElement* pipeline, GstBuffer* buffer, void* unused)
> {
>     static int count = 0;
>     static GstBuffer* buffers[50];
>
>     //auto ident = gst_bin_get_by_name(GST_BIN(pipeline), "ident");
>     auto pads = GST_ELEMENT_PADS(pipeline);
>
>     auto pad0 = GST_PAD(pads->data);
>     auto pad1 = GST_PAD(pads->next->data);
>
>     auto caps = gst_pad_get_current_caps(pad1);
>
>     print_caps(caps, "");
>
>     if (count < 50)
>     {
>         GstBuffer* copy = gst_buffer_copy(buffer);
>
>         buffers[count] = copy;
>
>         ++count;
>     }
>     else
>     {
>         count = 100;
>
>
>     }
> }
>
> int main()
> {
>     GstElement* pipeline;
>     GstBus* bus;
>     GstMessage* msg;
>
>     timer = g_timer_new();
>
>
>     /* Initialize GStreamer */
>     gst_init(0, 0);
>
>     /* Build the pipeline */
>
>     GError* err = 0;
>
>     //auto udpPipe = "videotestsrc pattern=smpte !
> video/x-raw,width=640,height=360,framerate=10/1 ! videoscale ! videoconvert
> ! identity name=ident ! x264enc zerolatency=true speed-preset=superfast !
> rtph264pay ! udpsink host=127.0.0.1 port=5000";
>
>     //auto videoPipe = "videotestsrc pattern=smpte !
> video/x-raw,width=640,height=360,framerate=10/1 ! videoscale ! videoconvert
> ! autovideosink";
>
>     auto appSrcPipe = "appsrc name=MyAppSrc !
> video/x-raw,width=640,height=360 ! videoconvert ! identity name=ident !
> x264enc zerolatency=true speed-preset=superfast ! rtph264pay ! udpsink
> host=127.0.0.1 port=5000";
>
>     //auto appSrcPipeVideo = "appsrc name=MyAppSrc ! videoscale !
> videoconvert ! autovideosink";
>
>     pipeline =
>         gst_parse_launch
>         (appSrcPipe,
>             &err);
>
>     appSrc = (GstAppSrc*)gst_bin_get_by_name(GST_BIN(pipeline),
> "MyAppSrc");
>
>     g_object_set(G_OBJECT(appSrc), "format", GST_FORMAT_TIME, NULL);
>
>     g_signal_connect(appSrc, "need-data", G_CALLBACK(start_feed), 0);
>     g_signal_connect(appSrc, "enough-data", G_CALLBACK(stop_feed), 0);
>
>     auto caps = gst_caps_new_simple("video/x-raw",
>         "format", G_TYPE_STRING, "RGB",
>         "bpp", G_TYPE_INT, 24,
>         "depth", G_TYPE_INT, 24,
>         "width", G_TYPE_INT, 640,
>         "height", G_TYPE_INT, 360,
>         NULL);
>
>     gst_app_src_set_caps((GstAppSrc*)appSrc, caps);
>
>     //GstPad* pad = gst_element_get_static_pad(appSrc, "src");
>
>     //auto ident = gst_bin_get_by_name(GST_BIN(pipeline), "ident");
>
>     //g_signal_connect(ident, "handoff", G_CALLBACK(handoff), 0);
>
>
>     /* Start playing */
>     gst_element_set_state(pipeline, GST_STATE_PLAYING);
>
>     auto main_loop = g_main_loop_new(NULL, FALSE);
>     g_main_loop_run(main_loop);
>
>     /* Wait until error or EOS */
>     bus = gst_element_get_bus(pipeline);
>     msg =
>         gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE,
>             (GstMessageType)(GST_MESSAGE_ERROR | GST_MESSAGE_EOS));
>
>     /* Free resources */
>     if (msg != NULL)
>         gst_message_unref(msg);
>     gst_object_unref(bus);
>     gst_element_set_state(pipeline, GST_STATE_NULL);
>     gst_object_unref(pipeline);
>     return 0;
> }
>
>
> _______________________________________________
> gstreamer-devel mailing list
> gstreamer-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/gstreamer-devel/attachments/20200922/7637dc94/attachment-0001.htm>


More information about the gstreamer-devel mailing list