4bece8c455287d56e05e314e25a0c9f11b15ad98
[ffmpeg.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 }