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