#include "libavformat/rtpdec.h"
#include "libavformat/rtsp.h"
#include "libavutil/avstring.h"
-#include "libavutil/random.h"
+#include "libavutil/lfg.h"
+#include "libavutil/random_seed.h"
#include "libavutil/intreadwrite.h"
#include "libavcodec/opt.h"
#include <stdarg.h>
int feed_opened; /* true if someone is writing to the feed */
int is_feed; /* true if it is a feed */
int readonly; /* True if writing is prohibited to the file */
+ int truncate; /* True if feeder connection truncate the feed file */
int conns_served;
int64_t bytes_served;
int64_t feed_max_size; /* maximum storage size, zero means unlimited */
static int rtsp_parse_request(HTTPContext *c);
static void rtsp_cmd_describe(HTTPContext *c, const char *url);
static void rtsp_cmd_options(HTTPContext *c, const char *url);
-static void rtsp_cmd_setup(HTTPContext *c, const char *url, RTSPHeader *h);
-static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPHeader *h);
-static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPHeader *h);
-static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPHeader *h);
+static void rtsp_cmd_setup(HTTPContext *c, const char *url, RTSPMessageHeader *h);
+static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h);
+static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h);
+static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPMessageHeader *h);
/* SDP handling */
static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
static int64_t cur_time; // Making this global saves on passing it around everywhere
-static AVRandomState random_state;
+static AVLFG random_state;
static FILE *logfile = NULL;
{
static int print_prefix = 1;
AVClass *avc = ptr ? *(AVClass**)ptr : NULL;
- if (level > av_log_level)
+ if (level > av_log_get_level())
return;
if (print_prefix && avc)
http_log("[%s @ %p]", avc->item_name(ptr), ptr);
if (stream->is_multicast) {
/* open the RTP connection */
snprintf(session_id, sizeof(session_id), "%08x%08x",
- av_random(&random_state), av_random(&random_state));
+ av_lfg_get(&random_state), av_lfg_get(&random_state));
/* choose a port if none given */
if (stream->multicast_port == 0) {
}
}
+static void http_send_too_busy_reply(int fd)
+{
+ char buffer[300];
+ int len = snprintf(buffer, sizeof(buffer),
+ "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 number of current connections is %d, and this exceeds the limit of %d.</p>\r\n"
+ "</body></html>\r\n",
+ nb_connections, nb_max_connections);
+ send(fd, buffer, len, 0);
+}
+
+
static void new_connection(int server_fd, int is_rtsp)
{
struct sockaddr_in from_addr;
}
ff_socket_nonblock(fd, 1);
- /* XXX: should output a warning page when coming
- close to the connection limit */
- if (nb_connections >= nb_max_connections)
+ if (nb_connections >= nb_max_connections) {
+ http_send_too_busy_reply(fd);
goto fail;
+ }
/* add a new connection */
c = av_mallocz(sizeof(HTTPContext));
*pp = p;
}
+static void get_arg(char *buf, int buf_size, const char **pp)
+{
+ const char *p;
+ char *q;
+ int quote;
+
+ p = *pp;
+ while (isspace(*p)) p++;
+ q = buf;
+ quote = 0;
+ if (*p == '\"' || *p == '\'')
+ quote = *p++;
+ for(;;) {
+ if (quote) {
+ if (*p == quote)
+ break;
+ } else {
+ if (isspace(*p))
+ break;
+ }
+ if (*p == '\0')
+ break;
+ if ((q - buf) < buf_size - 1)
+ *q++ = *p;
+ p++;
+ }
+ *q = '\0';
+ if (quote && *p == quote)
+ p++;
+ *pp = p;
+}
+
static int validate_acl(FFStream *stream, HTTPContext *c)
{
enum IPAddressAction last_action = IP_DENY;
av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
if (ffserver_debug)
- http_log("New connection: %s %s\n", cmd, url);
+ http_log("%s - - New connection: %s %s\n", inet_ntoa(c->from_addr.sin_addr), cmd, url);
/* find the filename and the optional info string in the request */
p = strchr(url, '?');
}
if (stream == NULL) {
snprintf(msg, sizeof(msg), "File '%s' not found", url);
+ http_log("File '%s' not found\n", url);
goto send_error;
}
}
}
+ if (c->post == 0 && stream->stream_type == STREAM_TYPE_LIVE)
+ current_bandwidth += stream->bandwidth;
+
/* If already streaming this feed, do not let start another feeder. */
if (stream->feed_opened) {
snprintf(msg, sizeof(msg), "This feed is already being received.");
- http_log("feed %s already being received\n", stream->feed_filename);
+ http_log("Feed '%s' already being received\n", stream->feed_filename);
goto send_error;
}
- if (c->post == 0 && stream->stream_type == STREAM_TYPE_LIVE)
- current_bandwidth += stream->bandwidth;
-
if (c->post == 0 && max_bandwidth < current_bandwidth) {
c->http_error = 200;
q = c->buffer;
if (!strcmp(c->stream->fmt->name,"asf_stream")) {
/* Need to allocate a client id */
- c->wmp_client_id = av_random(&random_state) & 0x7fffffff;
+ c->wmp_client_id = av_lfg_get(&random_state);
q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Server: Cougar 4.1.0.3923\r\nCache-Control: no-cache\r\nPragma: client-id=%d\r\nPragma: features=\"broadcast\"\r\n", c->wmp_client_id);
}
"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);
+ "<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, "<HTML><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, "<H1>%s Status</H1>\n", program_name);
+ url_fprintf(pb, "</head>\n<body>");
+ url_fprintf(pb, "<h1>%s Status</h1>\n", program_name);
/* format status */
- url_fprintf(pb, "<H2>Available Streams</H2>\n");
- url_fprintf(pb, "<TABLE cellspacing=0 cellpadding=4>\n");
- url_fprintf(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");
+ url_fprintf(pb, "<h2>Available Streams</h2>\n");
+ url_fprintf(pb, "<table cellspacing=0 cellpadding=4>\n");
+ url_fprintf(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");
stream = first_stream;
while (stream != NULL) {
char sfilename[1024];
}
}
- url_fprintf(pb, "<TR><TD><A HREF=\"/%s\">%s</A> ",
+ url_fprintf(pb, "<tr><td><a href=\"/%s\">%s</a> ",
sfilename, stream->filename);
url_fprintf(pb, "<td align=right> %d <td align=right> ",
stream->conns_served);
abort();
}
}
- url_fprintf(pb, "<TD align=center> %s <TD align=right> %d <TD align=right> %d <TD> %s %s <TD align=right> %d <TD> %s %s",
+ url_fprintf(pb, "<td align=center> %s <td align=right> %d <td align=right> %d <td> %s %s <td align=right> %d <td> %s %s",
stream->fmt->name,
stream->bandwidth,
video_bit_rate / 1000, video_codec_name, video_codec_name_extra,
audio_bit_rate / 1000, audio_codec_name, audio_codec_name_extra);
if (stream->feed)
- url_fprintf(pb, "<TD>%s", stream->feed->filename);
+ url_fprintf(pb, "<td>%s", stream->feed->filename);
else
- url_fprintf(pb, "<TD>%s", stream->feed_filename);
+ url_fprintf(pb, "<td>%s", stream->feed_filename);
url_fprintf(pb, "\n");
}
break;
default:
- url_fprintf(pb, "<TD align=center> - <TD align=right> - <TD align=right> - <td><td align=right> - <TD>\n");
+ url_fprintf(pb, "<td align=center> - <td align=right> - <td align=right> - <td><td align=right> - <td>\n");
break;
}
}
stream = stream->next;
}
- url_fprintf(pb, "</TABLE>\n");
+ url_fprintf(pb, "</table>\n");
stream = first_stream;
while (stream != NULL) {
stream = stream->next;
}
-#if 0
- {
- float avg;
- AVCodecContext *enc;
- char buf[1024];
-
- /* feed status */
- stream = first_feed;
- while (stream != NULL) {
- url_fprintf(pb, "<H1>Feed '%s'</H1>\n", stream->filename);
- url_fprintf(pb, "<TABLE>\n");
- url_fprintf(pb, "<TR><TD>Parameters<TD>Frame count<TD>Size<TD>Avg bitrate (kbits/s)\n");
- for(i=0;i<stream->nb_streams;i++) {
- AVStream *st = stream->streams[i];
- FeedData *fdata = st->priv_data;
- enc = st->codec;
-
- avcodec_string(buf, sizeof(buf), enc);
- avg = fdata->avg_frame_size * (float)enc->rate * 8.0;
- if (enc->codec->type == CODEC_TYPE_AUDIO && enc->frame_size > 0)
- avg /= enc->frame_size;
- url_fprintf(pb, "<TR><TD>%s <TD> %d <TD> %"PRId64" <TD> %0.1f\n",
- buf, enc->frame_number, fdata->data_count, avg / 1000.0);
- }
- url_fprintf(pb, "</TABLE>\n");
- stream = stream->next_feed;
- }
- }
-#endif
-
/* connection status */
- url_fprintf(pb, "<H2>Connection Status</H2>\n");
+ url_fprintf(pb, "<h2>Connection Status</h2>\n");
- url_fprintf(pb, "Number of connections: %d / %d<BR>\n",
+ url_fprintf(pb, "Number of connections: %d / %d<br>\n",
nb_connections, nb_max_connections);
- url_fprintf(pb, "Bandwidth in use: %"PRIu64"k / %"PRIu64"k<BR>\n",
+ url_fprintf(pb, "Bandwidth in use: %"PRIu64"k / %"PRIu64"k<br>\n",
current_bandwidth, max_bandwidth);
- url_fprintf(pb, "<TABLE>\n");
- url_fprintf(pb, "<TR><th>#<th>File<th>IP<th>Proto<th>State<th>Target bits/sec<th>Actual bits/sec<th>Bytes transferred\n");
+ url_fprintf(pb, "<table>\n");
+ url_fprintf(pb, "<tr><th>#<th>File<th>IP<th>Proto<th>State<th>Target bits/sec<th>Actual bits/sec<th>Bytes transferred\n");
c1 = first_http_ctx;
i = 0;
while (c1 != NULL) {
i++;
p = inet_ntoa(c1->from_addr.sin_addr);
- url_fprintf(pb, "<TR><TD><B>%d</B><TD>%s%s<TD>%s<TD>%s<TD>%s<td align=right>",
+ url_fprintf(pb, "<tr><td><b>%d</b><td>%s%s<td>%s<td>%s<td>%s<td align=right>",
i,
c1->stream ? c1->stream->filename : "",
c1->state == HTTPSTATE_RECEIVE_DATA ? "(input)" : "",
url_fprintf(pb, "\n");
c1 = c1->next;
}
- url_fprintf(pb, "</TABLE>\n");
+ url_fprintf(pb, "</table>\n");
/* date */
ti = time(NULL);
p = ctime(&ti);
- url_fprintf(pb, "<HR size=1 noshade>Generated at %s", p);
- url_fprintf(pb, "</BODY>\n</HTML>\n");
+ url_fprintf(pb, "<hr size=1 noshade>Generated at %s", p);
+ url_fprintf(pb, "</body>\n</html>\n");
len = url_close_dyn_buf(pb, &c->pb_buffer);
c->buffer_ptr = c->pb_buffer;
if (input_filename[0] == '\0')
return -1;
-#if 0
- { time_t when = stream_pos / 1000000;
- http_log("Stream pos = %"PRId64", time=%s", stream_pos, ctime(&when));
- }
-#endif
-
/* open stream */
if ((ret = av_open_input_file(&s, input_filename, c->stream->ifmt,
buf_size, c->stream->ap_in)) < 0) {
}
s->flags |= AVFMT_FLAG_GENPTS;
c->fmt_in = s;
- av_find_stream_info(c->fmt_in);
+ if (strcmp(s->iformat->name, "ffm") && av_find_stream_info(c->fmt_in) < 0) {
+ http_log("Could not find stream info '%s'\n", input_filename);
+ av_close_input_file(s);
+ return -1;
+ }
/* open each parser */
for(i=0;i<s->nb_streams;i++)
switch(c->state) {
case HTTPSTATE_SEND_DATA_HEADER:
memset(&c->fmt_ctx, 0, sizeof(c->fmt_ctx));
- av_strlcpy(c->fmt_ctx.author, c->stream->author,
- sizeof(c->fmt_ctx.author));
- av_strlcpy(c->fmt_ctx.comment, c->stream->comment,
- sizeof(c->fmt_ctx.comment));
- av_strlcpy(c->fmt_ctx.copyright, c->stream->copyright,
- sizeof(c->fmt_ctx.copyright));
- av_strlcpy(c->fmt_ctx.title, c->stream->title,
- sizeof(c->fmt_ctx.title));
+ av_metadata_set(&c->fmt_ctx.metadata, "author" ,c->stream->author);
+ av_metadata_set(&c->fmt_ctx.metadata, "comment" ,c->stream->comment);
+ av_metadata_set(&c->fmt_ctx.metadata, "copyright",c->stream->copyright);
+ av_metadata_set(&c->fmt_ctx.metadata, "title" ,c->stream->title);
for(i=0;i<c->stream->nb_streams;i++) {
AVStream *st;
if (ist->start_time != AV_NOPTS_VALUE)
c->cur_pts -= av_rescale_q(ist->start_time, ist->time_base, AV_TIME_BASE_Q);
c->cur_frame_duration = av_rescale_q(pkt.duration, ist->time_base, AV_TIME_BASE_Q);
-#if 0
- printf("index=%d pts=%0.3f duration=%0.6f\n",
- pkt.stream_index,
- (double)c->cur_pts /
- AV_TIME_BASE,
- (double)c->cur_frame_duration /
- AV_TIME_BASE);
-#endif
/* find RTP context */
c->packet_stream_index = pkt.stream_index;
ctx = c->rtp_ctx[c->packet_stream_index];
}
c->feed_fd = fd;
- if ((c->stream->feed_write_index = ffm_read_write_index(fd)) < 0) {
- http_log("Error reading write index from feed file: %s\n", strerror(errno));
- return -1;
+ if (c->stream->truncate) {
+ /* truncate feed file */
+ ffm_write_write_index(c->feed_fd, FFM_PACKET_SIZE);
+ ftruncate(c->feed_fd, FFM_PACKET_SIZE);
+ http_log("Truncating feed file '%s'\n", c->stream->feed_filename);
+ } else {
+ if ((c->stream->feed_write_index = ffm_read_write_index(fd)) < 0) {
+ http_log("Error reading write index from feed file: %s\n", strerror(errno));
+ return -1;
+ }
}
+
+ c->stream->feed_write_index = FFMAX(ffm_read_write_index(fd), FFM_PACKET_SIZE);
c->stream->feed_size = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
if (s->nb_streams != feed->nb_streams) {
av_close_input_stream(s);
av_free(pb);
+ http_log("Feed '%s' stream number does not match registered feed\n",
+ c->stream->feed_filename);
goto fail;
}
char protocol[32];
char line[1024];
int len;
- RTSPHeader header1, *header = &header1;
+ RTSPMessageHeader header1, *header = &header1;
c->buffer_ptr[0] = '\0';
p = c->buffer;
if (avc == NULL) {
return -1;
}
- if (stream->title[0] != 0) {
- av_strlcpy(avc->title, stream->title, sizeof(avc->title));
- } else {
- av_strlcpy(avc->title, "No Title", sizeof(avc->title));
- }
+ av_metadata_set(&avc->metadata, "title",
+ stream->title[0] ? stream->title : "No Title");
avc->nb_streams = stream->nb_streams;
if (stream->is_multicast) {
snprintf(avc->filename, 1024, "rtp://%s:%d?multicast=1?ttl=%d",
return NULL;
}
-static RTSPTransportField *find_transport(RTSPHeader *h, enum RTSPLowerTransport lower_transport)
+static RTSPTransportField *find_transport(RTSPMessageHeader *h, enum RTSPLowerTransport lower_transport)
{
RTSPTransportField *th;
int i;
}
static void rtsp_cmd_setup(HTTPContext *c, const char *url,
- RTSPHeader *h)
+ RTSPMessageHeader *h)
{
FFStream *stream;
int stream_index, port;
/* generate session id if needed */
if (h->session_id[0] == '\0')
snprintf(h->session_id, sizeof(h->session_id), "%08x%08x",
- av_random(&random_state), av_random(&random_state));
+ av_lfg_get(&random_state), av_lfg_get(&random_state));
/* find rtp session, and create it if none found */
rtp_c = find_rtp_session(h->session_id);
return NULL;
}
-static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPHeader *h)
+static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h)
{
HTTPContext *rtp_c;
return;
}
-#if 0
- /* XXX: seek in stream */
- if (h->range_start != AV_NOPTS_VALUE) {
- printf("range_start=%0.3f\n", (double)h->range_start / AV_TIME_BASE);
- av_seek_frame(rtp_c->fmt_in, -1, h->range_start);
- }
-#endif
-
rtp_c->state = HTTPSTATE_SEND_DATA;
/* now everything is OK, so we can send the connection parameters */
url_fprintf(c->pb, "\r\n");
}
-static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPHeader *h)
+static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h)
{
HTTPContext *rtp_c;
url_fprintf(c->pb, "\r\n");
}
-static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPHeader *h)
+static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPMessageHeader *h)
{
HTTPContext *rtp_c;
char session_id[32];
stream->ap_in->mpeg2ts_compute_pcr = 1;
}
+ http_log("Opening file '%s'\n", stream->feed_filename);
if ((ret = av_open_input_file(&infile, stream->feed_filename,
stream->ifmt, 0, stream->ap_in)) < 0) {
- http_log("could not open %s: %d\n", stream->feed_filename, ret);
+ http_log("Could not open '%s': %d\n", stream->feed_filename, ret);
/* remove stream (no need to spend more time on it) */
fail:
remove_stream(stream);
exit(1);
}
- feed->feed_write_index = ffm_read_write_index(fd);
+ feed->feed_write_index = FFMAX(ffm_read_write_index(fd), FFM_PACKET_SIZE);
feed->feed_size = lseek(fd, 0, SEEK_END);
/* ensure that we do not wrap before the end of file */
if (feed->feed_max_size && feed->feed_max_size < feed->feed_size)
}
}
-static void get_arg(char *buf, int buf_size, const char **pp)
-{
- const char *p;
- char *q;
- int quote;
-
- p = *pp;
- while (isspace(*p)) p++;
- q = buf;
- quote = 0;
- if (*p == '\"' || *p == '\'')
- quote = *p++;
- for(;;) {
- if (quote) {
- if (*p == quote)
- break;
- } else {
- if (isspace(*p))
- break;
- }
- if (*p == '\0')
- break;
- if ((q - buf) < buf_size - 1)
- *q++ = *p;
- p++;
- }
- *q = '\0';
- if (quote && *p == quote)
- p++;
- *pp = p;
-}
-
/* add a codec and set the default parameters */
static void add_codec(FFStream *stream, AVCodecContext *av)
{
const char *p;
int val, errors, line_num;
FFStream **last_stream, *stream, *redirect;
- FFStream **last_feed, *feed;
+ FFStream **last_feed, *feed, *s;
AVCodecContext audio_enc, video_enc;
enum CodecID audio_id, video_id;
filename, line_num);
} else {
feed = av_mallocz(sizeof(FFStream));
- /* add in stream list */
- *last_stream = feed;
- last_stream = &feed->next;
- /* add in feed list */
- *last_feed = feed;
- last_feed = &feed->next_feed;
-
get_arg(feed->filename, sizeof(feed->filename), &p);
q = strrchr(feed->filename, '>');
if (*q)
*q = '\0';
+
+ for (s = first_feed; s; s = s->next) {
+ if (!strcmp(feed->filename, s->filename)) {
+ fprintf(stderr, "%s:%d: Feed '%s' already registered\n",
+ filename, line_num, s->filename);
+ errors++;
+ }
+ }
+
feed->fmt = guess_format("ffm", NULL, NULL);
/* defaut feed file */
snprintf(feed->feed_filename, sizeof(feed->feed_filename),
feed->feed_max_size = 5 * 1024 * 1024;
feed->is_feed = 1;
feed->feed = feed; /* self feeding :-) */
+
+ /* add in stream list */
+ *last_stream = feed;
+ last_stream = &feed->next;
+ /* add in feed list */
+ *last_feed = feed;
+ last_feed = &feed->next_feed;
}
} else if (!strcasecmp(cmd, "Launch")) {
if (feed) {
get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
} else if (stream)
get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
+ } else if (!strcasecmp(cmd, "Truncate")) {
+ if (feed) {
+ get_arg(arg, sizeof(arg), &p);
+ feed->truncate = strtod(arg, NULL);
+ }
} else if (!strcasecmp(cmd, "FileMaxSize")) {
if (feed) {
char *p1;
break;
}
feed->feed_max_size = (int64_t)fsize;
+ if (feed->feed_max_size < FFM_PACKET_SIZE*4) {
+ fprintf(stderr, "%s:%d: Feed max file size is too small, "
+ "must be at least %d\n", filename, line_num, FFM_PACKET_SIZE*4);
+ errors++;
+ }
}
} else if (!strcasecmp(cmd, "</Feed>")) {
if (!feed) {
fprintf(stderr, "%s:%d: Already in a tag\n",
filename, line_num);
} else {
+ FFStream *s;
const AVClass *class;
stream = av_mallocz(sizeof(FFStream));
- *last_stream = stream;
- last_stream = &stream->next;
-
get_arg(stream->filename, sizeof(stream->filename), &p);
q = strrchr(stream->filename, '>');
if (*q)
*q = '\0';
+
+ for (s = first_stream; s; s = s->next) {
+ if (!strcmp(stream->filename, s->filename)) {
+ fprintf(stderr, "%s:%d: Stream '%s' already registered\n",
+ filename, line_num, s->filename);
+ errors++;
+ }
+ }
+
stream->fmt = guess_stream_format(NULL, stream->filename, NULL);
/* fetch avclass so AVOption works
* FIXME try to use avcodec_get_context_defaults2
audio_id = stream->fmt->audio_codec;
video_id = stream->fmt->video_codec;
}
+
+ *last_stream = stream;
+ last_stream = &stream->next;
}
} else if (!strcasecmp(cmd, "Feed")) {
get_arg(arg, sizeof(arg), &p);
} else {
fprintf(stderr, "%s:%d: Incorrect keyword: '%s'\n",
filename, line_num, cmd);
- errors++;
}
}
{ "h", OPT_EXIT, {(void*)opt_show_help}, "show help" },
{ "version", OPT_EXIT, {(void*)show_version}, "show version" },
{ "L", OPT_EXIT, {(void*)show_license}, "show license" },
- { "formats", OPT_EXIT, {(void*)show_formats}, "show available formats, codecs, protocols, ..." },
+ { "formats" , OPT_EXIT, {(void*)show_formats }, "show available formats" },
+ { "codecs" , OPT_EXIT, {(void*)show_codecs }, "show available codecs" },
+ { "bsfs" , OPT_EXIT, {(void*)show_bsfs }, "show available bit stream filters" },
+ { "protocols", OPT_EXIT, {(void*)show_protocols}, "show available protocols" },
+ { "loglevel", HAS_ARG | OPT_FUNC2, {(void*)opt_loglevel}, "set libav* logging level", "loglevel" },
{ "n", OPT_BOOL, {(void *)&no_launch }, "enable no-launch mode" },
{ "d", 0, {(void*)opt_debug}, "enable debug mode" },
{ "f", HAS_ARG | OPT_STRING, {(void*)&config_filename }, "use configfile instead of /etc/ffserver.conf", "configfile" },
unsetenv("http_proxy"); /* Kill the http_proxy */
- av_random_init(&random_state, av_gettime() + (getpid() << 16));
+ av_lfg_init(&random_state, ff_random_get_seed());
memset(&sigact, 0, sizeof(sigact));
sigact.sa_handler = handle_child_exit;