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