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