~ubuntu-branches/ubuntu/trusty/sflphone/trusty

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.1.0/pjsip-apps/src/samples/pcaputil.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (4.3.4 sid)
  • Revision ID: package-import@ubuntu.com-20140128182336-jrsv0k9u6cawc068
Tags: 1.3.0-1
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: pcaputil.c 3841 2011-10-24 09:28:13Z ming $ */
 
2
/* 
 
3
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
 
4
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
 
5
 *
 
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.
 
10
 *
 
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.
 
15
 *
 
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 
 
19
 */
 
20
#include <pjlib.h>
 
21
#include <pjlib-util.h>
 
22
#include <pjmedia.h>
 
23
#include <pjmedia-codec.h>
 
24
 
 
25
static const char *USAGE =
 
26
"pcaputil [options] INPUT OUTPUT\n"
 
27
"\n"
 
28
"  Convert captured RTP packets in PCAP file to WAV file or play it\n"
 
29
"  to audio device.\n"
 
30
"\n"
 
31
"  INPUT  is the PCAP file name/path.\n"
 
32
"  OUTPUT is the WAV file name/path to store the output, or set to \"-\",\n"
 
33
"         to play the output to audio device. The program will decode\n"
 
34
"         the RTP contents using codec that is available in PJMEDIA,\n"
 
35
"         and optionally decrypt the content using the SRTP crypto and\n"
 
36
"         keys below.\n"
 
37
"\n"
 
38
"Options to filter packets from PCAP file:\n"
 
39
"(you can always select the relevant packets from Wireshark of course!)\n"
 
40
"  --src-ip=IP            Only include packets from this source address\n"
 
41
"  --dst-ip=IP            Only include packets destined to this address\n"
 
42
"  --src-port=port        Only include packets from this source port number\n"
 
43
"  --dst-port=port        Only include packets destined to this port number\n"
 
44
"\n"
 
45
"Options for RTP packet processing:\n"
 
46
""
 
47
"  --codec=codec_id       The codec ID formatted \"name/clock-rate/channel-count\"\n"
 
48
"                         must be specified for codec with dynamic PT,\n"
 
49
"                         e.g: \"Speex/8000\"\n"
 
50
"  --srtp-crypto=TAG, -c  Set crypto to be used to decrypt SRTP packets. Valid\n"
 
51
"                         tags are: \n"
 
52
"                           AES_CM_128_HMAC_SHA1_80 \n"
 
53
"                           AES_CM_128_HMAC_SHA1_32\n"
 
54
"  --srtp-key=KEY, -k     Set the base64 key to decrypt SRTP packets.\n"
 
55
"\n"
 
56
"Options for playing to audio device:\n"
 
57
""
 
58
"  --play-dev-id=dev_id   Audio device ID for playback.\n"
 
59
"\n"
 
60
"  Example:\n"
 
61
"    pcaputil file.pcap output.wav\n"
 
62
"    pcaputil -c AES_CM_128_HMAC_SHA1_80 \\\n"
 
63
"             -k VLDONbsbGl2Puqy+0PV7w/uGfpSPKFevDpxGsxN3 \\\n"
 
64
"             file.pcap output.wav\n"
 
65
"\n"
 
66
;
 
67
 
 
68
static struct app
 
69
{
 
70
    pj_caching_pool      cp;
 
71
    pj_pool_t           *pool;
 
72
    pjmedia_endpt       *mept;
 
73
    pj_pcap_file        *pcap;
 
74
    pjmedia_port        *wav;
 
75
    pjmedia_codec       *codec;
 
76
    pjmedia_aud_stream  *aud_strm;
 
77
    unsigned             pt;
 
78
    pjmedia_transport   *srtp;
 
79
    pjmedia_rtp_session  rtp_sess;
 
80
    pj_bool_t            rtp_sess_init;
 
81
} app;
 
82
 
 
83
 
 
84
static void cleanup()
 
