avcodec/mjpegdec: make "unknown colorspace" error more informative
[ffmpeg.git] / ffserver.c
index e83534c..4215265 100644 (file)
 #endif
 #include <string.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include "libavformat/avformat.h"
 // FIXME those are internal headers, ffserver _really_ shouldn't use them
 #include "libavformat/ffm.h"
 #include "libavformat/network.h"
 #include "libavformat/os_support.h"
 #include "libavformat/rtpdec.h"
+#include "libavformat/rtpproto.h"
 #include "libavformat/rtsp.h"
 #include "libavformat/avio_internal.h"
 #include "libavformat/internal.h"
@@ -62,9 +64,6 @@
 #include <time.h>
 #include <sys/wait.h>
 #include <signal.h>
-#if HAVE_DLFCN_H
-#include <dlfcn.h>
-#endif
 
 #include "cmdutils.h"
 
@@ -306,12 +305,10 @@ static int rtp_new_av_stream(HTTPContext *c,
                              HTTPContext *rtsp_c);
 
 static const char *my_program_name;
-static const char *my_program_dir;
 
-static const char *config_filename = "/etc/ffserver.conf";
+static const char *config_filename;
 
 static int ffserver_debug;
-static int ffserver_daemon;
 static int no_launch;
 static int need_to_start_children;
 
@@ -397,14 +394,14 @@ static int resolve_host(struct in_addr *sin_addr, const char *hostname)
     return 0;
 }
 
