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));
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')
1253 static void get_word(
char *buf,
int buf_size,
const char **pp)
1262 if ((q - buf) < buf_size - 1)
1271 static void get_arg(
char *buf,
int buf_size,
const char **pp)
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);
1422 struct in_addr *src = &c->
from_addr.sin_addr;
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) {
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;
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;
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)
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",
3998 char filename[1000], tmp[1000], tmp2[1000],
line[1000];
4004 fprintf(stderr,
"File for preset '%s' not found\n", arg);
4009 int e= fscanf(f,
"%999[^\n]\n", line) - 1;
4010 if(line[0] ==
'#' && !e)
4012 e|= sscanf(line,
"%999[^=]=%999[^\n]\n", tmp, tmp2) - 2;
4014 fprintf(stderr,
"%s: Invalid syntax: '%s'\n", filename, line);
4018 if(!strcmp(tmp,
"acodec")){
4020 }
else if(!strcmp(tmp,
"vcodec")){
4022 }
else if(!strcmp(tmp,
"scodec")){
4025 fprintf(stderr,
"%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", filename, line, tmp, tmp2);
4037 const char *mime_type)
4043 char stream_format_name[64];
4045 snprintf(stream_format_name,
sizeof(stream_format_name),
"%s_stream", fmt->
name);
4059 fprintf(stderr,
"%s:%d: ", filename, line_num);
4060 vfprintf(stderr, fmt, vl);
4073 int val, errors, line_num;
4074 FFStream **last_stream, *stream, *redirect;
4079 f = fopen(filename,
"r");
4087 first_stream =
NULL;
4097 #define ERROR(...) report_config_error(filename, line_num, &errors, __VA_ARGS__)
4099 if (fgets(line,
sizeof(line), f) ==
NULL)
4105 if (*p ==
'\0' || *p ==
'#')
4108 get_arg(cmd,
sizeof(cmd), &p);
4111 get_arg(arg,
sizeof(arg), &p);
4113 if (val < 1 || val > 65536) {
4114 ERROR(
"Invalid_port: %s\n", arg);
4118 get_arg(arg,
sizeof(arg), &p);
4120 ERROR(
"%s:%d: Invalid host/IP address: %s\n", arg);
4125 get_arg(arg,
sizeof(arg), &p);
4127 if (val < 1 || val > 65536) {
4128 ERROR(
"%s:%d: Invalid port: %s\n", arg);
4132 get_arg(arg,
sizeof(arg), &p);
4134 ERROR(
"Invalid host/IP address: %s\n", arg);
4137 get_arg(arg,
sizeof(arg), &p);
4139 if (val < 1 || val > 65536) {
4140 ERROR(
"Invalid MaxHTTPConnections: %s\n", arg);
4144 get_arg(arg,
sizeof(arg), &p);
4147 ERROR(
"Invalid MaxClients: %s\n", arg);
4153 get_arg(arg,
sizeof(arg), &p);
4155 if (llval < 10 || llval > 10000000) {
4156 ERROR(
"Invalid MaxBandwidth: %s\n", arg);
4166 if (stream || feed) {
4167 ERROR(
"Already in a tag\n");
4175 for (s = first_feed; s; s = s->
next) {
4190 *last_stream = feed;
4191 last_stream = &feed->
next;
4202 for (i = 0; i < 62; i++) {
4203 get_arg(arg,
sizeof(arg), &p);
4211 (
my_http_addr.sin_addr.s_addr == INADDR_ANY) ?
"127.0.0.1" :
4219 }
else if (stream) {
4229 get_arg(arg,
sizeof(arg), &p);
4237 get_arg(arg,
sizeof(arg), &p);
4245 fsize *= 1024 * 1024;
4248 fsize *= 1024 * 1024 * 1024;
4258 ERROR(
"No corresponding <Feed> for </Feed>\n");
4265 if (stream || feed) {
4266 ERROR(
"Already in a tag\n");
4271 q = strrchr(stream->
filename,
'>');
4275 for (s = first_stream; s; s = s->
next) {
4292 *last_stream = stream;
4293 last_stream = &stream->
next;
4296 get_arg(arg,
sizeof(arg), &p);
4301 while (sfeed !=
NULL) {
4307 ERROR(
"feed '%s' not defined\n", arg);
4309 stream->
feed = sfeed;
4312 get_arg(arg,
sizeof(arg), &p);
4314 if (!strcmp(arg,
"status")) {
4320 if (!strcmp(arg,
"jpeg"))
4321 strcpy(arg,
"mjpeg");
4324 ERROR(
"Unknown Format: %s\n", arg);
4333 get_arg(arg,
sizeof(arg), &p);
4336 if (!stream->
ifmt) {
4337 ERROR(
"Unknown input format: %s\n", arg);
4344 ERROR(
"FaviconURL only permitted for status streams\n");
4359 get_arg(arg,
sizeof(arg), &p);
4366 get_arg(arg,
sizeof(arg), &p);
4369 ERROR(
"Unknown AudioCodec: %s\n", arg);
4372 get_arg(arg,
sizeof(arg), &p);
4375 ERROR(
"Unknown VideoCodec: %s\n", arg);
4378 get_arg(arg,
sizeof(arg), &p);
4380 stream->
max_time = atof(arg) * 1000;
4382 get_arg(arg,
sizeof(arg), &p);
4386 get_arg(arg,
sizeof(arg), &p);
4390 get_arg(arg,
sizeof(arg), &p);
4394 get_arg(arg,
sizeof(arg), &p);
4400 int minrate, maxrate;
4402 get_arg(arg,
sizeof(arg), &p);
4404 if (sscanf(arg,
"%d-%d", &minrate, &maxrate) == 2) {
4408 ERROR(
"Incorrect format for VideoBitRateRange -- should be <min>-<max>: %s\n", arg);
4413 get_arg(arg,
sizeof(arg), &p);
4414 video_enc.
debug = strtol(arg,0,0);
4418 get_arg(arg,
sizeof(arg), &p);
4423 get_arg(arg,
sizeof(arg), &p);
4428 get_arg(arg,
sizeof(arg), &p);
4432 get_arg(arg,
sizeof(arg), &p);
4434 video_enc.
bit_rate = atoi(arg) * 1000;
4437 get_arg(arg,
sizeof(arg), &p);
4440 if ((video_enc.
width % 16) != 0 ||
4441 (video_enc.
height % 16) != 0) {
4442 ERROR(
"Image size must be a multiple of 16\n");
4446 get_arg(arg,
sizeof(arg), &p);
4450 ERROR(
"Incorrect frame rate: %s\n", arg);
4457 get_arg(arg,
sizeof(arg), &p);
4476 get_arg(arg,
sizeof(arg), &p);
4477 get_arg(arg2,
sizeof(arg2), &p);
4486 ERROR(
"AVOption error: %s %s\n", arg, arg2);
4492 get_arg(arg,
sizeof(arg), &p);
4503 ERROR(
"AVPreset error: %s\n", arg);
4506 get_arg(arg,
sizeof(arg), &p);
4507 if ((strlen(arg) == 4) && stream)
4519 get_arg(arg,
sizeof(arg), &p);
4525 get_arg(arg,
sizeof(arg), &p);
4529 ERROR(
"VideoQDiff out of range\n");
4533 get_arg(arg,
sizeof(arg), &p);
4535 video_enc.
qmax = atoi(arg);
4536 if (video_enc.
qmax < 1 || video_enc.
qmax > 31) {
4537 ERROR(
"VideoQMax out of range\n");
4541 get_arg(arg,
sizeof(arg), &p);
4543 video_enc.
qmin = atoi(arg);
4544 if (video_enc.
qmin < 1 || video_enc.
qmin > 31) {
4545 ERROR(
"VideoQMin out of range\n");
4549 get_arg(arg,
sizeof(arg), &p);
4551 video_enc.luma_elim_threshold = atoi(arg);
4553 get_arg(arg,
sizeof(arg), &p);
4555 video_enc.chroma_elim_threshold = atoi(arg);
4557 get_arg(arg,
sizeof(arg), &p);
4561 get_arg(arg,
sizeof(arg), &p);
4575 get_arg(arg,
sizeof(arg), &p);
4581 get_arg(arg,
sizeof(arg), &p);
4584 ERROR(
"Invalid host/IP address: %s\n", arg);
4590 get_arg(arg,
sizeof(arg), &p);
4594 get_arg(arg,
sizeof(arg), &p);
4602 ERROR(
"No corresponding <Stream> for </Stream>\n");
4604 if (stream->
feed && stream->
fmt && strcmp(stream->
fmt->
name,
"ffm") != 0) {
4621 if (stream || feed || redirect) {
4622 ERROR(
"Already in a tag\n");
4625 *last_stream = redirect;
4626 last_stream = &redirect->
next;
4629 q = strrchr(redirect->
filename,
'>');
4639 ERROR(
"No corresponding <Redirect> for </Redirect>\n");
4642 ERROR(
"No URL found for <Redirect>\n");
4647 get_arg(arg,
sizeof(arg), &p);
4651 ERROR(
"Module support not compiled into this version: '%s'\n", arg);
4654 ERROR(
"Incorrect keyword: '%s'\n", cmd);
4671 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
4674 for (feed = first_feed; feed; feed = feed->
next) {
4675 if (feed->
pid == pid) {
4679 fprintf(stderr,
"%s: Pid %d exited with status %d after %d seconds\n", feed->
filename, pid, status, uptime);
4699 printf(
"usage: ffserver [options]\n"
4700 "Hyper fast multi format Audio/Video streaming server\n");
4708 {
"d", 0, {(
void*)
opt_debug},
"enable debug mode" },
4715 struct sigaction sigact = { { 0 } };
4727 unsetenv(
"http_proxy");
4732 sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
4733 sigaction(SIGCHLD, &sigact, 0);
4736 fprintf(stderr,
"Incorrect config file - exiting.\n");
4756 signal(SIGPIPE, SIG_IGN);
4759 http_log(
"Could not start server\n");