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 \
cdxaparse \
dccp faceoverlay \
fieldanalysis freeverb frei0r \
fieldanalysis freeverb \
hdvparse ivfparse jp2kdecimator \
kate librfb \
mpegpsmux mve mxf mythtv nsf nuvdemux \

View file

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

View file

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

View file

@ -26,8 +26,6 @@
#include "gstfrei0r.h"
#include "gstfrei0rmixer.h"
#include <gst/controller/gstcontroller.h>
GST_DEBUG_CATEGORY_EXTERN (frei0r_debug);
#define GST_CAT_DEFAULT frei0r_debug
@ -54,11 +52,10 @@ gst_frei0r_mixer_reset (GstFrei0rMixer * self)
self->property_cache = NULL;
gst_caps_replace (&self->caps, NULL);
p_ev = &self->newseg_event;
p_ev = &self->segment_event;
gst_event_replace (p_ev, NULL);
self->fmt = GST_VIDEO_FORMAT_UNKNOWN;
self->width = self->height = 0;
gst_video_info_init (&self->info);
}
static void
@ -155,85 +152,74 @@ gst_frei0r_mixer_change_state (GstElement * element, GstStateChange transition)
}
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;
if (self->caps) {
caps = gst_caps_ref (self->caps);
} else {
GstCaps *tmp, *tmp1;
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;
}
GstCaps *tmp;
caps = gst_pad_get_pad_template_caps (self->src);
if (filter) {
tmp = caps;
tmp1 = gst_pad_peer_get_caps (self->sink0);
if (tmp1) {
caps = gst_caps_intersect (tmp, tmp1);
caps = gst_caps_intersect_full (tmp, filter, GST_CAPS_INTERSECT_FIRST);
gst_caps_unref (tmp);
gst_caps_unref (tmp1);
}
tmp = caps;
tmp1 = gst_pad_peer_get_caps (self->sink1);
if (tmp1) {
caps = gst_caps_intersect (tmp, tmp1);
gst_caps_unref (tmp);
gst_caps_unref (tmp1);
caps = gst_frei0r_mixer_query_pad_caps (self->src, pad, caps);
caps = gst_frei0r_mixer_query_pad_caps (self->sink0, pad, caps);
caps = gst_frei0r_mixer_query_pad_caps (self->sink1, pad, caps);
if (self->sink2)
caps = gst_frei0r_mixer_query_pad_caps (self->sink2, pad, caps);
}
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;
}
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;
if (!self->caps) {
gst_caps_replace (&self->caps, caps);
if (pad != self->src)
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);
ret = gst_pad_set_caps (self->src, caps);
if (ret) {
if (!gst_video_format_parse_caps (caps, &self->fmt, &self->width,
&self->height)) {
ret = FALSE;
goto out;
}
}
out:
GstVideoInfo info;
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;
}
@ -258,7 +244,7 @@ gst_frei0r_mixer_src_query_duration (GstFrei0rMixer * self, GstQuery * query)
it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (self));
while (!done) {
GstIteratorResult ires;
gpointer item;
GValue item = { 0 };
ires = gst_iterator_next (it, &item);
switch (ires) {
@ -267,11 +253,11 @@ gst_frei0r_mixer_src_query_duration (GstFrei0rMixer * self, GstQuery * query)
break;
case GST_ITERATOR_OK:
{
GstPad *pad = GST_PAD_CAST (item);
GstPad *pad = g_value_get_object (&item);
gint64 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 */
if (res) {
/* valid unknown length, stop searching */
@ -283,7 +269,7 @@ gst_frei0r_mixer_src_query_duration (GstFrei0rMixer * self, GstQuery * query)
else if (duration < min)
min = duration;
}
gst_object_unref (pad);
g_value_reset (&item);
break;
}
case GST_ITERATOR_RESYNC:
@ -296,6 +282,8 @@ gst_frei0r_mixer_src_query_duration (GstFrei0rMixer * self, GstQuery * query)
done = TRUE;
break;
}
g_value_unset (&item);
}
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));
while (!done) {
GstIteratorResult ires;
gpointer item;
GValue item = { 0 };
ires = gst_iterator_next (it, &item);
switch (ires) {
@ -338,7 +326,7 @@ gst_frei0r_mixer_src_query_latency (GstFrei0rMixer * self, GstQuery * query)
break;
case GST_ITERATOR_OK:
{
GstPad *pad = GST_PAD_CAST (item);
GstPad *pad = g_value_get_object (&item);
GstQuery *peerquery;
GstClockTime min_cur, max_cur;
gboolean live_cur;
@ -364,7 +352,7 @@ gst_frei0r_mixer_src_query_latency (GstFrei0rMixer * self, GstQuery * query)
}
gst_query_unref (peerquery);
gst_object_unref (pad);
g_value_reset (&item);
break;
}
case GST_ITERATOR_RESYNC:
@ -379,6 +367,8 @@ gst_frei0r_mixer_src_query_latency (GstFrei0rMixer * self, GstQuery * query)
done = TRUE;
break;
}
g_value_unset (&item);
}
gst_iterator_free (it);
@ -394,9 +384,9 @@ gst_frei0r_mixer_src_query_latency (GstFrei0rMixer * self, GstQuery * query)
}
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;
switch (GST_QUERY_TYPE (query)) {
@ -409,68 +399,50 @@ gst_frei0r_mixer_src_query (GstPad * pad, GstQuery * query)
case GST_QUERY_LATENCY:
ret = gst_frei0r_mixer_src_query_latency (self, query);
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:
ret = gst_pad_query_default (pad, query);
ret = gst_pad_query_default (pad, GST_OBJECT (self), query);
break;
}
gst_object_unref (self);
return ret;
}
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 = gst_pad_query (self->src, query);
gboolean ret = TRUE;
gst_object_unref (self);
return ret;
}
static gboolean
forward_event_func (GstPad * pad, GValue * ret, GstEvent * event)
{
gst_event_ref (event);
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));
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_CAPS:
{
GstCaps *filter, *caps;
gst_query_parse_caps (query, &filter);
caps = gst_frei0r_mixer_get_caps (self, cdata->pad, filter);
gst_query_set_caps_result (query, caps);
gst_caps_unref (caps);
break;
}
gst_object_unref (pad);
return TRUE;
default:
ret = gst_collect_pads_query_default (pads, cdata, query, FALSE);
break;
}
return ret;
}
static gboolean
forward_event (GstFrei0rMixer * self, GstEvent * event)
gst_frei0r_mixer_src_event (GstPad * pad, GstObject * object, GstEvent * event)
{
GstIterator *it;
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));
GstFrei0rMixer *self = GST_FREI0R_MIXER (object);
gboolean ret = FALSE;
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 ());
}
ret = forward_event (self, event);
ret = gst_pad_event_default (pad, GST_OBJECT (self), event);
break;
}
case GST_EVENT_NAVIGATION:
/* navigation is rather pointless. */
ret = FALSE;
break;
default:
/* just forward the rest for now */
ret = forward_event (self, event);
ret = gst_pad_event_default (pad, GST_OBJECT (self), event);
break;
}
gst_object_unref (self);
return ret;
}
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 = FALSE;
GstEvent **p_ev;
GST_DEBUG ("Got %s event on pad %s:%s", GST_EVENT_TYPE_NAME (event),
GST_DEBUG_PAD_NAME (pad));
gboolean ret = TRUE;
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_NEWSEGMENT:
p_ev = &self->newseg_event;
gst_event_replace (p_ev, event);
break;
default:
case GST_EVENT_CAPS:
{
GstCaps *caps;
gst_event_parse_caps (event, &caps);
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;
}
/* now GstCollectPads can take care of the rest, e.g. EOS */
ret = self->collect_event (pad, event);
gst_object_unref (self);
return ret;
}
@ -551,28 +511,27 @@ gst_frei0r_mixer_collected (GstCollectPads * pads, GstFrei0rMixer * self)
GstClockTime timestamp;
gdouble time;
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;
if (G_UNLIKELY (!self->f0r_instance)) {
self->f0r_instance =
gst_frei0r_instance_construct (klass->ftable, klass->properties,
klass->n_properties, self->property_cache, self->width, self->height);
self->f0r_instance = gst_frei0r_instance_construct (klass->ftable,
klass->properties, klass->n_properties, self->property_cache,
self->info.width, self->info.height);
if (G_UNLIKELY (!self->f0r_instance))
return GST_FLOW_ERROR;
}
if (self->newseg_event) {
gst_pad_push_event (self->src, self->newseg_event);
self->newseg_event = NULL;
if (self->segment_event) {
gst_pad_push_event (self->src, self->segment_event);
self->segment_event = NULL;
}
if ((ret =
gst_pad_alloc_buffer_and_set_caps (self->src, GST_BUFFER_OFFSET_NONE,
gst_video_format_get_size (self->fmt, self->width, self->height),
GST_PAD_CAPS (self->src), &outbuf)) != GST_FLOW_OK)
return ret;
/* FIXME Request an allocator and/or pool */
outbuf = gst_buffer_new_allocate (NULL, self->info.size, &alloc_params);
for (l = pads->data; l; l = l->next) {
GstCollectData *cdata = l->data;
@ -590,8 +549,14 @@ gst_frei0r_mixer_collected (GstCollectPads * pads, GstFrei0rMixer * self)
if (!inbuf0 || !inbuf1 || (!inbuf2 && self->sink2))
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);
timestamp = GST_BUFFER_TIMESTAMP (inbuf0);
timestamp = GST_BUFFER_PTS (inbuf0);
timestamp = gst_segment_to_stream_time (segment, GST_FORMAT_TIME, timestamp);
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))
gst_object_sync_values (GST_OBJECT (self), timestamp);
gst_buffer_copy_metadata (outbuf, inbuf0,
GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS);
time = ((gdouble) GST_BUFFER_TIMESTAMP (outbuf)) / GST_SECOND;
gst_buffer_copy_into (outbuf, inbuf0,
GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
time = ((gdouble) GST_BUFFER_PTS (outbuf)) / GST_SECOND;
GST_OBJECT_LOCK (self);
klass->ftable->update2 (self->f0r_instance, time,
(const guint32 *) GST_BUFFER_DATA (inbuf0),
(const guint32 *) GST_BUFFER_DATA (inbuf1),
(inbuf2) ? (const guint32 *) GST_BUFFER_DATA (inbuf2) : NULL,
(guint32 *) GST_BUFFER_DATA (outbuf));
(const guint32 *) inmap0.data, (const guint32 *) inmap1.data,
(inbuf2) ? (const guint32 *) inmap2.data : NULL, (guint32 *) outmap.data);
GST_OBJECT_UNLOCK (self);
gst_buffer_unmap (outbuf, &outmap);
gst_buffer_unref (inbuf0);
gst_buffer_unmap (inbuf0, &inmap0);
gst_buffer_unref (inbuf1);
if (inbuf2)
gst_buffer_unmap (inbuf1, &inmap1);
if (inbuf2) {
gst_buffer_unmap (inbuf2, &inmap2);
gst_buffer_unref (inbuf2);
}
ret = gst_pad_push (self->src, outbuf);
@ -634,7 +602,7 @@ eos:
gst_buffer_unref (inbuf2);
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_caps_ref (caps));
gst_element_class_add_pad_template (gstelement_class, templ);
gst_object_unref (templ);
templ =
gst_pad_template_new ("sink_0", GST_PAD_SINK, GST_PAD_ALWAYS,
gst_caps_ref (caps));
gst_element_class_add_pad_template (gstelement_class, templ);
gst_object_unref (templ);
templ =
gst_pad_template_new ("sink_1", GST_PAD_SINK, GST_PAD_ALWAYS,
gst_caps_ref (caps));
gst_element_class_add_pad_template (gstelement_class, templ);
gst_object_unref (templ);
if (klass->info->plugin_type == F0R_PLUGIN_TYPE_MIXER3) {
templ =
gst_pad_template_new ("sink_2", GST_PAD_SINK, GST_PAD_ALWAYS,
gst_caps_ref (caps));
gst_element_class_add_pad_template (gstelement_class, templ);
gst_object_unref (templ);
}
gst_caps_unref (caps);
@ -707,18 +671,19 @@ gst_frei0r_mixer_init (GstFrei0rMixer * self, GstFrei0rMixerClass * klass)
{
self->property_cache =
gst_frei0r_property_cache_init (klass->properties, klass->n_properties);
gst_video_info_init (&self->info);
self->collect = gst_collect_pads_new ();
gst_collect_pads_set_function (self->collect,
(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 =
gst_pad_new_from_template (gst_element_class_get_pad_template
(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_DEBUG_FUNCPTR (gst_frei0r_mixer_src_query));
gst_pad_set_event_function (self->src,
@ -728,28 +693,14 @@ gst_frei0r_mixer_init (GstFrei0rMixer * self, GstFrei0rMixerClass * klass)
self->sink0 =
gst_pad_new_from_template (gst_element_class_get_pad_template
(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,
sizeof (GstCollectData), NULL, TRUE);
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);
self->sink1 =
gst_pad_new_from_template (gst_element_class_get_pad_template
(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,
sizeof (GstCollectData), NULL, TRUE);
gst_element_add_pad (GST_ELEMENT_CAST (self), self->sink1);
@ -758,12 +709,6 @@ gst_frei0r_mixer_init (GstFrei0rMixer * self, GstFrei0rMixerClass * klass)
self->sink2 =
gst_pad_new_from_template (gst_element_class_get_pad_template
(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,
sizeof (GstCollectData), NULL, TRUE);
gst_element_add_pad (GST_ELEMENT_CAST (self), self->sink2);

View file

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

View file

@ -26,8 +26,6 @@
#include "gstfrei0r.h"
#include "gstfrei0rsrc.h"
#include <gst/controller/gstcontroller.h>
GST_DEBUG_CATEGORY_EXTERN (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);
if (!gst_video_format_parse_caps (caps, &self->fmt, &self->width,
&self->height)
|| !gst_video_parse_caps_framerate (caps, &self->fps_n, &self->fps_d))
gst_video_info_init (&self->info);
if (!gst_video_info_from_caps (&self->info, caps))
return FALSE;
gst_base_src_set_blocksize (src, self->info.size);
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
gst_frei0r_src_create (GstPushSrc * src, GstBuffer ** buf)
gst_frei0r_src_fill (GstPushSrc * src, GstBuffer * buf)
{
GstFrei0rSrc *self = GST_FREI0R_SRC (src);
GstFrei0rSrcClass *klass = GST_FREI0R_SRC_GET_CLASS (src);
guint size, newsize;
GstFlowReturn ret = GST_FLOW_OK;
GstBuffer *outbuf = NULL;
GstClockTime timestamp;
gdouble time;
*buf = NULL;
if (G_UNLIKELY (self->width <= 0 || self->height <= 0))
return GST_FLOW_NOT_NEGOTIATED;
GstMapInfo map;
if (G_UNLIKELY (!self->f0r_instance)) {
self->f0r_instance =
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))
return GST_FLOW_ERROR;
}
newsize = gst_video_format_get_size (self->fmt, self->width, self->height);
ret =
gst_pad_alloc_buffer_and_set_caps (GST_BASE_SRC_PAD (src),
GST_BUFFER_OFFSET_NONE, newsize, GST_PAD_CAPS (GST_BASE_SRC_PAD (src)),
&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;
timestamp =
gst_util_uint64_scale (self->n_frames, GST_SECOND * self->info.fps_d,
self->info.fps_n);
GST_BUFFER_PTS (buf) = GST_BUFFER_DTS (buf) = timestamp;
GST_BUFFER_OFFSET (buf) = self->n_frames;
self->n_frames++;
GST_BUFFER_OFFSET_END (outbuf) = self->n_frames;
GST_BUFFER_DURATION (outbuf) =
gst_util_uint64_scale (self->n_frames, GST_SECOND * self->fps_d,
self->fps_n) - GST_BUFFER_TIMESTAMP (outbuf);
GST_BUFFER_OFFSET_END (buf) = self->n_frames;
GST_BUFFER_DURATION (buf) =
gst_util_uint64_scale (self->n_frames, GST_SECOND * self->info.fps_d,
self->info.fps_n) - GST_BUFFER_TIMESTAMP (buf);
timestamp =
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))
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);
if (!gst_buffer_map (buf, &map, GST_MAP_WRITE))
goto map_error;
if (klass->ftable->update2)
klass->ftable->update2 (self->f0r_instance, time, NULL, NULL, NULL,
(guint32 *) GST_BUFFER_DATA (outbuf));
(guint32 *) map.data);
else
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);
*buf = outbuf;
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
@ -161,9 +137,7 @@ gst_frei0r_src_stop (GstBaseSrc * basesrc)
self->f0r_instance = NULL;
}
self->fmt = GST_VIDEO_FORMAT_UNKNOWN;
self->width = self->height = 0;
self->fps_n = self->fps_d = 0;
gst_video_info_init (&self->info);
self->n_frames = 0;
return TRUE;
@ -182,12 +156,12 @@ gst_frei0r_src_do_seek (GstBaseSrc * bsrc, GstSegment * segment)
GstFrei0rSrc *self = GST_FREI0R_SRC (bsrc);
segment->time = segment->start;
time = segment->last_stop;
time = segment->position;
/* now move to the time indicated */
if (self->fps_n) {
if (self->info.fps_n) {
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 {
self->n_frames = 0;
}
@ -219,9 +193,9 @@ gst_frei0r_src_query (GstBaseSrc * bsrc, GstQuery * query)
switch (dest_fmt) {
case GST_FORMAT_TIME:
/* frames to time */
if (self->fps_n) {
if (self->info.fps_n) {
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 {
dest_val = 0;
}
@ -234,9 +208,9 @@ gst_frei0r_src_query (GstBaseSrc * bsrc, GstQuery * query)
switch (dest_fmt) {
case GST_FORMAT_DEFAULT:
/* time to frames */
if (self->fps_n) {
if (self->info.fps_n) {
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 {
dest_val = 0;
}
@ -268,16 +242,20 @@ error:
}
}
static void
gst_frei0r_src_src_fixate (GstPad * pad, GstCaps * caps)
static GstCaps *
gst_frei0r_src_fixate (GstBaseSrc * src, GstCaps * caps)
{
GstStructure *structure;
caps = gst_caps_make_writable (caps);
structure = gst_caps_get_structure (caps, 0);
gst_structure_fixate_field_nearest_int (structure, "width", 320);
gst_structure_fixate_field_nearest_int (structure, "height", 240);
gst_structure_fixate_field_nearest_fraction (structure, "framerate", 30, 1);
return caps;
}
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);
gst_element_class_add_pad_template (gstelement_class, templ);
gstbasesrc_class->set_caps = gst_frei0r_src_set_caps;
gstbasesrc_class->get_caps = gst_frei0r_src_get_caps;
gstbasesrc_class->is_seekable = gst_frei0r_src_is_seekable;
gstbasesrc_class->do_seek = gst_frei0r_src_do_seek;
gstbasesrc_class->query = gst_frei0r_src_query;
gstbasesrc_class->start = gst_frei0r_src_start;
gstbasesrc_class->stop = gst_frei0r_src_stop;
gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_frei0r_src_set_caps);
gstbasesrc_class->is_seekable =
GST_DEBUG_FUNCPTR (gst_frei0r_src_is_seekable);
gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (gst_frei0r_src_do_seek);
gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_frei0r_src_query);
gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_frei0r_src_start);
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
gst_frei0r_src_init (GstFrei0rSrc * self, GstFrei0rSrcClass * klass)
{
GstPad *pad = GST_BASE_SRC_PAD (self);
self->property_cache =
gst_frei0r_property_cache_init (klass->properties, klass->n_properties);
gst_pad_set_fixatecaps_function (pad, gst_frei0r_src_src_fixate);
gst_video_info_init (&self->info);
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;
GstFrei0rPropertyValue *property_cache;
GstVideoFormat fmt;
gint width, height;
gint fps_n, fps_d;
GstVideoInfo info;
guint64 n_frames;
};