BLOG | DOCUMENTATION | TRAC

Home --> Documentations --> PJSIP Reference

Samples: Simple UA

This is a very simple SIP User Agent application that only use PJSIP (without PJSIP-UA). It's able to make and receive call, and play media to the sound device.

1 /* $Id$ */
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 
21 
54 /* Include all headers. */
55 #include <pjsip.h>
56 #include <pjmedia.h>
57 #include <pjmedia-codec.h>
58 #include <pjsip_ua.h>
59 #include <pjsip_simple.h>
60 #include <pjlib-util.h>
61 #include <pjlib.h>
62 
63 /* For logging purpose. */
64 #define THIS_FILE "simpleua.c"
65 
66 #include "util.h"
67 
68 
69 /* Settings */
70 #define AF pj_AF_INET() /* Change to pj_AF_INET6() for IPv6.
71  * PJ_HAS_IPV6 must be enabled and
72  * your system must support IPv6. */
73 #if 0
74 #define SIP_PORT 5080 /* Listening SIP port */
75 #define RTP_PORT 5000 /* RTP port */
76 #else
77 #define SIP_PORT 5060 /* Listening SIP port */
78 #define RTP_PORT 4000 /* RTP port */
79 #endif
80 
81 #define MAX_MEDIA_CNT 2 /* Media count, set to 1 for audio
82  * only or 2 for audio and video */
83 
84 /*
85  * Static variables.
86  */
87 
88 static pj_bool_t g_complete; /* Quit flag. */
89 static pjsip_endpoint *g_endpt; /* SIP endpoint. */
90 static pj_caching_pool cp; /* Global pool factory. */
91 
92 static pjmedia_endpt *g_med_endpt; /* Media endpoint. */
93 
94 static pjmedia_transport_info g_med_tpinfo[MAX_MEDIA_CNT];
95  /* Socket info for media */
96 static pjmedia_transport *g_med_transport[MAX_MEDIA_CNT];
97  /* Media stream transport */
98 static pjmedia_sock_info g_sock_info[MAX_MEDIA_CNT];
99  /* Socket info array */
100 
101 /* Call variables: */
102 static pjsip_inv_session *g_inv; /* Current invite session. */
103 static pjmedia_stream *g_med_stream; /* Call's audio stream. */
104 static pjmedia_snd_port *g_snd_port; /* Sound device. */
105 
106 #if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
107 static pjmedia_vid_stream *g_med_vstream; /* Call's video stream. */
108 static pjmedia_vid_port *g_vid_capturer;/* Call's video capturer. */
109 static pjmedia_vid_port *g_vid_renderer;/* Call's video renderer. */
110 #endif /* PJMEDIA_HAS_VIDEO */
111 
112 /*
113  * Prototypes:
114  */
115 
116 /* Callback to be called when SDP negotiation is done in the call: */
117 static void call_on_media_update( pjsip_inv_session *inv,
118  pj_status_t status);
119 
120 /* Callback to be called when invite session's state has changed: */
121 static void call_on_state_changed( pjsip_inv_session *inv,
122  pjsip_event *e);
123 
124 /* Callback to be called when dialog has forked: */
125 static void call_on_forked(pjsip_inv_session *inv, pjsip_event *e);
126 
127 /* Callback to be called to handle incoming requests outside dialogs: */
128 static pj_bool_t on_rx_request( pjsip_rx_data *rdata );
129 
130 
131 
132 
133 /* This is a PJSIP module to be registered by application to handle
134  * incoming requests outside any dialogs/transactions. The main purpose
135  * here is to handle incoming INVITE request message, where we will
136  * create a dialog and INVITE session for it.
137  */
138 static pjsip_module mod_simpleua =
139 {
140  NULL, NULL, /* prev, next. */
141  { "mod-simpleua", 12 }, /* Name. */
142  -1, /* Id */
143  PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */
144  NULL, /* load() */
145  NULL, /* start() */
146  NULL, /* stop() */
147  NULL, /* unload() */
148  &on_rx_request, /* on_rx_request() */
149  NULL, /* on_rx_response() */
150  NULL, /* on_tx_request. */
151  NULL, /* on_tx_response() */
152  NULL, /* on_tsx_state() */
153 };
154 
155 
156 /* Notification on incoming messages */
157 static pj_bool_t logging_on_rx_msg(pjsip_rx_data *rdata)
158 {
159  PJ_LOG(4,(THIS_FILE, "RX %d bytes %s from %s %s:%d:\n"
160  "%.*s\n"
161  "--end msg--",
162  rdata->msg_info.len,
163  pjsip_rx_data_get_info(rdata),
164  rdata->tp_info.transport->type_name,
165  rdata->pkt_info.src_name,
166  rdata->pkt_info.src_port,
167  (int)rdata->msg_info.len,
168  rdata->msg_info.msg_buf));
169 
170  /* Always return false, otherwise messages will not get processed! */
171  return PJ_FALSE;
172 }
173 
174 /* Notification on outgoing messages */
175 static pj_status_t logging_on_tx_msg(pjsip_tx_data *tdata)
176 {
177 
178  /* Important note:
179  * tp_info field is only valid after outgoing messages has passed
180  * transport layer. So don't try to access tp_info when the module
181  * has lower priority than transport layer.
182  */
183 
184  PJ_LOG(4,(THIS_FILE, "TX %d bytes %s to %s %s:%d:\n"
185  "%.*s\n"
186  "--end msg--",
187  (tdata->buf.cur - tdata->buf.start),
188  pjsip_tx_data_get_info(tdata),
189  tdata->tp_info.transport->type_name,
190  tdata->tp_info.dst_name,
191  tdata->tp_info.dst_port,
192  (int)(tdata->buf.cur - tdata->buf.start),
193  tdata->buf.start));
194 
195  /* Always return success, otherwise message will not get sent! */
196  return PJ_SUCCESS;
197 }
198 
199 /* The module instance. */
200 static pjsip_module msg_logger =
201 {
202  NULL, NULL, /* prev, next. */
203  { "mod-msg-log", 13 }, /* Name. */
204  -1, /* Id */
205  PJSIP_MOD_PRIORITY_TRANSPORT_LAYER-1,/* Priority */
206  NULL, /* load() */
207  NULL, /* start() */
208  NULL, /* stop() */
209  NULL, /* unload() */
210  &logging_on_rx_msg, /* on_rx_request() */
211  &logging_on_rx_msg, /* on_rx_response() */
212  &logging_on_tx_msg, /* on_tx_request. */
213  &logging_on_tx_msg, /* on_tx_response() */
214  NULL, /* on_tsx_state() */
215 
216 };
217 
218 
219 /*
220  * main()
221  *
222  * If called with argument, treat argument as SIP URL to be called.
223  * Otherwise wait for incoming calls.
224  */
225 int main(int argc, char *argv[])
226 {
227  pj_pool_t *pool = NULL;
228  pj_status_t status;
229  unsigned i;
230 
231  /* Must init PJLIB first: */
232  status = pj_init();
233  PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
234 
235  pj_log_set_level(5);
236 
237  /* Then init PJLIB-UTIL: */
238  status = pjlib_util_init();
239  PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
240 
241 
242  /* Must create a pool factory before we can allocate any memory. */
244 
245 
246  /* Create global endpoint: */
247  {
248  const pj_str_t *hostname;
249  const char *endpt_name;
250 
251  /* Endpoint MUST be assigned a globally unique name.
252  * The name will be used as the hostname in Warning header.
253  */
254 
255  /* For this implementation, we'll use hostname for simplicity */
256  hostname = pj_gethostname();
257  endpt_name = hostname->ptr;
258 
259  /* Create the endpoint: */
260 
261  status = pjsip_endpt_create(&cp.factory, endpt_name,
262  &g_endpt);
263  PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
264  }
265 
266 
267  /*
268  * Add UDP transport, with hard-coded port
269  * Alternatively, application can use pjsip_udp_transport_attach() to
270  * start UDP transport, if it already has an UDP socket (e.g. after it
271  * resolves the address with STUN).
272  */
273  {
274  pj_sockaddr addr;
275  int af = AF;
276 
277  pj_sockaddr_init(af, &addr, NULL, (pj_uint16_t)SIP_PORT);
278 
279  if (af == pj_AF_INET()) {
280  status = pjsip_udp_transport_start( g_endpt, &addr.ipv4, NULL,
281  1, NULL);
282  } else if (af == pj_AF_INET6()) {
283  status = pjsip_udp_transport_start6(g_endpt, &addr.ipv6, NULL,
284  1, NULL);
285  } else {
286  status = PJ_EAFNOTSUP;
287  }
288 
289  if (status != PJ_SUCCESS) {
290  app_perror(THIS_FILE, "Unable to start UDP transport", status);
291  return 1;
292  }
293  }
294 
295 
296  /*
297  * Init transaction layer.
298  * This will create/initialize transaction hash tables etc.
299  */
300  status = pjsip_tsx_layer_init_module(g_endpt);
301  PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
302 
303 
304  /*
305  * Initialize UA layer module.
306  * This will create/initialize dialog hash tables etc.
307  */
308  status = pjsip_ua_init_module( g_endpt, NULL );
309  PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
310 
311 
312  /*
313  * Init invite session module.
314  * The invite session module initialization takes additional argument,
315  * i.e. a structure containing callbacks to be called on specific
316  * occurence of events.
317  *
318  * The on_state_changed and on_new_session callbacks are mandatory.
319  * Application must supply the callback function.
320  *
321  * We use on_media_update() callback in this application to start
322  * media transmission.
323  */
324  {
325  pjsip_inv_callback inv_cb;
326 
327  /* Init the callback for INVITE session: */
328  pj_bzero(&inv_cb, sizeof(inv_cb));
329  inv_cb.on_state_changed = &call_on_state_changed;
330  inv_cb.on_new_session = &call_on_forked;
331  inv_cb.on_media_update = &call_on_media_update;
332 
333  /* Initialize invite session module: */
334  status = pjsip_inv_usage_init(g_endpt, &inv_cb);
335  PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
336  }
337 
338  /* Initialize 100rel support */
339  status = pjsip_100rel_init_module(g_endpt);
340  PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
341 
342  /*
343  * Register our module to receive incoming requests.
344  */
345  status = pjsip_endpt_register_module( g_endpt, &mod_simpleua);
346  PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
347 
348  /*
349  * Register message logger module.
350  */
351  status = pjsip_endpt_register_module( g_endpt, &msg_logger);
352  PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
353 
354 
355  /*
356  * Initialize media endpoint.
357  * This will implicitly initialize PJMEDIA too.
358  */
359 #if PJ_HAS_THREADS
360  status = pjmedia_endpt_create(&cp.factory, NULL, 1, &g_med_endpt);
361 #else
362  status = pjmedia_endpt_create(&cp.factory,
363  pjsip_endpt_get_ioqueue(g_endpt),
364  0, &g_med_endpt);
365 #endif
366  PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
367 
368  /* Create pool. */
369  pool = pjmedia_endpt_create_pool(g_med_endpt, "Media pool", 512, 512);
370 
371  /*
372  * Add PCMA/PCMU codec to the media endpoint.
373  */
374 #if defined(PJMEDIA_HAS_G711_CODEC) && PJMEDIA_HAS_G711_CODEC!=0
375  status = pjmedia_codec_g711_init(g_med_endpt);
376  PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
377 #endif
378 
379 
380 #if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
381  /* Init video subsystem */
382  status = pjmedia_video_format_mgr_create(pool, 64, 0, NULL);
383  PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
384  status = pjmedia_converter_mgr_create(pool, NULL);
385  PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
386  status = pjmedia_vid_codec_mgr_create(pool, NULL);
387  PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
388  status = pjmedia_vid_dev_subsys_init(&cp.factory);
389  PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
390 
391 #if PJMEDIA_HAS_VIDEO && PJMEDIA_HAS_VID_TOOLBOX_CODEC
392  status = pjmedia_codec_vid_toolbox_init(NULL, &cp.factory);
393  PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
394 #endif
395 
396 # if defined(PJMEDIA_HAS_OPENH264_CODEC) && PJMEDIA_HAS_OPENH264_CODEC != 0
397  status = pjmedia_codec_openh264_vid_init(NULL, &cp.factory);
398  PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
399 # endif
400 
401 # if defined(PJMEDIA_HAS_VPX_CODEC) && PJMEDIA_HAS_VPX_CODEC != 0
402  status = pjmedia_codec_vpx_vid_init(NULL, &cp.factory);
403  PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
404 # endif
405 
406 # if defined(PJMEDIA_HAS_FFMPEG_VID_CODEC) && PJMEDIA_HAS_FFMPEG_VID_CODEC!=0
407  /* Init ffmpeg video codecs */
408  status = pjmedia_codec_ffmpeg_vid_init(NULL, &cp.factory);
409  PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
410 # endif /* PJMEDIA_HAS_FFMPEG_VID_CODEC */
411 
412 #endif /* PJMEDIA_HAS_VIDEO */
413 
414  /* Create event manager */
415  status = pjmedia_event_mgr_create(pool, 0, NULL);
416  PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
417 
418  /*
419  * Create media transport used to send/receive RTP/RTCP socket.
420  * One media transport is needed for each call. Application may
421  * opt to re-use the same media transport for subsequent calls.
422  */
423  for (i = 0; i < PJ_ARRAY_SIZE(g_med_transport); ++i) {
424  status = pjmedia_transport_udp_create3(g_med_endpt, AF, NULL, NULL,
425  RTP_PORT + i*2, 0,
426  &g_med_transport[i]);
427  if (status != PJ_SUCCESS) {
428  app_perror(THIS_FILE, "Unable to create media transport", status);
429  return 1;
430  }
431 
432  /*
433  * Get socket info (address, port) of the media transport. We will
434  * need this info to create SDP (i.e. the address and port info in
435  * the SDP).
436  */
437  pjmedia_transport_info_init(&g_med_tpinfo[i]);
438  pjmedia_transport_get_info(g_med_transport[i], &g_med_tpinfo[i]);
439 
440  pj_memcpy(&g_sock_info[i], &g_med_tpinfo[i].sock_info,
441  sizeof(pjmedia_sock_info));
442  }
443 
444  /*
445  * If URL is specified, then make call immediately.
446  */
447  if (argc > 1) {
448  pj_sockaddr hostaddr;
449  char hostip[PJ_INET6_ADDRSTRLEN+2];
450  char temp[80];
451  pj_str_t dst_uri = pj_str(argv[1]);
452  pj_str_t local_uri;
453  pjsip_dialog *dlg;
454  pjmedia_sdp_session *local_sdp;
455  pjsip_tx_data *tdata;
456 
457  if (pj_gethostip(AF, &hostaddr) != PJ_SUCCESS) {
458  app_perror(THIS_FILE, "Unable to retrieve local host IP", status);
459  return 1;
460  }
461  pj_sockaddr_print(&hostaddr, hostip, sizeof(hostip), 2);
462 
463  pj_ansi_sprintf(temp, "<sip:simpleuac@%s:%d>",
464  hostip, SIP_PORT);
465  local_uri = pj_str(temp);
466 
467  /* Create UAC dialog */
469  &local_uri, /* local URI */
470  &local_uri, /* local Contact */
471  &dst_uri, /* remote URI */
472  &dst_uri, /* remote target */
473  &dlg); /* dialog */
474  if (status != PJ_SUCCESS) {
475  app_perror(THIS_FILE, "Unable to create UAC dialog", status);
476  return 1;
477  }
478 
479  /* If we expect the outgoing INVITE to be challenged, then we should
480  * put the credentials in the dialog here, with something like this:
481  *
482  {
483  pjsip_cred_info cred[1];
484 
485  cred[0].realm = pj_str("sip.server.realm");
486  cred[0].scheme = pj_str("digest");
487  cred[0].username = pj_str("theuser");
488  cred[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
489  cred[0].data = pj_str("thepassword");
490 
491  pjsip_auth_clt_set_credentials( &dlg->auth_sess, 1, cred);
492  }
493  *
494  */
495 
496 
497  /* Get the SDP body to be put in the outgoing INVITE, by asking
498  * media endpoint to create one for us.
499  */
500  status = pjmedia_endpt_create_sdp( g_med_endpt, /* the media endpt */
501  dlg->pool, /* pool. */
502  MAX_MEDIA_CNT, /* # of streams */
503  g_sock_info, /* RTP sock info */
504  &local_sdp); /* the SDP result */
505  PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
506 
507 
508 
509  /* Create the INVITE session, and pass the SDP returned earlier
510  * as the session's initial capability.
511  */
512  status = pjsip_inv_create_uac( dlg, local_sdp, 0, &g_inv);
513  PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
514 
515  /* If we want the initial INVITE to travel to specific SIP proxies,
516  * then we should put the initial dialog's route set here. The final
517  * route set will be updated once a dialog has been established.
518  * To set the dialog's initial route set, we do it with something
519  * like this:
520  *
521  {
522  pjsip_route_hdr route_set;
523  pjsip_route_hdr *route;
524  const pj_str_t hname = { "Route", 5 };
525  char *uri = "sip:proxy.server;lr";
526 
527  pj_list_init(&route_set);
528 
529  route = pjsip_parse_hdr( dlg->pool, &hname,
530  uri, strlen(uri),
531  NULL);
532  PJ_ASSERT_RETURN(route != NULL, 1);
533  pj_list_push_back(&route_set, route);
534 
535  pjsip_dlg_set_route_set(dlg, &route_set);
536  }
537  *
538  * Note that Route URI SHOULD have an ";lr" parameter!
539  */
540 
541  /* Create initial INVITE request.
542  * This INVITE request will contain a perfectly good request and
543  * an SDP body as well.
544  */
545  status = pjsip_inv_invite(g_inv, &tdata);
546  PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
547 
548 
549 
550  /* Send initial INVITE request.
551  * From now on, the invite session's state will be reported to us
552  * via the invite session callbacks.
553  */
554  status = pjsip_inv_send_msg(g_inv, tdata);
555  PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
556 
557 
558  } else {
559 
560  /* No URL to make call to */
561 
562  PJ_LOG(3,(THIS_FILE, "Ready to accept incoming calls..."));
563  }
564 
565 
566  /* Loop until one call is completed */
567  for (;!g_complete;) {
568  pj_time_val timeout = {0, 10};
569  pjsip_endpt_handle_events(g_endpt, &timeout);
570  }
571 
572  /* On exit, dump current memory usage: */
573  dump_pool_usage(THIS_FILE, &cp);
574 
575  /* Destroy audio ports. Destroy the audio port first
576  * before the stream since the audio port has threads
577  * that get/put frames to the stream.
578  */
579  if (g_snd_port)
580  pjmedia_snd_port_destroy(g_snd_port);
581 
582 #if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
583  /* Destroy video ports */
584  if (g_vid_capturer)
585  pjmedia_vid_port_destroy(g_vid_capturer);
586  if (g_vid_renderer)
587  pjmedia_vid_port_destroy(g_vid_renderer);
588 #endif
589 
590  /* Destroy streams */
591  if (g_med_stream)
592  pjmedia_stream_destroy(g_med_stream);
593 #if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
594  if (g_med_vstream)
595  pjmedia_vid_stream_destroy(g_med_vstream);
596 
597  /* Deinit ffmpeg codec */
598 # if defined(PJMEDIA_HAS_FFMPEG_VID_CODEC) && PJMEDIA_HAS_FFMPEG_VID_CODEC!=0
600 # endif
601 # if defined(PJMEDIA_HAS_OPENH264_CODEC) && PJMEDIA_HAS_OPENH264_CODEC != 0
603 # endif
604 # if PJMEDIA_HAS_VIDEO && PJMEDIA_HAS_VID_TOOLBOX_CODEC
606 # endif
607 # if defined(PJMEDIA_HAS_VPX_CODEC) && PJMEDIA_HAS_VPX_CODEC != 0
609 # endif
610 
611 #endif
612 
613  /* Destroy media transports */
614  for (i = 0; i < MAX_MEDIA_CNT; ++i) {
615  if (g_med_transport[i])
616  pjmedia_transport_close(g_med_transport[i]);
617  }
618 
619  /* Destroy event manager */
621 
622  /* Deinit pjmedia endpoint */
623  if (g_med_endpt)
624  pjmedia_endpt_destroy(g_med_endpt);
625 
626  /* Deinit pjsip endpoint */
627  if (g_endpt)
628  pjsip_endpt_destroy(g_endpt);
629 
630  /* Release pool */
631  if (pool)
632  pj_pool_release(pool);
633 
634  return 0;
635 }
636 
637 
638 
639 /*
640  * Callback when INVITE session state has changed.
641  * This callback is registered when the invite session module is initialized.
642  * We mostly want to know when the invite session has been disconnected,
643  * so that we can quit the application.
644  */
645 static void call_on_state_changed( pjsip_inv_session *inv,
646  pjsip_event *e)
647 {
648  PJ_UNUSED_ARG(e);
649 
650  if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
651 
652  PJ_LOG(3,(THIS_FILE, "Call DISCONNECTED [reason=%d (%s)]",
653  inv->cause,
655 
656  PJ_LOG(3,(THIS_FILE, "One call completed, application quitting..."));
657  g_complete = 1;
658 
659  } else {
660 
661  PJ_LOG(3,(THIS_FILE, "Call state changed to %s",
662  pjsip_inv_state_name(inv->state)));
663 
664  }
665 }
666 
667 
668 /* This callback is called when dialog has forked. */
669 static void call_on_forked(pjsip_inv_session *inv, pjsip_event *e)
670 {
671  /* To be done... */
672  PJ_UNUSED_ARG(inv);
673  PJ_UNUSED_ARG(e);
674 }
675 
676 
677 /*
678  * Callback when incoming requests outside any transactions and any
679  * dialogs are received. We're only interested to hande incoming INVITE
680  * request, and we'll reject any other requests with 500 response.
681  */
682 static pj_bool_t on_rx_request( pjsip_rx_data *rdata )
683 {
684  pj_sockaddr hostaddr;
685  char temp[80], hostip[PJ_INET6_ADDRSTRLEN];
686  pj_str_t local_uri;
687  pjsip_dialog *dlg;
688  pjmedia_sdp_session *local_sdp;
689  pjsip_tx_data *tdata;
690  unsigned options = 0;
691  pj_status_t status;
692 
693 
694  /*
695  * Respond (statelessly) any non-INVITE requests with 500
696  */
697  if (rdata->msg_info.msg->line.req.method.id != PJSIP_INVITE_METHOD) {
698 
699  if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) {
700  pj_str_t reason = pj_str("Simple UA unable to handle "
701  "this request");
702 
703  pjsip_endpt_respond_stateless( g_endpt, rdata,
704  500, &reason,
705  NULL, NULL);
706  }
707  return PJ_TRUE;
708  }
709 
710 
711  /*
712  * Reject INVITE if we already have an INVITE session in progress.
713  */
714  if (g_inv) {
715 
716  pj_str_t reason = pj_str("Another call is in progress");
717 
718  pjsip_endpt_respond_stateless( g_endpt, rdata,
719  500, &reason,
720  NULL, NULL);
721  return PJ_TRUE;
722 
723  }
724 
725  /* Verify that we can handle the request. */
726  status = pjsip_inv_verify_request(rdata, &options, NULL, NULL,
727  g_endpt, NULL);
728  if (status != PJ_SUCCESS) {
729 
730  pj_str_t reason = pj_str("Sorry Simple UA can not handle this INVITE");
731 
732  pjsip_endpt_respond_stateless( g_endpt, rdata,
733  500, &reason,
734  NULL, NULL);
735  return PJ_TRUE;
736  }
737 
738  /*
739  * Generate Contact URI
740  */
741  if (pj_gethostip(AF, &hostaddr) != PJ_SUCCESS) {
742  app_perror(THIS_FILE, "Unable to retrieve local host IP", status);
743  return PJ_TRUE;
744  }
745  pj_sockaddr_print(&hostaddr, hostip, sizeof(hostip), 2);
746 
747  pj_ansi_sprintf(temp, "<sip:simpleuas@%s:%d>",
748  hostip, SIP_PORT);
749  local_uri = pj_str(temp);
750 
751  /*
752  * Create UAS dialog.
753  */
755  rdata,
756  &local_uri, /* contact */
757  &dlg);
758  if (status != PJ_SUCCESS) {
759  pjsip_endpt_respond_stateless(g_endpt, rdata, 500, NULL,
760  NULL, NULL);
761  return PJ_TRUE;
762  }
763 
764  /*
765  * Get media capability from media endpoint:
766  */
767 
768  status = pjmedia_endpt_create_sdp( g_med_endpt, rdata->tp_info.pool,
769  MAX_MEDIA_CNT, g_sock_info, &local_sdp);
770  pj_assert(status == PJ_SUCCESS);
771  if (status != PJ_SUCCESS) {
772  pjsip_dlg_dec_lock(dlg);
773  return PJ_TRUE;
774  }
775 
776 
777  /*
778  * Create invite session, and pass both the UAS dialog and the SDP
779  * capability to the session.
780  */
781  status = pjsip_inv_create_uas( dlg, rdata, local_sdp, 0, &g_inv);
782  pj_assert(status == PJ_SUCCESS);
783  if (status != PJ_SUCCESS) {
784  pjsip_dlg_dec_lock(dlg);
785  return PJ_TRUE;
786  }
787 
788  /*
789  * Invite session has been created, decrement & release dialog lock.
790  */
791  pjsip_dlg_dec_lock(dlg);
792 
793 
794  /*
795  * Initially send 180 response.
796  *
797  * The very first response to an INVITE must be created with
798  * pjsip_inv_initial_answer(). Subsequent responses to the same
799  * transaction MUST use pjsip_inv_answer().
800  */
801  status = pjsip_inv_initial_answer(g_inv, rdata,
802  180,
803  NULL, NULL, &tdata);
804  PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE);
805 
806 
807  /* Send the 180 response. */
808  status = pjsip_inv_send_msg(g_inv, tdata);
809  PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE);
810 
811 
812  /*
813  * Now create 200 response.
814  */
815  status = pjsip_inv_answer( g_inv,
816  200, NULL, /* st_code and st_text */
817  NULL, /* SDP already specified */
818  &tdata);
819  PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE);
820 
821  /*
822  * Send the 200 response.
823  */
824  status = pjsip_inv_send_msg(g_inv, tdata);
825  PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE);
826 
827 
828  /* Done.
829  * When the call is disconnected, it will be reported via the callback.
830  */
831 
832  return PJ_TRUE;
833 }
834 
835 
836 
837 /*
838  * Callback when SDP negotiation has completed.
839  * We are interested with this callback because we want to start media
840  * as soon as SDP negotiation is completed.
841  */
842 static void call_on_media_update( pjsip_inv_session *inv,
843  pj_status_t status)
844 {
845  pjmedia_stream_info stream_info;
846  const pjmedia_sdp_session *local_sdp;
847  const pjmedia_sdp_session *remote_sdp;
848  pjmedia_port *media_port;
849 
850  if (status != PJ_SUCCESS) {
851 
852  app_perror(THIS_FILE, "SDP negotiation has failed", status);
853 
854  /* Here we should disconnect call if we're not in the middle
855  * of initializing an UAS dialog and if this is not a re-INVITE.
856  */
857  return;
858  }
859 
860  /* Get local and remote SDP.
861  * We need both SDPs to create a media session.
862  */
863  status = pjmedia_sdp_neg_get_active_local(inv->neg, &local_sdp);
864 
865  status = pjmedia_sdp_neg_get_active_remote(inv->neg, &remote_sdp);
866 
867 
868  /* Create stream info based on the media audio SDP. */
869  status = pjmedia_stream_info_from_sdp(&stream_info, inv->dlg->pool,
870  g_med_endpt,
871  local_sdp, remote_sdp, 0);
872  if (status != PJ_SUCCESS) {
873  app_perror(THIS_FILE,"Unable to create audio stream info",status);
874  return;
875  }
876 
877  /* If required, we can also change some settings in the stream info,
878  * (such as jitter buffer settings, codec settings, etc) before we
879  * create the stream.
880  */
881 
882  /* Create new audio media stream, passing the stream info, and also the
883  * media socket that we created earlier.
884  */
885  status = pjmedia_stream_create(g_med_endpt, inv->dlg->pool, &stream_info,
886  g_med_transport[0], NULL, &g_med_stream);
887  if (status != PJ_SUCCESS) {
888  app_perror( THIS_FILE, "Unable to create audio stream", status);
889  return;
890  }
891 
892  /* Start the audio stream */
893  status = pjmedia_stream_start(g_med_stream);
894  if (status != PJ_SUCCESS) {
895  app_perror( THIS_FILE, "Unable to start audio stream", status);
896  return;
897  }
898 
899  /* Start the UDP media transport */
900  pjmedia_transport_media_start(g_med_transport[0], 0, 0, 0, 0);
901 
902  /* Get the media port interface of the audio stream.
903  * Media port interface is basicly a struct containing get_frame() and
904  * put_frame() function. With this media port interface, we can attach
905  * the port interface to conference bridge, or directly to a sound
906  * player/recorder device.
907  */
908  pjmedia_stream_get_port(g_med_stream, &media_port);
909 
910  /* Create sound port */
914  PJMEDIA_PIA_SRATE(&media_port->info),/* clock rate */
915  PJMEDIA_PIA_CCNT(&media_port->info),/* channel count */
916  PJMEDIA_PIA_SPF(&media_port->info), /* samples per frame*/
917  PJMEDIA_PIA_BITS(&media_port->info),/* bits per sample */
918  0,
919  &g_snd_port);
920 
921  if (status != PJ_SUCCESS) {
922  app_perror( THIS_FILE, "Unable to create sound port", status);
923  PJ_LOG(3,(THIS_FILE, "%d %d %d %d",
924  PJMEDIA_PIA_SRATE(&media_port->info),/* clock rate */
925  PJMEDIA_PIA_CCNT(&media_port->info),/* channel count */
926  PJMEDIA_PIA_SPF(&media_port->info), /* samples per frame*/
927  PJMEDIA_PIA_BITS(&media_port->info) /* bits per sample */
928  ));
929  return;
930  }
931 
932  status = pjmedia_snd_port_connect(g_snd_port, media_port);
933 
934 
935  /* Get the media port interface of the second stream in the session,
936  * which is video stream. With this media port interface, we can attach
937  * the port directly to a renderer/capture video device.
938  */
939 #if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
940  if (local_sdp->media_count > 1) {
941  pjmedia_vid_stream_info vstream_info;
942  pjmedia_vid_port_param vport_param;
943 
944  pjmedia_vid_port_param_default(&vport_param);
945 
946  /* Create stream info based on the media video SDP. */
947  status = pjmedia_vid_stream_info_from_sdp(&vstream_info,
948  inv->dlg->pool, g_med_endpt,
949  local_sdp, remote_sdp, 1);
950  if (status != PJ_SUCCESS) {
951  app_perror(THIS_FILE,"Unable to create video stream info",status);
952  return;
953  }
954 
955  /* If required, we can also change some settings in the stream info,
956  * (such as jitter buffer settings, codec settings, etc) before we
957  * create the video stream.
958  */
959 
960  /* Create new video media stream, passing the stream info, and also the
961  * media socket that we created earlier.
962  */
963  status = pjmedia_vid_stream_create(g_med_endpt, NULL, &vstream_info,
964  g_med_transport[1], NULL,
965  &g_med_vstream);
966  if (status != PJ_SUCCESS) {
967  app_perror( THIS_FILE, "Unable to create video stream", status);
968  return;
969  }
970 
971  /* Start the video stream */
972  status = pjmedia_vid_stream_start(g_med_vstream);
973  if (status != PJ_SUCCESS) {
974  app_perror( THIS_FILE, "Unable to start video stream", status);
975  return;
976  }
977 
978  /* Start the UDP media transport */
979  pjmedia_transport_media_start(g_med_transport[1], 0, 0, 0, 0);
980 
981  if (vstream_info.dir & PJMEDIA_DIR_DECODING) {
984  &vport_param.vidparam);
985  if (status != PJ_SUCCESS) {
986  app_perror(THIS_FILE, "Unable to get default param of video "
987  "renderer device", status);
988  return;
989  }
990 
991  /* Get video stream port for decoding direction */
993  &media_port);
994 
995  /* Set format */
996  pjmedia_format_copy(&vport_param.vidparam.fmt,
997  &media_port->info.fmt);
998  vport_param.vidparam.dir = PJMEDIA_DIR_RENDER;
999  vport_param.active = PJ_TRUE;
1000 
1001  /* Create renderer */
1002  status = pjmedia_vid_port_create(inv->pool, &vport_param,
1003  &g_vid_renderer);
1004  if (status != PJ_SUCCESS) {
1005  app_perror(THIS_FILE, "Unable to create video renderer device",
1006  status);
1007  return;
1008  }
1009 
1010  /* Connect renderer to media_port */
1011  status = pjmedia_vid_port_connect(g_vid_renderer, media_port,
1012  PJ_FALSE);
1013  if (status != PJ_SUCCESS) {
1014  app_perror(THIS_FILE, "Unable to connect renderer to stream",
1015  status);
1016  return;
1017  }
1018  }
1019 
1020  /* Create capturer */
1021  if (vstream_info.dir & PJMEDIA_DIR_ENCODING) {
1024  &vport_param.vidparam);
1025  if (status != PJ_SUCCESS) {
1026  app_perror(THIS_FILE, "Unable to get default param of video "
1027  "capture device", status);
1028  return;
1029  }
1030 
1031  /* Get video stream port for decoding direction */
1033  &media_port);
1034 
1035  /* Get capturer format from stream info */
1036  pjmedia_format_copy(&vport_param.vidparam.fmt,
1037  &media_port->info.fmt);
1038  vport_param.vidparam.dir = PJMEDIA_DIR_CAPTURE;
1039  vport_param.active = PJ_TRUE;
1040 
1041  /* Create capturer */
1042  status = pjmedia_vid_port_create(inv->pool, &vport_param,
1043  &g_vid_capturer);
1044  if (status != PJ_SUCCESS) {
1045  app_perror(THIS_FILE, "Unable to create video capture device",
1046  status);
1047  return;
1048  }
1049 
1050  /* Connect capturer to media_port */
1051  status = pjmedia_vid_port_connect(g_vid_capturer, media_port,
1052  PJ_FALSE);
1053  if (status != PJ_SUCCESS) {
1054  app_perror(THIS_FILE, "Unable to connect capturer to stream",
1055  status);
1056  return;
1057  }
1058  }
1059 
1060  /* Start streaming */
1061  if (g_vid_renderer) {
1062  status = pjmedia_vid_port_start(g_vid_renderer);
1063  if (status != PJ_SUCCESS) {
1064  app_perror(THIS_FILE, "Unable to start video renderer",
1065  status);
1066  return;
1067  }
1068  }
1069  if (g_vid_capturer) {
1070  status = pjmedia_vid_port_start(g_vid_capturer);
1071  if (status != PJ_SUCCESS) {
1072  app_perror(THIS_FILE, "Unable to start video capturer",
1073  status);
1074  return;
1075  }
1076  }
1077  }
1078 #endif /* PJMEDIA_HAS_VIDEO */
1079 
1080  /* Done with media. */
1081 }
1082 
1083 
pj_status_t pjmedia_transport_close(pjmedia_transport *tp)
pj_status_t pjmedia_sdp_neg_get_active_local(pjmedia_sdp_neg *neg, const pjmedia_sdp_session **local)
pj_status_t pjmedia_sdp_neg_get_active_remote(pjmedia_sdp_neg *neg, const pjmedia_sdp_session **remote)
Definition: sip_module.h:191
pjsip_buffer buf
Definition: sip_transport.h:569
struct pjsip_request_line req
Definition: sip_msg.h:869
void(* on_media_update)(pjsip_inv_session *inv_ses, pj_status_t status)
Definition: sip_inv.h:244
pj_status_t pjsip_inv_usage_init(pjsip_endpoint *endpt, const pjsip_inv_callback *cb)
const pj_str_t * pjsip_get_status_text(int status_code)
#define PJ_ASSERT_RETURN(expr, retval)
pj_status_t pjsip_udp_transport_start6(pjsip_endpoint *endpt, const pj_sockaddr_in6 *local, const pjsip_host_port *a_name, unsigned async_cnt, pjsip_transport **p_transport)
Definition: sip_transport.h:522
PJMEDIA_VID_DEFAULT_CAPTURE_DEV
char * ptr
pjmedia_port_info info
void pj_pool_release(pj_pool_t *pool)
const char * pjsip_inv_state_name(pjsip_inv_state state)
pjmedia_format fmt
int pj_bool_t
pjmedia_format * pjmedia_format_copy(pjmedia_format *dst, const pjmedia_format *src)
pjsip_dialog * dlg
Definition: sip_inv.h:445
SIP SIMPLE Extension.
pjmedia_sdp_neg * neg
Definition: sip_inv.h:448
pj_status_t pjsip_inv_send_msg(pjsip_inv_session *inv, pjsip_tx_data *tdata)
void * pj_memcpy(void *dst, const void *src, pj_size_t size)
void pjsip_dlg_dec_lock(pjsip_dialog *dlg)
pjsip_method_e id
Definition: sip_msg.h:79
void pjmedia_vid_port_param_default(pjmedia_vid_port_param *prm)
pj_status_t pjmedia_vid_stream_info_from_sdp(pjmedia_vid_stream_info *si, pj_pool_t *pool, pjmedia_endpt *endpt, const pjmedia_sdp_session *local, const pjmedia_sdp_session *remote, unsigned stream_idx)
#define PJMEDIA_AUD_DEFAULT_CAPTURE_DEV
pj_ssize_t len
Definition: sip_transport.h:335
struct pjmedia_endpt pjmedia_endpt
PJMEDIA_DIR_RENDER
pj_status_t pjmedia_vid_stream_create(pjmedia_endpt *endpt, pj_pool_t *pool, pjmedia_vid_stream_info *info, pjmedia_transport *tp, void *user_data, pjmedia_vid_stream **p_stream)
#define pj_AF_INET()
pj_status_t pjmedia_codec_vid_toolbox_init(pjmedia_vid_codec_mgr *mgr, pj_pool_factory *pf)
pj_status_t pjmedia_stream_start(pjmedia_stream *stream)
pj_status_t pjmedia_snd_port_destroy(pjmedia_snd_port *snd_port)
struct pjmedia_vid_port pjmedia_vid_port
pj_pool_t * pool
Definition: sip_dialog.h:143
pj_status_t pjmedia_video_format_mgr_create(pj_pool_t *pool, unsigned max_fmt, unsigned options, pjmedia_video_format_mgr **p_mgr)
pj_status_t pjsip_endpt_respond_stateless(pjsip_endpoint *endpt, pjsip_rx_data *rdata, int st_code, const pj_str_t *st_text, const pjsip_hdr *hdr_list, const pjsip_msg_body *body)
char src_name[PJ_INET6_ADDRSTRLEN]
Definition: sip_transport.h:344
pj_status_t pjsip_udp_transport_start(pjsip_endpoint *endpt, const pj_sockaddr_in *local, const pjsip_host_port *a_name, unsigned async_cnt, pjsip_transport **p_transport)
pj_status_t pjsip_inv_create_uas(pjsip_dialog *dlg, pjsip_rx_data *rdata, const pjmedia_sdp_session *local_sdp, unsigned options, pjsip_inv_session **p_inv)
pj_status_t pjmedia_vid_stream_start(pjmedia_vid_stream *stream)
#define PJ_LOG(level, arg)
pj_status_t pjmedia_transport_get_info(pjmedia_transport *tp, pjmedia_transport_info *info)
char * start
Definition: sip_types.h:208
struct pjmedia_snd_port pjmedia_snd_port
int pj_status_t
char * type_name
Definition: sip_transport.h:822
pj_status_t pjsip_inv_initial_answer(pjsip_inv_session *inv, pjsip_rx_data *rdata, int st_code, const pj_str_t *st_text, const pjmedia_sdp_session *sdp, pjsip_tx_data **p_tdata)
pjmedia_vid_dev_param vidparam
char * msg_buf
Definition: sip_transport.h:359
pj_pool_factory_policy pj_pool_factory_default_policy
Definition: sip_msg.h:57
pj_status_t pjmedia_converter_mgr_create(pj_pool_t *pool, pjmedia_converter_mgr **mgr)
pj_status_t pjmedia_event_mgr_create(pj_pool_t *pool, unsigned options, pjmedia_event_mgr **mgr)
PJMEDIA_DIR_ENCODING
void pjsip_endpt_destroy(pjsip_endpoint *endpt)
#define PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV
PJMEDIA_DIR_DECODING
pj_pool_t * pool
Definition: sip_transport.h:305
pj_status_t pjmedia_vid_codec_mgr_create(pj_pool_t *pool, pjmedia_vid_codec_mgr **mgr)
pj_status_t pjsip_endpt_create(pj_pool_factory *pf, const char *name, pjsip_endpoint **endpt)
pj_status_t pjsip_inv_create_uac(pjsip_dialog *dlg, const pjmedia_sdp_session *local_sdp, unsigned options, pjsip_inv_session **p_inv)
pj_status_t pjmedia_stream_create(pjmedia_endpt *endpt, pj_pool_t *pool, const pjmedia_stream_info *info, pjmedia_transport *tp, void *user_data, pjmedia_stream **p_stream)
Definition: sip_event.h:81
Definition: sip_msg.h:59
pj_status_t pjsip_endpt_handle_events(pjsip_endpoint *endpt, const pj_time_val *max_timeout)
pj_status_t pjmedia_vid_stream_destroy(pjmedia_vid_stream *stream)
pj_ioqueue_t * pjsip_endpt_get_ioqueue(pjsip_endpoint *endpt)
pj_pool_factory factory
pj_status_t pjmedia_stream_info_from_sdp(pjmedia_stream_info *si, pj_pool_t *pool, pjmedia_endpt *endpt, const pjmedia_sdp_session *local, const pjmedia_sdp_session *remote, unsigned stream_idx)
pj_status_t pjmedia_vid_port_connect(pjmedia_vid_port *vid_port, pjmedia_port *port, pj_bool_t destroy)
void pjmedia_event_mgr_destroy(pjmedia_event_mgr *mgr)
pj_status_t pjsip_dlg_create_uac(pjsip_user_agent *ua, const pj_str_t *local_uri, const pj_str_t *local_contact, const pj_str_t *remote_uri, const pj_str_t *target, pjsip_dialog **p_dlg)
Definition: sip_transport.h:295
char * cur
Definition: sip_types.h:213
pj_status_t pjsip_endpt_register_module(pjsip_endpoint *endpt, pjsip_module *module)
Definition: sip_inv.h:431
pjsip_user_agent * pjsip_ua_instance(void)
Definition: sip_inv.h:96
pj_status_t pjmedia_snd_port_create(pj_pool_t *pool, int rec_id, int play_id, unsigned clock_rate, unsigned channel_count, unsigned samples_per_frame, unsigned bits_per_sample, unsigned options, pjmedia_snd_port **p_port)
pj_pool_t * pool
Definition: sip_inv.h:434
PJ_TRUE
const pj_str_t * pj_gethostname(void)
struct pjsip_rx_data::@24 msg_info
int dst_port
Definition: sip_transport.h:616
pj_status_t pjmedia_codec_vpx_vid_init(pjmedia_vid_codec_mgr *mgr, pj_pool_factory *pf)
struct pjsip_rx_data::@23 pkt_info
pj_status_t pjmedia_codec_vid_toolbox_deinit(void)
unsigned PJMEDIA_PIA_CCNT(const pjmedia_port_info *pia)
struct pjsip_rx_data::@22 tp_info
pj_status_t pjmedia_endpt_create(pj_pool_factory *pf, pj_ioqueue_t *ioqueue, unsigned worker_cnt, pjmedia_endpt **p_endpt)
pj_status_t pjmedia_codec_ffmpeg_vid_init(pjmedia_vid_codec_mgr *mgr, pj_pool_factory *pf)
pj_sockaddr_in6 ipv6
pj_status_t pjmedia_vid_port_start(pjmedia_vid_port *vid_port)
void pjmedia_transport_info_init(pjmedia_transport_info *info)
char * pjsip_tx_data_get_info(pjsip_tx_data *tdata)
pj_status_t pj_gethostip(int af, pj_sockaddr *addr)
pj_status_t pjmedia_vid_dev_default_param(pj_pool_t *pool, pjmedia_vid_dev_index id, pjmedia_vid_dev_param *param)
pj_str_t pj_str(char *str)
pj_status_t pjsip_tsx_layer_init_module(pjsip_endpoint *endpt)
pjsip_msg * msg
Definition: sip_transport.h:365
pj_status_t pjsip_100rel_init_module(pjsip_endpoint *endpt)
void pj_caching_pool_init(pj_caching_pool *ch_pool, const pj_pool_factory_policy *policy, pj_size_t max_capacity)
pj_status_t pj_sockaddr_init(int af, pj_sockaddr *addr, const pj_str_t *cp, pj_uint16_t port)
char dst_name[PJ_INET6_ADDRSTRLEN]
Definition: sip_transport.h:615
pj_status_t pjsip_inv_verify_request(pjsip_rx_data *rdata, unsigned *options, const pjmedia_sdp_session *sdp, pjsip_dialog *dlg, pjsip_endpoint *endpt, pjsip_tx_data **tdata)
PJ_BEGIN_DECL pj_status_t pjlib_util_init(void)
char * pj_sockaddr_print(const pj_sockaddr_t *addr, char *buf, int size, unsigned flags)
void pj_bzero(void *dst, pj_size_t size)
pj_status_t pjsip_dlg_create_uas_and_inc_lock(pjsip_user_agent *ua, pjsip_rx_data *rdata, const pj_str_t *contact, pjsip_dialog **p_dlg)
void(* on_state_changed)(pjsip_inv_session *inv, pjsip_event *e)
Definition: sip_inv.h:128
pj_status_t pjsip_ua_init_module(pjsip_endpoint *endpt, const pjsip_ua_init_param *prm)
pj_status_t pjmedia_codec_openh264_vid_deinit(void)
pj_status_t pjmedia_vid_dev_subsys_init(pj_pool_factory *pf)
#define PJ_EAFNOTSUP
struct pjsip_endpoint pjsip_endpoint
Definition: sip_types.h:112
#define pj_assert(expr)
Definition: sip_inv.h:115
void pjmedia_vid_port_destroy(pjmedia_vid_port *vid_port)
char * pjsip_rx_data_get_info(pjsip_rx_data *rdata)
pjsip_inv_state state
Definition: sip_inv.h:437
#define PJ_ARRAY_SIZE(a)
pj_status_t pjmedia_stream_destroy(pjmedia_stream *stream)
pjsip_transport * transport
Definition: sip_transport.h:308
int src_port
Definition: sip_transport.h:347
union pjsip_msg::@17 line
unsigned PJMEDIA_PIA_SPF(const pjmedia_port_info *pia)
struct pjsip_tx_data::@27 tp_info
pj_status_t pjmedia_snd_port_connect(pjmedia_snd_port *snd_port, pjmedia_port *port)
PJMEDIA_VID_DEFAULT_RENDER_DEV
unsigned PJMEDIA_PIA_SRATE(const pjmedia_port_info *pia)
pj_status_t pjmedia_transport_udp_create3(pjmedia_endpt *endpt, int af, const char *name, const pj_str_t *addr, int port, unsigned options, pjmedia_transport **p_tp)
pj_status_t pjmedia_transport_media_start(pjmedia_transport *tp, pj_pool_t *tmp_pool, const pjmedia_sdp_session *sdp_local, const pjmedia_sdp_session *sdp_remote, unsigned media_index)
PJMEDIA_DIR_CAPTURE
pj_sockaddr_in ipv4
pj_status_t pjsip_inv_invite(pjsip_inv_session *inv, pjsip_tx_data **p_tdata)
unsigned PJMEDIA_PIA_BITS(const pjmedia_port_info *pia)
Definition: sip_module.h:54
#define pj_AF_INET6()
pj_pool_t * pjmedia_endpt_create_pool(pjmedia_endpt *endpt, const char *name, pj_size_t initial, pj_size_t increment)
Definition: sip_dialog.h:136
pj_status_t pjmedia_stream_get_port(pjmedia_stream *stream, pjmedia_port **p_port)
pj_status_t pjmedia_codec_openh264_vid_init(pjmedia_vid_codec_mgr *mgr, pj_pool_factory *pf)
PJ_BEGIN_DECL pj_status_t pjmedia_codec_g711_init(pjmedia_endpt *endpt)
pj_status_t pjmedia_vid_stream_get_port(pjmedia_vid_stream *stream, pjmedia_dir dir, pjmedia_port **p_port)
void(* on_new_session)(pjsip_inv_session *inv, pjsip_event *e)
Definition: sip_inv.h:142
PJ_SUCCESS
pjmedia_format fmt
pj_status_t pjmedia_vid_port_create(pj_pool_t *pool, const pjmedia_vid_port_param *prm, pjmedia_vid_port **p_vp)
unsigned short pj_uint16_t
pjsip_transport * transport
Definition: sip_transport.h:612
pj_status_t pj_init(void)
pj_status_t pjsip_inv_answer(pjsip_inv_session *inv, int st_code, const pj_str_t *st_text, const pjmedia_sdp_session *local_sdp, pjsip_tx_data **p_tdata)
pj_status_t pjmedia_endpt_destroy(pjmedia_endpt *endpt)
pjsip_method method
Definition: sip_msg.h:435
pjsip_status_code cause
Definition: sip_inv.h:441
PJ_FALSE
void pj_log_set_level(int level)
#define PJ_UNUSED_ARG(arg)
pj_status_t pjmedia_codec_vpx_vid_deinit(void)
pj_status_t pjmedia_endpt_create_sdp(pjmedia_endpt *endpt, pj_pool_t *pool, unsigned stream_cnt, const pjmedia_sock_info sock_info[], pjmedia_sdp_session **p_sdp)
pj_status_t pjmedia_codec_ffmpeg_vid_deinit(void)
#define PJ_INET6_ADDRSTRLEN
Definition: sip_module.h:211

 


PJSIP Open Source, high performance, small footprint, and very very portable SIP stack
Copyright (C) 2006-2008 Teluu Inc.