28 #define closesocket close
57 #include <sys/ioctl.h>
69 #define PATH_LENGTH 1024
107 #define IOBUFFER_INIT_SIZE 8192
110 #define HTTP_REQUEST_TIMEOUT (15 * 1000)
111 #define RTSP_REQUEST_TIMEOUT (3600 * 24 * 1000)
113 #define SYNC_TIMEOUT (10 * 1000)
195 .nb_max_connections = 5,
196 .max_bandwidth = 1000,
226 struct in_addr my_ip);
234 int stream_index,
struct sockaddr_in *dest_addr,
262 #define COPY(a) st->a = lst->a;
269 COPY(sample_aspect_ratio)
270 COPY(recommended_encoder_configuration)
274 if (!buffer || !entity)
277 *buffer++ = *entity++;
288 const char *amp =
"&";
289 const char *lt =
"<";
290 const char *gt =
">";
293 size_t final_size = 0;
301 while (*src !=
'\0') {
323 while (*src !=
'\0') {
352 if (lseek(fd, 8, SEEK_SET) < 0)
354 if (read(fd, buf, 8) != 8)
365 buf[i] = (pos >> (56 - i * 8)) & 0xff;
366 if (lseek(fd, 8, SEEK_SET) < 0)
368 if (write(fd, buf, 8) != 8)
385 static char *
ctime1(
char *buf2,
size_t buf_size)
397 p = buf2 + strlen(buf2) - 1;
405 static int print_prefix = 1;
415 print_prefix = strstr(fmt,
"\n") !=
NULL;
421 __attribute__ ((
format (printf, 1, 2)))
426 va_start(vargs, fmt);
433 static int print_prefix = 1;
437 if (print_prefix && avc)
439 print_prefix = strstr(fmt,
"\n") !=
NULL;
448 http_log(
"%s - - [%s] \"%s %s\" %d %"PRId64
"\n",
479 char *dirname, *prog;
493 http_log(
"Could not start children. Command line: '%s' exceeds "
502 pathname = *dirname ?
av_asprintf(
"%s/%s", dirname,
"ffmpeg")
506 if (!prog || !pathname) {
507 http_log(
"Could not allocate memory for children cmd line\n");
511 for (; feed; feed = feed->
next) {
520 http_log(
"Unable to create children: %s\n", strerror(errno));
537 for (i = 3; i < 256; i++)
541 if (!freopen(
"/dev/null",
"r", stdin))
542 http_log(
"failed to redirect STDIN to /dev/null\n;");
543 if (!freopen(
"/dev/null",
"w", stdout))
544 http_log(
"failed to redirect STDOUT to /dev/null\n;");
545 if (!freopen(
"/dev/null",
"w", stderr))
546 http_log(
"failed to redirect STDERR to /dev/null\n;");
549 signal(SIGPIPE, SIG_DFL);
562 server_fd = socket(AF_INET,SOCK_STREAM,0);
569 if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp,
sizeof(tmp)))
572 my_addr->sin_family = AF_INET;
573 if (bind (server_fd, (
struct sockaddr *) my_addr,
sizeof (*my_addr)) < 0) {
575 snprintf(bindmsg,
sizeof(bindmsg),
"bind(port %d)",
576 ntohs(my_addr->sin_port));
581 if (
listen (server_fd, 5) < 0) {
602 struct sockaddr_in dest_addr = {0};
603 int default_port, stream_index;
604 unsigned int random0, random1;
616 snprintf(session_id,
sizeof(session_id),
"%08x%08x", random0, random1);
624 dest_addr.sin_family = AF_INET;
634 http_log(
"Could not open input stream for stream '%s'\n",
640 for(stream_index = 0; stream_index < stream->
nb_streams;
647 http_log(
"Could not open output stream '%s/streamid=%d'\n",
659 int server_fd = 0, rtsp_server_fd = 0;
661 struct pollfd *poll_table, *poll_entry;
665 sizeof(*poll_table));
667 http_log(
"Impossible to allocate a poll table handling %d "
680 if (rtsp_server_fd < 0) {
686 if (!rtsp_server_fd && !server_fd) {
687 http_log(
"HTTP and RTSP disabled.\n");
698 poll_entry = poll_table;
700 poll_entry->fd = server_fd;
701 poll_entry->events = POLLIN;
704 if (rtsp_server_fd) {
705 poll_entry->fd = rtsp_server_fd;
706 poll_entry->events = POLLIN;
722 poll_entry->events = POLLOUT;
733 poll_entry->events = POLLOUT;
750 poll_entry->events = POLLIN;
763 ret = poll(poll_table, poll_entry - poll_table, delay);
778 for(c = first_http_ctx;
c; c = c_next) {
787 poll_entry = poll_table;
790 if (poll_entry->revents & POLLIN)
794 if (rtsp_server_fd) {
796 if (poll_entry->revents & POLLIN)
821 "HTTP/1.0 503 Server too busy\r\n"
822 "Content-type: text/html\r\n"
825 "<html><head><title>Too busy</title></head><body>\r\n"
826 "<p>The server is too busy to serve your request at "
828 "<p>The number of current connections is %u, and this "
829 "exceeds the limit of %u.</p>\r\n"
830 "</body></html>\r\n",
833 if (send(fd, buffer, len, 0) < len)
835 "Could not send too-busy reply, send() failed\n");
841 struct sockaddr_in from_addr;
846 len =
sizeof(from_addr);
847 fd = accept(server_fd, (
struct sockaddr *)&from_addr,
850 http_log(
"error during accept %s\n", strerror(errno));
908 for(c1 = first_http_ctx;
c1; c1 = c1->
next) {
920 if (st->codec->codec)
986 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1006 if ((ptr >= c->
buffer + 2 && !memcmp(ptr-2,
"\n\n", 2)) ||
1007 (ptr >= c->
buffer + 4 && !memcmp(ptr-4,
"\r\n\r\n", 4))) {
1019 }
else goto read_loop;
1024 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1061 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1080 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1089 if (c->
poll_entry->revents & (POLLIN | POLLERR | POLLHUP))
1096 if (c->
poll_entry->revents & (POLLERR | POLLHUP))
1118 if (c->
poll_entry->revents & (POLLERR | POLLHUP)) {
1160 for (p = request; *p && *p !=
'\r' && *p !=
'\n'; ) {
1162 const char *q = p + 7;
1173 memset(rates, 0xff, ratelen);
1176 while (*q && *q !=
'\n' && *q !=
':')
1179 if (sscanf(q,
":%d:%d", &stream_no, &rate_no) != 2)
1183 if (stream_no < ratelen && stream_no >= 0)
1184 rates[stream_no] = rate_no;
1193 p = strchr(p,
'\n');
1207 int best_bitrate = 100000000;
1225 if (feed_codec->
bit_rate <= bit_rate) {
1226 if (best_bitrate > bit_rate ||
1227 feed_codec->
bit_rate > best_bitrate) {
1228 best_bitrate = feed_codec->
bit_rate;
1233 if (feed_codec->
bit_rate < best_bitrate) {
1234 best_bitrate = feed_codec->
bit_rate;
1245 int action_required = 0;
1274 action_required = 1;
1278 return action_required;
1286 #define SPACE_CHARS " \t\r\n"
1292 if ((q - buf) < buf_size - 1)
1324 while (fgets(line,
sizeof(line), f)) {
1329 if (*p ==
'\0' || *p ==
'#')
1359 unsigned long src_addr = src->s_addr;
1361 for (acl = in_acl; acl; acl = acl->
next) {
1362 if (src_addr >= acl->
first.s_addr && src_addr <= acl->last.s_addr)
1364 last_action = acl->
action;
1368 return (last_action ==
IP_DENY) ? 1 : 0;
1400 p = strrchr(file1,
'.');
1405 p = strrchr(file2,
'.');
1408 if (!strcmp(file1, file2)) {
1431 char info[1024], filename[1024];
1435 char *encoded_msg =
NULL;
1436 const char *mime_type;
1440 const char *useragent = 0;
1446 if (!strcmp(cmd,
"GET"))
1448 else if (!strcmp(cmd,
"POST"))
1456 get_word(protocol,
sizeof(protocol), (
const char **)&p);
1457 if (strcmp(protocol,
"HTTP/1.0") && strcmp(protocol,
"HTTP/1.1"))
1463 http_log(
"%s - - New connection: %s %s\n",
1464 inet_ntoa(c->
from_addr.sin_addr), cmd, url);
1467 p1 = strchr(url,
'?');
1474 av_strlcpy(filename, url + ((*url ==
'/') ? 1 : 0),
sizeof(filename)-1);
1476 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1479 if (*useragent && *useragent !=
'\n' &&
av_isspace(*useragent))
1483 p = strchr(p,
'\n');
1493 filename[strlen(filename)-1] =
'f';
1500 strcpy(filename + strlen(filename)-2,
"m");
1510 if (!strlen(filename))
1511 av_strlcpy(filename,
"index.html",
sizeof(filename) - 1);
1517 stream = stream->
next;
1520 snprintf(msg,
sizeof(msg),
"File '%s' not found", url);
1521 http_log(
"File '%s' not found\n", url);
1533 "HTTP/1.0 301 Moved\r\n"
1535 "Content-type: text/html\r\n"
1538 "<html><head><title>Moved</title></head><body>\r\n"
1539 "You should be <a href=\"%s\">redirected</a>.\r\n"
1540 "</body></html>\r\n",
1565 snprintf(msg,
sizeof(msg),
"This feed is already being received.");
1574 "HTTP/1.0 503 Server too busy\r\n"
1575 "Content-type: text/html\r\n"
1578 "<html><head><title>Too busy</title></head><body>\r\n"
1579 "<p>The server is too busy to serve your request at "
1580 "this time.</p>\r\n"
1581 "<p>The bandwidth being served (including your stream) "
1582 "is %"PRIu64
"kbit/s, and this exceeds the limit of "
1583 "%"PRIu64
"kbit/s.</p>\r\n"
1584 "</body></html>\r\n",
1595 const char *hostinfo = 0;
1597 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1602 p = strchr(p,
'\n');
1616 eoh = strchr(hostinfo,
'\n');
1618 if (eoh[-1] ==
'\r')
1621 if (eoh - hostinfo <
sizeof(hostbuf) - 1) {
1622 memcpy(hostbuf, hostinfo, eoh - hostinfo);
1623 hostbuf[eoh - hostinfo] = 0;
1627 switch(redir_type) {
1630 "HTTP/1.0 200 ASX Follows\r\n"
1631 "Content-type: video/x-ms-asf\r\n"
1633 "<ASX Version=\"3\">\r\n"
1635 "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n"
1636 "</ASX>\r\n", hostbuf, filename, info);
1641 "HTTP/1.0 200 RAM Follows\r\n"
1642 "Content-type: audio/x-pn-realaudio\r\n"
1644 "# Autogenerated by ffserver\r\n"
1645 "http://%s/%s%s\r\n", hostbuf, filename, info);
1650 "HTTP/1.0 200 ASF Redirect follows\r\n"
1651 "Content-type: video/x-ms-asf\r\n"
1654 "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info);
1659 char hostname[256], *p;
1661 av_strlcpy(hostname, hostbuf,
sizeof(hostname));
1662 p = strrchr(hostname,
':');
1666 "HTTP/1.0 200 RTSP Redirect follows\r\n"
1668 "Content-type: application/x-rtsp\r\n"
1670 "rtsp://%s:%d/%s\r\n", hostname, ntohs(config.
rtsp_addr.sin_port), filename);
1679 struct sockaddr_in my_addr;
1682 "HTTP/1.0 200 OK\r\n"
1683 "Content-type: application/sdp\r\n"
1687 len =
sizeof(my_addr);
1690 if (getsockname(c->
fd, (
struct sockaddr *)&my_addr, &len))
1691 http_log(
"getsockname() failed\n");
1697 if (sdp_data_size > 0) {
1698 memcpy(q, sdp_data, sdp_data_size);
1719 snprintf(msg,
sizeof(msg),
"ASX/RAM file not handled");
1732 const char *logline = 0;
1735 for (p = c->
buffer; *p && *p !=
'\r' && *p !=
'\n'; ) {
1741 client_id = strtol(p + 18, 0, 10);
1742 p = strchr(p,
'\n');
1750 char *eol = strchr(logline,
'\n');
1755 if (eol[-1] ==
'\r')
1757 http_log(
"%.*s\n", (
int) (eol - logline), logline);
1770 for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->
next) {
1779 snprintf(msg,
sizeof(msg),
"POST command not handled");
1784 snprintf(msg,
sizeof(msg),
"could not open feed");
1802 snprintf(msg,
sizeof(msg),
"Input stream corresponding to '%s' not found", url);
1811 mime_type =
"application/x-octet-stream";
1836 http_log(
"Could not encode filename '%s' as HTML\n", msg);
1839 "HTTP/1.0 404 Not Found\r\n"
1840 "Content-type: text/html\r\n"
1845 "<meta charset=\"UTF-8\">\n"
1846 "<title>404 Not Found</title>\n"
1849 "</html>\n", encoded_msg? encoded_msg :
"File not found");
1868 static const char suffix[] =
" kMGTP";
1871 for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++);
1879 const char *
type =
"unknown";
1880 char parameters[64];
1887 "type<th>kbit/s<th>codec<th>"
1890 for (i = 0; i < stream_no; i++) {
1899 snprintf(parameters,
sizeof(parameters),
"%d channel(s), %d Hz",
1904 snprintf(parameters,
sizeof(parameters),
1916 codec ? codec->
name :
"", parameters);
1926 for (o = i = 0; o+10 < clean_len && dirty[i];) {
1927 int len = strspn(dirty+i,
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$-_.+!*(),?/ :;%");
1929 if (o + len >= clean_len)
1931 memcpy(clean + o, dirty + i, len);
1937 case '&':
av_strlcat(clean+o,
"&" , clean_len - o);
break;
1938 case '<':
av_strlcat(clean+o,
"<" , clean_len - o);
break;
1939 case '>':
av_strlcat(clean+o,
">" , clean_len - o);
break;
1940 case '\'':
av_strlcat(clean+o,
"'" , clean_len - o);
break;
1941 case '\"':
av_strlcat(clean+o,
""" , clean_len - o);
break;
1942 default:
av_strlcat(clean+o,
"☹", clean_len - o);
break;
1944 o += strlen(clean+o);
1974 avio_printf(pb,
"<link rel=\"shortcut icon\" href=\"%s\">\n",
1981 avio_printf(pb,
"<tr><th>Path<th>Served<br>Conns<th><br>bytes<th>Format<th>Bit rate<br>kbit/s<th>Video<br>kbit/s<th><br>Codec<th>Audio<br>kbit/s<th><br>Codec<th>Feed\n");
1984 char sfilename[1024];
1987 if (stream->
feed == stream) {
1988 stream = stream->
next;
1993 eosf = sfilename + strlen(sfilename);
1994 if (eosf - sfilename >= 4) {
1995 if (strcmp(eosf - 4,
".asf") == 0)
1996 strcpy(eosf - 4,
".asx");
1997 else if (strcmp(eosf - 3,
".rm") == 0)
1998 strcpy(eosf - 3,
".ram");
1999 else if (stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp")) {
2003 eosf = strrchr(sfilename,
'.');
2005 eosf = sfilename + strlen(sfilename);
2007 strcpy(eosf,
".sdp");
2009 strcpy(eosf,
".rtsp");
2013 avio_printf(pb,
"<tr><td><a href=\"/%s\">%s</a> ",
2023 int audio_bit_rate = 0;
2024 int video_bit_rate = 0;
2027 const char *audio_codec_name_extra =
"";
2028 const char *video_codec_name_extra =
"";
2038 if (*audio_codec_name)
2039 audio_codec_name_extra =
"...";
2040 audio_codec_name = codec->
name;
2046 if (*video_codec_name)
2047 video_codec_name_extra =
"...";
2048 video_codec_name = codec->
name;
2059 avio_printf(pb,
"<td> %s <td> %d <td> %d <td> %s %s <td> "
2062 video_bit_rate / 1000, video_codec_name,
2063 video_codec_name_extra, audio_bit_rate / 1000,
2064 audio_codec_name, audio_codec_name_extra);
2075 "<td> - <td><td> - <td>\n");
2078 stream = stream->
next;
2085 if (stream->
feed != stream) {
2086 stream = stream->
next;
2092 avio_printf(pb,
"Running as pid %"PRId64
".\n", (int64_t) stream->
pid);
2101 "ps -o \"%%cpu,cputime\" --no-headers %"PRId64
"",
2102 (int64_t) stream->
pid);
2104 pid_stat = popen(ps_cmd,
"r");
2109 if (fscanf(pid_stat,
"%9s %63s", cpuperc, cpuused) == 2) {
2110 avio_printf(pb,
"Currently using %s%% of the cpu. "
2111 "Total time used %s.\n",
2123 stream = stream->
next;
2129 avio_printf(pb,
"Number of connections: %d / %d<br>\n",
2132 avio_printf(pb,
"Bandwidth in use: %"PRIu64
"k / %"PRIu64
"k<br>\n",
2136 avio_printf(pb,
"<tr><th>#<th>File<th>IP<th>URL<th>Proto<th>State<th>Target "
2137 "bit/s<th>Actual bit/s<th>Bytes transferred\n");
2157 avio_printf(pb,
"<tr><td><b>%d</b><td>%s%s<td>%s<td>%s<td>%s<td>%s"
2192 int buf_size, i, ret;
2202 http_log(
"Invalid date specification '%s' for stream\n", buf);
2206 int prebuffer = strtol(buf, 0, 10);
2207 stream_pos =
av_gettime() - prebuffer * (int64_t)1000000;
2216 http_log(
"Invalid date specification '%s' for stream\n", buf);
2222 if (!input_filename[0]) {
2223 http_log(
"No filename was specified for stream\n");
2231 http_log(
"Could not open input '%s': %s\n",
2240 http_log(
"Failed to set buffer size\n");
2249 http_log(
"Could not find stream info for input '%s'\n", input_filename);
2282 int bytes_left, bytes_sent, frame_bytes;
2285 if (frame_bytes <= 0)
2289 bytes_sent = frame_bytes - bytes_left;
2349 http_log(
"Error writing output header for stream '%s': %s\n",
2460 int max_packet_size;
2486 http_log(
"Error writing frame to output for stream '%s': %s\n",
2575 int interleaved_index,
size;
2591 interleaved_index++;
2594 header[1] = interleaved_index;
2595 header[2] = len >> 8;
2662 http_log(
"Stream feed '%s' was not opened\n",
2669 http_log(
"Cannot write to read-only file '%s'\n",
2678 http_log(
"Could not open feed file '%s': %s\n",
2690 http_log(
"Error truncating feed file '%s': %s\n",
2697 http_log(
"Error reading write index from feed file '%s': %s\n",
2707 lseek(fd, 0, SEEK_SET);
2720 int len, loop_run = 0;
2733 }
else if (len == 0) {
2745 }
else if (++loop_run > 10)
2760 }
else if (len == 0)
2773 if (c->
buffer[0] !=
'f' ||
2775 http_log(
"Feed stream has become desynchronized -- disconnecting\n");
2791 http_log(
"Error writing to feed file: %s\n", strerror(errno));
2807 http_log(
"Error writing index to feed file: %s\n",
2813 for(c1 = first_http_ctx;
c1; c1 = c1->
next) {
2850 http_log(
"Feed '%s' stream number does not match registered feed\n",
2873 for(c1 = first_http_ctx;
c1; c1 = c1->
next) {
2893 str =
"Unknown Error";
2895 avio_printf(c->
pb,
"RTSP/1.0 %d %s\r\n", error_number, str);
2901 strftime(buf2,
sizeof(buf2),
"%a, %d %b %Y %H:%M:%S", tm);
2913 const char *p, *p1, *p2;
2926 get_word(protocol,
sizeof(protocol), &p);
2939 if (strcmp(protocol,
"RTSP/1.0")) {
2946 while (*p !=
'\n' && *p !=
'\0')
2950 while (*p !=
'\0') {
2951 p1 = memchr(p,
'\n', (
char *)c->
buffer_ptr - p);
2955 if (p2 > p && p2[-1] ==
'\r')
2961 if (len >
sizeof(line) - 1)
2962 len =
sizeof(line) - 1;
2963 memcpy(line, p, len);
2972 if (!strcmp(cmd,
"DESCRIBE"))
2974 else if (!strcmp(cmd,
"OPTIONS"))
2976 else if (!strcmp(cmd,
"SETUP"))
2978 else if (!strcmp(cmd,
"PLAY"))
2980 else if (!strcmp(cmd,
"PAUSE"))
2982 else if (!strcmp(cmd,
"TEARDOWN"))
3001 struct in_addr my_ip)
3011 if (!avc || !rtp_format)
3016 entry ? entry->
value :
"No Title", 0);
3031 #define PBUFFER_SIZE 2048
3042 return *pbuffer ? strlen(*pbuffer) :
AVERROR(ENOMEM);
3051 "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
3063 struct sockaddr_in my_addr;
3073 stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp") &&
3086 len =
sizeof(my_addr);
3087 getsockname(c->
fd, (
struct sockaddr *)&my_addr, &len);
3090 if (content_length < 0) {
3097 avio_printf(c->
pb,
"Content-Length: %d\r\n", content_length);
3107 if (session_id[0] ==
'\0')
3110 for(c = first_http_ctx;
c; c = c->
next) {
3134 int stream_index, rtp_port, rtcp_port;
3140 struct sockaddr_in dest_addr;
3152 strcmp(stream->
fmt->
name,
"rtp")) {
3156 if (!strcmp(path, stream->
filename)) {
3165 for(stream_index = 0; stream_index < stream->
nb_streams;
3167 snprintf(buf,
sizeof(buf),
"%s/streamid=%d",
3169 if (!strcmp(path, buf))
3180 unsigned random0 =
av_lfg_get(&random_state);
3181 unsigned random1 =
av_lfg_get(&random_state);
3215 if (rtp_c->
stream != stream) {
3221 if (rtp_c->
rtp_ctx[stream_index]) {
3235 setup.transport_option[0] =
'\0';
3255 "client_port=%d-%d;server_port=%d-%d",
3257 rtp_port, rtcp_port);
3260 avio_printf(c->
pb,
"Transport: RTP/AVP/TCP;interleaved=%d-%d",
3261 stream_index * 2, stream_index * 2 + 1);
3266 if (setup.transport_option[0] !=
'\0')
3280 const char *session_id)
3299 snprintf(buf,
sizeof(buf),
"%s/streamid=%d",
3301 if(!strncmp(path, buf,
sizeof(buf)))
3307 if (len > 0 && path[len - 1] ==
'/' &&
3375 const char *session_id,
3379 const char *proto_str;
3408 proto_str =
"MCAST";
3443 int stream_index,
struct sockaddr_in *dest_addr,
3451 int max_packet_size;
3476 ipaddr = inet_ntoa(dest_addr->sin_addr);
3490 "rtp://%s:%d?multicast=1&ttl=%d",
3491 ipaddr, ntohs(dest_addr->sin_port), ttl);
3494 "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
3511 http_log(
"%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
3512 ipaddr, ntohs(dest_addr->sin_port),
3651 if (stream->
fmt && !strcmp(stream->
fmt->
name,
"rtp"))
3655 http_log(
"Unspecified feed file for stream '%s'\n",
3660 http_log(
"Opening feed file '%s' for stream '%s'\n",
3675 http_log(
"Could not find codec parameters from '%s'\n",
3695 #define CHECK_CODEC(x) (ccf->codecpar->x != ccs->codecpar->x)
3697 http_log(
"Codecs do not match for stream %d\n", stream);
3700 http_log(
"Codec bitrates do not match for stream %d\n", stream);
3705 http_log(
"Codec width, height or framerate do not match for stream %d\n", stream);
3712 http_log(
"Codec sample_rate, channels, frame_size do not match for stream %d\n", stream);
3716 http_log(
"Unknown codec type for stream %d\n", stream);
3731 feed = stream->
feed;
3755 http_log(
"Deleting feed file '%s' as it appears "
3763 http_log(
"Failed to set buffer size\n");
3770 http_log(
"Deleting feed file '%s' as stream counts "
3771 "differ (%d != %d)\n",
3785 http_log(
"Index & Id do not match for stream %d (%s)\n",
3802 http_log(
"Unable to delete read-only feed file '%s'\n",
3814 http_log(
"Failed to allocate context\n");
3819 http_log(
"Unable to create feed file '%s' as it is "
3820 "marked readonly\n",
3828 http_log(
"Could not open output feed file '%s'\n",
3837 http_log(
"Failed to allocate stream\n");
3843 http_log(
"Container doesn't support the required parameters\n");
3861 http_log(
"Could not open output feed file '%s'\n",
3868 feed->
feed_size = lseek(fd, 0, SEEK_END);
3901 stream->
bandwidth = (bandwidth + 999) / 1000;
3911 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
3915 if (feed->
pid != pid)
3921 "%s: Pid %"PRId64
" exited with status %d after %"PRId64
" "
3923 feed->
filename, (int64_t) pid, status, (int64_t)uptime);
3942 printf(
"usage: ffserver [options]\n"
3943 "Hyper fast multi format Audio/Video streaming server\n");
3951 {
"d", 0, {(
void*)
opt_debug},
"enable debug mode" },
3952 {
"f",
HAS_ARG |
OPT_STRING, {(
void*)&config.
filename },
"use configfile instead of /etc/ffserver.conf",
"configfile" },
3958 struct sigaction sigact = { { 0 } };
3960 int ret = EXIT_FAILURE;
3976 unsetenv(
"http_proxy");
3981 sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
3982 sigaction(SIGCHLD, &sigact, 0);
3985 fprintf(stderr,
"Error reading configuration file '%s': %s\n",
4002 http_log(
"Could not setup feed streams\n");
4009 signal(SIGPIPE, SIG_IGN);
4012 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 init_dynload(void)
Initialize dynamic library loading.
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 copy(const float *p1, float *p2, const int length)
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)
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
uint8_t * packet_buffer_end
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 * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
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.
This struct describes the properties of an encoded stream.
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...
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)
AVRational sample_aspect_ratio
Opaque data information usually continuous.
static void opt_debug(void)
AVCodecParameters * codecpar
uint8_t * packet_buffer_ptr
AVCodecParameters * avcodec_parameters_alloc(void)
Allocate a new AVCodecParameters and set its fields to default values (unknown/invalid/0).
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)
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.
int avcodec_parameters_to_context(AVCodecContext *codec, const AVCodecParameters *par)
Fill the codec context based on the values from the supplied codec parameters.
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
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)
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)
void ff_rtsp_parse_line(AVFormatContext *s, RTSPMessageHeader *reply, const char *buf, RTSPState *rt, const char *method)
struct AVOutputFormat * oformat
The output container format.
int64_t bit_rate
The average bitrate of the encoded data (in bits per second).
#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)
static LayeredAVStream * add_av_stream1(FFServerStream *stream, AVCodecContext *codec, int copy)
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
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values. ...
enum AVMediaType codec_type
General type of the encoded data.
int flags
AV_CODEC_FLAG_*.
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)
void avcodec_parameters_free(AVCodecParameters **par)
Free an AVCodecParameters instance and everything associated with it and write NULL to the supplied p...
static void * av_mallocz_array(size_t nmemb, size_t size)
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.
static HTTPContext * first_http_ctx
static void clean_html(char *clean, int clean_len, char *dirty)
char * av_asprintf(const char *fmt,...)
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)
#define AV_CODEC_FLAG_BITEXACT
Use only bitexact stuff (except (I)DCT).
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.
attribute_deprecated int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src)
Copy the settings of the source AVCodecContext into the destination AVCodecContext.
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 int check_codec_match(LayeredAVStream *ccf, AVStream *ccs, int stream)
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.
char * av_strdup(const char *s)
Duplicate a string.
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
void avcodec_free_context(AVCodecContext **avctx)
Free the codec context and everything associated with it and write NULL to the provided pointer...
static void start_multicast(void)
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
int sample_rate
samples per second
AVIOContext * pb
I/O context.
main external API structure.
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
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.
static int http_server(void)
static const char * format
Describe the class of an AVClass context structure.
static void cp_html_entity(char *buffer, const char *entity)
int avcodec_parameters_from_context(AVCodecParameters *par, const AVCodecContext *codec)
Fill the parameters struct based on the values from the supplied codec context.
static void update_datarate(DataRateData *drd, int64_t count)
This holds the stream parameters for an AVStream, it cannot be a AVStream because AVStreams cannot be...
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
LayeredAVStream * streams[FFSERVER_MAX_STREAMS]
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)
static int add_av_stream(FFServerStream *feed, LayeredAVStream *st)
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]
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
int sample_rate
Audio only.
static int av_cmp_q(AVRational a, AVRational b)
Compare two rationals.
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
Utilties for rational number calculation.
int ffurl_open(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options)
static int find_stream_in_feed(FFServerStream *feed, AVCodecParameters *codec, int bit_rate)
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.
const char * av_dirname(char *path)
Thread safe dirname.
void ffserver_parse_acl_row(FFServerStream *stream, FFServerStream *feed, FFServerIPAddressACL *ext_acl, const char *p, const char *filename, int line_num)
AVFormatContext * pfmt_ctx
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.
char * recommended_encoder_configuration
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.
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...
int av_write_trailer(AVFormatContext *s)
Write the stream trailer to an output media file and free the file private data.
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)
uint32_t av_get_random_seed(void)
Get a seed to use in conjunction with random functions.
struct in_addr multicast_ip
AVCodecParameters * codecpar
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...
static void unlayer_stream(AVStream *st, LayeredAVStream *lst)
unsigned int nb_max_http_connections
static int build_feed_streams(void)
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)