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