RTSP server not working with .ts files

Section1: problem statement

I have a working deepstream application developed based on deepstream_test_5 in C that uses uri=file://../streamer/Vehicle.Target.Sample_EO.ts under [source0] tag in a config file.

It runs using this command:
./my-app -c configs/test_config_file_src_infer.txt

Desired next step
Now I want to configure the application to use uri=rtsp:// under the [source0] tag in the config file.


Section2: Checking the video

nvidia@jetson2:/opt/nvidia/deepstream/deepstream/sources/apps/sample_apps/my-app/streamer$ gst-discoverer-1.0 Vehicle.Target.Sample_EO.ts

Analyzing file:///opt/nvidia/deepstream/deepstream/sources/apps/sample_apps/my-app/streamer/Vehicle.Target.Sample_EO.ts


NvMMLiteOpen : Block : BlockType = 261 

NVMEDIA: Reading vendor.tegra.display-size : status: 6 

NvMMLiteBlockCreate : Block : BlockType = 261 

Done discovering file:///opt/nvidia/deepstream/deepstream/sources/apps/sample_apps/my-app/streamer/Vehicle.Target.Sample_EO.ts

  container: MPEG-2 Transport Stream
	video: H.264 (Main Profile)

  Duration: 0:00:28.445187777
  Seekable: yes
  Live: no
	  video codec: H.264


Section3: Set up of the RTSP server (look at comment by Dusan Kovacevic): https://stackoverflow.com/questions/59858898/how-to-convert-a-video-on-disk-to-a-rtsp-stream#

  • note the changes to my pipeline in the python file for src_demux and h264_transcode!


import sys
import gi

gi.require_version('Gst', '1.0')
gi.require_version('GstRtspServer', '1.0')
from gi.repository import Gst, GstRtspServer, GObject, GLib

loop = GLib.MainLoop()

class TestRtspMediaFactory(GstRtspServer.RTSPMediaFactory):
	def __init__(self):

	def do_create_element(self, url):
		#set mp4 file path to filesrc's location property
		src_demux = "filesrc location=streamer/Vehicle.Target.Sample_EO.ts ! qtdemux name=demux"

                    # Uncomment below to use a test source
                    # src_demux = "videotestsrc ! qtdemux name=demux"

		h264_transcode = "demux.video_0"
		#uncomment following line if video transcoding is necessary
		h264_transcode = "demux.video_0 ! decodebin ! queue ! x264enc"
		pipeline = "{0} {1} ! queue ! rtph264pay name=pay0 config-interval=1 pt=96".format(src_demux, h264_transcode)
		print("Element created: " + pipeline)
		return Gst.parse_launch(pipeline)

class GstreamerRtspServer:
	def __init__(self):
		self.rtspServer = GstRtspServer.RTSPServer()
		factory = TestRtspMediaFactory()
		mountPoints = self.rtspServer.get_mount_points()
		mountPoints.add_factory("/stream1", factory)

if __name__ == '__main__':
	s = GstreamerRtspServer()

running the server (rtsp_server.py):
python3 rtsp_server.py

  • please note src_demux can be changed to use a videotestsrc and it works for step 3!


