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