Index: /pjproject/trunk/pjsip-apps/build/Samples-vc.mak
===================================================================
--- /pjproject/trunk/pjsip-apps/build/Samples-vc.mak	(revision 1677)
+++ /pjproject/trunk/pjsip-apps/build/Samples-vc.mak	(revision 1678)
@@ -51,4 +51,5 @@
 SAMPLES = $(BINDIR)\confsample.exe \
 	  $(BINDIR)\confbench.exe \
+	  $(BINDIR)\encdec.exe \
 	  $(BINDIR)\level.exe \
 	  $(BINDIR)\pjsip-perf.exe \
Index: /pjproject/trunk/pjsip-apps/build/Samples.mak
===================================================================
--- /pjproject/trunk/pjsip-apps/build/Samples.mak	(revision 1677)
+++ /pjproject/trunk/pjsip-apps/build/Samples.mak	(revision 1678)
@@ -15,4 +15,5 @@
 
 SAMPLES := confsample \
+	   encdec \
 	   level \
 	   pjsip-perf \
Index: /pjproject/trunk/pjsip-apps/build/samples.dsp
===================================================================
--- /pjproject/trunk/pjsip-apps/build/samples.dsp	(revision 1677)
+++ /pjproject/trunk/pjsip-apps/build/samples.dsp	(revision 1678)
@@ -99,4 +99,8 @@
 # Begin Source File
 
+SOURCE=..\src\samples\encdec.c
+# End Source File
+# Begin Source File
+
 SOURCE=..\src\samples\footprint.c
 # End Source File
Index: /pjproject/trunk/pjsip-apps/build/samples.vcproj
===================================================================
--- /pjproject/trunk/pjsip-apps/build/samples.vcproj	(revision 1677)
+++ /pjproject/trunk/pjsip-apps/build/samples.vcproj	(revision 1678)
@@ -80,4 +80,8 @@
 			<File
 				RelativePath="..\src\samples\confsample.c"
+				>
+			</File>
+			<File
+				RelativePath="..\src\samples\encdec.c"
 				>
 			</File>
