DVB Remux

Jan Schmidt thaytan at noraisin.net
Fri Jan 30 19:09:11 PST 2015


Hi Bernhard,

As a general rule, whenever you have a demuxer you also need a queue (or 
use multiqueue) on the output of each demuxer pad to decouple the 
streams, or your pipeline will stall exactly like you are seeing.

Regards,
Jan.

On 31/01/15 06:34, Bernhard Graaf wrote:
> I've tried to use following code:
>
> #include <stdio.h>
> #include <unistd.h>
> #include <string.h>
> #include <gst/gst.h>
> #include <glib.h>
>
>
> GstElement *pipeline;
> GstElement *parser, *parser2;
>
> static gboolean
> bus_call (GstBus     *bus,
>            GstMessage *msg,
>            gpointer    data)
> {
>    GMainLoop *loop = (GMainLoop *) data;
>
>    switch (GST_MESSAGE_TYPE (msg)) {
>
>      case GST_MESSAGE_EOS:
>        g_print ("End of stream\n");
>        g_main_loop_quit (loop);
>        break;
>
>      case GST_MESSAGE_ERROR: {
>        gchar  *debug;
>        GError *error;
>
>        gst_message_parse_error (msg, &error, &debug);
>        g_free (debug);
>
>        g_printerr ("Error: %s\n", error->message);
>        g_error_free (error);
>
>        g_main_loop_quit (loop);
>        break;
>      }
> /*    case GST_MESSAGE_ELEMENT:
>      {
>        const GstStructure *str;
>
>        str = gst_message_get_structure (msg);
>        const gchar *name = gst_structure_get_name (str);
>
>        printf("got message from %s\n", name);
>      } */
>      default:
>        break;
>    }
>
>    return TRUE;
> }
>
>
> void link_to_mux (GstPad *tolink_pad,  GstElement *mux)
> {
>    GstPad *pad;
>    gchar *srcname, *sinkname;
>
>    srcname = gst_pad_get_name (tolink_pad);
>    pad = gst_element_get_compatible_pad (mux, tolink_pad, NULL);
>    gst_pad_link (tolink_pad, pad);
>    sinkname = gst_pad_get_name (pad);
>    if (GST_PAD_IS_LINKED (pad)) g_print ("A new pad %s was created and linked
> to %s\n", srcname, sinkname);
>    else g_print("Link failed: %s to %s\n",srcname, sinkname);
>    gst_object_unref (GST_OBJECT (pad));
>
>
>    g_free (sinkname);
>    g_free (srcname);
> }
>
> void on_pad_added (GstElement *element,
>                GstPad     *pad,
>                gpointer    data)
> {
>    GstElement *mux = (GstElement *) data;
>    GstCaps *caps;
>    gchar *caps_string;
>    gchar *name;
>
>    GstPad *to_link_pad, *from_link_pad;
>
>    name = gst_pad_get_name (pad);
>    printf("A new pad %s was created\n", name);
>
>    caps = gst_pad_query_caps (pad, NULL);
>    caps_string = gst_caps_to_string (caps);
>    g_print (" Capability:  %s\n", caps_string);
>
>    if (strstr(caps_string, "video/mpeg"))
>    {
>      parser = gst_element_factory_make ("mpegvideoparse",  NULL);
>      if(!parser)
>      {
>        g_print("Parser not found\n");
>        exit (-1);
>      }
>      gst_bin_add (GST_BIN (pipeline), parser);
>      gst_element_set_state (parser, GST_STATE_PLAYING);
>      to_link_pad = gst_element_get_static_pad (parser, "sink");
>      from_link_pad = gst_element_get_static_pad (parser, "src");
>      gst_pad_link (pad, to_link_pad);
>      link_to_mux(from_link_pad, mux);
>      gst_object_unref (GST_OBJECT (to_link_pad));
>      gst_object_unref (GST_OBJECT (from_link_pad));
>    }
>    else if (strstr(caps_string, "audio/mpeg"))
>    {
>      parser2 = gst_element_factory_make ("mpegaudioparse",  NULL);
>      if(!parser2)
>      {
>        g_print("Parser2 not found\n");
>        exit (-1);
>      }
>      gst_bin_add (GST_BIN (pipeline), parser2);
>      gst_element_set_state (parser2, GST_STATE_PLAYING);
>      to_link_pad = gst_element_get_static_pad (parser2, "sink");
>      from_link_pad = gst_element_get_static_pad (parser2, "src");
>      gst_pad_link (pad, to_link_pad);
>      link_to_mux(from_link_pad, mux);
>      gst_object_unref (GST_OBJECT (to_link_pad));
>      gst_object_unref (GST_OBJECT (from_link_pad));
>    }
>
>
>    gst_caps_unref (caps);
>    g_free (name);
>    g_free (caps_string);
>
> }
>
>
> void no_more_pads (GstElement* object, gpointer user_data)
> {
>    g_print("No more pads event from %s\n", gst_element_get_name(object));
> }
>
> int
> main ()
> {
>    GMainLoop *loop;
>
>    GstElement *source, *demux, *mux, *sink;
>    GstBus *bus;
>
>    gst_init (0, NULL);
>
>    loop = g_main_loop_new (NULL, FALSE);
>
>    pipeline = gst_pipeline_new ("DVB-Filesave");
>    source   = gst_element_factory_make ("dvbbasebin",  "dvb-source");
>    demux    = gst_element_factory_make ("tsdemux",     "dvb-demux");
>    mux	   = gst_element_factory_make ("mpegtsmux",   "dvb-mux");
>    sink     = gst_element_factory_make ("filesink", "file-output");
>
>    if (!pipeline || !source || !demux || !mux || !sink) {
>      g_printerr ("One element could not be created. Exiting.\n");
>      if(!pipeline) g_printerr("Pipeline not created\n");
>      else if(!source) g_printerr("Source not created\n");
>      else if(!demux) g_printerr("Demux not created\n");
>      else if(!mux) g_printerr("Muxer not created\n");
>      else if(!sink) g_printerr("Sink not created\n");
>      return -1;
>    }
>
>    g_object_set (G_OBJECT (source), "adapter", 2, NULL);
>    g_object_set (G_OBJECT (source), "frequency", 12544000, NULL);
>    g_object_set (G_OBJECT (source), "program-numbers", "17501", NULL);
>    g_object_set (G_OBJECT (source), "polarity", "h", NULL);
>    g_object_set (G_OBJECT (source), "symbol-rate", 22000, NULL);
>
>    g_object_set (G_OBJECT (sink), "location", "remux_test.mpg", NULL);
>
>    bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
>    gst_bus_add_watch (bus, bus_call, loop);
>    gst_object_unref (bus);
>
>    gst_bin_add_many (GST_BIN (pipeline), source, demux, mux, sink, NULL);
>
>    gst_element_link (source, demux);
>    gst_element_link (mux, sink);
>
>    g_signal_connect (demux, "pad-added", G_CALLBACK (on_pad_added), mux);
>    g_signal_connect (demux, "no-more-pads", G_CALLBACK (on_pad_added), NULL);
>
>
>
>    g_print ("Now playing: ");
>    gst_element_set_state (pipeline, GST_STATE_PLAYING);
>
>    g_print ("Running...\n");
>    g_main_loop_run (loop);
>
>    return 0;
> }
>
> But the pipeline hangs on this:
> <snipe>
> 0:00:00.760394705 18570       0xb0d8a0 INFO        GST_ELEMENT_PADS
> gstelement.c:643:gst_element_add_pad:<dvb-mux> adding pad 'sink_65'
> 0:00:00.760454365 18570       0xb0d8a0 INFO                GST_PADS
> gstpad.c:2186:gst_pad_link_prepare: trying to link mpegvparse0:src and
> dvb-mux:sink_65
> 0:00:00.760506215 18570       0xb0d8a0 INFO                GST_PADS
> gstpad.c:2388:gst_pad_link_full: linked mpegvparse0:src and dvb-mux:sink_65,
> successful
> 0:00:00.760534970 18570       0xb0d8a0 INFO               GST_EVENT
> gstevent.c:1373:gst_event_new_reconfigure: creating reconfigure event
> A new pad src was created and linked to sink_65
> 0:00:00.760658475 18570       0xb0d8a0 INFO               GST_EVENT
> gstevent.c:759:gst_event_new_segment: creating segment event time segment
> start=0:00:00.000000000, offset=0:00:00.000000000, stop=99:99:99.999999999,
> rate=1.000000, applied_rate=1.000000, flags=0x00, time=0:00:00.000000000,
> base=0:00:00.000000000, position 0:00:00.000000000, duration
> 99:99:99.999999999
> 0:00:00.760934626 18570       0xb0d8a0 INFO        GST_ELEMENT_PADS
> gstelement.c:643:gst_element_add_pad:<dvb-demux> adding pad 'private_0021'
> A new pad private_0021 was created
>   Capability:  application/x-teletext
> 0:00:00.788089961 18570       0xb0d850 INFO               GST_EVENT
> gstevent.c:678:gst_event_new_caps: creating caps event video/mpegts,
> mpegversion=(int)2, systemstream=(boolean)true
> 0:00:00.877835322 18570       0xb0d8a0 INFO        GST_ELEMENT_PADS
> gstelement.c:643:gst_element_add_pad:<dvb-demux> adding pad 'audio_0203'
> A new pad audio_0203 was created
>   Capability:  audio/x-ac3
> 0:00:00.878095442 18570       0xb0d8a0 INFO        GST_ELEMENT_PADS
> gstelement.c:643:gst_element_add_pad:<dvb-demux> adding pad 'audio_0200'
> A new pad audio_0200 was created
>   Capability:  audio/mpeg, mpegversion=(int)1
> 0:00:00.878752238 18570       0xb0d8a0 INFO      GST_PLUGIN_LOADING
> gstplugin.c:833:gst_plugin_load_file: plugin
> "/usr/local/lib/gstreamer-1.0/libgstaudioparsers.so" loaded
> 0:00:00.878804593 18570       0xb0d8a0 INFO     GST_ELEMENT_FACTORY
> gstelementfactory.c:364:gst_element_factory_create: creating element
> "mpegaudioparse"
> 0:00:00.879019978 18570       0xb0d8a0 INFO        GST_ELEMENT_PADS
> gstelement.c:643:gst_element_add_pad:<GstBaseParse at 0x7f3604179660> adding
> pad 'sink'
> 0:00:00.879085838 18570       0xb0d8a0 INFO        GST_ELEMENT_PADS
> gstelement.c:643:gst_element_add_pad:<GstBaseParse at 0x7f3604179660> adding
> pad 'src'
> 0:00:00.879169348 18570       0xb0d8a0 INFO              GST_STATES
> gstelement.c:2303:gst_element_continue_state:<mpegaudioparse0> committing
> state from NULL to READY, pending PLAYING, next PAUSED
> 0:00:00.879212453 18570       0xb0d8a0 INFO              GST_STATES
> gstelement.c:2233:_priv_gst_element_state_changed:<mpegaudioparse0>
> notifying about state-changed NULL to READY (PLAYING pending)
> 0:00:00.879259623 18570       0xb0d8a0 INFO              GST_STATES
> gstelement.c:2310:gst_element_continue_state:<mpegaudioparse0> continue
> state change READY to PAUSED, final PLAYING
> 0:00:00.879340888 18570       0xb0d8a0 INFO                GST_PADS
> gstpad.c:3748:gst_pad_peer_query:<mpegaudioparse0:sink> pad has no peer
> 0:00:00.879379959 18570       0xb0d8a0 INFO              GST_STATES
> gstelement.c:2303:gst_element_continue_state:<mpegaudioparse0> committing
> state from READY to PAUSED, pending PLAYING, next PLAYING
> 0:00:00.879409529 18570       0xb0d8a0 INFO              GST_STATES
> gstelement.c:2233:_priv_gst_element_state_changed:<mpegaudioparse0>
> notifying about state-changed READY to PAUSED (PLAYING pending)
> 0:00:00.879450104 18570       0xb0d8a0 INFO              GST_STATES
> gstelement.c:2310:gst_element_continue_state:<mpegaudioparse0> continue
> state change PAUSED to PLAYING, final PLAYING
> 0:00:00.879480739 18570       0xb0d8a0 INFO              GST_STATES
> gstelement.c:2328:gst_element_continue_state:<mpegaudioparse0> completed
> state change to PLAYING
> 0:00:00.879504654 18570       0xb0d8a0 INFO              GST_STATES
> gstelement.c:2233:_priv_gst_element_state_changed:<mpegaudioparse0>
> notifying about state-changed PAUSED to PLAYING (VOID_PENDING pending)
> 0:00:00.879556579 18570       0xb0d8a0 INFO        GST_ELEMENT_PADS
> gstelement.c:895:gst_element_get_static_pad: found pad mpegaudioparse0:sink
> 0:00:00.879586924 18570       0xb0d8a0 INFO        GST_ELEMENT_PADS
> gstelement.c:895:gst_element_get_static_pad: found pad mpegaudioparse0:src
> 0:00:00.879622269 18570       0xb0d8a0 INFO                GST_PADS
> gstpad.c:2186:gst_pad_link_prepare: trying to link dvb-demux:audio_0200 and
> mpegaudioparse0:sink
> 0:00:00.879671664 18570       0xb0d8a0 INFO                GST_PADS
> gstpad.c:3748:gst_pad_peer_query:<mpegaudioparse0:src> pad has no peer
> 0:00:00.879711444 18570       0xb0d8a0 INFO                GST_PADS
> gstpad.c:2388:gst_pad_link_full: linked dvb-demux:audio_0200 and
> mpegaudioparse0:sink, successful
> 0:00:00.879745204 18570       0xb0d8a0 INFO               GST_EVENT
> gstevent.c:1373:gst_event_new_reconfigure: creating reconfigure event
> 0:00:00.879894009 18570       0xb0d8a0 INFO        GST_ELEMENT_PADS
> gstelement.c:643:gst_element_add_pad:<dvb-mux> adding pad 'sink_66'
> 0:00:00.879950774 18570       0xb0d8a0 INFO                GST_PADS
> gstpad.c:2186:gst_pad_link_prepare: trying to link mpegaudioparse0:src and
> dvb-mux:sink_66
> 0:00:00.880001239 18570       0xb0d8a0 INFO                GST_PADS
> gstpad.c:2388:gst_pad_link_full: linked mpegaudioparse0:src and
> dvb-mux:sink_66, successful
> 0:00:00.880032749 18570       0xb0d8a0 INFO               GST_EVENT
> gstevent.c:1373:gst_event_new_reconfigure: creating reconfigure event
> A new pad src was created and linked to sink_66
>
> (remux_test:18570): GStreamer-CRITICAL **: gst_object_get_name: assertion
> 'GST_IS_OBJECT (object)' failed
> A new pad (null) was created
>
> (remux_test:18570): GStreamer-CRITICAL **: gst_pad_query_caps: assertion
> 'GST_IS_PAD (pad)' failed
>   Capability:  NULL
>
> (remux_test:18570): GStreamer-CRITICAL **: gst_mini_object_unref: assertion
> 'mini_object != NULL' failed
> 0:00:00.880440385 18570       0xb0d8a0 INFO               GST_EVENT
> gstevent.c:678:gst_event_new_caps: creating caps event audio/mpeg,
> mpegversion=(int)1, mpegaudioversion=(int)1, layer=(int)2, rate=(int)48000,
> channels=(int)2, parsed=(boolean)true
> 0:00:00.907704596 18570       0xb0d850 INFO               GST_EVENT
> gstevent.c:678:gst_event_new_caps: creating caps event video/mpegts,
> mpegversion=(int)2, systemstream=(boolean)true
>
> I know there is a smarter way with typefind, but I need only the
> mpegvideo/mpegaudio-streams.
>
> But why the pipline hangs on this, I don't know.
> Any further idea?
>
> Thanks again!
> Bernhard
>
> -----Ursprüngliche Nachricht-----
> Von: gstreamer-devel [mailto:gstreamer-devel-bounces at lists.freedesktop.org]
> Im Auftrag von Jan Schmidt
> Gesendet: Freitag, 30. Januar 2015 15:11
> An: Discussion of the development of and with GStreamer
> Betreff: Re: DVB Remux
>
> On 30/01/15 23:52, Bernhard Graaf wrote:
>
> Hi Bernhard,
>
> In general for this kind of operation, you need a parser for each stream
> before connecting to the muxer. i.e.  h264parse, mpegvideoparse,
> mpegaudioparse etc.
>
> You'll need to do some autoplugging and find the right parsers, unless
> you known which formats are in your DVB stream and can hard-code them.
>
> - Jan.
>
>
> _______________________________________________
> gstreamer-devel mailing list
> gstreamer-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
>


More information about the gstreamer-devel mailing list