Statistics
| Branch: | Revision:

ffmpeg / ffserver.c @ 3ee53dab

History | View | Annotate | Download (155 KB)

1
/*
2
 * Multiple format streaming server
3
 * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
4
 *
5
 * This file is part of Libav.
6
 *
7
 * Libav is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * Libav is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with Libav; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21

    
22
#define _XOPEN_SOURCE 600
23

    
24
#include "config.h"
25
#if !HAVE_CLOSESOCKET
26
#define closesocket close
27
#endif
28
#include <string.h>
29
#include <strings.h>
30
#include <stdlib.h>
31
#include "libavformat/avformat.h"
32
#include "libavformat/ffm.h"
33
#include "libavformat/network.h"
34
#include "libavformat/os_support.h"
35
#include "libavformat/rtpdec.h"
36
#include "libavformat/rtsp.h"
37
// XXX for ffio_open_dyn_packet_buffer, to be removed
38
#include "libavformat/avio_internal.h"
39
#include "libavutil/avstring.h"
40
#include "libavutil/lfg.h"
41
#include "libavutil/random_seed.h"
42
#include "libavutil/parseutils.h"
43
#include "libavcodec/opt.h"
44
#include <stdarg.h>
45
#include <unistd.h>
46
#include <fcntl.h>
47
#include <sys/ioctl.h>
48
#if HAVE_POLL_H
49
#include <poll.h>
50
#endif
51
#include <errno.h>
52
#include <sys/time.h>
53
#include <time.h>
54
#include <sys/wait.h>
55
#include <signal.h>
56
#if HAVE_DLFCN_H
57
#include <dlfcn.h>
58
#endif
59

    
60
#include "cmdutils.h"
61

    
62
const char program_name[] = "FFserver";
63
const int program_birth_year = 2000;
64

    
65
static const OptionDef options[];
66

    
67
enum HTTPState {
68
    HTTPSTATE_WAIT_REQUEST,
69
    HTTPSTATE_SEND_HEADER,
70
    HTTPSTATE_SEND_DATA_HEADER,
71
    HTTPSTATE_SEND_DATA,          /* sending TCP or UDP data */
72
    HTTPSTATE_SEND_DATA_TRAILER,
73
    HTTPSTATE_RECEIVE_DATA,
74
    HTTPSTATE_WAIT_FEED,          /* wait for data from the feed */
75
    HTTPSTATE_READY,
76

    
77
    RTSPSTATE_WAIT_REQUEST,
78
    RTSPSTATE_SEND_REPLY,
79
    RTSPSTATE_SEND_PACKET,
80
};
81

    
82
static const char *http_state[] = {
83
    "HTTP_WAIT_REQUEST",
84
    "HTTP_SEND_HEADER",
85

    
86
    "SEND_DATA_HEADER",
87
    "SEND_DATA",
88
    "SEND_DATA_TRAILER",
89
    "RECEIVE_DATA",
90
    "WAIT_FEED",
91
    "READY",
92

    
93
    "RTSP_WAIT_REQUEST",
94
    "RTSP_SEND_REPLY",
95
    "RTSP_SEND_PACKET",
96
};
97

    
98
#if !FF_API_MAX_STREAMS
99
#define MAX_STREAMS 20
100
#endif
101

    
102
#define IOBUFFER_INIT_SIZE 8192
103

    
104
/* timeouts are in ms */
105
#define HTTP_REQUEST_TIMEOUT (15 * 1000)
106
#define RTSP_REQUEST_TIMEOUT (3600 * 24 * 1000)
107

    
108
#define SYNC_TIMEOUT (10 * 1000)
109

    
110
typedef struct RTSPActionServerSetup {
111
    uint32_t ipaddr;
112
    char transport_option[512];
113
} RTSPActionServerSetup;
114

    
115
typedef struct {
116
    int64_t count1, count2;
117
    int64_t time1, time2;
118
} DataRateData;
119

    
120
/* context associated with one connection */
121
typedef struct HTTPContext {
122
    enum HTTPState state;
123
    int fd; /* socket file descriptor */
124
    struct sockaddr_in from_addr; /* origin */
125
    struct pollfd *poll_entry; /* used when polling */
126
    int64_t timeout;
127
    uint8_t *buffer_ptr, *buffer_end;
128
    int http_error;
129
    int post;
130
    int chunked_encoding;
131
    int chunk_size;               /* 0 if it needs to be read */
132
    struct HTTPContext *next;
133
    int got_key_frame; /* stream 0 => 1, stream 1 => 2, stream 2=> 4 */
134
    int64_t data_count;
135
    /* feed input */
136
    int feed_fd;
137
    /* input format handling */
138
    AVFormatContext *fmt_in;
139
    int64_t start_time;            /* In milliseconds - this wraps fairly often */
140
    int64_t first_pts;            /* initial pts value */
141
    int64_t cur_pts;             /* current pts value from the stream in us */
142
    int64_t cur_frame_duration;  /* duration of the current frame in us */
143
    int cur_frame_bytes;       /* output frame size, needed to compute
144
                                  the time at which we send each
145
                                  packet */
146
    int pts_stream_index;        /* stream we choose as clock reference */
147
    int64_t cur_clock;           /* current clock reference value in us */
148
    /* output format handling */
149
    struct FFStream *stream;
150
    /* -1 is invalid stream */
151
    int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
152
    int switch_feed_streams[MAX_STREAMS]; /* index of streams in the feed */
153
    int switch_pending;
154
    AVFormatContext fmt_ctx; /* instance of FFStream for one user */
155
    int last_packet_sent; /* true if last data packet was sent */
156
    int suppress_log;
157
    DataRateData datarate;
158
    int wmp_client_id;
159
    char protocol[16];
160
    char method[16];
161
    char url[128];
162
    int buffer_size;
163
    uint8_t *buffer;
164
    int is_packetized; /* if true, the stream is packetized */
165
    int packet_stream_index; /* current stream for output in state machine */
166

    
167
    /* RTSP state specific */
168
    uint8_t *pb_buffer; /* XXX: use that in all the code */
169
    AVIOContext *pb;
170
    int seq; /* RTSP sequence number */
171

    
172
    /* RTP state specific */
173
    enum RTSPLowerTransport rtp_protocol;
174
    char session_id[32]; /* session id */
175
    AVFormatContext *rtp_ctx[MAX_STREAMS];
176

    
177
    /* RTP/UDP specific */
178
    URLContext *rtp_handles[MAX_STREAMS];
179

    
180
    /* RTP/TCP specific */
181
    struct HTTPContext *rtsp_c;
182
    uint8_t *packet_buffer, *packet_buffer_ptr, *packet_buffer_end;
183
} HTTPContext;
184

    
185
/* each generated stream is described here */
186
enum StreamType {
187
    STREAM_TYPE_LIVE,
188
    STREAM_TYPE_STATUS,
189
    STREAM_TYPE_REDIRECT,
190
};
191

    
192
enum IPAddressAction {
193
    IP_ALLOW = 1,
194
    IP_DENY,
195
};
196

    
197
typedef struct IPAddressACL {
198
    struct IPAddressACL *next;
199
    enum IPAddressAction action;
200
    /* These are in host order */
201
    struct in_addr first;
202
    struct in_addr last;
203
} IPAddressACL;
204

    
205
/* description of each stream of the ffserver.conf file */
206
typedef struct FFStream {
207
    enum StreamType stream_type;
208
    char filename[1024];     /* stream filename */
209
    struct FFStream *feed;   /* feed we are using (can be null if
210
                                coming from file) */
211
    AVFormatParameters *ap_in; /* input parameters */
212
    AVInputFormat *ifmt;       /* if non NULL, force input format */
213
    AVOutputFormat *fmt;
214
    IPAddressACL *acl;
215
    char dynamic_acl[1024];
216
    int nb_streams;
217
    int prebuffer;      /* Number of millseconds early to start */
218
    int64_t max_time;      /* Number of milliseconds to run */
219
    int send_on_key;
220
    AVStream *streams[MAX_STREAMS];
221
    int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
222
    char feed_filename[1024]; /* file name of the feed storage, or
223
                                 input file name for a stream */
224
    char author[512];
225
    char title[512];
226
    char copyright[512];
227
    char comment[512];
228
    pid_t pid;  /* Of ffmpeg process */
229
    time_t pid_start;  /* Of ffmpeg process */
230
    char **child_argv;
231
    struct FFStream *next;
232
    unsigned bandwidth; /* bandwidth, in kbits/s */
233
    /* RTSP options */
234
    char *rtsp_option;
235
    /* multicast specific */
236
    int is_multicast;
237
    struct in_addr multicast_ip;
238
    int multicast_port; /* first port used for multicast */
239
    int multicast_ttl;
240
    int loop; /* if true, send the stream in loops (only meaningful if file) */
241

    
242
    /* feed specific */
243
    int feed_opened;     /* true if someone is writing to the feed */
244
    int is_feed;         /* true if it is a feed */
245
    int readonly;        /* True if writing is prohibited to the file */
246
    int truncate;        /* True if feeder connection truncate the feed file */
247
    int conns_served;
248
    int64_t bytes_served;
249
    int64_t feed_max_size;      /* maximum storage size, zero means unlimited */
250
    int64_t feed_write_index;   /* current write position in feed (it wraps around) */
251
    int64_t feed_size;          /* current size of feed */
252
    struct FFStream *next_feed;
253
} FFStream;
254

    
255
typedef struct FeedData {
256
    long long data_count;
257
    float avg_frame_size;   /* frame size averaged over last frames with exponential mean */
258
} FeedData;
259

    
260
static struct sockaddr_in my_http_addr;
261
static struct sockaddr_in my_rtsp_addr;
262

    
263
static char logfilename[1024];
264
static HTTPContext *first_http_ctx;
265
static FFStream *first_feed;   /* contains only feeds */
266
static FFStream *first_stream; /* contains all streams, including feeds */
267

    
268
static void new_connection(int server_fd, int is_rtsp);
269
static void close_connection(HTTPContext *c);
270

    
271
/* HTTP handling */
272
static int handle_connection(HTTPContext *c);
273
static int http_parse_request(HTTPContext *c);
274
static int http_send_data(HTTPContext *c);
275
static void compute_status(HTTPContext *c);
276
static int open_input_stream(HTTPContext *c, const char *info);
277
static int http_start_receive_data(HTTPContext *c);
278
static int http_receive_data(HTTPContext *c);
279

    
280
/* RTSP handling */
281
static int rtsp_parse_request(HTTPContext *c);
282
static void rtsp_cmd_describe(HTTPContext *c, const char *url);
283
static void rtsp_cmd_options(HTTPContext *c, const char *url);
284
static void rtsp_cmd_setup(HTTPContext *c, const char *url, RTSPMessageHeader *h);
285
static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h);
286
static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h);
287
static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPMessageHeader *h);
288

    
289
/* SDP handling */
290
static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
291
                                   struct in_addr my_ip);
292

    
293
/* RTP handling */
294
static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
295
                                       FFStream *stream, const char *session_id,
296
                                       enum RTSPLowerTransport rtp_protocol);
297
static int rtp_new_av_stream(HTTPContext *c,
298
                             int stream_index, struct sockaddr_in *dest_addr,
299
                             HTTPContext *rtsp_c);
300

    
301
static const char *my_program_name;
302
static const char *my_program_dir;
303

    
304
static const char *config_filename = "/etc/ffserver.conf";
305

    
306
static int ffserver_debug;
307
static int ffserver_daemon;
308
static int no_launch;
309
static int need_to_start_children;
310

    
311
/* maximum number of simultaneous HTTP connections */
312
static unsigned int nb_max_http_connections = 2000;
313
static unsigned int nb_max_connections = 5;
314
static unsigned int nb_connections;
315

    
316
static uint64_t max_bandwidth = 1000;
317
static uint64_t current_bandwidth;
318

    
319
static int64_t cur_time;           // Making this global saves on passing it around everywhere
320

    
321
static AVLFG random_state;
322

    
323
static FILE *logfile = NULL;
324

    
325
/* FIXME: make ffserver work with IPv6 */
326
/* resolve host with also IP address parsing */
327
static int resolve_host(struct in_addr *sin_addr, const char *hostname)
328
{
329

    
330
    if (!ff_inet_aton(hostname, sin_addr)) {
331
#if HAVE_GETADDRINFO
332
        struct addrinfo *ai, *cur;
333
        struct addrinfo hints;
334
        memset(&hints, 0, sizeof(hints));
335
        hints.ai_family = AF_INET;
336
        if (getaddrinfo(hostname, NULL, &hints, &ai))
337
            return -1;
338
        /* getaddrinfo returns a linked list of addrinfo structs.
339
         * Even if we set ai_family = AF_INET above, make sure
340
         * that the returned one actually is of the correct type. */
341
        for (cur = ai; cur; cur = cur->ai_next) {
342
            if (cur->ai_family == AF_INET) {
343
                *sin_addr = ((struct sockaddr_in *)cur->ai_addr)->sin_addr;
344
                freeaddrinfo(ai);
345
                return 0;
346
            }
347
        }
348
        freeaddrinfo(ai);
349
        return -1;
350
#else
351
        struct hostent *hp;
352
        hp = gethostbyname(hostname);
353
        if (!hp)
354
            return -1;
355
        memcpy(sin_addr, hp->h_addr_list[0], sizeof(struct in_addr));
356
#endif
357
    }
358
    return 0;
359
}
360

    
361
static char *ctime1(char *buf2)
362
{
363
    time_t ti;
364
    char *p;
365

    
366
    ti = time(NULL);
367
    p = ctime(&ti);
368
    strcpy(buf2, p);
369
    p = buf2 + strlen(p) - 1;
370
    if (*p == '\n')
371
        *p = '\0';
372
    return buf2;
373
}
374

    
375
static void http_vlog(const char *fmt, va_list vargs)
376
{
377
    static int print_prefix = 1;
378
    if (logfile) {
379
        if (print_prefix) {
380
            char buf[32];
381
            ctime1(buf);
382
            fprintf(logfile, "%s ", buf);
383
        }
384
        print_prefix = strstr(fmt, "\n") != NULL;
385
        vfprintf(logfile, fmt, vargs);
386
        fflush(logfile);
387
    }
388
}
389

    
390
#ifdef __GNUC__
391
__attribute__ ((format (printf, 1, 2)))
392
#endif
393
static void http_log(const char *fmt, ...)
394
{
395
    va_list vargs;
396
    va_start(vargs, fmt);
397
    http_vlog(fmt, vargs);
398
    va_end(vargs);
399
}
400

    
401
static void http_av_log(void *ptr, int level, const char *fmt, va_list vargs)
402
{
403
    static int print_prefix = 1;
404
    AVClass *avc = ptr ? *(AVClass**)ptr : NULL;
405
    if (level > av_log_get_level())
406
        return;
407
    if (print_prefix && avc)
408
        http_log("[%s @ %p]", avc->item_name(ptr), ptr);
409
    print_prefix = strstr(fmt, "\n") != NULL;
410
    http_vlog(fmt, vargs);
411
}
412

    
413
static void log_connection(HTTPContext *c)
414
{
415
    if (c->suppress_log)
416
        return;
417

    
418
    http_log("%s - - [%s] \"%s %s\" %d %"PRId64"\n",
419
             inet_ntoa(c->from_addr.sin_addr), c->method, c->url,
420
             c->protocol, (c->http_error ? c->http_error : 200), c->data_count);
421
}
422

    
423
static void update_datarate(DataRateData *drd, int64_t count)
424
{
425
    if (!drd->time1 && !drd->count1) {
426
        drd->time1 = drd->time2 = cur_time;
427
        drd->count1 = drd->count2 = count;
428
    } else if (cur_time - drd->time2 > 5000) {
429
        drd->time1 = drd->time2;
430
        drd->count1 = drd->count2;
431
        drd->time2 = cur_time;
432
        drd->count2 = count;
433
    }
434
}
435

    
436
/* In bytes per second */
437
static int compute_datarate(DataRateData *drd, int64_t count)
438
{
439
    if (cur_time == drd->time1)
440
        return 0;
441

    
442
    return ((count - drd->count1) * 1000) / (cur_time - drd->time1);
443
}
444

    
445

    
446
static void start_children(FFStream *feed)
447
{
448
    if (no_launch)
449
        return;
450

    
451
    for (; feed; feed = feed->next) {
452
        if (feed->child_argv && !feed->pid) {
453
            feed->pid_start = time(0);
454

    
455
            feed->pid = fork();
456

    
457
            if (feed->pid < 0) {
458
                http_log("Unable to create children\n");
459
                exit(1);
460
            }
461
            if (!feed->pid) {
462
                /* In child */
463
                char pathname[1024];
464
                char *slash;
465
                int i;
466

    
467
                av_strlcpy(pathname, my_program_name, sizeof(pathname));
468

    
469
                slash = strrchr(pathname, '/');
470
                if (!slash)
471
                    slash = pathname;
472
                else
473
                    slash++;
474
                strcpy(slash, "ffmpeg");
475

    
476
                http_log("Launch commandline: ");
477
                http_log("%s ", pathname);
478
                for (i = 1; feed->child_argv[i] && feed->child_argv[i][0]; i++)
479
                    http_log("%s ", feed->child_argv[i]);
480
                http_log("\n");
481

    
482
                for (i = 3; i < 256; i++)
483
                    close(i);
484

    
485
                if (!ffserver_debug) {
486
                    i = open("/dev/null", O_RDWR);
487
                    if (i != -1) {
488
                        dup2(i, 0);
489
                        dup2(i, 1);
490
                        dup2(i, 2);
491
                        close(i);
492
                    }
493
                }
494

    
495
                /* This is needed to make relative pathnames work */
496
                chdir(my_program_dir);
497

    
498
                signal(SIGPIPE, SIG_DFL);
499

    
500
                execvp(pathname, feed->child_argv);
501

    
502
                _exit(1);
503
            }
504
        }
505
    }
506
}
507

    
508
/* open a listening socket */
509
static int socket_open_listen(struct sockaddr_in *my_addr)
510
{
511
    int server_fd, tmp;
512

    
513
    server_fd = socket(AF_INET,SOCK_STREAM,0);
514
    if (server_fd < 0) {
515
        perror ("socket");
516
        return -1;
517
    }
518

    
519
    tmp = 1;
520
    setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp));
521

    
522
    if (bind (server_fd, (struct sockaddr *) my_addr, sizeof (*my_addr)) < 0) {
523
        char bindmsg[32];
524
        snprintf(bindmsg, sizeof(bindmsg), "bind(port %d)", ntohs(my_addr->sin_port));
525
        perror (bindmsg);
526
        closesocket(server_fd);
527
        return -1;
528
    }
529

    
530
    if (listen (server_fd, 5) < 0) {
531
        perror ("listen");
532
        closesocket(server_fd);
533
        return -1;
534
    }
535
    ff_socket_nonblock(server_fd, 1);
536

    
537
    return server_fd;
538
}
539

    
540
/* start all multicast streams */
541
static void start_multicast(void)
542
{
543
    FFStream *stream;
544
    char session_id[32];
545
    HTTPContext *rtp_c;
546
    struct sockaddr_in dest_addr;
547
    int default_port, stream_index;
548

    
549
    default_port = 6000;
550
    for(stream = first_stream; stream != NULL; stream = stream->next) {
551
        if (stream->is_multicast) {
552
            /* open the RTP connection */
553
            snprintf(session_id, sizeof(session_id), "%08x%08x",
554
                     av_lfg_get(&random_state), av_lfg_get(&random_state));
555

    
556
            /* choose a port if none given */
557
            if (stream->multicast_port == 0) {
558
                stream->multicast_port = default_port;
559
                default_port += 100;
560
            }
561

    
562
            dest_addr.sin_family = AF_INET;
563
            dest_addr.sin_addr = stream->multicast_ip;
564
            dest_addr.sin_port = htons(stream->multicast_port);
565

    
566
            rtp_c = rtp_new_connection(&dest_addr, stream, session_id,
567
                                       RTSP_LOWER_TRANSPORT_UDP_MULTICAST);
568
            if (!rtp_c)
569
                continue;
570

    
571
            if (open_input_stream(rtp_c, "") < 0) {
572
                http_log("Could not open input stream for stream '%s'\n",
573
                         stream->filename);
574
                continue;
575
            }
576

    
577
            /* open each RTP stream */
578
            for(stream_index = 0; stream_index < stream->nb_streams;
579
                stream_index++) {
580
                dest_addr.sin_port = htons(stream->multicast_port +
581
                                           2 * stream_index);
582
                if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, NULL) < 0) {
583
                    http_log("Could not open output stream '%s/streamid=%d'\n",
584
                             stream->filename, stream_index);
585
                    exit(1);
586
                }
587
            }
588

    
589
            /* change state to send data */
590
            rtp_c->state = HTTPSTATE_SEND_DATA;
591
        }
592
    }
