OSDN Git Service

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