summaryrefslogtreecommitdiffstats
path: root/gst/mpegaudioparse
diff options
context:
space:
mode:
Diffstat (limited to 'gst/mpegaudioparse')
-rw-r--r--gst/mpegaudioparse/gstmpegaudioparse.c121
-rw-r--r--gst/mpegaudioparse/gstmpegaudioparse.h1
2 files changed, 63 insertions, 59 deletions
diff --git a/gst/mpegaudioparse/gstmpegaudioparse.c b/gst/mpegaudioparse/gstmpegaudioparse.c
index a5d8797c..d97fce17 100644
--- a/gst/mpegaudioparse/gstmpegaudioparse.c
+++ b/gst/mpegaudioparse/gstmpegaudioparse.c
@@ -46,13 +46,11 @@ mp3_src_factory (void)
gst_caps_new (
"mp3parse_src",
"audio/x-mp3",
- /*
gst_props_new (
"layer", GST_PROPS_INT_RANGE (1, 3),
- "bitrate", GST_PROPS_INT_RANGE (8, 320),
- "framed", GST_PROPS_BOOLEAN (TRUE),
- */
- NULL),
+ "rate", GST_PROPS_INT_RANGE (8000, 48000),
+ "channels", GST_PROPS_INT_RANGE (1, 2),
+ NULL)),
NULL);
}
@@ -89,13 +87,14 @@ static GstPadTemplate *sink_temp, *src_temp;
static void gst_mp3parse_class_init (GstMPEGAudioParseClass *klass);
static void gst_mp3parse_init (GstMPEGAudioParse *mp3parse);
-static void gst_mp3parse_loop (GstElement *element);
static void gst_mp3parse_chain (GstPad *pad,GstBuffer *buf);
static long bpf_from_header (GstMPEGAudioParse *parse, unsigned long header);
static int head_check (unsigned long head);
static void gst_mp3parse_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
static void gst_mp3parse_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
+static GstElementStateReturn
+ gst_mp3parse_change_state (GstElement *element);
static GstElementClass *parent_class = NULL;
/*static guint gst_mp3parse_signals[LAST_SIGNAL] = { 0 }; */
@@ -133,13 +132,15 @@ gst_mp3parse_class_init (GstMPEGAudioParseClass *klass)
g_param_spec_int("skip","skip","skip",
G_MININT,G_MAXINT,0,G_PARAM_READWRITE)); /* CHECKME */
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_BIT_RATE,
- g_param_spec_int("bit_rate","bit_rate","bit_rate",
+ g_param_spec_int("bitrate","Bitrate","Bit Rate",
G_MININT,G_MAXINT,0,G_PARAM_READABLE)); /* CHECKME */
parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
gobject_class->set_property = gst_mp3parse_set_property;
gobject_class->get_property = gst_mp3parse_get_property;
+
+ gstelement_class->change_state = gst_mp3parse_change_state;
}
static void
@@ -148,11 +149,8 @@ gst_mp3parse_init (GstMPEGAudioParse *mp3parse)
mp3parse->sinkpad = gst_pad_new_from_template(sink_temp, "sink");
gst_element_add_pad(GST_ELEMENT(mp3parse),mp3parse->sinkpad);
- gst_element_set_loop_function (GST_ELEMENT(mp3parse),gst_mp3parse_loop);
-#if 1 /* set this to one to use the old chaining code */
gst_pad_set_chain_function(mp3parse->sinkpad,gst_mp3parse_chain);
gst_element_set_loop_function (GST_ELEMENT(mp3parse),NULL);
-#endif
mp3parse->srcpad = gst_pad_new_from_template(src_temp, "src");
gst_element_add_pad(GST_ELEMENT(mp3parse),mp3parse->srcpad);
@@ -161,6 +159,8 @@ gst_mp3parse_init (GstMPEGAudioParse *mp3parse)
mp3parse->partialbuf = NULL;
mp3parse->skip = 0;
mp3parse->in_flush = FALSE;
+
+ mp3parse->rate = mp3parse->channels = mp3parse->layer = -1;
}
static guint32
@@ -170,7 +170,6 @@ gst_mp3parse_next_header (guchar *buf,guint32 len,guint32 start)
int f = 0;
while (offset < (len - 4)) {
- fprintf(stderr,"%02x ",buf[offset]);
if (buf[offset] == 0xff)
f = 1;
else if (f && ((buf[offset] >> 4) == 0x0f))
@@ -183,52 +182,6 @@ gst_mp3parse_next_header (guchar *buf,guint32 len,guint32 start)
}
static void
-gst_mp3parse_loop (GstElement *element)
-{
- GstMPEGAudioParse *parse = GST_MP3PARSE(element);
- GstBuffer *inbuf, *outbuf;
- guint32 size, offset;
- guchar *data;
- guint32 start;
- guint32 header;
- gint bpf;
-
- while (1) {
- /* get a new buffer */
- inbuf = gst_pad_pull (parse->sinkpad);
- size = GST_BUFFER_SIZE (inbuf);
- data = GST_BUFFER_DATA (inbuf);
- offset = 0;
-fprintf(stderr, "have buffer of %d bytes\n",size);
-
- /* loop through it and find all the frames */
- while (offset < (size - 4)) {
- start = gst_mp3parse_next_header (data,size,offset);
-fprintf(stderr, "skipped %d bytes searching for the next header\n",start-offset);
- header = GUINT32_FROM_BE(*((guint32 *)(data+start)));
-fprintf(stderr, "header is 0x%08x\n",header);
-
- /* figure out how big the frame is supposed to be */
- bpf = bpf_from_header (parse, header);
-
- /* see if there are enough bytes in this buffer for the whole frame */
- if ((start + bpf) <= size) {
- outbuf = gst_buffer_create_sub (inbuf,start,bpf);
-fprintf(stderr, "sending buffer of %d bytes\n",bpf);
- gst_pad_push (parse->srcpad, outbuf);
- offset = start + bpf;
-
- /* if not, we have to deal with it somehow */
- } else {
-fprintf(stderr,"don't have enough data for this frame\n");
-
- break;
- }
- }
- }
-}
-
-static void
gst_mp3parse_chain (GstPad *pad, GstBuffer *buf)
{
GstMPEGAudioParse *mp3parse;
@@ -337,7 +290,13 @@ gst_mp3parse_chain (GstPad *pad, GstBuffer *buf)
mp3parse->in_flush = FALSE;
}
GST_BUFFER_TIMESTAMP(outbuf) = last_ts;
- gst_pad_push(mp3parse->srcpad,outbuf);
+
+ if (GST_PAD_CAPS (mp3parse->srcpad) != NULL) {
+ gst_pad_push(mp3parse->srcpad,outbuf);
+ } else {
+ GST_DEBUG ("No capsnego yet, delaying buffer push");
+ gst_buffer_unref (outbuf);
+ }
}
else {
GST_DEBUG ("mp3parse: skipping buffer of %d bytes",GST_BUFFER_SIZE(outbuf));
@@ -382,8 +341,9 @@ static long mp3parse_freqs[9] =
static long
bpf_from_header (GstMPEGAudioParse *parse, unsigned long header)
{
- int layer_index,layer,lsf,samplerate_index,padding;
+ int layer_index,layer,lsf,samplerate_index,padding,mode;
long bpf;
+ gint channels, rate;
/*mpegver = (header >> 19) & 0x3; // don't need this for bpf */
layer_index = (header >> 17) & 0x3;
@@ -392,6 +352,7 @@ bpf_from_header (GstMPEGAudioParse *parse, unsigned long header)
parse->bit_rate = mp3parse_tabsel[lsf][layer - 1][((header >> 12) & 0xf)];
samplerate_index = (header >> 10) & 0x3;
padding = (header >> 9) & 0x1;
+ mode = (header >> 6) & 0x3;
if (layer == 1) {
bpf = parse->bit_rate * 12000;
@@ -403,6 +364,26 @@ bpf_from_header (GstMPEGAudioParse *parse, unsigned long header)
bpf += padding;
}
+ channels = (mode == 3) ? 1 : 2;
+ rate = mp3parse_freqs[samplerate_index];
+ if (channels != parse->channels ||
+ rate != parse->rate ||
+ layer != parse->layer) {
+ GstCaps *caps = GST_CAPS_NEW ("mp3parse_src",
+ "audio/mpeg",
+ "layer", GST_PROPS_INT (layer),
+ "channels", GST_PROPS_INT (channels),
+ "rate", GST_PROPS_INT (rate));
+ if (gst_pad_try_set_caps(parse->srcpad, caps) <= 0) {
+ gst_element_error (GST_ELEMENT (parse),
+ "mp3parse: failed to negotiate format with next element");
+ }
+
+ parse->channels = channels;
+ parse->layer = layer;
+ parse->rate = rate;
+ }
+
/*g_print("%08x: layer %d lsf %d bitrate %d samplerate_index %d padding %d - bpf %d\n", */
/*header,layer,lsf,bitrate,samplerate_index,padding,bpf); */
@@ -478,6 +459,28 @@ gst_mp3parse_get_property (GObject *object, guint prop_id, GValue *value, GParam
}
}
+static GstElementStateReturn
+gst_mp3parse_change_state (GstElement *element)
+{
+ GstMPEGAudioParse *src;
+
+ g_return_val_if_fail(GST_IS_MP3PARSE(element), GST_STATE_FAILURE);
+ src = GST_MP3PARSE(element);
+
+ switch (GST_STATE_TRANSITION (element)) {
+ case GST_STATE_PAUSED_TO_READY:
+ src->channels = -1; src->rate = -1; src->layer = -1;
+ break;
+ default:
+ break;
+ }
+
+ if (GST_ELEMENT_CLASS(parent_class)->change_state)
+ return GST_ELEMENT_CLASS(parent_class)->change_state(element);
+
+ return GST_STATE_SUCCESS;
+}
+
static gboolean
plugin_init (GModule *module, GstPlugin *plugin)
{
diff --git a/gst/mpegaudioparse/gstmpegaudioparse.h b/gst/mpegaudioparse/gstmpegaudioparse.h
index f929a5d9..7d1edc95 100644
--- a/gst/mpegaudioparse/gstmpegaudioparse.h
+++ b/gst/mpegaudioparse/gstmpegaudioparse.h
@@ -53,6 +53,7 @@ struct _GstMPEGAudioParse {
GstBuffer *partialbuf; /* previous buffer (if carryover) */
guint skip; /* number of frames to skip */
guint bit_rate;
+ gint channels, rate, layer;
gboolean in_flush;
};