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: Video Streaming

This example mainly demonstrates how to stream video to remote peer using RTP.

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

1/*
2 * Copyright (C) 2011 Teluu Inc. (http://www.teluu.com)
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19
31#include <pjlib.h>
32#include <pjlib-util.h>
33#include <pjmedia.h>
34#include <pjmedia-codec.h>
36
37
38#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
39
40
41#include <stdlib.h> /* atoi() */
42#include <stdio.h>
43
44#include "util.h"
45
46
47static const char *desc =
48 " vid_streamutil \n"
49 "\n"
50 " PURPOSE: \n"
51 " Demonstrate how to use pjmedia video stream component to \n"
52 " transmit/receive RTP packets to/from video device/file. \n"
53 "\n"
54 "\n"
55 " USAGE: \n"
56 " vid_streamutil [options] \n"
57 "\n"
58 "\n"
59 " Options: \n"
60 " --codec=CODEC Set the codec name. \n"
61 " --local-port=PORT Set local RTP port (default=4000) \n"
62 " --remote=IP:PORT Set the remote peer. If this option is set, \n"
63 " the program will transmit RTP audio to the \n"
64 " specified address. (default: recv only) \n"
65 " --play-file=AVI Send video from the AVI file instead of from \n"
66 " the video device. \n"
67 " --send-recv Set stream direction to bidirectional. \n"
68 " --send-only Set stream direction to send only \n"
69 " --recv-only Set stream direction to recv only (default) \n"
70
71 " --send-width Video width to be sent \n"
72 " --send-height Video height to be sent \n"
73 " --send-width and --send-height not applicable \n"
74 " for file streaming (see --play-file) \n"
75
76 " --send-pt Payload type for sending \n"
77 " --recv-pt Payload type for receiving \n"
78
79#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
80 " --use-srtp[=NAME] Enable SRTP with crypto suite NAME \n"
81 " e.g: AES_CM_128_HMAC_SHA1_80 (default), \n"
82 " AES_CM_128_HMAC_SHA1_32 \n"
83 " Use this option along with the TX & RX keys, \n"
84 " formated of 60 hex digits (e.g: E148DA..) \n"
85 " --srtp-tx-key SRTP key for transmiting \n"
86 " --srtp-rx-key SRTP key for receiving \n"
87#endif
88
89 "\n"
90;
91
92#define THIS_FILE "vid_streamutil.c"
93
94
95/* If set, local renderer will be created to play original file */
96#define HAS_LOCAL_RENDERER_FOR_PLAY_FILE 1
97
98
99/* Default width and height for the renderer, better be set to maximum
100 * acceptable size.
101 */
102#define DEF_RENDERER_WIDTH 640
103#define DEF_RENDERER_HEIGHT 480
104
105
106/* Hexa string to octet array */
107int my_hex_string_to_octet_string(char *raw, char *hex, int len)
108{
109 int i;
110 for (i = 0; i < len; i+=2) {
111 int tmp;
112 if (i+1 >= len || !pj_isxdigit(hex[i]) || !pj_isxdigit(hex[i+1]))
113 return i;
114 tmp = pj_hex_digit_to_val((unsigned char)hex[i]) << 4;
115 tmp |= pj_hex_digit_to_val((unsigned char)hex[i+1]);
116 raw[i/2] = (char)(tmp & 0xFF);
117 }
118 return len;
119}
120
121/*
122 * Register all codecs.
123 */
124static pj_status_t init_codecs(pj_pool_factory *pf)
125{
126 pj_status_t status;
127
128 /* To suppress warning about unused var when all codecs are disabled */
129 PJ_UNUSED_ARG(status);
130 PJ_UNUSED_ARG(pf);
131
132#if defined(PJMEDIA_HAS_OPENH264_CODEC) && PJMEDIA_HAS_OPENH264_CODEC != 0
133 status = pjmedia_codec_openh264_vid_init(NULL, pf);
134 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
135#endif
136
137#if defined(PJMEDIA_HAS_VID_TOOLBOX_CODEC) && \
138 PJMEDIA_HAS_VID_TOOLBOX_CODEC != 0
139 status = pjmedia_codec_vid_toolbox_init(NULL, pf);
140 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
141#endif
142
143#if defined(PJMEDIA_HAS_VPX_CODEC) && PJMEDIA_HAS_VPX_CODEC != 0
144 status = pjmedia_codec_vpx_vid_init(NULL, pf);
145 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
146#endif
147
148#if defined(PJMEDIA_HAS_FFMPEG_VID_CODEC) && PJMEDIA_HAS_FFMPEG_VID_CODEC != 0
149 status = pjmedia_codec_ffmpeg_vid_init(NULL, pf);
150 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
151#endif
152
153 return PJ_SUCCESS;
154}
155
156/*
157 * Register all codecs.
158 */
159static void deinit_codecs()
160{
161#if defined(PJMEDIA_HAS_FFMPEG_VID_CODEC) && PJMEDIA_HAS_FFMPEG_VID_CODEC != 0
163#endif
164
165#if defined(PJMEDIA_HAS_OPENH264_CODEC) && PJMEDIA_HAS_OPENH264_CODEC != 0
167#endif
168
169#if defined(PJMEDIA_HAS_VID_TOOLBOX_CODEC) && \
170 PJMEDIA_HAS_VID_TOOLBOX_CODEC != 0
172#endif
173
174#if defined(PJMEDIA_HAS_VPX_CODEC) && PJMEDIA_HAS_VPX_CODEC != 0
176#endif
177
178}
179
180static pj_status_t create_file_player( pj_pool_t *pool,
181 const char *file_name,
182 pjmedia_port **p_play_port)
183{
184 pjmedia_avi_streams *avi_streams;
185 pjmedia_avi_stream *vid_stream;
186 pjmedia_port *play_port;
187 pj_status_t status;
188
189 status = pjmedia_avi_player_create_streams(pool, file_name, 0, &avi_streams);
190 if (status != PJ_SUCCESS)
191 return status;
192
193 vid_stream = pjmedia_avi_streams_get_stream_by_media(avi_streams,
194 0,
196 if (!vid_stream)
197 return PJ_ENOTFOUND;
198
199 play_port = pjmedia_avi_stream_get_port(vid_stream);
200 pj_assert(play_port);
201
202 *p_play_port = play_port;
203
204 return PJ_SUCCESS;
205}
206
207/*
208 * Create stream based on the codec, dir, remote address, etc.
209 */
210static pj_status_t create_stream( pj_pool_t *pool,
211 pjmedia_endpt *med_endpt,
212 const pjmedia_vid_codec_info *codec_info,
213 pjmedia_vid_codec_param *codec_param,
214 pjmedia_dir dir,
215 pj_int8_t rx_pt,
216 pj_int8_t tx_pt,
217 pj_uint16_t local_port,
218 const pj_sockaddr_in *rem_addr,
219#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
220 pj_bool_t use_srtp,
221 const pj_str_t *crypto_suite,
222 const pj_str_t *srtp_tx_key,
223 const pj_str_t *srtp_rx_key,
224#endif
225 pjmedia_vid_stream **p_stream )
226{
228 pjmedia_transport *transport = NULL;
229 pj_status_t status;
230#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
231 pjmedia_transport *srtp_tp = NULL;
232#endif
233
234 /* Reset stream info. */
235 pj_bzero(&info, sizeof(info));
236
237 /* Initialize stream info formats */
239 info.dir = dir;
240 info.codec_info = *codec_info;
241 info.tx_pt = (tx_pt == -1)? codec_info->pt : tx_pt;
242 info.rx_pt = (rx_pt == -1)? codec_info->pt : rx_pt;
243 info.ssrc = pj_rand();
244 if (codec_param)
245 info.codec_param = codec_param;
246
247 /* Copy remote address */
248 pj_memcpy(&info.rem_addr, rem_addr, sizeof(pj_sockaddr_in));
249
250 /* If remote address is not set, set to an arbitrary address
251 * (otherwise stream will assert).
252 */
253 if (info.rem_addr.addr.sa_family == 0) {
254 const pj_str_t addr = pj_str("127.0.0.1");
255 pj_sockaddr_in_init(&info.rem_addr.ipv4, &addr, 0);
256 }
257
258 /* Create media transport */
259 status = pjmedia_transport_udp_create(med_endpt, NULL, local_port,
260 0, &transport);
261 if (status != PJ_SUCCESS)
262 return status;
263
264#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
265 /* Check if SRTP enabled */
266 if (use_srtp) {
267 pjmedia_srtp_crypto tx_plc, rx_plc;
268
269 status = pjmedia_transport_srtp_create(med_endpt, transport,
270 NULL, &srtp_tp);
271 if (status != PJ_SUCCESS)
272 return status;
273
274 pj_bzero(&tx_plc, sizeof(pjmedia_srtp_crypto));
275 pj_bzero(&rx_plc, sizeof(pjmedia_srtp_crypto));
276
277 tx_plc.key = *srtp_tx_key;
278 tx_plc.name = *crypto_suite;
279 rx_plc.key = *srtp_rx_key;
280 rx_plc.name = *crypto_suite;
281
282 status = pjmedia_transport_srtp_start(srtp_tp, &tx_plc, &rx_plc);
283 if (status != PJ_SUCCESS)
284 return status;
285
286 transport = srtp_tp;
287 }
288#endif
289
290 /* Now that the stream info is initialized, we can create the
291 * stream.
292 */
293
294 status = pjmedia_vid_stream_create( med_endpt, pool, &info,
295 transport,
296 NULL, p_stream);
297
298 if (status != PJ_SUCCESS) {
299 app_perror(THIS_FILE, "Error creating stream", status);
300 pjmedia_transport_close(transport);
301 return status;
302 }
303
304 /* Start media transport */
305 pjmedia_transport_media_start(transport, 0, 0, 0, 0);
306
307 return PJ_SUCCESS;
308}
309
310
311typedef struct play_file_data
312{
313 const char *file_name;
314 pjmedia_port *play_port;
315 pjmedia_port *stream_port;
316 pjmedia_vid_codec *decoder;
317 pjmedia_port *renderer;
318 void *read_buf;
319 pj_size_t read_buf_size;
320 void *dec_buf;
321 pj_size_t dec_buf_size;
322} play_file_data;
323
324
325static void clock_cb(const pj_timestamp *ts, void *user_data)
326{
327 play_file_data *play_file = (play_file_data*)user_data;
328 pjmedia_frame read_frame, write_frame;
329 pj_status_t status;
330
331 PJ_UNUSED_ARG(ts);
332
333 /* Read frame from file */
334 read_frame.buf = play_file->read_buf;
335 read_frame.size = play_file->read_buf_size;
336 pjmedia_port_get_frame(play_file->play_port, &read_frame);
337
338 /* Decode frame, if needed */
339 if (play_file->decoder) {
340 pjmedia_vid_codec *decoder = play_file->decoder;
341
342 write_frame.buf = play_file->dec_buf;
343 write_frame.size = play_file->dec_buf_size;
344 status = pjmedia_vid_codec_decode(decoder, 1, &read_frame,
345 (unsigned)write_frame.size,
346 &write_frame);
347 if (status != PJ_SUCCESS)
348 return;
349 } else {
350 write_frame = read_frame;
351 }
352
353 /* Display frame locally */
354 if (play_file->renderer)
355 pjmedia_port_put_frame(play_file->renderer, &write_frame);
356
357 /* Send frame */
358 pjmedia_port_put_frame(play_file->stream_port, &write_frame);
359}
360
361
362/*
363 * usage()
364 */
365static void usage()
366{
367 puts(desc);
368}
369
370/*
371 * main()
372 */
373static int main_func(int argc, char *argv[])
374{
376 pjmedia_endpt *med_endpt;
377 pj_pool_t *pool;
378 pjmedia_vid_stream *stream = NULL;
379 pjmedia_port *enc_port, *dec_port;
380 char addr[PJ_INET_ADDRSTRLEN];
381 pj_status_t status;
382
383 pjmedia_vid_port *capture=NULL, *renderer=NULL;
385
386#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
387 /* SRTP variables */
388 pj_bool_t use_srtp = PJ_FALSE;
389 char tmp_tx_key[64];
390 char tmp_rx_key[64];
391 pj_str_t srtp_tx_key = {NULL, 0};
392 pj_str_t srtp_rx_key = {NULL, 0};
393 pj_str_t srtp_crypto_suite = {NULL, 0};
394 int tmp_key_len;
395#endif
396
397 /* Default values */
398 const pjmedia_vid_codec_info *codec_info;
399 pjmedia_vid_codec_param codec_param;
401 pj_sockaddr_in remote_addr;
402 pj_uint16_t local_port = 4000;
403 char *codec_id = NULL;
404 pjmedia_rect_size tx_size = {0};
405 pj_int8_t rx_pt = -1, tx_pt = -1;
406
407 play_file_data play_file = { NULL };
408 pjmedia_port *play_port = NULL;
409 pjmedia_vid_codec *play_decoder = NULL;
410 pjmedia_clock *play_clock = NULL;
411
412 enum {
413 OPT_CODEC = 'c',
414 OPT_LOCAL_PORT = 'p',
415 OPT_REMOTE = 'r',
416 OPT_PLAY_FILE = 'f',
417 OPT_SEND_RECV = 'b',
418 OPT_SEND_ONLY = 's',
419 OPT_RECV_ONLY = 'i',
420 OPT_SEND_WIDTH = 'W',
421 OPT_SEND_HEIGHT = 'H',
422 OPT_RECV_PT = 't',
423 OPT_SEND_PT = 'T',
424#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
425 OPT_USE_SRTP = 'S',
426#endif
427 OPT_SRTP_TX_KEY = 'x',
428 OPT_SRTP_RX_KEY = 'y',
429 OPT_HELP = 'h',
430 };
431
432 struct pj_getopt_option long_options[] = {
433 { "codec", 1, 0, OPT_CODEC },
434 { "local-port", 1, 0, OPT_LOCAL_PORT },
435 { "remote", 1, 0, OPT_REMOTE },
436 { "play-file", 1, 0, OPT_PLAY_FILE },
437 { "send-recv", 0, 0, OPT_SEND_RECV },
438 { "send-only", 0, 0, OPT_SEND_ONLY },
439 { "recv-only", 0, 0, OPT_RECV_ONLY },
440 { "send-width", 1, 0, OPT_SEND_WIDTH },
441 { "send-height", 1, 0, OPT_SEND_HEIGHT },
442 { "recv-pt", 1, 0, OPT_RECV_PT },
443 { "send-pt", 1, 0, OPT_SEND_PT },
444#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
445 { "use-srtp", 2, 0, OPT_USE_SRTP },
446 { "srtp-tx-key", 1, 0, OPT_SRTP_TX_KEY },
447 { "srtp-rx-key", 1, 0, OPT_SRTP_RX_KEY },
448#endif
449 { "help", 0, 0, OPT_HELP },
450 { NULL, 0, 0, 0 },
451 };
452
453 int c;
454 int option_index;
455
456
457 pj_bzero(&remote_addr, sizeof(remote_addr));
458
459
460 /* init PJLIB : */
461 status = pj_init();
462 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
463
464
465 /* Parse arguments */
466 pj_optind = 0;
467 while((c=pj_getopt_long(argc,argv, "h", long_options, &option_index))!=-1)
468 {
469 switch (c) {
470 case OPT_CODEC:
471 codec_id = pj_optarg;
472 break;
473
474 case OPT_LOCAL_PORT:
475 local_port = (pj_uint16_t) atoi(pj_optarg);
476 if (local_port < 1) {
477 printf("Error: invalid local port %s\n", pj_optarg);
478 return 1;
479 }
480 break;
481
482 case OPT_REMOTE:
483 {
484 pj_str_t ip = pj_str(strtok(pj_optarg, ":"));
485 pj_uint16_t port = (pj_uint16_t) atoi(strtok(NULL, ":"));
486
487 status = pj_sockaddr_in_init(&remote_addr, &ip, port);
488 if (status != PJ_SUCCESS) {
489 app_perror(THIS_FILE, "Invalid remote address", status);
490 return 1;
491 }
492 }
493 break;
494
495 case OPT_PLAY_FILE:
496 play_file.file_name = pj_optarg;
497 break;
498
499 case OPT_SEND_RECV:
501 break;
502
503 case OPT_SEND_ONLY:
505 break;
506
507 case OPT_RECV_ONLY:
509 break;
510
511 case OPT_SEND_WIDTH:
512 tx_size.w = (unsigned)atoi(pj_optarg);
513 break;
514
515 case OPT_SEND_HEIGHT:
516 tx_size.h = (unsigned)atoi(pj_optarg);
517 break;
518
519 case OPT_RECV_PT:
520 rx_pt = (pj_int8_t)atoi(pj_optarg);
521 break;
522
523 case OPT_SEND_PT:
524 tx_pt = (pj_int8_t)atoi(pj_optarg);
525 break;
526
527#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
528 case OPT_USE_SRTP:
529 use_srtp = PJ_TRUE;
530 if (pj_optarg) {
531 pj_strset(&srtp_crypto_suite, pj_optarg, strlen(pj_optarg));
532 } else {
533 srtp_crypto_suite = pj_str("AES_CM_128_HMAC_SHA1_80");
534 }
535 break;
536
537 case OPT_SRTP_TX_KEY:
538 tmp_key_len = my_hex_string_to_octet_string(tmp_tx_key, pj_optarg,
539 (int)strlen(pj_optarg));
540 pj_strset(&srtp_tx_key, tmp_tx_key, tmp_key_len/2);
541 break;
542
543 case OPT_SRTP_RX_KEY:
544 tmp_key_len = my_hex_string_to_octet_string(tmp_rx_key, pj_optarg,
545 (int)strlen(pj_optarg));
546 pj_strset(&srtp_rx_key, tmp_rx_key, tmp_key_len/2);
547 break;
548#endif
549
550 case OPT_HELP:
551 usage();
552 return 1;
553
554 default:
555 printf("Invalid options %s\n", argv[pj_optind]);
556 return 1;
557 }
558
559 }
560
561
562 /* Verify arguments. */
563 if (dir & PJMEDIA_DIR_ENCODING) {
564 if (remote_addr.sin_addr.s_addr == 0) {
565 printf("Error: remote address must be set\n");
566 return 1;
567 }
568 }
569
570 if (play_file.file_name != NULL && dir != PJMEDIA_DIR_ENCODING) {
571 printf("Direction is set to --send-only because of --play-file\n");
573 }
574
575#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
576 /* SRTP validation */
577 if (use_srtp) {
578 if (!srtp_tx_key.slen || !srtp_rx_key.slen)
579 {
580 printf("Error: Key for each SRTP stream direction must be set\n");
581 return 1;
582 }
583 }
584#endif
585
586 /* Must create a pool factory before we can allocate any memory. */
588
589 /*
590 * Initialize media endpoint.
591 * This will implicitly initialize PJMEDIA too.
592 */
593 status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt);
594 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
595
596 /* Create memory pool for application purpose */
597 pool = pj_pool_create( &cp.factory, /* pool factory */
598 "app", /* pool name. */
599 4000, /* init size */
600 4000, /* increment size */
601 NULL /* callback on error */
602 );
603
604 /* Init video format manager */
605 pjmedia_video_format_mgr_create(pool, 64, 0, NULL);
606
607 /* Init video converter manager */
609
610 /* Init event manager */
611 pjmedia_event_mgr_create(pool, 0, NULL);
612
613 /* Init video codec manager */
615
616 /* Init video subsystem */
618
619 /* Register all supported codecs */
620 status = init_codecs(&cp.factory);
621 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
622
623
624 /* Find which codec to use. */
625 if (codec_id) {
626 unsigned count = 1;
627 pj_str_t str_codec_id = pj_str(codec_id);
628
630 &str_codec_id, &count,
631 &codec_info, NULL);
632 if (status != PJ_SUCCESS) {
633 printf("Error: unable to find codec %s\n", codec_id);
634 return 1;
635 }
636 } else {
637 static pjmedia_vid_codec_info info[1];
638 unsigned count = PJ_ARRAY_SIZE(info);
639
640 /* Default to first codec */
641 pjmedia_vid_codec_mgr_enum_codecs(NULL, &count, info, NULL);
642 codec_info = &info[0];
643 }
644
645 /* Get codec default param for info */
646 status = pjmedia_vid_codec_mgr_get_default_param(NULL, codec_info,
647 &codec_param);
648 pj_assert(status == PJ_SUCCESS);
649
650 /* Set outgoing video size */
651 if (tx_size.w && tx_size.h)
652 codec_param.enc_fmt.det.vid.size = tx_size;
653
654#if DEF_RENDERER_WIDTH && DEF_RENDERER_HEIGHT
655 /* Set incoming video size */
656 if (DEF_RENDERER_WIDTH > codec_param.dec_fmt.det.vid.size.w)
657 codec_param.dec_fmt.det.vid.size.w = DEF_RENDERER_WIDTH;
658 if (DEF_RENDERER_HEIGHT > codec_param.dec_fmt.det.vid.size.h)
659 codec_param.dec_fmt.det.vid.size.h = DEF_RENDERER_HEIGHT;
660#endif
661
662 if (play_file.file_name) {
664 pjmedia_clock_param clock_param;
665 char fmt_name[5];
666
667 /* Create file player */
668 status = create_file_player(pool, play_file.file_name, &play_port);
669 if (status != PJ_SUCCESS)
670 goto on_exit;
671
672 /* Collect format info */
673 file_vfd = pjmedia_format_get_video_format_detail(&play_port->info.fmt,
674 PJ_TRUE);
675 PJ_LOG(2, (THIS_FILE, "Reading video stream %dx%d %s @%.2ffps",
676 file_vfd->size.w, file_vfd->size.h,
677 pjmedia_fourcc_name(play_port->info.fmt.id, fmt_name),
678 (1.0*file_vfd->fps.num/file_vfd->fps.denum)));
679
680 /* Allocate file read buffer */
681 play_file.read_buf_size = PJMEDIA_MAX_VIDEO_ENC_FRAME_SIZE;
682 play_file.read_buf = pj_pool_zalloc(pool, play_file.read_buf_size);
683
684 /* Create decoder, if the file and the stream uses different codec */
685 if (codec_info->fmt_id != (pjmedia_format_id)play_port->info.fmt.id) {
686 const pjmedia_video_format_info *dec_vfi;
687 pjmedia_video_apply_fmt_param dec_vafp = {0};
688 const pjmedia_vid_codec_info *codec_info2;
689 pjmedia_vid_codec_param codec_param2;
690
691 /* Find decoder */
693 play_port->info.fmt.id,
694 &codec_info2);
695 if (status != PJ_SUCCESS)
696 goto on_exit;
697
698 /* Init decoder */
699 status = pjmedia_vid_codec_mgr_alloc_codec(NULL, codec_info2,
700 &play_decoder);
701 if (status != PJ_SUCCESS)
702 goto on_exit;
703
704 status = play_decoder->op->init(play_decoder, pool);
705 if (status != PJ_SUCCESS)
706 goto on_exit;
707
708 /* Open decoder */
709 status = pjmedia_vid_codec_mgr_get_default_param(NULL, codec_info2,
710 &codec_param2);
711 if (status != PJ_SUCCESS)
712 goto on_exit;
713
714 codec_param2.dir = PJMEDIA_DIR_DECODING;
715 status = play_decoder->op->open(play_decoder, &codec_param2);
716 if (status != PJ_SUCCESS)
717 goto on_exit;
718
719 /* Get decoder format info and apply param */
720 dec_vfi = pjmedia_get_video_format_info(NULL,
721 codec_info2->dec_fmt_id[0]);
722 if (!dec_vfi || !dec_vfi->apply_fmt) {
723 status = PJ_ENOTSUP;
724 goto on_exit;
725 }
726 dec_vafp.size = file_vfd->size;
727 (*dec_vfi->apply_fmt)(dec_vfi, &dec_vafp);
728
729 /* Allocate buffer to receive decoder output */
730 play_file.dec_buf_size = dec_vafp.framebytes;
731 play_file.dec_buf = pj_pool_zalloc(pool, play_file.dec_buf_size);
732 }
733
734 /* Create player clock */
735 clock_param.usec_interval = PJMEDIA_PTIME(&file_vfd->fps);
736 clock_param.clock_rate = codec_info->clock_rate;
737 status = pjmedia_clock_create2(pool, &clock_param,
739 &clock_cb, &play_file, &play_clock);
740 if (status != PJ_SUCCESS)
741 goto on_exit;
742
743 /* Override stream codec param for encoding direction */
744 codec_param.enc_fmt.det.vid.size = file_vfd->size;
745 codec_param.enc_fmt.det.vid.fps = file_vfd->fps;
746
747 } else {
749
750 /* Set as active for all video devices */
751 vpp.active = PJ_TRUE;
752
753 /* Create video device port. */
754 if (dir & PJMEDIA_DIR_ENCODING) {
755 /* Create capture */
757 pool,
759 &vpp.vidparam);
760 if (status != PJ_SUCCESS)
761 goto on_exit;
762
763 pjmedia_format_copy(&vpp.vidparam.fmt, &codec_param.enc_fmt);
764 vpp.vidparam.fmt.id = codec_param.dec_fmt.id;
766
767 status = pjmedia_vid_port_create(pool, &vpp, &capture);
768 if (status != PJ_SUCCESS)
769 goto on_exit;
770 }
771
772 if (dir & PJMEDIA_DIR_DECODING) {
773 /* Create renderer */
775 pool,
777 &vpp.vidparam);
778 if (status != PJ_SUCCESS)
779 goto on_exit;
780
781 pjmedia_format_copy(&vpp.vidparam.fmt, &codec_param.dec_fmt);
787
788 status = pjmedia_vid_port_create(pool, &vpp, &renderer);
789 if (status != PJ_SUCCESS)
790 goto on_exit;
791 }
792 }
793
794 /* Set to ignore fmtp */
795 codec_param.ignore_fmtp = PJ_TRUE;
796
797 /* Create stream based on program arguments */
798 status = create_stream(pool, med_endpt, codec_info, &codec_param,
799 dir, rx_pt, tx_pt, local_port, &remote_addr,
800#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
801 use_srtp, &srtp_crypto_suite,
802 &srtp_tx_key, &srtp_rx_key,
803#endif
804 &stream);
805 if (status != PJ_SUCCESS)
806 goto on_exit;
807
808 /* Get the port interface of the stream */
810 &enc_port);
811 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
812
814 &dec_port);
815 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
816
817 /* Start streaming */
819 if (status != PJ_SUCCESS)
820 goto on_exit;
821
822 /* Start renderer */
823 if (renderer) {
824 status = pjmedia_vid_port_connect(renderer, dec_port, PJ_FALSE);
825 if (status != PJ_SUCCESS)
826 goto on_exit;
827 status = pjmedia_vid_port_start(renderer);
828 if (status != PJ_SUCCESS)
829 goto on_exit;
830 }
831
832 /* Start capture */
833 if (capture) {
834 status = pjmedia_vid_port_connect(capture, enc_port, PJ_FALSE);
835 if (status != PJ_SUCCESS)
836 goto on_exit;
837 status = pjmedia_vid_port_start(capture);
838 if (status != PJ_SUCCESS)
839 goto on_exit;
840 }
841
842 /* Start playing file */
843 if (play_file.file_name) {
844
845#if HAS_LOCAL_RENDERER_FOR_PLAY_FILE
846 /* Create local renderer */
848 vpp.active = PJ_FALSE;
850 pool,
852 &vpp.vidparam);
853 if (status != PJ_SUCCESS)
854 goto on_exit;
855
857 pjmedia_format_copy(&vpp.vidparam.fmt, &codec_param.dec_fmt);
858 vpp.vidparam.fmt.det.vid.size = play_port->info.fmt.det.vid.size;
859 vpp.vidparam.fmt.det.vid.fps = play_port->info.fmt.det.vid.fps;
864
865 status = pjmedia_vid_port_create(pool, &vpp, &renderer);
866 if (status != PJ_SUCCESS)
867 goto on_exit;
868 status = pjmedia_vid_port_start(renderer);
869 if (status != PJ_SUCCESS)
870 goto on_exit;
871#endif
872
873 /* Init play file data */
874 play_file.play_port = play_port;
875 play_file.stream_port = enc_port;
876 play_file.decoder = play_decoder;
877 if (renderer) {
878 play_file.renderer = pjmedia_vid_port_get_passive_port(renderer);
879 }
880
881 status = pjmedia_clock_start(play_clock);
882 if (status != PJ_SUCCESS)
883 goto on_exit;
884 }
885
886 /* Done */
887
888 if (dir == PJMEDIA_DIR_DECODING)
889 printf("Stream is active, dir is recv-only, local port is %d\n",
890 local_port);
891 else if (dir == PJMEDIA_DIR_ENCODING)
892 printf("Stream is active, dir is send-only, sending to %s:%d\n",
893 pj_inet_ntop2(pj_AF_INET(), &remote_addr.sin_addr, addr,
894 sizeof(addr)),
895 pj_ntohs(remote_addr.sin_port));
896 else
897 printf("Stream is active, send/recv, local port is %d, "
898 "sending to %s:%d\n",
899 local_port,
900 pj_inet_ntop2(pj_AF_INET(), &remote_addr.sin_addr, addr,
901 sizeof(addr)),
902 pj_ntohs(remote_addr.sin_port));
903
904 if (dir & PJMEDIA_DIR_ENCODING)
905 PJ_LOG(2, (THIS_FILE, "Sending %dx%d %.*s @%.2ffps",
906 codec_param.enc_fmt.det.vid.size.w,
907 codec_param.enc_fmt.det.vid.size.h,
908 codec_info->encoding_name.slen,
909 codec_info->encoding_name.ptr,
910 (1.0*codec_param.enc_fmt.det.vid.fps.num/
911 codec_param.enc_fmt.det.vid.fps.denum)));
912
913 for (;;) {
914 char tmp[10];
915
916 puts("");
917 puts("Commands:");
918 puts(" q Quit");
919 puts("");
920
921 printf("Command: "); fflush(stdout);
922
923 if (fgets(tmp, sizeof(tmp), stdin) == NULL) {
924 puts("EOF while reading stdin, will quit now..");
925 break;
926 }
927
928 if (tmp[0] == 'q')
929 break;
930
931 }
932
933
934
935 /* Start deinitialization: */
936on_exit:
937
938 /* Stop video devices */
939 if (capture)
940 pjmedia_vid_port_stop(capture);
941 if (renderer)
942 pjmedia_vid_port_stop(renderer);
943
944 /* Stop and destroy file clock */
945 if (play_clock) {
946 pjmedia_clock_stop(play_clock);
947 pjmedia_clock_destroy(play_clock);
948 }
949
950 /* Destroy file reader/player */
951 if (play_port)
952 pjmedia_port_destroy(play_port);
953
954 /* Destroy file decoder */
955 if (play_decoder) {
956 play_decoder->op->close(play_decoder);
957 pjmedia_vid_codec_mgr_dealloc_codec(NULL, play_decoder);
958 }
959
960 /* Destroy video devices */
961 if (capture)
963 if (renderer)
964 pjmedia_vid_port_destroy(renderer);
965
966 /* Destroy stream */
967 if (stream) {
969
972
975 }
976
977 /* Deinit codecs */
978 deinit_codecs();
979
980 /* Shutdown video subsystem */
982
983 /* Destroy event manager */
985
986 /* Release application pool */
987 pj_pool_release( pool );
988
989 /* Destroy media endpoint. */
990 pjmedia_endpt_destroy( med_endpt );
991
992 /* Destroy pool factory */
994
995 /* Shutdown PJLIB */
996 pj_shutdown();
997
998 return (status == PJ_SUCCESS) ? 0 : 1;
999}
1000
1001
1002int main(int argc, char *argv[])
1003{
1004 return pj_run_app(&main_func, argc, argv, 0);
1005}
1006
1007#else
1008
1009int main(int argc, char *argv[])
1010{
1011 PJ_UNUSED_ARG(argc);
1012 PJ_UNUSED_ARG(argv);
1013 puts("Error: this sample requires video capability (PJMEDIA_HAS_VIDEO == 1)");
1014 return -1;
1015}
1016
1017#endif /* PJMEDIA_HAS_VIDEO */
struct pjmedia_avi_streams pjmedia_avi_streams
Definition: avi_stream.h:60
pjmedia_avi_stream * pjmedia_avi_streams_get_stream_by_media(pjmedia_avi_streams *streams, unsigned start_idx, pjmedia_type media_type)
pj_status_t pjmedia_avi_player_create_streams(pj_pool_t *pool, const char *filename, unsigned flags, pjmedia_avi_streams **p_streams)
pjmedia_port * pjmedia_avi_stream_get_port(pjmedia_avi_stream *stream)
Definition: avi_stream.h:124
pj_status_t pjmedia_clock_destroy(pjmedia_clock *clock)
struct pjmedia_clock pjmedia_clock
Definition: clock.h:161
pj_status_t pjmedia_clock_stop(pjmedia_clock *clock)
pj_status_t pjmedia_clock_create2(pj_pool_t *pool, const pjmedia_clock_param *param, unsigned options, pjmedia_clock_callback *cb, void *user_data, pjmedia_clock **p_clock)
pj_status_t pjmedia_clock_start(pjmedia_clock *clock)
@ PJMEDIA_CLOCK_NO_HIGHEST_PRIO
Definition: clock.h:179
pj_status_t pjmedia_codec_openh264_vid_init(pjmedia_vid_codec_mgr *mgr, pj_pool_factory *pf)
pj_status_t pjmedia_codec_openh264_vid_deinit(void)
pj_status_t pjmedia_codec_ffmpeg_vid_deinit(void)
pj_status_t pjmedia_codec_ffmpeg_vid_init(pjmedia_vid_codec_mgr *mgr, pj_pool_factory *pf)
pj_status_t pjmedia_codec_vid_toolbox_init(pjmedia_vid_codec_mgr *mgr, pj_pool_factory *pf)
pj_status_t pjmedia_codec_vid_toolbox_deinit(void)
pj_status_t pjmedia_codec_vpx_vid_init(pjmedia_vid_codec_mgr *mgr, pj_pool_factory *pf)
pj_status_t pjmedia_codec_vpx_vid_deinit(void)
#define PJMEDIA_MAX_VIDEO_ENC_FRAME_SIZE
Definition: pjmedia/config.h:1441
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)
void pjmedia_event_mgr_destroy(pjmedia_event_mgr *mgr)
unsigned PJMEDIA_PTIME(const pjmedia_ratio *frame_rate)
Definition: format.h:538
const pjmedia_video_format_info * pjmedia_get_video_format_info(pjmedia_video_format_mgr *mgr, pj_uint32_t id)
pjmedia_format_id
Definition: format.h:55
pjmedia_format * pjmedia_format_copy(pjmedia_format *dst, const pjmedia_format *src)
pjmedia_video_format_detail * pjmedia_format_get_video_format_detail(const pjmedia_format *fmt, pj_bool_t assert_valid)
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 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)
pj_status_t pjmedia_transport_srtp_create(pjmedia_endpt *endpt, pjmedia_transport *tp, const pjmedia_srtp_setting *opt, pjmedia_transport **p_tp)
pj_status_t pjmedia_transport_srtp_start(pjmedia_transport *srtp, const pjmedia_srtp_crypto *tx, const pjmedia_srtp_crypto *rx)
pj_status_t pjmedia_transport_udp_create(pjmedia_endpt *endpt, const char *name, int port, unsigned options, pjmedia_transport **p_tp)
pj_status_t pjmedia_transport_close(pjmedia_transport *tp)
Definition: transport.h:1030
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)
Definition: transport.h:994
pj_status_t pjmedia_transport_media_stop(pjmedia_transport *tp)
Definition: transport.h:1016
struct pjmedia_endpt pjmedia_endpt
Definition: pjmedia/types.h:186
const char * pjmedia_fourcc_name(pj_uint32_t sig, char buf[])
Definition: pjmedia/types.h:328
pjmedia_dir
Definition: pjmedia/types.h:152
@ PJMEDIA_TYPE_VIDEO
Definition: pjmedia/types.h:62
@ PJMEDIA_DIR_RENDER
Definition: pjmedia/types.h:169
@ PJMEDIA_DIR_ENCODING
Definition: pjmedia/types.h:157
@ PJMEDIA_DIR_ENCODING_DECODING
Definition: pjmedia/types.h:172
@ PJMEDIA_DIR_CAPTURE
Definition: pjmedia/types.h:160
@ PJMEDIA_DIR_DECODING
Definition: pjmedia/types.h:163
void pjmedia_vid_port_destroy(pjmedia_vid_port *vid_port)
pj_status_t pjmedia_vid_port_connect(pjmedia_vid_port *vid_port, pjmedia_port *port, pj_bool_t destroy)
struct pjmedia_vid_port pjmedia_vid_port
Definition: vid_port.h:68
pj_status_t pjmedia_vid_port_create(pj_pool_t *pool, const pjmedia_vid_port_param *prm, pjmedia_vid_port **p_vp)
void pjmedia_vid_port_param_default(pjmedia_vid_port_param *prm)
pj_status_t pjmedia_vid_port_start(pjmedia_vid_port *vid_port)
pjmedia_port * pjmedia_vid_port_get_passive_port(pjmedia_vid_port *vid_port)
pj_status_t pjmedia_vid_port_stop(pjmedia_vid_port *vid_port)
pj_status_t pjmedia_vid_codec_mgr_get_default_param(pjmedia_vid_codec_mgr *mgr, const pjmedia_vid_codec_info *info, pjmedia_vid_codec_param *param)
pj_status_t pjmedia_vid_codec_mgr_dealloc_codec(pjmedia_vid_codec_mgr *mgr, pjmedia_vid_codec *codec)
pj_status_t pjmedia_vid_codec_mgr_enum_codecs(pjmedia_vid_codec_mgr *mgr, unsigned *count, pjmedia_vid_codec_info info[], unsigned *prio)
pj_status_t pjmedia_vid_codec_mgr_alloc_codec(pjmedia_vid_codec_mgr *mgr, const pjmedia_vid_codec_info *info, pjmedia_vid_codec **p_codec)
pj_status_t pjmedia_vid_codec_decode(pjmedia_vid_codec *codec, pj_size_t pkt_count, pjmedia_frame packets[], unsigned out_size, pjmedia_frame *output)
Definition: vid_codec.h:825
pj_status_t pjmedia_vid_codec_mgr_find_codecs_by_id(pjmedia_vid_codec_mgr *mgr, const pj_str_t *codec_id, unsigned *count, const pjmedia_vid_codec_info *p_info[], unsigned prio[])
pj_status_t pjmedia_vid_codec_mgr_get_codec_info2(pjmedia_vid_codec_mgr *mgr, pjmedia_format_id fmt_id, const pjmedia_vid_codec_info **info)
pj_status_t pjmedia_vid_codec_mgr_create(pj_pool_t *pool, pjmedia_vid_codec_mgr **mgr)
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_status_t pjmedia_endpt_destroy(pjmedia_endpt *endpt)
Definition: endpoint.h:168
pj_status_t pjmedia_vid_stream_destroy(pjmedia_vid_stream *stream)
pj_status_t pjmedia_vid_stream_get_port(pjmedia_vid_stream *stream, pjmedia_dir dir, pjmedia_port **p_port)
pj_status_t pjmedia_vid_stream_start(pjmedia_vid_stream *stream)
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)
pjmedia_transport * pjmedia_vid_stream_get_transport(pjmedia_vid_stream *st)
int pj_run_app(pj_main_func_ptr main_func, int argc, char *argv[], unsigned flags)
pj_status_t pj_init(void)
int pj_bool_t
unsigned short pj_uint16_t
size_t pj_size_t
int pj_status_t
#define PJ_ARRAY_SIZE(a)
void pj_shutdown(void)
signed char pj_int8_t
PJ_SUCCESS
PJ_TRUE
PJ_FALSE
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)
pj_pool_factory_policy pj_pool_factory_default_policy
pj_pool_t * pj_pool_create(pj_pool_factory *factory, const char *name, pj_size_t initial_size, pj_size_t increment_size, pj_pool_callback *callback)
void * pj_pool_zalloc(pj_pool_t *pool, pj_size_t size)
void pj_pool_release(pj_pool_t *pool)
void * pj_memcpy(void *dst, const void *src, pj_size_t size)
pj_str_t pj_str(char *str)
pj_str_t * pj_strset(pj_str_t *str, char *ptr, pj_size_t length)
void pj_bzero(void *dst, pj_size_t size)
int pj_rand(void)
#define PJ_INET_ADDRSTRLEN
pj_uint16_t pj_ntohs(pj_uint16_t netshort)
#define pj_AF_INET()
pj_status_t pj_sockaddr_in_init(pj_sockaddr_in *addr, const pj_str_t *cp, pj_uint16_t port)
char * pj_inet_ntop2(int af, const void *src, char *dst, int size)
#define pj_assert(expr)
#define PJ_ASSERT_RETURN(expr, retval)
#define PJ_UNUSED_ARG(arg)
unsigned pj_hex_digit_to_val(unsigned char c)
int pj_isxdigit(unsigned char c)
#define PJ_ENOTFOUND
#define PJ_ENOTSUP
pj_status_t pjmedia_vid_dev_default_param(pj_pool_t *pool, pjmedia_vid_dev_index id, pjmedia_vid_dev_param *param)
pj_status_t pjmedia_vid_dev_subsys_shutdown(void)
pj_status_t pjmedia_vid_dev_subsys_init(pj_pool_factory *pf)
@ PJMEDIA_VID_DEV_WND_RESIZABLE
Definition: pjmedia/videodev.h:137
@ PJMEDIA_VID_DEV_WND_BORDER
Definition: pjmedia/videodev.h:132
@ PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW_FLAGS
Definition: pjmedia/videodev.h:298
@ PJMEDIA_VID_DEFAULT_CAPTURE_DEV
Definition: pjmedia/videodev.h:150
@ PJMEDIA_VID_DEFAULT_RENDER_DEV
Definition: pjmedia/videodev.h:155
Include all codecs API in PJMEDIA-CODEC.
PJMEDIA main header file.
pj_uint16_t sa_family
pj_pool_factory factory
pj_uint16_t sin_port
pj_in_addr sin_addr
pj_ssize_t slen
char * ptr
Definition: clock.h:184
unsigned usec_interval
Definition: clock.h:188
unsigned clock_rate
Definition: clock.h:193
union pjmedia_format::@11 det
pj_uint32_t id
Definition: format.h:303
pjmedia_video_format_detail vid
Definition: format.h:328
Definition: frame.h:56
void * buf
Definition: frame.h:58
pj_size_t size
Definition: frame.h:59
pjmedia_format fmt
Definition: port.h:247
Definition: port.h:378
pjmedia_port_info info
Definition: port.h:379
int denum
Definition: pjmedia/types.h:218
Definition: pjmedia/types.h:234
unsigned h
Definition: pjmedia/types.h:236
unsigned w
Definition: pjmedia/types.h:235
Definition: transport_srtp.h:91
pj_str_t key
Definition: transport_srtp.h:93
pj_str_t name
Definition: transport_srtp.h:96
Definition: transport.h:504
Definition: vid_codec.h:114
pjmedia_format_id dec_fmt_id[8]
Definition: vid_codec.h:123
pj_str_t encoding_name
Definition: vid_codec.h:117
pjmedia_format_id fmt_id
Definition: vid_codec.h:115
unsigned clock_rate
Definition: vid_codec.h:119
unsigned pt
Definition: vid_codec.h:116
pj_status_t(* open)(pjmedia_vid_codec *codec, pjmedia_vid_codec_param *param)
Definition: vid_codec.h:200
pj_status_t(* close)(pjmedia_vid_codec *codec)
Definition: vid_codec.h:206
pj_status_t(* init)(pjmedia_vid_codec *codec, pj_pool_t *pool)
Definition: vid_codec.h:194
Definition: vid_codec.h:148
pjmedia_dir dir
Definition: vid_codec.h:149
pjmedia_format dec_fmt
Definition: vid_codec.h:156
pj_bool_t ignore_fmtp
Definition: vid_codec.h:159
pjmedia_format enc_fmt
Definition: vid_codec.h:152
Definition: vid_codec.h:271
pjmedia_vid_codec_op * op
Definition: vid_codec.h:282
pjmedia_format fmt
Definition: pjmedia/videodev.h:447
pjmedia_dir dir
Definition: pjmedia/videodev.h:412
unsigned flags
Definition: pjmedia/videodev.h:442
unsigned window_flags
Definition: pjmedia/videodev.h:492
pjmedia_rect_size disp_size
Definition: pjmedia/videodev.h:460
Definition: vid_port.h:42
pjmedia_vid_dev_param vidparam
Definition: vid_port.h:46
pj_bool_t active
Definition: vid_port.h:61
Definition: vid_stream.h:150
unsigned rx_pt
Definition: vid_stream.h:163
pj_uint32_t ssrc
Definition: vid_stream.h:164
pjmedia_vid_codec_param * codec_param
Definition: vid_stream.h:193
pj_sockaddr rem_addr
Definition: vid_stream.h:155
unsigned tx_pt
Definition: vid_stream.h:162
pjmedia_vid_codec_info codec_info
Definition: vid_stream.h:192
pjmedia_dir dir
Definition: vid_stream.h:153
pjmedia_type type
Definition: vid_stream.h:151
Definition: format.h:362
pj_size_t framebytes
Definition: format.h:387
pjmedia_rect_size size
Definition: format.h:369
Definition: format.h:275
pjmedia_rect_size size
Definition: format.h:276
pjmedia_ratio fps
Definition: format.h:277
Definition: format.h:413
pj_status_t(* apply_fmt)(const struct pjmedia_video_format_info *vfi, pjmedia_video_apply_fmt_param *vafp)
Definition: format.h:456
Definition: jbsim.c:73
Secure RTP (SRTP) transport.
pj_addr_hdr addr
pj_sockaddr_in ipv4

 


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