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 |
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 |
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 |
Free forum by Nabble | Edit this page |