85
{
 
86
    if (app.srtp) pjmedia_transport_close(app.srtp);
 
87
    if (app.wav) {
 
88
        pj_ssize_t pos = pjmedia_wav_writer_port_get_pos(app.wav);
 
89
        if (pos >= 0) {
 
90
            unsigned msec;
 
91
            msec = pos / 2 * 1000 / PJMEDIA_PIA_SRATE(&app.wav->info);
 
92
            printf("Written: %dm:%02ds.%03d\n",
 
93
                    msec / 1000 / 60,
 
94
                    (msec / 1000) % 60,
 
95
                    msec % 1000);
 
96
        }
 
97
        pjmedia_port_destroy(app.wav);
 
98
    }
 
99
    if (app.pcap) pj_pcap_close(app.pcap);
 
100
    if (app.codec) {
 
101
        pjmedia_codec_mgr *cmgr;
 
102
        pjmedia_codec_close(app.codec);
 
103
        cmgr = pjmedia_endpt_get_codec_mgr(app.mept);
 
104
        pjmedia_codec_mgr_dealloc_codec(cmgr, app.codec);
 
105
    }
 
106
    if (app.aud_strm) {
 
107
        pjmedia_aud_stream_stop(app.aud_strm);
 
108
        pjmedia_aud_stream_destroy(app.aud_strm);
 
109
    }
 
110
    if (app.mept) pjmedia_endpt_destroy(app.mept);
 
111
    if (app.pool) pj_pool_release(app.pool);
 
112
    pj_caching_pool_destroy(&app.cp);
 
113
    pj_shutdown();
 
114
}
 
115
 
 
116
static void err_exit(const char *title, pj_status_t status)
 
117
{
 
118
    if (status != PJ_SUCCESS) {
 
119
        char errmsg[PJ_ERR_MSG_SIZE];
 
120
        pj_strerror(status, errmsg, sizeof(errmsg));
 
121
        printf("Error: %s: %s\n", title, errmsg);
 
122
    } else {
 
123
        printf("Error: %s\n", title);
 
124
    }
 
125
    cleanup();
 
126
    exit(1);
 
127
}
 
128
 
 
129
#define T(op)       do { \
 
130
                        status = op; \
 
131
                        if (status != PJ_SUCCESS) \
 
132
                            err_exit(#op, status); \
 
133
                    } while (0)
 
134
 
 
135
 
 
136
static void read_rtp(pj_uint8_t *buf, pj_size_t bufsize,
 
137
                     pjmedia_rtp_hdr **rtp,
 
138
                     pj_uint8_t **payload,
 
139
                     unsigned *payload_size,
 
140
                     pj_bool_t check_pt)
 
