RE: Issue with rtsp server source h264 encoded

LEVY David via gstreamer-devel <[email protected]>
Newsgroups gmane.comp.video.gstreamer.devel
Message-ID <YT3PR01MB65500483BF0D3CF1B7EACC16E8FFA@YT3PR01MB6550.CANPRD01.PROD.OUTLOOK.COM>
Same behaviour with both main and constrained-baseline

But since the rtsp server does not emit the "need-data" signal more than once, I would suppose the issue is coming from here, and not the encoding
(but I don't know at all how all this work im new, so it may be completely wrong)

From: Nicolas Dufresne <[email protected]>
Sent: Thursday, September 21, 2023 8:33 PM
To: Discussion of the development of and with GStreamer <[email protected]>
Cc: LEVY David <[email protected]>; Michael Gruner <[email protected]>
Subject: Re: Issue with rtsp server source h264 encoded

videotestsrc ! x264enc tune=zerolayency tends to negotiate yuv444+high profile. That can cause introp issues. Ide suggest a caps filter after the encoder with caps video/x-h264,profile=main (or constrained-baseline, though that will not compress as much).

Hopefully this will improve your situation.

Le jeu. 21 sept. 2023, 16 h 30, LEVY David via gstreamer-devel <[email protected]<mailto:[email protected]>> a écrit :
Same behaviour.

I just noted that "need-data" is only called once with ffplay, and twice with gst-launch (probably once udp and once tcp)

From: Michael Gruner <[email protected]<mailto:[email protected]>>
Sent: Thursday, September 21, 2023 2:45 PM
To: Discussion of the development of and with GStreamer <[email protected]<mailto:[email protected]>>
Cc: LEVY David <[email protected]<mailto:[email protected]>>
Subject: Re: Issue with rtsp server source h264 encoded

Hi

Try sending periodic I frames, "x264enc key-int-max=10" or, programmatically:

    g_object_set( lEncoder, "key-int-max", 10, NULL ); // 4 = zerolatency


10 is just a made up number to send a reference frame every second (given that your framerate is 10/1). You may space them according to your needs.

Michael.

On 21 Sep 2023, at 09:59, LEVY David via gstreamer-devel <[email protected]<mailto:[email protected]>> wrote:

Hello,
i'm new to gstreamer / rtsp so, sorry if it's a basic mistake.

Im trying to set up a pipeline that end with an appsink that push data into a rtsp server starting with an appsrc.

It would be:
videotestsrc -> x264enc -> appsink (push data to src as soon as received)
and
appsrc -> rtph264pay

I can't find any example similar, but I found this one:
https://github.com/GStreamer/gst-rtsp-server/blob/master/examples/test-appsrc.c

Which does:
appsrc-> videoconvert -> x264enc -> rtph264pay (and uses "need-data")

I have successfully tweaked it to
videotestsrc -> appsink
appsrc-> videoconvert -> x264enc -> rtph264pay (and uses "need-data")

My next step would be
Videotestsrc -> x264enc -> appsink
appsrc-> rtph264pay (and uses "need-data")

but when I try to read the stream from either
    gst-launch-1.0 --gst-debug=rtspsrc:2 rtspsrc location=rtsp://127.0.0.1:8554/test ! queue ! rtph264depay ! h264parse ! avdec_h264 ! videoconvert ! videoscale ! autovideosink
or ffplay rtsp://127.0.0.1:8554/test

I don't have any playback:

Setting pipeline to PAUSED ...
Pipeline is live and does not need PREROLL ...
Got context from element 'autovideosink0': gst.gl.GLDisplay=context, gst.gl.GLDisplay=(GstGLDisplay)"\(GstGLDisplayWayland\)\ gldisplaywayland0";
Progress: (open) Opening Stream
Pipeline is PREROLLED ...
Prerolled, waiting for progress to finish...
Progress: (connect) Connecting to rtsp://127.0.0.1:8554/test
Progress: (open) Retrieving server options
Progress: (open) Retrieving media info
Progress: (request) SETUP stream 0
Progress: (open) Opened Stream
Setting pipeline to PLAYING ...
New clock: GstSystemClock
Progress: (request) Sending PLAY request
Redistribute latency...
Progress: (request) Sending PLAY request
Redistribute latency...
Progress: (request) Sent PLAY request
Redistribute latency...
Redistribute latency...
0:00:05.945770874 15996 0x55c83ec97f60 WARN                 rtspsrc gstrtspsrc.c:5964:gst_rtspsrc_reconnect:<rtspsrc0> warning: Could not receive any UDP packets for 5.0000 seconds, maybe your firewall is blocking it. Retrying using a tcp connection.
WARNING: from element /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0: Could not read from resource.
Additional debug info:
../gst/rtsp/gstrtspsrc.c(5964): gst_rtspsrc_reconnect (): /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0:
Could not receive any UDP packets for 5.0000 seconds, maybe your firewall is blocking it. Retrying using a tcp connection.
Redistribute latency...

And it is stuck here

I'm using the code below:


#include <gst/gst.h>

#include <gst/app/gstappsink.h>
#include <gst/app/gstappsrc.h>
#include <gst/rtsp-server/rtsp-server.h>

GstElement *gSink = nullptr;

static void InitPipeline()
{
    GstElement *lPipeline = gst_pipeline_new( "x264-pipeline" );

    GstElement *lSource  = gst_element_factory_make( "videotestsrc", "source" );
    GstElement *lEncoder = gst_element_factory_make( "x264enc", "x264-encoder" );
    GstElement *lSink    = gst_element_factory_make( "appsink", "appsink" );

    gst_bin_add_many( GST_BIN( lPipeline ), lSource, lEncoder, lSink, NULL );
    // gst_bin_add_many( GST_BIN( lPipeline ), lSource, lSink, NULL );
    g_object_set( lEncoder, "tune", 4, NULL ); // 4 = zerolatency

    GstCaps *lCaps =
        gst_caps_new_simple( "video/x-raw", "width", G_TYPE_INT, 384, "height", G_TYPE_INT, 288, "framerate", GST_TYPE_FRACTION, 10, 1, NULL );
    if( !gst_element_link_filtered( lSource, lEncoder, lCaps ) )
    // if( !gst_element_link_filtered( lSource, lSink, lCaps ) )
    {
        gst_caps_unref( lCaps );
        throw;
    }
    gst_caps_unref( lCaps );
    gst_element_link( lEncoder, lSink );

    GstStateChangeReturn ret = gst_element_set_state( lPipeline, GST_STATE_PLAYING );
    if( ret == GST_STATE_CHANGE_FAILURE )
    {
        throw;
    }
    gSink = lSink;
}

static void need_data( GstElement *appsrc, guint unused, void *aUnused )
{
    GstSample *lSample = gst_app_sink_pull_sample( GST_APP_SINK_CAST( gSink ) );
    GstFlowReturn lRet = gst_app_src_push_sample( GST_APP_SRC( appsrc ), lSample );
    gst_sample_unref( lSample );
    return;
}

static void media_configure( GstRTSPMediaFactory *factory, GstRTSPMedia *media, gpointer user_data )
{
    GstElement *element, *appsrc;

    element = gst_rtsp_media_get_element( media );
    appsrc = gst_bin_get_by_name_recurse_up( GST_BIN( element ), "mysrc" );

    gst_util_set_object_arg( G_OBJECT( appsrc ), "format", "time" );

    if( GstPad *pad = gst_element_get_static_pad( gSink, "sink" ) )
    {
        g_print( "Got pad\n" );
        GstCaps *caps = gst_pad_get_current_caps( pad );
        if( caps )
        {
            auto *caps_str = gst_caps_to_string( caps );
            g_print( "Got caps %s\n", caps_str );
            g_object_set( G_OBJECT( appsrc ), "caps", caps, NULL );

            gst_caps_unref( caps );
        }
    }

    g_signal_connect( appsrc, "need-data", (GCallback)need_data, NULL );
    gst_object_unref( appsrc );
    gst_object_unref( element );
}

int main( int argc, char *argv[] )
{
    GMainLoop *loop;
    GstRTSPServer *server;
    GstRTSPMountPoints *mounts;
    GstRTSPMediaFactory *factory;

    gst_init( &argc, &argv );

    loop = g_main_loop_new( NULL, FALSE );

    InitPipeline();

    server = gst_rtsp_server_new();
    mounts = gst_rtsp_server_get_mount_points( server );
    factory = gst_rtsp_media_factory_new();

    // gst_rtsp_media_factory_set_launch( factory, "( appsrc name=mysrc ! videoconvert ! x264enc ! rtph264pay name=pay0 pt=96 )" );
    gst_rtsp_media_factory_set_launch( factory, "( appsrc name=mysrc ! rtph264pay name=pay0 pt=96 )" );

    g_signal_connect( factory, "media-configure", (GCallback)media_configure, NULL );
    gst_rtsp_mount_points_add_factory( mounts, "/test", factory );
    g_object_unref( mounts );

    gst_rtsp_server_attach( server, NULL );

    g_print( "stream ready at rtsp://127.0.0.1:8554/test\n" );
    g_main_loop_run( loop );

    return 0;
}


Is it a good idea to convert before the appsink?

Thanks for your time
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.