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