~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (1.1.11)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: package-import@ubuntu.com-20140128182336-3xenud1kbnwmf3mz
* 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: aviplay.c 4051 2012-04-13 08:16:30Z ming $ */
 
2
/* 
 
3
 * Copyright (C) 2010-2011 Teluu Inc. (http://www.teluu.com)
 
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
 
 
20
#include <pjmedia.h>
 
21
#include <pjmedia/converter.h>
 
22
#include <pjmedia-codec.h>
 
23
#include <pjlib-util.h>
 
24
#include <pjlib.h>
 
25
#include <stdio.h>
 
26
#include <stdlib.h>
 
27
 
 
28
#include "util.h"
 
29
 
 
30
/**
 
31
 * \page page_pjmedia_samples_aviplay_c Samples: Playing AVI File to
 
32
 * Video and Sound Devices
 
33
 *
 
34
 * This is a very simple example to use the @ref PJMEDIA_FILE_PLAY,
 
35
 * @ref PJMED_SND_PORT, and @ref PJMEDIA_VID_PORT. In this example, we
 
36
 * open the file, video, and sound devices, then connect the file to both
 
37
 * video and sound devices to play the contents of the file.
 
38
 *
 
39
 *
 
40
 * This file is pjsip-apps/src/samples/aviplay.c
 
41
 *
 
42
 * \includelineno aviplay.c
 
43
 */
 
44
 
 
45
 
 
46
/*
 
47
 * aviplay.c
 
48
 *
 
49
 * PURPOSE:
 
50
 *  Play a AVI file to video and sound devices.
 
51
 *
 
52
 * USAGE:
 
53
 *  aviplay FILE.AVI
 
54
 */
 
55
 
 
56
 
 
57
#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
 
58
 
 
59
 
 
60
/* For logging purpose. */
 
61
#define THIS_FILE   "aviplay.c"
 
62
 
 
63
static const char *desc = 
 
64
" FILE                                                              \n"
 
65
"                                                                   \n"
 
66
"  aviplay.c                                                        \n"
 
67
"                                                                   \n"
 
68
" PURPOSE                                                           \n"
 
69
"                                                                   \n"
 
70
"  Demonstrate how to play a AVI file.                              \n"
 
71
"                                                                   \n"
 
72
" USAGE                                                             \n"
 
73
"                                                                   \n"
 
74
"  aviplay FILE.AVI                                                 \n";
 
75
 
 
76
struct codec_fmt {
 
77
    pj_uint32_t         pjmedia_id;
 
78
    const char         *codec_id;
 
79
    /* Do we need to convert the decoded frame? */
 
80
    pj_bool_t           need_conversion;
 
81
    /* If conversion is needed, dst_fmt indicates the destination format */
 
82
    pjmedia_format_id   dst_fmt;
 
83
} codec_fmts[] = {{PJMEDIA_FORMAT_MJPEG, "mjpeg",
 
84
                   PJ_TRUE , PJMEDIA_FORMAT_I420},
 
85
                  {PJMEDIA_FORMAT_H263 , "h263" ,
 
86
                   PJ_FALSE, 0},
 
87
                  {PJMEDIA_FORMAT_MPEG4, "mp4v"}, 
 
88
                  {PJMEDIA_FORMAT_H264 , "h264"}
 
89
                 };
 
90
 
 
91
typedef struct avi_port_t
 
92
{
 
93
    pjmedia_vid_port   *vid_port;
 
94
    pjmedia_snd_port   *snd_port;
 
95
    pj_bool_t           is_running;
 
96
    pj_bool_t           is_quitting;
 
97
} avi_port_t;
 
98
 
 
99
typedef struct codec_port_data_t
 
100
{
 
101
    pjmedia_vid_codec   *codec;
 
102
    pjmedia_port        *src_port;
 
103
    pj_uint8_t          *enc_buf;
 
104
    pj_size_t            enc_buf_size;
 
105
    
 
106
    pjmedia_converter   *conv;
 
107
} codec_port_data_t;
 
108
 
 
109
static pj_status_t avi_event_cb(pjmedia_event *event,
 
110
                                void *user_data)
 
