]> git.sesse.net Git - ffmpeg/blobdiff - ffserver.c
fix a typo
[ffmpeg] / ffserver.c
index 8bf38225cf3409606577073840b591b51f451a5b..6742e583543be05420c43198a10d4bcac3cc57d4 100644 (file)
  */
 
 #include "config.h"
-#if HAVE_CLOSESOCKET != 1
+#ifndef HAVE_CLOSESOCKET
 #define closesocket close
 #endif
 #include <string.h>
 #include <stdlib.h>
 #include "avformat.h"
+#include "rtsp.h"
+#include "rtp.h"
+#include "os_support.h"
 
 #include <stdarg.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
-#ifdef HAVE_SYS_POLL_H
-#include <sys/poll.h>
+#ifdef HAVE_POLL_H
+#include <poll.h>
 #endif
 #include <errno.h>
 #include <sys/time.h>
 #include "ffserver.h"
 #include "random.h"
 #include "avstring.h"
+#include "cmdutils.h"
 
 #undef exit
 
+static const char program_name[] = "FFserver";
+static const int program_birth_year = 2000;
+
 /* maximum number of simultaneous HTTP connections */
 #define HTTP_MAX_CONNECTIONS 2000
 
@@ -227,14 +234,14 @@ typedef struct FFStream {
     int conns_served;
     int64_t bytes_served;
     int64_t feed_max_size;      /* maximum storage size, zero means unlimited */
-    int64_t feed_write_index;   /* current write position in feed (it wraps round) */
+    int64_t feed_write_index;   /* current write position in feed (it wraps around) */
     int64_t feed_size;          /* current size of feed */
     struct FFStream *next_feed;
 } FFStream;
 
 typedef struct FeedData {
     long long data_count;
-    float avg_frame_size;   /* frame size averraged over last frames with exponential mean */
+    float avg_frame_size;   /* frame size averaged over last frames with exponential mean */
 } FeedData;
 
 static struct sockaddr_in my_http_addr;
@@ -746,7 +753,7 @@ static void close_connection(HTTPContext *c)
             /* prepare header */
             if (url_open_dyn_buf(&ctx->pb) >= 0) {
                 av_write_trailer(ctx);
-                url_close_dyn_buf(&ctx->pb, &c->pb_buffer);
+                url_close_dyn_buf(ctx->pb, &c->pb_buffer);
             }
         }
     }
@@ -1590,9 +1597,9 @@ static void compute_stats(HTTPContext *c)
     char *p;
     time_t ti;
     int i, len;
-    ByteIOContext pb1, *pb = &pb1;
+    ByteIOContext *pb;
 
