Playbin with custom audiosink bin audio/x-raw conversion

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Playbin with custom audiosink bin audio/x-raw conversion

GStreamer-devel mailing list
Afternoon,
I am trying to get gstreamer to simply loop a .wav file to a filesink.
for testing purposes the filesink will be a .wav file but actually want to
write raw audio to a fifo.

I tried to combine these two concepts:
https://tristanswork.blogspot.com/2010/10/looping-playback-with-gstreamer.html
https://gstreamer.freedesktop.org/documentation/tutorials/playback/custom-playbin-sinks.html?gi-language=c

and the pipeline does run but the audio in the .wav is corrupted. I then
tried adding a decodebin with audio/x-raw caps but now there is no audio
written out.

So in essence I think it should be simple, I just need the playbin to
playout raw audio or to somehow convert whatever playbin outputs to
raw-audio.

any help would be greatly appreciated.

gboolean bus_callback(GstBus* bus, GstMessage* msg, gpointer data)
{
        GstElement* play = GST_ELEMENT(data);
        switch (GST_MESSAGE_TYPE(msg)) {
                case GST_MESSAGE_EOS:
                        /* restart playback if at end */
                        if (!gst_element_seek(play,
                                                                  1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
                                                                  GST_SEEK_TYPE_SET, 0,
                                                                  GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
                                g_print("Seek failed!\n");
                        }
                        break;
                default:
                        break;
        }
        return TRUE;
}

void Playfile()
{
        GMainLoop* loop;
        GstElement* play;
        GstBus* bus;

        /* init GStreamer */
        gst_init(NULL, NULL);
        loop = g_main_loop_new(NULL, FALSE);

        /* set up */
        play = gst_element_factory_make("playbin", "play");
        g_object_set(G_OBJECT(play), "uri", "file:/tmp/tone_sink_1.wav", NULL);

        GstElement *audio_sink{nullptr}, *wav_convert{nullptr}, *wavenc{nullptr};

        GstElement* decodebin{nullptr};
        decodebin = gst_element_factory_make("decodebin", NULL);

        audio_sink = gst_element_factory_make("filesink", NULL);
        wav_convert = gst_element_factory_make("audioconvert", NULL);
        wavenc = gst_element_factory_make("wavenc", NULL);

        if (!decodebin ||
                !audio_sink ||
                !wav_convert ||
                !wavenc) {
                throw std::runtime_error("sink elements could be created.");
        }
        g_object_set(audio_sink, "location", "tester.wav", NULL);

        GstCaps* in_filtercaps = gst_caps_new_simple("audio/x-raw",
                                                                                                 "format", G_TYPE_STRING, "F32LE",
                                                                                                 "rate", G_TYPE_INT, 48000,
                                                                                                 NULL);

        g_object_set(decodebin, "caps", in_filtercaps, NULL);
        gst_caps_unref(in_filtercaps);

        GstElement* bin = gst_bin_new("audio_sink_bin");

        gst_bin_add_many(GST_BIN(bin),
                                         decodebin,
                                         wav_convert,
                                         wavenc,
                                         audio_sink,
                                         NULL);

        gst_element_link_many(decodebin, wav_convert, wavenc, audio_sink, NULL);

        GstPad *pad, *ghost_pad;

        pad = gst_element_get_static_pad(decodebin, "sink");
        ghost_pad = gst_ghost_pad_new("sink", pad);
        gst_pad_set_active(ghost_pad, TRUE);
        gst_element_add_pad(bin, ghost_pad);
        gst_object_unref(pad);

        g_object_set(GST_OBJECT(play), "audio-sink", bin, NULL);

        bus = gst_pipeline_get_bus(GST_PIPELINE(play));
        gst_bus_add_watch(bus, bus_callback, play);
        gst_object_unref(bus);

        gst_element_set_state(play, GST_STATE_PLAYING);
        std::string name = "test";
        GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(play), GST_DEBUG_GRAPH_SHOW_ALL,
name.c_str());

        /* now run */
        g_main_loop_run(loop);

        /* also clean up */
        gst_element_set_state(play, GST_STATE_NULL);
        gst_object_unref(GST_OBJECT(play));
}




--
Sent from: http://gstreamer-devel.966125.n4.nabble.com/
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: Playbin with custom audiosink bin audio/x-raw conversion