593
}
594

    
595
/* main loop of the http server */
596
static int http_server(void)
597
{
598
    int server_fd = 0, rtsp_server_fd = 0;
599
    int ret, delay, delay1;
600
    struct pollfd *poll_table, *poll_entry;
601
    HTTPContext *c, *c_next;
602

    
603
    if(!(poll_table = av_mallocz((nb_max_http_connections + 2)*sizeof(*poll_table)))) {
604
        http_log("Impossible to allocate a poll table handling %d connections.\n", nb_max_http_connections);
605
        return -1;
606
    }
607

    
608
    if (my_http_addr.sin_port) {
609
        server_fd = socket_open_listen(&my_http_addr);
610
        if (server_fd < 0)
611
            return -1;
612
    }
613

    
614
    if (my_rtsp_addr.sin_port) {
615
        rtsp_server_fd = socket_open_listen(&my_rtsp_addr);
616
        if (rtsp_server_fd < 0)
617
            return -1;
618
    }
619

    
620
    if (!rtsp_server_fd && !server_fd) {
621
        http_log("HTTP and RTSP disabled.\n");
622
        return -1;
623
    }
624

    
625
    http_log("FFserver started.\n");
626

    
627
    start_children(first_feed);
628

    
629
    start_multicast();
630

    
631
    for(;;) {
632
        poll_entry = poll_table;
633
        if (server_fd) {
634
            poll_entry->fd = server_fd;
635
            poll_entry->events = POLLIN;
636
            poll_entry++;
637
        }
638
        if (rtsp_server_fd) {
639
            poll_entry->fd = rtsp_server_fd;
640
            poll_entry->events = POLLIN;
641
            poll_entry++;
642
        }
643

    
644
        /* wait for events on each HTTP handle */
645
        c = first_http_ctx;
646
        delay = 1000;
647
        while (c != NULL) {
648
            int fd;
649
            fd = c->fd;
650
            switch(c->state) {
651
            case HTTPSTATE_SEND_HEADER:
652
            case RTSPSTATE_SEND_REPLY:
653
            case RTSPSTATE_SEND_PACKET:
654
                c->poll_entry = poll_entry;
655
                poll_entry->fd = fd;
656
                poll_entry->events = POLLOUT;
657
                poll_entry++;
658
                break;
659
            case HTTPSTATE_SEND_DATA_HEADER:
660
            case HTTPSTATE_SEND_DATA:
661
            case HTTPSTATE_SEND_DATA_TRAILER:
662
                if (!c->is_packetized) {
663
                    /* for TCP, we output as much as we can (may need to put a limit) */
664
                    c->poll_entry = poll_entry;
665
                    poll_entry->fd = fd;
666
                    poll_entry->events = POLLOUT;
667
                    poll_entry++;
668
                } else {
669
                    /* when ffserver is doing the timing, we work by
670
                       looking at which packet need to be sent every
671
                       10 ms */
672
                    delay1 = 10; /* one tick wait XXX: 10 ms assumed */
673
                    if (delay1 < delay)
674
                        delay = delay1;
675
                }
676
                break;
677
            case HTTPSTATE_WAIT_REQUEST:
678
            case HTTPSTATE_RECEIVE_DATA:
679
            case HTTPSTATE_WAIT_FEED:
680
            case RTSPSTATE_WAIT_REQUEST:
681
                /* need to catch errors */
682
                c->poll_entry = poll_entry;
683
                poll_entry->fd = fd;
684
                poll_entry->events = POLLIN;/* Maybe this will work */
685
                poll_entry++;
686
                break;
687
            default:
688
                c->poll_entry = NULL;
689
                break;
690
            }
691
            c = c->next;
692
        }
693

    
694
        /* wait for an event on one connection. We poll at least every
695
           second to handle timeouts */
696
        do {
697
            ret = poll(poll_table, poll_entry - poll_table, delay);
698
            if (ret < 0 && ff_neterrno() != AVERROR(EAGAIN) &&
699
                ff_neterrno() != AVERROR(EINTR))
700
                return -1;
701
        } while (ret < 0);
702

    
703
        cur_time = av_gettime() / 1000;
704

    
705
        if (need_to_start_children) {
706
            need_to_start_children = 0;
707
            start_children(first_feed);
708
        }
709

    
710
        /* now handle the events */
711
        for(c = first_http_ctx; c != NULL; c = c_next) {
712
            c_next = c->next;
713
            if (handle_connection(c) < 0) {
714
                /* close and free the connection */
715
                log_connection(c);
716
                close_connection(c);
717
            }
718
        }
719

    
720
        poll_entry = poll_table;
721
        if (server_fd) {
722
            /* new HTTP connection request ? */
723
            if (poll_entry->revents & POLLIN)
724
                new_connection(server_fd, 0);
725
            poll_entry++;
726
        }
727
        if (rtsp_server_fd) {
728
            /* new RTSP connection request ? */
729
            if (poll_entry->revents & POLLIN)
730
                new_connection(rtsp_server_fd, 1);
731
        }
732
    }
733
}
734

    
735
/* start waiting for a new HTTP/RTSP request */
736
static void start_wait_request(HTTPContext *c, int is_rtsp)
737
{
738
    c->buffer_ptr = c->buffer;
739
    c->buffer_end = c->buffer + c->buffer_size - 1; /* leave room for '\0' */
740

    
741
    if (is_rtsp) {
742
        c->timeout = cur_time + RTSP_REQUEST_TIMEOUT;
743
        c->state = RTSPSTATE_WAIT_REQUEST;
744
    } else {
745
        c->timeout = cur_time + HTTP_REQUEST_TIMEOUT;
746
        c->state = HTTPSTATE_WAIT_REQUEST;
747
    }
748
}
749

    
750
static void http_send_too_busy_reply(int fd)
751
{
752
    char buffer[300];
753
    int len = snprintf(buffer, sizeof(buffer),
754
                       "HTTP/1.0 503 Server too busy\r\n"
755
                       "Content-type: text/html\r\n"
756
                       "\r\n"
757
                       "<html><head><title>Too busy</title></head><body>\r\n"
758
                       "<p>The server is too busy to serve your request at this time.</p>\r\n"
759
                       "<p>The number of current connections is %d, and this exceeds the limit of %d.</p>\r\n"
760
                       "</body></html>\r\n",
761
                       nb_connections, nb_max_connections);
762
    send(fd, buffer, len, 0);
763
}
764

    
765

    
766
static void new_connection(int server_fd, int is_rtsp)
767
{
768
    struct sockaddr_in from_addr;
769
    int fd, len;
770
    HTTPContext *c = NULL;
771

    
772
    len = sizeof(from_addr);
773
    fd = accept(server_fd, (struct sockaddr *)&from_addr,
774
                &len);
775
    if (fd < 0) {
776
        http_log("error during accept %s\n", strerror(errno));
777
        return;
778
    }
779
    ff_socket_nonblock(fd, 1);
780

    
781
    if (nb_connections >= nb_max_connections) {
782
        http_send_too_busy_reply(fd);
783
        goto fail;
784
    }
785

    
786
    /* add a new connection */
787
    c = av_mallocz(sizeof(HTTPContext));
788
    if (!c)
789
        goto fail;
790

    
791
    c->fd = fd;
792
    c->poll_entry = NULL;
793
    c->from_addr = from_addr;
794
    c->buffer_size = IOBUFFER_INIT_SIZE;
795
    c->buffer = av_malloc(c->buffer_size);
796
    if (!c->buffer)
797
        goto fail;
798

    
799
    c->next = first_http_ctx;
800
    first_http_ctx = c;
801
    nb_connections++;
802

    
803
    start_wait_request(c, is_rtsp);
804

    
805
    return;
806

    
807
 fail:
808
    if (c) {
809
        av_free(c->buffer);
810
        av_free(c);
811
    }
812
    closesocket(fd);
813
}
814

    
815
static void close_connection(HTTPContext *c)
816
{
817
    HTTPContext **cp, *c1;
818
    int i, nb_streams;
819
    AVFormatContext *ctx;
820
    URLContext *h;
821
    AVStream *st;
822

    
823
    /* remove connection from list */
824
    cp = &first_http_ctx;
825
    while ((*cp) != NULL) {
826
        c1 = *cp;
827
        if (c1 == c)
828
            *cp = c->next;
829
        else
830
            cp = &c1->next;
831
    }
832

    
833
    /* remove references, if any (XXX: do it faster) */
834
    for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
835
        if (c1->rtsp_c == c)
836
            c1->rtsp_c = NULL;
837
    }
838

    
839
    /* remove connection associated resources */
840
    if (c->fd >= 0)
841
        closesocket(c->fd);
842
    if (c->fmt_in) {
843
        /* close each frame parser */
844
        for(i=0;i<c->fmt_in->nb_streams;i++) {
845
            st = c->fmt_in->streams[i];
846
            if (st->codec->codec)
847
                avcodec_close(st->codec);
848
        }
849
        av_close_input_file(c->fmt_in);
850
    }
851

    
852
    /* free RTP output streams if any */
853
    nb_streams = 0;
854
    if (c->stream)
855
        nb_streams = c->stream->nb_streams;
856

    
857
    for(i=0;i<nb_streams;i++) {
858
        ctx = c->rtp_ctx[i];
859
        if (ctx) {
860
            av_write_trailer(ctx);
861
            av_metadata_free(&ctx->metadata);
862
            av_free(ctx->streams[0]);
863
            av_free(ctx);
864
        }
865
        h = c->rtp_handles[i];
866
        if (h)
867
            url_close(h);
868
    }
869

    
870
    ctx = &c->fmt_ctx;
871

    
872
    if (!c->last_packet_sent && c->state == HTTPSTATE_SEND_DATA_TRAILER) {
873
        if (ctx->oformat) {
874
            /* prepare header */
875
            if (avio_open_dyn_buf(&ctx->pb) >= 0) {
876
                av_write_trailer(ctx);
877
                av_freep(&c->pb_buffer);
878
                avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
879
            }
880
        }
881
    }
882

    
883
    for(i=0; i<ctx->nb_streams; i++)
884
        av_free(ctx->streams[i]);
885

    
886
    if (c->stream && !c->post && c->stream->stream_type == STREAM_TYPE_LIVE)
887
        current_bandwidth -= c->stream->bandwidth;
888

    
889
    /* signal that there is no feed if we are the feeder socket */
890
    if (c->state == HTTPSTATE_RECEIVE_DATA && c->stream) {
891
        c->stream->feed_opened = 0;
892
        close(c->feed_fd);
893
    }
894

    
895
    av_freep(&c->pb_buffer);
896
    av_freep(&c->packet_buffer);
897
    av_free(c->buffer);
898
    av_free(c);
899
    nb_connections--;
900
}
901

    
902
static int handle_connection(HTTPContext *c)
903
{
904
    int len, ret;
905

    
906
    switch(c->state) {
907
    case HTTPSTATE_WAIT_REQUEST:
908
    case RTSPSTATE_WAIT_REQUEST:
909
        /* timeout ? */
910
        if ((c->timeout - cur_time) < 0)
911
            return -1;
912
        if (c->poll_entry->revents & (POLLERR | POLLHUP))
913
            return -1;
914

    
915
        /* no need to read if no events */
916
        if (!(c->poll_entry->revents & POLLIN))
917
            return 0;
918
        /* read the data */
919
    read_loop:
920
        len = recv(c->fd, c->buffer_ptr, 1, 0);
921
        if (len < 0) {
922
            if (ff_neterrno() != AVERROR(EAGAIN) &&
923
                ff_neterrno() != AVERROR(EINTR))
924
                return -1;
925
        } else if (len == 0) {
926
            return -1;
927
        } else {
928
            /* search for end of request. */
929
            uint8_t *ptr;
930
            c->buffer_ptr += len;
931
            ptr = c->buffer_ptr;
932
            if ((ptr >= c->buffer + 2 && !memcmp(ptr-2, "\n\n", 2)) ||
933
                (ptr >= c->buffer + 4 && !memcmp(ptr-4, "\r\n\r\n", 4))) {
934
                /* request found : parse it and reply */
935
                if (c->state == HTTPSTATE_WAIT_REQUEST) {
936
                    ret = http_parse_request(c);
937
                } else {
938
                    ret = rtsp_parse_request(c);
939
                }
940
                if (ret < 0)
941
                    return -1;
942
            } else if (ptr >= c->buffer_end) {
943
                /* request too long: cannot do anything */
944
                return -1;
945
            } else goto read_loop;
946
        }
947
        break;
948

    
949
    case HTTPSTATE_SEND_HEADER:
950
        if (c->poll_entry->revents & (POLLERR | POLLHUP))
951
            return -1;
952

    
953
        /* no need to write if no events */
954
        if (!(c->poll_entry->revents & POLLOUT))
955
            return 0;
956
        len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
957
        if (len < 0) {
958
            if (ff_neterrno() != AVERROR(EAGAIN) &&
959
                ff_neterrno() != AVERROR(EINTR)) {
960
                /* error : close connection */
961
                av_freep(&c->pb_buffer);
962
                return -1;
963
            }
964
        } else {
965
            c->buffer_ptr += len;
966
            if (c->stream)
967
                c->stream->bytes_served += len;
968
            c->data_count += len;
969
            if (c->buffer_ptr >= c->buffer_end) {
970
                av_freep(&c->pb_buffer);
971
                /* if error, exit */
972
                if (c->http_error)
973
                    return -1;
974
                /* all the buffer was sent : synchronize to the incoming stream */
975
                c->state = HTTPSTATE_SEND_DATA_HEADER;
976
                c->buffer_ptr = c->buffer_end = c->buffer;
977
            }
978
        }
979
        break;
980

    
981
    case HTTPSTATE_SEND_DATA:
982
    case HTTPSTATE_SEND_DATA_HEADER:
983
    case HTTPSTATE_SEND_DATA_TRAILER:
984
        /* for packetized output, we consider we can always write (the
985
           input streams sets the speed). It may be better to verify
986
           that we do not rely too much on the kernel queues */
987
        if (!c->is_packetized) {
988
            if (c->poll_entry->revents & (POLLERR | POLLHUP))
989
                return -1;
990

    
991
            /* no need to read if no events */
992
            if (!(c->poll_entry->revents & POLLOUT))
993
                return 0;
994
        }
995
        if (http_send_data(c) < 0)
996
            return -1;
997
        /* close connection if trailer sent */
998
        if (c->state == HTTPSTATE_SEND_DATA_TRAILER)
999
            return -1;
1000
        break;
1001
    case HTTPSTATE_RECEIVE_DATA:
1002
        /* no need to read if no events */
1003
        if (c->poll_entry->revents & (POLLERR | POLLHUP))
1004
            return -1;
1005
        if (!(c->poll_entry->revents & POLLIN))
1006
            return 0;
1007
        if (http_receive_data(c) < 0)
1008
            return -1;
1009
        break;
1010
    case HTTPSTATE_WAIT_FEED:
1011
        /* no need to read if no events */
1012
        if (c->poll_entry->revents & (POLLIN | POLLERR | POLLHUP))
1013
            return -1;
1014

    
1015
        /* nothing to do, we'll be waken up by incoming feed packets */
1016
        break;
1017

    
1018
    case RTSPSTATE_SEND_REPLY:
1019
        if (c->poll_entry->revents & (POLLERR | POLLHUP)) {
1020
            av_freep(&c->pb_buffer);
1021
            return -1;
1022
        }
1023
        /* no need to write if no events */
1024
        if (!(c->poll_entry->revents & POLLOUT))
1025
            return 0;
1026
        len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
1027
        if (len < 0) {
1028
            if (ff_neterrno() != AVERROR(EAGAIN) &&
1029
                ff_neterrno() != AVERROR(EINTR)) {
1030
                /* error : close connection */
1031
                av_freep(&c->pb_buffer);
1032
                return -1;
1033
            }
1034
        } else {
1035
            c->buffer_ptr += len;
1036
            c->data_count += len;
1037
            if (c->buffer_ptr >= c->buffer_end) {
1038
                /* all the buffer was sent : wait for a new request */
1039
                av_freep(&c->pb_buffer);
1040
                start_wait_request(c, 1);
1041
            }
1042
        }
1043
        break;
1044
    case RTSPSTATE_SEND_PACKET:
1045
        if (c->poll_entry->revents & (POLLERR | POLLHUP)) {
1046
            av_freep(&c->packet_buffer);
1047
            return -1;
1048
        }
1049
        /* no need to write if no events */
1050
        if (!(c->poll_entry->revents & POLLOUT))
1051
            return 0;
1052
        len = send(c->fd, c->packet_buffer_ptr,
1053
                    c->packet_buffer_end - c->packet_buffer_ptr, 0);
1054
        if (len < 0) {
1055
            if (ff_neterrno() != AVERROR(EAGAIN) &&
1056
                ff_neterrno() != AVERROR(EINTR)) {
1057
                /* error : close connection */
1058
                av_freep(&c->packet_buffer);
1059
                return -1;
1060
            }
1061
        } else {
1062
            c->packet_buffer_ptr += len;
1063
            if (c->packet_buffer_ptr >= c->packet_buffer_end) {
1064
                /* all the buffer was sent : wait for a new request */
1065
                av_freep(&c->packet_buffer);
1066
                c->state = RTSPSTATE_WAIT_REQUEST;
1067
            }
1068
        }
1069
        break;
1070
    case HTTPSTATE_READY:
1071
        /* nothing to do */
1072
        break;
1073
    default:
1074
        return -1;
1075
    }
1076
    return 0;
1077
}
1078

    
1079
static int extract_rates(char *rates, int ratelen, const char *request)
1080
{
1081
    const char *p;
1082

    
1083
    for (p = request; *p && *p != '\r' && *p != '\n'; ) {
1084
        if (strncasecmp(p, "Pragma:", 7) == 0) {
1085
            const char *q = p + 7;
1086

    
1087
            while (*q && *q != '\n' && isspace(*q))
1088
                q++;
1089

    
1090
            if (strncasecmp(q, "stream-switch-entry=", 20) == 0) {
1091
                int stream_no;
1092
                int rate_no;
1093

    
1094
                q += 20;
1095

    
1096
                memset(rates, 0xff, ratelen);
1097

    
1098
                while (1) {
1099
                    while (*q && *q != '\n' && *q != ':')
1100
                        q++;
1101

    
1102
                    if (sscanf(q, ":%d:%d", &stream_no, &rate_no) != 2)
1103
                        break;
1104

    
1105
                    stream_no--;
1106
                    if (stream_no < ratelen && stream_no >= 0)
1107
                        rates[stream_no] = rate_no;
1108

    
1109
                    while (*q && *q != '\n' && !isspace(*q))
1110
                        q++;
1111
                }
1112

    
1113
                return 1;
1114
            }
1115
        }
1116
        p = strchr(p, '\n');
1117
        if (!p)
1118
            break;
1119

    
1120
        p++;
1121
    }
1122

    
1123
    return 0;
1124
}
1125

    
1126
static int find_stream_in_feed(FFStream *feed, AVCodecContext *codec, int bit_rate)
1127
{
1128
    int i;
1129
    int best_bitrate = 100000000;
1130
    int best = -1;
1131

    
1132
    for (i = 0; i < feed->nb_streams; i++) {
1133
        AVCodecContext *feed_codec = feed->streams[i]->codec;
1134

    
1135
        if (feed_codec->codec_id != codec->codec_id ||
1136
            feed_codec->sample_rate != codec->sample_rate ||
1137
            feed_codec->width != codec->width ||
1138
            feed_codec->height != codec->height)
1139
            continue;
1140

    
1141
        /* Potential stream */
1142

    
1143
        /* We want the fastest stream less than bit_rate, or the slowest
1144
         * faster than bit_rate
1145
         */
1146

    
1147
        if (feed_codec->bit_rate <= bit_rate) {
1148
            if (best_bitrate > bit_rate || feed_codec->bit_rate > best_bitrate) {
1149
                best_bitrate = feed_codec->bit_rate;
1150
                best = i;
1151
            }
1152
        } else {
1153
            if (feed_codec->bit_rate < best_bitrate) {
1154
                best_bitrate = feed_codec->bit_rate;
1155
                best = i;
1156
            }
1157
        }
1158
    }
1159

    
1160
    return best;
1161
}
1162

    
1163
static int modify_current_stream(HTTPContext *c, char *rates)
1164
{
1165
    int i;
1166
    FFStream *req = c->stream;
1167
    int action_required = 0;
1168

    
1169
    /* Not much we can do for a feed */
1170
    if (!req->feed)
1171
        return 0;
1172

    
1173
    for (i = 0; i < req->nb_streams; i++) {
1174
        AVCodecContext *codec = req->streams[i]->codec;
1175

    
1176
        switch(rates[i]) {
1177
            case 0:
1178
                c->switch_feed_streams[i] = req->feed_streams[i];
1179
                break;
1180
            case 1:
1181
                c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 2);
1182
                break;
1183
            case 2:
1184
                /* Wants off or slow */
1185
                c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 4);
1186
#ifdef WANTS_OFF
1187
                /* This doesn't work well when it turns off the only stream! */
1188
                c->switch_feed_streams[i] = -2;
1189
                c->feed_streams[i] = -2;
1190
#endif
1191
                break;
1192
        }
1193

    
1194
        if (c->switch_feed_streams[i] >= 0 && c->switch_feed_streams[i] != c->feed_streams[i])
1195
            action_required = 1;
1196
    }
1197

    
1198
    return action_required;
1199
}
1200

    
1201
/* XXX: factorize in utils.c ? */
1202
/* XXX: take care with different space meaning */
1203
static void skip_spaces(const char **pp)
1204
{
1205
    const char *p;
1206
    p = *pp;
1207
    while (*p == ' ' || *p == '\t')
1208
        p++;
1209
    *pp = p;
1210
}
1211

    
1212
static void get_word(char *buf, int buf_size, const char **pp)
1213
{
1214
    const char *p;
1215
    char *q;
1216

    
1217
    p = *pp;
1218
    skip_spaces(&p);
1219
    q = buf;
1220
    while (!isspace(*p) && *p != '\0') {
1221
        if ((q - buf) < buf_size - 1)
1222
            *q++ = *p;
1223
        p++;
1224
    }
1225
    if (buf_size > 0)
1226
        *q = '\0';
1227
    *pp = p;
1228
}
1229

    
1230
static void get_arg(char *buf, int buf_size, const char **pp)
1231
{
1232
    const char *p;
1233
    char *q;
1234
    int quote;
1235

    
1236
    p = *pp;
1237
    while (isspace(*p)) p++;
1238
    q = buf;
1239
    quote = 0;
1240
    if (*p == '\"' || *p == '\'')
1241
        quote = *p++;
1242
    for(;;) {
1243
        if (quote) {
1244
            if (*p == quote)
1245
                break;
1246
        } else {
1247
            if (isspace(*p))
1248
                break;
1249
        }
1250
        if (*p == '\0')
1251
            break;
1252
        if ((q - buf) < buf_size - 1)
1253
            *q++ = *p;
1254
        p++;
1255
    }
1256
    *q = '\0';
1257
    if (quote && *p == quote)
1258
        p++;
1259
    *pp = p;
1260
}
1261

    
1262
static void parse_acl_row(FFStream *stream, FFStream* feed, IPAddressACL *ext_acl,
1263
                         const char *p, const char *filename, int line_num)
