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