OSDN Git Service

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