OSDN Git Service

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