* #27232: jni: added pjproject checkout as regular git content

We will remove it once the next release of pjsip (with Android support)
comes out and is merged into SFLphone.
diff --git a/jni/pjproject-android/.svn/pristine/25/2508212b8e773aaeedfe83aa9d5d8764b20ad520.svn-base b/jni/pjproject-android/.svn/pristine/25/2508212b8e773aaeedfe83aa9d5d8764b20ad520.svn-base
new file mode 100644
index 0000000..4f574f6
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/25/2508212b8e773aaeedfe83aa9d5d8764b20ad520.svn-base
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB" version="8.00">
+	<data>
+		<int key="IBDocument.SystemTarget">1536</int>
+		<string key="IBDocument.SystemVersion">12A206j</string>
+		<string key="IBDocument.InterfaceBuilderVersion">2519</string>
+		<string key="IBDocument.AppKitVersion">1172.1</string>
+		<string key="IBDocument.HIToolboxVersion">613.00</string>
+		<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+			<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+			<string key="NS.object.0">1856</string>
+		</object>
+		<array key="IBDocument.IntegratedClassDependencies">
+			<string>IBProxyObject</string>
+			<string>IBUIView</string>
+		</array>
+		<array key="IBDocument.PluginDependencies">
+			<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+		</array>
+		<object class="NSMutableDictionary" key="IBDocument.Metadata">
+			<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
+			<integer value="1" key="NS.object.0"/>
+		</object>
+		<array class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+			<object class="IBProxyObject" id="841351856">
+				<string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
+				<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+			</object>
+			<object class="IBProxyObject" id="606714003">
+				<string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
+				<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+			</object>
+			<object class="IBUIView" id="766721923">
+				<reference key="NSNextResponder"/>
+				<int key="NSvFlags">274</int>
+				<string key="NSFrame">{{0, 20}, {768, 1004}}</string>
+				<reference key="NSSuperview"/>
+				<reference key="NSWindow"/>
+				<object class="NSColor" key="IBUIBackgroundColor">
+					<int key="NSColorSpace">3</int>
+					<bytes key="NSWhite">MQA</bytes>
+					<object class="NSColorSpace" key="NSCustomColorSpace">
+						<int key="NSID">2</int>
+					</object>
+				</object>
+				<object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics">
+					<int key="IBUIStatusBarStyle">2</int>
+				</object>
+				<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+			</object>
+		</array>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<array class="NSMutableArray" key="connectionRecords">
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchOutletConnection" key="connection">
+						<string key="label">view</string>
+						<reference key="source" ref="841351856"/>
+						<reference key="destination" ref="766721923"/>
+					</object>
+					<int key="connectionID">3</int>
+				</object>
+			</array>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<array key="orderedObjects">
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<array key="object" id="0"/>
+						<reference key="children" ref="1000"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="841351856"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">File's Owner</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="606714003"/>
+						<reference key="parent" ref="0"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">2</int>
+						<reference key="object" ref="766721923"/>
+						<reference key="parent" ref="0"/>
+					</object>
+				</array>
+			</object>
+			<dictionary class="NSMutableDictionary" key="flattenedProperties">
+				<string key="-1.CustomClassName">ipjsuaViewController</string>
+				<string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="-2.CustomClassName">UIResponder</string>
+				<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+			</dictionary>
+			<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
+			<nil key="activeLocalization"/>
+			<dictionary class="NSMutableDictionary" key="localizations"/>
+			<nil key="sourceID"/>
+			<int key="maxID">3</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<array class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<object class="IBPartialClassDescription">
+					<string key="className">ipjsuaViewController</string>
+					<string key="superclassName">UIViewController</string>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">./Classes/ipjsuaViewController.h</string>
+					</object>
+				</object>
+			</array>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<string key="IBDocument.TargetRuntimeIdentifier">IBIPadFramework</string>
+		<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+		<bool key="IBDocument.UseAutolayout">YES</bool>
+		<string key="IBCocoaTouchPluginVersion">1856</string>
+	</data>
+</archive>
diff --git a/jni/pjproject-android/.svn/pristine/25/25388d2c4261eb57957410d6f5dbc729534b727f.svn-base b/jni/pjproject-android/.svn/pristine/25/25388d2c4261eb57957410d6f5dbc729534b727f.svn-base
new file mode 100644
index 0000000..9f37c32
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/25/25388d2c4261eb57957410d6f5dbc729534b727f.svn-base
@@ -0,0 +1,791 @@
+/* $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 __PJSIP_SIP_DIALOG_H__
+#define __PJSIP_SIP_DIALOG_H__
+
+
+/**
+ * @file sip_dialog.h
+ * @brief SIP Dialog abstraction
+ */
+
+#include <pjsip/sip_msg.h>
+#include <pjsip/sip_auth.h>
+#include <pjsip/sip_errno.h>
+#include <pjsip/sip_transport.h>
+#include <pjsip/sip_util.h>
+#include <pj/sock.h>
+#include <pj/assert.h>
+
+
+/**
+ * @defgroup PJSIP_DIALOG Base Dialog
+ * @ingroup PJSIP_UA
+ * @brief The base dialog framework to support dialog usages.
+ * @{
+ *
+ * The base dialog framework provides management for base dialog
+ * properties such as <b>From</b> header, <b>To</b> header, <b>CSeq</b>
+ * sequencing, <b>Call-ID</b> header, <b>Contact</b> header management, 
+ * dialog <b>route-set</b> management, and common <b>authentication</b>. 
+ * This basic dialog functionality will be shared by all <b>dialog
+ * usages</b> of a particular dialog.
+ *
+ * More detailed information is explained in
+ * <A HREF="/docs.htm">PJSIP Developer's Guide</A>
+ * PDF document, and readers are encouraged to read the document to
+ * get the concept behind dialog, dialog usages, and INVITE sessions.
+ *
+ * Application MUST initialize the user agent layer module by calling
+ * #pjsip_ua_init_module() before using any of the dialog API, and link
+ * the application with with <b>pjsip-core</b> library.
+ */
+
+PJ_BEGIN_DECL
+
+
+/**
+ * This structure is used to describe dialog's participants, which in this
+ * case is local party (i.e. us) and remote party.
+ */
+typedef struct pjsip_dlg_party
+{
+    pjsip_fromto_hdr	*info;	    /**< From/To header, inc tag.	*/
+    pj_str_t		 info_str;  /**< String rep of info header.	*/
+    pj_uint32_t		 tag_hval;  /**< Hashed value of the tag.	*/
+    pjsip_contact_hdr	*contact;   /**< Contact header.		*/
+    pj_int32_t		 first_cseq;/**< First CSeq seen.		*/
+    pj_int32_t		 cseq;	    /**< Next sequence number.		*/
+} pjsip_dlg_party;
+
+
+/**
+ * Dialog state.
+ */
+typedef enum pjsip_dialog_state
+{
+    /** Dialog is not established. */
+    PJSIP_DIALOG_STATE_NULL,
+
+    /** Dialog has been established (probably early) */
+    PJSIP_DIALOG_STATE_ESTABLISHED
+} pjsip_dialog_state;
+
+
+/**
+ * Dialog capability status.
+ */
+typedef enum pjsip_dialog_cap_status
+{
+    /** Capability is unsupported. */
+    PJSIP_DIALOG_CAP_UNSUPPORTED    = 0,
+
+    /** Capability is supported */
+    PJSIP_DIALOG_CAP_SUPPORTED	    = 1,
+
+    /** 
+     *  Unknown capability status. This is usually because we lack the 
+     *  capability info which is retrieved from capability header specified
+     *  in the dialog messages.
+     */
+    PJSIP_DIALOG_CAP_UNKNOWN	    = 2
+} pjsip_dialog_cap_status;
+
+
+/**
+ * This structure describes the dialog structure. Application MUST NOT
+ * try to SET the values here directly, but instead it MUST use the
+ * appropriate dialog API. The dialog declaration only needs to be made 
+ * visible because other PJSIP modules need to see it (e.g. INVITE session,
+ * the event framework, etc.).
+ *
+ * Application MAY READ the dialog contents directly after it acquires
+ * dialog lock.
+ *
+ * To acquire dialog lock, use #pjsip_dlg_inc_lock(), and to release it,
+ * use #pjsip_dlg_dec_lock(). DO NOT USE pj_mutex_lock()/pj_mutex_unlock()
+ * on the dialog's mutex directly, because this will not protect against
+ * dialog being destroyed.
+ */
+struct pjsip_dialog
+{
+    /** The dialog set list. */
+    PJ_DECL_LIST_MEMBER(pjsip_dialog);
+
+    /* Dialog's system properties. */
+    char		obj_name[PJ_MAX_OBJ_NAME];  /**< Standard id.	    */
+    pj_pool_t	       *pool;	    /**< Dialog's pool.			    */
+    pj_mutex_t	       *mutex_;	    /**< Dialog's mutex. Do not call!!
+					 Use pjsip_dlg_inc_lock() instead!  */
+    pjsip_user_agent   *ua;	    /**< User agent instance.		    */
+    pjsip_endpoint     *endpt;	    /**< Endpoint instance.		    */
+
+    /** The dialog set which this dialog belongs (opaque type). */
+    void	       *dlg_set;
+
+    /* Dialog's session properties. */
+    pjsip_dialog_state	state;	    /**< Dialog state.			    */
+    pjsip_uri	       *target;	    /**< Current target.		    */
+    pjsip_target_set	target_set; /**< Target set, for UAC only.	    */
+    pjsip_hdr	        inv_hdr;    /**< Headers from hparam in dest URL    */
+    pjsip_dlg_party     local;	    /**< Local party info.		    */
+    pjsip_dlg_party     remote;	    /**< Remote party info.		    */
+    pjsip_hdr		rem_cap_hdr;/**< List of remote capability header.  */
+    pjsip_role_e	role;	    /**< Initial role.			    */
+    pj_bool_t		uac_has_2xx;/**< UAC has received 2xx response?	    */
+    pj_bool_t		secure;	    /**< Use secure transport?		    */
+    pj_bool_t		add_allow;  /**< Add Allow header in requests?	    */
+    pjsip_cid_hdr      *call_id;    /**< Call-ID header.		    */
+    pjsip_route_hdr	route_set;  /**< Route set.			    */
+    pj_bool_t		route_set_frozen; /**< Route set has been set.	    */
+    pjsip_auth_clt_sess	auth_sess;  /**< Client authentication session.	    */
+
+    /** Session counter. */
+    int			sess_count; /**< Number of sessions.		    */
+
+    /** Transaction counter. */
+    int			tsx_count;  /**< Number of pending transactions.    */
+
+    /** Transport selector. */
+    pjsip_tpselector	tp_sel;
+
+    /* Dialog usages. */
+    unsigned		usage_cnt;  /**< Number of registered usages.	    */
+    pjsip_module       *usage[PJSIP_MAX_MODULE]; /**< Array of usages, 
+					 priority sorted		    */
+
+    /** Module specific data. */
+    void	       *mod_data[PJSIP_MAX_MODULE]; /**< Module data.	    */
+
+    /**
+     * If via_addr is set, it will be used as the "sent-by" field of the
+     * Via header for outgoing requests as long as the request uses via_tp
+     * transport. Normally application should not use or access these fields.
+     */
+    pjsip_host_port     via_addr;   /**< Via address.	                    */
+    const void         *via_tp;     /**< Via transport.	                    */
+};
+
+
+/**
+ * This utility function returns PJ_TRUE if the specified method is a
+ * dialog creating request. This method property is used to determine
+ * whether Contact header should be included in outgoing request.
+ *
+ * @param m		The SIP method.
+ *
+ * @return		PJ_TRUE if the method creates a dialog.
+ */
+PJ_DECL(pj_bool_t) pjsip_method_creates_dialog(const pjsip_method *m);
+
+/**
+ * Create a new dialog and return the instance in p_dlg parameter. 
+ * After creating  the dialog, application can add modules as dialog usages
+ * by calling  #pjsip_dlg_add_usage(). 
+ *
+ * If the request has To tag parameter, dialog's local tag will be initialized 
+ * from this value. Otherwise a globally unique id generator will be invoked to
+ * create dialog's local tag.
+ *
+ * This function also initializes the dialog's route set based on the 
+ * Record-Route headers in the request, if present.
+ *
+ * Note that initially, the session count in the dialog will be initialized 
+ * to zero.
+ *
+ * @param ua		    The user agent module instance.
+ * @param local_uri	    Dialog local URI (i.e. From header).
+ * @param local_contact	    Optional dialog local Contact to be put as Contact
+ *			    header value, hence the format must follow
+ *			    RFC 3261 Section 20.10:
+ *			    When the header field value contains a display 
+ *			    name, the URI including all URI parameters is 
+ *			    enclosed in "<" and ">".  If no "<" and ">" are 
+ *			    present, all parameters after the URI are header
+ *			    parameters, not URI parameters.  The display name 
+ *			    can be tokens, or a quoted string, if a larger 
+ *			    character set is desired.
+ *			    If this argument is NULL, the Contact will be taken
+ *			    from the local URI.
+ * @param remote_uri	    Dialog remote URI (i.e. To header).
+ * @param target	    Optional initial remote target. If this argument
+ *			    is NULL, the initial target will be set to
+ *			    remote URI.
+ * @param p_dlg		    Pointer to receive the dialog.
+ *
+ * @return		    PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_create_uac( pjsip_user_agent *ua,
+					   const pj_str_t *local_uri,
+					   const pj_str_t *local_contact,
+					   const pj_str_t *remote_uri,
+					   const pj_str_t *target,
+					   pjsip_dialog **p_dlg);
+
+
+/**
+ * Initialize UAS dialog from the information found in the incoming request 
+ * that creates a dialog (such as INVITE, REFER, or SUBSCRIBE), and set the 
+ * local Contact to contact. If contact is not specified, the local contact 
+ * is initialized from the URI in the To header in the request. 
+ *
+ * This function will also create UAS transaction for the incoming request,
+ * and associate the transaction to the rdata. Application can query the
+ * transaction used to handle this request by calling #pjsip_rdata_get_tsx()
+ * after this function returns.
+ *
+ * Note that initially, the session count in the dialog will be initialized 
+ * to zero.
+ *
+ *
+ * @param ua		    The user agent module instance.
+ * @param rdata		    The incoming request that creates the dialog,
+ *			    such as INVITE, SUBSCRIBE, or REFER.
+ * @param contact	    Optional dialog local Contact to be put as Contact
+ *			    header value, hence the format must follow
+ *			    RFC 3261 Section 20.10:
+ *			    When the header field value contains a display 
+ *			    name, the URI including all URI parameters is 
+ *			    enclosed in "<" and ">".  If no "<" and ">" are 
+ *			    present, all parameters after the URI are header
+ *			    parameters, not URI parameters.  The display name 
+ *			    can be tokens, or a quoted string, if a larger 
+ *			    character set is desired.
+ *			    If this argument is NULL, the local contact will be
+ *			    initialized from the value of To header in the
+ *			    request.
+ * @param p_dlg		    Pointer to receive the dialog.
+ *
+ * @return		    PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_create_uas(  pjsip_user_agent *ua,
+					    pjsip_rx_data *rdata,
+					    const pj_str_t *contact,
+					    pjsip_dialog **p_dlg);
+
+
+/**
+ * Lock/bind dialog to a specific transport/listener. This is optional,
+ * as normally transport will be selected automatically based on the 
+ * destination of messages upon resolver completion. When the dialog is 
+ * explicitly bound to the specific transport/listener, all transactions
+ * originated by this dialog will use the specified transport/listener
+ * when sending outgoing requests.
+ *
+ * Note that this doesn't affect the Contact header generated by this
+ * dialog. Application must manually update the Contact header if
+ * necessary, to adjust the address according to the transport being
+ * selected.
+ *
+ * @param dlg	    The dialog instance.
+ * @param sel	    Transport selector containing the specification of
+ *		    transport or listener to be used by this dialog
+ *		    to send requests.
+ *
+ * @return	    PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_set_transport(pjsip_dialog *dlg,
+					     const pjsip_tpselector *sel);
+
+
+/**
+ * Set the "sent-by" field of the Via header for outgoing requests.
+ *
+ * @param dlg	    The dialog instance.
+ * @param via_addr  Set via_addr to use for the Via header or NULL to use
+ *                  the transport's published name.
+ * @param via_tp    via_addr will only be used if we are using via_tp
+ *                  transport.
+ *
+ * @return	    PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_set_via_sent_by(pjsip_dialog *dlg,
+				               pjsip_host_port *via_addr,
+                                               pjsip_transport *via_tp);
+
+
+/**
+ * Create a new (forked) dialog on receipt on forked response in rdata. 
+ * The new dialog will be created from original_dlg, except that it will have
+ * new remote tag as copied from the To header in the response. Upon return, 
+ * the new_dlg will have been registered to the user agent. Applications just 
+ * need to add modules as dialog's usages.
+ *
+ * Note that initially, the session count in the dialog will be initialized 
+ * to zero.
+ *
+ * @param original_dlg	    The original UAC dialog.
+ * @param rdata		    The incoming forked response message.
+ * @param new_dlg	    Pointer to receive the new dialog.
+ *
+ * @return		    PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_fork(const pjsip_dialog *original_dlg,
+				    const pjsip_rx_data *rdata,
+				    pjsip_dialog **new_dlg );
+
+/**
+ * Forcefully terminate the dialog. Application can only call this function
+ * when there is no session associated to the dialog. If there are sessions
+ * that use this dialog, this function will refuse to terminate the dialog.
+ * For this case, application MUST call the appropriate termination function 
+ * for each dialog session (e.g. #pjsip_inv_terminate() to terminate INVITE
+ * session).
+ *
+ * @param dlg		    The dialog.
+ *
+ * @return		    PJ_SUCCESS if dialog has been terminated.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_terminate( pjsip_dialog *dlg );
+
+
+/**
+ * Set dialog's initial route set to route_set list. This can only be called
+ * for UAC dialog, before any request is sent. After dialog has been 
+ * established, the route set can not be changed.
+ *
+ * For UAS dialog,the route set will be initialized in pjsip_dlg_create_uas()
+ * from the Record-Route headers in the incoming request.
+ *
+ * The route_set argument is standard list of Route headers (i.e. with 
+ * sentinel).
+ *
+ * @param dlg		    The UAC dialog.
+ * @param route_set	    List of Route header.
+ *
+ * @return		    PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_set_route_set( pjsip_dialog *dlg,
+					      const pjsip_route_hdr *route_set );
+
+/**
+ * Increment the number of sessions in the dialog. Note that initially 
+ * (after created) the dialog has the session counter set to zero.
+ *
+ * @param dlg		    The dialog.
+ * @param mod		    The module that increments the session counter.
+ *
+ * @return		    PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_inc_session( pjsip_dialog *dlg,
+					    pjsip_module *mod);
+
+
+/**
+ * Decrement the number of sessions in the dialog. Once the session counter 
+ * reach zero and there is no pending transaction, the dialog will be 
+ * destroyed. Note that this function may destroy the dialog immediately 
+ * if there is no pending transaction when this function is called.
+ *
+ * @param dlg		    The dialog.
+ * @param mod		    The module that decrements the session counter.
+ *
+ * @return		    PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_dec_session( pjsip_dialog *dlg,
+					    pjsip_module *mod);
+
+/**
+ * Add a module as dialog usage, and optionally set the module specific data.
+ *
+ * @param dlg		    The dialog.
+ * @param module	    The module to be registered as dialog usage.
+ * @param mod_data	    Optional arbitrary data to be attached to dialog's
+ *			    mod_data array at the module's index.
+ *
+ * @return		    PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_add_usage( pjsip_dialog *dlg,
+					  pjsip_module *module,
+					  void *mod_data );
+
+/**
+ * Check if the specified module has been registered as usage to the dialog.
+ *
+ * @param dlg		    The dialog.
+ * @param module	    The module.
+ *
+ * @return		    PJ_TRUE if the specified module is currently
+ * 			    registered as a usage to the dialog.
+ */
+PJ_DECL(pj_bool_t) pjsip_dlg_has_usage(pjsip_dialog *dlg,
+				       pjsip_module *module);
+
+/**
+ * Attach module specific data to the dialog. Application can also set 
+ * the value directly by accessing dlg->mod_data[module_id].
+ *
+ * @param dlg		    The dialog
+ * @param mod_id	    The ID of the module from which the data is to be
+ *			    set to the dialog.
+ * @param data		    Arbitrary data.
+ *
+ * @return		    PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_set_mod_data( pjsip_dialog *dlg,
+					     int mod_id,
+					     void *data );
+
+/**
+ * Get module specific data previously attached to the dialog. Application
+ * can also get value directly by accessing dlg->mod_data[module_id].
+ *
+ * @param dlg		    The dialog
+ * @param mod_id	    The ID of the module from which the data is to be
+ *			    retrieved from the dialog.
+ *
+ * @return		    The data that was previously set, or NULL.
+ */
+PJ_DECL(void*) pjsip_dlg_get_mod_data( pjsip_dialog *dlg,
+				       int mod_id);
+
+
+/**
+ * Lock dialog and increment session counter termporarily, to prevent it 
+ * from being destroyed.
+ *
+ * @param dlg		    The dialog.
+ */
+PJ_DECL(void) pjsip_dlg_inc_lock( pjsip_dialog *dlg );
+
+/**
+ * Try to acquire dialog's lock, but return immediately if lock can not
+ * be acquired.
+ *
+ * @param dlg		    The dialog.
+ *
+ * @return		    PJ_SUCCESS if lock has been acquired.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_try_inc_lock( pjsip_dialog *dlg );
+
+/**
+ * Unlock dialog and decrement temporary session counter. After this function
+ * is called, dialog may be destroyed.
+ *
+ * @param dlg		    The dialog.
+ */
+PJ_DECL(void) pjsip_dlg_dec_lock( pjsip_dialog *dlg );
+
+
+/**
+ * Get the dialog instance in the incoming rdata. If an incoming message 
+ * matches an existing dialog, the user agent must have put the matching 
+ * dialog instance in the rdata, or otherwise this function will return 
+ * NULL if the message didn't match any existing dialog.
+ *
+ * This function can only be called after endpoint distributes the message
+ * to the transaction layer or UA layer. In other words, application can
+ * only call this function in the context of module that runs in priority
+ * number higher than PJSIP_MOD_PRIORITY_UA_PROXY_LAYER.
+ *
+ * @param rdata		    Incoming message buffer.
+ *
+ * @return		    The dialog instance that "owns" the message.
+ */
+PJ_DECL(pjsip_dialog*) pjsip_rdata_get_dlg( pjsip_rx_data *rdata );
+
+/**
+ * Get the associated dialog for the specified transaction, if any.
+ *
+ * @param tsx		    The transaction.
+ *
+ * @return		    The dialog instance which has been registered
+ *			    to the transaction as transaction user, or
+ *			    NULL if the transaction is outside any dialogs.
+ */
+PJ_DECL(pjsip_dialog*) pjsip_tsx_get_dlg( pjsip_transaction *tsx );
+
+
+/**
+ * Create a basic/generic request with the specified method and optionally
+ * specify the cseq. Use value -1 for cseq to have the dialog automatically
+ * put next cseq number for the request. Otherwise for some requests, 
+ * e.q. CANCEL and ACK, application must put the CSeq in the original 
+ * INVITE request as the parameter. 
+ *
+ * This function will also put Contact header where appropriate.
+ *
+ * @param dlg		    The dialog instance.
+ * @param method	    The method of the request.
+ * @param cseq		    Optional CSeq, which only needs to be specified
+ *			    when creating ACK and CANCEL. For other requests,
+ *			    specify -1 to use dialog's internal counter.
+ * @param tdata		    Pointer to receive the request's transmit
+ *			    data buffer.
+ *
+ * @return		    PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_create_request(	pjsip_dialog *dlg,
+						const pjsip_method *method,
+						int cseq,
+						pjsip_tx_data **tdata);
+
+
+/**
+ * Send request message to remote peer. If the request is not an ACK request, 
+ * the dialog will send the request statefully, by creating an UAC transaction
+ * and send the request with the transaction. 
+ *
+ * Also when the request is not ACK or CANCEL, the dialog will increment its
+ * local cseq number and update the cseq in the request according to dialog's 
+ * cseq.
+ *
+ * If p_tsx is not null, this argument will be set with the transaction 
+ * instance that was used to send the request.
+ *
+ * This function will decrement the transmit data's reference counter
+ * regardless the status of the operation.
+ *
+ * @param dlg		    The dialog.
+ * @param tdata		    The request message to be sent.
+ * @param mod_data_id	    Optional module data index to put an optional data
+ *			    into the transaction. If no module data is to be
+ *			    attached, this value should be -1.
+ * @param mod_data	    Optional module data to be attached to the 
+ *			    transaction at mod_data_id index.
+ *
+ * @return		    PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_send_request (	pjsip_dialog *dlg,
+						pjsip_tx_data *tdata,
+						int mod_data_id,
+						void *mod_data);
+
+
+/**
+ * Create a response message for the incoming request in rdata with status
+ * code st_code and optional status text st_text. This function is different
+ * than endpoint's API #pjsip_endpt_create_response() in that the dialog 
+ * function adds Contact header and Record-Routes headers in the response 
+ * where appropriate.
+ *
+ * @param dlg		    The dialog.
+ * @param rdata		    The incoming request message for which the
+ *			    response will be created.
+ * @param st_code	    Status code.
+ * @param st_text	    Optional string for custom status reason text.
+ * @param tdata		    Pointer to receive the response message transmit
+ *			    data buffer.
+ *
+ * @return		    PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_create_response(	pjsip_dialog *dlg,
+						pjsip_rx_data *rdata,
+						int st_code,
+						const pj_str_t *st_text,
+						pjsip_tx_data **tdata);
+
+
+/**
+ * Modify previously sent response with other status code. Contact header 
+ * will be added when appropriate.
+ *
+ * @param dlg		    The dialog.
+ * @param tdata		    The transmit data buffer containing response
+ *			    message to be modified.
+ * @param st_code	    New status code to be set.
+ * @param st_text	    Optional string for custom status reason text.
+ *
+ * @return		    PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_modify_response(	pjsip_dialog *dlg,
+						pjsip_tx_data *tdata,
+						int st_code,
+						const pj_str_t *st_text);
+
+
+/**
+ * Send response message statefully. The transaction instance MUST be the 
+ * transaction that was reported on on_rx_request() callback.
+ *
+ * This function decrements the transmit data's reference counter regardless
+ * the status of the operation.
+ *
+ * @param dlg		    The dialog.
+ * @param tsx		    The UAS transaction associated with the incoming
+ *			    request. If the request is within a dialog, or
+ *			    a dialog has been created for the request that
+ *			    creates the dialog, application can get the
+ *			    transaction instance for the request by calling
+ *			    #pjsip_rdata_get_tsx().
+ * @param tdata		    Response message to be sent.
+ *
+ * @return		    PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_send_response(	pjsip_dialog *dlg,
+						pjsip_transaction *tsx,
+						pjsip_tx_data *tdata);
+
+
+/**
+ * This composite function sends response message statefully to an incoming
+ * request message inside dialog.
+ *
+ * @param dlg	    The endpoint instance.
+ * @param rdata	    The incoming request message.
+ * @param st_code   Status code of the response.
+ * @param st_text   Optional status text of the response.
+ * @param hdr_list  Optional header list to be added to the response.
+ * @param body	    Optional message body to be added to the response.
+ *
+ * @return	    PJ_SUCCESS if response message has successfully been
+ *		    sent.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_respond( pjsip_dialog *dlg,
+					pjsip_rx_data *rdata,
+					int st_code,
+					const pj_str_t *st_text,
+					const pjsip_hdr *hdr_list,
+					const pjsip_msg_body *body );
+
+
+/**
+ * Check if remote peer have the specified capability as published
+ * in the dialog messages from remote peer.
+ *
+ * Notes:
+ * - The capability \a token lookup will apply exact match, but not 
+ *   case-sensitive, for example: <tt>"text/html"</tt> will not match 
+ *   <tt>"text / html"</tt> (notice the spaces).
+ *
+ * @param dlg	    The dialog.
+ * @param htype	    The header type to be checked, which value may be:
+ *		    - PJSIP_H_ACCEPT
+ *		    - PJSIP_H_ALLOW
+ *		    - PJSIP_H_SUPPORTED
+ * @param hname	    If htype specifies PJSIP_H_OTHER, then the header name
+ *		    must be supplied in this argument. Otherwise the value
+ *		    must be set to NULL.
+ * @param token	    The capability token to check. For example, if \a htype
+ *		    is PJSIP_H_ALLOW, then \a token specifies the method
+ *		    names; if \a htype is PJSIP_H_SUPPORTED, then \a token
+ *		    specifies the extension names such as "100rel".
+ *
+ * @return	    PJSIP_DIALOG_CAP_SUPPORTED if the specified capability
+ *		    is explicitly supported, see @pjsip_dialog_cap_status
+ *		    for more info.
+ */
+PJ_DECL(pjsip_dialog_cap_status) pjsip_dlg_remote_has_cap(
+						    pjsip_dialog *dlg,
+						    int htype,
+						    const pj_str_t *hname,
+						    const pj_str_t *token);
+
+/**
+ * Get the specified capability header from the remote capability headers
+ * stored in the dialog.
+ *
+ * @param dlg	    The dialog.
+ * @param htype	    The header type to be retrieved, which value may be:
+ *		    - PJSIP_H_ACCEPT
+ *		    - PJSIP_H_ALLOW
+ *		    - PJSIP_H_SUPPORTED
+ * @param hname	    If htype specifies PJSIP_H_OTHER, then the header name
+ *		    must be supplied in this argument. Otherwise the value
+ *		    must be set to NULL.
+ *
+ * @return	    The appropriate header, or NULL if the header is not
+ *		    available.
+ */
+PJ_DECL(const pjsip_hdr*) pjsip_dlg_get_remote_cap_hdr(pjsip_dialog *dlg,
+						       int htype,
+						       const pj_str_t *hname);
+
+/**
+ * Set remote capability from a SIP header containing array of capability 
+ * tags/values.
+ *
+ * @param dlg	    The dialog.
+ * @param cap_hdr   The SIP header.
+ *
+ * @return	    PJ_SUCCESS when successful, otherwise the appropriate
+ *		    error code will be returned.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_set_remote_cap_hdr(
+				    pjsip_dialog *dlg,
+				    const pjsip_generic_array_hdr *cap_hdr);
+
+/**
+ * Remove a remote capability header.
+ *
+ * @param dlg	    The dialog.
+ * @param htype	    The header type to be removed, which value may be:
+ *		    - PJSIP_H_ACCEPT
+ *		    - PJSIP_H_ALLOW
+ *		    - PJSIP_H_SUPPORTED
+ * @param hname	    If htype specifies PJSIP_H_OTHER, then the header name
+ *		    must be supplied in this argument. Otherwise the value
+ *		    must be set to NULL.
+ *
+ * @return	    PJ_SUCCESS when successful, otherwise the appropriate
+ *		    error code will be returned.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_remove_remote_cap_hdr(pjsip_dialog *dlg,
+						     int htype,
+						     const pj_str_t *hname);
+
+/**
+ * Update remote capabilities from a received message. The header types
+ * to be updated from the message will only be \a PJSIP_H_ACCEPT, 
+ * \a PJSIP_H_ALLOW, and \a PJSIP_H_SUPPORTED.
+ *
+ * @param dlg	    The dialog.
+ * @param msg	    The received message.
+ * @param strict    If this is set to PJ_TRUE, any header types missing
+ *		    from the message will cause removal of existing
+ *		    header types in the capability list. Otherwise, the 
+ *		    capability list will not be modified when any header
+ *                  type is missing.
+ *
+ * @return	    PJ_SUCCESS when successful, otherwise the appropriate
+ *		    error code will be returned.
+ */
+PJ_DECL(pj_status_t) pjsip_dlg_update_remote_cap(pjsip_dialog *dlg,
+					         const pjsip_msg *msg,
+						 pj_bool_t strict);
+
+
+
+/**
+ * @}
+ */
+
+/* 
+ * Internal (called by sip_ua_layer.c)
+ */
+
+/* Receives transaction event (called by user_agent module) */
+void pjsip_dlg_on_tsx_state( pjsip_dialog *dlg,
+			     pjsip_transaction *tsx,
+			     pjsip_event *e );
+
+void pjsip_dlg_on_rx_request( pjsip_dialog *dlg,
+			      pjsip_rx_data *rdata );
+
+void pjsip_dlg_on_rx_response( pjsip_dialog *dlg,
+			       pjsip_rx_data *rdata );
+
+
+
+PJ_END_DECL
+
+
+#endif	/* __PJSIP_SIP_DIALOG_H__ */
+
diff --git a/jni/pjproject-android/.svn/pristine/25/255255a3266c1358c7f9c0508c2fb8c98ec2b1f9.svn-base b/jni/pjproject-android/.svn/pristine/25/255255a3266c1358c7f9c0508c2fb8c98ec2b1f9.svn-base
new file mode 100644
index 0000000..86c3d57
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/25/255255a3266c1358c7f9c0508c2fb8c98ec2b1f9.svn-base
@@ -0,0 +1,645 @@
+/* $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-codec/gsm.h>
+#include <pjmedia/codec.h>
+#include <pjmedia/errno.h>
+#include <pjmedia/endpoint.h>
+#include <pjmedia/plc.h>
+#include <pjmedia/port.h>
+#include <pjmedia/silencedet.h>
+#include <pj/assert.h>
+#include <pj/pool.h>
+#include <pj/string.h>
+#include <pj/os.h>
+
+/*
+ * Only build this file if PJMEDIA_HAS_GSM_CODEC != 0
+ */
+#if defined(PJMEDIA_HAS_GSM_CODEC) && PJMEDIA_HAS_GSM_CODEC != 0
+
+#if defined(PJMEDIA_EXTERNAL_GSM_CODEC) && PJMEDIA_EXTERNAL_GSM_CODEC
+# if PJMEDIA_EXTERNAL_GSM_GSM_H
+#   include <gsm/gsm.h>
+# elif PJMEDIA_EXTERNAL_GSM_H
+#   include <gsm.h>
+# else
+#   error Please set the location of gsm.h
+# endif
+#else
+#   include "../../third_party/gsm/inc/gsm.h"
+#endif
+
+/* We removed PLC in 0.6 (and re-enabled it again in 0.9!) */
+#define PLC_DISABLED	0
+
+
+/* Prototypes for GSM factory */
+static pj_status_t gsm_test_alloc( pjmedia_codec_factory *factory, 
+				   const pjmedia_codec_info *id );
+static pj_status_t gsm_default_attr( pjmedia_codec_factory *factory, 
+				     const pjmedia_codec_info *id, 
+				     pjmedia_codec_param *attr );
+static pj_status_t gsm_enum_codecs( pjmedia_codec_factory *factory, 
+				    unsigned *count, 
+				    pjmedia_codec_info codecs[]);
+static pj_status_t gsm_alloc_codec( pjmedia_codec_factory *factory, 
+				    const pjmedia_codec_info *id, 
+				    pjmedia_codec **p_codec);
+static pj_status_t gsm_dealloc_codec( pjmedia_codec_factory *factory, 
+				      pjmedia_codec *codec );
+
+/* Prototypes for GSM implementation. */
+static pj_status_t  gsm_codec_init( pjmedia_codec *codec, 
+				    pj_pool_t *pool );
+static pj_status_t  gsm_codec_open( pjmedia_codec *codec, 
+				    pjmedia_codec_param *attr );
+static pj_status_t  gsm_codec_close( pjmedia_codec *codec );
+static pj_status_t  gsm_codec_modify(pjmedia_codec *codec, 
+				     const pjmedia_codec_param *attr );
+static pj_status_t  gsm_codec_parse( pjmedia_codec *codec,
+				     void *pkt,
+				     pj_size_t pkt_size,
+				     const pj_timestamp *ts,
+				     unsigned *frame_cnt,
+				     pjmedia_frame frames[]);
+static pj_status_t  gsm_codec_encode( pjmedia_codec *codec, 
+				      const struct pjmedia_frame *input,
+				      unsigned output_buf_len, 
+				      struct pjmedia_frame *output);
+static pj_status_t  gsm_codec_decode( pjmedia_codec *codec, 
+				      const struct pjmedia_frame *input,
+				      unsigned output_buf_len, 
+				      struct pjmedia_frame *output);
+#if !PLC_DISABLED
+static pj_status_t  gsm_codec_recover(pjmedia_codec *codec,
+				      unsigned output_buf_len,
+				      struct pjmedia_frame *output);
+#endif
+
+/* Definition for GSM codec operations. */
+static pjmedia_codec_op gsm_op = 
+{
+    &gsm_codec_init,
+    &gsm_codec_open,
+    &gsm_codec_close,
+    &gsm_codec_modify,
+    &gsm_codec_parse,
+    &gsm_codec_encode,
+    &gsm_codec_decode,
+#if !PLC_DISABLED
+    &gsm_codec_recover
+#else
+    NULL
+#endif
+};
+
+/* Definition for GSM codec factory operations. */
+static pjmedia_codec_factory_op gsm_factory_op =
+{
+    &gsm_test_alloc,
+    &gsm_default_attr,
+    &gsm_enum_codecs,
+    &gsm_alloc_codec,
+    &gsm_dealloc_codec,
+    &pjmedia_codec_gsm_deinit
+};
+
+/* GSM factory */
+static struct gsm_codec_factory
+{
+    pjmedia_codec_factory    base;
+    pjmedia_endpt	    *endpt;
+    pj_pool_t		    *pool;
+    pj_mutex_t		    *mutex;
+    pjmedia_codec	     codec_list;
+} gsm_codec_factory;
+
+
+/* GSM codec private data. */
+struct gsm_data
+{
+    struct gsm_state	*encoder;
+    struct gsm_state	*decoder;
+    pj_bool_t		 plc_enabled;
+#if !PLC_DISABLED
+    pjmedia_plc		*plc;
+#endif
+    pj_bool_t		 vad_enabled;
+    pjmedia_silence_det	*vad;
+    pj_timestamp	 last_tx;
+};
+
+
+
+/*
+ * Initialize and register GSM codec factory to pjmedia endpoint.
+ */
+PJ_DEF(pj_status_t) pjmedia_codec_gsm_init( pjmedia_endpt *endpt )
+{
+    pjmedia_codec_mgr *codec_mgr;
+    pj_status_t status;
+
+    if (gsm_codec_factory.pool != NULL)
+	return PJ_SUCCESS;
+
+    /* Create GSM codec factory. */
+    gsm_codec_factory.base.op = &gsm_factory_op;
+    gsm_codec_factory.base.factory_data = NULL;
+    gsm_codec_factory.endpt = endpt;
+
+    gsm_codec_factory.pool = pjmedia_endpt_create_pool(endpt, "gsm", 4000, 
+						       4000);
+    if (!gsm_codec_factory.pool)
+	return PJ_ENOMEM;
+
+    pj_list_init(&gsm_codec_factory.codec_list);
+
+    /* Create mutex. */
+    status = pj_mutex_create_simple(gsm_codec_factory.pool, "gsm", 
+				    &gsm_codec_factory.mutex);
+    if (status != PJ_SUCCESS)
+	goto on_error;
+
+    /* Get the codec manager. */
+    codec_mgr = pjmedia_endpt_get_codec_mgr(endpt);
+    if (!codec_mgr) {
+	status = PJ_EINVALIDOP;
+	goto on_error;
+    }
+
+    /* Register codec factory to endpoint. */
+    status = pjmedia_codec_mgr_register_factory(codec_mgr, 
+						&gsm_codec_factory.base);
+    if (status != PJ_SUCCESS)
+	goto on_error;
+
+    /* Done. */
+    return PJ_SUCCESS;
+
+on_error:
+    pj_pool_release(gsm_codec_factory.pool);
+    gsm_codec_factory.pool = NULL;
+    return status;
+}
+
+
+
+/*
+ * Unregister GSM codec factory from pjmedia endpoint and deinitialize
+ * the GSM codec library.
+ */
+PJ_DEF(pj_status_t) pjmedia_codec_gsm_deinit(void)
+{
+    pjmedia_codec_mgr *codec_mgr;
+    pj_status_t status;
+
+    if (gsm_codec_factory.pool == NULL)
+	return PJ_SUCCESS;
+
+    /* We don't want to deinit if there's outstanding codec. */
+    /* This is silly, as we'll always have codec in the list if
+       we ever allocate a codec! A better behavior maybe is to 
+       deallocate all codecs in the list.
+    pj_mutex_lock(gsm_codec_factory.mutex);
+    if (!pj_list_empty(&gsm_codec_factory.codec_list)) {
+	pj_mutex_unlock(gsm_codec_factory.mutex);
+	return PJ_EBUSY;
+    }
+    */
+
+    /* Get the codec manager. */
+    codec_mgr = pjmedia_endpt_get_codec_mgr(gsm_codec_factory.endpt);
+    if (!codec_mgr) {
+	pj_pool_release(gsm_codec_factory.pool);
+	gsm_codec_factory.pool = NULL;
+	return PJ_EINVALIDOP;
+    }
+
+    /* Unregister GSM codec factory. */
+    status = pjmedia_codec_mgr_unregister_factory(codec_mgr,
+						  &gsm_codec_factory.base);
+    
+    /* Destroy mutex. */
+    pj_mutex_destroy(gsm_codec_factory.mutex);
+
+    /* Destroy pool. */
+    pj_pool_release(gsm_codec_factory.pool);
+    gsm_codec_factory.pool = NULL;
+
+    return status;
+}
+
+/* 
+ * Check if factory can allocate the specified codec. 
+ */
+static pj_status_t gsm_test_alloc( pjmedia_codec_factory *factory, 
+				   const pjmedia_codec_info *info )
+{
+    PJ_UNUSED_ARG(factory);
+
+    /* Check payload type. */
+    if (info->pt != PJMEDIA_RTP_PT_GSM)
+	return PJMEDIA_CODEC_EUNSUP;
+
+    /* Ignore the rest, since it's static payload type. */
+
+    return PJ_SUCCESS;
+}
+
+/*
+ * Generate default attribute.
+ */
+static pj_status_t gsm_default_attr (pjmedia_codec_factory *factory, 
+				      const pjmedia_codec_info *id, 
+				      pjmedia_codec_param *attr )
+{
+    PJ_UNUSED_ARG(factory);
+    PJ_UNUSED_ARG(id);
+
+    pj_bzero(attr, sizeof(pjmedia_codec_param));
+    attr->info.clock_rate = 8000;
+    attr->info.channel_cnt = 1;
+    attr->info.avg_bps = 13200;
+    attr->info.max_bps = 13200;
+    attr->info.pcm_bits_per_sample = 16;
+    attr->info.frm_ptime = 20;
+    attr->info.pt = PJMEDIA_RTP_PT_GSM;
+
+    attr->setting.frm_per_pkt = 1;
+    attr->setting.vad = 1;
+#if !PLC_DISABLED
+    attr->setting.plc = 1;
+#endif
+
+    /* Default all other flag bits disabled. */
+
+    return PJ_SUCCESS;
+}
+
+/*
+ * Enum codecs supported by this factory (i.e. only GSM!).
+ */
+static pj_status_t gsm_enum_codecs(pjmedia_codec_factory *factory, 
+				    unsigned *count, 
+				    pjmedia_codec_info codecs[])
+{
+    PJ_UNUSED_ARG(factory);
+    PJ_ASSERT_RETURN(codecs && *count > 0, PJ_EINVAL);
+
+    pj_bzero(&codecs[0], sizeof(pjmedia_codec_info));
+    codecs[0].encoding_name = pj_str("GSM");
+    codecs[0].pt = PJMEDIA_RTP_PT_GSM;
+    codecs[0].type = PJMEDIA_TYPE_AUDIO;
+    codecs[0].clock_rate = 8000;
+    codecs[0].channel_cnt = 1;
+
+    *count = 1;
+
+    return PJ_SUCCESS;
+}
+
+/*
+ * Allocate a new GSM codec instance.
+ */
+static pj_status_t gsm_alloc_codec( pjmedia_codec_factory *factory, 
+				    const pjmedia_codec_info *id,
+				    pjmedia_codec **p_codec)
+{
+    pjmedia_codec *codec;
+    struct gsm_data *gsm_data;
+    pj_status_t status;
+
+    PJ_ASSERT_RETURN(factory && id && p_codec, PJ_EINVAL);
+    PJ_ASSERT_RETURN(factory == &gsm_codec_factory.base, PJ_EINVAL);
+
+
+    pj_mutex_lock(gsm_codec_factory.mutex);
+
+    /* Get free nodes, if any. */
+    if (!pj_list_empty(&gsm_codec_factory.codec_list)) {
+	codec = gsm_codec_factory.codec_list.next;
+	pj_list_erase(codec);
+    } else {
+	codec = PJ_POOL_ZALLOC_T(gsm_codec_factory.pool, pjmedia_codec);
+	PJ_ASSERT_RETURN(codec != NULL, PJ_ENOMEM);
+	codec->op = &gsm_op;
+	codec->factory = factory;
+
+	gsm_data = PJ_POOL_ZALLOC_T(gsm_codec_factory.pool, struct gsm_data);
+	codec->codec_data = gsm_data;
+
+#if !PLC_DISABLED
+	/* Create PLC */
+	status = pjmedia_plc_create(gsm_codec_factory.pool, 8000, 
+				    160, 0, &gsm_data->plc);
+	if (status != PJ_SUCCESS) {
+	    pj_mutex_unlock(gsm_codec_factory.mutex);
+	    return status;
+	}
+#endif
+
+	/* Create silence detector */
+	status = pjmedia_silence_det_create(gsm_codec_factory.pool,
+					    8000, 160,
+					    &gsm_data->vad);
+	if (status != PJ_SUCCESS) {
+	    pj_mutex_unlock(gsm_codec_factory.mutex);
+	    return status;
+	}
+    }
+
+    pj_mutex_unlock(gsm_codec_factory.mutex);
+
+    *p_codec = codec;
+    return PJ_SUCCESS;
+}
+
+/*
+ * Free codec.
+ */
+static pj_status_t gsm_dealloc_codec( pjmedia_codec_factory *factory, 
+				      pjmedia_codec *codec )
+{
+    struct gsm_data *gsm_data;
+    int i;
+
+    PJ_ASSERT_RETURN(factory && codec, PJ_EINVAL);
+    PJ_ASSERT_RETURN(factory == &gsm_codec_factory.base, PJ_EINVAL);
+
+    gsm_data = (struct gsm_data*) codec->codec_data;
+
+    /* Close codec, if it's not closed. */
+    gsm_codec_close(codec);
+
+#if !PLC_DISABLED
+    /* Clear left samples in the PLC, since codec+plc will be reused
+     * next time.
+     */
+    for (i=0; i<2; ++i) {
+	pj_int16_t frame[160];
+	pjmedia_zero_samples(frame, PJ_ARRAY_SIZE(frame));
+	pjmedia_plc_save(gsm_data->plc, frame);
+    }
+#else
+    PJ_UNUSED_ARG(i);
+#endif
+
+    /* Re-init silence_period */
+    pj_set_timestamp32(&gsm_data->last_tx, 0, 0);
+
+    /* Put in the free list. */
+    pj_mutex_lock(gsm_codec_factory.mutex);
+    pj_list_push_front(&gsm_codec_factory.codec_list, codec);
+    pj_mutex_unlock(gsm_codec_factory.mutex);
+
+    return PJ_SUCCESS;
+}
+
+/*
+ * Init codec.
+ */
+static pj_status_t gsm_codec_init( pjmedia_codec *codec, 
+				   pj_pool_t *pool )
+{
+    PJ_UNUSED_ARG(codec);
+    PJ_UNUSED_ARG(pool);
+    return PJ_SUCCESS;
+}
+
+/*
+ * Open codec.
+ */
+static pj_status_t gsm_codec_open( pjmedia_codec *codec, 
+				   pjmedia_codec_param *attr )
+{
+    struct gsm_data *gsm_data = (struct gsm_data*) codec->codec_data;
+
+    pj_assert(gsm_data != NULL);
+    pj_assert(gsm_data->encoder == NULL && gsm_data->decoder == NULL);
+
+    gsm_data->encoder = gsm_create();
+    if (!gsm_data->encoder)
+	return PJMEDIA_CODEC_EFAILED;
+
+    gsm_data->decoder = gsm_create();
+    if (!gsm_data->decoder)
+	return PJMEDIA_CODEC_EFAILED;
+
+    gsm_data->vad_enabled = (attr->setting.vad != 0);
+    gsm_data->plc_enabled = (attr->setting.plc != 0);
+
+    return PJ_SUCCESS;
+}
+
+/*
+ * Close codec.
+ */
+static pj_status_t gsm_codec_close( pjmedia_codec *codec )
+{
+    struct gsm_data *gsm_data = (struct gsm_data*) codec->codec_data;
+
+    pj_assert(gsm_data != NULL);
+
+    if (gsm_data->encoder) {
+	gsm_destroy(gsm_data->encoder);
+	gsm_data->encoder = NULL;
+    }
+    if (gsm_data->decoder) {
+	gsm_destroy(gsm_data->decoder);
+	gsm_data->decoder = NULL;
+    }
+
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Modify codec settings.
+ */
+static pj_status_t  gsm_codec_modify(pjmedia_codec *codec, 
+				     const pjmedia_codec_param *attr )
+{
+    struct gsm_data *gsm_data = (struct gsm_data*) codec->codec_data;
+
+    pj_assert(gsm_data != NULL);
+    pj_assert(gsm_data->encoder != NULL && gsm_data->decoder != NULL);
+
+    gsm_data->vad_enabled = (attr->setting.vad != 0);
+    gsm_data->plc_enabled = (attr->setting.plc != 0);
+
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Get frames in the packet.
+ */
+static pj_status_t  gsm_codec_parse( pjmedia_codec *codec,
+				     void *pkt,
+				     pj_size_t pkt_size,
+				     const pj_timestamp *ts,
+				     unsigned *frame_cnt,
+				     pjmedia_frame frames[])
+{
+    unsigned count = 0;
+
+    PJ_UNUSED_ARG(codec);
+
+    PJ_ASSERT_RETURN(frame_cnt, PJ_EINVAL);
+
+    while (pkt_size >= 33 && count < *frame_cnt) {
+	frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO;
+	frames[count].buf = pkt;
+	frames[count].size = 33;
+	frames[count].timestamp.u64 = ts->u64 + count * 160;
+
+	pkt = ((char*)pkt) + 33;
+	pkt_size -= 33;
+
+	++count;
+    }
+
+    *frame_cnt = count;
+    return PJ_SUCCESS;
+}
+
+/*
+ * Encode frame.
+ */
+static pj_status_t gsm_codec_encode( pjmedia_codec *codec, 
+				     const struct pjmedia_frame *input,
+				     unsigned output_buf_len, 
+				     struct pjmedia_frame *output)
+{
+    struct gsm_data *gsm_data = (struct gsm_data*) codec->codec_data;
+    pj_int16_t *pcm_in;
+    pj_size_t in_size;
+
+    pj_assert(gsm_data && input && output);
+    
+    pcm_in = (pj_int16_t*)input->buf;
+    in_size = input->size;
+
+    PJ_ASSERT_RETURN(in_size % 320 == 0, PJMEDIA_CODEC_EPCMFRMINLEN);
+    PJ_ASSERT_RETURN(output_buf_len >= 33 * in_size/320, 
+		     PJMEDIA_CODEC_EFRMTOOSHORT);
+
+    /* Detect silence */
+    if (gsm_data->vad_enabled) {
+	pj_bool_t is_silence;
+	pj_int32_t silence_duration;
+
+	silence_duration = pj_timestamp_diff32(&gsm_data->last_tx, 
+					       &input->timestamp);
+
+	is_silence = pjmedia_silence_det_detect(gsm_data->vad, 
+					        (const pj_int16_t*) input->buf,
+						(input->size >> 1),
+						NULL);
+	if (is_silence &&
+	    (PJMEDIA_CODEC_MAX_SILENCE_PERIOD == -1 ||
+	     silence_duration < PJMEDIA_CODEC_MAX_SILENCE_PERIOD*8000/1000))
+	{
+	    output->type = PJMEDIA_FRAME_TYPE_NONE;
+	    output->buf = NULL;
+	    output->size = 0;
+	    output->timestamp = input->timestamp;
+	    return PJ_SUCCESS;
+	} else {
+	    gsm_data->last_tx = input->timestamp;
+	}
+    }
+
+    /* Encode */
+    output->size = 0;
+    while (in_size >= 320) {
+	gsm_encode(gsm_data->encoder, pcm_in, 
+		   (unsigned char*)output->buf + output->size);
+	pcm_in += 160;
+	output->size += 33;
+	in_size -= 320;
+    }
+
+    output->type = PJMEDIA_FRAME_TYPE_AUDIO;
+    output->timestamp = input->timestamp;
+
+    return PJ_SUCCESS;
+}
+
+/*
+ * Decode frame.
+ */
+static pj_status_t gsm_codec_decode( pjmedia_codec *codec, 
+				     const struct pjmedia_frame *input,
+				     unsigned output_buf_len, 
+				     struct pjmedia_frame *output)
+{
+    struct gsm_data *gsm_data = (struct gsm_data*) codec->codec_data;
+
+    pj_assert(gsm_data != NULL);
+    PJ_ASSERT_RETURN(input && output, PJ_EINVAL);
+
+    if (output_buf_len < 320)
+	return PJMEDIA_CODEC_EPCMTOOSHORT;
+
+    if (input->size < 33)
+	return PJMEDIA_CODEC_EFRMTOOSHORT;
+
+    gsm_decode(gsm_data->decoder, 
+	       (unsigned char*)input->buf, 
+	       (short*)output->buf);
+
+    output->size = 320;
+    output->type = PJMEDIA_FRAME_TYPE_AUDIO;
+    output->timestamp = input->timestamp;
+
+#if !PLC_DISABLED
+    if (gsm_data->plc_enabled)
+	pjmedia_plc_save( gsm_data->plc, (pj_int16_t*)output->buf);
+#endif
+
+    return PJ_SUCCESS;
+}
+
+
+#if !PLC_DISABLED
+/*
+ * Recover lost frame.
+ */
+static pj_status_t  gsm_codec_recover(pjmedia_codec *codec,
+				      unsigned output_buf_len,
+				      struct pjmedia_frame *output)
+{
+    struct gsm_data *gsm_data = (struct gsm_data*) codec->codec_data;
+
+    PJ_ASSERT_RETURN(gsm_data->plc_enabled, PJ_EINVALIDOP);
+
+    PJ_ASSERT_RETURN(output_buf_len >= 320, PJMEDIA_CODEC_EPCMTOOSHORT);
+
+    pjmedia_plc_generate(gsm_data->plc, (pj_int16_t*)output->buf);
+    output->size = 320;
+
+    return PJ_SUCCESS;
+}
+#endif
+
+
+#endif	/* PJMEDIA_HAS_GSM_CODEC */
+
diff --git a/jni/pjproject-android/.svn/pristine/25/2560f472573d73e0a272ecc68a60e306e3ff3f77.svn-base b/jni/pjproject-android/.svn/pristine/25/2560f472573d73e0a272ecc68a60e306e3ff3f77.svn-base
new file mode 100644
index 0000000..2fa6334
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/25/2560f472573d73e0a272ecc68a60e306e3ff3f77.svn-base
@@ -0,0 +1,822 @@
+/* $Id$ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * 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-videodev/videodev_imp.h>
+#include <pjmedia/errno.h>
+#include <pj/assert.h>
+#include <pj/errno.h>
+#include <pj/file_access.h>
+#include <pj/log.h>
+#include <pj/os.h>
+#include <pj/rand.h>
+
+#if PJMEDIA_VIDEO_DEV_HAS_V4L2
+
+#include <linux/videodev2.h>
+#include <libv4l2.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/mman.h>
+
+#define THIS_FILE		"v4l2_dev.c"
+#define DRIVER_NAME		"v4l2"
+#define V4L2_MAX_DEVS		4
+#define DEFAULT_WIDTH		640
+#define DEFAULT_HEIGHT		480
+#define DEFAULT_FPS		25
+#define DEFAULT_CLOCK_RATE	90000
+#define INVALID_FD		-1
+#define BUFFER_CNT		2
+#define MAX_IOCTL_RETRY		20
+
+
+/* mapping between pjmedia_fmt_id and v4l2 pixel format */
+typedef struct vid4lin_fmt_map
+{
+    pj_uint32_t pjmedia_fmt_id;
+    pj_uint32_t	v4l2_fmt_id;
+} vid4lin_fmt_map;
+
+/* I/O type being used */
+enum vid4lin_io_type
+{
+    IO_TYPE_NONE,
+    IO_TYPE_READ,
+    IO_TYPE_MMAP,
+    IO_TYPE_MMAP_USER
+};
+
+/* descriptor for each mmap-ed buffer */
+typedef struct vid4lin_buffer
+{
+    void   *start;
+    size_t  length;
+} vid4lin_buffer;
+
+/* v4l2 device info */
+typedef struct vid4lin_dev_info
+{
+    pjmedia_vid_dev_info	 info;
+    char			 dev_name[32];
+    struct v4l2_capability 	 v4l2_cap;
+} vid4lin_dev_info;
+
+/* v4l2 factory */
+typedef struct vid4lin_factory
+{
+    pjmedia_vid_dev_factory	 base;
+    pj_pool_t			*pool;
+    pj_pool_t			*dev_pool;
+    pj_pool_factory		*pf;
+
+    unsigned			 dev_count;
+    vid4lin_dev_info		*dev_info;
+} vid4lin_factory;
+
+/* Video stream. */
+typedef struct vid4lin_stream
+{
+    pjmedia_vid_dev_stream	 base;		/**< Base stream	*/
+    pjmedia_vid_dev_param	 param;		/**< Settings		*/
+    pj_pool_t           	*pool;		/**< Memory pool.	*/
+
+    int			 	 fd;		/**< Video fd.		*/
+    char			 name[64];	/**< Name for log	*/
+    enum vid4lin_io_type	 io_type;	/**< I/O method.	*/
+    unsigned			 buf_cnt;	/**< MMap buf cnt.  	*/
+    vid4lin_buffer		*buffers;	/**< MMap buffers.  	*/
+    pj_time_val			 start_time;	/**< Time when started	*/
+
+    pjmedia_vid_dev_cb       	 vid_cb;	/**< Stream callback  	*/
+    void                	*user_data;	/**< Application data 	*/
+} vid4lin_stream;
+
+/* Use this to convert between pjmedia_format_id and V4L2 fourcc */
+static vid4lin_fmt_map v4l2_fmt_maps[] =
+{
+    { PJMEDIA_FORMAT_RGB24,	V4L2_PIX_FMT_BGR24 },
+    { PJMEDIA_FORMAT_RGBA,	V4L2_PIX_FMT_BGR32 },
+    { PJMEDIA_FORMAT_RGB32,	V4L2_PIX_FMT_BGR32 },
+    { PJMEDIA_FORMAT_AYUV,	V4L2_PIX_FMT_YUV32 },
+    { PJMEDIA_FORMAT_YUY2,	V4L2_PIX_FMT_YUYV },
+    { PJMEDIA_FORMAT_UYVY,	V4L2_PIX_FMT_UYVY }
+};
+
+/* Prototypes */
+static pj_status_t vid4lin_factory_init(pjmedia_vid_dev_factory *f);
+static pj_status_t vid4lin_factory_destroy(pjmedia_vid_dev_factory *f);
+static pj_status_t vid4lin_factory_refresh(pjmedia_vid_dev_factory *f);
+static unsigned    vid4lin_factory_get_dev_count(pjmedia_vid_dev_factory *f);
+static pj_status_t vid4lin_factory_get_dev_info(pjmedia_vid_dev_factory *f,
+					        unsigned index,
+					        pjmedia_vid_dev_info *info);
+static pj_status_t vid4lin_factory_default_param(pj_pool_t *pool,
+                                                 pjmedia_vid_dev_factory *f,
+					         unsigned index,
+					         pjmedia_vid_dev_param *param);
+static pj_status_t vid4lin_factory_create_stream(pjmedia_vid_dev_factory *f,
+						 pjmedia_vid_dev_param *prm,
+					         const pjmedia_vid_dev_cb *cb,
+					         void *user_data,
+					         pjmedia_vid_dev_stream **p);
+
+static pj_status_t vid4lin_stream_get_param(pjmedia_vid_dev_stream *strm,
+					    pjmedia_vid_dev_param *param);
+static pj_status_t vid4lin_stream_get_cap(pjmedia_vid_dev_stream *strm,
+				          pjmedia_vid_dev_cap cap,
+				          void *value);
+static pj_status_t vid4lin_stream_set_cap(pjmedia_vid_dev_stream *strm,
+				          pjmedia_vid_dev_cap cap,
+				          const void *value);
+static pj_status_t vid4lin_stream_get_frame(pjmedia_vid_dev_stream *strm,
+                                            pjmedia_frame *frame);
+static pj_status_t vid4lin_stream_start(pjmedia_vid_dev_stream *strm);
+static pj_status_t vid4lin_stream_stop(pjmedia_vid_dev_stream *strm);
+static pj_status_t vid4lin_stream_destroy(pjmedia_vid_dev_stream *strm);
+
+/* Operations */
+static pjmedia_vid_dev_factory_op factory_op =
+{
+    &vid4lin_factory_init,
+    &vid4lin_factory_destroy,
+    &vid4lin_factory_get_dev_count,
+    &vid4lin_factory_get_dev_info,
+    &vid4lin_factory_default_param,
+    &vid4lin_factory_create_stream,
+    &vid4lin_factory_refresh
+};
+
+static pjmedia_vid_dev_stream_op stream_op =
+{
+    &vid4lin_stream_get_param,
+    &vid4lin_stream_get_cap,
+    &vid4lin_stream_set_cap,
+    &vid4lin_stream_start,
+    &vid4lin_stream_get_frame,
+    NULL,
+    &vid4lin_stream_stop,
+    &vid4lin_stream_destroy
+};
+
+
+/****************************************************************************
+ * Factory operations
+ */
+/*
+ * Factory creation function.
+ */
+pjmedia_vid_dev_factory* pjmedia_v4l2_factory(pj_pool_factory *pf)
+{
+    vid4lin_factory *f;
+    pj_pool_t *pool;
+
+    pool = pj_pool_create(pf, DRIVER_NAME, 512, 512, NULL);
+    f = PJ_POOL_ZALLOC_T(pool, vid4lin_factory);
+    f->pf = pf;
+    f->pool = pool;
+    f->base.op = &factory_op;
+
+    return &f->base;
+}
+
+/* util: ioctl that tries harder. */
+static pj_status_t xioctl(int fh, int request, void *arg)
+{
+    enum { RETRY = MAX_IOCTL_RETRY };
+    int r, c=0;
+
+    do {
+	r = v4l2_ioctl(fh, request, arg);
+    } while (r==-1 && c++<RETRY && ((errno==EINTR) || (errno==EAGAIN)));
+
+    return (r == -1) ? pj_get_os_error() : PJ_SUCCESS;
+}
+
+/* Scan V4L2 devices */
+static pj_status_t v4l2_scan_devs(vid4lin_factory *f)
+{
+    vid4lin_dev_info vdi[V4L2_MAX_DEVS];
+    char dev_name[32];
+    unsigned i, old_count;
+    pj_status_t status;
+
+    if (f->dev_pool) {
+        pj_pool_release(f->dev_pool);
+        f->dev_pool = NULL;
+    }
+
+    pj_bzero(vdi, sizeof(vdi));
+    old_count = f->dev_count;
+    f->dev_count = 0;
+    f->dev_pool = pj_pool_create(f->pf, DRIVER_NAME, 500, 500, NULL);
+
+    for (i=0; i<V4L2_MAX_DEVS && f->dev_count < V4L2_MAX_DEVS; ++i) {
+	int fd;
+	vid4lin_dev_info *pdi;
+	pj_uint32_t fmt_cap[8];
+	int j, fmt_cnt=0;
+
+	pdi = &vdi[f->dev_count];
+
+	snprintf(dev_name, sizeof(dev_name), "/dev/video%d", i);
+	if (!pj_file_exists(dev_name))
+	    continue;
+
+	fd = v4l2_open(dev_name, O_RDWR, 0);
+	if (fd == -1)
+	    continue;
+
+	status = xioctl(fd, VIDIOC_QUERYCAP, &pdi->v4l2_cap);
+	if (status != PJ_SUCCESS) {
+	    PJ_PERROR(4,(THIS_FILE, status, "Error querying %s", dev_name));
+	    v4l2_close(fd);
+	    continue;
+	}
+
+	if ((pdi->v4l2_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
+	    v4l2_close(fd);
+	    continue;
+	}
+
+	PJ_LOG(5,(THIS_FILE, "Found capture device %s", pdi->v4l2_cap.card));
+	PJ_LOG(5,(THIS_FILE, "  Enumerating formats:"));
+	for (j=0; fmt_cnt<PJ_ARRAY_SIZE(fmt_cap); ++j) {
+	    struct v4l2_fmtdesc fdesc;
+	    unsigned k;
+
+	    pj_bzero(&fdesc, sizeof(fdesc));
+	    fdesc.index = j;
+	    fdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+	    status = xioctl(fd, VIDIOC_ENUM_FMT, &fdesc);
+	    if (status != PJ_SUCCESS)
+		break;
+
+	    for (k=0; k<PJ_ARRAY_SIZE(v4l2_fmt_maps); ++k) {
+		if (v4l2_fmt_maps[k].v4l2_fmt_id == fdesc.pixelformat) {
+		    fmt_cap[fmt_cnt++] = v4l2_fmt_maps[k].pjmedia_fmt_id;
+		    PJ_LOG(5,(THIS_FILE, "   Supported: %s",
+			      fdesc.description));
+		    break;
+		}
+	    }
+	    if (k==PJ_ARRAY_SIZE(v4l2_fmt_maps)) {
+		PJ_LOG(5,(THIS_FILE, "   Unsupported: %s", fdesc.description));
+	    }
+	}
+
+	v4l2_close(fd);
+
+	if (fmt_cnt==0) {
+	    PJ_LOG(5,(THIS_FILE, "    Found no common format"));
+	    continue;
+	}
+
+	strncpy(pdi->dev_name, dev_name, sizeof(pdi->dev_name));
+	pdi->dev_name[sizeof(pdi->dev_name)-1] = '\0';
+	strncpy(pdi->info.name, (char*)pdi->v4l2_cap.card,
+		sizeof(pdi->info.name));
+	pdi->info.name[sizeof(pdi->info.name)-1] = '\0';
+	strncpy(pdi->info.driver, DRIVER_NAME, sizeof(pdi->info.driver));
+	pdi->info.driver[sizeof(pdi->info.driver)-1] = '\0';
+	pdi->info.dir = PJMEDIA_DIR_CAPTURE;
+	pdi->info.has_callback = PJ_FALSE;
+	pdi->info.caps = PJMEDIA_VID_DEV_CAP_FORMAT;
+
+	pdi->info.fmt_cnt = fmt_cnt;
+	for (j=0; j<fmt_cnt; ++j) {
+	    pjmedia_format_init_video(&pdi->info.fmt[j],
+				      fmt_cap[j],
+				      DEFAULT_WIDTH,
+				      DEFAULT_HEIGHT,
+				      DEFAULT_FPS, 1);
+	}
+	if (j < fmt_cnt)
+	    continue;
+
+	f->dev_count++;
+    }
+
+    if (f->dev_count == 0)
+	return PJ_SUCCESS;
+
+    if (f->dev_count > old_count || f->dev_info == NULL) {
+	f->dev_info = (vid4lin_dev_info*)
+		      pj_pool_calloc(f->dev_pool,
+				     f->dev_count,
+				     sizeof(vid4lin_dev_info));
+    }
+    pj_memcpy(f->dev_info, vdi, f->dev_count * sizeof(vid4lin_dev_info));
+
+    return PJ_SUCCESS;
+}
+
+
+/* API: init factory */
+static pj_status_t vid4lin_factory_init(pjmedia_vid_dev_factory *f)
+{
+    return vid4lin_factory_refresh(f);
+}
+
+/* API: destroy factory */
+static pj_status_t vid4lin_factory_destroy(pjmedia_vid_dev_factory *f)
+{
+    vid4lin_factory *cf = (vid4lin_factory*)f;
+    pj_pool_t *pool = cf->pool;
+
+    if (cf->dev_pool)
+        pj_pool_release(cf->dev_pool);
+    if (cf->pool) {
+	cf->pool = NULL;
+	pj_pool_release(pool);
+    }
+
+    return PJ_SUCCESS;
+}
+
+/* API: refresh the list of devices */
+static pj_status_t vid4lin_factory_refresh(pjmedia_vid_dev_factory *f)
+{
+    vid4lin_factory *cf = (vid4lin_factory*)f;
+    pj_status_t status;
+
+    status = v4l2_scan_devs(cf);
+    if (status != PJ_SUCCESS)
+	return status;
+
+    PJ_LOG(4, (THIS_FILE, "Video4Linux2 has %d devices",
+	       cf->dev_count));
+
+    return PJ_SUCCESS;
+}
+
+/* API: get number of devices */
+static unsigned vid4lin_factory_get_dev_count(pjmedia_vid_dev_factory *f)
+{
+    vid4lin_factory *cf = (vid4lin_factory*)f;
+    return cf->dev_count;
+}
+
+/* API: get device info */
+static pj_status_t vid4lin_factory_get_dev_info(pjmedia_vid_dev_factory *f,
+					     unsigned index,
+					     pjmedia_vid_dev_info *info)
+{
+    vid4lin_factory *cf = (vid4lin_factory*)f;
+
+    PJ_ASSERT_RETURN(index < cf->dev_count, PJMEDIA_EVID_INVDEV);
+
+    pj_memcpy(info, &cf->dev_info[index].info, sizeof(*info));
+
+    return PJ_SUCCESS;
+}
+
+/* API: create default device parameter */
+static pj_status_t vid4lin_factory_default_param(pj_pool_t *pool,
+                                                 pjmedia_vid_dev_factory *f,
+                                                 unsigned index,
+                                                 pjmedia_vid_dev_param *param)
+{
+    vid4lin_factory *cf = (vid4lin_factory*)f;
+
+    PJ_ASSERT_RETURN(index < cf->dev_count, PJMEDIA_EVID_INVDEV);
+
+    pj_bzero(param, sizeof(*param));
+    param->dir = PJMEDIA_DIR_CAPTURE;
+    param->cap_id = index;
+    param->rend_id = PJMEDIA_VID_INVALID_DEV;
+    param->flags = PJMEDIA_VID_DEV_CAP_FORMAT;
+    param->clock_rate = DEFAULT_CLOCK_RATE;
+    pjmedia_format_copy(&param->fmt, &cf->dev_info[index].info.fmt[0]);
+
+    return PJ_SUCCESS;
+}
+
+static vid4lin_fmt_map* get_v4l2_format_info(pjmedia_format_id id)
+{
+    unsigned i;
+
+    for (i = 0; i < PJ_ARRAY_SIZE(v4l2_fmt_maps); i++) {
+        if (v4l2_fmt_maps[i].pjmedia_fmt_id == id)
+            return &v4l2_fmt_maps[i];
+    }
+
+    return NULL;
+}
+
+/* util: setup format */
+static pj_status_t vid4lin_stream_init_fmt(vid4lin_stream *stream,
+					const pjmedia_vid_dev_param *param,
+					pj_uint32_t pix_fmt)
+{
+    pjmedia_video_format_detail *vfd;
+    struct v4l2_format v4l2_fmt;
+    pj_status_t status;
+
+    vfd = pjmedia_format_get_video_format_detail(&param->fmt, PJ_TRUE);
+    if (vfd == NULL)
+	return PJMEDIA_EVID_BADFORMAT;
+
+    pj_bzero(&v4l2_fmt, sizeof(v4l2_fmt));
+    v4l2_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    v4l2_fmt.fmt.pix.width       = vfd->size.w;
+    v4l2_fmt.fmt.pix.height      = vfd->size.h;
+    v4l2_fmt.fmt.pix.pixelformat = pix_fmt;
+    v4l2_fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;
+    status = xioctl(stream->fd, VIDIOC_S_FMT, &v4l2_fmt);
+    if (status != PJ_SUCCESS)
+	return status;
+
+    if (v4l2_fmt.fmt.pix.pixelformat != pix_fmt) {
+	status = PJMEDIA_EVID_BADFORMAT;
+	return status;
+    }
+
+    if ((v4l2_fmt.fmt.pix.width != vfd->size.w) ||
+	(v4l2_fmt.fmt.pix.height != vfd->size.h))
+    {
+	/* Size has changed */
+	vfd->size.w = v4l2_fmt.fmt.pix.width;
+	vfd->size.h = v4l2_fmt.fmt.pix.height;
+    }
+
+    return PJ_SUCCESS;
+}
+
+/* Util: initiate v4l2 streaming via mmap */
+static pj_status_t vid4lin_stream_init_streaming(vid4lin_stream *stream)
+{
+    struct v4l2_requestbuffers req;
+    unsigned i;
+    pj_status_t status;
+
+    pj_bzero(&req, sizeof(req));
+    req.count = BUFFER_CNT;
+    req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    req.memory = V4L2_MEMORY_MMAP;
+    status = xioctl(stream->fd, VIDIOC_REQBUFS, &req);
+    if (status != PJ_SUCCESS)
+	return status;
+
+    stream->buffers = pj_pool_calloc(stream->pool, req.count,
+				     sizeof(*stream->buffers));
+    stream->buf_cnt = 0;
+
+    for (i = 0; i < req.count; ++i) {
+	struct v4l2_buffer buf;
+
+	pj_bzero(&buf, sizeof(buf));
+
+	buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	buf.memory      = V4L2_MEMORY_MMAP;
+	buf.index       = i;
+
+	status = xioctl(stream->fd, VIDIOC_QUERYBUF, &buf);
+	if (status != PJ_SUCCESS)
+	    goto on_error;
+
+	stream->buffers[i].length = buf.length;
+	stream->buffers[i].start = v4l2_mmap(NULL, buf.length,
+					     PROT_READ | PROT_WRITE,
+					     MAP_SHARED, stream->fd,
+					     buf.m.offset);
+
+	if (MAP_FAILED == stream->buffers[i].start) {
+	    status = pj_get_os_error();
+	    goto on_error;
+	}
+
+	stream->buf_cnt++;
+    }
+
+    PJ_LOG(5,(THIS_FILE, "  mmap streaming initialized"));
+
+    stream->io_type = IO_TYPE_MMAP;
+    return PJ_SUCCESS;
+
+on_error:
+    return status;
+}
+
+/* init streaming with user pointer */
+static pj_status_t vid4lin_stream_init_streaming_user(vid4lin_stream *stream)
+{
+    return PJ_ENOTSUP;
+}
+
+/* init streaming with read() */
+static pj_status_t vid4lin_stream_init_read_write(vid4lin_stream *stream)
+{
+    return PJ_ENOTSUP;
+}
+
+/* API: create stream */
+static pj_status_t vid4lin_factory_create_stream(pjmedia_vid_dev_factory *f,
+				      pjmedia_vid_dev_param *param,
+				      const pjmedia_vid_dev_cb *cb,
+				      void *user_data,
+				      pjmedia_vid_dev_stream **p_vid_strm)
+{
+    vid4lin_factory *cf = (vid4lin_factory*)f;
+    pj_pool_t *pool;
+    vid4lin_stream *stream;
+    vid4lin_dev_info *vdi;
+    const vid4lin_fmt_map *fmt_map;
+    const pjmedia_video_format_info *fmt_info;
+    pjmedia_video_format_detail *vfd;
+    pj_status_t status = PJ_SUCCESS;
+
+
+    PJ_ASSERT_RETURN(f && param && p_vid_strm, PJ_EINVAL);
+    PJ_ASSERT_RETURN(param->fmt.type == PJMEDIA_TYPE_VIDEO &&
+		     param->fmt.detail_type == PJMEDIA_FORMAT_DETAIL_VIDEO &&
+                     param->dir == PJMEDIA_DIR_CAPTURE,
+		     PJ_EINVAL);
+    PJ_ASSERT_RETURN(param->cap_id >= 0 && param->cap_id < cf->dev_count,
+		     PJMEDIA_EVID_INVDEV);
+
+    fmt_info = pjmedia_get_video_format_info(NULL, param->fmt.id);
+    if (!fmt_info || (fmt_map=get_v4l2_format_info(param->fmt.id))==NULL)
+        return PJMEDIA_EVID_BADFORMAT;
+
+    vdi = &cf->dev_info[param->cap_id];
+    vfd = pjmedia_format_get_video_format_detail(&param->fmt, PJ_TRUE);
+
+    /* Create and Initialize stream descriptor */
+    pool = pj_pool_create(cf->pf, vdi->info.name, 512, 512, NULL);
+    PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM);
+
+    stream = PJ_POOL_ZALLOC_T(pool, vid4lin_stream);
+    pj_memcpy(&stream->param, param, sizeof(*param));
+    stream->pool = pool;
+    pj_memcpy(&stream->vid_cb, cb, sizeof(*cb));
+    strncpy(stream->name, vdi->info.name, sizeof(stream->name));
+    stream->name[sizeof(stream->name)-1] = '\0';
+    stream->user_data = user_data;
+    stream->fd = INVALID_FD;
+
+    stream->fd = v4l2_open(vdi->dev_name, O_RDWR, 0);
+    if (stream->fd < 0)
+	goto on_error;
+
+    status = vid4lin_stream_init_fmt(stream, param, fmt_map->v4l2_fmt_id);
+    if (status != PJ_SUCCESS)
+	goto on_error;
+
+    if (vdi->v4l2_cap.capabilities & V4L2_CAP_STREAMING)
+	status = vid4lin_stream_init_streaming(stream);
+
+    if (status!=PJ_SUCCESS && vdi->v4l2_cap.capabilities & V4L2_CAP_STREAMING)
+	status = vid4lin_stream_init_streaming_user(stream);
+
+    if (status!=PJ_SUCCESS && vdi->v4l2_cap.capabilities & V4L2_CAP_READWRITE)
+	status = vid4lin_stream_init_read_write(stream);
+
+    if (status != PJ_SUCCESS) {
+	PJ_LOG(1,(THIS_FILE, "Error: unable to initiate I/O on %s",
+		  stream->name));
+	goto on_error;
+    }
+
+    /* Done */
+    stream->base.op = &stream_op;
+    *p_vid_strm = &stream->base;
+
+    return PJ_SUCCESS;
+
+on_error:
+    if (status == PJ_SUCCESS)
+	status = PJ_RETURN_OS_ERROR(errno);
+
+    vid4lin_stream_destroy(&stream->base);
+    return status;
+}
+
+/* API: Get stream info. */
+static pj_status_t vid4lin_stream_get_param(pjmedia_vid_dev_stream *s,
+					    pjmedia_vid_dev_param *pi)
+{
+    vid4lin_stream *strm = (vid4lin_stream*)s;
+
+    PJ_ASSERT_RETURN(strm && pi, PJ_EINVAL);
+
+    pj_memcpy(pi, &strm->param, sizeof(*pi));
+
+    return PJ_SUCCESS;
+}
+
+/* API: get capability */
+static pj_status_t vid4lin_stream_get_cap(pjmedia_vid_dev_stream *s,
+                                          pjmedia_vid_dev_cap cap,
+                                          void *pval)
+{
+    vid4lin_stream *strm = (vid4lin_stream*)s;
+
+    PJ_UNUSED_ARG(strm);
+
+    PJ_ASSERT_RETURN(s && pval, PJ_EINVAL);
+
+    if (cap==PJMEDIA_VID_DEV_CAP_INPUT_SCALE)
+    {
+        return PJMEDIA_EVID_INVCAP;
+//	return PJ_SUCCESS;
+    } else {
+	return PJMEDIA_EVID_INVCAP;
+    }
+}
+
+/* API: set capability */
+static pj_status_t vid4lin_stream_set_cap(pjmedia_vid_dev_stream *s,
+                                          pjmedia_vid_dev_cap cap,
+                                          const void *pval)
+{
+    vid4lin_stream *strm = (vid4lin_stream*)s;
+
+
+    PJ_ASSERT_RETURN(s && pval, PJ_EINVAL);
+
+    /*
+    if (cap==PJMEDIA_VID_DEV_CAP_INPUT_SCALE)
+    {
+	return PJ_SUCCESS;
+    }
+    */
+    PJ_UNUSED_ARG(strm);
+    PJ_UNUSED_ARG(cap);
+    PJ_UNUSED_ARG(pval);
+
+    return PJMEDIA_EVID_INVCAP;
+}
+
+/* get frame from mmap */
+static pj_status_t vid4lin_stream_get_frame_mmap(vid4lin_stream *stream,
+                                                 pjmedia_frame *frame)
+{
+    struct v4l2_buffer buf;
+    pj_time_val time;
+    pj_status_t status = PJ_SUCCESS;
+    unsigned tmp_idx;
+
+    pj_bzero(&buf, sizeof(buf));
+    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    buf.memory = V4L2_MEMORY_MMAP;
+    status = xioctl(stream->fd, VIDIOC_DQBUF, &buf);
+    if (status != PJ_SUCCESS)
+	return status;
+
+    if (frame->size < buf.bytesused) {
+	/* supplied buffer is too small */
+	pj_assert(!"frame buffer is too small for v4l2");
+	status = PJ_ETOOSMALL;
+	goto on_return;
+    }
+
+    time.sec = buf.timestamp.tv_sec;
+    time.msec = buf.timestamp.tv_usec / 1000;
+    PJ_TIME_VAL_SUB(time, stream->start_time);
+
+    frame->type = PJMEDIA_FRAME_TYPE_VIDEO;
+    frame->bit_info = 0;
+    frame->size = buf.bytesused;
+    frame->timestamp.u64 = PJ_UINT64(1) * PJ_TIME_VAL_MSEC(time) *
+			   stream->param.clock_rate / PJ_UINT64(1000);
+    pj_memcpy(frame->buf, stream->buffers[buf.index].start, buf.bytesused);
+
+on_return:
+    tmp_idx = buf.index;
+    pj_bzero(&buf, sizeof(buf));
+    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    buf.memory = V4L2_MEMORY_MMAP;
+    buf.index = tmp_idx;
+    xioctl(stream->fd, VIDIOC_QBUF, &buf);
+
+    return status;
+}
+
+/* API: Get frame from stream */
+static pj_status_t vid4lin_stream_get_frame(pjmedia_vid_dev_stream *strm,
+                                            pjmedia_frame *frame)
+{
+    vid4lin_stream *stream = (vid4lin_stream*)strm;
+
+    if (stream->io_type == IO_TYPE_MMAP)
+	return vid4lin_stream_get_frame_mmap(stream, frame);
+    else {
+	pj_assert(!"Unsupported i/o type");
+	return PJ_EINVALIDOP;
+    }
+}
+
+/* API: Start stream. */
+static pj_status_t vid4lin_stream_start(pjmedia_vid_dev_stream *strm)
+{
+    vid4lin_stream *stream = (vid4lin_stream*)strm;
+    struct v4l2_buffer buf;
+    enum v4l2_buf_type type;
+    unsigned i;
+    pj_status_t status;
+
+    PJ_ASSERT_RETURN(stream->fd != -1, PJ_EINVALIDOP);
+
+    PJ_LOG(4, (THIS_FILE, "Starting v4l2 video stream %s", stream->name));
+
+    pj_gettimeofday(&stream->start_time);
+
+    for (i = 0; i < stream->buf_cnt; ++i) {
+	pj_bzero(&buf, sizeof(buf));
+	buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	buf.memory = V4L2_MEMORY_MMAP;
+	buf.index = i;
+	status = xioctl(stream->fd, VIDIOC_QBUF, &buf);
+	if (status != PJ_SUCCESS)
+	    goto on_error;
+    }
+    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+    status = xioctl(stream->fd, VIDIOC_STREAMON, &type);
+    if (status != PJ_SUCCESS)
+	goto on_error;
+
+    return PJ_SUCCESS;
+
+on_error:
+    if (i > 0) {
+	/* Dequeue already enqueued buffers. Can we do this while streaming
+	 * is not started?
+	 */
+	unsigned n = i;
+	for (i=0; i<n; ++i) {
+	    pj_bzero(&buf, sizeof(buf));
+	    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	    buf.memory = V4L2_MEMORY_MMAP;
+	    xioctl(stream->fd, VIDIOC_DQBUF, &buf);
+	}
+    }
+    return status;
+}
+
+/* API: Stop stream. */
+static pj_status_t vid4lin_stream_stop(pjmedia_vid_dev_stream *strm)
+{
+    vid4lin_stream *stream = (vid4lin_stream*)strm;
+    enum v4l2_buf_type type;
+    pj_status_t status;
+
+    if (stream->fd < 0)
+	return PJ_SUCCESS;
+
+    PJ_LOG(4, (THIS_FILE, "Stopping v4l2 video stream %s", stream->name));
+
+    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    status = xioctl(stream->fd, VIDIOC_STREAMOFF, &type);
+    if (status != PJ_SUCCESS)
+	return status;
+
+    return PJ_SUCCESS;
+}
+
+
+/* API: Destroy stream. */
+static pj_status_t vid4lin_stream_destroy(pjmedia_vid_dev_stream *strm)
+{
+    vid4lin_stream *stream = (vid4lin_stream*)strm;
+    unsigned i;
+
+    PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL);
+
+    vid4lin_stream_stop(strm);
+
+    PJ_LOG(4, (THIS_FILE, "Destroying v4l2 video stream %s", stream->name));
+
+    for (i=0; i<stream->buf_cnt; ++i) {
+	if (stream->buffers[i].start != MAP_FAILED) {
+	    v4l2_munmap(stream->buffers[i].start, stream->buffers[i].length);
+	    stream->buffers[i].start = MAP_FAILED;
+	}
+    }
+
+    if (stream->fd >= 0) {
+	v4l2_close(stream->fd);
+	stream->fd = -1;
+    }
+    pj_pool_release(stream->pool);
+
+    return PJ_SUCCESS;
+}
+
+#endif	/* PJMEDIA_VIDEO_DEV_HAS_V4L2 */
diff --git a/jni/pjproject-android/.svn/pristine/25/2586232dac33421a5f2c81cca0eb2933c592ba50.svn-base b/jni/pjproject-android/.svn/pristine/25/2586232dac33421a5f2c81cca0eb2933c592ba50.svn-base
new file mode 100644
index 0000000..9bb760b
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/25/2586232dac33421a5f2c81cca0eb2933c592ba50.svn-base
@@ -0,0 +1,147 @@
+/* $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 __PJSIP_TRANSPORT_LOOP_H__
+#define __PJSIP_TRANSPORT_LOOP_H__
+
+
+/**
+ * @file sip_transport_loop.h
+ * @brief 
+ * Loopback transport (for debugging)
+ */
+
+
+#include <pjsip/sip_transport.h>
+
+/**
+ * @defgroup PJSIP_TRANSPORT_LOOP Loop Transport
+ * @ingroup PJSIP_TRANSPORT
+ * @brief Loopback transport (for testing purposes).
+ * @{
+ * The loopback transport simply bounce back outgoing messages as
+ * incoming messages. This feature is used mostly during automated
+ * testing, to provide controlled behavior.
+ */
+
+PJ_BEGIN_DECL
+
+/**
+ * Create and start datagram loop transport.
+ *
+ * @param endpt		The endpoint instance.
+ * @param transport	Pointer to receive the transport instance.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_loop_start( pjsip_endpoint *endpt,
+				       pjsip_transport **transport);
+
+
+/**
+ * Enable/disable flag to discard any packets sent using the specified
+ * loop transport.
+ *
+ * @param tp		The loop transport.
+ * @param discard	If non-zero, any outgoing packets will be discarded.
+ * @param prev_value	Optional argument to receive previous value of
+ *			the discard flag.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_loop_set_discard( pjsip_transport *tp,
+					     pj_bool_t discard,
+					     pj_bool_t *prev_value );
+
+
+/**
+ * Enable/disable flag to simulate network error. When this flag is set,
+ * outgoing transmission will return either immediate error or error via
+ * callback. If error is to be notified via callback, then the notification
+ * will occur after some delay, which is controlled by #pjsip_loop_set_delay().
+ *
+ * @param tp		The loop transport.
+ * @param fail_flag	If set to 1, the transport will return fail to deliver
+ *			the message. If delay is zero, failure will occur
+ *			immediately; otherwise it will be reported in callback.
+ *			If set to zero, the transport will successfully deliver
+ *			the packet.
+ * @param prev_value	Optional argument to receive previous value of
+ *			the failure flag.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_loop_set_failure( pjsip_transport *tp,
+					     int fail_flag,
+					     int *prev_value );
+
+
+/**
+ * Set delay (in miliseconds) before packet is received by the other end
+ * of the loop transport. This will also 
+ * control the delay for error notification callback.
+ *
+ * @param tp		The loop transport.
+ * @param delay		Delay, in miliseconds.
+ * @param prev_value	Optional argument to receive previous value of the
+ *			delay.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_loop_set_recv_delay( pjsip_transport *tp,
+						unsigned delay,
+						unsigned *prev_value);
+
+
+/**
+ * Set delay (in miliseconds) before send notification is delivered to sender.
+ * This will also control the delay for error notification callback.
+ *
+ * @param tp		The loop transport.
+ * @param delay		Delay, in miliseconds.
+ * @param prev_value	Optional argument to receive previous value of the
+ *			delay.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_loop_set_send_callback_delay( pjsip_transport *tp,
+							 unsigned delay,
+							 unsigned *prev_value);
+
+
+/**
+ * Set both receive and send notification delay.
+ *
+ * @param tp		The loop transport.
+ * @param delay		Delay, in miliseconds.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_loop_set_delay( pjsip_transport *tp,
+					   unsigned delay );
+
+
+PJ_END_DECL
+
+/**
+ * @}
+ */
+
+#endif	/* __PJSIP_TRANSPORT_LOOP_H__ */
+
diff --git a/jni/pjproject-android/.svn/pristine/25/25a47d060db4aac66812983663f5e09036acca9b.svn-base b/jni/pjproject-android/.svn/pristine/25/25a47d060db4aac66812983663f5e09036acca9b.svn-base
new file mode 100644
index 0000000..b8d8126
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/25/25a47d060db4aac66812983663f5e09036acca9b.svn-base
@@ -0,0 +1,208 @@
+/* $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 __PJSIP_XFER_H__
+#define __PJSIP_XFER_H__
+
+
+
+/**
+ * @file sip_xfer.h
+ * @brief SIP Transfer (REFER, RFC 3515)
+ */
+#include <pjsip-simple/evsub.h>
+#include <pjsip/sip_msg.h>
+
+/**
+ * @defgroup PJSUA_XFER SIP REFER (RFC 3515) for Call Transfer etc.
+ * @ingroup PJSIP_HIGH_UA
+ * @brief SIP REFER dialog usage (call transfer, etc.)
+ * @{
+ *
+ * This describes a generic handling of SIP REFER request. The SIP REFER
+ * request is described in RFC 3515, and commonly used to perform call
+ * transfer functionality. Other types of SIP REFER usages are described
+ * in draft-worley-sip-many-refers-00 draft, for example:
+ *  - Remote Dial: where UAC sends REFER to instruct REFER recipient to
+ *    initiate an INVITE session to some target.
+ * 
+ * A REFER request can be sent inside or outside existing dialog context,
+ * although for call transfer case, it is more common to send REFER inside
+ * existing INVITE session context. PJSIP supports both sending REFER request
+ * inside or outside dialog context.
+ *
+ * The REFER framework uses @ref PJSIP_EVENT_NOT to manage the event
+ * subscription created by the REFER request. Because of this, application 
+ * must link with <b>pjsip-ua</b> AND <b>pjsip-simple</b> static libraries 
+ * to use REFER functionality.
+ *
+ * Reference:
+ *  - <A HREF="http://www.ietf.org/rfc/rfc3515.txt">RFC 3515: The Session 
+ *    Initiation Protocol (SIP) Refer Method</A>
+ *  - @ref PJSIP_EVENT_NOT
+ */
+
+
+PJ_BEGIN_DECL
+
+
+/** Declaration for REFER method constant. */
+PJ_DECL_DATA(const pjsip_method) pjsip_refer_method;
+
+/** Get REFER method constant */
+PJ_DECL(const pjsip_method*) pjsip_get_refer_method(void);
+
+
+/**
+ * Initialize the REFER subsystem.
+ * This currently does very little (only register REFER as supported method).
+ */
+PJ_DECL(pj_status_t) pjsip_xfer_init_module(pjsip_endpoint *endpt);
+
+
+
+/**
+ * Create transferer (sender of REFER request).
+ *
+ * @param dlg		The underlying dialog to use.
+ * @param user_cb	Pointer to callbacks to receive presence subscription
+ *			events.
+ * @param p_evsub	Pointer to receive the presence subscription
+ *			session.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_xfer_create_uac( pjsip_dialog *dlg,
+					    const pjsip_evsub_user *user_cb,
+					    pjsip_evsub **p_evsub );
+
+
+/**
+ * Create transferee (receiver of REFER request).
+ *
+ * @param dlg		The underlying dialog to use.
+ * @param user_cb	Pointer to callbacks to receive presence subscription
+ *			events.
+ * @param rdata		The incoming SUBSCRIBE request that creates the event 
+ *			subscription.
+ * @param p_evsub	Pointer to receive the presence subscription
+ *			session.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_xfer_create_uas( pjsip_dialog *dlg,
+					    const pjsip_evsub_user *user_cb,
+					    pjsip_rx_data *rdata,
+					    pjsip_evsub **p_evsub );
+
+/**
+ * Call this function to create request to initiate REFER subscription,
+ * to refresh subscription, or to unsubscribe. For request other than
+ * the initial REFER request, "refer_to_uri" argument may be NULL.
+ *
+ * @param sub		Client subscription instance.
+ * @param refer_to_uri	URI to be put to the Refer-To header. This argument
+ *			may be NULL for subsequent REFER requests.
+ * @param p_tdata	Pointer to receive the request.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_xfer_initiate( pjsip_evsub *sub,
+					  const pj_str_t *refer_to_uri,
+					  pjsip_tx_data **p_tdata);
+
+
+/**
+ * Accept the incoming REFER request by sending 2xx response.
+ *
+ * @param sub		Server subscription instance.
+ * @param rdata		The incoming subscription request message.
+ * @param st_code	Status code, which MUST be 2xx.
+ * @param hdr_list	Optional list of headers to be added in the response.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_xfer_accept( pjsip_evsub *sub,
+					pjsip_rx_data *rdata,
+				        int st_code,
+					const pjsip_hdr *hdr_list );
+
+
+/**
+ * For notifier, create NOTIFY request to subscriber, and set the state 
+ * of the subscription. 
+ *
+ * @param sub		The server subscription (notifier) instance.
+ * @param state		New state to set.
+ * @param xfer_st_code	The call status code to be reported with the NOTIFY
+ *			request.
+ * @param xfer_st_text	Optional call status text to be reported with the 
+ *			NOTIFY request. If the value is NULL, default 
+ *			status text will be used.
+ * @param p_tdata	Pointer to receive the request.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_xfer_notify( pjsip_evsub *sub,
+					pjsip_evsub_state state,
+					int xfer_st_code,
+					const pj_str_t *xfer_st_text,
+					pjsip_tx_data **p_tdata);
+
+
+/**
+ * Create NOTIFY request to reflect current subscription status. Application
+ * can only call this function after it has sent NOTIFY before.
+ * This will also re-send the last "message/sipfrag" body that was sent
+ * in the previous NOTIFY.
+ *
+ * @param sub		Server subscription object.
+ * @param p_tdata	Pointer to receive request.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_xfer_current_notify( pjsip_evsub *sub,
+					        pjsip_tx_data **p_tdata );
+
+
+
+/**
+ * Send request message that was previously created with initiate(), notify(),
+ * or current_notify(). Application may also send request created with other
+ * functions, e.g. authentication. But the request MUST be either request
+ * that creates/refresh subscription or NOTIFY request.
+ *
+ *
+ * @param sub		The event subscription object.
+ * @param tdata		Request message to be send.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_xfer_send_request( pjsip_evsub *sub,
+					      pjsip_tx_data *tdata);
+
+
+PJ_END_DECL
+
+/**
+ * @}
+ */
+
+#endif	/* __PJSIP_XFER_H__ */
+
diff --git a/jni/pjproject-android/.svn/pristine/25/25afa02a75d73733e6453c108b8362ab7c5581a9.svn-base b/jni/pjproject-android/.svn/pristine/25/25afa02a75d73733e6453c108b8362ab7c5581a9.svn-base
new file mode 100644
index 0000000..4cb9f22
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/25/25afa02a75d73733e6453c108b8362ab7c5581a9.svn-base
@@ -0,0 +1,1277 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <pjlib.h>
+#include <pjlib-util.h>
+#include <pjnath.h>
+
+
+#define THIS_FILE   "icedemo.c"
+
+/* For this demo app, configure longer STUN keep-alive time
+ * so that it does't clutter the screen output.
+ */
+#define KA_INTERVAL 300
+
+
+/* This is our global variables */
+static struct app_t
+{
+    /* Command line options are stored here */
+    struct options
+    {
+	unsigned    comp_cnt;
+	pj_str_t    ns;
+	int	    max_host;
+	pj_bool_t   regular;
+	pj_str_t    stun_srv;
+	pj_str_t    turn_srv;
+	pj_bool_t   turn_tcp;
+	pj_str_t    turn_username;
+	pj_str_t    turn_password;
+	pj_bool_t   turn_fingerprint;
+	const char *log_file;
+    } opt;
+
+    /* Our global variables */
+    pj_caching_pool	 cp;
+    pj_pool_t		*pool;
+    pj_thread_t		*thread;
+    pj_bool_t		 thread_quit_flag;
+    pj_ice_strans_cfg	 ice_cfg;
+    pj_ice_strans	*icest;
+    FILE		*log_fhnd;
+
+    /* Variables to store parsed remote ICE info */
+    struct rem_info
+    {
+	char		 ufrag[80];
+	char		 pwd[80];
+	unsigned	 comp_cnt;
+	pj_sockaddr	 def_addr[PJ_ICE_MAX_COMP];
+	unsigned	 cand_cnt;
+	pj_ice_sess_cand cand[PJ_ICE_ST_MAX_CAND];
+    } rem;
+
+} icedemo;
+
+/* Utility to display error messages */
+static void icedemo_perror(const char *title, pj_status_t status)
+{
+    char errmsg[PJ_ERR_MSG_SIZE];
+
+    pj_strerror(status, errmsg, sizeof(errmsg));
+    PJ_LOG(1,(THIS_FILE, "%s: %s", title, errmsg));
+}
+
+/* Utility: display error message and exit application (usually
+ * because of fatal error.
+ */
+static void err_exit(const char *title, pj_status_t status)
+{
+    if (status != PJ_SUCCESS) {
+	icedemo_perror(title, status);
+    }
+    PJ_LOG(3,(THIS_FILE, "Shutting down.."));
+
+    if (icedemo.icest)
+	pj_ice_strans_destroy(icedemo.icest);
+    
+    pj_thread_sleep(500);
+
+    icedemo.thread_quit_flag = PJ_TRUE;
+    if (icedemo.thread) {
+	pj_thread_join(icedemo.thread);
+	pj_thread_destroy(icedemo.thread);
+    }
+
+    if (icedemo.ice_cfg.stun_cfg.ioqueue)
+	pj_ioqueue_destroy(icedemo.ice_cfg.stun_cfg.ioqueue);
+
+    if (icedemo.ice_cfg.stun_cfg.timer_heap)
+	pj_timer_heap_destroy(icedemo.ice_cfg.stun_cfg.timer_heap);
+
+    pj_caching_pool_destroy(&icedemo.cp);
+
+    pj_shutdown();
+
+    if (icedemo.log_fhnd) {
+	fclose(icedemo.log_fhnd);
+	icedemo.log_fhnd = NULL;
+    }
+
+    exit(status != PJ_SUCCESS);
+}
+
+#define CHECK(expr)	status=expr; \
+			if (status!=PJ_SUCCESS) { \
+			    err_exit(#expr, status); \
+			}
+
+/*
+ * This function checks for events from both timer and ioqueue (for
+ * network events). It is invoked by the worker thread.
+ */
+static pj_status_t handle_events(unsigned max_msec, unsigned *p_count)
+{
+    enum { MAX_NET_EVENTS = 1 };
+    pj_time_val max_timeout = {0, 0};
+    pj_time_val timeout = { 0, 0};
+    unsigned count = 0, net_event_count = 0;
+    int c;
+
+    max_timeout.msec = max_msec;
+
+    /* Poll the timer to run it and also to retrieve the earliest entry. */
+    timeout.sec = timeout.msec = 0;
+    c = pj_timer_heap_poll( icedemo.ice_cfg.stun_cfg.timer_heap, &timeout );
+    if (c > 0)
+	count += c;
+
+    /* timer_heap_poll should never ever returns negative value, or otherwise
+     * ioqueue_poll() will block forever!
+     */
+    pj_assert(timeout.sec >= 0 && timeout.msec >= 0);
+    if (timeout.msec >= 1000) timeout.msec = 999;
+
+    /* compare the value with the timeout to wait from timer, and use the 
+     * minimum value. 
+    */
+    if (PJ_TIME_VAL_GT(timeout, max_timeout))
+	timeout = max_timeout;
+
+    /* Poll ioqueue. 
+     * Repeat polling the ioqueue while we have immediate events, because
+     * timer heap may process more than one events, so if we only process
+     * one network events at a time (such as when IOCP backend is used),
+     * the ioqueue may have trouble keeping up with the request rate.
+     *
+     * For example, for each send() request, one network event will be
+     *   reported by ioqueue for the send() completion. If we don't poll
+     *   the ioqueue often enough, the send() completion will not be
+     *   reported in timely manner.
+     */
+    do {
+	c = pj_ioqueue_poll( icedemo.ice_cfg.stun_cfg.ioqueue, &timeout);
+	if (c < 0) {
+	    pj_status_t err = pj_get_netos_error();
+	    pj_thread_sleep(PJ_TIME_VAL_MSEC(timeout));
+	    if (p_count)
+		*p_count = count;
+	    return err;
+	} else if (c == 0) {
+	    break;
+	} else {
+	    net_event_count += c;
+	    timeout.sec = timeout.msec = 0;
+	}
+    } while (c > 0 && net_event_count < MAX_NET_EVENTS);
+
+    count += net_event_count;
+    if (p_count)
+	*p_count = count;
+
+    return PJ_SUCCESS;
+
+}
+
+/*
+ * This is the worker thread that polls event in the background.
+ */
+static int icedemo_worker_thread(void *unused)
+{
+    PJ_UNUSED_ARG(unused);
+
+    while (!icedemo.thread_quit_flag) {
+	handle_events(500, NULL);
+    }
+
+    return 0;
+}
+
+/*
+ * This is the callback that is registered to the ICE stream transport to
+ * receive notification about incoming data. By "data" it means application
+ * data such as RTP/RTCP, and not packets that belong to ICE signaling (such
+ * as STUN connectivity checks or TURN signaling).
+ */
+static void cb_on_rx_data(pj_ice_strans *ice_st,
+			  unsigned comp_id, 
+			  void *pkt, pj_size_t size,
+			  const pj_sockaddr_t *src_addr,
+			  unsigned src_addr_len)
+{
+    char ipstr[PJ_INET6_ADDRSTRLEN+10];
+
+    PJ_UNUSED_ARG(ice_st);
+    PJ_UNUSED_ARG(src_addr_len);
+    PJ_UNUSED_ARG(pkt);
+
+    // Don't do this! It will ruin the packet buffer in case TCP is used!
+    //((char*)pkt)[size] = '\0';
+
+    PJ_LOG(3,(THIS_FILE, "Component %d: received %d bytes data from %s: \"%.*s\"",
+	      comp_id, size,
+	      pj_sockaddr_print(src_addr, ipstr, sizeof(ipstr), 3),
+	      (unsigned)size,
+	      (char*)pkt));
+}
+
+/*
+ * This is the callback that is registered to the ICE stream transport to
+ * receive notification about ICE state progression.
+ */
+static void cb_on_ice_complete(pj_ice_strans *ice_st, 
+			       pj_ice_strans_op op,
+			       pj_status_t status)
+{
+    const char *opname = 
+	(op==PJ_ICE_STRANS_OP_INIT? "initialization" :
+	    (op==PJ_ICE_STRANS_OP_NEGOTIATION ? "negotiation" : "unknown_op"));
+
+    if (status == PJ_SUCCESS) {
+	PJ_LOG(3,(THIS_FILE, "ICE %s successful", opname));
+    } else {
+	char errmsg[PJ_ERR_MSG_SIZE];
+
+	pj_strerror(status, errmsg, sizeof(errmsg));
+	PJ_LOG(1,(THIS_FILE, "ICE %s failed: %s", opname, errmsg));
+	pj_ice_strans_destroy(ice_st);
+	icedemo.icest = NULL;
+    }
+}
+
+/* log callback to write to file */
+static void log_func(int level, const char *data, int len)
+{
+    pj_log_write(level, data, len);
+    if (icedemo.log_fhnd) {
+	if (fwrite(data, len, 1, icedemo.log_fhnd) != 1)
+	    return;
+    }
+}
+
+/*
+ * This is the main application initialization function. It is called
+ * once (and only once) during application initialization sequence by 
+ * main().
+ */
+static pj_status_t icedemo_init(void)
+{
+    pj_status_t status;
+
+    if (icedemo.opt.log_file) {
+	icedemo.log_fhnd = fopen(icedemo.opt.log_file, "a");
+	pj_log_set_log_func(&log_func);
+    }
+
+    /* Initialize the libraries before anything else */
+    CHECK( pj_init() );
+    CHECK( pjlib_util_init() );
+    CHECK( pjnath_init() );
+
+    /* Must create pool factory, where memory allocations come from */
+    pj_caching_pool_init(&icedemo.cp, NULL, 0);
+
+    /* Init our ICE settings with null values */
+    pj_ice_strans_cfg_default(&icedemo.ice_cfg);
+
+    icedemo.ice_cfg.stun_cfg.pf = &icedemo.cp.factory;
+
+    /* Create application memory pool */
+    icedemo.pool = pj_pool_create(&icedemo.cp.factory, "icedemo", 
+				  512, 512, NULL);
+
+    /* Create timer heap for timer stuff */
+    CHECK( pj_timer_heap_create(icedemo.pool, 100, 
+				&icedemo.ice_cfg.stun_cfg.timer_heap) );
+
+    /* and create ioqueue for network I/O stuff */
+    CHECK( pj_ioqueue_create(icedemo.pool, 16, 
+			     &icedemo.ice_cfg.stun_cfg.ioqueue) );
+
+    /* something must poll the timer heap and ioqueue, 
+     * unless we're on Symbian where the timer heap and ioqueue run
+     * on themselves.
+     */
+    CHECK( pj_thread_create(icedemo.pool, "icedemo", &icedemo_worker_thread,
+			    NULL, 0, 0, &icedemo.thread) );
+
+    icedemo.ice_cfg.af = pj_AF_INET();
+
+    /* Create DNS resolver if nameserver is set */
+    if (icedemo.opt.ns.slen) {
+	CHECK( pj_dns_resolver_create(&icedemo.cp.factory, 
+				      "resolver", 
+				      0, 
+				      icedemo.ice_cfg.stun_cfg.timer_heap,
+				      icedemo.ice_cfg.stun_cfg.ioqueue, 
+				      &icedemo.ice_cfg.resolver) );
+
+	CHECK( pj_dns_resolver_set_ns(icedemo.ice_cfg.resolver, 1, 
+				      &icedemo.opt.ns, NULL) );
+    }
+
+    /* -= Start initializing ICE stream transport config =- */
+
+    /* Maximum number of host candidates */
+    if (icedemo.opt.max_host != -1)
+	icedemo.ice_cfg.stun.max_host_cands = icedemo.opt.max_host;
+
+    /* Nomination strategy */
+    if (icedemo.opt.regular)
+	icedemo.ice_cfg.opt.aggressive = PJ_FALSE;
+    else
+	icedemo.ice_cfg.opt.aggressive = PJ_TRUE;
+
+    /* Configure STUN/srflx candidate resolution */
+    if (icedemo.opt.stun_srv.slen) {
+	char *pos;
+
+	/* Command line option may contain port number */
+	if ((pos=pj_strchr(&icedemo.opt.stun_srv, ':')) != NULL) {
+	    icedemo.ice_cfg.stun.server.ptr = icedemo.opt.stun_srv.ptr;
+	    icedemo.ice_cfg.stun.server.slen = (pos - icedemo.opt.stun_srv.ptr);
+
+	    icedemo.ice_cfg.stun.port = (pj_uint16_t)atoi(pos+1);
+	} else {
+	    icedemo.ice_cfg.stun.server = icedemo.opt.stun_srv;
+	    icedemo.ice_cfg.stun.port = PJ_STUN_PORT;
+	}
+
+	/* For this demo app, configure longer STUN keep-alive time
+	 * so that it does't clutter the screen output.
+	 */
+	icedemo.ice_cfg.stun.cfg.ka_interval = KA_INTERVAL;
+    }
+
+    /* Configure TURN candidate */
+    if (icedemo.opt.turn_srv.slen) {
+	char *pos;
+
+	/* Command line option may contain port number */
+	if ((pos=pj_strchr(&icedemo.opt.turn_srv, ':')) != NULL) {
+	    icedemo.ice_cfg.turn.server.ptr = icedemo.opt.turn_srv.ptr;
+	    icedemo.ice_cfg.turn.server.slen = (pos - icedemo.opt.turn_srv.ptr);
+
+	    icedemo.ice_cfg.turn.port = (pj_uint16_t)atoi(pos+1);
+	} else {
+	    icedemo.ice_cfg.turn.server = icedemo.opt.turn_srv;
+	    icedemo.ice_cfg.turn.port = PJ_STUN_PORT;
+	}
+
+	/* TURN credential */
+	icedemo.ice_cfg.turn.auth_cred.type = PJ_STUN_AUTH_CRED_STATIC;
+	icedemo.ice_cfg.turn.auth_cred.data.static_cred.username = icedemo.opt.turn_username;
+	icedemo.ice_cfg.turn.auth_cred.data.static_cred.data_type = PJ_STUN_PASSWD_PLAIN;
+	icedemo.ice_cfg.turn.auth_cred.data.static_cred.data = icedemo.opt.turn_password;
+
+	/* Connection type to TURN server */
+	if (icedemo.opt.turn_tcp)
+	    icedemo.ice_cfg.turn.conn_type = PJ_TURN_TP_TCP;
+	else
+	    icedemo.ice_cfg.turn.conn_type = PJ_TURN_TP_UDP;
+
+	/* For this demo app, configure longer keep-alive time
+	 * so that it does't clutter the screen output.
+	 */
+	icedemo.ice_cfg.turn.alloc_param.ka_interval = KA_INTERVAL;
+    }
+
+    /* -= That's it for now, initialization is complete =- */
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Create ICE stream transport instance, invoked from the menu.
+ */
+static void icedemo_create_instance(void)
+{
+    pj_ice_strans_cb icecb;
+    pj_status_t status;
+
+    if (icedemo.icest != NULL) {
+	puts("ICE instance already created, destroy it first");
+	return;
+    }
+
+    /* init the callback */
+    pj_bzero(&icecb, sizeof(icecb));
+    icecb.on_rx_data = cb_on_rx_data;
+    icecb.on_ice_complete = cb_on_ice_complete;
+
+    /* create the instance */
+    status = pj_ice_strans_create("icedemo",		    /* object name  */
+				&icedemo.ice_cfg,	    /* settings	    */
+				icedemo.opt.comp_cnt,	    /* comp_cnt	    */
+				NULL,			    /* user data    */
+				&icecb,			    /* callback	    */
+				&icedemo.icest)		    /* instance ptr */
+				;
+    if (status != PJ_SUCCESS)
+	icedemo_perror("error creating ice", status);
+    else
+	PJ_LOG(3,(THIS_FILE, "ICE instance successfully created"));
+}
+
+/* Utility to nullify parsed remote info */
+static void reset_rem_info(void)
+{
+    pj_bzero(&icedemo.rem, sizeof(icedemo.rem));
+}
+
+
+/*
+ * Destroy ICE stream transport instance, invoked from the menu.
+ */
+static void icedemo_destroy_instance(void)
+{
+    if (icedemo.icest == NULL) {
+	PJ_LOG(1,(THIS_FILE, "Error: No ICE instance, create it first"));
+	return;
+    }
+
+    pj_ice_strans_destroy(icedemo.icest);
+    icedemo.icest = NULL;
+
+    reset_rem_info();
+
+    PJ_LOG(3,(THIS_FILE, "ICE instance destroyed"));
+}
+
+
+/*
+ * Create ICE session, invoked from the menu.
+ */
+static void icedemo_init_session(unsigned rolechar)
+{
+    pj_ice_sess_role role = (pj_tolower((pj_uint8_t)rolechar)=='o' ? 
+				PJ_ICE_SESS_ROLE_CONTROLLING : 
+				PJ_ICE_SESS_ROLE_CONTROLLED);
+    pj_status_t status;
+
+    if (icedemo.icest == NULL) {
+	PJ_LOG(1,(THIS_FILE, "Error: No ICE instance, create it first"));
+	return;
+    }
+
+    if (pj_ice_strans_has_sess(icedemo.icest)) {
+	PJ_LOG(1,(THIS_FILE, "Error: Session already created"));
+	return;
+    }
+
+    status = pj_ice_strans_init_ice(icedemo.icest, role, NULL, NULL);
+    if (status != PJ_SUCCESS)
+	icedemo_perror("error creating session", status);
+    else
+	PJ_LOG(3,(THIS_FILE, "ICE session created"));
+
+    reset_rem_info();
+}
+
+
+/*
+ * Stop/destroy ICE session, invoked from the menu.
+ */
+static void icedemo_stop_session(void)
+{
+    pj_status_t status;
+
+    if (icedemo.icest == NULL) {
+	PJ_LOG(1,(THIS_FILE, "Error: No ICE instance, create it first"));
+	return;
+    }
+
+    if (!pj_ice_strans_has_sess(icedemo.icest)) {
+	PJ_LOG(1,(THIS_FILE, "Error: No ICE session, initialize first"));
+	return;
+    }
+
+    status = pj_ice_strans_stop_ice(icedemo.icest);
+    if (status != PJ_SUCCESS)
+	icedemo_perror("error stopping session", status);
+    else
+	PJ_LOG(3,(THIS_FILE, "ICE session stopped"));
+
+    reset_rem_info();
+}
+
+#define PRINT(fmt, arg0, arg1, arg2, arg3, arg4, arg5)	    \
+	printed = pj_ansi_snprintf(p, maxlen - (p-buffer),  \
+				   fmt, arg0, arg1, arg2, arg3, arg4, arg5); \
+	if (printed <= 0) return -PJ_ETOOSMALL; \
+	p += printed
+
+
+/* Utility to create a=candidate SDP attribute */
+static int print_cand(char buffer[], unsigned maxlen,
+		      const pj_ice_sess_cand *cand)
+{
+    char ipaddr[PJ_INET6_ADDRSTRLEN];
+    char *p = buffer;
+    int printed;
+
+    PRINT("a=candidate:%.*s %u UDP %u %s %u typ ",
+	  (int)cand->foundation.slen,
+	  cand->foundation.ptr,
+	  (unsigned)cand->comp_id,
+	  cand->prio,
+	  pj_sockaddr_print(&cand->addr, ipaddr, 
+			    sizeof(ipaddr), 0),
+	  (unsigned)pj_sockaddr_get_port(&cand->addr));
+
+    PRINT("%s\n",
+	  pj_ice_get_cand_type_name(cand->type),
+	  0, 0, 0, 0, 0);
+
+    if (p == buffer+maxlen)
+	return -PJ_ETOOSMALL;
+
+    *p = '\0';
+
+    return (int)(p-buffer);
+}
+
+/* 
+ * Encode ICE information in SDP.
+ */
+static int encode_session(char buffer[], unsigned maxlen)
+{
+    char *p = buffer;
+    unsigned comp;
+    int printed;
+    pj_str_t local_ufrag, local_pwd;
+    pj_status_t status;
+
+    /* Write "dummy" SDP v=, o=, s=, and t= lines */
+    PRINT("v=0\no=- 3414953978 3414953978 IN IP4 localhost\ns=ice\nt=0 0\n", 
+	  0, 0, 0, 0, 0, 0);
+
+    /* Get ufrag and pwd from current session */
+    pj_ice_strans_get_ufrag_pwd(icedemo.icest, &local_ufrag, &local_pwd,
+				NULL, NULL);
+
+    /* Write the a=ice-ufrag and a=ice-pwd attributes */
+    PRINT("a=ice-ufrag:%.*s\na=ice-pwd:%.*s\n",
+	   (int)local_ufrag.slen,
+	   local_ufrag.ptr,
+	   (int)local_pwd.slen,
+	   local_pwd.ptr, 
+	   0, 0);
+
+    /* Write each component */
+    for (comp=0; comp<icedemo.opt.comp_cnt; ++comp) {
+	unsigned j, cand_cnt;
+	pj_ice_sess_cand cand[PJ_ICE_ST_MAX_CAND];
+	char ipaddr[PJ_INET6_ADDRSTRLEN];
+
+	/* Get default candidate for the component */
+	status = pj_ice_strans_get_def_cand(icedemo.icest, comp+1, &cand[0]);
+	if (status != PJ_SUCCESS)
+	    return -status;
+
+	/* Write the default address */
+	if (comp==0) {
+	    /* For component 1, default address is in m= and c= lines */
+	    PRINT("m=audio %d RTP/AVP 0\n"
+		  "c=IN IP4 %s\n",
+		  (int)pj_sockaddr_get_port(&cand[0].addr),
+		  pj_sockaddr_print(&cand[0].addr, ipaddr,
+				    sizeof(ipaddr), 0),
+		  0, 0, 0, 0);
+	} else if (comp==1) {
+	    /* For component 2, default address is in a=rtcp line */
+	    PRINT("a=rtcp:%d IN IP4 %s\n",
+		  (int)pj_sockaddr_get_port(&cand[0].addr),
+		  pj_sockaddr_print(&cand[0].addr, ipaddr,
+				    sizeof(ipaddr), 0),
+		  0, 0, 0, 0);
+	} else {
+	    /* For other components, we'll just invent this.. */
+	    PRINT("a=Xice-defcand:%d IN IP4 %s\n",
+		  (int)pj_sockaddr_get_port(&cand[0].addr),
+		  pj_sockaddr_print(&cand[0].addr, ipaddr,
+				    sizeof(ipaddr), 0),
+		  0, 0, 0, 0);
+	}
+
+	/* Enumerate all candidates for this component */
+	cand_cnt = PJ_ARRAY_SIZE(cand);
+	status = pj_ice_strans_enum_cands(icedemo.icest, comp+1,
+					  &cand_cnt, cand);
+	if (status != PJ_SUCCESS)
+	    return -status;
+
+	/* And encode the candidates as SDP */
+	for (j=0; j<cand_cnt; ++j) {
+	    printed = print_cand(p, maxlen - (unsigned)(p-buffer), &cand[j]);
+	    if (printed < 0)
+		return -PJ_ETOOSMALL;
+	    p += printed;
+	}
+    }
+
+    if (p == buffer+maxlen)
+	return -PJ_ETOOSMALL;
+
+    *p = '\0';
+    return (int)(p - buffer);
+}
+
+
+/*
+ * Show information contained in the ICE stream transport. This is
+ * invoked from the menu.
+ */
+static void icedemo_show_ice(void)
+{
+    static char buffer[1000];
+    int len;
+
+    if (icedemo.icest == NULL) {
+	PJ_LOG(1,(THIS_FILE, "Error: No ICE instance, create it first"));
+	return;
+    }
+
+    puts("General info");
+    puts("---------------");
+    printf("Component count    : %d\n", icedemo.opt.comp_cnt);
+    printf("Status             : ");
+    if (pj_ice_strans_sess_is_complete(icedemo.icest))
+	puts("negotiation complete");
+    else if (pj_ice_strans_sess_is_running(icedemo.icest))
+	puts("negotiation is in progress");
+    else if (pj_ice_strans_has_sess(icedemo.icest))
+	puts("session ready");
+    else
+	puts("session not created");
+
+    if (!pj_ice_strans_has_sess(icedemo.icest)) {
+	puts("Create the session first to see more info");
+	return;
+    }
+
+    printf("Negotiated comp_cnt: %d\n", 
+	   pj_ice_strans_get_running_comp_cnt(icedemo.icest));
+    printf("Role               : %s\n",
+	   pj_ice_strans_get_role(icedemo.icest)==PJ_ICE_SESS_ROLE_CONTROLLED ?
+	   "controlled" : "controlling");
+
+    len = encode_session(buffer, sizeof(buffer));
+    if (len < 0)
+	err_exit("not enough buffer to show ICE status", -len);
+
+    puts("");
+    printf("Local SDP (paste this to remote host):\n"
+	   "--------------------------------------\n"
+	   "%s\n", buffer);
+
+
+    puts("");
+    puts("Remote info:\n"
+	 "----------------------");
+    if (icedemo.rem.cand_cnt==0) {
+	puts("No remote info yet");
+    } else {
+	unsigned i;
+
+	printf("Remote ufrag       : %s\n", icedemo.rem.ufrag);
+	printf("Remote password    : %s\n", icedemo.rem.pwd);
+	printf("Remote cand. cnt.  : %d\n", icedemo.rem.cand_cnt);
+
+	for (i=0; i<icedemo.rem.cand_cnt; ++i) {
+	    len = print_cand(buffer, sizeof(buffer), &icedemo.rem.cand[i]);
+	    if (len < 0)
+		err_exit("not enough buffer to show ICE status", -len);
+
+	    printf("  %s", buffer);
+	}
+    }
+}
+
+
+/*
+ * Input and parse SDP from the remote (containing remote's ICE information) 
+ * and save it to global variables.
+ */
+static void icedemo_input_remote(void)
+{
+    char linebuf[80];
+    unsigned media_cnt = 0;
+    unsigned comp0_port = 0;
+    char     comp0_addr[80];
+    pj_bool_t done = PJ_FALSE;
+
+    puts("Paste SDP from remote host, end with empty line");
+
+    reset_rem_info();
+
+    comp0_addr[0] = '\0';
+
+    while (!done) {
+	pj_size_t len;
+	char *line;
+
+	printf(">");
+	if (stdout) fflush(stdout);
+
+	if (fgets(linebuf, sizeof(linebuf), stdin)==NULL)
+	    break;
+
+	len = strlen(linebuf);
+	while (len && (linebuf[len-1] == '\r' || linebuf[len-1] == '\n'))
+	    linebuf[--len] = '\0';
+
+	line = linebuf;
+	while (len && pj_isspace(*line))
+	    ++line, --len;
+
+	if (len==0)
+	    break;
+
+	/* Ignore subsequent media descriptors */
+	if (media_cnt > 1)
+	    continue;
+
+	switch (line[0]) {
+	case 'm':
+	    {
+		int cnt;
+		char media[32], portstr[32];
+
+		++media_cnt;
+		if (media_cnt > 1) {
+		    puts("Media line ignored");
+		    break;
+		}
+
+		cnt = sscanf(line+2, "%s %s RTP/", media, portstr);
+		if (cnt != 2) {
+		    PJ_LOG(1,(THIS_FILE, "Error parsing media line"));
+		    goto on_error;
+		}
+
+		comp0_port = atoi(portstr);
+		
+	    }
+	    break;
+	case 'c':
+	    {
+		int cnt;
+		char c[32], net[32], ip[80];
+		
+		cnt = sscanf(line+2, "%s %s %s", c, net, ip);
+		if (cnt != 3) {
+		    PJ_LOG(1,(THIS_FILE, "Error parsing connection line"));
+		    goto on_error;
+		}
+
+		strcpy(comp0_addr, ip);
+	    }
+	    break;
+	case 'a':
+	    {
+		char *attr = strtok(line+2, ": \t\r\n");
+		if (strcmp(attr, "ice-ufrag")==0) {
+		    strcpy(icedemo.rem.ufrag, attr+strlen(attr)+1);
+		} else if (strcmp(attr, "ice-pwd")==0) {
+		    strcpy(icedemo.rem.pwd, attr+strlen(attr)+1);
+		} else if (strcmp(attr, "rtcp")==0) {
+		    char *val = attr+strlen(attr)+1;
+		    int af, cnt;
+		    int port;
+		    char net[32], ip[64];
+		    pj_str_t tmp_addr;
+		    pj_status_t status;
+
+		    cnt = sscanf(val, "%d IN %s %s", &port, net, ip);
+		    if (cnt != 3) {
+			PJ_LOG(1,(THIS_FILE, "Error parsing rtcp attribute"));
+			goto on_error;
+		    }
+
+		    if (strchr(ip, ':'))
+			af = pj_AF_INET6();
+		    else
+			af = pj_AF_INET();
+
+		    pj_sockaddr_init(af, &icedemo.rem.def_addr[1], NULL, 0);
+		    tmp_addr = pj_str(ip);
+		    status = pj_sockaddr_set_str_addr(af, &icedemo.rem.def_addr[1],
+						      &tmp_addr);
+		    if (status != PJ_SUCCESS) {
+			PJ_LOG(1,(THIS_FILE, "Invalid IP address"));
+			goto on_error;
+		    }
+		    pj_sockaddr_set_port(&icedemo.rem.def_addr[1], (pj_uint16_t)port);
+
+		} else if (strcmp(attr, "candidate")==0) {
+		    char *sdpcand = attr+strlen(attr)+1;
+		    int af, cnt;
+		    char foundation[32], transport[12], ipaddr[80], type[32];
+		    pj_str_t tmpaddr;
+		    int comp_id, prio, port;
+		    pj_ice_sess_cand *cand;
+		    pj_status_t status;
+
+		    cnt = sscanf(sdpcand, "%s %d %s %d %s %d typ %s",
+				 foundation,
+				 &comp_id,
+				 transport,
+				 &prio,
+				 ipaddr,
+				 &port,
+				 type);
+		    if (cnt != 7) {
+			PJ_LOG(1, (THIS_FILE, "error: Invalid ICE candidate line"));
+			goto on_error;
+		    }
+
+		    cand = &icedemo.rem.cand[icedemo.rem.cand_cnt];
+		    pj_bzero(cand, sizeof(*cand));
+		    
+		    if (strcmp(type, "host")==0)
+			cand->type = PJ_ICE_CAND_TYPE_HOST;
+		    else if (strcmp(type, "srflx")==0)
+			cand->type = PJ_ICE_CAND_TYPE_SRFLX;
+		    else if (strcmp(type, "relay")==0)
+			cand->type = PJ_ICE_CAND_TYPE_RELAYED;
+		    else {
+			PJ_LOG(1, (THIS_FILE, "Error: invalid candidate type '%s'", 
+				   type));
+			goto on_error;
+		    }
+
+		    cand->comp_id = (pj_uint8_t)comp_id;
+		    pj_strdup2(icedemo.pool, &cand->foundation, foundation);
+		    cand->prio = prio;
+		    
+		    if (strchr(ipaddr, ':'))
+			af = pj_AF_INET6();
+		    else
+			af = pj_AF_INET();
+
+		    tmpaddr = pj_str(ipaddr);
+		    pj_sockaddr_init(af, &cand->addr, NULL, 0);
+		    status = pj_sockaddr_set_str_addr(af, &cand->addr, &tmpaddr);
+		    if (status != PJ_SUCCESS) {
+			PJ_LOG(1,(THIS_FILE, "Error: invalid IP address '%s'",
+				  ipaddr));
+			goto on_error;
+		    }
+
+		    pj_sockaddr_set_port(&cand->addr, (pj_uint16_t)port);
+
+		    ++icedemo.rem.cand_cnt;
+
+		    if (cand->comp_id > icedemo.rem.comp_cnt)
+			icedemo.rem.comp_cnt = cand->comp_id;
+		}
+	    }
+	    break;
+	}
+    }
+
+    if (icedemo.rem.cand_cnt==0 ||
+	icedemo.rem.ufrag[0]==0 ||
+	icedemo.rem.pwd[0]==0 ||
+	icedemo.rem.comp_cnt == 0)
+    {
+	PJ_LOG(1, (THIS_FILE, "Error: not enough info"));
+	goto on_error;
+    }
+
+    if (comp0_port==0 || comp0_addr[0]=='\0') {
+	PJ_LOG(1, (THIS_FILE, "Error: default address for component 0 not found"));
+	goto on_error;
+    } else {
+	int af;
+	pj_str_t tmp_addr;
+	pj_status_t status;
+
+	if (strchr(comp0_addr, ':'))
+	    af = pj_AF_INET6();
+	else
+	    af = pj_AF_INET();
+
+	pj_sockaddr_init(af, &icedemo.rem.def_addr[0], NULL, 0);
+	tmp_addr = pj_str(comp0_addr);
+	status = pj_sockaddr_set_str_addr(af, &icedemo.rem.def_addr[0],
+					  &tmp_addr);
+	if (status != PJ_SUCCESS) {
+	    PJ_LOG(1,(THIS_FILE, "Invalid IP address in c= line"));
+	    goto on_error;
+	}
+	pj_sockaddr_set_port(&icedemo.rem.def_addr[0], (pj_uint16_t)comp0_port);
+    }
+
+    PJ_LOG(3, (THIS_FILE, "Done, %d remote candidate(s) added", 
+	       icedemo.rem.cand_cnt));
+    return;
+
+on_error:
+    reset_rem_info();
+}
+
+
+/*
+ * Start ICE negotiation! This function is invoked from the menu.
+ */
+static void icedemo_start_nego(void)
+{
+    pj_str_t rufrag, rpwd;
+    pj_status_t status;
+
+    if (icedemo.icest == NULL) {
+	PJ_LOG(1,(THIS_FILE, "Error: No ICE instance, create it first"));
+	return;
+    }
+
+    if (!pj_ice_strans_has_sess(icedemo.icest)) {
+	PJ_LOG(1,(THIS_FILE, "Error: No ICE session, initialize first"));
+	return;
+    }
+
+    if (icedemo.rem.cand_cnt == 0) {
+	PJ_LOG(1,(THIS_FILE, "Error: No remote info, input remote info first"));
+	return;
+    }
+
+    PJ_LOG(3,(THIS_FILE, "Starting ICE negotiation.."));
+
+    status = pj_ice_strans_start_ice(icedemo.icest, 
+				     pj_cstr(&rufrag, icedemo.rem.ufrag),
+				     pj_cstr(&rpwd, icedemo.rem.pwd),
+				     icedemo.rem.cand_cnt,
+				     icedemo.rem.cand);
+    if (status != PJ_SUCCESS)
+	icedemo_perror("Error starting ICE", status);
+    else
+	PJ_LOG(3,(THIS_FILE, "ICE negotiation started"));
+}
+
+
+/*
+ * Send application data to remote agent.
+ */
+static void icedemo_send_data(unsigned comp_id, const char *data)
+{
+    pj_status_t status;
+
+    if (icedemo.icest == NULL) {
+	PJ_LOG(1,(THIS_FILE, "Error: No ICE instance, create it first"));
+	return;
+    }
+
+    if (!pj_ice_strans_has_sess(icedemo.icest)) {
+	PJ_LOG(1,(THIS_FILE, "Error: No ICE session, initialize first"));
+	return;
+    }
+
+    /*
+    if (!pj_ice_strans_sess_is_complete(icedemo.icest)) {
+	PJ_LOG(1,(THIS_FILE, "Error: ICE negotiation has not been started or is in progress"));
+	return;
+    }
+    */
+
+    if (comp_id<1||comp_id>pj_ice_strans_get_running_comp_cnt(icedemo.icest)) {
+	PJ_LOG(1,(THIS_FILE, "Error: invalid component ID"));
+	return;
+    }
+
+    status = pj_ice_strans_sendto(icedemo.icest, comp_id, data, strlen(data),
+				  &icedemo.rem.def_addr[comp_id-1],
+				  pj_sockaddr_get_len(&icedemo.rem.def_addr[comp_id-1]));
+    if (status != PJ_SUCCESS)
+	icedemo_perror("Error sending data", status);
+    else
+	PJ_LOG(3,(THIS_FILE, "Data sent"));
+}
+
+
+/*
+ * Display help for the menu.
+ */
+static void icedemo_help_menu(void)
+{
+    puts("");
+    puts("-= Help on using ICE and this icedemo program =-");
+    puts("");
+    puts("This application demonstrates how to use ICE in pjnath without having\n"
+	 "to use the SIP protocol. To use this application, you will need to run\n"
+	 "two instances of this application, to simulate two ICE agents.\n");
+
+    puts("Basic ICE flow:\n"
+	 " create instance [menu \"c\"]\n"
+	 " repeat these steps as wanted:\n"
+	 "   - init session as offerer or answerer [menu \"i\"]\n"
+	 "   - display our SDP [menu \"s\"]\n"
+	 "   - \"send\" our SDP from the \"show\" output above to remote, by\n"
+	 "     copy-pasting the SDP to the other icedemo application\n"
+	 "   - parse remote SDP, by pasting SDP generated by the other icedemo\n"
+	 "     instance [menu \"r\"]\n"
+	 "   - begin ICE negotiation in our end [menu \"b\"], and \n"
+	 "   - immediately begin ICE negotiation in the other icedemo instance\n"
+	 "   - ICE negotiation will run, and result will be printed to screen\n"
+	 "   - send application data to remote [menu \"x\"]\n"
+	 "   - end/stop ICE session [menu \"e\"]\n"
+	 " destroy instance [menu \"d\"]\n"
+	 "");
+
+    puts("");
+    puts("This concludes the help screen.");
+    puts("");
+}
+
+
+/*
+ * Display console menu
+ */
+static void icedemo_print_menu(void)
+{
+    puts("");
+    puts("+----------------------------------------------------------------------+");
+    puts("|                    M E N U                                           |");
+    puts("+---+------------------------------------------------------------------+");
+    puts("| c | create           Create the instance                             |");
+    puts("| d | destroy          Destroy the instance                            |");
+    puts("| i | init o|a         Initialize ICE session as offerer or answerer   |");
+    puts("| e | stop             End/stop ICE session                            |");
+    puts("| s | show             Display local ICE info                          |");
+    puts("| r | remote           Input remote ICE info                           |");
+    puts("| b | start            Begin ICE negotiation                           |");
+    puts("| x | send <compid> .. Send data to remote                             |");
+    puts("+---+------------------------------------------------------------------+");
+    puts("| h |  help            * Help! *                                       |");
+    puts("| q |  quit            Quit                                            |");
+    puts("+----------------------------------------------------------------------+");
+}
+
+
+/*
+ * Main console loop.
+ */
+static void icedemo_console(void)
+{
+    pj_bool_t app_quit = PJ_FALSE;
+
+    while (!app_quit) {
+	char input[80], *cmd;
+	const char *SEP = " \t\r\n";
+	pj_size_t len;
+
+	icedemo_print_menu();
+
+	printf("Input: ");
+	if (stdout) fflush(stdout);
+
+	pj_bzero(input, sizeof(input));
+	if (fgets(input, sizeof(input), stdin) == NULL)
+	    break;
+
+	len = strlen(input);
+	while (len && (input[len-1]=='\r' || input[len-1]=='\n'))
+	    input[--len] = '\0';
+
+	cmd = strtok(input, SEP);
+	if (!cmd)
+	    continue;
+
+	if (strcmp(cmd, "create")==0 || strcmp(cmd, "c")==0) {
+
+	    icedemo_create_instance();
+
+	} else if (strcmp(cmd, "destroy")==0 || strcmp(cmd, "d")==0) {
+
+	    icedemo_destroy_instance();
+
+	} else if (strcmp(cmd, "init")==0 || strcmp(cmd, "i")==0) {
+
+	    char *role = strtok(NULL, SEP);
+	    if (role)
+		icedemo_init_session(*role);
+	    else
+		puts("error: Role required");
+
+	} else if (strcmp(cmd, "stop")==0 || strcmp(cmd, "e")==0) {
+
+	    icedemo_stop_session();
+
+	} else if (strcmp(cmd, "show")==0 || strcmp(cmd, "s")==0) {
+
+	    icedemo_show_ice();
+
+	} else if (strcmp(cmd, "remote")==0 || strcmp(cmd, "r")==0) {
+
+	    icedemo_input_remote();
+
+	} else if (strcmp(cmd, "start")==0 || strcmp(cmd, "b")==0) {
+
+	    icedemo_start_nego();
+
+	} else if (strcmp(cmd, "send")==0 || strcmp(cmd, "x")==0) {
+
+	    char *comp = strtok(NULL, SEP);
+
+	    if (!comp) {
+		PJ_LOG(1,(THIS_FILE, "Error: component ID required"));
+	    } else {
+		char *data = comp + strlen(comp) + 1;
+		if (!data)
+		    data = "";
+		icedemo_send_data(atoi(comp), data);
+	    }
+
+	} else if (strcmp(cmd, "help")==0 || strcmp(cmd, "h")==0) {
+
+	    icedemo_help_menu();
+
+	} else if (strcmp(cmd, "quit")==0 || strcmp(cmd, "q")==0) {
+
+	    app_quit = PJ_TRUE;
+
+	} else {
+
+	    printf("Invalid command '%s'\n", cmd);
+
+	}
+    }
+}
+
+
+/*
+ * Display program usage.
+ */
+static void icedemo_usage()
+{
+    puts("Usage: icedemo [optons]");
+    printf("icedemo v%s by pjsip.org\n", pj_get_version());
+    puts("");
+    puts("General options:");
+    puts(" --comp-cnt, -c N          Component count (default=1)");
+    puts(" --nameserver, -n IP       Configure nameserver to activate DNS SRV");
+    puts("                           resolution");
+    puts(" --max-host, -H N          Set max number of host candidates to N");
+    puts(" --regular, -R             Use regular nomination (default aggressive)");
+    puts(" --log-file, -L FILE       Save output to log FILE");
+    puts(" --help, -h                Display this screen.");
+    puts("");
+    puts("STUN related options:");
+    puts(" --stun-srv, -s HOSTDOM    Enable srflx candidate by resolving to STUN server.");
+    puts("                           HOSTDOM may be a \"host_or_ip[:port]\" or a domain");
+    puts("                           name if DNS SRV resolution is used.");
+    puts("");
+    puts("TURN related options:");
+    puts(" --turn-srv, -t HOSTDOM    Enable relayed candidate by using this TURN server.");
+    puts("                           HOSTDOM may be a \"host_or_ip[:port]\" or a domain");
+    puts("                           name if DNS SRV resolution is used.");
+    puts(" --turn-tcp, -T            Use TCP to connect to TURN server");
+    puts(" --turn-username, -u UID   Set TURN username of the credential to UID");
+    puts(" --turn-password, -p PWD   Set password of the credential to WPWD");
+    puts(" --turn-fingerprint, -F    Use fingerprint for outgoing TURN requests");
+    puts("");
+}
+
+
+/*
+ * And here's the main()
+ */
+int main(int argc, char *argv[])
+{
+    struct pj_getopt_option long_options[] = {
+	{ "comp-cnt",           1, 0, 'c'},
+	{ "nameserver",		1, 0, 'n'},
+	{ "max-host",		1, 0, 'H'},
+	{ "help",		0, 0, 'h'},
+	{ "stun-srv",		1, 0, 's'},
+	{ "turn-srv",		1, 0, 't'},
+	{ "turn-tcp",		0, 0, 'T'},
+	{ "turn-username",	1, 0, 'u'},
+	{ "turn-password",	1, 0, 'p'},
+	{ "turn-fingerprint",	0, 0, 'F'},
+	{ "regular",		0, 0, 'R'},
+	{ "log-file",		1, 0, 'L'},
+    };
+    int c, opt_id;
+    pj_status_t status;
+
+    icedemo.opt.comp_cnt = 1;
+    icedemo.opt.max_host = -1;
+
+    while((c=pj_getopt_long(argc,argv, "c:n:s:t:u:p:H:L:hTFR", long_options, &opt_id))!=-1) {
+	switch (c) {
+	case 'c':
+	    icedemo.opt.comp_cnt = atoi(pj_optarg);
+	    if (icedemo.opt.comp_cnt < 1 || icedemo.opt.comp_cnt >= PJ_ICE_MAX_COMP) {
+		puts("Invalid component count value");
+		return 1;
+	    }
+	    break;
+	case 'n':
+	    icedemo.opt.ns = pj_str(pj_optarg);
+	    break;
+	case 'H':
+	    icedemo.opt.max_host = atoi(pj_optarg);
+	    break;
+	case 'h':
+	    icedemo_usage();
+	    return 0;
+	case 's':
+	    icedemo.opt.stun_srv = pj_str(pj_optarg);
+	    break;
+	case 't':
+	    icedemo.opt.turn_srv = pj_str(pj_optarg);
+	    break;
+	case 'T':
+	    icedemo.opt.turn_tcp = PJ_TRUE;
+	    break;
+	case 'u':
+	    icedemo.opt.turn_username = pj_str(pj_optarg);
+	    break;
+	case 'p':
+	    icedemo.opt.turn_password = pj_str(pj_optarg);
+	    break;
+	case 'F':
+	    icedemo.opt.turn_fingerprint = PJ_TRUE;
+	    break;
+	case 'R':
+	    icedemo.opt.regular = PJ_TRUE;
+	    break;
+	case 'L':
+	    icedemo.opt.log_file = pj_optarg;
+	    break;
+	default:
+	    printf("Argument \"%s\" is not valid. Use -h to see help",
+		   argv[pj_optind]);
+	    return 1;
+	}
+    }
+
+    status = icedemo_init();
+    if (status != PJ_SUCCESS)
+	return 1;
+
+    icedemo_console();
+
+    err_exit("Quitting..", PJ_SUCCESS);
+    return 0;
+}
diff --git a/jni/pjproject-android/.svn/pristine/25/25fad9456e3f97ff2f27cf0320d7b2b941c3d26d.svn-base b/jni/pjproject-android/.svn/pristine/25/25fad9456e3f97ff2f27cf0320d7b2b941c3d26d.svn-base
new file mode 100644
index 0000000..1eeee93
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/25/25fad9456e3f97ff2f27cf0320d7b2b941c3d26d.svn-base
@@ -0,0 +1,211 @@
+
+   /******************************************************************
+
+       iLBC Speech Coder ANSI-C Source Code
+
+       StateSearchW.c
+
+       Copyright (C) The Internet Society (2004).
+       All Rights Reserved.
+
+   ******************************************************************/
+
+   #include <math.h>
+   #include <string.h>
+
+   #include "iLBC_define.h"
+   #include "constants.h"
+   #include "filter.h"
+   #include "helpfun.h"
+
+   /*----------------------------------------------------------------*
+    *  predictive noise shaping encoding of scaled start state
+    *  (subrutine for StateSearchW)
+    *---------------------------------------------------------------*/
+
+   void AbsQuantW(
+       iLBC_Enc_Inst_t *iLBCenc_inst,
+                           /* (i) Encoder instance */
+       float *in,          /* (i) vector to encode */
+       float *syntDenum,   /* (i) denominator of synthesis filter */
+       float *weightDenum, /* (i) denominator of weighting filter */
+       int *out,           /* (o) vector of quantizer indexes */
+       int len,        /* (i) length of vector to encode and
+                                  vector of quantizer indexes */
+       int state_first     /* (i) position of start state in the
+                                  80 vec */
+   ){
+       float *syntOut;
+       float syntOutBuf[LPC_FILTERORDER+STATE_SHORT_LEN_30MS];
+       float toQ, xq;
+       int n;
+       int index;
+
+       /* initialization of buffer for filtering */
+
+       memset(syntOutBuf, 0, LPC_FILTERORDER*sizeof(float));
+
+
+
+
+
+
+       /* initialization of pointer for filtering */
+
+       syntOut = &syntOutBuf[LPC_FILTERORDER];
+
+       /* synthesis and weighting filters on input */
+
+       if (state_first) {
+           AllPoleFilter (in, weightDenum, SUBL, LPC_FILTERORDER);
+       } else {
+           AllPoleFilter (in, weightDenum,
+               iLBCenc_inst->state_short_len-SUBL,
+               LPC_FILTERORDER);
+       }
+
+       /* encoding loop */
+
+       for (n=0; n<len; n++) {
+
+           /* time update of filter coefficients */
+
+           if ((state_first)&&(n==SUBL)){
+               syntDenum += (LPC_FILTERORDER+1);
+               weightDenum += (LPC_FILTERORDER+1);
+
+               /* synthesis and weighting filters on input */
+               AllPoleFilter (&in[n], weightDenum, len-n,
+                   LPC_FILTERORDER);
+
+           } else if ((state_first==0)&&
+               (n==(iLBCenc_inst->state_short_len-SUBL))) {
+               syntDenum += (LPC_FILTERORDER+1);
+               weightDenum += (LPC_FILTERORDER+1);
+
+               /* synthesis and weighting filters on input */
+               AllPoleFilter (&in[n], weightDenum, len-n,
+                   LPC_FILTERORDER);
+
+           }
+
+           /* prediction of synthesized and weighted input */
+
+           syntOut[n] = 0.0;
+           AllPoleFilter (&syntOut[n], weightDenum, 1,
+               LPC_FILTERORDER);
+
+           /* quantization */
+
+           toQ = in[n]-syntOut[n];
+
+
+
+
+
+           sort_sq(&xq, &index, toQ, state_sq3Tbl, 8);
+           out[n]=index;
+           syntOut[n] = state_sq3Tbl[out[n]];
+
+           /* update of the prediction filter */
+
+           AllPoleFilter(&syntOut[n], weightDenum, 1,
+               LPC_FILTERORDER);
+       }
+   }
+
+   /*----------------------------------------------------------------*
+    *  encoding of start state
+    *---------------------------------------------------------------*/
+
+   void StateSearchW(
+       iLBC_Enc_Inst_t *iLBCenc_inst,
+                           /* (i) Encoder instance */
+       float *residual,/* (i) target residual vector */
+       float *syntDenum,   /* (i) lpc synthesis filter */
+       float *weightDenum, /* (i) weighting filter denuminator */
+       int *idxForMax,     /* (o) quantizer index for maximum
+                                  amplitude */
+       int *idxVec,    /* (o) vector of quantization indexes */
+       int len,        /* (i) length of all vectors */
+       int state_first     /* (i) position of start state in the
+                                  80 vec */
+   ){
+       float dtmp, maxVal;
+       float tmpbuf[LPC_FILTERORDER+2*STATE_SHORT_LEN_30MS];
+       float *tmp, numerator[1+LPC_FILTERORDER];
+       float foutbuf[LPC_FILTERORDER+2*STATE_SHORT_LEN_30MS], *fout;
+       int k;
+       float qmax, scal;
+
+       /* initialization of buffers and filter coefficients */
+
+       memset(tmpbuf, 0, LPC_FILTERORDER*sizeof(float));
+       memset(foutbuf, 0, LPC_FILTERORDER*sizeof(float));
+       for (k=0; k<LPC_FILTERORDER; k++) {
+           numerator[k]=syntDenum[LPC_FILTERORDER-k];
+       }
+       numerator[LPC_FILTERORDER]=syntDenum[0];
+       tmp = &tmpbuf[LPC_FILTERORDER];
+       fout = &foutbuf[LPC_FILTERORDER];
+
+       /* circular convolution with the all-pass filter */
+
+
+
+
+
+
+       memcpy(tmp, residual, len*sizeof(float));
+       memset(tmp+len, 0, len*sizeof(float));
+       ZeroPoleFilter(tmp, numerator, syntDenum, 2*len,
+           LPC_FILTERORDER, fout);
+       for (k=0; k<len; k++) {
+           fout[k] += fout[k+len];
+       }
+
+       /* identification of the maximum amplitude value */
+
+       maxVal = fout[0];
+       for (k=1; k<len; k++) {
+
+           if (fout[k]*fout[k] > maxVal*maxVal){
+               maxVal = fout[k];
+           }
+       }
+       maxVal=(float)fabs(maxVal);
+
+       /* encoding of the maximum amplitude value */
+
+       if (maxVal < 10.0) {
+           maxVal = 10.0;
+       }
+       maxVal = (float)log10(maxVal);
+       sort_sq(&dtmp, idxForMax, maxVal, state_frgqTbl, 64);
+
+       /* decoding of the maximum amplitude representation value,
+          and corresponding scaling of start state */
+
+       maxVal=state_frgqTbl[*idxForMax];
+       qmax = (float)pow(10,maxVal);
+       scal = (float)(4.5)/qmax;
+       for (k=0; k<len; k++){
+           fout[k] *= scal;
+       }
+
+       /* predictive noise shaping encoding of scaled start state */
+
+       AbsQuantW(iLBCenc_inst, fout,syntDenum,
+           weightDenum,idxVec, len, state_first);
+   }
+
+
+
+
+
+
+
+
+
+
+