28 #define closesocket close
60 #include <sys/ioctl.h>
107 #define MAX_STREAMS 20
109 #define IOBUFFER_INIT_SIZE 8192
112 #define HTTP_REQUEST_TIMEOUT (15 * 1000)
113 #define RTSP_REQUEST_TIMEOUT (3600 * 24 * 1000)
115 #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,
328 s += strspn(s,
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,. ");
338 if (lseek(fd, 8, SEEK_SET) < 0)
340 if (read(fd, buf, 8) != 8)
351 buf[i] = (pos >> (56 - i * 8)) & 0xff;
352 if (lseek(fd, 8, SEEK_SET) < 0)
354 if (write(fd, buf, 8) != 8)
369 static int resolve_host(
struct in_addr *sin_addr,
const char *hostname)
382 for (cur = ai; cur; cur = cur->
ai_next) {
384 *sin_addr = ((
struct sockaddr_in *)cur->
ai_addr)->sin_addr;
393 hp = gethostbyname(hostname);
396 memcpy(sin_addr, hp->h_addr_list[0],
sizeof(
struct in_addr));
402 static char *
ctime1(
char *buf2,
int buf_size)
410 p = buf2 + strlen(p) - 1;
418 static int print_prefix = 1;
425 print_prefix = strstr(fmt,
"\n") != NULL;
432 __attribute__ ((format (printf, 1, 2)))
437 va_start(vargs, fmt);
444 static int print_prefix = 1;
448 if (print_prefix && avc)
450 print_prefix = strstr(fmt,
"\n") != NULL;
459 http_log(
"%s - - [%s] \"%s %s\" %d %"PRId64
"\n",
492 for (; feed; feed = feed->
next) {
499 http_log(
"Unable to create children\n");
511 slash = strrchr(pathname,
'/');
516 strcpy(slash,
"ffmpeg");
524 for (i = 3; i < 256; i++)
528 if (!freopen(
"/dev/null",
"r", stdin))
529 http_log(
"failed to redirect STDIN to /dev/null\n;");
530 if (!freopen(
"/dev/null",
"w", stdout))
531 http_log(
"failed to redirect STDOUT to /dev/null\n;");
532 if (!freopen(
"/dev/null",
"w", stderr))
533 http_log(
"failed to redirect STDERR to /dev/null\n;");
536 signal(SIGPIPE, SIG_DFL);
551 server_fd = socket(AF_INET,SOCK_STREAM,0);
558 setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp,
sizeof(tmp));
560 my_addr->sin_family = AF_INET;
561 if (bind (server_fd, (
struct sockaddr *) my_addr,
sizeof (*my_addr)) < 0) {
563 snprintf(bindmsg,
sizeof(bindmsg),
"bind(port %d)", ntohs(my_addr->sin_port));
569 if (listen (server_fd, 5) < 0) {
585 struct sockaddr_in dest_addr = {0};
586 int default_port, stream_index;
589 for(stream = first_stream; stream != NULL; stream = stream->
next) {
594 snprintf(session_id,
sizeof(session_id),
"%08x%08x",
603 dest_addr.sin_family = AF_INET;
613 http_log(
"Could not open input stream for stream '%s'\n",
619 for(stream_index = 0; stream_index < stream->
nb_streams;
624 http_log(
"Could not open output stream '%s/streamid=%d'\n",
638 int server_fd = 0, rtsp_server_fd = 0;
640 struct pollfd *poll_table, *poll_entry;
656 if (rtsp_server_fd < 0)
660 if (!rtsp_server_fd && !server_fd) {
661 http_log(
"HTTP and RTSP disabled.\n");
672 poll_entry = poll_table;
674 poll_entry->fd = server_fd;
675 poll_entry->events = POLLIN;
678 if (rtsp_server_fd) {
679 poll_entry->fd = rtsp_server_fd;
680 poll_entry->events = POLLIN;
696 poll_entry->events = POLLOUT;
707 poll_entry->events = POLLOUT;
725 poll_entry->events = POLLIN;
738 ret = poll(poll_table, poll_entry - poll_table, delay);
752 for(c = first_http_ctx; c != NULL; c = c_next) {
761 poll_entry = poll_table;
764 if (poll_entry->revents & POLLIN)
768 if (rtsp_server_fd) {
770 if (poll_entry->revents & POLLIN)
795 "HTTP/1.0 503 Server too busy\r\n"
796 "Content-type: text/html\r\n"
798 "<html><head><title>Too busy</title></head><body>\r\n"
799 "<p>The server is too busy to serve your request at this time.</p>\r\n"
800 "<p>The number of current connections is %u, and this exceeds the limit of %u.</p>\r\n"
801 "</body></html>\r\n",
804 send(fd, buffer, len, 0);
810 struct sockaddr_in from_addr;
815 len =
sizeof(from_addr);
816 fd = accept(server_fd, (
struct sockaddr *)&from_addr,
819 http_log(
"error during accept %s\n", strerror(errno));
868 while ((*cp) != NULL) {
877 for(c1 = first_http_ctx; c1 != NULL; c1 = c1->
next) {
900 for(i=0;i<nb_streams;i++) {
957 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
970 }
else if (len == 0) {
977 if ((ptr >= c->
buffer + 2 && !memcmp(ptr-2,
"\n\n", 2)) ||
978 (ptr >= c->
buffer + 4 && !memcmp(ptr-4,
"\r\n\r\n", 4))) {
990 }
else goto read_loop;
995 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1032 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1047 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1056 if (c->
poll_entry->revents & (POLLIN | POLLERR | POLLHUP))
1063 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1085 if (c->
poll_entry->revents & (POLLERR | POLLHUP)) {
1127 for (p = request; *p && *p !=
'\r' && *p !=
'\n'; ) {
1129 const char *q = p + 7;
1140 memset(rates, 0xff, ratelen);
1143 while (*q && *q !=
'\n' && *q !=
':')
1146 if (sscanf(q,
":%d:%d", &stream_no, &rate_no) != 2)
1150 if (stream_no < ratelen && stream_no >= 0)
1151 rates[stream_no] = rate_no;
1160 p = strchr(p,
'\n');
1173 int best_bitrate = 100000000;
1191 if (feed_codec->
bit_rate <= bit_rate) {
1192 if (best_bitrate > bit_rate || feed_codec->
bit_rate > best_bitrate) {
1193 best_bitrate = feed_codec->
bit_rate;
1197 if (feed_codec->
bit_rate < best_bitrate) {
1198 best_bitrate = feed_codec->
bit_rate;
1211 int action_required = 0;
1239 action_required = 1;
1242 return action_required;
1251 while (*p ==
' ' || *p ==
'\t')
1265 if ((q - buf) < buf_size - 1)
1284 if (*p ==
'\"' || *p ==
'\'')
1296 if ((q - buf) < buf_size - 1)
1301 if (quote && *p == quote)
1307 const char *p,
const char *filename,
int line_num)
1313 get_arg(arg,
sizeof(arg), &p);
1319 fprintf(stderr,
"%s:%d: ACL action '%s' is not ALLOW or DENY\n",
1320 filename, line_num, arg);
1324 get_arg(arg,
sizeof(arg), &p);
1327 fprintf(stderr,
"%s:%d: ACL refers to invalid host or ip address '%s'\n",
1328 filename, line_num, arg);
1333 get_arg(arg,
sizeof(arg), &p);
1337 fprintf(stderr,
"%s:%d: ACL refers to invalid host or ip address '%s'\n",
1338 filename, line_num, arg);
1351 naclp = &stream->
acl;
1357 fprintf(stderr,
"%s:%d: ACL found not in <stream> or <feed>\n",
1358 filename, line_num);
1364 naclp = &(*naclp)->
next;
1391 if (fgets(line,
sizeof(line), f) == NULL)
1397 if (*p ==
'\0' || *p ==
'#')
1399 get_arg(cmd,
sizeof(cmd), &p);
1426 unsigned long src_addr = src->s_addr;
1428 for (acl = in_acl; acl; acl = acl->
next) {
1429 if (src_addr >= acl->
first.s_addr && src_addr <= acl->last.s_addr)
1431 last_action = acl->
action;
1435 return (last_action ==
IP_DENY) ? 1 : 0;
1469 p = strrchr(file1,
'.');
1472 for(stream = first_stream; stream != NULL; stream = stream->
next) {
1474 p = strrchr(file2,
'.');
1477 if (!strcmp(file1, file2)) {
1500 char info[1024], filename[1024];
1504 const char *mime_type;
1508 const char *useragent = 0;
1514 if (!strcmp(cmd,
"GET"))
1516 else if (!strcmp(cmd,
"POST"))
1524 get_word(protocol,
sizeof(protocol), (
const char **)&p);
1525 if (strcmp(protocol,
"HTTP/1.0") && strcmp(protocol,
"HTTP/1.1"))
1531 http_log(
"%s - - New connection: %s %s\n", inet_ntoa(c->
from_addr.sin_addr), cmd, url);
1534 p1 = strchr(url,
'?');
1541 av_strlcpy(filename, url + ((*url ==
'/') ? 1 : 0),
sizeof(filename)-1);
1543 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1546 if (*useragent && *useragent !=
'\n' &&
av_isspace(*useragent))
1550 p = strchr(p,
'\n');
1560 filename[strlen(filename)-1] =
'f';
1567 strcpy(filename + strlen(filename)-2,
"m");
1577 if (!strlen(filename))
1578 av_strlcpy(filename,
"index.html",
sizeof(filename) - 1);
1581 while (stream != NULL) {
1584 stream = stream->
next;
1586 if (stream == NULL) {
1587 snprintf(msg,
sizeof(msg),
"File '%s' not found", url);
1588 http_log(
"File '%s' not found\n", url);
1600 "HTTP/1.0 301 Moved\r\n"
1602 "Content-type: text/html\r\n"
1604 "<html><head><title>Moved</title></head><body>\r\n"
1605 "You should be <a href=\"%s\">redirected</a>.\r\n"
1630 snprintf(msg,
sizeof(msg),
"This feed is already being received.");
1639 "HTTP/1.0 503 Server too busy\r\n"
1640 "Content-type: text/html\r\n"
1642 "<html><head><title>Too busy</title></head><body>\r\n"
1643 "<p>The server is too busy to serve your request at this time.</p>\r\n"
1644 "<p>The bandwidth being served (including your stream) is %"PRIu64
"kbit/sec, "
1645 "and this exceeds the limit of %"PRIu64
"kbit/sec.</p>\r\n"
1656 const char *hostinfo = 0;
1658 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1663 p = strchr(p,
'\n');
1677 eoh = strchr(hostinfo,
'\n');
1679 if (eoh[-1] ==
'\r')
1682 if (eoh - hostinfo <
sizeof(hostbuf) - 1) {
1683 memcpy(hostbuf, hostinfo, eoh - hostinfo);
1684 hostbuf[eoh - hostinfo] = 0;
1688 switch(redir_type) {
1691 "HTTP/1.0 200 ASX Follows\r\n"
1692 "Content-type: video/x-ms-asf\r\n"
1694 "<ASX Version=\"3\">\r\n"
1696 "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n"
1697 "</ASX>\r\n", hostbuf, filename, info);
1702 "HTTP/1.0 200 RAM Follows\r\n"
1703 "Content-type: audio/x-pn-realaudio\r\n"
1705 "# Autogenerated by ffserver\r\n"
1706 "http://%s/%s%s\r\n", hostbuf, filename, info);
1711 "HTTP/1.0 200 ASF Redirect follows\r\n"
1712 "Content-type: video/x-ms-asf\r\n"
1715 "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info);
1720 char hostname[256], *p;
1722 av_strlcpy(hostname, hostbuf,
sizeof(hostname));
1723 p = strrchr(hostname,
':');
1727 "HTTP/1.0 200 RTSP Redirect follows\r\n"
1729 "Content-type: application/x-rtsp\r\n"
1731 "rtsp://%s:%d/%s\r\n", hostname, ntohs(
my_rtsp_addr.sin_port), filename);
1740 struct sockaddr_in my_addr;
1743 "HTTP/1.0 200 OK\r\n"
1744 "Content-type: application/sdp\r\n"
1748 len =
sizeof(my_addr);
1749 getsockname(c->
fd, (
struct sockaddr *)&my_addr, &len);
1755 if (sdp_data_size > 0) {
1756 memcpy(q, sdp_data, sdp_data_size);
1777 snprintf(msg,
sizeof(msg),
"ASX/RAM file not handled");
1790 const char *logline = 0;
1793 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1799 client_id = strtol(p + 18, 0, 10);
1800 p = strchr(p,
'\n');
1808 char *eol = strchr(logline,
'\n');
1813 if (eol[-1] ==
'\r')
1815 http_log(
"%.*s\n", (
int) (eol - logline), logline);
1828 for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->
next) {
1837 snprintf(msg,
sizeof(msg),
"POST command not handled");
1842 snprintf(msg,
sizeof(msg),
"could not open feed");
1860 snprintf(msg,
sizeof(msg),
"Input stream corresponding to '%s' not found", url);
1869 mime_type =
"application/x-octet-stream";
1895 "HTTP/1.0 404 Not Found\r\n"
1896 "Content-type: text/html\r\n"
1899 "<head><title>404 Not Found</title></head>\n"
1918 static const char suffix[] =
" kMGTP";
1921 for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++);
1954 avio_printf(pb,
"<table cellspacing=0 cellpadding=4>\n");
1955 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");
1957 while (stream != NULL) {
1958 char sfilename[1024];
1961 if (stream->
feed != stream) {
1963 eosf = sfilename + strlen(sfilename);
1964 if (eosf - sfilename >= 4) {
1965 if (strcmp(eosf - 4,
".asf") == 0)
1966 strcpy(eosf - 4,
".asx");
1967 else if (strcmp(eosf - 3,
".rm") == 0)
1968 strcpy(eosf - 3,
".ram");
1969 else if (stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
1973 eosf = strrchr(sfilename,
'.');
1975 eosf = sfilename + strlen(sfilename);
1977 strcpy(eosf,
".sdp");
1979 strcpy(eosf,
".rtsp");
1983 avio_printf(pb,
"<tr><td><a href=\"/%s\">%s</a> ",
1985 avio_printf(pb,
"<td align=right> %d <td align=right> ",
1990 int audio_bit_rate = 0;
1991 int video_bit_rate = 0;
1994 const char *audio_codec_name_extra =
"";
1995 const char *video_codec_name_extra =
"";
2004 if (*audio_codec_name)
2005 audio_codec_name_extra =
"...";
2006 audio_codec_name = codec->
name;
2012 if (*video_codec_name)
2013 video_codec_name_extra =
"...";
2014 video_codec_name = codec->
name;
2024 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",
2027 video_bit_rate / 1000, video_codec_name, video_codec_name_extra,
2028 audio_bit_rate / 1000, audio_codec_name, audio_codec_name_extra);
2037 avio_printf(pb,
"<td align=center> - <td align=right> - <td align=right> - <td><td align=right> - <td>\n");
2041 stream = stream->
next;
2046 while (stream != NULL) {
2047 if (stream->
feed == stream) {
2059 "ps -o \"%%cpu,cputime\" --no-headers %d",
2062 pid_stat = popen(ps_cmd,
"r");
2067 if (fscanf(pid_stat,
"%9s %63s", cpuperc,
2069 avio_printf(pb,
"Currently using %s%% of the cpu. Total time used %s.\n",
2079 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");
2084 const char *
type =
"unknown";
2085 char parameters[64];
2102 avio_printf(pb,
"<tr><td align=right>%d<td>%s<td align=right>%d<td>%s<td>%s\n",
2108 stream = stream->
next;
2114 avio_printf(pb,
"Number of connections: %d / %d<br>\n",
2117 avio_printf(pb,
"Bandwidth in use: %"PRIu64
"k / %"PRIu64
"k<br>\n",
2121 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");
2124 while (c1 != NULL) {
2140 avio_printf(pb,
"<tr><td><b>%d</b><td>%s%s<td>%s<td>%s<td>%s<td align=right>",
2160 avio_printf(pb,
"<hr size=1 noshade>Generated at %s", p);
2173 int buf_size, i,
ret;
2183 http_log(
"Invalid date specification '%s' for stream\n", buf);
2187 int prebuffer = strtol(buf, 0, 10);
2188 stream_pos =
av_gettime() - prebuffer * (int64_t)1000000;
2197 http_log(
"Invalid date specification '%s' for stream\n", buf);
2203 if (!input_filename[0]) {
2204 http_log(
"No filename was specified for stream\n");
2221 http_log(
"Could not find stream info for input '%s'\n", input_filename);
2255 int bytes_left, bytes_sent, frame_bytes;
2258 if (frame_bytes <= 0)
2262 bytes_sent = frame_bytes - bytes_left;
2318 http_log(
"Error writing output header for stream '%s': %s\n",
2353 }
else if (ret ==
AVERROR(EAGAIN)) {
2430 int max_packet_size;
2452 http_log(
"Error writing frame to output for stream '%s': %s\n",
2539 int interleaved_index,
size;
2555 interleaved_index++;
2558 header[1] = interleaved_index;
2559 header[2] = len >> 8;
2637 http_log(
"Could not open feed file '%s': %s\n",
2649 http_log(
"Error truncating feed file '%s': %s\n",
2656 http_log(
"Error reading write index from feed file '%s': %s\n",
2666 lseek(fd, 0, SEEK_SET);
2679 int len, loop_run = 0;
2692 }
else if (len == 0) {
2702 }
else if (++loop_run > 10) {
2718 }
else if (len == 0)
2730 if (c->
buffer[0] !=
'f' ||
2732 http_log(
"Feed stream has become desynchronized -- disconnecting\n");
2745 http_log(
"Error writing to feed file: %s\n", strerror(errno));
2760 http_log(
"Error writing index to feed file: %s\n", strerror(errno));
2765 for(c1 = first_http_ctx; c1 != NULL; c1 = c1->
next) {
2786 0, NULL, NULL, NULL, NULL);
2799 http_log(
"Feed '%s' stream number does not match registered feed\n",
2821 for(c1 = first_http_ctx; c1 != NULL; c1 = c1->
next) {
2839 switch(error_number) {
2844 str =
"Method Not Allowed";
2847 str =
"Not Enough Bandwidth";
2850 str =
"Session Not Found";
2853 str =
"Method Not Valid in This State";
2856 str =
"Aggregate operation not allowed";
2859 str =
"Only aggregate operation allowed";
2862 str =
"Unsupported transport";
2865 str =
"Internal Server Error";
2868 str =
"Service Unavailable";
2871 str =
"RTSP Version not supported";
2874 str =
"Unknown Error";
2878 avio_printf(c->
pb,
"RTSP/1.0 %d %s\r\n", error_number, str);
2884 strftime(buf2,
sizeof(buf2),
"%a, %d %b %Y %H:%M:%S", tm);
2896 const char *p, *p1, *p2;
2909 get_word(protocol,
sizeof(protocol), &p);
2922 if (strcmp(protocol,
"RTSP/1.0") != 0) {
2929 while (*p !=
'\n' && *p !=
'\0')
2933 while (*p !=
'\0') {
2934 p1 = memchr(p,
'\n', (
char *)c->
buffer_ptr - p);
2938 if (p2 > p && p2[-1] ==
'\r')
2944 if (len >
sizeof(line) - 1)
2945 len =
sizeof(line) - 1;
2946 memcpy(line, p, len);
2955 if (!strcmp(cmd,
"DESCRIBE"))
2957 else if (!strcmp(cmd,
"OPTIONS"))
2959 else if (!strcmp(cmd,
"SETUP"))
2961 else if (!strcmp(cmd,
"PLAY"))
2963 else if (!strcmp(cmd,
"PAUSE"))
2965 else if (!strcmp(cmd,
"TEARDOWN"))
2984 struct in_addr my_ip)
2993 if (avc == NULL || !rtp_format) {
2998 entry ? entry->
value :
"No Title", 0);
3011 if (avc->
nb_streams >= INT_MAX/
sizeof(*avs) ||
3028 return strlen(*pbuffer);
3036 avio_printf(c->
pb,
"Public: %s\r\n",
"OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
3048 struct sockaddr_in my_addr;
3051 av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1,
sizeof(path1), url);
3056 for(stream = first_stream; stream != NULL; stream = stream->
next) {
3058 stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp") &&
3071 len =
sizeof(my_addr);
3072 getsockname(c->
fd, (
struct sockaddr *)&my_addr, &len);
3074 if (content_length < 0) {
3081 avio_printf(c->
pb,
"Content-Length: %d\r\n", content_length);
3091 if (session_id[0] ==
'\0')
3094 for(c = first_http_ctx; c != NULL; c = c->
next) {
3118 int stream_index, rtp_port, rtcp_port;
3124 struct sockaddr_in dest_addr;
3128 av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1,
sizeof(path1), url);
3134 for(stream = first_stream; stream != NULL; stream = stream->
next) {
3136 stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
3138 if (!strcmp(path, stream->
filename)) {
3147 for(stream_index = 0; stream_index < stream->
nb_streams;
3149 snprintf(buf,
sizeof(buf),
"%s/streamid=%d",
3151 if (!strcmp(path, buf))
3163 unsigned random0 =
av_lfg_get(&random_state);
3164 unsigned random1 =
av_lfg_get(&random_state);
3198 if (rtp_c->
stream != stream) {
3204 if (rtp_c->
rtp_ctx[stream_index]) {
3218 setup.transport_option[0] =
'\0';
3238 "client_port=%d-%d;server_port=%d-%d",
3240 rtp_port, rtcp_port);
3243 avio_printf(c->
pb,
"Transport: RTP/AVP/TCP;interleaved=%d-%d",
3244 stream_index * 2, stream_index * 2 + 1);
3249 if (setup.transport_option[0] !=
'\0')
3261 const char *session_id)
3274 av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1,
sizeof(path1), url);
3280 snprintf(buf,
sizeof(buf),
"%s/streamid=%d",
3282 if(!strncmp(path, buf,
sizeof(buf))) {
3288 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),
3510 c->
rtp_ctx[stream_index] = ctx;
3594 while (*ps != NULL) {
3605 int mpeg4_count, i,
size;
3623 printf(
"MPEG4 without extra data: trying to find header in %s\n", infile->
filename);
3624 while (mpeg4_count > 0) {
3634 while (p < pkt.
data + pkt.
size - 4) {
3636 if (p[0] == 0x00 && p[1] == 0x00 &&
3637 p[2] == 0x01 && p[3] == 0xb6) {
3638 size = p - pkt.
data;
3660 for(stream = first_stream; stream != NULL; stream = stream_next) {
3662 stream_next = stream->
next;
3668 if (stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
3689 http_log(
"Could not find codec parameters from '%s'\n",
3712 for(stream = first_stream; stream != NULL; stream = stream->
next) {
3713 feed = stream->
feed;
3727 for(feed = first_feed; feed != NULL; feed = feed->
next_feed) {
3748 http_log(
"Index & Id do not match for stream %d (%s)\n",
3756 #define CHECK_CODEC(x) (ccf->x != ccs->x)
3759 http_log(
"Codecs do not match for stream %d\n", i);
3762 http_log(
"Codec bitrates do not match for stream %d\n", i);
3769 http_log(
"Codec width, height and framerate do not match for stream %d\n", i);
3776 http_log(
"Codec sample_rate, channels, frame_size do not match for stream %d\n", i);
3788 http_log(
"Deleting feed file '%s' as stream counts differ (%d != %d)\n",
3793 http_log(
"Deleting feed file '%s' as it appears to be corrupt\n",
3798 http_log(
"Unable to delete feed file '%s' as it is marked readonly\n",
3809 http_log(
"Unable to create feed file '%s' as it is marked readonly\n",
3816 http_log(
"Could not open output feed file '%s'\n",
3824 http_log(
"Container doesn't support the required parameters\n");
3837 http_log(
"Could not open output feed file '%s'\n",
3843 feed->
feed_size = lseek(fd, 0, SEEK_END);
3859 for(stream = first_stream; stream != NULL; stream = stream->
next) {
3872 stream->
bandwidth = (bandwidth + 999) / 1000;
3959 if (!codec || codec->
type != type)
3979 char filename[1000], tmp[1000], tmp2[1000],
line[1000];
3984 codec ? codec->
name : NULL))) {
3985 fprintf(stderr,
"File for preset '%s' not found\n", arg);
3990 int e= fscanf(f,
"%999[^\n]\n", line) - 1;
3991 if(line[0] ==
'#' && !e)
3993 e|= sscanf(line,
"%999[^=]=%999[^\n]\n", tmp, tmp2) - 2;
3995 fprintf(stderr,
"%s: Invalid syntax: '%s'\n", filename, line);
3999 if(!strcmp(tmp,
"acodec")){
4001 }
else if(!strcmp(tmp,
"vcodec")){
4003 }
else if(!strcmp(tmp,
"scodec")){
4006 fprintf(stderr,
"%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", filename, line, tmp, tmp2);
4023 char stream_format_name[64];
4025 snprintf(stream_format_name,
sizeof(stream_format_name),
"%s_stream", fmt->
name);
4039 av_log(NULL, log_level,
"%s:%d: ", filename, line_num);
4040 av_vlog(NULL, log_level, fmt, vl);
4051 char arg[1024], arg2[1024];
4053 int val, errors, warnings, line_num;
4054 FFStream **last_stream, *stream, *redirect;
4060 f = fopen(filename,
"r");
4063 av_log(NULL,
AV_LOG_ERROR,
"Could not open the configuration file '%s'\n", filename);
4067 errors = warnings = 0;
4069 first_stream = NULL;
4078 #define ERROR(...) report_config_error(filename, line_num, AV_LOG_ERROR, &errors, __VA_ARGS__)
4079 #define WARNING(...) report_config_error(filename, line_num, AV_LOG_WARNING, &warnings, __VA_ARGS__)
4082 if (fgets(line,
sizeof(line), f) == NULL)
4088 if (*p ==
'\0' || *p ==
'#')
4091 get_arg(cmd,
sizeof(cmd), &p);
4094 get_arg(arg,
sizeof(arg), &p);
4096 if (val < 1 || val > 65536) {
4097 ERROR(
"Invalid_port: %s\n", arg);
4101 get_arg(arg,
sizeof(arg), &p);
4103 ERROR(
"%s:%d: Invalid host/IP address: %s\n", arg);
4106 WARNING(
"NoDaemon option has no effect, you should remove it\n");
4108 get_arg(arg,
sizeof(arg), &p);
4110 if (val < 1 || val > 65536) {
4111 ERROR(
"%s:%d: Invalid port: %s\n", arg);
4115 get_arg(arg,
sizeof(arg), &p);
4117 ERROR(
"Invalid host/IP address: %s\n", arg);
4120 get_arg(arg,
sizeof(arg), &p);
4122 if (val < 1 || val > 65536) {
4123 ERROR(
"Invalid MaxHTTPConnections: %s\n", arg);
4127 get_arg(arg,
sizeof(arg), &p);
4130 ERROR(
"Invalid MaxClients: %s\n", arg);
4136 get_arg(arg,
sizeof(arg), &p);
4137 llval = strtoll(arg, NULL, 10);
4138 if (llval < 10 || llval > 10000000) {
4139 ERROR(
"Invalid MaxBandwidth: %s\n", arg);
4149 if (stream || feed) {
4150 ERROR(
"Already in a tag\n");
4162 for (s = first_feed;
s; s = s->
next) {
4177 *last_stream = feed;
4178 last_stream = &feed->
next;
4192 for (i = 0; i < 62; i++) {
4193 get_arg(arg,
sizeof(arg), &p);
4206 (
my_http_addr.sin_addr.s_addr == INADDR_ANY) ?
"127.0.0.1" :
4218 }
else if (stream) {
4223 get_arg(arg,
sizeof(arg), &p);
4228 WARNING(
"Truncate N syntax in configuration file is deprecated, "
4229 "use Truncate alone with no arguments\n");
4238 get_arg(arg,
sizeof(arg), &p);
4246 fsize *= 1024 * 1024;
4249 fsize *= 1024 * 1024 * 1024;
4259 ERROR(
"No corresponding <Feed> for </Feed>\n");
4266 if (stream || feed) {
4267 ERROR(
"Already in a tag\n");
4276 q = strrchr(stream->
filename,
'>');
4280 for (s = first_stream;
s; s = s->
next) {
4297 *last_stream = stream;
4298 last_stream = &stream->
next;
4301 get_arg(arg,
sizeof(arg), &p);
4306 while (sfeed != NULL) {
4312 ERROR(
"Feed with name '%s' for stream '%s' is not defined\n", arg, stream->
filename);
4314 stream->
feed = sfeed;
4317 get_arg(arg,
sizeof(arg), &p);
4319 if (!strcmp(arg,
"status")) {
4325 if (!strcmp(arg,
"jpeg"))
4326 strcpy(arg,
"mjpeg");
4329 ERROR(
"Unknown Format: %s\n", arg);
4338 get_arg(arg,
sizeof(arg), &p);
4341 if (!stream->
ifmt) {
4342 ERROR(
"Unknown input format: %s\n", arg);
4349 ERROR(
"FaviconURL only permitted for status streams\n");
4355 get_arg(arg,
sizeof(arg), &p);
4361 for (i = 0; i < strlen(cmd); i++)
4364 WARNING(
"'%s' option in configuration file is deprecated, "
4365 "use 'Metadata %s VALUE' instead\n", cmd, key);
4367 ERROR(
"Could not set metadata '%s' to value '%s': %s\n",
4372 get_arg(arg,
sizeof(arg), &p);
4373 get_arg(arg2,
sizeof(arg2), &p);
4377 ERROR(
"Could not set metadata '%s' to value '%s': %s\n",
4382 get_arg(arg,
sizeof(arg), &p);
4389 get_arg(arg,
sizeof(arg), &p);
4392 ERROR(
"Unknown AudioCodec: %s\n", arg);
4395 get_arg(arg,
sizeof(arg), &p);
4398 ERROR(
"Unknown VideoCodec: %s\n", arg);
4401 get_arg(arg,
sizeof(arg), &p);
4403 stream->
max_time = atof(arg) * 1000;
4405 get_arg(arg,
sizeof(arg), &p);
4409 get_arg(arg,
sizeof(arg), &p);
4413 get_arg(arg,
sizeof(arg), &p);
4418 int minrate, maxrate;
4420 get_arg(arg,
sizeof(arg), &p);
4422 if (sscanf(arg,
"%d-%d", &minrate, &maxrate) == 2) {
4426 ERROR(
"Incorrect format for VideoBitRateRange -- should be <min>-<max>: %s\n", arg);
4431 get_arg(arg,
sizeof(arg), &p);
4432 video_enc.
debug = strtol(arg,0,0);
4436 get_arg(arg,
sizeof(arg), &p);
4441 get_arg(arg,
sizeof(arg), &p);
4446 get_arg(arg,
sizeof(arg), &p);
4450 get_arg(arg,
sizeof(arg), &p);
4452 video_enc.
bit_rate = atoi(arg) * 1000;
4455 get_arg(arg,
sizeof(arg), &p);
4459 ERROR(
"Invalid video size '%s'\n", arg);
4461 if ((video_enc.
width % 16) != 0 ||
4462 (video_enc.
height % 16) != 0) {
4463 ERROR(
"Image size must be a multiple of 16\n");
4468 get_arg(arg,
sizeof(arg), &p);
4472 ERROR(
"Incorrect frame rate: %s\n", arg);
4479 get_arg(arg,
sizeof(arg), &p);
4483 ERROR(
"Unknown pixel format: %s\n", arg);
4487 get_arg(arg,
sizeof(arg), &p);
4505 get_arg(arg,
sizeof(arg), &p);
4506 get_arg(arg2,
sizeof(arg2), &p);
4515 ERROR(
"Error setting %s option to %s %s\n", cmd, arg, arg2);
4521 get_arg(arg,
sizeof(arg), &p);
4532 ERROR(
"AVPreset error: %s\n", arg);
4535 get_arg(arg,
sizeof(arg), &p);
4536 if ((strlen(arg) == 4) && stream)
4548 get_arg(arg,
sizeof(arg), &p);
4554 get_arg(arg,
sizeof(arg), &p);
4558 ERROR(
"VideoQDiff out of range\n");
4562 get_arg(arg,
sizeof(arg), &p);
4564 video_enc.
qmax = atoi(arg);
4565 if (video_enc.
qmax < 1 || video_enc.
qmax > 31) {
4566 ERROR(
"VideoQMax out of range\n");
4570 get_arg(arg,
sizeof(arg), &p);
4572 video_enc.
qmin = atoi(arg);
4573 if (video_enc.
qmin < 1 || video_enc.
qmin > 31) {
4574 ERROR(
"VideoQMin out of range\n");
4578 get_arg(arg,
sizeof(arg), &p);
4582 get_arg(arg,
sizeof(arg), &p);
4596 get_arg(arg,
sizeof(arg), &p);
4602 get_arg(arg,
sizeof(arg), &p);
4605 ERROR(
"Invalid host/IP address: %s\n", arg);
4611 get_arg(arg,
sizeof(arg), &p);
4615 get_arg(arg,
sizeof(arg), &p);
4623 ERROR(
"No corresponding <Stream> for </Stream>\n");
4625 if (stream->
feed && stream->
fmt && strcmp(stream->
fmt->
name,
"ffm") != 0) {
4642 if (stream || feed || redirect) {
4643 ERROR(
"Already in a tag\n");
4650 *last_stream = redirect;
4651 last_stream = &redirect->
next;
4654 q = strrchr(redirect->
filename,
'>');
4664 ERROR(
"No corresponding <Redirect> for </Redirect>\n");
4667 ERROR(
"No URL found for <Redirect>\n");
4672 ERROR(
"Loadable modules no longer supported\n");
4674 ERROR(
"Incorrect keyword: '%s'\n", cmd);
4694 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
4697 for (feed = first_feed; feed; feed = feed->
next) {
4698 if (feed->
pid == pid) {
4702 fprintf(stderr,
"%s: Pid %d exited with status %d after %d seconds\n", feed->
filename, pid, status, uptime);
4722 printf(
"usage: ffserver [options]\n"
4723 "Hyper fast multi format Audio/Video streaming server\n");
4731 {
"d", 0, {(
void*)
opt_debug},
"enable debug mode" },
4738 struct sigaction sigact = { { 0 } };
4753 unsetenv(
"http_proxy");
4758 sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
4759 sigaction(SIGCHLD, &sigact, 0);
4762 fprintf(stderr,
"Error reading configuration file '%s': %s\n",
4784 signal(SIGPIPE, SIG_IGN);
4787 http_log(
"Could not start server\n");