-    if (url_open_dyn_buf(pb) < 0) {
+    if (url_open_dyn_buf(&pb) < 0) {
         /* XXX: return an error ? */
         c->buffer_ptr = c->buffer;
         c->buffer_end = c->buffer;
@@ -1626,7 +1633,7 @@ static void compute_stats(HTTPContext *c)
                     strcpy(eosf - 4, ".asx");
                 else if (strcmp(eosf - 3, ".rm") == 0)
                     strcpy(eosf - 3, ".ram");
-                else if (stream->fmt == &rtp_muxer) {
+                else if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
                     /* generate a sample RTSP director if
                        unicast. Generate an SDP redirector if
                        multicast */
@@ -1886,7 +1893,11 @@ static int open_input_stream(HTTPContext *c, const char *info)
         buf_size = FFM_PACKET_SIZE;
         /* compute position (absolute time) */
         if (find_info_tag(buf, sizeof(buf), "date", info))
+        {
             stream_pos = parse_date(buf, 0);
+            if (stream_pos == INT64_MIN)
+                return -1;
+        }
         else if (find_info_tag(buf, sizeof(buf), "buffer", info)) {
             int prebuffer = strtol(buf, 0, 10);
             stream_pos = av_gettime() - prebuffer * (int64_t)1000000;
@@ -1897,7 +1908,11 @@ static int open_input_stream(HTTPContext *c, const char *info)
         buf_size = 0;
         /* compute position (relative time) */
         if (find_info_tag(buf, sizeof(buf), "date", info))
+        {
             stream_pos = parse_date(buf, 1);
+            if (stream_pos == INT64_MIN)
+                return -1;
+        }
         else
             stream_pos = 0;
     }
@@ -1916,7 +1931,9 @@ static int open_input_stream(HTTPContext *c, const char *info)
         http_log("%s not found", input_filename);
         return -1;
     }
+    s->flags |= AVFMT_FLAG_GENPTS;
     c->fmt_in = s;
+    av_find_stream_info(c->fmt_in);
 
     /* open each parser */
     for(i=0;i<s->nb_streams;i++)
@@ -2016,13 +2033,13 @@ static int http_prepare_data(HTTPContext *c)
             /* XXX: potential leak */
             return -1;
         }
-        c->fmt_ctx.pb.is_streamed = 1;
+        c->fmt_ctx.pb->is_streamed = 1;
 
         av_set_parameters(&c->fmt_ctx, NULL);
         if (av_write_header(&c->fmt_ctx) < 0)
             return -1;
 
-        len = url_close_dyn_buf(&c->fmt_ctx.pb, &c->pb_buffer);
+        len = url_close_dyn_buf(c->fmt_ctx.pb, &c->pb_buffer);
         c->buffer_ptr = c->pb_buffer;
         c->buffer_end = c->pb_buffer + len;
 
@@ -2166,7 +2183,7 @@ static int http_prepare_data(HTTPContext *c)
                         if (av_write_frame(ctx, &pkt))
                             c->state = HTTPSTATE_SEND_DATA_TRAILER;
 
-                        len = url_close_dyn_buf(&ctx->pb, &c->pb_buffer);
+                        len = url_close_dyn_buf(ctx->pb, &c->pb_buffer);
                         c->cur_frame_bytes = len;
                         c->buffer_ptr = c->pb_buffer;
                         c->buffer_end = c->pb_buffer + len;
@@ -2192,7 +2209,7 @@ static int http_prepare_data(HTTPContext *c)
             return -1;
         }
         av_write_trailer(ctx);
-        len = url_close_dyn_buf(&ctx->pb, &c->pb_buffer);
+        len = url_close_dyn_buf(ctx->pb, &c->pb_buffer);
         c->buffer_ptr = c->pb_buffer;
         c->buffer_end = c->pb_buffer + len;
 
