* #36737: switch back to svn repo, remove assert in sip_transaction.c
diff --git a/jni/pjproject-android/.svn/pristine/7f/7f116035d97af90dbbfbac8cfa78356e2ccd5d91.svn-base b/jni/pjproject-android/.svn/pristine/7f/7f116035d97af90dbbfbac8cfa78356e2ccd5d91.svn-base
new file mode 100644
index 0000000..31cb731
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/7f/7f116035d97af90dbbfbac8cfa78356e2ccd5d91.svn-base
@@ -0,0 +1,870 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#ifndef __PJPP_OS_HPP__
+#define __PJPP_OS_HPP__
+
+#include <pj/os.h>
+#include <pj/string.h>
+#include <pj++/types.hpp>
+#include <pj++/pool.hpp>
+
+class Pj_Thread;
+
+//
+// Thread API.
+//
+class Pj_Thread_API
+{
+public:
+    //
+    // Create a thread.
+    //
+    static pj_status_t create( Pj_Pool *pool, pj_thread_t **thread,
+                               pj_thread_proc *proc, void *arg,
+                               unsigned flags = 0,
+                               const char *name = NULL,
+                               pj_size_t stack_size = 0 )
+    {
+        return pj_thread_create(pool->pool_(), name, proc, arg, stack_size,
+                                flags, thread);
+    }
+
+    //
+    // Register a thread.
+    //
+    static pj_status_t register_this_thread( pj_thread_desc desc,
+                                             pj_thread_t **thread,
+                                             const char *name = NULL )
+    {
+        return pj_thread_register( name, desc, thread );
+    }
+
+    //
+    // Get current thread.
+    // Will return pj_thread_t (sorry folks, not Pj_Thread).
+    //
+    static pj_thread_t *this_thread()
+    {
+        return pj_thread_this();
+    }
+
+    //
+    // Get thread name.
+    //
+    static const char *get_name(pj_thread_t *thread)
+    {
+        return pj_thread_get_name(thread);
+    }
+
+    //
+    // Resume thread.
+    //
+    static pj_status_t resume(pj_thread_t *thread)
+    {
+        return pj_thread_resume(thread);
+    }
+
+    //
+    // Sleep.
+    //
+    static pj_status_t sleep(unsigned msec)
+    {
+	return pj_thread_sleep(msec);
+    }
+
+    //
+    // Join the specified thread.
+    //
+    static pj_status_t join(pj_thread_t *thread)
+    {
+        return pj_thread_join(thread);
+    }
+
+    //
+    // Destroy thread
+    //
+    static pj_status_t destroy(pj_thread_t *thread)
+    {
+        return pj_thread_destroy(thread);
+    }
+};
+
+
+
+//
+// Thread object.
+//
+// How to use:
+//  Derive a class from this class, then override main().
+//
+class Pj_Thread : public Pj_Object
+{
+public:
+    enum Flags
+    {
+	FLAG_SUSPENDED = PJ_THREAD_SUSPENDED
+    };
+
+    //
+    // Default constructor.
+    //
+    Pj_Thread()
+        : thread_(NULL)
+    {
+    }
+
+    //
+    // Destroy thread.
+    //
+    ~Pj_Thread()
+    {
+        destroy();
+    }
+
+    //
+    // This is the main thread function.
+    //
+    virtual int main() = 0;
+
+    //
+    // Start a thread.
+    //
+    pj_status_t create( Pj_Pool *pool, 
+                        unsigned flags = 0,
+                        const char *thread_name = NULL,
+			pj_size_t stack_size = PJ_THREAD_DEFAULT_STACK_SIZE)
+    {
+        destroy();
+        return Pj_Thread_API::create( pool, &thread_, &thread_proc, this,
+                                      flags, thread_name, stack_size);
+    }
+
+    //
+    // Get pjlib compatible thread object.
+    //
+    pj_thread_t *pj_thread_t_()
+    {
+	return thread_;
+    }
+
+    //
+    // Get thread name.
+    //
+    const char *get_name()
+    {
+        return Pj_Thread_API::get_name(thread_);
+    }
+
+    //
+    // Resume a suspended thread.
+    //
+    pj_status_t resume()
+    {
+        return Pj_Thread_API::resume(thread_);
+    }
+
+    //
+    // Join this thread.
+    //
+    pj_status_t join()
+    {
+        return Pj_Thread_API::join(thread_);
+    }
+
+    //
+    // Destroy thread.
+    //
+    pj_status_t destroy()
+    {
+        if (thread_) {
+            Pj_Thread_API::destroy(thread_);
+            thread_ = NULL;
+        }
+    }
+
+protected:
+    pj_thread_t *thread_;
+
+    static int PJ_THREAD_FUNC thread_proc(void *obj)
+    {
+        Pj_Thread *thread_class = (Pj_Thread*)obj;
+        return thread_class->main();
+    }
+};
+
+
+//
+// External Thread
+//  (threads that were started by external means, i.e. not 
+//   with Pj_Thread::create).
+//
+// This class will normally be defined as local variable in
+// external thread's stack, normally inside thread's main proc.
+// But be aware that the handle will be destroyed on destructor!
+//
+class Pj_External_Thread : public Pj_Thread
+{
+public:
+    Pj_External_Thread()
+    {
+    }
+
+    //
+    // Register external thread so that pjlib functions can work
+    // in that thread.
+    //
+    pj_status_t register_this_thread( const char *name=NULL )
+    {
+        return Pj_Thread_API::register_this_thread(desc_, &thread_,name);
+    }
+
+private:
+    pj_thread_desc desc_;
+};
+
+
+//
+// Thread specific data/thread local storage/TLS.
+//
+class Pj_Thread_Local_API
+{
+public:
+    //
+    // Allocate thread local storage (TLS) index.
+    //
+    static pj_status_t alloc(long *index)
+    {
+        return pj_thread_local_alloc(index);
+    }
+
+    //
+    // Free TLS index.
+    //
+    static void free(long index)
+    {
+        pj_thread_local_free(index);
+    }
+
+    //
+    // Set thread specific data.
+    //
+    static pj_status_t set(long index, void *value)
+    {
+        return pj_thread_local_set(index, value);
+    }
+
+    //
+    // Get thread specific data.
+    //
+    static void *get(long index)
+    {
+        return pj_thread_local_get(index);
+    }
+
+};
+
+//
+// Atomic variable
+//
+// How to use:
+//   Pj_Atomic_Var var(pool, 0);
+//   var.set(..);
+//
+class Pj_Atomic_Var : public Pj_Object
+{
+public:
+    //
+    // Default constructor, initialize variable with NULL.
+    //
+    Pj_Atomic_Var()
+        : var_(NULL)
+    {
+    }
+
+    //
+    // Construct atomic variable.
+    //
+    Pj_Atomic_Var(Pj_Pool *pool, pj_atomic_value_t value)
+        : var_(NULL)
+    {
+        create(pool, value);
+    }
+
+    //
+    // Destructor.
+    //
+    ~Pj_Atomic_Var()
+    {
+        destroy();
+    }
+
+    //
+    // Create atomic variable.
+    //
+    pj_status_t create( Pj_Pool *pool, pj_atomic_value_t value)
+    {
+        destroy();
+	return pj_atomic_create(pool->pool_(), value, &var_);
+    }
+
+    //
+    // Destroy.
+    //
+    void destroy()
+    {
+        if (var_) {
+            pj_atomic_destroy(var_);
+            var_ = NULL;
+        }
+    }
+
+    //
+    // Get pjlib compatible atomic variable.
+    //
+    pj_atomic_t *pj_atomic_t_()
+    {
+	return var_;
+    }
+
+    //
+    // Set the value.
+    //
+    void set(pj_atomic_value_t val)
+    {
+	pj_atomic_set(var_, val);
+    }
+
+    //
+    // Get the value.
+    //
+    pj_atomic_value_t get()
+    {
+	return pj_atomic_get(var_);
+    }
+
+    //
+    // Increment.
+    //
+    void inc()
+    {
+	pj_atomic_inc(var_);
+    }
+
+    //
+    // Increment and get the result.
+    //
+    pj_atomic_value_t inc_and_get()
+    {
+        return pj_atomic_inc_and_get(var_);
+    }
+
+    //
+    // Decrement.
+    //
+    void dec()
+    {
+	pj_atomic_dec(var_);
+    }
+
+    //
+    // Decrement and get the result.
+    //
+    pj_atomic_value_t dec_and_get()
+    {
+        return pj_atomic_dec_and_get(var_);
+    }
+
+    //
+    // Add the variable.
+    //
+    void add(pj_atomic_value_t value)
+    {
+        pj_atomic_add(var_, value);
+    }
+
+    //
+    // Add the variable and get the value.
+    //
+    pj_atomic_value_t add_and_get(pj_atomic_value_t value)
+    {
+        return pj_atomic_add_and_get(var_, value );
+    }
+
+private:
+    pj_atomic_t *var_;
+};
+
+
+//
+// Mutex
+//
+class Pj_Mutex : public Pj_Object
+{
+public:
+    //
+    // Mutex type.
+    //
+    enum Type
+    {
+	DEFAULT = PJ_MUTEX_DEFAULT,
+	SIMPLE = PJ_MUTEX_SIMPLE,
+	RECURSE = PJ_MUTEX_RECURSE,
+    };
+
+    //
+    // Default constructor will create default mutex.
+    //
+    explicit Pj_Mutex(Pj_Pool *pool, Type type = DEFAULT,
+                      const char *name = NULL)
+        : mutex_(NULL)
+    {
+        create(pool, type, name);
+    }
+
+    //
+    // Destructor.
+    //
+    ~Pj_Mutex()
+    {
+        destroy();
+    }
+
+    //
+    // Create mutex.
+    //
+    pj_status_t create( Pj_Pool *pool, Type type, const char *name = NULL)
+    {
+        destroy();
+	return pj_mutex_create( pool->pool_(), name, type,
+                                &mutex_ );
+    }
+
+    //
+    // Create simple mutex.
+    //
+    pj_status_t create_simple( Pj_Pool *pool,const char *name = NULL)
+    {
+        return create(pool, SIMPLE, name);
+    }
+
+    //
+    // Create recursive mutex.
+    //
+    pj_status_t create_recursive( Pj_Pool *pool, const char *name = NULL )
+    {
+        return create(pool, RECURSE, name);
+    }
+
+    //
+    // Get pjlib compatible mutex object.
+    //
+    pj_mutex_t *pj_mutex_t_()
+    {
+	return mutex_;
+    }
+
+    //
+    // Destroy mutex.
+    //
+    void destroy()
+    {
+        if (mutex_) {
+	    pj_mutex_destroy(mutex_);
+            mutex_ = NULL;
+        }
+    }
+
+    //
+    // Lock mutex.
+    //
+    pj_status_t acquire()
+    {
+	return pj_mutex_lock(mutex_);
+    }
+
+    //
+    // Unlock mutex.
+    //
+    pj_status_t release()
+    {
+	return pj_mutex_unlock(mutex_);
+    }
+
+    //
+    // Try locking the mutex.
+    //
+    pj_status_t tryacquire()
+    {
+	return pj_mutex_trylock(mutex_);
+    }
+
+private:
+    pj_mutex_t *mutex_;
+};
+
+
+//
+// Semaphore
+//
+class Pj_Semaphore : public Pj_Object
+{
+public:
+    //
+    // Construct semaphore
+    //
+    Pj_Semaphore(Pj_Pool *pool, unsigned max,
+                 unsigned initial = 0, const char *name = NULL)
+    : sem_(NULL)
+    {
+	create(pool, max, initial, name);
+    }
+
+    //
+    // Destructor.
+    //
+    ~Pj_Semaphore()
+    {
+        destroy();
+    }
+
+    //
+    // Create semaphore
+    //
+    pj_status_t create( Pj_Pool *pool, unsigned max,
+                        unsigned initial = 0, const char *name = NULL )
+    {
+        destroy();
+	return pj_sem_create( pool->pool_(), name, initial, max, &sem_);
+    }
+
+    //
+    // Destroy semaphore.
+    //
+    void destroy()
+    {
+        if (sem_) {
+            pj_sem_destroy(sem_);
+            sem_ = NULL;
+        }
+    }
+
+    //
+    // Get pjlib compatible semaphore object.
+    //
+    pj_sem_t *pj_sem_t_()
+    {
+	return (pj_sem_t*)this;
+    }
+
+    //
+    // Wait semaphore.
+    //
+    pj_status_t wait()
+    {
+	return pj_sem_wait(this->pj_sem_t_());
+    }
+
+    //
+    // Wait semaphore.
+    //
+    pj_status_t acquire()
+    {
+	return wait();
+    }
+
+    //
+    // Try wait semaphore.
+    //
+    pj_status_t trywait()
+    {
+	return pj_sem_trywait(this->pj_sem_t_());
+    }
+
+    //
+    // Try wait semaphore.
+    //
+    pj_status_t tryacquire()
+    {
+	return trywait();
+    }
+
+    //
+    // Post semaphore.
+    //
+    pj_status_t post()
+    {
+	return pj_sem_post(this->pj_sem_t_());
+    }
+
+    //
+    // Post semaphore.
+    //
+    pj_status_t release()
+    {
+	return post();
+    }
+
+private:
+    pj_sem_t *sem_;
+};
+
+
+//
+// Event object.
+//
+class Pj_Event
+{
+public:
+    //
+    // Construct event object.
+    //
+    Pj_Event( Pj_Pool *pool, bool manual_reset = false,
+              bool initial = false, const char *name = NULL )
+    : event_(NULL)
+    {
+        create(pool, manual_reset, initial, name);
+    }
+
+    //
+    // Destructor.
+    //
+    ~Pj_Event()
+    {
+        destroy();
+    }
+
+    //
+    // Create event object.
+    //
+    pj_status_t create( Pj_Pool *pool, bool manual_reset = false, 
+                        bool initial = false, const char *name = NULL)
+    {
+        destroy();
+	return pj_event_create(pool->pool_(), name, manual_reset, initial,
+                               &event_);
+    }
+
+    //
+    // Get pjlib compatible event object.
+    //
+    pj_event_t *pj_event_t_()
+    {
+	return event_;
+    }
+
+    //
+    // Destroy event object.
+    //
+    void destroy()
+    {
+        if (event_) {
+	    pj_event_destroy(event_);
+            event_ = NULL;
+        }
+    }
+
+    //
+    // Wait.
+    //
+    pj_status_t wait()
+    {
+	return pj_event_wait(event_);
+    }
+
+    //
+    // Try wait.
+    //
+    pj_status_t trywait()
+    {
+	return pj_event_trywait(event_);
+    }
+
+    //
+    // Set event state to signalled.
+    //
+    pj_status_t set()
+    {
+	return pj_event_set(this->pj_event_t_());
+    }
+
+    //
+    // Release one waiting thread.
+    //
+    pj_status_t pulse()
+    {
+	return pj_event_pulse(this->pj_event_t_());
+    }
+
+    //
+    // Set a non-signalled.
+    //
+    pj_status_t reset()
+    {
+	return pj_event_reset(this->pj_event_t_());
+    }
+
+private:
+    pj_event_t *event_;
+};
+
+//
+// Timestamp
+//
+class Pj_Timestamp
+{
+public:
+    pj_status_t get_timestamp()
+    {
+	return pj_get_timestamp(&ts_);
+    }
+
+    Pj_Timestamp& operator += (const Pj_Timestamp &rhs)
+    {
+	pj_add_timestamp(&ts_, &rhs.ts_);
+	return *this;
+    }
+
+    Pj_Timestamp& operator -= (const Pj_Timestamp &rhs)
+    {
+	pj_sub_timestamp(&ts_, &rhs.ts_);
+	return *this;
+    }
+
+    Pj_Time_Val to_time() const
+    {
+	Pj_Timestamp zero;
+	pj_memset(&zero, 0, sizeof(zero));
+	return Pj_Time_Val(pj_elapsed_time(&zero.ts_, &ts_));
+    }
+
+    pj_uint32_t to_msec() const
+    {
+	Pj_Timestamp zero;
+	pj_memset(&zero, 0, sizeof(zero));
+	return pj_elapsed_msec(&zero.ts_, &ts_);
+    }
+
+    pj_uint32_t to_usec() const
+    {
+	Pj_Timestamp zero;
+	pj_memset(&zero, 0, sizeof(zero));
+	return pj_elapsed_usec(&zero.ts_, &ts_);
+    }
+
+    pj_uint32_t to_nanosec() const
+    {
+	Pj_Timestamp zero;
+	pj_memset(&zero, 0, sizeof(zero));
+	return pj_elapsed_nanosec(&zero.ts_, &ts_);
+    }
+
+    pj_uint32_t to_cycle() const
+    {
+	Pj_Timestamp zero;
+	pj_memset(&zero, 0, sizeof(zero));
+	return pj_elapsed_cycle(&zero.ts_, &ts_);
+    }
+
+private:
+    pj_timestamp    ts_;
+};
+
+
+//
+// OS abstraction.
+//
+class Pj_OS_API
+{
+public:
+    //
+    // Get current time.
+    //
+    static pj_status_t gettimeofday( Pj_Time_Val *tv )
+    {
+	return pj_gettimeofday(tv);
+    }
+
+    //
+    // Parse to time of day.
+    //
+    static pj_status_t time_decode( const Pj_Time_Val *tv, 
+                                    pj_parsed_time *pt )
+    {
+	return pj_time_decode(tv, pt);
+    }
+
+    //
+    // Parse from time of day.
+    //
+    static pj_status_t time_encode( const pj_parsed_time *pt, 
+                                    Pj_Time_Val *tv)
+    {
+	return pj_time_encode(pt, tv);
+    }
+
+    //
+    // Convert to GMT.
+    //
+    static pj_status_t time_local_to_gmt( Pj_Time_Val *tv )
+    {
+	return pj_time_local_to_gmt( tv );
+    }
+
+    //
+    // Convert time to local.
+    //
+    static pj_status_t time_gmt_to_local( Pj_Time_Val *tv) 
+    {
+	return pj_time_gmt_to_local( tv );
+    }
+};
+
+//
+// Timeval inlines.
+//
+inline pj_status_t Pj_Time_Val::gettimeofday()
+{
+    return Pj_OS_API::gettimeofday(this);
+}
+
+inline pj_parsed_time Pj_Time_Val::decode()
+{
+    pj_parsed_time pt;
+    Pj_OS_API::time_decode(this, &pt);
+    return pt;
+}
+
+inline pj_status_t Pj_Time_Val::encode(const pj_parsed_time *pt)
+{
+    return Pj_OS_API::time_encode(pt, this);
+}
+
+inline pj_status_t Pj_Time_Val::to_gmt()
+{
+    return Pj_OS_API::time_local_to_gmt(this);
+}
+
+inline pj_status_t Pj_Time_Val::to_local()
+{
+    return Pj_OS_API::time_gmt_to_local(this);
+}
+
+#endif	/* __PJPP_OS_HPP__ */
+
diff --git a/jni/pjproject-android/.svn/pristine/7f/7f1d2c97acf9436310c942260d4350c17654a586.svn-base b/jni/pjproject-android/.svn/pristine/7f/7f1d2c97acf9436310c942260d4350c17654a586.svn-base
new file mode 100644
index 0000000..952ecdd
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/7f/7f1d2c97acf9436310c942260d4350c17654a586.svn-base
@@ -0,0 +1,53 @@
+/* Copyright (C) 2002 Jean-Marc Valin */
+/**
+   @file lpc.h
+   @brief Functions for LPC (Linear Prediction Coefficients) analysis
+*/
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+   
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+   
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+   
+   - Neither the name of the Xiph.org Foundation nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+   
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef LPC_H
+#define LPC_H
+
+#include "arch.h"
+
+void _spx_autocorr(
+              const spx_word16_t * x,   /*  in: [0...n-1] samples x   */
+              spx_word16_t *ac,   /* out: [0...lag-1] ac values */
+              int lag, int   n);
+
+spx_word32_t                      /* returns minimum mean square error    */
+_spx_lpc(
+    spx_coef_t       * lpc, /*      [0...p-1] LPC coefficients      */
+    const spx_word16_t * ac,  /*  in: [0...p] autocorrelation values  */
+    int p
+    );
+
+
+#endif
diff --git a/jni/pjproject-android/.svn/pristine/7f/7f25a740b14c70b16a3084a0d97091466120232b.svn-base b/jni/pjproject-android/.svn/pristine/7f/7f25a740b14c70b16a3084a0d97091466120232b.svn-base
new file mode 100644
index 0000000..b4acce6
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/7f/7f25a740b14c70b16a3084a0d97091466120232b.svn-base
@@ -0,0 +1,17 @@
+include ../../../build.mak
+
+lib_dir:
+	@for token in `echo $(APP_LDFLAGS)`; do \
+		echo $$token | grep L | sed 's/-L//'; \
+	done
+
+inc_dir:
+	@for token in `echo $(APP_CFLAGS)`; do \
+		echo $$token | grep I | sed 's/-I//'; \
+	done
+
+libs:
+	@for token in `echo $(APP_LDLIBS)`; do \
+		echo $$token | grep \\-l | sed 's/-l//'; \
+	done
+
diff --git a/jni/pjproject-android/.svn/pristine/7f/7f33155eb56e1b72a0e1bf0b0bfd2282c530e45f.svn-base b/jni/pjproject-android/.svn/pristine/7f/7f33155eb56e1b72a0e1bf0b0bfd2282c530e45f.svn-base
new file mode 100644
index 0000000..d68674b
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/7f/7f33155eb56e1b72a0e1bf0b0bfd2282c530e45f.svn-base
@@ -0,0 +1,197 @@
+/* Copyright (C) 2002 Jean-Marc Valin */
+/**
+   @file speex_jitter.h
+   @brief Adaptive jitter buffer for Speex
+*/
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+   
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+   
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+   
+   - Neither the name of the Xiph.org Foundation nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+   
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef SPEEX_JITTER_H
+#define SPEEX_JITTER_H
+/** @defgroup JitterBuffer JitterBuffer: Adaptive jitter buffer
+ *  This is the jitter buffer that reorders UDP/RTP packets and adjusts the buffer size
+ * to maintain good quality and low latency.
+ *  @{
+ */
+
+#include "speex/speex_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Generic adaptive jitter buffer state */
+struct JitterBuffer_;
+
+/** Generic adaptive jitter buffer state */
+typedef struct JitterBuffer_ JitterBuffer;
+
+/** Definition of an incoming packet */
+typedef struct _JitterBufferPacket JitterBufferPacket;
+
+/** Definition of an incoming packet */
+struct _JitterBufferPacket {
+   char        *data;       /**< Data bytes contained in the packet */
+   spx_uint32_t len;        /**< Length of the packet in bytes */
+   spx_uint32_t timestamp;  /**< Timestamp for the packet */
+   spx_uint32_t span;       /**< Time covered by the packet (same units as timestamp) */
+   spx_uint16_t sequence;   /**< RTP Sequence number if available (0 otherwise) */
+   spx_uint32_t user_data;  /**< Put whatever data you like here (it's ignored by the jitter buffer) */
+};
+
+/** Packet has been retrieved */
+#define JITTER_BUFFER_OK 0
+/** Packet is lost or is late */
+#define JITTER_BUFFER_MISSING 1
+/** A "fake" packet is meant to be inserted here to increase buffering */
+#define JITTER_BUFFER_INSERTION 2
+/** There was an error in the jitter buffer */
+#define JITTER_BUFFER_INTERNAL_ERROR -1
+/** Invalid argument */
+#define JITTER_BUFFER_BAD_ARGUMENT -2
+
+
+/** Set minimum amount of extra buffering required (margin) */
+#define JITTER_BUFFER_SET_MARGIN 0
+/** Get minimum amount of extra buffering required (margin) */
+#define JITTER_BUFFER_GET_MARGIN 1
+/* JITTER_BUFFER_SET_AVAILABLE_COUNT wouldn't make sense */
+
+/** Get the amount of available packets currently buffered */
+#define JITTER_BUFFER_GET_AVAILABLE_COUNT 3
+/** Included because of an early misspelling (will remove in next release) */
+#define JITTER_BUFFER_GET_AVALIABLE_COUNT 3
+
+/** Assign a function to destroy unused packet. When setting that, the jitter 
+    buffer no longer copies packet data. */
+#define JITTER_BUFFER_SET_DESTROY_CALLBACK 4
+/**  */
+#define JITTER_BUFFER_GET_DESTROY_CALLBACK 5
+
+/** Tell the jitter buffer to only adjust the delay in multiples of the step parameter provided */
+#define JITTER_BUFFER_SET_DELAY_STEP 6
+/**  */
+#define JITTER_BUFFER_GET_DELAY_STEP 7
+
+/** Tell the jitter buffer to only do concealment in multiples of the size parameter provided */
+#define JITTER_BUFFER_SET_CONCEALMENT_SIZE 8
+#define JITTER_BUFFER_GET_CONCEALMENT_SIZE 9
+
+/** Absolute max amount of loss that can be tolerated regardless of the delay. Typical loss 
+    should be half of that or less. */
+#define JITTER_BUFFER_SET_MAX_LATE_RATE 10
+#define JITTER_BUFFER_GET_MAX_LATE_RATE 11
+
+/** Equivalent cost of one percent late packet in timestamp units */
+#define JITTER_BUFFER_SET_LATE_COST 12
+#define JITTER_BUFFER_GET_LATE_COST 13
+
+
+/** Initialises jitter buffer 
+ * 
+ * @param step_size Starting value for the size of concleanment packets and delay 
+       adjustment steps. Can be changed at any time using JITTER_BUFFER_SET_DELAY_STEP
+       and JITTER_BUFFER_GET_CONCEALMENT_SIZE.
+ * @return Newly created jitter buffer state
+ */
+JitterBuffer *jitter_buffer_init(int step_size);
+
+/** Restores jitter buffer to its original state 
+ * 
+ * @param jitter Jitter buffer state
+ */
+void jitter_buffer_reset(JitterBuffer *jitter);
+
+/** Destroys jitter buffer 
+ * 
+ * @param jitter Jitter buffer state
+ */
+void jitter_buffer_destroy(JitterBuffer *jitter);
+
+/** Put one packet into the jitter buffer
+ * 
+ * @param jitter Jitter buffer state
+ * @param packet Incoming packet
+*/
+void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet);
+
+/** Get one packet from the jitter buffer
+ * 
+ * @param jitter Jitter buffer state
+ * @param packet Returned packet
+ * @param desired_span Number of samples (or units) we wish to get from the buffer (no guarantee)
+ * @param current_timestamp Timestamp for the returned packet 
+*/
+int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t desired_span, spx_int32_t *start_offset);
+
+/** Used right after jitter_buffer_get() to obtain another packet that would have the same timestamp.
+ * This is mainly useful for media where a single "frame" can be split into several packets.
+ * 
+ * @param jitter Jitter buffer state
+ * @param packet Returned packet
+ */
+int jitter_buffer_get_another(JitterBuffer *jitter, JitterBufferPacket *packet);
+
+/** Get pointer timestamp of jitter buffer
+ * 
+ * @param jitter Jitter buffer state
+*/
+int jitter_buffer_get_pointer_timestamp(JitterBuffer *jitter);
+
+/** Advance by one tick
+ * 
+ * @param jitter Jitter buffer state
+*/
+void jitter_buffer_tick(JitterBuffer *jitter);
+
+/** Telling the jitter buffer about the remaining data in the application buffer
+ * @param jitter Jitter buffer state
+ * @param rem Amount of data buffered by the application (timestamp units)
+ */
+void jitter_buffer_remaining_span(JitterBuffer *jitter, spx_uint32_t rem);
+
+/** Used like the ioctl function to control the jitter buffer parameters
+ * 
+ * @param jitter Jitter buffer state
+ * @param request ioctl-type request (one of the JITTER_BUFFER_* macros)
+ * @param ptr Data exchanged to-from function
+ * @return 0 if no error, -1 if request in unknown
+*/
+int jitter_buffer_ctl(JitterBuffer *jitter, int request, void *ptr);
+
+int jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t *start_offset);
+
+/* @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/jni/pjproject-android/.svn/pristine/7f/7f3f67aef48ead049bebdab307c04c2e03342710.svn-base b/jni/pjproject-android/.svn/pristine/7f/7f3f67aef48ead049bebdab307c04c2e03342710.svn-base
new file mode 100644
index 0000000..de6fbe2
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/7f/7f3f67aef48ead049bebdab307c04c2e03342710.svn-base
@@ -0,0 +1,35 @@
+Copyright 2002-2008 	Xiph.org Foundation
+Copyright 2002-2008 	Jean-Marc Valin
+Copyright 2005-2007	Analog Devices Inc.
+Copyright 2005-2008	Commonwealth Scientific and Industrial Research 
+                        Organisation (CSIRO)
+Copyright 1993, 2002, 2006 David Rowe
+Copyright 2003 		EpicGames
+Copyright 1992-1994	Jutta Degener, Carsten Bormann
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+- Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+- Neither the name of the Xiph.org Foundation nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/jni/pjproject-android/.svn/pristine/7f/7f9cb8208397e2985603c579a2fd5e80da12b3c0.svn-base b/jni/pjproject-android/.svn/pristine/7f/7f9cb8208397e2985603c579a2fd5e80da12b3c0.svn-base
new file mode 100644
index 0000000..887a1b5
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/7f/7f9cb8208397e2985603c579a2fd5e80da12b3c0.svn-base
@@ -0,0 +1,213 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#ifndef __PJMEDIA_ALAW_ULAW_H__
+#define __PJMEDIA_ALAW_ULAW_H__
+
+#include <pjmedia/types.h>
+
+PJ_BEGIN_DECL
+
+#if defined(PJMEDIA_HAS_ALAW_ULAW_TABLE) && PJMEDIA_HAS_ALAW_ULAW_TABLE!=0
+
+extern const pj_uint8_t pjmedia_linear2ulaw_tab[16384];
+extern const pj_uint8_t pjmedia_linear2alaw_tab[16384];
+extern const pj_int16_t pjmedia_ulaw2linear_tab[256];
+extern const pj_int16_t pjmedia_alaw2linear_tab[256];
+
+
+/**
+ * Convert 16-bit linear PCM value to 8-bit A-Law.
+ *
+ * @param pcm_val   16-bit linear PCM value.
+ * @return	    8-bit A-Law value.
+ */
+#define pjmedia_linear2alaw(pcm_val)	\
+	    pjmedia_linear2alaw_tab[(((pj_int16_t)pcm_val) >> 2) & 0x3fff]
+
+/**
+ * Convert 8-bit A-Law value to 16-bit linear PCM value.
+ *
+ * @param chara_val 8-bit A-Law value.
+ * @return	    16-bit linear PCM value.
+ */
+#define pjmedia_alaw2linear(chara_val)	\
+	    pjmedia_alaw2linear_tab[chara_val]
+
+/**
+ * Convert 16-bit linear PCM value to 8-bit U-Law.
+ *
+ * @param pcm_val   16-bit linear PCM value.
+ * @return	    U-bit A-Law value.
+ */
+#define pjmedia_linear2ulaw(pcm_val)	\
+	    pjmedia_linear2ulaw_tab[(((pj_int16_t)pcm_val) >> 2) & 0x3fff]
+
+/**
+ * Convert 8-bit U-Law value to 16-bit linear PCM value.
+ *
+ * @param u_val	    8-bit U-Law value.
+ * @return	    16-bit linear PCM value.
+ */
+#define pjmedia_ulaw2linear(u_val)	\
+	    pjmedia_ulaw2linear_tab[u_val]
+
+/**
+ * Convert 8-bit A-Law value to 8-bit U-Law value.
+ *
+ * @param aval	    8-bit A-Law value.
+ * @return	    8-bit U-Law value.
+ */
+#define pjmedia_alaw2ulaw(aval)		\
+	    pjmedia_linear2ulaw(pjmedia_alaw2linear(aval))
+
+/**
+ * Convert 8-bit U-Law value to 8-bit A-Law value.
+ *
+ * @param uval	    8-bit U-Law value.
+ * @return	    8-bit A-Law value.
+ */
+#define pjmedia_ulaw2alaw(uval)		\
+	    pjmedia_linear2alaw(pjmedia_ulaw2linear(uval))
+
+
+#else
+
+/**
+ * Convert 16-bit linear PCM value to 8-bit A-Law.
+ *
+ * @param pcm_val   16-bit linear PCM value.
+ * @return	    8-bit A-Law value.
+ */
+PJ_DECL(pj_uint8_t) pjmedia_linear2alaw(int pcm_val);
+
+/**
+ * Convert 8-bit A-Law value to 16-bit linear PCM value.
+ *
+ * @param chara_val 8-bit A-Law value.
+ * @return	    16-bit linear PCM value.
+ */
+PJ_DECL(int) pjmedia_alaw2linear(unsigned chara_val);
+
+/**
+ * Convert 16-bit linear PCM value to 8-bit U-Law.
+ *
+ * @param pcm_val   16-bit linear PCM value.
+ * @return	    U-bit A-Law value.
+ */
+PJ_DECL(unsigned char) pjmedia_linear2ulaw(int pcm_val);
+
+/**
+ * Convert 8-bit U-Law value to 16-bit linear PCM value.
+ *
+ * @param u_val	    8-bit U-Law value.
+ * @return	    16-bit linear PCM value.
+ */
+PJ_DECL(int) pjmedia_ulaw2linear(unsigned char u_val);
+
+/**
+ * Convert 8-bit A-Law value to 8-bit U-Law value.
+ *
+ * @param aval	    8-bit A-Law value.
+ * @return	    8-bit U-Law value.
+ */
+PJ_DECL(unsigned char) pjmedia_alaw2ulaw(unsigned char aval);
+
+/**
+ * Convert 8-bit U-Law value to 8-bit A-Law value.
+ *
+ * @param uval	    8-bit U-Law value.
+ * @return	    8-bit A-Law value.
+ */
+PJ_DECL(unsigned char) pjmedia_ulaw2alaw(unsigned char uval);
+
+#endif
+
+/**
+ * Encode 16-bit linear PCM data to 8-bit U-Law data.
+ *
+ * @param dst	    Destination buffer for 8-bit U-Law data.
+ * @param src	    Source, 16-bit linear PCM data.
+ * @param count	    Number of samples.
+ */
+PJ_INLINE(void) pjmedia_ulaw_encode(pj_uint8_t *dst, const pj_int16_t *src, 
+				    pj_size_t count)
+{
+    const pj_int16_t *end = src + count;
+    
+    while (src < end) {
+	*dst++ = pjmedia_linear2ulaw(*src++);
+    }
+}
+
+/**
+ * Encode 16-bit linear PCM data to 8-bit A-Law data.
+ *
+ * @param dst	    Destination buffer for 8-bit A-Law data.
+ * @param src	    Source, 16-bit linear PCM data.
+ * @param count	    Number of samples.
+ */
+PJ_INLINE(void) pjmedia_alaw_encode(pj_uint8_t *dst, const pj_int16_t *src, 
+				    pj_size_t count)
+{
+    const pj_int16_t *end = src + count;
+    
+    while (src < end) {
+	*dst++ = pjmedia_linear2alaw(*src++);
+    }
+}
+
+/**
+ * Decode 8-bit U-Law data to 16-bit linear PCM data.
+ *
+ * @param dst	    Destination buffer for 16-bit PCM data.
+ * @param src	    Source, 8-bit U-Law data.
+ * @param len	    Encoded frame/source length in bytes.
+ */
+PJ_INLINE(void) pjmedia_ulaw_decode(pj_int16_t *dst, const pj_uint8_t *src, 
+				    pj_size_t len)
+{
+    const pj_uint8_t *end = src + len;
+    
+    while (src < end) {
+	*dst++ = pjmedia_ulaw2linear(*src++);
+    }
+}
+
+/**
+ * Decode 8-bit A-Law data to 16-bit linear PCM data.
+ *
+ * @param dst	    Destination buffer for 16-bit PCM data.
+ * @param src	    Source, 8-bit A-Law data.
+ * @param len	    Encoded frame/source length in bytes.
+ */
+PJ_INLINE(void) pjmedia_alaw_decode(pj_int16_t *dst, const pj_uint8_t *src, 
+				    pj_size_t len)
+{
+    const pj_uint8_t *end = src + len;
+    
+    while (src < end) {
+	*dst++ = pjmedia_alaw2linear(*src++);
+    }
+}
+
+PJ_END_DECL
+
+#endif	/* __PJMEDIA_ALAW_ULAW_H__ */
+
diff --git a/jni/pjproject-android/.svn/pristine/7f/7fd3e078ff9483e9bdcd23c80e9ddd6e76552e8e.svn-base b/jni/pjproject-android/.svn/pristine/7f/7fd3e078ff9483e9bdcd23c80e9ddd6e76552e8e.svn-base
new file mode 100644
index 0000000..2d7a3b0
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/7f/7fd3e078ff9483e9bdcd23c80e9ddd6e76552e8e.svn-base
@@ -0,0 +1,26 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include <pj/list.h>
+
+#if !PJ_FUNCTIONS_ARE_INLINED
+#  include <pj/list_i.h>
+#endif
+
+
diff --git a/jni/pjproject-android/.svn/pristine/7f/7fed08acf20717af7fb4ad1a82cd12d28d78d9c2.svn-base b/jni/pjproject-android/.svn/pristine/7f/7fed08acf20717af7fb4ad1a82cd12d28d78d9c2.svn-base
new file mode 100644
index 0000000..173be9a
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/7f/7fed08acf20717af7fb4ad1a82cd12d28d78d9c2.svn-base
@@ -0,0 +1,858 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+
+#include <pjmedia/rtcp_xr.h>
+#include <pjmedia/errno.h>
+#include <pjmedia/rtcp.h>
+#include <pj/assert.h>
+#include <pj/log.h>
+#include <pj/os.h>
+#include <pj/sock.h>
+#include <pj/string.h>
+
+#if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0)
+
+#define THIS_FILE "rtcp_xr.c"
+
+
+#if PJ_HAS_HIGH_RES_TIMER==0
+#   error "High resolution timer needs to be enabled"
+#endif
+
+
+/* RTCP XR payload type */
+#define RTCP_XR		    207
+
+/* RTCP XR block types */
+#define BT_LOSS_RLE	    1
+#define BT_DUP_RLE	    2
+#define BT_RCPT_TIMES	    3
+#define BT_RR_TIME	    4
+#define BT_DLRR		    5
+#define BT_STATS	    6
+#define BT_VOIP_METRICS	    7
+
+
+#define DEFAULT_GMIN	    16
+
+
+#if 0
+#   define TRACE_(x)	PJ_LOG(3,x)
+#else
+#   define TRACE_(x)	;
+#endif
+
+void pjmedia_rtcp_xr_init( pjmedia_rtcp_xr_session *session, 
+			   struct pjmedia_rtcp_session *parent_session,
+			   pj_uint8_t gmin,
+			   unsigned frames_per_packet)
+{
+    pj_bzero(session, sizeof(pjmedia_rtcp_xr_session));
+
+    session->name = parent_session->name;
+    session->rtcp_session = parent_session;
+    pj_memcpy(&session->pkt.common, &session->rtcp_session->rtcp_sr_pkt.common,
+	      sizeof(pjmedia_rtcp_common));
+    session->pkt.common.pt = RTCP_XR;
+
+    /* Init config */
+    session->stat.rx.voip_mtc.gmin = (pj_uint8_t)(gmin? gmin : DEFAULT_GMIN);
+    session->ptime = session->rtcp_session->pkt_size * 1000 / 
+		     session->rtcp_session->clock_rate;
+    session->frames_per_packet = frames_per_packet;
+
+    /* Init Statistics Summary fields which have non-zero default */
+    session->stat.rx.stat_sum.jitter.min = (unsigned) -1;
+    session->stat.rx.stat_sum.toh.min = (unsigned) -1;
+
+    /* Init VoIP Metrics fields which have non-zero default */
+    session->stat.rx.voip_mtc.signal_lvl = 127;
+    session->stat.rx.voip_mtc.noise_lvl = 127;
+    session->stat.rx.voip_mtc.rerl = 127;
+    session->stat.rx.voip_mtc.r_factor = 127;
+    session->stat.rx.voip_mtc.ext_r_factor = 127;
+    session->stat.rx.voip_mtc.mos_lq = 127;
+    session->stat.rx.voip_mtc.mos_cq = 127;
+
+    session->stat.tx.voip_mtc.signal_lvl = 127;
+    session->stat.tx.voip_mtc.noise_lvl = 127;
+    session->stat.tx.voip_mtc.rerl = 127;
+    session->stat.tx.voip_mtc.r_factor = 127;
+    session->stat.tx.voip_mtc.ext_r_factor = 127;
+    session->stat.tx.voip_mtc.mos_lq = 127;
+    session->stat.tx.voip_mtc.mos_cq = 127;
+}
+
+void pjmedia_rtcp_xr_fini(pjmedia_rtcp_xr_session *session)
+{
+    PJ_UNUSED_ARG(session);
+}
+
+PJ_DEF(void) pjmedia_rtcp_build_rtcp_xr( pjmedia_rtcp_xr_session *sess, 
+					 unsigned rpt_types,
+					 void **rtcp_pkt, int *len)
+{
+    pj_uint16_t size = 0;
+
+    /* Receiver Reference Time Report Block */
+    /* Build this block if we have received packets since last build */
+    if ((rpt_types == 0 || (rpt_types & PJMEDIA_RTCP_XR_RR_TIME)) &&
+	sess->rx_last_rr != sess->rtcp_session->stat.rx.pkt)
+    {
+	pjmedia_rtcp_xr_rb_rr_time *r;
+	pjmedia_rtcp_ntp_rec ntp;
+
+	r = (pjmedia_rtcp_xr_rb_rr_time*) &sess->pkt.buf[size];
+	pj_bzero(r, sizeof(pjmedia_rtcp_xr_rb_rr_time));
+
+	/* Init block header */
+	r->header.bt = BT_RR_TIME;
+	r->header.specific = 0;
+	r->header.length = pj_htons(2);
+
+	/* Generate block contents */
+	pjmedia_rtcp_get_ntp_time(sess->rtcp_session, &ntp);
+	r->ntp_sec = pj_htonl(ntp.hi);
+	r->ntp_frac = pj_htonl(ntp.lo);
+
+	/* Finally */
+	size += sizeof(pjmedia_rtcp_xr_rb_rr_time);
+	sess->rx_last_rr = sess->rtcp_session->stat.rx.pkt;
+    }
+
+    /* DLRR Report Block */
+    /* Build this block if we have received RR NTP (rx_lrr) before */
+    if ((rpt_types == 0 || (rpt_types & PJMEDIA_RTCP_XR_DLRR)) && 
+	sess->rx_lrr)
+    {
+	pjmedia_rtcp_xr_rb_dlrr *r;
+	pjmedia_rtcp_xr_rb_dlrr_item *dlrr_item;
+	pj_timestamp ts;
+
+	r = (pjmedia_rtcp_xr_rb_dlrr*) &sess->pkt.buf[size];
+	pj_bzero(r, sizeof(pjmedia_rtcp_xr_rb_dlrr));
+
+	/* Init block header */
+	r->header.bt = BT_DLRR;
+	r->header.specific = 0;
+	r->header.length = pj_htons(sizeof(pjmedia_rtcp_xr_rb_dlrr)/4 - 1);
+
+	/* Generate block contents */
+	dlrr_item = &r->item;
+	dlrr_item->ssrc = pj_htonl(sess->rtcp_session->peer_ssrc);
+	dlrr_item->lrr = pj_htonl(sess->rx_lrr);
+
+	/* Calculate DLRR */
+	if (sess->rx_lrr != 0) {
+	    pj_get_timestamp(&ts);
+	    ts.u64 -= sess->rx_lrr_time.u64;
+	
+	    /* Convert DLRR time to 1/65536 seconds resolution */
+	    ts.u64 = (ts.u64 << 16) / sess->rtcp_session->ts_freq.u64;
+	    dlrr_item->dlrr = pj_htonl(ts.u32.lo);
+	} else {
+	    dlrr_item->dlrr = 0;
+	}
+
+	/* Finally */
+	size += sizeof(pjmedia_rtcp_xr_rb_dlrr);
+    }
+
+    /* Statistics Summary Block */
+    /* Build this block if we have received packets since last build */
+    if ((rpt_types == 0 || (rpt_types & PJMEDIA_RTCP_XR_STATS)) &&
+	sess->stat.rx.stat_sum.count > 0)
+    {
+	pjmedia_rtcp_xr_rb_stats *r;
+	pj_uint8_t specific = 0;
+
+	r = (pjmedia_rtcp_xr_rb_stats*) &sess->pkt.buf[size];
+	pj_bzero(r, sizeof(pjmedia_rtcp_xr_rb_stats));
+
+	/* Init block header */
+	specific |= sess->stat.rx.stat_sum.l ? (1 << 7) : 0;
+	specific |= sess->stat.rx.stat_sum.d ? (1 << 6) : 0;
+	specific |= sess->stat.rx.stat_sum.j ? (1 << 5) : 0;
+	specific |= (sess->stat.rx.stat_sum.t & 3) << 3;
+	r->header.bt = BT_STATS;
+	r->header.specific = specific;
+	r->header.length = pj_htons(9);
+
+	/* Generate block contents */
+	r->ssrc = pj_htonl(sess->rtcp_session->peer_ssrc);
+	r->begin_seq = pj_htons((pj_uint16_t)
+				(sess->stat.rx.stat_sum.begin_seq & 0xFFFF));
+	r->end_seq = pj_htons((pj_uint16_t)
+			      (sess->stat.rx.stat_sum.end_seq & 0xFFFF));
+	if (sess->stat.rx.stat_sum.l) {
+	    r->lost = pj_htonl(sess->stat.rx.stat_sum.lost);
+	}
+	if (sess->stat.rx.stat_sum.d) {
+	    r->dup = pj_htonl(sess->stat.rx.stat_sum.dup);
+	}
+	if (sess->stat.rx.stat_sum.j) {
+	    r->jitter_min = pj_htonl(sess->stat.rx.stat_sum.jitter.min);
+	    r->jitter_max = pj_htonl(sess->stat.rx.stat_sum.jitter.max);
+	    r->jitter_mean = 
+		pj_htonl((unsigned)sess->stat.rx.stat_sum.jitter.mean);
+	    r->jitter_dev = 
+		pj_htonl(pj_math_stat_get_stddev(&sess->stat.rx.stat_sum.jitter));
+	}
+	if (sess->stat.rx.stat_sum.t) {
+	    r->toh_min = sess->stat.rx.stat_sum.toh.min;
+	    r->toh_max = sess->stat.rx.stat_sum.toh.max;
+	    r->toh_mean = (unsigned) sess->stat.rx.stat_sum.toh.mean;
+	    r->toh_dev = pj_math_stat_get_stddev(&sess->stat.rx.stat_sum.toh);
+	}
+
+	/* Reset TX statistics summary each time built */
+	pj_bzero(&sess->stat.rx.stat_sum, sizeof(sess->stat.rx.stat_sum));
+	sess->stat.rx.stat_sum.jitter.min = (unsigned) -1;
+	sess->stat.rx.stat_sum.toh.min = (unsigned) -1;
+
+	/* Finally */
+	size += sizeof(pjmedia_rtcp_xr_rb_stats);
+	pj_gettimeofday(&sess->stat.rx.stat_sum.update);
+    }
+
+    /* Voip Metrics Block */
+    /* Build this block if we have received packets */
+    if ((rpt_types == 0 || (rpt_types & PJMEDIA_RTCP_XR_VOIP_METRICS)) &&
+	sess->rtcp_session->stat.rx.pkt)
+    {
+	pjmedia_rtcp_xr_rb_voip_mtc *r;
+	pj_uint32_t c11;
+	pj_uint32_t c13;
+	pj_uint32_t c14;
+	pj_uint32_t c22;
+	pj_uint32_t c23;
+	pj_uint32_t c31;
+	pj_uint32_t c32;
+	pj_uint32_t c33;
+	pj_uint32_t ctotal, m;
+	unsigned est_extra_delay;
+
+	r = (pjmedia_rtcp_xr_rb_voip_mtc*) &sess->pkt.buf[size];
+	pj_bzero(r, sizeof(pjmedia_rtcp_xr_rb_voip_mtc));
+
+	/* Init block header */
+	r->header.bt = BT_VOIP_METRICS;
+	r->header.specific = 0;
+	r->header.length = pj_htons(8);
+
+	/* Use temp vars for easiness. */
+	c11 = sess->voip_mtc_stat.c11;
+	c13 = sess->voip_mtc_stat.c13;
+	c14 = sess->voip_mtc_stat.c14;
+	c22 = sess->voip_mtc_stat.c22;
+	c23 = sess->voip_mtc_stat.c23;
+	c33 = sess->voip_mtc_stat.c33;
+	m = sess->ptime * sess->frames_per_packet;
+
+	/* Calculate additional transition counts. */
+	c31 = c13;
+	c32 = c23;
+	ctotal = c11 + c14 + c13 + c22 + c23 + c31 + c32 + c33;
+
+	if (ctotal) {
+	    pj_uint32_t p32, p23;
+
+	    //original version:
+	    //p32 = c32 / (c31 + c32 + c33);
+	    if (c31 + c32 + c33 == 0)
+		p32 = 0;
+	    else
+		p32 = (c32 << 16) / (c31 + c32 + c33);
+
+	    //original version:
+	    //if ((c22 + c23) < 1) {
+	    //    p23 = 1;
+	    //} else {
+	    //    p23 = 1 - c22 / (c22 + c23);
+	    //}
+	    if (c23 == 0) {
+	        p23 = 0;
+	    } else {
+	        p23 = (c23 << 16) / (c22 + c23);
+	    }
+
+	    /* Calculate loss/discard densities, scaled of 0-256 */
+	    if (c11 == 0)
+		sess->stat.rx.voip_mtc.gap_den = 0;
+	    else
+		sess->stat.rx.voip_mtc.gap_den = (pj_uint8_t)
+						 ((c14 << 8) / (c11 + c14));
+	    if (p23 == 0)
+		sess->stat.rx.voip_mtc.burst_den = 0;
+	    else
+		sess->stat.rx.voip_mtc.burst_den = (pj_uint8_t)
+						   ((p23 << 8) / (p23 + p32));
+
+	    /* Calculate (average) durations, in ms */
+	    if (c13 == 0) {
+		c13 = 1;
+		ctotal += 1;
+	    }
+	    sess->stat.rx.voip_mtc.gap_dur = (pj_uint16_t)
+					    ((c11+c14+c13) * m / c13);
+	    sess->stat.rx.voip_mtc.burst_dur = (pj_uint16_t)
+					    ((ctotal - (c11+c14+c13)) * m / c13);
+
+	    /* Callculate loss/discard rates, scaled 0-256 */
+	    sess->stat.rx.voip_mtc.loss_rate = (pj_uint8_t)
+			((sess->voip_mtc_stat.loss_count << 8) / ctotal);
+	    sess->stat.rx.voip_mtc.discard_rate = (pj_uint8_t)
+			((sess->voip_mtc_stat.discard_count << 8) / ctotal);
+	} else {
+	    /* No lost/discarded packet yet. */
+	    sess->stat.rx.voip_mtc.gap_den = 0;
+	    sess->stat.rx.voip_mtc.burst_den = 0;
+	    sess->stat.rx.voip_mtc.gap_dur = 0;
+	    sess->stat.rx.voip_mtc.burst_dur = 0;
+	    sess->stat.rx.voip_mtc.loss_rate = 0;
+	    sess->stat.rx.voip_mtc.discard_rate = 0;
+	}
+
+	/* Set round trip delay (in ms) to RTT calculated after receiving
+	 * DLRR or DLSR.
+	 */
+	if (sess->stat.rtt.last)
+	    sess->stat.rx.voip_mtc.rnd_trip_delay = (pj_uint16_t)
+				    (sess->stat.rtt.last / 1000);
+	else if (sess->rtcp_session->stat.rtt.last)
+	    sess->stat.rx.voip_mtc.rnd_trip_delay = (pj_uint16_t)
+				    (sess->rtcp_session->stat.rtt.last / 1000);
+	
+	/* End system delay = RTT/2 + current jitter buffer size + 
+	 *                    EXTRA (estimated extra delay)
+	 * EXTRA will cover additional delay introduced by other components of
+	 * audio engine, e.g: sound device, codec, AEC, PLC, WSOLA.
+	 * Since it is difficult to get the exact value of EXTRA, estimation
+	 * is taken to be totally around 30ms + sound device latency.
+	 */
+	est_extra_delay = 30;
+
+#if PJMEDIA_SOUND_IMPLEMENTATION!=PJMEDIA_SOUND_NULL_SOUND
+	est_extra_delay += PJMEDIA_SND_DEFAULT_REC_LATENCY + 
+			   PJMEDIA_SND_DEFAULT_PLAY_LATENCY;
+#endif
+
+	sess->stat.rx.voip_mtc.end_sys_delay = (pj_uint16_t)
+				 (sess->stat.rx.voip_mtc.rnd_trip_delay / 2 +
+				 sess->stat.rx.voip_mtc.jb_nom + 
+				 est_extra_delay);
+
+	/* Generate block contents */
+	r->ssrc		    = pj_htonl(sess->rtcp_session->peer_ssrc);
+	r->loss_rate	    = sess->stat.rx.voip_mtc.loss_rate;
+	r->discard_rate	    = sess->stat.rx.voip_mtc.discard_rate;
+	r->burst_den	    = sess->stat.rx.voip_mtc.burst_den;
+	r->gap_den	    = sess->stat.rx.voip_mtc.gap_den;
+	r->burst_dur	    = pj_htons(sess->stat.rx.voip_mtc.burst_dur);
+	r->gap_dur	    = pj_htons(sess->stat.rx.voip_mtc.gap_dur);
+	r->rnd_trip_delay   = pj_htons(sess->stat.rx.voip_mtc.rnd_trip_delay);
+	r->end_sys_delay    = pj_htons(sess->stat.rx.voip_mtc.end_sys_delay);
+	/* signal & noise level encoded in two's complement form */
+	r->signal_lvl	    = (pj_uint8_t) 
+			      ((sess->stat.rx.voip_mtc.signal_lvl >= 0)?
+			       sess->stat.rx.voip_mtc.signal_lvl :
+			       (sess->stat.rx.voip_mtc.signal_lvl + 256));
+	r->noise_lvl	    = (pj_uint8_t)
+			      ((sess->stat.rx.voip_mtc.noise_lvl >= 0)?
+			       sess->stat.rx.voip_mtc.noise_lvl :
+			       (sess->stat.rx.voip_mtc.noise_lvl + 256));
+	r->rerl		    = sess->stat.rx.voip_mtc.rerl;
+	r->gmin		    = sess->stat.rx.voip_mtc.gmin;
+	r->r_factor	    = sess->stat.rx.voip_mtc.r_factor;
+	r->ext_r_factor	    = sess->stat.rx.voip_mtc.ext_r_factor;
+	r->mos_lq	    = sess->stat.rx.voip_mtc.mos_lq;
+	r->mos_cq	    = sess->stat.rx.voip_mtc.mos_cq;
+	r->rx_config	    = sess->stat.rx.voip_mtc.rx_config;
+	r->jb_nom	    = pj_htons(sess->stat.rx.voip_mtc.jb_nom);
+	r->jb_max	    = pj_htons(sess->stat.rx.voip_mtc.jb_max);
+	r->jb_abs_max	    = pj_htons(sess->stat.rx.voip_mtc.jb_abs_max);
+
+	/* Finally */
+	size += sizeof(pjmedia_rtcp_xr_rb_voip_mtc);
+	pj_gettimeofday(&sess->stat.rx.voip_mtc.update);
+    }
+
+    /* Add RTCP XR header size */
+    size += sizeof(sess->pkt.common);
+
+    /* Set RTCP XR header 'length' to packet size in 32-bit unit minus one */
+    sess->pkt.common.length = pj_htons((pj_uint16_t)(size/4 - 1));
+
+    /* Set the return values */
+    *rtcp_pkt = (void*) &sess->pkt;
+    *len = size;
+}
+
+
+void pjmedia_rtcp_xr_rx_rtcp_xr( pjmedia_rtcp_xr_session *sess,
+				 const void *pkt,
+				 pj_size_t size)
+{
+    const pjmedia_rtcp_xr_pkt	      *rtcp_xr = (pjmedia_rtcp_xr_pkt*) pkt;
+    const pjmedia_rtcp_xr_rb_rr_time  *rb_rr_time = NULL;
+    const pjmedia_rtcp_xr_rb_dlrr     *rb_dlrr = NULL;
+    const pjmedia_rtcp_xr_rb_stats    *rb_stats = NULL;
+    const pjmedia_rtcp_xr_rb_voip_mtc *rb_voip_mtc = NULL;
+    const pjmedia_rtcp_xr_rb_header   *rb_hdr = (pjmedia_rtcp_xr_rb_header*) 
+						rtcp_xr->buf;
+    unsigned pkt_len, rb_len;
+
+    if (rtcp_xr->common.pt != RTCP_XR)
+	return;
+
+    pkt_len = pj_ntohs((pj_uint16_t)rtcp_xr->common.length);
+
+    if ((pkt_len + 1) > (size / 4))
+	return;
+
+    /* Parse report rpt_types */
+    while ((pj_int32_t*)rb_hdr < (pj_int32_t*)pkt + pkt_len)
+    {	
+	rb_len = pj_ntohs((pj_uint16_t)rb_hdr->length);
+
+	/* Just skip any block with length == 0 (no report content) */
+	if (rb_len) {
+	    switch (rb_hdr->bt) {
+		case BT_RR_TIME:
+		    rb_rr_time = (pjmedia_rtcp_xr_rb_rr_time*) rb_hdr;
+		    break;
+		case BT_DLRR:
+		    rb_dlrr = (pjmedia_rtcp_xr_rb_dlrr*) rb_hdr;
+		    break;
+		case BT_STATS:
+		    rb_stats = (pjmedia_rtcp_xr_rb_stats*) rb_hdr;
+		    break;
+		case BT_VOIP_METRICS:
+		    rb_voip_mtc = (pjmedia_rtcp_xr_rb_voip_mtc*) rb_hdr;
+		    break;
+		default:
+		    break;
+	    }
+	}
+	rb_hdr = (pjmedia_rtcp_xr_rb_header*)
+		 ((pj_int32_t*)rb_hdr + rb_len + 1);
+    }
+
+    /* Receiving RR Time */
+    if (rb_rr_time) {
+	/* Save LRR from NTP timestamp of the RR time block report */
+	sess->rx_lrr = ((pj_ntohl(rb_rr_time->ntp_sec) & 0x0000FFFF) << 16) | 
+		       ((pj_ntohl(rb_rr_time->ntp_frac) >> 16) & 0xFFFF);
+
+	/* Calculate RR arrival time for DLRR */
+	pj_get_timestamp(&sess->rx_lrr_time);
+
+	TRACE_((sess->name, "Rx RTCP SR: ntp_ts=%p", sess->rx_lrr,
+	       (pj_uint32_t)(sess->rx_lrr_time.u64*65536/
+			     sess->rtcp_session->ts_freq.u64)));
+    }
+
+    /* Receiving DLRR */
+    if (rb_dlrr) {
+	pj_uint32_t lrr, now, dlrr;
+	pj_uint64_t eedelay;
+	pjmedia_rtcp_ntp_rec ntp;
+
+	/* LRR is the middle 32bit of NTP. It has 1/65536 second 
+	 * resolution 
+	 */
+	lrr = pj_ntohl(rb_dlrr->item.lrr);
+
+	/* DLRR is delay since LRR, also in 1/65536 resolution */
+	dlrr = pj_ntohl(rb_dlrr->item.dlrr);
+
+	/* Get current time, and convert to 1/65536 resolution */
+	pjmedia_rtcp_get_ntp_time(sess->rtcp_session, &ntp);
+	now = ((ntp.hi & 0xFFFF) << 16) + (ntp.lo >> 16);
+
+	/* End-to-end delay is (now-lrr-dlrr) */
+	eedelay = now - lrr - dlrr;
+
+	/* Convert end to end delay to usec (keeping the calculation in
+         * 64bit space)::
+	 *   sess->ee_delay = (eedelay * 1000) / 65536;
+	 */
+	if (eedelay < 4294) {
+	    eedelay = (eedelay * 1000000) >> 16;
+	} else {
+	    eedelay = (eedelay * 1000) >> 16;
+	    eedelay *= 1000;
+	}
+
+	TRACE_((sess->name, "Rx RTCP XR DLRR: lrr=%p, dlrr=%p (%d:%03dms), "
+			   "now=%p, rtt=%p",
+		lrr, dlrr, dlrr/65536, (dlrr%65536)*1000/65536,
+		now, (pj_uint32_t)eedelay));
+	
+	/* Only save calculation if "now" is greater than lrr, or
+	 * otherwise rtt will be invalid 
+	 */
+	if (now-dlrr >= lrr) {
+	    unsigned rtt = (pj_uint32_t)eedelay;
+	    
+	    /* Check that eedelay value really makes sense. 
+	     * We allow up to 30 seconds RTT!
+	     */
+	    if (eedelay <= 30 * 1000 * 1000UL) {
+		/* "Normalize" rtt value that is exceptionally high.
+		 * For such values, "normalize" the rtt to be three times
+		 * the average value.
+		 */
+		if (rtt>((unsigned)sess->stat.rtt.mean*3) && sess->stat.rtt.n!=0)
+		{
+		    unsigned orig_rtt = rtt;
+		    rtt = (unsigned)sess->stat.rtt.mean*3;
+		    PJ_LOG(5,(sess->name, 
+			      "RTT value %d usec is normalized to %d usec",
+			      orig_rtt, rtt));
+		}
+    	
+		TRACE_((sess->name, "RTCP RTT is set to %d usec", rtt));
+		pj_math_stat_update(&sess->stat.rtt, rtt);
+	    }
+	} else {
+	    PJ_LOG(5, (sess->name, "Internal RTCP NTP clock skew detected: "
+				   "lrr=%p, now=%p, dlrr=%p (%d:%03dms), "
+				   "diff=%d",
+				   lrr, now, dlrr, dlrr/65536,
+				   (dlrr%65536)*1000/65536,
+				   dlrr-(now-lrr)));
+	}
+    }
+
+    /* Receiving Statistics Summary */
+    if (rb_stats) {
+	pj_uint8_t flags = rb_stats->header.specific;
+
+	pj_bzero(&sess->stat.tx.stat_sum, sizeof(sess->stat.tx.stat_sum));
+
+	/* Range of packets sequence reported in this blocks */
+	sess->stat.tx.stat_sum.begin_seq = pj_ntohs(rb_stats->begin_seq);
+	sess->stat.tx.stat_sum.end_seq   = pj_ntohs(rb_stats->end_seq);
+
+	/* Get flags of valid fields */
+	sess->stat.tx.stat_sum.l = (flags & (1 << 7)) != 0;
+	sess->stat.tx.stat_sum.d = (flags & (1 << 6)) != 0;
+	sess->stat.tx.stat_sum.j = (flags & (1 << 5)) != 0;
+	sess->stat.tx.stat_sum.t = (flags & (3 << 3)) != 0;
+
+	/* Fetch the reports info */
+	if (sess->stat.tx.stat_sum.l) {
+	    sess->stat.tx.stat_sum.lost = pj_ntohl(rb_stats->lost);
+	}
+
+	if (sess->stat.tx.stat_sum.d) {
+	    sess->stat.tx.stat_sum.dup = pj_ntohl(rb_stats->dup);
+	}
+
+	if (sess->stat.tx.stat_sum.j) {
+	    sess->stat.tx.stat_sum.jitter.min = pj_ntohl(rb_stats->jitter_min);
+	    sess->stat.tx.stat_sum.jitter.max = pj_ntohl(rb_stats->jitter_max);
+	    sess->stat.tx.stat_sum.jitter.mean= pj_ntohl(rb_stats->jitter_mean);
+	    pj_math_stat_set_stddev(&sess->stat.tx.stat_sum.jitter, 
+				    pj_ntohl(rb_stats->jitter_dev));
+	}
+
+	if (sess->stat.tx.stat_sum.t) {
+	    sess->stat.tx.stat_sum.toh.min = rb_stats->toh_min;
+	    sess->stat.tx.stat_sum.toh.max = rb_stats->toh_max;
+	    sess->stat.tx.stat_sum.toh.mean= rb_stats->toh_mean;
+	    pj_math_stat_set_stddev(&sess->stat.tx.stat_sum.toh, 
+				    pj_ntohl(rb_stats->toh_dev));
+	}
+
+	pj_gettimeofday(&sess->stat.tx.stat_sum.update);
+    }
+
+    /* Receiving VoIP Metrics */
+    if (rb_voip_mtc) {
+	sess->stat.tx.voip_mtc.loss_rate = rb_voip_mtc->loss_rate;
+	sess->stat.tx.voip_mtc.discard_rate = rb_voip_mtc->discard_rate;
+	sess->stat.tx.voip_mtc.burst_den = rb_voip_mtc->burst_den;
+	sess->stat.tx.voip_mtc.gap_den = rb_voip_mtc->gap_den;
+	sess->stat.tx.voip_mtc.burst_dur = pj_ntohs(rb_voip_mtc->burst_dur);
+	sess->stat.tx.voip_mtc.gap_dur = pj_ntohs(rb_voip_mtc->gap_dur);
+	sess->stat.tx.voip_mtc.rnd_trip_delay = 
+					pj_ntohs(rb_voip_mtc->rnd_trip_delay);
+	sess->stat.tx.voip_mtc.end_sys_delay = 
+					pj_ntohs(rb_voip_mtc->end_sys_delay);
+	/* signal & noise level encoded in two's complement form */
+	sess->stat.tx.voip_mtc.signal_lvl = (pj_int8_t)
+				    ((rb_voip_mtc->signal_lvl > 127)?
+				     ((int)rb_voip_mtc->signal_lvl - 256) : 
+				     rb_voip_mtc->signal_lvl);
+	sess->stat.tx.voip_mtc.noise_lvl  = (pj_int8_t)
+				    ((rb_voip_mtc->noise_lvl > 127)?
+				     ((int)rb_voip_mtc->noise_lvl - 256) : 
+				     rb_voip_mtc->noise_lvl);
+	sess->stat.tx.voip_mtc.rerl = rb_voip_mtc->rerl;
+	sess->stat.tx.voip_mtc.gmin = rb_voip_mtc->gmin;
+	sess->stat.tx.voip_mtc.r_factor = rb_voip_mtc->r_factor;
+	sess->stat.tx.voip_mtc.ext_r_factor = rb_voip_mtc->ext_r_factor;
+	sess->stat.tx.voip_mtc.mos_lq = rb_voip_mtc->mos_lq;
+	sess->stat.tx.voip_mtc.mos_cq = rb_voip_mtc->mos_cq;
+	sess->stat.tx.voip_mtc.rx_config = rb_voip_mtc->rx_config;
+	sess->stat.tx.voip_mtc.jb_nom = pj_ntohs(rb_voip_mtc->jb_nom);
+	sess->stat.tx.voip_mtc.jb_max = pj_ntohs(rb_voip_mtc->jb_max);
+	sess->stat.tx.voip_mtc.jb_abs_max = pj_ntohs(rb_voip_mtc->jb_abs_max);
+
+	pj_gettimeofday(&sess->stat.tx.voip_mtc.update);
+    }
+}
+
+/* Place seq into a 32-bit sequence number space based upon a
+ * heuristic for its most likely location.
+ */
+static pj_uint32_t extend_seq(pjmedia_rtcp_xr_session *sess,
+			      const pj_uint16_t seq)
+{
+
+    pj_uint32_t extended_seq, seq_a, seq_b, diff_a, diff_b;
+    if(sess->uninitialized_src_ref_seq) {
+	/* This is the first sequence number received.  Place
+	 * it in the middle of the extended sequence number
+	 * space.
+	 */
+	sess->src_ref_seq = seq | 0x80000000u;
+	sess->uninitialized_src_ref_seq = PJ_FALSE;
+	extended_seq = sess->src_ref_seq;
+    } else {
+	/* Prior sequence numbers have been received.
+	 * Propose two candidates for the extended sequence
+	 * number: seq_a is without wraparound, seq_b with
+	 * wraparound.
+	 */
+	seq_a = seq | (sess->src_ref_seq & 0xFFFF0000u);
+	if(sess->src_ref_seq < seq_a) {
+	    seq_b  = seq_a - 0x00010000u;
+	    diff_a = seq_a - sess->src_ref_seq;
+	    diff_b = sess->src_ref_seq - seq_b;
+	} else {
+	    seq_b  = seq_a + 0x00010000u;
+	    diff_a = sess->src_ref_seq - seq_a;
+	    diff_b = seq_b - sess->src_ref_seq;
+	}
+
+	/* Choose the closer candidate.  If they are equally
+	 * close, the choice is somewhat arbitrary: we choose
+	 * the candidate for which no rollover is necessary.
+	 */
+	if(diff_a < diff_b) {
+	    extended_seq = seq_a;
+	} else {
+	    extended_seq = seq_b;
+	}
+
+	/* Set the reference sequence number to be this most
+	 * recently-received sequence number.
+	 */
+	sess->src_ref_seq = extended_seq;
+    }
+
+    /* Return our best guess for a 32-bit sequence number that
+     * corresponds to the 16-bit number we were given.
+     */
+    return extended_seq;
+}
+
+void pjmedia_rtcp_xr_rx_rtp( pjmedia_rtcp_xr_session *sess,
+			     unsigned seq, 
+			     int lost,
+			     int dup,
+			     int discarded,
+			     int jitter,
+			     int toh, pj_bool_t toh_ipv4)
+{
+    pj_uint32_t ext_seq;
+
+    /* Get 32 bit version of sequence */
+    ext_seq = extend_seq(sess, (pj_uint16_t)seq);
+
+    /* Update statistics summary */
+    sess->stat.rx.stat_sum.count++;
+
+    if (sess->stat.rx.stat_sum.begin_seq == 0 || 
+	sess->stat.rx.stat_sum.begin_seq > ext_seq)
+    {
+	sess->stat.rx.stat_sum.begin_seq = ext_seq;
+    }
+
+    if (sess->stat.rx.stat_sum.end_seq == 0 || 
+	sess->stat.rx.stat_sum.end_seq < ext_seq)
+    {
+	sess->stat.rx.stat_sum.end_seq = ext_seq;
+    }
+
+    if (lost >= 0) {
+	sess->stat.rx.stat_sum.l = PJ_TRUE;
+	if (lost > 0)
+	    sess->stat.rx.stat_sum.lost++;
+    }
+
+    if (dup >= 0) {
+	sess->stat.rx.stat_sum.d = PJ_TRUE;
+	if (dup > 0)
+	    sess->stat.rx.stat_sum.dup++;
+    }
+
+    if (jitter >= 0) {
+	sess->stat.rx.stat_sum.j = PJ_TRUE;
+	pj_math_stat_update(&sess->stat.rx.stat_sum.jitter, jitter);
+    }
+
+    if (toh >= 0) {
+	sess->stat.rx.stat_sum.t = toh_ipv4? 1 : 2;
+	pj_math_stat_update(&sess->stat.rx.stat_sum.toh, toh);
+    }
+
+    /* Update burst metrics.
+     * There are two terms introduced in the RFC 3611: gap & burst.
+     * Gap represents good stream condition, lost+discard rate <= 1/Gmin.
+     * Burst represents the opposite, lost+discard rate > 1/Gmin.
+     */
+    if (lost >= 0 && discarded >= 0) {
+	if(lost > 0) {
+	    sess->voip_mtc_stat.loss_count++;
+	}
+	if(discarded > 0) {
+	    sess->voip_mtc_stat.discard_count++;
+	}
+	if(!lost && !discarded) {
+	    /* Number of good packets since last lost/discarded */
+	    sess->voip_mtc_stat.pkt++;
+	}
+	else {
+	    if(sess->voip_mtc_stat.pkt >= sess->stat.rx.voip_mtc.gmin) {
+		/* Gap condition */
+		if(sess->voip_mtc_stat.lost == 1) {
+		    /* Gap -> Gap */
+		    sess->voip_mtc_stat.c14++;
+		}
+		else {
+		    /* Burst -> Gap */
+		    sess->voip_mtc_stat.c13++;
+		}
+		sess->voip_mtc_stat.lost = 1;
+		sess->voip_mtc_stat.c11 += sess->voip_mtc_stat.pkt;
+	    }
+	    else {
+		/* Burst condition */
+		sess->voip_mtc_stat.lost++;
+		if(sess->voip_mtc_stat.pkt == 0) {
+		    /* Consecutive losts */
+		    sess->voip_mtc_stat.c33++;
+		}
+		else {
+		    /* Any good packets, but still bursting */
+		    sess->voip_mtc_stat.c23++;
+		    sess->voip_mtc_stat.c22 += (sess->voip_mtc_stat.pkt - 1);
+		}
+	    }
+
+	    sess->voip_mtc_stat.pkt = 0;
+	}
+    }
+}
+
+void pjmedia_rtcp_xr_tx_rtp( pjmedia_rtcp_xr_session *session, 
+			     unsigned ptsize )
+{
+    PJ_UNUSED_ARG(session);
+    PJ_UNUSED_ARG(ptsize);
+}
+
+PJ_DEF(pj_status_t) pjmedia_rtcp_xr_update_info( 
+					 pjmedia_rtcp_xr_session *sess,
+					 unsigned info,
+					 pj_int32_t val)
+{
+    int v = val;
+
+    switch(info) {
+	case PJMEDIA_RTCP_XR_INFO_SIGNAL_LVL:
+	    sess->stat.rx.voip_mtc.signal_lvl = (pj_int8_t) v;
+	    break;
+
+	case PJMEDIA_RTCP_XR_INFO_NOISE_LVL:
+	    sess->stat.rx.voip_mtc.noise_lvl = (pj_int8_t) v;
+	    break;
+
+	case PJMEDIA_RTCP_XR_INFO_RERL:
+	    sess->stat.rx.voip_mtc.rerl = (pj_uint8_t) v;
+	    break;
+
+	case PJMEDIA_RTCP_XR_INFO_R_FACTOR:
+	    sess->stat.rx.voip_mtc.ext_r_factor = (pj_uint8_t) v;
+	    break;
+
+	case PJMEDIA_RTCP_XR_INFO_MOS_LQ:
+	    sess->stat.rx.voip_mtc.mos_lq = (pj_uint8_t) v;
+	    break;
+
+	case PJMEDIA_RTCP_XR_INFO_MOS_CQ:
+	    sess->stat.rx.voip_mtc.mos_cq = (pj_uint8_t) v;
+	    break;
+
+	case PJMEDIA_RTCP_XR_INFO_CONF_PLC:
+	    if (v >= 0 && v <= 3) {
+		sess->stat.rx.voip_mtc.rx_config &= 0x3F;
+		sess->stat.rx.voip_mtc.rx_config |= (pj_uint8_t) (v << 6);
+	    }
+	    break;
+
+	case PJMEDIA_RTCP_XR_INFO_CONF_JBA:
+	    if (v >= 0 && v <= 3) {
+		sess->stat.rx.voip_mtc.rx_config &= 0xCF;
+		sess->stat.rx.voip_mtc.rx_config |= (pj_uint8_t) (v << 4);
+	    }
+	    break;
+
+	case PJMEDIA_RTCP_XR_INFO_CONF_JBR:
+	    if (v >= 0 && v <= 15) {
+		sess->stat.rx.voip_mtc.rx_config &= 0xF0;
+		sess->stat.rx.voip_mtc.rx_config |= (pj_uint8_t) v;
+	    }
+	    break;
+
+	case PJMEDIA_RTCP_XR_INFO_JB_NOM:
+	    sess->stat.rx.voip_mtc.jb_nom = (pj_uint16_t) v;
+	    break;
+
+	case PJMEDIA_RTCP_XR_INFO_JB_MAX:
+	    sess->stat.rx.voip_mtc.jb_max = (pj_uint16_t) v;
+	    break;
+
+	case PJMEDIA_RTCP_XR_INFO_JB_ABS_MAX:
+	    sess->stat.rx.voip_mtc.jb_abs_max = (pj_uint16_t) v;
+	    break;
+
+	default:
+	    return PJ_EINVAL;
+    }
+
+    return PJ_SUCCESS;
+}
+
+#endif