Section 4: reading from the RTSP stream with Gstreamer

  • run gstreamer

      nvidia@jetson2:/opt/nvidia/deepstream/deepstream/sources/apps/sample_apps/my-app$ GST_DEBUG=3 gst-launch-1.0 playbin uri=rtsp://
      Setting pipeline to PAUSED ...
      Pipeline is live and does not need PREROLL ...
      Progress: (open) Opening Stream
      Progress: (connect) Connecting to rtsp://
      Progress: (open) Retrieving server options
      Progress: (open) Retrieving media info
      0:00:00.102916883 19618   0x5589ed8280 WARN                 rtspsrc gstrtspsrc.c:6161:gst_rtspsrc_send:<source> error: Unhandled error
      0:00:00.103013750 19618   0x5589ed8280 WARN                 rtspsrc gstrtspsrc.c:6161:gst_rtspsrc_send:<source> error: Service Unavailable (503)
      0:00:00.103385859 19618   0x5589ed8280 WARN                 rtspsrc gstrtspsrc.c:7548:gst_rtspsrc_open:<source> can't get sdp
      ERROR: from element /GstPlayBin:playbin0/GstURIDecodeBin:uridecodebin0/GstRTSPSrc:source: Unhandled error
      0:00:00.103474726 19618   0x5589ed8280 WARN                 rtspsrc gstrtspsrc.c:5628:gst_rtspsrc_loop:<source> we are not connected
      Additional debug info:
      gstrtspsrc.c(6161): gst_rtspsrc_send (): /GstPlayBin:playbin0/GstURIDecodeBin:uridecodebin0/GstRTSPSrc:source:
      Service Unavailable (503)
      ERROR: pipeline doesn't want to preroll.
      Setting pipeline to PAUSED ...
      Setting pipeline to READY ...
      Setting pipeline to NULL ...
      Freeing pipeline ...
  • it doesn’t run but look what happens to rtsp_server.py after I run this command. A new element is created by rtsp_server.py each time I run this gstreamer command:

      nvidia@jetson2:/opt/nvidia/deepstream/deepstream-5.0/sources/apps/sample_apps/my-app$ python3 rtsp_server.py
      Element created: filesrc location=streamer/Vehicle.Target.Sample_EO.ts ! qtdemux name=demux demux.video_0 ! queue ! rtph264pay name=pay0 config-interval=1 pt=96



  • This seems quite straightforward and it works for a videotestsrc, so where may I investigate to see why it doesn’t work with a .ts file?

  • How can I properly install gst-validate-1.0? I installed all normal packages from the gstreamer installation page (gstreamer has been working for a while now) and also installed the .tar.xz files located here (https://gstreamer.freedesktop.org/) with this command:

      sudo tar Jxvf [package-name.tar.xz]

I cannot use gst-validate-1.0 playbin uri=file:///path/to/some/media/file it only gives this:

    nvidia@jetson2:/opt/nvidia/deepstream/deepstream/sources/apps/sample_apps/my-app/streamer$ gst-validate-1.0 Vehicle.Target.Sample_EO.ts
        -bash: gst-validate-1.0: command not found

Thanks for reading and your help is much appreciated!

We have existing implementation in sink group. Please check development guide.
Suggest modify config file to enable it and try.

Reading the documentation (your suggestion) is not a solution!

In this case the solution was created by modifying the way that the RTSP server demuxed the β€˜.ts’ file. I’ll create a proper reply later in the week.

Does Nvidia have an example of using an RTSP server with a β€˜.ts’ file in the development guide?

There is a wiki page from RidgeRun. Please take a look:

Usually we use rtph264pay or rtph265pay. You may follow the page to use mpegtsmux.

1 Like

A later in the week ;)

