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