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