@@ -2245,7 +2262,7 @@ static int http_send_data(HTTPContext *c)
 
                 if (c->rtp_protocol == RTSP_PROTOCOL_RTP_TCP) {
                     /* RTP packets are sent inside the RTSP TCP connection */
-                    ByteIOContext pb1, *pb = &pb1;
+                    ByteIOContext *pb;
                     int interleaved_index, size;
                     uint8_t header[4];
                     HTTPContext *rtsp_c;
@@ -2257,7 +2274,7 @@ static int http_send_data(HTTPContext *c)
                     /* if already sending something, then wait. */
                     if (rtsp_c->state != RTSPSTATE_WAIT_REQUEST)
                         break;
-                    if (url_open_dyn_buf(pb) < 0)
+                    if (url_open_dyn_buf(&pb) < 0)
                         goto fail1;
                     interleaved_index = c->packet_stream_index * 2;
                     /* RTCP packets are sent at odd indexes */
@@ -2416,14 +2433,12 @@ static int http_receive_data(HTTPContext *c)
             /* We have a header in our hands that contains useful data */
             AVFormatContext s;
             AVInputFormat *fmt_in;
-            ByteIOContext *pb = &s.pb;
             int i;
 
             memset(&s, 0, sizeof(s));
 
-            url_open_buf(pb, c->buffer, c->buffer_end - c->buffer, URL_RDONLY);
-            pb->buf_end = c->buffer_end;        /* ?? */
-            pb->is_streamed = 1;
+            url_open_buf(&s.pb, c->buffer, c->buffer_end - c->buffer, URL_RDONLY);
+            s.pb->is_streamed = 1;
 
             /* use feed output format name to find corresponding input format */
             fmt_in = av_find_input_format(feed->fmt->name);
@@ -2537,7 +2552,6 @@ static int rtsp_parse_request(HTTPContext *c)
     char url[1024];
     char protocol[32];
     char line[1024];
-    ByteIOContext pb1;
     int len;
     RTSPHeader header1, *header = &header1;
 
@@ -2552,8 +2566,7 @@ static int rtsp_parse_request(HTTPContext *c)
     av_strlcpy(c->url, url, sizeof(c->url));
     av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
 
-    c->pb = &pb1;
-    if (url_open_dyn_buf(c->pb) < 0) {
+    if (url_open_dyn_buf(&c->pb) < 0) {
         /* XXX: cannot do more */
         c->pb = NULL; /* safety */
         return -1;
@@ -2622,94 +2635,38 @@ static int rtsp_parse_request(HTTPContext *c)
     return 0;
 }
 
-/* XXX: move that to rtsp.c, but would need to replace FFStream by
-   AVFormatContext */
 static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
                                    struct in_addr my_ip)
 {
-    ByteIOContext pb1, *pb = &pb1;
-    int i, payload_type, port, private_payload_type, j;
-    const char *ipstr, *title, *mediatype;
-    AVStream *st;
+    AVFormatContext *avc;
+    AVStream avs[MAX_STREAMS];
+    int i;
 
-    if (url_open_dyn_buf(pb) < 0)
+    avc =  av_alloc_format_context();
+    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));
+    }
+    avc->nb_streams = stream->nb_streams;
+    if (stream->is_multicast) {
+        snprintf(avc->filename, 1024, "rtp://%s:%d?multicast=1?ttl=%d",
+                 inet_ntoa(stream->multicast_ip),
+                 stream->multicast_port, stream->multicast_ttl);
+    }
 
-    /* general media info */
-
-    url_fprintf(pb, "v=0\n");
-    ipstr = inet_ntoa(my_ip);
-    url_fprintf(pb, "o=- 0 0 IN IP4 %s\n", ipstr);
-    title = stream->title;
-    if (title[0] == '\0')
-        title = "No Title";
-    url_fprintf(pb, "s=%s\n", title);
-    if (stream->comment[0] != '\0')
-        url_fprintf(pb, "i=%s\n", stream->comment);
-    if (stream->is_multicast)
-        url_fprintf(pb, "c=IN IP4 %s\n", inet_ntoa(stream->multicast_ip));
-
-    /* for each stream, we output the necessary info */
-    private_payload_type = RTP_PT_PRIVATE;
     for(i = 0; i < stream->nb_streams; i++) {
-        st = stream->streams[i];
-        if (st->codec->codec_id == CODEC_ID_MPEG2TS)
-            mediatype = "video";
-        else {
-            switch(st->codec->codec_type) {
-            case CODEC_TYPE_AUDIO:
-                mediatype = "audio";
-                break;
-            case CODEC_TYPE_VIDEO:
-                mediatype = "video";
-                break;
-            default:
-                mediatype = "application";
-                break;
-            }
-        }
-        /* NOTE: the port indication is not correct in case of
-           unicast. It is not an issue because RTSP gives it */
-        payload_type = rtp_get_payload_type(st->codec);
-        if (payload_type < 0)
-            payload_type = private_payload_type++;
-        if (stream->is_multicast)
-            port = stream->multicast_port + 2 * i;
-        else
-            port = 0;
-
-        url_fprintf(pb, "m=%s %d RTP/AVP %d\n",
-                    mediatype, port, payload_type);
-        if (payload_type >= RTP_PT_PRIVATE) {
-            /* for private payload type, we need to give more info */
-            switch(st->codec->codec_id) {
-            case CODEC_ID_MPEG4:
-                {
-                    uint8_t *data;
-                    url_fprintf(pb, "a=rtpmap:%d MP4V-ES/%d\n",
-                                payload_type, 90000);
-                    /* we must also add the mpeg4 header */
-                    data = st->codec->extradata;
-                    if (data) {
-                        url_fprintf(pb, "a=fmtp:%d config=", payload_type);
-                        for(j=0;j<st->codec->extradata_size;j++)
-                            url_fprintf(pb, "%02x", data[j]);
-                        url_fprintf(pb, "\n");
-                    }
-                }
-                break;
-            default:
-                /* XXX: add other codecs ? */
-                goto fail;
-            }
-        }
-        url_fprintf(pb, "a=control:streamid=%d\n", i);
+        avc->streams[i] = &avs[i];
+        avc->streams[i]->codec = stream->streams[i]->codec;
     }
