OSDN Git Service

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