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