28 #define closesocket close
62 #include <sys/ioctl.h>
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)
202 .nb_max_connections = 5,
203 .max_bandwidth = 1000,
229 struct in_addr my_ip);
236 int stream_index,
struct sockaddr_in *dest_addr,
257 s += strspn(s,
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,. ");
267 if (lseek(fd, 8, SEEK_SET) < 0)
269 if (read(fd, buf, 8) != 8)
280 buf[i] = (pos >> (56 - i * 8)) & 0xff;
281 if (lseek(fd, 8, SEEK_SET) < 0)
283 if (write(fd, buf, 8) != 8)
296 static char *
ctime1(
char *buf2,
int buf_size)
304 p = buf2 + strlen(p) - 1;
312 static int print_prefix = 1;
319 print_prefix = strstr(fmt,
"\n") != NULL;
326 __attribute__ ((format (printf, 1, 2)))
331 va_start(vargs, fmt);
338 static int print_prefix = 1;
342 if (print_prefix && avc)
344 print_prefix = strstr(fmt,
"\n") != NULL;
353 http_log(
"%s - - [%s] \"%s %s\" %d %"PRId64
"\n",
386 for (; feed; feed = feed->
next) {
393 http_log(
"Unable to create children\n");
405 slash = strrchr(pathname,
'/');
410 strcpy(slash,
"ffmpeg");
418 for (i = 3; i < 256; i++)
422 if (!freopen(
"/dev/null",
"r", stdin))
423 http_log(
"failed to redirect STDIN to /dev/null\n;");
424 if (!freopen(
"/dev/null",
"w", stdout))
425 http_log(
"failed to redirect STDOUT to /dev/null\n;");
426 if (!freopen(
"/dev/null",
"w", stderr))
427 http_log(
"failed to redirect STDERR to /dev/null\n;");
430 signal(SIGPIPE, SIG_DFL);
445 server_fd = socket(AF_INET,SOCK_STREAM,0);
452 if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp,
sizeof(tmp)))
455 my_addr->sin_family = AF_INET;
456 if (bind (server_fd, (
struct sockaddr *) my_addr,
sizeof (*my_addr)) < 0) {
458 snprintf(bindmsg,
sizeof(bindmsg),
"bind(port %d)", ntohs(my_addr->sin_port));
464 if (listen (server_fd, 5) < 0) {
482 struct sockaddr_in dest_addr = {0};
483 int default_port, stream_index;
491 snprintf(session_id,
sizeof(session_id),
"%08x%08x",
500 dest_addr.sin_family = AF_INET;
510 http_log(
"Could not open input stream for stream '%s'\n",
516 for(stream_index = 0; stream_index < stream->
nb_streams;
521 http_log(
"Could not open output stream '%s/streamid=%d'\n",
535 int server_fd = 0, rtsp_server_fd = 0;
537 struct pollfd *poll_table, *poll_entry;
555 if (rtsp_server_fd < 0) {
562 if (!rtsp_server_fd && !server_fd) {
563 http_log(
"HTTP and RTSP disabled.\n");
575 poll_entry = poll_table;
577 poll_entry->fd = server_fd;
578 poll_entry->events = POLLIN;
581 if (rtsp_server_fd) {
582 poll_entry->fd = rtsp_server_fd;
583 poll_entry->events = POLLIN;
599 poll_entry->events = POLLOUT;
610 poll_entry->events = POLLOUT;
628 poll_entry->events = POLLIN;
641 ret = poll(poll_table, poll_entry - poll_table, delay);
657 for(c = first_http_ctx;
c; c = c_next) {
666 poll_entry = poll_table;
669 if (poll_entry->revents & POLLIN)
673 if (rtsp_server_fd) {
675 if (poll_entry->revents & POLLIN)
700 "HTTP/1.0 503 Server too busy\r\n"
701 "Content-type: text/html\r\n"
703 "<html><head><title>Too busy</title></head><body>\r\n"
704 "<p>The server is too busy to serve your request at this time.</p>\r\n"
705 "<p>The number of current connections is %u, and this exceeds the limit of %u.</p>\r\n"
706 "</body></html>\r\n",
709 if (send(fd, buffer, len, 0) < len)
716 struct sockaddr_in from_addr;
721 len =
sizeof(from_addr);
722 fd = accept(server_fd, (
struct sockaddr *)&from_addr,
725 http_log(
"error during accept %s\n", strerror(errno));
784 for(c1 = first_http_ctx;
c1; c1 = c1->
next) {
864 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
877 }
else if (len == 0) {
884 if ((ptr >= c->
buffer + 2 && !memcmp(ptr-2,
"\n\n", 2)) ||
885 (ptr >= c->
buffer + 4 && !memcmp(ptr-4,
"\r\n\r\n", 4))) {
897 }
else goto read_loop;
902 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
939 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
954 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
963 if (c->
poll_entry->revents & (POLLIN | POLLERR | POLLHUP))
970 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
992 if (c->
poll_entry->revents & (POLLERR | POLLHUP)) {
1034 for (p = request; *p && *p !=
'\r' && *p !=
'\n'; ) {
1036 const char *q = p + 7;
1047 memset(rates, 0xff, ratelen);
1050 while (*q && *q !=
'\n' && *q !=
':')
1053 if (sscanf(q,
":%d:%d", &stream_no, &rate_no) != 2)
1057 if (stream_no < ratelen && stream_no >= 0)
1058 rates[stream_no] = rate_no;
1067 p = strchr(p,
'\n');
1080 int best_bitrate = 100000000;
1098 if (feed_codec->
bit_rate <= bit_rate) {
1099 if (best_bitrate > bit_rate || feed_codec->
bit_rate > best_bitrate) {
1100 best_bitrate = feed_codec->
bit_rate;
1104 if (feed_codec->
bit_rate < best_bitrate) {
1105 best_bitrate = feed_codec->
bit_rate;
1118 int action_required = 0;
1146 action_required = 1;
1149 return action_required;
1161 if ((q - buf) < buf_size - 1)
1189 if (fgets(line,
sizeof(line), f) == NULL)
1195 if (*p ==
'\0' || *p ==
'#')
1224 unsigned long src_addr = src->s_addr;
1226 for (acl = in_acl; acl; acl = acl->
next) {
1227 if (src_addr >= acl->
first.s_addr && src_addr <= acl->last.s_addr)
1229 last_action = acl->
action;
1233 return (last_action ==
IP_DENY) ? 1 : 0;
1266 p = strrchr(file1,
'.');
1271 p = strrchr(file2,
'.');
1274 if (!strcmp(file1, file2)) {
1297 char info[1024], filename[1024];
1301 const char *mime_type;
1305 const char *useragent = 0;
1311 if (!strcmp(cmd,
"GET"))
1313 else if (!strcmp(cmd,
"POST"))
1321 get_word(protocol,
sizeof(protocol), (
const char **)&p);
1322 if (strcmp(protocol,
"HTTP/1.0") && strcmp(protocol,
"HTTP/1.1"))
1328 http_log(
"%s - - New connection: %s %s\n", inet_ntoa(c->
from_addr.sin_addr), cmd, url);
1331 p1 = strchr(url,
'?');
1338 av_strlcpy(filename, url + ((*url ==
'/') ? 1 : 0),
sizeof(filename)-1);
1340 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1343 if (*useragent && *useragent !=
'\n' &&
av_isspace(*useragent))
1347 p = strchr(p,
'\n');
1357 filename[strlen(filename)-1] =
'f';
1364 strcpy(filename + strlen(filename)-2,
"m");
1374 if (!strlen(filename))
1375 av_strlcpy(filename,
"index.html",
sizeof(filename) - 1);
1381 stream = stream->
next;
1384 snprintf(msg,
sizeof(msg),
"File '%s' not found", url);
1385 http_log(
"File '%s' not found\n", url);
1397 "HTTP/1.0 301 Moved\r\n"
1399 "Content-type: text/html\r\n"
1401 "<html><head><title>Moved</title></head><body>\r\n"
1402 "You should be <a href=\"%s\">redirected</a>.\r\n"
1427 snprintf(msg,
sizeof(msg),
"This feed is already being received.");
1436 "HTTP/1.0 503 Server too busy\r\n"
1437 "Content-type: text/html\r\n"
1439 "<html><head><title>Too busy</title></head><body>\r\n"
1440 "<p>The server is too busy to serve your request at this time.</p>\r\n"
1441 "<p>The bandwidth being served (including your stream) is %"PRIu64
"kbit/sec, "
1442 "and this exceeds the limit of %"PRIu64
"kbit/sec.</p>\r\n"
1453 const char *hostinfo = 0;
1455 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1460 p = strchr(p,
'\n');
1474 eoh = strchr(hostinfo,
'\n');
1476 if (eoh[-1] ==
'\r')
1479 if (eoh - hostinfo <
sizeof(hostbuf) - 1) {
1480 memcpy(hostbuf, hostinfo, eoh - hostinfo);
1481 hostbuf[eoh - hostinfo] = 0;
1485 switch(redir_type) {
1488 "HTTP/1.0 200 ASX Follows\r\n"
1489 "Content-type: video/x-ms-asf\r\n"
1491 "<ASX Version=\"3\">\r\n"
1493 "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n"
1494 "</ASX>\r\n", hostbuf, filename, info);
1499 "HTTP/1.0 200 RAM Follows\r\n"
1500 "Content-type: audio/x-pn-realaudio\r\n"
1502 "# Autogenerated by ffserver\r\n"
1503 "http://%s/%s%s\r\n", hostbuf, filename, info);
1508 "HTTP/1.0 200 ASF Redirect follows\r\n"
1509 "Content-type: video/x-ms-asf\r\n"
1512 "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info);
1517 char hostname[256], *p;
1519 av_strlcpy(hostname, hostbuf,
sizeof(hostname));
1520 p = strrchr(hostname,
':');
1524 "HTTP/1.0 200 RTSP Redirect follows\r\n"
1526 "Content-type: application/x-rtsp\r\n"
1528 "rtsp://%s:%d/%s\r\n", hostname, ntohs(config.
rtsp_addr.sin_port), filename);
1537 struct sockaddr_in my_addr;
1540 "HTTP/1.0 200 OK\r\n"
1541 "Content-type: application/sdp\r\n"
1545 len =
sizeof(my_addr);
1548 if (getsockname(c->
fd, (
struct sockaddr *)&my_addr, &len))
1549 http_log(
"getsockname() failed\n");
1555 if (sdp_data_size > 0) {
1556 memcpy(q, sdp_data, sdp_data_size);
1577 snprintf(msg,
sizeof(msg),
"ASX/RAM file not handled");
1590 const char *logline = 0;
1593 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1599 client_id = strtol(p + 18, 0, 10);
1600 p = strchr(p,
'\n');
1608 char *eol = strchr(logline,
'\n');
1613 if (eol[-1] ==
'\r')
1615 http_log(
"%.*s\n", (
int) (eol - logline), logline);
1628 for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->
next) {
1637 snprintf(msg,
sizeof(msg),
"POST command not handled");
1642 snprintf(msg,
sizeof(msg),
"could not open feed");
1660 snprintf(msg,
sizeof(msg),
"Input stream corresponding to '%s' not found", url);
1669 mime_type =
"application/x-octet-stream";
1695 "HTTP/1.0 404 Not Found\r\n"
1696 "Content-type: text/html\r\n"
1699 "<head><title>404 Not Found</title></head>\n"
1718 static const char suffix[] =
" kMGTP";
1721 for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++);
1754 avio_printf(pb,
"<table cellspacing=0 cellpadding=4>\n");
1755 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");
1758 char sfilename[1024];
1761 if (stream->
feed != stream) {
1763 eosf = sfilename + strlen(sfilename);
1764 if (eosf - sfilename >= 4) {
1765 if (strcmp(eosf - 4,
".asf") == 0)
1766 strcpy(eosf - 4,
".asx");
1767 else if (strcmp(eosf - 3,
".rm") == 0)
1768 strcpy(eosf - 3,
".ram");
1769 else if (stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
1773 eosf = strrchr(sfilename,
'.');
1775 eosf = sfilename + strlen(sfilename);
1777 strcpy(eosf,
".sdp");
1779 strcpy(eosf,
".rtsp");
1783 avio_printf(pb,
"<tr><td><a href=\"/%s\">%s</a> ",
1785 avio_printf(pb,
"<td align=right> %d <td align=right> ",
1790 int audio_bit_rate = 0;
1791 int video_bit_rate = 0;
1794 const char *audio_codec_name_extra =
"";
1795 const char *video_codec_name_extra =
"";
1804 if (*audio_codec_name)
1805 audio_codec_name_extra =
"...";
1806 audio_codec_name = codec->
name;
1812 if (*video_codec_name)
1813 video_codec_name_extra =
"...";
1814 video_codec_name = codec->
name;
1824 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",
1827 video_bit_rate / 1000, video_codec_name, video_codec_name_extra,
1828 audio_bit_rate / 1000, audio_codec_name, audio_codec_name_extra);
1837 avio_printf(pb,
"<td align=center> - <td align=right> - <td align=right> - <td><td align=right> - <td>\n");
1841 stream = stream->
next;
1847 if (stream->
feed == stream) {
1859 "ps -o \"%%cpu,cputime\" --no-headers %d",
1862 pid_stat = popen(ps_cmd,
"r");
1867 if (fscanf(pid_stat,
"%9s %63s", cpuperc,
1869 avio_printf(pb,
"Currently using %s%% of the cpu. Total time used %s.\n",
1879 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");
1884 const char *
type =
"unknown";
1885 char parameters[64];
1902 avio_printf(pb,
"<tr><td align=right>%d<td>%s<td align=right>%d<td>%s<td>%s\n",
1908 stream = stream->
next;
1914 avio_printf(pb,
"Number of connections: %d / %d<br>\n",
1917 avio_printf(pb,
"Bandwidth in use: %"PRIu64
"k / %"PRIu64
"k<br>\n",
1921 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");
1940 avio_printf(pb,
"<tr><td><b>%d</b><td>%s%s<td>%s<td>%s<td>%s<td align=right>",
1960 avio_printf(pb,
"<hr size=1 noshade>Generated at %s", p);
1973 int buf_size, i,
ret;
1983 http_log(
"Invalid date specification '%s' for stream\n", buf);
1987 int prebuffer = strtol(buf, 0, 10);
1988 stream_pos =
av_gettime() - prebuffer * (int64_t)1000000;
1997 http_log(
"Invalid date specification '%s' for stream\n", buf);
2003 if (!input_filename[0]) {
2004 http_log(
"No filename was specified for stream\n");
2021 http_log(
"Could not find stream info for input '%s'\n", input_filename);
2055 int bytes_left, bytes_sent, frame_bytes;
2058 if (frame_bytes <= 0)
2062 bytes_sent = frame_bytes - bytes_left;
2118 http_log(
"Error writing output header for stream '%s': %s\n",
2153 }
else if (ret ==
AVERROR(EAGAIN)) {
2230 int max_packet_size;
2252 http_log(
"Error writing frame to output for stream '%s': %s\n",
2340 int interleaved_index,
size;
2356 interleaved_index++;
2359 header[1] = interleaved_index;
2360 header[2] = len >> 8;
2438 http_log(
"Could not open feed file '%s': %s\n",
2450 http_log(
"Error truncating feed file '%s': %s\n",
2457 http_log(
"Error reading write index from feed file '%s': %s\n",
2467 lseek(fd, 0, SEEK_SET);
2480 int len, loop_run = 0;
2493 }
else if (len == 0) {
2503 }
else if (++loop_run > 10) {
2519 }
else if (len == 0)
2531 if (c->
buffer[0] !=
'f' ||
2533 http_log(
"Feed stream has become desynchronized -- disconnecting\n");
2549 http_log(
"Error writing to feed file: %s\n", strerror(errno));
2564 http_log(
"Error writing index to feed file: %s\n", strerror(errno));
2569 for(c1 = first_http_ctx;
c1; c1 = c1->
next) {
2590 0, NULL, NULL, NULL, NULL);
2603 http_log(
"Feed '%s' stream number does not match registered feed\n",
2625 for(c1 = first_http_ctx;
c1; c1 = c1->
next) {
2645 str =
"Unknown Error";
2647 avio_printf(c->
pb,
"RTSP/1.0 %d %s\r\n", error_number, str);
2653 strftime(buf2,
sizeof(buf2),
"%a, %d %b %Y %H:%M:%S", tm);
2665 const char *p, *p1, *p2;
2678 get_word(protocol,
sizeof(protocol), &p);
2691 if (strcmp(protocol,
"RTSP/1.0")) {
2698 while (*p !=
'\n' && *p !=
'\0')
2702 while (*p !=
'\0') {
2703 p1 = memchr(p,
'\n', (
char *)c->
buffer_ptr - p);
2707 if (p2 > p && p2[-1] ==
'\r')
2713 if (len >
sizeof(line) - 1)
2714 len =
sizeof(line) - 1;
2715 memcpy(line, p, len);
2724 if (!strcmp(cmd,
"DESCRIBE"))
2726 else if (!strcmp(cmd,
"OPTIONS"))
2728 else if (!strcmp(cmd,
"SETUP"))
2730 else if (!strcmp(cmd,
"PLAY"))
2732 else if (!strcmp(cmd,
"PAUSE"))
2734 else if (!strcmp(cmd,
"TEARDOWN"))
2753 struct in_addr my_ip)
2764 if (!avc || !rtp_format) {
2769 entry ? entry->
value :
"No Title", 0);
2782 if (avc->
nb_streams >= INT_MAX/
sizeof(*avs) ||
2799 return *pbuffer ? strlen(*pbuffer) :
AVERROR(ENOMEM);
2807 avio_printf(c->
pb,
"Public: %s\r\n",
"OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
2819 struct sockaddr_in my_addr;
2822 av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1,
sizeof(path1), url);
2829 stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp") &&
2842 len =
sizeof(my_addr);
2843 getsockname(c->
fd, (
struct sockaddr *)&my_addr, &len);
2845 if (content_length < 0) {
2852 avio_printf(c->
pb,
"Content-Length: %d\r\n", content_length);
2862 if (session_id[0] ==
'\0')
2865 for(c = first_http_ctx;
c; c = c->
next) {
2889 int stream_index, rtp_port, rtcp_port;
2895 struct sockaddr_in dest_addr;
2899 av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1,
sizeof(path1), url);
2907 stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
2909 if (!strcmp(path, stream->
filename)) {
2918 for(stream_index = 0; stream_index < stream->
nb_streams;
2920 snprintf(buf,
sizeof(buf),
"%s/streamid=%d",
2922 if (!strcmp(path, buf))
2934 unsigned random0 =
av_lfg_get(&random_state);
2935 unsigned random1 =
av_lfg_get(&random_state);
2969 if (rtp_c->
stream != stream) {
2975 if (rtp_c->
rtp_ctx[stream_index]) {
2989 setup.transport_option[0] =
'\0';
3009 "client_port=%d-%d;server_port=%d-%d",
3011 rtp_port, rtcp_port);
3014 avio_printf(c->
pb,
"Transport: RTP/AVP/TCP;interleaved=%d-%d",
3015 stream_index * 2, stream_index * 2 + 1);
3020 if (setup.transport_option[0] !=
'\0')
3032 const char *session_id)
3045 av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1,
sizeof(path1), url);
3051 snprintf(buf,
sizeof(buf),
"%s/streamid=%d",
3053 if(!strncmp(path, buf,
sizeof(buf))) {
3059 if (len > 0 && path[len - 1] ==
'/' &&
3129 const char *proto_str;
3158 proto_str =
"MCAST";
3191 int stream_index,
struct sockaddr_in *dest_addr,
3199 int max_packet_size;
3226 ipaddr = inet_ntoa(dest_addr->sin_addr);
3240 "rtp://%s:%d?multicast=1&ttl=%d",
3241 ipaddr, ntohs(dest_addr->sin_port), ttl);
3244 "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
3261 http_log(
"%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
3262 ipaddr, ntohs(dest_addr->sin_port),
3282 c->
rtp_ctx[stream_index] = ctx;
3374 int mpeg4_count, i,
size;
3392 printf(
"MPEG4 without extra data: trying to find header in %s\n", infile->
filename);
3393 while (mpeg4_count > 0) {
3403 while (p < pkt.
data + pkt.
size - 4) {
3405 if (p[0] == 0x00 && p[1] == 0x00 &&
3406 p[2] == 0x01 && p[3] == 0xb6) {
3407 size = p - pkt.
data;
3429 for(stream = config.
first_stream; stream; stream = stream_next) {
3431 stream_next = stream->
next;
3437 if (stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
3458 http_log(
"Could not find codec parameters from '%s'\n",
3482 feed = stream->
feed;
3517 http_log(
"Index & Id do not match for stream %d (%s)\n",
3525 #define CHECK_CODEC(x) (ccf->x != ccs->x)
3528 http_log(
"Codecs do not match for stream %d\n", i);
3531 http_log(
"Codec bitrates do not match for stream %d\n", i);
3538 http_log(
"Codec width, height and framerate do not match for stream %d\n", i);
3545 http_log(
"Codec sample_rate, channels, frame_size do not match for stream %d\n", i);
3557 http_log(
"Deleting feed file '%s' as stream counts differ (%d != %d)\n",
3562 http_log(
"Deleting feed file '%s' as it appears to be corrupt\n",
3567 http_log(
"Unable to delete feed file '%s' as it is marked readonly\n",
3578 http_log(
"Unable to create feed file '%s' as it is marked readonly\n",
3585 http_log(
"Could not open output feed file '%s'\n",
3593 http_log(
"Container doesn't support the required parameters\n");
3606 http_log(
"Could not open output feed file '%s'\n",
3612 feed->
feed_size = lseek(fd, 0, SEEK_END);
3641 stream->
bandwidth = (bandwidth + 999) / 1000;
3650 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
3654 if (feed->
pid == pid) {
3658 fprintf(stderr,
"%s: Pid %d exited with status %d after %d seconds\n", feed->
filename, pid, status, uptime);
3678 printf(
"usage: ffserver [options]\n"
3679 "Hyper fast multi format Audio/Video streaming server\n");
3687 {
"d", 0, {(
void*)
opt_debug},
"enable debug mode" },
3688 {
"f",
HAS_ARG |
OPT_STRING, {(
void*)&config.
filename },
"use configfile instead of /etc/ffserver.conf",
"configfile" },
3694 struct sigaction sigact = { { 0 } };
3709 unsetenv(
"http_proxy");
3714 sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
3715 sigaction(SIGCHLD, &sigact, 0);
3718 fprintf(stderr,
"Error reading configuration file '%s': %s\n",
3740 signal(SIGPIPE, SIG_IGN);
3743 http_log(
"Could not start server\n");