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