-    return url_close_dyn_buf(pb, pbuffer);
- fail:
-    url_close_dyn_buf(pb, pbuffer);
-    av_free(*pbuffer);
-    return -1;
+    *pbuffer = av_mallocz(2048);
+    avf_sdp_create(&avc, 1, *pbuffer, 2048);
+    av_free(avc);
+
+    return strlen(*pbuffer);
 }
 
 static void rtsp_cmd_options(HTTPContext *c, const char *url)
@@ -2737,7 +2694,8 @@ static void rtsp_cmd_describe(HTTPContext *c, const char *url)
         path++;
 
     for(stream = first_stream; stream != NULL; stream = stream->next) {
-        if (!stream->is_feed && stream->fmt == &rtp_muxer &&
+        if (!stream->is_feed &&
+            stream->fmt && !strcmp(stream->fmt->name, "rtp") &&
             !strcmp(path, stream->filename)) {
             goto found;
         }
@@ -2812,7 +2770,8 @@ static void rtsp_cmd_setup(HTTPContext *c, const char *url,
 
     /* now check each stream */
     for(stream = first_stream; stream != NULL; stream = stream->next) {
-        if (!stream->is_feed && stream->fmt == &rtp_muxer) {
+        if (!stream->is_feed &&
+            stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
             /* accept aggregate filenames only if single stream */
             if (!strcmp(path, stream->filename)) {
                 if (stream->nb_streams != 1) {
@@ -3130,7 +3089,7 @@ static int rtp_new_av_stream(HTTPContext *c,
     ctx = av_alloc_format_context();
     if (!ctx)
         return -1;
-    ctx->oformat = &rtp_muxer;
+    ctx->oformat = guess_format("rtp", NULL, NULL);
 
     st = av_mallocz(sizeof(AVStream));
     if (!st)
@@ -3202,7 +3161,7 @@ static int rtp_new_av_stream(HTTPContext *c,
         av_free(ctx);
         return -1;
     }
-    url_close_dyn_buf(&ctx->pb, &dummy_buf);
+    url_close_dyn_buf(ctx->pb, &dummy_buf);
     av_free(dummy_buf);
 
     c->rtp_ctx[stream_index] = ctx;
@@ -3349,7 +3308,7 @@ static void build_file_streams(void)
             /* try to open the file */
             /* open stream */
             stream->ap_in = av_mallocz(sizeof(AVFormatParameters));
-            if (stream->fmt == &rtp_muxer) {
+            if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
                 /* specific case : if transport stream output to RTP,
                    we use a raw transport stream reader */
                 stream->ap_in->mpeg2ts_raw = 1;
@@ -3517,7 +3476,7 @@ static void build_feed_streams(void)
             }
             /* XXX: need better api */
             av_freep(&s->priv_data);
-            url_fclose(&s->pb);
+            url_fclose(s->pb);
         }
         /* get feed size and write index */
         fd = open(feed->feed_filename, O_RDONLY);
@@ -3668,15 +3627,9 @@ static void add_codec(FFStream *stream, AVCodecContext *av)
 
 static int opt_audio_codec(const char *arg)
 {
-    AVCodec *p;
+    AVCodec *p= avcodec_find_encoder_by_name(arg);
 
-    p = first_avcodec;
-    while (p) {
-        if (!strcmp(p->name, arg) && p->type == CODEC_TYPE_AUDIO)
-            break;
-        p = p->next;
-    }
-    if (p == NULL)
+    if (p == NULL || p->type != CODEC_TYPE_AUDIO)
         return CODEC_ID_NONE;
 
     return p->id;
@@ -3684,15 +3637,9 @@ static int opt_audio_codec(const char *arg)
 
 static int opt_video_codec(const char *arg)
 {
-    AVCodec *p;
+    AVCodec *p= avcodec_find_encoder_by_name(arg);
 
-    p = first_avcodec;
-    while (p) {
-        if (!strcmp(p->name, arg) && p->type == CODEC_TYPE_VIDEO)
-            break;
-        p = p->next;
-    }
-    if (p == NULL)
+    if (p == NULL || p->type != CODEC_TYPE_VIDEO)
         return CODEC_ID_NONE;
 
     return p->id;
@@ -3853,7 +3800,7 @@ static int parse_ffconfig(const char *filename)
             if (feed) {
                 int i;
 
-                feed->child_argv = (char **) av_mallocz(64 * sizeof(char *));
+                feed->child_argv = av_mallocz(64 * sizeof(char *));
 
                 for (i = 0; i < 62; i++) {
                     get_arg(arg, sizeof(arg), &p);
@@ -3894,12 +3841,12 @@ static int parse_ffconfig(const char *filename)
                 get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
         } else if (!strcasecmp(cmd, "FileMaxSize")) {
             if (feed) {
-                const char *p1;
+                char *p1;
                 double fsize;
 
                 get_arg(arg, sizeof(arg), &p);
                 p1 = arg;
-                fsize = strtod(p1, (char **)&p1);
+                fsize = strtod(p1, &p1);
                 switch(toupper(*p1)) {
                 case 'K':
                     fsize *= 1024;
@@ -4230,7 +4177,7 @@ static int parse_ffconfig(const char *filename)
             }
 
             if (!errors) {
-                IPAddressACL *nacl = (IPAddressACL *) av_mallocz(sizeof(*nacl));
+                IPAddressACL *nacl = av_mallocz(sizeof(*nacl));
                 IPAddressACL **naclp = 0;
 
                 acl.next = 0;
@@ -4356,14 +4303,8 @@ static int parse_ffconfig(const char *filename)
         return 0;
 }
 
-static void show_banner(void)
-{
-    printf("ffserver version " FFMPEG_VERSION ", Copyright (c) 2000-2006 Fabrice Bellard, et al.\n");
-}
-
 static void show_help(void)
 {
-    show_banner();
     printf("usage: ffserver [-L] [-h] [-f configfile]\n"
            "Hyper fast multi format Audio/Video streaming server\n"
            "\n"
@@ -4373,26 +4314,6 @@ static void show_help(void)
            );
 }
 
-static void show_license(void)
-{
-    show_banner();
-    printf(
-    "FFmpeg is free software; you can redistribute it and/or\n"
-    "modify it under the terms of the GNU Lesser General Public\n"
-    "License as published by the Free Software Foundation; either\n"
-    "version 2.1 of the License, or (at your option) any later version.\n"
-    "\n"
-    "FFmpeg is distributed in the hope that it will be useful,\n"
-    "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
-    "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n"
-    "Lesser General Public License for more details.\n"
-    "\n"
-    "You should have received a copy of the GNU Lesser General Public\n"
-    "License along with FFmpeg; if not, write to the Free Software\n"
-    "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n"
-    );
-}
-
 static void handle_child_exit(int sig)
 {
     pid_t pid;
@@ -4426,6 +4347,8 @@ int main(int argc, char **argv)
 
     av_register_all();
 
+    show_banner(program_name, program_birth_year);
+
     config_filename = "/etc/ffserver.conf";
 
     my_program_name = argv[0];
@@ -4439,11 +4362,11 @@ int main(int argc, char **argv)
         switch(c) {
         case 'L':
             show_license();
-            exit(1);
+            exit(0);
         case '?':
         case 'h':
             show_help();
-            exit(1);
+            exit(0);
         case 'n':
             no_launch = 1;
             break;