24 #define closesocket close
46 #include <sys/ioctl.h>
97 #define MAX_STREAMS 20
99 #define IOBUFFER_INIT_SIZE 8192
102 #define HTTP_REQUEST_TIMEOUT (15 * 1000)
103 #define RTSP_REQUEST_TIMEOUT (3600 * 24 * 1000)
105 #define SYNC_TIMEOUT (10 * 1000)
288 struct in_addr my_ip);
292 FFStream *stream,
const char *session_id,
295 int stream_index,
struct sockaddr_in *dest_addr,
329 static int resolve_host(
struct in_addr *sin_addr,
const char *hostname)
336 memset(&hints, 0,
sizeof(hints));
343 for (cur = ai; cur; cur = cur->
ai_next) {
345 *sin_addr = ((
struct sockaddr_in *)cur->
ai_addr)->sin_addr;
354 hp = gethostbyname(hostname);
357 memcpy(sin_addr, hp->h_addr_list[0],
sizeof(
struct in_addr));
371 p = buf2 + strlen(p) - 1;
379 static int print_prefix = 1;
386 print_prefix = strstr(fmt,
"\n") !=
NULL;
393 __attribute__ ((format (
printf, 1, 2)))
398 va_start(vargs, fmt);
405 static int print_prefix = 1;
409 if (print_prefix && avc)
411 print_prefix = strstr(fmt,
"\n") !=
NULL;
420 http_log(
"%s - - [%s] \"%s %s\" %d %"PRId64
"\n",
453 for (; feed; feed = feed->
next) {
460 http_log(
"Unable to create children\n");
471 slash = strrchr(pathname,
'/');
476 strcpy(slash,
"avconv");
484 for (i = 3; i < 256; i++)
488 i = open(
"/dev/null", O_RDWR);
500 signal(SIGPIPE, SIG_DFL);
515 server_fd = socket(AF_INET,SOCK_STREAM,0);
522 setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp,
sizeof(tmp));
524 my_addr->sin_family = AF_INET;
525 if (bind (server_fd, (
struct sockaddr *) my_addr,
sizeof (*my_addr)) < 0) {
527 snprintf(bindmsg,
sizeof(bindmsg),
"bind(port %d)", ntohs(my_addr->sin_port));
533 if (listen (server_fd, 5) < 0) {
549 struct sockaddr_in dest_addr;
550 int default_port, stream_index;
553 for(stream = first_stream; stream !=
NULL; stream = stream->
next) {
556 snprintf(session_id,
sizeof(session_id),
"%08x%08x",
565 dest_addr.sin_family = AF_INET;
575 http_log(
"Could not open input stream for stream '%s'\n",
581 for(stream_index = 0; stream_index < stream->
nb_streams;
586 http_log(
"Could not open output stream '%s/streamid=%d'\n",
601 int server_fd = 0, rtsp_server_fd = 0;
602 int ret, delay, delay1;
603 struct pollfd *poll_table, *poll_entry;
619 if (rtsp_server_fd < 0)
623 if (!rtsp_server_fd && !server_fd) {
624 http_log(
"HTTP and RTSP disabled.\n");
635 poll_entry = poll_table;
637 poll_entry->fd = server_fd;
638 poll_entry->events = POLLIN;
641 if (rtsp_server_fd) {
642 poll_entry->fd = rtsp_server_fd;
643 poll_entry->events = POLLIN;
659 poll_entry->events = POLLOUT;
669 poll_entry->events = POLLOUT;
687 poll_entry->events = POLLIN;
700 ret = poll(poll_table, poll_entry - poll_table, delay);
714 for(c = first_http_ctx; c !=
NULL; c = c_next) {
723 poll_entry = poll_table;
726 if (poll_entry->revents & POLLIN)
730 if (rtsp_server_fd) {
732 if (poll_entry->revents & POLLIN)
756 int len = snprintf(buffer,
sizeof(buffer),
757 "HTTP/1.0 503 Server too busy\r\n"
758 "Content-type: text/html\r\n"
760 "<html><head><title>Too busy</title></head><body>\r\n"
761 "<p>The server is too busy to serve your request at this time.</p>\r\n"
762 "<p>The number of current connections is %d, and this exceeds the limit of %d.</p>\r\n"
763 "</body></html>\r\n",
765 send(fd, buffer, len, 0);
771 struct sockaddr_in from_addr;
775 len =
sizeof(from_addr);
776 fd = accept(server_fd, (
struct sockaddr *)&from_addr,
779 http_log(
"error during accept %s\n", strerror(errno));
828 while ((*cp) !=
NULL) {
837 for(c1 = first_http_ctx; c1 !=
NULL; c1 = c1->
next) {
860 for(i=0;i<nb_streams;i++) {
915 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
928 }
else if (len == 0) {
935 if ((ptr >= c->
buffer + 2 && !memcmp(ptr-2,
"\n\n", 2)) ||
936 (ptr >= c->
buffer + 4 && !memcmp(ptr-4,
"\r\n\r\n", 4))) {
948 }
else goto read_loop;
953 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
991 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1006 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1015 if (c->
poll_entry->revents & (POLLIN | POLLERR | POLLHUP))
1022 if (c->
poll_entry->revents & (POLLERR | POLLHUP)) {
1048 if (c->
poll_entry->revents & (POLLERR | POLLHUP)) {
1086 for (p = request; *p && *p !=
'\r' && *p !=
'\n'; ) {
1088 const char *q = p + 7;
1090 while (*q && *q !=
'\n' && isspace(*q))
1099 memset(rates, 0xff, ratelen);
1102 while (*q && *q !=
'\n' && *q !=
':')
1105 if (sscanf(q,
":%d:%d", &stream_no, &rate_no) != 2)
1109 if (stream_no < ratelen && stream_no >= 0)
1110 rates[stream_no] = rate_no;
1112 while (*q && *q !=
'\n' && !isspace(*q))
1119 p = strchr(p,
'\n');
1132 int best_bitrate = 100000000;
1150 if (feed_codec->
bit_rate <= bit_rate) {
1151 if (best_bitrate > bit_rate || feed_codec->
bit_rate > best_bitrate) {
1152 best_bitrate = feed_codec->
bit_rate;
1156 if (feed_codec->
bit_rate < best_bitrate) {
1157 best_bitrate = feed_codec->
bit_rate;
1170 int action_required = 0;
1198 action_required = 1;
1201 return action_required;
1210 while (*p ==
' ' || *p ==
'\t')
1215 static void get_word(
char *buf,
int buf_size,
const char **pp)
1223 while (!isspace(*p) && *p !=
'\0') {
1224 if ((q - buf) < buf_size - 1)
1233 static void get_arg(
char *buf,
int buf_size,
const char **pp)
1240 while (isspace(*p)) p++;
1243 if (*p ==
'\"' || *p ==
'\'')
1255 if ((q - buf) < buf_size - 1)
1260 if (quote && *p == quote)
1266 const char *p,
const char *filename,
int line_num)
1272 get_arg(arg,
sizeof(arg), &p);
1278 fprintf(stderr,
"%s:%d: ACL action '%s' is not ALLOW or DENY\n",
1279 filename, line_num, arg);
1283 get_arg(arg,
sizeof(arg), &p);
1286 fprintf(stderr,
"%s:%d: ACL refers to invalid host or ip address '%s'\n",
1287 filename, line_num, arg);
1292 get_arg(arg,
sizeof(arg), &p);
1296 fprintf(stderr,
"%s:%d: ACL refers to invalid host or ip address '%s'\n",
1297 filename, line_num, arg);
1310 naclp = &stream->
acl;
1316 fprintf(stderr,
"%s:%d: ACL found not in <stream> or <feed>\n",
1317 filename, line_num);
1323 naclp = &(*naclp)->
next;
1350 if (fgets(line,
sizeof(line), f) ==
NULL)
1356 if (*p ==
'\0' || *p ==
'#')
1358 get_arg(cmd,
sizeof(cmd), &p);
1384 struct in_addr *src = &c->
from_addr.sin_addr;
1385 unsigned long src_addr = src->s_addr;
1387 for (acl = in_acl; acl; acl = acl->
next) {
1388 if (src_addr >= acl->
first.s_addr && src_addr <= acl->last.s_addr)
1390 last_action = acl->
action;
1394 return (last_action ==
IP_DENY) ? 1 : 0;
1428 p = strrchr(file1,
'.');
1431 for(stream = first_stream; stream !=
NULL; stream = stream->
next) {
1433 p = strrchr(file2,
'.');
1436 if (!strcmp(file1, file2)) {
1458 char info[1024], filename[1024];
1462 const char *mime_type;
1466 char *useragent = 0;
1469 get_word(cmd,
sizeof(cmd), (
const char **)&p);
1472 if (!strcmp(cmd,
"GET"))
1474 else if (!strcmp(cmd,
"POST"))
1479 get_word(url,
sizeof(url), (
const char **)&p);
1482 get_word(protocol,
sizeof(protocol), (
const char **)&p);
1483 if (strcmp(protocol,
"HTTP/1.0") && strcmp(protocol,
"HTTP/1.1"))
1489 http_log(
"%s - - New connection: %s %s\n", inet_ntoa(c->
from_addr.sin_addr), cmd, url);
1492 p = strchr(url,
'?');
1499 av_strlcpy(filename, url + ((*url ==
'/') ? 1 : 0),
sizeof(filename)-1);
1501 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1504 if (*useragent && *useragent !=
'\n' && isspace(*useragent))
1508 p = strchr(p,
'\n');
1518 filename[strlen(filename)-1] =
'f';
1525 strcpy(filename + strlen(filename)-2,
"m");
1535 if (!strlen(filename))
1536 av_strlcpy(filename,
"index.html",
sizeof(filename) - 1);
1539 while (stream !=
NULL) {
1542 stream = stream->
next;
1544 if (stream ==
NULL) {
1545 snprintf(msg,
sizeof(msg),
"File '%s' not found", url);
1546 http_log(
"File '%s' not found\n", url);
1558 "HTTP/1.0 301 Moved\r\n"
1560 "Content-type: text/html\r\n"
1562 "<html><head><title>Moved</title></head><body>\r\n"
1563 "You should be <a href=\"%s\">redirected</a>.\r\n"
1587 snprintf(msg,
sizeof(msg),
"This feed is already being received.");
1596 "HTTP/1.0 503 Server too busy\r\n"
1597 "Content-type: text/html\r\n"
1599 "<html><head><title>Too busy</title></head><body>\r\n"
1600 "<p>The server is too busy to serve your request at this time.</p>\r\n"
1601 "<p>The bandwidth being served (including your stream) is %"PRIu64
"kbit/sec, "
1602 "and this exceeds the limit of %"PRIu64
"kbit/sec.</p>\r\n"
1614 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1619 p = strchr(p,
'\n');
1630 while (isspace(*hostinfo))
1633 eoh = strchr(hostinfo,
'\n');
1635 if (eoh[-1] ==
'\r')
1638 if (eoh - hostinfo <
sizeof(hostbuf) - 1) {
1639 memcpy(hostbuf, hostinfo, eoh - hostinfo);
1640 hostbuf[eoh - hostinfo] = 0;
1644 switch(redir_type) {
1647 "HTTP/1.0 200 ASX Follows\r\n"
1648 "Content-type: video/x-ms-asf\r\n"
1650 "<ASX Version=\"3\">\r\n"
1652 "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n"
1653 "</ASX>\r\n", hostbuf, filename, info);
1657 "HTTP/1.0 200 RAM Follows\r\n"
1658 "Content-type: audio/x-pn-realaudio\r\n"
1660 "# Autogenerated by avserver\r\n"
1661 "http://%s/%s%s\r\n", hostbuf, filename, info);
1665 "HTTP/1.0 200 ASF Redirect follows\r\n"
1666 "Content-type: video/x-ms-asf\r\n"
1669 "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info);
1673 char hostname[256], *p;
1675 av_strlcpy(hostname, hostbuf,
sizeof(hostname));
1676 p = strrchr(hostname,
':');
1680 "HTTP/1.0 200 RTSP Redirect follows\r\n"
1682 "Content-type: application/x-rtsp\r\n"
1684 "rtsp://%s:%d/%s\r\n", hostname, ntohs(
my_rtsp_addr.sin_port), filename);
1690 int sdp_data_size,
len;
1691 struct sockaddr_in my_addr;
1694 "HTTP/1.0 200 OK\r\n"
1695 "Content-type: application/sdp\r\n"
1698 len =
sizeof(my_addr);
1699 getsockname(c->
fd, (
struct sockaddr *)&my_addr, &len);
1705 if (sdp_data_size > 0) {
1706 memcpy(q, sdp_data, sdp_data_size);
1727 snprintf(msg,
sizeof(msg),
"ASX/RAM file not handled");
1743 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1749 client_id = strtol(p + 18, 0, 10);
1750 p = strchr(p,
'\n');
1758 char *eol = strchr(logline,
'\n');
1763 if (eol[-1] ==
'\r')
1765 http_log(
"%.*s\n", (
int) (eol - logline), logline);
1778 for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->
next) {
1787 snprintf(msg,
sizeof(msg),
"POST command not handled");
1792 snprintf(msg,
sizeof(msg),
"could not open feed");
1810 snprintf(msg,
sizeof(msg),
"Input stream corresponding to '%s' not found", url);
1816 q += snprintf(q, q - (
char *) c->
buffer + c->
buffer_size,
"HTTP/1.0 200 OK\r\n");
1819 mime_type =
"application/x-octet-stream";
1820 q += snprintf(q, q - (
char *) c->
buffer + c->
buffer_size,
"Pragma: no-cache\r\n");
1828 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);
1830 q += snprintf(q, q - (
char *) c->
buffer + c->
buffer_size,
"Content-Type: %s\r\n", mime_type);
1843 "HTTP/1.0 404 Not Found\r\n"
1844 "Content-type: text/html\r\n"
1847 "<head><title>404 Not Found</title></head>\n"
1865 static const char *suffix =
" kMGTP";
1868 for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++);
1890 avio_printf(pb,
"Content-type: %s\r\n",
"text/html");
1901 avio_printf(pb,
"<table cellspacing=0 cellpadding=4>\n");
1902 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");
1904 while (stream !=
NULL) {
1905 char sfilename[1024];
1908 if (stream->
feed != stream) {
1910 eosf = sfilename + strlen(sfilename);
1911 if (eosf - sfilename >= 4) {
1912 if (strcmp(eosf - 4,
".asf") == 0)
1913 strcpy(eosf - 4,
".asx");
1914 else if (strcmp(eosf - 3,
".rm") == 0)
1915 strcpy(eosf - 3,
".ram");
1916 else if (stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
1920 eosf = strrchr(sfilename,
'.');
1922 eosf = sfilename + strlen(sfilename);
1924 strcpy(eosf,
".sdp");
1926 strcpy(eosf,
".rtsp");
1930 avio_printf(pb,
"<tr><td><a href=\"/%s\">%s</a> ",
1932 avio_printf(pb,
"<td align=right> %d <td align=right> ",
1937 int audio_bit_rate = 0;
1938 int video_bit_rate = 0;
1941 const char *audio_codec_name_extra =
"";
1942 const char *video_codec_name_extra =
"";
1951 if (*audio_codec_name)
1952 audio_codec_name_extra =
"...";
1953 audio_codec_name = codec->
name;
1959 if (*video_codec_name)
1960 video_codec_name_extra =
"...";
1961 video_codec_name = codec->
name;
1971 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",
1974 video_bit_rate / 1000, video_codec_name, video_codec_name_extra,
1975 audio_bit_rate / 1000, audio_codec_name, audio_codec_name_extra);
1984 avio_printf(pb,
"<td align=center> - <td align=right> - <td align=right> - <td><td align=right> - <td>\n");
1988 stream = stream->
next;
1993 while (stream !=
NULL) {
1994 if (stream->
feed == stream) {
1999 #if defined(linux) && !defined(CONFIG_NOCUTILS)
2005 snprintf(ps_cmd,
sizeof(ps_cmd),
2006 "ps -o \"%%cpu,cputime\" --no-headers %d",
2009 pid_stat = popen(ps_cmd,
"r");
2014 if (fscanf(pid_stat,
"%10s %64s", cpuperc,
2016 avio_printf(pb,
"Currently using %s%% of the cpu. Total time used %s.\n",
2026 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");
2031 const char *type =
"unknown";
2032 char parameters[64];
2043 snprintf(parameters,
sizeof(parameters),
"%dx%d, q=%d-%d, fps=%d", st->
codec->
width, st->
codec->
height,
2049 avio_printf(pb,
"<tr><td align=right>%d<td>%s<td align=right>%d<td>%s<td>%s\n",
2055 stream = stream->
next;
2061 avio_printf(pb,
"Number of connections: %d / %d<br>\n",
2064 avio_printf(pb,
"Bandwidth in use: %"PRIu64
"k / %"PRIu64
"k<br>\n",
2068 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");
2071 while (c1 !=
NULL) {
2087 avio_printf(pb,
"<tr><td><b>%d</b><td>%s%s<td>%s<td>%s<td>%s<td align=right>",
2107 avio_printf(pb,
"<hr size=1 noshade>Generated at %s", p);
2131 int prebuffer = strtol(buf, 0, 10);
2132 stream_pos =
av_gettime() - prebuffer * (int64_t)1000000;
2144 if (input_filename[0] ==
'\0')
2149 http_log(
"could not open %s: %d\n", input_filename, ret);
2155 http_log(
"Could not find stream info '%s'\n", input_filename);
2189 int bytes_left, bytes_sent, frame_bytes;
2192 if (frame_bytes <= 0)
2196 bytes_sent = frame_bytes - bytes_left;
2255 http_log(
"Error writing output header\n");
2289 }
else if (ret ==
AVERROR(EAGAIN)) {
2366 int max_packet_size;
2388 http_log(
"Error writing frame to output\n");
2474 int interleaved_index,
size;
2490 interleaved_index++;
2493 header[1] = interleaved_index;
2494 header[2] = len >> 8;
2566 http_log(
"Error opening feeder file: %s\n", strerror(errno));
2578 http_log(
"Error reading write index from feed file: %s\n", strerror(errno));
2585 lseek(fd, 0, SEEK_SET);
2598 int len, loop_run = 0;
2611 }
else if (len == 0) {
2621 }
else if (++loop_run > 10) {
2637 }
else if (len == 0)
2649 if (c->
buffer[0] !=
'f' ||
2651 http_log(
"Feed stream has become desynchronized -- disconnecting\n");
2666 http_log(
"Error writing to feed file: %s\n", strerror(errno));
2681 http_log(
"Error writing index to feed file: %s\n", strerror(errno));
2686 for(c1 = first_http_ctx; c1 !=
NULL; c1 = c1->
next) {
2720 http_log(
"Feed '%s' stream number does not match registered feed\n",
2742 for(c1 = first_http_ctx; c1 !=
NULL; c1 = c1->
next) {
2760 switch(error_number) {
2765 str =
"Method Not Allowed";
2768 str =
"Not Enough Bandwidth";
2771 str =
"Session Not Found";
2774 str =
"Method Not Valid in This State";
2777 str =
"Aggregate operation not allowed";
2780 str =
"Only aggregate operation allowed";
2783 str =
"Unsupported transport";
2786 str =
"Internal Server Error";
2789 str =
"Service Unavailable";
2792 str =
"RTSP Version not supported";
2795 str =
"Unknown Error";
2799 avio_printf(c->
pb,
"RTSP/1.0 %d %s\r\n", error_number, str);
2805 strftime(buf2,
sizeof(buf2),
"%a, %d %b %Y %H:%M:%S", tm);
2817 const char *p, *p1, *p2;
2830 get_word(protocol,
sizeof(protocol), &p);
2843 if (strcmp(protocol,
"RTSP/1.0") != 0) {
2849 memset(header, 0,
sizeof(*header));
2851 while (*p !=
'\n' && *p !=
'\0')
2855 while (*p !=
'\0') {
2856 p1 = memchr(p,
'\n', (
char *)c->
buffer_ptr - p);
2860 if (p2 > p && p2[-1] ==
'\r')
2866 if (len >
sizeof(line) - 1)
2867 len =
sizeof(line) - 1;
2868 memcpy(line, p, len);
2877 if (!strcmp(cmd,
"DESCRIBE"))
2879 else if (!strcmp(cmd,
"OPTIONS"))
2881 else if (!strcmp(cmd,
"SETUP"))
2883 else if (!strcmp(cmd,
"PLAY"))
2885 else if (!strcmp(cmd,
"PAUSE"))
2887 else if (!strcmp(cmd,
"TEARDOWN"))
2906 struct in_addr my_ip)
2917 stream->
title[0] ? stream->
title :
"No Title", 0);
2920 snprintf(avc->
filename, 1024,
"rtp://%s:%d?multicast=1?ttl=%d",
2924 snprintf(avc->
filename, 1024,
"rtp://0.0.0.0");
2930 if (avc->
nb_streams >= INT_MAX/
sizeof(*avs) ||
2947 return strlen(*pbuffer);
2955 avio_printf(c->
pb,
"Public: %s\r\n",
"OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
2965 int content_length,
len;
2966 struct sockaddr_in my_addr;
2974 for(stream = first_stream; stream !=
NULL; stream = stream->
next) {
2976 stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp") &&
2989 len =
sizeof(my_addr);
2990 getsockname(c->
fd, (
struct sockaddr *)&my_addr, &len);
2992 if (content_length < 0) {
2999 avio_printf(c->
pb,
"Content-Length: %d\r\n", content_length);
3009 if (session_id[0] ==
'\0')
3012 for(c = first_http_ctx; c !=
NULL; c = c->
next) {
3036 int stream_index, rtp_port, rtcp_port;
3042 struct sockaddr_in dest_addr;
3052 for(stream = first_stream; stream !=
NULL; stream = stream->
next) {
3054 stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
3056 if (!strcmp(path, stream->
filename)) {
3065 for(stream_index = 0; stream_index < stream->
nb_streams;
3067 snprintf(buf,
sizeof(buf),
"%s/streamid=%d",
3069 if (!strcmp(path, buf))
3113 if (rtp_c->
stream != stream) {
3119 if (rtp_c->
rtp_ctx[stream_index]) {
3133 setup.transport_option[0] =
'\0';
3153 "client_port=%d-%d;server_port=%d-%d",
3155 rtp_port, rtcp_port);
3158 avio_printf(c->
pb,
"Transport: RTP/AVP/TCP;interleaved=%d-%d",
3159 stream_index * 2, stream_index * 2 + 1);
3164 if (setup.transport_option[0] !=
'\0')
3176 const char *session_id)
3195 snprintf(buf,
sizeof(buf),
"%s/streamid=%d",
3197 if(!strncmp(path, buf,
sizeof(buf))) {
3203 if (len > 0 && path[len - 1] ==
'/' &&
3285 FFStream *stream,
const char *session_id,
3289 const char *proto_str;
3318 proto_str =
"MCAST";
3351 int stream_index,
struct sockaddr_in *dest_addr,
3359 int max_packet_size;
3386 ipaddr = inet_ntoa(dest_addr->sin_addr);
3400 "rtp://%s:%d?multicast=1&ttl=%d",
3401 ipaddr, ntohs(dest_addr->sin_port), ttl);
3404 "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
3410 max_packet_size = url_get_max_packet_size(h);
3421 http_log(
"%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
3422 ipaddr, ntohs(dest_addr->sin_port),
3440 c->
rtp_ctx[stream_index] = ctx;
3470 av_set_pts_info(fst, 33, 1, 90000);
3521 while (*ps !=
NULL) {
3532 int mpeg4_count, i,
size;
3548 printf(
"MPEG4 without extra data: trying to find header in %s\n", infile->
filename);
3549 while (mpeg4_count > 0) {
3559 while (p < pkt.
data + pkt.
size - 4) {
3561 if (p[0] == 0x00 && p[1] == 0x00 &&
3562 p[2] == 0x01 && p[3] == 0xb6) {
3563 size = p - pkt.
data;
3585 for(stream = first_stream; stream !=
NULL; stream = stream_next) {
3587 stream_next = stream->
next;
3593 if (stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
3609 http_log(
"Could not find codec parameters from '%s'\n",
3632 for(stream = first_stream; stream !=
NULL; stream = stream->
next) {
3633 feed = stream->
feed;
3647 for(feed = first_feed; feed !=
NULL; feed = feed->
next_feed) {
3666 http_log(
"Index & Id do not match for stream %d (%s)\n",
3674 #define CHECK_CODEC(x) (ccf->x != ccs->x)
3677 http_log(
"Codecs do not match for stream %d\n", i);
3680 http_log(
"Codec bitrates do not match for stream %d\n", i);
3687 http_log(
"Codec width, height and framerate do not match for stream %d\n", i);
3694 http_log(
"Codec sample_rate, channels, frame_size do not match for stream %d\n", i);
3706 http_log(
"Deleting feed file '%s' as stream counts differ (%d != %d)\n",
3711 http_log(
"Deleting feed file '%s' as it appears to be corrupt\n",
3716 http_log(
"Unable to delete feed file '%s' as it is marked readonly\n",
3727 http_log(
"Unable to create feed file '%s' as it is marked readonly\n",
3734 http_log(
"Could not open output feed file '%s'\n",
3738 s->oformat = feed->
fmt;
3742 http_log(
"Container doesn't supports the required parameters\n");
3752 http_log(
"Could not open output feed file '%s'\n",
3758 feed->
feed_size = lseek(fd, 0, SEEK_END);
3774 for(stream = first_stream; stream !=
NULL; stream = stream->
next) {
3787 stream->
bandwidth = (bandwidth + 999) / 1000;
3839 av->
rc_eq =
"tex^qComp";
3890 static void load_module(
const char *filename)
3894 dll = dlopen(filename, RTLD_NOW);
3896 fprintf(stderr,
"Could not load module '%s' - %s\n",
3897 filename, dlerror());
3901 init_func = dlsym(dll,
"avserver_module_init");
3904 "%s: init function 'avserver_module_init()' not found\n",
3928 char filename[1000], tmp[1000], tmp2[1000],
line[1000];
3934 fprintf(stderr,
"File for preset '%s' not found\n", arg);
3939 int e= fscanf(f,
"%999[^\n]\n", line) - 1;
3940 if(line[0] ==
'#' && !e)
3942 e|= sscanf(line,
"%999[^=]=%999[^\n]\n", tmp, tmp2) - 2;
3944 fprintf(stderr,
"%s: Invalid syntax: '%s'\n", filename, line);
3948 if(!strcmp(tmp,
"acodec")){
3950 }
else if(!strcmp(tmp,
"vcodec")){
3952 }
else if(!strcmp(tmp,
"scodec")){
3955 fprintf(stderr,
"%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", filename, line, tmp, tmp2);
3967 const char *mime_type)
3973 char stream_format_name[64];
3975 snprintf(stream_format_name,
sizeof(stream_format_name),
"%s_stream", fmt->
name);
3989 fprintf(stderr,
"%s:%d: ", filename, line_num);
3990 vfprintf(stderr, fmt, vl);
4003 int val, errors, line_num;
4004 FFStream **last_stream, *stream, *redirect;
4007 enum CodecID audio_id, video_id;
4009 f = fopen(filename,
"r");
4017 first_stream =
NULL;
4027 #define ERROR(...) report_config_error(filename, line_num, &errors, __VA_ARGS__)
4029 if (fgets(line,
sizeof(line), f) ==
NULL)
4035 if (*p ==
'\0' || *p ==
'#')
4038 get_arg(cmd,
sizeof(cmd), &p);
4041 get_arg(arg,
sizeof(arg), &p);
4043 if (val < 1 || val > 65536) {
4044 ERROR(
"Invalid_port: %s\n", arg);
4048 get_arg(arg,
sizeof(arg), &p);
4050 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);
4172 fsize = strtod(p1, &p1);
4173 switch(toupper(*p1)) {
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);
4489 get_arg(arg,
sizeof(arg), &p);
4493 get_arg(arg,
sizeof(arg), &p);
4507 get_arg(arg,
sizeof(arg), &p);
4513 get_arg(arg,
sizeof(arg), &p);
4516 ERROR(
"Invalid host/IP address: %s\n", arg);
4522 get_arg(arg,
sizeof(arg), &p);
4526 get_arg(arg,
sizeof(arg), &p);
4534 ERROR(
"No corresponding <Stream> for </Stream>\n");
4536 if (stream->
feed && stream->
fmt && strcmp(stream->
fmt->
name,
"ffm") != 0) {
4553 if (stream || feed || redirect) {
4554 ERROR(
"Already in a tag\n");
4557 *last_stream = redirect;
4558 last_stream = &redirect->
next;
4561 q = strrchr(redirect->
filename,
'>');
4571 ERROR(
"No corresponding <Redirect> for </Redirect>\n");
4574 ERROR(
"No URL found for <Redirect>\n");
4579 get_arg(arg,
sizeof(arg), &p);
4583 ERROR(
"Module support not compiled into this version: '%s'\n", arg);
4586 ERROR(
"Incorrect keyword: '%s'\n", cmd);
4603 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
4606 for (feed = first_feed; feed; feed = feed->
next) {
4607 if (feed->
pid == pid) {
4611 fprintf(stderr,
"%s: Pid %d exited with status %d after %d seconds\n", feed->
filename, pid, status, uptime);
4632 printf(
"usage: avserver [options]\n"
4633 "Hyper fast multi format Audio/Video streaming server\n");
4641 {
"d", 0, {(
void*)
opt_debug},
"enable debug mode" },
4648 struct sigaction sigact;
4662 unsetenv(
"http_proxy");
4666 memset(&sigact, 0,
sizeof(sigact));
4668 sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
4669 sigaction(SIGCHLD, &sigact, 0);
4672 fprintf(stderr,
"Incorrect config file - exiting.\n");
4699 }
else if (pid > 0) {
4706 open(
"/dev/null", O_RDWR);
4717 signal(SIGPIPE, SIG_IGN);
4723 http_log(
"Could not start server\n");