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 != NULL; 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 != NULL; 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));
884 while ((*cp) != NULL) {
893 for(c1 = first_http_ctx; c1 != NULL; 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;
1267 while (*p ==
' ' || *p ==
'\t')
1281 if ((q - buf) < buf_size - 1)
1300 if (*p ==
'\"' || *p ==
'\'')
1312 if ((q - buf) < buf_size - 1)
1317 if (quote && *p == quote)
1323 const char *p,
const char *filename,
int line_num)
1329 get_arg(arg,
sizeof(arg), &p);
1335 fprintf(stderr,
"%s:%d: ACL action '%s' is not ALLOW or DENY\n",
1336 filename, line_num, arg);
1340 get_arg(arg,
sizeof(arg), &p);
1343 fprintf(stderr,
"%s:%d: ACL refers to invalid host or IP address '%s'\n",
1344 filename, line_num, arg);
1349 get_arg(arg,
sizeof(arg), &p);
1353 fprintf(stderr,
"%s:%d: ACL refers to invalid host or IP address '%s'\n",
1354 filename, line_num, arg);
1367 naclp = &stream->
acl;
1373 fprintf(stderr,
"%s:%d: ACL found not in <stream> or <feed>\n",
1374 filename, line_num);
1380 naclp = &(*naclp)->
next;
1408 if (fgets(line,
sizeof(line), f) == NULL)
1414 if (*p ==
'\0' || *p ==
'#')
1416 get_arg(cmd,
sizeof(cmd), &p);
1443 unsigned long src_addr = src->s_addr;
1445 for (acl = in_acl; acl; acl = acl->
next) {
1446 if (src_addr >= acl->
first.s_addr && src_addr <= acl->last.s_addr)
1448 last_action = acl->
action;
1452 return (last_action ==
IP_DENY) ? 1 : 0;
1486 p = strrchr(file1,
'.');
1489 for(stream = first_stream; stream != NULL; stream = stream->
next) {
1491 p = strrchr(file2,
'.');
1494 if (!strcmp(file1, file2)) {
1517 char info[1024], filename[1024];
1521 const char *mime_type;
1525 const char *useragent = 0;
1531 if (!strcmp(cmd,
"GET"))
1533 else if (!strcmp(cmd,
"POST"))
1541 get_word(protocol,
sizeof(protocol), (
const char **)&p);
1542 if (strcmp(protocol,
"HTTP/1.0") && strcmp(protocol,
"HTTP/1.1"))
1548 http_log(
"%s - - New connection: %s %s\n", inet_ntoa(c->
from_addr.sin_addr), cmd, url);
1551 p1 = strchr(url,
'?');
1558 av_strlcpy(filename, url + ((*url ==
'/') ? 1 : 0),
sizeof(filename)-1);
1560 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1563 if (*useragent && *useragent !=
'\n' &&
av_isspace(*useragent))
1567 p = strchr(p,
'\n');
1577 filename[strlen(filename)-1] =
'f';
1584 strcpy(filename + strlen(filename)-2,
"m");
1594 if (!strlen(filename))
1595 av_strlcpy(filename,
"index.html",
sizeof(filename) - 1);
1598 while (stream != NULL) {
1601 stream = stream->
next;
1603 if (stream == NULL) {
1604 snprintf(msg,
sizeof(msg),
"File '%s' not found", url);
1605 http_log(
"File '%s' not found\n", url);
1617 "HTTP/1.0 301 Moved\r\n"
1619 "Content-type: text/html\r\n"
1621 "<html><head><title>Moved</title></head><body>\r\n"
1622 "You should be <a href=\"%s\">redirected</a>.\r\n"
1647 snprintf(msg,
sizeof(msg),
"This feed is already being received.");
1656 "HTTP/1.0 503 Server too busy\r\n"
1657 "Content-type: text/html\r\n"
1659 "<html><head><title>Too busy</title></head><body>\r\n"
1660 "<p>The server is too busy to serve your request at this time.</p>\r\n"
1661 "<p>The bandwidth being served (including your stream) is %"PRIu64
"kbit/sec, "
1662 "and this exceeds the limit of %"PRIu64
"kbit/sec.</p>\r\n"
1673 const char *hostinfo = 0;
1675 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1680 p = strchr(p,
'\n');
1694 eoh = strchr(hostinfo,
'\n');
1696 if (eoh[-1] ==
'\r')
1699 if (eoh - hostinfo <
sizeof(hostbuf) - 1) {
1700 memcpy(hostbuf, hostinfo, eoh - hostinfo);
1701 hostbuf[eoh - hostinfo] = 0;
1705 switch(redir_type) {
1708 "HTTP/1.0 200 ASX Follows\r\n"
1709 "Content-type: video/x-ms-asf\r\n"
1711 "<ASX Version=\"3\">\r\n"
1713 "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n"
1714 "</ASX>\r\n", hostbuf, filename, info);
1719 "HTTP/1.0 200 RAM Follows\r\n"
1720 "Content-type: audio/x-pn-realaudio\r\n"
1722 "# Autogenerated by ffserver\r\n"
1723 "http://%s/%s%s\r\n", hostbuf, filename, info);
1728 "HTTP/1.0 200 ASF Redirect follows\r\n"
1729 "Content-type: video/x-ms-asf\r\n"
1732 "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info);
1737 char hostname[256], *p;
1739 av_strlcpy(hostname, hostbuf,
sizeof(hostname));
1740 p = strrchr(hostname,
':');
1744 "HTTP/1.0 200 RTSP Redirect follows\r\n"
1746 "Content-type: application/x-rtsp\r\n"
1748 "rtsp://%s:%d/%s\r\n", hostname, ntohs(
my_rtsp_addr.sin_port), filename);
1757 struct sockaddr_in my_addr;
1760 "HTTP/1.0 200 OK\r\n"
1761 "Content-type: application/sdp\r\n"
1765 len =
sizeof(my_addr);
1768 if (getsockname(c->
fd, (
struct sockaddr *)&my_addr, &len))
1769 http_log(
"getsockname() failed\n");
1775 if (sdp_data_size > 0) {
1776 memcpy(q, sdp_data, sdp_data_size);
1797 snprintf(msg,
sizeof(msg),
"ASX/RAM file not handled");
1810 const char *logline = 0;
1813 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1819 client_id = strtol(p + 18, 0, 10);
1820 p = strchr(p,
'\n');
1828 char *eol = strchr(logline,
'\n');
1833 if (eol[-1] ==
'\r')
1835 http_log(
"%.*s\n", (
int) (eol - logline), logline);
1848 for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->
next) {
1857 snprintf(msg,
sizeof(msg),
"POST command not handled");
1862 snprintf(msg,
sizeof(msg),
"could not open feed");
1880 snprintf(msg,
sizeof(msg),
"Input stream corresponding to '%s' not found", url);
1889 mime_type =
"application/x-octet-stream";
1915 "HTTP/1.0 404 Not Found\r\n"
1916 "Content-type: text/html\r\n"
1919 "<head><title>404 Not Found</title></head>\n"
1938 static const char suffix[] =
" kMGTP";
1941 for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++);
1974 avio_printf(pb,
"<table cellspacing=0 cellpadding=4>\n");
1975 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");
1977 while (stream != NULL) {
1978 char sfilename[1024];
1981 if (stream->
feed != stream) {
1983 eosf = sfilename + strlen(sfilename);
1984 if (eosf - sfilename >= 4) {
1985 if (strcmp(eosf - 4,
".asf") == 0)
1986 strcpy(eosf - 4,
".asx");
1987 else if (strcmp(eosf - 3,
".rm") == 0)
1988 strcpy(eosf - 3,
".ram");
1989 else if (stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
1993 eosf = strrchr(sfilename,
'.');
1995 eosf = sfilename + strlen(sfilename);
1997 strcpy(eosf,
".sdp");
1999 strcpy(eosf,
".rtsp");
2003 avio_printf(pb,
"<tr><td><a href=\"/%s\">%s</a> ",
2005 avio_printf(pb,
"<td align=right> %d <td align=right> ",
2010 int audio_bit_rate = 0;
2011 int video_bit_rate = 0;
2014 const char *audio_codec_name_extra =
"";
2015 const char *video_codec_name_extra =
"";
2024 if (*audio_codec_name)
2025 audio_codec_name_extra =
"...";
2026 audio_codec_name = codec->
name;
2032 if (*video_codec_name)
2033 video_codec_name_extra =
"...";
2034 video_codec_name = codec->
name;
2044 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",
2047 video_bit_rate / 1000, video_codec_name, video_codec_name_extra,
2048 audio_bit_rate / 1000, audio_codec_name, audio_codec_name_extra);
2057 avio_printf(pb,
"<td align=center> - <td align=right> - <td align=right> - <td><td align=right> - <td>\n");
2061 stream = stream->
next;
2066 while (stream != NULL) {
2067 if (stream->
feed == stream) {
2079 "ps -o \"%%cpu,cputime\" --no-headers %d",
2082 pid_stat = popen(ps_cmd,
"r");
2087 if (fscanf(pid_stat,
"%9s %63s", cpuperc,
2089 avio_printf(pb,
"Currently using %s%% of the cpu. Total time used %s.\n",
2099 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");
2104 const char *
type =
"unknown";
2105 char parameters[64];
2122 avio_printf(pb,
"<tr><td align=right>%d<td>%s<td align=right>%d<td>%s<td>%s\n",
2128 stream = stream->
next;
2134 avio_printf(pb,
"Number of connections: %d / %d<br>\n",
2137 avio_printf(pb,
"Bandwidth in use: %"PRIu64
"k / %"PRIu64
"k<br>\n",
2141 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");
2144 while (c1 != NULL) {
2160 avio_printf(pb,
"<tr><td><b>%d</b><td>%s%s<td>%s<td>%s<td>%s<td align=right>",
2180 avio_printf(pb,
"<hr size=1 noshade>Generated at %s", p);
2193 int buf_size, i,
ret;
2203 http_log(
"Invalid date specification '%s' for stream\n", buf);
2207 int prebuffer = strtol(buf, 0, 10);
2208 stream_pos =
av_gettime() - prebuffer * (int64_t)1000000;
2217 http_log(
"Invalid date specification '%s' for stream\n", buf);
2223 if (!input_filename[0]) {
2224 http_log(
"No filename was specified for stream\n");
2241 http_log(
"Could not find stream info for input '%s'\n", input_filename);
2275 int bytes_left, bytes_sent, frame_bytes;
2278 if (frame_bytes <= 0)
2282 bytes_sent = frame_bytes - bytes_left;
2338 http_log(
"Error writing output header for stream '%s': %s\n",
2373 }
else if (ret ==
AVERROR(EAGAIN)) {
2450 int max_packet_size;
2472 http_log(
"Error writing frame to output for stream '%s': %s\n",
2559 int interleaved_index,
size;
2575 interleaved_index++;
2578 header[1] = interleaved_index;
2579 header[2] = len >> 8;
2657 http_log(
"Could not open feed file '%s': %s\n",
2669 http_log(
"Error truncating feed file '%s': %s\n",
2676 http_log(
"Error reading write index from feed file '%s': %s\n",
2686 lseek(fd, 0, SEEK_SET);
2699 int len, loop_run = 0;
2712 }
else if (len == 0) {
2722 }
else if (++loop_run > 10) {
2738 }
else if (len == 0)
2750 if (c->
buffer[0] !=
'f' ||
2752 http_log(
"Feed stream has become desynchronized -- disconnecting\n");
2768 http_log(
"Error writing to feed file: %s\n", strerror(errno));
2783 http_log(
"Error writing index to feed file: %s\n", strerror(errno));
2788 for(c1 = first_http_ctx; c1 != NULL; c1 = c1->
next) {
2809 0, NULL, NULL, NULL, NULL);
2822 http_log(
"Feed '%s' stream number does not match registered feed\n",
2844 for(c1 = first_http_ctx; c1 != NULL; c1 = c1->
next) {
2864 str =
"Unknown Error";
2866 avio_printf(c->
pb,
"RTSP/1.0 %d %s\r\n", error_number, str);
2872 strftime(buf2,
sizeof(buf2),
"%a, %d %b %Y %H:%M:%S", tm);
2884 const char *p, *p1, *p2;
2897 get_word(protocol,
sizeof(protocol), &p);
2910 if (strcmp(protocol,
"RTSP/1.0") != 0) {
2917 while (*p !=
'\n' && *p !=
'\0')
2921 while (*p !=
'\0') {
2922 p1 = memchr(p,
'\n', (
char *)c->
buffer_ptr - p);
2926 if (p2 > p && p2[-1] ==
'\r')
2932 if (len >
sizeof(line) - 1)
2933 len =
sizeof(line) - 1;
2934 memcpy(line, p, len);
2943 if (!strcmp(cmd,
"DESCRIBE"))
2945 else if (!strcmp(cmd,
"OPTIONS"))
2947 else if (!strcmp(cmd,
"SETUP"))
2949 else if (!strcmp(cmd,
"PLAY"))
2951 else if (!strcmp(cmd,
"PAUSE"))
2953 else if (!strcmp(cmd,
"TEARDOWN"))
2972 struct in_addr my_ip)
2981 if (avc == NULL || !rtp_format) {
2986 entry ? entry->
value :
"No Title", 0);
2999 if (avc->
nb_streams >= INT_MAX/
sizeof(*avs) ||
3016 return strlen(*pbuffer);
3024 avio_printf(c->
pb,
"Public: %s\r\n",
"OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
3036 struct sockaddr_in my_addr;
3039 av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1,
sizeof(path1), url);
3044 for(stream = first_stream; stream != NULL; stream = stream->
next) {
3046 stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp") &&
3059 len =
sizeof(my_addr);
3060 getsockname(c->
fd, (
struct sockaddr *)&my_addr, &len);
3062 if (content_length < 0) {
3069 avio_printf(c->
pb,
"Content-Length: %d\r\n", content_length);
3079 if (session_id[0] ==
'\0')
3082 for(c = first_http_ctx; c != NULL; c = c->
next) {
3106 int stream_index, rtp_port, rtcp_port;
3112 struct sockaddr_in dest_addr;
3116 av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1,
sizeof(path1), url);
3122 for(stream = first_stream; stream != NULL; stream = stream->
next) {
3124 stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
3126 if (!strcmp(path, stream->
filename)) {
3135 for(stream_index = 0; stream_index < stream->
nb_streams;
3137 snprintf(buf,
sizeof(buf),
"%s/streamid=%d",
3139 if (!strcmp(path, buf))
3151 unsigned random0 =
av_lfg_get(&random_state);
3152 unsigned random1 =
av_lfg_get(&random_state);
3186 if (rtp_c->
stream != stream) {
3192 if (rtp_c->
rtp_ctx[stream_index]) {
3206 setup.transport_option[0] =
'\0';
3226 "client_port=%d-%d;server_port=%d-%d",
3228 rtp_port, rtcp_port);
3231 avio_printf(c->
pb,
"Transport: RTP/AVP/TCP;interleaved=%d-%d",
3232 stream_index * 2, stream_index * 2 + 1);
3237 if (setup.transport_option[0] !=
'\0')
3249 const char *session_id)
3262 av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1,
sizeof(path1), url);
3268 snprintf(buf,
sizeof(buf),
"%s/streamid=%d",
3270 if(!strncmp(path, buf,
sizeof(buf))) {
3276 if (len > 0 && path[len - 1] ==
'/' &&
3342 FFStream *stream,
const char *session_id,
3346 const char *proto_str;
3375 proto_str =
"MCAST";
3408 int stream_index,
struct sockaddr_in *dest_addr,
3416 int max_packet_size;
3443 ipaddr = inet_ntoa(dest_addr->sin_addr);
3457 "rtp://%s:%d?multicast=1&ttl=%d",
3458 ipaddr, ntohs(dest_addr->sin_port), ttl);
3461 "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
3478 http_log(
"%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
3479 ipaddr, ntohs(dest_addr->sin_port),
3499 c->
rtp_ctx[stream_index] = ctx;
3583 while (*ps != NULL) {
3594 int mpeg4_count, i,
size;
3612 printf(
"MPEG4 without extra data: trying to find header in %s\n", infile->
filename);
3613 while (mpeg4_count > 0) {
3623 while (p < pkt.
data + pkt.
size - 4) {
3625 if (p[0] == 0x00 && p[1] == 0x00 &&
3626 p[2] == 0x01 && p[3] == 0xb6) {
3627 size = p - pkt.
data;
3649 for(stream = first_stream; stream != NULL; stream = stream_next) {
3651 stream_next = stream->
next;
3657 if (stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
3678 http_log(
"Could not find codec parameters from '%s'\n",
3701 for(stream = first_stream; stream != NULL; stream = stream->
next) {
3702 feed = stream->
feed;
3716 for(feed = first_feed; feed != NULL; feed = feed->
next_feed) {
3737 http_log(
"Index & Id do not match for stream %d (%s)\n",
3745 #define CHECK_CODEC(x) (ccf->x != ccs->x)
3748 http_log(
"Codecs do not match for stream %d\n", i);
3751 http_log(
"Codec bitrates do not match for stream %d\n", i);
3758 http_log(
"Codec width, height and framerate do not match for stream %d\n", i);
3765 http_log(
"Codec sample_rate, channels, frame_size do not match for stream %d\n", i);
3777 http_log(
"Deleting feed file '%s' as stream counts differ (%d != %d)\n",
3782 http_log(
"Deleting feed file '%s' as it appears to be corrupt\n",
3787 http_log(
"Unable to delete feed file '%s' as it is marked readonly\n",
3798 http_log(
"Unable to create feed file '%s' as it is marked readonly\n",
3805 http_log(
"Could not open output feed file '%s'\n",
3813 http_log(
"Container doesn't support the required parameters\n");
3826 http_log(
"Could not open output feed file '%s'\n",
3832 feed->
feed_size = lseek(fd, 0, SEEK_END);
3848 for(stream = first_stream; stream != NULL; stream = stream->
next) {
3861 stream->
bandwidth = (bandwidth + 999) / 1000;
3948 if (!codec || codec->
type != type)
3968 char filename[1000], tmp[1000], tmp2[1000],
line[1000];
3973 codec ? codec->
name : NULL))) {
3974 fprintf(stderr,
"File for preset '%s' not found\n", arg);
3979 int e= fscanf(f,
"%999[^\n]\n", line) - 1;
3980 if(line[0] ==
'#' && !e)
3982 e|= sscanf(line,
"%999[^=]=%999[^\n]\n", tmp, tmp2) - 2;
3984 fprintf(stderr,
"%s: Invalid syntax: '%s'\n", filename, line);
3988 if(!strcmp(tmp,
"acodec")){
3990 }
else if(!strcmp(tmp,
"vcodec")){
3992 }
else if(!strcmp(tmp,
"scodec")){
3995 fprintf(stderr,
"%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", filename, line, tmp, tmp2);
4012 char stream_format_name[64];
4014 snprintf(stream_format_name,
sizeof(stream_format_name),
"%s_stream", fmt->
name);
4028 av_log(NULL, log_level,
"%s:%d: ", filename, line_num);
4029 av_vlog(NULL, log_level, fmt, vl);
4040 char arg[1024], arg2[1024];
4042 int val, errors, warnings, line_num;
4043 FFStream **last_stream, *stream, *redirect;
4049 f = fopen(filename,
"r");
4052 av_log(NULL,
AV_LOG_ERROR,
"Could not open the configuration file '%s'\n", filename);
4056 errors = warnings = 0;
4058 first_stream = NULL;
4067 #define ERROR(...) report_config_error(filename, line_num, AV_LOG_ERROR, &errors, __VA_ARGS__)
4068 #define WARNING(...) report_config_error(filename, line_num, AV_LOG_WARNING, &warnings, __VA_ARGS__)
4071 if (fgets(line,
sizeof(line), f) == NULL)
4077 if (*p ==
'\0' || *p ==
'#')
4080 get_arg(cmd,
sizeof(cmd), &p);
4083 get_arg(arg,
sizeof(arg), &p);
4085 if (val < 1 || val > 65536) {
4086 ERROR(
"Invalid_port: %s\n", arg);
4090 get_arg(arg,
sizeof(arg), &p);
4092 ERROR(
"%s:%d: Invalid host/IP address: %s\n", arg);
4095 WARNING(
"NoDaemon option has no effect, you should remove it\n");
4097 get_arg(arg,
sizeof(arg), &p);
4099 if (val < 1 || val > 65536) {
4100 ERROR(
"%s:%d: Invalid port: %s\n", arg);
4104 get_arg(arg,
sizeof(arg), &p);
4106 ERROR(
"Invalid host/IP address: %s\n", arg);
4109 get_arg(arg,
sizeof(arg), &p);
4111 if (val < 1 || val > 65536) {
4112 ERROR(
"Invalid MaxHTTPConnections: %s\n", arg);
4116 get_arg(arg,
sizeof(arg), &p);
4119 ERROR(
"Invalid MaxClients: %s\n", arg);
4125 get_arg(arg,
sizeof(arg), &p);
4126 llval = strtoll(arg, NULL, 10);
4127 if (llval < 10 || llval > 10000000) {
4128 ERROR(
"Invalid MaxBandwidth: %s\n", arg);
4138 if (stream || feed) {
4139 ERROR(
"Already in a tag\n");
4151 for (s = first_feed;
s; s = s->
next) {
4166 *last_stream = feed;
4167 last_stream = &feed->
next;
4181 for (i = 0; i < 62; i++) {
4182 get_arg(arg,
sizeof(arg), &p);
4195 (
my_http_addr.sin_addr.s_addr == INADDR_ANY) ?
"127.0.0.1" :
4207 }
else if (stream) {
4212 get_arg(arg,
sizeof(arg), &p);
4217 WARNING(
"Truncate N syntax in configuration file is deprecated, "
4218 "use Truncate alone with no arguments\n");
4227 get_arg(arg,
sizeof(arg), &p);
4235 fsize *= 1024 * 1024;
4238 fsize *= 1024 * 1024 * 1024;
4248 ERROR(
"No corresponding <Feed> for </Feed>\n");
4255 if (stream || feed) {
4256 ERROR(
"Already in a tag\n");
4265 q = strrchr(stream->
filename,
'>');
4269 for (s = first_stream;
s; s = s->
next) {
4286 *last_stream = stream;
4287 last_stream = &stream->
next;
4290 get_arg(arg,
sizeof(arg), &p);
4295 while (sfeed != NULL) {
4301 ERROR(
"Feed with name '%s' for stream '%s' is not defined\n", arg, stream->
filename);
4303 stream->
feed = sfeed;
4306 get_arg(arg,
sizeof(arg), &p);
4308 if (!strcmp(arg,
"status")) {
4314 if (!strcmp(arg,
"jpeg"))
4315 strcpy(arg,
"mjpeg");
4318 ERROR(
"Unknown Format: %s\n", arg);
4327 get_arg(arg,
sizeof(arg), &p);
4330 if (!stream->
ifmt) {
4331 ERROR(
"Unknown input format: %s\n", arg);
4338 ERROR(
"FaviconURL only permitted for status streams\n");
4344 get_arg(arg,
sizeof(arg), &p);
4350 for (i = 0; i < strlen(cmd); i++)
4353 WARNING(
"'%s' option in configuration file is deprecated, "
4354 "use 'Metadata %s VALUE' instead\n", cmd, key);
4356 ERROR(
"Could not set metadata '%s' to value '%s': %s\n",
4361 get_arg(arg,
sizeof(arg), &p);
4362 get_arg(arg2,
sizeof(arg2), &p);
4366 ERROR(
"Could not set metadata '%s' to value '%s': %s\n",
4371 get_arg(arg,
sizeof(arg), &p);
4378 get_arg(arg,
sizeof(arg), &p);
4381 ERROR(
"Unknown AudioCodec: %s\n", arg);
4384 get_arg(arg,
sizeof(arg), &p);
4387 ERROR(
"Unknown VideoCodec: %s\n", arg);
4390 get_arg(arg,
sizeof(arg), &p);
4392 stream->
max_time = atof(arg) * 1000;
4394 get_arg(arg,
sizeof(arg), &p);
4398 get_arg(arg,
sizeof(arg), &p);
4402 get_arg(arg,
sizeof(arg), &p);
4407 int minrate, maxrate;
4409 get_arg(arg,
sizeof(arg), &p);
4411 if (sscanf(arg,
"%d-%d", &minrate, &maxrate) == 2) {
4415 ERROR(
"Incorrect format for VideoBitRateRange -- should be <min>-<max>: %s\n", arg);
4420 get_arg(arg,
sizeof(arg), &p);
4421 video_enc.
debug = strtol(arg,0,0);
4425 get_arg(arg,
sizeof(arg), &p);
4430 get_arg(arg,
sizeof(arg), &p);
4435 get_arg(arg,
sizeof(arg), &p);
4439 get_arg(arg,
sizeof(arg), &p);
4441 video_enc.
bit_rate = atoi(arg) * 1000;
4444 get_arg(arg,
sizeof(arg), &p);
4448 ERROR(
"Invalid video size '%s'\n", arg);
4450 if ((video_enc.
width % 16) != 0 ||
4451 (video_enc.
height % 16) != 0) {
4452 ERROR(
"Image size must be a multiple of 16\n");
4457 get_arg(arg,
sizeof(arg), &p);
4461 ERROR(
"Incorrect frame rate: %s\n", arg);
4468 get_arg(arg,
sizeof(arg), &p);
4472 ERROR(
"Unknown pixel format: %s\n", arg);
4476 get_arg(arg,
sizeof(arg), &p);
4494 get_arg(arg,
sizeof(arg), &p);
4495 get_arg(arg2,
sizeof(arg2), &p);
4504 ERROR(
"Error setting %s option to %s %s\n", cmd, arg, arg2);
4510 get_arg(arg,
sizeof(arg), &p);
4521 ERROR(
"AVPreset error: %s\n", arg);
4524 get_arg(arg,
sizeof(arg), &p);
4525 if ((strlen(arg) == 4) && stream)
4537 get_arg(arg,
sizeof(arg), &p);
4543 get_arg(arg,
sizeof(arg), &p);
4547 ERROR(
"VideoQDiff out of range\n");
4551 get_arg(arg,
sizeof(arg), &p);
4553 video_enc.
qmax = atoi(arg);
4554 if (video_enc.
qmax < 1 || video_enc.
qmax > 31) {
4555 ERROR(
"VideoQMax out of range\n");
4559 get_arg(arg,
sizeof(arg), &p);
4561 video_enc.
qmin = atoi(arg);
4562 if (video_enc.
qmin < 1 || video_enc.
qmin > 31) {
4563 ERROR(
"VideoQMin out of range\n");
4567 get_arg(arg,
sizeof(arg), &p);
4571 get_arg(arg,
sizeof(arg), &p);
4585 get_arg(arg,
sizeof(arg), &p);
4591 get_arg(arg,
sizeof(arg), &p);
4594 ERROR(
"Invalid host/IP address: %s\n", arg);
4600 get_arg(arg,
sizeof(arg), &p);
4604 get_arg(arg,
sizeof(arg), &p);
4612 ERROR(
"No corresponding <Stream> for </Stream>\n");
4614 if (stream->
feed && stream->
fmt && strcmp(stream->
fmt->
name,
"ffm") != 0) {
4631 if (stream || feed || redirect) {
4632 ERROR(
"Already in a tag\n");
4639 *last_stream = redirect;
4640 last_stream = &redirect->
next;
4643 q = strrchr(redirect->
filename,
'>');
4653 ERROR(
"No corresponding <Redirect> for </Redirect>\n");
4656 ERROR(
"No URL found for <Redirect>\n");
4661 ERROR(
"Loadable modules no longer supported\n");
4663 ERROR(
"Incorrect keyword: '%s'\n", cmd);
4683 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
4686 for (feed = first_feed; feed; feed = feed->
next) {
4687 if (feed->
pid == pid) {
4691 fprintf(stderr,
"%s: Pid %d exited with status %d after %d seconds\n", feed->
filename, pid, status, uptime);
4711 printf(
"usage: ffserver [options]\n"
4712 "Hyper fast multi format Audio/Video streaming server\n");
4720 {
"d", 0, {(
void*)
opt_debug},
"enable debug mode" },
4727 struct sigaction sigact = { { 0 } };
4742 unsetenv(
"http_proxy");
4747 sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
4748 sigaction(SIGCHLD, &sigact, 0);
4751 fprintf(stderr,
"Error reading configuration file '%s': %s\n",
4773 signal(SIGPIPE, SIG_IGN);
4776 http_log(
"Could not start server\n");