GNOME Bugzilla – Bug 744442
Clash between gst_element_get_clock() and gst_pipeline_get_clock()
Last modified: 2015-04-02 21:34:31 UTC
Using simple example extracted from android-tutorial-5, adding a call to gst_get_element_clock() returns 0x0. static void *test_player(void *userdata) { CustomData *data = (CustomData *)userdata; GError *error = NULL; GST_DEBUG ("Creating test pipeline"); // Create our own GLib Main Context and make it the default one data->context = g_main_context_new (); g_main_context_push_thread_default(data->context); // Build pipeline data->pipeline = gst_parse_launch("playbin", &error); if (error) { gchar *message = g_strdup_printf("Unable to build pipeline: %s", error->message); g_clear_error (&error); set_ui_message(message, data); g_free (message); return NULL; } gchar* uri = "http://docs.gstreamer.com/media/sintel_trailer-368p.ogv"; g_object_set(data->pipeline, "uri", uri, NULL); // Set the pipeline to READY, so it can already accept a window handle, if we have one data->target_state = GST_STATE_READY; gst_element_set_state(data->pipeline, GST_STATE_READY); // Get clock for netprovider GstClock* clock = gst_element_get_clock(data->pipeline); GST_DEBUG ("gst_element_get_clock... (GstClock:%p)", clock); // clock == 0x0 . . .
You are only guaranteed to get a clock when you reach the playing state as the selection of the clock is done during the paused->playing transition. So you want to do something like: gst_element_set_state(data->pipeline, GST_STATE_PLAYING); gst_element_get_state(data->pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); GstClock* clock = gst_element_get_clock(data->pipeline); Note that the get_state() may block for some time, so you may want to instead way for the state change GstMessage on the bus if you don't want to block. To use with the net clock provider, the most common case is just to use the system clock that you can get with gst_system_clock_obtain().
Thank you Olivier. Unfortunately this excellent information is not easily found in the GStreamer docs. I added your code and it works. Thank you. I am porting a python application (syncing playback across two devices - [noraisin.net]) and the following code works properly without first having to play the video. This runs on Ubuntu 14.04. Can you see any reason why they would behave differently? Thanks. #!/usr/bin/env python import sys from gi.repository import Gst from gi.repository import GstNet def main(args): _, uri, port = args port = int(port) Gst.init() # make the pipeline pipeline = Gst.parse_launch('playbin') pipeline.set_property('uri', uri) # uri interface # make sure some other clock isn't autoselected clock = pipeline.get_clock() print 'Using clock: ', clock pipeline.use_clock(clock) # this will start a server listening on a UDP port clock_provider = GstNet.NetTimeProvider.new(clock, None, port) # we explicitly manage our base time base_time = clock.get_time() print ('Start slave as: python ./play-slave.py %s [IP] %d %d' % (uri, port, base_time)) # disable the pipeline's management of base_time -- we're going # to set it ourselves. pipeline.set_start_time(Gst.CLOCK_TIME_NONE) pipeline.set_base_time(base_time) # now we go :) pipeline.set_state(Gst.State.PLAYING) # wait until things stop pipeline.get_bus().poll(Gst.MessageType.EOS | Gst.MessageType.ERROR, Gst.CLOCK_TIME_NONE) pipeline.set_state(Gst.State.NULL) if __name__ == '__main__': main(sys.argv)
In Python, you're calling gst_pipeline_get_clock(), not gst_element_get_clock(). But it's still not useful to do that before going to playing, because you'll always get the system clock, so you shoul use gst_system_clock_obtain() instead. I'm renaming this bug about the API clash. I suggest we create an alias for one of them (and deprecate it), as it means one of these functions (surprise surprise which!) is not available in most OO bindings.
Created attachment 296729 [details] [review] pipeline: Add binding friendly gst_pipeline_get_pipeline_clock() I suggest we add a gst_pipeline_get_pipeline_clock() and skip gst_pipeline_set/set_clock() from the GIR to avoid this confusion. This patch implements this, also tries to document how gst_pipeline_get_pipeline_clock() is different from gst_element_get_clock()... API: gst_pipeline_get_pipeline_clock()
Created attachment 296730 [details] [review] element: Document when a clock is available from gst_element_get_clock()
Ping.
Pushed: commit 518babf6cb6f71b2704a4b420804322cfa1dda54 Author: Olivier Crête <olivier.crete@collabora.com> Date: Thu Feb 12 19:39:44 2015 -0500 element: Document when a clock is available from gst_element_get_clock() https://bugzilla.gnome.org/show_bug.cgi?id=744442 commit 59d9992ed02f0e9f650481e940e8aba8d96409f1 Author: Olivier Crête <olivier.crete@collabora.com> Date: Thu Feb 12 19:40:06 2015 -0500 pipeline: Add binding friendly gst_pipeline_get_pipeline_clock() Also skip gst_pipeline_get_clock() and gst_pipeline_set_clock() from the bindings as they are confused with gst_element_*_clock(). API: gst_pipeline_get_pipeline_clock() https://bugzilla.gnome.org/show_bug.cgi?id=744442