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