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