141
{
 
142
    pj_status_t status;
 
143
 
 
144
    /* Init RTP session */
 
145
    if (!app.rtp_sess_init) {
 
146
        T(pjmedia_rtp_session_init(&app.rtp_sess, 0, 0));
 
147
        app.rtp_sess_init = PJ_TRUE;
 
148
    }
 
149
 
 
150
    /* Loop reading until we have a good RTP packet */
 
151
    for (;;) {
 
152
        pj_size_t sz = bufsize;
 
153
        const pjmedia_rtp_hdr *r;
 
154
        const void *p;
 
155
        pjmedia_rtp_status seq_st;
 
156
 
 
157
        status = pj_pcap_read_udp(app.pcap, NULL, buf, &sz);
 
158
        if (status != PJ_SUCCESS)
 
159
            err_exit("Error reading PCAP file", status);
 
160
 
 
161
        /* Decode RTP packet to make sure that this is an RTP packet.
 
162
         * We will decode it again to get the payload after we do
 
163
         * SRTP decoding
 
164
         */
 
165
        status = pjmedia_rtp_decode_rtp(&app.rtp_sess, buf, sz, &r, 
 
166
                                        &p, payload_size);
 
167
        if (status != PJ_SUCCESS) {
 
168
            char errmsg[PJ_ERR_MSG_SIZE];
 
169
            pj_strerror(status, errmsg, sizeof(errmsg));
 
170
            printf("Not RTP packet, skipping packet: %s\n", errmsg);
 
171
            continue;
 
172
        }
 
173
 
 
174
        /* Decrypt SRTP */
 
175
#if PJMEDIA_HAS_SRTP
 
176
        if (app.srtp) {
 
177
            int len = sz;
 
178
            status = pjmedia_transport_srtp_decrypt_pkt(app.srtp, PJ_TRUE, 
 
179
                                                        buf, &len);
 
180
            if (status != PJ_SUCCESS) {
 
181
                char errmsg[PJ_ERR_MSG_SIZE];
 
182
                pj_strerror(status, errmsg, sizeof(errmsg));
 
183
                printf("SRTP packet decryption failed, skipping packet: %s\n", 
 
184
                        errmsg);
 
185
                continue;
 
186
            }
 
187
            sz = len;
 
188
 
 
189
            /* Decode RTP packet again */
 
190
            status = pjmedia_rtp_decode_rtp(&app.rtp_sess, buf, sz, &r,
 
191
                                            &p, payload_size);
 
192
            if (status != PJ_SUCCESS) {
 
193
                char errmsg[PJ_ERR_MSG_SIZE];
 
194
                pj_strerror(status, errmsg, sizeof(errmsg));
 
195
                printf("Not RTP packet, skipping packet: %s\n", errmsg);
 
196
                continue;
 
197
            }
 
198
        }
 
199
#endif
 
200
 
 
201
        /* Update RTP session */
 
202
        pjmedia_rtp_session_update2(&app.rtp_sess, r, &seq_st, PJ_FALSE);
 
203
 
 
204
        /* Skip out-of-order packet */
 
205
        if (seq_st.diff == 0) {
 
206
            printf("Skipping out of order packet\n");
 
207
            continue;
 
208
        }
 
209
 
 
210
        /* Skip if payload type is different */
 
211
        if (check_pt && r->pt != app.pt) {
 
212
            printf("Skipping RTP packet with bad payload type\n");
 
213
            continue;
 
214
        }
 
215
 
 
216
        /* Skip bad packet */
 
217
        if (seq_st.status.flag.bad) {
 
218
            printf("Skipping bad RTP\n");
 
219
            continue;
 
220
        }
 
221
 
 
222
 
 
223
        *rtp = (pjmedia_rtp_hdr*)r;
 
224
        *payload = (pj_uint8_t*)p;
 
225
 
 
226
        /* We have good packet */
 
227
        break;
 
228
    }
 
229
}
 
230
 
 
231
pjmedia_frame play_frm;
 
232
static pj_bool_t play_frm_copied, play_frm_ready;
 
233
 
 
234
static pj_status_t wait_play(pjmedia_frame *f)
 
235
{
 
236
    play_frm_copied = PJ_FALSE;
 
237
    play_frm = *f;
 
238
    play_frm_ready = PJ_TRUE;
 
239
    while (!play_frm_copied) {
 
240
        pj_thread_sleep(1);
 
241
    }
 
242
    play_frm_ready = PJ_FALSE;
 
243
 
 
244
    return PJ_SUCCESS;
 
245
}
 
246
 
 
247
static pj_status_t play_cb(void *user_data, pjmedia_frame *f)
 
248
{
 
249
    PJ_UNUSED_ARG(user_data);
 
250
 
 
251
    if (!play_frm_ready) {
 
252
        PJ_LOG(3, ("play_cb()", "Warning! Play frame not ready")); 
 
253
        return PJ_SUCCESS;
 
254
    }
 
255
 
 
256
    pj_memcpy(f->buf, play_frm.buf, play_frm.size);
 
257
    f->size = play_frm.size;
 
258
 
 
259
    play_frm_copied = PJ_TRUE;
 
260
    return PJ_SUCCESS;
 
261
}
 
262
 
 
263
static void pcap2wav(const pj_str_t *codec,
 
264
                     const pj_str_t *wav_filename,
 
265
                     pjmedia_aud_dev_index dev_id,
 
266
                     const pj_str_t *srtp_crypto,
 
267
                     const pj_str_t *srtp_key)
 
