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