Index: /pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
===================================================================
--- /pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 5184)
+++ /pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 5185)
@@ -910,4 +910,29 @@
 			     pjsip_status_code *code,
 			     pjsua_call_setting *opt);
+
+
+    /**
+    * Notify application when call has received INVITE with no SDP offer.
+    * Application can update the call setting (e.g: add audio/video), or
+    * enable/disable codecs, or update other media session settings from
+    * within the callback, however, as mandated by the standard (RFC3261
+    * section 14.2), it must ensure that the update overlaps with the
+    * existing media session (in codecs, transports, or other parameters)
+    * that require support from the peer, this is to avoid the need for
+    * the peer to reject the offer.
+    *
+    * When this callback is not defined, the default behavior is to send
+    * SDP offer using current active media session (with all enabled codecs
+    * on each media type).
+    *
+    * @param call_id	The call index.
+    * @param reserved	Reserved param, currently not used.
+    * @param opt	The current call setting, application can update
+    *			this setting for generating the offer.
+    */
+    void (*on_call_tx_offer)(pjsua_call_id call_id,
+			     void *reserved,
+			     pjsua_call_setting *opt);
+
 
     /**
Index: /pjproject/trunk/pjsip/include/pjsua2/call.hpp
===================================================================
--- /pjproject/trunk/pjsip/include/pjsua2/call.hpp	(revision 5184)
+++ /pjproject/trunk/pjsip/include/pjsua2/call.hpp	(revision 5185)
@@ -852,4 +852,17 @@
 
 /**
+ * This structure contains parameters for Call::onCallTxOffer() callback.
+ */
+struct OnCallTxOfferParam
+{
+    /**
+     * The current call setting, application can update this setting for
+     * generating the offer. Note that application should maintain any
+     * active media to avoid the need for the peer to reject the offer.
+     */
+    CallSetting         opt;
+};
+
+/**
  * This structure contains parameters for Call::onCallRedirected() callback.
  */
@@ -1601,4 +1614,23 @@
      */
     virtual void onCallRxOffer(OnCallRxOfferParam &prm)
+    { PJ_UNUSED_ARG(prm); }
+    
+    /**
+     * Notify application when call has received INVITE with no SDP offer.
+     * Application can update the call setting (e.g: add audio/video), or
+     * enable/disable codecs, or update other media session settings from
+     * within the callback, however, as mandated by the standard (RFC3261
+     * section 14.2), it must ensure that the update overlaps with the
+     * existing media session (in codecs, transports, or other parameters)
+     * that require support from the peer, this is to avoid the need for
+     * the peer to reject the offer.
+     *
+     * When this callback is not implemented, the default behavior is to send
+     * SDP offer using current active media session (with all enabled codecs
+     * on each media type).
+     *
+     * @param prm	Callback parameter.
+     */
+    virtual void onCallTxOffer(OnCallTxOfferParam &prm)
     { PJ_UNUSED_ARG(prm); }
     
Index: /pjproject/trunk/pjsip/include/pjsua2/endpoint.hpp
===================================================================
--- /pjproject/trunk/pjsip/include/pjsua2/endpoint.hpp	(revision 5184)
+++ /pjproject/trunk/pjsip/include/pjsua2/endpoint.hpp	(revision 5185)
@@ -1359,4 +1359,7 @@
                                  pjsip_status_code *code,
                                  pjsua_call_setting *opt);
+    static void on_call_tx_offer(pjsua_call_id call_id,
+				 void *reserved,
+				 pjsua_call_setting *opt);
     static pjsip_redirect_op on_call_redirected(pjsua_call_id call_id,
                                                 const pjsip_uri *target,
Index: /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c	(revision 5184)
+++ /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c	(revision 5185)
@@ -4182,6 +4182,12 @@
 #endif
 
+    if (pjsua_var.ua_cfg.cb.on_call_tx_offer) {
+	cleanup_call_setting_flag(&call->opt);
+	(*pjsua_var.ua_cfg.cb.on_call_tx_offer)(call->index, NULL,
+						&call->opt);
+    }
+
     /* We may need to re-initialize media before creating SDP */
-    if (call->med_prov_cnt == 0) {
+    if (call->med_prov_cnt == 0 || pjsua_var.ua_cfg.cb.on_call_tx_offer) {
     	status = apply_call_setting(call, &call->opt, NULL);
     	if (status != PJ_SUCCESS)
Index: /pjproject/trunk/pjsip/src/pjsua2/endpoint.cpp
===================================================================
--- /pjproject/trunk/pjsip/src/pjsua2/endpoint.cpp	(revision 5184)
+++ /pjproject/trunk/pjsip/src/pjsua2/endpoint.cpp	(revision 5185)
@@ -1074,4 +1074,23 @@
 }
 
+void Endpoint::on_call_tx_offer(pjsua_call_id call_id,
+				void *reserved,
+				pjsua_call_setting *opt)
+{
+    PJ_UNUSED_ARG(reserved);
+
+    Call *call = Call::lookup(call_id);
+    if (!call) {
+	return;
+    }
+
+    OnCallTxOfferParam prm;
+    prm.opt.fromPj(*opt);
+
+    call->onCallTxOffer(prm);
+
+    *opt = prm.opt.toPj();
+}
+
 pjsip_redirect_op Endpoint::on_call_redirected(pjsua_call_id call_id,
                                                const pjsip_uri *target,
@@ -1273,4 +1292,5 @@
     ua_cfg.cb.on_call_replaced          = &Endpoint::on_call_replaced;
     ua_cfg.cb.on_call_rx_offer          = &Endpoint::on_call_rx_offer;
+    ua_cfg.cb.on_call_tx_offer          = &Endpoint::on_call_tx_offer;
     ua_cfg.cb.on_call_redirected        = &Endpoint::on_call_redirected;
     ua_cfg.cb.on_call_media_transport_state =
