frei0r: Port to 1.0

https://bugzilla.gnome.org/show_bug.cgi?id=681678
This commit is contained in:
Nicolas Dufresne 2012-09-28 11:59:57 -04:00 committed by Olivier Crête
parent 75dba03688
commit 9a2735a063
7 changed files with 223 additions and 300 deletions

View file

@ -313,7 +313,7 @@ dnl Make sure you have a space before and after all plugins
GST_PLUGINS_NONPORTED=" aiff \ GST_PLUGINS_NONPORTED=" aiff \
cdxaparse \ cdxaparse \
dccp faceoverlay \ dccp faceoverlay \
fieldanalysis freeverb frei0r \ fieldanalysis freeverb \
hdvparse ivfparse jp2kdecimator \ hdvparse ivfparse jp2kdecimator \
kate librfb \ kate librfb \
mpegpsmux mve mxf mythtv nsf nuvdemux \ mpegpsmux mve mxf mythtv nsf nuvdemux \

View file

@ -27,20 +27,17 @@
#include "gstfrei0rmixer.h" #include "gstfrei0rmixer.h"
#include <string.h> #include <string.h>
#include <gmodule.h>
GST_DEBUG_CATEGORY (frei0r_debug); GST_DEBUG_CATEGORY (frei0r_debug);
#define GST_CAT_DEFAULT frei0r_debug #define GST_CAT_DEFAULT frei0r_debug
static GstStaticCaps bgra8888_caps = GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRA); static GstStaticCaps bgra8888_caps = GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE
static GstStaticCaps rgba8888_caps = GST_STATIC_CAPS (GST_VIDEO_CAPS_RGBA); ("BGRA"));
static GstStaticCaps packed32_caps = GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRA " ; " static GstStaticCaps rgba8888_caps = GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE
GST_VIDEO_CAPS_RGBA " ; " ("RGBA"));
GST_VIDEO_CAPS_ABGR " ; " static GstStaticCaps packed32_caps = GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE
GST_VIDEO_CAPS_ARGB " ; " ("{ BGRA, RGBA, ABGR, ARGB, BGRx, RGBx, xBGR, xRGB, AYUV }"));
GST_VIDEO_CAPS_BGRx " ; "
GST_VIDEO_CAPS_RGBx " ; "
GST_VIDEO_CAPS_xBGR " ; "
GST_VIDEO_CAPS_xRGB " ; " GST_VIDEO_CAPS_YUV ("AYUV"));
GstCaps * GstCaps *
gst_frei0r_caps_from_color_model (gint color_model) gst_frei0r_caps_from_color_model (gint color_model)

View file

