Added Lots of properties
authorWim Taymans <wim.taymans@gmail.com>
Sun, 15 Sep 2002 22:26:33 +0000 (22:26 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Sun, 15 Sep 2002 22:26:33 +0000 (22:26 +0000)
Original commit message from CVS:
Added Lots of properties
More cleanups

ext/flac/gstflacenc.c
ext/flac/gstflacenc.h

index a2e14ae..f915063 100644 (file)
@@ -43,28 +43,45 @@ enum {
 
 enum {
   ARG_0,
+  ARG_QUALITY,
+  ARG_STREAMABLE_SUBSET,
+  ARG_MID_SIDE_STEREO,
+  ARG_LOOSE_MID_SIDE_STEREO,
+  ARG_BLOCKSIZE,
+  ARG_MAX_LPC_ORDER,
+  ARG_QLP_COEFF_PRECISION,
+  ARG_QLP_COEFF_PREC_SEARCH,
+  ARG_ESCAPE_CODING,
+  ARG_EXHAUSTIVE_MODEL_SEARCH,
+  ARG_MIN_RESIDUAL_PARTITION_ORDER,
+  ARG_MAX_RESIDUAL_PARTITION_ORDER,
+  ARG_RICE_PARAMETER_SEARCH_DIST,
 };
 
-static void    gst_flacenc_init                (FlacEnc *flacenc);
-static void    gst_flacenc_class_init          (FlacEncClass *klass);
+static void            gst_flacenc_init                (FlacEnc *flacenc);
+static void            gst_flacenc_class_init          (FlacEncClass *klass);
+static void            gst_flacenc_dispose             (GObject *object);
 
-static void    gst_flacenc_chain               (GstPad *pad, GstBuffer *buf);
-
-static void     gst_flacenc_set_property        (GObject *object, guint prop_id, 
-                                                const GValue *value, GParamSpec *pspec);
-static void     gst_flacenc_get_property        (GObject *object, guint prop_id,
-                                                GValue *value, GParamSpec *pspec);
+static GstPadConnectReturn
+                       gst_flacenc_sinkconnect         (GstPad *pad, GstCaps *caps);
+static void            gst_flacenc_chain               (GstPad *pad, GstBuffer *buf);
+
+static gboolean        gst_flacenc_update_quality      (FlacEnc *flacenc, gint quality);
+static void            gst_flacenc_set_property        (GObject *object, guint prop_id, 
+                                                        const GValue *value, GParamSpec *pspec);
+static void            gst_flacenc_get_property        (GObject *object, guint prop_id,
+                                                        GValue *value, GParamSpec *pspec);
 static GstElementStateReturn
-               gst_flacenc_change_state        (GstElement *element);
+                       gst_flacenc_change_state        (GstElement *element);
 
 static FLAC__StreamEncoderWriteStatus 
-               gst_flacenc_write_callback      (const FLAC__StreamEncoder *encoder, 
-                                                const FLAC__byte buffer[], unsigned bytes, 
-                                                unsigned samples, unsigned current_frame, 
-                                                void *client_data);
-static void    gst_flacenc_metadata_callback   (const FLAC__StreamEncoder *encoder, 
-                                                const FLAC__StreamMetadata *metadata, 
-                                                void *client_data);
+                       gst_flacenc_write_callback      (const FLAC__StreamEncoder *encoder, 
+                                                        const FLAC__byte buffer[], unsigned bytes, 
+                                                        unsigned samples, unsigned current_frame, 
+                                                        void *client_data);
+static void            gst_flacenc_metadata_callback   (const FLAC__StreamEncoder *encoder, 
+                                                        const FLAC__StreamMetadata *metadata, 
+                                                        void *client_data);
 
 static GstElementClass *parent_class = NULL;
 /*static guint gst_flacenc_signals[LAST_SIGNAL] = { 0 }; */
@@ -91,6 +108,60 @@ flacenc_get_type (void)
   return flacenc_type;
 }
 
+typedef struct {
+  gboolean     exhaustive_model_search;
+  gboolean     escape_coding;
+  gboolean     mid_side;
+  gboolean     loose_mid_side;
+  guint        qlp_coeff_precision;
+  gboolean     qlp_coeff_prec_search;
+  guint        min_residual_partition_order;
+  guint        max_residual_partition_order;
+  guint        rice_parameter_search_dist;
+  guint        max_lpc_order;
+  guint                blocksize;
+} FlacEncParams;
+
+static const FlacEncParams flacenc_params[] = 
+{
+  { FALSE, FALSE, FALSE, FALSE, 0, FALSE, 2, 2,  0, 0,  1152 },
+  { FALSE, FALSE, TRUE,  TRUE,  0, FALSE, 2, 2,  0, 0,  1152 },
+  { FALSE, FALSE, TRUE,  FALSE, 0, FALSE, 0, 3,  0, 0,  1152 },
+  { FALSE, FALSE, FALSE, FALSE, 0, FALSE, 3, 3,  0, 6,  4608 },
+  { FALSE, FALSE, TRUE,  TRUE,  0, FALSE, 3, 3,  0, 8,  4608 },
+  { FALSE, FALSE, TRUE,  FALSE, 0, FALSE, 3, 3,  0, 8,  4608 },
+  { FALSE, FALSE, TRUE,  FALSE, 0, FALSE, 0, 4,  0, 8,  4608 },
+  { TRUE,  FALSE, TRUE,  FALSE, 0, FALSE, 0, 6,  0, 8,  4608 },
+  { TRUE,  FALSE, TRUE,  FALSE, 0, FALSE, 0, 6,  0, 12, 4608 },
+  { TRUE,  TRUE,  TRUE,  FALSE, 0, FALSE, 0, 16, 0, 32, 4608 },
+};
+
+#define DEFAULT_QUALITY 5
+
+#define GST_TYPE_FLACENC_QUALITY (gst_flacenc_quality_get_type ())
+GType
+gst_flacenc_quality_get_type (void)
+{
+  static GType qtype = 0;
+  if (qtype == 0) {
+    static const GEnumValue values[] = {
+      { 0, "0", "0 - Fastest compression" },
+      { 1, "1", "1" },
+      { 2, "2", "2" },
+      { 3, "3", "3" },
+      { 4, "4", "4" },
+      { 5, "5", "5 - Default" },
+      { 6, "6", "6" },
+      { 7, "7", "7" },
+      { 8, "8", "8 - Highest compression " },
+      { 9, "9", "9 - Insane" },
+      { 0, NULL, NULL }
+    };
+    qtype = g_enum_register_static ("FlacEncQuality", values);
+  }
+  return qtype;
+}
+
 static void
 gst_flacenc_class_init (FlacEncClass *klass)
 {
@@ -105,10 +176,125 @@ gst_flacenc_class_init (FlacEncClass *klass)
   /* we have no properties atm so this is a bit silly */
   gobject_class->set_property = gst_flacenc_set_property;
   gobject_class->get_property = gst_flacenc_get_property;
+  gobject_class->dispose      = gst_flacenc_dispose;
+
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUALITY,
+    g_param_spec_enum ("quality", 
+                      "Quality", 
+                      "Speed versus compression tradeoff",
+                       GST_TYPE_FLACENC_QUALITY, DEFAULT_QUALITY, G_PARAM_READWRITE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_STREAMABLE_SUBSET,
+    g_param_spec_boolean ("streamable_subset", 
+                         "Streamable subset", 
+                         "true to limit encoder to generating a Subset stream, else false",
+                          TRUE, G_PARAM_READWRITE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MID_SIDE_STEREO,
+    g_param_spec_boolean ("mid_side_stereo", 
+                         "Do mid side stereo", 
+                         "Do mid side stereo (only for stereo input)", 
+                          flacenc_params[DEFAULT_QUALITY].mid_side, G_PARAM_READWRITE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOOSE_MID_SIDE_STEREO,
+    g_param_spec_boolean ("loose_mid_side_stereo", 
+                         "Loose mid side stereo", 
+                         "Loose mid side stereo", 
+                          flacenc_params[DEFAULT_QUALITY].loose_mid_side, G_PARAM_READWRITE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BLOCKSIZE,
+    g_param_spec_uint ("blocksize", 
+                      "Blocksize", 
+                      "Blocksize in samples",
+                       FLAC__MIN_BLOCK_SIZE, FLAC__MAX_BLOCK_SIZE, 
+                       flacenc_params[DEFAULT_QUALITY].blocksize, G_PARAM_READWRITE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAX_LPC_ORDER,
+    g_param_spec_uint ("max_lpc_order", 
+                      "Max LPC order", 
+                      "Max LPC order; 0 => use only fixed predictors",
+                       0, FLAC__MAX_LPC_ORDER,
+                       flacenc_params[DEFAULT_QUALITY].max_lpc_order, G_PARAM_READWRITE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QLP_COEFF_PRECISION,
+    g_param_spec_uint ("qlp_coeff_precision", 
+                      "QLP coefficients precision", 
+                      "Precision in bits of quantized linear-predictor coefficients; 0 = automatic",
+                       0, 32, 
+                       flacenc_params[DEFAULT_QUALITY].qlp_coeff_precision, G_PARAM_READWRITE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QLP_COEFF_PREC_SEARCH,
+    g_param_spec_boolean ("qlp_coeff_prec_search", 
+                         "Do QLP coefficients precision search", 
+                         "false = use qlp_coeff_precision, "
+                           "true = search around qlp_coeff_precision, take best", 
+                          flacenc_params[DEFAULT_QUALITY].qlp_coeff_prec_search, G_PARAM_READWRITE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ESCAPE_CODING,
+    g_param_spec_boolean ("escape_coding", 
+                         "Do Escape coding", 
+                         "search for escape codes in the entropy coding stage "
+                           "for slightly better compression", 
+                          flacenc_params[DEFAULT_QUALITY].escape_coding, G_PARAM_READWRITE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_EXHAUSTIVE_MODEL_SEARCH,
+    g_param_spec_boolean ("exhaustive_model_search", 
+                         "Do exhaustive model search", 
+                         "do exhaustive search of LP coefficient quantization (expensive!)",
+                          flacenc_params[DEFAULT_QUALITY].exhaustive_model_search, G_PARAM_READWRITE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MIN_RESIDUAL_PARTITION_ORDER,
+    g_param_spec_uint ("min_residual_partition_order", 
+                      "Min residual partition order", 
+                      "Min residual partition order (above 4 doesn't usually help much)",
+                       0, 16, 
+                       flacenc_params[DEFAULT_QUALITY].min_residual_partition_order, G_PARAM_READWRITE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAX_RESIDUAL_PARTITION_ORDER,
+    g_param_spec_uint ("max_residual_partition_order", 
+                      "Max residual partition order", 
+                      "Max residual partition order (above 4 doesn't usually help much)",
+                       0, 16, 
+                       flacenc_params[DEFAULT_QUALITY].max_residual_partition_order, G_PARAM_READWRITE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_RICE_PARAMETER_SEARCH_DIST,
+    g_param_spec_uint ("rice_parameter_search_dist", 
+                      "rice_parameter_search_dist", 
+                      "0 = try only calc'd parameter k; else try all [k-dist..k+dist] "
+                        "parameters, use best",
+                       0, FLAC__MAX_RICE_PARTITION_ORDER, 
+                       flacenc_params[DEFAULT_QUALITY].rice_parameter_search_dist, G_PARAM_READWRITE));
 
   gstelement_class->change_state = gst_flacenc_change_state;
 }
 
+static void
+gst_flacenc_init (FlacEnc *flacenc)
+{
+  flacenc->sinkpad = gst_pad_new_from_template (gst_flacenc_sink_template, "sink");
+  gst_element_add_pad(GST_ELEMENT(flacenc),flacenc->sinkpad);
+  gst_pad_set_chain_function(flacenc->sinkpad,gst_flacenc_chain);
+  gst_pad_set_connect_function (flacenc->sinkpad, gst_flacenc_sinkconnect);
+
+  flacenc->srcpad = gst_pad_new_from_template (gst_flacenc_src_template, "src");
+  gst_element_add_pad(GST_ELEMENT(flacenc),flacenc->srcpad);
+
+  GST_FLAG_SET (flacenc, GST_ELEMENT_EVENT_AWARE);
+
+  flacenc->encoder = FLAC__stream_encoder_new();
+
+  FLAC__stream_encoder_set_write_callback (flacenc->encoder, 
+                                       gst_flacenc_write_callback);
+  FLAC__stream_encoder_set_metadata_callback (flacenc->encoder, 
+                                       gst_flacenc_metadata_callback);
+  FLAC__stream_encoder_set_client_data (flacenc->encoder, 
+                                       flacenc);
+
+  flacenc->negotiated = FALSE;
+  flacenc->first = TRUE;
+  flacenc->first_buf = NULL;
+  flacenc->data = NULL;
+  gst_flacenc_update_quality (flacenc, DEFAULT_QUALITY);
+}
+
+static void
+gst_flacenc_dispose (GObject *object)
+{
+  FlacEnc *flacenc = GST_FLACENC (object);
+
+  FLAC__stream_encoder_delete (flacenc->encoder);
+  
+  G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
 static GstPadConnectReturn
 gst_flacenc_sinkconnect (GstPad *pad, GstCaps *caps)
 {
@@ -135,31 +321,40 @@ gst_flacenc_sinkconnect (GstPad *pad, GstCaps *caps)
   return GST_PAD_CONNECT_OK;
 }
 
-static void
-gst_flacenc_init (FlacEnc *flacenc)
+static gboolean
+gst_flacenc_update_quality (FlacEnc *flacenc, gint quality)
 {
-  flacenc->sinkpad = gst_pad_new_from_template (gst_flacenc_sink_template, "sink");
-  gst_element_add_pad(GST_ELEMENT(flacenc),flacenc->sinkpad);
-  gst_pad_set_chain_function(flacenc->sinkpad,gst_flacenc_chain);
-  gst_pad_set_connect_function (flacenc->sinkpad, gst_flacenc_sinkconnect);
-
-  flacenc->srcpad = gst_pad_new_from_template (gst_flacenc_src_template, "src");
-  gst_element_add_pad(GST_ELEMENT(flacenc),flacenc->srcpad);
-
-  flacenc->first = TRUE;
-  flacenc->first_buf = NULL;
-  flacenc->encoder = FLAC__stream_encoder_new();
-
-  FLAC__stream_encoder_set_write_callback (flacenc->encoder, 
-                                          gst_flacenc_write_callback);
-  FLAC__stream_encoder_set_metadata_callback (flacenc->encoder, 
-                                             gst_flacenc_metadata_callback);
-  FLAC__stream_encoder_set_client_data (flacenc->encoder, 
-                                       flacenc);
-
-  GST_FLAG_SET (flacenc, GST_ELEMENT_EVENT_AWARE);
-
-  flacenc->negotiated = FALSE;
+  flacenc->quality = quality;
+
+#define DO_UPDATE(name, val, str)                              \
+G_STMT_START{                                                   \
+  if (FLAC__stream_encoder_get_##name (flacenc->encoder) !=    \
+      flacenc_params[quality].##val) {                         \
+    FLAC__stream_encoder_set_##name (flacenc->encoder,                 \
+      flacenc_params[quality].##val);                          \
+    g_object_notify (G_OBJECT (flacenc), str);                  \
+  };                                                            \
+} G_STMT_END
+
+  g_object_freeze_notify (G_OBJECT (flacenc));
+
+  DO_UPDATE (do_mid_side_stereo,           mid_side,                     "mid_side_stereo");
+  DO_UPDATE (loose_mid_side_stereo,        loose_mid_side,               "loose_mid_side");
+  DO_UPDATE (blocksize,                    blocksize,                    "blocksize");
+  DO_UPDATE (max_lpc_order,                max_lpc_order,                "max_lpc_order");
+  DO_UPDATE (qlp_coeff_precision,          qlp_coeff_precision,          "qlp_coeff_precision");
+  DO_UPDATE (do_qlp_coeff_prec_search,     qlp_coeff_prec_search,        "qlp_coeff_prec_search");
+  DO_UPDATE (do_escape_coding,             escape_coding,                "escape_coding");
+  DO_UPDATE (do_exhaustive_model_search,   exhaustive_model_search,      "exhaustive_model_search");
+  DO_UPDATE (min_residual_partition_order, min_residual_partition_order, "min_residual_partition_order");
+  DO_UPDATE (max_residual_partition_order, max_residual_partition_order, "max_residual_partition_order");
+  DO_UPDATE (rice_parameter_search_dist,   rice_parameter_search_dist,   "rice_parameter_search_dist");
+
+#undef DO_UPDATE
+
+  g_object_thaw_notify (G_OBJECT (flacenc));
+
+  return TRUE;
 }
 
 static FLAC__StreamEncoderWriteStatus 
@@ -173,9 +368,10 @@ gst_flacenc_write_callback (const FLAC__StreamEncoder *encoder,
 
   flacenc = GST_FLACENC (client_data);
 
-  outbuf = gst_buffer_new ();
-  GST_BUFFER_SIZE (outbuf) = bytes;
-  GST_BUFFER_DATA (outbuf) = g_malloc (bytes);
+  if (flacenc->stopped) 
+    return FLAC__STREAM_ENCODER_WRITE_OK;
+
+  outbuf = gst_buffer_new_and_alloc (bytes);
 
   memcpy (GST_BUFFER_DATA (outbuf), buffer, bytes);
 
@@ -200,6 +396,9 @@ gst_flacenc_metadata_callback (const FLAC__StreamEncoder *encoder,
 
   flacenc = GST_FLACENC (client_data);
 
+  if (flacenc->stopped) 
+    return;
+
   event = gst_event_new_discontinuous (FALSE, GST_FORMAT_BYTES, 0, NULL);
   gst_pad_push (flacenc->srcpad, GST_BUFFER (event));
 
@@ -240,14 +439,12 @@ static void
 gst_flacenc_chain (GstPad *pad, GstBuffer *buf)
 {
   FlacEnc *flacenc;
-  gint32 *data[FLAC__MAX_CHANNELS];
+  FLAC__int32 *data;
   gulong insize;
-  gint samples, channels, depth;
-  gulong i, j;
-  gboolean res;
+  gint samples, depth;
+  gulong i;
+  FLAC__bool res;
 
-  g_return_if_fail(pad != NULL);
-  g_return_if_fail(GST_IS_PAD(pad));
   g_return_if_fail(buf != NULL);
 
   flacenc = GST_FLACENC (gst_pad_get_parent (pad));
@@ -271,11 +468,10 @@ gst_flacenc_chain (GstPad *pad, GstBuffer *buf)
     return;
   }
 
-  channels = flacenc->channels;
   depth = flacenc->depth;
 
   insize = GST_BUFFER_SIZE (buf);
-  samples = insize / channels / ((depth+7)>>3);
+  samples = insize / ((depth+7)>>3);
 
   if (FLAC__stream_encoder_get_state (flacenc->encoder) == 
                  FLAC__STREAM_ENCODER_UNINITIALIZED) 
@@ -283,39 +479,44 @@ gst_flacenc_chain (GstPad *pad, GstBuffer *buf)
     FLAC__StreamEncoderState state;
 
     state = FLAC__stream_encoder_init (flacenc->encoder);
-    
-    g_assert (state == FLAC__STREAM_ENCODER_OK);
+    if (state != FLAC__STREAM_ENCODER_OK) {
+      gst_element_error (GST_ELEMENT (flacenc),
+                        "could not initialize encoder (wrong parameters?)");
+      return;
+    }
   }
 
-  for (i=0; i<channels; i++) {
-    data[i] = g_malloc (samples * sizeof (gint32));
-  }
+  /* we keep a pointer in the flacenc struct because we are freeing the data
+   * after a push opreration that might never return */
+  data = flacenc->data = g_malloc (samples * sizeof (FLAC__int32));
     
   if (depth == 8) {
     gint8 *indata = (gint8 *) GST_BUFFER_DATA (buf);
-    for (j=0; j<samples; j++) {
-      for (i=0; i<channels; i++) {
-        data[i][j] = (gint32) *indata++;
-      }
+    
+    for (i=0; i<samples; i++) {
+      data[i] = (FLAC__int32) *indata++;
     }
   }
   else if (depth == 16) {
     gint16 *indata = (gint16 *) GST_BUFFER_DATA (buf);
-    for (j=0; j<samples; j++) {
-      for (i=0; i<channels; i++) {
-        data[i][j] = (gint32) *indata++;
-      }
+
+    for (i=0; i<samples; i++) {
+      data[i] = (FLAC__int32) *indata++;
     }
   }
 
-  res = FLAC__stream_encoder_process (flacenc->encoder, 
-                                     (const FLAC__int32 **)data, samples);
+  gst_buffer_unref(buf);
 
-  for (i=0; i<channels; i++) {
-    g_free (data[i]);
-  }
+  res = FLAC__stream_encoder_process_interleaved (flacenc->encoder, 
+                             (const FLAC__int32 *) data, samples / flacenc->channels);
 
-  gst_buffer_unref(buf);
+  g_free (flacenc->data);
+  flacenc->data = NULL;
+
+  if (!res) {
+    gst_element_error (GST_ELEMENT (flacenc),
+                        "encoding error");
+  }
 }
 
 static void
@@ -326,9 +527,60 @@ gst_flacenc_set_property (GObject *object, guint prop_id,
   
   this = (FlacEnc *)object;
   switch (prop_id) {
-  default:
-    GST_DEBUG(0, "Unknown arg %d", prop_id);
-    return;
+    case ARG_QUALITY:
+      gst_flacenc_update_quality (this, g_value_get_enum (value));
+      break;
+    case ARG_STREAMABLE_SUBSET:
+      FLAC__stream_encoder_set_streamable_subset (this->encoder, 
+                          g_value_get_boolean (value));
+      break;
+    case ARG_MID_SIDE_STEREO:
+      FLAC__stream_encoder_set_do_mid_side_stereo (this->encoder, 
+                          g_value_get_boolean (value));
+      break;
+    case ARG_LOOSE_MID_SIDE_STEREO:
+      FLAC__stream_encoder_set_loose_mid_side_stereo (this->encoder, 
+                          g_value_get_boolean (value));
+      break;
+    case ARG_BLOCKSIZE:
+      FLAC__stream_encoder_set_blocksize (this->encoder, 
+                          g_value_get_uint (value));
+      break;
+    case ARG_MAX_LPC_ORDER:
+      FLAC__stream_encoder_set_max_lpc_order (this->encoder, 
+                          g_value_get_uint (value));
+      break;
+    case ARG_QLP_COEFF_PRECISION:
+      FLAC__stream_encoder_set_qlp_coeff_precision (this->encoder, 
+                          g_value_get_uint (value));
+      break;
+    case ARG_QLP_COEFF_PREC_SEARCH:
+      FLAC__stream_encoder_set_do_qlp_coeff_prec_search (this->encoder, 
+                          g_value_get_boolean (value));
+      break;
+    case ARG_ESCAPE_CODING:
+      FLAC__stream_encoder_set_do_escape_coding (this->encoder, 
+                          g_value_get_boolean (value));
+      break;
+    case ARG_EXHAUSTIVE_MODEL_SEARCH:
+      FLAC__stream_encoder_set_do_exhaustive_model_search (this->encoder, 
+                          g_value_get_boolean (value));
+      break;
+    case ARG_MIN_RESIDUAL_PARTITION_ORDER:
+      FLAC__stream_encoder_set_min_residual_partition_order (this->encoder, 
+                          g_value_get_uint (value));
+      break;
+    case ARG_MAX_RESIDUAL_PARTITION_ORDER:
+      FLAC__stream_encoder_set_max_residual_partition_order (this->encoder, 
+                          g_value_get_uint (value));
+      break;
+    case ARG_RICE_PARAMETER_SEARCH_DIST:
+      FLAC__stream_encoder_set_rice_parameter_search_dist (this->encoder, 
+                                                g_value_get_uint (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      return;
   }
 }
 
@@ -341,9 +593,60 @@ gst_flacenc_get_property (GObject *object, guint prop_id,
   this = (FlacEnc *)object;
   
   switch (prop_id) {
-  default:
-    GST_DEBUG(0, "Unknown arg %d", prop_id);
-    break;
+    case ARG_QUALITY:
+      g_value_set_enum (value, this->quality);
+      break;
+    case ARG_STREAMABLE_SUBSET:
+      g_value_set_boolean (value, 
+             FLAC__stream_encoder_get_streamable_subset (this->encoder));
+      break;
+    case ARG_MID_SIDE_STEREO:
+      g_value_set_boolean (value, 
+             FLAC__stream_encoder_get_do_mid_side_stereo (this->encoder));
+      break;
+    case ARG_LOOSE_MID_SIDE_STEREO:
+      g_value_set_boolean (value, 
+             FLAC__stream_encoder_get_loose_mid_side_stereo (this->encoder));
+      break;
+    case ARG_BLOCKSIZE:
+      g_value_set_uint (value, 
+             FLAC__stream_encoder_get_blocksize (this->encoder));
+      break;
+    case ARG_MAX_LPC_ORDER:
+      g_value_set_uint (value, 
+             FLAC__stream_encoder_get_max_lpc_order (this->encoder));
+      break;
+    case ARG_QLP_COEFF_PRECISION:
+      g_value_set_uint (value, 
+             FLAC__stream_encoder_get_qlp_coeff_precision (this->encoder));
+      break;
+    case ARG_QLP_COEFF_PREC_SEARCH:
+      g_value_set_boolean (value, 
+             FLAC__stream_encoder_get_do_qlp_coeff_prec_search (this->encoder));
+      break;
+    case ARG_ESCAPE_CODING:
+      g_value_set_boolean (value, 
+             FLAC__stream_encoder_get_do_escape_coding (this->encoder));
+      break;
+    case ARG_EXHAUSTIVE_MODEL_SEARCH:
+      g_value_set_boolean (value, 
+             FLAC__stream_encoder_get_do_exhaustive_model_search (this->encoder));
+      break;
+    case ARG_MIN_RESIDUAL_PARTITION_ORDER:
+      g_value_set_uint (value, 
+             FLAC__stream_encoder_get_min_residual_partition_order (this->encoder));
+      break;
+    case ARG_MAX_RESIDUAL_PARTITION_ORDER:
+      g_value_set_uint (value, 
+             FLAC__stream_encoder_get_max_residual_partition_order (this->encoder));
+      break;
+    case ARG_RICE_PARAMETER_SEARCH_DIST:
+      g_value_set_uint (value, 
+             FLAC__stream_encoder_get_rice_parameter_search_dist (this->encoder));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
   }
 }
 
@@ -355,12 +658,24 @@ gst_flacenc_change_state (GstElement *element)
   switch (GST_STATE_TRANSITION (element)) {
     case GST_STATE_NULL_TO_READY:
     case GST_STATE_READY_TO_PAUSED:
+      flacenc->first = TRUE;
+      flacenc->stopped = FALSE;
       break;
     case GST_STATE_PAUSED_TO_PLAYING:
     case GST_STATE_PLAYING_TO_PAUSED:
       break;
     case GST_STATE_PAUSED_TO_READY:
+      if (FLAC__stream_encoder_get_state (flacenc->encoder) != 
+                       FLAC__STREAM_ENCODER_UNINITIALIZED) {
+        flacenc->stopped = TRUE;
+        FLAC__stream_encoder_finish (flacenc->encoder);
+      }
       flacenc->negotiated = FALSE;
+      if (flacenc->first_buf)
+       gst_buffer_unref (flacenc->first_buf);
+      flacenc->first_buf = NULL;
+      g_free (flacenc->data);
+      flacenc->data = NULL;
       break;
     case GST_STATE_READY_TO_NULL:
     default:
index 27f09ab..84c16db 100644 (file)
@@ -52,6 +52,9 @@ struct _FlacEnc {
   gint                  depth;
   gint                  sample_rate;
   gboolean      negotiated;
+  gint                  quality;
+  gboolean      stopped;
+  FLAC__int32  *data;
 
   FLAC__StreamEncoder *encoder;
 };