28 #define closesocket close
33 #include "libavformat/avformat.h"
44 #include "libavutil/avassert.h"
45 #include "libavutil/avstring.h"
46 #include "libavutil/lfg.h"
47 #include "libavutil/dict.h"
48 #include "libavutil/intreadwrite.h"
49 #include "libavutil/mathematics.h"
50 #include "libavutil/random_seed.h"
51 #include "libavutil/parseutils.h"
52 #include "libavutil/opt.h"
53 #include "libavutil/time.h"
58 #include <sys/ioctl.h>
108 #define MAX_STREAMS 20
110 #define IOBUFFER_INIT_SIZE 8192
113 #define HTTP_REQUEST_TIMEOUT (15 * 1000)
114 #define RTSP_REQUEST_TIMEOUT (3600 * 24 * 1000)
116 #define SYNC_TIMEOUT (10 * 1000)
299 struct in_addr my_ip);
303 FFStream *stream,
const char *session_id,
306 int stream_index,
struct sockaddr_in *dest_addr,
333 s += strspn(s,
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,. ");
343 if (lseek(fd, 8, SEEK_SET) < 0)
345 if (read(fd, buf, 8) != 8)
356 buf[i] = (pos >> (56 - i * 8)) & 0xff;
357 if (lseek(fd, 8, SEEK_SET) < 0)
359 if (write(fd, buf, 8) != 8)
374 static int resolve_host(
struct in_addr *sin_addr,
const char *hostname)
387 for (cur = ai; cur; cur = cur->
ai_next) {
389 *sin_addr = ((
struct sockaddr_in *)cur->
ai_addr)->sin_addr;
398 hp = gethostbyname(hostname);
401 memcpy(sin_addr, hp->h_addr_list[0],
sizeof(
struct in_addr));
415 p = buf2 + strlen(p) - 1;
423 static int print_prefix = 1;
430 print_prefix = strstr(fmt,
"\n") !=
NULL;
437 __attribute__ ((format (printf, 1, 2)))
442 va_start(vargs, fmt);
449 static int print_prefix = 1;
453 if (print_prefix && avc)
455 print_prefix = strstr(fmt,
"\n") !=
NULL;
464 http_log(
"%s - - [%s] \"%s %s\" %d %"PRId64
"\n",
497 for (; feed; feed = feed->
next) {
504 http_log(
"Unable to create children\n");
515 slash = strrchr(pathname,
'/');
520 strcpy(slash,
"ffmpeg");
528 for (i = 3; i < 256; i++)
532 if (!freopen(
"/dev/null",
"r", stdin))
533 http_log(
"failed to redirect STDIN to /dev/null\n;");
534 if (!freopen(
"/dev/null",
"w", stdout))
535 http_log(
"failed to redirect STDOUT to /dev/null\n;");
536 if (!freopen(
"/dev/null",
"w", stderr))
537 http_log(
"failed to redirect STDERR to /dev/null\n;");
540 signal(SIGPIPE, SIG_DFL);
555 server_fd = socket(AF_INET,SOCK_STREAM,0);
562 setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp,
sizeof(tmp));
564 my_addr->sin_family = AF_INET;
565 if (bind (server_fd, (
struct sockaddr *) my_addr,
sizeof (*my_addr)) < 0) {
567 snprintf(bindmsg,
sizeof(bindmsg),
"bind(port %d)", ntohs(my_addr->sin_port));
573 if (listen (server_fd, 5) < 0) {
589 struct sockaddr_in dest_addr = {0};
590 int default_port, stream_index;
593 for(stream = first_stream; stream !=
NULL; stream = stream->
next) {
598 snprintf(session_id,
sizeof(session_id),
"%08x%08x",
607 dest_addr.sin_family = AF_INET;
617 http_log(
"Could not open input stream for stream '%s'\n",
623 for(stream_index = 0; stream_index < stream->
nb_streams;
628 http_log(
"Could not open output stream '%s/streamid=%d'\n",
643 int server_fd = 0, rtsp_server_fd = 0;
644 int ret, delay, delay1;
645 struct pollfd *poll_table, *poll_entry;
661 if (rtsp_server_fd < 0)
665 if (!rtsp_server_fd && !server_fd) {
666 http_log(
"HTTP and RTSP disabled.\n");
677 poll_entry = poll_table;
679 poll_entry->fd = server_fd;
680 poll_entry->events = POLLIN;
683 if (rtsp_server_fd) {
684 poll_entry->fd = rtsp_server_fd;
685 poll_entry->events = POLLIN;
701 poll_entry->events = POLLOUT;
711 poll_entry->events = POLLOUT;
729 poll_entry->events = POLLIN;
742 ret = poll(poll_table, poll_entry - poll_table, delay);
756 for(c = first_http_ctx; c !=
NULL; c = c_next) {
765 poll_entry = poll_table;
768 if (poll_entry->revents & POLLIN)
772 if (rtsp_server_fd) {
774 if (poll_entry->revents & POLLIN)
799 "HTTP/1.0 503 Server too busy\r\n"
800 "Content-type: text/html\r\n"
802 "<html><head><title>Too busy</title></head><body>\r\n"
803 "<p>The server is too busy to serve your request at this time.</p>\r\n"
804 "<p>The number of current connections is %u, and this exceeds the limit of %u.</p>\r\n"
805 "</body></html>\r\n",
808 send(fd, buffer, len, 0);
814 struct sockaddr_in from_addr;
819 len =
sizeof(from_addr);
820 fd = accept(server_fd, (
struct sockaddr *)&from_addr,
823 http_log(
"error during accept %s\n", strerror(errno));
872 while ((*cp) !=
NULL) {
881 for(c1 = first_http_ctx; c1 !=
NULL; c1 = c1->
next) {
904 for(i=0;i<nb_streams;i++) {
961 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
974 }
else if (len == 0) {
981 if ((ptr >= c->
buffer + 2 && !memcmp(ptr-2,
"\n\n", 2)) ||
982 (ptr >= c->
buffer + 4 && !memcmp(ptr-4,
"\r\n\r\n", 4))) {
994 }
else goto read_loop;
999 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1037 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1052 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1061 if (c->
poll_entry->revents & (POLLIN | POLLERR | POLLHUP))
1068 if (c->
poll_entry->revents & (POLLERR | POLLHUP)) {
1094 if (c->
poll_entry->revents & (POLLERR | POLLHUP)) {
1132 for (p = request; *p && *p !=
'\r' && *p !=
'\n'; ) {
1134 const char *q = p + 7;
1145 memset(rates, 0xff, ratelen);
1148 while (*q && *q !=
'\n' && *q !=
':')
1151 if (sscanf(q,
":%d:%d", &stream_no, &rate_no) != 2)
1155 if (stream_no < ratelen && stream_no >= 0)
1156 rates[stream_no] = rate_no;
1165 p = strchr(p,
'\n');
1178 int best_bitrate = 100000000;
1196 if (feed_codec->
bit_rate <= bit_rate) {
1197 if (best_bitrate > bit_rate || feed_codec->
bit_rate > best_bitrate) {
1198 best_bitrate = feed_codec->
bit_rate;
1202 if (feed_codec->
bit_rate < best_bitrate) {
1203 best_bitrate = feed_codec->
bit_rate;
1216 int action_required = 0;
1244 action_required = 1;
1247 return action_required;
1256 while (*p ==
' ' || *p ==
'\t')
1261 static void get_word(
char *buf,
int buf_size,
const char **pp)
1270 if ((q - buf) < buf_size - 1)
1279 static void get_arg(
char *buf,
int buf_size,
const char **pp)
1289 if (*p ==
'\"' || *p ==
'\'')
1301 if ((q - buf) < buf_size - 1)
1306 if (quote && *p == quote)
1312 const char *p,
const char *filename,
int line_num)
1318 get_arg(arg,
sizeof(arg), &p);
1324 fprintf(stderr,
"%s:%d: ACL action '%s' is not ALLOW or DENY\n",
1325 filename, line_num, arg);
1329 get_arg(arg,
sizeof(arg), &p);
1332 fprintf(stderr,
"%s:%d: ACL refers to invalid host or ip address '%s'\n",
1333 filename, line_num, arg);
1338 get_arg(arg,
sizeof(arg), &p);
1342 fprintf(stderr,
"%s:%d: ACL refers to invalid host or ip address '%s'\n",
1343 filename, line_num, arg);
1356 naclp = &stream->
acl;
1362 fprintf(stderr,
"%s:%d: ACL found not in <stream> or <feed>\n",
1363 filename, line_num);
1369 naclp = &(*naclp)->
next;
1396 if (fgets(line,
sizeof(line), f) ==
NULL)
1402 if (*p ==
'\0' || *p ==
'#')
1404 get_arg(cmd,
sizeof(cmd), &p);
1430 struct in_addr *src = &c->
from_addr.sin_addr;
1431 unsigned long src_addr = src->s_addr;
1433 for (acl = in_acl; acl; acl = acl->
next) {
1434 if (src_addr >= acl->
first.s_addr && src_addr <= acl->last.s_addr)
1436 last_action = acl->
action;
1440 return (last_action ==
IP_DENY) ? 1 : 0;
1474 p = strrchr(file1,
'.');
1477 for(stream = first_stream; stream !=
NULL; stream = stream->
next) {
1479 p = strrchr(file2,
'.');
1482 if (!strcmp(file1, file2)) {
1505 char info[1024], filename[1024];
1509 const char *mime_type;
1513 const char *useragent = 0;
1519 if (!strcmp(cmd,
"GET"))
1521 else if (!strcmp(cmd,
"POST"))
1529 get_word(protocol,
sizeof(protocol), (
const char **)&p);
1530 if (strcmp(protocol,
"HTTP/1.0") && strcmp(protocol,
"HTTP/1.1"))
1536 http_log(
"%s - - New connection: %s %s\n", inet_ntoa(c->
from_addr.sin_addr), cmd, url);
1539 p1 = strchr(url,
'?');
1546 av_strlcpy(filename, url + ((*url ==
'/') ? 1 : 0),
sizeof(filename)-1);
1548 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1551 if (*useragent && *useragent !=
'\n' &&
av_isspace(*useragent))
1555 p = strchr(p,
'\n');
1565 filename[strlen(filename)-1] =
'f';
1572 strcpy(filename + strlen(filename)-2,
"m");
1582 if (!strlen(filename))
1583 av_strlcpy(filename,
"index.html",
sizeof(filename) - 1);
1586 while (stream !=
NULL) {
1589 stream = stream->
next;
1591 if (stream ==
NULL) {
1592 snprintf(msg,
sizeof(msg),
"File '%s' not found", url);
1593 http_log(
"File '%s' not found\n", url);
1605 "HTTP/1.0 301 Moved\r\n"
1607 "Content-type: text/html\r\n"
1609 "<html><head><title>Moved</title></head><body>\r\n"
1610 "You should be <a href=\"%s\">redirected</a>.\r\n"
1635 snprintf(msg,
sizeof(msg),
"This feed is already being received.");
1644 "HTTP/1.0 503 Server too busy\r\n"
1645 "Content-type: text/html\r\n"
1647 "<html><head><title>Too busy</title></head><body>\r\n"
1648 "<p>The server is too busy to serve your request at this time.</p>\r\n"
1649 "<p>The bandwidth being served (including your stream) is %"PRIu64
"kbit/sec, "
1650 "and this exceeds the limit of %"PRIu64
"kbit/sec.</p>\r\n"
1661 const char *hostinfo = 0;
1663 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1668 p = strchr(p,
'\n');
1682 eoh = strchr(hostinfo,
'\n');
1684 if (eoh[-1] ==
'\r')
1687 if (eoh - hostinfo <
sizeof(hostbuf) - 1) {
1688 memcpy(hostbuf, hostinfo, eoh - hostinfo);
1689 hostbuf[eoh - hostinfo] = 0;
1693 switch(redir_type) {
1696 "HTTP/1.0 200 ASX Follows\r\n"
1697 "Content-type: video/x-ms-asf\r\n"
1699 "<ASX Version=\"3\">\r\n"
1701 "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n"
1702 "</ASX>\r\n", hostbuf, filename, info);
1707 "HTTP/1.0 200 RAM Follows\r\n"
1708 "Content-type: audio/x-pn-realaudio\r\n"
1710 "# Autogenerated by ffserver\r\n"
1711 "http://%s/%s%s\r\n", hostbuf, filename, info);
1716 "HTTP/1.0 200 ASF Redirect follows\r\n"
1717 "Content-type: video/x-ms-asf\r\n"
1720 "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info);
1725 char hostname[256], *p;
1727 av_strlcpy(hostname, hostbuf,
sizeof(hostname));
1728 p = strrchr(hostname,
':');
1732 "HTTP/1.0 200 RTSP Redirect follows\r\n"
1734 "Content-type: application/x-rtsp\r\n"
1736 "rtsp://%s:%d/%s\r\n", hostname, ntohs(
my_rtsp_addr.sin_port), filename);
1745 struct sockaddr_in my_addr;
1748 "HTTP/1.0 200 OK\r\n"
1749 "Content-type: application/sdp\r\n"
1753 len =
sizeof(my_addr);
1754 getsockname(c->
fd, (
struct sockaddr *)&my_addr, &len);
1760 if (sdp_data_size > 0) {
1761 memcpy(q, sdp_data, sdp_data_size);
1782 snprintf(msg,
sizeof(msg),
"ASX/RAM file not handled");
1795 const char *logline = 0;
1798 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1804 client_id = strtol(p + 18, 0, 10);
1805 p = strchr(p,
'\n');
1813 char *eol = strchr(logline,
'\n');
1818 if (eol[-1] ==
'\r')
1820 http_log(
"%.*s\n", (
int) (eol - logline), logline);
1833 for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->
next) {
1842 snprintf(msg,
sizeof(msg),
"POST command not handled");
1847 snprintf(msg,
sizeof(msg),
"could not open feed");
1865 snprintf(msg,
sizeof(msg),
"Input stream corresponding to '%s' not found", url);
1874 mime_type =
"application/x-octet-stream";
1900 "HTTP/1.0 404 Not Found\r\n"
1901 "Content-type: text/html\r\n"
1904 "<head><title>404 Not Found</title></head>\n"
1923 static const char suffix[] =
" kMGTP";
1926 for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++);
1948 avio_printf(pb,
"Content-type: %s\r\n",
"text/html");
1959 avio_printf(pb,
"<table cellspacing=0 cellpadding=4>\n");
1960 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");
1962 while (stream !=
NULL) {
1963 char sfilename[1024];
1966 if (stream->
feed != stream) {
1968 eosf = sfilename + strlen(sfilename);
1969 if (eosf - sfilename >= 4) {
1970 if (strcmp(eosf - 4,
".asf") == 0)
1971 strcpy(eosf - 4,
".asx");
1972 else if (strcmp(eosf - 3,
".rm") == 0)
1973 strcpy(eosf - 3,
".ram");
1974 else if (stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
1978 eosf = strrchr(sfilename,
'.');
1980 eosf = sfilename + strlen(sfilename);
1982 strcpy(eosf,
".sdp");
1984 strcpy(eosf,
".rtsp");
1988 avio_printf(pb,
"<tr><td><a href=\"/%s\">%s</a> ",
1990 avio_printf(pb,
"<td align=right> %d <td align=right> ",
1995 int audio_bit_rate = 0;
1996 int video_bit_rate = 0;
1999 const char *audio_codec_name_extra =
"";
2000 const char *video_codec_name_extra =
"";
2009 if (*audio_codec_name)
2010 audio_codec_name_extra =
"...";
2011 audio_codec_name = codec->
name;
2017 if (*video_codec_name)
2018 video_codec_name_extra =
"...";
2019 video_codec_name = codec->
name;
2029 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",
2032 video_bit_rate / 1000, video_codec_name, video_codec_name_extra,
2033 audio_bit_rate / 1000, audio_codec_name, audio_codec_name_extra);
2042 avio_printf(pb,
"<td align=center> - <td align=right> - <td align=right> - <td><td align=right> - <td>\n");
2046 stream = stream->
next;
2051 while (stream !=
NULL) {
2052 if (stream->
feed == stream) {
2064 "ps -o \"%%cpu,cputime\" --no-headers %d",
2067 pid_stat = popen(ps_cmd,
"r");
2072 if (fscanf(pid_stat,
"%9s %63s", cpuperc,
2074 avio_printf(pb,
"Currently using %s%% of the cpu. Total time used %s.\n",
2084 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");
2089 const char *type =
"unknown";
2090 char parameters[64];
2107 avio_printf(pb,
"<tr><td align=right>%d<td>%s<td align=right>%d<td>%s<td>%s\n",
2113 stream = stream->
next;
2119 avio_printf(pb,
"Number of connections: %d / %d<br>\n",
2122 avio_printf(pb,
"Bandwidth in use: %"PRIu64
"k / %"PRIu64
"k<br>\n",
2126 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");
2129 while (c1 !=
NULL) {
2145 avio_printf(pb,
"<tr><td><b>%d</b><td>%s%s<td>%s<td>%s<td>%s<td align=right>",
2165 avio_printf(pb,
"<hr size=1 noshade>Generated at %s", p);
2178 int buf_size, i, ret;
2190 int prebuffer = strtol(buf, 0, 10);
2191 stream_pos =
av_gettime() - prebuffer * (int64_t)1000000;
2204 if (input_filename[0] ==
'\0')
2209 http_log(
"could not open %s: %d\n", input_filename, ret);
2219 http_log(
"Could not find stream info '%s'\n", input_filename);
2253 int bytes_left, bytes_sent, frame_bytes;
2256 if (frame_bytes <= 0)
2260 bytes_sent = frame_bytes - bytes_left;
2318 http_log(
"Error writing output header\n");
2352 }
else if (ret ==
AVERROR(EAGAIN)) {
2429 int max_packet_size;
2451 http_log(
"Error writing frame to output\n");
2537 int interleaved_index,
size;
2553 interleaved_index++;
2556 header[1] = interleaved_index;
2557 header[2] = len >> 8;
2629 http_log(
"Error opening feeder file: %s\n", strerror(errno));
2639 http_log(
"Error truncating feed file: %s\n", strerror(errno));
2644 http_log(
"Error reading write index from feed file: %s\n", strerror(errno));
2651 lseek(fd, 0, SEEK_SET);
2664 int len, loop_run = 0;
2677 }
else if (len == 0) {
2687 }
else if (++loop_run > 10) {
2703 }
else if (len == 0)
2715 if (c->
buffer[0] !=
'f' ||
2717 http_log(
"Feed stream has become desynchronized -- disconnecting\n");
2730 http_log(
"Error writing to feed file: %s\n", strerror(errno));
2745 http_log(
"Error writing index to feed file: %s\n", strerror(errno));
2750 for(c1 = first_http_ctx; c1 !=
NULL; c1 = c1->
next) {
2784 http_log(
"Feed '%s' stream number does not match registered feed\n",
2806 for(c1 = first_http_ctx; c1 !=
NULL; c1 = c1->
next) {
2824 switch(error_number) {
2829 str =
"Method Not Allowed";
2832 str =
"Not Enough Bandwidth";
2835 str =
"Session Not Found";
2838 str =
"Method Not Valid in This State";
2841 str =
"Aggregate operation not allowed";
2844 str =
"Only aggregate operation allowed";
2847 str =
"Unsupported transport";
2850 str =
"Internal Server Error";
2853 str =
"Service Unavailable";
2856 str =
"RTSP Version not supported";
2859 str =
"Unknown Error";
2863 avio_printf(c->
pb,
"RTSP/1.0 %d %s\r\n", error_number, str);
2869 strftime(buf2,
sizeof(buf2),
"%a, %d %b %Y %H:%M:%S", tm);
2881 const char *p, *p1, *p2;
2894 get_word(protocol,
sizeof(protocol), &p);
2907 if (strcmp(protocol,
"RTSP/1.0") != 0) {
2914 while (*p !=
'\n' && *p !=
'\0')
2918 while (*p !=
'\0') {
2919 p1 = memchr(p,
'\n', (
char *)c->
buffer_ptr - p);
2923 if (p2 > p && p2[-1] ==
'\r')
2929 if (len >
sizeof(line) - 1)
2930 len =
sizeof(line) - 1;
2931 memcpy(line, p, len);
2938 c->
seq = header->seq;
2940 if (!strcmp(cmd,
"DESCRIBE"))
2942 else if (!strcmp(cmd,
"OPTIONS"))
2944 else if (!strcmp(cmd,
"SETUP"))
2946 else if (!strcmp(cmd,
"PLAY"))
2948 else if (!strcmp(cmd,
"PAUSE"))
2950 else if (!strcmp(cmd,
"TEARDOWN"))
2969 struct in_addr my_ip)
2977 if (avc ==
NULL || !rtp_format) {
2982 stream->
title[0] ? stream->
title :
"No Title", 0);
2995 if (avc->
nb_streams >= INT_MAX/
sizeof(*avs) ||
3012 return strlen(*pbuffer);
3020 avio_printf(c->
pb,
"Public: %s\r\n",
"OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
3032 struct sockaddr_in my_addr;
3040 for(stream = first_stream; stream !=
NULL; stream = stream->
next) {
3042 stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp") &&
3055 len =
sizeof(my_addr);
3056 getsockname(c->
fd, (
struct sockaddr *)&my_addr, &len);
3058 if (content_length < 0) {
3065 avio_printf(c->
pb,
"Content-Length: %d\r\n", content_length);
3075 if (session_id[0] ==
'\0')
3078 for(c = first_http_ctx; c !=
NULL; c = c->
next) {
3102 int stream_index, rtp_port, rtcp_port;
3108 struct sockaddr_in dest_addr;
3118 for(stream = first_stream; stream !=
NULL; stream = stream->
next) {
3120 stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
3122 if (!strcmp(path, stream->
filename)) {
3131 for(stream_index = 0; stream_index < stream->
nb_streams;
3133 snprintf(buf,
sizeof(buf),
"%s/streamid=%d",
3135 if (!strcmp(path, buf))
3147 unsigned random0 =
av_lfg_get(&random_state);
3148 unsigned random1 =
av_lfg_get(&random_state);
3182 if (rtp_c->
stream != stream) {
3188 if (rtp_c->
rtp_ctx[stream_index]) {
3202 setup.transport_option[0] =
'\0';
3222 "client_port=%d-%d;server_port=%d-%d",
3224 rtp_port, rtcp_port);
3227 avio_printf(c->
pb,
"Transport: RTP/AVP/TCP;interleaved=%d-%d",
3228 stream_index * 2, stream_index * 2 + 1);
3233 if (setup.transport_option[0] !=
'\0')
3245 const char *session_id)
3264 snprintf(buf,
sizeof(buf),
"%s/streamid=%d",
3266 if(!strncmp(path, buf,
sizeof(buf))) {
3272 if (len > 0 && path[len - 1] ==
'/' &&
3354 FFStream *stream,
const char *session_id,
3358 const char *proto_str;
3387 proto_str =
"MCAST";
3420 int stream_index,
struct sockaddr_in *dest_addr,
3428 int max_packet_size;
3455 ipaddr = inet_ntoa(dest_addr->sin_addr);
3469 "rtp://%s:%d?multicast=1&ttl=%d",
3470 ipaddr, ntohs(dest_addr->sin_port), ttl);
3473 "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
3490 http_log(
"%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
3491 ipaddr, ntohs(dest_addr->sin_port),
3509 c->
rtp_ctx[stream_index] = ctx;
3593 while (*ps !=
NULL) {
3604 int mpeg4_count, i,
size;
3622 printf(
"MPEG4 without extra data: trying to find header in %s\n", infile->
filename);
3623 while (mpeg4_count > 0) {
3633 while (p < pkt.
data + pkt.
size - 4) {
3635 if (p[0] == 0x00 && p[1] == 0x00 &&
3636 p[2] == 0x01 && p[3] == 0xb6) {
3637 size = p - pkt.
data;
3659 for(stream = first_stream; stream !=
NULL; stream = stream_next) {
3661 stream_next = stream->
next;
3667 if (stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
3683 http_log(
"Could not find codec parameters from '%s'\n",
3706 for(stream = first_stream; stream !=
NULL; stream = stream->
next) {
3707 feed = stream->
feed;
3721 for(feed = first_feed; feed !=
NULL; feed = feed->
next_feed) {
3742 http_log(
"Index & Id do not match for stream %d (%s)\n",
3750 #define CHECK_CODEC(x) (ccf->x != ccs->x)
3753 http_log(
"Codecs do not match for stream %d\n", i);
3756 http_log(
"Codec bitrates do not match for stream %d\n", i);
3763 http_log(
"Codec width, height and framerate do not match for stream %d\n", i);
3770 http_log(
"Codec sample_rate, channels, frame_size do not match for stream %d\n", i);
3782 http_log(
"Deleting feed file '%s' as stream counts differ (%d != %d)\n",
3787 http_log(
"Deleting feed file '%s' as it appears to be corrupt\n",
3792 http_log(
"Unable to delete feed file '%s' as it is marked readonly\n",
3803 http_log(
"Unable to create feed file '%s' as it is marked readonly\n",
3810 http_log(
"Could not open output feed file '%s'\n",
3814 s->oformat = feed->
fmt;
3818 http_log(
"Container doesn't support the required parameters\n");
3828 http_log(
"Could not open output feed file '%s'\n",
3834 feed->
feed_size = lseek(fd, 0, SEEK_END);
3850 for(stream = first_stream; stream !=
NULL; stream = stream->
next) {
3863 stream->
bandwidth = (bandwidth + 999) / 1000;
3918 av->
rc_eq =
"tex^qComp";
3973 dll = dlopen(filename, RTLD_NOW);
3975 fprintf(stderr,
"Could not load module '%s' - %s\n",
3976 filename, dlerror());
3980 init_func = dlsym(dll,
"ffserver_module_init");
3983 "%s: init function 'ffserver_module_init()' not found\n",
4007 char filename[1000], tmp[1000], tmp2[1000],
line[1000];
4013 fprintf(stderr,
"File for preset '%s' not found\n", arg);
4018 int e= fscanf(f,
"%999[^\n]\n", line) - 1;
4019 if(line[0] ==
'#' && !e)
4021 e|= sscanf(line,
"%999[^=]=%999[^\n]\n", tmp, tmp2) - 2;
4023 fprintf(stderr,
"%s: Invalid syntax: '%s'\n", filename, line);
4027 if(!strcmp(tmp,
"acodec")){
4029 }
else if(!strcmp(tmp,
"vcodec")){
4031 }
else if(!strcmp(tmp,
"scodec")){
4034 fprintf(stderr,
"%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", filename, line, tmp, tmp2);
4046 const char *mime_type)
4052 char stream_format_name[64];
4054 snprintf(stream_format_name,
sizeof(stream_format_name),
"%s_stream", fmt->
name);
4068 fprintf(stderr,
"%s:%d: ", filename, line_num);
4069 vfprintf(stderr, fmt, vl);
4082 int val, errors, line_num;
4083 FFStream **last_stream, *stream, *redirect;
4088 f = fopen(filename,
"r");
4096 first_stream =
NULL;
4106 #define ERROR(...) report_config_error(filename, line_num, &errors, __VA_ARGS__)
4108 if (fgets(line,
sizeof(line), f) ==
NULL)
4114 if (*p ==
'\0' || *p ==
'#')
4117 get_arg(cmd,
sizeof(cmd), &p);
4120 get_arg(arg,
sizeof(arg), &p);
4122 if (val < 1 || val > 65536) {
4123 ERROR(
"Invalid_port: %s\n", arg);
4127 get_arg(arg,
sizeof(arg), &p);
4129 ERROR(
"%s:%d: Invalid host/IP address: %s\n", arg);
4134 get_arg(arg,
sizeof(arg), &p);
4136 if (val < 1 || val > 65536) {
4137 ERROR(
"%s:%d: Invalid port: %s\n", arg);
4141 get_arg(arg,
sizeof(arg), &p);
4143 ERROR(
"Invalid host/IP address: %s\n", arg);
4146 get_arg(arg,
sizeof(arg), &p);
4148 if (val < 1 || val > 65536) {
4149 ERROR(
"Invalid MaxHTTPConnections: %s\n", arg);
4153 get_arg(arg,
sizeof(arg), &p);
4156 ERROR(
"Invalid MaxClients: %s\n", arg);
4162 get_arg(arg,
sizeof(arg), &p);
4164 if (llval < 10 || llval > 10000000) {
4165 ERROR(
"Invalid MaxBandwidth: %s\n", arg);
4175 if (stream || feed) {
4176 ERROR(
"Already in a tag\n");
4184 for (s = first_feed; s; s = s->
next) {
4199 *last_stream = feed;
4200 last_stream = &feed->
next;
4211 for (i = 0; i < 62; i++) {
4212 get_arg(arg,
sizeof(arg), &p);
4220 (
my_http_addr.sin_addr.s_addr == INADDR_ANY) ?
"127.0.0.1" :
4228 }
else if (stream) {
4238 get_arg(arg,
sizeof(arg), &p);
4246 get_arg(arg,
sizeof(arg), &p);
4254 fsize *= 1024 * 1024;
4257 fsize *= 1024 * 1024 * 1024;
4267 ERROR(
"No corresponding <Feed> for </Feed>\n");
4274 if (stream || feed) {
4275 ERROR(
"Already in a tag\n");
4280 q = strrchr(stream->
filename,
'>');
4284 for (s = first_stream; s; s = s->
next) {
4301 *last_stream = stream;
4302 last_stream = &stream->
next;
4305 get_arg(arg,
sizeof(arg), &p);
4310 while (sfeed !=
NULL) {
4316 ERROR(
"feed '%s' not defined\n", arg);
4318 stream->
feed = sfeed;
4321 get_arg(arg,
sizeof(arg), &p);
4323 if (!strcmp(arg,
"status")) {
4329 if (!strcmp(arg,
"jpeg"))
4330 strcpy(arg,
"mjpeg");
4333 ERROR(
"Unknown Format: %s\n", arg);
4342 get_arg(arg,
sizeof(arg), &p);
4345 if (!stream->
ifmt) {
4346 ERROR(
"Unknown input format: %s\n", arg);
4353 ERROR(
"FaviconURL only permitted for status streams\n");
4368 get_arg(arg,
sizeof(arg), &p);
4375 get_arg(arg,
sizeof(arg), &p);
4378 ERROR(
"Unknown AudioCodec: %s\n", arg);
4381 get_arg(arg,
sizeof(arg), &p);
4384 ERROR(
"Unknown VideoCodec: %s\n", arg);
4387 get_arg(arg,
sizeof(arg), &p);
4389 stream->
max_time = atof(arg) * 1000;
4391 get_arg(arg,
sizeof(arg), &p);
4395 get_arg(arg,
sizeof(arg), &p);
4399 get_arg(arg,
sizeof(arg), &p);
4403 get_arg(arg,
sizeof(arg), &p);
4409 int minrate, maxrate;
4411 get_arg(arg,
sizeof(arg), &p);
4413 if (sscanf(arg,
"%d-%d", &minrate, &maxrate) == 2) {
4417 ERROR(
"Incorrect format for VideoBitRateRange -- should be <min>-<max>: %s\n", arg);
4422 get_arg(arg,
sizeof(arg), &p);
4423 video_enc.
debug = strtol(arg,0,0);
4427 get_arg(arg,
sizeof(arg), &p);
4432 get_arg(arg,
sizeof(arg), &p);
4437 get_arg(arg,
sizeof(arg), &p);
4441 get_arg(arg,
sizeof(arg), &p);
4443 video_enc.
bit_rate = atoi(arg) * 1000;
4446 get_arg(arg,
sizeof(arg), &p);
4449 if ((video_enc.
width % 16) != 0 ||
4450 (video_enc.
height % 16) != 0) {
4451 ERROR(
"Image size must be a multiple of 16\n");
4455 get_arg(arg,
sizeof(arg), &p);
4459 ERROR(
"Incorrect frame rate: %s\n", arg);
4466 get_arg(arg,
sizeof(arg), &p);
4485 get_arg(arg,
sizeof(arg), &p);
4486 get_arg(arg2,
sizeof(arg2), &p);
4495 ERROR(
"AVOption error: %s %s\n", arg, arg2);
4501 get_arg(arg,
sizeof(arg), &p);
4512 ERROR(
"AVPreset error: %s\n", arg);
4515 get_arg(arg,
sizeof(arg), &p);
4516 if ((strlen(arg) == 4) && stream)
4528 get_arg(arg,
sizeof(arg), &p);
4534 get_arg(arg,
sizeof(arg), &p);
4538 ERROR(
"VideoQDiff out of range\n");
4542 get_arg(arg,
sizeof(arg), &p);
4544 video_enc.
qmax = atoi(arg);
4545 if (video_enc.
qmax < 1 || video_enc.
qmax > 31) {
4546 ERROR(
"VideoQMax out of range\n");
4550 get_arg(arg,
sizeof(arg), &p);
4552 video_enc.
qmin = atoi(arg);
4553 if (video_enc.
qmin < 1 || video_enc.
qmin > 31) {
4554 ERROR(
"VideoQMin out of range\n");
4558 get_arg(arg,
sizeof(arg), &p);
4560 video_enc.luma_elim_threshold = atoi(arg);
4562 get_arg(arg,
sizeof(arg), &p);
4564 video_enc.chroma_elim_threshold = atoi(arg);
4566 get_arg(arg,
sizeof(arg), &p);
4570 get_arg(arg,
sizeof(arg), &p);
4584 get_arg(arg,
sizeof(arg), &p);
4590 get_arg(arg,
sizeof(arg), &p);
4593 ERROR(
"Invalid host/IP address: %s\n", arg);
4599 get_arg(arg,
sizeof(arg), &p);
4603 get_arg(arg,
sizeof(arg), &p);
4611 ERROR(
"No corresponding <Stream> for </Stream>\n");
4613 if (stream->
feed && stream->
fmt && strcmp(stream->
fmt->
name,
"ffm") != 0) {
4630 if (stream || feed || redirect) {
4631 ERROR(
"Already in a tag\n");
4634 *last_stream = redirect;
4635 last_stream = &redirect->
next;
4638 q = strrchr(redirect->
filename,
'>');
4648 ERROR(
"No corresponding <Redirect> for </Redirect>\n");
4651 ERROR(
"No URL found for <Redirect>\n");
4656 get_arg(arg,
sizeof(arg), &p);
4660 ERROR(
"Module support not compiled into this version: '%s'\n", arg);
4663 ERROR(
"Incorrect keyword: '%s'\n", cmd);
4680 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
4683 for (feed = first_feed; feed; feed = feed->
next) {
4684 if (feed->
pid == pid) {
4688 fprintf(stderr,
"%s: Pid %d exited with status %d after %d seconds\n", feed->
filename, pid, status, uptime);
4708 printf(
"usage: ffserver [options]\n"
4709 "Hyper fast multi format Audio/Video streaming server\n");
4717 {
"d", 0, {(
void*)
opt_debug},
"enable debug mode" },
4724 struct sigaction sigact = { { 0 } };
4736 unsetenv(
"http_proxy");
4741 sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
4742 sigaction(SIGCHLD, &sigact, 0);
4745 fprintf(stderr,
"Incorrect config file - exiting.\n");
4765 signal(SIGPIPE, SIG_IGN);
4768 http_log(
"Could not start server\n");