From e3e4257ac93a5a7926650ed9898b547ba19a3fd3 Mon Sep 17 00:00:00 2001 From: Sebastian Dröge Date: Sun, 3 Aug 2008 11:38:22 +0000 Subject: ext/flac/gstflacdec.c: Support decoding of all depths between 4 and 32 bits and read the depth from the streaminfo he... Original commit message from CVS: * ext/flac/gstflacdec.c: (gst_flac_dec_metadata_callback), (gst_flac_dec_write): Support decoding of all depths between 4 and 32 bits and read the depth from the streaminfo header if needed. Also support all sampling rates between 1 and 655350 Hz. * ext/flac/gstflacenc.c: (gst_flac_enc_caps_append_structure_with_widths), (gst_flac_enc_sink_getcaps), (gst_flac_enc_sink_setcaps), (gst_flac_enc_chain): * ext/flac/gstflacenc.h: Support encoding in all bit depths supported by the streamable subformat (i.e. 8, 12, 16, 20 and 24 bits) and all sampling rates between 1 Hz and 655350 Hz. --- ext/flac/gstflacdec.c | 35 ++++++++++++------- ext/flac/gstflacenc.c | 93 +++++++++++++++++++++++++++++++++++++++++---------- ext/flac/gstflacenc.h | 1 + 3 files changed, 99 insertions(+), 30 deletions(-) (limited to 'ext/flac') diff --git a/ext/flac/gstflacdec.c b/ext/flac/gstflacdec.c index 5d65c837..7b8e381f 100644 --- a/ext/flac/gstflacdec.c +++ b/ext/flac/gstflacdec.c @@ -218,8 +218,8 @@ GST_BOILERPLATE (GstFlacDec, gst_flac_dec, GstElement, GST_TYPE_ELEMENT); "endianness = (int) BYTE_ORDER, " \ "signed = (boolean) true, " \ "width = (int) { 8, 16, 32 }, " \ - "depth = (int) { 8, 12, 16, 20, 24, 32 }, " \ - "rate = (int) [ 8000, 96000 ], " \ + "depth = (int) [ 4, 32 ], " \ + "rate = (int) [ 1, 655350 ], " \ "channels = (int) [ 1, 8 ]" static void gst_flac_dec_base_init (gpointer g_class) @@ -680,6 +680,7 @@ gst_flac_dec_metadata_callback (GstFlacDec * flacdec, flacdec->min_blocksize = metadata->data.stream_info.min_blocksize; flacdec->max_blocksize = metadata->data.stream_info.max_blocksize; flacdec->sample_rate = metadata->data.stream_info.sample_rate; + flacdec->depth = metadata->data.stream_info.bits_per_sample; GST_DEBUG_OBJECT (flacdec, "blocksize: min=%u, max=%u", flacdec->min_blocksize, flacdec->max_blocksize); @@ -997,19 +998,12 @@ gst_flac_dec_write (GstFlacDec * flacdec, const FLAC__Frame * frame, const FLAC__int32 * const buffer[]) { GstFlowReturn ret = GST_FLOW_OK; - GstBuffer *outbuf; - guint depth = frame->header.bits_per_sample; - guint width; - guint channels = frame->header.channels; - guint samples = frame->header.blocksize; - guint j, i; - GstClockTime next; switch (depth) { @@ -1024,6 +1018,23 @@ gst_flac_dec_write (GstFlacDec * flacdec, const FLAC__Frame * frame, case 24: case 32: width = 32; + break; + case 0: + if (flacdec->depth < 4 || flacdec->depth > 32) { + GST_ERROR_OBJECT (flacdec, "unsupported depth %d from STREAMINFO", + flacdec->depth); + ret = GST_FLOW_ERROR; + goto done; + } + + depth = flacdec->depth; + if (depth < 9) + width = 8; + else if (depth < 17) + width = 16; + else + width = 32; + break; default: GST_ERROR_OBJECT (flacdec, "unsupported depth %d", depth); @@ -1101,7 +1112,7 @@ gst_flac_dec_write (GstFlacDec * flacdec, const FLAC__Frame * frame, GST_BUFFER_DURATION (outbuf) = next - GST_BUFFER_TIMESTAMP (outbuf); - if (depth == 8) { + if (width == 8) { gint8 *outbuffer = (gint8 *) GST_BUFFER_DATA (outbuf); for (i = 0; i < samples; i++) { @@ -1109,7 +1120,7 @@ gst_flac_dec_write (GstFlacDec * flacdec, const FLAC__Frame * frame, *outbuffer++ = (gint8) buffer[j][i]; } } - } else if (depth == 12 || depth == 16) { + } else if (width == 16) { gint16 *outbuffer = (gint16 *) GST_BUFFER_DATA (outbuf); for (i = 0; i < samples; i++) { @@ -1117,7 +1128,7 @@ gst_flac_dec_write (GstFlacDec * flacdec, const FLAC__Frame * frame, *outbuffer++ = (gint16) buffer[j][i]; } } - } else if (depth == 20 || depth == 24 || depth == 32) { + } else if (width == 32) { gint32 *outbuffer = (gint32 *) GST_BUFFER_DATA (outbuf); for (i = 0; i < samples; i++) { diff --git a/ext/flac/gstflacenc.c b/ext/flac/gstflacenc.c index bcd51556..475d7a67 100644 --- a/ext/flac/gstflacenc.c +++ b/ext/flac/gstflacenc.c @@ -21,9 +21,6 @@ * - we assume timestamps start from 0 and that we get a perfect stream; we * don't handle non-zero starts and mid-stream discontinuities, esp. not if * we're muxing into ogg - * - need to support wider caps, 4-32 bit pcm - * http://flac.sourceforge.net/faq.html#general__channels - * it also support sampling rate from 1Hz - 655350Hz */ #ifdef HAVE_CONFIG_H @@ -87,12 +84,26 @@ GST_ELEMENT_DETAILS ("FLAC audio encoder", "Wim Taymans "); #define FLAC_SINK_CAPS \ + "audio/x-raw-int, " \ + "endianness = (int) BYTE_ORDER, " \ + "signed = (boolean) TRUE, " \ + "width = (int) 8, " \ + "depth = (int) 8, " \ + "rate = (int) [ 1, 655350 ], " \ + "channels = (int) [ 1, 8 ]; " \ "audio/x-raw-int, " \ "endianness = (int) BYTE_ORDER, " \ "signed = (boolean) TRUE, " \ "width = (int) 16, " \ - "depth = (int) 16, " \ - "rate = (int) [ 8000, 96000 ], " \ + "depth = (int) { 12, 16 }, " \ + "rate = (int) [ 1, 655350 ], " \ + "channels = (int) [ 1, 8 ]; " \ + "audio/x-raw-int, " \ + "endianness = (int) BYTE_ORDER, " \ + "signed = (boolean) TRUE, " \ + "width = (int) 32, " \ + "depth = (int) { 20, 24 }, " \ + "rate = (int) [ 1, 655350 ], " \ "channels = (int) [ 1, 8 ]" static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", @@ -446,6 +457,49 @@ gst_flac_enc_set_metadata (GstFlacEnc * flacenc) gst_tag_list_free (copy); } +static void +gst_flac_enc_caps_append_structure_with_widths (GstCaps * caps, + GstStructure * s) +{ + GstStructure *tmp; + GValue list = { 0, }; + GValue depth = { 0, }; + + + tmp = gst_structure_copy (s); + gst_structure_set (tmp, "width", G_TYPE_INT, 8, "depth", G_TYPE_INT, 8, NULL); + gst_caps_append_structure (caps, tmp); + + tmp = gst_structure_copy (s); + + g_value_init (&depth, G_TYPE_INT); + g_value_init (&list, GST_TYPE_LIST); + g_value_set_int (&depth, 12); + gst_value_list_append_value (&list, &depth); + g_value_set_int (&depth, 16); + gst_value_list_append_value (&list, &depth); + + gst_structure_set (tmp, "width", G_TYPE_INT, 16, NULL); + gst_structure_set_value (tmp, "depth", &list); + gst_caps_append_structure (caps, tmp); + + g_value_reset (&list); + + tmp = s; + + g_value_set_int (&depth, 20); + gst_value_list_append_value (&list, &depth); + g_value_set_int (&depth, 24); + gst_value_list_append_value (&list, &depth); + + gst_structure_set (tmp, "width", G_TYPE_INT, 32, NULL); + gst_structure_set_value (tmp, "depth", &list); + gst_caps_append_structure (caps, tmp); + + g_value_unset (&list); + g_value_unset (&depth); +} + static GstCaps * gst_flac_enc_sink_getcaps (GstPad * pad) { @@ -460,12 +514,11 @@ gst_flac_enc_sink_getcaps (GstPad * pad) ret = gst_caps_new_empty (); - gst_caps_append_structure (ret, gst_structure_new ("audio/x-raw-int", + gst_flac_enc_caps_append_structure_with_widths (ret, + gst_structure_new ("audio/x-raw-int", "endianness", G_TYPE_INT, G_BYTE_ORDER, "signed", G_TYPE_BOOLEAN, TRUE, - "width", G_TYPE_INT, 16, - "depth", G_TYPE_INT, 16, - "rate", GST_TYPE_INT_RANGE, 8000, 96000, + "rate", GST_TYPE_INT_RANGE, 1, 655350, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL)); for (i = 3; i <= 8; i++) { @@ -485,14 +538,12 @@ gst_flac_enc_sink_getcaps (GstPad * pad) s = gst_structure_new ("audio/x-raw-int", "endianness", G_TYPE_INT, G_BYTE_ORDER, "signed", G_TYPE_BOOLEAN, TRUE, - "width", G_TYPE_INT, 16, - "depth", G_TYPE_INT, 16, - "rate", GST_TYPE_INT_RANGE, 8000, 96000, + "rate", GST_TYPE_INT_RANGE, 1, 655350, "channels", G_TYPE_INT, i, NULL); gst_structure_set_value (s, "channel-positions", &positions); g_value_unset (&positions); - gst_caps_append_structure (ret, s); + gst_flac_enc_caps_append_structure_with_widths (ret, s); } } @@ -539,6 +590,7 @@ gst_flac_enc_sink_setcaps (GstPad * pad, GstCaps * caps) } flacenc->channels = chans; + flacenc->width = width; flacenc->depth = depth; flacenc->sample_rate = rate; @@ -1019,7 +1071,7 @@ gst_flac_enc_chain (GstPad * pad, GstBuffer * buffer) GstFlacEnc *flacenc; FLAC__int32 *data; gulong insize; - gint samples, depth; + gint samples, width; gulong i; FLAC__bool res; @@ -1029,21 +1081,26 @@ gst_flac_enc_chain (GstPad * pad, GstBuffer * buffer) if (G_UNLIKELY (flacenc->depth == 0)) return GST_FLOW_NOT_NEGOTIATED; - depth = flacenc->depth; + width = flacenc->width; insize = GST_BUFFER_SIZE (buffer); - samples = insize / ((depth + 7) >> 3); + samples = insize / (width >> 3); data = g_malloc (samples * sizeof (FLAC__int32)); - if (depth == 8) { + if (width == 8) { gint8 *indata = (gint8 *) GST_BUFFER_DATA (buffer); for (i = 0; i < samples; i++) data[i] = (FLAC__int32) indata[i]; - } else if (depth == 16) { + } else if (width == 16) { gint16 *indata = (gint16 *) GST_BUFFER_DATA (buffer); + for (i = 0; i < samples; i++) + data[i] = (FLAC__int32) indata[i]; + } else if (width == 32) { + gint32 *indata = (gint32 *) GST_BUFFER_DATA (buffer); + for (i = 0; i < samples; i++) data[i] = (FLAC__int32) indata[i]; } else { diff --git a/ext/flac/gstflacenc.h b/ext/flac/gstflacenc.h index a7bbd46a..016a56b6 100644 --- a/ext/flac/gstflacenc.h +++ b/ext/flac/gstflacenc.h @@ -58,6 +58,7 @@ struct _GstFlacEnc { guint64 samples_written; gboolean eos; gint channels; + gint width; gint depth; gint sample_rate; gboolean negotiated; -- cgit