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