@ -26,8 +26,6 @@
#include "gstfrei0r.h" #include "gstfrei0r.h"
#include "gstfrei0rfilter.h" #include "gstfrei0rfilter.h"
#include <gst/controller/gstcontroller.h>
GST_DEBUG_CATEGORY_EXTERN (frei0r_debug); GST_DEBUG_CATEGORY_EXTERN (frei0r_debug);
#define GST_CAT_DEFAULT frei0r_debug #define GST_CAT_DEFAULT frei0r_debug
@ -42,11 +40,15 @@ gst_frei0r_filter_set_caps (GstBaseTransform * trans, GstCaps * incaps,
GstCaps * outcaps) GstCaps * outcaps)
{ {
GstFrei0rFilter *self = GST_FREI0R_FILTER (trans); GstFrei0rFilter *self = GST_FREI0R_FILTER (trans);
GstVideoFormat fmt; GstVideoInfo info;
if (!gst_video_format_parse_caps (incaps, &fmt, &self->width, &self->height)) gst_video_info_init (&info);
if (!gst_video_info_from_caps (&info, incaps))
return FALSE; return FALSE;
self->width = info.width;
self->height = info.height;
return TRUE; return TRUE;
} }
@ -91,6 +93,7 @@ gst_frei0r_filter_transform (GstBaseTransform * trans, GstBuffer * inbuf,
GstFrei0rFilter *self = GST_FREI0R_FILTER (trans); GstFrei0rFilter *self = GST_FREI0R_FILTER (trans);
GstFrei0rFilterClass *klass = GST_FREI0R_FILTER_GET_CLASS (trans); GstFrei0rFilterClass *klass = GST_FREI0R_FILTER_GET_CLASS (trans);
gdouble time; gdouble time;
GstMapInfo inmap, outmap;
if (G_UNLIKELY (self->width <= 0 || self->height <= 0)) if (G_UNLIKELY (self->width <= 0 || self->height <= 0))
return GST_FLOW_NOT_NEGOTIATED; return GST_FLOW_NOT_NEGOTIATED;
@ -106,14 +109,20 @@ gst_frei0r_filter_transform (GstBaseTransform * trans, GstBuffer * inbuf,
time = ((gdouble) GST_BUFFER_TIMESTAMP (inbuf)) / GST_SECOND; time = ((gdouble) GST_BUFFER_TIMESTAMP (inbuf)) / GST_SECOND;
GST_OBJECT_LOCK (self); GST_OBJECT_LOCK (self);
gst_buffer_map (inbuf, &inmap, GST_MAP_READ);
gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE);
if (klass->ftable->update2) if (klass->ftable->update2)
klass->ftable->update2 (self->f0r_instance, time, klass->ftable->update2 (self->f0r_instance, time,
(const guint32 *) GST_BUFFER_DATA (inbuf), NULL, NULL, (const guint32 *) inmap.data, NULL, NULL, (guint32 *) outmap.data);
(guint32 *) GST_BUFFER_DATA (outbuf));
else else
klass->ftable->update (self->f0r_instance, time, klass->ftable->update (self->f0r_instance, time,
(const guint32 *) GST_BUFFER_DATA (inbuf), (const guint32 *) inmap.data, (guint32 *) outmap.data);
(guint32 *) GST_BUFFER_DATA (outbuf));
gst_buffer_unmap (outbuf, &outmap);
gst_buffer_unmap (inbuf, &inmap);
GST_OBJECT_UNLOCK (self); GST_OBJECT_UNLOCK (self);
return GST_FLOW_OK; return GST_FLOW_OK;

View file

@ -26,8 +26,6 @@
#include "gstfrei0r.h" #include "gstfrei0r.h"
#include "gstfrei0rmixer.h" #include "gstfrei0rmixer.h"
#include <gst/controller/gstcontroller.h>
GST_DEBUG_CATEGORY_EXTERN (frei0r_debug); GST_DEBUG_CATEGORY_EXTERN (frei0r_debug);
#define GST_CAT_DEFAULT frei0r_debug #define GST_CAT_DEFAULT frei0r_debug
@ -54,11 +52,10 @@ gst_frei0r_mixer_reset (GstFrei0rMixer * self)
self->property_cache = NULL; self->property_cache = NULL;
gst_caps_replace (&self->caps, NULL); gst_caps_replace (&self->caps, NULL);
p_ev = &self->newseg_event; p_ev = &self->segment_event;
gst_event_replace (p_ev, NULL); gst_event_replace (p_ev, NULL);
self->fmt = GST_VIDEO_FORMAT_UNKNOWN; gst_video_info_init (&self->info);
self->width = self->height = 0;
} }
static void static void
@ -155,85 +152,74 @@ gst_frei0r_mixer_change_state (GstElement * element, GstStateChange transition)
} }
static GstCaps * static GstCaps *
gst_frei0r_mixer_get_caps (GstPad * pad) gst_frei0r_mixer_query_pad_caps (GstPad * pad, GstPad * skip, GstCaps * filter)
{
GstCaps *caps;
if (pad == skip)
return filter;
caps = gst_pad_peer_query_caps (pad, filter);
if (caps)
gst_caps_unref (filter);
else
caps = filter;
return caps;
}
static GstCaps *
gst_frei0r_mixer_get_caps (GstFrei0rMixer * self, GstPad * pad,
GstCaps * filter)
{ {
GstFrei0rMixer *self = GST_FREI0R_MIXER (gst_pad_get_parent (pad));
GstCaps *caps = NULL; GstCaps *caps = NULL;
if (self->caps) { if (self->caps) {
caps = gst_caps_ref (self->caps); caps = gst_caps_ref (self->caps);
} else { } else {
GstCaps *tmp, *tmp1; GstCaps *tmp;
tmp = gst_caps_copy (gst_pad_get_pad_template_caps (self->src));
tmp1 = gst_pad_peer_get_caps (pad);
if (tmp1) {
caps = gst_caps_intersect (tmp, tmp1);
gst_caps_unref (tmp1);
gst_caps_unref (tmp);
} else {
caps = tmp;
}
caps = gst_pad_get_pad_template_caps (self->src);
if (filter) {
tmp = caps; tmp = caps;
tmp1 = gst_pad_peer_get_caps (self->sink0); caps = gst_caps_intersect_full (tmp, filter, GST_CAPS_INTERSECT_FIRST);
if (tmp1) {
caps = gst_caps_intersect (tmp, tmp1);
gst_caps_unref (tmp); gst_caps_unref (tmp);
gst_caps_unref (tmp1);
} }
tmp = caps; caps = gst_frei0r_mixer_query_pad_caps (self->src, pad, caps);
tmp1 = gst_pad_peer_get_caps (self->sink1); caps = gst_frei0r_mixer_query_pad_caps (self->sink0, pad, caps);
if (tmp1) { caps = gst_frei0r_mixer_query_pad_caps (self->sink1, pad, caps);
caps = gst_caps_intersect (tmp, tmp1); if (self->sink2)
gst_caps_unref (tmp); caps = gst_frei0r_mixer_query_pad_caps (self->sink2, pad, caps);
gst_caps_unref (tmp1);
} }
if (self->sink2) {
tmp = caps;
tmp1 = gst_pad_peer_get_caps (self->sink2);
if (tmp1) {
caps = gst_caps_intersect (tmp, tmp1);
gst_caps_unref (tmp);
gst_caps_unref (tmp1);
}
}
}
gst_object_unref (self);
return caps; return caps;
} }
static gboolean static gboolean
gst_frei0r_mixer_set_caps (GstPad * pad, GstCaps * caps) gst_frei0r_mixer_set_caps (GstFrei0rMixer * self, GstPad * pad, GstCaps * caps)
{ {
GstFrei0rMixer *self = GST_FREI0R_MIXER (gst_pad_get_parent (pad));
gboolean ret = TRUE; gboolean ret = TRUE;
if (!self->caps) {
gst_caps_replace (&self->caps, caps); gst_caps_replace (&self->caps, caps);
if (pad != self->src) ret = gst_pad_set_caps (self->src, caps);
ret &= gst_pad_set_caps (self->src, caps);
if (pad != self->sink0)
ret &= gst_pad_set_caps (self->sink0, caps);
if (pad != self->sink1)
ret &= gst_pad_set_caps (self->sink1, caps);
if (pad != self->sink2 && self->sink2)
ret &= gst_pad_set_caps (self->sink2, caps);
if (ret) { if (ret) {
if (!gst_video_format_parse_caps (caps, &self->fmt, &self->width, GstVideoInfo info;
&self->height)) {
ret = FALSE;
goto out;
}
}
out:
gst_object_unref (self); gst_video_info_init (&info);
if (!gst_video_info_from_caps (&self->info, caps)) {
ret = FALSE;
}
}
} else if (!gst_caps_is_equal (caps, self->caps)) {
if (gst_pad_peer_query_accept_caps (pad, self->caps))
gst_pad_push_event (pad, gst_event_new_reconfigure ());
ret = FALSE;
}
return ret; return ret;
} }
@ -258,7 +244,7 @@ gst_frei0r_mixer_src_query_duration (GstFrei0rMixer * self, GstQuery * query)
it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (self)); it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (self));
while (!done) { while (!done) {
GstIteratorResult ires; GstIteratorResult ires;
gpointer item; GValue item = { 0 };
ires = gst_iterator_next (it, &item); ires = gst_iterator_next (it, &item);
switch (ires) { switch (ires) {
@ -267,11 +253,11 @@ gst_frei0r_mixer_src_query_duration (GstFrei0rMixer * self, GstQuery * query)
break; break;
case GST_ITERATOR_OK: case GST_ITERATOR_OK:
{ {
GstPad *pad = GST_PAD_CAST (item); GstPad *pad = g_value_get_object (&item);
gint64 duration; gint64 duration;
/* ask sink peer for duration */ /* ask sink peer for duration */
res &= gst_pad_query_peer_duration (pad, &format, &duration); res &= gst_pad_peer_query_duration (pad, format, &duration);
/* take min from all valid return values */ /* take min from all valid return values */
if (res) { if (res) {
/* valid unknown length, stop searching */ /* valid unknown length, stop searching */
@ -283,7 +269,7 @@ gst_frei0r_mixer_src_query_duration (GstFrei0rMixer * self, GstQuery * query)
else if (duration < min) else if (duration < min)
min = duration; min = duration;
} }
gst_object_unref (pad); g_value_reset (&item);
break; break;
} }
case GST_ITERATOR_RESYNC: case GST_ITERATOR_RESYNC:
@ -296,6 +282,8 @@ gst_frei0r_mixer_src_query_duration (GstFrei0rMixer * self, GstQuery * query)
done = TRUE; done = TRUE;
break; break;
} }
g_value_unset (&item);
} }
gst_iterator_free (it); gst_iterator_free (it);
@ -329,7 +317,7 @@ gst_frei0r_mixer_src_query_latency (GstFrei0rMixer * self, GstQuery * query)
it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (self)); it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (self));
while (!done) { while (!done) {
GstIteratorResult ires; GstIteratorResult ires;
gpointer item; GValue item = { 0 };
ires = gst_iterator_next (it, &item); ires = gst_iterator_next (it, &item);
switch (ires) { switch (ires) {
@ -338,7 +326,7 @@ gst_frei0r_mixer_src_query_latency (GstFrei0rMixer * self, GstQuery * query)
break; break;
case GST_ITERATOR_OK: case GST_ITERATOR_OK:
{ {
GstPad *pad = GST_PAD_CAST (item); GstPad *pad = g_value_get_object (&item);
GstQuery *peerquery; GstQuery *peerquery;
GstClockTime min_cur, max_cur; GstClockTime min_cur, max_cur;
gboolean live_cur; gboolean live_cur;
@ -364,7 +352,7 @@ gst_frei0r_mixer_src_query_latency (GstFrei0rMixer * self, GstQuery * query)
} }
gst_query_unref (peerquery); gst_query_unref (peerquery);
gst_object_unref (pad); g_value_reset (&item);
break; break;
} }
case GST_ITERATOR_RESYNC: case GST_ITERATOR_RESYNC:
@ -379,6 +367,8 @@ gst_frei0r_mixer_src_query_latency (GstFrei0rMixer * self, GstQuery * query)
done = TRUE; done = TRUE;
break; break;
} }
g_value_unset (&item);
} }
gst_iterator_free (it); gst_iterator_free (it);
@ -394,9 +384,9 @@ gst_frei0r_mixer_src_query_latency (GstFrei0rMixer * self, GstQuery * query)
} }
static gboolean static gboolean
gst_frei0r_mixer_src_query (GstPad * pad, GstQuery * query) gst_frei0r_mixer_src_query (GstPad * pad, GstObject * object, GstQuery * query)
{ {
GstFrei0rMixer *self = GST_FREI0R_MIXER (gst_pad_get_parent (pad)); GstFrei0rMixer *self = GST_FREI0R_MIXER (object);
gboolean ret = FALSE; gboolean ret = FALSE;
switch (GST_QUERY_TYPE (query)) { switch (GST_QUERY_TYPE (query)) {
@ -409,68 +399,50 @@ gst_frei0r_mixer_src_query (GstPad * pad, GstQuery * query)
case GST_QUERY_LATENCY: case GST_QUERY_LATENCY:
ret = gst_frei0r_mixer_src_query_latency (self, query); ret = gst_frei0r_mixer_src_query_latency (self, query);
break; break;
case GST_QUERY_CAPS:
{
GstCaps *filter, *caps;
gst_query_parse_caps (query, &filter);
caps = gst_frei0r_mixer_get_caps (self, pad, filter);
gst_query_set_caps_result (query, caps);
gst_caps_unref (caps);
break;
}
default: default:
ret = gst_pad_query_default (pad, query); ret = gst_pad_query_default (pad, GST_OBJECT (self), query);
break; break;
} }
gst_object_unref (self);
return ret; return ret;
} }
static gboolean static gboolean
gst_frei0r_mixer_sink_query (GstPad * pad, GstQuery * query) gst_frei0r_mixer_sink_query (GstCollectPads * pads, GstCollectData * cdata,
GstQuery * query, GstFrei0rMixer * self)
{ {
GstFrei0rMixer *self = GST_FREI0R_MIXER (gst_pad_get_parent (pad)); gboolean ret = TRUE;
gboolean ret = gst_pad_query (self->src, query);
gst_object_unref (self); switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_CAPS:
return ret; {
} GstCaps *filter, *caps;
gst_query_parse_caps (query, &filter);
static gboolean caps = gst_frei0r_mixer_get_caps (self, cdata->pad, filter);
forward_event_func (GstPad * pad, GValue * ret, GstEvent * event) gst_query_set_caps_result (query, caps);
{ gst_caps_unref (caps);
gst_event_ref (event); break;
GST_LOG_OBJECT (pad, "About to send event %s", GST_EVENT_TYPE_NAME (event));
if (!gst_pad_push_event (pad, event)) {
g_value_set_boolean (ret, FALSE);
GST_WARNING_OBJECT (pad, "Sending event %p (%s) failed.",
event, GST_EVENT_TYPE_NAME (event));
} else {
GST_LOG_OBJECT (pad, "Sent event %p (%s).",
event, GST_EVENT_TYPE_NAME (event));
} }
gst_object_unref (pad); default:
return TRUE; ret = gst_collect_pads_query_default (pads, cdata, query, FALSE);
break;
}
return ret;
} }
static gboolean static gboolean
forward_event (GstFrei0rMixer * self, GstEvent * event) gst_frei0r_mixer_src_event (GstPad * pad, GstObject * object, GstEvent * event)
{ {
GstIterator *it; GstFrei0rMixer *self = GST_FREI0R_MIXER (object);
GValue vret = { 0 };
GST_LOG_OBJECT (self, "Forwarding event %p (%s)", event,
GST_EVENT_TYPE_NAME (event));
g_value_init (&vret, G_TYPE_BOOLEAN);
g_value_set_boolean (&vret, TRUE);
it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (self));
gst_iterator_fold (it, (GstIteratorFoldFunction) forward_event_func, &vret,
event);
gst_iterator_free (it);
gst_event_unref (event);
return g_value_get_boolean (&vret);
}
static gboolean
gst_frei0r_mixer_src_event (GstPad * pad, GstEvent * event)
{
GstFrei0rMixer *self = GST_FREI0R_MIXER (gst_pad_get_parent (pad));
gboolean ret = FALSE; gboolean ret = FALSE;
switch (GST_EVENT_TYPE (event)) { switch (GST_EVENT_TYPE (event)) {
@ -495,48 +467,36 @@ gst_frei0r_mixer_src_event (GstPad * pad, GstEvent * event)
gst_pad_push_event (self->src, gst_event_new_flush_start ()); gst_pad_push_event (self->src, gst_event_new_flush_start ());
} }
ret = forward_event (self, event); ret = gst_pad_event_default (pad, GST_OBJECT (self), event);
break; break;
} }
case GST_EVENT_NAVIGATION:
/* navigation is rather pointless. */
ret = FALSE;
break;
default: default:
/* just forward the rest for now */ ret = gst_pad_event_default (pad, GST_OBJECT (self), event);
ret = forward_event (self, event);
break; break;
} }
gst_object_unref (self);
return ret; return ret;
} }
static gboolean static gboolean
gst_frei0r_mixer_sink0_event (GstPad * pad, GstEvent * event) gst_frei0r_mixer_sink_event (GstCollectPads * pads, GstCollectData * cdata,
GstEvent * event, GstFrei0rMixer * self)
{ {
GstFrei0rMixer *self = GST_FREI0R_MIXER (gst_pad_get_parent (pad)); gboolean ret = TRUE;
gboolean ret = FALSE;
GstEvent **p_ev;
GST_DEBUG ("Got %s event on pad %s:%s", GST_EVENT_TYPE_NAME (event),
GST_DEBUG_PAD_NAME (pad));
switch (GST_EVENT_TYPE (event)) { switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_NEWSEGMENT: case GST_EVENT_CAPS:
p_ev = &self->newseg_event; {
gst_event_replace (p_ev, event); GstCaps *caps;
break; gst_event_parse_caps (event, &caps);
default: ret = gst_frei0r_mixer_set_caps (self, cdata->pad, caps);
gst_event_unref (event);
break;
}
default:
ret = gst_collect_pads_event_default (pads, cdata, event, FALSE);
break; break;
} }
/* now GstCollectPads can take care of the rest, e.g. EOS */
ret = self->collect_event (pad, event);
gst_object_unref (self);
return ret; return ret;
} }
@ -551,28 +511,27 @@ gst_frei0r_mixer_collected (GstCollectPads * pads, GstFrei0rMixer * self)
GstClockTime timestamp; GstClockTime timestamp;
gdouble time; gdouble time;
GstSegment *segment = NULL; GstSegment *segment = NULL;
GstAllocationParams alloc_params = { 0, 31, 0, 0 };
GstMapInfo outmap, inmap0, inmap1, inmap2;
if (G_UNLIKELY (self->width <= 0 || self->height <= 0)) if (G_UNLIKELY (self->info.width <= 0 || self->info.height <= 0))
return GST_FLOW_NOT_NEGOTIATED; return GST_FLOW_NOT_NEGOTIATED;
if (G_UNLIKELY (!self->f0r_instance)) { if (G_UNLIKELY (!self->f0r_instance)) {
self->f0r_instance = self->f0r_instance = gst_frei0r_instance_construct (klass->ftable,
gst_frei0r_instance_construct (klass->ftable, klass->properties, klass->properties, klass->n_properties, self->property_cache,
klass->n_properties, self->property_cache, self->width, self->height); self->info.width, self->info.height);
if (G_UNLIKELY (!self->f0r_instance)) if (G_UNLIKELY (!self->f0r_instance))
return GST_FLOW_ERROR; return GST_FLOW_ERROR;
} }
if (self->newseg_event) { if (self->segment_event) {
gst_pad_push_event (self->src, self->newseg_event); gst_pad_push_event (self->src, self->segment_event);
self->newseg_event = NULL; self->segment_event = NULL;
} }
if ((ret = /* FIXME Request an allocator and/or pool */
gst_pad_alloc_buffer_and_set_caps (self->src, GST_BUFFER_OFFSET_NONE, outbuf = gst_buffer_new_allocate (NULL, self->info.size, &alloc_params);
gst_video_format_get_size (self->fmt, self->width, self->height),
GST_PAD_CAPS (self->src), &outbuf)) != GST_FLOW_OK)
return ret;
for (l = pads->data; l; l = l->next) { for (l = pads->data; l; l = l->next) {
GstCollectData *cdata = l->data; GstCollectData *cdata = l->data;
@ -590,8 +549,14 @@ gst_frei0r_mixer_collected (GstCollectPads * pads, GstFrei0rMixer * self)
if (!inbuf0 || !inbuf1 || (!inbuf2 && self->sink2)) if (!inbuf0 || !inbuf1 || (!inbuf2 && self->sink2))
goto eos; goto eos;
gst_buffer_map (outbuf, &outmap, GST_MAP_READWRITE);
gst_buffer_map (inbuf0, &inmap0, GST_MAP_READ);
gst_buffer_map (inbuf1, &inmap1, GST_MAP_READ);
if (inbuf2)
gst_buffer_map (inbuf2, &inmap2, GST_MAP_READ);
g_assert (segment != NULL); g_assert (segment != NULL);
timestamp = GST_BUFFER_TIMESTAMP (inbuf0); timestamp = GST_BUFFER_PTS (inbuf0);
timestamp = gst_segment_to_stream_time (segment, GST_FORMAT_TIME, timestamp); timestamp = gst_segment_to_stream_time (segment, GST_FORMAT_TIME, timestamp);
GST_DEBUG_OBJECT (self, "sync to %" GST_TIME_FORMAT, GST_DEBUG_OBJECT (self, "sync to %" GST_TIME_FORMAT,
@ -600,22 +565,25 @@ gst_frei0r_mixer_collected (GstCollectPads * pads, GstFrei0rMixer * self)
if (GST_CLOCK_TIME_IS_VALID (timestamp)) if (GST_CLOCK_TIME_IS_VALID (timestamp))
gst_object_sync_values (GST_OBJECT (self), timestamp); gst_object_sync_values (GST_OBJECT (self), timestamp);
gst_buffer_copy_metadata (outbuf, inbuf0, gst_buffer_copy_into (outbuf, inbuf0,
GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS); GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
time = ((gdouble) GST_BUFFER_TIMESTAMP (outbuf)) / GST_SECOND; time = ((gdouble) GST_BUFFER_PTS (outbuf)) / GST_SECOND;
GST_OBJECT_LOCK (self); GST_OBJECT_LOCK (self);
klass->ftable->update2 (self->f0r_instance, time, klass->ftable->update2 (self->f0r_instance, time,
(const guint32 *) GST_BUFFER_DATA (inbuf0), (const guint32 *) inmap0.data, (const guint32 *) inmap1.data,
(const guint32 *) GST_BUFFER_DATA (inbuf1), (inbuf2) ? (const guint32 *) inmap2.data : NULL, (guint32 *) outmap.data);
(inbuf2) ? (const guint32 *) GST_BUFFER_DATA (inbuf2) : NULL,
(guint32 *) GST_BUFFER_DATA (outbuf));
GST_OBJECT_UNLOCK (self); GST_OBJECT_UNLOCK (self);
gst_buffer_unmap (outbuf, &outmap);
gst_buffer_unref (inbuf0); gst_buffer_unref (inbuf0);
gst_buffer_unmap (inbuf0, &inmap0);
gst_buffer_unref (inbuf1); gst_buffer_unref (inbuf1);
if (inbuf2) gst_buffer_unmap (inbuf1, &inmap1);
if (inbuf2) {
gst_buffer_unmap (inbuf2, &inmap2);
gst_buffer_unref (inbuf2); gst_buffer_unref (inbuf2);
}
ret = gst_pad_push (self->src, outbuf); ret = gst_pad_push (self->src, outbuf);
@ -634,7 +602,7 @@ eos:
gst_buffer_unref (inbuf2); gst_buffer_unref (inbuf2);
gst_pad_push_event (self->src, gst_event_new_eos ()); gst_pad_push_event (self->src, gst_event_new_eos ());
return GST_FLOW_UNEXPECTED; return GST_FLOW_EOS;
} }
} }
@ -675,26 +643,22 @@ gst_frei0r_mixer_class_init (GstFrei0rMixerClass * klass,
gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
gst_caps_ref (caps)); gst_caps_ref (caps));
gst_element_class_add_pad_template (gstelement_class, templ); gst_element_class_add_pad_template (gstelement_class, templ);
gst_object_unref (templ);
templ = templ =
gst_pad_template_new ("sink_0", GST_PAD_SINK, GST_PAD_ALWAYS, gst_pad_template_new ("sink_0", GST_PAD_SINK, GST_PAD_ALWAYS,
gst_caps_ref (caps)); gst_caps_ref (caps));
gst_element_class_add_pad_template (gstelement_class, templ); gst_element_class_add_pad_template (gstelement_class, templ);
gst_object_unref (templ);
templ = templ =
gst_pad_template_new ("sink_1", GST_PAD_SINK, GST_PAD_ALWAYS, gst_pad_template_new ("sink_1", GST_PAD_SINK, GST_PAD_ALWAYS,
gst_caps_ref (caps)); gst_caps_ref (caps));
gst_element_class_add_pad_template (gstelement_class, templ); gst_element_class_add_pad_template (gstelement_class, templ);
gst_object_unref (templ);
if (klass->info->plugin_type == F0R_PLUGIN_TYPE_MIXER3) { if (klass->info->plugin_type == F0R_PLUGIN_TYPE_MIXER3) {
templ = templ =
gst_pad_template_new ("sink_2", GST_PAD_SINK, GST_PAD_ALWAYS, gst_pad_template_new ("sink_2", GST_PAD_SINK, GST_PAD_ALWAYS,
gst_caps_ref (caps)); gst_caps_ref (caps));
gst_element_class_add_pad_template (gstelement_class, templ); gst_element_class_add_pad_template (gstelement_class, templ);
gst_object_unref (templ);
} }
gst_caps_unref (caps); gst_caps_unref (caps);
@ -707,18 +671,19 @@ gst_frei0r_mixer_init (GstFrei0rMixer * self, GstFrei0rMixerClass * klass)
{ {
self->property_cache = self->property_cache =
gst_frei0r_property_cache_init (klass->properties, klass->n_properties); gst_frei0r_property_cache_init (klass->properties, klass->n_properties);
gst_video_info_init (&self->info);
self->collect = gst_collect_pads_new (); self->collect = gst_collect_pads_new ();
gst_collect_pads_set_function (self->collect, gst_collect_pads_set_function (self->collect,
(GstCollectPadsFunction) gst_frei0r_mixer_collected, self); (GstCollectPadsFunction) gst_frei0r_mixer_collected, self);
gst_collect_pads_set_event_function (self->collect,
(GstCollectPadsEventFunction) gst_frei0r_mixer_sink_event, self);
gst_collect_pads_set_query_function (self->collect,
(GstCollectPadsQueryFunction) gst_frei0r_mixer_sink_query, self);
self->src = self->src =
gst_pad_new_from_template (gst_element_class_get_pad_template gst_pad_new_from_template (gst_element_class_get_pad_template
(GST_ELEMENT_CLASS (klass), "src"), "src"); (GST_ELEMENT_CLASS (klass), "src"), "src");
gst_pad_set_getcaps_function (self->src,
GST_DEBUG_FUNCPTR (gst_frei0r_mixer_get_caps));
gst_pad_set_setcaps_function (self->src,
GST_DEBUG_FUNCPTR (gst_frei0r_mixer_set_caps));
gst_pad_set_query_function (self->src, gst_pad_set_query_function (self->src,
GST_DEBUG_FUNCPTR (gst_frei0r_mixer_src_query)); GST_DEBUG_FUNCPTR (gst_frei0r_mixer_src_query));
gst_pad_set_event_function (self->src, gst_pad_set_event_function (self->src,
@ -728,28 +693,14 @@ gst_frei0r_mixer_init (GstFrei0rMixer * self, GstFrei0rMixerClass * klass)
self->sink0 = self->sink0 =
gst_pad_new_from_template (gst_element_class_get_pad_template gst_pad_new_from_template (gst_element_class_get_pad_template
(GST_ELEMENT_CLASS (klass), "sink_0"), "sink_0"); (GST_ELEMENT_CLASS (klass), "sink_0"), "sink_0");
gst_pad_set_getcaps_function (self->sink0,
GST_DEBUG_FUNCPTR (gst_frei0r_mixer_get_caps));
gst_pad_set_setcaps_function (self->sink0,
GST_DEBUG_FUNCPTR (gst_frei0r_mixer_set_caps));
gst_pad_set_query_function (self->sink0,
GST_DEBUG_FUNCPTR (gst_frei0r_mixer_sink_query));
gst_collect_pads_add_pad (self->collect, self->sink0, gst_collect_pads_add_pad (self->collect, self->sink0,
sizeof (GstCollectData), NULL, TRUE); sizeof (GstCollectData), NULL, TRUE);
self->collect_event = (GstPadEventFunction) GST_PAD_EVENTFUNC (self->sink0); self->collect_event = (GstPadEventFunction) GST_PAD_EVENTFUNC (self->sink0);
gst_pad_set_event_function (self->sink0,
GST_DEBUG_FUNCPTR (gst_frei0r_mixer_sink0_event));
gst_element_add_pad (GST_ELEMENT_CAST (self), self->sink0); gst_element_add_pad (GST_ELEMENT_CAST (self), self->sink0);
self->sink1 = self->sink1 =
gst_pad_new_from_template (gst_element_class_get_pad_template gst_pad_new_from_template (gst_element_class_get_pad_template
(GST_ELEMENT_CLASS (klass), "sink_1"), "sink_1"); (GST_ELEMENT_CLASS (klass), "sink_1"), "sink_1");
gst_pad_set_getcaps_function (self->sink1,
GST_DEBUG_FUNCPTR (gst_frei0r_mixer_get_caps));
gst_pad_set_setcaps_function (self->sink1,
GST_DEBUG_FUNCPTR (gst_frei0r_mixer_set_caps));
gst_pad_set_query_function (self->sink0,
GST_DEBUG_FUNCPTR (gst_frei0r_mixer_sink_query));
gst_collect_pads_add_pad (self->collect, self->sink1, gst_collect_pads_add_pad (self->collect, self->sink1,
sizeof (GstCollectData), NULL, TRUE); sizeof (GstCollectData), NULL, TRUE);
gst_element_add_pad (GST_ELEMENT_CAST (self), self->sink1); gst_element_add_pad (GST_ELEMENT_CAST (self), self->sink1);
@ -758,12 +709,6 @@ gst_frei0r_mixer_init (GstFrei0rMixer * self, GstFrei0rMixerClass * klass)
self->sink2 = self->sink2 =
gst_pad_new_from_template (gst_element_class_get_pad_template gst_pad_new_from_template (gst_element_class_get_pad_template
(GST_ELEMENT_CLASS (klass), "sink_2"), "sink_2"); (GST_ELEMENT_CLASS (klass), "sink_2"), "sink_2");
gst_pad_set_getcaps_function (self->sink2,
GST_DEBUG_FUNCPTR (gst_frei0r_mixer_get_caps));
gst_pad_set_setcaps_function (self->sink2,
GST_DEBUG_FUNCPTR (gst_frei0r_mixer_set_caps));
gst_pad_set_query_function (self->sink0,
GST_DEBUG_FUNCPTR (gst_frei0r_mixer_sink_query));
gst_collect_pads_add_pad (self->collect, self->sink2, gst_collect_pads_add_pad (self->collect, self->sink2,
sizeof (GstCollectData), NULL, TRUE); sizeof (GstCollectData), NULL, TRUE);
gst_element_add_pad (GST_ELEMENT_CAST (self), self->sink2); gst_element_add_pad (GST_ELEMENT_CAST (self), self->sink2);

View file

@ -47,10 +47,9 @@ struct _GstFrei0rMixer {
GstPad *sink0, *sink1, *sink2; GstPad *sink0, *sink1, *sink2;
GstCaps *caps; GstCaps *caps;
GstVideoFormat fmt; GstVideoInfo info;
gint width, height;
GstEvent *newseg_event; GstEvent *segment_event;
GstPadEventFunction collect_event; GstPadEventFunction collect_event;

View file

@ -26,8 +26,6 @@
#include "gstfrei0r.h" #include "gstfrei0r.h"
#include "gstfrei0rsrc.h" #include "gstfrei0rsrc.h"
#include <gst/controller/gstcontroller.h>
GST_DEBUG_CATEGORY_EXTERN (frei0r_debug); GST_DEBUG_CATEGORY_EXTERN (frei0r_debug);
#define GST_CAT_DEFAULT frei0r_debug #define GST_CAT_DEFAULT frei0r_debug
@ -42,77 +40,44 @@ gst_frei0r_src_set_caps (GstBaseSrc * src, GstCaps * caps)
{ {
GstFrei0rSrc *self = GST_FREI0R_SRC (src); GstFrei0rSrc *self = GST_FREI0R_SRC (src);
if (!gst_video_format_parse_caps (caps, &self->fmt, &self->width, gst_video_info_init (&self->info);
&self->height) if (!gst_video_info_from_caps (&self->info, caps))
|| !gst_video_parse_caps_framerate (caps, &self->fps_n, &self->fps_d))
return FALSE; return FALSE;
gst_base_src_set_blocksize (src, self->info.size);
return TRUE; return TRUE;
} }
static GstCaps *
gst_frei0r_src_get_caps (GstBaseSrc * src)
{
if (GST_PAD_CAPS (GST_BASE_SRC_PAD (src)))
return gst_caps_ref (GST_PAD_CAPS (GST_BASE_SRC_PAD (src)));
else
return
gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD (src)));
}
static GstFlowReturn static GstFlowReturn
gst_frei0r_src_create (GstPushSrc * src, GstBuffer ** buf) gst_frei0r_src_fill (GstPushSrc * src, GstBuffer * buf)
{ {
GstFrei0rSrc *self = GST_FREI0R_SRC (src); GstFrei0rSrc *self = GST_FREI0R_SRC (src);
GstFrei0rSrcClass *klass = GST_FREI0R_SRC_GET_CLASS (src); GstFrei0rSrcClass *klass = GST_FREI0R_SRC_GET_CLASS (src);
guint size, newsize;
GstFlowReturn ret = GST_FLOW_OK;
GstBuffer *outbuf = NULL;
GstClockTime timestamp; GstClockTime timestamp;
gdouble time; gdouble time;
GstMapInfo map;
*buf = NULL;
if (G_UNLIKELY (self->width <= 0 || self->height <= 0))
return GST_FLOW_NOT_NEGOTIATED;
if (G_UNLIKELY (!self->f0r_instance)) { if (G_UNLIKELY (!self->f0r_instance)) {
self->f0r_instance = self->f0r_instance =
gst_frei0r_instance_construct (klass->ftable, klass->properties, gst_frei0r_instance_construct (klass->ftable, klass->properties,
klass->n_properties, self->property_cache, self->width, self->height); klass->n_properties, self->property_cache, self->info.width,
self->info.height);
if (G_UNLIKELY (!self->f0r_instance)) if (G_UNLIKELY (!self->f0r_instance))
return GST_FLOW_ERROR; return GST_FLOW_ERROR;
} }
newsize = gst_video_format_get_size (self->fmt, self->width, self->height); timestamp =
gst_util_uint64_scale (self->n_frames, GST_SECOND * self->info.fps_d,
ret = self->info.fps_n);
gst_pad_alloc_buffer_and_set_caps (GST_BASE_SRC_PAD (src), GST_BUFFER_PTS (buf) = GST_BUFFER_DTS (buf) = timestamp;
GST_BUFFER_OFFSET_NONE, newsize, GST_PAD_CAPS (GST_BASE_SRC_PAD (src)), GST_BUFFER_OFFSET (buf) = self->n_frames;
&outbuf);
if (ret != GST_FLOW_OK)
return ret;
/* Format might have changed */
size = GST_BUFFER_SIZE (outbuf);
newsize = gst_video_format_get_size (self->fmt, self->width, self->height);
if (size != newsize) {
gst_buffer_unref (outbuf);
outbuf = gst_buffer_new_and_alloc (newsize);
gst_buffer_set_caps (outbuf, GST_PAD_CAPS (GST_BASE_SRC_PAD (src)));
}
GST_BUFFER_TIMESTAMP (outbuf) = timestamp =
gst_util_uint64_scale (self->n_frames, GST_SECOND * self->fps_d,
self->fps_n);
GST_BUFFER_OFFSET (outbuf) = self->n_frames;
self->n_frames++; self->n_frames++;
GST_BUFFER_OFFSET_END (outbuf) = self->n_frames; GST_BUFFER_OFFSET_END (buf) = self->n_frames;
GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buf) =
gst_util_uint64_scale (self->n_frames, GST_SECOND * self->fps_d, gst_util_uint64_scale (self->n_frames, GST_SECOND * self->info.fps_d,
self->fps_n) - GST_BUFFER_TIMESTAMP (outbuf); self->info.fps_n) - GST_BUFFER_TIMESTAMP (buf);
timestamp = timestamp =
gst_segment_to_stream_time (&GST_BASE_SRC_CAST (self)->segment, gst_segment_to_stream_time (&GST_BASE_SRC_CAST (self)->segment,
@ -124,20 +89,31 @@ gst_frei0r_src_create (GstPushSrc * src, GstBuffer ** buf)
if (GST_CLOCK_TIME_IS_VALID (timestamp)) if (GST_CLOCK_TIME_IS_VALID (timestamp))
gst_object_sync_values (GST_OBJECT (self), timestamp); gst_object_sync_values (GST_OBJECT (self), timestamp);
time = ((gdouble) GST_BUFFER_TIMESTAMP (outbuf)) / GST_SECOND; time = ((gdouble) GST_BUFFER_TIMESTAMP (buf)) / GST_SECOND;
GST_OBJECT_LOCK (self); GST_OBJECT_LOCK (self);
if (!gst_buffer_map (buf, &map, GST_MAP_WRITE))
goto map_error;
if (klass->ftable->update2) if (klass->ftable->update2)
klass->ftable->update2 (self->f0r_instance, time, NULL, NULL, NULL, klass->ftable->update2 (self->f0r_instance, time, NULL, NULL, NULL,
(guint32 *) GST_BUFFER_DATA (outbuf)); (guint32 *) map.data);
else else
klass->ftable->update (self->f0r_instance, time, NULL, klass->ftable->update (self->f0r_instance, time, NULL,
(guint32 *) GST_BUFFER_DATA (outbuf)); (guint32 *) map.data);
gst_buffer_unmap (buf, &map);
GST_OBJECT_UNLOCK (self); GST_OBJECT_UNLOCK (self);
*buf = outbuf;
return GST_FLOW_OK; return GST_FLOW_OK;
map_error:
GST_OBJECT_UNLOCK (self);
GST_ELEMENT_ERROR (GST_ELEMENT (src), RESOURCE, WRITE, (NULL),
("Could not map buffer for writing"));
return GST_FLOW_ERROR;
} }
static gboolean static gboolean
@ -161,9 +137,7 @@ gst_frei0r_src_stop (GstBaseSrc * basesrc)
self->f0r_instance = NULL; self->f0r_instance = NULL;
} }
self->fmt = GST_VIDEO_FORMAT_UNKNOWN; gst_video_info_init (&self->info);
self->width = self->height = 0;
self->fps_n = self->fps_d = 0;
self->n_frames = 0; self->n_frames = 0;
return TRUE; return TRUE;
@ -182,12 +156,12 @@ gst_frei0r_src_do_seek (GstBaseSrc * bsrc, GstSegment * segment)
GstFrei0rSrc *self = GST_FREI0R_SRC (bsrc); GstFrei0rSrc *self = GST_FREI0R_SRC (bsrc);
segment->time = segment->start; segment->time = segment->start;
time = segment->last_stop; time = segment->position;
/* now move to the time indicated */ /* now move to the time indicated */
if (self->fps_n) { if (self->info.fps_n) {
self->n_frames = gst_util_uint64_scale (time, self->n_frames = gst_util_uint64_scale (time,
self->fps_n, self->fps_d * GST_SECOND); self->info.fps_n, self->info.fps_d * GST_SECOND);
} else { } else {
self->n_frames = 0; self->n_frames = 0;
} }
@ -219,9 +193,9 @@ gst_frei0r_src_query (GstBaseSrc * bsrc, GstQuery * query)
switch (dest_fmt) { switch (dest_fmt) {
case GST_FORMAT_TIME: case GST_FORMAT_TIME:
/* frames to time */ /* frames to time */
if (self->fps_n) { if (self->info.fps_n) {
dest_val = gst_util_uint64_scale (src_val, dest_val = gst_util_uint64_scale (src_val,
self->fps_d * GST_SECOND, self->fps_n); self->info.fps_d * GST_SECOND, self->info.fps_n);
} else { } else {
dest_val = 0; dest_val = 0;
} }
@ -234,9 +208,9 @@ gst_frei0r_src_query (GstBaseSrc * bsrc, GstQuery * query)
switch (dest_fmt) { switch (dest_fmt) {
case GST_FORMAT_DEFAULT: case GST_FORMAT_DEFAULT:
/* time to frames */ /* time to frames */
if (self->fps_n) { if (self->info.fps_n) {
dest_val = gst_util_uint64_scale (src_val, dest_val = gst_util_uint64_scale (src_val,
self->fps_n, self->fps_d * GST_SECOND); self->info.fps_n, self->info.fps_d * GST_SECOND);
} else { } else {
dest_val = 0; dest_val = 0;
} }
@ -268,16 +242,20 @@ error:
} }
} }
static void static GstCaps *
gst_frei0r_src_src_fixate (GstPad * pad, GstCaps * caps) gst_frei0r_src_fixate (GstBaseSrc * src, GstCaps * caps)
{ {
GstStructure *structure; GstStructure *structure;
caps = gst_caps_make_writable (caps);
structure = gst_caps_get_structure (caps, 0); structure = gst_caps_get_structure (caps, 0);
gst_structure_fixate_field_nearest_int (structure, "width", 320); gst_structure_fixate_field_nearest_int (structure, "width", 320);
gst_structure_fixate_field_nearest_int (structure, "height", 240); gst_structure_fixate_field_nearest_int (structure, "height", 240);
gst_structure_fixate_field_nearest_fraction (structure, "framerate", 30, 1); gst_structure_fixate_field_nearest_fraction (structure, "framerate", 30, 1);
return caps;
} }
static void static void
@ -367,27 +345,24 @@ gst_frei0r_src_class_init (GstFrei0rSrcClass * klass,
templ = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, caps); templ = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, caps);
gst_element_class_add_pad_template (gstelement_class, templ); gst_element_class_add_pad_template (gstelement_class, templ);
gstbasesrc_class->set_caps = gst_frei0r_src_set_caps; gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_frei0r_src_set_caps);
gstbasesrc_class->get_caps = gst_frei0r_src_get_caps; gstbasesrc_class->is_seekable =
gstbasesrc_class->is_seekable = gst_frei0r_src_is_seekable; GST_DEBUG_FUNCPTR (gst_frei0r_src_is_seekable);
gstbasesrc_class->do_seek = gst_frei0r_src_do_seek; gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (gst_frei0r_src_do_seek);
gstbasesrc_class->query = gst_frei0r_src_query; gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_frei0r_src_query);
gstbasesrc_class->start = gst_frei0r_src_start; gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_frei0r_src_start);
gstbasesrc_class->stop = gst_frei0r_src_stop; gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_frei0r_src_stop);
gstbasesrc_class->fixate = GST_DEBUG_FUNCPTR (gst_frei0r_src_fixate);
gstpushsrc_class->create = GST_DEBUG_FUNCPTR (gst_frei0r_src_create); gstpushsrc_class->fill = GST_DEBUG_FUNCPTR (gst_frei0r_src_fill);
} }
static void static void
gst_frei0r_src_init (GstFrei0rSrc * self, GstFrei0rSrcClass * klass) gst_frei0r_src_init (GstFrei0rSrc * self, GstFrei0rSrcClass * klass)
{ {
GstPad *pad = GST_BASE_SRC_PAD (self);
self->property_cache = self->property_cache =
gst_frei0r_property_cache_init (klass->properties, klass->n_properties); gst_frei0r_property_cache_init (klass->properties, klass->n_properties);
gst_video_info_init (&self->info);
gst_pad_set_fixatecaps_function (pad, gst_frei0r_src_src_fixate);
gst_base_src_set_format (GST_BASE_SRC_CAST (self), GST_FORMAT_TIME); gst_base_src_set_format (GST_BASE_SRC_CAST (self), GST_FORMAT_TIME);
} }

View file

@ -45,9 +45,7 @@ struct _GstFrei0rSrc {
f0r_instance_t *f0r_instance; f0r_instance_t *f0r_instance;
GstFrei0rPropertyValue *property_cache; GstFrei0rPropertyValue *property_cache;
GstVideoFormat fmt; GstVideoInfo info;
gint width, height;
gint fps_n, fps_d;
guint64 n_frames; guint64 n_frames;
}; };