OSDN Git Service

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