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