1264
{
1265
    char arg[1024];
1266
    IPAddressACL acl;
1267
    int errors = 0;
1268

    
1269
    get_arg(arg, sizeof(arg), &p);
1270
    if (strcasecmp(arg, "allow") == 0)
1271
        acl.action = IP_ALLOW;
1272
    else if (strcasecmp(arg, "deny") == 0)
1273
        acl.action = IP_DENY;
1274
    else {
1275
        fprintf(stderr, "%s:%d: ACL action '%s' is not ALLOW or DENY\n",
1276
                filename, line_num, arg);
1277
        errors++;
1278
    }
1279

    
1280
    get_arg(arg, sizeof(arg), &p);
1281

    
1282
    if (resolve_host(&acl.first, arg) != 0) {
1283
        fprintf(stderr, "%s:%d: ACL refers to invalid host or ip address '%s'\n",
1284
                filename, line_num, arg);
1285
        errors++;
1286
    } else
1287
        acl.last = acl.first;
1288

    
1289
    get_arg(arg, sizeof(arg), &p);
1290

    
1291
    if (arg[0]) {
1292
        if (resolve_host(&acl.last, arg) != 0) {
1293
            fprintf(stderr, "%s:%d: ACL refers to invalid host or ip address '%s'\n",
1294
                    filename, line_num, arg);
1295
            errors++;
1296
        }
1297
    }
1298

    
1299
    if (!errors) {
1300
        IPAddressACL *nacl = av_mallocz(sizeof(*nacl));
1301
        IPAddressACL **naclp = 0;
1302

    
1303
        acl.next = 0;
1304
        *nacl = acl;
1305

    
1306
        if (stream)
1307
            naclp = &stream->acl;
1308
        else if (feed)
1309
            naclp = &feed->acl;
1310
        else if (ext_acl)
1311
            naclp = &ext_acl;
1312
        else {
1313
            fprintf(stderr, "%s:%d: ACL found not in <stream> or <feed>\n",
1314
                    filename, line_num);
1315
            errors++;
1316
        }
1317

    
1318
        if (naclp) {
1319
            while (*naclp)
1320
                naclp = &(*naclp)->next;
1321

    
1322
            *naclp = nacl;
1323
        }
1324
    }
1325
}
1326

    
1327

    
1328
static IPAddressACL* parse_dynamic_acl(FFStream *stream, HTTPContext *c)
1329
{
1330
    FILE* f;
1331
    char line[1024];
1332
    char  cmd[1024];
1333
    IPAddressACL *acl = NULL;
1334
    int line_num = 0;
1335
    const char *p;
1336

    
1337
    f = fopen(stream->dynamic_acl, "r");
1338
    if (!f) {
1339
        perror(stream->dynamic_acl);
1340
        return NULL;
1341
    }
1342

    
1343
    acl = av_mallocz(sizeof(IPAddressACL));
1344

    
1345
    /* Build ACL */
1346
    for(;;) {
1347
        if (fgets(line, sizeof(line), f) == NULL)
1348
            break;
1349
        line_num++;
1350
        p = line;
1351
        while (isspace(*p))
1352
            p++;
1353
        if (*p == '\0' || *p == '#')
1354
            continue;
1355
        get_arg(cmd, sizeof(cmd), &p);
1356

    
1357
        if (!strcasecmp(cmd, "ACL"))
1358
            parse_acl_row(NULL, NULL, acl, p, stream->dynamic_acl, line_num);
1359
    }
1360
    fclose(f);
1361
    return acl;
1362
}
1363

    
1364

    
1365
static void free_acl_list(IPAddressACL *in_acl)
1366
{
1367
    IPAddressACL *pacl,*pacl2;
1368

    
1369
    pacl = in_acl;
1370
    while(pacl) {
1371
        pacl2 = pacl;
1372
        pacl = pacl->next;
1373
        av_freep(pacl2);
1374
    }
1375
}
1376

    
1377
static int validate_acl_list(IPAddressACL *in_acl, HTTPContext *c)
1378
{
1379
    enum IPAddressAction last_action = IP_DENY;
1380
    IPAddressACL *acl;
1381
    struct in_addr *src = &c->from_addr.sin_addr;
1382
    unsigned long src_addr = src->s_addr;
1383

    
1384
    for (acl = in_acl; acl; acl = acl->next) {
1385
        if (src_addr >= acl->first.s_addr && src_addr <= acl->last.s_addr)
1386
            return (acl->action == IP_ALLOW) ? 1 : 0;
1387
        last_action = acl->action;
1388
    }
1389

    
1390
    /* Nothing matched, so return not the last action */
1391
    return (last_action == IP_DENY) ? 1 : 0;
1392
}
1393

    
1394
static int validate_acl(FFStream *stream, HTTPContext *c)
1395
{
1396
    int ret = 0;
1397
    IPAddressACL *acl;
1398

    
1399

    
1400
    /* if stream->acl is null validate_acl_list will return 1 */
1401
    ret = validate_acl_list(stream->acl, c);
1402

    
1403
    if (stream->dynamic_acl[0]) {
1404
        acl = parse_dynamic_acl(stream, c);
1405

    
1406
        ret = validate_acl_list(acl, c);
1407

    
1408
        free_acl_list(acl);
1409
    }
1410

    
1411
    return ret;
1412
}
1413

    
1414
/* compute the real filename of a file by matching it without its
1415
   extensions to all the stream filenames */
1416
static void compute_real_filename(char *filename, int max_size)
1417
{
1418
    char file1[1024];
1419
    char file2[1024];
1420
    char *p;
1421
    FFStream *stream;
1422

    
1423
    /* compute filename by matching without the file extensions */
1424
    av_strlcpy(file1, filename, sizeof(file1));
1425
    p = strrchr(file1, '.');
1426
    if (p)
1427
        *p = '\0';
1428
    for(stream = first_stream; stream != NULL; stream = stream->next) {
1429
        av_strlcpy(file2, stream->filename, sizeof(file2));
1430
        p = strrchr(file2, '.');
1431
        if (p)
1432
            *p = '\0';
1433
        if (!strcmp(file1, file2)) {
1434
            av_strlcpy(filename, stream->filename, max_size);
1435
            break;
1436
        }
1437
    }
1438
}
1439

    
1440
enum RedirType {
1441
    REDIR_NONE,
1442
    REDIR_ASX,
1443
    REDIR_RAM,
1444
    REDIR_ASF,
1445
    REDIR_RTSP,
1446
    REDIR_SDP,
1447
};
1448

    
1449
/* parse http request and prepare header */
1450
static int http_parse_request(HTTPContext *c)
1451
{
1452
    char *p;
1453
    enum RedirType redir_type;
1454
    char cmd[32];
1455
    char info[1024], filename[1024];
1456
    char url[1024], *q;
1457
    char protocol[32];
1458
    char msg[1024];
1459
    const char *mime_type;
1460
    FFStream *stream;
1461
    int i;
1462
    char ratebuf[32];
1463
    char *useragent = 0;
1464

    
1465
    p = c->buffer;
1466
    get_word(cmd, sizeof(cmd), (const char **)&p);
1467
    av_strlcpy(c->method, cmd, sizeof(c->method));
1468

    
1469
    if (!strcmp(cmd, "GET"))
1470
        c->post = 0;
1471
    else if (!strcmp(cmd, "POST"))
1472
        c->post = 1;
1473
    else
1474
        return -1;
1475

    
1476
    get_word(url, sizeof(url), (const char **)&p);
1477
    av_strlcpy(c->url, url, sizeof(c->url));
1478

    
1479
    get_word(protocol, sizeof(protocol), (const char **)&p);
1480
    if (strcmp(protocol, "HTTP/1.0") && strcmp(protocol, "HTTP/1.1"))
1481
        return -1;
1482

    
1483
    av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
1484

    
1485
    if (ffserver_debug)
1486
        http_log("%s - - New connection: %s %s\n", inet_ntoa(c->from_addr.sin_addr), cmd, url);
1487

    
1488
    /* find the filename and the optional info string in the request */
1489
    p = strchr(url, '?');
1490
    if (p) {
1491
        av_strlcpy(info, p, sizeof(info));
1492
        *p = '\0';
1493
    } else
1494
        info[0] = '\0';
1495

    
1496
    av_strlcpy(filename, url + ((*url == '/') ? 1 : 0), sizeof(filename)-1);
1497

    
1498
    for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1499
        if (strncasecmp(p, "User-Agent:", 11) == 0) {
1500
            useragent = p + 11;
1501
            if (*useragent && *useragent != '\n' && isspace(*useragent))
1502
                useragent++;
1503
            break;
1504
        }
1505
        p = strchr(p, '\n');
1506
        if (!p)
1507
            break;
1508

    
1509
        p++;
1510
    }
1511

    
1512
    redir_type = REDIR_NONE;
1513
    if (av_match_ext(filename, "asx")) {
1514
        redir_type = REDIR_ASX;
1515
        filename[strlen(filename)-1] = 'f';
1516
    } else if (av_match_ext(filename, "asf") &&
1517
        (!useragent || strncasecmp(useragent, "NSPlayer", 8) != 0)) {
1518
        /* if this isn't WMP or lookalike, return the redirector file */
1519
        redir_type = REDIR_ASF;
1520
    } else if (av_match_ext(filename, "rpm,ram")) {
1521
        redir_type = REDIR_RAM;
1522
        strcpy(filename + strlen(filename)-2, "m");
1523
    } else if (av_match_ext(filename, "rtsp")) {
1524
        redir_type = REDIR_RTSP;
1525
        compute_real_filename(filename, sizeof(filename) - 1);
1526
    } else if (av_match_ext(filename, "sdp")) {
1527
        redir_type = REDIR_SDP;
1528
        compute_real_filename(filename, sizeof(filename) - 1);
1529
    }
1530

    
1531
    // "redirect" / request to index.html
1532
    if (!strlen(filename))
1533
        av_strlcpy(filename, "index.html", sizeof(filename) - 1);
1534

    
1535
    stream = first_stream;
1536
    while (stream != NULL) {
1537
        if (!strcmp(stream->filename, filename) && validate_acl(stream, c))
1538
            break;
1539
        stream = stream->next;
1540
    }
1541
    if (stream == NULL) {
1542
        snprintf(msg, sizeof(msg), "File '%s' not found", url);
1543
        http_log("File '%s' not found\n", url);
1544
        goto send_error;
1545
    }
1546

    
1547
    c->stream = stream;
1548
    memcpy(c->feed_streams, stream->feed_streams, sizeof(c->feed_streams));
1549
    memset(c->switch_feed_streams, -1, sizeof(c->switch_feed_streams));
1550

    
1551
    if (stream->stream_type == STREAM_TYPE_REDIRECT) {
1552
        c->http_error = 301;
1553
        q = c->buffer;
1554
        q += snprintf(q, c->buffer_size,
1555
                      "HTTP/1.0 301 Moved\r\n"
1556
                      "Location: %s\r\n"
1557
                      "Content-type: text/html\r\n"
1558
                      "\r\n"
1559
                      "<html><head><title>Moved</title></head><body>\r\n"
1560
                      "You should be <a href=\"%s\">redirected</a>.\r\n"
1561
                      "</body></html>\r\n", stream->feed_filename, stream->feed_filename);
1562
        /* prepare output buffer */
1563
        c->buffer_ptr = c->buffer;
1564
        c->buffer_end = q;
1565
        c->state = HTTPSTATE_SEND_HEADER;
1566
        return 0;
1567
    }
1568

    
1569
    /* If this is WMP, get the rate information */
1570
    if (extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
1571
        if (modify_current_stream(c, ratebuf)) {
1572
            for (i = 0; i < FF_ARRAY_ELEMS(c->feed_streams); i++) {
1573
                if (c->switch_feed_streams[i] >= 0)
1574
                    c->switch_feed_streams[i] = -1;
1575
            }
1576
        }
1577
    }
1578

    
1579
    if (c->post == 0 && stream->stream_type == STREAM_TYPE_LIVE)
1580
        current_bandwidth += stream->bandwidth;
1581

    
1582
    /* If already streaming this feed, do not let start another feeder. */
1583
    if (stream->feed_opened) {
1584
        snprintf(msg, sizeof(msg), "This feed is already being received.");
1585
        http_log("Feed '%s' already being received\n", stream->feed_filename);
1586
        goto send_error;
1587
    }
1588

    
1589
    if (c->post == 0 && max_bandwidth < current_bandwidth) {
1590
        c->http_error = 503;
1591
        q = c->buffer;
1592
        q += snprintf(q, c->buffer_size,
1593
                      "HTTP/1.0 503 Server too busy\r\n"
1594
                      "Content-type: text/html\r\n"
1595
                      "\r\n"
1596
                      "<html><head><title>Too busy</title></head><body>\r\n"
1597
                      "<p>The server is too busy to serve your request at this time.</p>\r\n"
1598
                      "<p>The bandwidth being served (including your stream) is %"PRIu64"kbit/sec, "
1599
                      "and this exceeds the limit of %"PRIu64"kbit/sec.</p>\r\n"
1600
                      "</body></html>\r\n", current_bandwidth, max_bandwidth);
1601
        /* prepare output buffer */
1602
        c->buffer_ptr = c->buffer;
1603
        c->buffer_end = q;
1604
        c->state = HTTPSTATE_SEND_HEADER;
1605
        return 0;
1606
    }
1607

    
1608
    if (redir_type != REDIR_NONE) {
1609
        char *hostinfo = 0;
1610

    
1611
        for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1612
            if (strncasecmp(p, "Host:", 5) == 0) {
1613
                hostinfo = p + 5;
1614
                break;
1615
            }
1616
            p = strchr(p, '\n');
1617
            if (!p)
1618
                break;
1619

    
1620
            p++;
1621
        }
1622

    
1623
        if (hostinfo) {
1624
            char *eoh;
1625
            char hostbuf[260];
1626

    
1627
            while (isspace(*hostinfo))
1628
                hostinfo++;
1629

    
1630
            eoh = strchr(hostinfo, '\n');
1631
            if (eoh) {
1632
                if (eoh[-1] == '\r')
1633
                    eoh--;
1634

    
1635
                if (eoh - hostinfo < sizeof(hostbuf) - 1) {
1636
                    memcpy(hostbuf, hostinfo, eoh - hostinfo);
1637
                    hostbuf[eoh - hostinfo] = 0;
1638

    
1639
                    c->http_error = 200;
1640
                    q = c->buffer;
1641
                    switch(redir_type) {
1642
                    case REDIR_ASX:
1643
                        q += snprintf(q, c->buffer_size,
1644
                                      "HTTP/1.0 200 ASX Follows\r\n"
1645
                                      "Content-type: video/x-ms-asf\r\n"
1646
                                      "\r\n"
1647
                                      "<ASX Version=\"3\">\r\n"
1648
                                      //"<!-- Autogenerated by ffserver -->\r\n"
1649
                                      "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n"
1650
                                      "</ASX>\r\n", hostbuf, filename, info);
1651
                        break;
1652
                    case REDIR_RAM:
1653
                        q += snprintf(q, c->buffer_size,
1654
                                      "HTTP/1.0 200 RAM Follows\r\n"
1655
                                      "Content-type: audio/x-pn-realaudio\r\n"
1656
                                      "\r\n"
1657
                                      "# Autogenerated by ffserver\r\n"
1658
                                      "http://%s/%s%s\r\n", hostbuf, filename, info);
1659
                        break;
1660
                    case REDIR_ASF:
1661
                        q += snprintf(q, c->buffer_size,
1662
                                      "HTTP/1.0 200 ASF Redirect follows\r\n"
1663
                                      "Content-type: video/x-ms-asf\r\n"
1664
                                      "\r\n"
1665
                                      "[Reference]\r\n"
1666
                                      "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info);
1667
                        break;
1668
                    case REDIR_RTSP:
1669
                        {
1670
                            char hostname[256], *p;
1671
                            /* extract only hostname */
1672
                            av_strlcpy(hostname, hostbuf, sizeof(hostname));
1673
                            p = strrchr(hostname, ':');
1674
                            if (p)
1675
                                *p = '\0';
1676
                            q += snprintf(q, c->buffer_size,
1677
                                          "HTTP/1.0 200 RTSP Redirect follows\r\n"
1678
                                          /* XXX: incorrect mime type ? */
1679
                                          "Content-type: application/x-rtsp\r\n"
1680
                                          "\r\n"
1681
                                          "rtsp://%s:%d/%s\r\n", hostname, ntohs(my_rtsp_addr.sin_port), filename);
1682
                        }
1683
                        break;
1684
                    case REDIR_SDP:
1685
                        {
1686
                            uint8_t *sdp_data;
1687
                            int sdp_data_size, len;
1688
                            struct sockaddr_in my_addr;
1689

    
1690
                            q += snprintf(q, c->buffer_size,
1691
                                          "HTTP/1.0 200 OK\r\n"
1692
                                          "Content-type: application/sdp\r\n"
1693
                                          "\r\n");
1694

    
1695
                            len = sizeof(my_addr);
1696
                            getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
1697

    
1698
                            /* XXX: should use a dynamic buffer */
1699
                            sdp_data_size = prepare_sdp_description(stream,
1700
                                                                    &sdp_data,
1701
                                                                    my_addr.sin_addr);
1702
                            if (sdp_data_size > 0) {
1703
                                memcpy(q, sdp_data, sdp_data_size);
1704
                                q += sdp_data_size;
1705
                                *q = '\0';
1706
                                av_free(sdp_data);
1707
                            }
1708
                        }
1709
                        break;
1710
                    default:
1711
                        abort();
1712
                        break;
1713
                    }
1714

    
1715
                    /* prepare output buffer */
1716
                    c->buffer_ptr = c->buffer;
1717
                    c->buffer_end = q;
1718
                    c->state = HTTPSTATE_SEND_HEADER;
1719
                    return 0;
1720
                }
1721
            }
1722
        }
1723

    
1724
        snprintf(msg, sizeof(msg), "ASX/RAM file not handled");
1725
        goto send_error;
1726
    }
1727

    
1728
    stream->conns_served++;
1729

    
1730
    /* XXX: add there authenticate and IP match */
1731

    
1732
    if (c->post) {
1733
        /* if post, it means a feed is being sent */
1734
        if (!stream->is_feed) {
1735
            /* However it might be a status report from WMP! Let us log the
1736
             * data as it might come in handy one day. */
1737
            char *logline = 0;
1738
            int client_id = 0;
1739

    
1740
            for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1741
                if (strncasecmp(p, "Pragma: log-line=", 17) == 0) {
1742
                    logline = p;
1743
                    break;
1744
                }
1745
                if (strncasecmp(p, "Pragma: client-id=", 18) == 0)
1746
                    client_id = strtol(p + 18, 0, 10);
1747
                p = strchr(p, '\n');
1748
                if (!p)
1749
                    break;
1750

    
1751
                p++;
1752
            }
1753

    
1754
            if (logline) {
1755
                char *eol = strchr(logline, '\n');
1756

    
1757
                logline += 17;
1758

    
1759
                if (eol) {
1760
                    if (eol[-1] == '\r')
1761
                        eol--;
1762
                    http_log("%.*s\n", (int) (eol - logline), logline);
1763
                    c->suppress_log = 1;
1764
                }
1765
            }
1766

    
1767
#ifdef DEBUG_WMP
1768
            http_log("\nGot request:\n%s\n", c->buffer);
1769
#endif
1770

    
1771
            if (client_id && extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
1772
                HTTPContext *wmpc;
1773

    
1774
                /* Now we have to find the client_id */
1775
                for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->next) {
1776
                    if (wmpc->wmp_client_id == client_id)
1777
                        break;
1778
                }
1779

    
1780
                if (wmpc && modify_current_stream(wmpc, ratebuf))
1781
                    wmpc->switch_pending = 1;
1782
            }
1783

    
1784
            snprintf(msg, sizeof(msg), "POST command not handled");
1785
            c->stream = 0;
1786
            goto send_error;
1787
        }
1788
        if (http_start_receive_data(c) < 0) {
1789
            snprintf(msg, sizeof(msg), "could not open feed");
1790
            goto send_error;
1791
        }
1792
        c->http_error = 0;
1793
        c->state = HTTPSTATE_RECEIVE_DATA;
1794
        return 0;
1795
    }
1796

    
1797
#ifdef DEBUG_WMP
1798
    if (strcmp(stream->filename + strlen(stream->filename) - 4, ".asf") == 0)
1799
        http_log("\nGot request:\n%s\n", c->buffer);
1800
#endif
1801

    
1802
    if (c->stream->stream_type == STREAM_TYPE_STATUS)
1803
        goto send_status;
1804

    
1805
    /* open input stream */
1806
    if (open_input_stream(c, info) < 0) {
1807
        snprintf(msg, sizeof(msg), "Input stream corresponding to '%s' not found", url);
1808
        goto send_error;
1809
    }
1810

    
1811
    /* prepare http header */
1812
    q = c->buffer;
1813
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 OK\r\n");
1814
    mime_type = c->stream->fmt->mime_type;
1815
    if (!mime_type)
1816
        mime_type = "application/x-octet-stream";
1817
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Pragma: no-cache\r\n");
1818

    
1819
    /* for asf, we need extra headers */
1820
    if (!strcmp(c->stream->fmt->name,"asf_stream")) {
1821
        /* Need to allocate a client id */
1822

    
1823
        c->wmp_client_id = av_lfg_get(&random_state);
1824

    
1825
        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Server: Cougar 4.1.0.3923\r\nCache-Control: no-cache\r\nPragma: client-id=%d\r\nPragma: features=\"broadcast\"\r\n", c->wmp_client_id);
1826
    }
1827
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-Type: %s\r\n", mime_type);
1828
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
1829

    
1830
    /* prepare output buffer */
1831
    c->http_error = 0;
1832
    c->buffer_ptr = c->buffer;
1833
    c->buffer_end = q;
1834
    c->state = HTTPSTATE_SEND_HEADER;
1835
    return 0;
1836
 send_error:
1837
    c->http_error = 404;
1838
    q = c->buffer;
1839
    q += snprintf(q, c->buffer_size,
1840
                  "HTTP/1.0 404 Not Found\r\n"
1841
                  "Content-type: text/html\r\n"
1842
                  "\r\n"
1843
                  "<html>\n"
1844
                  "<head><title>404 Not Found</title></head>\n"
1845
                  "<body>%s</body>\n"
1846
                  "</html>\n", msg);
1847
    /* prepare output buffer */
1848
    c->buffer_ptr = c->buffer;
1849
    c->buffer_end = q;
1850
    c->state = HTTPSTATE_SEND_HEADER;
1851
    return 0;
1852
 send_status:
1853
    compute_status(c);
1854
    c->http_error = 200; /* horrible : we use this value to avoid
1855
                            going to the send data state */
1856
    c->state = HTTPSTATE_SEND_HEADER;
1857
    return 0;
1858
}
1859

    
1860
static void fmt_bytecount(AVIOContext *pb, int64_t count)
1861
{
1862
    static const char *suffix = " kMGTP";
1863
    const char *s;
1864

    
1865
    for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++);
1866

    
1867
    avio_printf(pb, "%"PRId64"%c", count, *s);
