24 #define closesocket close
53 #include <sys/ioctl.h>
103 #define MAX_STREAMS 20
105 #define IOBUFFER_INIT_SIZE 8192
108 #define HTTP_REQUEST_TIMEOUT (15 * 1000)
109 #define RTSP_REQUEST_TIMEOUT (3600 * 24 * 1000)
111 #define SYNC_TIMEOUT (10 * 1000)
294 struct in_addr my_ip);
298 FFStream *stream,
const char *session_id,
301 int stream_index,
struct sockaddr_in *dest_addr,
330 lseek(fd, 8, SEEK_SET);
331 if (read(fd, buf, 8) != 8)
342 buf[i] = (pos >> (56 - i * 8)) & 0xff;
343 lseek(fd, 8, SEEK_SET);
344 if (write(fd, buf, 8) != 8)
359 static int resolve_host(
struct in_addr *sin_addr,
const char *hostname)
372 for (cur = ai; cur; cur = cur->
ai_next) {
374 *sin_addr = ((
struct sockaddr_in *)cur->
ai_addr)->sin_addr;
383 hp = gethostbyname(hostname);
386 memcpy(sin_addr, hp->h_addr_list[0],
sizeof(
struct in_addr));
400 p = buf2 + strlen(p) - 1;
408 static int print_prefix = 1;
415 print_prefix = strstr(fmt,
"\n") !=
NULL;
422 __attribute__ ((format (printf, 1, 2)))
427 va_start(vargs, fmt);
434 static int print_prefix = 1;
438 if (print_prefix && avc)
440 print_prefix = strstr(fmt,
"\n") !=
NULL;
449 http_log(
"%s - - [%s] \"%s %s\" %d %"PRId64
"\n",
482 for (; feed; feed = feed->
next) {
489 http_log(
"Unable to create children\n");
500 slash = strrchr(pathname,
'/');
505 strcpy(slash,
"avconv");
513 for (i = 3; i < 256; i++)
517 if (!freopen(
"/dev/null",
"r", stdin))
518 http_log(
"failed to redirect STDIN to /dev/null\n;");
519 if (!freopen(
"/dev/null",
"w", stdout))
520 http_log(
"failed to redirect STDOUT to /dev/null\n;");
521 if (!freopen(
"/dev/null",
"w", stderr))
522 http_log(
"failed to redirect STDERR to /dev/null\n;");
525 signal(SIGPIPE, SIG_DFL);
540 server_fd = socket(AF_INET,SOCK_STREAM,0);
547 setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp,
sizeof(tmp));
549 my_addr->sin_family = AF_INET;
550 if (bind (server_fd, (
struct sockaddr *) my_addr,
sizeof (*my_addr)) < 0) {
552 snprintf(bindmsg,
sizeof(bindmsg),
"bind(port %d)", ntohs(my_addr->sin_port));
558 if (listen (server_fd, 5) < 0) {
574 struct sockaddr_in dest_addr;
575 int default_port, stream_index;
578 for(stream = first_stream; stream !=
NULL; stream = stream->
next) {
581 snprintf(session_id,
sizeof(session_id),
"%08x%08x",
590 dest_addr.sin_family = AF_INET;
600 http_log(
"Could not open input stream for stream '%s'\n",
606 for(stream_index = 0; stream_index < stream->
nb_streams;
611 http_log(
"Could not open output stream '%s/streamid=%d'\n",
626 int server_fd = 0, rtsp_server_fd = 0;
627 int ret, delay, delay1;
628 struct pollfd *poll_table, *poll_entry;
644 if (rtsp_server_fd < 0)
648 if (!rtsp_server_fd && !server_fd) {
649 http_log(
"HTTP and RTSP disabled.\n");
660 poll_entry = poll_table;
662 poll_entry->fd = server_fd;
663 poll_entry->events = POLLIN;
666 if (rtsp_server_fd) {
667 poll_entry->fd = rtsp_server_fd;
668 poll_entry->events = POLLIN;
684 poll_entry->events = POLLOUT;
694 poll_entry->events = POLLOUT;
712 poll_entry->events = POLLIN;
725 ret = poll(poll_table, poll_entry - poll_table, delay);
739 for(c = first_http_ctx; c !=
NULL; c = c_next) {
748 poll_entry = poll_table;
751 if (poll_entry->revents & POLLIN)
755 if (rtsp_server_fd) {
757 if (poll_entry->revents & POLLIN)
781 int len = snprintf(buffer,
sizeof(buffer),
782 "HTTP/1.0 503 Server too busy\r\n"
783 "Content-type: text/html\r\n"
785 "<html><head><title>Too busy</title></head><body>\r\n"
786 "<p>The server is too busy to serve your request at this time.</p>\r\n"
787 "<p>The number of current connections is %d, and this exceeds the limit of %d.</p>\r\n"
788 "</body></html>\r\n",
790 send(fd, buffer, len, 0);
796 struct sockaddr_in from_addr;
801 len =
sizeof(from_addr);
802 fd = accept(server_fd, (
struct sockaddr *)&from_addr,
805 http_log(
"error during accept %s\n", strerror(errno));
854 while ((*cp) !=
NULL) {
863 for(c1 = first_http_ctx; c1 !=
NULL; c1 = c1->
next) {
886 for(i=0;i<nb_streams;i++) {
941 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
954 }
else if (len == 0) {
961 if ((ptr >= c->
buffer + 2 && !memcmp(ptr-2,
"\n\n", 2)) ||
962 (ptr >= c->
buffer + 4 && !memcmp(ptr-4,
"\r\n\r\n", 4))) {
974 }
else goto read_loop;
979 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1017 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1032 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1041 if (c->
poll_entry->revents & (POLLIN | POLLERR | POLLHUP))
1048 if (c->
poll_entry->revents & (POLLERR | POLLHUP)) {
1074 if (c->
poll_entry->revents & (POLLERR | POLLHUP)) {
1112 for (p = request; *p && *p !=
'\r' && *p !=
'\n'; ) {
1114 const char *q = p + 7;
1116 while (*q && *q !=
'\n' && isspace(*q))
1125 memset(rates, 0xff, ratelen);
1128 while (*q && *q !=
'\n' && *q !=
':')
1131 if (sscanf(q,
":%d:%d", &stream_no, &rate_no) != 2)
1135 if (stream_no < ratelen && stream_no >= 0)
1136 rates[stream_no] = rate_no;
1138 while (*q && *q !=
'\n' && !isspace(*q))
1145 p = strchr(p,
'\n');
1158 int best_bitrate = 100000000;
1176 if (feed_codec->
bit_rate <= bit_rate) {
1177 if (best_bitrate > bit_rate || feed_codec->
bit_rate > best_bitrate) {
1178 best_bitrate = feed_codec->
bit_rate;
1182 if (feed_codec->
bit_rate < best_bitrate) {
1183 best_bitrate = feed_codec->
bit_rate;
1196 int action_required = 0;
1224 action_required = 1;
1227 return action_required;
1236 while (*p ==
' ' || *p ==
'\t')
1241 static void get_word(
char *buf,
int buf_size,
const char **pp)
1249 while (!isspace(*p) && *p !=
'\0') {
1250 if ((q - buf) < buf_size - 1)
1259 static void get_arg(
char *buf,
int buf_size,
const char **pp)
1266 while (isspace(*p)) p++;
1269 if (*p ==
'\"' || *p ==
'\'')
1281 if ((q - buf) < buf_size - 1)
1286 if (quote && *p == quote)
1292 const char *p,
const char *filename,
int line_num)
1298 get_arg(arg,
sizeof(arg), &p);
1304 fprintf(stderr,
"%s:%d: ACL action '%s' is not ALLOW or DENY\n",
1305 filename, line_num, arg);
1309 get_arg(arg,
sizeof(arg), &p);
1312 fprintf(stderr,
"%s:%d: ACL refers to invalid host or ip address '%s'\n",
1313 filename, line_num, arg);
1318 get_arg(arg,
sizeof(arg), &p);
1322 fprintf(stderr,
"%s:%d: ACL refers to invalid host or ip address '%s'\n",
1323 filename, line_num, arg);
1336 naclp = &stream->
acl;
1342 fprintf(stderr,
"%s:%d: ACL found not in <stream> or <feed>\n",
1343 filename, line_num);
1349 naclp = &(*naclp)->
next;
1376 if (fgets(line,
sizeof(line), f) ==
NULL)
1382 if (*p ==
'\0' || *p ==
'#')
1384 get_arg(cmd,
sizeof(cmd), &p);
1410 struct in_addr *src = &c->
from_addr.sin_addr;
1411 unsigned long src_addr = src->s_addr;
1413 for (acl = in_acl; acl; acl = acl->
next) {
1414 if (src_addr >= acl->
first.s_addr && src_addr <= acl->last.s_addr)
1416 last_action = acl->
action;
1420 return (last_action ==
IP_DENY) ? 1 : 0;
1454 p = strrchr(file1,
'.');
1457 for(stream = first_stream; stream !=
NULL; stream = stream->
next) {
1459 p = strrchr(file2,
'.');
1462 if (!strcmp(file1, file2)) {
1485 char info[1024], filename[1024];
1489 const char *mime_type;
1493 const char *useragent = 0;
1499 if (!strcmp(cmd,
"GET"))
1501 else if (!strcmp(cmd,
"POST"))
1509 get_word(protocol,
sizeof(protocol), (
const char **)&p);
1510 if (strcmp(protocol,
"HTTP/1.0") && strcmp(protocol,
"HTTP/1.1"))
1516 http_log(
"%s - - New connection: %s %s\n", inet_ntoa(c->
from_addr.sin_addr), cmd, url);
1519 p1 = strchr(url,
'?');
1526 av_strlcpy(filename, url + ((*url ==
'/') ? 1 : 0),
sizeof(filename)-1);
1528 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1531 if (*useragent && *useragent !=
'\n' && isspace(*useragent))
1535 p = strchr(p,
'\n');
1545 filename[strlen(filename)-1] =
'f';
1552 strcpy(filename + strlen(filename)-2,
"m");
1562 if (!strlen(filename))
1563 av_strlcpy(filename,
"index.html",
sizeof(filename) - 1);
1566 while (stream !=
NULL) {
1569 stream = stream->
next;
1571 if (stream ==
NULL) {
1572 snprintf(msg,
sizeof(msg),
"File '%s' not found", url);
1573 http_log(
"File '%s' not found\n", url);
1585 "HTTP/1.0 301 Moved\r\n"
1587 "Content-type: text/html\r\n"
1589 "<html><head><title>Moved</title></head><body>\r\n"
1590 "You should be <a href=\"%s\">redirected</a>.\r\n"
1614 snprintf(msg,
sizeof(msg),
"This feed is already being received.");
1623 "HTTP/1.0 503 Server too busy\r\n"
1624 "Content-type: text/html\r\n"
1626 "<html><head><title>Too busy</title></head><body>\r\n"
1627 "<p>The server is too busy to serve your request at this time.</p>\r\n"
1628 "<p>The bandwidth being served (including your stream) is %"PRIu64
"kbit/sec, "
1629 "and this exceeds the limit of %"PRIu64
"kbit/sec.</p>\r\n"
1639 const char *hostinfo = 0;
1641 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1646 p = strchr(p,
'\n');
1657 while (isspace(*hostinfo))
1660 eoh = strchr(hostinfo,
'\n');
1662 if (eoh[-1] ==
'\r')
1665 if (eoh - hostinfo <
sizeof(hostbuf) - 1) {
1666 memcpy(hostbuf, hostinfo, eoh - hostinfo);
1667 hostbuf[eoh - hostinfo] = 0;
1671 switch(redir_type) {
1674 "HTTP/1.0 200 ASX Follows\r\n"
1675 "Content-type: video/x-ms-asf\r\n"
1677 "<ASX Version=\"3\">\r\n"
1679 "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n"
1680 "</ASX>\r\n", hostbuf, filename, info);
1684 "HTTP/1.0 200 RAM Follows\r\n"
1685 "Content-type: audio/x-pn-realaudio\r\n"
1687 "# Autogenerated by avserver\r\n"
1688 "http://%s/%s%s\r\n", hostbuf, filename, info);
1692 "HTTP/1.0 200 ASF Redirect follows\r\n"
1693 "Content-type: video/x-ms-asf\r\n"
1696 "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info);
1700 char hostname[256], *p;
1702 av_strlcpy(hostname, hostbuf,
sizeof(hostname));
1703 p = strrchr(hostname,
':');
1707 "HTTP/1.0 200 RTSP Redirect follows\r\n"
1709 "Content-type: application/x-rtsp\r\n"
1711 "rtsp://%s:%d/%s\r\n", hostname, ntohs(
my_rtsp_addr.sin_port), filename);
1719 struct sockaddr_in my_addr;
1722 "HTTP/1.0 200 OK\r\n"
1723 "Content-type: application/sdp\r\n"
1726 len =
sizeof(my_addr);
1727 getsockname(c->
fd, (
struct sockaddr *)&my_addr, &len);
1733 if (sdp_data_size > 0) {
1734 memcpy(q, sdp_data, sdp_data_size);
1755 snprintf(msg,
sizeof(msg),
"ASX/RAM file not handled");
1768 const char *logline = 0;
1771 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1777 client_id = strtol(p + 18, 0, 10);
1778 p = strchr(p,
'\n');
1786 char *eol = strchr(logline,
'\n');
1791 if (eol[-1] ==
'\r')
1793 http_log(
"%.*s\n", (
int) (eol - logline), logline);
1806 for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->
next) {
1815 snprintf(msg,
sizeof(msg),
"POST command not handled");
1820 snprintf(msg,
sizeof(msg),
"could not open feed");
1838 snprintf(msg,
sizeof(msg),
"Input stream corresponding to '%s' not found", url);
1844 q += snprintf(q, q - (
char *) c->
buffer + c->
buffer_size,
"HTTP/1.0 200 OK\r\n");
1847 mime_type =
"application/x-octet-stream";
1848 q += snprintf(q, q - (
char *) c->
buffer + c->
buffer_size,
"Pragma: no-cache\r\n");
1856 q += snprintf(q, q - (
char *) c->
buffer + c->
buffer_size,
"Server: Cougar 4.1.0.3923\r\nCache-Control: no-cache\r\nPragma: client-id=%d\r\nPragma: features=\"broadcast\"\r\n", c->
wmp_client_id);
1858 q += snprintf(q, q - (
char *) c->
buffer + c->
buffer_size,
"Content-Type: %s\r\n", mime_type);
1871 "HTTP/1.0 404 Not Found\r\n"
1872 "Content-type: text/html\r\n"
1875 "<head><title>404 Not Found</title></head>\n"
1893 static const char suffix[] =
" kMGTP";
1896 for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++);
1918 avio_printf(pb,
"Content-type: %s\r\n",
"text/html");
1929 avio_printf(pb,
"<table cellspacing=0 cellpadding=4>\n");
1930 avio_printf(pb,
"<tr><th valign=top>Path<th align=left>Served<br>Conns<th><br>bytes<th valign=top>Format<th>Bit rate<br>kbits/s<th align=left>Video<br>kbits/s<th><br>Codec<th align=left>Audio<br>kbits/s<th><br>Codec<th align=left valign=top>Feed\n");
1932 while (stream !=
NULL) {
1933 char sfilename[1024];
1936 if (stream->
feed != stream) {
1938 eosf = sfilename + strlen(sfilename);
1939 if (eosf - sfilename >= 4) {
1940 if (strcmp(eosf - 4,
".asf") == 0)
1941 strcpy(eosf - 4,
".asx");
1942 else if (strcmp(eosf - 3,
".rm") == 0)
1943 strcpy(eosf - 3,
".ram");
1944 else if (stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
1948 eosf = strrchr(sfilename,
'.');
1950 eosf = sfilename + strlen(sfilename);
1952 strcpy(eosf,
".sdp");
1954 strcpy(eosf,
".rtsp");
1958 avio_printf(pb,
"<tr><td><a href=\"/%s\">%s</a> ",
1960 avio_printf(pb,
"<td align=right> %d <td align=right> ",
1965 int audio_bit_rate = 0;
1966 int video_bit_rate = 0;
1967 const char *audio_codec_name =
"";
1968 const char *video_codec_name =
"";
1969 const char *audio_codec_name_extra =
"";
1970 const char *video_codec_name_extra =
"";
1979 if (*audio_codec_name)
1980 audio_codec_name_extra =
"...";
1981 audio_codec_name = codec->
name;
1987 if (*video_codec_name)
1988 video_codec_name_extra =
"...";
1989 video_codec_name = codec->
name;
1999 avio_printf(pb,
"<td align=center> %s <td align=right> %d <td align=right> %d <td> %s %s <td align=right> %d <td> %s %s",
2002 video_bit_rate / 1000, video_codec_name, video_codec_name_extra,
2003 audio_bit_rate / 1000, audio_codec_name, audio_codec_name_extra);
2012 avio_printf(pb,
"<td align=center> - <td align=right> - <td align=right> - <td><td align=right> - <td>\n");
2016 stream = stream->
next;
2021 while (stream !=
NULL) {
2022 if (stream->
feed == stream) {
2027 #if defined(linux) && !defined(CONFIG_NOCUTILS)
2033 snprintf(ps_cmd,
sizeof(ps_cmd),
2034 "ps -o \"%%cpu,cputime\" --no-headers %d",
2037 pid_stat = popen(ps_cmd,
"r");
2042 if (fscanf(pid_stat,
"%10s %64s", cpuperc,
2044 avio_printf(pb,
"Currently using %s%% of the cpu. Total time used %s.\n",
2054 avio_printf(pb,
"<table cellspacing=0 cellpadding=4><tr><th>Stream<th>type<th>kbits/s<th align=left>codec<th align=left>Parameters\n");
2059 const char *type =
"unknown";
2060 char parameters[64];
2071 snprintf(parameters,
sizeof(parameters),
"%dx%d, q=%d-%d, fps=%d", st->
codec->
width, st->
codec->
height,
2077 avio_printf(pb,
"<tr><td align=right>%d<td>%s<td align=right>%d<td>%s<td>%s\n",
2083 stream = stream->
next;
2089 avio_printf(pb,
"Number of connections: %d / %d<br>\n",
2092 avio_printf(pb,
"Bandwidth in use: %"PRIu64
"k / %"PRIu64
"k<br>\n",
2096 avio_printf(pb,
"<tr><th>#<th>File<th>IP<th>Proto<th>State<th>Target bits/sec<th>Actual bits/sec<th>Bytes transferred\n");
2099 while (c1 !=
NULL) {
2115 avio_printf(pb,
"<tr><td><b>%d</b><td>%s%s<td>%s<td>%s<td>%s<td align=right>",
2135 avio_printf(pb,
"<hr size=1 noshade>Generated at %s", p);
2159 int prebuffer = strtol(buf, 0, 10);
2160 stream_pos =
av_gettime() - prebuffer * (int64_t)1000000;
2172 if (input_filename[0] ==
'\0')
2177 http_log(
"could not open %s: %d\n", input_filename, ret);
2183 http_log(
"Could not find stream info '%s'\n", input_filename);
2217 int bytes_left, bytes_sent, frame_bytes;
2220 if (frame_bytes <= 0)
2224 bytes_sent = frame_bytes - bytes_left;
2282 http_log(
"Error writing output header\n");
2316 }
else if (ret ==
AVERROR(EAGAIN)) {
2393 int max_packet_size;
2415 http_log(
"Error writing frame to output\n");
2501 int interleaved_index,
size;
2517 interleaved_index++;
2520 header[1] = interleaved_index;
2521 header[2] = len >> 8;
2593 http_log(
"Error opening feeder file: %s\n", strerror(errno));
2603 http_log(
"Error truncating feed file: %s\n", strerror(errno));
2608 http_log(
"Error reading write index from feed file: %s\n", strerror(errno));
2615 lseek(fd, 0, SEEK_SET);
2628 int len, loop_run = 0;
2641 }
else if (len == 0) {
2651 }
else if (++loop_run > 10) {
2667 }
else if (len == 0)
2679 if (c->
buffer[0] !=
'f' ||
2681 http_log(
"Feed stream has become desynchronized -- disconnecting\n");
2694 http_log(
"Error writing to feed file: %s\n", strerror(errno));
2709 http_log(
"Error writing index to feed file: %s\n", strerror(errno));
2714 for(c1 = first_http_ctx; c1 !=
NULL; c1 = c1->
next) {
2748 http_log(
"Feed '%s' stream number does not match registered feed\n",
2770 for(c1 = first_http_ctx; c1 !=
NULL; c1 = c1->
next) {
2788 switch(error_number) {
2793 str =
"Method Not Allowed";
2796 str =
"Not Enough Bandwidth";
2799 str =
"Session Not Found";
2802 str =
"Method Not Valid in This State";
2805 str =
"Aggregate operation not allowed";
2808 str =
"Only aggregate operation allowed";
2811 str =
"Unsupported transport";
2814 str =
"Internal Server Error";
2817 str =
"Service Unavailable";
2820 str =
"RTSP Version not supported";
2823 str =
"Unknown Error";
2827 avio_printf(c->
pb,
"RTSP/1.0 %d %s\r\n", error_number, str);
2833 strftime(buf2,
sizeof(buf2),
"%a, %d %b %Y %H:%M:%S", tm);
2845 const char *p, *p1, *p2;
2858 get_word(protocol,
sizeof(protocol), &p);
2871 if (strcmp(protocol,
"RTSP/1.0") != 0) {
2878 while (*p !=
'\n' && *p !=
'\0')
2882 while (*p !=
'\0') {
2883 p1 = memchr(p,
'\n', (
char *)c->
buffer_ptr - p);
2887 if (p2 > p && p2[-1] ==
'\r')
2893 if (len >
sizeof(line) - 1)
2894 len =
sizeof(line) - 1;
2895 memcpy(line, p, len);
2902 c->
seq = header->seq;
2904 if (!strcmp(cmd,
"DESCRIBE"))
2906 else if (!strcmp(cmd,
"OPTIONS"))
2908 else if (!strcmp(cmd,
"SETUP"))
2910 else if (!strcmp(cmd,
"PLAY"))
2912 else if (!strcmp(cmd,
"PAUSE"))
2914 else if (!strcmp(cmd,
"TEARDOWN"))
2933 struct in_addr my_ip)
2944 stream->
title[0] ? stream->
title :
"No Title", 0);
2947 snprintf(avc->
filename, 1024,
"rtp://%s:%d?multicast=1?ttl=%d",
2951 snprintf(avc->
filename, 1024,
"rtp://0.0.0.0");
2957 if (avc->
nb_streams >= INT_MAX/
sizeof(*avs) ||
2974 return strlen(*pbuffer);
2982 avio_printf(c->
pb,
"Public: %s\r\n",
"OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
2994 struct sockaddr_in my_addr;
3002 for(stream = first_stream; stream !=
NULL; stream = stream->
next) {
3004 stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp") &&
3017 len =
sizeof(my_addr);
3018 getsockname(c->
fd, (
struct sockaddr *)&my_addr, &len);
3020 if (content_length < 0) {
3027 avio_printf(c->
pb,
"Content-Length: %d\r\n", content_length);
3037 if (session_id[0] ==
'\0')
3040 for(c = first_http_ctx; c !=
NULL; c = c->
next) {
3064 int stream_index, rtp_port, rtcp_port;
3070 struct sockaddr_in dest_addr;
3080 for(stream = first_stream; stream !=
NULL; stream = stream->
next) {
3082 stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
3084 if (!strcmp(path, stream->
filename)) {
3093 for(stream_index = 0; stream_index < stream->
nb_streams;
3095 snprintf(buf,
sizeof(buf),
"%s/streamid=%d",
3097 if (!strcmp(path, buf))
3141 if (rtp_c->
stream != stream) {
3147 if (rtp_c->
rtp_ctx[stream_index]) {
3161 setup.transport_option[0] =
'\0';
3181 "client_port=%d-%d;server_port=%d-%d",
3183 rtp_port, rtcp_port);
3186 avio_printf(c->
pb,
"Transport: RTP/AVP/TCP;interleaved=%d-%d",
3187 stream_index * 2, stream_index * 2 + 1);
3192 if (setup.transport_option[0] !=
'\0')
3204 const char *session_id)
3223 snprintf(buf,
sizeof(buf),
"%s/streamid=%d",
3225 if(!strncmp(path, buf,
sizeof(buf))) {
3231 if (len > 0 && path[len - 1] ==
'/' &&
3313 FFStream *stream,
const char *session_id,
3317 const char *proto_str;
3346 proto_str =
"MCAST";
3379 int stream_index,
struct sockaddr_in *dest_addr,
3387 int max_packet_size;
3414 ipaddr = inet_ntoa(dest_addr->sin_addr);
3428 "rtp://%s:%d?multicast=1&ttl=%d",
3429 ipaddr, ntohs(dest_addr->sin_port), ttl);
3432 "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
3449 http_log(
"%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
3450 ipaddr, ntohs(dest_addr->sin_port),
3468 c->
rtp_ctx[stream_index] = ctx;
3549 while (*ps !=
NULL) {
3560 int mpeg4_count, i,
size;
3578 printf(
"MPEG4 without extra data: trying to find header in %s\n", infile->
filename);
3579 while (mpeg4_count > 0) {
3589 while (p < pkt.
data + pkt.
size - 4) {
3591 if (p[0] == 0x00 && p[1] == 0x00 &&
3592 p[2] == 0x01 && p[3] == 0xb6) {
3593 size = p - pkt.
data;
3615 for(stream = first_stream; stream !=
NULL; stream = stream_next) {
3617 stream_next = stream->
next;
3623 if (stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
3639 http_log(
"Could not find codec parameters from '%s'\n",
3662 for(stream = first_stream; stream !=
NULL; stream = stream->
next) {
3663 feed = stream->
feed;
3677 for(feed = first_feed; feed !=
NULL; feed = feed->
next_feed) {
3696 http_log(
"Index & Id do not match for stream %d (%s)\n",
3704 #define CHECK_CODEC(x) (ccf->x != ccs->x)
3707 http_log(
"Codecs do not match for stream %d\n", i);
3710 http_log(
"Codec bitrates do not match for stream %d\n", i);
3717 http_log(
"Codec width, height and framerate do not match for stream %d\n", i);
3724 http_log(
"Codec sample_rate, channels, frame_size do not match for stream %d\n", i);
3736 http_log(
"Deleting feed file '%s' as stream counts differ (%d != %d)\n",
3741 http_log(
"Deleting feed file '%s' as it appears to be corrupt\n",
3746 http_log(
"Unable to delete feed file '%s' as it is marked readonly\n",
3757 http_log(
"Unable to create feed file '%s' as it is marked readonly\n",
3764 http_log(
"Could not open output feed file '%s'\n",
3768 s->oformat = feed->
fmt;
3772 http_log(
"Container doesn't supports the required parameters\n");
3782 http_log(
"Could not open output feed file '%s'\n",
3788 feed->
feed_size = lseek(fd, 0, SEEK_END);
3804 for(stream = first_stream; stream !=
NULL; stream = stream->
next) {
3817 stream->
bandwidth = (bandwidth + 999) / 1000;
3869 av->
rc_eq =
"tex^qComp";
3920 static void load_module(
const char *filename)
3924 dll = dlopen(filename, RTLD_NOW);
3926 fprintf(stderr,
"Could not load module '%s' - %s\n",
3927 filename, dlerror());
3931 init_func = dlsym(dll,
"avserver_module_init");
3934 "%s: init function 'avserver_module_init()' not found\n",
3958 char filename[1000], tmp[1000], tmp2[1000],
line[1000];
3964 fprintf(stderr,
"File for preset '%s' not found\n", arg);
3969 int e= fscanf(f,
"%999[^\n]\n", line) - 1;
3970 if(line[0] ==
'#' && !e)
3972 e|= sscanf(line,
"%999[^=]=%999[^\n]\n", tmp, tmp2) - 2;
3974 fprintf(stderr,
"%s: Invalid syntax: '%s'\n", filename, line);
3978 if(!strcmp(tmp,
"acodec")){
3980 }
else if(!strcmp(tmp,
"vcodec")){
3982 }
else if(!strcmp(tmp,
"scodec")){
3985 fprintf(stderr,
"%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", filename, line, tmp, tmp2);
3997 const char *mime_type)
4003 char stream_format_name[64];
4005 snprintf(stream_format_name,
sizeof(stream_format_name),
"%s_stream", fmt->
name);
4019 fprintf(stderr,
"%s:%d: ", filename, line_num);
4020 vfprintf(stderr, fmt, vl);
4033 int val, errors, line_num;
4034 FFStream **last_stream, *stream, *redirect;
4039 f = fopen(filename,
"r");
4047 first_stream =
NULL;
4057 #define ERROR(...) report_config_error(filename, line_num, &errors, __VA_ARGS__)
4059 if (fgets(line,
sizeof(line), f) ==
NULL)
4065 if (*p ==
'\0' || *p ==
'#')
4068 get_arg(cmd,
sizeof(cmd), &p);
4071 get_arg(arg,
sizeof(arg), &p);
4073 if (val < 1 || val > 65536) {
4074 ERROR(
"Invalid_port: %s\n", arg);
4078 get_arg(arg,
sizeof(arg), &p);
4080 ERROR(
"%s:%d: Invalid host/IP address: %s\n", arg);
4083 get_arg(arg,
sizeof(arg), &p);
4085 if (val < 1 || val > 65536) {
4086 ERROR(
"%s:%d: Invalid port: %s\n", arg);
4090 get_arg(arg,
sizeof(arg), &p);
4092 ERROR(
"Invalid host/IP address: %s\n", arg);
4095 get_arg(arg,
sizeof(arg), &p);
4097 if (val < 1 || val > 65536) {
4098 ERROR(
"Invalid MaxHTTPConnections: %s\n", arg);
4102 get_arg(arg,
sizeof(arg), &p);
4105 ERROR(
"Invalid MaxClients: %s\n", arg);
4111 get_arg(arg,
sizeof(arg), &p);
4113 if (llval < 10 || llval > 10000000) {
4114 ERROR(
"Invalid MaxBandwidth: %s\n", arg);
4124 if (stream || feed) {
4125 ERROR(
"Already in a tag\n");
4133 for (s = first_feed; s; s = s->
next) {
4148 *last_stream = feed;
4149 last_stream = &feed->
next;
4160 for (i = 0; i < 62; i++) {
4161 get_arg(arg,
sizeof(arg), &p);
4172 (
my_http_addr.sin_addr.s_addr == INADDR_ANY) ?
"127.0.0.1" :
4180 }
else if (stream) {
4190 get_arg(arg,
sizeof(arg), &p);
4198 get_arg(arg,
sizeof(arg), &p);
4201 switch(toupper(*p1)) {
4206 fsize *= 1024 * 1024;
4209 fsize *= 1024 * 1024 * 1024;
4219 ERROR(
"No corresponding <Feed> for </Feed>\n");
4226 if (stream || feed) {
4227 ERROR(
"Already in a tag\n");
4232 q = strrchr(stream->
filename,
'>');
4236 for (s = first_stream; s; s = s->
next) {
4252 *last_stream = stream;
4253 last_stream = &stream->
next;
4256 get_arg(arg,
sizeof(arg), &p);
4261 while (sfeed !=
NULL) {
4267 ERROR(
"feed '%s' not defined\n", arg);
4269 stream->
feed = sfeed;
4272 get_arg(arg,
sizeof(arg), &p);
4274 if (!strcmp(arg,
"status")) {
4280 if (!strcmp(arg,
"jpeg"))
4281 strcpy(arg,
"mjpeg");
4284 ERROR(
"Unknown Format: %s\n", arg);
4293 get_arg(arg,
sizeof(arg), &p);
4296 if (!stream->
ifmt) {
4297 ERROR(
"Unknown input format: %s\n", arg);
4304 ERROR(
"FaviconURL only permitted for status streams\n");
4319 get_arg(arg,
sizeof(arg), &p);
4326 get_arg(arg,
sizeof(arg), &p);
4329 ERROR(
"Unknown AudioCodec: %s\n", arg);
4332 get_arg(arg,
sizeof(arg), &p);
4335 ERROR(
"Unknown VideoCodec: %s\n", arg);
4338 get_arg(arg,
sizeof(arg), &p);
4340 stream->
max_time = atof(arg) * 1000;
4342 get_arg(arg,
sizeof(arg), &p);
4346 get_arg(arg,
sizeof(arg), &p);
4350 get_arg(arg,
sizeof(arg), &p);
4354 get_arg(arg,
sizeof(arg), &p);
4360 int minrate, maxrate;
4362 get_arg(arg,
sizeof(arg), &p);
4364 if (sscanf(arg,
"%d-%d", &minrate, &maxrate) == 2) {
4368 ERROR(
"Incorrect format for VideoBitRateRange -- should be <min>-<max>: %s\n", arg);
4373 get_arg(arg,
sizeof(arg), &p);
4374 video_enc.
debug = strtol(arg,0,0);
4378 get_arg(arg,
sizeof(arg), &p);
4383 get_arg(arg,
sizeof(arg), &p);
4388 get_arg(arg,
sizeof(arg), &p);
4392 get_arg(arg,
sizeof(arg), &p);
4394 video_enc.
bit_rate = atoi(arg) * 1000;
4397 get_arg(arg,
sizeof(arg), &p);
4400 if ((video_enc.
width % 16) != 0 ||
4401 (video_enc.
height % 16) != 0) {
4402 ERROR(
"Image size must be a multiple of 16\n");
4406 get_arg(arg,
sizeof(arg), &p);
4410 ERROR(
"Incorrect frame rate: %s\n", arg);
4417 get_arg(arg,
sizeof(arg), &p);
4436 get_arg(arg,
sizeof(arg), &p);
4437 get_arg(arg2,
sizeof(arg2), &p);
4446 ERROR(
"AVOption error: %s %s\n", arg, arg2);
4452 get_arg(arg,
sizeof(arg), &p);
4463 ERROR(
"AVPreset error: %s\n", arg);
4466 get_arg(arg,
sizeof(arg), &p);
4467 if ((strlen(arg) == 4) && stream)
4479 get_arg(arg,
sizeof(arg), &p);
4485 get_arg(arg,
sizeof(arg), &p);
4489 ERROR(
"VideoQDiff out of range\n");
4493 get_arg(arg,
sizeof(arg), &p);
4495 video_enc.
qmax = atoi(arg);
4496 if (video_enc.
qmax < 1 || video_enc.
qmax > 31) {
4497 ERROR(
"VideoQMax out of range\n");
4501 get_arg(arg,
sizeof(arg), &p);
4503 video_enc.
qmin = atoi(arg);
4504 if (video_enc.
qmin < 1 || video_enc.
qmin > 31) {
4505 ERROR(
"VideoQMin out of range\n");
4509 get_arg(arg,
sizeof(arg), &p);
4511 video_enc.luma_elim_threshold = atoi(arg);
4513 get_arg(arg,
sizeof(arg), &p);
4515 video_enc.chroma_elim_threshold = atoi(arg);
4517 get_arg(arg,
sizeof(arg), &p);
4521 get_arg(arg,
sizeof(arg), &p);
4535 get_arg(arg,
sizeof(arg), &p);
4541 get_arg(arg,
sizeof(arg), &p);
4544 ERROR(
"Invalid host/IP address: %s\n", arg);
4550 get_arg(arg,
sizeof(arg), &p);
4554 get_arg(arg,
sizeof(arg), &p);
4562 ERROR(
"No corresponding <Stream> for </Stream>\n");
4564 if (stream->
feed && stream->
fmt && strcmp(stream->
fmt->
name,
"ffm") != 0) {
4581 if (stream || feed || redirect) {
4582 ERROR(
"Already in a tag\n");
4585 *last_stream = redirect;
4586 last_stream = &redirect->
next;
4589 q = strrchr(redirect->
filename,
'>');
4599 ERROR(
"No corresponding <Redirect> for </Redirect>\n");
4602 ERROR(
"No URL found for <Redirect>\n");
4607 get_arg(arg,
sizeof(arg), &p);
4611 ERROR(
"Module support not compiled into this version: '%s'\n", arg);
4614 ERROR(
"Incorrect keyword: '%s'\n", cmd);
4631 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
4634 for (feed = first_feed; feed; feed = feed->
next) {
4635 if (feed->
pid == pid) {
4639 fprintf(stderr,
"%s: Pid %d exited with status %d after %d seconds\n", feed->
filename, pid, status, uptime);
4659 printf(
"usage: avserver [options]\n"
4660 "Hyper fast multi format Audio/Video streaming server\n");
4668 {
"d", 0, {(
void*)
opt_debug},
"enable debug mode" },
4675 struct sigaction sigact = { { 0 } };
4687 unsetenv(
"http_proxy");
4692 sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
4693 sigaction(SIGCHLD, &sigact, 0);
4696 fprintf(stderr,
"Incorrect config file - exiting.\n");
4716 signal(SIGPIPE, SIG_IGN);
4719 http_log(
"Could not start server\n");