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