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