pjsip logo pjsip.org
Open source SIP stack and media stack for presence, im/instant messaging, and multimedia communication

HOME

SIP/media Features
High Performance SIP
Small Footprint SIP
Symbian Port

FAQ

Documentation

Licensing

Download

Development (Trac)

Projects using pjsip

Mailing List

Open Source Links


About: PJLIB, PJLIB-UTIL, PJSIP, and PJMEDIA are created by: Benny Prijono
<bennylp@pjsip.org>


 

Home --> Documentations --> PJMEDIA Reference

Samples: Encoding and Decoding

This sample shows how to use codec.

This file is pjsip-apps/src/samples/encdec.c

00001 /* $Id: encdec.c 2039 2008-06-20 22:44:47Z bennylp $ */
00002 /* 
00003  * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
00018  */
00019 
00030 #include <pjlib.h>
00031 #include <pjmedia.h>
00032 #include <pjmedia-codec.h>
00033 
00034 #define THIS_FILE   "encdec.c"
00035 
00036 static const char *desc = 
00037  " encdec                                                               \n"
00038  "                                                                      \n"
00039  " PURPOSE:                                                             \n"
00040  "  Encode input WAV with a codec, and decode the result to another WAV \n"
00041  "\n"
00042  "\n"
00043  " USAGE:                                                               \n"
00044  "  encdec codec input.wav output.wav                                   \n"
00045  "\n"
00046  "\n"
00047  " where:\n"
00048  "  codec         Set the codec name.                                   \n"
00049  "  input.wav     Set the input WAV filename.                           \n"
00050  "  output.wav    Set the output WAV filename.                          \n"
00051 
00052  "\n"
00053 ;
00054 
00055 //#undef PJ_TRACE
00056 //#define PJ_TRACE 1
00057 
00058 #ifndef PJ_TRACE
00059 #       define PJ_TRACE 0
00060 #endif
00061 
00062 #if PJ_TRACE
00063 #   define TRACE_(expr)     PJ_LOG(4,expr)
00064 #else
00065 #   define TRACE_(expr)
00066 #endif
00067 
00068 
00069 static void err(const char *op, pj_status_t status)
00070 {
00071     char errmsg[PJ_ERR_MSG_SIZE];
00072     pj_strerror(status, errmsg, sizeof(errmsg));
00073     PJ_LOG(3,("", "%s error: %s", op, errmsg));
00074 }
00075 
00076 #define CHECK(op)   do { \
00077                         status = op; \
00078                         if (status != PJ_SUCCESS) { \
00079                             err(#op, status); \
00080                             return status; \
00081                         } \
00082                     } \
00083                     while (0)
00084 
00085 static pjmedia_endpt *mept;
00086 static unsigned file_msec_duration;
00087 
00088 static pj_status_t enc_dec_test(const char *codec_id,
00089                                 const char *filein,
00090                                 const char *fileout)
00091 {
00092     pj_pool_t *pool;
00093     pjmedia_codec_mgr *cm;
00094     pjmedia_codec *codec;
00095     const pjmedia_codec_info *pci;
00096     pjmedia_codec_param param;
00097     unsigned cnt, samples_per_frame;
00098     pj_str_t tmp;
00099     pjmedia_port *wavin, *wavout;
00100     unsigned lost_pct;
00101     pj_status_t status;
00102 
00103 #define T   file_msec_duration/1000, file_msec_duration%1000
00104     
00105     pool = pjmedia_endpt_create_pool(mept, "encdec", 1000, 1000);
00106 
00107     cm = pjmedia_endpt_get_codec_mgr(mept);
00108 
00109 #ifdef LOST_PCT
00110     lost_pct = LOST_PCT;
00111 #else
00112     lost_pct = 0;
00113 #endif
00114     
00115     cnt = 1;
00116     CHECK( pjmedia_codec_mgr_find_codecs_by_id(cm, pj_cstr(&tmp, codec_id), 
00117                                                &cnt, &pci, NULL) );
00118     CHECK( pjmedia_codec_mgr_get_default_param(cm, pci, &param) );
00119 
00120     samples_per_frame = param.info.clock_rate * param.info.frm_ptime / 1000;
00121 
00122     /* Control VAD */
00123     param.setting.vad = 1;
00124 
00125     /* Open wav for reading */
00126     CHECK( pjmedia_wav_player_port_create(pool, filein, 
00127                                           param.info.frm_ptime, 
00128                                           PJMEDIA_FILE_NO_LOOP, 0, &wavin) );
00129 
00130     /* Open wav for writing */
00131     CHECK( pjmedia_wav_writer_port_create(pool, fileout,
00132                                           param.info.clock_rate, 
00133                                           param.info.channel_cnt,
00134                                           samples_per_frame,
00135                                           16, 0, 0, &wavout) );
00136 
00137     /* Alloc codec */
00138     CHECK( pjmedia_codec_mgr_alloc_codec(cm, pci, &codec) );
00139     CHECK( codec->op->init(codec, pool) );
00140     CHECK( codec->op->open(codec, &param) );
00141     
00142     for (;;) {
00143         pjmedia_frame frm_pcm, frm_bit, out_frm, frames[4];
00144         pj_int16_t pcmbuf[320];
00145         pj_timestamp ts;
00146         pj_uint8_t bitstream[160];
00147 
00148         frm_pcm.buf = (char*)pcmbuf;
00149         frm_pcm.size = samples_per_frame * 2;
00150 
00151         /* Read from WAV */
00152         if (pjmedia_port_get_frame(wavin, &frm_pcm) != PJ_SUCCESS)
00153             break;
00154         if (frm_pcm.type != PJMEDIA_FRAME_TYPE_AUDIO)
00155             break;;
00156 
00157         /* Update duration */
00158         file_msec_duration += samples_per_frame * 1000 / 
00159                               param.info.clock_rate;
00160 
00161         /* Encode */
00162         frm_bit.buf = bitstream;
00163         frm_bit.size = sizeof(bitstream);
00164         CHECK(codec->op->encode(codec, &frm_pcm, sizeof(bitstream), &frm_bit));
00165 
00166         /* On DTX, write zero frame to wavout to maintain duration */
00167         if (frm_bit.size == 0 || frm_bit.type != PJMEDIA_FRAME_TYPE_AUDIO) {
00168             out_frm.buf = (char*)pcmbuf;
00169             out_frm.size = 160;
00170             CHECK( pjmedia_port_put_frame(wavout, &out_frm) );
00171             TRACE_((THIS_FILE, "%d.%03d read: %u, enc: %u",
00172                     T, frm_pcm.size, frm_bit.size));
00173             continue;
00174         }
00175         
00176         /* Parse the bitstream (not really necessary for this case
00177          * since we always decode 1 frame, but it's still good
00178          * for testing)
00179          */
00180         ts.u64 = 0;
00181         cnt = PJ_ARRAY_SIZE(frames);
00182         CHECK( codec->op->parse(codec, bitstream, frm_bit.size, &ts, &cnt, 
00183                                 frames) );
00184         CHECK( (cnt==1 ? PJ_SUCCESS : -1) );
00185 
00186         /* Decode or simulate packet loss */
00187         out_frm.buf = (char*)pcmbuf;
00188         out_frm.size = sizeof(pcmbuf);
00189         
00190         if ((pj_rand() % 100) < (int)lost_pct) {
00191             /* Simulate loss */
00192             CHECK( codec->op->recover(codec, sizeof(pcmbuf), &out_frm) );
00193             TRACE_((THIS_FILE, "%d.%03d Packet lost", T));
00194         } else {
00195             /* Decode */
00196             CHECK( codec->op->decode(codec, &frames[0], sizeof(pcmbuf), 
00197                                      &out_frm) );
00198         }
00199 
00200         /* Write to WAV */
00201         CHECK( pjmedia_port_put_frame(wavout, &out_frm) );
00202 
00203         TRACE_((THIS_FILE, "%d.%03d read: %u, enc: %u, dec/write: %u",
00204                 T, frm_pcm.size, frm_bit.size, out_frm.size));
00205     }
00206 
00207     /* Close wavs */
00208     pjmedia_port_destroy(wavout);
00209     pjmedia_port_destroy(wavin);
00210 
00211     /* Close codec */
00212     codec->op->close(codec);
00213     pjmedia_codec_mgr_dealloc_codec(cm, codec);
00214 
00215     /* Release pool */
00216     pj_pool_release(pool);
00217 
00218     return PJ_SUCCESS;
00219 }
00220 
00221 
00222 int main(int argc, char *argv[])
00223 {
00224     pj_caching_pool cp;
00225     pj_time_val t0, t1;
00226     pj_status_t status;
00227 
00228     if (argc != 4) {
00229         puts(desc);
00230         return 1;
00231     }
00232 
00233     CHECK( pj_init() );
00234     
00235     pj_caching_pool_init(&cp, NULL, 0);
00236 
00237     CHECK( pjmedia_endpt_create(&cp.factory, NULL, 1, &mept) );
00238 
00239     /* Register all codecs */
00240 #if PJMEDIA_HAS_G711_CODEC
00241     CHECK( pjmedia_codec_g711_init(mept) );
00242 #endif
00243 #if PJMEDIA_HAS_GSM_CODEC
00244     CHECK( pjmedia_codec_gsm_init(mept) );
00245 #endif
00246 #if PJMEDIA_HAS_ILBC_CODEC
00247     CHECK( pjmedia_codec_ilbc_init(mept, 30) );
00248 #endif
00249 #if PJMEDIA_HAS_SPEEX_CODEC
00250     CHECK( pjmedia_codec_speex_init(mept, 0, 5, 5) );
00251 #endif
00252 #if PJMEDIA_HAS_G722_CODEC
00253     CHECK( pjmedia_codec_g722_init(mept) );
00254 #endif
00255 
00256     pj_gettimeofday(&t0);
00257     status = enc_dec_test(argv[1], argv[2], argv[3]);
00258     pj_gettimeofday(&t1);
00259     PJ_TIME_VAL_SUB(t1, t0);
00260 
00261     pjmedia_endpt_destroy(mept);
00262     pj_caching_pool_destroy(&cp);
00263     pj_shutdown();
00264 
00265     if (status == PJ_SUCCESS) {
00266         puts("");
00267         puts("Success");
00268         printf("Duration: %ds.%03d\n", file_msec_duration/1000, 
00269                                        file_msec_duration%1000);
00270         printf("Time: %lds.%03ld\n", t1.sec, t1.msec);
00271     }
00272 
00273     return 0;
00274 }
00275 

 


PJMEDIA small footprint Open Source media stack
(C)2003-2008 Benny Prijono