GStreamer-devel mailing list
Update,
I now get valid audio out, but the data written to file is never longer than
the input file.
But if I switch the sink from file sink to autoaudiosink then the audio out
my speaker does loop.
I'm not sure if the EOS signal is resetting the filesink file?


gboolean bus_callback(GstBus* bus, GstMessage* msg, gpointer data)
{
        GstElement* play = GST_ELEMENT(data);
        switch (GST_MESSAGE_TYPE(msg)) {
                case GST_MESSAGE_EOS:
                        /* restart playback if at end */
                        //std::cout << "Replay" << std::endl;
                        if (!gst_element_seek(play,
                                                                  1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
                                                                  GST_SEEK_TYPE_SET, 0,
                                                                  GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
                                g_print("Seek failed!\n");
                        }
                        break;
                default:
                        break;
        }
        return TRUE;
}

void Playfile()
{
        GMainLoop* loop;
        GstElement* pipeline;
        GstBus* bus;
        GstMessage* msg;

        /* init GStreamer */
        gst_init(NULL, NULL);
        loop = g_main_loop_new(NULL, FALSE);

        /* set up */
        pipeline = gst_element_factory_make("playbin", "play");
        g_object_set(G_OBJECT(pipeline), "uri",
"file:///home/nick/devel/tnm/analysis/modules/gcc_release_build/ssf_tests/bin/8ch_24bit_1s.wav",
NULL);

        //-------------
        GstElement *bin, *convert, *sink, *filter;
        GstCaps* caps;
        GstPad *pad, *ghost_pad;

        convert = gst_element_factory_make("audioconvert", "convert");
        //sink = gst_element_factory_make("filesink", "audio_sink");
        sink = gst_element_factory_make("autoaudiosink", "audio_sink");

        filter = gst_element_factory_make("capsfilter", "capsfilter");
        if (!convert || !sink) {
                g_printerr("Not all elements could be created.\n");
        }

        caps = gst_caps_new_simple("audio/x-raw",
                                                           "format", G_TYPE_STRING, "F32LE",
                                                           "rate", G_TYPE_INT, 48000,
                                                           "channel-mask", GST_TYPE_BITMASK, 0xff,
                                                           NULL);

        g_object_set(G_OBJECT(filter), "caps", caps, NULL);
        gst_caps_unref(caps);

        //g_object_set(sink, "location", "stinker", NULL);

        /* Create the sink bin, add the elements and link them */
        bin = gst_bin_new("audio_sink_bin");
        gst_bin_add_many(GST_BIN(bin), filter, convert, sink, NULL);
        gst_element_link_many(filter, convert, sink, NULL);
        pad = gst_element_get_static_pad(filter, "sink");
        ghost_pad = gst_ghost_pad_new("sink", pad);
        gst_pad_set_active(ghost_pad, TRUE);
        gst_element_add_pad(bin, ghost_pad);
        gst_object_unref(pad);

        /* Set playbin's audio sink to be our sink bin */
        g_object_set(GST_OBJECT(pipeline), "audio-sink", bin, NULL);

        //-------------

        gst_element_set_state(pipeline, GST_STATE_PLAYING);
        // gst_element_set_state(pipeline, GST_STATE_PLAYING);

        bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
        gst_bus_add_watch(bus, bus_callback, pipeline);
        gst_object_unref(bus);

        //msg = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE,
static_cast<GstMessageType>(GST_MESSAGE_ERROR));

        Thread_wrapper mainloop_thread;

        mainloop_thread.Start(
                "mainloop_thread", [&]() {
                        g_main_loop_run(loop);
                        return false;
                });
        /* now run */

        for (int i = 0; i < 30; ++i) {
                gst_element_set_state(sink, GST_STATE_PLAYING);

                sleep(1);
                std::string name = "test";
                GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(pipeline), GST_DEBUG_GRAPH_SHOW_ALL,
name.c_str());
                std::cout << i << " seconds" << std::endl;
        }

        g_main_loop_quit(loop);
        mainloop_thread.Stop();

        /* also clean up */
        /* Free resources */
        // if (msg != NULL)
        // gst_message_unref(msg);
        gst_object_unref(bus);
        gst_element_set_state(pipeline, GST_STATE_NULL);
        gst_object_unref(GST_OBJECT(pipeline));
}



--
Sent from: http://gstreamer-devel.966125.n4.nabble.com/
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel