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