Seek works strangely with filesink

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

Seek works strangely with filesink

David Banks-3
Hi, I'm just getting started with GStreamer.  I want to write a program to load
an Ogg file, play it, and seek to a random point within the file every two
seconds.  In addition, I want to be able to save the output of the program to a
file.

I initially wrote the program using the pipeline:

filesrc | oggdemux | vorbisdec | audioconvert | autoaudiosink

Basically according to the example given in the application development manual.
I added the function 'cb_timeout0' to detect the length and do the seek.  That
version worked perfectly and produced exactly what I expected.

I then tried to make it write its output to a file.  I initially tried to simply
replace 'autoaudiosink' with 'filesink', but couldn't figure out the format of
the raw samples in the output file.  Since I wanted WAV output anyway, I tried
using wavenc.  After a little trial and error, I found the pipeline below:

filesrc | oggdemux | vorbisdec | audioconvert | wavenc | filesink

I converted it to the program below.  This program displays an odd behaviour,
however.  Its output is always the size of the fully decoded Ogg file, no matter
where you interrupt it.  That is, even if you run it for only a few seconds
(when it .  In addition, the seeks in the output are erratic.  For
example, if you run the program for three minutes, the output file might contain
only three or four seeks.  They seem to occur at random points in the output.

Why is the filesink output so different from the autoaudiosink output?  Is it
possible the seeks are happening in the *output* rather than the input file?  I
tried replacing the first parameter to gst_element_seek() with a pointer to the
demuxer rather than the entire pipeline, but still the same behaviour.

// gcc -o demo -Wall -g $(pkg-config --libs --cflags $(libs)) demo.c

#include <stdio.h>

#include <gst/gst.h>
#include <glib.h>

static gboolean cb_bus(GstBus *bus, GstMessage *msg, gpointer data);
static void cb_pad_added(GstElement *element, GstPad *pad, gpointer data);
gboolean cb_timeout0(gpointer data);

gint32 pos = 0;

int main(int argc, char **argv) {
    GMainLoop *loop;
    GstElement *pipeline, *source, *demuxer, *decoder, *conv1, *conv2, *sink;
    GstBus *bus;

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

    if (argc != 2) {
        g_printerr("Usage: %s <ogg vorbis filename>\n", argv[0]);
        return 1;
    }

    pipeline = gst_pipeline_new("audio-player");
    source = gst_element_factory_make("filesrc", "file-source");
    demuxer = gst_element_factory_make("oggdemux", "ogg-demuxer");
    decoder = gst_element_factory_make("vorbisdec", "vorbis-decoder");
    conv1    = gst_element_factory_make("audioconvert", NULL);
    conv2    = gst_element_factory_make("wavenc", NULL);
    sink    = gst_element_factory_make("filesink", "audio-output");

    if (!pipeline || !source || !demuxer || !decoder || !conv1 ||
!conv2 || !sink) {
        g_printerr("pipeline failed to create properly, exiting\n");
        return 1;
    }

    g_object_set(G_OBJECT(source), "location", argv[1], NULL);
    g_object_set(G_OBJECT(sink), "location", "/home/amoe/foo.wav", NULL);

    bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
    gst_bus_add_watch(bus, cb_bus, loop);
    gst_object_unref(bus);

    gst_bin_add_many(
        GST_BIN(pipeline),
        source, demuxer, decoder, conv1, conv2, sink, NULL
    );

    gst_element_link(source, demuxer);
    gst_element_link_many(decoder, conv1, conv2, sink, NULL);


    g_signal_connect(
        demuxer, "pad-added", G_CALLBACK(cb_pad_added), decoder
    );

    g_print("Now playing: %s\n", argv[1]);
    gst_element_set_state(pipeline, GST_STATE_PLAYING);

    // seek
    g_timeout_add(2 * 1000, cb_timeout0, pipeline);

    g_print("running...\n");
    g_main_loop_run(loop);

    g_print("returned, stopping playback\n");
    gst_element_set_state(pipeline, GST_STATE_NULL);

    g_print("deleting pipeline\n");
    gst_object_unref(GST_OBJECT(pipeline));

    return 0;
}

gboolean cb_timeout0(gpointer data) {
    GstElement *pipeline = (GstElement *) data;
    GstFormat fmt = GST_FORMAT_TIME;
    gboolean test;
    gint64 len;
    guint64 len_seconds;

    test = gst_element_seek(
        pipeline,
        1.0,
        GST_FORMAT_TIME,
        GST_SEEK_FLAG_FLUSH,
        GST_SEEK_TYPE_SET,
        pos * GST_SECOND,
        GST_SEEK_TYPE_NONE,
        -1
        );
    printf("seek: %d\n", test);

    test = gst_element_query_duration(
        pipeline, &fmt, &len
    );

    len_seconds = len / GST_SECOND;
    printf("total time: %lld (%llds)\n", len, len_seconds);
    pos = g_random_int_range(0, len_seconds);
    printf("random: %d\n", pos);

    puts("timeout called");

    return TRUE;
}

static gboolean cb_bus(GstBus *bus, GstMessage *msg, gpointer data) {

    return TRUE;
}

static void cb_pad_added(GstElement *element, GstPad *pad, gpointer data) {

    GstPad *sinkpad;
    GstElement *decoder = (GstElement *) data;

    puts("pad added callback");
    g_print("dynamic pad created, linking demuxer/decoder\n");

    sinkpad = gst_element_get_static_pad(decoder, "sink");
    gst_pad_link(pad, sinkpad);

    gst_object_unref(sinkpad);

}

Thanks,
--
David Banks <[hidden email]>

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: Seek works strangely with filesink

Aurelien Grimaud (elzz)
Hi,
audiosink is sync on the clock, not filesink.
So your pipeline with filesink runs as fast as possible, while the
audiosink one runs at real time.
Your filesink pipelines misses a sync element.
Try add identity with sync=TRUE in it to force clock sync.

gst-launch -v filesrc location=/home/musique/Heidsieck-Bernard.mp3 \
! decodebin ! identity sync=TRUE ! wavenc ! filesink location=/tmp/xx.wav

Note:
I was first expecting sync option on filesink to do the trick, but it
fails :
gst-launch -v filesrc location=/home/musique/Heidsieck-Bernard.mp3 \
! decodebin ! wavenc ! identity ! filesink location=/tmp/xx.wav sync=TRUE

So I tried
gst-launch -v filesrc location=/home/musique/Heidsieck-Bernard.mp3 \
! decodebin ! wavenc ! identity sync=TRUE ! filesink location=/tmp/xx.wav
but it runs too fast too.

Aurelien

David Banks a écrit :

> Hi, I'm just getting started with GStreamer.  I want to write a program to load
> an Ogg file, play it, and seek to a random point within the file every two
> seconds.  In addition, I want to be able to save the output of the program to a
> file.
>
> I initially wrote the program using the pipeline:
>
> filesrc | oggdemux | vorbisdec | audioconvert | autoaudiosink
>
> Basically according to the example given in the application development manual.
> I added the function 'cb_timeout0' to detect the length and do the seek.  That
> version worked perfectly and produced exactly what I expected.
>
> I then tried to make it write its output to a file.  I initially tried to simply
> replace 'autoaudiosink' with 'filesink', but couldn't figure out the format of
> the raw samples in the output file.  Since I wanted WAV output anyway, I tried
> using wavenc.  After a little trial and error, I found the pipeline below:
>
> filesrc | oggdemux | vorbisdec | audioconvert | wavenc | filesink
>
> I converted it to the program below.  This program displays an odd behaviour,
> however.  Its output is always the size of the fully decoded Ogg file, no matter
> where you interrupt it.  That is, even if you run it for only a few seconds
> (when it .  In addition, the seeks in the output are erratic.  For
> example, if you run the program for three minutes, the output file might contain
> only three or four seeks.  They seem to occur at random points in the output.
>
> Why is the filesink output so different from the autoaudiosink output?  Is it
> possible the seeks are happening in the *output* rather than the input file?  I
> tried replacing the first parameter to gst_element_seek() with a pointer to the
> demuxer rather than the entire pipeline, but still the same behaviour.
>
> // gcc -o demo -Wall -g $(pkg-config --libs --cflags $(libs)) demo.c
>
> #include <stdio.h>
>
> #include <gst/gst.h>
> #include <glib.h>
>
> static gboolean cb_bus(GstBus *bus, GstMessage *msg, gpointer data);
> static void cb_pad_added(GstElement *element, GstPad *pad, gpointer data);
> gboolean cb_timeout0(gpointer data);
>
> gint32 pos = 0;
>
> int main(int argc, char **argv) {
>     GMainLoop *loop;
>     GstElement *pipeline, *source, *demuxer, *decoder, *conv1, *conv2, *sink;
>     GstBus *bus;
>
>     gst_init(&argc, &argv);
>     loop = g_main_loop_new(NULL, FALSE);
>
>     if (argc != 2) {
>         g_printerr("Usage: %s <ogg vorbis filename>\n", argv[0]);
>         return 1;
>     }
>
>     pipeline = gst_pipeline_new("audio-player");
>     source = gst_element_factory_make("filesrc", "file-source");
>     demuxer = gst_element_factory_make("oggdemux", "ogg-demuxer");
>     decoder = gst_element_factory_make("vorbisdec", "vorbis-decoder");
>     conv1    = gst_element_factory_make("audioconvert", NULL);
>     conv2    = gst_element_factory_make("wavenc", NULL);
>     sink    = gst_element_factory_make("filesink", "audio-output");
>
>     if (!pipeline || !source || !demuxer || !decoder || !conv1 ||
> !conv2 || !sink) {
>         g_printerr("pipeline failed to create properly, exiting\n");
>         return 1;
>     }
>
>     g_object_set(G_OBJECT(source), "location", argv[1], NULL);
>     g_object_set(G_OBJECT(sink), "location", "/home/amoe/foo.wav", NULL);
>
>     bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
>     gst_bus_add_watch(bus, cb_bus, loop);
>     gst_object_unref(bus);
>
>     gst_bin_add_many(
>         GST_BIN(pipeline),
>         source, demuxer, decoder, conv1, conv2, sink, NULL
>     );
>
>     gst_element_link(source, demuxer);
>     gst_element_link_many(decoder, conv1, conv2, sink, NULL);
>
>
>     g_signal_connect(
>         demuxer, "pad-added", G_CALLBACK(cb_pad_added), decoder
>     );
>
>     g_print("Now playing: %s\n", argv[1]);
>     gst_element_set_state(pipeline, GST_STATE_PLAYING);
>
>     // seek
>     g_timeout_add(2 * 1000, cb_timeout0, pipeline);
>
>     g_print("running...\n");
>     g_main_loop_run(loop);
>
>     g_print("returned, stopping playback\n");
>     gst_element_set_state(pipeline, GST_STATE_NULL);
>
>     g_print("deleting pipeline\n");
>     gst_object_unref(GST_OBJECT(pipeline));
>
>     return 0;
> }
>
> gboolean cb_timeout0(gpointer data) {
>     GstElement *pipeline = (GstElement *) data;
>     GstFormat fmt = GST_FORMAT_TIME;
>     gboolean test;
>     gint64 len;
>     guint64 len_seconds;
>
>     test = gst_element_seek(
>         pipeline,
>         1.0,
>         GST_FORMAT_TIME,
>         GST_SEEK_FLAG_FLUSH,
>         GST_SEEK_TYPE_SET,
>         pos * GST_SECOND,
>         GST_SEEK_TYPE_NONE,
>         -1
>         );
>     printf("seek: %d\n", test);
>
>     test = gst_element_query_duration(
>         pipeline, &fmt, &len
>     );
>
>     len_seconds = len / GST_SECOND;
>     printf("total time: %lld (%llds)\n", len, len_seconds);
>     pos = g_random_int_range(0, len_seconds);
>     printf("random: %d\n", pos);
>
>     puts("timeout called");
>
>     return TRUE;
> }
>
> static gboolean cb_bus(GstBus *bus, GstMessage *msg, gpointer data) {
>
>     return TRUE;
> }
>
> static void cb_pad_added(GstElement *element, GstPad *pad, gpointer data) {
>
>     GstPad *sinkpad;
>     GstElement *decoder = (GstElement *) data;
>
>     puts("pad added callback");
>     g_print("dynamic pad created, linking demuxer/decoder\n");
>
>     sinkpad = gst_element_get_static_pad(decoder, "sink");
>     gst_pad_link(pad, sinkpad);
>
>     gst_object_unref(sinkpad);
>
> }
>
> Thanks,
>  



-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: Seek works strangely with filesink

David Banks-3
2008/9/17 Aurelien Grimaud <[hidden email]>:
> Your filesink pipelines misses a sync element.
> Try add identity with sync=TRUE in it to force clock sync.

Thanks!  This fixed it.

--
David Banks <[hidden email]>

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gstreamer-devel