Index: pjproject/trunk/build.symbian/symsndtest.mmp
===================================================================
--- pjproject/trunk/build.symbian/symsndtest.mmp	(revision 3134)
+++ pjproject/trunk/build.symbian/symsndtest.mmp	(revision 3135)
@@ -30,6 +30,7 @@
 LIBRARY			charconv.lib euser.lib estlib.lib
 LIBRARY			esock.lib insock.lib
-STATICLIBRARY		pjlib.lib pjmedia.lib
 STATICLIBRARY		pjmedia_audiodev.lib
+STATICLIBRARY		pjmedia.lib
+STATICLIBRARY		pjlib.lib 
 STATICLIBRARY		libresample.lib
 
Index: pjproject/trunk/pjmedia/include/pjmedia-audiodev/config.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia-audiodev/config.h	(revision 3134)
+++ pjproject/trunk/pjmedia/include/pjmedia-audiodev/config.h	(revision 3135)
@@ -88,4 +88,23 @@
 #ifndef PJMEDIA_AUDIO_DEV_HAS_SYMB_APS
 #   define PJMEDIA_AUDIO_DEV_HAS_SYMB_APS	0
+#endif
+
+
+/**
+ * This setting controls whether Symbian APS should perform codec
+ * detection in its factory initalization. Note that codec detection 
+ * may take few seconds and detecting more codecs will take more time.
+ * Possible values are:
+ * - 0: no codec detection, all APS codec (AMR-NB, G.711, G.729, and
+ *      iLBC) will be assumed as supported.
+ * - 1: minimal codec detection, i.e: only detect for AMR-NB and G.711,
+ *      (G.729 and iLBC are considered to be supported/unsupported when
+ *      G.711 is supported/unsupported).
+ * - 2: full codec detection, i.e: detect AMR-NB, G.711, G.729, and iLBC.
+ * 
+ * Default: 1 (minimal codec detection)
+ */
+#ifndef PJMEDIA_AUDIO_DEV_SYMB_APS_DETECTS_CODEC
+#   define PJMEDIA_AUDIO_DEV_SYMB_APS_DETECTS_CODEC 1
 #endif
 
Index: pjproject/trunk/pjmedia/src/pjmedia-audiodev/symb_aps_dev.cpp
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia-audiodev/symb_aps_dev.cpp	(revision 3134)
+++ pjproject/trunk/pjmedia/src/pjmedia-audiodev/symb_aps_dev.cpp	(revision 3135)
@@ -1294,26 +1294,127 @@
     af->dev_info.output_count = 1;
 