268
{
 
269
    const pj_str_t WAV = {".wav", 4};
 
270
    struct pkt
 
271
    {
 
272
        pj_uint8_t       buffer[320];
 
273
        pjmedia_rtp_hdr *rtp;
 
274
        pj_uint8_t      *payload;
 
275
        unsigned         payload_len;
 
276
    } pkt0;
 
277
    pjmedia_codec_mgr *cmgr;
 
278
    const pjmedia_codec_info *ci;
 
279
    pjmedia_codec_param param;
 
280
    unsigned samples_per_frame;
 
281
    pj_status_t status;
 
282
 
 
283
    /* Initialize all codecs */
 
284
    T( pjmedia_codec_register_audio_codecs(app.mept, NULL) );
 
285
 
 
286
    /* Create SRTP transport is needed */
 
287
#if PJMEDIA_HAS_SRTP
 
288
    if (srtp_crypto->slen) {
 
289
        pjmedia_srtp_crypto crypto;
 
290
 
 
291
        pj_bzero(&crypto, sizeof(crypto));
 
292
        crypto.key = *srtp_key;
 
293
        crypto.name = *srtp_crypto;
 
294
        T( pjmedia_transport_srtp_create(app.mept, NULL, NULL, &app.srtp) );
 
295
        T( pjmedia_transport_srtp_start(app.srtp, &crypto, &crypto) );
 
296
    }
 
297
#else
 
298
    PJ_UNUSED_ARG(srtp_crypto);
 
299
    PJ_UNUSED_ARG(srtp_key);
 
300
#endif
 
301
 
 
302
    /* Read first packet */
 
303
    read_rtp(pkt0.buffer, sizeof(pkt0.buffer), &pkt0.rtp, 
 
304
             &pkt0.payload, &pkt0.payload_len, PJ_FALSE);
 
305
 
 
306
    cmgr = pjmedia_endpt_get_codec_mgr(app.mept);
 
307
 
 
308
    /* Get codec info and param for the specified payload type */
 
309
    app.pt = pkt0.rtp->pt;
 
310
    if (app.pt >=0 && app.pt < 96) {
 
311
        T( pjmedia_codec_mgr_get_codec_info(cmgr, pkt0.rtp->pt, &ci) );
 
312
    } else {
 
313
        unsigned cnt = 2;
 
314
        const pjmedia_codec_info *info[2];
 
315
        T( pjmedia_codec_mgr_find_codecs_by_id(cmgr, codec, &cnt, 
 
316
                                               info, NULL) );
 
317
        if (cnt != 1)
 
318
            err_exit("Codec ID must be specified and unique!", 0);
 
319
 
 
320
        ci = info[0];
 
321
    }
 
322
    T( pjmedia_codec_mgr_get_default_param(cmgr, ci, &param) );
 
323
 
 
324
    /* Alloc and init codec */
 
325
    T( pjmedia_codec_mgr_alloc_codec(cmgr, ci, &app.codec) );
 
326
    T( pjmedia_codec_init(app.codec, app.pool) );
 
327
    T( pjmedia_codec_open(app.codec, &param) );
 
328
 
 
329
    /* Init audio device or WAV file */
 
330
    samples_per_frame = ci->clock_rate * param.info.frm_ptime / 1000;
 
331
    if (pj_strcmp2(wav_filename, "-") == 0) {
 
332
        pjmedia_aud_param aud_param;
 
333
 
 
334
        /* Open audio device */
 
335
        T( pjmedia_aud_dev_default_param(dev_id, &aud_param) );
 
336
        aud_param.dir = PJMEDIA_DIR_PLAYBACK;
 
337
        aud_param.channel_count = ci->channel_cnt;
 
338
        aud_param.clock_rate = ci->clock_rate;
 
339
        aud_param.samples_per_frame = samples_per_frame;
 
340
        T( pjmedia_aud_stream_create(&aud_param, NULL, &play_cb, 
 
341
                                     NULL, &app.aud_strm) );
 
342
        T( pjmedia_aud_stream_start(app.aud_strm) );
 
343
    } else if (pj_stristr(wav_filename, &WAV)) {
 
344
        /* Open WAV file */
 
345
        T( pjmedia_wav_writer_port_create(app.pool, wav_filename->ptr,
 
346
                                          ci->clock_rate, ci->channel_cnt,
 
347
                                          samples_per_frame,
 
348
                                          param.info.pcm_bits_per_sample, 0, 0,
 
349
                                          &app.wav) );
 
350
    } else {
 
351
        err_exit("invalid output file", PJ_EINVAL);
 
352
    }
 
353
 
 
354
    /* Loop reading PCAP and writing WAV file */
 
355
    for (;;) {
 
356
        struct pkt pkt1;
 
357
        pj_timestamp ts;
 
358
        pjmedia_frame frames[16], pcm_frame;
 
359
        short pcm[320];
 
360
        unsigned i, frame_cnt;
 
361
        long samples_cnt, ts_gap;
 
362
 
 
363
        pj_assert(sizeof(pcm) >= samples_per_frame);
 
364
 
 
365
        /* Parse first packet */
 
366
        ts.u64 = 0;
 
367
        frame_cnt = PJ_ARRAY_SIZE(frames);
 
368
        T( pjmedia_codec_parse(app.codec, pkt0.payload, pkt0.payload_len, 
 
369
                                &ts, &frame_cnt, frames) );
 
370
 
 
371
        /* Decode and write to WAV file */
 
372
        samples_cnt = 0;
 
373
        for (i=0; i<frame_cnt; ++i) {
 
374
            pjmedia_frame pcm_frame;
 
375
 
 
376
            pcm_frame.buf = pcm;
 
377
            pcm_frame.size = samples_per_frame * 2;
 
378
 
 
379
            T( pjmedia_codec_decode(app.codec, &frames[i], pcm_frame.size, 
 
380
                                     &pcm_frame) );
 
381
            if (app.wav) {
 
382
                T( pjmedia_port_put_frame(app.wav, &pcm_frame) );
 
383
            }
 
384
            if (app.aud_strm) {
 
385
                T( wait_play(&pcm_frame) );
 
386
            }
 
387
            samples_cnt += samples_per_frame;
 
388
        }
 
389
 
 
390
        /* Read next packet */
 
391
        read_rtp(pkt1.buffer, sizeof(pkt1.buffer), &pkt1.rtp,
 
392
                 &pkt1.payload, &pkt1.payload_len, PJ_TRUE);
 
393
 
 
394
        /* Fill in the gap (if any) between pkt0 and pkt1 */
 
395
        ts_gap = pj_ntohl(pkt1.rtp->ts) - pj_ntohl(pkt0.rtp->ts) -
 
396
                 samples_cnt;
 
397
        while (ts_gap >= (long)samples_per_frame) {
 
398
 
 
399
            pcm_frame.buf = pcm;
 
400
            pcm_frame.size = samples_per_frame * 2;
 
401
 
 
402
            if (app.codec->op->recover) {
 
403
                T( pjmedia_codec_recover(app.codec, pcm_frame.size, 
 
404
                                         &pcm_frame) );
 
405
            } else {
 
406
                pj_bzero(pcm_frame.buf, pcm_frame.size);
 
407
            }
 
408
 
 
409
            if (app.wav) {
 
410
                T( pjmedia_port_put_frame(app.wav, &pcm_frame) );
 
411
            }
 
412
            if (app.aud_strm) {
 
413
                T( wait_play(&pcm_frame) );
 
414
            }
 
415
            ts_gap -= samples_per_frame;
 
416
        }
 
417
        
 
418
        /* Next */
 
419
        pkt0 = pkt1;
 
420
        pkt0.rtp = (pjmedia_rtp_hdr*)pkt0.buffer;
 
421
        pkt0.payload = pkt0.buffer + (pkt1.payload - pkt1.buffer);
 
422
    }
 
423
}
 
