diff --git a/gst/qtdemux/Makefile.am b/gst/qtdemux/Makefile.am
index 74c683c..ecfa0da 100644
--- a/gst/qtdemux/Makefile.am
+++ b/gst/qtdemux/Makefile.am
@@ -8,6 +8,7 @@
     -lgstaudio-@GST_MAJORMINOR@ \
     -lgstrtp-@GST_MAJORMINOR@ \
     -lgsttag-@GST_MAJORMINOR@ \
+    -lgstpbutils-@GST_MAJORMINOR@ \
     $(GST_BASE_LIBS) $(GST_LIBS) $(ZLIB_LIBS)
 libgstqtdemux_la_LDFLAGS = ${GST_PLUGIN_LDFLAGS} 
 libgstqtdemux_la_SOURCES = quicktime.c gstrtpxqtdepay.c \
diff --git a/gst/qtdemux/qtdemux.c b/gst/qtdemux/qtdemux.c
index ffac66a..bd2e089 100644
--- a/gst/qtdemux/qtdemux.c
+++ b/gst/qtdemux/qtdemux.c
@@ -63,6 +63,8 @@
 #include "gst/riff/riff-media.h"
 #include "gst/riff/riff-read.h"
 
+#include <gst/pbutils/pbutils.h>
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -4236,7 +4238,7 @@
   /* sync sample atom */
   stream->stps_present = FALSE;
   if ((stream->stss_present =
-          !!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
+          ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
               &stream->stss) ? TRUE : FALSE) == TRUE) {
     /* copy atom data into a new buffer for later use */
     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
@@ -4254,7 +4256,7 @@
 
     /* partial sync sample atom */
     if ((stream->stps_present =
-            !!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
+            ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
                 &stream->stps) ? TRUE : FALSE) == TRUE) {
       /* copy atom data into a new buffer for later use */
       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
@@ -4378,7 +4380,7 @@
 
   /* composition time-to-sample */
   if ((stream->ctts_present =
-          !!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
+          ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
               &stream->ctts) ? TRUE : FALSE) == TRUE) {
     /* copy atom data into a new buffer for later use */
     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
@@ -7495,20 +7497,23 @@
        * wrong. */
       /* Only do so for basic setup without HE-AAC extension */
       if (data_ptr && data_len == 2) {
-        guint channels, rateindex;
-        int rates[] = { 96000, 88200, 64000, 48000, 44100, 32000,
-          24000, 22050, 16000, 12000, 11025, 8000
-        };
+        guint channels, rateindex, rate;
 
+        /* FIXME: add gst_codec_utils_aac_get_{channels|sample_rate}()? */
         channels = (data_ptr[1] & 0x7f) >> 3;
-        if (channels <= 7) {
+        if (channels > 0 && channels < 7) {
           stream->n_channels = channels;
+        } else if (channels == 7) {
+          stream->n_channels = 8;
         }
 
         rateindex = ((data_ptr[0] & 0x7) << 1) | ((data_ptr[1] & 0x80) >> 7);
-        if (rateindex < sizeof (rates) / sizeof (*rates)) {
-          stream->rate = rates[rateindex];
-        }
+        rate = gst_codec_utils_aac_get_sample_rate_from_index (rateindex);
+        if (rate > 0)
+          stream->rate = rate;
+
+        gst_codec_utils_aac_caps_set_level_and_profile (stream->caps,
+            data_ptr, data_len);
       }
       break;
     case 0x60:                 /* MPEG-2, various profiles */
diff --git a/gst/rtp/Makefile.am b/gst/rtp/Makefile.am
index b6aefe6..5a300b3 100644
--- a/gst/rtp/Makefile.am
+++ b/gst/rtp/Makefile.am
@@ -23,6 +23,8 @@
 	gstrtppcmudepay.c \
 	gstrtppcmupay.c \
 	gstrtppcmapay.c \
+	gstrtpg722depay.c \
+	gstrtpg722pay.c \
 	gstrtpg723depay.c \
 	gstrtpg723pay.c \
 	gstrtpg726pay.c \
@@ -106,6 +108,8 @@
 		 gstrtppcmudepay.h	\
 		 gstrtppcmupay.h 	\
 		 gstrtppcmapay.h 	\
+	         gstrtpg722depay.h      \
+	         gstrtpg722pay.h        \
 	         gstrtpg723depay.h      \
 	         gstrtpg723pay.h        \
 	         gstrtpg726depay.h      \
diff --git a/gst/rtp/gstrtp.c b/gst/rtp/gstrtp.c
index 852906e..339ff97 100644
--- a/gst/rtp/gstrtp.c
+++ b/gst/rtp/gstrtp.c
@@ -35,6 +35,8 @@
 #include "gstrtppcmapay.h"
 #include "gstrtppcmadepay.h"
 #include "gstrtppcmudepay.h"
+#include "gstrtpg722depay.h"
+#include "gstrtpg722pay.h"
 #include "gstrtpg723depay.h"
 #include "gstrtpg723pay.h"
 #include "gstrtpg726depay.h"
@@ -117,6 +119,12 @@
     return FALSE;
 
   if (!gst_rtp_ilbc_depay_plugin_init (plugin))
+    return FALSE;
+
+  if (!gst_rtp_g722_depay_plugin_init (plugin))
+    return FALSE;
+
+  if (!gst_rtp_g722_pay_plugin_init (plugin))
     return FALSE;
 
   if (!gst_rtp_g723_depay_plugin_init (plugin))
diff --git a/gst/rtp/gstrtpg722depay.c b/gst/rtp/gstrtpg722depay.c
new file mode 100644
index 0000000..ff479c1
--- /dev/null
+++ b/gst/rtp/gstrtpg722depay.c
@@ -0,0 +1,260 @@
+/* GStreamer
+ * Copyright (C) <2007> Wim Taymans <wim.taymans@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <gst/audio/audio.h>
+#include <gst/audio/multichannel.h>
+
+#include "gstrtpg722depay.h"
+#include "gstrtpchannels.h"
+
+GST_DEBUG_CATEGORY_STATIC (rtpg722depay_debug);
+#define GST_CAT_DEFAULT (rtpg722depay_debug)
+
+static GstStaticPadTemplate gst_rtp_g722_depay_src_template =
+GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("audio/G722, "
+        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]")
+    );
+
+static GstStaticPadTemplate gst_rtp_g722_depay_sink_template =
+    GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("application/x-rtp, "
+        "media = (string) \"audio\", "
+        "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
+        "clock-rate = (int) 8000, "
+        /* "channels = (int) [1, MAX]"  */
+        /* "channel-order = (string) ANY" */
+        "encoding-name = (string) \"G722\";"
+        "application/x-rtp, "
+        "media = (string) \"audio\", "
+        "payload = (int) " GST_RTP_PAYLOAD_G722_STRING ", "
+        "clock-rate = (int) [ 1, MAX ]"
+        /* "channels = (int) [1, MAX]" */
+        /* "emphasis = (string) ANY" */
+        /* "channel-order = (string) ANY" */
+    )
+    );
+
+GST_BOILERPLATE (GstRtpG722Depay, gst_rtp_g722_depay, GstBaseRTPDepayload,
+    GST_TYPE_BASE_RTP_DEPAYLOAD);
+
+static gboolean gst_rtp_g722_depay_setcaps (GstBaseRTPDepayload * depayload,
+    GstCaps * caps);
+static GstBuffer *gst_rtp_g722_depay_process (GstBaseRTPDepayload * depayload,
+    GstBuffer * buf);
+
+static void
+gst_rtp_g722_depay_base_init (gpointer klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_rtp_g722_depay_src_template));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_rtp_g722_depay_sink_template));
+
+  gst_element_class_set_details_simple (element_class, "RTP audio depayloader",
+      "Codec/Depayloader/Network",
+      "Extracts G722 audio from RTP packets",
+      "Wim Taymans <wim.taymans@gmail.com>");
+}
+
+static void
+gst_rtp_g722_depay_class_init (GstRtpG722DepayClass * klass)
+{
+  GstBaseRTPDepayloadClass *gstbasertpdepayload_class;
+
+  gstbasertpdepayload_class = (GstBaseRTPDepayloadClass *) klass;
+
+  gstbasertpdepayload_class->set_caps = gst_rtp_g722_depay_setcaps;
+  gstbasertpdepayload_class->process = gst_rtp_g722_depay_process;
+
+  GST_DEBUG_CATEGORY_INIT (rtpg722depay_debug, "rtpg722depay", 0,
+      "G722 RTP Depayloader");
+}
+
+static void
+gst_rtp_g722_depay_init (GstRtpG722Depay * rtpg722depay,
+    GstRtpG722DepayClass * klass)
+{
+  /* needed because of GST_BOILERPLATE */
+}
+
+static gint
+gst_rtp_g722_depay_parse_int (GstStructure * structure, const gchar * field,
+    gint def)
+{
+  const gchar *str;
+  gint res;
+
+  if ((str = gst_structure_get_string (structure, field)))
+    return atoi (str);
+
+  if (gst_structure_get_int (structure, field, &res))
+    return res;
+
+  return def;
+}
+
+static gboolean
+gst_rtp_g722_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps)
+{
+  GstStructure *structure;
+  GstRtpG722Depay *rtpg722depay;
+  gint clock_rate, payload, samplerate;
+  gint channels;
+  GstCaps *srccaps;
+  gboolean res;
+  const gchar *channel_order;
+  const GstRTPChannelOrder *order;
+
+  rtpg722depay = GST_RTP_G722_DEPAY (depayload);
+
+  structure = gst_caps_get_structure (caps, 0);
+
+  payload = 96;
+  gst_structure_get_int (structure, "payload", &payload);
+  switch (payload) {
+    case GST_RTP_PAYLOAD_G722:
+      channels = 1;
+      clock_rate = 8000;
+      samplerate = 16000;
+      break;
+    default:
+      /* no fixed mapping, we need clock-rate */
+      channels = 0;
+      clock_rate = 0;
+      samplerate = 0;
+      break;
+  }
+
+  /* caps can overwrite defaults */
+  clock_rate =
+      gst_rtp_g722_depay_parse_int (structure, "clock-rate", clock_rate);
+  if (clock_rate == 0)
+    goto no_clockrate;
+
+  if (clock_rate == 8000)
+    samplerate = 16000;
+
+  if (samplerate == 0)
+    samplerate = clock_rate;
+
+  channels =
+      gst_rtp_g722_depay_parse_int (structure, "encoding-params", channels);
+  if (channels == 0) {
+    channels = gst_rtp_g722_depay_parse_int (structure, "channels", channels);
+    if (channels == 0) {
+      /* channels defaults to 1 otherwise */
+      channels = 1;
+    }
+  }
+
+  depayload->clock_rate = clock_rate;
+  rtpg722depay->rate = samplerate;
+  rtpg722depay->channels = channels;
+
+  srccaps = gst_caps_new_simple ("audio/G722",
+      "rate", G_TYPE_INT, samplerate, "channels", G_TYPE_INT, channels, NULL);
+
+  /* add channel positions */
+  channel_order = gst_structure_get_string (structure, "channel-order");
+
+  order = gst_rtp_channels_get_by_order (channels, channel_order);
+  if (order) {
+    gst_audio_set_channel_positions (gst_caps_get_structure (srccaps, 0),
+        order->pos);
+  } else {
+    GstAudioChannelPosition *pos;
+
+    GST_ELEMENT_WARNING (rtpg722depay, STREAM, DECODE,
+        (NULL), ("Unknown channel order '%s' for %d channels",
+            GST_STR_NULL (channel_order), channels));
+    /* create default NONE layout */
+    pos = gst_rtp_channels_create_default (channels);
+    gst_audio_set_channel_positions (gst_caps_get_structure (srccaps, 0), pos);
+    g_free (pos);
+  }
+
+  res = gst_pad_set_caps (depayload->srcpad, srccaps);
+  gst_caps_unref (srccaps);
+
+  return res;
+
+  /* ERRORS */
+no_clockrate:
+  {
+    GST_ERROR_OBJECT (depayload, "no clock-rate specified");
+    return FALSE;
+  }
+}
+
+static GstBuffer *
+gst_rtp_g722_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
+{
+  GstRtpG722Depay *rtpg722depay;
+  GstBuffer *outbuf;
+  gint payload_len;
+  gboolean marker;
+
+  rtpg722depay = GST_RTP_G722_DEPAY (depayload);
+
+  payload_len = gst_rtp_buffer_get_payload_len (buf);
+
+  if (payload_len <= 0)
+    goto empty_packet;
+
+  GST_DEBUG_OBJECT (rtpg722depay, "got payload of %d bytes", payload_len);
+
+  outbuf = gst_rtp_buffer_get_payload_buffer (buf);
+  marker = gst_rtp_buffer_get_marker (buf);
+
+  if (marker) {
+    /* mark talk spurt with DISCONT */
+    GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
+  }
+
+  return outbuf;
+
+  /* ERRORS */
+empty_packet:
+  {
+    GST_ELEMENT_WARNING (rtpg722depay, STREAM, DECODE,
+        ("Empty Payload."), (NULL));
+    return NULL;
+  }
+}
+
+gboolean
+gst_rtp_g722_depay_plugin_init (GstPlugin * plugin)
+{
+  return gst_element_register (plugin, "rtpg722depay",
+      GST_RANK_MARGINAL, GST_TYPE_RTP_G722_DEPAY);
+}
diff --git a/gst/rtp/gstrtpg722depay.h b/gst/rtp/gstrtpg722depay.h
new file mode 100644
index 0000000..2f6b980
--- /dev/null
+++ b/gst/rtp/gstrtpg722depay.h
@@ -0,0 +1,64 @@
+/* GStreamer
+ * Copyright (C) <2010> Wim Taymans <wim.taymans@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_RTP_G722_DEPAY_H__
+#define __GST_RTP_G722_DEPAY_H__
+
+#include <gst/gst.h>
+#include <gst/rtp/gstbasertpdepayload.h>
+
+G_BEGIN_DECLS
+
+/* Standard macros for defining types for this element.  */
+#define GST_TYPE_RTP_G722_DEPAY \
+  (gst_rtp_g722_depay_get_type())
+#define GST_RTP_G722_DEPAY(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_G722_DEPAY,GstRtpG722Depay))
+#define GST_RTP_G722_DEPAY_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_G722_DEPAY,GstRtpG722DepayClass))
+#define GST_IS_RTP_G722_DEPAY(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_G722_DEPAY))
+#define GST_IS_RTP_G722_DEPAY_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_G722_DEPAY))
+
+typedef struct _GstRtpG722Depay GstRtpG722Depay;
+typedef struct _GstRtpG722DepayClass GstRtpG722DepayClass;
+
+/* Definition of structure storing data for this element. */
+struct _GstRtpG722Depay
+{
+  GstBaseRTPDepayload depayload;
+
+  guint rate;
+  guint channels;
+};
+
+/* Standard definition defining a class for this element. */
+struct _GstRtpG722DepayClass
+{
+  GstBaseRTPDepayloadClass parent_class;
+};
+
+GType gst_rtp_g722_depay_get_type (void);
+
+gboolean gst_rtp_g722_depay_plugin_init (GstPlugin * plugin);
+
+G_END_DECLS
+
+#endif /* __GST_RTP_G722_DEPAY_H__ */
diff --git a/gst/rtp/gstrtpg722pay.c b/gst/rtp/gstrtpg722pay.c
new file mode 100644
index 0000000..9788fa5
--- /dev/null
+++ b/gst/rtp/gstrtpg722pay.c
@@ -0,0 +1,209 @@
+/* GStreamer
+ * Copyright (C) <2010> Wim Taymans <wim.taymans@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include <string.h>
+
+#include <gst/audio/audio.h>
+#include <gst/audio/multichannel.h>
+#include <gst/rtp/gstrtpbuffer.h>
+
+#include "gstrtpg722pay.h"
+#include "gstrtpchannels.h"
+
+GST_DEBUG_CATEGORY_STATIC (rtpg722pay_debug);
+#define GST_CAT_DEFAULT (rtpg722pay_debug)
+
+static GstStaticPadTemplate gst_rtp_g722_pay_sink_template =
+GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("audio/G722, " "rate = (int) 16000, " "channels = (int) 1")
+    );
+
+static GstStaticPadTemplate gst_rtp_g722_pay_src_template =
+GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("application/x-rtp, "
+        "media = (string) \"audio\", "
+        "encoding-name = (string) \"G722\", "
+        "payload = (int) " GST_RTP_PAYLOAD_G722_STRING ", "
+        "clock-rate = (int) 8000")
+    );
+
+static gboolean gst_rtp_g722_pay_setcaps (GstBaseRTPPayload * basepayload,
+    GstCaps * caps);
+static GstCaps *gst_rtp_g722_pay_getcaps (GstBaseRTPPayload * rtppayload,
+    GstPad * pad);
+
+GST_BOILERPLATE (GstRtpG722Pay, gst_rtp_g722_pay, GstBaseRTPAudioPayload,
+    GST_TYPE_BASE_RTP_AUDIO_PAYLOAD);
+
+static void
+gst_rtp_g722_pay_base_init (gpointer klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_rtp_g722_pay_src_template));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_rtp_g722_pay_sink_template));
+
+  gst_element_class_set_details_simple (element_class, "RTP audio payloader",
+      "Codec/Payloader/Network",
+      "Payload-encode Raw audio into RTP packets (RFC 3551)",
+      "Wim Taymans <wim.taymans@gmail.com>");
+}
+
+static void
+gst_rtp_g722_pay_class_init (GstRtpG722PayClass * klass)
+{
+  GstBaseRTPPayloadClass *gstbasertppayload_class;
+
+  gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass;
+
+  gstbasertppayload_class->set_caps = gst_rtp_g722_pay_setcaps;
+  gstbasertppayload_class->get_caps = gst_rtp_g722_pay_getcaps;
+
+  GST_DEBUG_CATEGORY_INIT (rtpg722pay_debug, "rtpg722pay", 0,
+      "G722 RTP Payloader");
+}
+
+static void
+gst_rtp_g722_pay_init (GstRtpG722Pay * rtpg722pay, GstRtpG722PayClass * klass)
+{
+  GstBaseRTPAudioPayload *basertpaudiopayload;
+
+  basertpaudiopayload = GST_BASE_RTP_AUDIO_PAYLOAD (rtpg722pay);
+
+  /* tell basertpaudiopayload that this is a sample based codec */
+  gst_base_rtp_audio_payload_set_sample_based (basertpaudiopayload);
+}
+
+static gboolean
+gst_rtp_g722_pay_setcaps (GstBaseRTPPayload * basepayload, GstCaps * caps)
+{
+  GstRtpG722Pay *rtpg722pay;
+  GstStructure *structure;
+  gint rate, channels, clock_rate;
+  gboolean res;
+  gchar *params;
+  GstAudioChannelPosition *pos;
+  const GstRTPChannelOrder *order;
+  GstBaseRTPAudioPayload *basertpaudiopayload;
+
+  basertpaudiopayload = GST_BASE_RTP_AUDIO_PAYLOAD (basepayload);
+  rtpg722pay = GST_RTP_G722_PAY (basepayload);
+
+  structure = gst_caps_get_structure (caps, 0);
+
+  /* first parse input caps */
+  if (!gst_structure_get_int (structure, "rate", &rate))
+    goto no_rate;
+
+  if (!gst_structure_get_int (structure, "channels", &channels))
+    goto no_channels;
+
+  /* get the channel order */
+  pos = gst_audio_get_channel_positions (structure);
+  if (pos)
+    order = gst_rtp_channels_get_by_pos (channels, pos);
+  else
+    order = NULL;
+
+  if (rate == 16000)
+    clock_rate = 8000;
+
+  gst_basertppayload_set_options (basepayload, "audio", TRUE, "G722",
+      clock_rate);
+  params = g_strdup_printf ("%d", channels);
+
+  if (!order && channels > 2) {
+    GST_ELEMENT_WARNING (rtpg722pay, STREAM, DECODE,
+        (NULL), ("Unknown channel order for %d channels", channels));
+  }
+
+  if (order && order->name) {
+    res = gst_basertppayload_set_outcaps (basepayload,
+        "encoding-params", G_TYPE_STRING, params, "channels", G_TYPE_INT,
+        channels, "channel-order", G_TYPE_STRING, order->name, NULL);
+  } else {
+    res = gst_basertppayload_set_outcaps (basepayload,
+        "encoding-params", G_TYPE_STRING, params, "channels", G_TYPE_INT,
+        channels, NULL);
+  }
+
+  g_free (params);
+  g_free (pos);
+
+  rtpg722pay->rate = rate;
+  rtpg722pay->channels = channels;
+
+  /* octet-per-sample is 1 * channels for G722 */
+  gst_base_rtp_audio_payload_set_samplebits_options (basertpaudiopayload,
+      4 * rtpg722pay->channels);
+
+  return res;
+
+  /* ERRORS */
+no_rate:
+  {
+    GST_DEBUG_OBJECT (rtpg722pay, "no rate given");
+    return FALSE;
+  }
+no_channels:
+  {
+    GST_DEBUG_OBJECT (rtpg722pay, "no channels given");
+    return FALSE;
+  }
+}
+
+static GstCaps *
+gst_rtp_g722_pay_getcaps (GstBaseRTPPayload * rtppayload, GstPad * pad)
+{
+  GstCaps *otherpadcaps;
+  GstCaps *caps;
+
+  otherpadcaps = gst_pad_get_allowed_caps (rtppayload->srcpad);
+  caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
+
+  if (otherpadcaps) {
+    if (!gst_caps_is_empty (otherpadcaps)) {
+      GstStructure *structure;
+
+      structure = gst_caps_get_structure (otherpadcaps, 0);
+
+      gst_caps_set_simple (caps, "channels", G_TYPE_INT, 1, NULL);
+      gst_caps_set_simple (caps, "rate", G_TYPE_INT, 16000, NULL);
+    }
+    gst_caps_unref (otherpadcaps);
+  }
+  return caps;
+}
+
+gboolean
+gst_rtp_g722_pay_plugin_init (GstPlugin * plugin)
+{
+  return gst_element_register (plugin, "rtpg722pay",
+      GST_RANK_NONE, GST_TYPE_RTP_G722_PAY);
+}
diff --git a/gst/rtp/gstrtpg722pay.h b/gst/rtp/gstrtpg722pay.h
new file mode 100644
index 0000000..6712204
--- /dev/null
+++ b/gst/rtp/gstrtpg722pay.h
@@ -0,0 +1,61 @@
+/* GStreamer
+ * Copyright (C) <2010> Wim Taymans <wim.taymans@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_RTP_G722_PAY_H__
+#define __GST_RTP_G722_PAY_H__
+
+#include <gst/gst.h>
+#include <gst/rtp/gstbasertpaudiopayload.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_RTP_G722_PAY \
+  (gst_rtp_g722_pay_get_type())
+#define GST_RTP_G722_PAY(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_G722_PAY,GstRtpG722Pay))
+#define GST_RTP_G722_PAY_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_G722_PAY,GstRtpG722PayClass))
+#define GST_IS_RTP_G722_PAY(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_G722_PAY))
+#define GST_IS_RTP_G722_PAY_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_G722_PAY))
+
+typedef struct _GstRtpG722Pay GstRtpG722Pay;
+typedef struct _GstRtpG722PayClass GstRtpG722PayClass;
+
+struct _GstRtpG722Pay
+{
+  GstBaseRTPAudioPayload payload;
+
+  gint rate;
+  gint channels;
+};
+
+struct _GstRtpG722PayClass
+{
+  GstBaseRTPAudioPayloadClass parent_class;
+};
+
+GType gst_rtp_g722_pay_get_type (void);
+
+gboolean gst_rtp_g722_pay_plugin_init (GstPlugin * plugin);
+
+G_END_DECLS
+
+#endif /* __GST_RTP_G722_PAY_H__ */
diff --git a/gst/rtpmanager/rtpjitterbuffer.c b/gst/rtpmanager/rtpjitterbuffer.c
index b0107a8..d3e0e67 100644
--- a/gst/rtpmanager/rtpjitterbuffer.c
+++ b/gst/rtpmanager/rtpjitterbuffer.c
@@ -274,8 +274,12 @@
 }
 
 /* For the clock skew we use a windowed low point averaging algorithm as can be
- * found in http://www.grame.fr/Ressources/pub/TR-050601.pdf. The idea is that
- * the jitter is composed of:
+ * found in
+ * Fober, Orlarey and Letz, 2005, "Real Time Clock Skew Estimation over Network Delays"
+ * http://www.grame.fr/Ressources/pub/TR-050601.pdf
+ * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.102.1546
+ *
+ * The idea is that the jitter is  composed of:
  *
  *  J = N + n
  *
diff --git a/gst/rtsp/gstrtspsrc.c b/gst/rtsp/gstrtspsrc.c
index 52ec272..2700849 100644
--- a/gst/rtsp/gstrtspsrc.c
+++ b/gst/rtsp/gstrtspsrc.c
@@ -454,7 +454,6 @@
   gst_rtsp_ext_list_init ();
 }
 
-
 static void
 gst_rtspsrc_init (GstRTSPSrc * src, GstRTSPSrcClass * g_class)
 {
@@ -1018,7 +1017,10 @@
   GST_DEBUG_OBJECT (src, " caps: %" GST_PTR_FORMAT, stream->caps);
   GST_DEBUG_OBJECT (src, " control: %s", GST_STR_NULL (control_url));
 
-  if (control_url != NULL) {
+  if (src->is_kasenna) {
+    stream->control_url = g_strdup (src->conninfo.url_str);
+    stream->conninfo.location = g_strdup (src->conninfo.url_str);
+  } else if (control_url != NULL) {
     stream->control_url = g_strdup (control_url);
     /* Build a fully qualified url using the content_base if any or by prefixing
      * the original request.
@@ -5233,7 +5235,104 @@
   {
     GST_ERROR_OBJECT (src, "setup failed");
     return FALSE;
+  }
+}
+
+#define MAX_LEN 1024 * 16
+
+static GstSDPResult
+gst_rtspsrc_rtspmh_to_sdp (const guint8 * data, guint size,
+    GstSDPMessage * msg, GstRTSPSrc * src)
+{
+  GstSDPResult res;
+  gchar *sdp_buffer;
+  gchar *st;
+  gchar *current_word;
+  gchar *current_pos;
+
+  gint32 video_pid;
+  gint64 duration;
+
+  g_return_val_if_fail (msg != NULL, GST_SDP_EINVAL);
+  g_return_val_if_fail (data != NULL, GST_SDP_EINVAL);
+  g_return_val_if_fail (size != 0, GST_SDP_EINVAL);
+  g_return_val_if_fail (src != NULL, GST_SDP_EINVAL);
+  g_return_val_if_fail (g_str_has_prefix ((const gchar *) data,
+          (const gchar *) "<MediaDescription>"), GST_SDP_EINVAL);
+
+  if ((sdp_buffer = g_malloc (MAX_LEN)) == NULL)
+    return GST_SDP_EINVAL;
+
+  if ((current_word = g_malloc (MAX_LEN)) == NULL) {
+    g_free (sdp_buffer);
+    return GST_SDP_EINVAL;
+  }
+
+  g_snprintf (sdp_buffer, MAX_LEN,
+      "v=0\n"
+      "o=NoSpacesAllowed 1 1 IN IP4 %s\n"
+      "s=%s\n"
+      "c=IN IP4 %s\n"
+      "t=0 0\n"
+      "a=control:*\n",
+      gst_rtsp_connection_get_ip (src->conninfo.connection),
+      GST_STR_NULL (src->conninfo.url_str),
+      gst_rtsp_connection_get_ip (src->conninfo.connection)
+      );
+
+  current_pos = (gchar *) data;
+
+  while (g_strcmp0 (current_word, "</MediaDescription>") != 0) {
+    sscanf (current_pos, "%s", current_word);
+
+    if (g_strcmp0 (current_word, "VideoPid") == 0) {
+      //gchar *endptr = NULL;
+      current_pos += strlen (current_word) + 1;
+      sscanf (current_pos, "%s", current_word);
+      current_pos += strlen (current_word) + 1;
+      sscanf (current_pos, "%" G_GINT32_FORMAT, &video_pid);
+      current_pos += 3;
+      GST_DEBUG ("video_pid=%" G_GINT32_FORMAT, video_pid);
+    }
+
+    if (g_strcmp0 (current_word, "Duration") == 0) {
+      //gchar *endptr = NULL;
+      current_pos += strlen (current_word) + 1;
+      sscanf (current_pos, "%s", current_word);
+      current_pos += strlen (current_word) + 1;
+      sscanf (current_pos, "%" G_GINT64_FORMAT, &duration);
+      current_pos += 3;
+      GST_DEBUG ("duration=%" G_GINT64_FORMAT, duration);
+    }
+
+    /*if (strcmp(current_word, "TypeSpecificData") == 0) {
+       current_pos += strlen(current_word) + 1;
+       sscanf(current_pos, "%s", current_word);
+       current_pos += strlen(current_word) + 1;
+       sscanf(current_pos, "%s", fKasennaContentType);
+       currentPos += 3;
+       } */
+
+    //TODO: добыть TrickSpeed
+    current_pos += strlen (current_word) + 1;
   }
