OSDN Git Service

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