]> git.sesse.net Git - ffmpeg/blobdiff - ffserver.c
remove useless init, logfilename is static
[ffmpeg] / ffserver.c
index acce0b34075f2762eb74cf4c13d6439fee9fde21..d636d3c1f7b8cf213bca8549c9bf36400d015f55 100644 (file)
@@ -32,7 +32,7 @@
 #include "libavformat/os_support.h"
 #include "libavformat/rtp.h"
 #include "libavformat/rtsp.h"
-
+#include "libavcodec/opt.h"
 #include <stdarg.h>
 #include <unistd.h>
 #include <fcntl.h>
@@ -77,7 +77,7 @@ enum HTTPState {
     RTSPSTATE_SEND_PACKET,
 };
 
-const char *http_state[] = {
+static const char *http_state[] = {
     "HTTP_WAIT_REQUEST",
     "HTTP_SEND_HEADER",
 
@@ -257,7 +257,7 @@ static void close_connection(HTTPContext *c);
 static int handle_connection(HTTPContext *c);
 static int http_parse_request(HTTPContext *c);
 static int http_send_data(HTTPContext *c);
-static void compute_stats(HTTPContext *c);
+static void compute_status(HTTPContext *c);
 static int open_input_stream(HTTPContext *c, const char *info);
 static int http_start_receive_data(HTTPContext *c);
 static int http_receive_data(HTTPContext *c);
@@ -295,8 +295,8 @@ static int need_to_start_children;
 static int nb_max_connections;
 static int nb_connections;
 
-static int max_bandwidth;
-static int current_bandwidth;
+static uint64_t max_bandwidth;
+static uint64_t current_bandwidth;
 
 static int64_t cur_time;           // Making this global saves on passing it around everywhere
 
@@ -378,7 +378,7 @@ static void start_children(FFStream *feed)
             feed->pid = fork();
 
             if (feed->pid < 0) {
-                fprintf(stderr, "Unable to create children\n");
+                http_log("Unable to create children\n");
                 exit(1);
             }
             if (!feed->pid) {
@@ -486,8 +486,8 @@ static void start_multicast(void)
                 continue;
 
             if (open_input_stream(rtp_c, "") < 0) {
-                fprintf(stderr, "Could not open input stream for stream '%s'\n",
-                        stream->filename);
+                http_log("Could not open input stream for stream '%s'\n",
+                         stream->filename);
                 continue;
             }
 
@@ -497,8 +497,8 @@ static void start_multicast(void)
                 dest_addr.sin_port = htons(stream->multicast_port +
                                            2 * stream_index);
                 if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, NULL) < 0) {
-                    fprintf(stderr, "Could not open output stream '%s/streamid=%d'\n",
-                            stream->filename, stream_index);
+                    http_log("Could not open output stream '%s/streamid=%d'\n",
+                             stream->filename, stream_index);
                     exit(1);
                 }
             }
@@ -654,8 +654,10 @@ static void new_connection(int server_fd, int is_rtsp)
     len = sizeof(from_addr);
     fd = accept(server_fd, (struct sockaddr *)&from_addr,
                 &len);
-    if (fd < 0)
+    if (fd < 0) {
+        http_log("error during accept %s\n", strerror(errno));
         return;
+    }
     ff_socket_nonblock(fd, 1);
 
     /* XXX: should output a warning page when coming
@@ -1315,7 +1317,7 @@ static int http_parse_request(HTTPContext *c)
         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 %dkbit/sec, and this exceeds the limit of %dkbit/sec.</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");
 
@@ -1522,7 +1524,7 @@ static int http_parse_request(HTTPContext *c)
 #endif
 
     if (c->stream->stream_type == STREAM_TYPE_STATUS)
-        goto send_stats;
+        goto send_status;
 
     /* open input stream */
     if (open_input_stream(c, info) < 0) {
@@ -1571,8 +1573,8 @@ static int http_parse_request(HTTPContext *c)
     c->buffer_end = q;
     c->state = HTTPSTATE_SEND_HEADER;
     return 0;
- send_stats:
-    compute_stats(c);
+ send_status:
+    compute_status(c);
     c->http_error = 200; /* horrible : we use this value to avoid
                             going to the send data state */
     c->state = HTTPSTATE_SEND_HEADER;
@@ -1589,7 +1591,7 @@ static void fmt_bytecount(ByteIOContext *pb, int64_t count)
     url_fprintf(pb, "%"PRId64"%c", count, *s);
 }
 
