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