Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed










Rev Author Line No. Line
4349 Serge 1
/*
2
 * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
3
 *
4
 * This file is part of FFmpeg.
5
 *
6
 * FFmpeg is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * FFmpeg is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with FFmpeg; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
 */
20
 
21
/**
22
 * @file
23
 * multiple format streaming server based on the FFmpeg libraries
24
 */
25
 
26
#include "config.h"
27
#if !HAVE_CLOSESOCKET
28
#define closesocket close
29
#endif
30
#include 
31
#include 
32
#include 
33
#include "libavformat/avformat.h"
34
// FIXME those are internal headers, ffserver _really_ shouldn't use them
35
#include "libavformat/ffm.h"
36
#include "libavformat/network.h"
37
#include "libavformat/os_support.h"
38
#include "libavformat/rtpdec.h"
39
#include "libavformat/rtpproto.h"
40
#include "libavformat/rtsp.h"
41
#include "libavformat/avio_internal.h"
42
#include "libavformat/internal.h"
43
#include "libavformat/url.h"
44
 
45
#include "libavutil/avassert.h"
46
#include "libavutil/avstring.h"
47
#include "libavutil/lfg.h"
48
#include "libavutil/dict.h"
49
#include "libavutil/intreadwrite.h"
50
#include "libavutil/mathematics.h"
51
#include "libavutil/pixdesc.h"
52
#include "libavutil/random_seed.h"
53
#include "libavutil/parseutils.h"
54
#include "libavutil/opt.h"
55
#include "libavutil/time.h"
56
 
57
#include 
58
#include 
59
#include 
60
#include 
61
#if HAVE_POLL_H
62
#include 
63
#endif
64
#include 
65
#include 
66
#include 
67
#include 
68
 
69
#include "cmdutils.h"
70
 
71
const char program_name[] = "ffserver";
72
const int program_birth_year = 2000;
73
 
74
static const OptionDef options[];
75
 
76
enum HTTPState {
77
    HTTPSTATE_WAIT_REQUEST,
78
    HTTPSTATE_SEND_HEADER,
79
    HTTPSTATE_SEND_DATA_HEADER,
80
    HTTPSTATE_SEND_DATA,          /* sending TCP or UDP data */
81
    HTTPSTATE_SEND_DATA_TRAILER,
82
    HTTPSTATE_RECEIVE_DATA,
83
    HTTPSTATE_WAIT_FEED,          /* wait for data from the feed */
84
    HTTPSTATE_READY,
85
 
86
    RTSPSTATE_WAIT_REQUEST,
87
    RTSPSTATE_SEND_REPLY,
88
    RTSPSTATE_SEND_PACKET,
89
};
90
 
91
static const char *http_state[] = {
92
    "HTTP_WAIT_REQUEST",
93
    "HTTP_SEND_HEADER",
94
 
95
    "SEND_DATA_HEADER",
96
    "SEND_DATA",
97
    "SEND_DATA_TRAILER",
98
    "RECEIVE_DATA",
99
    "WAIT_FEED",
100
    "READY",
101
 
102
    "RTSP_WAIT_REQUEST",
103
    "RTSP_SEND_REPLY",
104
    "RTSP_SEND_PACKET",
105
};
106
 
107
#define MAX_STREAMS 20
108
 
109
#define IOBUFFER_INIT_SIZE 8192
110
 
111
/* timeouts are in ms */
112
#define HTTP_REQUEST_TIMEOUT (15 * 1000)
113
#define RTSP_REQUEST_TIMEOUT (3600 * 24 * 1000)
114
 
115
#define SYNC_TIMEOUT (10 * 1000)
116
 
117
typedef struct RTSPActionServerSetup {
118
    uint32_t ipaddr;
119
    char transport_option[512];
120
} RTSPActionServerSetup;
121
 
122
typedef struct {
123
    int64_t count1, count2;
124
    int64_t time1, time2;
125
} DataRateData;
126
 
127
/* context associated with one connection */
128
typedef struct HTTPContext {
129
    enum HTTPState state;
130
    int fd; /* socket file descriptor */
131
    struct sockaddr_in from_addr; /* origin */
132
    struct pollfd *poll_entry; /* used when polling */
133
    int64_t timeout;
134
    uint8_t *buffer_ptr, *buffer_end;
135
    int http_error;
136
    int post;
137
    int chunked_encoding;
138
    int chunk_size;               /* 0 if it needs to be read */
139
    struct HTTPContext *next;
140
    int got_key_frame; /* stream 0 => 1, stream 1 => 2, stream 2=> 4 */
141
    int64_t data_count;
142
    /* feed input */
143
    int feed_fd;
144
    /* input format handling */
145
    AVFormatContext *fmt_in;
146
    int64_t start_time;            /* In milliseconds - this wraps fairly often */
147
    int64_t first_pts;            /* initial pts value */
148
    int64_t cur_pts;             /* current pts value from the stream in us */
149
    int64_t cur_frame_duration;  /* duration of the current frame in us */
150
    int cur_frame_bytes;       /* output frame size, needed to compute
151
                                  the time at which we send each
152
                                  packet */
153
    int pts_stream_index;        /* stream we choose as clock reference */
154
    int64_t cur_clock;           /* current clock reference value in us */
155
    /* output format handling */
156
    struct FFStream *stream;
157
    /* -1 is invalid stream */
158
    int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
159
    int switch_feed_streams[MAX_STREAMS]; /* index of streams in the feed */
160
    int switch_pending;
161
    AVFormatContext fmt_ctx; /* instance of FFStream for one user */
162
    int last_packet_sent; /* true if last data packet was sent */
163
    int suppress_log;
164
    DataRateData datarate;
165
    int wmp_client_id;
166
    char protocol[16];
167
    char method[16];
168
    char url[128];
169
    int buffer_size;
170
    uint8_t *buffer;
171
    int is_packetized; /* if true, the stream is packetized */
172
    int packet_stream_index; /* current stream for output in state machine */
173
 
174
    /* RTSP state specific */
175
    uint8_t *pb_buffer; /* XXX: use that in all the code */
176
    AVIOContext *pb;
177
    int seq; /* RTSP sequence number */
178
 
179
    /* RTP state specific */
180
    enum RTSPLowerTransport rtp_protocol;
181
    char session_id[32]; /* session id */
182
    AVFormatContext *rtp_ctx[MAX_STREAMS];
183
 
184
    /* RTP/UDP specific */
185
    URLContext *rtp_handles[MAX_STREAMS];
186
 
187
    /* RTP/TCP specific */
188
    struct HTTPContext *rtsp_c;
189
    uint8_t *packet_buffer, *packet_buffer_ptr, *packet_buffer_end;
190
} HTTPContext;
191
 
192
/* each generated stream is described here */
193
enum StreamType {
194
    STREAM_TYPE_LIVE,
195
    STREAM_TYPE_STATUS,
196
    STREAM_TYPE_REDIRECT,
197
};
198
 
199
enum IPAddressAction {
200
    IP_ALLOW = 1,
201
    IP_DENY,
202
};
203
 
204
typedef struct IPAddressACL {
205
    struct IPAddressACL *next;
206
    enum IPAddressAction action;
207
    /* These are in host order */
208
    struct in_addr first;
209
    struct in_addr last;
210
} IPAddressACL;
211
 
212
/* description of each stream of the ffserver.conf file */
213
typedef struct FFStream {
214
    enum StreamType stream_type;
215
    char filename[1024];     /* stream filename */
216
    struct FFStream *feed;   /* feed we are using (can be null if
217
                                coming from file) */
218
    AVDictionary *in_opts;   /* input parameters */
219
    AVInputFormat *ifmt;       /* if non NULL, force input format */
220
    AVOutputFormat *fmt;
221
    IPAddressACL *acl;
222
    char dynamic_acl[1024];
223
    int nb_streams;
224
    int prebuffer;      /* Number of millseconds early to start */
225
    int64_t max_time;      /* Number of milliseconds to run */
226
    int send_on_key;
227
    AVStream *streams[MAX_STREAMS];
228
    int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
229
    char feed_filename[1024]; /* file name of the feed storage, or
230
                                 input file name for a stream */
231
    char author[512];
232
    char title[512];
233
    char copyright[512];
234
    char comment[512];
235
    pid_t pid;  /* Of ffmpeg process */
236
    time_t pid_start;  /* Of ffmpeg process */
237
    char **child_argv;
238
    struct FFStream *next;
239
    unsigned bandwidth; /* bandwidth, in kbits/s */
240
    /* RTSP options */
241
    char *rtsp_option;
242
    /* multicast specific */
243
    int is_multicast;
244
    struct in_addr multicast_ip;
245
    int multicast_port; /* first port used for multicast */
246
    int multicast_ttl;
247
    int loop; /* if true, send the stream in loops (only meaningful if file) */
248
 
249
    /* feed specific */
250
    int feed_opened;     /* true if someone is writing to the feed */
251
    int is_feed;         /* true if it is a feed */
252
    int readonly;        /* True if writing is prohibited to the file */
253
    int truncate;        /* True if feeder connection truncate the feed file */
254
    int conns_served;
255
    int64_t bytes_served;
256
    int64_t feed_max_size;      /* maximum storage size, zero means unlimited */
257
    int64_t feed_write_index;   /* current write position in feed (it wraps around) */
258
    int64_t feed_size;          /* current size of feed */
259
    struct FFStream *next_feed;
260
} FFStream;
261
 
262
typedef struct FeedData {
263
    long long data_count;
264
    float avg_frame_size;   /* frame size averaged over last frames with exponential mean */
265
} FeedData;
266
 
267
static struct sockaddr_in my_http_addr;
268
static struct sockaddr_in my_rtsp_addr;
269
 
270
static char logfilename[1024];
271
static HTTPContext *first_http_ctx;
272
static FFStream *first_feed;   /* contains only feeds */
273
static FFStream *first_stream; /* contains all streams, including feeds */
274
 
275
static void new_connection(int server_fd, int is_rtsp);
276
static void close_connection(HTTPContext *c);
277
 
278
/* HTTP handling */
279
static int handle_connection(HTTPContext *c);
280
static int http_parse_request(HTTPContext *c);
281
static int http_send_data(HTTPContext *c);
282
static void compute_status(HTTPContext *c);
283
static int open_input_stream(HTTPContext *c, const char *info);
284
static int http_start_receive_data(HTTPContext *c);
285
static int http_receive_data(HTTPContext *c);
286
 
287
/* RTSP handling */
288
static int rtsp_parse_request(HTTPContext *c);
289
static void rtsp_cmd_describe(HTTPContext *c, const char *url);
290
static void rtsp_cmd_options(HTTPContext *c, const char *url);
291
static void rtsp_cmd_setup(HTTPContext *c, const char *url, RTSPMessageHeader *h);
292
static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h);
293
static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h);
294
static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPMessageHeader *h);
295
 
296
/* SDP handling */
297
static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
298
                                   struct in_addr my_ip);
299
 
300
/* RTP handling */
301
static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
302
                                       FFStream *stream, const char *session_id,
303
                                       enum RTSPLowerTransport rtp_protocol);
304
static int rtp_new_av_stream(HTTPContext *c,
305
                             int stream_index, struct sockaddr_in *dest_addr,
306
                             HTTPContext *rtsp_c);
307
 
308
static const char *my_program_name;
309
 
310
static const char *config_filename;
311
 
312
static int ffserver_debug;
313
static int no_launch;
314
static int need_to_start_children;
315
 
316
/* maximum number of simultaneous HTTP connections */
317
static unsigned int nb_max_http_connections = 2000;
318
static unsigned int nb_max_connections = 5;
319
static unsigned int nb_connections;
320
 
321
static uint64_t max_bandwidth = 1000;
322
static uint64_t current_bandwidth;
323
 
324
static int64_t cur_time;           // Making this global saves on passing it around everywhere
325
 
326
static AVLFG random_state;
327
 
328
static FILE *logfile = NULL;
329
 
330
static void htmlstrip(char *s) {
331
    while (s && *s) {
332
        s += strspn(s, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,. ");
333
        if (*s)
334
            *s++ = '?';
335
    }
336
}
337
 
338
static int64_t ffm_read_write_index(int fd)
339
{
340
    uint8_t buf[8];
341
 
342
    if (lseek(fd, 8, SEEK_SET) < 0)
343
        return AVERROR(EIO);
344
    if (read(fd, buf, 8) != 8)
345
        return AVERROR(EIO);
346
    return AV_RB64(buf);
347
}
348
 
349
static int ffm_write_write_index(int fd, int64_t pos)
350
{
351
    uint8_t buf[8];
352
    int i;
353
 
354
    for(i=0;i<8;i++)
355
        buf[i] = (pos >> (56 - i * 8)) & 0xff;
356
    if (lseek(fd, 8, SEEK_SET) < 0)
357
        return AVERROR(EIO);
358
    if (write(fd, buf, 8) != 8)
359
        return AVERROR(EIO);
360
    return 8;
361
}
362
 
363
static void ffm_set_write_index(AVFormatContext *s, int64_t pos,
364
                                int64_t file_size)
365
{
366
    FFMContext *ffm = s->priv_data;
367
    ffm->write_index = pos;
368
    ffm->file_size = file_size;
369
}
370
 
371
/* FIXME: make ffserver work with IPv6 */
372
/* resolve host with also IP address parsing */
373
static int resolve_host(struct in_addr *sin_addr, const char *hostname)
374
{
375
 
376
    if (!ff_inet_aton(hostname, sin_addr)) {
377
#if HAVE_GETADDRINFO
378
        struct addrinfo *ai, *cur;
379
        struct addrinfo hints = { 0 };
380
        hints.ai_family = AF_INET;
381
        if (getaddrinfo(hostname, NULL, &hints, &ai))
382
            return -1;
383
        /* getaddrinfo returns a linked list of addrinfo structs.
384
         * Even if we set ai_family = AF_INET above, make sure
385
         * that the returned one actually is of the correct type. */
386
        for (cur = ai; cur; cur = cur->ai_next) {
387
            if (cur->ai_family == AF_INET) {
388
                *sin_addr = ((struct sockaddr_in *)cur->ai_addr)->sin_addr;
389
                freeaddrinfo(ai);
390
                return 0;
391
            }
392
        }
393
        freeaddrinfo(ai);
394
        return -1;
395
#else
396
        struct hostent *hp;
397
        hp = gethostbyname(hostname);
398
        if (!hp)
399
            return -1;
400
        memcpy(sin_addr, hp->h_addr_list[0], sizeof(struct in_addr));
401
#endif
402
    }
403
    return 0;
404
}
405
 
406
static char *ctime1(char *buf2, int buf_size)
407
{
408
    time_t ti;
409
    char *p;
410
 
411
    ti = time(NULL);
412
    p = ctime(&ti);
413
    av_strlcpy(buf2, p, buf_size);
414
    p = buf2 + strlen(p) - 1;
415
    if (*p == '\n')
416
        *p = '\0';
417
    return buf2;
418
}
419
 
420
static void http_vlog(const char *fmt, va_list vargs)
421
{
422
    static int print_prefix = 1;
423
    if (logfile) {
424
        if (print_prefix) {
425
            char buf[32];
426
            ctime1(buf, sizeof(buf));
427
            fprintf(logfile, "%s ", buf);
428
        }
429
        print_prefix = strstr(fmt, "\n") != NULL;
430
        vfprintf(logfile, fmt, vargs);
431
        fflush(logfile);
432
    }
433
}
434
 
435
#ifdef __GNUC__
436
__attribute__ ((format (printf, 1, 2)))
437
#endif
438
static void http_log(const char *fmt, ...)
439
{
440
    va_list vargs;
441
    va_start(vargs, fmt);
442
    http_vlog(fmt, vargs);
443
    va_end(vargs);
444
}
445
 
446
static void http_av_log(void *ptr, int level, const char *fmt, va_list vargs)
447
{
448
    static int print_prefix = 1;
449
    AVClass *avc = ptr ? *(AVClass**)ptr : NULL;
450
    if (level > av_log_get_level())
451
        return;
452
    if (print_prefix && avc)
453
        http_log("[%s @ %p]", avc->item_name(ptr), ptr);
454
    print_prefix = strstr(fmt, "\n") != NULL;
455
    http_vlog(fmt, vargs);
456
}
457
 
458
static void log_connection(HTTPContext *c)
459
{
460
    if (c->suppress_log)
461
        return;
462
 
463
    http_log("%s - - [%s] \"%s %s\" %d %"PRId64"\n",
464
             inet_ntoa(c->from_addr.sin_addr), c->method, c->url,
465
             c->protocol, (c->http_error ? c->http_error : 200), c->data_count);
466
}
467
 
468
static void update_datarate(DataRateData *drd, int64_t count)
469
{
470
    if (!drd->time1 && !drd->count1) {
471
        drd->time1 = drd->time2 = cur_time;
472
        drd->count1 = drd->count2 = count;
473
    } else if (cur_time - drd->time2 > 5000) {
474
        drd->time1 = drd->time2;
475
        drd->count1 = drd->count2;
476
        drd->time2 = cur_time;
477
        drd->count2 = count;
478
    }
479
}
480
 
481
/* In bytes per second */
482
static int compute_datarate(DataRateData *drd, int64_t count)
483
{
484
    if (cur_time == drd->time1)
485
        return 0;
486
 
487
    return ((count - drd->count1) * 1000) / (cur_time - drd->time1);
488
}
489
 
490
 
491
static void start_children(FFStream *feed)
492
{
493
    if (no_launch)
494
        return;
495
 
496
    for (; feed; feed = feed->next) {
497
        if (feed->child_argv && !feed->pid) {
498
            feed->pid_start = time(0);
499
 
500
            feed->pid = fork();
501
 
502
            if (feed->pid < 0) {
503
                http_log("Unable to create children\n");
504
                exit(1);
505
            }
506
            if (!feed->pid) {
507
                /* In child */
508
                char pathname[1024];
509
                char *slash;
510
                int i;
511
 
512
                av_strlcpy(pathname, my_program_name, sizeof(pathname));
513
 
514
                slash = strrchr(pathname, '/');
515
                if (!slash)
516
                    slash = pathname;
517
                else
518
                    slash++;
519
                strcpy(slash, "ffmpeg");
520
 
521
                http_log("Launch command line: ");
522
                http_log("%s ", pathname);
523
                for (i = 1; feed->child_argv[i] && feed->child_argv[i][0]; i++)
524
                    http_log("%s ", feed->child_argv[i]);
525
                http_log("\n");
526
 
527
                for (i = 3; i < 256; i++)
528
                    close(i);
529
 
530
                if (!ffserver_debug) {
531
                    if (!freopen("/dev/null", "r", stdin))
532
                        http_log("failed to redirect STDIN to /dev/null\n;");
533
                    if (!freopen("/dev/null", "w", stdout))
534
                        http_log("failed to redirect STDOUT to /dev/null\n;");
535
                    if (!freopen("/dev/null", "w", stderr))
536
                        http_log("failed to redirect STDERR to /dev/null\n;");
537
                }
538
 
539
                signal(SIGPIPE, SIG_DFL);
540
 
541
                execvp(pathname, feed->child_argv);
542
 
543
                _exit(1);
544
            }
545
        }
546
    }
547
}
548
 
549
/* open a listening socket */
550
static int socket_open_listen(struct sockaddr_in *my_addr)
551
{
552
    int server_fd, tmp;
553
 
554
    server_fd = socket(AF_INET,SOCK_STREAM,0);
555
    if (server_fd < 0) {
556
        perror ("socket");
557
        return -1;
558
    }
559
 
560
    tmp = 1;
561
    setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp));
562
 
563
    my_addr->sin_family = AF_INET;
564
    if (bind (server_fd, (struct sockaddr *) my_addr, sizeof (*my_addr)) < 0) {
565
        char bindmsg[32];
566
        snprintf(bindmsg, sizeof(bindmsg), "bind(port %d)", ntohs(my_addr->sin_port));
567
        perror (bindmsg);
568
        closesocket(server_fd);
569
        return -1;
570
    }
571
 
572
    if (listen (server_fd, 5) < 0) {
573
        perror ("listen");
574
        closesocket(server_fd);
575
        return -1;
576
    }
577
    ff_socket_nonblock(server_fd, 1);
578
 
579
    return server_fd;
580
}
581
 
582
/* start all multicast streams */
583
static void start_multicast(void)
584
{
585
    FFStream *stream;
586
    char session_id[32];
587
    HTTPContext *rtp_c;
588
    struct sockaddr_in dest_addr = {0};
589
    int default_port, stream_index;
590
 
591
    default_port = 6000;
592
    for(stream = first_stream; stream != NULL; stream = stream->next) {
593
        if (stream->is_multicast) {
594
            unsigned random0 = av_lfg_get(&random_state);
595
            unsigned random1 = av_lfg_get(&random_state);
596
            /* open the RTP connection */
597
            snprintf(session_id, sizeof(session_id), "%08x%08x",
598
                     random0, random1);
599
 
600
            /* choose a port if none given */
601
            if (stream->multicast_port == 0) {
602
                stream->multicast_port = default_port;
603
                default_port += 100;
604
            }
605
 
606
            dest_addr.sin_family = AF_INET;
607
            dest_addr.sin_addr = stream->multicast_ip;
608
            dest_addr.sin_port = htons(stream->multicast_port);
609
 
610
            rtp_c = rtp_new_connection(&dest_addr, stream, session_id,
611
                                       RTSP_LOWER_TRANSPORT_UDP_MULTICAST);
612
            if (!rtp_c)
613
                continue;
614
 
615
            if (open_input_stream(rtp_c, "") < 0) {
616
                http_log("Could not open input stream for stream '%s'\n",
617
                         stream->filename);
618
                continue;
619
            }
620
 
621
            /* open each RTP stream */
622
            for(stream_index = 0; stream_index < stream->nb_streams;
623
                stream_index++) {
624
                dest_addr.sin_port = htons(stream->multicast_port +
625
                                           2 * stream_index);
626
                if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, NULL) < 0) {
627
                    http_log("Could not open output stream '%s/streamid=%d'\n",
628
                             stream->filename, stream_index);
629
                    exit(1);
630
                }
631
            }
632
 
633
            /* change state to send data */
634
            rtp_c->state = HTTPSTATE_SEND_DATA;
635
        }
636
    }
637
}
638
 