+
+  st = g_strdup_printf ("a=range:npt=0-%d\n"
+      "m=video 1554 RAW/RAW/UDP 33\n"
+      "a=control:trackID=%d\n", (int) (duration / 1000000L)
+      , video_pid);
+  g_strlcat (sdp_buffer, st, MAX_LEN);
+  g_free (st);
+
+  if (src->debug)
+    g_print ("constructed sdp:\n-----\n%s\n-------\n", sdp_buffer);
+
+  res =
+      gst_sdp_message_parse_buffer ((const guint8 *) sdp_buffer,
+      strlen (sdp_buffer), msg);
+
+  g_free (sdp_buffer);
+  return res;
 }
 
 static gboolean
@@ -5283,9 +5382,8 @@
   if (res < 0)
     goto create_request_failed;
 
-  /* we only accept SDP for now */
   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_ACCEPT,
-      "application/sdp");
+      "application/x-rtsp-mh,application/sdp");
 
   /* send DESCRIBE */
   GST_DEBUG_OBJECT (src, "send describe...");
@@ -5316,7 +5414,8 @@
   /* could not be set but since the request returned OK, we assume it
    * was SDP, else check it. */
   if (respcont) {
-    if (!g_ascii_strcasecmp (respcont, "application/sdp") == 0)
+    if ((g_ascii_strcasecmp (respcont, "application/sdp") != 0) &&
+        (g_ascii_strcasecmp (respcont, "application/x-rtsp-mh") != 0))
       goto wrong_content_type;
   }
 
