add clock

Add a gstreamer pinos clock that reports the time at the server
This commit is contained in:
Wim Taymans 2016-09-12 12:28:51 +02:00
parent 0b380dd43e
commit f86b50d202
11 changed files with 259 additions and 72 deletions

88
pinos/gst/gstpinosclock.c Normal file
View file

@ -0,0 +1,88 @@
/* GStreamer
* Copyright (C) 2016 Wim Taymans <wim.taymans@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
* Boston, MA 02110-1335, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gst/gst.h>
#include "gstpinosclock.h"
GST_DEBUG_CATEGORY_STATIC (gst_pinos_clock_debug_category);
#define GST_CAT_DEFAULT gst_pinos_clock_debug_category
G_DEFINE_TYPE (GstPinosClock, gst_pinos_clock, GST_TYPE_SYSTEM_CLOCK);
GstClock *
gst_pinos_clock_new (PinosStream *stream)
{
GstPinosClock *clock;
clock = g_object_new (GST_TYPE_PINOS_CLOCK, NULL);
clock->stream = stream;
return GST_CLOCK_CAST (clock);
}
static GstClockTime
gst_pinos_clock_get_internal_time (GstClock * clock)
{
GstPinosClock *pclock = (GstPinosClock *) clock;
GstClockTime result;
PinosTime t;
pinos_stream_get_time (pclock->stream, &t);
result = gst_util_uint64_scale_int (t.ticks, GST_SECOND, t.rate);
GST_DEBUG ("%"PRId64", %d %"PRId64, t.ticks, t.rate, result);
return result;
}
static void
gst_pinos_clock_finalize (GObject * object)
{
GstPinosClock *clock = GST_PINOS_CLOCK (object);
GST_DEBUG_OBJECT (clock, "finalize");
G_OBJECT_CLASS (gst_pinos_clock_parent_class)->finalize (object);
}
static void
gst_pinos_clock_class_init (GstPinosClockClass * klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GstClockClass *gstclock_class = GST_CLOCK_CLASS (klass);
gobject_class->finalize = gst_pinos_clock_finalize;
gstclock_class->get_internal_time = gst_pinos_clock_get_internal_time;
GST_DEBUG_CATEGORY_INIT (gst_pinos_clock_debug_category, "pinosclock", 0,
"debug category for pinosclock object");
}
static void
gst_pinos_clock_init (GstPinosClock * clock)
{
GST_OBJECT_FLAG_SET (clock, GST_CLOCK_FLAG_CAN_SET_MASTER);
}

62
pinos/gst/gstpinosclock.h Normal file
View file

@ -0,0 +1,62 @@
/* GStreamer
* Copyright (C) <2016> Wim Taymans <wim.taymans@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __GST_PINOS_CLOCK_H__
#define __GST_PINOS_CLOCK_H__
#include <gst/gst.h>
#include <client/pinos.h>
G_BEGIN_DECLS
#define GST_TYPE_PINOS_CLOCK \
(gst_pinos_clock_get_type())
#define GST_PINOS_CLOCK(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PINOS_CLOCK,GstPinosClock))
#define GST_PINOS_CLOCK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PINOS_CLOCK,GstPinosClockClass))
#define GST_IS_PINOS_CLOCK(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PINOS_CLOCK))
#define GST_IS_PINOS_CLOCK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PINOS_CLOCK))
#define GST_PINOS_CLOCK_GET_CLASS(klass) \
(G_TYPE_INSTANCE_GET_CLASS ((klass), GST_TYPE_PINOS_CLOCK, GstPinosClockClass))
typedef struct _GstPinosClock GstPinosClock;
typedef struct _GstPinosClockClass GstPinosClockClass;
struct _GstPinosClock {
GstSystemClock parent;
PinosStream *stream;
};
struct _GstPinosClockClass {
GstSystemClockClass parent_class;
};
GType gst_pinos_clock_get_type (void);
GstClock * gst_pinos_clock_new (PinosStream *stream);
G_END_DECLS
#endif /* __GST_PINOS_CLOCK_H__ */

View file

@ -48,6 +48,7 @@
#include <spa/include/spa/memory.h>
#include <spa/include/spa/buffer.h>
#include "gstpinosclock.h"
static GQuark process_mem_data_quark;
@ -269,6 +270,7 @@ gst_pinos_src_init (GstPinosSrc * src)
gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
GST_OBJECT_FLAG_SET (src, GST_ELEMENT_FLAG_PROVIDE_CLOCK);
gst_base_src_set_live (GST_BASE_SRC (src), TRUE);
g_queue_init (&src->queue);
@ -523,31 +525,11 @@ parse_stream_properties (GstPinosSrc *pinossrc, PinosProperties *props)
var = pinos_properties_get (props, "pinos.latency.max");
pinossrc->max_latency = var ? (GstClockTime) atoi (var) : GST_CLOCK_TIME_NONE;
var = pinos_properties_get (props, "pinos.clock.type");
if (var != NULL) {
GST_DEBUG_OBJECT (pinossrc, "got clock type %s", var);
if (strcmp (var, "gst.net.time.provider") == 0) {
const gchar *address;
gint port;
GstClockTime base_time;
address = pinos_properties_get (props, "pinos.clock.address");
port = atoi (pinos_properties_get (props, "pinos.clock.port"));
base_time = atoll (pinos_properties_get (props, "pinos.clock.base-time"));
GST_DEBUG_OBJECT (pinossrc, "making net clock for %s:%d %" G_GUINT64_FORMAT, address, port, base_time);
if (pinossrc->clock)
gst_object_unref (pinossrc->clock);
pinossrc->clock = gst_net_client_clock_new ("pinosclock", address, port, base_time);
gst_element_post_message (GST_ELEMENT_CAST (pinossrc),
gst_message_new_clock_provide (GST_OBJECT_CAST (pinossrc),
pinossrc->clock, TRUE));
}
}
pinossrc->is_live = TRUE;
pinossrc->min_latency = 100000000;
pinossrc->max_latency = GST_CLOCK_TIME_NONE;
}
static gboolean
gst_pinos_src_stream_start (GstPinosSrc *pinossrc)
{
@ -817,6 +799,8 @@ gst_pinos_src_query (GstBaseSrc * src, GstQuery * query)
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_LATENCY:
pinossrc->min_latency = 10000000;
pinossrc->max_latency = GST_CLOCK_TIME_NONE;
gst_query_set_latency (query, pinossrc->is_live, pinossrc->min_latency, pinossrc->max_latency);
res = TRUE;
break;
@ -1004,6 +988,7 @@ gst_pinos_src_open (GstPinosSrc * pinossrc)
g_signal_connect (pinossrc->stream, "add-buffer", (GCallback) on_add_buffer, pinossrc);
g_signal_connect (pinossrc->stream, "remove-buffer", (GCallback) on_remove_buffer, pinossrc);
g_signal_connect (pinossrc->stream, "new-buffer", (GCallback) on_new_buffer, pinossrc);
pinossrc->clock = gst_pinos_clock_new (pinossrc->stream);
pinos_main_loop_unlock (pinossrc->loop);
return TRUE;
@ -1031,6 +1016,7 @@ gst_pinos_src_close (GstPinosSrc * pinossrc)
g_main_context_unref (pinossrc->context);
GST_OBJECT_LOCK (pinossrc);
pinossrc->stream_state = PINOS_STREAM_STATE_UNCONNECTED;
g_clear_object (&pinossrc->clock);
g_clear_object (&pinossrc->stream);
GST_OBJECT_UNLOCK (pinossrc);
clear_queue (pinossrc);