Merge remote-tracking branch 'origin/master' into 0.11
authorEdward Hervey <edward.hervey@collabora.co.uk>
Fri, 25 Nov 2011 11:48:58 +0000 (12:48 +0100)
committerEdward Hervey <edward.hervey@collabora.co.uk>
Fri, 25 Nov 2011 11:48:58 +0000 (12:48 +0100)
Conflicts:
ext/faac/gstfaac.c
ext/opus/gstopusdec.c
ext/opus/gstopusenc.c
gst/audiovisualizers/gstspacescope.c
gst/colorspace/colorspace.c

14 files changed:
1  2 
configure.ac
ext/faac/gstfaac.c
ext/opus/gstopusdec.c
ext/opus/gstopusenc.c
ext/opus/gstopusheader.c
ext/opus/gstopusparse.c
gst/audiovisualizers/gstspacescope.c
gst/audiovisualizers/gstwavescope.c
gst/frei0r/gstfrei0r.c
gst/mpeg4videoparse/mpeg4videoparse.c
gst/videoparsers/gstdiracparse.c
gst/videoparsers/gsth263parse.c
gst/videoparsers/gstmpegvideoparse.c
sys/Makefile.am

diff --cc configure.ac
Simple merge
@@@ -672,10 -678,8 +672,11 @@@ gst_faac_handle_frame (GstAudioEncoder 
    /* ERRORS */
  encode_failed:
    {
+     gst_buffer_unref (out_buf);
      GST_ELEMENT_ERROR (faac, LIBRARY, ENCODE, (NULL), (NULL));
 +    gst_buffer_unmap (in_buf, data, size);
 +    gst_buffer_unmap (out_buf, out_data, 0);
 +    gst_buffer_unref (out_buf);
      return GST_FLOW_ERROR;
    }
  }
@@@ -53,10 -55,11 +55,10 @@@ static GstStaticPadTemplate opus_dec_sr
  GST_STATIC_PAD_TEMPLATE ("src",
      GST_PAD_SRC,
      GST_PAD_ALWAYS,
 -    GST_STATIC_CAPS ("audio/x-raw-int, "
 -        "rate = (int) { 48000, 24000, 16000, 12000, 8000 }, "
 -        "channels = (int) [ 1, 8 ], "
 -        "endianness = (int) BYTE_ORDER, "
 -        "signed = (boolean) true, " "width = (int) 16, " "depth = (int) 16")
 +    GST_STATIC_CAPS ("audio/x-raw, "
-         "format = (string) { S16LE }, "
++        "format = (string) { " GST_AUDIO_NE (S16) " }, "
 +        "rate = (int) { 8000, 12000, 16000, 24000, 48000 }, "
-         "channels = (int) [ 1, 2 ] ")
++        "channels = (int) [ 1, 8 ] ")
      );
  
  static GstStaticPadTemplate opus_dec_sink_factory =
@@@ -66,8 -69,21 +68,21 @@@ GST_STATIC_PAD_TEMPLATE ("sink"
      GST_STATIC_CAPS ("audio/x-opus")
      );
  
 -GST_BOILERPLATE (GstOpusDec, gst_opus_dec, GstAudioDecoder,
 -    GST_TYPE_AUDIO_DECODER);
 +G_DEFINE_TYPE (GstOpusDec, gst_opus_dec, GST_TYPE_AUDIO_DECODER);
 +
+ #define DB_TO_LINEAR(x) pow (10., (x) / 20.)
+ #define DEFAULT_USE_INBAND_FEC FALSE
+ #define DEFAULT_APPLY_GAIN TRUE
+ enum
+ {
+   PROP_0,
+   PROP_USE_INBAND_FEC,
+   PROP_APPLY_GAIN
+ };
  static GstFlowReturn gst_opus_dec_parse_header (GstOpusDec * dec,
      GstBuffer * buf);
  static gboolean gst_opus_dec_start (GstAudioDecoder * dec);
@@@ -76,29 -92,55 +91,48 @@@ static GstFlowReturn gst_opus_dec_handl
      GstBuffer * buffer);
  static gboolean gst_opus_dec_set_format (GstAudioDecoder * bdec,
      GstCaps * caps);