@@ -5324,10 +5423,22 @@
   gst_rtsp_message_get_body (&response, &data, &size);
   if (data == NULL || size == 0)
     goto no_describe;
+
+  src->is_kasenna = FALSE;
 
   GST_DEBUG_OBJECT (src, "parse SDP...");
   gst_sdp_message_new (sdp);
-  gst_sdp_message_parse_buffer (data, size, *sdp);
+
+  if (g_ascii_strcasecmp (respcont, "application/sdp") == 0) {
+    gst_sdp_message_parse_buffer (data, size, *sdp);
+  } else {
+    if (gst_rtspsrc_rtspmh_to_sdp (data, size, *sdp, src) == GST_SDP_OK) {
+      src->is_kasenna = TRUE;
+    } else {
+      gst_sdp_message_free (*sdp);
+      goto no_describe;
+    }
+  }
 
   /* clean up any messages */
   gst_rtsp_message_unset (&request);
diff --git a/gst/rtsp/gstrtspsrc.h b/gst/rtsp/gstrtspsrc.h
index a15ec88..9b248e3 100644
--- a/gst/rtsp/gstrtspsrc.h
+++ b/gst/rtsp/gstrtspsrc.h
@@ -47,14 +47,11 @@
 #include <gst/gst.h>
 
 G_BEGIN_DECLS
