]> git.sesse.net Git - ffmpeg/blob - avserver.c
cmdutils: extend -h to allow printing codec details.
[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 <stdlib.h>
28 #include "libavformat/avformat.h"
29 // FIXME those are internal headers, avserver _really_ shouldn't use them
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 #include "libavformat/avio_internal.h"
36 #include "libavformat/internal.h"
37 #include "libavformat/url.h"
38
39 #include "libavutil/avstring.h"
40 #include "libavutil/lfg.h"
41 #include "libavutil/dict.h"
42 #include "libavutil/mathematics.h"
43 #include "libavutil/random_seed.h"
44 #include "libavutil/parseutils.h"
45 #include "libavutil/opt.h"
46 #include <stdarg.h>
47 #include <unistd.h>
48 #include <fcntl.h>
49 #include <sys/ioctl.h>
50 #if HAVE_POLL_H
51 #include <poll.h>
52 #endif
53 #include <errno.h>
54 #include <time.h>
55 #include <sys/wait.h>
56 #include <signal.h>
57 #if HAVE_DLFCN_H
58 #include <dlfcn.h>
59 #endif
60
61 #include "cmdutils.h"
62
63 const char program_name[] = "avserver";
64 const int program_birth_year = 2000;
65
66 static const OptionDef options[];
67
68 enum HTTPState {
69     HTTPSTATE_WAIT_REQUEST,
70     HTTPSTATE_SEND_HEADER,
71     HTTPSTATE_SEND_DATA_HEADER,
72     HTTPSTATE_SEND_DATA,          /* sending TCP or UDP data */
73     HTTPSTATE_SEND_DATA_TRAILER,
74     HTTPSTATE_RECEIVE_DATA,
75     HTTPSTATE_WAIT_FEED,          /* wait for data from the feed */
76     HTTPSTATE_READY,
77
78     RTSPSTATE_WAIT_REQUEST,
79     RTSPSTATE_SEND_REPLY,
80     RTSPSTATE_SEND_PACKET,
81 };
82
83 static const char *http_state[] = {
84     "HTTP_WAIT_REQUEST",
85     "HTTP_SEND_HEADER",
86
87     "SEND_DATA_HEADER",
88     "SEND_DATA",
89     "SEND_DATA_TRAILER",
90     "RECEIVE_DATA",
91     "WAIT_FEED",
92     "READY",
93
94     "RTSP_WAIT_REQUEST",
95     "RTSP_SEND_REPLY",
96     "RTSP_SEND_PACKET",
97 };
98
99 #define MAX_STREAMS 20
100
101 #define IOBUFFER_INIT_SIZE 8192
102
103 /* timeouts are in ms */
104 #define HTTP_REQUEST_TIMEOUT (15 * 1000)
105 #define RTSP_REQUEST_TIMEOUT (3600 * 24 * 1000)
106
107 #define SYNC_TIMEOUT (10 * 1000)
108
109 typedef struct RTSPActionServerSetup {
110     uint32_t ipaddr;
111     char transport_option[512];
112 } RTSPActionServerSetup;
113
114 typedef struct {
115     int64_t count1, count2;
116     int64_t time1, time2;
117 } DataRateData;
118
119 /* context associated with one connection */
120 typedef struct HTTPContext {
121     enum HTTPState state;
122     int fd; /* socket file descriptor */
123     struct sockaddr_in from_addr; /* origin */
124     struct pollfd *poll_entry; /* used when polling */
125     int64_t timeout;
126     uint8_t *buffer_ptr, *buffer_end;
127     int http_error;
128     int post;
129     int chunked_encoding;
130     int chunk_size;               /* 0 if it needs to be read */
131     struct HTTPContext *next;
132     int got_key_frame; /* stream 0 => 1, stream 1 => 2, stream 2=> 4 */
133     int64_t data_count;
134     /* feed input */
135     int feed_fd;
136     /* input format handling */
137     AVFormatContext *fmt_in;
138     int64_t start_time;            /* In milliseconds - this wraps fairly often */
139     int64_t first_pts;            /* initial pts value */
140     int64_t cur_pts;             /* current pts value from the stream in us */
141     int64_t cur_frame_duration;  /* duration of the current frame in us */
142     int cur_frame_bytes;       /* output frame size, needed to compute
143                                   the time at which we send each
144                                   packet */
145     int pts_stream_index;        /* stream we choose as clock reference */
146     int64_t cur_clock;           /* current clock reference value in us */
147     /* output format handling */
148     struct FFStream *stream;
149     /* -1 is invalid stream */
150     int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
151     int switch_feed_streams[MAX_STREAMS]; /* index of streams in the feed */
152     int switch_pending;
153     AVFormatContext fmt_ctx; /* instance of FFStream for one user */
154     int last_packet_sent; /* true if last data packet was sent */
155     int suppress_log;
156     DataRateData datarate;
157     int wmp_client_id;
158     char protocol[16];
159     char method[16];
160     char url[128];
161     int buffer_size;
162     uint8_t *buffer;
163     int is_packetized; /* if true, the stream is packetized */
164     int packet_stream_index; /* current stream for output in state machine */
165
166     /* RTSP state specific */
167     uint8_t *pb_buffer; /* XXX: use that in all the code */
168     AVIOContext *pb;
169     int seq; /* RTSP sequence number */
170
171     /* RTP state specific */
172     enum RTSPLowerTransport rtp_protocol;
173     char session_id[32]; /* session id */
174     AVFormatContext *rtp_ctx[MAX_STREAMS];
175
176     /* RTP/UDP specific */
177     URLContext *rtp_handles[MAX_STREAMS];
178
179     /* RTP/TCP specific */
180     struct HTTPContext *rtsp_c;
181     uint8_t *packet_buffer, *packet_buffer_ptr, *packet_buffer_end;
182 } HTTPContext;
183
184 /* each generated stream is described here */
185 enum StreamType {
186     STREAM_TYPE_LIVE,
187     STREAM_TYPE_STATUS,
188     STREAM_TYPE_REDIRECT,
189 };
190
191 enum IPAddressAction {
192     IP_ALLOW = 1,
193     IP_DENY,
194 };
195
196 typedef struct IPAddressACL {
197     struct IPAddressACL *next;
198     enum IPAddressAction action;
199     /* These are in host order */
200     struct in_addr first;
201     struct in_addr last;
202 } IPAddressACL;
203
204 /* description of each stream of the avserver.conf file */
205 typedef struct FFStream {
206     enum StreamType stream_type;
207     char filename[1024];     /* stream filename */
208     struct FFStream *feed;   /* feed we are using (can be null if
209                                 coming from file) */
210     AVDictionary *in_opts;   /* input parameters */
211     AVInputFormat *ifmt;       /* if non NULL, force input format */
212     AVOutputFormat *fmt;
213     IPAddressACL *acl;
214     char dynamic_acl[1024];
215     int nb_streams;
216     int prebuffer;      /* Number of millseconds early to start */
217     int64_t max_time;      /* Number of milliseconds to run */
218     int send_on_key;
219     AVStream *streams[MAX_STREAMS];
220     int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
221     char feed_filename[1024]; /* file name of the feed storage, or
222                                  input file name for a stream */
223     char author[512];
224     char title[512];
225     char copyright[512];
226     char comment[512];
227     pid_t pid;  /* of avconv process */
228     time_t pid_start;  /* of avconv process */
229     char **child_argv;
230     struct FFStream *next;
231     unsigned bandwidth; /* bandwidth, in kbits/s */
232     /* RTSP options */
233     char *rtsp_option;
234     /* multicast specific */
235     int is_multicast;
236     struct in_addr multicast_ip;
237     int multicast_port; /* first port used for multicast */
238     int multicast_ttl;
239     int loop; /* if true, send the stream in loops (only meaningful if file) */
240
241     /* feed specific */
242     int feed_opened;     /* true if someone is writing to the feed */
243     int is_feed;         /* true if it is a feed */
244     int readonly;        /* True if writing is prohibited to the file */
245     int truncate;        /* True if feeder connection truncate the feed file */
246     int conns_served;
247     int64_t bytes_served;
248     int64_t feed_max_size;      /* maximum storage size, zero means unlimited */
249     int64_t feed_write_index;   /* current write position in feed (it wraps around) */
250     int64_t feed_size;          /* current size of feed */
251     struct FFStream *next_feed;
252 } FFStream;
253
254 typedef struct FeedData {
255     long long data_count;
256     float avg_frame_size;   /* frame size averaged over last frames with exponential mean */
257 } FeedData;
258
259 static struct sockaddr_in my_http_addr;
260 static struct sockaddr_in my_rtsp_addr;
261
262 static char logfilename[1024];
263 static HTTPContext *first_http_ctx;
264 static FFStream *first_feed;   /* contains only feeds */
265 static FFStream *first_stream; /* contains all streams, including feeds */
266
267 static void new_connection(int server_fd, int is_rtsp);
268 static void close_connection(HTTPContext *c);
269
270 /* HTTP handling */
271 static int handle_connection(HTTPContext *c);
272 static int http_parse_request(HTTPContext *c);
273 static int http_send_data(HTTPContext *c);
274 static void compute_status(HTTPContext *c);
275 static int open_input_stream(HTTPContext *c, const char *info);
276 static int http_start_receive_data(HTTPContext *c);
277 static int http_receive_data(HTTPContext *c);
278
279 /* RTSP handling */
280 static int rtsp_parse_request(HTTPContext *c);
281 static void rtsp_cmd_describe(HTTPContext *c, const char *url);
282 static void rtsp_cmd_options(HTTPContext *c, const char *url);
283 static void rtsp_cmd_setup(HTTPContext *c, const char *url, RTSPMessageHeader *h);
284 static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h);
285 static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h);
286 static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPMessageHeader *h);
287
288 /* SDP handling */
289 static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
290                                    struct in_addr my_ip);
291
292 /* RTP handling */
293 static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
294                                        FFStream *stream, const char *session_id,
295                                        enum RTSPLowerTransport rtp_protocol);
296 static int rtp_new_av_stream(HTTPContext *c,
297                              int stream_index, struct sockaddr_in *dest_addr,
298                              HTTPContext *rtsp_c);
299
300 static const char *my_program_name;
301 static const char *my_program_dir;
302
303 static const char *config_filename = "/etc/avserver.conf";
304
305 static int avserver_debug;
306 static int avserver_daemon;
307 static int no_launch;
308 static int need_to_start_children;
309
310 /* maximum number of simultaneous HTTP connections */
311 static unsigned int nb_max_http_connections = 2000;
312 static unsigned int nb_max_connections = 5;
313 static unsigned int nb_connections;
314
315 static uint64_t max_bandwidth = 1000;
316 static uint64_t current_bandwidth;
317
318 static int64_t cur_time;           // Making this global saves on passing it around everywhere
319
320 static AVLFG random_state;
321
322 static FILE *logfile = NULL;
323
324 void exit_program(int ret)
325 {
326     exit(ret);
327 }
328
329 /* FIXME: make avserver work with IPv6 */
330 /* resolve host with also IP address parsing */
331 static int resolve_host(struct in_addr *sin_addr, const char *hostname)
332 {
333
334     if (!ff_inet_aton(hostname, sin_addr)) {
335 #if HAVE_GETADDRINFO
336         struct addrinfo *ai, *cur;
337         struct addrinfo hints = { 0 };
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, "avconv");
478
479                 http_log("Launch command line: ");
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         avformat_close_input(&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             ffurl_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 (av_strncasecmp(p, "Pragma:", 7) == 0) {
1089             const char *q = p + 7;
1090
1091             while (*q && *q != '\n' && isspace(*q))
1092                 q++;
1093
1094             if (av_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 (av_strcasecmp(arg, "allow") == 0)
1275         acl.action = IP_ALLOW;
1276     else if (av_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 (!av_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 (av_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 || av_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 (av_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 (av_strncasecmp(p, "Pragma: log-line=", 17) == 0) {
1746                     logline = p;
1747                     break;
1748                 }
1749                 if (av_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 static int open_input_stream(HTTPContext *c, const char *info)
2117 {
2118     char buf[128];
2119     char input_filename[1024];
2120     AVFormatContext *s = NULL;
2121     int i, ret;
2122     int64_t stream_pos;
2123
2124     /* find file name */
2125     if (c->stream->feed) {
2126         strcpy(input_filename, c->stream->feed->feed_filename);
2127         /* compute position (absolute time) */
2128         if (av_find_info_tag(buf, sizeof(buf), "date", info)) {
2129             if ((ret = av_parse_time(&stream_pos, buf, 0)) < 0)
2130                 return ret;
2131         } else if (av_find_info_tag(buf, sizeof(buf), "buffer", info)) {
2132             int prebuffer = strtol(buf, 0, 10);
2133             stream_pos = av_gettime() - prebuffer * (int64_t)1000000;
2134         } else
2135             stream_pos = av_gettime() - c->stream->prebuffer * (int64_t)1000;
2136     } else {
2137         strcpy(input_filename, c->stream->feed_filename);
2138         /* compute position (relative time) */
2139         if (av_find_info_tag(buf, sizeof(buf), "date", info)) {
2140             if ((ret = av_parse_time(&stream_pos, buf, 1)) < 0)
2141                 return ret;
2142         } else
2143             stream_pos = 0;
2144     }
2145     if (input_filename[0] == '\0')
2146         return -1;
2147
2148     /* open stream */
2149     if ((ret = avformat_open_input(&s, input_filename, c->stream->ifmt, &c->stream->in_opts)) < 0) {
2150         http_log("could not open %s: %d\n", input_filename, ret);
2151         return -1;
2152     }
2153     s->flags |= AVFMT_FLAG_GENPTS;
2154     c->fmt_in = s;
2155     if (strcmp(s->iformat->name, "ffm") && avformat_find_stream_info(c->fmt_in, NULL) < 0) {
2156         http_log("Could not find stream info '%s'\n", input_filename);
2157         avformat_close_input(&s);
2158         return -1;
2159     }
2160
2161     /* choose stream as clock source (we favorize video stream if
2162        present) for packet sending */
2163     c->pts_stream_index = 0;
2164     for(i=0;i<c->stream->nb_streams;i++) {
2165         if (c->pts_stream_index == 0 &&
2166             c->stream->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
2167             c->pts_stream_index = i;
2168         }
2169     }
2170
2171     if (c->fmt_in->iformat->read_seek)
2172         av_seek_frame(c->fmt_in, -1, stream_pos, 0);
2173     /* set the start time (needed for maxtime and RTP packet timing) */
2174     c->start_time = cur_time;
2175     c->first_pts = AV_NOPTS_VALUE;
2176     return 0;
2177 }
2178
2179 /* return the server clock (in us) */
2180 static int64_t get_server_clock(HTTPContext *c)
2181 {
2182     /* compute current pts value from system time */
2183     return (cur_time - c->start_time) * 1000;
2184 }
2185
2186 /* return the estimated time at which the current packet must be sent
2187    (in us) */
2188 static int64_t get_packet_send_clock(HTTPContext *c)
2189 {
2190     int bytes_left, bytes_sent, frame_bytes;
2191
2192     frame_bytes = c->cur_frame_bytes;
2193     if (frame_bytes <= 0)
2194         return c->cur_pts;
2195     else {
2196         bytes_left = c->buffer_end - c->buffer_ptr;
2197         bytes_sent = frame_bytes - bytes_left;
2198         return c->cur_pts + (c->cur_frame_duration * bytes_sent) / frame_bytes;
2199     }
2200 }
2201
2202
2203 static int http_prepare_data(HTTPContext *c)
2204 {
2205     int i, len, ret;
2206     AVFormatContext *ctx;
2207
2208     av_freep(&c->pb_buffer);
2209     switch(c->state) {
2210     case HTTPSTATE_SEND_DATA_HEADER:
2211         memset(&c->fmt_ctx, 0, sizeof(c->fmt_ctx));
2212         av_dict_set(&c->fmt_ctx.metadata, "author"   , c->stream->author   , 0);
2213         av_dict_set(&c->fmt_ctx.metadata, "comment"  , c->stream->comment  , 0);
2214         av_dict_set(&c->fmt_ctx.metadata, "copyright", c->stream->copyright, 0);
2215         av_dict_set(&c->fmt_ctx.metadata, "title"    , c->stream->title    , 0);
2216
2217         c->fmt_ctx.streams = av_mallocz(sizeof(AVStream *) * c->stream->nb_streams);
2218
2219         for(i=0;i<c->stream->nb_streams;i++) {
2220             AVStream *src;
2221             c->fmt_ctx.streams[i] = av_mallocz(sizeof(AVStream));
2222             /* if file or feed, then just take streams from FFStream struct */
2223             if (!c->stream->feed ||
2224                 c->stream->feed == c->stream)
2225                 src = c->stream->streams[i];
2226             else
2227                 src = c->stream->feed->streams[c->stream->feed_streams[i]];
2228
2229             *(c->fmt_ctx.streams[i]) = *src;
2230             c->fmt_ctx.streams[i]->priv_data = 0;
2231             c->fmt_ctx.streams[i]->codec->frame_number = 0; /* XXX: should be done in
2232                                            AVStream, not in codec */
2233         }
2234         /* set output format parameters */
2235         c->fmt_ctx.oformat = c->stream->fmt;
2236         c->fmt_ctx.nb_streams = c->stream->nb_streams;
2237
2238         c->got_key_frame = 0;
2239
2240         /* prepare header and save header data in a stream */
2241         if (avio_open_dyn_buf(&c->fmt_ctx.pb) < 0) {
2242             /* XXX: potential leak */
2243             return -1;
2244         }
2245         c->fmt_ctx.pb->seekable = 0;
2246
2247         /*
2248          * HACK to avoid mpeg ps muxer to spit many underflow errors
2249          * Default value from Libav
2250          * Try to set it use configuration option
2251          */
2252         c->fmt_ctx.max_delay = (int)(0.7*AV_TIME_BASE);
2253
2254         if (avformat_write_header(&c->fmt_ctx, NULL) < 0) {
2255             http_log("Error writing output header\n");
2256             return -1;
2257         }
2258         av_dict_free(&c->fmt_ctx.metadata);
2259
2260         len = avio_close_dyn_buf(c->fmt_ctx.pb, &c->pb_buffer);
2261         c->buffer_ptr = c->pb_buffer;
2262         c->buffer_end = c->pb_buffer + len;
2263
2264         c->state = HTTPSTATE_SEND_DATA;
2265         c->last_packet_sent = 0;
2266         break;
2267     case HTTPSTATE_SEND_DATA:
2268         /* find a new packet */
2269         /* read a packet from the input stream */
2270         if (c->stream->feed)
2271             ffm_set_write_index(c->fmt_in,
2272                                 c->stream->feed->feed_write_index,
2273                                 c->stream->feed->feed_size);
2274
2275         if (c->stream->max_time &&
2276             c->stream->max_time + c->start_time - cur_time < 0)
2277             /* We have timed out */
2278             c->state = HTTPSTATE_SEND_DATA_TRAILER;
2279         else {
2280             AVPacket pkt;
2281         redo:
2282             ret = av_read_frame(c->fmt_in, &pkt);
2283             if (ret < 0) {
2284                 if (c->stream->feed) {
2285                     /* if coming from feed, it means we reached the end of the
2286                        ffm file, so must wait for more data */
2287                     c->state = HTTPSTATE_WAIT_FEED;
2288                     return 1; /* state changed */
2289                 } else if (ret == AVERROR(EAGAIN)) {
2290                     /* input not ready, come back later */
2291                     return 0;
2292                 } else {
2293                     if (c->stream->loop) {
2294                         avformat_close_input(&c->fmt_in);
2295                         if (open_input_stream(c, "") < 0)
2296                             goto no_loop;
2297                         goto redo;
2298                     } else {
2299                     no_loop:
2300                         /* must send trailer now because eof or error */
2301                         c->state = HTTPSTATE_SEND_DATA_TRAILER;
2302                     }
2303                 }
2304             } else {
2305                 int source_index = pkt.stream_index;
2306                 /* update first pts if needed */
2307                 if (c->first_pts == AV_NOPTS_VALUE) {
2308                     c->first_pts = av_rescale_q(pkt.dts, c->fmt_in->streams[pkt.stream_index]->time_base, AV_TIME_BASE_Q);
2309                     c->start_time = cur_time;
2310                 }
2311                 /* send it to the appropriate stream */
2312                 if (c->stream->feed) {
2313                     /* if coming from a feed, select the right stream */
2314                     if (c->switch_pending) {
2315                         c->switch_pending = 0;
2316                         for(i=0;i<c->stream->nb_streams;i++) {
2317                             if (c->switch_feed_streams[i] == pkt.stream_index)
2318                                 if (pkt.flags & AV_PKT_FLAG_KEY)
2319                                     c->switch_feed_streams[i] = -1;
2320                             if (c->switch_feed_streams[i] >= 0)
2321                                 c->switch_pending = 1;
2322                         }
2323                     }
2324                     for(i=0;i<c->stream->nb_streams;i++) {
2325                         if (c->stream->feed_streams[i] == pkt.stream_index) {
2326                             AVStream *st = c->fmt_in->streams[source_index];
2327                             pkt.stream_index = i;
2328                             if (pkt.flags & AV_PKT_FLAG_KEY &&
2329                                 (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
2330                                  c->stream->nb_streams == 1))
2331                                 c->got_key_frame = 1;
2332                             if (!c->stream->send_on_key || c->got_key_frame)
2333                                 goto send_it;
2334                         }
2335                     }
2336                 } else {
2337                     AVCodecContext *codec;
2338                     AVStream *ist, *ost;
2339                 send_it:
2340                     ist = c->fmt_in->streams[source_index];
2341                     /* specific handling for RTP: we use several
2342                        output stream (one for each RTP
2343                        connection). XXX: need more abstract handling */
2344                     if (c->is_packetized) {
2345                         /* compute send time and duration */
2346                         c->cur_pts = av_rescale_q(pkt.dts, ist->time_base, AV_TIME_BASE_Q);
2347                         c->cur_pts -= c->first_pts;
2348                         c->cur_frame_duration = av_rescale_q(pkt.duration, ist->time_base, AV_TIME_BASE_Q);
2349                         /* find RTP context */
2350                         c->packet_stream_index = pkt.stream_index;
2351                         ctx = c->rtp_ctx[c->packet_stream_index];
2352                         if(!ctx) {
2353                             av_free_packet(&pkt);
2354                             break;
2355                         }
2356                         codec = ctx->streams[0]->codec;
2357                         /* only one stream per RTP connection */
2358                         pkt.stream_index = 0;
2359                     } else {
2360                         ctx = &c->fmt_ctx;
2361                         /* Fudge here */
2362                         codec = ctx->streams[pkt.stream_index]->codec;
2363                     }
2364
2365                     if (c->is_packetized) {
2366                         int max_packet_size;
2367                         if (c->rtp_protocol == RTSP_LOWER_TRANSPORT_TCP)
2368                             max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
2369                         else
2370                             max_packet_size = c->rtp_handles[c->packet_stream_index]->max_packet_size;
2371                         ret = ffio_open_dyn_packet_buf(&ctx->pb, max_packet_size);
2372                     } else {
2373                         ret = avio_open_dyn_buf(&ctx->pb);
2374                     }
2375                     if (ret < 0) {
2376                         /* XXX: potential leak */
2377                         return -1;
2378                     }
2379                     ost = ctx->streams[pkt.stream_index];
2380
2381                     ctx->pb->seekable = 0;
2382                     if (pkt.dts != AV_NOPTS_VALUE)
2383                         pkt.dts = av_rescale_q(pkt.dts, ist->time_base, ost->time_base);
2384                     if (pkt.pts != AV_NOPTS_VALUE)
2385                         pkt.pts = av_rescale_q(pkt.pts, ist->time_base, ost->time_base);
2386                     pkt.duration = av_rescale_q(pkt.duration, ist->time_base, ost->time_base);
2387                     if (av_write_frame(ctx, &pkt) < 0) {
2388                         http_log("Error writing frame to output\n");
2389                         c->state = HTTPSTATE_SEND_DATA_TRAILER;
2390                     }
2391
2392                     len = avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
2393                     c->cur_frame_bytes = len;
2394                     c->buffer_ptr = c->pb_buffer;
2395                     c->buffer_end = c->pb_buffer + len;
2396
2397                     codec->frame_number++;
2398                     if (len == 0) {
2399                         av_free_packet(&pkt);
2400                         goto redo;
2401                     }
2402                 }
2403                 av_free_packet(&pkt);
2404             }
2405         }
2406         break;
2407     default:
2408     case HTTPSTATE_SEND_DATA_TRAILER:
2409         /* last packet test ? */
2410         if (c->last_packet_sent || c->is_packetized)
2411             return -1;
2412         ctx = &c->fmt_ctx;
2413         /* prepare header */
2414         if (avio_open_dyn_buf(&ctx->pb) < 0) {
2415             /* XXX: potential leak */
2416             return -1;
2417         }
2418         c->fmt_ctx.pb->seekable = 0;
2419         av_write_trailer(ctx);
2420         len = avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
2421         c->buffer_ptr = c->pb_buffer;
2422         c->buffer_end = c->pb_buffer + len;
2423
2424         c->last_packet_sent = 1;
2425         break;
2426     }
2427     return 0;
2428 }
2429
2430 /* should convert the format at the same time */
2431 /* send data starting at c->buffer_ptr to the output connection
2432    (either UDP or TCP connection) */
2433 static int http_send_data(HTTPContext *c)
2434 {
2435     int len, ret;
2436
2437     for(;;) {
2438         if (c->buffer_ptr >= c->buffer_end) {
2439             ret = http_prepare_data(c);
2440             if (ret < 0)
2441                 return -1;
2442             else if (ret != 0)
2443                 /* state change requested */
2444                 break;
2445         } else {
2446             if (c->is_packetized) {
2447                 /* RTP data output */
2448                 len = c->buffer_end - c->buffer_ptr;
2449                 if (len < 4) {
2450                     /* fail safe - should never happen */
2451                 fail1:
2452                     c->buffer_ptr = c->buffer_end;
2453                     return 0;
2454                 }
2455                 len = (c->buffer_ptr[0] << 24) |
2456                     (c->buffer_ptr[1] << 16) |
2457                     (c->buffer_ptr[2] << 8) |
2458                     (c->buffer_ptr[3]);
2459                 if (len > (c->buffer_end - c->buffer_ptr))
2460                     goto fail1;
2461                 if ((get_packet_send_clock(c) - get_server_clock(c)) > 0) {
2462                     /* nothing to send yet: we can wait */
2463                     return 0;
2464                 }
2465
2466                 c->data_count += len;
2467                 update_datarate(&c->datarate, c->data_count);
2468                 if (c->stream)
2469                     c->stream->bytes_served += len;
2470
2471                 if (c->rtp_protocol == RTSP_LOWER_TRANSPORT_TCP) {
2472                     /* RTP packets are sent inside the RTSP TCP connection */
2473                     AVIOContext *pb;
2474                     int interleaved_index, size;
2475                     uint8_t header[4];
2476                     HTTPContext *rtsp_c;
2477
2478                     rtsp_c = c->rtsp_c;
2479                     /* if no RTSP connection left, error */
2480                     if (!rtsp_c)
2481                         return -1;
2482                     /* if already sending something, then wait. */
2483                     if (rtsp_c->state != RTSPSTATE_WAIT_REQUEST)
2484                         break;
2485                     if (avio_open_dyn_buf(&pb) < 0)
2486                         goto fail1;
2487                     interleaved_index = c->packet_stream_index * 2;
2488                     /* RTCP packets are sent at odd indexes */
2489                     if (c->buffer_ptr[1] == 200)
2490                         interleaved_index++;
2491                     /* write RTSP TCP header */
2492                     header[0] = '$';
2493                     header[1] = interleaved_index;
2494                     header[2] = len >> 8;
2495                     header[3] = len;
2496                     avio_write(pb, header, 4);
2497                     /* write RTP packet data */
2498                     c->buffer_ptr += 4;
2499                     avio_write(pb, c->buffer_ptr, len);
2500                     size = avio_close_dyn_buf(pb, &c->packet_buffer);
2501                     /* prepare asynchronous TCP sending */
2502                     rtsp_c->packet_buffer_ptr = c->packet_buffer;
2503                     rtsp_c->packet_buffer_end = c->packet_buffer + size;
2504                     c->buffer_ptr += len;
2505
2506                     /* send everything we can NOW */
2507                     len = send(rtsp_c->fd, rtsp_c->packet_buffer_ptr,
2508                                 rtsp_c->packet_buffer_end - rtsp_c->packet_buffer_ptr, 0);
2509                     if (len > 0)
2510                         rtsp_c->packet_buffer_ptr += len;
2511                     if (rtsp_c->packet_buffer_ptr < rtsp_c->packet_buffer_end) {
2512                         /* if we could not send all the data, we will
2513                            send it later, so a new state is needed to
2514                            "lock" the RTSP TCP connection */
2515                         rtsp_c->state = RTSPSTATE_SEND_PACKET;
2516                         break;
2517                     } else
2518                         /* all data has been sent */
2519                         av_freep(&c->packet_buffer);
2520                 } else {
2521                     /* send RTP packet directly in UDP */
2522                     c->buffer_ptr += 4;
2523                     ffurl_write(c->rtp_handles[c->packet_stream_index],
2524                                 c->buffer_ptr, len);
2525                     c->buffer_ptr += len;
2526                     /* here we continue as we can send several packets per 10 ms slot */
2527                 }
2528             } else {
2529                 /* TCP data output */
2530                 len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
2531                 if (len < 0) {
2532                     if (ff_neterrno() != AVERROR(EAGAIN) &&
2533                         ff_neterrno() != AVERROR(EINTR))
2534                         /* error : close connection */
2535                         return -1;
2536                     else
2537                         return 0;
2538                 } else
2539                     c->buffer_ptr += len;
2540
2541                 c->data_count += len;
2542                 update_datarate(&c->datarate, c->data_count);
2543                 if (c->stream)
2544                     c->stream->bytes_served += len;
2545                 break;
2546             }
2547         }
2548     } /* for(;;) */
2549     return 0;
2550 }
2551
2552 static int http_start_receive_data(HTTPContext *c)
2553 {
2554     int fd;
2555
2556     if (c->stream->feed_opened)
2557         return -1;
2558
2559     /* Don't permit writing to this one */
2560     if (c->stream->readonly)
2561         return -1;
2562
2563     /* open feed */
2564     fd = open(c->stream->feed_filename, O_RDWR);
2565     if (fd < 0) {
2566         http_log("Error opening feeder file: %s\n", strerror(errno));
2567         return -1;
2568     }
2569     c->feed_fd = fd;
2570
2571     if (c->stream->truncate) {
2572         /* truncate feed file */
2573         ffm_write_write_index(c->feed_fd, FFM_PACKET_SIZE);
2574         http_log("Truncating feed file '%s'\n", c->stream->feed_filename);
2575         if (ftruncate(c->feed_fd, FFM_PACKET_SIZE) < 0) {
2576             http_log("Error truncating feed file: %s\n", strerror(errno));
2577             return -1;
2578         }
2579     } else {
2580         if ((c->stream->feed_write_index = ffm_read_write_index(fd)) < 0) {
2581             http_log("Error reading write index from feed file: %s\n", strerror(errno));
2582             return -1;
2583         }
2584     }
2585
2586     c->stream->feed_write_index = FFMAX(ffm_read_write_index(fd), FFM_PACKET_SIZE);
2587     c->stream->feed_size = lseek(fd, 0, SEEK_END);
2588     lseek(fd, 0, SEEK_SET);
2589
2590     /* init buffer input */
2591     c->buffer_ptr = c->buffer;
2592     c->buffer_end = c->buffer + FFM_PACKET_SIZE;
2593     c->stream->feed_opened = 1;
2594     c->chunked_encoding = !!av_stristr(c->buffer, "Transfer-Encoding: chunked");
2595     return 0;
2596 }
2597
2598 static int http_receive_data(HTTPContext *c)
2599 {
2600     HTTPContext *c1;
2601     int len, loop_run = 0;
2602
2603     while (c->chunked_encoding && !c->chunk_size &&
2604            c->buffer_end > c->buffer_ptr) {
2605         /* read chunk header, if present */
2606         len = recv(c->fd, c->buffer_ptr, 1, 0);
2607
2608         if (len < 0) {
2609             if (ff_neterrno() != AVERROR(EAGAIN) &&
2610                 ff_neterrno() != AVERROR(EINTR))
2611                 /* error : close connection */
2612                 goto fail;
2613             return 0;
2614         } else if (len == 0) {
2615             /* end of connection : close it */
2616             goto fail;
2617         } else if (c->buffer_ptr - c->buffer >= 2 &&
2618                    !memcmp(c->buffer_ptr - 1, "\r\n", 2)) {
2619             c->chunk_size = strtol(c->buffer, 0, 16);
2620             if (c->chunk_size == 0) // end of stream
2621                 goto fail;
2622             c->buffer_ptr = c->buffer;
2623             break;
2624         } else if (++loop_run > 10) {
2625             /* no chunk header, abort */
2626             goto fail;
2627         } else {
2628             c->buffer_ptr++;
2629         }
2630     }
2631
2632     if (c->buffer_end > c->buffer_ptr) {
2633         len = recv(c->fd, c->buffer_ptr,
2634                    FFMIN(c->chunk_size, c->buffer_end - c->buffer_ptr), 0);
2635         if (len < 0) {
2636             if (ff_neterrno() != AVERROR(EAGAIN) &&
2637                 ff_neterrno() != AVERROR(EINTR))
2638                 /* error : close connection */
2639                 goto fail;
2640         } else if (len == 0)
2641             /* end of connection : close it */
2642             goto fail;
2643         else {
2644             c->chunk_size -= len;
2645             c->buffer_ptr += len;
2646             c->data_count += len;
2647             update_datarate(&c->datarate, c->data_count);
2648         }
2649     }
2650
2651     if (c->buffer_ptr - c->buffer >= 2 && c->data_count > FFM_PACKET_SIZE) {
2652         if (c->buffer[0] != 'f' ||
2653             c->buffer[1] != 'm') {
2654             http_log("Feed stream has become desynchronized -- disconnecting\n");
2655             goto fail;
2656         }
2657     }
2658
2659     if (c->buffer_ptr >= c->buffer_end) {
2660         FFStream *feed = c->stream;
2661         /* a packet has been received : write it in the store, except
2662            if header */
2663         if (c->data_count > FFM_PACKET_SIZE) {
2664
2665             //            printf("writing pos=0x%"PRIx64" size=0x%"PRIx64"\n", feed->feed_write_index, feed->feed_size);
2666             /* XXX: use llseek or url_seek */
2667             lseek(c->feed_fd, feed->feed_write_index, SEEK_SET);
2668             if (write(c->feed_fd, c->buffer, FFM_PACKET_SIZE) < 0) {
2669                 http_log("Error writing to feed file: %s\n", strerror(errno));
2670                 goto fail;
2671             }
2672
2673             feed->feed_write_index += FFM_PACKET_SIZE;
2674             /* update file size */
2675             if (feed->feed_write_index > c->stream->feed_size)
2676                 feed->feed_size = feed->feed_write_index;
2677
2678             /* handle wrap around if max file size reached */
2679             if (c->stream->feed_max_size && feed->feed_write_index >= c->stream->feed_max_size)
2680                 feed->feed_write_index = FFM_PACKET_SIZE;
2681
2682             /* write index */
2683             if (ffm_write_write_index(c->feed_fd, feed->feed_write_index) < 0) {
2684                 http_log("Error writing index to feed file: %s\n", strerror(errno));
2685                 goto fail;
2686             }
2687
2688             /* wake up any waiting connections */
2689             for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
2690                 if (c1->state == HTTPSTATE_WAIT_FEED &&
2691                     c1->stream->feed == c->stream->feed)
2692                     c1->state = HTTPSTATE_SEND_DATA;
2693             }
2694         } else {
2695             /* We have a header in our hands that contains useful data */
2696             AVFormatContext *s = avformat_alloc_context();
2697             AVIOContext *pb;
2698             AVInputFormat *fmt_in;
2699             int i;
2700
2701             if (!s)
2702                 goto fail;
2703
2704             /* use feed output format name to find corresponding input format */
2705             fmt_in = av_find_input_format(feed->fmt->name);
2706             if (!fmt_in)
2707                 goto fail;
2708
2709             pb = avio_alloc_context(c->buffer, c->buffer_end - c->buffer,
2710                                     0, NULL, NULL, NULL, NULL);
2711             pb->seekable = 0;
2712
2713             s->pb = pb;
2714             if (avformat_open_input(&s, c->stream->feed_filename, fmt_in, NULL) < 0) {
2715                 av_free(pb);
2716                 goto fail;
2717             }
2718
2719             /* Now we have the actual streams */
2720             if (s->nb_streams != feed->nb_streams) {
2721                 avformat_close_input(&s);
2722                 av_free(pb);
2723                 http_log("Feed '%s' stream number does not match registered feed\n",
2724                          c->stream->feed_filename);
2725                 goto fail;
2726             }
2727
2728             for (i = 0; i < s->nb_streams; i++) {
2729                 AVStream *fst = feed->streams[i];
2730                 AVStream *st = s->streams[i];
2731                 avcodec_copy_context(fst->codec, st->codec);
2732             }
2733
2734             avformat_close_input(&s);
2735             av_free(pb);
2736         }
2737         c->buffer_ptr = c->buffer;
2738     }
2739
2740     return 0;
2741  fail:
2742     c->stream->feed_opened = 0;
2743     close(c->feed_fd);
2744     /* wake up any waiting connections to stop waiting for feed */
2745     for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
2746         if (c1->state == HTTPSTATE_WAIT_FEED &&
2747             c1->stream->feed == c->stream->feed)
2748             c1->state = HTTPSTATE_SEND_DATA_TRAILER;
2749     }
2750     return -1;
2751 }
2752
2753 /********************************************************************/
2754 /* RTSP handling */
2755
2756 static void rtsp_reply_header(HTTPContext *c, enum RTSPStatusCode error_number)
2757 {
2758     const char *str;
2759     time_t ti;
2760     struct tm *tm;
2761     char buf2[32];
2762
2763     switch(error_number) {
2764     case RTSP_STATUS_OK:
2765         str = "OK";
2766         break;
2767     case RTSP_STATUS_METHOD:
2768         str = "Method Not Allowed";
2769         break;
2770     case RTSP_STATUS_BANDWIDTH:
2771         str = "Not Enough Bandwidth";
2772         break;
2773     case RTSP_STATUS_SESSION:
2774         str = "Session Not Found";
2775         break;
2776     case RTSP_STATUS_STATE:
2777         str = "Method Not Valid in This State";
2778         break;
2779     case RTSP_STATUS_AGGREGATE:
2780         str = "Aggregate operation not allowed";
2781         break;
2782     case RTSP_STATUS_ONLY_AGGREGATE:
2783         str = "Only aggregate operation allowed";
2784         break;
2785     case RTSP_STATUS_TRANSPORT:
2786         str = "Unsupported transport";
2787         break;
2788     case RTSP_STATUS_INTERNAL:
2789         str = "Internal Server Error";
2790         break;
2791     case RTSP_STATUS_SERVICE:
2792         str = "Service Unavailable";
2793         break;
2794     case RTSP_STATUS_VERSION:
2795         str = "RTSP Version not supported";
2796         break;
2797     default:
2798         str = "Unknown Error";
2799         break;
2800     }
2801
2802     avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", error_number, str);
2803     avio_printf(c->pb, "CSeq: %d\r\n", c->seq);
2804
2805     /* output GMT time */
2806     ti = time(NULL);
2807     tm = gmtime(&ti);
2808     strftime(buf2, sizeof(buf2), "%a, %d %b %Y %H:%M:%S", tm);
2809     avio_printf(c->pb, "Date: %s GMT\r\n", buf2);
2810 }
2811
2812 static void rtsp_reply_error(HTTPContext *c, enum RTSPStatusCode error_number)
2813 {
2814     rtsp_reply_header(c, error_number);
2815     avio_printf(c->pb, "\r\n");
2816 }
2817
2818 static int rtsp_parse_request(HTTPContext *c)
2819 {
2820     const char *p, *p1, *p2;
2821     char cmd[32];
2822     char url[1024];
2823     char protocol[32];
2824     char line[1024];
2825     int len;
2826     RTSPMessageHeader header1 = { 0 }, *header = &header1;
2827
2828     c->buffer_ptr[0] = '\0';
2829     p = c->buffer;
2830
2831     get_word(cmd, sizeof(cmd), &p);
2832     get_word(url, sizeof(url), &p);
2833     get_word(protocol, sizeof(protocol), &p);
2834
2835     av_strlcpy(c->method, cmd, sizeof(c->method));
2836     av_strlcpy(c->url, url, sizeof(c->url));
2837     av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
2838
2839     if (avio_open_dyn_buf(&c->pb) < 0) {
2840         /* XXX: cannot do more */
2841         c->pb = NULL; /* safety */
2842         return -1;
2843     }
2844
2845     /* check version name */
2846     if (strcmp(protocol, "RTSP/1.0") != 0) {
2847         rtsp_reply_error(c, RTSP_STATUS_VERSION);
2848         goto the_end;
2849     }
2850
2851     /* parse each header line */
2852     /* skip to next line */
2853     while (*p != '\n' && *p != '\0')
2854         p++;
2855     if (*p == '\n')
2856         p++;
2857     while (*p != '\0') {
2858         p1 = memchr(p, '\n', (char *)c->buffer_ptr - p);
2859         if (!p1)
2860             break;
2861         p2 = p1;
2862         if (p2 > p && p2[-1] == '\r')
2863             p2--;
2864         /* skip empty line */
2865         if (p2 == p)
2866             break;
2867         len = p2 - p;
2868         if (len > sizeof(line) - 1)
2869             len = sizeof(line) - 1;
2870         memcpy(line, p, len);
2871         line[len] = '\0';
2872         ff_rtsp_parse_line(header, line, NULL, NULL);
2873         p = p1 + 1;
2874     }
2875
2876     /* handle sequence number */
2877     c->seq = header->seq;
2878
2879     if (!strcmp(cmd, "DESCRIBE"))
2880         rtsp_cmd_describe(c, url);
2881     else if (!strcmp(cmd, "OPTIONS"))
2882         rtsp_cmd_options(c, url);
2883     else if (!strcmp(cmd, "SETUP"))
2884         rtsp_cmd_setup(c, url, header);
2885     else if (!strcmp(cmd, "PLAY"))
2886         rtsp_cmd_play(c, url, header);
2887     else if (!strcmp(cmd, "PAUSE"))
2888         rtsp_cmd_pause(c, url, header);
2889     else if (!strcmp(cmd, "TEARDOWN"))
2890         rtsp_cmd_teardown(c, url, header);
2891     else
2892         rtsp_reply_error(c, RTSP_STATUS_METHOD);
2893
2894  the_end:
2895     len = avio_close_dyn_buf(c->pb, &c->pb_buffer);
2896     c->pb = NULL; /* safety */
2897     if (len < 0) {
2898         /* XXX: cannot do more */
2899         return -1;
2900     }
2901     c->buffer_ptr = c->pb_buffer;
2902     c->buffer_end = c->pb_buffer + len;
2903     c->state = RTSPSTATE_SEND_REPLY;
2904     return 0;
2905 }
2906
2907 static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
2908                                    struct in_addr my_ip)
2909 {
2910     AVFormatContext *avc;
2911     AVStream *avs = NULL;
2912     int i;
2913
2914     avc =  avformat_alloc_context();
2915     if (avc == NULL) {
2916         return -1;
2917     }
2918     av_dict_set(&avc->metadata, "title",
2919                stream->title[0] ? stream->title : "No Title", 0);
2920     avc->nb_streams = stream->nb_streams;
2921     if (stream->is_multicast) {
2922         snprintf(avc->filename, 1024, "rtp://%s:%d?multicast=1?ttl=%d",
2923                  inet_ntoa(stream->multicast_ip),
2924                  stream->multicast_port, stream->multicast_ttl);
2925     } else {
2926         snprintf(avc->filename, 1024, "rtp://0.0.0.0");
2927     }
2928
2929     if (avc->nb_streams >= INT_MAX/sizeof(*avc->streams) ||
2930         !(avc->streams = av_malloc(avc->nb_streams * sizeof(*avc->streams))))
2931         goto sdp_done;
2932     if (avc->nb_streams >= INT_MAX/sizeof(*avs) ||
2933         !(avs = av_malloc(avc->nb_streams * sizeof(*avs))))
2934         goto sdp_done;
2935
2936     for(i = 0; i < stream->nb_streams; i++) {
2937         avc->streams[i] = &avs[i];
2938         avc->streams[i]->codec = stream->streams[i]->codec;
2939     }
2940     *pbuffer = av_mallocz(2048);
2941     av_sdp_create(&avc, 1, *pbuffer, 2048);
2942
2943  sdp_done:
2944     av_free(avc->streams);
2945     av_dict_free(&avc->metadata);
2946     av_free(avc);
2947     av_free(avs);
2948
2949     return strlen(*pbuffer);
2950 }
2951
2952 static void rtsp_cmd_options(HTTPContext *c, const char *url)
2953 {
2954 //    rtsp_reply_header(c, RTSP_STATUS_OK);
2955     avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", RTSP_STATUS_OK, "OK");
2956     avio_printf(c->pb, "CSeq: %d\r\n", c->seq);
2957     avio_printf(c->pb, "Public: %s\r\n", "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
2958     avio_printf(c->pb, "\r\n");
2959 }
2960
2961 static void rtsp_cmd_describe(HTTPContext *c, const char *url)
2962 {
2963     FFStream *stream;
2964     char path1[1024];
2965     const char *path;
2966     uint8_t *content;
2967     int content_length, len;
2968     struct sockaddr_in my_addr;
2969
2970     /* find which url is asked */
2971     av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
2972     path = path1;
2973     if (*path == '/')
2974         path++;
2975
2976     for(stream = first_stream; stream != NULL; stream = stream->next) {
2977         if (!stream->is_feed &&
2978             stream->fmt && !strcmp(stream->fmt->name, "rtp") &&
2979             !strcmp(path, stream->filename)) {
2980             goto found;
2981         }
2982     }
2983     /* no stream found */
2984     rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
2985     return;
2986
2987  found:
2988     /* prepare the media description in sdp format */
2989
2990     /* get the host IP */
2991     len = sizeof(my_addr);
2992     getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
2993     content_length = prepare_sdp_description(stream, &content, my_addr.sin_addr);
2994     if (content_length < 0) {
2995         rtsp_reply_error(c, RTSP_STATUS_INTERNAL);
2996         return;
2997     }
2998     rtsp_reply_header(c, RTSP_STATUS_OK);
2999     avio_printf(c->pb, "Content-Base: %s/\r\n", url);
3000     avio_printf(c->pb, "Content-Type: application/sdp\r\n");
3001     avio_printf(c->pb, "Content-Length: %d\r\n", content_length);
3002     avio_printf(c->pb, "\r\n");
3003     avio_write(c->pb, content, content_length);
3004     av_free(content);
3005 }
3006
3007 static HTTPContext *find_rtp_session(const char *session_id)
3008 {
3009     HTTPContext *c;
3010
3011     if (session_id[0] == '\0')
3012         return NULL;
3013
3014     for(c = first_http_ctx; c != NULL; c = c->next) {
3015         if (!strcmp(c->session_id, session_id))
3016             return c;
3017     }
3018     return NULL;
3019 }
3020
3021 static RTSPTransportField *find_transport(RTSPMessageHeader *h, enum RTSPLowerTransport lower_transport)
3022 {
3023     RTSPTransportField *th;
3024     int i;
3025
3026     for(i=0;i<h->nb_transports;i++) {
3027         th = &h->transports[i];
3028         if (th->lower_transport == lower_transport)
3029             return th;
3030     }
3031     return NULL;
3032 }
3033
3034 static void rtsp_cmd_setup(HTTPContext *c, const char *url,
3035                            RTSPMessageHeader *h)
3036 {
3037     FFStream *stream;
3038     int stream_index, rtp_port, rtcp_port;
3039     char buf[1024];
3040     char path1[1024];
3041     const char *path;
3042     HTTPContext *rtp_c;
3043     RTSPTransportField *th;
3044     struct sockaddr_in dest_addr;
3045     RTSPActionServerSetup setup;
3046
3047     /* find which url is asked */
3048     av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3049     path = path1;
3050     if (*path == '/')
3051         path++;
3052
3053     /* now check each stream */
3054     for(stream = first_stream; stream != NULL; stream = stream->next) {
3055         if (!stream->is_feed &&
3056             stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
3057             /* accept aggregate filenames only if single stream */
3058             if (!strcmp(path, stream->filename)) {
3059                 if (stream->nb_streams != 1) {
3060                     rtsp_reply_error(c, RTSP_STATUS_AGGREGATE);
3061                     return;
3062                 }
3063                 stream_index = 0;
3064                 goto found;
3065             }
3066
3067             for(stream_index = 0; stream_index < stream->nb_streams;
3068                 stream_index++) {
3069                 snprintf(buf, sizeof(buf), "%s/streamid=%d",
3070                          stream->filename, stream_index);
3071                 if (!strcmp(path, buf))
3072                     goto found;
3073             }
3074         }
3075     }
3076     /* no stream found */
3077     rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
3078     return;
3079  found:
3080
3081     /* generate session id if needed */
3082     if (h->session_id[0] == '\0')
3083         snprintf(h->session_id, sizeof(h->session_id), "%08x%08x",
3084                  av_lfg_get(&random_state), av_lfg_get(&random_state));
3085
3086     /* find rtp session, and create it if none found */
3087     rtp_c = find_rtp_session(h->session_id);
3088     if (!rtp_c) {
3089         /* always prefer UDP */
3090         th = find_transport(h, RTSP_LOWER_TRANSPORT_UDP);
3091         if (!th) {
3092             th = find_transport(h, RTSP_LOWER_TRANSPORT_TCP);
3093             if (!th) {
3094                 rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3095                 return;
3096             }
3097         }
3098
3099         rtp_c = rtp_new_connection(&c->from_addr, stream, h->session_id,
3100                                    th->lower_transport);
3101         if (!rtp_c) {
3102             rtsp_reply_error(c, RTSP_STATUS_BANDWIDTH);
3103             return;
3104         }
3105
3106         /* open input stream */
3107         if (open_input_stream(rtp_c, "") < 0) {
3108             rtsp_reply_error(c, RTSP_STATUS_INTERNAL);
3109             return;
3110         }
3111     }
3112
3113     /* test if stream is OK (test needed because several SETUP needs
3114        to be done for a given file) */
3115     if (rtp_c->stream != stream) {
3116         rtsp_reply_error(c, RTSP_STATUS_SERVICE);
3117         return;
3118     }
3119
3120     /* test if stream is already set up */
3121     if (rtp_c->rtp_ctx[stream_index]) {
3122         rtsp_reply_error(c, RTSP_STATUS_STATE);
3123         return;
3124     }
3125
3126     /* check transport */
3127     th = find_transport(h, rtp_c->rtp_protocol);
3128     if (!th || (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
3129                 th->client_port_min <= 0)) {
3130         rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3131         return;
3132     }
3133
3134     /* setup default options */
3135     setup.transport_option[0] = '\0';
3136     dest_addr = rtp_c->from_addr;
3137     dest_addr.sin_port = htons(th->client_port_min);
3138
3139     /* setup stream */
3140     if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, c) < 0) {
3141         rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3142         return;
3143     }
3144
3145     /* now everything is OK, so we can send the connection parameters */
3146     rtsp_reply_header(c, RTSP_STATUS_OK);
3147     /* session ID */
3148     avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3149
3150     switch(rtp_c->rtp_protocol) {
3151     case RTSP_LOWER_TRANSPORT_UDP:
3152         rtp_port = ff_rtp_get_local_rtp_port(rtp_c->rtp_handles[stream_index]);
3153         rtcp_port = ff_rtp_get_local_rtcp_port(rtp_c->rtp_handles[stream_index]);
3154         avio_printf(c->pb, "Transport: RTP/AVP/UDP;unicast;"
3155                     "client_port=%d-%d;server_port=%d-%d",
3156                     th->client_port_min, th->client_port_max,
3157                     rtp_port, rtcp_port);
3158         break;
3159     case RTSP_LOWER_TRANSPORT_TCP:
3160         avio_printf(c->pb, "Transport: RTP/AVP/TCP;interleaved=%d-%d",
3161                     stream_index * 2, stream_index * 2 + 1);
3162         break;
3163     default:
3164         break;
3165     }
3166     if (setup.transport_option[0] != '\0')
3167         avio_printf(c->pb, ";%s", setup.transport_option);
3168     avio_printf(c->pb, "\r\n");
3169
3170
3171     avio_printf(c->pb, "\r\n");
3172 }
3173
3174
3175 /* find an rtp connection by using the session ID. Check consistency
3176    with filename */
3177 static HTTPContext *find_rtp_session_with_url(const char *url,
3178                                               const char *session_id)
3179 {
3180     HTTPContext *rtp_c;
3181     char path1[1024];
3182     const char *path;
3183     char buf[1024];
3184     int s, len;
3185
3186     rtp_c = find_rtp_session(session_id);
3187     if (!rtp_c)
3188         return NULL;
3189
3190     /* find which url is asked */
3191     av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3192     path = path1;
3193     if (*path == '/')
3194         path++;
3195     if(!strcmp(path, rtp_c->stream->filename)) return rtp_c;
3196     for(s=0; s<rtp_c->stream->nb_streams; ++s) {
3197       snprintf(buf, sizeof(buf), "%s/streamid=%d",
3198         rtp_c->stream->filename, s);
3199       if(!strncmp(path, buf, sizeof(buf))) {
3200     // XXX: Should we reply with RTSP_STATUS_ONLY_AGGREGATE if nb_streams>1?
3201         return rtp_c;
3202       }
3203     }
3204     len = strlen(path);
3205     if (len > 0 && path[len - 1] == '/' &&
3206         !strncmp(path, rtp_c->stream->filename, len - 1))
3207         return rtp_c;
3208     return NULL;
3209 }
3210
3211 static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3212 {
3213     HTTPContext *rtp_c;
3214
3215     rtp_c = find_rtp_session_with_url(url, h->session_id);
3216     if (!rtp_c) {
3217         rtsp_reply_error(c, RTSP_STATUS_SESSION);
3218         return;
3219     }
3220
3221     if (rtp_c->state != HTTPSTATE_SEND_DATA &&
3222         rtp_c->state != HTTPSTATE_WAIT_FEED &&
3223         rtp_c->state != HTTPSTATE_READY) {
3224         rtsp_reply_error(c, RTSP_STATUS_STATE);
3225         return;
3226     }
3227
3228     rtp_c->state = HTTPSTATE_SEND_DATA;
3229
3230     /* now everything is OK, so we can send the connection parameters */
3231     rtsp_reply_header(c, RTSP_STATUS_OK);
3232     /* session ID */
3233     avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3234     avio_printf(c->pb, "\r\n");
3235 }
3236
3237 static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3238 {
3239     HTTPContext *rtp_c;
3240
3241     rtp_c = find_rtp_session_with_url(url, h->session_id);
3242     if (!rtp_c) {
3243         rtsp_reply_error(c, RTSP_STATUS_SESSION);
3244         return;
3245     }
3246
3247     if (rtp_c->state != HTTPSTATE_SEND_DATA &&
3248         rtp_c->state != HTTPSTATE_WAIT_FEED) {
3249         rtsp_reply_error(c, RTSP_STATUS_STATE);
3250         return;
3251     }
3252
3253     rtp_c->state = HTTPSTATE_READY;
3254     rtp_c->first_pts = AV_NOPTS_VALUE;
3255     /* now everything is OK, so we can send the connection parameters */
3256     rtsp_reply_header(c, RTSP_STATUS_OK);
3257     /* session ID */
3258     avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3259     avio_printf(c->pb, "\r\n");
3260 }
3261
3262 static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3263 {
3264     HTTPContext *rtp_c;
3265
3266     rtp_c = find_rtp_session_with_url(url, h->session_id);
3267     if (!rtp_c) {
3268         rtsp_reply_error(c, RTSP_STATUS_SESSION);
3269         return;
3270     }
3271
3272     /* now everything is OK, so we can send the connection parameters */
3273     rtsp_reply_header(c, RTSP_STATUS_OK);
3274     /* session ID */
3275     avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3276     avio_printf(c->pb, "\r\n");
3277
3278     /* abort the session */
3279     close_connection(rtp_c);
3280 }
3281
3282
3283 /********************************************************************/
3284 /* RTP handling */
3285
3286 static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
3287                                        FFStream *stream, const char *session_id,
3288                                        enum RTSPLowerTransport rtp_protocol)
3289 {
3290     HTTPContext *c = NULL;
3291     const char *proto_str;
3292
3293     /* XXX: should output a warning page when coming
3294        close to the connection limit */
3295     if (nb_connections >= nb_max_connections)
3296         goto fail;
3297
3298     /* add a new connection */
3299     c = av_mallocz(sizeof(HTTPContext));
3300     if (!c)
3301         goto fail;
3302
3303     c->fd = -1;
3304     c->poll_entry = NULL;
3305     c->from_addr = *from_addr;
3306     c->buffer_size = IOBUFFER_INIT_SIZE;
3307     c->buffer = av_malloc(c->buffer_size);
3308     if (!c->buffer)
3309         goto fail;
3310     nb_connections++;
3311     c->stream = stream;
3312     av_strlcpy(c->session_id, session_id, sizeof(c->session_id));
3313     c->state = HTTPSTATE_READY;
3314     c->is_packetized = 1;
3315     c->rtp_protocol = rtp_protocol;
3316
3317     /* protocol is shown in statistics */
3318     switch(c->rtp_protocol) {
3319     case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
3320         proto_str = "MCAST";
3321         break;
3322     case RTSP_LOWER_TRANSPORT_UDP:
3323         proto_str = "UDP";
3324         break;
3325     case RTSP_LOWER_TRANSPORT_TCP:
3326         proto_str = "TCP";
3327         break;
3328     default:
3329         proto_str = "???";
3330         break;
3331     }
3332     av_strlcpy(c->protocol, "RTP/", sizeof(c->protocol));
3333     av_strlcat(c->protocol, proto_str, sizeof(c->protocol));
3334
3335     current_bandwidth += stream->bandwidth;
3336
3337     c->next = first_http_ctx;
3338     first_http_ctx = c;
3339     return c;
3340
3341  fail:
3342     if (c) {
3343         av_free(c->buffer);
3344         av_free(c);
3345     }
3346     return NULL;
3347 }
3348
3349 /* add a new RTP stream in an RTP connection (used in RTSP SETUP
3350    command). If RTP/TCP protocol is used, TCP connection 'rtsp_c' is
3351    used. */
3352 static int rtp_new_av_stream(HTTPContext *c,
3353                              int stream_index, struct sockaddr_in *dest_addr,
3354                              HTTPContext *rtsp_c)
3355 {
3356     AVFormatContext *ctx;
3357     AVStream *st;
3358     char *ipaddr;
3359     URLContext *h = NULL;
3360     uint8_t *dummy_buf;
3361     int max_packet_size;
3362
3363     /* now we can open the relevant output stream */
3364     ctx = avformat_alloc_context();
3365     if (!ctx)
3366         return -1;
3367     ctx->oformat = av_guess_format("rtp", NULL, NULL);
3368
3369     st = av_mallocz(sizeof(AVStream));
3370     if (!st)
3371         goto fail;
3372     ctx->nb_streams = 1;
3373     ctx->streams = av_mallocz(sizeof(AVStream *) * ctx->nb_streams);
3374     if (!ctx->streams)
3375       goto fail;
3376     ctx->streams[0] = st;
3377
3378     if (!c->stream->feed ||
3379         c->stream->feed == c->stream)
3380         memcpy(st, c->stream->streams[stream_index], sizeof(AVStream));
3381     else
3382         memcpy(st,
3383                c->stream->feed->streams[c->stream->feed_streams[stream_index]],
3384                sizeof(AVStream));
3385     st->priv_data = NULL;
3386
3387     /* build destination RTP address */
3388     ipaddr = inet_ntoa(dest_addr->sin_addr);
3389
3390     switch(c->rtp_protocol) {
3391     case RTSP_LOWER_TRANSPORT_UDP:
3392     case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
3393         /* RTP/UDP case */
3394
3395         /* XXX: also pass as parameter to function ? */
3396         if (c->stream->is_multicast) {
3397             int ttl;
3398             ttl = c->stream->multicast_ttl;
3399             if (!ttl)
3400                 ttl = 16;
3401             snprintf(ctx->filename, sizeof(ctx->filename),
3402                      "rtp://%s:%d?multicast=1&ttl=%d",
3403                      ipaddr, ntohs(dest_addr->sin_port), ttl);
3404         } else {
3405             snprintf(ctx->filename, sizeof(ctx->filename),
3406                      "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
3407         }
3408
3409         if (ffurl_open(&h, ctx->filename, AVIO_FLAG_WRITE, NULL, NULL) < 0)
3410             goto fail;
3411         c->rtp_handles[stream_index] = h;
3412         max_packet_size = h->max_packet_size;
3413         break;
3414     case RTSP_LOWER_TRANSPORT_TCP:
3415         /* RTP/TCP case */
3416         c->rtsp_c = rtsp_c;
3417         max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
3418         break;
3419     default:
3420         goto fail;
3421     }
3422
3423     http_log("%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
3424              ipaddr, ntohs(dest_addr->sin_port),
3425              c->stream->filename, stream_index, c->protocol);
3426
3427     /* normally, no packets should be output here, but the packet size may be checked */
3428     if (ffio_open_dyn_packet_buf(&ctx->pb, max_packet_size) < 0) {
3429         /* XXX: close stream */
3430         goto fail;
3431     }
3432     if (avformat_write_header(ctx, NULL) < 0) {
3433     fail:
3434         if (h)
3435             ffurl_close(h);
3436         av_free(ctx);
3437         return -1;
3438     }
3439     avio_close_dyn_buf(ctx->pb, &dummy_buf);
3440     av_free(dummy_buf);
3441
3442     c->rtp_ctx[stream_index] = ctx;
3443     return 0;
3444 }
3445
3446 /********************************************************************/
3447 /* avserver initialization */
3448
3449 static AVStream *add_av_stream1(FFStream *stream, AVCodecContext *codec, int copy)
3450 {
3451     AVStream *fst;
3452
3453     fst = av_mallocz(sizeof(AVStream));
3454     if (!fst)
3455         return NULL;
3456     if (copy) {
3457         fst->codec = avcodec_alloc_context3(NULL);
3458         memcpy(fst->codec, codec, sizeof(AVCodecContext));
3459         if (codec->extradata_size) {
3460             fst->codec->extradata = av_malloc(codec->extradata_size);
3461             memcpy(fst->codec->extradata, codec->extradata,
3462                 codec->extradata_size);
3463         }
3464     } else {
3465         /* live streams must use the actual feed's codec since it may be
3466          * updated later to carry extradata needed by the streams.
3467          */
3468         fst->codec = codec;
3469     }
3470     fst->priv_data = av_mallocz(sizeof(FeedData));
3471     fst->index = stream->nb_streams;
3472     avpriv_set_pts_info(fst, 33, 1, 90000);
3473     fst->sample_aspect_ratio = codec->sample_aspect_ratio;
3474     stream->streams[stream->nb_streams++] = fst;
3475     return fst;
3476 }
3477
3478 /* return the stream number in the feed */
3479 static int add_av_stream(FFStream *feed, AVStream *st)
3480 {
3481     AVStream *fst;
3482     AVCodecContext *av, *av1;
3483     int i;
3484
3485     av = st->codec;
3486     for(i=0;i<feed->nb_streams;i++) {
3487         st = feed->streams[i];
3488         av1 = st->codec;
3489         if (av1->codec_id == av->codec_id &&
3490             av1->codec_type == av->codec_type &&
3491             av1->bit_rate == av->bit_rate) {
3492
3493             switch(av->codec_type) {
3494             case AVMEDIA_TYPE_AUDIO:
3495                 if (av1->channels == av->channels &&
3496                     av1->sample_rate == av->sample_rate)
3497                     return i;
3498                 break;
3499             case AVMEDIA_TYPE_VIDEO:
3500                 if (av1->width == av->width &&
3501                     av1->height == av->height &&
3502                     av1->time_base.den == av->time_base.den &&
3503                     av1->time_base.num == av->time_base.num &&
3504                     av1->gop_size == av->gop_size)
3505                     return i;
3506                 break;
3507             default:
3508                 abort();
3509             }
3510         }
3511     }
3512
3513     fst = add_av_stream1(feed, av, 0);
3514     if (!fst)
3515         return -1;
3516     return feed->nb_streams - 1;
3517 }
3518
3519 static void remove_stream(FFStream *stream)
3520 {
3521     FFStream **ps;
3522     ps = &first_stream;
3523     while (*ps != NULL) {
3524         if (*ps == stream)
3525             *ps = (*ps)->next;
3526         else
3527             ps = &(*ps)->next;
3528     }
3529 }
3530
3531 /* specific mpeg4 handling : we extract the raw parameters */
3532 static void extract_mpeg4_header(AVFormatContext *infile)
3533 {
3534     int mpeg4_count, i, size;
3535     AVPacket pkt;
3536     AVStream *st;
3537     const uint8_t *p;
3538
3539     mpeg4_count = 0;
3540     for(i=0;i<infile->nb_streams;i++) {
3541         st = infile->streams[i];
3542         if (st->codec->codec_id == AV_CODEC_ID_MPEG4 &&
3543             st->codec->extradata_size == 0) {
3544             mpeg4_count++;
3545         }
3546     }
3547     if (!mpeg4_count)
3548         return;
3549
3550     printf("MPEG4 without extra data: trying to find header in %s\n", infile->filename);
3551     while (mpeg4_count > 0) {
3552         if (av_read_packet(infile, &pkt) < 0)
3553             break;
3554         st = infile->streams[pkt.stream_index];
3555         if (st->codec->codec_id == AV_CODEC_ID_MPEG4 &&
3556             st->codec->extradata_size == 0) {
3557             av_freep(&st->codec->extradata);
3558             /* fill extradata with the header */
3559             /* XXX: we make hard suppositions here ! */
3560             p = pkt.data;
3561             while (p < pkt.data + pkt.size - 4) {
3562                 /* stop when vop header is found */
3563                 if (p[0] == 0x00 && p[1] == 0x00 &&
3564                     p[2] == 0x01 && p[3] == 0xb6) {
3565                     size = p - pkt.data;
3566                     //                    av_hex_dump_log(infile, AV_LOG_DEBUG, pkt.data, size);
3567                     st->codec->extradata = av_malloc(size);
3568                     st->codec->extradata_size = size;
3569                     memcpy(st->codec->extradata, pkt.data, size);
3570                     break;
3571                 }
3572                 p++;
3573             }
3574             mpeg4_count--;
3575         }
3576         av_free_packet(&pkt);
3577     }
3578 }
3579
3580 /* compute the needed AVStream for each file */
3581 static void build_file_streams(void)
3582 {
3583     FFStream *stream, *stream_next;
3584     int i, ret;
3585
3586     /* gather all streams */
3587     for(stream = first_stream; stream != NULL; stream = stream_next) {
3588         AVFormatContext *infile = NULL;
3589         stream_next = stream->next;
3590         if (stream->stream_type == STREAM_TYPE_LIVE &&
3591             !stream->feed) {
3592             /* the stream comes from a file */
3593             /* try to open the file */
3594             /* open stream */
3595             if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
3596                 /* specific case : if transport stream output to RTP,
3597                    we use a raw transport stream reader */
3598                 av_dict_set(&stream->in_opts, "mpeg2ts_compute_pcr", "1", 0);
3599             }
3600
3601             http_log("Opening file '%s'\n", stream->feed_filename);
3602             if ((ret = avformat_open_input(&infile, stream->feed_filename, stream->ifmt, &stream->in_opts)) < 0) {
3603                 http_log("Could not open '%s': %d\n", stream->feed_filename, ret);
3604                 /* remove stream (no need to spend more time on it) */
3605             fail:
3606                 remove_stream(stream);
3607             } else {
3608                 /* find all the AVStreams inside and reference them in
3609                    'stream' */
3610                 if (avformat_find_stream_info(infile, NULL) < 0) {
3611                     http_log("Could not find codec parameters from '%s'\n",
3612                              stream->feed_filename);
3613                     avformat_close_input(&infile);
3614                     goto fail;
3615                 }
3616                 extract_mpeg4_header(infile);
3617
3618                 for(i=0;i<infile->nb_streams;i++)
3619                     add_av_stream1(stream, infile->streams[i]->codec, 1);
3620
3621                 avformat_close_input(&infile);
3622             }
3623         }
3624     }
3625 }
3626
3627 /* compute the needed AVStream for each feed */
3628 static void build_feed_streams(void)
3629 {
3630     FFStream *stream, *feed;
3631     int i;
3632
3633     /* gather all streams */
3634     for(stream = first_stream; stream != NULL; stream = stream->next) {
3635         feed = stream->feed;
3636         if (feed) {
3637             if (stream->is_feed) {
3638                 for(i=0;i<stream->nb_streams;i++)
3639                     stream->feed_streams[i] = i;
3640             } else {
3641                 /* we handle a stream coming from a feed */
3642                 for(i=0;i<stream->nb_streams;i++)
3643                     stream->feed_streams[i] = add_av_stream(feed, stream->streams[i]);
3644             }
3645         }
3646     }
3647
3648     /* create feed files if needed */
3649     for(feed = first_feed; feed != NULL; feed = feed->next_feed) {
3650         int fd;
3651
3652         if (avio_check(feed->feed_filename, AVIO_FLAG_READ) > 0) {
3653             /* See if it matches */
3654             AVFormatContext *s = NULL;
3655             int matches = 0;
3656
3657             if (avformat_open_input(&s, feed->feed_filename, NULL, NULL) >= 0) {
3658                 /* Now see if it matches */
3659                 if (s->nb_streams == feed->nb_streams) {
3660                     matches = 1;
3661                     for(i=0;i<s->nb_streams;i++) {
3662                         AVStream *sf, *ss;
3663                         sf = feed->streams[i];
3664                         ss = s->streams[i];
3665
3666                         if (sf->index != ss->index ||
3667                             sf->id != ss->id) {
3668                             http_log("Index & Id do not match for stream %d (%s)\n",
3669                                    i, feed->feed_filename);
3670                             matches = 0;
3671                         } else {
3672                             AVCodecContext *ccf, *ccs;
3673
3674                             ccf = sf->codec;
3675                             ccs = ss->codec;
3676 #define CHECK_CODEC(x)  (ccf->x != ccs->x)
3677
3678                             if (CHECK_CODEC(codec_id) || CHECK_CODEC(codec_type)) {
3679                                 http_log("Codecs do not match for stream %d\n", i);
3680                                 matches = 0;
3681                             } else if (CHECK_CODEC(bit_rate) || CHECK_CODEC(flags)) {
3682                                 http_log("Codec bitrates do not match for stream %d\n", i);
3683                                 matches = 0;
3684                             } else if (ccf->codec_type == AVMEDIA_TYPE_VIDEO) {
3685                                 if (CHECK_CODEC(time_base.den) ||
3686                                     CHECK_CODEC(time_base.num) ||
3687                                     CHECK_CODEC(width) ||
3688                                     CHECK_CODEC(height)) {
3689                                     http_log("Codec width, height and framerate do not match for stream %d\n", i);
3690                                     matches = 0;
3691                                 }
3692                             } else if (ccf->codec_type == AVMEDIA_TYPE_AUDIO) {
3693                                 if (CHECK_CODEC(sample_rate) ||
3694                                     CHECK_CODEC(channels) ||
3695                                     CHECK_CODEC(frame_size)) {
3696                                     http_log("Codec sample_rate, channels, frame_size do not match for stream %d\n", i);
3697                                     matches = 0;
3698                                 }
3699                             } else {
3700                                 http_log("Unknown codec type\n");
3701                                 matches = 0;
3702                             }
3703                         }
3704                         if (!matches)
3705                             break;
3706                     }
3707                 } else
3708                     http_log("Deleting feed file '%s' as stream counts differ (%d != %d)\n",
3709                         feed->feed_filename, s->nb_streams, feed->nb_streams);
3710
3711                 avformat_close_input(&s);
3712             } else
3713                 http_log("Deleting feed file '%s' as it appears to be corrupt\n",
3714                         feed->feed_filename);
3715
3716             if (!matches) {
3717                 if (feed->readonly) {
3718                     http_log("Unable to delete feed file '%s' as it is marked readonly\n",
3719                         feed->feed_filename);
3720                     exit(1);
3721                 }
3722                 unlink(feed->feed_filename);
3723             }
3724         }
3725         if (avio_check(feed->feed_filename, AVIO_FLAG_WRITE) <= 0) {
3726             AVFormatContext s1 = {0}, *s = &s1;
3727
3728             if (feed->readonly) {
3729                 http_log("Unable to create feed file '%s' as it is marked readonly\n",
3730                     feed->feed_filename);
3731                 exit(1);
3732             }
3733
3734             /* only write the header of the ffm file */
3735             if (avio_open(&s->pb, feed->feed_filename, AVIO_FLAG_WRITE) < 0) {
3736                 http_log("Could not open output feed file '%s'\n",
3737                          feed->feed_filename);
3738                 exit(1);
3739             }
3740             s->oformat = feed->fmt;
3741             s->nb_streams = feed->nb_streams;
3742             s->streams = feed->streams;
3743             if (avformat_write_header(s, NULL) < 0) {
3744                 http_log("Container doesn't supports the required parameters\n");
3745                 exit(1);
3746             }
3747             /* XXX: need better api */
3748             av_freep(&s->priv_data);
3749             avio_close(s->pb);
3750         }
3751         /* get feed size and write index */
3752         fd = open(feed->feed_filename, O_RDONLY);
3753         if (fd < 0) {
3754             http_log("Could not open output feed file '%s'\n",
3755                     feed->feed_filename);
3756             exit(1);
3757         }
3758
3759         feed->feed_write_index = FFMAX(ffm_read_write_index(fd), FFM_PACKET_SIZE);
3760         feed->feed_size = lseek(fd, 0, SEEK_END);
3761         /* ensure that we do not wrap before the end of file */
3762         if (feed->feed_max_size && feed->feed_max_size < feed->feed_size)
3763             feed->feed_max_size = feed->feed_size;
3764
3765         close(fd);
3766     }
3767 }
3768
3769 /* compute the bandwidth used by each stream */
3770 static void compute_bandwidth(void)
3771 {
3772     unsigned bandwidth;
3773     int i;
3774     FFStream *stream;
3775
3776     for(stream = first_stream; stream != NULL; stream = stream->next) {
3777         bandwidth = 0;
3778         for(i=0;i<stream->nb_streams;i++) {
3779             AVStream *st = stream->streams[i];
3780             switch(st->codec->codec_type) {
3781             case AVMEDIA_TYPE_AUDIO:
3782             case AVMEDIA_TYPE_VIDEO:
3783                 bandwidth += st->codec->bit_rate;
3784                 break;
3785             default:
3786                 break;
3787             }
3788         }
3789         stream->bandwidth = (bandwidth + 999) / 1000;
3790     }
3791 }
3792
3793 /* add a codec and set the default parameters */
3794 static void add_codec(FFStream *stream, AVCodecContext *av)
3795 {
3796     AVStream *st;
3797
3798     /* compute default parameters */
3799     switch(av->codec_type) {
3800     case AVMEDIA_TYPE_AUDIO:
3801         if (av->bit_rate == 0)
3802             av->bit_rate = 64000;
3803         if (av->sample_rate == 0)
3804             av->sample_rate = 22050;
3805         if (av->channels == 0)
3806             av->channels = 1;
3807         break;
3808     case AVMEDIA_TYPE_VIDEO:
3809         if (av->bit_rate == 0)
3810             av->bit_rate = 64000;
3811         if (av->time_base.num == 0){
3812             av->time_base.den = 5;
3813             av->time_base.num = 1;
3814         }
3815         if (av->width == 0 || av->height == 0) {
3816             av->width = 160;
3817             av->height = 128;
3818         }
3819         /* Bitrate tolerance is less for streaming */
3820         if (av->bit_rate_tolerance == 0)
3821             av->bit_rate_tolerance = FFMAX(av->bit_rate / 4,
3822                       (int64_t)av->bit_rate*av->time_base.num/av->time_base.den);
3823         if (av->qmin == 0)
3824             av->qmin = 3;
3825         if (av->qmax == 0)
3826             av->qmax = 31;
3827         if (av->max_qdiff == 0)
3828             av->max_qdiff = 3;
3829         av->qcompress = 0.5;
3830         av->qblur = 0.5;
3831
3832         if (!av->nsse_weight)
3833             av->nsse_weight = 8;
3834
3835         av->frame_skip_cmp = FF_CMP_DCTMAX;
3836         if (!av->me_method)
3837             av->me_method = ME_EPZS;
3838         av->rc_buffer_aggressivity = 1.0;
3839
3840         if (!av->rc_eq)
3841             av->rc_eq = "tex^qComp";
3842         if (!av->i_quant_factor)
3843             av->i_quant_factor = -0.8;
3844         if (!av->b_quant_factor)
3845             av->b_quant_factor = 1.25;
3846         if (!av->b_quant_offset)
3847             av->b_quant_offset = 1.25;
3848         if (!av->rc_max_rate)
3849             av->rc_max_rate = av->bit_rate * 2;
3850
3851         if (av->rc_max_rate && !av->rc_buffer_size) {
3852             av->rc_buffer_size = av->rc_max_rate;
3853         }
3854
3855
3856         break;
3857     default:
3858         abort();
3859     }
3860
3861     st = av_mallocz(sizeof(AVStream));
3862     if (!st)
3863         return;
3864     st->codec = avcodec_alloc_context3(NULL);
3865     stream->streams[stream->nb_streams++] = st;
3866     memcpy(st->codec, av, sizeof(AVCodecContext));
3867 }
3868
3869 static enum AVCodecID opt_audio_codec(const char *arg)
3870 {
3871     AVCodec *p= avcodec_find_encoder_by_name(arg);
3872
3873     if (p == NULL || p->type != AVMEDIA_TYPE_AUDIO)
3874         return AV_CODEC_ID_NONE;
3875
3876     return p->id;
3877 }
3878
3879 static enum AVCodecID opt_video_codec(const char *arg)
3880 {
3881     AVCodec *p= avcodec_find_encoder_by_name(arg);
3882
3883     if (p == NULL || p->type != AVMEDIA_TYPE_VIDEO)
3884         return AV_CODEC_ID_NONE;
3885
3886     return p->id;
3887 }
3888
3889 /* simplistic plugin support */
3890
3891 #if HAVE_DLOPEN
3892 static void load_module(const char *filename)
3893 {
3894     void *dll;
3895     void (*init_func)(void);
3896     dll = dlopen(filename, RTLD_NOW);
3897     if (!dll) {
3898         fprintf(stderr, "Could not load module '%s' - %s\n",
3899                 filename, dlerror());
3900         return;
3901     }
3902
3903     init_func = dlsym(dll, "avserver_module_init");
3904     if (!init_func) {
3905         fprintf(stderr,
3906                 "%s: init function 'avserver_module_init()' not found\n",
3907                 filename);
3908         dlclose(dll);
3909     }
3910
3911     init_func();
3912 }
3913 #endif
3914
3915 static int avserver_opt_default(const char *opt, const char *arg,
3916                        AVCodecContext *avctx, int type)
3917 {
3918     int ret = 0;
3919     const AVOption *o = av_opt_find(avctx, opt, NULL, type, 0);
3920     if(o)
3921         ret = av_opt_set(avctx, opt, arg, 0);
3922     return ret;
3923 }
3924
3925 static int avserver_opt_preset(const char *arg,
3926                        AVCodecContext *avctx, int type,
3927                        enum AVCodecID *audio_id, enum AVCodecID *video_id)
3928 {
3929     FILE *f=NULL;
3930     char filename[1000], tmp[1000], tmp2[1000], line[1000];
3931     int ret = 0;
3932     AVCodec *codec = avcodec_find_encoder(avctx->codec_id);
3933
3934     if (!(f = get_preset_file(filename, sizeof(filename), arg, 0,
3935                               codec ? codec->name : NULL))) {
3936         fprintf(stderr, "File for preset '%s' not found\n", arg);
3937         return 1;
3938     }
3939
3940     while(!feof(f)){
3941         int e= fscanf(f, "%999[^\n]\n", line) - 1;
3942         if(line[0] == '#' && !e)
3943             continue;
3944         e|= sscanf(line, "%999[^=]=%999[^\n]\n", tmp, tmp2) - 2;
3945         if(e){
3946             fprintf(stderr, "%s: Invalid syntax: '%s'\n", filename, line);
3947             ret = 1;
3948             break;
3949         }
3950         if(!strcmp(tmp, "acodec")){
3951             *audio_id = opt_audio_codec(tmp2);
3952         }else if(!strcmp(tmp, "vcodec")){
3953             *video_id = opt_video_codec(tmp2);
3954         }else if(!strcmp(tmp, "scodec")){
3955             /* opt_subtitle_codec(tmp2); */
3956         }else if(avserver_opt_default(tmp, tmp2, avctx, type) < 0){
3957             fprintf(stderr, "%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", filename, line, tmp, tmp2);
3958             ret = 1;
3959             break;
3960         }
3961     }
3962
3963     fclose(f);
3964
3965     return ret;
3966 }
3967
3968 static AVOutputFormat *avserver_guess_format(const char *short_name, const char *filename,
3969                                              const char *mime_type)
3970 {
3971     AVOutputFormat *fmt = av_guess_format(short_name, filename, mime_type);
3972
3973     if (fmt) {
3974         AVOutputFormat *stream_fmt;
3975         char stream_format_name[64];
3976
3977         snprintf(stream_format_name, sizeof(stream_format_name), "%s_stream", fmt->name);
3978         stream_fmt = av_guess_format(stream_format_name, NULL, NULL);
3979
3980         if (stream_fmt)
3981             fmt = stream_fmt;
3982     }
3983
3984     return fmt;
3985 }
3986
3987 static void report_config_error(const char *filename, int line_num, int *errors, const char *fmt, ...)
3988 {
3989     va_list vl;
3990     va_start(vl, fmt);
3991     fprintf(stderr, "%s:%d: ", filename, line_num);
3992     vfprintf(stderr, fmt, vl);
3993     va_end(vl);
3994
3995     (*errors)++;
3996 }
3997
3998 static int parse_ffconfig(const char *filename)
3999 {
4000     FILE *f;
4001     char line[1024];
4002     char cmd[64];
4003     char arg[1024];
4004     const char *p;
4005     int val, errors, line_num;
4006     FFStream **last_stream, *stream, *redirect;
4007     FFStream **last_feed, *feed, *s;
4008     AVCodecContext audio_enc, video_enc;
4009     enum AVCodecID audio_id, video_id;
4010
4011     f = fopen(filename, "r");
4012     if (!f) {
4013         perror(filename);
4014         return -1;
4015     }
4016
4017     errors = 0;
4018     line_num = 0;
4019     first_stream = NULL;
4020     last_stream = &first_stream;
4021     first_feed = NULL;
4022     last_feed = &first_feed;
4023     stream = NULL;
4024     feed = NULL;
4025     redirect = NULL;
4026     audio_id = AV_CODEC_ID_NONE;
4027     video_id = AV_CODEC_ID_NONE;
4028
4029 #define ERROR(...) report_config_error(filename, line_num, &errors, __VA_ARGS__)
4030     for(;;) {
4031         if (fgets(line, sizeof(line), f) == NULL)
4032             break;
4033         line_num++;
4034         p = line;
4035         while (isspace(*p))
4036             p++;
4037         if (*p == '\0' || *p == '#')
4038             continue;
4039
4040         get_arg(cmd, sizeof(cmd), &p);
4041
4042         if (!av_strcasecmp(cmd, "Port")) {
4043             get_arg(arg, sizeof(arg), &p);
4044             val = atoi(arg);
4045             if (val < 1 || val > 65536) {
4046                 ERROR("Invalid_port: %s\n", arg);
4047             }
4048             my_http_addr.sin_port = htons(val);
4049         } else if (!av_strcasecmp(cmd, "BindAddress")) {
4050             get_arg(arg, sizeof(arg), &p);
4051             if (resolve_host(&my_http_addr.sin_addr, arg) != 0) {
4052                 ERROR("%s:%d: Invalid host/IP address: %s\n", arg);
4053             }
4054         } else if (!av_strcasecmp(cmd, "NoDaemon")) {
4055             avserver_daemon = 0;
4056         } else if (!av_strcasecmp(cmd, "RTSPPort")) {
4057             get_arg(arg, sizeof(arg), &p);
4058             val = atoi(arg);
4059             if (val < 1 || val > 65536) {
4060                 ERROR("%s:%d: Invalid port: %s\n", arg);
4061             }
4062             my_rtsp_addr.sin_port = htons(atoi(arg));
4063         } else if (!av_strcasecmp(cmd, "RTSPBindAddress")) {
4064             get_arg(arg, sizeof(arg), &p);
4065             if (resolve_host(&my_rtsp_addr.sin_addr, arg) != 0) {
4066                 ERROR("Invalid host/IP address: %s\n", arg);
4067             }
4068         } else if (!av_strcasecmp(cmd, "MaxHTTPConnections")) {
4069             get_arg(arg, sizeof(arg), &p);
4070             val = atoi(arg);
4071             if (val < 1 || val > 65536) {
4072                 ERROR("Invalid MaxHTTPConnections: %s\n", arg);
4073             }
4074             nb_max_http_connections = val;
4075         } else if (!av_strcasecmp(cmd, "MaxClients")) {
4076             get_arg(arg, sizeof(arg), &p);
4077             val = atoi(arg);
4078             if (val < 1 || val > nb_max_http_connections) {
4079                 ERROR("Invalid MaxClients: %s\n", arg);
4080             } else {
4081                 nb_max_connections = val;
4082             }
4083         } else if (!av_strcasecmp(cmd, "MaxBandwidth")) {
4084             int64_t llval;
4085             get_arg(arg, sizeof(arg), &p);
4086             llval = atoll(arg);
4087             if (llval < 10 || llval > 10000000) {
4088                 ERROR("Invalid MaxBandwidth: %s\n", arg);
4089             } else
4090                 max_bandwidth = llval;
4091         } else if (!av_strcasecmp(cmd, "CustomLog")) {
4092             if (!avserver_debug)
4093                 get_arg(logfilename, sizeof(logfilename), &p);
4094         } else if (!av_strcasecmp(cmd, "<Feed")) {
4095             /*********************************************/
4096             /* Feed related options */
4097             char *q;
4098             if (stream || feed) {
4099                 ERROR("Already in a tag\n");
4100             } else {
4101                 feed = av_mallocz(sizeof(FFStream));
4102                 get_arg(feed->filename, sizeof(feed->filename), &p);
4103                 q = strrchr(feed->filename, '>');
4104                 if (*q)
4105                     *q = '\0';
4106
4107                 for (s = first_feed; s; s = s->next) {
4108                     if (!strcmp(feed->filename, s->filename)) {
4109                         ERROR("Feed '%s' already registered\n", s->filename);
4110                     }
4111                 }
4112
4113                 feed->fmt = av_guess_format("ffm", NULL, NULL);
4114                 /* defaut feed file */
4115                 snprintf(feed->feed_filename, sizeof(feed->feed_filename),
4116                          "/tmp/%s.ffm", feed->filename);
4117                 feed->feed_max_size = 5 * 1024 * 1024;
4118                 feed->is_feed = 1;
4119                 feed->feed = feed; /* self feeding :-) */
4120
4121                 /* add in stream list */
4122                 *last_stream = feed;
4123                 last_stream = &feed->next;
4124                 /* add in feed list */
4125                 *last_feed = feed;
4126                 last_feed = &feed->next_feed;
4127             }
4128         } else if (!av_strcasecmp(cmd, "Launch")) {
4129             if (feed) {
4130                 int i;
4131
4132                 feed->child_argv = av_mallocz(64 * sizeof(char *));
4133
4134                 for (i = 0; i < 62; i++) {
4135                     get_arg(arg, sizeof(arg), &p);
4136                     if (!arg[0])
4137                         break;
4138
4139                     feed->child_argv[i] = av_strdup(arg);
4140                 }
4141
4142                 feed->child_argv[i] = av_malloc(30 + strlen(feed->filename));
4143
4144                 snprintf(feed->child_argv[i], 30+strlen(feed->filename),
4145                     "http://%s:%d/%s",
4146                         (my_http_addr.sin_addr.s_addr == INADDR_ANY) ? "127.0.0.1" :
4147                     inet_ntoa(my_http_addr.sin_addr),
4148                     ntohs(my_http_addr.sin_port), feed->filename);
4149             }
4150         } else if (!av_strcasecmp(cmd, "ReadOnlyFile")) {
4151             if (feed) {
4152                 get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
4153                 feed->readonly = 1;
4154             } else if (stream) {
4155                 get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4156             }
4157         } else if (!av_strcasecmp(cmd, "File")) {
4158             if (feed) {
4159                 get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
4160             } else if (stream)
4161                 get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4162         } else if (!av_strcasecmp(cmd, "Truncate")) {
4163             if (feed) {
4164                 get_arg(arg, sizeof(arg), &p);
4165                 feed->truncate = strtod(arg, NULL);
4166             }
4167         } else if (!av_strcasecmp(cmd, "FileMaxSize")) {
4168             if (feed) {
4169                 char *p1;
4170                 double fsize;
4171
4172                 get_arg(arg, sizeof(arg), &p);
4173                 p1 = arg;
4174                 fsize = strtod(p1, &p1);
4175                 switch(toupper(*p1)) {
4176                 case 'K':
4177                     fsize *= 1024;
4178                     break;
4179                 case 'M':
4180                     fsize *= 1024 * 1024;
4181                     break;
4182                 case 'G':
4183                     fsize *= 1024 * 1024 * 1024;
4184                     break;
4185                 }
4186                 feed->feed_max_size = (int64_t)fsize;
4187                 if (feed->feed_max_size < FFM_PACKET_SIZE*4) {
4188                     ERROR("Feed max file size is too small, must be at least %d\n", FFM_PACKET_SIZE*4);
4189                 }
4190             }
4191         } else if (!av_strcasecmp(cmd, "</Feed>")) {
4192             if (!feed) {
4193                 ERROR("No corresponding <Feed> for </Feed>\n");
4194             }
4195             feed = NULL;
4196         } else if (!av_strcasecmp(cmd, "<Stream")) {
4197             /*********************************************/
4198             /* Stream related options */
4199             char *q;
4200             if (stream || feed) {
4201                 ERROR("Already in a tag\n");
4202             } else {
4203                 FFStream *s;
4204                 stream = av_mallocz(sizeof(FFStream));
4205                 get_arg(stream->filename, sizeof(stream->filename), &p);
4206                 q = strrchr(stream->filename, '>');
4207                 if (*q)
4208                     *q = '\0';
4209
4210                 for (s = first_stream; s; s = s->next) {
4211                     if (!strcmp(stream->filename, s->filename)) {
4212                         ERROR("Stream '%s' already registered\n", s->filename);
4213                     }
4214                 }
4215
4216                 stream->fmt = avserver_guess_format(NULL, stream->filename, NULL);
4217                 avcodec_get_context_defaults3(&video_enc, NULL);
4218                 avcodec_get_context_defaults3(&audio_enc, NULL);
4219                 audio_id = AV_CODEC_ID_NONE;
4220                 video_id = AV_CODEC_ID_NONE;
4221                 if (stream->fmt) {
4222                     audio_id = stream->fmt->audio_codec;
4223                     video_id = stream->fmt->video_codec;
4224                 }
4225
4226                 *last_stream = stream;
4227                 last_stream = &stream->next;
4228             }
4229         } else if (!av_strcasecmp(cmd, "Feed")) {
4230             get_arg(arg, sizeof(arg), &p);
4231             if (stream) {
4232                 FFStream *sfeed;
4233
4234                 sfeed = first_feed;
4235                 while (sfeed != NULL) {
4236                     if (!strcmp(sfeed->filename, arg))
4237                         break;
4238                     sfeed = sfeed->next_feed;
4239                 }
4240                 if (!sfeed)
4241                     ERROR("feed '%s' not defined\n", arg);
4242                 else
4243                     stream->feed = sfeed;
4244             }
4245         } else if (!av_strcasecmp(cmd, "Format")) {
4246             get_arg(arg, sizeof(arg), &p);
4247             if (stream) {
4248                 if (!strcmp(arg, "status")) {
4249                     stream->stream_type = STREAM_TYPE_STATUS;
4250                     stream->fmt = NULL;
4251                 } else {
4252                     stream->stream_type = STREAM_TYPE_LIVE;
4253                     /* jpeg cannot be used here, so use single frame jpeg */
4254                     if (!strcmp(arg, "jpeg"))
4255                         strcpy(arg, "mjpeg");
4256                     stream->fmt = avserver_guess_format(arg, NULL, NULL);
4257                     if (!stream->fmt) {
4258                         ERROR("Unknown Format: %s\n", arg);
4259                     }
4260                 }
4261                 if (stream->fmt) {
4262                     audio_id = stream->fmt->audio_codec;
4263                     video_id = stream->fmt->video_codec;
4264                 }
4265             }
4266         } else if (!av_strcasecmp(cmd, "InputFormat")) {
4267             get_arg(arg, sizeof(arg), &p);
4268             if (stream) {
4269                 stream->ifmt = av_find_input_format(arg);
4270                 if (!stream->ifmt) {
4271                     ERROR("Unknown input format: %s\n", arg);
4272                 }
4273             }
4274         } else if (!av_strcasecmp(cmd, "FaviconURL")) {
4275             if (stream && stream->stream_type == STREAM_TYPE_STATUS) {
4276                 get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4277             } else {
4278                 ERROR("FaviconURL only permitted for status streams\n");
4279             }
4280         } else if (!av_strcasecmp(cmd, "Author")) {
4281             if (stream)
4282                 get_arg(stream->author, sizeof(stream->author), &p);
4283         } else if (!av_strcasecmp(cmd, "Comment")) {
4284             if (stream)
4285                 get_arg(stream->comment, sizeof(stream->comment), &p);
4286         } else if (!av_strcasecmp(cmd, "Copyright")) {
4287             if (stream)
4288                 get_arg(stream->copyright, sizeof(stream->copyright), &p);
4289         } else if (!av_strcasecmp(cmd, "Title")) {
4290             if (stream)
4291                 get_arg(stream->title, sizeof(stream->title), &p);
4292         } else if (!av_strcasecmp(cmd, "Preroll")) {
4293             get_arg(arg, sizeof(arg), &p);
4294             if (stream)
4295                 stream->prebuffer = atof(arg) * 1000;
4296         } else if (!av_strcasecmp(cmd, "StartSendOnKey")) {
4297             if (stream)
4298                 stream->send_on_key = 1;
4299         } else if (!av_strcasecmp(cmd, "AudioCodec")) {
4300             get_arg(arg, sizeof(arg), &p);
4301             audio_id = opt_audio_codec(arg);
4302             if (audio_id == AV_CODEC_ID_NONE) {
4303                 ERROR("Unknown AudioCodec: %s\n", arg);
4304             }
4305         } else if (!av_strcasecmp(cmd, "VideoCodec")) {
4306             get_arg(arg, sizeof(arg), &p);
4307             video_id = opt_video_codec(arg);
4308             if (video_id == AV_CODEC_ID_NONE) {
4309                 ERROR("Unknown VideoCodec: %s\n", arg);
4310             }
4311         } else if (!av_strcasecmp(cmd, "MaxTime")) {
4312             get_arg(arg, sizeof(arg), &p);
4313             if (stream)
4314                 stream->max_time = atof(arg) * 1000;
4315         } else if (!av_strcasecmp(cmd, "AudioBitRate")) {
4316             get_arg(arg, sizeof(arg), &p);
4317             if (stream)
4318                 audio_enc.bit_rate = lrintf(atof(arg) * 1000);
4319         } else if (!av_strcasecmp(cmd, "AudioChannels")) {
4320             get_arg(arg, sizeof(arg), &p);
4321             if (stream)
4322                 audio_enc.channels = atoi(arg);
4323         } else if (!av_strcasecmp(cmd, "AudioSampleRate")) {
4324             get_arg(arg, sizeof(arg), &p);
4325             if (stream)
4326                 audio_enc.sample_rate = atoi(arg);
4327         } else if (!av_strcasecmp(cmd, "AudioQuality")) {
4328             get_arg(arg, sizeof(arg), &p);
4329             if (stream) {
4330 //                audio_enc.quality = atof(arg) * 1000;
4331             }
4332         } else if (!av_strcasecmp(cmd, "VideoBitRateRange")) {
4333             if (stream) {
4334                 int minrate, maxrate;
4335
4336                 get_arg(arg, sizeof(arg), &p);
4337
4338                 if (sscanf(arg, "%d-%d", &minrate, &maxrate) == 2) {
4339                     video_enc.rc_min_rate = minrate * 1000;
4340                     video_enc.rc_max_rate = maxrate * 1000;
4341                 } else {
4342                     ERROR("Incorrect format for VideoBitRateRange -- should be <min>-<max>: %s\n", arg);
4343                 }
4344             }
4345         } else if (!av_strcasecmp(cmd, "Debug")) {
4346             if (stream) {
4347                 get_arg(arg, sizeof(arg), &p);
4348                 video_enc.debug = strtol(arg,0,0);
4349             }
4350         } else if (!av_strcasecmp(cmd, "Strict")) {
4351             if (stream) {
4352                 get_arg(arg, sizeof(arg), &p);
4353                 video_enc.strict_std_compliance = atoi(arg);
4354             }
4355         } else if (!av_strcasecmp(cmd, "VideoBufferSize")) {
4356             if (stream) {
4357                 get_arg(arg, sizeof(arg), &p);
4358                 video_enc.rc_buffer_size = atoi(arg) * 8*1024;
4359             }
4360         } else if (!av_strcasecmp(cmd, "VideoBitRateTolerance")) {
4361             if (stream) {
4362                 get_arg(arg, sizeof(arg), &p);
4363                 video_enc.bit_rate_tolerance = atoi(arg) * 1000;
4364             }
4365         } else if (!av_strcasecmp(cmd, "VideoBitRate")) {
4366             get_arg(arg, sizeof(arg), &p);
4367             if (stream) {
4368                 video_enc.bit_rate = atoi(arg) * 1000;
4369             }
4370         } else if (!av_strcasecmp(cmd, "VideoSize")) {
4371             get_arg(arg, sizeof(arg), &p);
4372             if (stream) {
4373                 av_parse_video_size(&video_enc.width, &video_enc.height, arg);
4374                 if ((video_enc.width % 16) != 0 ||
4375                     (video_enc.height % 16) != 0) {
4376                     ERROR("Image size must be a multiple of 16\n");
4377                 }
4378             }
4379         } else if (!av_strcasecmp(cmd, "VideoFrameRate")) {
4380             get_arg(arg, sizeof(arg), &p);
4381             if (stream) {
4382                 AVRational frame_rate;
4383                 if (av_parse_video_rate(&frame_rate, arg) < 0) {
4384                     ERROR("Incorrect frame rate: %s\n", arg);
4385                 } else {
4386                     video_enc.time_base.num = frame_rate.den;
4387                     video_enc.time_base.den = frame_rate.num;
4388                 }
4389             }
4390         } else if (!av_strcasecmp(cmd, "VideoGopSize")) {
4391             get_arg(arg, sizeof(arg), &p);
4392             if (stream)
4393                 video_enc.gop_size = atoi(arg);
4394         } else if (!av_strcasecmp(cmd, "VideoIntraOnly")) {
4395             if (stream)
4396                 video_enc.gop_size = 1;
4397         } else if (!av_strcasecmp(cmd, "VideoHighQuality")) {
4398             if (stream)
4399                 video_enc.mb_decision = FF_MB_DECISION_BITS;
4400         } else if (!av_strcasecmp(cmd, "Video4MotionVector")) {
4401             if (stream) {
4402                 video_enc.mb_decision = FF_MB_DECISION_BITS; //FIXME remove
4403                 video_enc.flags |= CODEC_FLAG_4MV;
4404             }
4405         } else if (!av_strcasecmp(cmd, "AVOptionVideo") ||
4406                    !av_strcasecmp(cmd, "AVOptionAudio")) {
4407             char arg2[1024];
4408             AVCodecContext *avctx;
4409             int type;
4410             get_arg(arg, sizeof(arg), &p);
4411             get_arg(arg2, sizeof(arg2), &p);
4412             if (!av_strcasecmp(cmd, "AVOptionVideo")) {
4413                 avctx = &video_enc;
4414                 type = AV_OPT_FLAG_VIDEO_PARAM;
4415             } else {
4416                 avctx = &audio_enc;
4417                 type = AV_OPT_FLAG_AUDIO_PARAM;
4418             }
4419             if (avserver_opt_default(arg, arg2, avctx, type|AV_OPT_FLAG_ENCODING_PARAM)) {
4420                 ERROR("AVOption error: %s %s\n", arg, arg2);
4421             }
4422         } else if (!av_strcasecmp(cmd, "AVPresetVideo") ||
4423                    !av_strcasecmp(cmd, "AVPresetAudio")) {
4424             AVCodecContext *avctx;
4425             int type;
4426             get_arg(arg, sizeof(arg), &p);
4427             if (!av_strcasecmp(cmd, "AVPresetVideo")) {
4428                 avctx = &video_enc;
4429                 video_enc.codec_id = video_id;
4430                 type = AV_OPT_FLAG_VIDEO_PARAM;
4431             } else {
4432                 avctx = &audio_enc;
4433                 audio_enc.codec_id = audio_id;
4434                 type = AV_OPT_FLAG_AUDIO_PARAM;
4435             }
4436             if (avserver_opt_preset(arg, avctx, type|AV_OPT_FLAG_ENCODING_PARAM, &audio_id, &video_id)) {
4437                 ERROR("AVPreset error: %s\n", arg);
4438             }
4439         } else if (!av_strcasecmp(cmd, "VideoTag")) {
4440             get_arg(arg, sizeof(arg), &p);
4441             if ((strlen(arg) == 4) && stream)
4442                 video_enc.codec_tag = MKTAG(arg[0], arg[1], arg[2], arg[3]);
4443         } else if (!av_strcasecmp(cmd, "BitExact")) {
4444             if (stream)
4445                 video_enc.flags |= CODEC_FLAG_BITEXACT;
4446         } else if (!av_strcasecmp(cmd, "DctFastint")) {
4447             if (stream)
4448                 video_enc.dct_algo  = FF_DCT_FASTINT;
4449         } else if (!av_strcasecmp(cmd, "IdctSimple")) {
4450             if (stream)
4451                 video_enc.idct_algo = FF_IDCT_SIMPLE;
4452         } else if (!av_strcasecmp(cmd, "Qscale")) {
4453             get_arg(arg, sizeof(arg), &p);
4454             if (stream) {
4455                 video_enc.flags |= CODEC_FLAG_QSCALE;
4456                 video_enc.global_quality = FF_QP2LAMBDA * atoi(arg);
4457             }
4458         } else if (!av_strcasecmp(cmd, "VideoQDiff")) {
4459             get_arg(arg, sizeof(arg), &p);
4460             if (stream) {
4461                 video_enc.max_qdiff = atoi(arg);
4462                 if (video_enc.max_qdiff < 1 || video_enc.max_qdiff > 31) {
4463                     ERROR("VideoQDiff out of range\n");
4464                 }
4465             }
4466         } else if (!av_strcasecmp(cmd, "VideoQMax")) {
4467             get_arg(arg, sizeof(arg), &p);
4468             if (stream) {
4469                 video_enc.qmax = atoi(arg);
4470                 if (video_enc.qmax < 1 || video_enc.qmax > 31) {
4471                     ERROR("VideoQMax out of range\n");
4472                 }
4473             }
4474         } else if (!av_strcasecmp(cmd, "VideoQMin")) {
4475             get_arg(arg, sizeof(arg), &p);
4476             if (stream) {
4477                 video_enc.qmin = atoi(arg);
4478                 if (video_enc.qmin < 1 || video_enc.qmin > 31) {
4479                     ERROR("VideoQMin out of range\n");
4480                 }
4481             }
4482         } else if (!av_strcasecmp(cmd, "LumaElim")) {
4483             get_arg(arg, sizeof(arg), &p);
4484             if (stream)
4485                 video_enc.luma_elim_threshold = atoi(arg);
4486         } else if (!av_strcasecmp(cmd, "ChromaElim")) {
4487             get_arg(arg, sizeof(arg), &p);
4488             if (stream)
4489                 video_enc.chroma_elim_threshold = atoi(arg);
4490         } else if (!av_strcasecmp(cmd, "LumiMask")) {
4491             get_arg(arg, sizeof(arg), &p);
4492             if (stream)
4493                 video_enc.lumi_masking = atof(arg);
4494         } else if (!av_strcasecmp(cmd, "DarkMask")) {
4495             get_arg(arg, sizeof(arg), &p);
4496             if (stream)
4497                 video_enc.dark_masking = atof(arg);
4498         } else if (!av_strcasecmp(cmd, "NoVideo")) {
4499             video_id = AV_CODEC_ID_NONE;
4500         } else if (!av_strcasecmp(cmd, "NoAudio")) {
4501             audio_id = AV_CODEC_ID_NONE;
4502         } else if (!av_strcasecmp(cmd, "ACL")) {
4503             parse_acl_row(stream, feed, NULL, p, filename, line_num);
4504         } else if (!av_strcasecmp(cmd, "DynamicACL")) {
4505             if (stream) {
4506                 get_arg(stream->dynamic_acl, sizeof(stream->dynamic_acl), &p);
4507             }
4508         } else if (!av_strcasecmp(cmd, "RTSPOption")) {
4509             get_arg(arg, sizeof(arg), &p);
4510             if (stream) {
4511                 av_freep(&stream->rtsp_option);
4512                 stream->rtsp_option = av_strdup(arg);
4513             }
4514         } else if (!av_strcasecmp(cmd, "MulticastAddress")) {
4515             get_arg(arg, sizeof(arg), &p);
4516             if (stream) {
4517                 if (resolve_host(&stream->multicast_ip, arg) != 0) {
4518                     ERROR("Invalid host/IP address: %s\n", arg);
4519                 }
4520                 stream->is_multicast = 1;
4521                 stream->loop = 1; /* default is looping */
4522             }
4523         } else if (!av_strcasecmp(cmd, "MulticastPort")) {
4524             get_arg(arg, sizeof(arg), &p);
4525             if (stream)
4526                 stream->multicast_port = atoi(arg);
4527         } else if (!av_strcasecmp(cmd, "MulticastTTL")) {
4528             get_arg(arg, sizeof(arg), &p);
4529             if (stream)
4530                 stream->multicast_ttl = atoi(arg);
4531         } else if (!av_strcasecmp(cmd, "NoLoop")) {
4532             if (stream)
4533                 stream->loop = 0;
4534         } else if (!av_strcasecmp(cmd, "</Stream>")) {
4535             if (!stream) {
4536                 ERROR("No corresponding <Stream> for </Stream>\n");
4537             } else {
4538                 if (stream->feed && stream->fmt && strcmp(stream->fmt->name, "ffm") != 0) {
4539                     if (audio_id != AV_CODEC_ID_NONE) {
4540                         audio_enc.codec_type = AVMEDIA_TYPE_AUDIO;
4541                         audio_enc.codec_id = audio_id;
4542                         add_codec(stream, &audio_enc);
4543                     }
4544                     if (video_id != AV_CODEC_ID_NONE) {
4545                         video_enc.codec_type = AVMEDIA_TYPE_VIDEO;
4546                         video_enc.codec_id = video_id;
4547                         add_codec(stream, &video_enc);
4548                     }
4549                 }
4550                 stream = NULL;
4551             }
4552         } else if (!av_strcasecmp(cmd, "<Redirect")) {
4553             /*********************************************/
4554             char *q;
4555             if (stream || feed || redirect) {
4556                 ERROR("Already in a tag\n");
4557             } else {
4558                 redirect = av_mallocz(sizeof(FFStream));
4559                 *last_stream = redirect;
4560                 last_stream = &redirect->next;
4561
4562                 get_arg(redirect->filename, sizeof(redirect->filename), &p);
4563                 q = strrchr(redirect->filename, '>');
4564                 if (*q)
4565                     *q = '\0';
4566                 redirect->stream_type = STREAM_TYPE_REDIRECT;
4567             }
4568         } else if (!av_strcasecmp(cmd, "URL")) {
4569             if (redirect)
4570                 get_arg(redirect->feed_filename, sizeof(redirect->feed_filename), &p);
4571         } else if (!av_strcasecmp(cmd, "</Redirect>")) {
4572             if (!redirect) {
4573                 ERROR("No corresponding <Redirect> for </Redirect>\n");
4574             } else {
4575                 if (!redirect->feed_filename[0]) {
4576                     ERROR("No URL found for <Redirect>\n");
4577                 }
4578                 redirect = NULL;
4579             }
4580         } else if (!av_strcasecmp(cmd, "LoadModule")) {
4581             get_arg(arg, sizeof(arg), &p);
4582 #if HAVE_DLOPEN
4583             load_module(arg);
4584 #else
4585             ERROR("Module support not compiled into this version: '%s'\n", arg);
4586 #endif
4587         } else {
4588             ERROR("Incorrect keyword: '%s'\n", cmd);
4589         }
4590     }
4591 #undef ERROR
4592
4593     fclose(f);
4594     if (errors)
4595         return -1;
4596     else
4597         return 0;
4598 }
4599
4600 static void handle_child_exit(int sig)
4601 {
4602     pid_t pid;
4603     int status;
4604
4605     while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
4606         FFStream *feed;
4607
4608         for (feed = first_feed; feed; feed = feed->next) {
4609             if (feed->pid == pid) {
4610                 int uptime = time(0) - feed->pid_start;
4611
4612                 feed->pid = 0;
4613                 fprintf(stderr, "%s: Pid %d exited with status %d after %d seconds\n", feed->filename, pid, status, uptime);
4614
4615                 if (uptime < 30)
4616                     /* Turn off any more restarts */
4617                     feed->child_argv = 0;
4618             }
4619         }
4620     }
4621
4622     need_to_start_children = 1;
4623 }
4624
4625 static void opt_debug(void)
4626 {
4627     avserver_debug = 1;
4628     avserver_daemon = 0;
4629     logfilename[0] = '-';
4630 }
4631
4632 void show_help_default(const char *opt, const char *arg)
4633 {
4634     printf("usage: avserver [options]\n"
4635            "Hyper fast multi format Audio/Video streaming server\n");
4636     printf("\n");
4637     show_help_options(options, "Main options:", 0, 0);
4638 }
4639
4640 static const OptionDef options[] = {
4641 #include "cmdutils_common_opts.h"
4642     { "n", OPT_BOOL, {(void *)&no_launch }, "enable no-launch mode" },
4643     { "d", 0, {(void*)opt_debug}, "enable debug mode" },
4644     { "f", HAS_ARG | OPT_STRING, {(void*)&config_filename }, "use configfile instead of /etc/avserver.conf", "configfile" },
4645     { NULL },
4646 };
4647
4648 int main(int argc, char **argv)
4649 {
4650     struct sigaction sigact = { { 0 } };
4651
4652     parse_loglevel(argc, argv, options);
4653     av_register_all();
4654     avformat_network_init();
4655
4656     show_banner();
4657
4658     my_program_name = argv[0];
4659     my_program_dir = getcwd(0, 0);
4660     avserver_daemon = 1;
4661
4662     parse_options(NULL, argc, argv, options, NULL);
4663
4664     unsetenv("http_proxy");             /* Kill the http_proxy */
4665
4666     av_lfg_init(&random_state, av_get_random_seed());
4667
4668     sigact.sa_handler = handle_child_exit;
4669     sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
4670     sigaction(SIGCHLD, &sigact, 0);
4671
4672     if (parse_ffconfig(config_filename) < 0) {
4673         fprintf(stderr, "Incorrect config file - exiting.\n");
4674         exit(1);
4675     }
4676
4677     /* open log file if needed */
4678     if (logfilename[0] != '\0') {
4679         if (!strcmp(logfilename, "-"))
4680             logfile = stdout;
4681         else
4682             logfile = fopen(logfilename, "a");
4683         av_log_set_callback(http_av_log);
4684     }
4685
4686     build_file_streams();
4687
4688     build_feed_streams();
4689
4690     compute_bandwidth();
4691
4692     /* put the process in background and detach it from its TTY */
4693     if (avserver_daemon) {
4694         int pid;
4695
4696         pid = fork();
4697         if (pid < 0) {
4698             perror("fork");
4699             exit(1);
4700         } else if (pid > 0) {
4701             /* parent : exit */
4702             exit(0);
4703         } else {
4704             /* child */
4705             setsid();
4706             close(0);
4707             open("/dev/null", O_RDWR);
4708             if (strcmp(logfilename, "-") != 0) {
4709                 close(1);
4710                 dup(0);
4711             }
4712             close(2);
4713             dup(0);
4714         }
4715     }
4716
4717     /* signal init */
4718     signal(SIGPIPE, SIG_IGN);
4719
4720     if (avserver_daemon)
4721         chdir("/");
4722
4723     if (http_server() < 0) {
4724         http_log("Could not start server\n");
4725         exit(1);
4726     }
4727
4728     return 0;
4729 }