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