-static void compute_stats(HTTPContext *c)
+static void compute_status(HTTPContext *c)
 {
     HTTPContext *c1;
     FFStream *stream;
@@ -1610,11 +1612,11 @@ static void compute_stats(HTTPContext *c)
     url_fprintf(pb, "Pragma: no-cache\r\n");
     url_fprintf(pb, "\r\n");
 
-    url_fprintf(pb, "<HEAD><TITLE>FFServer Status</TITLE>\n");
+    url_fprintf(pb, "<HEAD><TITLE>%s Status</TITLE>\n", program_name);
     if (c->stream->feed_filename)
         url_fprintf(pb, "<link rel=\"shortcut icon\" href=\"%s\">\n", c->stream->feed_filename);
     url_fprintf(pb, "</HEAD>\n<BODY>");
-    url_fprintf(pb, "<H1>FFServer Status</H1>\n");
+    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");
@@ -1811,7 +1813,7 @@ static void compute_stats(HTTPContext *c)
     url_fprintf(pb, "Number of connections: %d / %d<BR>\n",
                  nb_connections, nb_max_connections);
 
-    url_fprintf(pb, "Bandwidth in use: %dk / %dk<BR>\n",
+    url_fprintf(pb, "Bandwidth in use: %lldk / %lldk<BR>\n",
                  current_bandwidth, max_bandwidth);
 
     url_fprintf(pb, "<TABLE>\n");
@@ -2099,18 +2101,13 @@ static int http_prepare_data(HTTPContext *c)
                     }
                     for(i=0;i<c->stream->nb_streams;i++) {
                         if (c->feed_streams[i] == pkt.stream_index) {
+                            AVStream *st = c->fmt_in->streams[source_index];
                             pkt.stream_index = i;
-                            if (pkt.flags & PKT_FLAG_KEY)
-                                c->got_key_frame |= 1 << i;
-                            /* See if we have all the key frames, then
-                             * we start to send. This logic is not quite
-                             * right, but it works for the case of a
-                             * single video stream with one or more
-                             * audio streams (for which every frame is
-                             * typically a key frame).
-                             */
-                            if (!c->stream->send_on_key ||
-                                ((c->got_key_frame + 1) >> c->stream->nb_streams))
+                            if (pkt.flags & PKT_FLAG_KEY &&
+                                (st->codec->codec_type == CODEC_TYPE_VIDEO ||
+                                 c->stream->nb_streams == 1))
+                                c->got_key_frame = 1;
+                            if (!c->stream->send_on_key || c->got_key_frame)
                                 goto send_it;
                         }
                     }
@@ -2176,8 +2173,13 @@ static int http_prepare_data(HTTPContext *c)
                         pkt.pts = av_rescale_q(pkt.pts,
                                                c->fmt_in->streams[source_index]->time_base,
                                                ctx->streams[pkt.stream_index]->time_base);
-                    if (av_write_frame(ctx, &pkt))
+                    pkt.duration = av_rescale_q(pkt.duration,
+                                                c->fmt_in->streams[source_index]->time_base,
+                                                ctx->streams[pkt.stream_index]->time_base);
+                    if (av_write_frame(ctx, &pkt) < 0) {
+                        http_log("Error writing frame to output\n");
                         c->state = HTTPSTATE_SEND_DATA_TRAILER;
+                    }
 
                     len = url_close_dyn_buf(ctx->pb, &c->pb_buffer);
                     c->cur_frame_bytes = len;
@@ -3333,7 +3335,7 @@ static void build_file_streams(void)
                 /* find all the AVStreams inside and reference them in
                    'stream' */
                 if (av_find_stream_info(infile) < 0) {
-                    http_log("Could not find codec parameters from '%s'",
+                    http_log("Could not find codec parameters from '%s'\n",
                              stream->feed_filename);
                     av_close_input_file(infile);
                     goto fail;
@@ -3466,8 +3468,8 @@ static void build_feed_streams(void)
 
             /* only write the header of the ffm file */
             if (url_fopen(&s->pb, feed->feed_filename, URL_WRONLY) < 0) {
-                fprintf(stderr, "Could not open output feed file '%s'\n",
-                        feed->feed_filename);
+                http_log("Could not open output feed file '%s'\n",
+                         feed->feed_filename);
                 exit(1);
             }
             s->oformat = feed->fmt;
@@ -3479,7 +3481,7 @@ static void build_feed_streams(void)
             }
             av_set_parameters(s, NULL);
             if (av_write_header(s) < 0) {
-                fprintf(stderr, "Container doesn't supports the required parameters\n");
+                http_log("Container doesn't supports the required parameters\n");
                 exit(1);
             }
             /* XXX: need better api */
@@ -3489,7 +3491,7 @@ static void build_feed_streams(void)
         /* get feed size and write index */
         fd = open(feed->feed_filename, O_RDONLY);
         if (fd < 0) {
-            fprintf(stderr, "Could not open output feed file '%s'\n",
+            http_log("Could not open output feed file '%s'\n",
                     feed->feed_filename);
             exit(1);
         }
@@ -3680,6 +3682,18 @@ static void load_module(const char *filename)
 }
 #endif
 
+static int 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_string(avctx, opt, arg);
+    if(!o)
+        return -1;
+    return 0;
+}
+
 static int parse_ffconfig(const char *filename)
 {
     FILE *f;
@@ -3767,16 +3781,18 @@ static int parse_ffconfig(const char *filename)
                 nb_max_connections = val;
             }
         } else if (!strcasecmp(cmd, "MaxBandwidth")) {
+            int64_t llval;
             get_arg(arg, sizeof(arg), &p);
-            val = atoi(arg);
-            if (val < 10 || val > 100000) {
+            llval = atoll(arg);
+            if (llval < 10 || llval > 10000000) {
                 fprintf(stderr, "%s:%d: Invalid MaxBandwidth: %s\n",
                         filename, line_num, arg);
                 errors++;
             } else
-                max_bandwidth = val;
+                max_bandwidth = llval;
         } else if (!strcasecmp(cmd, "CustomLog")) {
-            get_arg(logfilename, sizeof(logfilename), &p);
+            if (!ffserver_debug)
+                get_arg(logfilename, sizeof(logfilename), &p);
         } else if (!strcasecmp(cmd, "<Feed")) {
             /*********************************************/
             /* Feed related options */
@@ -3884,6 +3900,7 @@ static int parse_ffconfig(const char *filename)
                 fprintf(stderr, "%s:%d: Already in a tag\n",
                         filename, line_num);
             } else {
+                const AVClass *class;
                 stream = av_mallocz(sizeof(FFStream));
                 *last_stream = stream;
                 last_stream = &stream->next;
@@ -3893,8 +3910,15 @@ static int parse_ffconfig(const char *filename)
                 if (*q)
                     *q = '\0';
                 stream->fmt = guess_stream_format(NULL, stream->filename, NULL);
+                /* fetch avclass so AVOption works
+                 * FIXME try to use avcodec_get_context_defaults2
+                 * without changing defaults too much */
+                avcodec_get_context_defaults(&video_enc);
+                class = video_enc.av_class;
                 memset(&audio_enc, 0, sizeof(AVCodecContext));
                 memset(&video_enc, 0, sizeof(AVCodecContext));
+                audio_enc.av_class = class;
+                video_enc.av_class = class;
                 audio_id = CODEC_ID_NONE;
                 video_id = CODEC_ID_NONE;
                 if (stream->fmt) {
@@ -4091,6 +4115,24 @@ static int parse_ffconfig(const char *filename)
                 video_enc.mb_decision = FF_MB_DECISION_BITS; //FIXME remove
                 video_enc.flags |= CODEC_FLAG_4MV;
             }
+        } else if (!strcasecmp(cmd, "AVOptionVideo") ||
+                   !strcasecmp(cmd, "AVOptionAudio")) {
+            char arg2[1024];
+            AVCodecContext *avctx;
+            int type;
+            get_arg(arg, sizeof(arg), &p);
+            get_arg(arg2, sizeof(arg2), &p);
+            if (!strcasecmp(cmd, "AVOptionVideo")) {
+                avctx = &video_enc;
+                type = AV_OPT_FLAG_VIDEO_PARAM;
+            } else {
+                avctx = &audio_enc;
+                type = AV_OPT_FLAG_AUDIO_PARAM;
+            }
+            if (opt_default(arg, arg2, avctx, type|AV_OPT_FLAG_ENCODING_PARAM)) {
+                fprintf(stderr, "AVOption error: %s %s\n", arg, arg2);
+                errors++;
+            }
         } else if (!strcasecmp(cmd, "VideoTag")) {
             get_arg(arg, sizeof(arg), &p);
             if ((strlen(arg) == 4) && stream)
@@ -4351,6 +4393,7 @@ static void opt_debug()
 {
     ffserver_debug = 1;
     ffserver_daemon = 0;
+    logfilename[0] = '-';
 }
 
 static void opt_show_help(void)
@@ -4388,7 +4431,7 @@ int main(int argc, char **argv)
 
     parse_options(argc, argv, options, NULL);
 
-    putenv("http_proxy");               /* Kill the http_proxy */
+    unsetenv("http_proxy");             /* Kill the http_proxy */
 
     av_init_random(av_gettime() + (getpid() << 16), &random_state);
 
@@ -4405,7 +4448,6 @@ int main(int argc, char **argv)
     nb_max_connections = 5;
     max_bandwidth = 1000;
     first_stream = NULL;
-    logfilename[0] = '\0';
 
     memset(&sigact, 0, sizeof(sigact));
     sigact.sa_handler = handle_child_exit;
@@ -4461,7 +4503,7 @@ int main(int argc, char **argv)
     }
 
     if (http_server() < 0) {
-        fprintf(stderr, "Could not start server\n");
+        http_log("Could not start server\n");
         exit(1);
     }