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