mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 16:50:47 +00:00
goom: port goom
This commit is contained in:
parent
710fa239d5
commit
9290baba06
2 changed files with 114 additions and 107 deletions
|
@ -1,6 +1,7 @@
|
|||
/* gstgoom.c: implementation of goom drawing element
|
||||
* Copyright (C) <2001> Richard Boulton <richard@tartarus.org>
|
||||
* (C) <2006> Wim Taymans <wim at fluendo dot com>
|
||||
* (C) <2011> Wim Taymans <wim.taymans at gmail dot com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
|
@ -86,9 +87,6 @@ static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
|
|||
);
|
||||
|
||||
|
||||
static void gst_goom_class_init (GstGoomClass * klass);
|
||||
static void gst_goom_base_init (GstGoomClass * klass);
|
||||
static void gst_goom_init (GstGoom * goom);
|
||||
static void gst_goom_finalize (GObject * object);
|
||||
|
||||
static GstStateChangeReturn gst_goom_change_state (GstElement * element,
|
||||
|
@ -100,48 +98,8 @@ static gboolean gst_goom_sink_event (GstPad * pad, GstEvent * event);
|
|||
|
||||
static gboolean gst_goom_src_query (GstPad * pad, GstQuery * query);
|
||||
|
||||
static gboolean gst_goom_sink_setcaps (GstPad * pad, GstCaps * caps);
|
||||
static gboolean gst_goom_src_setcaps (GstPad * pad, GstCaps * caps);
|
||||
|
||||
static GstElementClass *parent_class = NULL;
|
||||
|
||||
GType
|
||||
gst_goom_get_type (void)
|
||||
{
|
||||
static GType type = 0;
|
||||
|
||||
if (!type) {
|
||||
static const GTypeInfo info = {
|
||||
sizeof (GstGoomClass),
|
||||
(GBaseInitFunc) gst_goom_base_init,
|
||||
NULL,
|
||||
(GClassInitFunc) gst_goom_class_init,
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof (GstGoom),
|
||||
0,
|
||||
(GInstanceInitFunc) gst_goom_init,
|
||||
};
|
||||
|
||||
type = g_type_register_static (GST_TYPE_ELEMENT, "GstGoom", &info, 0);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_goom_base_init (GstGoomClass * klass)
|
||||
{
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||
|
||||
gst_element_class_set_details_simple (element_class, "GOOM: what a GOOM!",
|
||||
"Visualization",
|
||||
"Takes frames of data and outputs video frames using the GOOM filter",
|
||||
"Wim Taymans <wim@fluendo.com>");
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&sink_template));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&src_template));
|
||||
}
|
||||
#define gst_goom_parent_class parent_class
|
||||
G_DEFINE_TYPE (GstGoom, gst_goom, GST_TYPE_ELEMENT);
|
||||
|
||||
static void
|
||||
gst_goom_class_init (GstGoomClass * klass)
|
||||
|
@ -152,10 +110,17 @@ gst_goom_class_init (GstGoomClass * klass)
|
|||
gobject_class = (GObjectClass *) klass;
|
||||
gstelement_class = (GstElementClass *) klass;
|
||||
|
||||
parent_class = g_type_class_peek_parent (klass);
|
||||
|
||||
gobject_class->finalize = gst_goom_finalize;
|
||||
|
||||
gst_element_class_set_details_simple (gstelement_class, "GOOM: what a GOOM!",
|
||||
"Visualization",
|
||||
"Takes frames of data and outputs video frames using the GOOM filter",
|
||||
"Wim Taymans <wim@fluendo.com>");
|
||||
gst_element_class_add_pad_template (gstelement_class,
|
||||
gst_static_pad_template_get (&sink_template));
|
||||
gst_element_class_add_pad_template (gstelement_class,
|
||||
gst_static_pad_template_get (&src_template));
|
||||
|
||||
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_goom_change_state);
|
||||
}
|
||||
|
||||
|
@ -168,13 +133,9 @@ gst_goom_init (GstGoom * goom)
|
|||
GST_DEBUG_FUNCPTR (gst_goom_chain));
|
||||
gst_pad_set_event_function (goom->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_goom_sink_event));
|
||||
gst_pad_set_setcaps_function (goom->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_goom_sink_setcaps));
|
||||
gst_element_add_pad (GST_ELEMENT (goom), goom->sinkpad);
|
||||
|
||||
goom->srcpad = gst_pad_new_from_static_template (&src_template, "src");
|
||||
gst_pad_set_setcaps_function (goom->srcpad,
|
||||
GST_DEBUG_FUNCPTR (gst_goom_src_setcaps));
|
||||
gst_pad_set_event_function (goom->srcpad,
|
||||
GST_DEBUG_FUNCPTR (gst_goom_src_event));
|
||||
gst_pad_set_query_function (goom->srcpad,
|
||||
|
@ -203,6 +164,8 @@ gst_goom_finalize (GObject * object)
|
|||
goom->plugin = NULL;
|
||||
|
||||
g_object_unref (goom->adapter);
|
||||
if (goom->pool)
|
||||
gst_object_unref (goom->pool);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
@ -220,14 +183,11 @@ gst_goom_reset (GstGoom * goom)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_goom_sink_setcaps (GstPad * pad, GstCaps * caps)
|
||||
gst_goom_sink_setcaps (GstGoom * goom, GstCaps * caps)
|
||||
{
|
||||
GstGoom *goom;
|
||||
GstStructure *structure;
|
||||
gboolean res;
|
||||
|
||||
goom = GST_GOOM (GST_PAD_PARENT (pad));
|
||||
|
||||
structure = gst_caps_get_structure (caps, 0);
|
||||
|
||||
res = gst_structure_get_int (structure, "channels", &goom->channels);
|
||||
|
@ -235,24 +195,21 @@ gst_goom_sink_setcaps (GstPad * pad, GstCaps * caps)
|
|||
|
||||
goom->bps = goom->channels * sizeof (gint16);
|
||||
|
||||
return res;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_goom_src_setcaps (GstPad * pad, GstCaps * caps)
|
||||
gst_goom_src_setcaps (GstGoom * goom, GstCaps * caps)
|
||||
{
|
||||
GstGoom *goom;
|
||||
GstStructure *structure;
|
||||
|
||||
goom = GST_GOOM (GST_PAD_PARENT (pad));
|
||||
gboolean res;
|
||||
|
||||
structure = gst_caps_get_structure (caps, 0);
|
||||
|
||||
if (!gst_structure_get_int (structure, "width", &goom->width) ||
|
||||
!gst_structure_get_int (structure, "height", &goom->height) ||
|
||||
!gst_structure_get_fraction (structure, "framerate", &goom->fps_n,
|
||||
&goom->fps_d))
|
||||
return FALSE;
|
||||
goto error;
|
||||
|
||||
goom_set_resolution (goom->plugin, goom->width, goom->height);
|
||||
|
||||
|
@ -266,32 +223,46 @@ gst_goom_src_setcaps (GstPad * pad, GstCaps * caps)
|
|||
GST_DEBUG_OBJECT (goom, "dimension %dx%d, framerate %d/%d, spf %d",
|
||||
goom->width, goom->height, goom->fps_n, goom->fps_d, goom->spf);
|
||||
|
||||
return TRUE;
|
||||
res = gst_pad_push_event (goom->srcpad, gst_event_new_caps (caps));
|
||||
|
||||
return res;
|
||||
|
||||
/* ERRORS */
|
||||
error:
|
||||
{
|
||||
GST_DEBUG_OBJECT (goom, "error parsing caps");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_goom_src_negotiate (GstGoom * goom)
|
||||
{
|
||||
gboolean res;
|
||||
GstCaps *othercaps, *target;
|
||||
GstStructure *structure;
|
||||
const GstCaps *templ;
|
||||
GstCaps *templ;
|
||||
GstQuery *query;
|
||||
GstBufferPool *pool = NULL;
|
||||
guint size, min, max, prefix, alignment;
|
||||
|
||||
templ = gst_pad_get_pad_template_caps (goom->srcpad);
|
||||
|
||||
GST_DEBUG_OBJECT (goom, "performing negotiation");
|
||||
|
||||
/* see what the peer can do */
|
||||
othercaps = gst_pad_peer_get_caps (goom->srcpad);
|
||||
othercaps = gst_pad_peer_get_caps (goom->srcpad, NULL);
|
||||
if (othercaps) {
|
||||
target = gst_caps_intersect (othercaps, templ);
|
||||
gst_caps_unref (othercaps);
|
||||
gst_caps_unref (templ);
|
||||
|
||||
if (gst_caps_is_empty (target))
|
||||
goto no_format;
|
||||
|
||||
gst_caps_truncate (target);
|
||||
} else {
|
||||
target = gst_caps_ref ((GstCaps *) templ);
|
||||
target = templ;
|
||||
}
|
||||
|
||||
structure = gst_caps_get_structure (target, 0);
|
||||
|
@ -300,7 +271,42 @@ gst_goom_src_negotiate (GstGoom * goom)
|
|||
gst_structure_fixate_field_nearest_fraction (structure, "framerate",
|
||||
DEFAULT_FPS_N, DEFAULT_FPS_D);
|
||||
|
||||
gst_pad_set_caps (goom->srcpad, target);
|
||||
res = gst_goom_src_setcaps (goom, target);
|
||||
|
||||
/* try to get a bufferpool now */
|
||||
/* find a pool for the negotiated caps now */
|
||||
query = gst_query_new_allocation (target, TRUE);
|
||||
|
||||
if (gst_pad_peer_query (goom->srcpad, query)) {
|
||||
/* we got configuration from our peer, parse them */
|
||||
gst_query_parse_allocation_params (query, &size, &min, &max, &prefix,
|
||||
&alignment, &pool);
|
||||
} else {
|
||||
size = goom->outsize;
|
||||
min = max = 0;
|
||||
prefix = 0;
|
||||
alignment = 1;
|
||||
}
|
||||
|
||||
if (pool == NULL) {
|
||||
GstStructure *config;
|
||||
|
||||
/* we did not get a pool, make one ourselves then */
|
||||
pool = gst_buffer_pool_new ();
|
||||
|
||||
config = gst_buffer_pool_get_config (pool);
|
||||
gst_buffer_pool_config_set (config, target, size, min, max, prefix, 0,
|
||||
alignment);
|
||||
gst_buffer_pool_set_config (pool, config);
|
||||
}
|
||||
|
||||
if (goom->pool)
|
||||
gst_object_unref (goom->pool);
|
||||
goom->pool = pool;
|
||||
|
||||
/* and activate */
|
||||
gst_buffer_pool_set_active (pool, TRUE);
|
||||
|
||||
gst_caps_unref (target);
|
||||
|
||||
return TRUE;
|
||||
|
@ -327,7 +333,7 @@ gst_goom_src_event (GstPad * pad, GstEvent * event)
|
|||
GstClockTimeDiff diff;
|
||||
GstClockTime timestamp;
|
||||
|
||||
gst_event_parse_qos (event, &proportion, &diff, ×tamp);
|
||||
gst_event_parse_qos (event, NULL, &proportion, &diff, ×tamp);
|
||||
|
||||
/* save stuff for the _chain() function */
|
||||
GST_OBJECT_LOCK (goom);
|
||||
|
@ -361,6 +367,14 @@ gst_goom_sink_event (GstPad * pad, GstEvent * event)
|
|||
goom = GST_GOOM (gst_pad_get_parent (pad));
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_CAPS:
|
||||
{
|
||||
GstCaps *caps;
|
||||
|
||||
gst_event_parse_caps (event, &caps);
|
||||
res = gst_goom_sink_setcaps (goom, caps);
|
||||
break;
|
||||
}
|
||||
case GST_EVENT_FLUSH_START:
|
||||
res = gst_pad_push_event (goom->srcpad, event);
|
||||
break;
|
||||
|
@ -368,22 +382,12 @@ gst_goom_sink_event (GstPad * pad, GstEvent * event)
|
|||
gst_goom_reset (goom);
|
||||
res = gst_pad_push_event (goom->srcpad, event);
|
||||
break;
|
||||
case GST_EVENT_NEWSEGMENT:
|
||||
case GST_EVENT_SEGMENT:
|
||||
{
|
||||
GstFormat format;
|
||||
gdouble rate, arate;
|
||||
gint64 start, stop, time;
|
||||
gboolean update;
|
||||
|
||||
/* the newsegment values are used to clip the input samples
|
||||
* and to convert the incomming timestamps to running time so
|
||||
* we can do QoS */
|
||||
gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
|
||||
&start, &stop, &time);
|
||||
|
||||
/* now configure the values */
|
||||
gst_segment_set_newsegment_full (&goom->segment, update,
|
||||
rate, arate, format, start, stop, time);
|
||||
gst_event_copy_segment (event, &goom->segment);
|
||||
|
||||
res = gst_pad_push_event (goom->srcpad, event);
|
||||
break;
|
||||
|
@ -454,29 +458,26 @@ gst_goom_src_query (GstPad * pad, GstQuery * query)
|
|||
return res;
|
||||
}
|
||||
|
||||
/* make sure we are negotiated */
|
||||
static GstFlowReturn
|
||||
get_buffer (GstGoom * goom, GstBuffer ** outbuf)
|
||||
ensure_negotiated (GstGoom * goom)
|
||||
{
|
||||
GstFlowReturn ret;
|
||||
gboolean reconfigure;
|
||||
|
||||
if (GST_PAD_CAPS (goom->srcpad) == NULL) {
|
||||
GST_OBJECT_LOCK (goom->srcpad);
|
||||
reconfigure = GST_PAD_NEEDS_RECONFIGURE (goom->srcpad);
|
||||
GST_OBJECT_FLAG_UNSET (goom->srcpad, GST_PAD_NEED_RECONFIGURE);
|
||||
GST_OBJECT_UNLOCK (goom->srcpad);
|
||||
|
||||
/* we don't know an output format yet, pick one */
|
||||
if (reconfigure || !gst_pad_has_current_caps (goom->srcpad)) {
|
||||
if (!gst_goom_src_negotiate (goom))
|
||||
return GST_FLOW_NOT_NEGOTIATED;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (goom, "allocating output buffer with caps %"
|
||||
GST_PTR_FORMAT, GST_PAD_CAPS (goom->srcpad));
|
||||
|
||||
ret =
|
||||
gst_pad_alloc_buffer_and_set_caps (goom->srcpad,
|
||||
GST_BUFFER_OFFSET_NONE, goom->outsize,
|
||||
GST_PAD_CAPS (goom->srcpad), outbuf);
|
||||
if (ret != GST_FLOW_OK)
|
||||
return ret;
|
||||
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
|
||||
static GstFlowReturn
|
||||
gst_goom_chain (GstPad * pad, GstBuffer * buffer)
|
||||
{
|
||||
|
@ -490,14 +491,11 @@ gst_goom_chain (GstPad * pad, GstBuffer * buffer)
|
|||
goto beach;
|
||||
}
|
||||
|
||||
/* If we don't have an output format yet, preallocate a buffer to try and
|
||||
* set one */
|
||||
if (GST_PAD_CAPS (goom->srcpad) == NULL) {
|
||||
ret = get_buffer (goom, &outbuf);
|
||||
if (ret != GST_FLOW_OK) {
|
||||
gst_buffer_unref (buffer);
|
||||
goto beach;
|
||||
}
|
||||
/* Make sure have an output format */
|
||||
ret = ensure_negotiated (goom);
|
||||
if (ret != GST_FLOW_OK) {
|
||||
gst_buffer_unref (buffer);
|
||||
goto beach;
|
||||
}
|
||||
|
||||
/* don't try to combine samples from discont buffer */
|
||||
|
@ -507,7 +505,7 @@ gst_goom_chain (GstPad * pad, GstBuffer * buffer)
|
|||
|
||||
GST_DEBUG_OBJECT (goom,
|
||||
"Input buffer has %d samples, time=%" G_GUINT64_FORMAT,
|
||||
GST_BUFFER_SIZE (buffer) / goom->bps, GST_BUFFER_TIMESTAMP (buffer));
|
||||
gst_buffer_get_size (buffer) / goom->bps, GST_BUFFER_TIMESTAMP (buffer));
|
||||
|
||||
/* Collect samples until we have enough for an output frame */
|
||||
gst_adapter_push (goom->adapter, buffer);
|
||||
|
@ -565,7 +563,7 @@ gst_goom_chain (GstPad * pad, GstBuffer * buffer)
|
|||
|
||||
/* get next GOOM_SAMPLES, we have at least this amount of samples */
|
||||
data =
|
||||
(const guint16 *) gst_adapter_peek (goom->adapter,
|
||||
(const guint16 *) gst_adapter_map (goom->adapter,
|
||||
GOOM_SAMPLES * goom->bps);
|
||||
|
||||
if (goom->channels == 2) {
|
||||
|
@ -583,18 +581,21 @@ gst_goom_chain (GstPad * pad, GstBuffer * buffer)
|
|||
/* alloc a buffer if we don't have one yet, this happens
|
||||
* when we pushed a buffer in this while loop before */
|
||||
if (outbuf == NULL) {
|
||||
ret = get_buffer (goom, &outbuf);
|
||||
GST_DEBUG_OBJECT (goom, "allocating output buffer");
|
||||
ret = gst_buffer_pool_acquire_buffer (goom->pool, &outbuf, NULL);
|
||||
if (ret != GST_FLOW_OK) {
|
||||
gst_adapter_unmap (goom->adapter, 0);
|
||||
goto beach;
|
||||
}
|
||||
}
|
||||
|
||||
GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
|
||||
GST_BUFFER_DURATION (outbuf) = goom->duration;
|
||||
GST_BUFFER_SIZE (outbuf) = goom->outsize;
|
||||
|
||||
out_frame = (guchar *) goom_update (goom->plugin, goom->datain, 0, 0);
|
||||
memcpy (GST_BUFFER_DATA (outbuf), out_frame, goom->outsize);
|
||||
gst_buffer_fill (outbuf, 0, out_frame, goom->outsize);
|
||||
|
||||
gst_adapter_unmap (goom->adapter, 0);
|
||||
|
||||
GST_DEBUG ("Pushing frame with time=%" GST_TIME_FORMAT ", duration=%"
|
||||
GST_TIME_FORMAT, GST_TIME_ARGS (timestamp),
|
||||
|
@ -645,6 +646,11 @@ gst_goom_change_state (GstElement * element, GstStateChange transition)
|
|||
|
||||
switch (transition) {
|
||||
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
||||
if (goom->pool) {
|
||||
gst_buffer_pool_set_active (goom->pool, FALSE);
|
||||
gst_object_unref (goom->pool);
|
||||
goom->pool = NULL;
|
||||
}
|
||||
break;
|
||||
case GST_STATE_CHANGE_READY_TO_NULL:
|
||||
break;
|
||||
|
|
|
@ -57,6 +57,7 @@ struct _GstGoom
|
|||
gint height;
|
||||
GstClockTime duration;
|
||||
guint outsize;
|
||||
GstBufferPool *pool;
|
||||
|
||||
/* samples per frame */
|
||||
guint spf;
|
||||
|
|
Loading…
Reference in a new issue