[wfdmanager/wfdtsdemux] 1. Fix the pad probe function 29/40529/4 accepted/tizen/common/20150605.080245 accepted/tizen/mobile/20150605.092658 accepted/tizen/tv/20150605.092629 accepted/tizen/wearable/20150605.092637 submit/tizen/20150605.064824
authorSangkyu Park <sk1122.park@samsung.com>
Fri, 5 Jun 2015 02:27:07 +0000 (11:27 +0900)
committerSangkyu Park <sk1122.park@samsung.com>
Fri, 5 Jun 2015 05:08:51 +0000 (14:08 +0900)
2. Fix to handle message confige error.
3. Fix prevent defects.
4. Remove unnecessary files and code.
5. Change CMD_SET_PARAM with CMD_SEND_REQUEST
6. Fix RTSP Message for Wi-Fi display.

Change-Id: Iffeb2a173f37d7830392bdce055923960e64bfdb
Signed-off-by: Sangkyu Park <sk1122.park@samsung.com>
18 files changed:
packaging/gst-plugins-tizen.spec
wfdmanager/src/Makefile.am
wfdmanager/src/gstwfdrtpbuffer.c [deleted file]
wfdmanager/src/gstwfdrtspext.c [deleted file]
wfdmanager/src/gstwfdrtspext.h [deleted file]
wfdmanager/src/gstwfdrtspsrc.c
wfdmanager/src/gstwfdrtspsrc.h
wfdmanager/src/wfdrtpbuffer/gstwfdrtpbuffer.c
wfdmanager/src/wfdrtspconfigmessage.h
wfdmanager/src/wfdrtspmacro.h
wfdmanager/src/wfdrtspmanager.c
wfdtsdemux/Makefile.am
wfdtsdemux/gstwfdh264parser.c
wfdtsdemux/gstwfdtsdescriptor.c
wfdtsdemux/gstwfdtssection.c
wfdtsdemux/wfdtsbase.c
wfdtsdemux/wfdtsdemux.c
wfdtsdemux/wfdtspacketizer.c

index e94f3c8..2b2ee2e 100644 (file)
@@ -4,7 +4,7 @@
 Name:       gst-plugins-tizen
 Version:    1.0.0
 Summary:    GStreamer tizen plugins (common)
-Release:    1
+Release:    2
 Group:      Multimedia/Framework
 Url:        http://gstreamer.freedesktop.org/
 License:    LGPL-2.0+
index 960924b..bd49941 100755 (executable)
@@ -2,7 +2,6 @@ plugin_LTLIBRARIES = libgstwfdmanager.la
 
 libgstwfdmanager_la_SOURCES = gstwfdmanager.c \
                        gstwfdrtspsrc.c \
-                       gstwfdrtspext.c \
                        gstwfdrtprequester.c
 
 libgstwfdmanager_la_SOURCES += wfdrtspmanager.c \
@@ -20,7 +19,6 @@ libgstwfdmanager_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 libgstwfdmanager_la_LIBTOOLFLAGS = --tag=disable-static
 
 noinst_HEADERS = gstwfdrtspsrc.h \
-                gstwfdrtspext.h \
                gstwfdrtprequester.h
 
 noinst_HEADERS += wfdrtspmanager.h \
