BLOG | DOCUMENTATION | TRAC

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

 


PJMEDIA small footprint Open Source media stack
Copyright (C) 2006-2008 Teluu Inc.