111
{
 
112
    avi_port_t *ap = (avi_port_t *)user_data;
 
113
    
 
114
    switch (event->type) {
 
115
    case PJMEDIA_EVENT_WND_CLOSED:
 
116
        ap->is_quitting = PJ_TRUE;
 
117
        break;
 
118
    case PJMEDIA_EVENT_MOUSE_BTN_DOWN:
 
119
        if (ap->is_running) {
 
120
            pjmedia_vid_port_stop(ap->vid_port);
 
121
            if (ap->snd_port)
 
122
                pjmedia_aud_stream_stop(
 
123
                    pjmedia_snd_port_get_snd_stream(ap->snd_port));
 
124
        } else {
 
125
            pjmedia_vid_port_start(ap->vid_port);
 
126
            if (ap->snd_port)
 
127
                pjmedia_aud_stream_start(
 
128
                    pjmedia_snd_port_get_snd_stream(ap->snd_port));
 
129
        }
 
130
        ap->is_running = !ap->is_running;
 
131
        break;
 
132
    default:
 
133
        return PJ_SUCCESS;
 
134
    }
 
135
    
 
136
    /* We handled the event on our own, so return non-PJ_SUCCESS here */
 
137
    return -1;
 
138
}
 
139
 
 
140
static pj_status_t codec_get_frame(pjmedia_port *port,
 
141
                                   pjmedia_frame *frame)
 
142
{
 
143
    codec_port_data_t *port_data = (codec_port_data_t*)port->port_data.pdata;
 
144
    pjmedia_vid_codec *codec = port_data->codec;
 
145
    pjmedia_frame enc_frame;
 
146
    pj_status_t status;
 
147
    
 
148
    enc_frame.buf = port_data->enc_buf;
 
149
    enc_frame.size = port_data->enc_buf_size;
 
150
    
 
151
    if (port_data->conv) {
 
152
        pj_size_t frame_size = frame->size;
 
153
        
 
154
        status = pjmedia_port_get_frame(port_data->src_port, frame);
 
155
        if (status != PJ_SUCCESS) goto on_error;
 
156
        
 
157
        status = pjmedia_vid_codec_decode(codec, 1, frame,
 
158
                                          frame->size, &enc_frame);
 
159
        if (status != PJ_SUCCESS) goto on_error;
 
160
        
 
161
        frame->size = frame_size;
 
162
        status = pjmedia_converter_convert(port_data->conv, &enc_frame, frame);
 
163
        if (status != PJ_SUCCESS) goto on_error;
 
164
        
 
165
        return PJ_SUCCESS;
 
166
    }
 
167
    
 
168
    status = pjmedia_port_get_frame(port_data->src_port, &enc_frame);
 
169
    if (status != PJ_SUCCESS) goto on_error;
 
170
    
 
171
    status = pjmedia_vid_codec_decode(codec, 1, &enc_frame,
 
172
                                      frame->size, frame);
 
173
    if (status != PJ_SUCCESS) goto on_error;
 
174
    
 
175
    return PJ_SUCCESS;
 
176
    
 
177
on_error:
 
178
    pj_perror(3, THIS_FILE, status, "codec_get_frame() error");
 
179
    return status;
 
180
}
 
181
 
 
182
static int aviplay(pj_pool_t *pool, const char *fname)
 
