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