-static char *ctime1(char *buf2)
+static char *ctime1(char *buf2, int buf_size)
 {
     time_t ti;
     char *p;
 
     ti = time(NULL);
     p = ctime(&ti);
-    strcpy(buf2, p);
+    av_strlcpy(buf2, p, buf_size);
     p = buf2 + strlen(p) - 1;
     if (*p == '\n')
         *p = '\0';
@@ -417,7 +414,7 @@ static void http_vlog(const char *fmt, va_list vargs)
     if (logfile) {
         if (print_prefix) {
             char buf[32];
-            ctime1(buf);
+            ctime1(buf, sizeof(buf));
             fprintf(logfile, "%s ", buf);
         }
         print_prefix = strstr(fmt, "\n") != NULL;
@@ -522,19 +519,12 @@ static void start_children(FFStream *feed)
                     close(i);
 
                 if (!ffserver_debug) {
-                    i = open("/dev/null", O_RDWR);
-                    if (i != -1) {
-                        dup2(i, 0);
-                        dup2(i, 1);
-                        dup2(i, 2);
-                        close(i);
-                    }
-                }
-
-                /* This is needed to make relative pathnames work */
-                if (chdir(my_program_dir) < 0) {
-                    http_log("chdir failed\n");
-                    exit(1);
+                    if (!freopen("/dev/null", "r", stdin))
+                        http_log("failed to redirect STDIN to /dev/null\n;");
+                    if (!freopen("/dev/null", "w", stdout))
+                        http_log("failed to redirect STDOUT to /dev/null\n;");
+                    if (!freopen("/dev/null", "w", stderr))
+                        http_log("failed to redirect STDERR to /dev/null\n;");
                 }
 
                 signal(SIGPIPE, SIG_DFL);
@@ -586,7 +576,7 @@ static void start_multicast(void)
     FFStream *stream;
     char session_id[32];
     HTTPContext *rtp_c;
-    struct sockaddr_in dest_addr;
+    struct sockaddr_in dest_addr = {0};
     int default_port, stream_index;
 
     default_port = 6000;
@@ -929,6 +919,8 @@ static void close_connection(HTTPContext *c)
 
     for(i=0; i<ctx->nb_streams; i++)
         av_free(ctx->streams[i]);
+    av_freep(&ctx->streams);
+    av_freep(&ctx->priv_data);
 
     if (c->stream && !c->post && c->stream->stream_type == STREAM_TYPE_LIVE)
         current_bandwidth -= c->stream->bandwidth;
@@ -1131,7 +1123,7 @@ static int extract_rates(char *rates, int ratelen, const char *request)
         if (av_strncasecmp(p, "Pragma:", 7) == 0) {
             const char *q = p + 7;
 
-            while (*q && *q != '\n' && isspace(*q))
+            while (*q && *q != '\n' && av_isspace(*q))
                 q++;
 
             if (av_strncasecmp(q, "stream-switch-entry=", 20) == 0) {
@@ -1153,7 +1145,7 @@ static int extract_rates(char *rates, int ratelen, const char *request)
                     if (stream_no < ratelen && stream_no >= 0)
                         rates[stream_no] = rate_no;
 
-                    while (*q && *q != '\n' && !isspace(*q))
+                    while (*q && *q != '\n' && !av_isspace(*q))
                         q++;
                 }
 
@@ -1264,7 +1256,7 @@ static void get_word(char *buf, int buf_size, const char **pp)
     p = *pp;
     skip_spaces(&p);
     q = buf;
-    while (!isspace(*p) && *p != '\0') {
+    while (!av_isspace(*p) && *p != '\0') {
         if ((q - buf) < buf_size - 1)
             *q++ = *p;
         p++;
@@ -1281,7 +1273,7 @@ static void get_arg(char *buf, int buf_size, const char **pp)
     int quote;
 
     p = *pp;
-    while (isspace(*p)) p++;
+    while (av_isspace(*p)) p++;
     q = buf;
     quote = 0;
     if (*p == '\"' || *p == '\'')
@@ -1291,7 +1283,7 @@ static void get_arg(char *buf, int buf_size, const char **pp)
             if (*p == quote)
                 break;
         } else {
-            if (isspace(*p))
+            if (av_isspace(*p))
                 break;
         }
         if (*p == '\0')
@@ -1395,7 +1387,7 @@ static IPAddressACL* parse_dynamic_acl(FFStream *stream, HTTPContext *c)
             break;
         line_num++;
         p = line;
-        while (isspace(*p))
+        while (av_isspace(*p))
             p++;
         if (*p == '\0' || *p == '#')
             continue;
@@ -1496,7 +1488,8 @@ enum RedirType {
 /* parse http request and prepare header */
 static int http_parse_request(HTTPContext *c)
 {
-    char *p;
+    const char *p;
+    char *p1;
     enum RedirType redir_type;
     char cmd[32];
     char info[1024], filename[1024];
@@ -1507,10 +1500,10 @@ static int http_parse_request(HTTPContext *c)
     FFStream *stream;
     int i;
     char ratebuf[32];
-    char *useragent = 0;
+    const char *useragent = 0;
 
     p = c->buffer;
-    get_word(cmd, sizeof(cmd), (const char **)&p);
+    get_word(cmd, sizeof(cmd), &p);
     av_strlcpy(c->method, cmd, sizeof(c->method));
 
     if (!strcmp(cmd, "GET"))
@@ -1520,7 +1513,7 @@ static int http_parse_request(HTTPContext *c)
     else
         return -1;
 
-    get_word(url, sizeof(url), (const char **)&p);
+    get_word(url, sizeof(url), &p);
     av_strlcpy(c->url, url, sizeof(c->url));
 
     get_word(protocol, sizeof(protocol), (const char **)&p);
@@ -1533,10 +1526,10 @@ static int http_parse_request(HTTPContext *c)
         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 (p) {
-        av_strlcpy(info, p, sizeof(info));
-        *p = '\0';
+    p1 = strchr(url, '?');
+    if (p1) {
+        av_strlcpy(info, p1, sizeof(info));
+        *p1 = '\0';
     } else
         info[0] = '\0';
 
@@ -1545,7 +1538,7 @@ static int http_parse_request(HTTPContext *c)
     for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
         if (av_strncasecmp(p, "User-Agent:", 11) == 0) {
             useragent = p + 11;
-            if (*useragent && *useragent != '\n' && isspace(*useragent))
+            if (*useragent && *useragent != '\n' && av_isspace(*useragent))
                 useragent++;
             break;
         }
@@ -1655,7 +1648,7 @@ static int http_parse_request(HTTPContext *c)
     }
 
     if (redir_type != REDIR_NONE) {
-        char *hostinfo = 0;
+        const char *hostinfo = 0;
 
         for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
             if (av_strncasecmp(p, "Host:", 5) == 0) {
@@ -1673,7 +1666,7 @@ static int http_parse_request(HTTPContext *c)
             char *eoh;
             char hostbuf[260];
 
-            while (isspace(*hostinfo))
+            while (av_isspace(*hostinfo))
                 hostinfo++;
 
             eoh = strchr(hostinfo, '\n');
@@ -1789,7 +1782,7 @@ static int http_parse_request(HTTPContext *c)
         if (!stream->is_feed) {
             /* However it might be a status report from WMP! Let us log the
              * data as it might come in handy one day. */
-            char *logline = 0;
+            const char *logline = 0;
             int client_id = 0;
 
             for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
@@ -2050,7 +2043,7 @@ static void compute_status(HTTPContext *c)
             if (stream->pid) {
                 avio_printf(pb, "Running as pid %d.\n", stream->pid);
 
-#if defined(linux) && !defined(CONFIG_NOCUTILS)
+#if defined(linux)
                 {
                     FILE *pid_stat;
                     char ps_cmd[64];
@@ -2966,12 +2959,14 @@ static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
 {
     AVFormatContext *avc;
     AVStream *avs = NULL;
+    AVOutputFormat *rtp_format = av_guess_format("rtp", NULL, NULL);
     int i;
 
     avc =  avformat_alloc_context();
-    if (avc == NULL) {
+    if (avc == NULL || !rtp_format) {
         return -1;
     }
+    avc->oformat = rtp_format;
     av_dict_set(&avc->metadata, "title",
                stream->title[0] ? stream->title : "No Title", 0);
     avc->nb_streams = stream->nb_streams;
@@ -3521,7 +3516,7 @@ static AVStream *add_av_stream1(FFStream *stream, AVCodecContext *codec, int cop
         fst->codec = avcodec_alloc_context3(NULL);
         memcpy(fst->codec, codec, sizeof(AVCodecContext));
         if (codec->extradata_size) {
-            fst->codec->extradata = av_malloc(codec->extradata_size);
+            fst->codec->extradata = av_mallocz(codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
             memcpy(fst->codec->extradata, codec->extradata,
                 codec->extradata_size);
         }
@@ -3600,6 +3595,8 @@ static void extract_mpeg4_header(AVFormatContext *infile)
     AVStream *st;
     const uint8_t *p;
 
+    infile->flags |= AVFMT_FLAG_NOFILLIN | AVFMT_FLAG_NOPARSE;
+
     mpeg4_count = 0;
     for(i=0;i<infile->nb_streams;i++) {
         st = infile->streams[i];
@@ -3613,7 +3610,7 @@ static void extract_mpeg4_header(AVFormatContext *infile)
 
     printf("MPEG4 without extra data: trying to find header in %s\n", infile->filename);
     while (mpeg4_count > 0) {
-        if (av_read_packet(infile, &pkt) < 0)
+        if (av_read_frame(infile, &pkt) < 0)
             break;
         st = infile->streams[pkt.stream_index];
         if (st->codec->codec_id == AV_CODEC_ID_MPEG4 &&
@@ -3628,7 +3625,7 @@ static void extract_mpeg4_header(AVFormatContext *infile)
                     p[2] == 0x01 && p[3] == 0xb6) {
                     size = p - pkt.data;
                     //                    av_hex_dump_log(infile, AV_LOG_DEBUG, pkt.data, size);
-                    st->codec->extradata = av_malloc(size);
+                    st->codec->extradata = av_mallocz(size + FF_INPUT_BUFFER_PADDING_SIZE);
                     st->codec->extradata_size = size;
                     memcpy(st->codec->extradata, pkt.data, size);
                     break;
@@ -3907,7 +3904,7 @@ static void add_codec(FFStream *stream, AVCodecContext *av)
         av->rc_buffer_aggressivity = 1.0;
 
         if (!av->rc_eq)
-            av->rc_eq = "tex^qComp";
+            av->rc_eq = av_strdup("tex^qComp");
         if (!av->i_quant_factor)
             av->i_quant_factor = -0.8;
         if (!av->b_quant_factor)
@@ -3955,32 +3952,6 @@ static enum AVCodecID opt_video_codec(const char *arg)
     return p->id;
 }
 
-/* simplistic plugin support */
-
-#if HAVE_DLOPEN
-static void load_module(const char *filename)
-{
-    void *dll;
-    void (*init_func)(void);
-    dll = dlopen(filename, RTLD_NOW);
-    if (!dll) {
-        fprintf(stderr, "Could not load module '%s' - %s\n",
-                filename, dlerror());
-        return;
-    }
-
-    init_func = dlsym(dll, "ffserver_module_init");
-    if (!init_func) {
-        fprintf(stderr,
-                "%s: init function 'ffserver_module_init()' not found\n",
-                filename);
-        dlclose(dll);
-    }
-
-    init_func();
-}
-#endif
-
 static int ffserver_opt_default(const char *opt, const char *arg,
                        AVCodecContext *avctx, int type)
 {
@@ -4101,7 +4072,7 @@ static int parse_ffconfig(const char *filename)
             break;
         line_num++;
         p = line;
-        while (isspace(*p))
+        while (av_isspace(*p))
             p++;
         if (*p == '\0' || *p == '#')
             continue;
@@ -4121,7 +4092,7 @@ static int parse_ffconfig(const char *filename)
                 ERROR("%s:%d: Invalid host/IP address: %s\n", arg);
             }
         } else if (!av_strcasecmp(cmd, "NoDaemon")) {
-            ffserver_daemon = 0;
+            // do nothing here, its the default now
         } else if (!av_strcasecmp(cmd, "RTSPPort")) {
             get_arg(arg, sizeof(arg), &p);
             val = atoi(arg);
@@ -4152,7 +4123,7 @@ static int parse_ffconfig(const char *filename)
         } else if (!av_strcasecmp(cmd, "MaxBandwidth")) {
             int64_t llval;
             get_arg(arg, sizeof(arg), &p);
-            llval = atoll(arg);
+            llval = strtoll(arg, NULL, 10);
             if (llval < 10 || llval > 10000000) {
                 ERROR("Invalid MaxBandwidth: %s\n", arg);
             } else
@@ -4208,10 +4179,7 @@ static int parse_ffconfig(const char *filename)
                     feed->child_argv[i] = av_strdup(arg);
                 }
 
-                feed->child_argv[i] = av_malloc(30 + strlen(feed->filename));
-
-                snprintf(feed->child_argv[i], 30+strlen(feed->filename),
-                    "http://%s:%d/%s",
+                feed->child_argv[i] = av_asprintf("http://%s:%d/%s",
                         (my_http_addr.sin_addr.s_addr == INADDR_ANY) ? "127.0.0.1" :
                     inet_ntoa(my_http_addr.sin_addr),
                     ntohs(my_http_addr.sin_port), feed->filename);
@@ -4241,7 +4209,7 @@ static int parse_ffconfig(const char *filename)
                 get_arg(arg, sizeof(arg), &p);
                 p1 = arg;
                 fsize = strtod(p1, &p1);
-                switch(toupper(*p1)) {
+                switch(av_toupper(*p1)) {
                 case 'K':
                     fsize *= 1024;
                     break;
@@ -4273,7 +4241,7 @@ static int parse_ffconfig(const char *filename)
                 stream = av_mallocz(sizeof(FFStream));
                 get_arg(stream->filename, sizeof(stream->filename), &p);
                 q = strrchr(stream->filename, '>');
-                if (*q)
+                if (q)
                     *q = '\0';
 
                 for (s = first_stream; s; s = s->next) {
@@ -4549,14 +4517,6 @@ static int parse_ffconfig(const char *filename)
                     ERROR("VideoQMin out of range\n");
                 }
             }
-        } else if (!av_strcasecmp(cmd, "LumaElim")) {
-            get_arg(arg, sizeof(arg), &p);
-            if (stream)
-                video_enc.luma_elim_threshold = atoi(arg);
-        } else if (!av_strcasecmp(cmd, "ChromaElim")) {
-            get_arg(arg, sizeof(arg), &p);
-            if (stream)
-                video_enc.chroma_elim_threshold = atoi(arg);
         } else if (!av_strcasecmp(cmd, "LumiMask")) {
             get_arg(arg, sizeof(arg), &p);
             if (stream)
@@ -4648,12 +4608,7 @@ static int parse_ffconfig(const char *filename)
                 redirect = NULL;
             }
         } else if (!av_strcasecmp(cmd, "LoadModule")) {
-            get_arg(arg, sizeof(arg), &p);
-#if HAVE_DLOPEN
-            load_module(arg);
-#else
-            ERROR("Module support not compiled into this version: '%s'\n", arg);
-#endif
+            ERROR("Loadable modules no longer supported\n");
         } else {
             ERROR("Incorrect keyword: '%s'\n", cmd);
         }
@@ -4695,7 +4650,6 @@ static void handle_child_exit(int sig)
 static void opt_debug(void)
 {
     ffserver_debug = 1;
-    ffserver_daemon = 0;
     logfilename[0] = '-';
 }
 
@@ -4719,6 +4673,8 @@ int main(int argc, char **argv)
 {
     struct sigaction sigact = { { 0 } };
 
+    config_filename = av_strdup("/etc/ffserver.conf");
+
     parse_loglevel(argc, argv, options);
     av_register_all();
     avformat_network_init();
@@ -4726,8 +4682,6 @@ int main(int argc, char **argv)
     show_banner(argc, argv, options);
 
     my_program_name = argv[0];
-    my_program_dir = getcwd(0, 0);
-    ffserver_daemon = 1;
 
     parse_options(NULL, argc, argv, options, NULL);
 
@@ -4743,6 +4697,7 @@ int main(int argc, char **argv)
         fprintf(stderr, "Incorrect config file - exiting.\n");
         exit(1);
     }
+    av_freep(&config_filename);
 
     /* open log file if needed */
     if (logfilename[0] != '\0') {
@@ -4759,37 +4714,9 @@ int main(int argc, char **argv)
 
     compute_bandwidth();
 
-    /* put the process in background and detach it from its TTY */
-    if (ffserver_daemon) {
-        int pid;
-
-        pid = fork();
-        if (pid < 0) {
-            perror("fork");
-            exit(1);
-        } else if (pid > 0) {
-            /* parent : exit */
-            exit(0);
-        } else {
-            /* child */
-            setsid();
-            close(0);
-            open("/dev/null", O_RDWR);
-            if (strcmp(logfilename, "-") != 0) {
-                close(1);
-                dup(0);
-            }
-            close(2);
-            dup(0);
-        }
-    }
-
     /* signal init */
     signal(SIGPIPE, SIG_IGN);
 
-    if (ffserver_daemon)
-        chdir("/");
-
     if (http_server() < 0) {
         http_log("Could not start server\n");
         exit(1);