183
{
 
184
    pjmedia_vid_port *renderer=NULL;
 
185
    pjmedia_vid_port_param param;
 
186
    const pjmedia_video_format_info *vfi;
 
187
    pjmedia_video_format_detail *vfd;
 
188
    pjmedia_snd_port *snd_port = NULL;
 
189
    pj_status_t status;
 
190
    int rc = 0;
 
191
    pjmedia_avi_streams *avi_streams;
 
192
    pjmedia_avi_stream *vid_stream, *aud_stream;
 
193
    pjmedia_port *vid_port = NULL, *aud_port = NULL;
 
194
    pjmedia_vid_codec *codec=NULL;
 
195
    avi_port_t avi_port;
 
196
    
 
197
    pj_bzero(&avi_port, sizeof(avi_port));
 
198
    
 
199
    status = pjmedia_avi_player_create_streams(pool, fname, 0, &avi_streams);
 
200
    if (status != PJ_SUCCESS) {
 
201
        PJ_PERROR(2,("", status, "    Error playing %s", fname));
 
202
        rc = 210; goto on_return;
 
203
    }
 
204
    
 
205
    vid_stream = pjmedia_avi_streams_get_stream_by_media(avi_streams,
 
206
                                                         0,
 
207
                                                         PJMEDIA_TYPE_VIDEO);
 
208
    vid_port = pjmedia_avi_stream_get_port(vid_stream);
 
209
    
 
210
    if (vid_port) {
 
211
        pjmedia_vid_port_param_default(&param);
 
212
        
 
213
        status = pjmedia_vid_dev_default_param(pool,
 
214
                                               PJMEDIA_VID_DEFAULT_RENDER_DEV,
 
215
                                               &param.vidparam);
 
216
        if (status != PJ_SUCCESS) {
 
217
            rc = 220; goto on_return;
 
218
        }
 
219
        
 
220
        /* Create renderer, set it to active  */
 
221
        param.active = PJ_TRUE;
 
222
        param.vidparam.dir = PJMEDIA_DIR_RENDER;
 
223
        vfd = pjmedia_format_get_video_format_detail(&vid_port->info.fmt,
 
224
                                                     PJ_TRUE);
 
225
        pjmedia_format_init_video(&param.vidparam.fmt, 
 
226
                                  vid_port->info.fmt.id,
 
227
                                  vfd->size.w, vfd->size.h,
 
228
                                  vfd->fps.num, vfd->fps.denum);
 
229
        
 
230
        vfi = pjmedia_get_video_format_info(
 
231
                  pjmedia_video_format_mgr_instance(),
 
232
                  vid_port->info.fmt.id);
 
233
        /* Check whether the frame is encoded */
 
234
        if (!vfi || vfi->bpp == 0) {
 
235
            /* Yes, prepare codec */
 
236
            pj_str_t codec_id_st;
 
237
            unsigned info_cnt = 1, i, k;
 
238
            const pjmedia_vid_codec_info *codec_info;
 
239
            pj_str_t port_name = {"codec", 5};
 
240
            pj_uint8_t *enc_buf = NULL;
 
241
            pj_size_t enc_buf_size = 0;
 
242
            pjmedia_vid_dev_info rdr_info;
 
243
            pjmedia_port codec_port;
 
244
            codec_port_data_t codec_port_data;
 
245
            pjmedia_vid_codec_param codec_param;
 
246
            struct codec_fmt *codecp = NULL;
 
247
            
 
248
            /* Lookup codec */
 
249
            for (i = 0; i < sizeof(codec_fmts)/sizeof(codec_fmts[0]); i++) {
 
250
                if (vid_port->info.fmt.id == codec_fmts[i].pjmedia_id) {
 
251
                    codecp = &codec_fmts[i];
 
252
                    break;
 
253
                }
 
254
            }
 
255
            if (!codecp) {
 
256
                rc = 242; goto on_return;
 
257
            }
 
258
            pj_cstr(&codec_id_st, codecp->codec_id);
 
259
            status = pjmedia_vid_codec_mgr_find_codecs_by_id(NULL,
 
260
                                                             &codec_id_st, 
 
261
                                                             &info_cnt, 
 
262
                                                             &codec_info,
 
263
                                                             NULL);
 
264
            if (status != PJ_SUCCESS) {
 
265
                rc = 245; goto on_return;
 
266
            }
 
267
            status = pjmedia_vid_codec_mgr_get_default_param(NULL, codec_info,
 
268
                                                             &codec_param);
 
269
            if (status != PJ_SUCCESS) {
 
270
                rc = 246; goto on_return;
 
271
            }
 
272
            
 
273
            pjmedia_format_copy(&codec_param.enc_fmt, &param.vidparam.fmt);
 
274
 
 
275
            pjmedia_vid_dev_get_info(param.vidparam.rend_id, &rdr_info);
 
276
            for (i=0; i<codec_info->dec_fmt_id_cnt; ++i) {
 
277
                for (k=0; k<rdr_info.fmt_cnt; ++k) {
 
278
                    if (codec_info->dec_fmt_id[i]==(int)rdr_info.fmt[k].id)
 
279
                    {
 
280
                        param.vidparam.fmt.id = codec_info->dec_fmt_id[i];
 
281
                        i = codec_info->dec_fmt_id_cnt;
 
282
                        break;
 
283
                    }
 
284
                }
 
285
            }
 
286
            
 
287
            /* Open codec */
 
288
            status = pjmedia_vid_codec_mgr_alloc_codec(NULL, codec_info,
 
289
                                                       &codec);
 
290
            if (status != PJ_SUCCESS) {
 
291
                rc = 250; goto on_return;
 
292
            }
 
293
            
 
294
            status = pjmedia_vid_codec_init(codec, pool);
 
295
            if (status != PJ_SUCCESS) {
 
296
                rc = 251; goto on_return;
 
297
            }
 
298
            
 
299
            pjmedia_format_copy(&codec_param.dec_fmt, &param.vidparam.fmt);
 
300
            codec_param.dir = PJMEDIA_DIR_DECODING;
 
301
            codec_param.packing = PJMEDIA_VID_PACKING_WHOLE;
 
302
            status = pjmedia_vid_codec_open(codec, &codec_param);
 
303
            if (status != PJ_SUCCESS) {
 
304
                rc = 252; goto on_return;
 
305
            }
 
306
            
 
307
            /* Alloc encoding buffer */
 
308
            enc_buf_size =  codec_param.dec_fmt.det.vid.size.w *
 
309
            codec_param.dec_fmt.det.vid.size.h * 4
 
310
            + 16; /*< padding, just in case */
 
311
            enc_buf = pj_pool_alloc(pool,enc_buf_size);
 
312
            
 
313
            /* Init codec port */
 
314
            pj_bzero(&codec_port, sizeof(codec_port));
 
315
            status = pjmedia_port_info_init2(&codec_port.info, &port_name,
 
316
                                             0x1234,
 
317
                                             PJMEDIA_DIR_ENCODING, 
 
318
                                             &codec_param.dec_fmt);
 
319
            if (status != PJ_SUCCESS) {
 
320
                rc = 260; goto on_return;
 
321
            }
 
322
            pj_bzero(&codec_port_data, sizeof(codec_port_data));
 
323
            codec_port_data.codec = codec;
 
324
            codec_port_data.src_port = vid_port;
 
325
            codec_port_data.enc_buf = enc_buf;
 
326
            codec_port_data.enc_buf_size = enc_buf_size;
 
327
            
 
328
            codec_port.get_frame = &codec_get_frame;
 
329
            codec_port.port_data.pdata = &codec_port_data;
 
330
            
 
331
            /* Check whether we need to convert the decoded frame */
 
332
            if (codecp->need_conversion) {
 
333
                pjmedia_conversion_param conv_param;
 
334
                
 
335
                pjmedia_format_copy(&conv_param.src, &param.vidparam.fmt);
 
336
                pjmedia_format_copy(&conv_param.dst, &param.vidparam.fmt);
 
337
                conv_param.dst.id = codecp->dst_fmt;
 
338
                param.vidparam.fmt.id = conv_param.dst.id;
 
339
                
 
340
                status = pjmedia_converter_create(NULL, pool, &conv_param,
 
341
                                                  &codec_port_data.conv);
 
342
                if (status != PJ_SUCCESS) {
 
343
                    rc = 270; goto on_return;
 
344
                }
 
345
            }
 
346
            
 
347
            status = pjmedia_vid_port_create(pool, &param, &renderer);
 
348
            if (status != PJ_SUCCESS) {
 
349
                rc = 230; goto on_return;
 
350
            }
 
351
            
 
352
            status = pjmedia_vid_port_connect(renderer, &codec_port,
 
353
                                              PJ_FALSE);
 
354
        } else {
 
355
            status = pjmedia_vid_port_create(pool, &param, &renderer);
 
356
            if (status != PJ_SUCCESS) {
 
357
                rc = 230; goto on_return;
 
358
            }
 
359
            
 
360
            /* Connect avi port to renderer */
 
361
            status = pjmedia_vid_port_connect(renderer, vid_port,
 
362
                                              PJ_FALSE);
 
363
        }
 
364
        
 
365
        if (status != PJ_SUCCESS) {
 
366
            rc = 240; goto on_return;
 
367
        }
 
368
    }
 
369
    
 
370
    aud_stream = pjmedia_avi_streams_get_stream_by_media(avi_streams,
 
371
                                                         0,
 
372
                                                         PJMEDIA_TYPE_AUDIO);
 
373
    aud_port = pjmedia_avi_stream_get_port(aud_stream);
 
374
    
 
375
    if (aud_port) {
 
376
        /* Create sound player port. */
 
377
        status = pjmedia_snd_port_create_player( 
 
378
                 pool,                              /* pool                 */
 
379
                 -1,                                /* use default dev.     */
 
380
                 PJMEDIA_PIA_SRATE(&aud_port->info),/* clock rate.          */
 
381
                 PJMEDIA_PIA_CCNT(&aud_port->info), /* # of channels.       */
 
382
                 PJMEDIA_PIA_SPF(&aud_port->info),  /* samples per frame.   */
 
383
                 PJMEDIA_PIA_BITS(&aud_port->info), /* bits per sample.     */
 
384
                 0,                                 /* options              */
 
385
                 &snd_port                          /* returned port        */
 
386
                 );
 
387
        if (status != PJ_SUCCESS) {
 
388
            rc = 310; goto on_return;
 
389
        }
 
390
        
 
391
        /* Connect file port to the sound player.
 
392
         * Stream playing will commence immediately.
 
393
         */
 
394
        status = pjmedia_snd_port_connect(snd_port, aud_port);
 
395
        if (status != PJ_SUCCESS) {
 
396
            rc = 330; goto on_return;
 
397
        }
 
398
    }
 
399
    
 
400
    if (vid_port) {
 
401
        pjmedia_vid_dev_cb cb;
 
402
        
 
403
        pj_bzero(&cb, sizeof(cb));
 
404
        avi_port.snd_port = snd_port;
 
405
        avi_port.vid_port = renderer;
 
406
        avi_port.is_running = PJ_TRUE;
 
407
        pjmedia_vid_port_set_cb(renderer, &cb, &avi_port);
 
408
 
 
409
        /* subscribe events */
 
410
        pjmedia_event_subscribe(NULL, &avi_event_cb, &avi_port,
 
411
                                renderer);
 
412
 
 
413
        if (snd_port) {
 
414
            /* Synchronize video rendering and audio playback */
 
415
            pjmedia_vid_port_set_clock_src(
 
416
                renderer,
 
417
                pjmedia_snd_port_get_clock_src(
 
418
                    snd_port, PJMEDIA_DIR_PLAYBACK));
 
419
        }
 
420
                                              
 
421
        
 
422
        /* Start video streaming.. */
 
423
        status = pjmedia_vid_port_start(renderer);
 
424
        if (status != PJ_SUCCESS) {
 
425
            rc = 270; goto on_return;
 
426
        }
 
427
    }
 
428
    
 
429
    while (!avi_port.is_quitting) {
 
430
        pj_thread_sleep(100);
 
431
    }
 
432
 
 
433
on_return:
 
434
    if (snd_port) {
 
435
        pjmedia_snd_port_disconnect(snd_port);
 
436
        /* Without this sleep, Windows/DirectSound will repeteadly
 
437
         * play the last frame during destroy.
 
438
         */
 
439
        pj_thread_sleep(100);
 
440
        pjmedia_snd_port_destroy(snd_port);
 
441
    }
 
442
    if (renderer) {
 
443
        pjmedia_event_unsubscribe(NULL, &avi_event_cb, &avi_port,
 
444
                                  renderer);
 
445
        pjmedia_vid_port_destroy(renderer);
 
446
    }
 
447
    if (aud_port)
 
448
        pjmedia_port_destroy(aud_port);
 
449
    if (vid_port)
 
450
        pjmedia_port_destroy(vid_port);
 
451
    if (codec) {
 
452
        pjmedia_vid_codec_close(codec);
 
453
        pjmedia_vid_codec_mgr_dealloc_codec(NULL, codec);
 
454
    }
 
455
    
 
456
    return rc;
 
457
}
 
