summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2008-01-11 09:01:50 +0000
committerBenny Prijono <bennylp@teluu.com>2008-01-11 09:01:50 +0000
commit1d0950491c7823396ab571eb66984467e95bfae7 (patch)
treebc12cce0df79043d23c1be9699d33c4d0c5bd425
parent4aa48aaf92d711ba6d99086e9f808c790814d491 (diff)
Ticket #445: added codec encoding/decoding sample
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1678 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjsip-apps/build/Samples-vc.mak1
-rw-r--r--pjsip-apps/build/Samples.mak1
-rw-r--r--pjsip-apps/build/samples.dsp4
-rw-r--r--pjsip-apps/build/samples.vcproj4
-rw-r--r--pjsip-apps/src/samples/encdec.c245
5 files changed, 255 insertions, 0 deletions
diff --git a/pjsip-apps/build/Samples-vc.mak b/pjsip-apps/build/Samples-vc.mak
index 9e7b5d4d..59a9b085 100644
--- a/pjsip-apps/build/Samples-vc.mak
+++ b/pjsip-apps/build/Samples-vc.mak
@@ -50,6 +50,7 @@ BINDIR = ..\bin\samples
SAMPLES = $(BINDIR)\confsample.exe \
$(BINDIR)\confbench.exe \
+ $(BINDIR)\encdec.exe \
$(BINDIR)\level.exe \
$(BINDIR)\pjsip-perf.exe \
$(BINDIR)\playfile.exe \
diff --git a/pjsip-apps/build/Samples.mak b/pjsip-apps/build/Samples.mak
index a6eca7be..2535d019 100644
--- a/pjsip-apps/build/Samples.mak
+++ b/pjsip-apps/build/Samples.mak
@@ -14,6 +14,7 @@ OBJDIR := ./output/samples-$(TARGET_NAME)
BINDIR := ../bin/samples
SAMPLES := confsample \
+ encdec \
level \
pjsip-perf \
playfile \
diff --git a/pjsip-apps/build/samples.dsp b/pjsip-apps/build/samples.dsp
index c94b4940..a4831820 100644
--- a/pjsip-apps/build/samples.dsp
+++ b/pjsip-apps/build/samples.dsp
@@ -98,6 +98,10 @@ SOURCE=..\src\samples\confsample.c
# End Source File
# Begin Source File
+SOURCE=..\src\samples\encdec.c
+# End Source File
+# Begin Source File
+
SOURCE=..\src\samples\footprint.c
# End Source File
# Begin Source File
diff --git a/pjsip-apps/build/samples.vcproj b/pjsip-apps/build/samples.vcproj
index 74891653..e7326341 100644
--- a/pjsip-apps/build/samples.vcproj
+++ b/pjsip-apps/build/samples.vcproj
@@ -82,6 +82,10 @@
>
</File>
<File
+ RelativePath="..\src\samples\encdec.c"
+ >
+ </File>
+ <File
RelativePath="..\src\samples\footprint.c"
>
</File>
diff --git a/pjsip-apps/src/samples/encdec.c b/pjsip-apps/src/samples/encdec.c
new file mode 100644
index 00000000..39297083
--- /dev/null
+++ b/pjsip-apps/src/samples/encdec.c
@@ -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;
+}
+