28 #define closesocket close
62 #include <sys/ioctl.h>
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)
202 .nb_max_connections = 5,
203 .max_bandwidth = 1000,
233 struct in_addr my_ip);
238 const char *session_id,
241 int stream_index,
struct sockaddr_in *dest_addr,
263 s += strspn(s,
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,. ");
273 if (lseek(fd, 8, SEEK_SET) < 0)
275 if (read(fd, buf, 8) != 8)
286 buf[i] = (pos >> (56 - i * 8)) & 0xff;
287 if (lseek(fd, 8, SEEK_SET) < 0)
289 if (write(fd, buf, 8) != 8)
302 static char *
ctime1(
char *buf2,
int buf_size)
310 p = buf2 + strlen(p) - 1;
318 static int print_prefix = 1;
328 print_prefix = strstr(fmt,
"\n") !=
NULL;
334 __attribute__ ((format (printf, 1, 2)))
339 va_start(vargs, fmt);
346 static int print_prefix = 1;
350 if (print_prefix && avc)
352 print_prefix = strstr(fmt,
"\n") !=
NULL;
361 http_log(
"%s - - [%s] \"%s %s\" %d %"PRId64
"\n",
402 slash = strrchr(pathname,
'/');
407 strcpy(slash,
"ffmpeg");
409 for (; feed; feed = feed->
next) {
418 http_log(
"Unable to create children\n");
434 for (i = 3; i < 256; i++)
438 if (!freopen(
"/dev/null",
"r", stdin))
439 http_log(
"failed to redirect STDIN to /dev/null\n;");
440 if (!freopen(
"/dev/null",
"w", stdout))
441 http_log(
"failed to redirect STDOUT to /dev/null\n;");
442 if (!freopen(
"/dev/null",
"w", stderr))
443 http_log(
"failed to redirect STDERR to /dev/null\n;");
446 signal(SIGPIPE, SIG_DFL);
457 server_fd = socket(AF_INET,SOCK_STREAM,0);
464 if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp,
sizeof(tmp)))
467 my_addr->sin_family = AF_INET;
468 if (bind (server_fd, (
struct sockaddr *) my_addr,
sizeof (*my_addr)) < 0) {
470 snprintf(bindmsg,
sizeof(bindmsg),
"bind(port %d)",
471 ntohs(my_addr->sin_port));
477 if (listen (server_fd, 5) < 0) {
495 struct sockaddr_in dest_addr = {0};
496 int default_port, stream_index;
497 unsigned int random0, random1;
509 snprintf(session_id,
sizeof(session_id),
"%08x%08x", random0, random1);
517 dest_addr.sin_family = AF_INET;
527 http_log(
"Could not open input stream for stream '%s'\n",
533 for(stream_index = 0; stream_index < stream->
nb_streams;
540 http_log(
"Could not open output stream '%s/streamid=%d'\n",
552 int server_fd = 0, rtsp_server_fd = 0;
554 struct pollfd *poll_table, *poll_entry;
558 sizeof(*poll_table));
560 http_log(
"Impossible to allocate a poll table handling %d "
575 if (rtsp_server_fd < 0) {
582 if (!rtsp_server_fd && !server_fd) {
583 http_log(
"HTTP and RTSP disabled.\n");
595 poll_entry = poll_table;
597 poll_entry->fd = server_fd;
598 poll_entry->events = POLLIN;
601 if (rtsp_server_fd) {
602 poll_entry->fd = rtsp_server_fd;
603 poll_entry->events = POLLIN;
619 poll_entry->events = POLLOUT;
630 poll_entry->events = POLLOUT;
647 poll_entry->events = POLLIN;
660 ret = poll(poll_table, poll_entry - poll_table, delay);
676 for(c = first_http_ctx;
c; c = c_next) {
685 poll_entry = poll_table;
688 if (poll_entry->revents & POLLIN)
692 if (rtsp_server_fd) {
694 if (poll_entry->revents & POLLIN)
715 "HTTP/1.0 503 Server too busy\r\n"
716 "Content-type: text/html\r\n"
718 "<html><head><title>Too busy</title></head><body>\r\n"
719 "<p>The server is too busy to serve your request at this time.</p>\r\n"
720 "<p>The number of current connections is %u, and this exceeds the limit of %u.</p>\r\n"
721 "</body></html>\r\n",
724 if (send(fd, buffer, len, 0) < len)
726 "Could not send too-busy reply, send() failed\n");
732 struct sockaddr_in from_addr;
737 len =
sizeof(from_addr);
738 fd = accept(server_fd, (
struct sockaddr *)&from_addr,
741 http_log(
"error during accept %s\n", strerror(errno));
799 for(c1 = first_http_ctx;
c1; c1 = c1->
next) {
876 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
896 if ((ptr >= c->
buffer + 2 && !memcmp(ptr-2,
"\n\n", 2)) ||
897 (ptr >= c->
buffer + 4 && !memcmp(ptr-4,
"\r\n\r\n", 4))) {
909 }
else goto read_loop;
914 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
951 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
970 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
979 if (c->
poll_entry->revents & (POLLIN | POLLERR | POLLHUP))
986 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1008 if (c->
poll_entry->revents & (POLLERR | POLLHUP)) {
1050 for (p = request; *p && *p !=
'\r' && *p !=
'\n'; ) {
1052 const char *q = p + 7;
1063 memset(rates, 0xff, ratelen);
1066 while (*q && *q !=
'\n' && *q !=
':')
1069 if (sscanf(q,
":%d:%d", &stream_no, &rate_no) != 2)
1073 if (stream_no < ratelen && stream_no >= 0)
1074 rates[stream_no] = rate_no;
1083 p = strchr(p,
'\n');
1097 int best_bitrate = 100000000;
1115 if (feed_codec->
bit_rate <= bit_rate) {
1116 if (best_bitrate > bit_rate ||
1117 feed_codec->
bit_rate > best_bitrate) {
1118 best_bitrate = feed_codec->
bit_rate;
1123 if (feed_codec->
bit_rate < best_bitrate) {
1124 best_bitrate = feed_codec->
bit_rate;
1135 int action_required = 0;
1164 action_required = 1;
1168 return action_required;
1180 if ((q - buf) < buf_size - 1)
1212 while (fgets(line,
sizeof(line), f)) {
1217 if (*p ==
'\0' || *p ==
'#')
1247 unsigned long src_addr = src->s_addr;
1249 for (acl = in_acl; acl; acl = acl->
next) {
1250 if (src_addr >= acl->
first.s_addr && src_addr <= acl->last.s_addr)
1252 last_action = acl->
action;
1256 return (last_action ==
IP_DENY) ? 1 : 0;
1289 p = strrchr(file1,
'.');
1294 p = strrchr(file2,
'.');
1297 if (!strcmp(file1, file2)) {
1320 char info[1024], filename[1024];
1324 const char *mime_type;
1328 const char *useragent = 0;
1334 if (!strcmp(cmd,
"GET"))
1336 else if (!strcmp(cmd,
"POST"))
1344 get_word(protocol,
sizeof(protocol), (
const char **)&p);
1345 if (strcmp(protocol,
"HTTP/1.0") && strcmp(protocol,
"HTTP/1.1"))
1351 http_log(
"%s - - New connection: %s %s\n",
1352 inet_ntoa(c->
from_addr.sin_addr), cmd, url);
1355 p1 = strchr(url,
'?');
1362 av_strlcpy(filename, url + ((*url ==
'/') ? 1 : 0),
sizeof(filename)-1);
1364 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1367 if (*useragent && *useragent !=
'\n' &&
av_isspace(*useragent))
1371 p = strchr(p,
'\n');
1381 filename[strlen(filename)-1] =
'f';
1388 strcpy(filename + strlen(filename)-2,
"m");
1398 if (!strlen(filename))
1399 av_strlcpy(filename,
"index.html",
sizeof(filename) - 1);
1405 stream = stream->
next;
1408 snprintf(msg,
sizeof(msg),
"File '%s' not found", url);
1409 http_log(
"File '%s' not found\n", url);
1421 "HTTP/1.0 301 Moved\r\n"
1423 "Content-type: text/html\r\n"
1425 "<html><head><title>Moved</title></head><body>\r\n"
1426 "You should be <a href=\"%s\">redirected</a>.\r\n"
1427 "</body></html>\r\n",
1452 snprintf(msg,
sizeof(msg),
"This feed is already being received.");
1461 "HTTP/1.0 503 Server too busy\r\n"
1462 "Content-type: text/html\r\n"
1464 "<html><head><title>Too busy</title></head><body>\r\n"
1465 "<p>The server is too busy to serve your request at this time.</p>\r\n"
1466 "<p>The bandwidth being served (including your stream) is %"PRIu64
"kbit/sec, "
1467 "and this exceeds the limit of %"PRIu64
"kbit/sec.</p>\r\n"
1468 "</body></html>\r\n",
1479 const char *hostinfo = 0;
1481 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1486 p = strchr(p,
'\n');
1500 eoh = strchr(hostinfo,
'\n');
1502 if (eoh[-1] ==
'\r')
1505 if (eoh - hostinfo <
sizeof(hostbuf) - 1) {
1506 memcpy(hostbuf, hostinfo, eoh - hostinfo);
1507 hostbuf[eoh - hostinfo] = 0;
1511 switch(redir_type) {
1514 "HTTP/1.0 200 ASX Follows\r\n"
1515 "Content-type: video/x-ms-asf\r\n"
1517 "<ASX Version=\"3\">\r\n"
1519 "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n"
1520 "</ASX>\r\n", hostbuf, filename, info);
1525 "HTTP/1.0 200 RAM Follows\r\n"
1526 "Content-type: audio/x-pn-realaudio\r\n"
1528 "# Autogenerated by ffserver\r\n"
1529 "http://%s/%s%s\r\n", hostbuf, filename, info);
1534 "HTTP/1.0 200 ASF Redirect follows\r\n"
1535 "Content-type: video/x-ms-asf\r\n"
1538 "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info);
1543 char hostname[256], *p;
1545 av_strlcpy(hostname, hostbuf,
sizeof(hostname));
1546 p = strrchr(hostname,
':');
1550 "HTTP/1.0 200 RTSP Redirect follows\r\n"
1552 "Content-type: application/x-rtsp\r\n"
1554 "rtsp://%s:%d/%s\r\n", hostname, ntohs(config.
rtsp_addr.sin_port), filename);
1563 struct sockaddr_in my_addr;
1566 "HTTP/1.0 200 OK\r\n"
1567 "Content-type: application/sdp\r\n"
1571 len =
sizeof(my_addr);
1574 if (getsockname(c->
fd, (
struct sockaddr *)&my_addr, &len))
1575 http_log(
"getsockname() failed\n");
1581 if (sdp_data_size > 0) {
1582 memcpy(q, sdp_data, sdp_data_size);
1603 snprintf(msg,
sizeof(msg),
"ASX/RAM file not handled");
1616 const char *logline = 0;
1619 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1625 client_id = strtol(p + 18, 0, 10);
1626 p = strchr(p,
'\n');
1634 char *eol = strchr(logline,
'\n');
1639 if (eol[-1] ==
'\r')
1641 http_log(
"%.*s\n", (
int) (eol - logline), logline);
1654 for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->
next) {
1663 snprintf(msg,
sizeof(msg),
"POST command not handled");
1668 snprintf(msg,
sizeof(msg),
"could not open feed");
1686 snprintf(msg,
sizeof(msg),
"Input stream corresponding to '%s' not found", url);
1695 mime_type =
"application/x-octet-stream";
1721 "HTTP/1.0 404 Not Found\r\n"
1722 "Content-type: text/html\r\n"
1725 "<head><title>404 Not Found</title></head>\n"
1745 static const char suffix[] =
" kMGTP";
1748 for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++);
1756 const char *
type =
"unknown";
1757 char parameters[64];
1763 avio_printf(pb,
"<table cellspacing=0 cellpadding=4><tr><th>Stream<th>"
1764 "type<th>kbits/s<th align=left>codec<th align=left>"
1767 for (i = 0; i < stream_no; i++) {
1776 snprintf(parameters,
sizeof(parameters),
"%d channel(s), %d Hz",
1781 snprintf(parameters,
sizeof(parameters),
1790 avio_printf(pb,
"<tr><td align=right>%d<td>%s<td align=right>%d"
1793 codec ? codec->
name :
"", parameters);
1822 avio_printf(pb,
"<link rel=\"shortcut icon\" href=\"%s\">\n",
1828 avio_printf(pb,
"<table cellspacing=0 cellpadding=4>\n");
1829 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");
1832 char sfilename[1024];
1835 if (stream->
feed == stream) {
1836 stream = stream->
next;
1841 eosf = sfilename + strlen(sfilename);
1842 if (eosf - sfilename >= 4) {
1843 if (strcmp(eosf - 4,
".asf") == 0)
1844 strcpy(eosf - 4,
".asx");
1845 else if (strcmp(eosf - 3,
".rm") == 0)
1846 strcpy(eosf - 3,
".ram");
1847 else if (stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
1851 eosf = strrchr(sfilename,
'.');
1853 eosf = sfilename + strlen(sfilename);
1855 strcpy(eosf,
".sdp");
1857 strcpy(eosf,
".rtsp");
1861 avio_printf(pb,
"<tr><td><a href=\"/%s\">%s</a> ",
1863 avio_printf(pb,
"<td align=right> %d <td align=right> ",
1869 int audio_bit_rate = 0;
1870 int video_bit_rate = 0;
1873 const char *audio_codec_name_extra =
"";
1874 const char *video_codec_name_extra =
"";
1884 if (*audio_codec_name)
1885 audio_codec_name_extra =
"...";
1886 audio_codec_name = codec->
name;
1892 if (*video_codec_name)
1893 video_codec_name_extra =
"...";
1894 video_codec_name = codec->
name;
1905 avio_printf(pb,
"<td align=center> %s <td align=right> %d "
1906 "<td align=right> %d <td> %s %s <td align=right> "
1909 video_bit_rate / 1000, video_codec_name,
1910 video_codec_name_extra, audio_bit_rate / 1000,
1911 audio_codec_name, audio_codec_name_extra);
1921 avio_printf(pb,
"<td align=center> - <td align=right> - "
1922 "<td align=right> - <td><td align=right> - <td>\n");
1925 stream = stream->
next;
1932 if (stream->
feed != stream) {
1933 stream = stream->
next;
1939 avio_printf(pb,
"Running as pid %"PRId64
".\n", (int64_t) stream->
pid);
1948 "ps -o \"%%cpu,cputime\" --no-headers %"PRId64
"",
1949 (int64_t) stream->
pid);
1951 pid_stat = popen(ps_cmd,
"r");
1956 if (fscanf(pid_stat,
"%9s %63s", cpuperc, cpuused) == 2) {
1957 avio_printf(pb,
"Currently using %s%% of the cpu. "
1958 "Total time used %s.\n",
1970 stream = stream->
next;
1976 avio_printf(pb,
"Number of connections: %d / %d<br>\n",
1979 avio_printf(pb,
"Bandwidth in use: %"PRIu64
"k / %"PRIu64
"k<br>\n",
1983 avio_printf(pb,
"<tr><th>#<th>File<th>IP<th>Proto<th>State<th>Target "
1984 "bits/sec<th>Actual bits/sec<th>Bytes transferred\n");
2003 avio_printf(pb,
"<tr><td><b>%d</b><td>%s%s<td>%s<td>%s<td>%s"
2021 avio_printf(pb,
"<hr size=1 noshade>Generated at %s", p);
2034 int buf_size, i, ret;
2044 http_log(
"Invalid date specification '%s' for stream\n", buf);
2048 int prebuffer = strtol(buf, 0, 10);
2049 stream_pos =
av_gettime() - prebuffer * (int64_t)1000000;
2058 http_log(
"Invalid date specification '%s' for stream\n", buf);
2064 if (!input_filename[0]) {
2065 http_log(
"No filename was specified for stream\n");
2073 http_log(
"Could not open input '%s': %s\n",
2082 http_log(
"Failed to set buffer size\n");
2091 http_log(
"Could not find stream info for input '%s'\n", input_filename);
2124 int bytes_left, bytes_sent, frame_bytes;
2127 if (frame_bytes <= 0)
2131 bytes_sent = frame_bytes - bytes_left;
2193 http_log(
"Error writing output header for stream '%s': %s\n",
2305 int max_packet_size;
2331 http_log(
"Error writing frame to output for stream '%s': %s\n",
2420 int interleaved_index,
size;
2436 interleaved_index++;
2439 header[1] = interleaved_index;
2440 header[2] = len >> 8;
2506 http_log(
"Stream feed '%s' was not opened\n",
2513 http_log(
"Cannot write to read-only file '%s'\n",
2522 http_log(
"Could not open feed file '%s': %s\n",
2534 http_log(
"Error truncating feed file '%s': %s\n",
2541 http_log(
"Error reading write index from feed file '%s': %s\n",
2551 lseek(fd, 0, SEEK_SET);
2564 int len, loop_run = 0;
2577 }
else if (len == 0) {
2587 }
else if (++loop_run > 10)
2602 }
else if (len == 0)
2614 if (c->
buffer[0] !=
'f' ||
2616 http_log(
"Feed stream has become desynchronized -- disconnecting\n");
2632 http_log(
"Error writing to feed file: %s\n", strerror(errno));
2648 http_log(
"Error writing index to feed file: %s\n",
2654 for(c1 = first_http_ctx;
c1; c1 = c1->
next) {
2691 http_log(
"Feed '%s' stream number does not match registered feed\n",
2713 for(c1 = first_http_ctx;
c1; c1 = c1->
next) {
2733 str =
"Unknown Error";
2735 avio_printf(c->
pb,
"RTSP/1.0 %d %s\r\n", error_number, str);
2741 strftime(buf2,
sizeof(buf2),
"%a, %d %b %Y %H:%M:%S", tm);
2753 const char *p, *p1, *p2;
2766 get_word(protocol,
sizeof(protocol), &p);
2779 if (strcmp(protocol,
"RTSP/1.0")) {
2786 while (*p !=
'\n' && *p !=
'\0')
2790 while (*p !=
'\0') {
2791 p1 = memchr(p,
'\n', (
char *)c->
buffer_ptr - p);
2795 if (p2 > p && p2[-1] ==
'\r')
2801 if (len >
sizeof(line) - 1)
2802 len =
sizeof(line) - 1;
2803 memcpy(line, p, len);
2812 if (!strcmp(cmd,
"DESCRIBE"))
2814 else if (!strcmp(cmd,
"OPTIONS"))
2816 else if (!strcmp(cmd,
"SETUP"))
2818 else if (!strcmp(cmd,
"PLAY"))
2820 else if (!strcmp(cmd,
"PAUSE"))
2822 else if (!strcmp(cmd,
"TEARDOWN"))
2841 struct in_addr my_ip)
2852 if (!avc || !rtp_format)
2857 entry ? entry->
value :
"No Title", 0);
2889 return *pbuffer ? strlen(*pbuffer) :
AVERROR(ENOMEM);
2898 "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
2910 struct sockaddr_in my_addr;
2920 stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp") &&
2933 len =
sizeof(my_addr);
2934 getsockname(c->
fd, (
struct sockaddr *)&my_addr, &len);
2937 if (content_length < 0) {
2944 avio_printf(c->
pb,
"Content-Length: %d\r\n", content_length);
2954 if (session_id[0] ==
'\0')
2957 for(c = first_http_ctx;
c; c = c->
next) {
2981 int stream_index, rtp_port, rtcp_port;
2987 struct sockaddr_in dest_addr;
2999 strcmp(stream->
fmt->
name,
"rtp")) {
3003 if (!strcmp(path, stream->
filename)) {
3012 for(stream_index = 0; stream_index < stream->
nb_streams;
3014 snprintf(buf,
sizeof(buf),
"%s/streamid=%d",
3016 if (!strcmp(path, buf))
3027 unsigned random0 =
av_lfg_get(&random_state);
3028 unsigned random1 =
av_lfg_get(&random_state);
3062 if (rtp_c->
stream != stream) {
3068 if (rtp_c->
rtp_ctx[stream_index]) {
3082 setup.transport_option[0] =
'\0';
3102 "client_port=%d-%d;server_port=%d-%d",
3104 rtp_port, rtcp_port);
3107 avio_printf(c->
pb,
"Transport: RTP/AVP/TCP;interleaved=%d-%d",
3108 stream_index * 2, stream_index * 2 + 1);
3113 if (setup.transport_option[0] !=
'\0')
3127 const char *session_id)
3146 snprintf(buf,
sizeof(buf),
"%s/streamid=%d",
3148 if(!strncmp(path, buf,
sizeof(buf)))
3154 if (len > 0 && path[len - 1] ==
'/' &&
3222 const char *session_id,
3226 const char *proto_str;
3255 proto_str =
"MCAST";
3290 int stream_index,
struct sockaddr_in *dest_addr,
3298 int max_packet_size;
3325 ipaddr = inet_ntoa(dest_addr->sin_addr);
3339 "rtp://%s:%d?multicast=1&ttl=%d",
3340 ipaddr, ntohs(dest_addr->sin_port), ttl);
3343 "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
3360 http_log(
"%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
3361 ipaddr, ntohs(dest_addr->sin_port),
3381 c->
rtp_ctx[stream_index] = ctx;
3478 int mpeg4_count, i,
size;
3496 printf(
"MPEG4 without extra data: trying to find header in %s\n",
3498 while (mpeg4_count > 0) {
3508 while (p < pkt.
data + pkt.
size - 4) {
3510 if (p[0] == 0x00 && p[1] == 0x00 &&
3511 p[2] == 0x01 && p[3] == 0xb6) {
3512 size = p - pkt.
data;
3533 for(stream = config.
first_stream; stream; stream = stream_next) {
3535 stream_next = stream->
next;
3541 if (stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
3548 http_log(
"Unspecified feed file for stream '%s'\n",
3553 http_log(
"Opening feed file '%s' for stream '%s'\n",
3567 http_log(
"Could not find codec parameters from '%s'\n",
3591 feed = stream->
feed;
3619 http_log(
"Failed to set buffer size\n");
3633 http_log(
"Index & Id do not match for stream %d (%s)\n",
3641 #define CHECK_CODEC(x) (ccf->x != ccs->x)
3644 http_log(
"Codecs do not match for stream %d\n", i);
3647 http_log(
"Codec bitrates do not match for stream %d\n", i);
3654 http_log(
"Codec width, height and framerate do not match for stream %d\n", i);
3661 http_log(
"Codec sample_rate, channels, frame_size do not match for stream %d\n", i);
3673 http_log(
"Deleting feed file '%s' as stream counts differ (%d != %d)\n",
3678 http_log(
"Deleting feed file '%s' as it appears to be corrupt\n",
3683 http_log(
"Unable to delete feed file '%s' as it is marked readonly\n",
3694 http_log(
"Failed to allocate context\n");
3699 http_log(
"Unable to create feed file '%s' as it is marked readonly\n",
3706 http_log(
"Could not open output feed file '%s'\n",
3714 http_log(
"Container doesn't support the required parameters\n");
3727 http_log(
"Could not open output feed file '%s'\n",
3733 feed->
feed_size = lseek(fd, 0, SEEK_END);
3762 stream->
bandwidth = (bandwidth + 999) / 1000;
3771 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
3775 if (feed->
pid != pid)
3781 "%s: Pid %"PRId64
" exited with status %d after %d seconds\n",
3782 feed->
filename, (int64_t) pid, status, uptime);
3801 printf(
"usage: ffserver [options]\n"
3802 "Hyper fast multi format Audio/Video streaming server\n");
3810 {
"d", 0, {(
void*)
opt_debug},
"enable debug mode" },
3811 {
"f",
HAS_ARG |
OPT_STRING, {(
void*)&config.
filename },
"use configfile instead of /etc/ffserver.conf",
"configfile" },
3817 struct sigaction sigact = { { 0 } };
3832 unsetenv(
"http_proxy");
3837 sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
3838 sigaction(SIGCHLD, &sigact, 0);
3841 fprintf(stderr,
"Error reading configuration file '%s': %s\n",
3863 signal(SIGPIPE, SIG_IGN);
3866 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)
void av_free_packet(AVPacket *pkt)
Free a packet.
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
int avformat_write_header(AVFormatContext *s, AVDictionary **options)
Allocate the stream private data and write the stream header to an output media file.
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.
int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options)
Open an input stream and read the header.
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)
#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.
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.
static void build_feed_streams(void)
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
int av_isspace(int c)
Locale-independent conversion of ASCII isspace.
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
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.
void ff_rtsp_parse_line(RTSPMessageHeader *reply, const char *buf, RTSPState *rt, const char *method)
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 ** 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)
int duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
void av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
Copy entries from one AVDictionary struct into another.
static void htmlstrip(char *s)
AVStream * streams[FFSERVER_MAX_STREAMS]
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. ...
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]
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.
int bit_rate
the average bitrate
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.
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.
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
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)
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.
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 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
int ffurl_open(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options)
Create an URLContext for accessing to the resource indicated by url, and open it. ...
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
#define RTSP_STATUS_CODE2STRING(x)
void * priv_data
Format private data.
static void new_connection(int server_fd, int is_rtsp)
static char * ctime1(char *buf2, int buf_size)
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
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
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)