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.
This commit is contained in:
parent
826f568cb4
commit
e3e4257ac9
17
ChangeLog
17
ChangeLog
@ -1,3 +1,20 @@
|
|||||||
|
2008-08-03 Sebastian Dröge <sebastian.droege@collabora.co.uk>
|
||||||
|
|
||||||
|
* 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.
|
||||||
|
|
||||||
2008-08-03 Sebastian Dröge <sebastian.droege@collabora.co.uk>
|
2008-08-03 Sebastian Dröge <sebastian.droege@collabora.co.uk>
|
||||||
|
|
||||||
* ext/flac/gstflacenc.c: (gst_flac_enc_init),
|
* ext/flac/gstflacenc.c: (gst_flac_enc_init),
|
||||||
|
@ -218,8 +218,8 @@ GST_BOILERPLATE (GstFlacDec, gst_flac_dec, GstElement, GST_TYPE_ELEMENT);
|
|||||||
"endianness = (int) BYTE_ORDER, " \
|
"endianness = (int) BYTE_ORDER, " \
|
||||||
"signed = (boolean) true, " \
|
"signed = (boolean) true, " \
|
||||||
"width = (int) { 8, 16, 32 }, " \
|
"width = (int) { 8, 16, 32 }, " \
|
||||||
"depth = (int) { 8, 12, 16, 20, 24, 32 }, " \
|
"depth = (int) [ 4, 32 ], " \
|
||||||
"rate = (int) [ 8000, 96000 ], " \
|
"rate = (int) [ 1, 655350 ], " \
|
||||||
"channels = (int) [ 1, 8 ]"
|
"channels = (int) [ 1, 8 ]"
|
||||||
static void
|
static void
|
||||||
gst_flac_dec_base_init (gpointer g_class)
|
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->min_blocksize = metadata->data.stream_info.min_blocksize;
|
||||||
flacdec->max_blocksize = metadata->data.stream_info.max_blocksize;
|
flacdec->max_blocksize = metadata->data.stream_info.max_blocksize;
|
||||||
flacdec->sample_rate = metadata->data.stream_info.sample_rate;
|
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",
|
GST_DEBUG_OBJECT (flacdec, "blocksize: min=%u, max=%u",
|
||||||
flacdec->min_blocksize, flacdec->max_blocksize);
|
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[])
|
const FLAC__int32 * const buffer[])
|
||||||
{
|
{
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
|
||||||
GstBuffer *outbuf;
|
GstBuffer *outbuf;
|
||||||
|
|
||||||
guint depth = frame->header.bits_per_sample;
|
guint depth = frame->header.bits_per_sample;
|
||||||
|
|
||||||
guint width;
|
guint width;
|
||||||
|
|
||||||
guint channels = frame->header.channels;
|
guint channels = frame->header.channels;
|
||||||
|
|
||||||
guint samples = frame->header.blocksize;
|
guint samples = frame->header.blocksize;
|
||||||
|
|
||||||
guint j, i;
|
guint j, i;
|
||||||
|
|
||||||
GstClockTime next;
|
GstClockTime next;
|
||||||
|
|
||||||
switch (depth) {
|
switch (depth) {
|
||||||
@ -1024,6 +1018,23 @@ gst_flac_dec_write (GstFlacDec * flacdec, const FLAC__Frame * frame,
|
|||||||
case 24:
|
case 24:
|
||||||
case 32:
|
case 32:
|
||||||
width = 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;
|
break;
|
||||||
default:
|
default:
|
||||||
GST_ERROR_OBJECT (flacdec, "unsupported depth %d", depth);
|
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);
|
GST_BUFFER_DURATION (outbuf) = next - GST_BUFFER_TIMESTAMP (outbuf);
|
||||||
|
|
||||||
if (depth == 8) {
|
if (width == 8) {
|
||||||
gint8 *outbuffer = (gint8 *) GST_BUFFER_DATA (outbuf);
|
gint8 *outbuffer = (gint8 *) GST_BUFFER_DATA (outbuf);
|
||||||
|
|
||||||
for (i = 0; i < samples; i++) {
|
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];
|
*outbuffer++ = (gint8) buffer[j][i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (depth == 12 || depth == 16) {
|
} else if (width == 16) {
|
||||||
gint16 *outbuffer = (gint16 *) GST_BUFFER_DATA (outbuf);
|
gint16 *outbuffer = (gint16 *) GST_BUFFER_DATA (outbuf);
|
||||||
|
|
||||||
for (i = 0; i < samples; i++) {
|
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];
|
*outbuffer++ = (gint16) buffer[j][i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (depth == 20 || depth == 24 || depth == 32) {
|
} else if (width == 32) {
|
||||||
gint32 *outbuffer = (gint32 *) GST_BUFFER_DATA (outbuf);
|
gint32 *outbuffer = (gint32 *) GST_BUFFER_DATA (outbuf);
|
||||||
|
|
||||||
for (i = 0; i < samples; i++) {
|
for (i = 0; i < samples; i++) {
|
||||||
|
@ -21,9 +21,6 @@
|
|||||||
* - we assume timestamps start from 0 and that we get a perfect stream; we
|
* - 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
|
* don't handle non-zero starts and mid-stream discontinuities, esp. not if
|
||||||
* we're muxing into ogg
|
* 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
|
#ifdef HAVE_CONFIG_H
|
||||||
@ -87,12 +84,26 @@ GST_ELEMENT_DETAILS ("FLAC audio encoder",
|
|||||||
"Wim Taymans <wim.taymans@chello.be>");
|
"Wim Taymans <wim.taymans@chello.be>");
|
||||||
|
|
||||||
#define FLAC_SINK_CAPS \
|
#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, " \
|
"audio/x-raw-int, " \
|
||||||
"endianness = (int) BYTE_ORDER, " \
|
"endianness = (int) BYTE_ORDER, " \
|
||||||
"signed = (boolean) TRUE, " \
|
"signed = (boolean) TRUE, " \
|
||||||
"width = (int) 16, " \
|
"width = (int) 16, " \
|
||||||
"depth = (int) 16, " \
|
"depth = (int) { 12, 16 }, " \
|
||||||
"rate = (int) [ 8000, 96000 ], " \
|
"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 ]"
|
"channels = (int) [ 1, 8 ]"
|
||||||
|
|
||||||
static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
|
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);
|
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 *
|
static GstCaps *
|
||||||
gst_flac_enc_sink_getcaps (GstPad * pad)
|
gst_flac_enc_sink_getcaps (GstPad * pad)
|
||||||
{
|
{
|
||||||
@ -460,12 +514,11 @@ gst_flac_enc_sink_getcaps (GstPad * pad)
|
|||||||
|
|
||||||
ret = gst_caps_new_empty ();
|
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,
|
"endianness", G_TYPE_INT, G_BYTE_ORDER,
|
||||||
"signed", G_TYPE_BOOLEAN, TRUE,
|
"signed", G_TYPE_BOOLEAN, TRUE,
|
||||||
"width", G_TYPE_INT, 16,
|
"rate", GST_TYPE_INT_RANGE, 1, 655350,
|
||||||
"depth", G_TYPE_INT, 16,
|
|
||||||
"rate", GST_TYPE_INT_RANGE, 8000, 96000,
|
|
||||||
"channels", GST_TYPE_INT_RANGE, 1, 2, NULL));
|
"channels", GST_TYPE_INT_RANGE, 1, 2, NULL));
|
||||||
|
|
||||||
for (i = 3; i <= 8; i++) {
|
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",
|
s = gst_structure_new ("audio/x-raw-int",
|
||||||
"endianness", G_TYPE_INT, G_BYTE_ORDER,
|
"endianness", G_TYPE_INT, G_BYTE_ORDER,
|
||||||
"signed", G_TYPE_BOOLEAN, TRUE,
|
"signed", G_TYPE_BOOLEAN, TRUE,
|
||||||
"width", G_TYPE_INT, 16,
|
"rate", GST_TYPE_INT_RANGE, 1, 655350,
|
||||||
"depth", G_TYPE_INT, 16,
|
|
||||||
"rate", GST_TYPE_INT_RANGE, 8000, 96000,
|
|
||||||
"channels", G_TYPE_INT, i, NULL);
|
"channels", G_TYPE_INT, i, NULL);
|
||||||
gst_structure_set_value (s, "channel-positions", &positions);
|
gst_structure_set_value (s, "channel-positions", &positions);
|
||||||
g_value_unset (&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->channels = chans;
|
||||||
|
flacenc->width = width;
|
||||||
flacenc->depth = depth;
|
flacenc->depth = depth;
|
||||||
flacenc->sample_rate = rate;
|
flacenc->sample_rate = rate;
|
||||||
|
|
||||||
@ -1019,7 +1071,7 @@ gst_flac_enc_chain (GstPad * pad, GstBuffer * buffer)
|
|||||||
GstFlacEnc *flacenc;
|
GstFlacEnc *flacenc;
|
||||||
FLAC__int32 *data;
|
FLAC__int32 *data;
|
||||||
gulong insize;
|
gulong insize;
|
||||||
gint samples, depth;
|
gint samples, width;
|
||||||
gulong i;
|
gulong i;
|
||||||
FLAC__bool res;
|
FLAC__bool res;
|
||||||
|
|
||||||
@ -1029,21 +1081,26 @@ gst_flac_enc_chain (GstPad * pad, GstBuffer * buffer)
|
|||||||
if (G_UNLIKELY (flacenc->depth == 0))
|
if (G_UNLIKELY (flacenc->depth == 0))
|
||||||
return GST_FLOW_NOT_NEGOTIATED;
|
return GST_FLOW_NOT_NEGOTIATED;
|
||||||
|
|
||||||
depth = flacenc->depth;
|
width = flacenc->width;
|
||||||
|
|
||||||
insize = GST_BUFFER_SIZE (buffer);
|
insize = GST_BUFFER_SIZE (buffer);
|
||||||
samples = insize / ((depth + 7) >> 3);
|
samples = insize / (width >> 3);
|
||||||
|
|
||||||
data = g_malloc (samples * sizeof (FLAC__int32));
|
data = g_malloc (samples * sizeof (FLAC__int32));
|
||||||
|
|
||||||
if (depth == 8) {
|
if (width == 8) {
|
||||||
gint8 *indata = (gint8 *) GST_BUFFER_DATA (buffer);
|
gint8 *indata = (gint8 *) GST_BUFFER_DATA (buffer);
|
||||||
|
|
||||||
for (i = 0; i < samples; i++)
|
for (i = 0; i < samples; i++)
|
||||||
data[i] = (FLAC__int32) indata[i];
|
data[i] = (FLAC__int32) indata[i];
|
||||||
} else if (depth == 16) {
|
} else if (width == 16) {
|
||||||
gint16 *indata = (gint16 *) GST_BUFFER_DATA (buffer);
|
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++)
|
for (i = 0; i < samples; i++)
|
||||||
data[i] = (FLAC__int32) indata[i];
|
data[i] = (FLAC__int32) indata[i];
|
||||||
} else {
|
} else {
|
||||||
|
@ -58,6 +58,7 @@ struct _GstFlacEnc {
|
|||||||
guint64 samples_written;
|
guint64 samples_written;
|
||||||
gboolean eos;
|
gboolean eos;
|
||||||
gint channels;
|
gint channels;
|
||||||
|
gint width;
|
||||||
gint depth;
|
gint depth;
|
||||||
gint sample_rate;
|
gint sample_rate;
|
||||||
gboolean negotiated;
|
gboolean negotiated;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user