28 #define closesocket close
62 #include <sys/ioctl.h>
74 #define PATH_LENGTH 1024
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)
204 .nb_max_connections = 5,
205 .max_bandwidth = 1000,
235 struct in_addr my_ip);
240 const char *session_id,
243 int stream_index,
struct sockaddr_in *dest_addr,
269 if (!buffer || !entity)
272 *buffer++ = *entity++;
283 const char *amp =
"&";
284 const char *lt =
"<";
285 const char *gt =
">";
288 size_t final_size = 0;
296 while (*src !=
'\0') {
318 while (*src !=
'\0') {
347 if (lseek(fd, 8, SEEK_SET) < 0)
349 if (read(fd, buf, 8) != 8)
360 buf[i] = (pos >> (56 - i * 8)) & 0xff;
361 if (lseek(fd, 8, SEEK_SET) < 0)
363 if (write(fd, buf, 8) != 8)
380 static char *
ctime1(
char *buf2,
size_t buf_size)
392 p = buf2 + strlen(buf2) - 1;
400 static int print_prefix = 1;
410 print_prefix = strstr(fmt,
"\n") !=
NULL;
416 __attribute__ ((
format (printf, 1, 2)))
421 va_start(vargs, fmt);
428 static int print_prefix = 1;
432 if (print_prefix && avc)
434 print_prefix = strstr(fmt,
"\n") !=
NULL;
443 http_log(
"%s - - [%s] \"%s %s\" %d %"PRId64
"\n",
488 http_log(
"Could not start children. Command line: '%s' exceeds "
495 http_log(
"Could not allocate memory for children cmd line\n");
501 slash = strrchr(pathname,
'/');
506 strcpy(slash,
"ffmpeg");
508 for (; feed; feed = feed->
next) {
517 http_log(
"Unable to create children: %s\n", strerror(errno));
534 for (i = 3; i < 256; i++)
538 if (!freopen(
"/dev/null",
"r", stdin))
539 http_log(
"failed to redirect STDIN to /dev/null\n;");
540 if (!freopen(
"/dev/null",
"w", stdout))
541 http_log(
"failed to redirect STDOUT to /dev/null\n;");
542 if (!freopen(
"/dev/null",
"w", stderr))
543 http_log(
"failed to redirect STDERR to /dev/null\n;");
546 signal(SIGPIPE, SIG_DFL);
559 server_fd = socket(AF_INET,SOCK_STREAM,0);
566 if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp,
sizeof(tmp)))
569 my_addr->sin_family = AF_INET;
570 if (bind (server_fd, (
struct sockaddr *) my_addr,
sizeof (*my_addr)) < 0) {
572 snprintf(bindmsg,
sizeof(bindmsg),
"bind(port %d)",
573 ntohs(my_addr->sin_port));
578 if (listen (server_fd, 5) < 0) {
599 struct sockaddr_in dest_addr = {0};
600 int default_port, stream_index;
601 unsigned int random0, random1;
613 snprintf(session_id,
sizeof(session_id),
"%08x%08x", random0, random1);
621 dest_addr.sin_family = AF_INET;
631 http_log(
"Could not open input stream for stream '%s'\n",
637 for(stream_index = 0; stream_index < stream->
nb_streams;
644 http_log(
"Could not open output stream '%s/streamid=%d'\n",
656 int server_fd = 0, rtsp_server_fd = 0;
658 struct pollfd *poll_table, *poll_entry;
662 sizeof(*poll_table));
664 http_log(
"Impossible to allocate a poll table handling %d "
677 if (rtsp_server_fd < 0) {
683 if (!rtsp_server_fd && !server_fd) {
684 http_log(
"HTTP and RTSP disabled.\n");
695 poll_entry = poll_table;
697 poll_entry->fd = server_fd;
698 poll_entry->events = POLLIN;
701 if (rtsp_server_fd) {
702 poll_entry->fd = rtsp_server_fd;
703 poll_entry->events = POLLIN;
719 poll_entry->events = POLLOUT;
730 poll_entry->events = POLLOUT;
747 poll_entry->events = POLLIN;
760 ret = poll(poll_table, poll_entry - poll_table, delay);
775 for(c = first_http_ctx;
c; c = c_next) {
784 poll_entry = poll_table;
787 if (poll_entry->revents & POLLIN)
791 if (rtsp_server_fd) {
793 if (poll_entry->revents & POLLIN)
818 "HTTP/1.0 503 Server too busy\r\n"
819 "Content-type: text/html\r\n"
822 "<html><head><title>Too busy</title></head><body>\r\n"
823 "<p>The server is too busy to serve your request at "
825 "<p>The number of current connections is %u, and this "
826 "exceeds the limit of %u.</p>\r\n"
827 "</body></html>\r\n",
830 if (send(fd, buffer, len, 0) < len)
832 "Could not send too-busy reply, send() failed\n");
838 struct sockaddr_in from_addr;
843 len =
sizeof(from_addr);
844 fd = accept(server_fd, (
struct sockaddr *)&from_addr,
847 http_log(
"error during accept %s\n", strerror(errno));
905 for(c1 = first_http_ctx;
c1; c1 = c1->
next) {
982 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1002 if ((ptr >= c->
buffer + 2 && !memcmp(ptr-2,
"\n\n", 2)) ||
1003 (ptr >= c->
buffer + 4 && !memcmp(ptr-4,
"\r\n\r\n", 4))) {
1015 }
else goto read_loop;
1020 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1057 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1076 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1085 if (c->
poll_entry->revents & (POLLIN | POLLERR | POLLHUP))
1092 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1114 if (c->
poll_entry->revents & (POLLERR | POLLHUP)) {
1156 for (p = request; *p && *p !=
'\r' && *p !=
'\n'; ) {
1158 const char *q = p + 7;
1169 memset(rates, 0xff, ratelen);
1172 while (*q && *q !=
'\n' && *q !=
':')
1175 if (sscanf(q,
":%d:%d", &stream_no, &rate_no) != 2)
1179 if (stream_no < ratelen && stream_no >= 0)
1180 rates[stream_no] = rate_no;
1189 p = strchr(p,
'\n');
1203 int best_bitrate = 100000000;
1221 if (feed_codec->
bit_rate <= bit_rate) {
1222 if (best_bitrate > bit_rate ||
1223 feed_codec->
bit_rate > best_bitrate) {
1224 best_bitrate = feed_codec->
bit_rate;
1229 if (feed_codec->
bit_rate < best_bitrate) {
1230 best_bitrate = feed_codec->
bit_rate;
1241 int action_required = 0;
1270 action_required = 1;
1274 return action_required;
1286 if ((q - buf) < buf_size - 1)
1318 while (fgets(line,
sizeof(line), f)) {
1323 if (*p ==
'\0' || *p ==
'#')
1353 unsigned long src_addr = src->s_addr;
1355 for (acl = in_acl; acl; acl = acl->
next) {
1356 if (src_addr >= acl->
first.s_addr && src_addr <= acl->last.s_addr)
1358 last_action = acl->
action;
1362 return (last_action ==
IP_DENY) ? 1 : 0;
1394 p = strrchr(file1,
'.');
1399 p = strrchr(file2,
'.');
1402 if (!strcmp(file1, file2)) {
1425 char info[1024], filename[1024];
1429 char *encoded_msg =
NULL;
1430 const char *mime_type;
1434 const char *useragent = 0;
1440 if (!strcmp(cmd,
"GET"))
1442 else if (!strcmp(cmd,
"POST"))
1450 get_word(protocol,
sizeof(protocol), (
const char **)&p);
1451 if (strcmp(protocol,
"HTTP/1.0") && strcmp(protocol,
"HTTP/1.1"))
1457 http_log(
"%s - - New connection: %s %s\n",
1458 inet_ntoa(c->
from_addr.sin_addr), cmd, url);
1461 p1 = strchr(url,
'?');
1468 av_strlcpy(filename, url + ((*url ==
'/') ? 1 : 0),
sizeof(filename)-1);
1470 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1473 if (*useragent && *useragent !=
'\n' &&
av_isspace(*useragent))
1477 p = strchr(p,
'\n');
1487 filename[strlen(filename)-1] =
'f';
1494 strcpy(filename + strlen(filename)-2,
"m");
1504 if (!strlen(filename))
1505 av_strlcpy(filename,
"index.html",
sizeof(filename) - 1);
1511 stream = stream->
next;
1514 snprintf(msg,
sizeof(msg),
"File '%s' not found", url);
1515 http_log(
"File '%s' not found\n", url);
1527 "HTTP/1.0 301 Moved\r\n"
1529 "Content-type: text/html\r\n"
1532 "<html><head><title>Moved</title></head><body>\r\n"
1533 "You should be <a href=\"%s\">redirected</a>.\r\n"
1534 "</body></html>\r\n",
1559 snprintf(msg,
sizeof(msg),
"This feed is already being received.");
1568 "HTTP/1.0 503 Server too busy\r\n"
1569 "Content-type: text/html\r\n"
1572 "<html><head><title>Too busy</title></head><body>\r\n"
1573 "<p>The server is too busy to serve your request at "
1574 "this time.</p>\r\n"
1575 "<p>The bandwidth being served (including your stream) "
1576 "is %"PRIu64
"kbit/s, and this exceeds the limit of "
1577 "%"PRIu64
"kbit/s.</p>\r\n"
1578 "</body></html>\r\n",
1589 const char *hostinfo = 0;
1591 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1596 p = strchr(p,
'\n');
1610 eoh = strchr(hostinfo,
'\n');
1612 if (eoh[-1] ==
'\r')
1615 if (eoh - hostinfo <
sizeof(hostbuf) - 1) {
1616 memcpy(hostbuf, hostinfo, eoh - hostinfo);
1617 hostbuf[eoh - hostinfo] = 0;
1621 switch(redir_type) {
1624 "HTTP/1.0 200 ASX Follows\r\n"
1625 "Content-type: video/x-ms-asf\r\n"
1627 "<ASX Version=\"3\">\r\n"
1629 "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n"
1630 "</ASX>\r\n", hostbuf, filename, info);
1635 "HTTP/1.0 200 RAM Follows\r\n"
1636 "Content-type: audio/x-pn-realaudio\r\n"
1638 "# Autogenerated by ffserver\r\n"
1639 "http://%s/%s%s\r\n", hostbuf, filename, info);
1644 "HTTP/1.0 200 ASF Redirect follows\r\n"
1645 "Content-type: video/x-ms-asf\r\n"
1648 "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info);
1653 char hostname[256], *p;
1655 av_strlcpy(hostname, hostbuf,
sizeof(hostname));
1656 p = strrchr(hostname,
':');
1660 "HTTP/1.0 200 RTSP Redirect follows\r\n"
1662 "Content-type: application/x-rtsp\r\n"
1664 "rtsp://%s:%d/%s\r\n", hostname, ntohs(config.
rtsp_addr.sin_port), filename);
1673 struct sockaddr_in my_addr;
1676 "HTTP/1.0 200 OK\r\n"
1677 "Content-type: application/sdp\r\n"
1681 len =
sizeof(my_addr);
1684 if (getsockname(c->
fd, (
struct sockaddr *)&my_addr, &len))
1685 http_log(
"getsockname() failed\n");
1691 if (sdp_data_size > 0) {
1692 memcpy(q, sdp_data, sdp_data_size);
1713 snprintf(msg,
sizeof(msg),
"ASX/RAM file not handled");
1726 const char *logline = 0;
1729 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1735 client_id = strtol(p + 18, 0, 10);
1736 p = strchr(p,
'\n');
1744 char *eol = strchr(logline,
'\n');
1749 if (eol[-1] ==
'\r')
1751 http_log(
"%.*s\n", (
int) (eol - logline), logline);
1764 for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->
next) {
1773 snprintf(msg,
sizeof(msg),
"POST command not handled");
1778 snprintf(msg,
sizeof(msg),
"could not open feed");
1796 snprintf(msg,
sizeof(msg),
"Input stream corresponding to '%s' not found", url);
1805 mime_type =
"application/x-octet-stream";
1830 http_log(
"Could not encode filename '%s' as HTML\n", msg);
1833 "HTTP/1.0 404 Not Found\r\n"
1834 "Content-type: text/html\r\n"
1839 "<meta charset=\"UTF-8\">\n"
1840 "<title>404 Not Found</title>\n"
1843 "</html>\n", encoded_msg? encoded_msg :
"File not found");
1862 static const char suffix[] =
" kMGTP";
1865 for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++);
1873 const char *
type =
"unknown";
1874 char parameters[64];
1880 avio_printf(pb,
"<table cellspacing=0 cellpadding=4><tr><th>Stream<th>"
1881 "type<th>kbit/s<th align=left>codec<th align=left>"
1884 for (i = 0; i < stream_no; i++) {
1893 snprintf(parameters,
sizeof(parameters),
"%d channel(s), %d Hz",
1898 snprintf(parameters,
sizeof(parameters),
1907 avio_printf(pb,
"<tr><td align=right>%d<td>%s<td align=right>%"PRId64
1910 codec ? codec->
name :
"", parameters);
1940 avio_printf(pb,
"<link rel=\"shortcut icon\" href=\"%s\">\n",
1946 avio_printf(pb,
"<table cellspacing=0 cellpadding=4>\n");
1947 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>kbit/s<th align=left>Video<br>kbit/s<th><br>Codec<th align=left>Audio<br>kbit/s<th><br>Codec<th align=left valign=top>Feed\n");
1950 char sfilename[1024];
1953 if (stream->
feed == stream) {
1954 stream = stream->
next;
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> ",
1987 int audio_bit_rate = 0;
1988 int video_bit_rate = 0;
1991 const char *audio_codec_name_extra =
"";
1992 const char *video_codec_name_extra =
"";
2002 if (*audio_codec_name)
2003 audio_codec_name_extra =
"...";
2004 audio_codec_name = codec->
name;
2010 if (*video_codec_name)
2011 video_codec_name_extra =
"...";
2012 video_codec_name = codec->
name;
2023 avio_printf(pb,
"<td align=center> %s <td align=right> %d "
2024 "<td align=right> %d <td> %s %s <td align=right> "
2027 video_bit_rate / 1000, video_codec_name,
2028 video_codec_name_extra, audio_bit_rate / 1000,
2029 audio_codec_name, audio_codec_name_extra);
2039 avio_printf(pb,
"<td align=center> - <td align=right> - "
2040 "<td align=right> - <td><td align=right> - <td>\n");
2043 stream = stream->
next;
2050 if (stream->
feed != stream) {
2051 stream = stream->
next;
2057 avio_printf(pb,
"Running as pid %"PRId64
".\n", (int64_t) stream->
pid);
2066 "ps -o \"%%cpu,cputime\" --no-headers %"PRId64
"",
2067 (int64_t) stream->
pid);
2069 pid_stat = popen(ps_cmd,
"r");
2074 if (fscanf(pid_stat,
"%9s %63s", cpuperc, cpuused) == 2) {
2075 avio_printf(pb,
"Currently using %s%% of the cpu. "
2076 "Total time used %s.\n",
2088 stream = stream->
next;
2094 avio_printf(pb,
"Number of connections: %d / %d<br>\n",
2097 avio_printf(pb,
"Bandwidth in use: %"PRIu64
"k / %"PRIu64
"k<br>\n",
2101 avio_printf(pb,
"<tr><th>#<th>File<th>IP<th>Proto<th>State<th>Target "
2102 "bit/s<th>Actual bit/s<th>Bytes transferred\n");
2121 avio_printf(pb,
"<tr><td><b>%d</b><td>%s%s<td>%s<td>%s<td>%s"
2139 avio_printf(pb,
"<hr size=1 noshade>Generated at %s", p);
2152 int buf_size, i, ret;
2162 http_log(
"Invalid date specification '%s' for stream\n", buf);
2166 int prebuffer = strtol(buf, 0, 10);
2167 stream_pos =
av_gettime() - prebuffer * (int64_t)1000000;
2176 http_log(
"Invalid date specification '%s' for stream\n", buf);
2182 if (!input_filename[0]) {
2183 http_log(
"No filename was specified for stream\n");
2191 http_log(
"Could not open input '%s': %s\n",
2200 http_log(
"Failed to set buffer size\n");
2209 http_log(
"Could not find stream info for input '%s'\n", input_filename);
2242 int bytes_left, bytes_sent, frame_bytes;
2245 if (frame_bytes <= 0)
2249 bytes_sent = frame_bytes - bytes_left;
2311 http_log(
"Error writing output header for stream '%s': %s\n",
2425 int max_packet_size;
2451 http_log(
"Error writing frame to output for stream '%s': %s\n",
2541 int interleaved_index,
size;
2557 interleaved_index++;
2560 header[1] = interleaved_index;
2561 header[2] = len >> 8;
2627 http_log(
"Stream feed '%s' was not opened\n",
2634 http_log(
"Cannot write to read-only file '%s'\n",
2643 http_log(
"Could not open feed file '%s': %s\n",
2655 http_log(
"Error truncating feed file '%s': %s\n",
2662 http_log(
"Error reading write index from feed file '%s': %s\n",
2672 lseek(fd, 0, SEEK_SET);
2685 int len, loop_run = 0;
2698 }
else if (len == 0) {
2708 }
else if (++loop_run > 10)
2723 }
else if (len == 0)
2735 if (c->
buffer[0] !=
'f' ||
2737 http_log(
"Feed stream has become desynchronized -- disconnecting\n");
2753 http_log(
"Error writing to feed file: %s\n", strerror(errno));
2769 http_log(
"Error writing index to feed file: %s\n",
2775 for(c1 = first_http_ctx;
c1; c1 = c1->
next) {
2812 http_log(
"Feed '%s' stream number does not match registered feed\n",
2834 for(c1 = first_http_ctx;
c1; c1 = c1->
next) {
2854 str =
"Unknown Error";
2856 avio_printf(c->
pb,
"RTSP/1.0 %d %s\r\n", error_number, str);
2862 strftime(buf2,
sizeof(buf2),
"%a, %d %b %Y %H:%M:%S", tm);
2874 const char *p, *p1, *p2;
2887 get_word(protocol,
sizeof(protocol), &p);
2900 if (strcmp(protocol,
"RTSP/1.0")) {
2907 while (*p !=
'\n' && *p !=
'\0')
2911 while (*p !=
'\0') {
2912 p1 = memchr(p,
'\n', (
char *)c->
buffer_ptr - p);
2916 if (p2 > p && p2[-1] ==
'\r')
2922 if (len >
sizeof(line) - 1)
2923 len =
sizeof(line) - 1;
2924 memcpy(line, p, len);
2933 if (!strcmp(cmd,
"DESCRIBE"))
2935 else if (!strcmp(cmd,
"OPTIONS"))
2937 else if (!strcmp(cmd,
"SETUP"))
2939 else if (!strcmp(cmd,
"PLAY"))
2941 else if (!strcmp(cmd,
"PAUSE"))
2943 else if (!strcmp(cmd,
"TEARDOWN"))
2962 struct in_addr my_ip)
2973 if (!avc || !rtp_format)
2978 entry ? entry->
value :
"No Title", 0);
3010 return *pbuffer ? strlen(*pbuffer) :
AVERROR(ENOMEM);
3019 "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
3031 struct sockaddr_in my_addr;
3041 stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp") &&
3054 len =
sizeof(my_addr);
3055 getsockname(c->
fd, (
struct sockaddr *)&my_addr, &len);
3058 if (content_length < 0) {
3065 avio_printf(c->
pb,
"Content-Length: %d\r\n", content_length);
3075 if (session_id[0] ==
'\0')
3078 for(c = first_http_ctx;
c; c = c->
next) {
3102 int stream_index, rtp_port, rtcp_port;
3108 struct sockaddr_in dest_addr;
3120 strcmp(stream->
fmt->
name,
"rtp")) {
3124 if (!strcmp(path, stream->
filename)) {
3133 for(stream_index = 0; stream_index < stream->
nb_streams;
3135 snprintf(buf,
sizeof(buf),
"%s/streamid=%d",
3137 if (!strcmp(path, buf))
3148 unsigned random0 =
av_lfg_get(&random_state);
3149 unsigned random1 =
av_lfg_get(&random_state);
3183 if (rtp_c->
stream != stream) {
3189 if (rtp_c->
rtp_ctx[stream_index]) {
3203 setup.transport_option[0] =
'\0';
3223 "client_port=%d-%d;server_port=%d-%d",
3225 rtp_port, rtcp_port);
3228 avio_printf(c->
pb,
"Transport: RTP/AVP/TCP;interleaved=%d-%d",
3229 stream_index * 2, stream_index * 2 + 1);
3234 if (setup.transport_option[0] !=
'\0')
3248 const char *session_id)
3267 snprintf(buf,
sizeof(buf),
"%s/streamid=%d",
3269 if(!strncmp(path, buf,
sizeof(buf)))
3275 if (len > 0 && path[len - 1] ==
'/' &&
3343 const char *session_id,
3347 const char *proto_str;
3376 proto_str =
"MCAST";
3411 int stream_index,
struct sockaddr_in *dest_addr,
3419 int max_packet_size;
3447 ipaddr = inet_ntoa(dest_addr->sin_addr);
3461 "rtp://%s:%d?multicast=1&ttl=%d",
3462 ipaddr, ntohs(dest_addr->sin_port), ttl);
3465 "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
3482 http_log(
"%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
3483 ipaddr, ntohs(dest_addr->sin_port),
3603 int mpeg4_count, i,
size;
3621 printf(
"MPEG4 without extra data: trying to find header in %s\n",
3623 while (mpeg4_count > 0) {
3633 while (p < pkt.
data + pkt.
size - 4) {
3635 if (p[0] == 0x00 && p[1] == 0x00 &&
3636 p[2] == 0x01 && p[3] == 0xb6) {
3637 size = p - pkt.
data;
3672 if (stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp"))
3676 http_log(
"Unspecified feed file for stream '%s'\n",
3681 http_log(
"Opening feed file '%s' for stream '%s'\n",
3696 http_log(
"Could not find codec parameters from '%s'\n",
3716 #define CHECK_CODEC(x) (ccf->x != ccs->x)
3718 http_log(
"Codecs do not match for stream %d\n", stream);
3721 http_log(
"Codec bitrates do not match for stream %d\n", stream);
3728 http_log(
"Codec width, height or framerate do not match for stream %d\n", stream);
3735 http_log(
"Codec sample_rate, channels, frame_size do not match for stream %d\n", stream);
3739 http_log(
"Unknown codec type for stream %d\n", stream);
3754 feed = stream->
feed;
3778 http_log(
"Deleting feed file '%s' as it appears "
3786 http_log(
"Failed to set buffer size\n");
3793 http_log(
"Deleting feed file '%s' as stream counts "
3794 "differ (%d != %d)\n",
3807 http_log(
"Index & Id do not match for stream %d (%s)\n",
3824 http_log(
"Unable to delete read-only feed file '%s'\n",
3836 http_log(
"Failed to allocate context\n");
3841 http_log(
"Unable to create feed file '%s' as it is "
3842 "marked readonly\n",
3850 http_log(
"Could not open output feed file '%s'\n",
3859 http_log(
"Container doesn't support the required parameters\n");
3875 http_log(
"Could not open output feed file '%s'\n",
3882 feed->
feed_size = lseek(fd, 0, SEEK_END);
3915 stream->
bandwidth = (bandwidth + 999) / 1000;
3925 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
3929 if (feed->
pid != pid)
3935 "%s: Pid %"PRId64
" exited with status %d after %"PRId64
" "
3937 feed->
filename, (int64_t) pid, status, (int64_t)uptime);
3956 printf(
"usage: ffserver [options]\n"
3957 "Hyper fast multi format Audio/Video streaming server\n");
3965 {
"d", 0, {(
void*)
opt_debug},
"enable debug mode" },
3966 {
"f",
HAS_ARG |
OPT_STRING, {(
void*)&config.
filename },
"use configfile instead of /etc/ffserver.conf",
"configfile" },
3972 struct sigaction sigact = { { 0 } };
3974 int ret = EXIT_FAILURE;
3989 unsetenv(
"http_proxy");
3994 sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
3995 sigaction(SIGCHLD, &sigact, 0);
3998 fprintf(stderr,
"Error reading configuration file '%s': %s\n",
4015 http_log(
"Could not setup feed streams\n");
4022 signal(SIGPIPE, SIG_IGN);
4025 http_log(
"Could not start server\n");
int avio_open(AVIOContext **s, const char *url, int flags)
Create and initialize a AVIOContext for accessing the resource indicated by url.
static int rtp_new_av_stream(HTTPContext *c, int stream_index, struct sockaddr_in *dest_addr, HTTPContext *rtsp_c)
add a new RTP stream in an RTP connection (used in RTSP SETUP command).
void av_url_split(char *proto, int proto_size, char *authorization, int authorization_size, char *hostname, int hostname_size, int *port_ptr, char *path, int path_size, const char *url)
Split a URL string into components.
static int validate_acl(FFServerStream *stream, HTTPContext *c)
static const char *const http_state[]
static HTTPContext * find_rtp_session(const char *session_id)
const struct AVCodec * codec
int ffserver_parse_ffconfig(const char *filename, FFServerConfig *config)
static const char * my_program_name
static void http_log(const char *fmt,...)
struct sockaddr_in http_addr
int ff_rtp_get_local_rtp_port(URLContext *h)
Return the local rtp port used by the RTP connection.
static void rtsp_reply_error(HTTPContext *c, enum RTSPStatusCode error_number)
RTSPLowerTransport
Network layer over which RTP/etc packet data will be transported.
AVCodec * avcodec_find_encoder(enum AVCodecID id)
Find a registered encoder with a matching codec ID.
static void http_av_log(void *ptr, int level, const char *fmt, va_list vargs)
int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
Return the written size and a pointer to the buffer.
FFServerIPAddressACL * acl
static void print_stream_params(AVIOContext *pb, FFServerStream *stream)
int av_write_frame(AVFormatContext *s, AVPacket *pkt)
Write a packet to an output media file.
static int prepare_sdp_description(FFServerStream *stream, uint8_t **pbuffer, struct in_addr my_ip)
static void build_file_streams(void)
unsigned int nb_max_connections
#define AV_LOG_WARNING
Something somehow does not look correct.
int64_t bit_rate
the average bitrate
int av_parse_time(int64_t *timeval, const char *timestr, int duration)
Parse timestr and return in *time a corresponding number of microseconds.
int ffurl_write(URLContext *h, const unsigned char *buf, int size)
Write size bytes from buf to the resource accessed by h.
char * av_stristr(const char *s1, const char *s2)
Locate the first case-independent occurrence in the string haystack of the string needle...
struct HTTPContext * next
static FFServerConfig config
static void rtsp_reply_header(HTTPContext *c, enum RTSPStatusCode error_number)
static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h)
uint8_t * packet_buffer_end
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown)
static int validate_acl_list(FFServerIPAddressACL *in_acl, HTTPContext *c)
int index
stream index in AVFormatContext
#define AVIO_FLAG_READ
read-only
static int rtsp_parse_request(HTTPContext *c)
static av_const int av_isspace(int c)
Locale-independent conversion of ASCII isspace.
#define AVIO_FLAG_WRITE
write-only
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown) That is the width of a pixel divided by the height of the pixel...
enum AVMediaType codec_type
void show_banner(int argc, char **argv, const OptionDef *options)
Print the program banner to stderr.
int av_strncasecmp(const char *a, const char *b, size_t n)
Locale-independent case-insensitive compare.
int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
Copy entries from one AVDictionary struct into another.
struct pollfd * poll_entry
void show_help_default(const char *opt, const char *arg)
Per-fftool specific help handler.
static const char * audio_codec_name
int avio_open_dyn_buf(AVIOContext **s)
Open a write only memory stream.
int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src)
Copy the settings of the source AVCodecContext into the destination AVCodecContext.
enum RTSPLowerTransport lower_transport
network layer transport protocol; e.g.
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
struct FFServerStream * next
const int program_birth_year
program birth year, defined by the program for show_banner()
#define IOBUFFER_INIT_SIZE
int avio_check(const char *url, int flags)
Return AVIO_FLAG_* access flags corresponding to the access permissions of the resource in url...
static AVStream * add_av_stream1(FFServerStream *stream, AVCodecContext *codec, int copy)
void ffserver_free_child_args(void *argsp)
#define av_assert0(cond)
assert() equivalent, that is always enabled.
static void free_acl_list(FFServerIPAddressACL *in_acl)
static void http_vlog(const char *fmt, va_list vargs)
Opaque data information usually continuous.
static void opt_debug(void)
uint8_t * packet_buffer_ptr
miscellaneous OS support macros and functions.
static void compute_real_filename(char *filename, int max_size)
compute the real filename of a file by matching it without its extensions to all the stream's filenam...
static unsigned int nb_connections
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
const char program_name[]
program name, defined by the program for show_version().
AVFormatContext * rtp_ctx[FFSERVER_MAX_STREAMS]
static int http_parse_request(HTTPContext *c)
int id
Format-specific stream ID.
static int http_send_data(HTTPContext *c)
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
static void get_word(char *buf, int buf_size, const char **pp)
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
AVStream ** streams
A list of all streams in the file.
AVFormatContext * avformat_alloc_context(void)
Allocate an AVFormatContext.
int feed_streams[FFSERVER_MAX_STREAMS]
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
int flags
Flags modifying the (de)muxer behaviour.
static void rtsp_cmd_interrupt(HTTPContext *c, const char *url, RTSPMessageHeader *h, int pause_only)
void parse_options(void *optctx, int argc, char **argv, const OptionDef *options, void(*parse_arg_function)(void *, const char *))
struct FFServerStream * stream
static int find_stream_in_feed(FFServerStream *feed, AVCodecContext *codec, int bit_rate)
int avformat_network_init(void)
Do global initialization of network components.
static HTTPContext * find_rtp_session_with_url(const char *url, const char *session_id)
find an RTP connection by using the session ID.
int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size)
Generate an SDP for an RTP session.
int av_find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
Attempt to find a specific tag in a URL.
int av_match_ext(const char *filename, const char *extensions)
Return a positive value if the given filename has one of the given extensions, 0 otherwise.
static int http_receive_data(HTTPContext *c)
static void copy(LZOContext *c, int cnt)
Copies bytes from input to output buffer with checking.
void parse_loglevel(int argc, char **argv, const OptionDef *options)
Find the '-loglevel' option in the command line args and apply it.
static const uint8_t header[24]
void show_help_options(const OptionDef *options, const char *msg, int req_flags, int rej_flags, int alt_flags)
Print help for all options matching specified flags.
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
AVStream * streams[FFSERVER_MAX_STREAMS]
void ff_rtsp_parse_line(AVFormatContext *s, RTSPMessageHeader *reply, const char *buf, RTSPState *rt, const char *method)
struct AVOutputFormat * oformat
The output container format.
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
static void http_send_too_busy_reply(int fd)
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
int avcodec_close(AVCodecContext *avctx)
Close a given AVCodecContext and free all the data associated with it (but not the AVCodecContext its...
AVIOContext * avio_alloc_context(unsigned char *buffer, int buffer_size, int write_flag, void *opaque, int(*read_packet)(void *opaque, uint8_t *buf, int buf_size), int(*write_packet)(void *opaque, uint8_t *buf, int buf_size), int64_t(*seek)(void *opaque, int64_t offset, int whence))
Allocate and initialize an AVIOContext for buffered I/O.
static int extract_rates(char *rates, int ratelen, const char *request)
AVDictionary * metadata
Metadata that applies to the whole file.
int main(int argc, char **argv)
static int handle_connection(HTTPContext *c)
static int64_t get_server_clock(HTTPContext *c)
int ffio_set_buf_size(AVIOContext *s, int buf_size)
static void rtsp_cmd_options(HTTPContext *c, const char *url)
static uint64_t current_bandwidth
int qmax
maximum quantizer
#define FFSERVER_MAX_STREAMS
static int add_av_stream(FFServerStream *feed, AVStream *st)
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values. ...
int av_opt_set_int(void *obj, const char *name, int64_t val, int search_flags)
enum FFServerStreamType stream_type
simple assert() macros that are a bit more flexible than ISO C assert().
int av_log_get_level(void)
Get the current log level.
static int socket_open_listen(struct sockaddr_in *my_addr)
const char * name
Name of the codec implementation.
static void start_children(FFServerStream *feed)
static int ffm_write_write_index(int fd, int64_t pos)
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
int feed_streams[FFSERVER_MAX_STREAMS]
static size_t htmlencode(const char *src, char **dest)
Substitutes known conflicting chars on a text string with their corresponding HTML entities...
int flags
A combination of AV_PKT_FLAG values.
AVCodecContext * codec
Codec context associated with this stream.
static HTTPContext * first_http_ctx
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
static int open_input_stream(HTTPContext *c, const char *info)
static void log_connection(HTTPContext *c)
AVInputFormat * av_find_input_format(const char *short_name)
Find AVInputFormat based on the short name of the input format.
#define RTSP_REQUEST_TIMEOUT
int seekable
A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable.
static int modify_current_stream(HTTPContext *c, char *rates)
char filename[1024]
input or output filename
static void rtsp_cmd_describe(HTTPContext *c, const char *url)
#define AV_TIME_BASE
Internal time base represented as integer.
av_warn_unused_result int avformat_write_header(AVFormatContext *s, AVDictionary **options)
Allocate the stream private data and write the stream header to an output media file.
struct FFServerStream * next_feed
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
void av_log_set_callback(void(*callback)(void *, int, const char *, va_list))
Set the logging callback.
AVCodecContext * avcodec_alloc_context3(const AVCodec *codec)
Allocate an AVCodecContext and set its fields to default values.
#define AV_OPT_SEARCH_CHILDREN
Search in possible children of the given object first.
int width
picture width / height.
int ffio_open_dyn_packet_buf(AVIOContext **s, int max_packet_size)
Open a write only packetized memory stream with a maximum packet size of 'max_packet_size'.
#define RTSP_TCP_MAX_PACKET_SIZE
void ffserver_get_arg(char *buf, int buf_size, const char **pp)
struct FFServerIPAddressACL * next
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
This describes a single item in the "Transport:" line of one stream as negotiated by the SETUP RTSP c...
static int need_to_start_children
struct HTTPContext * rtsp_c
static AVLFG random_state
AVOutputFormat * av_guess_format(const char *short_name, const char *filename, const char *mime_type)
Return the output format in the list of registered output formats which best matches the provided par...
const char *(* item_name)(void *ctx)
A pointer to a function which returns the name of a context instance ctx associated with the class...
int ff_socket_nonblock(int socket, int enable)
static const char * input_filename
#define FF_ARRAY_ELEMS(a)
int64_t av_gettime(void)
Get the current time in microseconds.
enum RTSPLowerTransport rtp_protocol
static int64_t ffm_read_write_index(int fd)
struct sockaddr_in from_addr
int avformat_network_deinit(void)
Undo the initialization done by avformat_network_init.
static HTTPContext * rtp_new_connection(struct sockaddr_in *from_addr, FFServerStream *stream, const char *session_id, enum RTSPLowerTransport rtp_protocol)
static void compute_status(HTTPContext *c)
AVStreamInternal * internal
An opaque field for libavformat internal usage.
enum AVMediaType codec_type
static void start_multicast(void)
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
char * av_strdup(const char *s)
Duplicate the string s.
int sample_rate
samples per second
AVIOContext * pb
I/O context.
main external API structure.
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
static const char * format
int qmin
minimum quantizer
static int compute_datarate(DataRateData *drd, int64_t count)
struct sockaddr_in rtsp_addr
static unsigned int av_lfg_get(AVLFG *c)
Get the next random unsigned 32-bit number using an ALFG.
static RTSPTransportField * find_transport(RTSPMessageHeader *h, enum RTSPLowerTransport lower_transport)
static void close_connection(HTTPContext *c)
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
BYTE int const BYTE int int int height
static int http_server(void)
Describe the class of an AVClass context structure.
static void cp_html_entity(char *buffer, const char *entity)
static void update_datarate(DataRateData *drd, int64_t count)
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
av_cold void av_lfg_init(AVLFG *c, unsigned int seed)
static const OptionDef options[]
static void start_wait_request(HTTPContext *c, int is_rtsp)
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
Return the next frame of a stream.
size_t av_strlcat(char *dst, const char *src, size_t size)
Append the string src to the string dst, but to a total length of no more than size - 1 bytes...
FFServerStream * first_feed
int switch_feed_streams[FFSERVER_MAX_STREAMS]
static void extract_mpeg4_header(AVFormatContext *infile)
RTSPStatusCode
RTSP handling.
int ffurl_close(URLContext *h)
URLContext * rtp_handles[FFSERVER_MAX_STREAMS]
static int64_t get_packet_send_clock(HTTPContext *c)
int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
Seek to the keyframe at timestamp.
struct FFServerStream * feed
int gop_size
the number of pictures in a group of pictures, or 0 for intra_only
char transport_option[512]
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_RB64
struct AVStream::@158 * info
int ffurl_open(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options)
static FFServerIPAddressACL * parse_dynamic_acl(FFServerStream *stream, HTTPContext *c)
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
Read packets of a media file to get stream information.
void ffserver_parse_acl_row(FFServerStream *stream, FFServerStream *feed, FFServerIPAddressACL *ext_acl, const char *p, const char *filename, int line_num)
struct AVInputFormat * iformat
The input container format.
void avformat_close_input(AVFormatContext **s)
Close an opened input AVFormatContext.
int ff_rtp_get_local_rtcp_port(URLContext *h)
Return the local rtcp port used by the RTP connection.
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding...
static void compute_bandwidth(void)
static void ffm_set_write_index(AVFormatContext *s, int64_t pos, int64_t file_size)
TCP; interleaved in RTSP.
int channels
number of audio channels
static int check_codec_match(AVCodecContext *ccf, AVCodecContext *ccs, int stream)
#define RTSP_STATUS_CODE2STRING(x)
void * priv_data
Format private data.
int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options)
Open an input stream and read the header.
static void new_connection(int server_fd, int is_rtsp)
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed...
static void * av_mallocz_array(size_t nmemb, size_t size)
int av_write_trailer(AVFormatContext *s)
Write the stream trailer to an output media file and free the file private data.
int frame_number
Frame counter, set by libavcodec.
int max_packet_size
if non zero, the stream is packetized with this max packet size
static void rtsp_cmd_setup(HTTPContext *c, const char *url, RTSPMessageHeader *h)
static const char * video_codec_name
static char * ctime1(char *buf2, size_t buf_size)
unbuffered private I/O API
uint32_t av_get_random_seed(void)
Get a seed to use in conjunction with random functions.
struct in_addr multicast_ip
#define av_malloc_array(a, b)
FFServerStream * first_stream
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
static void handle_child_exit(int sig)
This structure stores compressed data.
void av_register_all(void)
Initialize libavformat and register all the muxers, demuxers and protocols.
int avio_closep(AVIOContext **s)
Close the resource accessed by the AVIOContext *s, free it and set the pointer pointing to it to NULL...
unsigned int nb_max_http_connections
static int build_feed_streams(void)
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
static void fmt_bytecount(AVIOContext *pb, int64_t count)
enum FFServerIPAddressAction action
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
#define AV_NOPTS_VALUE
Undefined timestamp value.
#define HTTP_REQUEST_TIMEOUT
static int http_prepare_data(HTTPContext *c)
int avio_printf(AVIOContext *s, const char *fmt,...) av_printf_format(2
int client_port_min
UDP client ports; these should be the local ports of the UDP RTP (and RTCP) sockets over which we rec...
int64_t cur_frame_duration
static void remove_stream(FFServerStream *stream)
static int http_start_receive_data(HTTPContext *c)