]> git.sesse.net Git - ffmpeg/blob - ffserver.c
Simplify H.264 decode_cabac_mb_cbp_luma(), giving a ~0.5% speedup.
[ffmpeg] / 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 (stream->fmt && !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         {
1891             stream_pos = parse_date(buf, 0);
1892             if (stream_pos == INT64_MIN)
1893                 return -1;
1894         }
1895         else if (find_info_tag(buf, sizeof(buf), "buffer", info)) {
1896             int prebuffer = strtol(buf, 0, 10);
1897             stream_pos = av_gettime() - prebuffer * (int64_t)1000000;
1898         } else
1899             stream_pos = av_gettime() - c->stream->prebuffer * (int64_t)1000;
1900     } else {
1901         strcpy(input_filename, c->stream->feed_filename);
1902         buf_size = 0;
1903         /* compute position (relative time) */
1904         if (find_info_tag(buf, sizeof(buf), "date", info))
1905         {
1906             stream_pos = parse_date(buf, 1);
1907             if (stream_pos == INT64_MIN)
1908                 return -1;
1909         }
1910         else
1911             stream_pos = 0;
1912     }
1913     if (input_filename[0] == '\0')
1914         return -1;
1915
1916 #if 0
1917     { time_t when = stream_pos / 1000000;
1918     http_log("Stream pos = %"PRId64", time=%s", stream_pos, ctime(&when));
1919     }
1920 #endif
1921
1922     /* open stream */
1923     if (av_open_input_file(&s, input_filename, c->stream->ifmt,
1924                            buf_size, c->stream->ap_in) < 0) {
1925         http_log("%s not found", input_filename);
1926         return -1;
1927     }
1928     s->flags |= AVFMT_FLAG_GENPTS;
1929     c->fmt_in = s;
1930     av_find_stream_info(c->fmt_in);
1931
1932     /* open each parser */
1933     for(i=0;i<s->nb_streams;i++)
1934         open_parser(s, i);
1935
1936     /* choose stream as clock source (we favorize video stream if
1937        present) for packet sending */
1938     c->pts_stream_index = 0;
1939     for(i=0;i<c->stream->nb_streams;i++) {
1940         if (c->pts_stream_index == 0 &&
1941             c->stream->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO) {
1942             c->pts_stream_index = i;
1943         }
1944     }
1945
1946 #if 1
1947     if (c->fmt_in->iformat->read_seek)
1948         c->fmt_in->iformat->read_seek(c->fmt_in, 0, stream_pos, 0);
1949 #endif
1950     /* set the start time (needed for maxtime and RTP packet timing) */
1951     c->start_time = cur_time;
1952     c->first_pts = AV_NOPTS_VALUE;
1953     return 0;
1954 }
1955
1956 /* return the server clock (in us) */
1957 static int64_t get_server_clock(HTTPContext *c)
1958 {
1959     /* compute current pts value from system time */
1960     return (cur_time - c->start_time) * 1000;
1961 }
1962
1963 /* return the estimated time at which the current packet must be sent
1964    (in us) */
1965 static int64_t get_packet_send_clock(HTTPContext *c)
1966 {
1967     int bytes_left, bytes_sent, frame_bytes;
1968
1969     frame_bytes = c->cur_frame_bytes;
1970     if (frame_bytes <= 0)
1971         return c->cur_pts;
1972     else {
1973         bytes_left = c->buffer_end - c->buffer_ptr;
1974         bytes_sent = frame_bytes - bytes_left;
1975         return c->cur_pts + (c->cur_frame_duration * bytes_sent) / frame_bytes;
1976     }
1977 }
1978
1979
1980 static int http_prepare_data(HTTPContext *c)
1981 {
1982     int i, len, ret;
1983     AVFormatContext *ctx;
1984
1985     av_freep(&c->pb_buffer);
1986     switch(c->state) {
1987     case HTTPSTATE_SEND_DATA_HEADER:
1988         memset(&c->fmt_ctx, 0, sizeof(c->fmt_ctx));
1989         av_strlcpy(c->fmt_ctx.author, c->stream->author,
1990                    sizeof(c->fmt_ctx.author));
1991         av_strlcpy(c->fmt_ctx.comment, c->stream->comment,
1992                    sizeof(c->fmt_ctx.comment));
1993         av_strlcpy(c->fmt_ctx.copyright, c->stream->copyright,
1994                    sizeof(c->fmt_ctx.copyright));
1995         av_strlcpy(c->fmt_ctx.title, c->stream->title,
1996                    sizeof(c->fmt_ctx.title));
1997
1998         /* open output stream by using specified codecs */
1999         c->fmt_ctx.oformat = c->stream->fmt;
2000         c->fmt_ctx.nb_streams = c->stream->nb_streams;
2001         for(i=0;i<c->fmt_ctx.nb_streams;i++) {
2002             AVStream *st;
2003             AVStream *src;
2004             st = av_mallocz(sizeof(AVStream));
2005             st->codec= avcodec_alloc_context();
2006             c->fmt_ctx.streams[i] = st;
2007             /* if file or feed, then just take streams from FFStream struct */
2008             if (!c->stream->feed ||
2009                 c->stream->feed == c->stream)
2010                 src = c->stream->streams[i];
2011             else
2012                 src = c->stream->feed->streams[c->stream->feed_streams[i]];
2013
2014             *st = *src;
2015             st->priv_data = 0;
2016             st->codec->frame_number = 0; /* XXX: should be done in
2017                                            AVStream, not in codec */
2018             /* I'm pretty sure that this is not correct...
2019              * However, without it, we crash
2020              */
2021             st->codec->coded_frame = &dummy_frame;
2022         }
2023         c->got_key_frame = 0;
2024
2025         /* prepare header and save header data in a stream */
2026         if (url_open_dyn_buf(&c->fmt_ctx.pb) < 0) {
2027             /* XXX: potential leak */
2028             return -1;
2029         }
2030         c->fmt_ctx.pb.is_streamed = 1;
2031
2032         av_set_parameters(&c->fmt_ctx, NULL);
2033         if (av_write_header(&c->fmt_ctx) < 0)
2034             return -1;
2035
2036         len = url_close_dyn_buf(&c->fmt_ctx.pb, &c->pb_buffer);
2037         c->buffer_ptr = c->pb_buffer;
2038         c->buffer_end = c->pb_buffer + len;
2039
2040         c->state = HTTPSTATE_SEND_DATA;
2041         c->last_packet_sent = 0;
2042         break;
2043     case HTTPSTATE_SEND_DATA:
2044         /* find a new packet */
2045         {
2046             AVPacket pkt;
2047
2048             /* read a packet from the input stream */
2049             if (c->stream->feed)
2050                 ffm_set_write_index(c->fmt_in,
2051                                     c->stream->feed->feed_write_index,
2052                                     c->stream->feed->feed_size);
2053
2054             if (c->stream->max_time &&
2055                 c->stream->max_time + c->start_time - cur_time < 0)
2056                 /* We have timed out */
2057                 c->state = HTTPSTATE_SEND_DATA_TRAILER;
2058             else {
2059             redo:
2060                 if (av_read_frame(c->fmt_in, &pkt) < 0) {
2061                     if (c->stream->feed && c->stream->feed->feed_opened) {
2062                         /* if coming from feed, it means we reached the end of the
2063                            ffm file, so must wait for more data */
2064                         c->state = HTTPSTATE_WAIT_FEED;
2065                         return 1; /* state changed */
2066                     } else {
2067                         if (c->stream->loop) {
2068                             av_close_input_file(c->fmt_in);
2069                             c->fmt_in = NULL;
2070                             if (open_input_stream(c, "") < 0)
2071                                 goto no_loop;
2072                             goto redo;
2073                         } else {
2074                         no_loop:
2075                             /* must send trailer now because eof or error */
2076                             c->state = HTTPSTATE_SEND_DATA_TRAILER;
2077                         }
2078                     }
2079                 } else {
2080                     /* update first pts if needed */
2081                     if (c->first_pts == AV_NOPTS_VALUE) {
2082                         c->first_pts = av_rescale_q(pkt.dts, c->fmt_in->streams[pkt.stream_index]->time_base, AV_TIME_BASE_Q);
2083                         c->start_time = cur_time;
2084                     }
2085                     /* send it to the appropriate stream */
2086                     if (c->stream->feed) {
2087                         /* if coming from a feed, select the right stream */
2088                         if (c->switch_pending) {
2089                             c->switch_pending = 0;
2090                             for(i=0;i<c->stream->nb_streams;i++) {
2091                                 if (c->switch_feed_streams[i] == pkt.stream_index)
2092                                     if (pkt.flags & PKT_FLAG_KEY)
2093                                         do_switch_stream(c, i);
2094                                 if (c->switch_feed_streams[i] >= 0)
2095                                     c->switch_pending = 1;
2096                             }
2097                         }
2098                         for(i=0;i<c->stream->nb_streams;i++) {
2099                             if (c->feed_streams[i] == pkt.stream_index) {
2100                                 pkt.stream_index = i;
2101                                 if (pkt.flags & PKT_FLAG_KEY)
2102                                     c->got_key_frame |= 1 << i;
2103                                 /* See if we have all the key frames, then
2104                                  * we start to send. This logic is not quite
2105                                  * right, but it works for the case of a
2106                                  * single video stream with one or more
2107                                  * audio streams (for which every frame is
2108                                  * typically a key frame).
2109                                  */
2110                                 if (!c->stream->send_on_key ||
2111                                     ((c->got_key_frame + 1) >> c->stream->nb_streams))
2112                                     goto send_it;
2113                             }
2114                         }
2115                     } else {
2116                         AVCodecContext *codec;
2117
2118                     send_it:
2119                         /* specific handling for RTP: we use several
2120                            output stream (one for each RTP
2121                            connection). XXX: need more abstract handling */
2122                         if (c->is_packetized) {
2123                             AVStream *st;
2124                             /* compute send time and duration */
2125                             st = c->fmt_in->streams[pkt.stream_index];
2126                             c->cur_pts = av_rescale_q(pkt.dts, st->time_base, AV_TIME_BASE_Q);
2127                             if (st->start_time != AV_NOPTS_VALUE)
2128                                 c->cur_pts -= av_rescale_q(st->start_time, st->time_base, AV_TIME_BASE_Q);
2129                             c->cur_frame_duration = av_rescale_q(pkt.duration, st->time_base, AV_TIME_BASE_Q);
2130 #if 0
2131                             printf("index=%d pts=%0.3f duration=%0.6f\n",
2132                                    pkt.stream_index,
2133                                    (double)c->cur_pts /
2134                                    AV_TIME_BASE,
2135                                    (double)c->cur_frame_duration /
2136                                    AV_TIME_BASE);
2137 #endif
2138                             /* find RTP context */
2139                             c->packet_stream_index = pkt.stream_index;
2140                             ctx = c->rtp_ctx[c->packet_stream_index];
2141                             if(!ctx) {
2142                               av_free_packet(&pkt);
2143                               break;
2144                             }
2145                             codec = ctx->streams[0]->codec;
2146                             /* only one stream per RTP connection */
2147                             pkt.stream_index = 0;
2148                         } else {
2149                             ctx = &c->fmt_ctx;
2150                             /* Fudge here */
2151                             codec = ctx->streams[pkt.stream_index]->codec;
2152                         }
2153
2154                         codec->coded_frame->key_frame = ((pkt.flags & PKT_FLAG_KEY) != 0);
2155                         if (c->is_packetized) {
2156                             int max_packet_size;
2157                             if (c->rtp_protocol == RTSP_PROTOCOL_RTP_TCP)
2158                                 max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
2159                             else
2160                                 max_packet_size = url_get_max_packet_size(c->rtp_handles[c->packet_stream_index]);
2161                             ret = url_open_dyn_packet_buf(&ctx->pb, max_packet_size);
2162                         } else {
2163                             ret = url_open_dyn_buf(&ctx->pb);
2164                         }
2165                         if (ret < 0) {
2166                             /* XXX: potential leak */
2167                             return -1;
2168                         }
2169                         if (pkt.dts != AV_NOPTS_VALUE)
2170                             pkt.dts = av_rescale_q(pkt.dts,
2171                                 c->fmt_in->streams[pkt.stream_index]->time_base,
2172                                 ctx->streams[pkt.stream_index]->time_base);
2173                         if (pkt.pts != AV_NOPTS_VALUE)
2174                             pkt.pts = av_rescale_q(pkt.pts,
2175                                 c->fmt_in->streams[pkt.stream_index]->time_base,
2176                                 ctx->streams[pkt.stream_index]->time_base);
2177                         if (av_write_frame(ctx, &pkt))
2178                             c->state = HTTPSTATE_SEND_DATA_TRAILER;
2179
2180                         len = url_close_dyn_buf(&ctx->pb, &c->pb_buffer);
2181                         c->cur_frame_bytes = len;
2182                         c->buffer_ptr = c->pb_buffer;
2183                         c->buffer_end = c->pb_buffer + len;
2184
2185                         codec->frame_number++;
2186                         if (len == 0)
2187                             goto redo;
2188                     }
2189                     av_free_packet(&pkt);
2190                 }
2191             }
2192         }
2193         break;
2194     default:
2195     case HTTPSTATE_SEND_DATA_TRAILER:
2196         /* last packet test ? */
2197         if (c->last_packet_sent || c->is_packetized)
2198             return -1;
2199         ctx = &c->fmt_ctx;
2200         /* prepare header */
2201         if (url_open_dyn_buf(&ctx->pb) < 0) {
2202             /* XXX: potential leak */
2203             return -1;
2204         }
2205         av_write_trailer(ctx);
2206         len = url_close_dyn_buf(&ctx->pb, &c->pb_buffer);
2207         c->buffer_ptr = c->pb_buffer;
2208         c->buffer_end = c->pb_buffer + len;
2209
2210         c->last_packet_sent = 1;
2211         break;
2212     }
2213     return 0;
2214 }
2215
2216 /* should convert the format at the same time */
2217 /* send data starting at c->buffer_ptr to the output connection
2218    (either UDP or TCP connection) */
2219 static int http_send_data(HTTPContext *c)
2220 {
2221     int len, ret;
2222
2223     for(;;) {
2224         if (c->buffer_ptr >= c->buffer_end) {
2225             ret = http_prepare_data(c);
2226             if (ret < 0)
2227                 return -1;
2228             else if (ret != 0)
2229                 /* state change requested */
2230                 break;
2231         } else {
2232             if (c->is_packetized) {
2233                 /* RTP data output */
2234                 len = c->buffer_end - c->buffer_ptr;
2235                 if (len < 4) {
2236                     /* fail safe - should never happen */
2237                 fail1:
2238                     c->buffer_ptr = c->buffer_end;
2239                     return 0;
2240                 }
2241                 len = (c->buffer_ptr[0] << 24) |
2242                     (c->buffer_ptr[1] << 16) |
2243                     (c->buffer_ptr[2] << 8) |
2244                     (c->buffer_ptr[3]);
2245                 if (len > (c->buffer_end - c->buffer_ptr))
2246                     goto fail1;
2247                 if ((get_packet_send_clock(c) - get_server_clock(c)) > 0) {
2248                     /* nothing to send yet: we can wait */
2249                     return 0;
2250                 }
2251
2252                 c->data_count += len;
2253                 update_datarate(&c->datarate, c->data_count);
2254                 if (c->stream)
2255                     c->stream->bytes_served += len;
2256
2257                 if (c->rtp_protocol == RTSP_PROTOCOL_RTP_TCP) {
2258                     /* RTP packets are sent inside the RTSP TCP connection */
2259                     ByteIOContext pb1, *pb = &pb1;
2260                     int interleaved_index, size;
2261                     uint8_t header[4];
2262                     HTTPContext *rtsp_c;
2263
2264                     rtsp_c = c->rtsp_c;
2265                     /* if no RTSP connection left, error */
2266                     if (!rtsp_c)
2267                         return -1;
2268                     /* if already sending something, then wait. */
2269                     if (rtsp_c->state != RTSPSTATE_WAIT_REQUEST)
2270                         break;
2271                     if (url_open_dyn_buf(pb) < 0)
2272                         goto fail1;
2273                     interleaved_index = c->packet_stream_index * 2;
2274                     /* RTCP packets are sent at odd indexes */
2275                     if (c->buffer_ptr[1] == 200)
2276                         interleaved_index++;
2277                     /* write RTSP TCP header */
2278                     header[0] = '$';
2279                     header[1] = interleaved_index;
2280                     header[2] = len >> 8;
2281                     header[3] = len;
2282                     put_buffer(pb, header, 4);
2283                     /* write RTP packet data */
2284                     c->buffer_ptr += 4;
2285                     put_buffer(pb, c->buffer_ptr, len);
2286                     size = url_close_dyn_buf(pb, &c->packet_buffer);
2287                     /* prepare asynchronous TCP sending */
2288                     rtsp_c->packet_buffer_ptr = c->packet_buffer;
2289                     rtsp_c->packet_buffer_end = c->packet_buffer + size;
2290                     c->buffer_ptr += len;
2291
2292                     /* send everything we can NOW */
2293                     len = send(rtsp_c->fd, rtsp_c->packet_buffer_ptr,
2294                                 rtsp_c->packet_buffer_end - rtsp_c->packet_buffer_ptr, 0);
2295                     if (len > 0)
2296                         rtsp_c->packet_buffer_ptr += len;
2297                     if (rtsp_c->packet_buffer_ptr < rtsp_c->packet_buffer_end) {
2298                         /* if we could not send all the data, we will
2299                            send it later, so a new state is needed to
2300                            "lock" the RTSP TCP connection */
2301                         rtsp_c->state = RTSPSTATE_SEND_PACKET;
2302                         break;
2303                     } else
2304                         /* all data has been sent */
2305                         av_freep(&c->packet_buffer);
2306                 } else {
2307                     /* send RTP packet directly in UDP */
2308                     c->buffer_ptr += 4;
2309                     url_write(c->rtp_handles[c->packet_stream_index],
2310                               c->buffer_ptr, len);
2311                     c->buffer_ptr += len;
2312                     /* here we continue as we can send several packets per 10 ms slot */
2313                 }
2314             } else {
2315                 /* TCP data output */
2316                 len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
2317                 if (len < 0) {
2318                     if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
2319                         ff_neterrno() != FF_NETERROR(EINTR))
2320                         /* error : close connection */
2321                         return -1;
2322                     else
2323                         return 0;
2324                 } else
2325                     c->buffer_ptr += len;
2326
2327                 c->data_count += len;
2328                 update_datarate(&c->datarate, c->data_count);
2329                 if (c->stream)
2330                     c->stream->bytes_served += len;
2331                 break;
2332             }
2333         }
2334     } /* for(;;) */
2335     return 0;
2336 }
2337
2338 static int http_start_receive_data(HTTPContext *c)
2339 {
2340     int fd;
2341
2342     if (c->stream->feed_opened)
2343         return -1;
2344
2345     /* Don't permit writing to this one */
2346     if (c->stream->readonly)
2347         return -1;
2348
2349     /* open feed */
2350     fd = open(c->stream->feed_filename, O_RDWR);
2351     if (fd < 0)
2352         return -1;
2353     c->feed_fd = fd;
2354
2355     c->stream->feed_write_index = ffm_read_write_index(fd);
2356     c->stream->feed_size = lseek(fd, 0, SEEK_END);
2357     lseek(fd, 0, SEEK_SET);
2358
2359     /* init buffer input */
2360     c->buffer_ptr = c->buffer;
2361     c->buffer_end = c->buffer + FFM_PACKET_SIZE;
2362     c->stream->feed_opened = 1;
2363     return 0;
2364 }
2365
2366 static int http_receive_data(HTTPContext *c)
2367 {
2368     HTTPContext *c1;
2369
2370     if (c->buffer_end > c->buffer_ptr) {
2371         int len;
2372
2373         len = recv(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
2374         if (len < 0) {
2375             if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
2376                 ff_neterrno() != FF_NETERROR(EINTR))
2377                 /* error : close connection */
2378                 goto fail;
2379         } else if (len == 0)
2380             /* end of connection : close it */
2381             goto fail;
2382         else {
2383             c->buffer_ptr += len;
2384             c->data_count += len;
2385             update_datarate(&c->datarate, c->data_count);
2386         }
2387     }
2388
2389     if (c->buffer_ptr - c->buffer >= 2 && c->data_count > FFM_PACKET_SIZE) {
2390         if (c->buffer[0] != 'f' ||
2391             c->buffer[1] != 'm') {
2392             http_log("Feed stream has become desynchronized -- disconnecting\n");
2393             goto fail;
2394         }
2395     }
2396
2397     if (c->buffer_ptr >= c->buffer_end) {
2398         FFStream *feed = c->stream;
2399         /* a packet has been received : write it in the store, except
2400            if header */
2401         if (c->data_count > FFM_PACKET_SIZE) {
2402
2403             //            printf("writing pos=0x%"PRIx64" size=0x%"PRIx64"\n", feed->feed_write_index, feed->feed_size);
2404             /* XXX: use llseek or url_seek */
2405             lseek(c->feed_fd, feed->feed_write_index, SEEK_SET);
2406             write(c->feed_fd, c->buffer, FFM_PACKET_SIZE);
2407
2408             feed->feed_write_index += FFM_PACKET_SIZE;
2409             /* update file size */
2410             if (feed->feed_write_index > c->stream->feed_size)
2411                 feed->feed_size = feed->feed_write_index;
2412
2413             /* handle wrap around if max file size reached */
2414             if (c->stream->feed_max_size && feed->feed_write_index >= c->stream->feed_max_size)
2415                 feed->feed_write_index = FFM_PACKET_SIZE;
2416
2417             /* write index */
2418             ffm_write_write_index(c->feed_fd, feed->feed_write_index);
2419
2420             /* wake up any waiting connections */
2421             for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
2422                 if (c1->state == HTTPSTATE_WAIT_FEED &&
2423                     c1->stream->feed == c->stream->feed)
2424                     c1->state = HTTPSTATE_SEND_DATA;
2425             }
2426         } else {
2427             /* We have a header in our hands that contains useful data */
2428             AVFormatContext s;
2429             AVInputFormat *fmt_in;
2430             ByteIOContext *pb = &s.pb;
2431             int i;
2432
2433             memset(&s, 0, sizeof(s));
2434
2435             url_open_buf(pb, c->buffer, c->buffer_end - c->buffer, URL_RDONLY);
2436             pb->buf_end = c->buffer_end;        /* ?? */
2437             pb->is_streamed = 1;
2438
2439             /* use feed output format name to find corresponding input format */
2440             fmt_in = av_find_input_format(feed->fmt->name);
2441             if (!fmt_in)
2442                 goto fail;
2443
2444             if (fmt_in->priv_data_size > 0) {
2445                 s.priv_data = av_mallocz(fmt_in->priv_data_size);
2446                 if (!s.priv_data)
2447                     goto fail;
2448             } else
2449                 s.priv_data = NULL;
2450
2451             if (fmt_in->read_header(&s, 0) < 0) {
2452                 av_freep(&s.priv_data);
2453                 goto fail;
2454             }
2455
2456             /* Now we have the actual streams */
2457             if (s.nb_streams != feed->nb_streams) {
2458                 av_freep(&s.priv_data);
2459                 goto fail;
2460             }
2461             for (i = 0; i < s.nb_streams; i++)
2462                 memcpy(feed->streams[i]->codec,
2463                        s.streams[i]->codec, sizeof(AVCodecContext));
2464             av_freep(&s.priv_data);
2465         }
2466         c->buffer_ptr = c->buffer;
2467     }
2468
2469     return 0;
2470  fail:
2471     c->stream->feed_opened = 0;
2472     close(c->feed_fd);
2473     return -1;
2474 }
2475
2476 /********************************************************************/
2477 /* RTSP handling */
2478
2479 static void rtsp_reply_header(HTTPContext *c, enum RTSPStatusCode error_number)
2480 {
2481     const char *str;
2482     time_t ti;
2483     char *p;
2484     char buf2[32];
2485
2486     switch(error_number) {
2487     case RTSP_STATUS_OK:
2488         str = "OK";
2489         break;
2490     case RTSP_STATUS_METHOD:
2491         str = "Method Not Allowed";
2492         break;
2493     case RTSP_STATUS_BANDWIDTH:
2494         str = "Not Enough Bandwidth";
2495         break;
2496     case RTSP_STATUS_SESSION:
2497         str = "Session Not Found";
2498         break;
2499     case RTSP_STATUS_STATE:
2500         str = "Method Not Valid in This State";
2501         break;
2502     case RTSP_STATUS_AGGREGATE:
2503         str = "Aggregate operation not allowed";
2504         break;
2505     case RTSP_STATUS_ONLY_AGGREGATE:
2506         str = "Only aggregate operation allowed";
2507         break;
2508     case RTSP_STATUS_TRANSPORT:
2509         str = "Unsupported transport";
2510         break;
2511     case RTSP_STATUS_INTERNAL:
2512         str = "Internal Server Error";
2513         break;
2514     case RTSP_STATUS_SERVICE:
2515         str = "Service Unavailable";
2516         break;
2517     case RTSP_STATUS_VERSION:
2518         str = "RTSP Version not supported";
2519         break;
2520     default:
2521         str = "Unknown Error";
2522         break;
2523     }
2524
2525     url_fprintf(c->pb, "RTSP/1.0 %d %s\r\n", error_number, str);
2526     url_fprintf(c->pb, "CSeq: %d\r\n", c->seq);
2527
2528     /* output GMT time */
2529     ti = time(NULL);
2530     p = ctime(&ti);
2531     strcpy(buf2, p);
2532     p = buf2 + strlen(p) - 1;
2533     if (*p == '\n')
2534         *p = '\0';
2535     url_fprintf(c->pb, "Date: %s GMT\r\n", buf2);
2536 }
2537
2538 static void rtsp_reply_error(HTTPContext *c, enum RTSPStatusCode error_number)
2539 {
2540     rtsp_reply_header(c, error_number);
2541     url_fprintf(c->pb, "\r\n");
2542 }
2543
2544 static int rtsp_parse_request(HTTPContext *c)
2545 {
2546     const char *p, *p1, *p2;
2547     char cmd[32];
2548     char url[1024];
2549     char protocol[32];
2550     char line[1024];
2551     ByteIOContext pb1;
2552     int len;
2553     RTSPHeader header1, *header = &header1;
2554
2555     c->buffer_ptr[0] = '\0';
2556     p = c->buffer;
2557
2558     get_word(cmd, sizeof(cmd), &p);
2559     get_word(url, sizeof(url), &p);
2560     get_word(protocol, sizeof(protocol), &p);
2561
2562     av_strlcpy(c->method, cmd, sizeof(c->method));
2563     av_strlcpy(c->url, url, sizeof(c->url));
2564     av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
2565
2566     c->pb = &pb1;
2567     if (url_open_dyn_buf(c->pb) < 0) {
2568         /* XXX: cannot do more */
2569         c->pb = NULL; /* safety */
2570         return -1;
2571     }
2572
2573     /* check version name */
2574     if (strcmp(protocol, "RTSP/1.0") != 0) {
2575         rtsp_reply_error(c, RTSP_STATUS_VERSION);
2576         goto the_end;
2577     }
2578
2579     /* parse each header line */
2580     memset(header, 0, sizeof(RTSPHeader));
2581     /* skip to next line */
2582     while (*p != '\n' && *p != '\0')
2583         p++;
2584     if (*p == '\n')
2585         p++;
2586     while (*p != '\0') {
2587         p1 = strchr(p, '\n');
2588         if (!p1)
2589             break;
2590         p2 = p1;
2591         if (p2 > p && p2[-1] == '\r')
2592             p2--;
2593         /* skip empty line */
2594         if (p2 == p)
2595             break;
2596         len = p2 - p;
2597         if (len > sizeof(line) - 1)
2598             len = sizeof(line) - 1;
2599         memcpy(line, p, len);
2600         line[len] = '\0';
2601         rtsp_parse_line(header, line);
2602         p = p1 + 1;
2603     }
2604
2605     /* handle sequence number */
2606     c->seq = header->seq;
2607
2608     if (!strcmp(cmd, "DESCRIBE"))
2609         rtsp_cmd_describe(c, url);
2610     else if (!strcmp(cmd, "OPTIONS"))
2611         rtsp_cmd_options(c, url);
2612     else if (!strcmp(cmd, "SETUP"))
2613         rtsp_cmd_setup(c, url, header);
2614     else if (!strcmp(cmd, "PLAY"))
2615         rtsp_cmd_play(c, url, header);
2616     else if (!strcmp(cmd, "PAUSE"))
2617         rtsp_cmd_pause(c, url, header);
2618     else if (!strcmp(cmd, "TEARDOWN"))
2619         rtsp_cmd_teardown(c, url, header);
2620     else
2621         rtsp_reply_error(c, RTSP_STATUS_METHOD);
2622
2623  the_end:
2624     len = url_close_dyn_buf(c->pb, &c->pb_buffer);
2625     c->pb = NULL; /* safety */
2626     if (len < 0) {
2627         /* XXX: cannot do more */
2628         return -1;
2629     }
2630     c->buffer_ptr = c->pb_buffer;
2631     c->buffer_end = c->pb_buffer + len;
2632     c->state = RTSPSTATE_SEND_REPLY;
2633     return 0;
2634 }
2635
2636 static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
2637                                    struct in_addr my_ip)
2638 {
2639     AVFormatContext *avc;
2640     AVStream avs[MAX_STREAMS];
2641     int i;
2642
2643     avc =  av_alloc_format_context();
2644     if (avc == NULL) {
2645         return -1;
2646     }
2647     if (stream->title[0] != 0) {
2648         av_strlcpy(avc->title, stream->title, sizeof(avc->title));
2649     } else {
2650         av_strlcpy(avc->title, "No Title", sizeof(avc->title));
2651     }
2652     avc->nb_streams = stream->nb_streams;
2653     if (stream->is_multicast) {
2654         snprintf(avc->filename, 1024, "rtp://%s:%d?multicast=1?ttl=%d",
2655                  inet_ntoa(stream->multicast_ip),
2656                  stream->multicast_port, stream->multicast_ttl);
2657     }
2658
2659     for(i = 0; i < stream->nb_streams; i++) {
2660         avc->streams[i] = &avs[i];
2661         avc->streams[i]->codec = stream->streams[i]->codec;
2662     }
2663     *pbuffer = av_mallocz(2048);
2664     avf_sdp_create(&avc, 1, *pbuffer, 2048);
2665     av_free(avc);
2666
2667     return strlen(*pbuffer);
2668 }
2669
2670 static void rtsp_cmd_options(HTTPContext *c, const char *url)
2671 {
2672 //    rtsp_reply_header(c, RTSP_STATUS_OK);
2673     url_fprintf(c->pb, "RTSP/1.0 %d %s\r\n", RTSP_STATUS_OK, "OK");
2674     url_fprintf(c->pb, "CSeq: %d\r\n", c->seq);
2675     url_fprintf(c->pb, "Public: %s\r\n", "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
2676     url_fprintf(c->pb, "\r\n");
2677 }
2678
2679 static void rtsp_cmd_describe(HTTPContext *c, const char *url)
2680 {
2681     FFStream *stream;
2682     char path1[1024];
2683     const char *path;
2684     uint8_t *content;
2685     int content_length, len;
2686     struct sockaddr_in my_addr;
2687
2688     /* find which url is asked */
2689     url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
2690     path = path1;
2691     if (*path == '/')
2692         path++;
2693
2694     for(stream = first_stream; stream != NULL; stream = stream->next) {
2695         if (!stream->is_feed &&
2696             stream->fmt && !strcmp(stream->fmt->name, "rtp") &&
2697             !strcmp(path, stream->filename)) {
2698             goto found;
2699         }
2700     }
2701     /* no stream found */
2702     rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
2703     return;
2704
2705  found:
2706     /* prepare the media description in sdp format */
2707
2708     /* get the host IP */
2709     len = sizeof(my_addr);
2710     getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
2711     content_length = prepare_sdp_description(stream, &content, my_addr.sin_addr);
2712     if (content_length < 0) {
2713         rtsp_reply_error(c, RTSP_STATUS_INTERNAL);
2714         return;
2715     }
2716     rtsp_reply_header(c, RTSP_STATUS_OK);
2717     url_fprintf(c->pb, "Content-Type: application/sdp\r\n");
2718     url_fprintf(c->pb, "Content-Length: %d\r\n", content_length);
2719     url_fprintf(c->pb, "\r\n");
2720     put_buffer(c->pb, content, content_length);
2721 }
2722
2723 static HTTPContext *find_rtp_session(const char *session_id)
2724 {
2725     HTTPContext *c;
2726
2727     if (session_id[0] == '\0')
2728         return NULL;
2729
2730     for(c = first_http_ctx; c != NULL; c = c->next) {
2731         if (!strcmp(c->session_id, session_id))
2732             return c;
2733     }
2734     return NULL;
2735 }
2736
2737 static RTSPTransportField *find_transport(RTSPHeader *h, enum RTSPProtocol protocol)
2738 {
2739     RTSPTransportField *th;
2740     int i;
2741
2742     for(i=0;i<h->nb_transports;i++) {
2743         th = &h->transports[i];
2744         if (th->protocol == protocol)
2745             return th;
2746     }
2747     return NULL;
2748 }
2749
2750 static void rtsp_cmd_setup(HTTPContext *c, const char *url,
2751                            RTSPHeader *h)
2752 {
2753     FFStream *stream;
2754     int stream_index, port;
2755     char buf[1024];
2756     char path1[1024];
2757     const char *path;
2758     HTTPContext *rtp_c;
2759     RTSPTransportField *th;
2760     struct sockaddr_in dest_addr;
2761     RTSPActionServerSetup setup;
2762
2763     /* find which url is asked */
2764     url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
2765     path = path1;
2766     if (*path == '/')
2767         path++;
2768
2769     /* now check each stream */
2770     for(stream = first_stream; stream != NULL; stream = stream->next) {
2771         if (!stream->is_feed &&
2772             stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
2773             /* accept aggregate filenames only if single stream */
2774             if (!strcmp(path, stream->filename)) {
2775                 if (stream->nb_streams != 1) {
2776                     rtsp_reply_error(c, RTSP_STATUS_AGGREGATE);
2777                     return;
2778                 }
2779                 stream_index = 0;
2780                 goto found;
2781             }
2782
2783             for(stream_index = 0; stream_index < stream->nb_streams;
2784                 stream_index++) {
2785                 snprintf(buf, sizeof(buf), "%s/streamid=%d",
2786                          stream->filename, stream_index);
2787                 if (!strcmp(path, buf))
2788                     goto found;
2789             }
2790         }
2791     }
2792     /* no stream found */
2793     rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
2794     return;
2795  found:
2796
2797     /* generate session id if needed */
2798     if (h->session_id[0] == '\0')
2799         snprintf(h->session_id, sizeof(h->session_id), "%08x%08x",
2800                  av_random(&random_state), av_random(&random_state));
2801
2802     /* find rtp session, and create it if none found */
2803     rtp_c = find_rtp_session(h->session_id);
2804     if (!rtp_c) {
2805         /* always prefer UDP */
2806         th = find_transport(h, RTSP_PROTOCOL_RTP_UDP);
2807         if (!th) {
2808             th = find_transport(h, RTSP_PROTOCOL_RTP_TCP);
2809             if (!th) {
2810                 rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
2811                 return;
2812             }
2813         }
2814
2815         rtp_c = rtp_new_connection(&c->from_addr, stream, h->session_id,
2816                                    th->protocol);
2817         if (!rtp_c) {
2818             rtsp_reply_error(c, RTSP_STATUS_BANDWIDTH);
2819             return;
2820         }
2821
2822         /* open input stream */
2823         if (open_input_stream(rtp_c, "") < 0) {
2824             rtsp_reply_error(c, RTSP_STATUS_INTERNAL);
2825             return;
2826         }
2827     }
2828
2829     /* test if stream is OK (test needed because several SETUP needs
2830        to be done for a given file) */
2831     if (rtp_c->stream != stream) {
2832         rtsp_reply_error(c, RTSP_STATUS_SERVICE);
2833         return;
2834     }
2835
2836     /* test if stream is already set up */
2837     if (rtp_c->rtp_ctx[stream_index]) {
2838         rtsp_reply_error(c, RTSP_STATUS_STATE);
2839         return;
2840     }
2841
2842     /* check transport */
2843     th = find_transport(h, rtp_c->rtp_protocol);
2844     if (!th || (th->protocol == RTSP_PROTOCOL_RTP_UDP &&
2845                 th->client_port_min <= 0)) {
2846         rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
2847         return;
2848     }
2849
2850     /* setup default options */
2851     setup.transport_option[0] = '\0';
2852     dest_addr = rtp_c->from_addr;
2853     dest_addr.sin_port = htons(th->client_port_min);
2854
2855     /* setup stream */
2856     if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, c) < 0) {
2857         rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
2858         return;
2859     }
2860
2861     /* now everything is OK, so we can send the connection parameters */
2862     rtsp_reply_header(c, RTSP_STATUS_OK);
2863     /* session ID */
2864     url_fprintf(c->pb, "Session: %s\r\n", rtp_c->session_id);
2865
2866     switch(rtp_c->rtp_protocol) {
2867     case RTSP_PROTOCOL_RTP_UDP:
2868         port = rtp_get_local_port(rtp_c->rtp_handles[stream_index]);
2869         url_fprintf(c->pb, "Transport: RTP/AVP/UDP;unicast;"
2870                     "client_port=%d-%d;server_port=%d-%d",
2871                     th->client_port_min, th->client_port_min + 1,
2872                     port, port + 1);
2873         break;
2874     case RTSP_PROTOCOL_RTP_TCP:
2875         url_fprintf(c->pb, "Transport: RTP/AVP/TCP;interleaved=%d-%d",
2876                     stream_index * 2, stream_index * 2 + 1);
2877         break;
2878     default:
2879         break;
2880     }
2881     if (setup.transport_option[0] != '\0')
2882         url_fprintf(c->pb, ";%s", setup.transport_option);
2883     url_fprintf(c->pb, "\r\n");
2884
2885
2886     url_fprintf(c->pb, "\r\n");
2887 }
2888
2889
2890 /* find an rtp connection by using the session ID. Check consistency
2891    with filename */
2892 static HTTPContext *find_rtp_session_with_url(const char *url,
2893                                               const char *session_id)
2894 {
2895     HTTPContext *rtp_c;
2896     char path1[1024];
2897     const char *path;
2898     char buf[1024];
2899     int s;
2900
2901     rtp_c = find_rtp_session(session_id);
2902     if (!rtp_c)
2903         return NULL;
2904
2905     /* find which url is asked */
2906     url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
2907     path = path1;
2908     if (*path == '/')
2909         path++;
2910     if(!strcmp(path, rtp_c->stream->filename)) return rtp_c;
2911     for(s=0; s<rtp_c->stream->nb_streams; ++s) {
2912       snprintf(buf, sizeof(buf), "%s/streamid=%d",
2913         rtp_c->stream->filename, s);
2914       if(!strncmp(path, buf, sizeof(buf))) {
2915     // XXX: Should we reply with RTSP_STATUS_ONLY_AGGREGATE if nb_streams>1?
2916         return rtp_c;
2917       }
2918     }
2919     return NULL;
2920 }
2921
2922 static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPHeader *h)
2923 {
2924     HTTPContext *rtp_c;
2925
2926     rtp_c = find_rtp_session_with_url(url, h->session_id);
2927     if (!rtp_c) {
2928         rtsp_reply_error(c, RTSP_STATUS_SESSION);
2929         return;
2930     }
2931
2932     if (rtp_c->state != HTTPSTATE_SEND_DATA &&
2933         rtp_c->state != HTTPSTATE_WAIT_FEED &&
2934         rtp_c->state != HTTPSTATE_READY) {
2935         rtsp_reply_error(c, RTSP_STATUS_STATE);
2936         return;
2937     }
2938
2939 #if 0
2940     /* XXX: seek in stream */
2941     if (h->range_start != AV_NOPTS_VALUE) {
2942         printf("range_start=%0.3f\n", (double)h->range_start / AV_TIME_BASE);
2943         av_seek_frame(rtp_c->fmt_in, -1, h->range_start);
2944     }
2945 #endif
2946
2947     rtp_c->state = HTTPSTATE_SEND_DATA;
2948
2949     /* now everything is OK, so we can send the connection parameters */
2950     rtsp_reply_header(c, RTSP_STATUS_OK);
2951     /* session ID */
2952     url_fprintf(c->pb, "Session: %s\r\n", rtp_c->session_id);
2953     url_fprintf(c->pb, "\r\n");
2954 }
2955
2956 static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPHeader *h)
2957 {
2958     HTTPContext *rtp_c;
2959
2960     rtp_c = find_rtp_session_with_url(url, h->session_id);
2961     if (!rtp_c) {
2962         rtsp_reply_error(c, RTSP_STATUS_SESSION);
2963         return;
2964     }
2965
2966     if (rtp_c->state != HTTPSTATE_SEND_DATA &&
2967         rtp_c->state != HTTPSTATE_WAIT_FEED) {
2968         rtsp_reply_error(c, RTSP_STATUS_STATE);
2969         return;
2970     }
2971
2972     rtp_c->state = HTTPSTATE_READY;
2973     rtp_c->first_pts = AV_NOPTS_VALUE;
2974     /* now everything is OK, so we can send the connection parameters */
2975     rtsp_reply_header(c, RTSP_STATUS_OK);
2976     /* session ID */
2977     url_fprintf(c->pb, "Session: %s\r\n", rtp_c->session_id);
2978     url_fprintf(c->pb, "\r\n");
2979 }
2980
2981 static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPHeader *h)
2982 {
2983     HTTPContext *rtp_c;
2984     char session_id[32];
2985
2986     rtp_c = find_rtp_session_with_url(url, h->session_id);
2987     if (!rtp_c) {
2988         rtsp_reply_error(c, RTSP_STATUS_SESSION);
2989         return;
2990     }
2991
2992     av_strlcpy(session_id, rtp_c->session_id, sizeof(session_id));
2993
2994     /* abort the session */
2995     close_connection(rtp_c);
2996
2997     /* now everything is OK, so we can send the connection parameters */
2998     rtsp_reply_header(c, RTSP_STATUS_OK);
2999     /* session ID */
3000     url_fprintf(c->pb, "Session: %s\r\n", session_id);
3001     url_fprintf(c->pb, "\r\n");
3002 }
3003
3004
3005 /********************************************************************/
3006 /* RTP handling */
3007
3008 static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
3009                                        FFStream *stream, const char *session_id,
3010                                        enum RTSPProtocol rtp_protocol)
3011 {
3012     HTTPContext *c = NULL;
3013     const char *proto_str;
3014
3015     /* XXX: should output a warning page when coming
3016        close to the connection limit */
3017     if (nb_connections >= nb_max_connections)
3018         goto fail;
3019
3020     /* add a new connection */
3021     c = av_mallocz(sizeof(HTTPContext));
3022     if (!c)
3023         goto fail;
3024
3025     c->fd = -1;
3026     c->poll_entry = NULL;
3027     c->from_addr = *from_addr;
3028     c->buffer_size = IOBUFFER_INIT_SIZE;
3029     c->buffer = av_malloc(c->buffer_size);
3030     if (!c->buffer)
3031         goto fail;
3032     nb_connections++;
3033     c->stream = stream;
3034     av_strlcpy(c->session_id, session_id, sizeof(c->session_id));
3035     c->state = HTTPSTATE_READY;
3036     c->is_packetized = 1;
3037     c->rtp_protocol = rtp_protocol;
3038
3039     /* protocol is shown in statistics */
3040     switch(c->rtp_protocol) {
3041     case RTSP_PROTOCOL_RTP_UDP_MULTICAST:
3042         proto_str = "MCAST";
3043         break;
3044     case RTSP_PROTOCOL_RTP_UDP:
3045         proto_str = "UDP";
3046         break;
3047     case RTSP_PROTOCOL_RTP_TCP:
3048         proto_str = "TCP";
3049         break;
3050     default:
3051         proto_str = "???";
3052         break;
3053     }
3054     av_strlcpy(c->protocol, "RTP/", sizeof(c->protocol));
3055     av_strlcat(c->protocol, proto_str, sizeof(c->protocol));
3056
3057     current_bandwidth += stream->bandwidth;
3058
3059     c->next = first_http_ctx;
3060     first_http_ctx = c;
3061     return c;
3062
3063  fail:
3064     if (c) {
3065         av_free(c->buffer);
3066         av_free(c);
3067     }
3068     return NULL;
3069 }
3070
3071 /* add a new RTP stream in an RTP connection (used in RTSP SETUP
3072    command). If RTP/TCP protocol is used, TCP connection 'rtsp_c' is
3073    used. */
3074 static int rtp_new_av_stream(HTTPContext *c,
3075                              int stream_index, struct sockaddr_in *dest_addr,
3076                              HTTPContext *rtsp_c)
3077 {
3078     AVFormatContext *ctx;
3079     AVStream *st;
3080     char *ipaddr;
3081     URLContext *h;
3082     uint8_t *dummy_buf;
3083     char buf2[32];
3084     int max_packet_size;
3085
3086     /* now we can open the relevant output stream */
3087     ctx = av_alloc_format_context();
3088     if (!ctx)
3089         return -1;
3090     ctx->oformat = guess_format("rtp", NULL, NULL);
3091
3092     st = av_mallocz(sizeof(AVStream));
3093     if (!st)
3094         goto fail;
3095     st->codec= avcodec_alloc_context();
3096     ctx->nb_streams = 1;
3097     ctx->streams[0] = st;
3098
3099     if (!c->stream->feed ||
3100         c->stream->feed == c->stream)
3101         memcpy(st, c->stream->streams[stream_index], sizeof(AVStream));
3102     else
3103         memcpy(st,
3104                c->stream->feed->streams[c->stream->feed_streams[stream_index]],
3105                sizeof(AVStream));
3106     st->priv_data = NULL;
3107
3108     /* build destination RTP address */
3109     ipaddr = inet_ntoa(dest_addr->sin_addr);
3110
3111     switch(c->rtp_protocol) {
3112     case RTSP_PROTOCOL_RTP_UDP:
3113     case RTSP_PROTOCOL_RTP_UDP_MULTICAST:
3114         /* RTP/UDP case */
3115
3116         /* XXX: also pass as parameter to function ? */
3117         if (c->stream->is_multicast) {
3118             int ttl;
3119             ttl = c->stream->multicast_ttl;
3120             if (!ttl)
3121                 ttl = 16;
3122             snprintf(ctx->filename, sizeof(ctx->filename),
3123                      "rtp://%s:%d?multicast=1&ttl=%d",
3124                      ipaddr, ntohs(dest_addr->sin_port), ttl);
3125         } else {
3126             snprintf(ctx->filename, sizeof(ctx->filename),
3127                      "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
3128         }
3129
3130         if (url_open(&h, ctx->filename, URL_WRONLY) < 0)
3131             goto fail;
3132         c->rtp_handles[stream_index] = h;
3133         max_packet_size = url_get_max_packet_size(h);
3134         break;
3135     case RTSP_PROTOCOL_RTP_TCP:
3136         /* RTP/TCP case */
3137         c->rtsp_c = rtsp_c;
3138         max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
3139         break;
3140     default:
3141         goto fail;
3142     }
3143
3144     http_log("%s:%d - - [%s] \"PLAY %s/streamid=%d %s\"\n",
3145              ipaddr, ntohs(dest_addr->sin_port),
3146              ctime1(buf2),
3147              c->stream->filename, stream_index, c->protocol);
3148
3149     /* normally, no packets should be output here, but the packet size may be checked */
3150     if (url_open_dyn_packet_buf(&ctx->pb, max_packet_size) < 0) {
3151         /* XXX: close stream */
3152         goto fail;
3153     }
3154     av_set_parameters(ctx, NULL);
3155     if (av_write_header(ctx) < 0) {
3156     fail:
3157         if (h)
3158             url_close(h);
3159         av_free(ctx);
3160         return -1;
3161     }
3162     url_close_dyn_buf(&ctx->pb, &dummy_buf);
3163     av_free(dummy_buf);
3164
3165     c->rtp_ctx[stream_index] = ctx;
3166     return 0;
3167 }
3168
3169 /********************************************************************/
3170 /* ffserver initialization */
3171
3172 static AVStream *add_av_stream1(FFStream *stream, AVCodecContext *codec)
3173 {
3174     AVStream *fst;
3175
3176     fst = av_mallocz(sizeof(AVStream));
3177     if (!fst)
3178         return NULL;
3179     fst->codec= avcodec_alloc_context();
3180     fst->priv_data = av_mallocz(sizeof(FeedData));
3181     memcpy(fst->codec, codec, sizeof(AVCodecContext));
3182     fst->codec->coded_frame = &dummy_frame;
3183     fst->index = stream->nb_streams;
3184     av_set_pts_info(fst, 33, 1, 90000);
3185     stream->streams[stream->nb_streams++] = fst;
3186     return fst;
3187 }
3188
3189 /* return the stream number in the feed */
3190 static int add_av_stream(FFStream *feed, AVStream *st)
3191 {
3192     AVStream *fst;
3193     AVCodecContext *av, *av1;
3194     int i;
3195
3196     av = st->codec;
3197     for(i=0;i<feed->nb_streams;i++) {
3198         st = feed->streams[i];
3199         av1 = st->codec;
3200         if (av1->codec_id == av->codec_id &&
3201             av1->codec_type == av->codec_type &&
3202             av1->bit_rate == av->bit_rate) {
3203
3204             switch(av->codec_type) {
3205             case CODEC_TYPE_AUDIO:
3206                 if (av1->channels == av->channels &&
3207                     av1->sample_rate == av->sample_rate)
3208                     goto found;
3209                 break;
3210             case CODEC_TYPE_VIDEO:
3211                 if (av1->width == av->width &&
3212                     av1->height == av->height &&
3213                     av1->time_base.den == av->time_base.den &&
3214                     av1->time_base.num == av->time_base.num &&
3215                     av1->gop_size == av->gop_size)
3216                     goto found;
3217                 break;
3218             default:
3219                 abort();
3220             }
3221         }
3222     }
3223
3224     fst = add_av_stream1(feed, av);
3225     if (!fst)
3226         return -1;
3227     return feed->nb_streams - 1;
3228  found:
3229     return i;
3230 }
3231
3232 static void remove_stream(FFStream *stream)
3233 {
3234     FFStream **ps;
3235     ps = &first_stream;
3236     while (*ps != NULL) {
3237         if (*ps == stream)
3238             *ps = (*ps)->next;
3239         else
3240             ps = &(*ps)->next;
3241     }
3242 }
3243
3244 /* specific mpeg4 handling : we extract the raw parameters */
3245 static void extract_mpeg4_header(AVFormatContext *infile)
3246 {
3247     int mpeg4_count, i, size;
3248     AVPacket pkt;
3249     AVStream *st;
3250     const uint8_t *p;
3251
3252     mpeg4_count = 0;
3253     for(i=0;i<infile->nb_streams;i++) {
3254         st = infile->streams[i];
3255         if (st->codec->codec_id == CODEC_ID_MPEG4 &&
3256             st->codec->extradata_size == 0) {
3257             mpeg4_count++;
3258         }
3259     }
3260     if (!mpeg4_count)
3261         return;
3262
3263     printf("MPEG4 without extra data: trying to find header in %s\n", infile->filename);
3264     while (mpeg4_count > 0) {
3265         if (av_read_packet(infile, &pkt) < 0)
3266             break;
3267         st = infile->streams[pkt.stream_index];
3268         if (st->codec->codec_id == CODEC_ID_MPEG4 &&
3269             st->codec->extradata_size == 0) {
3270             av_freep(&st->codec->extradata);
3271             /* fill extradata with the header */
3272             /* XXX: we make hard suppositions here ! */
3273             p = pkt.data;
3274             while (p < pkt.data + pkt.size - 4) {
3275                 /* stop when vop header is found */
3276                 if (p[0] == 0x00 && p[1] == 0x00 &&
3277                     p[2] == 0x01 && p[3] == 0xb6) {
3278                     size = p - pkt.data;
3279                     //                    av_hex_dump_log(infile, AV_LOG_DEBUG, pkt.data, size);
3280                     st->codec->extradata = av_malloc(size);
3281                     st->codec->extradata_size = size;
3282                     memcpy(st->codec->extradata, pkt.data, size);
3283                     break;
3284                 }
3285                 p++;
3286             }
3287             mpeg4_count--;
3288         }
3289         av_free_packet(&pkt);
3290     }
3291 }
3292
3293 /* compute the needed AVStream for each file */
3294 static void build_file_streams(void)
3295 {
3296     FFStream *stream, *stream_next;
3297     AVFormatContext *infile;
3298     int i;
3299
3300     /* gather all streams */
3301     for(stream = first_stream; stream != NULL; stream = stream_next) {
3302         stream_next = stream->next;
3303         if (stream->stream_type == STREAM_TYPE_LIVE &&
3304             !stream->feed) {
3305             /* the stream comes from a file */
3306             /* try to open the file */
3307             /* open stream */
3308             stream->ap_in = av_mallocz(sizeof(AVFormatParameters));
3309             if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
3310                 /* specific case : if transport stream output to RTP,
3311                    we use a raw transport stream reader */
3312                 stream->ap_in->mpeg2ts_raw = 1;
3313                 stream->ap_in->mpeg2ts_compute_pcr = 1;
3314             }
3315
3316             if (av_open_input_file(&infile, stream->feed_filename,
3317                                    stream->ifmt, 0, stream->ap_in) < 0) {
3318                 http_log("%s not found", stream->feed_filename);
3319                 /* remove stream (no need to spend more time on it) */
3320             fail:
3321                 remove_stream(stream);
3322             } else {
3323                 /* find all the AVStreams inside and reference them in
3324                    'stream' */
3325                 if (av_find_stream_info(infile) < 0) {
3326                     http_log("Could not find codec parameters from '%s'",
3327                              stream->feed_filename);
3328                     av_close_input_file(infile);
3329                     goto fail;
3330                 }
3331                 extract_mpeg4_header(infile);
3332
3333                 for(i=0;i<infile->nb_streams;i++)
3334                     add_av_stream1(stream, infile->streams[i]->codec);
3335
3336                 av_close_input_file(infile);
3337             }
3338         }
3339     }
3340 }
3341
3342 /* compute the needed AVStream for each feed */
3343 static void build_feed_streams(void)
3344 {
3345     FFStream *stream, *feed;
3346     int i;
3347
3348     /* gather all streams */
3349     for(stream = first_stream; stream != NULL; stream = stream->next) {
3350         feed = stream->feed;
3351         if (feed) {
3352             if (!stream->is_feed) {
3353                 /* we handle a stream coming from a feed */
3354                 for(i=0;i<stream->nb_streams;i++)
3355                     stream->feed_streams[i] = add_av_stream(feed, stream->streams[i]);
3356             }
3357         }
3358     }
3359
3360     /* gather all streams */
3361     for(stream = first_stream; stream != NULL; stream = stream->next) {
3362         feed = stream->feed;
3363         if (feed) {
3364             if (stream->is_feed) {
3365                 for(i=0;i<stream->nb_streams;i++)
3366                     stream->feed_streams[i] = i;
3367             }
3368         }
3369     }
3370
3371     /* create feed files if needed */
3372     for(feed = first_feed; feed != NULL; feed = feed->next_feed) {
3373         int fd;
3374
3375         if (url_exist(feed->feed_filename)) {
3376             /* See if it matches */
3377             AVFormatContext *s;
3378             int matches = 0;
3379
3380             if (av_open_input_file(&s, feed->feed_filename, NULL, FFM_PACKET_SIZE, NULL) >= 0) {
3381                 /* Now see if it matches */
3382                 if (s->nb_streams == feed->nb_streams) {
3383                     matches = 1;
3384                     for(i=0;i<s->nb_streams;i++) {
3385                         AVStream *sf, *ss;
3386                         sf = feed->streams[i];
3387                         ss = s->streams[i];
3388
3389                         if (sf->index != ss->index ||
3390                             sf->id != ss->id) {
3391                             printf("Index & Id do not match for stream %d (%s)\n",
3392                                    i, feed->feed_filename);
3393                             matches = 0;
3394                         } else {
3395                             AVCodecContext *ccf, *ccs;
3396
3397                             ccf = sf->codec;
3398                             ccs = ss->codec;
3399 #define CHECK_CODEC(x)  (ccf->x != ccs->x)
3400
3401                             if (CHECK_CODEC(codec) || CHECK_CODEC(codec_type)) {
3402                                 printf("Codecs do not match for stream %d\n", i);
3403                                 matches = 0;
3404                             } else if (CHECK_CODEC(bit_rate) || CHECK_CODEC(flags)) {
3405                                 printf("Codec bitrates do not match for stream %d\n", i);
3406                                 matches = 0;
3407                             } else if (ccf->codec_type == CODEC_TYPE_VIDEO) {
3408                                 if (CHECK_CODEC(time_base.den) ||
3409                                     CHECK_CODEC(time_base.num) ||
3410                                     CHECK_CODEC(width) ||
3411                                     CHECK_CODEC(height)) {
3412                                     printf("Codec width, height and framerate do not match for stream %d\n", i);
3413                                     matches = 0;
3414                                 }
3415                             } else if (ccf->codec_type == CODEC_TYPE_AUDIO) {
3416                                 if (CHECK_CODEC(sample_rate) ||
3417                                     CHECK_CODEC(channels) ||
3418                                     CHECK_CODEC(frame_size)) {
3419                                     printf("Codec sample_rate, channels, frame_size do not match for stream %d\n", i);
3420                                     matches = 0;
3421                                 }
3422                             } else {
3423                                 printf("Unknown codec type\n");
3424                                 matches = 0;
3425                             }
3426                         }
3427                         if (!matches)
3428                             break;
3429                     }
3430                 } else
3431                     printf("Deleting feed file '%s' as stream counts differ (%d != %d)\n",
3432                         feed->feed_filename, s->nb_streams, feed->nb_streams);
3433
3434                 av_close_input_file(s);
3435             } else
3436                 printf("Deleting feed file '%s' as it appears to be corrupt\n",
3437                         feed->feed_filename);
3438
3439             if (!matches) {
3440                 if (feed->readonly) {
3441                     printf("Unable to delete feed file '%s' as it is marked readonly\n",
3442                         feed->feed_filename);
3443                     exit(1);
3444                 }
3445                 unlink(feed->feed_filename);
3446             }
3447         }
3448         if (!url_exist(feed->feed_filename)) {
3449             AVFormatContext s1, *s = &s1;
3450
3451             if (feed->readonly) {
3452                 printf("Unable to create feed file '%s' as it is marked readonly\n",
3453                     feed->feed_filename);
3454                 exit(1);
3455             }
3456
3457             /* only write the header of the ffm file */
3458             if (url_fopen(&s->pb, feed->feed_filename, URL_WRONLY) < 0) {
3459                 fprintf(stderr, "Could not open output feed file '%s'\n",
3460                         feed->feed_filename);
3461                 exit(1);
3462             }
3463             s->oformat = feed->fmt;
3464             s->nb_streams = feed->nb_streams;
3465             for(i=0;i<s->nb_streams;i++) {
3466                 AVStream *st;
3467                 st = feed->streams[i];
3468                 s->streams[i] = st;
3469             }
3470             av_set_parameters(s, NULL);
3471             if (av_write_header(s) < 0) {
3472                 fprintf(stderr, "Container doesn't supports the required parameters\n");
3473                 exit(1);
3474             }
3475             /* XXX: need better api */
3476             av_freep(&s->priv_data);
3477             url_fclose(&s->pb);
3478         }
3479         /* get feed size and write index */
3480         fd = open(feed->feed_filename, O_RDONLY);
3481         if (fd < 0) {
3482             fprintf(stderr, "Could not open output feed file '%s'\n",
3483                     feed->feed_filename);
3484             exit(1);
3485         }
3486
3487         feed->feed_write_index = ffm_read_write_index(fd);
3488         feed->feed_size = lseek(fd, 0, SEEK_END);
3489         /* ensure that we do not wrap before the end of file */
3490         if (feed->feed_max_size && feed->feed_max_size < feed->feed_size)
3491             feed->feed_max_size = feed->feed_size;
3492
3493         close(fd);
3494     }
3495 }
3496
3497 /* compute the bandwidth used by each stream */
3498 static void compute_bandwidth(void)
3499 {
3500     int bandwidth, i;
3501     FFStream *stream;
3502
3503     for(stream = first_stream; stream != NULL; stream = stream->next) {
3504         bandwidth = 0;
3505         for(i=0;i<stream->nb_streams;i++) {
3506             AVStream *st = stream->streams[i];
3507             switch(st->codec->codec_type) {
3508             case CODEC_TYPE_AUDIO:
3509             case CODEC_TYPE_VIDEO:
3510                 bandwidth += st->codec->bit_rate;
3511                 break;
3512             default:
3513                 break;
3514             }
3515         }
3516         stream->bandwidth = (bandwidth + 999) / 1000;
3517     }
3518 }
3519
3520 static void get_arg(char *buf, int buf_size, const char **pp)
3521 {
3522     const char *p;
3523     char *q;
3524     int quote;
3525
3526     p = *pp;
3527     while (isspace(*p)) p++;
3528     q = buf;
3529     quote = 0;
3530     if (*p == '\"' || *p == '\'')
3531         quote = *p++;
3532     for(;;) {
3533         if (quote) {
3534             if (*p == quote)
3535                 break;
3536         } else {
3537             if (isspace(*p))
3538                 break;
3539         }
3540         if (*p == '\0')
3541             break;
3542         if ((q - buf) < buf_size - 1)
3543             *q++ = *p;
3544         p++;
3545     }
3546     *q = '\0';
3547     if (quote && *p == quote)
3548         p++;
3549     *pp = p;
3550 }
3551
3552 /* add a codec and set the default parameters */
3553 static void add_codec(FFStream *stream, AVCodecContext *av)
3554 {
3555     AVStream *st;
3556
3557     /* compute default parameters */
3558     switch(av->codec_type) {
3559     case CODEC_TYPE_AUDIO:
3560         if (av->bit_rate == 0)
3561             av->bit_rate = 64000;
3562         if (av->sample_rate == 0)
3563             av->sample_rate = 22050;
3564         if (av->channels == 0)
3565             av->channels = 1;
3566         break;
3567     case CODEC_TYPE_VIDEO:
3568         if (av->bit_rate == 0)
3569             av->bit_rate = 64000;
3570         if (av->time_base.num == 0){
3571             av->time_base.den = 5;
3572             av->time_base.num = 1;
3573         }
3574         if (av->width == 0 || av->height == 0) {
3575             av->width = 160;
3576             av->height = 128;
3577         }
3578         /* Bitrate tolerance is less for streaming */
3579         if (av->bit_rate_tolerance == 0)
3580             av->bit_rate_tolerance = av->bit_rate / 4;
3581         if (av->qmin == 0)
3582             av->qmin = 3;
3583         if (av->qmax == 0)
3584             av->qmax = 31;
3585         if (av->max_qdiff == 0)
3586             av->max_qdiff = 3;
3587         av->qcompress = 0.5;
3588         av->qblur = 0.5;
3589
3590         if (!av->nsse_weight)
3591             av->nsse_weight = 8;
3592
3593         av->frame_skip_cmp = FF_CMP_DCTMAX;
3594         av->me_method = ME_EPZS;
3595         av->rc_buffer_aggressivity = 1.0;
3596
3597         if (!av->rc_eq)
3598             av->rc_eq = "tex^qComp";
3599         if (!av->i_quant_factor)
3600             av->i_quant_factor = -0.8;
3601         if (!av->b_quant_factor)
3602             av->b_quant_factor = 1.25;
3603         if (!av->b_quant_offset)
3604             av->b_quant_offset = 1.25;
3605         if (!av->rc_max_rate)
3606             av->rc_max_rate = av->bit_rate * 2;
3607
3608         if (av->rc_max_rate && !av->rc_buffer_size) {
3609             av->rc_buffer_size = av->rc_max_rate;
3610         }
3611
3612
3613         break;
3614     default:
3615         abort();
3616     }
3617
3618     st = av_mallocz(sizeof(AVStream));
3619     if (!st)
3620         return;
3621     st->codec = avcodec_alloc_context();
3622     stream->streams[stream->nb_streams++] = st;
3623     memcpy(st->codec, av, sizeof(AVCodecContext));
3624 }
3625
3626 static int opt_audio_codec(const char *arg)
3627 {
3628     AVCodec *p;
3629
3630     p = first_avcodec;
3631     while (p) {
3632         if (!strcmp(p->name, arg) && p->type == CODEC_TYPE_AUDIO)
3633             break;
3634         p = p->next;
3635     }
3636     if (p == NULL)
3637         return CODEC_ID_NONE;
3638
3639     return p->id;
3640 }
3641
3642 static int opt_video_codec(const char *arg)
3643 {
3644     AVCodec *p;
3645
3646     p = first_avcodec;
3647     while (p) {
3648         if (!strcmp(p->name, arg) && p->type == CODEC_TYPE_VIDEO)
3649             break;
3650         p = p->next;
3651     }
3652     if (p == NULL)
3653         return CODEC_ID_NONE;
3654
3655     return p->id;
3656 }
3657
3658 /* simplistic plugin support */
3659
3660 #ifdef HAVE_DLOPEN
3661 static void load_module(const char *filename)
3662 {
3663     void *dll;
3664     void (*init_func)(void);
3665     dll = dlopen(filename, RTLD_NOW);
3666     if (!dll) {
3667         fprintf(stderr, "Could not load module '%s' - %s\n",
3668                 filename, dlerror());
3669         return;
3670     }
3671
3672     init_func = dlsym(dll, "ffserver_module_init");
3673     if (!init_func) {
3674         fprintf(stderr,
3675                 "%s: init function 'ffserver_module_init()' not found\n",
3676                 filename);
3677         dlclose(dll);
3678     }
3679
3680     init_func();
3681 }
3682 #endif
3683
3684 static int parse_ffconfig(const char *filename)
3685 {
3686     FILE *f;
3687     char line[1024];
3688     char cmd[64];
3689     char arg[1024];
3690     const char *p;
3691     int val, errors, line_num;
3692     FFStream **last_stream, *stream, *redirect;
3693     FFStream **last_feed, *feed;
3694     AVCodecContext audio_enc, video_enc;
3695     int audio_id, video_id;
3696
3697     f = fopen(filename, "r");
3698     if (!f) {
3699         perror(filename);
3700         return -1;
3701     }
3702
3703     errors = 0;
3704     line_num = 0;
3705     first_stream = NULL;
3706     last_stream = &first_stream;
3707     first_feed = NULL;
3708     last_feed = &first_feed;
3709     stream = NULL;
3710     feed = NULL;
3711     redirect = NULL;
3712     audio_id = CODEC_ID_NONE;
3713     video_id = CODEC_ID_NONE;
3714     for(;;) {
3715         if (fgets(line, sizeof(line), f) == NULL)
3716             break;
3717         line_num++;
3718         p = line;
3719         while (isspace(*p))
3720             p++;
3721         if (*p == '\0' || *p == '#')
3722             continue;
3723
3724         get_arg(cmd, sizeof(cmd), &p);
3725
3726         if (!strcasecmp(cmd, "Port")) {
3727             get_arg(arg, sizeof(arg), &p);
3728             val = atoi(arg);
3729             if (val < 1 || val > 65536) {
3730                 fprintf(stderr, "%s:%d: Invalid port: %s\n",
3731                         filename, line_num, arg);
3732                 errors++;
3733             }
3734             my_http_addr.sin_port = htons(val);
3735         } else if (!strcasecmp(cmd, "BindAddress")) {
3736             get_arg(arg, sizeof(arg), &p);
3737             if (resolve_host(&my_http_addr.sin_addr, arg) != 0) {
3738                 fprintf(stderr, "%s:%d: Invalid host/IP address: %s\n",
3739                         filename, line_num, arg);
3740                 errors++;
3741             }
3742         } else if (!strcasecmp(cmd, "NoDaemon")) {
3743             ffserver_daemon = 0;
3744         } else if (!strcasecmp(cmd, "RTSPPort")) {
3745             get_arg(arg, sizeof(arg), &p);
3746             val = atoi(arg);
3747             if (val < 1 || val > 65536) {
3748                 fprintf(stderr, "%s:%d: Invalid port: %s\n",
3749                         filename, line_num, arg);
3750                 errors++;
3751             }
3752             my_rtsp_addr.sin_port = htons(atoi(arg));
3753         } else if (!strcasecmp(cmd, "RTSPBindAddress")) {
3754             get_arg(arg, sizeof(arg), &p);
3755             if (resolve_host(&my_rtsp_addr.sin_addr, arg) != 0) {
3756                 fprintf(stderr, "%s:%d: Invalid host/IP address: %s\n",
3757                         filename, line_num, arg);
3758                 errors++;
3759             }
3760         } else if (!strcasecmp(cmd, "MaxClients")) {
3761             get_arg(arg, sizeof(arg), &p);
3762             val = atoi(arg);
3763             if (val < 1 || val > HTTP_MAX_CONNECTIONS) {
3764                 fprintf(stderr, "%s:%d: Invalid MaxClients: %s\n",
3765                         filename, line_num, arg);
3766                 errors++;
3767             } else {
3768                 nb_max_connections = val;
3769             }
3770         } else if (!strcasecmp(cmd, "MaxBandwidth")) {
3771             get_arg(arg, sizeof(arg), &p);
3772             val = atoi(arg);
3773             if (val < 10 || val > 100000) {
3774                 fprintf(stderr, "%s:%d: Invalid MaxBandwidth: %s\n",
3775                         filename, line_num, arg);
3776                 errors++;
3777             } else
3778                 max_bandwidth = val;
3779         } else if (!strcasecmp(cmd, "CustomLog")) {
3780             get_arg(logfilename, sizeof(logfilename), &p);
3781         } else if (!strcasecmp(cmd, "<Feed")) {
3782             /*********************************************/
3783             /* Feed related options */
3784             char *q;
3785             if (stream || feed) {
3786                 fprintf(stderr, "%s:%d: Already in a tag\n",
3787                         filename, line_num);
3788             } else {
3789                 feed = av_mallocz(sizeof(FFStream));
3790                 /* add in stream list */
3791                 *last_stream = feed;
3792                 last_stream = &feed->next;
3793                 /* add in feed list */
3794                 *last_feed = feed;
3795                 last_feed = &feed->next_feed;
3796
3797                 get_arg(feed->filename, sizeof(feed->filename), &p);
3798                 q = strrchr(feed->filename, '>');
3799                 if (*q)
3800                     *q = '\0';
3801                 feed->fmt = guess_format("ffm", NULL, NULL);
3802                 /* defaut feed file */
3803                 snprintf(feed->feed_filename, sizeof(feed->feed_filename),
3804                          "/tmp/%s.ffm", feed->filename);
3805                 feed->feed_max_size = 5 * 1024 * 1024;
3806                 feed->is_feed = 1;
3807                 feed->feed = feed; /* self feeding :-) */
3808             }
3809         } else if (!strcasecmp(cmd, "Launch")) {
3810             if (feed) {
3811                 int i;
3812
3813                 feed->child_argv = (char **) av_mallocz(64 * sizeof(char *));
3814
3815                 for (i = 0; i < 62; i++) {
3816                     get_arg(arg, sizeof(arg), &p);
3817                     if (!arg[0])
3818                         break;
3819
3820                     feed->child_argv[i] = av_strdup(arg);
3821                 }
3822
3823                 feed->child_argv[i] = av_malloc(30 + strlen(feed->filename));
3824
3825                 snprintf(feed->child_argv[i], 30+strlen(feed->filename),
3826                     "http://%s:%d/%s",
3827                         (my_http_addr.sin_addr.s_addr == INADDR_ANY) ? "127.0.0.1" :
3828                     inet_ntoa(my_http_addr.sin_addr),
3829                     ntohs(my_http_addr.sin_port), feed->filename);
3830
3831                 if (ffserver_debug)
3832                 {
3833                     int j;
3834                     fprintf(stdout, "Launch commandline: ");
3835                     for (j = 0; j <= i; j++)
3836                         fprintf(stdout, "%s ", feed->child_argv[j]);
3837                     fprintf(stdout, "\n");
3838                 }
3839             }
3840         } else if (!strcasecmp(cmd, "ReadOnlyFile")) {
3841             if (feed) {
3842                 get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
3843                 feed->readonly = 1;
3844             } else if (stream) {
3845                 get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
3846             }
3847         } else if (!strcasecmp(cmd, "File")) {
3848             if (feed) {
3849                 get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
3850             } else if (stream)
3851                 get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
3852         } else if (!strcasecmp(cmd, "FileMaxSize")) {
3853             if (feed) {
3854                 const char *p1;
3855                 double fsize;
3856
3857                 get_arg(arg, sizeof(arg), &p);
3858                 p1 = arg;
3859                 fsize = strtod(p1, (char **)&p1);
3860                 switch(toupper(*p1)) {
3861                 case 'K':
3862                     fsize *= 1024;
3863                     break;
3864                 case 'M':
3865                     fsize *= 1024 * 1024;
3866                     break;
3867                 case 'G':
3868                     fsize *= 1024 * 1024 * 1024;
3869                     break;
3870                 }
3871                 feed->feed_max_size = (int64_t)fsize;
3872             }
3873         } else if (!strcasecmp(cmd, "</Feed>")) {
3874             if (!feed) {
3875                 fprintf(stderr, "%s:%d: No corresponding <Feed> for </Feed>\n",
3876                         filename, line_num);
3877                 errors++;
3878             }
3879             feed = NULL;
3880         } else if (!strcasecmp(cmd, "<Stream")) {
3881             /*********************************************/
3882             /* Stream related options */
3883             char *q;
3884             if (stream || feed) {
3885                 fprintf(stderr, "%s:%d: Already in a tag\n",
3886                         filename, line_num);
3887             } else {
3888                 stream = av_mallocz(sizeof(FFStream));
3889                 *last_stream = stream;
3890                 last_stream = &stream->next;
3891
3892                 get_arg(stream->filename, sizeof(stream->filename), &p);
3893                 q = strrchr(stream->filename, '>');
3894                 if (*q)
3895                     *q = '\0';
3896                 stream->fmt = guess_stream_format(NULL, stream->filename, NULL);
3897                 memset(&audio_enc, 0, sizeof(AVCodecContext));
3898                 memset(&video_enc, 0, sizeof(AVCodecContext));
3899                 audio_id = CODEC_ID_NONE;
3900                 video_id = CODEC_ID_NONE;
3901                 if (stream->fmt) {
3902                     audio_id = stream->fmt->audio_codec;
3903                     video_id = stream->fmt->video_codec;
3904                 }
3905             }
3906         } else if (!strcasecmp(cmd, "Feed")) {
3907             get_arg(arg, sizeof(arg), &p);
3908             if (stream) {
3909                 FFStream *sfeed;
3910
3911                 sfeed = first_feed;
3912                 while (sfeed != NULL) {
3913                     if (!strcmp(sfeed->filename, arg))
3914                         break;
3915                     sfeed = sfeed->next_feed;
3916                 }
3917                 if (!sfeed)
3918                     fprintf(stderr, "%s:%d: feed '%s' not defined\n",
3919                             filename, line_num, arg);
3920                 else
3921                     stream->feed = sfeed;
3922             }
3923         } else if (!strcasecmp(cmd, "Format")) {
3924             get_arg(arg, sizeof(arg), &p);
3925             if (!strcmp(arg, "status")) {
3926                 stream->stream_type = STREAM_TYPE_STATUS;
3927                 stream->fmt = NULL;
3928             } else {
3929                 stream->stream_type = STREAM_TYPE_LIVE;
3930                 /* jpeg cannot be used here, so use single frame jpeg */
3931                 if (!strcmp(arg, "jpeg"))
3932                     strcpy(arg, "mjpeg");
3933                 stream->fmt = guess_stream_format(arg, NULL, NULL);
3934                 if (!stream->fmt) {
3935                     fprintf(stderr, "%s:%d: Unknown Format: %s\n",
3936                             filename, line_num, arg);
3937                     errors++;
3938                 }
3939             }
3940             if (stream->fmt) {
3941                 audio_id = stream->fmt->audio_codec;
3942                 video_id = stream->fmt->video_codec;
3943             }
3944         } else if (!strcasecmp(cmd, "InputFormat")) {
3945             get_arg(arg, sizeof(arg), &p);
3946             stream->ifmt = av_find_input_format(arg);
3947             if (!stream->ifmt) {
3948                 fprintf(stderr, "%s:%d: Unknown input format: %s\n",
3949                         filename, line_num, arg);
3950             }
3951         } else if (!strcasecmp(cmd, "FaviconURL")) {
3952             if (stream && stream->stream_type == STREAM_TYPE_STATUS) {
3953                 get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
3954             } else {
3955                 fprintf(stderr, "%s:%d: FaviconURL only permitted for status streams\n",
3956                             filename, line_num);
3957                 errors++;
3958             }
3959         } else if (!strcasecmp(cmd, "Author")) {
3960             if (stream)
3961                 get_arg(stream->author, sizeof(stream->author), &p);
3962         } else if (!strcasecmp(cmd, "Comment")) {
3963             if (stream)
3964                 get_arg(stream->comment, sizeof(stream->comment), &p);
3965         } else if (!strcasecmp(cmd, "Copyright")) {
3966             if (stream)
3967                 get_arg(stream->copyright, sizeof(stream->copyright), &p);
3968         } else if (!strcasecmp(cmd, "Title")) {
3969             if (stream)
3970                 get_arg(stream->title, sizeof(stream->title), &p);
3971         } else if (!strcasecmp(cmd, "Preroll")) {
3972             get_arg(arg, sizeof(arg), &p);
3973             if (stream)
3974                 stream->prebuffer = atof(arg) * 1000;
3975         } else if (!strcasecmp(cmd, "StartSendOnKey")) {
3976             if (stream)
3977                 stream->send_on_key = 1;
3978         } else if (!strcasecmp(cmd, "AudioCodec")) {
3979             get_arg(arg, sizeof(arg), &p);
3980             audio_id = opt_audio_codec(arg);
3981             if (audio_id == CODEC_ID_NONE) {
3982                 fprintf(stderr, "%s:%d: Unknown AudioCodec: %s\n",
3983                         filename, line_num, arg);
3984                 errors++;
3985             }
3986         } else if (!strcasecmp(cmd, "VideoCodec")) {
3987             get_arg(arg, sizeof(arg), &p);
3988             video_id = opt_video_codec(arg);
3989             if (video_id == CODEC_ID_NONE) {
3990                 fprintf(stderr, "%s:%d: Unknown VideoCodec: %s\n",
3991                         filename, line_num, arg);
3992                 errors++;
3993             }
3994         } else if (!strcasecmp(cmd, "MaxTime")) {
3995             get_arg(arg, sizeof(arg), &p);
3996             if (stream)
3997                 stream->max_time = atof(arg) * 1000;
3998         } else if (!strcasecmp(cmd, "AudioBitRate")) {
3999             get_arg(arg, sizeof(arg), &p);
4000             if (stream)
4001                 audio_enc.bit_rate = atoi(arg) * 1000;
4002         } else if (!strcasecmp(cmd, "AudioChannels")) {
4003             get_arg(arg, sizeof(arg), &p);
4004             if (stream)
4005                 audio_enc.channels = atoi(arg);
4006         } else if (!strcasecmp(cmd, "AudioSampleRate")) {
4007             get_arg(arg, sizeof(arg), &p);
4008             if (stream)
4009                 audio_enc.sample_rate = atoi(arg);
4010         } else if (!strcasecmp(cmd, "AudioQuality")) {
4011             get_arg(arg, sizeof(arg), &p);
4012             if (stream) {
4013 //                audio_enc.quality = atof(arg) * 1000;
4014             }
4015         } else if (!strcasecmp(cmd, "VideoBitRateRange")) {
4016             if (stream) {
4017                 int minrate, maxrate;
4018
4019                 get_arg(arg, sizeof(arg), &p);
4020
4021                 if (sscanf(arg, "%d-%d", &minrate, &maxrate) == 2) {
4022                     video_enc.rc_min_rate = minrate * 1000;
4023                     video_enc.rc_max_rate = maxrate * 1000;
4024                 } else {
4025                     fprintf(stderr, "%s:%d: Incorrect format for VideoBitRateRange -- should be <min>-<max>: %s\n",
4026                             filename, line_num, arg);
4027                     errors++;
4028                 }
4029             }
4030         } else if (!strcasecmp(cmd, "Debug")) {
4031             if (stream) {
4032                 get_arg(arg, sizeof(arg), &p);
4033                 video_enc.debug = strtol(arg,0,0);
4034             }
4035         } else if (!strcasecmp(cmd, "Strict")) {
4036             if (stream) {
4037                 get_arg(arg, sizeof(arg), &p);
4038                 video_enc.strict_std_compliance = atoi(arg);
4039             }
4040         } else if (!strcasecmp(cmd, "VideoBufferSize")) {
4041             if (stream) {
4042                 get_arg(arg, sizeof(arg), &p);
4043                 video_enc.rc_buffer_size = atoi(arg) * 8*1024;
4044             }
4045         } else if (!strcasecmp(cmd, "VideoBitRateTolerance")) {
4046             if (stream) {
4047                 get_arg(arg, sizeof(arg), &p);
4048                 video_enc.bit_rate_tolerance = atoi(arg) * 1000;
4049             }
4050         } else if (!strcasecmp(cmd, "VideoBitRate")) {
4051             get_arg(arg, sizeof(arg), &p);
4052             if (stream) {
4053                 video_enc.bit_rate = atoi(arg) * 1000;
4054             }
4055         } else if (!strcasecmp(cmd, "VideoSize")) {
4056             get_arg(arg, sizeof(arg), &p);
4057             if (stream) {
4058                 av_parse_video_frame_size(&video_enc.width, &video_enc.height, arg);
4059                 if ((video_enc.width % 16) != 0 ||
4060                     (video_enc.height % 16) != 0) {
4061                     fprintf(stderr, "%s:%d: Image size must be a multiple of 16\n",
4062                             filename, line_num);
4063                     errors++;
4064                 }
4065             }
4066         } else if (!strcasecmp(cmd, "VideoFrameRate")) {
4067             get_arg(arg, sizeof(arg), &p);
4068             if (stream) {
4069                 video_enc.time_base.num= DEFAULT_FRAME_RATE_BASE;
4070                 video_enc.time_base.den = (int)(strtod(arg, NULL) * video_enc.time_base.num);
4071             }
4072         } else if (!strcasecmp(cmd, "VideoGopSize")) {
4073             get_arg(arg, sizeof(arg), &p);
4074             if (stream)
4075                 video_enc.gop_size = atoi(arg);
4076         } else if (!strcasecmp(cmd, "VideoIntraOnly")) {
4077             if (stream)
4078                 video_enc.gop_size = 1;
4079         } else if (!strcasecmp(cmd, "VideoHighQuality")) {
4080             if (stream)
4081                 video_enc.mb_decision = FF_MB_DECISION_BITS;
4082         } else if (!strcasecmp(cmd, "Video4MotionVector")) {
4083             if (stream) {
4084                 video_enc.mb_decision = FF_MB_DECISION_BITS; //FIXME remove
4085                 video_enc.flags |= CODEC_FLAG_4MV;
4086             }
4087         } else if (!strcasecmp(cmd, "VideoTag")) {
4088             get_arg(arg, sizeof(arg), &p);
4089             if ((strlen(arg) == 4) && stream)
4090                 video_enc.codec_tag = ff_get_fourcc(arg);
4091         } else if (!strcasecmp(cmd, "BitExact")) {
4092             if (stream)
4093                 video_enc.flags |= CODEC_FLAG_BITEXACT;
4094         } else if (!strcasecmp(cmd, "DctFastint")) {
4095             if (stream)
4096                 video_enc.dct_algo  = FF_DCT_FASTINT;
4097         } else if (!strcasecmp(cmd, "IdctSimple")) {
4098             if (stream)
4099                 video_enc.idct_algo = FF_IDCT_SIMPLE;
4100         } else if (!strcasecmp(cmd, "Qscale")) {
4101             get_arg(arg, sizeof(arg), &p);
4102             if (stream) {
4103                 video_enc.flags |= CODEC_FLAG_QSCALE;
4104                 video_enc.global_quality = FF_QP2LAMBDA * atoi(arg);
4105             }
4106         } else if (!strcasecmp(cmd, "VideoQDiff")) {
4107             get_arg(arg, sizeof(arg), &p);
4108             if (stream) {
4109                 video_enc.max_qdiff = atoi(arg);
4110                 if (video_enc.max_qdiff < 1 || video_enc.max_qdiff > 31) {
4111                     fprintf(stderr, "%s:%d: VideoQDiff out of range\n",
4112                             filename, line_num);
4113                     errors++;
4114                 }
4115             }
4116         } else if (!strcasecmp(cmd, "VideoQMax")) {
4117             get_arg(arg, sizeof(arg), &p);
4118             if (stream) {
4119                 video_enc.qmax = atoi(arg);
4120                 if (video_enc.qmax < 1 || video_enc.qmax > 31) {
4121                     fprintf(stderr, "%s:%d: VideoQMax out of range\n",
4122                             filename, line_num);
4123                     errors++;
4124                 }
4125             }
4126         } else if (!strcasecmp(cmd, "VideoQMin")) {
4127             get_arg(arg, sizeof(arg), &p);
4128             if (stream) {
4129                 video_enc.qmin = atoi(arg);
4130                 if (video_enc.qmin < 1 || video_enc.qmin > 31) {
4131                     fprintf(stderr, "%s:%d: VideoQMin out of range\n",
4132                             filename, line_num);
4133                     errors++;
4134                 }
4135             }
4136         } else if (!strcasecmp(cmd, "LumaElim")) {
4137             get_arg(arg, sizeof(arg), &p);
4138             if (stream)
4139                 video_enc.luma_elim_threshold = atoi(arg);
4140         } else if (!strcasecmp(cmd, "ChromaElim")) {
4141             get_arg(arg, sizeof(arg), &p);
4142             if (stream)
4143                 video_enc.chroma_elim_threshold = atoi(arg);
4144         } else if (!strcasecmp(cmd, "LumiMask")) {
4145             get_arg(arg, sizeof(arg), &p);
4146             if (stream)
4147                 video_enc.lumi_masking = atof(arg);
4148         } else if (!strcasecmp(cmd, "DarkMask")) {
4149             get_arg(arg, sizeof(arg), &p);
4150             if (stream)
4151                 video_enc.dark_masking = atof(arg);
4152         } else if (!strcasecmp(cmd, "NoVideo")) {
4153             video_id = CODEC_ID_NONE;
4154         } else if (!strcasecmp(cmd, "NoAudio")) {
4155             audio_id = CODEC_ID_NONE;
4156         } else if (!strcasecmp(cmd, "ACL")) {
4157             IPAddressACL acl;
4158
4159             get_arg(arg, sizeof(arg), &p);
4160             if (strcasecmp(arg, "allow") == 0)
4161                 acl.action = IP_ALLOW;
4162             else if (strcasecmp(arg, "deny") == 0)
4163                 acl.action = IP_DENY;
4164             else {
4165                 fprintf(stderr, "%s:%d: ACL action '%s' is not ALLOW or DENY\n",
4166                         filename, line_num, arg);
4167                 errors++;
4168             }
4169
4170             get_arg(arg, sizeof(arg), &p);
4171
4172             if (resolve_host(&acl.first, 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             } else
4177                 acl.last = acl.first;
4178
4179             get_arg(arg, sizeof(arg), &p);
4180
4181             if (arg[0]) {
4182                 if (resolve_host(&acl.last, arg) != 0) {
4183                     fprintf(stderr, "%s:%d: ACL refers to invalid host or ip address '%s'\n",
4184                             filename, line_num, arg);
4185                     errors++;
4186                 }
4187             }
4188
4189             if (!errors) {
4190                 IPAddressACL *nacl = (IPAddressACL *) av_mallocz(sizeof(*nacl));
4191                 IPAddressACL **naclp = 0;
4192
4193                 acl.next = 0;
4194                 *nacl = acl;
4195
4196                 if (stream)
4197                     naclp = &stream->acl;
4198                 else if (feed)
4199                     naclp = &feed->acl;
4200                 else {
4201                     fprintf(stderr, "%s:%d: ACL found not in <stream> or <feed>\n",
4202                             filename, line_num);
4203                     errors++;
4204                 }
4205
4206                 if (naclp) {
4207                     while (*naclp)
4208                         naclp = &(*naclp)->next;
4209
4210                     *naclp = nacl;
4211                 }
4212             }
4213         } else if (!strcasecmp(cmd, "RTSPOption")) {
4214             get_arg(arg, sizeof(arg), &p);
4215             if (stream) {
4216                 av_freep(&stream->rtsp_option);
4217                 stream->rtsp_option = av_strdup(arg);
4218             }
4219         } else if (!strcasecmp(cmd, "MulticastAddress")) {
4220             get_arg(arg, sizeof(arg), &p);
4221             if (stream) {
4222                 if (resolve_host(&stream->multicast_ip, arg) != 0) {
4223                     fprintf(stderr, "%s:%d: Invalid host/IP address: %s\n",
4224                             filename, line_num, arg);
4225                     errors++;
4226                 }
4227                 stream->is_multicast = 1;
4228                 stream->loop = 1; /* default is looping */
4229             }
4230         } else if (!strcasecmp(cmd, "MulticastPort")) {
4231             get_arg(arg, sizeof(arg), &p);
4232             if (stream)
4233                 stream->multicast_port = atoi(arg);
4234         } else if (!strcasecmp(cmd, "MulticastTTL")) {
4235             get_arg(arg, sizeof(arg), &p);
4236             if (stream)
4237                 stream->multicast_ttl = atoi(arg);
4238         } else if (!strcasecmp(cmd, "NoLoop")) {
4239             if (stream)
4240                 stream->loop = 0;
4241         } else if (!strcasecmp(cmd, "</Stream>")) {
4242             if (!stream) {
4243                 fprintf(stderr, "%s:%d: No corresponding <Stream> for </Stream>\n",
4244                         filename, line_num);
4245                 errors++;
4246             }
4247             if (stream->feed && stream->fmt && strcmp(stream->fmt->name, "ffm") != 0) {
4248                 if (audio_id != CODEC_ID_NONE) {
4249                     audio_enc.codec_type = CODEC_TYPE_AUDIO;
4250                     audio_enc.codec_id = audio_id;
4251                     add_codec(stream, &audio_enc);
4252                 }
4253                 if (video_id != CODEC_ID_NONE) {
4254                     video_enc.codec_type = CODEC_TYPE_VIDEO;
4255                     video_enc.codec_id = video_id;
4256                     add_codec(stream, &video_enc);
4257                 }
4258             }
4259             stream = NULL;
4260         } else if (!strcasecmp(cmd, "<Redirect")) {
4261             /*********************************************/
4262             char *q;
4263             if (stream || feed || redirect) {
4264                 fprintf(stderr, "%s:%d: Already in a tag\n",
4265                         filename, line_num);
4266                 errors++;
4267             } else {
4268                 redirect = av_mallocz(sizeof(FFStream));
4269                 *last_stream = redirect;
4270                 last_stream = &redirect->next;
4271
4272                 get_arg(redirect->filename, sizeof(redirect->filename), &p);
4273                 q = strrchr(redirect->filename, '>');
4274                 if (*q)
4275                     *q = '\0';
4276                 redirect->stream_type = STREAM_TYPE_REDIRECT;
4277             }
4278         } else if (!strcasecmp(cmd, "URL")) {
4279             if (redirect)
4280                 get_arg(redirect->feed_filename, sizeof(redirect->feed_filename), &p);
4281         } else if (!strcasecmp(cmd, "</Redirect>")) {
4282             if (!redirect) {
4283                 fprintf(stderr, "%s:%d: No corresponding <Redirect> for </Redirect>\n",
4284                         filename, line_num);
4285                 errors++;
4286             }
4287             if (!redirect->feed_filename[0]) {
4288                 fprintf(stderr, "%s:%d: No URL found for <Redirect>\n",
4289                         filename, line_num);
4290                 errors++;
4291             }
4292             redirect = NULL;
4293         } else if (!strcasecmp(cmd, "LoadModule")) {
4294             get_arg(arg, sizeof(arg), &p);
4295 #ifdef HAVE_DLOPEN
4296             load_module(arg);
4297 #else
4298             fprintf(stderr, "%s:%d: Module support not compiled into this version: '%s'\n",
4299                     filename, line_num, arg);
4300             errors++;
4301 #endif
4302         } else {
4303             fprintf(stderr, "%s:%d: Incorrect keyword: '%s'\n",
4304                     filename, line_num, cmd);
4305             errors++;
4306         }
4307     }
4308
4309     fclose(f);
4310     if (errors)
4311         return -1;
4312     else
4313         return 0;
4314 }
4315
4316 static void show_banner(void)
4317 {
4318     printf("ffserver version " FFMPEG_VERSION ", Copyright (c) 2000-2006 Fabrice Bellard, et al.\n");
4319 }
4320
4321 static void show_help(void)
4322 {
4323     show_banner();
4324     printf("usage: ffserver [-L] [-h] [-f configfile]\n"
4325            "Hyper fast multi format Audio/Video streaming server\n"
4326            "\n"
4327            "-L            : print the LICENSE\n"
4328            "-h            : this help\n"
4329            "-f configfile : use configfile instead of /etc/ffserver.conf\n"
4330            );
4331 }
4332
4333 static void handle_child_exit(int sig)
4334 {
4335     pid_t pid;
4336     int status;
4337
4338     while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
4339         FFStream *feed;
4340
4341         for (feed = first_feed; feed; feed = feed->next) {
4342             if (feed->pid == pid) {
4343                 int uptime = time(0) - feed->pid_start;
4344
4345                 feed->pid = 0;
4346                 fprintf(stderr, "%s: Pid %d exited with status %d after %d seconds\n", feed->filename, pid, status, uptime);
4347
4348                 if (uptime < 30)
4349                     /* Turn off any more restarts */
4350                     feed->child_argv = 0;
4351             }
4352         }
4353     }
4354
4355     need_to_start_children = 1;
4356 }
4357
4358 int main(int argc, char **argv)
4359 {
4360     const char *config_filename;
4361     int c;
4362     struct sigaction sigact;
4363
4364     av_register_all();
4365
4366     config_filename = "/etc/ffserver.conf";
4367
4368     my_program_name = argv[0];
4369     my_program_dir = getcwd(0, 0);
4370     ffserver_daemon = 1;
4371
4372     for(;;) {
4373         c = getopt(argc, argv, "ndLh?f:");
4374         if (c == -1)
4375             break;
4376         switch(c) {
4377         case 'L':
4378             show_banner();
4379             show_license();
4380             exit(0);
4381         case '?':
4382         case 'h':
4383             show_help();
4384             exit(0);
4385         case 'n':
4386             no_launch = 1;
4387             break;
4388         case 'd':
4389             ffserver_debug = 1;
4390             ffserver_daemon = 0;
4391             break;
4392         case 'f':
4393             config_filename = optarg;
4394             break;
4395         default:
4396             exit(2);
4397         }
4398     }
4399
4400     putenv("http_proxy");               /* Kill the http_proxy */
4401
4402     av_init_random(av_gettime() + (getpid() << 16), &random_state);
4403
4404     /* address on which the server will handle HTTP connections */
4405     my_http_addr.sin_family = AF_INET;
4406     my_http_addr.sin_port = htons (8080);
4407     my_http_addr.sin_addr.s_addr = htonl (INADDR_ANY);
4408
4409     /* address on which the server will handle RTSP connections */
4410     my_rtsp_addr.sin_family = AF_INET;
4411     my_rtsp_addr.sin_port = htons (5454);
4412     my_rtsp_addr.sin_addr.s_addr = htonl (INADDR_ANY);
4413
4414     nb_max_connections = 5;
4415     max_bandwidth = 1000;
4416     first_stream = NULL;
4417     logfilename[0] = '\0';
4418
4419     memset(&sigact, 0, sizeof(sigact));
4420     sigact.sa_handler = handle_child_exit;
4421     sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
4422     sigaction(SIGCHLD, &sigact, 0);
4423
4424     if (parse_ffconfig(config_filename) < 0) {
4425         fprintf(stderr, "Incorrect config file - exiting.\n");
4426         exit(1);
4427     }
4428
4429     build_file_streams();
4430
4431     build_feed_streams();
4432
4433     compute_bandwidth();
4434
4435     /* put the process in background and detach it from its TTY */
4436     if (ffserver_daemon) {
4437         int pid;
4438
4439         pid = fork();
4440         if (pid < 0) {
4441             perror("fork");
4442             exit(1);
4443         } else if (pid > 0) {
4444             /* parent : exit */
4445             exit(0);
4446         } else {
4447             /* child */
4448             setsid();
4449             chdir("/");
4450             close(0);
4451             open("/dev/null", O_RDWR);
4452             if (strcmp(logfilename, "-") != 0) {
4453                 close(1);
4454                 dup(0);
4455             }
4456             close(2);
4457             dup(0);
4458         }
4459     }
4460
4461     /* signal init */
4462     signal(SIGPIPE, SIG_IGN);
4463
4464     /* open log file if needed */
4465     if (logfilename[0] != '\0') {
4466         if (!strcmp(logfilename, "-"))
4467             logfile = stdout;
4468         else
4469             logfile = fopen(logfilename, "w");
4470     }
4471
4472     if (http_server() < 0) {
4473         fprintf(stderr, "Could not start server\n");
4474         exit(1);
4475     }
4476
4477     return 0;
4478 }