mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-03 09:12:19 +00:00
interleave: port to 0.11
Port of the interleave element and its unittests. https://bugzilla.gnome.org/show_bug.cgi?id=669643
This commit is contained in:
parent
6623ab258b
commit
4945af5eff
6 changed files with 222 additions and 213 deletions
|
@ -1,13 +1,13 @@
|
|||
|
||||
plugin_LTLIBRARIES = libgstinterleave.la
|
||||
|
||||
libgstinterleave_la_SOURCES = plugin.c deinterleave.c
|
||||
libgstinterleave_la_SOURCES = plugin.c interleave.c deinterleave.c
|
||||
libgstinterleave_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS)
|
||||
libgstinterleave_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_MAJORMINOR) $(GST_BASE_LIBS) $(GST_LIBS)
|
||||
libgstinterleave_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
||||
libgstinterleave_la_LIBTOOLFLAGS = --tag=disable-static
|
||||
|
||||
noinst_HEADERS = plugin.h deinterleave.h
|
||||
noinst_HEADERS = plugin.h interleave.h deinterleave.h
|
||||
|
||||
Android.mk: Makefile.am $(BUILT_SOURCES)
|
||||
androgenizer \
|
||||
|
|
|
@ -47,12 +47,12 @@
|
|||
* <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>
|
||||
*/
|
||||
|
@ -65,7 +65,8 @@
|
|||
#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
|
||||
|
@ -73,35 +74,21 @@ GST_DEBUG_CATEGORY_STATIC (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, "
|
||||
GST_STATIC_CAPS ("audio/x-raw, "
|
||||
"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, "
|
||||
"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) \
|
||||
|
@ -196,7 +183,8 @@ gst_interleave_pad_class_init (GstPadClass * klass)
|
|||
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
|
||||
{
|
||||
|
@ -211,21 +199,26 @@ static void gst_interleave_get_property (GObject * object,
|
|||
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);
|
||||
|
@ -242,12 +235,12 @@ gst_interleave_finalize (GObject * object)
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -257,23 +250,24 @@ gst_interleave_finalize (GObject * object)
|
|||
}
|
||||
|
||||
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;
|
||||
|
@ -282,48 +276,22 @@ gst_interleave_check_channel_positions (GValueArray * positions)
|
|||
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
|
||||
|
@ -338,6 +306,17 @@ gst_interleave_class_init (GstInterleaveClass * klass)
|
|||
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
|
||||
*/
|
||||
|
@ -362,13 +341,8 @@ gst_interleave_class_init (GstInterleaveClass * klass)
|
|||
*
|
||||
*/
|
||||
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));
|
||||
|
||||
/**
|
||||
|
@ -396,7 +370,7 @@ gst_interleave_class_init (GstInterleaveClass * klass)
|
|||
}
|
||||
|
||||
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");
|
||||
|
||||
|
@ -405,13 +379,14 @@ gst_interleave_init (GstInterleave * self, GstInterleaveClass * klass)
|
|||
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;
|
||||
}
|
||||
|
@ -421,15 +396,22 @@ gst_interleave_set_property (GObject * object, guint prop_id,
|
|||
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);
|
||||
|
@ -437,7 +419,7 @@ gst_interleave_set_property (GObject * object, guint prop_id,
|
|||
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;
|
||||
|
@ -468,7 +450,7 @@ gst_interleave_get_property (GObject * object, guint prop_id,
|
|||
|
||||
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;
|
||||
|
@ -479,8 +461,11 @@ gst_interleave_request_new_pad (GstElement * element, GstPadTemplate * templ,
|
|||
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,
|
||||
|
@ -490,19 +475,13 @@ gst_interleave_request_new_pad (GstElement * element, GstPadTemplate * templ,
|
|||
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;
|
||||
|
@ -510,7 +489,7 @@ gst_interleave_request_new_pad (GstElement * element, GstPadTemplate * templ,
|
|||
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 */
|
||||
|
@ -527,6 +506,7 @@ gst_interleave_request_new_pad (GstElement * element, GstPadTemplate * templ,
|
|||
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);
|
||||
|
||||
|
@ -555,6 +535,7 @@ gst_interleave_release_pad (GstElement * element, GstPad * pad)
|
|||
{
|
||||
GstInterleave *self = GST_INTERLEAVE (element);
|
||||
GList *l;
|
||||
GstAudioChannelPosition position;
|
||||
|
||||
g_return_if_fail (GST_IS_INTERLEAVE_PAD (pad));
|
||||
|
||||
|
@ -563,8 +544,8 @@ gst_interleave_release_pad (GstElement * element, GstPad * 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);
|
||||
|
@ -588,11 +569,11 @@ gst_interleave_release_pad (GstElement * element, GstPad * pad)
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -641,7 +622,6 @@ gst_interleave_change_state (GstElement * element, GstStateChange transition)
|
|||
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:
|
||||
|
@ -662,7 +642,7 @@ __remove_channels (GstCaps * caps)
|
|||
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");
|
||||
}
|
||||
}
|
||||
|
@ -685,9 +665,9 @@ __set_channels (GstCaps * caps, gint 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);
|
||||
|
@ -697,7 +677,8 @@ gst_interleave_sink_getcaps (GstPad * pad)
|
|||
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);
|
||||
|
@ -719,8 +700,6 @@ gst_interleave_sink_getcaps (GstPad * pad)
|
|||
|
||||
GST_OBJECT_UNLOCK (self);
|
||||
|
||||
gst_object_unref (self);
|
||||
|
||||
GST_DEBUG_OBJECT (pad, "Returning caps %" GST_PTR_FORMAT, result);
|
||||
|
||||
return result;
|
||||
|
@ -752,14 +731,11 @@ gst_interleave_set_process_function (GstInterleave * self)
|
|||
}
|
||||
|
||||
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)) {
|
||||
|
@ -768,38 +744,35 @@ gst_interleave_sink_setcaps (GstPad * pad, GstCaps * caps)
|
|||
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);
|
||||
|
||||
|
@ -811,53 +784,42 @@ gst_interleave_sink_setcaps (GstPad * pad, GstCaps * caps)
|
|||
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:
|
||||
|
@ -869,14 +831,21 @@ gst_interleave_sink_event (GstPad * pad, GstEvent * event)
|
|||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -901,7 +870,7 @@ gst_interleave_src_query_duration (GstInterleave * self, GstQuery * query)
|
|||
while (!done) {
|
||||
GstIteratorResult ires;
|
||||
|
||||
gpointer item;
|
||||
GValue item = { 0, };
|
||||
|
||||
ires = gst_iterator_next (it, &item);
|
||||
switch (ires) {
|
||||
|
@ -910,12 +879,12 @@ gst_interleave_src_query_duration (GstInterleave * self, GstQuery * query)
|
|||
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 */
|
||||
|
@ -928,6 +897,7 @@ gst_interleave_src_query_duration (GstInterleave * self, GstQuery * query)
|
|||
max = duration;
|
||||
}
|
||||
gst_object_unref (pad);
|
||||
g_value_unset (&item);
|
||||
break;
|
||||
}
|
||||
case GST_ITERATOR_RESYNC:
|
||||
|
@ -978,7 +948,7 @@ gst_interleave_src_query_latency (GstInterleave * 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) {
|
||||
|
@ -987,7 +957,7 @@ gst_interleave_src_query_latency (GstInterleave * self, GstQuery * query)
|
|||
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;
|
||||
|
@ -1014,6 +984,7 @@ gst_interleave_src_query_latency (GstInterleave * self, GstQuery * query)
|
|||
|
||||
gst_query_unref (peerquery);
|
||||
gst_object_unref (pad);
|
||||
g_value_unset (&item);
|
||||
break;
|
||||
}
|
||||
case GST_ITERATOR_RESYNC:
|
||||
|
@ -1043,9 +1014,9 @@ gst_interleave_src_query_latency (GstInterleave * self, GstQuery * query)
|
|||
}
|
||||
|
||||
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)) {
|
||||
|
@ -1081,20 +1052,30 @@ gst_interleave_src_query (GstPad * pad, GstQuery * 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)) {
|
||||
|
@ -1131,9 +1112,9 @@ forward_event (GstInterleave * self, GstEvent * 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)) {
|
||||
|
@ -1183,7 +1164,6 @@ gst_interleave_src_event (GstPad * pad, GstEvent * event)
|
|||
result = forward_event (self, event);
|
||||
break;
|
||||
}
|
||||
gst_object_unref (self);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -1199,6 +1179,7 @@ gst_interleave_collected (GstCollectPads2 * pads, GstInterleave * self)
|
|||
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);
|
||||
|
@ -1214,27 +1195,21 @@ gst_interleave_collected (GstCollectPads2 * pads, GstInterleave * self)
|
|||
|
||||
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;
|
||||
|
||||
|
@ -1244,30 +1219,33 @@ gst_interleave_collected (GstCollectPads2 * pads, GstInterleave * self)
|
|||
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;
|
||||
|
@ -1287,6 +1265,8 @@ gst_interleave_collected (GstCollectPads2 * pads, GstInterleave * self)
|
|||
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);
|
||||
|
|
|
@ -56,8 +56,8 @@ struct _GstInterleave
|
|||
gint rate;
|
||||
gint width;
|
||||
|
||||
GValueArray *channel_positions;
|
||||
GValueArray *input_channel_positions;
|
||||
GArray* channel_positions;
|
||||
GArray* input_channel_positions;
|
||||
gboolean channel_positions_from_input;
|
||||
|
||||
GstCaps *sinkcaps;
|
||||
|
|
|
@ -28,16 +28,16 @@
|
|||
static gboolean
|
||||
plugin_init (GstPlugin * plugin)
|
||||
{
|
||||
#if 0
|
||||
if (!gst_element_register (plugin, "interleave",
|
||||
GST_RANK_NONE, gst_interleave_get_type ()) ||
|
||||
#endif
|
||||
if (!gst_element_register (plugin, "deinterleave",
|
||||
GST_RANK_NONE, gst_deinterleave_get_type ()))
|
||||
return FALSE; return TRUE;}
|
||||
!gst_element_register (plugin, "deinterleave",
|
||||
GST_RANK_NONE, gst_deinterleave_get_type ()))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
|
||||
GST_VERSION_MINOR,
|
||||
"interleave",
|
||||
"Audio interleaver/deinterleaver",
|
||||
plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);
|
||||
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
|
||||
GST_VERSION_MINOR,
|
||||
"interleave",
|
||||
"Audio interleaver/deinterleaver",
|
||||
plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);
|
||||
|
|
|
@ -25,9 +25,7 @@
|
|||
|
||||
|
||||
#include <gst/gst.h>
|
||||
#if 0
|
||||
#include "interleave.h"
|
||||
#endif
|
||||
#include "deinterleave.h"
|
||||
|
||||
#endif /* __GST_PLUGIN_INTERLEAVE_H__ */
|
||||
|
|
|
@ -18,10 +18,6 @@
|
|||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* FIXME 0.11: suppress warnings for deprecated API such as GValueArray
|
||||
* with newer GLib versions (>= 2.31.0) */
|
||||
#define GLIB_DISABLE_DEPRECATION_WARNINGS
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
@ -81,19 +77,19 @@ static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
|
|||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("audio/x-raw, "
|
||||
"format = (string) " GST_AUDIO_NE (F32) ", "
|
||||
"channels = (int) 2, " "rate = (int) 48000"));
|
||||
"channels = (int) 2, layout = (string) {interleaved, non-interleaved}, rate = (int) 48000"));
|
||||
|
||||
static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("audio/x-raw, "
|
||||
"format = (string) " GST_AUDIO_NE (F32) ", "
|
||||
"channels = (int) 1, " "rate = (int) 48000"));
|
||||
"channels = (int) 1, layout = (string) interleaved, rate = (int) 48000"));
|
||||
|
||||
#define CAPS_48khz \
|
||||
"audio/x-raw, " \
|
||||
"format = (string) " GST_AUDIO_NE (F32) ", " \
|
||||
"channels = (int) 1, " \
|
||||
"channels = (int) 1, layout = (string) non-interleaved," \
|
||||
"rate = (int) 48000"
|
||||
|
||||
static GstFlowReturn
|
||||
|
@ -153,12 +149,14 @@ GST_START_TEST (test_interleave_2ch)
|
|||
fail_unless (mysrcpads[0] != NULL);
|
||||
|
||||
caps = gst_caps_from_string (CAPS_48khz);
|
||||
gst_pad_set_active (mysrcpads[0], TRUE);
|
||||
fail_unless (gst_pad_set_caps (mysrcpads[0], caps));
|
||||
gst_pad_use_fixed_caps (mysrcpads[0]);
|
||||
|
||||
mysrcpads[1] = gst_pad_new_from_static_template (&srctemplate, "src1");
|
||||
fail_unless (mysrcpads[1] != NULL);
|
||||
|
||||
gst_pad_set_active (mysrcpads[1], TRUE);
|
||||
fail_unless (gst_pad_set_caps (mysrcpads[1], caps));
|
||||
gst_pad_use_fixed_caps (mysrcpads[1]);
|
||||
|
||||
|
@ -281,12 +279,14 @@ GST_START_TEST (test_interleave_2ch_1eos)
|
|||
fail_unless (mysrcpads[0] != NULL);
|
||||
|
||||
caps = gst_caps_from_string (CAPS_48khz);
|
||||
gst_pad_set_active (mysrcpads[0], TRUE);
|
||||
fail_unless (gst_pad_set_caps (mysrcpads[0], caps));
|
||||
gst_pad_use_fixed_caps (mysrcpads[0]);
|
||||
|
||||
mysrcpads[1] = gst_pad_new_from_static_template (&srctemplate, "src1");
|
||||
fail_unless (mysrcpads[1] != NULL);
|
||||
|
||||
gst_pad_set_active (mysrcpads[1], TRUE);
|
||||
fail_unless (gst_pad_set_caps (mysrcpads[1], caps));
|
||||
gst_pad_use_fixed_caps (mysrcpads[1]);
|
||||
|
||||
|
@ -381,6 +381,34 @@ src_handoff_float32 (GstElement * element, GstBuffer * buffer, GstPad * pad,
|
|||
gfloat *data;
|
||||
gint i;
|
||||
gsize size;
|
||||
GstCaps *caps;
|
||||
guint64 mask;
|
||||
GstAudioChannelPosition pos;
|
||||
|
||||
switch (n) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
pos = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
|
||||
break;
|
||||
case 3:
|
||||
pos = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
|
||||
break;
|
||||
default:
|
||||
pos = GST_AUDIO_CHANNEL_POSITION_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
mask = G_GUINT64_CONSTANT (1) << pos;
|
||||
|
||||
caps = gst_caps_new_simple ("audio/x-raw",
|
||||
"format", G_TYPE_STRING, GST_AUDIO_NE (F32),
|
||||
"channels", G_TYPE_INT, 1,
|
||||
"layout", G_TYPE_STRING, "interleaved",
|
||||
"channel-mask", GST_TYPE_BITMASK, mask, "rate", G_TYPE_INT, 48000, NULL);
|
||||
|
||||
gst_pad_set_caps (pad, caps);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
size = 48000 * sizeof (gfloat);
|
||||
data = g_malloc (size);
|
||||
|
@ -433,7 +461,8 @@ sink_handoff_float32 (GstElement * element, GstBuffer * buffer, GstPad * pad,
|
|||
caps = gst_caps_new_simple ("audio/x-raw",
|
||||
"format", G_TYPE_STRING, GST_AUDIO_NE (F32),
|
||||
"channels", G_TYPE_INT, 2, "rate", G_TYPE_INT, 48000,
|
||||
"channel-mask", GST_TYPE_BITMASK, &mask, NULL);
|
||||
"layout", G_TYPE_STRING, "interleaved",
|
||||
"channel-mask", GST_TYPE_BITMASK, mask, NULL);
|
||||
|
||||
ccaps = gst_pad_get_current_caps (pad);
|
||||
fail_unless (gst_caps_is_equal (caps, ccaps));
|
||||
|
@ -619,7 +648,7 @@ GST_START_TEST (test_interleave_2ch_pipeline_custom_chanpos)
|
|||
GstElement *pipeline, *queue, *src1, *src2, *interleave, *sink;
|
||||
GstPad *sinkpad0, *sinkpad1, *tmp, *tmp2;
|
||||
GstMessage *msg;
|
||||
GValueArray *arr;
|
||||
GArray *arr;
|
||||
GValue val = { 0, };
|
||||
|
||||
have_data = 0;
|
||||
|
@ -650,16 +679,18 @@ GST_START_TEST (test_interleave_2ch_pipeline_custom_chanpos)
|
|||
interleave = gst_element_factory_make ("interleave", "interleave");
|
||||
fail_unless (interleave != NULL);
|
||||
g_object_set (interleave, "channel-positions-from-input", FALSE, NULL);
|
||||
arr = g_value_array_new (2);
|
||||
arr = g_array_new (FALSE, TRUE, sizeof (GValue));
|
||||
|
||||
g_value_init (&val, GST_TYPE_AUDIO_CHANNEL_POSITION);
|
||||
g_value_set_enum (&val, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER);
|
||||
g_value_array_append (arr, &val);
|
||||
g_array_append_val (arr, val);
|
||||
g_value_reset (&val);
|
||||
g_value_set_enum (&val, GST_AUDIO_CHANNEL_POSITION_REAR_CENTER);
|
||||
g_value_array_append (arr, &val);
|
||||
g_array_append_val (arr, val);
|
||||
g_value_unset (&val);
|
||||
|
||||
g_object_set (interleave, "channel-positions", arr, NULL);
|
||||
g_value_array_free (arr);
|
||||
g_array_free (arr, TRUE);
|
||||
gst_bin_add (GST_BIN (pipeline), gst_object_ref (interleave));
|
||||
|
||||
sinkpad0 = gst_element_get_request_pad (interleave, "sink_%u");
|
||||
|
|
Loading…
Reference in a new issue