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