OSDN Git Service

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