1868
}
1869

    
1870
static void compute_status(HTTPContext *c)
1871
{
1872
    HTTPContext *c1;
1873
    FFStream *stream;
1874
    char *p;
1875
    time_t ti;
1876
    int i, len;
1877
    AVIOContext *pb;
1878

    
1879
    if (avio_open_dyn_buf(&pb) < 0) {
1880
        /* XXX: return an error ? */
1881
        c->buffer_ptr = c->buffer;
1882
        c->buffer_end = c->buffer;
1883
        return;
1884
    }
1885

    
1886
    avio_printf(pb, "HTTP/1.0 200 OK\r\n");
1887
    avio_printf(pb, "Content-type: %s\r\n", "text/html");
1888
    avio_printf(pb, "Pragma: no-cache\r\n");
1889
    avio_printf(pb, "\r\n");
1890

    
1891
    avio_printf(pb, "<html><head><title>%s Status</title>\n", program_name);
1892
    if (c->stream->feed_filename[0])
1893
        avio_printf(pb, "<link rel=\"shortcut icon\" href=\"%s\">\n", c->stream->feed_filename);
1894
    avio_printf(pb, "</head>\n<body>");
1895
    avio_printf(pb, "<h1>%s Status</h1>\n", program_name);
1896
    /* format status */
1897
    avio_printf(pb, "<h2>Available Streams</h2>\n");
1898
    avio_printf(pb, "<table cellspacing=0 cellpadding=4>\n");
1899
    avio_printf(pb, "<tr><th valign=top>Path<th align=left>Served<br>Conns<th><br>bytes<th valign=top>Format<th>Bit rate<br>kbits/s<th align=left>Video<br>kbits/s<th><br>Codec<th align=left>Audio<br>kbits/s<th><br>Codec<th align=left valign=top>Feed\n");
1900
    stream = first_stream;
1901
    while (stream != NULL) {
1902
        char sfilename[1024];
1903
        char *eosf;
1904

    
1905
        if (stream->feed != stream) {
1906
            av_strlcpy(sfilename, stream->filename, sizeof(sfilename) - 10);
1907
            eosf = sfilename + strlen(sfilename);
1908
            if (eosf - sfilename >= 4) {
1909
                if (strcmp(eosf - 4, ".asf") == 0)
1910
                    strcpy(eosf - 4, ".asx");
1911
                else if (strcmp(eosf - 3, ".rm") == 0)
1912
                    strcpy(eosf - 3, ".ram");
1913
                else if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
1914
                    /* generate a sample RTSP director if
1915
                       unicast. Generate an SDP redirector if
1916
                       multicast */
1917
                    eosf = strrchr(sfilename, '.');
1918
                    if (!eosf)
1919
                        eosf = sfilename + strlen(sfilename);
1920
                    if (stream->is_multicast)
1921
                        strcpy(eosf, ".sdp");
1922
                    else
1923
                        strcpy(eosf, ".rtsp");
1924
                }
1925
            }
1926

    
1927
            avio_printf(pb, "<tr><td><a href=\"/%s\">%s</a> ",
1928
                         sfilename, stream->filename);
1929
            avio_printf(pb, "<td align=right> %d <td align=right> ",
1930
                        stream->conns_served);
1931
            fmt_bytecount(pb, stream->bytes_served);
1932
            switch(stream->stream_type) {
1933
            case STREAM_TYPE_LIVE: {
1934
                    int audio_bit_rate = 0;
1935
                    int video_bit_rate = 0;
1936
                    const char *audio_codec_name = "";
1937
                    const char *video_codec_name = "";
1938
                    const char *audio_codec_name_extra = "";
1939
                    const char *video_codec_name_extra = "";
1940

    
1941
                    for(i=0;i<stream->nb_streams;i++) {
1942
                        AVStream *st = stream->streams[i];
1943
                        AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
1944
                        switch(st->codec->codec_type) {
1945
                        case AVMEDIA_TYPE_AUDIO:
1946
                            audio_bit_rate += st->codec->bit_rate;
1947
                            if (codec) {
1948
                                if (*audio_codec_name)
1949
                                    audio_codec_name_extra = "...";
1950
                                audio_codec_name = codec->name;
1951
                            }
1952
                            break;
1953
                        case AVMEDIA_TYPE_VIDEO:
1954
                            video_bit_rate += st->codec->bit_rate;
1955
                            if (codec) {
1956
                                if (*video_codec_name)
1957
                                    video_codec_name_extra = "...";
1958
                                video_codec_name = codec->name;
1959
                            }
1960
                            break;
1961
                        case AVMEDIA_TYPE_DATA:
1962
                            video_bit_rate += st->codec->bit_rate;
1963
                            break;
1964
                        default:
1965
                            abort();
1966
                        }
1967
                    }
1968
                    avio_printf(pb, "<td align=center> %s <td align=right> %d <td align=right> %d <td> %s %s <td align=right> %d <td> %s %s",
1969
                                 stream->fmt->name,
1970
                                 stream->bandwidth,
1971
                                 video_bit_rate / 1000, video_codec_name, video_codec_name_extra,
1972
                                 audio_bit_rate / 1000, audio_codec_name, audio_codec_name_extra);
1973
                    if (stream->feed)
1974
                        avio_printf(pb, "<td>%s", stream->feed->filename);
1975
                    else
1976
                        avio_printf(pb, "<td>%s", stream->feed_filename);
1977
                    avio_printf(pb, "\n");
1978
                }
1979
                break;
1980
            default:
1981
                avio_printf(pb, "<td align=center> - <td align=right> - <td align=right> - <td><td align=right> - <td>\n");
1982
                break;
1983
            }
1984
        }
1985
        stream = stream->next;
1986
    }
1987
    avio_printf(pb, "</table>\n");
1988

    
1989
    stream = first_stream;
1990
    while (stream != NULL) {
1991
        if (stream->feed == stream) {
1992
            avio_printf(pb, "<h2>Feed %s</h2>", stream->filename);
1993
            if (stream->pid) {
1994
                avio_printf(pb, "Running as pid %d.\n", stream->pid);
1995

    
1996
#if defined(linux) && !defined(CONFIG_NOCUTILS)
1997
                {
1998
                    FILE *pid_stat;
1999
                    char ps_cmd[64];
2000

    
2001
                    /* This is somewhat linux specific I guess */
2002
                    snprintf(ps_cmd, sizeof(ps_cmd),
2003
                             "ps -o \"%%cpu,cputime\" --no-headers %d",
2004
                             stream->pid);
2005

    
2006
                    pid_stat = popen(ps_cmd, "r");
2007
                    if (pid_stat) {
2008
                        char cpuperc[10];
2009
                        char cpuused[64];
2010

    
2011
                        if (fscanf(pid_stat, "%10s %64s", cpuperc,
2012
                                   cpuused) == 2) {
2013
                            avio_printf(pb, "Currently using %s%% of the cpu. Total time used %s.\n",
2014
                                         cpuperc, cpuused);
2015
                        }
2016
                        fclose(pid_stat);
2017
                    }
2018
                }
2019
#endif
2020

    
2021
                avio_printf(pb, "<p>");
2022
            }
2023
            avio_printf(pb, "<table cellspacing=0 cellpadding=4><tr><th>Stream<th>type<th>kbits/s<th align=left>codec<th align=left>Parameters\n");
2024

    
2025
            for (i = 0; i < stream->nb_streams; i++) {
2026
                AVStream *st = stream->streams[i];
2027
                AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
2028
                const char *type = "unknown";
2029
                char parameters[64];
2030

    
2031
                parameters[0] = 0;
2032

    
2033
                switch(st->codec->codec_type) {
2034
                case AVMEDIA_TYPE_AUDIO:
2035
                    type = "audio";
2036
                    snprintf(parameters, sizeof(parameters), "%d channel(s), %d Hz", st->codec->channels, st->codec->sample_rate);
2037
                    break;
2038
                case AVMEDIA_TYPE_VIDEO:
2039
                    type = "video";
2040
                    snprintf(parameters, sizeof(parameters), "%dx%d, q=%d-%d, fps=%d", st->codec->width, st->codec->height,
2041
                                st->codec->qmin, st->codec->qmax, st->codec->time_base.den / st->codec->time_base.num);
2042
                    break;
2043
                default:
2044
                    abort();
2045
                }
2046
                avio_printf(pb, "<tr><td align=right>%d<td>%s<td align=right>%d<td>%s<td>%s\n",
2047
                        i, type, st->codec->bit_rate/1000, codec ? codec->name : "", parameters);
2048
            }
2049
            avio_printf(pb, "</table>\n");
2050

    
2051
        }
2052
        stream = stream->next;
2053
    }
2054

    
2055
    /* connection status */
2056
    avio_printf(pb, "<h2>Connection Status</h2>\n");
2057

    
2058
    avio_printf(pb, "Number of connections: %d / %d<br>\n",
2059
                 nb_connections, nb_max_connections);
2060

    
2061
    avio_printf(pb, "Bandwidth in use: %"PRIu64"k / %"PRIu64"k<br>\n",
2062
                 current_bandwidth, max_bandwidth);
2063

    
2064
    avio_printf(pb, "<table>\n");
2065
    avio_printf(pb, "<tr><th>#<th>File<th>IP<th>Proto<th>State<th>Target bits/sec<th>Actual bits/sec<th>Bytes transferred\n");
2066
    c1 = first_http_ctx;
2067
    i = 0;
2068
    while (c1 != NULL) {
2069
        int bitrate;
2070
        int j;
2071

    
2072
        bitrate = 0;
2073
        if (c1->stream) {
2074
            for (j = 0; j < c1->stream->nb_streams; j++) {
2075
                if (!c1->stream->feed)
2076
                    bitrate += c1->stream->streams[j]->codec->bit_rate;
2077
                else if (c1->feed_streams[j] >= 0)
2078
                    bitrate += c1->stream->feed->streams[c1->feed_streams[j]]->codec->bit_rate;
2079
            }
2080
        }
2081

    
2082
        i++;
2083
        p = inet_ntoa(c1->from_addr.sin_addr);
2084
        avio_printf(pb, "<tr><td><b>%d</b><td>%s%s<td>%s<td>%s<td>%s<td align=right>",
2085
                    i,
2086
                    c1->stream ? c1->stream->filename : "",
2087
                    c1->state == HTTPSTATE_RECEIVE_DATA ? "(input)" : "",
2088
                    p,
2089
                    c1->protocol,
2090
                    http_state[c1->state]);
2091
        fmt_bytecount(pb, bitrate);
2092
        avio_printf(pb, "<td align=right>");
2093
        fmt_bytecount(pb, compute_datarate(&c1->datarate, c1->data_count) * 8);
2094
        avio_printf(pb, "<td align=right>");
2095
        fmt_bytecount(pb, c1->data_count);
2096
        avio_printf(pb, "\n");
2097
        c1 = c1->next;
2098
    }
2099
    avio_printf(pb, "</table>\n");
2100

    
2101
    /* date */
2102
    ti = time(NULL);
2103
    p = ctime(&ti);
2104
    avio_printf(pb, "<hr size=1 noshade>Generated at %s", p);
2105
    avio_printf(pb, "</body>\n</html>\n");
2106

    
2107
    len = avio_close_dyn_buf(pb, &c->pb_buffer);
2108
    c->buffer_ptr = c->pb_buffer;
2109
    c->buffer_end = c->pb_buffer + len;
2110
}
2111

    
2112
/* check if the parser needs to be opened for stream i */
2113
static void open_parser(AVFormatContext *s, int i)
2114
{
2115
    AVStream *st = s->streams[i];
2116
    AVCodec *codec;
2117

    
2118
    if (!st->codec->codec) {
2119
        codec = avcodec_find_decoder(st->codec->codec_id);
2120
        if (codec && (codec->capabilities & CODEC_CAP_PARSE_ONLY)) {
2121
            st->codec->parse_only = 1;
2122
            if (avcodec_open(st->codec, codec) < 0)
2123
                st->codec->parse_only = 0;
2124
        }
2125
    }
2126
}
2127

    
2128
static int open_input_stream(HTTPContext *c, const char *info)
2129
{
2130
    char buf[128];
2131
    char input_filename[1024];
2132
    AVFormatContext *s;
2133
    int buf_size, i, ret;
2134
    int64_t stream_pos;
2135

    
2136
    /* find file name */
2137
    if (c->stream->feed) {
2138
        strcpy(input_filename, c->stream->feed->feed_filename);
2139
        buf_size = FFM_PACKET_SIZE;
2140
        /* compute position (absolute time) */
2141
        if (av_find_info_tag(buf, sizeof(buf), "date", info)) {
2142
            if ((ret = av_parse_time(&stream_pos, buf, 0)) < 0)
2143
                return ret;
2144
        } else if (av_find_info_tag(buf, sizeof(buf), "buffer", info)) {
2145
            int prebuffer = strtol(buf, 0, 10);
2146
            stream_pos = av_gettime() - prebuffer * (int64_t)1000000;
2147
        } else
2148
            stream_pos = av_gettime() - c->stream->prebuffer * (int64_t)1000;
2149
    } else {
2150
        strcpy(input_filename, c->stream->feed_filename);
2151
        buf_size = 0;
2152
        /* compute position (relative time) */
2153
        if (av_find_info_tag(buf, sizeof(buf), "date", info)) {
2154
            if ((ret = av_parse_time(&stream_pos, buf, 1)) < 0)
2155
                return ret;
2156
        } else
2157
            stream_pos = 0;
2158
    }
2159
    if (input_filename[0] == '\0')
2160
        return -1;
2161

    
2162
    /* open stream */
2163
    if ((ret = av_open_input_file(&s, input_filename, c->stream->ifmt,
2164
                                  buf_size, c->stream->ap_in)) < 0) {
2165
        http_log("could not open %s: %d\n", input_filename, ret);
2166
        return -1;
2167
    }
2168
    s->flags |= AVFMT_FLAG_GENPTS;
2169
    c->fmt_in = s;
2170
    if (strcmp(s->iformat->name, "ffm") && av_find_stream_info(c->fmt_in) < 0) {
2171
        http_log("Could not find stream info '%s'\n", input_filename);
2172
        av_close_input_file(s);
2173
        return -1;
2174
    }
2175

    
2176
    /* open each parser */
2177
    for(i=0;i<s->nb_streams;i++)
2178
        open_parser(s, i);
2179

    
2180
    /* choose stream as clock source (we favorize video stream if
2181
       present) for packet sending */
2182
    c->pts_stream_index = 0;
2183
    for(i=0;i<c->stream->nb_streams;i++) {
2184
        if (c->pts_stream_index == 0 &&
2185
            c->stream->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
2186
            c->pts_stream_index = i;
2187
        }
2188
    }
2189

    
2190
#if 1
2191
    if (c->fmt_in->iformat->read_seek)
2192
        av_seek_frame(c->fmt_in, -1, stream_pos, 0);
2193
#endif
2194
    /* set the start time (needed for maxtime and RTP packet timing) */
2195
    c->start_time = cur_time;
2196
    c->first_pts = AV_NOPTS_VALUE;
2197
    return 0;
2198
}
2199

    
2200
/* return the server clock (in us) */
2201
static int64_t get_server_clock(HTTPContext *c)
2202
{
2203
    /* compute current pts value from system time */
2204
    return (cur_time - c->start_time) * 1000;
2205
}
2206

    
2207
/* return the estimated time at which the current packet must be sent
2208
   (in us) */
2209
static int64_t get_packet_send_clock(HTTPContext *c)
2210
{
2211
    int bytes_left, bytes_sent, frame_bytes;
2212

    
2213
    frame_bytes = c->cur_frame_bytes;
2214
    if (frame_bytes <= 0)
2215
        return c->cur_pts;
2216
    else {
2217
        bytes_left = c->buffer_end - c->buffer_ptr;
2218
        bytes_sent = frame_bytes - bytes_left;
2219
        return c->cur_pts + (c->cur_frame_duration * bytes_sent) / frame_bytes;
2220
    }
2221
}
2222

    
2223

    
2224
static int http_prepare_data(HTTPContext *c)
2225
{
2226
    int i, len, ret;
2227
    AVFormatContext *ctx;
2228

    
2229
    av_freep(&c->pb_buffer);
2230
    switch(c->state) {
2231
    case HTTPSTATE_SEND_DATA_HEADER:
2232
        memset(&c->fmt_ctx, 0, sizeof(c->fmt_ctx));
2233
        av_metadata_set2(&c->fmt_ctx.metadata, "author"   , c->stream->author   , 0);
2234
        av_metadata_set2(&c->fmt_ctx.metadata, "comment"  , c->stream->comment  , 0);
2235
        av_metadata_set2(&c->fmt_ctx.metadata, "copyright", c->stream->copyright, 0);
2236
        av_metadata_set2(&c->fmt_ctx.metadata, "title"    , c->stream->title    , 0);
2237

    
2238
        for(i=0;i<c->stream->nb_streams;i++) {
2239
            AVStream *st;
2240
            AVStream *src;
2241
            st = av_mallocz(sizeof(AVStream));
2242
            c->fmt_ctx.streams[i] = st;
2243
            /* if file or feed, then just take streams from FFStream struct */
2244
            if (!c->stream->feed ||
2245
                c->stream->feed == c->stream)
2246
                src = c->stream->streams[i];
2247
            else
2248
                src = c->stream->feed->streams[c->stream->feed_streams[i]];
2249

    
2250
            *st = *src;
2251
            st->priv_data = 0;
2252
            st->codec->frame_number = 0; /* XXX: should be done in
2253
                                           AVStream, not in codec */
2254
        }
2255
        /* set output format parameters */
2256
        c->fmt_ctx.oformat = c->stream->fmt;
2257
        c->fmt_ctx.nb_streams = c->stream->nb_streams;
2258

    
2259
        c->got_key_frame = 0;
2260

    
2261
        /* prepare header and save header data in a stream */
2262
        if (avio_open_dyn_buf(&c->fmt_ctx.pb) < 0) {
2263
            /* XXX: potential leak */
2264
            return -1;
2265
        }
2266
        c->fmt_ctx.pb->seekable = 0;
2267

    
2268
        /*
2269
         * HACK to avoid mpeg ps muxer to spit many underflow errors
2270
         * Default value from FFmpeg
2271
         * Try to set it use configuration option
2272
         */
2273
        c->fmt_ctx.preload   = (int)(0.5*AV_TIME_BASE);
2274
        c->fmt_ctx.max_delay = (int)(0.7*AV_TIME_BASE);
2275

    
2276
        av_set_parameters(&c->fmt_ctx, NULL);
2277
        if (av_write_header(&c->fmt_ctx) < 0) {
2278
            http_log("Error writing output header\n");
2279
            return -1;
2280
        }
2281
        av_metadata_free(&c->fmt_ctx.metadata);
2282

    
2283
        len = avio_close_dyn_buf(c->fmt_ctx.pb, &c->pb_buffer);
2284
        c->buffer_ptr = c->pb_buffer;
2285
        c->buffer_end = c->pb_buffer + len;
2286

    
2287
        c->state = HTTPSTATE_SEND_DATA;
2288
        c->last_packet_sent = 0;
2289
        break;
2290
    case HTTPSTATE_SEND_DATA:
2291
        /* find a new packet */
2292
        /* read a packet from the input stream */
2293
        if (c->stream->feed)
2294
            ffm_set_write_index(c->fmt_in,
2295
                                c->stream->feed->feed_write_index,
2296
                                c->stream->feed->feed_size);
2297

    
2298
        if (c->stream->max_time &&
2299
            c->stream->max_time + c->start_time - cur_time < 0)
2300
            /* We have timed out */
2301
            c->state = HTTPSTATE_SEND_DATA_TRAILER;
2302
        else {
2303
            AVPacket pkt;
2304
        redo:
2305
            ret = av_read_frame(c->fmt_in, &pkt);
2306
            if (ret < 0) {
2307
                if (c->stream->feed) {
2308
                    /* if coming from feed, it means we reached the end of the
2309
                       ffm file, so must wait for more data */
2310
                    c->state = HTTPSTATE_WAIT_FEED;
2311
                    return 1; /* state changed */
2312
                } else if (ret == AVERROR(EAGAIN)) {
2313
                    /* input not ready, come back later */
2314
                    return 0;
2315
                } else {
2316
                    if (c->stream->loop) {
2317
                        av_close_input_file(c->fmt_in);
2318
                        c->fmt_in = NULL;
2319
                        if (open_input_stream(c, "") < 0)
2320
                            goto no_loop;
2321
                        goto redo;
2322
                    } else {
2323
                    no_loop:
2324
                        /* must send trailer now because eof or error */
2325
                        c->state = HTTPSTATE_SEND_DATA_TRAILER;
2326
                    }
2327
                }
2328
            } else {
2329
                int source_index = pkt.stream_index;
2330
                /* update first pts if needed */
2331
                if (c->first_pts == AV_NOPTS_VALUE) {
2332
                    c->first_pts = av_rescale_q(pkt.dts, c->fmt_in->streams[pkt.stream_index]->time_base, AV_TIME_BASE_Q);
2333
                    c->start_time = cur_time;
2334
                }
2335
                /* send it to the appropriate stream */
2336
                if (c->stream->feed) {
2337
                    /* if coming from a feed, select the right stream */
2338
                    if (c->switch_pending) {
2339
                        c->switch_pending = 0;
2340
                        for(i=0;i<c->stream->nb_streams;i++) {
2341
                            if (c->switch_feed_streams[i] == pkt.stream_index)
2342
                                if (pkt.flags & AV_PKT_FLAG_KEY)
2343
                                    c->switch_feed_streams[i] = -1;
2344
                            if (c->switch_feed_streams[i] >= 0)
2345
                                c->switch_pending = 1;
2346
                        }
2347
                    }
2348
                    for(i=0;i<c->stream->nb_streams;i++) {
2349
                        if (c->stream->feed_streams[i] == pkt.stream_index) {
2350
                            AVStream *st = c->fmt_in->streams[source_index];
2351
                            pkt.stream_index = i;
2352
                            if (pkt.flags & AV_PKT_FLAG_KEY &&
2353
                                (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
2354
                                 c->stream->nb_streams == 1))
2355
                                c->got_key_frame = 1;
2356
                            if (!c->stream->send_on_key || c->got_key_frame)
2357
                                goto send_it;
2358
                        }
2359
                    }
2360
                } else {
2361
                    AVCodecContext *codec;
2362
                    AVStream *ist, *ost;
2363
                send_it:
2364
                    ist = c->fmt_in->streams[source_index];
2365
                    /* specific handling for RTP: we use several
2366
                       output stream (one for each RTP
2367
                       connection). XXX: need more abstract handling */
2368
                    if (c->is_packetized) {
2369
                        /* compute send time and duration */
2370
                        c->cur_pts = av_rescale_q(pkt.dts, ist->time_base, AV_TIME_BASE_Q);
2371
                        c->cur_pts -= c->first_pts;
2372
                        c->cur_frame_duration = av_rescale_q(pkt.duration, ist->time_base, AV_TIME_BASE_Q);
2373
                        /* find RTP context */
2374
                        c->packet_stream_index = pkt.stream_index;
2375
                        ctx = c->rtp_ctx[c->packet_stream_index];
2376
                        if(!ctx) {
2377
                            av_free_packet(&pkt);
2378
                            break;
2379
                        }
2380
                        codec = ctx->streams[0]->codec;
2381
                        /* only one stream per RTP connection */
2382
                        pkt.stream_index = 0;
2383
                    } else {
2384
                        ctx = &c->fmt_ctx;
2385
                        /* Fudge here */
2386
                        codec = ctx->streams[pkt.stream_index]->codec;
2387
                    }
2388

    
2389
                    if (c->is_packetized) {
2390
                        int max_packet_size;
2391
                        if (c->rtp_protocol == RTSP_LOWER_TRANSPORT_TCP)
2392
                            max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
2393
                        else
2394
                            max_packet_size = url_get_max_packet_size(c->rtp_handles[c->packet_stream_index]);
2395
                        ret = ffio_open_dyn_packet_buf(&ctx->pb, max_packet_size);
2396
                    } else {
2397
                        ret = avio_open_dyn_buf(&ctx->pb);
2398
                    }
2399
                    if (ret < 0) {
2400
                        /* XXX: potential leak */
2401
                        return -1;
2402
                    }
2403
                    ost = ctx->streams[pkt.stream_index];
2404

    
2405
                    ctx->pb->seekable = 0;
2406
                    if (pkt.dts != AV_NOPTS_VALUE)
2407
                        pkt.dts = av_rescale_q(pkt.dts, ist->time_base, ost->time_base);
2408
                    if (pkt.pts != AV_NOPTS_VALUE)
2409
                        pkt.pts = av_rescale_q(pkt.pts, ist->time_base, ost->time_base);
2410
                    pkt.duration = av_rescale_q(pkt.duration, ist->time_base, ost->time_base);
2411
                    if (av_write_frame(ctx, &pkt) < 0) {
2412
                        http_log("Error writing frame to output\n");
2413
                        c->state = HTTPSTATE_SEND_DATA_TRAILER;
2414
                    }
2415

    
2416
                    len = avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
2417
                    c->cur_frame_bytes = len;
2418
                    c->buffer_ptr = c->pb_buffer;
2419
                    c->buffer_end = c->pb_buffer + len;
2420

    
2421
                    codec->frame_number++;
2422
                    if (len == 0) {
2423
                        av_free_packet(&pkt);
2424
                        goto redo;
2425
                    }
2426
                }
2427
                av_free_packet(&pkt);
2428
            }
2429
        }
2430
        break;
2431
    default:
2432
    case HTTPSTATE_SEND_DATA_TRAILER:
2433
        /* last packet test ? */
2434
        if (c->last_packet_sent || c->is_packetized)
2435
            return -1;
2436
        ctx = &c->fmt_ctx;
2437
        /* prepare header */
2438
        if (avio_open_dyn_buf(&ctx->pb) < 0) {
2439
            /* XXX: potential leak */
2440
            return -1;
2441
        }
2442
        c->fmt_ctx.pb->seekable = 0;
2443
        av_write_trailer(ctx);
2444
        len = avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
2445
        c->buffer_ptr = c->pb_buffer;
2446
        c->buffer_end = c->pb_buffer + len;
2447

    
2448
        c->last_packet_sent = 1;
2449
        break;
2450
    }
2451
    return 0;
2452
}
2453

    
2454
/* should convert the format at the same time */
2455
/* send data starting at c->buffer_ptr to the output connection
2456
   (either UDP or TCP connection) */
