24 #define closesocket close
54 #include <sys/ioctl.h>
101 #define MAX_STREAMS 20
103 #define IOBUFFER_INIT_SIZE 8192
106 #define HTTP_REQUEST_TIMEOUT (15 * 1000)
107 #define RTSP_REQUEST_TIMEOUT (3600 * 24 * 1000)
109 #define SYNC_TIMEOUT (10 * 1000)
292 struct in_addr my_ip);
296 FFStream *stream,
const char *session_id,
299 int stream_index,
struct sockaddr_in *dest_addr,
328 lseek(fd, 8, SEEK_SET);
329 if (read(fd, buf, 8) != 8)
340 buf[i] = (pos >> (56 - i * 8)) & 0xff;
341 lseek(fd, 8, SEEK_SET);
342 if (write(fd, buf, 8) != 8)
357 static int resolve_host(
struct in_addr *sin_addr,
const char *hostname)
370 for (cur = ai; cur; cur = cur->
ai_next) {
372 *sin_addr = ((
struct sockaddr_in *)cur->
ai_addr)->sin_addr;
381 hp = gethostbyname(hostname);
384 memcpy(sin_addr, hp->h_addr_list[0],
sizeof(
struct in_addr));
398 p = buf2 + strlen(p) - 1;
406 static int print_prefix = 1;
413 print_prefix = strstr(fmt,
"\n") !=
NULL;
420 __attribute__ ((format (printf, 1, 2)))
425 va_start(vargs, fmt);
432 static int print_prefix = 1;
436 if (print_prefix && avc)
438 print_prefix = strstr(fmt,
"\n") !=
NULL;
447 http_log(
"%s - - [%s] \"%s %s\" %d %"PRId64
"\n",
480 for (; feed; feed = feed->
next) {
487 http_log(
"Unable to create children\n");
498 slash = strrchr(pathname,
'/');
503 strcpy(slash,
"avconv");
511 for (i = 3; i < 256; i++)
515 if (!freopen(
"/dev/null",
"r", stdin))
516 http_log(
"failed to redirect STDIN to /dev/null\n;");
517 if (!freopen(
"/dev/null",
"w", stdout))
518 http_log(
"failed to redirect STDOUT to /dev/null\n;");
519 if (!freopen(
"/dev/null",
"w", stderr))
520 http_log(
"failed to redirect STDERR to /dev/null\n;");
523 signal(SIGPIPE, SIG_DFL);
538 server_fd = socket(AF_INET,SOCK_STREAM,0);
545 setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp,
sizeof(tmp));
547 my_addr->sin_family = AF_INET;
548 if (bind (server_fd, (
struct sockaddr *) my_addr,
sizeof (*my_addr)) < 0) {
550 snprintf(bindmsg,
sizeof(bindmsg),
"bind(port %d)", ntohs(my_addr->sin_port));
556 if (listen (server_fd, 5) < 0) {
572 struct sockaddr_in dest_addr;
573 int default_port, stream_index;
576 for(stream = first_stream; stream !=
NULL; stream = stream->
next) {
579 snprintf(session_id,
sizeof(session_id),
"%08x%08x",
588 dest_addr.sin_family = AF_INET;
598 http_log(
"Could not open input stream for stream '%s'\n",
604 for(stream_index = 0; stream_index < stream->
nb_streams;
609 http_log(
"Could not open output stream '%s/streamid=%d'\n",
624 int server_fd = 0, rtsp_server_fd = 0;
625 int ret, delay, delay1;
626 struct pollfd *poll_table, *poll_entry;
642 if (rtsp_server_fd < 0)
646 if (!rtsp_server_fd && !server_fd) {
647 http_log(
"HTTP and RTSP disabled.\n");
658 poll_entry = poll_table;
660 poll_entry->fd = server_fd;
661 poll_entry->events = POLLIN;
664 if (rtsp_server_fd) {
665 poll_entry->fd = rtsp_server_fd;
666 poll_entry->events = POLLIN;
682 poll_entry->events = POLLOUT;
692 poll_entry->events = POLLOUT;
710 poll_entry->events = POLLIN;
723 ret = poll(poll_table, poll_entry - poll_table, delay);
737 for(c = first_http_ctx; c !=
NULL; c = c_next) {
746 poll_entry = poll_table;
749 if (poll_entry->revents & POLLIN)
753 if (rtsp_server_fd) {
755 if (poll_entry->revents & POLLIN)
779 int len = snprintf(buffer,
sizeof(buffer),
780 "HTTP/1.0 503 Server too busy\r\n"
781 "Content-type: text/html\r\n"
783 "<html><head><title>Too busy</title></head><body>\r\n"
784 "<p>The server is too busy to serve your request at this time.</p>\r\n"
785 "<p>The number of current connections is %d, and this exceeds the limit of %d.</p>\r\n"
786 "</body></html>\r\n",
788 send(fd, buffer, len, 0);
794 struct sockaddr_in from_addr;
799 len =
sizeof(from_addr);
800 fd = accept(server_fd, (
struct sockaddr *)&from_addr,
803 http_log(
"error during accept %s\n", strerror(errno));
852 while ((*cp) !=
NULL) {
861 for(c1 = first_http_ctx; c1 !=
NULL; c1 = c1->
next) {
884 for(i=0;i<nb_streams;i++) {
939 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
952 }
else if (len == 0) {
959 if ((ptr >= c->
buffer + 2 && !memcmp(ptr-2,
"\n\n", 2)) ||
960 (ptr >= c->
buffer + 4 && !memcmp(ptr-4,
"\r\n\r\n", 4))) {
972 }
else goto read_loop;
977 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1015 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1030 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1039 if (c->
poll_entry->revents & (POLLIN | POLLERR | POLLHUP))
1046 if (c->
poll_entry->revents & (POLLERR | POLLHUP)) {
1072 if (c->
poll_entry->revents & (POLLERR | POLLHUP)) {
1110 for (p = request; *p && *p !=
'\r' && *p !=
'\n'; ) {
1112 const char *q = p + 7;
1123 memset(rates, 0xff, ratelen);
1126 while (*q && *q !=
'\n' && *q !=
':')
1129 if (sscanf(q,
":%d:%d", &stream_no, &rate_no) != 2)
1133 if (stream_no < ratelen && stream_no >= 0)
1134 rates[stream_no] = rate_no;
1143 p = strchr(p,
'\n');
1156 int best_bitrate = 100000000;
1174 if (feed_codec->
bit_rate <= bit_rate) {
1175 if (best_bitrate > bit_rate || feed_codec->
bit_rate > best_bitrate) {
1176 best_bitrate = feed_codec->
bit_rate;
1180 if (feed_codec->
bit_rate < best_bitrate) {
1181 best_bitrate = feed_codec->
bit_rate;
1194 int action_required = 0;
1222 action_required = 1;
1225 return action_required;
1234 while (*p ==
' ' || *p ==
'\t')
1239 static void get_word(
char *buf,
int buf_size,
const char **pp)
1248 if ((q - buf) < buf_size - 1)
1257 static void get_arg(
char *buf,
int buf_size,
const char **pp)
1267 if (*p ==
'\"' || *p ==
'\'')
1279 if ((q - buf) < buf_size - 1)
1284 if (quote && *p == quote)
1290 const char *p,
const char *filename,
int line_num)
1296 get_arg(arg,
sizeof(arg), &p);
1302 fprintf(stderr,
"%s:%d: ACL action '%s' is not ALLOW or DENY\n",
1303 filename, line_num, arg);
1307 get_arg(arg,
sizeof(arg), &p);
1310 fprintf(stderr,
"%s:%d: ACL refers to invalid host or ip address '%s'\n",
1311 filename, line_num, arg);
1316 get_arg(arg,
sizeof(arg), &p);
1320 fprintf(stderr,
"%s:%d: ACL refers to invalid host or ip address '%s'\n",
1321 filename, line_num, arg);
1334 naclp = &stream->
acl;
1340 fprintf(stderr,
"%s:%d: ACL found not in <stream> or <feed>\n",
1341 filename, line_num);
1347 naclp = &(*naclp)->
next;
1374 if (fgets(line,
sizeof(line), f) ==
NULL)
1380 if (*p ==
'\0' || *p ==
'#')
1382 get_arg(cmd,
sizeof(cmd), &p);
1408 struct in_addr *src = &c->
from_addr.sin_addr;
1409 unsigned long src_addr = src->s_addr;
1411 for (acl = in_acl; acl; acl = acl->
next) {
1412 if (src_addr >= acl->
first.s_addr && src_addr <= acl->last.s_addr)
1414 last_action = acl->
action;
1418 return (last_action ==
IP_DENY) ? 1 : 0;
1452 p = strrchr(file1,
'.');
1455 for(stream = first_stream; stream !=
NULL; stream = stream->
next) {
1457 p = strrchr(file2,
'.');
1460 if (!strcmp(file1, file2)) {
1483 char info[1024], filename[1024];
1487 const char *mime_type;
1491 const char *useragent = 0;
1497 if (!strcmp(cmd,
"GET"))
1499 else if (!strcmp(cmd,
"POST"))
1507 get_word(protocol,
sizeof(protocol), (
const char **)&p);
1508 if (strcmp(protocol,
"HTTP/1.0") && strcmp(protocol,
"HTTP/1.1"))
1514 http_log(
"%s - - New connection: %s %s\n", inet_ntoa(c->
from_addr.sin_addr), cmd, url);
1517 p1 = strchr(url,
'?');
1524 av_strlcpy(filename, url + ((*url ==
'/') ? 1 : 0),
sizeof(filename)-1);
1526 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1529 if (*useragent && *useragent !=
'\n' &&
av_isspace(*useragent))
1533 p = strchr(p,
'\n');
1543 filename[strlen(filename)-1] =
'f';
1550 strcpy(filename + strlen(filename)-2,
"m");
1560 if (!strlen(filename))
1561 av_strlcpy(filename,
"index.html",
sizeof(filename) - 1);
1564 while (stream !=
NULL) {
1567 stream = stream->
next;
1569 if (stream ==
NULL) {
1570 snprintf(msg,
sizeof(msg),
"File '%s' not found", url);
1571 http_log(
"File '%s' not found\n", url);
1583 "HTTP/1.0 301 Moved\r\n"
1585 "Content-type: text/html\r\n"
1587 "<html><head><title>Moved</title></head><body>\r\n"
1588 "You should be <a href=\"%s\">redirected</a>.\r\n"
1612 snprintf(msg,
sizeof(msg),
"This feed is already being received.");
1621 "HTTP/1.0 503 Server too busy\r\n"
1622 "Content-type: text/html\r\n"
1624 "<html><head><title>Too busy</title></head><body>\r\n"
1625 "<p>The server is too busy to serve your request at this time.</p>\r\n"
1626 "<p>The bandwidth being served (including your stream) is %"PRIu64
"kbit/sec, "
1627 "and this exceeds the limit of %"PRIu64
"kbit/sec.</p>\r\n"
1637 const char *hostinfo = 0;
1639 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1644 p = strchr(p,
'\n');
1658 eoh = strchr(hostinfo,
'\n');
1660 if (eoh[-1] ==
'\r')
1663 if (eoh - hostinfo <
sizeof(hostbuf) - 1) {
1664 memcpy(hostbuf, hostinfo, eoh - hostinfo);
1665 hostbuf[eoh - hostinfo] = 0;
1669 switch(redir_type) {
1672 "HTTP/1.0 200 ASX Follows\r\n"
1673 "Content-type: video/x-ms-asf\r\n"
1675 "<ASX Version=\"3\">\r\n"
1677 "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n"
1678 "</ASX>\r\n", hostbuf, filename, info);
1682 "HTTP/1.0 200 RAM Follows\r\n"
1683 "Content-type: audio/x-pn-realaudio\r\n"
1685 "# Autogenerated by avserver\r\n"
1686 "http://%s/%s%s\r\n", hostbuf, filename, info);
1690 "HTTP/1.0 200 ASF Redirect follows\r\n"
1691 "Content-type: video/x-ms-asf\r\n"
1694 "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info);
1698 char hostname[256], *p;
1700 av_strlcpy(hostname, hostbuf,
sizeof(hostname));
1701 p = strrchr(hostname,
':');
1705 "HTTP/1.0 200 RTSP Redirect follows\r\n"
1707 "Content-type: application/x-rtsp\r\n"
1709 "rtsp://%s:%d/%s\r\n", hostname, ntohs(
my_rtsp_addr.sin_port), filename);
1717 struct sockaddr_in my_addr;
1720 "HTTP/1.0 200 OK\r\n"
1721 "Content-type: application/sdp\r\n"
1724 len =
sizeof(my_addr);
1725 getsockname(c->
fd, (
struct sockaddr *)&my_addr, &len);
1731 if (sdp_data_size > 0) {
1732 memcpy(q, sdp_data, sdp_data_size);
1753 snprintf(msg,
sizeof(msg),
"ASX/RAM file not handled");
1766 const char *logline = 0;
1769 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1775 client_id = strtol(p + 18, 0, 10);
1776 p = strchr(p,
'\n');
1784 char *eol = strchr(logline,
'\n');
1789 if (eol[-1] ==
'\r')
1791 http_log(
"%.*s\n", (
int) (eol - logline), logline);
1804 for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->
next) {
1813 snprintf(msg,
sizeof(msg),
"POST command not handled");
1818 snprintf(msg,
sizeof(msg),
"could not open feed");
1836 snprintf(msg,
sizeof(msg),
"Input stream corresponding to '%s' not found", url);
1842 q += snprintf(q, q - (
char *) c->
buffer + c->
buffer_size,
"HTTP/1.0 200 OK\r\n");
1845 mime_type =
"application/x-octet-stream";
1846 q += snprintf(q, q - (
char *) c->
buffer + c->
buffer_size,
"Pragma: no-cache\r\n");
1854 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);
1856 q += snprintf(q, q - (
char *) c->
buffer + c->
buffer_size,
"Content-Type: %s\r\n", mime_type);
1869 "HTTP/1.0 404 Not Found\r\n"
1870 "Content-type: text/html\r\n"
1873 "<head><title>404 Not Found</title></head>\n"
1891 static const char suffix[] =
" kMGTP";
1894 for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++);
1916 avio_printf(pb,
"Content-type: %s\r\n",
"text/html");
1927 avio_printf(pb,
"<table cellspacing=0 cellpadding=4>\n");
1928 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");
1930 while (stream !=
NULL) {
1931 char sfilename[1024];
1934 if (stream->
feed != stream) {
1936 eosf = sfilename + strlen(sfilename);
1937 if (eosf - sfilename >= 4) {
1938 if (strcmp(eosf - 4,
".asf") == 0)
1939 strcpy(eosf - 4,
".asx");
1940 else if (strcmp(eosf - 3,
".rm") == 0)
1941 strcpy(eosf - 3,
".ram");
1942 else if (stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
1946 eosf = strrchr(sfilename,
'.');
1948 eosf = sfilename + strlen(sfilename);
1950 strcpy(eosf,
".sdp");
1952 strcpy(eosf,
".rtsp");
1956 avio_printf(pb,
"<tr><td><a href=\"/%s\">%s</a> ",
1958 avio_printf(pb,
"<td align=right> %d <td align=right> ",
1963 int audio_bit_rate = 0;
1964 int video_bit_rate = 0;
1965 const char *audio_codec_name =
"";
1966 const char *video_codec_name =
"";
1967 const char *audio_codec_name_extra =
"";
1968 const char *video_codec_name_extra =
"";
1977 if (*audio_codec_name)
1978 audio_codec_name_extra =
"...";
1979 audio_codec_name = codec->
name;
1985 if (*video_codec_name)
1986 video_codec_name_extra =
"...";
1987 video_codec_name = codec->
name;
1997 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",
2000 video_bit_rate / 1000, video_codec_name, video_codec_name_extra,
2001 audio_bit_rate / 1000, audio_codec_name, audio_codec_name_extra);
2010 avio_printf(pb,
"<td align=center> - <td align=right> - <td align=right> - <td><td align=right> - <td>\n");
2014 stream = stream->
next;
2019 while (stream !=
NULL) {
2020 if (stream->
feed == stream) {
2025 #if defined(linux) && !defined(CONFIG_NOCUTILS)
2031 snprintf(ps_cmd,
sizeof(ps_cmd),
2032 "ps -o \"%%cpu,cputime\" --no-headers %d",
2035 pid_stat = popen(ps_cmd,
"r");
2040 if (fscanf(pid_stat,
"%10s %64s", cpuperc,
2042 avio_printf(pb,
"Currently using %s%% of the cpu. Total time used %s.\n",
2052 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");
2057 const char *type =
"unknown";
2058 char parameters[64];
2069 snprintf(parameters,
sizeof(parameters),
"%dx%d, q=%d-%d, fps=%d", st->
codec->
width, st->
codec->
height,
2075 avio_printf(pb,
"<tr><td align=right>%d<td>%s<td align=right>%d<td>%s<td>%s\n",
2081 stream = stream->
next;
2087 avio_printf(pb,
"Number of connections: %d / %d<br>\n",
2090 avio_printf(pb,
"Bandwidth in use: %"PRIu64
"k / %"PRIu64
"k<br>\n",
2094 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");
2097 while (c1 !=
NULL) {
2113 avio_printf(pb,
"<tr><td><b>%d</b><td>%s%s<td>%s<td>%s<td>%s<td align=right>",
2133 avio_printf(pb,
"<hr size=1 noshade>Generated at %s", p);
2157 int prebuffer = strtol(buf, 0, 10);
2158 stream_pos =
av_gettime() - prebuffer * (int64_t)1000000;
2170 if (input_filename[0] ==
'\0')
2175 http_log(
"could not open %s: %d\n", input_filename, ret);
2181 http_log(
"Could not find stream info '%s'\n", input_filename);
2215 int bytes_left, bytes_sent, frame_bytes;
2218 if (frame_bytes <= 0)
2222 bytes_sent = frame_bytes - bytes_left;
2280 http_log(
"Error writing output header\n");
2314 }
else if (ret ==
AVERROR(EAGAIN)) {
2391 int max_packet_size;
2413 http_log(
"Error writing frame to output\n");
2499 int interleaved_index,
size;
2515 interleaved_index++;
2518 header[1] = interleaved_index;
2519 header[2] = len >> 8;
2591 http_log(
"Error opening feeder file: %s\n", strerror(errno));
2601 http_log(
"Error truncating feed file: %s\n", strerror(errno));
2606 http_log(
"Error reading write index from feed file: %s\n", strerror(errno));
2613 lseek(fd, 0, SEEK_SET);
2626 int len, loop_run = 0;
2639 }
else if (len == 0) {
2649 }
else if (++loop_run > 10) {
2665 }
else if (len == 0)
2677 if (c->
buffer[0] !=
'f' ||
2679 http_log(
"Feed stream has become desynchronized -- disconnecting\n");
2692 http_log(
"Error writing to feed file: %s\n", strerror(errno));
2707 http_log(
"Error writing index to feed file: %s\n", strerror(errno));
2712 for(c1 = first_http_ctx; c1 !=
NULL; c1 = c1->
next) {
2746 http_log(
"Feed '%s' stream number does not match registered feed\n",
2768 for(c1 = first_http_ctx; c1 !=
NULL; c1 = c1->
next) {
2786 switch(error_number) {
2791 str =
"Method Not Allowed";
2794 str =
"Not Enough Bandwidth";
2797 str =
"Session Not Found";
2800 str =
"Method Not Valid in This State";
2803 str =
"Aggregate operation not allowed";
2806 str =
"Only aggregate operation allowed";
2809 str =
"Unsupported transport";
2812 str =
"Internal Server Error";
2815 str =
"Service Unavailable";
2818 str =
"RTSP Version not supported";
2821 str =
"Unknown Error";
2825 avio_printf(c->
pb,
"RTSP/1.0 %d %s\r\n", error_number, str);
2831 strftime(buf2,
sizeof(buf2),
"%a, %d %b %Y %H:%M:%S", tm);
2843 const char *p, *p1, *p2;
2856 get_word(protocol,
sizeof(protocol), &p);
2869 if (strcmp(protocol,
"RTSP/1.0") != 0) {
2876 while (*p !=
'\n' && *p !=
'\0')
2880 while (*p !=
'\0') {
2881 p1 = memchr(p,
'\n', (
char *)c->
buffer_ptr - p);
2885 if (p2 > p && p2[-1] ==
'\r')
2891 if (len >
sizeof(line) - 1)
2892 len =
sizeof(line) - 1;
2893 memcpy(line, p, len);
2900 c->
seq = header->seq;
2902 if (!strcmp(cmd,
"DESCRIBE"))
2904 else if (!strcmp(cmd,
"OPTIONS"))
2906 else if (!strcmp(cmd,
"SETUP"))
2908 else if (!strcmp(cmd,
"PLAY"))
2910 else if (!strcmp(cmd,
"PAUSE"))
2912 else if (!strcmp(cmd,
"TEARDOWN"))
2931 struct in_addr my_ip)
2942 stream->
title[0] ? stream->
title :
"No Title", 0);
2945 snprintf(avc->
filename, 1024,
"rtp://%s:%d?multicast=1?ttl=%d",
2949 snprintf(avc->
filename, 1024,
"rtp://0.0.0.0");
2955 if (avc->
nb_streams >= INT_MAX/
sizeof(*avs) ||
2972 return strlen(*pbuffer);
2980 avio_printf(c->
pb,
"Public: %s\r\n",
"OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
2992 struct sockaddr_in my_addr;
3000 for(stream = first_stream; stream !=
NULL; stream = stream->
next) {
3002 stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp") &&
3015 len =
sizeof(my_addr);
3016 getsockname(c->
fd, (
struct sockaddr *)&my_addr, &len);
3018 if (content_length < 0) {
3025 avio_printf(c->
pb,
"Content-Length: %d\r\n", content_length);
3035 if (session_id[0] ==
'\0')
3038 for(c = first_http_ctx; c !=
NULL; c = c->
next) {
3062 int stream_index, rtp_port, rtcp_port;
3068 struct sockaddr_in dest_addr;
3078 for(stream = first_stream; stream !=
NULL; stream = stream->
next) {
3080 stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
3082 if (!strcmp(path, stream->
filename)) {
3091 for(stream_index = 0; stream_index < stream->
nb_streams;
3093 snprintf(buf,
sizeof(buf),
"%s/streamid=%d",
3095 if (!strcmp(path, buf))
3139 if (rtp_c->
stream != stream) {
3145 if (rtp_c->
rtp_ctx[stream_index]) {
3159 setup.transport_option[0] =
'\0';
3179 "client_port=%d-%d;server_port=%d-%d",
3181 rtp_port, rtcp_port);
3184 avio_printf(c->
pb,
"Transport: RTP/AVP/TCP;interleaved=%d-%d",
3185 stream_index * 2, stream_index * 2 + 1);
3190 if (setup.transport_option[0] !=
'\0')
3202 const char *session_id)
3221 snprintf(buf,
sizeof(buf),
"%s/streamid=%d",
3223 if(!strncmp(path, buf,
sizeof(buf))) {
3229 if (len > 0 && path[len - 1] ==
'/' &&
3311 FFStream *stream,
const char *session_id,
3315 const char *proto_str;
3344 proto_str =
"MCAST";
3377 int stream_index,
struct sockaddr_in *dest_addr,
3385 int max_packet_size;
3412 ipaddr = inet_ntoa(dest_addr->sin_addr);
3426 "rtp://%s:%d?multicast=1&ttl=%d",
3427 ipaddr, ntohs(dest_addr->sin_port), ttl);
3430 "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
3447 http_log(
"%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
3448 ipaddr, ntohs(dest_addr->sin_port),
3466 c->
rtp_ctx[stream_index] = ctx;
3547 while (*ps !=
NULL) {
3558 int mpeg4_count, i,
size;
3576 printf(
"MPEG4 without extra data: trying to find header in %s\n", infile->
filename);
3577 while (mpeg4_count > 0) {
3587 while (p < pkt.
data + pkt.
size - 4) {
3589 if (p[0] == 0x00 && p[1] == 0x00 &&
3590 p[2] == 0x01 && p[3] == 0xb6) {
3591 size = p - pkt.
data;
3613 for(stream = first_stream; stream !=
NULL; stream = stream_next) {
3615 stream_next = stream->
next;
3621 if (stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
3637 http_log(
"Could not find codec parameters from '%s'\n",
3660 for(stream = first_stream; stream !=
NULL; stream = stream->
next) {
3661 feed = stream->
feed;
3675 for(feed = first_feed; feed !=
NULL; feed = feed->
next_feed) {
3694 http_log(
"Index & Id do not match for stream %d (%s)\n",
3702 #define CHECK_CODEC(x) (ccf->x != ccs->x)
3705 http_log(
"Codecs do not match for stream %d\n", i);
3708 http_log(
"Codec bitrates do not match for stream %d\n", i);
3715 http_log(
"Codec width, height and framerate do not match for stream %d\n", i);
3722 http_log(
"Codec sample_rate, channels, frame_size do not match for stream %d\n", i);
3734 http_log(
"Deleting feed file '%s' as stream counts differ (%d != %d)\n",
3739 http_log(
"Deleting feed file '%s' as it appears to be corrupt\n",
3744 http_log(
"Unable to delete feed file '%s' as it is marked readonly\n",
3755 http_log(
"Unable to create feed file '%s' as it is marked readonly\n",
3762 http_log(
"Could not open output feed file '%s'\n",
3766 s->oformat = feed->
fmt;
3770 http_log(
"Container doesn't supports the required parameters\n");
3780 http_log(
"Could not open output feed file '%s'\n",
3786 feed->
feed_size = lseek(fd, 0, SEEK_END);
3802 for(stream = first_stream; stream !=
NULL; stream = stream->
next) {
3815 stream->
bandwidth = (bandwidth + 999) / 1000;
3867 av->
rc_eq =
"tex^qComp";
3930 char filename[1000], tmp[1000], tmp2[1000],
line[1000];
3936 fprintf(stderr,
"File for preset '%s' not found\n", arg);
3941 int e= fscanf(f,
"%999[^\n]\n", line) - 1;
3942 if(line[0] ==
'#' && !e)
3944 e|= sscanf(line,
"%999[^=]=%999[^\n]\n", tmp, tmp2) - 2;
3946 fprintf(stderr,
"%s: Invalid syntax: '%s'\n", filename, line);
3950 if(!strcmp(tmp,
"acodec")){
3952 }
else if(!strcmp(tmp,
"vcodec")){
3954 }
else if(!strcmp(tmp,
"scodec")){
3957 fprintf(stderr,
"%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", filename, line, tmp, tmp2);
3969 const char *mime_type)
3975 char stream_format_name[64];
3977 snprintf(stream_format_name,
sizeof(stream_format_name),
"%s_stream", fmt->
name);
3991 fprintf(stderr,
"%s:%d: ", filename, line_num);
3992 vfprintf(stderr, fmt, vl);
4005 int val, errors, line_num;
4006 FFStream **last_stream, *stream, *redirect;
4011 f = fopen(filename,
"r");
4019 first_stream =
NULL;
4029 #define ERROR(...) report_config_error(filename, line_num, &errors, __VA_ARGS__)
4031 if (fgets(line,
sizeof(line), f) ==
NULL)
4037 if (*p ==
'\0' || *p ==
'#')
4040 get_arg(cmd,
sizeof(cmd), &p);
4043 get_arg(arg,
sizeof(arg), &p);
4045 if (val < 1 || val > 65536) {
4046 ERROR(
"Invalid_port: %s\n", arg);
4050 get_arg(arg,
sizeof(arg), &p);
4052 ERROR(
"%s:%d: Invalid host/IP address: %s\n", arg);
4055 get_arg(arg,
sizeof(arg), &p);
4057 if (val < 1 || val > 65536) {
4058 ERROR(
"%s:%d: Invalid port: %s\n", arg);
4062 get_arg(arg,
sizeof(arg), &p);
4064 ERROR(
"Invalid host/IP address: %s\n", arg);
4067 get_arg(arg,
sizeof(arg), &p);
4069 if (val < 1 || val > 65536) {
4070 ERROR(
"Invalid MaxHTTPConnections: %s\n", arg);
4074 get_arg(arg,
sizeof(arg), &p);
4077 ERROR(
"Invalid MaxClients: %s\n", arg);
4083 get_arg(arg,
sizeof(arg), &p);
4085 if (llval < 10 || llval > 10000000) {
4086 ERROR(
"Invalid MaxBandwidth: %s\n", arg);
4096 if (stream || feed) {
4097 ERROR(
"Already in a tag\n");
4105 for (s = first_feed; s; s = s->
next) {
4120 *last_stream = feed;
4121 last_stream = &feed->
next;
4132 for (i = 0; i < 62; i++) {
4133 get_arg(arg,
sizeof(arg), &p);
4144 (
my_http_addr.sin_addr.s_addr == INADDR_ANY) ?
"127.0.0.1" :
4152 }
else if (stream) {
4162 get_arg(arg,
sizeof(arg), &p);
4170 get_arg(arg,
sizeof(arg), &p);
4178 fsize *= 1024 * 1024;
4181 fsize *= 1024 * 1024 * 1024;
4191 ERROR(
"No corresponding <Feed> for </Feed>\n");
4198 if (stream || feed) {
4199 ERROR(
"Already in a tag\n");
4204 q = strrchr(stream->
filename,
'>');
4208 for (s = first_stream; s; s = s->
next) {
4224 *last_stream = stream;
4225 last_stream = &stream->
next;
4228 get_arg(arg,
sizeof(arg), &p);
4233 while (sfeed !=
NULL) {
4239 ERROR(
"feed '%s' not defined\n", arg);
4241 stream->
feed = sfeed;
4244 get_arg(arg,
sizeof(arg), &p);
4246 if (!strcmp(arg,
"status")) {
4252 if (!strcmp(arg,
"jpeg"))
4253 strcpy(arg,
"mjpeg");
4256 ERROR(
"Unknown Format: %s\n", arg);
4265 get_arg(arg,
sizeof(arg), &p);
4268 if (!stream->
ifmt) {
4269 ERROR(
"Unknown input format: %s\n", arg);
4276 ERROR(
"FaviconURL only permitted for status streams\n");
4291 get_arg(arg,
sizeof(arg), &p);
4298 get_arg(arg,
sizeof(arg), &p);
4301 ERROR(
"Unknown AudioCodec: %s\n", arg);
4304 get_arg(arg,
sizeof(arg), &p);
4307 ERROR(
"Unknown VideoCodec: %s\n", arg);
4310 get_arg(arg,
sizeof(arg), &p);
4312 stream->
max_time = atof(arg) * 1000;
4314 get_arg(arg,
sizeof(arg), &p);
4318 get_arg(arg,
sizeof(arg), &p);
4322 get_arg(arg,
sizeof(arg), &p);
4326 get_arg(arg,
sizeof(arg), &p);
4332 int minrate, maxrate;
4334 get_arg(arg,
sizeof(arg), &p);
4336 if (sscanf(arg,
"%d-%d", &minrate, &maxrate) == 2) {
4340 ERROR(
"Incorrect format for VideoBitRateRange -- should be <min>-<max>: %s\n", arg);
4345 get_arg(arg,
sizeof(arg), &p);
4346 video_enc.
debug = strtol(arg,0,0);
4350 get_arg(arg,
sizeof(arg), &p);
4355 get_arg(arg,
sizeof(arg), &p);
4360 get_arg(arg,
sizeof(arg), &p);
4364 get_arg(arg,
sizeof(arg), &p);
4366 video_enc.
bit_rate = atoi(arg) * 1000;
4369 get_arg(arg,
sizeof(arg), &p);
4372 if ((video_enc.
width % 16) != 0 ||
4373 (video_enc.
height % 16) != 0) {
4374 ERROR(
"Image size must be a multiple of 16\n");
4378 get_arg(arg,
sizeof(arg), &p);
4382 ERROR(
"Incorrect frame rate: %s\n", arg);
4389 get_arg(arg,
sizeof(arg), &p);
4408 get_arg(arg,
sizeof(arg), &p);
4409 get_arg(arg2,
sizeof(arg2), &p);
4418 ERROR(
"AVOption error: %s %s\n", arg, arg2);
4424 get_arg(arg,
sizeof(arg), &p);
4435 ERROR(
"AVPreset error: %s\n", arg);
4438 get_arg(arg,
sizeof(arg), &p);
4439 if ((strlen(arg) == 4) && stream)
4451 get_arg(arg,
sizeof(arg), &p);
4457 get_arg(arg,
sizeof(arg), &p);
4461 ERROR(
"VideoQDiff out of range\n");
4465 get_arg(arg,
sizeof(arg), &p);
4467 video_enc.
qmax = atoi(arg);
4468 if (video_enc.
qmax < 1 || video_enc.
qmax > 31) {
4469 ERROR(
"VideoQMax out of range\n");
4473 get_arg(arg,
sizeof(arg), &p);
4475 video_enc.
qmin = atoi(arg);
4476 if (video_enc.
qmin < 1 || video_enc.
qmin > 31) {
4477 ERROR(
"VideoQMin out of range\n");
4481 get_arg(arg,
sizeof(arg), &p);
4485 get_arg(arg,
sizeof(arg), &p);
4499 get_arg(arg,
sizeof(arg), &p);
4505 get_arg(arg,
sizeof(arg), &p);
4508 ERROR(
"Invalid host/IP address: %s\n", arg);
4514 get_arg(arg,
sizeof(arg), &p);
4518 get_arg(arg,
sizeof(arg), &p);
4526 ERROR(
"No corresponding <Stream> for </Stream>\n");
4528 if (stream->
feed && stream->
fmt && strcmp(stream->
fmt->
name,
"ffm") != 0) {
4545 if (stream || feed || redirect) {
4546 ERROR(
"Already in a tag\n");
4549 *last_stream = redirect;
4550 last_stream = &redirect->
next;
4553 q = strrchr(redirect->
filename,
'>');
4563 ERROR(
"No corresponding <Redirect> for </Redirect>\n");
4566 ERROR(
"No URL found for <Redirect>\n");
4571 ERROR(
"Loadable modules no longer supported\n");
4573 ERROR(
"Incorrect keyword: '%s'\n", cmd);
4590 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
4593 for (feed = first_feed; feed; feed = feed->
next) {
4594 if (feed->
pid == pid) {
4598 fprintf(stderr,
"%s: Pid %d exited with status %d after %d seconds\n", feed->
filename, pid, status, uptime);
4618 printf(
"usage: avserver [options]\n"
4619 "Hyper fast multi format Audio/Video streaming server\n");
4627 {
"d", 0, {(
void*)
opt_debug},
"enable debug mode" },
4634 struct sigaction sigact = { { 0 } };
4648 unsetenv(
"http_proxy");
4653 sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
4654 sigaction(SIGCHLD, &sigact, 0);
4657 fprintf(stderr,
"Incorrect config file - exiting.\n");
4677 signal(SIGPIPE, SIG_IGN);
4680 http_log(
"Could not start server\n");