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