demux/remux pipeline hangs when audio is added

Carah Smith carah29ingress at gmail.com
Wed Oct 2 10:19:19 PDT 2013


Hi,
I am trying to make a pipeline that takes a transport stream in, demuxes
it, does some transcoding, remuxes, and sends it to a sink.
I can make it work if I only have video in the pipeline or if I only have
audio but once I add both, the application hangs. Here is my source code (I
removed all the error checking for emailing to reduce line length):

struct custom_data
{
    GstElement *video_decoder;
    GstElement *audio_decoder;
};

void
link_to_multiplexer(
    GstElement *tolink_element,
    GstElement *mux)
{
    GstCaps          *pad_caps = NULL;
    GstPad           *pad;
    GstPad           *tolink_pad;
    GstPadLinkReturn  ret;

    tolink_pad = gst_element_get_static_pad(tolink_element, "src");
    pad_caps   = gst_pad_query_caps(tolink_pad, NULL);
    pad        = gst_element_get_compatible_pad(mux, tolink_pad, pad_caps);
    gst_caps_unref(pad_caps);

    ret = gst_pad_link(tolink_pad, pad);
    gst_object_unref(GST_OBJECT(pad));
    g_print("A new pad %s was created and linked to %s\n",
gst_pad_get_name(tolink_pad), gst_pad_get_name(pad));
}

static void on_pad_added(
    GstElement *src,
    GstPad *new_pad,
    struct custom_data *data)
{
    GstCaps          *new_pad_caps = NULL;
    GstStructure     *new_pad_struct = NULL;
    const gchar      *new_pad_type = NULL;
    GstPad           *decode_pad = NULL;
    GstPadLinkReturn  ret;

    g_print("Received new pad '%s' from '%s':\n", GST_PAD_NAME(new_pad),
            GST_ELEMENT_NAME(src));

    /* Check the new pad's type */
    new_pad_caps   = gst_pad_query_caps(new_pad, NULL);
    new_pad_struct = gst_caps_get_structure(new_pad_caps, 0);
    new_pad_type   = gst_structure_get_name(new_pad_struct);

    g_print("New pad type is %s\n", new_pad_type);
    if (g_str_has_prefix(new_pad_type, "video/mpeg"))
    {
        decode_pad = gst_element_get_static_pad(data->video_decoder,
"sink");
    }
    else if (g_str_has_prefix(new_pad_type, "audio/x-ac3"))
    {
        decode_pad = gst_element_get_static_pad(data->audio_decoder,
"sink");
    }
    if (!gst_pad_is_linked(decode_pad))
    {
        ret = gst_pad_link(new_pad, decode_pad);
    }

    gst_caps_unref(new_pad_caps);
    gst_object_unref(decode_pad);
}

int
main(int argc, char **argv)
{
    GstElement *source;
    GstElement *pipeline;
    GstElement *sink;
    GstElement *demux;
    GstElement *mux;
    GstElement *v_dec;
    GstElement *x264_enc;
    GstElement *a_dec;
    GstElement *a_convert;
    GstElement *aac_enc;
    struct custom_data data;

    GstBus     *bus;
    GstMessage *msg;
    gboolean terminate = FALSE;

    gst_init (&argc, &argv);

    source    = gst_element_factory_make("filesrc", "file-source");
    demux     = gst_element_factory_make("tsdemux", "demux");
    v_dec     = gst_element_factory_make("mpeg2dec", "video_decoder");
    x264_enc  = gst_element_factory_make("x264enc", "h264_encoder");
    a_dec     = gst_element_factory_make("a52dec", "audio_decoder");
    a_convert = gst_element_factory_make("audioconvert", "audio_converter");
    aac_enc   = gst_element_factory_make("faac", "aac_encoder");
    mux       = gst_element_factory_make("mpegtsmux", "muxer");
    sink      = gst_element_factory_make("hlssink", "hls_sink");

    data.video_decoder = v_dec;
    data.audio_decoder = a_dec;

    pipeline = gst_pipeline_new("test-pipeline");

    g_object_set(G_OBJECT(source), "location", "stream_1.ts", NULL);

    gst_bin_add_many(GST_BIN(pipeline), source, demux, x264_enc, v_dec,
a_dec, aac_enc, a_convert, mux, sink, NULL);

    gst_element_link(source, demux);
    gst_element_link_many(a_dec, a_convert, aac_enc, NULL);
    link_to_multiplexer(x264_enc, mux);
    link_to_multiplexer(aac_enc, mux);

    gst_element_link(v_dec, x264_enc);
    gst_element_link(mux, sink);

    g_signal_connect(demux, "pad-added", G_CALLBACK(on_pad_added), &data);

    gst_element_set_state(pipeline, GST_STATE_PLAYING);

    /* Listen to the bus */
    bus = gst_element_get_bus(pipeline);
    do
    {
        msg = gst_bus_timed_pop(bus, 0);

        /* Parse message */
        if (msg != NULL)
        {
            switch (GST_MESSAGE_TYPE(msg))
            {
                case GST_MESSAGE_ERROR:
                case GST_MESSAGE_EOS:
                    terminate = TRUE;
                    break;
                case GST_MESSAGE_STATE_CHANGED:
                    if (GST_MESSAGE_SRC(msg) == GST_OBJECT(pipeline))
                    {
                        GstState old_state, new_state, pending_state;

                        gst_message_parse_state_changed(msg, &old_state,
&new_state, &pending_state);
                        g_print("Pipeline state changed from %s to %s:\n",
                        gst_element_state_get_name(old_state),
gst_element_state_get_name(new_state));
                    }
                    break;
                default:
                g_printerr("New bus message: %s.\n",
gst_message_type_get_name(GST_MESSAGE_TYPE(msg)));
                break;
            }
            gst_message_unref(msg);
        }
    } while (!terminate);

    /* Free resources */
    gst_object_unref(bus);
    gst_element_set_state(pipeline, GST_STATE_NULL);
    gst_object_unref(pipeline);

    return 0;
}

Here is my output when it hangs:

A new pad src was created and linked to sink_65
A new pad src was created and linked to sink_66
Pipeline state changed from NULL to READY:
New bus message: stream-status.
New bus message: stream-status.
New bus message: element.
New bus message: element.
Received new pad 'video_01e1' from 'demux':
New pad type is video/mpeg
New bus message: latency.
New bus message: qos.
New bus message: qos.
New bus message: latency.
Received new pad 'audio_01e2' from 'demux':
New pad type is audio/x-ac3
New bus message: tag.
(Hangs here)

Here is my output if I detach the audio from the muxer and only let the
video flow all the way through:

A new pad src was created and linked to sink_65
Pipeline state changed from NULL to READY:
New bus message: stream-status.
New bus message: stream-status.
New bus message: element.
New bus message: element.
Received new pad 'video_01e1' from 'demux':
New pad type is video/mpeg
New bus message: latency.
New bus message: qos.
New bus message: qos.
New bus message: latency.
Received new pad 'audio_01e2' from 'demux':
New pad type is audio/x-ac3
Received new pad 'audio_01e3' from 'demux':
New pad type is audio/x-ac3
Pad is already linked.
New bus message: tag.
New bus message: stream-start.
Pipeline state changed from READY to PAUSED:
New bus message: async-done.
New bus message: new-clock.
Pipeline state changed from PAUSED to PLAYING:
(Program reads whole transport stream and successfully completes)

Could please help me determine why adding the audio to the muxer causes the
program to hang?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/gstreamer-devel/attachments/20131002/d23fb434/attachment-0001.html>


More information about the gstreamer-devel mailing list