diff --git a/wfdmanager/src/gstwfdrtpbuffer.c b/wfdmanager/src/gstwfdrtpbuffer.c
deleted file mode 100755 (executable)
index 77988ab..0000000
+++ /dev/null
@@ -1,3568 +0,0 @@
-/*
- * Farsight Voice+Video library
- *
- *  Copyright 2007 Collabora Ltd,
- *  Copyright 2007 Nokia Corporation
- *   @author: Philippe Kalaf <philippe.kalaf@collabora.co.uk>.
- *  Copyright 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-/**
- * SECTION:element-wfdrtpbuffer
- *
- * This element reorders and removes duplicate RTP packets as they are received
- * from a network source.
- *
- * The element needs the clock-rate of the RTP payload in order to estimate the
- * delay. This information is obtained either from the caps on the sink pad or,
- * when no caps are present, from the #GstWfdRTPBuffer::request-pt-map signal.
- * To clear the previous pt-map use the #GstWfdRTPBuffer::clear-pt-map signal.
- *
- * The wfdrtpbuffer will wait for missing packets up to a configurable time
- * limit using the #GstWfdRTPBuffer:latency property. Packets arriving too
- * late are considered to be lost packets. If the #GstWfdRTPBuffer:do-lost
- * property is set, lost packets will result in a custom serialized downstream
- * event of name GstRTPPacketLost. The lost packet events are usually used by a
- * depayloader or other element to create concealment data or some other logic
- * to gracefully handle the missing packets.
- *
- * The jitterbuffer will use the DTS (or PTS if no DTS is set) of the incomming
- * buffer and the rtptime inside the RTP packet to create a PTS on the outgoing
- * buffer.
- *
- * The jitterbuffer can also be configured to send early retransmission events
- * upstream by setting the #GstWfdRTPBuffer:do-retransmission property. In
- * this mode, the jitterbuffer tries to estimate when a packet should arrive and
- * sends a custom upstream event named GstRTPRetransmissionRequest when the
- * packet is considered late. The initial expected packet arrival time is
- * calculated as follows:
- *
- * - If seqnum N arrived at time T, seqnum N+1 is expected to arrive at
- *     T + packet-spacing + #GstWfdRTPBuffer:rtx-delay. The packet spacing is
- *     calculated from the DTS (or PTS is no DTS) of two consecutive RTP
- *     packets with different rtptime.
- *
- * - If seqnum N0 arrived at time T0 and seqnum Nm arrived at time Tm,
- *     seqnum Ni is expected at time Ti = T0 + i*(Tm - T0)/(Nm - N0). Any
- *     previously scheduled timeout is overwritten.
- *
- * - If seqnum N arrived, all seqnum older than
- *     N - #GstWfdRTPBuffer:rtx-delay-reorder are considered late
- *     immediately. This is to request fast feedback for abonormally reorder
- *     packets before any of the previous timeouts is triggered.
- *
- * A late packet triggers the GstRTPRetransmissionRequest custom upstream
- * event. After the initial timeout expires and the retransmission event is
- * sent, the timeout is scheduled for
- * T + #GstWfdRTPBuffer:rtx-retry-timeout. If the missing packet did not
- * arrive after #GstWfdRTPBuffer:rtx-retry-timeout, a new
- * GstRTPRetransmissionRequest is sent upstream and the timeout is rescheduled
- * again for T + #GstWfdRTPBuffer:rtx-retry-timeout. This repeats until
- * #GstWfdRTPBuffer:rtx-retry-period elapsed, at which point no further
- * retransmission requests are sent and the regular logic is performed to
- * schedule a lost packet as discussed above.
- *
- * This element acts as a live element and so adds #GstWfdRTPBuffer:latency
- * to the pipeline.
- *
- * This element will automatically be used inside rtpbin.
- *
- * <refsect2>
- * <title>Example pipelines</title>
- * |[
- * gst-launch-1.0 rtspsrc location=rtsp://192.168.1.133:8554/mpeg1or2AudioVideoTest ! wfdrtpbuffer ! rtpmpvdepay ! mpeg2dec ! xvimagesink
- * ]| Connect to a streaming server and decode the MPEG video. The jitterbuffer is
- * inserted into the pipeline to smooth out network jitter and to reorder the
- * out-of-order RTP packets.
- * </refsect2>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include <gst/rtp/gstrtpbuffer.h>
-
-#include "gstwfdrtpbuffer.h"
-#include "wfdrtpbuffer.h"
-#include "rtpstats.h"
-
-GST_DEBUG_CATEGORY (wfdrtpbuffer_debug);
-#define GST_CAT_DEFAULT (wfdrtpbuffer_debug)
-
-/* WfdRTPBuffer signals and args */
-enum
-{
-  SIGNAL_REQUEST_PT_MAP,
-  SIGNAL_CLEAR_PT_MAP,
-  SIGNAL_HANDLE_SYNC,
-  SIGNAL_ON_NPT_STOP,
-  SIGNAL_SET_ACTIVE,
-  LAST_SIGNAL
-};
-
-#define DEFAULT_LATENCY_MS          200
-#define DEFAULT_DROP_ON_LATENCY     FALSE
-#define DEFAULT_TS_OFFSET           0
-#define DEFAULT_DO_LOST             FALSE
-#define DEFAULT_MODE                WFD_RTP_BUFFER_MODE_SLAVE
-#define DEFAULT_PERCENT             0
-#define DEFAULT_DO_RETRANSMISSION   FALSE
-#define DEFAULT_RTX_DELAY           -1
-#define DEFAULT_RTX_DELAY_REORDER   3
-#define DEFAULT_RTX_RETRY_TIMEOUT   -1
-#define DEFAULT_RTX_RETRY_PERIOD    -1
-
-#define DEFAULT_AUTO_RTX_DELAY (20 * GST_MSECOND)
-#define DEFAULT_AUTO_RTX_TIMEOUT (40 * GST_MSECOND)
-
-enum
-{
-  PROP_0,
-  PROP_LATENCY,
-  PROP_DROP_ON_LATENCY,
-  PROP_TS_OFFSET,
-  PROP_DO_LOST,
-  PROP_MODE,
-  PROP_PERCENT,
-  PROP_DO_RETRANSMISSION,
-  PROP_RTX_DELAY,
-  PROP_RTX_DELAY_REORDER,
-  PROP_RTX_RETRY_TIMEOUT,
-  PROP_RTX_RETRY_PERIOD,
-  PROP_STATS,
-  PROP_LAST
-};
-
-#define JBUF_LOCK(priv)   (g_mutex_lock (&(priv)->jbuf_lock))
-
-#define JBUF_LOCK_CHECK(priv,label) G_STMT_START {    \
-  JBUF_LOCK (priv);                                   \
-  if (G_UNLIKELY (priv->srcresult != GST_FLOW_OK))    \
-    goto label;                                       \
-} G_STMT_END
-#define JBUF_UNLOCK(priv) (g_mutex_unlock (&(priv)->jbuf_lock))
-
-#define JBUF_WAIT_TIMER(priv)   G_STMT_START {            \
-  GST_DEBUG ("waiting timer");                            \
-  (priv)->waiting_timer = TRUE;                           \
-  g_cond_wait (&(priv)->jbuf_timer, &(priv)->jbuf_lock);  \
-  (priv)->waiting_timer = FALSE;                          \
-  GST_DEBUG ("waiting timer done");                       \
-} G_STMT_END
-#define JBUF_SIGNAL_TIMER(priv) G_STMT_START {            \
-  if (G_UNLIKELY ((priv)->waiting_timer)) {               \
-    GST_DEBUG ("signal timer");                           \
-    g_cond_signal (&(priv)->jbuf_timer);                  \
-  }                                                       \
-} G_STMT_END
-
-#define JBUF_WAIT_EVENT(priv,label) G_STMT_START {       \
-  GST_DEBUG ("waiting event");                           \
-  (priv)->waiting_event = TRUE;                          \
-  g_cond_wait (&(priv)->jbuf_event, &(priv)->jbuf_lock); \
-  (priv)->waiting_event = FALSE;                         \
-  GST_DEBUG ("waiting event done");                      \
-  if (G_UNLIKELY (priv->srcresult != GST_FLOW_OK))       \
-    goto label;                                          \
-} G_STMT_END
-#define JBUF_SIGNAL_EVENT(priv) G_STMT_START {           \
-  if (G_UNLIKELY ((priv)->waiting_event)) {              \
-    GST_DEBUG ("signal event");                          \
-    g_cond_signal (&(priv)->jbuf_event);                 \
-  }                                                      \
-} G_STMT_END
-
-#define JBUF_WAIT_QUERY(priv,label) G_STMT_START {       \
-  GST_DEBUG ("waiting query");                           \
-  (priv)->waiting_query = TRUE;                          \
-  g_cond_wait (&(priv)->jbuf_query, &(priv)->jbuf_lock); \
-  (priv)->waiting_query = FALSE;                         \
-  GST_DEBUG ("waiting query done");                      \
-  if (G_UNLIKELY (priv->srcresult != GST_FLOW_OK))       \
-    goto label;                                          \
-} G_STMT_END
-#define JBUF_SIGNAL_QUERY(priv,res) G_STMT_START {       \
-  (priv)->last_query = res;                              \
-  if (G_UNLIKELY ((priv)->waiting_query)) {              \
-    GST_DEBUG ("signal query");                          \
-    g_cond_signal (&(priv)->jbuf_query);                 \
-  }                                                      \
-} G_STMT_END
-
-
-struct _GstWfdRTPBufferPrivate
-{
-  GstPad *sinkpad, *srcpad;
-  GstPad *rtcpsinkpad;
-
-  WfdRTPBuffer *jbuf;
-  GMutex jbuf_lock;
-  gboolean waiting_timer;
-  GCond jbuf_timer;
-  gboolean waiting_event;
-  GCond jbuf_event;
-  gboolean waiting_query;
-  GCond jbuf_query;
-  gboolean last_query;
-  gboolean discont;
-  gboolean ts_discont;
-  gboolean active;
-  guint64 out_offset;
-
-  gboolean timer_running;
-  GThread *timer_thread;
-
-  /* properties */
-  guint latency_ms;
-  guint64 latency_ns;
-  gboolean drop_on_latency;
-  gint64 ts_offset;
-  gboolean do_lost;
-  gboolean do_retransmission;
-  gint rtx_delay;
-  gint rtx_delay_reorder;
-  gint rtx_retry_timeout;
-  gint rtx_retry_period;
-
-  /* the last seqnum we pushed out */
-  guint32 last_popped_seqnum;
-  /* the next expected seqnum we push */
-  guint32 next_seqnum;
-  /* last output time */
-  GstClockTime last_out_time;
-  /* last valid input timestamp and rtptime pair */
-  GstClockTime ips_dts;
-  guint64 ips_rtptime;
-  GstClockTime packet_spacing;
-
-  /* the next expected seqnum we receive */
-  GstClockTime last_in_dts;
-  guint32 last_in_seqnum;
-  guint32 next_in_seqnum;
-
-  GArray *timers;
-
-  /* start and stop ranges */
-  GstClockTime npt_start;
-  GstClockTime npt_stop;
-  guint64 ext_timestamp;
-  guint64 last_elapsed;
-  guint64 estimated_eos;
-  GstClockID eos_id;
-
-  /* state */
-  gboolean eos;
-  guint last_percent;
-
-  /* clock rate and rtp timestamp offset */
-  gint last_pt;
-  gint32 clock_rate;
-  gint64 clock_base;
-  gint64 prev_ts_offset;
-
-  /* when we are shutting down */
-  GstFlowReturn srcresult;
-  gboolean blocked;
-
-  /* for sync */
-  GstSegment segment;
-  GstClockID clock_id;
-  GstClockTime timer_timeout;
-  guint16 timer_seqnum;
-  /* the latency of the upstream peer, we have to take this into account when
-   * synchronizing the buffers. */
-  GstClockTime peer_latency;
-  guint64 ext_rtptime;
-  GstBuffer *last_sr;
-
-  /* some accounting */
-  guint64 num_late;
-  guint64 num_duplicates;
-  guint64 num_rtx_requests;
-  guint64 num_rtx_success;
-  guint64 num_rtx_failed;
-  gdouble avg_rtx_num;
-  guint64 avg_rtx_rtt;
-
-  /* for the jitter */
-  GstClockTime last_dts;
-  guint64 last_rtptime;
-  GstClockTime avg_jitter;
-};
-
-typedef enum
-{
-  TIMER_TYPE_EXPECTED,
-  TIMER_TYPE_LOST,
-  TIMER_TYPE_DEADLINE,
-  TIMER_TYPE_EOS
-} TimerType;
-
-typedef struct
-{
-  guint idx;
-  guint16 seqnum;
-  guint num;
-  TimerType type;
-  GstClockTime timeout;
-  GstClockTime duration;
-  GstClockTime rtx_base;
-  GstClockTime rtx_delay;
-  GstClockTime rtx_retry;
-  GstClockTime rtx_last;
-  guint num_rtx_retry;
-} TimerData;
-
-#define GST_WFD_RTP_BUFFER_GET_PRIVATE(o) \
-  (G_TYPE_INSTANCE_GET_PRIVATE ((o), GST_TYPE_WFD_RTP_BUFFER, \
-                                GstWfdRTPBufferPrivate))
-
-static GstStaticPadTemplate gst_wfd_rtp_buffer_sink_template =
-GST_STATIC_PAD_TEMPLATE ("sink",
-    GST_PAD_SINK,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("application/x-rtp, "
-        "clock-rate = (int) [ 1, 2147483647 ]"
-        /* "payload = (int) , "
-         * "encoding-name = (string) "
-         */ )
-    );
-
-static GstStaticPadTemplate gst_wfd_rtp_buffer_sink_rtcp_template =
-GST_STATIC_PAD_TEMPLATE ("sink_rtcp",
-    GST_PAD_SINK,
-    GST_PAD_REQUEST,
-    GST_STATIC_CAPS ("application/x-rtcp")
-    );
-
-static GstStaticPadTemplate gst_wfd_rtp_buffer_src_template =
-GST_STATIC_PAD_TEMPLATE ("src",
-    GST_PAD_SRC,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("application/x-rtp"
-        /* "payload = (int) , "
-         * "clock-rate = (int) , "
-         * "encoding-name = (string) "
-         */ )
-    );
-
-static guint gst_wfd_rtp_buffer_signals[LAST_SIGNAL] = { 0 };
-
-#define gst_wfd_rtp_buffer_parent_class parent_class
-G_DEFINE_TYPE (GstWfdRTPBuffer, gst_wfd_rtp_buffer, GST_TYPE_ELEMENT);
-
-/* object overrides */
-static void gst_wfd_rtp_buffer_set_property (GObject * object,
-    guint prop_id, const GValue * value, GParamSpec * pspec);
-static void gst_wfd_rtp_buffer_get_property (GObject * object,
-    guint prop_id, GValue * value, GParamSpec * pspec);
-static void gst_wfd_rtp_buffer_finalize (GObject * object);
-
-/* element overrides */
-static GstStateChangeReturn gst_wfd_rtp_buffer_change_state (GstElement
-    * element, GstStateChange transition);
-static GstPad *gst_wfd_rtp_buffer_request_new_pad (GstElement * element,
-    GstPadTemplate * templ, const gchar * name, const GstCaps * filter);
-static void gst_wfd_rtp_buffer_release_pad (GstElement * element,
-    GstPad * pad);
-static GstClock *gst_wfd_rtp_buffer_provide_clock (GstElement * element);
-
-/* pad overrides */
-static GstCaps *gst_wfd_rtp_buffer_getcaps (GstPad * pad, GstCaps * filter);
-static GstIterator *gst_wfd_rtp_buffer_iterate_internal_links (GstPad * pad,
-    GstObject * parent);
-
-/* sinkpad overrides */
-static gboolean gst_wfd_rtp_buffer_sink_event (GstPad * pad,
-    GstObject * parent, GstEvent * event);
-static GstFlowReturn gst_wfd_rtp_buffer_chain (GstPad * pad,
-    GstObject * parent, GstBuffer * buffer);
-
-static gboolean gst_wfd_rtp_buffer_sink_rtcp_event (GstPad * pad,
-    GstObject * parent, GstEvent * event);
-static GstFlowReturn gst_wfd_rtp_buffer_chain_rtcp (GstPad * pad,
-    GstObject * parent, GstBuffer * buffer);
-
-static gboolean gst_wfd_rtp_buffer_sink_query (GstPad * pad,
-    GstObject * parent, GstQuery * query);
-
-/* srcpad overrides */
-static gboolean gst_wfd_rtp_buffer_src_event (GstPad * pad,
-    GstObject * parent, GstEvent * event);
-static gboolean gst_wfd_rtp_buffer_src_activate_mode (GstPad * pad,
-    GstObject * parent, GstPadMode mode, gboolean active);
-static void gst_wfd_rtp_buffer_loop (GstWfdRTPBuffer * jitterbuffer);
-static gboolean gst_wfd_rtp_buffer_src_query (GstPad * pad,
-    GstObject * parent, GstQuery * query);
-
-static void
-gst_wfd_rtp_buffer_clear_pt_map (GstWfdRTPBuffer * jitterbuffer);
-static GstClockTime
-gst_wfd_rtp_buffer_set_active (GstWfdRTPBuffer * jitterbuffer,
-    gboolean active, guint64 base_time);
-static void do_handle_sync (GstWfdRTPBuffer * jitterbuffer);
-
-static void unschedule_current_timer (GstWfdRTPBuffer * jitterbuffer);
-static void remove_all_timers (GstWfdRTPBuffer * jitterbuffer);
-
-static void wait_next_timeout (GstWfdRTPBuffer * jitterbuffer);
-
-static GstStructure *gst_wfd_rtp_buffer_create_stats (GstWfdRTPBuffer *
-    jitterbuffer);
-
-static void
-gst_wfd_rtp_buffer_class_init (GstWfdRTPBufferClass * klass)
-{
-  GObjectClass *gobject_class;
-  GstElementClass *gstelement_class;
-
-  gobject_class = (GObjectClass *) klass;
-  gstelement_class = (GstElementClass *) klass;
-
-  g_type_class_add_private (klass, sizeof (GstWfdRTPBufferPrivate));
-
-  gobject_class->finalize = gst_wfd_rtp_buffer_finalize;
-
-  gobject_class->set_property = gst_wfd_rtp_buffer_set_property;
-  gobject_class->get_property = gst_wfd_rtp_buffer_get_property;
-
-  /**
-   * GstWfdRTPBuffer:latency:
-   *
-   * The maximum latency of the jitterbuffer. Packets will be kept in the buffer
-   * for at most this time.
-   */
-  g_object_class_install_property (gobject_class, PROP_LATENCY,
-      g_param_spec_uint ("latency", "Buffer latency in ms",
-          "Amount of ms to buffer", 0, G_MAXUINT, DEFAULT_LATENCY_MS,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-  /**
-   * GstWfdRTPBuffer:drop-on-latency:
-   *
-   * Drop oldest buffers when the queue is completely filled.
-   */
-  g_object_class_install_property (gobject_class, PROP_DROP_ON_LATENCY,
-      g_param_spec_boolean ("drop-on-latency",
-          "Drop buffers when maximum latency is reached",
-          "Tells the jitterbuffer to never exceed the given latency in size",
-          DEFAULT_DROP_ON_LATENCY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-  /**
-   * GstWfdRTPBuffer:ts-offset:
-   *
-   * Adjust GStreamer output buffer timestamps in the jitterbuffer with offset.
-   * This is mainly used to ensure interstream synchronisation.
-   */
-  g_object_class_install_property (gobject_class, PROP_TS_OFFSET,
-      g_param_spec_int64 ("ts-offset", "Timestamp Offset",
-          "Adjust buffer timestamps with offset in nanoseconds", G_MININT64,
-          G_MAXINT64, DEFAULT_TS_OFFSET,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
-  /**
-   * GstWfdRTPBuffer:do-lost:
-   *
-   * Send out a GstRTPPacketLost event downstream when a packet is considered
-   * lost.
-   */
-  g_object_class_install_property (gobject_class, PROP_DO_LOST,
-      g_param_spec_boolean ("do-lost", "Do Lost",
-          "Send an event downstream when a packet is lost", DEFAULT_DO_LOST,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
-  /**
-   * GstWfdRTPBuffer:mode:
-   *
-   * Control the buffering and timestamping mode used by the jitterbuffer.
-   */
-  g_object_class_install_property (gobject_class, PROP_MODE,
-      g_param_spec_enum ("mode", "Mode",
-          "Control the buffering algorithm in use", WFD_TYPE_RTP_BUFFER_MODE,
-          DEFAULT_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-  /**
-   * GstWfdRTPBuffer:percent:
-   *
-   * The percent of the jitterbuffer that is filled.
-   */
-  g_object_class_install_property (gobject_class, PROP_PERCENT,
-      g_param_spec_int ("percent", "percent",
-          "The buffer filled percent", 0, 100,
-          0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
-  /**
-   * GstWfdRTPBuffer:do-retransmission:
-   *
-   * Send out a GstRTPRetransmission event upstream when a packet is considered
-   * late and should be retransmitted.
-   *
-   * Since: 1.2
-   */
-  g_object_class_install_property (gobject_class, PROP_DO_RETRANSMISSION,
-      g_param_spec_boolean ("do-retransmission", "Do Retransmission",
-          "Send retransmission events upstream when a packet is late",
-          DEFAULT_DO_RETRANSMISSION,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
-  /**
-   * GstWfdRTPBuffer:rtx-delay:
-   *
-   * When a packet did not arrive at the expected time, wait this extra amount
-   * of time before sending a retransmission event.
-   *
-   * When -1 is used, the max jitter will be used as extra delay.
-   *
-   * Since: 1.2
-   */
-  g_object_class_install_property (gobject_class, PROP_RTX_DELAY,
-      g_param_spec_int ("rtx-delay", "RTX Delay",
-          "Extra time in ms to wait before sending retransmission "
-          "event (-1 automatic)", -1, G_MAXINT, DEFAULT_RTX_DELAY,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-  /**
-   * GstWfdRTPBuffer:rtx-delay-reorder:
-   *
-   * Assume that a retransmission event should be sent when we see
-   * this much packet reordering.
-   *
-   * When -1 is used, the value will be estimated based on observed packet
-   * reordering.
-   *
-   * Since: 1.2
-   */
-  g_object_class_install_property (gobject_class, PROP_RTX_DELAY_REORDER,
-      g_param_spec_int ("rtx-delay-reorder", "RTX Delay Reorder",
-          "Sending retransmission event when this much reordering (-1 automatic)",
-          -1, G_MAXINT, DEFAULT_RTX_DELAY_REORDER,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-  /**
-   * GstWfdRTPBuffer::rtx-retry-timeout:
-   *
-   * When no packet has been received after sending a retransmission event
-   * for this time, retry sending a retransmission event.
-   *
-   * When -1 is used, the value will be estimated based on observed round
-   * trip time.
-   *
-   * Since: 1.2
-   */
-  g_object_class_install_property (gobject_class, PROP_RTX_RETRY_TIMEOUT,
-      g_param_spec_int ("rtx-retry-timeout", "RTX Retry Timeout",
-          "Retry sending a transmission event after this timeout in "
-          "ms (-1 automatic)", -1, G_MAXINT, DEFAULT_RTX_RETRY_TIMEOUT,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-  /**
-   * GstWfdRTPBuffer:rtx-retry-period:
-   *
-   * The amount of time to try to get a retransmission.
-   *
-   * When -1 is used, the value will be estimated based on the jitterbuffer
-   * latency and the observed round trip time.
-   *
-   * Since: 1.2
-   */
-  g_object_class_install_property (gobject_class, PROP_RTX_RETRY_PERIOD,
-      g_param_spec_int ("rtx-retry-period", "RTX Retry Period",
-          "Try to get a retransmission for this many ms "
-          "(-1 automatic)", -1, G_MAXINT, DEFAULT_RTX_RETRY_PERIOD,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-  /**
-   * GstWfdRTPBuffer:stats:
-   *
-   * Various jitterbuffer statistics. This property returns a GstStructure
-   * with name application/x-rtp-jitterbuffer-stats with the following fields:
-   *
-   *  "rtx-count"         G_TYPE_UINT64 The number of retransmissions requested
-   *  "rtx-success-count" G_TYPE_UINT64 The number of successful retransmissions
-   *  "rtx-per-packet"    G_TYPE_DOUBLE Average number of RTX per packet
-   *  "rtx-rtt"           G_TYPE_UINT64 Average round trip time per RTX
-   *
-   * Since: 1.4
-   */
-  g_object_class_install_property (gobject_class, PROP_STATS,
-      g_param_spec_boxed ("stats", "Statistics",
-          "Various statistics", GST_TYPE_STRUCTURE,
-          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
-
-  /**
-   * GstWfdRTPBuffer::request-pt-map:
-   * @buffer: the object which received the signal
-   * @pt: the pt
-   *
-   * Request the payload type as #GstCaps for @pt.
-   */
-  gst_wfd_rtp_buffer_signals[SIGNAL_REQUEST_PT_MAP] =
-      g_signal_new ("request-pt-map", G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstWfdRTPBufferClass,
-          request_pt_map), NULL, NULL, g_cclosure_marshal_generic,
-      GST_TYPE_CAPS, 1, G_TYPE_UINT);
-  /**
-   * GstWfdRTPBuffer::handle-sync:
-   * @buffer: the object which received the signal
-   * @struct: a GstStructure containing sync values.
-   *
-   * Be notified of new sync values.
-   */
-  gst_wfd_rtp_buffer_signals[SIGNAL_HANDLE_SYNC] =
-      g_signal_new ("handle-sync", G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstWfdRTPBufferClass,
-          handle_sync), NULL, NULL, g_cclosure_marshal_VOID__BOXED,
-      G_TYPE_NONE, 1, GST_TYPE_STRUCTURE | G_SIGNAL_TYPE_STATIC_SCOPE);
-
-  /**
-   * GstWfdRTPBuffer::on-npt-stop:
-   * @buffer: the object which received the signal
-   *
-   * Signal that the jitterbufer has pushed the RTP packet that corresponds to
-   * the npt-stop position.
-   */
-  gst_wfd_rtp_buffer_signals[SIGNAL_ON_NPT_STOP] =
-      g_signal_new ("on-npt-stop", G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstWfdRTPBufferClass,
-          on_npt_stop), NULL, NULL, g_cclosure_marshal_VOID__VOID,
-      G_TYPE_NONE, 0, G_TYPE_NONE);
-
-  /**
-   * GstWfdRTPBuffer::clear-pt-map:
-   * @buffer: the object which received the signal
-   *
-   * Invalidate the clock-rate as obtained with the
-   * #GstWfdRTPBuffer::request-pt-map signal.
-   */
-  gst_wfd_rtp_buffer_signals[SIGNAL_CLEAR_PT_MAP] =
-      g_signal_new ("clear-pt-map", G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
-      G_STRUCT_OFFSET (GstWfdRTPBufferClass, clear_pt_map), NULL, NULL,
-      g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
-
-  /**
-   * GstWfdRTPBuffer::set-active:
-   * @buffer: the object which received the signal
-   *
-   * Start pushing out packets with the given base time. This signal is only
-   * useful in buffering mode.
-   *
-   * Returns: the time of the last pushed packet.
-   */
-  gst_wfd_rtp_buffer_signals[SIGNAL_SET_ACTIVE] =
-      g_signal_new ("set-active", G_TYPE_FROM_CLASS (klass),
-      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
-      G_STRUCT_OFFSET (GstWfdRTPBufferClass, set_active), NULL, NULL,
-      g_cclosure_marshal_generic, G_TYPE_UINT64, 2, G_TYPE_BOOLEAN,
-      G_TYPE_UINT64);
-
-  gstelement_class->change_state =
-      GST_DEBUG_FUNCPTR (gst_wfd_rtp_buffer_change_state);
-  gstelement_class->request_new_pad =
-      GST_DEBUG_FUNCPTR (gst_wfd_rtp_buffer_request_new_pad);
-  gstelement_class->release_pad =
-      GST_DEBUG_FUNCPTR (gst_wfd_rtp_buffer_release_pad);
-  gstelement_class->provide_clock =
-      GST_DEBUG_FUNCPTR (gst_wfd_rtp_buffer_provide_clock);
-
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&gst_wfd_rtp_buffer_src_template));
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&gst_wfd_rtp_buffer_sink_template));
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&gst_wfd_rtp_buffer_sink_rtcp_template));
-
-  gst_element_class_set_static_metadata (gstelement_class,
-      "The Wi-Fi Display RTP packet jitter-buffer", "Filter/Network/RTP",
-      "A buffer that deals with network jitter and other transmission faults",
-      "Taewan kim <taewan79.kim@samsung.com>, "
-      "YeJin Cho <cho.yejin@samsung.com>,"
-      "Sangkyu Park <sk1122.park@samsung.com>");
-
-  klass->clear_pt_map = GST_DEBUG_FUNCPTR (gst_wfd_rtp_buffer_clear_pt_map);
-  klass->set_active = GST_DEBUG_FUNCPTR (gst_wfd_rtp_buffer_set_active);
-
-  GST_DEBUG_CATEGORY_INIT
-      (wfdrtpbuffer_debug, "wfdrtpbuffer", 0, "WFD RTP Jitter Buffer");
-}
-
-static void
-gst_wfd_rtp_buffer_init (GstWfdRTPBuffer * jitterbuffer)
-{
-  GstWfdRTPBufferPrivate *priv;
-
-  priv = GST_WFD_RTP_BUFFER_GET_PRIVATE (jitterbuffer);
-  jitterbuffer->priv = priv;
-
-  priv->latency_ms = DEFAULT_LATENCY_MS;
-  priv->latency_ns = priv->latency_ms * GST_MSECOND;
-  priv->drop_on_latency = DEFAULT_DROP_ON_LATENCY;
-  priv->do_lost = DEFAULT_DO_LOST;
-  priv->do_retransmission = DEFAULT_DO_RETRANSMISSION;
-  priv->rtx_delay = DEFAULT_RTX_DELAY;
-  priv->rtx_delay_reorder = DEFAULT_RTX_DELAY_REORDER;
-  priv->rtx_retry_timeout = DEFAULT_RTX_RETRY_TIMEOUT;
-  priv->rtx_retry_period = DEFAULT_RTX_RETRY_PERIOD;
-
-  priv->last_dts = -1;
-  priv->last_rtptime = -1;
-  priv->avg_jitter = 0;
-  priv->timers = g_array_new (FALSE, TRUE, sizeof (TimerData));
-  priv->jbuf = wfd_rtp_buffer_new ();
-  g_mutex_init (&priv->jbuf_lock);
-  g_cond_init (&priv->jbuf_timer);
-  g_cond_init (&priv->jbuf_event);
-  g_cond_init (&priv->jbuf_query);
-
-  /* reset skew detection initialy */
-  wfd_rtp_buffer_reset_skew (priv->jbuf);
-  wfd_rtp_buffer_set_delay (priv->jbuf, priv->latency_ns);
-  wfd_rtp_buffer_set_buffering (priv->jbuf, FALSE);
-  priv->active = TRUE;
-
-  priv->srcpad =
-      gst_pad_new_from_static_template (&gst_wfd_rtp_buffer_src_template,
-      "src");
-
-  gst_pad_set_activatemode_function (priv->srcpad,
-      GST_DEBUG_FUNCPTR (gst_wfd_rtp_buffer_src_activate_mode));
-  gst_pad_set_query_function (priv->srcpad,
-      GST_DEBUG_FUNCPTR (gst_wfd_rtp_buffer_src_query));
-  gst_pad_set_event_function (priv->srcpad,
-      GST_DEBUG_FUNCPTR (gst_wfd_rtp_buffer_src_event));
-
-  priv->sinkpad =
-      gst_pad_new_from_static_template (&gst_wfd_rtp_buffer_sink_template,
-      "sink");
-
-  gst_pad_set_chain_function (priv->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_wfd_rtp_buffer_chain));
-  gst_pad_set_event_function (priv->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_wfd_rtp_buffer_sink_event));
-  gst_pad_set_query_function (priv->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_wfd_rtp_buffer_sink_query));
-
-  gst_element_add_pad (GST_ELEMENT (jitterbuffer), priv->srcpad);
-  gst_element_add_pad (GST_ELEMENT (jitterbuffer), priv->sinkpad);
-
-  GST_OBJECT_FLAG_SET (jitterbuffer, GST_ELEMENT_FLAG_PROVIDE_CLOCK);
-}
-
-#define IS_DROPABLE(it) (((it)->type == ITEM_TYPE_BUFFER) || ((it)->type == ITEM_TYPE_LOST))
-
-#define ITEM_TYPE_BUFFER        0
-#define ITEM_TYPE_LOST          1
-#define ITEM_TYPE_EVENT         2
-#define ITEM_TYPE_QUERY         3
-
-static WfdRTPBufferItem *
-alloc_item (gpointer data, guint type, GstClockTime dts, GstClockTime pts,
-    guint seqnum, guint count, guint rtptime)
-{
-  WfdRTPBufferItem *item;
-
-  item = g_slice_new (WfdRTPBufferItem);
-  item->data = data;
-  item->next = NULL;
-  item->prev = NULL;
-  item->type = type;
-  item->dts = dts;
-  item->pts = pts;
-  item->seqnum = seqnum;
-  item->count = count;
-  item->rtptime = rtptime;
-
-  return item;
-}
-
-static void
-free_item (WfdRTPBufferItem * item)
-{
-  if (item->data && item->type != ITEM_TYPE_QUERY)
-    gst_mini_object_unref (item->data);
-  g_slice_free (WfdRTPBufferItem, item);
-}
-
-static void
-gst_wfd_rtp_buffer_finalize (GObject * object)
-{
-  GstWfdRTPBuffer *jitterbuffer;
-  GstWfdRTPBufferPrivate *priv;
-
-  jitterbuffer = GST_WFD_RTP_BUFFER (object);
-  priv = jitterbuffer->priv;
-
-  g_array_free (priv->timers, TRUE);
-  g_mutex_clear (&priv->jbuf_lock);
-  g_cond_clear (&priv->jbuf_timer);
-  g_cond_clear (&priv->jbuf_event);
-  g_cond_clear (&priv->jbuf_query);
-
-  wfd_rtp_buffer_flush (priv->jbuf, (GFunc) free_item, NULL);
-  g_object_unref (priv->jbuf);
-
-  G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static GstIterator *
-gst_wfd_rtp_buffer_iterate_internal_links (GstPad * pad, GstObject * parent)
-{
-  GstWfdRTPBuffer *jitterbuffer;
-  GstPad *otherpad = NULL;
-  GstIterator *it = NULL;
-  GValue val = { 0, };
-
-  jitterbuffer = GST_WFD_RTP_BUFFER_CAST (parent);
-
-  if (pad == jitterbuffer->priv->sinkpad) {
-    otherpad = jitterbuffer->priv->srcpad;
-  } else if (pad == jitterbuffer->priv->srcpad) {
-    otherpad = jitterbuffer->priv->sinkpad;
-  } else if (pad == jitterbuffer->priv->rtcpsinkpad) {
-    it = gst_iterator_new_single (GST_TYPE_PAD, NULL);
-  }
-
-  if (it == NULL) {
-    g_value_init (&val, GST_TYPE_PAD);
-    g_value_set_object (&val, otherpad);
-    it = gst_iterator_new_single (GST_TYPE_PAD, &val);
-    g_value_unset (&val);
-  }
-
-  return it;
-}
-
-static GstPad *
-create_rtcp_sink (GstWfdRTPBuffer * jitterbuffer)
-{
-  GstWfdRTPBufferPrivate *priv;
-
-  priv = jitterbuffer->priv;
-
-  GST_DEBUG_OBJECT (jitterbuffer, "creating RTCP sink pad");
-
-  priv->rtcpsinkpad =
-      gst_pad_new_from_static_template
-      (&gst_wfd_rtp_buffer_sink_rtcp_template, "sink_rtcp");
-  gst_pad_set_chain_function (priv->rtcpsinkpad,
-      gst_wfd_rtp_buffer_chain_rtcp);
-  gst_pad_set_event_function (priv->rtcpsinkpad,
-      (GstPadEventFunction) gst_wfd_rtp_buffer_sink_rtcp_event);
-  gst_pad_set_iterate_internal_links_function (priv->rtcpsinkpad,
-      gst_wfd_rtp_buffer_iterate_internal_links);
-  gst_pad_set_active (priv->rtcpsinkpad, TRUE);
-  gst_element_add_pad (GST_ELEMENT_CAST (jitterbuffer), priv->rtcpsinkpad);
-
-  return priv->rtcpsinkpad;
-}
-
-static void
-remove_rtcp_sink (GstWfdRTPBuffer * jitterbuffer)
-{
-  GstWfdRTPBufferPrivate *priv;
-
-  priv = jitterbuffer->priv;
-
-  GST_DEBUG_OBJECT (jitterbuffer, "removing RTCP sink pad");
-
-  gst_pad_set_active (priv->rtcpsinkpad, FALSE);
-
-  gst_element_remove_pad (GST_ELEMENT_CAST (jitterbuffer), priv->rtcpsinkpad);
-  priv->rtcpsinkpad = NULL;
-}
-
-static GstPad *
-gst_wfd_rtp_buffer_request_new_pad (GstElement * element,
-    GstPadTemplate * templ, const gchar * name, const GstCaps * filter)
-{
-  GstWfdRTPBuffer *jitterbuffer;
-  GstElementClass *klass;
-  GstPad *result;
-  GstWfdRTPBufferPrivate *priv;
-
-  g_return_val_if_fail (templ != NULL, NULL);
-  g_return_val_if_fail (GST_IS_WFD_RTP_BUFFER (element), NULL);
-
-  jitterbuffer = GST_WFD_RTP_BUFFER_CAST (element);
-  priv = jitterbuffer->priv;
-  klass = GST_ELEMENT_GET_CLASS (element);
-
-  GST_DEBUG_OBJECT (element, "requesting pad %s", GST_STR_NULL (name));
-
-  /* figure out the template */
-  if (templ == gst_element_class_get_pad_template (klass, "sink_rtcp")) {
-    if (priv->rtcpsinkpad != NULL)
-      goto exists;
-
-    result = create_rtcp_sink (jitterbuffer);
-  } else
-    goto wrong_template;
-
-  return result;
-
-  /* ERRORS */
-wrong_template:
-  {
-    g_warning ("wfdrtpbuffer: this is not our template");
-    return NULL;
-  }
-exists:
-  {
-    g_warning ("wfdrtpbuffer: pad already requested");
-    return NULL;
-  }
-}
-
-static void
-gst_wfd_rtp_buffer_release_pad (GstElement * element, GstPad * pad)
-{
-  GstWfdRTPBuffer *jitterbuffer;
-  GstWfdRTPBufferPrivate *priv;
-
-  g_return_if_fail (GST_IS_WFD_RTP_BUFFER (element));
-  g_return_if_fail (GST_IS_PAD (pad));
-
-  jitterbuffer = GST_WFD_RTP_BUFFER_CAST (element);
-  priv = jitterbuffer->priv;
-
-  GST_DEBUG_OBJECT (element, "releasing pad %s:%s", GST_DEBUG_PAD_NAME (pad));
-
-  if (priv->rtcpsinkpad == pad) {
-    remove_rtcp_sink (jitterbuffer);
-  } else
-    goto wrong_pad;
-
-  return;
-
-  /* ERRORS */
-wrong_pad:
-  {
-    g_warning ("wfdrtpbuffer: asked to release an unknown pad");
-    return;
-  }
-}
-
-static GstClock *
-gst_wfd_rtp_buffer_provide_clock (GstElement * element)
-{
-  return gst_system_clock_obtain ();
-}
-
-static void
-gst_wfd_rtp_buffer_clear_pt_map (GstWfdRTPBuffer * jitterbuffer)
-{
-  GstWfdRTPBufferPrivate *priv;
-
-  priv = jitterbuffer->priv;
-
-  /* this will trigger a new pt-map request signal, FIXME, do something better. */
-
-  JBUF_LOCK (priv);
-  priv->clock_rate = -1;
-  /* do not clear current content, but refresh state for new arrival */
-  GST_DEBUG_OBJECT (jitterbuffer, "reset jitterbuffer");
-  wfd_rtp_buffer_reset_skew (priv->jbuf);
-  JBUF_UNLOCK (priv);
-}
-
-static GstClockTime
-gst_wfd_rtp_buffer_set_active (GstWfdRTPBuffer * jbuf, gboolean active,
-    guint64 offset)
-{
-  GstWfdRTPBufferPrivate *priv;
-  GstClockTime last_out;
-  WfdRTPBufferItem *item;
-
-  priv = jbuf->priv;
-
-  JBUF_LOCK (priv);
-  GST_DEBUG_OBJECT (jbuf, "setting active %d with offset %" GST_TIME_FORMAT,
-      active, GST_TIME_ARGS (offset));
-
-  if (active != priv->active) {
-    /* add the amount of time spent in paused to the output offset. All
-     * outgoing buffers will have this offset applied to their timestamps in
-     * order to make them arrive in time in the sink. */
-    priv->out_offset = offset;
-    GST_DEBUG_OBJECT (jbuf, "out offset %" GST_TIME_FORMAT,
-        GST_TIME_ARGS (priv->out_offset));
-    priv->active = active;
-    JBUF_SIGNAL_EVENT (priv);
-  }
-  if (!active) {
-    wfd_rtp_buffer_set_buffering (priv->jbuf, TRUE);
-  }
-  if ((item = wfd_rtp_buffer_peek (priv->jbuf))) {
-    /* head buffer timestamp and offset gives our output time */
-    last_out = item->dts + priv->ts_offset;
-  } else {
-    /* use last known time when the buffer is empty */
-    last_out = priv->last_out_time;
-  }
-  JBUF_UNLOCK (priv);
-
-  return last_out;
-}
-
-static GstCaps *
-gst_wfd_rtp_buffer_getcaps (GstPad * pad, GstCaps * filter)
-{
-  GstWfdRTPBuffer *jitterbuffer;
-  GstWfdRTPBufferPrivate *priv;
-  GstPad *other;
-  GstCaps *caps;
-  GstCaps *templ;
-
-  jitterbuffer = GST_WFD_RTP_BUFFER (gst_pad_get_parent (pad));
-  priv = jitterbuffer->priv;
-
-  other = (pad == priv->srcpad ? priv->sinkpad : priv->srcpad);
-
-  caps = gst_pad_peer_query_caps (other, filter);
-
-  templ = gst_pad_get_pad_template_caps (pad);
-  if (caps == NULL) {
-    GST_DEBUG_OBJECT (jitterbuffer, "use template");
-    caps = templ;
-  } else {
-    GstCaps *intersect;
-
-    GST_DEBUG_OBJECT (jitterbuffer, "intersect with template");
-
-    intersect = gst_caps_intersect (caps, templ);
-    gst_caps_unref (caps);
-    gst_caps_unref (templ);
-
-    caps = intersect;
-  }
-  gst_object_unref (jitterbuffer);
-
-  return caps;
-}
-
-/*
- * Must be called with JBUF_LOCK held
- */
-
-static gboolean
-gst_wfd_rtp_buffer_sink_parse_caps (GstWfdRTPBuffer * jitterbuffer,
-    GstCaps * caps)
-{
-  GstWfdRTPBufferPrivate *priv;
-  GstStructure *caps_struct;
-  guint val;
-  GstClockTime tval;
-
-  priv = jitterbuffer->priv;
-
-  /* first parse the caps */
-  caps_struct = gst_caps_get_structure (caps, 0);
-
-  GST_DEBUG_OBJECT (jitterbuffer, "got caps");
-
-  /* we need a clock-rate to convert the rtp timestamps to GStreamer time and to
-   * measure the amount of data in the buffer */
-  if (!gst_structure_get_int (caps_struct, "clock-rate", &priv->clock_rate))
-    goto error;
-
-  if (priv->clock_rate <= 0)
-    goto wrong_rate;
-
-  GST_DEBUG_OBJECT (jitterbuffer, "got clock-rate %d", priv->clock_rate);
-
-  wfd_rtp_buffer_set_clock_rate (priv->jbuf, priv->clock_rate);
-
-  /* The clock base is the RTP timestamp corrsponding to the npt-start value. We
-   * can use this to track the amount of time elapsed on the sender. */
-  if (gst_structure_get_uint (caps_struct, "clock-base", &val))
-    priv->clock_base = val;
-  else
-    priv->clock_base = -1;
-
-  priv->ext_timestamp = priv->clock_base;
-
-  GST_DEBUG_OBJECT (jitterbuffer, "got clock-base %" G_GINT64_FORMAT,
-      priv->clock_base);
-
-  if (gst_structure_get_uint (caps_struct, "seqnum-base", &val)) {
-    /* first expected seqnum, only update when we didn't have a previous base. */
-    if (priv->next_in_seqnum == -1)
-      priv->next_in_seqnum = val;
-    if (priv->next_seqnum == -1) {
-      priv->next_seqnum = val;
-      JBUF_SIGNAL_EVENT (priv);
-    }
-  }
-
-  GST_DEBUG_OBJECT (jitterbuffer, "got seqnum-base %d", priv->next_in_seqnum);
-
-  /* the start and stop times. The seqnum-base corresponds to the start time. We
-   * will keep track of the seqnums on the output and when we reach the one
-   * corresponding to npt-stop, we emit the npt-stop-reached signal */
-  if (gst_structure_get_clock_time (caps_struct, "npt-start", &tval))
-    priv->npt_start = tval;
-  else
-    priv->npt_start = 0;
-
-  if (gst_structure_get_clock_time (caps_struct, "npt-stop", &tval))
-    priv->npt_stop = tval;
-  else
-    priv->npt_stop = -1;
-
-  GST_DEBUG_OBJECT (jitterbuffer,
-      "npt start/stop: %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
-      GST_TIME_ARGS (priv->npt_start), GST_TIME_ARGS (priv->npt_stop));
-
-  return TRUE;
-
-  /* ERRORS */
-error:
-  {
-    GST_DEBUG_OBJECT (jitterbuffer, "No clock-rate in caps!");
-    return FALSE;
-  }
-wrong_rate:
-  {
-    GST_DEBUG_OBJECT (jitterbuffer, "Invalid clock-rate %d", priv->clock_rate);
-    return FALSE;
-  }
-}
-
-static void
-gst_wfd_rtp_buffer_flush_start (GstWfdRTPBuffer * jitterbuffer)
-{
-  GstWfdRTPBufferPrivate *priv;
-
-  priv = jitterbuffer->priv;
-
-  JBUF_LOCK (priv);
-  /* mark ourselves as flushing */
-  priv->srcresult = GST_FLOW_FLUSHING;
-  GST_DEBUG_OBJECT (jitterbuffer, "Disabling pop on queue");
-  /* this unblocks any waiting pops on the src pad task */
-  JBUF_SIGNAL_EVENT (priv);
-  JBUF_SIGNAL_QUERY (priv, FALSE);
-  JBUF_UNLOCK (priv);
-}
-
-static void
-gst_wfd_rtp_buffer_flush_stop (GstWfdRTPBuffer * jitterbuffer)
-{
-  GstWfdRTPBufferPrivate *priv;
-
-  priv = jitterbuffer->priv;
-
-  JBUF_LOCK (priv);
-  GST_DEBUG_OBJECT (jitterbuffer, "Enabling pop on queue");
-  /* Mark as non flushing */
-  priv->srcresult = GST_FLOW_OK;
-  gst_segment_init (&priv->segment, GST_FORMAT_TIME);
-  priv->last_popped_seqnum = -1;
-  priv->last_out_time = -1;
-  priv->next_seqnum = -1;
-  priv->ips_rtptime = -1;
-  priv->ips_dts = GST_CLOCK_TIME_NONE;
-  priv->packet_spacing = 0;
-  priv->next_in_seqnum = -1;
-  priv->clock_rate = -1;
-  priv->last_pt = -1;
-  priv->eos = FALSE;
-  priv->estimated_eos = -1;
-  priv->last_elapsed = 0;
-  priv->ext_timestamp = -1;
-  priv->avg_jitter = 0;
-  priv->last_dts = -1;
-  priv->last_rtptime = -1;
-  GST_DEBUG_OBJECT (jitterbuffer, "flush and reset jitterbuffer");
-  wfd_rtp_buffer_flush (priv->jbuf, (GFunc) free_item, NULL);
-  wfd_rtp_buffer_disable_buffering (priv->jbuf, FALSE);
-  wfd_rtp_buffer_reset_skew (priv->jbuf);
-  remove_all_timers (jitterbuffer);
-  JBUF_UNLOCK (priv);
-}
-
-static gboolean
-gst_wfd_rtp_buffer_src_activate_mode (GstPad * pad, GstObject * parent,
-    GstPadMode mode, gboolean active)
-{
-  gboolean result;
-  GstWfdRTPBuffer *jitterbuffer = NULL;
-
-  jitterbuffer = GST_WFD_RTP_BUFFER (parent);
-
-  switch (mode) {
-    case GST_PAD_MODE_PUSH:
-      if (active) {
-        /* allow data processing */
-        gst_wfd_rtp_buffer_flush_stop (jitterbuffer);
-
-        /* start pushing out buffers */
-        GST_DEBUG_OBJECT (jitterbuffer, "Starting task on srcpad");
-        result = gst_pad_start_task (jitterbuffer->priv->srcpad,
-            (GstTaskFunction) gst_wfd_rtp_buffer_loop, jitterbuffer, NULL);
-      } else {
-        /* make sure all data processing stops ASAP */
-        gst_wfd_rtp_buffer_flush_start (jitterbuffer);
-
-        /* NOTE this will hardlock if the state change is called from the src pad
-         * task thread because we will _join() the thread. */
-        GST_DEBUG_OBJECT (jitterbuffer, "Stopping task on srcpad");
-        result = gst_pad_stop_task (pad);
-      }
-      break;
-    default:
-      result = FALSE;
-      break;
-  }
-  return result;
-}
-
-static GstStateChangeReturn
-gst_wfd_rtp_buffer_change_state (GstElement * element,
-    GstStateChange transition)
-{
-  GstWfdRTPBuffer *jitterbuffer;
-  GstWfdRTPBufferPrivate *priv;
-  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
-
-  jitterbuffer = GST_WFD_RTP_BUFFER (element);
-  priv = jitterbuffer->priv;
-
-  switch (transition) {
-    case GST_STATE_CHANGE_NULL_TO_READY:
-      break;
-    case GST_STATE_CHANGE_READY_TO_PAUSED:
-      JBUF_LOCK (priv);
-      /* reset negotiated values */
-      priv->clock_rate = -1;
-      priv->clock_base = -1;
-      priv->peer_latency = 0;
-      priv->last_pt = -1;
-      /* block until we go to PLAYING */
-      priv->blocked = TRUE;
-      priv->timer_running = TRUE;
-      priv->timer_thread =
-          g_thread_new ("timer", (GThreadFunc) wait_next_timeout, jitterbuffer);
-      JBUF_UNLOCK (priv);
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
-      JBUF_LOCK (priv);
-      /* unblock to allow streaming in PLAYING */
-      priv->blocked = FALSE;
-      JBUF_SIGNAL_EVENT (priv);
-      JBUF_SIGNAL_TIMER (priv);
-      JBUF_UNLOCK (priv);
-      break;
-    default:
-      break;
-  }
-
-  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
-  switch (transition) {
-    case GST_STATE_CHANGE_READY_TO_PAUSED:
-      /* we are a live element because we sync to the clock, which we can only
-       * do in the PLAYING state */
-      if (ret != GST_STATE_CHANGE_FAILURE)
-        ret = GST_STATE_CHANGE_NO_PREROLL;
-      break;
-    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
-      JBUF_LOCK (priv);
-      /* block to stop streaming when PAUSED */
-      priv->blocked = TRUE;
-      unschedule_current_timer (jitterbuffer);
-      JBUF_UNLOCK (priv);
-      if (ret != GST_STATE_CHANGE_FAILURE)
-        ret = GST_STATE_CHANGE_NO_PREROLL;
-      break;
-    case GST_STATE_CHANGE_PAUSED_TO_READY:
-      JBUF_LOCK (priv);
-      gst_buffer_replace (&priv->last_sr, NULL);
-      priv->timer_running = FALSE;
-      unschedule_current_timer (jitterbuffer);
-      JBUF_SIGNAL_TIMER (priv);
-      JBUF_SIGNAL_QUERY (priv, FALSE);
-      JBUF_UNLOCK (priv);
-      g_thread_join (priv->timer_thread);
-      priv->timer_thread = NULL;
-      break;
-    case GST_STATE_CHANGE_READY_TO_NULL:
-      break;
-    default:
-      break;
-  }
-
-  return ret;
-}
-
-static gboolean
-gst_wfd_rtp_buffer_src_event (GstPad * pad, GstObject * parent,
-    GstEvent * event)
-{
-  gboolean ret = TRUE;
-  GstWfdRTPBuffer *jitterbuffer;
-  GstWfdRTPBufferPrivate *priv;
-
-  jitterbuffer = GST_WFD_RTP_BUFFER_CAST (parent);
-  priv = jitterbuffer->priv;
-
-  GST_DEBUG_OBJECT (jitterbuffer, "received %s", GST_EVENT_TYPE_NAME (event));
-
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_LATENCY:
-    {
-      GstClockTime latency;
-
-      gst_event_parse_latency (event, &latency);
-
-      GST_DEBUG_OBJECT (jitterbuffer,
-          "configuring latency of %" GST_TIME_FORMAT, GST_TIME_ARGS (latency));
-
-      JBUF_LOCK (priv);
-      /* adjust the overall buffer delay to the total pipeline latency in
-       * buffering mode because if downstream consumes too fast (because of
-       * large latency or queues, we would start rebuffering again. */
-      if (wfd_rtp_buffer_get_mode (priv->jbuf) ==
-          WFD_RTP_BUFFER_MODE_BUFFER) {
-        wfd_rtp_buffer_set_delay (priv->jbuf, latency);
-      }
-      JBUF_UNLOCK (priv);
-
-      ret = gst_pad_push_event (priv->sinkpad, event);
-      break;
-    }
-    default:
-      ret = gst_pad_push_event (priv->sinkpad, event);
-      break;
-  }
-
-  return ret;
-}
-
-/* handles and stores the event in the jitterbuffer, must be called with
- * LOCK */
-static gboolean
-queue_event (GstWfdRTPBuffer * jitterbuffer, GstEvent * event)
-{
-  GstWfdRTPBufferPrivate *priv = jitterbuffer->priv;
-  WfdRTPBufferItem *item;
-  gboolean head;
-
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_CAPS:
-    {
-      GstCaps *caps;
-
-      gst_event_parse_caps (event, &caps);
-      if (!gst_wfd_rtp_buffer_sink_parse_caps (jitterbuffer, caps))
-        goto wrong_caps;
-
-      break;
-    }
-    case GST_EVENT_SEGMENT:
-      gst_event_copy_segment (event, &priv->segment);
-
-      /* we need time for now */
-      if (priv->segment.format != GST_FORMAT_TIME)
-        goto newseg_wrong_format;
-
-      GST_DEBUG_OBJECT (jitterbuffer,
-          "newsegment:  %" GST_SEGMENT_FORMAT, &priv->segment);
-      break;
-    case GST_EVENT_EOS:
-      priv->eos = TRUE;
-      wfd_rtp_buffer_disable_buffering (priv->jbuf, TRUE);
-      break;
-    default:
-      break;
-  }
-
-
-  GST_DEBUG_OBJECT (jitterbuffer, "adding event");
-  item = alloc_item (event, ITEM_TYPE_EVENT, -1, -1, -1, 0, -1);
-  wfd_rtp_buffer_insert (priv->jbuf, item, &head, NULL);
-  if (head)
-    JBUF_SIGNAL_EVENT (priv);
-
-  return TRUE;
-
-  /* ERRORS */
-wrong_caps:
-  {
-    GST_DEBUG_OBJECT (jitterbuffer, "received invalid caps");
-    gst_event_unref (event);
-    return FALSE;
-  }
-newseg_wrong_format:
-  {
-    GST_DEBUG_OBJECT (jitterbuffer, "received non TIME newsegment");
-    gst_event_unref (event);
-    return FALSE;
-  }
-}
-
-static gboolean
-gst_wfd_rtp_buffer_sink_event (GstPad * pad, GstObject * parent,
-    GstEvent * event)
-{
-  gboolean ret = TRUE;
-  GstWfdRTPBuffer *jitterbuffer;
-  GstWfdRTPBufferPrivate *priv;
-
-  jitterbuffer = GST_WFD_RTP_BUFFER (parent);
-  priv = jitterbuffer->priv;
-
-  GST_DEBUG_OBJECT (jitterbuffer, "received %s", GST_EVENT_TYPE_NAME (event));
-
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_FLUSH_START:
-      ret = gst_pad_push_event (priv->srcpad, event);
-      gst_wfd_rtp_buffer_flush_start (jitterbuffer);
-      /* wait for the loop to go into PAUSED */
-      gst_pad_pause_task (priv->srcpad);
-      break;
-    case GST_EVENT_FLUSH_STOP:
-      ret = gst_pad_push_event (priv->srcpad, event);
-      ret =
-          gst_wfd_rtp_buffer_src_activate_mode (priv->srcpad, parent,
-          GST_PAD_MODE_PUSH, TRUE);
-      break;
-    default:
-      if (GST_EVENT_IS_SERIALIZED (event)) {
-        /* serialized events go in the queue */
-        JBUF_LOCK (priv);
-        if (priv->srcresult != GST_FLOW_OK) {
-          /* Errors in sticky event pushing are no problem and ignored here
-           * as they will cause more meaningful errors during data flow.
-           * For EOS events, that are not followed by data flow, we still
-           * return FALSE here though.
-           */
-          if (!GST_EVENT_IS_STICKY (event) ||
-              GST_EVENT_TYPE (event) == GST_EVENT_EOS)
-            goto out_flow_error;
-        }
-        /* refuse more events on EOS */
-        if (priv->eos)
-          goto out_eos;
-        ret = queue_event (jitterbuffer, event);
-        JBUF_UNLOCK (priv);
-      } else {
-        /* non-serialized events are forwarded downstream immediately */
-        ret = gst_pad_push_event (priv->srcpad, event);
-      }
-      break;
-  }
-  return ret;
-
-  /* ERRORS */
-out_flow_error:
-  {
-    GST_DEBUG_OBJECT (jitterbuffer,
-        "refusing event, we have a downstream flow error: %s",
-        gst_flow_get_name (priv->srcresult));
-    JBUF_UNLOCK (priv);
-    gst_event_unref (event);
-    return FALSE;
-  }
-out_eos:
-  {
-    GST_DEBUG_OBJECT (jitterbuffer, "refusing event, we are EOS");
-    JBUF_UNLOCK (priv);
-    gst_event_unref (event);
-    return FALSE;
-  }
-}
-
-static gboolean
-gst_wfd_rtp_buffer_sink_rtcp_event (GstPad * pad, GstObject * parent,
-    GstEvent * event)
-{
-  gboolean ret = TRUE;
-  GstWfdRTPBuffer *jitterbuffer;
-
-  jitterbuffer = GST_WFD_RTP_BUFFER (parent);
-
-  GST_DEBUG_OBJECT (jitterbuffer, "received %s", GST_EVENT_TYPE_NAME (event));
-
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_FLUSH_START:
-      gst_event_unref (event);
-      break;
-    case GST_EVENT_FLUSH_STOP:
-      gst_event_unref (event);
-      break;
-    default:
-      ret = gst_pad_event_default (pad, parent, event);
-      break;
-  }
-
-  return ret;
-}
-
-/*
- * Must be called with JBUF_LOCK held, will release the LOCK when emiting the
- * signal. The function returns GST_FLOW_ERROR when a parsing error happened and
- * GST_FLOW_FLUSHING when the element is shutting down. On success
- * GST_FLOW_OK is returned.
- */
-static GstFlowReturn
-gst_wfd_rtp_buffer_get_clock_rate (GstWfdRTPBuffer * jitterbuffer,
-    guint8 pt)
-{
-  GValue ret = { 0 };
-  GValue args[2] = { {0}, {0} };
-  GstCaps *caps;
-  gboolean res;
-
-  g_value_init (&args[0], GST_TYPE_ELEMENT);
-  g_value_set_object (&args[0], jitterbuffer);
-  g_value_init (&args[1], G_TYPE_UINT);
-  g_value_set_uint (&args[1], pt);
-
-  g_value_init (&ret, GST_TYPE_CAPS);
-  g_value_set_boxed (&ret, NULL);
-
-  JBUF_UNLOCK (jitterbuffer->priv);
-  g_signal_emitv (args, gst_wfd_rtp_buffer_signals[SIGNAL_REQUEST_PT_MAP], 0,
-      &ret);
-  JBUF_LOCK_CHECK (jitterbuffer->priv, out_flushing);
-
-  g_value_unset (&args[0]);
-  g_value_unset (&args[1]);
-  caps = (GstCaps *) g_value_dup_boxed (&ret);
-  g_value_unset (&ret);
-  if (!caps)
-    goto no_caps;
-
-  res = gst_wfd_rtp_buffer_sink_parse_caps (jitterbuffer, caps);
-  gst_caps_unref (caps);
-
-  if (G_UNLIKELY (!res))
-    goto parse_failed;
-
-  return GST_FLOW_OK;
-
-  /* ERRORS */
-no_caps:
-  {
-    GST_DEBUG_OBJECT (jitterbuffer, "could not get caps");
-    return GST_FLOW_ERROR;
-  }
-out_flushing:
-  {
-    GST_DEBUG_OBJECT (jitterbuffer, "we are flushing");
-    return GST_FLOW_FLUSHING;
-  }
-parse_failed:
-  {
-    GST_DEBUG_OBJECT (jitterbuffer, "parse failed");
-    return GST_FLOW_ERROR;
-  }
-}
-
-/* call with jbuf lock held */
-static GstMessage *
-check_buffering_percent (GstWfdRTPBuffer * jitterbuffer, gint percent)
-{
-  GstWfdRTPBufferPrivate *priv = jitterbuffer->priv;
-  GstMessage *message = NULL;
-
-  if (percent == -1)
-    return NULL;
-
-  /* Post a buffering message */
-  if (priv->last_percent != percent) {
-    priv->last_percent = percent;
-    message =
-        gst_message_new_buffering (GST_OBJECT_CAST (jitterbuffer), percent);
-    gst_message_set_buffering_stats (message, GST_BUFFERING_LIVE, -1, -1, -1);
-  }
-
-  return message;
-}
-
-static GstClockTime
-apply_offset (GstWfdRTPBuffer * jitterbuffer, GstClockTime timestamp)
-{
-  GstWfdRTPBufferPrivate *priv;
-
-  priv = jitterbuffer->priv;
-
-  if (timestamp == -1)
-    return -1;
-
-  /* apply the timestamp offset, this is used for inter stream sync */
-  timestamp += priv->ts_offset;
-  /* add the offset, this is used when buffering */
-  timestamp += priv->out_offset;
-
-  return timestamp;
-}
-
-static TimerData *
-find_timer (GstWfdRTPBuffer * jitterbuffer, TimerType type, guint16 seqnum)
-{
-  GstWfdRTPBufferPrivate *priv = jitterbuffer->priv;
-  TimerData *timer = NULL;
-  gint i, len;
-
-  len = priv->timers->len;
-  for (i = 0; i < len; i++) {
-    TimerData *test = &g_array_index (priv->timers, TimerData, i);
-    if (test->seqnum == seqnum && test->type == type) {
-      timer = test;
-      break;
-    }
-  }
-  return timer;
-}
-
-static void
-unschedule_current_timer (GstWfdRTPBuffer * jitterbuffer)
-{
-  GstWfdRTPBufferPrivate *priv = jitterbuffer->priv;
-
-  if (priv->clock_id) {
-    GST_DEBUG_OBJECT (jitterbuffer, "unschedule current timer");
-    gst_clock_id_unschedule (priv->clock_id);
-    priv->clock_id = NULL;
-  }
-}
-
-static GstClockTime
-get_timeout (GstWfdRTPBuffer * jitterbuffer, TimerData * timer)
-{
-  GstWfdRTPBufferPrivate *priv = jitterbuffer->priv;
-  GstClockTime test_timeout;
-
-  if ((test_timeout = timer->timeout) == -1)
-    return -1;
-
-  if (timer->type != TIMER_TYPE_EXPECTED) {
-    /* add our latency and offset to get output times. */
-    test_timeout = apply_offset (jitterbuffer, test_timeout);
-    test_timeout += priv->latency_ns;
-  }
-  return test_timeout;
-}
-
-static void
-recalculate_timer (GstWfdRTPBuffer * jitterbuffer, TimerData * timer)
-{
-  GstWfdRTPBufferPrivate *priv = jitterbuffer->priv;
-
-  if (priv->clock_id) {
-    GstClockTime timeout = get_timeout (jitterbuffer, timer);
-
-    GST_DEBUG ("%" GST_TIME_FORMAT " <> %" GST_TIME_FORMAT,
-        GST_TIME_ARGS (timeout), GST_TIME_ARGS (priv->timer_timeout));
-
-    if (timeout == -1 || timeout < priv->timer_timeout)
-      unschedule_current_timer (jitterbuffer);
-  }
-}
-
-static TimerData *
-add_timer (GstWfdRTPBuffer * jitterbuffer, TimerType type,
-    guint16 seqnum, guint num, GstClockTime timeout, GstClockTime delay,
-    GstClockTime duration)
-{
-  GstWfdRTPBufferPrivate *priv = jitterbuffer->priv;
-  TimerData *timer;
-  gint len;
-
-  GST_DEBUG_OBJECT (jitterbuffer,
-      "add timer %d for seqnum %d to %" GST_TIME_FORMAT ", delay %"
-      GST_TIME_FORMAT, type, seqnum, GST_TIME_ARGS (timeout),
-      GST_TIME_ARGS (delay));
-
-  len = priv->timers->len;
-  g_array_set_size (priv->timers, len + 1);
-  timer = &g_array_index (priv->timers, TimerData, len);
-  timer->idx = len;
-  timer->type = type;
-  timer->seqnum = seqnum;
-  timer->num = num;
-  timer->timeout = timeout + delay;
-  timer->duration = duration;
-  if (type == TIMER_TYPE_EXPECTED) {
-    timer->rtx_base = timeout;
-    timer->rtx_delay = delay;
-    timer->rtx_retry = 0;
-  }
-  timer->num_rtx_retry = 0;
-  recalculate_timer (jitterbuffer, timer);
-  JBUF_SIGNAL_TIMER (priv);
-
-  return timer;
-}
-
-static void
-reschedule_timer (GstWfdRTPBuffer * jitterbuffer, TimerData * timer,
-    guint16 seqnum, GstClockTime timeout, GstClockTime delay, gboolean reset)
-{
-  GstWfdRTPBufferPrivate *priv = jitterbuffer->priv;
-  gboolean seqchange, timechange;
-  guint16 oldseq;
-
-  seqchange = timer->seqnum != seqnum;
-  timechange = timer->timeout != timeout;
-
-  if (!seqchange && !timechange)
-    return;
-
-  oldseq = timer->seqnum;
-
-  GST_DEBUG_OBJECT (jitterbuffer,
-      "replace timer for seqnum %d->%d to %" GST_TIME_FORMAT,
-      oldseq, seqnum, GST_TIME_ARGS (timeout + delay));
-
-  timer->timeout = timeout + delay;
-  timer->seqnum = seqnum;
-  if (reset) {
-    timer->rtx_base = timeout;
-    timer->rtx_delay = delay;
-    timer->rtx_retry = 0;
-  }
-  if (seqchange)
-    timer->num_rtx_retry = 0;
-
-  if (priv->clock_id) {
-    /* we changed the seqnum and there is a timer currently waiting with this
-     * seqnum, unschedule it */
-    if (seqchange && priv->timer_seqnum == oldseq)
-      unschedule_current_timer (jitterbuffer);
-    /* we changed the time, check if it is earlier than what we are waiting
-     * for and unschedule if so */
-    else if (timechange)
-      recalculate_timer (jitterbuffer, timer);
-  }
-}
-
-static TimerData *
-set_timer (GstWfdRTPBuffer * jitterbuffer, TimerType type,
-    guint16 seqnum, GstClockTime timeout)
-{
-  TimerData *timer;
-
-  /* find the seqnum timer */
-  timer = find_timer (jitterbuffer, type, seqnum);
-  if (timer == NULL) {
-    timer = add_timer (jitterbuffer, type, seqnum, 0, timeout, 0, -1);
-  } else {
-    reschedule_timer (jitterbuffer, timer, seqnum, timeout, 0, FALSE);
-  }
-  return timer;
-}
-
-static void
-remove_timer (GstWfdRTPBuffer * jitterbuffer, TimerData * timer)
-{
-  GstWfdRTPBufferPrivate *priv = jitterbuffer->priv;
-  guint idx;
-
-  if (priv->clock_id && priv->timer_seqnum == timer->seqnum)
-    unschedule_current_timer (jitterbuffer);
-
-  idx = timer->idx;
-  GST_DEBUG_OBJECT (jitterbuffer, "removed index %d", idx);
-  g_array_remove_index_fast (priv->timers, idx);
-  timer->idx = idx;
-}
-
-static void
-remove_all_timers (GstWfdRTPBuffer * jitterbuffer)
-{
-  GstWfdRTPBufferPrivate *priv = jitterbuffer->priv;
-  GST_DEBUG_OBJECT (jitterbuffer, "removed all timers");
-  g_array_set_size (priv->timers, 0);
-  unschedule_current_timer (jitterbuffer);
-}
-
-/* we just received a packet with seqnum and dts.
- *
- * First check for old seqnum that we are still expecting. If the gap with the
- * current seqnum is too big, unschedule the timeouts.
- *
- * If we have a valid packet spacing estimate we can set a timer for when we
- * should receive the next packet.
- * If we don't have a valid estimate, we remove any timer we might have
- * had for this packet.
- */
-static void
-update_timers (GstWfdRTPBuffer * jitterbuffer, guint16 seqnum,
-    GstClockTime dts, gboolean do_next_seqnum)
-{
-  GstWfdRTPBufferPrivate *priv = jitterbuffer->priv;
-  TimerData *timer = NULL;
-  gint i, len;
-
-  /* go through all timers and unschedule the ones with a large gap, also find
-   * the timer for the seqnum */
-  len = priv->timers->len;
-  for (i = 0; i < len; i++) {
-    TimerData *test = &g_array_index (priv->timers, TimerData, i);
-    gint gap;
-
-    gap = gst_rtp_buffer_compare_seqnum (test->seqnum, seqnum);
-
-    GST_DEBUG_OBJECT (jitterbuffer, "%d, %d, #%d<->#%d gap %d", i,
-        test->type, test->seqnum, seqnum, gap);
-
-    if (gap == 0) {
-      GST_DEBUG ("found timer for current seqnum");
-      /* the timer for the current seqnum */
-      timer = test;
-      /* when no retransmission, we can stop now, we only need to find the
-       * timer for the current seqnum */
-      if (!priv->do_retransmission)
-        break;
-    } else if (gap > priv->rtx_delay_reorder) {
-      /* max gap, we exceeded the max reorder distance and we don't expect the
-       * missing packet to be this reordered */
-      if (test->num_rtx_retry == 0 && test->type == TIMER_TYPE_EXPECTED)
-        reschedule_timer (jitterbuffer, test, test->seqnum, -1, 0, FALSE);
-    }
-  }
-
-  do_next_seqnum = do_next_seqnum && priv->packet_spacing > 0
-      && priv->do_retransmission;
-
-  if (timer && timer->type != TIMER_TYPE_DEADLINE) {
-    if (timer->num_rtx_retry > 0) {
-      GstClockTime rtx_last, delay;
-
-      /* we scheduled a retry for this packet and now we have it */
-      priv->num_rtx_success++;
-      /* all the previous retry attempts failed */
-      priv->num_rtx_failed += timer->num_rtx_retry - 1;
-      /* number of retries before receiving the packet */
-      if (priv->avg_rtx_num == 0.0)
-        priv->avg_rtx_num = timer->num_rtx_retry;
-      else
-        priv->avg_rtx_num = (timer->num_rtx_retry + 7 * priv->avg_rtx_num) / 8;
-      /* calculate the delay between retransmission request and receiving this
-       * packet, start with when we scheduled this timeout last */
-      rtx_last = timer->rtx_last;
-      if (dts != GST_CLOCK_TIME_NONE && dts > rtx_last) {
-        /* we have a valid delay if this packet arrived after we scheduled the
-         * request */
-        delay = dts - rtx_last;
-        if (priv->avg_rtx_rtt == 0)
-          priv->avg_rtx_rtt = delay;
-        else
-          priv->avg_rtx_rtt = (delay + 7 * priv->avg_rtx_rtt) / 8;
-      } else
-        delay = 0;
-
-      GST_LOG_OBJECT (jitterbuffer,
-          "RTX success %" G_GUINT64_FORMAT ", failed %" G_GUINT64_FORMAT
-          ", requests %" G_GUINT64_FORMAT ", dups %" G_GUINT64_FORMAT
-          ", avg-num %g, delay %" GST_TIME_FORMAT ", avg-rtt %" GST_TIME_FORMAT,
-          priv->num_rtx_success, priv->num_rtx_failed, priv->num_rtx_requests,
-          priv->num_duplicates, priv->avg_rtx_num, GST_TIME_ARGS (delay),
-          GST_TIME_ARGS (priv->avg_rtx_rtt));
-
-      /* don't try to estimate the next seqnum because this is a retransmitted
-       * packet and it probably did not arrive with the expected packet
-       * spacing. */
-      do_next_seqnum = FALSE;
-    }
-  }
-
-  if (do_next_seqnum) {
-    GstClockTime expected, delay;
-
-    /* calculate expected arrival time of the next seqnum */
-    expected = dts + priv->packet_spacing;
-
-    if (priv->rtx_delay == -1) {
-      if (priv->avg_jitter == 0)
-        delay = DEFAULT_AUTO_RTX_DELAY;
-      else
-        /* jitter is in nanoseconds, 2x jitter is a good margin */
-        delay = priv->avg_jitter * 2;
-    } else {
-      delay = priv->rtx_delay * GST_MSECOND;
-    }
-
-    /* and update/install timer for next seqnum */
-    if (timer)
-      reschedule_timer (jitterbuffer, timer, priv->next_in_seqnum, expected,
-          delay, TRUE);
-    else
-      add_timer (jitterbuffer, TIMER_TYPE_EXPECTED, priv->next_in_seqnum, 0,
-          expected, delay, priv->packet_spacing);
-  } else if (timer && timer->type != TIMER_TYPE_DEADLINE) {
-    /* if we had a timer, remove it, we don't know when to expect the next
-     * packet. */
-    remove_timer (jitterbuffer, timer);
-  }
-}
-
-static void
-calculate_packet_spacing (GstWfdRTPBuffer * jitterbuffer, guint32 rtptime,
-    GstClockTime dts)
-{
-  GstWfdRTPBufferPrivate *priv = jitterbuffer->priv;
-
-  /* we need consecutive seqnums with a different
-   * rtptime to estimate the packet spacing. */
-  if (priv->ips_rtptime != rtptime) {
-    /* rtptime changed, check dts diff */
-    if (priv->ips_dts != -1 && dts != -1 && dts > priv->ips_dts) {
-      priv->packet_spacing = dts - priv->ips_dts;
-      GST_DEBUG_OBJECT (jitterbuffer,
-          "new packet spacing %" GST_TIME_FORMAT,
-          GST_TIME_ARGS (priv->packet_spacing));
-    }
-    priv->ips_rtptime = rtptime;
-    priv->ips_dts = dts;
-  }
-}
-
-static void
-calculate_expected (GstWfdRTPBuffer * jitterbuffer, guint32 expected,
-    guint16 seqnum, GstClockTime dts, gint gap)
-{
-  GstWfdRTPBufferPrivate *priv = jitterbuffer->priv;
-  GstClockTime total_duration, duration, expected_dts;
-  TimerType type;
-
-  GST_DEBUG_OBJECT (jitterbuffer,
-      "dts %" GST_TIME_FORMAT ", last %" GST_TIME_FORMAT,
-      GST_TIME_ARGS (dts), GST_TIME_ARGS (priv->last_in_dts));
-
-  /* the total duration spanned by the missing packets */
-  if (dts >= priv->last_in_dts)
-    total_duration = dts - priv->last_in_dts;
-  else
-    total_duration = 0;
-
-  /* interpolate between the current time and the last time based on
-   * number of packets we are missing, this is the estimated duration
-   * for the missing packet based on equidistant packet spacing. */
-  duration = total_duration / (gap + 1);
-
-  GST_DEBUG_OBJECT (jitterbuffer, "duration %" GST_TIME_FORMAT,
-      GST_TIME_ARGS (duration));
-
-  if (total_duration > priv->latency_ns) {
-    GstClockTime gap_time;
-    guint lost_packets;
-
-    gap_time = total_duration - priv->latency_ns;
-
-    if (duration > 0) {
-      lost_packets = gap_time / duration;
-      gap_time = lost_packets * duration;
-    } else {
-      lost_packets = gap;
-    }
-
-    /* too many lost packets, some of the missing packets are already
-     * too late and we can generate lost packet events for them. */
-    GST_DEBUG_OBJECT (jitterbuffer, "too many lost packets %" GST_TIME_FORMAT
-        " > %" GST_TIME_FORMAT ", consider %u lost",
-        GST_TIME_ARGS (total_duration), GST_TIME_ARGS (priv->latency_ns),
-        lost_packets);
-
-    /* this timer will fire immediately and the lost event will be pushed from
-     * the timer thread */
-    add_timer (jitterbuffer, TIMER_TYPE_LOST, expected, lost_packets,
-        priv->last_in_dts + duration, 0, gap_time);
-
-    expected += lost_packets;
-    priv->last_in_dts += gap_time;
-  }
-
-  expected_dts = priv->last_in_dts + duration;
-
-  if (priv->do_retransmission) {
-    TimerData *timer;
-
-    type = TIMER_TYPE_EXPECTED;
-    /* if we had a timer for the first missing packet, update it. */
-    if ((timer = find_timer (jitterbuffer, type, expected))) {
-      GstClockTime timeout = timer->timeout;
-
-      timer->duration = duration;
-      if (timeout > expected_dts) {
-        GstClockTime delay = timeout - expected_dts - timer->rtx_retry;
-        reschedule_timer (jitterbuffer, timer, timer->seqnum, expected_dts,
-            delay, TRUE);
-      }
-      expected++;
-      expected_dts += duration;
-    }
-  } else {
-    type = TIMER_TYPE_LOST;
-  }
-
-  while (gst_rtp_buffer_compare_seqnum (expected, seqnum) > 0) {
-    add_timer (jitterbuffer, type, expected, 0, expected_dts, 0, duration);
-    expected_dts += duration;
-    expected++;
-  }
-}
-
-static void
-calculate_jitter (GstWfdRTPBuffer * jitterbuffer, GstClockTime dts,
-    guint rtptime)
-{
-  gint32 rtpdiff;
-  GstClockTimeDiff dtsdiff, rtpdiffns, diff;
-  GstWfdRTPBufferPrivate *priv;
-
-  priv = jitterbuffer->priv;
-
-  if (G_UNLIKELY (dts == GST_CLOCK_TIME_NONE) || priv->clock_rate <= 0)
-    goto no_time;
-
-  if (priv->last_dts != -1)
-    dtsdiff = dts - priv->last_dts;
-  else
-    dtsdiff = 0;
-
-  if (priv->last_rtptime != -1)
-    rtpdiff = rtptime - (guint32) priv->last_rtptime;
-  else
-    rtpdiff = 0;
-
-  priv->last_dts = dts;
-  priv->last_rtptime = rtptime;
-
-  if (rtpdiff > 0)
-    rtpdiffns =
-        gst_util_uint64_scale_int (rtpdiff, GST_SECOND, priv->clock_rate);
-  else
-    rtpdiffns =
-        -gst_util_uint64_scale_int (-rtpdiff, GST_SECOND, priv->clock_rate);
-
-  diff = ABS (dtsdiff - rtpdiffns);
-
-  /* jitter is stored in nanoseconds */
-  priv->avg_jitter = (diff + (15 * priv->avg_jitter)) >> 4;
-
-  GST_LOG_OBJECT (jitterbuffer,
-      "dtsdiff %" GST_TIME_FORMAT " rtptime %" GST_TIME_FORMAT
-      ", clock-rate %d, diff %" GST_TIME_FORMAT ", jitter: %" GST_TIME_FORMAT,
-      GST_TIME_ARGS (dtsdiff), GST_TIME_ARGS (rtpdiffns), priv->clock_rate,
-      GST_TIME_ARGS (diff), GST_TIME_ARGS (priv->avg_jitter));
-
-  return;
-
-  /* ERRORS */
-no_time:
-  {
-    GST_DEBUG_OBJECT (jitterbuffer,
-        "no dts or no clock-rate, can't calculate jitter");
-    return;
-  }
-}
-
-static GstFlowReturn
-gst_wfd_rtp_buffer_chain (GstPad * pad, GstObject * parent,
-    GstBuffer * buffer)
-{
-  GstWfdRTPBuffer *jitterbuffer;
-  GstWfdRTPBufferPrivate *priv;
-  guint16 seqnum;
-  guint32 expected, rtptime;
-  GstFlowReturn ret = GST_FLOW_OK;
-  GstClockTime dts, pts;
-  guint64 latency_ts;
-  gboolean head;
-  gint percent = -1;
-  guint8 pt;
-  GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
-  gboolean do_next_seqnum = FALSE;
-  WfdRTPBufferItem *item;
-  GstMessage *msg = NULL;
-
-  jitterbuffer = GST_WFD_RTP_BUFFER_CAST (parent);
-
-  priv = jitterbuffer->priv;
-
-  if (G_UNLIKELY (!gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtp)))
-    goto invalid_buffer;
-
-  pt = gst_rtp_buffer_get_payload_type (&rtp);
-  seqnum = gst_rtp_buffer_get_seq (&rtp);
-  rtptime = gst_rtp_buffer_get_timestamp (&rtp);
-  gst_rtp_buffer_unmap (&rtp);
-
-  /* make sure we have PTS and DTS set */
-  pts = GST_BUFFER_PTS (buffer);
-  dts = GST_BUFFER_DTS (buffer);
-  if (dts == -1)
-    dts = pts;
-  else if (pts == -1)
-    pts = dts;
-
-  /* take the DTS of the buffer. This is the time when the packet was
-   * received and is used to calculate jitter and clock skew. We will adjust
-   * this DTS with the smoothed value after processing it in the
-   * jitterbuffer and assign it as the PTS. */
-  /* bring to running time */
-  dts = gst_segment_to_running_time (&priv->segment, GST_FORMAT_TIME, dts);
-
-  GST_DEBUG_OBJECT (jitterbuffer,
-      "Received packet #%d at time %" GST_TIME_FORMAT ", discont %d", seqnum,
-      GST_TIME_ARGS (dts), GST_BUFFER_IS_DISCONT (buffer));
-
-  JBUF_LOCK_CHECK (priv, out_flushing);
-
-  if (G_UNLIKELY (priv->last_pt != pt)) {
-    GstCaps *caps;
-
-    GST_DEBUG_OBJECT (jitterbuffer, "pt changed from %u to %u", priv->last_pt,
-        pt);
-
-    priv->last_pt = pt;
-    /* reset clock-rate so that we get a new one */
-    priv->clock_rate = -1;
-
-    /* Try to get the clock-rate from the caps first if we can. If there are no
-     * caps we must fire the signal to get the clock-rate. */
-    if ((caps = gst_pad_get_current_caps (pad))) {
-      gst_wfd_rtp_buffer_sink_parse_caps (jitterbuffer, caps);
-      gst_caps_unref (caps);
-    }
-  }
-
-  if (G_UNLIKELY (priv->clock_rate == -1)) {
-    /* no clock rate given on the caps, try to get one with the signal */
-    if (gst_wfd_rtp_buffer_get_clock_rate (jitterbuffer,
-            pt) == GST_FLOW_FLUSHING)
-      goto out_flushing;
-
-    if (G_UNLIKELY (priv->clock_rate == -1))
-      goto no_clock_rate;
-  }
-
-  /* don't accept more data on EOS */
-  if (G_UNLIKELY (priv->eos))
-    goto have_eos;
-
-  calculate_jitter (jitterbuffer, dts, rtptime);
-
-  expected = priv->next_in_seqnum;
-
-  /* now check against our expected seqnum */
-  if (G_LIKELY (expected != -1)) {
-    gint gap;
-
-    /* now calculate gap */
-    gap = gst_rtp_buffer_compare_seqnum (expected, seqnum);
-
-    GST_DEBUG_OBJECT (jitterbuffer, "expected #%d, got #%d, gap of %d",
-        expected, seqnum, gap);
-
-    if (G_LIKELY (gap == 0)) {
-      /* packet is expected */
-      calculate_packet_spacing (jitterbuffer, rtptime, dts);
-      do_next_seqnum = TRUE;
-    } else {
-      gboolean reset = FALSE;
-
-      if (gap < 0) {
-        /* we received an old packet */
-        if (G_UNLIKELY (gap < -RTP_MAX_MISORDER)) {
-          /* too old packet, reset */
-          GST_DEBUG_OBJECT (jitterbuffer, "reset: buffer too old %d < %d", gap,
-              -RTP_MAX_MISORDER);
-          reset = TRUE;
-        } else {
-          GST_DEBUG_OBJECT (jitterbuffer, "old packet received");
-        }
-      } else {
-        /* new packet, we are missing some packets */
-        if (G_UNLIKELY (gap > RTP_MAX_DROPOUT)) {
-          /* packet too far in future, reset */
-          GST_DEBUG_OBJECT (jitterbuffer, "reset: buffer too new %d > %d", gap,
-              RTP_MAX_DROPOUT);
-          reset = TRUE;
-        } else {
-          GST_DEBUG_OBJECT (jitterbuffer, "%d missing packets", gap);
-          /* fill in the gap with EXPECTED timers */
-          calculate_expected (jitterbuffer, expected, seqnum, dts, gap);
-
-          do_next_seqnum = TRUE;
-        }
-      }
-      if (G_UNLIKELY (reset)) {
-        GST_DEBUG_OBJECT (jitterbuffer, "flush and reset jitterbuffer");
-        wfd_rtp_buffer_flush (priv->jbuf, (GFunc) free_item, NULL);
-        wfd_rtp_buffer_reset_skew (priv->jbuf);
-        remove_all_timers (jitterbuffer);
-        priv->last_popped_seqnum = -1;
-        priv->next_seqnum = seqnum;
-        do_next_seqnum = TRUE;
-        JBUF_SIGNAL_EVENT (priv);
-      }
-      /* reset spacing estimation when gap */
-      priv->ips_rtptime = -1;
-      priv->ips_dts = GST_CLOCK_TIME_NONE;
-    }
-  } else {
-    GST_DEBUG_OBJECT (jitterbuffer, "First buffer #%d", seqnum);
-    /* we don't know what the next_in_seqnum should be, wait for the last
-     * possible moment to push this buffer, maybe we get an earlier seqnum
-     * while we wait */
-    set_timer (jitterbuffer, TIMER_TYPE_DEADLINE, seqnum, dts);
-    do_next_seqnum = TRUE;
-    /* take rtptime and dts to calculate packet spacing */
-    priv->ips_rtptime = rtptime;
-    priv->ips_dts = dts;
-  }
-  if (do_next_seqnum) {
-    priv->last_in_seqnum = seqnum;
-    priv->last_in_dts = dts;
-    priv->next_in_seqnum = (seqnum + 1) & 0xffff;
-  }
-
-  /* let's check if this buffer is too late, we can only accept packets with
-   * bigger seqnum than the one we last pushed. */
-  if (G_LIKELY (priv->last_popped_seqnum != -1)) {
-    gint gap;
-
-    gap = gst_rtp_buffer_compare_seqnum (priv->last_popped_seqnum, seqnum);
-
-    /* priv->last_popped_seqnum >= seqnum, we're too late. */
-    if (G_UNLIKELY (gap <= 0))
-      goto too_late;
-  }
-
-  /* let's drop oldest packet if the queue is already full and drop-on-latency
-   * is set. We can only do this when there actually is a latency. When no
-   * latency is set, we just pump it in the queue and let the other end push it
-   * out as fast as possible. */
-  if (priv->latency_ms && priv->drop_on_latency) {
-    latency_ts =
-        gst_util_uint64_scale_int (priv->latency_ms, priv->clock_rate, 1000);
-
-    if (G_UNLIKELY (wfd_rtp_buffer_get_ts_diff (priv->jbuf) >= latency_ts)) {
-      WfdRTPBufferItem *old_item;
-
-      old_item = wfd_rtp_buffer_peek (priv->jbuf);
-
-      if (IS_DROPABLE (old_item)) {
-        old_item = wfd_rtp_buffer_pop (priv->jbuf, &percent);
-        GST_DEBUG_OBJECT (jitterbuffer, "Queue full, dropping old packet %p",
-            old_item);
-        priv->next_seqnum = (old_item->seqnum + 1) & 0xffff;
-        free_item (old_item);
-      }
-      /* we might have removed some head buffers, signal the pushing thread to
-       * see if it can push now */
-      JBUF_SIGNAL_EVENT (priv);
-    }
-  }
-
-  item = alloc_item (buffer, ITEM_TYPE_BUFFER, dts, pts, seqnum, 1, rtptime);
-
-  /* now insert the packet into the queue in sorted order. This function returns
-   * FALSE if a packet with the same seqnum was already in the queue, meaning we
-   * have a duplicate. */
-  if (G_UNLIKELY (!wfd_rtp_buffer_insert (priv->jbuf, item,
-              &head, &percent)))
-    goto duplicate;
-
-  /* update timers */
-  update_timers (jitterbuffer, seqnum, dts, do_next_seqnum);
-
-  /* we had an unhandled SR, handle it now */
-  if (priv->last_sr)
-    do_handle_sync (jitterbuffer);
-
-  if (G_UNLIKELY (head)) {
-    /* signal addition of new buffer when the _loop is waiting. */
-    if (G_LIKELY (priv->active))
-      JBUF_SIGNAL_EVENT (priv);
-
-    /* let's unschedule and unblock any waiting buffers. We only want to do this
-     * when the head buffer changed */
-    if (G_UNLIKELY (priv->clock_id)) {
-      GST_DEBUG_OBJECT (jitterbuffer, "Unscheduling waiting new buffer");
-      unschedule_current_timer (jitterbuffer);
-    }
-  }
-
-  GST_DEBUG_OBJECT (jitterbuffer,
-      "Pushed packet #%d, now %d packets, head: %d, " "percent %d", seqnum,
-      wfd_rtp_buffer_num_packets (priv->jbuf), head, percent);
-
-  msg = check_buffering_percent (jitterbuffer, percent);
-
-finished:
-  JBUF_UNLOCK (priv);
-
-  if (msg)
-    gst_element_post_message (GST_ELEMENT_CAST (jitterbuffer), msg);
-
-  return ret;
-
-  /* ERRORS */
-invalid_buffer:
-  {
-    /* this is not fatal but should be filtered earlier */
-    GST_ELEMENT_WARNING (jitterbuffer, STREAM, DECODE, (NULL),
-        ("Received invalid RTP payload, dropping"));
-    gst_buffer_unref (buffer);
-    return GST_FLOW_OK;
-  }
-no_clock_rate:
-  {
-    GST_WARNING_OBJECT (jitterbuffer,
-        "No clock-rate in caps!, dropping buffer");
-    gst_buffer_unref (buffer);
-    goto finished;
-  }
-out_flushing:
-  {
-    ret = priv->srcresult;
-    GST_DEBUG_OBJECT (jitterbuffer, "flushing %s", gst_flow_get_name (ret));
-    gst_buffer_unref (buffer);
-    goto finished;
-  }
-have_eos:
-  {
-    ret = GST_FLOW_EOS;
-    GST_WARNING_OBJECT (jitterbuffer, "we are EOS, refusing buffer");
-    gst_buffer_unref (buffer);
-    goto finished;
-  }
-too_late:
-  {
-    GST_WARNING_OBJECT (jitterbuffer, "Packet #%d too late as #%d was already"
-        " popped, dropping", seqnum, priv->last_popped_seqnum);
-    priv->num_late++;
-    gst_buffer_unref (buffer);
-    goto finished;
-  }
-duplicate:
-  {
-    GST_WARNING_OBJECT (jitterbuffer, "Duplicate packet #%d detected, dropping",
-        seqnum);
-    priv->num_duplicates++;
-    free_item (item);
-    goto finished;
-  }
-}
-
-static GstClockTime
-compute_elapsed (GstWfdRTPBuffer * jitterbuffer, WfdRTPBufferItem * item)
-{
-  guint64 ext_time, elapsed;
-  guint32 rtp_time;
-  GstWfdRTPBufferPrivate *priv;
-
-  priv = jitterbuffer->priv;
-  rtp_time = item->rtptime;
-
-  GST_LOG_OBJECT (jitterbuffer, "rtp %" G_GUINT32_FORMAT ", ext %"
-      G_GUINT64_FORMAT, rtp_time, priv->ext_timestamp);
-
-  if (rtp_time < priv->ext_timestamp) {
-    ext_time = priv->ext_timestamp;
-  } else {
-    ext_time = gst_rtp_buffer_ext_timestamp (&priv->ext_timestamp, rtp_time);
-  }
-
-  if (ext_time > priv->clock_base)
-    elapsed = ext_time - priv->clock_base;
-  else
-    elapsed = 0;
-
-  elapsed = gst_util_uint64_scale_int (elapsed, GST_SECOND, priv->clock_rate);
-  return elapsed;
-}
-
-static void
-update_estimated_eos (GstWfdRTPBuffer * jitterbuffer,
-    WfdRTPBufferItem * item)
-{
-  guint64 total, elapsed, left, estimated;
-  GstClockTime out_time;
-  GstWfdRTPBufferPrivate *priv = jitterbuffer->priv;
-
-  if (priv->npt_stop == -1 || priv->ext_timestamp == -1
-      || priv->clock_base == -1 || priv->clock_rate <= 0)
-    return;
-
-  /* compute the elapsed time */
-  elapsed = compute_elapsed (jitterbuffer, item);
-
-  /* do nothing if elapsed time doesn't increment */
-  if (priv->last_elapsed && elapsed <= priv->last_elapsed)
-    return;
-
-  priv->last_elapsed = elapsed;
-
-  /* this is the total time we need to play */
-  total = priv->npt_stop - priv->npt_start;
-  GST_LOG_OBJECT (jitterbuffer, "total %" GST_TIME_FORMAT,
-      GST_TIME_ARGS (total));
-
-  /* this is how much time there is left */
-  if (total > elapsed)
-    left = total - elapsed;
-  else
-    left = 0;
-
-  /* if we have less time left that the size of the buffer, we will not
-   * be able to keep it filled, disabled buffering then */
-  if (left < wfd_rtp_buffer_get_delay (priv->jbuf)) {
-    GST_DEBUG_OBJECT (jitterbuffer, "left %" GST_TIME_FORMAT
-        ", disable buffering close to EOS", GST_TIME_ARGS (left));
-    wfd_rtp_buffer_disable_buffering (priv->jbuf, TRUE);
-  }
-
-  /* this is the current time as running-time */
-  out_time = item->dts;
-
-  if (elapsed > 0)
-    estimated = gst_util_uint64_scale (out_time, total, elapsed);
-  else {
-    /* if there is almost nothing left,
-     * we may never advance enough to end up in the above case */
-    if (total < GST_SECOND)
-      estimated = GST_SECOND;
-    else
-      estimated = -1;
-  }
-  GST_LOG_OBJECT (jitterbuffer, "elapsed %" GST_TIME_FORMAT ", estimated %"
-      GST_TIME_FORMAT, GST_TIME_ARGS (elapsed), GST_TIME_ARGS (estimated));
-
-  if (estimated != -1 && priv->estimated_eos != estimated) {
-    set_timer (jitterbuffer, TIMER_TYPE_EOS, -1, estimated);
-    priv->estimated_eos = estimated;
-  }
-}
-
-/* take a buffer from the queue and push it */
-static GstFlowReturn
-pop_and_push_next (GstWfdRTPBuffer * jitterbuffer, guint seqnum)
-{
-  GstWfdRTPBufferPrivate *priv = jitterbuffer->priv;
-  GstFlowReturn result = GST_FLOW_OK;
-  WfdRTPBufferItem *item;
-  GstBuffer *outbuf = NULL;
-  GstEvent *outevent = NULL;
-  GstQuery *outquery = NULL;
-  GstClockTime dts, pts;
-  gint percent = -1;
-  gboolean do_push = TRUE;
-  guint type;
-  GstMessage *msg;
-
-  /* when we get here we are ready to pop and push the buffer */
-  item = wfd_rtp_buffer_pop (priv->jbuf, &percent);
-  type = item->type;
-
-  switch (type) {
-    case ITEM_TYPE_BUFFER:
-
-      /* we need to make writable to change the flags and timestamps */
-      outbuf = gst_buffer_make_writable (item->data);
-
-      if (G_UNLIKELY (priv->discont)) {
-        /* set DISCONT flag when we missed a packet. We pushed the buffer writable
-         * into the jitterbuffer so we can modify now. */
-        GST_DEBUG_OBJECT (jitterbuffer, "mark output buffer discont");
-        GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
-        priv->discont = FALSE;
-      }
-      if (G_UNLIKELY (priv->ts_discont)) {
-        GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_RESYNC);
-        priv->ts_discont = FALSE;
-      }
-
-      dts =
-          gst_segment_to_position (&priv->segment, GST_FORMAT_TIME, item->dts);
-      pts =
-          gst_segment_to_position (&priv->segment, GST_FORMAT_TIME, item->pts);
-
-      /* apply timestamp with offset to buffer now */
-      GST_BUFFER_DTS (outbuf) = apply_offset (jitterbuffer, dts);
-      GST_BUFFER_PTS (outbuf) = apply_offset (jitterbuffer, pts);
-
-      /* update the elapsed time when we need to check against the npt stop time. */
-      update_estimated_eos (jitterbuffer, item);
-
-      priv->last_out_time = GST_BUFFER_PTS (outbuf);
-      break;
-    case ITEM_TYPE_LOST:
-      priv->discont = TRUE;
-      if (!priv->do_lost)
-        do_push = FALSE;
-      /* FALLTHROUGH */
-    case ITEM_TYPE_EVENT:
-      outevent = item->data;
-      break;
-    case ITEM_TYPE_QUERY:
-      outquery = item->data;
-      break;
-  }
-
-  /* now we are ready to push the buffer. Save the seqnum and release the lock
-   * so the other end can push stuff in the queue again. */
-  if (seqnum != -1) {
-    priv->last_popped_seqnum = seqnum;
-    priv->next_seqnum = (seqnum + item->count) & 0xffff;
-  }
-  msg = check_buffering_percent (jitterbuffer, percent);
-  JBUF_UNLOCK (priv);
-
-  item->data = NULL;
-  free_item (item);
-
-  if (msg)
-    gst_element_post_message (GST_ELEMENT_CAST (jitterbuffer), msg);
-
-  switch (type) {
-    case ITEM_TYPE_BUFFER:
-      /* push buffer */
-      GST_DEBUG_OBJECT (jitterbuffer,
-          "Pushing buffer %d, dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT,
-          seqnum, GST_TIME_ARGS (GST_BUFFER_DTS (outbuf)),
-          GST_TIME_ARGS (GST_BUFFER_PTS (outbuf)));
-      result = gst_pad_push (priv->srcpad, outbuf);
-
-      JBUF_LOCK_CHECK (priv, out_flushing);
-      break;
-    case ITEM_TYPE_LOST:
-    case ITEM_TYPE_EVENT:
-      GST_DEBUG_OBJECT (jitterbuffer, "%sPushing event %" GST_PTR_FORMAT
-          ", seqnum %d", do_push ? "" : "NOT ", outevent, seqnum);
-
-      if (do_push)
-        gst_pad_push_event (priv->srcpad, outevent);
-      else
-        gst_event_unref (outevent);
-
-      result = GST_FLOW_OK;
-
-      JBUF_LOCK_CHECK (priv, out_flushing);
-      break;
-    case ITEM_TYPE_QUERY:
-    {
-      gboolean res;
-
-      res = gst_pad_peer_query (priv->srcpad, outquery);
-
-      JBUF_LOCK_CHECK (priv, out_flushing);
-      result = GST_FLOW_OK;
-      GST_LOG_OBJECT (jitterbuffer, "did query %p, return %d", outquery, res);
-      JBUF_SIGNAL_QUERY (priv, res);
-      break;
-    }
-  }
-  return result;
-
-  /* ERRORS */
-out_flushing:
-  {
-    return priv->srcresult;
-  }
-}
-
-#define GST_FLOW_WAIT GST_FLOW_CUSTOM_SUCCESS
-
-/* Peek a buffer and compare the seqnum to the expected seqnum.
- * If all is fine, the buffer is pushed.
- * If something is wrong, we wait for some event
- */
-static GstFlowReturn
-handle_next_buffer (GstWfdRTPBuffer * jitterbuffer)
-{
-  GstWfdRTPBufferPrivate *priv = jitterbuffer->priv;
-  GstFlowReturn result = GST_FLOW_OK;
-  WfdRTPBufferItem *item;
-  guint seqnum;
-  guint32 next_seqnum;
-  gint gap;
-
-  /* only push buffers when PLAYING and active and not buffering */
-  if (priv->blocked || !priv->active ||
-      wfd_rtp_buffer_is_buffering (priv->jbuf))
-    return GST_FLOW_WAIT;
-
-again:
-  /* peek a buffer, we're just looking at the sequence number.
-   * If all is fine, we'll pop and push it. If the sequence number is wrong we
-   * wait for a timeout or something to change.
-   * The peeked buffer is valid for as long as we hold the jitterbuffer lock. */
-  item = wfd_rtp_buffer_peek (priv->jbuf);
-  if (item == NULL)
-    goto wait;
-
-  /* get the seqnum and the next expected seqnum */
-  seqnum = item->seqnum;
-  if (seqnum == -1)
-    goto do_push;
-
-  next_seqnum = priv->next_seqnum;
-
-  /* get the gap between this and the previous packet. If we don't know the
-   * previous packet seqnum assume no gap. */
-  if (G_UNLIKELY (next_seqnum == -1)) {
-    GST_DEBUG_OBJECT (jitterbuffer, "First buffer #%d", seqnum);
-    /* we don't know what the next_seqnum should be, the chain function should
-     * have scheduled a DEADLINE timer that will increment next_seqnum when it
-     * fires, so wait for that */
-    result = GST_FLOW_WAIT;
-  } else {
-    /* else calculate GAP */
-    gap = gst_rtp_buffer_compare_seqnum (next_seqnum, seqnum);
-
-    if (G_LIKELY (gap == 0)) {
-    do_push:
-      /* no missing packet, pop and push */
-      result = pop_and_push_next (jitterbuffer, seqnum);
-    } else if (G_UNLIKELY (gap < 0)) {
-      WfdRTPBufferItem *item;
-      /* if we have a packet that we already pushed or considered dropped, pop it
-       * off and get the next packet */
-      GST_DEBUG_OBJECT (jitterbuffer, "Old packet #%d, next #%d dropping",
-          seqnum, next_seqnum);
-      item = wfd_rtp_buffer_pop (priv->jbuf, NULL);
-      free_item (item);
-      goto again;
-    } else {
-      /* the chain function has scheduled timers to request retransmission or
-       * when to consider the packet lost, wait for that */
-      GST_DEBUG_OBJECT (jitterbuffer,
-          "Sequence number GAP detected: expected %d instead of %d (%d missing)",
-          next_seqnum, seqnum, gap);
-      result = GST_FLOW_WAIT;
-    }
-  }
-  return result;
-
-wait:
-  {
-    GST_DEBUG_OBJECT (jitterbuffer, "no buffer, going to wait");
-    if (priv->eos)
-      result = GST_FLOW_EOS;
-    else
-      result = GST_FLOW_WAIT;
-    return result;
-  }
-}
-
-/* the timeout for when we expected a packet expired */
-static gboolean
-do_expected_timeout (GstWfdRTPBuffer * jitterbuffer, TimerData * timer,
-    GstClockTime now)
-{
-  GstWfdRTPBufferPrivate *priv = jitterbuffer->priv;
-  GstEvent *event;
-  guint delay, delay_ms, avg_rtx_rtt_ms;
-  guint rtx_retry_timeout_ms, rtx_retry_period_ms;
-  GstClockTime rtx_retry_period;
-  GstClockTime rtx_retry_timeout;
-  GstClock *clock;
-
-  GST_DEBUG_OBJECT (jitterbuffer, "expected %d didn't arrive, now %"
-      GST_TIME_FORMAT, timer->seqnum, GST_TIME_ARGS (now));
-
-  if (priv->rtx_retry_timeout == -1) {
-    if (priv->avg_rtx_rtt == 0)
-      rtx_retry_timeout = DEFAULT_AUTO_RTX_TIMEOUT;
-    else
-      /* we want to ask for a retransmission after we waited for a
-       * complete RTT and the additional jitter */
-      rtx_retry_timeout = priv->avg_rtx_rtt + priv->avg_jitter * 2;
-  } else {
-    rtx_retry_timeout = priv->rtx_retry_timeout * GST_MSECOND;
-  }
-
-  if (priv->rtx_retry_period == -1) {
-    /* we retry up to the configured jitterbuffer size but leaving some
-     * room for the retransmission to arrive in time */
-    rtx_retry_period = priv->latency_ns - rtx_retry_timeout;
-  } else {
-    rtx_retry_period = priv->rtx_retry_period * GST_MSECOND;
-  }
-
-  GST_DEBUG_OBJECT (jitterbuffer, "timeout %" GST_TIME_FORMAT ", period %"
-      GST_TIME_FORMAT, GST_TIME_ARGS (rtx_retry_timeout),
-      GST_TIME_ARGS (rtx_retry_period));
-
-  delay = timer->rtx_delay + timer->rtx_retry;
-
-  delay_ms = GST_TIME_AS_MSECONDS (delay);
-  rtx_retry_timeout_ms = GST_TIME_AS_MSECONDS (rtx_retry_timeout);
-  rtx_retry_period_ms = GST_TIME_AS_MSECONDS (rtx_retry_period);
-  avg_rtx_rtt_ms = GST_TIME_AS_MSECONDS (priv->avg_rtx_rtt);
-
-  event = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM,
-      gst_structure_new ("GstRTPRetransmissionRequest",
-          "seqnum", G_TYPE_UINT, (guint) timer->seqnum,
-          "running-time", G_TYPE_UINT64, timer->rtx_base,
-          "delay", G_TYPE_UINT, delay_ms,
-          "retry", G_TYPE_UINT, timer->num_rtx_retry,
-          "frequency", G_TYPE_UINT, rtx_retry_timeout_ms,
-          "period", G_TYPE_UINT, rtx_retry_period_ms,
-          "deadline", G_TYPE_UINT, priv->latency_ms,
-          "packet-spacing", G_TYPE_UINT64, priv->packet_spacing,
-          "avg-rtt", G_TYPE_UINT, avg_rtx_rtt_ms, NULL));
-
-  priv->num_rtx_requests++;
-  timer->num_rtx_retry++;
-
-  GST_OBJECT_LOCK (jitterbuffer);
-  if ((clock = GST_ELEMENT_CLOCK (jitterbuffer))) {
-    timer->rtx_last = gst_clock_get_time (clock);
-    timer->rtx_last -= GST_ELEMENT_CAST (jitterbuffer)->base_time;
-  } else {
-    timer->rtx_last = now;
-  }
-  GST_OBJECT_UNLOCK (jitterbuffer);
-
-  /* calculate the timeout for the next retransmission attempt */
-  timer->rtx_retry += rtx_retry_timeout;
-  GST_DEBUG_OBJECT (jitterbuffer, "base %" GST_TIME_FORMAT ", delay %"
-      GST_TIME_FORMAT ", retry %" GST_TIME_FORMAT ", num_retry %u",
-      GST_TIME_ARGS (timer->rtx_base), GST_TIME_ARGS (timer->rtx_delay),
-      GST_TIME_ARGS (timer->rtx_retry), timer->num_rtx_retry);
-
-  if (timer->rtx_retry + timer->rtx_delay > rtx_retry_period) {
-    GST_DEBUG_OBJECT (jitterbuffer, "reschedule as LOST timer");
-    /* too many retransmission request, we now convert the timer
-     * to a lost timer, leave the num_rtx_retry as it is for stats */
-    timer->type = TIMER_TYPE_LOST;
-    timer->rtx_delay = 0;
-    timer->rtx_retry = 0;
-  }
-  reschedule_timer (jitterbuffer, timer, timer->seqnum,
-      timer->rtx_base + timer->rtx_retry, timer->rtx_delay, FALSE);
-
-  JBUF_UNLOCK (priv);
-  gst_pad_push_event (priv->sinkpad, event);
-  JBUF_LOCK (priv);
-
-  return FALSE;
-}
-
-/* a packet is lost */
-static gboolean
-do_lost_timeout (GstWfdRTPBuffer * jitterbuffer, TimerData * timer,
-    GstClockTime now)
-{
-  GstWfdRTPBufferPrivate *priv = jitterbuffer->priv;
-  GstClockTime duration, timestamp;
-  guint seqnum, lost_packets, num_rtx_retry, next_in_seqnum;
-  gboolean late, head;
-  GstEvent *event;
-  WfdRTPBufferItem *item;
-
-  seqnum = timer->seqnum;
-  timestamp = apply_offset (jitterbuffer, timer->timeout);
-  duration = timer->duration;
-  if (duration == GST_CLOCK_TIME_NONE && priv->packet_spacing > 0)
-    duration = priv->packet_spacing;
-  lost_packets = MAX (timer->num, 1);
-  late = timer->num > 0;
-  num_rtx_retry = timer->num_rtx_retry;
-
-  /* we had a gap and thus we lost some packets. Create an event for this.  */
-  if (lost_packets > 1)
-    GST_DEBUG_OBJECT (jitterbuffer, "Packets #%d -> #%d lost", seqnum,
-        seqnum + lost_packets - 1);
-  else
-    GST_DEBUG_OBJECT (jitterbuffer, "Packet #%d lost", seqnum);
-
-  priv->num_late += lost_packets;
-  priv->num_rtx_failed += num_rtx_retry;
-
-  next_in_seqnum = (seqnum + lost_packets) & 0xffff;
-
-  /* we now only accept seqnum bigger than this */
-  if (gst_rtp_buffer_compare_seqnum (priv->next_in_seqnum, next_in_seqnum) > 0)
-    priv->next_in_seqnum = next_in_seqnum;
-
-  /* create paket lost event */
-  event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
-      gst_structure_new ("GstRTPPacketLost",
-          "seqnum", G_TYPE_UINT, (guint) seqnum,
-          "timestamp", G_TYPE_UINT64, timestamp,
-          "duration", G_TYPE_UINT64, duration,
-          "late", G_TYPE_BOOLEAN, late,
-          "retry", G_TYPE_UINT, num_rtx_retry, NULL));
-
-  item = alloc_item (event, ITEM_TYPE_LOST, -1, -1, seqnum, lost_packets, -1);
-  wfd_rtp_buffer_insert (priv->jbuf, item, &head, NULL);
-
-  /* remove timer now */
-  remove_timer (jitterbuffer, timer);
-  if (head)
-    JBUF_SIGNAL_EVENT (priv);
-
-  return TRUE;
-}
-
-static gboolean
-do_eos_timeout (GstWfdRTPBuffer * jitterbuffer, TimerData * timer,
-    GstClockTime now)
-{
-  GstWfdRTPBufferPrivate *priv = jitterbuffer->priv;
-
-  GST_INFO_OBJECT (jitterbuffer, "got the NPT timeout");
-  remove_timer (jitterbuffer, timer);
-  if (!priv->eos) {
-    /* there was no EOS in the buffer, put one in there now */
-    queue_event (jitterbuffer, gst_event_new_eos ());
-  }
-  JBUF_SIGNAL_EVENT (priv);
-
-  return TRUE;
-}
-
-static gboolean
-do_deadline_timeout (GstWfdRTPBuffer * jitterbuffer, TimerData * timer,
-    GstClockTime now)
-{
-  GstWfdRTPBufferPrivate *priv = jitterbuffer->priv;
-
-  GST_INFO_OBJECT (jitterbuffer, "got deadline timeout");
-
-  /* timer seqnum might have been obsoleted by caps seqnum-base,
-   * only mess with current ongoing seqnum if still unknown */
-  if (priv->next_seqnum == -1)
-    priv->next_seqnum = timer->seqnum;
-  remove_timer (jitterbuffer, timer);
-  JBUF_SIGNAL_EVENT (priv);
-
-  return TRUE;
-}
-
-static gboolean
-do_timeout (GstWfdRTPBuffer * jitterbuffer, TimerData * timer,
-    GstClockTime now)
-{
-  gboolean removed = FALSE;
-
-  switch (timer->type) {
-    case TIMER_TYPE_EXPECTED:
-      removed = do_expected_timeout (jitterbuffer, timer, now);
-      break;
-    case TIMER_TYPE_LOST:
-      removed = do_lost_timeout (jitterbuffer, timer, now);
-      break;
-    case TIMER_TYPE_DEADLINE:
-      removed = do_deadline_timeout (jitterbuffer, timer, now);
-      break;
-    case TIMER_TYPE_EOS:
-      removed = do_eos_timeout (jitterbuffer, timer, now);
-      break;
-  }
-  return removed;
-}
-
-/* called when we need to wait for the next timeout.
- *
- * We loop over the array of recorded timeouts and wait for the earliest one.
- * When it timed out, do the logic associated with the timer.
- *
- * If there are no timers, we wait on a gcond until something new happens.
- */
-static void
-wait_next_timeout (GstWfdRTPBuffer * jitterbuffer)
-{
-  GstWfdRTPBufferPrivate *priv = jitterbuffer->priv;
-  GstClockTime now = 0;
-
-  JBUF_LOCK (priv);
-  while (priv->timer_running) {
-    TimerData *timer = NULL;
-    GstClockTime timer_timeout = -1;
-    gint i, len;
-
-    GST_DEBUG_OBJECT (jitterbuffer, "now %" GST_TIME_FORMAT,
-        GST_TIME_ARGS (now));
-
-    len = priv->timers->len;
-    for (i = 0; i < len; i++) {
-      TimerData *test = &g_array_index (priv->timers, TimerData, i);
-      GstClockTime test_timeout = get_timeout (jitterbuffer, test);
-      gboolean save_best = FALSE;
-
-      GST_DEBUG_OBJECT (jitterbuffer, "%d, %d, %d, %" GST_TIME_FORMAT,
-          i, test->type, test->seqnum, GST_TIME_ARGS (test_timeout));
-
-      /* find the smallest timeout */
-      if (timer == NULL) {
-        save_best = TRUE;
-      } else if (timer_timeout == -1) {
-        /* we already have an immediate timeout, the new timer must be an
-         * immediate timer with smaller seqnum to become the best */
-        if (test_timeout == -1
-            && (gst_rtp_buffer_compare_seqnum (test->seqnum,
-                    timer->seqnum) > 0))
-          save_best = TRUE;
-      } else if (test_timeout == -1) {
-        /* first immediate timer */
-        save_best = TRUE;
-      } else if (test_timeout < timer_timeout) {
-        /* earlier timer */
-        save_best = TRUE;
-      } else if (test_timeout == timer_timeout
-          && (gst_rtp_buffer_compare_seqnum (test->seqnum,
-                  timer->seqnum) > 0)) {
-        /* same timer, smaller seqnum */
-        save_best = TRUE;
-      }
-      if (save_best) {
-        GST_DEBUG_OBJECT (jitterbuffer, "new best %d", i);
-        timer = test;
-        timer_timeout = test_timeout;
-      }
-    }
-    if (timer && !priv->blocked) {
-      GstClock *clock;
-      GstClockTime sync_time;
-      GstClockID id;
-      GstClockReturn ret;
-      GstClockTimeDiff clock_jitter;
-
-      if (timer_timeout == -1 || timer_timeout <= now) {
-        do_timeout (jitterbuffer, timer, now);
-        /* check here, do_timeout could have released the lock */
-        if (!priv->timer_running)
-          break;
-        continue;
-      }
-
-      GST_OBJECT_LOCK (jitterbuffer);
-      clock = GST_ELEMENT_CLOCK (jitterbuffer);
-      if (!clock) {
-        GST_OBJECT_UNLOCK (jitterbuffer);
-        /* let's just push if there is no clock */
-        GST_DEBUG_OBJECT (jitterbuffer, "No clock, timeout right away");
-        now = timer_timeout;
-        continue;
-      }
-
-      /* prepare for sync against clock */
-      sync_time = timer_timeout + GST_ELEMENT_CAST (jitterbuffer)->base_time;
-      /* add latency of peer to get input time */
-      sync_time += priv->peer_latency;
-
-      GST_DEBUG_OBJECT (jitterbuffer, "sync to timestamp %" GST_TIME_FORMAT
-          " with sync time %" GST_TIME_FORMAT,
-          GST_TIME_ARGS (timer_timeout), GST_TIME_ARGS (sync_time));
-
-      /* create an entry for the clock */
-      id = priv->clock_id = gst_clock_new_single_shot_id (clock, sync_time);
-      priv->timer_timeout = timer_timeout;
-      priv->timer_seqnum = timer->seqnum;
-      GST_OBJECT_UNLOCK (jitterbuffer);
-
-      /* release the lock so that the other end can push stuff or unlock */
-      JBUF_UNLOCK (priv);
-
-      ret = gst_clock_id_wait (id, &clock_jitter);
-
-      JBUF_LOCK (priv);
-      if (!priv->timer_running) {
-        gst_clock_id_unref (id);
-        priv->clock_id = NULL;
-        break;
-      }
-
-      if (ret != GST_CLOCK_UNSCHEDULED) {
-        now = timer_timeout + MAX (clock_jitter, 0);
-        GST_DEBUG_OBJECT (jitterbuffer, "sync done, %d, #%d, %" G_GINT64_FORMAT,
-            ret, priv->timer_seqnum, clock_jitter);
-      } else {
-        GST_DEBUG_OBJECT (jitterbuffer, "sync unscheduled");
-      }
-      /* and free the entry */
-      gst_clock_id_unref (id);
-      priv->clock_id = NULL;
-    } else {
-      /* no timers, wait for activity */
-      JBUF_WAIT_TIMER (priv);
-    }
-  }
-  JBUF_UNLOCK (priv);
-
-  GST_DEBUG_OBJECT (jitterbuffer, "we are stopping");
-  return;
-}
-
-/*
- * This funcion implements the main pushing loop on the source pad.
- *
- * It first tries to push as many buffers as possible. If there is a seqnum
- * mismatch, we wait for the next timeouts.
- */
-static void
-gst_wfd_rtp_buffer_loop (GstWfdRTPBuffer * jitterbuffer)
-{
-  GstWfdRTPBufferPrivate *priv;
-  GstFlowReturn result = GST_FLOW_OK;
-
-  priv = jitterbuffer->priv;
-
-  JBUF_LOCK_CHECK (priv, flushing);
-  do {
-    result = handle_next_buffer (jitterbuffer);
-    if (G_LIKELY (result == GST_FLOW_WAIT)) {
-      /* now wait for the next event */
-      JBUF_WAIT_EVENT (priv, flushing);
-      result = GST_FLOW_OK;
-    }
-  }
-  while (result == GST_FLOW_OK);
-  /* store result for upstream */
-  priv->srcresult = result;
-  /* if we get here we need to pause */
-  goto pause;
-
-  /* ERRORS */
-flushing:
-  {
-    result = priv->srcresult;
-    goto pause;
-  }
-pause:
-  {
-    GstEvent *event;
-
-    JBUF_SIGNAL_QUERY (priv, FALSE);
-    JBUF_UNLOCK (priv);
-
-    GST_DEBUG_OBJECT (jitterbuffer, "pausing task, reason %s",
-        gst_flow_get_name (result));
-    gst_pad_pause_task (priv->srcpad);
-    if (result == GST_FLOW_EOS) {
-      event = gst_event_new_eos ();
-      gst_pad_push_event (priv->srcpad, event);
-    }
-    return;
-  }
-}
-
-/* collect the info from the lastest RTCP packet and the jitterbuffer sync, do
- * some sanity checks and then emit the handle-sync signal with the parameters.
- * This function must be called with the LOCK */
-static void
-do_handle_sync (GstWfdRTPBuffer * jitterbuffer)
-{
-  GstWfdRTPBufferPrivate *priv;
-  guint64 base_rtptime, base_time;
-  guint32 clock_rate;
-  guint64 last_rtptime;
-  guint64 clock_base;
-  guint64 ext_rtptime, diff;
-  gboolean valid = TRUE, keep = FALSE;
-
-  priv = jitterbuffer->priv;
-
-  /* get the last values from the jitterbuffer */
-  wfd_rtp_buffer_get_sync (priv->jbuf, &base_rtptime, &base_time,
-      &clock_rate, &last_rtptime);
-
-  clock_base = priv->clock_base;
-  ext_rtptime = priv->ext_rtptime;
-
-  GST_DEBUG_OBJECT (jitterbuffer, "ext SR %" G_GUINT64_FORMAT ", base %"
-      G_GUINT64_FORMAT ", clock-rate %" G_GUINT32_FORMAT
-      ", clock-base %" G_GUINT64_FORMAT ", last-rtptime %" G_GUINT64_FORMAT,
-      ext_rtptime, base_rtptime, clock_rate, clock_base, last_rtptime);
-
-  if (base_rtptime == -1 || clock_rate == -1 || base_time == -1) {
-    /* we keep this SR packet for later. When we get a valid RTP packet the
-     * above values will be set and we can try to use the SR packet */
-    GST_DEBUG_OBJECT (jitterbuffer, "keeping for later, no RTP values");
-    keep = TRUE;
-  } else {
-    /* we can't accept anything that happened before we did the last resync */
-    if (base_rtptime > ext_rtptime) {
-      GST_DEBUG_OBJECT (jitterbuffer, "dropping, older than base time");
-      valid = FALSE;
-    } else {
-      /* the SR RTP timestamp must be something close to what we last observed
-       * in the jitterbuffer */
-      if (ext_rtptime > last_rtptime) {
-        /* check how far ahead it is to our RTP timestamps */
-        diff = ext_rtptime - last_rtptime;
-        /* if bigger than 1 second, we drop it */
-        if (diff > clock_rate) {
-          GST_DEBUG_OBJECT (jitterbuffer, "too far ahead");
-          /* should drop this, but some RTSP servers end up with bogus
-           * way too ahead RTCP packet when repeated PAUSE/PLAY,
-           * so still trigger rptbin sync but invalidate RTCP data
-           * (sync might use other methods) */
-          ext_rtptime = -1;
-        }
-        GST_DEBUG_OBJECT (jitterbuffer, "ext last %" G_GUINT64_FORMAT ", diff %"
-            G_GUINT64_FORMAT, last_rtptime, diff);
-      }
-    }
-  }
-
-  if (keep) {
-    GST_DEBUG_OBJECT (jitterbuffer, "keeping RTCP packet for later");
-  } else if (valid) {
-    GstStructure *s;
-
-    s = gst_structure_new ("application/x-rtp-sync",
-        "base-rtptime", G_TYPE_UINT64, base_rtptime,
-        "base-time", G_TYPE_UINT64, base_time,
-        "clock-rate", G_TYPE_UINT, clock_rate,
-        "clock-base", G_TYPE_UINT64, clock_base,
-        "sr-ext-rtptime", G_TYPE_UINT64, ext_rtptime,
-        "sr-buffer", GST_TYPE_BUFFER, priv->last_sr, NULL);
-
-    GST_DEBUG_OBJECT (jitterbuffer, "signaling sync");
-    gst_buffer_replace (&priv->last_sr, NULL);
-    JBUF_UNLOCK (priv);
-    g_signal_emit (jitterbuffer,
-        gst_wfd_rtp_buffer_signals[SIGNAL_HANDLE_SYNC], 0, s);
-    JBUF_LOCK (priv);
-    gst_structure_free (s);
-  } else {
-    GST_DEBUG_OBJECT (jitterbuffer, "dropping RTCP packet");
-    gst_buffer_replace (&priv->last_sr, NULL);
-  }
-}
-
-static GstFlowReturn
-gst_wfd_rtp_buffer_chain_rtcp (GstPad * pad, GstObject * parent,
-    GstBuffer * buffer)
-{
-  GstWfdRTPBuffer *jitterbuffer;
-  GstWfdRTPBufferPrivate *priv;
-  GstFlowReturn ret = GST_FLOW_OK;
-  guint32 ssrc;
-  GstRTCPPacket packet;
-  guint64 ext_rtptime;
-  guint32 rtptime;
-  GstRTCPBuffer rtcp = { NULL, };
-
-  jitterbuffer = GST_WFD_RTP_BUFFER (parent);
-
-  if (G_UNLIKELY (!gst_rtcp_buffer_validate (buffer)))
-    goto invalid_buffer;
-
-  priv = jitterbuffer->priv;
-
-  gst_rtcp_buffer_map (buffer, GST_MAP_READ, &rtcp);
-
-  if (!gst_rtcp_buffer_get_first_packet (&rtcp, &packet))
-    goto empty_buffer;
-
-  /* first packet must be SR or RR or else the validate would have failed */
-  switch (gst_rtcp_packet_get_type (&packet)) {
-    case GST_RTCP_TYPE_SR:
-      gst_rtcp_packet_sr_get_sender_info (&packet, &ssrc, NULL, &rtptime,
-          NULL, NULL);
-      break;
-    default:
-      goto ignore_buffer;
-  }
-  gst_rtcp_buffer_unmap (&rtcp);
-
-  GST_DEBUG_OBJECT (jitterbuffer, "received RTCP of SSRC %08x", ssrc);
-
-  JBUF_LOCK (priv);
-  /* convert the RTP timestamp to our extended timestamp, using the same offset
-   * we used in the jitterbuffer */
-  ext_rtptime = priv->jbuf->ext_rtptime;
-  ext_rtptime = gst_rtp_buffer_ext_timestamp (&ext_rtptime, rtptime);
-
-  priv->ext_rtptime = ext_rtptime;
-  gst_buffer_replace (&priv->last_sr, buffer);
-
-  do_handle_sync (jitterbuffer);
-  JBUF_UNLOCK (priv);
-
-done:
-  gst_buffer_unref (buffer);
-
-  return ret;
-
-invalid_buffer:
-  {
-    /* this is not fatal but should be filtered earlier */
-    GST_ELEMENT_WARNING (jitterbuffer, STREAM, DECODE, (NULL),
-        ("Received invalid RTCP payload, dropping"));
-    ret = GST_FLOW_OK;
-    goto done;
-  }
-empty_buffer:
-  {
-    /* this is not fatal but should be filtered earlier */
-    GST_ELEMENT_WARNING (jitterbuffer, STREAM, DECODE, (NULL),
-        ("Received empty RTCP payload, dropping"));
-    gst_rtcp_buffer_unmap (&rtcp);
-    ret = GST_FLOW_OK;
-    goto done;
-  }
-ignore_buffer:
-  {
-    GST_DEBUG_OBJECT (jitterbuffer, "ignoring RTCP packet");
-    gst_rtcp_buffer_unmap (&rtcp);
-    ret = GST_FLOW_OK;
-    goto done;
-  }
-}
-
-static gboolean
-gst_wfd_rtp_buffer_sink_query (GstPad * pad, GstObject * parent,
-    GstQuery * query)
-{
-  gboolean res = FALSE;
-  GstWfdRTPBuffer *jitterbuffer;
-  GstWfdRTPBufferPrivate *priv;
-
-  jitterbuffer = GST_WFD_RTP_BUFFER (parent);
-  priv = jitterbuffer->priv;
-
-  switch (GST_QUERY_TYPE (query)) {
-    case GST_QUERY_CAPS:
-    {
-      GstCaps *filter, *caps;
-
-      gst_query_parse_caps (query, &filter);
-      caps = gst_wfd_rtp_buffer_getcaps (pad, filter);
-      gst_query_set_caps_result (query, caps);
-      gst_caps_unref (caps);
-      res = TRUE;
-      break;
-    }
-    default:
-      if (GST_QUERY_IS_SERIALIZED (query)) {
-        WfdRTPBufferItem *item;
-        gboolean head;
-
-        JBUF_LOCK_CHECK (priv, out_flushing);
-        if (wfd_rtp_buffer_get_mode (priv->jbuf) !=
-            WFD_RTP_BUFFER_MODE_BUFFER) {
-          GST_DEBUG_OBJECT (jitterbuffer, "adding serialized query");
-          item = alloc_item (query, ITEM_TYPE_QUERY, -1, -1, -1, 0, -1);
-          wfd_rtp_buffer_insert (priv->jbuf, item, &head, NULL);
-          if (head)
-            JBUF_SIGNAL_EVENT (priv);
-          JBUF_WAIT_QUERY (priv, out_flushing);
-          res = priv->last_query;
-        } else {
-          GST_DEBUG_OBJECT (jitterbuffer, "refusing query, we are buffering");
-          res = FALSE;
-        }
-        JBUF_UNLOCK (priv);
-      } else {
-        res = gst_pad_query_default (pad, parent, query);
-      }
-      break;
-  }
-  return res;
-  /* ERRORS */
-out_flushing:
-  {
-    GST_DEBUG_OBJECT (jitterbuffer, "we are flushing");
-    JBUF_UNLOCK (priv);
-    return FALSE;
-  }
-
-}
-
-static gboolean
-gst_wfd_rtp_buffer_src_query (GstPad * pad, GstObject * parent,
-    GstQuery * query)
-{
-  GstWfdRTPBuffer *jitterbuffer;
-  GstWfdRTPBufferPrivate *priv;
-  gboolean res = FALSE;
-
-  jitterbuffer = GST_WFD_RTP_BUFFER (parent);
-  priv = jitterbuffer->priv;
-
-  switch (GST_QUERY_TYPE (query)) {
-    case GST_QUERY_LATENCY:
-    {
-      /* We need to send the query upstream and add the returned latency to our
-       * own */
-      GstClockTime min_latency, max_latency;
-      gboolean us_live;
-      GstClockTime our_latency;
-
-      if ((res = gst_pad_peer_query (priv->sinkpad, query))) {
-        gst_query_parse_latency (query, &us_live, &min_latency, &max_latency);
-
-        GST_DEBUG_OBJECT (jitterbuffer, "Peer latency: min %"
-            GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
-            GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency));
-
-        /* store this so that we can safely sync on the peer buffers. */
-        JBUF_LOCK (priv);
-        priv->peer_latency = min_latency;
-        our_latency = priv->latency_ns;
-        JBUF_UNLOCK (priv);
-
-        GST_DEBUG_OBJECT (jitterbuffer, "Our latency: %" GST_TIME_FORMAT,
-            GST_TIME_ARGS (our_latency));
-
-        /* we add some latency but can buffer an infinite amount of time */
-        min_latency += our_latency;
-        max_latency = -1;
-
-        GST_DEBUG_OBJECT (jitterbuffer, "Calculated total latency : min %"
-            GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
-            GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency));
-
-        gst_query_set_latency (query, TRUE, min_latency, max_latency);
-      }
-      break;
-    }
-    case GST_QUERY_POSITION:
-    {
-      GstClockTime start, last_out;
-      GstFormat fmt;
-
-      gst_query_parse_position (query, &fmt, NULL);
-      if (fmt != GST_FORMAT_TIME) {
-        res = gst_pad_query_default (pad, parent, query);
-        break;
-      }
-
-      JBUF_LOCK (priv);
-      start = priv->npt_start;
-      last_out = priv->last_out_time;
-      JBUF_UNLOCK (priv);
-
-      GST_DEBUG_OBJECT (jitterbuffer, "npt start %" GST_TIME_FORMAT
-          ", last out %" GST_TIME_FORMAT, GST_TIME_ARGS (start),
-          GST_TIME_ARGS (last_out));
-
-      if (GST_CLOCK_TIME_IS_VALID (start) && GST_CLOCK_TIME_IS_VALID (last_out)) {
-        /* bring 0-based outgoing time to stream time */
-        gst_query_set_position (query, GST_FORMAT_TIME, start + last_out);
-        res = TRUE;
-      } else {
-        res = gst_pad_query_default (pad, parent, query);
-      }
-      break;
-    }
-    case GST_QUERY_CAPS:
-    {
-      GstCaps *filter, *caps;
-
-      gst_query_parse_caps (query, &filter);
-      caps = gst_wfd_rtp_buffer_getcaps (pad, filter);
-      gst_query_set_caps_result (query, caps);
-      gst_caps_unref (caps);
-      res = TRUE;
-      break;
-    }
-    default:
-      res = gst_pad_query_default (pad, parent, query);
-      break;
-  }
-
-  return res;
-}
-
-static void
-gst_wfd_rtp_buffer_set_property (GObject * object,
-    guint prop_id, const GValue * value, GParamSpec * pspec)
-{
-  GstWfdRTPBuffer *jitterbuffer;
-  GstWfdRTPBufferPrivate *priv;
-
-  jitterbuffer = GST_WFD_RTP_BUFFER (object);
-  priv = jitterbuffer->priv;
-
-  switch (prop_id) {
-    case PROP_LATENCY:
-    {
-      guint new_latency, old_latency;
-
-      new_latency = g_value_get_uint (value);
-
-      JBUF_LOCK (priv);
-      old_latency = priv->latency_ms;
-      priv->latency_ms = new_latency;
-      priv->latency_ns = priv->latency_ms * GST_MSECOND;
-      wfd_rtp_buffer_set_delay (priv->jbuf, priv->latency_ns);
-      JBUF_UNLOCK (priv);
-
-      /* post message if latency changed, this will inform the parent pipeline
-       * that a latency reconfiguration is possible/needed. */
-      if (new_latency != old_latency) {
-        GST_DEBUG_OBJECT (jitterbuffer, "latency changed to: %" GST_TIME_FORMAT,
-            GST_TIME_ARGS (new_latency * GST_MSECOND));
-
-        gst_element_post_message (GST_ELEMENT_CAST (jitterbuffer),
-            gst_message_new_latency (GST_OBJECT_CAST (jitterbuffer)));
-      }
-      break;
-    }
-    case PROP_DROP_ON_LATENCY:
-      JBUF_LOCK (priv);
-      priv->drop_on_latency = g_value_get_boolean (value);
-      JBUF_UNLOCK (priv);
-      break;
-    case PROP_TS_OFFSET:
-      JBUF_LOCK (priv);
-      priv->ts_offset = g_value_get_int64 (value);
-      priv->ts_discont = TRUE;
-      JBUF_UNLOCK (priv);
-      break;
-    case PROP_DO_LOST:
-      JBUF_LOCK (priv);
-      priv->do_lost = g_value_get_boolean (value);
-      JBUF_UNLOCK (priv);
-      break;
-    case PROP_MODE:
-      JBUF_LOCK (priv);
-      wfd_rtp_buffer_set_mode (priv->jbuf, g_value_get_enum (value));
-      JBUF_UNLOCK (priv);
-      break;
-    case PROP_DO_RETRANSMISSION:
-      JBUF_LOCK (priv);
-      priv->do_retransmission = g_value_get_boolean (value);
-      JBUF_UNLOCK (priv);
-      break;
-    case PROP_RTX_DELAY:
-      JBUF_LOCK (priv);
-      priv->rtx_delay = g_value_get_int (value);
-      JBUF_UNLOCK (priv);
-      break;
-    case PROP_RTX_DELAY_REORDER:
-      JBUF_LOCK (priv);
-      priv->rtx_delay_reorder = g_value_get_int (value);
-      JBUF_UNLOCK (priv);
-      break;
-    case PROP_RTX_RETRY_TIMEOUT:
-      JBUF_LOCK (priv);
-      priv->rtx_retry_timeout = g_value_get_int (value);
-      JBUF_UNLOCK (priv);
-      break;
-    case PROP_RTX_RETRY_PERIOD:
-      JBUF_LOCK (priv);
-      priv->rtx_retry_period = g_value_get_int (value);
-      JBUF_UNLOCK (priv);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static void
-gst_wfd_rtp_buffer_get_property (GObject * object,
-    guint prop_id, GValue * value, GParamSpec * pspec)
-{
-  GstWfdRTPBuffer *jitterbuffer;
-  GstWfdRTPBufferPrivate *priv;
-
-  jitterbuffer = GST_WFD_RTP_BUFFER (object);
-  priv = jitterbuffer->priv;
-
-  switch (prop_id) {
-    case PROP_LATENCY:
-      JBUF_LOCK (priv);
-      g_value_set_uint (value, priv->latency_ms);
-      JBUF_UNLOCK (priv);
-      break;
-    case PROP_DROP_ON_LATENCY:
-      JBUF_LOCK (priv);
-      g_value_set_boolean (value, priv->drop_on_latency);
-      JBUF_UNLOCK (priv);
-      break;
-    case PROP_TS_OFFSET:
-      JBUF_LOCK (priv);
-      g_value_set_int64 (value, priv->ts_offset);
-      JBUF_UNLOCK (priv);
-      break;
-    case PROP_DO_LOST:
-      JBUF_LOCK (priv);
-      g_value_set_boolean (value, priv->do_lost);
-      JBUF_UNLOCK (priv);
-      break;
-    case PROP_MODE:
-      JBUF_LOCK (priv);
-      g_value_set_enum (value, wfd_rtp_buffer_get_mode (priv->jbuf));
-      JBUF_UNLOCK (priv);
-      break;
-    case PROP_PERCENT:
-    {
-      gint percent;
-
-      JBUF_LOCK (priv);
-      if (priv->srcresult != GST_FLOW_OK)
-        percent = 100;
-      else
-        percent = wfd_rtp_buffer_get_percent (priv->jbuf);
-
-      g_value_set_int (value, percent);
-      JBUF_UNLOCK (priv);
-      break;
-    }
-    case PROP_DO_RETRANSMISSION:
-      JBUF_LOCK (priv);
-      g_value_set_boolean (value, priv->do_retransmission);
-      JBUF_UNLOCK (priv);
-      break;
-    case PROP_RTX_DELAY:
-      JBUF_LOCK (priv);
-      g_value_set_int (value, priv->rtx_delay);
-      JBUF_UNLOCK (priv);
-      break;
-    case PROP_RTX_DELAY_REORDER:
-      JBUF_LOCK (priv);
-      g_value_set_int (value, priv->rtx_delay_reorder);
-      JBUF_UNLOCK (priv);
-      break;
-    case PROP_RTX_RETRY_TIMEOUT:
-      JBUF_LOCK (priv);
-      g_value_set_int (value, priv->rtx_retry_timeout);
-      JBUF_UNLOCK (priv);
-      break;
-    case PROP_RTX_RETRY_PERIOD:
-      JBUF_LOCK (priv);
-      g_value_set_int (value, priv->rtx_retry_period);
-      JBUF_UNLOCK (priv);
-      break;
-    case PROP_STATS:
-      g_value_take_boxed (value,
-          gst_wfd_rtp_buffer_create_stats (jitterbuffer));
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
-
-static GstStructure *
-gst_wfd_rtp_buffer_create_stats (GstWfdRTPBuffer * jbuf)
-{
-  GstStructure *s;
-
-  JBUF_LOCK (jbuf->priv);
-  s = gst_structure_new ("application/x-rtp-jitterbuffer-stats",
-      "rtx-count", G_TYPE_UINT64, jbuf->priv->num_rtx_requests,
-      "rtx-success-count", G_TYPE_UINT64, jbuf->priv->num_rtx_success,
-      "rtx-per-packet", G_TYPE_DOUBLE, jbuf->priv->avg_rtx_num,
-      "rtx-rtt", G_TYPE_UINT64, jbuf->priv->avg_rtx_rtt, NULL);
-  JBUF_UNLOCK (jbuf->priv);
-
-  return s;
-}
diff --git a/wfdmanager/src/gstwfdrtspext.c b/wfdmanager/src/gstwfdrtspext.c
deleted file mode 100755 (executable)
index 94bb5fc..0000000
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * wfdrtspext
- *
- * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Alternatively, the contents of this file may be used under the
- * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
- * which case the following provisions apply instead of the ones
- * mentioned above:
- *
- * 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.
- */
-
-
-#include "gstwfdrtspext.h"
-
-GST_DEBUG_CATEGORY_STATIC (wfdrtspext_debug);
-#define GST_CAT_DEFAULT (wfdrtspext_debug)
-
-static GList *extensions;
-
-static gboolean
-gst_wfd_rtsp_ext_list_filter (GstPluginFeature * feature, gpointer user_data)
-{
-  GstElementFactory *factory;
-  guint rank;
-
-  /* we only care about element factories */
-  if (!GST_IS_ELEMENT_FACTORY (feature))
-    return FALSE;
-
-  factory = GST_ELEMENT_FACTORY (feature);
-
-  if (!gst_element_factory_has_interface (factory, "GstWFDRTSPExtension"))
-    return FALSE;
-
-  /* only select elements with autoplugging rank */
-  rank = gst_plugin_feature_get_rank (feature);
-  if (rank < GST_RANK_MARGINAL)
-    return FALSE;
-
-  return TRUE;
-}
-
-void
-gst_wfd_rtsp_ext_list_init (void)
-{
-  GST_DEBUG_CATEGORY_INIT (wfdrtspext_debug, "wfdrtspext", 0, "WFD RTSP extension");
-
-  /* get a list of all extensions */
-  extensions = gst_registry_feature_filter (gst_registry_get (),
-      (GstPluginFeatureFilter) gst_wfd_rtsp_ext_list_filter, FALSE, NULL);
-}
-
-GstWFDRTSPExtensionList *
-gst_wfd_rtsp_ext_list_get (void)
-{
-  GstWFDRTSPExtensionList *result;
-  GList *walk;
-
-  result = g_new0 (GstWFDRTSPExtensionList, 1);
-
-  for (walk = extensions; walk; walk = g_list_next (walk)) {
-    GstElementFactory *factory = GST_ELEMENT_FACTORY (walk->data);
-    GstElement *element;
-
-    element = gst_element_factory_create (factory, NULL);
-    if (!element) {
-      GST_ERROR ("could not create extension instance");
-      continue;
-    }
-
-    GST_DEBUG ("added extension interface for '%s'",
-        GST_ELEMENT_NAME (element));
-    result->extensions = g_list_prepend (result->extensions, element);
-  }
-  return result;
-}
-
-void
-gst_wfd_rtsp_ext_list_free (GstWFDRTSPExtensionList * ext)
-{
-  GList *walk;
-
-  for (walk = ext->extensions; walk; walk = g_list_next (walk)) {
-    GstRTSPExtension *elem = (GstRTSPExtension *) walk->data;
-
-    gst_object_unref (GST_OBJECT_CAST (elem));
-  }
-  g_list_free (ext->extensions);
-  g_free (ext);
-}
-
-gboolean
-gst_wfd_rtsp_ext_list_detect_server (GstWFDRTSPExtensionList * ext,
-    GstRTSPMessage * resp)
-{
-  GList *walk;
-  gboolean res = TRUE;
-
-  for (walk = ext->extensions; walk; walk = g_list_next (walk)) {
-    GstRTSPExtension *elem = (GstRTSPExtension *) walk->data;
-
-    res = gst_rtsp_extension_detect_server (elem, resp);
-  }
-  return res;
-}
-
-GstRTSPResult
-gst_wfd_rtsp_ext_list_before_send (GstWFDRTSPExtensionList * ext, GstRTSPMessage * req)
-{
-  GList *walk;
-  GstRTSPResult res = GST_RTSP_OK;
-
-  for (walk = ext->extensions; walk; walk = g_list_next (walk)) {
-    GstRTSPExtension *elem = (GstRTSPExtension *) walk->data;
-
-    res = gst_rtsp_extension_before_send (elem, req);
-  }
-  return res;
-}
-
-GstRTSPResult
-gst_wfd_rtsp_ext_list_after_send (GstWFDRTSPExtensionList * ext, GstRTSPMessage * req,
-    GstRTSPMessage * resp)
-{
-  GList *walk;
-  GstRTSPResult res = GST_RTSP_OK;
-
-  for (walk = ext->extensions; walk; walk = g_list_next (walk)) {
-    GstRTSPExtension *elem = (GstRTSPExtension *) walk->data;
-
-    res = gst_rtsp_extension_after_send (elem, req, resp);
-  }
-  return res;
-}
-
-GstRTSPResult
-gst_wfd_rtsp_ext_list_parse_sdp (GstWFDRTSPExtensionList * ext, GstSDPMessage * sdp,
-    GstStructure * s)
-{
-  GList *walk;
-  GstRTSPResult res = GST_RTSP_OK;
-
-  for (walk = ext->extensions; walk; walk = g_list_next (walk)) {
-    GstRTSPExtension *elem = (GstRTSPExtension *) walk->data;
-
-    res = gst_rtsp_extension_parse_sdp (elem, sdp, s);
-  }
-  return res;
-}
-
-GstRTSPResult
-gst_wfd_rtsp_ext_list_setup_media (GstWFDRTSPExtensionList * ext, GstSDPMedia * media)
-{
-  GList *walk;
-  GstRTSPResult res = GST_RTSP_OK;
-
-  for (walk = ext->extensions; walk; walk = g_list_next (walk)) {
-    GstRTSPExtension *elem = (GstRTSPExtension *) walk->data;
-
-    res = gst_rtsp_extension_setup_media (elem, media);
-  }
-  return res;
-}
-
-gboolean
-gst_wfd_rtsp_ext_list_configure_stream (GstWFDRTSPExtensionList * ext, GstCaps * caps)
-{
-  GList *walk;
-  gboolean res = TRUE;
-
-  for (walk = ext->extensions; walk; walk = g_list_next (walk)) {
-    GstRTSPExtension *elem = (GstRTSPExtension *) walk->data;
-
-    res = gst_rtsp_extension_configure_stream (elem, caps);
-    if (!res)
-      break;
-  }
-  return res;
-}
-
-GstRTSPResult
-gst_wfd_rtsp_ext_list_get_transports (GstWFDRTSPExtensionList * ext,
-    GstRTSPLowerTrans protocols, gchar ** transport)
-{
-  GList *walk;
-  GstRTSPResult res = GST_RTSP_OK;
-
-  for (walk = ext->extensions; walk; walk = g_list_next (walk)) {
-    GstRTSPExtension *elem = (GstRTSPExtension *) walk->data;
-
-    res = gst_rtsp_extension_get_transports (elem, protocols, transport);
-  }
-  return res;
-}
-
-GstRTSPResult
-gst_wfd_rtsp_ext_list_stream_select (GstWFDRTSPExtensionList * ext, GstRTSPUrl * url)
-{
-  GList *walk;
-  GstRTSPResult res = GST_RTSP_OK;
-
-  for (walk = ext->extensions; walk; walk = g_list_next (walk)) {
-    GstRTSPExtension *elem = (GstRTSPExtension *) walk->data;
-
-    res = gst_rtsp_extension_stream_select (elem, url);
-  }
-  return res;
-}
-
-void
-gst_wfd_rtsp_ext_list_connect (GstWFDRTSPExtensionList * ext,
-    const gchar * detailed_signal, GCallback c_handler, gpointer data)
-{
-  GList *walk;
-
-  for (walk = ext->extensions; walk; walk = g_list_next (walk)) {
-    GstRTSPExtension *elem = (GstRTSPExtension *) walk->data;
-
-    g_signal_connect (elem, detailed_signal, c_handler, data);
-  }
-}
-
-GstRTSPResult
-gst_wfd_rtsp_ext_list_receive_request (GstWFDRTSPExtensionList * ext,
-    GstRTSPMessage * req)
-{
-  GList *walk;
-  GstRTSPResult res = GST_RTSP_ENOTIMPL;
-
-  for (walk = ext->extensions; walk; walk = g_list_next (walk)) {
-    GstRTSPExtension *elem = (GstRTSPExtension *) walk->data;
-
-    res = gst_rtsp_extension_receive_request (elem, req);
-    if (res != GST_RTSP_ENOTIMPL)
-      break;
-  }
-  return res;
-}
diff --git a/wfdmanager/src/gstwfdrtspext.h b/wfdmanager/src/gstwfdrtspext.h
deleted file mode 100755 (executable)
index f95b69e..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * wfdrtspext
- *
- * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Alternatively, the contents of this file may be used under the
- * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
- * which case the following provisions apply instead of the ones
- * mentioned above:
- *
- * 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_WFD_RTSP_EXT_H__
-#define __GST_WFD_RTSP_EXT_H__
-
-#include <gst/gst.h>
-#include <gst/rtsp/gstrtspextension.h>
-
-G_BEGIN_DECLS
-
-typedef struct _GstWFDRTSPExtensionList GstWFDRTSPExtensionList;
-
-struct _GstWFDRTSPExtensionList
-{
-  GList *extensions;
-};
-
-void                    gst_wfd_rtsp_ext_list_init    (void);
-
-GstWFDRTSPExtensionList *  gst_wfd_rtsp_ext_list_get     (void);
-void                    gst_wfd_rtsp_ext_list_free    (GstWFDRTSPExtensionList *ext);
-
-gboolean      gst_wfd_rtsp_ext_list_detect_server     (GstWFDRTSPExtensionList *ext, GstRTSPMessage *resp);
-
-GstRTSPResult gst_wfd_rtsp_ext_list_before_send       (GstWFDRTSPExtensionList *ext, GstRTSPMessage *req);
-GstRTSPResult gst_wfd_rtsp_ext_list_after_send        (GstWFDRTSPExtensionList *ext, GstRTSPMessage *req,
-                                                   GstRTSPMessage *resp);
-GstRTSPResult gst_wfd_rtsp_ext_list_parse_sdp         (GstWFDRTSPExtensionList *ext, GstSDPMessage *sdp,
-                                                   GstStructure *s);
-GstRTSPResult gst_wfd_rtsp_ext_list_setup_media       (GstWFDRTSPExtensionList *ext, GstSDPMedia *media);
-gboolean      gst_wfd_rtsp_ext_list_configure_stream  (GstWFDRTSPExtensionList *ext, GstCaps *caps);
-GstRTSPResult gst_wfd_rtsp_ext_list_get_transports    (GstWFDRTSPExtensionList *ext, GstRTSPLowerTrans protocols,
-                                                   gchar **transport);
-GstRTSPResult gst_wfd_rtsp_ext_list_stream_select     (GstWFDRTSPExtensionList *ext, GstRTSPUrl *url);
-
-void          gst_wfd_rtsp_ext_list_connect           (GstWFDRTSPExtensionList *ext,
-                                                  const gchar *detailed_signal, GCallback c_handler,
-                                                   gpointer data);
-GstRTSPResult gst_wfd_rtsp_ext_list_receive_request   (GstWFDRTSPExtensionList *ext, GstRTSPMessage *req);
-
-G_END_DECLS
-
-#endif /* __GST_RTSP_EXT_H__ */
index f3bdb17..6782c6b 100755 (executable)
@@ -125,31 +125,11 @@ enum _GstWfdRtspSrcBufferMode
 
 #define _SET_FRAMERATE_TO_CAPS 1
 
-
-#define GST_TYPE_WFD_RTSP_NAT_METHOD (gst_wfd_rtsp_nat_method_get_type())
-static GType
-gst_wfd_rtsp_nat_method_get_type (void)
-{
-  static GType wfd_rtsp_nat_method_type = 0;
-  static const GEnumValue wfd_rtsp_nat_method[] = {
-    {GST_WFD_RTSP_NAT_NONE, "None", "none"},
-    {GST_WFD_RTSP_NAT_DUMMY, "Send Dummy packets", "dummy"},
-    {0, NULL, NULL},
-  };
-
-  if (!wfd_rtsp_nat_method_type) {
-    wfd_rtsp_nat_method_type =
-        g_enum_register_static ("GstWFDRTSPNatMethod", wfd_rtsp_nat_method);
-  }
-  return wfd_rtsp_nat_method_type;
-}
-
 /* properties default values */
 #define DEFAULT_LOCATION         NULL
 #define DEFAULT_DEBUG            FALSE
 #define DEFAULT_RETRY            20
 #define DEFAULT_TCP_TIMEOUT      20000000
-#define DEFAULT_NAT_METHOD       GST_WFD_RTSP_NAT_DUMMY
 #define DEFAULT_PROXY            NULL
 #define DEFAULT_RTP_BLOCKSIZE    0
 #define DEFAULT_USER_ID          NULL
@@ -168,7 +148,6 @@ enum
   PROP_DEBUG,
   PROP_RETRY,
   PROP_TCP_TIMEOUT,
-  PROP_NAT_METHOD,
   PROP_PROXY,
   PROP_RTP_BLOCKSIZE,
   PROP_USER_ID,
@@ -194,7 +173,7 @@ enum
 #define CMD_CLOSE      3
 #define CMD_WAIT       4
 #define CMD_LOOP       5
-#define CMD_SET_PARAM  6
+#define CMD_SEND_REQUEST       6
 
 #define GST_ELEMENT_PROGRESS(el, type, code, text)      \
 G_STMT_START {                                          \
@@ -237,10 +216,6 @@ static void gst_wfdrtspsrc_set_tcp_timeout (GstWFDRTSPSrc * src, guint64 timeout
 static gboolean gst_wfdrtspsrc_setup_auth (GstWFDRTSPSrc * src,
     GstRTSPMessage * response);
 
-static GstRTSPResult gst_wfdrtspsrc_send_cb (GstRTSPExtension * ext,
-    GstRTSPMessage * request, GstRTSPMessage * response, GstWFDRTSPSrc * src);
-
-
 static void gst_wfdrtspsrc_uri_handler_init (gpointer g_iface,
     gpointer iface_data);
 static gboolean gst_wfdrtspsrc_uri_set_uri (GstURIHandler * handler,
@@ -260,37 +235,36 @@ gst_wfdrtspsrc_send (GstWFDRTSPSrc * src, GstRTSPConnection * conn,
 
 static gboolean gst_wfdrtspsrc_parse_methods (GstWFDRTSPSrc * src, GstRTSPMessage * response);
 
-static GstRTSPResult gst_wfdrtspsrc_send_keep_alive (GstWFDRTSPSrc * src);
-
 static void gst_wfdrtspsrc_connection_flush (GstWFDRTSPSrc * src, gboolean flush);
 
 static GstRTSPResult gst_wfdrtspsrc_get_video_parameter(GstWFDRTSPSrc * src, WFDMessage *msg);
 static GstRTSPResult gst_wfdrtspsrc_get_audio_parameter(GstWFDRTSPSrc * src, WFDMessage *msg);
 
 #ifdef ENABLE_WFD_MESSAGE
-
-void __wfd_config_message_init(GstWFDRTSPSrc * src)
+static gint
+__wfd_config_message_init(GstWFDRTSPSrc * src)
 {
   src->message_handle = dlopen(WFD_MESSAGE_FEATURES_PATH, RTLD_LAZY);
   if (src->message_handle == NULL)
   {
     GST_ERROR("failed to init __wfd_config_message_init");
     src->extended_wfd_message_support = FALSE;
+    return FALSE;
   }
   else
   {
     src->extended_wfd_message_support = TRUE;
   }
-  return;
+  return TRUE;
 }
 
-void *
+static void *
 __wfd_config_message_func(GstWFDRTSPSrc *src, const char *func)
 {
   return dlsym(src->message_handle, func);
 }
 
-void
+static void
 __wfd_config_message_close(GstWFDRTSPSrc *src)
 {
   GST_DEBUG("close wfd cofig message");
@@ -365,12 +339,6 @@ gst_wfdrtspsrc_class_init (GstWFDRTSPSrcClass * klass)
           0, G_MAXUINT64, DEFAULT_TCP_TIMEOUT,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
-  g_object_class_install_property (gobject_class, PROP_NAT_METHOD,
-      g_param_spec_enum ("nat-method", "NAT Method",
-          "Method to use for traversing firewalls and NAT",
-          GST_TYPE_WFD_RTSP_NAT_METHOD, DEFAULT_NAT_METHOD,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
   g_object_class_install_property (gobject_class, PROP_PROXY,
       g_param_spec_string ("proxy", "Proxy",
           "Proxy settings for HTTP tunneling. Format: [http://][user:passwd@]host[:port]",
@@ -461,8 +429,6 @@ gst_wfdrtspsrc_class_init (GstWFDRTSPSrcClass * klass)
   gstelement_class->change_state = gst_wfdrtspsrc_change_state;
 
   gstbin_class->handle_message = gst_wfdrtspsrc_handle_message;
-
-  gst_wfd_rtsp_ext_list_init ();
 }
 
 static GstStructure *
@@ -507,7 +473,7 @@ gst_wfdrtspsrc_init (GstWFDRTSPSrc * src)
 {
   GstPadTemplate *template = NULL;
   GstPad * outpad = NULL;
-
+  gint result = FALSE;
 
 #ifdef G_OS_WIN32
   WSADATA wsa_data;
@@ -522,15 +488,11 @@ gst_wfdrtspsrc_init (GstWFDRTSPSrc * src)
   src->debug = DEFAULT_DEBUG;
   src->retry = DEFAULT_RETRY;
   gst_wfdrtspsrc_set_tcp_timeout (src, DEFAULT_TCP_TIMEOUT);
-  src->nat_method = DEFAULT_NAT_METHOD;
   gst_wfdrtspsrc_set_proxy (src, DEFAULT_PROXY);
   src->rtp_blocksize = DEFAULT_RTP_BLOCKSIZE;
   src->user_id = g_strdup (DEFAULT_USER_ID);
   src->user_pw = g_strdup (DEFAULT_USER_PW);
   src->user_agent = g_strdup (DEFAULT_USER_AGENT);
-  src->ssr_timeout.tv_sec = 0;
-  src->ssr_timeout.tv_usec = 0;
-  src->is_paused = TRUE;
   src->do_stop = FALSE;
   src->audio_param = NULL;
   src->video_param = NULL;
@@ -539,16 +501,11 @@ gst_wfdrtspsrc_init (GstWFDRTSPSrc * src)
   src->audio_param = gst_wfd_rtsp_set_default_audio_param ();
   src->video_param = gst_wfd_rtsp_set_default_video_param ();
 #ifdef ENABLE_WFD_MESSAGE
-  __wfd_config_message_init(src);
+  result = __wfd_config_message_init(src);
+  if(result == FALSE)
+    return;
 #endif
 
-  /* get a list of all extensions */
-  src->extensions = gst_wfd_rtsp_ext_list_get ();
-
-  /* connect to send signal */
-  gst_wfd_rtsp_ext_list_connect (src->extensions, "send",
-      (GCallback) gst_wfdrtspsrc_send_cb, src);
-
   /* init lock */
   g_rec_mutex_init (&(src->task_rec_lock));
 
@@ -670,7 +627,6 @@ gst_wfdrtspsrc_finalize (GObject * object)
   src = GST_WFDRTSPSRC (object);
 
   GST_INFO ("finalize");
-  gst_wfd_rtsp_ext_list_free (src->extensions);
   gst_rtsp_url_free (src->conninfo.url);
   if (src->conninfo.location)
     g_free (src->conninfo.location);
@@ -805,9 +761,6 @@ gst_wfdrtspsrc_set_property (GObject * object, guint prop_id, const GValue * val
     case PROP_TCP_TIMEOUT:
       gst_wfdrtspsrc_set_tcp_timeout (src, g_value_get_uint64 (value));
       break;
-    case PROP_NAT_METHOD:
-      src->nat_method = g_value_get_enum (value);
-      break;
     case PROP_PROXY:
       gst_wfdrtspsrc_set_proxy (src, g_value_get_string (value));
       break;
@@ -914,9 +867,6 @@ gst_wfdrtspsrc_get_property (GObject * object, guint prop_id, GValue * value,
       g_value_set_uint64 (value, timeout);
       break;
     }
-    case PROP_NAT_METHOD:
-      g_value_set_enum (value, src->nat_method);
-      break;
     case PROP_PROXY:
     {
       gchar *str;
@@ -1008,17 +958,17 @@ gst_wfdrtspsrc_connection_receive (GstWFDRTSPSrc * src, GstRTSPConnection * conn
 }
 
 static GstRTSPResult
-gst_wfdrtspsrc_prepare_set_param (GstWFDRTSPSrc * src)
+gst_wfdrtspsrc_send_request (GstWFDRTSPSrc * src)
 {
   GstRTSPMessage request = { 0 };
   GstRTSPMessage response = { 0 };
   GstRTSPResult res = GST_RTSP_OK;
   WFDResult wfd_res = WFD_OK;
-  WFDMessage *msg_no= NULL;
+  WFDMessage *wfd_msg= NULL;
   GstWFDParam param = WFD_PARAM_NONE;
-  guint msglen = 0;
-  GString *msglength = NULL;
-  gchar *msg = NULL;
+  gchar *rtsp_body = NULL;
+  guint rtsp_body_length = 0;
+  GString *rtsp_body_length_str = NULL;
 
   if (src->wfd_param == WFD_PARAM_NONE) {
     GST_ERROR_OBJECT (src, "no wfd messag to be sent...");
@@ -1033,83 +983,56 @@ gst_wfdrtspsrc_prepare_set_param (GstWFDRTSPSrc * src)
   if (res < 0)
     goto error;
 
-  /* Create set_parameter body to be sent in the request */
-  WFDCONFIG_MESSAGE_NEW (&msg_no, wfd_res);
-
-  if (wfd_res != WFD_OK) {
-    GST_ERROR_OBJECT (src, "Failed to create wfd message...");
-    res = GST_RTSP_ERROR;
-    goto error;
-  }
+  gst_rtsp_message_add_header (&request, GST_RTSP_HDR_USER_AGENT, (const gchar*)src->user_agent);
 
-  WFDCONFIG_MESSAGE_INIT(msg_no, wfd_res);
-  if (wfd_res != WFD_OK) {
-    GST_ERROR_OBJECT (src, "Failed to init wfd message...");
-    res = GST_RTSP_ERROR;
-    goto error;
-  }
+  /* Create set_parameter body to be sent in the request */
+  WFDCONFIG_MESSAGE_NEW (&wfd_msg, error);
+  WFDCONFIG_MESSAGE_INIT(wfd_msg, error);
 
   switch(param) {
-
-    case WFD_ROUTE: {
-      WFDCONFIG_SET_AUDIO_SINK_TYPE(msg_no, WFD_SECONDARY_SINK, wfd_res);
-      if (wfd_res != WFD_OK) {
-        GST_ERROR_OBJECT (src, "Failed to set audio sink type...");
-        res = GST_RTSP_ERROR;
-        goto error;
-      }
+    case WFD_ROUTE:
+     /* Note : RTSP M10  :
+      *   Send RTSP SET_PARAMETER with wfd-route to change the WFD sink at which audio is rendered.
+      *   Applies only when both a primary and secondary sinks are in WFD session with a WFD source.
+      */
+      WFDCONFIG_SET_AUDIO_SINK_TYPE(wfd_msg, WFD_SECONDARY_SINK, error);
       break;
-    }
 
-    case WFD_CONNECTOR_TYPE: {
-      WFDCONFIG_SET_CONNECTOR_TYPE(msg_no, WFD_CONNECTOR_VGA, wfd_res);
-      if (wfd_res != WFD_OK) {
-        GST_ERROR_OBJECT (src, "Failed to set connector type...");
-        res = GST_RTSP_ERROR;
-        goto error;
-      }
+    case WFD_CONNECTOR_TYPE:
+     /* Note : RTSP M11  :
+      *   Send RTSP SET_PARAMETER with wfd-connector-type to indicate change of active connector type,
+      *     when the WFD source and WFD sink support content protection.
+      */
+      WFDCONFIG_SET_CONNECTOR_TYPE(wfd_msg, WFD_CONNECTOR_VGA, error);
       break;
-    }
 
-    case WFD_STANDBY: {
-      WFDCONFIG_SET_STANDBY(msg_no, TRUE, wfd_res);
-      if (wfd_res != WFD_OK) {
-        GST_ERROR_OBJECT (src, "Failed to set standby...");
-        res = GST_RTSP_ERROR;
-        goto error;
-      }
+    case WFD_STANDBY:
+     /* Note : RTSP M12  :
+      *   Send RTSP SET_PARAMETER with wfd-stanby to indicate that the sender is entering WFD stanby mode.
+      */
+      WFDCONFIG_SET_STANDBY(wfd_msg, TRUE, error);
       break;
-    }
 
-    case WFD_IDR_REQUEST: {
-      WFDCONFIG_SET_IDR_REQUESTER(msg_no, wfd_res);
-      if (wfd_res != WFD_OK) {
-        GST_ERROR_OBJECT (src, "Failed to set IDR request...");
-        res = GST_RTSP_ERROR;
-        goto error;
-      }
+    case WFD_IDR_REQUEST:
+     /* Note : RTSP M13  :
+      *   Send RTSP SET_PARAMETER with wfd-idr-request to request IDR refresh.
+      */
+      WFDCONFIG_SET_IDR_REQUESTER(wfd_msg, error);
       break;
-    }
 
-    case WFD_UIBC_CAPABILITY: {
-      WFDCONFIG_SET_UIBC_CAPABILITY(msg_no, WFD_UIBC_INPUT_CAT_UNKNOWN, 0, NULL, 0, 0, wfd_res);
-      if (wfd_res != WFD_OK) {
-        GST_ERROR_OBJECT (src, "Failed to set UIBC capability...");
-        res = GST_RTSP_ERROR;
-        goto error;
-      }
+    case WFD_UIBC_CAPABILITY:
+     /* Note : RTSP M14  :
+      *   Send RTSP SET_PARAMETER with wfd-uibc-capability to select UIBC to be used.
+      */
+      WFDCONFIG_SET_UIBC_CAPABILITY(wfd_msg, WFD_UIBC_INPUT_CAT_UNKNOWN, 0, NULL, 0, 0, error);
       break;
-    }
 
-    case WFD_UIBC_SETTING: {
-      WFDCONFIG_SET_UIBC_STATUS(msg_no, TRUE, wfd_res);
-      if (wfd_res != WFD_OK) {
-        GST_ERROR_OBJECT (src, "Failed to set UIBC setting...");
-        res = GST_RTSP_ERROR;
-        goto error;
-      }
+    case WFD_UIBC_SETTING:
+     /* Note : RTSP M15 :
+      *   Send RTSP SET_PARAMETER with wfd-uibc-setting to enable or disable the UIBC.
+      */
+      WFDCONFIG_SET_UIBC_STATUS(wfd_msg, TRUE, error);
       break;
-    }
 
     default:
       GST_ERROR_OBJECT (src, "Unhandled WFD message type...");
@@ -1117,42 +1040,29 @@ gst_wfdrtspsrc_prepare_set_param (GstWFDRTSPSrc * src)
       break;
   }
 
-  WFDCONFIG_MESSAGE_DUMP(msg_no, wfd_res);
-  if (wfd_res != WFD_OK) {
-    GST_ERROR_OBJECT (src, "Failed to dump wfd message...");
-    res = GST_RTSP_ERROR;
-    goto error;
-  }
+  WFDCONFIG_MESSAGE_DUMP(wfd_msg);
+  WFDCONFIG_MESSAGE_AS_TEXT(wfd_msg, rtsp_body, error);
 
-  WFDCONFIG_MESSAGE_AS_TEXT(msg_no, msg);
-  if (msg == NULL) {
-    GST_ERROR_OBJECT (src, "Failed to get wfd message as text...");
-    res = GST_RTSP_ERROR;
+  if(rtsp_body == NULL)
     goto error;
-  }
 
-  msglen = strlen(msg);
-  msglength = g_string_new ("");
-  g_string_append_printf (msglength,"%d",msglen);
+  rtsp_body_length = strlen(rtsp_body);
+  rtsp_body_length_str = g_string_new ("");
+  g_string_append_printf (rtsp_body_length_str,"%d",rtsp_body_length);
 
-  res = gst_rtsp_message_add_header (&request, GST_RTSP_HDR_USER_AGENT, (const gchar*)src->user_agent);
+  GST_DEBUG ("WFD message body: %s", rtsp_body);
 
-  GST_DEBUG ("WFD message body: %s", msg);
   /* add content-length type */
-  res = gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CONTENT_LENGTH, g_string_free (msglength, FALSE));
-  if (res != GST_RTSP_OK) {
-    GST_ERROR_OBJECT (src, "Failed to add header to rtsp request...");
-    goto error;
-  }
+  gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CONTENT_LENGTH, g_string_free (rtsp_body_length_str, FALSE));
 
   /* adding wfdconfig data to request */
-  res = gst_rtsp_message_set_body (&request,(guint8 *)msg, msglen);
+  res = gst_rtsp_message_set_body (&request,(guint8 *)rtsp_body, rtsp_body_length);
   if (res != GST_RTSP_OK) {
     GST_ERROR_OBJECT (src, "Failed to set body to rtsp request...");
     goto error;
   }
 
-  WFDCONFIG_MESSAGE_FREE(msg_no);
+  WFDCONFIG_MESSAGE_FREE(wfd_msg);
 
   /* send request message  */
   GST_DEBUG_OBJECT (src, "send reuest...");
@@ -1168,10 +1078,14 @@ gst_wfdrtspsrc_prepare_set_param (GstWFDRTSPSrc * src)
 /* ERRORS */
 error:
  {
-    if(msg_no)
-      WFDCONFIG_MESSAGE_FREE(msg_no);
+    if(wfd_msg)
+      WFDCONFIG_MESSAGE_FREE(wfd_msg);
     gst_rtsp_message_unset (&request);
     gst_rtsp_message_unset (&response);
+    if(wfd_res != WFD_OK) {
+      GST_ERROR_OBJECT(src, "Message config error : %d", wfd_res);
+      return GST_RTSP_ERROR;
+    }
     return res;
  }
 }
@@ -1205,7 +1119,7 @@ gst_wfdrtspsrc_handle_src_event (GstPad * pad, GstObject *parent, GstEvent * eve
       if (gst_structure_has_name (s, "GstWFDIDRRequest")) {
         /* Send IDR request */
         src->wfd_param = WFD_IDR_REQUEST;
-        gst_wfdrtspsrc_loop_send_cmd(src, CMD_SET_PARAM);
+        gst_wfdrtspsrc_loop_send_cmd(src, CMD_SEND_REQUEST);
       }
       break;
     default:
@@ -1274,32 +1188,6 @@ gst_wfdrtspsrc_handle_src_query (GstPad * pad, GstObject *parent, GstQuery * que
   return res;
 }
 
-
-/* send a couple of dummy random packets on the receiver RTP port to the server,
- * this should make a firewall think we initiated the data transfer and
- * hopefully allow packets to go from the sender port to our RTP receiver port */
-static gboolean
-gst_wfdrtspsrc_send_dummy_packets (GstWFDRTSPSrc * src)
-{
-  WFDRTSPManager *manager = src->manager;
-
-  if (src->nat_method != GST_WFD_RTSP_NAT_DUMMY)
-    return TRUE;
-
-  if (manager) {
-    if (manager->fakesrc && manager->udpsink[0]) {
-      GST_DEBUG_OBJECT (src, "sending dummy packet to manager %p", manager);
-      gst_element_set_state (manager->udpsink[0], GST_STATE_NULL);
-      gst_element_set_state (manager->fakesrc, GST_STATE_NULL);
-      gst_element_set_state (manager->udpsink[0], GST_STATE_PLAYING);
-      gst_element_set_state (manager->fakesrc, GST_STATE_PLAYING);
-    }
-  }
-
-  return TRUE;
-}
-
-
 static void
 gst_wfdrtspsrc_configure_caps (GstWFDRTSPSrc * src)
 {
@@ -1395,19 +1283,6 @@ gst_wfdrtspsrc_stream_push_event (WFDRTSPManager * manager, GstEvent * event, gb
       res &= gst_pad_send_event (manager->channelpad[1], event);
   }
 
-#if 0
-  if (source && manager->udpsrc[2]) {
-    gst_event_ref (event);
-    res &= gst_element_send_event (manager->udpsrc[2], event);
-  } else if (manager->channelpad[2]) {
-    gst_event_ref (event);
-    if (GST_PAD_IS_SRC (manager->channelpad[2]))
-      res &= gst_pad_push_event (manager->channelpad[2], event);
-    else
-      res &= gst_pad_send_event (manager->channelpad[2], event);
-  }
-#endif
-
 done:
   gst_event_unref (event);
 
@@ -1533,18 +1408,6 @@ gst_wfdrtspsrc_conninfo_close (GstWFDRTSPSrc * src, GstWFDRTSPConnInfo * info,
   return GST_RTSP_OK;
 }
 
-static GstRTSPResult
-gst_wfdrtspsrc_conninfo_reconnect (GstWFDRTSPSrc * src, GstWFDRTSPConnInfo * info)
-{
-  GstRTSPResult res;
-
-  GST_DEBUG_OBJECT (src, "reconnecting connection...");
-  gst_wfdrtspsrc_conninfo_close (src, info, FALSE);
-  res = gst_wfdrtspsrc_conninfo_connect (src, info);
-
-  return res;
-}
-
 static void
 gst_wfdrtspsrc_connection_flush (GstWFDRTSPSrc * src, gboolean flush)
 {
@@ -1568,128 +1431,108 @@ static GstRTSPResult
 gst_wfdrtspsrc_handle_request (GstWFDRTSPSrc * src, GstRTSPConnection * conn,
     GstRTSPMessage * request)
 {
+  GstRTSPMethod method = GST_RTSP_INVALID;
+  GstRTSPVersion version = GST_RTSP_VERSION_INVALID;
   GstRTSPMessage response = { 0 };
   GstRTSPResult res = GST_RTSP_OK;
-  GstRTSPMethod method;
+  WFDResult wfd_res = WFD_OK;
   const gchar *uristr;
-  GstRTSPVersion version;
-  GstRTSPMethod options;
-  gchar *str;
-  guint8 *data;
-  guint size;
-
-  GST_DEBUG_OBJECT (src, "got server request message");
-
-  res = gst_wfd_rtsp_ext_list_receive_request (src->extensions, request);
+  guint8 *data = NULL;
+  guint size = 0;
+  WFDMessage *wfd_msg = NULL;
 
-  gst_rtsp_message_parse_request (request, &method, &uristr, &version);
+  res = gst_rtsp_message_parse_request (request, &method, &uristr, &version);
+  if (res < 0)
+    goto send_error;
 
   if (version != GST_RTSP_VERSION_1_0) {
     /* we can only handle 1.0 requests */
     res = GST_RTSP_ENOTIMPL;
+    goto send_error;
   }
 
+  GST_DEBUG_OBJECT (src, "got %s request", gst_rtsp_method_as_text(method));
+
   if (src->debug)
     wfd_rtsp_manager_message_dump (request);
 
   switch(method) {
     case GST_RTSP_OPTIONS:
     {
-      gchar *tmp = NULL;
-      char *options_str = NULL;
-
-      options = GST_RTSP_GET_PARAMETER |GST_RTSP_SET_PARAMETER;
-
-      str = gst_rtsp_options_as_text (options);
-
-      tmp = g_strdup (", org.wfa.wfd1.0");
-
-      GST_LOG ("tmp = %s\n\n", tmp);
-
-      options_str = (char *) malloc (strlen(tmp) + strlen (str) + 1);
-      if (!options_str) {
-        GST_ERROR ("Failed to allocate memory...");
-        res = GST_RTSP_ENOMEM;
+      /* Note : RTSP M1 :
+       *   A WFD source shall send an RTSP M1 request to a WFD sink to begin the RTSP procedures and a WFD Capability Negotiation.
+       *   A WFD sink shall respond with an RTSP M1 response message which contains an RTSP OPTIONS.
+       */
+      res = gst_rtsp_message_init_response (&response, GST_RTSP_STS_OK, gst_rtsp_status_as_text (GST_RTSP_STS_OK), request);
+      if (res < 0)
         goto send_error;
-      } else {
-        strncpy (options_str, str, strlen (str));
-        strncpy (options_str+strlen(str), tmp, strlen (tmp));
-        options_str [strlen(tmp) + strlen (str)] = '\0';
 
-        GST_LOG ("\n\noptions_str = %s\n\n", options_str);
-      }
-      GST_DEBUG_OBJECT (src, "Creating OPTIONS response");
-
-      res = gst_rtsp_message_init_response (&response, GST_RTSP_STS_OK,
-          gst_rtsp_status_as_text (GST_RTSP_STS_OK), request);
-      if(res < 0) {
-        if(options_str)
-          g_free (options_str);
-        goto send_error;
-      }
-      gst_rtsp_message_add_header (&response, GST_RTSP_HDR_PUBLIC, options_str);
+      gst_rtsp_message_add_header (&response, GST_RTSP_HDR_PUBLIC, (const gchar *)"org.wfa.wfd1.0");
+      gst_rtsp_message_add_header (&response, GST_RTSP_HDR_PUBLIC, gst_rtsp_options_as_text(GST_RTSP_SET_PARAMETER));
+      gst_rtsp_message_add_header (&response, GST_RTSP_HDR_PUBLIC, gst_rtsp_options_as_text(GST_RTSP_GET_PARAMETER));
+      gst_rtsp_message_add_header (&response, GST_RTSP_HDR_PUBLIC, gst_rtsp_options_as_text(GST_RTSP_TEARDOWN));
+      gst_rtsp_message_add_header (&response, GST_RTSP_HDR_PUBLIC, gst_rtsp_options_as_text(GST_RTSP_OPTIONS));
+      gst_rtsp_message_add_header (&response, GST_RTSP_HDR_PUBLIC, gst_rtsp_options_as_text(GST_RTSP_PLAY));
+      gst_rtsp_message_add_header (&response, GST_RTSP_HDR_PUBLIC, gst_rtsp_options_as_text(GST_RTSP_SETUP));
       gst_rtsp_message_add_header (&response, GST_RTSP_HDR_USER_AGENT, (const gchar*)src->user_agent);
-      if(options_str)
-        g_free (options_str);
       break;
     }
 
     case GST_RTSP_GET_PARAMETER:
     {
-      gchar *msg = NULL;
-      guint msglen = 0;
-      GString *msglength = NULL;
-      WFDMessage *msg3rep = NULL;
-      WFDResult wfd_res = WFD_OK;
-
-      GST_DEBUG_OBJECT (src, "Got GET_PARAMETER request");
+      gchar *rtsp_body = NULL;
+      guint rtsp_body_length = 0;
+      GString *rtsp_body_length_str = NULL;
 
       res = gst_rtsp_message_init_response (&response, GST_RTSP_STS_OK, gst_rtsp_status_as_text (GST_RTSP_STS_OK), request);
-      if(res < 0)
+      if (res < 0)
         goto send_error;
 
       gst_rtsp_message_add_header (&response, GST_RTSP_HDR_CONTENT_TYPE, "text/parameters");
       gst_rtsp_message_add_header (&response, GST_RTSP_HDR_USER_AGENT, (const gchar*)src->user_agent);
 
-      gst_rtsp_message_get_body (request, &data, &size);
+      res = gst_rtsp_message_get_body (request, &data, &size);
+      if (res < 0)
+        goto send_error;
 
-      /* Check if message is keep-alive if body is empty*/
-      if(size==0) {
-        res = gst_rtsp_message_init_response (&response, GST_RTSP_STS_OK, "OK",
-              request);
-        gst_rtsp_connection_reset_timeout (src->conninfo.connection);
+      if (size==0) {
+        /* Note : RTSP M16 : WFD keep-alive :
+         *   The WFD keep-alive function is used to periodically ensure the status of WFD sesion.
+         *   A WFD source indicates the timeout value via the "Session:" line in the RTSP M6 response.
+         *   A WFD sink shall respond with an RTSP M16 request message upon successful receiving the RTSP M16 request message.
+         */
+        res = gst_rtsp_connection_reset_timeout (src->conninfo.connection);
         if (res < 0)
           goto send_error;
-        break;
-      }
 
-      /* Creating WFD parameters supported to send as response for
-        * GET_PARAMETER request from server*/
-
-      WFDCONFIG_MESSAGE_NEW(&msg3rep, wfd_res);
-      if(msg3rep == NULL || wfd_res != WFD_OK) {
-        res = GST_RTSP_ERROR;
-        goto send_error;
-      }
-
-      WFDCONFIG_MESSAGE_INIT(msg3rep, wfd_res);
-      WFDCONFIG_MESSAGE_PARSE_BUFFER(data, size, msg3rep, wfd_res);
-      if(wfd_res != WFD_OK) {
-        res = GST_RTSP_ERROR;
-        goto send_error;
-      }
-      WFDCONFIG_MESSAGE_DUMP(msg3rep, wfd_res);
-      if (wfd_res != WFD_OK) {
-        GST_ERROR_OBJECT (src, "Failed to dump wfd message...");
+        break;
       }
 
-      /* Check if the request message has "wfd_audio_codecs" in it */
-      if(msg3rep->audio_codecs) {
+      if(src->extended_wfd_message_support == FALSE)
+        goto message_config_error;
+
+      WFDCONFIG_MESSAGE_NEW(&wfd_msg, message_config_error);
+      WFDCONFIG_MESSAGE_INIT(wfd_msg, message_config_error);
+      WFDCONFIG_MESSAGE_PARSE_BUFFER(data, size, wfd_msg, message_config_error);
+      WFDCONFIG_MESSAGE_DUMP(wfd_msg);
+
+      /* Note : RTSP M3 :
+       *   The WFD source shall send RTSP M3 request to the WFD sink to query the WFD sink's attributes and capabilities.
+       *   A WFD sink shall respond with an RTSP M3 response message which contains the values of the requested parameters.
+       *   The WFD source may query all parameters at once with a single RTSP M3 request message or may send separate RTSP M3 request message.
+       *   The WFD sink shall only response with formats and settings that it can accept in the following RTSP M4 message exchnage.
+       */
+      /* Note : wfd-audio-codecs :
+       *    The wfd-audio-codecs parameter specifies the audio formats supported in the WFD session.
+       *    Valid audio codecs are LPCM, AAC, AC3.
+       *    Primary sink should support one of audio codecs.
+       */
+      if(wfd_msg->audio_codecs) {
         guint audio_codec = 0;
         guint audio_sampling_frequency = 0;
         guint audio_channels = 0;
         guint audio_latency = 0;
-        //reading audio parameters which are set from sink ini file
+
         if(src->audio_param != NULL) {
           if (gst_structure_has_field (src->audio_param, "audio_codec"))
             gst_structure_get_uint (src->audio_param, "audio_codec", &audio_codec);
@@ -1701,12 +1544,21 @@ gst_wfdrtspsrc_handle_request (GstWFDRTSPSrc * src, GstRTSPConnection * conn,
             gst_structure_get_uint (src->audio_param, "audio_sampling_frequency", &audio_sampling_frequency);
         }
 
-        WFDCONFIG_SET_SUPPORTED_AUDIO_FORMAT(msg3rep, audio_codec,
-            audio_sampling_frequency, audio_channels, 16, audio_latency, wfd_res);
+        WFDCONFIG_SET_SUPPORTED_AUDIO_FORMAT(wfd_msg,
+          audio_codec,
+          audio_sampling_frequency,
+          audio_channels,
+          16,
+          audio_latency,
+          message_config_error);
       }
 
-      /* Check if the request message has "wfd_video_formats" in it */
-      if(msg3rep->video_formats) {
+      /* Note : wfd-video-formats :
+       *    The wfd-video-formats parameter specifies the supported video resolutions,
+       *    H.644 codec profile, level, decoder latency,  minimum slice size, slice encoding parameters
+       *      and support for video frame rate control (including explicit frame rate change and implicit video frame skipping.
+       */
+      if(wfd_msg->video_formats) {
         guint video_codec = 0;
         guint video_native_resolution = 0;
         guint video_cea_support = 0;
@@ -1721,7 +1573,6 @@ gst_wfdrtspsrc_handle_request (GstWFDRTSPSrc * src, GstRTSPConnection * conn,
         gint video_slice_enc_param = 0;
         gint video_framerate_control_support = 0;
 
-        //reading video parameters which are set from sink ini file
         if (src->video_param != NULL) {
           if (gst_structure_has_field (src->video_param, "video_codec"))
             gst_structure_get_uint (src->video_param, "video_codec", &video_codec);
@@ -1751,8 +1602,7 @@ gst_wfdrtspsrc_handle_request (GstWFDRTSPSrc * src, GstRTSPConnection * conn,
             gst_structure_get_int (src->video_param, "video_framerate_control_support", &video_framerate_control_support);
         }
 
-
-        WFDCONFIG_SET_SUPPORTED_VIDEO_FORMAT(msg3rep,
+        WFDCONFIG_SET_SUPPORTED_VIDEO_FORMAT(wfd_msg,
             video_codec,
             WFD_VIDEO_CEA_RESOLUTION,
             video_native_resolution,
@@ -1767,148 +1617,198 @@ gst_wfdrtspsrc_handle_request (GstWFDRTSPSrc * src, GstRTSPConnection * conn,
             video_minimum_slicing,
             video_slice_enc_param,
             video_framerate_control_support,
-            wfd_res);
-      }
-
-      /* Check if the request has "wfd_client_rtp_ports" in it */
-      if(msg3rep->client_rtp_ports) {
-        /* Hardcoded as of now. This is to comply with dongle port settings.
-        This should be derived from gst_wfdrtspsrc_alloc_udp_ports */
-        src->primary_rtpport = 19000;
-        src->secondary_rtpport = 0;
-        WFDCONFIG_SET_PREFERD_RTP_PORT(msg3rep,
-                     WFD_RTSP_TRANS_RTP,
-                     WFD_RTSP_PROFILE_AVP,
-                     WFD_RTSP_LOWER_TRANS_UDP,
-                     src->primary_rtpport,
-                     src->secondary_rtpport,
-                     wfd_res);
+            message_config_error);
       }
 
-      if(wfd_res != WFD_OK) {
-        res = GST_RTSP_ERROR;
-        goto send_error;
-      }
-
-      /* Check if the request has "wfd_3d_video_formats " in it */
-      if(msg3rep->video_3d_formats) {
-        /* TODO: Set preferred 3d_video_formats */
+      /* Note : wfd-3d-formats :
+       *    The wfd-3d-formats parameter specifies the support for stereoscopic video capabilities.
+       */
+      if(wfd_msg->video_3d_formats) {
+        /* TODO : Set preferred video_3d_formats */
         wfd_res = WFD_OK;
       }
 
-      /* When set preferred 3d_video_formats is done, following block need to be uncommented */
-      /*if(wfd_res != WFD_OK) {
-      res = GST_RTSP_ERROR;
-      goto send_error;
-      }*/
-
-      /* Check if the request has "wfd_content_protection " in it */
-      if(msg3rep->content_protection) {
+      /* Note : wfd-content-protection :
+       *   The wfd-content-protection parameter specifies whether the WFD sink supports the HDCP system 2.0/2.1 for content protection.
+       */
+     if(wfd_msg->content_protection) {
         gint hdcp_version = 0;
         gint hdcp_port_no = 0;
-        //reading hdcp parameters which are set from sink ini file
+
         if (src->hdcp_param != NULL) {
-          if (gst_structure_has_field (src->hdcp_param, "hdcp_version")) {
+          if (gst_structure_has_field (src->hdcp_param, "hdcp_version"))
             gst_structure_get_int (src->hdcp_param, "hdcp_version", &hdcp_version);
-            GST_DEBUG_OBJECT(src, "hdcp version : %d", hdcp_version);
-          }
-
-          if (gst_structure_has_field (src->hdcp_param, "hdcp_port_no")) {
+          if (gst_structure_has_field (src->hdcp_param, "hdcp_port_no"))
             gst_structure_get_int (src->hdcp_param, "hdcp_port_no", &hdcp_port_no);
-            GST_DEBUG_OBJECT(src, "hdcp_port_no : %d", hdcp_port_no);
-          }
-        } else {
-            GST_DEBUG_OBJECT(src, "No HDCP");
         }
-        WFDCONFIG_SET_CONTPROTECTION_TYPE(msg3rep, hdcp_version, (guint32)hdcp_port_no, wfd_res);
-      }
 
-      if(wfd_res != WFD_OK) {
-        res = GST_RTSP_ERROR;
-        goto send_error;
+        WFDCONFIG_SET_CONTENT_PROTECTION_TYPE(wfd_msg,
+          hdcp_version,
+          (guint32)hdcp_port_no,
+          message_config_error);
       }
-      /* Check if the request has "wfd_display_edid" in it */
-      if(msg3rep->display_edid) {
+
+      /* Note : wfd-display-edid :
+       *   The wfd-display-edid parameter specifies the EDID of the display on which the content will be rendered.
+       *   EDID data comes in multiples of 128-byte blocks of EDID data depending on the EDID structure that it supports.
+       *   If a WFD sink reports wfd-connector-type as HDMI or DP or UDI, the WFD sink should return the EDID of the display that renders the streamed video.
+       *   The WFD sink dongle without an integrated display or with an integrated display that is not being used to render streamed video
+       *     shall not set the edid filed of the wfd-display-edid paramter to "none" regardless of whether an external display devices is attached or not.
+       */
+      if(wfd_msg->display_edid) {
         /* TODO: Set preferred display_edid */
         wfd_res = WFD_OK;
       }
 
-      /* when set preferred display_edid following block need to be uncommented. */
-      /*if(wfd_res != WFD_OK) {
-      res = GST_RTSP_ERROR;
-      goto send_error;
-      }*/
-
-      /* Check if the request has "wfd_coupled_sink" in it */
-      if(msg3rep->coupled_sink) {
-        //wfd_res = wfdconfig_set_coupled_sink(msg3rep, WFD_SINK_NOT_COUPLED, NULL);
+      /* Note : wfd-coupled-sink :
+       *   The wfd-coupled-sink parameter is used by a WFD sink to convey its coupled status
+       *     and if coupled to another WFD sink, the coupled WFD sink's MAC address
+       */
+      if(wfd_msg->coupled_sink) {
         /* To test with dummy coupled sink address */
-        WFDCONFIG_SET_COUPLED_SINK(msg3rep,WFD_SINK_COUPLED,(gchar *)"1.0.0.1:435", wfd_res);
+        WFDCONFIG_SET_COUPLED_SINK(wfd_msg,
+          WFD_SINK_COUPLED,
+          (gchar *)"1.0.0.1:435",
+          message_config_error);
       }
 
-      if(wfd_res != WFD_OK) {
-        res = GST_RTSP_ERROR;
-        goto send_error;
+      /* Note : wfd-client-rtp-ports :
+       *   The wfd-coupled-sink parameter is used by a WFD sink to convey the RTP port(s) that the WFD sink is listening on
+       *     and by the a WFD source to indicate how audio, video or both audio and video payload will be encapsulated in the MPEG2-TS stream
+       *     transmitted from the WFD source to the WFD sink.
+       */
+      if(wfd_msg->client_rtp_ports) {
+        /* Hardcoded as of now. This is to comply with dongle port settings.
+        This should be derived from gst_wfdrtspsrc_alloc_udp_ports */
+        src->primary_rtpport = 19000;
+        src->secondary_rtpport = 0;
+        WFDCONFIG_SET_PREFERD_RTP_PORT(wfd_msg,
+          WFD_RTSP_TRANS_RTP,
+          WFD_RTSP_PROFILE_AVP,
+          WFD_RTSP_LOWER_TRANS_UDP,
+          src->primary_rtpport,
+          src->secondary_rtpport,
+          message_config_error);
+      }
+
+      /* Note : wfd-I2C :
+       *   The wfd-I2C parameter is used by a WFD source to inquire whether a WFD sink supports remote I2C read/write function or not.
+       *   If the WFD sink supports remote I2C read/write function, it shall set the value of this parameter to the TCP port number
+       *     to be used by the WFD source to exchange remote I2C read/write messaging transactions with the WFD sink.
+       */
+      if(wfd_msg->I2C) {
+        /* TODO */
+        wfd_res = WFD_OK;
+      }
+
+      /* Note : wfd-uibc-capability :
+       *   The wfd-I2C parameter describes support for the use input back channel and related attributes.
+       *   The WFD source indicates the TCP port number to be used for UIBC in the tcp-port filed in RTSP M4 and/or M14 request messages.
+       *   The WFD sink uses "none" for the tcp-port filed of the wfd-uibc-capability paramter, in RTSP M3 response and M14 request message.
+       */
+      if(wfd_msg->uibc_capability) {
+        /* TODO */
+        wfd_res = WFD_OK;
+      }
+
+      /* Note : wfd-connector-type :
+       *   The WFD source may send wfd-connector-type parameter to inquire about the connector type that is currently active in the WFD sink.
+       *   The WFD sink shall not send wfd-connector-type parameter unless the WFD source support this parameter.
+       *   The WFD sink dongle that is not connected to an external display and it is not acting as a WFD sink with embedded display
+       *     (to render streamed content) shall return a value of "none". Otherwise, the WFD sink shall choose a non-reserved value.
+       */
+      if(wfd_msg->connector_type) {
+        /* TODO */
+        wfd_res = WFD_OK;
       }
-      WFDCONFIG_MESSAGE_AS_TEXT(msg3rep, msg);
 
-      msglen = strlen(msg);
-      msglength = g_string_new ("");
-      g_string_append_printf (msglength,"%d",msglen);
+      /* Note : wfd-standby-resume-capability :
+       *   The wfd-standby-resume-capability parameter describes support of both stanby control using
+       *     a wfd-stanby parameter and resume control using PLAY and using triggered-method setting PLAY.
+       */
+      if(wfd_msg->standby_resume_capability) {
+        /* TODO */
+        wfd_res = WFD_OK;
+      }
 
-      GST_DEBUG_OBJECT (src, "GET_PARAMETER response message body: %s\n\n", msg);
+      WFDCONFIG_MESSAGE_AS_TEXT(wfd_msg, rtsp_body, message_config_error);
 
-      gst_rtsp_message_set_body (&response, (guint8*) msg, msglen);
+      rtsp_body_length = strlen(rtsp_body);
+      rtsp_body_length_str = g_string_new ("");
+      g_string_append_printf (rtsp_body_length_str,"%d", rtsp_body_length);
 
-      WFDCONFIG_MESSAGE_FREE(msg3rep);
+      //gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CONTENT_LENGTH, g_string_free (rtsp_body_length_str, FALSE));
+
+      res = gst_rtsp_message_set_body (&response, (guint8*)rtsp_body, rtsp_body_length);
+      if (res < 0)
+        goto send_error;
 
       break;
-      
     }
 
     case GST_RTSP_SET_PARAMETER:
     {
-      WFDMessage *msg = NULL;
-      WFDResult wfd_res = WFD_OK;
-
-      GST_DEBUG_OBJECT (src, "Got SET_PARAMETER request");
-
-      res = gst_rtsp_message_init_response (&response, GST_RTSP_STS_OK,
-            gst_rtsp_status_as_text (GST_RTSP_STS_OK), request);
+      res = gst_rtsp_message_init_response (&response, GST_RTSP_STS_OK, gst_rtsp_status_as_text (GST_RTSP_STS_OK), request);
       if (res < 0)
         goto send_error;
 
       gst_rtsp_message_add_header (&response, GST_RTSP_HDR_USER_AGENT, (const gchar*)src->user_agent);
 
-      gst_rtsp_message_get_body (request, &data, &size);
-      WFDCONFIG_MESSAGE_NEW(&msg, wfd_res);
-      if(msg == NULL || wfd_res != WFD_OK) {
-        res = GST_RTSP_ERROR;
+      res = gst_rtsp_message_get_body (request, &data, &size);
+      if (res < 0)
         goto send_error;
-      }
 
-      WFDCONFIG_MESSAGE_INIT(msg, wfd_res);
-      if(wfd_res != WFD_OK) {
-        res = GST_RTSP_ERROR;
-        goto send_error;
-      }
-      WFDCONFIG_MESSAGE_PARSE_BUFFER(data, size, msg, wfd_res);
-      if(wfd_res != WFD_OK) {
-        res = GST_RTSP_ERROR;
-        goto send_error;
-      }
+      if(src->extended_wfd_message_support == FALSE)
+        goto message_config_error;
+
+      WFDCONFIG_MESSAGE_NEW(&wfd_msg, message_config_error);
+      WFDCONFIG_MESSAGE_INIT(wfd_msg, message_config_error);
+      WFDCONFIG_MESSAGE_PARSE_BUFFER(data, size, wfd_msg, message_config_error);
+      WFDCONFIG_MESSAGE_DUMP(wfd_msg);
+
+      /* Note : RTSP M4 :
+       */
+      /* Note : wfd-trigger-method :
+       *   The wfd-trigger-method parameter is used by a WFD source to trigger the WFD sink to initiate an operation with the WFD source.
+       */
+      if (wfd_msg->trigger_method) {
+        WFDTrigger trigger = WFD_TRIGGER_UNKNOWN;
+
+        WFDCONFIG_GET_TRIGGER_TYPE(wfd_msg, &trigger, message_config_error);
+
+        res = gst_wfdrtspsrc_connection_send (src, conn, &response, NULL);
+        if (res < 0)
+          goto send_error;
 
-      WFDCONFIG_MESSAGE_DUMP(msg, wfd_res);
-      if (wfd_res != WFD_OK) {
-        GST_ERROR_OBJECT (src, "Failed to dump wfd message...");
+        GST_DEBUG_OBJECT (src, "got trigger method for %s", GST_STR_NULL(wfd_msg->trigger_method->wfd_trigger_method));
+        switch(trigger) {
+          case WFD_TRIGGER_PAUSE:
+            gst_wfdrtspsrc_loop_send_cmd (src, CMD_PAUSE);
+            break;
+          case WFD_TRIGGER_PLAY:
+            gst_wfdrtspsrc_loop_send_cmd (src, CMD_PLAY);
+            break;
+          case WFD_TRIGGER_TEARDOWN:
+            gst_wfdrtspsrc_loop_send_cmd (src, CMD_CLOSE);
+            break;
+          case WFD_TRIGGER_SETUP:
+            if (!gst_wfdrtspsrc_setup (src))
+              goto setup_failed;
+            break;
+          default:
+            break;
+        }
+        goto done;
       }
-      if (msg->audio_codecs || msg->video_formats || msg->video_3d_formats) {
-        GstStructure *stream_info = NULL;
-        stream_info = gst_structure_new ("WFDStreamInfo", NULL, NULL);
 
-        /* check audio codec */
-        if(msg->audio_codecs) {
-          gst_wfdrtspsrc_get_audio_parameter(src, msg);
+      if (wfd_msg->audio_codecs || wfd_msg->video_formats || wfd_msg->video_3d_formats) {
+        GstStructure *stream_info = gst_structure_new ("WFDStreamInfo", NULL, NULL);
+
+        if(wfd_msg->audio_codecs) {
+          res = gst_wfdrtspsrc_get_audio_parameter(src, wfd_msg);
+          if(res != GST_RTSP_OK) {
+            goto message_config_error;
+          }
 
           gst_structure_set (stream_info,
               "audio_format", G_TYPE_STRING, src->audio_format,
@@ -1918,9 +1818,11 @@ gst_wfdrtspsrc_handle_request (GstWFDRTSPSrc * src, GstRTSPConnection * conn,
               NULL);
         }
 
-        /* check video formats  */
-        if(msg->video_formats) {
-          gst_wfdrtspsrc_get_video_parameter(src, msg);
+        if(wfd_msg->video_formats) {
+          res = gst_wfdrtspsrc_get_video_parameter(src, wfd_msg);
+          if(res != GST_RTSP_OK) {
+            goto message_config_error;
+          }
 
           gst_structure_set (stream_info,
               "video_format", G_TYPE_STRING, "H264",
@@ -1930,202 +1832,174 @@ gst_wfdrtspsrc_handle_request (GstWFDRTSPSrc * src, GstRTSPConnection * conn,
               NULL);
         }
 
-        /* check video formats  */
-        if(msg->video_3d_formats) {
-          guint count = 0;
-          count = msg->video_3d_formats->count;
-          GST_DEBUG_OBJECT (src, "got video 3d formats with %d count.", count);
+        if(wfd_msg->video_3d_formats) {
+        /* TO DO */
         }
 
         g_signal_emit (src, gst_wfdrtspsrc_signals[SIGNAL_UPDATE_MEDIA_INFO], 0, stream_info);
       }
 
-      /* check av format change timing  */
-      if (msg->av_format_change_timing) {
-        if (src->state != GST_RTSP_STATE_PLAYING) {
-          GST_WARNING_OBJECT(src, "could not handle wfd_av_format_change_timing before session is established");
-          break;
-        } else {
-          guint64 pts=0LL, dts=0LL;
-          gboolean need_to_flush = FALSE;
+      /* Note : wfd-presentation-url :
+       *   The wfd-presentation-url parameter describes the Universial Resource Identified (URI)
+       *     to be used in the RTSP Setup (RTSP M6) request message in order to setup the WFD session from the WFD sink to the WFD source.
+       */
+      if(wfd_msg->presentation_url) {
+        gchar *url0 = NULL, *url1 = NULL;
 
-          pts = msg->av_format_change_timing->PTS;
-          dts = msg->av_format_change_timing->DTS;
+        WFDCONFIG_GET_PRESENTATION_URL(wfd_msg, &url0, &url1, message_config_error);
 
+        g_free (src->conninfo.location);
+        src->conninfo.location = g_strdup (url0);
+        /* url1 is ignored as of now */
+      }
+
+      /* Note : wfd-client-rtp-ports :
+       *   The wfd-coupled-sink parameter is used by a WFD sink to convey the RTP port(s) that the WFD sink is listening on
+       *     and by the a WFD source to indicate how audio, video or both audio and video payload will be encapsulated in the MPEG2-TS stream
+       *     transmitted from the WFD source to the WFD sink.
+       */
+      if(wfd_msg->client_rtp_ports) {
+        WFDRTSPTransMode trans = WFD_RTSP_TRANS_UNKNOWN;
+        WFDRTSPProfile profile = WFD_RTSP_PROFILE_UNKNOWN;
+        WFDRTSPLowerTrans lowertrans = WFD_RTSP_LOWER_TRANS_UNKNOWN;
+        guint32 rtp_port0 =0, rtp_port1 =0;
+
+        WFDCONFIG_GET_PREFERD_RTP_PORT(wfd_msg, &trans, &profile, &lowertrans, &rtp_port0, &rtp_port1, message_config_error);
+      }
+
+      /* Note : wfd-preferred-display-mode :
+       *   The wfd-preferred-display-mode-supported field in a wfd-video-formats and/or in a wfd-3d-formats parameter in an RTSP M3 response message
+       *      indicates whether a WFD sink supports the prefered display mod operation or not.
+       */
+      if(wfd_msg->preferred_display_mode) {
+      }
+
+      /* Note : wfd-av-format-change-timing :
+       *   The wfd-av-format-change-timing parameter is used to signal the actual AV format change timing of the streaming data to the WFD sink.
+       *   It shall be included in an RTSP M4 request message for WFD capability re-nogotiation after a WFD session has been established.
+       */
+      if (wfd_msg->av_format_change_timing) {
+        guint64 pts=0LL, dts=0LL;
+        gboolean need_to_flush = FALSE;
+
+        WFDCONFIG_GET_AV_FORMAT_CHANGE_TIMING(wfd_msg, &pts, &dts, message_config_error);
+
+        if (src->state == GST_RTSP_STATE_PLAYING) {
           GST_DEBUG_OBJECT(src, "change format with PTS[%lld] and DTS[%lld]", pts, dts);
 
           g_signal_emit (src, gst_wfdrtspsrc_signals[SIGNAL_AV_FORMAT_CHANGE], 0, (gpointer)&need_to_flush);
 
           if (need_to_flush) {
-              wfd_rtsp_manager_flush(src->manager, TRUE);
-              wfd_rtsp_manager_flush(src->manager, FALSE);
+            wfd_rtsp_manager_flush(src->manager, TRUE);
+            wfd_rtsp_manager_flush(src->manager, FALSE);
           }
         }
       }
 
-      if(msg->presentation_url) {
-        gchar *url0, *url1;
-
-        WFDCONFIG_GET_PRESENTATION_URL(msg, &url0, &url1, wfd_res);
-        if(wfd_res == WFD_OK) {
-          g_free (src->conninfo.location);
-          src->conninfo.location = g_strdup (url0);
-          /* url1 is ignored as of now */
-        } else {
-          res = GST_RTSP_ERROR;
-          goto send_error;
-        }
+      /* Note : RTSP M10 :
+       */
+      /* Note : wfd-route :
+       *   The wfd-route parameter provides a mechanism to specify the destination to which the audio stream is to be routed.
+       */
+      if(wfd_msg->route) {
+        /* TO DO*/
       }
 
-      if(msg->standby) {
+      /* Note : RTSP M12 :
+       */
+      /* Note : wfd-standby :
+       *   The wfd-standby parameter is used to indicate that the sender is entering WFD stanby mode.
+       */
+      if(wfd_msg->standby) {
         gboolean standby_enable = FALSE;
-        WFDCONFIG_GET_STANDBY(msg, &standby_enable, wfd_res);
-        if(wfd_res == WFD_OK)
-          GST_DEBUG("M12 server set param request STANDBY %s", standby_enable?"ENABLE":"DISABLE");
+
+        WFDCONFIG_GET_STANDBY(wfd_msg, &standby_enable, message_config_error);
+
+        GST_DEBUG_OBJECT (src, "wfd source is entering stanby mode");
+      }
+
+      /* Note : RTSP M14 :
+       */
+      /* Note : wfd-uibc-capability :
+       *   The wfd-uibc-capability parameter describes support for the use input back channel and related attributes.
+       *   The WFD source indicates the TCP port number to be used for UIBC in the tcp-port filed in RTSP M4 and/or M14 request messages.
+       *   The WFD sink uses "none" for the tcp-port filed of the wfd-uibc-capability paramter, in RTSP M3 response and M14 request message.
+       */
+      if(wfd_msg->uibc_capability) {
+        guint32 input_category = 0, input_type = 0, input_type_path_count = 0;
+        WFDHIDCTypePathPair *input_pair =  NULL;
+        guint32 tcp_port = 0;
+
+        WFDCONFIG_GET_UIBC_CAPABILITY(wfd_msg, &input_category, &input_type,& input_pair, &input_type_path_count, &tcp_port, message_config_error);
+      }
+
+      /* Note : RTSP M15 :
+       */
+      /* Note : wfd-uibc-setting :
+       *   The wfd-setting parameter is used to enable and disable the UIBC.
+       *   The wfd-setting parameter may be included in the first RTSP M4 request meesage during the WFD capability negotiation,
+       *     provided that the RTSP M4 request message contains the wfd-uibc-capability parameter.
+       */
+      if(wfd_msg->uibc_setting) {
+        gboolean uibc_enable = TRUE;
+
+        WFDCONFIG_GET_UIBC_STATUS(wfd_msg, &uibc_enable, message_config_error);
+
+        GST_DEBUG_OBJECT ("UIBC is %s", uibc_enable? "enabled" : "disabled");
       }
 
-      /* DEAD CODE It will be used for UIBC implementation
-      else if(g_strrstr((gchar*)data,"wfd_standby")) {
-        gboolean uibc_enable;
-        wfd_res = wfdconfig_get_uibc_status(msg, &uibc_enable);
-        if(wfd_res == WFD_OK)
-          GST_DEBUG("M15 server set param request for UIBC %s", uibc_enable?"ENABLE":"DISABLE");
-      }*/
       break;
     }
 
     default:
     {
-      res = gst_rtsp_message_init_response (&response, GST_RTSP_STS_OK, "OK",
-            request);
+      res = gst_rtsp_message_init_response (&response, GST_RTSP_STS_OK, gst_rtsp_status_as_text (GST_RTSP_STS_OK), request);
       if (res < 0)
         goto send_error;
+
+      gst_rtsp_message_add_header (&response, GST_RTSP_HDR_USER_AGENT, (const gchar*)src->user_agent);
+
       break;
     }
   }
 
-  if (src->debug)
-    wfd_rtsp_manager_message_dump (&response);
-
-  res = gst_wfdrtspsrc_connection_send (src, conn, &response, NULL);
+  res = gst_wfdrtspsrc_connection_send (src, conn, &response, src->ptcp_timeout);
   if (res < 0)
     goto send_error;
 
-  /* Handling wfd_trigger_method: PAUSE */
-  if(method == GST_RTSP_SET_PARAMETER && g_strrstr((gchar*)data,"PAUSE")) {
-    GST_DEBUG_OBJECT (src, "trigger PAUSE \n");
-    gst_wfdrtspsrc_loop_send_cmd (src, CMD_PAUSE);
-  }
-
-  /* Handling wfd_trigger_method: RESUME */
-  if(method == GST_RTSP_SET_PARAMETER && g_strrstr((gchar*)data,"PLAY")) {
-    GST_DEBUG_OBJECT (src, "trigger RESUME \n");
-    gst_wfdrtspsrc_loop_send_cmd (src, CMD_PLAY);
-  }
-
-  /* Handling wfd_trigger_method: TEARDOWN */
-  if(method == GST_RTSP_SET_PARAMETER && g_strrstr((gchar*)data,"TEARDOWN")) {
-    GstBus *bus;
-
-    GST_DEBUG_OBJECT (src, "trigger TEARDOWN \n");
-
-    gst_wfdrtspsrc_loop_send_cmd (src, CMD_CLOSE);
-
-    bus = gst_element_get_bus(GST_ELEMENT_CAST(src));
-    if(!gst_bus_post(bus, gst_message_new_application(GST_OBJECT_CAST(src), gst_structure_new_empty("TEARDOWN")))){
-      GST_ERROR_OBJECT(src, "Failed to send TEARDOWN message\n");
-    }
-    gst_object_unref(bus);
-
-    goto exit;
-  }
-
-  /* Handling wfd_trigger_method: setup */
-  if(method == GST_RTSP_SET_PARAMETER && g_strrstr((gchar*)data,"SETUP")) {
-    src->state = GST_RTSP_STATE_INIT;
-
-    /* setup streams */
-    if (!gst_wfdrtspsrc_setup (src))
-      goto setup_failed;
-
-    src->state = GST_RTSP_STATE_READY;
-  }
+done:
+  if (src->debug)
+    wfd_rtsp_manager_message_dump (&response);
 
-exit:
   gst_rtsp_message_unset (request);
   gst_rtsp_message_unset (&response);
+  WFDCONFIG_MESSAGE_FREE(wfd_msg);
 
   return GST_RTSP_OK;
 
   /* ERRORS */
 setup_failed:
   {
+    GST_ERROR_OBJECT(src, "Error: Could not setup(error)");
     gst_rtsp_message_unset (request);
     gst_rtsp_message_unset (&response);
+    WFDCONFIG_MESSAGE_FREE(wfd_msg);
     return GST_RTSP_ERROR;
   }
-send_error:
+message_config_error:
   {
+    GST_ERROR_OBJECT(src, "Error: Message config error (%d)", wfd_res);
     gst_rtsp_message_unset (request);
     gst_rtsp_message_unset (&response);
-    return res;
-  }
-}
-
-/* send server keep-alive */
-static GstRTSPResult
-gst_wfdrtspsrc_send_keep_alive (GstWFDRTSPSrc * src)
-{
-  GstRTSPMessage request = { 0 };
-  GstRTSPResult res;
-  GstRTSPMethod method;
-  gchar *control;
-
-  GST_INFO_OBJECT (src, "creating server keep-alive");
-
-  /* find a method to use for keep-alive */
-  if (src->methods & GST_RTSP_GET_PARAMETER)
-    method = GST_RTSP_GET_PARAMETER;
-  else
-    method = GST_RTSP_OPTIONS;
-
-  control = src->conninfo.url_str;
-
-  if (control == NULL)
-    goto no_control;
-
-  res = gst_rtsp_message_init_request (&request, method, control);
-  if (res < 0)
-    goto send_error;
-
-  if (src->debug && request.body != NULL)
-    wfd_rtsp_manager_message_dump (&request);
-
-  res =
-      gst_wfdrtspsrc_connection_send (src, src->conninfo.connection, &request,
-      NULL);
-  if (res < 0)
-    goto send_error;
-
-  gst_rtsp_connection_reset_timeout (src->conninfo.connection);
-  gst_rtsp_message_unset (&request);
-
-  return GST_RTSP_OK;
-
-  /* ERRORS */
-no_control:
-  {
-    GST_WARNING_OBJECT (src, "no control url to send keepalive");
-    return GST_RTSP_OK;
+    WFDCONFIG_MESSAGE_FREE(wfd_msg);
+    return GST_RTSP_ERROR;
   }
 send_error:
   {
-    gchar *str = gst_rtsp_strresult (res);
-
-    gst_rtsp_message_unset (&request);
-    GST_ELEMENT_WARNING (src, RESOURCE, WRITE, (NULL),
-        ("Could not send keep-alive. (%s)", str));
-    g_free (str);
+    GST_ERROR_OBJECT(src, "Error: Could not send message");
+    gst_rtsp_message_unset (request);
+    gst_rtsp_message_unset (&response);
+    WFDCONFIG_MESSAGE_FREE(wfd_msg);
     return res;
   }
 }
@@ -2272,9 +2146,8 @@ gst_wfdrtspsrc_loop_send_cmd (GstWFDRTSPSrc * src, gint cmd)
 static GstFlowReturn
 gst_wfdrtspsrc_loop_udp (GstWFDRTSPSrc * src)
 {
-  GstRTSPResult res;
+  GstRTSPResult res = GST_RTSP_OK;
   GstRTSPMessage message = { 0 };
-  gint retry = 0;
 
   while (TRUE) {
     GTimeVal tv_timeout;
@@ -2301,14 +2174,10 @@ gst_wfdrtspsrc_loop_udp (GstWFDRTSPSrc * src)
         /* we got interrupted, see what we have to do */
         goto interrupt;
       case GST_RTSP_ETIMEOUT:
-        /* send keep-alive, ignore the result, a warning will be posted. */
-        GST_DEBUG_OBJECT (src, "timeout, sending keep-alive");
-        if ((res = gst_wfdrtspsrc_send_keep_alive (src)) == GST_RTSP_EINTR)
-          goto interrupt;
-       break;
+        /* timeout */
+        break;
       case GST_RTSP_EEOF:
-        /* server closed the connection. not very fatal for UDP, reconnect and
-         * see what happens. */
+        /* server closed the connection.*/
         GST_ELEMENT_WARNING (src, RESOURCE, READ, (NULL),
             ("The server closed the connection."));
         goto connect_error;
@@ -2330,18 +2199,6 @@ gst_wfdrtspsrc_loop_udp (GstWFDRTSPSrc * src)
       case GST_RTSP_MESSAGE_RESPONSE:
         /* we ignore response and data messages */
         GST_DEBUG_OBJECT (src, "ignoring response message");
-        if (src->debug)
-          wfd_rtsp_manager_message_dump (&message);
-        if (message.type_data.response.code == GST_RTSP_STS_UNAUTHORIZED) {
-          GST_DEBUG_OBJECT (src, "but is Unauthorized response ...");
-          if (gst_wfdrtspsrc_setup_auth (src, &message) && !(retry++)) {
-            GST_DEBUG_OBJECT (src, "so retrying keep-alive");
-            if ((res = gst_wfdrtspsrc_send_keep_alive (src)) == GST_RTSP_EINTR)
-              goto interrupt;
-          }
-        } else {
-          retry = 0;
-        }
         break;
       case GST_RTSP_MESSAGE_DATA:
         /* we ignore response and data messages */
@@ -2750,8 +2607,6 @@ gst_wfdrtspsrc_try_send (GstWFDRTSPSrc * src, GstRTSPConnection * conn,
   GstRTSPResult res = GST_RTSP_OK;
   GstRTSPStatusCode thecode = GST_RTSP_STS_OK;
 
-  gst_wfd_rtsp_ext_list_before_send (src->extensions, request);
-
   GST_DEBUG_OBJECT (src, "sending message");
 
   if (src->debug)
@@ -2802,8 +2657,6 @@ next:
   if (thecode != GST_RTSP_STS_OK)
     return GST_RTSP_OK;
 
-  gst_wfd_rtsp_ext_list_after_send (src->extensions, request, response);
-
   return GST_RTSP_OK;
 
   /* ERRORS */
@@ -2818,28 +2671,11 @@ send_error:
   }
 receive_error:
   {
-    switch (res) {
-      case GST_RTSP_EEOF:
-        GST_ERROR_OBJECT (src, "server closed connection, doing reconnect");
-#if 0
-        if (try == 0) {
-          try++;
-          /* if reconnect succeeds, try again */
-          if ((res = gst_wfdrtspsrc_conninfo_reconnect (src, &src->conninfo)) == 0)
-            goto again;
-        }
-#endif
-        /* only try once after reconnect, then fallthrough and error out */
-      default:
-      {
-        gchar *str = gst_rtsp_strresult (res);
+    gchar *str = gst_rtsp_strresult (res);
 
-        GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
-            ("Could not receive message. (%s)", str));
-        g_free (str);
-        break;
-      }
-    }
+    GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
+        ("Could not receive message. (%s)", str));
+    g_free (str);
     return res;
   }
 handle_request_failed:
@@ -2945,41 +2781,6 @@ error_response:
         GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL), ("%s",
                 response->type_data.response.reason));
         break;
-      case GST_RTSP_STS_MOVED_PERMANENTLY:
-      case GST_RTSP_STS_MOVE_TEMPORARILY:
-      {
-        gchar *new_location;
-        GstRTSPLowerTrans transports;
-
-        GST_DEBUG_OBJECT (src, "got redirection");
-        /* if we don't have a Location Header, we must error */
-        if (gst_rtsp_message_get_header (response, GST_RTSP_HDR_LOCATION,
-                &new_location, 0) < 0)
-          break;
-
-        /* When we receive a redirect result, we go back to the INIT state after
-         * parsing the new URI. The caller should do the needed steps to issue
-         * a new setup when it detects this state change. */
-        GST_DEBUG_OBJECT (src, "redirection to %s", new_location);
-
-        /* save current transports */
-        if (src->conninfo.url)
-          transports = src->conninfo.url->transports;
-        else
-          transports = GST_RTSP_LOWER_TRANS_UNKNOWN;
-
-        GError *err = NULL;
-        gst_wfdrtspsrc_uri_set_uri (GST_URI_HANDLER (src), new_location, &err);
-
-        /* set old transports */
-        if (src->conninfo.url && transports != GST_RTSP_LOWER_TRANS_UNKNOWN)
-          src->conninfo.url->transports = transports;
-
-        src->need_redirect = TRUE;
-        src->state = GST_RTSP_STATE_INIT;
-        res = GST_RTSP_OK;
-        break;
-      }
       case GST_RTSP_STS_NOT_ACCEPTABLE:
       case GST_RTSP_STS_NOT_IMPLEMENTED:
       case GST_RTSP_STS_METHOD_NOT_ALLOWED:
@@ -3002,14 +2803,6 @@ error_response:
   }
 }
 
-static GstRTSPResult
-gst_wfdrtspsrc_send_cb (GstRTSPExtension * ext, GstRTSPMessage * request,
-    GstRTSPMessage * response, GstWFDRTSPSrc * src)
-{
-  return gst_wfdrtspsrc_send (src, src->conninfo.connection, request, response,
-      NULL);
-}
-
 
 /* parse the response and collect all the supported methods. We need this
  * information so that we don't try to send an unsupported request to the
@@ -3068,7 +2861,7 @@ gst_wfdrtspsrc_parse_methods (GstWFDRTSPSrc * src, GstRTSPMessage * response)
      * at least DESCRIBE, SETUP, we always assume it supports PLAY as
      * well. */
     GST_DEBUG_OBJECT (src, "could not get OPTIONS");
-    src->methods = GST_RTSP_DESCRIBE | GST_RTSP_SETUP;
+    src->methods = GST_RTSP_SETUP;
   }
   /* always assume PLAY, FIXME, extensions should be able to override
    * this */
@@ -3090,17 +2883,10 @@ no_setup:
 static GstRTSPResult
 gst_wfdrtspsrc_create_transports_string (GstWFDRTSPSrc * src, gchar ** transports)
 {
-  GstRTSPResult res = GST_RTSP_OK;
   GString *result;
 
   *transports = NULL;
 
-  res =
-      gst_wfd_rtsp_ext_list_get_transports (src->extensions, GST_RTSP_LOWER_TRANS_UDP, transports);
-
-  if (res < 0)
-    return GST_RTSP_ERROR;
-
   GST_DEBUG_OBJECT (src, "got transports %s", GST_STR_NULL (*transports));
 
   /* extension listed transports, use those */
@@ -3177,15 +2963,9 @@ gst_wfdrtspsrc_setup (GstWFDRTSPSrc * src)
   manager->control_connection = src->conninfo.connection;
   GST_DEBUG_OBJECT (src, " setup: %p", manager->control_connection);
 
-  /* see if we need to configure this manager */
-  if (!gst_wfd_rtsp_ext_list_configure_stream (src->extensions, manager->caps)) {
-    GST_DEBUG_OBJECT (src, "disabled by extension");
-    goto no_setup;
-  }
-
   /* skip setup if we have no URL for it */
   if (manager->conninfo.location == NULL) {
-    GST_DEBUG_OBJECT (src, "no URL for set.");
+    GST_DEBUG_OBJECT (src, "no URL for setup");
     goto no_setup;
   }
 
@@ -3308,7 +3088,7 @@ gst_wfdrtspsrc_setup (GstWFDRTSPSrc * src)
     gst_rtsp_message_unset (&response);
   }
 
-  gst_wfd_rtsp_ext_list_stream_select (src->extensions, url);
+  src->state = GST_RTSP_STATE_READY;
 
   return TRUE;
 
@@ -3409,10 +3189,15 @@ gst_wfdrtspsrc_retrieve_wifi_parameters (GstWFDRTSPSrc * src)
 
   if(message.type == GST_RTSP_MESSAGE_REQUEST) {
     method = message.type_data.request.method;
-    if(method == GST_RTSP_OPTIONS)
-      gst_wfdrtspsrc_handle_request (src, src->conninfo.connection, &message);
-    else
+    if(method == GST_RTSP_OPTIONS) {
+      res = gst_wfdrtspsrc_handle_request (src, src->conninfo.connection, &message);
+      if (res < GST_RTSP_OK)
+        goto connect_failed;
+    } else
       goto methods_error;
+  } else {
+    GST_ERROR_OBJECT (src, "failed to receive options...");
+    goto methods_error;
   }
 
   /* create OPTIONS */
@@ -3426,8 +3211,8 @@ gst_wfdrtspsrc_retrieve_wifi_parameters (GstWFDRTSPSrc * src)
 
   /* send OPTIONS */
   GST_DEBUG_OBJECT (src, "send options...");
-  if (gst_wfdrtspsrc_send (src, src->conninfo.connection, &request, &response,
-          NULL) < 0)
+  if ((res = gst_wfdrtspsrc_send (src, src->conninfo.connection, &request, &response,
+          NULL)) < 0)
     goto send_error;
 
   /* parse OPTIONS */
@@ -3512,15 +3297,14 @@ cleanup_error:
 }
 
 
-
+/* Note : RTSP M1~M6 :
+ *   WFD session capability negotiation
+ */
 static GstRTSPResult
 gst_wfdrtspsrc_open (GstWFDRTSPSrc * src)
 {
   GstRTSPResult res;
 
-  src->methods =
-      GST_RTSP_SETUP | GST_RTSP_PLAY | GST_RTSP_PAUSE | GST_RTSP_TEARDOWN;
-
   if ((res = gst_wfdrtspsrc_retrieve_wifi_parameters (src)) < 0)
     goto open_failed;
 
@@ -3537,7 +3321,9 @@ open_failed:
   }
 }
 
-
+/* Note : RTSP M8 :
+ *   Send TEARDOWN request to WFD source.
+ */
 static GstRTSPResult
 gst_wfdrtspsrc_close (GstWFDRTSPSrc * src, gboolean only_close)
 {
@@ -3715,6 +3501,9 @@ gst_wfdrtspsrc_parse_rtpinfo (GstWFDRTSPSrc * src, gchar * rtpinfo)
   return TRUE;
 }
 
+/* Note : RTSP M7 :
+ *   Send PLAY request to WFD source. WFD source begins audio and/or video streaming.
+ */
 static GstRTSPResult
 gst_wfdrtspsrc_play (GstWFDRTSPSrc * src)
 {
@@ -3728,9 +3517,6 @@ gst_wfdrtspsrc_play (GstWFDRTSPSrc * src)
   gchar *setup_url;
   GstRTSPConnection *conn;
 
-  src->is_paused = FALSE;
-
-
   GST_DEBUG_OBJECT (src, "PLAY...");
 
   if (!(src->methods & GST_RTSP_PLAY))
@@ -3742,10 +3528,6 @@ gst_wfdrtspsrc_play (GstWFDRTSPSrc * src)
   if (!src->conninfo.connection || !src->conninfo.connected)
     goto done;
 
-  /* send some dummy packets before we activate the receive in the
-   * udp sources */
-  gst_wfdrtspsrc_send_dummy_packets (src);
-
   gst_element_set_state (GST_ELEMENT_CAST (src), GST_STATE_PLAYING);
 
   /* construct a control url */
@@ -3829,6 +3611,9 @@ send_error:
   }
 }
 
+/* Note : RTSP M9  :
+ *   Send PAUSE request to WFD source. WFD source pauses the audio video stream(s).
+ */
 static GstRTSPResult
 gst_wfdrtspsrc_pause (GstWFDRTSPSrc * src)
 {
@@ -3881,8 +3666,6 @@ gst_wfdrtspsrc_pause (GstWFDRTSPSrc * src)
   gst_rtsp_message_unset (&request);
   gst_rtsp_message_unset (&response);
 
-  src->is_paused = TRUE;
-
 no_connection:
   src->state = GST_RTSP_STATE_READY;
 
@@ -3999,7 +3782,7 @@ gst_wfdrtspsrc_thread (GstWFDRTSPSrc * src)
   gst_wfdrtspsrc_connection_flush (src, FALSE);
 
   /* we allow these to be interrupted */
-  if (cmd == CMD_LOOP || cmd == CMD_PAUSE || cmd == CMD_SET_PARAM )
+  if (cmd == CMD_LOOP || cmd == CMD_PAUSE || cmd == CMD_SEND_REQUEST )
     src->waiting = TRUE;
   GST_OBJECT_UNLOCK (src);
 
@@ -4023,8 +3806,8 @@ gst_wfdrtspsrc_thread (GstWFDRTSPSrc * src)
     case CMD_LOOP:
       running = gst_wfdrtspsrc_loop (src);
       break;
-     case CMD_SET_PARAM:
-      ret = gst_wfdrtspsrc_prepare_set_param (src);
+     case CMD_SEND_REQUEST:
+      ret = gst_wfdrtspsrc_send_request (src);
       if (ret == GST_RTSP_OK)
         running = TRUE;
       break;
@@ -4053,6 +3836,8 @@ gst_wfdrtspsrc_start (GstWFDRTSPSrc * src)
 
   GST_OBJECT_LOCK (src);
 
+  src->state = GST_RTSP_STATE_INIT;
+
   src->loop_cmd = CMD_WAIT;
 
   if (src->task == NULL) {
@@ -4630,8 +4415,13 @@ gst_wfdrtspsrc_get_audio_parameter(GstWFDRTSPSrc * src, WFDMessage * msg)
   WFDAudioFreq audio_frequency = WFD_FREQ_UNKNOWN;
   guint audio_bitwidth = 0;
   guint32 audio_latency = 0;
+  WFDResult wfd_res = WFD_OK;
 
   WFDCONFIG_GET_PREFERED_AUDIO_FORMAT(msg, &audio_format, &audio_frequency, &audio_channels, &audio_bitwidth, &audio_latency);
+  if(wfd_res != WFD_OK) {
+    GST_ERROR("Failed to get prefered audio format.");
+    return GST_RTSP_ERROR;
+  }
 
   src->audio_format = g_strdup(msg->audio_codecs->list->audio_format);
   if(audio_frequency == WFD_FREQ_48000)
@@ -4672,10 +4462,16 @@ gst_wfdrtspsrc_get_video_parameter(GstWFDRTSPSrc * src, WFDMessage * msg)
   guint32 cslice_enc_params = 0;
   guint cframe_rate_control = 0;
   guint cvLatency = 0;
+  WFDResult wfd_res = WFD_OK;
+
   WFDCONFIG_GET_PREFERED_VIDEO_FORMAT(msg, &cvCodec, &cNative, &cNativeResolution,
       &cCEAResolution, &cVESAResolution, &cHHResolution,
       &cProfile, &cLevel, &cvLatency, &cMaxHeight,
       &cMaxWidth, &cmin_slice_size, &cslice_enc_params, &cframe_rate_control);
+  if(wfd_res != WFD_OK) {
+      GST_ERROR("Failed to get prefered video format.");
+      return GST_RTSP_ERROR;
+  }
 #if 0
   switch(cNative)
   {
index 51acc25..4c82e83 100755 (executable)
@@ -65,7 +65,6 @@ G_BEGIN_DECLS
 #include "wfdrtspconfigmessage.h"
 #define ENABLE_WFD_MESSAGE
 
-#include "gstwfdrtspext.h"
 #include "wfdrtspmanager.h"
 
 #define GST_TYPE_WFDRTSPSRC \
@@ -83,25 +82,11 @@ G_BEGIN_DECLS
 
 typedef struct _GstWFDRTSPSrc GstWFDRTSPSrc;
 typedef struct _GstWFDRTSPSrcClass GstWFDRTSPSrcClass;
-typedef struct _GstWFDRTSPSrcPrivate GstWFDRTSPSrcPrivate;
 
 #define GST_WFD_RTSP_TASK_GET_LOCK(wfd)   ((GST_WFDRTSPSRC_CAST(wfd)->task_rec_lock))
 #define GST_WFD_RTSP_TASK_LOCK(wfd)       (g_rec_mutex_lock (&(GST_WFD_RTSP_TASK_GET_LOCK(wfd))))
 #define GST_WFD_RTSP_TASK_UNLOCK(wfd)     (g_rec_mutex_unlock (&(GST_WFD_RTSP_TASK_GET_LOCK(wfd))))
 
-/**
- * GstWFDRTSPNatMethod:
- * @GST_WFD_RTSP_NAT_NONE: none
- * @GST_WFD_RTSP_NAT_DUMMY: send dummy packets
- *
- * Different methods for trying to traverse firewalls.
- */
-typedef enum
-{
-  GST_WFD_RTSP_NAT_NONE,
-  GST_WFD_RTSP_NAT_DUMMY
-} GstWFDRTSPNatMethod;
-
 typedef enum
 {
   WFD_PARAM_NONE,
@@ -133,7 +118,6 @@ struct _GstWFDRTSPSrc {
   guint             retry;
   GTimeVal          tcp_timeout;
   GTimeVal         *ptcp_timeout;
-  GstWFDRTSPNatMethod  nat_method;
   gchar            *proxy_host;
   guint             proxy_port;
   gchar            *proxy_user;
@@ -153,18 +137,12 @@ struct _GstWFDRTSPSrc {
   /* state */
   GstRTSPState       state;
   gboolean           tried_url_auth;
-  gboolean           need_redirect;
 
   /* supported methods */
   gint               methods;
 
   GstWFDRTSPConnInfo  conninfo;
 
-  /* a list of RTSP extensions as GstElement */
-  GstWFDRTSPExtensionList  *extensions;
-
-
-  GTimeVal ssr_timeout;
   guint video_height;
   guint video_width;
   guint video_framerate;
index 0115c96..e7b1a33 100755 (executable)
@@ -791,7 +791,7 @@ alloc_item (gpointer data, guint type, GstClockTime dts, GstClockTime pts,
 static void
 free_item (WfdRTPBufferItem * item)
 {
-  if (item->data && item->type != ITEM_TYPE_QUERY)
+  if (item && item->data && item->type != ITEM_TYPE_QUERY)
     gst_mini_object_unref (item->data);
   g_slice_free (WfdRTPBufferItem, item);
 }
index 59f08c4..d02d597 100755 (executable)
@@ -36,7 +36,9 @@ G_BEGIN_DECLS
  */
 typedef enum {
   WFD_OK     = 0,
-  WFD_EINVAL = -1
+  WFD_EINVAL = -1,
+  WFD_NOT_IMPLEMENTED = -2,
+  WFD_NOT_SUPPORTED = -3
 } WFDResult;
 
 typedef enum {
index c61813d..e629c4d 100755 (executable)
@@ -39,6 +39,7 @@
 #define WFD_MESSAGE_SET_SUPPORTED_AUDIO_FORMAT "wfdconfig_set_supported_audio_format"
 #define WFD_MESSAGE_SET_SUPPORTED_VIDEO_FORMAT "wfdconfig_set_supported_video_format"
 #define WFD_MESSAGE_SET_PREFERD_RTP_PORT "wfdconfig_set_prefered_RTP_ports"
+#define WFD_MESSAGE_GET_PREFERD_RTP_PORT "wfdconfig_get_prefered_RTP_ports"
 #define WFD_MESSAGE_SET_CONTPROTECTION_TYPE "wfdconfig_set_contentprotection_type"
 #define WFD_MESSAGE_SET_COUPLED_SINK "wfdconfig_set_coupled_sink"
 #define WFD_MESSAGE_GET_PRESENTATION_URL "wfdconfig_get_presentation_url"
 #define WFD_MESSAGE_GET_UIBC_STATUS "wfdconfig_get_uibc_status"
 #define WFD_MESSAGE_GET_PREFERED_AUDIO_FORMAT "wfdconfig_get_prefered_audio_format"
 #define WFD_MESSAGE_GET_PREFERED_VIDEO_FORMAT "wfdconfig_get_prefered_video_format"
+#define WFD_MESSAGE_GET_TRIGGER_TYPE "wfdconfig_get_trigger_type"
+#define WFD_MESSAGE_GET_AV_FORMAT_CHANGE_TIMING "wfdconfig_get_av_format_change_timing"
 
-#define WFDCONFIG_MESSAGE_NEW(msg, result)\
-if (src->extended_wfd_message_support) {\
-  WFDResult (*func)(WFDMessage **) = __wfd_config_message_func(src, WFD_MESSAGE_NEW);\
-  result = func(msg);\
-}
+#define WFDCONFIG_MESSAGE_NEW(msg, label)\
+G_STMT_START { \
+  if (src->extended_wfd_message_support) {\
+    WFDResult (*func)(WFDMessage **) = __wfd_config_message_func(src, WFD_MESSAGE_NEW);\
+    if(func == NULL) {\
+      wfd_res = WFD_NOT_IMPLEMENTED;\
+      goto label;\
+    }\
+    wfd_res = func(msg);\
+    if (G_UNLIKELY (wfd_res != WFD_OK) || G_LIKELY((*(msg)) == NULL)) \
+      goto label; \
+  }\
+} G_STMT_END
 
-#define WFDCONFIG_MESSAGE_INIT(msg, result)\
-if (src->extended_wfd_message_support) {\
-  WFDResult (*func)(WFDMessage *) = __wfd_config_message_func(src, WFD_MESSAGE_INIT);\
-  result = func(msg);\
-}
+#define WFDCONFIG_MESSAGE_INIT(msg, label)\
+G_STMT_START { \
+  if (src->extended_wfd_message_support) {\
+    WFDResult (*func)(WFDMessage *) = __wfd_config_message_func(src, WFD_MESSAGE_INIT);\
+    if(func == NULL) {\
+      wfd_res = WFD_NOT_IMPLEMENTED;\
+      goto label;\
+    }\
+    wfd_res = func(msg);\
+    if (G_UNLIKELY (wfd_res != WFD_OK)) \
+      goto label; \
+  }\
+} G_STMT_END
 
-#define WFDCONFIG_SET_AUDIO_SINK_TYPE(msg, sink_number, result)\
-if (src->extended_wfd_message_support) {\
+#define WFDCONFIG_SET_AUDIO_SINK_TYPE(msg, sink_number, label)\
+G_STMT_START { \
+  if (src->extended_wfd_message_support) {\
     WFDResult (*func)(WFDMessage *, WFDSinkType) = __wfd_config_message_func(src, WFD_MESSAGE_SET_AUDIO_SINK_TYPE);\
-    result = func(msg, sink_number);\
-}
-
-#define WFDCONFIG_SET_CONNECTOR_TYPE(msg, connector, result)\
-if (src->extended_wfd_message_support){\
-  WFDResult (*func)(WFDMessage *, WFDConnector) = __wfd_config_message_func(src, WFD_MESSAGE_SET_CONNECTOR_TYPE);\
-  result = func(msg, connector);\
-}
-
-#define WFDCONFIG_SET_STANDBY(msg, standby_enable, result)\
-if (src->extended_wfd_message_support){\
-  WFDResult (*func)(WFDMessage *, gboolean) = __wfd_config_message_func(src, WFD_MESSAGE_SET_STANDBY);\
-  result = func(msg, standby_enable);\
-}
-
-#define WFDCONFIG_SET_IDR_REQUESTER(msg, result)\
-if (src->extended_wfd_message_support){\
-  WFDResult (*func)(WFDMessage *) = __wfd_config_message_func(src, WFD_MESSAGE_SET_IDR_REQUESTER);\
-  result = func(msg);\
-}
-
-#define WFDCONFIG_SET_UIBC_CAPABILITY(msg, input_category, inp_type, inp_pair, inp_type_path_count, tcp_port, result)\
-if (src->extended_wfd_message_support){\
-  WFDResult (*func)(WFDMessage *, guint32 , guint32 , WFDHIDCTypePathPair *, guint32 , guint32 ) = __wfd_config_message_func(src, WFD_MESSAGE_SET_UIBC_CAPABILITY);\
-  result = func(msg, input_category, inp_type, inp_pair, inp_type_path_count, tcp_port);\
-}
-
-#define WFDCONFIG_SET_UIBC_STATUS(msg, uibc_enable, result)\
-if (src->extended_wfd_message_support){\
-  WFDResult (*func)(WFDMessage *, gboolean) = __wfd_config_message_func(src, WFD_MESSAGE_SET_UIBC_STATUS);\
-  result = func(msg, uibc_enable);\
-}
+    if(func == NULL) {\
+      wfd_res = WFD_NOT_IMPLEMENTED;\
+      goto label;\
+    }\
+    wfd_res = func(msg, sink_number);\
+    if (G_UNLIKELY (wfd_res != WFD_OK)) \
+      goto label; \
+  }\
+} G_STMT_END
+
+#define WFDCONFIG_SET_CONNECTOR_TYPE(msg, connector, label)\
+G_STMT_START { \
+  if (src->extended_wfd_message_support){\
+    WFDResult (*func)(WFDMessage *, WFDConnector) = __wfd_config_message_func(src, WFD_MESSAGE_SET_CONNECTOR_TYPE);\
+    if(func == NULL) {\
+      wfd_res = WFD_NOT_IMPLEMENTED;\
+      goto label;\
+    }\
+    wfd_res = func(msg, connector);\
+    if (G_UNLIKELY (wfd_res != WFD_OK)) \
+      goto label; \
+  }\
+} G_STMT_END
+
+#define WFDCONFIG_SET_STANDBY(msg, standby_enable, label)\
+G_STMT_START { \
+  if (src->extended_wfd_message_support){\
+    WFDResult (*func)(WFDMessage *, gboolean) = __wfd_config_message_func(src, WFD_MESSAGE_SET_STANDBY);\
+    if(func == NULL) {\
+      wfd_res = WFD_NOT_IMPLEMENTED;\
+      goto label;\
+    }\
+    wfd_res = func(msg, standby_enable);\
+    if (G_UNLIKELY (wfd_res != WFD_OK)) \
+      goto label; \
+  }\
+} G_STMT_END
+
+#define WFDCONFIG_SET_IDR_REQUESTER(msg, label)\
+G_STMT_START { \
+  if (src->extended_wfd_message_support){\
+    WFDResult (*func)(WFDMessage *) = __wfd_config_message_func(src, WFD_MESSAGE_SET_IDR_REQUESTER);\
+    if(func == NULL) {\
+      wfd_res = WFD_NOT_IMPLEMENTED;\
+      goto label;\
+    }\
+    wfd_res = func(msg);\
+    if (G_UNLIKELY (wfd_res != WFD_OK)) \
+      goto label; \
+  }\
+} G_STMT_END
+
+#define WFDCONFIG_SET_UIBC_CAPABILITY(msg, input_category, inp_type, inp_pair, inp_type_path_count, tcp_port, label)\
+G_STMT_START { \
+  if (src->extended_wfd_message_support){\
+    WFDResult (*func)(WFDMessage *, guint32 , guint32 , WFDHIDCTypePathPair *, guint32 , guint32 ) = __wfd_config_message_func(src, WFD_MESSAGE_SET_UIBC_CAPABILITY);\
+    if(func == NULL) {\
+      wfd_res = WFD_NOT_IMPLEMENTED;\
+      goto label;\
+    }\
+    wfd_res = func(msg, input_category, inp_type, inp_pair, inp_type_path_count, tcp_port);\
+    if (G_UNLIKELY (wfd_res != WFD_OK)) \
+      goto label; \
+  }\
+} G_STMT_END
+
+#define WFDCONFIG_SET_UIBC_STATUS(msg, uibc_enable, label)\
+G_STMT_START { \
+  if (src->extended_wfd_message_support){\
+    WFDResult (*func)(WFDMessage *, gboolean) = __wfd_config_message_func(src, WFD_MESSAGE_SET_UIBC_STATUS);\
+    if(func == NULL) {\
+      wfd_res = WFD_NOT_IMPLEMENTED;\
+      goto label;\
+    }\
+    wfd_res = func(msg, uibc_enable);\
+    if (G_UNLIKELY (wfd_res != WFD_OK)) \
+      goto label; \
+  }\
+} G_STMT_END
 
 #define WFDCONFIG_MESSAGE_FREE(msg)\
-if (src->extended_wfd_message_support){\
-  WFDResult (*func)(WFDMessage *) = __wfd_config_message_func(src, WFD_MESSAGE_FREE);\
-  func(msg);\
-  msg = NULL;\
-}
-
-#define WFDCONFIG_MESSAGE_DUMP(msg, result)\
-if (src->extended_wfd_message_support){\
-  WFDResult (*func)(WFDMessage *) = __wfd_config_message_func(src, WFD_MESSAGE_DUMP);\
-  result = func(msg);\
-}
-
-#define WFDCONFIG_MESSAGE_AS_TEXT(msg, text)\
-if (src->extended_wfd_message_support){\
-  gchar* (*func)(WFDMessage *) = __wfd_config_message_func(src, WFD_MESSAGE_AS_TEXT);\
-  text = func(msg);\
-}
-
-#define WFDCONFIG_MESSAGE_PARSE_BUFFER(data, size, msg, result)\
-if (src->extended_wfd_message_support){\
-  WFDResult (*func)(const guint8 * , guint , WFDMessage *) = __wfd_config_message_func(src, WFD_MESSAGE_PARSE_BUFFER);\
-  result = func(data, size, msg);\
-}
-
-#define WFDCONFIG_SET_SUPPORTED_AUDIO_FORMAT(msg, audio_codec, audio_sampling_frequency, audio_channels, audio_bit_width, audio_latency, result)\
-if (src->extended_wfd_message_support){\
-  WFDResult (*func)(WFDMessage *, WFDAudioFormats , guint , guint , guint , guint32 ) = __wfd_config_message_func(src, WFD_MESSAGE_SET_SUPPORTED_AUDIO_FORMAT);\
-  result = func(msg, audio_codec, audio_sampling_frequency, audio_channels, audio_bit_width, audio_latency);\
-}
+G_STMT_START { \
+  if (src->extended_wfd_message_support && msg != NULL){\
+    WFDResult (*func)(WFDMessage *) = __wfd_config_message_func(src, WFD_MESSAGE_FREE);\
+    if(func != NULL) {\
+      func(msg);\
+      msg = NULL;\
+    } else {\
+      wfd_res = WFD_NOT_IMPLEMENTED;\
+    }\
+  }\
+} G_STMT_END
+
+#define WFDCONFIG_MESSAGE_DUMP(msg)\
+G_STMT_START { \
+  if (src->extended_wfd_message_support){\
+    WFDResult (*func)(WFDMessage *) = __wfd_config_message_func(src, WFD_MESSAGE_DUMP);\
+    if(func != NULL) {\
+      func(msg);\
+    } else {\
+      wfd_res = WFD_NOT_IMPLEMENTED;\
+    }\
+  }\
+} G_STMT_END
+
+#define WFDCONFIG_MESSAGE_AS_TEXT(msg, text, label)\
+G_STMT_START { \
+  if (src->extended_wfd_message_support){\
+    gchar* (*func)(WFDMessage *) = __wfd_config_message_func(src, WFD_MESSAGE_AS_TEXT);\
+    if(func == NULL) {\
+      wfd_res = WFD_NOT_IMPLEMENTED;\
+      goto label;\
+    }\
+    text = func(msg);\
+    if (!text)\
+      goto label;\
+  }\
+} G_STMT_END
+
+#define WFDCONFIG_MESSAGE_PARSE_BUFFER(data, size, msg, label)\
+G_STMT_START { \
+  if (src->extended_wfd_message_support){\
+    WFDResult (*func)(const guint8 * , guint , WFDMessage *) = __wfd_config_message_func(src, WFD_MESSAGE_PARSE_BUFFER);\
+    if(func == NULL) {\
+      wfd_res = WFD_NOT_IMPLEMENTED;\
+      goto label;\
+    }\
+    wfd_res = func(data, size, msg);\
+    if (G_UNLIKELY (wfd_res != WFD_OK)) \
+      goto label; \
+  }\
+} G_STMT_END
+
+#define WFDCONFIG_SET_SUPPORTED_AUDIO_FORMAT(msg, audio_codec, audio_sampling_frequency, audio_channels, audio_bit_width, audio_latency, label)\
+G_STMT_START { \
+  if (src->extended_wfd_message_support){\
+    WFDResult (*func)(WFDMessage *, WFDAudioFormats , guint , guint , guint , guint32 ) = __wfd_config_message_func(src, WFD_MESSAGE_SET_SUPPORTED_AUDIO_FORMAT);\
+    if(func == NULL) {\
+      wfd_res = WFD_NOT_IMPLEMENTED;\
+      goto label;\
+    }\
+    wfd_res = func(msg, audio_codec, audio_sampling_frequency, audio_channels, audio_bit_width, audio_latency);\
+     if (G_UNLIKELY (wfd_res != WFD_OK)) \
+      goto label; \
+  }\
+} G_STMT_END
 
 #define WFDCONFIG_SET_SUPPORTED_VIDEO_FORMAT(msg, video_codec, video_native, video_native_resolution, video_cea_support,\
   video_vesa_support, video_hh_support, video_profile, video_level, video_latency, video_vertical_resolution,\
-  video_horizontal_resolution, video_minimum_slicing, video_slice_enc_param, video_framerate_control_support, result)\
-if (src->extended_wfd_message_support){\
-  WFDResult (*func)(WFDMessage *, WFDVideoCodecs ,\
+  video_horizontal_resolution, video_minimum_slicing, video_slice_enc_param, video_framerate_control_support, label)\
+G_STMT_START { \
+  if (src->extended_wfd_message_support){\
+    WFDResult (*func)(WFDMessage *, WFDVideoCodecs ,\
                   WFDVideoNativeResolution , guint64 ,\
                   guint64 , guint64 , guint64 ,\
                   guint , guint , guint32 , guint32 ,\
                   guint32 , guint32 , guint32 , guint ) = __wfd_config_message_func(src, WFD_MESSAGE_SET_SUPPORTED_VIDEO_FORMAT);\
-  result = func(msg,\
+    if(func == NULL) {\
+      wfd_res = WFD_NOT_IMPLEMENTED;\
+      goto label;\
+    }\
+    wfd_res = func(msg,\
           video_codec,\
           video_native,\
           video_native_resolution,\
@@ -151,70 +259,191 @@ if (src->extended_wfd_message_support){\
           video_minimum_slicing,\
           video_slice_enc_param,\
           video_framerate_control_support);\
-}
-
-#define WFDCONFIG_SET_PREFERD_RTP_PORT(msg, trans, profile, lowertrans, rtp_port0, rtp_port1, result)\
-if (src->extended_wfd_message_support){\
-  WFDResult (*func)(WFDMessage *, WFDRTSPTransMode , WFDRTSPProfile , WFDRTSPLowerTrans , guint32 , guint32 ) = __wfd_config_message_func(src, WFD_MESSAGE_SET_PREFERD_RTP_PORT);\
-  result = func(msg, trans, profile, lowertrans, rtp_port0, rtp_port1);\
-}
-
-#define WFDCONFIG_SET_CONTPROTECTION_TYPE(msg, hdcp_version, hdcp_port_no, result)\
-if (src->extended_wfd_message_support){\
-  WFDResult (*func)(WFDMessage *, WFDHDCPProtection , guint32) = __wfd_config_message_func(src, WFD_MESSAGE_SET_CONTPROTECTION_TYPE);\
-  result = func(msg, hdcp_version, (guint32)hdcp_port_no);\
-}
-
-#define WFDCONFIG_SET_COUPLED_SINK(msg, status, sink_address, result)\
-if (src->extended_wfd_message_support){\
-  WFDResult (*func)(WFDMessage *, WFDCoupledSinkStatus , gchar *) = __wfd_config_message_func(src, WFD_MESSAGE_SET_COUPLED_SINK);\
-  result = func(msg, status,(gchar *)sink_address);\
-}
-
-#define WFDCONFIG_GET_PRESENTATION_URL(msg, wfd_url0, wfd_url1, result)\
-if (src->extended_wfd_message_support){\
-  WFDResult (*func)(WFDMessage *, gchar **, gchar **) = __wfd_config_message_func(src, WFD_MESSAGE_GET_PRESENTATION_URL);\
-  result = func(msg, wfd_url0, wfd_url1);\
-}
-
-#define WFDCONFIG_GET_STANDBY(msg, standby_enable, result)\
-if (src->extended_wfd_message_support){\
-  WFDResult (*func)(WFDMessage *, gboolean *) = __wfd_config_message_func(src, WFD_MESSAGE_GET_STANDBY);\
-  result = func(msg, standby_enable);\
-}
-
-#define WFDCONFIG_GET_UIBC_CAPABILITY(msg, input_category, inp_type, inp_pair, inp_type_path_count, tcp_port, result)\
-if (src->extended_wfd_message_support){\
-  WFDResult (*func)(WFDMessage *, guint32 *, guint32 *, WFDHIDCTypePathPair **,guint32 *, guint32 *) = __wfd_config_message_func(src, WFD_MESSAGE_GET_UIBC_CAPABILITY);\
-  result = func(msg, input_category, inp_type, inp_pair, inp_type_path_count, tcp_port);\
-}
-
-#define WFDCONFIG_GET_UIBC_STATUS(msg, uibc_enable, result)\
-if (src->extended_wfd_message_support){\
-  WFDResult (*func)(WFDMessage *, gboolean *) = __wfd_config_message_func(src, WFD_MESSAGE_GET_UIBC_STATUS);\
-  result = func(msg, uibc_enable);\
-}
+    if (G_UNLIKELY (wfd_res != WFD_OK)) \
+      goto label; \
+  }\
+} G_STMT_END
+
+#define WFDCONFIG_SET_PREFERD_RTP_PORT(msg, trans, profile, lowertrans, rtp_port0, rtp_port1, label)\
+G_STMT_START { \
+  if (src->extended_wfd_message_support){\
+    WFDResult (*func)(WFDMessage *, WFDRTSPTransMode , WFDRTSPProfile , WFDRTSPLowerTrans , guint32 , guint32 ) = __wfd_config_message_func(src, WFD_MESSAGE_SET_PREFERD_RTP_PORT);\
+    if(func == NULL) {\
+      wfd_res = WFD_NOT_IMPLEMENTED;\
+      goto label;\
+    }\
+    wfd_res = func(msg, trans, profile, lowertrans, rtp_port0, rtp_port1);\
+    if (G_UNLIKELY (wfd_res != WFD_OK)) \
+      goto label; \
+  }\
+} G_STMT_END
+
+#define WFDCONFIG_GET_PREFERD_RTP_PORT(msg, trans, profile, lowertrans, rtp_port0, rtp_port1, label)\
+G_STMT_START { \
+  if (src->extended_wfd_message_support){\
+    WFDResult (*func)(WFDMessage *, WFDRTSPTransMode *, WFDRTSPProfile  *, WFDRTSPLowerTrans  *, guint32  *, guint32  *) = __wfd_config_message_func(src, WFD_MESSAGE_GET_PREFERD_RTP_PORT);\
+    if(func == NULL) {\
+      wfd_res = WFD_NOT_IMPLEMENTED;\
+      goto label;\
+    }\
+    wfd_res = func(msg, trans, profile, lowertrans, rtp_port0, rtp_port1);\
+    if (G_UNLIKELY (wfd_res != WFD_OK)) \
+      goto label; \
+  }\
+} G_STMT_END
+
+
+#define WFDCONFIG_SET_CONTENT_PROTECTION_TYPE(msg, hdcp_version, hdcp_port_no, label)\
+G_STMT_START { \
+  if (src->extended_wfd_message_support){\
+    WFDResult (*func)(WFDMessage *, WFDHDCPProtection , guint32) = __wfd_config_message_func(src, WFD_MESSAGE_SET_CONTPROTECTION_TYPE);\
+    if(func == NULL) {\
+      wfd_res = WFD_NOT_IMPLEMENTED;\
+      goto label;\
+    }\
+    wfd_res = func(msg, hdcp_version, (guint32)hdcp_port_no);\
+    if (G_UNLIKELY (wfd_res != WFD_OK)) \
+      goto label; \
+  }\
+} G_STMT_END
+
+#define WFDCONFIG_SET_COUPLED_SINK(msg, status, sink_address, label)\
+G_STMT_START { \
+  if (src->extended_wfd_message_support){\
+    WFDResult (*func)(WFDMessage *, WFDCoupledSinkStatus , gchar *) = __wfd_config_message_func(src, WFD_MESSAGE_SET_COUPLED_SINK);\
+    if(func == NULL) {\
+      wfd_res = WFD_NOT_IMPLEMENTED;\
+      goto label;\
+    }\
+    wfd_res = func(msg, status,(gchar *)sink_address);\
+    if (G_UNLIKELY (wfd_res != WFD_OK)) \
+      goto label; \
+  }\
+} G_STMT_END
+
+#define WFDCONFIG_GET_PRESENTATION_URL(msg, wfd_url0, wfd_url1, label)\
+G_STMT_START { \
+  if (src->extended_wfd_message_support){\
+    WFDResult (*func)(WFDMessage *, gchar **, gchar **) = __wfd_config_message_func(src, WFD_MESSAGE_GET_PRESENTATION_URL);\
+    if(func == NULL) {\
+      wfd_res = WFD_NOT_IMPLEMENTED;\
+      goto label;\
+    }\
+    wfd_res = func(msg, wfd_url0, wfd_url1);\
+    if (G_UNLIKELY (wfd_res != WFD_OK)) \
+      goto label; \
+  }\
+} G_STMT_END
+
+#define WFDCONFIG_GET_STANDBY(msg, standby_enable, label)\
+G_STMT_START { \
+  if (src->extended_wfd_message_support){\
+    WFDResult (*func)(WFDMessage *, gboolean *) = __wfd_config_message_func(src, WFD_MESSAGE_GET_STANDBY);\
+    if(func == NULL) {\
+      wfd_res = WFD_NOT_IMPLEMENTED;\
+      goto label;\
+    }\
+    wfd_res = func(msg, standby_enable);\
+    if (G_UNLIKELY (wfd_res != WFD_OK)) \
+      goto label; \
+  }\
+} G_STMT_END
+
+#define WFDCONFIG_GET_UIBC_CAPABILITY(msg, input_category, inp_type, inp_pair, inp_type_path_count, tcp_port, label)\
+G_STMT_START { \
+  if (src->extended_wfd_message_support){\
+    WFDResult (*func)(WFDMessage *, guint32 *, guint32 *, WFDHIDCTypePathPair **,guint32 *, guint32 *) = __wfd_config_message_func(src, WFD_MESSAGE_GET_UIBC_CAPABILITY);\
+    if(func == NULL) {\
+      wfd_res = WFD_NOT_IMPLEMENTED;\
+      goto label;\
+    }\
+    wfd_res = func(msg, input_category, inp_type, inp_pair, inp_type_path_count, tcp_port);\
+    if (G_UNLIKELY (wfd_res != WFD_OK)) \
+      goto label; \
+  }\
+} G_STMT_END
+
+#define WFDCONFIG_GET_UIBC_STATUS(msg, uibc_enable, label)\
+G_STMT_START { \
+  if (src->extended_wfd_message_support){\
+    WFDResult (*func)(WFDMessage *, gboolean *) = __wfd_config_message_func(src, WFD_MESSAGE_GET_UIBC_STATUS);\
+    if(func == NULL) {\
+      wfd_res = WFD_NOT_IMPLEMENTED;\
+      goto label;\
+    }\
+    wfd_res = func(msg, uibc_enable);\
+    if (G_UNLIKELY (wfd_res != WFD_OK)) \
+      goto label; \
+  }\
+} G_STMT_END
 
 #define WFDCONFIG_GET_PREFERED_AUDIO_FORMAT(msg, audio_format, audio_frequency, audio_channels, audio_bitwidth, audio_latency)\
-if (src->extended_wfd_message_support){\
-  WFDResult (*func)(WFDMessage *, WFDAudioFormats *, WFDAudioFreq *, WFDAudioChannels *, guint *, guint32 *) = __wfd_config_message_func(src, WFD_MESSAGE_GET_PREFERED_AUDIO_FORMAT);\
-  func(msg, audio_format, audio_frequency, audio_channels, audio_bitwidth, audio_latency);\
-}
+G_STMT_START { \
+  if (src->extended_wfd_message_support){\
+    WFDResult (*func)(WFDMessage *, WFDAudioFormats *, WFDAudioFreq *, WFDAudioChannels *, guint *, guint32 *) = __wfd_config_message_func(src, WFD_MESSAGE_GET_PREFERED_AUDIO_FORMAT);\
+    if(func != NULL) {\
+      wfd_res = func(msg, audio_format, audio_frequency, audio_channels, audio_bitwidth, audio_latency);\
+    } else {\
+      wfd_res = WFD_NOT_IMPLEMENTED;\
+    }\
+  }\
+} G_STMT_END
 
 #define WFDCONFIG_GET_PREFERED_VIDEO_FORMAT(msg, cvCodec, cNative, cNativeResolution,\
 cCEAResolution, cVESAResolution, cHHResolution, cProfile, cLevel, cvLatency, cMaxHeight,\
 cMaxWidth, cmin_slice_size, cslice_enc_params, cframe_rate_control)\
-if (src->extended_wfd_message_support){\
-  WFDResult (*func)(WFDMessage *, WFDVideoCodecs *,\
-    WFDVideoNativeResolution *, guint64 *,\
-    WFDVideoCEAResolution *, WFDVideoVESAResolution *,\
-    WFDVideoHHResolution *,    WFDVideoH264Profile *,\
-    WFDVideoH264Level *, guint32 *, guint32 *,\
-    guint32 *, guint32 *, guint32 *, guint *) = __wfd_config_message_func(src, WFD_MESSAGE_GET_PREFERED_VIDEO_FORMAT);\
-    func(msg, cvCodec, cNative, cNativeResolution,\
-    cCEAResolution, cVESAResolution, cHHResolution,\
-    cProfile, cLevel, cvLatency, cMaxHeight,\
-    cMaxWidth, cmin_slice_size, cslice_enc_params, cframe_rate_control);\
-}
+G_STMT_START { \
+  if (src->extended_wfd_message_support){\
+    WFDResult (*func)(WFDMessage *, WFDVideoCodecs *,\
+      WFDVideoNativeResolution *, guint64 *,\
+      WFDVideoCEAResolution *, WFDVideoVESAResolution *,\
+      WFDVideoHHResolution *,  WFDVideoH264Profile *,\
+      WFDVideoH264Level *, guint32 *, guint32 *,\
+      guint32 *, guint32 *, guint32 *, guint *) = __wfd_config_message_func(src, WFD_MESSAGE_GET_PREFERED_VIDEO_FORMAT);\
+    if(func != NULL) {\
+      wfd_res = func(msg, cvCodec, cNative, cNativeResolution,\
+        cCEAResolution, cVESAResolution, cHHResolution,\
+        cProfile, cLevel, cvLatency, cMaxHeight,\
+        cMaxWidth, cmin_slice_size, cslice_enc_params, cframe_rate_control);\
+    } else {\
+      wfd_res = WFD_NOT_IMPLEMENTED;\
+    }\
+  }\
+} G_STMT_END
+
+#define WFDCONFIG_GET_TRIGGER_TYPE(msg, trigger, label)\
+G_STMT_START { \
+  if (src->extended_wfd_message_support){\
+    WFDResult (*func)(WFDMessage *, WFDTrigger *) = __wfd_config_message_func(src, WFD_MESSAGE_GET_TRIGGER_TYPE);\
+    if(func == NULL) {\
+      wfd_res = WFD_NOT_IMPLEMENTED;\
+      goto label;\
+    }\
+    wfd_res = func(msg, trigger);\
+    if (G_UNLIKELY (wfd_res != WFD_OK)) \
+      goto label; \
+  }\
+} G_STMT_END
+
+#define WFDCONFIG_GET_AV_FORMAT_CHANGE_TIMING(msg, PTS, DTS, label)\
+G_STMT_START { \
+  if (src->extended_wfd_message_support){\
+    WFDResult (*func)(WFDMessage *, guint64 *, guint64 *) = __wfd_config_message_func(src, WFD_MESSAGE_GET_AV_FORMAT_CHANGE_TIMING);\
+    if(func == NULL) {\
+      wfd_res = WFD_NOT_IMPLEMENTED;\
+      goto label;\
+    }\
+    wfd_res = func(msg, PTS, DTS);\
+    if (G_UNLIKELY (wfd_res != WFD_OK)) \
+      goto label; \
+  }\
+} G_STMT_END
+
+#define WFDCONFIG_MESSAGE_CHECK(stmt, label)  \
+G_STMT_START { \
+  if (G_UNLIKELY ((wfd_res = (stmt)) != WFD_OK)) \
+    goto label; \
+} G_STMT_END
+
 
 #endif /*__WFD_RTSP_MACRO_H__*/
index feb288f..01d46d5 100755 (executable)
@@ -1135,53 +1135,29 @@ wfd_rtsp_manager_flush (WFDRTSPManager * manager, gboolean flush)
 }
 
 GstPadProbeReturn
-//wfd_rtsp_manager_pad_probe_cb(GstPad * pad, GstMiniObject * object, gpointer u_data)
 wfd_rtsp_manager_pad_probe_cb(GstPad * pad, GstPadProbeInfo *info, gpointer u_data)
 {
   GstElement* parent = NULL;
   const GstSegment *segment = NULL;
 
-  parent = (GstElement*)gst_object_get_parent(GST_OBJECT(pad));
-
-#if 0
-  if (GST_IS_EVENT (object)) {
-    GstEvent *event = GST_EVENT_CAST(object);
-
-    /* show name and event type */
-    GST_DEBUG_OBJECT(WFD_RTSP_MANAGER (u_data), "EVENT PROBE : %s:%s :  %s\n",
-      GST_STR_NULL(GST_ELEMENT_NAME(parent)), GST_STR_NULL(GST_PAD_NAME(pad)),
-      GST_EVENT_TYPE_NAME(event));
+  g_return_val_if_fail (pad, GST_PAD_PROBE_DROP);
+  g_return_val_if_fail (info, GST_PAD_PROBE_DROP);
 
-    if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) {
-      GstSegment *seg = NULL;
-
-      gst_event_parse_segment (event, &segment);
-
-      GST_DEBUG_OBJECT (WFD_RTSP_MANAGER (u_data), "NEWSEGMENT : %" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %" G_GINT64_FORMAT " \n",
-      seg->start, seg->stop, seg->time);
-      gst_segment_free(seg);
-    }
-  }
-  else if  (GST_IS_BUFFER(object)) {
-    GstBuffer *buffer = GST_BUFFER_CAST(object);
+  parent = (GstElement*)gst_object_get_parent(GST_OBJECT(pad));
+  if(!parent)
+    return GST_PAD_PROBE_DROP;
 
-    /* show name and timestamp */
-    GST_DEBUG_OBJECT(WFD_RTSP_MANAGER (u_data), "BUFFER PROBE : %s:%s :  %u:%02u:%02u.%09u  (%d bytes)\n",
-        GST_STR_NULL(GST_ELEMENT_NAME(parent)), GST_STR_NULL(GST_PAD_NAME(pad)),
-        GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)), gst_buffer_get_size(buffer));
-  }
-#else
-  if (info->type == GST_PAD_PROBE_TYPE_BUFFER) {
+  if (info->type & GST_PAD_PROBE_TYPE_BUFFER) {
     GstBuffer *buffer = gst_pad_probe_info_get_buffer (info);
 
     /* show name and timestamp */
     GST_DEBUG_OBJECT(WFD_RTSP_MANAGER (u_data), "BUFFER PROBE : %s:%s :  %u:%02u:%02u.%09u  (%d bytes)\n",
         GST_STR_NULL(GST_ELEMENT_NAME(parent)), GST_STR_NULL(GST_PAD_NAME(pad)),
         GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)), gst_buffer_get_size(buffer));
-  } else if (info->type == GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM ||
-                info->type == GST_PAD_PROBE_TYPE_EVENT_UPSTREAM ||
-                info->type == GST_PAD_PROBE_TYPE_EVENT_FLUSH ||
-                info->type == GST_PAD_PROBE_TYPE_EVENT_BOTH) {
+  } else if (info->type & GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM ||
+                info->type & GST_PAD_PROBE_TYPE_EVENT_UPSTREAM ||
+                info->type & GST_PAD_PROBE_TYPE_EVENT_FLUSH ||
+                info->type & GST_PAD_PROBE_TYPE_EVENT_BOTH) {
       GstEvent *event = gst_pad_probe_info_get_event (info);
     /* show name and event type */
     GST_DEBUG_OBJECT(WFD_RTSP_MANAGER (u_data), "EVENT PROBE : %s:%s :  %s\n",
@@ -1198,10 +1174,6 @@ wfd_rtsp_manager_pad_probe_cb(GstPad * pad, GstPadProbeInfo *info, gpointer u_da
     }
   }
 
-
-
-#endif
-
   if ( parent ) {
     gst_object_unref(parent);
   }
@@ -1237,27 +1209,6 @@ void wfd_rtsp_manager_enable_pad_probe(WFDRTSPManager * manager)
       pad = NULL;
     }
   }
-#if 0
-  if(manager->requester) {
-    pad = gst_element_get_static_pad(manager->requester, "rtp_sink");
-    if (pad) {
-      if( gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_DATA_DOWNSTREAM, wfd_rtsp_manager_pad_probe_cb, (gpointer)manager, NULL)) {
-        GST_DEBUG_OBJECT (manager, "added pad probe (pad : %s, element : %s)", gst_pad_get_name(pad), gst_element_get_name(manager->requester));
-      }
-      gst_object_unref (pad);
-      pad = NULL;
-    }
-
-    pad = gst_element_get_static_pad(manager->requester, "rtp_src");
-    if (pad) {
-      if( gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_DATA_DOWNSTREAM, wfd_rtsp_manager_pad_probe_cb, (gpointer)manager, NULL)) {
-        GST_DEBUG_OBJECT (manager, "added pad probe (pad : %s, element : %s)", gst_pad_get_name(pad), gst_element_get_name(manager->requester));
-    }
-      gst_object_unref (pad);
-      pad = NULL;
-    }
-  }
-#endif
 
   if(manager->wfdrtpbuffer) {
     pad = gst_element_get_static_pad(manager->wfdrtpbuffer, "sink");
index b48c1ce..0e72d93 100755 (executable)
@@ -17,6 +17,8 @@ libgstwfdtsdemux_la_CFLAGS = \
        $(GST_BASE_CFLAGS) $(GST_CFLAGS)
 libgstwfdtsdemux_la_LIBADD = \
        $(GST_PLUGINS_BASE_LIBS) \
+       -lgsttag-@GST_MAJORMINOR@ \
+       -lgstpbutils-@GST_MAJORMINOR@ \
        $(GST_BASE_LIBS) \
        $(GST_LIBS)
 libgstwfdtsdemux_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
index e849e19..453b438 100755 (executable)
@@ -1219,9 +1219,11 @@ gst_wfd_h264_parser_parse_nal (GstWFDH264NalParser * nalparser, GstWFDH264NalUni
 
   switch (nalu->type) {
     case GST_H264_NAL_SPS:
+      memset(&sps, 0, sizeof(GstWFDH264SPS));
       return gst_wfd_h264_parser_parse_sps (nalparser, nalu, &sps, FALSE);
       break;
     case GST_H264_NAL_PPS:
+      memset(&pps, 0, sizeof(GstWFDH264PPS));
       return gst_wfd_h264_parser_parse_pps (nalparser, nalu, &pps);
   }
 
index 7c36aae..dc62b25 100755 (executable)
@@ -430,6 +430,8 @@ convert_to_utf8 (const gchar * text, gint length, guint start,
   text += start;
 
   pos = tmp = g_malloc (length * 2);
+  if(!pos)
+    return NULL;
 
   if (is_multibyte) {
     if (length == -1) {
index d97f821..af2f66c 100755 (executable)
@@ -651,6 +651,10 @@ _parse_pmt (GstWFDTSSection * section)
   guint stream_info_length;
 
   pmt = g_slice_new0 (GstWFDTSPMT);
+  if(pmt == NULL) {
+    GST_ERROR("Failed to allocate memory for pmt");
+    return NULL;
+  }
 
   data = section->data;
   end = data + section->section_length;
index 29082f8..00f3533 100755 (executable)
@@ -867,6 +867,9 @@ wfd_ts_base_apply_pmt (WFDTSBase * base, GstWFDTSSection * section)
   /* If the current program is active, this means we have a new program */
   if (old_program->active) {
     old_program = wfd_ts_base_steal_program (base, program_number);
+    if(G_UNLIKELY (old_program == NULL))
+      goto no_program;
+
     program = wfd_ts_base_new_program (base, program_number, section->pid);
     g_hash_table_insert (base->programs,
         GINT_TO_POINTER (program_number), program);
index c825ae5..cf9cc38 100755 (executable)
@@ -1961,7 +1961,8 @@ calculate_and_push_newsegment (GstWFDTSDemux * demux, WFDTSDemuxStream * stream)
 
   if (!demux->segment_event) {
     demux->segment_event = gst_event_new_segment (&demux->segment);
-    GST_EVENT_SEQNUM (demux->segment_event) = base->last_seek_seqnum;
+    if(demux->segment_event)
+      GST_EVENT_SEQNUM (demux->segment_event) = base->last_seek_seqnum;
   }
 
 push_new_segment:
index f451dad..ce8f26d 100755 (executable)
@@ -384,12 +384,15 @@ wfd_ts_packetizer_parse_adaptation_field_control (WFDTSPacketizer *
     if (packetizer->calculate_skew
         && GST_CLOCK_TIME_IS_VALID (packetizer->last_in_time)) {
       pcrtable = get_pcr_table (packetizer, packet->pid);
-      calculate_skew (pcrtable, packet->pcr, packetizer->last_in_time);
+      if (pcrtable)
+        calculate_skew (pcrtable, packet->pcr, packetizer->last_in_time);
     }
     if (packetizer->calculate_offset) {
       if (!pcrtable)
         pcrtable = get_pcr_table (packetizer, packet->pid);
-      record_pcr (packetizer, pcrtable, packet->pcr, packet->offset);
+
+      if (pcrtable)
+        record_pcr (packetizer, pcrtable, packet->pcr, packet->offset);
     }
     PACKETIZER_GROUP_UNLOCK (packetizer);
   }
@@ -2096,6 +2099,11 @@ wfd_ts_packetizer_offset_to_ts (WFDTSPacketizer * packetizer,
   PACKETIZER_GROUP_LOCK (packetizer);
 
   pcrtable = get_pcr_table (packetizer, pid);
+  if(pcrtable == NULL) {
+    PACKETIZER_GROUP_UNLOCK (packetizer);
+    GST_WARNING ("The pcr table is null");
+    return GST_CLOCK_TIME_NONE;
+  }
 
   if (g_list_length (pcrtable->groups) < 1) {
     PACKETIZER_GROUP_UNLOCK (packetizer);
@@ -2161,6 +2169,11 @@ wfd_ts_packetizer_pts_to_ts (WFDTSPacketizer * packetizer,
 
   PACKETIZER_GROUP_LOCK (packetizer);
   pcrtable = get_pcr_table (packetizer, pcr_pid);
+  if(G_UNLIKELY(pcrtable == NULL)) {
+    PACKETIZER_GROUP_UNLOCK (packetizer);
+    GST_ERROR ("The pcr table is null");
+    return res;
+  }
 
   /* Use clock skew if present */
   if (packetizer->calculate_skew
@@ -2293,7 +2306,7 @@ wfd_ts_packetizer_ts_to_offset (WFDTSPacketizer * packetizer,
   PACKETIZER_GROUP_LOCK (packetizer);
   pcrtable = get_pcr_table (packetizer, pcr_pid);
 
-  if (pcrtable->groups == NULL) {
+  if (pcrtable == NULL || pcrtable->groups == NULL) {
     PACKETIZER_GROUP_UNLOCK (packetizer);
     return -1;
   }