Statistics
| Branch: | Revision:

ffmpeg / ffserver.c @ 403ee835

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/network.h"
33
#include "libavformat/os_support.h"
34
#include "libavformat/rtpdec.h"
35
#include "libavformat/rtsp.h"
36
// XXX for ffio_open_dyn_packet_buffer, to be removed
37
#include "libavformat/avio_internal.h"
38
#include "libavutil/avstring.h"
39
#include "libavutil/lfg.h"
40
#include "libavutil/random_seed.h"
41
#include "libavutil/parseutils.h"
42
#include "libavcodec/opt.h"
43
#include <stdarg.h>
44
#include <unistd.h>
45
#include <fcntl.h>
46
#include <sys/ioctl.h>
47
#if HAVE_POLL_H
48
#include <poll.h>
49
#endif
50
#include <errno.h>
51
#include <sys/time.h>
52
#include <time.h>
53
#include <sys/wait.h>
54
#include <signal.h>
55
#if HAVE_DLFCN_H
56
#include <dlfcn.h>
57
#endif
58

    
59
#include "cmdutils.h"
60

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

    
64
static const OptionDef options[];
65

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

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

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

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

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

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

    
101
#define IOBUFFER_INIT_SIZE 8192
102

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

    
107
#define SYNC_TIMEOUT (10 * 1000)
108

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
320
static AVLFG random_state;
321

    
322
static FILE *logfile = NULL;
323

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

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

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

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

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

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

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

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

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

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

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

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

    
444

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

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

    
454
            feed->pid = fork();
455

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

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

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

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

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

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

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

    
497
                signal(SIGPIPE, SIG_DFL);
498

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

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

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

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

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

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

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

    
536
    return server_fd;
537
}
538

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
626
    start_children(first_feed);
627

    
628
    start_multicast();
629

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

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

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

    
702
        cur_time = av_gettime() / 1000;
703

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

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

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

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

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

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

    
764

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

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

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

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

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

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

    
802
    start_wait_request(c, is_rtsp);
803

    
804
    return;
805

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

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

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

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

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

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

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

    
869
    ctx = &c->fmt_ctx;
870

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1093
                q += 20;
1094

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

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

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

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

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

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

    
1119
        p++;
1120
    }
1121

    
1122
    return 0;
1123
}
1124

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

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

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

    
1140
        /* Potential stream */
1141

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

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

    
1159
    return best;
1160
}
1161

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

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

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

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

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

    
1197
    return action_required;
1198
}
1199

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1326

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

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

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

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

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

    
1363

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

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

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

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

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

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

    
1398

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

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

    
1405
        ret = validate_acl_list(acl, c);
1406

    
1407
        free_acl_list(acl);
1408
    }
1409

    
1410
    return ret;
1411
}
1412

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1508
        p++;
1509
    }
1510

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

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

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

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

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

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

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

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

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

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

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

    
1619
            p++;
1620
        }
1621

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

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

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

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

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

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

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

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

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

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

    
1727
    stream->conns_served++;
1728

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

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

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

    
1750
                p++;
1751
            }
1752

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

    
1756
                logline += 17;
1757

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

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

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

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

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

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

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

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

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

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

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

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

    
1824
        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);
1825
    }
1826
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-Type: %s\r\n", mime_type);
1827
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
1828

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

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

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

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

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

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

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

    
1890
    avio_printf(pb, "<html><head><title>%s Status</title>\n", program_name);
1891
    if (c->stream->feed_filename[0])
1892
        avio_printf(pb, "<link rel=\"shortcut icon\" href=\"%s\">\n", c->stream->feed_filename);
1893
    avio_printf(pb, "</head>\n<body>");
1894
    avio_printf(pb, "<h1>%s Status</h1>\n", program_name);
1895
    /* format status */
1896
    avio_printf(pb, "<h2>Available Streams</h2>\n");
1897
    avio_printf(pb, "<table cellspacing=0 cellpadding=4>\n");
1898
    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");
1899
    stream = first_stream;
1900
    while (stream != NULL) {
1901
        char sfilename[1024];
1902
        char *eosf;
1903

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

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

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

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

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

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

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

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

    
2020
                avio_printf(pb, "<p>");
2021
            }
2022
            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");
2023

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

    
2030
                parameters[0] = 0;
2031

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

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

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

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

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

    
2063
    avio_printf(pb, "<table>\n");
2064
    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");
2065
    c1 = first_http_ctx;
2066
    i = 0;
2067
    while (c1 != NULL) {
2068
        int bitrate;
2069
        int j;
2070

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2222

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

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

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

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

    
2258
        c->got_key_frame = 0;
2259

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2769
/********************************************************************/
2770
/* RTSP handling */
2771

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2970
    return strlen(*pbuffer);
2971
}
2972

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
3191

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

    
3195

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

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

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

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

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

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

    
3249
    rtp_c->state = HTTPSTATE_SEND_DATA;
3250

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

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

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

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

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

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

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

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

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

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

    
3306

    
3307
/********************************************************************/
3308
/* RTP handling */
3309

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

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

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

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

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

    
3359
    current_bandwidth += stream->bandwidth;
3360

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

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

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

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

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

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

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

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

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

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

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

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

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

    
3468
/********************************************************************/
3469
/* ffserver initialization */
3470

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
3805
        close(fd);
3806
    }
3807
}
3808

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

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

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

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

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

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

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

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

    
3895

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

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

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

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

    
3916
    return p->id;
3917
}
3918

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

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

    
3926
    return p->id;
3927
}
3928

    
3929
/* simplistic plugin support */
3930

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

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

    
3951
    init_func();
3952
}
3953
#endif
3954

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

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

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

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

    
4003
    fclose(f);
4004

    
4005
    return ret;
4006
}
4007

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

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

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

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

    
4024
    return fmt;
4025
}
4026

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

    
4035
    (*errors)++;
4036
}
4037

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
4662
    need_to_start_children = 1;
4663
}
4664

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

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

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

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

    
4692
    av_register_all();
4693

    
4694
    show_banner();
4695

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

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

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

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

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

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

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