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