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