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): python - How to convert a video (on disk) to a rtsp stream - Stack Overflow

  • 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!

1 Like

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: GitHub - GStreamer/gst-rtsp-server: RTSP server based on GStreamer. This module has been merged into the main GStreamer repo for further development.

  • 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: gst-rtsp-server/test-launch.c at master Β· GStreamer/gst-rtsp-server Β· GitHub

      	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!