639
/* main loop of the http server */
640
static int http_server(void)
641
{
642
    int server_fd = 0, rtsp_server_fd = 0;
643
    int ret, delay, delay1;
644
    struct pollfd *poll_table, *poll_entry;
645
    HTTPContext *c, *c_next;
646
 
647
    if(!(poll_table = av_mallocz((nb_max_http_connections + 2)*sizeof(*poll_table)))) {
648
        http_log("Impossible to allocate a poll table handling %d connections.\n", nb_max_http_connections);
649
        return -1;
650
    }
651
 
652
    if (my_http_addr.sin_port) {
653
        server_fd = socket_open_listen(&my_http_addr);
654
        if (server_fd < 0)
655
            return -1;
656
    }
657
 
658
    if (my_rtsp_addr.sin_port) {
659
        rtsp_server_fd = socket_open_listen(&my_rtsp_addr);
660
        if (rtsp_server_fd < 0)
661
            return -1;
662
    }
663
 
664
    if (!rtsp_server_fd && !server_fd) {
665
        http_log("HTTP and RTSP disabled.\n");
666
        return -1;
667
    }
668
 
669
    http_log("FFserver started.\n");
670
 
671
    start_children(first_feed);
672
 
673
    start_multicast();
674
 
675
    for(;;) {
676
        poll_entry = poll_table;
677
        if (server_fd) {
678
            poll_entry->fd = server_fd;
679
            poll_entry->events = POLLIN;
680
            poll_entry++;
681
        }
682
        if (rtsp_server_fd) {
683
            poll_entry->fd = rtsp_server_fd;
684
            poll_entry->events = POLLIN;
685
            poll_entry++;
686
        }
687
 
688
        /* wait for events on each HTTP handle */
689
        c = first_http_ctx;
690
        delay = 1000;
691
        while (c != NULL) {
692
            int fd;
693
            fd = c->fd;
694
            switch(c->state) {
695
            case HTTPSTATE_SEND_HEADER:
696
            case RTSPSTATE_SEND_REPLY:
697
            case RTSPSTATE_SEND_PACKET:
698
                c->poll_entry = poll_entry;
699
                poll_entry->fd = fd;
700
                poll_entry->events = POLLOUT;
701
                poll_entry++;
702
                break;
703
            case HTTPSTATE_SEND_DATA_HEADER:
704
            case HTTPSTATE_SEND_DATA:
705
            case HTTPSTATE_SEND_DATA_TRAILER:
706
                if (!c->is_packetized) {
707
                    /* for TCP, we output as much as we can (may need to put a limit) */
708
                    c->poll_entry = poll_entry;
709
                    poll_entry->fd = fd;
710
                    poll_entry->events = POLLOUT;
711
                    poll_entry++;
712
                } else {
713
                    /* when ffserver is doing the timing, we work by
714
                       looking at which packet need to be sent every
715
                       10 ms */
716
                    delay1 = 10; /* one tick wait XXX: 10 ms assumed */
717
                    if (delay1 < delay)
718
                        delay = delay1;
719
                }
720
                break;
721
            case HTTPSTATE_WAIT_REQUEST:
722
            case HTTPSTATE_RECEIVE_DATA:
723
            case HTTPSTATE_WAIT_FEED:
724
            case RTSPSTATE_WAIT_REQUEST:
725
                /* need to catch errors */
726
                c->poll_entry = poll_entry;
727
                poll_entry->fd = fd;
728
                poll_entry->events = POLLIN;/* Maybe this will work */
729
                poll_entry++;
730
                break;
731
            default:
732
                c->poll_entry = NULL;
733
                break;
734
            }
735
            c = c->next;
736
        }
737
 
738
        /* wait for an event on one connection. We poll at least every
739
           second to handle timeouts */
740
        do {
741
            ret = poll(poll_table, poll_entry - poll_table, delay);
742
            if (ret < 0 && ff_neterrno() != AVERROR(EAGAIN) &&
743
                ff_neterrno() != AVERROR(EINTR))
744
                return -1;
745
        } while (ret < 0);
746
 
747
        cur_time = av_gettime() / 1000;
748
 
749
        if (need_to_start_children) {
750
            need_to_start_children = 0;
751
            start_children(first_feed);
752
        }
753
 
754
        /* now handle the events */
755
        for(c = first_http_ctx; c != NULL; c = c_next) {
756
            c_next = c->next;
757
            if (handle_connection(c) < 0) {
758
                /* close and free the connection */
759
                log_connection(c);
760
                close_connection(c);
761
            }
762
        }
763
 
764
        poll_entry = poll_table;
765
        if (server_fd) {
766
            /* new HTTP connection request ? */
767
            if (poll_entry->revents & POLLIN)
768
                new_connection(server_fd, 0);
769
            poll_entry++;
770
        }
771
        if (rtsp_server_fd) {
772
            /* new RTSP connection request ? */
773
            if (poll_entry->revents & POLLIN)
774
                new_connection(rtsp_server_fd, 1);
775
        }
776
    }
777
}
778
 
779
/* start waiting for a new HTTP/RTSP request */
780
static void start_wait_request(HTTPContext *c, int is_rtsp)
781
{
782
    c->buffer_ptr = c->buffer;
783
    c->buffer_end = c->buffer + c->buffer_size - 1; /* leave room for '\0' */
784
 
785
    if (is_rtsp) {
786
        c->timeout = cur_time + RTSP_REQUEST_TIMEOUT;
787
        c->state = RTSPSTATE_WAIT_REQUEST;
788
    } else {
789
        c->timeout = cur_time + HTTP_REQUEST_TIMEOUT;
790
        c->state = HTTPSTATE_WAIT_REQUEST;
791
    }
792
}
793
 
794
static void http_send_too_busy_reply(int fd)
795
{
796
    char buffer[400];
797
    int len = snprintf(buffer, sizeof(buffer),
798
                       "HTTP/1.0 503 Server too busy\r\n"
799
                       "Content-type: text/html\r\n"
800
                       "\r\n"
801
                       "Too busy\r\n"
802
                       "

The server is too busy to serve your request at this time.

\r\n"
803
                       "

The number of current connections is %u, and this exceeds the limit of %u.

\r\n"
804
                       "\r\n",
805
                       nb_connections, nb_max_connections);
806
    av_assert0(len < sizeof(buffer));
807
    send(fd, buffer, len, 0);
808
}
809
 
810
 
811
static void new_connection(int server_fd, int is_rtsp)
812
{
813
    struct sockaddr_in from_addr;
814
    socklen_t len;
815
    int fd;
816
    HTTPContext *c = NULL;
817
 
818
    len = sizeof(from_addr);
819
    fd = accept(server_fd, (struct sockaddr *)&from_addr,
820
                &len);
821
    if (fd < 0) {
822
        http_log("error during accept %s\n", strerror(errno));
823
        return;
824
    }
825
    ff_socket_nonblock(fd, 1);
826
 
827
    if (nb_connections >= nb_max_connections) {
828
        http_send_too_busy_reply(fd);
829
        goto fail;
830
    }
831
 
832
    /* add a new connection */
833
    c = av_mallocz(sizeof(HTTPContext));
834
    if (!c)
835
        goto fail;
836
 
837
    c->fd = fd;
838
    c->poll_entry = NULL;
839
    c->from_addr = from_addr;
840
    c->buffer_size = IOBUFFER_INIT_SIZE;
841
    c->buffer = av_malloc(c->buffer_size);
842
    if (!c->buffer)
843
        goto fail;
844
 
845
    c->next = first_http_ctx;
846
    first_http_ctx = c;
847
    nb_connections++;
848
 
849
    start_wait_request(c, is_rtsp);
850
 
851
    return;
852
 
853
 fail:
854
    if (c) {
855
        av_free(c->buffer);
856
        av_free(c);
857
    }
858
    closesocket(fd);
859
}
860
 
861
static void close_connection(HTTPContext *c)
862
{
863
    HTTPContext **cp, *c1;
864
    int i, nb_streams;
865
    AVFormatContext *ctx;
866
    URLContext *h;
867
    AVStream *st;
868
 
869
    /* remove connection from list */
870
    cp = &first_http_ctx;
871
    while ((*cp) != NULL) {
872
        c1 = *cp;
873
        if (c1 == c)
874
            *cp = c->next;
875
        else
876
            cp = &c1->next;
877
    }
878
 
879
    /* remove references, if any (XXX: do it faster) */
880
    for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
881
        if (c1->rtsp_c == c)
882
            c1->rtsp_c = NULL;
883
    }
884
 
885
    /* remove connection associated resources */
886
    if (c->fd >= 0)
887
        closesocket(c->fd);
888
    if (c->fmt_in) {
889
        /* close each frame parser */
890
        for(i=0;ifmt_in->nb_streams;i++) {
891
            st = c->fmt_in->streams[i];
892
            if (st->codec->codec)
893
                avcodec_close(st->codec);
894
        }
895
        avformat_close_input(&c->fmt_in);
896
    }
897
 
898
    /* free RTP output streams if any */
899
    nb_streams = 0;
900
    if (c->stream)
901
        nb_streams = c->stream->nb_streams;
902
 
903
    for(i=0;i
904
        ctx = c->rtp_ctx[i];
905
        if (ctx) {
906
            av_write_trailer(ctx);
907
            av_dict_free(&ctx->metadata);
908
            av_free(ctx->streams[0]);
909
            av_free(ctx);
910
        }
911
        h = c->rtp_handles[i];
912
        if (h)
913
            ffurl_close(h);
914
    }
915
 
916
    ctx = &c->fmt_ctx;
917
 
918
    if (!c->last_packet_sent && c->state == HTTPSTATE_SEND_DATA_TRAILER) {
919
        if (ctx->oformat) {
920
            /* prepare header */
921
            if (avio_open_dyn_buf(&ctx->pb) >= 0) {
922
                av_write_trailer(ctx);
923
                av_freep(&c->pb_buffer);
924
                avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
925
            }
926
        }
927
    }
928
 
929
    for(i=0; inb_streams; i++)
930
        av_free(ctx->streams[i]);
931
    av_freep(&ctx->streams);
932
    av_freep(&ctx->priv_data);
933
 
934
    if (c->stream && !c->post && c->stream->stream_type == STREAM_TYPE_LIVE)
935
        current_bandwidth -= c->stream->bandwidth;
936
 
937
    /* signal that there is no feed if we are the feeder socket */
938
    if (c->state == HTTPSTATE_RECEIVE_DATA && c->stream) {
939
        c->stream->feed_opened = 0;
940
        close(c->feed_fd);
941
    }
942
 
943
    av_freep(&c->pb_buffer);
944
    av_freep(&c->packet_buffer);
945
    av_free(c->buffer);
946
    av_free(c);
947
    nb_connections--;
948
}
949
 
950
static int handle_connection(HTTPContext *c)
951
{
952
    int len, ret;
953
 
954
    switch(c->state) {
955
    case HTTPSTATE_WAIT_REQUEST:
956
    case RTSPSTATE_WAIT_REQUEST:
957
        /* timeout ? */
958
        if ((c->timeout - cur_time) < 0)
959
            return -1;
960
        if (c->poll_entry->revents & (POLLERR | POLLHUP))
961
            return -1;
962
 
963
        /* no need to read if no events */
964
        if (!(c->poll_entry->revents & POLLIN))
965
            return 0;
966
        /* read the data */
967
    read_loop:
968
        len = recv(c->fd, c->buffer_ptr, 1, 0);
969
        if (len < 0) {
970
            if (ff_neterrno() != AVERROR(EAGAIN) &&
971
                ff_neterrno() != AVERROR(EINTR))
972
                return -1;
973
        } else if (len == 0) {
974
            return -1;
975
        } else {
976
            /* search for end of request. */
977
            uint8_t *ptr;
978
            c->buffer_ptr += len;
979
            ptr = c->buffer_ptr;
980
            if ((ptr >= c->buffer + 2 && !memcmp(ptr-2, "\n\n", 2)) ||
981
                (ptr >= c->buffer + 4 && !memcmp(ptr-4, "\r\n\r\n", 4))) {
982
                /* request found : parse it and reply */
983
                if (c->state == HTTPSTATE_WAIT_REQUEST) {
984
                    ret = http_parse_request(c);
985
                } else {
986
                    ret = rtsp_parse_request(c);
987
                }
988
                if (ret < 0)
989
                    return -1;
990
            } else if (ptr >= c->buffer_end) {
991
                /* request too long: cannot do anything */
992
                return -1;
993
            } else goto read_loop;
994
        }
995
        break;
996
 
997
    case HTTPSTATE_SEND_HEADER:
998
        if (c->poll_entry->revents & (POLLERR | POLLHUP))
999
            return -1;
1000
 
1001
        /* no need to write if no events */
1002
        if (!(c->poll_entry->revents & POLLOUT))
1003
            return 0;
1004
        len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
1005
        if (len < 0) {
1006
            if (ff_neterrno() != AVERROR(EAGAIN) &&
1007
                ff_neterrno() != AVERROR(EINTR)) {
1008
                /* error : close connection */
1009
                av_freep(&c->pb_buffer);
1010
                return -1;
1011
            }
1012
        } else {
1013
            c->buffer_ptr += len;
1014
            if (c->stream)
1015
                c->stream->bytes_served += len;
1016
            c->data_count += len;
1017
            if (c->buffer_ptr >= c->buffer_end) {
1018
                av_freep(&c->pb_buffer);
1019
                /* if error, exit */
1020
                if (c->http_error)
1021
                    return -1;
1022
                /* all the buffer was sent : synchronize to the incoming stream */
1023
                c->state = HTTPSTATE_SEND_DATA_HEADER;
1024
                c->buffer_ptr = c->buffer_end = c->buffer;
1025
            }
1026
        }
1027
        break;
1028
 
1029
    case HTTPSTATE_SEND_DATA:
1030
    case HTTPSTATE_SEND_DATA_HEADER:
1031
    case HTTPSTATE_SEND_DATA_TRAILER:
1032
        /* for packetized output, we consider we can always write (the
1033
           input streams sets the speed). It may be better to verify
1034
           that we do not rely too much on the kernel queues */
1035
        if (!c->is_packetized) {
1036
            if (c->poll_entry->revents & (POLLERR | POLLHUP))
1037
                return -1;
1038
 
1039
            /* no need to read if no events */
1040
            if (!(c->poll_entry->revents & POLLOUT))
1041
                return 0;
1042
        }
1043
        if (http_send_data(c) < 0)
1044
            return -1;
1045
        /* close connection if trailer sent */
1046
        if (c->state == HTTPSTATE_SEND_DATA_TRAILER)
1047
            return -1;
1048
        break;
1049
    case HTTPSTATE_RECEIVE_DATA:
1050
        /* no need to read if no events */
1051
        if (c->poll_entry->revents & (POLLERR | POLLHUP))
1052
            return -1;
1053
        if (!(c->poll_entry->revents & POLLIN))
1054
            return 0;
1055
        if (http_receive_data(c) < 0)
1056
            return -1;
1057
        break;
1058
    case HTTPSTATE_WAIT_FEED:
1059
        /* no need to read if no events */
1060
        if (c->poll_entry->revents & (POLLIN | POLLERR | POLLHUP))
1061
            return -1;
1062
 
1063
        /* nothing to do, we'll be waken up by incoming feed packets */
1064
        break;
1065
 
1066
    case RTSPSTATE_SEND_REPLY:
1067
        if (c->poll_entry->revents & (POLLERR | POLLHUP)) {
1068
            av_freep(&c->pb_buffer);
1069
            return -1;
1070
        }
1071
        /* no need to write if no events */
1072
        if (!(c->poll_entry->revents & POLLOUT))
1073
            return 0;
1074
        len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
1075
        if (len < 0) {
1076
            if (ff_neterrno() != AVERROR(EAGAIN) &&
1077
                ff_neterrno() != AVERROR(EINTR)) {
1078
                /* error : close connection */
1079
                av_freep(&c->pb_buffer);
1080
                return -1;
1081
            }
1082
        } else {
1083
            c->buffer_ptr += len;
1084
            c->data_count += len;
1085
            if (c->buffer_ptr >= c->buffer_end) {
1086
                /* all the buffer was sent : wait for a new request */
1087
                av_freep(&c->pb_buffer);
1088
                start_wait_request(c, 1);
1089
            }
1090
        }
1091
        break;
1092
    case RTSPSTATE_SEND_PACKET:
1093
        if (c->poll_entry->revents & (POLLERR | POLLHUP)) {
1094
            av_freep(&c->packet_buffer);
1095
            return -1;
1096
        }
1097
        /* no need to write if no events */
1098
        if (!(c->poll_entry->revents & POLLOUT))
1099
            return 0;
1100
        len = send(c->fd, c->packet_buffer_ptr,
1101
                    c->packet_buffer_end - c->packet_buffer_ptr, 0);
1102
        if (len < 0) {
1103
            if (ff_neterrno() != AVERROR(EAGAIN) &&
1104
                ff_neterrno() != AVERROR(EINTR)) {
1105
                /* error : close connection */
1106
                av_freep(&c->packet_buffer);
1107
                return -1;
1108
            }
1109
        } else {
1110
            c->packet_buffer_ptr += len;
1111
            if (c->packet_buffer_ptr >= c->packet_buffer_end) {
1112
                /* all the buffer was sent : wait for a new request */
1113
                av_freep(&c->packet_buffer);
1114
                c->state = RTSPSTATE_WAIT_REQUEST;
1115
            }
1116
        }
1117
        break;
1118
    case HTTPSTATE_READY:
1119
        /* nothing to do */
1120
        break;
1121
    default:
1122
        return -1;
1123
    }
1124
    return 0;
1125
}
1126
 
1127
static int extract_rates(char *rates, int ratelen, const char *request)
1128
{
1129
    const char *p;
1130
 
1131
    for (p = request; *p && *p != '\r' && *p != '\n'; ) {
1132
        if (av_strncasecmp(p, "Pragma:", 7) == 0) {
1133
            const char *q = p + 7;
1134
 
1135
            while (*q && *q != '\n' && av_isspace(*q))
1136
                q++;
1137
 
1138
            if (av_strncasecmp(q, "stream-switch-entry=", 20) == 0) {
1139
                int stream_no;
1140
                int rate_no;
1141
 
1142
                q += 20;
1143
 
1144
                memset(rates, 0xff, ratelen);
1145
 
1146
                while (1) {
1147
                    while (*q && *q != '\n' && *q != ':')
1148
                        q++;
1149
 
1150
                    if (sscanf(q, ":%d:%d", &stream_no, &rate_no) != 2)
1151
                        break;
1152
 
1153
                    stream_no--;
1154
                    if (stream_no < ratelen && stream_no >= 0)
1155
                        rates[stream_no] = rate_no;
1156
 
1157
                    while (*q && *q != '\n' && !av_isspace(*q))
1158
                        q++;
1159
                }
1160
 
1161
                return 1;
1162
            }
1163
        }
1164
        p = strchr(p, '\n');
1165
        if (!p)
1166
            break;
1167
 
1168
        p++;
1169
    }
1170
 
1171
    return 0;
1172
}
1173
 
1174
static int find_stream_in_feed(FFStream *feed, AVCodecContext *codec, int bit_rate)
1175
{
1176
    int i;
1177
    int best_bitrate = 100000000;
1178
    int best = -1;
1179
 
1180
    for (i = 0; i < feed->nb_streams; i++) {
1181
        AVCodecContext *feed_codec = feed->streams[i]->codec;
1182
 
1183
        if (feed_codec->codec_id != codec->codec_id ||
1184
            feed_codec->sample_rate != codec->sample_rate ||
1185
            feed_codec->width != codec->width ||
1186
            feed_codec->height != codec->height)
1187
            continue;
1188
 
1189
        /* Potential stream */
1190
 
1191
        /* We want the fastest stream less than bit_rate, or the slowest
1192
         * faster than bit_rate
1193
         */
1194
 
1195
        if (feed_codec->bit_rate <= bit_rate) {
1196
            if (best_bitrate > bit_rate || feed_codec->bit_rate > best_bitrate) {
1197
                best_bitrate = feed_codec->bit_rate;
1198
                best = i;
1199
            }
1200
        } else {
1201
            if (feed_codec->bit_rate < best_bitrate) {
1202
                best_bitrate = feed_codec->bit_rate;
1203
                best = i;
1204
            }
1205
        }
1206
    }
1207
 
1208
    return best;
1209
}
1210
 
1211
static int modify_current_stream(HTTPContext *c, char *rates)
1212
{
1213
    int i;
1214
    FFStream *req = c->stream;
1215
    int action_required = 0;
1216
 
1217
    /* Not much we can do for a feed */
1218
    if (!req->feed)
1219
        return 0;
1220
 
1221
    for (i = 0; i < req->nb_streams; i++) {
1222
        AVCodecContext *codec = req->streams[i]->codec;
1223
 
1224
        switch(rates[i]) {
1225
            case 0:
1226
                c->switch_feed_streams[i] = req->feed_streams[i];
1227
                break;
1228
            case 1:
1229
                c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 2);
1230
                break;
1231
            case 2:
1232
                /* Wants off or slow */
1233
                c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 4);
1234
#ifdef WANTS_OFF
1235
                /* This doesn't work well when it turns off the only stream! */
1236
                c->switch_feed_streams[i] = -2;
1237
                c->feed_streams[i] = -2;
1238
#endif
1239
                break;
1240
        }
1241
 
1242
        if (c->switch_feed_streams[i] >= 0 && c->switch_feed_streams[i] != c->feed_streams[i])
1243
            action_required = 1;
1244
    }
1245
 
1246
    return action_required;
1247
}
1248
 
1249
/* XXX: factorize in utils.c ? */
1250
/* XXX: take care with different space meaning */
1251
static void skip_spaces(const char **pp)
1252
{
1253
    const char *p;
1254
    p = *pp;
1255
    while (*p == ' ' || *p == '\t')
1256
        p++;
1257
    *pp = p;
1258
}
1259
 
1260
static void get_word(char *buf, int buf_size, const char **pp)
1261
{
1262
    const char *p;
1263
    char *q;
1264
 
1265
    p = *pp;
1266
    skip_spaces(&p);
1267
    q = buf;
1268
    while (!av_isspace(*p) && *p != '\0') {
1269
        if ((q - buf) < buf_size - 1)
1270
            *q++ = *p;
1271
        p++;
1272
    }
1273
    if (buf_size > 0)
1274
        *q = '\0';
1275
    *pp = p;
1276
}
1277
 
1278
static void get_arg(char *buf, int buf_size, const char **pp)
1279
{
1280
    const char *p;
1281
    char *q;
1282
    int quote;
1283
 
1284
    p = *pp;
1285
    while (av_isspace(*p)) p++;
1286
    q = buf;
1287
    quote = 0;
1288
    if (*p == '\"' || *p == '\'')
1289
        quote = *p++;
1290
    for(;;) {
1291
        if (quote) {
1292
            if (*p == quote)
1293
                break;
1294
        } else {
1295
            if (av_isspace(*p))
1296
                break;
1297
        }
1298
        if (*p == '\0')
1299
            break;
1300
        if ((q - buf) < buf_size - 1)
1301
            *q++ = *p;
1302
        p++;
1303
    }
1304
    *q = '\0';
1305
    if (quote && *p == quote)
1306
        p++;
1307
    *pp = p;
1308
}
1309
 
1310
static void parse_acl_row(FFStream *stream, FFStream* feed, IPAddressACL *ext_acl,
1311
                         const char *p, const char *filename, int line_num)
