28 #define closesocket close
60 #include <sys/ioctl.h>
107 #define MAX_STREAMS 20
109 #define IOBUFFER_INIT_SIZE 8192
112 #define HTTP_REQUEST_TIMEOUT (15 * 1000)
113 #define RTSP_REQUEST_TIMEOUT (3600 * 24 * 1000)
115 #define SYNC_TIMEOUT (10 * 1000)
298 struct in_addr my_ip);
302 FFStream *stream,
const char *session_id,
305 int stream_index,
struct sockaddr_in *dest_addr,
332 s += strspn(s,
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,. ");
342 if (lseek(fd, 8, SEEK_SET) < 0)
344 if (read(fd, buf, 8) != 8)
355 buf[i] = (pos >> (56 - i * 8)) & 0xff;
356 if (lseek(fd, 8, SEEK_SET) < 0)
358 if (write(fd, buf, 8) != 8)
373 static int resolve_host(
struct in_addr *sin_addr,
const char *hostname)
386 for (cur = ai; cur; cur = cur->
ai_next) {
388 *sin_addr = ((
struct sockaddr_in *)cur->
ai_addr)->sin_addr;
397 hp = gethostbyname(hostname);
400 memcpy(sin_addr, hp->h_addr_list[0],
sizeof(
struct in_addr));
406 static char *
ctime1(
char *buf2,
int buf_size)
414 p = buf2 + strlen(p) - 1;
422 static int print_prefix = 1;
429 print_prefix = strstr(fmt,
"\n") != NULL;
436 __attribute__ ((format (printf, 1, 2)))
441 va_start(vargs, fmt);
448 static int print_prefix = 1;
452 if (print_prefix && avc)
454 print_prefix = strstr(fmt,
"\n") != NULL;
463 http_log(
"%s - - [%s] \"%s %s\" %d %"PRId64
"\n",
496 for (; feed; feed = feed->
next) {
503 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 setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp,
sizeof(tmp));
563 my_addr->sin_family = AF_INET;
564 if (bind (server_fd, (
struct sockaddr *) my_addr,
sizeof (*my_addr)) < 0) {
566 snprintf(bindmsg,
sizeof(bindmsg),
"bind(port %d)", ntohs(my_addr->sin_port));
572 if (listen (server_fd, 5) < 0) {
588 struct sockaddr_in dest_addr = {0};
589 int default_port, stream_index;
592 for(stream = first_stream; stream != NULL; stream = stream->
next) {
597 snprintf(session_id,
sizeof(session_id),
"%08x%08x",
606 dest_addr.sin_family = AF_INET;
616 http_log(
"Could not open input stream for stream '%s'\n",
622 for(stream_index = 0; stream_index < stream->
nb_streams;
627 http_log(
"Could not open output stream '%s/streamid=%d'\n",
642 int server_fd = 0, rtsp_server_fd = 0;
643 int ret, delay, delay1;
644 struct pollfd *poll_table, *poll_entry;
660 if (rtsp_server_fd < 0)
664 if (!rtsp_server_fd && !server_fd) {
665 http_log(
"HTTP and RTSP disabled.\n");
676 poll_entry = poll_table;
678 poll_entry->fd = server_fd;
679 poll_entry->events = POLLIN;
682 if (rtsp_server_fd) {
683 poll_entry->fd = rtsp_server_fd;
684 poll_entry->events = POLLIN;
700 poll_entry->events = POLLOUT;
710 poll_entry->events = POLLOUT;
728 poll_entry->events = POLLIN;
741 ret = poll(poll_table, poll_entry - poll_table, delay);
755 for(c = first_http_ctx; c != NULL; c = c_next) {
764 poll_entry = poll_table;
767 if (poll_entry->revents & POLLIN)
771 if (rtsp_server_fd) {
773 if (poll_entry->revents & POLLIN)
798 "HTTP/1.0 503 Server too busy\r\n"
799 "Content-type: text/html\r\n"
801 "<html><head><title>Too busy</title></head><body>\r\n"
802 "<p>The server is too busy to serve your request at this time.</p>\r\n"
803 "<p>The number of current connections is %u, and this exceeds the limit of %u.</p>\r\n"
804 "</body></html>\r\n",
807 send(fd, buffer, len, 0);
813 struct sockaddr_in from_addr;
818 len =
sizeof(from_addr);
819 fd = accept(server_fd, (
struct sockaddr *)&from_addr,
822 http_log(
"error during accept %s\n", strerror(errno));
871 while ((*cp) != NULL) {
880 for(c1 = first_http_ctx; c1 != NULL; c1 = c1->
next) {
903 for(i=0;i<nb_streams;i++) {
960 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
973 }
else if (len == 0) {
980 if ((ptr >= c->
buffer + 2 && !memcmp(ptr-2,
"\n\n", 2)) ||
981 (ptr >= c->
buffer + 4 && !memcmp(ptr-4,
"\r\n\r\n", 4))) {
993 }
else goto read_loop;
998 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1036 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1051 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1060 if (c->
poll_entry->revents & (POLLIN | POLLERR | POLLHUP))
1067 if (c->
poll_entry->revents & (POLLERR | POLLHUP)) {
1093 if (c->
poll_entry->revents & (POLLERR | POLLHUP)) {
1131 for (p = request; *p && *p !=
'\r' && *p !=
'\n'; ) {
1133 const char *q = p + 7;
1144 memset(rates, 0xff, ratelen);
1147 while (*q && *q !=
'\n' && *q !=
':')
1150 if (sscanf(q,
":%d:%d", &stream_no, &rate_no) != 2)
1154 if (stream_no < ratelen && stream_no >= 0)
1155 rates[stream_no] = rate_no;
1164 p = strchr(p,
'\n');
1177 int best_bitrate = 100000000;
1195 if (feed_codec->
bit_rate <= bit_rate) {
1196 if (best_bitrate > bit_rate || feed_codec->
bit_rate > best_bitrate) {
1197 best_bitrate = feed_codec->
bit_rate;
1201 if (feed_codec->
bit_rate < best_bitrate) {
1202 best_bitrate = feed_codec->
bit_rate;
1215 int action_required = 0;
1243 action_required = 1;
1246 return action_required;
1255 while (*p ==
' ' || *p ==
'\t')
1269 if ((q - buf) < buf_size - 1)
1288 if (*p ==
'\"' || *p ==
'\'')
1300 if ((q - buf) < buf_size - 1)
1305 if (quote && *p == quote)
1311 const char *p,
const char *filename,
int line_num)
1317 get_arg(arg,
sizeof(arg), &p);
1323 fprintf(stderr,
"%s:%d: ACL action '%s' is not ALLOW or DENY\n",
1324 filename, line_num, arg);
1328 get_arg(arg,
sizeof(arg), &p);
1331 fprintf(stderr,
"%s:%d: ACL refers to invalid host or ip address '%s'\n",
1332 filename, line_num, arg);
1337 get_arg(arg,
sizeof(arg), &p);
1341 fprintf(stderr,
"%s:%d: ACL refers to invalid host or ip address '%s'\n",
1342 filename, line_num, arg);
1355 naclp = &stream->
acl;
1361 fprintf(stderr,
"%s:%d: ACL found not in <stream> or <feed>\n",
1362 filename, line_num);
1368 naclp = &(*naclp)->
next;
1395 if (fgets(line,
sizeof(line), f) == NULL)
1401 if (*p ==
'\0' || *p ==
'#')
1403 get_arg(cmd,
sizeof(cmd), &p);
1430 unsigned long src_addr = src->s_addr;
1432 for (acl = in_acl; acl; acl = acl->
next) {
1433 if (src_addr >= acl->
first.s_addr && src_addr <= acl->last.s_addr)
1435 last_action = acl->
action;
1439 return (last_action ==
IP_DENY) ? 1 : 0;
1473 p = strrchr(file1,
'.');
1476 for(stream = first_stream; stream != NULL; stream = stream->
next) {
1478 p = strrchr(file2,
'.');
1481 if (!strcmp(file1, file2)) {
1504 char info[1024], filename[1024];
1508 const char *mime_type;
1512 const char *useragent = 0;
1518 if (!strcmp(cmd,
"GET"))
1520 else if (!strcmp(cmd,
"POST"))
1528 get_word(protocol,
sizeof(protocol), (
const char **)&p);
1529 if (strcmp(protocol,
"HTTP/1.0") && strcmp(protocol,
"HTTP/1.1"))
1535 http_log(
"%s - - New connection: %s %s\n", inet_ntoa(c->
from_addr.sin_addr), cmd, url);
1538 p1 = strchr(url,
'?');
1545 av_strlcpy(filename, url + ((*url ==
'/') ? 1 : 0),
sizeof(filename)-1);
1547 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1550 if (*useragent && *useragent !=
'\n' &&
av_isspace(*useragent))
1554 p = strchr(p,
'\n');
1564 filename[strlen(filename)-1] =
'f';
1571 strcpy(filename + strlen(filename)-2,
"m");
1581 if (!strlen(filename))
1582 av_strlcpy(filename,
"index.html",
sizeof(filename) - 1);
1585 while (stream != NULL) {
1588 stream = stream->
next;
1590 if (stream == NULL) {
1591 snprintf(msg,
sizeof(msg),
"File '%s' not found", url);
1592 http_log(
"File '%s' not found\n", url);
1604 "HTTP/1.0 301 Moved\r\n"
1606 "Content-type: text/html\r\n"
1608 "<html><head><title>Moved</title></head><body>\r\n"
1609 "You should be <a href=\"%s\">redirected</a>.\r\n"
1634 snprintf(msg,
sizeof(msg),
"This feed is already being received.");
1643 "HTTP/1.0 503 Server too busy\r\n"
1644 "Content-type: text/html\r\n"
1646 "<html><head><title>Too busy</title></head><body>\r\n"
1647 "<p>The server is too busy to serve your request at this time.</p>\r\n"
1648 "<p>The bandwidth being served (including your stream) is %"PRIu64
"kbit/sec, "
1649 "and this exceeds the limit of %"PRIu64
"kbit/sec.</p>\r\n"
1660 const char *hostinfo = 0;
1662 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1667 p = strchr(p,
'\n');
1681 eoh = strchr(hostinfo,
'\n');
1683 if (eoh[-1] ==
'\r')
1686 if (eoh - hostinfo <
sizeof(hostbuf) - 1) {
1687 memcpy(hostbuf, hostinfo, eoh - hostinfo);
1688 hostbuf[eoh - hostinfo] = 0;
1692 switch(redir_type) {
1695 "HTTP/1.0 200 ASX Follows\r\n"
1696 "Content-type: video/x-ms-asf\r\n"
1698 "<ASX Version=\"3\">\r\n"
1700 "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n"
1701 "</ASX>\r\n", hostbuf, filename, info);
1706 "HTTP/1.0 200 RAM Follows\r\n"
1707 "Content-type: audio/x-pn-realaudio\r\n"
1709 "# Autogenerated by ffserver\r\n"
1710 "http://%s/%s%s\r\n", hostbuf, filename, info);
1715 "HTTP/1.0 200 ASF Redirect follows\r\n"
1716 "Content-type: video/x-ms-asf\r\n"
1719 "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info);
1724 char hostname[256], *p;
1726 av_strlcpy(hostname, hostbuf,
sizeof(hostname));
1727 p = strrchr(hostname,
':');
1731 "HTTP/1.0 200 RTSP Redirect follows\r\n"
1733 "Content-type: application/x-rtsp\r\n"
1735 "rtsp://%s:%d/%s\r\n", hostname, ntohs(
my_rtsp_addr.sin_port), filename);
1744 struct sockaddr_in my_addr;
1747 "HTTP/1.0 200 OK\r\n"
1748 "Content-type: application/sdp\r\n"
1752 len =
sizeof(my_addr);
1753 getsockname(c->
fd, (
struct sockaddr *)&my_addr, &len);
1759 if (sdp_data_size > 0) {
1760 memcpy(q, sdp_data, sdp_data_size);
1781 snprintf(msg,
sizeof(msg),
"ASX/RAM file not handled");
1794 const char *logline = 0;
1797 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1803 client_id = strtol(p + 18, 0, 10);
1804 p = strchr(p,
'\n');
1812 char *eol = strchr(logline,
'\n');
1817 if (eol[-1] ==
'\r')
1819 http_log(
"%.*s\n", (
int) (eol - logline), logline);
1832 for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->
next) {
1841 snprintf(msg,
sizeof(msg),
"POST command not handled");
1846 snprintf(msg,
sizeof(msg),
"could not open feed");
1864 snprintf(msg,
sizeof(msg),
"Input stream corresponding to '%s' not found", url);
1873 mime_type =
"application/x-octet-stream";
1899 "HTTP/1.0 404 Not Found\r\n"
1900 "Content-type: text/html\r\n"
1903 "<head><title>404 Not Found</title></head>\n"
1922 static const char suffix[] =
" kMGTP";
1925 for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++);
1947 avio_printf(pb,
"Content-type: %s\r\n",
"text/html");
1958 avio_printf(pb,
"<table cellspacing=0 cellpadding=4>\n");
1959 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");
1961 while (stream != NULL) {
1962 char sfilename[1024];
1965 if (stream->
feed != stream) {
1967 eosf = sfilename + strlen(sfilename);
1968 if (eosf - sfilename >= 4) {
1969 if (strcmp(eosf - 4,
".asf") == 0)
1970 strcpy(eosf - 4,
".asx");
1971 else if (strcmp(eosf - 3,
".rm") == 0)
1972 strcpy(eosf - 3,
".ram");
1973 else if (stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
1977 eosf = strrchr(sfilename,
'.');
1979 eosf = sfilename + strlen(sfilename);
1981 strcpy(eosf,
".sdp");
1983 strcpy(eosf,
".rtsp");
1987 avio_printf(pb,
"<tr><td><a href=\"/%s\">%s</a> ",
1989 avio_printf(pb,
"<td align=right> %d <td align=right> ",
1994 int audio_bit_rate = 0;
1995 int video_bit_rate = 0;
1998 const char *audio_codec_name_extra =
"";
1999 const char *video_codec_name_extra =
"";
2008 if (*audio_codec_name)
2009 audio_codec_name_extra =
"...";
2010 audio_codec_name = codec->
name;
2016 if (*video_codec_name)
2017 video_codec_name_extra =
"...";
2018 video_codec_name = codec->
name;
2028 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",
2031 video_bit_rate / 1000, video_codec_name, video_codec_name_extra,
2032 audio_bit_rate / 1000, audio_codec_name, audio_codec_name_extra);
2041 avio_printf(pb,
"<td align=center> - <td align=right> - <td align=right> - <td><td align=right> - <td>\n");
2045 stream = stream->
next;
2050 while (stream != NULL) {
2051 if (stream->
feed == stream) {
2063 "ps -o \"%%cpu,cputime\" --no-headers %d",
2066 pid_stat = popen(ps_cmd,
"r");
2071 if (fscanf(pid_stat,
"%9s %63s", cpuperc,
2073 avio_printf(pb,
"Currently using %s%% of the cpu. Total time used %s.\n",
2083 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");
2088 const char *
type =
"unknown";
2089 char parameters[64];
2106 avio_printf(pb,
"<tr><td align=right>%d<td>%s<td align=right>%d<td>%s<td>%s\n",
2112 stream = stream->
next;
2118 avio_printf(pb,
"Number of connections: %d / %d<br>\n",
2121 avio_printf(pb,
"Bandwidth in use: %"PRIu64
"k / %"PRIu64
"k<br>\n",
2125 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");
2128 while (c1 != NULL) {
2144 avio_printf(pb,
"<tr><td><b>%d</b><td>%s%s<td>%s<td>%s<td>%s<td align=right>",
2164 avio_printf(pb,
"<hr size=1 noshade>Generated at %s", p);
2177 int buf_size, i,
ret;
2189 int prebuffer = strtol(buf, 0, 10);
2190 stream_pos =
av_gettime() - prebuffer * (int64_t)1000000;
2203 if (input_filename[0] ==
'\0')
2208 http_log(
"could not open %s: %d\n", input_filename, ret);
2218 http_log(
"Could not find stream info '%s'\n", input_filename);
2252 int bytes_left, bytes_sent, frame_bytes;
2255 if (frame_bytes <= 0)
2259 bytes_sent = frame_bytes - bytes_left;
2317 http_log(
"Error writing output header\n");
2351 }
else if (ret ==
AVERROR(EAGAIN)) {
2428 int max_packet_size;
2450 http_log(
"Error writing frame to output\n");
2536 int interleaved_index,
size;
2552 interleaved_index++;
2555 header[1] = interleaved_index;
2556 header[2] = len >> 8;
2628 http_log(
"Error opening feeder file: %s\n", strerror(errno));
2638 http_log(
"Error truncating feed file: %s\n", strerror(errno));
2643 http_log(
"Error reading write index from feed file: %s\n", strerror(errno));
2650 lseek(fd, 0, SEEK_SET);
2663 int len, loop_run = 0;
2676 }
else if (len == 0) {
2686 }
else if (++loop_run > 10) {
2702 }
else if (len == 0)
2714 if (c->
buffer[0] !=
'f' ||
2716 http_log(
"Feed stream has become desynchronized -- disconnecting\n");
2729 http_log(
"Error writing to feed file: %s\n", strerror(errno));
2744 http_log(
"Error writing index to feed file: %s\n", strerror(errno));
2749 for(c1 = first_http_ctx; c1 != NULL; c1 = c1->
next) {
2770 0, NULL, NULL, NULL, NULL);
2783 http_log(
"Feed '%s' stream number does not match registered feed\n",
2805 for(c1 = first_http_ctx; c1 != NULL; c1 = c1->
next) {
2823 switch(error_number) {
2828 str =
"Method Not Allowed";
2831 str =
"Not Enough Bandwidth";
2834 str =
"Session Not Found";
2837 str =
"Method Not Valid in This State";
2840 str =
"Aggregate operation not allowed";
2843 str =
"Only aggregate operation allowed";
2846 str =
"Unsupported transport";
2849 str =
"Internal Server Error";
2852 str =
"Service Unavailable";
2855 str =
"RTSP Version not supported";
2858 str =
"Unknown Error";
2862 avio_printf(c->
pb,
"RTSP/1.0 %d %s\r\n", error_number, str);
2868 strftime(buf2,
sizeof(buf2),
"%a, %d %b %Y %H:%M:%S", tm);
2880 const char *p, *p1, *p2;
2893 get_word(protocol,
sizeof(protocol), &p);
2906 if (strcmp(protocol,
"RTSP/1.0") != 0) {
2913 while (*p !=
'\n' && *p !=
'\0')
2917 while (*p !=
'\0') {
2918 p1 = memchr(p,
'\n', (
char *)c->
buffer_ptr - p);
2922 if (p2 > p && p2[-1] ==
'\r')
2928 if (len >
sizeof(line) - 1)
2929 len =
sizeof(line) - 1;
2930 memcpy(line, p, len);
2937 c->
seq = header->seq;
2939 if (!strcmp(cmd,
"DESCRIBE"))
2941 else if (!strcmp(cmd,
"OPTIONS"))
2943 else if (!strcmp(cmd,
"SETUP"))
2945 else if (!strcmp(cmd,
"PLAY"))
2947 else if (!strcmp(cmd,
"PAUSE"))
2949 else if (!strcmp(cmd,
"TEARDOWN"))
2968 struct in_addr my_ip)
2976 if (avc == NULL || !rtp_format) {
2981 stream->
title[0] ? stream->
title :
"No Title", 0);
2994 if (avc->
nb_streams >= INT_MAX/
sizeof(*avs) ||
3011 return strlen(*pbuffer);
3019 avio_printf(c->
pb,
"Public: %s\r\n",
"OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
3031 struct sockaddr_in my_addr;
3034 av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1,
sizeof(path1), url);
3039 for(stream = first_stream; stream != NULL; stream = stream->
next) {
3041 stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp") &&
3054 len =
sizeof(my_addr);
3055 getsockname(c->
fd, (
struct sockaddr *)&my_addr, &len);
3057 if (content_length < 0) {
3064 avio_printf(c->
pb,
"Content-Length: %d\r\n", content_length);
3074 if (session_id[0] ==
'\0')
3077 for(c = first_http_ctx; c != NULL; c = c->
next) {
3101 int stream_index, rtp_port, rtcp_port;
3107 struct sockaddr_in dest_addr;
3111 av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1,
sizeof(path1), url);
3117 for(stream = first_stream; stream != NULL; stream = stream->
next) {
3119 stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
3121 if (!strcmp(path, stream->
filename)) {
3130 for(stream_index = 0; stream_index < stream->
nb_streams;
3132 snprintf(buf,
sizeof(buf),
"%s/streamid=%d",
3134 if (!strcmp(path, buf))
3146 unsigned random0 =
av_lfg_get(&random_state);
3147 unsigned random1 =
av_lfg_get(&random_state);
3181 if (rtp_c->
stream != stream) {
3187 if (rtp_c->
rtp_ctx[stream_index]) {
3201 setup.transport_option[0] =
'\0';
3221 "client_port=%d-%d;server_port=%d-%d",
3223 rtp_port, rtcp_port);
3226 avio_printf(c->
pb,
"Transport: RTP/AVP/TCP;interleaved=%d-%d",
3227 stream_index * 2, stream_index * 2 + 1);
3232 if (setup.transport_option[0] !=
'\0')
3244 const char *session_id)
3257 av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1,
sizeof(path1), url);
3263 snprintf(buf,
sizeof(buf),
"%s/streamid=%d",
3265 if(!strncmp(path, buf,
sizeof(buf))) {
3271 if (len > 0 && path[len - 1] ==
'/' &&
3353 FFStream *stream,
const char *session_id,
3357 const char *proto_str;
3386 proto_str =
"MCAST";
3419 int stream_index,
struct sockaddr_in *dest_addr,
3427 int max_packet_size;
3454 ipaddr = inet_ntoa(dest_addr->sin_addr);
3468 "rtp://%s:%d?multicast=1&ttl=%d",
3469 ipaddr, ntohs(dest_addr->sin_port), ttl);
3472 "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
3489 http_log(
"%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
3490 ipaddr, ntohs(dest_addr->sin_port),
3508 c->
rtp_ctx[stream_index] = ctx;
3592 while (*ps != NULL) {
3603 int mpeg4_count, i,
size;
3621 printf(
"MPEG4 without extra data: trying to find header in %s\n", infile->
filename);
3622 while (mpeg4_count > 0) {
3632 while (p < pkt.
data + pkt.
size - 4) {
3634 if (p[0] == 0x00 && p[1] == 0x00 &&
3635 p[2] == 0x01 && p[3] == 0xb6) {
3636 size = p - pkt.
data;
3658 for(stream = first_stream; stream != NULL; stream = stream_next) {
3660 stream_next = stream->
next;
3666 if (stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
3682 http_log(
"Could not find codec parameters from '%s'\n",
3705 for(stream = first_stream; stream != NULL; stream = stream->
next) {
3706 feed = stream->
feed;
3720 for(feed = first_feed; feed != NULL; feed = feed->
next_feed) {
3741 http_log(
"Index & Id do not match for stream %d (%s)\n",
3749 #define CHECK_CODEC(x) (ccf->x != ccs->x)
3752 http_log(
"Codecs do not match for stream %d\n", i);
3755 http_log(
"Codec bitrates do not match for stream %d\n", i);
3762 http_log(
"Codec width, height and framerate do not match for stream %d\n", i);
3769 http_log(
"Codec sample_rate, channels, frame_size do not match for stream %d\n", i);
3781 http_log(
"Deleting feed file '%s' as stream counts differ (%d != %d)\n",
3786 http_log(
"Deleting feed file '%s' as it appears to be corrupt\n",
3791 http_log(
"Unable to delete feed file '%s' as it is marked readonly\n",
3802 http_log(
"Unable to create feed file '%s' as it is marked readonly\n",
3809 http_log(
"Could not open output feed file '%s'\n",
3813 s->oformat = feed->
fmt;
3817 http_log(
"Container doesn't support the required parameters\n");
3827 http_log(
"Could not open output feed file '%s'\n",
3833 feed->
feed_size = lseek(fd, 0, SEEK_END);
3849 for(stream = first_stream; stream != NULL; stream = stream->
next) {
3862 stream->
bandwidth = (bandwidth + 999) / 1000;
3980 char filename[1000], tmp[1000], tmp2[1000],
line[1000];
3985 codec ? codec->
name : NULL))) {
3986 fprintf(stderr,
"File for preset '%s' not found\n", arg);
3991 int e= fscanf(f,
"%999[^\n]\n", line) - 1;
3992 if(line[0] ==
'#' && !e)
3994 e|= sscanf(line,
"%999[^=]=%999[^\n]\n", tmp, tmp2) - 2;
3996 fprintf(stderr,
"%s: Invalid syntax: '%s'\n", filename, line);
4000 if(!strcmp(tmp,
"acodec")){
4002 }
else if(!strcmp(tmp,
"vcodec")){
4004 }
else if(!strcmp(tmp,
"scodec")){
4007 fprintf(stderr,
"%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", filename, line, tmp, tmp2);
4019 const char *mime_type)
4025 char stream_format_name[64];
4027 snprintf(stream_format_name,
sizeof(stream_format_name),
"%s_stream", fmt->
name);
4041 fprintf(stderr,
"%s:%d: ", filename, line_num);
4042 vfprintf(stderr, fmt, vl);
4055 int val, errors, line_num;
4056 FFStream **last_stream, *stream, *redirect;
4061 f = fopen(filename,
"r");
4069 first_stream = NULL;
4079 #define ERROR(...) report_config_error(filename, line_num, &errors, __VA_ARGS__)
4081 if (fgets(line,
sizeof(line), f) == NULL)
4087 if (*p ==
'\0' || *p ==
'#')
4090 get_arg(cmd,
sizeof(cmd), &p);
4093 get_arg(arg,
sizeof(arg), &p);
4095 if (val < 1 || val > 65536) {
4096 ERROR(
"Invalid_port: %s\n", arg);
4100 get_arg(arg,
sizeof(arg), &p);
4102 ERROR(
"%s:%d: Invalid host/IP address: %s\n", arg);
4107 get_arg(arg,
sizeof(arg), &p);
4109 if (val < 1 || val > 65536) {
4110 ERROR(
"%s:%d: Invalid port: %s\n", arg);
4114 get_arg(arg,
sizeof(arg), &p);
4116 ERROR(
"Invalid host/IP address: %s\n", arg);
4119 get_arg(arg,
sizeof(arg), &p);
4121 if (val < 1 || val > 65536) {
4122 ERROR(
"Invalid MaxHTTPConnections: %s\n", arg);
4126 get_arg(arg,
sizeof(arg), &p);
4129 ERROR(
"Invalid MaxClients: %s\n", arg);
4135 get_arg(arg,
sizeof(arg), &p);
4136 llval = strtoll(arg, NULL, 10);
4137 if (llval < 10 || llval > 10000000) {
4138 ERROR(
"Invalid MaxBandwidth: %s\n", arg);
4148 if (stream || feed) {
4149 ERROR(
"Already in a tag\n");
4157 for (s = first_feed;
s; s = s->
next) {
4172 *last_stream = feed;
4173 last_stream = &feed->
next;
4184 for (i = 0; i < 62; i++) {
4185 get_arg(arg,
sizeof(arg), &p);
4193 (
my_http_addr.sin_addr.s_addr == INADDR_ANY) ?
"127.0.0.1" :
4201 }
else if (stream) {
4211 get_arg(arg,
sizeof(arg), &p);
4219 get_arg(arg,
sizeof(arg), &p);
4227 fsize *= 1024 * 1024;
4230 fsize *= 1024 * 1024 * 1024;
4240 ERROR(
"No corresponding <Feed> for </Feed>\n");
4247 if (stream || feed) {
4248 ERROR(
"Already in a tag\n");
4253 q = strrchr(stream->
filename,
'>');
4257 for (s = first_stream;
s; s = s->
next) {
4274 *last_stream = stream;
4275 last_stream = &stream->
next;
4278 get_arg(arg,
sizeof(arg), &p);
4283 while (sfeed != NULL) {
4289 ERROR(
"feed '%s' not defined\n", arg);
4291 stream->
feed = sfeed;
4294 get_arg(arg,
sizeof(arg), &p);
4296 if (!strcmp(arg,
"status")) {
4302 if (!strcmp(arg,
"jpeg"))
4303 strcpy(arg,
"mjpeg");
4306 ERROR(
"Unknown Format: %s\n", arg);
4315 get_arg(arg,
sizeof(arg), &p);
4318 if (!stream->
ifmt) {
4319 ERROR(
"Unknown input format: %s\n", arg);
4326 ERROR(
"FaviconURL only permitted for status streams\n");
4341 get_arg(arg,
sizeof(arg), &p);
4348 get_arg(arg,
sizeof(arg), &p);
4351 ERROR(
"Unknown AudioCodec: %s\n", arg);
4354 get_arg(arg,
sizeof(arg), &p);
4357 ERROR(
"Unknown VideoCodec: %s\n", arg);
4360 get_arg(arg,
sizeof(arg), &p);
4362 stream->
max_time = atof(arg) * 1000;
4364 get_arg(arg,
sizeof(arg), &p);
4368 get_arg(arg,
sizeof(arg), &p);
4372 get_arg(arg,
sizeof(arg), &p);
4376 get_arg(arg,
sizeof(arg), &p);
4382 int minrate, maxrate;
4384 get_arg(arg,
sizeof(arg), &p);
4386 if (sscanf(arg,
"%d-%d", &minrate, &maxrate) == 2) {
4390 ERROR(
"Incorrect format for VideoBitRateRange -- should be <min>-<max>: %s\n", arg);
4395 get_arg(arg,
sizeof(arg), &p);
4396 video_enc.
debug = strtol(arg,0,0);
4400 get_arg(arg,
sizeof(arg), &p);
4405 get_arg(arg,
sizeof(arg), &p);
4410 get_arg(arg,
sizeof(arg), &p);
4414 get_arg(arg,
sizeof(arg), &p);
4416 video_enc.
bit_rate = atoi(arg) * 1000;
4419 get_arg(arg,
sizeof(arg), &p);
4422 if ((video_enc.
width % 16) != 0 ||
4423 (video_enc.
height % 16) != 0) {
4424 ERROR(
"Image size must be a multiple of 16\n");
4428 get_arg(arg,
sizeof(arg), &p);
4432 ERROR(
"Incorrect frame rate: %s\n", arg);
4439 get_arg(arg,
sizeof(arg), &p);
4443 ERROR(
"Unknown pixel format: %s\n", arg);
4447 get_arg(arg,
sizeof(arg), &p);
4466 get_arg(arg,
sizeof(arg), &p);
4467 get_arg(arg2,
sizeof(arg2), &p);
4476 ERROR(
"AVOption error: %s %s\n", arg, arg2);
4482 get_arg(arg,
sizeof(arg), &p);
4493 ERROR(
"AVPreset error: %s\n", arg);
4496 get_arg(arg,
sizeof(arg), &p);
4497 if ((strlen(arg) == 4) && stream)
4509 get_arg(arg,
sizeof(arg), &p);
4515 get_arg(arg,
sizeof(arg), &p);
4519 ERROR(
"VideoQDiff out of range\n");
4523 get_arg(arg,
sizeof(arg), &p);
4525 video_enc.
qmax = atoi(arg);
4526 if (video_enc.
qmax < 1 || video_enc.
qmax > 31) {
4527 ERROR(
"VideoQMax out of range\n");
4531 get_arg(arg,
sizeof(arg), &p);
4533 video_enc.
qmin = atoi(arg);
4534 if (video_enc.
qmin < 1 || video_enc.
qmin > 31) {
4535 ERROR(
"VideoQMin out of range\n");
4539 get_arg(arg,
sizeof(arg), &p);
4543 get_arg(arg,
sizeof(arg), &p);
4557 get_arg(arg,
sizeof(arg), &p);
4563 get_arg(arg,
sizeof(arg), &p);
4566 ERROR(
"Invalid host/IP address: %s\n", arg);
4572 get_arg(arg,
sizeof(arg), &p);
4576 get_arg(arg,
sizeof(arg), &p);
4584 ERROR(
"No corresponding <Stream> for </Stream>\n");
4586 if (stream->
feed && stream->
fmt && strcmp(stream->
fmt->
name,
"ffm") != 0) {
4603 if (stream || feed || redirect) {
4604 ERROR(
"Already in a tag\n");
4607 *last_stream = redirect;
4608 last_stream = &redirect->
next;
4611 q = strrchr(redirect->
filename,
'>');
4621 ERROR(
"No corresponding <Redirect> for </Redirect>\n");
4624 ERROR(
"No URL found for <Redirect>\n");
4629 ERROR(
"Loadable modules no longer supported\n");
4631 ERROR(
"Incorrect keyword: '%s'\n", cmd);
4648 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
4651 for (feed = first_feed; feed; feed = feed->
next) {
4652 if (feed->
pid == pid) {
4656 fprintf(stderr,
"%s: Pid %d exited with status %d after %d seconds\n", feed->
filename, pid, status, uptime);
4676 printf(
"usage: ffserver [options]\n"
4677 "Hyper fast multi format Audio/Video streaming server\n");
4685 {
"d", 0, {(
void*)
opt_debug},
"enable debug mode" },
4692 struct sigaction sigact = { { 0 } };
4706 unsetenv(
"http_proxy");
4711 sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
4712 sigaction(SIGCHLD, &sigact, 0);
4715 fprintf(stderr,
"Incorrect config file - exiting.\n");
4736 signal(SIGPIPE, SIG_IGN);
4739 http_log(
"Could not start server\n");