UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
sdp.c
Go to the documentation of this file.
1/*
2 * FILE: utils/sdp.c
3 * AUTHORS: Gerard Castillo <gerard.castillo@i2cat.net>
4 * Martin Pulec <pulec@cesnet.cz>
5 *
6 * Copyright (c) 2005-2010 Fundació i2CAT, Internet I Innovació Digital a Catalunya
7 * Copyright (c) 2018-2024 CESNET, z. s. p. o.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, is permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 *
23 * This product includes software developed by CESNET z.s.p.o.
24 *
25 * 4. Neither the name of the CESNET nor the names of its contributors may be
26 * used to endorse or promote products derived from this software without
27 * specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
31 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
32 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
33 * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
34 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
35 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
36 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
38 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
39 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
40 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 */
50#include "utils/sdp.h"
51
52#include <assert.h>
53#include <errno.h>
54#include <pthread.h>
55#include <stdint.h>
56#include <stdio.h>
57#include <stdlib.h>
58#include <string.h>
59#ifdef _WIN32
60#include <winsock2.h>
61#include <ws2tcpip.h>
62#else
63#include <netdb.h>
64#include <sys/socket.h>
65#endif
66
67#include "audio/types.h"
68#include "compat/htonl.h" // for htons, htonl
69#include "compat/strings.h" // for strcasecmp
70#include "config.h" // for SDP_HTTP
71#include "debug.h"
72#include "rtp/rtp_types.h"
73#include "types.h"
74#include "utils/color_out.h"
75#include "utils/fs.h"
76#include "utils/misc.h"
77#include "utils/macros.h"
78#include "utils/net.h"
79#include "video_codec.h" // for get_codec_from_name
80#ifdef SDP_HTTP
81#define EWS_DISABLE_SNPRINTF_COMPAT
82#include "EmbeddableWebServer.h"
83#endif // SDP_HTTP
84
85#define MOD_NAME "[SDP] "
86#define SDP_FILE "ug.sdp"
87
88enum {
91};
92
95static bool want_sdp_audio = false;
96static bool want_sdp_video = false;
97static char sdp_receiver[1024];
99
100static struct sdp *sdp_state = NULL;
101
107
108struct sdp {
111#ifdef SDP_HTTP
112 struct Server http_server;
113#endif // defined SDP_HTTP
122 int stream_count; //between 1 and MAX_STREAMS
125 char *sdp_dump;
126 void (*audio_address_callback)(void *udata, const char *address);
128 void (*video_address_callback)(void *udata, const char *address);
130};
131
132static bool gen_sdp(void);
133static struct sdp *new_sdp(bool ipv6, const char *receiver);
134#ifdef SDP_HTTP
135static bool sdp_run_http_server(struct sdp *sdp, int port);
136static void sdp_stop_http_server(struct sdp *sdp);
137#endif // defined SDP_HTTP
138static void clean_sdp(struct sdp *sdp);
139
140static struct sdp *new_sdp(bool ipv6, const char *receiver) {
141 struct sdp *sdp = calloc(1, sizeof(*sdp));
142 assert(sdp != NULL);
143 sdp->audio_index = -1;
144 sdp->video_index = -1;
145 sdp->ip_version = ipv6 ? 6 : 4;
146 const char *ip_loopback;
147 if (sdp->ip_version == 6) {
148 ip_loopback = "::1";
149 } else {
150 ip_loopback = "127.0.0.1";
151 }
152 char hostname[256];
153 const char *connection_address = ip_loopback;
154 const char *origin_address = ip_loopback;
155 struct sockaddr_storage addrs[20];
156 size_t len = sizeof addrs;
157 if (get_local_addresses(addrs, &len, sdp->ip_version)) {
158 for (int i = 0; i < (int)(len / sizeof addrs[0]); ++i) {
159 if (!is_addr_linklocal((struct sockaddr *) &addrs[i]) && !is_addr_loopback((struct sockaddr *) &addrs[i])) {
160 bool ipv6 = addrs[i].ss_family == AF_INET6;
161 size_t sa_len = ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
162 getnameinfo((struct sockaddr *) &addrs[i], sa_len, hostname, sizeof(hostname), NULL, 0, NI_NUMERICHOST);
163 origin_address = hostname;
164 break;
165 }
166 }
167 }
168 if (is_addr_multicast(receiver)) {
169 connection_address = receiver;
170 }
171 snprintf(sdp->version, sizeof sdp->version, "v=0\r\n");
172 snprintf(sdp->origin, sizeof sdp->origin, "o=- 0 0 IN IP%d %s\r\n",
173 sdp->ip_version, origin_address);
174 snprintf(sdp->session_name, sizeof sdp->session_name,
175 "s=Ultragrid streams\r\n");
176 snprintf(sdp->connection, sizeof sdp->connection, "c=IN IP%d %s\r\n",
177 sdp->ip_version, connection_address);
178 snprintf(sdp->times, sizeof sdp->times, "t=0 0\r\n");
179
180#ifdef SDP_HTTP
181 serverInit(&sdp->http_server);
182#endif // defined SDP_HTTP
183
184 return sdp;
185}
186
187static int new_stream(struct sdp *sdp){
189 sdp->stream_count++;
190 return sdp->stream_count - 1;
191 }
192 return -1;
193}
194
195static void cleanup() {
196#ifdef SDP_HTTP
197 sdp_stop_http_server(sdp_state);
198#endif // defined SDP_HTTP
200}
201
202static void start() {
203 // either SDP properties not set or not all streams already configured
205 return;
206 }
207 if (!gen_sdp()) {
208 log_msg(LOG_LEVEL_ERROR, "[SDP] File creation failed\n");
209 return;
210 }
211#ifdef SDP_HTTP
212 if (!sdp_run_http_server(sdp_state, requested_http_port)) {
213 log_msg(LOG_LEVEL_ERROR, "[SDP] Server run failed!\n");
214 }
215#else
216 log_msg(LOG_LEVEL_WARNING, "[SDP] HTTP support not enabled - skipping server creation!\n");
217#endif
218
219 atexit(cleanup);
220}
221
226int
228 char rtpmapLine[STR_LEN])
229{
230 rtpmapLine[0] = '\0';
231 int pt = PT_DynRTP_Type97; // default
232
233 if (sample_rate == kHz8 && channels == 1 &&
234 (codec == AC_ALAW || codec == AC_MULAW)) {
236 }
237 if (codec == AC_MP3) {
238 pt = PT_MPA;
239 }
240
241 // skip rtpmap creation could be skipped for static PT, optionally added
242 // if (pt != PT_DynRTP_Type97) {
243 // rtpmapLine[0] = '\0';
244 // return pt;
245 // }
246
247 const int sdp_ch_count =
248 codec == AC_OPUS ? 2 : channels; // RFC 7587 enforces 2 for Opus
249 const char *sdp_codec_name = NULL;
250 switch (codec) {
251 case AC_MULAW:
252 sdp_codec_name = "PCMU";
253 break;
254 case AC_ALAW:
255 sdp_codec_name = "PCMA";
256 break;
257 case AC_OPUS:
258 sdp_codec_name = "opus";
259 break;
260 case AC_MP3: // rtpmap is optional for MPA
261 sdp_codec_name = "MPA";
262 break;
263 default:
264 abort();
265 }
266
267 snprintf(rtpmapLine, STR_LEN, "a=rtpmap:%u %s/%d/%d\r\n",
268 pt, sdp_codec_name, sample_rate, sdp_ch_count);
269 return pt;
270}
271
277int sdp_add_audio(bool ipv6, int port, int sample_rate, int channels, audio_codec_t codec, address_callback_t addr_callback, void *addr_callback_udata)
278{
279 if (!sdp_state) {
281 if (!sdp_state) {
282 assert(0 && "[SDP] SDP creation failed\n");
283 }
284 }
285 sdp_state->audio_address_callback = addr_callback;
286 sdp_state->audio_address_callback_udata = addr_callback_udata;
287 int index = new_stream(sdp_state);
288 if (index < 0) {
289 return -1;
290 }
291 sdp_state->audio_index = index;
293 sdp_state->stream[index].rtpmap);
294 snprintf(sdp_state->stream[index].media_info,
295 sizeof sdp_state->stream[index].media_info,
296 "m=audio %d RTP/AVP %d\r\n", port, pt);
297 sdp_state->audio_set = true;
298 start();
299
300 return 0;
301}
302
303int
305{
306 rtpmapLine[0] = '\0';
307 int pt = -1;
308 const char *rtpmap_codec = NULL;
309 switch (codec) {
310 case JPEG:
311 case MJPG:
312 pt = PT_JPEG;
313 rtpmap_codec = "JPEG";
314 break;
315 case H264:
316 pt = PT_DynRTP_Type96;
317 rtpmap_codec = "H264";
318 break;
319 default:
320 return -2;
321 }
322
323 assert(pt >= 0);
324 assert(rtpmap_codec != NULL);
325 snprintf(rtpmapLine, STR_LEN, "a=rtpmap:%d %s/90000\r\n",
326 pt, rtpmap_codec);
327 return pt;
328}
329
335int sdp_add_video(bool ipv6, int port, codec_t codec, address_callback_t addr_callback, void *addr_callback_udata)
336{
337 char rtpmap[STR_LEN];
338 const int pt = get_video_rtp_pt_rtpmap(codec, rtpmap);
339 if (pt < 0) {
340 return pt;
341 }
342 if (!sdp_state) {
344 if (!sdp_state) {
345 assert(0 && "[SDP] SDP creation failed\n");
346 }
347 }
348 sdp_state->video_address_callback = addr_callback;
349 sdp_state->video_address_callback_udata = addr_callback_udata;
350
351 int index = new_stream(sdp_state);
352 if (index < 0) {
353 return -1;
354 }
355 sdp_state->video_index = index;
356 snprintf(sdp_state->stream[index].media_info,
357 sizeof sdp_state->stream[index].media_info,
358 "m=video %d RTP/AVP %d\r\n", port, pt);
359 snprintf_ch(sdp_state->stream[index].rtpmap, "%s", rtpmap);
360
361 sdp_state->video_set = true;
362 start();
363 return 0;
364}
365
366static void strappend(char **dst, size_t *dst_alloc_len, const char *src)
367{
368 if (*dst_alloc_len < strlen(*dst) + strlen(src) + 1) {
369 *dst_alloc_len = strlen(*dst) + strlen(src) + 1;
370 *dst = realloc(*dst, *dst_alloc_len);
371 }
372 strncat(*dst, src, *dst_alloc_len - strlen(*dst) - 1);
373}
374
375static bool gen_sdp() {
376 size_t len = 1;
377 char *buf = calloc(1, 1);
378 strappend(&buf, &len, sdp_state->version);
379 strappend(&buf, &len, sdp_state->origin);
382 strappend(&buf, &len, sdp_state->times);
383 for (int i = 0; i < sdp_state->stream_count; ++i) {
385 strappend(&buf, &len, sdp_state->stream[i].rtpmap);
386 }
387 strappend(&buf, &len, "\r\n");
388
389 printf("Printed version:\n%s", buf);
390
391 sdp_state->sdp_dump = buf;
392 if (strcmp(sdp_filename, "no") == 0) {
393 return true;
394 }
395
396 if (strlen(sdp_filename) == 0) {
397 strncpy(sdp_filename, get_temp_dir(), sizeof sdp_filename - 1);
398 strncat(sdp_filename, SDP_FILE, sizeof sdp_filename - strlen(sdp_filename) - 1);
399 }
400 FILE *fOut = fopen(sdp_filename, "wb");
401 if (fOut == NULL) {
402 log_msg(LOG_LEVEL_ERROR, "Unable to write SDP file %s: %s\n", sdp_filename, ug_strerror(errno));
403 } else {
404 if (fprintf(fOut, "%s", buf) != (int) strlen(buf)) {
405 perror("fprintf");
406 } else {
407 printf("[SDP] File %s created.\n", sdp_filename);
408 }
409 fclose(fOut);
410 }
411
412 return true;
413}
414
415void clean_sdp(struct sdp *sdp){
416 if (!sdp) {
417 return;
418 }
419 free(sdp->sdp_dump);
420#ifdef SDP_HTTP
421 serverDeInit(&sdp->http_server);
422#endif // defined SDP_HTTP
423 free(sdp);
424}
425
426
427// --------------------------------------------------------------------
428// HTTP server stuff
429// --------------------------------------------------------------------
430#ifdef SDP_HTTP
431
432#define ROBOTS_TXT "User-agent: *\r\nDisallow: /\r\n"
433#define SECURITY_TXT "Contact: http://www.ultragrid.cz/contact\r\n"
434
435struct Response* createResponseForRequest(const struct Request* request, struct Connection* connection) {
436 struct sdp *sdp = connection->server->tag;
437
438 if (autorun) {
441 }
444 }
445 }
446
447 log_msg(LOG_LEVEL_VERBOSE, MOD_NAME "Requested %s.\n", request->pathDecoded);
448
449 if (strcasecmp(request->pathDecoded, "/robots.txt") == 0 ||
450 strcasecmp(request->pathDecoded, "/.well-known/security.txt") == 0 ||
451 strcasecmp(request->pathDecoded, "/security.txt") == 0) {
452 struct Response* response = responseAlloc(200, "OK", "text/plain", 0);
453 heapStringSetToCString(&response->body, strcasecmp(request->pathDecoded, "/robots.txt") == 0 ? ROBOTS_TXT : SECURITY_TXT);
454 return response;
455 }
456
457 log_msg(LOG_LEVEL_VERBOSE, MOD_NAME "Returning the SDP.\n");
458 const char *sdp_content = sdp->sdp_dump;
459 struct Response* response = responseAlloc(200, "OK", "application/sdp", 0);
460 heapStringSetToCString(&response->body, sdp_content);
461 return response;
462}
463
464static uint16_t portInHostOrder;
465
466static THREAD_RETURN_TYPE STDCALL_ON_WIN32 acceptConnectionsThread(void* param) {
467 struct sockaddr_storage ss = { 0 };
468 struct sdp *sdp = ((struct Server *) param)->tag;
469 ss.ss_family = sdp->ip_version == 4 ? AF_INET : AF_INET6;
470 size_t sa_len = sdp->ip_version == 4 ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
471 if (sdp->ip_version == 4) {
472 struct sockaddr_in *sin = (struct sockaddr_in *) &ss;
473 sin->sin_addr.s_addr = htonl(INADDR_ANY);
474 sin->sin_port = htons(portInHostOrder);
475 } else {
476 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &ss;
477 sin6->sin6_addr = in6addr_any;
478 sin6->sin6_port = htons(portInHostOrder);
479 }
480 acceptConnectionsUntilStopped(param, (struct sockaddr *) &ss, sa_len);
481 log_msg(LOG_LEVEL_WARNING, "Warning: HTTP/SDP thread has exited.\n");
482 return (THREAD_RETURN_TYPE) 0;
483}
484
489static void
490print_std_rtp_urls(struct sdp *sdp) {
491 const char *const bind_addr = sdp->ip_version == 6 ? "[::]" : "0.0.0.0";
492 int port = 0;
493 int pt = 0;
494 if (sdp->audio_index >= 0) {
496 "%*[^ ] %d RTP/AVP %d", &port, &pt) == 2 &&
497 pt < PT_DynRTP_Type96) {
498 MSG(NOTICE, "audio can be played directly with rtp://%s:%d\n",
499 bind_addr, port);
500 }
501 }
502 if (sdp->video_index >= 0) {
504 "%*[^ ] %d RTP/AVP %d", &port, &pt) == 2 &&
505 pt < PT_DynRTP_Type96) {
506 MSG(NOTICE, "video can be played directly with rtp://%s:%d\n",
507 bind_addr, port);
508 }
509 }
510}
511
512static void print_http_path(struct sdp *sdp) {
513 struct sockaddr_storage addrs[20];
514 size_t len = sizeof addrs;
515 if (get_local_addresses(addrs, &len, sdp->ip_version)) {
516 bool found_preferred_addr = false;
517#define PREFERRED_ADDR(addr) \
518 (!is_addr_loopback((struct sockaddr *) (addr)) && \
519 !is_addr_linklocal((struct sockaddr *) (addr)))
520 for (size_t i = 0; i < len / sizeof addrs[0]; ++i) {
521 if (PREFERRED_ADDR(&addrs[i])) {
522 found_preferred_addr = true;
523 }
524 }
525 for (size_t i = 0; i < len / sizeof addrs[0]; ++i) {
526 if (!found_preferred_addr || PREFERRED_ADDR(&addrs[i])) {
527 char hostname[256];
528 bool ipv6 = addrs[i].ss_family == AF_INET6;
529 size_t sa_len = ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
530 getnameinfo((struct sockaddr *) &addrs[i], sa_len, hostname, sizeof(hostname), NULL, 0, NI_NUMERICHOST);
531
532 char recv_str[STR_LEN];
533 if (autorun) {
534 snprintf(recv_str, sizeof recv_str, "ANY receiver");
535 } else {
536 snprintf(recv_str, sizeof recv_str, "Receiver \"%s\"", sdp_receiver);
537 }
538 MSG(NOTICE,
539 "%s can play SDP with URL "
540 "http://%s%s%s:%u/%s\n",
541 recv_str, ipv6 ? "[" : "", hostname, ipv6 ? "]" : "",
542 portInHostOrder, SDP_FILE);
543 }
544 }
545 }
546 if (!autorun) {
547 print_std_rtp_urls(sdp);
548 }
549}
550
551static bool sdp_run_http_server(struct sdp *sdp, int port)
552{
553 assert(port >= 0 && port < 65536);
554 assert(sdp->sdp_dump != NULL);
555
556 portInHostOrder = port;
557 sdp->http_server.tag = sdp;
558 pthread_create(&sdp->http_server_thr, NULL, &acceptConnectionsThread, &sdp->http_server);
559 // some resource will definitely leak but it shouldn't be a problem
560 print_http_path(sdp);
561 return true;
562}
563
564void sdp_stop_http_server(struct sdp *sdp)
565{
567 serverMutexLock(&sdp->http_server);
568 sdp->http_server.shouldRun = false;
569 serverMutexUnlock(&sdp->http_server);
570 pthread_cancel(sdp->http_server_thr);
571
572 pthread_join(sdp->http_server_thr, NULL);
573}
574#endif // defined SDP_HTTP
575
576void sdp_set_properties(const char *receiver, bool has_sdp_video, bool has_sdp_audio)
577{
578 strncpy(sdp_receiver, receiver, sizeof sdp_receiver - 1);
579 want_sdp_audio = has_sdp_audio;
580 want_sdp_video = has_sdp_video;
581
582 start();
583}
584
585int sdp_set_options(const char *opts) {
586 if (strcmp(opts, "help") == 0) {
587 color_printf("Usage:\n");
588 color_printf("\t" TBOLD("uv " TRED("--protocol sdp") "[:autorun][:file=<name>|no][:port=<http_port>]") "\n");
589 color_printf("where:\n");
590 color_printf("\t" TBOLD("autorun") " - automatically send to the address that requested the SDP over HTTP without giving an address (use with caution!)\n");
591 color_printf("\n");
593 return 1;
594 }
595
596 char opts_c[strlen(opts) + 1];
597 char *tmp = opts_c;
598 strcpy(opts_c, opts);
599 char *item, *save_ptr;
600 while ((item = strtok_r(tmp, ":", &save_ptr)) != NULL) {
601 if (strstr(item, "port=") == item) {
602 requested_http_port = atoi(strchr(item, '=') + 1);
603 } else if (strstr(item, "file=") == item) {
604 strncpy(sdp_filename, strchr(item, '=') + 1, sizeof sdp_filename - 1);
605 } else if (strstr(item, "autorun") == item) {
606 autorun = true;
607 } else {
608 log_msg(LOG_LEVEL_ERROR, "[SDP] Wrong option: %s\n", item);
609 return -1;
610 }
611 tmp = NULL;
612 }
613 return 0;
614}
615
622get_video_codec_from_pt_rtpmap(int pt, const char *rtpmap_codec_name)
623{
624 // prefer PT type (if assigned) if codec is in form "?H264" (the mapping
625 // was incorrect), otherwise prefer the value from rtpmap
626 bool prefer_pt = false;
627 if (rtpmap_codec_name[0] == '?') {
628 rtpmap_codec_name += 1;
629 prefer_pt = true;
630 }
631
632 codec_t c = VC_NONE;
633 if (strlen(rtpmap_codec_name) > 1) {
634 c = get_codec_from_name(rtpmap_codec_name);
635 if (c == VC_NONE) {
636 MSG(WARNING, "Codec %s not known to UltraGrid!\n",
637 rtpmap_codec_name);
638 }
639 }
640
641 if (!prefer_pt && c != VC_NONE) {
642 return c;
643 }
644 if (pt == PT_JPEG) {
645 return JPEG;
646 }
647 MSG(WARNING, "No mapping of PT=%d to video coddec in UG!\n", pt);
648 return VC_NONE;
649}
650
651void
653{
655 color_printf("Supported audio codecs: " TBOLD("MP3") ", " TBOLD(
656 "Opus") ", " TBOLD("PCMA") " (A-law), " TBOLD("PCMU") " (u-law)\n");
658 "Supported video codecs: " TBOLD("H.264") ", " TBOLD("JPEG") "\n");
659 color_printf("\n");
660}
661
662/* vim: set expandtab sw=4 : */
int int int sample_rate
int int channels
int void size_t * len
codec_t get_codec_from_name(const char *name)
This file contains definition of some common audio types.
audio_codec_t
Definition types.h:51
@ AC_OPUS
Definition types.h:57
@ AC_MULAW
Definition types.h:55
@ AC_MP3
Definition types.h:59
@ AC_ALAW
Definition types.h:54
int color_printf(const char *format,...)
#define TRED(x)
Definition color_out.h:75
#define TBOLD(x)
Definition color_out.h:70
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
#define LOG_LEVEL_VERBOSE
Definition debug.h:63
#define MSG(l, fmt,...)
Definition debug.h:96
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
#define MAX_PATH_SIZE
Definition fs.h:48
#define snprintf_ch(str,...)
shortcut for snprintf(var, sizeof var...), var must be a char array
Definition macros.h:101
@ STR_LEN
"standard" string length placeholder
Definition macros.h:134
const char * ug_strerror(int errnum)
Definition misc.cpp:203
bool is_addr_linklocal(struct sockaddr *sa)
Definition net.c:79
bool get_local_addresses(struct sockaddr_storage *addrs, size_t *len, int ip_version)
Definition net.c:229
bool is_addr_loopback(struct sockaddr *sa)
Definition net.c:108
static const char * get_temp_dir(void)
#define PT_DynRTP_Type97
Definition rtp_types.h:79
#define PT_MPA
Definition rtp_types.h:65
#define PT_ITU_T_G711_PCMU
Definition rtp_types.h:63
#define PT_ITU_T_G711_PCMA
Definition rtp_types.h:64
#define PT_DynRTP_Type96
Definition rtp_types.h:78
#define PT_JPEG
Definition rtp_types.h:71
int get_audio_rtp_pt_rtpmap(audio_codec_t codec, int sample_rate, int channels, char rtpmapLine[STR_LEN])
Definition sdp.c:227
static struct sdp * new_sdp(bool ipv6, const char *receiver)
Definition sdp.c:140
static int new_stream(struct sdp *sdp)
Definition sdp.c:187
int sdp_add_audio(bool ipv6, int port, int sample_rate, int channels, audio_codec_t codec, address_callback_t addr_callback, void *addr_callback_udata)
Definition sdp.c:277
#define SDP_FILE
Definition sdp.c:86
static void start()
Definition sdp.c:202
bool autorun
Definition sdp.c:93
@ MAX_STREAMS
Definition sdp.c:90
@ DEFAULT_SDP_HTTP_PORT
Definition sdp.c:89
static void cleanup()
Definition sdp.c:195
static void clean_sdp(struct sdp *sdp)
Definition sdp.c:415
static char sdp_filename[MAX_PATH_SIZE]
Definition sdp.c:98
static bool want_sdp_audio
Definition sdp.c:95
void sdp_set_properties(const char *receiver, bool has_sdp_video, bool has_sdp_audio)
Definition sdp.c:576
int get_video_rtp_pt_rtpmap(codec_t codec, char rtpmapLine[STR_LEN])
Definition sdp.c:304
int sdp_set_options(const char *opts)
Definition sdp.c:585
static bool want_sdp_video
Definition sdp.c:96
static bool gen_sdp(void)
Definition sdp.c:375
#define MOD_NAME
Definition sdp.c:85
int sdp_add_video(bool ipv6, int port, codec_t codec, address_callback_t addr_callback, void *addr_callback_udata)
Definition sdp.c:335
void sdp_print_supported_codecs(void)
Definition sdp.c:652
static void strappend(char **dst, size_t *dst_alloc_len, const char *src)
Definition sdp.c:366
static char sdp_receiver[1024]
Definition sdp.c:97
static struct sdp * sdp_state
Definition sdp.c:100
codec_t get_video_codec_from_pt_rtpmap(int pt, const char *rtpmap_codec_name)
get UG video codec to given params
Definition sdp.c:622
int requested_http_port
Definition sdp.c:94
void(* address_callback_t)(void *udata, const char *address)
Definition sdp.h:59
const char * param
Definition settings.cpp:195
Definition hd-rum.c:27
Definition sdp.c:108
int video_index
Definition sdp.c:124
bool video_set
Definition sdp.c:110
void * audio_address_callback_udata
Definition sdp.c:127
char session_name[STR_LEN]
Definition sdp.c:118
struct stream_info stream[MAX_STREAMS]
Definition sdp.c:121
char times[STR_LEN]
Definition sdp.c:120
pthread_t http_server_thr
Definition sdp.c:114
char * sdp_dump
Definition sdp.c:125
void * video_address_callback_udata
Definition sdp.c:129
char connection[STR_LEN]
Definition sdp.c:119
int audio_index
Definition sdp.c:123
bool audio_set
Definition sdp.c:109
char version[STR_LEN]
Definition sdp.c:116
char origin[STR_LEN]
Definition sdp.c:117
void(* audio_address_callback)(void *udata, const char *address)
Definition sdp.c:126
int ip_version
Definition sdp.c:115
void(* video_address_callback)(void *udata, const char *address)
Definition sdp.c:128
int stream_count
Definition sdp.c:122
char media_info[STR_LEN]
Definition sdp.c:103
char rtpmap[STR_LEN]
Definition sdp.c:104
char fmtp[STR_LEN]
Definition sdp.c:105
This file contains some common data types.
@ kHz8
Definition types.h:147
codec_t
Definition types.h:65
@ VC_NONE
Definition types.h:67
@ JPEG
JPEG image, restart intervals may be used. Compatible with GPUJPEG.
Definition types.h:81
@ MJPG
JPEG image, without restart intervals.
Definition types.h:85
@ H264
H.264 frame.
Definition types.h:83