Limiting a RTSP recording after X seconds

Jesper Taxbøl jesper at taxboel.dk
Wed Dec 13 09:32:42 UTC 2017


2017-12-01 12:20 GMT+01:00 Jesper Taxbøl <jesper at taxboel.dk>:

> You guys are right. My solution is not safe.
>
> The signal works but the file is messed up in such a way that when
> transcoding the file gstreamer often stalls generating much larger files
> than the input. When running ffprobe against the file duration is strange.
>
> I was thinking that the problem was that the pipeline did not have time to
> close the file properly.
>
> Therefore I found the example from https://gstreamer.freedesktop.
> org/documentation/tutorials/basic/time-management.html.I could insert my
> configuration and piggyback on the message flow.
>
>
>
>
>
>
>
> *mpegtsmux ! filesink location=two.ts \  rtspsrc
> location=rtsp://root:hest1234@192.168.130.200/axis-media/media.amp
> <http://root:hest1234@192.168.130.200/axis-media/media.amp> ntp-sync=true
> protocols=GST_RTSP_LOWER_TRANS_TCP ! \  queue ! capsfilter
> caps=\"application/x-rtp,media=video\" ! \  rtph264depay ! mpegtsmux0. \
> rtspsrc location=rtsp://root:hest1234@192.168.130.201/axis-media/media.amp
> <http://root:hest1234@192.168.130.201/axis-media/media.amp> ntp-sync=true
> protocols=GST_RTSP_LOWER_TRANS_TCP ! \  queue ! capsfilter
> caps=\"application/x-rtp,media=video\" ! \  rtph264depay ! mpegtsmux0.*
>
> In the message handler I count timeouts and stop after a given time. Full
> source added below.
>
> The approach works as such, but it still gives me funny readings. ffprobe
> says:
>
> Invalid return value 0 for stream protocol
> Input #0, mpegts, from 'two.ts':
>   Duration: 00:00:11.95, start: 3600.698056, bitrate: 37229 kb/s
>   Program 1
>     Stream #0:0[0x41]: Video: h264 (High) (HDMV / 0x564D4448),
> yuvj420p(pc, bt709, progressive), 3840x2160 [SAR 1:1 DAR 16:9], 29.97 fps,
> 29.97 tbr, 90k tbn, 59.94 tbc
>     Stream #0:1[0x42]: Video: h264 (High) (HDMV / 0x564D4448),
> yuvj420p(pc, bt709, progressive), 3840x2160 [SAR 1:1 DAR 16:9], 29.97 fps,
> 29.97 tbr, 90k tbn, 59.94 tbc
>
> I notice that duration is somewhat plausible, but start is 3600, which I
> guess could be part of the problem.
>
> Any Ideas on how to fix time in my output file.
>
> Kind regards
>
> Jesper
>
>
>
>
> #include <stdio.h>
> #include <gst/gst.h>
>
> /* Structure to contain all our information, so we can pass it around */
> typedef struct _CustomData {
>   GstElement *playbin;  /* Our one and only element */
>   gboolean playing;      /* Are we in the PLAYING state? */
>   gboolean terminate;    /* Should we terminate execution? */
>   gboolean seek_enabled; /* Is seeking enabled for this media? */
>   gboolean seek_done;    /* Have we performed the seek already? */
>   gint64 duration;       /* How long does this media last, in nanoseconds
> */
> } CustomData;
>
> /* Forward definition of the message processing function */
> static void handle_message (CustomData *data, GstMessage *msg);
>
> int main(int argc, char *argv[]) {
>   CustomData data;
>   GstBus *bus;
>   GstMessage *msg;
>   GstStateChangeReturn ret;
>
>   data.playing = FALSE;
>   data.terminate = FALSE;
>   data.seek_enabled = FALSE;
>   data.seek_done = FALSE;
>   data.duration = GST_CLOCK_TIME_NONE;
>
>   /* Initialize GStreamer */
>   gst_init (&argc, &argv);
>
>   /* Create the elements */
>   //data.playbin = gst_element_factory_make ("playbin", "playbin");
>
>   char* cmd = "mpegtsmux ! filesink location=two.ts \
>   rtspsrc location=rtsp://root:hest1234@192.168.130.200/axis-media/
> media.amp ntp-sync=true protocols=GST_RTSP_LOWER_TRANS_TCP ! \
>   queue ! capsfilter caps=\"application/x-rtp,media=video\" ! \
>   rtph264depay ! mpegtsmux0. \
>   rtspsrc location=rtsp://root:hest1234@192.168.130.201/axis-media/
> media.amp ntp-sync=true protocols=GST_RTSP_LOWER_TRANS_TCP ! \
>   queue ! capsfilter caps=\"application/x-rtp,media=video\" ! \
>   rtph264depay ! mpegtsmux0.";
>   printf(cmd);
>   data.playbin = gst_parse_launch (cmd, NULL);
>
>
>   if (!data.playbin) {
>     g_printerr ("Not all elements could be created.\n");
>     return -1;
>   }
>
>   /* Set the URI to play */
>   //g_object_set (data.playbin, "uri", //"https://www.freedesktop.
> org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL);
>
>
>
>   /* Start playing */
>   ret = gst_element_set_state (data.playbin, GST_STATE_PLAYING);
>   if (ret == GST_STATE_CHANGE_FAILURE) {
>     g_printerr ("Unable to set the pipeline to the playing state.\n");
>     gst_object_unref (data.playbin);
>     return -1;
>   }
>
>   /* Listen to the bus */
>   bus = gst_element_get_bus (data.playbin);
>
>   int t = 0;
>
>   do {
>     msg = gst_bus_timed_pop_filtered (bus, 100 * GST_MSECOND,
>         GST_MESSAGE_STATE_CHANGED | GST_MESSAGE_ERROR | GST_MESSAGE_EOS |
> GST_MESSAGE_DURATION);
>
>     printf("Tick: \r\n%d\r\n", t++);
>     if(t == 200)
>     {
>       gst_element_send_event (GST_ELEMENT (data.playbin),
> gst_event_new_eos());
>     }
>
>     /* Parse message */
>     if (msg != NULL) {
>       handle_message (&data, msg);
>     } else {
>
>       /* We got no message, this means the timeout expired */
>       if (data.playing) {
>         gint64 current = -1;
>
>         /* Query the current position of the stream */
>         if (!gst_element_query_position (data.playbin, GST_FORMAT_TIME,
> &current)) {
>           g_printerr ("Could not query current position.\n");
>         }
>
>         /* If we didn't know it yet, query the stream duration */
>         if (!GST_CLOCK_TIME_IS_VALID (data.duration)) {
>           if (!gst_element_query_duration (data.playbin, GST_FORMAT_TIME,
> &data.duration)) {
>             g_printerr ("Could not query current duration.\n");
>           }
>         }
>
>         /* Print current position and total duration */
>         g_print ("Position %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT "\r",
>             GST_TIME_ARGS (current), GST_TIME_ARGS (data.duration));
>
>         /* If seeking is enabled, we have not done it yet, and the time is
> right, seek */
>         if (data.seek_enabled && !data.seek_done && current > 10 *
> GST_SECOND) {
>           g_print ("\nReached 10s, performing seek...\n");
>           gst_element_seek_simple (data.playbin, GST_FORMAT_TIME,
>               GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT, 30 *
> GST_SECOND);
>           data.seek_done = TRUE;
>         }
>       }
>     }
>   } while (!data.terminate);
>
>   /* Free resources */
>   gst_object_unref (bus);
>   gst_element_set_state (data.playbin, GST_STATE_NULL);
>   gst_object_unref (data.playbin);
>   return 0;
> }
>
> static void handle_message (CustomData *data, GstMessage *msg) {
>   GError *err;
>   gchar *debug_info;
>
>   switch (GST_MESSAGE_TYPE (msg)) {
>     case GST_MESSAGE_ERROR:
>       gst_message_parse_error (msg, &err, &debug_info);
>       g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME
> (msg->src), err->message);
>       g_printerr ("Debugging information: %s\n", debug_info ? debug_info :
> "none");
>       g_clear_error (&err);
>       g_free (debug_info);
>       data->terminate = TRUE;
>       break;
>     case GST_MESSAGE_EOS:
>       g_print ("End-Of-Stream reached.\n");
>       data->terminate = TRUE;
>       break;
>     case GST_MESSAGE_DURATION:
>       /* The duration has changed, mark the current one as invalid */
>       printf("...\r\n");
>       data->duration = GST_CLOCK_TIME_NONE;
>       break;
>     case GST_MESSAGE_STATE_CHANGED: {
>       GstState old_state, new_state, pending_state;
>       gst_message_parse_state_changed (msg, &old_state, &new_state,
> &pending_state);
>       if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data->playbin)) {
>         g_print ("Pipeline state changed from %s to %s:\n",
>             gst_element_state_get_name (old_state),
> gst_element_state_get_name (new_state));
>
>         /* Remember whether we are in the PLAYING state or not */
>         data->playing = (new_state == GST_STATE_PLAYING);
>
>         if (data->playing) {
>           /* We just moved to PLAYING. Check if seeking is possible */
>           GstQuery *query;
>           gint64 start, end;
>           query = gst_query_new_seeking (GST_FORMAT_TIME);
>           if (gst_element_query (data->playbin, query)) {
>             gst_query_parse_seeking (query, NULL, &data->seek_enabled,
> &start, &end);
>             if (data->seek_enabled) {
>               g_print ("Seeking is ENABLED from %" GST_TIME_FORMAT " to %"
> GST_TIME_FORMAT "\n",
>                   GST_TIME_ARGS (start), GST_TIME_ARGS (end));
>             } else {
>               g_print ("Seeking is DISABLED for this stream.\n");
>             }
>           }
>           else {
>             g_printerr ("Seeking query failed.");
>           }
>           gst_query_unref (query);
>         }
>       }
>     } break;
>     default:
>       /* We should not reach here */
>       g_printerr ("Unexpected message received.\n");
>       break;
>   }
>   gst_message_unref (msg);
> }
>
>
>
>
>
> 2017-11-30 11:40 GMT+01:00 Tim Müller <tim at centricular.com>:
>
>> On Thu, 2017-11-30 at 10:22 +0100, Jesper Taxbøl wrote:
>>
>> > I spent some time today and figured out i can use use the following
>> > syntax in my makefile. Its actually the terminal sending a signal to
>> > kill the process.
>>
>> That'll work of course, but the file won't be finalised properly, so
>> the headers won't be updated with the duration and there won't be a
>> seektable and you might be missing the last few frames/seconds.
>>
>> Cheers
>> -Tim
>>
>> --
>> Tim Müller, Centricular Ltd - http://www.centricular.com
>> _______________________________________________
>> gstreamer-devel mailing list
>> gstreamer-devel at lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
>>
>
>
>
> --
> Jesper Taxbøl
> +45 61627501 <+45%2061%2062%2075%2001>
>
>
I ended up taking the recording into a ffmpeg program I have been working
on, and I could read PTS on every frame there. I wrote a simple mechanism
to repeat frames if the frames are out of sync and that seems to work for
now.

I am still interrested though if it was possible to offset PTS to start
from zero in gstreamer with existing modules.

Kind regards


-- 
Jesper Taxbøl
+45 61627501
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/gstreamer-devel/attachments/20171213/25825127/attachment-0001.html>


More information about the gstreamer-devel mailing list