-    af->dev_info.ext_fmt_cnt = 5;
-
-    af->dev_info.ext_fmt[0].id = PJMEDIA_FORMAT_AMR;
-    af->dev_info.ext_fmt[0].bitrate = 7400;
-    af->dev_info.ext_fmt[0].vad = PJ_TRUE;
-
-    af->dev_info.ext_fmt[1].id = PJMEDIA_FORMAT_G729;
-    af->dev_info.ext_fmt[1].bitrate = 8000;
-    af->dev_info.ext_fmt[1].vad = PJ_FALSE;
-
-    af->dev_info.ext_fmt[2].id = PJMEDIA_FORMAT_ILBC;
-    af->dev_info.ext_fmt[2].bitrate = 13333;
-    af->dev_info.ext_fmt[2].vad = PJ_TRUE;
-
-    af->dev_info.ext_fmt[3].id = PJMEDIA_FORMAT_PCMU;
-    af->dev_info.ext_fmt[3].bitrate = 64000;
-    af->dev_info.ext_fmt[3].vad = PJ_FALSE;
-
-    af->dev_info.ext_fmt[4].id = PJMEDIA_FORMAT_PCMA;
-    af->dev_info.ext_fmt[4].bitrate = 64000;
-    af->dev_info.ext_fmt[4].vad = PJ_FALSE;
+    /* Enumerate codecs by trying to initialize each codec and examining
+     * the error code. Consider the following:
+     * - not possible to reinitialize the same APS session with 
+     *   different settings,
+     * - closing APS session and trying to immediately reconnect may fail,
+     *   clients should wait ~5s before attempting to reconnect.
+     */
+
+    unsigned i, fmt_cnt = 0;
+    pj_bool_t g711_supported = PJ_FALSE;
+
+    /* Do not change the order! */
+    TFourCC fourcc[] = {
+	TFourCC(KMCPFourCCIdAMRNB),
+	TFourCC(KMCPFourCCIdG711),
+	TFourCC(KMCPFourCCIdG729),
+	TFourCC(KMCPFourCCIdILBC)
+    };
+
+    for (i = 0; i < PJ_ARRAY_SIZE(fourcc); ++i) {
+	pj_bool_t supported = PJ_FALSE;
+	unsigned retry_cnt = 0;
+	enum { MAX_RETRY = 3 }; 
+
+#if (PJMEDIA_AUDIO_DEV_SYMB_APS_DETECTS_CODEC == 0)
+	/* Codec detection is disabled */
+	supported = PJ_TRUE;
+#elif (PJMEDIA_AUDIO_DEV_SYMB_APS_DETECTS_CODEC == 1)
+	/* Minimal codec detection, AMR-NB and G.711 only */
+	if (i > 1) {
+	    /* If G.711 has been checked, skip G.729 and iLBC checks */
+	    retry_cnt = MAX_RETRY;
+	    supported = g711_supported;
+	}
+#endif
+	
+	while (!supported && ++retry_cnt <= MAX_RETRY) {
+	    RAPSSession iSession;
+	    TAPSInitSettings iPlaySettings;
+	    TAPSInitSettings iRecSettings;
+	    TInt err;
+
+	    // Recorder settings
+	    iRecSettings.iGlobal		= APP_UID;
+	    iRecSettings.iPriority		= TMdaPriority(100);
+	    iRecSettings.iPreference		= TMdaPriorityPreference(0x05210001);
+	    iRecSettings.iSettings.iChannels	= EMMFMono;
+	    iRecSettings.iSettings.iSampleRate	= EMMFSampleRate8000Hz;
+
+	    // Player settings
+	    iPlaySettings.iGlobal		= APP_UID;
+	    iPlaySettings.iPriority		= TMdaPriority(100);
+	    iPlaySettings.iPreference		= TMdaPriorityPreference(0x05220001);
+	    iPlaySettings.iSettings.iChannels	= EMMFMono;
+	    iPlaySettings.iSettings.iSampleRate = EMMFSampleRate8000Hz;
+
+	    iRecSettings.iFourCC = iPlaySettings.iFourCC = fourcc[i];
+
+	    err = iSession.Connect();
+	    if (err == KErrNone)
+		err = iSession.InitializePlayer(iPlaySettings);
+	    if (err == KErrNone)
+		err = iSession.InitializeRecorder(iRecSettings);
+	    iSession.Close();
+
+	    if (err == KErrNone) {
+		/* All fine, stop retyring */
+		supported = PJ_TRUE;
+	    }  else if (err == KErrAlreadyExists && retry_cnt < MAX_RETRY) {
+		/* Seems that the previous session is still arround,
+		 * let's wait before retrying.
+		 */
+		enum { RETRY_WAIT = 3000 }; /* in msecs */
+		TTime start, now;
+                
+		start.UniversalTime();
+		do {
+		    pj_symbianos_poll(-1, RETRY_WAIT);
+		    now.UniversalTime();
+		} while (now.MicroSecondsFrom(start) < RETRY_WAIT * 1000);
+	    } else {
+		/* Seems that this format is not supported */
+		retry_cnt = MAX_RETRY;
+	    }
+	}
+
+	if (supported) {
+	    switch(i) {
+	    case 0: /* AMRNB */
+		af->dev_info.ext_fmt[fmt_cnt].id = PJMEDIA_FORMAT_AMR;
+		af->dev_info.ext_fmt[fmt_cnt].bitrate = 7400;
+		af->dev_info.ext_fmt[fmt_cnt].vad = PJ_TRUE;
+		++fmt_cnt;
+		break;
+	    case 1: /* G.711 */
+		af->dev_info.ext_fmt[fmt_cnt].id = PJMEDIA_FORMAT_PCMU;
+		af->dev_info.ext_fmt[fmt_cnt].bitrate = 64000;
+		af->dev_info.ext_fmt[fmt_cnt].vad = PJ_FALSE;
+		++fmt_cnt;
+		af->dev_info.ext_fmt[fmt_cnt].id = PJMEDIA_FORMAT_PCMA;
+		af->dev_info.ext_fmt[fmt_cnt].bitrate = 64000;
+		af->dev_info.ext_fmt[fmt_cnt].vad = PJ_FALSE;
+		++fmt_cnt;
+		g711_supported = PJ_TRUE;
+		break;
+	    case 2: /* G.729 */
+		af->dev_info.ext_fmt[fmt_cnt].id = PJMEDIA_FORMAT_G729;
+		af->dev_info.ext_fmt[fmt_cnt].bitrate = 8000;
+		af->dev_info.ext_fmt[fmt_cnt].vad = PJ_FALSE;
+		++fmt_cnt;
+		break;
+	    case 3: /* iLBC */
+		af->dev_info.ext_fmt[fmt_cnt].id = PJMEDIA_FORMAT_ILBC;
+		af->dev_info.ext_fmt[fmt_cnt].bitrate = 13333;
+		af->dev_info.ext_fmt[fmt_cnt].vad = PJ_TRUE;
+		++fmt_cnt;
+		break;
+	    }
+	}
+    }
     
+    af->dev_info.ext_fmt_cnt = fmt_cnt;
+
     PJ_LOG(4, (THIS_FILE, "APS initialized"));
 
Index: pjproject/trunk/pjsip-apps/src/symsndtest/app_main.cpp
===================================================================
--- pjproject/trunk/pjsip-apps/src/symsndtest/app_main.cpp	(revision 3134)
+++ pjproject/trunk/pjsip-apps/src/symsndtest/app_main.cpp	(revision 3135)
@@ -124,4 +124,37 @@
     		   i, info.name, info.input_count, info.output_count,
     		   info.default_samples_per_sec));
+    	
+	unsigned j;
+
+	/* Print extended formats supported by this audio device */
+	PJ_LOG(3, (THIS_FILE, "   Extended formats supported:"));
+	for (j = 0; j < info.ext_fmt_cnt; ++j) {
+	    const char *fmt_name = NULL;
+	    
+	    switch (info.ext_fmt[j].id) {
+	    case PJMEDIA_FORMAT_PCMA:
+		fmt_name = "PCMA";
+		break;
+	    case PJMEDIA_FORMAT_PCMU:
+		fmt_name = "PCMU";
+		break;
+	    case PJMEDIA_FORMAT_AMR:
+		fmt_name = "AMR-NB";
+		break;
+	    case PJMEDIA_FORMAT_G729:
+		fmt_name = "G729";
+		break;
+	    case PJMEDIA_FORMAT_ILBC:
+		fmt_name = "ILBC";
+		break;
+	    case PJMEDIA_FORMAT_PCM:
+		fmt_name = "PCM";
+		break;
+	    default:
+		fmt_name = "Unknown";
+		break;
+	    }
+	    PJ_LOG(3, (THIS_FILE, "   - %s", fmt_name));
+	}
     }
 
