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