-
 #include <gst/rtsp/gstrtspconnection.h>
 #include <gst/rtsp/gstrtspmessage.h>
 #include <gst/rtsp/gstrtspurl.h>
 #include <gst/rtsp/gstrtsprange.h>
-
 #include "gstrtspext.h"
-
 #define GST_TYPE_RTSPSRC \
   (gst_rtspsrc_get_type())
 #define GST_RTSPSRC(obj) \
@@ -67,7 +64,6 @@
   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTSPSRC))
 #define GST_RTSPSRC_CAST(obj) \
   ((GstRTSPSrc *)(obj))
-
 typedef struct _GstRTSPSrc GstRTSPSrc;
 typedef struct _GstRTSPSrcClass GstRTSPSrcClass;
 
@@ -85,67 +81,69 @@
 
 typedef struct _GstRTSPConnInfo GstRTSPConnInfo;
 
-struct _GstRTSPConnInfo {
-  gchar              *location;
-  GstRTSPUrl         *url;
-  gchar              *url_str;
-  GstRTSPConnection  *connection;
-  gboolean            connected;
+struct _GstRTSPConnInfo
+{
+  gchar *location;
+  GstRTSPUrl *url;
+  gchar *url_str;
+  GstRTSPConnection *connection;
+  gboolean connected;
 };
 
 typedef struct _GstRTSPStream GstRTSPStream;
 
-struct _GstRTSPStream {
-  gint          id;
+struct _GstRTSPStream
+{
+  gint id;
 
-  GstRTSPSrc   *parent; /* parent, no extra ref to parent is taken */
+  GstRTSPSrc *parent;           /* parent, no extra ref to parent is taken */
 
   /* pad we expose or NULL when it does not have an actual pad */
-  GstPad       *srcpad;
+  GstPad *srcpad;
   GstFlowReturn last_ret;
-  gboolean      added;
-  gboolean      disabled;
-  gboolean      eos;
-  gboolean      discont;
+  gboolean added;
+  gboolean disabled;
+  gboolean eos;
+  gboolean discont;
 
   /* for interleaved mode */
-  guint8        channel[2];
-  GstCaps      *caps;
-  GstPad       *channelpad[2];
+  guint8 channel[2];
+  GstCaps *caps;
+  GstPad *channelpad[2];
 
   /* our udp sources */
-  GstElement   *udpsrc[2];
-  GstPad       *blockedpad;
-  gboolean      is_ipv6;
+  GstElement *udpsrc[2];
+  GstPad *blockedpad;
+  gboolean is_ipv6;
 
   /* our udp sinks back to the server */
-  GstElement   *udpsink[2];
-  GstPad       *rtcppad;
+  GstElement *udpsink[2];
+  GstPad *rtcppad;
 
   /* fakesrc for sending dummy data */
-  GstElement   *fakesrc;
+  GstElement *fakesrc;
 
   /* state */
-  gint          pt;
-  guint         port;
-  gboolean      container;
+  gint pt;
+  guint port;
+  gboolean container;
   /* original control url */
-  gchar        *control_url;
-  guint32       ssrc; 
-  guint32       seqbase;
-  guint64       timebase;
+  gchar *control_url;
+  guint32 ssrc;
+  guint32 seqbase;
+  guint64 timebase;
 
   /* per stream connection */
-  GstRTSPConnInfo  conninfo;
+  GstRTSPConnInfo conninfo;
 
   /* bandwidth */
-  guint         as_bandwidth;
-  guint         rs_bandwidth;
-  guint         rr_bandwidth;
+  guint as_bandwidth;
+  guint rs_bandwidth;
+  guint rr_bandwidth;
 
   /* destination */
-  gchar        *destination;
-  guint         ttl;
+  gchar *destination;
+  guint ttl;
 };
 
 /**
@@ -161,25 +159,26 @@
   GST_RTSP_NAT_DUMMY
 } GstRTSPNatMethod;
 
-struct _GstRTSPSrc {
-  GstBin           parent;
+struct _GstRTSPSrc
+{
+  GstBin parent;
 
   /* task and mutex for interleaved mode */
-  gboolean         interleaved;
-  GstTask         *task;
+  gboolean interleaved;
+  GstTask *task;
   GStaticRecMutex *stream_rec_lock;
-  GstSegment       segment;
-  gboolean         running;
-  gboolean         need_range;
-  gboolean         skip;
-  gint             free_channel;
-  GstEvent        *close_segment;
-  GstEvent        *start_segment;
-  GstClockTime     base_time;
+  GstSegment segment;
+  gboolean running;
+  gboolean need_range;
+  gboolean skip;
+  gint free_channel;
+  GstEvent *close_segment;
+  GstEvent *start_segment;
+  GstClockTime base_time;
 
   /* UDP mode loop */
-  gint             loop_cmd;
-  gboolean         ignore_timeout;
+  gint loop_cmd;
+  gboolean ignore_timeout;
 
   /* mutex for protecting state changes */
   GStaticRecMutex *state_rec_lock;
@@ -187,66 +186,67 @@
   /* mutex for protecting the connection */
   GStaticRecMutex *conn_rec_lock;
 
-  GstSDPMessage   *sdp;
-  gboolean         from_sdp;
-  gint             numstreams;
-  GList           *streams;
-  GstStructure    *props;
-  gboolean         need_activate;
+  GstSDPMessage *sdp;
+  gboolean from_sdp;
+  gint numstreams;
+  GList *streams;
+  GstStructure *props;
+  gboolean need_activate;
+  gboolean is_kasenna;
 
   /* properties */
   GstRTSPLowerTrans protocols;
-  gboolean          debug;
-  guint   	    retry;
-  guint64           udp_timeout;
-  GTimeVal          tcp_timeout;
-  GTimeVal         *ptcp_timeout;
-  guint             latency;
-  guint             connection_speed;
-  GstRTSPNatMethod  nat_method;
-  gboolean          do_rtcp;
-  gchar            *proxy_host;
-  guint             proxy_port;
-  gchar            *proxy_user;
-  gchar            *proxy_passwd;
-  guint             rtp_blocksize;
-  gchar            *user_id;
-  gchar            *user_pw;
-  gint              buffer_mode;
-  GstRTSPRange      client_port_range;
-  gint              udp_buffer_size;
+  gboolean debug;
+  guint retry;
+  guint64 udp_timeout;
+  GTimeVal tcp_timeout;
+  GTimeVal *ptcp_timeout;
+  guint latency;
+  guint connection_speed;
+  GstRTSPNatMethod nat_method;
+  gboolean do_rtcp;
+  gchar *proxy_host;
+  guint proxy_port;
+  gchar *proxy_user;
+  gchar *proxy_passwd;
+  guint rtp_blocksize;
+  gchar *user_id;
+  gchar *user_pw;
+  gint buffer_mode;
+  GstRTSPRange client_port_range;
+  gint udp_buffer_size;
 
   /* state */
-  GstRTSPState       state;
-  gchar             *content_base;
-  GstRTSPLowerTrans  cur_protocols;
-  gboolean           tried_url_auth;
-  gchar             *addr;
-  gboolean           need_redirect;
-  GstRTSPTimeRange  *range;
-  gchar             *control;
-  guint              next_port_num;
+  GstRTSPState state;
+  gchar *content_base;
+  GstRTSPLowerTrans cur_protocols;
+  gboolean tried_url_auth;
+  gchar *addr;
+  gboolean need_redirect;
+  GstRTSPTimeRange *range;
+  gchar *control;
+  guint next_port_num;
 
   /* supported methods */
-  gint               methods;
+  gint methods;
 
   /* session management */
-  GstElement      *session;
-  gulong           session_sig_id;
-  gulong           session_ptmap_id;
+  GstElement *session;
+  gulong session_sig_id;
+  gulong session_ptmap_id;
 
-  GstRTSPConnInfo  conninfo;
+  GstRTSPConnInfo conninfo;
 
   /* a list of RTSP extensions as GstElement */
-  GstRTSPExtensionList  *extensions;
+  GstRTSPExtensionList *extensions;
 };
 
-struct _GstRTSPSrcClass {
+struct _GstRTSPSrcClass
+{
   GstBinClass parent_class;
 };
 
-GType gst_rtspsrc_get_type(void);
+GType gst_rtspsrc_get_type (void);
 
 G_END_DECLS
-
 #endif /* __GST_RTSPSRC_H__ */
