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