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