ext/flac/gstflacenc.c: Support encoding of up to 8 channels.

Original commit message from CVS:
* ext/flac/gstflacenc.c: (gst_flac_enc_init),
(gst_flac_enc_sink_getcaps):
Support encoding of up to 8 channels.
This commit is contained in:
Sebastian Dröge 2008-08-03 09:23:14 +00:00
parent 4223e83f3c
commit 826f568cb4
2 changed files with 144 additions and 36 deletions

View file

@ -1,3 +1,9 @@
2008-08-03 Sebastian Dröge <sebastian.droege@collabora.co.uk>
* ext/flac/gstflacenc.c: (gst_flac_enc_init),
(gst_flac_enc_sink_getcaps):
Support encoding of up to 8 channels.
2008-08-02 Jan Schmidt <jan.schmidt@sun.com> 2008-08-02 Jan Schmidt <jan.schmidt@sun.com>
* ext/soup/gstsouphttpsrc.c: * ext/soup/gstsouphttpsrc.c:

View file

@ -21,7 +21,7 @@
* - 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, flac can do 1-8 channels and 4-32 bit pcm * - need to support wider caps, 4-32 bit pcm
* http://flac.sourceforge.net/faq.html#general__channels * http://flac.sourceforge.net/faq.html#general__channels
* it also support sampling rate from 1Hz - 655350Hz * it also support sampling rate from 1Hz - 655350Hz
*/ */
@ -34,9 +34,51 @@
#include <gstflacenc.h> #include <gstflacenc.h>
#include <gst/audio/audio.h> #include <gst/audio/audio.h>
#include <gst/audio/multichannel.h>
#include <gst/tag/tag.h> #include <gst/tag/tag.h>
#include <gst/gsttagsetter.h> #include <gst/gsttagsetter.h>
/* Taken from http://flac.sourceforge.net/format.html#frame_header */
static const GstAudioChannelPosition channel_positions[8][8] = {
{GST_AUDIO_CHANNEL_POSITION_FRONT_MONO},
{GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, {
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER}, {
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}, {
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}, {
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
GST_AUDIO_CHANNEL_POSITION_LFE,
GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT},
/* FIXME: 7/8 channel layouts are not defined in the FLAC specs */
{
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
GST_AUDIO_CHANNEL_POSITION_LFE,
GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}, {
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
GST_AUDIO_CHANNEL_POSITION_LFE,
GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT}
};
static const GstElementDetails flacenc_details = static const GstElementDetails flacenc_details =
GST_ELEMENT_DETAILS ("FLAC audio encoder", GST_ELEMENT_DETAILS ("FLAC audio encoder",
@ -51,7 +93,7 @@ GST_ELEMENT_DETAILS ("FLAC audio encoder",
"width = (int) 16, " \ "width = (int) 16, " \
"depth = (int) 16, " \ "depth = (int) 16, " \
"rate = (int) [ 8000, 96000 ], " \ "rate = (int) [ 8000, 96000 ], " \
"channels = (int) [ 1, 2 ]" "channels = (int) [ 1, 8 ]"
static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC, GST_PAD_SRC,
@ -104,6 +146,7 @@ GST_BOILERPLATE_FULL (GstFlacEnc, gst_flac_enc, GstElement, GST_TYPE_ELEMENT,
static void gst_flac_enc_finalize (GObject * object); static void gst_flac_enc_finalize (GObject * object);
static gboolean gst_flac_enc_sink_setcaps (GstPad * pad, GstCaps * caps); static gboolean gst_flac_enc_sink_setcaps (GstPad * pad, GstCaps * caps);
static GstCaps *gst_flac_enc_sink_getcaps (GstPad * pad);
static gboolean gst_flac_enc_sink_event (GstPad * pad, GstEvent * event); static gboolean gst_flac_enc_sink_event (GstPad * pad, GstEvent * event);
static GstFlowReturn gst_flac_enc_chain (GstPad * pad, GstBuffer * buffer); static GstFlowReturn gst_flac_enc_chain (GstPad * pad, GstBuffer * buffer);
@ -312,6 +355,8 @@ gst_flac_enc_init (GstFlacEnc * flacenc, GstFlacEncClass * klass)
GST_DEBUG_FUNCPTR (gst_flac_enc_chain)); GST_DEBUG_FUNCPTR (gst_flac_enc_chain));
gst_pad_set_event_function (flacenc->sinkpad, gst_pad_set_event_function (flacenc->sinkpad,
GST_DEBUG_FUNCPTR (gst_flac_enc_sink_event)); GST_DEBUG_FUNCPTR (gst_flac_enc_sink_event));
gst_pad_set_getcaps_function (flacenc->sinkpad,
GST_DEBUG_FUNCPTR (gst_flac_enc_sink_getcaps));
gst_pad_set_setcaps_function (flacenc->sinkpad, gst_pad_set_setcaps_function (flacenc->sinkpad,
GST_DEBUG_FUNCPTR (gst_flac_enc_sink_setcaps)); GST_DEBUG_FUNCPTR (gst_flac_enc_sink_setcaps));
gst_element_add_pad (GST_ELEMENT (flacenc), flacenc->sinkpad); gst_element_add_pad (GST_ELEMENT (flacenc), flacenc->sinkpad);
@ -401,6 +446,63 @@ gst_flac_enc_set_metadata (GstFlacEnc * flacenc)
gst_tag_list_free (copy); gst_tag_list_free (copy);
} }
static GstCaps *
gst_flac_enc_sink_getcaps (GstPad * pad)
{
GstCaps *ret = NULL;
GST_OBJECT_LOCK (pad);
if (GST_PAD_CAPS (pad)) {
ret = gst_caps_ref (GST_PAD_CAPS (pad));
} else {
gint i, c;
ret = gst_caps_new_empty ();
gst_caps_append_structure (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,
"channels", GST_TYPE_INT_RANGE, 1, 2, NULL));
for (i = 3; i <= 8; i++) {
GValue positions = { 0, };
GValue pos = { 0, };
GstStructure *s;
g_value_init (&positions, GST_TYPE_ARRAY);
g_value_init (&pos, GST_TYPE_AUDIO_CHANNEL_POSITION);
for (c = 0; c < i; c++) {
g_value_set_enum (&pos, channel_positions[i - 1][c]);
gst_value_array_append_value (&positions, &pos);
}
g_value_unset (&pos);
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,
"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_OBJECT_UNLOCK (pad);
GST_DEBUG_OBJECT (pad, "Return caps %" GST_PTR_FORMAT, ret);
return ret;
}
static gboolean static gboolean
gst_flac_enc_sink_setcaps (GstPad * pad, GstCaps * caps) gst_flac_enc_sink_setcaps (GstPad * pad, GstCaps * caps)
{ {
@ -1056,38 +1158,38 @@ gst_flac_enc_set_property (GObject * object, guint prop_id,
break; break;
case PROP_EXHAUSTIVE_MODEL_SEARCH: case PROP_EXHAUSTIVE_MODEL_SEARCH:
#ifdef LEGACY_FLAC #ifdef LEGACY_FLAC
FLAC__seekable_stream_encoder_set_do_exhaustive_model_search (this-> FLAC__seekable_stream_encoder_set_do_exhaustive_model_search
encoder, g_value_get_boolean (value)); (this->encoder, g_value_get_boolean (value));
#else #else
FLAC__stream_encoder_set_do_exhaustive_model_search (this-> FLAC__stream_encoder_set_do_exhaustive_model_search (this->encoder,
encoder, g_value_get_boolean (value)); g_value_get_boolean (value));
#endif #endif
break; break;
case PROP_MIN_RESIDUAL_PARTITION_ORDER: case PROP_MIN_RESIDUAL_PARTITION_ORDER:
#ifdef LEGACY_FLAC #ifdef LEGACY_FLAC
FLAC__seekable_stream_encoder_set_min_residual_partition_order (this-> FLAC__seekable_stream_encoder_set_min_residual_partition_order
encoder, g_value_get_uint (value)); (this->encoder, g_value_get_uint (value));
#else #else
FLAC__stream_encoder_set_min_residual_partition_order (this-> FLAC__stream_encoder_set_min_residual_partition_order (this->encoder,
encoder, g_value_get_uint (value)); g_value_get_uint (value));
#endif #endif
break; break;
case PROP_MAX_RESIDUAL_PARTITION_ORDER: case PROP_MAX_RESIDUAL_PARTITION_ORDER:
#ifdef LEGACY_FLAC #ifdef LEGACY_FLAC
FLAC__seekable_stream_encoder_set_max_residual_partition_order (this-> FLAC__seekable_stream_encoder_set_max_residual_partition_order
encoder, g_value_get_uint (value)); (this->encoder, g_value_get_uint (value));
#else #else
FLAC__stream_encoder_set_max_residual_partition_order (this-> FLAC__stream_encoder_set_max_residual_partition_order (this->encoder,
encoder, g_value_get_uint (value)); g_value_get_uint (value));
#endif #endif
break; break;
case PROP_RICE_PARAMETER_SEARCH_DIST: case PROP_RICE_PARAMETER_SEARCH_DIST:
#ifdef LEGACY_FLAC #ifdef LEGACY_FLAC
FLAC__seekable_stream_encoder_set_rice_parameter_search_dist (this-> FLAC__seekable_stream_encoder_set_rice_parameter_search_dist
encoder, g_value_get_uint (value)); (this->encoder, g_value_get_uint (value));
#else #else
FLAC__stream_encoder_set_rice_parameter_search_dist (this-> FLAC__stream_encoder_set_rice_parameter_search_dist (this->encoder,
encoder, g_value_get_uint (value)); g_value_get_uint (value));
#endif #endif
break; break;
default: default:
@ -1131,8 +1233,8 @@ gst_flac_enc_get_property (GObject * object, guint prop_id,
case PROP_LOOSE_MID_SIDE_STEREO: case PROP_LOOSE_MID_SIDE_STEREO:
#ifdef LEGACY_FLAC #ifdef LEGACY_FLAC
g_value_set_boolean (value, g_value_set_boolean (value,
FLAC__seekable_stream_encoder_get_loose_mid_side_stereo (this-> FLAC__seekable_stream_encoder_get_loose_mid_side_stereo
encoder)); (this->encoder));
#else #else
g_value_set_boolean (value, g_value_set_boolean (value,
FLAC__stream_encoder_get_loose_mid_side_stereo (this->encoder)); FLAC__stream_encoder_get_loose_mid_side_stereo (this->encoder));
@ -1159,8 +1261,8 @@ gst_flac_enc_get_property (GObject * object, guint prop_id,
case PROP_QLP_COEFF_PRECISION: case PROP_QLP_COEFF_PRECISION:
#ifdef LEGACY_FLAC #ifdef LEGACY_FLAC
g_value_set_uint (value, g_value_set_uint (value,
FLAC__seekable_stream_encoder_get_qlp_coeff_precision (this-> FLAC__seekable_stream_encoder_get_qlp_coeff_precision
encoder)); (this->encoder));
#else #else
g_value_set_uint (value, g_value_set_uint (value,
FLAC__stream_encoder_get_qlp_coeff_precision (this->encoder)); FLAC__stream_encoder_get_qlp_coeff_precision (this->encoder));
@ -1169,8 +1271,8 @@ gst_flac_enc_get_property (GObject * object, guint prop_id,
case PROP_QLP_COEFF_PREC_SEARCH: case PROP_QLP_COEFF_PREC_SEARCH:
#ifdef LEGACY_FLAC #ifdef LEGACY_FLAC
g_value_set_boolean (value, g_value_set_boolean (value,
FLAC__seekable_stream_encoder_get_do_qlp_coeff_prec_search (this-> FLAC__seekable_stream_encoder_get_do_qlp_coeff_prec_search
encoder)); (this->encoder));
#else #else
g_value_set_boolean (value, g_value_set_boolean (value,
FLAC__stream_encoder_get_do_qlp_coeff_prec_search (this->encoder)); FLAC__stream_encoder_get_do_qlp_coeff_prec_search (this->encoder));
@ -1188,8 +1290,8 @@ gst_flac_enc_get_property (GObject * object, guint prop_id,
case PROP_EXHAUSTIVE_MODEL_SEARCH: case PROP_EXHAUSTIVE_MODEL_SEARCH:
#ifdef LEGACY_FLAC #ifdef LEGACY_FLAC
g_value_set_boolean (value, g_value_set_boolean (value,
FLAC__seekable_stream_encoder_get_do_exhaustive_model_search (this-> FLAC__seekable_stream_encoder_get_do_exhaustive_model_search
encoder)); (this->encoder));
#else #else
g_value_set_boolean (value, g_value_set_boolean (value,
FLAC__stream_encoder_get_do_exhaustive_model_search (this->encoder)); FLAC__stream_encoder_get_do_exhaustive_model_search (this->encoder));
@ -1198,30 +1300,30 @@ gst_flac_enc_get_property (GObject * object, guint prop_id,
case PROP_MIN_RESIDUAL_PARTITION_ORDER: case PROP_MIN_RESIDUAL_PARTITION_ORDER:
#ifdef LEGACY_FLAC #ifdef LEGACY_FLAC
g_value_set_uint (value, g_value_set_uint (value,
FLAC__seekable_stream_encoder_get_min_residual_partition_order (this-> FLAC__seekable_stream_encoder_get_min_residual_partition_order
encoder)); (this->encoder));
#else #else
g_value_set_uint (value, g_value_set_uint (value,
FLAC__stream_encoder_get_min_residual_partition_order (this-> FLAC__stream_encoder_get_min_residual_partition_order
encoder)); (this->encoder));
#endif #endif
break; break;
case PROP_MAX_RESIDUAL_PARTITION_ORDER: case PROP_MAX_RESIDUAL_PARTITION_ORDER:
#ifdef LEGACY_FLAC #ifdef LEGACY_FLAC
g_value_set_uint (value, g_value_set_uint (value,
FLAC__seekable_stream_encoder_get_max_residual_partition_order (this-> FLAC__seekable_stream_encoder_get_max_residual_partition_order
encoder)); (this->encoder));
#else #else
g_value_set_uint (value, g_value_set_uint (value,
FLAC__stream_encoder_get_max_residual_partition_order (this-> FLAC__stream_encoder_get_max_residual_partition_order
encoder)); (this->encoder));
#endif #endif
break; break;
case PROP_RICE_PARAMETER_SEARCH_DIST: case PROP_RICE_PARAMETER_SEARCH_DIST:
#ifdef LEGACY_FLAC #ifdef LEGACY_FLAC
g_value_set_uint (value, g_value_set_uint (value,
FLAC__seekable_stream_encoder_get_rice_parameter_search_dist (this-> FLAC__seekable_stream_encoder_get_rice_parameter_search_dist
encoder)); (this->encoder));
#else #else
g_value_set_uint (value, g_value_set_uint (value,
FLAC__stream_encoder_get_rice_parameter_search_dist (this->encoder)); FLAC__stream_encoder_get_rice_parameter_search_dist (this->encoder));