Commit d5085251 authored by Carlos Rafael Giani's avatar Carlos Rafael Giani Committed by Sebastian Dröge

rawparse: Add new raw audio and video parser elements

The new rawaudioparse and rawvideoparse elements are based on GstBaseParse
and completely replace audioparse and videoparse

https://bugzilla.gnome.org/show_bug.cgi?id=767011
parent f6e62647
......@@ -4,8 +4,12 @@ plugin_LTLIBRARIES = libgstrawparse.la
libgstrawparse_la_SOURCES = \
gstrawparse.c \
gstunalignedaudioparse.c \
gstunalignedvideoparse.c \
gstaudioparse.c \
gstvideoparse.c \
gstrawbaseparse.c \
gstrawaudioparse.c \
gstrawvideoparse.c \
plugin.c
libgstrawparse_la_CFLAGS = \
$(GST_PLUGINS_BASE_CFLAGS) \
......@@ -21,7 +25,12 @@ libgstrawparse_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
noinst_HEADERS = \
unalignedaudio.h \
unalignedvideo.h \
gstunalignedaudioparse.h \
gstunalignedvideoparse.h \
gstaudioparse.h \
gstrawparse.h \
gstvideoparse.h
gstvideoparse.h \
gstrawbaseparse.h \
gstrawaudioparse.h \
gstrawvideoparse.h
/* GStreamer
* Copyright (C) <2016> Carlos Rafael Giani <dv at pseudoterminal dot org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/**
* SECTION:element-rawaudioparse
*
* This element parses incoming data as raw audio samples and timestamps it.
* It also handles seek queries in said raw audio data, and ensures that output
* buffers contain an integer number of samples, even if the input buffers don't.
* For example, with sample format S16LE and 2 channels, an input buffer of 411
* bytes contains 102.75 samples. rawaudioparse will then output 102 samples
* (= 408 bytes) and keep the remaining 3 bytes. These will then be prepended to
* the next input data.
*
* The element implements the properties and sink caps configuration as specified
* in the #GstRawBaseParse documentation. The properties configuration can be
* modified by using the sample-rate, num-channels, channel-positions, format,
* and pcm-format properties.
*
* Currently, this parser supports raw data in a-law, mu-law, or linear PCM format.
*
* To facilitate operation with the unalignedaudioparse element, rawaudioparse
* supports the "audio/x-unaligned-raw" media type. This is treated identically to
* "audio/x-raw", except that it is used by source elements which do not guarantee
* that the buffers they push out are timestamped and contain an integer amount of
* samples (see the 411 bytes example above). By using a different media type, it
* is guaranteed that unalignedaudioparse is autoplugged, making sure that the
* autoplugged chain does not push unparsed content downstream. The source caps'
* media type with linear PCM data is always "audio/x-raw", even if the sink caps
* use "audio/x-unaligned-raw".
*
* The channel-positions property can be used to set explicit position information
* for each channel. If the array that is passed to this property does not match
* the number of channels indicated by num-channels, then said number of channels
* is updated to the array length. If channel-positions is NULL, then the default
* GStreamer positioning is used. This property is also useful for swapping left
* and right in a stereo signal for example.
*
* <refsect2>
* <title>Example pipelines</title>
* |[
* gst-launch-1.0 souphttpsrc http://my-dlna-server/track.l16 \
* rawaudioparse ! audioconvert ! audioresample ! autoaudiosink
* ]| Receive L16 data from a DLNA server, parse and timestamp it with
* rawaudioparse, and play it. use-sink-caps is set to true since souphttpsrc
* will set its source pad's caps to audio/x-unaligned-raw for the L16 stream.
* |[
* gst-launch-1.0 filesrc location=audio.raw ! rawaudioparse use-sink-caps=false \
* format=pcm pcm-format=s16le sample-rate=48000 num-channels=2 \
* audioconvert ! audioresample ! autoaudiosink
* ]| Read raw data from a local file and parse it as PCM data with 48000 Hz sample
* rate, signed 16 bit integer samples, and 2 channels. use-sink-caps is set to
* false to ensure the property information is used and the parser does not expect
* audio/x-raw or audio/x-unaligned-raw caps.
* </refsect2>
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
/* FIXME: GValueArray is deprecated, but there is currently no viabla alternative
* See https://bugzilla.gnome.org/show_bug.cgi?id=667228 */
#define GLIB_DISABLE_DEPRECATION_WARNINGS
#include <string.h>
#include "gstrawaudioparse.h"
#include "unalignedaudio.h"
GST_DEBUG_CATEGORY_STATIC (raw_audio_parse_debug);
#define GST_CAT_DEFAULT raw_audio_parse_debug
enum
{
PROP_0,
PROP_FORMAT,
PROP_PCM_FORMAT,
PROP_SAMPLE_RATE,
PROP_NUM_CHANNELS,
PROP_INTERLEAVED,
PROP_CHANNEL_POSITIONS
};
#define DEFAULT_FORMAT GST_RAW_AUDIO_PARSE_FORMAT_PCM
#define DEFAULT_PCM_FORMAT GST_AUDIO_FORMAT_S16
#define DEFAULT_SAMPLE_RATE 44100
#define DEFAULT_NUM_CHANNELS 2
#define DEFAULT_INTERLEAVED TRUE
#define GST_RAW_AUDIO_PARSE_CAPS \
GST_AUDIO_CAPS_MAKE(GST_AUDIO_FORMATS_ALL) \
", layout = (string) { interleaved, non-interleaved }; " \
"audio/x-alaw, rate = (int) [ 1, MAX ], channels = (int) [ 1, MAX ]; " \
"audio/x-mulaw, rate = (int) [ 1, MAX ], channels = (int) [ 1, MAX ]; "
static GstStaticPadTemplate static_sink_template =
GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS (GST_UNALIGNED_RAW_AUDIO_CAPS "; " GST_RAW_AUDIO_PARSE_CAPS)
);
static GstStaticPadTemplate static_src_template =
GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS (GST_RAW_AUDIO_PARSE_CAPS)
);
#define gst_raw_audio_parse_parent_class parent_class
G_DEFINE_TYPE (GstRawAudioParse, gst_raw_audio_parse, GST_TYPE_RAW_BASE_PARSE);
static void gst_raw_audio_parse_set_property (GObject * object, guint prop_id,
GValue const *value, GParamSpec * pspec);
static void gst_raw_audio_parse_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static gboolean gst_raw_audio_parse_stop (GstBaseParse * parse);
static gboolean gst_raw_audio_parse_set_current_config (GstRawBaseParse *
raw_base_parse, GstRawBaseParseConfig config);
static GstRawBaseParseConfig
gst_raw_audio_parse_get_current_config (GstRawBaseParse * raw_base_parse);
static gboolean gst_raw_audio_parse_set_config_from_caps (GstRawBaseParse *
raw_base_parse, GstRawBaseParseConfig config, GstCaps * caps);
static gboolean gst_raw_audio_parse_get_caps_from_config (GstRawBaseParse *
raw_base_parse, GstRawBaseParseConfig config, GstCaps ** caps);
static gsize gst_raw_audio_parse_get_config_frame_size (GstRawBaseParse *
raw_base_parse, GstRawBaseParseConfig config);
static gboolean gst_raw_audio_parse_is_config_ready (GstRawBaseParse *
raw_base_parse, GstRawBaseParseConfig config);
static gboolean gst_raw_audio_parse_process (GstRawBaseParse * raw_base_parse,
GstRawBaseParseConfig config, GstBuffer * in_data, gsize total_num_in_bytes,
gsize num_valid_in_bytes, GstBuffer ** processed_data);
static gboolean gst_raw_audio_parse_is_unit_format_supported (GstRawBaseParse *
raw_base_parse, GstFormat format);
static void gst_raw_audio_parse_get_units_per_second (GstRawBaseParse *
raw_base_parse, GstFormat format, GstRawBaseParseConfig config,
gsize * units_per_sec_n, gsize * units_per_sec_d);
static gboolean gst_raw_audio_parse_is_using_sink_caps (GstRawAudioParse *
raw_audio_parse);
static GstRawAudioParseConfig
* gst_raw_audio_parse_get_config_ptr (GstRawAudioParse * raw_audio_parse,
GstRawBaseParseConfig config);
static void gst_raw_audio_parse_init_config (GstRawAudioParseConfig * config);
static gboolean gst_raw_audio_parse_set_config_channels (GstRawAudioParseConfig
* config, guint num_channels, guint64 channel_mask, gboolean set_positions);
static gboolean
gst_raw_audio_parse_update_channel_reordering_flag (GstRawAudioParseConfig *
config);
static void gst_raw_audio_parse_update_config_bpf (GstRawAudioParseConfig *
config);
static gboolean gst_raw_audio_parse_caps_to_config (GstRawAudioParse *
raw_audio_parse, GstCaps * caps, GstRawAudioParseConfig * config);
static gboolean gst_raw_audio_parse_config_to_caps (GstRawAudioParse *
raw_audio_parse, GstCaps ** caps, GstRawAudioParseConfig * config);
static void
gst_raw_audio_parse_class_init (GstRawAudioParseClass * klass)
{
GObjectClass *object_class;
GstElementClass *element_class;
GstBaseParseClass *baseparse_class;
GstRawBaseParseClass *rawbaseparse_class;
GST_DEBUG_CATEGORY_INIT (raw_audio_parse_debug, "rawaudioparse", 0,
"rawaudioparse element");
object_class = G_OBJECT_CLASS (klass);
element_class = GST_ELEMENT_CLASS (klass);
baseparse_class = GST_BASE_PARSE_CLASS (klass);
rawbaseparse_class = GST_RAW_BASE_PARSE_CLASS (klass);
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&static_sink_template));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&static_src_template));
object_class->set_property =
GST_DEBUG_FUNCPTR (gst_raw_audio_parse_set_property);
object_class->get_property =
GST_DEBUG_FUNCPTR (gst_raw_audio_parse_get_property);
baseparse_class->stop = GST_DEBUG_FUNCPTR (gst_raw_audio_parse_stop);
rawbaseparse_class->set_current_config =
GST_DEBUG_FUNCPTR (gst_raw_audio_parse_set_current_config);
rawbaseparse_class->get_current_config =
GST_DEBUG_FUNCPTR (gst_raw_audio_parse_get_current_config);
rawbaseparse_class->set_config_from_caps =
GST_DEBUG_FUNCPTR (gst_raw_audio_parse_set_config_from_caps);
rawbaseparse_class->get_caps_from_config =
GST_DEBUG_FUNCPTR (gst_raw_audio_parse_get_caps_from_config);
rawbaseparse_class->get_config_frame_size =
GST_DEBUG_FUNCPTR (gst_raw_audio_parse_get_config_frame_size);
rawbaseparse_class->is_config_ready =
GST_DEBUG_FUNCPTR (gst_raw_audio_parse_is_config_ready);
rawbaseparse_class->process = GST_DEBUG_FUNCPTR (gst_raw_audio_parse_process);
rawbaseparse_class->is_unit_format_supported =
GST_DEBUG_FUNCPTR (gst_raw_audio_parse_is_unit_format_supported);
rawbaseparse_class->get_units_per_second =
GST_DEBUG_FUNCPTR (gst_raw_audio_parse_get_units_per_second);
g_object_class_install_property (object_class,
PROP_FORMAT,
g_param_spec_enum ("format",
"Format",
"Format of the raw audio stream",
gst_raw_audio_parse_format_get_type (),
GST_RAW_AUDIO_PARSE_FORMAT_PCM,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
);
g_object_class_install_property (object_class,
PROP_PCM_FORMAT,
g_param_spec_enum ("pcm-format",
"PCM format",
"Format of audio samples in PCM stream (ignored if format property is not set to pcm)",
GST_TYPE_AUDIO_FORMAT,
GST_RAW_AUDIO_PARSE_FORMAT_PCM,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
);
g_object_class_install_property (object_class,
PROP_SAMPLE_RATE,
g_param_spec_int ("sample-rate",
"Sample rate",
"Rate of audio samples in raw stream",
1, INT_MAX,
DEFAULT_SAMPLE_RATE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
);
g_object_class_install_property (object_class,
PROP_NUM_CHANNELS,
g_param_spec_int ("num-channels",
"Number of channels",
"Number of channels in raw stream",
1, INT_MAX,
DEFAULT_NUM_CHANNELS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
);
g_object_class_install_property (object_class,
PROP_INTERLEAVED,
g_param_spec_boolean ("interleaved",
"Interleaved layout",
"True if audio has interleaved layout",
DEFAULT_INTERLEAVED, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
);
g_object_class_install_property (object_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_READWRITE | G_PARAM_STATIC_STRINGS)
);
gst_element_class_set_static_metadata (element_class,
"rawaudioparse",
"Codec/Parser/Audio",
"Converts unformatted data streams into timestamped raw audio frames",
"Carlos Rafael Giani <dv@pseudoterminal.org>");
}
static void
gst_raw_audio_parse_init (GstRawAudioParse * raw_audio_parse)
{
/* Setup configs and select which one shall be the current one from the start. */
gst_raw_audio_parse_init_config (&(raw_audio_parse->properties_config));
gst_raw_audio_parse_init_config (&(raw_audio_parse->sink_caps_config));
/* As required by GstRawBaseParse, ensure that the current configuration
* is initially set to be the properties config */
raw_audio_parse->current_config = &(raw_audio_parse->properties_config);
/* Properties config must be valid from the start, so set its ready value
* to TRUE, and make sure its bpf value is valid. */
raw_audio_parse->properties_config.ready = TRUE;
gst_raw_audio_parse_update_config_bpf (&(raw_audio_parse->properties_config));
}
static void
gst_raw_audio_parse_set_property (GObject * object, guint prop_id,
GValue const *value, GParamSpec * pspec)
{
GstBaseParse *base_parse = GST_BASE_PARSE (object);
GstRawBaseParse *raw_base_parse = GST_RAW_BASE_PARSE (object);
GstRawAudioParse *raw_audio_parse = GST_RAW_AUDIO_PARSE (object);
/* All properties are handled similarly:
* - if the new value is the same as the current value, nothing is done
* - the parser lock is held while the new value is set
* - if the properties config is the current config, the source caps are
* invalidated to ensure that the code in handle_frame pushes a new CAPS
* event out
* - properties that affect the bpf value call the function to update
* the bpf and also call gst_base_parse_set_min_frame_size() to ensure
* that the minimum frame size can hold 1 frame (= one sample for each
* channel)
*/
switch (prop_id) {
case PROP_FORMAT:
{
GstRawAudioParseFormat new_format = g_value_get_enum (value);
GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK (object);
if (new_format != raw_audio_parse->properties_config.format) {
raw_audio_parse->properties_config.format = new_format;
gst_raw_audio_parse_update_config_bpf (&
(raw_audio_parse->properties_config));
if (!gst_raw_audio_parse_is_using_sink_caps (raw_audio_parse)) {
gst_raw_base_parse_invalidate_src_caps (raw_base_parse);
gst_base_parse_set_min_frame_size (base_parse,
raw_audio_parse->properties_config.bpf);
}
}
GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (object);
break;
}
case PROP_PCM_FORMAT:
{
GstAudioFormat new_pcm_format = g_value_get_enum (value);
GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK (object);
if (new_pcm_format != raw_audio_parse->properties_config.pcm_format) {
raw_audio_parse->properties_config.pcm_format = new_pcm_format;
gst_raw_audio_parse_update_config_bpf (&
(raw_audio_parse->properties_config));
if (!gst_raw_audio_parse_is_using_sink_caps (raw_audio_parse)) {
gst_raw_base_parse_invalidate_src_caps (raw_base_parse);
gst_base_parse_set_min_frame_size (base_parse,
raw_audio_parse->properties_config.bpf);
}
}
GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (object);
break;
}
case PROP_SAMPLE_RATE:
{
guint new_sample_rate = g_value_get_int (value);
GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK (object);
if (new_sample_rate != raw_audio_parse->properties_config.sample_rate) {
raw_audio_parse->properties_config.sample_rate = new_sample_rate;
if (!gst_raw_audio_parse_is_using_sink_caps (raw_audio_parse))
gst_raw_base_parse_invalidate_src_caps (raw_base_parse);
}
GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (object);
break;
}
case PROP_NUM_CHANNELS:
{
guint new_num_channels = g_value_get_int (value);
GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK (object);
if (new_num_channels != raw_audio_parse->properties_config.num_channels) {
gst_raw_audio_parse_set_config_channels (&
(raw_audio_parse->properties_config), new_num_channels, 0, TRUE);
raw_audio_parse->properties_config.num_channels = new_num_channels;
gst_raw_audio_parse_update_config_bpf (&
(raw_audio_parse->properties_config));
if (!gst_raw_audio_parse_is_using_sink_caps (raw_audio_parse)) {
gst_raw_base_parse_invalidate_src_caps (raw_base_parse);
gst_base_parse_set_min_frame_size (base_parse,
raw_audio_parse->properties_config.bpf);
}
}
GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (object);
break;
}
case PROP_INTERLEAVED:
{
gboolean new_interleaved = g_value_get_boolean (value);
GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK (object);
if (new_interleaved != raw_audio_parse->properties_config.interleaved) {
raw_audio_parse->properties_config.interleaved = new_interleaved;
if (!gst_raw_audio_parse_is_using_sink_caps (raw_audio_parse))
gst_raw_base_parse_invalidate_src_caps (raw_base_parse);
}
GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (object);
break;
}
case PROP_CHANNEL_POSITIONS:
{
GValueArray *valarray = g_value_get_boxed (value);
GstRawAudioParseConfig *config = &(raw_audio_parse->properties_config);
/* Sanity check - reject empty arrays */
if ((valarray != NULL) && (valarray->n_values == 0)) {
GST_ELEMENT_ERROR (raw_audio_parse, LIBRARY, SETTINGS,
("channel position property holds an empty array"), (NULL));
break;
}
GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK (object);
if ((valarray == NULL) && (config->num_channels > 0)) {
/* NULL value given, and number of channels is nonzero.
* Use the default GStreamer positioning. Call
* set_config_channels with the set_positions parameter
* set to TRUE to ensure the position values are filled. */
gst_raw_audio_parse_set_config_channels (&
(raw_audio_parse->properties_config), config->num_channels, 0,
TRUE);
} else {
/* Non-NULL value given. Make sure the channel_positions
* array in the properties config has enough room, and that
* the num_channels value equals the array length. Then copy
* the values from the valarray to channel_positions, and
* produce a copy of that array in case its channel positions
* are not in a valid GStreamer order (to be able to apply
* channel reordering later).
*/
guint i;
if (valarray->n_values != config->num_channels) {
/* Call with set_positions == FALSE to ensure that
* the array is properly allocated but not filled
* (it is filled below) */
gst_raw_audio_parse_set_config_channels (config, valarray->n_values,
0, FALSE);
}
for (i = 0; i < config->num_channels; ++i) {
GValue *val = g_value_array_get_nth (valarray, i);
config->channel_positions[i] = g_value_get_enum (val);
}
gst_raw_audio_parse_update_channel_reordering_flag (config);
}
gst_raw_audio_parse_update_config_bpf (&
(raw_audio_parse->properties_config));
if (!gst_raw_audio_parse_is_using_sink_caps (raw_audio_parse)) {
gst_raw_base_parse_invalidate_src_caps (raw_base_parse);
gst_base_parse_set_min_frame_size (base_parse,
raw_audio_parse->properties_config.bpf);
}
GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (object);
break;
}
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_raw_audio_parse_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
GstRawAudioParse *raw_audio_parse = GST_RAW_AUDIO_PARSE (object);
switch (prop_id) {
case PROP_FORMAT:
GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK (object);
g_value_set_enum (value, raw_audio_parse->properties_config.format);
GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (object);
break;
case PROP_PCM_FORMAT:
GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK (object);
g_value_set_enum (value, raw_audio_parse->properties_config.pcm_format);
GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (object);
break;
case PROP_SAMPLE_RATE:
GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK (object);
g_value_set_int (value, raw_audio_parse->properties_config.sample_rate);
GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (object);
break;
case PROP_NUM_CHANNELS:
GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK (object);
g_value_set_int (value, raw_audio_parse->properties_config.num_channels);
GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (object);
break;
case PROP_INTERLEAVED:
GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK (object);
g_value_set_boolean (value,
raw_audio_parse->properties_config.interleaved);
GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (object);
break;
case PROP_CHANNEL_POSITIONS:
{
GstRawAudioParseConfig *config;
GValueArray *valarray;
GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK (object);
valarray = NULL;
config = &(raw_audio_parse->properties_config);
/* Copy channel positions into the valuearray */
if (config->num_channels > 0) {
guint i;
GValue val = G_VALUE_INIT;
g_assert (config->channel_positions);
g_value_init (&val, GST_TYPE_AUDIO_CHANNEL_POSITION);
valarray = g_value_array_new (config->num_channels);
for (i = 0; i < config->num_channels; ++i) {
g_value_set_enum (&val, config->channel_positions[i]);
g_value_array_insert (valarray, i, &val);
}
g_value_unset (&val);
}
GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (object);
/* Pass on ownership to the value array,
* since we don't need it anymore */
g_value_take_boxed (value, valarray);
break;
}
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static gboolean
gst_raw_audio_parse_stop (GstBaseParse * parse)
{
GstRawAudioParse *raw_audio_parse = GST_RAW_AUDIO_PARSE (parse);
/* Sink caps config is not ready until caps come in.
* We are stopping processing, the element is being reset,
* so the config has to be un-readied.
* (Since the properties config is not depending on caps,
* its ready status is always TRUE.) */
raw_audio_parse->sink_caps_config.ready = FALSE;
return GST_BASE_PARSE_CLASS (parent_class)->stop (parse);
}
static gboolean
gst_raw_audio_parse_set_current_config (GstRawBaseParse * raw_base_parse,
GstRawBaseParseConfig config)
{
GstRawAudioParse *raw_audio_parse = GST_RAW_AUDIO_PARSE (raw_base_parse);
switch (config) {
case GST_RAW_BASE_PARSE_CONFIG_PROPERTIES:
raw_audio_parse->current_config = &(raw_audio_parse->properties_config);
break;
case GST_RAW_BASE_PARSE_CONFIG_SINKCAPS:
raw_audio_parse->current_config = &(raw_audio_parse->sink_caps_config);
break;
default:
g_assert_not_reached ();
}