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,
232 struct in_addr my_ip);
237 const char *session_id,
240 int stream_index,
struct sockaddr_in *dest_addr,
261 s += strspn(s,
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,. ");
271 if (lseek(fd, 8, SEEK_SET) < 0)
273 if (read(fd, buf, 8) != 8)
284 buf[i] = (pos >> (56 - i * 8)) & 0xff;
285 if (lseek(fd, 8, SEEK_SET) < 0)
287 if (write(fd, buf, 8) != 8)
300 static char *
ctime1(
char *buf2,
int buf_size)
308 p = buf2 + strlen(p) - 1;
316 static int print_prefix = 1;
326 print_prefix = strstr(fmt,
"\n") !=
NULL;
332 __attribute__ ((format (printf, 1, 2)))
337 va_start(vargs, fmt);
344 static int print_prefix = 1;
348 if (print_prefix && avc)
350 print_prefix = strstr(fmt,
"\n") !=
NULL;
359 http_log(
"%s - - [%s] \"%s %s\" %d %"PRId64
"\n",
400 slash = strrchr(pathname,
'/');
405 strcpy(slash,
"ffmpeg");
407 for (; feed; feed = feed->
next) {
416 http_log(
"Unable to create children\n");
432 for (i = 3; i < 256; i++)
436 if (!freopen(
"/dev/null",
"r", stdin))
437 http_log(
"failed to redirect STDIN to /dev/null\n;");
438 if (!freopen(
"/dev/null",
"w", stdout))
439 http_log(
"failed to redirect STDOUT to /dev/null\n;");
440 if (!freopen(
"/dev/null",
"w", stderr))
441 http_log(
"failed to redirect STDERR to /dev/null\n;");
444 signal(SIGPIPE, SIG_DFL);
455 server_fd = socket(AF_INET,SOCK_STREAM,0);
462 if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp,
sizeof(tmp)))
465 my_addr->sin_family = AF_INET;
466 if (bind (server_fd, (
struct sockaddr *) my_addr,
sizeof (*my_addr)) < 0) {
468 snprintf(bindmsg,
sizeof(bindmsg),
"bind(port %d)",
469 ntohs(my_addr->sin_port));
475 if (listen (server_fd, 5) < 0) {
493 struct sockaddr_in dest_addr = {0};
494 int default_port, stream_index;
495 unsigned int random0, random1;
507 snprintf(session_id,
sizeof(session_id),
"%08x%08x",
516 dest_addr.sin_family = AF_INET;
526 http_log(
"Could not open input stream for stream '%s'\n",
532 for(stream_index = 0; stream_index < stream->
nb_streams;
539 http_log(
"Could not open output stream '%s/streamid=%d'\n",
551 int server_fd = 0, rtsp_server_fd = 0;
553 struct pollfd *poll_table, *poll_entry;
557 sizeof(*poll_table));
559 http_log(
"Impossible to allocate a poll table handling %d "
574 if (rtsp_server_fd < 0) {
581 if (!rtsp_server_fd && !server_fd) {
582 http_log(
"HTTP and RTSP disabled.\n");
594 poll_entry = poll_table;
596 poll_entry->fd = server_fd;
597 poll_entry->events = POLLIN;
600 if (rtsp_server_fd) {
601 poll_entry->fd = rtsp_server_fd;
602 poll_entry->events = POLLIN;
618 poll_entry->events = POLLOUT;
629 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)
719 "HTTP/1.0 503 Server too busy\r\n"
720 "Content-type: text/html\r\n"
722 "<html><head><title>Too busy</title></head><body>\r\n"
723 "<p>The server is too busy to serve your request at this time.</p>\r\n"
724 "<p>The number of current connections is %u, and this exceeds the limit of %u.</p>\r\n"
725 "</body></html>\r\n",
728 if (send(fd, buffer, len, 0) < len)
730 "Could not send too-busy reply, send() failed\n");
736 struct sockaddr_in from_addr;
741 len =
sizeof(from_addr);
742 fd = accept(server_fd, (
struct sockaddr *)&from_addr,
745 http_log(
"error during accept %s\n", strerror(errno));
804 for(c1 = first_http_ctx;
c1; c1 = c1->
next) {
883 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
903 if ((ptr >= c->
buffer + 2 && !memcmp(ptr-2,
"\n\n", 2)) ||
904 (ptr >= c->
buffer + 4 && !memcmp(ptr-4,
"\r\n\r\n", 4))) {
916 }
else goto read_loop;
921 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
958 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
977 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
986 if (c->
poll_entry->revents & (POLLIN | POLLERR | POLLHUP))
993 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1015 if (c->
poll_entry->revents & (POLLERR | POLLHUP)) {
1057 for (p = request; *p && *p !=
'\r' && *p !=
'\n'; ) {
1059 const char *q = p + 7;
1070 memset(rates, 0xff, ratelen);
1073 while (*q && *q !=
'\n' && *q !=
':')
1076 if (sscanf(q,
":%d:%d", &stream_no, &rate_no) != 2)
1080 if (stream_no < ratelen && stream_no >= 0)
1081 rates[stream_no] = rate_no;
1090 p = strchr(p,
'\n');
1104 int best_bitrate = 100000000;
1122 if (feed_codec->
bit_rate <= bit_rate) {
1123 if (best_bitrate > bit_rate ||
1124 feed_codec->
bit_rate > best_bitrate) {
1125 best_bitrate = feed_codec->
bit_rate;
1130 if (feed_codec->
bit_rate < best_bitrate) {
1131 best_bitrate = feed_codec->
bit_rate;
1142 int action_required = 0;
1170 action_required = 1;
1173 return action_required;
1185 if ((q - buf) < buf_size - 1)
1217 while (fgets(line,
sizeof(line), f)) {
1222 if (*p ==
'\0' || *p ==
'#')
1252 unsigned long src_addr = src->s_addr;
1254 for (acl = in_acl; acl; acl = acl->
next) {
1255 if (src_addr >= acl->
first.s_addr && src_addr <= acl->last.s_addr)
1257 last_action = acl->
action;
1261 return (last_action ==
IP_DENY) ? 1 : 0;
1294 p = strrchr(file1,
'.');
1299 p = strrchr(file2,
'.');
1302 if (!strcmp(file1, file2)) {
1325 char info[1024], filename[1024];
1329 const char *mime_type;
1333 const char *useragent = 0;
1339 if (!strcmp(cmd,
"GET"))
1341 else if (!strcmp(cmd,
"POST"))
1349 get_word(protocol,
sizeof(protocol), (
const char **)&p);
1350 if (strcmp(protocol,
"HTTP/1.0") && strcmp(protocol,
"HTTP/1.1"))
1356 http_log(
"%s - - New connection: %s %s\n",
1357 inet_ntoa(c->
from_addr.sin_addr), cmd, url);
1360 p1 = strchr(url,
'?');
1367 av_strlcpy(filename, url + ((*url ==
'/') ? 1 : 0),
sizeof(filename)-1);
1369 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1372 if (*useragent && *useragent !=
'\n' &&
av_isspace(*useragent))
1376 p = strchr(p,
'\n');
1386 filename[strlen(filename)-1] =
'f';
1393 strcpy(filename + strlen(filename)-2,
"m");
1403 if (!strlen(filename))
1404 av_strlcpy(filename,
"index.html",
sizeof(filename) - 1);
1410 stream = stream->
next;
1413 snprintf(msg,
sizeof(msg),
"File '%s' not found", url);
1414 http_log(
"File '%s' not found\n", url);
1426 "HTTP/1.0 301 Moved\r\n"
1428 "Content-type: text/html\r\n"
1430 "<html><head><title>Moved</title></head><body>\r\n"
1431 "You should be <a href=\"%s\">redirected</a>.\r\n"
1432 "</body></html>\r\n",
1457 snprintf(msg,
sizeof(msg),
"This feed is already being received.");
1466 "HTTP/1.0 503 Server too busy\r\n"
1467 "Content-type: text/html\r\n"
1469 "<html><head><title>Too busy</title></head><body>\r\n"
1470 "<p>The server is too busy to serve your request at this time.</p>\r\n"
1471 "<p>The bandwidth being served (including your stream) is %"PRIu64
"kbit/sec, "
1472 "and this exceeds the limit of %"PRIu64
"kbit/sec.</p>\r\n"
1473 "</body></html>\r\n",
1484 const char *hostinfo = 0;
1486 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1491 p = strchr(p,
'\n');
1505 eoh = strchr(hostinfo,
'\n');
1507 if (eoh[-1] ==
'\r')
1510 if (eoh - hostinfo <
sizeof(hostbuf) - 1) {
1511 memcpy(hostbuf, hostinfo, eoh - hostinfo);
1512 hostbuf[eoh - hostinfo] = 0;
1516 switch(redir_type) {
1519 "HTTP/1.0 200 ASX Follows\r\n"
1520 "Content-type: video/x-ms-asf\r\n"
1522 "<ASX Version=\"3\">\r\n"
1524 "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n"
1525 "</ASX>\r\n", hostbuf, filename, info);
1530 "HTTP/1.0 200 RAM Follows\r\n"
1531 "Content-type: audio/x-pn-realaudio\r\n"
1533 "# Autogenerated by ffserver\r\n"
1534 "http://%s/%s%s\r\n", hostbuf, filename, info);
1539 "HTTP/1.0 200 ASF Redirect follows\r\n"
1540 "Content-type: video/x-ms-asf\r\n"
1543 "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info);
1548 char hostname[256], *p;
1550 av_strlcpy(hostname, hostbuf,
sizeof(hostname));
1551 p = strrchr(hostname,
':');
1555 "HTTP/1.0 200 RTSP Redirect follows\r\n"
1557 "Content-type: application/x-rtsp\r\n"
1559 "rtsp://%s:%d/%s\r\n", hostname, ntohs(config.
rtsp_addr.sin_port), filename);
1568 struct sockaddr_in my_addr;
1571 "HTTP/1.0 200 OK\r\n"
1572 "Content-type: application/sdp\r\n"
1576 len =
sizeof(my_addr);
1579 if (getsockname(c->
fd, (
struct sockaddr *)&my_addr, &len))
1580 http_log(
"getsockname() failed\n");
1586 if (sdp_data_size > 0) {
1587 memcpy(q, sdp_data, sdp_data_size);
1608 snprintf(msg,
sizeof(msg),
"ASX/RAM file not handled");
1621 const char *logline = 0;
1624 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1630 client_id = strtol(p + 18, 0, 10);
1631 p = strchr(p,
'\n');
1639 char *eol = strchr(logline,
'\n');
1644 if (eol[-1] ==
'\r')
1646 http_log(
"%.*s\n", (
int) (eol - logline), logline);
1659 for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->
next) {
1668 snprintf(msg,
sizeof(msg),
"POST command not handled");
1673 snprintf(msg,
sizeof(msg),
"could not open feed");
1691 snprintf(msg,
sizeof(msg),
"Input stream corresponding to '%s' not found", url);
1700 mime_type =
"application/x-octet-stream";
1726 "HTTP/1.0 404 Not Found\r\n"
1727 "Content-type: text/html\r\n"
1730 "<head><title>404 Not Found</title></head>\n"
1749 static const char suffix[] =
" kMGTP";
1752 for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++);
1780 avio_printf(pb,
"<link rel=\"shortcut icon\" href=\"%s\">\n",
1786 avio_printf(pb,
"<table cellspacing=0 cellpadding=4>\n");
1787 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");
1790 char sfilename[1024];
1793 if (stream->
feed == stream) {
1794 stream = stream->
next;
1799 eosf = sfilename + strlen(sfilename);
1800 if (eosf - sfilename >= 4) {
1801 if (strcmp(eosf - 4,
".asf") == 0)
1802 strcpy(eosf - 4,
".asx");
1803 else if (strcmp(eosf - 3,
".rm") == 0)
1804 strcpy(eosf - 3,
".ram");
1805 else if (stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
1809 eosf = strrchr(sfilename,
'.');
1811 eosf = sfilename + strlen(sfilename);
1813 strcpy(eosf,
".sdp");
1815 strcpy(eosf,
".rtsp");
1819 avio_printf(pb,
"<tr><td><a href=\"/%s\">%s</a> ",
1821 avio_printf(pb,
"<td align=right> %d <td align=right> ",
1827 int audio_bit_rate = 0;
1828 int video_bit_rate = 0;
1831 const char *audio_codec_name_extra =
"";
1832 const char *video_codec_name_extra =
"";
1842 if (*audio_codec_name)
1843 audio_codec_name_extra =
"...";
1844 audio_codec_name = codec->
name;
1850 if (*video_codec_name)
1851 video_codec_name_extra =
"...";
1852 video_codec_name = codec->
name;
1863 avio_printf(pb,
"<td align=center> %s <td align=right> %d "
1864 "<td align=right> %d <td> %s %s <td align=right> "
1867 video_bit_rate / 1000, video_codec_name,
1868 video_codec_name_extra, audio_bit_rate / 1000,
1869 audio_codec_name, audio_codec_name_extra);
1879 avio_printf(pb,
"<td align=center> - <td align=right> - "
1880 "<td align=right> - <td><td align=right> - <td>\n");
1883 stream = stream->
next;
1890 if (stream->
feed != stream) {
1891 stream = stream->
next;
1906 "ps -o \"%%cpu,cputime\" --no-headers %d",
1909 pid_stat = popen(ps_cmd,
"r");
1914 if (fscanf(pid_stat,
"%9s %63s", cpuperc, cpuused) == 2) {
1915 avio_printf(pb,
"Currently using %s%% of the cpu. "
1916 "Total time used %s.\n",
1927 avio_printf(pb,
"<table cellspacing=0 cellpadding=4><tr><th>Stream<th>"
1928 "type<th>kbits/s<th align=left>codec<th align=left>"
1934 const char *
type =
"unknown";
1935 char parameters[64];
1942 snprintf(parameters,
sizeof(parameters),
"%d channel(s), %d Hz",
1947 snprintf(parameters,
sizeof(parameters),
1956 avio_printf(pb,
"<tr><td align=right>%d<td>%s<td align=right>%d"
1959 codec ? codec->
name :
"", parameters);
1963 stream = stream->
next;
1969 avio_printf(pb,
"Number of connections: %d / %d<br>\n",
1972 avio_printf(pb,
"Bandwidth in use: %"PRIu64
"k / %"PRIu64
"k<br>\n",
1976 avio_printf(pb,
"<tr><th>#<th>File<th>IP<th>Proto<th>State<th>Target "
1977 "bits/sec<th>Actual bits/sec<th>Bytes transferred\n");
1996 avio_printf(pb,
"<tr><td><b>%d</b><td>%s%s<td>%s<td>%s<td>%s"
2014 avio_printf(pb,
"<hr size=1 noshade>Generated at %s", p);
2027 int buf_size, i,
ret;
2037 http_log(
"Invalid date specification '%s' for stream\n", buf);
2041 int prebuffer = strtol(buf, 0, 10);
2042 stream_pos =
av_gettime() - prebuffer * (int64_t)1000000;
2051 http_log(
"Invalid date specification '%s' for stream\n", buf);
2057 if (!input_filename[0]) {
2058 http_log(
"No filename was specified for stream\n");
2066 http_log(
"Could not open input '%s': %s\n",
2075 http_log(
"Failed to set buffer size\n");
2084 http_log(
"Could not find stream info for input '%s'\n", input_filename);
2118 int bytes_left, bytes_sent, frame_bytes;
2121 if (frame_bytes <= 0)
2125 bytes_sent = frame_bytes - bytes_left;
2187 http_log(
"Error writing output header for stream '%s': %s\n",
2222 }
else if (ret ==
AVERROR(EAGAIN)) {
2299 int max_packet_size;
2325 http_log(
"Error writing frame to output for stream '%s': %s\n",
2413 int interleaved_index,
size;
2429 interleaved_index++;
2432 header[1] = interleaved_index;
2433 header[2] = len >> 8;
2499 http_log(
"Stream feed '%s' was not opened\n",
2506 http_log(
"Cannot write to read-only file '%s'\n",
2515 http_log(
"Could not open feed file '%s': %s\n",
2527 http_log(
"Error truncating feed file '%s': %s\n",
2534 http_log(
"Error reading write index from feed file '%s': %s\n",
2545 lseek(fd, 0, SEEK_SET);
2558 int len, loop_run = 0;
2571 }
else if (len == 0) {
2581 }
else if (++loop_run > 10) {
2597 }
else if (len == 0)
2609 if (c->
buffer[0] !=
'f' ||
2611 http_log(
"Feed stream has become desynchronized -- disconnecting\n");
2627 http_log(
"Error writing to feed file: %s\n", strerror(errno));
2643 http_log(
"Error writing index to feed file: %s\n",
2649 for(c1 = first_http_ctx;
c1; c1 = c1->
next) {
2686 http_log(
"Feed '%s' stream number does not match registered feed\n",
2708 for(c1 = first_http_ctx;
c1; c1 = c1->
next) {
2728 str =
"Unknown Error";
2730 avio_printf(c->
pb,
"RTSP/1.0 %d %s\r\n", error_number, str);
2736 strftime(buf2,
sizeof(buf2),
"%a, %d %b %Y %H:%M:%S", tm);
2748 const char *p, *p1, *p2;
2761 get_word(protocol,
sizeof(protocol), &p);
2774 if (strcmp(protocol,
"RTSP/1.0")) {
2781 while (*p !=
'\n' && *p !=
'\0')
2785 while (*p !=
'\0') {
2786 p1 = memchr(p,
'\n', (
char *)c->
buffer_ptr - p);
2790 if (p2 > p && p2[-1] ==
'\r')
2796 if (len >
sizeof(line) - 1)
2797 len =
sizeof(line) - 1;
2798 memcpy(line, p, len);
2807 if (!strcmp(cmd,
"DESCRIBE"))
2809 else if (!strcmp(cmd,
"OPTIONS"))
2811 else if (!strcmp(cmd,
"SETUP"))
2813 else if (!strcmp(cmd,
"PLAY"))
2815 else if (!strcmp(cmd,
"PAUSE"))
2817 else if (!strcmp(cmd,
"TEARDOWN"))
2836 struct in_addr my_ip)
2847 if (!avc || !rtp_format) {
2852 entry ? entry->
value :
"No Title", 0);
2885 return *pbuffer ? strlen(*pbuffer) :
AVERROR(ENOMEM);
2894 "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
2906 struct sockaddr_in my_addr;
2916 stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp") &&
2929 len =
sizeof(my_addr);
2930 getsockname(c->
fd, (
struct sockaddr *)&my_addr, &len);
2933 if (content_length < 0) {
2940 avio_printf(c->
pb,
"Content-Length: %d\r\n", content_length);
2950 if (session_id[0] ==
'\0')
2953 for(c = first_http_ctx;
c; c = c->
next) {
2977 int stream_index, rtp_port, rtcp_port;
2983 struct sockaddr_in dest_addr;
2995 strcmp(stream->
fmt->
name,
"rtp")) {
2999 if (!strcmp(path, stream->
filename)) {
3008 for(stream_index = 0; stream_index < stream->
nb_streams;
3010 snprintf(buf,
sizeof(buf),
"%s/streamid=%d",
3012 if (!strcmp(path, buf))
3023 unsigned random0 =
av_lfg_get(&random_state);
3024 unsigned random1 =
av_lfg_get(&random_state);
3058 if (rtp_c->
stream != stream) {
3064 if (rtp_c->
rtp_ctx[stream_index]) {
3078 setup.transport_option[0] =
'\0';
3098 "client_port=%d-%d;server_port=%d-%d",
3100 rtp_port, rtcp_port);
3103 avio_printf(c->
pb,
"Transport: RTP/AVP/TCP;interleaved=%d-%d",
3104 stream_index * 2, stream_index * 2 + 1);
3109 if (setup.transport_option[0] !=
'\0')
3121 const char *session_id)
3140 snprintf(buf,
sizeof(buf),
"%s/streamid=%d",
3142 if(!strncmp(path, buf,
sizeof(buf))) {
3148 if (len > 0 && path[len - 1] ==
'/' &&
3216 const char *session_id,
3220 const char *proto_str;
3249 proto_str =
"MCAST";
3282 int stream_index,
struct sockaddr_in *dest_addr,
3290 int max_packet_size;
3317 ipaddr = inet_ntoa(dest_addr->sin_addr);
3331 "rtp://%s:%d?multicast=1&ttl=%d",
3332 ipaddr, ntohs(dest_addr->sin_port), ttl);
3335 "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
3352 http_log(
"%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
3353 ipaddr, ntohs(dest_addr->sin_port),
3373 c->
rtp_ctx[stream_index] = ctx;
3470 int mpeg4_count, i,
size;
3488 printf(
"MPEG4 without extra data: trying to find header in %s\n",
3490 while (mpeg4_count > 0) {
3500 while (p < pkt.
data + pkt.
size - 4) {
3502 if (p[0] == 0x00 && p[1] == 0x00 &&
3503 p[2] == 0x01 && p[3] == 0xb6) {
3504 size = p - pkt.
data;
3525 for(stream = config.
first_stream; stream; stream = stream_next) {
3527 stream_next = stream->
next;
3533 if (stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
3540 http_log(
"Unspecified feed file for stream '%s'\n",
3545 http_log(
"Opening feed file '%s' for stream '%s'\n",
3559 http_log(
"Could not find codec parameters from '%s'\n",
3583 feed = stream->
feed;
3610 http_log(
"Failed to set buffer size\n");
3624 http_log(
"Index & Id do not match for stream %d (%s)\n",
3632 #define CHECK_CODEC(x) (ccf->x != ccs->x)
3635 http_log(
"Codecs do not match for stream %d\n", i);
3638 http_log(
"Codec bitrates do not match for stream %d\n", i);
3645 http_log(
"Codec width, height and framerate do not match for stream %d\n", i);
3652 http_log(
"Codec sample_rate, channels, frame_size do not match for stream %d\n", i);
3664 http_log(
"Deleting feed file '%s' as stream counts differ (%d != %d)\n",
3669 http_log(
"Deleting feed file '%s' as it appears to be corrupt\n",
3674 http_log(
"Unable to delete feed file '%s' as it is marked readonly\n",
3685 http_log(
"Failed to allocate context\n");
3690 http_log(
"Unable to create feed file '%s' as it is marked readonly\n",
3697 http_log(
"Could not open output feed file '%s'\n",
3705 http_log(
"Container doesn't support the required parameters\n");
3718 http_log(
"Could not open output feed file '%s'\n",
3724 feed->
feed_size = lseek(fd, 0, SEEK_END);
3753 stream->
bandwidth = (bandwidth + 999) / 1000;
3762 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
3766 if (feed->
pid == pid) {
3771 "%s: Pid %d exited with status %d after %d seconds\n",
3772 feed->
filename, pid, status, uptime);
3792 printf(
"usage: ffserver [options]\n"
3793 "Hyper fast multi format Audio/Video streaming server\n");
3801 {
"d", 0, {(
void*)
opt_debug},
"enable debug mode" },
3802 {
"f",
HAS_ARG |
OPT_STRING, {(
void*)&config.
filename },
"use configfile instead of /etc/ffserver.conf",
"configfile" },
3808 struct sigaction sigact = { { 0 } };
3823 unsetenv(
"http_proxy");
3828 sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
3829 sigaction(SIGCHLD, &sigact, 0);
3832 fprintf(stderr,
"Error reading configuration file '%s': %s\n",
3854 signal(SIGPIPE, SIG_IGN);
3857 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)
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.
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
#define FF_ARRAY_ELEMS(a)
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)
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)
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
#define FF_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding...
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
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.
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)