interdependently seeking of multible filesources in pipeline

Nicolas Dufresne nicolas at ndufresne.ca
Sun Dec 17 18:41:15 UTC 2017


Le 17 déc. 2017 11:44 AM, <spam at feuerundbenzin.tk> a écrit :

Hello,

I want to create a lite sampler application. Where you can play,stop,loop
multiple sound files.
im currently experimenting with gstreamer and stuck on some point.

this is how my application currently look like:

pipeline:
bin1: filesource1 -> decoder1 -> converter1 ---\
|-> audiomixer -> alsasink
bin2: filesource2 -> decoder2 -> converter2  ---/

i have an audiomixer connected with to file sources. how can i seek the 2
sources interdependently ?
I can seek the whole pipeline, but seeking the filesources don't work (see
function play_button_CB in src).

can anybody help ?


For now, your only "easy" option would be to use GStreamer Editing
Services, a library designed on top of GStreamer to implement non-linear
audio/video editing applications. Second possibility would be to use it's
helper plugins, NLE. The hard way is to implement something similar to NLE,
though that requires strong GStreamer dynamic coding skills, it's not for
everyone.


Thanks Richard


-----------------------------------------------
#include <gst/gst.h>
#include <gst/gstelement.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

#include <glib.h>
#define FALSE (0)
#define TRUE (!FALSE)

#include <gtk/gtk.h>

typedef struct
{
    GstElement *pipeline;

    GstElement *file_source;
    GstElement *audio_decoder;
    GstElement *audioconvert;
    GstElement *bin_playback;

    GstElement *file_source2;
    GstElement *audio_decoder2;
    GstElement *audioconvert2;
    GstElement *bin_playback2;

    GstElement *audio_mixer;
    GstElement *alsasink;

    GstElement *visual;
    GstElement *tee;


    GstBus *bus;
    GstMessage *message;

    gchar filelocation[2000];
}playerData;

playerData gstreamerPlayer;


typedef struct
{
    GtkWidget *mainWindow;
    GtkWidget *play_button;

}guiData;

guiData guiElements;

/*
void on_pad_added2 (GstElement *src_element, GstPad *src_pad, gpointer data)
{
    g_print ("\nLinking dynamic pad between wavparse and alsasink\n");

    GstElement *sink_element = (GstElement *) data;     // Is alsasink
    GstPad *sink_pad = gst_element_get_static_pad (sink_element, "sink");
    gst_pad_link (src_pad, sink_pad);

    gst_object_unref (sink_pad);
    src_element = NULL;     // Prevent "unused" warning here
}
*/

gboolean player_Create(playerData *data)
{
    data->pipeline = gst_pipeline_new("audio_pipeline");

    if (data->pipeline == NULL)    return FALSE;
    gst_element_set_state (data->pipeline, GST_STATE_NULL);

    data->alsasink = gst_element_factory_make("alsasink", "audiosink");
    data->audio_mixer = gst_element_factory_make("audiomixer","audiomixer");

    if ( !data->pipeline || !data->alsasink || !data->audio_mixer)    {
        g_printerr ("\nNot all elements for audio pipeline were created\n");
        return FALSE;
    }


    gst_bin_add_many(GST_BIN (data->pipeline),
data->audio_mixer,data->alsasink,NULL);


    if (gst_element_link_many (data->audio_mixer, data->alsasink, NULL) !=
TRUE) {
        g_printerr("\nAudio mixer and audio sink element could not link\n");
        return FALSE;
    }


}


