RE: Issue with rtsp server source h264 encoded

LEVY David via gstreamer-devel <[email protected]>
Newsgroups gmane.comp.video.gstreamer.devel
Message-ID <YT3PR01MB65507782B196898D777E1F7AE8F8A@YT3PR01MB6550.CANPRD01.PROD.OUTLOOK.COM>
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]>
Sent: Thursday, September 21, 2023 2:45 PM
To: Discussion of the development of and with GStreamer <[email protected]>
Cc: LEVY David <[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<rtsp://127.0.0.1:8554/test/n>\n<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.