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