gboolean player_Add(playerData *data)
{
    data->bin_playback = gst_bin_new ("bin_playback");
    data->bin_playback2 = gst_bin_new ("bin_playback2");




    data->file_source = gst_element_factory_make("filesrc", "filesource");
    data->audioconvert = gst_element_factory_make("audioconvert",
"audioconverter");

    data->file_source2 = gst_element_factory_make("filesrc", "filesource2");
    data->audioconvert2 = gst_element_factory_make("audioconvert",
"audioconverter2");





    if ( !data->file_source || !data->audioconvert)    {
        g_printerr ("\nNot all elements for audio pipeline were created\n");
        return FALSE;
    }

    if ( !data->file_source2 || !data->audioconvert2)    {
        g_printerr ("\nNot all elements for audio pipeline were created\n");
        return FALSE;
    }



    g_object_set (G_OBJECT (data->file_source), "location",
"/home/admin2/Downloads/SampleAudio_0.4mb.mp3", NULL);

    g_object_set (G_OBJECT (data->file_source2), "location",
"/home/admin2/Downloads/SampleAudio_0.7mb.mp3", NULL);



    data->audio_decoder = gst_element_factory_make("mad",
"audiomp3decoder");
    if ( !data->audio_decoder)    {
        g_printerr ("\nNot all elements for audio pipeline were created\n");
        return FALSE;
    }


    gst_bin_add_many(GST_BIN(data->bin_playback), data->file_source,
data->audio_decoder, data->audioconvert, NULL);

    if (gst_element_link_many (data->file_source, data->audio_decoder,
NULL) != TRUE) {
        g_printerr("\nFile source and audio decoder element could not
link\n");
        return FALSE;
    }

    if (gst_element_link_many (data->audio_decoder, data->audioconvert,
NULL) != TRUE) {
        g_printerr("\nAudio decoder and audio converter element could not
link\n");
        return FALSE;
    }

    {
    GstPad *pad;
    pad = gst_element_get_static_pad (data->audioconvert, "src");
    gst_element_add_pad (data->bin_playback, gst_ghost_pad_new ("src",
pad));
    gst_object_unref (GST_OBJECT (pad));
    }



/*################################################################################*/

    data->audio_decoder2 = gst_element_factory_make("mad",
"audiomp3decoder2");
    if ( !data->audio_decoder2)    {
        g_printerr ("\nNot all elements for audio pipeline were created\n");
        return FALSE;
    }

    gst_bin_add_many(GST_BIN(data->bin_playback2), data->file_source2,
data->audio_decoder2, data->audioconvert2,NULL);

    if (gst_element_link_many (data->file_source2, data->audio_decoder2,
NULL) != TRUE) {
        g_printerr("\nFile source and audio decoder element could not
link\n");
        return FALSE;
    }
    if (gst_element_link_many (data->audio_decoder2, data->audioconvert2,
NULL) != TRUE) {
        g_printerr("\nAudio decoder and audio converter element could not
link\n");
        return FALSE;
    }

    {
    GstPad *pad;
    pad = gst_element_get_static_pad (data->audioconvert2, "src");
    gst_element_add_pad (data->bin_playback2, gst_ghost_pad_new ("src",
pad));
    gst_object_unref (GST_OBJECT (pad));
    }



    return TRUE;
}





gboolean player_Start(playerData *data)
{
    gst_bin_add_many(GST_BIN (data->pipeline), data->bin_playback,
data->bin_playback2, NULL);



    if (gst_element_link_many (data->bin_playback, data->audio_mixer, NULL)
!= TRUE) {
        g_printerr("\nbin_playback and audio mixer element could not
link\n");
        return FALSE;
    }
    if (gst_element_link_many (data->bin_playback2, data->audio_mixer,
NULL) != TRUE) {
            g_printerr("\nbin_playback2 and audio mixer element could not
link\n");
            return FALSE;
    }

    if (gst_element_set_state (data->pipeline, GST_STATE_NULL) !=
GST_STATE_CHANGE_SUCCESS) {
        g_print("\nFailed to set pipeline state to NULL\n");
        return FALSE;
    }

    gst_element_set_state (data->pipeline, GST_STATE_PLAYING);
    while(gst_element_get_state(data->pipeline, NULL, NULL,
GST_CLOCK_TIME_NONE) != GST_STATE_CHANGE_SUCCESS);
    return TRUE;

}




static gboolean bus_call_CB (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_printerr ("Error: %s\n", error->message);
            g_error_free (error);

            if (debug) {
                g_printerr ("\nDebug details: %s\n", debug);
                g_free (debug);
            }

            g_main_loop_quit (loop);
            break;
            }

        default:
            break;
    }

  return TRUE;
}

static void play_button_CB (GtkButton *button, guiData *data) {

    //this works ...
    /*
    if (!gst_element_seek(gstreamerPlayer.pipeline, 1.0, GST_FORMAT_TIME,
GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SEGMENT,GST_SEEK
_TYPE_SET,0,GST_SEEK_TYPE_NONE, 6)) {
        g_print("Seek failed!\n");
    }
    */

    //how to seek file_source independently ???

    //this not ...
    if (!gst_element_seek(gstreamerPlayer.file_source, 1.0,
GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SEGMENT,GST_SEEK
_TYPE_SET,0,GST_SEEK_TYPE_NONE, 6)) {
        g_print("Seek failed!\n");
    }
}

void create_Gui(guiData *data) {


      data->mainWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);


      data->play_button = gtk_button_new_from_icon_name
("media-playback-start", GTK_ICON_SIZE_SMALL_TOOLBAR);
      g_signal_connect (G_OBJECT (data->play_button), "clicked", G_CALLBACK
(play_button_CB), data);

      GtkWidget *controls = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
      gtk_box_pack_start (GTK_BOX (controls), data->play_button, FALSE,
FALSE, 2);
      gtk_container_add (GTK_CONTAINER (data->mainWindow), controls);

      gtk_widget_show_all(data->mainWindow);

}




int main(int argc, char *argv[])
{
    gtk_init_check(&argc, &argv);
    gst_init (&argc, &argv);


    player_Create(&gstreamerPlayer);
    player_Add(&gstreamerPlayer);
    player_Start(&gstreamerPlayer);



    GstBus *bus;
    guint bus_watch_id;
    GMainLoop *loop;
    loop = g_main_loop_new (NULL, FALSE);



    bus = gst_pipeline_get_bus (GST_PIPELINE (gstreamerPlayer.pipeline));
    bus_watch_id = gst_bus_add_watch (bus, bus_call_CB, loop);
    gst_object_unref (bus);







    create_Gui(&guiElements);
    g_main_loop_run (loop);


    gst_element_set_state (gstreamerPlayer.pipeline, GST_STATE_NULL);
    gst_object_unref (GST_OBJECT (gstreamerPlayer.pipeline));
    g_source_remove (bus_watch_id);
    g_main_loop_unref (loop);

    //to more cleanup here
}

_______________________________________________
gstreamer-devel mailing list
gstreamer-devel at lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/gstreamer-devel/attachments/20171217/79fbab9b/attachment-0001.html>


More information about the gstreamer-devel mailing list