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