Initial revision
[libav.git] / ffserver.c
1 /*
2 * Multiple format streaming server
3 * Copyright (c) 2000 Gerard Lantau.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program 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
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 #include <stdarg.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <netinet/in.h>
24 #include <linux/videodev.h>
25 #include <linux/soundcard.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <sys/ioctl.h>
29 #include <sys/mman.h>
30 #include <sys/poll.h>
31 #include <errno.h>
32 #include <sys/time.h>
33 #include <getopt.h>
34 #include <sys/socket.h>
35 #include <arpa/inet.h>
36 #include <netdb.h>
37 #include <ctype.h>
38 #include <pthread.h>
39
40 #include "mpegenc.h"
41
42 /* maximum number of simultaneous HTTP connections */
43 #define HTTP_MAX_CONNECTIONS 2000
44
45 enum HTTPState {
46 HTTPSTATE_WAIT_REQUEST,
47 HTTPSTATE_SEND_HEADER,
48 HTTPSTATE_SEND_DATA_HEADER,
49 HTTPSTATE_SEND_DATA,
50 HTTPSTATE_SEND_DATA_TRAILER,
51 };
52
53 enum MasterState {
54 MASTERSTATE_RECEIVE_HEADER,
55 MASTERSTATE_RECEIVE_DATA,
56 };
57
58 #define IOBUFFER_MAX_SIZE 16384
59 #define FIFO_MAX_SIZE (1024*1024)
60
61 /* coef for exponential mean for bitrate estimation in statistics */
62 #define AVG_COEF 0.9
63
64 /* timeouts are in ms */
65 #define REQUEST_TIMEOUT (15 * 1000)
66 #define SYNC_TIMEOUT (10 * 1000)
67 #define MASTER_CONNECT_TIMEOUT (10 * 1000)
68
69 typedef struct HTTPContext {
70 enum HTTPState state;
71 int fd; /* socket file descriptor */
72 struct sockaddr_in from_addr; /* origin */
73 struct pollfd *poll_entry; /* used when polling */
74 long timeout;
75 UINT8 buffer[IOBUFFER_MAX_SIZE];
76 UINT8 *buffer_ptr, *buffer_end;
77 int http_error;
78 struct HTTPContext *next;
79 UINT8 *rptr; /* read pointer in the fifo */
80 int got_key_frame[2]; /* for each type */
81 long long data_count;
82 long long last_http_fifo_write_count; /* used to monitor overflow in the fifo */
83 /* format handling */
84 struct FFStream *stream;
85 AVFormatContext fmt_ctx;
86 int last_packet_sent; /* true if last data packet was sent */
87 } HTTPContext;
88
89 /* each generated stream is described here */
90 enum StreamType {
91 STREAM_TYPE_LIVE,
92 STREAM_TYPE_MASTER,
93 STREAM_TYPE_STATUS,
94 };
95
96 typedef struct FFStream {
97 enum StreamType stream_type;
98 char filename[1024];
99 AVFormat *fmt;
100 AVEncodeContext *audio_enc;
101 AVEncodeContext *video_enc;
102 struct FFStream *next;
103 } FFStream;
104
105 typedef struct FifoBuffer {
106 UINT8 *buffer;
107 UINT8 *rptr, *wptr, *end;
108 } FifoBuffer;
109
110 /* each codec is here */
111 typedef struct FFCodec {
112 struct FFCodec *next;
113 FifoBuffer fifo; /* for compression: one audio fifo per codec */
114 ReSampleContext resample; /* for audio resampling */
115 long long data_count;
116 float avg_frame_size; /* frame size averraged over last frames with exponential mean */
117 AVEncodeContext enc;
118 } FFCodec;
119
120 /* packet header */
121 typedef struct {
122 UINT8 codec_type;
123 UINT8 codec_id;
124 UINT8 data[4];
125 UINT16 bit_rate;
126 UINT16 payload_size;
127 } PacketHeader;
128
129 struct sockaddr_in my_addr;
130 char logfilename[1024];
131 HTTPContext *first_http_ctx;
132 FFStream *first_stream;
133 FFCodec *first_codec;
134
135 /* master state */
136 char master_url[1024];
137 enum MasterState master_state;
138 UINT8 *master_wptr;
139 int master_count;
140
141 long long http_fifo_write_count;
142 static FifoBuffer http_fifo;
143
144 static int handle_http(HTTPContext *c, long cur_time);
145 static int http_parse_request(HTTPContext *c);
146 static int http_send_data(HTTPContext *c);
147 static int master_receive(int fd);
148 static void compute_stats(HTTPContext *c);
149
150 int nb_max_connections;
151 int nb_connections;
152
153 /* fifo handling */
154 int fifo_init(FifoBuffer *f, int size)
155 {
156 f->buffer = malloc(size);
157 if (!f->buffer)
158 return -1;
159 f->end = f->buffer + size;
160 f->wptr = f->rptr = f->buffer;
161 return 0;
162 }
163
164 static int fifo_size(FifoBuffer *f, UINT8 *rptr)
165 {
166 int size;
167
168 if (f->wptr >= rptr) {
169 size = f->wptr - rptr;
170 } else {
171 size = (f->end - rptr) + (f->wptr - f->buffer);
172 }
173 return size;
174 }
175
176 /* get data from the fifo (return -1 if not enough data) */
177 static int fifo_read(FifoBuffer *f, UINT8 *buf, int buf_size, UINT8 **rptr_ptr)
178 {
179 UINT8 *rptr = *rptr_ptr;
180 int size, len;
181
182 if (f->wptr >= rptr) {
183 size = f->wptr - rptr;
184 } else {
185 size = (f->end - rptr) + (f->wptr - f->buffer);
186 }
187
188 if (size < buf_size)
189 return -1;
190 while (buf_size > 0) {
191 len = f->end - rptr;
192 if (len > buf_size)
193 len = buf_size;
194 memcpy(buf, rptr, len);
195 buf += len;
196 rptr += len;
197 if (rptr >= f->end)
198 rptr = f->buffer;
199 buf_size -= len;
200 }
201 *rptr_ptr = rptr;
202 return 0;
203 }
204
205 static void fifo_write(FifoBuffer *f, UINT8 *buf, int size, UINT8 **wptr_ptr)
206 {
207 int len;
208 UINT8 *wptr;
209 wptr = *wptr_ptr;
210 while (size > 0) {
211 len = f->end - wptr;
212 if (len > size)
213 len = size;
214 memcpy(wptr, buf, len);
215 wptr += len;
216 if (wptr >= f->end)
217 wptr = f->buffer;
218 buf += len;
219 size -= len;
220 }
221 *wptr_ptr = wptr;
222 }
223
224 static long gettime_ms(void)
225 {
226 struct timeval tv;
227
228 gettimeofday(&tv,NULL);
229 return (long long)tv.tv_sec * 1000 + (tv.tv_usec / 1000);
230 }
231
232 static FILE *logfile = NULL;
233
234 static void http_log(char *fmt, ...)
235 {
236 va_list ap;
237 va_start(ap, fmt);
238
239 if (logfile)
240 vfprintf(logfile, fmt, ap);
241 va_end(ap);
242 }
243
244
245 /* connect to url 'url' and return the connected socket ready to read data */
246 static int url_get(const char *url)
247 {
248 struct sockaddr_in dest_addr;
249 struct hostent *h;
250 int s, port, size, line_size, len;
251 char hostname[1024], *q;
252 const char *p, *path;
253 char req[1024];
254 unsigned char ch;
255
256 if (!strstart(url, "http://", &p))
257 return -1;
258 q = hostname;
259 while (*p != ':' && *p != '\0' && *p != '/') {
260 if ((q - hostname) < (sizeof(hostname) - 1))
261 *q++ = *p;
262 p++;
263 }
264 port = 80;
265 if (*p == ':') {
266 p++;
267 port = strtol(p, (char **)&p, 10);
268 }
269 path = p;
270
271 dest_addr.sin_family = AF_INET;
272 dest_addr.sin_port = htons(port);
273
274 if (!inet_aton(hostname, &dest_addr.sin_addr)) {
275 if ((h = gethostbyname(hostname)) == NULL)
276 return -1;
277 memcpy(&dest_addr.sin_addr, h->h_addr, sizeof(dest_addr.sin_addr));
278 }
279
280 s=socket(AF_INET, SOCK_STREAM, 0);
281 if (s < 0)
282 return -1;
283
284 if (connect(s, (struct sockaddr *)&dest_addr, sizeof(dest_addr)) < 0) {
285 fail:
286 close(s);
287 return -1;
288 }
289
290 /* send http request */
291 snprintf(req, sizeof(req), "GET %s HTTP/1.0\r\n\r\n", path);
292 p = req;
293 size = strlen(req);
294 while (size > 0) {
295 len = write(s, p, size);
296 if (len == -1) {
297 if (errno != EAGAIN && errno != EINTR)
298 goto fail;
299 } else {
300 size -= len;
301 p += len;
302 }
303 }
304
305 /* receive answer */
306 line_size = 0;
307 for(;;) {
308 len = read(s, &ch, 1);
309 if (len == -1) {
310 if (errno != EAGAIN && errno != EINTR)
311 goto fail;
312 } else if (len == 0) {
313 goto fail;
314 } else {
315 if (ch == '\n') {
316 if (line_size == 0)
317 break;
318 line_size = 0;
319 } else if (ch != '\r') {
320 line_size++;
321 }
322 }
323 }
324
325 return s;
326 }
327
328 /* Each request is served by reading the input FIFO and by adding the
329 right format headers */
330 static int http_server(struct sockaddr_in my_addr)
331 {
332 int server_fd, tmp, ret;
333 struct sockaddr_in from_addr;
334 struct pollfd poll_table[HTTP_MAX_CONNECTIONS + 1], *poll_entry;
335 HTTPContext *c, **cp;
336 long cur_time;
337 int master_fd, master_timeout;
338
339 /* will try to connect to master as soon as possible */
340 master_fd = -1;
341 master_timeout = gettime_ms();
342
343 server_fd = socket(AF_INET,SOCK_STREAM,0);
344 if (server_fd < 0) {
345 perror ("socket");
346 return -1;
347 }
348
349 tmp = 1;
350 setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp));
351
352 if (bind (server_fd, (struct sockaddr *) &my_addr, sizeof (my_addr)) < 0) {
353 perror ("bind");
354 close(server_fd);
355 return -1;
356 }
357
358 if (listen (server_fd, 5) < 0) {
359 perror ("listen");
360 close(server_fd);
361 return -1;
362 }
363
364 http_log("ffserver started.\n");
365
366 fcntl(server_fd, F_SETFL, O_NONBLOCK);
367 first_http_ctx = NULL;
368 nb_connections = 0;
369 first_http_ctx = NULL;
370 for(;;) {
371 poll_entry = poll_table;
372 poll_entry->fd = server_fd;
373 poll_entry->events = POLLIN;
374 poll_entry++;
375
376 if (master_fd >= 0) {
377 poll_entry->fd = master_fd;
378 poll_entry->events = POLLIN;
379 poll_entry++;
380 }
381
382 /* wait for events on each HTTP handle */
383 c = first_http_ctx;
384 while (c != NULL) {
385 int fd;
386 fd = c->fd;
387 switch(c->state) {
388 case HTTPSTATE_WAIT_REQUEST:
389 c->poll_entry = poll_entry;
390 poll_entry->fd = fd;
391 poll_entry->events = POLLIN;
392 poll_entry++;
393 break;
394 case HTTPSTATE_SEND_HEADER:
395 case HTTPSTATE_SEND_DATA_HEADER:
396 case HTTPSTATE_SEND_DATA:
397 case HTTPSTATE_SEND_DATA_TRAILER:
398 c->poll_entry = poll_entry;
399 poll_entry->fd = fd;
400 poll_entry->events = POLLOUT;
401 poll_entry++;
402 break;
403 default:
404 c->poll_entry = NULL;
405 break;
406 }
407 c = c->next;
408 }
409
410 /* wait for an event on one connection. We poll at least every
411 second to handle timeouts */
412 do {
413 ret = poll(poll_table, poll_entry - poll_table, 1000);
414 } while (ret == -1);
415
416 cur_time = gettime_ms();
417
418 /* now handle the events */
419
420 cp = &first_http_ctx;
421 while ((*cp) != NULL) {
422 c = *cp;
423 if (handle_http (c, cur_time) < 0) {
424 /* close and free the connection */
425 close(c->fd);
426 *cp = c->next;
427 free(c);
428 nb_connections--;
429 } else {
430 cp = &c->next;
431 }
432 }
433
434 /* new connection request ? */
435 poll_entry = poll_table;
436 if (poll_entry->revents & POLLIN) {
437 int fd, len;
438
439 len = sizeof(from_addr);
440 fd = accept(server_fd, &from_addr, &len);
441 if (fd >= 0) {
442 fcntl(fd, F_SETFL, O_NONBLOCK);
443 /* XXX: should output a warning page when comming
444 close to the connection limit */
445 if (nb_connections >= nb_max_connections) {
446 close(fd);
447 } else {
448 /* add a new connection */
449 c = malloc(sizeof(HTTPContext));
450 memset(c, 0, sizeof(*c));
451 c->next = first_http_ctx;
452 first_http_ctx = c;
453 c->fd = fd;
454 c->poll_entry = NULL;
455 c->from_addr = from_addr;
456 c->state = HTTPSTATE_WAIT_REQUEST;
457 c->buffer_ptr = c->buffer;
458 c->buffer_end = c->buffer + IOBUFFER_MAX_SIZE;
459 c->timeout = cur_time + REQUEST_TIMEOUT;
460 nb_connections++;
461 }
462 }
463 }
464 poll_entry++;
465
466 /* master events */
467 if (poll_entry->revents & POLLIN) {
468 if (master_receive(master_fd) < 0) {
469 close(master_fd);
470 master_fd = -1;
471 }
472 }
473
474 /* master (re)connection handling */
475 if (master_url[0] != '\0' &&
476 master_fd < 0 && (master_timeout - cur_time) <= 0) {
477 master_fd = url_get(master_url);
478 if (master_fd < 0) {
479 master_timeout = gettime_ms() + MASTER_CONNECT_TIMEOUT;
480 http_log("Connection to master: '%s' failed\n", master_url);
481 } else {
482 fcntl(master_fd, F_SETFL, O_NONBLOCK);
483 master_state = MASTERSTATE_RECEIVE_HEADER;
484 master_count = sizeof(PacketHeader);
485 master_wptr = http_fifo.wptr;
486 }
487 }
488 }
489 }
490
491 static int handle_http(HTTPContext *c, long cur_time)
492 {
493 int len;
494
495 switch(c->state) {
496 case HTTPSTATE_WAIT_REQUEST:
497 /* timeout ? */
498 if ((c->timeout - cur_time) < 0)
499 return -1;
500 if (c->poll_entry->revents & (POLLERR | POLLHUP))
501 return -1;
502
503 /* no need to read if no events */
504 if (!(c->poll_entry->revents & POLLIN))
505 return 0;
506 /* read the data */
507 len = read(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr);
508 if (len < 0) {
509 if (errno != EAGAIN && errno != EINTR)
510 return -1;
511 } else if (len == 0) {
512 return -1;
513 } else {
514 /* search for end of request. XXX: not fully correct since garbage could come after the end */
515 UINT8 *ptr;
516 c->buffer_ptr += len;
517 ptr = c->buffer_ptr;
518 if ((ptr >= c->buffer + 2 && !memcmp(ptr-2, "\n\n", 2)) ||
519 (ptr >= c->buffer + 4 && !memcmp(ptr-4, "\r\n\r\n", 4))) {
520 /* request found : parse it and reply */
521 if (http_parse_request(c) < 0)
522 return -1;
523 } else if (ptr >= c->buffer_end) {
524 /* request too long: cannot do anything */
525 return -1;
526 }
527 }
528 break;
529
530 case HTTPSTATE_SEND_HEADER:
531 if (c->poll_entry->revents & (POLLERR | POLLHUP))
532 return -1;
533
534 /* no need to read if no events */
535 if (!(c->poll_entry->revents & POLLOUT))
536 return 0;
537 len = write(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr);
538 if (len < 0) {
539 if (errno != EAGAIN && errno != EINTR) {
540 /* error : close connection */
541 return -1;
542 }
543 } else {
544 c->buffer_ptr += len;
545 if (c->buffer_ptr >= c->buffer_end) {
546 /* if error, exit */
547 if (c->http_error)
548 return -1;
549 /* all the buffer was send : synchronize to the incoming stream */
550 c->state = HTTPSTATE_SEND_DATA_HEADER;
551 c->buffer_ptr = c->buffer_end = c->buffer;
552 }
553 }
554 break;
555
556 case HTTPSTATE_SEND_DATA:
557 case HTTPSTATE_SEND_DATA_HEADER:
558 case HTTPSTATE_SEND_DATA_TRAILER:
559 /* no need to read if no events */
560 if (c->poll_entry->revents & (POLLERR | POLLHUP))
561 return -1;
562
563 if (!(c->poll_entry->revents & POLLOUT))
564 return 0;
565 if (http_send_data(c) < 0)
566 return -1;
567 break;
568 default:
569 return -1;
570 }
571 return 0;
572 }
573
574 /* parse http request and prepare header */
575 static int http_parse_request(HTTPContext *c)
576 {
577 const char *p;
578 char cmd[32];
579 char url[1024], *q;
580 char protocol[32];
581 char msg[1024];
582 char *mime_type;
583 FFStream *stream;
584
585 p = c->buffer;
586 q = cmd;
587 while (!isspace(*p) && *p != '\0') {
588 if ((q - cmd) < sizeof(cmd) - 1)
589 *q++ = *p;
590 p++;
591 }
592 *q = '\0';
593 if (strcmp(cmd, "GET"))
594 return -1;
595
596 while (isspace(*p)) p++;
597 q = url;
598 while (!isspace(*p) && *p != '\0') {
599 if ((q - url) < sizeof(url) - 1)
600 *q++ = *p;
601 p++;
602 }
603 *q = '\0';
604
605 while (isspace(*p)) p++;
606 q = protocol;
607 while (!isspace(*p) && *p != '\0') {
608 if ((q - protocol) < sizeof(protocol) - 1)
609 *q++ = *p;
610 p++;
611 }
612 *q = '\0';
613 if (strcmp(protocol, "HTTP/1.0") && strcmp(protocol, "HTTP/1.1"))
614 return -1;
615
616 /* find the filename in the request */
617 p = url;
618 if (*p == '/')
619 p++;
620
621 stream = first_stream;
622 while (stream != NULL) {
623 if (!strcmp(stream->filename, p))
624 break;
625 stream = stream->next;
626 }
627 if (stream == NULL) {
628 sprintf(msg, "File '%s' not found", url);
629 goto send_error;
630 }
631 c->stream = stream;
632
633 /* should do it after so that the size can be computed */
634 {
635 char buf1[32], buf2[32], *p;
636 time_t ti;
637 /* XXX: reentrant function ? */
638 p = inet_ntoa(c->from_addr.sin_addr);
639 strcpy(buf1, p);
640 ti = time(NULL);
641 p = ctime(&ti);
642 strcpy(buf2, p);
643 p = buf2 + strlen(p) - 1;
644 if (*p == '\n')
645 *p = '\0';
646 http_log("%s - - [%s] \"%s %s %s\" %d %d\n",
647 buf1, buf2, cmd, url, protocol, 200, 1024);
648 }
649
650 if (c->stream->stream_type == STREAM_TYPE_STATUS)
651 goto send_stats;
652
653 /* prepare http header */
654 q = c->buffer;
655 q += sprintf(q, "HTTP/1.0 200 OK\r\n");
656 mime_type = c->stream->fmt->mime_type;
657 if (!mime_type)
658 mime_type = "application/x-octet_stream";
659 q += sprintf(q, "Content-type: %s\r\n", mime_type);
660 q += sprintf(q, "Pragma: no-cache\r\n");
661 /* for asf, we need extra headers */
662 if (!strcmp(c->stream->fmt->name,"asf")) {
663 q += sprintf(q, "Pragma: features=broadcast\r\n");
664 }
665 q += sprintf(q, "\r\n");
666
667 /* prepare output buffer */
668 c->http_error = 0;
669 c->buffer_ptr = c->buffer;
670 c->buffer_end = q;
671 c->state = HTTPSTATE_SEND_HEADER;
672 return 0;
673 send_error:
674 c->http_error = 404;
675 q = c->buffer;
676 q += sprintf(q, "HTTP/1.0 404 Not Found\r\n");
677 q += sprintf(q, "Content-type: %s\r\n", "text/html");
678 q += sprintf(q, "\r\n");
679 q += sprintf(q, "<HTML>\n");
680 q += sprintf(q, "<HEAD><TITLE>404 Not Found</TITLE></HEAD>\n");
681 q += sprintf(q, "<BODY>%s</BODY>\n", msg);
682 q += sprintf(q, "</HTML>\n");
683
684 /* prepare output buffer */
685 c->buffer_ptr = c->buffer;
686 c->buffer_end = q;
687 c->state = HTTPSTATE_SEND_HEADER;
688 return 0;
689 send_stats:
690 compute_stats(c);
691 c->http_error = 200; /* horrible : we use this value to avoid
692 going to the send data state */
693 c->state = HTTPSTATE_SEND_HEADER;
694 return 0;
695 }
696
697 static void compute_stats(HTTPContext *c)
698 {
699 AVEncodeContext *enc;
700 HTTPContext *c1;
701 FFCodec *ffenc;
702 FFStream *stream;
703 float avg;
704 char buf[1024], *q, *p;
705 time_t ti;
706 int i;
707
708 q = c->buffer;
709 q += sprintf(q, "HTTP/1.0 200 OK\r\n");
710 q += sprintf(q, "Content-type: %s\r\n", "text/html");
711 q += sprintf(q, "Pragma: no-cache\r\n");
712 q += sprintf(q, "\r\n");
713
714 q += sprintf(q, "<HEAD><TITLE>FFServer Status</TITLE></HEAD>\n<BODY>");
715 q += sprintf(q, "<H1>FFServer Status</H1>\n");
716 /* format status */
717 q += sprintf(q, "<H1>Available Streams</H1>\n");
718 q += sprintf(q, "<TABLE>\n");
719 q += sprintf(q, "<TR><TD>Path<TD>Format<TD>Bit rate (kbits/s)<TD>Video<TD>Audio\n");
720 stream = first_stream;
721 while (stream != NULL) {
722 q += sprintf(q, "<TR><TD><A HREF=\"/%s\">%s</A> ",
723 stream->filename, stream->filename);
724 switch(stream->stream_type) {
725 case STREAM_TYPE_LIVE:
726 {
727 int audio_bit_rate = 0;
728 int video_bit_rate = 0;
729 if (stream->audio_enc)
730 audio_bit_rate = stream->audio_enc->bit_rate;
731 if (stream->video_enc)
732 video_bit_rate = stream->video_enc->bit_rate;
733
734 q += sprintf(q, "<TD> %s <TD> %d <TD> %d <TD> %d\n",
735 stream->fmt->name,
736 (audio_bit_rate + video_bit_rate) / 1000,
737 video_bit_rate / 1000, audio_bit_rate / 1000);
738 }
739 break;
740 case STREAM_TYPE_MASTER:
741 q += sprintf(q, "<TD> %s <TD> - <TD> - <TD> -\n",
742 "master");
743 break;
744 default:
745 q += sprintf(q, "<TD> - <TD> - <TD> - <TD> -\n");
746 break;
747 }
748 stream = stream->next;
749 }
750 q += sprintf(q, "</TABLE>\n");
751
752 /* codec status */
753 q += sprintf(q, "<H1>Codec Status</H1>\n");
754 q += sprintf(q, "<TABLE>\n");
755 q += sprintf(q, "<TR><TD>Parameters<TD>Frame count<TD>Size<TD>Avg bitrate (kbits/s)\n");
756 ffenc = first_codec;
757 while (ffenc != NULL) {
758 enc = &ffenc->enc;
759 avencoder_string(buf, sizeof(buf), enc);
760 avg = ffenc->avg_frame_size * (float)enc->rate * 8.0;
761 if (enc->codec->type == CODEC_TYPE_AUDIO && enc->frame_size > 0)
762 avg /= enc->frame_size;
763 q += sprintf(q, "<TR><TD>%s <TD> %d <TD> %Ld <TD> %0.1f\n",
764 buf, enc->frame_number, ffenc->data_count, avg / 1000.0);
765 ffenc = ffenc->next;
766 }
767 q += sprintf(q, "</TABLE>\n");
768
769 /* exclude the stat connection */
770 q += sprintf(q, "Number of connections: %d / %d<BR>\n",
771 nb_connections, nb_max_connections);
772
773 /* connection status */
774 q += sprintf(q, "<H1>Connection Status</H1>\n");
775 q += sprintf(q, "<TABLE>\n");
776 q += sprintf(q, "<TR><TD>#<TD>File<TD>IP<TD>Size\n");
777 c1 = first_http_ctx;
778 i = 0;
779 while (c1 != NULL) {
780 i++;
781 p = inet_ntoa(c1->from_addr.sin_addr);
782 q += sprintf(q, "<TR><TD><B>%d</B><TD>%s <TD> %s <TD> %Ld\n",
783 i, c1->stream->filename, p, c1->data_count);
784 c1 = c1->next;
785 }
786 q += sprintf(q, "</TABLE>\n");
787
788 /* date */
789 ti = time(NULL);
790 p = ctime(&ti);
791 q += sprintf(q, "<HR>Generated at %s", p);
792 q += sprintf(q, "</BODY>\n</HTML>\n");
793
794 c->buffer_ptr = c->buffer;
795 c->buffer_end = q;
796 }
797
798
799 static void http_write_packet(void *opaque,
800 unsigned char *buf, int size)
801 {
802 HTTPContext *c = opaque;
803 if (size > IOBUFFER_MAX_SIZE)
804 abort();
805 memcpy(c->buffer, buf, size);
806 c->buffer_ptr = c->buffer;
807 c->buffer_end = c->buffer + size;
808 }
809
810 /* this headers are used to identify a packet for a given codec */
811 void mk_header(PacketHeader *h, AVEncodeContext *c, int payload_size)
812 {
813 h->codec_type = c->codec->type;
814 h->codec_id = c->codec->id;
815 h->bit_rate = htons(c->bit_rate / 1000);
816 switch(c->codec->type) {
817 case CODEC_TYPE_VIDEO:
818 h->data[0] = c->rate;
819 h->data[1] = c->width / 16;
820 h->data[2] = c->height / 16;
821 break;
822 case CODEC_TYPE_AUDIO:
823 h->data[0] = c->rate / 1000;
824 h->data[1] = c->channels;
825 h->data[2] = 0;
826 break;
827 }
828 h->data[3] = c->key_frame;
829 h->payload_size = htons(payload_size);
830 }
831
832 int test_header(PacketHeader *h, AVEncodeContext *c)
833 {
834 if (!c)
835 return 0;
836
837 if (h->codec_type == c->codec->type &&
838 h->codec_id == c->codec->id &&
839 h->bit_rate == htons(c->bit_rate / 1000)) {
840
841 switch(c->codec->type) {
842 case CODEC_TYPE_VIDEO:
843 if (h->data[0] == c->rate &&
844 h->data[1] == (c->width / 16) &&
845 h->data[2] == (c->height / 16))
846 goto found;
847 break;
848 case CODEC_TYPE_AUDIO:
849 if (h->data[0] == (c->rate / 1000) &&
850 (h->data[1] == c->channels))
851 goto found;
852 break;
853 }
854 }
855 return 0;
856 found:
857 c->frame_number++;
858 c->key_frame = h->data[3];
859 return 1;
860 }
861
862 static int http_prepare_data(HTTPContext *c)
863 {
864 PacketHeader hdr;
865 UINT8 *start_rptr, *payload;
866 int payload_size, ret;
867 long long fifo_total_size;
868
869 switch(c->state) {
870 case HTTPSTATE_SEND_DATA_HEADER:
871 if (c->stream->stream_type != STREAM_TYPE_MASTER) {
872 memset(&c->fmt_ctx, 0, sizeof(c->fmt_ctx));
873 c->fmt_ctx.format = c->stream->fmt;
874 if (c->fmt_ctx.format->audio_codec != CODEC_ID_NONE) {
875 /* create a fake new codec instance */
876 c->fmt_ctx.audio_enc = malloc(sizeof(AVEncodeContext));
877 memcpy(c->fmt_ctx.audio_enc, c->stream->audio_enc,
878 sizeof(AVEncodeContext));
879 c->fmt_ctx.audio_enc->frame_number = 0;
880 }
881 if (c->fmt_ctx.format->video_codec != CODEC_ID_NONE) {
882 c->fmt_ctx.video_enc = malloc(sizeof(AVEncodeContext));
883 memcpy(c->fmt_ctx.video_enc, c->stream->video_enc,
884 sizeof(AVEncodeContext));
885 c->fmt_ctx.video_enc->frame_number = 0;
886 }
887 init_put_byte(&c->fmt_ctx.pb, c->buffer, IOBUFFER_MAX_SIZE,
888 c, http_write_packet, NULL);
889 c->fmt_ctx.is_streamed = 1;
890 c->got_key_frame[0] = 0;
891 c->got_key_frame[1] = 0;
892 /* prepare header */
893 c->fmt_ctx.format->write_header(&c->fmt_ctx);
894 }
895 c->state = HTTPSTATE_SEND_DATA;
896 c->last_packet_sent = 0;
897 c->rptr = http_fifo.wptr;
898 c->last_http_fifo_write_count = http_fifo_write_count;
899 break;
900 case HTTPSTATE_SEND_DATA:
901 /* find a new packet */
902 fifo_total_size = http_fifo_write_count - c->last_http_fifo_write_count;
903 if (fifo_total_size >= ((3 * FIFO_MAX_SIZE) / 4)) {
904 /* overflow : resync. We suppose that wptr is at this
905 point a pointer to a valid packet */
906 c->rptr = http_fifo.wptr;
907 c->got_key_frame[0] = 0;
908 c->got_key_frame[1] = 0;
909 }
910
911 start_rptr = c->rptr;
912 if (fifo_read(&http_fifo, (UINT8 *)&hdr, sizeof(hdr), &c->rptr) < 0)
913 return 0;
914 payload_size = ntohs(hdr.payload_size);
915 payload = malloc(payload_size);
916 if (fifo_read(&http_fifo, payload, payload_size, &c->rptr) < 0) {
917 /* cannot read all the payload */
918 free(payload);
919 c->rptr = start_rptr;
920 return 0;
921 }
922
923 c->last_http_fifo_write_count = http_fifo_write_count -
924 fifo_size(&http_fifo, c->rptr);
925
926 if (c->stream->stream_type != STREAM_TYPE_MASTER) {
927 /* test if the packet can be handled by this format */
928 ret = 0;
929 if (test_header(&hdr, c->fmt_ctx.audio_enc)) {
930 /* only begin sending when got a key frame */
931 if (c->fmt_ctx.audio_enc->key_frame)
932 c->got_key_frame[1] = 1;
933 if (c->got_key_frame[1]) {
934 ret = c->fmt_ctx.format->write_audio_frame(&c->fmt_ctx,
935 payload, payload_size);
936 }
937 } else if (test_header(&hdr, c->fmt_ctx.video_enc)) {
938 if (c->fmt_ctx.video_enc->key_frame)
939 c->got_key_frame[0] = 1;
940 if (c->got_key_frame[0]) {
941 ret = c->fmt_ctx.format->write_video_picture(&c->fmt_ctx,
942 payload, payload_size);
943 }
944 }
945 if (ret) {
946 /* must send trailer now */
947 c->state = HTTPSTATE_SEND_DATA_TRAILER;
948 }
949 } else {
950 /* master case : send everything */
951 char *q;
952 q = c->buffer;
953 memcpy(q, &hdr, sizeof(hdr));
954 q += sizeof(hdr);
955 memcpy(q, payload, payload_size);
956 q += payload_size;
957 c->buffer_ptr = c->buffer;
958 c->buffer_end = q;
959 }
960 free(payload);
961 break;
962 default:
963 case HTTPSTATE_SEND_DATA_TRAILER:
964 /* last packet test ? */
965 if (c->last_packet_sent)
966 return -1;
967 /* prepare header */
968 c->fmt_ctx.format->write_trailer(&c->fmt_ctx);
969 c->last_packet_sent = 1;
970 break;
971 }
972 return 0;
973 }
974
975
976 /* should convert the format at the same time */
977 static int http_send_data(HTTPContext *c)
978 {
979 int len;
980
981 while (c->buffer_ptr >= c->buffer_end) {
982 if (http_prepare_data(c) < 0)
983 return -1;
984 }
985
986 len = write(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr);
987 if (len < 0) {
988 if (errno != EAGAIN && errno != EINTR) {
989 /* error : close connection */
990 return -1;
991 }
992 } else {
993 c->buffer_ptr += len;
994 c->data_count += len;
995 }
996 return 0;
997 }
998
999 static int master_receive(int fd)
1000 {
1001 int len, size;
1002 FifoBuffer *f = &http_fifo;
1003 UINT8 *rptr;
1004
1005 size = f->end - f->wptr;
1006 if (size > master_count)
1007 size = master_count;
1008 len = read(fd, f->wptr, size);
1009 if (len == -1) {
1010 if (errno != EAGAIN && errno != EINTR)
1011 return -1;
1012 } else if (len == 0) {
1013 return -1;
1014 } else {
1015 master_wptr += len;
1016 if (master_wptr >= f->end)
1017 master_wptr = f->buffer;
1018 master_count -= len;
1019 if (master_count == 0) {
1020 if (master_state == MASTERSTATE_RECEIVE_HEADER) {
1021 /* XXX: use generic fifo read to extract packet header */
1022 rptr = master_wptr;
1023 if (rptr == f->buffer)
1024 rptr = f->end - 1;
1025 else
1026 rptr--;
1027 master_count = *rptr;
1028 if (rptr == f->buffer)
1029 rptr = f->end - 1;
1030 else
1031 rptr--;
1032 master_count |= *rptr << 8;
1033 master_state = MASTERSTATE_RECEIVE_DATA;
1034 } else {
1035 /* update fifo wptr */
1036 f->wptr = master_wptr;
1037 master_state = MASTERSTATE_RECEIVE_HEADER;
1038 }
1039 }
1040 }
1041 return 0;
1042 }
1043
1044 static void get_arg(char *buf, int buf_size, const char **pp)
1045 {
1046 const char *p;
1047 char *q;
1048
1049 p = *pp;
1050 while (isspace(*p)) p++;
1051 q = buf;
1052 while (!isspace(*p) && *p != '\0') {
1053 if ((q - buf) < buf_size - 1)
1054 *q++ = *p;
1055 p++;
1056 }
1057 *q = '\0';
1058 *pp = p;
1059 }
1060
1061 /* add a codec and check if it does not already exists */
1062 AVEncodeContext *add_codec(int codec_id,
1063 AVEncodeContext *av)
1064 {
1065 AVEncoder *codec;
1066 FFCodec *ctx, **pctx;
1067 AVEncodeContext *av1;
1068
1069 codec = avencoder_find(codec_id);
1070 if (!codec)
1071 return NULL;
1072
1073 /* compute default parameters */
1074 av->codec = codec;
1075 switch(codec->type) {
1076 case CODEC_TYPE_AUDIO:
1077 if (av->bit_rate == 0)
1078 av->bit_rate = 64000;
1079 if (av->rate == 0)
1080 av->rate = 22050;
1081 if (av->channels == 0)
1082 av->channels = 1;
1083 break;
1084 case CODEC_TYPE_VIDEO:
1085 if (av->bit_rate == 0)
1086 av->bit_rate = 64000;
1087 if (av->rate == 0)
1088 av->rate = 5;
1089 if (av->width == 0 || av->height == 0) {
1090 av->width = 160;
1091 av->height = 128;
1092 }
1093 break;
1094 }
1095
1096 /* find if the codec already exists */
1097 pctx = &first_codec;
1098 while (*pctx != NULL) {
1099 av1 = &(*pctx)->enc;
1100 if (av1->codec == av->codec &&
1101 av1->bit_rate == av->bit_rate &&
1102 av1->rate == av->rate) {
1103
1104 switch(av->codec->type) {
1105 case CODEC_TYPE_AUDIO:
1106 if (av1->channels == av->channels)
1107 goto found;
1108 break;
1109 case CODEC_TYPE_VIDEO:
1110 if (av1->width == av->width &&
1111 av1->height == av->height &&
1112 av1->gop_size == av->gop_size)
1113 goto found;
1114 break;
1115 }
1116 }
1117 pctx = &(*pctx)->next;
1118 }
1119
1120 ctx = malloc(sizeof(FFCodec));
1121 if (!ctx)
1122 return NULL;
1123 memset(ctx, 0, sizeof(FFCodec));
1124 *pctx = ctx;
1125
1126 memcpy(&ctx->enc, av, sizeof(AVEncodeContext));
1127 return &ctx->enc;
1128 found:
1129 ctx = *pctx;
1130 return &ctx->enc;
1131 }
1132
1133 int parse_ffconfig(const char *filename)
1134 {
1135 FILE *f;
1136 char line[1024];
1137 char cmd[64];
1138 char arg[1024];
1139 const char *p;
1140 int val, errors, line_num;
1141 FFStream **last_stream, *stream;
1142 AVEncodeContext audio_enc, video_enc;
1143
1144 f = fopen(filename, "r");
1145 if (!f) {
1146 perror(filename);
1147 return -1;
1148 }
1149
1150 errors = 0;
1151 line_num = 0;
1152 first_stream = NULL;
1153 first_codec = NULL;
1154 last_stream = &first_stream;
1155 stream = NULL;
1156 for(;;) {
1157 if (fgets(line, sizeof(line), f) == NULL)
1158 break;
1159 line_num++;
1160 p = line;
1161 while (isspace(*p))
1162 p++;
1163 if (*p == '\0' || *p == '#')
1164 continue;
1165
1166 get_arg(cmd, sizeof(cmd), &p);
1167
1168 if (!strcasecmp(cmd, "Port")) {
1169 get_arg(arg, sizeof(arg), &p);
1170 my_addr.sin_port = htons (atoi(arg));
1171 } else if (!strcasecmp(cmd, "BindAddress")) {
1172 get_arg(arg, sizeof(arg), &p);
1173 if (!inet_aton(arg, &my_addr.sin_addr)) {
1174 fprintf(stderr, "%s:%d: Invalid IP address: %s\n",
1175 filename, line_num, arg);
1176 errors++;
1177 }
1178 } else if (!strcasecmp(cmd, "MasterServer")) {
1179 get_arg(master_url, sizeof(master_url), &p);
1180 if (!strstart(master_url, "http://", NULL)) {
1181 fprintf(stderr, "%s:%d: Invalid URL for master server: %s\n",
1182 filename, line_num, master_url);
1183 errors++;
1184 }
1185 } else if (!strcasecmp(cmd, "MaxClients")) {
1186 get_arg(arg, sizeof(arg), &p);
1187 val = atoi(arg);
1188 if (val < 1 || val > HTTP_MAX_CONNECTIONS) {
1189 fprintf(stderr, "%s:%d: Invalid MaxClients: %s\n",
1190 filename, line_num, arg);
1191 errors++;
1192 } else {
1193 nb_max_connections = val;
1194 }
1195 } else if (!strcasecmp(cmd, "CustomLog")) {
1196 get_arg(logfilename, sizeof(logfilename), &p);
1197 } else if (!strcasecmp(cmd, "<Stream")) {
1198 char *q;
1199 if (stream) {
1200 fprintf(stderr, "%s:%d: Already in a stream tag\n",
1201 filename, line_num);
1202 } else {
1203 stream = malloc(sizeof(FFStream));
1204 memset(stream, 0, sizeof(FFStream));
1205 *last_stream = stream;
1206 last_stream = &stream->next;
1207
1208 get_arg(stream->filename, sizeof(stream->filename), &p);
1209 q = strrchr(stream->filename, '>');
1210 if (*q)
1211 *q = '\0';
1212 stream->fmt = guess_format(NULL, stream->filename, NULL);
1213 memset(&audio_enc, 0, sizeof(AVEncodeContext));
1214 memset(&video_enc, 0, sizeof(AVEncodeContext));
1215 }
1216 } else if (!strcasecmp(cmd, "Format")) {
1217 get_arg(arg, sizeof(arg), &p);
1218 if (!strcmp(arg, "master")) {
1219 stream->stream_type = STREAM_TYPE_MASTER;
1220 stream->fmt = NULL;
1221 } else if (!strcmp(arg, "status")) {
1222 stream->stream_type = STREAM_TYPE_STATUS;
1223 stream->fmt = NULL;
1224 } else {
1225 stream->stream_type = STREAM_TYPE_LIVE;
1226 stream->fmt = guess_format(arg, NULL, NULL);
1227 if (!stream->fmt) {
1228 fprintf(stderr, "%s:%d: Unknown Format: %s\n",
1229 filename, line_num, arg);
1230 errors++;
1231 }
1232 }
1233 } else if (!strcasecmp(cmd, "AudioBitRate")) {
1234 get_arg(arg, sizeof(arg), &p);
1235 if (stream) {
1236 audio_enc.bit_rate = atoi(arg) * 1000;
1237 }
1238 } else if (!strcasecmp(cmd, "AudioChannels")) {
1239 get_arg(arg, sizeof(arg), &p);
1240 if (stream) {
1241 audio_enc.channels = atoi(arg);
1242 }
1243 } else if (!strcasecmp(cmd, "AudioSampleRate")) {
1244 get_arg(arg, sizeof(arg), &p);
1245 if (stream) {
1246 audio_enc.rate = atoi(arg);
1247 }
1248 } else if (!strcasecmp(cmd, "VideoBitRate")) {
1249 get_arg(arg, sizeof(arg), &p);
1250 if (stream) {
1251 video_enc.bit_rate = atoi(arg) * 1000;
1252 }
1253 } else if (!strcasecmp(cmd, "VideoFrameRate")) {
1254 get_arg(arg, sizeof(arg), &p);
1255 if (stream) {
1256 video_enc.rate = atoi(arg);
1257 }
1258 } else if (!strcasecmp(cmd, "VideoGopSize")) {
1259 get_arg(arg, sizeof(arg), &p);
1260 if (stream) {
1261 video_enc.gop_size = atoi(arg);
1262 }
1263 } else if (!strcasecmp(cmd, "VideoIntraOnly")) {
1264 if (stream) {
1265 video_enc.gop_size = 1;
1266 }
1267 } else if (!strcasecmp(cmd, "</Stream>")) {
1268 if (!stream) {
1269 fprintf(stderr, "%s:%d: No corresponding <Stream> for </Stream>\n",
1270 filename, line_num);
1271 errors++;
1272 }
1273 if (stream->fmt) {
1274 if (stream->fmt->audio_codec != CODEC_ID_NONE) {
1275 stream->audio_enc = add_codec(stream->fmt->audio_codec,
1276 &audio_enc);
1277 }
1278
1279 if (stream->fmt->video_codec != CODEC_ID_NONE)
1280 stream->video_enc = add_codec(stream->fmt->video_codec,
1281 &video_enc);
1282 }
1283 stream = NULL;
1284 } else {
1285 fprintf(stderr, "%s:%d: Incorrect keyword: '%s'\n",
1286 filename, line_num, cmd);
1287 errors++;
1288 }
1289 }
1290
1291 fclose(f);
1292 if (errors)
1293 return -1;
1294 else
1295 return 0;
1296 }
1297
1298
1299 void *http_server_thread(void *arg)
1300 {
1301 http_server(my_addr);
1302 return NULL;
1303 }
1304
1305 static void write_packet(FFCodec *ffenc,
1306 UINT8 *buf, int size)
1307 {
1308 PacketHeader hdr;
1309 AVEncodeContext *enc = &ffenc->enc;
1310 UINT8 *wptr;
1311 mk_header(&hdr, enc, size);
1312 wptr = http_fifo.wptr;
1313 fifo_write(&http_fifo, (UINT8 *)&hdr, sizeof(hdr), &wptr);
1314 fifo_write(&http_fifo, buf, size, &wptr);
1315 /* atomic modification of wptr */
1316 http_fifo.wptr = wptr;
1317 ffenc->data_count += size;
1318 ffenc->avg_frame_size = ffenc->avg_frame_size * AVG_COEF + size * (1.0 - AVG_COEF);
1319 }
1320
1321 #define AUDIO_FIFO_SIZE 8192
1322
1323 int av_grab(void)
1324 {
1325 UINT8 audio_buf[AUDIO_FIFO_SIZE/2];
1326 UINT8 audio_buf1[AUDIO_FIFO_SIZE/2];
1327 UINT8 audio_out[AUDIO_FIFO_SIZE/2];
1328 UINT8 video_buffer[128*1024];
1329 char buf[256];
1330 short *samples;
1331 int ret;
1332 int audio_fd;
1333 FFCodec *ffenc;
1334 AVEncodeContext *enc;
1335 int frame_size, frame_bytes;
1336 int use_audio, use_video;
1337 int frame_rate, sample_rate, channels;
1338 int width, height, frame_number;
1339 UINT8 *picture[3];
1340
1341 use_audio = 0;
1342 use_video = 0;
1343 frame_rate = 0;
1344 sample_rate = 0;
1345 frame_size = 0;
1346 channels = 1;
1347 width = 0;
1348 height = 0;
1349 frame_number = 0;
1350 ffenc = first_codec;
1351 while (ffenc != NULL) {
1352 enc = &ffenc->enc;
1353 avencoder_string(buf, sizeof(buf), enc);
1354 fprintf(stderr, " %s\n", buf);
1355 if (avencoder_open(enc, enc->codec) < 0) {
1356 fprintf(stderr, "Incorrect encode parameters\n");
1357 return -1;
1358 }
1359 switch(enc->codec->type) {
1360 case CODEC_TYPE_AUDIO:
1361 use_audio = 1;
1362 if (enc->rate > sample_rate)
1363 sample_rate = enc->rate;
1364 if (enc->frame_size > frame_size)
1365 frame_size = enc->frame_size;
1366 if (enc->channels > channels)
1367 channels = enc->channels;
1368 fifo_init(&ffenc->fifo, AUDIO_FIFO_SIZE);
1369 break;
1370 case CODEC_TYPE_VIDEO:
1371 use_video = 1;
1372 if (enc->rate > frame_rate)
1373 frame_rate = enc->rate;
1374 if (enc->width > width)
1375 width = enc->width;
1376 if (enc->height > height)
1377 height = enc->height;
1378 break;
1379 }
1380 ffenc = ffenc->next;
1381 }
1382
1383 /* audio */
1384 samples = NULL;
1385 audio_fd = -1;
1386 if (use_audio) {
1387 printf("Audio sampling: %d Hz, %s\n",
1388 sample_rate, channels == 2 ? "stereo" : "mono");
1389 audio_fd = audio_open(sample_rate, channels);
1390 if (audio_fd < 0) {
1391 fprintf(stderr, "Could not open audio device\n");
1392 exit(1);
1393 }
1394 }
1395
1396 ffenc = first_codec;
1397 while (ffenc != NULL) {
1398 enc = &ffenc->enc;
1399 if (enc->codec->type == CODEC_TYPE_AUDIO &&
1400 (enc->channels != channels ||
1401 enc->rate != sample_rate)) {
1402 audio_resample_init(&ffenc->resample, enc->channels, channels,
1403 enc->rate, sample_rate);
1404 }
1405 ffenc = ffenc->next;
1406 }
1407
1408 /* video */
1409 if (use_video) {
1410 printf("Video sampling: %dx%d, %d fps\n",
1411 width, height, frame_rate);
1412 ret = v4l_init(frame_rate, width, height);
1413 if (ret < 0) {
1414 fprintf(stderr,"Could not init video 4 linux capture\n");
1415 exit(1);
1416 }
1417 }
1418
1419 for(;;) {
1420 /* read & compress audio frames */
1421 if (use_audio) {
1422 int ret, nb_samples, nb_samples_out;
1423 UINT8 *buftmp;
1424
1425 for(;;) {
1426 ret = read(audio_fd, audio_buf, AUDIO_FIFO_SIZE/2);
1427 if (ret <= 0)
1428 break;
1429 /* fill each codec fifo by doing the right sample
1430 rate conversion. This is not optimal because we
1431 do too much work, but it is easy to do */
1432 nb_samples = ret / (channels * 2);
1433 ffenc = first_codec;
1434 while (ffenc != NULL) {
1435 enc = &ffenc->enc;
1436 if (enc->codec->type == CODEC_TYPE_AUDIO) {
1437 /* rate & stereo convertion */
1438 if (enc->channels == channels &&
1439 enc->rate == sample_rate) {
1440 buftmp = audio_buf;
1441 nb_samples_out = nb_samples;
1442 } else {
1443 buftmp = audio_buf1;
1444 nb_samples_out = audio_resample(&ffenc->resample,
1445 (short *)buftmp, (short *)audio_buf,
1446 nb_samples);
1447
1448 }
1449 fifo_write(&ffenc->fifo, buftmp, nb_samples_out * enc->channels * 2,
1450 &ffenc->fifo.wptr);
1451 }
1452 ffenc = ffenc->next;
1453 }
1454
1455 /* compress as many frame as possible with each audio codec */
1456 ffenc = first_codec;
1457 while (ffenc != NULL) {
1458 enc = &ffenc->enc;
1459 if (enc->codec->type == CODEC_TYPE_AUDIO) {
1460 frame_bytes = enc->frame_size * 2 * enc->channels;
1461
1462 while (fifo_read(&ffenc->fifo, audio_buf, frame_bytes, &ffenc->fifo.rptr) == 0) {
1463 ret = avencoder_encode(enc,
1464 audio_out, sizeof(audio_out), audio_buf);
1465 write_packet(ffenc, audio_out, ret);
1466 }
1467 }
1468 ffenc = ffenc->next;
1469 }
1470 }
1471 }
1472
1473 if (use_video) {
1474 ret = v4l_read_picture (picture, width, height,
1475 frame_number);
1476 if (ret < 0)
1477 break;
1478 ffenc = first_codec;
1479 while (ffenc != NULL) {
1480 enc = &ffenc->enc;
1481 if (enc->codec->type == CODEC_TYPE_VIDEO) {
1482 int n1, n2;
1483 /* feed each codec with its requested frame rate */
1484 n1 = (frame_number * enc->rate) / frame_rate;
1485 n2 = ((frame_number + 1) * enc->rate) / frame_rate;
1486 if (n2 > n1) {
1487 ret = avencoder_encode(enc, video_buffer, sizeof(video_buffer), picture);
1488 write_packet(ffenc, video_buffer, ret);
1489 }
1490 }
1491 ffenc = ffenc->next;
1492 }
1493 frame_number++;
1494 }
1495 }
1496
1497 ffenc = first_codec;
1498 while (ffenc != NULL) {
1499 enc = &ffenc->enc;
1500 avencoder_close(enc);
1501 ffenc = ffenc->next;
1502 }
1503 close(audio_fd);
1504 return 0;
1505 }
1506
1507
1508 void help(void)
1509 {
1510 printf("ffserver version 1.0, Copyright (c) 2000 Gerard Lantau\n"
1511 "usage: ffserver [-L] [-h] [-f configfile]\n"
1512 "Hyper fast multi format Audio/Video streaming server\n"
1513 "\n"
1514 "-L : print the LICENCE\n"
1515 "-h : this help\n"
1516 "-f configfile : use configfile instead of /etc/ffserver.conf\n"
1517 );
1518 }
1519
1520 void licence(void)
1521 {
1522 printf(
1523 "ffserver version 1.0\n"
1524 "Copyright (c) 2000 Gerard Lantau\n"
1525 "This program is free software; you can redistribute it and/or modify\n"
1526 "it under the terms of the GNU General Public License as published by\n"
1527 "the Free Software Foundation; either version 2 of the License, or\n"
1528 "(at your option) any later version.\n"
1529 "\n"
1530 "This program is distributed in the hope that it will be useful,\n"
1531 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
1532 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
1533 "GNU General Public License for more details.\n"
1534 "\n"
1535 "You should have received a copy of the GNU General Public License\n"
1536 "along with this program; if not, write to the Free Software\n"
1537 "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n"
1538 );
1539 }
1540
1541 int main(int argc, char **argv)
1542 {
1543 pthread_t http_server_tid;
1544 const char *config_filename;
1545 int c;
1546
1547 /* codecs */
1548 register_avencoder(&ac3_encoder);
1549 register_avencoder(&mp2_encoder);
1550 register_avencoder(&mpeg1video_encoder);
1551 register_avencoder(&h263_encoder);
1552 register_avencoder(&rv10_encoder);
1553 register_avencoder(&mjpeg_encoder);
1554
1555 /* audio video formats */
1556 register_avformat(&mp2_format);
1557 register_avformat(&ac3_format);
1558 register_avformat(&mpeg_mux_format);
1559 register_avformat(&mpeg1video_format);
1560 register_avformat(&h263_format);
1561 register_avformat(&rm_format);
1562 register_avformat(&ra_format);
1563 register_avformat(&asf_format);
1564 register_avformat(&mpjpeg_format);
1565 register_avformat(&jpeg_format);
1566 register_avformat(&swf_format);
1567
1568 config_filename = "/etc/ffserver.conf";
1569
1570 for(;;) {
1571 c = getopt_long_only(argc, argv, "Lh?f:", NULL, NULL);
1572 if (c == -1)
1573 break;
1574 switch(c) {
1575 case 'L':
1576 licence();
1577 exit(1);
1578 case '?':
1579 case 'h':
1580 help();
1581 exit(1);
1582 case 'f':
1583 config_filename = optarg;
1584 break;
1585 default:
1586 exit(2);
1587 }
1588 }
1589
1590 /* address on which the server will handle connections */
1591 my_addr.sin_family = AF_INET;
1592 my_addr.sin_port = htons (8080);
1593 my_addr.sin_addr.s_addr = htonl (INADDR_ANY);
1594 nb_max_connections = 5;
1595 first_stream = NULL;
1596 logfilename[0] = '\0';
1597
1598 if (parse_ffconfig(config_filename) < 0) {
1599 fprintf(stderr, "Incorrect config file - exiting.\n");
1600 exit(1);
1601 }
1602
1603 /* open log file if needed */
1604 if (logfilename[0] != '\0') {
1605 if (!strcmp(logfilename, "-"))
1606 logfile = stdout;
1607 else
1608 logfile = fopen(logfilename, "w");
1609 }
1610
1611 /* init fifo */
1612 http_fifo_write_count = 0;
1613 if (fifo_init(&http_fifo, FIFO_MAX_SIZE) < 0) {
1614 fprintf(stderr, "Could not allow receive fifo\n");
1615 exit(1);
1616 }
1617
1618 if (master_url[0] == '\0') {
1619 /* no master server: we grab ourself */
1620
1621 /* launch server thread */
1622 if (pthread_create(&http_server_tid, NULL,
1623 http_server_thread, NULL) != 0) {
1624 fprintf(stderr, "Could not create http server thread\n");
1625 exit(1);
1626 }
1627
1628 /* launch the audio / video grab */
1629 if (av_grab() < 0) {
1630 fprintf(stderr, "Could not start audio/video grab\n");
1631 exit(1);
1632 }
1633 } else {
1634 /* master server : no thread are needed */
1635 if (http_server(my_addr) < 0) {
1636 fprintf(stderr, "Could start http server\n");
1637 exit(1);
1638 }
1639 }
1640
1641 return 0;
1642 }