WARNING: The online documentation has moved to https://docs.pjsip.org.

Visit the new documentation at https://docs.pjsip.org:

BLOG | DOCUMENTATION | GITHUB

Home --> Documentations --> PJMEDIA Reference

Samples: Encoding and Decoding

This sample shows how to use codec.

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

1/*
2 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
3 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
30#include <pjlib.h>
31#include <pjmedia.h>
32#include <pjmedia-codec.h>
33
34#define THIS_FILE "encdec.c"
35
36static const char *desc =
37 " encdec \n"
38 " \n"
39 " PURPOSE: \n"
40 " Encode input WAV with a codec, and decode the result to another WAV \n"
41 "\n"
42 "\n"
43 " USAGE: \n"
44 " encdec codec input.wav output.wav \n"
45 "\n"
46 "\n"
47 " where:\n"
48 " codec Set the codec name. \n"
49 " input.wav Set the input WAV filename. \n"
50 " output.wav Set the output WAV filename. \n"
51
52 "\n"
53;
54
55//#undef PJ_TRACE
56//#define PJ_TRACE 1
57
58#ifndef PJ_TRACE
59# define PJ_TRACE 0
60#endif
61
62#if PJ_TRACE
63# define TRACE_(expr) PJ_LOG(4,expr)
64#else
65# define TRACE_(expr)
66#endif
67
68
69static void err(const char *op, pj_status_t status)
70{
71 char errmsg[PJ_ERR_MSG_SIZE];
72 pj_strerror(status, errmsg, sizeof(errmsg));
73 PJ_LOG(3,("", "%s error: %s", op, errmsg));
74}
75
76#define CHECK(op) do { \
77 status = op; \
78 if (status != PJ_SUCCESS) { \
79 err(#op, status); \
80 return status; \
81 } \
82 } \
83 while (0)
84
85static pjmedia_endpt *mept;
86static unsigned file_msec_duration;
87
88static pj_status_t enc_dec_test(const char *codec_id,
89 const char *filein,
90 const char *fileout)
91{
92 pj_pool_t *pool;
95 const pjmedia_codec_info *pci;
97 unsigned cnt, samples_per_frame;
98 pj_str_t tmp;
99 pjmedia_port *wavin, *wavout;
100 unsigned lost_pct;
101 unsigned bitstream_size = 0;
102 pj_status_t status;
103
104#define T file_msec_duration/1000, file_msec_duration%1000
105
106 pool = pjmedia_endpt_create_pool(mept, "encdec", 1000, 1000);
107
109
110#ifdef LOST_PCT
111 lost_pct = LOST_PCT;
112#else
113 lost_pct = 0;
114#endif
115
116 cnt = 1;
117 CHECK( pjmedia_codec_mgr_find_codecs_by_id(cm, pj_cstr(&tmp, codec_id),
118 &cnt, &pci, NULL) );
119 CHECK( pjmedia_codec_mgr_get_default_param(cm, pci, &param) );
120
121 samples_per_frame = param.info.clock_rate * param.info.frm_ptime / 1000;
122
123 /* Control VAD */
124 param.setting.vad = 1;
125
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) );
130
131 /* Open wav for writing */
132 CHECK( pjmedia_wav_writer_port_create(pool, fileout,
133 param.info.clock_rate,
134 param.info.channel_cnt,
135 samples_per_frame,
136 16, 0, 0, &wavout) );
137
138 /* Alloc codec */
139 CHECK( pjmedia_codec_mgr_alloc_codec(cm, pci, &codec) );
140 CHECK( pjmedia_codec_init(codec, pool) );
141 CHECK( pjmedia_codec_open(codec, &param) );
142
143 for (;;) {
144 pjmedia_frame frm_pcm, frm_bit, out_frm, frames[4];
145 pj_int16_t pcmbuf[2048];
146 pj_timestamp ts;
147 pj_uint8_t bitstream[2048];
148
149 frm_pcm.buf = (char*)pcmbuf;
150 frm_pcm.size = samples_per_frame * 2;
151
152 /* Read from WAV */
153 if (pjmedia_port_get_frame(wavin, &frm_pcm) != PJ_SUCCESS)
154 break;
155 if (frm_pcm.type != PJMEDIA_FRAME_TYPE_AUDIO)
156 break;;
157
158 /* Update duration */
159 file_msec_duration += samples_per_frame * 1000 /
160 param.info.clock_rate;
161
162 /* Encode */
163 frm_bit.buf = bitstream;
164 frm_bit.size = sizeof(bitstream);
165 CHECK(pjmedia_codec_encode(codec, &frm_pcm, sizeof(bitstream),
166 &frm_bit));
167
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;
171 out_frm.size = 160;
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));
175 continue;
176 }
177
178 bitstream_size += (unsigned)frm_bit.size;
179
180 /* Parse the bitstream (not really necessary for this case
181 * since we always decode 1 frame, but it's still good
182 * for testing)
183 */
184 ts.u64 = 0;
185 cnt = PJ_ARRAY_SIZE(frames);
186 CHECK( pjmedia_codec_parse(codec, bitstream, frm_bit.size, &ts, &cnt,
187 frames) );
188 CHECK( (cnt==1 ? PJ_SUCCESS : -1) );
189
190 /* Decode or simulate packet loss */
191 out_frm.buf = (char*)pcmbuf;
192 out_frm.size = sizeof(pcmbuf);
193
194 if ((pj_rand() % 100) < (int)lost_pct) {
195 /* Simulate loss */
196 CHECK( pjmedia_codec_recover(codec, sizeof(pcmbuf), &out_frm) );
197 TRACE_((THIS_FILE, "%d.%03d Packet lost", T));
198 } else {
199 /* Decode */
200 CHECK( pjmedia_codec_decode(codec, &frames[0], sizeof(pcmbuf),
201 &out_frm) );
202 }
203
204 /* Write to WAV */
205 CHECK( pjmedia_port_put_frame(wavout, &out_frm) );
206
207 TRACE_((THIS_FILE, "%d.%03d read: %u, enc: %u, dec/write: %u",
208 T, frm_pcm.size, frm_bit.size, out_frm.size));
209 }
210
211 /* Close wavs */
212 pjmedia_port_destroy(wavout);
214
215 /* Close codec */
218
219 /* Release pool */
220 pj_pool_release(pool);
221
222 printf("Total encoded size: %u bytes\n", bitstream_size);
223 printf("Bitrate: %.3fKbps\n", bitstream_size*8.0/file_msec_duration);
224 return PJ_SUCCESS;
225}
226
227
228int main(int argc, char *argv[])
229{
231 pj_time_val t0, t1;
232 pj_status_t status;
233
234 if (argc != 4) {
235 puts(desc);
236 return 1;
237 }
238
239 CHECK( pj_init() );
240
241 pj_caching_pool_init(&cp, NULL, 0);
242
243 CHECK( pjmedia_endpt_create(&cp.factory, NULL, 1, &mept) );
244
245 /* Register all codecs */
246 CHECK( pjmedia_codec_register_audio_codecs(mept, NULL) );
247
248 pj_gettimeofday(&t0);
249 status = enc_dec_test(argv[1], argv[2], argv[3]);
250 pj_gettimeofday(&t1);
251 PJ_TIME_VAL_SUB(t1, t0);
252
255 pj_shutdown();
256
257 if (status == PJ_SUCCESS) {
258 puts("");
259 puts("Success");
260 printf("Duration: %ds.%03d\n", file_msec_duration/1000,
261 file_msec_duration%1000);
262 printf("Time: %lds.%03ld\n", t1.sec, t1.msec);
263 }
264
265 return 0;
266}
267
pj_status_t pjmedia_codec_register_audio_codecs(pjmedia_endpt *endpt, const pjmedia_audio_codec_config *c)
pj_status_t pjmedia_codec_close(pjmedia_codec *codec)
Definition: codec.h:994
pj_status_t pjmedia_codec_decode(pjmedia_codec *codec, const struct pjmedia_frame *input, unsigned out_size, struct pjmedia_frame *output)
Definition: codec.h:1085
pj_status_t pjmedia_codec_mgr_alloc_codec(pjmedia_codec_mgr *mgr, const pjmedia_codec_info *info, pjmedia_codec **p_codec)
pj_status_t pjmedia_codec_mgr_get_default_param(pjmedia_codec_mgr *mgr, const pjmedia_codec_info *info, pjmedia_codec_param *param)
pj_status_t pjmedia_codec_mgr_find_codecs_by_id(pjmedia_codec_mgr *mgr, const pj_str_t *codec_id, unsigned *count, const pjmedia_codec_info *p_info[], unsigned prio[])
pj_status_t pjmedia_codec_open(pjmedia_codec *codec, pjmedia_codec_param *param)
Definition: codec.h:979
pj_status_t pjmedia_codec_mgr_dealloc_codec(pjmedia_codec_mgr *mgr, pjmedia_codec *codec)
pj_status_t pjmedia_codec_encode(pjmedia_codec *codec, const struct pjmedia_frame *input, unsigned out_size, struct pjmedia_frame *output)
Definition: codec.h:1061
pj_status_t pjmedia_codec_init(pjmedia_codec *codec, pj_pool_t *pool)
Definition: codec.h:961
pj_status_t pjmedia_codec_parse(pjmedia_codec *codec, void *pkt, pj_size_t pkt_size, const pj_timestamp *timestamp, unsigned *frame_cnt, pjmedia_frame frames[])
Definition: codec.h:1037
pj_status_t pjmedia_codec_recover(pjmedia_codec *codec, unsigned out_size, struct pjmedia_frame *output)
Definition: codec.h:1105
pj_status_t pjmedia_wav_player_port_create(pj_pool_t *pool, const char *filename, unsigned ptime, unsigned flags, pj_ssize_t buff_size, pjmedia_port **p_port)
@ PJMEDIA_FILE_NO_LOOP
Definition: wav_port.h:49
pj_status_t pjmedia_wav_writer_port_create(pj_pool_t *pool, const char *filename, unsigned clock_rate, unsigned channel_count, unsigned samples_per_frame, unsigned bits_per_sample, unsigned flags, pj_ssize_t buff_size, pjmedia_port **p_port)
@ PJMEDIA_FRAME_TYPE_AUDIO
Definition: frame.h:45
pj_status_t pjmedia_port_put_frame(pjmedia_port *port, pjmedia_frame *frame)
pj_status_t pjmedia_port_destroy(pjmedia_port *port)
pj_status_t pjmedia_port_get_frame(pjmedia_port *port, pjmedia_frame *frame)
struct pjmedia_endpt pjmedia_endpt
Definition: pjmedia/types.h:186
pj_status_t pjmedia_endpt_create(pj_pool_factory *pf, pj_ioqueue_t *ioqueue, unsigned worker_cnt, pjmedia_endpt **p_endpt)
Definition: endpoint.h:127
pj_pool_t * pjmedia_endpt_create_pool(pjmedia_endpt *endpt, const char *name, pj_size_t initial, pj_size_t increment)
pj_status_t pjmedia_endpt_destroy(pjmedia_endpt *endpt)
Definition: endpoint.h:168
pjmedia_codec_mgr * pjmedia_endpt_get_codec_mgr(pjmedia_endpt *endpt)
unsigned char pj_uint8_t
pj_status_t pj_init(void)
short pj_int16_t
int pj_status_t
#define PJ_ARRAY_SIZE(a)
void pj_shutdown(void)
PJ_SUCCESS
void pj_caching_pool_destroy(pj_caching_pool *ch_pool)
void pj_caching_pool_init(pj_caching_pool *ch_pool, const pj_pool_factory_policy *policy, pj_size_t max_capacity)
#define PJ_LOG(level, arg)
void pj_pool_release(pj_pool_t *pool)
const pj_str_t * pj_cstr(pj_str_t *str, const char *s)
int pj_rand(void)
pj_status_t pj_gettimeofday(pj_time_val *tv)
#define PJ_TIME_VAL_SUB(t1, t2)
#define PJ_ERR_MSG_SIZE
pj_str_t pj_strerror(pj_status_t statcode, char *buf, pj_size_t bufsize)
Include all codecs API in PJMEDIA-CODEC.
PJMEDIA main header file.
Definition: siprtp.c:101
pj_pool_factory factory
Definition: codec.h:235
Definition: codec.h:705
Definition: codec.h:268
struct pjmedia_codec_param::@8 info
unsigned channel_cnt
Definition: codec.h:275
unsigned clock_rate
Definition: codec.h:274
struct pjmedia_codec_param::@9 setting
unsigned vad
Definition: codec.h:300
pj_uint16_t frm_ptime
Definition: codec.h:279
Definition: codec.h:502
Definition: frame.h:56
pjmedia_frame_type type
Definition: frame.h:57
void * buf
Definition: frame.h:58
pj_size_t size
Definition: frame.h:59
Definition: port.h:378

 


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