2457
static int http_send_data(HTTPContext *c)
2458
{
2459
    int len, ret;
2460

    
2461
    for(;;) {
2462
        if (c->buffer_ptr >= c->buffer_end) {
2463
            ret = http_prepare_data(c);
2464
            if (ret < 0)
2465
                return -1;
2466
            else if (ret != 0)
2467
                /* state change requested */
2468
                break;
2469
        } else {
2470
            if (c->is_packetized) {
2471
                /* RTP data output */
2472
                len = c->buffer_end - c->buffer_ptr;
2473
                if (len < 4) {
2474
                    /* fail safe - should never happen */
2475
                fail1:
2476
                    c->buffer_ptr = c->buffer_end;
2477
                    return 0;
2478
                }
2479
                len = (c->buffer_ptr[0] << 24) |
2480
                    (c->buffer_ptr[1] << 16) |
2481
                    (c->buffer_ptr[2] << 8) |
2482
                    (c->buffer_ptr[3]);
2483
                if (len > (c->buffer_end - c->buffer_ptr))
2484
                    goto fail1;
2485
                if ((get_packet_send_clock(c) - get_server_clock(c)) > 0) {
2486
                    /* nothing to send yet: we can wait */
2487
                    return 0;
2488
                }
2489

    
2490
                c->data_count += len;
2491
                update_datarate(&c->datarate, c->data_count);
2492
                if (c->stream)
2493
                    c->stream->bytes_served += len;
2494

    
2495
                if (c->rtp_protocol == RTSP_LOWER_TRANSPORT_TCP) {
2496
                    /* RTP packets are sent inside the RTSP TCP connection */
2497
                    AVIOContext *pb;
2498
                    int interleaved_index, size;
2499
                    uint8_t header[4];
2500
                    HTTPContext *rtsp_c;
2501

    
2502
                    rtsp_c = c->rtsp_c;
2503
                    /* if no RTSP connection left, error */
2504
                    if (!rtsp_c)
2505
                        return -1;
2506
                    /* if already sending something, then wait. */
2507
                    if (rtsp_c->state != RTSPSTATE_WAIT_REQUEST)
2508
                        break;
2509
                    if (avio_open_dyn_buf(&pb) < 0)
2510
                        goto fail1;
2511
                    interleaved_index = c->packet_stream_index * 2;
2512
                    /* RTCP packets are sent at odd indexes */
2513
                    if (c->buffer_ptr[1] == 200)
2514
                        interleaved_index++;
2515
                    /* write RTSP TCP header */
2516
                    header[0] = '$';
2517
                    header[1] = interleaved_index;
2518
                    header[2] = len >> 8;
2519
                    header[3] = len;
2520
                    avio_write(pb, header, 4);
2521
                    /* write RTP packet data */
2522
                    c->buffer_ptr += 4;
2523
                    avio_write(pb, c->buffer_ptr, len);
2524
                    size = avio_close_dyn_buf(pb, &c->packet_buffer);
2525
                    /* prepare asynchronous TCP sending */
2526
                    rtsp_c->packet_buffer_ptr = c->packet_buffer;
2527
                    rtsp_c->packet_buffer_end = c->packet_buffer + size;
2528
                    c->buffer_ptr += len;
2529

    
2530
                    /* send everything we can NOW */
2531
                    len = send(rtsp_c->fd, rtsp_c->packet_buffer_ptr,
2532
                                rtsp_c->packet_buffer_end - rtsp_c->packet_buffer_ptr, 0);
2533
                    if (len > 0)
2534
                        rtsp_c->packet_buffer_ptr += len;
2535
                    if (rtsp_c->packet_buffer_ptr < rtsp_c->packet_buffer_end) {
2536
                        /* if we could not send all the data, we will
2537
                           send it later, so a new state is needed to
2538
                           "lock" the RTSP TCP connection */
2539
                        rtsp_c->state = RTSPSTATE_SEND_PACKET;
2540
                        break;
2541
                    } else
2542
                        /* all data has been sent */
2543
                        av_freep(&c->packet_buffer);
2544
                } else {
2545
                    /* send RTP packet directly in UDP */
2546
                    c->buffer_ptr += 4;
2547
                    url_write(c->rtp_handles[c->packet_stream_index],
2548
                              c->buffer_ptr, len);
2549
                    c->buffer_ptr += len;
2550
                    /* here we continue as we can send several packets per 10 ms slot */
2551
                }
2552
            } else {
2553
                /* TCP data output */
2554
                len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
2555
                if (len < 0) {
2556
                    if (ff_neterrno() != AVERROR(EAGAIN) &&
2557
                        ff_neterrno() != AVERROR(EINTR))
2558
                        /* error : close connection */
2559
                        return -1;
2560
                    else
2561
                        return 0;
2562
                } else
2563
                    c->buffer_ptr += len;
2564

    
2565
                c->data_count += len;
2566
                update_datarate(&c->datarate, c->data_count);
2567
                if (c->stream)
2568
                    c->stream->bytes_served += len;
2569
                break;
2570
            }
2571
        }
2572
    } /* for(;;) */
2573
    return 0;
2574
}
2575

    
2576
static int http_start_receive_data(HTTPContext *c)
2577
{
2578
    int fd;
2579

    
2580
    if (c->stream->feed_opened)
2581
        return -1;
2582

    
2583
    /* Don't permit writing to this one */
2584
    if (c->stream->readonly)
2585
        return -1;
2586

    
2587
    /* open feed */
2588
    fd = open(c->stream->feed_filename, O_RDWR);
2589
    if (fd < 0) {
2590
        http_log("Error opening feeder file: %s\n", strerror(errno));
2591
        return -1;
2592
    }
2593
    c->feed_fd = fd;
2594

    
2595
    if (c->stream->truncate) {
2596
        /* truncate feed file */
2597
        ffm_write_write_index(c->feed_fd, FFM_PACKET_SIZE);
2598
        ftruncate(c->feed_fd, FFM_PACKET_SIZE);
2599
        http_log("Truncating feed file '%s'\n", c->stream->feed_filename);
2600
    } else {
2601
        if ((c->stream->feed_write_index = ffm_read_write_index(fd)) < 0) {
2602
            http_log("Error reading write index from feed file: %s\n", strerror(errno));
2603
            return -1;
2604
        }
2605
    }
2606

    
2607
    c->stream->feed_write_index = FFMAX(ffm_read_write_index(fd), FFM_PACKET_SIZE);
2608
    c->stream->feed_size = lseek(fd, 0, SEEK_END);
2609
    lseek(fd, 0, SEEK_SET);
2610

    
2611
    /* init buffer input */
2612
    c->buffer_ptr = c->buffer;
2613
    c->buffer_end = c->buffer + FFM_PACKET_SIZE;
2614
    c->stream->feed_opened = 1;
2615
    c->chunked_encoding = !!av_stristr(c->buffer, "Transfer-Encoding: chunked");
2616
    return 0;
2617
}
2618

    
2619
static int http_receive_data(HTTPContext *c)
2620
{
2621
    HTTPContext *c1;
2622
    int len, loop_run = 0;
2623

    
2624
    while (c->chunked_encoding && !c->chunk_size &&
2625
           c->buffer_end > c->buffer_ptr) {
2626
        /* read chunk header, if present */
2627
        len = recv(c->fd, c->buffer_ptr, 1, 0);
2628

    
2629
        if (len < 0) {
2630
            if (ff_neterrno() != AVERROR(EAGAIN) &&
2631
                ff_neterrno() != AVERROR(EINTR))
2632
                /* error : close connection */
2633
                goto fail;
2634
            return 0;
2635
        } else if (len == 0) {
2636
            /* end of connection : close it */
2637
            goto fail;
2638
        } else if (c->buffer_ptr - c->buffer >= 2 &&
2639
                   !memcmp(c->buffer_ptr - 1, "\r\n", 2)) {
2640
            c->chunk_size = strtol(c->buffer, 0, 16);
2641
            if (c->chunk_size == 0) // end of stream
2642
                goto fail;
2643
            c->buffer_ptr = c->buffer;
2644
            break;
2645
        } else if (++loop_run > 10) {
2646
            /* no chunk header, abort */
2647
            goto fail;
2648
        } else {
2649
            c->buffer_ptr++;
2650
        }
2651
    }
2652

    
2653
    if (c->buffer_end > c->buffer_ptr) {
2654
        len = recv(c->fd, c->buffer_ptr,
2655
                   FFMIN(c->chunk_size, c->buffer_end - c->buffer_ptr), 0);
2656
        if (len < 0) {
2657
            if (ff_neterrno() != AVERROR(EAGAIN) &&
2658
                ff_neterrno() != AVERROR(EINTR))
2659
                /* error : close connection */
2660
                goto fail;
2661
        } else if (len == 0)
2662
            /* end of connection : close it */
2663
            goto fail;
2664
        else {
2665
            c->chunk_size -= len;
2666
            c->buffer_ptr += len;
2667
            c->data_count += len;
2668
            update_datarate(&c->datarate, c->data_count);
2669
        }
2670
    }
2671

    
2672
    if (c->buffer_ptr - c->buffer >= 2 && c->data_count > FFM_PACKET_SIZE) {
2673
        if (c->buffer[0] != 'f' ||
2674
            c->buffer[1] != 'm') {
2675
            http_log("Feed stream has become desynchronized -- disconnecting\n");
2676
            goto fail;
2677
        }
2678
    }
2679

    
2680
    if (c->buffer_ptr >= c->buffer_end) {
2681
        FFStream *feed = c->stream;
2682
        /* a packet has been received : write it in the store, except
2683
           if header */
2684
        if (c->data_count > FFM_PACKET_SIZE) {
2685

    
2686
            //            printf("writing pos=0x%"PRIx64" size=0x%"PRIx64"\n", feed->feed_write_index, feed->feed_size);
2687
            /* XXX: use llseek or url_seek */
2688
            lseek(c->feed_fd, feed->feed_write_index, SEEK_SET);
2689
            if (write(c->feed_fd, c->buffer, FFM_PACKET_SIZE) < 0) {
2690
                http_log("Error writing to feed file: %s\n", strerror(errno));
2691
                goto fail;
2692
            }
2693

    
2694
            feed->feed_write_index += FFM_PACKET_SIZE;
2695
            /* update file size */
2696
            if (feed->feed_write_index > c->stream->feed_size)
2697
                feed->feed_size = feed->feed_write_index;
2698

    
2699
            /* handle wrap around if max file size reached */
2700
            if (c->stream->feed_max_size && feed->feed_write_index >= c->stream->feed_max_size)
2701
                feed->feed_write_index = FFM_PACKET_SIZE;
2702

    
2703
            /* write index */
2704
            if (ffm_write_write_index(c->feed_fd, feed->feed_write_index) < 0) {
2705
                http_log("Error writing index to feed file: %s\n", strerror(errno));
2706
                goto fail;
2707
            }
2708

    
2709
            /* wake up any waiting connections */
2710
            for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
2711
                if (c1->state == HTTPSTATE_WAIT_FEED &&
2712
                    c1->stream->feed == c->stream->feed)
2713
                    c1->state = HTTPSTATE_SEND_DATA;
2714
            }
2715
        } else {
2716
            /* We have a header in our hands that contains useful data */
2717
            AVFormatContext *s = NULL;
2718
            AVIOContext *pb;
2719
            AVInputFormat *fmt_in;
2720
            int i;
2721

    
2722
            /* use feed output format name to find corresponding input format */
2723
            fmt_in = av_find_input_format(feed->fmt->name);
2724
            if (!fmt_in)
2725
                goto fail;
2726

    
2727
            pb = avio_alloc_context(c->buffer, c->buffer_end - c->buffer,
2728
                                    0, NULL, NULL, NULL, NULL);
2729
            pb->seekable = 0;
2730

    
2731
            if (av_open_input_stream(&s, pb, c->stream->feed_filename, fmt_in, NULL) < 0) {
2732
                av_free(pb);
2733
                goto fail;
2734
            }
2735

    
2736
            /* Now we have the actual streams */
2737
            if (s->nb_streams != feed->nb_streams) {
2738
                av_close_input_stream(s);
2739
                av_free(pb);
2740
                http_log("Feed '%s' stream number does not match registered feed\n",
2741
                         c->stream->feed_filename);
2742
                goto fail;
2743
            }
2744

    
2745
            for (i = 0; i < s->nb_streams; i++) {
2746
                AVStream *fst = feed->streams[i];
2747
                AVStream *st = s->streams[i];
2748
                avcodec_copy_context(fst->codec, st->codec);
2749
            }
2750

    
2751
            av_close_input_stream(s);
2752
            av_free(pb);
2753
        }
2754
        c->buffer_ptr = c->buffer;
2755
    }
2756

    
2757
    return 0;
2758
 fail:
2759
    c->stream->feed_opened = 0;
2760
    close(c->feed_fd);
2761
    /* wake up any waiting connections to stop waiting for feed */
2762
    for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
2763
        if (c1->state == HTTPSTATE_WAIT_FEED &&
2764
            c1->stream->feed == c->stream->feed)
2765
            c1->state = HTTPSTATE_SEND_DATA_TRAILER;
2766
    }
2767
    return -1;
2768
}
2769

    
2770
/********************************************************************/
2771
/* RTSP handling */
2772

    
2773
static void rtsp_reply_header(HTTPContext *c, enum RTSPStatusCode error_number)
2774
{
2775
    const char *str;
2776
    time_t ti;
2777
    struct tm *tm;
2778
    char buf2[32];
2779

    
2780
    switch(error_number) {
2781
    case RTSP_STATUS_OK:
2782
        str = "OK";
2783
        break;
2784
    case RTSP_STATUS_METHOD:
2785
        str = "Method Not Allowed";
2786
        break;
2787
    case RTSP_STATUS_BANDWIDTH:
2788
        str = "Not Enough Bandwidth";
2789
        break;
2790
    case RTSP_STATUS_SESSION:
2791
        str = "Session Not Found";
2792
        break;
2793
    case RTSP_STATUS_STATE:
2794
        str = "Method Not Valid in This State";
2795
        break;
2796
    case RTSP_STATUS_AGGREGATE:
2797
        str = "Aggregate operation not allowed";
2798
        break;
2799
    case RTSP_STATUS_ONLY_AGGREGATE:
2800
        str = "Only aggregate operation allowed";
2801
        break;
2802
    case RTSP_STATUS_TRANSPORT:
2803
        str = "Unsupported transport";
2804
        break;
2805
    case RTSP_STATUS_INTERNAL:
2806
        str = "Internal Server Error";
2807
        break;
2808
    case RTSP_STATUS_SERVICE:
2809
        str = "Service Unavailable";
2810
        break;
2811
    case RTSP_STATUS_VERSION:
2812
        str = "RTSP Version not supported";
2813
        break;
2814
    default:
2815
        str = "Unknown Error";
2816
        break;
2817
    }
2818

    
2819
    avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", error_number, str);
2820
    avio_printf(c->pb, "CSeq: %d\r\n", c->seq);
2821

    
2822
    /* output GMT time */
2823
    ti = time(NULL);
2824
    tm = gmtime(&ti);
2825
    strftime(buf2, sizeof(buf2), "%a, %d %b %Y %H:%M:%S", tm);
2826
    avio_printf(c->pb, "Date: %s GMT\r\n", buf2);
2827
}
2828

    
2829
static void rtsp_reply_error(HTTPContext *c, enum RTSPStatusCode error_number)
2830
{
2831
    rtsp_reply_header(c, error_number);
2832
    avio_printf(c->pb, "\r\n");
2833
}
2834

    
2835
static int rtsp_parse_request(HTTPContext *c)
2836
{
2837
    const char *p, *p1, *p2;
2838
    char cmd[32];
2839
    char url[1024];
2840
    char protocol[32];
2841
    char line[1024];
2842
    int len;
2843
    RTSPMessageHeader header1, *header = &header1;
2844

    
2845
    c->buffer_ptr[0] = '\0';
2846
    p = c->buffer;
2847

    
2848
    get_word(cmd, sizeof(cmd), &p);
2849
    get_word(url, sizeof(url), &p);
2850
    get_word(protocol, sizeof(protocol), &p);
2851

    
2852
    av_strlcpy(c->method, cmd, sizeof(c->method));
2853
    av_strlcpy(c->url, url, sizeof(c->url));
2854
    av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
2855

    
2856
    if (avio_open_dyn_buf(&c->pb) < 0) {
2857
        /* XXX: cannot do more */
2858
        c->pb = NULL; /* safety */
2859
        return -1;
2860
    }
2861

    
2862
    /* check version name */
2863
    if (strcmp(protocol, "RTSP/1.0") != 0) {
2864
        rtsp_reply_error(c, RTSP_STATUS_VERSION);
2865
        goto the_end;
2866
    }
2867

    
2868
    /* parse each header line */
2869
    memset(header, 0, sizeof(*header));
2870
    /* skip to next line */
2871
    while (*p != '\n' && *p != '\0')
2872
        p++;
2873
    if (*p == '\n')
2874
        p++;
2875
    while (*p != '\0') {
2876
        p1 = memchr(p, '\n', (char *)c->buffer_ptr - p);
2877
        if (!p1)
2878
            break;
2879
        p2 = p1;
2880
        if (p2 > p && p2[-1] == '\r')
2881
            p2--;
2882
        /* skip empty line */
2883
        if (p2 == p)
2884
            break;
2885
        len = p2 - p;
2886
        if (len > sizeof(line) - 1)
2887
            len = sizeof(line) - 1;
2888
        memcpy(line, p, len);
2889
        line[len] = '\0';
2890
        ff_rtsp_parse_line(header, line, NULL, NULL);
2891
        p = p1 + 1;
2892
    }
2893

    
2894
    /* handle sequence number */
2895
    c->seq = header->seq;
2896

    
2897
    if (!strcmp(cmd, "DESCRIBE"))
2898
        rtsp_cmd_describe(c, url);
2899
    else if (!strcmp(cmd, "OPTIONS"))
2900
        rtsp_cmd_options(c, url);
2901
    else if (!strcmp(cmd, "SETUP"))
2902
        rtsp_cmd_setup(c, url, header);
2903
    else if (!strcmp(cmd, "PLAY"))
2904
        rtsp_cmd_play(c, url, header);
2905
    else if (!strcmp(cmd, "PAUSE"))
2906
        rtsp_cmd_pause(c, url, header);
2907
    else if (!strcmp(cmd, "TEARDOWN"))
2908
        rtsp_cmd_teardown(c, url, header);
2909
    else
2910
        rtsp_reply_error(c, RTSP_STATUS_METHOD);
2911

    
2912
 the_end:
2913
    len = avio_close_dyn_buf(c->pb, &c->pb_buffer);
2914
    c->pb = NULL; /* safety */
2915
    if (len < 0) {
2916
        /* XXX: cannot do more */
2917
        return -1;
2918
    }
2919
    c->buffer_ptr = c->pb_buffer;
2920
    c->buffer_end = c->pb_buffer + len;
2921
    c->state = RTSPSTATE_SEND_REPLY;
2922
    return 0;
2923
}
2924

    
2925
static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
2926
                                   struct in_addr my_ip)
