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