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,
232 struct in_addr my_ip);
237 const char *session_id,
240 int stream_index,
struct sockaddr_in *dest_addr,
261 s += strspn(s,
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,. ");
271 if (lseek(fd, 8, SEEK_SET) < 0)
273 if (read(fd, buf, 8) != 8)
284 buf[i] = (pos >> (56 - i * 8)) & 0xff;
285 if (lseek(fd, 8, SEEK_SET) < 0)
287 if (write(fd, buf, 8) != 8)
300 static char *
ctime1(
char *buf2,
int buf_size)
308 p = buf2 + strlen(p) - 1;
316 static int print_prefix = 1;
326 print_prefix = strstr(fmt,
"\n") !=
NULL;
332 __attribute__ ((format (printf, 1, 2)))
337 va_start(vargs, fmt);
344 static int print_prefix = 1;
348 if (print_prefix && avc)
350 print_prefix = strstr(fmt,
"\n") !=
NULL;
359 http_log(
"%s - - [%s] \"%s %s\" %d %"PRId64
"\n",
400 slash = strrchr(pathname,
'/');
405 strcpy(slash,
"ffmpeg");
407 for (; feed; feed = feed->
next) {
416 http_log(
"Unable to create children\n");
432 for (i = 3; i < 256; i++)
436 if (!freopen(
"/dev/null",
"r", stdin))
437 http_log(
"failed to redirect STDIN to /dev/null\n;");
438 if (!freopen(
"/dev/null",
"w", stdout))
439 http_log(
"failed to redirect STDOUT to /dev/null\n;");
440 if (!freopen(
"/dev/null",
"w", stderr))
441 http_log(
"failed to redirect STDERR to /dev/null\n;");
444 signal(SIGPIPE, SIG_DFL);
455 server_fd = socket(AF_INET,SOCK_STREAM,0);
462 if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp,
sizeof(tmp)))
465 my_addr->sin_family = AF_INET;
466 if (bind (server_fd, (
struct sockaddr *) my_addr,
sizeof (*my_addr)) < 0) {
468 snprintf(bindmsg,
sizeof(bindmsg),
"bind(port %d)",
469 ntohs(my_addr->sin_port));
475 if (listen (server_fd, 5) < 0) {
493 struct sockaddr_in dest_addr = {0};
494 int default_port, stream_index;
495 unsigned int random0, random1;
507 snprintf(session_id,
sizeof(session_id),
"%08x%08x",
516 dest_addr.sin_family = AF_INET;
526 http_log(
"Could not open input stream for stream '%s'\n",
532 for(stream_index = 0; stream_index < stream->
nb_streams;
539 http_log(
"Could not open output stream '%s/streamid=%d'\n",
551 int server_fd = 0, rtsp_server_fd = 0;
553 struct pollfd *poll_table, *poll_entry;
557 sizeof(*poll_table));
559 http_log(
"Impossible to allocate a poll table handling %d "
574 if (rtsp_server_fd < 0) {
581 if (!rtsp_server_fd && !server_fd) {
582 http_log(
"HTTP and RTSP disabled.\n");
594 poll_entry = poll_table;
596 poll_entry->fd = server_fd;
597 poll_entry->events = POLLIN;
600 if (rtsp_server_fd) {
601 poll_entry->fd = rtsp_server_fd;
602 poll_entry->events = POLLIN;
618 poll_entry->events = POLLOUT;
629 poll_entry->events = POLLOUT;
647 poll_entry->events = POLLIN;
660 ret = poll(poll_table, poll_entry - poll_table, delay);
676 for(c = first_http_ctx;
c; c = c_next) {
685 poll_entry = poll_table;
688 if (poll_entry->revents & POLLIN)
692 if (rtsp_server_fd) {
694 if (poll_entry->revents & POLLIN)
719 "HTTP/1.0 503 Server too busy\r\n"
720 "Content-type: text/html\r\n"
722 "<html><head><title>Too busy</title></head><body>\r\n"
723 "<p>The server is too busy to serve your request at this time.</p>\r\n"
724 "<p>The number of current connections is %u, and this exceeds the limit of %u.</p>\r\n"
725 "</body></html>\r\n",
728 if (send(fd, buffer, len, 0) < len)
730 "Could not send too-busy reply, send() failed\n");
736 struct sockaddr_in from_addr;
741 len =
sizeof(from_addr);
742 fd = accept(server_fd, (
struct sockaddr *)&from_addr,
745 http_log(
"error during accept %s\n", strerror(errno));
804 for(c1 = first_http_ctx;
c1; c1 = c1->
next) {
883 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
903 if ((ptr >= c->
buffer + 2 && !memcmp(ptr-2,
"\n\n", 2)) ||
904 (ptr >= c->
buffer + 4 && !memcmp(ptr-4,
"\r\n\r\n", 4))) {
916 }
else goto read_loop;
921 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
958 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
973 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
982 if (c->
poll_entry->revents & (POLLIN | POLLERR | POLLHUP))
989 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1011 if (c->
poll_entry->revents & (POLLERR | POLLHUP)) {
1053 for (p = request; *p && *p !=
'\r' && *p !=
'\n'; ) {
1055 const char *q = p + 7;
1066 memset(rates, 0xff, ratelen);
1069 while (*q && *q !=
'\n' && *q !=
':')
1072 if (sscanf(q,
":%d:%d", &stream_no, &rate_no) != 2)
1076 if (stream_no < ratelen && stream_no >= 0)
1077 rates[stream_no] = rate_no;
1086 p = strchr(p,
'\n');
1100 int best_bitrate = 100000000;
1118 if (feed_codec->
bit_rate <= bit_rate) {
1119 if (best_bitrate > bit_rate ||
1120 feed_codec->
bit_rate > best_bitrate) {
1121 best_bitrate = feed_codec->
bit_rate;
1126 if (feed_codec->
bit_rate < best_bitrate) {
1127 best_bitrate = feed_codec->
bit_rate;
1138 int action_required = 0;
1166 action_required = 1;
1169 return action_required;
1181 if ((q - buf) < buf_size - 1)
1209 while (fgets(line,
sizeof(line), f)) {
1214 if (*p ==
'\0' || *p ==
'#')
1244 unsigned long src_addr = src->s_addr;
1246 for (acl = in_acl; acl; acl = acl->
next) {
1247 if (src_addr >= acl->
first.s_addr && src_addr <= acl->last.s_addr)
1249 last_action = acl->
action;
1253 return (last_action ==
IP_DENY) ? 1 : 0;
1286 p = strrchr(file1,
'.');
1291 p = strrchr(file2,
'.');
1294 if (!strcmp(file1, file2)) {
1317 char info[1024], filename[1024];
1321 const char *mime_type;
1325 const char *useragent = 0;
1331 if (!strcmp(cmd,
"GET"))
1333 else if (!strcmp(cmd,
"POST"))
1341 get_word(protocol,
sizeof(protocol), (
const char **)&p);
1342 if (strcmp(protocol,
"HTTP/1.0") && strcmp(protocol,
"HTTP/1.1"))
1348 http_log(
"%s - - New connection: %s %s\n",
1349 inet_ntoa(c->
from_addr.sin_addr), cmd, url);
1352 p1 = strchr(url,
'?');
1359 av_strlcpy(filename, url + ((*url ==
'/') ? 1 : 0),
sizeof(filename)-1);
1361 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1364 if (*useragent && *useragent !=
'\n' &&
av_isspace(*useragent))
1368 p = strchr(p,
'\n');
1378 filename[strlen(filename)-1] =
'f';
1385 strcpy(filename + strlen(filename)-2,
"m");
1395 if (!strlen(filename))
1396 av_strlcpy(filename,
"index.html",
sizeof(filename) - 1);
1402 stream = stream->
next;
1405 snprintf(msg,
sizeof(msg),
"File '%s' not found", url);
1406 http_log(
"File '%s' not found\n", url);
1418 "HTTP/1.0 301 Moved\r\n"
1420 "Content-type: text/html\r\n"
1422 "<html><head><title>Moved</title></head><body>\r\n"
1423 "You should be <a href=\"%s\">redirected</a>.\r\n"
1424 "</body></html>\r\n",
1449 snprintf(msg,
sizeof(msg),
"This feed is already being received.");
1458 "HTTP/1.0 503 Server too busy\r\n"
1459 "Content-type: text/html\r\n"
1461 "<html><head><title>Too busy</title></head><body>\r\n"
1462 "<p>The server is too busy to serve your request at this time.</p>\r\n"
1463 "<p>The bandwidth being served (including your stream) is %"PRIu64
"kbit/sec, "
1464 "and this exceeds the limit of %"PRIu64
"kbit/sec.</p>\r\n"
1465 "</body></html>\r\n",
1476 const char *hostinfo = 0;
1478 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1483 p = strchr(p,
'\n');
1497 eoh = strchr(hostinfo,
'\n');
1499 if (eoh[-1] ==
'\r')
1502 if (eoh - hostinfo <
sizeof(hostbuf) - 1) {
1503 memcpy(hostbuf, hostinfo, eoh - hostinfo);
1504 hostbuf[eoh - hostinfo] = 0;
1508 switch(redir_type) {
1511 "HTTP/1.0 200 ASX Follows\r\n"
1512 "Content-type: video/x-ms-asf\r\n"
1514 "<ASX Version=\"3\">\r\n"
1516 "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n"
1517 "</ASX>\r\n", hostbuf, filename, info);
1522 "HTTP/1.0 200 RAM Follows\r\n"
1523 "Content-type: audio/x-pn-realaudio\r\n"
1525 "# Autogenerated by ffserver\r\n"
1526 "http://%s/%s%s\r\n", hostbuf, filename, info);
1531 "HTTP/1.0 200 ASF Redirect follows\r\n"
1532 "Content-type: video/x-ms-asf\r\n"
1535 "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info);
1540 char hostname[256], *p;
1542 av_strlcpy(hostname, hostbuf,
sizeof(hostname));
1543 p = strrchr(hostname,
':');
1547 "HTTP/1.0 200 RTSP Redirect follows\r\n"
1549 "Content-type: application/x-rtsp\r\n"
1551 "rtsp://%s:%d/%s\r\n", hostname, ntohs(config.
rtsp_addr.sin_port), filename);
1560 struct sockaddr_in my_addr;
1563 "HTTP/1.0 200 OK\r\n"
1564 "Content-type: application/sdp\r\n"
1568 len =
sizeof(my_addr);
1571 if (getsockname(c->
fd, (
struct sockaddr *)&my_addr, &len))
1572 http_log(
"getsockname() failed\n");
1578 if (sdp_data_size > 0) {
1579 memcpy(q, sdp_data, sdp_data_size);
1600 snprintf(msg,
sizeof(msg),
"ASX/RAM file not handled");
1613 const char *logline = 0;
1616 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1622 client_id = strtol(p + 18, 0, 10);
1623 p = strchr(p,
'\n');
1631 char *eol = strchr(logline,
'\n');
1636 if (eol[-1] ==
'\r')
1638 http_log(
"%.*s\n", (
int) (eol - logline), logline);
1651 for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->
next) {
1660 snprintf(msg,
sizeof(msg),
"POST command not handled");
1665 snprintf(msg,
sizeof(msg),
"could not open feed");
1683 snprintf(msg,
sizeof(msg),
"Input stream corresponding to '%s' not found", url);
1692 mime_type =
"application/x-octet-stream";
1718 "HTTP/1.0 404 Not Found\r\n"
1719 "Content-type: text/html\r\n"
1722 "<head><title>404 Not Found</title></head>\n"
1741 static const char suffix[] =
" kMGTP";
1744 for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++);
1772 avio_printf(pb,
"<link rel=\"shortcut icon\" href=\"%s\">\n",
1778 avio_printf(pb,
"<table cellspacing=0 cellpadding=4>\n");
1779 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");
1782 char sfilename[1024];
1785 if (stream->
feed == stream) {
1786 stream = stream->
next;
1791 eosf = sfilename + strlen(sfilename);
1792 if (eosf - sfilename >= 4) {
1793 if (strcmp(eosf - 4,
".asf") == 0)
1794 strcpy(eosf - 4,
".asx");
1795 else if (strcmp(eosf - 3,
".rm") == 0)
1796 strcpy(eosf - 3,
".ram");
1797 else if (stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
1801 eosf = strrchr(sfilename,
'.');
1803 eosf = sfilename + strlen(sfilename);
1805 strcpy(eosf,
".sdp");
1807 strcpy(eosf,
".rtsp");
1811 avio_printf(pb,
"<tr><td><a href=\"/%s\">%s</a> ",
1813 avio_printf(pb,
"<td align=right> %d <td align=right> ",
1819 int audio_bit_rate = 0;
1820 int video_bit_rate = 0;
1823 const char *audio_codec_name_extra =
"";
1824 const char *video_codec_name_extra =
"";
1834 if (*audio_codec_name)
1835 audio_codec_name_extra =
"...";
1836 audio_codec_name = codec->
name;
1842 if (*video_codec_name)
1843 video_codec_name_extra =
"...";
1844 video_codec_name = codec->
name;
1855 avio_printf(pb,
"<td align=center> %s <td align=right> %d "
1856 "<td align=right> %d <td> %s %s <td align=right> "
1859 video_bit_rate / 1000, video_codec_name,
1860 video_codec_name_extra, audio_bit_rate / 1000,
1861 audio_codec_name, audio_codec_name_extra);
1871 avio_printf(pb,
"<td align=center> - <td align=right> - "
1872 "<td align=right> - <td><td align=right> - <td>\n");
1875 stream = stream->
next;
1882 if (stream->
feed != stream) {
1883 stream = stream->
next;
1898 "ps -o \"%%cpu,cputime\" --no-headers %d",
1901 pid_stat = popen(ps_cmd,
"r");
1906 if (fscanf(pid_stat,
"%9s %63s", cpuperc, cpuused) == 2) {
1907 avio_printf(pb,
"Currently using %s%% of the cpu. "
1908 "Total time used %s.\n",
1919 avio_printf(pb,
"<table cellspacing=0 cellpadding=4><tr><th>Stream<th>"
1920 "type<th>kbits/s<th align=left>codec<th align=left>"
1926 const char *
type =
"unknown";
1927 char parameters[64];
1934 snprintf(parameters,
sizeof(parameters),
"%d channel(s), %d Hz",
1939 snprintf(parameters,
sizeof(parameters),
1948 avio_printf(pb,
"<tr><td align=right>%d<td>%s<td align=right>%d"
1951 codec ? codec->
name :
"", parameters);
1955 stream = stream->
next;
1961 avio_printf(pb,
"Number of connections: %d / %d<br>\n",
1964 avio_printf(pb,
"Bandwidth in use: %"PRIu64
"k / %"PRIu64
"k<br>\n",
1968 avio_printf(pb,
"<tr><th>#<th>File<th>IP<th>Proto<th>State<th>Target "
1969 "bits/sec<th>Actual bits/sec<th>Bytes transferred\n");
1988 avio_printf(pb,
"<tr><td><b>%d</b><td>%s%s<td>%s<td>%s<td>%s"
2006 avio_printf(pb,
"<hr size=1 noshade>Generated at %s", p);
2019 int buf_size, i,
ret;
2029 http_log(
"Invalid date specification '%s' for stream\n", buf);
2033 int prebuffer = strtol(buf, 0, 10);
2034 stream_pos =
av_gettime() - prebuffer * (int64_t)1000000;
2043 http_log(
"Invalid date specification '%s' for stream\n", buf);
2049 if (!input_filename[0]) {
2050 http_log(
"No filename was specified for stream\n");
2069 http_log(
"Could not find stream info for input '%s'\n", input_filename);
2103 int bytes_left, bytes_sent, frame_bytes;
2106 if (frame_bytes <= 0)
2110 bytes_sent = frame_bytes - bytes_left;
2166 http_log(
"Error writing output header for stream '%s': %s\n",
2201 }
else if (ret ==
AVERROR(EAGAIN)) {
2278 int max_packet_size;
2300 http_log(
"Error writing frame to output for stream '%s': %s\n",
2388 int interleaved_index,
size;
2404 interleaved_index++;
2407 header[1] = interleaved_index;
2408 header[2] = len >> 8;
2473 http_log(
"Stream feed '%s' was not opened\n",
2480 http_log(
"Cannot write to read-only file '%s'\n",
2489 http_log(
"Could not open feed file '%s': %s\n",
2501 http_log(
"Error truncating feed file '%s': %s\n",
2508 http_log(
"Error reading write index from feed file '%s': %s\n",
2519 lseek(fd, 0, SEEK_SET);
2532 int len, loop_run = 0;
2545 }
else if (len == 0) {
2555 }
else if (++loop_run > 10) {
2571 }
else if (len == 0)
2583 if (c->
buffer[0] !=
'f' ||
2585 http_log(
"Feed stream has become desynchronized -- disconnecting\n");
2601 http_log(
"Error writing to feed file: %s\n", strerror(errno));
2617 http_log(
"Error writing index to feed file: %s\n",
2623 for(c1 = first_http_ctx;
c1; c1 = c1->
next) {
2657 http_log(
"Feed '%s' stream number does not match registered feed\n",
2679 for(c1 = first_http_ctx;
c1; c1 = c1->
next) {
2699 str =
"Unknown Error";
2701 avio_printf(c->
pb,
"RTSP/1.0 %d %s\r\n", error_number, str);
2707 strftime(buf2,
sizeof(buf2),
"%a, %d %b %Y %H:%M:%S", tm);
2719 const char *p, *p1, *p2;
2732 get_word(protocol,
sizeof(protocol), &p);
2745 if (strcmp(protocol,
"RTSP/1.0")) {
2752 while (*p !=
'\n' && *p !=
'\0')
2756 while (*p !=
'\0') {
2757 p1 = memchr(p,
'\n', (
char *)c->
buffer_ptr - p);
2761 if (p2 > p && p2[-1] ==
'\r')
2767 if (len >
sizeof(line) - 1)
2768 len =
sizeof(line) - 1;
2769 memcpy(line, p, len);
2778 if (!strcmp(cmd,
"DESCRIBE"))
2780 else if (!strcmp(cmd,
"OPTIONS"))
2782 else if (!strcmp(cmd,
"SETUP"))
2784 else if (!strcmp(cmd,
"PLAY"))
2786 else if (!strcmp(cmd,
"PAUSE"))
2788 else if (!strcmp(cmd,
"TEARDOWN"))
2807 struct in_addr my_ip)
2818 if (!avc || !rtp_format) {
2823 entry ? entry->
value :
"No Title", 0);
2851 return *pbuffer ? strlen(*pbuffer) :
AVERROR(ENOMEM);
2860 "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
2872 struct sockaddr_in my_addr;
2882 stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp") &&
2895 len =
sizeof(my_addr);
2896 getsockname(c->
fd, (
struct sockaddr *)&my_addr, &len);
2898 if (content_length < 0) {
2905 avio_printf(c->
pb,
"Content-Length: %d\r\n", content_length);
2915 if (session_id[0] ==
'\0')
2918 for(c = first_http_ctx;
c; c = c->
next) {
2942 int stream_index, rtp_port, rtcp_port;
2948 struct sockaddr_in dest_addr;
2960 strcmp(stream->
fmt->
name,
"rtp")) {
2964 if (!strcmp(path, stream->
filename)) {
2973 for(stream_index = 0; stream_index < stream->
nb_streams;
2975 snprintf(buf,
sizeof(buf),
"%s/streamid=%d",
2977 if (!strcmp(path, buf))
2988 unsigned random0 =
av_lfg_get(&random_state);
2989 unsigned random1 =
av_lfg_get(&random_state);
3023 if (rtp_c->
stream != stream) {
3029 if (rtp_c->
rtp_ctx[stream_index]) {
3043 setup.transport_option[0] =
'\0';
3063 "client_port=%d-%d;server_port=%d-%d",
3065 rtp_port, rtcp_port);
3068 avio_printf(c->
pb,
"Transport: RTP/AVP/TCP;interleaved=%d-%d",
3069 stream_index * 2, stream_index * 2 + 1);
3074 if (setup.transport_option[0] !=
'\0')
3086 const char *session_id)
3105 snprintf(buf,
sizeof(buf),
"%s/streamid=%d",
3107 if(!strncmp(path, buf,
sizeof(buf))) {
3113 if (len > 0 && path[len - 1] ==
'/' &&
3181 const char *session_id,
3185 const char *proto_str;
3214 proto_str =
"MCAST";
3247 int stream_index,
struct sockaddr_in *dest_addr,
3255 int max_packet_size;
3282 ipaddr = inet_ntoa(dest_addr->sin_addr);
3296 "rtp://%s:%d?multicast=1&ttl=%d",
3297 ipaddr, ntohs(dest_addr->sin_port), ttl);
3300 "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
3317 http_log(
"%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
3318 ipaddr, ntohs(dest_addr->sin_port),
3338 c->
rtp_ctx[stream_index] = ctx;
3431 int mpeg4_count, i,
size;
3449 printf(
"MPEG4 without extra data: trying to find header in %s\n",
3451 while (mpeg4_count > 0) {
3461 while (p < pkt.
data + pkt.
size - 4) {
3463 if (p[0] == 0x00 && p[1] == 0x00 &&
3464 p[2] == 0x01 && p[3] == 0xb6) {
3465 size = p - pkt.
data;
3487 for(stream = config.
first_stream; stream; stream = stream_next) {
3489 stream_next = stream->
next;
3495 if (stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
3502 http_log(
"Unspecified feed file for stream '%s'\n",
3507 http_log(
"Opening feed file '%s' for stream '%s'\n",
3521 http_log(
"Could not find codec parameters from '%s'\n",
3545 feed = stream->
feed;
3580 http_log(
"Index & Id do not match for stream %d (%s)\n",
3588 #define CHECK_CODEC(x) (ccf->x != ccs->x)
3591 http_log(
"Codecs do not match for stream %d\n", i);
3594 http_log(
"Codec bitrates do not match for stream %d\n", i);
3601 http_log(
"Codec width, height and framerate do not match for stream %d\n", i);
3608 http_log(
"Codec sample_rate, channels, frame_size do not match for stream %d\n", i);
3620 http_log(
"Deleting feed file '%s' as stream counts differ (%d != %d)\n",
3625 http_log(
"Deleting feed file '%s' as it appears to be corrupt\n",
3630 http_log(
"Unable to delete feed file '%s' as it is marked readonly\n",
3641 http_log(
"Unable to create feed file '%s' as it is marked readonly\n",
3648 http_log(
"Could not open output feed file '%s'\n",
3656 http_log(
"Container doesn't support the required parameters\n");
3669 http_log(
"Could not open output feed file '%s'\n",
3675 feed->
feed_size = lseek(fd, 0, SEEK_END);
3704 stream->
bandwidth = (bandwidth + 999) / 1000;
3713 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
3717 if (feed->
pid == pid) {
3722 "%s: Pid %d exited with status %d after %d seconds\n",
3723 feed->
filename, pid, status, uptime);
3743 printf(
"usage: ffserver [options]\n"
3744 "Hyper fast multi format Audio/Video streaming server\n");
3752 {
"d", 0, {(
void*)
opt_debug},
"enable debug mode" },
3753 {
"f",
HAS_ARG |
OPT_STRING, {(
void*)&config.
filename },
"use configfile instead of /etc/ffserver.conf",
"configfile" },
3759 struct sigaction sigact = { { 0 } };
3774 unsetenv(
"http_proxy");
3779 sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
3780 sigaction(SIGCHLD, &sigact, 0);
3783 fprintf(stderr,
"Error reading configuration file '%s': %s\n",
3805 signal(SIGPIPE, SIG_IGN);
3808 http_log(
"Could not start server\n");