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