28 #define closesocket close
63 #include <sys/ioctl.h>
110 #define MAX_STREAMS 20
112 #define IOBUFFER_INIT_SIZE 8192
115 #define HTTP_REQUEST_TIMEOUT (15 * 1000)
116 #define RTSP_REQUEST_TIMEOUT (3600 * 24 * 1000)
118 #define SYNC_TIMEOUT (10 * 1000)
297 struct in_addr my_ip);
301 FFStream *stream,
const char *session_id,
304 int stream_index,
struct sockaddr_in *dest_addr,
331 s += strspn(s,
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,. ");
341 if (lseek(fd, 8, SEEK_SET) < 0)
343 if (read(fd, buf, 8) != 8)
354 buf[i] = (pos >> (56 - i * 8)) & 0xff;
355 if (lseek(fd, 8, SEEK_SET) < 0)
357 if (write(fd, buf, 8) != 8)
372 static int resolve_host(
struct in_addr *sin_addr,
const char *hostname)
385 for (cur = ai; cur; cur = cur->
ai_next) {
387 *sin_addr = ((
struct sockaddr_in *)cur->
ai_addr)->sin_addr;
396 hp = gethostbyname(hostname);
399 memcpy(sin_addr, hp->h_addr_list[0],
sizeof(
struct in_addr));
405 static char *
ctime1(
char *buf2,
int buf_size)
413 p = buf2 + strlen(p) - 1;
421 static int print_prefix = 1;
428 print_prefix = strstr(fmt,
"\n") != NULL;
435 __attribute__ ((format (printf, 1, 2)))
440 va_start(vargs, fmt);
447 static int print_prefix = 1;
451 if (print_prefix && avc)
453 print_prefix = strstr(fmt,
"\n") != NULL;
462 http_log(
"%s - - [%s] \"%s %s\" %d %"PRId64
"\n",
495 for (; feed; feed = feed->
next) {
502 http_log(
"Unable to create children\n");
514 slash = strrchr(pathname,
'/');
519 strcpy(slash,
"ffmpeg");
527 for (i = 3; i < 256; i++)
531 if (!freopen(
"/dev/null",
"r", stdin))
532 http_log(
"failed to redirect STDIN to /dev/null\n;");
533 if (!freopen(
"/dev/null",
"w", stdout))
534 http_log(
"failed to redirect STDOUT to /dev/null\n;");
535 if (!freopen(
"/dev/null",
"w", stderr))
536 http_log(
"failed to redirect STDERR to /dev/null\n;");
539 signal(SIGPIPE, SIG_DFL);
554 server_fd = socket(AF_INET,SOCK_STREAM,0);
561 if (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) {
591 struct sockaddr_in dest_addr = {0};
592 int default_port, stream_index;
595 for(stream = first_stream; stream; stream = stream->
next) {
600 snprintf(session_id,
sizeof(session_id),
"%08x%08x",
609 dest_addr.sin_family = AF_INET;
619 http_log(
"Could not open input stream for stream '%s'\n",
625 for(stream_index = 0; stream_index < stream->
nb_streams;
630 http_log(
"Could not open output stream '%s/streamid=%d'\n",
644 int server_fd = 0, rtsp_server_fd = 0;
646 struct pollfd *poll_table, *poll_entry;
664 if (rtsp_server_fd < 0) {
671 if (!rtsp_server_fd && !server_fd) {
672 http_log(
"HTTP and RTSP disabled.\n");
684 poll_entry = poll_table;
686 poll_entry->fd = server_fd;
687 poll_entry->events = POLLIN;
690 if (rtsp_server_fd) {
691 poll_entry->fd = rtsp_server_fd;
692 poll_entry->events = POLLIN;
708 poll_entry->events = POLLOUT;
719 poll_entry->events = POLLOUT;
737 poll_entry->events = POLLIN;
750 ret = poll(poll_table, poll_entry - poll_table, delay);
766 for(c = first_http_ctx;
c; c = c_next) {
775 poll_entry = poll_table;
778 if (poll_entry->revents & POLLIN)
782 if (rtsp_server_fd) {
784 if (poll_entry->revents & POLLIN)
809 "HTTP/1.0 503 Server too busy\r\n"
810 "Content-type: text/html\r\n"
812 "<html><head><title>Too busy</title></head><body>\r\n"
813 "<p>The server is too busy to serve your request at this time.</p>\r\n"
814 "<p>The number of current connections is %u, and this exceeds the limit of %u.</p>\r\n"
815 "</body></html>\r\n",
818 if (send(fd, buffer, len, 0) < len)
825 struct sockaddr_in from_addr;
830 len =
sizeof(from_addr);
831 fd = accept(server_fd, (
struct sockaddr *)&from_addr,
834 http_log(
"error during accept %s\n", strerror(errno));
893 for(c1 = first_http_ctx;
c1; c1 = c1->
next) {
973 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
986 }
else if (len == 0) {
993 if ((ptr >= c->
buffer + 2 && !memcmp(ptr-2,
"\n\n", 2)) ||
994 (ptr >= c->
buffer + 4 && !memcmp(ptr-4,
"\r\n\r\n", 4))) {
1006 }
else goto read_loop;
1011 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1048 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1063 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1072 if (c->
poll_entry->revents & (POLLIN | POLLERR | POLLHUP))
1079 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1101 if (c->
poll_entry->revents & (POLLERR | POLLHUP)) {
1143 for (p = request; *p && *p !=
'\r' && *p !=
'\n'; ) {
1145 const char *q = p + 7;
1156 memset(rates, 0xff, ratelen);
1159 while (*q && *q !=
'\n' && *q !=
':')
1162 if (sscanf(q,
":%d:%d", &stream_no, &rate_no) != 2)
1166 if (stream_no < ratelen && stream_no >= 0)
1167 rates[stream_no] = rate_no;
1176 p = strchr(p,
'\n');
1189 int best_bitrate = 100000000;
1207 if (feed_codec->
bit_rate <= bit_rate) {
1208 if (best_bitrate > bit_rate || feed_codec->
bit_rate > best_bitrate) {
1209 best_bitrate = feed_codec->
bit_rate;
1213 if (feed_codec->
bit_rate < best_bitrate) {
1214 best_bitrate = feed_codec->
bit_rate;
1227 int action_required = 0;
1255 action_required = 1;
1258 return action_required;
1270 if ((q - buf) < buf_size - 1)
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;
1397 if (fgets(line,
sizeof(line), f) == NULL)
1403 if (*p ==
'\0' || *p ==
'#')
1405 get_arg(cmd,
sizeof(cmd), &p);
1432 unsigned long src_addr = src->s_addr;
1434 for (acl = in_acl; acl; acl = acl->
next) {
1435 if (src_addr >= acl->
first.s_addr && src_addr <= acl->last.s_addr)
1437 last_action = acl->
action;
1441 return (last_action ==
IP_DENY) ? 1 : 0;
1475 p = strrchr(file1,
'.');
1478 for(stream = first_stream; stream; stream = stream->
next) {
1480 p = strrchr(file2,
'.');
1483 if (!strcmp(file1, file2)) {
1506 char info[1024], filename[1024];
1510 const char *mime_type;
1514 const char *useragent = 0;
1520 if (!strcmp(cmd,
"GET"))
1522 else if (!strcmp(cmd,
"POST"))
1530 get_word(protocol,
sizeof(protocol), (
const char **)&p);
1531 if (strcmp(protocol,
"HTTP/1.0") && strcmp(protocol,
"HTTP/1.1"))
1537 http_log(
"%s - - New connection: %s %s\n", inet_ntoa(c->
from_addr.sin_addr), cmd, url);
1540 p1 = strchr(url,
'?');
1547 av_strlcpy(filename, url + ((*url ==
'/') ? 1 : 0),
sizeof(filename)-1);
1549 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1552 if (*useragent && *useragent !=
'\n' &&
av_isspace(*useragent))
1556 p = strchr(p,
'\n');
1566 filename[strlen(filename)-1] =
'f';
1573 strcpy(filename + strlen(filename)-2,
"m");
1583 if (!strlen(filename))
1584 av_strlcpy(filename,
"index.html",
sizeof(filename) - 1);
1590 stream = stream->
next;
1593 snprintf(msg,
sizeof(msg),
"File '%s' not found", url);
1594 http_log(
"File '%s' not found\n", url);
1606 "HTTP/1.0 301 Moved\r\n"
1608 "Content-type: text/html\r\n"
1610 "<html><head><title>Moved</title></head><body>\r\n"
1611 "You should be <a href=\"%s\">redirected</a>.\r\n"
1636 snprintf(msg,
sizeof(msg),
"This feed is already being received.");
1645 "HTTP/1.0 503 Server too busy\r\n"
1646 "Content-type: text/html\r\n"
1648 "<html><head><title>Too busy</title></head><body>\r\n"
1649 "<p>The server is too busy to serve your request at this time.</p>\r\n"
1650 "<p>The bandwidth being served (including your stream) is %"PRIu64
"kbit/sec, "
1651 "and this exceeds the limit of %"PRIu64
"kbit/sec.</p>\r\n"
1662 const char *hostinfo = 0;
1664 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1669 p = strchr(p,
'\n');
1683 eoh = strchr(hostinfo,
'\n');
1685 if (eoh[-1] ==
'\r')
1688 if (eoh - hostinfo <
sizeof(hostbuf) - 1) {
1689 memcpy(hostbuf, hostinfo, eoh - hostinfo);
1690 hostbuf[eoh - hostinfo] = 0;
1694 switch(redir_type) {
1697 "HTTP/1.0 200 ASX Follows\r\n"
1698 "Content-type: video/x-ms-asf\r\n"
1700 "<ASX Version=\"3\">\r\n"
1702 "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n"
1703 "</ASX>\r\n", hostbuf, filename, info);
1708 "HTTP/1.0 200 RAM Follows\r\n"
1709 "Content-type: audio/x-pn-realaudio\r\n"
1711 "# Autogenerated by ffserver\r\n"
1712 "http://%s/%s%s\r\n", hostbuf, filename, info);
1717 "HTTP/1.0 200 ASF Redirect follows\r\n"
1718 "Content-type: video/x-ms-asf\r\n"
1721 "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info);
1726 char hostname[256], *p;
1728 av_strlcpy(hostname, hostbuf,
sizeof(hostname));
1729 p = strrchr(hostname,
':');
1733 "HTTP/1.0 200 RTSP Redirect follows\r\n"
1735 "Content-type: application/x-rtsp\r\n"
1737 "rtsp://%s:%d/%s\r\n", hostname, ntohs(
my_rtsp_addr.sin_port), filename);
1746 struct sockaddr_in my_addr;
1749 "HTTP/1.0 200 OK\r\n"
1750 "Content-type: application/sdp\r\n"
1754 len =
sizeof(my_addr);
1757 if (getsockname(c->
fd, (
struct sockaddr *)&my_addr, &len))
1758 http_log(
"getsockname() failed\n");
1764 if (sdp_data_size > 0) {
1765 memcpy(q, sdp_data, sdp_data_size);
1786 snprintf(msg,
sizeof(msg),
"ASX/RAM file not handled");
1799 const char *logline = 0;
1802 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1808 client_id = strtol(p + 18, 0, 10);
1809 p = strchr(p,
'\n');
1817 char *eol = strchr(logline,
'\n');
1822 if (eol[-1] ==
'\r')
1824 http_log(
"%.*s\n", (
int) (eol - logline), logline);
1837 for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->
next) {
1846 snprintf(msg,
sizeof(msg),
"POST command not handled");
1851 snprintf(msg,
sizeof(msg),
"could not open feed");
1869 snprintf(msg,
sizeof(msg),
"Input stream corresponding to '%s' not found", url);
1878 mime_type =
"application/x-octet-stream";
1904 "HTTP/1.0 404 Not Found\r\n"
1905 "Content-type: text/html\r\n"
1908 "<head><title>404 Not Found</title></head>\n"
1927 static const char suffix[] =
" kMGTP";
1930 for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++);
1963 avio_printf(pb,
"<table cellspacing=0 cellpadding=4>\n");
1964 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");
1967 char sfilename[1024];
1970 if (stream->
feed != stream) {
1972 eosf = sfilename + strlen(sfilename);
1973 if (eosf - sfilename >= 4) {
1974 if (strcmp(eosf - 4,
".asf") == 0)
1975 strcpy(eosf - 4,
".asx");
1976 else if (strcmp(eosf - 3,
".rm") == 0)
1977 strcpy(eosf - 3,
".ram");
1978 else if (stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
1982 eosf = strrchr(sfilename,
'.');
1984 eosf = sfilename + strlen(sfilename);
1986 strcpy(eosf,
".sdp");
1988 strcpy(eosf,
".rtsp");
1992 avio_printf(pb,
"<tr><td><a href=\"/%s\">%s</a> ",
1994 avio_printf(pb,
"<td align=right> %d <td align=right> ",
1999 int audio_bit_rate = 0;
2000 int video_bit_rate = 0;
2003 const char *audio_codec_name_extra =
"";
2004 const char *video_codec_name_extra =
"";
2013 if (*audio_codec_name)
2014 audio_codec_name_extra =
"...";
2015 audio_codec_name = codec->
name;
2021 if (*video_codec_name)
2022 video_codec_name_extra =
"...";
2023 video_codec_name = codec->
name;
2033 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",
2036 video_bit_rate / 1000, video_codec_name, video_codec_name_extra,
2037 audio_bit_rate / 1000, audio_codec_name, audio_codec_name_extra);
2046 avio_printf(pb,
"<td align=center> - <td align=right> - <td align=right> - <td><td align=right> - <td>\n");
2050 stream = stream->
next;
2056 if (stream->
feed == stream) {
2068 "ps -o \"%%cpu,cputime\" --no-headers %d",
2071 pid_stat = popen(ps_cmd,
"r");
2076 if (fscanf(pid_stat,
"%9s %63s", cpuperc,
2078 avio_printf(pb,
"Currently using %s%% of the cpu. Total time used %s.\n",
2088 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");
2093 const char *
type =
"unknown";
2094 char parameters[64];
2111 avio_printf(pb,
"<tr><td align=right>%d<td>%s<td align=right>%d<td>%s<td>%s\n",
2117 stream = stream->
next;
2123 avio_printf(pb,
"Number of connections: %d / %d<br>\n",
2126 avio_printf(pb,
"Bandwidth in use: %"PRIu64
"k / %"PRIu64
"k<br>\n",
2130 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");
2149 avio_printf(pb,
"<tr><td><b>%d</b><td>%s%s<td>%s<td>%s<td>%s<td align=right>",
2169 avio_printf(pb,
"<hr size=1 noshade>Generated at %s", p);
2182 int buf_size, i,
ret;
2192 http_log(
"Invalid date specification '%s' for stream\n", buf);
2196 int prebuffer = strtol(buf, 0, 10);
2197 stream_pos =
av_gettime() - prebuffer * (int64_t)1000000;
2206 http_log(
"Invalid date specification '%s' for stream\n", buf);
2212 if (!input_filename[0]) {
2213 http_log(
"No filename was specified for stream\n");
2230 http_log(
"Could not find stream info for input '%s'\n", input_filename);
2264 int bytes_left, bytes_sent, frame_bytes;
2267 if (frame_bytes <= 0)
2271 bytes_sent = frame_bytes - bytes_left;
2327 http_log(
"Error writing output header for stream '%s': %s\n",
2362 }
else if (ret ==
AVERROR(EAGAIN)) {
2439 int max_packet_size;
2461 http_log(
"Error writing frame to output for stream '%s': %s\n",
2548 int interleaved_index,
size;
2564 interleaved_index++;
2567 header[1] = interleaved_index;
2568 header[2] = len >> 8;
2646 http_log(
"Could not open feed file '%s': %s\n",
2658 http_log(
"Error truncating feed file '%s': %s\n",
2665 http_log(
"Error reading write index from feed file '%s': %s\n",
2675 lseek(fd, 0, SEEK_SET);
2688 int len, loop_run = 0;
2701 }
else if (len == 0) {
2711 }
else if (++loop_run > 10) {
2727 }
else if (len == 0)
2739 if (c->
buffer[0] !=
'f' ||
2741 http_log(
"Feed stream has become desynchronized -- disconnecting\n");
2757 http_log(
"Error writing to feed file: %s\n", strerror(errno));
2772 http_log(
"Error writing index to feed file: %s\n", strerror(errno));
2777 for(c1 = first_http_ctx;
c1; c1 = c1->
next) {
2798 0, NULL, NULL, NULL, NULL);
2811 http_log(
"Feed '%s' stream number does not match registered feed\n",
2833 for(c1 = first_http_ctx;
c1; c1 = c1->
next) {
2853 str =
"Unknown Error";
2855 avio_printf(c->
pb,
"RTSP/1.0 %d %s\r\n", error_number, str);
2861 strftime(buf2,
sizeof(buf2),
"%a, %d %b %Y %H:%M:%S", tm);
2873 const char *p, *p1, *p2;
2886 get_word(protocol,
sizeof(protocol), &p);
2899 if (strcmp(protocol,
"RTSP/1.0") != 0) {
2906 while (*p !=
'\n' && *p !=
'\0')
2910 while (*p !=
'\0') {
2911 p1 = memchr(p,
'\n', (
char *)c->
buffer_ptr - p);
2915 if (p2 > p && p2[-1] ==
'\r')
2921 if (len >
sizeof(line) - 1)
2922 len =
sizeof(line) - 1;
2923 memcpy(line, p, len);
2932 if (!strcmp(cmd,
"DESCRIBE"))
2934 else if (!strcmp(cmd,
"OPTIONS"))
2936 else if (!strcmp(cmd,
"SETUP"))
2938 else if (!strcmp(cmd,
"PLAY"))
2940 else if (!strcmp(cmd,
"PAUSE"))
2942 else if (!strcmp(cmd,
"TEARDOWN"))
2961 struct in_addr my_ip)
2972 if (!avc || !rtp_format) {
2977 entry ? entry->
value :
"No Title", 0);
2990 if (avc->
nb_streams >= INT_MAX/
sizeof(*avs) ||
3007 return *pbuffer ? strlen(*pbuffer) :
AVERROR(ENOMEM);
3015 avio_printf(c->
pb,
"Public: %s\r\n",
"OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
3027 struct sockaddr_in my_addr;
3030 av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1,
sizeof(path1), url);
3035 for(stream = first_stream; stream; stream = stream->
next) {
3037 stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp") &&
3050 len =
sizeof(my_addr);
3051 getsockname(c->
fd, (
struct sockaddr *)&my_addr, &len);
3053 if (content_length < 0) {
3060 avio_printf(c->
pb,
"Content-Length: %d\r\n", content_length);
3070 if (session_id[0] ==
'\0')
3073 for(c = first_http_ctx;
c; c = c->
next) {
3097 int stream_index, rtp_port, rtcp_port;
3103 struct sockaddr_in dest_addr;
3107 av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1,
sizeof(path1), url);
3113 for(stream = first_stream; stream; stream = stream->
next) {
3115 stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
3117 if (!strcmp(path, stream->
filename)) {
3126 for(stream_index = 0; stream_index < stream->
nb_streams;
3128 snprintf(buf,
sizeof(buf),
"%s/streamid=%d",
3130 if (!strcmp(path, buf))
3142 unsigned random0 =
av_lfg_get(&random_state);
3143 unsigned random1 =
av_lfg_get(&random_state);
3177 if (rtp_c->
stream != stream) {
3183 if (rtp_c->
rtp_ctx[stream_index]) {
3197 setup.transport_option[0] =
'\0';
3217 "client_port=%d-%d;server_port=%d-%d",
3219 rtp_port, rtcp_port);
3222 avio_printf(c->
pb,
"Transport: RTP/AVP/TCP;interleaved=%d-%d",
3223 stream_index * 2, stream_index * 2 + 1);
3228 if (setup.transport_option[0] !=
'\0')
3240 const char *session_id)
3253 av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1,
sizeof(path1), url);
3259 snprintf(buf,
sizeof(buf),
"%s/streamid=%d",
3261 if(!strncmp(path, buf,
sizeof(buf))) {
3267 if (len > 0 && path[len - 1] ==
'/' &&
3333 FFStream *stream,
const char *session_id,
3337 const char *proto_str;
3366 proto_str =
"MCAST";
3399 int stream_index,
struct sockaddr_in *dest_addr,
3407 int max_packet_size;
3434 ipaddr = inet_ntoa(dest_addr->sin_addr);
3448 "rtp://%s:%d?multicast=1&ttl=%d",
3449 ipaddr, ntohs(dest_addr->sin_port), ttl);
3452 "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
3469 http_log(
"%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
3470 ipaddr, ntohs(dest_addr->sin_port),
3490 c->
rtp_ctx[stream_index] = ctx;
3585 int mpeg4_count, i,
size;
3603 printf(
"MPEG4 without extra data: trying to find header in %s\n", infile->
filename);
3604 while (mpeg4_count > 0) {
3614 while (p < pkt.
data + pkt.
size - 4) {
3616 if (p[0] == 0x00 && p[1] == 0x00 &&
3617 p[2] == 0x01 && p[3] == 0xb6) {
3618 size = p - pkt.
data;
3640 for(stream = first_stream; stream; stream = stream_next) {
3642 stream_next = stream->
next;
3648 if (stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
3669 http_log(
"Could not find codec parameters from '%s'\n",
3692 for(stream = first_stream; stream; stream = stream->
next) {
3693 feed = stream->
feed;
3707 for(feed = first_feed; feed; feed = feed->
next_feed) {
3728 http_log(
"Index & Id do not match for stream %d (%s)\n",
3736 #define CHECK_CODEC(x) (ccf->x != ccs->x)
3739 http_log(
"Codecs do not match for stream %d\n", i);
3742 http_log(
"Codec bitrates do not match for stream %d\n", i);
3749 http_log(
"Codec width, height and framerate do not match for stream %d\n", i);
3756 http_log(
"Codec sample_rate, channels, frame_size do not match for stream %d\n", i);
3768 http_log(
"Deleting feed file '%s' as stream counts differ (%d != %d)\n",
3773 http_log(
"Deleting feed file '%s' as it appears to be corrupt\n",
3778 http_log(
"Unable to delete feed file '%s' as it is marked readonly\n",
3789 http_log(
"Unable to create feed file '%s' as it is marked readonly\n",
3796 http_log(
"Could not open output feed file '%s'\n",
3804 http_log(
"Container doesn't support the required parameters\n");
3817 http_log(
"Could not open output feed file '%s'\n",
3823 feed->
feed_size = lseek(fd, 0, SEEK_END);
3839 for(stream = first_stream; stream; stream = stream->
next) {
3852 stream->
bandwidth = (bandwidth + 999) / 1000;
3939 if (!codec || codec->
type != type)
3959 char filename[1000], tmp[1000], tmp2[1000],
line[1000];
3964 codec ? codec->
name : NULL))) {
3965 fprintf(stderr,
"File for preset '%s' not found\n", arg);
3970 int e= fscanf(f,
"%999[^\n]\n", line) - 1;
3971 if(line[0] ==
'#' && !e)
3973 e|= sscanf(line,
"%999[^=]=%999[^\n]\n", tmp, tmp2) - 2;
3975 fprintf(stderr,
"%s: Invalid syntax: '%s'\n", filename, line);
3979 if(!strcmp(tmp,
"acodec")){
3981 }
else if(!strcmp(tmp,
"vcodec")){
3983 }
else if(!strcmp(tmp,
"scodec")){
3986 fprintf(stderr,
"%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", filename, line, tmp, tmp2);
4003 char stream_format_name[64];
4005 snprintf(stream_format_name,
sizeof(stream_format_name),
"%s_stream", fmt->
name);
4019 av_log(NULL, log_level,
"%s:%d: ", filename, line_num);
4020 av_vlog(NULL, log_level, fmt, vl);
4031 char arg[1024], arg2[1024];
4033 int val, errors, warnings, line_num;
4034 FFStream **last_stream, *stream, *redirect;
4040 f = fopen(filename,
"r");
4043 av_log(NULL,
AV_LOG_ERROR,
"Could not open the configuration file '%s'\n", filename);
4047 errors = warnings = 0;
4049 first_stream = NULL;
4058 #define ERROR(...) report_config_error(filename, line_num, AV_LOG_ERROR, &errors, __VA_ARGS__)
4059 #define WARNING(...) report_config_error(filename, line_num, AV_LOG_WARNING, &warnings, __VA_ARGS__)
4062 if (fgets(line,
sizeof(line), f) == NULL)
4068 if (*p ==
'\0' || *p ==
'#')
4071 get_arg(cmd,
sizeof(cmd), &p);
4075 WARNING(
"Port option is deprecated, use HTTPPort instead\n");
4076 get_arg(arg,
sizeof(arg), &p);
4078 if (val < 1 || val > 65536) {
4079 ERROR(
"Invalid port: %s\n", arg);
4082 WARNING(
"Trying to use IETF assigned system port: %d\n", val);
4086 WARNING(
"BindAddress option is deprecated, use HTTPBindAddress instead\n");
4087 get_arg(arg,
sizeof(arg), &p);
4089 ERROR(
"%s:%d: Invalid host/IP address: %s\n", arg);
4092 WARNING(
"NoDaemon option has no effect, you should remove it\n");
4094 get_arg(arg,
sizeof(arg), &p);
4096 if (val < 1 || val > 65536) {
4097 ERROR(
"%s:%d: Invalid port: %s\n", arg);
4101 get_arg(arg,
sizeof(arg), &p);
4103 ERROR(
"Invalid host/IP address: %s\n", arg);
4106 get_arg(arg,
sizeof(arg), &p);
4108 if (val < 1 || val > 65536) {
4109 ERROR(
"Invalid MaxHTTPConnections: %s\n", arg);
4113 get_arg(arg,
sizeof(arg), &p);
4116 ERROR(
"Invalid MaxClients: %s\n", arg);
4122 get_arg(arg,
sizeof(arg), &p);
4123 llval = strtoll(arg, NULL, 10);
4124 if (llval < 10 || llval > 10000000) {
4125 ERROR(
"Invalid MaxBandwidth: %s\n", arg);
4135 if (stream || feed) {
4136 ERROR(
"Already in a tag\n");
4148 for (s = first_feed;
s; s = s->
next) {
4163 *last_stream = feed;
4164 last_stream = &feed->
next;
4178 for (i = 0; i < 62; i++) {
4179 get_arg(arg,
sizeof(arg), &p);
4192 (
my_http_addr.sin_addr.s_addr == INADDR_ANY) ?
"127.0.0.1" :
4204 }
else if (stream) {
4209 get_arg(arg,
sizeof(arg), &p);
4214 WARNING(
"Truncate N syntax in configuration file is deprecated, "
4215 "use Truncate alone with no arguments\n");
4224 get_arg(arg,
sizeof(arg), &p);
4232 fsize *= 1024 * 1024;
4235 fsize *= 1024 * 1024 * 1024;
4245 ERROR(
"No corresponding <Feed> for </Feed>\n");
4252 if (stream || feed) {
4253 ERROR(
"Already in a tag\n");
4262 q = strrchr(stream->
filename,
'>');
4266 for (s = first_stream;
s; s = s->
next) {
4283 *last_stream = stream;
4284 last_stream = &stream->
next;
4287 get_arg(arg,
sizeof(arg), &p);
4298 ERROR(
"Feed with name '%s' for stream '%s' is not defined\n", arg, stream->
filename);
4300 stream->
feed = sfeed;
4303 get_arg(arg,
sizeof(arg), &p);
4305 if (!strcmp(arg,
"status")) {
4311 if (!strcmp(arg,
"jpeg"))
4312 strcpy(arg,
"mjpeg");
4315 ERROR(
"Unknown Format: %s\n", arg);
4324 get_arg(arg,
sizeof(arg), &p);
4327 if (!stream->
ifmt) {
4328 ERROR(
"Unknown input format: %s\n", arg);
4335 ERROR(
"FaviconURL only permitted for status streams\n");
4341 get_arg(arg,
sizeof(arg), &p);
4347 for (i = 0; i < strlen(cmd); i++)
4350 WARNING(
"'%s' option in configuration file is deprecated, "
4351 "use 'Metadata %s VALUE' instead\n", cmd, key);
4353 ERROR(
"Could not set metadata '%s' to value '%s': %s\n",
4358 get_arg(arg,
sizeof(arg), &p);
4359 get_arg(arg2,
sizeof(arg2), &p);
4363 ERROR(
"Could not set metadata '%s' to value '%s': %s\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);
4404 int minrate, maxrate;
4406 get_arg(arg,
sizeof(arg), &p);
4408 if (sscanf(arg,
"%d-%d", &minrate, &maxrate) == 2) {
4412 ERROR(
"Incorrect format for VideoBitRateRange -- should be <min>-<max>: %s\n", arg);
4417 get_arg(arg,
sizeof(arg), &p);
4418 video_enc.
debug = strtol(arg,0,0);
4422 get_arg(arg,
sizeof(arg), &p);
4427 get_arg(arg,
sizeof(arg), &p);
4432 get_arg(arg,
sizeof(arg), &p);
4436 get_arg(arg,
sizeof(arg), &p);
4438 video_enc.
bit_rate = atoi(arg) * 1000;
4441 get_arg(arg,
sizeof(arg), &p);
4445 ERROR(
"Invalid video size '%s'\n", arg);
4447 if ((video_enc.
width % 16) != 0 ||
4448 (video_enc.
height % 16) != 0) {
4449 ERROR(
"Image size must be a multiple of 16\n");
4454 get_arg(arg,
sizeof(arg), &p);
4458 ERROR(
"Incorrect frame rate: %s\n", arg);
4465 get_arg(arg,
sizeof(arg), &p);
4469 ERROR(
"Unknown pixel format: %s\n", arg);
4473 get_arg(arg,
sizeof(arg), &p);
4491 get_arg(arg,
sizeof(arg), &p);
4492 get_arg(arg2,
sizeof(arg2), &p);
4501 ERROR(
"Error setting %s option to %s %s\n", cmd, arg, arg2);
4507 get_arg(arg,
sizeof(arg), &p);
4518 ERROR(
"AVPreset error: %s\n", arg);
4521 get_arg(arg,
sizeof(arg), &p);
4522 if ((strlen(arg) == 4) && stream)
4534 get_arg(arg,
sizeof(arg), &p);
4540 get_arg(arg,
sizeof(arg), &p);
4544 ERROR(
"VideoQDiff out of range\n");
4548 get_arg(arg,
sizeof(arg), &p);
4550 video_enc.
qmax = atoi(arg);
4551 if (video_enc.
qmax < 1 || video_enc.
qmax > 31) {
4552 ERROR(
"VideoQMax out of range\n");
4556 get_arg(arg,
sizeof(arg), &p);
4558 video_enc.
qmin = atoi(arg);
4559 if (video_enc.
qmin < 1 || video_enc.
qmin > 31) {
4560 ERROR(
"VideoQMin out of range\n");
4564 get_arg(arg,
sizeof(arg), &p);
4568 get_arg(arg,
sizeof(arg), &p);
4582 get_arg(arg,
sizeof(arg), &p);
4588 get_arg(arg,
sizeof(arg), &p);
4591 ERROR(
"Invalid host/IP address: %s\n", arg);
4597 get_arg(arg,
sizeof(arg), &p);
4601 get_arg(arg,
sizeof(arg), &p);
4609 ERROR(
"No corresponding <Stream> for </Stream>\n");
4611 if (stream->
feed && stream->
fmt && strcmp(stream->
fmt->
name,
"ffm") != 0) {
4628 if (stream || feed || redirect) {
4629 ERROR(
"Already in a tag\n");
4636 *last_stream = redirect;
4637 last_stream = &redirect->
next;
4640 q = strrchr(redirect->
filename,
'>');
4650 ERROR(
"No corresponding <Redirect> for </Redirect>\n");
4653 ERROR(
"No URL found for <Redirect>\n");
4658 ERROR(
"Loadable modules no longer supported\n");
4660 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 } };
4739 unsetenv(
"http_proxy");
4744 sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
4745 sigaction(SIGCHLD, &sigact, 0);
4748 fprintf(stderr,
"Error reading configuration file '%s': %s\n",
4770 signal(SIGPIPE, SIG_IGN);
4773 http_log(
"Could not start server\n");