From 1d0950491c7823396ab571eb66984467e95bfae7 Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Fri, 11 Jan 2008 09:01:50 +0000 Subject: Ticket #445: added codec encoding/decoding sample git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1678 74dad513-b988-da41-8d7b-12977e46ad98 --- pjsip-apps/build/Samples-vc.mak | 1 + pjsip-apps/build/Samples.mak | 1 + pjsip-apps/build/samples.dsp | 4 + pjsip-apps/build/samples.vcproj | 4 + pjsip-apps/src/samples/encdec.c | 245 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 255 insertions(+) create mode 100644 pjsip-apps/src/samples/encdec.c (limited to 'pjsip-apps') 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 @@ -81,6 +81,10 @@ RelativePath="..\src\samples\confsample.c" > + + 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 + * + * 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 +#include +#include + +#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, ¶m) ); + + 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, ¶m) ); + + 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; +} + -- cgit v1.2.3