From 11c74ccec634b809d727ea9704a6b8e7920c2fae Mon Sep 17 00:00:00 2001 From: Mathieu Duponchelle Date: Fri, 23 Sep 2022 18:25:41 +0200 Subject: [PATCH] fake{video|audio}sink: don't proxy properties at instance init. Instead proxy properties from the GstBaseSink class at class_init time, and duplicate the rest of the fakesink properties manually. Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/1442 Part-of: --- subprojects/gst-docs/symbols/symbol_index.json | 8 -- .../docs/plugins/gst_plugins_cache.json | 46 ++++++- .../gst/debugutils/gstfakeaudiosink.c | 144 +++++++++++++++++++-- .../gst/debugutils/gstfakesinkutils.c | 12 +- .../gst/debugutils/gstfakesinkutils.h | 5 +- .../gst/debugutils/gstfakevideosink.c | 140 ++++++++++++++++++-- 6 files changed, 308 insertions(+), 47 deletions(-) diff --git a/subprojects/gst-docs/symbols/symbol_index.json b/subprojects/gst-docs/symbols/symbol_index.json index 3c1efbf..54c29ae 100644 --- a/subprojects/gst-docs/symbols/symbol_index.json +++ b/subprojects/gst-docs/symbols/symbol_index.json @@ -34716,14 +34716,6 @@ "element-fakesink", "element-fakesrc", "element-fakevideosink", - "element-fakevideosink_GstFakeSinkStateError", - "element-fakevideosink_GstFakeSinkStateError::none", - "element-fakevideosink_GstFakeSinkStateError::null-to-ready", - "element-fakevideosink_GstFakeSinkStateError::paused-to-playing", - "element-fakevideosink_GstFakeSinkStateError::paused-to-ready", - "element-fakevideosink_GstFakeSinkStateError::playing-to-paused", - "element-fakevideosink_GstFakeSinkStateError::ready-to-null", - "element-fakevideosink_GstFakeSinkStateError::ready-to-paused", "element-fbdevsink", "element-fdkaacdec", "element-fdkaacenc", diff --git a/subprojects/gst-plugins-bad/docs/plugins/gst_plugins_cache.json b/subprojects/gst-plugins-bad/docs/plugins/gst_plugins_cache.json index 5f7e7d7..dbc2b82 100644 --- a/subprojects/gst-plugins-bad/docs/plugins/gst_plugins_cache.json +++ b/subprojects/gst-plugins-bad/docs/plugins/gst_plugins_cache.json @@ -10454,7 +10454,7 @@ "default": "none (0)", "mutable": "null", "readable": true, - "type": "GstFakeSinkStateError", + "type": "GstFakeAudioSinkStateError", "writable": true }, "stats": { @@ -10816,7 +10816,7 @@ "default": "none (0)", "mutable": "null", "readable": true, - "type": "GstFakeSinkStateError", + "type": "GstFakeVideoSinkStateError", "writable": true }, "stats": { @@ -11308,7 +11308,7 @@ } ] }, - "GstFakeSinkStateError": { + "GstFakeAudioSinkStateError": { "kind": "enum", "values": [ { @@ -11362,6 +11362,46 @@ "value": "0x00000002" } ] + }, + "GstFakeVideoSinkStateError": { + "kind": "enum", + "values": [ + { + "desc": "No state change errors", + "name": "none", + "value": "0" + }, + { + "desc": "Fail state change from NULL to READY", + "name": "null-to-ready", + "value": "1" + }, + { + "desc": "Fail state change from READY to PAUSED", + "name": "ready-to-paused", + "value": "2" + }, + { + "desc": "Fail state change from PAUSED to PLAYING", + "name": "paused-to-playing", + "value": "3" + }, + { + "desc": "Fail state change from PLAYING to PAUSED", + "name": "playing-to-paused", + "value": "4" + }, + { + "desc": "Fail state change from PAUSED to READY", + "name": "paused-to-ready", + "value": "5" + }, + { + "desc": "Fail state change from READY to NULL", + "name": "ready-to-null", + "value": "6" + } + ] } }, "package": "GStreamer Bad Plug-ins", diff --git a/subprojects/gst-plugins-bad/gst/debugutils/gstfakeaudiosink.c b/subprojects/gst-plugins-bad/gst/debugutils/gstfakeaudiosink.c index 1493965..6a33435 100644 --- a/subprojects/gst-plugins-bad/gst/debugutils/gstfakeaudiosink.c +++ b/subprojects/gst-plugins-bad/gst/debugutils/gstfakeaudiosink.c @@ -43,11 +43,80 @@ #include +typedef enum +{ + FAKE_SINK_STATE_ERROR_NONE = 0, + FAKE_SINK_STATE_ERROR_NULL_READY, + FAKE_SINK_STATE_ERROR_READY_PAUSED, + FAKE_SINK_STATE_ERROR_PAUSED_PLAYING, + FAKE_SINK_STATE_ERROR_PLAYING_PAUSED, + FAKE_SINK_STATE_ERROR_PAUSED_READY, + FAKE_SINK_STATE_ERROR_READY_NULL +} GstFakeSinkStateError; + +#define DEFAULT_DROP_OUT_OF_SEGMENT TRUE +#define DEFAULT_STATE_ERROR FAKE_SINK_STATE_ERROR_NONE +#define DEFAULT_SILENT TRUE +#define DEFAULT_DUMP FALSE +#define DEFAULT_SIGNAL_HANDOFFS FALSE +#define DEFAULT_LAST_MESSAGE NULL +#define DEFAULT_CAN_ACTIVATE_PUSH TRUE +#define DEFAULT_CAN_ACTIVATE_PULL FALSE +#define DEFAULT_NUM_BUFFERS -1 + +/** + * GstFakeAudioSinkStateError: + * + * Proxy for GstFakeSinkError. + * + * Since: 1.22 + */ + +#define GST_TYPE_FAKE_AUDIO_SINK_STATE_ERROR (gst_fake_audio_sink_state_error_get_type()) +static GType +gst_fake_audio_sink_state_error_get_type (void) +{ + static GType fakeaudiosink_state_error_type = 0; + static const GEnumValue fakeaudiosink_state_error[] = { + {FAKE_SINK_STATE_ERROR_NONE, "No state change errors", "none"}, + {FAKE_SINK_STATE_ERROR_NULL_READY, + "Fail state change from NULL to READY", "null-to-ready"}, + {FAKE_SINK_STATE_ERROR_READY_PAUSED, + "Fail state change from READY to PAUSED", "ready-to-paused"}, + {FAKE_SINK_STATE_ERROR_PAUSED_PLAYING, + "Fail state change from PAUSED to PLAYING", "paused-to-playing"}, + {FAKE_SINK_STATE_ERROR_PLAYING_PAUSED, + "Fail state change from PLAYING to PAUSED", "playing-to-paused"}, + {FAKE_SINK_STATE_ERROR_PAUSED_READY, + "Fail state change from PAUSED to READY", "paused-to-ready"}, + {FAKE_SINK_STATE_ERROR_READY_NULL, + "Fail state change from READY to NULL", "ready-to-null"}, + {0, NULL, NULL}, + }; + + if (!fakeaudiosink_state_error_type) { + fakeaudiosink_state_error_type = + g_enum_register_static ("GstFakeAudioSinkStateError", + fakeaudiosink_state_error); + } + return fakeaudiosink_state_error_type; +} + + enum { PROP_0, PROP_VOLUME, PROP_MUTE, + PROP_STATE_ERROR, + PROP_SILENT, + PROP_DUMP, + PROP_SIGNAL_HANDOFFS, + PROP_DROP_OUT_OF_SEGMENT, + PROP_LAST_MESSAGE, + PROP_CAN_ACTIVATE_PUSH, + PROP_CAN_ACTIVATE_PULL, + PROP_NUM_BUFFERS, PROP_LAST }; @@ -60,29 +129,20 @@ enum static guint gst_fake_audio_sink_signals[LAST_SIGNAL] = { 0 }; +static GParamSpec *pspec_last_message = NULL; + static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS (GST_AUDIO_CAPS_MAKE (GST_AUDIO_FORMATS_ALL))); G_DEFINE_TYPE_WITH_CODE (GstFakeAudioSink, gst_fake_audio_sink, GST_TYPE_BIN, - G_IMPLEMENT_INTERFACE (GST_TYPE_STREAM_VOLUME, NULL);); + G_IMPLEMENT_INTERFACE (GST_TYPE_STREAM_VOLUME, NULL); + ); GST_ELEMENT_REGISTER_DEFINE (fakeaudiosink, "fakeaudiosink", GST_RANK_NONE, gst_fake_audio_sink_get_type ()); static void -gst_fake_audio_sink_proxy_properties (GstFakeAudioSink * self, - GstElement * child) -{ - static gsize initialized = 0; - - if (g_once_init_enter (&initialized)) { - gst_fake_sink_proxy_properties (GST_ELEMENT_CAST (self), child, PROP_LAST); - g_once_init_leave (&initialized, 1); - } -} - -static void gst_fake_audio_sink_proxy_handoff (GstElement * element, GstBuffer * buffer, GstPad * pad, GstFakeAudioSink * self) { @@ -99,6 +159,12 @@ gst_fake_audio_sink_proxy_preroll_handoff (GstElement * element, } static void +gst_fake_audio_sink_proxy_last_message (GstElement * element) +{ + g_object_notify_by_pspec ((GObject *) element, pspec_last_message); +} + +static void gst_fake_audio_sink_init (GstFakeAudioSink * self) { GstElement *child; @@ -126,7 +192,8 @@ gst_fake_audio_sink_init (GstFakeAudioSink * self) self->child = child; - gst_fake_audio_sink_proxy_properties (self, child); + g_signal_connect (child, "notify::last-message", + G_CALLBACK (gst_fake_audio_sink_proxy_last_message), self); g_signal_connect (child, "handoff", G_CALLBACK (gst_fake_audio_sink_proxy_handoff), self); g_signal_connect (child, "preroll-handoff", @@ -180,6 +247,7 @@ gst_fake_audio_sink_class_init (GstFakeAudioSinkClass * klass) { GstElementClass *element_class = GST_ELEMENT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass); + GObjectClass *base_sink_class; object_class->get_property = gst_fake_audio_sink_get_property; object_class->set_property = gst_fake_audio_sink_set_property; @@ -241,8 +309,56 @@ gst_fake_audio_sink_class_init (GstFakeAudioSinkClass * klass) preroll_handoff), NULL, NULL, NULL, G_TYPE_NONE, 2, GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE, GST_TYPE_PAD); + g_object_class_install_property (object_class, PROP_STATE_ERROR, + g_param_spec_enum ("state-error", "State Error", + "Generate a state change error", GST_TYPE_FAKE_AUDIO_SINK_STATE_ERROR, + DEFAULT_STATE_ERROR, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + pspec_last_message = g_param_spec_string ("last-message", "Last Message", + "The message describing current status", DEFAULT_LAST_MESSAGE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_LAST_MESSAGE, + pspec_last_message); + g_object_class_install_property (object_class, PROP_SIGNAL_HANDOFFS, + g_param_spec_boolean ("signal-handoffs", "Signal handoffs", + "Send a signal before unreffing the buffer", DEFAULT_SIGNAL_HANDOFFS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_DROP_OUT_OF_SEGMENT, + g_param_spec_boolean ("drop-out-of-segment", + "Drop out-of-segment buffers", + "Drop and don't render / hand off out-of-segment buffers", + DEFAULT_DROP_OUT_OF_SEGMENT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_SILENT, + g_param_spec_boolean ("silent", "Silent", + "Don't produce last_message events", DEFAULT_SILENT, + G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_DUMP, + g_param_spec_boolean ("dump", "Dump", "Dump buffer contents to stdout", + DEFAULT_DUMP, + G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_CAN_ACTIVATE_PUSH, + g_param_spec_boolean ("can-activate-push", "Can activate push", + "Can activate in push mode", DEFAULT_CAN_ACTIVATE_PUSH, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_CAN_ACTIVATE_PULL, + g_param_spec_boolean ("can-activate-pull", "Can activate pull", + "Can activate in pull mode", DEFAULT_CAN_ACTIVATE_PULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_NUM_BUFFERS, + g_param_spec_int ("num-buffers", "num-buffers", + "Number of buffers to accept going EOS", -1, G_MAXINT, + DEFAULT_NUM_BUFFERS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + base_sink_class = g_type_class_ref (GST_TYPE_BASE_SINK); + gst_util_proxy_class_properties (object_class, base_sink_class, PROP_LAST); + g_type_class_unref (base_sink_class); + gst_element_class_add_static_pad_template (element_class, &sink_factory); gst_element_class_set_static_metadata (element_class, "Fake Audio Sink", "Audio/Sink", "Fake audio renderer", "Philippe Normand "); + + gst_type_mark_as_plugin_api (GST_TYPE_FAKE_AUDIO_SINK_STATE_ERROR, 0); } diff --git a/subprojects/gst-plugins-bad/gst/debugutils/gstfakesinkutils.c b/subprojects/gst-plugins-bad/gst/debugutils/gstfakesinkutils.c index 46ac983..137c061 100644 --- a/subprojects/gst-plugins-bad/gst/debugutils/gstfakesinkutils.c +++ b/subprojects/gst-plugins-bad/gst/debugutils/gstfakesinkutils.c @@ -24,22 +24,20 @@ /* TODO complete the types */ void -gst_fake_sink_proxy_properties (GstElement * self, - GstElement * child, guint property_id_offset) +gst_util_proxy_class_properties (GObjectClass * object_class, + GObjectClass * target_class, guint property_id_offset) { - GObjectClass *object_class; GParamSpec **properties; guint n_properties, i; - object_class = G_OBJECT_CLASS (GST_ELEMENT_GET_CLASS (self)); - properties = g_object_class_list_properties (G_OBJECT_GET_CLASS (child), + properties = g_object_class_list_properties (G_OBJECT_CLASS (target_class), &n_properties); for (i = 0; i < n_properties; i++) { guint property_id = i + property_id_offset; - if (properties[i]->owner_type != G_OBJECT_TYPE (child) && - properties[i]->owner_type != GST_TYPE_BASE_SINK) + if (properties[i]->owner_type == G_TYPE_OBJECT + || properties[i]->owner_type == GST_TYPE_OBJECT) continue; if (G_IS_PARAM_SPEC_BOOLEAN (properties[i])) { diff --git a/subprojects/gst-plugins-bad/gst/debugutils/gstfakesinkutils.h b/subprojects/gst-plugins-bad/gst/debugutils/gstfakesinkutils.h index ca8231f..62760b4 100644 --- a/subprojects/gst-plugins-bad/gst/debugutils/gstfakesinkutils.h +++ b/subprojects/gst-plugins-bad/gst/debugutils/gstfakesinkutils.h @@ -26,7 +26,10 @@ G_BEGIN_DECLS -void gst_fake_sink_proxy_properties (GstElement * self, GstElement * child, guint property_id_offset); +void +gst_util_proxy_class_properties (GObjectClass *object_class, + GObjectClass *target_class, + guint property_id_offset); G_END_DECLS diff --git a/subprojects/gst-plugins-bad/gst/debugutils/gstfakevideosink.c b/subprojects/gst-plugins-bad/gst/debugutils/gstfakevideosink.c index 4e47e69..2cb683d 100644 --- a/subprojects/gst-plugins-bad/gst/debugutils/gstfakevideosink.c +++ b/subprojects/gst-plugins-bad/gst/debugutils/gstfakevideosink.c @@ -70,10 +70,78 @@ gst_fake_video_sink_allocation_meta_flags_get_type (void) return id; } +typedef enum +{ + FAKE_SINK_STATE_ERROR_NONE = 0, + FAKE_SINK_STATE_ERROR_NULL_READY, + FAKE_SINK_STATE_ERROR_READY_PAUSED, + FAKE_SINK_STATE_ERROR_PAUSED_PLAYING, + FAKE_SINK_STATE_ERROR_PLAYING_PAUSED, + FAKE_SINK_STATE_ERROR_PAUSED_READY, + FAKE_SINK_STATE_ERROR_READY_NULL +} GstFakeSinkStateError; + +#define DEFAULT_DROP_OUT_OF_SEGMENT TRUE +#define DEFAULT_STATE_ERROR FAKE_SINK_STATE_ERROR_NONE +#define DEFAULT_SILENT TRUE +#define DEFAULT_DUMP FALSE +#define DEFAULT_SIGNAL_HANDOFFS FALSE +#define DEFAULT_LAST_MESSAGE NULL +#define DEFAULT_CAN_ACTIVATE_PUSH TRUE +#define DEFAULT_CAN_ACTIVATE_PULL FALSE +#define DEFAULT_NUM_BUFFERS -1 + +/** + * GstFakeVideoSinkStateError: + * + * Proxy for GstFakeSinkError. + * + * Since: 1.22 + */ + +#define GST_TYPE_FAKE_VIDEO_SINK_STATE_ERROR (gst_fake_video_sink_state_error_get_type()) +static GType +gst_fake_video_sink_state_error_get_type (void) +{ + static GType fakevideosink_state_error_type = 0; + static const GEnumValue fakevideosink_state_error[] = { + {FAKE_SINK_STATE_ERROR_NONE, "No state change errors", "none"}, + {FAKE_SINK_STATE_ERROR_NULL_READY, + "Fail state change from NULL to READY", "null-to-ready"}, + {FAKE_SINK_STATE_ERROR_READY_PAUSED, + "Fail state change from READY to PAUSED", "ready-to-paused"}, + {FAKE_SINK_STATE_ERROR_PAUSED_PLAYING, + "Fail state change from PAUSED to PLAYING", "paused-to-playing"}, + {FAKE_SINK_STATE_ERROR_PLAYING_PAUSED, + "Fail state change from PLAYING to PAUSED", "playing-to-paused"}, + {FAKE_SINK_STATE_ERROR_PAUSED_READY, + "Fail state change from PAUSED to READY", "paused-to-ready"}, + {FAKE_SINK_STATE_ERROR_READY_NULL, + "Fail state change from READY to NULL", "ready-to-null"}, + {0, NULL, NULL}, + }; + + if (!fakevideosink_state_error_type) { + fakevideosink_state_error_type = + g_enum_register_static ("GstFakeVideoSinkStateError", + fakevideosink_state_error); + } + return fakevideosink_state_error_type; +} + enum { PROP_0, PROP_ALLOCATION_META_FLAGS, + PROP_STATE_ERROR, + PROP_SILENT, + PROP_DUMP, + PROP_SIGNAL_HANDOFFS, + PROP_DROP_OUT_OF_SEGMENT, + PROP_LAST_MESSAGE, + PROP_CAN_ACTIVATE_PUSH, + PROP_CAN_ACTIVATE_PULL, + PROP_NUM_BUFFERS, PROP_LAST }; @@ -86,6 +154,8 @@ enum static guint gst_fake_video_sink_signals[LAST_SIGNAL] = { 0 }; +static GParamSpec *pspec_last_message = NULL; + #define ALLOCATION_META_DEFAULT_FLAGS GST_ALLOCATION_FLAG_CROP_META | GST_ALLOCATION_FLAG_OVERLAY_COMPOSITION_META static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", @@ -137,18 +207,6 @@ gst_fake_video_sink_query (GstPad * pad, GstObject * parent, GstQuery * query) } static void -gst_fake_video_sink_proxy_properties (GstFakeVideoSink * self, - GstElement * child) -{ - static gsize initialized = 0; - - if (g_once_init_enter (&initialized)) { - gst_fake_sink_proxy_properties (GST_ELEMENT_CAST (self), child, PROP_LAST); - g_once_init_leave (&initialized, 1); - } -} - -static void gst_fake_video_sink_proxy_handoff (GstElement * element, GstBuffer * buffer, GstPad * pad, GstFakeVideoSink * self) { @@ -157,6 +215,12 @@ gst_fake_video_sink_proxy_handoff (GstElement * element, GstBuffer * buffer, } static void +gst_fake_video_sink_proxy_last_message (GstElement * element) +{ + g_object_notify_by_pspec ((GObject *) element, pspec_last_message); +} + +static void gst_fake_video_sink_proxy_preroll_handoff (GstElement * element, GstBuffer * buffer, GstPad * pad, GstFakeVideoSink * self) { @@ -195,7 +259,8 @@ gst_fake_video_sink_init (GstFakeVideoSink * self) self->child = child; - gst_fake_video_sink_proxy_properties (self, child); + g_signal_connect (child, "notify::last-message", + G_CALLBACK (gst_fake_video_sink_proxy_last_message), self); g_signal_connect (child, "handoff", G_CALLBACK (gst_fake_video_sink_proxy_handoff), self); g_signal_connect (child, "preroll-handoff", @@ -247,6 +312,7 @@ gst_fake_video_sink_class_init (GstFakeVideoSinkClass * klass) { GstElementClass *element_class = GST_ELEMENT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass); + GObjectClass *base_sink_class; object_class->get_property = gst_fake_video_sink_get_property; object_class->set_property = gst_fake_video_sink_set_property; @@ -270,7 +336,6 @@ gst_fake_video_sink_class_init (GstFakeVideoSinkClass * klass) ALLOCATION_META_DEFAULT_FLAGS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - /** * GstFakeVideoSink::handoff: * @fakevideosink: the fakevideosink instance @@ -303,6 +368,53 @@ gst_fake_video_sink_class_init (GstFakeVideoSinkClass * klass) preroll_handoff), NULL, NULL, NULL, G_TYPE_NONE, 2, GST_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE, GST_TYPE_PAD); + g_object_class_install_property (object_class, PROP_STATE_ERROR, + g_param_spec_enum ("state-error", "State Error", + "Generate a state change error", GST_TYPE_FAKE_VIDEO_SINK_STATE_ERROR, + DEFAULT_STATE_ERROR, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + pspec_last_message = g_param_spec_string ("last-message", "Last Message", + "The message describing current status", DEFAULT_LAST_MESSAGE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_LAST_MESSAGE, + pspec_last_message); + g_object_class_install_property (object_class, PROP_SIGNAL_HANDOFFS, + g_param_spec_boolean ("signal-handoffs", "Signal handoffs", + "Send a signal before unreffing the buffer", DEFAULT_SIGNAL_HANDOFFS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_DROP_OUT_OF_SEGMENT, + g_param_spec_boolean ("drop-out-of-segment", + "Drop out-of-segment buffers", + "Drop and don't render / hand off out-of-segment buffers", + DEFAULT_DROP_OUT_OF_SEGMENT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_SILENT, + g_param_spec_boolean ("silent", "Silent", + "Don't produce last_message events", DEFAULT_SILENT, + G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_DUMP, + g_param_spec_boolean ("dump", "Dump", "Dump buffer contents to stdout", + DEFAULT_DUMP, + G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_CAN_ACTIVATE_PUSH, + g_param_spec_boolean ("can-activate-push", "Can activate push", + "Can activate in push mode", DEFAULT_CAN_ACTIVATE_PUSH, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_CAN_ACTIVATE_PULL, + g_param_spec_boolean ("can-activate-pull", "Can activate pull", + "Can activate in pull mode", DEFAULT_CAN_ACTIVATE_PULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_NUM_BUFFERS, + g_param_spec_int ("num-buffers", "num-buffers", + "Number of buffers to accept going EOS", -1, G_MAXINT, + DEFAULT_NUM_BUFFERS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + base_sink_class = g_type_class_ref (GST_TYPE_BASE_SINK); + gst_util_proxy_class_properties (object_class, base_sink_class, PROP_LAST); + g_type_class_unref (base_sink_class); + gst_type_mark_as_plugin_api (GST_TYPE_FAKE_VIDEO_SINK_ALLOCATION_META_FLAGS, 0); + gst_type_mark_as_plugin_api (GST_TYPE_FAKE_VIDEO_SINK_STATE_ERROR, 0); } -- 2.7.4