here is the repository to reference this solution: https://github.com/GStreamer/gst-rtsp-server

  • in the deepstream configuration file, set the following match to declarations at top of rtsp-server-launch.c below:

    #Type - 1=CameraV4L2 2=URI 3=MultiURI

  • first start the rtsp streamer by running the following two commands:

      	gcc rtsp-server-launch.c -o rtsp-server-launch $(pkg-config --cflags --libs gstreamer-1.0 gstreamer-rtsp-server-1.0)
  • when the deepstream app is initiated the β€˜video’ is pulled into deepstream and the β€˜klv’ data from the ts file is broadcast over UDP port

  • below is the tailored solution of this file: https://github.com/GStreamer/gst-rtsp-server/blob/master/examples/test-launch.c

      	nvidia@jetson2:/opt/nvidia/deepstream/deepstream-5.0/sources/apps/sample_apps/streamer$ cat rtsp-server-launch.c 
      	/* GStreamer
      	 * Copyright (C) 2008 Wim Taymans <wim.taymans at gmail.com>
      	 * This library is free software; you can redistribute it and/or
      	 * modify it under the terms of the GNU Library General Public
      	 * License as published by the Free Software Foundation; either
      	 * version 2 of the License, or (at your option) any later version.
      	 * This library is distributed in the hope that it will be useful,
      	 * but WITHOUT ANY WARRANTY; without even the implied warranty of
      	 * Library General Public License for more details.
      	 * You should have received a copy of the GNU Library General Public
      	 * License along with this library; if not, write to the
      	 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
      	 * Boston, MA 02110-1301, USA.
      	#include <gst/gst.h>
      	#include <gst/rtsp-server/rtsp-server.h>
      	#include <stdio.h>
      	#include <string.h>
      	#define DEFAULT_RTSP_PORT "50007"
      	#define DEFAULT_RTSP_ADDRESS ""
      	#define DEFAULT_LAUNCH_COMMAND "filesrc location=videos/sample_video.ts ! tee name=t ! queue ! video/x-h264,stream-format=byte-stream,alignment=nal ! udpsink host= port=50007 auto-multicast=true t. ! queue ! tsdemux ! h264parse ! rtph264pay name=pay0 pt=96"
      	#define URL_PATH "stream"
      	static char *port = (char *) DEFAULT_RTSP_PORT;
      	static GOptionEntry entries[] = {
      			{"port", 'p', 0, G_OPTION_ARG_STRING, &port,
      					"Port to listen on (default: " DEFAULT_RTSP_PORT ")", "PORT"},
      	int main (int argc, char *argv[]) {
      		GMainLoop *loop;
      		GstRTSPServer *server;
      		GstRTSPMountPoints *mounts;
      		GstRTSPMediaFactory *factory;
      		GOptionContext *optctx;
      		GError *error = NULL;
      		/* Set configurations from arguments or default parameters */
      		const char *launch = (char *) DEFAULT_LAUNCH_COMMAND;
      		const char *address = (char *) DEFAULT_RTSP_ADDRESS;
      		const char *using_port = (char *) DEFAULT_RTSP_PORT;
      		const char *path = (char *) URL_PATH;
      		optctx = g_option_context_new ("<launch line> - Test RTSP Server, Launch\n\n"
      									   "Example: \"( videotestsrc ! x264enc ! rtph264pay name=pay0 pt=96 )\"");
      		g_option_context_add_main_entries (optctx, entries, NULL);
      		g_option_context_add_group (optctx, gst_init_get_option_group ());
      		if (!g_option_context_parse (optctx, &argc, &argv, &error)) {
      			g_printerr ("Error parsing options: %s\n", error->message);
      			g_option_context_free (optctx);
      			g_clear_error (&error);
      			return -1;
      		g_option_context_free (optctx);
      		loop = g_main_loop_new (NULL, FALSE);
      		printf("\naddress:: (%s)\tport:: (%s)\tpath:: (%s)\nlaunch:: (%s)\n\n", address, port, path, launch);
      		/* create a server instance */
      		server = gst_rtsp_server_new ();
      		gst_rtsp_server_set_address(server, address);
      		g_object_set (server, "service", using_port, NULL);
      		/* get the mount points for this server, every server has a default object
      		 * that be used to map uri mount points to media factories */
      		mounts = gst_rtsp_server_get_mount_points (server);
      		/* make a media factory for a test stream. The default media factory can use
      		 * gst-launch syntax to create pipelines.
      		 * any launch line works as long as it contains elements named pay%d. Each
      		 * element with pay%d names will be a stream */
      		factory = gst_rtsp_media_factory_new ();
      		gst_rtsp_media_factory_set_launch (factory, launch);
      		gst_rtsp_media_factory_set_shared (factory, TRUE);
      		/* attach the test factory to the URL_PATH url */
      		gst_rtsp_mount_points_add_factory (mounts, path, factory);
      		/* don't need the ref to the mapper anymore */
      		g_object_unref (mounts);
      		/* attach the server to the default maincontext */
      		gst_rtsp_server_attach (server, NULL);
      		/* start serving */
      		g_print ("stream ready at rtsp://%s:%s/%s\n", address, using_port, path);
      		g_main_loop_run (loop);
      		return 0;

  • for those wondering where the files are located:

      	nvidia@jetson2:/opt/nvidia/deepstream/deepstream-5.0/sources/apps/sample_apps/streamer$ tree
      β”œβ”€β”€ gst
      β”‚   └── rtsp-server
      β”‚       β”œβ”€β”€ Makefile
      β”‚       β”œβ”€β”€ Makefile.am
      β”‚       β”œβ”€β”€ Makefile.in
      β”‚       β”œβ”€β”€ meson.build
      β”‚       β”œβ”€β”€ rtsp-address-pool.c
      β”‚       β”œβ”€β”€ rtsp-address-pool.h
      β”‚       β”œβ”€β”€ rtsp-auth.c
      β”‚       β”œβ”€β”€ rtsp-auth.h
      β”‚       β”œβ”€β”€ rtsp-client.c
      β”‚       β”œβ”€β”€ rtsp-client.h
      β”‚       β”œβ”€β”€ rtsp-context.c
      β”‚       β”œβ”€β”€ rtsp-context.h
      β”‚       β”œβ”€β”€ rtsp-media.c
      β”‚       β”œβ”€β”€ rtsp-media-factory.c
      β”‚       β”œβ”€β”€ rtsp-media-factory.h
      β”‚       β”œβ”€β”€ rtsp-media-factory-uri.c
      β”‚       β”œβ”€β”€ rtsp-media-factory-uri.h
      β”‚       β”œβ”€β”€ rtsp-media.h
      β”‚       β”œβ”€β”€ rtsp-mount-points.c
      β”‚       β”œβ”€β”€ rtsp-mount-points.h
      β”‚       β”œβ”€β”€ rtsp-onvif-client.c
      β”‚       β”œβ”€β”€ rtsp-onvif-client.h
      β”‚       β”œβ”€β”€ rtsp-onvif-media.c
      β”‚       β”œβ”€β”€ rtsp-onvif-media-factory.c
      β”‚       β”œβ”€β”€ rtsp-onvif-media-factory.h
      β”‚       β”œβ”€β”€ rtsp-onvif-media.h
      β”‚       β”œβ”€β”€ rtsp-onvif-server.c
      β”‚       β”œβ”€β”€ rtsp-onvif-server.h
      β”‚       β”œβ”€β”€ rtsp-params.c
      β”‚       β”œβ”€β”€ rtsp-params.h
      β”‚       β”œβ”€β”€ rtsp-permissions.c
      β”‚       β”œβ”€β”€ rtsp-permissions.h
      β”‚       β”œβ”€β”€ rtsp-sdp.c
      β”‚       β”œβ”€β”€ rtsp-sdp.h
      β”‚       β”œβ”€β”€ rtsp-server.c
      β”‚       β”œβ”€β”€ rtsp-server.h
      β”‚       β”œβ”€β”€ rtsp-server-object.h
      β”‚       β”œβ”€β”€ rtsp-server-prelude.h
      β”‚       β”œβ”€β”€ rtsp-session.c
      β”‚       β”œβ”€β”€ rtsp-session.h
      β”‚       β”œβ”€β”€ rtsp-session-media.c
      β”‚       β”œβ”€β”€ rtsp-session-media.h
      β”‚       β”œβ”€β”€ rtsp-session-pool.c
      β”‚       β”œβ”€β”€ rtsp-session-pool.h
      β”‚       β”œβ”€β”€ rtsp-stream.c
      β”‚       β”œβ”€β”€ rtsp-stream.h
      β”‚       β”œβ”€β”€ rtsp-stream-transport.c
      β”‚       β”œβ”€β”€ rtsp-stream-transport.h
      β”‚       β”œβ”€β”€ rtsp-thread-pool.c
      β”‚       β”œβ”€β”€ rtsp-thread-pool.h
      β”‚       β”œβ”€β”€ rtsp-token.c
      β”‚       └── rtsp-token.h
      β”œβ”€β”€ rtsp-server-launch.c
      └── videos
      	β”œβ”€β”€ sample_video.ts

  • Happy coding!