1
/* $Id: encdec.c 3664 2011-07-19 03:42:28Z nanang $ */
3
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
* \page page_pjmedia_samples_encdec_c Samples: Encoding and Decoding
24
* This sample shows how to use codec.
26
* This file is pjsip-apps/src/samples/encdec.c
28
* \includelineno encdec.c
33
#include <pjmedia-codec.h>
35
#define THIS_FILE "encdec.c"
37
static const char *desc =
41
" Encode input WAV with a codec, and decode the result to another WAV \n"
45
" encdec codec input.wav output.wav \n"
49
" codec Set the codec name. \n"
50
" input.wav Set the input WAV filename. \n"
51
" output.wav Set the output WAV filename. \n"
64
# define TRACE_(expr) PJ_LOG(4,expr)
70
static void err(const char *op, pj_status_t status)
72
char errmsg[PJ_ERR_MSG_SIZE];
73
pj_strerror(status, errmsg, sizeof(errmsg));
74
PJ_LOG(3,("", "%s error: %s", op, errmsg));
77
#define CHECK(op) do { \
79
if (status != PJ_SUCCESS) { \
86
static pjmedia_endpt *mept;
87
static unsigned file_msec_duration;
89
static pj_status_t enc_dec_test(const char *codec_id,
94
pjmedia_codec_mgr *cm;
96
const pjmedia_codec_info *pci;
97
pjmedia_codec_param param;
98
unsigned cnt, samples_per_frame;
100
pjmedia_port *wavin, *wavout;
104
#define T file_msec_duration/1000, file_msec_duration%1000
106
pool = pjmedia_endpt_create_pool(mept, "encdec", 1000, 1000);
108
cm = pjmedia_endpt_get_codec_mgr(mept);
117
CHECK( pjmedia_codec_mgr_find_codecs_by_id(cm, pj_cstr(&tmp, codec_id),
119
CHECK( pjmedia_codec_mgr_get_default_param(cm, pci, ¶m) );
121
samples_per_frame = param.info.clock_rate * param.info.frm_ptime / 1000;
124
param.setting.vad = 1;
126
/* Open wav for reading */
127
CHECK( pjmedia_wav_player_port_create(pool, filein,
128
param.info.frm_ptime,
129
PJMEDIA_FILE_NO_LOOP, 0, &wavin) );
131
/* Open wav for writing */
132
CHECK( pjmedia_wav_writer_port_create(pool, fileout,
133
param.info.clock_rate,
134
param.info.channel_cnt,
136
16, 0, 0, &wavout) );
139
CHECK( pjmedia_codec_mgr_alloc_codec(cm, pci, &codec) );
140
CHECK( pjmedia_codec_init(codec, pool) );
141
CHECK( pjmedia_codec_open(codec, ¶m) );
144
pjmedia_frame frm_pcm, frm_bit, out_frm, frames[4];
145
pj_int16_t pcmbuf[320];
147
pj_uint8_t bitstream[160];
149
frm_pcm.buf = (char*)pcmbuf;
150
frm_pcm.size = samples_per_frame * 2;
153
if (pjmedia_port_get_frame(wavin, &frm_pcm) != PJ_SUCCESS)
155
if (frm_pcm.type != PJMEDIA_FRAME_TYPE_AUDIO)
158
/* Update duration */
159
file_msec_duration += samples_per_frame * 1000 /
160
param.info.clock_rate;
163
frm_bit.buf = bitstream;
164
frm_bit.size = sizeof(bitstream);
165
CHECK(pjmedia_codec_encode(codec, &frm_pcm, sizeof(bitstream),
168
/* On DTX, write zero frame to wavout to maintain duration */
169
if (frm_bit.size == 0 || frm_bit.type != PJMEDIA_FRAME_TYPE_AUDIO) {
170
out_frm.buf = (char*)pcmbuf;
172
CHECK( pjmedia_port_put_frame(wavout, &out_frm) );
173
TRACE_((THIS_FILE, "%d.%03d read: %u, enc: %u",
174
T, frm_pcm.size, frm_bit.size));
178
/* Parse the bitstream (not really necessary for this case
179
* since we always decode 1 frame, but it's still good
183
cnt = PJ_ARRAY_SIZE(frames);
184
CHECK( pjmedia_codec_parse(codec, bitstream, frm_bit.size, &ts, &cnt,
186
CHECK( (cnt==1 ? PJ_SUCCESS : -1) );
188
/* Decode or simulate packet loss */
189
out_frm.buf = (char*)pcmbuf;
190
out_frm.size = sizeof(pcmbuf);
192
if ((pj_rand() % 100) < (int)lost_pct) {
194
CHECK( pjmedia_codec_recover(codec, sizeof(pcmbuf), &out_frm) );
195
TRACE_((THIS_FILE, "%d.%03d Packet lost", T));
198
CHECK( pjmedia_codec_decode(codec, &frames[0], sizeof(pcmbuf),
203
CHECK( pjmedia_port_put_frame(wavout, &out_frm) );
205
TRACE_((THIS_FILE, "%d.%03d read: %u, enc: %u, dec/write: %u",
206
T, frm_pcm.size, frm_bit.size, out_frm.size));
210
pjmedia_port_destroy(wavout);
211
pjmedia_port_destroy(wavin);
214
pjmedia_codec_close(codec);
215
pjmedia_codec_mgr_dealloc_codec(cm, codec);
218
pj_pool_release(pool);
224
int main(int argc, char *argv[])
237
pj_caching_pool_init(&cp, NULL, 0);
239
CHECK( pjmedia_endpt_create(&cp.factory, NULL, 1, &mept) );
241
/* Register all codecs */
242
CHECK( pjmedia_codec_register_audio_codecs(mept, NULL) );
244
pj_gettimeofday(&t0);
245
status = enc_dec_test(argv[1], argv[2], argv[3]);
246
pj_gettimeofday(&t1);
247
PJ_TIME_VAL_SUB(t1, t0);
249
pjmedia_endpt_destroy(mept);
250
pj_caching_pool_destroy(&cp);
253
if (status == PJ_SUCCESS) {
256
printf("Duration: %ds.%03d\n", file_msec_duration/1000,
257
file_msec_duration%1000);
258
printf("Time: %lds.%03ld\n", t1.sec, t1.msec);