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