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