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