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