2927
{
2928
    AVFormatContext *avc;
2929
    AVStream *avs = NULL;
2930
    int i;
2931

    
2932
    avc =  avformat_alloc_context();
2933
    if (avc == NULL) {
2934
        return -1;
2935
    }
2936
    av_metadata_set2(&avc->metadata, "title",
2937
                     stream->title[0] ? stream->title : "No Title", 0);
2938
    avc->nb_streams = stream->nb_streams;
2939
    if (stream->is_multicast) {
2940
        snprintf(avc->filename, 1024, "rtp://%s:%d?multicast=1?ttl=%d",
2941
                 inet_ntoa(stream->multicast_ip),
2942
                 stream->multicast_port, stream->multicast_ttl);
2943
    } else {
2944
        snprintf(avc->filename, 1024, "rtp://0.0.0.0");
2945
    }
2946

    
2947
#if !FF_API_MAX_STREAMS
2948
    if (avc->nb_streams >= INT_MAX/sizeof(*avc->streams) ||
2949
        !(avc->streams = av_malloc(avc->nb_streams * sizeof(*avc->streams))))
2950
        goto sdp_done;
2951
#endif
2952
    if (avc->nb_streams >= INT_MAX/sizeof(*avs) ||
2953
        !(avs = av_malloc(avc->nb_streams * sizeof(*avs))))
2954
        goto sdp_done;
2955

    
2956
    for(i = 0; i < stream->nb_streams; i++) {
2957
        avc->streams[i] = &avs[i];
2958
        avc->streams[i]->codec = stream->streams[i]->codec;
2959
    }
2960
    *pbuffer = av_mallocz(2048);
2961
    av_sdp_create(&avc, 1, *pbuffer, 2048);
2962

    
2963
 sdp_done:
2964
#if !FF_API_MAX_STREAMS
2965
    av_free(avc->streams);
2966
#endif
2967
    av_metadata_free(&avc->metadata);
2968
    av_free(avc);
2969
    av_free(avs);
2970

    
2971
    return strlen(*pbuffer);
2972
}
2973

    
2974
static void rtsp_cmd_options(HTTPContext *c, const char *url)
2975
{
2976
//    rtsp_reply_header(c, RTSP_STATUS_OK);
2977
    avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", RTSP_STATUS_OK, "OK");
2978
    avio_printf(c->pb, "CSeq: %d\r\n", c->seq);
2979
    avio_printf(c->pb, "Public: %s\r\n", "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
2980
    avio_printf(c->pb, "\r\n");
2981
}
2982

    
2983
static void rtsp_cmd_describe(HTTPContext *c, const char *url)
2984
{
2985
    FFStream *stream;
2986
    char path1[1024];
2987
    const char *path;
2988
    uint8_t *content;
2989
    int content_length, len;
2990
    struct sockaddr_in my_addr;
2991

    
2992
    /* find which url is asked */
2993
    av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
2994
    path = path1;
2995
    if (*path == '/')
2996
        path++;
2997

    
2998
    for(stream = first_stream; stream != NULL; stream = stream->next) {
2999
        if (!stream->is_feed &&
3000
            stream->fmt && !strcmp(stream->fmt->name, "rtp") &&
3001
            !strcmp(path, stream->filename)) {
3002
            goto found;
3003
        }
3004
    }
3005
    /* no stream found */
3006
    rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
3007
    return;
3008

    
3009
 found:
3010
    /* prepare the media description in sdp format */
3011

    
3012
    /* get the host IP */
3013
    len = sizeof(my_addr);
3014
    getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
3015
    content_length = prepare_sdp_description(stream, &content, my_addr.sin_addr);
3016
    if (content_length < 0) {
3017
        rtsp_reply_error(c, RTSP_STATUS_INTERNAL);
3018
        return;
3019
    }
3020
    rtsp_reply_header(c, RTSP_STATUS_OK);
3021
    avio_printf(c->pb, "Content-Base: %s/\r\n", url);
3022
    avio_printf(c->pb, "Content-Type: application/sdp\r\n");
3023
    avio_printf(c->pb, "Content-Length: %d\r\n", content_length);
3024
    avio_printf(c->pb, "\r\n");
3025
    avio_write(c->pb, content, content_length);
3026
    av_free(content);
3027
}
3028

    
3029
static HTTPContext *find_rtp_session(const char *session_id)
3030
{
3031
    HTTPContext *c;
3032

    
3033
    if (session_id[0] == '\0')
3034
        return NULL;
3035

    
3036
    for(c = first_http_ctx; c != NULL; c = c->next) {
3037
        if (!strcmp(c->session_id, session_id))
3038
            return c;
3039
    }
3040
    return NULL;
3041
}
3042

    
3043
static RTSPTransportField *find_transport(RTSPMessageHeader *h, enum RTSPLowerTransport lower_transport)
3044
{
3045
    RTSPTransportField *th;
3046
    int i;
3047

    
3048
    for(i=0;i<h->nb_transports;i++) {
3049
        th = &h->transports[i];
3050
        if (th->lower_transport == lower_transport)
3051
            return th;
3052
    }
3053
    return NULL;
3054
}
3055

    
3056
static void rtsp_cmd_setup(HTTPContext *c, const char *url,
3057
                           RTSPMessageHeader *h)
3058
{
3059
    FFStream *stream;
3060
    int stream_index, rtp_port, rtcp_port;
3061
    char buf[1024];
3062
    char path1[1024];
3063
    const char *path;
3064
    HTTPContext *rtp_c;
3065
    RTSPTransportField *th;
3066
    struct sockaddr_in dest_addr;
3067
    RTSPActionServerSetup setup;
3068

    
3069
    /* find which url is asked */
3070
    av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3071
    path = path1;
3072
    if (*path == '/')
3073
        path++;
3074

    
3075
    /* now check each stream */
3076
    for(stream = first_stream; stream != NULL; stream = stream->next) {
3077
        if (!stream->is_feed &&
3078
            stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
3079
            /* accept aggregate filenames only if single stream */
3080
            if (!strcmp(path, stream->filename)) {
3081
                if (stream->nb_streams != 1) {
3082
                    rtsp_reply_error(c, RTSP_STATUS_AGGREGATE);
3083
                    return;
3084
                }
3085
                stream_index = 0;
3086
                goto found;
3087
            }
3088

    
3089
            for(stream_index = 0; stream_index < stream->nb_streams;
3090
                stream_index++) {
3091
                snprintf(buf, sizeof(buf), "%s/streamid=%d",
3092
                         stream->filename, stream_index);
3093
                if (!strcmp(path, buf))
3094
                    goto found;
3095
            }
3096
        }
3097
    }
3098
    /* no stream found */
3099
    rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
3100
    return;
3101
 found:
3102

    
3103
    /* generate session id if needed */
3104
    if (h->session_id[0] == '\0')
3105
        snprintf(h->session_id, sizeof(h->session_id), "%08x%08x",
3106
                 av_lfg_get(&random_state), av_lfg_get(&random_state));
3107

    
3108
    /* find rtp session, and create it if none found */
3109
    rtp_c = find_rtp_session(h->session_id);
3110
    if (!rtp_c) {
3111
        /* always prefer UDP */
3112
        th = find_transport(h, RTSP_LOWER_TRANSPORT_UDP);
3113
        if (!th) {
3114
            th = find_transport(h, RTSP_LOWER_TRANSPORT_TCP);
3115
            if (!th) {
3116
                rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3117
                return;
3118
            }
3119
        }
3120

    
3121
        rtp_c = rtp_new_connection(&c->from_addr, stream, h->session_id,
3122
                                   th->lower_transport);
3123
        if (!rtp_c) {
3124
            rtsp_reply_error(c, RTSP_STATUS_BANDWIDTH);
3125
            return;
3126
        }
3127

    
3128
        /* open input stream */
3129
        if (open_input_stream(rtp_c, "") < 0) {
3130
            rtsp_reply_error(c, RTSP_STATUS_INTERNAL);
3131
            return;
3132
        }
3133
    }
3134

    
3135
    /* test if stream is OK (test needed because several SETUP needs
3136
       to be done for a given file) */
3137
    if (rtp_c->stream != stream) {
3138
        rtsp_reply_error(c, RTSP_STATUS_SERVICE);
3139
        return;
3140
    }
3141

    
3142
    /* test if stream is already set up */
3143
    if (rtp_c->rtp_ctx[stream_index]) {
3144
        rtsp_reply_error(c, RTSP_STATUS_STATE);
3145
        return;
3146
    }
3147

    
3148
    /* check transport */
3149
    th = find_transport(h, rtp_c->rtp_protocol);
3150
    if (!th || (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
3151
                th->client_port_min <= 0)) {
3152
        rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3153
        return;
3154
    }
3155

    
3156
    /* setup default options */
3157
    setup.transport_option[0] = '\0';
3158
    dest_addr = rtp_c->from_addr;
3159
    dest_addr.sin_port = htons(th->client_port_min);
3160

    
3161
    /* setup stream */
3162
    if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, c) < 0) {
3163
        rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3164
        return;
3165
    }
3166

    
3167
    /* now everything is OK, so we can send the connection parameters */
3168
    rtsp_reply_header(c, RTSP_STATUS_OK);
3169
    /* session ID */
3170
    avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3171

    
3172
    switch(rtp_c->rtp_protocol) {
3173
    case RTSP_LOWER_TRANSPORT_UDP:
3174
        rtp_port = rtp_get_local_rtp_port(rtp_c->rtp_handles[stream_index]);
3175
        rtcp_port = rtp_get_local_rtcp_port(rtp_c->rtp_handles[stream_index]);
3176
        avio_printf(c->pb, "Transport: RTP/AVP/UDP;unicast;"
3177
                    "client_port=%d-%d;server_port=%d-%d",
3178
                    th->client_port_min, th->client_port_max,
3179
                    rtp_port, rtcp_port);
3180
        break;
3181
    case RTSP_LOWER_TRANSPORT_TCP:
3182
        avio_printf(c->pb, "Transport: RTP/AVP/TCP;interleaved=%d-%d",
3183
                    stream_index * 2, stream_index * 2 + 1);
3184
        break;
3185
    default:
3186
        break;
3187
    }
3188
    if (setup.transport_option[0] != '\0')
3189
        avio_printf(c->pb, ";%s", setup.transport_option);
3190
    avio_printf(c->pb, "\r\n");
3191

    
3192

    
3193
    avio_printf(c->pb, "\r\n");
3194
}
3195

    
3196

    
3197
/* find an rtp connection by using the session ID. Check consistency
3198
   with filename */
3199
static HTTPContext *find_rtp_session_with_url(const char *url,
3200
                                              const char *session_id)
3201
{
3202
    HTTPContext *rtp_c;
3203
    char path1[1024];
3204
    const char *path;
3205
    char buf[1024];
3206
    int s, len;
3207

    
3208
    rtp_c = find_rtp_session(session_id);
3209
    if (!rtp_c)
3210
        return NULL;
3211

    
3212
    /* find which url is asked */
3213
    av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3214
    path = path1;
3215
    if (*path == '/')
3216
        path++;
3217
    if(!strcmp(path, rtp_c->stream->filename)) return rtp_c;
3218
    for(s=0; s<rtp_c->stream->nb_streams; ++s) {
3219
      snprintf(buf, sizeof(buf), "%s/streamid=%d",
3220
        rtp_c->stream->filename, s);
3221
      if(!strncmp(path, buf, sizeof(buf))) {
3222
    // XXX: Should we reply with RTSP_STATUS_ONLY_AGGREGATE if nb_streams>1?
3223
        return rtp_c;
3224
      }
3225
    }
3226
    len = strlen(path);
3227
    if (len > 0 && path[len - 1] == '/' &&
3228
        !strncmp(path, rtp_c->stream->filename, len - 1))
3229
        return rtp_c;
3230
    return NULL;
3231
}
3232

    
3233
static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3234
{
3235
    HTTPContext *rtp_c;
3236

    
3237
    rtp_c = find_rtp_session_with_url(url, h->session_id);
3238
    if (!rtp_c) {
3239
        rtsp_reply_error(c, RTSP_STATUS_SESSION);
3240
        return;
3241
    }
3242

    
3243
    if (rtp_c->state != HTTPSTATE_SEND_DATA &&
3244
        rtp_c->state != HTTPSTATE_WAIT_FEED &&
3245
        rtp_c->state != HTTPSTATE_READY) {
3246
        rtsp_reply_error(c, RTSP_STATUS_STATE);
3247
        return;
3248
    }
3249

    
3250
    rtp_c->state = HTTPSTATE_SEND_DATA;
3251

    
3252
    /* now everything is OK, so we can send the connection parameters */
3253
    rtsp_reply_header(c, RTSP_STATUS_OK);
3254
    /* session ID */
3255
    avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3256
    avio_printf(c->pb, "\r\n");
3257
}
3258

    
3259
static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3260
{
3261
    HTTPContext *rtp_c;
3262

    
3263
    rtp_c = find_rtp_session_with_url(url, h->session_id);
3264
    if (!rtp_c) {
3265
        rtsp_reply_error(c, RTSP_STATUS_SESSION);
3266
        return;
3267
    }
3268

    
3269
    if (rtp_c->state != HTTPSTATE_SEND_DATA &&
3270
        rtp_c->state != HTTPSTATE_WAIT_FEED) {
3271
        rtsp_reply_error(c, RTSP_STATUS_STATE);
3272
        return;
3273
    }
3274

    
3275
    rtp_c->state = HTTPSTATE_READY;
3276
    rtp_c->first_pts = AV_NOPTS_VALUE;
3277
    /* now everything is OK, so we can send the connection parameters */
3278
    rtsp_reply_header(c, RTSP_STATUS_OK);
3279
    /* session ID */
3280
    avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3281
    avio_printf(c->pb, "\r\n");
3282
}
3283

    
3284
static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3285
{
3286
    HTTPContext *rtp_c;
3287
    char session_id[32];
3288

    
3289
    rtp_c = find_rtp_session_with_url(url, h->session_id);
3290
    if (!rtp_c) {
3291
        rtsp_reply_error(c, RTSP_STATUS_SESSION);
3292
        return;
3293
    }
3294

    
3295
    av_strlcpy(session_id, rtp_c->session_id, sizeof(session_id));
3296

    
3297
    /* abort the session */
3298
    close_connection(rtp_c);
3299

    
3300
    /* now everything is OK, so we can send the connection parameters */
3301
    rtsp_reply_header(c, RTSP_STATUS_OK);
3302
    /* session ID */
3303
    avio_printf(c->pb, "Session: %s\r\n", session_id);
3304
    avio_printf(c->pb, "\r\n");
3305
}
3306

    
3307

    
3308
/********************************************************************/
3309
/* RTP handling */
3310

    
3311
static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
3312
                                       FFStream *stream, const char *session_id,
3313
                                       enum RTSPLowerTransport rtp_protocol)
3314
{
3315
    HTTPContext *c = NULL;
3316
    const char *proto_str;
3317

    
3318
    /* XXX: should output a warning page when coming
3319
       close to the connection limit */
3320
    if (nb_connections >= nb_max_connections)
3321
        goto fail;
3322

    
3323
    /* add a new connection */
3324
    c = av_mallocz(sizeof(HTTPContext));
3325
    if (!c)
3326
        goto fail;
3327

    
3328
    c->fd = -1;
3329
    c->poll_entry = NULL;
3330
    c->from_addr = *from_addr;
3331
    c->buffer_size = IOBUFFER_INIT_SIZE;
3332
    c->buffer = av_malloc(c->buffer_size);
3333
    if (!c->buffer)
3334
        goto fail;
3335
    nb_connections++;
3336
    c->stream = stream;
3337
    av_strlcpy(c->session_id, session_id, sizeof(c->session_id));
3338
    c->state = HTTPSTATE_READY;
3339
    c->is_packetized = 1;
3340
    c->rtp_protocol = rtp_protocol;
3341

    
3342
    /* protocol is shown in statistics */
3343
    switch(c->rtp_protocol) {
3344
    case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
3345
        proto_str = "MCAST";
3346
        break;
3347
    case RTSP_LOWER_TRANSPORT_UDP:
3348
        proto_str = "UDP";
3349
        break;
3350
    case RTSP_LOWER_TRANSPORT_TCP:
3351
        proto_str = "TCP";
3352
        break;
3353
    default:
3354
        proto_str = "???";
3355
        break;
3356
    }
3357
    av_strlcpy(c->protocol, "RTP/", sizeof(c->protocol));
3358
    av_strlcat(c->protocol, proto_str, sizeof(c->protocol));
3359

    
3360
    current_bandwidth += stream->bandwidth;
3361

    
3362
    c->next = first_http_ctx;
3363
    first_http_ctx = c;
3364
    return c;
3365

    
3366
 fail:
3367
    if (c) {
3368
        av_free(c->buffer);
3369
        av_free(c);
3370
    }
3371
    return NULL;
3372
}
3373

    
3374
/* add a new RTP stream in an RTP connection (used in RTSP SETUP
3375
   command). If RTP/TCP protocol is used, TCP connection 'rtsp_c' is
3376
   used. */
3377
static int rtp_new_av_stream(HTTPContext *c,
3378
                             int stream_index, struct sockaddr_in *dest_addr,
3379
                             HTTPContext *rtsp_c)
