* <refsect2>
* <title>Example launch line</title>
* |[
- * gst-launch filesrc location=file.mp3 ! decodebin ! audioconvert ! "audio/x-raw-int,channels=2" ! deinterleave name=d interleave name=i ! audioconvert ! wavenc ! filesink location=test.wav d.src0 ! queue ! audioconvert ! i.sink1 d.src1 ! queue ! audioconvert ! i.sink0
+ * gst-launch filesrc location=file.mp3 ! decodebin ! audioconvert ! "audio/x-raw,channels=2" ! deinterleave name=d interleave name=i ! audioconvert ! wavenc ! filesink location=test.wav d.src_0 ! queue ! audioconvert ! i.sink_1 d.src_1 ! queue ! audioconvert ! i.sink_0
* ]| Decodes and deinterleaves a Stereo MP3 file into separate channels and
* then interleaves the channels again to a WAV file with the channel with the
* channels exchanged.
* |[
- * gst-launch interleave name=i ! audioconvert ! wavenc ! filesink location=file.wav filesrc location=file1.wav ! decodebin ! audioconvert ! "audio/x-raw-int,channels=1" ! queue ! i.sink0 filesrc location=file2.wav ! decodebin ! audioconvert ! "audio/x-raw-int,channels=1" ! queue ! i.sink1
+ * gst-launch interleave name=i ! audioconvert ! wavenc ! filesink location=file.wav filesrc location=file1.wav ! decodebin ! audioconvert ! "audio/x-raw,channels=1" ! queue ! i.sink_0 filesrc location=file2.wav ! decodebin ! audioconvert ! "audio/x-raw,channels=1" ! queue ! i.sink_1
* ]| Interleaves two Mono WAV files to a single Stereo WAV file.
* </refsect2>
*/
#include <string.h>
#include "interleave.h"
-#include <gst/audio/multichannel.h>
+#include <gst/audio/audio.h>
+#include <gst/audio/audio-enumtypes.h>
GST_DEBUG_CATEGORY_STATIC (gst_interleave_debug);
#define GST_CAT_DEFAULT gst_interleave_debug
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink_%u",
GST_PAD_SINK,
GST_PAD_REQUEST,
- GST_STATIC_CAPS ("audio/x-raw-int, "
+ GST_STATIC_CAPS ("audio/x-raw, "
"rate = (int) [ 1, MAX ], "
"channels = (int) 1, "
- "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, "
- "width = (int) { 8, 16, 24, 32 }, "
- "depth = (int) [ 1, 32 ], "
- "signed = (boolean) true; "
- "audio/x-raw-float, "
- "rate = (int) [ 1, MAX ], "
- "channels = (int) 1, "
- "endianness = (int) { LITTLE_ENDIAN , BIG_ENDIAN }, "
- "width = (int) { 32, 64 }")
+ "format = (string) " GST_AUDIO_FORMATS_ALL ", "
+ "layout = (string) {non-interleaved, interleaved}")
);
static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("audio/x-raw-int, "
- "rate = (int) [ 1, MAX ], "
- "channels = (int) [ 1, MAX ], "
- "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, "
- "width = (int) { 8, 16, 24, 32 }, "
- "depth = (int) [ 1, 32 ], "
- "signed = (boolean) true; "
- "audio/x-raw-float, "
+ GST_STATIC_CAPS ("audio/x-raw, "
"rate = (int) [ 1, MAX ], "
"channels = (int) [ 1, MAX ], "
- "endianness = (int) { LITTLE_ENDIAN , BIG_ENDIAN }, "
- "width = (int) { 32, 64 }")
+ "format = (string) " GST_AUDIO_FORMATS_ALL ", "
+ "layout = (string) interleaved")
);
#define MAKE_FUNC(type) \
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
}
-GST_BOILERPLATE (GstInterleave, gst_interleave, GstElement, GST_TYPE_ELEMENT);
+#define gst_interleave_parent_class parent_class
+G_DEFINE_TYPE (GstInterleave, gst_interleave, GST_TYPE_ELEMENT);
enum
{
guint prop_id, GValue * value, GParamSpec * pspec);
static GstPad *gst_interleave_request_new_pad (GstElement * element,
- GstPadTemplate * templ, const gchar * name);
+ GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
static void gst_interleave_release_pad (GstElement * element, GstPad * pad);
static GstStateChangeReturn gst_interleave_change_state (GstElement * element,
GstStateChange transition);
-static gboolean gst_interleave_src_query (GstPad * pad, GstQuery * query);
+static gboolean gst_interleave_src_query (GstPad * pad, GstObject * parent,
+ GstQuery * query);
-static gboolean gst_interleave_src_event (GstPad * pad, GstEvent * event);
+static gboolean gst_interleave_src_event (GstPad * pad, GstObject * parent,
+ GstEvent * event);
-static gboolean gst_interleave_sink_event (GstPad * pad, GstEvent * event);
+static gboolean gst_interleave_sink_event (GstCollectPads2 * pads,
+ GstCollectData2 * data, GstEvent * event, gpointer user_data);
-static gboolean gst_interleave_sink_setcaps (GstPad * pad, GstCaps * caps);
+static gboolean gst_interleave_sink_setcaps (GstInterleave * self,
+ GstPad * pad, const GstCaps * caps);
-static GstCaps *gst_interleave_sink_getcaps (GstPad * pad);
+static GstCaps *gst_interleave_sink_getcaps (GstPad * pad, GstObject * parent,
+ GstCaps * filter);
static GstFlowReturn gst_interleave_collected (GstCollectPads2 * pads,
GstInterleave * self);
if (self->channel_positions
&& self->channel_positions != self->input_channel_positions) {
- g_value_array_free (self->channel_positions);
+ g_array_free (self->channel_positions, TRUE);
self->channel_positions = NULL;
}
if (self->input_channel_positions) {
- g_value_array_free (self->input_channel_positions);
+ g_array_free (self->input_channel_positions, TRUE);
self->input_channel_positions = NULL;
}
}
static gboolean
-gst_interleave_check_channel_positions (GValueArray * positions)
+gst_interleave_check_channel_positions (GArray * positions)
{
gint i;
guint channels;
GstAudioChannelPosition *pos;
gboolean ret;
+ GValue val;
- channels = positions->n_values;
- pos = g_new (GstAudioChannelPosition, positions->n_values);
+ channels = positions->len;
+ pos = g_new (GstAudioChannelPosition, channels);
for (i = 0; i < channels; i++) {
- GValue *v = g_value_array_get_nth (positions, i);
-
- pos[i] = g_value_get_enum (v);
+ val = g_array_index (positions, GValue, i);
+ pos[i] = g_value_get_enum (&val);
+ g_value_reset (&val);
}
- ret = gst_audio_check_channel_positions (pos, channels);
+ ret = gst_audio_check_valid_channel_positions (pos, channels, FALSE);
g_free (pos);
return ret;
static void
gst_interleave_set_channel_positions (GstInterleave * self, GstStructure * s)
{
- GValue pos_array = { 0, };
gint i;
+ guint64 channel_mask = 0;
+ GValue val;
- g_value_init (&pos_array, GST_TYPE_ARRAY);
-
- if (self->channel_positions
- && self->channels == self->channel_positions->n_values
+ if (self->channel_positions && self->channels == self->channel_positions->len
&& gst_interleave_check_channel_positions (self->channel_positions)) {
GST_DEBUG_OBJECT (self, "Using provided channel positions");
- for (i = 0; i < self->channels; i++)
- gst_value_array_append_value (&pos_array,
- g_value_array_get_nth (self->channel_positions, i));
+ for (i = 0; i < self->channels; i++) {
+ val = g_array_index (self->channel_positions, GValue, i);
+ channel_mask |= G_GUINT64_CONSTANT (1) << g_value_get_enum (&val);
+ g_value_reset (&val);
+ }
} else {
- GValue pos_none = { 0, };
-
GST_WARNING_OBJECT (self, "Using NONE channel positions");
-
- g_value_init (&pos_none, GST_TYPE_AUDIO_CHANNEL_POSITION);
- g_value_set_enum (&pos_none, GST_AUDIO_CHANNEL_POSITION_NONE);
-
- for (i = 0; i < self->channels; i++)
- gst_value_array_append_value (&pos_array, &pos_none);
-
- g_value_unset (&pos_none);
}
- gst_structure_set_value (s, "channel-positions", &pos_array);
- g_value_unset (&pos_array);
-}
-
-static void
-gst_interleave_base_init (gpointer g_class)
-{
- gst_element_class_set_details_simple (g_class, "Audio interleaver",
- "Filter/Converter/Audio",
- "Folds many mono channels into one interleaved audio stream",
- "Andy Wingo <wingo at pobox.com>, "
- "Sebastian Dröge <slomo@circular-chaos.org>");
-
- gst_element_class_add_pad_template (g_class,
- gst_static_pad_template_get (&sink_template));
- gst_element_class_add_pad_template (g_class,
- gst_static_pad_template_get (&src_template));
+ gst_structure_set (s, "channel-mask", GST_TYPE_BITMASK, channel_mask, NULL);
}
static void
GST_DEBUG_CATEGORY_INIT (gst_interleave_debug, "interleave", 0,
"interleave element");
+ gst_element_class_set_details_simple (gstelement_class, "Audio interleaver",
+ "Filter/Converter/Audio",
+ "Folds many mono channels into one interleaved audio stream",
+ "Andy Wingo <wingo at pobox.com>, "
+ "Sebastian Dröge <slomo@circular-chaos.org>");
+
+ 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));
+
/* Reference GstInterleavePad class to have the type registered from
* a threadsafe context
*/
*
*/
g_object_class_install_property (gobject_class, PROP_CHANNEL_POSITIONS,
- g_param_spec_value_array ("channel-positions", "Channel positions",
- "Channel positions used on the output",
- g_param_spec_enum ("channel-position", "Channel position",
- "Channel position of the n-th input",
- GST_TYPE_AUDIO_CHANNEL_POSITION,
- GST_AUDIO_CHANNEL_POSITION_NONE,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS),
+ g_param_spec_boxed ("channel-positions", "Channel positions",
+ "Channel position of the n-th output", G_TYPE_ARRAY,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
}
static void
-gst_interleave_init (GstInterleave * self, GstInterleaveClass * klass)
+gst_interleave_init (GstInterleave * self)
{
self->src = gst_pad_new_from_static_template (&src_template, "src");
gst_pad_set_event_function (self->src,
GST_DEBUG_FUNCPTR (gst_interleave_src_event));
+ gst_pad_set_active (self->src, TRUE);
gst_element_add_pad (GST_ELEMENT (self), self->src);
self->collect = gst_collect_pads2_new ();
gst_collect_pads2_set_function (self->collect,
(GstCollectPads2Function) gst_interleave_collected, self);
- self->input_channel_positions = g_value_array_new (0);
+ self->input_channel_positions = g_array_new (FALSE, TRUE, sizeof (GValue));
self->channel_positions_from_input = TRUE;
self->channel_positions = self->input_channel_positions;
}
const GValue * value, GParamSpec * pspec)
{
GstInterleave *self = GST_INTERLEAVE (object);
+ int i;
+ GArray *arr;
switch (prop_id) {
case PROP_CHANNEL_POSITIONS:
if (self->channel_positions &&
self->channel_positions != self->input_channel_positions)
- g_value_array_free (self->channel_positions);
+ g_array_free (self->channel_positions, TRUE);
- self->channel_positions = g_value_dup_boxed (value);
+ arr = g_value_get_boxed (value);
+ self->channel_positions = g_array_new (FALSE, TRUE, sizeof (GValue));
+ for (i = 0; i < arr->len; i++)
+ g_array_append_val (self->channel_positions, g_array_index (arr, GValue,
+ i));
self->channel_positions_from_input = FALSE;
+ self->channels = self->channel_positions->len;
break;
case PROP_CHANNEL_POSITIONS_FROM_INPUT:
self->channel_positions_from_input = g_value_get_boolean (value);
if (self->channel_positions_from_input) {
if (self->channel_positions &&
self->channel_positions != self->input_channel_positions)
- g_value_array_free (self->channel_positions);
+ g_array_free (self->channel_positions, TRUE);
self->channel_positions = self->input_channel_positions;
}
break;
static GstPad *
gst_interleave_request_new_pad (GstElement * element, GstPadTemplate * templ,
- const gchar * req_name)
+ const gchar * req_name, const GstCaps * caps)
{
GstInterleave *self = GST_INTERLEAVE (element);
GstPad *new_pad;
if (templ->direction != GST_PAD_SINK)
goto not_sink_pad;
- channels = g_atomic_int_add (&self->channels, 1);
padnumber = g_atomic_int_add (&self->padcounter, 1);
+ if (self->channel_positions_from_input)
+ channels = g_atomic_int_add (&self->channels, 1);
+ else
+ channels = padnumber;
pad_name = g_strdup_printf ("sink_%u", padnumber);
new_pad = GST_PAD_CAST (g_object_new (GST_TYPE_INTERLEAVE_PAD,
GST_DEBUG_OBJECT (self, "requested new pad %s", pad_name);
g_free (pad_name);
- gst_pad_set_setcaps_function (new_pad,
- GST_DEBUG_FUNCPTR (gst_interleave_sink_setcaps));
- gst_pad_set_getcaps_function (new_pad,
- GST_DEBUG_FUNCPTR (gst_interleave_sink_getcaps));
+ gst_pad_use_fixed_caps (new_pad);
gst_collect_pads2_add_pad (self->collect, new_pad, sizeof (GstCollectData2));
- /* FIXME: hacked way to override/extend the event function of
- * GstCollectPads2; because it sets its own event function giving the
- * element no access to events */
- self->collect_event = (GstPadEventFunction) GST_PAD_EVENTFUNC (new_pad);
- gst_pad_set_event_function (new_pad,
- GST_DEBUG_FUNCPTR (gst_interleave_sink_event));
+ gst_collect_pads2_set_event_function (self->collect,
+ (GstCollectPads2EventFunction)
+ GST_DEBUG_FUNCPTR (gst_interleave_sink_event), self);
if (!gst_element_add_pad (element, new_pad))
goto could_not_add;
g_value_init (&val, GST_TYPE_AUDIO_CHANNEL_POSITION);
g_value_set_enum (&val, GST_AUDIO_CHANNEL_POSITION_NONE);
self->input_channel_positions =
- g_value_array_append (self->input_channel_positions, &val);
+ g_array_append_val (self->input_channel_positions, val);
g_value_unset (&val);
/* Update the src caps if we already have them */
gst_structure_set (s, "channels", G_TYPE_INT, self->channels, NULL);
gst_interleave_set_channel_positions (self, s);
+ gst_pad_set_active (self->src, TRUE);
gst_pad_set_caps (self->src, srccaps);
gst_caps_unref (srccaps);
{
GstInterleave *self = GST_INTERLEAVE (element);
GList *l;
+ GstAudioChannelPosition position;
g_return_if_fail (GST_IS_INTERLEAVE_PAD (pad));
g_atomic_int_add (&self->channels, -1);
- g_value_array_remove (self->input_channel_positions,
- GST_INTERLEAVE_PAD_CAST (pad)->channel);
+ position = GST_INTERLEAVE_PAD_CAST (pad)->channel;
+ g_array_remove_index (self->input_channel_positions, position);
/* Update channel numbers */
GST_OBJECT_LOCK (self);
gst_structure_set (s, "channels", G_TYPE_INT, self->channels, NULL);
gst_interleave_set_channel_positions (self, s);
+ gst_pad_set_active (self->src, TRUE);
gst_pad_set_caps (self->src, srccaps);
gst_caps_unref (srccaps);
} else {
gst_caps_replace (&self->sinkcaps, NULL);
- gst_pad_set_caps (self->src, NULL);
}
}
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
- gst_pad_set_caps (self->src, NULL);
gst_caps_replace (&self->sinkcaps, NULL);
break;
case GST_STATE_CHANGE_READY_TO_NULL:
size = gst_caps_get_size (caps);
for (i = 0; i < size; i++) {
s = gst_caps_get_structure (caps, i);
- gst_structure_remove_field (s, "channel-positions");
+ gst_structure_remove_field (s, "channel-mask");
gst_structure_remove_field (s, "channels");
}
}
/* we can only accept caps that we and downstream can handle. */
static GstCaps *
-gst_interleave_sink_getcaps (GstPad * pad)
+gst_interleave_sink_getcaps (GstPad * pad, GstObject * parent, GstCaps * filter)
{
- GstInterleave *self = GST_INTERLEAVE (gst_pad_get_parent (pad));
+ GstInterleave *self = GST_INTERLEAVE (parent);
GstCaps *result, *peercaps, *sinkcaps;
GST_OBJECT_LOCK (self);
result = gst_caps_copy (self->sinkcaps);
} else {
/* get the downstream possible caps */
- peercaps = gst_pad_peer_get_caps (self->src);
+ peercaps = gst_pad_peer_query_caps (self->src, NULL);
+
/* get the allowed caps on this sinkpad */
sinkcaps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
__remove_channels (sinkcaps);
GST_OBJECT_UNLOCK (self);
- gst_object_unref (self);
-
GST_DEBUG_OBJECT (pad, "Returning caps %" GST_PTR_FORMAT, result);
return result;
}
static gboolean
-gst_interleave_sink_setcaps (GstPad * pad, GstCaps * caps)
+gst_interleave_sink_setcaps (GstInterleave * self, GstPad * pad,
+ const GstCaps * caps)
{
- GstInterleave *self;
-
g_return_val_if_fail (GST_IS_INTERLEAVE_PAD (pad), FALSE);
- self = GST_INTERLEAVE (gst_pad_get_parent (pad));
-
/* First caps that are set on a sink pad are used as output caps */
/* TODO: handle caps changes */
if (self->sinkcaps && !gst_caps_is_subset (caps, self->sinkcaps)) {
GstCaps *srccaps;
GstStructure *s;
gboolean res;
+ GstAudioInfo info;
+ GValue *val;
+ guint channel;
- s = gst_caps_get_structure (caps, 0);
+ if (!gst_audio_info_from_caps (&info, caps))
+ goto invalid_caps;
- if (!gst_structure_get_int (s, "width", &self->width))
- goto no_width;
+ self->width = GST_AUDIO_INFO_WIDTH (&info);
+ self->rate = GST_AUDIO_INFO_RATE (&info);
- if (!gst_structure_get_int (s, "rate", &self->rate))
- goto no_rate;
gst_interleave_set_process_function (self);
+ channel = GST_INTERLEAVE_PAD_CAST (pad)->channel;
- if (gst_structure_has_field (s, "channel-positions")) {
- const GValue *pos_array;
-
- pos_array = gst_structure_get_value (s, "channel-positions");
- if (GST_VALUE_HOLDS_ARRAY (pos_array)
- && gst_value_array_get_size (pos_array) == 1) {
- const GValue *pos = gst_value_array_get_value (pos_array, 0);
-
- GValue *apos = g_value_array_get_nth (self->input_channel_positions,
- GST_INTERLEAVE_PAD_CAST (pad)->channel);
-
- g_value_set_enum (apos, g_value_get_enum (pos));
- }
+ if (self->channel_positions_from_input
+ && GST_AUDIO_INFO_CHANNELS (&info) == 1) {
+ val = &g_array_index (self->input_channel_positions, GValue, channel);
+ g_value_set_enum (val, GST_AUDIO_INFO_POSITION (&info, 0));
}
srccaps = gst_caps_copy (caps);
s = gst_caps_get_structure (srccaps, 0);
+ gst_structure_remove_field (s, "channel-mask");
+
gst_structure_set (s, "channels", G_TYPE_INT, self->channels, NULL);
gst_interleave_set_channel_positions (self, s);
+ gst_pad_set_active (self->src, TRUE);
res = gst_pad_set_caps (self->src, srccaps);
gst_caps_unref (srccaps);
GstCaps *sinkcaps = gst_caps_copy (caps);
GstStructure *s = gst_caps_get_structure (sinkcaps, 0);
- gst_structure_remove_field (s, "channel-positions");
+ gst_structure_remove_field (s, "channel-mask");
gst_caps_replace (&self->sinkcaps, sinkcaps);
gst_caps_unref (sinkcaps);
}
- gst_object_unref (self);
-
return TRUE;
cannot_change_caps:
{
GST_WARNING_OBJECT (self, "caps of %" GST_PTR_FORMAT " already set, can't "
"change", self->sinkcaps);
- gst_object_unref (self);
return FALSE;
}
src_did_not_accept:
{
GST_WARNING_OBJECT (self, "src did not accept setcaps()");
- gst_object_unref (self);
return FALSE;
}
-no_width:
+invalid_caps:
{
- GST_WARNING_OBJECT (self, "caps did not have width: %" GST_PTR_FORMAT,
- caps);
- gst_object_unref (self);
- return FALSE;
- }
-no_rate:
- {
- GST_WARNING_OBJECT (self, "caps did not have rate: %" GST_PTR_FORMAT, caps);
- gst_object_unref (self);
+ GST_WARNING_OBJECT (self, "invalid sink caps");
return FALSE;
}
}
static gboolean
-gst_interleave_sink_event (GstPad * pad, GstEvent * event)
+gst_interleave_sink_event (GstCollectPads2 * pads, GstCollectData2 * data,
+ GstEvent * event, gpointer user_data)
{
- GstInterleave *self = GST_INTERLEAVE (gst_pad_get_parent (pad));
- gboolean ret;
+ GstInterleave *self = GST_INTERLEAVE (user_data);
+ gboolean ret = FALSE;
GST_DEBUG ("Got %s event on pad %s:%s", GST_EVENT_TYPE_NAME (event),
- GST_DEBUG_PAD_NAME (pad));
+ GST_DEBUG_PAD_NAME (data->pad));
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_FLUSH_STOP:
*/
self->segment_pending = TRUE;
break;
+ case GST_EVENT_CAPS:
+ {
+ GstCaps *caps;
+
+ gst_event_parse_caps (event, &caps);
+ ret = gst_interleave_sink_setcaps (self, data->pad, caps);
+ gst_event_unref (event);
+ break;
+ }
default:
+ ret = gst_pad_event_default (data->pad, GST_OBJECT (self), event);
break;
}
/* now GstCollectPads2 can take care of the rest, e.g. EOS */
- ret = self->collect_event (pad, event);
-
- gst_object_unref (self);
return ret;
}
while (!done) {
GstIteratorResult ires;
- gpointer item;
+ GValue item = { 0, };
ires = gst_iterator_next (it, &item);
switch (ires) {
break;
case GST_ITERATOR_OK:
{
- GstPad *pad = GST_PAD_CAST (item);
+ GstPad *pad = GST_PAD_CAST (g_value_dup_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 max from all valid return values */
if (res) {
/* valid unknown length, stop searching */
max = duration;
}
gst_object_unref (pad);
+ g_value_unset (&item);
break;
}
case GST_ITERATOR_RESYNC:
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) {
break;
case GST_ITERATOR_OK:
{
- GstPad *pad = GST_PAD_CAST (item);
+ GstPad *pad = GST_PAD_CAST (g_value_dup_object (&item));
GstQuery *peerquery;
GstClockTime min_cur, max_cur;
gboolean live_cur;
gst_query_unref (peerquery);
gst_object_unref (pad);
+ g_value_unset (&item);
break;
}
case GST_ITERATOR_RESYNC:
}
static gboolean
-gst_interleave_src_query (GstPad * pad, GstQuery * query)
+gst_interleave_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
{
- GstInterleave *self = GST_INTERLEAVE (gst_pad_get_parent (pad));
+ GstInterleave *self = GST_INTERLEAVE (parent);
gboolean res = FALSE;
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_LATENCY:
res = gst_interleave_src_query_latency (self, query);
break;
+ case GST_QUERY_CAPS:
+ {
+ GstCaps *filter, *caps;
+
+ gst_query_parse_caps (query, &filter);
+ caps = gst_interleave_sink_getcaps (pad, parent, filter);
+ gst_query_set_caps_result (query, caps);
+ gst_caps_unref (caps);
+ res = TRUE;
+ }
default:
/* FIXME, needs a custom query handler because we have multiple
* sinkpads */
- res = gst_pad_query_default (pad, query);
+ res = gst_pad_query_default (pad, parent, query);
break;
}
- gst_object_unref (self);
return res;
}
static gboolean
-forward_event_func (GstPad * pad, GValue * ret, GstEvent * event)
+forward_event_func (const GValue * item, GValue * ret, GstEvent * event)
{
+ GstPad *pad = GST_PAD_CAST (g_value_dup_object (item));
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)) {
static gboolean
-gst_interleave_src_event (GstPad * pad, GstEvent * event)
+gst_interleave_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
{
- GstInterleave *self = GST_INTERLEAVE (gst_pad_get_parent (pad));
+ GstInterleave *self = GST_INTERLEAVE (parent);
gboolean result;
switch (GST_EVENT_TYPE (event)) {
result = forward_event (self, event);
break;
}
- gst_object_unref (self);
return result;
}
guint ncollected = 0;
gboolean empty = TRUE;
gint width = self->width / 8;
+ GstMapInfo write_info;
g_return_val_if_fail (self->func != NULL, GST_FLOW_NOT_NEGOTIATED);
g_return_val_if_fail (self->width > 0, GST_FLOW_NOT_NEGOTIATED);
nsamples = size / width;
- ret =
- gst_pad_alloc_buffer (self->src, GST_BUFFER_OFFSET_NONE,
- size * self->channels, GST_PAD_CAPS (self->src), &outbuf);
+ outbuf = gst_buffer_new_allocate (NULL, size * self->channels, 0);
- if (ret != GST_FLOW_OK) {
- return ret;
- } else if (outbuf == NULL || GST_BUFFER_SIZE (outbuf) < size * self->channels) {
- gst_buffer_unref (outbuf);
- return GST_FLOW_NOT_NEGOTIATED;
- } else if (!gst_caps_is_equal (GST_BUFFER_CAPS (outbuf),
- GST_PAD_CAPS (self->src))) {
+ if (outbuf == NULL || gst_buffer_get_size (outbuf) < size * self->channels) {
gst_buffer_unref (outbuf);
return GST_FLOW_NOT_NEGOTIATED;
}
- memset (GST_BUFFER_DATA (outbuf), 0, size * self->channels);
+ gst_buffer_map (outbuf, &write_info, GST_MAP_WRITE);
+ memset (write_info.data, 0, size * self->channels);
for (collected = pads->data; collected != NULL; collected = collected->next) {
GstCollectData2 *cdata;
GstBuffer *inbuf;
guint8 *outdata;
+ GstMapInfo input_info;
cdata = (GstCollectData2 *) collected->data;
goto next;
}
ncollected++;
+ gst_buffer_map (inbuf, &input_info, GST_MAP_READ);
if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_GAP))
goto next;
empty = FALSE;
outdata =
- GST_BUFFER_DATA (outbuf) +
- width * GST_INTERLEAVE_PAD_CAST (cdata->pad)->channel;
+ write_info.data + width * GST_INTERLEAVE_PAD_CAST (cdata->pad)->channel;
- self->func (outdata, GST_BUFFER_DATA (inbuf), self->channels, nsamples);
+ self->func (outdata, input_info.data, self->channels, nsamples);
+ gst_buffer_unmap (inbuf, &input_info);
next:
if (inbuf)
gst_buffer_unref (inbuf);
}
- if (ncollected == 0)
+ if (ncollected == 0) {
+ gst_buffer_unmap (outbuf, &write_info);
goto eos;
+ }
if (self->segment_pending) {
GstEvent *event;
- event = gst_event_new_new_segment_full (FALSE, self->segment_rate,
- 1.0, GST_FORMAT_TIME, self->timestamp, -1, self->segment_position);
+ self->segment.format = GST_FORMAT_TIME;
+ event = gst_event_new_segment (&self->segment);
gst_pad_push_event (self->src, event);
self->segment_pending = FALSE;
if (empty)
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_GAP);
+ gst_buffer_unmap (outbuf, &write_info);
+
GST_LOG_OBJECT (self, "pushing outbuf, timestamp %" GST_TIME_FORMAT,
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)));
ret = gst_pad_push (self->src, outbuf);