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