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