OSDN Git Service

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