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