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