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