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