DVB Remux
Bernhard Graaf
bernhard.graaf at gmx.de
Fri Jan 30 11:34:52 PST 2015
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.
More information about the gstreamer-devel
mailing list