GStreamer: как подключить динамические панели

Я пытаюсь использовать GStreamer для воспроизведения видео MP4 из файла. Мне удалось воспроизвести файл с помощью playbin2 и из командной строки, используя:

gst-launch filesrc location=bbb.mp4 ! decodebin2 ! autovideosink

Я ожидаю, что в будущем мне потребуется создавать более сложные конвейеры, и поэтому я пытаюсь «запрограммировать» конвейер. В своей программе я пытаюсь воспроизвести описанный выше конвейер, однако у меня есть проблема, которая, как я подозреваю, связана с подключением динамической или «иногда» исходной панели decodebin2 к автоприемнику видео. Я использую эти элементы только для того, чтобы все было как можно проще.

static void on_new_decoded_pad(GstElement* object,
                           GstPad* arg0,
                           gboolean arg1,
                           gpointer user_data)
{
    // dynamically connect decoderbin2 src pad to autovideosink sink pad
}

static gboolean bus_call (GstBus *bus, GstMessage *msg, gpointer data)
{
    // handle bus messages
}

int main(int argc, char *argv[])
{
    GMainLoop *loop;
    GstElement *pipeline, *source, *decodebin, *videosink;
    GstBus *bus;

    gst_init (&argc, &argv);
    loop = g_main_loop_new (NULL, FALSE);

    pipeline  = gst_pipeline_new ("pipeline");
    source    = gst_element_factory_make("filesrc",       "source");
    decodebin = gst_element_factory_make("decodebin2",    "decodebin");
    videosink = gst_element_factory_make("autovideosink", "videosink");

    /* check elements were created successfully */
    if (!pipeline || !source || !decodebin || !videosink) {
        // Failed to create element. Exit Program
        return -1;
    }

    /* apply properties to elements before adding to pipeline */
    gchar * filename = "bbb.mp4";
    g_object_set(G_OBJECT(source), "location", filename, NULL);

    /* add a message handler */
    bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
    gst_bus_add_watch (bus, bus_call, loop);
    gst_object_unref (bus);

    /* add elements to pipeline (and bin if necessary) before linking them */
    gst_bin_add_many(GST_BIN (pipeline),
                     source,
                     decodebin,
                     videosink,
                     NULL);

    gst_element_link_pads(source, "src", decodebin, "sink");

    /* decodebins src pad is a sometimes pad - it gets created dynamically */
    g_signal_connect(decodebin, "new-decoded-pad", G_CALLBACK(on_new_decoded_pad),   videosink);

    /* run pipeline */
    gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_PLAYING);

    g_main_loop_run(loop);

    gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_NULL);
    gst_object_unref (pipeline);

    return 0;
}

Когда я запускаю эту программу, я ожидаю, что on_new_decoded_pad будет вызван с помощью функции обратного вызова, которая задается в строке:

g_signal_connect(decodebin, "new-decoded-pad", G_CALLBACK(on_new_decoded_pad), videosink);

и позволит мне подключить контактные площадки соответствующим образом. Но его никогда не называют. На самом деле кажется, что программа проходит полностью, а затем просто завершается (основной цикл ничего не делает).

Я был бы очень признателен, если бы кто-нибудь мог указать, что я сделал не так в отношении обратного вызова, или объяснить, что еще нужно сделать, чтобы этот пример воспроизводил mp4 с использованием предоставленных элементов.

С уважением.

6
задан user975326 4 November 2011 в 19:05
поделиться