mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-14 13:21:28 +00:00
319 lines
9.2 KiB
C
319 lines
9.2 KiB
C
|
/* GStreamer
|
||
|
* Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
|
||
|
*
|
||
|
* gstaudioparse.c:
|
||
|
*
|
||
|
* 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., 59 Temple Place - Suite 330,
|
||
|
* Boston, MA 02111-1307, USA.
|
||
|
*/
|
||
|
/**
|
||
|
* SECTION:element-audioparse
|
||
|
*
|
||
|
* Converts a byte stream into audio frames.
|
||
|
*/
|
||
|
|
||
|
#ifdef HAVE_CONFIG_H
|
||
|
# include "config.h"
|
||
|
#endif
|
||
|
|
||
|
#include "gstaudioparse.h"
|
||
|
|
||
|
typedef enum
|
||
|
{
|
||
|
GST_AUDIO_PARSE_FORMAT_INT,
|
||
|
GST_AUDIO_PARSE_FORMAT_FLOAT
|
||
|
} GstAudioParseFormat;
|
||
|
|
||
|
typedef enum
|
||
|
{
|
||
|
GST_AUDIO_PARSE_ENDIANNESS_LITTLE = 1234,
|
||
|
GST_AUDIO_PARSE_ENDIANNESS_BIG = 4321
|
||
|
} GstAudioParseEndianness;
|
||
|
|
||
|
static void gst_audio_parse_set_property (GObject * object, guint prop_id,
|
||
|
const GValue * value, GParamSpec * pspec);
|
||
|
static void gst_audio_parse_get_property (GObject * object, guint prop_id,
|
||
|
GValue * value, GParamSpec * pspec);
|
||
|
|
||
|
static GstCaps *gst_audio_parse_get_caps (GstRawParse * rp);
|
||
|
|
||
|
static void gst_audio_parse_update_frame_size (GstAudioParse * ap);
|
||
|
|
||
|
GST_DEBUG_CATEGORY_STATIC (gst_audio_parse_debug);
|
||
|
#define GST_CAT_DEFAULT gst_audio_parse_debug
|
||
|
|
||
|
static const GstElementDetails gst_audio_parse_details =
|
||
|
GST_ELEMENT_DETAILS ("Audio Parse",
|
||
|
"Filter/Audio",
|
||
|
"Converts stream into audio frames",
|
||
|
"Sebastian Dröge <slomo@circular-chaos.org>");
|
||
|
|
||
|
enum
|
||
|
{
|
||
|
ARG_0,
|
||
|
ARG_FORMAT,
|
||
|
ARG_RATE,
|
||
|
ARG_CHANNELS,
|
||
|
ARG_ENDIANNESS,
|
||
|
ARG_WIDTH,
|
||
|
ARG_DEPTH,
|
||
|
ARG_SIGNED,
|
||
|
};
|
||
|
|
||
|
|
||
|
#define GST_AUDIO_PARSE_FORMAT (gst_audio_parse_format_get_type ())
|
||
|
static GType
|
||
|
gst_audio_parse_format_get_type (void)
|
||
|
{
|
||
|
static GType audio_parse_format_type = 0;
|
||
|
static const GEnumValue format_types[] = {
|
||
|
{GST_AUDIO_PARSE_FORMAT_INT, "Integer", "int"},
|
||
|
{GST_AUDIO_PARSE_FORMAT_FLOAT, "Floating Point", "float"},
|
||
|
{0, NULL, NULL}
|
||
|
};
|
||
|
|
||
|
if (!audio_parse_format_type) {
|
||
|
audio_parse_format_type =
|
||
|
g_enum_register_static ("GstAudioParseFormat", format_types);
|
||
|
}
|
||
|
|
||
|
return audio_parse_format_type;
|
||
|
}
|
||
|
|
||
|
#define GST_AUDIO_PARSE_ENDIANNESS (gst_audio_parse_endianness_get_type ())
|
||
|
static GType
|
||
|
gst_audio_parse_endianness_get_type (void)
|
||
|
{
|
||
|
static GType audio_parse_endianness_type = 0;
|
||
|
static const GEnumValue endian_types[] = {
|
||
|
{GST_AUDIO_PARSE_ENDIANNESS_LITTLE, "Little Endian", "little"},
|
||
|
{GST_AUDIO_PARSE_ENDIANNESS_BIG, "Big Endian", "big"},
|
||
|
{0, NULL, NULL}
|
||
|
};
|
||
|
|
||
|
if (!audio_parse_endianness_type) {
|
||
|
audio_parse_endianness_type =
|
||
|
g_enum_register_static ("GstAudioParseEndianness", endian_types);
|
||
|
}
|
||
|
|
||
|
return audio_parse_endianness_type;
|
||
|
}
|
||
|
|
||
|
GST_BOILERPLATE (GstAudioParse, gst_audio_parse, GstRawParse,
|
||
|
GST_TYPE_RAW_PARSE);
|
||
|
|
||
|
static void
|
||
|
gst_audio_parse_base_init (gpointer g_class)
|
||
|
{
|
||
|
GstRawParseClass *rp_class = GST_RAW_PARSE_CLASS (g_class);
|
||
|
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
|
||
|
GstCaps *caps;
|
||
|
|
||
|
GST_DEBUG_CATEGORY_INIT (gst_audio_parse_debug, "audioparse", 0,
|
||
|
"audioparse element");
|
||
|
|
||
|
gst_element_class_set_details (gstelement_class, &gst_audio_parse_details);
|
||
|
|
||
|
caps =
|
||
|
gst_caps_from_string ("audio/x-raw-int,"
|
||
|
" depth=(int) [ 1, 32 ],"
|
||
|
" width=(int) { 8, 16, 24, 32 },"
|
||
|
" endianness=(int) { LITTLE_ENDIAN, BIG_ENDIAN }, "
|
||
|
" signed=(bool) { TRUE, FALSE },"
|
||
|
" rate=(int) [ 1, MAX ],"
|
||
|
" channels=(int) [ 1, MAX ]; "
|
||
|
"audio/x-raw-float,"
|
||
|
" width=(int) { 32, 64 },"
|
||
|
" endianness=(int) { LITTLE_ENDIAN, BIG_ENDIAN }, "
|
||
|
" rate=(int)[1,MAX]," " channels=(int)[1,MAX]");
|
||
|
|
||
|
gst_raw_parse_class_set_src_pad_template (rp_class, caps);
|
||
|
gst_raw_parse_class_set_multiple_frames_per_buffer (rp_class, TRUE);
|
||
|
gst_caps_unref (caps);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
gst_audio_parse_class_init (GstAudioParseClass * klass)
|
||
|
{
|
||
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||
|
GstRawParseClass *rp_class = GST_RAW_PARSE_CLASS (klass);
|
||
|
|
||
|
gobject_class->set_property = gst_audio_parse_set_property;
|
||
|
gobject_class->get_property = gst_audio_parse_get_property;
|
||
|
|
||
|
rp_class->get_caps = gst_audio_parse_get_caps;
|
||
|
|
||
|
g_object_class_install_property (gobject_class, ARG_FORMAT,
|
||
|
g_param_spec_enum ("format", "Format",
|
||
|
"Format of audio samples in raw stream", GST_AUDIO_PARSE_FORMAT,
|
||
|
GST_AUDIO_PARSE_FORMAT_INT, G_PARAM_READWRITE));
|
||
|
|
||
|
g_object_class_install_property (gobject_class, ARG_RATE,
|
||
|
g_param_spec_int ("rate", "Rate", "Rate of audio samples in raw stream",
|
||
|
1, INT_MAX, 44100, G_PARAM_READWRITE));
|
||
|
|
||
|
g_object_class_install_property (gobject_class, ARG_CHANNELS,
|
||
|
g_param_spec_int ("channels", "Channels",
|
||
|
"Number of channels in raw stream", 1, INT_MAX, 2,
|
||
|
G_PARAM_READWRITE));
|
||
|
|
||
|
g_object_class_install_property (gobject_class, ARG_WIDTH,
|
||
|
g_param_spec_int ("width", "Width",
|
||
|
"Width of audio samples in raw stream", 1, INT_MAX, 16,
|
||
|
G_PARAM_READWRITE));
|
||
|
|
||
|
g_object_class_install_property (gobject_class, ARG_DEPTH,
|
||
|
g_param_spec_int ("depth", "Depth",
|
||
|
"Depth of audio samples in raw stream", 1, INT_MAX, 16,
|
||
|
G_PARAM_READWRITE));
|
||
|
|
||
|
g_object_class_install_property (gobject_class, ARG_SIGNED,
|
||
|
g_param_spec_boolean ("signed", "signed",
|
||
|
"Sign of audio samples in raw stream", TRUE, G_PARAM_READWRITE));
|
||
|
|
||
|
g_object_class_install_property (gobject_class, ARG_ENDIANNESS,
|
||
|
g_param_spec_enum ("endianness", "Endianness",
|
||
|
"Endianness of audio samples in raw stream",
|
||
|
GST_AUDIO_PARSE_ENDIANNESS, G_BYTE_ORDER, G_PARAM_READWRITE));
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
gst_audio_parse_init (GstAudioParse * ap, GstAudioParseClass * g_class)
|
||
|
{
|
||
|
ap->format = GST_AUDIO_PARSE_FORMAT_INT;
|
||
|
ap->channels = 2;
|
||
|
ap->width = 16;
|
||
|
ap->depth = 16;
|
||
|
ap->signedness = TRUE;
|
||
|
ap->endianness = G_BYTE_ORDER;
|
||
|
|
||
|
gst_audio_parse_update_frame_size (ap);
|
||
|
gst_raw_parse_set_fps (GST_RAW_PARSE (ap), 44100, 1);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
gst_audio_parse_set_property (GObject * object, guint prop_id,
|
||
|
const GValue * value, GParamSpec * pspec)
|
||
|
{
|
||
|
GstAudioParse *ap = GST_AUDIO_PARSE (object);
|
||
|
|
||
|
g_return_if_fail (!gst_raw_parse_is_negotiated (GST_RAW_PARSE (ap)));
|
||
|
|
||
|
switch (prop_id) {
|
||
|
case ARG_FORMAT:
|
||
|
ap->format = g_value_get_enum (value);
|
||
|
break;
|
||
|
case ARG_RATE:
|
||
|
gst_raw_parse_set_fps (GST_RAW_PARSE (ap), g_value_get_int (value), 1);
|
||
|
break;
|
||
|
case ARG_CHANNELS:
|
||
|
ap->channels = g_value_get_int (value);
|
||
|
break;
|
||
|
case ARG_WIDTH:
|
||
|
ap->width = g_value_get_int (value);
|
||
|
break;
|
||
|
case ARG_DEPTH:
|
||
|
ap->depth = g_value_get_int (value);
|
||
|
break;
|
||
|
case ARG_SIGNED:
|
||
|
ap->signedness = g_value_get_boolean (value);
|
||
|
break;
|
||
|
case ARG_ENDIANNESS:
|
||
|
ap->endianness = g_value_get_enum (value);
|
||
|
break;
|
||
|
default:
|
||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
gst_audio_parse_update_frame_size (ap);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
gst_audio_parse_get_property (GObject * object, guint prop_id, GValue * value,
|
||
|
GParamSpec * pspec)
|
||
|
{
|
||
|
GstAudioParse *ap = GST_AUDIO_PARSE (object);
|
||
|
|
||
|
switch (prop_id) {
|
||
|
case ARG_FORMAT:
|
||
|
g_value_set_enum (value, ap->format);
|
||
|
break;
|
||
|
case ARG_RATE:{
|
||
|
gint fps_n, fps_d;
|
||
|
|
||
|
gst_raw_parse_get_fps (GST_RAW_PARSE (ap), &fps_n, &fps_d);
|
||
|
g_value_set_int (value, fps_n);
|
||
|
break;
|
||
|
}
|
||
|
case ARG_CHANNELS:
|
||
|
g_value_set_int (value, ap->channels);
|
||
|
break;
|
||
|
case ARG_WIDTH:
|
||
|
g_value_set_int (value, ap->width);
|
||
|
break;
|
||
|
case ARG_DEPTH:
|
||
|
g_value_set_int (value, ap->depth);
|
||
|
break;
|
||
|
case ARG_SIGNED:
|
||
|
g_value_set_boolean (value, ap->signedness);
|
||
|
break;
|
||
|
case ARG_ENDIANNESS:
|
||
|
g_value_set_enum (value, ap->endianness);
|
||
|
break;
|
||
|
default:
|
||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
gst_audio_parse_update_frame_size (GstAudioParse * ap)
|
||
|
{
|
||
|
gint framesize;
|
||
|
|
||
|
framesize = (ap->width / 8) * ap->channels;
|
||
|
|
||
|
gst_raw_parse_set_framesize (GST_RAW_PARSE (ap), framesize);
|
||
|
}
|
||
|
|
||
|
static GstCaps *
|
||
|
gst_audio_parse_get_caps (GstRawParse * rp)
|
||
|
{
|
||
|
GstAudioParse *ap = GST_AUDIO_PARSE (rp);
|
||
|
GstCaps *caps;
|
||
|
|
||
|
gint fps_n, fps_d;
|
||
|
|
||
|
gst_raw_parse_get_fps (rp, &fps_n, &fps_d);
|
||
|
|
||
|
if (ap->format == GST_AUDIO_PARSE_FORMAT_INT) {
|
||
|
caps = gst_caps_new_simple ("audio/x-raw-int",
|
||
|
"rate", G_TYPE_INT, fps_n,
|
||
|
"channels", G_TYPE_INT, ap->channels,
|
||
|
"width", G_TYPE_INT, ap->width,
|
||
|
"depth", G_TYPE_INT, ap->depth,
|
||
|
"signed", G_TYPE_BOOLEAN, ap->signedness,
|
||
|
"endianness", G_TYPE_INT, ap->endianness, NULL);
|
||
|
} else {
|
||
|
caps = gst_caps_new_simple ("audio/x-raw-float",
|
||
|
"rate", G_TYPE_INT, fps_n,
|
||
|
"channels", G_TYPE_INT, ap->channels,
|
||
|
"width", G_TYPE_INT, ap->width,
|
||
|
"endianness", G_TYPE_INT, ap->endianness, NULL);
|
||
|
}
|
||
|
return caps;
|
||
|
}
|