Dear gst-devel,
Further to my question a while back, I have now progressed to my next task. This time I'm trying to capture a section from a stream to a file, using gst_element_seek(). My program is included below. As you can see, I watch for state changes on the bus. When the pipeline goes to PAUSED state, I perform the seek. To quote the manual for gst_element_seek_simple: 'In a completely prerolled PAUSED or PLAYING pipeline, seeking is always guaranteed to return TRUE on a seekable media type.' Since I seek while the pipeline is paused, I expect the program below to give the output: stream is now ready seek result: 1 And 'output.wav' should contain the 10 second period from 10 to 20 seconds of '/home/amoe/test.ogg'. In reality, I get this output: stream is now ready seek result: 0 stream is now ready seek result: 0 stream is now ready seek result: 0 stream is now ready seek result: 0 stream is now ready seek result: 0 stream is now ready seek result: 1 And 'output.wav' contains the entire decoding of 'test.ogg'. The really strange thing is that sometimes it will give the 10-second output I expect, maybe once in every 100 runs? The console output will always be the same, though. I really don't know what's going on here. As far as I can see, I'm not missing any events, and the seek should be executed before the pipeline goes to PLAYING state, so my first thought (that the whole file is getting decoded to 'output.wav' before the seek has a chance to be executed) should not be possible. Any ideas? Thanks, David #include <stdio.h> #include <stdbool.h> #include <gst/gst.h> GstElement *pipeline, *audio; gboolean seek_succeeded = FALSE; static void cb_new_decoded_pad( GstElement *decodebin, GstPad *pad, gboolean last, gpointer data ); static gboolean cb_bus_watch(GstBus *bus, GstMessage *message, gpointer data); void handle_state_change(); int main(int argc, char **argv) { GMainLoop *loop; GstElement *src, *dec, *conv1, *conv2, *sink; GstPad *audiopad; GstBus *bus; gst_init(&argc, &argv); loop = g_main_loop_new(NULL, FALSE); pipeline = gst_pipeline_new("pipeline"); audio = gst_bin_new("audiobin"); src = gst_element_factory_make("filesrc", "source"); dec = gst_element_factory_make("decodebin", "decoder"); conv1 = gst_element_factory_make("audioconvert", "aconv"); conv2 = gst_element_factory_make("wavenc", "wconv"); sink = gst_element_factory_make("filesink", "sink"); g_object_set(G_OBJECT(src), "location", "/home/amoe/test.ogg", NULL); g_object_set(G_OBJECT(sink), "location", "output.wav", NULL); gst_bin_add_many(GST_BIN(pipeline), src, dec, NULL); gst_element_link(src, dec); gst_bin_add_many(GST_BIN(audio), conv1, conv2, sink, NULL); gst_element_link(conv1, conv2); gst_element_link(conv2, sink); // Do some voodoo audiopad = gst_element_get_static_pad(conv1, "sink"); gst_element_add_pad(audio, gst_ghost_pad_new("sink", audiopad)); gst_object_unref(audiopad); gst_bin_add(GST_BIN(pipeline), audio); // Connect signals & buses g_signal_connect( dec, "new-decoded-pad", G_CALLBACK(cb_new_decoded_pad), NULL ); bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline)); gst_bus_add_watch(bus, cb_bus_watch, loop); gst_object_unref(bus); gst_element_set_state(pipeline, GST_STATE_PLAYING); g_main_loop_run(loop); gst_element_set_state(pipeline, GST_STATE_NULL); gst_object_unref(GST_OBJECT(pipeline)); return 0; } static void cb_new_decoded_pad( GstElement *decodebin, GstPad *pad, gboolean last, gpointer data ) { GstPad *audiopad; audiopad = gst_element_get_static_pad(audio, "sink"); gst_pad_link(pad, audiopad); } static gboolean cb_bus_watch(GstBus *bus, GstMessage *message, gpointer data) { GMainLoop *loop = data; switch (GST_MESSAGE_TYPE(message)) { case GST_MESSAGE_EOS: g_main_loop_quit(loop); break; case GST_MESSAGE_STATE_CHANGED: handle_state_change(message); break; default: break; } return TRUE; } void handle_state_change(GstMessage *msg) { GstState previous; GstState current; GstState pending; gboolean ret; gst_message_parse_state_changed(msg, &previous, ¤t, &pending); if (current == GST_STATE_PAUSED && !seek_succeeded) { printf("stream is now ready\n"); // Not working. NB, the use of GST_SEEK_FLAG_FLUSH changes the stream // to one that never gets EOS? Why? ret = gst_element_seek( pipeline, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_SET, 10 * GST_SECOND, GST_SEEK_TYPE_SET, 20 * GST_SECOND ); printf("seek result: %d\n", ret); seek_succeeded = ret; } } -- 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 |
Hoi David,
Not that I know much about seeking, but since nobody else is replying, I will :-) There is no need to use a bus watch in order to wait for the state to change to paused. Instead, you can simply do the following from main(): gst_element_set_state(pipeline, GST_STATE_PAUSED); gst_element_get_state(pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); The gst_element_get_state is required because setting the state to PAUSED happens asynchronously. The reason that you get 'stream is now ready' several times is that you get a bus message for the state change of each individual element; it's only the last one (that of the pipeline) that is actually OK. In fact, trying to seek on the pipeline which is not yet completely prerolled (i.e. state is not yet PAUSED) causes the pipeline to remain in an erroneous state... When you set the state to PLAYING, the playing thread will run concurrently with your main thread. Therefore, some output will already be generated in the file before you start seeking. By delaying the PLAYING until after you've done the seek, you avoid this problem. Does this clarify things? Regards, Arnout On Thursday 09 October 2008 17:36:28 David Banks wrote: > Dear gst-devel, > > Further to my question a while back, I have now progressed to my next task. > This time I'm trying to capture a section from a stream to a file, using > gst_element_seek(). My program is included below. > > As you can see, I watch for state changes on the bus. When the pipeline > goes to PAUSED state, I perform the seek. To quote the manual for > gst_element_seek_simple: 'In a completely prerolled PAUSED or PLAYING > pipeline, seeking is always guaranteed to return TRUE on a seekable media > type.' Since I seek while the pipeline is paused, I expect the program > below to give the output: > > stream is now ready > seek result: 1 > > And 'output.wav' should contain the 10 second period from 10 to 20 seconds > of '/home/amoe/test.ogg'. In reality, I get this output: > > stream is now ready > seek result: 0 > stream is now ready > seek result: 0 > stream is now ready > seek result: 0 > stream is now ready > seek result: 0 > stream is now ready > seek result: 0 > stream is now ready > seek result: 1 > > And 'output.wav' contains the entire decoding of 'test.ogg'. > > The really strange thing is that sometimes it will give the 10-second > output I expect, maybe once in every 100 runs? The console output will > always be the same, though. > > I really don't know what's going on here. As far as I can see, I'm not > missing any events, and the seek should be executed before the pipeline > goes to PLAYING state, so my first thought (that the whole file is getting > decoded to 'output.wav' before the seek has a chance to be executed) should > not be possible. > > Any ideas? > > Thanks, > David -- Arnout Vandecappelle arnout at mind be Senior Embedded Software Architect +32-16-286540 Essensium/Mind http://www.mind.be G.Geenslaan 9, 3001 Leuven, Belgium BE 872 984 063 RPR Leuven LinkedIn profile: http://www.linkedin.com/in/arnoutvandecappelle GPG fingerprint: D206 D44B 5155 DF98 550D 3F2A 2213 88AA A1C7 C933 ------------------------------------------------------------------------- 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 |