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