int seq; /* RTSP sequence number */
/* RTP state specific */
- enum RTSPProtocol rtp_protocol;
+ enum RTSPLowerTransport rtp_protocol;
char session_id[32]; /* session id */
AVFormatContext *rtp_ctx[MAX_STREAMS];
/* RTP handling */
static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
FFStream *stream, const char *session_id,
- enum RTSPProtocol rtp_protocol);
+ enum RTSPLowerTransport rtp_protocol);
static int rtp_new_av_stream(HTTPContext *c,
int stream_index, struct sockaddr_in *dest_addr,
HTTPContext *rtsp_c);
/* maximum number of simultaneous HTTP connections */
static unsigned int nb_max_http_connections = 2000;
-static int nb_max_connections = 5;
-static int nb_connections;
+static unsigned int nb_max_connections = 5;
+static unsigned int nb_connections;
static uint64_t max_bandwidth = 1000;
static uint64_t current_bandwidth;
dest_addr.sin_port = htons(stream->multicast_port);
rtp_c = rtp_new_connection(&dest_addr, stream, session_id,
- RTSP_PROTOCOL_RTP_UDP_MULTICAST);
+ RTSP_LOWER_TRANSPORT_UDP_MULTICAST);
if (!rtp_c)
continue;
struct pollfd *poll_table, *poll_entry;
HTTPContext *c, *c_next;
- if(!(poll_table = av_mallocz(nb_max_http_connections + 2))) {
+ if(!(poll_table = av_mallocz((nb_max_http_connections + 2)*sizeof(*poll_table)))) {
http_log("Impossible to allocate a poll table handling %d connections.\n", nb_max_http_connections);
return -1;
}
return -1;
}
- http_log("ffserver started.\n");
+ http_log("FFserver started.\n");
start_children(first_feed);
ctx = &c->fmt_ctx;
- if (!c->last_packet_sent) {
+ if (!c->last_packet_sent && c->state == HTTPSTATE_SEND_DATA_TRAILER) {
if (ctx->oformat) {
/* prepare header */
if (url_open_dyn_buf(&ctx->pb) >= 0) {
if (stream->stream_type == STREAM_TYPE_REDIRECT) {
c->http_error = 301;
q = c->buffer;
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 301 Moved\r\n");
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Location: %s\r\n", stream->feed_filename);
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: text/html\r\n");
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<html><head><title>Moved</title></head><body>\r\n");
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "You should be <a href=\"%s\">redirected</a>.\r\n", stream->feed_filename);
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "</body></html>\r\n");
-
+ q += snprintf(q, c->buffer_size,
+ "HTTP/1.0 301 Moved\r\n"
+ "Location: %s\r\n"
+ "Content-type: text/html\r\n"
+ "\r\n"
+ "<html><head><title>Moved</title></head><body>\r\n"
+ "You should be <a href=\"%s\">redirected</a>.\r\n"
+ "</body></html>\r\n", stream->feed_filename, stream->feed_filename);
/* prepare output buffer */
c->buffer_ptr = c->buffer;
c->buffer_end = q;
/* If this is WMP, get the rate information */
if (extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
if (modify_current_stream(c, ratebuf)) {
- for (i = 0; i < sizeof(c->feed_streams) / sizeof(c->feed_streams[0]); i++) {
+ for (i = 0; i < FF_ARRAY_ELEMS(c->feed_streams); i++) {
if (c->switch_feed_streams[i] >= 0)
do_switch_stream(c, i);
}
if (c->post == 0 && max_bandwidth < current_bandwidth) {
c->http_error = 200;
q = c->buffer;
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 Server too busy\r\n");
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: text/html\r\n");
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<html><head><title>Too busy</title></head><body>\r\n");
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<p>The server is too busy to serve your request at this time.</p>\r\n");
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<p>The bandwidth being served (including your stream) is %lldkbit/sec, and this exceeds the limit of %lldkbit/sec.</p>\r\n",
- current_bandwidth, max_bandwidth);
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "</body></html>\r\n");
-
+ q += snprintf(q, c->buffer_size,
+ "HTTP/1.0 200 Server too busy\r\n"
+ "Content-type: text/html\r\n"
+ "\r\n"
+ "<html><head><title>Too busy</title></head><body>\r\n"
+ "<p>The server is too busy to serve your request at this time.</p>\r\n"
+ "<p>The bandwidth being served (including your stream) is %"PRIu64"kbit/sec, "
+ "and this exceeds the limit of %"PRIu64"kbit/sec.</p>\r\n"
+ "</body></html>\r\n", current_bandwidth, max_bandwidth);
/* prepare output buffer */
c->buffer_ptr = c->buffer;
c->buffer_end = q;
q = c->buffer;
switch(redir_type) {
case REDIR_ASX:
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 ASX Follows\r\n");
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: video/x-ms-asf\r\n");
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<ASX Version=\"3\">\r\n");
- //q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<!-- Autogenerated by ffserver -->\r\n");
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n",
- hostbuf, filename, info);
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "</ASX>\r\n");
+ q += snprintf(q, c->buffer_size,
+ "HTTP/1.0 200 ASX Follows\r\n"
+ "Content-type: video/x-ms-asf\r\n"
+ "\r\n"
+ "<ASX Version=\"3\">\r\n"
+ //"<!-- Autogenerated by ffserver -->\r\n"
+ "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n"
+ "</ASX>\r\n", hostbuf, filename, info);
break;
case REDIR_RAM:
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 RAM Follows\r\n");
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: audio/x-pn-realaudio\r\n");
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "# Autogenerated by ffserver\r\n");
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "http://%s/%s%s\r\n",
- hostbuf, filename, info);
+ q += snprintf(q, c->buffer_size,
+ "HTTP/1.0 200 RAM Follows\r\n"
+ "Content-type: audio/x-pn-realaudio\r\n"
+ "\r\n"
+ "# Autogenerated by ffserver\r\n"
+ "http://%s/%s%s\r\n", hostbuf, filename, info);
break;
case REDIR_ASF:
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 ASF Redirect follows\r\n");
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: video/x-ms-asf\r\n");
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "[Reference]\r\n");
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Ref1=http://%s/%s%s\r\n",
- hostbuf, filename, info);
+ q += snprintf(q, c->buffer_size,
+ "HTTP/1.0 200 ASF Redirect follows\r\n"
+ "Content-type: video/x-ms-asf\r\n"
+ "\r\n"
+ "[Reference]\r\n"
+ "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info);
break;
case REDIR_RTSP:
{
p = strrchr(hostname, ':');
if (p)
*p = '\0';
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 RTSP Redirect follows\r\n");
- /* XXX: incorrect mime type ? */
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: application/x-rtsp\r\n");
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "rtsp://%s:%d/%s\r\n",
- hostname, ntohs(my_rtsp_addr.sin_port),
- filename);
+ q += snprintf(q, c->buffer_size,
+ "HTTP/1.0 200 RTSP Redirect follows\r\n"
+ /* XXX: incorrect mime type ? */
+ "Content-type: application/x-rtsp\r\n"
+ "\r\n"
+ "rtsp://%s:%d/%s\r\n", hostname, ntohs(my_rtsp_addr.sin_port), filename);
}
break;
case REDIR_SDP:
int sdp_data_size, len;
struct sockaddr_in my_addr;
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 OK\r\n");
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: application/sdp\r\n");
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
+ q += snprintf(q, c->buffer_size,
+ "HTTP/1.0 200 OK\r\n"
+ "Content-type: application/sdp\r\n"
+ "\r\n");
len = sizeof(my_addr);
getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
send_error:
c->http_error = 404;
q = c->buffer;
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 404 Not Found\r\n");
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: %s\r\n", "text/html");
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<HTML>\n");
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<HEAD><TITLE>404 Not Found</TITLE></HEAD>\n");
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<BODY>%s</BODY>\n", msg);
- q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "</HTML>\n");
-
+ q += snprintf(q, c->buffer_size,
+ "HTTP/1.0 404 Not Found\r\n"
+ "Content-type: text/html\r\n"
+ "\r\n"
+ "<HTML>\n"
+ "<HEAD><TITLE>404 Not Found</TITLE></HEAD>\n"
+ "<BODY>%s</BODY>\n"
+ "</HTML>\n", msg);
/* prepare output buffer */
c->buffer_ptr = c->buffer;
c->buffer_end = q;
url_fprintf(pb, "Pragma: no-cache\r\n");
url_fprintf(pb, "\r\n");
- url_fprintf(pb, "<HEAD><TITLE>%s Status</TITLE>\n", program_name);
+ url_fprintf(pb, "<HTML><HEAD><TITLE>%s Status</TITLE>\n", program_name);
if (c->stream->feed_filename[0])
url_fprintf(pb, "<link rel=\"shortcut icon\" href=\"%s\">\n", c->stream->feed_filename);
url_fprintf(pb, "</HEAD>\n<BODY>");
url_fprintf(pb, "Number of connections: %d / %d<BR>\n",
nb_connections, nb_max_connections);
- url_fprintf(pb, "Bandwidth in use: %lldk / %lldk<BR>\n",
+ url_fprintf(pb, "Bandwidth in use: %"PRIu64"k / %"PRIu64"k<BR>\n",
current_bandwidth, max_bandwidth);
url_fprintf(pb, "<TABLE>\n");
if (c->is_packetized) {
int max_packet_size;
- if (c->rtp_protocol == RTSP_PROTOCOL_RTP_TCP)
+ if (c->rtp_protocol == RTSP_LOWER_TRANSPORT_TCP)
max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
else
max_packet_size = url_get_max_packet_size(c->rtp_handles[c->packet_stream_index]);
if (c->stream)
c->stream->bytes_served += len;
- if (c->rtp_protocol == RTSP_PROTOCOL_RTP_TCP) {
+ if (c->rtp_protocol == RTSP_LOWER_TRANSPORT_TCP) {
/* RTP packets are sent inside the RTSP TCP connection */
ByteIOContext *pb;
int interleaved_index, size;
return NULL;
}
-static RTSPTransportField *find_transport(RTSPHeader *h, enum RTSPProtocol protocol)
+static RTSPTransportField *find_transport(RTSPHeader *h, enum RTSPLowerTransport lower_transport)
{
RTSPTransportField *th;
int i;
for(i=0;i<h->nb_transports;i++) {
th = &h->transports[i];
- if (th->protocol == protocol)
+ if (th->lower_transport == lower_transport)
return th;
}
return NULL;
rtp_c = find_rtp_session(h->session_id);
if (!rtp_c) {
/* always prefer UDP */
- th = find_transport(h, RTSP_PROTOCOL_RTP_UDP);
+ th = find_transport(h, RTSP_LOWER_TRANSPORT_UDP);
if (!th) {
- th = find_transport(h, RTSP_PROTOCOL_RTP_TCP);
+ th = find_transport(h, RTSP_LOWER_TRANSPORT_TCP);
if (!th) {
rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
return;
}
rtp_c = rtp_new_connection(&c->from_addr, stream, h->session_id,
- th->protocol);
+ th->lower_transport);
if (!rtp_c) {
rtsp_reply_error(c, RTSP_STATUS_BANDWIDTH);
return;
/* check transport */
th = find_transport(h, rtp_c->rtp_protocol);
- if (!th || (th->protocol == RTSP_PROTOCOL_RTP_UDP &&
+ if (!th || (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
th->client_port_min <= 0)) {
rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
return;
url_fprintf(c->pb, "Session: %s\r\n", rtp_c->session_id);
switch(rtp_c->rtp_protocol) {
- case RTSP_PROTOCOL_RTP_UDP:
+ case RTSP_LOWER_TRANSPORT_UDP:
port = rtp_get_local_port(rtp_c->rtp_handles[stream_index]);
url_fprintf(c->pb, "Transport: RTP/AVP/UDP;unicast;"
"client_port=%d-%d;server_port=%d-%d",
th->client_port_min, th->client_port_min + 1,
port, port + 1);
break;
- case RTSP_PROTOCOL_RTP_TCP:
+ case RTSP_LOWER_TRANSPORT_TCP:
url_fprintf(c->pb, "Transport: RTP/AVP/TCP;interleaved=%d-%d",
stream_index * 2, stream_index * 2 + 1);
break;
static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
FFStream *stream, const char *session_id,
- enum RTSPProtocol rtp_protocol)
+ enum RTSPLowerTransport rtp_protocol)
{
HTTPContext *c = NULL;
const char *proto_str;
/* protocol is shown in statistics */
switch(c->rtp_protocol) {
- case RTSP_PROTOCOL_RTP_UDP_MULTICAST:
+ case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
proto_str = "MCAST";
break;
- case RTSP_PROTOCOL_RTP_UDP:
+ case RTSP_LOWER_TRANSPORT_UDP:
proto_str = "UDP";
break;
- case RTSP_PROTOCOL_RTP_TCP:
+ case RTSP_LOWER_TRANSPORT_TCP:
proto_str = "TCP";
break;
default:
ipaddr = inet_ntoa(dest_addr->sin_addr);
switch(c->rtp_protocol) {
- case RTSP_PROTOCOL_RTP_UDP:
- case RTSP_PROTOCOL_RTP_UDP_MULTICAST:
+ case RTSP_LOWER_TRANSPORT_UDP:
+ case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
/* RTP/UDP case */
/* XXX: also pass as parameter to function ? */
c->rtp_handles[stream_index] = h;
max_packet_size = url_get_max_packet_size(h);
break;
- case RTSP_PROTOCOL_RTP_TCP:
+ case RTSP_LOWER_TRANSPORT_TCP:
/* RTP/TCP case */
c->rtsp_c = rtsp_c;
max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
}
#endif
-static int opt_default(const char *opt, const char *arg,
+static int ffserver_opt_default(const char *opt, const char *arg,
AVCodecContext *avctx, int type)
{
- const AVOption *o = NULL;
- const AVOption *o2 = av_find_opt(avctx, opt, NULL, type, type);
- if(o2)
- o = av_set_string2(avctx, opt, arg, 1);
- if(!o)
- return -1;
- return 0;
+ int ret = 0;
+ const AVOption *o = av_find_opt(avctx, opt, NULL, type, type);
+ if(o)
+ ret = av_set_string3(avctx, opt, arg, 1, NULL);
+ return ret;
}
static int parse_ffconfig(const char *filename)
}
} else if (!strcasecmp(cmd, "InputFormat")) {
get_arg(arg, sizeof(arg), &p);
- stream->ifmt = av_find_input_format(arg);
- if (!stream->ifmt) {
- fprintf(stderr, "%s:%d: Unknown input format: %s\n",
- filename, line_num, arg);
+ if (stream) {
+ stream->ifmt = av_find_input_format(arg);
+ if (!stream->ifmt) {
+ fprintf(stderr, "%s:%d: Unknown input format: %s\n",
+ filename, line_num, arg);
+ }
}
} else if (!strcasecmp(cmd, "FaviconURL")) {
if (stream && stream->stream_type == STREAM_TYPE_STATUS) {
avctx = &audio_enc;
type = AV_OPT_FLAG_AUDIO_PARAM;
}
- if (opt_default(arg, arg2, avctx, type|AV_OPT_FLAG_ENCODING_PARAM)) {
+ if (ffserver_opt_default(arg, arg2, avctx, type|AV_OPT_FLAG_ENCODING_PARAM)) {
fprintf(stderr, "AVOption error: %s %s\n", arg, arg2);
errors++;
}