static GstFlowReturn gst_frei0r_filter_transform (GstBaseTransform * trans, GstBuffer * inbuf, GstBuffer * outbuf) { GstFrei0rFilter *self = GST_FREI0R_FILTER (trans); GstFrei0rFilterClass *klass = GST_FREI0R_FILTER_GET_CLASS (trans); gdouble time; if (G_UNLIKELY (self->width <= 0 || self->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); if (G_UNLIKELY (!self->f0r_instance)) return GST_FLOW_ERROR; } time = ((gdouble) GST_BUFFER_TIMESTAMP (inbuf)) / GST_SECOND; if (klass->ftable->update2) klass->ftable->update2 (self->f0r_instance, time, (const guint32 *) GST_BUFFER_DATA (inbuf), NULL, NULL, (guint32 *) GST_BUFFER_DATA (outbuf)); else klass->ftable->update (self->f0r_instance, time, (const guint32 *) GST_BUFFER_DATA (inbuf), (guint32 *) GST_BUFFER_DATA (outbuf)); return GST_FLOW_OK; }
static GstFlowReturn gst_frei0r_mixer_collected (GstCollectPads * pads, GstFrei0rMixer * self) { GstBuffer *inbuf0 = NULL, *inbuf1 = NULL, *inbuf2 = NULL; GstBuffer *outbuf = NULL; GstFlowReturn ret = GST_FLOW_OK; GSList *l; GstFrei0rMixerClass *klass = GST_FREI0R_MIXER_GET_CLASS (self); GstClockTime timestamp; gdouble time; GstSegment *segment = NULL; GstAllocationParams alloc_params = { 0, 31, 0, 0 }; GstMapInfo outmap, inmap0, inmap1, inmap2; 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->info.width, self->info.height); if (G_UNLIKELY (!self->f0r_instance)) return GST_FLOW_ERROR; } if (self->segment_event) { gst_pad_push_event (self->src, self->segment_event); self->segment_event = NULL; } /* 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; if (cdata->pad == self->sink0) { inbuf0 = gst_collect_pads_pop (pads, cdata); segment = &cdata->segment; } else if (cdata->pad == self->sink1) { inbuf1 = gst_collect_pads_pop (pads, cdata); } else if (cdata->pad == self->sink2) { inbuf2 = gst_collect_pads_pop (pads, cdata); } } 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_PTS (inbuf0); timestamp = gst_segment_to_stream_time (segment, GST_FORMAT_TIME, timestamp); GST_DEBUG_OBJECT (self, "sync to %" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp)); if (GST_CLOCK_TIME_IS_VALID (timestamp)) gst_object_sync_values (GST_OBJECT (self), timestamp); 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 *) 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); gst_buffer_unmap (inbuf1, &inmap1); if (inbuf2) { gst_buffer_unmap (inbuf2, &inmap2); gst_buffer_unref (inbuf2); } ret = gst_pad_push (self->src, outbuf); return ret; eos: { GST_DEBUG_OBJECT (self, "no data available, must be EOS"); gst_buffer_unref (outbuf); if (inbuf0) gst_buffer_unref (inbuf0); if (inbuf1) gst_buffer_unref (inbuf1); if (inbuf2) gst_buffer_unref (inbuf2); gst_pad_push_event (self->src, gst_event_new_eos ()); return GST_FLOW_EOS; } }
static GstFlowReturn gst_frei0r_mixer_collected (GstCollectPads * pads, GstFrei0rMixer * self) { GstBuffer *inbuf0 = NULL, *inbuf1 = NULL, *inbuf2 = NULL; GstBuffer *outbuf = NULL; GstFlowReturn ret = GST_FLOW_OK; GSList *l; GstFrei0rMixerClass *klass = GST_FREI0R_MIXER_GET_CLASS (self); GstClockTime timestamp; gdouble time; GstSegment *segment = NULL; if (G_UNLIKELY (self->width <= 0 || self->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); 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 ((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; for (l = pads->data; l; l = l->next) { GstCollectData *cdata = l->data; if (cdata->pad == self->sink0) { inbuf0 = gst_collect_pads_pop (pads, cdata); segment = &cdata->segment; } else if (cdata->pad == self->sink1) { inbuf1 = gst_collect_pads_pop (pads, cdata); } else if (cdata->pad == self->sink2) { inbuf2 = gst_collect_pads_pop (pads, cdata); } } if (!inbuf0 || !inbuf1 || (!inbuf2 && self->sink2)) goto eos; g_assert (segment != NULL); timestamp = GST_BUFFER_TIMESTAMP (inbuf0); timestamp = gst_segment_to_stream_time (segment, GST_FORMAT_TIME, timestamp); GST_DEBUG_OBJECT (self, "sync to %" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp)); if (GST_CLOCK_TIME_IS_VALID (timestamp)) gst_object_sync_values (G_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_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)); GST_OBJECT_UNLOCK (self); gst_buffer_unref (inbuf0); gst_buffer_unref (inbuf1); if (inbuf2) gst_buffer_unref (inbuf2); ret = gst_pad_push (self->src, outbuf); return ret; eos: { GST_DEBUG_OBJECT (self, "no data available, must be EOS"); gst_buffer_unref (outbuf); if (inbuf0) gst_buffer_unref (inbuf0); if (inbuf1) gst_buffer_unref (inbuf1); if (inbuf2) gst_buffer_unref (inbuf2); gst_pad_push_event (self->src, gst_event_new_eos ()); return GST_FLOW_UNEXPECTED; } }