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