424
 
 
425
 
 
426
int main(int argc, char *argv[])
 
427
{
 
428
    pj_str_t input, output, srtp_crypto, srtp_key, codec;
 
429
    pjmedia_aud_dev_index dev_id = PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV;
 
430
    pj_pcap_filter filter;
 
431
    pj_status_t status;
 
432
 
 
433
    enum { 
 
434
        OPT_SRC_IP = 1, OPT_DST_IP, OPT_SRC_PORT, OPT_DST_PORT,
 
435
        OPT_CODEC, OPT_PLAY_DEV_ID
 
436
    };
 
437
    struct pj_getopt_option long_options[] = {
 
438
        { "srtp-crypto",    1, 0, 'c' },
 
439
        { "srtp-key",       1, 0, 'k' },
 
440
        { "src-ip",         1, 0, OPT_SRC_IP },
 
441
        { "dst-ip",         1, 0, OPT_DST_IP },
 
442
        { "src-port",       1, 0, OPT_SRC_PORT },
 
443
        { "dst-port",       1, 0, OPT_DST_PORT },
 
444
        { "codec",          1, 0, OPT_CODEC },
 
445
        { "play-dev-id",    1, 0, OPT_PLAY_DEV_ID },
 
446
        { NULL, 0, 0, 0}
 
447
    };
 
448
    int c;
 
449
    int option_index;
 
450
    char key_bin[32];
 
451
 
 
452
    srtp_crypto.slen = srtp_key.slen = 0;
 
453
    codec.slen = 0;
 
454
 
 
455
    pj_pcap_filter_default(&filter);
 
456
    filter.link = PJ_PCAP_LINK_TYPE_ETH;
 
457
    filter.proto = PJ_PCAP_PROTO_TYPE_UDP;
 
458
 
 
459
    /* Parse arguments */
 
460
    pj_optind = 0;
 
461
    while((c=pj_getopt_long(argc,argv, "c:k:", long_options, &option_index))!=-1) {
 
462
        switch (c) {
 
463
        case 'c':
 
464
            srtp_crypto = pj_str(pj_optarg);
 
465
            break;
 
466
        case 'k':
 
467
            {
 
468
                int key_len = sizeof(key_bin);
 
469
                srtp_key = pj_str(pj_optarg);
 
470
                if (pj_base64_decode(&srtp_key, (pj_uint8_t*)key_bin, &key_len)) {
 
471
                    puts("Error: invalid key");
 
472
                    return 1;
 
473
                }
 
474
                srtp_key.ptr = key_bin;
 
475
                srtp_key.slen = key_len;
 
476
            }
 
477
            break;
 
478
        case OPT_SRC_IP:
 
479
            {
 
480
                pj_str_t t = pj_str(pj_optarg);
 
481
                pj_in_addr a = pj_inet_addr(&t);
 
482
                filter.ip_src = a.s_addr;
 
483
            }
 
484
            break;
 
485
        case OPT_DST_IP:
 
486
            {
 
487
                pj_str_t t = pj_str(pj_optarg);
 
488
                pj_in_addr a = pj_inet_addr(&t);
 
489
                filter.ip_dst = a.s_addr;
 
490
            }
 
491
            break;
 
492
        case OPT_SRC_PORT:
 
493
            filter.src_port = pj_htons((pj_uint16_t)atoi(pj_optarg));
 
494
            break;
 
495
        case OPT_DST_PORT:
 
496
            filter.dst_port = pj_htons((pj_uint16_t)atoi(pj_optarg));
 
497
            break;
 
498
        case OPT_CODEC:
 
499
            codec = pj_str(pj_optarg);
 
500
            break;
 
501
        case OPT_PLAY_DEV_ID:
 
502
            dev_id = atoi(pj_optarg);
 
503
            break;
 
504
        default:
 
505
            puts("Error: invalid option");
 
506
            return 1;
 
507
        }
 
508
    }
 
509
 
 
510
    if (pj_optind != argc - 2) {
 
511
        puts(USAGE);
 
512
        return 1;
 
513
    }
 
514
 
 
515
    if (!(srtp_crypto.slen) != !(srtp_key.slen)) {
 
516
        puts("Error: both SRTP crypto and key must be specified");
 
517
        puts(USAGE);
 
518
        return 1;
 
519
    }
 
520
 
 
521
    input = pj_str(argv[pj_optind]);
 
522
    output = pj_str(argv[pj_optind+1]);
 
523
    
 
524
    T( pj_init() );
 
525
 
 
526
    pj_caching_pool_init(&app.cp, NULL, 0);
 
527
    app.pool = pj_pool_create(&app.cp.factory, "pcaputil", 1000, 1000, NULL);
 
528
 
 
529
    T( pjlib_util_init() );
 
530
    T( pjmedia_endpt_create(&app.cp.factory, NULL, 0, &app.mept) );
 
531
 
 
532
    T( pj_pcap_open(app.pool, input.ptr, &app.pcap) );
 
533
    T( pj_pcap_set_filter(app.pcap, &filter) );
 
534
 
 
535
    pcap2wav(&codec, &output, dev_id, &srtp_crypto, &srtp_key);
 
536
 
 
537
    cleanup();
 
538
    return 0;
 
539
}
 
540