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