]> git.sesse.net Git - ffmpeg/blob - avserver.c
APIChanges: add entry for av_read_packet deprecation
[ffmpeg] / avserver.c
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 #include "config.h"
23 #if !HAVE_CLOSESOCKET
24 #define closesocket close
25 #endif
26 #include <string.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include "libavformat/avformat.h"
30 // FIXME those are internal headers, avserver _really_ shouldn't use them
31 #include "libavformat/ffm.h"
32 #include "libavformat/network.h"
33 #include "libavformat/os_support.h"
34 #include "libavformat/rtpdec.h"
35 #include "libavformat/rtsp.h"
36 #include "libavformat/avio_internal.h"
37 #include "libavformat/internal.h"
38 #include "libavformat/url.h"
39
40 #include "libavutil/avstring.h"
41 #include "libavutil/lfg.h"
42 #include "libavutil/dict.h"
43 #include "libavutil/intreadwrite.h"
44 #include "libavutil/mathematics.h"
45 #include "libavutil/random_seed.h"
46 #include "libavutil/parseutils.h"
47 #include "libavutil/opt.h"
48 #include "libavutil/time.h"
49
50 #include <stdarg.h>
51 #include <unistd.h>
52 #include <fcntl.h>
53 #include <sys/ioctl.h>
54 #if HAVE_POLL_H
55 #include <poll.h>
56 #endif
57 #include <errno.h>
58 #include <time.h>
59 #include <sys/wait.h>
60 #include <signal.h>
61 #if HAVE_DLFCN_H
62 #include <dlfcn.h>
63 #endif
64
65 #include "cmdutils.h"
66
67 const char program_name[] = "avserver";
68 const int program_birth_year = 2000;
69
70 static const OptionDef options[];
71
72 enum HTTPState {
73     HTTPSTATE_WAIT_REQUEST,
74     HTTPSTATE_SEND_HEADER,
75     HTTPSTATE_SEND_DATA_HEADER,
76     HTTPSTATE_SEND_DATA,          /* sending TCP or UDP data */
77     HTTPSTATE_SEND_DATA_TRAILER,
78     HTTPSTATE_RECEIVE_DATA,
79     HTTPSTATE_WAIT_FEED,          /* wait for data from the feed */
80     HTTPSTATE_READY,
81
82     RTSPSTATE_WAIT_REQUEST,
83     RTSPSTATE_SEND_REPLY,
84     RTSPSTATE_SEND_PACKET,
85 };
86
87 static const char *http_state[] = {
88     "HTTP_WAIT_REQUEST",
89     "HTTP_SEND_HEADER",
90
91     "SEND_DATA_HEADER",
92     "SEND_DATA",
93     "SEND_DATA_TRAILER",
94     "RECEIVE_DATA",
95     "WAIT_FEED",
96     "READY",
97
98     "RTSP_WAIT_REQUEST",
99     "RTSP_SEND_REPLY",
100     "RTSP_SEND_PACKET",
101 };
102
103 #define MAX_STREAMS 20
104
105 #define IOBUFFER_INIT_SIZE 8192
106
107 /* timeouts are in ms */
108 #define HTTP_REQUEST_TIMEOUT (15 * 1000)
109 #define RTSP_REQUEST_TIMEOUT (3600 * 24 * 1000)
110
111 #define SYNC_TIMEOUT (10 * 1000)
112
113 typedef struct RTSPActionServerSetup {
114     uint32_t ipaddr;
115     char transport_option[512];
116 } RTSPActionServerSetup;
117
118 typedef struct {
119     int64_t count1, count2;
120     int64_t time1, time2;
121 } DataRateData;
122
123 /* context associated with one connection */
124 typedef struct HTTPContext {
125     enum HTTPState state;
126     int fd; /* socket file descriptor */
127     struct sockaddr_in from_addr; /* origin */
128     struct pollfd *poll_entry; /* used when polling */
129     int64_t timeout;
130     uint8_t *buffer_ptr, *buffer_end;
131     int http_error;
132     int post;
133     int chunked_encoding;
134     int chunk_size;               /* 0 if it needs to be read */
135     struct HTTPContext *next;
136     int got_key_frame; /* stream 0 => 1, stream 1 => 2, stream 2=> 4 */
137     int64_t data_count;
138     /* feed input */
139     int feed_fd;
140     /* input format handling */
141     AVFormatContext *fmt_in;
142     int64_t start_time;            /* In milliseconds - this wraps fairly often */
143     int64_t first_pts;            /* initial pts value */
144     int64_t cur_pts;             /* current pts value from the stream in us */
145     int64_t cur_frame_duration;  /* duration of the current frame in us */
146     int cur_frame_bytes;       /* output frame size, needed to compute
147                                   the time at which we send each
148                                   packet */
149     int pts_stream_index;        /* stream we choose as clock reference */
150     int64_t cur_clock;           /* current clock reference value in us */
151     /* output format handling */
152     struct FFStream *stream;
153     /* -1 is invalid stream */
154     int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
155     int switch_feed_streams[MAX_STREAMS]; /* index of streams in the feed */
156     int switch_pending;
157     AVFormatContext fmt_ctx; /* instance of FFStream for one user */
158     int last_packet_sent; /* true if last data packet was sent */
159     int suppress_log;
160     DataRateData datarate;
161     int wmp_client_id;
162     char protocol[16];
163     char method[16];
164     char url[128];
165     int buffer_size;
166     uint8_t *buffer;
167     int is_packetized; /* if true, the stream is packetized */
168     int packet_stream_index; /* current stream for output in state machine */
169
170     /* RTSP state specific */
171     uint8_t *pb_buffer; /* XXX: use that in all the code */
172     AVIOContext *pb;
173     int seq; /* RTSP sequence number */
174
175     /* RTP state specific */
176     enum RTSPLowerTransport rtp_protocol;
177     char session_id[32]; /* session id */
178     AVFormatContext *rtp_ctx[MAX_STREAMS];
179
180     /* RTP/UDP specific */
181     URLContext *rtp_handles[MAX_STREAMS];
182
183     /* RTP/TCP specific */
184     struct HTTPContext *rtsp_c;
185     uint8_t *packet_buffer, *packet_buffer_ptr, *packet_buffer_end;
186 } HTTPContext;
187
188 /* each generated stream is described here */
189 enum StreamType {
190     STREAM_TYPE_LIVE,
191     STREAM_TYPE_STATUS,
192     STREAM_TYPE_REDIRECT,
193 };
194
195 enum IPAddressAction {
196     IP_ALLOW = 1,
197     IP_DENY,
198 };
199
200 typedef struct IPAddressACL {
201     struct IPAddressACL *next;
202     enum IPAddressAction action;
203     /* These are in host order */
204     struct in_addr first;
205     struct in_addr last;
206 } IPAddressACL;
207
208 /* description of each stream of the avserver.conf file */
209 typedef struct FFStream {
210     enum StreamType stream_type;
211     char filename[1024];     /* stream filename */
212     struct FFStream *feed;   /* feed we are using (can be null if
213                                 coming from file) */
214     AVDictionary *in_opts;   /* input parameters */
215     AVInputFormat *ifmt;       /* if non NULL, force input format */
216     AVOutputFormat *fmt;
217     IPAddressACL *acl;
218     char dynamic_acl[1024];
219     int nb_streams;
220     int prebuffer;      /* Number of millseconds early to start */
221     int64_t max_time;      /* Number of milliseconds to run */
222     int send_on_key;
223     AVStream *streams[MAX_STREAMS];
224     int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
225     char feed_filename[1024]; /* file name of the feed storage, or
226                                  input file name for a stream */
227     char author[512];
228     char title[512];
229     char copyright[512];
230     char comment[512];
231     pid_t pid;  /* of avconv process */
232     time_t pid_start;  /* of avconv process */
233     char **child_argv;
234     struct FFStream *next;
235     unsigned bandwidth; /* bandwidth, in kbits/s */
236     /* RTSP options */
237     char *rtsp_option;
238     /* multicast specific */
239     int is_multicast;
240     struct in_addr multicast_ip;
241     int multicast_port; /* first port used for multicast */
242     int multicast_ttl;
243     int loop; /* if true, send the stream in loops (only meaningful if file) */
244
245     /* feed specific */
246     int feed_opened;     /* true if someone is writing to the feed */
247     int is_feed;         /* true if it is a feed */
248     int readonly;        /* True if writing is prohibited to the file */
249     int truncate;        /* True if feeder connection truncate the feed file */
250     int conns_served;
251     int64_t bytes_served;
252     int64_t feed_max_size;      /* maximum storage size, zero means unlimited */
253     int64_t feed_write_index;   /* current write position in feed (it wraps around) */
254     int64_t feed_size;          /* current size of feed */
255     struct FFStream *next_feed;
256 } FFStream;
257
258 typedef struct FeedData {
259     long long data_count;
260     float avg_frame_size;   /* frame size averaged over last frames with exponential mean */
261 } FeedData;
262
263 static struct sockaddr_in my_http_addr;
264 static struct sockaddr_in my_rtsp_addr;
265
266 static char logfilename[1024];
267 static HTTPContext *first_http_ctx;
268 static FFStream *first_feed;   /* contains only feeds */
269 static FFStream *first_stream; /* contains all streams, including feeds */
270
271 static void new_connection(int server_fd, int is_rtsp);
272 static void close_connection(HTTPContext *c);
273
274 /* HTTP handling */
275 static int handle_connection(HTTPContext *c);
276 static int http_parse_request(HTTPContext *c);
277 static int http_send_data(HTTPContext *c);
278 static void compute_status(HTTPContext *c);
279 static int open_input_stream(HTTPContext *c, const char *info);
280 static int http_start_receive_data(HTTPContext *c);
281 static int http_receive_data(HTTPContext *c);
282
283 /* RTSP handling */
284 static int rtsp_parse_request(HTTPContext *c);
285 static void rtsp_cmd_describe(HTTPContext *c, const char *url);
286 static void rtsp_cmd_options(HTTPContext *c, const char *url);
287 static void rtsp_cmd_setup(HTTPContext *c, const char *url, RTSPMessageHeader *h);
288 static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h);
289 static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h);
290 static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPMessageHeader *h);
291
292 /* SDP handling */
293 static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
294                                    struct in_addr my_ip);
295
296 /* RTP handling */
297 static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
298                                        FFStream *stream, const char *session_id,
299                                        enum RTSPLowerTransport rtp_protocol);
300 static int rtp_new_av_stream(HTTPContext *c,
301                              int stream_index, struct sockaddr_in *dest_addr,
302                              HTTPContext *rtsp_c);
303
304 static const char *my_program_name;
305
306 static const char *config_filename = "/etc/avserver.conf";
307
308 static int avserver_debug;
309 static int no_launch;
310 static int need_to_start_children;
311
312 /* maximum number of simultaneous HTTP connections */
313 static unsigned int nb_max_http_connections = 2000;
314 static unsigned int nb_max_connections = 5;
315 static unsigned int nb_connections;
316
317 static uint64_t max_bandwidth = 1000;
318 static uint64_t current_bandwidth;
319
320 static int64_t cur_time;           // Making this global saves on passing it around everywhere
321
322 static AVLFG random_state;
323
324 static FILE *logfile = NULL;
325
326 static int64_t ffm_read_write_index(int fd)
327 {
328     uint8_t buf[8];
329
330     lseek(fd, 8, SEEK_SET);
331     if (read(fd, buf, 8) != 8)
332         return AVERROR(EIO);
333     return AV_RB64(buf);
334 }
335
336 static int ffm_write_write_index(int fd, int64_t pos)
337 {
338     uint8_t buf[8];
339     int i;
340
341     for(i=0;i<8;i++)
342         buf[i] = (pos >> (56 - i * 8)) & 0xff;
343     lseek(fd, 8, SEEK_SET);
344     if (write(fd, buf, 8) != 8)
345         return AVERROR(EIO);
346     return 8;
347 }
348
349 static void ffm_set_write_index(AVFormatContext *s, int64_t pos,
350                                 int64_t file_size)
351 {
352     FFMContext *ffm = s->priv_data;
353     ffm->write_index = pos;
354     ffm->file_size = file_size;
355 }
356
357 /* FIXME: make avserver work with IPv6 */
358 /* resolve host with also IP address parsing */
359 static int resolve_host(struct in_addr *sin_addr, const char *hostname)
360 {
361
362     if (!ff_inet_aton(hostname, sin_addr)) {
363 #if HAVE_GETADDRINFO
364         struct addrinfo *ai, *cur;
365         struct addrinfo hints = { 0 };
366         hints.ai_family = AF_INET;
367         if (getaddrinfo(hostname, NULL, &hints, &ai))
368             return -1;
369         /* getaddrinfo returns a linked list of addrinfo structs.
370          * Even if we set ai_family = AF_INET above, make sure
371          * that the returned one actually is of the correct type. */
372         for (cur = ai; cur; cur = cur->ai_next) {
373             if (cur->ai_family == AF_INET) {
374                 *sin_addr = ((struct sockaddr_in *)cur->ai_addr)->sin_addr;
375                 freeaddrinfo(ai);
376                 return 0;
377             }
378         }
379         freeaddrinfo(ai);
380         return -1;
381 #else
382         struct hostent *hp;
383         hp = gethostbyname(hostname);
384         if (!hp)
385             return -1;
386         memcpy(sin_addr, hp->h_addr_list[0], sizeof(struct in_addr));
387 #endif
388     }
389     return 0;
390 }
391
392 static char *ctime1(char *buf2)
393 {
394     time_t ti;
395     char *p;
396
397     ti = time(NULL);
398     p = ctime(&ti);
399     strcpy(buf2, p);
400     p = buf2 + strlen(p) - 1;
401     if (*p == '\n')
402         *p = '\0';
403     return buf2;
404 }
405
406 static void http_vlog(const char *fmt, va_list vargs)
407 {
408     static int print_prefix = 1;
409     if (logfile) {
410         if (print_prefix) {
411             char buf[32];
412             ctime1(buf);
413             fprintf(logfile, "%s ", buf);
414         }
415         print_prefix = strstr(fmt, "\n") != NULL;
416         vfprintf(logfile, fmt, vargs);
417         fflush(logfile);
418     }
419 }
420
421 #ifdef __GNUC__
422 __attribute__ ((format (printf, 1, 2)))
423 #endif
424 static void http_log(const char *fmt, ...)
425 {
426     va_list vargs;
427     va_start(vargs, fmt);
428     http_vlog(fmt, vargs);
429     va_end(vargs);
430 }
431
432 static void http_av_log(void *ptr, int level, const char *fmt, va_list vargs)
433 {
434     static int print_prefix = 1;
435     AVClass *avc = ptr ? *(AVClass**)ptr : NULL;
436     if (level > av_log_get_level())
437         return;
438     if (print_prefix && avc)
439         http_log("[%s @ %p]", avc->item_name(ptr), ptr);
440     print_prefix = strstr(fmt, "\n") != NULL;
441     http_vlog(fmt, vargs);
442 }
443
444 static void log_connection(HTTPContext *c)
445 {
446     if (c->suppress_log)
447         return;
448
449     http_log("%s - - [%s] \"%s %s\" %d %"PRId64"\n",
450              inet_ntoa(c->from_addr.sin_addr), c->method, c->url,
451              c->protocol, (c->http_error ? c->http_error : 200), c->data_count);
452 }
453
454 static void update_datarate(DataRateData *drd, int64_t count)
455 {
456     if (!drd->time1 && !drd->count1) {
457         drd->time1 = drd->time2 = cur_time;
458         drd->count1 = drd->count2 = count;
459     } else if (cur_time - drd->time2 > 5000) {
460         drd->time1 = drd->time2;
461         drd->count1 = drd->count2;
462         drd->time2 = cur_time;
463         drd->count2 = count;
464     }
465 }
466
467 /* In bytes per second */
468 static int compute_datarate(DataRateData *drd, int64_t count)
469 {
470     if (cur_time == drd->time1)
471         return 0;
472
473     return ((count - drd->count1) * 1000) / (cur_time - drd->time1);
474 }
475
476
477 static void start_children(FFStream *feed)
478 {
479     if (no_launch)
480         return;
481
482     for (; feed; feed = feed->next) {
483         if (feed->child_argv && !feed->pid) {
484             feed->pid_start = time(0);
485
486             feed->pid = fork();
487
488             if (feed->pid < 0) {
489                 http_log("Unable to create children\n");
490                 exit(1);
491             }
492             if (!feed->pid) {
493                 /* In child */
494                 char pathname[1024];
495                 char *slash;
496                 int i;
497
498                 av_strlcpy(pathname, my_program_name, sizeof(pathname));
499
500                 slash = strrchr(pathname, '/');
501                 if (!slash)
502                     slash = pathname;
503                 else
504                     slash++;
505                 strcpy(slash, "avconv");
506
507                 http_log("Launch command line: ");
508                 http_log("%s ", pathname);
509                 for (i = 1; feed->child_argv[i] && feed->child_argv[i][0]; i++)
510                     http_log("%s ", feed->child_argv[i]);
511                 http_log("\n");
512
513                 for (i = 3; i < 256; i++)
514                     close(i);
515
516                 if (!avserver_debug) {
517                     if (!freopen("/dev/null", "r", stdin))
518                         http_log("failed to redirect STDIN to /dev/null\n;");
519                     if (!freopen("/dev/null", "w", stdout))
520                         http_log("failed to redirect STDOUT to /dev/null\n;");
521                     if (!freopen("/dev/null", "w", stderr))
522                         http_log("failed to redirect STDERR to /dev/null\n;");
523                 }
524
525                 signal(SIGPIPE, SIG_DFL);
526
527                 execvp(pathname, feed->child_argv);
528
529                 _exit(1);
530             }
531         }
532     }
533 }
534
535 /* open a listening socket */
536 static int socket_open_listen(struct sockaddr_in *my_addr)
537 {
538     int server_fd, tmp;
539
540     server_fd = socket(AF_INET,SOCK_STREAM,0);
541     if (server_fd < 0) {
542         perror ("socket");
543         return -1;
544     }
545
546     tmp = 1;
547     setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp));
548
549     my_addr->sin_family = AF_INET;
550     if (bind (server_fd, (struct sockaddr *) my_addr, sizeof (*my_addr)) < 0) {
551         char bindmsg[32];
552         snprintf(bindmsg, sizeof(bindmsg), "bind(port %d)", ntohs(my_addr->sin_port));
553         perror (bindmsg);
554         closesocket(server_fd);
555         return -1;
556     }
557
558     if (listen (server_fd, 5) < 0) {
559         perror ("listen");
560         closesocket(server_fd);
561         return -1;
562     }
563     ff_socket_nonblock(server_fd, 1);
564
565     return server_fd;
566 }
567
568 /* start all multicast streams */
569 static void start_multicast(void)
570 {
571     FFStream *stream;
572     char session_id[32];
573     HTTPContext *rtp_c;
574     struct sockaddr_in dest_addr;
575     int default_port, stream_index;
576
577     default_port = 6000;
578     for(stream = first_stream; stream != NULL; stream = stream->next) {
579         if (stream->is_multicast) {
580             /* open the RTP connection */
581             snprintf(session_id, sizeof(session_id), "%08x%08x",
582                      av_lfg_get(&random_state), av_lfg_get(&random_state));
583
584             /* choose a port if none given */
585             if (stream->multicast_port == 0) {
586                 stream->multicast_port = default_port;
587                 default_port += 100;
588             }
589
590             dest_addr.sin_family = AF_INET;
591             dest_addr.sin_addr = stream->multicast_ip;
592             dest_addr.sin_port = htons(stream->multicast_port);
593
594             rtp_c = rtp_new_connection(&dest_addr, stream, session_id,
595                                        RTSP_LOWER_TRANSPORT_UDP_MULTICAST);
596             if (!rtp_c)
597                 continue;
598
599             if (open_input_stream(rtp_c, "") < 0) {
600                 http_log("Could not open input stream for stream '%s'\n",
601                          stream->filename);
602                 continue;
603             }
604
605             /* open each RTP stream */
606             for(stream_index = 0; stream_index < stream->nb_streams;
607                 stream_index++) {
608                 dest_addr.sin_port = htons(stream->multicast_port +
609                                            2 * stream_index);
610                 if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, NULL) < 0) {
611                     http_log("Could not open output stream '%s/streamid=%d'\n",
612                              stream->filename, stream_index);
613                     exit(1);
614                 }
615             }
616
617             /* change state to send data */
618             rtp_c->state = HTTPSTATE_SEND_DATA;
619         }
620     }
621 }
622
623 /* main loop of the http server */
624 static int http_server(void)
625 {
626     int server_fd = 0, rtsp_server_fd = 0;
627     int ret, delay, delay1;
628     struct pollfd *poll_table, *poll_entry;
629     HTTPContext *c, *c_next;
630
631     if(!(poll_table = av_mallocz((nb_max_http_connections + 2)*sizeof(*poll_table)))) {
632         http_log("Impossible to allocate a poll table handling %d connections.\n", nb_max_http_connections);
633         return -1;
634     }
635
636     if (my_http_addr.sin_port) {
637         server_fd = socket_open_listen(&my_http_addr);
638         if (server_fd < 0)
639             return -1;
640     }
641
642     if (my_rtsp_addr.sin_port) {
643         rtsp_server_fd = socket_open_listen(&my_rtsp_addr);
644         if (rtsp_server_fd < 0)
645             return -1;
646     }
647
648     if (!rtsp_server_fd && !server_fd) {
649         http_log("HTTP and RTSP disabled.\n");
650         return -1;
651     }
652
653     http_log("AVserver started.\n");
654
655     start_children(first_feed);
656
657     start_multicast();
658
659     for(;;) {
660         poll_entry = poll_table;
661         if (server_fd) {
662             poll_entry->fd = server_fd;
663             poll_entry->events = POLLIN;
664             poll_entry++;
665         }
666         if (rtsp_server_fd) {
667             poll_entry->fd = rtsp_server_fd;
668             poll_entry->events = POLLIN;
669             poll_entry++;
670         }
671
672         /* wait for events on each HTTP handle */
673         c = first_http_ctx;
674         delay = 1000;
675         while (c != NULL) {
676             int fd;
677             fd = c->fd;
678             switch(c->state) {
679             case HTTPSTATE_SEND_HEADER:
680             case RTSPSTATE_SEND_REPLY:
681             case RTSPSTATE_SEND_PACKET:
682                 c->poll_entry = poll_entry;
683                 poll_entry->fd = fd;
684                 poll_entry->events = POLLOUT;
685                 poll_entry++;
686                 break;
687             case HTTPSTATE_SEND_DATA_HEADER:
688             case HTTPSTATE_SEND_DATA:
689             case HTTPSTATE_SEND_DATA_TRAILER:
690                 if (!c->is_packetized) {
691                     /* for TCP, we output as much as we can (may need to put a limit) */
692                     c->poll_entry = poll_entry;
693                     poll_entry->fd = fd;
694                     poll_entry->events = POLLOUT;
695                     poll_entry++;
696                 } else {
697                     /* when avserver is doing the timing, we work by
698                        looking at which packet need to be sent every
699                        10 ms */
700                     delay1 = 10; /* one tick wait XXX: 10 ms assumed */
701                     if (delay1 < delay)
702                         delay = delay1;
703                 }
704                 break;
705             case HTTPSTATE_WAIT_REQUEST:
706             case HTTPSTATE_RECEIVE_DATA:
707             case HTTPSTATE_WAIT_FEED:
708             case RTSPSTATE_WAIT_REQUEST:
709                 /* need to catch errors */
710                 c->poll_entry = poll_entry;
711                 poll_entry->fd = fd;
712                 poll_entry->events = POLLIN;/* Maybe this will work */
713                 poll_entry++;
714                 break;
715             default:
716                 c->poll_entry = NULL;
717                 break;
718             }
719             c = c->next;
720         }
721
722         /* wait for an event on one connection. We poll at least every
723            second to handle timeouts */
724         do {
725             ret = poll(poll_table, poll_entry - poll_table, delay);
726             if (ret < 0 && ff_neterrno() != AVERROR(EAGAIN) &&
727                 ff_neterrno() != AVERROR(EINTR))
728                 return -1;
729         } while (ret < 0);
730
731         cur_time = av_gettime() / 1000;
732
733         if (need_to_start_children) {
734             need_to_start_children = 0;
735             start_children(first_feed);
736         }
737
738         /* now handle the events */
739         for(c = first_http_ctx; c != NULL; c = c_next) {
740             c_next = c->next;
741             if (handle_connection(c) < 0) {
742                 /* close and free the connection */
743                 log_connection(c);
744                 close_connection(c);
745             }
746         }
747
748         poll_entry = poll_table;
749         if (server_fd) {
750             /* new HTTP connection request ? */
751             if (poll_entry->revents & POLLIN)
752                 new_connection(server_fd, 0);
753             poll_entry++;
754         }
755         if (rtsp_server_fd) {
756             /* new RTSP connection request ? */
757             if (poll_entry->revents & POLLIN)
758                 new_connection(rtsp_server_fd, 1);
759         }
760     }
761 }
762
763 /* start waiting for a new HTTP/RTSP request */
764 static void start_wait_request(HTTPContext *c, int is_rtsp)
765 {
766     c->buffer_ptr = c->buffer;
767     c->buffer_end = c->buffer + c->buffer_size - 1; /* leave room for '\0' */
768
769     if (is_rtsp) {
770         c->timeout = cur_time + RTSP_REQUEST_TIMEOUT;
771         c->state = RTSPSTATE_WAIT_REQUEST;
772     } else {
773         c->timeout = cur_time + HTTP_REQUEST_TIMEOUT;
774         c->state = HTTPSTATE_WAIT_REQUEST;
775     }
776 }
777
778 static void http_send_too_busy_reply(int fd)
779 {
780     char buffer[300];
781     int len = snprintf(buffer, sizeof(buffer),
782                        "HTTP/1.0 503 Server too busy\r\n"
783                        "Content-type: text/html\r\n"
784                        "\r\n"
785                        "<html><head><title>Too busy</title></head><body>\r\n"
786                        "<p>The server is too busy to serve your request at this time.</p>\r\n"
787                        "<p>The number of current connections is %d, and this exceeds the limit of %d.</p>\r\n"
788                        "</body></html>\r\n",
789                        nb_connections, nb_max_connections);
790     send(fd, buffer, len, 0);
791 }
792
793
794 static void new_connection(int server_fd, int is_rtsp)
795 {
796     struct sockaddr_in from_addr;
797     socklen_t len;
798     int fd;
799     HTTPContext *c = NULL;
800
801     len = sizeof(from_addr);
802     fd = accept(server_fd, (struct sockaddr *)&from_addr,
803                 &len);
804     if (fd < 0) {
805         http_log("error during accept %s\n", strerror(errno));
806         return;
807     }
808     ff_socket_nonblock(fd, 1);
809
810     if (nb_connections >= nb_max_connections) {
811         http_send_too_busy_reply(fd);
812         goto fail;
813     }
814
815     /* add a new connection */
816     c = av_mallocz(sizeof(HTTPContext));
817     if (!c)
818         goto fail;
819
820     c->fd = fd;
821     c->poll_entry = NULL;
822     c->from_addr = from_addr;
823     c->buffer_size = IOBUFFER_INIT_SIZE;
824     c->buffer = av_malloc(c->buffer_size);
825     if (!c->buffer)
826         goto fail;
827
828     c->next = first_http_ctx;
829     first_http_ctx = c;
830     nb_connections++;
831
832     start_wait_request(c, is_rtsp);
833
834     return;
835
836  fail:
837     if (c) {
838         av_free(c->buffer);
839         av_free(c);
840     }
841     closesocket(fd);
842 }
843
844 static void close_connection(HTTPContext *c)
845 {
846     HTTPContext **cp, *c1;
847     int i, nb_streams;
848     AVFormatContext *ctx;
849     URLContext *h;
850     AVStream *st;
851
852     /* remove connection from list */
853     cp = &first_http_ctx;
854     while ((*cp) != NULL) {
855         c1 = *cp;
856         if (c1 == c)
857             *cp = c->next;
858         else
859             cp = &c1->next;
860     }
861
862     /* remove references, if any (XXX: do it faster) */
863     for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
864         if (c1->rtsp_c == c)
865             c1->rtsp_c = NULL;
866     }
867
868     /* remove connection associated resources */
869     if (c->fd >= 0)
870         closesocket(c->fd);
871     if (c->fmt_in) {
872         /* close each frame parser */
873         for(i=0;i<c->fmt_in->nb_streams;i++) {
874             st = c->fmt_in->streams[i];
875             if (st->codec->codec)
876                 avcodec_close(st->codec);
877         }
878         avformat_close_input(&c->fmt_in);
879     }
880
881     /* free RTP output streams if any */
882     nb_streams = 0;
883     if (c->stream)
884         nb_streams = c->stream->nb_streams;
885
886     for(i=0;i<nb_streams;i++) {
887         ctx = c->rtp_ctx[i];
888         if (ctx) {
889             av_write_trailer(ctx);
890             av_dict_free(&ctx->metadata);
891             av_free(ctx->streams[0]);
892             av_free(ctx);
893         }
894         h = c->rtp_handles[i];
895         if (h)
896             ffurl_close(h);
897     }
898
899     ctx = &c->fmt_ctx;
900
901     if (!c->last_packet_sent && c->state == HTTPSTATE_SEND_DATA_TRAILER) {
902         if (ctx->oformat) {
903             /* prepare header */
904             if (avio_open_dyn_buf(&ctx->pb) >= 0) {
905                 av_write_trailer(ctx);
906                 av_freep(&c->pb_buffer);
907                 avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
908             }
909         }
910     }
911
912     for(i=0; i<ctx->nb_streams; i++)
913         av_free(ctx->streams[i]);
914
915     if (c->stream && !c->post && c->stream->stream_type == STREAM_TYPE_LIVE)
916         current_bandwidth -= c->stream->bandwidth;
917
918     /* signal that there is no feed if we are the feeder socket */
919     if (c->state == HTTPSTATE_RECEIVE_DATA && c->stream) {
920         c->stream->feed_opened = 0;
921         close(c->feed_fd);
922     }
923
924     av_freep(&c->pb_buffer);
925     av_freep(&c->packet_buffer);
926     av_free(c->buffer);
927     av_free(c);
928     nb_connections--;
929 }
930
931 static int handle_connection(HTTPContext *c)
932 {
933     int len, ret;
934
935     switch(c->state) {
936     case HTTPSTATE_WAIT_REQUEST:
937     case RTSPSTATE_WAIT_REQUEST:
938         /* timeout ? */
939         if ((c->timeout - cur_time) < 0)
940             return -1;
941         if (c->poll_entry->revents & (POLLERR | POLLHUP))
942             return -1;
943
944         /* no need to read if no events */
945         if (!(c->poll_entry->revents & POLLIN))
946             return 0;
947         /* read the data */
948     read_loop:
949         len = recv(c->fd, c->buffer_ptr, 1, 0);
950         if (len < 0) {
951             if (ff_neterrno() != AVERROR(EAGAIN) &&
952                 ff_neterrno() != AVERROR(EINTR))
953                 return -1;
954         } else if (len == 0) {
955             return -1;
956         } else {
957             /* search for end of request. */
958             uint8_t *ptr;
959             c->buffer_ptr += len;
960             ptr = c->buffer_ptr;
961             if ((ptr >= c->buffer + 2 && !memcmp(ptr-2, "\n\n", 2)) ||
962                 (ptr >= c->buffer + 4 && !memcmp(ptr-4, "\r\n\r\n", 4))) {
963                 /* request found : parse it and reply */
964                 if (c->state == HTTPSTATE_WAIT_REQUEST) {
965                     ret = http_parse_request(c);
966                 } else {
967                     ret = rtsp_parse_request(c);
968                 }
969                 if (ret < 0)
970                     return -1;
971             } else if (ptr >= c->buffer_end) {
972                 /* request too long: cannot do anything */
973                 return -1;
974             } else goto read_loop;
975         }
976         break;
977
978     case HTTPSTATE_SEND_HEADER:
979         if (c->poll_entry->revents & (POLLERR | POLLHUP))
980             return -1;
981
982         /* no need to write if no events */
983         if (!(c->poll_entry->revents & POLLOUT))
984             return 0;
985         len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
986         if (len < 0) {
987             if (ff_neterrno() != AVERROR(EAGAIN) &&
988                 ff_neterrno() != AVERROR(EINTR)) {
989                 /* error : close connection */
990                 av_freep(&c->pb_buffer);
991                 return -1;
992             }
993         } else {
994             c->buffer_ptr += len;
995             if (c->stream)
996                 c->stream->bytes_served += len;
997             c->data_count += len;
998             if (c->buffer_ptr >= c->buffer_end) {
999                 av_freep(&c->pb_buffer);
1000                 /* if error, exit */
1001                 if (c->http_error)
1002                     return -1;
1003                 /* all the buffer was sent : synchronize to the incoming stream */
1004                 c->state = HTTPSTATE_SEND_DATA_HEADER;
1005                 c->buffer_ptr = c->buffer_end = c->buffer;
1006             }
1007         }
1008         break;
1009
1010     case HTTPSTATE_SEND_DATA:
1011     case HTTPSTATE_SEND_DATA_HEADER:
1012     case HTTPSTATE_SEND_DATA_TRAILER:
1013         /* for packetized output, we consider we can always write (the
1014            input streams sets the speed). It may be better to verify
1015            that we do not rely too much on the kernel queues */
1016         if (!c->is_packetized) {
1017             if (c->poll_entry->revents & (POLLERR | POLLHUP))
1018                 return -1;
1019
1020             /* no need to read if no events */
1021             if (!(c->poll_entry->revents & POLLOUT))
1022                 return 0;
1023         }
1024         if (http_send_data(c) < 0)
1025             return -1;
1026         /* close connection if trailer sent */
1027         if (c->state == HTTPSTATE_SEND_DATA_TRAILER)
1028             return -1;
1029         break;
1030     case HTTPSTATE_RECEIVE_DATA:
1031         /* no need to read if no events */
1032         if (c->poll_entry->revents & (POLLERR | POLLHUP))
1033             return -1;
1034         if (!(c->poll_entry->revents & POLLIN))
1035             return 0;
1036         if (http_receive_data(c) < 0)
1037             return -1;
1038         break;
1039     case HTTPSTATE_WAIT_FEED:
1040         /* no need to read if no events */
1041         if (c->poll_entry->revents & (POLLIN | POLLERR | POLLHUP))
1042             return -1;
1043
1044         /* nothing to do, we'll be waken up by incoming feed packets */
1045         break;
1046
1047     case RTSPSTATE_SEND_REPLY:
1048         if (c->poll_entry->revents & (POLLERR | POLLHUP)) {
1049             av_freep(&c->pb_buffer);
1050             return -1;
1051         }
1052         /* no need to write if no events */
1053         if (!(c->poll_entry->revents & POLLOUT))
1054             return 0;
1055         len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
1056         if (len < 0) {
1057             if (ff_neterrno() != AVERROR(EAGAIN) &&
1058                 ff_neterrno() != AVERROR(EINTR)) {
1059                 /* error : close connection */
1060                 av_freep(&c->pb_buffer);
1061                 return -1;
1062             }
1063         } else {
1064             c->buffer_ptr += len;
1065             c->data_count += len;
1066             if (c->buffer_ptr >= c->buffer_end) {
1067                 /* all the buffer was sent : wait for a new request */
1068                 av_freep(&c->pb_buffer);
1069                 start_wait_request(c, 1);
1070             }
1071         }
1072         break;
1073     case RTSPSTATE_SEND_PACKET:
1074         if (c->poll_entry->revents & (POLLERR | POLLHUP)) {
1075             av_freep(&c->packet_buffer);
1076             return -1;
1077         }
1078         /* no need to write if no events */
1079         if (!(c->poll_entry->revents & POLLOUT))
1080             return 0;
1081         len = send(c->fd, c->packet_buffer_ptr,
1082                     c->packet_buffer_end - c->packet_buffer_ptr, 0);
1083         if (len < 0) {
1084             if (ff_neterrno() != AVERROR(EAGAIN) &&
1085                 ff_neterrno() != AVERROR(EINTR)) {
1086                 /* error : close connection */
1087                 av_freep(&c->packet_buffer);
1088                 return -1;
1089             }
1090         } else {
1091             c->packet_buffer_ptr += len;
1092             if (c->packet_buffer_ptr >= c->packet_buffer_end) {
1093                 /* all the buffer was sent : wait for a new request */
1094                 av_freep(&c->packet_buffer);
1095                 c->state = RTSPSTATE_WAIT_REQUEST;
1096             }
1097         }
1098         break;
1099     case HTTPSTATE_READY:
1100         /* nothing to do */
1101         break;
1102     default:
1103         return -1;
1104     }
1105     return 0;
1106 }
1107
1108 static int extract_rates(char *rates, int ratelen, const char *request)
1109 {
1110     const char *p;
1111
1112     for (p = request; *p && *p != '\r' && *p != '\n'; ) {
1113         if (av_strncasecmp(p, "Pragma:", 7) == 0) {
1114             const char *q = p + 7;
1115
1116             while (*q && *q != '\n' && isspace(*q))
1117                 q++;
1118
1119             if (av_strncasecmp(q, "stream-switch-entry=", 20) == 0) {
1120                 int stream_no;
1121                 int rate_no;
1122
1123                 q += 20;
1124
1125                 memset(rates, 0xff, ratelen);
1126
1127                 while (1) {
1128                     while (*q && *q != '\n' && *q != ':')
1129                         q++;
1130
1131                     if (sscanf(q, ":%d:%d", &stream_no, &rate_no) != 2)
1132                         break;
1133
1134                     stream_no--;
1135                     if (stream_no < ratelen && stream_no >= 0)
1136                         rates[stream_no] = rate_no;
1137
1138                     while (*q && *q != '\n' && !isspace(*q))
1139                         q++;
1140                 }
1141
1142                 return 1;
1143             }
1144         }
1145         p = strchr(p, '\n');
1146         if (!p)
1147             break;
1148
1149         p++;
1150     }
1151
1152     return 0;
1153 }
1154
1155 static int find_stream_in_feed(FFStream *feed, AVCodecContext *codec, int bit_rate)
1156 {
1157     int i;
1158     int best_bitrate = 100000000;
1159     int best = -1;
1160
1161     for (i = 0; i < feed->nb_streams; i++) {
1162         AVCodecContext *feed_codec = feed->streams[i]->codec;
1163
1164         if (feed_codec->codec_id != codec->codec_id ||
1165             feed_codec->sample_rate != codec->sample_rate ||
1166             feed_codec->width != codec->width ||
1167             feed_codec->height != codec->height)
1168             continue;
1169
1170         /* Potential stream */
1171
1172         /* We want the fastest stream less than bit_rate, or the slowest
1173          * faster than bit_rate
1174          */
1175
1176         if (feed_codec->bit_rate <= bit_rate) {
1177             if (best_bitrate > bit_rate || feed_codec->bit_rate > best_bitrate) {
1178                 best_bitrate = feed_codec->bit_rate;
1179                 best = i;
1180             }
1181         } else {
1182             if (feed_codec->bit_rate < best_bitrate) {
1183                 best_bitrate = feed_codec->bit_rate;
1184                 best = i;
1185             }
1186         }
1187     }
1188
1189     return best;
1190 }
1191
1192 static int modify_current_stream(HTTPContext *c, char *rates)
1193 {
1194     int i;
1195     FFStream *req = c->stream;
1196     int action_required = 0;
1197
1198     /* Not much we can do for a feed */
1199     if (!req->feed)
1200         return 0;
1201
1202     for (i = 0; i < req->nb_streams; i++) {
1203         AVCodecContext *codec = req->streams[i]->codec;
1204
1205         switch(rates[i]) {
1206             case 0:
1207                 c->switch_feed_streams[i] = req->feed_streams[i];
1208                 break;
1209             case 1:
1210                 c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 2);
1211                 break;
1212             case 2:
1213                 /* Wants off or slow */
1214                 c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 4);
1215 #ifdef WANTS_OFF
1216                 /* This doesn't work well when it turns off the only stream! */
1217                 c->switch_feed_streams[i] = -2;
1218                 c->feed_streams[i] = -2;
1219 #endif
1220                 break;
1221         }
1222
1223         if (c->switch_feed_streams[i] >= 0 && c->switch_feed_streams[i] != c->feed_streams[i])
1224             action_required = 1;
1225     }
1226
1227     return action_required;
1228 }
1229
1230 /* XXX: factorize in utils.c ? */
1231 /* XXX: take care with different space meaning */
1232 static void skip_spaces(const char **pp)
1233 {
1234     const char *p;
1235     p = *pp;
1236     while (*p == ' ' || *p == '\t')
1237         p++;
1238     *pp = p;
1239 }
1240
1241 static void get_word(char *buf, int buf_size, const char **pp)
1242 {
1243     const char *p;
1244     char *q;
1245
1246     p = *pp;
1247     skip_spaces(&p);
1248     q = buf;
1249     while (!isspace(*p) && *p != '\0') {
1250         if ((q - buf) < buf_size - 1)
1251             *q++ = *p;
1252         p++;
1253     }
1254     if (buf_size > 0)
1255         *q = '\0';
1256     *pp = p;
1257 }
1258
1259 static void get_arg(char *buf, int buf_size, const char **pp)
1260 {
1261     const char *p;
1262     char *q;
1263     int quote;
1264
1265     p = *pp;
1266     while (isspace(*p)) p++;
1267     q = buf;
1268     quote = 0;
1269     if (*p == '\"' || *p == '\'')
1270         quote = *p++;
1271     for(;;) {
1272         if (quote) {
1273             if (*p == quote)
1274                 break;
1275         } else {
1276             if (isspace(*p))
1277                 break;
1278         }
1279         if (*p == '\0')
1280             break;
1281         if ((q - buf) < buf_size - 1)
1282             *q++ = *p;
1283         p++;
1284     }
1285     *q = '\0';
1286     if (quote && *p == quote)
1287         p++;
1288     *pp = p;
1289 }
1290
1291 static void parse_acl_row(FFStream *stream, FFStream* feed, IPAddressACL *ext_acl,
1292                          const char *p, const char *filename, int line_num)
1293 {
1294     char arg[1024];
1295     IPAddressACL acl;
1296     int errors = 0;
1297
1298     get_arg(arg, sizeof(arg), &p);
1299     if (av_strcasecmp(arg, "allow") == 0)
1300         acl.action = IP_ALLOW;
1301     else if (av_strcasecmp(arg, "deny") == 0)
1302         acl.action = IP_DENY;
1303     else {
1304         fprintf(stderr, "%s:%d: ACL action '%s' is not ALLOW or DENY\n",
1305                 filename, line_num, arg);
1306         errors++;
1307     }
1308
1309     get_arg(arg, sizeof(arg), &p);
1310
1311     if (resolve_host(&acl.first, arg) != 0) {
1312         fprintf(stderr, "%s:%d: ACL refers to invalid host or ip address '%s'\n",
1313                 filename, line_num, arg);
1314         errors++;
1315     } else
1316         acl.last = acl.first;
1317
1318     get_arg(arg, sizeof(arg), &p);
1319
1320     if (arg[0]) {
1321         if (resolve_host(&acl.last, arg) != 0) {
1322             fprintf(stderr, "%s:%d: ACL refers to invalid host or ip address '%s'\n",
1323                     filename, line_num, arg);
1324             errors++;
1325         }
1326     }
1327
1328     if (!errors) {
1329         IPAddressACL *nacl = av_mallocz(sizeof(*nacl));
1330         IPAddressACL **naclp = 0;
1331
1332         acl.next = 0;
1333         *nacl = acl;
1334
1335         if (stream)
1336             naclp = &stream->acl;
1337         else if (feed)
1338             naclp = &feed->acl;
1339         else if (ext_acl)
1340             naclp = &ext_acl;
1341         else {
1342             fprintf(stderr, "%s:%d: ACL found not in <stream> or <feed>\n",
1343                     filename, line_num);
1344             errors++;
1345         }
1346
1347         if (naclp) {
1348             while (*naclp)
1349                 naclp = &(*naclp)->next;
1350
1351             *naclp = nacl;
1352         }
1353     }
1354 }
1355
1356
1357 static IPAddressACL* parse_dynamic_acl(FFStream *stream, HTTPContext *c)
1358 {
1359     FILE* f;
1360     char line[1024];
1361     char  cmd[1024];
1362     IPAddressACL *acl = NULL;
1363     int line_num = 0;
1364     const char *p;
1365
1366     f = fopen(stream->dynamic_acl, "r");
1367     if (!f) {
1368         perror(stream->dynamic_acl);
1369         return NULL;
1370     }
1371
1372     acl = av_mallocz(sizeof(IPAddressACL));
1373
1374     /* Build ACL */
1375     for(;;) {
1376         if (fgets(line, sizeof(line), f) == NULL)
1377             break;
1378         line_num++;
1379         p = line;
1380         while (isspace(*p))
1381             p++;
1382         if (*p == '\0' || *p == '#')
1383             continue;
1384         get_arg(cmd, sizeof(cmd), &p);
1385
1386         if (!av_strcasecmp(cmd, "ACL"))
1387             parse_acl_row(NULL, NULL, acl, p, stream->dynamic_acl, line_num);
1388     }
1389     fclose(f);
1390     return acl;
1391 }
1392
1393
1394 static void free_acl_list(IPAddressACL *in_acl)
1395 {
1396     IPAddressACL *pacl,*pacl2;
1397
1398     pacl = in_acl;
1399     while(pacl) {
1400         pacl2 = pacl;
1401         pacl = pacl->next;
1402         av_freep(pacl2);
1403     }
1404 }
1405
1406 static int validate_acl_list(IPAddressACL *in_acl, HTTPContext *c)
1407 {
1408     enum IPAddressAction last_action = IP_DENY;
1409     IPAddressACL *acl;
1410     struct in_addr *src = &c->from_addr.sin_addr;
1411     unsigned long src_addr = src->s_addr;
1412
1413     for (acl = in_acl; acl; acl = acl->next) {
1414         if (src_addr >= acl->first.s_addr && src_addr <= acl->last.s_addr)
1415             return (acl->action == IP_ALLOW) ? 1 : 0;
1416         last_action = acl->action;
1417     }
1418
1419     /* Nothing matched, so return not the last action */
1420     return (last_action == IP_DENY) ? 1 : 0;
1421 }
1422
1423 static int validate_acl(FFStream *stream, HTTPContext *c)
1424 {
1425     int ret = 0;
1426     IPAddressACL *acl;
1427
1428
1429     /* if stream->acl is null validate_acl_list will return 1 */
1430     ret = validate_acl_list(stream->acl, c);
1431
1432     if (stream->dynamic_acl[0]) {
1433         acl = parse_dynamic_acl(stream, c);
1434
1435         ret = validate_acl_list(acl, c);
1436
1437         free_acl_list(acl);
1438     }
1439
1440     return ret;
1441 }
1442
1443 /* compute the real filename of a file by matching it without its
1444    extensions to all the stream filenames */
1445 static void compute_real_filename(char *filename, int max_size)
1446 {
1447     char file1[1024];
1448     char file2[1024];
1449     char *p;
1450     FFStream *stream;
1451
1452     /* compute filename by matching without the file extensions */
1453     av_strlcpy(file1, filename, sizeof(file1));
1454     p = strrchr(file1, '.');
1455     if (p)
1456         *p = '\0';
1457     for(stream = first_stream; stream != NULL; stream = stream->next) {
1458         av_strlcpy(file2, stream->filename, sizeof(file2));
1459         p = strrchr(file2, '.');
1460         if (p)
1461             *p = '\0';
1462         if (!strcmp(file1, file2)) {
1463             av_strlcpy(filename, stream->filename, max_size);
1464             break;
1465         }
1466     }
1467 }
1468
1469 enum RedirType {
1470     REDIR_NONE,
1471     REDIR_ASX,
1472     REDIR_RAM,
1473     REDIR_ASF,
1474     REDIR_RTSP,
1475     REDIR_SDP,
1476 };
1477
1478 /* parse http request and prepare header */
1479 static int http_parse_request(HTTPContext *c)
1480 {
1481     char *p;
1482     enum RedirType redir_type;
1483     char cmd[32];
1484     char info[1024], filename[1024];
1485     char url[1024], *q;
1486     char protocol[32];
1487     char msg[1024];
1488     const char *mime_type;
1489     FFStream *stream;
1490     int i;
1491     char ratebuf[32];
1492     char *useragent = 0;
1493
1494     p = c->buffer;
1495     get_word(cmd, sizeof(cmd), (const char **)&p);
1496     av_strlcpy(c->method, cmd, sizeof(c->method));
1497
1498     if (!strcmp(cmd, "GET"))
1499         c->post = 0;
1500     else if (!strcmp(cmd, "POST"))
1501         c->post = 1;
1502     else
1503         return -1;
1504
1505     get_word(url, sizeof(url), (const char **)&p);
1506     av_strlcpy(c->url, url, sizeof(c->url));
1507
1508     get_word(protocol, sizeof(protocol), (const char **)&p);
1509     if (strcmp(protocol, "HTTP/1.0") && strcmp(protocol, "HTTP/1.1"))
1510         return -1;
1511
1512     av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
1513
1514     if (avserver_debug)
1515         http_log("%s - - New connection: %s %s\n", inet_ntoa(c->from_addr.sin_addr), cmd, url);
1516
1517     /* find the filename and the optional info string in the request */
1518     p = strchr(url, '?');
1519     if (p) {
1520         av_strlcpy(info, p, sizeof(info));
1521         *p = '\0';
1522     } else
1523         info[0] = '\0';
1524
1525     av_strlcpy(filename, url + ((*url == '/') ? 1 : 0), sizeof(filename)-1);
1526
1527     for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1528         if (av_strncasecmp(p, "User-Agent:", 11) == 0) {
1529             useragent = p + 11;
1530             if (*useragent && *useragent != '\n' && isspace(*useragent))
1531                 useragent++;
1532             break;
1533         }
1534         p = strchr(p, '\n');
1535         if (!p)
1536             break;
1537
1538         p++;
1539     }
1540
1541     redir_type = REDIR_NONE;
1542     if (av_match_ext(filename, "asx")) {
1543         redir_type = REDIR_ASX;
1544         filename[strlen(filename)-1] = 'f';
1545     } else if (av_match_ext(filename, "asf") &&
1546         (!useragent || av_strncasecmp(useragent, "NSPlayer", 8) != 0)) {
1547         /* if this isn't WMP or lookalike, return the redirector file */
1548         redir_type = REDIR_ASF;
1549     } else if (av_match_ext(filename, "rpm,ram")) {
1550         redir_type = REDIR_RAM;
1551         strcpy(filename + strlen(filename)-2, "m");
1552     } else if (av_match_ext(filename, "rtsp")) {
1553         redir_type = REDIR_RTSP;
1554         compute_real_filename(filename, sizeof(filename) - 1);
1555     } else if (av_match_ext(filename, "sdp")) {
1556         redir_type = REDIR_SDP;
1557         compute_real_filename(filename, sizeof(filename) - 1);
1558     }
1559
1560     // "redirect" / request to index.html
1561     if (!strlen(filename))
1562         av_strlcpy(filename, "index.html", sizeof(filename) - 1);
1563
1564     stream = first_stream;
1565     while (stream != NULL) {
1566         if (!strcmp(stream->filename, filename) && validate_acl(stream, c))
1567             break;
1568         stream = stream->next;
1569     }
1570     if (stream == NULL) {
1571         snprintf(msg, sizeof(msg), "File '%s' not found", url);
1572         http_log("File '%s' not found\n", url);
1573         goto send_error;
1574     }
1575
1576     c->stream = stream;
1577     memcpy(c->feed_streams, stream->feed_streams, sizeof(c->feed_streams));
1578     memset(c->switch_feed_streams, -1, sizeof(c->switch_feed_streams));
1579
1580     if (stream->stream_type == STREAM_TYPE_REDIRECT) {
1581         c->http_error = 301;
1582         q = c->buffer;
1583         q += snprintf(q, c->buffer_size,
1584                       "HTTP/1.0 301 Moved\r\n"
1585                       "Location: %s\r\n"
1586                       "Content-type: text/html\r\n"
1587                       "\r\n"
1588                       "<html><head><title>Moved</title></head><body>\r\n"
1589                       "You should be <a href=\"%s\">redirected</a>.\r\n"
1590                       "</body></html>\r\n", stream->feed_filename, stream->feed_filename);
1591         /* prepare output buffer */
1592         c->buffer_ptr = c->buffer;
1593         c->buffer_end = q;
1594         c->state = HTTPSTATE_SEND_HEADER;
1595         return 0;
1596     }
1597
1598     /* If this is WMP, get the rate information */
1599     if (extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
1600         if (modify_current_stream(c, ratebuf)) {
1601             for (i = 0; i < FF_ARRAY_ELEMS(c->feed_streams); i++) {
1602                 if (c->switch_feed_streams[i] >= 0)
1603                     c->switch_feed_streams[i] = -1;
1604             }
1605         }
1606     }
1607
1608     if (c->post == 0 && stream->stream_type == STREAM_TYPE_LIVE)
1609         current_bandwidth += stream->bandwidth;
1610
1611     /* If already streaming this feed, do not let start another feeder. */
1612     if (stream->feed_opened) {
1613         snprintf(msg, sizeof(msg), "This feed is already being received.");
1614         http_log("Feed '%s' already being received\n", stream->feed_filename);
1615         goto send_error;
1616     }
1617
1618     if (c->post == 0 && max_bandwidth < current_bandwidth) {
1619         c->http_error = 503;
1620         q = c->buffer;
1621         q += snprintf(q, c->buffer_size,
1622                       "HTTP/1.0 503 Server too busy\r\n"
1623                       "Content-type: text/html\r\n"
1624                       "\r\n"
1625                       "<html><head><title>Too busy</title></head><body>\r\n"
1626                       "<p>The server is too busy to serve your request at this time.</p>\r\n"
1627                       "<p>The bandwidth being served (including your stream) is %"PRIu64"kbit/sec, "
1628                       "and this exceeds the limit of %"PRIu64"kbit/sec.</p>\r\n"
1629                       "</body></html>\r\n", current_bandwidth, max_bandwidth);
1630         /* prepare output buffer */
1631         c->buffer_ptr = c->buffer;
1632         c->buffer_end = q;
1633         c->state = HTTPSTATE_SEND_HEADER;
1634         return 0;
1635     }
1636
1637     if (redir_type != REDIR_NONE) {
1638         char *hostinfo = 0;
1639
1640         for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1641             if (av_strncasecmp(p, "Host:", 5) == 0) {
1642                 hostinfo = p + 5;
1643                 break;
1644             }
1645             p = strchr(p, '\n');
1646             if (!p)
1647                 break;
1648
1649             p++;
1650         }
1651
1652         if (hostinfo) {
1653             char *eoh;
1654             char hostbuf[260];
1655
1656             while (isspace(*hostinfo))
1657                 hostinfo++;
1658
1659             eoh = strchr(hostinfo, '\n');
1660             if (eoh) {
1661                 if (eoh[-1] == '\r')
1662                     eoh--;
1663
1664                 if (eoh - hostinfo < sizeof(hostbuf) - 1) {
1665                     memcpy(hostbuf, hostinfo, eoh - hostinfo);
1666                     hostbuf[eoh - hostinfo] = 0;
1667
1668                     c->http_error = 200;
1669                     q = c->buffer;
1670                     switch(redir_type) {
1671                     case REDIR_ASX:
1672                         q += snprintf(q, c->buffer_size,
1673                                       "HTTP/1.0 200 ASX Follows\r\n"
1674                                       "Content-type: video/x-ms-asf\r\n"
1675                                       "\r\n"
1676                                       "<ASX Version=\"3\">\r\n"
1677                                       //"<!-- Autogenerated by avserver -->\r\n"
1678                                       "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n"
1679                                       "</ASX>\r\n", hostbuf, filename, info);
1680                         break;
1681                     case REDIR_RAM:
1682                         q += snprintf(q, c->buffer_size,
1683                                       "HTTP/1.0 200 RAM Follows\r\n"
1684                                       "Content-type: audio/x-pn-realaudio\r\n"
1685                                       "\r\n"
1686                                       "# Autogenerated by avserver\r\n"
1687                                       "http://%s/%s%s\r\n", hostbuf, filename, info);
1688                         break;
1689                     case REDIR_ASF:
1690                         q += snprintf(q, c->buffer_size,
1691                                       "HTTP/1.0 200 ASF Redirect follows\r\n"
1692                                       "Content-type: video/x-ms-asf\r\n"
1693                                       "\r\n"
1694                                       "[Reference]\r\n"
1695                                       "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info);
1696                         break;
1697                     case REDIR_RTSP:
1698                         {
1699                             char hostname[256], *p;
1700                             /* extract only hostname */
1701                             av_strlcpy(hostname, hostbuf, sizeof(hostname));
1702                             p = strrchr(hostname, ':');
1703                             if (p)
1704                                 *p = '\0';
1705                             q += snprintf(q, c->buffer_size,
1706                                           "HTTP/1.0 200 RTSP Redirect follows\r\n"
1707                                           /* XXX: incorrect mime type ? */
1708                                           "Content-type: application/x-rtsp\r\n"
1709                                           "\r\n"
1710                                           "rtsp://%s:%d/%s\r\n", hostname, ntohs(my_rtsp_addr.sin_port), filename);
1711                         }
1712                         break;
1713                     case REDIR_SDP:
1714                         {
1715                             uint8_t *sdp_data;
1716                             int sdp_data_size;
1717                             socklen_t len;
1718                             struct sockaddr_in my_addr;
1719
1720                             q += snprintf(q, c->buffer_size,
1721                                           "HTTP/1.0 200 OK\r\n"
1722                                           "Content-type: application/sdp\r\n"
1723                                           "\r\n");
1724
1725                             len = sizeof(my_addr);
1726                             getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
1727
1728                             /* XXX: should use a dynamic buffer */
1729                             sdp_data_size = prepare_sdp_description(stream,
1730                                                                     &sdp_data,
1731                                                                     my_addr.sin_addr);
1732                             if (sdp_data_size > 0) {
1733                                 memcpy(q, sdp_data, sdp_data_size);
1734                                 q += sdp_data_size;
1735                                 *q = '\0';
1736                                 av_free(sdp_data);
1737                             }
1738                         }
1739                         break;
1740                     default:
1741                         abort();
1742                         break;
1743                     }
1744
1745                     /* prepare output buffer */
1746                     c->buffer_ptr = c->buffer;
1747                     c->buffer_end = q;
1748                     c->state = HTTPSTATE_SEND_HEADER;
1749                     return 0;
1750                 }
1751             }
1752         }
1753
1754         snprintf(msg, sizeof(msg), "ASX/RAM file not handled");
1755         goto send_error;
1756     }
1757
1758     stream->conns_served++;
1759
1760     /* XXX: add there authenticate and IP match */
1761
1762     if (c->post) {
1763         /* if post, it means a feed is being sent */
1764         if (!stream->is_feed) {
1765             /* However it might be a status report from WMP! Let us log the
1766              * data as it might come in handy one day. */
1767             char *logline = 0;
1768             int client_id = 0;
1769
1770             for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1771                 if (av_strncasecmp(p, "Pragma: log-line=", 17) == 0) {
1772                     logline = p;
1773                     break;
1774                 }
1775                 if (av_strncasecmp(p, "Pragma: client-id=", 18) == 0)
1776                     client_id = strtol(p + 18, 0, 10);
1777                 p = strchr(p, '\n');
1778                 if (!p)
1779                     break;
1780
1781                 p++;
1782             }
1783
1784             if (logline) {
1785                 char *eol = strchr(logline, '\n');
1786
1787                 logline += 17;
1788
1789                 if (eol) {
1790                     if (eol[-1] == '\r')
1791                         eol--;
1792                     http_log("%.*s\n", (int) (eol - logline), logline);
1793                     c->suppress_log = 1;
1794                 }
1795             }
1796
1797 #ifdef DEBUG
1798             http_log("\nGot request:\n%s\n", c->buffer);
1799 #endif
1800
1801             if (client_id && extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
1802                 HTTPContext *wmpc;
1803
1804                 /* Now we have to find the client_id */
1805                 for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->next) {
1806                     if (wmpc->wmp_client_id == client_id)
1807                         break;
1808                 }
1809
1810                 if (wmpc && modify_current_stream(wmpc, ratebuf))
1811                     wmpc->switch_pending = 1;
1812             }
1813
1814             snprintf(msg, sizeof(msg), "POST command not handled");
1815             c->stream = 0;
1816             goto send_error;
1817         }
1818         if (http_start_receive_data(c) < 0) {
1819             snprintf(msg, sizeof(msg), "could not open feed");
1820             goto send_error;
1821         }
1822         c->http_error = 0;
1823         c->state = HTTPSTATE_RECEIVE_DATA;
1824         return 0;
1825     }
1826
1827 #ifdef DEBUG
1828     if (strcmp(stream->filename + strlen(stream->filename) - 4, ".asf") == 0)
1829         http_log("\nGot request:\n%s\n", c->buffer);
1830 #endif
1831
1832     if (c->stream->stream_type == STREAM_TYPE_STATUS)
1833         goto send_status;
1834
1835     /* open input stream */
1836     if (open_input_stream(c, info) < 0) {
1837         snprintf(msg, sizeof(msg), "Input stream corresponding to '%s' not found", url);
1838         goto send_error;
1839     }
1840
1841     /* prepare http header */
1842     q = c->buffer;
1843     q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 OK\r\n");
1844     mime_type = c->stream->fmt->mime_type;
1845     if (!mime_type)
1846         mime_type = "application/x-octet-stream";
1847     q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Pragma: no-cache\r\n");
1848
1849     /* for asf, we need extra headers */
1850     if (!strcmp(c->stream->fmt->name,"asf_stream")) {
1851         /* Need to allocate a client id */
1852
1853         c->wmp_client_id = av_lfg_get(&random_state);
1854
1855         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);
1856     }
1857     q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-Type: %s\r\n", mime_type);
1858     q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
1859
1860     /* prepare output buffer */
1861     c->http_error = 0;
1862     c->buffer_ptr = c->buffer;
1863     c->buffer_end = q;
1864     c->state = HTTPSTATE_SEND_HEADER;
1865     return 0;
1866  send_error:
1867     c->http_error = 404;
1868     q = c->buffer;
1869     q += snprintf(q, c->buffer_size,
1870                   "HTTP/1.0 404 Not Found\r\n"
1871                   "Content-type: text/html\r\n"
1872                   "\r\n"
1873                   "<html>\n"
1874                   "<head><title>404 Not Found</title></head>\n"
1875                   "<body>%s</body>\n"
1876                   "</html>\n", msg);
1877     /* prepare output buffer */
1878     c->buffer_ptr = c->buffer;
1879     c->buffer_end = q;
1880     c->state = HTTPSTATE_SEND_HEADER;
1881     return 0;
1882  send_status:
1883     compute_status(c);
1884     c->http_error = 200; /* horrible : we use this value to avoid
1885                             going to the send data state */
1886     c->state = HTTPSTATE_SEND_HEADER;
1887     return 0;
1888 }
1889
1890 static void fmt_bytecount(AVIOContext *pb, int64_t count)
1891 {
1892     static const char suffix[] = " kMGTP";
1893     const char *s;
1894
1895     for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++);
1896
1897     avio_printf(pb, "%"PRId64"%c", count, *s);
1898 }
1899
1900 static void compute_status(HTTPContext *c)
1901 {
1902     HTTPContext *c1;
1903     FFStream *stream;
1904     char *p;
1905     time_t ti;
1906     int i, len;
1907     AVIOContext *pb;
1908
1909     if (avio_open_dyn_buf(&pb) < 0) {
1910         /* XXX: return an error ? */
1911         c->buffer_ptr = c->buffer;
1912         c->buffer_end = c->buffer;
1913         return;
1914     }
1915
1916     avio_printf(pb, "HTTP/1.0 200 OK\r\n");
1917     avio_printf(pb, "Content-type: %s\r\n", "text/html");
1918     avio_printf(pb, "Pragma: no-cache\r\n");
1919     avio_printf(pb, "\r\n");
1920
1921     avio_printf(pb, "<html><head><title>%s Status</title>\n", program_name);
1922     if (c->stream->feed_filename[0])
1923         avio_printf(pb, "<link rel=\"shortcut icon\" href=\"%s\">\n", c->stream->feed_filename);
1924     avio_printf(pb, "</head>\n<body>");
1925     avio_printf(pb, "<h1>%s Status</h1>\n", program_name);
1926     /* format status */
1927     avio_printf(pb, "<h2>Available Streams</h2>\n");
1928     avio_printf(pb, "<table cellspacing=0 cellpadding=4>\n");
1929     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");
1930     stream = first_stream;
1931     while (stream != NULL) {
1932         char sfilename[1024];
1933         char *eosf;
1934
1935         if (stream->feed != stream) {
1936             av_strlcpy(sfilename, stream->filename, sizeof(sfilename) - 10);
1937             eosf = sfilename + strlen(sfilename);
1938             if (eosf - sfilename >= 4) {
1939                 if (strcmp(eosf - 4, ".asf") == 0)
1940                     strcpy(eosf - 4, ".asx");
1941                 else if (strcmp(eosf - 3, ".rm") == 0)
1942                     strcpy(eosf - 3, ".ram");
1943                 else if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
1944                     /* generate a sample RTSP director if
1945                        unicast. Generate an SDP redirector if
1946                        multicast */
1947                     eosf = strrchr(sfilename, '.');
1948                     if (!eosf)
1949                         eosf = sfilename + strlen(sfilename);
1950                     if (stream->is_multicast)
1951                         strcpy(eosf, ".sdp");
1952                     else
1953                         strcpy(eosf, ".rtsp");
1954                 }
1955             }
1956
1957             avio_printf(pb, "<tr><td><a href=\"/%s\">%s</a> ",
1958                          sfilename, stream->filename);
1959             avio_printf(pb, "<td align=right> %d <td align=right> ",
1960                         stream->conns_served);
1961             fmt_bytecount(pb, stream->bytes_served);
1962             switch(stream->stream_type) {
1963             case STREAM_TYPE_LIVE: {
1964                     int audio_bit_rate = 0;
1965                     int video_bit_rate = 0;
1966                     const char *audio_codec_name = "";
1967                     const char *video_codec_name = "";
1968                     const char *audio_codec_name_extra = "";
1969                     const char *video_codec_name_extra = "";
1970
1971                     for(i=0;i<stream->nb_streams;i++) {
1972                         AVStream *st = stream->streams[i];
1973                         AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
1974                         switch(st->codec->codec_type) {
1975                         case AVMEDIA_TYPE_AUDIO:
1976                             audio_bit_rate += st->codec->bit_rate;
1977                             if (codec) {
1978                                 if (*audio_codec_name)
1979                                     audio_codec_name_extra = "...";
1980                                 audio_codec_name = codec->name;
1981                             }
1982                             break;
1983                         case AVMEDIA_TYPE_VIDEO:
1984                             video_bit_rate += st->codec->bit_rate;
1985                             if (codec) {
1986                                 if (*video_codec_name)
1987                                     video_codec_name_extra = "...";
1988                                 video_codec_name = codec->name;
1989                             }
1990                             break;
1991                         case AVMEDIA_TYPE_DATA:
1992                             video_bit_rate += st->codec->bit_rate;
1993                             break;
1994                         default:
1995                             abort();
1996                         }
1997                     }
1998                     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",
1999                                  stream->fmt->name,
2000                                  stream->bandwidth,
2001                                  video_bit_rate / 1000, video_codec_name, video_codec_name_extra,
2002                                  audio_bit_rate / 1000, audio_codec_name, audio_codec_name_extra);
2003                     if (stream->feed)
2004                         avio_printf(pb, "<td>%s", stream->feed->filename);
2005                     else
2006                         avio_printf(pb, "<td>%s", stream->feed_filename);
2007                     avio_printf(pb, "\n");
2008                 }
2009                 break;
2010             default:
2011                 avio_printf(pb, "<td align=center> - <td align=right> - <td align=right> - <td><td align=right> - <td>\n");
2012                 break;
2013             }
2014         }
2015         stream = stream->next;
2016     }
2017     avio_printf(pb, "</table>\n");
2018
2019     stream = first_stream;
2020     while (stream != NULL) {
2021         if (stream->feed == stream) {
2022             avio_printf(pb, "<h2>Feed %s</h2>", stream->filename);
2023             if (stream->pid) {
2024                 avio_printf(pb, "Running as pid %d.\n", stream->pid);
2025
2026 #if defined(linux) && !defined(CONFIG_NOCUTILS)
2027                 {
2028                     FILE *pid_stat;
2029                     char ps_cmd[64];
2030
2031                     /* This is somewhat linux specific I guess */
2032                     snprintf(ps_cmd, sizeof(ps_cmd),
2033                              "ps -o \"%%cpu,cputime\" --no-headers %d",
2034                              stream->pid);
2035
2036                     pid_stat = popen(ps_cmd, "r");
2037                     if (pid_stat) {
2038                         char cpuperc[10];
2039                         char cpuused[64];
2040
2041                         if (fscanf(pid_stat, "%10s %64s", cpuperc,
2042                                    cpuused) == 2) {
2043                             avio_printf(pb, "Currently using %s%% of the cpu. Total time used %s.\n",
2044                                          cpuperc, cpuused);
2045                         }
2046                         fclose(pid_stat);
2047                     }
2048                 }
2049 #endif
2050
2051                 avio_printf(pb, "<p>");
2052             }
2053             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");
2054
2055             for (i = 0; i < stream->nb_streams; i++) {
2056                 AVStream *st = stream->streams[i];
2057                 AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
2058                 const char *type = "unknown";
2059                 char parameters[64];
2060
2061                 parameters[0] = 0;
2062
2063                 switch(st->codec->codec_type) {
2064                 case AVMEDIA_TYPE_AUDIO:
2065                     type = "audio";
2066                     snprintf(parameters, sizeof(parameters), "%d channel(s), %d Hz", st->codec->channels, st->codec->sample_rate);
2067                     break;
2068                 case AVMEDIA_TYPE_VIDEO:
2069                     type = "video";
2070                     snprintf(parameters, sizeof(parameters), "%dx%d, q=%d-%d, fps=%d", st->codec->width, st->codec->height,
2071                                 st->codec->qmin, st->codec->qmax, st->codec->time_base.den / st->codec->time_base.num);
2072                     break;
2073                 default:
2074                     abort();
2075                 }
2076                 avio_printf(pb, "<tr><td align=right>%d<td>%s<td align=right>%d<td>%s<td>%s\n",
2077                         i, type, st->codec->bit_rate/1000, codec ? codec->name : "", parameters);
2078             }
2079             avio_printf(pb, "</table>\n");
2080
2081         }
2082         stream = stream->next;
2083     }
2084
2085     /* connection status */
2086     avio_printf(pb, "<h2>Connection Status</h2>\n");
2087
2088     avio_printf(pb, "Number of connections: %d / %d<br>\n",
2089                  nb_connections, nb_max_connections);
2090
2091     avio_printf(pb, "Bandwidth in use: %"PRIu64"k / %"PRIu64"k<br>\n",
2092                  current_bandwidth, max_bandwidth);
2093
2094     avio_printf(pb, "<table>\n");
2095     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");
2096     c1 = first_http_ctx;
2097     i = 0;
2098     while (c1 != NULL) {
2099         int bitrate;
2100         int j;
2101
2102         bitrate = 0;
2103         if (c1->stream) {
2104             for (j = 0; j < c1->stream->nb_streams; j++) {
2105                 if (!c1->stream->feed)
2106                     bitrate += c1->stream->streams[j]->codec->bit_rate;
2107                 else if (c1->feed_streams[j] >= 0)
2108                     bitrate += c1->stream->feed->streams[c1->feed_streams[j]]->codec->bit_rate;
2109             }
2110         }
2111
2112         i++;
2113         p = inet_ntoa(c1->from_addr.sin_addr);
2114         avio_printf(pb, "<tr><td><b>%d</b><td>%s%s<td>%s<td>%s<td>%s<td align=right>",
2115                     i,
2116                     c1->stream ? c1->stream->filename : "",
2117                     c1->state == HTTPSTATE_RECEIVE_DATA ? "(input)" : "",
2118                     p,
2119                     c1->protocol,
2120                     http_state[c1->state]);
2121         fmt_bytecount(pb, bitrate);
2122         avio_printf(pb, "<td align=right>");
2123         fmt_bytecount(pb, compute_datarate(&c1->datarate, c1->data_count) * 8);
2124         avio_printf(pb, "<td align=right>");
2125         fmt_bytecount(pb, c1->data_count);
2126         avio_printf(pb, "\n");
2127         c1 = c1->next;
2128     }
2129     avio_printf(pb, "</table>\n");
2130
2131     /* date */
2132     ti = time(NULL);
2133     p = ctime(&ti);
2134     avio_printf(pb, "<hr size=1 noshade>Generated at %s", p);
2135     avio_printf(pb, "</body>\n</html>\n");
2136
2137     len = avio_close_dyn_buf(pb, &c->pb_buffer);
2138     c->buffer_ptr = c->pb_buffer;
2139     c->buffer_end = c->pb_buffer + len;
2140 }
2141
2142 static int open_input_stream(HTTPContext *c, const char *info)
2143 {
2144     char buf[128];
2145     char input_filename[1024];
2146     AVFormatContext *s = NULL;
2147     int i, ret;
2148     int64_t stream_pos;
2149
2150     /* find file name */
2151     if (c->stream->feed) {
2152         strcpy(input_filename, c->stream->feed->feed_filename);
2153         /* compute position (absolute time) */
2154         if (av_find_info_tag(buf, sizeof(buf), "date", info)) {
2155             if ((ret = av_parse_time(&stream_pos, buf, 0)) < 0)
2156                 return ret;
2157         } else if (av_find_info_tag(buf, sizeof(buf), "buffer", info)) {
2158             int prebuffer = strtol(buf, 0, 10);
2159             stream_pos = av_gettime() - prebuffer * (int64_t)1000000;
2160         } else
2161             stream_pos = av_gettime() - c->stream->prebuffer * (int64_t)1000;
2162     } else {
2163         strcpy(input_filename, c->stream->feed_filename);
2164         /* compute position (relative time) */
2165         if (av_find_info_tag(buf, sizeof(buf), "date", info)) {
2166             if ((ret = av_parse_time(&stream_pos, buf, 1)) < 0)
2167                 return ret;
2168         } else
2169             stream_pos = 0;
2170     }
2171     if (input_filename[0] == '\0')
2172         return -1;
2173
2174     /* open stream */
2175     if ((ret = avformat_open_input(&s, input_filename, c->stream->ifmt, &c->stream->in_opts)) < 0) {
2176         http_log("could not open %s: %d\n", input_filename, ret);
2177         return -1;
2178     }
2179     s->flags |= AVFMT_FLAG_GENPTS;
2180     c->fmt_in = s;
2181     if (strcmp(s->iformat->name, "ffm") && avformat_find_stream_info(c->fmt_in, NULL) < 0) {
2182         http_log("Could not find stream info '%s'\n", input_filename);
2183         avformat_close_input(&s);
2184         return -1;
2185     }
2186
2187     /* choose stream as clock source (we favorize video stream if
2188        present) for packet sending */
2189     c->pts_stream_index = 0;
2190     for(i=0;i<c->stream->nb_streams;i++) {
2191         if (c->pts_stream_index == 0 &&
2192             c->stream->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
2193             c->pts_stream_index = i;
2194         }
2195     }
2196
2197     if (c->fmt_in->iformat->read_seek)
2198         av_seek_frame(c->fmt_in, -1, stream_pos, 0);
2199     /* set the start time (needed for maxtime and RTP packet timing) */
2200     c->start_time = cur_time;
2201     c->first_pts = AV_NOPTS_VALUE;
2202     return 0;
2203 }
2204
2205 /* return the server clock (in us) */
2206 static int64_t get_server_clock(HTTPContext *c)
2207 {
2208     /* compute current pts value from system time */
2209     return (cur_time - c->start_time) * 1000;
2210 }
2211
2212 /* return the estimated time at which the current packet must be sent
2213    (in us) */
2214 static int64_t get_packet_send_clock(HTTPContext *c)
2215 {
2216     int bytes_left, bytes_sent, frame_bytes;
2217
2218     frame_bytes = c->cur_frame_bytes;
2219     if (frame_bytes <= 0)
2220         return c->cur_pts;
2221     else {
2222         bytes_left = c->buffer_end - c->buffer_ptr;
2223         bytes_sent = frame_bytes - bytes_left;
2224         return c->cur_pts + (c->cur_frame_duration * bytes_sent) / frame_bytes;
2225     }
2226 }
2227
2228
2229 static int http_prepare_data(HTTPContext *c)
2230 {
2231     int i, len, ret;
2232     AVFormatContext *ctx;
2233
2234     av_freep(&c->pb_buffer);
2235     switch(c->state) {
2236     case HTTPSTATE_SEND_DATA_HEADER:
2237         memset(&c->fmt_ctx, 0, sizeof(c->fmt_ctx));
2238         av_dict_set(&c->fmt_ctx.metadata, "author"   , c->stream->author   , 0);
2239         av_dict_set(&c->fmt_ctx.metadata, "comment"  , c->stream->comment  , 0);
2240         av_dict_set(&c->fmt_ctx.metadata, "copyright", c->stream->copyright, 0);
2241         av_dict_set(&c->fmt_ctx.metadata, "title"    , c->stream->title    , 0);
2242
2243         c->fmt_ctx.streams = av_mallocz(sizeof(AVStream *) * c->stream->nb_streams);
2244
2245         for(i=0;i<c->stream->nb_streams;i++) {
2246             AVStream *src;
2247             c->fmt_ctx.streams[i] = av_mallocz(sizeof(AVStream));
2248             /* if file or feed, then just take streams from FFStream struct */
2249             if (!c->stream->feed ||
2250                 c->stream->feed == c->stream)
2251                 src = c->stream->streams[i];
2252             else
2253                 src = c->stream->feed->streams[c->stream->feed_streams[i]];
2254
2255             *(c->fmt_ctx.streams[i]) = *src;
2256             c->fmt_ctx.streams[i]->priv_data = 0;
2257             c->fmt_ctx.streams[i]->codec->frame_number = 0; /* XXX: should be done in
2258                                            AVStream, not in codec */
2259         }
2260         /* set output format parameters */
2261         c->fmt_ctx.oformat = c->stream->fmt;
2262         c->fmt_ctx.nb_streams = c->stream->nb_streams;
2263
2264         c->got_key_frame = 0;
2265
2266         /* prepare header and save header data in a stream */
2267         if (avio_open_dyn_buf(&c->fmt_ctx.pb) < 0) {
2268             /* XXX: potential leak */
2269             return -1;
2270         }
2271         c->fmt_ctx.pb->seekable = 0;
2272
2273         /*
2274          * HACK to avoid mpeg ps muxer to spit many underflow errors
2275          * Default value from Libav
2276          * Try to set it use configuration option
2277          */
2278         c->fmt_ctx.max_delay = (int)(0.7*AV_TIME_BASE);
2279
2280         if (avformat_write_header(&c->fmt_ctx, NULL) < 0) {
2281             http_log("Error writing output header\n");
2282             return -1;
2283         }
2284         av_dict_free(&c->fmt_ctx.metadata);
2285
2286         len = avio_close_dyn_buf(c->fmt_ctx.pb, &c->pb_buffer);
2287         c->buffer_ptr = c->pb_buffer;
2288         c->buffer_end = c->pb_buffer + len;
2289
2290         c->state = HTTPSTATE_SEND_DATA;
2291         c->last_packet_sent = 0;
2292         break;
2293     case HTTPSTATE_SEND_DATA:
2294         /* find a new packet */
2295         /* read a packet from the input stream */
2296         if (c->stream->feed)
2297             ffm_set_write_index(c->fmt_in,
2298                                 c->stream->feed->feed_write_index,
2299                                 c->stream->feed->feed_size);
2300
2301         if (c->stream->max_time &&
2302             c->stream->max_time + c->start_time - cur_time < 0)
2303             /* We have timed out */
2304             c->state = HTTPSTATE_SEND_DATA_TRAILER;
2305         else {
2306             AVPacket pkt;
2307         redo:
2308             ret = av_read_frame(c->fmt_in, &pkt);
2309             if (ret < 0) {
2310                 if (c->stream->feed) {
2311                     /* if coming from feed, it means we reached the end of the
2312                        ffm file, so must wait for more data */
2313                     c->state = HTTPSTATE_WAIT_FEED;
2314                     return 1; /* state changed */
2315                 } else if (ret == AVERROR(EAGAIN)) {
2316                     /* input not ready, come back later */
2317                     return 0;
2318                 } else {
2319                     if (c->stream->loop) {
2320                         avformat_close_input(&c->fmt_in);
2321                         if (open_input_stream(c, "") < 0)
2322                             goto no_loop;
2323                         goto redo;
2324                     } else {
2325                     no_loop:
2326                         /* must send trailer now because eof or error */
2327                         c->state = HTTPSTATE_SEND_DATA_TRAILER;
2328                     }
2329                 }
2330             } else {
2331                 int source_index = pkt.stream_index;
2332                 /* update first pts if needed */
2333                 if (c->first_pts == AV_NOPTS_VALUE) {
2334                     c->first_pts = av_rescale_q(pkt.dts, c->fmt_in->streams[pkt.stream_index]->time_base, AV_TIME_BASE_Q);
2335                     c->start_time = cur_time;
2336                 }
2337                 /* send it to the appropriate stream */
2338                 if (c->stream->feed) {
2339                     /* if coming from a feed, select the right stream */
2340                     if (c->switch_pending) {
2341                         c->switch_pending = 0;
2342                         for(i=0;i<c->stream->nb_streams;i++) {
2343                             if (c->switch_feed_streams[i] == pkt.stream_index)
2344                                 if (pkt.flags & AV_PKT_FLAG_KEY)
2345                                     c->switch_feed_streams[i] = -1;
2346                             if (c->switch_feed_streams[i] >= 0)
2347                                 c->switch_pending = 1;
2348                         }
2349                     }
2350                     for(i=0;i<c->stream->nb_streams;i++) {
2351                         if (c->stream->feed_streams[i] == pkt.stream_index) {
2352                             AVStream *st = c->fmt_in->streams[source_index];
2353                             pkt.stream_index = i;
2354                             if (pkt.flags & AV_PKT_FLAG_KEY &&
2355                                 (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
2356                                  c->stream->nb_streams == 1))
2357                                 c->got_key_frame = 1;
2358                             if (!c->stream->send_on_key || c->got_key_frame)
2359                                 goto send_it;
2360                         }
2361                     }
2362                 } else {
2363                     AVCodecContext *codec;
2364                     AVStream *ist, *ost;
2365                 send_it:
2366                     ist = c->fmt_in->streams[source_index];
2367                     /* specific handling for RTP: we use several
2368                        output stream (one for each RTP
2369                        connection). XXX: need more abstract handling */
2370                     if (c->is_packetized) {
2371                         /* compute send time and duration */
2372                         c->cur_pts = av_rescale_q(pkt.dts, ist->time_base, AV_TIME_BASE_Q);
2373                         c->cur_pts -= c->first_pts;
2374                         c->cur_frame_duration = av_rescale_q(pkt.duration, ist->time_base, AV_TIME_BASE_Q);
2375                         /* find RTP context */
2376                         c->packet_stream_index = pkt.stream_index;
2377                         ctx = c->rtp_ctx[c->packet_stream_index];
2378                         if(!ctx) {
2379                             av_free_packet(&pkt);
2380                             break;
2381                         }
2382                         codec = ctx->streams[0]->codec;
2383                         /* only one stream per RTP connection */
2384                         pkt.stream_index = 0;
2385                     } else {
2386                         ctx = &c->fmt_ctx;
2387                         /* Fudge here */
2388                         codec = ctx->streams[pkt.stream_index]->codec;
2389                     }
2390
2391                     if (c->is_packetized) {
2392                         int max_packet_size;
2393                         if (c->rtp_protocol == RTSP_LOWER_TRANSPORT_TCP)
2394                             max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
2395                         else
2396                             max_packet_size = c->rtp_handles[c->packet_stream_index]->max_packet_size;
2397                         ret = ffio_open_dyn_packet_buf(&ctx->pb, max_packet_size);
2398                     } else {
2399                         ret = avio_open_dyn_buf(&ctx->pb);
2400                     }
2401                     if (ret < 0) {
2402                         /* XXX: potential leak */
2403                         return -1;
2404                     }
2405                     ost = ctx->streams[pkt.stream_index];
2406
2407                     ctx->pb->seekable = 0;
2408                     if (pkt.dts != AV_NOPTS_VALUE)
2409                         pkt.dts = av_rescale_q(pkt.dts, ist->time_base, ost->time_base);
2410                     if (pkt.pts != AV_NOPTS_VALUE)
2411                         pkt.pts = av_rescale_q(pkt.pts, ist->time_base, ost->time_base);
2412                     pkt.duration = av_rescale_q(pkt.duration, ist->time_base, ost->time_base);
2413                     if (av_write_frame(ctx, &pkt) < 0) {
2414                         http_log("Error writing frame to output\n");
2415                         c->state = HTTPSTATE_SEND_DATA_TRAILER;
2416                     }
2417
2418                     len = avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
2419                     c->cur_frame_bytes = len;
2420                     c->buffer_ptr = c->pb_buffer;
2421                     c->buffer_end = c->pb_buffer + len;
2422
2423                     codec->frame_number++;
2424                     if (len == 0) {
2425                         av_free_packet(&pkt);
2426                         goto redo;
2427                     }
2428                 }
2429                 av_free_packet(&pkt);
2430             }
2431         }
2432         break;
2433     default:
2434     case HTTPSTATE_SEND_DATA_TRAILER:
2435         /* last packet test ? */
2436         if (c->last_packet_sent || c->is_packetized)
2437             return -1;
2438         ctx = &c->fmt_ctx;
2439         /* prepare header */
2440         if (avio_open_dyn_buf(&ctx->pb) < 0) {
2441             /* XXX: potential leak */
2442             return -1;
2443         }
2444         c->fmt_ctx.pb->seekable = 0;
2445         av_write_trailer(ctx);
2446         len = avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
2447         c->buffer_ptr = c->pb_buffer;
2448         c->buffer_end = c->pb_buffer + len;
2449
2450         c->last_packet_sent = 1;
2451         break;
2452     }
2453     return 0;
2454 }
2455
2456 /* should convert the format at the same time */
2457 /* send data starting at c->buffer_ptr to the output connection
2458    (either UDP or TCP connection) */
2459 static int http_send_data(HTTPContext *c)
2460 {
2461     int len, ret;
2462
2463     for(;;) {
2464         if (c->buffer_ptr >= c->buffer_end) {
2465             ret = http_prepare_data(c);
2466             if (ret < 0)
2467                 return -1;
2468             else if (ret != 0)
2469                 /* state change requested */
2470                 break;
2471         } else {
2472             if (c->is_packetized) {
2473                 /* RTP data output */
2474                 len = c->buffer_end - c->buffer_ptr;
2475                 if (len < 4) {
2476                     /* fail safe - should never happen */
2477                 fail1:
2478                     c->buffer_ptr = c->buffer_end;
2479                     return 0;
2480                 }
2481                 len = (c->buffer_ptr[0] << 24) |
2482                     (c->buffer_ptr[1] << 16) |
2483                     (c->buffer_ptr[2] << 8) |
2484                     (c->buffer_ptr[3]);
2485                 if (len > (c->buffer_end - c->buffer_ptr))
2486                     goto fail1;
2487                 if ((get_packet_send_clock(c) - get_server_clock(c)) > 0) {
2488                     /* nothing to send yet: we can wait */
2489                     return 0;
2490                 }
2491
2492                 c->data_count += len;
2493                 update_datarate(&c->datarate, c->data_count);
2494                 if (c->stream)
2495                     c->stream->bytes_served += len;
2496
2497                 if (c->rtp_protocol == RTSP_LOWER_TRANSPORT_TCP) {
2498                     /* RTP packets are sent inside the RTSP TCP connection */
2499                     AVIOContext *pb;
2500                     int interleaved_index, size;
2501                     uint8_t header[4];
2502                     HTTPContext *rtsp_c;
2503
2504                     rtsp_c = c->rtsp_c;
2505                     /* if no RTSP connection left, error */
2506                     if (!rtsp_c)
2507                         return -1;
2508                     /* if already sending something, then wait. */
2509                     if (rtsp_c->state != RTSPSTATE_WAIT_REQUEST)
2510                         break;
2511                     if (avio_open_dyn_buf(&pb) < 0)
2512                         goto fail1;
2513                     interleaved_index = c->packet_stream_index * 2;
2514                     /* RTCP packets are sent at odd indexes */
2515                     if (c->buffer_ptr[1] == 200)
2516                         interleaved_index++;
2517                     /* write RTSP TCP header */
2518                     header[0] = '$';
2519                     header[1] = interleaved_index;
2520                     header[2] = len >> 8;
2521                     header[3] = len;
2522                     avio_write(pb, header, 4);
2523                     /* write RTP packet data */
2524                     c->buffer_ptr += 4;
2525                     avio_write(pb, c->buffer_ptr, len);
2526                     size = avio_close_dyn_buf(pb, &c->packet_buffer);
2527                     /* prepare asynchronous TCP sending */
2528                     rtsp_c->packet_buffer_ptr = c->packet_buffer;
2529                     rtsp_c->packet_buffer_end = c->packet_buffer + size;
2530                     c->buffer_ptr += len;
2531
2532                     /* send everything we can NOW */
2533                     len = send(rtsp_c->fd, rtsp_c->packet_buffer_ptr,
2534                                 rtsp_c->packet_buffer_end - rtsp_c->packet_buffer_ptr, 0);
2535                     if (len > 0)
2536                         rtsp_c->packet_buffer_ptr += len;
2537                     if (rtsp_c->packet_buffer_ptr < rtsp_c->packet_buffer_end) {
2538                         /* if we could not send all the data, we will
2539                            send it later, so a new state is needed to
2540                            "lock" the RTSP TCP connection */
2541                         rtsp_c->state = RTSPSTATE_SEND_PACKET;
2542                         break;
2543                     } else
2544                         /* all data has been sent */
2545                         av_freep(&c->packet_buffer);
2546                 } else {
2547                     /* send RTP packet directly in UDP */
2548                     c->buffer_ptr += 4;
2549                     ffurl_write(c->rtp_handles[c->packet_stream_index],
2550                                 c->buffer_ptr, len);
2551                     c->buffer_ptr += len;
2552                     /* here we continue as we can send several packets per 10 ms slot */
2553                 }
2554             } else {
2555                 /* TCP data output */
2556                 len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
2557                 if (len < 0) {
2558                     if (ff_neterrno() != AVERROR(EAGAIN) &&
2559                         ff_neterrno() != AVERROR(EINTR))
2560                         /* error : close connection */
2561                         return -1;
2562                     else
2563                         return 0;
2564                 } else
2565                     c->buffer_ptr += len;
2566
2567                 c->data_count += len;
2568                 update_datarate(&c->datarate, c->data_count);
2569                 if (c->stream)
2570                     c->stream->bytes_served += len;
2571                 break;
2572             }
2573         }
2574     } /* for(;;) */
2575     return 0;
2576 }
2577
2578 static int http_start_receive_data(HTTPContext *c)
2579 {
2580     int fd;
2581
2582     if (c->stream->feed_opened)
2583         return -1;
2584
2585     /* Don't permit writing to this one */
2586     if (c->stream->readonly)
2587         return -1;
2588
2589     /* open feed */
2590     fd = open(c->stream->feed_filename, O_RDWR);
2591     if (fd < 0) {
2592         http_log("Error opening feeder file: %s\n", strerror(errno));
2593         return -1;
2594     }
2595     c->feed_fd = fd;
2596
2597     if (c->stream->truncate) {
2598         /* truncate feed file */
2599         ffm_write_write_index(c->feed_fd, FFM_PACKET_SIZE);
2600         http_log("Truncating feed file '%s'\n", c->stream->feed_filename);
2601         if (ftruncate(c->feed_fd, FFM_PACKET_SIZE) < 0) {
2602             http_log("Error truncating feed file: %s\n", strerror(errno));
2603             return -1;
2604         }
2605     } else {
2606         if ((c->stream->feed_write_index = ffm_read_write_index(fd)) < 0) {
2607             http_log("Error reading write index from feed file: %s\n", strerror(errno));
2608             return -1;
2609         }
2610     }
2611
2612     c->stream->feed_write_index = FFMAX(ffm_read_write_index(fd), FFM_PACKET_SIZE);
2613     c->stream->feed_size = lseek(fd, 0, SEEK_END);
2614     lseek(fd, 0, SEEK_SET);
2615
2616     /* init buffer input */
2617     c->buffer_ptr = c->buffer;
2618     c->buffer_end = c->buffer + FFM_PACKET_SIZE;
2619     c->stream->feed_opened = 1;
2620     c->chunked_encoding = !!av_stristr(c->buffer, "Transfer-Encoding: chunked");
2621     return 0;
2622 }
2623
2624 static int http_receive_data(HTTPContext *c)
2625 {
2626     HTTPContext *c1;
2627     int len, loop_run = 0;
2628
2629     while (c->chunked_encoding && !c->chunk_size &&
2630            c->buffer_end > c->buffer_ptr) {
2631         /* read chunk header, if present */
2632         len = recv(c->fd, c->buffer_ptr, 1, 0);
2633
2634         if (len < 0) {
2635             if (ff_neterrno() != AVERROR(EAGAIN) &&
2636                 ff_neterrno() != AVERROR(EINTR))
2637                 /* error : close connection */
2638                 goto fail;
2639             return 0;
2640         } else if (len == 0) {
2641             /* end of connection : close it */
2642             goto fail;
2643         } else if (c->buffer_ptr - c->buffer >= 2 &&
2644                    !memcmp(c->buffer_ptr - 1, "\r\n", 2)) {
2645             c->chunk_size = strtol(c->buffer, 0, 16);
2646             if (c->chunk_size == 0) // end of stream
2647                 goto fail;
2648             c->buffer_ptr = c->buffer;
2649             break;
2650         } else if (++loop_run > 10) {
2651             /* no chunk header, abort */
2652             goto fail;
2653         } else {
2654             c->buffer_ptr++;
2655         }
2656     }
2657
2658     if (c->buffer_end > c->buffer_ptr) {
2659         len = recv(c->fd, c->buffer_ptr,
2660                    FFMIN(c->chunk_size, c->buffer_end - c->buffer_ptr), 0);
2661         if (len < 0) {
2662             if (ff_neterrno() != AVERROR(EAGAIN) &&
2663                 ff_neterrno() != AVERROR(EINTR))
2664                 /* error : close connection */
2665                 goto fail;
2666         } else if (len == 0)
2667             /* end of connection : close it */
2668             goto fail;
2669         else {
2670             c->chunk_size -= len;
2671             c->buffer_ptr += len;
2672             c->data_count += len;
2673             update_datarate(&c->datarate, c->data_count);
2674         }
2675     }
2676
2677     if (c->buffer_ptr - c->buffer >= 2 && c->data_count > FFM_PACKET_SIZE) {
2678         if (c->buffer[0] != 'f' ||
2679             c->buffer[1] != 'm') {
2680             http_log("Feed stream has become desynchronized -- disconnecting\n");
2681             goto fail;
2682         }
2683     }
2684
2685     if (c->buffer_ptr >= c->buffer_end) {
2686         FFStream *feed = c->stream;
2687         /* a packet has been received : write it in the store, except
2688            if header */
2689         if (c->data_count > FFM_PACKET_SIZE) {
2690             /* XXX: use llseek or url_seek */
2691             lseek(c->feed_fd, feed->feed_write_index, SEEK_SET);
2692             if (write(c->feed_fd, c->buffer, FFM_PACKET_SIZE) < 0) {
2693                 http_log("Error writing to feed file: %s\n", strerror(errno));
2694                 goto fail;
2695             }
2696
2697             feed->feed_write_index += FFM_PACKET_SIZE;
2698             /* update file size */
2699             if (feed->feed_write_index > c->stream->feed_size)
2700                 feed->feed_size = feed->feed_write_index;
2701
2702             /* handle wrap around if max file size reached */
2703             if (c->stream->feed_max_size && feed->feed_write_index >= c->stream->feed_max_size)
2704                 feed->feed_write_index = FFM_PACKET_SIZE;
2705
2706             /* write index */
2707             if (ffm_write_write_index(c->feed_fd, feed->feed_write_index) < 0) {
2708                 http_log("Error writing index to feed file: %s\n", strerror(errno));
2709                 goto fail;
2710             }
2711
2712             /* wake up any waiting connections */
2713             for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
2714                 if (c1->state == HTTPSTATE_WAIT_FEED &&
2715                     c1->stream->feed == c->stream->feed)
2716                     c1->state = HTTPSTATE_SEND_DATA;
2717             }
2718         } else {
2719             /* We have a header in our hands that contains useful data */
2720             AVFormatContext *s = avformat_alloc_context();
2721             AVIOContext *pb;
2722             AVInputFormat *fmt_in;
2723             int i;
2724
2725             if (!s)
2726                 goto fail;
2727
2728             /* use feed output format name to find corresponding input format */
2729             fmt_in = av_find_input_format(feed->fmt->name);
2730             if (!fmt_in)
2731                 goto fail;
2732
2733             pb = avio_alloc_context(c->buffer, c->buffer_end - c->buffer,
2734                                     0, NULL, NULL, NULL, NULL);
2735             pb->seekable = 0;
2736
2737             s->pb = pb;
2738             if (avformat_open_input(&s, c->stream->feed_filename, fmt_in, NULL) < 0) {
2739                 av_free(pb);
2740                 goto fail;
2741             }
2742
2743             /* Now we have the actual streams */
2744             if (s->nb_streams != feed->nb_streams) {
2745                 avformat_close_input(&s);
2746                 av_free(pb);
2747                 http_log("Feed '%s' stream number does not match registered feed\n",
2748                          c->stream->feed_filename);
2749                 goto fail;
2750             }
2751
2752             for (i = 0; i < s->nb_streams; i++) {
2753                 AVStream *fst = feed->streams[i];
2754                 AVStream *st = s->streams[i];
2755                 avcodec_copy_context(fst->codec, st->codec);
2756             }
2757
2758             avformat_close_input(&s);
2759             av_free(pb);
2760         }
2761         c->buffer_ptr = c->buffer;
2762     }
2763
2764     return 0;
2765  fail:
2766     c->stream->feed_opened = 0;
2767     close(c->feed_fd);
2768     /* wake up any waiting connections to stop waiting for feed */
2769     for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
2770         if (c1->state == HTTPSTATE_WAIT_FEED &&
2771             c1->stream->feed == c->stream->feed)
2772             c1->state = HTTPSTATE_SEND_DATA_TRAILER;
2773     }
2774     return -1;
2775 }
2776
2777 /********************************************************************/
2778 /* RTSP handling */
2779
2780 static void rtsp_reply_header(HTTPContext *c, enum RTSPStatusCode error_number)
2781 {
2782     const char *str;
2783     time_t ti;
2784     struct tm *tm;
2785     char buf2[32];
2786
2787     switch(error_number) {
2788     case RTSP_STATUS_OK:
2789         str = "OK";
2790         break;
2791     case RTSP_STATUS_METHOD:
2792         str = "Method Not Allowed";
2793         break;
2794     case RTSP_STATUS_BANDWIDTH:
2795         str = "Not Enough Bandwidth";
2796         break;
2797     case RTSP_STATUS_SESSION:
2798         str = "Session Not Found";
2799         break;
2800     case RTSP_STATUS_STATE:
2801         str = "Method Not Valid in This State";
2802         break;
2803     case RTSP_STATUS_AGGREGATE:
2804         str = "Aggregate operation not allowed";
2805         break;
2806     case RTSP_STATUS_ONLY_AGGREGATE:
2807         str = "Only aggregate operation allowed";
2808         break;
2809     case RTSP_STATUS_TRANSPORT:
2810         str = "Unsupported transport";
2811         break;
2812     case RTSP_STATUS_INTERNAL:
2813         str = "Internal Server Error";
2814         break;
2815     case RTSP_STATUS_SERVICE:
2816         str = "Service Unavailable";
2817         break;
2818     case RTSP_STATUS_VERSION:
2819         str = "RTSP Version not supported";
2820         break;
2821     default:
2822         str = "Unknown Error";
2823         break;
2824     }
2825
2826     avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", error_number, str);
2827     avio_printf(c->pb, "CSeq: %d\r\n", c->seq);
2828
2829     /* output GMT time */
2830     ti = time(NULL);
2831     tm = gmtime(&ti);
2832     strftime(buf2, sizeof(buf2), "%a, %d %b %Y %H:%M:%S", tm);
2833     avio_printf(c->pb, "Date: %s GMT\r\n", buf2);
2834 }
2835
2836 static void rtsp_reply_error(HTTPContext *c, enum RTSPStatusCode error_number)
2837 {
2838     rtsp_reply_header(c, error_number);
2839     avio_printf(c->pb, "\r\n");
2840 }
2841
2842 static int rtsp_parse_request(HTTPContext *c)
2843 {
2844     const char *p, *p1, *p2;
2845     char cmd[32];
2846     char url[1024];
2847     char protocol[32];
2848     char line[1024];
2849     int len;
2850     RTSPMessageHeader header1 = { 0 }, *header = &header1;
2851
2852     c->buffer_ptr[0] = '\0';
2853     p = c->buffer;
2854
2855     get_word(cmd, sizeof(cmd), &p);
2856     get_word(url, sizeof(url), &p);
2857     get_word(protocol, sizeof(protocol), &p);
2858
2859     av_strlcpy(c->method, cmd, sizeof(c->method));
2860     av_strlcpy(c->url, url, sizeof(c->url));
2861     av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
2862
2863     if (avio_open_dyn_buf(&c->pb) < 0) {
2864         /* XXX: cannot do more */
2865         c->pb = NULL; /* safety */
2866         return -1;
2867     }
2868
2869     /* check version name */
2870     if (strcmp(protocol, "RTSP/1.0") != 0) {
2871         rtsp_reply_error(c, RTSP_STATUS_VERSION);
2872         goto the_end;
2873     }
2874
2875     /* parse each header line */
2876     /* skip to next line */
2877     while (*p != '\n' && *p != '\0')
2878         p++;
2879     if (*p == '\n')
2880         p++;
2881     while (*p != '\0') {
2882         p1 = memchr(p, '\n', (char *)c->buffer_ptr - p);
2883         if (!p1)
2884             break;
2885         p2 = p1;
2886         if (p2 > p && p2[-1] == '\r')
2887             p2--;
2888         /* skip empty line */
2889         if (p2 == p)
2890             break;
2891         len = p2 - p;
2892         if (len > sizeof(line) - 1)
2893             len = sizeof(line) - 1;
2894         memcpy(line, p, len);
2895         line[len] = '\0';
2896         ff_rtsp_parse_line(header, line, NULL, NULL);
2897         p = p1 + 1;
2898     }
2899
2900     /* handle sequence number */
2901     c->seq = header->seq;
2902
2903     if (!strcmp(cmd, "DESCRIBE"))
2904         rtsp_cmd_describe(c, url);
2905     else if (!strcmp(cmd, "OPTIONS"))
2906         rtsp_cmd_options(c, url);
2907     else if (!strcmp(cmd, "SETUP"))
2908         rtsp_cmd_setup(c, url, header);
2909     else if (!strcmp(cmd, "PLAY"))
2910         rtsp_cmd_play(c, url, header);
2911     else if (!strcmp(cmd, "PAUSE"))
2912         rtsp_cmd_pause(c, url, header);
2913     else if (!strcmp(cmd, "TEARDOWN"))
2914         rtsp_cmd_teardown(c, url, header);
2915     else
2916         rtsp_reply_error(c, RTSP_STATUS_METHOD);
2917
2918  the_end:
2919     len = avio_close_dyn_buf(c->pb, &c->pb_buffer);
2920     c->pb = NULL; /* safety */
2921     if (len < 0) {
2922         /* XXX: cannot do more */
2923         return -1;
2924     }
2925     c->buffer_ptr = c->pb_buffer;
2926     c->buffer_end = c->pb_buffer + len;
2927     c->state = RTSPSTATE_SEND_REPLY;
2928     return 0;
2929 }
2930
2931 static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
2932                                    struct in_addr my_ip)
2933 {
2934     AVFormatContext *avc;
2935     AVStream *avs = NULL;
2936     int i;
2937
2938     avc =  avformat_alloc_context();
2939     if (avc == NULL) {
2940         return -1;
2941     }
2942     av_dict_set(&avc->metadata, "title",
2943                stream->title[0] ? stream->title : "No Title", 0);
2944     avc->nb_streams = stream->nb_streams;
2945     if (stream->is_multicast) {
2946         snprintf(avc->filename, 1024, "rtp://%s:%d?multicast=1?ttl=%d",
2947                  inet_ntoa(stream->multicast_ip),
2948                  stream->multicast_port, stream->multicast_ttl);
2949     } else {
2950         snprintf(avc->filename, 1024, "rtp://0.0.0.0");
2951     }
2952
2953     if (avc->nb_streams >= INT_MAX/sizeof(*avc->streams) ||
2954         !(avc->streams = av_malloc(avc->nb_streams * sizeof(*avc->streams))))
2955         goto sdp_done;
2956     if (avc->nb_streams >= INT_MAX/sizeof(*avs) ||
2957         !(avs = av_malloc(avc->nb_streams * sizeof(*avs))))
2958         goto sdp_done;
2959
2960     for(i = 0; i < stream->nb_streams; i++) {
2961         avc->streams[i] = &avs[i];
2962         avc->streams[i]->codec = stream->streams[i]->codec;
2963     }
2964     *pbuffer = av_mallocz(2048);
2965     av_sdp_create(&avc, 1, *pbuffer, 2048);
2966
2967  sdp_done:
2968     av_free(avc->streams);
2969     av_dict_free(&avc->metadata);
2970     av_free(avc);
2971     av_free(avs);
2972
2973     return strlen(*pbuffer);
2974 }
2975
2976 static void rtsp_cmd_options(HTTPContext *c, const char *url)
2977 {
2978 //    rtsp_reply_header(c, RTSP_STATUS_OK);
2979     avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", RTSP_STATUS_OK, "OK");
2980     avio_printf(c->pb, "CSeq: %d\r\n", c->seq);
2981     avio_printf(c->pb, "Public: %s\r\n", "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
2982     avio_printf(c->pb, "\r\n");
2983 }
2984
2985 static void rtsp_cmd_describe(HTTPContext *c, const char *url)
2986 {
2987     FFStream *stream;
2988     char path1[1024];
2989     const char *path;
2990     uint8_t *content;
2991     int content_length;
2992     socklen_t len;
2993     struct sockaddr_in my_addr;
2994
2995     /* find which url is asked */
2996     av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
2997     path = path1;
2998     if (*path == '/')
2999         path++;
3000
3001     for(stream = first_stream; stream != NULL; stream = stream->next) {
3002         if (!stream->is_feed &&
3003             stream->fmt && !strcmp(stream->fmt->name, "rtp") &&
3004             !strcmp(path, stream->filename)) {
3005             goto found;
3006         }
3007     }
3008     /* no stream found */
3009     rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
3010     return;
3011
3012  found:
3013     /* prepare the media description in sdp format */
3014
3015     /* get the host IP */
3016     len = sizeof(my_addr);
3017     getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
3018     content_length = prepare_sdp_description(stream, &content, my_addr.sin_addr);
3019     if (content_length < 0) {
3020         rtsp_reply_error(c, RTSP_STATUS_INTERNAL);
3021         return;
3022     }
3023     rtsp_reply_header(c, RTSP_STATUS_OK);
3024     avio_printf(c->pb, "Content-Base: %s/\r\n", url);
3025     avio_printf(c->pb, "Content-Type: application/sdp\r\n");
3026     avio_printf(c->pb, "Content-Length: %d\r\n", content_length);
3027     avio_printf(c->pb, "\r\n");
3028     avio_write(c->pb, content, content_length);
3029     av_free(content);
3030 }
3031
3032 static HTTPContext *find_rtp_session(const char *session_id)
3033 {
3034     HTTPContext *c;
3035
3036     if (session_id[0] == '\0')
3037         return NULL;
3038
3039     for(c = first_http_ctx; c != NULL; c = c->next) {
3040         if (!strcmp(c->session_id, session_id))
3041             return c;
3042     }
3043     return NULL;
3044 }
3045
3046 static RTSPTransportField *find_transport(RTSPMessageHeader *h, enum RTSPLowerTransport lower_transport)
3047 {
3048     RTSPTransportField *th;
3049     int i;
3050
3051     for(i=0;i<h->nb_transports;i++) {
3052         th = &h->transports[i];
3053         if (th->lower_transport == lower_transport)
3054             return th;
3055     }
3056     return NULL;
3057 }
3058
3059 static void rtsp_cmd_setup(HTTPContext *c, const char *url,
3060                            RTSPMessageHeader *h)
3061 {
3062     FFStream *stream;
3063     int stream_index, rtp_port, rtcp_port;
3064     char buf[1024];
3065     char path1[1024];
3066     const char *path;
3067     HTTPContext *rtp_c;
3068     RTSPTransportField *th;
3069     struct sockaddr_in dest_addr;
3070     RTSPActionServerSetup setup;
3071
3072     /* find which url is asked */
3073     av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3074     path = path1;
3075     if (*path == '/')
3076         path++;
3077
3078     /* now check each stream */
3079     for(stream = first_stream; stream != NULL; stream = stream->next) {
3080         if (!stream->is_feed &&
3081             stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
3082             /* accept aggregate filenames only if single stream */
3083             if (!strcmp(path, stream->filename)) {
3084                 if (stream->nb_streams != 1) {
3085                     rtsp_reply_error(c, RTSP_STATUS_AGGREGATE);
3086                     return;
3087                 }
3088                 stream_index = 0;
3089                 goto found;
3090             }
3091
3092             for(stream_index = 0; stream_index < stream->nb_streams;
3093                 stream_index++) {
3094                 snprintf(buf, sizeof(buf), "%s/streamid=%d",
3095                          stream->filename, stream_index);
3096                 if (!strcmp(path, buf))
3097                     goto found;
3098             }
3099         }
3100     }
3101     /* no stream found */
3102     rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
3103     return;
3104  found:
3105
3106     /* generate session id if needed */
3107     if (h->session_id[0] == '\0')
3108         snprintf(h->session_id, sizeof(h->session_id), "%08x%08x",
3109                  av_lfg_get(&random_state), av_lfg_get(&random_state));
3110
3111     /* find rtp session, and create it if none found */
3112     rtp_c = find_rtp_session(h->session_id);
3113     if (!rtp_c) {
3114         /* always prefer UDP */
3115         th = find_transport(h, RTSP_LOWER_TRANSPORT_UDP);
3116         if (!th) {
3117             th = find_transport(h, RTSP_LOWER_TRANSPORT_TCP);
3118             if (!th) {
3119                 rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3120                 return;
3121             }
3122         }
3123
3124         rtp_c = rtp_new_connection(&c->from_addr, stream, h->session_id,
3125                                    th->lower_transport);
3126         if (!rtp_c) {
3127             rtsp_reply_error(c, RTSP_STATUS_BANDWIDTH);
3128             return;
3129         }
3130
3131         /* open input stream */
3132         if (open_input_stream(rtp_c, "") < 0) {
3133             rtsp_reply_error(c, RTSP_STATUS_INTERNAL);
3134             return;
3135         }
3136     }
3137
3138     /* test if stream is OK (test needed because several SETUP needs
3139        to be done for a given file) */
3140     if (rtp_c->stream != stream) {
3141         rtsp_reply_error(c, RTSP_STATUS_SERVICE);
3142         return;
3143     }
3144
3145     /* test if stream is already set up */
3146     if (rtp_c->rtp_ctx[stream_index]) {
3147         rtsp_reply_error(c, RTSP_STATUS_STATE);
3148         return;
3149     }
3150
3151     /* check transport */
3152     th = find_transport(h, rtp_c->rtp_protocol);
3153     if (!th || (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
3154                 th->client_port_min <= 0)) {
3155         rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3156         return;
3157     }
3158
3159     /* setup default options */
3160     setup.transport_option[0] = '\0';
3161     dest_addr = rtp_c->from_addr;
3162     dest_addr.sin_port = htons(th->client_port_min);
3163
3164     /* setup stream */
3165     if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, c) < 0) {
3166         rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3167         return;
3168     }
3169
3170     /* now everything is OK, so we can send the connection parameters */
3171     rtsp_reply_header(c, RTSP_STATUS_OK);
3172     /* session ID */
3173     avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3174
3175     switch(rtp_c->rtp_protocol) {
3176     case RTSP_LOWER_TRANSPORT_UDP:
3177         rtp_port = ff_rtp_get_local_rtp_port(rtp_c->rtp_handles[stream_index]);
3178         rtcp_port = ff_rtp_get_local_rtcp_port(rtp_c->rtp_handles[stream_index]);
3179         avio_printf(c->pb, "Transport: RTP/AVP/UDP;unicast;"
3180                     "client_port=%d-%d;server_port=%d-%d",
3181                     th->client_port_min, th->client_port_max,
3182                     rtp_port, rtcp_port);
3183         break;
3184     case RTSP_LOWER_TRANSPORT_TCP:
3185         avio_printf(c->pb, "Transport: RTP/AVP/TCP;interleaved=%d-%d",
3186                     stream_index * 2, stream_index * 2 + 1);
3187         break;
3188     default:
3189         break;
3190     }
3191     if (setup.transport_option[0] != '\0')
3192         avio_printf(c->pb, ";%s", setup.transport_option);
3193     avio_printf(c->pb, "\r\n");
3194
3195
3196     avio_printf(c->pb, "\r\n");
3197 }
3198
3199
3200 /* find an rtp connection by using the session ID. Check consistency
3201    with filename */
3202 static HTTPContext *find_rtp_session_with_url(const char *url,
3203                                               const char *session_id)
3204 {
3205     HTTPContext *rtp_c;
3206     char path1[1024];
3207     const char *path;
3208     char buf[1024];
3209     int s, len;
3210
3211     rtp_c = find_rtp_session(session_id);
3212     if (!rtp_c)
3213         return NULL;
3214
3215     /* find which url is asked */
3216     av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3217     path = path1;
3218     if (*path == '/')
3219         path++;
3220     if(!strcmp(path, rtp_c->stream->filename)) return rtp_c;
3221     for(s=0; s<rtp_c->stream->nb_streams; ++s) {
3222       snprintf(buf, sizeof(buf), "%s/streamid=%d",
3223         rtp_c->stream->filename, s);
3224       if(!strncmp(path, buf, sizeof(buf))) {
3225     // XXX: Should we reply with RTSP_STATUS_ONLY_AGGREGATE if nb_streams>1?
3226         return rtp_c;
3227       }
3228     }
3229     len = strlen(path);
3230     if (len > 0 && path[len - 1] == '/' &&
3231         !strncmp(path, rtp_c->stream->filename, len - 1))
3232         return rtp_c;
3233     return NULL;
3234 }
3235
3236 static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3237 {
3238     HTTPContext *rtp_c;
3239
3240     rtp_c = find_rtp_session_with_url(url, h->session_id);
3241     if (!rtp_c) {
3242         rtsp_reply_error(c, RTSP_STATUS_SESSION);
3243         return;
3244     }
3245
3246     if (rtp_c->state != HTTPSTATE_SEND_DATA &&
3247         rtp_c->state != HTTPSTATE_WAIT_FEED &&
3248         rtp_c->state != HTTPSTATE_READY) {
3249         rtsp_reply_error(c, RTSP_STATUS_STATE);
3250         return;
3251     }
3252
3253     rtp_c->state = HTTPSTATE_SEND_DATA;
3254
3255     /* now everything is OK, so we can send the connection parameters */
3256     rtsp_reply_header(c, RTSP_STATUS_OK);
3257     /* session ID */
3258     avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3259     avio_printf(c->pb, "\r\n");
3260 }
3261
3262 static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3263 {
3264     HTTPContext *rtp_c;
3265
3266     rtp_c = find_rtp_session_with_url(url, h->session_id);
3267     if (!rtp_c) {
3268         rtsp_reply_error(c, RTSP_STATUS_SESSION);
3269         return;
3270     }
3271
3272     if (rtp_c->state != HTTPSTATE_SEND_DATA &&
3273         rtp_c->state != HTTPSTATE_WAIT_FEED) {
3274         rtsp_reply_error(c, RTSP_STATUS_STATE);
3275         return;
3276     }
3277
3278     rtp_c->state = HTTPSTATE_READY;
3279     rtp_c->first_pts = AV_NOPTS_VALUE;
3280     /* now everything is OK, so we can send the connection parameters */
3281     rtsp_reply_header(c, RTSP_STATUS_OK);
3282     /* session ID */
3283     avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3284     avio_printf(c->pb, "\r\n");
3285 }
3286
3287 static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3288 {
3289     HTTPContext *rtp_c;
3290
3291     rtp_c = find_rtp_session_with_url(url, h->session_id);
3292     if (!rtp_c) {
3293         rtsp_reply_error(c, RTSP_STATUS_SESSION);
3294         return;
3295     }
3296
3297     /* now everything is OK, so we can send the connection parameters */
3298     rtsp_reply_header(c, RTSP_STATUS_OK);
3299     /* session ID */
3300     avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3301     avio_printf(c->pb, "\r\n");
3302
3303     /* abort the session */
3304     close_connection(rtp_c);
3305 }
3306
3307
3308 /********************************************************************/
3309 /* RTP handling */
3310
3311 static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
3312                                        FFStream *stream, const char *session_id,
3313                                        enum RTSPLowerTransport rtp_protocol)
3314 {
3315     HTTPContext *c = NULL;
3316     const char *proto_str;
3317
3318     /* XXX: should output a warning page when coming
3319        close to the connection limit */
3320     if (nb_connections >= nb_max_connections)
3321         goto fail;
3322
3323     /* add a new connection */
3324     c = av_mallocz(sizeof(HTTPContext));
3325     if (!c)
3326         goto fail;
3327
3328     c->fd = -1;
3329     c->poll_entry = NULL;
3330     c->from_addr = *from_addr;
3331     c->buffer_size = IOBUFFER_INIT_SIZE;
3332     c->buffer = av_malloc(c->buffer_size);
3333     if (!c->buffer)
3334         goto fail;
3335     nb_connections++;
3336     c->stream = stream;
3337     av_strlcpy(c->session_id, session_id, sizeof(c->session_id));
3338     c->state = HTTPSTATE_READY;
3339     c->is_packetized = 1;
3340     c->rtp_protocol = rtp_protocol;
3341
3342     /* protocol is shown in statistics */
3343     switch(c->rtp_protocol) {
3344     case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
3345         proto_str = "MCAST";
3346         break;
3347     case RTSP_LOWER_TRANSPORT_UDP:
3348         proto_str = "UDP";
3349         break;
3350     case RTSP_LOWER_TRANSPORT_TCP:
3351         proto_str = "TCP";
3352         break;
3353     default:
3354         proto_str = "???";
3355         break;
3356     }
3357     av_strlcpy(c->protocol, "RTP/", sizeof(c->protocol));
3358     av_strlcat(c->protocol, proto_str, sizeof(c->protocol));
3359
3360     current_bandwidth += stream->bandwidth;
3361
3362     c->next = first_http_ctx;
3363     first_http_ctx = c;
3364     return c;
3365
3366  fail:
3367     if (c) {
3368         av_free(c->buffer);
3369         av_free(c);
3370     }
3371     return NULL;
3372 }
3373
3374 /* add a new RTP stream in an RTP connection (used in RTSP SETUP
3375    command). If RTP/TCP protocol is used, TCP connection 'rtsp_c' is
3376    used. */
3377 static int rtp_new_av_stream(HTTPContext *c,
3378                              int stream_index, struct sockaddr_in *dest_addr,
3379                              HTTPContext *rtsp_c)
3380 {
3381     AVFormatContext *ctx;
3382     AVStream *st;
3383     char *ipaddr;
3384     URLContext *h = NULL;
3385     uint8_t *dummy_buf;
3386     int max_packet_size;
3387
3388     /* now we can open the relevant output stream */
3389     ctx = avformat_alloc_context();
3390     if (!ctx)
3391         return -1;
3392     ctx->oformat = av_guess_format("rtp", NULL, NULL);
3393
3394     st = av_mallocz(sizeof(AVStream));
3395     if (!st)
3396         goto fail;
3397     ctx->nb_streams = 1;
3398     ctx->streams = av_mallocz(sizeof(AVStream *) * ctx->nb_streams);
3399     if (!ctx->streams)
3400       goto fail;
3401     ctx->streams[0] = st;
3402
3403     if (!c->stream->feed ||
3404         c->stream->feed == c->stream)
3405         memcpy(st, c->stream->streams[stream_index], sizeof(AVStream));
3406     else
3407         memcpy(st,
3408                c->stream->feed->streams[c->stream->feed_streams[stream_index]],
3409                sizeof(AVStream));
3410     st->priv_data = NULL;
3411
3412     /* build destination RTP address */
3413     ipaddr = inet_ntoa(dest_addr->sin_addr);
3414
3415     switch(c->rtp_protocol) {
3416     case RTSP_LOWER_TRANSPORT_UDP:
3417     case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
3418         /* RTP/UDP case */
3419
3420         /* XXX: also pass as parameter to function ? */
3421         if (c->stream->is_multicast) {
3422             int ttl;
3423             ttl = c->stream->multicast_ttl;
3424             if (!ttl)
3425                 ttl = 16;
3426             snprintf(ctx->filename, sizeof(ctx->filename),
3427                      "rtp://%s:%d?multicast=1&ttl=%d",
3428                      ipaddr, ntohs(dest_addr->sin_port), ttl);
3429         } else {
3430             snprintf(ctx->filename, sizeof(ctx->filename),
3431                      "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
3432         }
3433
3434         if (ffurl_open(&h, ctx->filename, AVIO_FLAG_WRITE, NULL, NULL) < 0)
3435             goto fail;
3436         c->rtp_handles[stream_index] = h;
3437         max_packet_size = h->max_packet_size;
3438         break;
3439     case RTSP_LOWER_TRANSPORT_TCP:
3440         /* RTP/TCP case */
3441         c->rtsp_c = rtsp_c;
3442         max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
3443         break;
3444     default:
3445         goto fail;
3446     }
3447
3448     http_log("%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
3449              ipaddr, ntohs(dest_addr->sin_port),
3450              c->stream->filename, stream_index, c->protocol);
3451
3452     /* normally, no packets should be output here, but the packet size may be checked */
3453     if (ffio_open_dyn_packet_buf(&ctx->pb, max_packet_size) < 0) {
3454         /* XXX: close stream */
3455         goto fail;
3456     }
3457     if (avformat_write_header(ctx, NULL) < 0) {
3458     fail:
3459         if (h)
3460             ffurl_close(h);
3461         av_free(ctx);
3462         return -1;
3463     }
3464     avio_close_dyn_buf(ctx->pb, &dummy_buf);
3465     av_free(dummy_buf);
3466
3467     c->rtp_ctx[stream_index] = ctx;
3468     return 0;
3469 }
3470
3471 /********************************************************************/
3472 /* avserver initialization */
3473
3474 static AVStream *add_av_stream1(FFStream *stream, AVCodecContext *codec, int copy)
3475 {
3476     AVStream *fst;
3477
3478     fst = av_mallocz(sizeof(AVStream));
3479     if (!fst)
3480         return NULL;
3481     if (copy) {
3482         fst->codec = avcodec_alloc_context3(NULL);
3483         memcpy(fst->codec, codec, sizeof(AVCodecContext));
3484         if (codec->extradata_size) {
3485             fst->codec->extradata = av_malloc(codec->extradata_size);
3486             memcpy(fst->codec->extradata, codec->extradata,
3487                 codec->extradata_size);
3488         }
3489     } else {
3490         /* live streams must use the actual feed's codec since it may be
3491          * updated later to carry extradata needed by the streams.
3492          */
3493         fst->codec = codec;
3494     }
3495     fst->priv_data = av_mallocz(sizeof(FeedData));
3496     fst->index = stream->nb_streams;
3497     avpriv_set_pts_info(fst, 33, 1, 90000);
3498     fst->sample_aspect_ratio = codec->sample_aspect_ratio;
3499     stream->streams[stream->nb_streams++] = fst;
3500     return fst;
3501 }
3502
3503 /* return the stream number in the feed */
3504 static int add_av_stream(FFStream *feed, AVStream *st)
3505 {
3506     AVStream *fst;
3507     AVCodecContext *av, *av1;
3508     int i;
3509
3510     av = st->codec;
3511     for(i=0;i<feed->nb_streams;i++) {
3512         st = feed->streams[i];
3513         av1 = st->codec;
3514         if (av1->codec_id == av->codec_id &&
3515             av1->codec_type == av->codec_type &&
3516             av1->bit_rate == av->bit_rate) {
3517
3518             switch(av->codec_type) {
3519             case AVMEDIA_TYPE_AUDIO:
3520                 if (av1->channels == av->channels &&
3521                     av1->sample_rate == av->sample_rate)
3522                     return i;
3523                 break;
3524             case AVMEDIA_TYPE_VIDEO:
3525                 if (av1->width == av->width &&
3526                     av1->height == av->height &&
3527                     av1->time_base.den == av->time_base.den &&
3528                     av1->time_base.num == av->time_base.num &&
3529                     av1->gop_size == av->gop_size)
3530                     return i;
3531                 break;
3532             default:
3533                 abort();
3534             }
3535         }
3536     }
3537
3538     fst = add_av_stream1(feed, av, 0);
3539     if (!fst)
3540         return -1;
3541     return feed->nb_streams - 1;
3542 }
3543
3544 static void remove_stream(FFStream *stream)
3545 {
3546     FFStream **ps;
3547     ps = &first_stream;
3548     while (*ps != NULL) {
3549         if (*ps == stream)
3550             *ps = (*ps)->next;
3551         else
3552             ps = &(*ps)->next;
3553     }
3554 }
3555
3556 /* specific mpeg4 handling : we extract the raw parameters */
3557 static void extract_mpeg4_header(AVFormatContext *infile)
3558 {
3559     int mpeg4_count, i, size;
3560     AVPacket pkt;
3561     AVStream *st;
3562     const uint8_t *p;
3563
3564     mpeg4_count = 0;
3565     for(i=0;i<infile->nb_streams;i++) {
3566         st = infile->streams[i];
3567         if (st->codec->codec_id == AV_CODEC_ID_MPEG4 &&
3568             st->codec->extradata_size == 0) {
3569             mpeg4_count++;
3570         }
3571     }
3572     if (!mpeg4_count)
3573         return;
3574
3575     printf("MPEG4 without extra data: trying to find header in %s\n", infile->filename);
3576     while (mpeg4_count > 0) {
3577         if (av_read_packet(infile, &pkt) < 0)
3578             break;
3579         st = infile->streams[pkt.stream_index];
3580         if (st->codec->codec_id == AV_CODEC_ID_MPEG4 &&
3581             st->codec->extradata_size == 0) {
3582             av_freep(&st->codec->extradata);
3583             /* fill extradata with the header */
3584             /* XXX: we make hard suppositions here ! */
3585             p = pkt.data;
3586             while (p < pkt.data + pkt.size - 4) {
3587                 /* stop when vop header is found */
3588                 if (p[0] == 0x00 && p[1] == 0x00 &&
3589                     p[2] == 0x01 && p[3] == 0xb6) {
3590                     size = p - pkt.data;
3591                     //                    av_hex_dump_log(infile, AV_LOG_DEBUG, pkt.data, size);
3592                     st->codec->extradata = av_malloc(size);
3593                     st->codec->extradata_size = size;
3594                     memcpy(st->codec->extradata, pkt.data, size);
3595                     break;
3596                 }
3597                 p++;
3598             }
3599             mpeg4_count--;
3600         }
3601         av_free_packet(&pkt);
3602     }
3603 }
3604
3605 /* compute the needed AVStream for each file */
3606 static void build_file_streams(void)
3607 {
3608     FFStream *stream, *stream_next;
3609     int i, ret;
3610
3611     /* gather all streams */
3612     for(stream = first_stream; stream != NULL; stream = stream_next) {
3613         AVFormatContext *infile = NULL;
3614         stream_next = stream->next;
3615         if (stream->stream_type == STREAM_TYPE_LIVE &&
3616             !stream->feed) {
3617             /* the stream comes from a file */
3618             /* try to open the file */
3619             /* open stream */
3620             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                 av_dict_set(&stream->in_opts, "mpeg2ts_compute_pcr", "1", 0);
3624             }
3625
3626             http_log("Opening file '%s'\n", stream->feed_filename);
3627             if ((ret = avformat_open_input(&infile, stream->feed_filename, stream->ifmt, &stream->in_opts)) < 0) {
3628                 http_log("Could not open '%s': %d\n", stream->feed_filename, ret);
3629                 /* remove stream (no need to spend more time on it) */
3630             fail:
3631                 remove_stream(stream);
3632             } else {
3633                 /* find all the AVStreams inside and reference them in
3634                    'stream' */
3635                 if (avformat_find_stream_info(infile, NULL) < 0) {
3636                     http_log("Could not find codec parameters from '%s'\n",
3637                              stream->feed_filename);
3638                     avformat_close_input(&infile);
3639                     goto fail;
3640                 }
3641                 extract_mpeg4_header(infile);
3642
3643                 for(i=0;i<infile->nb_streams;i++)
3644                     add_av_stream1(stream, infile->streams[i]->codec, 1);
3645
3646                 avformat_close_input(&infile);
3647             }
3648         }
3649     }
3650 }
3651
3652 /* compute the needed AVStream for each feed */
3653 static void build_feed_streams(void)
3654 {
3655     FFStream *stream, *feed;
3656     int i;
3657
3658     /* gather all streams */
3659     for(stream = first_stream; stream != NULL; stream = stream->next) {
3660         feed = stream->feed;
3661         if (feed) {
3662             if (stream->is_feed) {
3663                 for(i=0;i<stream->nb_streams;i++)
3664                     stream->feed_streams[i] = i;
3665             } else {
3666                 /* we handle a stream coming from a feed */
3667                 for(i=0;i<stream->nb_streams;i++)
3668                     stream->feed_streams[i] = add_av_stream(feed, stream->streams[i]);
3669             }
3670         }
3671     }
3672
3673     /* create feed files if needed */
3674     for(feed = first_feed; feed != NULL; feed = feed->next_feed) {
3675         int fd;
3676
3677         if (avio_check(feed->feed_filename, AVIO_FLAG_READ) > 0) {
3678             /* See if it matches */
3679             AVFormatContext *s = NULL;
3680             int matches = 0;
3681
3682             if (avformat_open_input(&s, feed->feed_filename, NULL, NULL) >= 0) {
3683                 /* Now see if it matches */
3684                 if (s->nb_streams == feed->nb_streams) {
3685                     matches = 1;
3686                     for(i=0;i<s->nb_streams;i++) {
3687                         AVStream *sf, *ss;
3688                         sf = feed->streams[i];
3689                         ss = s->streams[i];
3690
3691                         if (sf->index != ss->index ||
3692                             sf->id != ss->id) {
3693                             http_log("Index & Id do not match for stream %d (%s)\n",
3694                                    i, feed->feed_filename);
3695                             matches = 0;
3696                         } else {
3697                             AVCodecContext *ccf, *ccs;
3698
3699                             ccf = sf->codec;
3700                             ccs = ss->codec;
3701 #define CHECK_CODEC(x)  (ccf->x != ccs->x)
3702
3703                             if (CHECK_CODEC(codec_id) || CHECK_CODEC(codec_type)) {
3704                                 http_log("Codecs do not match for stream %d\n", i);
3705                                 matches = 0;
3706                             } else if (CHECK_CODEC(bit_rate) || CHECK_CODEC(flags)) {
3707                                 http_log("Codec bitrates do not match for stream %d\n", i);
3708                                 matches = 0;
3709                             } else if (ccf->codec_type == AVMEDIA_TYPE_VIDEO) {
3710                                 if (CHECK_CODEC(time_base.den) ||
3711                                     CHECK_CODEC(time_base.num) ||
3712                                     CHECK_CODEC(width) ||
3713                                     CHECK_CODEC(height)) {
3714                                     http_log("Codec width, height and framerate do not match for stream %d\n", i);
3715                                     matches = 0;
3716                                 }
3717                             } else if (ccf->codec_type == AVMEDIA_TYPE_AUDIO) {
3718                                 if (CHECK_CODEC(sample_rate) ||
3719                                     CHECK_CODEC(channels) ||
3720                                     CHECK_CODEC(frame_size)) {
3721                                     http_log("Codec sample_rate, channels, frame_size do not match for stream %d\n", i);
3722                                     matches = 0;
3723                                 }
3724                             } else {
3725                                 http_log("Unknown codec type\n");
3726                                 matches = 0;
3727                             }
3728                         }
3729                         if (!matches)
3730                             break;
3731                     }
3732                 } else
3733                     http_log("Deleting feed file '%s' as stream counts differ (%d != %d)\n",
3734                         feed->feed_filename, s->nb_streams, feed->nb_streams);
3735
3736                 avformat_close_input(&s);
3737             } else
3738                 http_log("Deleting feed file '%s' as it appears to be corrupt\n",
3739                         feed->feed_filename);
3740
3741             if (!matches) {
3742                 if (feed->readonly) {
3743                     http_log("Unable to delete feed file '%s' as it is marked readonly\n",
3744                         feed->feed_filename);
3745                     exit(1);
3746                 }
3747                 unlink(feed->feed_filename);
3748             }
3749         }
3750         if (avio_check(feed->feed_filename, AVIO_FLAG_WRITE) <= 0) {
3751             AVFormatContext s1 = {0}, *s = &s1;
3752
3753             if (feed->readonly) {
3754                 http_log("Unable to create feed file '%s' as it is marked readonly\n",
3755                     feed->feed_filename);
3756                 exit(1);
3757             }
3758
3759             /* only write the header of the ffm file */
3760             if (avio_open(&s->pb, feed->feed_filename, AVIO_FLAG_WRITE) < 0) {
3761                 http_log("Could not open output feed file '%s'\n",
3762                          feed->feed_filename);
3763                 exit(1);
3764             }
3765             s->oformat = feed->fmt;
3766             s->nb_streams = feed->nb_streams;
3767             s->streams = feed->streams;
3768             if (avformat_write_header(s, NULL) < 0) {
3769                 http_log("Container doesn't supports the required parameters\n");
3770                 exit(1);
3771             }
3772             /* XXX: need better api */
3773             av_freep(&s->priv_data);
3774             avio_close(s->pb);
3775         }
3776         /* get feed size and write index */
3777         fd = open(feed->feed_filename, O_RDONLY);
3778         if (fd < 0) {
3779             http_log("Could not open output feed file '%s'\n",
3780                     feed->feed_filename);
3781             exit(1);
3782         }
3783
3784         feed->feed_write_index = FFMAX(ffm_read_write_index(fd), FFM_PACKET_SIZE);
3785         feed->feed_size = lseek(fd, 0, SEEK_END);
3786         /* ensure that we do not wrap before the end of file */
3787         if (feed->feed_max_size && feed->feed_max_size < feed->feed_size)
3788             feed->feed_max_size = feed->feed_size;
3789
3790         close(fd);
3791     }
3792 }
3793
3794 /* compute the bandwidth used by each stream */
3795 static void compute_bandwidth(void)
3796 {
3797     unsigned bandwidth;
3798     int i;
3799     FFStream *stream;
3800
3801     for(stream = first_stream; stream != NULL; stream = stream->next) {
3802         bandwidth = 0;
3803         for(i=0;i<stream->nb_streams;i++) {
3804             AVStream *st = stream->streams[i];
3805             switch(st->codec->codec_type) {
3806             case AVMEDIA_TYPE_AUDIO:
3807             case AVMEDIA_TYPE_VIDEO:
3808                 bandwidth += st->codec->bit_rate;
3809                 break;
3810             default:
3811                 break;
3812             }
3813         }
3814         stream->bandwidth = (bandwidth + 999) / 1000;
3815     }
3816 }
3817
3818 /* add a codec and set the default parameters */
3819 static void add_codec(FFStream *stream, AVCodecContext *av)
3820 {
3821     AVStream *st;
3822
3823     /* compute default parameters */
3824     switch(av->codec_type) {
3825     case AVMEDIA_TYPE_AUDIO:
3826         if (av->bit_rate == 0)
3827             av->bit_rate = 64000;
3828         if (av->sample_rate == 0)
3829             av->sample_rate = 22050;
3830         if (av->channels == 0)
3831             av->channels = 1;
3832         break;
3833     case AVMEDIA_TYPE_VIDEO:
3834         if (av->bit_rate == 0)
3835             av->bit_rate = 64000;
3836         if (av->time_base.num == 0){
3837             av->time_base.den = 5;
3838             av->time_base.num = 1;
3839         }
3840         if (av->width == 0 || av->height == 0) {
3841             av->width = 160;
3842             av->height = 128;
3843         }
3844         /* Bitrate tolerance is less for streaming */
3845         if (av->bit_rate_tolerance == 0)
3846             av->bit_rate_tolerance = FFMAX(av->bit_rate / 4,
3847                       (int64_t)av->bit_rate*av->time_base.num/av->time_base.den);
3848         if (av->qmin == 0)
3849             av->qmin = 3;
3850         if (av->qmax == 0)
3851             av->qmax = 31;
3852         if (av->max_qdiff == 0)
3853             av->max_qdiff = 3;
3854         av->qcompress = 0.5;
3855         av->qblur = 0.5;
3856
3857         if (!av->nsse_weight)
3858             av->nsse_weight = 8;
3859
3860         av->frame_skip_cmp = FF_CMP_DCTMAX;
3861         if (!av->me_method)
3862             av->me_method = ME_EPZS;
3863         av->rc_buffer_aggressivity = 1.0;
3864
3865         if (!av->rc_eq)
3866             av->rc_eq = "tex^qComp";
3867         if (!av->i_quant_factor)
3868             av->i_quant_factor = -0.8;
3869         if (!av->b_quant_factor)
3870             av->b_quant_factor = 1.25;
3871         if (!av->b_quant_offset)
3872             av->b_quant_offset = 1.25;
3873         if (!av->rc_max_rate)
3874             av->rc_max_rate = av->bit_rate * 2;
3875
3876         if (av->rc_max_rate && !av->rc_buffer_size) {
3877             av->rc_buffer_size = av->rc_max_rate;
3878         }
3879
3880
3881         break;
3882     default:
3883         abort();
3884     }
3885
3886     st = av_mallocz(sizeof(AVStream));
3887     if (!st)
3888         return;
3889     st->codec = avcodec_alloc_context3(NULL);
3890     stream->streams[stream->nb_streams++] = st;
3891     memcpy(st->codec, av, sizeof(AVCodecContext));
3892 }
3893
3894 static enum AVCodecID opt_audio_codec(const char *arg)
3895 {
3896     AVCodec *p= avcodec_find_encoder_by_name(arg);
3897
3898     if (p == NULL || p->type != AVMEDIA_TYPE_AUDIO)
3899         return AV_CODEC_ID_NONE;
3900
3901     return p->id;
3902 }
3903
3904 static enum AVCodecID opt_video_codec(const char *arg)
3905 {
3906     AVCodec *p= avcodec_find_encoder_by_name(arg);
3907
3908     if (p == NULL || p->type != AVMEDIA_TYPE_VIDEO)
3909         return AV_CODEC_ID_NONE;
3910
3911     return p->id;
3912 }
3913
3914 /* simplistic plugin support */
3915
3916 #if HAVE_DLOPEN
3917 static void load_module(const char *filename)
3918 {
3919     void *dll;
3920     void (*init_func)(void);
3921     dll = dlopen(filename, RTLD_NOW);
3922     if (!dll) {
3923         fprintf(stderr, "Could not load module '%s' - %s\n",
3924                 filename, dlerror());
3925         return;
3926     }
3927
3928     init_func = dlsym(dll, "avserver_module_init");
3929     if (!init_func) {
3930         fprintf(stderr,
3931                 "%s: init function 'avserver_module_init()' not found\n",
3932                 filename);
3933         dlclose(dll);
3934     }
3935
3936     init_func();
3937 }
3938 #endif
3939
3940 static int avserver_opt_default(const char *opt, const char *arg,
3941                        AVCodecContext *avctx, int type)
3942 {
3943     int ret = 0;
3944     const AVOption *o = av_opt_find(avctx, opt, NULL, type, 0);
3945     if(o)
3946         ret = av_opt_set(avctx, opt, arg, 0);
3947     return ret;
3948 }
3949
3950 static int avserver_opt_preset(const char *arg,
3951                        AVCodecContext *avctx, int type,
3952                        enum AVCodecID *audio_id, enum AVCodecID *video_id)
3953 {
3954     FILE *f=NULL;
3955     char filename[1000], tmp[1000], tmp2[1000], line[1000];
3956     int ret = 0;
3957     AVCodec *codec = avcodec_find_encoder(avctx->codec_id);
3958
3959     if (!(f = get_preset_file(filename, sizeof(filename), arg, 0,
3960                               codec ? codec->name : NULL))) {
3961         fprintf(stderr, "File for preset '%s' not found\n", arg);
3962         return 1;
3963     }
3964
3965     while(!feof(f)){
3966         int e= fscanf(f, "%999[^\n]\n", line) - 1;
3967         if(line[0] == '#' && !e)
3968             continue;
3969         e|= sscanf(line, "%999[^=]=%999[^\n]\n", tmp, tmp2) - 2;
3970         if(e){
3971             fprintf(stderr, "%s: Invalid syntax: '%s'\n", filename, line);
3972             ret = 1;
3973             break;
3974         }
3975         if(!strcmp(tmp, "acodec")){
3976             *audio_id = opt_audio_codec(tmp2);
3977         }else if(!strcmp(tmp, "vcodec")){
3978             *video_id = opt_video_codec(tmp2);
3979         }else if(!strcmp(tmp, "scodec")){
3980             /* opt_subtitle_codec(tmp2); */
3981         }else if(avserver_opt_default(tmp, tmp2, avctx, type) < 0){
3982             fprintf(stderr, "%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", filename, line, tmp, tmp2);
3983             ret = 1;
3984             break;
3985         }
3986     }
3987
3988     fclose(f);
3989
3990     return ret;
3991 }
3992
3993 static AVOutputFormat *avserver_guess_format(const char *short_name, const char *filename,
3994                                              const char *mime_type)
3995 {
3996     AVOutputFormat *fmt = av_guess_format(short_name, filename, mime_type);
3997
3998     if (fmt) {
3999         AVOutputFormat *stream_fmt;
4000         char stream_format_name[64];
4001
4002         snprintf(stream_format_name, sizeof(stream_format_name), "%s_stream", fmt->name);
4003         stream_fmt = av_guess_format(stream_format_name, NULL, NULL);
4004
4005         if (stream_fmt)
4006             fmt = stream_fmt;
4007     }
4008
4009     return fmt;
4010 }
4011
4012 static void report_config_error(const char *filename, int line_num, int *errors, const char *fmt, ...)
4013 {
4014     va_list vl;
4015     va_start(vl, fmt);
4016     fprintf(stderr, "%s:%d: ", filename, line_num);
4017     vfprintf(stderr, fmt, vl);
4018     va_end(vl);
4019
4020     (*errors)++;
4021 }
4022
4023 static int parse_ffconfig(const char *filename)
4024 {
4025     FILE *f;
4026     char line[1024];
4027     char cmd[64];
4028     char arg[1024];
4029     const char *p;
4030     int val, errors, line_num;
4031     FFStream **last_stream, *stream, *redirect;
4032     FFStream **last_feed, *feed, *s;
4033     AVCodecContext audio_enc, video_enc;
4034     enum AVCodecID audio_id, video_id;
4035
4036     f = fopen(filename, "r");
4037     if (!f) {
4038         perror(filename);
4039         return -1;
4040     }
4041
4042     errors = 0;
4043     line_num = 0;
4044     first_stream = NULL;
4045     last_stream = &first_stream;
4046     first_feed = NULL;
4047     last_feed = &first_feed;
4048     stream = NULL;
4049     feed = NULL;
4050     redirect = NULL;
4051     audio_id = AV_CODEC_ID_NONE;
4052     video_id = AV_CODEC_ID_NONE;
4053
4054 #define ERROR(...) report_config_error(filename, line_num, &errors, __VA_ARGS__)
4055     for(;;) {
4056         if (fgets(line, sizeof(line), f) == NULL)
4057             break;
4058         line_num++;
4059         p = line;
4060         while (isspace(*p))
4061             p++;
4062         if (*p == '\0' || *p == '#')
4063             continue;
4064
4065         get_arg(cmd, sizeof(cmd), &p);
4066
4067         if (!av_strcasecmp(cmd, "Port")) {
4068             get_arg(arg, sizeof(arg), &p);
4069             val = atoi(arg);
4070             if (val < 1 || val > 65536) {
4071                 ERROR("Invalid_port: %s\n", arg);
4072             }
4073             my_http_addr.sin_port = htons(val);
4074         } else if (!av_strcasecmp(cmd, "BindAddress")) {
4075             get_arg(arg, sizeof(arg), &p);
4076             if (resolve_host(&my_http_addr.sin_addr, arg) != 0) {
4077                 ERROR("%s:%d: Invalid host/IP address: %s\n", arg);
4078             }
4079         } else if (!av_strcasecmp(cmd, "RTSPPort")) {
4080             get_arg(arg, sizeof(arg), &p);
4081             val = atoi(arg);
4082             if (val < 1 || val > 65536) {
4083                 ERROR("%s:%d: Invalid port: %s\n", arg);
4084             }
4085             my_rtsp_addr.sin_port = htons(atoi(arg));
4086         } else if (!av_strcasecmp(cmd, "RTSPBindAddress")) {
4087             get_arg(arg, sizeof(arg), &p);
4088             if (resolve_host(&my_rtsp_addr.sin_addr, arg) != 0) {
4089                 ERROR("Invalid host/IP address: %s\n", arg);
4090             }
4091         } else if (!av_strcasecmp(cmd, "MaxHTTPConnections")) {
4092             get_arg(arg, sizeof(arg), &p);
4093             val = atoi(arg);
4094             if (val < 1 || val > 65536) {
4095                 ERROR("Invalid MaxHTTPConnections: %s\n", arg);
4096             }
4097             nb_max_http_connections = val;
4098         } else if (!av_strcasecmp(cmd, "MaxClients")) {
4099             get_arg(arg, sizeof(arg), &p);
4100             val = atoi(arg);
4101             if (val < 1 || val > nb_max_http_connections) {
4102                 ERROR("Invalid MaxClients: %s\n", arg);
4103             } else {
4104                 nb_max_connections = val;
4105             }
4106         } else if (!av_strcasecmp(cmd, "MaxBandwidth")) {
4107             int64_t llval;
4108             get_arg(arg, sizeof(arg), &p);
4109             llval = atoll(arg);
4110             if (llval < 10 || llval > 10000000) {
4111                 ERROR("Invalid MaxBandwidth: %s\n", arg);
4112             } else
4113                 max_bandwidth = llval;
4114         } else if (!av_strcasecmp(cmd, "CustomLog")) {
4115             if (!avserver_debug)
4116                 get_arg(logfilename, sizeof(logfilename), &p);
4117         } else if (!av_strcasecmp(cmd, "<Feed")) {
4118             /*********************************************/
4119             /* Feed related options */
4120             char *q;
4121             if (stream || feed) {
4122                 ERROR("Already in a tag\n");
4123             } else {
4124                 feed = av_mallocz(sizeof(FFStream));
4125                 get_arg(feed->filename, sizeof(feed->filename), &p);
4126                 q = strrchr(feed->filename, '>');
4127                 if (*q)
4128                     *q = '\0';
4129
4130                 for (s = first_feed; s; s = s->next) {
4131                     if (!strcmp(feed->filename, s->filename)) {
4132                         ERROR("Feed '%s' already registered\n", s->filename);
4133                     }
4134                 }
4135
4136                 feed->fmt = av_guess_format("ffm", NULL, NULL);
4137                 /* defaut feed file */
4138                 snprintf(feed->feed_filename, sizeof(feed->feed_filename),
4139                          "/tmp/%s.ffm", feed->filename);
4140                 feed->feed_max_size = 5 * 1024 * 1024;
4141                 feed->is_feed = 1;
4142                 feed->feed = feed; /* self feeding :-) */
4143
4144                 /* add in stream list */
4145                 *last_stream = feed;
4146                 last_stream = &feed->next;
4147                 /* add in feed list */
4148                 *last_feed = feed;
4149                 last_feed = &feed->next_feed;
4150             }
4151         } else if (!av_strcasecmp(cmd, "Launch")) {
4152             if (feed) {
4153                 int i;
4154
4155                 feed->child_argv = av_mallocz(64 * sizeof(char *));
4156
4157                 for (i = 0; i < 62; i++) {
4158                     get_arg(arg, sizeof(arg), &p);
4159                     if (!arg[0])
4160                         break;
4161
4162                     feed->child_argv[i] = av_strdup(arg);
4163                 }
4164
4165                 feed->child_argv[i] = av_malloc(30 + strlen(feed->filename));
4166
4167                 snprintf(feed->child_argv[i], 30+strlen(feed->filename),
4168                     "http://%s:%d/%s",
4169                         (my_http_addr.sin_addr.s_addr == INADDR_ANY) ? "127.0.0.1" :
4170                     inet_ntoa(my_http_addr.sin_addr),
4171                     ntohs(my_http_addr.sin_port), feed->filename);
4172             }
4173         } else if (!av_strcasecmp(cmd, "ReadOnlyFile")) {
4174             if (feed) {
4175                 get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
4176                 feed->readonly = 1;
4177             } else if (stream) {
4178                 get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4179             }
4180         } else if (!av_strcasecmp(cmd, "File")) {
4181             if (feed) {
4182                 get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
4183             } else if (stream)
4184                 get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4185         } else if (!av_strcasecmp(cmd, "Truncate")) {
4186             if (feed) {
4187                 get_arg(arg, sizeof(arg), &p);
4188                 feed->truncate = strtod(arg, NULL);
4189             }
4190         } else if (!av_strcasecmp(cmd, "FileMaxSize")) {
4191             if (feed) {
4192                 char *p1;
4193                 double fsize;
4194
4195                 get_arg(arg, sizeof(arg), &p);
4196                 p1 = arg;
4197                 fsize = strtod(p1, &p1);
4198                 switch(toupper(*p1)) {
4199                 case 'K':
4200                     fsize *= 1024;
4201                     break;
4202                 case 'M':
4203                     fsize *= 1024 * 1024;
4204                     break;
4205                 case 'G':
4206                     fsize *= 1024 * 1024 * 1024;
4207                     break;
4208                 }
4209                 feed->feed_max_size = (int64_t)fsize;
4210                 if (feed->feed_max_size < FFM_PACKET_SIZE*4) {
4211                     ERROR("Feed max file size is too small, must be at least %d\n", FFM_PACKET_SIZE*4);
4212                 }
4213             }
4214         } else if (!av_strcasecmp(cmd, "</Feed>")) {
4215             if (!feed) {
4216                 ERROR("No corresponding <Feed> for </Feed>\n");
4217             }
4218             feed = NULL;
4219         } else if (!av_strcasecmp(cmd, "<Stream")) {
4220             /*********************************************/
4221             /* Stream related options */
4222             char *q;
4223             if (stream || feed) {
4224                 ERROR("Already in a tag\n");
4225             } else {
4226                 FFStream *s;
4227                 stream = av_mallocz(sizeof(FFStream));
4228                 get_arg(stream->filename, sizeof(stream->filename), &p);
4229                 q = strrchr(stream->filename, '>');
4230                 if (*q)
4231                     *q = '\0';
4232
4233                 for (s = first_stream; s; s = s->next) {
4234                     if (!strcmp(stream->filename, s->filename)) {
4235                         ERROR("Stream '%s' already registered\n", s->filename);
4236                     }
4237                 }
4238
4239                 stream->fmt = avserver_guess_format(NULL, stream->filename, NULL);
4240                 avcodec_get_context_defaults3(&video_enc, NULL);
4241                 avcodec_get_context_defaults3(&audio_enc, NULL);
4242                 audio_id = AV_CODEC_ID_NONE;
4243                 video_id = AV_CODEC_ID_NONE;
4244                 if (stream->fmt) {
4245                     audio_id = stream->fmt->audio_codec;
4246                     video_id = stream->fmt->video_codec;
4247                 }
4248
4249                 *last_stream = stream;
4250                 last_stream = &stream->next;
4251             }
4252         } else if (!av_strcasecmp(cmd, "Feed")) {
4253             get_arg(arg, sizeof(arg), &p);
4254             if (stream) {
4255                 FFStream *sfeed;
4256
4257                 sfeed = first_feed;
4258                 while (sfeed != NULL) {
4259                     if (!strcmp(sfeed->filename, arg))
4260                         break;
4261                     sfeed = sfeed->next_feed;
4262                 }
4263                 if (!sfeed)
4264                     ERROR("feed '%s' not defined\n", arg);
4265                 else
4266                     stream->feed = sfeed;
4267             }
4268         } else if (!av_strcasecmp(cmd, "Format")) {
4269             get_arg(arg, sizeof(arg), &p);
4270             if (stream) {
4271                 if (!strcmp(arg, "status")) {
4272                     stream->stream_type = STREAM_TYPE_STATUS;
4273                     stream->fmt = NULL;
4274                 } else {
4275                     stream->stream_type = STREAM_TYPE_LIVE;
4276                     /* jpeg cannot be used here, so use single frame jpeg */
4277                     if (!strcmp(arg, "jpeg"))
4278                         strcpy(arg, "mjpeg");
4279                     stream->fmt = avserver_guess_format(arg, NULL, NULL);
4280                     if (!stream->fmt) {
4281                         ERROR("Unknown Format: %s\n", arg);
4282                     }
4283                 }
4284                 if (stream->fmt) {
4285                     audio_id = stream->fmt->audio_codec;
4286                     video_id = stream->fmt->video_codec;
4287                 }
4288             }
4289         } else if (!av_strcasecmp(cmd, "InputFormat")) {
4290             get_arg(arg, sizeof(arg), &p);
4291             if (stream) {
4292                 stream->ifmt = av_find_input_format(arg);
4293                 if (!stream->ifmt) {
4294                     ERROR("Unknown input format: %s\n", arg);
4295                 }
4296             }
4297         } else if (!av_strcasecmp(cmd, "FaviconURL")) {
4298             if (stream && stream->stream_type == STREAM_TYPE_STATUS) {
4299                 get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4300             } else {
4301                 ERROR("FaviconURL only permitted for status streams\n");
4302             }
4303         } else if (!av_strcasecmp(cmd, "Author")) {
4304             if (stream)
4305                 get_arg(stream->author, sizeof(stream->author), &p);
4306         } else if (!av_strcasecmp(cmd, "Comment")) {
4307             if (stream)
4308                 get_arg(stream->comment, sizeof(stream->comment), &p);
4309         } else if (!av_strcasecmp(cmd, "Copyright")) {
4310             if (stream)
4311                 get_arg(stream->copyright, sizeof(stream->copyright), &p);
4312         } else if (!av_strcasecmp(cmd, "Title")) {
4313             if (stream)
4314                 get_arg(stream->title, sizeof(stream->title), &p);
4315         } else if (!av_strcasecmp(cmd, "Preroll")) {
4316             get_arg(arg, sizeof(arg), &p);
4317             if (stream)
4318                 stream->prebuffer = atof(arg) * 1000;
4319         } else if (!av_strcasecmp(cmd, "StartSendOnKey")) {
4320             if (stream)
4321                 stream->send_on_key = 1;
4322         } else if (!av_strcasecmp(cmd, "AudioCodec")) {
4323             get_arg(arg, sizeof(arg), &p);
4324             audio_id = opt_audio_codec(arg);
4325             if (audio_id == AV_CODEC_ID_NONE) {
4326                 ERROR("Unknown AudioCodec: %s\n", arg);
4327             }
4328         } else if (!av_strcasecmp(cmd, "VideoCodec")) {
4329             get_arg(arg, sizeof(arg), &p);
4330             video_id = opt_video_codec(arg);
4331             if (video_id == AV_CODEC_ID_NONE) {
4332                 ERROR("Unknown VideoCodec: %s\n", arg);
4333             }
4334         } else if (!av_strcasecmp(cmd, "MaxTime")) {
4335             get_arg(arg, sizeof(arg), &p);
4336             if (stream)
4337                 stream->max_time = atof(arg) * 1000;
4338         } else if (!av_strcasecmp(cmd, "AudioBitRate")) {
4339             get_arg(arg, sizeof(arg), &p);
4340             if (stream)
4341                 audio_enc.bit_rate = lrintf(atof(arg) * 1000);
4342         } else if (!av_strcasecmp(cmd, "AudioChannels")) {
4343             get_arg(arg, sizeof(arg), &p);
4344             if (stream)
4345                 audio_enc.channels = atoi(arg);
4346         } else if (!av_strcasecmp(cmd, "AudioSampleRate")) {
4347             get_arg(arg, sizeof(arg), &p);
4348             if (stream)
4349                 audio_enc.sample_rate = atoi(arg);
4350         } else if (!av_strcasecmp(cmd, "AudioQuality")) {
4351             get_arg(arg, sizeof(arg), &p);
4352             if (stream) {
4353 //                audio_enc.quality = atof(arg) * 1000;
4354             }
4355         } else if (!av_strcasecmp(cmd, "VideoBitRateRange")) {
4356             if (stream) {
4357                 int minrate, maxrate;
4358
4359                 get_arg(arg, sizeof(arg), &p);
4360
4361                 if (sscanf(arg, "%d-%d", &minrate, &maxrate) == 2) {
4362                     video_enc.rc_min_rate = minrate * 1000;
4363                     video_enc.rc_max_rate = maxrate * 1000;
4364                 } else {
4365                     ERROR("Incorrect format for VideoBitRateRange -- should be <min>-<max>: %s\n", arg);
4366                 }
4367             }
4368         } else if (!av_strcasecmp(cmd, "Debug")) {
4369             if (stream) {
4370                 get_arg(arg, sizeof(arg), &p);
4371                 video_enc.debug = strtol(arg,0,0);
4372             }
4373         } else if (!av_strcasecmp(cmd, "Strict")) {
4374             if (stream) {
4375                 get_arg(arg, sizeof(arg), &p);
4376                 video_enc.strict_std_compliance = atoi(arg);
4377             }
4378         } else if (!av_strcasecmp(cmd, "VideoBufferSize")) {
4379             if (stream) {
4380                 get_arg(arg, sizeof(arg), &p);
4381                 video_enc.rc_buffer_size = atoi(arg) * 8*1024;
4382             }
4383         } else if (!av_strcasecmp(cmd, "VideoBitRateTolerance")) {
4384             if (stream) {
4385                 get_arg(arg, sizeof(arg), &p);
4386                 video_enc.bit_rate_tolerance = atoi(arg) * 1000;
4387             }
4388         } else if (!av_strcasecmp(cmd, "VideoBitRate")) {
4389             get_arg(arg, sizeof(arg), &p);
4390             if (stream) {
4391                 video_enc.bit_rate = atoi(arg) * 1000;
4392             }
4393         } else if (!av_strcasecmp(cmd, "VideoSize")) {
4394             get_arg(arg, sizeof(arg), &p);
4395             if (stream) {
4396                 av_parse_video_size(&video_enc.width, &video_enc.height, arg);
4397                 if ((video_enc.width % 16) != 0 ||
4398                     (video_enc.height % 16) != 0) {
4399                     ERROR("Image size must be a multiple of 16\n");
4400                 }
4401             }
4402         } else if (!av_strcasecmp(cmd, "VideoFrameRate")) {
4403             get_arg(arg, sizeof(arg), &p);
4404             if (stream) {
4405                 AVRational frame_rate;
4406                 if (av_parse_video_rate(&frame_rate, arg) < 0) {
4407                     ERROR("Incorrect frame rate: %s\n", arg);
4408                 } else {
4409                     video_enc.time_base.num = frame_rate.den;
4410                     video_enc.time_base.den = frame_rate.num;
4411                 }
4412             }
4413         } else if (!av_strcasecmp(cmd, "VideoGopSize")) {
4414             get_arg(arg, sizeof(arg), &p);
4415             if (stream)
4416                 video_enc.gop_size = atoi(arg);
4417         } else if (!av_strcasecmp(cmd, "VideoIntraOnly")) {
4418             if (stream)
4419                 video_enc.gop_size = 1;
4420         } else if (!av_strcasecmp(cmd, "VideoHighQuality")) {
4421             if (stream)
4422                 video_enc.mb_decision = FF_MB_DECISION_BITS;
4423         } else if (!av_strcasecmp(cmd, "Video4MotionVector")) {
4424             if (stream) {
4425                 video_enc.mb_decision = FF_MB_DECISION_BITS; //FIXME remove
4426                 video_enc.flags |= CODEC_FLAG_4MV;
4427             }
4428         } else if (!av_strcasecmp(cmd, "AVOptionVideo") ||
4429                    !av_strcasecmp(cmd, "AVOptionAudio")) {
4430             char arg2[1024];
4431             AVCodecContext *avctx;
4432             int type;
4433             get_arg(arg, sizeof(arg), &p);
4434             get_arg(arg2, sizeof(arg2), &p);
4435             if (!av_strcasecmp(cmd, "AVOptionVideo")) {
4436                 avctx = &video_enc;
4437                 type = AV_OPT_FLAG_VIDEO_PARAM;
4438             } else {
4439                 avctx = &audio_enc;
4440                 type = AV_OPT_FLAG_AUDIO_PARAM;
4441             }
4442             if (avserver_opt_default(arg, arg2, avctx, type|AV_OPT_FLAG_ENCODING_PARAM)) {
4443                 ERROR("AVOption error: %s %s\n", arg, arg2);
4444             }
4445         } else if (!av_strcasecmp(cmd, "AVPresetVideo") ||
4446                    !av_strcasecmp(cmd, "AVPresetAudio")) {
4447             AVCodecContext *avctx;
4448             int type;
4449             get_arg(arg, sizeof(arg), &p);
4450             if (!av_strcasecmp(cmd, "AVPresetVideo")) {
4451                 avctx = &video_enc;
4452                 video_enc.codec_id = video_id;
4453                 type = AV_OPT_FLAG_VIDEO_PARAM;
4454             } else {
4455                 avctx = &audio_enc;
4456                 audio_enc.codec_id = audio_id;
4457                 type = AV_OPT_FLAG_AUDIO_PARAM;
4458             }
4459             if (avserver_opt_preset(arg, avctx, type|AV_OPT_FLAG_ENCODING_PARAM, &audio_id, &video_id)) {
4460                 ERROR("AVPreset error: %s\n", arg);
4461             }
4462         } else if (!av_strcasecmp(cmd, "VideoTag")) {
4463             get_arg(arg, sizeof(arg), &p);
4464             if ((strlen(arg) == 4) && stream)
4465                 video_enc.codec_tag = MKTAG(arg[0], arg[1], arg[2], arg[3]);
4466         } else if (!av_strcasecmp(cmd, "BitExact")) {
4467             if (stream)
4468                 video_enc.flags |= CODEC_FLAG_BITEXACT;
4469         } else if (!av_strcasecmp(cmd, "DctFastint")) {
4470             if (stream)
4471                 video_enc.dct_algo  = FF_DCT_FASTINT;
4472         } else if (!av_strcasecmp(cmd, "IdctSimple")) {
4473             if (stream)
4474                 video_enc.idct_algo = FF_IDCT_SIMPLE;
4475         } else if (!av_strcasecmp(cmd, "Qscale")) {
4476             get_arg(arg, sizeof(arg), &p);
4477             if (stream) {
4478                 video_enc.flags |= CODEC_FLAG_QSCALE;
4479                 video_enc.global_quality = FF_QP2LAMBDA * atoi(arg);
4480             }
4481         } else if (!av_strcasecmp(cmd, "VideoQDiff")) {
4482             get_arg(arg, sizeof(arg), &p);
4483             if (stream) {
4484                 video_enc.max_qdiff = atoi(arg);
4485                 if (video_enc.max_qdiff < 1 || video_enc.max_qdiff > 31) {
4486                     ERROR("VideoQDiff out of range\n");
4487                 }
4488             }
4489         } else if (!av_strcasecmp(cmd, "VideoQMax")) {
4490             get_arg(arg, sizeof(arg), &p);
4491             if (stream) {
4492                 video_enc.qmax = atoi(arg);
4493                 if (video_enc.qmax < 1 || video_enc.qmax > 31) {
4494                     ERROR("VideoQMax out of range\n");
4495                 }
4496             }
4497         } else if (!av_strcasecmp(cmd, "VideoQMin")) {
4498             get_arg(arg, sizeof(arg), &p);
4499             if (stream) {
4500                 video_enc.qmin = atoi(arg);
4501                 if (video_enc.qmin < 1 || video_enc.qmin > 31) {
4502                     ERROR("VideoQMin out of range\n");
4503                 }
4504             }
4505         } else if (!av_strcasecmp(cmd, "LumaElim")) {
4506             get_arg(arg, sizeof(arg), &p);
4507             if (stream)
4508                 video_enc.luma_elim_threshold = atoi(arg);
4509         } else if (!av_strcasecmp(cmd, "ChromaElim")) {
4510             get_arg(arg, sizeof(arg), &p);
4511             if (stream)
4512                 video_enc.chroma_elim_threshold = atoi(arg);
4513         } else if (!av_strcasecmp(cmd, "LumiMask")) {
4514             get_arg(arg, sizeof(arg), &p);
4515             if (stream)
4516                 video_enc.lumi_masking = atof(arg);
4517         } else if (!av_strcasecmp(cmd, "DarkMask")) {
4518             get_arg(arg, sizeof(arg), &p);
4519             if (stream)
4520                 video_enc.dark_masking = atof(arg);
4521         } else if (!av_strcasecmp(cmd, "NoVideo")) {
4522             video_id = AV_CODEC_ID_NONE;
4523         } else if (!av_strcasecmp(cmd, "NoAudio")) {
4524             audio_id = AV_CODEC_ID_NONE;
4525         } else if (!av_strcasecmp(cmd, "ACL")) {
4526             parse_acl_row(stream, feed, NULL, p, filename, line_num);
4527         } else if (!av_strcasecmp(cmd, "DynamicACL")) {
4528             if (stream) {
4529                 get_arg(stream->dynamic_acl, sizeof(stream->dynamic_acl), &p);
4530             }
4531         } else if (!av_strcasecmp(cmd, "RTSPOption")) {
4532             get_arg(arg, sizeof(arg), &p);
4533             if (stream) {
4534                 av_freep(&stream->rtsp_option);
4535                 stream->rtsp_option = av_strdup(arg);
4536             }
4537         } else if (!av_strcasecmp(cmd, "MulticastAddress")) {
4538             get_arg(arg, sizeof(arg), &p);
4539             if (stream) {
4540                 if (resolve_host(&stream->multicast_ip, arg) != 0) {
4541                     ERROR("Invalid host/IP address: %s\n", arg);
4542                 }
4543                 stream->is_multicast = 1;
4544                 stream->loop = 1; /* default is looping */
4545             }
4546         } else if (!av_strcasecmp(cmd, "MulticastPort")) {
4547             get_arg(arg, sizeof(arg), &p);
4548             if (stream)
4549                 stream->multicast_port = atoi(arg);
4550         } else if (!av_strcasecmp(cmd, "MulticastTTL")) {
4551             get_arg(arg, sizeof(arg), &p);
4552             if (stream)
4553                 stream->multicast_ttl = atoi(arg);
4554         } else if (!av_strcasecmp(cmd, "NoLoop")) {
4555             if (stream)
4556                 stream->loop = 0;
4557         } else if (!av_strcasecmp(cmd, "</Stream>")) {
4558             if (!stream) {
4559                 ERROR("No corresponding <Stream> for </Stream>\n");
4560             } else {
4561                 if (stream->feed && stream->fmt && strcmp(stream->fmt->name, "ffm") != 0) {
4562                     if (audio_id != AV_CODEC_ID_NONE) {
4563                         audio_enc.codec_type = AVMEDIA_TYPE_AUDIO;
4564                         audio_enc.codec_id = audio_id;
4565                         add_codec(stream, &audio_enc);
4566                     }
4567                     if (video_id != AV_CODEC_ID_NONE) {
4568                         video_enc.codec_type = AVMEDIA_TYPE_VIDEO;
4569                         video_enc.codec_id = video_id;
4570                         add_codec(stream, &video_enc);
4571                     }
4572                 }
4573                 stream = NULL;
4574             }
4575         } else if (!av_strcasecmp(cmd, "<Redirect")) {
4576             /*********************************************/
4577             char *q;
4578             if (stream || feed || redirect) {
4579                 ERROR("Already in a tag\n");
4580             } else {
4581                 redirect = av_mallocz(sizeof(FFStream));
4582                 *last_stream = redirect;
4583                 last_stream = &redirect->next;
4584
4585                 get_arg(redirect->filename, sizeof(redirect->filename), &p);
4586                 q = strrchr(redirect->filename, '>');
4587                 if (*q)
4588                     *q = '\0';
4589                 redirect->stream_type = STREAM_TYPE_REDIRECT;
4590             }
4591         } else if (!av_strcasecmp(cmd, "URL")) {
4592             if (redirect)
4593                 get_arg(redirect->feed_filename, sizeof(redirect->feed_filename), &p);
4594         } else if (!av_strcasecmp(cmd, "</Redirect>")) {
4595             if (!redirect) {
4596                 ERROR("No corresponding <Redirect> for </Redirect>\n");
4597             } else {
4598                 if (!redirect->feed_filename[0]) {
4599                     ERROR("No URL found for <Redirect>\n");
4600                 }
4601                 redirect = NULL;
4602             }
4603         } else if (!av_strcasecmp(cmd, "LoadModule")) {
4604             get_arg(arg, sizeof(arg), &p);
4605 #if HAVE_DLOPEN
4606             load_module(arg);
4607 #else
4608             ERROR("Module support not compiled into this version: '%s'\n", arg);
4609 #endif
4610         } else {
4611             ERROR("Incorrect keyword: '%s'\n", cmd);
4612         }
4613     }
4614 #undef ERROR
4615
4616     fclose(f);
4617     if (errors)
4618         return -1;
4619     else
4620         return 0;
4621 }
4622
4623 static void handle_child_exit(int sig)
4624 {
4625     pid_t pid;
4626     int status;
4627
4628     while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
4629         FFStream *feed;
4630
4631         for (feed = first_feed; feed; feed = feed->next) {
4632             if (feed->pid == pid) {
4633                 int uptime = time(0) - feed->pid_start;
4634
4635                 feed->pid = 0;
4636                 fprintf(stderr, "%s: Pid %d exited with status %d after %d seconds\n", feed->filename, pid, status, uptime);
4637
4638                 if (uptime < 30)
4639                     /* Turn off any more restarts */
4640                     feed->child_argv = 0;
4641             }
4642         }
4643     }
4644
4645     need_to_start_children = 1;
4646 }
4647
4648 static void opt_debug(void)
4649 {
4650     avserver_debug = 1;
4651     logfilename[0] = '-';
4652 }
4653
4654 void show_help_default(const char *opt, const char *arg)
4655 {
4656     printf("usage: avserver [options]\n"
4657            "Hyper fast multi format Audio/Video streaming server\n");
4658     printf("\n");
4659     show_help_options(options, "Main options:", 0, 0, 0);
4660 }
4661
4662 static const OptionDef options[] = {
4663 #include "cmdutils_common_opts.h"
4664     { "n", OPT_BOOL, {(void *)&no_launch }, "enable no-launch mode" },
4665     { "d", 0, {(void*)opt_debug}, "enable debug mode" },
4666     { "f", HAS_ARG | OPT_STRING, {(void*)&config_filename }, "use configfile instead of /etc/avserver.conf", "configfile" },
4667     { NULL },
4668 };
4669
4670 int main(int argc, char **argv)
4671 {
4672     struct sigaction sigact = { { 0 } };
4673
4674     parse_loglevel(argc, argv, options);
4675     av_register_all();
4676     avformat_network_init();
4677
4678     show_banner();
4679
4680     my_program_name = argv[0];
4681
4682     parse_options(NULL, argc, argv, options, NULL);
4683
4684     unsetenv("http_proxy");             /* Kill the http_proxy */
4685
4686     av_lfg_init(&random_state, av_get_random_seed());
4687
4688     sigact.sa_handler = handle_child_exit;
4689     sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
4690     sigaction(SIGCHLD, &sigact, 0);
4691
4692     if (parse_ffconfig(config_filename) < 0) {
4693         fprintf(stderr, "Incorrect config file - exiting.\n");
4694         exit(1);
4695     }
4696
4697     /* open log file if needed */
4698     if (logfilename[0] != '\0') {
4699         if (!strcmp(logfilename, "-"))
4700             logfile = stdout;
4701         else
4702             logfile = fopen(logfilename, "a");
4703         av_log_set_callback(http_av_log);
4704     }
4705
4706     build_file_streams();
4707
4708     build_feed_streams();
4709
4710     compute_bandwidth();
4711
4712     /* signal init */
4713     signal(SIGPIPE, SIG_IGN);
4714
4715     if (http_server() < 0) {
4716         http_log("Could not start server\n");
4717         exit(1);
4718     }
4719
4720     return 0;
4721 }