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