3380
{
3381
    AVFormatContext *ctx;
3382
    AVStream *st;
3383
    char *ipaddr;
3384
    URLContext *h = NULL;
3385
    uint8_t *dummy_buf;
3386
    int max_packet_size;
3387

    
3388
    /* now we can open the relevant output stream */
3389
    ctx = avformat_alloc_context();
3390
    if (!ctx)
3391
        return -1;
3392
    ctx->oformat = av_guess_format("rtp", NULL, NULL);
3393

    
3394
    st = av_mallocz(sizeof(AVStream));
3395
    if (!st)
3396
        goto fail;
3397
    ctx->nb_streams = 1;
3398
    ctx->streams[0] = st;
3399

    
3400
    if (!c->stream->feed ||
3401
        c->stream->feed == c->stream)
3402
        memcpy(st, c->stream->streams[stream_index], sizeof(AVStream));
3403
    else
3404
        memcpy(st,
3405
               c->stream->feed->streams[c->stream->feed_streams[stream_index]],
3406
               sizeof(AVStream));
3407
    st->priv_data = NULL;
3408

    
3409
    /* build destination RTP address */
3410
    ipaddr = inet_ntoa(dest_addr->sin_addr);
3411

    
3412
    switch(c->rtp_protocol) {
3413
    case RTSP_LOWER_TRANSPORT_UDP:
3414
    case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
3415
        /* RTP/UDP case */
3416

    
3417
        /* XXX: also pass as parameter to function ? */
3418
        if (c->stream->is_multicast) {
3419
            int ttl;
3420
            ttl = c->stream->multicast_ttl;
3421
            if (!ttl)
3422
                ttl = 16;
3423
            snprintf(ctx->filename, sizeof(ctx->filename),
3424
                     "rtp://%s:%d?multicast=1&ttl=%d",
3425
                     ipaddr, ntohs(dest_addr->sin_port), ttl);
3426
        } else {
3427
            snprintf(ctx->filename, sizeof(ctx->filename),
3428
                     "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
3429
        }
3430

    
3431
        if (url_open(&h, ctx->filename, AVIO_WRONLY) < 0)
3432
            goto fail;
3433
        c->rtp_handles[stream_index] = h;
3434
        max_packet_size = url_get_max_packet_size(h);
3435
        break;
3436
    case RTSP_LOWER_TRANSPORT_TCP:
3437
        /* RTP/TCP case */
3438
        c->rtsp_c = rtsp_c;
3439
        max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
3440
        break;
3441
    default:
3442
        goto fail;
3443
    }
3444

    
3445
    http_log("%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
3446
             ipaddr, ntohs(dest_addr->sin_port),
3447
             c->stream->filename, stream_index, c->protocol);
3448

    
3449
    /* normally, no packets should be output here, but the packet size may be checked */
3450
    if (ffio_open_dyn_packet_buf(&ctx->pb, max_packet_size) < 0) {
3451
        /* XXX: close stream */
3452
        goto fail;
3453
    }
3454
    av_set_parameters(ctx, NULL);
3455
    if (av_write_header(ctx) < 0) {
3456
    fail:
3457
        if (h)
3458
            url_close(h);
3459
        av_free(ctx);
3460
        return -1;
3461
    }
3462
    avio_close_dyn_buf(ctx->pb, &dummy_buf);
3463
    av_free(dummy_buf);
3464

    
3465
    c->rtp_ctx[stream_index] = ctx;
3466
    return 0;
3467
}
3468

    
3469
/********************************************************************/
3470
/* ffserver initialization */
3471

    
3472
static AVStream *add_av_stream1(FFStream *stream, AVCodecContext *codec, int copy)
3473
{
3474
    AVStream *fst;
3475

    
3476
    fst = av_mallocz(sizeof(AVStream));
3477
    if (!fst)
3478
        return NULL;
3479
    if (copy) {
3480
        fst->codec= avcodec_alloc_context();
3481
        memcpy(fst->codec, codec, sizeof(AVCodecContext));
3482
        if (codec->extradata_size) {
3483
            fst->codec->extradata = av_malloc(codec->extradata_size);
3484
            memcpy(fst->codec->extradata, codec->extradata,
3485
                codec->extradata_size);
3486
        }
3487
    } else {
3488
        /* live streams must use the actual feed's codec since it may be
3489
         * updated later to carry extradata needed by the streams.
3490
         */
3491
        fst->codec = codec;
3492
    }
3493
    fst->priv_data = av_mallocz(sizeof(FeedData));
3494
    fst->index = stream->nb_streams;
3495
    av_set_pts_info(fst, 33, 1, 90000);
3496
    fst->sample_aspect_ratio = codec->sample_aspect_ratio;
3497
    stream->streams[stream->nb_streams++] = fst;
3498
    return fst;
3499
}
3500

    
3501
/* return the stream number in the feed */
3502
static int add_av_stream(FFStream *feed, AVStream *st)
3503
{
3504
    AVStream *fst;
3505
    AVCodecContext *av, *av1;
3506
    int i;
3507

    
3508
    av = st->codec;
3509
    for(i=0;i<feed->nb_streams;i++) {
3510
        st = feed->streams[i];
3511
        av1 = st->codec;
3512
        if (av1->codec_id == av->codec_id &&
3513
            av1->codec_type == av->codec_type &&
3514
            av1->bit_rate == av->bit_rate) {
3515

    
3516
            switch(av->codec_type) {
3517
            case AVMEDIA_TYPE_AUDIO:
3518
                if (av1->channels == av->channels &&
3519
                    av1->sample_rate == av->sample_rate)
3520
                    goto found;
3521
                break;
3522
            case AVMEDIA_TYPE_VIDEO:
3523
                if (av1->width == av->width &&
3524
                    av1->height == av->height &&
3525
                    av1->time_base.den == av->time_base.den &&
3526
                    av1->time_base.num == av->time_base.num &&
3527
                    av1->gop_size == av->gop_size)
3528
                    goto found;
3529
                break;
3530
            default:
3531
                abort();
3532
            }
3533
        }
3534
    }
3535

    
3536
    fst = add_av_stream1(feed, av, 0);
3537
    if (!fst)
3538
        return -1;
3539
    return feed->nb_streams - 1;
3540
 found:
3541
    return i;
3542
}
3543

    
3544
static void remove_stream(FFStream *stream)
3545
{
3546
    FFStream **ps;
3547
    ps = &first_stream;
3548
    while (*ps != NULL) {
3549
        if (*ps == stream)
3550
            *ps = (*ps)->next;
3551
        else
3552
            ps = &(*ps)->next;
3553
    }
3554
}
3555

    
3556
/* specific mpeg4 handling : we extract the raw parameters */
3557
static void extract_mpeg4_header(AVFormatContext *infile)
3558
{
3559
    int mpeg4_count, i, size;
3560
    AVPacket pkt;
3561
    AVStream *st;
3562
    const uint8_t *p;
3563

    
3564
    mpeg4_count = 0;
3565
    for(i=0;i<infile->nb_streams;i++) {
3566
        st = infile->streams[i];
3567
        if (st->codec->codec_id == CODEC_ID_MPEG4 &&
3568
            st->codec->extradata_size == 0) {
3569
            mpeg4_count++;
3570
        }
3571
    }
3572
    if (!mpeg4_count)
3573
        return;
3574

    
3575
    printf("MPEG4 without extra data: trying to find header in %s\n", infile->filename);
3576
    while (mpeg4_count > 0) {
3577
        if (av_read_packet(infile, &pkt) < 0)
3578
            break;
3579
        st = infile->streams[pkt.stream_index];
3580
        if (st->codec->codec_id == CODEC_ID_MPEG4 &&
3581
            st->codec->extradata_size == 0) {
3582
            av_freep(&st->codec->extradata);
3583
            /* fill extradata with the header */
3584
            /* XXX: we make hard suppositions here ! */
3585
            p = pkt.data;
3586
            while (p < pkt.data + pkt.size - 4) {
3587
                /* stop when vop header is found */
3588
                if (p[0] == 0x00 && p[1] == 0x00 &&
3589
                    p[2] == 0x01 && p[3] == 0xb6) {
3590
                    size = p - pkt.data;
3591
                    //                    av_hex_dump_log(infile, AV_LOG_DEBUG, pkt.data, size);
3592
                    st->codec->extradata = av_malloc(size);
3593
                    st->codec->extradata_size = size;
3594
                    memcpy(st->codec->extradata, pkt.data, size);
3595
                    break;
3596
                }
3597
                p++;
3598
            }
3599
            mpeg4_count--;
3600
        }
3601
        av_free_packet(&pkt);
3602
    }
3603
}
3604

    
3605
/* compute the needed AVStream for each file */
3606
static void build_file_streams(void)
3607
{
3608
    FFStream *stream, *stream_next;
3609
    AVFormatContext *infile;
3610
    int i, ret;
3611

    
3612
    /* gather all streams */
3613
    for(stream = first_stream; stream != NULL; stream = stream_next) {
3614
        stream_next = stream->next;
3615
        if (stream->stream_type == STREAM_TYPE_LIVE &&
3616
            !stream->feed) {
3617
            /* the stream comes from a file */
3618
            /* try to open the file */
3619
            /* open stream */
3620
            stream->ap_in = av_mallocz(sizeof(AVFormatParameters));
3621
            if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
3622
                /* specific case : if transport stream output to RTP,
3623
                   we use a raw transport stream reader */
3624
                stream->ap_in->mpeg2ts_raw = 1;
3625
                stream->ap_in->mpeg2ts_compute_pcr = 1;
3626
            }
3627

    
3628
            http_log("Opening file '%s'\n", stream->feed_filename);
3629
            if ((ret = av_open_input_file(&infile, stream->feed_filename,
3630
                                          stream->ifmt, 0, stream->ap_in)) < 0) {
3631
                http_log("Could not open '%s': %d\n", stream->feed_filename, ret);
3632
                /* remove stream (no need to spend more time on it) */
3633
            fail:
3634
                remove_stream(stream);
3635
            } else {
3636
                /* find all the AVStreams inside and reference them in
3637
                   'stream' */
3638
                if (av_find_stream_info(infile) < 0) {
3639
                    http_log("Could not find codec parameters from '%s'\n",
3640
                             stream->feed_filename);
3641
                    av_close_input_file(infile);
3642
                    goto fail;
3643
                }
3644
                extract_mpeg4_header(infile);
3645

    
3646
                for(i=0;i<infile->nb_streams;i++)
3647
                    add_av_stream1(stream, infile->streams[i]->codec, 1);
3648

    
3649
                av_close_input_file(infile);
3650
            }
3651
        }
3652
    }
3653
}
3654

    
3655
/* compute the needed AVStream for each feed */
3656
static void build_feed_streams(void)
3657
{
3658
    FFStream *stream, *feed;
3659
    int i;
3660

    
3661
    /* gather all streams */
3662
    for(stream = first_stream; stream != NULL; stream = stream->next) {
3663
        feed = stream->feed;
3664
        if (feed) {
3665
            if (!stream->is_feed) {
3666
                /* we handle a stream coming from a feed */
3667
                for(i=0;i<stream->nb_streams;i++)
3668
                    stream->feed_streams[i] = add_av_stream(feed, stream->streams[i]);
3669
            }
3670
        }
3671
    }
3672

    
3673
    /* gather all streams */
3674
    for(stream = first_stream; stream != NULL; stream = stream->next) {
3675
        feed = stream->feed;
3676
        if (feed) {
3677
            if (stream->is_feed) {
3678
                for(i=0;i<stream->nb_streams;i++)
3679
                    stream->feed_streams[i] = i;
3680
            }
3681
        }
3682
    }
3683

    
3684
    /* create feed files if needed */
3685
    for(feed = first_feed; feed != NULL; feed = feed->next_feed) {
3686
        int fd;
3687

    
3688
        if (url_exist(feed->feed_filename)) {
3689
            /* See if it matches */
3690
            AVFormatContext *s;
3691
            int matches = 0;
3692

    
3693
            if (av_open_input_file(&s, feed->feed_filename, NULL, FFM_PACKET_SIZE, NULL) >= 0) {
3694
                /* Now see if it matches */
3695
                if (s->nb_streams == feed->nb_streams) {
3696
                    matches = 1;
3697
                    for(i=0;i<s->nb_streams;i++) {
3698
                        AVStream *sf, *ss;
3699
                        sf = feed->streams[i];
3700
                        ss = s->streams[i];
3701

    
3702
                        if (sf->index != ss->index ||
3703
                            sf->id != ss->id) {
3704
                            http_log("Index & Id do not match for stream %d (%s)\n",
3705
                                   i, feed->feed_filename);
3706
                            matches = 0;
3707
                        } else {
3708
                            AVCodecContext *ccf, *ccs;
3709

    
3710
                            ccf = sf->codec;
3711
                            ccs = ss->codec;
3712
#define CHECK_CODEC(x)  (ccf->x != ccs->x)
3713

    
3714
                            if (CHECK_CODEC(codec_id) || CHECK_CODEC(codec_type)) {
3715
                                http_log("Codecs do not match for stream %d\n", i);
3716
                                matches = 0;
3717
                            } else if (CHECK_CODEC(bit_rate) || CHECK_CODEC(flags)) {
3718
                                http_log("Codec bitrates do not match for stream %d\n", i);
3719
                                matches = 0;
3720
                            } else if (ccf->codec_type == AVMEDIA_TYPE_VIDEO) {
3721
                                if (CHECK_CODEC(time_base.den) ||
3722
                                    CHECK_CODEC(time_base.num) ||
3723
                                    CHECK_CODEC(width) ||
3724
                                    CHECK_CODEC(height)) {
3725
                                    http_log("Codec width, height and framerate do not match for stream %d\n", i);
3726
                                    matches = 0;
3727
                                }
3728
                            } else if (ccf->codec_type == AVMEDIA_TYPE_AUDIO) {
3729
                                if (CHECK_CODEC(sample_rate) ||
3730
                                    CHECK_CODEC(channels) ||
3731
                                    CHECK_CODEC(frame_size)) {
3732
                                    http_log("Codec sample_rate, channels, frame_size do not match for stream %d\n", i);
3733
                                    matches = 0;
3734
                                }
3735
                            } else {
3736
                                http_log("Unknown codec type\n");
3737
                                matches = 0;
3738
                            }
3739
                        }
3740
                        if (!matches)
3741
                            break;
3742
                    }
3743
                } else
3744
                    http_log("Deleting feed file '%s' as stream counts differ (%d != %d)\n",
3745
                        feed->feed_filename, s->nb_streams, feed->nb_streams);
3746

    
3747
                av_close_input_file(s);
3748
            } else
3749
                http_log("Deleting feed file '%s' as it appears to be corrupt\n",
3750
                        feed->feed_filename);
3751

    
3752
            if (!matches) {
3753
                if (feed->readonly) {
3754
                    http_log("Unable to delete feed file '%s' as it is marked readonly\n",
3755
                        feed->feed_filename);
3756
                    exit(1);
3757
                }
3758
                unlink(feed->feed_filename);
3759
            }
3760
        }
3761
        if (!url_exist(feed->feed_filename)) {
3762
            AVFormatContext s1 = {0}, *s = &s1;
3763

    
3764
            if (feed->readonly) {
3765
                http_log("Unable to create feed file '%s' as it is marked readonly\n",
3766
                    feed->feed_filename);
3767
                exit(1);
3768
            }
3769

    
3770
            /* only write the header of the ffm file */
3771
            if (avio_open(&s->pb, feed->feed_filename, AVIO_WRONLY) < 0) {
3772
                http_log("Could not open output feed file '%s'\n",
3773
                         feed->feed_filename);
3774
                exit(1);
3775
            }
3776
            s->oformat = feed->fmt;
3777
            s->nb_streams = feed->nb_streams;
3778
            for(i=0;i<s->nb_streams;i++) {
3779
                AVStream *st;
3780
                st = feed->streams[i];
3781
                s->streams[i] = st;
3782
            }
3783
            av_set_parameters(s, NULL);
3784
            if (av_write_header(s) < 0) {
3785
                http_log("Container doesn't supports the required parameters\n");
3786
                exit(1);
3787
            }
3788
            /* XXX: need better api */
3789
            av_freep(&s->priv_data);
3790
            avio_close(s->pb);
3791
        }
3792
        /* get feed size and write index */
3793
        fd = open(feed->feed_filename, O_RDONLY);
3794
        if (fd < 0) {
3795
            http_log("Could not open output feed file '%s'\n",
3796
                    feed->feed_filename);
3797
            exit(1);
3798
        }
3799

    
3800
        feed->feed_write_index = FFMAX(ffm_read_write_index(fd), FFM_PACKET_SIZE);
3801
        feed->feed_size = lseek(fd, 0, SEEK_END);
3802
        /* ensure that we do not wrap before the end of file */
3803
        if (feed->feed_max_size && feed->feed_max_size < feed->feed_size)
3804
            feed->feed_max_size = feed->feed_size;
3805

    
3806
        close(fd);
3807
    }
3808
}
3809

    
3810
/* compute the bandwidth used by each stream */
3811
static void compute_bandwidth(void)
3812
{
3813
    unsigned bandwidth;
3814
    int i;
3815
    FFStream *stream;
3816

    
3817
    for(stream = first_stream; stream != NULL; stream = stream->next) {
3818
        bandwidth = 0;
3819
        for(i=0;i<stream->nb_streams;i++) {
3820
            AVStream *st = stream->streams[i];
3821
            switch(st->codec->codec_type) {
3822
            case AVMEDIA_TYPE_AUDIO:
3823
            case AVMEDIA_TYPE_VIDEO:
3824
                bandwidth += st->codec->bit_rate;
3825
                break;
3826
            default:
3827
                break;
3828
            }
3829
        }
3830
        stream->bandwidth = (bandwidth + 999) / 1000;
3831
    }
3832
}
3833

    
3834
/* add a codec and set the default parameters */
3835
static void add_codec(FFStream *stream, AVCodecContext *av)
3836
{
3837
    AVStream *st;
3838

    
3839
    /* compute default parameters */
3840
    switch(av->codec_type) {
3841
    case AVMEDIA_TYPE_AUDIO:
3842
        if (av->bit_rate == 0)
3843
            av->bit_rate = 64000;
3844
        if (av->sample_rate == 0)
3845
            av->sample_rate = 22050;
3846
        if (av->channels == 0)
3847
            av->channels = 1;
3848
        break;
3849
    case AVMEDIA_TYPE_VIDEO:
3850
        if (av->bit_rate == 0)
3851
            av->bit_rate = 64000;
3852
        if (av->time_base.num == 0){
3853
            av->time_base.den = 5;
3854
            av->time_base.num = 1;
3855
        }
3856
        if (av->width == 0 || av->height == 0) {
3857
            av->width = 160;
3858
            av->height = 128;
3859
        }
3860
        /* Bitrate tolerance is less for streaming */
3861
        if (av->bit_rate_tolerance == 0)
3862
            av->bit_rate_tolerance = FFMAX(av->bit_rate / 4,
3863
                      (int64_t)av->bit_rate*av->time_base.num/av->time_base.den);
3864
        if (av->qmin == 0)
3865
            av->qmin = 3;
3866
        if (av->qmax == 0)
3867
            av->qmax = 31;
3868
        if (av->max_qdiff == 0)
3869
            av->max_qdiff = 3;
3870
        av->qcompress = 0.5;
3871
        av->qblur = 0.5;
3872

    
3873
        if (!av->nsse_weight)
3874
            av->nsse_weight = 8;
3875

    
3876
        av->frame_skip_cmp = FF_CMP_DCTMAX;
3877
        if (!av->me_method)
3878
            av->me_method = ME_EPZS;
3879
        av->rc_buffer_aggressivity = 1.0;
3880

    
3881
        if (!av->rc_eq)
3882
            av->rc_eq = "tex^qComp";
3883
        if (!av->i_quant_factor)
3884
            av->i_quant_factor = -0.8;
3885
        if (!av->b_quant_factor)
3886
            av->b_quant_factor = 1.25;
3887
        if (!av->b_quant_offset)
3888
            av->b_quant_offset = 1.25;
3889
        if (!av->rc_max_rate)
3890
            av->rc_max_rate = av->bit_rate * 2;
3891

    
3892
        if (av->rc_max_rate && !av->rc_buffer_size) {
3893
            av->rc_buffer_size = av->rc_max_rate;
3894
        }
3895

    
3896

    
3897
        break;
3898
    default:
3899
        abort();
3900
    }
3901

    
3902
    st = av_mallocz(sizeof(AVStream));
3903
    if (!st)
3904
        return;
3905
    st->codec = avcodec_alloc_context();
3906
    stream->streams[stream->nb_streams++] = st;
3907
    memcpy(st->codec, av, sizeof(AVCodecContext));
3908
}
3909

    
3910
static enum CodecID opt_audio_codec(const char *arg)
3911
{
3912
    AVCodec *p= avcodec_find_encoder_by_name(arg);
3913

    
3914
    if (p == NULL || p->type != AVMEDIA_TYPE_AUDIO)
3915
        return CODEC_ID_NONE;
3916

    
3917
    return p->id;
3918
}
3919

    
3920
static enum CodecID opt_video_codec(const char *arg)
3921
{
3922
    AVCodec *p= avcodec_find_encoder_by_name(arg);
3923

    
3924
    if (p == NULL || p->type != AVMEDIA_TYPE_VIDEO)
3925
        return CODEC_ID_NONE;
3926

    
3927
    return p->id;
3928
}
3929

    
3930
/* simplistic plugin support */
3931

    
3932
#if HAVE_DLOPEN
3933
static void load_module(const char *filename)
3934
{
3935
    void *dll;
3936
    void (*init_func)(void);
3937
    dll = dlopen(filename, RTLD_NOW);
3938
    if (!dll) {
3939
        fprintf(stderr, "Could not load module '%s' - %s\n",
3940
                filename, dlerror());
3941
        return;
3942
    }
3943

    
3944
    init_func = dlsym(dll, "ffserver_module_init");
3945
    if (!init_func) {
3946
        fprintf(stderr,
3947
                "%s: init function 'ffserver_module_init()' not found\n",
3948
                filename);
3949
        dlclose(dll);
3950
    }
3951

    
3952
    init_func();
3953
}
3954
#endif
3955

    
3956
static int ffserver_opt_default(const char *opt, const char *arg,
3957
                       AVCodecContext *avctx, int type)
3958
{
3959
    int ret = 0;
3960
    const AVOption *o = av_find_opt(avctx, opt, NULL, type, type);
3961
    if(o)
3962
        ret = av_set_string3(avctx, opt, arg, 1, NULL);
3963
    return ret;
3964
}
3965

    
3966
static int ffserver_opt_preset(const char *arg,
3967
                       AVCodecContext *avctx, int type,
3968
                       enum CodecID *audio_id, enum CodecID *video_id)
3969
{
3970
    FILE *f=NULL;
3971
    char filename[1000], tmp[1000], tmp2[1000], line[1000];
3972
    int ret = 0;
3973
    AVCodec *codec = avcodec_find_encoder(avctx->codec_id);
3974

    
3975
    if (!(f = get_preset_file(filename, sizeof(filename), arg, 0,
3976
                              codec ? codec->name : NULL))) {
3977
        fprintf(stderr, "File for preset '%s' not found\n", arg);
3978
        return 1;
3979
    }
3980

    
3981
    while(!feof(f)){
3982
        int e= fscanf(f, "%999[^\n]\n", line) - 1;
3983
        if(line[0] == '#' && !e)
3984
            continue;
3985
        e|= sscanf(line, "%999[^=]=%999[^\n]\n", tmp, tmp2) - 2;
3986
        if(e){
3987
            fprintf(stderr, "%s: Invalid syntax: '%s'\n", filename, line);
3988
            ret = 1;
3989
            break;
3990
        }
3991
        if(!strcmp(tmp, "acodec")){
3992
            *audio_id = opt_audio_codec(tmp2);
3993
        }else if(!strcmp(tmp, "vcodec")){
3994
            *video_id = opt_video_codec(tmp2);
3995
        }else if(!strcmp(tmp, "scodec")){
3996
            /* opt_subtitle_codec(tmp2); */
3997
        }else if(ffserver_opt_default(tmp, tmp2, avctx, type) < 0){
3998
            fprintf(stderr, "%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", filename, line, tmp, tmp2);
3999
            ret = 1;
4000
            break;
4001
        }
4002
    }
4003

    
4004
    fclose(f);
4005

    
4006
    return ret;
4007
}
4008

    
4009
static AVOutputFormat *ffserver_guess_format(const char *short_name, const char *filename,
4010
                                             const char *mime_type)
