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