Index: /pjproject/trunk/pjsip-apps/src/samples/encdec.c
===================================================================
--- /pjproject/trunk/pjsip-apps/src/samples/encdec.c	(revision 1678)
+++ /pjproject/trunk/pjsip-apps/src/samples/encdec.c	(revision 1678)
@@ -0,0 +1,245 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2007 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 
+ */
+
+ /**
+ * \page page_pjmedia_samples_encdec_c Samples: Encoding and Decoding
+ *
+ * This sample shows how to use codec.
+ *
+ * This file is pjsip-apps/src/samples/encdec.c
+ *
+ * \includelineno encdec.c
+ */
+
+#include <pjlib.h>
+#include <pjmedia.h>
+#include <pjmedia-codec.h>
+
+#define THIS_FILE   "encdec.c"
+
+static const char *desc = 
+ " encdec								\n"
+ "									\n"
+ " PURPOSE:								\n"
+ "  Encode input WAV with a codec, and decode the result to another WAV \n"
+ "\n"
+ "\n"
+ " USAGE:								\n"
+ "  encdec codec input.wav output.wav                                   \n"
+ "\n"
+ "\n"
+ " where:\n"
+ "  codec         Set the codec name.                                   \n"
+ "  input.wav     Set the input WAV filename.                           \n"
+ "  output.wav    Set the output WAV filename.                          \n"
+
+ "\n"
+;
+
+#define HAS_G729_CODEC	0
+#if HAS_G729_CODEC
+#include "keystream_g729ab.h"
+#endif
+
+#if 0
+#   define TRACE_(expr)	    PJ_LOG(4,expr)
+#else
+#   define TRACE_(expr)
+#endif
+
+
+static void err(const char *op, pj_status_t status)
+{
+    char errmsg[PJ_ERR_MSG_SIZE];
+    pj_strerror(status, errmsg, sizeof(errmsg));
+    PJ_LOG(3,("", "%s error: %s", op, errmsg));
+}
+
+#define CHECK(op)   do { \
+			status = op; \
+			if (status != PJ_SUCCESS) { \
+			    err(#op, status); \
+			    return status; \
+			} \
+		    } \
+		    while (0)
+
+static pjmedia_endpt *mept;
+static unsigned file_msec_duration;
+
+static pj_status_t enc_dec_test(const char *codec_id,
+				const char *filein,
+			        const char *fileout)
+{
+    pj_pool_t *pool;
+    pjmedia_codec_mgr *cm;
+    pjmedia_codec *codec;
+    pjmedia_codec_info *pci;
+    pjmedia_codec_param param;
+    unsigned cnt, samples_per_frame;
+    pj_str_t tmp;
+    pjmedia_port *wavin, *wavout;
+    pj_status_t status;
+
+    pool = pjmedia_endpt_create_pool(mept, "encdec", 1000, 1000);
+
+    cm = pjmedia_endpt_get_codec_mgr(mept);
+
+    cnt = 1;
+    CHECK( pjmedia_codec_mgr_find_codecs_by_id(cm, pj_cstr(&tmp, codec_id), 
+					       &cnt, &pci, NULL) );
+    CHECK( pjmedia_codec_mgr_get_default_param(cm, pci, &param) );
+
+    samples_per_frame = param.info.clock_rate * param.info.frm_ptime / 1000;
+
+    /* Control VAD */
+    param.setting.vad = 0;
+
+    /* Open wav for reading */
+    CHECK( pjmedia_wav_player_port_create(pool, filein, 
+					  param.info.frm_ptime, 
+					  PJMEDIA_FILE_NO_LOOP, 0, &wavin) );
+
+    /* Open wav for writing */
+    CHECK( pjmedia_wav_writer_port_create(pool, fileout,
+					  param.info.clock_rate, 
+					  param.info.channel_cnt,
+					  samples_per_frame,
+					  16, 0, 0, &wavout) );
+
+    /* Alloc codec */
+    CHECK( pjmedia_codec_mgr_alloc_codec(cm, pci, &codec) );
+    CHECK( codec->op->init(codec, pool) );
+    CHECK( codec->op->open(codec, &param) );
+    
+    for (;;) {
+	pjmedia_frame frm_pcm, frm_bit, out_frm, frames[4];
+	pj_int16_t pcmbuf[320];
+	pj_timestamp ts;
+	pj_uint8_t bitstream[160];
+
+	frm_pcm.buf = (char*)pcmbuf;
+	frm_pcm.size = samples_per_frame * 2;
+
+	/* Read from WAV */
+	if (pjmedia_port_get_frame(wavin, &frm_pcm) != PJ_SUCCESS)
+	    break;
+	if (frm_pcm.type != PJMEDIA_FRAME_TYPE_AUDIO)
+	    break;;
+
+	/* Encode */
+	frm_bit.buf = bitstream;
+	frm_bit.size = sizeof(bitstream);
+	CHECK(codec->op->encode(codec, &frm_pcm, sizeof(bitstream), &frm_bit));
+
+	/* Parse the bitstream (not really necessary for this case
+	 * since we always decode 1 frame, but it's still good
+	 * for testing)
+	 */
+	ts.u64 = 0;
+	cnt = PJ_ARRAY_SIZE(frames);
+	CHECK( codec->op->parse(codec, bitstream, frm_bit.size, &ts, &cnt, 
+			        frames) );
+	CHECK( (cnt==1 ? PJ_SUCCESS : -1) );
+
+	/* Decode */
+	out_frm.buf = (char*)pcmbuf;
+	out_frm.size = sizeof(pcmbuf);
+	CHECK( codec->op->decode(codec, &frames[0], sizeof(pcmbuf), 
+				 &out_frm) );
+
+	/* Write to WAV */
+	CHECK( pjmedia_port_put_frame(wavout, &out_frm) );
+
+	file_msec_duration += samples_per_frame * 1000 / 
+			      param.info.clock_rate;
+
+	TRACE_((THIS_FILE, "Bytes read: %u, encode: %u, decode/write: %u",
+		frm_pcm.size, frm_bit.size, out_frm.size));
+    }
+
+    /* Close wavs */
+    pjmedia_port_destroy(wavout);
+    pjmedia_port_destroy(wavin);
+
+    /* Close codec */
+    codec->op->close(codec);
+    pjmedia_codec_mgr_dealloc_codec(cm, codec);
+
+    /* Release pool */
+    pj_pool_release(pool);
+
+    return PJ_SUCCESS;
+}
+
+
+int main(int argc, char *argv[])
+{
+    pj_caching_pool cp;
+    pj_time_val t0, t1;
+    pj_status_t status;
+
+    if (argc != 4) {
+	puts(desc);
+	return 1;
+    }
+
+    CHECK( pj_init() );
+    
+    pj_caching_pool_init(&cp, NULL, 0);
+
+    CHECK( pjmedia_endpt_create(&cp.factory, NULL, 1, &mept) );
+
+    /* Register all codecs */
+#if PJMEDIA_HAS_G711_CODEC
+    CHECK( pjmedia_codec_g711_init(mept) );
+#endif
+#if PJMEDIA_HAS_GSM_CODEC
+    CHECK( pjmedia_codec_gsm_init(mept) );
+#endif
+#if PJMEDIA_HAS_ILBC_CODEC
+    CHECK( pjmedia_codec_ilbc_init(mept, 30) );
+#endif
+#if PJMEDIA_HAS_SPEEX_CODEC
+    CHECK( pjmedia_codec_speex_init(mept, 0, 5, 5) );
+#endif
+#if HAS_G729_CODEC
+    CHECK( keystream_g729ab_init(mept) );
+#endif
+
+    pj_gettimeofday(&t0);
+    status = enc_dec_test(argv[1], argv[2], argv[3]);
+    pj_gettimeofday(&t1);
+    PJ_TIME_VAL_SUB(t1, t0);
+
+    pjmedia_endpt_destroy(mept);
+    pj_caching_pool_destroy(&cp);
+    pj_shutdown();
+
+    if (status == PJ_SUCCESS) {
+	puts("");
+	puts("Success");
+	printf("Duration: %ds.%03d\n", file_msec_duration/1000, 
+				       file_msec_duration%1000);
+	printf("Time: %ds.%03d\n", t1.sec, t1.msec);
+    }
+
+    return 0;
+}
+
