28 #define closesocket close
58 #include <sys/ioctl.h>
108 #define MAX_STREAMS 20
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)
299 struct in_addr my_ip);
303 FFStream *stream,
const char *session_id,
306 int stream_index,
struct sockaddr_in *dest_addr,
335 if (lseek(fd, 8, SEEK_SET) < 0)
337 if (read(fd, buf, 8) != 8)
348 buf[i] = (pos >> (56 - i * 8)) & 0xff;
349 if (lseek(fd, 8, SEEK_SET) < 0)
351 if (write(fd, buf, 8) != 8)
366 static int resolve_host(
struct in_addr *sin_addr,
const char *hostname)
379 for (cur = ai; cur; cur = cur->
ai_next) {
381 *sin_addr = ((
struct sockaddr_in *)cur->
ai_addr)->sin_addr;
390 hp = gethostbyname(hostname);
393 memcpy(sin_addr, hp->h_addr_list[0],
sizeof(
struct in_addr));
399 static char *
ctime1(
char *buf2,
int buf_size)
407 p = buf2 + strlen(p) - 1;
415 static int print_prefix = 1;
422 print_prefix = strstr(fmt,
"\n") != NULL;
429 __attribute__ ((format (printf, 1, 2)))
434 va_start(vargs, fmt);
441 static int print_prefix = 1;
445 if (print_prefix && avc)
447 print_prefix = strstr(fmt,
"\n") != NULL;
456 http_log(
"%s - - [%s] \"%s %s\" %d %"PRId64
"\n",
489 for (; feed; feed = feed->
next) {
496 http_log(
"Unable to create children\n");
507 slash = strrchr(pathname,
'/');
512 strcpy(slash,
"ffmpeg");
520 for (i = 3; i < 256; i++)
524 if (!freopen(
"/dev/null",
"r", stdin))
525 http_log(
"failed to redirect STDIN to /dev/null\n;");
526 if (!freopen(
"/dev/null",
"w", stdout))
527 http_log(
"failed to redirect STDOUT to /dev/null\n;");
528 if (!freopen(
"/dev/null",
"w", stderr))
529 http_log(
"failed to redirect STDERR to /dev/null\n;");
532 signal(SIGPIPE, SIG_DFL);
547 server_fd = socket(AF_INET,SOCK_STREAM,0);
554 setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp,
sizeof(tmp));
556 my_addr->sin_family = AF_INET;
557 if (bind (server_fd, (
struct sockaddr *) my_addr,
sizeof (*my_addr)) < 0) {
559 snprintf(bindmsg,
sizeof(bindmsg),
"bind(port %d)", ntohs(my_addr->sin_port));
565 if (listen (server_fd, 5) < 0) {
581 struct sockaddr_in dest_addr = {0};
582 int default_port, stream_index;
585 for(stream = first_stream; stream != NULL; stream = stream->
next) {
590 snprintf(session_id,
sizeof(session_id),
"%08x%08x",
599 dest_addr.sin_family = AF_INET;
609 http_log(
"Could not open input stream for stream '%s'\n",
615 for(stream_index = 0; stream_index < stream->
nb_streams;
620 http_log(
"Could not open output stream '%s/streamid=%d'\n",
635 int server_fd = 0, rtsp_server_fd = 0;
636 int ret, delay, delay1;
637 struct pollfd *poll_table, *poll_entry;
653 if (rtsp_server_fd < 0)
657 if (!rtsp_server_fd && !server_fd) {
658 http_log(
"HTTP and RTSP disabled.\n");
669 poll_entry = poll_table;
671 poll_entry->fd = server_fd;
672 poll_entry->events = POLLIN;
675 if (rtsp_server_fd) {
676 poll_entry->fd = rtsp_server_fd;
677 poll_entry->events = POLLIN;
693 poll_entry->events = POLLOUT;
703 poll_entry->events = POLLOUT;
721 poll_entry->events = POLLIN;
734 ret = poll(poll_table, poll_entry - poll_table, delay);
748 for(c = first_http_ctx; c != NULL; c = c_next) {
757 poll_entry = poll_table;
760 if (poll_entry->revents & POLLIN)
764 if (rtsp_server_fd) {
766 if (poll_entry->revents & POLLIN)
791 "HTTP/1.0 503 Server too busy\r\n"
792 "Content-type: text/html\r\n"
794 "<html><head><title>Too busy</title></head><body>\r\n"
795 "<p>The server is too busy to serve your request at this time.</p>\r\n"
796 "<p>The number of current connections is %u, and this exceeds the limit of %u.</p>\r\n"
797 "</body></html>\r\n",
800 send(fd, buffer, len, 0);
806 struct sockaddr_in from_addr;
811 len =
sizeof(from_addr);
812 fd = accept(server_fd, (
struct sockaddr *)&from_addr,
815 http_log(
"error during accept %s\n", strerror(errno));
864 while ((*cp) != NULL) {
873 for(c1 = first_http_ctx; c1 != NULL; c1 = c1->
next) {
896 for(i=0;i<nb_streams;i++) {
953 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
966 }
else if (len == 0) {
973 if ((ptr >= c->
buffer + 2 && !memcmp(ptr-2,
"\n\n", 2)) ||
974 (ptr >= c->
buffer + 4 && !memcmp(ptr-4,
"\r\n\r\n", 4))) {
986 }
else goto read_loop;
991 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1029 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1044 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1053 if (c->
poll_entry->revents & (POLLIN | POLLERR | POLLHUP))
1060 if (c->
poll_entry->revents & (POLLERR | POLLHUP)) {
1086 if (c->
poll_entry->revents & (POLLERR | POLLHUP)) {
1124 for (p = request; *p && *p !=
'\r' && *p !=
'\n'; ) {
1126 const char *q = p + 7;
1137 memset(rates, 0xff, ratelen);
1140 while (*q && *q !=
'\n' && *q !=
':')
1143 if (sscanf(q,
":%d:%d", &stream_no, &rate_no) != 2)
1147 if (stream_no < ratelen && stream_no >= 0)
1148 rates[stream_no] = rate_no;
1157 p = strchr(p,
'\n');
1170 int best_bitrate = 100000000;
1188 if (feed_codec->
bit_rate <= bit_rate) {
1189 if (best_bitrate > bit_rate || feed_codec->
bit_rate > best_bitrate) {
1190 best_bitrate = feed_codec->
bit_rate;
1194 if (feed_codec->
bit_rate < best_bitrate) {
1195 best_bitrate = feed_codec->
bit_rate;
1208 int action_required = 0;
1236 action_required = 1;
1239 return action_required;
1248 while (*p ==
' ' || *p ==
'\t')
1262 if ((q - buf) < buf_size - 1)
1281 if (*p ==
'\"' || *p ==
'\'')
1293 if ((q - buf) < buf_size - 1)
1298 if (quote && *p == quote)
1304 const char *p,
const char *filename,
int line_num)
1310 get_arg(arg,
sizeof(arg), &p);
1316 fprintf(stderr,
"%s:%d: ACL action '%s' is not ALLOW or DENY\n",
1317 filename, line_num, arg);
1321 get_arg(arg,
sizeof(arg), &p);
1324 fprintf(stderr,
"%s:%d: ACL refers to invalid host or ip address '%s'\n",
1325 filename, line_num, arg);
1330 get_arg(arg,
sizeof(arg), &p);
1334 fprintf(stderr,
"%s:%d: ACL refers to invalid host or ip address '%s'\n",
1335 filename, line_num, arg);
1348 naclp = &stream->
acl;
1354 fprintf(stderr,
"%s:%d: ACL found not in <stream> or <feed>\n",
1355 filename, line_num);
1361 naclp = &(*naclp)->
next;
1388 if (fgets(line,
sizeof(line), f) == NULL)
1394 if (*p ==
'\0' || *p ==
'#')
1396 get_arg(cmd,
sizeof(cmd), &p);
1423 unsigned long src_addr = src->s_addr;
1425 for (acl = in_acl; acl; acl = acl->
next) {
1426 if (src_addr >= acl->
first.s_addr && src_addr <= acl->last.s_addr)
1428 last_action = acl->
action;
1432 return (last_action ==
IP_DENY) ? 1 : 0;
1466 p = strrchr(file1,
'.');
1469 for(stream = first_stream; stream != NULL; stream = stream->
next) {
1471 p = strrchr(file2,
'.');
1474 if (!strcmp(file1, file2)) {
1497 char info[1024], filename[1024];
1501 const char *mime_type;
1505 const char *useragent = 0;
1511 if (!strcmp(cmd,
"GET"))
1513 else if (!strcmp(cmd,
"POST"))
1521 get_word(protocol,
sizeof(protocol), (
const char **)&p);
1522 if (strcmp(protocol,
"HTTP/1.0") && strcmp(protocol,
"HTTP/1.1"))
1528 http_log(
"%s - - New connection: %s %s\n", inet_ntoa(c->
from_addr.sin_addr), cmd, url);
1531 p1 = strchr(url,
'?');
1538 av_strlcpy(filename, url + ((*url ==
'/') ? 1 : 0),
sizeof(filename)-1);
1540 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1543 if (*useragent && *useragent !=
'\n' &&
av_isspace(*useragent))
1547 p = strchr(p,
'\n');
1557 filename[strlen(filename)-1] =
'f';
1564 strcpy(filename + strlen(filename)-2,
"m");
1574 if (!strlen(filename))
1575 av_strlcpy(filename,
"index.html",
sizeof(filename) - 1);
1578 while (stream != NULL) {
1581 stream = stream->
next;
1583 if (stream == NULL) {
1584 snprintf(msg,
sizeof(msg),
"File '%s' not found", url);
1585 http_log(
"File '%s' not found\n", url);
1597 "HTTP/1.0 301 Moved\r\n"
1599 "Content-type: text/html\r\n"
1601 "<html><head><title>Moved</title></head><body>\r\n"
1602 "You should be <a href=\"%s\">redirected</a>.\r\n"
1627 snprintf(msg,
sizeof(msg),
"This feed is already being received.");
1636 "HTTP/1.0 503 Server too busy\r\n"
1637 "Content-type: text/html\r\n"
1639 "<html><head><title>Too busy</title></head><body>\r\n"
1640 "<p>The server is too busy to serve your request at this time.</p>\r\n"
1641 "<p>The bandwidth being served (including your stream) is %"PRIu64
"kbit/sec, "
1642 "and this exceeds the limit of %"PRIu64
"kbit/sec.</p>\r\n"
1653 const char *hostinfo = 0;
1655 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1660 p = strchr(p,
'\n');
1674 eoh = strchr(hostinfo,
'\n');
1676 if (eoh[-1] ==
'\r')
1679 if (eoh - hostinfo <
sizeof(hostbuf) - 1) {
1680 memcpy(hostbuf, hostinfo, eoh - hostinfo);
1681 hostbuf[eoh - hostinfo] = 0;
1685 switch(redir_type) {
1688 "HTTP/1.0 200 ASX Follows\r\n"
1689 "Content-type: video/x-ms-asf\r\n"
1691 "<ASX Version=\"3\">\r\n"
1693 "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n"
1694 "</ASX>\r\n", hostbuf, filename, info);
1699 "HTTP/1.0 200 RAM Follows\r\n"
1700 "Content-type: audio/x-pn-realaudio\r\n"
1702 "# Autogenerated by ffserver\r\n"
1703 "http://%s/%s%s\r\n", hostbuf, filename, info);
1708 "HTTP/1.0 200 ASF Redirect follows\r\n"
1709 "Content-type: video/x-ms-asf\r\n"
1712 "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info);
1717 char hostname[256], *p;
1719 av_strlcpy(hostname, hostbuf,
sizeof(hostname));
1720 p = strrchr(hostname,
':');
1724 "HTTP/1.0 200 RTSP Redirect follows\r\n"
1726 "Content-type: application/x-rtsp\r\n"
1728 "rtsp://%s:%d/%s\r\n", hostname, ntohs(
my_rtsp_addr.sin_port), filename);
1737 struct sockaddr_in my_addr;
1740 "HTTP/1.0 200 OK\r\n"
1741 "Content-type: application/sdp\r\n"
1745 len =
sizeof(my_addr);
1746 getsockname(c->
fd, (
struct sockaddr *)&my_addr, &len);
1752 if (sdp_data_size > 0) {
1753 memcpy(q, sdp_data, sdp_data_size);
1774 snprintf(msg,
sizeof(msg),
"ASX/RAM file not handled");
1787 const char *logline = 0;
1790 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1796 client_id = strtol(p + 18, 0, 10);
1797 p = strchr(p,
'\n');
1805 char *eol = strchr(logline,
'\n');
1810 if (eol[-1] ==
'\r')
1812 http_log(
"%.*s\n", (
int) (eol - logline), logline);
1825 for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->
next) {
1834 snprintf(msg,
sizeof(msg),
"POST command not handled");
1839 snprintf(msg,
sizeof(msg),
"could not open feed");
1857 snprintf(msg,
sizeof(msg),
"Input stream corresponding to '%s' not found", url);
1866 mime_type =
"application/x-octet-stream";
1891 "HTTP/1.0 404 Not Found\r\n"
1892 "Content-type: text/html\r\n"
1895 "<head><title>404 Not Found</title></head>\n"
1914 static const char suffix[] =
" kMGTP";
1917 for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++);
1939 avio_printf(pb,
"Content-type: %s\r\n",
"text/html");
1950 avio_printf(pb,
"<table cellspacing=0 cellpadding=4>\n");
1951 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");
1953 while (stream != NULL) {
1954 char sfilename[1024];
1957 if (stream->
feed != stream) {
1959 eosf = sfilename + strlen(sfilename);
1960 if (eosf - sfilename >= 4) {
1961 if (strcmp(eosf - 4,
".asf") == 0)
1962 strcpy(eosf - 4,
".asx");
1963 else if (strcmp(eosf - 3,
".rm") == 0)
1964 strcpy(eosf - 3,
".ram");
1965 else if (stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
1969 eosf = strrchr(sfilename,
'.');
1971 eosf = sfilename + strlen(sfilename);
1973 strcpy(eosf,
".sdp");
1975 strcpy(eosf,
".rtsp");
1979 avio_printf(pb,
"<tr><td><a href=\"/%s\">%s</a> ",
1981 avio_printf(pb,
"<td align=right> %d <td align=right> ",
1986 int audio_bit_rate = 0;
1987 int video_bit_rate = 0;
1990 const char *audio_codec_name_extra =
"";
1991 const char *video_codec_name_extra =
"";
2000 if (*audio_codec_name)
2001 audio_codec_name_extra =
"...";
2002 audio_codec_name = codec->
name;
2008 if (*video_codec_name)
2009 video_codec_name_extra =
"...";
2010 video_codec_name = codec->
name;
2020 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",
2023 video_bit_rate / 1000, video_codec_name, video_codec_name_extra,
2024 audio_bit_rate / 1000, audio_codec_name, audio_codec_name_extra);
2033 avio_printf(pb,
"<td align=center> - <td align=right> - <td align=right> - <td><td align=right> - <td>\n");
2037 stream = stream->
next;
2042 while (stream != NULL) {
2043 if (stream->
feed == stream) {
2055 "ps -o \"%%cpu,cputime\" --no-headers %d",
2058 pid_stat = popen(ps_cmd,
"r");
2063 if (fscanf(pid_stat,
"%9s %63s", cpuperc,
2065 avio_printf(pb,
"Currently using %s%% of the cpu. Total time used %s.\n",
2075 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");
2080 const char *
type =
"unknown";
2081 char parameters[64];
2098 avio_printf(pb,
"<tr><td align=right>%d<td>%s<td align=right>%d<td>%s<td>%s\n",
2104 stream = stream->
next;
2110 avio_printf(pb,
"Number of connections: %d / %d<br>\n",
2113 avio_printf(pb,
"Bandwidth in use: %"PRIu64
"k / %"PRIu64
"k<br>\n",
2117 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");
2120 while (c1 != NULL) {
2136 avio_printf(pb,
"<tr><td><b>%d</b><td>%s%s<td>%s<td>%s<td>%s<td align=right>",
2156 avio_printf(pb,
"<hr size=1 noshade>Generated at %s", p);
2169 int buf_size, i,
ret;
2181 int prebuffer = strtol(buf, 0, 10);
2182 stream_pos =
av_gettime() - prebuffer * (int64_t)1000000;
2195 if (input_filename[0] ==
'\0')
2200 http_log(
"could not open %s: %d\n", input_filename, ret);
2210 http_log(
"Could not find stream info '%s'\n", input_filename);
2244 int bytes_left, bytes_sent, frame_bytes;
2247 if (frame_bytes <= 0)
2251 bytes_sent = frame_bytes - bytes_left;
2309 http_log(
"Error writing output header\n");
2343 }
else if (ret ==
AVERROR(EAGAIN)) {
2420 int max_packet_size;
2442 http_log(
"Error writing frame to output\n");
2528 int interleaved_index,
size;
2544 interleaved_index++;
2547 header[1] = interleaved_index;
2548 header[2] = len >> 8;
2620 http_log(
"Error opening feeder file: %s\n", strerror(errno));
2630 http_log(
"Error truncating feed file: %s\n", strerror(errno));
2635 http_log(
"Error reading write index from feed file: %s\n", strerror(errno));
2642 lseek(fd, 0, SEEK_SET);
2655 int len, loop_run = 0;
2668 }
else if (len == 0) {
2678 }
else if (++loop_run > 10) {
2694 }
else if (len == 0)
2706 if (c->
buffer[0] !=
'f' ||
2708 http_log(
"Feed stream has become desynchronized -- disconnecting\n");
2721 http_log(
"Error writing to feed file: %s\n", strerror(errno));
2736 http_log(
"Error writing index to feed file: %s\n", strerror(errno));
2741 for(c1 = first_http_ctx; c1 != NULL; c1 = c1->
next) {
2762 0, NULL, NULL, NULL, NULL);
2775 http_log(
"Feed '%s' stream number does not match registered feed\n",
2797 for(c1 = first_http_ctx; c1 != NULL; c1 = c1->
next) {
2815 switch(error_number) {
2820 str =
"Method Not Allowed";
2823 str =
"Not Enough Bandwidth";
2826 str =
"Session Not Found";
2829 str =
"Method Not Valid in This State";
2832 str =
"Aggregate operation not allowed";
2835 str =
"Only aggregate operation allowed";
2838 str =
"Unsupported transport";
2841 str =
"Internal Server Error";
2844 str =
"Service Unavailable";
2847 str =
"RTSP Version not supported";
2850 str =
"Unknown Error";
2854 avio_printf(c->
pb,
"RTSP/1.0 %d %s\r\n", error_number, str);
2860 strftime(buf2,
sizeof(buf2),
"%a, %d %b %Y %H:%M:%S", tm);
2872 const char *p, *p1, *p2;
2885 get_word(protocol,
sizeof(protocol), &p);
2898 if (strcmp(protocol,
"RTSP/1.0") != 0) {
2905 while (*p !=
'\n' && *p !=
'\0')
2909 while (*p !=
'\0') {
2910 p1 = memchr(p,
'\n', (
char *)c->
buffer_ptr - p);
2914 if (p2 > p && p2[-1] ==
'\r')
2920 if (len >
sizeof(line) - 1)
2921 len =
sizeof(line) - 1;
2922 memcpy(line, p, len);
2929 c->
seq = header->seq;
2931 if (!strcmp(cmd,
"DESCRIBE"))
2933 else if (!strcmp(cmd,
"OPTIONS"))
2935 else if (!strcmp(cmd,
"SETUP"))
2937 else if (!strcmp(cmd,
"PLAY"))
2939 else if (!strcmp(cmd,
"PAUSE"))
2941 else if (!strcmp(cmd,
"TEARDOWN"))
2960 struct in_addr my_ip)
2968 if (avc == NULL || !rtp_format) {
2973 stream->
title[0] ? stream->
title :
"No Title", 0);
2986 if (avc->
nb_streams >= INT_MAX/
sizeof(*avs) ||
3003 return strlen(*pbuffer);
3011 avio_printf(c->
pb,
"Public: %s\r\n",
"OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
3023 struct sockaddr_in my_addr;
3026 av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1,
sizeof(path1), url);
3031 for(stream = first_stream; stream != NULL; stream = stream->
next) {
3033 stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp") &&
3046 len =
sizeof(my_addr);
3047 getsockname(c->
fd, (
struct sockaddr *)&my_addr, &len);
3049 if (content_length < 0) {
3056 avio_printf(c->
pb,
"Content-Length: %d\r\n", content_length);
3066 if (session_id[0] ==
'\0')
3069 for(c = first_http_ctx; c != NULL; c = c->
next) {
3093 int stream_index, rtp_port, rtcp_port;
3099 struct sockaddr_in dest_addr;
3103 av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1,
sizeof(path1), url);
3109 for(stream = first_stream; stream != NULL; stream = stream->
next) {
3111 stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
3113 if (!strcmp(path, stream->
filename)) {
3122 for(stream_index = 0; stream_index < stream->
nb_streams;
3124 snprintf(buf,
sizeof(buf),
"%s/streamid=%d",
3126 if (!strcmp(path, buf))
3138 unsigned random0 =
av_lfg_get(&random_state);
3139 unsigned random1 =
av_lfg_get(&random_state);
3173 if (rtp_c->
stream != stream) {
3179 if (rtp_c->
rtp_ctx[stream_index]) {
3193 setup.transport_option[0] =
'\0';
3213 "client_port=%d-%d;server_port=%d-%d",
3215 rtp_port, rtcp_port);
3218 avio_printf(c->
pb,
"Transport: RTP/AVP/TCP;interleaved=%d-%d",
3219 stream_index * 2, stream_index * 2 + 1);
3224 if (setup.transport_option[0] !=
'\0')
3236 const char *session_id)
3249 av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1,
sizeof(path1), url);
3255 snprintf(buf,
sizeof(buf),
"%s/streamid=%d",
3257 if(!strncmp(path, buf,
sizeof(buf))) {
3263 if (len > 0 && path[len - 1] ==
'/' &&
3345 FFStream *stream,
const char *session_id,
3349 const char *proto_str;
3378 proto_str =
"MCAST";
3411 int stream_index,
struct sockaddr_in *dest_addr,
3419 int max_packet_size;
3446 ipaddr = inet_ntoa(dest_addr->sin_addr);
3460 "rtp://%s:%d?multicast=1&ttl=%d",
3461 ipaddr, ntohs(dest_addr->sin_port), ttl);
3464 "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
3481 http_log(
"%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
3482 ipaddr, ntohs(dest_addr->sin_port),
3500 c->
rtp_ctx[stream_index] = ctx;
3584 while (*ps != NULL) {
3595 int mpeg4_count, i,
size;
3613 printf(
"MPEG4 without extra data: trying to find header in %s\n", infile->
filename);
3614 while (mpeg4_count > 0) {
3624 while (p < pkt.
data + pkt.
size - 4) {
3626 if (p[0] == 0x00 && p[1] == 0x00 &&
3627 p[2] == 0x01 && p[3] == 0xb6) {
3628 size = p - pkt.
data;
3650 for(stream = first_stream; stream != NULL; stream = stream_next) {
3652 stream_next = stream->
next;
3658 if (stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
3674 http_log(
"Could not find codec parameters from '%s'\n",
3697 for(stream = first_stream; stream != NULL; stream = stream->
next) {
3698 feed = stream->
feed;
3712 for(feed = first_feed; feed != NULL; feed = feed->
next_feed) {
3733 http_log(
"Index & Id do not match for stream %d (%s)\n",
3741 #define CHECK_CODEC(x) (ccf->x != ccs->x)
3744 http_log(
"Codecs do not match for stream %d\n", i);
3747 http_log(
"Codec bitrates do not match for stream %d\n", i);
3754 http_log(
"Codec width, height and framerate do not match for stream %d\n", i);
3761 http_log(
"Codec sample_rate, channels, frame_size do not match for stream %d\n", i);
3773 http_log(
"Deleting feed file '%s' as stream counts differ (%d != %d)\n",
3778 http_log(
"Deleting feed file '%s' as it appears to be corrupt\n",
3783 http_log(
"Unable to delete feed file '%s' as it is marked readonly\n",
3794 http_log(
"Unable to create feed file '%s' as it is marked readonly\n",
3801 http_log(
"Could not open output feed file '%s'\n",
3805 s->oformat = feed->
fmt;
3809 http_log(
"Container doesn't support the required parameters\n");
3819 http_log(
"Could not open output feed file '%s'\n",
3825 feed->
feed_size = lseek(fd, 0, SEEK_END);
3841 for(stream = first_stream; stream != NULL; stream = stream->
next) {
3854 stream->
bandwidth = (bandwidth + 999) / 1000;
3909 av->
rc_eq =
"tex^qComp";
3960 static void load_module(
const char *filename)
3964 dll = dlopen(filename, RTLD_NOW);
3966 fprintf(stderr,
"Could not load module '%s' - %s\n",
3967 filename, dlerror());
3971 init_func = dlsym(dll,
"ffserver_module_init");
3974 "%s: init function 'ffserver_module_init()' not found\n",
3999 char filename[1000], tmp[1000], tmp2[1000],
line[1000];
4004 codec ? codec->
name : NULL))) {
4005 fprintf(stderr,
"File for preset '%s' not found\n", arg);
4010 int e= fscanf(f,
"%999[^\n]\n", line) - 1;
4011 if(line[0] ==
'#' && !e)
4013 e|= sscanf(line,
"%999[^=]=%999[^\n]\n", tmp, tmp2) - 2;
4015 fprintf(stderr,
"%s: Invalid syntax: '%s'\n", filename, line);
4019 if(!strcmp(tmp,
"acodec")){
4021 }
else if(!strcmp(tmp,
"vcodec")){
4023 }
else if(!strcmp(tmp,
"scodec")){
4026 fprintf(stderr,
"%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", filename, line, tmp, tmp2);
4038 const char *mime_type)
4044 char stream_format_name[64];
4046 snprintf(stream_format_name,
sizeof(stream_format_name),
"%s_stream", fmt->
name);
4060 fprintf(stderr,
"%s:%d: ", filename, line_num);
4061 vfprintf(stderr, fmt, vl);
4074 int val, errors, line_num;
4075 FFStream **last_stream, *stream, *redirect;
4080 f = fopen(filename,
"r");
4088 first_stream = NULL;
4098 #define ERROR(...) report_config_error(filename, line_num, &errors, __VA_ARGS__)
4100 if (fgets(line,
sizeof(line), f) == NULL)
4106 if (*p ==
'\0' || *p ==
'#')
4109 get_arg(cmd,
sizeof(cmd), &p);
4112 get_arg(arg,
sizeof(arg), &p);
4114 if (val < 1 || val > 65536) {
4115 ERROR(
"Invalid_port: %s\n", arg);
4119 get_arg(arg,
sizeof(arg), &p);
4121 ERROR(
"%s:%d: Invalid host/IP address: %s\n", arg);
4126 get_arg(arg,
sizeof(arg), &p);
4128 if (val < 1 || val > 65536) {
4129 ERROR(
"%s:%d: Invalid port: %s\n", arg);
4133 get_arg(arg,
sizeof(arg), &p);
4135 ERROR(
"Invalid host/IP address: %s\n", arg);
4138 get_arg(arg,
sizeof(arg), &p);
4140 if (val < 1 || val > 65536) {
4141 ERROR(
"Invalid MaxHTTPConnections: %s\n", arg);
4145 get_arg(arg,
sizeof(arg), &p);
4148 ERROR(
"Invalid MaxClients: %s\n", arg);
4154 get_arg(arg,
sizeof(arg), &p);
4155 llval = strtoll(arg, NULL, 10);
4156 if (llval < 10 || llval > 10000000) {
4157 ERROR(
"Invalid MaxBandwidth: %s\n", arg);
4167 if (stream || feed) {
4168 ERROR(
"Already in a tag\n");
4176 for (s = first_feed;
s; s = s->
next) {
4191 *last_stream = feed;
4192 last_stream = &feed->
next;
4203 for (i = 0; i < 62; i++) {
4204 get_arg(arg,
sizeof(arg), &p);
4212 (
my_http_addr.sin_addr.s_addr == INADDR_ANY) ?
"127.0.0.1" :
4220 }
else if (stream) {
4230 get_arg(arg,
sizeof(arg), &p);
4238 get_arg(arg,
sizeof(arg), &p);
4246 fsize *= 1024 * 1024;
4249 fsize *= 1024 * 1024 * 1024;
4259 ERROR(
"No corresponding <Feed> for </Feed>\n");
4266 if (stream || feed) {
4267 ERROR(
"Already in a tag\n");
4272 q = strrchr(stream->
filename,
'>');
4276 for (s = first_stream;
s; s = s->
next) {
4293 *last_stream = stream;
4294 last_stream = &stream->
next;
4297 get_arg(arg,
sizeof(arg), &p);
4302 while (sfeed != NULL) {
4308 ERROR(
"feed '%s' not defined\n", arg);
4310 stream->
feed = sfeed;
4313 get_arg(arg,
sizeof(arg), &p);
4315 if (!strcmp(arg,
"status")) {
4321 if (!strcmp(arg,
"jpeg"))
4322 strcpy(arg,
"mjpeg");
4325 ERROR(
"Unknown Format: %s\n", arg);
4334 get_arg(arg,
sizeof(arg), &p);
4337 if (!stream->
ifmt) {
4338 ERROR(
"Unknown input format: %s\n", arg);
4345 ERROR(
"FaviconURL only permitted for status streams\n");
4360 get_arg(arg,
sizeof(arg), &p);
4367 get_arg(arg,
sizeof(arg), &p);
4370 ERROR(
"Unknown AudioCodec: %s\n", arg);
4373 get_arg(arg,
sizeof(arg), &p);
4376 ERROR(
"Unknown VideoCodec: %s\n", arg);
4379 get_arg(arg,
sizeof(arg), &p);
4381 stream->
max_time = atof(arg) * 1000;
4383 get_arg(arg,
sizeof(arg), &p);
4387 get_arg(arg,
sizeof(arg), &p);
4391 get_arg(arg,
sizeof(arg), &p);
4395 get_arg(arg,
sizeof(arg), &p);
4401 int minrate, maxrate;
4403 get_arg(arg,
sizeof(arg), &p);
4405 if (sscanf(arg,
"%d-%d", &minrate, &maxrate) == 2) {
4409 ERROR(
"Incorrect format for VideoBitRateRange -- should be <min>-<max>: %s\n", arg);
4414 get_arg(arg,
sizeof(arg), &p);
4415 video_enc.
debug = strtol(arg,0,0);
4419 get_arg(arg,
sizeof(arg), &p);
4424 get_arg(arg,
sizeof(arg), &p);
4429 get_arg(arg,
sizeof(arg), &p);
4433 get_arg(arg,
sizeof(arg), &p);
4435 video_enc.
bit_rate = atoi(arg) * 1000;
4438 get_arg(arg,
sizeof(arg), &p);
4441 if ((video_enc.
width % 16) != 0 ||
4442 (video_enc.
height % 16) != 0) {
4443 ERROR(
"Image size must be a multiple of 16\n");
4447 get_arg(arg,
sizeof(arg), &p);
4451 ERROR(
"Incorrect frame rate: %s\n", arg);
4458 get_arg(arg,
sizeof(arg), &p);
4477 get_arg(arg,
sizeof(arg), &p);
4478 get_arg(arg2,
sizeof(arg2), &p);
4487 ERROR(
"AVOption error: %s %s\n", arg, arg2);
4493 get_arg(arg,
sizeof(arg), &p);
4504 ERROR(
"AVPreset error: %s\n", arg);
4507 get_arg(arg,
sizeof(arg), &p);
4508 if ((strlen(arg) == 4) && stream)
4520 get_arg(arg,
sizeof(arg), &p);
4526 get_arg(arg,
sizeof(arg), &p);
4530 ERROR(
"VideoQDiff out of range\n");
4534 get_arg(arg,
sizeof(arg), &p);
4536 video_enc.
qmax = atoi(arg);
4537 if (video_enc.
qmax < 1 || video_enc.
qmax > 31) {
4538 ERROR(
"VideoQMax out of range\n");
4542 get_arg(arg,
sizeof(arg), &p);
4544 video_enc.
qmin = atoi(arg);
4545 if (video_enc.
qmin < 1 || video_enc.
qmin > 31) {
4546 ERROR(
"VideoQMin out of range\n");
4550 get_arg(arg,
sizeof(arg), &p);
4554 get_arg(arg,
sizeof(arg), &p);
4568 get_arg(arg,
sizeof(arg), &p);
4574 get_arg(arg,
sizeof(arg), &p);
4577 ERROR(
"Invalid host/IP address: %s\n", arg);
4583 get_arg(arg,
sizeof(arg), &p);
4587 get_arg(arg,
sizeof(arg), &p);
4595 ERROR(
"No corresponding <Stream> for </Stream>\n");
4597 if (stream->
feed && stream->
fmt && strcmp(stream->
fmt->
name,
"ffm") != 0) {
4614 if (stream || feed || redirect) {
4615 ERROR(
"Already in a tag\n");
4618 *last_stream = redirect;
4619 last_stream = &redirect->
next;
4622 q = strrchr(redirect->
filename,
'>');
4632 ERROR(
"No corresponding <Redirect> for </Redirect>\n");
4635 ERROR(
"No URL found for <Redirect>\n");
4640 get_arg(arg,
sizeof(arg), &p);
4644 ERROR(
"Module support not compiled into this version: '%s'\n", arg);
4647 ERROR(
"Incorrect keyword: '%s'\n", cmd);
4664 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
4667 for (feed = first_feed; feed; feed = feed->
next) {
4668 if (feed->
pid == pid) {
4672 fprintf(stderr,
"%s: Pid %d exited with status %d after %d seconds\n", feed->
filename, pid, status, uptime);
4692 printf(
"usage: ffserver [options]\n"
4693 "Hyper fast multi format Audio/Video streaming server\n");
4701 {
"d", 0, {(
void*)
opt_debug},
"enable debug mode" },
4708 struct sigaction sigact = { { 0 } };
4723 unsetenv(
"http_proxy");
4728 sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
4729 sigaction(SIGCHLD, &sigact, 0);
4732 fprintf(stderr,
"Incorrect config file - exiting.\n");
4753 signal(SIGPIPE, SIG_IGN);
4756 http_log(
"Could not start server\n");