458
 
 
459
 
 
460
static int main_func(int argc, char *argv[])
 
461
{
 
462
    pj_caching_pool cp;
 
463
    pj_pool_t *pool;
 
464
    int rc = 0;
 
465
    pj_status_t status = PJ_SUCCESS;
 
466
    
 
467
    if (argc != 2) {
 
468
        puts("Error: filename required");
 
469
        puts(desc);
 
470
        return 1;
 
471
    }
 
472
 
 
473
 
 
474
    /* Must init PJLIB first: */
 
475
    status = pj_init();
 
476
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
 
477
 
 
478
    /* Must create a pool factory before we can allocate any memory. */
 
479
    pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
 
480
 
 
481
    /* Create memory pool for our file player */
 
482
    pool = pj_pool_create( &cp.factory,     /* pool factory         */
 
483
                           "AVI",           /* pool name.           */
 
484
                           4000,            /* init size            */
 
485
                           4000,            /* increment size       */
 
486
                           NULL             /* callback on error    */
 
487
                           );
 
488
 
 
489
    pjmedia_video_format_mgr_create(pool, 64, 0, NULL);
 
490
    pjmedia_converter_mgr_create(pool, NULL);
 
491
    pjmedia_event_mgr_create(pool, 0, NULL);
 
492
    pjmedia_vid_codec_mgr_create(pool, NULL);
 
493
    
 
494
    status = pjmedia_vid_dev_subsys_init(&cp.factory);
 
495
    if (status != PJ_SUCCESS)
 
496
        goto on_return;
 
497
    
 
498
    status = pjmedia_aud_subsys_init(&cp.factory);
 
499
    if (status != PJ_SUCCESS) {
 
500
        goto on_return;
 
501
    }
 
502
    
 
503
#if PJMEDIA_HAS_FFMPEG_VID_CODEC
 
504
    status = pjmedia_codec_ffmpeg_vid_init(NULL, &cp.factory);
 
505
    if (status != PJ_SUCCESS)
 
506
        goto on_return;    
 
507
#endif
 
508
 
 
509
    rc = aviplay(pool, argv[1]);
 
510
    
 
511
    /* 
 
512
     * File should be playing and looping now 
 
513
     */
 
514
 
 
515
    /* Without this sleep, Windows/DirectSound will repeteadly
 
516
     * play the last frame during destroy.
 
517
     */
 
518
    pj_thread_sleep(100);
 
519
 
 
520
on_return:    
 
521
#if PJMEDIA_HAS_FFMPEG_VID_CODEC
 
522
    pjmedia_codec_ffmpeg_vid_deinit();
 
523
#endif
 
524
    pjmedia_aud_subsys_shutdown();
 
525
    pjmedia_vid_dev_subsys_shutdown();
 
526
    
 
527
    pjmedia_video_format_mgr_destroy(pjmedia_video_format_mgr_instance());
 
528
    pjmedia_converter_mgr_destroy(pjmedia_converter_mgr_instance());
 
529
    pjmedia_event_mgr_destroy(pjmedia_event_mgr_instance());
 
530
    pjmedia_vid_codec_mgr_destroy(pjmedia_vid_codec_mgr_instance());    
 
531
    
 
532
    /* Release application pool */
 
533
    pj_pool_release( pool );
 
534
 
 
535
    /* Destroy pool factory */
 
536
    pj_caching_pool_destroy( &cp );
 
537
 
 
538
    /* Shutdown PJLIB */
 
539
    pj_shutdown();
 
540
 
 
541
    /* Done. */
 
542
    return 0;
 
543
}
 
544
 
 
545
int main(int argc, char *argv[])
 
546
{
 
547
    return pj_run_app(&main_func, argc, argv, 0);
 
548
}
 
549
 
 
550
#else
 
551
 
 
552
int main(int argc, char *argv[])
 
553
{
 
554
    PJ_UNUSED_ARG(argc);
 
555
    PJ_UNUSED_ARG(argv);
 
556
    puts("Error: this sample requires video capability (PJMEDIA_HAS_VIDEO == 1)");
 
557
    return -1;
 
558
}
 
559
 
 
560
#endif /* PJMEDIA_HAS_VIDEO */