]> 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         http_log("Truncating feed file '%s'\n", c->stream->feed_filename);
2589         if (ftruncate(c->feed_fd, FFM_PACKET_SIZE) < 0) {
2590             http_log("Error truncating feed file: %s\n", strerror(errno));
2591             return -1;
2592         }
2593     } else {
2594         if ((c->stream->feed_write_index = ffm_read_write_index(fd)) < 0) {
2595             http_log("Error reading write index from feed file: %s\n", strerror(errno));
2596             return -1;
2597         }
2598     }
2599
2600     c->stream->feed_write_index = FFMAX(ffm_read_write_index(fd), FFM_PACKET_SIZE);
2601     c->stream->feed_size = lseek(fd, 0, SEEK_END);
2602     lseek(fd, 0, SEEK_SET);
2603
2604     /* init buffer input */
2605     c->buffer_ptr = c->buffer;
2606     c->buffer_end = c->buffer + FFM_PACKET_SIZE;
2607     c->stream->feed_opened = 1;
2608     c->chunked_encoding = !!av_stristr(c->buffer, "Transfer-Encoding: chunked");
2609     return 0;
2610 }
2611
2612 static int http_receive_data(HTTPContext *c)
2613 {
2614     HTTPContext *c1;
2615     int len, loop_run = 0;
2616
2617     while (c->chunked_encoding && !c->chunk_size &&
2618            c->buffer_end > c->buffer_ptr) {
2619         /* read chunk header, if present */
2620         len = recv(c->fd, c->buffer_ptr, 1, 0);
2621
2622         if (len < 0) {
2623             if (ff_neterrno() != AVERROR(EAGAIN) &&
2624                 ff_neterrno() != AVERROR(EINTR))
2625                 /* error : close connection */
2626                 goto fail;
2627             return 0;
2628         } else if (len == 0) {
2629             /* end of connection : close it */
2630             goto fail;
2631         } else if (c->buffer_ptr - c->buffer >= 2 &&
2632                    !memcmp(c->buffer_ptr - 1, "\r\n", 2)) {
2633             c->chunk_size = strtol(c->buffer, 0, 16);
2634             if (c->chunk_size == 0) // end of stream
2635                 goto fail;
2636             c->buffer_ptr = c->buffer;
2637             break;
2638         } else if (++loop_run > 10) {
2639             /* no chunk header, abort */
2640             goto fail;
2641         } else {
2642             c->buffer_ptr++;
2643         }
2644     }
2645
2646     if (c->buffer_end > c->buffer_ptr) {
2647         len = recv(c->fd, c->buffer_ptr,
2648                    FFMIN(c->chunk_size, c->buffer_end - c->buffer_ptr), 0);
2649         if (len < 0) {
2650             if (ff_neterrno() != AVERROR(EAGAIN) &&
2651                 ff_neterrno() != AVERROR(EINTR))
2652                 /* error : close connection */
2653                 goto fail;
2654         } else if (len == 0)
2655             /* end of connection : close it */
2656             goto fail;
2657         else {
2658             c->chunk_size -= len;
2659             c->buffer_ptr += len;
2660             c->data_count += len;
2661             update_datarate(&c->datarate, c->data_count);
2662         }
2663     }
2664
2665     if (c->buffer_ptr - c->buffer >= 2 && c->data_count > FFM_PACKET_SIZE) {
2666         if (c->buffer[0] != 'f' ||
2667             c->buffer[1] != 'm') {
2668             http_log("Feed stream has become desynchronized -- disconnecting\n");
2669             goto fail;
2670         }
2671     }
2672
2673     if (c->buffer_ptr >= c->buffer_end) {
2674         FFStream *feed = c->stream;
2675         /* a packet has been received : write it in the store, except
2676            if header */
2677         if (c->data_count > FFM_PACKET_SIZE) {
2678
2679             //            printf("writing pos=0x%"PRIx64" size=0x%"PRIx64"\n", feed->feed_write_index, feed->feed_size);
2680             /* XXX: use llseek or url_seek */
2681             lseek(c->feed_fd, feed->feed_write_index, SEEK_SET);
2682             if (write(c->feed_fd, c->buffer, FFM_PACKET_SIZE) < 0) {
2683                 http_log("Error writing to feed file: %s\n", strerror(errno));
2684                 goto fail;
2685             }
2686
2687             feed->feed_write_index += FFM_PACKET_SIZE;
2688             /* update file size */
2689             if (feed->feed_write_index > c->stream->feed_size)
2690                 feed->feed_size = feed->feed_write_index;
2691
2692             /* handle wrap around if max file size reached */
2693             if (c->stream->feed_max_size && feed->feed_write_index >= c->stream->feed_max_size)
2694                 feed->feed_write_index = FFM_PACKET_SIZE;
2695
2696             /* write index */
2697             if (ffm_write_write_index(c->feed_fd, feed->feed_write_index) < 0) {
2698                 http_log("Error writing index to feed file: %s\n", strerror(errno));
2699                 goto fail;
2700             }
2701
2702             /* wake up any waiting connections */
2703             for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
2704                 if (c1->state == HTTPSTATE_WAIT_FEED &&
2705                     c1->stream->feed == c->stream->feed)
2706                     c1->state = HTTPSTATE_SEND_DATA;
2707             }
2708         } else {
2709             /* We have a header in our hands that contains useful data */
2710             AVFormatContext *s = avformat_alloc_context();
2711             AVIOContext *pb;
2712             AVInputFormat *fmt_in;
2713             int i;
2714
2715             if (!s)
2716                 goto fail;
2717
2718             /* use feed output format name to find corresponding input format */
2719             fmt_in = av_find_input_format(feed->fmt->name);
2720             if (!fmt_in)
2721                 goto fail;
2722
2723             pb = avio_alloc_context(c->buffer, c->buffer_end - c->buffer,
2724                                     0, NULL, NULL, NULL, NULL);
2725             pb->seekable = 0;
2726
2727             s->pb = pb;
2728             if (avformat_open_input(&s, c->stream->feed_filename, fmt_in, NULL) < 0) {
2729                 av_free(pb);
2730                 goto fail;
2731             }
2732
2733             /* Now we have the actual streams */
2734             if (s->nb_streams != feed->nb_streams) {
2735                 avformat_close_input(&s);
2736                 av_free(pb);
2737                 http_log("Feed '%s' stream number does not match registered feed\n",
2738                          c->stream->feed_filename);
2739                 goto fail;
2740             }
2741
2742             for (i = 0; i < s->nb_streams; i++) {
2743                 AVStream *fst = feed->streams[i];
2744                 AVStream *st = s->streams[i];
2745                 avcodec_copy_context(fst->codec, st->codec);
2746             }
2747
2748             avformat_close_input(&s);
2749             av_free(pb);
2750         }
2751         c->buffer_ptr = c->buffer;
2752     }
2753
2754     return 0;
2755  fail:
2756     c->stream->feed_opened = 0;
2757     close(c->feed_fd);
2758     /* wake up any waiting connections to stop waiting for feed */
2759     for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
2760         if (c1->state == HTTPSTATE_WAIT_FEED &&
2761             c1->stream->feed == c->stream->feed)
2762             c1->state = HTTPSTATE_SEND_DATA_TRAILER;
2763     }
2764     return -1;
2765 }
2766
2767 /********************************************************************/
2768 /* RTSP handling */
2769
2770 static void rtsp_reply_header(HTTPContext *c, enum RTSPStatusCode error_number)
2771 {
2772     const char *str;
2773     time_t ti;
2774     struct tm *tm;
2775     char buf2[32];
2776
2777     switch(error_number) {
2778     case RTSP_STATUS_OK:
2779         str = "OK";
2780         break;
2781     case RTSP_STATUS_METHOD:
2782         str = "Method Not Allowed";
2783         break;
2784     case RTSP_STATUS_BANDWIDTH:
2785         str = "Not Enough Bandwidth";
2786         break;
2787     case RTSP_STATUS_SESSION:
2788         str = "Session Not Found";
2789         break;
2790     case RTSP_STATUS_STATE:
2791         str = "Method Not Valid in This State";
2792         break;
2793     case RTSP_STATUS_AGGREGATE:
2794         str = "Aggregate operation not allowed";
2795         break;
2796     case RTSP_STATUS_ONLY_AGGREGATE:
2797         str = "Only aggregate operation allowed";
2798         break;
2799     case RTSP_STATUS_TRANSPORT:
2800         str = "Unsupported transport";
2801         break;
2802     case RTSP_STATUS_INTERNAL:
2803         str = "Internal Server Error";
2804         break;
2805     case RTSP_STATUS_SERVICE:
2806         str = "Service Unavailable";
2807         break;
2808     case RTSP_STATUS_VERSION:
2809         str = "RTSP Version not supported";
2810         break;
2811     default:
2812         str = "Unknown Error";
2813         break;
2814     }
2815
2816     avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", error_number, str);
2817     avio_printf(c->pb, "CSeq: %d\r\n", c->seq);
2818
2819     /* output GMT time */
2820     ti = time(NULL);
2821     tm = gmtime(&ti);
2822     strftime(buf2, sizeof(buf2), "%a, %d %b %Y %H:%M:%S", tm);
2823     avio_printf(c->pb, "Date: %s GMT\r\n", buf2);
2824 }
2825
2826 static void rtsp_reply_error(HTTPContext *c, enum RTSPStatusCode error_number)
2827 {
2828     rtsp_reply_header(c, error_number);
2829     avio_printf(c->pb, "\r\n");
2830 }
2831
2832 static int rtsp_parse_request(HTTPContext *c)
2833 {
2834     const char *p, *p1, *p2;
2835     char cmd[32];
2836     char url[1024];
2837     char protocol[32];
2838     char line[1024];
2839     int len;
2840     RTSPMessageHeader header1 = { 0 }, *header = &header1;
2841
2842     c->buffer_ptr[0] = '\0';
2843     p = c->buffer;
2844
2845     get_word(cmd, sizeof(cmd), &p);
2846     get_word(url, sizeof(url), &p);
2847     get_word(protocol, sizeof(protocol), &p);
2848
2849     av_strlcpy(c->method, cmd, sizeof(c->method));
2850     av_strlcpy(c->url, url, sizeof(c->url));
2851     av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
2852
2853     if (avio_open_dyn_buf(&c->pb) < 0) {
2854         /* XXX: cannot do more */
2855         c->pb = NULL; /* safety */
2856         return -1;
2857     }
2858
2859     /* check version name */
2860     if (strcmp(protocol, "RTSP/1.0") != 0) {
2861         rtsp_reply_error(c, RTSP_STATUS_VERSION);
2862         goto the_end;
2863     }
2864
2865     /* parse each header line */
2866     /* skip to next line */
2867     while (*p != '\n' && *p != '\0')
2868         p++;
2869     if (*p == '\n')
2870         p++;
2871     while (*p != '\0') {
2872         p1 = memchr(p, '\n', (char *)c->buffer_ptr - p);
2873         if (!p1)
2874             break;
2875         p2 = p1;
2876         if (p2 > p && p2[-1] == '\r')
2877             p2--;
2878         /* skip empty line */
2879         if (p2 == p)
2880             break;
2881         len = p2 - p;
2882         if (len > sizeof(line) - 1)
2883             len = sizeof(line) - 1;
2884         memcpy(line, p, len);
2885         line[len] = '\0';
2886         ff_rtsp_parse_line(header, line, NULL, NULL);
2887         p = p1 + 1;
2888     }
2889
2890     /* handle sequence number */
2891     c->seq = header->seq;
2892
2893     if (!strcmp(cmd, "DESCRIBE"))
2894         rtsp_cmd_describe(c, url);
2895     else if (!strcmp(cmd, "OPTIONS"))
2896         rtsp_cmd_options(c, url);
2897     else if (!strcmp(cmd, "SETUP"))
2898         rtsp_cmd_setup(c, url, header);
2899     else if (!strcmp(cmd, "PLAY"))
2900         rtsp_cmd_play(c, url, header);
2901     else if (!strcmp(cmd, "PAUSE"))
2902         rtsp_cmd_pause(c, url, header);
2903     else if (!strcmp(cmd, "TEARDOWN"))
2904         rtsp_cmd_teardown(c, url, header);
2905     else
2906         rtsp_reply_error(c, RTSP_STATUS_METHOD);
2907
2908  the_end:
2909     len = avio_close_dyn_buf(c->pb, &c->pb_buffer);
2910     c->pb = NULL; /* safety */
2911     if (len < 0) {
2912         /* XXX: cannot do more */
2913         return -1;
2914     }
2915     c->buffer_ptr = c->pb_buffer;
2916     c->buffer_end = c->pb_buffer + len;
2917     c->state = RTSPSTATE_SEND_REPLY;
2918     return 0;
2919 }
2920
2921 static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
2922                                    struct in_addr my_ip)
2923 {
2924     AVFormatContext *avc;
2925     AVStream *avs = NULL;
2926     int i;
2927
2928     avc =  avformat_alloc_context();
2929     if (avc == NULL) {
2930         return -1;
2931     }
2932     av_dict_set(&avc->metadata, "title",
2933                stream->title[0] ? stream->title : "No Title", 0);
2934     avc->nb_streams = stream->nb_streams;
2935     if (stream->is_multicast) {
2936         snprintf(avc->filename, 1024, "rtp://%s:%d?multicast=1?ttl=%d",
2937                  inet_ntoa(stream->multicast_ip),
2938                  stream->multicast_port, stream->multicast_ttl);
2939     } else {
2940         snprintf(avc->filename, 1024, "rtp://0.0.0.0");
2941     }
2942
2943     if (avc->nb_streams >= INT_MAX/sizeof(*avc->streams) ||
2944         !(avc->streams = av_malloc(avc->nb_streams * sizeof(*avc->streams))))
2945         goto sdp_done;
2946     if (avc->nb_streams >= INT_MAX/sizeof(*avs) ||
2947         !(avs = av_malloc(avc->nb_streams * sizeof(*avs))))
2948         goto sdp_done;
2949
2950     for(i = 0; i < stream->nb_streams; i++) {
2951         avc->streams[i] = &avs[i];
2952         avc->streams[i]->codec = stream->streams[i]->codec;
2953     }
2954     *pbuffer = av_mallocz(2048);
2955     av_sdp_create(&avc, 1, *pbuffer, 2048);
2956
2957  sdp_done:
2958     av_free(avc->streams);
2959     av_dict_free(&avc->metadata);
2960     av_free(avc);
2961     av_free(avs);
2962
2963     return strlen(*pbuffer);
2964 }
2965
2966 static void rtsp_cmd_options(HTTPContext *c, const char *url)
2967 {
2968 //    rtsp_reply_header(c, RTSP_STATUS_OK);
2969     avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", RTSP_STATUS_OK, "OK");
2970     avio_printf(c->pb, "CSeq: %d\r\n", c->seq);
2971     avio_printf(c->pb, "Public: %s\r\n", "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
2972     avio_printf(c->pb, "\r\n");
2973 }
2974
2975 static void rtsp_cmd_describe(HTTPContext *c, const char *url)
2976 {
2977     FFStream *stream;
2978     char path1[1024];
2979     const char *path;
2980     uint8_t *content;
2981     int content_length, len;
2982     struct sockaddr_in my_addr;
2983
2984     /* find which url is asked */
2985     av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
2986     path = path1;
2987     if (*path == '/')
2988         path++;
2989
2990     for(stream = first_stream; stream != NULL; stream = stream->next) {
2991         if (!stream->is_feed &&
2992             stream->fmt && !strcmp(stream->fmt->name, "rtp") &&
2993             !strcmp(path, stream->filename)) {
2994             goto found;
2995         }
2996     }
2997     /* no stream found */
2998     rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
2999     return;
3000
3001  found:
3002     /* prepare the media description in sdp format */
3003
3004     /* get the host IP */
3005     len = sizeof(my_addr);
3006     getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
3007     content_length = prepare_sdp_description(stream, &content, my_addr.sin_addr);
3008     if (content_length < 0) {
3009         rtsp_reply_error(c, RTSP_STATUS_INTERNAL);
3010         return;
3011     }
3012     rtsp_reply_header(c, RTSP_STATUS_OK);
3013     avio_printf(c->pb, "Content-Base: %s/\r\n", url);
3014     avio_printf(c->pb, "Content-Type: application/sdp\r\n");
3015     avio_printf(c->pb, "Content-Length: %d\r\n", content_length);
3016     avio_printf(c->pb, "\r\n");
3017     avio_write(c->pb, content, content_length);
3018     av_free(content);
3019 }
3020
3021 static HTTPContext *find_rtp_session(const char *session_id)
3022 {
3023     HTTPContext *c;
3024
3025     if (session_id[0] == '\0')
3026         return NULL;
3027
3028     for(c = first_http_ctx; c != NULL; c = c->next) {
3029         if (!strcmp(c->session_id, session_id))
3030             return c;
3031     }
3032     return NULL;
3033 }
3034
3035 static RTSPTransportField *find_transport(RTSPMessageHeader *h, enum RTSPLowerTransport lower_transport)
3036 {
3037     RTSPTransportField *th;
3038     int i;
3039
3040     for(i=0;i<h->nb_transports;i++) {
3041         th = &h->transports[i];
3042         if (th->lower_transport == lower_transport)
3043             return th;
3044     }
3045     return NULL;
3046 }
3047
3048 static void rtsp_cmd_setup(HTTPContext *c, const char *url,
3049                            RTSPMessageHeader *h)
3050 {
3051     FFStream *stream;
3052     int stream_index, rtp_port, rtcp_port;
3053     char buf[1024];
3054     char path1[1024];
3055     const char *path;
3056     HTTPContext *rtp_c;
3057     RTSPTransportField *th;
3058     struct sockaddr_in dest_addr;
3059     RTSPActionServerSetup setup;
3060
3061     /* find which url is asked */
3062     av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3063     path = path1;
3064     if (*path == '/')
3065         path++;
3066
3067     /* now check each stream */
3068     for(stream = first_stream; stream != NULL; stream = stream->next) {
3069         if (!stream->is_feed &&
3070             stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
3071             /* accept aggregate filenames only if single stream */
3072             if (!strcmp(path, stream->filename)) {
3073                 if (stream->nb_streams != 1) {
3074                     rtsp_reply_error(c, RTSP_STATUS_AGGREGATE);
3075                     return;
3076                 }
3077                 stream_index = 0;
3078                 goto found;
3079             }
3080
3081             for(stream_index = 0; stream_index < stream->nb_streams;
3082                 stream_index++) {
3083                 snprintf(buf, sizeof(buf), "%s/streamid=%d",
3084                          stream->filename, stream_index);
3085                 if (!strcmp(path, buf))
3086                     goto found;
3087             }
3088         }
3089     }
3090     /* no stream found */
3091     rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
3092     return;
3093  found:
3094
3095     /* generate session id if needed */
3096     if (h->session_id[0] == '\0')
3097         snprintf(h->session_id, sizeof(h->session_id), "%08x%08x",
3098                  av_lfg_get(&random_state), av_lfg_get(&random_state));
3099
3100     /* find rtp session, and create it if none found */
3101     rtp_c = find_rtp_session(h->session_id);
3102     if (!rtp_c) {
3103         /* always prefer UDP */
3104         th = find_transport(h, RTSP_LOWER_TRANSPORT_UDP);
3105         if (!th) {
3106             th = find_transport(h, RTSP_LOWER_TRANSPORT_TCP);
3107             if (!th) {
3108                 rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3109                 return;
3110             }
3111         }
3112
3113         rtp_c = rtp_new_connection(&c->from_addr, stream, h->session_id,
3114                                    th->lower_transport);
3115         if (!rtp_c) {
3116             rtsp_reply_error(c, RTSP_STATUS_BANDWIDTH);
3117             return;
3118         }
3119
3120         /* open input stream */
3121         if (open_input_stream(rtp_c, "") < 0) {
3122             rtsp_reply_error(c, RTSP_STATUS_INTERNAL);
3123             return;
3124         }
3125     }
3126
3127     /* test if stream is OK (test needed because several SETUP needs
3128        to be done for a given file) */
3129     if (rtp_c->stream != stream) {
3130         rtsp_reply_error(c, RTSP_STATUS_SERVICE);
3131         return;
3132     }
3133
3134     /* test if stream is already set up */
3135     if (rtp_c->rtp_ctx[stream_index]) {
3136         rtsp_reply_error(c, RTSP_STATUS_STATE);
3137         return;
3138     }
3139
3140     /* check transport */
3141     th = find_transport(h, rtp_c->rtp_protocol);
3142     if (!th || (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
3143                 th->client_port_min <= 0)) {
3144         rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3145         return;
3146     }
3147
3148     /* setup default options */
3149     setup.transport_option[0] = '\0';
3150     dest_addr = rtp_c->from_addr;
3151     dest_addr.sin_port = htons(th->client_port_min);
3152
3153     /* setup stream */
3154     if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, c) < 0) {
3155         rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3156         return;
3157     }
3158
3159     /* now everything is OK, so we can send the connection parameters */
3160     rtsp_reply_header(c, RTSP_STATUS_OK);
3161     /* session ID */
3162     avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3163
3164     switch(rtp_c->rtp_protocol) {
3165     case RTSP_LOWER_TRANSPORT_UDP:
3166         rtp_port = ff_rtp_get_local_rtp_port(rtp_c->rtp_handles[stream_index]);
3167         rtcp_port = ff_rtp_get_local_rtcp_port(rtp_c->rtp_handles[stream_index]);
3168         avio_printf(c->pb, "Transport: RTP/AVP/UDP;unicast;"
3169                     "client_port=%d-%d;server_port=%d-%d",
3170                     th->client_port_min, th->client_port_max,
3171                     rtp_port, rtcp_port);
3172         break;
3173     case RTSP_LOWER_TRANSPORT_TCP:
3174         avio_printf(c->pb, "Transport: RTP/AVP/TCP;interleaved=%d-%d",
3175                     stream_index * 2, stream_index * 2 + 1);
3176         break;
3177     default:
3178         break;
3179     }
3180     if (setup.transport_option[0] != '\0')
3181         avio_printf(c->pb, ";%s", setup.transport_option);
3182     avio_printf(c->pb, "\r\n");
3183
3184
3185     avio_printf(c->pb, "\r\n");
3186 }
3187
3188
3189 /* find an rtp connection by using the session ID. Check consistency
3190    with filename */
3191 static HTTPContext *find_rtp_session_with_url(const char *url,
3192                                               const char *session_id)
3193 {
3194     HTTPContext *rtp_c;
3195     char path1[1024];
3196     const char *path;
3197     char buf[1024];
3198     int s, len;
3199
3200     rtp_c = find_rtp_session(session_id);
3201     if (!rtp_c)
3202         return NULL;
3203
3204     /* find which url is asked */
3205     av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3206     path = path1;
3207     if (*path == '/')
3208         path++;
3209     if(!strcmp(path, rtp_c->stream->filename)) return rtp_c;
3210     for(s=0; s<rtp_c->stream->nb_streams; ++s) {
3211       snprintf(buf, sizeof(buf), "%s/streamid=%d",
3212         rtp_c->stream->filename, s);
3213       if(!strncmp(path, buf, sizeof(buf))) {
3214     // XXX: Should we reply with RTSP_STATUS_ONLY_AGGREGATE if nb_streams>1?
3215         return rtp_c;
3216       }
3217     }
3218     len = strlen(path);
3219     if (len > 0 && path[len - 1] == '/' &&
3220         !strncmp(path, rtp_c->stream->filename, len - 1))
3221         return rtp_c;
3222     return NULL;
3223 }
3224
3225 static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3226 {
3227     HTTPContext *rtp_c;
3228
3229     rtp_c = find_rtp_session_with_url(url, h->session_id);
3230     if (!rtp_c) {
3231         rtsp_reply_error(c, RTSP_STATUS_SESSION);
3232         return;
3233     }
3234
3235     if (rtp_c->state != HTTPSTATE_SEND_DATA &&
3236         rtp_c->state != HTTPSTATE_WAIT_FEED &&
3237         rtp_c->state != HTTPSTATE_READY) {
3238         rtsp_reply_error(c, RTSP_STATUS_STATE);
3239         return;
3240     }
3241
3242     rtp_c->state = HTTPSTATE_SEND_DATA;
3243
3244     /* now everything is OK, so we can send the connection parameters */
3245     rtsp_reply_header(c, RTSP_STATUS_OK);
3246     /* session ID */
3247     avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3248     avio_printf(c->pb, "\r\n");
3249 }
3250
3251 static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3252 {
3253     HTTPContext *rtp_c;
3254
3255     rtp_c = find_rtp_session_with_url(url, h->session_id);
3256     if (!rtp_c) {
3257         rtsp_reply_error(c, RTSP_STATUS_SESSION);
3258         return;
3259     }
3260
3261     if (rtp_c->state != HTTPSTATE_SEND_DATA &&
3262         rtp_c->state != HTTPSTATE_WAIT_FEED) {
3263         rtsp_reply_error(c, RTSP_STATUS_STATE);
3264         return;
3265     }
3266
3267     rtp_c->state = HTTPSTATE_READY;
3268     rtp_c->first_pts = AV_NOPTS_VALUE;
3269     /* now everything is OK, so we can send the connection parameters */
3270     rtsp_reply_header(c, RTSP_STATUS_OK);
3271     /* session ID */
3272     avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3273     avio_printf(c->pb, "\r\n");
3274 }
3275
3276 static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3277 {
3278     HTTPContext *rtp_c;
3279
3280     rtp_c = find_rtp_session_with_url(url, h->session_id);
3281     if (!rtp_c) {
3282         rtsp_reply_error(c, RTSP_STATUS_SESSION);
3283         return;
3284     }
3285
3286     /* now everything is OK, so we can send the connection parameters */
3287     rtsp_reply_header(c, RTSP_STATUS_OK);
3288     /* session ID */
3289     avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3290     avio_printf(c->pb, "\r\n");
3291
3292     /* abort the session */
3293     close_connection(rtp_c);
3294 }
3295
3296
3297 /********************************************************************/
3298 /* RTP handling */
3299
3300 static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
3301                                        FFStream *stream, const char *session_id,
3302                                        enum RTSPLowerTransport rtp_protocol)
3303 {
3304     HTTPContext *c = NULL;
3305     const char *proto_str;
3306
3307     /* XXX: should output a warning page when coming
3308        close to the connection limit */
3309     if (nb_connections >= nb_max_connections)
3310         goto fail;
3311
3312     /* add a new connection */
3313     c = av_mallocz(sizeof(HTTPContext));
3314     if (!c)
3315         goto fail;
3316
3317     c->fd = -1;
3318     c->poll_entry = NULL;
3319     c->from_addr = *from_addr;
3320     c->buffer_size = IOBUFFER_INIT_SIZE;
3321     c->buffer = av_malloc(c->buffer_size);
3322     if (!c->buffer)
3323         goto fail;
3324     nb_connections++;
3325     c->stream = stream;
3326     av_strlcpy(c->session_id, session_id, sizeof(c->session_id));
3327     c->state = HTTPSTATE_READY;
3328     c->is_packetized = 1;
3329     c->rtp_protocol = rtp_protocol;
3330
3331     /* protocol is shown in statistics */
3332     switch(c->rtp_protocol) {
3333     case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
3334         proto_str = "MCAST";
3335         break;
3336     case RTSP_LOWER_TRANSPORT_UDP:
3337         proto_str = "UDP";
3338         break;
3339     case RTSP_LOWER_TRANSPORT_TCP:
3340         proto_str = "TCP";
3341         break;
3342     default:
3343         proto_str = "???";
3344         break;
3345     }
3346     av_strlcpy(c->protocol, "RTP/", sizeof(c->protocol));
3347     av_strlcat(c->protocol, proto_str, sizeof(c->protocol));
3348
3349     current_bandwidth += stream->bandwidth;
3350
3351     c->next = first_http_ctx;
3352     first_http_ctx = c;
3353     return c;
3354
3355  fail:
3356     if (c) {
3357         av_free(c->buffer);
3358         av_free(c);
3359     }
3360     return NULL;
3361 }
3362
3363 /* add a new RTP stream in an RTP connection (used in RTSP SETUP
3364    command). If RTP/TCP protocol is used, TCP connection 'rtsp_c' is
3365    used. */
3366 static int rtp_new_av_stream(HTTPContext *c,
3367                              int stream_index, struct sockaddr_in *dest_addr,
3368                              HTTPContext *rtsp_c)
3369 {
3370     AVFormatContext *ctx;
3371     AVStream *st;
3372     char *ipaddr;
3373     URLContext *h = NULL;
3374     uint8_t *dummy_buf;
3375     int max_packet_size;
3376
3377     /* now we can open the relevant output stream */
3378     ctx = avformat_alloc_context();
3379     if (!ctx)
3380         return -1;
3381     ctx->oformat = av_guess_format("rtp", NULL, NULL);
3382
3383     st = av_mallocz(sizeof(AVStream));
3384     if (!st)
3385         goto fail;
3386     ctx->nb_streams = 1;
3387     ctx->streams = av_mallocz(sizeof(AVStream *) * ctx->nb_streams);
3388     if (!ctx->streams)
3389       goto fail;
3390     ctx->streams[0] = st;
3391
3392     if (!c->stream->feed ||
3393         c->stream->feed == c->stream)
3394         memcpy(st, c->stream->streams[stream_index], sizeof(AVStream));
3395     else
3396         memcpy(st,
3397                c->stream->feed->streams[c->stream->feed_streams[stream_index]],
3398                sizeof(AVStream));
3399     st->priv_data = NULL;
3400
3401     /* build destination RTP address */
3402     ipaddr = inet_ntoa(dest_addr->sin_addr);
3403
3404     switch(c->rtp_protocol) {
3405     case RTSP_LOWER_TRANSPORT_UDP:
3406     case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
3407         /* RTP/UDP case */
3408
3409         /* XXX: also pass as parameter to function ? */
3410         if (c->stream->is_multicast) {
3411             int ttl;
3412             ttl = c->stream->multicast_ttl;
3413             if (!ttl)
3414                 ttl = 16;
3415             snprintf(ctx->filename, sizeof(ctx->filename),
3416                      "rtp://%s:%d?multicast=1&ttl=%d",
3417                      ipaddr, ntohs(dest_addr->sin_port), ttl);
3418         } else {
3419             snprintf(ctx->filename, sizeof(ctx->filename),
3420                      "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
3421         }
3422
3423         if (ffurl_open(&h, ctx->filename, AVIO_FLAG_WRITE, NULL, NULL) < 0)
3424             goto fail;
3425         c->rtp_handles[stream_index] = h;
3426         max_packet_size = h->max_packet_size;
3427         break;
3428     case RTSP_LOWER_TRANSPORT_TCP:
3429         /* RTP/TCP case */
3430         c->rtsp_c = rtsp_c;
3431         max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
3432         break;
3433     default:
3434         goto fail;
3435     }
3436
3437     http_log("%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
3438              ipaddr, ntohs(dest_addr->sin_port),
3439              c->stream->filename, stream_index, c->protocol);
3440
3441     /* normally, no packets should be output here, but the packet size may be checked */
3442     if (ffio_open_dyn_packet_buf(&ctx->pb, max_packet_size) < 0) {
3443         /* XXX: close stream */
3444         goto fail;
3445     }
3446     if (avformat_write_header(ctx, NULL) < 0) {
3447     fail:
3448         if (h)
3449             ffurl_close(h);
3450         av_free(ctx);
3451         return -1;
3452     }
3453     avio_close_dyn_buf(ctx->pb, &dummy_buf);
3454     av_free(dummy_buf);
3455
3456     c->rtp_ctx[stream_index] = ctx;
3457     return 0;
3458 }
3459
3460 /********************************************************************/
3461 /* ffserver initialization */
3462
3463 static AVStream *add_av_stream1(FFStream *stream, AVCodecContext *codec, int copy)
3464 {
3465     AVStream *fst;
3466
3467     fst = av_mallocz(sizeof(AVStream));
3468     if (!fst)
3469         return NULL;
3470     if (copy) {
3471         fst->codec = avcodec_alloc_context3(NULL);
3472         memcpy(fst->codec, codec, sizeof(AVCodecContext));
3473         if (codec->extradata_size) {
3474             fst->codec->extradata = av_malloc(codec->extradata_size);
3475             memcpy(fst->codec->extradata, codec->extradata,
3476                 codec->extradata_size);
3477         }
3478     } else {
3479         /* live streams must use the actual feed's codec since it may be
3480          * updated later to carry extradata needed by the streams.
3481          */
3482         fst->codec = codec;
3483     }
3484     fst->priv_data = av_mallocz(sizeof(FeedData));
3485     fst->index = stream->nb_streams;
3486     avpriv_set_pts_info(fst, 33, 1, 90000);
3487     fst->sample_aspect_ratio = codec->sample_aspect_ratio;
3488     stream->streams[stream->nb_streams++] = fst;
3489     return fst;
3490 }
3491
3492 /* return the stream number in the feed */
3493 static int add_av_stream(FFStream *feed, AVStream *st)
3494 {
3495     AVStream *fst;
3496     AVCodecContext *av, *av1;
3497     int i;
3498
3499     av = st->codec;
3500     for(i=0;i<feed->nb_streams;i++) {
3501         st = feed->streams[i];
3502         av1 = st->codec;
3503         if (av1->codec_id == av->codec_id &&
3504             av1->codec_type == av->codec_type &&
3505             av1->bit_rate == av->bit_rate) {
3506
3507             switch(av->codec_type) {
3508             case AVMEDIA_TYPE_AUDIO:
3509                 if (av1->channels == av->channels &&
3510                     av1->sample_rate == av->sample_rate)
3511                     return i;
3512                 break;
3513             case AVMEDIA_TYPE_VIDEO:
3514                 if (av1->width == av->width &&
3515                     av1->height == av->height &&
3516                     av1->time_base.den == av->time_base.den &&
3517                     av1->time_base.num == av->time_base.num &&
3518                     av1->gop_size == av->gop_size)
3519                     return i;
3520                 break;
3521             default:
3522                 abort();
3523             }
3524         }
3525     }
3526
3527     fst = add_av_stream1(feed, av, 0);
3528     if (!fst)
3529         return -1;
3530     return feed->nb_streams - 1;
3531 }
3532
3533 static void remove_stream(FFStream *stream)
3534 {
3535     FFStream **ps;
3536     ps = &first_stream;
3537     while (*ps != NULL) {
3538         if (*ps == stream)
3539             *ps = (*ps)->next;
3540         else
3541             ps = &(*ps)->next;
3542     }
3543 }
3544
3545 /* specific mpeg4 handling : we extract the raw parameters */
3546 static void extract_mpeg4_header(AVFormatContext *infile)
3547 {
3548     int mpeg4_count, i, size;
3549     AVPacket pkt;
3550     AVStream *st;
3551     const uint8_t *p;
3552
3553     mpeg4_count = 0;
3554     for(i=0;i<infile->nb_streams;i++) {
3555         st = infile->streams[i];
3556         if (st->codec->codec_id == CODEC_ID_MPEG4 &&
3557             st->codec->extradata_size == 0) {
3558             mpeg4_count++;
3559         }
3560     }
3561     if (!mpeg4_count)
3562         return;
3563
3564     printf("MPEG4 without extra data: trying to find header in %s\n", infile->filename);
3565     while (mpeg4_count > 0) {
3566         if (av_read_packet(infile, &pkt) < 0)
3567             break;
3568         st = infile->streams[pkt.stream_index];
3569         if (st->codec->codec_id == CODEC_ID_MPEG4 &&
3570             st->codec->extradata_size == 0) {
3571             av_freep(&st->codec->extradata);
3572             /* fill extradata with the header */
3573             /* XXX: we make hard suppositions here ! */
3574             p = pkt.data;
3575             while (p < pkt.data + pkt.size - 4) {
3576                 /* stop when vop header is found */
3577                 if (p[0] == 0x00 && p[1] == 0x00 &&
3578                     p[2] == 0x01 && p[3] == 0xb6) {
3579                     size = p - pkt.data;
3580                     //                    av_hex_dump_log(infile, AV_LOG_DEBUG, pkt.data, size);
3581                     st->codec->extradata = av_malloc(size);
3582                     st->codec->extradata_size = size;
3583                     memcpy(st->codec->extradata, pkt.data, size);
3584                     break;
3585                 }
3586                 p++;
3587             }
3588             mpeg4_count--;
3589         }
3590         av_free_packet(&pkt);
3591     }
3592 }
3593
3594 /* compute the needed AVStream for each file */
3595 static void build_file_streams(void)
3596 {
3597     FFStream *stream, *stream_next;
3598     int i, ret;
3599
3600     /* gather all streams */
3601     for(stream = first_stream; stream != NULL; stream = stream_next) {
3602         AVFormatContext *infile = NULL;
3603         stream_next = stream->next;
3604         if (stream->stream_type == STREAM_TYPE_LIVE &&
3605             !stream->feed) {
3606             /* the stream comes from a file */
3607             /* try to open the file */
3608             /* open stream */
3609             if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
3610                 /* specific case : if transport stream output to RTP,
3611                    we use a raw transport stream reader */
3612                 av_dict_set(&stream->in_opts, "mpeg2ts_compute_pcr", "1", 0);
3613             }
3614
3615             http_log("Opening file '%s'\n", stream->feed_filename);
3616             if ((ret = avformat_open_input(&infile, stream->feed_filename, stream->ifmt, &stream->in_opts)) < 0) {
3617                 http_log("Could not open '%s': %d\n", stream->feed_filename, ret);
3618                 /* remove stream (no need to spend more time on it) */
3619             fail:
3620                 remove_stream(stream);
3621             } else {
3622                 /* find all the AVStreams inside and reference them in
3623                    'stream' */
3624                 if (avformat_find_stream_info(infile, NULL) < 0) {
3625                     http_log("Could not find codec parameters from '%s'\n",
3626                              stream->feed_filename);
3627                     avformat_close_input(&infile);
3628                     goto fail;
3629                 }
3630                 extract_mpeg4_header(infile);
3631
3632                 for(i=0;i<infile->nb_streams;i++)
3633                     add_av_stream1(stream, infile->streams[i]->codec, 1);
3634
3635                 avformat_close_input(&infile);
3636             }
3637         }
3638     }
3639 }
3640
3641 /* compute the needed AVStream for each feed */
3642 static void build_feed_streams(void)
3643 {
3644     FFStream *stream, *feed;
3645     int i;
3646
3647     /* gather all streams */
3648     for(stream = first_stream; stream != NULL; stream = stream->next) {
3649         feed = stream->feed;
3650         if (feed) {
3651             if (stream->is_feed) {
3652                 for(i=0;i<stream->nb_streams;i++)
3653                     stream->feed_streams[i] = i;
3654             } else {
3655                 /* we handle a stream coming from a feed */
3656                 for(i=0;i<stream->nb_streams;i++)
3657                     stream->feed_streams[i] = add_av_stream(feed, stream->streams[i]);
3658             }
3659         }
3660     }
3661
3662     /* create feed files if needed */
3663     for(feed = first_feed; feed != NULL; feed = feed->next_feed) {
3664         int fd;
3665
3666         if (avio_check(feed->feed_filename, AVIO_FLAG_READ) > 0) {
3667             /* See if it matches */
3668             AVFormatContext *s = NULL;
3669             int matches = 0;
3670
3671             if (avformat_open_input(&s, feed->feed_filename, NULL, NULL) >= 0) {
3672                 /* set buffer size */
3673                 ffio_set_buf_size(s->pb, FFM_PACKET_SIZE);
3674                 /* Now see if it matches */
3675                 if (s->nb_streams == feed->nb_streams) {
3676                     matches = 1;
3677                     for(i=0;i<s->nb_streams;i++) {
3678                         AVStream *sf, *ss;
3679                         sf = feed->streams[i];
3680                         ss = s->streams[i];
3681
3682                         if (sf->index != ss->index ||
3683                             sf->id != ss->id) {
3684                             http_log("Index & Id do not match for stream %d (%s)\n",
3685                                    i, feed->feed_filename);
3686                             matches = 0;
3687                         } else {
3688                             AVCodecContext *ccf, *ccs;
3689
3690                             ccf = sf->codec;
3691                             ccs = ss->codec;
3692 #define CHECK_CODEC(x)  (ccf->x != ccs->x)
3693
3694                             if (CHECK_CODEC(codec_id) || CHECK_CODEC(codec_type)) {
3695                                 http_log("Codecs do not match for stream %d\n", i);
3696                                 matches = 0;
3697                             } else if (CHECK_CODEC(bit_rate) || CHECK_CODEC(flags)) {
3698                                 http_log("Codec bitrates do not match for stream %d\n", i);
3699                                 matches = 0;
3700                             } else if (ccf->codec_type == AVMEDIA_TYPE_VIDEO) {
3701                                 if (CHECK_CODEC(time_base.den) ||
3702                                     CHECK_CODEC(time_base.num) ||
3703                                     CHECK_CODEC(width) ||
3704                                     CHECK_CODEC(height)) {
3705                                     http_log("Codec width, height and framerate do not match for stream %d\n", i);
3706                                     matches = 0;
3707                                 }
3708                             } else if (ccf->codec_type == AVMEDIA_TYPE_AUDIO) {
3709                                 if (CHECK_CODEC(sample_rate) ||
3710                                     CHECK_CODEC(channels) ||
3711                                     CHECK_CODEC(frame_size)) {
3712                                     http_log("Codec sample_rate, channels, frame_size do not match for stream %d\n", i);
3713                                     matches = 0;
3714                                 }
3715                             } else {
3716                                 http_log("Unknown codec type\n");
3717                                 matches = 0;
3718                             }
3719                         }
3720                         if (!matches)
3721                             break;
3722                     }
3723                 } else
3724                     http_log("Deleting feed file '%s' as stream counts differ (%d != %d)\n",
3725                         feed->feed_filename, s->nb_streams, feed->nb_streams);
3726
3727                 avformat_close_input(&s);
3728             } else
3729                 http_log("Deleting feed file '%s' as it appears to be corrupt\n",
3730                         feed->feed_filename);
3731
3732             if (!matches) {
3733                 if (feed->readonly) {
3734                     http_log("Unable to delete feed file '%s' as it is marked readonly\n",
3735                         feed->feed_filename);
3736                     exit(1);
3737                 }
3738                 unlink(feed->feed_filename);
3739             }
3740         }
3741         if (avio_check(feed->feed_filename, AVIO_FLAG_WRITE) <= 0) {
3742             AVFormatContext s1 = {0}, *s = &s1;
3743
3744             if (feed->readonly) {
3745                 http_log("Unable to create feed file '%s' as it is marked readonly\n",
3746                     feed->feed_filename);
3747                 exit(1);
3748             }
3749
3750             /* only write the header of the ffm file */
3751             if (avio_open(&s->pb, feed->feed_filename, AVIO_FLAG_WRITE) < 0) {
3752                 http_log("Could not open output feed file '%s'\n",
3753                          feed->feed_filename);
3754                 exit(1);
3755             }
3756             s->oformat = feed->fmt;
3757             s->nb_streams = feed->nb_streams;
3758             s->streams = feed->streams;
3759             if (avformat_write_header(s, NULL) < 0) {
3760                 http_log("Container doesn't supports the required parameters\n");
3761                 exit(1);
3762             }
3763             /* XXX: need better api */
3764             av_freep(&s->priv_data);
3765             avio_close(s->pb);
3766         }
3767         /* get feed size and write index */
3768         fd = open(feed->feed_filename, O_RDONLY);
3769         if (fd < 0) {
3770             http_log("Could not open output feed file '%s'\n",
3771                     feed->feed_filename);
3772             exit(1);
3773         }
3774
3775         feed->feed_write_index = FFMAX(ffm_read_write_index(fd), FFM_PACKET_SIZE);
3776         feed->feed_size = lseek(fd, 0, SEEK_END);
3777         /* ensure that we do not wrap before the end of file */
3778         if (feed->feed_max_size && feed->feed_max_size < feed->feed_size)
3779             feed->feed_max_size = feed->feed_size;
3780
3781         close(fd);
3782     }
3783 }
3784
3785 /* compute the bandwidth used by each stream */
3786 static void compute_bandwidth(void)
3787 {
3788     unsigned bandwidth;
3789     int i;
3790     FFStream *stream;
3791
3792     for(stream = first_stream; stream != NULL; stream = stream->next) {
3793         bandwidth = 0;
3794         for(i=0;i<stream->nb_streams;i++) {
3795             AVStream *st = stream->streams[i];
3796             switch(st->codec->codec_type) {
3797             case AVMEDIA_TYPE_AUDIO:
3798             case AVMEDIA_TYPE_VIDEO:
3799                 bandwidth += st->codec->bit_rate;
3800                 break;
3801             default:
3802                 break;
3803             }
3804         }
3805         stream->bandwidth = (bandwidth + 999) / 1000;
3806     }
3807 }
3808
3809 /* add a codec and set the default parameters */
3810 static void add_codec(FFStream *stream, AVCodecContext *av)
3811 {
3812     AVStream *st;
3813
3814     /* compute default parameters */
3815     switch(av->codec_type) {
3816     case AVMEDIA_TYPE_AUDIO:
3817         if (av->bit_rate == 0)
3818             av->bit_rate = 64000;
3819         if (av->sample_rate == 0)
3820             av->sample_rate = 22050;
3821         if (av->channels == 0)
3822             av->channels = 1;
3823         break;
3824     case AVMEDIA_TYPE_VIDEO:
3825         if (av->bit_rate == 0)
3826             av->bit_rate = 64000;
3827         if (av->time_base.num == 0){
3828             av->time_base.den = 5;
3829             av->time_base.num = 1;
3830         }
3831         if (av->width == 0 || av->height == 0) {
3832             av->width = 160;
3833             av->height = 128;
3834         }
3835         /* Bitrate tolerance is less for streaming */
3836         if (av->bit_rate_tolerance == 0)
3837             av->bit_rate_tolerance = FFMAX(av->bit_rate / 4,
3838                       (int64_t)av->bit_rate*av->time_base.num/av->time_base.den);
3839         if (av->qmin == 0)
3840             av->qmin = 3;
3841         if (av->qmax == 0)
3842             av->qmax = 31;
3843         if (av->max_qdiff == 0)
3844             av->max_qdiff = 3;
3845         av->qcompress = 0.5;
3846         av->qblur = 0.5;
3847
3848         if (!av->nsse_weight)
3849             av->nsse_weight = 8;
3850
3851         av->frame_skip_cmp = FF_CMP_DCTMAX;
3852         if (!av->me_method)
3853             av->me_method = ME_EPZS;
3854         av->rc_buffer_aggressivity = 1.0;
3855
3856         if (!av->rc_eq)
3857             av->rc_eq = "tex^qComp";
3858         if (!av->i_quant_factor)
3859             av->i_quant_factor = -0.8;
3860         if (!av->b_quant_factor)
3861             av->b_quant_factor = 1.25;
3862         if (!av->b_quant_offset)
3863             av->b_quant_offset = 1.25;
3864         if (!av->rc_max_rate)
3865             av->rc_max_rate = av->bit_rate * 2;
3866
3867         if (av->rc_max_rate && !av->rc_buffer_size) {
3868             av->rc_buffer_size = av->rc_max_rate;
3869         }
3870
3871
3872         break;
3873     default:
3874         abort();
3875     }
3876
3877     st = av_mallocz(sizeof(AVStream));
3878     if (!st)
3879         return;
3880     st->codec = avcodec_alloc_context3(NULL);
3881     stream->streams[stream->nb_streams++] = st;
3882     memcpy(st->codec, av, sizeof(AVCodecContext));
3883 }
3884
3885 static enum CodecID opt_audio_codec(const char *arg)
3886 {
3887     AVCodec *p= avcodec_find_encoder_by_name(arg);
3888
3889     if (p == NULL || p->type != AVMEDIA_TYPE_AUDIO)
3890         return CODEC_ID_NONE;
3891
3892     return p->id;
3893 }
3894
3895 static enum CodecID opt_video_codec(const char *arg)
3896 {
3897     AVCodec *p= avcodec_find_encoder_by_name(arg);
3898
3899     if (p == NULL || p->type != AVMEDIA_TYPE_VIDEO)
3900         return CODEC_ID_NONE;
3901
3902     return p->id;
3903 }
3904
3905 /* simplistic plugin support */
3906
3907 #if HAVE_DLOPEN
3908 static void load_module(const char *filename)
3909 {
3910     void *dll;
3911     void (*init_func)(void);
3912     dll = dlopen(filename, RTLD_NOW);
3913     if (!dll) {
3914         fprintf(stderr, "Could not load module '%s' - %s\n",
3915                 filename, dlerror());
3916         return;
3917     }
3918
3919     init_func = dlsym(dll, "ffserver_module_init");
3920     if (!init_func) {
3921         fprintf(stderr,
3922                 "%s: init function 'ffserver_module_init()' not found\n",
3923                 filename);
3924         dlclose(dll);
3925     }
3926
3927     init_func();
3928 }
3929 #endif
3930
3931 static int ffserver_opt_default(const char *opt, const char *arg,
3932                        AVCodecContext *avctx, int type)
3933 {
3934     int ret = 0;
3935     const AVOption *o = av_opt_find(avctx, opt, NULL, type, 0);
3936     if(o)
3937         ret = av_opt_set(avctx, opt, arg, 0);
3938     return ret;
3939 }
3940
3941 static int ffserver_opt_preset(const char *arg,
3942                        AVCodecContext *avctx, int type,
3943                        enum CodecID *audio_id, enum CodecID *video_id)
3944 {
3945     FILE *f=NULL;
3946     char filename[1000], tmp[1000], tmp2[1000], line[1000];
3947     int ret = 0;
3948     AVCodec *codec = avcodec_find_encoder(avctx->codec_id);
3949
3950     if (!(f = get_preset_file(filename, sizeof(filename), arg, 0,
3951                               codec ? codec->name : NULL))) {
3952         fprintf(stderr, "File for preset '%s' not found\n", arg);
3953         return 1;
3954     }
3955
3956     while(!feof(f)){
3957         int e= fscanf(f, "%999[^\n]\n", line) - 1;
3958         if(line[0] == '#' && !e)
3959             continue;
3960         e|= sscanf(line, "%999[^=]=%999[^\n]\n", tmp, tmp2) - 2;
3961         if(e){
3962             fprintf(stderr, "%s: Invalid syntax: '%s'\n", filename, line);
3963             ret = 1;
3964             break;
3965         }
3966         if(!strcmp(tmp, "acodec")){
3967             *audio_id = opt_audio_codec(tmp2);
3968         }else if(!strcmp(tmp, "vcodec")){
3969             *video_id = opt_video_codec(tmp2);
3970         }else if(!strcmp(tmp, "scodec")){
3971             /* opt_subtitle_codec(tmp2); */
3972         }else if(ffserver_opt_default(tmp, tmp2, avctx, type) < 0){
3973             fprintf(stderr, "%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", filename, line, tmp, tmp2);
3974             ret = 1;
3975             break;
3976         }
3977     }
3978
3979     fclose(f);
3980
3981     return ret;
3982 }
3983
3984 static AVOutputFormat *ffserver_guess_format(const char *short_name, const char *filename,
3985                                              const char *mime_type)
3986 {
3987     AVOutputFormat *fmt = av_guess_format(short_name, filename, mime_type);
3988
3989     if (fmt) {
3990         AVOutputFormat *stream_fmt;
3991         char stream_format_name[64];
3992
3993         snprintf(stream_format_name, sizeof(stream_format_name), "%s_stream", fmt->name);
3994         stream_fmt = av_guess_format(stream_format_name, NULL, NULL);
3995
3996         if (stream_fmt)
3997             fmt = stream_fmt;
3998     }
3999
4000     return fmt;
4001 }
4002
4003 static void report_config_error(const char *filename, int line_num, int *errors, const char *fmt, ...)
4004 {
4005     va_list vl;
4006     va_start(vl, fmt);
4007     fprintf(stderr, "%s:%d: ", filename, line_num);
4008     vfprintf(stderr, fmt, vl);
4009     va_end(vl);
4010
4011     (*errors)++;
4012 }
4013
4014 static int parse_ffconfig(const char *filename)
4015 {
4016     FILE *f;
4017     char line[1024];
4018     char cmd[64];
4019     char arg[1024];
4020     const char *p;
4021     int val, errors, line_num;
4022     FFStream **last_stream, *stream, *redirect;
4023     FFStream **last_feed, *feed, *s;
4024     AVCodecContext audio_enc, video_enc;
4025     enum CodecID audio_id, video_id;
4026
4027     f = fopen(filename, "r");
4028     if (!f) {
4029         perror(filename);
4030         return -1;
4031     }
4032
4033     errors = 0;
4034     line_num = 0;
4035     first_stream = NULL;
4036     last_stream = &first_stream;
4037     first_feed = NULL;
4038     last_feed = &first_feed;
4039     stream = NULL;
4040     feed = NULL;
4041     redirect = NULL;
4042     audio_id = CODEC_ID_NONE;
4043     video_id = CODEC_ID_NONE;
4044
4045 #define ERROR(...) report_config_error(filename, line_num, &errors, __VA_ARGS__)
4046     for(;;) {
4047         if (fgets(line, sizeof(line), f) == NULL)
4048             break;
4049         line_num++;
4050         p = line;
4051         while (isspace(*p))
4052             p++;
4053         if (*p == '\0' || *p == '#')
4054             continue;
4055
4056         get_arg(cmd, sizeof(cmd), &p);
4057
4058         if (!av_strcasecmp(cmd, "Port")) {
4059             get_arg(arg, sizeof(arg), &p);
4060             val = atoi(arg);
4061             if (val < 1 || val > 65536) {
4062                 ERROR("Invalid_port: %s\n", arg);
4063             }
4064             my_http_addr.sin_port = htons(val);
4065         } else if (!av_strcasecmp(cmd, "BindAddress")) {
4066             get_arg(arg, sizeof(arg), &p);
4067             if (resolve_host(&my_http_addr.sin_addr, arg) != 0) {
4068                 ERROR("%s:%d: Invalid host/IP address: %s\n", arg);
4069             }
4070         } else if (!av_strcasecmp(cmd, "NoDaemon")) {
4071             ffserver_daemon = 0;
4072         } else if (!av_strcasecmp(cmd, "RTSPPort")) {
4073             get_arg(arg, sizeof(arg), &p);
4074             val = atoi(arg);
4075             if (val < 1 || val > 65536) {
4076                 ERROR("%s:%d: Invalid port: %s\n", arg);
4077             }
4078             my_rtsp_addr.sin_port = htons(atoi(arg));
4079         } else if (!av_strcasecmp(cmd, "RTSPBindAddress")) {
4080             get_arg(arg, sizeof(arg), &p);
4081             if (resolve_host(&my_rtsp_addr.sin_addr, arg) != 0) {
4082                 ERROR("Invalid host/IP address: %s\n", arg);
4083             }
4084         } else if (!av_strcasecmp(cmd, "MaxHTTPConnections")) {
4085             get_arg(arg, sizeof(arg), &p);
4086             val = atoi(arg);
4087             if (val < 1 || val > 65536) {
4088                 ERROR("Invalid MaxHTTPConnections: %s\n", arg);
4089             }
4090             nb_max_http_connections = val;
4091         } else if (!av_strcasecmp(cmd, "MaxClients")) {
4092             get_arg(arg, sizeof(arg), &p);
4093             val = atoi(arg);
4094             if (val < 1 || val > nb_max_http_connections) {
4095                 ERROR("Invalid MaxClients: %s\n", arg);
4096             } else {
4097                 nb_max_connections = val;
4098             }
4099         } else if (!av_strcasecmp(cmd, "MaxBandwidth")) {
4100             int64_t llval;
4101             get_arg(arg, sizeof(arg), &p);
4102             llval = atoll(arg);
4103             if (llval < 10 || llval > 10000000) {
4104                 ERROR("Invalid MaxBandwidth: %s\n", arg);
4105             } else
4106                 max_bandwidth = llval;
4107         } else if (!av_strcasecmp(cmd, "CustomLog")) {
4108             if (!ffserver_debug)
4109                 get_arg(logfilename, sizeof(logfilename), &p);
4110         } else if (!av_strcasecmp(cmd, "<Feed")) {
4111             /*********************************************/
4112             /* Feed related options */
4113             char *q;
4114             if (stream || feed) {
4115                 ERROR("Already in a tag\n");
4116             } else {
4117                 feed = av_mallocz(sizeof(FFStream));
4118                 get_arg(feed->filename, sizeof(feed->filename), &p);
4119                 q = strrchr(feed->filename, '>');
4120                 if (*q)
4121                     *q = '\0';
4122
4123                 for (s = first_feed; s; s = s->next) {
4124                     if (!strcmp(feed->filename, s->filename)) {
4125                         ERROR("Feed '%s' already registered\n", s->filename);
4126                     }
4127                 }
4128
4129                 feed->fmt = av_guess_format("ffm", NULL, NULL);
4130                 /* defaut feed file */
4131                 snprintf(feed->feed_filename, sizeof(feed->feed_filename),
4132                          "/tmp/%s.ffm", feed->filename);
4133                 feed->feed_max_size = 5 * 1024 * 1024;
4134                 feed->is_feed = 1;
4135                 feed->feed = feed; /* self feeding :-) */
4136
4137                 /* add in stream list */
4138                 *last_stream = feed;
4139                 last_stream = &feed->next;
4140                 /* add in feed list */
4141                 *last_feed = feed;
4142                 last_feed = &feed->next_feed;
4143             }
4144         } else if (!av_strcasecmp(cmd, "Launch")) {
4145             if (feed) {
4146                 int i;
4147
4148                 feed->child_argv = av_mallocz(64 * sizeof(char *));
4149
4150                 for (i = 0; i < 62; i++) {
4151                     get_arg(arg, sizeof(arg), &p);
4152                     if (!arg[0])
4153                         break;
4154
4155                     feed->child_argv[i] = av_strdup(arg);
4156                 }
4157
4158                 feed->child_argv[i] = av_malloc(30 + strlen(feed->filename));
4159
4160                 snprintf(feed->child_argv[i], 30+strlen(feed->filename),
4161                     "http://%s:%d/%s",
4162                         (my_http_addr.sin_addr.s_addr == INADDR_ANY) ? "127.0.0.1" :
4163                     inet_ntoa(my_http_addr.sin_addr),
4164                     ntohs(my_http_addr.sin_port), feed->filename);
4165             }
4166         } else if (!av_strcasecmp(cmd, "ReadOnlyFile")) {
4167             if (feed) {
4168                 get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
4169                 feed->readonly = 1;
4170             } else if (stream) {
4171                 get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4172             }
4173         } else if (!av_strcasecmp(cmd, "File")) {
4174             if (feed) {
4175                 get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
4176             } else if (stream)
4177                 get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4178         } else if (!av_strcasecmp(cmd, "Truncate")) {
4179             if (feed) {
4180                 get_arg(arg, sizeof(arg), &p);
4181                 feed->truncate = strtod(arg, NULL);
4182             }
4183         } else if (!av_strcasecmp(cmd, "FileMaxSize")) {
4184             if (feed) {
4185                 char *p1;
4186                 double fsize;
4187
4188                 get_arg(arg, sizeof(arg), &p);
4189                 p1 = arg;
4190                 fsize = strtod(p1, &p1);
4191                 switch(toupper(*p1)) {
4192                 case 'K':
4193                     fsize *= 1024;
4194                     break;
4195                 case 'M':
4196                     fsize *= 1024 * 1024;
4197                     break;
4198                 case 'G':
4199                     fsize *= 1024 * 1024 * 1024;
4200                     break;
4201                 }
4202                 feed->feed_max_size = (int64_t)fsize;
4203                 if (feed->feed_max_size < FFM_PACKET_SIZE*4) {
4204                     ERROR("Feed max file size is too small, must be at least %d\n", FFM_PACKET_SIZE*4);
4205                 }
4206             }
4207         } else if (!av_strcasecmp(cmd, "</Feed>")) {
4208             if (!feed) {
4209                 ERROR("No corresponding <Feed> for </Feed>\n");
4210             }
4211             feed = NULL;
4212         } else if (!av_strcasecmp(cmd, "<Stream")) {
4213             /*********************************************/
4214             /* Stream related options */
4215             char *q;
4216             if (stream || feed) {
4217                 ERROR("Already in a tag\n");
4218             } else {
4219                 FFStream *s;
4220                 stream = av_mallocz(sizeof(FFStream));
4221                 get_arg(stream->filename, sizeof(stream->filename), &p);
4222                 q = strrchr(stream->filename, '>');
4223                 if (*q)
4224                     *q = '\0';
4225
4226                 for (s = first_stream; s; s = s->next) {
4227                     if (!strcmp(stream->filename, s->filename)) {
4228                         ERROR("Stream '%s' already registered\n", s->filename);
4229                     }
4230                 }
4231
4232                 stream->fmt = ffserver_guess_format(NULL, stream->filename, NULL);
4233                 avcodec_get_context_defaults3(&video_enc, NULL);
4234                 avcodec_get_context_defaults3(&audio_enc, NULL);
4235
4236                 audio_id = CODEC_ID_NONE;
4237                 video_id = CODEC_ID_NONE;
4238                 if (stream->fmt) {
4239                     audio_id = stream->fmt->audio_codec;
4240                     video_id = stream->fmt->video_codec;
4241                 }
4242
4243                 *last_stream = stream;
4244                 last_stream = &stream->next;
4245             }
4246         } else if (!av_strcasecmp(cmd, "Feed")) {
4247             get_arg(arg, sizeof(arg), &p);
4248             if (stream) {
4249                 FFStream *sfeed;
4250
4251                 sfeed = first_feed;
4252                 while (sfeed != NULL) {
4253                     if (!strcmp(sfeed->filename, arg))
4254                         break;
4255                     sfeed = sfeed->next_feed;
4256                 }
4257                 if (!sfeed)
4258                     ERROR("feed '%s' not defined\n", arg);
4259                 else
4260                     stream->feed = sfeed;
4261             }
4262         } else if (!av_strcasecmp(cmd, "Format")) {
4263             get_arg(arg, sizeof(arg), &p);
4264             if (stream) {
4265                 if (!strcmp(arg, "status")) {
4266                     stream->stream_type = STREAM_TYPE_STATUS;
4267                     stream->fmt = NULL;
4268                 } else {
4269                     stream->stream_type = STREAM_TYPE_LIVE;
4270                     /* jpeg cannot be used here, so use single frame jpeg */
4271                     if (!strcmp(arg, "jpeg"))
4272                         strcpy(arg, "mjpeg");
4273                     stream->fmt = ffserver_guess_format(arg, NULL, NULL);
4274                     if (!stream->fmt) {
4275                         ERROR("Unknown Format: %s\n", arg);
4276                     }
4277                 }
4278                 if (stream->fmt) {
4279                     audio_id = stream->fmt->audio_codec;
4280                     video_id = stream->fmt->video_codec;
4281                 }
4282             }
4283         } else if (!av_strcasecmp(cmd, "InputFormat")) {
4284             get_arg(arg, sizeof(arg), &p);
4285             if (stream) {
4286                 stream->ifmt = av_find_input_format(arg);
4287                 if (!stream->ifmt) {
4288                     ERROR("Unknown input format: %s\n", arg);
4289                 }
4290             }
4291         } else if (!av_strcasecmp(cmd, "FaviconURL")) {
4292             if (stream && stream->stream_type == STREAM_TYPE_STATUS) {
4293                 get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4294             } else {
4295                 ERROR("FaviconURL only permitted for status streams\n");
4296             }
4297         } else if (!av_strcasecmp(cmd, "Author")) {
4298             if (stream)
4299                 get_arg(stream->author, sizeof(stream->author), &p);
4300         } else if (!av_strcasecmp(cmd, "Comment")) {
4301             if (stream)
4302                 get_arg(stream->comment, sizeof(stream->comment), &p);
4303         } else if (!av_strcasecmp(cmd, "Copyright")) {
4304             if (stream)
4305                 get_arg(stream->copyright, sizeof(stream->copyright), &p);
4306         } else if (!av_strcasecmp(cmd, "Title")) {
4307             if (stream)
4308                 get_arg(stream->title, sizeof(stream->title), &p);
4309         } else if (!av_strcasecmp(cmd, "Preroll")) {
4310             get_arg(arg, sizeof(arg), &p);
4311             if (stream)
4312                 stream->prebuffer = atof(arg) * 1000;
4313         } else if (!av_strcasecmp(cmd, "StartSendOnKey")) {
4314             if (stream)
4315                 stream->send_on_key = 1;
4316         } else if (!av_strcasecmp(cmd, "AudioCodec")) {
4317             get_arg(arg, sizeof(arg), &p);
4318             audio_id = opt_audio_codec(arg);
4319             if (audio_id == CODEC_ID_NONE) {
4320                 ERROR("Unknown AudioCodec: %s\n", arg);
4321             }
4322         } else if (!av_strcasecmp(cmd, "VideoCodec")) {
4323             get_arg(arg, sizeof(arg), &p);
4324             video_id = opt_video_codec(arg);
4325             if (video_id == CODEC_ID_NONE) {
4326                 ERROR("Unknown VideoCodec: %s\n", arg);
4327             }
4328         } else if (!av_strcasecmp(cmd, "MaxTime")) {
4329             get_arg(arg, sizeof(arg), &p);
4330             if (stream)
4331                 stream->max_time = atof(arg) * 1000;
4332         } else if (!av_strcasecmp(cmd, "AudioBitRate")) {
4333             get_arg(arg, sizeof(arg), &p);
4334             if (stream)
4335                 audio_enc.bit_rate = lrintf(atof(arg) * 1000);
4336         } else if (!av_strcasecmp(cmd, "AudioChannels")) {
4337             get_arg(arg, sizeof(arg), &p);
4338             if (stream)
4339                 audio_enc.channels = atoi(arg);
4340         } else if (!av_strcasecmp(cmd, "AudioSampleRate")) {
4341             get_arg(arg, sizeof(arg), &p);
4342             if (stream)
4343                 audio_enc.sample_rate = atoi(arg);
4344         } else if (!av_strcasecmp(cmd, "AudioQuality")) {
4345             get_arg(arg, sizeof(arg), &p);
4346             if (stream) {
4347 //                audio_enc.quality = atof(arg) * 1000;
4348             }
4349         } else if (!av_strcasecmp(cmd, "VideoBitRateRange")) {
4350             if (stream) {
4351                 int minrate, maxrate;
4352
4353                 get_arg(arg, sizeof(arg), &p);
4354
4355                 if (sscanf(arg, "%d-%d", &minrate, &maxrate) == 2) {
4356                     video_enc.rc_min_rate = minrate * 1000;
4357                     video_enc.rc_max_rate = maxrate * 1000;
4358                 } else {
4359                     ERROR("Incorrect format for VideoBitRateRange -- should be <min>-<max>: %s\n", arg);
4360                 }
4361             }
4362         } else if (!av_strcasecmp(cmd, "Debug")) {
4363             if (stream) {
4364                 get_arg(arg, sizeof(arg), &p);
4365                 video_enc.debug = strtol(arg,0,0);
4366             }
4367         } else if (!av_strcasecmp(cmd, "Strict")) {
4368             if (stream) {
4369                 get_arg(arg, sizeof(arg), &p);
4370                 video_enc.strict_std_compliance = atoi(arg);
4371             }
4372         } else if (!av_strcasecmp(cmd, "VideoBufferSize")) {
4373             if (stream) {
4374                 get_arg(arg, sizeof(arg), &p);
4375                 video_enc.rc_buffer_size = atoi(arg) * 8*1024;
4376             }
4377         } else if (!av_strcasecmp(cmd, "VideoBitRateTolerance")) {
4378             if (stream) {
4379                 get_arg(arg, sizeof(arg), &p);
4380                 video_enc.bit_rate_tolerance = atoi(arg) * 1000;
4381             }
4382         } else if (!av_strcasecmp(cmd, "VideoBitRate")) {
4383             get_arg(arg, sizeof(arg), &p);
4384             if (stream) {
4385                 video_enc.bit_rate = atoi(arg) * 1000;
4386             }
4387         } else if (!av_strcasecmp(cmd, "VideoSize")) {
4388             get_arg(arg, sizeof(arg), &p);
4389             if (stream) {
4390                 av_parse_video_size(&video_enc.width, &video_enc.height, arg);
4391                 if ((video_enc.width % 16) != 0 ||
4392                     (video_enc.height % 16) != 0) {
4393                     ERROR("Image size must be a multiple of 16\n");
4394                 }
4395             }
4396         } else if (!av_strcasecmp(cmd, "VideoFrameRate")) {
4397             get_arg(arg, sizeof(arg), &p);
4398             if (stream) {
4399                 AVRational frame_rate;
4400                 if (av_parse_video_rate(&frame_rate, arg) < 0) {
4401                     ERROR("Incorrect frame rate: %s\n", arg);
4402                 } else {
4403                     video_enc.time_base.num = frame_rate.den;
4404                     video_enc.time_base.den = frame_rate.num;
4405                 }
4406             }
4407         } else if (!av_strcasecmp(cmd, "VideoGopSize")) {
4408             get_arg(arg, sizeof(arg), &p);
4409             if (stream)
4410                 video_enc.gop_size = atoi(arg);
4411         } else if (!av_strcasecmp(cmd, "VideoIntraOnly")) {
4412             if (stream)
4413                 video_enc.gop_size = 1;
4414         } else if (!av_strcasecmp(cmd, "VideoHighQuality")) {
4415             if (stream)
4416                 video_enc.mb_decision = FF_MB_DECISION_BITS;
4417         } else if (!av_strcasecmp(cmd, "Video4MotionVector")) {
4418             if (stream) {
4419                 video_enc.mb_decision = FF_MB_DECISION_BITS; //FIXME remove
4420                 video_enc.flags |= CODEC_FLAG_4MV;
4421             }
4422         } else if (!av_strcasecmp(cmd, "AVOptionVideo") ||
4423                    !av_strcasecmp(cmd, "AVOptionAudio")) {
4424             char arg2[1024];
4425             AVCodecContext *avctx;
4426             int type;
4427             get_arg(arg, sizeof(arg), &p);
4428             get_arg(arg2, sizeof(arg2), &p);
4429             if (!av_strcasecmp(cmd, "AVOptionVideo")) {
4430                 avctx = &video_enc;
4431                 type = AV_OPT_FLAG_VIDEO_PARAM;
4432             } else {
4433                 avctx = &audio_enc;
4434                 type = AV_OPT_FLAG_AUDIO_PARAM;
4435             }
4436             if (ffserver_opt_default(arg, arg2, avctx, type|AV_OPT_FLAG_ENCODING_PARAM)) {
4437                 ERROR("AVOption error: %s %s\n", arg, arg2);
4438             }
4439         } else if (!av_strcasecmp(cmd, "AVPresetVideo") ||
4440                    !av_strcasecmp(cmd, "AVPresetAudio")) {
4441             AVCodecContext *avctx;
4442             int type;
4443             get_arg(arg, sizeof(arg), &p);
4444             if (!av_strcasecmp(cmd, "AVPresetVideo")) {
4445                 avctx = &video_enc;
4446                 video_enc.codec_id = video_id;
4447                 type = AV_OPT_FLAG_VIDEO_PARAM;
4448             } else {
4449                 avctx = &audio_enc;
4450                 audio_enc.codec_id = audio_id;
4451                 type = AV_OPT_FLAG_AUDIO_PARAM;
4452             }
4453             if (ffserver_opt_preset(arg, avctx, type|AV_OPT_FLAG_ENCODING_PARAM, &audio_id, &video_id)) {
4454                 ERROR("AVPreset error: %s\n", arg);
4455             }
4456         } else if (!av_strcasecmp(cmd, "VideoTag")) {
4457             get_arg(arg, sizeof(arg), &p);
4458             if ((strlen(arg) == 4) && stream)
4459                 video_enc.codec_tag = MKTAG(arg[0], arg[1], arg[2], arg[3]);
4460         } else if (!av_strcasecmp(cmd, "BitExact")) {
4461             if (stream)
4462                 video_enc.flags |= CODEC_FLAG_BITEXACT;
4463         } else if (!av_strcasecmp(cmd, "DctFastint")) {
4464             if (stream)
4465                 video_enc.dct_algo  = FF_DCT_FASTINT;
4466         } else if (!av_strcasecmp(cmd, "IdctSimple")) {
4467             if (stream)
4468                 video_enc.idct_algo = FF_IDCT_SIMPLE;
4469         } else if (!av_strcasecmp(cmd, "Qscale")) {
4470             get_arg(arg, sizeof(arg), &p);
4471             if (stream) {
4472                 video_enc.flags |= CODEC_FLAG_QSCALE;
4473                 video_enc.global_quality = FF_QP2LAMBDA * atoi(arg);
4474             }
4475         } else if (!av_strcasecmp(cmd, "VideoQDiff")) {
4476             get_arg(arg, sizeof(arg), &p);
4477             if (stream) {
4478                 video_enc.max_qdiff = atoi(arg);
4479                 if (video_enc.max_qdiff < 1 || video_enc.max_qdiff > 31) {
4480                     ERROR("VideoQDiff out of range\n");
4481                 }
4482             }
4483         } else if (!av_strcasecmp(cmd, "VideoQMax")) {
4484             get_arg(arg, sizeof(arg), &p);
4485             if (stream) {
4486                 video_enc.qmax = atoi(arg);
4487                 if (video_enc.qmax < 1 || video_enc.qmax > 31) {
4488                     ERROR("VideoQMax out of range\n");
4489                 }
4490             }
4491         } else if (!av_strcasecmp(cmd, "VideoQMin")) {
4492             get_arg(arg, sizeof(arg), &p);
4493             if (stream) {
4494                 video_enc.qmin = atoi(arg);
4495                 if (video_enc.qmin < 1 || video_enc.qmin > 31) {
4496                     ERROR("VideoQMin out of range\n");
4497                 }
4498             }
4499         } else if (!av_strcasecmp(cmd, "LumaElim")) {
4500             get_arg(arg, sizeof(arg), &p);
4501             if (stream)
4502                 video_enc.luma_elim_threshold = atoi(arg);
4503         } else if (!av_strcasecmp(cmd, "ChromaElim")) {
4504             get_arg(arg, sizeof(arg), &p);
4505             if (stream)
4506                 video_enc.chroma_elim_threshold = atoi(arg);
4507         } else if (!av_strcasecmp(cmd, "LumiMask")) {
4508             get_arg(arg, sizeof(arg), &p);
4509             if (stream)
4510                 video_enc.lumi_masking = atof(arg);
4511         } else if (!av_strcasecmp(cmd, "DarkMask")) {
4512             get_arg(arg, sizeof(arg), &p);
4513             if (stream)
4514                 video_enc.dark_masking = atof(arg);
4515         } else if (!av_strcasecmp(cmd, "NoVideo")) {
4516             video_id = CODEC_ID_NONE;
4517         } else if (!av_strcasecmp(cmd, "NoAudio")) {
4518             audio_id = CODEC_ID_NONE;
4519         } else if (!av_strcasecmp(cmd, "ACL")) {
4520             parse_acl_row(stream, feed, NULL, p, filename, line_num);
4521         } else if (!av_strcasecmp(cmd, "DynamicACL")) {
4522             if (stream) {
4523                 get_arg(stream->dynamic_acl, sizeof(stream->dynamic_acl), &p);
4524             }
4525         } else if (!av_strcasecmp(cmd, "RTSPOption")) {
4526             get_arg(arg, sizeof(arg), &p);
4527             if (stream) {
4528                 av_freep(&stream->rtsp_option);
4529                 stream->rtsp_option = av_strdup(arg);
4530             }
4531         } else if (!av_strcasecmp(cmd, "MulticastAddress")) {
4532             get_arg(arg, sizeof(arg), &p);
4533             if (stream) {
4534                 if (resolve_host(&stream->multicast_ip, arg) != 0) {
4535                     ERROR("Invalid host/IP address: %s\n", arg);
4536                 }
4537                 stream->is_multicast = 1;
4538                 stream->loop = 1; /* default is looping */
4539             }
4540         } else if (!av_strcasecmp(cmd, "MulticastPort")) {
4541             get_arg(arg, sizeof(arg), &p);
4542             if (stream)
4543                 stream->multicast_port = atoi(arg);
4544         } else if (!av_strcasecmp(cmd, "MulticastTTL")) {
4545             get_arg(arg, sizeof(arg), &p);
4546             if (stream)
4547                 stream->multicast_ttl = atoi(arg);
4548         } else if (!av_strcasecmp(cmd, "NoLoop")) {
4549             if (stream)
4550                 stream->loop = 0;
4551         } else if (!av_strcasecmp(cmd, "</Stream>")) {
4552             if (!stream) {
4553                 ERROR("No corresponding <Stream> for </Stream>\n");
4554             } else {
4555                 if (stream->feed && stream->fmt && strcmp(stream->fmt->name, "ffm") != 0) {
4556                     if (audio_id != CODEC_ID_NONE) {
4557                         audio_enc.codec_type = AVMEDIA_TYPE_AUDIO;
4558                         audio_enc.codec_id = audio_id;
4559                         add_codec(stream, &audio_enc);
4560                     }
4561                     if (video_id != CODEC_ID_NONE) {
4562                         video_enc.codec_type = AVMEDIA_TYPE_VIDEO;
4563                         video_enc.codec_id = video_id;
4564                         add_codec(stream, &video_enc);
4565                     }
4566                 }
4567                 stream = NULL;
4568             }
4569         } else if (!av_strcasecmp(cmd, "<Redirect")) {
4570             /*********************************************/
4571             char *q;
4572             if (stream || feed || redirect) {
4573                 ERROR("Already in a tag\n");
4574             } else {
4575                 redirect = av_mallocz(sizeof(FFStream));
4576                 *last_stream = redirect;
4577                 last_stream = &redirect->next;
4578
4579                 get_arg(redirect->filename, sizeof(redirect->filename), &p);
4580                 q = strrchr(redirect->filename, '>');
4581                 if (*q)
4582                     *q = '\0';
4583                 redirect->stream_type = STREAM_TYPE_REDIRECT;
4584             }
4585         } else if (!av_strcasecmp(cmd, "URL")) {
4586             if (redirect)
4587                 get_arg(redirect->feed_filename, sizeof(redirect->feed_filename), &p);
4588         } else if (!av_strcasecmp(cmd, "</Redirect>")) {
4589             if (!redirect) {
4590                 ERROR("No corresponding <Redirect> for </Redirect>\n");
4591             } else {
4592                 if (!redirect->feed_filename[0]) {
4593                     ERROR("No URL found for <Redirect>\n");
4594                 }
4595                 redirect = NULL;
4596             }
4597         } else if (!av_strcasecmp(cmd, "LoadModule")) {
4598             get_arg(arg, sizeof(arg), &p);
4599 #if HAVE_DLOPEN
4600             load_module(arg);
4601 #else
4602             ERROR("Module support not compiled into this version: '%s'\n", arg);
4603 #endif
4604         } else {
4605             ERROR("Incorrect keyword: '%s'\n", cmd);
4606         }
4607     }
4608 #undef ERROR
4609
4610     fclose(f);
4611     if (errors)
4612         return -1;
4613     else
4614         return 0;
4615 }
4616
4617 static void handle_child_exit(int sig)
4618 {
4619     pid_t pid;
4620     int status;
4621
4622     while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
4623         FFStream *feed;
4624
4625         for (feed = first_feed; feed; feed = feed->next) {
4626             if (feed->pid == pid) {
4627                 int uptime = time(0) - feed->pid_start;
4628
4629                 feed->pid = 0;
4630                 fprintf(stderr, "%s: Pid %d exited with status %d after %d seconds\n", feed->filename, pid, status, uptime);
4631
4632                 if (uptime < 30)
4633                     /* Turn off any more restarts */
4634                     feed->child_argv = 0;
4635             }
4636         }
4637     }
4638
4639     need_to_start_children = 1;
4640 }
4641
4642 static void opt_debug(void)
4643 {
4644     ffserver_debug = 1;
4645     ffserver_daemon = 0;
4646     logfilename[0] = '-';
4647 }
4648
4649 static int opt_help(const char *opt, const char *arg)
4650 {
4651     printf("usage: ffserver [options]\n"
4652            "Hyper fast multi format Audio/Video streaming server\n");
4653     printf("\n");
4654     show_help_options(options, "Main options:\n", 0, 0);
4655     return 0;
4656 }
4657
4658 static const OptionDef options[] = {
4659 #include "cmdutils_common_opts.h"
4660     { "n", OPT_BOOL, {(void *)&no_launch }, "enable no-launch mode" },
4661     { "d", 0, {(void*)opt_debug}, "enable debug mode" },
4662     { "f", HAS_ARG | OPT_STRING, {(void*)&config_filename }, "use configfile instead of /etc/ffserver.conf", "configfile" },
4663     { NULL },
4664 };
4665
4666 int main(int argc, char **argv)
4667 {
4668     struct sigaction sigact = { { 0 } };
4669
4670     parse_loglevel(argc, argv, options);
4671     av_register_all();
4672     avformat_network_init();
4673
4674     show_banner(argc, argv, options);
4675
4676     my_program_name = argv[0];
4677     my_program_dir = getcwd(0, 0);
4678     ffserver_daemon = 1;
4679
4680     parse_options(NULL, argc, argv, options, NULL);
4681
4682     unsetenv("http_proxy");             /* Kill the http_proxy */
4683
4684     av_lfg_init(&random_state, av_get_random_seed());
4685
4686     sigact.sa_handler = handle_child_exit;
4687     sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
4688     sigaction(SIGCHLD, &sigact, 0);
4689
4690     if (parse_ffconfig(config_filename) < 0) {
4691         fprintf(stderr, "Incorrect config file - exiting.\n");
4692         exit(1);
4693     }
4694
4695     /* open log file if needed */
4696     if (logfilename[0] != '\0') {
4697         if (!strcmp(logfilename, "-"))
4698             logfile = stdout;
4699         else
4700             logfile = fopen(logfilename, "a");
4701         av_log_set_callback(http_av_log);
4702     }
4703
4704     build_file_streams();
4705
4706     build_feed_streams();
4707
4708     compute_bandwidth();
4709
4710     /* put the process in background and detach it from its TTY */
4711     if (ffserver_daemon) {
4712         int pid;
4713
4714         pid = fork();
4715         if (pid < 0) {
4716             perror("fork");
4717             exit(1);
4718         } else if (pid > 0) {
4719             /* parent : exit */
4720             exit(0);
4721         } else {
4722             /* child */
4723             setsid();
4724             close(0);
4725             open("/dev/null", O_RDWR);
4726             if (strcmp(logfilename, "-") != 0) {
4727                 close(1);
4728                 dup(0);
4729             }
4730             close(2);
4731             dup(0);
4732         }
4733     }
4734
4735     /* signal init */
4736     signal(SIGPIPE, SIG_IGN);
4737
4738     if (ffserver_daemon)
4739         chdir("/");
4740
4741     if (http_server() < 0) {
4742         http_log("Could not start server\n");
4743         exit(1);
4744     }
4745
4746     return 0;
4747 }