I am recording two a RTSP camera sources using this command gst-launch 1.0 -e 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. I am used to FFmpeg, where its exposed as a -t argument. Any ideas on how to proceed. Preferably by example. Kind regards Jesper
_______________________________________________ gstreamer-devel mailing list [hidden email] https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel |
On Wed, 2017-11-29 at 09:05 +0100, Jesper Taxbøl wrote:
Hi Jesper, > I would like to stop the recording after 10 seconds so I can > integrate the command in a Makefile, but cant seem to get my head > around how. Theoretically this should do it: gst_element_send_event (GST_ELEMENT (pipeline), gst_event_new_eos()); + wait for GST_MESSAGE_EOS on bus. In practice, I seem to remember that there was an issue in rtpjitterbuffer where it would sometimes 'eat' the EOS event. I don't remember if that was fixed or not. Try it :) Cheers -Tim -- Tim Müller, Centricular Ltd - http://www.centricular.com _______________________________________________ gstreamer-devel mailing list [hidden email] https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel |
On Wed, 2017-11-29 at 20:57 +0000, Tim Müller wrote:
> > I would like to stop the recording after 10 seconds so I can > > integrate the command in a Makefile, but cant seem to get my head > > around how. And I completely missed the second part which indicates that you want to use gst-launch for this. There is no easy way to do this with gst- launch currently, as far as I know. Write a little app/script around gst_parse_launch(). Cheers -Tim -- Tim Müller, Centricular Ltd - http://www.centricular.com _______________________________________________ gstreamer-devel mailing list [hidden email] https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel |
Hi 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. two.mkv: gst-launch-1.0 -ev \ matroskamux name=mux ! filesink location=two.mkv \ rtspsrc location=$(URLA) $(RTSPSRC_SETTINGS) ! \ queue ! capsfilter caps="application/x-rtp,media=video" ! \ rtph264depay ! h264parse ! mux.video_0 \ rtspsrc location=$(URLB) $(RTSPSRC_SETTINGS) ! \ queue ! capsfilter caps="application/x-rtp,media=video" ! \ rtph264depay ! h264parse ! mux.video_1 & sleep 1800; kill -INT $$! kind regards jesper On Nov 29, 2017 21:58, "Tim Müller" <[hidden email]> wrote: On Wed, 2017-11-29 at 20:57 +0000, Tim Müller wrote: _______________________________________________ gstreamer-devel mailing list [hidden email] https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel |
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 [hidden email] https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel |
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 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. 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 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, ¤t)) { 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 <[hidden email]>: On Thu, 2017-11-30 at 10:22 +0100, Jesper Taxbøl wrote: -- Jesper Taxbøl
+45 61627501 _______________________________________________ gstreamer-devel mailing list [hidden email] https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel |
2017-12-01 12:20 GMT+01:00 Jesper Taxbøl <[hidden email]>:
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 _______________________________________________ gstreamer-devel mailing list [hidden email] https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel |
Free forum by Nabble | Edit this page |