+ static void gst_opus_dec_get_property (GObject * object, guint prop_id,
+     GValue * value, GParamSpec * pspec);
+ static void gst_opus_dec_set_property (GObject * object, guint prop_id,
+     const GValue * value, GParamSpec * pspec);
  
  static void
 -gst_opus_dec_base_init (gpointer g_class)
 -{
 -  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
 -
 -  gst_element_class_add_pad_template (element_class,
 -      gst_static_pad_template_get (&opus_dec_src_factory));
 -  gst_element_class_add_pad_template (element_class,
 -      gst_static_pad_template_get (&opus_dec_sink_factory));
 -  gst_element_class_set_details_simple (element_class, "Opus audio decoder",
 -      "Codec/Decoder/Audio",
 -      "decode opus streams to audio",
 -      "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
 -}
 -
 -static void
  gst_opus_dec_class_init (GstOpusDecClass * klass)
  {
+   GObjectClass *gobject_class;
    GstAudioDecoderClass *adclass;
 -  GstElementClass *gstelement_class;
 +  GstElementClass *element_class;
  
+   gobject_class = (GObjectClass *) klass;
    adclass = (GstAudioDecoderClass *) klass;
 -  gstelement_class = (GstElementClass *) klass;
 +  element_class = (GstElementClass *) klass;
  
+   gobject_class->set_property = gst_opus_dec_set_property;
+   gobject_class->get_property = gst_opus_dec_get_property;
    adclass->start = GST_DEBUG_FUNCPTR (gst_opus_dec_start);
    adclass->stop = GST_DEBUG_FUNCPTR (gst_opus_dec_stop);
    adclass->handle_frame = GST_DEBUG_FUNCPTR (gst_opus_dec_handle_frame);
    adclass->set_format = GST_DEBUG_FUNCPTR (gst_opus_dec_set_format);
  
 +  gst_element_class_add_pad_template (element_class,
 +      gst_static_pad_template_get (&opus_dec_src_factory));
 +  gst_element_class_add_pad_template (element_class,
 +      gst_static_pad_template_get (&opus_dec_sink_factory));
 +  gst_element_class_set_details_simple (element_class, "Opus audio decoder",
 +      "Codec/Decoder/Audio",
 +      "decode opus streams to audio",
 +      "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+   g_object_class_install_property (gobject_class, PROP_USE_INBAND_FEC,
+       g_param_spec_boolean ("use-inband-fec", "Use in-band FEC",
+           "Use forward error correction if available", DEFAULT_USE_INBAND_FEC,
+           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+   g_object_class_install_property (gobject_class, PROP_APPLY_GAIN,
+       g_param_spec_boolean ("apply-gain", "Apply gain",
+           "Apply gain if any is specified in the header", DEFAULT_APPLY_GAIN,
+           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
  
    GST_DEBUG_CATEGORY_INIT (opusdec_debug, "opusdec", 0,
        "opus decoding element");
@@@ -154,13 -218,92 +210,97 @@@ gst_opus_dec_get_r128_volume (gint16 r1
  static GstFlowReturn
  gst_opus_dec_parse_header (GstOpusDec * dec, GstBuffer * buf)
  {
-   g_return_val_if_fail (gst_opus_header_is_header (buf, "OpusHead", 8),
-       GST_FLOW_ERROR);
-   g_return_val_if_fail (GST_BUFFER_SIZE (buf) >= 19, GST_FLOW_ERROR);
 -  const guint8 *data = GST_BUFFER_DATA (buf);
++  const guint8 *data;
+   GstCaps *caps;
+   GstStructure *s;
+   const GstAudioChannelPosition *pos = NULL;
+   g_return_val_if_fail (gst_opus_header_is_id_header (buf), GST_FLOW_ERROR);
++
++  data = gst_buffer_map (buf, NULL, NULL, GST_MAP_READ);
++
+   g_return_val_if_fail (dec->n_channels != data[9], GST_FLOW_ERROR);
  
-   dec->pre_skip = GST_READ_UINT16_LE (GST_BUFFER_DATA (buf) + 10);
-   GST_INFO_OBJECT (dec, "Found pre-skip of %u samples", dec->pre_skip);
+   dec->n_channels = data[9];
+   dec->pre_skip = GST_READ_UINT16_LE (data + 10);
+   dec->r128_gain = GST_READ_UINT16_LE (data + 14);
+   dec->r128_gain_volume = gst_opus_dec_get_r128_volume (dec->r128_gain);
+   GST_INFO_OBJECT (dec,
+       "Found pre-skip of %u samples, R128 gain %d (volume %f)",
+       dec->pre_skip, dec->r128_gain, dec->r128_gain_volume);
+   dec->channel_mapping_family = data[18];
+   if (dec->channel_mapping_family == 0) {
+     /* implicit mapping */
+     GST_INFO_OBJECT (dec, "Channel mapping family 0, implicit mapping");
+     dec->n_streams = dec->n_stereo_streams = 1;
+     dec->channel_mapping[0] = 0;
+     dec->channel_mapping[1] = 1;
+   } else {
+     dec->n_streams = data[19];
+     dec->n_stereo_streams = data[20];
+     memcpy (dec->channel_mapping, data + 21, dec->n_channels);
+     if (dec->channel_mapping_family == 1) {
+       GST_INFO_OBJECT (dec, "Channel mapping family 1, Vorbis mapping");
+       switch (dec->n_channels) {
+         case 1:
+         case 2:
+           /* nothing */
+           break;
+         case 3:
+         case 4:
+         case 5:
+         case 6:
+         case 7:
+         case 8:
+           pos = gst_opus_channel_positions[dec->n_channels - 1];
+           break;
+         default:{
+           gint i;
+           GstAudioChannelPosition *posn =
+               g_new (GstAudioChannelPosition, dec->n_channels);
+           GST_ELEMENT_WARNING (GST_ELEMENT (dec), STREAM, DECODE,
+               (NULL), ("Using NONE channel layout for more than 8 channels"));
+           for (i = 0; i < dec->n_channels; i++)
+             posn[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
+           pos = posn;
+         }
+       }
+     } else {
+       GST_INFO_OBJECT (dec, "Channel mapping family %d",
+           dec->channel_mapping_family);
+     }
+   }
+   /* negotiate width with downstream */
+   caps = gst_pad_get_allowed_caps (GST_AUDIO_DECODER_SRC_PAD (dec));
+   s = gst_caps_get_structure (caps, 0);
+   gst_structure_fixate_field_nearest_int (s, "rate", 48000);
+   gst_structure_get_int (s, "rate", &dec->sample_rate);
+   gst_structure_fixate_field_nearest_int (s, "channels", dec->n_channels);
+   gst_structure_get_int (s, "channels", &dec->n_channels);
+   GST_INFO_OBJECT (dec, "Negotiated %d channels, %d Hz", dec->n_channels,
+       dec->sample_rate);
+   if (pos) {
+     gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos);
+   }
+   if (dec->n_channels > 8) {
+     g_free ((GstAudioChannelPosition *) pos);
+   }
+   GST_INFO_OBJECT (dec, "Setting src caps to %" GST_PTR_FORMAT, caps);
+   gst_pad_set_caps (GST_AUDIO_DECODER_SRC_PAD (dec), caps);
+   gst_caps_unref (caps);
++  gst_buffer_unmap (buf, (guint8 *) data, -1);
 +
    return GST_FLOW_OK;
  }
  
@@@ -171,53 -314,11 +311,11 @@@ gst_opus_dec_parse_comments (GstOpusDe
    return GST_FLOW_OK;
  }
  
- static void
- gst_opus_dec_setup_from_peer_caps (GstOpusDec * dec)
- {
-   GstPad *srcpad, *peer;
-   GstStructure *s;
-   GstCaps *caps;
-   const GstCaps *template_caps;
-   const GstCaps *peer_caps;
-   srcpad = GST_AUDIO_DECODER_SRC_PAD (dec);
-   peer = gst_pad_get_peer (srcpad);
-   if (peer) {
-     template_caps = gst_pad_get_pad_template_caps (srcpad);
-     peer_caps = gst_pad_get_caps (peer);
-     GST_DEBUG_OBJECT (dec, "Peer caps: %" GST_PTR_FORMAT, peer_caps);
-     caps = gst_caps_intersect (template_caps, peer_caps);
-     gst_pad_fixate_caps (peer, caps);
-     GST_DEBUG_OBJECT (dec, "Fixated caps: %" GST_PTR_FORMAT, caps);
-     s = gst_caps_get_structure (caps, 0);
-     if (!gst_structure_get_int (s, "channels", &dec->n_channels)) {
-       dec->n_channels = 2;
-       GST_WARNING_OBJECT (dec, "Failed to get channels, using default %d",
-           dec->n_channels);
-     } else {
-       GST_DEBUG_OBJECT (dec, "Got channels %d", dec->n_channels);
-     }
-     if (!gst_structure_get_int (s, "rate", &dec->sample_rate)) {
-       dec->sample_rate = 48000;
-       GST_WARNING_OBJECT (dec, "Failed to get rate, using default %d",
-           dec->sample_rate);
-     } else {
-       GST_DEBUG_OBJECT (dec, "Got sample rate %d", dec->sample_rate);
-     }
-     gst_audio_decoder_set_outcaps (GST_AUDIO_DECODER (dec), caps);
-   } else {
-     GST_WARNING_OBJECT (dec, "Failed to get src pad peer");
-   }
- }
  static GstFlowReturn
- opus_dec_chain_parse_data (GstOpusDec * dec, GstBuffer * buf)
+ opus_dec_chain_parse_data (GstOpusDec * dec, GstBuffer * buffer)
  {
    GstFlowReturn res = GST_FLOW_OK;
 -  gint size;
 +  gsize size, out_size;
    guint8 *data;
    GstBuffer *outbuf;
    gint16 *out_data;
        goto creation_failed;
    }
  
 -        GST_BUFFER_SIZE (buffer));
+   if (buffer) {
+     GST_DEBUG_OBJECT (dec, "Received buffer of size %u",
++        gst_buffer_get_size (buffer));
+   } else {
+     GST_DEBUG_OBJECT (dec, "Received missing buffer");
+   }
+   /* if using in-band FEC, we introdude one extra frame's delay as we need
+      to potentially wait for next buffer to decode a missing buffer */
+   if (dec->use_inband_fec && !dec->primed) {
+     GST_DEBUG_OBJECT (dec, "First buffer received in FEC mode, early out");
+     goto done;
+   }
+   /* That's the buffer we'll be sending to the opus decoder. */
+   buf = dec->use_inband_fec && dec->last_buffer ? dec->last_buffer : buffer;
    if (buf) {
 -    data = GST_BUFFER_DATA (buf);
 -    size = GST_BUFFER_SIZE (buf);
 +    data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
 +
-     GST_DEBUG_OBJECT (dec, "received buffer of size %u", size);
+     GST_DEBUG_OBJECT (dec, "Using buffer of size %u", size);
    } else {
      /* concealment data, pass NULL as the bits parameters */
-     GST_DEBUG_OBJECT (dec, "creating concealment data");
+     GST_DEBUG_OBJECT (dec, "Using NULL buffer");
      data = NULL;
      size = 0;
    }
  
-   if (data) {
-     samples =
-         opus_packet_get_samples_per_frame (data,
-         dec->sample_rate) * opus_packet_get_nb_frames (data, size);
-     packet_size = samples * dec->n_channels * 2;
-     GST_DEBUG_OBJECT (dec, "bandwidth %d", opus_packet_get_bandwidth (data));
-     GST_DEBUG_OBJECT (dec, "samples %d", samples);
-   } else {
-     /* use maximum size (120 ms) as we do now know in advance how many samples
-        will be returned */
-     samples = 120 * dec->sample_rate / 1000;
-   }
+   /* use maximum size (120 ms) as the number of returned samples is
+      not constant over the stream. */
+   samples = 120 * dec->sample_rate / 1000;
    packet_size = samples * dec->n_channels * 2;
 -  res = gst_pad_alloc_buffer_and_set_caps (GST_AUDIO_DECODER_SRC_PAD (dec),
 -      GST_BUFFER_OFFSET_NONE, packet_size,
 -      GST_PAD_CAPS (GST_AUDIO_DECODER_SRC_PAD (dec)), &outbuf);
 -
 -  if (res != GST_FLOW_OK) {
 -    GST_DEBUG_OBJECT (dec, "buf alloc flow: %s", gst_flow_get_name (res));
 -    return res;
 +  outbuf = gst_buffer_new_and_alloc (packet_size);
 +  if (!outbuf) {
 +    goto buffer_failed;
    }
  
 -  out_data = (gint16 *) GST_BUFFER_DATA (outbuf);
 +  out_data = (gint16 *) gst_buffer_map (outbuf, &out_size, NULL, GST_MAP_WRITE);
  
-   n = opus_decode (dec->state, data, size, out_data, samples, 0);
+   if (dec->use_inband_fec) {
+     if (dec->last_buffer) {
+       /* normal delayed decode */
+       n = opus_multistream_decode (dec->state, data, size, out_data, samples,
+           0);
+     } else {
+       /* FEC reconstruction decode */
+       n = opus_multistream_decode (dec->state, data, size, out_data, samples,
+           1);
+     }
+   } else {
+     /* normal decode */
+     n = opus_multistream_decode (dec->state, data, size, out_data, samples, 0);
+   }
 +  gst_buffer_unmap (buf, data, size);
 +  gst_buffer_unmap (outbuf, out_data, out_size);
    if (n < 0) {
      GST_ELEMENT_ERROR (dec, STREAM, DECODE, ("Decoding error: %d", n), (NULL));
      return GST_FLOW_ERROR;
    }
    GST_DEBUG_OBJECT (dec, "decoded %d samples", n);
--  GST_BUFFER_SIZE (outbuf) = n * 2 * dec->n_channels;
++  gst_buffer_set_size (outbuf, n * 2 * dec->n_channels);
  
    /* Skip any samples that need skipping */
    if (dec->pre_skip > 0) {
      guint scaled_pre_skip = dec->pre_skip * dec->sample_rate / 48000;
      guint skip = scaled_pre_skip > n ? n : scaled_pre_skip;
      guint scaled_skip = skip * 48000 / dec->sample_rate;
--    GST_BUFFER_SIZE (outbuf) -= skip * 2 * dec->n_channels;
--    GST_BUFFER_DATA (outbuf) += skip * 2 * dec->n_channels;
++
++    gst_buffer_resize (outbuf, skip * 2 * dec->n_channels, -1);
      dec->pre_skip -= scaled_skip;
      GST_INFO_OBJECT (dec,
          "Skipping %u samples (%u at 48000 Hz, %u left to skip)", skip,
          scaled_skip, dec->pre_skip);
  
--    if (GST_BUFFER_SIZE (outbuf) == 0) {
++    if (gst_buffer_get_size (outbuf) == 0) {
        gst_buffer_unref (outbuf);
        outbuf = NULL;
      }
    }
  
 -    unsigned int i, nsamples = GST_BUFFER_SIZE (outbuf) / 2;
+   /* Apply gain */
+   /* Would be better off leaving this to a volume element, as this is
+      a naive conversion that does too many int/float conversions.
+      However, we don't have control over the pipeline...
+      So make it optional if the user program wants to use a volume,
+      but do it by default so the correct volume goes out by default */
+   if (dec->apply_gain && outbuf && dec->r128_gain) {
 -    gint16 *samples = (gint16 *) GST_BUFFER_DATA (outbuf);
++    gsize rsize;
++    unsigned int i, nsamples;
+     double volume = dec->r128_gain_volume;
++    gint16 *samples =
++        (gint16 *) gst_buffer_map (outbuf, &rsize, NULL, GST_MAP_READWRITE);
++
+     GST_DEBUG_OBJECT (dec, "Applying gain: volume %f", volume);
++    nsamples = rsize / 2;
+     for (i = 0; i < nsamples; ++i) {
+       int sample = (int) (samples[i] * volume + 0.5);
+       samples[i] = sample < -32768 ? -32768 : sample > 32767 ? 32767 : sample;
+     }
++    gst_buffer_unmap (outbuf, samples, rsize);
+   }
    res = gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (dec), outbuf, 1);
  
    if (res != GST_FLOW_OK)
@@@ -177,13 -178,41 +178,10 @@@ static gint64 gst_opus_enc_get_latency 
  
  static GstFlowReturn gst_opus_enc_encode (GstOpusEnc * enc, GstBuffer * buffer);
  
- static GstFlowReturn gst_opus_enc_encode (GstOpusEnc * enc, GstBuffer * buf);
- static gint64 gst_opus_enc_get_latency (GstOpusEnc * enc);
 -static void
 -gst_opus_enc_setup_interfaces (GType opusenc_type)
 -{
 -  static const GInterfaceInfo tag_setter_info = { NULL, NULL, NULL };
 -  const GInterfaceInfo preset_interface_info = {
 -    NULL,                       /* interface_init */
 -    NULL,                       /* interface_finalize */
 -    NULL                        /* interface_data */
 -  };
 -
 -  g_type_add_interface_static (opusenc_type, GST_TYPE_TAG_SETTER,
 -      &tag_setter_info);
 -  g_type_add_interface_static (opusenc_type, GST_TYPE_PRESET,
 -      &preset_interface_info);
 -
 -  GST_DEBUG_CATEGORY_INIT (opusenc_debug, "opusenc", 0, "Opus encoder");
 -}
 -
 -GST_BOILERPLATE_FULL (GstOpusEnc, gst_opus_enc, GstAudioEncoder,
 -    GST_TYPE_AUDIO_ENCODER, gst_opus_enc_setup_interfaces);
 -
 -static void
 -gst_opus_enc_base_init (gpointer g_class)
 -{
 -  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
--
 -  gst_element_class_add_pad_template (element_class,
 -      gst_static_pad_template_get (&src_factory));
 -  gst_element_class_add_pad_template (element_class,
 -      gst_static_pad_template_get (&sink_factory));
 -  gst_element_class_set_details_simple (element_class, "Opus audio encoder",
 -      "Codec/Encoder/Audio",
 -      "Encodes audio in Opus format",
 -      "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
 -}
 +#define gst_opus_enc_parent_class parent_class
 +G_DEFINE_TYPE_WITH_CODE (GstOpusEnc, gst_opus_enc, GST_TYPE_AUDIO_ENCODER,
 +    G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL);
 +    G_IMPLEMENT_INTERFACE (GST_TYPE_PRESET, NULL));
  
  static void
  gst_opus_enc_class_init (GstOpusEncClass * klass)
    gobject_class->set_property = gst_opus_enc_set_property;
    gobject_class->get_property = gst_opus_enc_get_property;
  
-   gst_element_class_add_pad_template (element_class,
++  gst_element_class_add_pad_template (gstelement_class,
 +      gst_static_pad_template_get (&src_factory));
-   gst_element_class_add_pad_template (element_class,
++  gst_element_class_add_pad_template (gstelement_class,
 +      gst_static_pad_template_get (&sink_factory));
-   gst_element_class_set_details_simple (element_class, "Opus audio encoder",
++  gst_element_class_set_details_simple (gstelement_class, "Opus audio encoder",
 +      "Codec/Encoder/Audio",
 +      "Encodes audio in Opus format",
 +      "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
 +
    base_class->start = GST_DEBUG_FUNCPTR (gst_opus_enc_start);
    base_class->stop = GST_DEBUG_FUNCPTR (gst_opus_enc_stop);
    base_class->set_format = GST_DEBUG_FUNCPTR (gst_opus_enc_set_format);
@@@ -290,7 -308,7 +288,7 @@@ gst_opus_enc_finalize (GObject * object
  }
  
  static void
--gst_opus_enc_init (GstOpusEnc * enc, GstOpusEncClass * klass)
++gst_opus_enc_init (GstOpusEnc * enc)
  {
    GstAudioEncoder *benc = GST_AUDIO_ENCODER (enc);
  
@@@ -324,7 -342,7 +322,7 @@@ gst_opus_enc_start (GstAudioEncoder * b
    GstOpusEnc *enc = GST_OPUS_ENC (benc);
  
    GST_DEBUG_OBJECT (enc, "start");
--  enc->tags = gst_tag_list_new ();
++  enc->tags = gst_tag_list_new_empty ();
    enc->header_sent = FALSE;
  
    return TRUE;
@@@ -501,9 -596,9 +577,9 @@@ gst_opus_enc_sink_event (GstAudioEncode
  static GstFlowReturn
  gst_opus_enc_encode (GstOpusEnc * enc, GstBuffer * buf)
  {
--  guint8 *bdata, *data, *mdata = NULL;
++  guint8 *bdata = NULL, *data, *mdata = NULL;
    gsize bsize, size;
 -  gsize bytes;
 +  gsize bytes = enc->frame_samples * enc->n_channels * 2;
    gint ret = GST_FLOW_OK;
  
    g_mutex_lock (enc->property_lock);
      goto done;
    }
  
 -
    while (size) {
 -    gint outsize;
 +    gint encoded_size;
 +    unsigned char *out_data;
 +    gsize out_size;
      GstBuffer *outbuf;
  
-     outbuf = gst_buffer_new_and_alloc (enc->max_payload_size);
 -    ret = gst_pad_alloc_buffer_and_set_caps (GST_AUDIO_ENCODER_SRC_PAD (enc),
 -        GST_BUFFER_OFFSET_NONE, enc->max_payload_size * enc->n_channels,
 -        GST_PAD_CAPS (GST_AUDIO_ENCODER_SRC_PAD (enc)), &outbuf);
 -
 -    if (GST_FLOW_OK != ret)
++    outbuf = gst_buffer_new_and_alloc (enc->max_payload_size * enc->n_channels);
 +    if (!outbuf)
        goto done;
  
      GST_DEBUG_OBJECT (enc, "encoding %d samples (%d bytes)",
-         enc->frame_samples);
+         enc->frame_samples, (int) bytes);
  
 -    outsize =
 +    out_data = gst_buffer_map (outbuf, &out_size, NULL, GST_MAP_WRITE);
 +    encoded_size =
-         opus_encode (enc->state, (const gint16 *) data, enc->frame_samples,
-         out_data, enc->max_payload_size);
+         opus_multistream_encode (enc->state, (const gint16 *) data,
 -        enc->frame_samples, GST_BUFFER_DATA (outbuf),
 -        enc->max_payload_size * enc->n_channels);
++        enc->frame_samples, out_data, enc->max_payload_size * enc->n_channels);
 +    gst_buffer_unmap (outbuf, out_data, out_size);
  
 -    if (outsize < 0) {
 -      GST_ERROR_OBJECT (enc, "Encoding failed: %d", outsize);
 +    if (encoded_size < 0) {
 +      GST_ERROR_OBJECT (enc, "Encoding failed: %d", encoded_size);
        ret = GST_FLOW_ERROR;
        goto done;
 -    } else if (outsize > enc->max_payload_size) {
 +    } else if (encoded_size > enc->max_payload_size) {
        GST_WARNING_OBJECT (enc,
            "Encoded size %d is higher than max payload size (%d bytes)",
--          outsize, enc->max_payload_size);
++          out_size, enc->max_payload_size);
        ret = GST_FLOW_ERROR;
        goto done;
      }
  
 -    GST_DEBUG_OBJECT (enc, "Output packet is %u bytes", outsize);
--    GST_BUFFER_SIZE (outbuf) = outsize;
++    GST_DEBUG_OBJECT (enc, "Output packet is %u bytes", encoded_size);
++    gst_buffer_set_size (outbuf, encoded_size);
  
      ret =
          gst_audio_encoder_finish_frame (GST_AUDIO_ENCODER (enc), outbuf,
@@@ -613,7 -709,7 +691,7 @@@ gst_opus_enc_handle_frame (GstAudioEnco
    }
  
    GST_DEBUG_OBJECT (enc, "received buffer %p of %u bytes", buf,
--      buf ? GST_BUFFER_SIZE (buf) : 0);
++      buf ? gst_buffer_get_size (buf) : 0);
  
    ret = gst_opus_enc_encode (enc, buf);
  
@@@ -62,7 -68,7 +68,7 @@@ gst_opus_enc_create_metadata_buffer (co
    if (tags == NULL) {
      /* FIXME: better fix chain of callers to not write metadata at all,
       * if there is none */
--    empty_tags = gst_tag_list_new ();
++    empty_tags = gst_tag_list_new_empty ();
      tags = empty_tags;
    }
    comments =
@@@ -165,6 -185,46 +185,58 @@@ gst_opus_header_create_caps (GstCaps *
  gboolean
  gst_opus_header_is_header (GstBuffer * buf, const char *magic, guint magic_size)
  {
--  return (GST_BUFFER_SIZE (buf) >= magic_size
--      && !memcmp (magic, GST_BUFFER_DATA (buf), magic_size));
++  return (gst_buffer_get_size (buf) >= magic_size
++      && !gst_buffer_memcmp (buf, 0, magic, magic_size));
+ }
+ gboolean
+ gst_opus_header_is_id_header (GstBuffer * buf)
+ {
 -  gsize size = GST_BUFFER_SIZE (buf);
 -  const guint8 *data = GST_BUFFER_DATA (buf);
++  gsize size = gst_buffer_get_size (buf);
++  guint8 *data = NULL;
+   guint8 channels, channel_mapping_family, n_streams, n_stereo_streams;
++  gboolean ret = FALSE;
+   if (size < 19)
 -    return FALSE;
++    goto beach;
+   if (!gst_opus_header_is_header (buf, "OpusHead", 8))
 -    return FALSE;
++    goto beach;
++
++  data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
++
+   channels = data[9];
++
+   if (channels == 0)
 -    return FALSE;
++    goto beach;
++
+   channel_mapping_family = data[18];
++
+   if (channel_mapping_family == 0) {
+     if (channels > 2)
 -      return FALSE;
++      goto beach;
+   } else {
+     channels = data[9];
+     if (size < 21 + channels)
 -      return FALSE;
++      goto beach;
+     n_streams = data[19];
+     n_stereo_streams = data[20];
+     if (n_streams == 0)
 -      return FALSE;
++      goto beach;
+     if (n_stereo_streams > n_streams)
 -      return FALSE;
++      goto beach;
+     if (n_streams + n_stereo_streams > 255)
 -      return FALSE;
++      goto beach;
+   }
 -  return TRUE;
++  ret = TRUE;
++
++beach:
++  if (data)
++    gst_buffer_unmap (buf, data, size);
++  return ret;
+ }
+ gboolean
+ gst_opus_header_is_comment_header (GstBuffer * buf)
+ {
+   return gst_opus_header_is_header (buf, "OpusTags", 8);
  }
@@@ -107,10 -108,6 +108,11 @@@ static gboolea
  gst_opus_parse_start (GstBaseParse * base)
  {
    GstOpusParse *parse = GST_OPUS_PARSE (base);
++  GstCaps *caps;
 +
 +  caps = gst_caps_new_empty_simple ("audio/x-opus");
 +  gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (parse)), caps);
 +  gst_caps_unref (caps);
  
    parse->header_sent = FALSE;
    parse->next_ts = 0;
@@@ -295,23 -270,63 +275,71 @@@ gst_opus_parse_parse_frame (GstBasePars
  {
    guint64 duration;
    GstOpusParse *parse;
+   gboolean is_idheader, is_commentheader;
++  guint8 *data;
++  gsize size;
  
    parse = GST_OPUS_PARSE (base);
  
-   if (gst_opus_header_is_header (frame->buffer, "OpusHead", 8)
-       || gst_opus_header_is_header (frame->buffer, "OpusTags", 8)) {
-     GST_BUFFER_TIMESTAMP (frame->buffer) = 0;
-     GST_BUFFER_DURATION (frame->buffer) = GST_CLOCK_TIME_NONE;
-     GST_BUFFER_OFFSET_END (frame->buffer) = GST_CLOCK_TIME_NONE;
-     GST_BUFFER_OFFSET (frame->buffer) = GST_CLOCK_TIME_NONE;
-     return GST_FLOW_OK;
+   is_idheader = gst_opus_header_is_id_header (frame->buffer);
+   is_commentheader = gst_opus_header_is_comment_header (frame->buffer);
+   if (!parse->header_sent) {
+     GstCaps *caps;
+     guint8 channels, channel_mapping_family, channel_mapping[256];
 -    const guint8 *data = GST_BUFFER_DATA (frame->buffer);
++
++    data = gst_buffer_map (frame->buffer, &size, NULL, GST_MAP_READ);
++
++    /* FIXME : Check available size ? */
+     /* Opus streams can decode to 1 or 2 channels, so use the header
+        value if we have one, or 2 otherwise */
+     if (is_idheader) {
+       channels = data[9];
+       channel_mapping_family = data[18];
+       /* header probing will already have done the size check */
 -      memcpy (channel_mapping, GST_BUFFER_DATA (frame->buffer) + 21, channels);
++      memcpy (channel_mapping, data + 21, channels);
++      gst_buffer_unmap (frame->buffer, data, size);
+       gst_buffer_replace (&parse->id_header, frame->buffer);
+       GST_DEBUG_OBJECT (parse, "Found ID header, keeping");
+       return GST_BASE_PARSE_FLOW_DROPPED;
+     } else if (is_commentheader) {
++      gst_buffer_unmap (frame->buffer, data, size);
+       gst_buffer_replace (&parse->comment_header, frame->buffer);
+       GST_DEBUG_OBJECT (parse, "Found comment header, keeping");
+       return GST_BASE_PARSE_FLOW_DROPPED;
+     }
++    gst_buffer_unmap (frame->buffer, data, size);
+     g_slist_foreach (parse->headers, (GFunc) gst_buffer_unref, NULL);
+     parse->headers = NULL;
+     if (parse->id_header && parse->comment_header) {
+       gst_opus_header_create_caps_from_headers (&caps, &parse->headers,
+           parse->id_header, parse->comment_header);
+     } else {
+       GST_INFO_OBJECT (parse,
+           "No headers, blindly setting up canonical stereo");
+       channels = 2;
+       channel_mapping_family = 0;
+       channel_mapping[0] = 0;
+       channel_mapping[1] = 1;
+       gst_opus_header_create_caps (&caps, &parse->headers, channels, 0,
+           channel_mapping_family, channel_mapping, NULL);
+     }
+     gst_buffer_replace (&parse->id_header, NULL);
+     gst_buffer_replace (&parse->comment_header, NULL);
+     gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps);
+     parse->header_sent = TRUE;
    }
  
    GST_BUFFER_TIMESTAMP (frame->buffer) = parse->next_ts;
  
--  duration =
--      packet_duration_opus (GST_BUFFER_DATA (frame->buffer),
--      GST_BUFFER_SIZE (frame->buffer));
++  data = gst_buffer_map (frame->buffer, &size, NULL, GST_MAP_READ);
++  duration = packet_duration_opus (data, size);
++  gst_buffer_unmap (frame->buffer, data, size);
    parse->next_ts += duration;
  
    GST_BUFFER_DURATION (frame->buffer) = duration;
@@@ -65,14 -101,13 +107,15 @@@ static gboolean gst_space_scope_render 
      GstBuffer * audio, GstBuffer * video);
  
  
 -GST_BOILERPLATE (GstSpaceScope, gst_space_scope, GstBaseAudioVisualizer,
 -    GST_TYPE_BASE_AUDIO_VISUALIZER);
 +G_DEFINE_TYPE (GstSpaceScope, gst_space_scope, GST_TYPE_BASE_AUDIO_VISUALIZER);
  
  static void
 -gst_space_scope_base_init (gpointer g_class)
 +gst_space_scope_class_init (GstSpaceScopeClass * g_class)
  {
 -  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
++  GObjectClass *gobject_class = (GObjectClass *) g_class;
 +  GstElementClass *element_class = (GstElementClass *) g_class;
 +  GstBaseAudioVisualizerClass *scope_class =
 +      (GstBaseAudioVisualizerClass *) g_class;
  
    gst_element_class_set_details_simple (element_class, "Stereo visualizer",
        "Visualization",
        gst_static_pad_template_get (&gst_space_scope_src_template));
    gst_element_class_add_pad_template (element_class,
        gst_static_pad_template_get (&gst_space_scope_sink_template));
 -}
 -
 -static void
 -gst_space_scope_class_init (GstSpaceScopeClass * g_class)
 -{
 -  GObjectClass *gobject_class = (GObjectClass *) g_class;
 -  GstBaseAudioVisualizerClass *scope_class =
 -      (GstBaseAudioVisualizerClass *) g_class;
  
+   gobject_class->set_property = gst_space_scope_set_property;
+   gobject_class->get_property = gst_space_scope_get_property;
    scope_class->render = GST_DEBUG_FUNCPTR (gst_space_scope_render);
+   g_object_class_install_property (gobject_class, PROP_STYLE,
+       g_param_spec_enum ("style", "drawing style",
+           "Drawing styles for the space scope display.",
+           GST_TYPE_SPACE_SCOPE_STYLE, STYLE_DOTS,
+           G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
  }
  
  static void
@@@ -115,11 -203,48 +203,52 @@@ render_dots (GstBaseAudioVisualizer * s
    for (i = 0; i < num_samples; i++) {
      x = (guint) (ox + (gfloat) adata[s++] * dx);
      y = (guint) (oy + (gfloat) adata[s++] * dy);
-     off = (y * w) + x;
-     vdata[off] = 0x00FFFFFF;
+     draw_dot (vdata, x, y, w, 0x00FFFFFF);
+   }
+ }
+ static void
+ render_lines (GstBaseAudioVisualizer * scope, guint32 * vdata, gint16 * adata,
+     guint num_samples)
+ {
+   guint i, s, x, y, ox, oy;
+   gfloat dx, dy;
+   guint w = scope->width;
+   guint h = scope->height;
+   gint x2, y2;
+   /* draw lines 1st channel x, 2nd channel y */
+   dx = (w - 1) / 65536.0;
+   ox = (w - 1) / 2;
+   dy = (h - 1) / 65536.0;
+   oy = (h - 1) / 2;
+   s = 0;
+   x2 = (guint) (ox + (gfloat) adata[s++] * dx);
+   y2 = (guint) (oy + (gfloat) adata[s++] * dy);
+   for (i = 1; i < num_samples; i++) {
+     x = (guint) (ox + (gfloat) adata[s++] * dx);
+     y = (guint) (oy + (gfloat) adata[s++] * dy);
+     draw_line_aa (vdata, x2, x, y2, y, w, 0x00FFFFFF);
+     x2 = x;
+     y2 = y;
    }
 -  guint32 *vdata = (guint32 *) GST_BUFFER_DATA (video);
 -  gint16 *adata = (gint16 *) GST_BUFFER_DATA (audio);
+ }
+ static gboolean
+ gst_space_scope_render (GstBaseAudioVisualizer * base, GstBuffer * audio,
+     GstBuffer * video)
+ {
+   GstSpaceScope *scope = GST_SPACE_SCOPE (base);
 -  num_samples = GST_BUFFER_SIZE (audio) / (base->channels * sizeof (gint16));
++  gsize asize;
++  guint32 *vdata =
++      (guint32 *) gst_buffer_map (video, NULL, NULL, GST_MAP_WRITE);
++  gint16 *adata = (gint16 *) gst_buffer_map (audio, &asize, NULL, GST_MAP_READ);
+   guint num_samples;
++  num_samples = asize / (base->channels * sizeof (gint16));
+   scope->process (base, vdata, adata, num_samples);
 +  gst_buffer_unmap (video, vdata, -1);
 +  gst_buffer_unmap (audio, adata, -1);
    return TRUE;
  }
  
Simple merge
Simple merge
@@@ -72,6 -72,7 +72,8 @@@ static GstFlowReturn gst_mpeg4vparse_pa
  static GstFlowReturn gst_mpeg4vparse_pre_push_frame (GstBaseParse * parse,
      GstBaseParseFrame * frame);
  static gboolean gst_mpeg4vparse_set_caps (GstBaseParse * parse, GstCaps * caps);
 -static GstCaps *gst_mpeg4vparse_get_caps (GstBaseParse * parse);
++static GstCaps *gst_mpeg4vparse_get_caps (GstBaseParse * parse,
++    GstCaps * filter);
  
  static void gst_mpeg4vparse_set_property (GObject * object, guint prop_id,
      const GValue * value, GParamSpec * pspec);
@@@ -627,6 -606,39 +630,39 @@@ gst_mpeg4vparse_set_caps (GstBaseParse 
    return TRUE;
  }
  
 -gst_mpeg4vparse_get_caps (GstBaseParse * parse)
+ static GstCaps *
++gst_mpeg4vparse_get_caps (GstBaseParse * parse, GstCaps * filter)
+ {
+   GstCaps *peercaps;
+   GstCaps *res;
+   peercaps = gst_pad_get_allowed_caps (GST_BASE_PARSE_SRC_PAD (parse));
+   if (peercaps) {
+     guint i, n;
+     /* Remove the parsed field */
+     peercaps = gst_caps_make_writable (peercaps);
+     n = gst_caps_get_size (peercaps);
+     for (i = 0; i < n; i++) {
+       GstStructure *s = gst_caps_get_structure (peercaps, i);
+       gst_structure_remove_field (s, "parsed");
+     }
+     res =
+         gst_caps_intersect_full (peercaps,
+         gst_pad_get_pad_template_caps (GST_BASE_PARSE_SRC_PAD (parse)),
+         GST_CAPS_INTERSECT_FIRST);
+     gst_caps_unref (peercaps);
+   } else {
+     res =
+         gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD
+             (parse)));
+   }
+   return res;
+ }
  static gboolean
  plugin_init (GstPlugin * plugin)
  {
@@@ -54,6 -54,7 +54,8 @@@ static gboolean gst_dirac_parse_start (
  static gboolean gst_dirac_parse_stop (GstBaseParse * parse);
  static gboolean gst_dirac_parse_set_sink_caps (GstBaseParse * parse,
      GstCaps * caps);
 -static GstCaps *gst_dirac_parse_get_sink_caps (GstBaseParse * parse);
++static GstCaps *gst_dirac_parse_get_sink_caps (GstBaseParse * parse,
++    GstCaps * filter);
  static gboolean gst_dirac_parse_check_valid_frame (GstBaseParse * parse,
      GstBaseParseFrame * frame, guint * framesize, gint * skipsize);
  static GstFlowReturn gst_dirac_parse_parse_frame (GstBaseParse * parse,
@@@ -377,3 -381,35 +381,35 @@@ gst_dirac_parse_pre_push_frame (GstBase
  
    return GST_FLOW_OK;
  }
 -gst_dirac_parse_get_sink_caps (GstBaseParse * parse)
+ static GstCaps *
++gst_dirac_parse_get_sink_caps (GstBaseParse * parse, GstCaps * filter)
+ {
+   GstCaps *peercaps;
+   GstCaps *res;
+   peercaps = gst_pad_get_allowed_caps (GST_BASE_PARSE_SRC_PAD (parse));
+   if (peercaps) {
+     guint i, n;
+     /* Remove the parsed field */
+     peercaps = gst_caps_make_writable (peercaps);
+     n = gst_caps_get_size (peercaps);
+     for (i = 0; i < n; i++) {
+       GstStructure *s = gst_caps_get_structure (peercaps, i);
+       gst_structure_remove_field (s, "parsed");
+     }
+     res =
+         gst_caps_intersect_full (peercaps,
+         gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse)),
+         GST_CAPS_INTERSECT_FIRST);
+     gst_caps_unref (peercaps);
+   } else {
+     res =
+         gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD
+             (parse)));
+   }
+   return res;
+ }
@@@ -58,14 -58,12 +58,16 @@@ static gboolean gst_h263_parse_check_va
      GstBaseParseFrame * frame, guint * framesize, gint * skipsize);
  static GstFlowReturn gst_h263_parse_parse_frame (GstBaseParse * parse,
      GstBaseParseFrame * frame);
 -static GstCaps *gst_h263_parse_get_sink_caps (GstBaseParse * parse);
++static GstCaps *gst_h263_parse_get_sink_caps (GstBaseParse * parse,
++    GstCaps * filter);
  
  static void
 -gst_h263_parse_base_init (gpointer g_class)
 +gst_h263_parse_class_init (GstH263ParseClass * klass)
  {
 -  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
 +  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
 +  GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
 +
 +  GST_DEBUG_CATEGORY_INIT (h263_parse_debug, "h263parse", 0, "h263 parser");
  
    gst_element_class_add_pad_template (gstelement_class,
        gst_static_pad_template_get (&srctemplate));
@@@ -357,3 -361,35 +360,35 @@@ out
  
    return res;
  }
 -gst_h263_parse_get_sink_caps (GstBaseParse * parse)
+ static GstCaps *
++gst_h263_parse_get_sink_caps (GstBaseParse * parse, GstCaps * filter)
+ {
+   GstCaps *peercaps;
+   GstCaps *res;
+   peercaps = gst_pad_get_allowed_caps (GST_BASE_PARSE_SRC_PAD (parse));
+   if (peercaps) {
+     guint i, n;
+     /* Remove parsed field */
+     peercaps = gst_caps_make_writable (peercaps);
+     n = gst_caps_get_size (peercaps);
+     for (i = 0; i < n; i++) {
+       GstStructure *s = gst_caps_get_structure (peercaps, i);
+       gst_structure_remove_field (s, "parsed");
+     }
+     res =
+         gst_caps_intersect_full (peercaps,
+         gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse)),
+         GST_CAPS_INTERSECT_FIRST);
+     gst_caps_unref (peercaps);
+   } else {
+     res =
+         gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD
+             (parse)));
+   }
+   return res;
+ }
@@@ -71,6 -71,7 +71,8 @@@ static gboolean gst_mpegv_parse_check_v
  static GstFlowReturn gst_mpegv_parse_parse_frame (GstBaseParse * parse,
      GstBaseParseFrame * frame);
  static gboolean gst_mpegv_parse_set_caps (GstBaseParse * parse, GstCaps * caps);
 -static GstCaps *gst_mpegv_parse_get_caps (GstBaseParse * parse);
++static GstCaps *gst_mpegv_parse_get_caps (GstBaseParse * parse,
++    GstCaps * filter);
  static GstFlowReturn gst_mpegv_parse_pre_push_frame (GstBaseParse * parse,
      GstBaseParseFrame * frame);
  
@@@ -776,3 -764,35 +779,35 @@@ gst_mpegv_parse_set_caps (GstBaseParse 
    /* let's not interfere and accept regardless of config parsing success */
    return TRUE;
  }
 -gst_mpegv_parse_get_caps (GstBaseParse * parse)
+ static GstCaps *
++gst_mpegv_parse_get_caps (GstBaseParse * parse, GstCaps * filter)
+ {
+   GstCaps *peercaps;
+   GstCaps *res;
+   peercaps = gst_pad_get_allowed_caps (GST_BASE_PARSE_SRC_PAD (parse));
+   if (peercaps) {
+     guint i, n;
+     /* Remove the parsed field */
+     peercaps = gst_caps_make_writable (peercaps);
+     n = gst_caps_get_size (peercaps);
+     for (i = 0; i < n; i++) {
+       GstStructure *s = gst_caps_get_structure (peercaps, i);
+       gst_structure_remove_field (s, "parsed");
+     }
+     res =
+         gst_caps_intersect_full (peercaps,
+         gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse)),
+         GST_CAPS_INTERSECT_FIRST);
+     gst_caps_unref (peercaps);
+   } else {
+     res =
+         gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD
+             (parse)));
+   }
+   return res;
+ }
diff --cc sys/Makefile.am
@@@ -95,12 -95,13 +95,13 @@@ els
  ACM_DIR=
  endif
  
 -if USE_VDPAU
 -VDPAU_DIR=vdpau
 -else
 -VDPAU_DIR=
 -endif
 +#if USE_VDPAU
 +#VDPAU_DIR=vdpau
 +#else
 +#VDPAU_DIR=
 +#endif
  
  if USE_SHM
  SHM_DIR=shm
  else