1312
{
1313
    char arg[1024];
1314
    IPAddressACL acl;
1315
    int errors = 0;
1316
 
1317
    get_arg(arg, sizeof(arg), &p);
1318
    if (av_strcasecmp(arg, "allow") == 0)
1319
        acl.action = IP_ALLOW;
1320
    else if (av_strcasecmp(arg, "deny") == 0)
1321
        acl.action = IP_DENY;
1322
    else {
1323
        fprintf(stderr, "%s:%d: ACL action '%s' is not ALLOW or DENY\n",
1324
                filename, line_num, arg);
1325
        errors++;
1326
    }
1327
 
1328
    get_arg(arg, sizeof(arg), &p);
1329
 
1330
    if (resolve_host(&acl.first, arg) != 0) {
1331
        fprintf(stderr, "%s:%d: ACL refers to invalid host or ip address '%s'\n",
1332
                filename, line_num, arg);
1333
        errors++;
1334
    } else
1335
        acl.last = acl.first;
1336
 
1337
    get_arg(arg, sizeof(arg), &p);
1338
 
1339
    if (arg[0]) {
1340
        if (resolve_host(&acl.last, arg) != 0) {
1341
            fprintf(stderr, "%s:%d: ACL refers to invalid host or ip address '%s'\n",
1342
                    filename, line_num, arg);
1343
            errors++;
1344
        }
1345
    }
1346
 
1347
    if (!errors) {
1348
        IPAddressACL *nacl = av_mallocz(sizeof(*nacl));
1349
        IPAddressACL **naclp = 0;
1350
 
1351
        acl.next = 0;
1352
        *nacl = acl;
1353
 
1354
        if (stream)
1355
            naclp = &stream->acl;
1356
        else if (feed)
1357
            naclp = &feed->acl;
1358
        else if (ext_acl)
1359
            naclp = &ext_acl;
1360
        else {
1361
            fprintf(stderr, "%s:%d: ACL found not in  or \n",
1362
                    filename, line_num);
1363
            errors++;
1364
        }
1365
 
1366
        if (naclp) {
1367
            while (*naclp)
1368
                naclp = &(*naclp)->next;
1369
 
1370
            *naclp = nacl;
1371
        }
1372
    }
1373
}
1374
 
1375
 
1376
static IPAddressACL* parse_dynamic_acl(FFStream *stream, HTTPContext *c)
1377
{
1378
    FILE* f;
1379
    char line[1024];
1380
    char  cmd[1024];
1381
    IPAddressACL *acl = NULL;
1382
    int line_num = 0;
1383
    const char *p;
1384
 
1385
    f = fopen(stream->dynamic_acl, "r");
1386
    if (!f) {
1387
        perror(stream->dynamic_acl);
1388
        return NULL;
1389
    }
1390
 
1391
    acl = av_mallocz(sizeof(IPAddressACL));
1392
 
1393
    /* Build ACL */
1394
    for(;;) {
1395
        if (fgets(line, sizeof(line), f) == NULL)
1396
            break;
1397
        line_num++;
1398
        p = line;
1399
        while (av_isspace(*p))
1400
            p++;
1401
        if (*p == '\0' || *p == '#')
1402
            continue;
1403
        get_arg(cmd, sizeof(cmd), &p);
1404
 
1405
        if (!av_strcasecmp(cmd, "ACL"))
1406
            parse_acl_row(NULL, NULL, acl, p, stream->dynamic_acl, line_num);
1407
    }
1408
    fclose(f);
1409
    return acl;
1410
}
1411
 
1412
 
1413
static void free_acl_list(IPAddressACL *in_acl)
1414
{
1415
    IPAddressACL *pacl,*pacl2;
1416
 
1417
    pacl = in_acl;
1418
    while(pacl) {
1419
        pacl2 = pacl;
1420
        pacl = pacl->next;
1421
        av_freep(pacl2);
1422
    }
1423
}
1424
 
1425
static int validate_acl_list(IPAddressACL *in_acl, HTTPContext *c)
1426
{
1427
    enum IPAddressAction last_action = IP_DENY;
1428
    IPAddressACL *acl;
1429
    struct in_addr *src = &c->from_addr.sin_addr;
1430
    unsigned long src_addr = src->s_addr;
1431
 
1432
    for (acl = in_acl; acl; acl = acl->next) {
1433
        if (src_addr >= acl->first.s_addr && src_addr <= acl->last.s_addr)
1434
            return (acl->action == IP_ALLOW) ? 1 : 0;
1435
        last_action = acl->action;
1436
    }
1437
 
1438
    /* Nothing matched, so return not the last action */
1439
    return (last_action == IP_DENY) ? 1 : 0;
1440
}
1441
 
1442
static int validate_acl(FFStream *stream, HTTPContext *c)
1443
{
1444
    int ret = 0;
1445
    IPAddressACL *acl;
1446
 
1447
 
1448
    /* if stream->acl is null validate_acl_list will return 1 */
1449
    ret = validate_acl_list(stream->acl, c);
1450
 
1451
    if (stream->dynamic_acl[0]) {
1452
        acl = parse_dynamic_acl(stream, c);
1453
 
1454
        ret = validate_acl_list(acl, c);
1455
 
1456
        free_acl_list(acl);
1457
    }
1458
 
1459
    return ret;
1460
}
1461
 
1462
/* compute the real filename of a file by matching it without its
1463
   extensions to all the stream filenames */
1464
static void compute_real_filename(char *filename, int max_size)
1465
{
1466
    char file1[1024];
1467
    char file2[1024];
1468
    char *p;
1469
    FFStream *stream;
1470
 
1471
    /* compute filename by matching without the file extensions */
1472
    av_strlcpy(file1, filename, sizeof(file1));
1473
    p = strrchr(file1, '.');
1474
    if (p)
1475
        *p = '\0';
1476
    for(stream = first_stream; stream != NULL; stream = stream->next) {
1477
        av_strlcpy(file2, stream->filename, sizeof(file2));
1478
        p = strrchr(file2, '.');
1479
        if (p)
1480
            *p = '\0';
1481
        if (!strcmp(file1, file2)) {
1482
            av_strlcpy(filename, stream->filename, max_size);
1483
            break;
1484
        }
1485
    }
1486
}
1487
 
1488
enum RedirType {
1489
    REDIR_NONE,
1490
    REDIR_ASX,
1491
    REDIR_RAM,
1492
    REDIR_ASF,
1493
    REDIR_RTSP,
1494
    REDIR_SDP,
1495
};
1496
 
1497
/* parse http request and prepare header */
1498
static int http_parse_request(HTTPContext *c)
1499
{
1500
    const char *p;
1501
    char *p1;
1502
    enum RedirType redir_type;
1503
    char cmd[32];
1504
    char info[1024], filename[1024];
1505
    char url[1024], *q;
1506
    char protocol[32];
1507
    char msg[1024];
1508
    const char *mime_type;
1509
    FFStream *stream;
1510
    int i;
1511
    char ratebuf[32];
1512
    const char *useragent = 0;
1513
 
1514
    p = c->buffer;
1515
    get_word(cmd, sizeof(cmd), &p);
1516
    av_strlcpy(c->method, cmd, sizeof(c->method));
1517
 
1518
    if (!strcmp(cmd, "GET"))
1519
        c->post = 0;
1520
    else if (!strcmp(cmd, "POST"))
1521
        c->post = 1;
1522
    else
1523
        return -1;
1524
 
1525
    get_word(url, sizeof(url), &p);
1526
    av_strlcpy(c->url, url, sizeof(c->url));
1527
 
1528
    get_word(protocol, sizeof(protocol), (const char **)&p);
1529
    if (strcmp(protocol, "HTTP/1.0") && strcmp(protocol, "HTTP/1.1"))
1530
        return -1;
1531
 
1532
    av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
1533
 
1534
    if (ffserver_debug)
1535
        http_log("%s - - New connection: %s %s\n", inet_ntoa(c->from_addr.sin_addr), cmd, url);
1536
 
1537
    /* find the filename and the optional info string in the request */
1538
    p1 = strchr(url, '?');
1539
    if (p1) {
1540
        av_strlcpy(info, p1, sizeof(info));
1541
        *p1 = '\0';
1542
    } else
1543
        info[0] = '\0';
1544
 
1545
    av_strlcpy(filename, url + ((*url == '/') ? 1 : 0), sizeof(filename)-1);
1546
 
1547
    for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1548
        if (av_strncasecmp(p, "User-Agent:", 11) == 0) {
1549
            useragent = p + 11;
1550
            if (*useragent && *useragent != '\n' && av_isspace(*useragent))
1551
                useragent++;
1552
            break;
1553
        }
1554
        p = strchr(p, '\n');
1555
        if (!p)
1556
            break;
1557
 
1558
        p++;
1559
    }
1560
 
1561
    redir_type = REDIR_NONE;
1562
    if (av_match_ext(filename, "asx")) {
1563
        redir_type = REDIR_ASX;
1564
        filename[strlen(filename)-1] = 'f';
1565
    } else if (av_match_ext(filename, "asf") &&
1566
        (!useragent || av_strncasecmp(useragent, "NSPlayer", 8) != 0)) {
1567
        /* if this isn't WMP or lookalike, return the redirector file */
1568
        redir_type = REDIR_ASF;
1569
    } else if (av_match_ext(filename, "rpm,ram")) {
1570
        redir_type = REDIR_RAM;
1571
        strcpy(filename + strlen(filename)-2, "m");
1572
    } else if (av_match_ext(filename, "rtsp")) {
1573
        redir_type = REDIR_RTSP;
1574
        compute_real_filename(filename, sizeof(filename) - 1);
1575
    } else if (av_match_ext(filename, "sdp")) {
1576
        redir_type = REDIR_SDP;
1577
        compute_real_filename(filename, sizeof(filename) - 1);
1578
    }
1579
 
1580
    // "redirect" / request to index.html
1581
    if (!strlen(filename))
1582
        av_strlcpy(filename, "index.html", sizeof(filename) - 1);
1583
 
1584
    stream = first_stream;
1585
    while (stream != NULL) {
1586
        if (!strcmp(stream->filename, filename) && validate_acl(stream, c))
1587
            break;
1588
        stream = stream->next;
1589
    }
1590
    if (stream == NULL) {
1591
        snprintf(msg, sizeof(msg), "File '%s' not found", url);
1592
        http_log("File '%s' not found\n", url);
1593
        goto send_error;
1594
    }
1595
 
1596
    c->stream = stream;
1597
    memcpy(c->feed_streams, stream->feed_streams, sizeof(c->feed_streams));
1598
    memset(c->switch_feed_streams, -1, sizeof(c->switch_feed_streams));
1599
 
1600
    if (stream->stream_type == STREAM_TYPE_REDIRECT) {
1601
        c->http_error = 301;
1602
        q = c->buffer;
1603
        snprintf(q, c->buffer_size,
1604
                      "HTTP/1.0 301 Moved\r\n"
1605
                      "Location: %s\r\n"
1606
                      "Content-type: text/html\r\n"
1607
                      "\r\n"
1608
                      "Moved\r\n"
1609
                      "You should be redirected.\r\n"
1610
                      "\r\n", stream->feed_filename, stream->feed_filename);
1611
        q += strlen(q);
1612
        /* prepare output buffer */
1613
        c->buffer_ptr = c->buffer;
1614
        c->buffer_end = q;
1615
        c->state = HTTPSTATE_SEND_HEADER;
1616
        return 0;
1617
    }
1618
 
1619
    /* If this is WMP, get the rate information */
1620
    if (extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
1621
        if (modify_current_stream(c, ratebuf)) {
1622
            for (i = 0; i < FF_ARRAY_ELEMS(c->feed_streams); i++) {
1623
                if (c->switch_feed_streams[i] >= 0)
1624
                    c->switch_feed_streams[i] = -1;
1625
            }
1626
        }
1627
    }
1628
 
1629
    if (c->post == 0 && stream->stream_type == STREAM_TYPE_LIVE)
1630
        current_bandwidth += stream->bandwidth;
1631
 
1632
    /* If already streaming this feed, do not let start another feeder. */
1633
    if (stream->feed_opened) {
1634
        snprintf(msg, sizeof(msg), "This feed is already being received.");
1635
        http_log("Feed '%s' already being received\n", stream->feed_filename);
1636
        goto send_error;
1637
    }
1638
 
1639
    if (c->post == 0 && max_bandwidth < current_bandwidth) {
1640
        c->http_error = 503;
1641
        q = c->buffer;
1642
        snprintf(q, c->buffer_size,
1643
                      "HTTP/1.0 503 Server too busy\r\n"
1644
                      "Content-type: text/html\r\n"
1645
                      "\r\n"
1646
                      "Too busy\r\n"
1647
                      "

The server is too busy to serve your request at this time.

\r\n"
1648
                      "

The bandwidth being served (including your stream) is %"PRIu64"kbit/sec, "

1649
                      "and this exceeds the limit of %"PRIu64"kbit/sec.

\r\n"
1650
                      "\r\n", current_bandwidth, max_bandwidth);
1651
        q += strlen(q);
1652
        /* prepare output buffer */
1653
        c->buffer_ptr = c->buffer;
1654
        c->buffer_end = q;
1655
        c->state = HTTPSTATE_SEND_HEADER;
1656
        return 0;
1657
    }
1658
 
1659
    if (redir_type != REDIR_NONE) {
1660
        const char *hostinfo = 0;
1661
 
1662
        for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1663
            if (av_strncasecmp(p, "Host:", 5) == 0) {
1664
                hostinfo = p + 5;
1665
                break;
1666
            }
1667
            p = strchr(p, '\n');
1668
            if (!p)
1669
                break;
1670
 
1671
            p++;
1672
        }
1673
 
1674
        if (hostinfo) {
1675
            char *eoh;
1676
            char hostbuf[260];
1677
 
1678
            while (av_isspace(*hostinfo))
1679
                hostinfo++;
1680
 
1681
            eoh = strchr(hostinfo, '\n');
1682
            if (eoh) {
1683
                if (eoh[-1] == '\r')
1684
                    eoh--;
1685
 
1686
                if (eoh - hostinfo < sizeof(hostbuf) - 1) {
1687
                    memcpy(hostbuf, hostinfo, eoh - hostinfo);
1688
                    hostbuf[eoh - hostinfo] = 0;
1689
 
1690
                    c->http_error = 200;
1691
                    q = c->buffer;
1692
                    switch(redir_type) {
1693
                    case REDIR_ASX:
1694
                        snprintf(q, c->buffer_size,
1695
                                      "HTTP/1.0 200 ASX Follows\r\n"
1696
                                      "Content-type: video/x-ms-asf\r\n"
1697
                                      "\r\n"
1698
                                      "\r\n"
1699
                                      //"\r\n"
1700
                                      "\r\n"
1701
                                      "\r\n", hostbuf, filename, info);
1702
                        q += strlen(q);
1703
                        break;
1704
                    case REDIR_RAM:
1705
                        snprintf(q, c->buffer_size,
1706
                                      "HTTP/1.0 200 RAM Follows\r\n"
1707
                                      "Content-type: audio/x-pn-realaudio\r\n"
1708
                                      "\r\n"
1709
                                      "# Autogenerated by ffserver\r\n"
1710
                                      "http://%s/%s%s\r\n", hostbuf, filename, info);
1711
                        q += strlen(q);
1712
                        break;
1713
                    case REDIR_ASF:
1714
                        snprintf(q, c->buffer_size,
1715
                                      "HTTP/1.0 200 ASF Redirect follows\r\n"
1716
                                      "Content-type: video/x-ms-asf\r\n"
1717
                                      "\r\n"
1718
                                      "[Reference]\r\n"
1719
                                      "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info);
1720
                        q += strlen(q);
1721
                        break;
1722
                    case REDIR_RTSP:
1723
                        {
1724
                            char hostname[256], *p;
1725
                            /* extract only hostname */
1726
                            av_strlcpy(hostname, hostbuf, sizeof(hostname));
1727
                            p = strrchr(hostname, ':');
1728
                            if (p)
1729
                                *p = '\0';
1730
                            snprintf(q, c->buffer_size,
1731
                                          "HTTP/1.0 200 RTSP Redirect follows\r\n"
1732
                                          /* XXX: incorrect mime type ? */
1733
                                          "Content-type: application/x-rtsp\r\n"
1734
                                          "\r\n"
1735
                                          "rtsp://%s:%d/%s\r\n", hostname, ntohs(my_rtsp_addr.sin_port), filename);
1736
                            q += strlen(q);
1737
                        }
1738
                        break;
1739
                    case REDIR_SDP:
1740
                        {
1741
                            uint8_t *sdp_data;
1742
                            int sdp_data_size;
1743
                            socklen_t len;
1744
                            struct sockaddr_in my_addr;
1745
 
1746
                            snprintf(q, c->buffer_size,
1747
                                          "HTTP/1.0 200 OK\r\n"
1748
                                          "Content-type: application/sdp\r\n"
1749
                                          "\r\n");
1750
                            q += strlen(q);
1751
 
1752
                            len = sizeof(my_addr);
1753
                            getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
1754
 
1755
                            /* XXX: should use a dynamic buffer */
1756
                            sdp_data_size = prepare_sdp_description(stream,
1757
                                                                    &sdp_data,
1758
                                                                    my_addr.sin_addr);
1759
                            if (sdp_data_size > 0) {
1760
                                memcpy(q, sdp_data, sdp_data_size);
1761
                                q += sdp_data_size;
1762
                                *q = '\0';
1763
                                av_free(sdp_data);
1764
                            }
1765
                        }
1766
                        break;
1767
                    default:
1768
                        abort();
1769
                        break;
1770
                    }
1771
 
1772
                    /* prepare output buffer */
1773
                    c->buffer_ptr = c->buffer;
1774
                    c->buffer_end = q;
1775
                    c->state = HTTPSTATE_SEND_HEADER;
1776
                    return 0;
1777
                }
1778
            }
1779
        }
1780
 
1781
        snprintf(msg, sizeof(msg), "ASX/RAM file not handled");
1782
        goto send_error;
1783
    }
1784
 
1785
    stream->conns_served++;
1786
 
1787
    /* XXX: add there authenticate and IP match */
1788
 
1789
    if (c->post) {
1790
        /* if post, it means a feed is being sent */
1791
        if (!stream->is_feed) {
1792
            /* However it might be a status report from WMP! Let us log the
1793
             * data as it might come in handy one day. */
1794
            const char *logline = 0;
1795
            int client_id = 0;
1796
 
1797
            for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1798
                if (av_strncasecmp(p, "Pragma: log-line=", 17) == 0) {
1799
                    logline = p;
1800
                    break;
1801
                }
1802
                if (av_strncasecmp(p, "Pragma: client-id=", 18) == 0)
1803
                    client_id = strtol(p + 18, 0, 10);
1804
                p = strchr(p, '\n');
1805
                if (!p)
1806
                    break;
1807
 
1808
                p++;
1809
            }
1810
 
1811
            if (logline) {
1812
                char *eol = strchr(logline, '\n');
1813
 
1814
                logline += 17;
1815
 
1816
                if (eol) {
1817
                    if (eol[-1] == '\r')
1818
                        eol--;
1819
                    http_log("%.*s\n", (int) (eol - logline), logline);
1820
                    c->suppress_log = 1;
1821
                }
1822
            }
1823
 
1824
#ifdef DEBUG
1825
            http_log("\nGot request:\n%s\n", c->buffer);
1826
#endif
1827
 
1828
            if (client_id && extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
1829
                HTTPContext *wmpc;
1830
 
1831
                /* Now we have to find the client_id */
1832
                for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->next) {
1833
                    if (wmpc->wmp_client_id == client_id)
1834
                        break;
1835
                }
1836
 
1837
                if (wmpc && modify_current_stream(wmpc, ratebuf))
1838
                    wmpc->switch_pending = 1;
1839
            }
1840
 
1841
            snprintf(msg, sizeof(msg), "POST command not handled");
1842
            c->stream = 0;
1843
            goto send_error;
1844
        }
1845
        if (http_start_receive_data(c) < 0) {
1846
            snprintf(msg, sizeof(msg), "could not open feed");
1847
            goto send_error;
1848
        }
1849
        c->http_error = 0;
1850
        c->state = HTTPSTATE_RECEIVE_DATA;
1851
        return 0;
1852
    }
1853
 
1854
#ifdef DEBUG
1855
    if (strcmp(stream->filename + strlen(stream->filename) - 4, ".asf") == 0)
1856
        http_log("\nGot request:\n%s\n", c->buffer);
1857
#endif
1858
 
1859
    if (c->stream->stream_type == STREAM_TYPE_STATUS)
1860
        goto send_status;
1861
 
1862
    /* open input stream */
1863
    if (open_input_stream(c, info) < 0) {
1864
        snprintf(msg, sizeof(msg), "Input stream corresponding to '%s' not found", url);
1865
        goto send_error;
1866
    }
1867
 
1868
    /* prepare http header */
1869
    c->buffer[0] = 0;
1870
    av_strlcatf(c->buffer, c->buffer_size, "HTTP/1.0 200 OK\r\n");
1871
    mime_type = c->stream->fmt->mime_type;
1872
    if (!mime_type)
1873
        mime_type = "application/x-octet-stream";
1874
    av_strlcatf(c->buffer, c->buffer_size, "Pragma: no-cache\r\n");
1875
 
1876
    /* for asf, we need extra headers */
1877
    if (!strcmp(c->stream->fmt->name,"asf_stream")) {
1878
        /* Need to allocate a client id */
1879
 
1880
        c->wmp_client_id = av_lfg_get(&random_state);
1881
 
1882
        av_strlcatf(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);
1883
    }
1884
    av_strlcatf(c->buffer, c->buffer_size, "Content-Type: %s\r\n", mime_type);
1885
    av_strlcatf(c->buffer, c->buffer_size, "\r\n");
1886
    q = c->buffer + strlen(c->buffer);
1887
 
1888
    /* prepare output buffer */
1889
    c->http_error = 0;
1890
    c->buffer_ptr = c->buffer;
1891
    c->buffer_end = q;
1892
    c->state = HTTPSTATE_SEND_HEADER;
1893
    return 0;
1894
 send_error:
1895
    c->http_error = 404;
1896
    q = c->buffer;
1897
    htmlstrip(msg);
1898
    snprintf(q, c->buffer_size,
1899
                  "HTTP/1.0 404 Not Found\r\n"
1900
                  "Content-type: text/html\r\n"
1901
                  "\r\n"
1902
                  "\n"
1903
                  "404 Not Found\n"
1904
                  "%s\n"
1905
                  "\n", msg);
1906
    q += strlen(q);
1907
    /* prepare output buffer */
1908
    c->buffer_ptr = c->buffer;
1909
    c->buffer_end = q;
1910
    c->state = HTTPSTATE_SEND_HEADER;
1911
    return 0;
1912
 send_status:
1913
    compute_status(c);
1914
    c->http_error = 200; /* horrible : we use this value to avoid
1915
                            going to the send data state */
1916
    c->state = HTTPSTATE_SEND_HEADER;
1917
    return 0;
1918
}
1919
 
1920
static void fmt_bytecount(AVIOContext *pb, int64_t count)
1921
{
1922
    static const char suffix[] = " kMGTP";
1923
    const char *s;
1924
 
1925
    for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++);
1926
 
1927
    avio_printf(pb, "%"PRId64"%c", count, *s);
1928
}
1929
 