4011
{
4012
    AVOutputFormat *fmt = av_guess_format(short_name, filename, mime_type);
4013

    
4014
    if (fmt) {
4015
        AVOutputFormat *stream_fmt;
4016
        char stream_format_name[64];
4017

    
4018
        snprintf(stream_format_name, sizeof(stream_format_name), "%s_stream", fmt->name);
4019
        stream_fmt = av_guess_format(stream_format_name, NULL, NULL);
4020

    
4021
        if (stream_fmt)
4022
            fmt = stream_fmt;
4023
    }
4024

    
4025
    return fmt;
4026
}
4027

    
4028
static void report_config_error(const char *filename, int line_num, int *errors, const char *fmt, ...)
4029
{
4030
    va_list vl;
4031
    va_start(vl, fmt);
4032
    fprintf(stderr, "%s:%d: ", filename, line_num);
4033
    vfprintf(stderr, fmt, vl);
4034
    va_end(vl);
4035

    
4036
    (*errors)++;
4037
}
4038

    
4039
static int parse_ffconfig(const char *filename)
4040
{
4041
    FILE *f;
4042
    char line[1024];
4043
    char cmd[64];
4044
    char arg[1024];
4045
    const char *p;
4046
    int val, errors, line_num;
4047
    FFStream **last_stream, *stream, *redirect;
4048
    FFStream **last_feed, *feed, *s;
4049
    AVCodecContext audio_enc, video_enc;
4050
    enum CodecID audio_id, video_id;
4051

    
4052
    f = fopen(filename, "r");
4053
    if (!f) {
4054
        perror(filename);
4055
        return -1;
4056
    }
4057

    
4058
    errors = 0;
4059
    line_num = 0;
4060
    first_stream = NULL;
4061
    last_stream = &first_stream;
4062
    first_feed = NULL;
4063
    last_feed = &first_feed;
4064
    stream = NULL;
4065
    feed = NULL;
4066
    redirect = NULL;
4067
    audio_id = CODEC_ID_NONE;
4068
    video_id = CODEC_ID_NONE;
4069

    
4070
#define ERROR(...) report_config_error(filename, line_num, &errors, __VA_ARGS__)
4071
    for(;;) {
4072
        if (fgets(line, sizeof(line), f) == NULL)
4073
            break;
4074
        line_num++;
4075
        p = line;
4076
        while (isspace(*p))
4077
            p++;
4078
        if (*p == '\0' || *p == '#')
4079
            continue;
4080

    
4081
        get_arg(cmd, sizeof(cmd), &p);
4082

    
4083
        if (!strcasecmp(cmd, "Port")) {
4084
            get_arg(arg, sizeof(arg), &p);
4085
            val = atoi(arg);
4086
            if (val < 1 || val > 65536) {
4087
                ERROR("Invalid_port: %s\n", arg);
4088
            }
4089
            my_http_addr.sin_port = htons(val);
4090
        } else if (!strcasecmp(cmd, "BindAddress")) {
4091
            get_arg(arg, sizeof(arg), &p);
4092
            if (resolve_host(&my_http_addr.sin_addr, arg) != 0) {
4093
                ERROR("%s:%d: Invalid host/IP address: %s\n", arg);
4094
            }
4095
        } else if (!strcasecmp(cmd, "NoDaemon")) {
4096
            ffserver_daemon = 0;
4097
        } else if (!strcasecmp(cmd, "RTSPPort")) {
4098
            get_arg(arg, sizeof(arg), &p);
4099
            val = atoi(arg);
4100
            if (val < 1 || val > 65536) {
4101
                ERROR("%s:%d: Invalid port: %s\n", arg);
4102
            }
4103
            my_rtsp_addr.sin_port = htons(atoi(arg));
4104
        } else if (!strcasecmp(cmd, "RTSPBindAddress")) {
4105
            get_arg(arg, sizeof(arg), &p);
4106
            if (resolve_host(&my_rtsp_addr.sin_addr, arg) != 0) {
4107
                ERROR("Invalid host/IP address: %s\n", arg);
4108
            }
4109
        } else if (!strcasecmp(cmd, "MaxHTTPConnections")) {
4110
            get_arg(arg, sizeof(arg), &p);
4111
            val = atoi(arg);
4112
            if (val < 1 || val > 65536) {
4113
                ERROR("Invalid MaxHTTPConnections: %s\n", arg);
4114
            }
4115
            nb_max_http_connections = val;
4116
        } else if (!strcasecmp(cmd, "MaxClients")) {
4117
            get_arg(arg, sizeof(arg), &p);
4118
            val = atoi(arg);
4119
            if (val < 1 || val > nb_max_http_connections) {
4120
                ERROR("Invalid MaxClients: %s\n", arg);
4121
            } else {
4122
                nb_max_connections = val;
4123
            }
4124
        } else if (!strcasecmp(cmd, "MaxBandwidth")) {
4125
            int64_t llval;
4126
            get_arg(arg, sizeof(arg), &p);
4127
            llval = atoll(arg);
4128
            if (llval < 10 || llval > 10000000) {
4129
                ERROR("Invalid MaxBandwidth: %s\n", arg);
4130
            } else
4131
                max_bandwidth = llval;
4132
        } else if (!strcasecmp(cmd, "CustomLog")) {
4133
            if (!ffserver_debug)
4134
                get_arg(logfilename, sizeof(logfilename), &p);
4135
        } else if (!strcasecmp(cmd, "<Feed")) {
4136
            /*********************************************/
4137
            /* Feed related options */
4138
            char *q;
4139
            if (stream || feed) {
4140
                ERROR("Already in a tag\n");
4141
            } else {
4142
                feed = av_mallocz(sizeof(FFStream));
4143
                get_arg(feed->filename, sizeof(feed->filename), &p);
4144
                q = strrchr(feed->filename, '>');
4145
                if (*q)
4146
                    *q = '\0';
4147

    
4148
                for (s = first_feed; s; s = s->next) {
4149
                    if (!strcmp(feed->filename, s->filename)) {
4150
                        ERROR("Feed '%s' already registered\n", s->filename);
4151
                    }
4152
                }
4153

    
4154
                feed->fmt = av_guess_format("ffm", NULL, NULL);
4155
                /* defaut feed file */
4156
                snprintf(feed->feed_filename, sizeof(feed->feed_filename),
4157
                         "/tmp/%s.ffm", feed->filename);
4158
                feed->feed_max_size = 5 * 1024 * 1024;
4159
                feed->is_feed = 1;
4160
                feed->feed = feed; /* self feeding :-) */
4161

    
4162
                /* add in stream list */
4163
                *last_stream = feed;
4164
                last_stream = &feed->next;
4165
                /* add in feed list */
4166
                *last_feed = feed;
4167
                last_feed = &feed->next_feed;
4168
            }
4169
        } else if (!strcasecmp(cmd, "Launch")) {
4170
            if (feed) {
4171
                int i;
4172

    
4173
                feed->child_argv = av_mallocz(64 * sizeof(char *));
4174

    
4175
                for (i = 0; i < 62; i++) {
4176
                    get_arg(arg, sizeof(arg), &p);
4177
                    if (!arg[0])
4178
                        break;
4179

    
4180
                    feed->child_argv[i] = av_strdup(arg);
4181
                }
4182

    
4183
                feed->child_argv[i] = av_malloc(30 + strlen(feed->filename));
4184

    
4185
                snprintf(feed->child_argv[i], 30+strlen(feed->filename),
4186
                    "http://%s:%d/%s",
4187
                        (my_http_addr.sin_addr.s_addr == INADDR_ANY) ? "127.0.0.1" :
4188
                    inet_ntoa(my_http_addr.sin_addr),
4189
                    ntohs(my_http_addr.sin_port), feed->filename);
4190
            }
4191
        } else if (!strcasecmp(cmd, "ReadOnlyFile")) {
4192
            if (feed) {
4193
                get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
4194
                feed->readonly = 1;
4195
            } else if (stream) {
4196
                get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4197
            }
4198
        } else if (!strcasecmp(cmd, "File")) {
4199
            if (feed) {
4200
                get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
4201
            } else if (stream)
4202
                get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4203
        } else if (!strcasecmp(cmd, "Truncate")) {
4204
            if (feed) {
4205
                get_arg(arg, sizeof(arg), &p);
4206
                feed->truncate = strtod(arg, NULL);
4207
            }
4208
        } else if (!strcasecmp(cmd, "FileMaxSize")) {
4209
            if (feed) {
4210
                char *p1;
4211
                double fsize;
4212

    
4213
                get_arg(arg, sizeof(arg), &p);
4214
                p1 = arg;
4215
                fsize = strtod(p1, &p1);
4216
                switch(toupper(*p1)) {
4217
                case 'K':
4218
                    fsize *= 1024;
4219
                    break;
4220
                case 'M':
4221
                    fsize *= 1024 * 1024;
4222
                    break;
4223
                case 'G':
4224
                    fsize *= 1024 * 1024 * 1024;
4225
                    break;
4226
                }
4227
                feed->feed_max_size = (int64_t)fsize;
4228
                if (feed->feed_max_size < FFM_PACKET_SIZE*4) {
4229
                    ERROR("Feed max file size is too small, must be at least %d\n", FFM_PACKET_SIZE*4);
4230
                }
4231
            }
4232
        } else if (!strcasecmp(cmd, "</Feed>")) {
4233
            if (!feed) {
4234
                ERROR("No corresponding <Feed> for </Feed>\n");
4235
            }
4236
            feed = NULL;
4237
        } else if (!strcasecmp(cmd, "<Stream")) {
4238
            /*********************************************/
4239
            /* Stream related options */
4240
            char *q;
4241
            if (stream || feed) {
4242
                ERROR("Already in a tag\n");
4243
            } else {
4244
                FFStream *s;
4245
                stream = av_mallocz(sizeof(FFStream));
4246
                get_arg(stream->filename, sizeof(stream->filename), &p);
4247
                q = strrchr(stream->filename, '>');
4248
                if (*q)
4249
                    *q = '\0';
4250

    
4251
                for (s = first_stream; s; s = s->next) {
4252
                    if (!strcmp(stream->filename, s->filename)) {
4253
                        ERROR("Stream '%s' already registered\n", s->filename);
4254
                    }
4255
                }
4256

    
4257
                stream->fmt = ffserver_guess_format(NULL, stream->filename, NULL);
4258
                avcodec_get_context_defaults2(&video_enc, AVMEDIA_TYPE_VIDEO);
4259
                avcodec_get_context_defaults2(&audio_enc, AVMEDIA_TYPE_AUDIO);
4260
                audio_id = CODEC_ID_NONE;
4261
                video_id = CODEC_ID_NONE;
4262
                if (stream->fmt) {
4263
                    audio_id = stream->fmt->audio_codec;
4264
                    video_id = stream->fmt->video_codec;
4265
                }
4266

    
4267
                *last_stream = stream;
4268
                last_stream = &stream->next;
4269
            }
4270
        } else if (!strcasecmp(cmd, "Feed")) {
4271
            get_arg(arg, sizeof(arg), &p);
4272
            if (stream) {
4273
                FFStream *sfeed;
4274

    
4275
                sfeed = first_feed;
4276
                while (sfeed != NULL) {
4277
                    if (!strcmp(sfeed->filename, arg))
4278
                        break;
4279
                    sfeed = sfeed->next_feed;
4280
                }
4281
                if (!sfeed)
4282
                    ERROR("feed '%s' not defined\n", arg);
4283
                else
4284
                    stream->feed = sfeed;
4285
            }
4286
        } else if (!strcasecmp(cmd, "Format")) {
4287
            get_arg(arg, sizeof(arg), &p);
4288
            if (stream) {
4289
                if (!strcmp(arg, "status")) {
4290
                    stream->stream_type = STREAM_TYPE_STATUS;
4291
                    stream->fmt = NULL;
4292
                } else {
4293
                    stream->stream_type = STREAM_TYPE_LIVE;
4294
                    /* jpeg cannot be used here, so use single frame jpeg */
4295
                    if (!strcmp(arg, "jpeg"))
4296
                        strcpy(arg, "mjpeg");
4297
                    stream->fmt = ffserver_guess_format(arg, NULL, NULL);
4298
                    if (!stream->fmt) {
4299
                        ERROR("Unknown Format: %s\n", arg);
4300
                    }
4301
                }
4302
                if (stream->fmt) {
4303
                    audio_id = stream->fmt->audio_codec;
4304
                    video_id = stream->fmt->video_codec;
4305
                }
4306
            }
4307
        } else if (!strcasecmp(cmd, "InputFormat")) {
4308
            get_arg(arg, sizeof(arg), &p);
4309
            if (stream) {
4310
                stream->ifmt = av_find_input_format(arg);
4311
                if (!stream->ifmt) {
4312
                    ERROR("Unknown input format: %s\n", arg);
4313
                }
4314
            }
4315
        } else if (!strcasecmp(cmd, "FaviconURL")) {
4316
            if (stream && stream->stream_type == STREAM_TYPE_STATUS) {
4317
                get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4318
            } else {
4319
                ERROR("FaviconURL only permitted for status streams\n");
4320
            }
4321
        } else if (!strcasecmp(cmd, "Author")) {
4322
            if (stream)
4323
                get_arg(stream->author, sizeof(stream->author), &p);
4324
        } else if (!strcasecmp(cmd, "Comment")) {
4325
            if (stream)
4326
                get_arg(stream->comment, sizeof(stream->comment), &p);
4327
        } else if (!strcasecmp(cmd, "Copyright")) {
4328
            if (stream)
4329
                get_arg(stream->copyright, sizeof(stream->copyright), &p);
4330
        } else if (!strcasecmp(cmd, "Title")) {
4331
            if (stream)
4332
                get_arg(stream->title, sizeof(stream->title), &p);
4333
        } else if (!strcasecmp(cmd, "Preroll")) {
4334
            get_arg(arg, sizeof(arg), &p);
4335
            if (stream)
4336
                stream->prebuffer = atof(arg) * 1000;
4337
        } else if (!strcasecmp(cmd, "StartSendOnKey")) {
4338
            if (stream)
4339
                stream->send_on_key = 1;
4340
        } else if (!strcasecmp(cmd, "AudioCodec")) {
4341
            get_arg(arg, sizeof(arg), &p);
4342
            audio_id = opt_audio_codec(arg);
4343
            if (audio_id == CODEC_ID_NONE) {
4344
                ERROR("Unknown AudioCodec: %s\n", arg);
4345
            }
4346
        } else if (!strcasecmp(cmd, "VideoCodec")) {
4347
            get_arg(arg, sizeof(arg), &p);
4348
            video_id = opt_video_codec(arg);
4349
            if (video_id == CODEC_ID_NONE) {
4350
                ERROR("Unknown VideoCodec: %s\n", arg);
4351
            }
4352
        } else if (!strcasecmp(cmd, "MaxTime")) {
4353
            get_arg(arg, sizeof(arg), &p);
4354
            if (stream)
4355
                stream->max_time = atof(arg) * 1000;
4356
        } else if (!strcasecmp(cmd, "AudioBitRate")) {
4357
            get_arg(arg, sizeof(arg), &p);
4358
            if (stream)
4359
                audio_enc.bit_rate = lrintf(atof(arg) * 1000);
4360
        } else if (!strcasecmp(cmd, "AudioChannels")) {
4361
            get_arg(arg, sizeof(arg), &p);
4362
            if (stream)
4363
                audio_enc.channels = atoi(arg);
4364
        } else if (!strcasecmp(cmd, "AudioSampleRate")) {
4365
            get_arg(arg, sizeof(arg), &p);
4366
            if (stream)
4367
                audio_enc.sample_rate = atoi(arg);
4368
        } else if (!strcasecmp(cmd, "AudioQuality")) {
4369
            get_arg(arg, sizeof(arg), &p);
4370
            if (stream) {
4371
//                audio_enc.quality = atof(arg) * 1000;
4372
            }
4373
        } else if (!strcasecmp(cmd, "VideoBitRateRange")) {
4374
            if (stream) {
4375
                int minrate, maxrate;
4376

    
4377
                get_arg(arg, sizeof(arg), &p);
4378

    
4379
                if (sscanf(arg, "%d-%d", &minrate, &maxrate) == 2) {
4380
                    video_enc.rc_min_rate = minrate * 1000;
4381
                    video_enc.rc_max_rate = maxrate * 1000;
4382
                } else {
4383
                    ERROR("Incorrect format for VideoBitRateRange -- should be <min>-<max>: %s\n", arg);
4384
                }
4385
            }
4386
        } else if (!strcasecmp(cmd, "Debug")) {
4387
            if (stream) {
4388
                get_arg(arg, sizeof(arg), &p);
4389
                video_enc.debug = strtol(arg,0,0);
4390
            }
4391
        } else if (!strcasecmp(cmd, "Strict")) {
4392
            if (stream) {
4393
                get_arg(arg, sizeof(arg), &p);
4394
                video_enc.strict_std_compliance = atoi(arg);
4395
            }
4396
        } else if (!strcasecmp(cmd, "VideoBufferSize")) {
4397
            if (stream) {
4398
                get_arg(arg, sizeof(arg), &p);
4399
                video_enc.rc_buffer_size = atoi(arg) * 8*1024;
4400
            }
4401
        } else if (!strcasecmp(cmd, "VideoBitRateTolerance")) {
4402
            if (stream) {
4403
                get_arg(arg, sizeof(arg), &p);
4404
                video_enc.bit_rate_tolerance = atoi(arg) * 1000;
4405
            }
4406
        } else if (!strcasecmp(cmd, "VideoBitRate")) {
4407
            get_arg(arg, sizeof(arg), &p);
4408
            if (stream) {
4409
                video_enc.bit_rate = atoi(arg) * 1000;
4410
            }
4411
        } else if (!strcasecmp(cmd, "VideoSize")) {
4412
            get_arg(arg, sizeof(arg), &p);
4413
            if (stream) {
4414
                av_parse_video_size(&video_enc.width, &video_enc.height, arg);
4415
                if ((video_enc.width % 16) != 0 ||
4416
                    (video_enc.height % 16) != 0) {
4417
                    ERROR("Image size must be a multiple of 16\n");
4418
                }
4419
            }
4420
        } else if (!strcasecmp(cmd, "VideoFrameRate")) {
4421
            get_arg(arg, sizeof(arg), &p);
4422
            if (stream) {
4423
                AVRational frame_rate;
4424
                if (av_parse_video_rate(&frame_rate, arg) < 0) {
4425
                    ERROR("Incorrect frame rate: %s\n", arg);
4426
                } else {
4427
                    video_enc.time_base.num = frame_rate.den;
4428
                    video_enc.time_base.den = frame_rate.num;
4429
                }
4430
            }
4431
        } else if (!strcasecmp(cmd, "VideoGopSize")) {
4432
            get_arg(arg, sizeof(arg), &p);
4433
            if (stream)
4434
                video_enc.gop_size = atoi(arg);
4435
        } else if (!strcasecmp(cmd, "VideoIntraOnly")) {
4436
            if (stream)
4437
                video_enc.gop_size = 1;
4438
        } else if (!strcasecmp(cmd, "VideoHighQuality")) {
4439
            if (stream)
4440
                video_enc.mb_decision = FF_MB_DECISION_BITS;
4441
        } else if (!strcasecmp(cmd, "Video4MotionVector")) {
4442
            if (stream) {
4443
                video_enc.mb_decision = FF_MB_DECISION_BITS; //FIXME remove
4444
                video_enc.flags |= CODEC_FLAG_4MV;
4445
            }
4446
        } else if (!strcasecmp(cmd, "AVOptionVideo") ||
4447
                   !strcasecmp(cmd, "AVOptionAudio")) {
4448
            char arg2[1024];
4449
            AVCodecContext *avctx;
4450
            int type;
4451
            get_arg(arg, sizeof(arg), &p);
4452
            get_arg(arg2, sizeof(arg2), &p);
4453
            if (!strcasecmp(cmd, "AVOptionVideo")) {
4454
                avctx = &video_enc;
4455
                type = AV_OPT_FLAG_VIDEO_PARAM;
4456
            } else {
4457
                avctx = &audio_enc;
4458
                type = AV_OPT_FLAG_AUDIO_PARAM;
4459
            }
4460
            if (ffserver_opt_default(arg, arg2, avctx, type|AV_OPT_FLAG_ENCODING_PARAM)) {
4461
                ERROR("AVOption error: %s %s\n", arg, arg2);
4462
            }
4463
        } else if (!strcasecmp(cmd, "AVPresetVideo") ||
4464
                   !strcasecmp(cmd, "AVPresetAudio")) {
4465
            AVCodecContext *avctx;
4466
            int type;
4467
            get_arg(arg, sizeof(arg), &p);
4468
            if (!strcasecmp(cmd, "AVPresetVideo")) {
4469
                avctx = &video_enc;
4470
                video_enc.codec_id = video_id;
4471
                type = AV_OPT_FLAG_VIDEO_PARAM;
4472
            } else {
4473
                avctx = &audio_enc;
4474
                audio_enc.codec_id = audio_id;
4475
                type = AV_OPT_FLAG_AUDIO_PARAM;
4476
            }
4477
            if (ffserver_opt_preset(arg, avctx, type|AV_OPT_FLAG_ENCODING_PARAM, &audio_id, &video_id)) {
4478
                ERROR("AVPreset error: %s\n", arg);
4479
            }
4480
        } else if (!strcasecmp(cmd, "VideoTag")) {
4481
            get_arg(arg, sizeof(arg), &p);
4482
            if ((strlen(arg) == 4) && stream)
4483
                video_enc.codec_tag = MKTAG(arg[0], arg[1], arg[2], arg[3]);
4484
        } else if (!strcasecmp(cmd, "BitExact")) {
4485
            if (stream)
4486
                video_enc.flags |= CODEC_FLAG_BITEXACT;
4487
        } else if (!strcasecmp(cmd, "DctFastint")) {
4488
            if (stream)
4489
                video_enc.dct_algo  = FF_DCT_FASTINT;
4490
        } else if (!strcasecmp(cmd, "IdctSimple")) {
4491
            if (stream)
4492
                video_enc.idct_algo = FF_IDCT_SIMPLE;
4493
        } else if (!strcasecmp(cmd, "Qscale")) {
4494
            get_arg(arg, sizeof(arg), &p);
4495
            if (stream) {
4496
                video_enc.flags |= CODEC_FLAG_QSCALE;
4497
                video_enc.global_quality = FF_QP2LAMBDA * atoi(arg);
4498
            }
4499
        } else if (!strcasecmp(cmd, "VideoQDiff")) {
4500
            get_arg(arg, sizeof(arg), &p);
4501
            if (stream) {
4502
                video_enc.max_qdiff = atoi(arg);
4503
                if (video_enc.max_qdiff < 1 || video_enc.max_qdiff > 31) {
4504
                    ERROR("VideoQDiff out of range\n");
4505
                }
4506
            }
4507
        } else if (!strcasecmp(cmd, "VideoQMax")) {
4508
            get_arg(arg, sizeof(arg), &p);
4509
            if (stream) {
4510
                video_enc.qmax = atoi(arg);
4511
                if (video_enc.qmax < 1 || video_enc.qmax > 31) {
4512
                    ERROR("VideoQMax out of range\n");
4513
                }
4514
            }
4515
        } else if (!strcasecmp(cmd, "VideoQMin")) {
4516
            get_arg(arg, sizeof(arg), &p);
4517
            if (stream) {
4518
                video_enc.qmin = atoi(arg);
4519
                if (video_enc.qmin < 1 || video_enc.qmin > 31) {
4520
                    ERROR("VideoQMin out of range\n");
4521
                }
4522
            }
4523
        } else if (!strcasecmp(cmd, "LumaElim")) {
4524
            get_arg(arg, sizeof(arg), &p);
4525
            if (stream)
4526
                video_enc.luma_elim_threshold = atoi(arg);
4527
        } else if (!strcasecmp(cmd, "ChromaElim")) {
4528
            get_arg(arg, sizeof(arg), &p);
4529
            if (stream)
4530
                video_enc.chroma_elim_threshold = atoi(arg);
4531
        } else if (!strcasecmp(cmd, "LumiMask")) {
4532
            get_arg(arg, sizeof(arg), &p);
4533
            if (stream)
4534
                video_enc.lumi_masking = atof(arg);
4535
        } else if (!strcasecmp(cmd, "DarkMask")) {
4536
            get_arg(arg, sizeof(arg), &p);
4537
            if (stream)
4538
                video_enc.dark_masking = atof(arg);
4539
        } else if (!strcasecmp(cmd, "NoVideo")) {
4540
            video_id = CODEC_ID_NONE;
4541
        } else if (!strcasecmp(cmd, "NoAudio")) {
4542
            audio_id = CODEC_ID_NONE;
4543
        } else if (!strcasecmp(cmd, "ACL")) {
4544
            parse_acl_row(stream, feed, NULL, p, filename, line_num);
4545
        } else if (!strcasecmp(cmd, "DynamicACL")) {
4546
            if (stream) {
4547
                get_arg(stream->dynamic_acl, sizeof(stream->dynamic_acl), &p);
4548
            }
4549
        } else if (!strcasecmp(cmd, "RTSPOption")) {
4550
            get_arg(arg, sizeof(arg), &p);
4551
            if (stream) {
4552
                av_freep(&stream->rtsp_option);
4553
                stream->rtsp_option = av_strdup(arg);
4554
            }
4555
        } else if (!strcasecmp(cmd, "MulticastAddress")) {
4556
            get_arg(arg, sizeof(arg), &p);
4557
            if (stream) {
4558
                if (resolve_host(&stream->multicast_ip, arg) != 0) {
4559
                    ERROR("Invalid host/IP address: %s\n", arg);
4560
                }
4561
                stream->is_multicast = 1;
4562
                stream->loop = 1; /* default is looping */
4563
            }
4564
        } else if (!strcasecmp(cmd, "MulticastPort")) {
4565
            get_arg(arg, sizeof(arg), &p);
4566
            if (stream)
4567
                stream->multicast_port = atoi(arg);
4568
        } else if (!strcasecmp(cmd, "MulticastTTL")) {
4569
            get_arg(arg, sizeof(arg), &p);
4570
            if (stream)
4571
                stream->multicast_ttl = atoi(arg);
4572
        } else if (!strcasecmp(cmd, "NoLoop")) {
4573
            if (stream)
4574
                stream->loop = 0;
4575
        } else if (!strcasecmp(cmd, "</Stream>")) {
4576
            if (!stream) {
4577
                ERROR("No corresponding <Stream> for </Stream>\n");
4578
            } else {
4579
                if (stream->feed && stream->fmt && strcmp(stream->fmt->name, "ffm") != 0) {
4580
                    if (audio_id != CODEC_ID_NONE) {
4581
                        audio_enc.codec_type = AVMEDIA_TYPE_AUDIO;
4582
                        audio_enc.codec_id = audio_id;
4583
                        add_codec(stream, &audio_enc);
4584
                    }
4585
                    if (video_id != CODEC_ID_NONE) {
4586
                        video_enc.codec_type = AVMEDIA_TYPE_VIDEO;
4587
                        video_enc.codec_id = video_id;
4588
                        add_codec(stream, &video_enc);
4589
                    }
4590
                }
4591
                stream = NULL;
4592
            }
4593
        } else if (!strcasecmp(cmd, "<Redirect")) {
4594
            /*********************************************/
4595
            char *q;
4596
            if (stream || feed || redirect) {
4597
                ERROR("Already in a tag\n");
4598
            } else {
4599
                redirect = av_mallocz(sizeof(FFStream));
4600
                *last_stream = redirect;
4601
                last_stream = &redirect->next;
4602

    
4603
                get_arg(redirect->filename, sizeof(redirect->filename), &p);
4604
                q = strrchr(redirect->filename, '>');
4605
                if (*q)
4606
                    *q = '\0';
4607
                redirect->stream_type = STREAM_TYPE_REDIRECT;
4608
            }
4609
        } else if (!strcasecmp(cmd, "URL")) {
4610
            if (redirect)
4611
                get_arg(redirect->feed_filename, sizeof(redirect->feed_filename), &p);
4612
        } else if (!strcasecmp(cmd, "</Redirect>")) {
4613
            if (!redirect) {
4614
                ERROR("No corresponding <Redirect> for </Redirect>\n");
4615
            } else {
4616
                if (!redirect->feed_filename[0]) {
4617
                    ERROR("No URL found for <Redirect>\n");
4618
                }
4619
                redirect = NULL;
4620
            }
4621
        } else if (!strcasecmp(cmd, "LoadModule")) {
4622
            get_arg(arg, sizeof(arg), &p);
4623
#if HAVE_DLOPEN
4624
            load_module(arg);
4625
#else
4626
            ERROR("Module support not compiled into this version: '%s'\n", arg);
4627
#endif
4628
        } else {
4629
            ERROR("Incorrect keyword: '%s'\n", cmd);
4630
        }
4631
    }
4632
#undef ERROR
4633

    
4634
    fclose(f);
4635
    if (errors)
4636
        return -1;
4637
    else
4638
        return 0;
4639
}
4640

    
4641
static void handle_child_exit(int sig)
4642
{
4643
    pid_t pid;
4644
    int status;
4645

    
4646
    while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
4647
        FFStream *feed;
4648

    
4649
        for (feed = first_feed; feed; feed = feed->next) {
4650
            if (feed->pid == pid) {
4651
                int uptime = time(0) - feed->pid_start;
4652

    
4653
                feed->pid = 0;
4654
                fprintf(stderr, "%s: Pid %d exited with status %d after %d seconds\n", feed->filename, pid, status, uptime);
4655

    
4656
                if (uptime < 30)
4657
                    /* Turn off any more restarts */
4658
                    feed->child_argv = 0;
4659
            }
4660
        }
4661
    }
4662

    
4663
    need_to_start_children = 1;
4664
}
4665

    
4666
static void opt_debug(void)
4667
{
4668
    ffserver_debug = 1;
4669
    ffserver_daemon = 0;
4670
    logfilename[0] = '-';
4671
}
4672

    
4673
static void show_help(void)
4674
{
4675
    printf("usage: ffserver [options]\n"
4676
           "Hyper fast multi format Audio/Video streaming server\n");
4677
    printf("\n");
4678
    show_help_options(options, "Main options:\n", 0, 0);
4679
}
4680

    
4681
static const OptionDef options[] = {
4682
#include "cmdutils_common_opts.h"
4683
    { "n", OPT_BOOL, {(void *)&no_launch }, "enable no-launch mode" },
4684
    { "d", 0, {(void*)opt_debug}, "enable debug mode" },
4685
    { "f", HAS_ARG | OPT_STRING, {(void*)&config_filename }, "use configfile instead of /etc/ffserver.conf", "configfile" },
4686
    { NULL },
4687
};
4688

    
4689
int main(int argc, char **argv)
4690
{
4691
    struct sigaction sigact;
4692

    
4693
    av_register_all();
4694

    
4695
    show_banner();
4696

    
4697
    my_program_name = argv[0];
4698
    my_program_dir = getcwd(0, 0);
4699
    ffserver_daemon = 1;
4700

    
4701
    parse_options(argc, argv, options, NULL);
4702

    
4703
    unsetenv("http_proxy");             /* Kill the http_proxy */
4704

    
4705
    av_lfg_init(&random_state, av_get_random_seed());
4706

    
4707
    memset(&sigact, 0, sizeof(sigact));
4708
    sigact.sa_handler = handle_child_exit;
4709
    sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
4710
    sigaction(SIGCHLD, &sigact, 0);
4711

    
4712
    if (parse_ffconfig(config_filename) < 0) {
4713
        fprintf(stderr, "Incorrect config file - exiting.\n");
4714
        exit(1);
4715
    }
4716

    
4717
    /* open log file if needed */
4718
    if (logfilename[0] != '\0') {
4719
        if (!strcmp(logfilename, "-"))
4720
            logfile = stdout;
4721
        else
4722
            logfile = fopen(logfilename,