1930
static void compute_status(HTTPContext *c)
1931
{
1932
    HTTPContext *c1;
1933
    FFStream *stream;
1934
    char *p;
1935
    time_t ti;
1936
    int i, len;
1937
    AVIOContext *pb;
1938
 
1939
    if (avio_open_dyn_buf(&pb) < 0) {
1940
        /* XXX: return an error ? */
1941
        c->buffer_ptr = c->buffer;
1942
        c->buffer_end = c->buffer;
1943
        return;
1944
    }
1945
 
1946
    avio_printf(pb, "HTTP/1.0 200 OK\r\n");
1947
    avio_printf(pb, "Content-type: %s\r\n", "text/html");
1948
    avio_printf(pb, "Pragma: no-cache\r\n");
1949
    avio_printf(pb, "\r\n");
1950
 
1951
    avio_printf(pb, "%s Status\n", program_name);
1952
    if (c->stream->feed_filename[0])
1953
        avio_printf(pb, "\n", c->stream->feed_filename);
1954
    avio_printf(pb, "\n");
1955
    avio_printf(pb, "

%s Status

\n", program_name);
1956
    /* format status */
1957
    avio_printf(pb, "

Available Streams

\n");
1958
    avio_printf(pb, "\n");
1959
    avio_printf(pb, "
PathServed
Conns

bytes
FormatBit rate
kbits/s
Video
kbits/s

Codec
Audio
kbits/s

Codec
Feed\n");
1960
    stream = first_stream;
1961
    while (stream != NULL) {
1962
        char sfilename[1024];
1963
        char *eosf;
1964
 
1965
        if (stream->feed != stream) {
1966
            av_strlcpy(sfilename, stream->filename, sizeof(sfilename) - 10);
1967
            eosf = sfilename + strlen(sfilename);
1968
            if (eosf - sfilename >= 4) {
1969
                if (strcmp(eosf - 4, ".asf") == 0)
1970
                    strcpy(eosf - 4, ".asx");
1971
                else if (strcmp(eosf - 3, ".rm") == 0)
1972
                    strcpy(eosf - 3, ".ram");
1973
                else if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
1974
                    /* generate a sample RTSP director if
1975
                       unicast. Generate an SDP redirector if
1976
                       multicast */
1977
                    eosf = strrchr(sfilename, '.');
1978
                    if (!eosf)
1979
                        eosf = sfilename + strlen(sfilename);
1980
                    if (stream->is_multicast)
1981
                        strcpy(eosf, ".sdp");
1982
                    else
1983
                        strcpy(eosf, ".rtsp");
1984
                }
1985
            }
1986
 
1987
            avio_printf(pb, "
%s ",
1988
                         sfilename, stream->filename);
1989
            avio_printf(pb, "
%d ",
1990
                        stream->conns_served);
1991
            fmt_bytecount(pb, stream->bytes_served);
1992
            switch(stream->stream_type) {
1993
            case STREAM_TYPE_LIVE: {
1994
                    int audio_bit_rate = 0;
1995
                    int video_bit_rate = 0;
1996
                    const char *audio_codec_name = "";
1997
                    const char *video_codec_name = "";
1998
                    const char *audio_codec_name_extra = "";
1999
                    const char *video_codec_name_extra = "";
2000
 
2001
                    for(i=0;inb_streams;i++) {
2002
                        AVStream *st = stream->streams[i];
2003
                        AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
2004
                        switch(st->codec->codec_type) {
2005
                        case AVMEDIA_TYPE_AUDIO:
2006
                            audio_bit_rate += st->codec->bit_rate;
2007
                            if (codec) {
2008
                                if (*audio_codec_name)
2009
                                    audio_codec_name_extra = "...";
2010
                                audio_codec_name = codec->name;
2011
                            }
2012
                            break;
2013
                        case AVMEDIA_TYPE_VIDEO:
2014
                            video_bit_rate += st->codec->bit_rate;
2015
                            if (codec) {
2016
                                if (*video_codec_name)
2017
                                    video_codec_name_extra = "...";
2018
                                video_codec_name = codec->name;
2019
                            }
2020
                            break;
2021
                        case AVMEDIA_TYPE_DATA:
2022
                            video_bit_rate += st->codec->bit_rate;
2023
                            break;
2024
                        default:
2025
                            abort();
2026
                        }
2027
                    }
2028
                    avio_printf(pb, "
%s %d %d %s %s %d %s %s",
2029
                                 stream->fmt->name,
2030
                                 stream->bandwidth,
2031
                                 video_bit_rate / 1000, video_codec_name, video_codec_name_extra,
2032
                                 audio_bit_rate / 1000, audio_codec_name, audio_codec_name_extra);
2033
                    if (stream->feed)
2034
                        avio_printf(pb, "
%s", stream->feed->filename);
2035
                    else
2036
                        avio_printf(pb, "
%s", stream->feed_filename);
2037
                    avio_printf(pb, "\n");
2038
                }
2039
                break;
2040
            default:
2041
                avio_printf(pb, "
- - - - \n");
2042
                break;
2043
            }
2044
        }
2045
        stream = stream->next;
2046
    }
2047
    avio_printf(pb, "
\n");
2048
 
2049
    stream = first_stream;
2050
    while (stream != NULL) {
2051
        if (stream->feed == stream) {
2052
            avio_printf(pb, "

Feed %s

", stream->filename);
2053
            if (stream->pid) {
2054
                avio_printf(pb, "Running as pid %d.\n", stream->pid);
2055
 
2056
#if defined(linux)
2057
                {
2058
                    FILE *pid_stat;
2059
                    char ps_cmd[64];
2060
 
2061
                    /* This is somewhat linux specific I guess */
2062
                    snprintf(ps_cmd, sizeof(ps_cmd),
2063
                             "ps -o \"%%cpu,cputime\" --no-headers %d",
2064
                             stream->pid);
2065
 
2066
                    pid_stat = popen(ps_cmd, "r");
2067
                    if (pid_stat) {
2068
                        char cpuperc[10];
2069
                        char cpuused[64];
2070
 
2071
                        if (fscanf(pid_stat, "%9s %63s", cpuperc,
2072
                                   cpuused) == 2) {
2073
                            avio_printf(pb, "Currently using %s%% of the cpu. Total time used %s.\n",
2074
                                         cpuperc, cpuused);
2075
                        }
2076
                        fclose(pid_stat);
2077
                    }
2078
                }
2079
#endif
2080
 
2081
                avio_printf(pb, "

");

2082
            }
2083
            avio_printf(pb, "
Streamtypekbits/scodecParameters\n");
2084
 
2085
            for (i = 0; i < stream->nb_streams; i++) {
2086
                AVStream *st = stream->streams[i];
2087
                AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
2088
                const char *type = "unknown";
2089
                char parameters[64];
2090
 
2091
                parameters[0] = 0;
2092
 
2093
                switch(st->codec->codec_type) {
2094
                case AVMEDIA_TYPE_AUDIO:
2095
                    type = "audio";
2096
                    snprintf(parameters, sizeof(parameters), "%d channel(s), %d Hz", st->codec->channels, st->codec->sample_rate);
2097
                    break;
2098
                case AVMEDIA_TYPE_VIDEO:
2099
                    type = "video";
2100
                    snprintf(parameters, sizeof(parameters), "%dx%d, q=%d-%d, fps=%d", st->codec->width, st->codec->height,
2101
                                st->codec->qmin, st->codec->qmax, st->codec->time_base.den / st->codec->time_base.num);
2102
                    break;
2103
                default:
2104
                    abort();
2105
                }
2106
                avio_printf(pb, "
%d%s%d%s%s\n",
2107
                        i, type, st->codec->bit_rate/1000, codec ? codec->name : "", parameters);
2108
            }
2109
            avio_printf(pb, "
\n");
2110
 
2111
        }
2112
        stream = stream->next;
2113
    }
2114
 
2115
    /* connection status */
2116
    avio_printf(pb, "

Connection Status

\n");
2117
 
2118
    avio_printf(pb, "Number of connections: %d / %d
\n",
2119
                 nb_connections, nb_max_connections);
2120
 
2121
    avio_printf(pb, "Bandwidth in use: %"PRIu64"k / %"PRIu64"k
\n",
2122
                 current_bandwidth, max_bandwidth);
2123
 
2124
    avio_printf(pb, "\n");
2125
    avio_printf(pb, "
#FileIPProtoStateTarget bits/secActual bits/secBytes transferred\n");
2126
    c1 = first_http_ctx;
2127
    i = 0;
2128
    while (c1 != NULL) {
2129
        int bitrate;
2130
        int j;
2131
 
2132
        bitrate = 0;
2133
        if (c1->stream) {
2134
            for (j = 0; j < c1->stream->nb_streams; j++) {
2135
                if (!c1->stream->feed)
2136
                    bitrate += c1->stream->streams[j]->codec->bit_rate;
2137
                else if (c1->feed_streams[j] >= 0)
2138
                    bitrate += c1->stream->feed->streams[c1->feed_streams[j]]->codec->bit_rate;
2139
            }
2140
        }
2141
 
2142
        i++;
2143
        p = inet_ntoa(c1->from_addr.sin_addr);
2144
        avio_printf(pb, "
%d%s%s%s%s%s",
2145
                    i,
2146
                    c1->stream ? c1->stream->filename : "",
2147
                    c1->state == HTTPSTATE_RECEIVE_DATA ? "(input)" : "",
2148
                    p,
2149
                    c1->protocol,
2150
                    http_state[c1->state]);
2151
        fmt_bytecount(pb, bitrate);
2152
        avio_printf(pb, "
");
2153
        fmt_bytecount(pb, compute_datarate(&c1->datarate, c1->data_count) * 8);
2154
        avio_printf(pb, "
");
2155
        fmt_bytecount(pb, c1->data_count);
2156
        avio_printf(pb, "\n");
2157
        c1 = c1->next;
2158
    }
2159
    avio_printf(pb, "
\n");
2160
 
2161
    /* date */
2162
    ti = time(NULL);
2163
    p = ctime(&ti);
2164
    avio_printf(pb, "
Generated at %s", p);
2165
    avio_printf(pb, "\n\n");
2166
 
2167
    len = avio_close_dyn_buf(pb, &c->pb_buffer);
2168
    c->buffer_ptr = c->pb_buffer;
2169
    c->buffer_end = c->pb_buffer + len;
2170
}
2171
 
2172
static int open_input_stream(HTTPContext *c, const char *info)
2173
{
2174
    char buf[128];
2175
    char input_filename[1024];
2176
    AVFormatContext *s = NULL;
2177
    int buf_size, i, ret;
2178
    int64_t stream_pos;
2179
 
2180
    /* find file name */
2181
    if (c->stream->feed) {
2182
        strcpy(input_filename, c->stream->feed->feed_filename);
2183
        buf_size = FFM_PACKET_SIZE;
2184
        /* compute position (absolute time) */
2185
        if (av_find_info_tag(buf, sizeof(buf), "date", info)) {
2186
            if ((ret = av_parse_time(&stream_pos, buf, 0)) < 0)
2187
                return ret;
2188
        } else if (av_find_info_tag(buf, sizeof(buf), "buffer", info)) {
2189
            int prebuffer = strtol(buf, 0, 10);
2190
            stream_pos = av_gettime() - prebuffer * (int64_t)1000000;
2191
        } else
2192
            stream_pos = av_gettime() - c->stream->prebuffer * (int64_t)1000;
2193
    } else {
2194
        strcpy(input_filename, c->stream->feed_filename);
2195
        buf_size = 0;
2196
        /* compute position (relative time) */
2197
        if (av_find_info_tag(buf, sizeof(buf), "date", info)) {
2198
            if ((ret = av_parse_time(&stream_pos, buf, 1)) < 0)
2199
                return ret;
2200
        } else
2201
            stream_pos = 0;
2202
    }
2203
    if (input_filename[0] == '\0')
2204
        return -1;
2205
 
2206
    /* open stream */
2207
    if ((ret = avformat_open_input(&s, input_filename, c->stream->ifmt, &c->stream->in_opts)) < 0) {
2208
        http_log("could not open %s: %d\n", input_filename, ret);
2209
        return -1;
2210
    }
2211
 
2212
    /* set buffer size */
2213
    if (buf_size > 0) ffio_set_buf_size(s->pb, buf_size);
2214
 
2215
    s->flags |= AVFMT_FLAG_GENPTS;
2216
    c->fmt_in = s;
2217
    if (strcmp(s->iformat->name, "ffm") && avformat_find_stream_info(c->fmt_in, NULL) < 0) {
2218
        http_log("Could not find stream info '%s'\n", input_filename);
2219
        avformat_close_input(&s);
2220
        return -1;
2221
    }
2222
 
2223
    /* choose stream as clock source (we favorize video stream if
2224
       present) for packet sending */
2225
    c->pts_stream_index = 0;
2226
    for(i=0;istream->nb_streams;i++) {
2227
        if (c->pts_stream_index == 0 &&
2228
            c->stream->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
2229
            c->pts_stream_index = i;
2230
        }
2231
    }
2232
 
2233
    if (c->fmt_in->iformat->read_seek)
2234
        av_seek_frame(c->fmt_in, -1, stream_pos, 0);
2235
    /* set the start time (needed for maxtime and RTP packet timing) */
2236
    c->start_time = cur_time;
2237
    c->first_pts = AV_NOPTS_VALUE;
2238
    return 0;
2239
}
2240
 
2241
/* return the server clock (in us) */
2242
static int64_t get_server_clock(HTTPContext *c)
2243
{
2244
    /* compute current pts value from system time */
2245
    return (cur_time - c->start_time) * 1000;
2246
}
2247
 
2248
/* return the estimated time at which the current packet must be sent
2249
   (in us) */
2250
static int64_t get_packet_send_clock(HTTPContext *c)
2251
{
2252
    int bytes_left, bytes_sent, frame_bytes;
2253
 
2254
    frame_bytes = c->cur_frame_bytes;
2255
    if (frame_bytes <= 0)
2256
        return c->cur_pts;
2257
    else {
2258
        bytes_left = c->buffer_end - c->buffer_ptr;
2259
        bytes_sent = frame_bytes - bytes_left;
2260
        return c->cur_pts + (c->cur_frame_duration * bytes_sent) / frame_bytes;
2261
    }
2262
}
2263
 
2264
 
2265
static int http_prepare_data(HTTPContext *c)
2266
{
2267
    int i, len, ret;
2268
    AVFormatContext *ctx;
2269
 
2270
    av_freep(&c->pb_buffer);
2271
    switch(c->state) {
2272
    case HTTPSTATE_SEND_DATA_HEADER:
2273
        memset(&c->fmt_ctx, 0, sizeof(c->fmt_ctx));
2274
        av_dict_set(&c->fmt_ctx.metadata, "author"   , c->stream->author   , 0);
2275
        av_dict_set(&c->fmt_ctx.metadata, "comment"  , c->stream->comment  , 0);
2276
        av_dict_set(&c->fmt_ctx.metadata, "copyright", c->stream->copyright, 0);
2277
        av_dict_set(&c->fmt_ctx.metadata, "title"    , c->stream->title    , 0);
2278
 
2279
        c->fmt_ctx.streams = av_mallocz(sizeof(AVStream *) * c->stream->nb_streams);
2280
 
2281
        for(i=0;istream->nb_streams;i++) {
2282
            AVStream *src;
2283
            c->fmt_ctx.streams[i] = av_mallocz(sizeof(AVStream));
2284
            /* if file or feed, then just take streams from FFStream struct */
2285
            if (!c->stream->feed ||
2286
                c->stream->feed == c->stream)
2287
                src = c->stream->streams[i];
2288
            else
2289
                src = c->stream->feed->streams[c->stream->feed_streams[i]];
2290
 
2291
            *(c->fmt_ctx.streams[i]) = *src;
2292
            c->fmt_ctx.streams[i]->priv_data = 0;
2293
            c->fmt_ctx.streams[i]->codec->frame_number = 0; /* XXX: should be done in
2294
                                           AVStream, not in codec */
2295
        }
2296
        /* set output format parameters */
2297
        c->fmt_ctx.oformat = c->stream->fmt;
2298
        c->fmt_ctx.nb_streams = c->stream->nb_streams;
2299
 
2300
        c->got_key_frame = 0;
2301
 
2302
        /* prepare header and save header data in a stream */
2303
        if (avio_open_dyn_buf(&c->fmt_ctx.pb) < 0) {
2304
            /* XXX: potential leak */
2305
            return -1;
2306
        }
2307
        c->fmt_ctx.pb->seekable = 0;
2308
 
2309
        /*
2310
         * HACK to avoid mpeg ps muxer to spit many underflow errors
2311
         * Default value from FFmpeg
2312
         * Try to set it use configuration option
2313
         */
2314
        c->fmt_ctx.max_delay = (int)(0.7*AV_TIME_BASE);
2315
 
2316
        if (avformat_write_header(&c->fmt_ctx, NULL) < 0) {
2317
            http_log("Error writing output header\n");
2318
            return -1;
2319
        }
2320
        av_dict_free(&c->fmt_ctx.metadata);
2321
 
2322
        len = avio_close_dyn_buf(c->fmt_ctx.pb, &c->pb_buffer);
2323
        c->buffer_ptr = c->pb_buffer;
2324
        c->buffer_end = c->pb_buffer + len;
2325
 
2326
        c->state = HTTPSTATE_SEND_DATA;
2327
        c->last_packet_sent = 0;
2328
        break;
2329
    case HTTPSTATE_SEND_DATA:
2330
        /* find a new packet */
2331
        /* read a packet from the input stream */
2332
        if (c->stream->feed)
2333
            ffm_set_write_index(c->fmt_in,
2334
                                c->stream->feed->feed_write_index,
2335
                                c->stream->feed->feed_size);
2336
 
2337
        if (c->stream->max_time &&
2338
            c->stream->max_time + c->start_time - cur_time < 0)
2339
            /* We have timed out */
2340
            c->state = HTTPSTATE_SEND_DATA_TRAILER;
2341
        else {
2342
            AVPacket pkt;
2343
        redo:
2344
            ret = av_read_frame(c->fmt_in, &pkt);
2345
            if (ret < 0) {
2346
                if (c->stream->feed) {
2347
                    /* if coming from feed, it means we reached the end of the
2348
                       ffm file, so must wait for more data */
2349
                    c->state = HTTPSTATE_WAIT_FEED;
2350
                    return 1; /* state changed */
2351
                } else if (ret == AVERROR(EAGAIN)) {
2352
                    /* input not ready, come back later */
2353
                    return 0;
2354
                } else {
2355
                    if (c->stream->loop) {
2356
                        avformat_close_input(&c->fmt_in);
2357
                        if (open_input_stream(c, "") < 0)
2358
                            goto no_loop;
2359
                        goto redo;
2360
                    } else {
2361
                    no_loop:
2362
                        /* must send trailer now because eof or error */
2363
                        c->state = HTTPSTATE_SEND_DATA_TRAILER;
2364
                    }
2365
                }
2366
            } else {
2367
                int source_index = pkt.stream_index;
2368
                /* update first pts if needed */
2369
                if (c->first_pts == AV_NOPTS_VALUE) {
2370
                    c->first_pts = av_rescale_q(pkt.dts, c->fmt_in->streams[pkt.stream_index]->time_base, AV_TIME_BASE_Q);
2371
                    c->start_time = cur_time;
2372
                }
2373
                /* send it to the appropriate stream */
2374
                if (c->stream->feed) {
2375
                    /* if coming from a feed, select the right stream */
2376
                    if (c->switch_pending) {
2377
                        c->switch_pending = 0;
2378
                        for(i=0;istream->nb_streams;i++) {
2379
                            if (c->switch_feed_streams[i] == pkt.stream_index)
2380
                                if (pkt.flags & AV_PKT_FLAG_KEY)
2381
                                    c->switch_feed_streams[i] = -1;
2382
                            if (c->switch_feed_streams[i] >= 0)
2383
                                c->switch_pending = 1;
2384
                        }
2385
                    }
2386
                    for(i=0;istream->nb_streams;i++) {
2387
                        if (c->stream->feed_streams[i] == pkt.stream_index) {
2388
                            AVStream *st = c->fmt_in->streams[source_index];
2389
                            pkt.stream_index = i;
2390
                            if (pkt.flags & AV_PKT_FLAG_KEY &&
2391
                                (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
2392
                                 c->stream->nb_streams == 1))
2393
                                c->got_key_frame = 1;
2394
                            if (!c->stream->send_on_key || c->got_key_frame)
2395
                                goto send_it;
2396
                        }
2397
                    }
2398
                } else {
2399
                    AVCodecContext *codec;
2400
                    AVStream *ist, *ost;
2401
                send_it:
2402
                    ist = c->fmt_in->streams[source_index];
2403
                    /* specific handling for RTP: we use several
2404
                       output stream (one for each RTP
2405
                       connection). XXX: need more abstract handling */
2406
                    if (c->is_packetized) {
2407
                        /* compute send time and duration */
2408
                        c->cur_pts = av_rescale_q(pkt.dts, ist->time_base, AV_TIME_BASE_Q);
2409
                        c->cur_pts -= c->first_pts;
2410
                        c->cur_frame_duration = av_rescale_q(pkt.duration, ist->time_base, AV_TIME_BASE_Q);
2411
                        /* find RTP context */
2412
                        c->packet_stream_index = pkt.stream_index;
2413
                        ctx = c->rtp_ctx[c->packet_stream_index];
2414
                        if(!ctx) {
2415
                            av_free_packet(&pkt);
2416
                            break;
2417
                        }
2418
                        codec = ctx->streams[0]->codec;
2419
                        /* only one stream per RTP connection */
2420
                        pkt.stream_index = 0;
2421
                    } else {
2422
                        ctx = &c->fmt_ctx;
2423
                        /* Fudge here */
2424
                        codec = ctx->streams[pkt.stream_index]->codec;
2425
                    }
2426
 
2427
                    if (c->is_packetized) {
2428
                        int max_packet_size;
2429
                        if (c->rtp_protocol == RTSP_LOWER_TRANSPORT_TCP)
2430
                            max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
2431
                        else
2432
                            max_packet_size = c->rtp_handles[c->packet_stream_index]->max_packet_size;
2433
                        ret = ffio_open_dyn_packet_buf(&ctx->pb, max_packet_size);
2434
                    } else {
2435
                        ret = avio_open_dyn_buf(&ctx->pb);
2436
                    }
2437
                    if (ret < 0) {
2438
                        /* XXX: potential leak */
2439
                        return -1;
2440
                    }
2441
                    ost = ctx->streams[pkt.stream_index];
2442
 
2443
                    ctx->pb->seekable = 0;
2444
                    if (pkt.dts != AV_NOPTS_VALUE)
2445
                        pkt.dts = av_rescale_q(pkt.dts, ist->time_base, ost->time_base);
2446
                    if (pkt.pts != AV_NOPTS_VALUE)
2447
                        pkt.pts = av_rescale_q(pkt.pts, ist->time_base, ost->time_base);
2448
                    pkt.duration = av_rescale_q(pkt.duration, ist->time_base, ost->time_base);
2449
                    if (av_write_frame(ctx, &pkt) < 0) {
2450
                        http_log("Error writing frame to output\n");
2451
                        c->state = HTTPSTATE_SEND_DATA_TRAILER;
2452
                    }
2453
 
2454
                    len = avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
2455
                    c->cur_frame_bytes = len;
2456
                    c->buffer_ptr = c->pb_buffer;
2457
                    c->buffer_end = c->pb_buffer + len;
2458
 
2459
                    codec->frame_number++;
2460
                    if (len == 0) {
2461
                        av_free_packet(&pkt);
2462
                        goto redo;
2463
                    }
2464
                }
2465
                av_free_packet(&pkt);
2466
            }
2467
        }
2468
        break;
2469
    default:
2470
    case HTTPSTATE_SEND_DATA_TRAILER:
2471
        /* last packet test ? */
2472
        if (c->last_packet_sent || c->is_packetized)
2473
            return -1;
2474
        ctx = &c->fmt_ctx;
2475
        /* prepare header */
2476
        if (avio_open_dyn_buf(&ctx->pb) < 0) {
2477
            /* XXX: potential leak */
2478
            return -1;
2479
        }
2480
        c->fmt_ctx.pb->seekable = 0;
2481
        av_write_trailer(ctx);
2482
        len = avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
2483
        c->buffer_ptr = c->pb_buffer;
2484
        c->buffer_end = c->pb_buffer + len;
2485
 
2486
        c->last_packet_sent = 1;
2487
        break;
2488
    }
2489
    return 0;
2490
}
2491
 
2492
/* should convert the format at the same time */
2493
/* send data starting at c->buffer_ptr to the output connection
2494
   (either UDP or TCP connection) */
2495
static int http_send_data(HTTPContext *c)
2496
{
2497
    int len, ret;
2498
 
2499
    for(;;) {
2500
        if (c->buffer_ptr >= c->buffer_end) {
2501
            ret = http_prepare_data(c);
2502
            if (ret < 0)
2503
                return -1;
2504
            else if (ret != 0)
2505
                /* state change requested */
2506
                break;
2507
        } else {
2508
            if (c->is_packetized) {
2509
                /* RTP data output */
2510
                len = c->buffer_end - c->buffer_ptr;
2511
                if (len < 4) {
2512
                    /* fail safe - should never happen */
2513
                fail1:
2514
                    c->buffer_ptr = c->buffer_end;
2515
                    return 0;
2516
                }
2517
                len = (c->buffer_ptr[0] << 24) |
2518
                    (c->buffer_ptr[1] << 16) |
2519
                    (c->buffer_ptr[2] << 8) |
2520
                    (c->buffer_ptr[3]);
2521
                if (len > (c->buffer_end - c->buffer_ptr))
2522
                    goto fail1;
2523
                if ((get_packet_send_clock(c) - get_server_clock(c)) > 0) {
2524
                    /* nothing to send yet: we can wait */
2525
                    return 0;
2526
                }
2527
 
2528
                c->data_count += len;
2529
                update_datarate(&c->datarate, c->data_count);
2530
                if (c->stream)
2531
                    c->stream->bytes_served += len;
2532
 
2533
                if (c->rtp_protocol == RTSP_LOWER_TRANSPORT_TCP) {
2534
                    /* RTP packets are sent inside the RTSP TCP connection */
2535
                    AVIOContext *pb;
2536
                    int interleaved_index, size;
2537
                    uint8_t header[4];
2538
                    HTTPContext *rtsp_c;
2539
 
2540
                    rtsp_c = c->rtsp_c;
2541
                    /* if no RTSP connection left, error */
2542
                    if (!rtsp_c)
2543
                        return -1;
2544
                    /* if already sending something, then wait. */
2545
                    if (rtsp_c->state != RTSPSTATE_WAIT_REQUEST)
2546
                        break;
2547
                    if (avio_open_dyn_buf(&pb) < 0)
2548
                        goto fail1;
2549
                    interleaved_index = c->packet_stream_index * 2;
2550
                    /* RTCP packets are sent at odd indexes */
2551
                    if (c->buffer_ptr[1] == 200)
2552
                        interleaved_index++;
2553
                    /* write RTSP TCP header */
2554
                    header[0] = '$';
2555
                    header[1] = interleaved_index;
2556
                    header[2] = len >> 8;
2557
                    header[3] = len;
2558
                    avio_write(pb, header, 4);
2559
                    /* write RTP packet data */
2560
                    c->buffer_ptr += 4;
2561
                    avio_write(pb, c->buffer_ptr, len);
2562
                    size = avio_close_dyn_buf(pb, &c->packet_buffer);
2563
                    /* prepare asynchronous TCP sending */
2564
                    rtsp_c->packet_buffer_ptr = c->packet_buffer;
2565
                    rtsp_c->packet_buffer_end = c->packet_buffer + size;
2566
                    c->buffer_ptr += len;
2567
 
2568
                    /* send everything we can NOW */
2569
                    len = send(rtsp_c->fd, rtsp_c->packet_buffer_ptr,
2570
                                rtsp_c->packet_buffer_end - rtsp_c->packet_buffer_ptr, 0);
2571
                    if (len > 0)
2572
                        rtsp_c->packet_buffer_ptr += len;
2573
                    if (rtsp_c->packet_buffer_ptr < rtsp_c->packet_buffer_end) {
2574
                        /* if we could not send all the data, we will
2575
                           send it later, so a new state is needed to
2576
                           "lock" the RTSP TCP connection */
2577
                        rtsp_c->state = RTSPSTATE_SEND_PACKET;
2578
                        break;
2579
                    } else
2580
                        /* all data has been sent */
2581
                        av_freep(&c->packet_buffer);
2582
                } else {
2583
                    /* send RTP packet directly in UDP */
2584
                    c->buffer_ptr += 4;
2585
                    ffurl_write(c->rtp_handles[c->packet_stream_index],
2586
                                c->buffer_ptr, len);
2587
                    c->buffer_ptr += len;
2588
                    /* here we continue as we can send several packets per 10 ms slot */
2589
                }
2590
            } else {
2591
                /* TCP data output */
2592
                len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
2593
                if (len < 0) {
2594
                    if (ff_neterrno() != AVERROR(EAGAIN) &&
2595
                        ff_neterrno() != AVERROR(EINTR))
2596
                        /* error : close connection */
2597
                        return -1;
2598
                    else
2599
                        return 0;
2600
                } else
2601
                    c->buffer_ptr += len;
2602
 
2603
                c->data_count += len;
2604
                update_datarate(&c->datarate, c->data_count);
2605
                if (c->stream)
2606
                    c->stream->bytes_served += len;
2607
                break;
2608
            }
2609
        }
2610
    } /* for(;;) */
2611
    return 0;
2612
}
2613
 
2614
static int http_start_receive_data(HTTPContext *c)
2615
{
2616
    int fd;
2617
 
2618
    if (c->stream->feed_opened)
2619
        return -1;
2620
 
2621
    /* Don't permit writing to this one */
2622
    if (c->stream->readonly)
2623
        return -1;
2624
 
2625
    /* open feed */
2626
    fd = open(c->stream->feed_filename, O_RDWR);
2627
    if (fd < 0) {
2628
        http_log("Error opening feeder file: %s\n", strerror(errno));
2629
        return -1;
2630
    }
2631
    c->feed_fd = fd;
2632
 
2633
    if (c->stream->truncate) {
2634
        /* truncate feed file */
2635
        ffm_write_write_index(c->feed_fd, FFM_PACKET_SIZE);
2636
        http_log("Truncating feed file '%s'\n", c->stream->feed_filename);
2637
        if (ftruncate(c->feed_fd, FFM_PACKET_SIZE) < 0) {
2638
            http_log("Error truncating feed file: %s\n", strerror(errno));
2639
            return -1;
2640
        }
2641
    } else {
2642
        if ((c->stream->feed_write_index = ffm_read_write_index(fd)) < 0) {
2643
            http_log("Error reading write index from feed file: %s\n", strerror(errno));
2644
            return -1;
2645
        }
2646
    }
2647
 
2648
    c->stream->feed_write_index = FFMAX(ffm_read_write_index(fd), FFM_PACKET_SIZE);
2649
    c->stream->feed_size = lseek(fd, 0, SEEK_END);
2650
    lseek(fd, 0, SEEK_SET);
2651
 
2652
    /* init buffer input */
2653
    c->buffer_ptr = c->buffer;
2654
    c->buffer_end = c->buffer + FFM_PACKET_SIZE;
2655
    c->stream->feed_opened = 1;
2656
    c->chunked_encoding = !!av_stristr(c->buffer, "Transfer-Encoding: chunked");
2657
    return 0;
2658
}
2659
 
2660
static int http_receive_data(HTTPContext *c)
2661
{
2662
    HTTPContext *c1;
2663
    int len, loop_run = 0;
2664
 
2665
    while (c->chunked_encoding && !c->chunk_size &&
2666
           c->buffer_end > c->buffer_ptr) {
2667
        /* read chunk header, if present */
2668
        len = recv(c->fd, c->buffer_ptr, 1, 0);
2669
 
2670
        if (len < 0) {
2671
            if (ff_neterrno() != AVERROR(EAGAIN) &&
2672
                ff_neterrno() != AVERROR(EINTR))
2673
                /* error : close connection */
2674
                goto fail;
2675
            return 0;
2676
        } else if (len == 0) {
2677
            /* end of connection : close it */
2678
            goto fail;
2679
        } else if (c->buffer_ptr - c->buffer >= 2 &&
2680
                   !memcmp(c->buffer_ptr - 1, "\r\n", 2)) {
2681
            c->chunk_size = strtol(c->buffer, 0, 16);
2682
            if (c->chunk_size == 0) // end of stream
2683
                goto fail;
2684
            c->buffer_ptr = c->buffer;
2685
            break;
2686
        } else if (++loop_run > 10) {
2687
            /* no chunk header, abort */
2688
            goto fail;
2689
        } else {
2690
            c->buffer_ptr++;
2691
        }
2692
    }
2693
 
2694
    if (c->buffer_end > c->buffer_ptr) {
2695
        len = recv(c->fd, c->buffer_ptr,
2696
                   FFMIN(c->chunk_size, c->buffer_end - c->buffer_ptr), 0);
2697
        if (len < 0) {
2698
            if (ff_neterrno() != AVERROR(EAGAIN) &&
2699
                ff_neterrno() != AVERROR(EINTR))
2700
                /* error : close connection */
2701
                goto fail;
2702
        } else if (len == 0)
2703
            /* end of connection : close it */
2704
            goto fail;
2705
        else {
2706
            c->chunk_size -= len;
2707
            c->buffer_ptr += len;
2708
            c->data_count += len;
2709
            update_datarate(&c->datarate, c->data_count);
2710
        }
2711
    }
2712
 
2713
    if (c->buffer_ptr - c->buffer >= 2 && c->data_count > FFM_PACKET_SIZE) {
2714
        if (c->buffer[0] != 'f' ||
2715
            c->buffer[1] != 'm') {
2716
            http_log("Feed stream has become desynchronized -- disconnecting\n");
2717
            goto fail;
2718
        }
2719
    }
2720
 
2721
    if (c->buffer_ptr >= c->buffer_end) {
2722
        FFStream *feed = c->stream;
2723
        /* a packet has been received : write it in the store, except
2724
           if header */
2725
        if (c->data_count > FFM_PACKET_SIZE) {
2726
            /* XXX: use llseek or url_seek */
2727
            lseek(c->feed_fd, feed->feed_write_index, SEEK_SET);
2728
            if (write(c->feed_fd, c->buffer, FFM_PACKET_SIZE) < 0) {
2729
                http_log("Error writing to feed file: %s\n", strerror(errno));
2730
                goto fail;
2731
            }
2732
 
2733
            feed->feed_write_index += FFM_PACKET_SIZE;
2734
            /* update file size */
2735
            if (feed->feed_write_index > c->stream->feed_size)
2736
                feed->feed_size = feed->feed_write_index;
2737
 
2738
            /* handle wrap around if max file size reached */
2739
            if (c->stream->feed_max_size && feed->feed_write_index >= c->stream->feed_max_size)
2740
                feed->feed_write_index = FFM_PACKET_SIZE;
2741
 
2742
            /* write index */
2743
            if (ffm_write_write_index(c->feed_fd, feed->feed_write_index) < 0) {
2744
                http_log("Error writing index to feed file: %s\n", strerror(errno));
2745
                goto fail;
2746
            }
2747
 
2748
            /* wake up any waiting connections */
2749
            for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
2750
                if (c1->state == HTTPSTATE_WAIT_FEED &&
2751
                    c1->stream->feed == c->stream->feed)
2752
                    c1->state = HTTPSTATE_SEND_DATA;
2753
            }
2754
        } else {
2755
            /* We have a header in our hands that contains useful data */
2756
            AVFormatContext *s = avformat_alloc_context();
2757
            AVIOContext *pb;
2758
            AVInputFormat *fmt_in;
2759
            int i;
2760
 
2761
            if (!s)
2762
                goto fail;
2763
 
2764
            /* use feed output format name to find corresponding input format */
2765
            fmt_in = av_find_input_format(feed->fmt->name);
2766
            if (!fmt_in)
2767
                goto fail;
2768
 
2769
            pb = avio_alloc_context(c->buffer, c->buffer_end - c->buffer,
2770
                                    0, NULL, NULL, NULL, NULL);
2771
            pb->seekable = 0;
2772
 
2773
            s->pb = pb;
2774
            if (avformat_open_input(&s, c->stream->feed_filename, fmt_in, NULL) < 0) {
2775
                av_free(pb);
2776
                goto fail;
2777
            }
2778
 
2779
            /* Now we have the actual streams */
2780
            if (s->nb_streams != feed->nb_streams) {
2781
                avformat_close_input(&s);
2782
                av_free(pb);
2783
                http_log("Feed '%s' stream number does not match registered feed\n",
2784
                         c->stream->feed_filename);
2785
                goto fail;
2786
            }
2787
 
2788
            for (i = 0; i < s->nb_streams; i++) {
2789
                AVStream *fst = feed->streams[i];
2790
                AVStream *st = s->streams[i];
2791
                avcodec_copy_context(fst->codec, st->codec);
2792
            }
2793
 
2794
            avformat_close_input(&s);
2795
            av_free(pb);
2796
        }
2797
        c->buffer_ptr = c->buffer;
2798
    }
2799
 
2800
    return 0;
2801
 fail:
2802
    c->stream->feed_opened = 0;
2803
    close(c->feed_fd);
2804
    /* wake up any waiting connections to stop waiting for feed */
2805
    for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
2806
        if (c1->state == HTTPSTATE_WAIT_FEED &&
2807
            c1->stream->feed == c->stream->feed)
2808
            c1->state = HTTPSTATE_SEND_DATA_TRAILER;
2809
    }
2810
    return -1;
2811
}
2812
 
2813
/********************************************************************/
2814
/* RTSP handling */
2815
 
2816
static void rtsp_reply_header(HTTPContext *c, enum RTSPStatusCode error_number)
2817
{
2818
    const char *str;
2819
    time_t ti;
2820
    struct tm *tm;
2821
    char buf2[32];
2822
 
2823
    switch(error_number) {
2824
    case RTSP_STATUS_OK:
2825
        str = "OK";
2826
        break;
2827
    case RTSP_STATUS_METHOD:
2828
        str = "Method Not Allowed";
2829
        break;
2830
    case RTSP_STATUS_BANDWIDTH:
2831
        str = "Not Enough Bandwidth";
2832
        break;
2833
    case RTSP_STATUS_SESSION:
2834
        str = "Session Not Found";
2835
        break;
2836
    case RTSP_STATUS_STATE:
2837
        str = "Method Not Valid in This State";
2838
        break;
2839
    case RTSP_STATUS_AGGREGATE:
2840
        str = "Aggregate operation not allowed";
2841
        break;
2842
    case RTSP_STATUS_ONLY_AGGREGATE:
2843
        str = "Only aggregate operation allowed";
2844
        break;
2845
    case RTSP_STATUS_TRANSPORT:
2846
        str = "Unsupported transport";
2847
        break;
2848
    case RTSP_STATUS_INTERNAL:
2849
        str = "Internal Server Error";
2850
        break;
2851
    case RTSP_STATUS_SERVICE:
2852
        str = "Service Unavailable";
2853
        break;
2854
    case RTSP_STATUS_VERSION:
2855
        str = "RTSP Version not supported";
2856
        break;
2857
    default:
2858
        str = "Unknown Error";
2859
        break;
2860
    }
2861
 
2862
    avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", error_number, str);
2863
    avio_printf(c->pb, "CSeq: %d\r\n", c->seq);
2864
 
2865
    /* output GMT time */
2866
    ti = time(NULL);
2867
    tm = gmtime(&ti);
2868
    strftime(buf2, sizeof(buf2), "%a, %d %b %Y %H:%M:%S", tm);
2869
    avio_printf(c->pb, "Date: %s GMT\r\n", buf2);
2870
}
2871
 
2872
static void rtsp_reply_error(HTTPContext *c, enum RTSPStatusCode error_number)
2873
{
2874
    rtsp_reply_header(c, error_number);
2875
    avio_printf(c->pb, "\r\n");
2876
}
2877
 
2878
static int rtsp_parse_request(HTTPContext *c)
2879
{
2880
    const char *p, *p1, *p2;
2881
    char cmd[32];
2882
    char url[1024];
2883
    char protocol[32];
2884
    char line[1024];
2885
    int len;
2886
    RTSPMessageHeader header1 = { 0 }, *header = &header1;
2887
 
2888
    c->buffer_ptr[0] = '\0';
2889
    p = c->buffer;
2890
 
2891
    get_word(cmd, sizeof(cmd), &p);
2892
    get_word(url, sizeof(url), &p);
2893
    get_word(protocol, sizeof(protocol), &p);
2894
 
2895
    av_strlcpy(c->method, cmd, sizeof(c->method));
2896
    av_strlcpy(c->url, url, sizeof(c->url));
2897
    av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
2898
 
2899
    if (avio_open_dyn_buf(&c->pb) < 0) {
2900
        /* XXX: cannot do more */
2901
        c->pb = NULL; /* safety */
2902
        return -1;
2903
    }
2904
 
2905
    /* check version name */
2906
    if (strcmp(protocol, "RTSP/1.0") != 0) {
2907
        rtsp_reply_error(c, RTSP_STATUS_VERSION);
2908
        goto the_end;
2909
    }
2910
 
2911
    /* parse each header line */
2912
    /* skip to next line */
2913
    while (*p != '\n' && *p != '\0')
2914
        p++;
2915
    if (*p == '\n')
2916
        p++;
2917
    while (*p != '\0') {
2918
        p1 = memchr(p, '\n', (char *)c->buffer_ptr - p);
2919
        if (!p1)
2920
            break;
2921
        p2 = p1;
2922
        if (p2 > p && p2[-1] == '\r')
2923
            p2--;
2924
        /* skip empty line */
2925
        if (p2 == p)
2926
            break;
2927
        len = p2 - p;
2928
        if (len > sizeof(line) - 1)
2929
            len = sizeof(line) - 1;
2930
        memcpy(line, p, len);
2931
        line[len] = '\0';
2932
        ff_rtsp_parse_line(header, line, NULL, NULL);
2933
        p = p1 + 1;
2934
    }
2935
 
2936
    /* handle sequence number */
2937
    c->seq = header->seq;
2938
 
2939
    if (!strcmp(cmd, "DESCRIBE"))
2940
        rtsp_cmd_describe(c, url);
2941
    else if (!strcmp(cmd, "OPTIONS"))
2942
        rtsp_cmd_options(c, url);
2943
    else if (!strcmp(cmd, "SETUP"))
2944
        rtsp_cmd_setup(c, url, header);
2945
    else if (!strcmp(cmd, "PLAY"))
2946
        rtsp_cmd_play(c, url, header);
2947
    else if (!strcmp(cmd, "PAUSE"))
2948
        rtsp_cmd_pause(c, url, header);
2949
    else if (!strcmp(cmd, "TEARDOWN"))
2950
        rtsp_cmd_teardown(c, url, header);
2951
    else
2952
        rtsp_reply_error(c, RTSP_STATUS_METHOD);
2953
 
2954
 the_end:
2955
    len = avio_close_dyn_buf(c->pb, &c->pb_buffer);
2956
    c->pb = NULL; /* safety */
2957
    if (len < 0) {
2958
        /* XXX: cannot do more */
2959
        return -1;
2960
    }
2961
    c->buffer_ptr = c->pb_buffer;
2962
    c->buffer_end = c->pb_buffer + len;
2963
    c->state = RTSPSTATE_SEND_REPLY;
2964
    return 0;
2965
}
2966
 
2967
static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
2968
                                   struct in_addr my_ip)
2969
{
2970
    AVFormatContext *avc;
2971
    AVStream *avs = NULL;
2972
    AVOutputFormat *rtp_format = av_guess_format("rtp", NULL, NULL);
2973
    int i;
2974
 
2975
    avc =  avformat_alloc_context();
2976
    if (avc == NULL || !rtp_format) {
2977
        return -1;
2978
    }
2979
    avc->oformat = rtp_format;
2980
    av_dict_set(&avc->metadata, "title",
2981
               stream->title[0] ? stream->title : "No Title", 0);
2982
    avc->nb_streams = stream->nb_streams;
2983
    if (stream->is_multicast) {
2984
        snprintf(avc->filename, 1024, "rtp://%s:%d?multicast=1?ttl=%d",
2985
                 inet_ntoa(stream->multicast_ip),
2986
                 stream->multicast_port, stream->multicast_ttl);
2987
    } else {
2988
        snprintf(avc->filename, 1024, "rtp://0.0.0.0");
2989
    }
2990
 
2991
    if (avc->nb_streams >= INT_MAX/sizeof(*avc->streams) ||
2992
        !(avc->streams = av_malloc(avc->nb_streams * sizeof(*avc->streams))))
2993
        goto sdp_done;
2994
    if (avc->nb_streams >= INT_MAX/sizeof(*avs) ||
2995
        !(avs = av_malloc(avc->nb_streams * sizeof(*avs))))
2996
        goto sdp_done;
2997
 
2998
    for(i = 0; i < stream->nb_streams; i++) {
2999
        avc->streams[i] = &avs[i];
3000
        avc->streams[i]->codec = stream->streams[i]->codec;
3001
    }
3002
    *pbuffer = av_mallocz(2048);
3003
    av_sdp_create(&avc, 1, *pbuffer, 2048);
3004
 
3005
 sdp_done:
3006
    av_free(avc->streams);
3007
    av_dict_free(&avc->metadata);
3008
    av_free(avc);
3009
    av_free(avs);
3010
 
3011
    return strlen(*pbuffer);
3012
}
3013
 
3014
static void rtsp_cmd_options(HTTPContext *c, const char *url)
3015
{
3016
//    rtsp_reply_header(c, RTSP_STATUS_OK);
3017
    avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", RTSP_STATUS_OK, "OK");
3018
    avio_printf(c->pb, "CSeq: %d\r\n", c->seq);
3019
    avio_printf(c->pb, "Public: %s\r\n", "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
3020
    avio_printf(c->pb, "\r\n");
3021
}
3022
 
3023
static void rtsp_cmd_describe(HTTPContext *c, const char *url)
3024
{
3025
    FFStream *stream;
3026
    char path1[1024];
3027
    const char *path;
3028
    uint8_t *content;
3029
    int content_length;
3030
    socklen_t len;
3031
    struct sockaddr_in my_addr;
3032
 
3033
    /* find which url is asked */
3034
    av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3035
    path = path1;
3036
    if (*path == '/')
3037
        path++;
3038
 
3039
    for(stream = first_stream; stream != NULL; stream = stream->next) {
3040
        if (!stream->is_feed &&
3041
            stream->fmt && !strcmp(stream->fmt->name, "rtp") &&
3042
            !strcmp(path, stream->filename)) {
3043
            goto found;
3044
        }
3045
    }
3046
    /* no stream found */
3047
    rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
3048
    return;
3049
 
3050
 found:
3051
    /* prepare the media description in sdp format */
3052
 
3053
    /* get the host IP */
3054
    len = sizeof(my_addr);
3055
    getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
3056
    content_length = prepare_sdp_description(stream, &content, my_addr.sin_addr);
3057
    if (content_length < 0) {
3058
        rtsp_reply_error(c, RTSP_STATUS_INTERNAL);
3059
        return;
3060
    }
3061
    rtsp_reply_header(c, RTSP_STATUS_OK);
3062
    avio_printf(c->pb, "Content-Base: %s/\r\n", url);
3063
    avio_printf(c->pb, "Content-Type: application/sdp\r\n");
3064
    avio_printf(c->pb, "Content-Length: %d\r\n", content_length);
3065
    avio_printf(c->pb, "\r\n");
3066
    avio_write(c->pb, content, content_length);
3067
    av_free(content);
3068
}
3069
 
3070
static HTTPContext *find_rtp_session(const char *session_id)
3071
{
3072
    HTTPContext *c;
3073
 
3074
    if (session_id[0] == '\0')
3075
        return NULL;
3076
 
3077
    for(c = first_http_ctx; c != NULL; c = c->next) {
3078
        if (!strcmp(c->session_id, session_id))
3079
            return c;
3080
    }
3081
    return NULL;
3082
}
3083
 
3084
static RTSPTransportField *find_transport(RTSPMessageHeader *h, enum RTSPLowerTransport lower_transport)
3085
{
3086
    RTSPTransportField *th;
3087
    int i;
3088
 
3089
    for(i=0;inb_transports;i++) {
3090
        th = &h->transports[i];
3091
        if (th->lower_transport == lower_transport)
3092
            return th;
3093
    }
3094
    return NULL;
3095
}
3096
 
3097
static void rtsp_cmd_setup(HTTPContext *c, const char *url,
3098
                           RTSPMessageHeader *h)
3099
{
3100
    FFStream *stream;
3101
    int stream_index, rtp_port, rtcp_port;
3102
    char buf[1024];
3103
    char path1[1024];
3104
    const char *path;
3105
    HTTPContext *rtp_c;
3106
    RTSPTransportField *th;
3107
    struct sockaddr_in dest_addr;
3108
    RTSPActionServerSetup setup;
3109
 
3110
    /* find which url is asked */
3111
    av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3112
    path = path1;
3113
    if (*path == '/')
3114
        path++;
3115
 
3116
    /* now check each stream */
3117
    for(stream = first_stream; stream != NULL; stream = stream->next) {
3118
        if (!stream->is_feed &&
3119
            stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
3120
            /* accept aggregate filenames only if single stream */
3121
            if (!strcmp(path, stream->filename)) {
3122
                if (stream->nb_streams != 1) {
3123
                    rtsp_reply_error(c, RTSP_STATUS_AGGREGATE);
3124
                    return;
3125
                }
3126
                stream_index = 0;
3127
                goto found;
3128
            }
3129
 
3130
            for(stream_index = 0; stream_index < stream->nb_streams;
3131
                stream_index++) {
3132
                snprintf(buf, sizeof(buf), "%s/streamid=%d",
3133
                         stream->filename, stream_index);
3134
                if (!strcmp(path, buf))
3135
                    goto found;
3136
            }
3137
        }
3138
    }
3139
    /* no stream found */
3140
    rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
3141
    return;
3142
 found:
3143
 
3144
    /* generate session id if needed */
3145
    if (h->session_id[0] == '\0') {
3146
        unsigned random0 = av_lfg_get(&random_state);
3147
        unsigned random1 = av_lfg_get(&random_state);
3148
        snprintf(h->session_id, sizeof(h->session_id), "%08x%08x",
3149
                 random0, random1);
3150
    }
3151
 
3152
    /* find rtp session, and create it if none found */
3153
    rtp_c = find_rtp_session(h->session_id);
3154
    if (!rtp_c) {
3155
        /* always prefer UDP */
3156
        th = find_transport(h, RTSP_LOWER_TRANSPORT_UDP);
3157
        if (!th) {
3158
            th = find_transport(h, RTSP_LOWER_TRANSPORT_TCP);
3159
            if (!th) {
3160
                rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3161
                return;
3162
            }
3163
        }
3164
 
3165
        rtp_c = rtp_new_connection(&c->from_addr, stream, h->session_id,
3166
                                   th->lower_transport);
3167
        if (!rtp_c) {
3168
            rtsp_reply_error(c, RTSP_STATUS_BANDWIDTH);
3169
            return;
3170
        }
3171
 
3172
        /* open input stream */
3173
        if (open_input_stream(rtp_c, "") < 0) {
3174
            rtsp_reply_error(c, RTSP_STATUS_INTERNAL);
3175
            return;
3176
        }
3177
    }
3178
 
3179
    /* test if stream is OK (test needed because several SETUP needs
3180
       to be done for a given file) */
3181
    if (rtp_c->stream != stream) {
3182
        rtsp_reply_error(c, RTSP_STATUS_SERVICE);
3183
        return;
3184
    }
3185
 
3186
    /* test if stream is already set up */
3187
    if (rtp_c->rtp_ctx[stream_index]) {
3188
        rtsp_reply_error(c, RTSP_STATUS_STATE);
3189
        return;
3190
    }
3191
 
3192
    /* check transport */
3193
    th = find_transport(h, rtp_c->rtp_protocol);
3194
    if (!th || (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
3195
                th->client_port_min <= 0)) {
3196
        rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3197
        return;
3198
    }
3199
 
3200
    /* setup default options */
3201
    setup.transport_option[0] = '\0';
3202
    dest_addr = rtp_c->from_addr;
3203
    dest_addr.sin_port = htons(th->client_port_min);
3204
 
3205
    /* setup stream */
3206
    if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, c) < 0) {
3207
        rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3208
        return;
3209
    }
3210
 
3211
    /* now everything is OK, so we can send the connection parameters */
3212
    rtsp_reply_header(c, RTSP_STATUS_OK);
3213
    /* session ID */
3214
    avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3215
 
3216
    switch(rtp_c->rtp_protocol) {
3217
    case RTSP_LOWER_TRANSPORT_UDP:
3218
        rtp_port = ff_rtp_get_local_rtp_port(rtp_c->rtp_handles[stream_index]);
3219
        rtcp_port = ff_rtp_get_local_rtcp_port(rtp_c->rtp_handles[stream_index]);
3220
        avio_printf(c->pb, "Transport: RTP/AVP/UDP;unicast;"
3221
                    "client_port=%d-%d;server_port=%d-%d",
3222
                    th->client_port_min, th->client_port_max,
3223
                    rtp_port, rtcp_port);
3224
        break;
3225
    case RTSP_LOWER_TRANSPORT_TCP:
3226
        avio_printf(c->pb, "Transport: RTP/AVP/TCP;interleaved=%d-%d",
3227
                    stream_index * 2, stream_index * 2 + 1);
3228
        break;
3229
    default:
3230
        break;
3231
    }
3232
    if (setup.transport_option[0] != '\0')
3233
        avio_printf(c->pb, ";%s", setup.transport_option);
3234
    avio_printf(c->pb, "\r\n");
3235
 
3236
 
3237
    avio_printf(c->pb, "\r\n");
3238
}
3239
 
3240
 
3241
/* find an rtp connection by using the session ID. Check consistency
3242
   with filename */
3243
static HTTPContext *find_rtp_session_with_url(const char *url,
3244
                                              const char *session_id)
3245
{
3246
    HTTPContext *rtp_c;
3247
    char path1[1024];
3248
    const char *path;
3249
    char buf[1024];
3250
    int s, len;
3251
 
3252
    rtp_c = find_rtp_session(session_id);
3253
    if (!rtp_c)
3254
        return NULL;
3255
 
3256
    /* find which url is asked */
3257
    av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3258
    path = path1;
3259
    if (*path == '/')
3260
        path++;
3261
    if(!strcmp(path, rtp_c->stream->filename)) return rtp_c;
3262
    for(s=0; sstream->nb_streams; ++s) {
3263
      snprintf(buf, sizeof(buf), "%s/streamid=%d",
3264
        rtp_c->stream->filename, s);
3265
      if(!strncmp(path, buf, sizeof(buf))) {
3266
    // XXX: Should we reply with RTSP_STATUS_ONLY_AGGREGATE if nb_streams>1?
3267
        return rtp_c;
3268
      }
3269
    }
3270
    len = strlen(path);
3271
    if (len > 0 && path[len - 1] == '/' &&
3272
        !strncmp(path, rtp_c->stream->filename, len - 1))
3273
        return rtp_c;
3274
    return NULL;
3275
}
3276
 
3277
static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3278
{
3279
    HTTPContext *rtp_c;
3280
 
3281
    rtp_c = find_rtp_session_with_url(url, h->session_id);
3282
    if (!rtp_c) {
3283
        rtsp_reply_error(c, RTSP_STATUS_SESSION);
3284
        return;
3285
    }
3286
 
3287
    if (rtp_c->state != HTTPSTATE_SEND_DATA &&
3288
        rtp_c->state != HTTPSTATE_WAIT_FEED &&
3289
        rtp_c->state != HTTPSTATE_READY) {
3290
        rtsp_reply_error(c, RTSP_STATUS_STATE);
3291
        return;
3292
    }
3293
 
3294
    rtp_c->state = HTTPSTATE_SEND_DATA;
3295
 
3296
    /* now everything is OK, so we can send the connection parameters */
3297
    rtsp_reply_header(c, RTSP_STATUS_OK);
3298
    /* session ID */
3299
    avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3300
    avio_printf(c->pb, "\r\n");
3301
}
3302
 
3303
static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3304
{
3305
    HTTPContext *rtp_c;
3306
 
3307
    rtp_c = find_rtp_session_with_url(url, h->session_id);
3308
    if (!rtp_c) {
3309
        rtsp_reply_error(c, RTSP_STATUS_SESSION);
3310
        return;
3311
    }
3312
 
3313
    if (rtp_c->state != HTTPSTATE_SEND_DATA &&
3314
        rtp_c->state != HTTPSTATE_WAIT_FEED) {
3315
        rtsp_reply_error(c, RTSP_STATUS_STATE);
3316
        return;
3317
    }
3318
 
3319
    rtp_c->state = HTTPSTATE_READY;
3320
    rtp_c->first_pts = AV_NOPTS_VALUE;
3321
    /* now everything is OK, so we can send the connection parameters */
3322
    rtsp_reply_header(c, RTSP_STATUS_OK);
3323
    /* session ID */
3324
    avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3325
    avio_printf(c->pb, "\r\n");
3326
}
3327
 
3328
static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3329
{
3330
    HTTPContext *rtp_c;
3331
 
3332
    rtp_c = find_rtp_session_with_url(url, h->session_id);
3333
    if (!rtp_c) {
3334
        rtsp_reply_error(c, RTSP_STATUS_SESSION);
3335
        return;
3336
    }
3337
 
3338
    /* now everything is OK, so we can send the connection parameters */
3339
    rtsp_reply_header(c, RTSP_STATUS_OK);
3340
    /* session ID */
3341
    avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3342
    avio_printf(c->pb, "\r\n");
3343
 
3344
    /* abort the session */
3345
    close_connection(rtp_c);
3346
}
3347
 
3348
 
3349
/********************************************************************/
3350
/* RTP handling */
3351
 
3352
static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
3353
                                       FFStream *stream, const char *session_id,
3354
                                       enum RTSPLowerTransport rtp_protocol)
3355
{
3356
    HTTPContext *c = NULL;
3357
    const char *proto_str;
3358
 
3359
    /* XXX: should output a warning page when coming
3360
       close to the connection limit */
3361
    if (nb_connections >= nb_max_connections)
3362
        goto fail;
3363
 
3364
    /* add a new connection */
3365
    c = av_mallocz(sizeof(HTTPContext));
3366
    if (!c)
3367
        goto fail;
3368
 
3369
    c->fd = -1;
3370
    c->poll_entry = NULL;
3371
    c->from_addr = *from_addr;
3372
    c->buffer_size = IOBUFFER_INIT_SIZE;
3373
    c->buffer = av_malloc(c->buffer_size);
3374
    if (!c->buffer)
3375
        goto fail;
3376
    nb_connections++;
3377
    c->stream = stream;
3378
    av_strlcpy(c->session_id, session_id, sizeof(c->session_id));
3379
    c->state = HTTPSTATE_READY;
3380
    c->is_packetized = 1;
3381
    c->rtp_protocol = rtp_protocol;
3382
 
3383
    /* protocol is shown in statistics */
3384
    switch(c->rtp_protocol) {
3385
    case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
3386
        proto_str = "MCAST";
3387
        break;
3388
    case RTSP_LOWER_TRANSPORT_UDP:
3389
        proto_str = "UDP";
3390
        break;
3391
    case RTSP_LOWER_TRANSPORT_TCP:
3392
        proto_str = "TCP";
3393
        break;
3394
    default:
3395
        proto_str = "???";
3396
        break;
3397
    }
3398
    av_strlcpy(c->protocol, "RTP/", sizeof(c->protocol));
3399
    av_strlcat(c->protocol, proto_str, sizeof(c->protocol));
3400
 
3401
    current_bandwidth += stream->bandwidth;
3402
 
3403
    c->next = first_http_ctx;
3404
    first_http_ctx = c;
3405
    return c;
3406
 
3407
 fail:
3408
    if (c) {
3409
        av_free(c->buffer);
3410
        av_free(c);
3411
    }
3412
    return NULL;
3413
}
3414
 
3415
/* add a new RTP stream in an RTP connection (used in RTSP SETUP
3416
   command). If RTP/TCP protocol is used, TCP connection 'rtsp_c' is
3417
   used. */
3418
static int rtp_new_av_stream(HTTPContext *c,
3419
                             int stream_index, struct sockaddr_in *dest_addr,
3420
                             HTTPContext *rtsp_c)
3421
{
3422
    AVFormatContext *ctx;
3423
    AVStream *st;
3424
    char *ipaddr;
3425
    URLContext *h = NULL;
3426
    uint8_t *dummy_buf;
3427
    int max_packet_size;
3428
 
3429
    /* now we can open the relevant output stream */
3430
    ctx = avformat_alloc_context();
3431
    if (!ctx)
3432
        return -1;
3433
    ctx->oformat = av_guess_format("rtp", NULL, NULL);
3434
 
3435
    st = av_mallocz(sizeof(AVStream));
3436
    if (!st)
3437
        goto fail;
3438
    ctx->nb_streams = 1;
3439
    ctx->streams = av_mallocz(sizeof(AVStream *) * ctx->nb_streams);
3440
    if (!ctx->streams)
3441
      goto fail;
3442
    ctx->streams[0] = st;
3443
 
3444
    if (!c->stream->feed ||
3445
        c->stream->feed == c->stream)
3446
        memcpy(st, c->stream->streams[stream_index], sizeof(AVStream));
3447
    else
3448
        memcpy(st,
3449
               c->stream->feed->streams[c->stream->feed_streams[stream_index]],
3450
               sizeof(AVStream));
3451
    st->priv_data = NULL;
3452
 
3453
    /* build destination RTP address */
3454
    ipaddr = inet_ntoa(dest_addr->sin_addr);
3455
 
3456
    switch(c->rtp_protocol) {
3457
    case RTSP_LOWER_TRANSPORT_UDP:
3458
    case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
3459
        /* RTP/UDP case */
3460
 
3461
        /* XXX: also pass as parameter to function ? */
3462
        if (c->stream->is_multicast) {
3463
            int ttl;
3464
            ttl = c->stream->multicast_ttl;
3465
            if (!ttl)
3466
                ttl = 16;
3467
            snprintf(ctx->filename, sizeof(ctx->filename),
3468
                     "rtp://%s:%d?multicast=1&ttl=%d",
3469
                     ipaddr, ntohs(dest_addr->sin_port), ttl);
3470
        } else {
3471
            snprintf(ctx->filename, sizeof(ctx->filename),
3472
                     "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
3473
        }
3474
 
3475
        if (ffurl_open(&h, ctx->filename, AVIO_FLAG_WRITE, NULL, NULL) < 0)
3476
            goto fail;
3477
        c->rtp_handles[stream_index] = h;
3478
        max_packet_size = h->max_packet_size;
3479
        break;
3480
    case RTSP_LOWER_TRANSPORT_TCP:
3481
        /* RTP/TCP case */
3482
        c->rtsp_c = rtsp_c;
3483
        max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
3484
        break;
3485
    default:
3486
        goto fail;
3487
    }
3488
 
3489
    http_log("%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
3490
             ipaddr, ntohs(dest_addr->sin_port),
3491
             c->stream->filename, stream_index, c->protocol);
3492
 
3493
    /* normally, no packets should be output here, but the packet size may be checked */
3494
    if (ffio_open_dyn_packet_buf(&ctx->pb, max_packet_size) < 0) {
3495
        /* XXX: close stream */
3496
        goto fail;
3497
    }
3498
    if (avformat_write_header(ctx, NULL) < 0) {
3499
    fail:
3500
        if (h)
3501
            ffurl_close(h);
3502
        av_free(ctx);
3503
        return -1;
3504
    }
3505
    avio_close_dyn_buf(ctx->pb, &dummy_buf);
3506
    av_free(dummy_buf);
3507
 
3508
    c->rtp_ctx[stream_index] = ctx;
3509
    return 0;
3510
}
3511
 
3512
/********************************************************************/
3513
/* ffserver initialization */
3514
 
3515
static AVStream *add_av_stream1(FFStream *stream, AVCodecContext *codec, int copy)
3516
{
3517
    AVStream *fst;
3518
 
3519
    if(stream->nb_streams >= FF_ARRAY_ELEMS(stream->streams))
3520
        return NULL;
3521
 
3522
    fst = av_mallocz(sizeof(AVStream));
3523
    if (!fst)
3524
        return NULL;
3525
    if (copy) {
3526
        fst->codec = avcodec_alloc_context3(NULL);
3527
        memcpy(fst->codec, codec, sizeof(AVCodecContext));
3528
        if (codec->extradata_size) {
3529
            fst->codec->extradata = av_mallocz(codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
3530
            memcpy(fst->codec->extradata, codec->extradata,
3531
                codec->extradata_size);
3532
        }
3533
    } else {
3534
        /* live streams must use the actual feed's codec since it may be
3535
         * updated later to carry extradata needed by the streams.
3536
         */
3537
        fst->codec = codec;
3538
    }
3539
    fst->priv_data = av_mallocz(sizeof(FeedData));
3540
    fst->index = stream->nb_streams;
3541
    avpriv_set_pts_info(fst, 33, 1, 90000);
3542
    fst->sample_aspect_ratio = codec->sample_aspect_ratio;
3543
    stream->streams[stream->nb_streams++] = fst;
3544
    return fst;
3545
}
3546
 
3547
/* return the stream number in the feed */
3548
static int add_av_stream(FFStream *feed, AVStream *st)
3549
{
3550
    AVStream *fst;
3551
    AVCodecContext *av, *av1;
3552
    int i;
3553
 
3554
    av = st->codec;
3555
    for(i=0;inb_streams;i++) {
3556
        st = feed->streams[i];
3557
        av1 = st->codec;
3558
        if (av1->codec_id == av->codec_id &&
3559
            av1->codec_type == av->codec_type &&
3560
            av1->bit_rate == av->bit_rate) {
3561
 
3562
            switch(av->codec_type) {
3563
            case AVMEDIA_TYPE_AUDIO:
3564
                if (av1->channels == av->channels &&
3565
                    av1->sample_rate == av->sample_rate)
3566
                    return i;
3567
                break;
3568
            case AVMEDIA_TYPE_VIDEO:
3569
                if (av1->width == av->width &&
3570
                    av1->height == av->height &&
3571
                    av1->time_base.den == av->time_base.den &&
3572
                    av1->time_base.num == av->time_base.num &&
3573
                    av1->gop_size == av->gop_size)
3574
                    return i;
3575
                break;
3576
            default:
3577
                abort();
3578
            }
3579
        }
3580
    }
3581
 
3582
    fst = add_av_stream1(feed, av, 0);
3583
    if (!fst)
3584
        return -1;
3585
    return feed->nb_streams - 1;
3586
}
3587
 
3588
static void remove_stream(FFStream *stream)
3589
{
3590
    FFStream **ps;
3591
    ps = &first_stream;
3592
    while (*ps != NULL) {
3593
        if (*ps == stream)
3594
            *ps = (*ps)->next;
3595
        else
3596
            ps = &(*ps)->next;
3597
    }
3598
}
3599
 
3600
/* specific mpeg4 handling : we extract the raw parameters */
3601
static void extract_mpeg4_header(AVFormatContext *infile)
3602
{
3603
    int mpeg4_count, i, size;
3604
    AVPacket pkt;
3605
    AVStream *st;
3606
    const uint8_t *p;
3607
 
3608
    infile->flags |= AVFMT_FLAG_NOFILLIN | AVFMT_FLAG_NOPARSE;
3609
 
3610
    mpeg4_count = 0;
3611
    for(i=0;inb_streams;i++) {
3612
        st = infile->streams[i];
3613
        if (st->codec->codec_id == AV_CODEC_ID_MPEG4 &&
3614
            st->codec->extradata_size == 0) {
3615
            mpeg4_count++;
3616
        }
3617
    }
3618
    if (!mpeg4_count)
3619
        return;
3620
 
3621
    printf("MPEG4 without extra data: trying to find header in %s\n", infile->filename);
3622
    while (mpeg4_count > 0) {
3623
        if (av_read_frame(infile, &pkt) < 0)
3624
            break;
3625
        st = infile->streams[pkt.stream_index];
3626
        if (st->codec->codec_id == AV_CODEC_ID_MPEG4 &&
3627
            st->codec->extradata_size == 0) {
3628
            av_freep(&st->codec->extradata);
3629
            /* fill extradata with the header */
3630
            /* XXX: we make hard suppositions here ! */
3631
            p = pkt.data;
3632
            while (p < pkt.data + pkt.size - 4) {
3633
                /* stop when vop header is found */
3634
                if (p[0] == 0x00 && p[1] == 0x00 &&
3635
                    p[2] == 0x01 && p[3] == 0xb6) {
3636
                    size = p - pkt.data;
3637
                    //                    av_hex_dump_log(infile, AV_LOG_DEBUG, pkt.data, size);
3638
                    st->codec->extradata = av_mallocz(size + FF_INPUT_BUFFER_PADDING_SIZE);
3639
                    st->codec->extradata_size = size;
3640
                    memcpy(st->codec->extradata, pkt.data, size);
3641
                    break;
3642
                }
3643
                p++;
3644
            }
3645
            mpeg4_count--;
3646
        }
3647
        av_free_packet(&pkt);
3648
    }
3649
}
3650
 
3651
/* compute the needed AVStream for each file */
3652
static void build_file_streams(void)
3653
{
3654
    FFStream *stream, *stream_next;
3655
    int i, ret;
3656
 
3657
    /* gather all streams */
3658
    for(stream = first_stream; stream != NULL; stream = stream_next) {
3659
        AVFormatContext *infile = NULL;
3660
        stream_next = stream->next;
3661
        if (stream->stream_type == STREAM_TYPE_LIVE &&
3662
            !stream->feed) {
3663
            /* the stream comes from a file */
3664
            /* try to open the file */
3665
            /* open stream */
3666
            if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
3667
                /* specific case : if transport stream output to RTP,
3668
                   we use a raw transport stream reader */
3669
                av_dict_set(&stream->in_opts, "mpeg2ts_compute_pcr", "1", 0);
3670
            }
3671
 
3672
            http_log("Opening file '%s'\n", stream->feed_filename);
3673
            if ((ret = avformat_open_input(&infile, stream->feed_filename, stream->ifmt, &stream->in_opts)) < 0) {
3674
                http_log("Could not open '%s': %d\n", stream->feed_filename, ret);
3675
                /* remove stream (no need to spend more time on it) */
3676
            fail:
3677
                remove_stream(stream);
3678
            } else {
3679
                /* find all the AVStreams inside and reference them in
3680
                   'stream' */
3681
                if (avformat_find_stream_info(infile, NULL) < 0) {
3682
                    http_log("Could not find codec parameters from '%s'\n",
3683
                             stream->feed_filename);
3684
                    avformat_close_input(&infile);
3685
                    goto fail;
3686
                }
3687
                extract_mpeg4_header(infile);
3688
 
3689
                for(i=0;inb_streams;i++)
3690
                    add_av_stream1(stream, infile->streams[i]->codec, 1);
3691
 
3692
                avformat_close_input(&infile);
3693
            }
3694
        }
3695
    }
3696
}
3697
 
3698
/* compute the needed AVStream for each feed */
3699
static void build_feed_streams(void)
3700
{
3701
    FFStream *stream, *feed;
3702
    int i;
3703
 
3704
    /* gather all streams */
3705
    for(stream = first_stream; stream != NULL; stream = stream->next) {
3706
        feed = stream->feed;
3707
        if (feed) {
3708
            if (stream->is_feed) {
3709
                for(i=0;inb_streams;i++)
3710
                    stream->feed_streams[i] = i;
3711
            } else {
3712
                /* we handle a stream coming from a feed */
3713
                for(i=0;inb_streams;i++)
3714
                    stream->feed_streams[i] = add_av_stream(feed, stream->streams[i]);
3715
            }
3716
        }
3717
    }
3718
 
3719
    /* create feed files if needed */
3720
    for(feed = first_feed; feed != NULL; feed = feed->next_feed) {
3721
        int fd;
3722
 
3723
        if (avio_check(feed->feed_filename, AVIO_FLAG_READ) > 0) {
3724
            /* See if it matches */
3725
            AVFormatContext *s = NULL;
3726
            int matches = 0;
3727
 
3728
            if (avformat_open_input(&s, feed->feed_filename, NULL, NULL) >= 0) {
3729
                /* set buffer size */
3730
                ffio_set_buf_size(s->pb, FFM_PACKET_SIZE);
3731
                /* Now see if it matches */
3732
                if (s->nb_streams == feed->nb_streams) {
3733
                    matches = 1;
3734
                    for(i=0;inb_streams;i++) {
3735
                        AVStream *sf, *ss;
3736
                        sf = feed->streams[i];
3737
                        ss = s->streams[i];
3738
 
3739
                        if (sf->index != ss->index ||
3740
                            sf->id != ss->id) {
3741
                            http_log("Index & Id do not match for stream %d (%s)\n",
3742
                                   i, feed->feed_filename);
3743
                            matches = 0;
3744
                        } else {
3745
                            AVCodecContext *ccf, *ccs;
3746
 
3747
                            ccf = sf->codec;
3748
                            ccs = ss->codec;
3749
#define CHECK_CODEC(x)  (ccf->x != ccs->x)
3750
 
3751
                            if (CHECK_CODEC(codec_id) || CHECK_CODEC(codec_type)) {
3752
                                http_log("Codecs do not match for stream %d\n", i);
3753
                                matches = 0;
3754
                            } else if (CHECK_CODEC(bit_rate) || CHECK_CODEC(flags)) {
3755
                                http_log("Codec bitrates do not match for stream %d\n", i);
3756
                                matches = 0;
3757
                            } else if (ccf->codec_type == AVMEDIA_TYPE_VIDEO) {
3758
                                if (CHECK_CODEC(time_base.den) ||
3759
                                    CHECK_CODEC(time_base.num) ||
3760
                                    CHECK_CODEC(width) ||
3761
                                    CHECK_CODEC(height)) {
3762
                                    http_log("Codec width, height and framerate do not match for stream %d\n", i);
3763
                                    matches = 0;
3764
                                }
3765
                            } else if (ccf->codec_type == AVMEDIA_TYPE_AUDIO) {
3766
                                if (CHECK_CODEC(sample_rate) ||
3767
                                    CHECK_CODEC(channels) ||
3768
                                    CHECK_CODEC(frame_size)) {
3769
                                    http_log("Codec sample_rate, channels, frame_size do not match for stream %d\n", i);
3770
                                    matches = 0;
3771
                                }
3772
                            } else {
3773
                                http_log("Unknown codec type\n");
3774
                                matches = 0;
3775
                            }
3776
                        }
3777
                        if (!matches)
3778
                            break;
3779
                    }
3780
                } else
3781
                    http_log("Deleting feed file '%s' as stream counts differ (%d != %d)\n",
3782
                        feed->feed_filename, s->nb_streams, feed->nb_streams);
3783
 
3784
                avformat_close_input(&s);
3785
            } else
3786
                http_log("Deleting feed file '%s' as it appears to be corrupt\n",
3787
                        feed->feed_filename);
3788
 
3789
            if (!matches) {
3790
                if (feed->readonly) {
3791
                    http_log("Unable to delete feed file '%s' as it is marked readonly\n",
3792
                        feed->feed_filename);
3793
                    exit(1);
3794
                }
3795
                unlink(feed->feed_filename);
3796
            }
3797
        }
3798
        if (avio_check(feed->feed_filename, AVIO_FLAG_WRITE) <= 0) {
3799
            AVFormatContext s1 = {0}, *s = &s1;
3800
 
3801
            if (feed->readonly) {
3802
                http_log("Unable to create feed file '%s' as it is marked readonly\n",
3803
                    feed->feed_filename);
3804
                exit(1);
3805
            }
3806
 
3807
            /* only write the header of the ffm file */
3808
            if (avio_open(&s->pb, feed->feed_filename, AVIO_FLAG_WRITE) < 0) {
3809
                http_log("Could not open output feed file '%s'\n",
3810
                         feed->feed_filename);
3811
                exit(1);
3812
            }
3813
            s->oformat = feed->fmt;
3814
            s->nb_streams = feed->nb_streams;
3815
            s->streams = feed->streams;
3816
            if (avformat_write_header(s, NULL) < 0) {
3817
                http_log("Container doesn't support the required parameters\n");
3818
                exit(1);
3819
            }
3820
            /* XXX: need better api */
3821
            av_freep(&s->priv_data);
3822
            avio_close(s->pb);
3823
        }
3824
        /* get feed size and write index */
3825
        fd = open(feed->feed_filename, O_RDONLY);
3826
        if (fd < 0) {
3827
            http_log("Could not open output feed file '%s'\n",
3828
                    feed->feed_filename);
3829
            exit(1);
3830
        }
3831
 
3832
        feed->feed_write_index = FFMAX(ffm_read_write_index(fd), FFM_PACKET_SIZE);
3833
        feed->feed_size = lseek(fd, 0, SEEK_END);
3834
        /* ensure that we do not wrap before the end of file */
3835
        if (feed->feed_max_size && feed->feed_max_size < feed->feed_size)
3836
            feed->feed_max_size = feed->feed_size;
3837
 
3838
        close(fd);
3839
    }
3840
}
3841
 
3842
/* compute the bandwidth used by each stream */
3843
static void compute_bandwidth(void)
3844
{
3845
    unsigned bandwidth;
3846
    int i;
3847
    FFStream *stream;
3848
 
3849
    for(stream = first_stream; stream != NULL; stream = stream->next) {
3850
        bandwidth = 0;
3851
        for(i=0;inb_streams;i++) {
3852
            AVStream *st = stream->streams[i];
3853
            switch(st->codec->codec_type) {
3854
            case AVMEDIA_TYPE_AUDIO:
3855
            case AVMEDIA_TYPE_VIDEO:
3856
                bandwidth += st->codec->bit_rate;
3857
                break;
3858
            default:
3859
                break;
3860
            }
3861
        }
3862
        stream->bandwidth = (bandwidth + 999) / 1000;
3863
    }
3864
}
3865
 
3866
/* add a codec and set the default parameters */
3867
static void add_codec(FFStream *stream, AVCodecContext *av)
3868
{
3869
    AVStream *st;
3870
 
3871
    if(stream->nb_streams >= FF_ARRAY_ELEMS(stream->streams))
3872
        return;
3873
 
3874
    /* compute default parameters */
3875
    switch(av->codec_type) {
3876
    case AVMEDIA_TYPE_AUDIO:
3877
        if (av->bit_rate == 0)
3878
            av->bit_rate = 64000;
3879
        if (av->sample_rate == 0)
3880
            av->sample_rate = 22050;
3881
        if (av->channels == 0)
3882
            av->channels = 1;
3883
        break;
3884
    case AVMEDIA_TYPE_VIDEO:
3885
        if (av->bit_rate == 0)
3886
            av->bit_rate = 64000;
3887
        if (av->time_base.num == 0){
3888
            av->time_base.den = 5;
3889
            av->time_base.num = 1;
3890
        }
3891
        if (av->width == 0 || av->height == 0) {
3892
            av->width = 160;
3893
            av->height = 128;
3894
        }
3895
        /* Bitrate tolerance is less for streaming */
3896
        if (av->bit_rate_tolerance == 0)
3897
            av->bit_rate_tolerance = FFMAX(av->bit_rate / 4,
3898
                      (int64_t)av->bit_rate*av->time_base.num/av->time_base.den);
3899
        if (av->qmin == 0)
3900
            av->qmin = 3;
3901
        if (av->qmax == 0)
3902
            av->qmax = 31;
3903
        if (av->max_qdiff == 0)
3904
            av->max_qdiff = 3;
3905
        av->qcompress = 0.5;
3906
        av->qblur = 0.5;
3907
 
3908
        if (!av->nsse_weight)
3909
            av->nsse_weight = 8;
3910
 
3911
        av->frame_skip_cmp = FF_CMP_DCTMAX;
3912
        if (!av->me_method)
3913
            av->me_method = ME_EPZS;
3914
        av->rc_buffer_aggressivity = 1.0;
3915
 
3916
        if (!av->rc_eq)
3917
            av->rc_eq = av_strdup("tex^qComp");
3918
        if (!av->i_quant_factor)
3919
            av->i_quant_factor = -0.8;
3920
        if (!av->b_quant_factor)
3921
            av->b_quant_factor = 1.25;
3922
        if (!av->b_quant_offset)
3923
            av->b_quant_offset = 1.25;
3924
        if (!av->rc_max_rate)
3925
            av->rc_max_rate = av->bit_rate * 2;
3926
 
3927
        if (av->rc_max_rate && !av->rc_buffer_size) {
3928
            av->rc_buffer_size = av->rc_max_rate;
3929
        }
3930
 
3931
 
3932
        break;
3933
    default:
3934
        abort();
3935
    }
3936
 
3937
    st = av_mallocz(sizeof(AVStream));
3938
    if (!st)
3939
        return;
3940
    st->codec = avcodec_alloc_context3(NULL);
3941
    stream->streams[stream->nb_streams++] = st;
3942
    memcpy(st->codec, av, sizeof(AVCodecContext));
3943
}
3944
 
3945
static enum AVCodecID opt_audio_codec(const char *arg)
3946
{
3947
    AVCodec *p= avcodec_find_encoder_by_name(arg);
3948
 
3949
    if (p == NULL || p->type != AVMEDIA_TYPE_AUDIO)
3950
        return AV_CODEC_ID_NONE;
3951
 
3952
    return p->id;
3953
}
3954
 
3955
static enum AVCodecID opt_video_codec(const char *arg)
3956
{
3957
    AVCodec *p= avcodec_find_encoder_by_name(arg);
3958
 
3959
    if (p == NULL || p->type != AVMEDIA_TYPE_VIDEO)
3960
        return AV_CODEC_ID_NONE;
3961
 
3962
    return p->id;
3963
}
3964
 
3965
static int ffserver_opt_default(const char *opt, const char *arg,
3966
                       AVCodecContext *avctx, int type)
3967
{
3968
    int ret = 0;
3969
    const AVOption *o = av_opt_find(avctx, opt, NULL, type, 0);
3970
    if(o)
3971
        ret = av_opt_set(avctx, opt, arg, 0);
3972
    return ret;
3973
}
3974
 
3975
static int ffserver_opt_preset(const char *arg,
3976
                       AVCodecContext *avctx, int type,
3977
                       enum AVCodecID *audio_id, enum AVCodecID *video_id)
3978
{
3979
    FILE *f=NULL;
3980
    char filename[1000], tmp[1000], tmp2[1000], line[1000];
3981
    int ret = 0;
3982
    AVCodec *codec = avcodec_find_encoder(avctx->codec_id);
3983
 
3984
    if (!(f = get_preset_file(filename, sizeof(filename), arg, 0,
3985
                              codec ? codec->name : NULL))) {
3986
        fprintf(stderr, "File for preset '%s' not found\n", arg);
3987
        return 1;
3988
    }
3989
 
3990
    while(!feof(f)){
3991
        int e= fscanf(f, "%999[^\n]\n", line) - 1;
3992
        if(line[0] == '#' && !e)
3993
            continue;
3994
        e|= sscanf(line, "%999[^=]=%999[^\n]\n", tmp, tmp2) - 2;
3995
        if(e){
3996
            fprintf(stderr, "%s: Invalid syntax: '%s'\n", filename, line);
3997
            ret = 1;
3998
            break;
3999
        }
4000
        if(!strcmp(tmp, "acodec")){
4001
            *audio_id = opt_audio_codec(tmp2);
4002
        }else if(!strcmp(tmp, "vcodec")){
4003
            *video_id = opt_video_codec(tmp2);
4004
        }else if(!strcmp(tmp, "scodec")){
4005
            /* opt_subtitle_codec(tmp2); */
4006
        }else if(ffserver_opt_default(tmp, tmp2, avctx, type) < 0){
4007
            fprintf(stderr, "%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", filename, line, tmp, tmp2);
4008
            ret = 1;
4009
            break;
4010
        }
4011
    }
4012
 
4013
    fclose(f);
4014
 
4015
    return ret;
4016
}
4017
 
4018
static AVOutputFormat *ffserver_guess_format(const char *short_name, const char *filename,
4019
                                             const char *mime_type)
4020
{
4021
    AVOutputFormat *fmt = av_guess_format(short_name, filename, mime_type);
4022
 
4023
    if (fmt) {
4024
        AVOutputFormat *stream_fmt;
4025
        char stream_format_name[64];
4026
 
4027
        snprintf(stream_format_name, sizeof(stream_format_name), "%s_stream", fmt->name);
4028
        stream_fmt = av_guess_format(stream_format_name, NULL, NULL);
4029
 
4030
        if (stream_fmt)
4031
            fmt = stream_fmt;
4032
    }
4033
 
4034
    return fmt;
4035
}
4036
 
4037
static void report_config_error(const char *filename, int line_num, int *errors, const char *fmt, ...)
4038
{
4039
    va_list vl;
4040
    va_start(vl, fmt);
4041
    fprintf(stderr, "%s:%d: ", filename, line_num);
4042
    vfprintf(stderr, fmt, vl);
4043
    va_end(vl);
4044
 
4045
    (*errors)++;
4046
}
4047
 
4048
static int parse_ffconfig(const char *filename)
4049
{
4050
    FILE *f;
4051
    char line[1024];
4052
    char cmd[64];
4053
    char arg[1024];
4054
    const char *p;
4055
    int val, errors, line_num;
4056
    FFStream **last_stream, *stream, *redirect;
4057
    FFStream **last_feed, *feed, *s;
4058
    AVCodecContext audio_enc, video_enc;
4059
    enum AVCodecID audio_id, video_id;
4060
 
4061
    f = fopen(filename, "r");
4062
    if (!f) {
4063
        perror(filename);
4064
        return -1;
4065
    }
4066
 
4067
    errors = 0;
4068
    line_num = 0;
4069
    first_stream = NULL;
4070
    last_stream = &first_stream;
4071
    first_feed = NULL;
4072
    last_feed = &first_feed;
4073
    stream = NULL;
4074
    feed = NULL;
4075
    redirect = NULL;
4076
    audio_id = AV_CODEC_ID_NONE;
4077
    video_id = AV_CODEC_ID_NONE;
4078
 
4079
#define ERROR(...) report_config_error(filename, line_num, &errors, __VA_ARGS__)
4080
    for(;;) {
4081
        if (fgets(line, sizeof(line), f) == NULL)
4082
            break;
4083
        line_num++;
4084
        p = line;
4085
        while (av_isspace(*p))
4086
            p++;
4087
        if (*p == '\0' || *p == '#')
4088
            continue;
4089
 
4090
        get_arg(cmd, sizeof(cmd), &p);
4091
 
4092
        if (!av_strcasecmp(cmd, "Port")) {
4093
            get_arg(arg, sizeof(arg), &p);
4094
            val = atoi(arg);
4095
            if (val < 1 || val > 65536) {
4096
                ERROR("Invalid_port: %s\n", arg);
4097
            }
4098
            my_http_addr.sin_port = htons(val);
4099
        } else if (!av_strcasecmp(cmd, "BindAddress")) {
4100
            get_arg(arg, sizeof(arg), &p);
4101
            if (resolve_host(&my_http_addr.sin_addr, arg) != 0) {
4102
                ERROR("%s:%d: Invalid host/IP address: %s\n", arg);
4103
            }
4104
        } else if (!av_strcasecmp(cmd, "NoDaemon")) {
4105
            // do nothing here, its the default now
4106
        } else if (!av_strcasecmp(cmd, "RTSPPort")) {
4107
            get_arg(arg, sizeof(arg), &p);
4108
            val = atoi(arg);
4109
            if (val < 1 || val > 65536) {
4110
                ERROR("%s:%d: Invalid port: %s\n", arg);
4111
            }
4112
            my_rtsp_addr.sin_port = htons(atoi(arg));
4113
        } else if (!av_strcasecmp(cmd, "RTSPBindAddress")) {
4114
            get_arg(arg, sizeof(arg), &p);
4115
            if (resolve_host(&my_rtsp_addr.sin_addr, arg) != 0) {
4116
                ERROR("Invalid host/IP address: %s\n", arg);
4117
            }
4118
        } else if (!av_strcasecmp(cmd, "MaxHTTPConnections")) {
4119
            get_arg(arg, sizeof(arg), &p);
4120
            val = atoi(arg);
4121
            if (val < 1 || val > 65536) {
4122
                ERROR("Invalid MaxHTTPConnections: %s\n", arg);
4123
            }
4124
            nb_max_http_connections = val;
4125
        } else if (!av_strcasecmp(cmd, "MaxClients")) {
4126
            get_arg(arg, sizeof(arg), &p);
4127
            val = atoi(arg);
4128
            if (val < 1 || val > nb_max_http_connections) {
4129
                ERROR("Invalid MaxClients: %s\n", arg);
4130
            } else {
4131
                nb_max_connections = val;
4132
            }
4133
        } else if (!av_strcasecmp(cmd, "MaxBandwidth")) {
4134
            int64_t llval;
4135
            get_arg(arg, sizeof(arg), &p);
4136
            llval = strtoll(arg, NULL, 10);
4137
            if (llval < 10 || llval > 10000000) {
4138
                ERROR("Invalid MaxBandwidth: %s\n", arg);
4139
            } else
4140
                max_bandwidth = llval;
4141
        } else if (!av_strcasecmp(cmd, "CustomLog")) {
4142
            if (!ffserver_debug)
4143
                get_arg(logfilename, sizeof(logfilename), &p);
4144
        } else if (!av_strcasecmp(cmd, "
4145
            /*********************************************/
4146
            /* Feed related options */
4147
            char *q;
4148
            if (stream || feed) {
4149
                ERROR("Already in a tag\n");
4150
            } else {
4151
                feed = av_mallocz(sizeof(FFStream));
4152
                get_arg(feed->filename, sizeof(feed->filename), &p);
4153
                q = strrchr(feed->filename, '>');
4154
                if (*q)
4155
                    *q = '\0';
4156
 
4157
                for (s = first_feed; s; s = s->next) {
4158
                    if (!strcmp(feed->filename, s->filename)) {
4159
                        ERROR("Feed '%s' already registered\n", s->filename);
4160
                    }
4161
                }
4162
 
4163
                feed->fmt = av_guess_format("ffm", NULL, NULL);
4164
                /* defaut feed file */
4165
                snprintf(feed->feed_filename, sizeof(feed->feed_filename),
4166
                         "/tmp/%s.ffm", feed->filename);
4167
                feed->feed_max_size = 5 * 1024 * 1024;
4168
                feed->is_feed = 1;
4169
                feed->feed = feed; /* self feeding :-) */
4170
 
4171
                /* add in stream list */
4172
                *last_stream = feed;
4173
                last_stream = &feed->next;
4174
                /* add in feed list */
4175
                *last_feed = feed;
4176
                last_feed = &feed->next_feed;
4177
            }
4178
        } else if (!av_strcasecmp(cmd, "Launch")) {
4179
            if (feed) {
4180
                int i;
4181
 
4182
                feed->child_argv = av_mallocz(64 * sizeof(char *));
4183
 
4184
                for (i = 0; i < 62; i++) {
4185
                    get_arg(arg, sizeof(arg), &p);
4186
                    if (!arg[0])
4187
                        break;
4188
 
4189
                    feed->child_argv[i] = av_strdup(arg);
4190
                }
4191
 
4192
                feed->child_argv[i] = av_asprintf("http://%s:%d/%s",
4193
                        (my_http_addr.sin_addr.s_addr == INADDR_ANY) ? "127.0.0.1" :
4194
                    inet_ntoa(my_http_addr.sin_addr),
4195
                    ntohs(my_http_addr.sin_port), feed->filename);
4196
            }
4197
        } else if (!av_strcasecmp(cmd, "ReadOnlyFile")) {
4198
            if (feed) {
4199
                get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
4200
                feed->readonly = 1;
4201
            } else if (stream) {
4202
                get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4203
            }
4204
        } else if (!av_strcasecmp(cmd, "File")) {
4205
            if (feed) {
4206
                get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
4207
            } else if (stream)
4208
                get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4209
        } else if (!av_strcasecmp(cmd, "Truncate")) {
4210
            if (feed) {
4211
                get_arg(arg, sizeof(arg), &p);
4212
                feed->truncate = strtod(arg, NULL);
4213
            }
4214
        } else if (!av_strcasecmp(cmd, "FileMaxSize")) {
4215
            if (feed) {
4216
                char *p1;
4217
                double fsize;
4218
 
4219
                get_arg(arg, sizeof(arg), &p);
4220
                p1 = arg;
4221
                fsize = strtod(p1, &p1);
4222
                switch(av_toupper(*p1)) {
4223
                case 'K':
4224
                    fsize *= 1024;
4225
                    break;
4226
                case 'M':
4227
                    fsize *= 1024 * 1024;
4228
                    break;
4229
                case 'G':
4230
                    fsize *= 1024 * 1024 * 1024;
4231
                    break;
4232
                }
4233
                feed->feed_max_size = (int64_t)fsize;
4234
                if (feed->feed_max_size < FFM_PACKET_SIZE*4) {
4235
                    ERROR("Feed max file size is too small, must be at least %d\n", FFM_PACKET_SIZE*4);
4236
                }
4237
            }
4238
        } else if (!av_strcasecmp(cmd, "")) {
4239
            if (!feed) {
4240
                ERROR("No corresponding  for \n");
4241
            }
4242
            feed = NULL;
4243
        } else if (!av_strcasecmp(cmd, "
4244
            /*********************************************/
4245
            /* Stream related options */
4246
            char *q;
4247
            if (stream || feed) {
4248
                ERROR("Already in a tag\n");
4249
            } else {
4250
                FFStream *s;
4251
                stream = av_mallocz(sizeof(FFStream));
4252
                get_arg(stream->filename, sizeof(stream->filename), &p);
4253
                q = strrchr(stream->filename, '>');
4254
                if (q)
4255
                    *q = '\0';
4256
 
4257
                for (s = first_stream; s; s = s->next) {
4258
                    if (!strcmp(stream->filename, s->filename)) {
4259
                        ERROR("Stream '%s' already registered\n", s->filename);
4260
                    }
4261
                }
4262
 
4263
                stream->fmt = ffserver_guess_format(NULL, stream->filename, NULL);
4264
                avcodec_get_context_defaults3(&video_enc, NULL);
4265
                avcodec_get_context_defaults3(&audio_enc, NULL);
4266
 
4267
                audio_id = AV_CODEC_ID_NONE;
4268
                video_id = AV_CODEC_ID_NONE;
4269
                if (stream->fmt) {
4270
                    audio_id = stream->fmt->audio_codec;
4271
                    video_id = stream->fmt->video_codec;
4272
                }
4273
 
4274
                *last_stream = stream;
4275
                last_stream = &stream->next;
4276
            }
4277
        } else if (!av_strcasecmp(cmd, "Feed")) {
4278
            get_arg(arg, sizeof(arg), &p);
4279
            if (stream) {
4280
                FFStream *sfeed;
4281
 
4282
                sfeed = first_feed;
4283
                while (sfeed != NULL) {
4284
                    if (!strcmp(sfeed->filename, arg))
4285
                        break;
4286
                    sfeed = sfeed->next_feed;
4287
                }
4288
                if (!sfeed)
4289
                    ERROR("feed '%s' not defined\n", arg);
4290
                else
4291
                    stream->feed = sfeed;
4292
            }
4293
        } else if (!av_strcasecmp(cmd, "Format")) {
4294
            get_arg(arg, sizeof(arg), &p);
4295
            if (stream) {
4296
                if (!strcmp(arg, "status")) {
4297
                    stream->stream_type = STREAM_TYPE_STATUS;
4298
                    stream->fmt = NULL;
4299
                } else {
4300
                    stream->stream_type = STREAM_TYPE_LIVE;
4301
                    /* jpeg cannot be used here, so use single frame jpeg */
4302
                    if (!strcmp(arg, "jpeg"))
4303
                        strcpy(arg, "mjpeg");
4304
                    stream->fmt = ffserver_guess_format(arg, NULL, NULL);
4305
                    if (!stream->fmt) {
4306
                        ERROR("Unknown Format: %s\n", arg);
4307
                    }
4308
                }
4309
                if (stream->fmt) {
4310
                    audio_id = stream->fmt->audio_codec;
4311
                    video_id = stream->fmt->video_codec;
4312
                }
4313
            }
4314
        } else if (!av_strcasecmp(cmd, "InputFormat")) {
4315
            get_arg(arg, sizeof(arg), &p);
4316
            if (stream) {
4317
                stream->ifmt = av_find_input_format(arg);
4318
                if (!stream->ifmt) {
4319
                    ERROR("Unknown input format: %s\n", arg);
4320
                }
4321
            }
4322
        } else if (!av_strcasecmp(cmd, "FaviconURL")) {
4323
            if (stream && stream->stream_type == STREAM_TYPE_STATUS) {
4324
                get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4325
            } else {
4326
                ERROR("FaviconURL only permitted for status streams\n");
4327
            }
4328
        } else if (!av_strcasecmp(cmd, "Author")) {
4329
            if (stream)
4330
                get_arg(stream->author, sizeof(stream->author), &p);
4331
        } else if (!av_strcasecmp(cmd, "Comment")) {
4332
            if (stream)
4333
                get_arg(stream->comment, sizeof(stream->comment), &p);
4334
        } else if (!av_strcasecmp(cmd, "Copyright")) {
4335
            if (stream)
4336
                get_arg(stream->copyright, sizeof(stream->copyright), &p);
4337
        } else if (!av_strcasecmp(cmd, "Title")) {
4338
            if (stream)
4339
                get_arg(stream->title, sizeof(stream->title), &p);
4340
        } else if (!av_strcasecmp(cmd, "Preroll")) {
4341
            get_arg(arg, sizeof(arg), &p);
4342
            if (stream)
4343
                stream->prebuffer = atof(arg) * 1000;
4344
        } else if (!av_strcasecmp(cmd, "StartSendOnKey")) {
4345
            if (stream)
4346
                stream->send_on_key = 1;
4347
        } else if (!av_strcasecmp(cmd, "AudioCodec")) {
4348
            get_arg(arg, sizeof(arg), &p);
4349
            audio_id = opt_audio_codec(arg);
4350
            if (audio_id == AV_CODEC_ID_NONE) {
4351
                ERROR("Unknown AudioCodec: %s\n", arg);
4352
            }
4353
        } else if (!av_strcasecmp(cmd, "VideoCodec")) {
4354
            get_arg(arg, sizeof(arg), &p);
4355
            video_id = opt_video_codec(arg);
4356
            if (video_id == AV_CODEC_ID_NONE) {
4357
                ERROR("Unknown VideoCodec: %s\n", arg);
4358
            }
4359
        } else if (!av_strcasecmp(cmd, "MaxTime")) {
4360
            get_arg(arg, sizeof(arg), &p);
4361
            if (stream)
4362
                stream->max_time = atof(arg) * 1000;
4363
        } else if (!av_strcasecmp(cmd, "AudioBitRate")) {
4364
            get_arg(arg, sizeof(arg), &p);
4365
            if (stream)
4366
                audio_enc.bit_rate = lrintf(atof(arg) * 1000);
4367
        } else if (!av_strcasecmp(cmd, "AudioChannels")) {
4368
            get_arg(arg, sizeof(arg), &p);
4369
            if (stream)
4370
                audio_enc.channels = atoi(arg);
4371
        } else if (!av_strcasecmp(cmd, "AudioSampleRate")) {
4372
            get_arg(arg, sizeof(arg), &p);
4373
            if (stream)
4374
                audio_enc.sample_rate = atoi(arg);
4375
        } else if (!av_strcasecmp(cmd, "AudioQuality")) {
4376
            get_arg(arg, sizeof(arg), &p);
4377
            if (stream) {
4378
//                audio_enc.quality = atof(arg) * 1000;
4379
            }
4380
        } else if (!av_strcasecmp(cmd, "VideoBitRateRange")) {
4381
            if (stream) {
4382
                int minrate, maxrate;
4383
 
4384
                get_arg(arg, sizeof(arg), &p);
4385
 
4386
                if (sscanf(arg, "%d-%d", &minrate, &maxrate) == 2) {
4387
                    video_enc.rc_min_rate = minrate * 1000;
4388
                    video_enc.rc_max_rate = maxrate * 1000;
4389
                } else {
4390
                    ERROR("Incorrect format for VideoBitRateRange -- should be -: %s\n", arg);
4391
                }
4392
            }
4393
        } else if (!av_strcasecmp(cmd, "Debug")) {
4394
            if (stream) {
4395
                get_arg(arg, sizeof(arg), &p);
4396
                video_enc.debug = strtol(arg,0,0);
4397
            }
4398
        } else if (!av_strcasecmp(cmd, "Strict")) {
4399
            if (stream) {
4400
                get_arg(arg, sizeof(arg), &p);
4401
                video_enc.strict_std_compliance = atoi(arg);
4402
            }
4403
        } else if (!av_strcasecmp(cmd, "VideoBufferSize")) {
4404
            if (stream) {
4405
                get_arg(arg, sizeof(arg), &p);
4406
                video_enc.rc_buffer_size = atoi(arg) * 8*1024;
4407
            }
4408
        } else if (!av_strcasecmp(cmd, "VideoBitRateTolerance")) {
4409
            if (stream) {
4410
                get_arg(arg, sizeof(arg), &p);
4411
                video_enc.bit_rate_tolerance = atoi(arg) * 1000;
4412
            }
4413
        } else if (!av_strcasecmp(cmd, "VideoBitRate")) {
4414
            get_arg(arg, sizeof(arg), &p);
4415
            if (stream) {
4416
                video_enc.bit_rate = atoi(arg) * 1000;
4417
            }
4418
        } else if (!av_strcasecmp(cmd, "VideoSize")) {
4419
            get_arg(arg, sizeof(arg), &p);
4420
            if (stream) {
4421
                av_parse_video_size(&video_enc.width, &video_enc.height, arg);
4422
                if ((video_enc.width % 16) != 0 ||
4423
                    (video_enc.height % 16) != 0) {
4424
                    ERROR("Image size must be a multiple of 16\n");
4425
                }
4426
            }
4427
        } else if (!av_strcasecmp(cmd, "VideoFrameRate")) {
4428
            get_arg(arg, sizeof(arg), &p);
4429
            if (stream) {
4430
                AVRational frame_rate;
4431
                if (av_parse_video_rate(&frame_rate, arg) < 0) {
4432
                    ERROR("Incorrect frame rate: %s\n", arg);
4433
                } else {
4434
                    video_enc.time_base.num = frame_rate.den;
4435
                    video_enc.time_base.den = frame_rate.num;
4436
                }
4437
            }
4438
        } else if (!av_strcasecmp(cmd, "PixelFormat")) {
4439
            get_arg(arg, sizeof(arg), &p);
4440
            if (stream) {
4441
                video_enc.pix_fmt = av_get_pix_fmt(arg);
4442
                if (video_enc.pix_fmt == AV_PIX_FMT_NONE) {
4443
                    ERROR("Unknown pixel format: %s\n", arg);
4444
                }
4445
            }
4446
        } else if (!av_strcasecmp(cmd, "VideoGopSize")) {
4447
            get_arg(arg, sizeof(arg), &p);
4448
            if (stream)
4449
                video_enc.gop_size = atoi(arg);
4450
        } else if (!av_strcasecmp(cmd, "VideoIntraOnly")) {
4451
            if (stream)
4452
                video_enc.gop_size = 1;
4453
        } else if (!av_strcasecmp(cmd, "VideoHighQuality")) {
4454
            if (stream)
4455
                video_enc.mb_decision = FF_MB_DECISION_BITS;
4456
        } else if (!av_strcasecmp(cmd, "Video4MotionVector")) {
4457
            if (stream) {
4458
                video_enc.mb_decision = FF_MB_DECISION_BITS; //FIXME remove
4459
                video_enc.flags |= CODEC_FLAG_4MV;
4460
            }
4461
        } else if (!av_strcasecmp(cmd, "AVOptionVideo") ||
4462
                   !av_strcasecmp(cmd, "AVOptionAudio")) {
4463
            char arg2[1024];
4464
            AVCodecContext *avctx;
4465
            int type;
4466
            get_arg(arg, sizeof(arg), &p);
4467
            get_arg(arg2, sizeof(arg2), &p);
4468
            if (!av_strcasecmp(cmd, "AVOptionVideo")) {
4469
                avctx = &video_enc;
4470
                type = AV_OPT_FLAG_VIDEO_PARAM;
4471
            } else {
4472
                avctx = &audio_enc;
4473
                type = AV_OPT_FLAG_AUDIO_PARAM;
4474
            }
4475
            if (ffserver_opt_default(arg, arg2, avctx, type|AV_OPT_FLAG_ENCODING_PARAM)) {
4476
                ERROR("AVOption error: %s %s\n", arg, arg2);
4477
            }
4478
        } else if (!av_strcasecmp(cmd, "AVPresetVideo") ||
4479
                   !av_strcasecmp(cmd, "AVPresetAudio")) {
4480
            AVCodecContext *avctx;
4481
            int type;
4482
            get_arg(arg, sizeof(arg), &p);
4483
            if (!av_strcasecmp(cmd, "AVPresetVideo")) {
4484
                avctx = &video_enc;
4485
                video_enc.codec_id = video_id;
4486
                type = AV_OPT_FLAG_VIDEO_PARAM;
4487
            } else {
4488
                avctx = &audio_enc;
4489
                audio_enc.codec_id = audio_id;
4490
                type = AV_OPT_FLAG_AUDIO_PARAM;
4491
            }
4492
            if (ffserver_opt_preset(arg, avctx, type|AV_OPT_FLAG_ENCODING_PARAM, &audio_id, &video_id)) {
4493
                ERROR("AVPreset error: %s\n", arg);
4494
            }
4495
        } else if (!av_strcasecmp(cmd, "VideoTag")) {
4496
            get_arg(arg, sizeof(arg), &p);
4497
            if ((strlen(arg) == 4) && stream)
4498
                video_enc.codec_tag = MKTAG(arg[0], arg[1], arg[2], arg[3]);
4499
        } else if (!av_strcasecmp(cmd, "BitExact")) {
4500
            if (stream)
4501
                video_enc.flags |= CODEC_FLAG_BITEXACT;
4502
        } else if (!av_strcasecmp(cmd, "DctFastint")) {
4503
            if (stream)
4504
                video_enc.dct_algo  = FF_DCT_FASTINT;
4505
        } else if (!av_strcasecmp(cmd, "IdctSimple")) {
4506
            if (stream)
4507
                video_enc.idct_algo = FF_IDCT_SIMPLE;
4508
        } else if (!av_strcasecmp(cmd, "Qscale")) {
4509
            get_arg(arg, sizeof(arg), &p);
4510
            if (stream) {
4511
                video_enc.flags |= CODEC_FLAG_QSCALE;
4512
                video_enc.global_quality = FF_QP2LAMBDA * atoi(arg);
4513
            }
4514
        } else if (!av_strcasecmp(cmd, "VideoQDiff")) {
4515
            get_arg(arg, sizeof(arg), &p);
4516
            if (stream) {
4517
                video_enc.max_qdiff = atoi(arg);
4518
                if (video_enc.max_qdiff < 1 || video_enc.max_qdiff > 31) {
4519
                    ERROR("VideoQDiff out of range\n");
4520
                }
4521
            }
4522
        } else if (!av_strcasecmp(cmd, "VideoQMax")) {
4523
            get_arg(arg, sizeof(arg), &p);
4524
            if (stream) {
4525
                video_enc.qmax = atoi(arg);
4526
                if (video_enc.qmax < 1 || video_enc.qmax > 31) {
4527
                    ERROR("VideoQMax out of range\n");
4528
                }
4529
            }
4530
        } else if (!av_strcasecmp(cmd, "VideoQMin")) {
4531
            get_arg(arg, sizeof(arg), &p);
4532
            if (stream) {
4533
                video_enc.qmin = atoi(arg);
4534
                if (video_enc.qmin < 1 || video_enc.qmin > 31) {
4535
                    ERROR("VideoQMin out of range\n");
4536
                }
4537
            }
4538
        } else if (!av_strcasecmp(cmd, "LumiMask")) {
4539
            get_arg(arg, sizeof(arg), &p);
4540
            if (stream)
4541
                video_enc.lumi_masking = atof(arg);
4542
        } else if (!av_strcasecmp(cmd, "DarkMask")) {
4543
            get_arg(arg, sizeof(arg), &p);
4544
            if (stream)
4545
                video_enc.dark_masking = atof(arg);
4546
        } else if (!av_strcasecmp(cmd, "NoVideo")) {
4547
            video_id = AV_CODEC_ID_NONE;
4548
        } else if (!av_strcasecmp(cmd, "NoAudio")) {
4549
            audio_id = AV_CODEC_ID_NONE;
4550
        } else if (!av_strcasecmp(cmd, "ACL")) {
4551
            parse_acl_row(stream, feed, NULL, p, filename, line_num);
4552
        } else if (!av_strcasecmp(cmd, "DynamicACL")) {
4553
            if (stream) {
4554
                get_arg(stream->dynamic_acl, sizeof(stream->dynamic_acl), &p);
4555
            }
4556
        } else if (!av_strcasecmp(cmd, "RTSPOption")) {
4557
            get_arg(arg, sizeof(arg), &p);
4558
            if (stream) {
4559
                av_freep(&stream->rtsp_option);
4560
                stream->rtsp_option = av_strdup(arg);
4561
            }
4562
        } else if (!av_strcasecmp(cmd, "MulticastAddress")) {
4563
            get_arg(arg, sizeof(arg), &p);
4564
            if (stream) {
4565
                if (resolve_host(&stream->multicast_ip, arg) != 0) {
4566
                    ERROR("Invalid host/IP address: %s\n", arg);
4567
                }
4568
                stream->is_multicast = 1;
4569
                stream->loop = 1; /* default is looping */
4570
            }
4571
        } else if (!av_strcasecmp(cmd, "MulticastPort")) {
4572
            get_arg(arg, sizeof(arg), &p);
4573
            if (stream)
4574
                stream->multicast_port = atoi(arg);
4575
        } else if (!av_strcasecmp(cmd, "MulticastTTL")) {
4576
            get_arg(arg, sizeof(arg), &p);
4577
            if (stream)
4578
                stream->multicast_ttl = atoi(arg);
4579
        } else if (!av_strcasecmp(cmd, "NoLoop")) {
4580
            if (stream)
4581
                stream->loop = 0;
4582
        } else if (!av_strcasecmp(cmd, "")) {
4583
            if (!stream) {
4584
                ERROR("No corresponding  for \n");
4585
            } else {
4586
                if (stream->feed && stream->fmt && strcmp(stream->fmt->name, "ffm") != 0) {
4587
                    if (audio_id != AV_CODEC_ID_NONE) {
4588
                        audio_enc.codec_type = AVMEDIA_TYPE_AUDIO;
4589
                        audio_enc.codec_id = audio_id;
4590
                        add_codec(stream, &audio_enc);
4591
                    }
4592
                    if (video_id != AV_CODEC_ID_NONE) {
4593
                        video_enc.codec_type = AVMEDIA_TYPE_VIDEO;
4594
                        video_enc.codec_id = video_id;
4595
                        add_codec(stream, &video_enc);
4596
                    }
4597
                }
4598
                stream = NULL;
4599
            }
4600
        } else if (!av_strcasecmp(cmd, "
4601
            /*********************************************/
4602
            char *q;
4603
            if (stream || feed || redirect) {
4604
                ERROR("Already in a tag\n");
4605
            } else {
4606
                redirect = av_mallocz(sizeof(FFStream));
4607
                *last_stream = redirect;
4608
                last_stream = &redirect->next;
4609
 
4610
                get_arg(redirect->filename, sizeof(redirect->filename), &p);
4611
                q = strrchr(redirect->filename, '>');
4612
                if (*q)
4613
                    *q = '\0';
4614
                redirect->stream_type = STREAM_TYPE_REDIRECT;
4615
            }
4616
        } else if (!av_strcasecmp(cmd, "URL")) {
4617
            if (redirect)
4618
                get_arg(redirect->feed_filename, sizeof(redirect->feed_filename), &p);
4619
        } else if (!av_strcasecmp(cmd, "")) {
4620
            if (!redirect) {
4621
                ERROR("No corresponding  for \n");
4622
            } else {
4623
                if (!redirect->feed_filename[0]) {
4624
                    ERROR("No URL found for \n");
4625
                }
4626
                redirect = NULL;
4627
            }
4628
        } else if (!av_strcasecmp(cmd, "LoadModule")) {
4629
            ERROR("Loadable modules no longer supported\n");
4630
        } else {
4631
            ERROR("Incorrect keyword: '%s'\n", cmd);
4632
        }
4633
    }
4634
#undef ERROR
4635
 
4636
    fclose(f);
4637
    if (errors)
4638
        return -1;
4639
    else
4640
        return 0;
4641
}
4642
 
4643
static void handle_child_exit(int sig)
4644
{
4645
    pid_t pid;
4646
    int status;
4647
 
4648
    while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
4649
        FFStream *feed;
4650
 
4651
        for (feed = first_feed; feed; feed = feed->next) {
4652
            if (feed->pid == pid) {
4653
                int uptime = time(0) - feed->pid_start;
4654
 
4655
                feed->pid = 0;
4656
                fprintf(stderr, "%s: Pid %d exited with status %d after %d seconds\n", feed->filename, pid, status, uptime);
4657
 
4658
                if (uptime < 30)
4659
                    /* Turn off any more restarts */
4660
                    feed->child_argv = 0;
4661
            }
4662
        }
4663
    }
4664
 
4665
    need_to_start_children = 1;
4666
}
4667
 
4668
static void opt_debug(void)
4669
{
4670
    ffserver_debug = 1;
4671
    logfilename[0] = '-';
4672
}
4673
 
4674
void show_help_default(const char *opt, const char *arg)
4675
{
4676
    printf("usage: ffserver [options]\n"
4677
           "Hyper fast multi format Audio/Video streaming server\n");
4678
    printf("\n");
4679
    show_help_options(options, "Main options:", 0, 0, 0);
4680
}
4681
 
4682
static const OptionDef options[] = {
4683
#include "cmdutils_common_opts.h"
4684
    { "n", OPT_BOOL, {(void *)&no_launch }, "enable no-launch mode" },
4685
    { "d", 0, {(void*)opt_debug}, "enable debug mode" },
4686
    { "f", HAS_ARG | OPT_STRING, {(void*)&config_filename }, "use configfile instead of /etc/ffserver.conf", "configfile" },
4687
    { NULL },
4688
};
4689
 
4690
int main(int argc, char **argv)
4691
{
4692
    struct sigaction sigact = { { 0 } };
4693
 
4694
    config_filename = av_strdup("/etc/ffserver.conf");
4695
 
4696
    parse_loglevel(argc, argv, options);
4697
    av_register_all();
4698
    avformat_network_init();
4699
 
4700
    show_banner(argc, argv, options);
4701
 
4702
    my_program_name = argv[0];
4703
 
4704
    parse_options(NULL, argc, argv, options, NULL);
4705
 
4706
    unsetenv("http_proxy");             /* Kill the http_proxy */
4707
 
4708
    av_lfg_init(&random_state, av_get_random_seed());
4709
 
4710
    sigact.sa_handler = handle_child_exit;
4711
    sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
4712
    sigaction(SIGCHLD, &sigact, 0);
4713
 
4714
    if (parse_ffconfig(config_filename) < 0) {
4715
        fprintf(stderr, "Incorrect config file - exiting.\n");
4716
        exit(1);
4717
    }
4718
    av_freep(&config_filename);
4719
 
4720
    /* open log file if needed */
4721
    if (logfilename[0] != '\0') {
4722
        if (!strcmp(logfilename, "-"))
4723
            logfile = stdout;
4724
        else
4725
            logfile = fopen(logfilename, "a");
4726
        av_log_set_callback(http_av_log);
4727
    }
4728
 
4729
    build_file_streams();
4730
 
4731
    build_feed_streams();
4732
 
4733
    compute_bandwidth();
4734
 
4735
    /* signal init */
4736
    signal(SIGPIPE, SIG_IGN);
4737
 
4738
    if (http_server() < 0) {
4739
        http_log("Could not start server\n");
4740
        exit(1);
4741
    }
4742
 
4743
    return 0;
4744
}