Browse code

Remove avserver.

It has not been properly maintained for years and there is little hope
of that changing in the future.
It appears simpler to write a new replacement from scratch than
unbreaking it.

Anton Khirnov authored on 2014/06/09 21:21:56
Showing 18 changed files
... ...
@@ -24,7 +24,6 @@
24 24
 /avconv
25 25
 /avplay
26 26
 /avprobe
27
-/avserver
28 27
 /config.*
29 28
 /coverage.info
30 29
 /version.h
... ...
@@ -27,6 +27,7 @@ version <next>:
27 27
 - libbs2b-based stereo-to-binaural audio filter
28 28
 - native Opus decoder
29 29
 - display matrix export and rotation api
30
+- drop avserver, it was unmaintained for years and largely broken
30 31
 
31 32
 
32 33
 version 10:
... ...
@@ -63,12 +63,11 @@ COMPILE_HOSTC = $(call COMPILE,HOSTCC)
63 63
 AVPROGS-$(CONFIG_AVCONV)   += avconv
64 64
 AVPROGS-$(CONFIG_AVPLAY)   += avplay
65 65
 AVPROGS-$(CONFIG_AVPROBE)  += avprobe
66
-AVPROGS-$(CONFIG_AVSERVER) += avserver
67 66
 
68 67
 AVPROGS    := $(AVPROGS-yes:%=%$(EXESUF))
69 68
 PROGS      += $(AVPROGS)
70 69
 
71
-AVBASENAMES = avconv avplay avprobe avserver
70
+AVBASENAMES = avconv avplay avprobe
72 71
 ALLAVPROGS  = $(AVBASENAMES:%=%$(EXESUF))
73 72
 
74 73
 $(foreach prog,$(AVBASENAMES),$(eval OBJS-$(prog) += cmdutils.o))
75 74
deleted file mode 100644
... ...
@@ -1,4685 +0,0 @@
1
-/*
2
- * Multiple format streaming server
3
- * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
4
- *
5
- * This file is part of Libav.
6
- *
7
- * Libav is free software; you can redistribute it and/or
8
- * modify it under the terms of the GNU Lesser General Public
9
- * License as published by the Free Software Foundation; either
10
- * version 2.1 of the License, or (at your option) any later version.
11
- *
12
- * Libav is distributed in the hope that it will be useful,
13
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
- * Lesser General Public License for more details.
16
- *
17
- * You should have received a copy of the GNU Lesser General Public
18
- * License along with Libav; if not, write to the Free Software
19
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
- */
21
-
22
-#include "config.h"
23
-#if !HAVE_CLOSESOCKET
24
-#define closesocket close
25
-#endif
26
-#include <string.h>
27
-#include <stdlib.h>
28
-#include <stdio.h>
29
-#include "libavformat/avformat.h"
30
-// FIXME those are internal headers, avserver _really_ shouldn't use them
31
-#include "libavformat/ffm.h"
32
-#include "libavformat/network.h"
33
-#include "libavformat/os_support.h"
34
-#include "libavformat/rtpdec.h"
35
-#include "libavformat/rtpproto.h"
36
-#include "libavformat/rtsp.h"
37
-#include "libavformat/avio_internal.h"
38
-#include "libavformat/internal.h"
39
-#include "libavformat/url.h"
40
-
41
-#include "libavutil/avstring.h"
42
-#include "libavutil/lfg.h"
43
-#include "libavutil/dict.h"
44
-#include "libavutil/intreadwrite.h"
45
-#include "libavutil/mathematics.h"
46
-#include "libavutil/random_seed.h"
47
-#include "libavutil/parseutils.h"
48
-#include "libavutil/opt.h"
49
-#include "libavutil/time.h"
50
-
51
-#include <stdarg.h>
52
-#include <unistd.h>
53
-#include <fcntl.h>
54
-#include <sys/ioctl.h>
55
-#if HAVE_POLL_H
56
-#include <poll.h>
57
-#endif
58
-#include <errno.h>
59
-#include <time.h>
60
-#include <sys/wait.h>
61
-#include <signal.h>
62
-
63
-#include "cmdutils.h"
64
-
65
-const char program_name[] = "avserver";
66
-const int program_birth_year = 2000;
67
-
68
-static const OptionDef options[];
69
-
70
-enum HTTPState {
71
-    HTTPSTATE_WAIT_REQUEST,
72
-    HTTPSTATE_SEND_HEADER,
73
-    HTTPSTATE_SEND_DATA_HEADER,
74
-    HTTPSTATE_SEND_DATA,          /* sending TCP or UDP data */
75
-    HTTPSTATE_SEND_DATA_TRAILER,
76
-    HTTPSTATE_RECEIVE_DATA,
77
-    HTTPSTATE_WAIT_FEED,          /* wait for data from the feed */
78
-    HTTPSTATE_READY,
79
-
80
-    RTSPSTATE_WAIT_REQUEST,
81
-    RTSPSTATE_SEND_REPLY,
82
-    RTSPSTATE_SEND_PACKET,
83
-};
84
-
85
-static const char *http_state[] = {
86
-    "HTTP_WAIT_REQUEST",
87
-    "HTTP_SEND_HEADER",
88
-
89
-    "SEND_DATA_HEADER",
90
-    "SEND_DATA",
91
-    "SEND_DATA_TRAILER",
92
-    "RECEIVE_DATA",
93
-    "WAIT_FEED",
94
-    "READY",
95
-
96
-    "RTSP_WAIT_REQUEST",
97
-    "RTSP_SEND_REPLY",
98
-    "RTSP_SEND_PACKET",
99
-};
100
-
101
-#define MAX_STREAMS 20
102
-
103
-#define IOBUFFER_INIT_SIZE 8192
104
-
105
-/* timeouts are in ms */
106
-#define HTTP_REQUEST_TIMEOUT (15 * 1000)
107
-#define RTSP_REQUEST_TIMEOUT (3600 * 24 * 1000)
108
-
109
-#define SYNC_TIMEOUT (10 * 1000)
110
-
111
-typedef struct RTSPActionServerSetup {
112
-    uint32_t ipaddr;
113
-    char transport_option[512];
114
-} RTSPActionServerSetup;
115
-
116
-typedef struct {
117
-    int64_t count1, count2;
118
-    int64_t time1, time2;
119
-} DataRateData;
120
-
121
-/* context associated with one connection */
122
-typedef struct HTTPContext {
123
-    enum HTTPState state;
124
-    int fd; /* socket file descriptor */
125
-    struct sockaddr_in from_addr; /* origin */
126
-    struct pollfd *poll_entry; /* used when polling */
127
-    int64_t timeout;
128
-    uint8_t *buffer_ptr, *buffer_end;
129
-    int http_error;
130
-    int post;
131
-    int chunked_encoding;
132
-    int chunk_size;               /* 0 if it needs to be read */
133
-    struct HTTPContext *next;
134
-    int got_key_frame; /* stream 0 => 1, stream 1 => 2, stream 2=> 4 */
135
-    int64_t data_count;
136
-    /* feed input */
137
-    int feed_fd;
138
-    /* input format handling */
139
-    AVFormatContext *fmt_in;
140
-    int64_t start_time;            /* In milliseconds - this wraps fairly often */
141
-    int64_t first_pts;            /* initial pts value */
142
-    int64_t cur_pts;             /* current pts value from the stream in us */
143
-    int64_t cur_frame_duration;  /* duration of the current frame in us */
144
-    int cur_frame_bytes;       /* output frame size, needed to compute
145
-                                  the time at which we send each
146
-                                  packet */
147
-    int pts_stream_index;        /* stream we choose as clock reference */
148
-    int64_t cur_clock;           /* current clock reference value in us */
149
-    /* output format handling */
150
-    struct FFStream *stream;
151
-    /* -1 is invalid stream */
152
-    int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
153
-    int switch_feed_streams[MAX_STREAMS]; /* index of streams in the feed */
154
-    int switch_pending;
155
-    AVFormatContext fmt_ctx; /* instance of FFStream for one user */
156
-    int last_packet_sent; /* true if last data packet was sent */
157
-    int suppress_log;
158
-    DataRateData datarate;
159
-    int wmp_client_id;
160
-    char protocol[16];
161
-    char method[16];
162
-    char url[128];
163
-    int buffer_size;
164
-    uint8_t *buffer;
165
-    int is_packetized; /* if true, the stream is packetized */
166
-    int packet_stream_index; /* current stream for output in state machine */
167
-
168
-    /* RTSP state specific */
169
-    uint8_t *pb_buffer; /* XXX: use that in all the code */
170
-    AVIOContext *pb;
171
-    int seq; /* RTSP sequence number */
172
-
173
-    /* RTP state specific */
174
-    enum RTSPLowerTransport rtp_protocol;
175
-    char session_id[32]; /* session id */
176
-    AVFormatContext *rtp_ctx[MAX_STREAMS];
177
-
178
-    /* RTP/UDP specific */
179
-    URLContext *rtp_handles[MAX_STREAMS];
180
-
181
-    /* RTP/TCP specific */
182
-    struct HTTPContext *rtsp_c;
183
-    uint8_t *packet_buffer, *packet_buffer_ptr, *packet_buffer_end;
184
-} HTTPContext;
185
-
186
-/* each generated stream is described here */
187
-enum StreamType {
188
-    STREAM_TYPE_LIVE,
189
-    STREAM_TYPE_STATUS,
190
-    STREAM_TYPE_REDIRECT,
191
-};
192
-
193
-enum IPAddressAction {
194
-    IP_ALLOW = 1,
195
-    IP_DENY,
196
-};
197
-
198
-typedef struct IPAddressACL {
199
-    struct IPAddressACL *next;
200
-    enum IPAddressAction action;
201
-    /* These are in host order */
202
-    struct in_addr first;
203
-    struct in_addr last;
204
-} IPAddressACL;
205
-
206
-/* description of each stream of the avserver.conf file */
207
-typedef struct FFStream {
208
-    enum StreamType stream_type;
209
-    char filename[1024];     /* stream filename */
210
-    struct FFStream *feed;   /* feed we are using (can be null if
211
-                                coming from file) */
212
-    AVDictionary *in_opts;   /* input parameters */
213
-    AVInputFormat *ifmt;       /* if non NULL, force input format */
214
-    AVOutputFormat *fmt;
215
-    IPAddressACL *acl;
216
-    char dynamic_acl[1024];
217
-    int nb_streams;
218
-    int prebuffer;      /* Number of millseconds early to start */
219
-    int64_t max_time;      /* Number of milliseconds to run */
220
-    int send_on_key;
221
-    AVStream *streams[MAX_STREAMS];
222
-    int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
223
-    char feed_filename[1024]; /* file name of the feed storage, or
224
-                                 input file name for a stream */
225
-    char author[512];
226
-    char title[512];
227
-    char copyright[512];
228
-    char comment[512];
229
-    pid_t pid;  /* of avconv process */
230
-    time_t pid_start;  /* of avconv process */
231
-    char **child_argv;
232
-    struct FFStream *next;
233
-    unsigned bandwidth; /* bandwidth, in kbits/s */
234
-    /* RTSP options */
235
-    char *rtsp_option;
236
-    /* multicast specific */
237
-    int is_multicast;
238
-    struct in_addr multicast_ip;
239
-    int multicast_port; /* first port used for multicast */
240
-    int multicast_ttl;
241
-    int loop; /* if true, send the stream in loops (only meaningful if file) */
242
-
243
-    /* feed specific */
244
-    int feed_opened;     /* true if someone is writing to the feed */
245
-    int is_feed;         /* true if it is a feed */
246
-    int readonly;        /* True if writing is prohibited to the file */
247
-    int truncate;        /* True if feeder connection truncate the feed file */
248
-    int conns_served;
249
-    int64_t bytes_served;
250
-    int64_t feed_max_size;      /* maximum storage size, zero means unlimited */
251
-    int64_t feed_write_index;   /* current write position in feed (it wraps around) */
252
-    int64_t feed_size;          /* current size of feed */
253
-    struct FFStream *next_feed;
254
-} FFStream;
255
-
256
-typedef struct FeedData {
257
-    long long data_count;
258
-    float avg_frame_size;   /* frame size averaged over last frames with exponential mean */
259
-} FeedData;
260
-
261
-static struct sockaddr_in my_http_addr;
262
-static struct sockaddr_in my_rtsp_addr;
263
-
264
-static char logfilename[1024];
265
-static HTTPContext *first_http_ctx;
266
-static FFStream *first_feed;   /* contains only feeds */
267
-static FFStream *first_stream; /* contains all streams, including feeds */
268
-
269
-static void new_connection(int server_fd, int is_rtsp);
270
-static void close_connection(HTTPContext *c);
271
-
272
-/* HTTP handling */
273
-static int handle_connection(HTTPContext *c);
274
-static int http_parse_request(HTTPContext *c);
275
-static int http_send_data(HTTPContext *c);
276
-static void compute_status(HTTPContext *c);
277
-static int open_input_stream(HTTPContext *c, const char *info);
278
-static int http_start_receive_data(HTTPContext *c);
279
-static int http_receive_data(HTTPContext *c);
280
-
281
-/* RTSP handling */
282
-static int rtsp_parse_request(HTTPContext *c);
283
-static void rtsp_cmd_describe(HTTPContext *c, const char *url);
284
-static void rtsp_cmd_options(HTTPContext *c, const char *url);
285
-static void rtsp_cmd_setup(HTTPContext *c, const char *url, RTSPMessageHeader *h);
286
-static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h);
287
-static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h);
288
-static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPMessageHeader *h);
289
-
290
-/* SDP handling */
291
-static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
292
-                                   struct in_addr my_ip);
293
-
294
-/* RTP handling */
295
-static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
296
-                                       FFStream *stream, const char *session_id,
297
-                                       enum RTSPLowerTransport rtp_protocol);
298
-static int rtp_new_av_stream(HTTPContext *c,
299
-                             int stream_index, struct sockaddr_in *dest_addr,
300
-                             HTTPContext *rtsp_c);
301
-
302
-static const char *my_program_name;
303
-
304
-static const char *config_filename;
305
-
306
-static int avserver_debug;
307
-static int no_launch;
308
-static int need_to_start_children;
309
-
310
-/* maximum number of simultaneous HTTP connections */
311
-static unsigned int nb_max_http_connections = 2000;
312
-static unsigned int nb_max_connections = 5;
313
-static unsigned int nb_connections;
314
-
315
-static uint64_t max_bandwidth = 1000;
316
-static uint64_t current_bandwidth;
317
-
318
-static int64_t cur_time;           // Making this global saves on passing it around everywhere
319
-
320
-static AVLFG random_state;
321
-
322
-static FILE *logfile = NULL;
323
-
324
-static int64_t ffm_read_write_index(int fd)
325
-{
326
-    uint8_t buf[8];
327
-
328
-    lseek(fd, 8, SEEK_SET);
329
-    if (read(fd, buf, 8) != 8)
330
-        return AVERROR(EIO);
331
-    return AV_RB64(buf);
332
-}
333
-
334
-static int ffm_write_write_index(int fd, int64_t pos)
335
-{
336
-    uint8_t buf[8];
337
-    int i;
338
-
339
-    for(i=0;i<8;i++)
340
-        buf[i] = (pos >> (56 - i * 8)) & 0xff;
341
-    lseek(fd, 8, SEEK_SET);
342
-    if (write(fd, buf, 8) != 8)
343
-        return AVERROR(EIO);
344
-    return 8;
345
-}
346
-
347
-static void ffm_set_write_index(AVFormatContext *s, int64_t pos,
348
-                                int64_t file_size)
349
-{
350
-    FFMContext *ffm = s->priv_data;
351
-    ffm->write_index = pos;
352
-    ffm->file_size = file_size;
353
-}
354
-
355
-/* FIXME: make avserver work with IPv6 */
356
-/* resolve host with also IP address parsing */
357
-static int resolve_host(struct in_addr *sin_addr, const char *hostname)
358
-{
359
-
360
-    if (!ff_inet_aton(hostname, sin_addr)) {
361
-#if HAVE_GETADDRINFO
362
-        struct addrinfo *ai, *cur;
363
-        struct addrinfo hints = { 0 };
364
-        hints.ai_family = AF_INET;
365
-        if (getaddrinfo(hostname, NULL, &hints, &ai))
366
-            return -1;
367
-        /* getaddrinfo returns a linked list of addrinfo structs.
368
-         * Even if we set ai_family = AF_INET above, make sure
369
-         * that the returned one actually is of the correct type. */
370
-        for (cur = ai; cur; cur = cur->ai_next) {
371
-            if (cur->ai_family == AF_INET) {
372
-                *sin_addr = ((struct sockaddr_in *)cur->ai_addr)->sin_addr;
373
-                freeaddrinfo(ai);
374
-                return 0;
375
-            }
376
-        }
377
-        freeaddrinfo(ai);
378
-        return -1;
379
-#else
380
-        struct hostent *hp;
381
-        hp = gethostbyname(hostname);
382
-        if (!hp)
383
-            return -1;
384
-        memcpy(sin_addr, hp->h_addr_list[0], sizeof(struct in_addr));
385
-#endif
386
-    }
387
-    return 0;
388
-}
389
-
390
-static char *ctime1(char *buf2)
391
-{
392
-    time_t ti;
393
-    char *p;
394
-
395
-    ti = time(NULL);
396
-    p = ctime(&ti);
397
-    strcpy(buf2, p);
398
-    p = buf2 + strlen(p) - 1;
399
-    if (*p == '\n')
400
-        *p = '\0';
401
-    return buf2;
402
-}
403
-
404
-static void http_vlog(const char *fmt, va_list vargs)
405
-{
406
-    static int print_prefix = 1;
407
-    if (logfile) {
408
-        if (print_prefix) {
409
-            char buf[32];
410
-            ctime1(buf);
411
-            fprintf(logfile, "%s ", buf);
412
-        }
413
-        print_prefix = strstr(fmt, "\n") != NULL;
414
-        vfprintf(logfile, fmt, vargs);
415
-        fflush(logfile);
416
-    }
417
-}
418
-
419
-#ifdef __GNUC__
420
-__attribute__ ((format (printf, 1, 2)))
421
-#endif
422
-static void http_log(const char *fmt, ...)
423
-{
424
-    va_list vargs;
425
-    va_start(vargs, fmt);
426
-    http_vlog(fmt, vargs);
427
-    va_end(vargs);
428
-}
429
-
430
-static void http_av_log(void *ptr, int level, const char *fmt, va_list vargs)
431
-{
432
-    static int print_prefix = 1;
433
-    AVClass *avc = ptr ? *(AVClass**)ptr : NULL;
434
-    if (level > av_log_get_level())
435
-        return;
436
-    if (print_prefix && avc)
437
-        http_log("[%s @ %p]", avc->item_name(ptr), ptr);
438
-    print_prefix = strstr(fmt, "\n") != NULL;
439
-    http_vlog(fmt, vargs);
440
-}
441
-
442
-static void log_connection(HTTPContext *c)
443
-{
444
-    if (c->suppress_log)
445
-        return;
446
-
447
-    http_log("%s - - [%s] \"%s %s\" %d %"PRId64"\n",
448
-             inet_ntoa(c->from_addr.sin_addr), c->method, c->url,
449
-             c->protocol, (c->http_error ? c->http_error : 200), c->data_count);
450
-}
451
-
452
-static void update_datarate(DataRateData *drd, int64_t count)
453
-{
454
-    if (!drd->time1 && !drd->count1) {
455
-        drd->time1 = drd->time2 = cur_time;
456
-        drd->count1 = drd->count2 = count;
457
-    } else if (cur_time - drd->time2 > 5000) {
458
-        drd->time1 = drd->time2;
459
-        drd->count1 = drd->count2;
460
-        drd->time2 = cur_time;
461
-        drd->count2 = count;
462
-    }
463
-}
464
-
465
-/* In bytes per second */
466
-static int compute_datarate(DataRateData *drd, int64_t count)
467
-{
468
-    if (cur_time == drd->time1)
469
-        return 0;
470
-
471
-    return ((count - drd->count1) * 1000) / (cur_time - drd->time1);
472
-}
473
-
474
-
475
-static void start_children(FFStream *feed)
476
-{
477
-    if (no_launch)
478
-        return;
479
-
480
-    for (; feed; feed = feed->next) {
481
-        if (feed->child_argv && !feed->pid) {
482
-            feed->pid_start = time(0);
483
-
484
-            feed->pid = fork();
485
-
486
-            if (feed->pid < 0) {
487
-                http_log("Unable to create children\n");
488
-                exit(1);
489
-            }
490
-            if (!feed->pid) {
491
-                /* In child */
492
-                char pathname[1024];
493
-                char *slash;
494
-                int i;
495
-
496
-                av_strlcpy(pathname, my_program_name, sizeof(pathname));
497
-
498
-                slash = strrchr(pathname, '/');
499
-                if (!slash)
500
-                    slash = pathname;
501
-                else
502
-                    slash++;
503
-                strcpy(slash, "avconv");
504
-
505
-                http_log("Launch command line: ");
506
-                http_log("%s ", pathname);
507
-                for (i = 1; feed->child_argv[i] && feed->child_argv[i][0]; i++)
508
-                    http_log("%s ", feed->child_argv[i]);
509
-                http_log("\n");
510
-
511
-                for (i = 3; i < 256; i++)
512
-                    close(i);
513
-
514
-                if (!avserver_debug) {
515
-                    if (!freopen("/dev/null", "r", stdin))
516
-                        http_log("failed to redirect STDIN to /dev/null\n;");
517
-                    if (!freopen("/dev/null", "w", stdout))
518
-                        http_log("failed to redirect STDOUT to /dev/null\n;");
519
-                    if (!freopen("/dev/null", "w", stderr))
520
-                        http_log("failed to redirect STDERR to /dev/null\n;");
521
-                }
522
-
523
-                signal(SIGPIPE, SIG_DFL);
524
-
525
-                execvp(pathname, feed->child_argv);
526
-
527
-                _exit(1);
528
-            }
529
-        }
530
-    }
531
-}
532
-
533
-/* open a listening socket */
534
-static int socket_open_listen(struct sockaddr_in *my_addr)
535
-{
536
-    int server_fd, tmp;
537
-
538
-    server_fd = socket(AF_INET,SOCK_STREAM,0);
539
-    if (server_fd < 0) {
540
-        perror ("socket");
541
-        return -1;
542
-    }
543
-
544
-    tmp = 1;
545
-    setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp));
546
-
547
-    my_addr->sin_family = AF_INET;
548
-    if (bind (server_fd, (struct sockaddr *) my_addr, sizeof (*my_addr)) < 0) {
549
-        char bindmsg[32];
550
-        snprintf(bindmsg, sizeof(bindmsg), "bind(port %d)", ntohs(my_addr->sin_port));
551
-        perror (bindmsg);
552
-        closesocket(server_fd);
553
-        return -1;
554
-    }
555
-
556
-    if (listen (server_fd, 5) < 0) {
557
-        perror ("listen");
558
-        closesocket(server_fd);
559
-        return -1;
560
-    }
561
-    ff_socket_nonblock(server_fd, 1);
562
-
563
-    return server_fd;
564
-}
565
-
566
-/* start all multicast streams */
567
-static void start_multicast(void)
568
-{
569
-    FFStream *stream;
570
-    char session_id[32];
571
-    HTTPContext *rtp_c;
572
-    struct sockaddr_in dest_addr;
573
-    int default_port, stream_index;
574
-
575
-    default_port = 6000;
576
-    for(stream = first_stream; stream != NULL; stream = stream->next) {
577
-        if (stream->is_multicast) {
578
-            /* open the RTP connection */
579
-            snprintf(session_id, sizeof(session_id), "%08x%08x",
580
-                     av_lfg_get(&random_state), av_lfg_get(&random_state));
581
-
582
-            /* choose a port if none given */
583
-            if (stream->multicast_port == 0) {
584
-                stream->multicast_port = default_port;
585
-                default_port += 100;
586
-            }
587
-
588
-            dest_addr.sin_family = AF_INET;
589
-            dest_addr.sin_addr = stream->multicast_ip;
590
-            dest_addr.sin_port = htons(stream->multicast_port);
591
-
592
-            rtp_c = rtp_new_connection(&dest_addr, stream, session_id,
593
-                                       RTSP_LOWER_TRANSPORT_UDP_MULTICAST);
594
-            if (!rtp_c)
595
-                continue;
596
-
597
-            if (open_input_stream(rtp_c, "") < 0) {
598
-                http_log("Could not open input stream for stream '%s'\n",
599
-                         stream->filename);
600
-                continue;
601
-            }
602
-
603
-            /* open each RTP stream */
604
-            for(stream_index = 0; stream_index < stream->nb_streams;
605
-                stream_index++) {
606
-                dest_addr.sin_port = htons(stream->multicast_port +
607
-                                           2 * stream_index);
608
-                if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, NULL) < 0) {
609
-                    http_log("Could not open output stream '%s/streamid=%d'\n",
610
-                             stream->filename, stream_index);
611
-                    exit(1);
612
-                }
613
-            }
614
-
615
-            /* change state to send data */
616
-            rtp_c->state = HTTPSTATE_SEND_DATA;
617
-        }
618
-    }
619
-}
620
-
621
-/* main loop of the http server */
622
-static int http_server(void)
623
-{
624
-    int server_fd = 0, rtsp_server_fd = 0;
625
-    int ret, delay, delay1;
626
-    struct pollfd *poll_table, *poll_entry;
627
-    HTTPContext *c, *c_next;
628
-
629
-    if(!(poll_table = av_mallocz((nb_max_http_connections + 2)*sizeof(*poll_table)))) {
630
-        http_log("Impossible to allocate a poll table handling %d connections.\n", nb_max_http_connections);
631
-        return -1;
632
-    }
633
-
634
-    if (my_http_addr.sin_port) {
635
-        server_fd = socket_open_listen(&my_http_addr);
636
-        if (server_fd < 0)
637
-            return -1;
638
-    }
639
-
640
-    if (my_rtsp_addr.sin_port) {
641
-        rtsp_server_fd = socket_open_listen(&my_rtsp_addr);
642
-        if (rtsp_server_fd < 0)
643
-            return -1;
644
-    }
645
-
646
-    if (!rtsp_server_fd && !server_fd) {
647
-        http_log("HTTP and RTSP disabled.\n");
648
-        return -1;
649
-    }
650
-
651
-    http_log("AVserver started.\n");
652
-
653
-    start_children(first_feed);
654
-
655
-    start_multicast();
656
-
657
-    for(;;) {
658
-        poll_entry = poll_table;
659
-        if (server_fd) {
660
-            poll_entry->fd = server_fd;
661
-            poll_entry->events = POLLIN;
662
-            poll_entry++;
663
-        }
664
-        if (rtsp_server_fd) {
665
-            poll_entry->fd = rtsp_server_fd;
666
-            poll_entry->events = POLLIN;
667
-            poll_entry++;
668
-        }
669
-
670
-        /* wait for events on each HTTP handle */
671
-        c = first_http_ctx;
672
-        delay = 1000;
673
-        while (c != NULL) {
674
-            int fd;
675
-            fd = c->fd;
676
-            switch(c->state) {
677
-            case HTTPSTATE_SEND_HEADER:
678
-            case RTSPSTATE_SEND_REPLY:
679
-            case RTSPSTATE_SEND_PACKET:
680
-                c->poll_entry = poll_entry;
681
-                poll_entry->fd = fd;
682
-                poll_entry->events = POLLOUT;
683
-                poll_entry++;
684
-                break;
685
-            case HTTPSTATE_SEND_DATA_HEADER:
686
-            case HTTPSTATE_SEND_DATA:
687
-            case HTTPSTATE_SEND_DATA_TRAILER:
688
-                if (!c->is_packetized) {
689
-                    /* for TCP, we output as much as we can (may need to put a limit) */
690
-                    c->poll_entry = poll_entry;
691
-                    poll_entry->fd = fd;
692
-                    poll_entry->events = POLLOUT;
693
-                    poll_entry++;
694
-                } else {
695
-                    /* when avserver is doing the timing, we work by
696
-                       looking at which packet need to be sent every
697
-                       10 ms */
698
-                    delay1 = 10; /* one tick wait XXX: 10 ms assumed */
699
-                    if (delay1 < delay)
700
-                        delay = delay1;
701
-                }
702
-                break;
703
-            case HTTPSTATE_WAIT_REQUEST:
704
-            case HTTPSTATE_RECEIVE_DATA:
705
-            case HTTPSTATE_WAIT_FEED:
706
-            case RTSPSTATE_WAIT_REQUEST:
707
-                /* need to catch errors */
708
-                c->poll_entry = poll_entry;
709
-                poll_entry->fd = fd;
710
-                poll_entry->events = POLLIN;/* Maybe this will work */
711
-                poll_entry++;
712
-                break;
713
-            default:
714
-                c->poll_entry = NULL;
715
-                break;
716
-            }
717
-            c = c->next;
718
-        }
719
-
720
-        /* wait for an event on one connection. We poll at least every
721
-           second to handle timeouts */
722
-        do {
723
-            ret = poll(poll_table, poll_entry - poll_table, delay);
724
-            if (ret < 0 && ff_neterrno() != AVERROR(EAGAIN) &&
725
-                ff_neterrno() != AVERROR(EINTR))
726
-                return -1;
727
-        } while (ret < 0);
728
-
729
-        cur_time = av_gettime() / 1000;
730
-
731
-        if (need_to_start_children) {
732
-            need_to_start_children = 0;
733
-            start_children(first_feed);
734
-        }
735
-
736
-        /* now handle the events */
737
-        for(c = first_http_ctx; c != NULL; c = c_next) {
738
-            c_next = c->next;
739
-            if (handle_connection(c) < 0) {
740
-                /* close and free the connection */
741
-                log_connection(c);
742
-                close_connection(c);
743
-            }
744
-        }
745
-
746
-        poll_entry = poll_table;
747
-        if (server_fd) {
748
-            /* new HTTP connection request ? */
749
-            if (poll_entry->revents & POLLIN)
750
-                new_connection(server_fd, 0);
751
-            poll_entry++;
752
-        }
753
-        if (rtsp_server_fd) {
754
-            /* new RTSP connection request ? */
755
-            if (poll_entry->revents & POLLIN)
756
-                new_connection(rtsp_server_fd, 1);
757
-        }
758
-    }
759
-}
760
-
761
-/* start waiting for a new HTTP/RTSP request */
762
-static void start_wait_request(HTTPContext *c, int is_rtsp)
763
-{
764
-    c->buffer_ptr = c->buffer;
765
-    c->buffer_end = c->buffer + c->buffer_size - 1; /* leave room for '\0' */
766
-
767
-    if (is_rtsp) {
768
-        c->timeout = cur_time + RTSP_REQUEST_TIMEOUT;
769
-        c->state = RTSPSTATE_WAIT_REQUEST;
770
-    } else {
771
-        c->timeout = cur_time + HTTP_REQUEST_TIMEOUT;
772
-        c->state = HTTPSTATE_WAIT_REQUEST;
773
-    }
774
-}
775
-
776
-static void http_send_too_busy_reply(int fd)
777
-{
778
-    char buffer[300];
779
-    int len = snprintf(buffer, sizeof(buffer),
780
-                       "HTTP/1.0 503 Server too busy\r\n"
781
-                       "Content-type: text/html\r\n"
782
-                       "\r\n"
783
-                       "<html><head><title>Too busy</title></head><body>\r\n"
784
-                       "<p>The server is too busy to serve your request at this time.</p>\r\n"
785
-                       "<p>The number of current connections is %d, and this exceeds the limit of %d.</p>\r\n"
786
-                       "</body></html>\r\n",
787
-                       nb_connections, nb_max_connections);
788
-    send(fd, buffer, len, 0);
789
-}
790
-
791
-
792
-static void new_connection(int server_fd, int is_rtsp)
793
-{
794
-    struct sockaddr_in from_addr;
795
-    socklen_t len;
796
-    int fd;
797
-    HTTPContext *c = NULL;
798
-
799
-    len = sizeof(from_addr);
800
-    fd = accept(server_fd, (struct sockaddr *)&from_addr,
801
-                &len);
802
-    if (fd < 0) {
803
-        http_log("error during accept %s\n", strerror(errno));
804
-        return;
805
-    }
806
-    ff_socket_nonblock(fd, 1);
807
-
808
-    if (nb_connections >= nb_max_connections) {
809
-        http_send_too_busy_reply(fd);
810
-        goto fail;
811
-    }
812
-
813
-    /* add a new connection */
814
-    c = av_mallocz(sizeof(HTTPContext));
815
-    if (!c)
816
-        goto fail;
817
-
818
-    c->fd = fd;
819
-    c->poll_entry = NULL;
820
-    c->from_addr = from_addr;
821
-    c->buffer_size = IOBUFFER_INIT_SIZE;
822
-    c->buffer = av_malloc(c->buffer_size);
823
-    if (!c->buffer)
824
-        goto fail;
825
-
826
-    c->next = first_http_ctx;
827
-    first_http_ctx = c;
828
-    nb_connections++;
829
-
830
-    start_wait_request(c, is_rtsp);
831
-
832
-    return;
833
-
834
- fail:
835
-    if (c) {
836
-        av_free(c->buffer);
837
-        av_free(c);
838
-    }
839
-    closesocket(fd);
840
-}
841
-
842
-static void close_connection(HTTPContext *c)
843
-{
844
-    HTTPContext **cp, *c1;
845
-    int i, nb_streams;
846
-    AVFormatContext *ctx;
847
-    URLContext *h;
848
-    AVStream *st;
849
-
850
-    /* remove connection from list */
851
-    cp = &first_http_ctx;
852
-    while ((*cp) != NULL) {
853
-        c1 = *cp;
854
-        if (c1 == c)
855
-            *cp = c->next;
856
-        else
857
-            cp = &c1->next;
858
-    }
859
-
860
-    /* remove references, if any (XXX: do it faster) */
861
-    for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
862
-        if (c1->rtsp_c == c)
863
-            c1->rtsp_c = NULL;
864
-    }
865
-
866
-    /* remove connection associated resources */
867
-    if (c->fd >= 0)
868
-        closesocket(c->fd);
869
-    if (c->fmt_in) {
870
-        /* close each frame parser */
871
-        for(i=0;i<c->fmt_in->nb_streams;i++) {
872
-            st = c->fmt_in->streams[i];
873
-            if (st->codec->codec)
874
-                avcodec_close(st->codec);
875
-        }
876
-        avformat_close_input(&c->fmt_in);
877
-    }
878
-
879
-    /* free RTP output streams if any */
880
-    nb_streams = 0;
881
-    if (c->stream)
882
-        nb_streams = c->stream->nb_streams;
883
-
884
-    for(i=0;i<nb_streams;i++) {
885
-        ctx = c->rtp_ctx[i];
886
-        if (ctx) {
887
-            av_write_trailer(ctx);
888
-            av_dict_free(&ctx->metadata);
889
-            av_free(ctx->streams[0]);
890
-            av_free(ctx);
891
-        }
892
-        h = c->rtp_handles[i];
893
-        if (h)
894
-            ffurl_close(h);
895
-    }
896
-
897
-    ctx = &c->fmt_ctx;
898
-
899
-    if (!c->last_packet_sent && c->state == HTTPSTATE_SEND_DATA_TRAILER) {
900
-        if (ctx->oformat) {
901
-            /* prepare header */
902
-            if (avio_open_dyn_buf(&ctx->pb) >= 0) {
903
-                av_write_trailer(ctx);
904
-                av_freep(&c->pb_buffer);
905
-                avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
906
-            }
907
-        }
908
-    }
909
-
910
-    for(i=0; i<ctx->nb_streams; i++)
911
-        av_free(ctx->streams[i]);
912
-
913
-    if (c->stream && !c->post && c->stream->stream_type == STREAM_TYPE_LIVE)
914
-        current_bandwidth -= c->stream->bandwidth;
915
-
916
-    /* signal that there is no feed if we are the feeder socket */
917
-    if (c->state == HTTPSTATE_RECEIVE_DATA && c->stream) {
918
-        c->stream->feed_opened = 0;
919
-        close(c->feed_fd);
920
-    }
921
-
922
-    av_freep(&c->pb_buffer);
923
-    av_freep(&c->packet_buffer);
924
-    av_free(c->buffer);
925
-    av_free(c);
926
-    nb_connections--;
927
-}
928
-
929
-static int handle_connection(HTTPContext *c)
930
-{
931
-    int len, ret;
932
-
933
-    switch(c->state) {
934
-    case HTTPSTATE_WAIT_REQUEST:
935
-    case RTSPSTATE_WAIT_REQUEST:
936
-        /* timeout ? */
937
-        if ((c->timeout - cur_time) < 0)
938
-            return -1;
939
-        if (c->poll_entry->revents & (POLLERR | POLLHUP))
940
-            return -1;
941
-
942
-        /* no need to read if no events */
943
-        if (!(c->poll_entry->revents & POLLIN))
944
-            return 0;
945
-        /* read the data */
946
-    read_loop:
947
-        len = recv(c->fd, c->buffer_ptr, 1, 0);
948
-        if (len < 0) {
949
-            if (ff_neterrno() != AVERROR(EAGAIN) &&
950
-                ff_neterrno() != AVERROR(EINTR))
951
-                return -1;
952
-        } else if (len == 0) {
953
-            return -1;
954
-        } else {
955
-            /* search for end of request. */
956
-            uint8_t *ptr;
957
-            c->buffer_ptr += len;
958
-            ptr = c->buffer_ptr;
959
-            if ((ptr >= c->buffer + 2 && !memcmp(ptr-2, "\n\n", 2)) ||
960
-                (ptr >= c->buffer + 4 && !memcmp(ptr-4, "\r\n\r\n", 4))) {
961
-                /* request found : parse it and reply */
962
-                if (c->state == HTTPSTATE_WAIT_REQUEST) {
963
-                    ret = http_parse_request(c);
964
-                } else {
965
-                    ret = rtsp_parse_request(c);
966
-                }
967
-                if (ret < 0)
968
-                    return -1;
969
-            } else if (ptr >= c->buffer_end) {
970
-                /* request too long: cannot do anything */
971
-                return -1;
972
-            } else goto read_loop;
973
-        }
974
-        break;
975
-
976
-    case HTTPSTATE_SEND_HEADER:
977
-        if (c->poll_entry->revents & (POLLERR | POLLHUP))
978
-            return -1;
979
-
980
-        /* no need to write if no events */
981
-        if (!(c->poll_entry->revents & POLLOUT))
982
-            return 0;
983
-        len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
984
-        if (len < 0) {
985
-            if (ff_neterrno() != AVERROR(EAGAIN) &&
986
-                ff_neterrno() != AVERROR(EINTR)) {
987
-                /* error : close connection */
988
-                av_freep(&c->pb_buffer);
989
-                return -1;
990
-            }
991
-        } else {
992
-            c->buffer_ptr += len;
993
-            if (c->stream)
994
-                c->stream->bytes_served += len;
995
-            c->data_count += len;
996
-            if (c->buffer_ptr >= c->buffer_end) {
997
-                av_freep(&c->pb_buffer);
998
-                /* if error, exit */
999
-                if (c->http_error)
1000
-                    return -1;
1001
-                /* all the buffer was sent : synchronize to the incoming stream */
1002
-                c->state = HTTPSTATE_SEND_DATA_HEADER;
1003
-                c->buffer_ptr = c->buffer_end = c->buffer;
1004
-            }
1005
-        }
1006
-        break;
1007
-
1008
-    case HTTPSTATE_SEND_DATA:
1009
-    case HTTPSTATE_SEND_DATA_HEADER:
1010
-    case HTTPSTATE_SEND_DATA_TRAILER:
1011
-        /* for packetized output, we consider we can always write (the
1012
-           input streams sets the speed). It may be better to verify
1013
-           that we do not rely too much on the kernel queues */
1014
-        if (!c->is_packetized) {
1015
-            if (c->poll_entry->revents & (POLLERR | POLLHUP))
1016
-                return -1;
1017
-
1018
-            /* no need to read if no events */
1019
-            if (!(c->poll_entry->revents & POLLOUT))
1020
-                return 0;
1021
-        }
1022
-        if (http_send_data(c) < 0)
1023
-            return -1;
1024
-        /* close connection if trailer sent */
1025
-        if (c->state == HTTPSTATE_SEND_DATA_TRAILER)
1026
-            return -1;
1027
-        break;
1028
-    case HTTPSTATE_RECEIVE_DATA:
1029
-        /* no need to read if no events */
1030
-        if (c->poll_entry->revents & (POLLERR | POLLHUP))
1031
-            return -1;
1032
-        if (!(c->poll_entry->revents & POLLIN))
1033
-            return 0;
1034
-        if (http_receive_data(c) < 0)
1035
-            return -1;
1036
-        break;
1037
-    case HTTPSTATE_WAIT_FEED:
1038
-        /* no need to read if no events */
1039
-        if (c->poll_entry->revents & (POLLIN | POLLERR | POLLHUP))
1040
-            return -1;
1041
-
1042
-        /* nothing to do, we'll be waken up by incoming feed packets */
1043
-        break;
1044
-
1045
-    case RTSPSTATE_SEND_REPLY:
1046
-        if (c->poll_entry->revents & (POLLERR | POLLHUP)) {
1047
-            av_freep(&c->pb_buffer);
1048
-            return -1;
1049
-        }
1050
-        /* no need to write if no events */
1051
-        if (!(c->poll_entry->revents & POLLOUT))
1052
-            return 0;
1053
-        len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
1054
-        if (len < 0) {
1055
-            if (ff_neterrno() != AVERROR(EAGAIN) &&
1056
-                ff_neterrno() != AVERROR(EINTR)) {
1057
-                /* error : close connection */
1058
-                av_freep(&c->pb_buffer);
1059
-                return -1;
1060
-            }
1061
-        } else {
1062
-            c->buffer_ptr += len;
1063
-            c->data_count += len;
1064
-            if (c->buffer_ptr >= c->buffer_end) {
1065
-                /* all the buffer was sent : wait for a new request */
1066
-                av_freep(&c->pb_buffer);
1067
-                start_wait_request(c, 1);
1068
-            }
1069
-        }
1070
-        break;
1071
-    case RTSPSTATE_SEND_PACKET:
1072
-        if (c->poll_entry->revents & (POLLERR | POLLHUP)) {
1073
-            av_freep(&c->packet_buffer);
1074
-            return -1;
1075
-        }
1076
-        /* no need to write if no events */
1077
-        if (!(c->poll_entry->revents & POLLOUT))
1078
-            return 0;
1079
-        len = send(c->fd, c->packet_buffer_ptr,
1080
-                    c->packet_buffer_end - c->packet_buffer_ptr, 0);
1081
-        if (len < 0) {
1082
-            if (ff_neterrno() != AVERROR(EAGAIN) &&
1083
-                ff_neterrno() != AVERROR(EINTR)) {
1084
-                /* error : close connection */
1085
-                av_freep(&c->packet_buffer);
1086
-                return -1;
1087
-            }
1088
-        } else {
1089
-            c->packet_buffer_ptr += len;
1090
-            if (c->packet_buffer_ptr >= c->packet_buffer_end) {
1091
-                /* all the buffer was sent : wait for a new request */
1092
-                av_freep(&c->packet_buffer);
1093
-                c->state = RTSPSTATE_WAIT_REQUEST;
1094
-            }
1095
-        }
1096
-        break;
1097
-    case HTTPSTATE_READY:
1098
-        /* nothing to do */
1099
-        break;
1100
-    default:
1101
-        return -1;
1102
-    }
1103
-    return 0;
1104
-}
1105
-
1106
-static int extract_rates(char *rates, int ratelen, const char *request)
1107
-{
1108
-    const char *p;
1109
-
1110
-    for (p = request; *p && *p != '\r' && *p != '\n'; ) {
1111
-        if (av_strncasecmp(p, "Pragma:", 7) == 0) {
1112
-            const char *q = p + 7;
1113
-
1114
-            while (*q && *q != '\n' && av_isspace(*q))
1115
-                q++;
1116
-
1117
-            if (av_strncasecmp(q, "stream-switch-entry=", 20) == 0) {
1118
-                int stream_no;
1119
-                int rate_no;
1120
-
1121
-                q += 20;
1122
-
1123
-                memset(rates, 0xff, ratelen);
1124
-
1125
-                while (1) {
1126
-                    while (*q && *q != '\n' && *q != ':')
1127
-                        q++;
1128
-
1129
-                    if (sscanf(q, ":%d:%d", &stream_no, &rate_no) != 2)
1130
-                        break;
1131
-
1132
-                    stream_no--;
1133
-                    if (stream_no < ratelen && stream_no >= 0)
1134
-                        rates[stream_no] = rate_no;
1135
-
1136
-                    while (*q && *q != '\n' && !av_isspace(*q))
1137
-                        q++;
1138
-                }
1139
-
1140
-                return 1;
1141
-            }
1142
-        }
1143
-        p = strchr(p, '\n');
1144
-        if (!p)
1145
-            break;
1146
-
1147
-        p++;
1148
-    }
1149
-
1150
-    return 0;
1151
-}
1152
-
1153
-static int find_stream_in_feed(FFStream *feed, AVCodecContext *codec, int bit_rate)
1154
-{
1155
-    int i;
1156
-    int best_bitrate = 100000000;
1157
-    int best = -1;
1158
-
1159
-    for (i = 0; i < feed->nb_streams; i++) {
1160
-        AVCodecContext *feed_codec = feed->streams[i]->codec;
1161
-
1162
-        if (feed_codec->codec_id != codec->codec_id ||
1163
-            feed_codec->sample_rate != codec->sample_rate ||
1164
-            feed_codec->width != codec->width ||
1165
-            feed_codec->height != codec->height)
1166
-            continue;
1167
-
1168
-        /* Potential stream */
1169
-
1170
-        /* We want the fastest stream less than bit_rate, or the slowest
1171
-         * faster than bit_rate
1172
-         */
1173
-
1174
-        if (feed_codec->bit_rate <= bit_rate) {
1175
-            if (best_bitrate > bit_rate || feed_codec->bit_rate > best_bitrate) {
1176
-                best_bitrate = feed_codec->bit_rate;
1177
-                best = i;
1178
-            }
1179
-        } else {
1180
-            if (feed_codec->bit_rate < best_bitrate) {
1181
-                best_bitrate = feed_codec->bit_rate;
1182
-                best = i;
1183
-            }
1184
-        }
1185
-    }
1186
-
1187
-    return best;
1188
-}
1189
-
1190
-static int modify_current_stream(HTTPContext *c, char *rates)
1191
-{
1192
-    int i;
1193
-    FFStream *req = c->stream;
1194
-    int action_required = 0;
1195
-
1196
-    /* Not much we can do for a feed */
1197
-    if (!req->feed)
1198
-        return 0;
1199
-
1200
-    for (i = 0; i < req->nb_streams; i++) {
1201
-        AVCodecContext *codec = req->streams[i]->codec;
1202
-
1203
-        switch(rates[i]) {
1204
-            case 0:
1205
-                c->switch_feed_streams[i] = req->feed_streams[i];
1206
-                break;
1207
-            case 1:
1208
-                c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 2);
1209
-                break;
1210
-            case 2:
1211
-                /* Wants off or slow */
1212
-                c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 4);
1213
-#ifdef WANTS_OFF
1214
-                /* This doesn't work well when it turns off the only stream! */
1215
-                c->switch_feed_streams[i] = -2;
1216
-                c->feed_streams[i] = -2;
1217
-#endif
1218
-                break;
1219
-        }
1220
-
1221
-        if (c->switch_feed_streams[i] >= 0 && c->switch_feed_streams[i] != c->feed_streams[i])
1222
-            action_required = 1;
1223
-    }
1224
-
1225
-    return action_required;
1226
-}
1227
-
1228
-/* XXX: factorize in utils.c ? */
1229
-/* XXX: take care with different space meaning */
1230
-static void skip_spaces(const char **pp)
1231
-{
1232
-    const char *p;
1233
-    p = *pp;
1234
-    while (*p == ' ' || *p == '\t')
1235
-        p++;
1236
-    *pp = p;
1237
-}
1238
-
1239
-static void get_word(char *buf, int buf_size, const char **pp)
1240
-{
1241
-    const char *p;
1242
-    char *q;
1243
-
1244
-    p = *pp;
1245
-    skip_spaces(&p);
1246
-    q = buf;
1247
-    while (!av_isspace(*p) && *p != '\0') {
1248
-        if ((q - buf) < buf_size - 1)
1249
-            *q++ = *p;
1250
-        p++;
1251
-    }
1252
-    if (buf_size > 0)
1253
-        *q = '\0';
1254
-    *pp = p;
1255
-}
1256
-
1257
-static void get_arg(char *buf, int buf_size, const char **pp)
1258
-{
1259
-    const char *p;
1260
-    char *q;
1261
-    int quote;
1262
-
1263
-    p = *pp;
1264
-    while (av_isspace(*p)) p++;
1265
-    q = buf;
1266
-    quote = 0;
1267
-    if (*p == '\"' || *p == '\'')
1268
-        quote = *p++;
1269
-    for(;;) {
1270
-        if (quote) {
1271
-            if (*p == quote)
1272
-                break;
1273
-        } else {
1274
-            if (av_isspace(*p))
1275
-                break;
1276
-        }
1277
-        if (*p == '\0')
1278
-            break;
1279
-        if ((q - buf) < buf_size - 1)
1280
-            *q++ = *p;
1281
-        p++;
1282
-    }
1283
-    *q = '\0';
1284
-    if (quote && *p == quote)
1285
-        p++;
1286
-    *pp = p;
1287
-}
1288
-
1289
-static void parse_acl_row(FFStream *stream, FFStream* feed, IPAddressACL *ext_acl,
1290
-                         const char *p, const char *filename, int line_num)
1291
-{
1292
-    char arg[1024];
1293
-    IPAddressACL acl;
1294
-    int errors = 0;
1295
-
1296
-    get_arg(arg, sizeof(arg), &p);
1297
-    if (av_strcasecmp(arg, "allow") == 0)
1298
-        acl.action = IP_ALLOW;
1299
-    else if (av_strcasecmp(arg, "deny") == 0)
1300
-        acl.action = IP_DENY;
1301
-    else {
1302
-        fprintf(stderr, "%s:%d: ACL action '%s' is not ALLOW or DENY\n",
1303
-                filename, line_num, arg);
1304
-        errors++;
1305
-    }
1306
-
1307
-    get_arg(arg, sizeof(arg), &p);
1308
-
1309
-    if (resolve_host(&acl.first, arg) != 0) {
1310
-        fprintf(stderr, "%s:%d: ACL refers to invalid host or ip address '%s'\n",
1311
-                filename, line_num, arg);
1312
-        errors++;
1313
-    } else
1314
-        acl.last = acl.first;
1315
-
1316
-    get_arg(arg, sizeof(arg), &p);
1317
-
1318
-    if (arg[0]) {
1319
-        if (resolve_host(&acl.last, arg) != 0) {
1320
-            fprintf(stderr, "%s:%d: ACL refers to invalid host or ip address '%s'\n",
1321
-                    filename, line_num, arg);
1322
-            errors++;
1323
-        }
1324
-    }
1325
-
1326
-    if (!errors) {
1327
-        IPAddressACL *nacl = av_mallocz(sizeof(*nacl));
1328
-        IPAddressACL **naclp = 0;
1329
-
1330
-        acl.next = 0;
1331
-        *nacl = acl;
1332
-
1333
-        if (stream)
1334
-            naclp = &stream->acl;
1335
-        else if (feed)
1336
-            naclp = &feed->acl;
1337
-        else if (ext_acl)
1338
-            naclp = &ext_acl;
1339
-        else {
1340
-            fprintf(stderr, "%s:%d: ACL found not in <stream> or <feed>\n",
1341
-                    filename, line_num);
1342
-            errors++;
1343
-        }
1344
-
1345
-        if (naclp) {
1346
-            while (*naclp)
1347
-                naclp = &(*naclp)->next;
1348
-
1349
-            *naclp = nacl;
1350
-        }
1351
-    }
1352
-}
1353
-
1354
-
1355
-static IPAddressACL* parse_dynamic_acl(FFStream *stream, HTTPContext *c)
1356
-{
1357
-    FILE* f;
1358
-    char line[1024];
1359
-    char  cmd[1024];
1360
-    IPAddressACL *acl = NULL;
1361
-    int line_num = 0;
1362
-    const char *p;
1363
-
1364
-    f = fopen(stream->dynamic_acl, "r");
1365
-    if (!f) {
1366
-        perror(stream->dynamic_acl);
1367
-        return NULL;
1368
-    }
1369
-
1370
-    acl = av_mallocz(sizeof(IPAddressACL));
1371
-
1372
-    /* Build ACL */
1373
-    for(;;) {
1374
-        if (fgets(line, sizeof(line), f) == NULL)
1375
-            break;
1376
-        line_num++;
1377
-        p = line;
1378
-        while (av_isspace(*p))
1379
-            p++;
1380
-        if (*p == '\0' || *p == '#')
1381
-            continue;
1382
-        get_arg(cmd, sizeof(cmd), &p);
1383
-
1384
-        if (!av_strcasecmp(cmd, "ACL"))
1385
-            parse_acl_row(NULL, NULL, acl, p, stream->dynamic_acl, line_num);
1386
-    }
1387
-    fclose(f);
1388
-    return acl;
1389
-}
1390
-
1391
-
1392
-static void free_acl_list(IPAddressACL *in_acl)
1393
-{
1394
-    IPAddressACL *pacl,*pacl2;
1395
-
1396
-    pacl = in_acl;
1397
-    while(pacl) {
1398
-        pacl2 = pacl;
1399
-        pacl = pacl->next;
1400
-        av_freep(pacl2);
1401
-    }
1402
-}
1403
-
1404
-static int validate_acl_list(IPAddressACL *in_acl, HTTPContext *c)
1405
-{
1406
-    enum IPAddressAction last_action = IP_DENY;
1407
-    IPAddressACL *acl;
1408
-    struct in_addr *src = &c->from_addr.sin_addr;
1409
-    unsigned long src_addr = src->s_addr;
1410
-
1411
-    for (acl = in_acl; acl; acl = acl->next) {
1412
-        if (src_addr >= acl->first.s_addr && src_addr <= acl->last.s_addr)
1413
-            return (acl->action == IP_ALLOW) ? 1 : 0;
1414
-        last_action = acl->action;
1415
-    }
1416
-
1417
-    /* Nothing matched, so return not the last action */
1418
-    return (last_action == IP_DENY) ? 1 : 0;
1419
-}
1420
-
1421
-static int validate_acl(FFStream *stream, HTTPContext *c)
1422
-{
1423
-    int ret = 0;
1424
-    IPAddressACL *acl;
1425
-
1426
-
1427
-    /* if stream->acl is null validate_acl_list will return 1 */
1428
-    ret = validate_acl_list(stream->acl, c);
1429
-
1430
-    if (stream->dynamic_acl[0]) {
1431
-        acl = parse_dynamic_acl(stream, c);
1432
-
1433
-        ret = validate_acl_list(acl, c);
1434
-
1435
-        free_acl_list(acl);
1436
-    }
1437
-
1438
-    return ret;
1439
-}
1440
-
1441
-/* compute the real filename of a file by matching it without its
1442
-   extensions to all the stream filenames */
1443
-static void compute_real_filename(char *filename, int max_size)
1444
-{
1445
-    char file1[1024];
1446
-    char file2[1024];
1447
-    char *p;
1448
-    FFStream *stream;
1449
-
1450
-    /* compute filename by matching without the file extensions */
1451
-    av_strlcpy(file1, filename, sizeof(file1));
1452
-    p = strrchr(file1, '.');
1453
-    if (p)
1454
-        *p = '\0';
1455
-    for(stream = first_stream; stream != NULL; stream = stream->next) {
1456
-        av_strlcpy(file2, stream->filename, sizeof(file2));
1457
-        p = strrchr(file2, '.');
1458
-        if (p)
1459
-            *p = '\0';
1460
-        if (!strcmp(file1, file2)) {
1461
-            av_strlcpy(filename, stream->filename, max_size);
1462
-            break;
1463
-        }
1464
-    }
1465
-}
1466
-
1467
-enum RedirType {
1468
-    REDIR_NONE,
1469
-    REDIR_ASX,
1470
-    REDIR_RAM,
1471
-    REDIR_ASF,
1472
-    REDIR_RTSP,
1473
-    REDIR_SDP,
1474
-};
1475
-
1476
-/* parse http request and prepare header */
1477
-static int http_parse_request(HTTPContext *c)
1478
-{
1479
-    const char *p;
1480
-    char *p1;
1481
-    enum RedirType redir_type;
1482
-    char cmd[32];
1483
-    char info[1024], filename[1024];
1484
-    char url[1024], *q;
1485
-    char protocol[32];
1486
-    char msg[1024];
1487
-    const char *mime_type;
1488
-    FFStream *stream;
1489
-    int i;
1490
-    char ratebuf[32];
1491
-    const char *useragent = 0;
1492
-
1493
-    p = c->buffer;
1494
-    get_word(cmd, sizeof(cmd), &p);
1495
-    av_strlcpy(c->method, cmd, sizeof(c->method));
1496
-
1497
-    if (!strcmp(cmd, "GET"))
1498
-        c->post = 0;
1499
-    else if (!strcmp(cmd, "POST"))
1500
-        c->post = 1;
1501
-    else
1502
-        return -1;
1503
-
1504
-    get_word(url, sizeof(url), &p);
1505
-    av_strlcpy(c->url, url, sizeof(c->url));
1506
-
1507
-    get_word(protocol, sizeof(protocol), (const char **)&p);
1508
-    if (strcmp(protocol, "HTTP/1.0") && strcmp(protocol, "HTTP/1.1"))
1509
-        return -1;
1510
-
1511
-    av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
1512
-
1513
-    if (avserver_debug)
1514
-        http_log("%s - - New connection: %s %s\n", inet_ntoa(c->from_addr.sin_addr), cmd, url);
1515
-
1516
-    /* find the filename and the optional info string in the request */
1517
-    p1 = strchr(url, '?');
1518
-    if (p1) {
1519
-        av_strlcpy(info, p1, sizeof(info));
1520
-        *p1 = '\0';
1521
-    } else
1522
-        info[0] = '\0';
1523
-
1524
-    av_strlcpy(filename, url + ((*url == '/') ? 1 : 0), sizeof(filename)-1);
1525
-
1526
-    for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1527
-        if (av_strncasecmp(p, "User-Agent:", 11) == 0) {
1528
-            useragent = p + 11;
1529
-            if (*useragent && *useragent != '\n' && av_isspace(*useragent))
1530
-                useragent++;
1531
-            break;
1532
-        }
1533
-        p = strchr(p, '\n');
1534
-        if (!p)
1535
-            break;
1536
-
1537
-        p++;
1538
-    }
1539
-
1540
-    redir_type = REDIR_NONE;
1541
-    if (av_match_ext(filename, "asx")) {
1542
-        redir_type = REDIR_ASX;
1543
-        filename[strlen(filename)-1] = 'f';
1544
-    } else if (av_match_ext(filename, "asf") &&
1545
-        (!useragent || av_strncasecmp(useragent, "NSPlayer", 8) != 0)) {
1546
-        /* if this isn't WMP or lookalike, return the redirector file */
1547
-        redir_type = REDIR_ASF;
1548
-    } else if (av_match_ext(filename, "rpm,ram")) {
1549
-        redir_type = REDIR_RAM;
1550
-        strcpy(filename + strlen(filename)-2, "m");
1551
-    } else if (av_match_ext(filename, "rtsp")) {
1552
-        redir_type = REDIR_RTSP;
1553
-        compute_real_filename(filename, sizeof(filename) - 1);
1554
-    } else if (av_match_ext(filename, "sdp")) {
1555
-        redir_type = REDIR_SDP;
1556
-        compute_real_filename(filename, sizeof(filename) - 1);
1557
-    }
1558
-
1559
-    // "redirect" / request to index.html
1560
-    if (!strlen(filename))
1561
-        av_strlcpy(filename, "index.html", sizeof(filename) - 1);
1562
-
1563
-    stream = first_stream;
1564
-    while (stream != NULL) {
1565
-        if (!strcmp(stream->filename, filename) && validate_acl(stream, c))
1566
-            break;
1567
-        stream = stream->next;
1568
-    }
1569
-    if (stream == NULL) {
1570
-        snprintf(msg, sizeof(msg), "File '%s' not found", url);
1571
-        http_log("File '%s' not found\n", url);
1572
-        goto send_error;
1573
-    }
1574
-
1575
-    c->stream = stream;
1576
-    memcpy(c->feed_streams, stream->feed_streams, sizeof(c->feed_streams));
1577
-    memset(c->switch_feed_streams, -1, sizeof(c->switch_feed_streams));
1578
-
1579
-    if (stream->stream_type == STREAM_TYPE_REDIRECT) {
1580
-        c->http_error = 301;
1581
-        q = c->buffer;
1582
-        q += snprintf(q, c->buffer_size,
1583
-                      "HTTP/1.0 301 Moved\r\n"
1584
-                      "Location: %s\r\n"
1585
-                      "Content-type: text/html\r\n"
1586
-                      "\r\n"
1587
-                      "<html><head><title>Moved</title></head><body>\r\n"
1588
-                      "You should be <a href=\"%s\">redirected</a>.\r\n"
1589
-                      "</body></html>\r\n", stream->feed_filename, stream->feed_filename);
1590
-        /* prepare output buffer */
1591
-        c->buffer_ptr = c->buffer;
1592
-        c->buffer_end = q;
1593
-        c->state = HTTPSTATE_SEND_HEADER;
1594
-        return 0;
1595
-    }
1596
-
1597
-    /* If this is WMP, get the rate information */
1598
-    if (extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
1599
-        if (modify_current_stream(c, ratebuf)) {
1600
-            for (i = 0; i < FF_ARRAY_ELEMS(c->feed_streams); i++) {
1601
-                if (c->switch_feed_streams[i] >= 0)
1602
-                    c->switch_feed_streams[i] = -1;
1603
-            }
1604
-        }
1605
-    }
1606
-
1607
-    if (c->post == 0 && stream->stream_type == STREAM_TYPE_LIVE)
1608
-        current_bandwidth += stream->bandwidth;
1609
-
1610
-    /* If already streaming this feed, do not let start another feeder. */
1611
-    if (stream->feed_opened) {
1612
-        snprintf(msg, sizeof(msg), "This feed is already being received.");
1613
-        http_log("Feed '%s' already being received\n", stream->feed_filename);
1614
-        goto send_error;
1615
-    }
1616
-
1617
-    if (c->post == 0 && max_bandwidth < current_bandwidth) {
1618
-        c->http_error = 503;
1619
-        q = c->buffer;
1620
-        q += snprintf(q, c->buffer_size,
1621
-                      "HTTP/1.0 503 Server too busy\r\n"
1622
-                      "Content-type: text/html\r\n"
1623
-                      "\r\n"
1624
-                      "<html><head><title>Too busy</title></head><body>\r\n"
1625
-                      "<p>The server is too busy to serve your request at this time.</p>\r\n"
1626
-                      "<p>The bandwidth being served (including your stream) is %"PRIu64"kbit/sec, "
1627
-                      "and this exceeds the limit of %"PRIu64"kbit/sec.</p>\r\n"
1628
-                      "</body></html>\r\n", current_bandwidth, max_bandwidth);
1629
-        /* prepare output buffer */
1630
-        c->buffer_ptr = c->buffer;
1631
-        c->buffer_end = q;
1632
-        c->state = HTTPSTATE_SEND_HEADER;
1633
-        return 0;
1634
-    }
1635
-
1636
-    if (redir_type != REDIR_NONE) {
1637
-        const char *hostinfo = 0;
1638
-
1639
-        for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1640
-            if (av_strncasecmp(p, "Host:", 5) == 0) {
1641
-                hostinfo = p + 5;
1642
-                break;
1643
-            }
1644
-            p = strchr(p, '\n');
1645
-            if (!p)
1646
-                break;
1647
-
1648
-            p++;
1649
-        }
1650
-
1651
-        if (hostinfo) {
1652
-            char *eoh;
1653
-            char hostbuf[260];
1654
-
1655
-            while (av_isspace(*hostinfo))
1656
-                hostinfo++;
1657
-
1658
-            eoh = strchr(hostinfo, '\n');
1659
-            if (eoh) {
1660
-                if (eoh[-1] == '\r')
1661
-                    eoh--;
1662
-
1663
-                if (eoh - hostinfo < sizeof(hostbuf) - 1) {
1664
-                    memcpy(hostbuf, hostinfo, eoh - hostinfo);
1665
-                    hostbuf[eoh - hostinfo] = 0;
1666
-
1667
-                    c->http_error = 200;
1668
-                    q = c->buffer;
1669
-                    switch(redir_type) {
1670
-                    case REDIR_ASX:
1671
-                        q += snprintf(q, c->buffer_size,
1672
-                                      "HTTP/1.0 200 ASX Follows\r\n"
1673
-                                      "Content-type: video/x-ms-asf\r\n"
1674
-                                      "\r\n"
1675
-                                      "<ASX Version=\"3\">\r\n"
1676
-                                      //"<!-- Autogenerated by avserver -->\r\n"
1677
-                                      "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n"
1678
-                                      "</ASX>\r\n", hostbuf, filename, info);
1679
-                        break;
1680
-                    case REDIR_RAM:
1681
-                        q += snprintf(q, c->buffer_size,
1682
-                                      "HTTP/1.0 200 RAM Follows\r\n"
1683
-                                      "Content-type: audio/x-pn-realaudio\r\n"
1684
-                                      "\r\n"
1685
-                                      "# Autogenerated by avserver\r\n"
1686
-                                      "http://%s/%s%s\r\n", hostbuf, filename, info);
1687
-                        break;
1688
-                    case REDIR_ASF:
1689
-                        q += snprintf(q, c->buffer_size,
1690
-                                      "HTTP/1.0 200 ASF Redirect follows\r\n"
1691
-                                      "Content-type: video/x-ms-asf\r\n"
1692
-                                      "\r\n"
1693
-                                      "[Reference]\r\n"
1694
-                                      "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info);
1695
-                        break;
1696
-                    case REDIR_RTSP:
1697
-                        {
1698
-                            char hostname[256], *p;
1699
-                            /* extract only hostname */
1700
-                            av_strlcpy(hostname, hostbuf, sizeof(hostname));
1701
-                            p = strrchr(hostname, ':');
1702
-                            if (p)
1703
-                                *p = '\0';
1704
-                            q += snprintf(q, c->buffer_size,
1705
-                                          "HTTP/1.0 200 RTSP Redirect follows\r\n"
1706
-                                          /* XXX: incorrect mime type ? */
1707
-                                          "Content-type: application/x-rtsp\r\n"
1708
-                                          "\r\n"
1709
-                                          "rtsp://%s:%d/%s\r\n", hostname, ntohs(my_rtsp_addr.sin_port), filename);
1710
-                        }
1711
-                        break;
1712
-                    case REDIR_SDP:
1713
-                        {
1714
-                            uint8_t *sdp_data;
1715
-                            int sdp_data_size;
1716
-                            socklen_t len;
1717
-                            struct sockaddr_in my_addr;
1718
-
1719
-                            q += snprintf(q, c->buffer_size,
1720
-                                          "HTTP/1.0 200 OK\r\n"
1721
-                                          "Content-type: application/sdp\r\n"
1722
-                                          "\r\n");
1723
-
1724
-                            len = sizeof(my_addr);
1725
-                            getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
1726
-
1727
-                            /* XXX: should use a dynamic buffer */
1728
-                            sdp_data_size = prepare_sdp_description(stream,
1729
-                                                                    &sdp_data,
1730
-                                                                    my_addr.sin_addr);
1731
-                            if (sdp_data_size > 0) {
1732
-                                memcpy(q, sdp_data, sdp_data_size);
1733
-                                q += sdp_data_size;
1734
-                                *q = '\0';
1735
-                                av_free(sdp_data);
1736
-                            }
1737
-                        }
1738
-                        break;
1739
-                    default:
1740
-                        abort();
1741
-                        break;
1742
-                    }
1743
-
1744
-                    /* prepare output buffer */
1745
-                    c->buffer_ptr = c->buffer;
1746
-                    c->buffer_end = q;
1747
-                    c->state = HTTPSTATE_SEND_HEADER;
1748
-                    return 0;
1749
-                }
1750
-            }
1751
-        }
1752
-
1753
-        snprintf(msg, sizeof(msg), "ASX/RAM file not handled");
1754
-        goto send_error;
1755
-    }
1756
-
1757
-    stream->conns_served++;
1758
-
1759
-    /* XXX: add there authenticate and IP match */
1760
-
1761
-    if (c->post) {
1762
-        /* if post, it means a feed is being sent */
1763
-        if (!stream->is_feed) {
1764
-            /* However it might be a status report from WMP! Let us log the
1765
-             * data as it might come in handy one day. */
1766
-            const char *logline = 0;
1767
-            int client_id = 0;
1768
-
1769
-            for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1770
-                if (av_strncasecmp(p, "Pragma: log-line=", 17) == 0) {
1771
-                    logline = p;
1772
-                    break;
1773
-                }
1774
-                if (av_strncasecmp(p, "Pragma: client-id=", 18) == 0)
1775
-                    client_id = strtol(p + 18, 0, 10);
1776
-                p = strchr(p, '\n');
1777
-                if (!p)
1778
-                    break;
1779
-
1780
-                p++;
1781
-            }
1782
-
1783
-            if (logline) {
1784
-                char *eol = strchr(logline, '\n');
1785
-
1786
-                logline += 17;
1787
-
1788
-                if (eol) {
1789
-                    if (eol[-1] == '\r')
1790
-                        eol--;
1791
-                    http_log("%.*s\n", (int) (eol - logline), logline);
1792
-                    c->suppress_log = 1;
1793
-                }
1794
-            }
1795
-
1796
-#ifdef DEBUG
1797
-            http_log("\nGot request:\n%s\n", c->buffer);
1798
-#endif
1799
-
1800
-            if (client_id && extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
1801
-                HTTPContext *wmpc;
1802
-
1803
-                /* Now we have to find the client_id */
1804
-                for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->next) {
1805
-                    if (wmpc->wmp_client_id == client_id)
1806
-                        break;
1807
-                }
1808
-
1809
-                if (wmpc && modify_current_stream(wmpc, ratebuf))
1810
-                    wmpc->switch_pending = 1;
1811
-            }
1812
-
1813
-            snprintf(msg, sizeof(msg), "POST command not handled");
1814
-            c->stream = 0;
1815
-            goto send_error;
1816
-        }
1817
-        if (http_start_receive_data(c) < 0) {
1818
-            snprintf(msg, sizeof(msg), "could not open feed");
1819
-            goto send_error;
1820
-        }
1821
-        c->http_error = 0;
1822
-        c->state = HTTPSTATE_RECEIVE_DATA;
1823
-        return 0;
1824
-    }
1825
-
1826
-#ifdef DEBUG
1827
-    if (strcmp(stream->filename + strlen(stream->filename) - 4, ".asf") == 0)
1828
-        http_log("\nGot request:\n%s\n", c->buffer);
1829
-#endif
1830
-
1831
-    if (c->stream->stream_type == STREAM_TYPE_STATUS)
1832
-        goto send_status;
1833
-
1834
-    /* open input stream */
1835
-    if (open_input_stream(c, info) < 0) {
1836
-        snprintf(msg, sizeof(msg), "Input stream corresponding to '%s' not found", url);
1837
-        goto send_error;
1838
-    }
1839
-
1840
-    /* prepare http header */
1841
-    q = c->buffer;
1842
-    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "HTTP/1.0 200 OK\r\n");
1843
-    mime_type = c->stream->fmt->mime_type;
1844
-    if (!mime_type)
1845
-        mime_type = "application/x-octet-stream";
1846
-    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Pragma: no-cache\r\n");
1847
-
1848
-    /* for asf, we need extra headers */
1849
-    if (!strcmp(c->stream->fmt->name,"asf_stream")) {
1850
-        /* Need to allocate a client id */
1851
-
1852
-        c->wmp_client_id = av_lfg_get(&random_state);
1853
-
1854
-        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Server: Cougar 4.1.0.3923\r\nCache-Control: no-cache\r\nPragma: client-id=%d\r\nPragma: features=\"broadcast\"\r\n", c->wmp_client_id);
1855
-    }
1856
-    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-Type: %s\r\n", mime_type);
1857
-    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
1858
-
1859
-    /* prepare output buffer */
1860
-    c->http_error = 0;
1861
-    c->buffer_ptr = c->buffer;
1862
-    c->buffer_end = q;
1863
-    c->state = HTTPSTATE_SEND_HEADER;
1864
-    return 0;
1865
- send_error:
1866
-    c->http_error = 404;
1867
-    q = c->buffer;
1868
-    q += snprintf(q, c->buffer_size,
1869
-                  "HTTP/1.0 404 Not Found\r\n"
1870
-                  "Content-type: text/html\r\n"
1871
-                  "\r\n"
1872
-                  "<html>\n"
1873
-                  "<head><title>404 Not Found</title></head>\n"
1874
-                  "<body>%s</body>\n"
1875
-                  "</html>\n", msg);
1876
-    /* prepare output buffer */
1877
-    c->buffer_ptr = c->buffer;
1878
-    c->buffer_end = q;
1879
-    c->state = HTTPSTATE_SEND_HEADER;
1880
-    return 0;
1881
- send_status:
1882
-    compute_status(c);
1883
-    c->http_error = 200; /* horrible : we use this value to avoid
1884
-                            going to the send data state */
1885
-    c->state = HTTPSTATE_SEND_HEADER;
1886
-    return 0;
1887
-}
1888
-
1889
-static void fmt_bytecount(AVIOContext *pb, int64_t count)
1890
-{
1891
-    static const char suffix[] = " kMGTP";
1892
-    const char *s;
1893
-
1894
-    for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++);
1895
-
1896
-    avio_printf(pb, "%"PRId64"%c", count, *s);
1897
-}
1898
-
1899
-static void compute_status(HTTPContext *c)
1900
-{
1901
-    HTTPContext *c1;
1902
-    FFStream *stream;
1903
-    char *p;
1904
-    time_t ti;
1905
-    int i, len;
1906
-    AVIOContext *pb;
1907
-
1908
-    if (avio_open_dyn_buf(&pb) < 0) {
1909
-        /* XXX: return an error ? */
1910
-        c->buffer_ptr = c->buffer;
1911
-        c->buffer_end = c->buffer;
1912
-        return;
1913
-    }
1914
-
1915
-    avio_printf(pb, "HTTP/1.0 200 OK\r\n");
1916
-    avio_printf(pb, "Content-type: %s\r\n", "text/html");
1917
-    avio_printf(pb, "Pragma: no-cache\r\n");
1918
-    avio_printf(pb, "\r\n");
1919
-
1920
-    avio_printf(pb, "<html><head><title>%s Status</title>\n", program_name);
1921
-    if (c->stream->feed_filename[0])
1922
-        avio_printf(pb, "<link rel=\"shortcut icon\" href=\"%s\">\n", c->stream->feed_filename);
1923
-    avio_printf(pb, "</head>\n<body>");
1924
-    avio_printf(pb, "<h1>%s Status</h1>\n", program_name);
1925
-    /* format status */
1926
-    avio_printf(pb, "<h2>Available Streams</h2>\n");
1927
-    avio_printf(pb, "<table cellspacing=0 cellpadding=4>\n");
1928
-    avio_printf(pb, "<tr><th valign=top>Path<th align=left>Served<br>Conns<th><br>bytes<th valign=top>Format<th>Bit rate<br>kbits/s<th align=left>Video<br>kbits/s<th><br>Codec<th align=left>Audio<br>kbits/s<th><br>Codec<th align=left valign=top>Feed\n");
1929
-    stream = first_stream;
1930
-    while (stream != NULL) {
1931
-        char sfilename[1024];
1932
-        char *eosf;
1933
-
1934
-        if (stream->feed != stream) {
1935
-            av_strlcpy(sfilename, stream->filename, sizeof(sfilename) - 10);
1936
-            eosf = sfilename + strlen(sfilename);
1937
-            if (eosf - sfilename >= 4) {
1938
-                if (strcmp(eosf - 4, ".asf") == 0)
1939
-                    strcpy(eosf - 4, ".asx");
1940
-                else if (strcmp(eosf - 3, ".rm") == 0)
1941
-                    strcpy(eosf - 3, ".ram");
1942
-                else if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
1943
-                    /* generate a sample RTSP director if
1944
-                       unicast. Generate an SDP redirector if
1945
-                       multicast */
1946
-                    eosf = strrchr(sfilename, '.');
1947
-                    if (!eosf)
1948
-                        eosf = sfilename + strlen(sfilename);
1949
-                    if (stream->is_multicast)
1950
-                        strcpy(eosf, ".sdp");
1951
-                    else
1952
-                        strcpy(eosf, ".rtsp");
1953
-                }
1954
-            }
1955
-
1956
-            avio_printf(pb, "<tr><td><a href=\"/%s\">%s</a> ",
1957
-                         sfilename, stream->filename);
1958
-            avio_printf(pb, "<td align=right> %d <td align=right> ",
1959
-                        stream->conns_served);
1960
-            fmt_bytecount(pb, stream->bytes_served);
1961
-            switch(stream->stream_type) {
1962
-            case STREAM_TYPE_LIVE: {
1963
-                    int audio_bit_rate = 0;
1964
-                    int video_bit_rate = 0;
1965
-                    const char *audio_codec_name = "";
1966
-                    const char *video_codec_name = "";
1967
-                    const char *audio_codec_name_extra = "";
1968
-                    const char *video_codec_name_extra = "";
1969
-
1970
-                    for(i=0;i<stream->nb_streams;i++) {
1971
-                        AVStream *st = stream->streams[i];
1972
-                        AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
1973
-                        switch(st->codec->codec_type) {
1974
-                        case AVMEDIA_TYPE_AUDIO:
1975
-                            audio_bit_rate += st->codec->bit_rate;
1976
-                            if (codec) {
1977
-                                if (*audio_codec_name)
1978
-                                    audio_codec_name_extra = "...";
1979
-                                audio_codec_name = codec->name;
1980
-                            }
1981
-                            break;
1982
-                        case AVMEDIA_TYPE_VIDEO:
1983
-                            video_bit_rate += st->codec->bit_rate;
1984
-                            if (codec) {
1985
-                                if (*video_codec_name)
1986
-                                    video_codec_name_extra = "...";
1987
-                                video_codec_name = codec->name;
1988
-                            }
1989
-                            break;
1990
-                        case AVMEDIA_TYPE_DATA:
1991
-                            video_bit_rate += st->codec->bit_rate;
1992
-                            break;
1993
-                        default:
1994
-                            abort();
1995
-                        }
1996
-                    }
1997
-                    avio_printf(pb, "<td align=center> %s <td align=right> %d <td align=right> %d <td> %s %s <td align=right> %d <td> %s %s",
1998
-                                 stream->fmt->name,
1999
-                                 stream->bandwidth,
2000
-                                 video_bit_rate / 1000, video_codec_name, video_codec_name_extra,
2001
-                                 audio_bit_rate / 1000, audio_codec_name, audio_codec_name_extra);
2002
-                    if (stream->feed)
2003
-                        avio_printf(pb, "<td>%s", stream->feed->filename);
2004
-                    else
2005
-                        avio_printf(pb, "<td>%s", stream->feed_filename);
2006
-                    avio_printf(pb, "\n");
2007
-                }
2008
-                break;
2009
-            default:
2010
-                avio_printf(pb, "<td align=center> - <td align=right> - <td align=right> - <td><td align=right> - <td>\n");
2011
-                break;
2012
-            }
2013
-        }
2014
-        stream = stream->next;
2015
-    }
2016
-    avio_printf(pb, "</table>\n");
2017
-
2018
-    stream = first_stream;
2019
-    while (stream != NULL) {
2020
-        if (stream->feed == stream) {
2021
-            avio_printf(pb, "<h2>Feed %s</h2>", stream->filename);
2022
-            if (stream->pid) {
2023
-                avio_printf(pb, "Running as pid %d.\n", stream->pid);
2024
-
2025
-#if defined(linux) && !defined(CONFIG_NOCUTILS)
2026
-                {
2027
-                    FILE *pid_stat;
2028
-                    char ps_cmd[64];
2029
-
2030
-                    /* This is somewhat linux specific I guess */
2031
-                    snprintf(ps_cmd, sizeof(ps_cmd),
2032
-                             "ps -o \"%%cpu,cputime\" --no-headers %d",
2033
-                             stream->pid);
2034
-
2035
-                    pid_stat = popen(ps_cmd, "r");
2036
-                    if (pid_stat) {
2037
-                        char cpuperc[10];
2038
-                        char cpuused[64];
2039
-
2040
-                        if (fscanf(pid_stat, "%10s %64s", cpuperc,
2041
-                                   cpuused) == 2) {
2042
-                            avio_printf(pb, "Currently using %s%% of the cpu. Total time used %s.\n",
2043
-                                         cpuperc, cpuused);
2044
-                        }
2045
-                        fclose(pid_stat);
2046
-                    }
2047
-                }
2048
-#endif
2049
-
2050
-                avio_printf(pb, "<p>");
2051
-            }
2052
-            avio_printf(pb, "<table cellspacing=0 cellpadding=4><tr><th>Stream<th>type<th>kbits/s<th align=left>codec<th align=left>Parameters\n");
2053
-
2054
-            for (i = 0; i < stream->nb_streams; i++) {
2055
-                AVStream *st = stream->streams[i];
2056
-                AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
2057
-                const char *type = "unknown";
2058
-                char parameters[64];
2059
-
2060
-                parameters[0] = 0;
2061
-
2062
-                switch(st->codec->codec_type) {
2063
-                case AVMEDIA_TYPE_AUDIO:
2064
-                    type = "audio";
2065
-                    snprintf(parameters, sizeof(parameters), "%d channel(s), %d Hz", st->codec->channels, st->codec->sample_rate);
2066
-                    break;
2067
-                case AVMEDIA_TYPE_VIDEO:
2068
-                    type = "video";
2069
-                    snprintf(parameters, sizeof(parameters), "%dx%d, q=%d-%d, fps=%d", st->codec->width, st->codec->height,
2070
-                                st->codec->qmin, st->codec->qmax, st->codec->time_base.den / st->codec->time_base.num);
2071
-                    break;
2072
-                default:
2073
-                    abort();
2074
-                }
2075
-                avio_printf(pb, "<tr><td align=right>%d<td>%s<td align=right>%d<td>%s<td>%s\n",
2076
-                        i, type, st->codec->bit_rate/1000, codec ? codec->name : "", parameters);
2077
-            }
2078
-            avio_printf(pb, "</table>\n");
2079
-
2080
-        }
2081
-        stream = stream->next;
2082
-    }
2083
-
2084
-    /* connection status */
2085
-    avio_printf(pb, "<h2>Connection Status</h2>\n");
2086
-
2087
-    avio_printf(pb, "Number of connections: %d / %d<br>\n",
2088
-                 nb_connections, nb_max_connections);
2089
-
2090
-    avio_printf(pb, "Bandwidth in use: %"PRIu64"k / %"PRIu64"k<br>\n",
2091
-                 current_bandwidth, max_bandwidth);
2092
-
2093
-    avio_printf(pb, "<table>\n");
2094
-    avio_printf(pb, "<tr><th>#<th>File<th>IP<th>Proto<th>State<th>Target bits/sec<th>Actual bits/sec<th>Bytes transferred\n");
2095
-    c1 = first_http_ctx;
2096
-    i = 0;
2097
-    while (c1 != NULL) {
2098
-        int bitrate;
2099
-        int j;
2100
-
2101
-        bitrate = 0;
2102
-        if (c1->stream) {
2103
-            for (j = 0; j < c1->stream->nb_streams; j++) {
2104
-                if (!c1->stream->feed)
2105
-                    bitrate += c1->stream->streams[j]->codec->bit_rate;
2106
-                else if (c1->feed_streams[j] >= 0)
2107
-                    bitrate += c1->stream->feed->streams[c1->feed_streams[j]]->codec->bit_rate;
2108
-            }
2109
-        }
2110
-
2111
-        i++;
2112
-        p = inet_ntoa(c1->from_addr.sin_addr);
2113
-        avio_printf(pb, "<tr><td><b>%d</b><td>%s%s<td>%s<td>%s<td>%s<td align=right>",
2114
-                    i,
2115
-                    c1->stream ? c1->stream->filename : "",
2116
-                    c1->state == HTTPSTATE_RECEIVE_DATA ? "(input)" : "",
2117
-                    p,
2118
-                    c1->protocol,
2119
-                    http_state[c1->state]);
2120
-        fmt_bytecount(pb, bitrate);
2121
-        avio_printf(pb, "<td align=right>");
2122
-        fmt_bytecount(pb, compute_datarate(&c1->datarate, c1->data_count) * 8);
2123
-        avio_printf(pb, "<td align=right>");
2124
-        fmt_bytecount(pb, c1->data_count);
2125
-        avio_printf(pb, "\n");
2126
-        c1 = c1->next;
2127
-    }
2128
-    avio_printf(pb, "</table>\n");
2129
-
2130
-    /* date */
2131
-    ti = time(NULL);
2132
-    p = ctime(&ti);
2133
-    avio_printf(pb, "<hr size=1 noshade>Generated at %s", p);
2134
-    avio_printf(pb, "</body>\n</html>\n");
2135
-
2136
-    len = avio_close_dyn_buf(pb, &c->pb_buffer);
2137
-    c->buffer_ptr = c->pb_buffer;
2138
-    c->buffer_end = c->pb_buffer + len;
2139
-}
2140
-
2141
-static int open_input_stream(HTTPContext *c, const char *info)
2142
-{
2143
-    char buf[128];
2144
-    char input_filename[1024];
2145
-    AVFormatContext *s = NULL;
2146
-    int i, ret;
2147
-    int64_t stream_pos;
2148
-
2149
-    /* find file name */
2150
-    if (c->stream->feed) {
2151
-        strcpy(input_filename, c->stream->feed->feed_filename);
2152
-        /* compute position (absolute time) */
2153
-        if (av_find_info_tag(buf, sizeof(buf), "date", info)) {
2154
-            if ((ret = av_parse_time(&stream_pos, buf, 0)) < 0)
2155
-                return ret;
2156
-        } else if (av_find_info_tag(buf, sizeof(buf), "buffer", info)) {
2157
-            int prebuffer = strtol(buf, 0, 10);
2158
-            stream_pos = av_gettime() - prebuffer * (int64_t)1000000;
2159
-        } else
2160
-            stream_pos = av_gettime() - c->stream->prebuffer * (int64_t)1000;
2161
-    } else {
2162
-        strcpy(input_filename, c->stream->feed_filename);
2163
-        /* compute position (relative time) */
2164
-        if (av_find_info_tag(buf, sizeof(buf), "date", info)) {
2165
-            if ((ret = av_parse_time(&stream_pos, buf, 1)) < 0)
2166
-                return ret;
2167
-        } else
2168
-            stream_pos = 0;
2169
-    }
2170
-    if (input_filename[0] == '\0')
2171
-        return -1;
2172
-
2173
-    /* open stream */
2174
-    if ((ret = avformat_open_input(&s, input_filename, c->stream->ifmt, &c->stream->in_opts)) < 0) {
2175
-        http_log("could not open %s: %d\n", input_filename, ret);
2176
-        return -1;
2177
-    }
2178
-    s->flags |= AVFMT_FLAG_GENPTS;
2179
-    c->fmt_in = s;
2180
-    if (strcmp(s->iformat->name, "ffm") && avformat_find_stream_info(c->fmt_in, NULL) < 0) {
2181
-        http_log("Could not find stream info '%s'\n", input_filename);
2182
-        avformat_close_input(&s);
2183
-        return -1;
2184
-    }
2185
-
2186
-    /* choose stream as clock source (we favorize video stream if
2187
-       present) for packet sending */
2188
-    c->pts_stream_index = 0;
2189
-    for(i=0;i<c->stream->nb_streams;i++) {
2190
-        if (c->pts_stream_index == 0 &&
2191
-            c->stream->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
2192
-            c->pts_stream_index = i;
2193
-        }
2194
-    }
2195
-
2196
-    if (c->fmt_in->iformat->read_seek)
2197
-        av_seek_frame(c->fmt_in, -1, stream_pos, 0);
2198
-    /* set the start time (needed for maxtime and RTP packet timing) */
2199
-    c->start_time = cur_time;
2200
-    c->first_pts = AV_NOPTS_VALUE;
2201
-    return 0;
2202
-}
2203
-
2204
-/* return the server clock (in us) */
2205
-static int64_t get_server_clock(HTTPContext *c)
2206
-{
2207
-    /* compute current pts value from system time */
2208
-    return (cur_time - c->start_time) * 1000;
2209
-}
2210
-
2211
-/* return the estimated time at which the current packet must be sent
2212
-   (in us) */
2213
-static int64_t get_packet_send_clock(HTTPContext *c)
2214
-{
2215
-    int bytes_left, bytes_sent, frame_bytes;
2216
-
2217
-    frame_bytes = c->cur_frame_bytes;
2218
-    if (frame_bytes <= 0)
2219
-        return c->cur_pts;
2220
-    else {
2221
-        bytes_left = c->buffer_end - c->buffer_ptr;
2222
-        bytes_sent = frame_bytes - bytes_left;
2223
-        return c->cur_pts + (c->cur_frame_duration * bytes_sent) / frame_bytes;
2224
-    }
2225
-}
2226
-
2227
-
2228
-static int http_prepare_data(HTTPContext *c)
2229
-{
2230
-    int i, len, ret;
2231
-    AVFormatContext *ctx;
2232
-
2233
-    av_freep(&c->pb_buffer);
2234
-    switch(c->state) {
2235
-    case HTTPSTATE_SEND_DATA_HEADER:
2236
-        memset(&c->fmt_ctx, 0, sizeof(c->fmt_ctx));
2237
-        av_dict_set(&c->fmt_ctx.metadata, "author"   , c->stream->author   , 0);
2238
-        av_dict_set(&c->fmt_ctx.metadata, "comment"  , c->stream->comment  , 0);
2239
-        av_dict_set(&c->fmt_ctx.metadata, "copyright", c->stream->copyright, 0);
2240
-        av_dict_set(&c->fmt_ctx.metadata, "title"    , c->stream->title    , 0);
2241
-
2242
-        c->fmt_ctx.streams = av_mallocz(sizeof(AVStream *) * c->stream->nb_streams);
2243
-
2244
-        for(i=0;i<c->stream->nb_streams;i++) {
2245
-            AVStream *src;
2246
-            c->fmt_ctx.streams[i] = av_mallocz(sizeof(AVStream));
2247
-            /* if file or feed, then just take streams from FFStream struct */
2248
-            if (!c->stream->feed ||
2249
-                c->stream->feed == c->stream)
2250
-                src = c->stream->streams[i];
2251
-            else
2252
-                src = c->stream->feed->streams[c->stream->feed_streams[i]];
2253
-
2254
-            *(c->fmt_ctx.streams[i]) = *src;
2255
-            c->fmt_ctx.streams[i]->priv_data = 0;
2256
-            c->fmt_ctx.streams[i]->codec->frame_number = 0; /* XXX: should be done in
2257
-                                           AVStream, not in codec */
2258
-        }
2259
-        /* set output format parameters */
2260
-        c->fmt_ctx.oformat = c->stream->fmt;
2261
-        c->fmt_ctx.nb_streams = c->stream->nb_streams;
2262
-
2263
-        c->got_key_frame = 0;
2264
-
2265
-        /* prepare header and save header data in a stream */
2266
-        if (avio_open_dyn_buf(&c->fmt_ctx.pb) < 0) {
2267
-            /* XXX: potential leak */
2268
-            return -1;
2269
-        }
2270
-        c->fmt_ctx.pb->seekable = 0;
2271
-
2272
-        /*
2273
-         * HACK to avoid mpeg ps muxer to spit many underflow errors
2274
-         * Default value from Libav
2275
-         * Try to set it use configuration option
2276
-         */
2277
-        c->fmt_ctx.max_delay = (int)(0.7*AV_TIME_BASE);
2278
-
2279
-        if (avformat_write_header(&c->fmt_ctx, NULL) < 0) {
2280
-            http_log("Error writing output header\n");
2281
-            return -1;
2282
-        }
2283
-        av_dict_free(&c->fmt_ctx.metadata);
2284
-
2285
-        len = avio_close_dyn_buf(c->fmt_ctx.pb, &c->pb_buffer);
2286
-        c->buffer_ptr = c->pb_buffer;
2287
-        c->buffer_end = c->pb_buffer + len;
2288
-
2289
-        c->state = HTTPSTATE_SEND_DATA;
2290
-        c->last_packet_sent = 0;
2291
-        break;
2292
-    case HTTPSTATE_SEND_DATA:
2293
-        /* find a new packet */
2294
-        /* read a packet from the input stream */
2295
-        if (c->stream->feed)
2296
-            ffm_set_write_index(c->fmt_in,
2297
-                                c->stream->feed->feed_write_index,
2298
-                                c->stream->feed->feed_size);
2299
-
2300
-        if (c->stream->max_time &&
2301
-            c->stream->max_time + c->start_time - cur_time < 0)
2302
-            /* We have timed out */
2303
-            c->state = HTTPSTATE_SEND_DATA_TRAILER;
2304
-        else {
2305
-            AVPacket pkt;
2306
-        redo:
2307
-            ret = av_read_frame(c->fmt_in, &pkt);
2308
-            if (ret < 0) {
2309
-                if (c->stream->feed) {
2310
-                    /* if coming from feed, it means we reached the end of the
2311
-                       ffm file, so must wait for more data */
2312
-                    c->state = HTTPSTATE_WAIT_FEED;
2313
-                    return 1; /* state changed */
2314
-                } else if (ret == AVERROR(EAGAIN)) {
2315
-                    /* input not ready, come back later */
2316
-                    return 0;
2317
-                } else {
2318
-                    if (c->stream->loop) {
2319
-                        avformat_close_input(&c->fmt_in);
2320
-                        if (open_input_stream(c, "") < 0)
2321
-                            goto no_loop;
2322
-                        goto redo;
2323
-                    } else {
2324
-                    no_loop:
2325
-                        /* must send trailer now because eof or error */
2326
-                        c->state = HTTPSTATE_SEND_DATA_TRAILER;
2327
-                    }
2328
-                }
2329
-            } else {
2330
-                int source_index = pkt.stream_index;
2331
-                /* update first pts if needed */
2332
-                if (c->first_pts == AV_NOPTS_VALUE) {
2333
-                    c->first_pts = av_rescale_q(pkt.dts, c->fmt_in->streams[pkt.stream_index]->time_base, AV_TIME_BASE_Q);
2334
-                    c->start_time = cur_time;
2335
-                }
2336
-                /* send it to the appropriate stream */
2337
-                if (c->stream->feed) {
2338
-                    /* if coming from a feed, select the right stream */
2339
-                    if (c->switch_pending) {
2340
-                        c->switch_pending = 0;
2341
-                        for(i=0;i<c->stream->nb_streams;i++) {
2342
-                            if (c->switch_feed_streams[i] == pkt.stream_index)
2343
-                                if (pkt.flags & AV_PKT_FLAG_KEY)
2344
-                                    c->switch_feed_streams[i] = -1;
2345
-                            if (c->switch_feed_streams[i] >= 0)
2346
-                                c->switch_pending = 1;
2347
-                        }
2348
-                    }
2349
-                    for(i=0;i<c->stream->nb_streams;i++) {
2350
-                        if (c->stream->feed_streams[i] == pkt.stream_index) {
2351
-                            AVStream *st = c->fmt_in->streams[source_index];
2352
-                            pkt.stream_index = i;
2353
-                            if (pkt.flags & AV_PKT_FLAG_KEY &&
2354
-                                (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
2355
-                                 c->stream->nb_streams == 1))
2356
-                                c->got_key_frame = 1;
2357
-                            if (!c->stream->send_on_key || c->got_key_frame)
2358
-                                goto send_it;
2359
-                        }
2360
-                    }
2361
-                } else {
2362
-                    AVCodecContext *codec;
2363
-                    AVStream *ist, *ost;
2364
-                send_it:
2365
-                    ist = c->fmt_in->streams[source_index];
2366
-                    /* specific handling for RTP: we use several
2367
-                       output stream (one for each RTP
2368
-                       connection). XXX: need more abstract handling */
2369
-                    if (c->is_packetized) {
2370
-                        /* compute send time and duration */
2371
-                        c->cur_pts = av_rescale_q(pkt.dts, ist->time_base, AV_TIME_BASE_Q);
2372
-                        c->cur_pts -= c->first_pts;
2373
-                        c->cur_frame_duration = av_rescale_q(pkt.duration, ist->time_base, AV_TIME_BASE_Q);
2374
-                        /* find RTP context */
2375
-                        c->packet_stream_index = pkt.stream_index;
2376
-                        ctx = c->rtp_ctx[c->packet_stream_index];
2377
-                        if(!ctx) {
2378
-                            av_free_packet(&pkt);
2379
-                            break;
2380
-                        }
2381
-                        codec = ctx->streams[0]->codec;
2382
-                        /* only one stream per RTP connection */
2383
-                        pkt.stream_index = 0;
2384
-                    } else {
2385
-                        ctx = &c->fmt_ctx;
2386
-                        /* Fudge here */
2387
-                        codec = ctx->streams[pkt.stream_index]->codec;
2388
-                    }
2389
-
2390
-                    if (c->is_packetized) {
2391
-                        int max_packet_size;
2392
-                        if (c->rtp_protocol == RTSP_LOWER_TRANSPORT_TCP)
2393
-                            max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
2394
-                        else
2395
-                            max_packet_size = c->rtp_handles[c->packet_stream_index]->max_packet_size;
2396
-                        ret = ffio_open_dyn_packet_buf(&ctx->pb, max_packet_size);
2397
-                    } else {
2398
-                        ret = avio_open_dyn_buf(&ctx->pb);
2399
-                    }
2400
-                    if (ret < 0) {
2401
-                        /* XXX: potential leak */
2402
-                        return -1;
2403
-                    }
2404
-                    ost = ctx->streams[pkt.stream_index];
2405
-
2406
-                    ctx->pb->seekable = 0;
2407
-                    if (pkt.dts != AV_NOPTS_VALUE)
2408
-                        pkt.dts = av_rescale_q(pkt.dts, ist->time_base, ost->time_base);
2409
-                    if (pkt.pts != AV_NOPTS_VALUE)
2410
-                        pkt.pts = av_rescale_q(pkt.pts, ist->time_base, ost->time_base);
2411
-                    pkt.duration = av_rescale_q(pkt.duration, ist->time_base, ost->time_base);
2412
-                    if (av_write_frame(ctx, &pkt) < 0) {
2413
-                        http_log("Error writing frame to output\n");
2414
-                        c->state = HTTPSTATE_SEND_DATA_TRAILER;
2415
-                    }
2416
-
2417
-                    len = avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
2418
-                    c->cur_frame_bytes = len;
2419
-                    c->buffer_ptr = c->pb_buffer;
2420
-                    c->buffer_end = c->pb_buffer + len;
2421
-
2422
-                    codec->frame_number++;
2423
-                    if (len == 0) {
2424
-                        av_free_packet(&pkt);
2425
-                        goto redo;
2426
-                    }
2427
-                }
2428
-                av_free_packet(&pkt);
2429
-            }
2430
-        }
2431
-        break;
2432
-    default:
2433
-    case HTTPSTATE_SEND_DATA_TRAILER:
2434
-        /* last packet test ? */
2435
-        if (c->last_packet_sent || c->is_packetized)
2436
-            return -1;
2437
-        ctx = &c->fmt_ctx;
2438
-        /* prepare header */
2439
-        if (avio_open_dyn_buf(&ctx->pb) < 0) {
2440
-            /* XXX: potential leak */
2441
-            return -1;
2442
-        }
2443
-        c->fmt_ctx.pb->seekable = 0;
2444
-        av_write_trailer(ctx);
2445
-        len = avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
2446
-        c->buffer_ptr = c->pb_buffer;
2447
-        c->buffer_end = c->pb_buffer + len;
2448
-
2449
-        c->last_packet_sent = 1;
2450
-        break;
2451
-    }
2452
-    return 0;
2453
-}
2454
-
2455
-/* should convert the format at the same time */
2456
-/* send data starting at c->buffer_ptr to the output connection
2457
-   (either UDP or TCP connection) */
2458
-static int http_send_data(HTTPContext *c)
2459
-{
2460
-    int len, ret;
2461
-
2462
-    for(;;) {
2463
-        if (c->buffer_ptr >= c->buffer_end) {
2464
-            ret = http_prepare_data(c);
2465
-            if (ret < 0)
2466
-                return -1;
2467
-            else if (ret != 0)
2468
-                /* state change requested */
2469
-                break;
2470
-        } else {
2471
-            if (c->is_packetized) {
2472
-                /* RTP data output */
2473
-                len = c->buffer_end - c->buffer_ptr;
2474
-                if (len < 4) {
2475
-                    /* fail safe - should never happen */
2476
-                fail1:
2477
-                    c->buffer_ptr = c->buffer_end;
2478
-                    return 0;
2479
-                }
2480
-                len = (c->buffer_ptr[0] << 24) |
2481
-                    (c->buffer_ptr[1] << 16) |
2482
-                    (c->buffer_ptr[2] << 8) |
2483
-                    (c->buffer_ptr[3]);
2484
-                if (len > (c->buffer_end - c->buffer_ptr))
2485
-                    goto fail1;
2486
-                if ((get_packet_send_clock(c) - get_server_clock(c)) > 0) {
2487
-                    /* nothing to send yet: we can wait */
2488
-                    return 0;
2489
-                }
2490
-
2491
-                c->data_count += len;
2492
-                update_datarate(&c->datarate, c->data_count);
2493
-                if (c->stream)
2494
-                    c->stream->bytes_served += len;
2495
-
2496
-                if (c->rtp_protocol == RTSP_LOWER_TRANSPORT_TCP) {
2497
-                    /* RTP packets are sent inside the RTSP TCP connection */
2498
-                    AVIOContext *pb;
2499
-                    int interleaved_index, size;
2500
-                    uint8_t header[4];
2501
-                    HTTPContext *rtsp_c;
2502
-
2503
-                    rtsp_c = c->rtsp_c;
2504
-                    /* if no RTSP connection left, error */
2505
-                    if (!rtsp_c)
2506
-                        return -1;
2507
-                    /* if already sending something, then wait. */
2508
-                    if (rtsp_c->state != RTSPSTATE_WAIT_REQUEST)
2509
-                        break;
2510
-                    if (avio_open_dyn_buf(&pb) < 0)
2511
-                        goto fail1;
2512
-                    interleaved_index = c->packet_stream_index * 2;
2513
-                    /* RTCP packets are sent at odd indexes */
2514
-                    if (c->buffer_ptr[1] == 200)
2515
-                        interleaved_index++;
2516
-                    /* write RTSP TCP header */
2517
-                    header[0] = '$';
2518
-                    header[1] = interleaved_index;
2519
-                    header[2] = len >> 8;
2520
-                    header[3] = len;
2521
-                    avio_write(pb, header, 4);
2522
-                    /* write RTP packet data */
2523
-                    c->buffer_ptr += 4;
2524
-                    avio_write(pb, c->buffer_ptr, len);
2525
-                    size = avio_close_dyn_buf(pb, &c->packet_buffer);
2526
-                    /* prepare asynchronous TCP sending */
2527
-                    rtsp_c->packet_buffer_ptr = c->packet_buffer;
2528
-                    rtsp_c->packet_buffer_end = c->packet_buffer + size;
2529
-                    c->buffer_ptr += len;
2530
-
2531
-                    /* send everything we can NOW */
2532
-                    len = send(rtsp_c->fd, rtsp_c->packet_buffer_ptr,
2533
-                                rtsp_c->packet_buffer_end - rtsp_c->packet_buffer_ptr, 0);
2534
-                    if (len > 0)
2535
-                        rtsp_c->packet_buffer_ptr += len;
2536
-                    if (rtsp_c->packet_buffer_ptr < rtsp_c->packet_buffer_end) {
2537
-                        /* if we could not send all the data, we will
2538
-                           send it later, so a new state is needed to
2539
-                           "lock" the RTSP TCP connection */
2540
-                        rtsp_c->state = RTSPSTATE_SEND_PACKET;
2541
-                        break;
2542
-                    } else
2543
-                        /* all data has been sent */
2544
-                        av_freep(&c->packet_buffer);
2545
-                } else {
2546
-                    /* send RTP packet directly in UDP */
2547
-                    c->buffer_ptr += 4;
2548
-                    ffurl_write(c->rtp_handles[c->packet_stream_index],
2549
-                                c->buffer_ptr, len);
2550
-                    c->buffer_ptr += len;
2551
-                    /* here we continue as we can send several packets per 10 ms slot */
2552
-                }
2553
-            } else {
2554
-                /* TCP data output */
2555
-                len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
2556
-                if (len < 0) {
2557
-                    if (ff_neterrno() != AVERROR(EAGAIN) &&
2558
-                        ff_neterrno() != AVERROR(EINTR))
2559
-                        /* error : close connection */
2560
-                        return -1;
2561
-                    else
2562
-                        return 0;
2563
-                } else
2564
-                    c->buffer_ptr += len;
2565
-
2566
-                c->data_count += len;
2567
-                update_datarate(&c->datarate, c->data_count);
2568
-                if (c->stream)
2569
-                    c->stream->bytes_served += len;
2570
-                break;
2571
-            }
2572
-        }
2573
-    } /* for(;;) */
2574
-    return 0;
2575
-}
2576
-
2577
-static int http_start_receive_data(HTTPContext *c)
2578
-{
2579
-    int fd;
2580
-
2581
-    if (c->stream->feed_opened)
2582
-        return -1;
2583
-
2584
-    /* Don't permit writing to this one */
2585
-    if (c->stream->readonly)
2586
-        return -1;
2587
-
2588
-    /* open feed */
2589
-    fd = open(c->stream->feed_filename, O_RDWR);
2590
-    if (fd < 0) {
2591
-        http_log("Error opening feeder file: %s\n", strerror(errno));
2592
-        return -1;
2593
-    }
2594
-    c->feed_fd = fd;
2595
-
2596
-    if (c->stream->truncate) {
2597
-        /* truncate feed file */
2598
-        ffm_write_write_index(c->feed_fd, FFM_PACKET_SIZE);
2599
-        http_log("Truncating feed file '%s'\n", c->stream->feed_filename);
2600
-        if (ftruncate(c->feed_fd, FFM_PACKET_SIZE) < 0) {
2601
-            http_log("Error truncating feed file: %s\n", strerror(errno));
2602
-            return -1;
2603
-        }
2604
-    } else {
2605
-        if ((c->stream->feed_write_index = ffm_read_write_index(fd)) < 0) {
2606
-            http_log("Error reading write index from feed file: %s\n", strerror(errno));
2607
-            return -1;
2608
-        }
2609
-    }
2610
-
2611
-    c->stream->feed_write_index = FFMAX(ffm_read_write_index(fd), FFM_PACKET_SIZE);
2612
-    c->stream->feed_size = lseek(fd, 0, SEEK_END);
2613
-    lseek(fd, 0, SEEK_SET);
2614
-
2615
-    /* init buffer input */
2616
-    c->buffer_ptr = c->buffer;
2617
-    c->buffer_end = c->buffer + FFM_PACKET_SIZE;
2618
-    c->stream->feed_opened = 1;
2619
-    c->chunked_encoding = !!av_stristr(c->buffer, "Transfer-Encoding: chunked");
2620
-    return 0;
2621
-}
2622
-
2623
-static int http_receive_data(HTTPContext *c)
2624
-{
2625
-    HTTPContext *c1;
2626
-    int len, loop_run = 0;
2627
-
2628
-    while (c->chunked_encoding && !c->chunk_size &&
2629
-           c->buffer_end > c->buffer_ptr) {
2630
-        /* read chunk header, if present */
2631
-        len = recv(c->fd, c->buffer_ptr, 1, 0);
2632
-
2633
-        if (len < 0) {
2634
-            if (ff_neterrno() != AVERROR(EAGAIN) &&
2635
-                ff_neterrno() != AVERROR(EINTR))
2636
-                /* error : close connection */
2637
-                goto fail;
2638
-            return 0;
2639
-        } else if (len == 0) {
2640
-            /* end of connection : close it */
2641
-            goto fail;
2642
-        } else if (c->buffer_ptr - c->buffer >= 2 &&
2643
-                   !memcmp(c->buffer_ptr - 1, "\r\n", 2)) {
2644
-            c->chunk_size = strtol(c->buffer, 0, 16);
2645
-            if (c->chunk_size == 0) // end of stream
2646
-                goto fail;
2647
-            c->buffer_ptr = c->buffer;
2648
-            break;
2649
-        } else if (++loop_run > 10) {
2650
-            /* no chunk header, abort */
2651
-            goto fail;
2652
-        } else {
2653
-            c->buffer_ptr++;
2654
-        }
2655
-    }
2656
-
2657
-    if (c->buffer_end > c->buffer_ptr) {
2658
-        len = recv(c->fd, c->buffer_ptr,
2659
-                   FFMIN(c->chunk_size, c->buffer_end - c->buffer_ptr), 0);
2660
-        if (len < 0) {
2661
-            if (ff_neterrno() != AVERROR(EAGAIN) &&
2662
-                ff_neterrno() != AVERROR(EINTR))
2663
-                /* error : close connection */
2664
-                goto fail;
2665
-        } else if (len == 0)
2666
-            /* end of connection : close it */
2667
-            goto fail;
2668
-        else {
2669
-            c->chunk_size -= len;
2670
-            c->buffer_ptr += len;
2671
-            c->data_count += len;
2672
-            update_datarate(&c->datarate, c->data_count);
2673
-        }
2674
-    }
2675
-
2676
-    if (c->buffer_ptr - c->buffer >= 2 && c->data_count > FFM_PACKET_SIZE) {
2677
-        if (c->buffer[0] != 'f' ||
2678
-            c->buffer[1] != 'm') {
2679
-            http_log("Feed stream has become desynchronized -- disconnecting\n");
2680
-            goto fail;
2681
-        }
2682
-    }
2683
-
2684
-    if (c->buffer_ptr >= c->buffer_end) {
2685
-        FFStream *feed = c->stream;
2686
-        /* a packet has been received : write it in the store, except
2687
-           if header */
2688
-        if (c->data_count > FFM_PACKET_SIZE) {
2689
-            /* XXX: use llseek or url_seek */
2690
-            lseek(c->feed_fd, feed->feed_write_index, SEEK_SET);
2691
-            if (write(c->feed_fd, c->buffer, FFM_PACKET_SIZE) < 0) {
2692
-                http_log("Error writing to feed file: %s\n", strerror(errno));
2693
-                goto fail;
2694
-            }
2695
-
2696
-            feed->feed_write_index += FFM_PACKET_SIZE;
2697
-            /* update file size */
2698
-            if (feed->feed_write_index > c->stream->feed_size)
2699
-                feed->feed_size = feed->feed_write_index;
2700
-
2701
-            /* handle wrap around if max file size reached */
2702
-            if (c->stream->feed_max_size && feed->feed_write_index >= c->stream->feed_max_size)
2703
-                feed->feed_write_index = FFM_PACKET_SIZE;
2704
-
2705
-            /* write index */
2706
-            if (ffm_write_write_index(c->feed_fd, feed->feed_write_index) < 0) {
2707
-                http_log("Error writing index to feed file: %s\n", strerror(errno));
2708
-                goto fail;
2709
-            }
2710
-
2711
-            /* wake up any waiting connections */
2712
-            for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
2713
-                if (c1->state == HTTPSTATE_WAIT_FEED &&
2714
-                    c1->stream->feed == c->stream->feed)
2715
-                    c1->state = HTTPSTATE_SEND_DATA;
2716
-            }
2717
-        } else {
2718
-            /* We have a header in our hands that contains useful data */
2719
-            AVFormatContext *s = avformat_alloc_context();
2720
-            AVIOContext *pb;
2721
-            AVInputFormat *fmt_in;
2722
-            int i;
2723
-
2724
-            if (!s)
2725
-                goto fail;
2726
-
2727
-            /* use feed output format name to find corresponding input format */
2728
-            fmt_in = av_find_input_format(feed->fmt->name);
2729
-            if (!fmt_in)
2730
-                goto fail;
2731
-
2732
-            pb = avio_alloc_context(c->buffer, c->buffer_end - c->buffer,
2733
-                                    0, NULL, NULL, NULL, NULL);
2734
-            pb->seekable = 0;
2735
-
2736
-            s->pb = pb;
2737
-            if (avformat_open_input(&s, c->stream->feed_filename, fmt_in, NULL) < 0) {
2738
-                av_free(pb);
2739
-                goto fail;
2740
-            }
2741
-
2742
-            /* Now we have the actual streams */
2743
-            if (s->nb_streams != feed->nb_streams) {
2744
-                avformat_close_input(&s);
2745
-                av_free(pb);
2746
-                http_log("Feed '%s' stream number does not match registered feed\n",
2747
-                         c->stream->feed_filename);
2748
-                goto fail;
2749
-            }
2750
-
2751
-            for (i = 0; i < s->nb_streams; i++) {
2752
-                AVStream *fst = feed->streams[i];
2753
-                AVStream *st = s->streams[i];
2754
-                avcodec_copy_context(fst->codec, st->codec);
2755
-            }
2756
-
2757
-            avformat_close_input(&s);
2758
-            av_free(pb);
2759
-        }
2760
-        c->buffer_ptr = c->buffer;
2761
-    }
2762
-
2763
-    return 0;
2764
- fail:
2765
-    c->stream->feed_opened = 0;
2766
-    close(c->feed_fd);
2767
-    /* wake up any waiting connections to stop waiting for feed */
2768
-    for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
2769
-        if (c1->state == HTTPSTATE_WAIT_FEED &&
2770
-            c1->stream->feed == c->stream->feed)
2771
-            c1->state = HTTPSTATE_SEND_DATA_TRAILER;
2772
-    }
2773
-    return -1;
2774
-}
2775
-
2776
-/********************************************************************/
2777
-/* RTSP handling */
2778
-
2779
-static void rtsp_reply_header(HTTPContext *c, enum RTSPStatusCode error_number)
2780
-{
2781
-    const char *str;
2782
-    time_t ti;
2783
-    struct tm *tm;
2784
-    char buf2[32];
2785
-
2786
-    switch(error_number) {
2787
-    case RTSP_STATUS_OK:
2788
-        str = "OK";
2789
-        break;
2790
-    case RTSP_STATUS_METHOD:
2791
-        str = "Method Not Allowed";
2792
-        break;
2793
-    case RTSP_STATUS_BANDWIDTH:
2794
-        str = "Not Enough Bandwidth";
2795
-        break;
2796
-    case RTSP_STATUS_SESSION:
2797
-        str = "Session Not Found";
2798
-        break;
2799
-    case RTSP_STATUS_STATE:
2800
-        str = "Method Not Valid in This State";
2801
-        break;
2802
-    case RTSP_STATUS_AGGREGATE:
2803
-        str = "Aggregate operation not allowed";
2804
-        break;
2805
-    case RTSP_STATUS_ONLY_AGGREGATE:
2806
-        str = "Only aggregate operation allowed";
2807
-        break;
2808
-    case RTSP_STATUS_TRANSPORT:
2809
-        str = "Unsupported transport";
2810
-        break;
2811
-    case RTSP_STATUS_INTERNAL:
2812
-        str = "Internal Server Error";
2813
-        break;
2814
-    case RTSP_STATUS_SERVICE:
2815
-        str = "Service Unavailable";
2816
-        break;
2817
-    case RTSP_STATUS_VERSION:
2818
-        str = "RTSP Version not supported";
2819
-        break;
2820
-    default:
2821
-        str = "Unknown Error";
2822
-        break;
2823
-    }
2824
-
2825
-    avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", error_number, str);
2826
-    avio_printf(c->pb, "CSeq: %d\r\n", c->seq);
2827
-
2828
-    /* output GMT time */
2829
-    ti = time(NULL);
2830
-    tm = gmtime(&ti);
2831
-    strftime(buf2, sizeof(buf2), "%a, %d %b %Y %H:%M:%S", tm);
2832
-    avio_printf(c->pb, "Date: %s GMT\r\n", buf2);
2833
-}
2834
-
2835
-static void rtsp_reply_error(HTTPContext *c, enum RTSPStatusCode error_number)
2836
-{
2837
-    rtsp_reply_header(c, error_number);
2838
-    avio_printf(c->pb, "\r\n");
2839
-}
2840
-
2841
-static int rtsp_parse_request(HTTPContext *c)
2842
-{
2843
-    const char *p, *p1, *p2;
2844
-    char cmd[32];
2845
-    char url[1024];
2846
-    char protocol[32];
2847
-    char line[1024];
2848
-    int len;
2849
-    RTSPMessageHeader header1 = { 0 }, *header = &header1;
2850
-
2851
-    c->buffer_ptr[0] = '\0';
2852
-    p = c->buffer;
2853
-
2854
-    get_word(cmd, sizeof(cmd), &p);
2855
-    get_word(url, sizeof(url), &p);
2856
-    get_word(protocol, sizeof(protocol), &p);
2857
-
2858
-    av_strlcpy(c->method, cmd, sizeof(c->method));
2859
-    av_strlcpy(c->url, url, sizeof(c->url));
2860
-    av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
2861
-
2862
-    if (avio_open_dyn_buf(&c->pb) < 0) {
2863
-        /* XXX: cannot do more */
2864
-        c->pb = NULL; /* safety */
2865
-        return -1;
2866
-    }
2867
-
2868
-    /* check version name */
2869
-    if (strcmp(protocol, "RTSP/1.0") != 0) {
2870
-        rtsp_reply_error(c, RTSP_STATUS_VERSION);
2871
-        goto the_end;
2872
-    }
2873
-
2874
-    /* parse each header line */
2875
-    /* skip to next line */
2876
-    while (*p != '\n' && *p != '\0')
2877
-        p++;
2878
-    if (*p == '\n')
2879
-        p++;
2880
-    while (*p != '\0') {
2881
-        p1 = memchr(p, '\n', (char *)c->buffer_ptr - p);
2882
-        if (!p1)
2883
-            break;
2884
-        p2 = p1;
2885
-        if (p2 > p && p2[-1] == '\r')
2886
-            p2--;
2887
-        /* skip empty line */
2888
-        if (p2 == p)
2889
-            break;
2890
-        len = p2 - p;
2891
-        if (len > sizeof(line) - 1)
2892
-            len = sizeof(line) - 1;
2893
-        memcpy(line, p, len);
2894
-        line[len] = '\0';
2895
-        ff_rtsp_parse_line(header, line, NULL, NULL);
2896
-        p = p1 + 1;
2897
-    }
2898
-
2899
-    /* handle sequence number */
2900
-    c->seq = header->seq;
2901
-
2902
-    if (!strcmp(cmd, "DESCRIBE"))
2903
-        rtsp_cmd_describe(c, url);
2904
-    else if (!strcmp(cmd, "OPTIONS"))
2905
-        rtsp_cmd_options(c, url);
2906
-    else if (!strcmp(cmd, "SETUP"))
2907
-        rtsp_cmd_setup(c, url, header);
2908
-    else if (!strcmp(cmd, "PLAY"))
2909
-        rtsp_cmd_play(c, url, header);
2910
-    else if (!strcmp(cmd, "PAUSE"))
2911
-        rtsp_cmd_pause(c, url, header);
2912
-    else if (!strcmp(cmd, "TEARDOWN"))
2913
-        rtsp_cmd_teardown(c, url, header);
2914
-    else
2915
-        rtsp_reply_error(c, RTSP_STATUS_METHOD);
2916
-
2917
- the_end:
2918
-    len = avio_close_dyn_buf(c->pb, &c->pb_buffer);
2919
-    c->pb = NULL; /* safety */
2920
-    if (len < 0) {
2921
-        /* XXX: cannot do more */
2922
-        return -1;
2923
-    }
2924
-    c->buffer_ptr = c->pb_buffer;
2925
-    c->buffer_end = c->pb_buffer + len;
2926
-    c->state = RTSPSTATE_SEND_REPLY;
2927
-    return 0;
2928
-}
2929
-
2930
-static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
2931
-                                   struct in_addr my_ip)
2932
-{
2933
-    AVFormatContext *avc;
2934
-    AVStream *avs = NULL;
2935
-    int i;
2936
-
2937
-    avc =  avformat_alloc_context();
2938
-    if (avc == NULL) {
2939
-        return -1;
2940
-    }
2941
-    av_dict_set(&avc->metadata, "title",
2942
-               stream->title[0] ? stream->title : "No Title", 0);
2943
-    avc->nb_streams = stream->nb_streams;
2944
-    if (stream->is_multicast) {
2945
-        snprintf(avc->filename, 1024, "rtp://%s:%d?multicast=1?ttl=%d",
2946
-                 inet_ntoa(stream->multicast_ip),
2947
-                 stream->multicast_port, stream->multicast_ttl);
2948
-    } else {
2949
-        snprintf(avc->filename, 1024, "rtp://0.0.0.0");
2950
-    }
2951
-
2952
-    if (avc->nb_streams >= INT_MAX/sizeof(*avc->streams) ||
2953
-        !(avc->streams = av_malloc(avc->nb_streams * sizeof(*avc->streams))))
2954
-        goto sdp_done;
2955
-    if (avc->nb_streams >= INT_MAX/sizeof(*avs) ||
2956
-        !(avs = av_malloc(avc->nb_streams * sizeof(*avs))))
2957
-        goto sdp_done;
2958
-
2959
-    for(i = 0; i < stream->nb_streams; i++) {
2960
-        avc->streams[i] = &avs[i];
2961
-        avc->streams[i]->codec = stream->streams[i]->codec;
2962
-    }
2963
-    *pbuffer = av_mallocz(2048);
2964
-    av_sdp_create(&avc, 1, *pbuffer, 2048);
2965
-
2966
- sdp_done:
2967
-    av_free(avc->streams);
2968
-    av_dict_free(&avc->metadata);
2969
-    av_free(avc);
2970
-    av_free(avs);
2971
-
2972
-    return strlen(*pbuffer);
2973
-}
2974
-
2975
-static void rtsp_cmd_options(HTTPContext *c, const char *url)
2976
-{
2977
-//    rtsp_reply_header(c, RTSP_STATUS_OK);
2978
-    avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", RTSP_STATUS_OK, "OK");
2979
-    avio_printf(c->pb, "CSeq: %d\r\n", c->seq);
2980
-    avio_printf(c->pb, "Public: %s\r\n", "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
2981
-    avio_printf(c->pb, "\r\n");
2982
-}
2983
-
2984
-static void rtsp_cmd_describe(HTTPContext *c, const char *url)
2985
-{
2986
-    FFStream *stream;
2987
-    char path1[1024];
2988
-    const char *path;
2989
-    uint8_t *content;
2990
-    int content_length;
2991
-    socklen_t len;
2992
-    struct sockaddr_in my_addr;
2993
-
2994
-    /* find which url is asked */
2995
-    av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
2996
-    path = path1;
2997
-    if (*path == '/')
2998
-        path++;
2999
-
3000
-    for(stream = first_stream; stream != NULL; stream = stream->next) {
3001
-        if (!stream->is_feed &&
3002
-            stream->fmt && !strcmp(stream->fmt->name, "rtp") &&
3003
-            !strcmp(path, stream->filename)) {
3004
-            goto found;
3005
-        }
3006
-    }
3007
-    /* no stream found */
3008
-    rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
3009
-    return;
3010
-
3011
- found:
3012
-    /* prepare the media description in sdp format */
3013
-
3014
-    /* get the host IP */
3015
-    len = sizeof(my_addr);
3016
-    getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
3017
-    content_length = prepare_sdp_description(stream, &content, my_addr.sin_addr);
3018
-    if (content_length < 0) {
3019
-        rtsp_reply_error(c, RTSP_STATUS_INTERNAL);
3020
-        return;
3021
-    }
3022
-    rtsp_reply_header(c, RTSP_STATUS_OK);
3023
-    avio_printf(c->pb, "Content-Base: %s/\r\n", url);
3024
-    avio_printf(c->pb, "Content-Type: application/sdp\r\n");
3025
-    avio_printf(c->pb, "Content-Length: %d\r\n", content_length);
3026
-    avio_printf(c->pb, "\r\n");
3027
-    avio_write(c->pb, content, content_length);
3028
-    av_free(content);
3029
-}
3030
-
3031
-static HTTPContext *find_rtp_session(const char *session_id)
3032
-{
3033
-    HTTPContext *c;
3034
-
3035
-    if (session_id[0] == '\0')
3036
-        return NULL;
3037
-
3038
-    for(c = first_http_ctx; c != NULL; c = c->next) {
3039
-        if (!strcmp(c->session_id, session_id))
3040
-            return c;
3041
-    }
3042
-    return NULL;
3043
-}
3044
-
3045
-static RTSPTransportField *find_transport(RTSPMessageHeader *h, enum RTSPLowerTransport lower_transport)
3046
-{
3047
-    RTSPTransportField *th;
3048
-    int i;
3049
-
3050
-    for(i=0;i<h->nb_transports;i++) {
3051
-        th = &h->transports[i];
3052
-        if (th->lower_transport == lower_transport)
3053
-            return th;
3054
-    }
3055
-    return NULL;
3056
-}
3057
-
3058
-static void rtsp_cmd_setup(HTTPContext *c, const char *url,
3059
-                           RTSPMessageHeader *h)
3060
-{
3061
-    FFStream *stream;
3062
-    int stream_index, rtp_port, rtcp_port;
3063
-    char buf[1024];
3064
-    char path1[1024];
3065
-    const char *path;
3066
-    HTTPContext *rtp_c;
3067
-    RTSPTransportField *th;
3068
-    struct sockaddr_in dest_addr;
3069
-    RTSPActionServerSetup setup;
3070
-
3071
-    /* find which url is asked */
3072
-    av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3073
-    path = path1;
3074
-    if (*path == '/')
3075
-        path++;
3076
-
3077
-    /* now check each stream */
3078
-    for(stream = first_stream; stream != NULL; stream = stream->next) {
3079
-        if (!stream->is_feed &&
3080
-            stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
3081
-            /* accept aggregate filenames only if single stream */
3082
-            if (!strcmp(path, stream->filename)) {
3083
-                if (stream->nb_streams != 1) {
3084
-                    rtsp_reply_error(c, RTSP_STATUS_AGGREGATE);
3085
-                    return;
3086
-                }
3087
-                stream_index = 0;
3088
-                goto found;
3089
-            }
3090
-
3091
-            for(stream_index = 0; stream_index < stream->nb_streams;
3092
-                stream_index++) {
3093
-                snprintf(buf, sizeof(buf), "%s/streamid=%d",
3094
-                         stream->filename, stream_index);
3095
-                if (!strcmp(path, buf))
3096
-                    goto found;
3097
-            }
3098
-        }
3099
-    }
3100
-    /* no stream found */
3101
-    rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
3102
-    return;
3103
- found:
3104
-
3105
-    /* generate session id if needed */
3106
-    if (h->session_id[0] == '\0')
3107
-        snprintf(h->session_id, sizeof(h->session_id), "%08x%08x",
3108
-                 av_lfg_get(&random_state), av_lfg_get(&random_state));
3109
-
3110
-    /* find rtp session, and create it if none found */
3111
-    rtp_c = find_rtp_session(h->session_id);
3112
-    if (!rtp_c) {
3113
-        /* always prefer UDP */
3114
-        th = find_transport(h, RTSP_LOWER_TRANSPORT_UDP);
3115
-        if (!th) {
3116
-            th = find_transport(h, RTSP_LOWER_TRANSPORT_TCP);
3117
-            if (!th) {
3118
-                rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3119
-                return;
3120
-            }
3121
-        }
3122
-
3123
-        rtp_c = rtp_new_connection(&c->from_addr, stream, h->session_id,
3124
-                                   th->lower_transport);
3125
-        if (!rtp_c) {
3126
-            rtsp_reply_error(c, RTSP_STATUS_BANDWIDTH);
3127
-            return;
3128
-        }
3129
-
3130
-        /* open input stream */
3131
-        if (open_input_stream(rtp_c, "") < 0) {
3132
-            rtsp_reply_error(c, RTSP_STATUS_INTERNAL);
3133
-            return;
3134
-        }
3135
-    }
3136
-
3137
-    /* test if stream is OK (test needed because several SETUP needs
3138
-       to be done for a given file) */
3139
-    if (rtp_c->stream != stream) {
3140
-        rtsp_reply_error(c, RTSP_STATUS_SERVICE);
3141
-        return;
3142
-    }
3143
-
3144
-    /* test if stream is already set up */
3145
-    if (rtp_c->rtp_ctx[stream_index]) {
3146
-        rtsp_reply_error(c, RTSP_STATUS_STATE);
3147
-        return;
3148
-    }
3149
-
3150
-    /* check transport */
3151
-    th = find_transport(h, rtp_c->rtp_protocol);
3152
-    if (!th || (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
3153
-                th->client_port_min <= 0)) {
3154
-        rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3155
-        return;
3156
-    }
3157
-
3158
-    /* setup default options */
3159
-    setup.transport_option[0] = '\0';
3160
-    dest_addr = rtp_c->from_addr;
3161
-    dest_addr.sin_port = htons(th->client_port_min);
3162
-
3163
-    /* setup stream */
3164
-    if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, c) < 0) {
3165
-        rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
3166
-        return;
3167
-    }
3168
-
3169
-    /* now everything is OK, so we can send the connection parameters */
3170
-    rtsp_reply_header(c, RTSP_STATUS_OK);
3171
-    /* session ID */
3172
-    avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3173
-
3174
-    switch(rtp_c->rtp_protocol) {
3175
-    case RTSP_LOWER_TRANSPORT_UDP:
3176
-        rtp_port = ff_rtp_get_local_rtp_port(rtp_c->rtp_handles[stream_index]);
3177
-        rtcp_port = ff_rtp_get_local_rtcp_port(rtp_c->rtp_handles[stream_index]);
3178
-        avio_printf(c->pb, "Transport: RTP/AVP/UDP;unicast;"
3179
-                    "client_port=%d-%d;server_port=%d-%d",
3180
-                    th->client_port_min, th->client_port_max,
3181
-                    rtp_port, rtcp_port);
3182
-        break;
3183
-    case RTSP_LOWER_TRANSPORT_TCP:
3184
-        avio_printf(c->pb, "Transport: RTP/AVP/TCP;interleaved=%d-%d",
3185
-                    stream_index * 2, stream_index * 2 + 1);
3186
-        break;
3187
-    default:
3188
-        break;
3189
-    }
3190
-    if (setup.transport_option[0] != '\0')
3191
-        avio_printf(c->pb, ";%s", setup.transport_option);
3192
-    avio_printf(c->pb, "\r\n");
3193
-
3194
-
3195
-    avio_printf(c->pb, "\r\n");
3196
-}
3197
-
3198
-
3199
-/* find an rtp connection by using the session ID. Check consistency
3200
-   with filename */
3201
-static HTTPContext *find_rtp_session_with_url(const char *url,
3202
-                                              const char *session_id)
3203
-{
3204
-    HTTPContext *rtp_c;
3205
-    char path1[1024];
3206
-    const char *path;
3207
-    char buf[1024];
3208
-    int s, len;
3209
-
3210
-    rtp_c = find_rtp_session(session_id);
3211
-    if (!rtp_c)
3212
-        return NULL;
3213
-
3214
-    /* find which url is asked */
3215
-    av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3216
-    path = path1;
3217
-    if (*path == '/')
3218
-        path++;
3219
-    if(!strcmp(path, rtp_c->stream->filename)) return rtp_c;
3220
-    for(s=0; s<rtp_c->stream->nb_streams; ++s) {
3221
-      snprintf(buf, sizeof(buf), "%s/streamid=%d",
3222
-        rtp_c->stream->filename, s);
3223
-      if(!strncmp(path, buf, sizeof(buf))) {
3224
-    // XXX: Should we reply with RTSP_STATUS_ONLY_AGGREGATE if nb_streams>1?
3225
-        return rtp_c;
3226
-      }
3227
-    }
3228
-    len = strlen(path);
3229
-    if (len > 0 && path[len - 1] == '/' &&
3230
-        !strncmp(path, rtp_c->stream->filename, len - 1))
3231
-        return rtp_c;
3232
-    return NULL;
3233
-}
3234
-
3235
-static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3236
-{
3237
-    HTTPContext *rtp_c;
3238
-
3239
-    rtp_c = find_rtp_session_with_url(url, h->session_id);
3240
-    if (!rtp_c) {
3241
-        rtsp_reply_error(c, RTSP_STATUS_SESSION);
3242
-        return;
3243
-    }
3244
-
3245
-    if (rtp_c->state != HTTPSTATE_SEND_DATA &&
3246
-        rtp_c->state != HTTPSTATE_WAIT_FEED &&
3247
-        rtp_c->state != HTTPSTATE_READY) {
3248
-        rtsp_reply_error(c, RTSP_STATUS_STATE);
3249
-        return;
3250
-    }
3251
-
3252
-    rtp_c->state = HTTPSTATE_SEND_DATA;
3253
-
3254
-    /* now everything is OK, so we can send the connection parameters */
3255
-    rtsp_reply_header(c, RTSP_STATUS_OK);
3256
-    /* session ID */
3257
-    avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3258
-    avio_printf(c->pb, "\r\n");
3259
-}
3260
-
3261
-static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3262
-{
3263
-    HTTPContext *rtp_c;
3264
-
3265
-    rtp_c = find_rtp_session_with_url(url, h->session_id);
3266
-    if (!rtp_c) {
3267
-        rtsp_reply_error(c, RTSP_STATUS_SESSION);
3268
-        return;
3269
-    }
3270
-
3271
-    if (rtp_c->state != HTTPSTATE_SEND_DATA &&
3272
-        rtp_c->state != HTTPSTATE_WAIT_FEED) {
3273
-        rtsp_reply_error(c, RTSP_STATUS_STATE);
3274
-        return;
3275
-    }
3276
-
3277
-    rtp_c->state = HTTPSTATE_READY;
3278
-    rtp_c->first_pts = AV_NOPTS_VALUE;
3279
-    /* now everything is OK, so we can send the connection parameters */
3280
-    rtsp_reply_header(c, RTSP_STATUS_OK);
3281
-    /* session ID */
3282
-    avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3283
-    avio_printf(c->pb, "\r\n");
3284
-}
3285
-
3286
-static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3287
-{
3288
-    HTTPContext *rtp_c;
3289
-
3290
-    rtp_c = find_rtp_session_with_url(url, h->session_id);
3291
-    if (!rtp_c) {
3292
-        rtsp_reply_error(c, RTSP_STATUS_SESSION);
3293
-        return;
3294
-    }
3295
-
3296
-    /* now everything is OK, so we can send the connection parameters */
3297
-    rtsp_reply_header(c, RTSP_STATUS_OK);
3298
-    /* session ID */
3299
-    avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3300
-    avio_printf(c->pb, "\r\n");
3301
-
3302
-    /* abort the session */
3303
-    close_connection(rtp_c);
3304
-}
3305
-
3306
-
3307
-/********************************************************************/
3308
-/* RTP handling */
3309
-
3310
-static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
3311
-                                       FFStream *stream, const char *session_id,
3312
-                                       enum RTSPLowerTransport rtp_protocol)
3313
-{
3314
-    HTTPContext *c = NULL;
3315
-    const char *proto_str;
3316
-
3317
-    /* XXX: should output a warning page when coming
3318
-       close to the connection limit */
3319
-    if (nb_connections >= nb_max_connections)
3320
-        goto fail;
3321
-
3322
-    /* add a new connection */
3323
-    c = av_mallocz(sizeof(HTTPContext));
3324
-    if (!c)
3325
-        goto fail;
3326
-
3327
-    c->fd = -1;
3328
-    c->poll_entry = NULL;
3329
-    c->from_addr = *from_addr;
3330
-    c->buffer_size = IOBUFFER_INIT_SIZE;
3331
-    c->buffer = av_malloc(c->buffer_size);
3332
-    if (!c->buffer)
3333
-        goto fail;
3334
-    nb_connections++;
3335
-    c->stream = stream;
3336
-    av_strlcpy(c->session_id, session_id, sizeof(c->session_id));
3337
-    c->state = HTTPSTATE_READY;
3338
-    c->is_packetized = 1;
3339
-    c->rtp_protocol = rtp_protocol;
3340
-
3341
-    /* protocol is shown in statistics */
3342
-    switch(c->rtp_protocol) {
3343
-    case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
3344
-        proto_str = "MCAST";
3345
-        break;
3346
-    case RTSP_LOWER_TRANSPORT_UDP:
3347
-        proto_str = "UDP";
3348
-        break;
3349
-    case RTSP_LOWER_TRANSPORT_TCP:
3350
-        proto_str = "TCP";
3351
-        break;
3352
-    default:
3353
-        proto_str = "???";
3354
-        break;
3355
-    }
3356
-    av_strlcpy(c->protocol, "RTP/", sizeof(c->protocol));
3357
-    av_strlcat(c->protocol, proto_str, sizeof(c->protocol));
3358
-
3359
-    current_bandwidth += stream->bandwidth;
3360
-
3361
-    c->next = first_http_ctx;
3362
-    first_http_ctx = c;
3363
-    return c;
3364
-
3365
- fail:
3366
-    if (c) {
3367
-        av_free(c->buffer);
3368
-        av_free(c);
3369
-    }
3370
-    return NULL;
3371
-}
3372
-
3373
-/* add a new RTP stream in an RTP connection (used in RTSP SETUP
3374
-   command). If RTP/TCP protocol is used, TCP connection 'rtsp_c' is
3375
-   used. */
3376
-static int rtp_new_av_stream(HTTPContext *c,
3377
-                             int stream_index, struct sockaddr_in *dest_addr,
3378
-                             HTTPContext *rtsp_c)
3379
-{
3380
-    AVFormatContext *ctx;
3381
-    AVStream *st;
3382
-    char *ipaddr;
3383
-    URLContext *h = NULL;
3384
-    uint8_t *dummy_buf;
3385
-    int max_packet_size;
3386
-
3387
-    /* now we can open the relevant output stream */
3388
-    ctx = avformat_alloc_context();
3389
-    if (!ctx)
3390
-        return -1;
3391
-    ctx->oformat = av_guess_format("rtp", NULL, NULL);
3392
-
3393
-    st = av_mallocz(sizeof(AVStream));
3394
-    if (!st)
3395
-        goto fail;
3396
-    ctx->nb_streams = 1;
3397
-    ctx->streams = av_mallocz(sizeof(AVStream *) * ctx->nb_streams);
3398
-    if (!ctx->streams)
3399
-      goto fail;
3400
-    ctx->streams[0] = st;
3401
-
3402
-    if (!c->stream->feed ||
3403
-        c->stream->feed == c->stream)
3404
-        memcpy(st, c->stream->streams[stream_index], sizeof(AVStream));
3405
-    else
3406
-        memcpy(st,
3407
-               c->stream->feed->streams[c->stream->feed_streams[stream_index]],
3408
-               sizeof(AVStream));
3409
-    st->priv_data = NULL;
3410
-
3411
-    /* build destination RTP address */
3412
-    ipaddr = inet_ntoa(dest_addr->sin_addr);
3413
-
3414
-    switch(c->rtp_protocol) {
3415
-    case RTSP_LOWER_TRANSPORT_UDP:
3416
-    case RTSP_LOWER_TRANSPORT_UDP_MULTICAST:
3417
-        /* RTP/UDP case */
3418
-
3419
-        /* XXX: also pass as parameter to function ? */
3420
-        if (c->stream->is_multicast) {
3421
-            int ttl;
3422
-            ttl = c->stream->multicast_ttl;
3423
-            if (!ttl)
3424
-                ttl = 16;
3425
-            snprintf(ctx->filename, sizeof(ctx->filename),
3426
-                     "rtp://%s:%d?multicast=1&ttl=%d",
3427
-                     ipaddr, ntohs(dest_addr->sin_port), ttl);
3428
-        } else {
3429
-            snprintf(ctx->filename, sizeof(ctx->filename),
3430
-                     "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
3431
-        }
3432
-
3433
-        if (ffurl_open(&h, ctx->filename, AVIO_FLAG_WRITE, NULL, NULL) < 0)
3434
-            goto fail;
3435
-        c->rtp_handles[stream_index] = h;
3436
-        max_packet_size = h->max_packet_size;
3437
-        break;
3438
-    case RTSP_LOWER_TRANSPORT_TCP:
3439
-        /* RTP/TCP case */
3440
-        c->rtsp_c = rtsp_c;
3441
-        max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
3442
-        break;
3443
-    default:
3444
-        goto fail;
3445
-    }
3446
-
3447
-    http_log("%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
3448
-             ipaddr, ntohs(dest_addr->sin_port),
3449
-             c->stream->filename, stream_index, c->protocol);
3450
-
3451
-    /* normally, no packets should be output here, but the packet size may be checked */
3452
-    if (ffio_open_dyn_packet_buf(&ctx->pb, max_packet_size) < 0) {
3453
-        /* XXX: close stream */
3454
-        goto fail;
3455
-    }
3456
-    if (avformat_write_header(ctx, NULL) < 0) {
3457
-    fail:
3458
-        if (h)
3459
-            ffurl_close(h);
3460
-        av_free(ctx);
3461
-        return -1;
3462
-    }
3463
-    avio_close_dyn_buf(ctx->pb, &dummy_buf);
3464
-    av_free(dummy_buf);
3465
-
3466
-    c->rtp_ctx[stream_index] = ctx;
3467
-    return 0;
3468
-}
3469
-
3470
-/********************************************************************/
3471
-/* avserver initialization */
3472
-
3473
-static AVStream *add_av_stream1(FFStream *stream, AVCodecContext *codec, int copy)
3474
-{
3475
-    AVStream *fst;
3476
-
3477
-    fst = av_mallocz(sizeof(AVStream));
3478
-    if (!fst)
3479
-        return NULL;
3480
-    if (copy) {
3481
-        fst->codec = avcodec_alloc_context3(NULL);
3482
-        memcpy(fst->codec, codec, sizeof(AVCodecContext));
3483
-        if (codec->extradata_size) {
3484
-            fst->codec->extradata = av_malloc(codec->extradata_size);
3485
-            memcpy(fst->codec->extradata, codec->extradata,
3486
-                codec->extradata_size);
3487
-        }
3488
-    } else {
3489
-        /* live streams must use the actual feed's codec since it may be
3490
-         * updated later to carry extradata needed by the streams.
3491
-         */
3492
-        fst->codec = codec;
3493
-    }
3494
-    fst->priv_data = av_mallocz(sizeof(FeedData));
3495
-    fst->index = stream->nb_streams;
3496
-    avpriv_set_pts_info(fst, 33, 1, 90000);
3497
-    fst->sample_aspect_ratio = codec->sample_aspect_ratio;
3498
-    stream->streams[stream->nb_streams++] = fst;
3499
-    return fst;
3500
-}
3501
-
3502
-/* return the stream number in the feed */
3503
-static int add_av_stream(FFStream *feed, AVStream *st)
3504
-{
3505
-    AVStream *fst;
3506
-    AVCodecContext *av, *av1;
3507
-    int i;
3508
-
3509
-    av = st->codec;
3510
-    for(i=0;i<feed->nb_streams;i++) {
3511
-        st = feed->streams[i];
3512
-        av1 = st->codec;
3513
-        if (av1->codec_id == av->codec_id &&
3514
-            av1->codec_type == av->codec_type &&
3515
-            av1->bit_rate == av->bit_rate) {
3516
-
3517
-            switch(av->codec_type) {
3518
-            case AVMEDIA_TYPE_AUDIO:
3519
-                if (av1->channels == av->channels &&
3520
-                    av1->sample_rate == av->sample_rate)
3521
-                    return i;
3522
-                break;
3523
-            case AVMEDIA_TYPE_VIDEO:
3524
-                if (av1->width == av->width &&
3525
-                    av1->height == av->height &&
3526
-                    av1->time_base.den == av->time_base.den &&
3527
-                    av1->time_base.num == av->time_base.num &&
3528
-                    av1->gop_size == av->gop_size)
3529
-                    return i;
3530
-                break;
3531
-            default:
3532
-                abort();
3533
-            }
3534
-        }
3535
-    }
3536
-
3537
-    fst = add_av_stream1(feed, av, 0);
3538
-    if (!fst)
3539
-        return -1;
3540
-    return feed->nb_streams - 1;
3541
-}
3542
-
3543
-static void remove_stream(FFStream *stream)
3544
-{
3545
-    FFStream **ps;
3546
-    ps = &first_stream;
3547
-    while (*ps != NULL) {
3548
-        if (*ps == stream)
3549
-            *ps = (*ps)->next;
3550
-        else
3551
-            ps = &(*ps)->next;
3552
-    }
3553
-}
3554
-
3555
-/* specific mpeg4 handling : we extract the raw parameters */
3556
-static void extract_mpeg4_header(AVFormatContext *infile)
3557
-{
3558
-    int mpeg4_count, i, size;
3559
-    AVPacket pkt;
3560
-    AVStream *st;
3561
-    const uint8_t *p;
3562
-
3563
-    infile->flags |= AVFMT_FLAG_NOFILLIN | AVFMT_FLAG_NOPARSE;
3564
-
3565
-    mpeg4_count = 0;
3566
-    for(i=0;i<infile->nb_streams;i++) {
3567
-        st = infile->streams[i];
3568
-        if (st->codec->codec_id == AV_CODEC_ID_MPEG4 &&
3569
-            st->codec->extradata_size == 0) {
3570
-            mpeg4_count++;
3571
-        }
3572
-    }
3573
-    if (!mpeg4_count)
3574
-        return;
3575
-
3576
-    printf("MPEG4 without extra data: trying to find header in %s\n", infile->filename);
3577
-    while (mpeg4_count > 0) {
3578
-        if (av_read_frame(infile, &pkt) < 0)
3579
-            break;
3580
-        st = infile->streams[pkt.stream_index];
3581
-        if (st->codec->codec_id == AV_CODEC_ID_MPEG4 &&
3582
-            st->codec->extradata_size == 0) {
3583
-            av_freep(&st->codec->extradata);
3584
-            /* fill extradata with the header */
3585
-            /* XXX: we make hard suppositions here ! */
3586
-            p = pkt.data;
3587
-            while (p < pkt.data + pkt.size - 4) {
3588
-                /* stop when vop header is found */
3589
-                if (p[0] == 0x00 && p[1] == 0x00 &&
3590
-                    p[2] == 0x01 && p[3] == 0xb6) {
3591
-                    size = p - pkt.data;
3592
-                    //                    av_hex_dump_log(infile, AV_LOG_DEBUG, pkt.data, size);
3593
-                    st->codec->extradata = av_malloc(size);
3594
-                    st->codec->extradata_size = size;
3595
-                    memcpy(st->codec->extradata, pkt.data, size);
3596
-                    break;
3597
-                }
3598
-                p++;
3599
-            }
3600
-            mpeg4_count--;
3601
-        }
3602
-        av_free_packet(&pkt);
3603
-    }
3604
-}
3605
-
3606
-/* compute the needed AVStream for each file */
3607
-static void build_file_streams(void)
3608
-{
3609
-    FFStream *stream, *stream_next;
3610
-    int i, ret;
3611
-
3612
-    /* gather all streams */
3613
-    for(stream = first_stream; stream != NULL; stream = stream_next) {
3614
-        AVFormatContext *infile = NULL;
3615
-        stream_next = stream->next;
3616
-        if (stream->stream_type == STREAM_TYPE_LIVE &&
3617
-            !stream->feed) {
3618
-            /* the stream comes from a file */
3619
-            /* try to open the file */
3620
-            /* open stream */
3621
-            if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
3622
-                /* specific case : if transport stream output to RTP,
3623
-                   we use a raw transport stream reader */
3624
-                av_dict_set(&stream->in_opts, "mpeg2ts_compute_pcr", "1", 0);
3625
-            }
3626
-
3627
-            http_log("Opening file '%s'\n", stream->feed_filename);
3628
-            if ((ret = avformat_open_input(&infile, stream->feed_filename, stream->ifmt, &stream->in_opts)) < 0) {
3629
-                http_log("Could not open '%s': %d\n", stream->feed_filename, ret);
3630
-                /* remove stream (no need to spend more time on it) */
3631
-            fail:
3632
-                remove_stream(stream);
3633
-            } else {
3634
-                /* find all the AVStreams inside and reference them in
3635
-                   'stream' */
3636
-                if (avformat_find_stream_info(infile, NULL) < 0) {
3637
-                    http_log("Could not find codec parameters from '%s'\n",
3638
-                             stream->feed_filename);
3639
-                    avformat_close_input(&infile);
3640
-                    goto fail;
3641
-                }
3642
-                extract_mpeg4_header(infile);
3643
-
3644
-                for(i=0;i<infile->nb_streams;i++)
3645
-                    add_av_stream1(stream, infile->streams[i]->codec, 1);
3646
-
3647
-                avformat_close_input(&infile);
3648
-            }
3649
-        }
3650
-    }
3651
-}
3652
-
3653
-/* compute the needed AVStream for each feed */
3654
-static void build_feed_streams(void)
3655
-{
3656
-    FFStream *stream, *feed;
3657
-    int i;
3658
-
3659
-    /* gather all streams */
3660
-    for(stream = first_stream; stream != NULL; stream = stream->next) {
3661
-        feed = stream->feed;
3662
-        if (feed) {
3663
-            if (stream->is_feed) {
3664
-                for(i=0;i<stream->nb_streams;i++)
3665
-                    stream->feed_streams[i] = i;
3666
-            } else {
3667
-                /* we handle a stream coming from a feed */
3668
-                for(i=0;i<stream->nb_streams;i++)
3669
-                    stream->feed_streams[i] = add_av_stream(feed, stream->streams[i]);
3670
-            }
3671
-        }
3672
-    }
3673
-
3674
-    /* create feed files if needed */
3675
-    for(feed = first_feed; feed != NULL; feed = feed->next_feed) {
3676
-        int fd;
3677
-
3678
-        if (avio_check(feed->feed_filename, AVIO_FLAG_READ) > 0) {
3679
-            /* See if it matches */
3680
-            AVFormatContext *s = NULL;
3681
-            int matches = 0;
3682
-
3683
-            if (avformat_open_input(&s, feed->feed_filename, NULL, NULL) >= 0) {
3684
-                /* Now see if it matches */
3685
-                if (s->nb_streams == feed->nb_streams) {
3686
-                    matches = 1;
3687
-                    for(i=0;i<s->nb_streams;i++) {
3688
-                        AVStream *sf, *ss;
3689
-                        sf = feed->streams[i];
3690
-                        ss = s->streams[i];
3691
-
3692
-                        if (sf->index != ss->index ||
3693
-                            sf->id != ss->id) {
3694
-                            http_log("Index & Id do not match for stream %d (%s)\n",
3695
-                                   i, feed->feed_filename);
3696
-                            matches = 0;
3697
-                        } else {
3698
-                            AVCodecContext *ccf, *ccs;
3699
-
3700
-                            ccf = sf->codec;
3701
-                            ccs = ss->codec;
3702
-#define CHECK_CODEC(x)  (ccf->x != ccs->x)
3703
-
3704
-                            if (CHECK_CODEC(codec_id) || CHECK_CODEC(codec_type)) {
3705
-                                http_log("Codecs do not match for stream %d\n", i);
3706
-                                matches = 0;
3707
-                            } else if (CHECK_CODEC(bit_rate) || CHECK_CODEC(flags)) {
3708
-                                http_log("Codec bitrates do not match for stream %d\n", i);
3709
-                                matches = 0;
3710
-                            } else if (ccf->codec_type == AVMEDIA_TYPE_VIDEO) {
3711
-                                if (CHECK_CODEC(time_base.den) ||
3712
-                                    CHECK_CODEC(time_base.num) ||
3713
-                                    CHECK_CODEC(width) ||
3714
-                                    CHECK_CODEC(height)) {
3715
-                                    http_log("Codec width, height and framerate do not match for stream %d\n", i);
3716
-                                    matches = 0;
3717
-                                }
3718
-                            } else if (ccf->codec_type == AVMEDIA_TYPE_AUDIO) {
3719
-                                if (CHECK_CODEC(sample_rate) ||
3720
-                                    CHECK_CODEC(channels) ||
3721
-                                    CHECK_CODEC(frame_size)) {
3722
-                                    http_log("Codec sample_rate, channels, frame_size do not match for stream %d\n", i);
3723
-                                    matches = 0;
3724
-                                }
3725
-                            } else {
3726
-                                http_log("Unknown codec type\n");
3727
-                                matches = 0;
3728
-                            }
3729
-                        }
3730
-                        if (!matches)
3731
-                            break;
3732
-                    }
3733
-                } else
3734
-                    http_log("Deleting feed file '%s' as stream counts differ (%d != %d)\n",
3735
-                        feed->feed_filename, s->nb_streams, feed->nb_streams);
3736
-
3737
-                avformat_close_input(&s);
3738
-            } else
3739
-                http_log("Deleting feed file '%s' as it appears to be corrupt\n",
3740
-                        feed->feed_filename);
3741
-
3742
-            if (!matches) {
3743
-                if (feed->readonly) {
3744
-                    http_log("Unable to delete feed file '%s' as it is marked readonly\n",
3745
-                        feed->feed_filename);
3746
-                    exit(1);
3747
-                }
3748
-                unlink(feed->feed_filename);
3749
-            }
3750
-        }
3751
-        if (avio_check(feed->feed_filename, AVIO_FLAG_WRITE) <= 0) {
3752
-            AVFormatContext s1 = {0}, *s = &s1;
3753
-
3754
-            if (feed->readonly) {
3755
-                http_log("Unable to create feed file '%s' as it is marked readonly\n",
3756
-                    feed->feed_filename);
3757
-                exit(1);
3758
-            }
3759
-
3760
-            /* only write the header of the ffm file */
3761
-            if (avio_open(&s->pb, feed->feed_filename, AVIO_FLAG_WRITE) < 0) {
3762
-                http_log("Could not open output feed file '%s'\n",
3763
-                         feed->feed_filename);
3764
-                exit(1);
3765
-            }
3766
-            s->oformat = feed->fmt;
3767
-            s->nb_streams = feed->nb_streams;
3768
-            s->streams = feed->streams;
3769
-            if (avformat_write_header(s, NULL) < 0) {
3770
-                http_log("Container doesn't supports the required parameters\n");
3771
-                exit(1);
3772
-            }
3773
-            /* XXX: need better api */
3774
-            av_freep(&s->priv_data);
3775
-            avio_close(s->pb);
3776
-        }
3777
-        /* get feed size and write index */
3778
-        fd = open(feed->feed_filename, O_RDONLY);
3779
-        if (fd < 0) {
3780
-            http_log("Could not open output feed file '%s'\n",
3781
-                    feed->feed_filename);
3782
-            exit(1);
3783
-        }
3784
-
3785
-        feed->feed_write_index = FFMAX(ffm_read_write_index(fd), FFM_PACKET_SIZE);
3786
-        feed->feed_size = lseek(fd, 0, SEEK_END);
3787
-        /* ensure that we do not wrap before the end of file */
3788
-        if (feed->feed_max_size && feed->feed_max_size < feed->feed_size)
3789
-            feed->feed_max_size = feed->feed_size;
3790
-
3791
-        close(fd);
3792
-    }
3793
-}
3794
-
3795
-/* compute the bandwidth used by each stream */
3796
-static void compute_bandwidth(void)
3797
-{
3798
-    unsigned bandwidth;
3799
-    int i;
3800
-    FFStream *stream;
3801
-
3802
-    for(stream = first_stream; stream != NULL; stream = stream->next) {
3803
-        bandwidth = 0;
3804
-        for(i=0;i<stream->nb_streams;i++) {
3805
-            AVStream *st = stream->streams[i];
3806
-            switch(st->codec->codec_type) {
3807
-            case AVMEDIA_TYPE_AUDIO:
3808
-            case AVMEDIA_TYPE_VIDEO:
3809
-                bandwidth += st->codec->bit_rate;
3810
-                break;
3811
-            default:
3812
-                break;
3813
-            }
3814
-        }
3815
-        stream->bandwidth = (bandwidth + 999) / 1000;
3816
-    }
3817
-}
3818
-
3819
-/* add a codec and set the default parameters */
3820
-static void add_codec(FFStream *stream, AVCodecContext *av)
3821
-{
3822
-    AVStream *st;
3823
-
3824
-    /* compute default parameters */
3825
-    switch(av->codec_type) {
3826
-    case AVMEDIA_TYPE_AUDIO:
3827
-        if (av->bit_rate == 0)
3828
-            av->bit_rate = 64000;
3829
-        if (av->sample_rate == 0)
3830
-            av->sample_rate = 22050;
3831
-        if (av->channels == 0)
3832
-            av->channels = 1;
3833
-        break;
3834
-    case AVMEDIA_TYPE_VIDEO:
3835
-        if (av->bit_rate == 0)
3836
-            av->bit_rate = 64000;
3837
-        if (av->time_base.num == 0){
3838
-            av->time_base.den = 5;
3839
-            av->time_base.num = 1;
3840
-        }
3841
-        if (av->width == 0 || av->height == 0) {
3842
-            av->width = 160;
3843
-            av->height = 128;
3844
-        }
3845
-        /* Bitrate tolerance is less for streaming */
3846
-        if (av->bit_rate_tolerance == 0)
3847
-            av->bit_rate_tolerance = FFMAX(av->bit_rate / 4,
3848
-                      (int64_t)av->bit_rate*av->time_base.num/av->time_base.den);
3849
-        if (av->qmin == 0)
3850
-            av->qmin = 3;
3851
-        if (av->qmax == 0)
3852
-            av->qmax = 31;
3853
-        if (av->max_qdiff == 0)
3854
-            av->max_qdiff = 3;
3855
-        av->qcompress = 0.5;
3856
-        av->qblur = 0.5;
3857
-
3858
-        if (!av->nsse_weight)
3859
-            av->nsse_weight = 8;
3860
-
3861
-        av->frame_skip_cmp = FF_CMP_DCTMAX;
3862
-        if (!av->me_method)
3863
-            av->me_method = ME_EPZS;
3864
-        av->rc_buffer_aggressivity = 1.0;
3865
-
3866
-        if (!av->rc_eq)
3867
-            av->rc_eq = "tex^qComp";
3868
-        if (!av->i_quant_factor)
3869
-            av->i_quant_factor = -0.8;
3870
-        if (!av->b_quant_factor)
3871
-            av->b_quant_factor = 1.25;
3872
-        if (!av->b_quant_offset)
3873
-            av->b_quant_offset = 1.25;
3874
-        if (!av->rc_max_rate)
3875
-            av->rc_max_rate = av->bit_rate * 2;
3876
-
3877
-        if (av->rc_max_rate && !av->rc_buffer_size) {
3878
-            av->rc_buffer_size = av->rc_max_rate;
3879
-        }
3880
-
3881
-
3882
-        break;
3883
-    default:
3884
-        abort();
3885
-    }
3886
-
3887
-    st = av_mallocz(sizeof(AVStream));
3888
-    if (!st)
3889
-        return;
3890
-    st->codec = avcodec_alloc_context3(NULL);
3891
-    stream->streams[stream->nb_streams++] = st;
3892
-    memcpy(st->codec, av, sizeof(AVCodecContext));
3893
-}
3894
-
3895
-static enum AVCodecID opt_audio_codec(const char *arg)
3896
-{
3897
-    AVCodec *p= avcodec_find_encoder_by_name(arg);
3898
-
3899
-    if (p == NULL || p->type != AVMEDIA_TYPE_AUDIO)
3900
-        return AV_CODEC_ID_NONE;
3901
-
3902
-    return p->id;
3903
-}
3904
-
3905
-static enum AVCodecID opt_video_codec(const char *arg)
3906
-{
3907
-    AVCodec *p= avcodec_find_encoder_by_name(arg);
3908
-
3909
-    if (p == NULL || p->type != AVMEDIA_TYPE_VIDEO)
3910
-        return AV_CODEC_ID_NONE;
3911
-
3912
-    return p->id;
3913
-}
3914
-
3915
-static int avserver_opt_default(const char *opt, const char *arg,
3916
-                       AVCodecContext *avctx, int type)
3917
-{
3918
-    int ret = 0;
3919
-    const AVOption *o = av_opt_find(avctx, opt, NULL, type, 0);
3920
-    if(o)
3921
-        ret = av_opt_set(avctx, opt, arg, 0);
3922
-    return ret;
3923
-}
3924
-
3925
-static int avserver_opt_preset(const char *arg,
3926
-                       AVCodecContext *avctx, int type,
3927
-                       enum AVCodecID *audio_id, enum AVCodecID *video_id)
3928
-{
3929
-    FILE *f=NULL;
3930
-    char filename[1000], tmp[1000], tmp2[1000], line[1000];
3931
-    int ret = 0;
3932
-    AVCodec *codec = avcodec_find_encoder(avctx->codec_id);
3933
-
3934
-    if (!(f = get_preset_file(filename, sizeof(filename), arg, 0,
3935
-                              codec ? codec->name : NULL))) {
3936
-        fprintf(stderr, "File for preset '%s' not found\n", arg);
3937
-        return 1;
3938
-    }
3939
-
3940
-    while(!feof(f)){
3941
-        int e= fscanf(f, "%999[^\n]\n", line) - 1;
3942
-        if(line[0] == '#' && !e)
3943
-            continue;
3944
-        e|= sscanf(line, "%999[^=]=%999[^\n]\n", tmp, tmp2) - 2;
3945
-        if(e){
3946
-            fprintf(stderr, "%s: Invalid syntax: '%s'\n", filename, line);
3947
-            ret = 1;
3948
-            break;
3949
-        }
3950
-        if(!strcmp(tmp, "acodec")){
3951
-            *audio_id = opt_audio_codec(tmp2);
3952
-        }else if(!strcmp(tmp, "vcodec")){
3953
-            *video_id = opt_video_codec(tmp2);
3954
-        }else if(!strcmp(tmp, "scodec")){
3955
-            /* opt_subtitle_codec(tmp2); */
3956
-        }else if(avserver_opt_default(tmp, tmp2, avctx, type) < 0){
3957
-            fprintf(stderr, "%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", filename, line, tmp, tmp2);
3958
-            ret = 1;
3959
-            break;
3960
-        }
3961
-    }
3962
-
3963
-    fclose(f);
3964
-
3965
-    return ret;
3966
-}
3967
-
3968
-static AVOutputFormat *avserver_guess_format(const char *short_name, const char *filename,
3969
-                                             const char *mime_type)
3970
-{
3971
-    AVOutputFormat *fmt = av_guess_format(short_name, filename, mime_type);
3972
-
3973
-    if (fmt) {
3974
-        AVOutputFormat *stream_fmt;
3975
-        char stream_format_name[64];
3976
-
3977
-        snprintf(stream_format_name, sizeof(stream_format_name), "%s_stream", fmt->name);
3978
-        stream_fmt = av_guess_format(stream_format_name, NULL, NULL);
3979
-
3980
-        if (stream_fmt)
3981
-            fmt = stream_fmt;
3982
-    }
3983
-
3984
-    return fmt;
3985
-}
3986
-
3987
-static void report_config_error(const char *filename, int line_num, int *errors, const char *fmt, ...)
3988
-{
3989
-    va_list vl;
3990
-    va_start(vl, fmt);
3991
-    fprintf(stderr, "%s:%d: ", filename, line_num);
3992
-    vfprintf(stderr, fmt, vl);
3993
-    va_end(vl);
3994
-
3995
-    (*errors)++;
3996
-}
3997
-
3998
-static int parse_ffconfig(const char *filename)
3999
-{
4000
-    FILE *f;
4001
-    char line[1024];
4002
-    char cmd[64];
4003
-    char arg[1024];
4004
-    const char *p;
4005
-    int val, errors, line_num;
4006
-    FFStream **last_stream, *stream, *redirect;
4007
-    FFStream **last_feed, *feed, *s;
4008
-    AVCodecContext audio_enc, video_enc;
4009
-    enum AVCodecID audio_id, video_id;
4010
-
4011
-    f = fopen(filename, "r");
4012
-    if (!f) {
4013
-        perror(filename);
4014
-        return -1;
4015
-    }
4016
-
4017
-    errors = 0;
4018
-    line_num = 0;
4019
-    first_stream = NULL;
4020
-    last_stream = &first_stream;
4021
-    first_feed = NULL;
4022
-    last_feed = &first_feed;
4023
-    stream = NULL;
4024
-    feed = NULL;
4025
-    redirect = NULL;
4026
-    audio_id = AV_CODEC_ID_NONE;
4027
-    video_id = AV_CODEC_ID_NONE;
4028
-
4029
-#define ERROR(...) report_config_error(filename, line_num, &errors, __VA_ARGS__)
4030
-    for(;;) {
4031
-        if (fgets(line, sizeof(line), f) == NULL)
4032
-            break;
4033
-        line_num++;
4034
-        p = line;
4035
-        while (av_isspace(*p))
4036
-            p++;
4037
-        if (*p == '\0' || *p == '#')
4038
-            continue;
4039
-
4040
-        get_arg(cmd, sizeof(cmd), &p);
4041
-
4042
-        if (!av_strcasecmp(cmd, "Port")) {
4043
-            get_arg(arg, sizeof(arg), &p);
4044
-            val = atoi(arg);
4045
-            if (val < 1 || val > 65536) {
4046
-                ERROR("Invalid_port: %s\n", arg);
4047
-            }
4048
-            my_http_addr.sin_port = htons(val);
4049
-        } else if (!av_strcasecmp(cmd, "BindAddress")) {
4050
-            get_arg(arg, sizeof(arg), &p);
4051
-            if (resolve_host(&my_http_addr.sin_addr, arg) != 0) {
4052
-                ERROR("%s:%d: Invalid host/IP address: %s\n", arg);
4053
-            }
4054
-        } else if (!av_strcasecmp(cmd, "RTSPPort")) {
4055
-            get_arg(arg, sizeof(arg), &p);
4056
-            val = atoi(arg);
4057
-            if (val < 1 || val > 65536) {
4058
-                ERROR("%s:%d: Invalid port: %s\n", arg);
4059
-            }
4060
-            my_rtsp_addr.sin_port = htons(atoi(arg));
4061
-        } else if (!av_strcasecmp(cmd, "RTSPBindAddress")) {
4062
-            get_arg(arg, sizeof(arg), &p);
4063
-            if (resolve_host(&my_rtsp_addr.sin_addr, arg) != 0) {
4064
-                ERROR("Invalid host/IP address: %s\n", arg);
4065
-            }
4066
-        } else if (!av_strcasecmp(cmd, "MaxHTTPConnections")) {
4067
-            get_arg(arg, sizeof(arg), &p);
4068
-            val = atoi(arg);
4069
-            if (val < 1 || val > 65536) {
4070
-                ERROR("Invalid MaxHTTPConnections: %s\n", arg);
4071
-            }
4072
-            nb_max_http_connections = val;
4073
-        } else if (!av_strcasecmp(cmd, "MaxClients")) {
4074
-            get_arg(arg, sizeof(arg), &p);
4075
-            val = atoi(arg);
4076
-            if (val < 1 || val > nb_max_http_connections) {
4077
-                ERROR("Invalid MaxClients: %s\n", arg);
4078
-            } else {
4079
-                nb_max_connections = val;
4080
-            }
4081
-        } else if (!av_strcasecmp(cmd, "MaxBandwidth")) {
4082
-            int64_t llval;
4083
-            get_arg(arg, sizeof(arg), &p);
4084
-            llval = atoll(arg);
4085
-            if (llval < 10 || llval > 10000000) {
4086
-                ERROR("Invalid MaxBandwidth: %s\n", arg);
4087
-            } else
4088
-                max_bandwidth = llval;
4089
-        } else if (!av_strcasecmp(cmd, "CustomLog")) {
4090
-            if (!avserver_debug)
4091
-                get_arg(logfilename, sizeof(logfilename), &p);
4092
-        } else if (!av_strcasecmp(cmd, "<Feed")) {
4093
-            /*********************************************/
4094
-            /* Feed related options */
4095
-            char *q;
4096
-            if (stream || feed) {
4097
-                ERROR("Already in a tag\n");
4098
-            } else {
4099
-                feed = av_mallocz(sizeof(FFStream));
4100
-                get_arg(feed->filename, sizeof(feed->filename), &p);
4101
-                q = strrchr(feed->filename, '>');
4102
-                if (*q)
4103
-                    *q = '\0';
4104
-
4105
-                for (s = first_feed; s; s = s->next) {
4106
-                    if (!strcmp(feed->filename, s->filename)) {
4107
-                        ERROR("Feed '%s' already registered\n", s->filename);
4108
-                    }
4109
-                }
4110
-
4111
-                feed->fmt = av_guess_format("ffm", NULL, NULL);
4112
-                /* defaut feed file */
4113
-                snprintf(feed->feed_filename, sizeof(feed->feed_filename),
4114
-                         "/tmp/%s.ffm", feed->filename);
4115
-                feed->feed_max_size = 5 * 1024 * 1024;
4116
-                feed->is_feed = 1;
4117
-                feed->feed = feed; /* self feeding :-) */
4118
-
4119
-                /* add in stream list */
4120
-                *last_stream = feed;
4121
-                last_stream = &feed->next;
4122
-                /* add in feed list */
4123
-                *last_feed = feed;
4124
-                last_feed = &feed->next_feed;
4125
-            }
4126
-        } else if (!av_strcasecmp(cmd, "Launch")) {
4127
-            if (feed) {
4128
-                int i;
4129
-
4130
-                feed->child_argv = av_mallocz(64 * sizeof(char *));
4131
-
4132
-                for (i = 0; i < 62; i++) {
4133
-                    get_arg(arg, sizeof(arg), &p);
4134
-                    if (!arg[0])
4135
-                        break;
4136
-
4137
-                    feed->child_argv[i] = av_strdup(arg);
4138
-                }
4139
-
4140
-                feed->child_argv[i] = av_malloc(30 + strlen(feed->filename));
4141
-
4142
-                snprintf(feed->child_argv[i], 30+strlen(feed->filename),
4143
-                    "http://%s:%d/%s",
4144
-                        (my_http_addr.sin_addr.s_addr == INADDR_ANY) ? "127.0.0.1" :
4145
-                    inet_ntoa(my_http_addr.sin_addr),
4146
-                    ntohs(my_http_addr.sin_port), feed->filename);
4147
-            }
4148
-        } else if (!av_strcasecmp(cmd, "ReadOnlyFile")) {
4149
-            if (feed) {
4150
-                get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
4151
-                feed->readonly = 1;
4152
-            } else if (stream) {
4153
-                get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4154
-            }
4155
-        } else if (!av_strcasecmp(cmd, "File")) {
4156
-            if (feed) {
4157
-                get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
4158
-            } else if (stream)
4159
-                get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4160
-        } else if (!av_strcasecmp(cmd, "Truncate")) {
4161
-            if (feed) {
4162
-                get_arg(arg, sizeof(arg), &p);
4163
-                feed->truncate = strtod(arg, NULL);
4164
-            }
4165
-        } else if (!av_strcasecmp(cmd, "FileMaxSize")) {
4166
-            if (feed) {
4167
-                char *p1;
4168
-                double fsize;
4169
-
4170
-                get_arg(arg, sizeof(arg), &p);
4171
-                p1 = arg;
4172
-                fsize = strtod(p1, &p1);
4173
-                switch(av_toupper(*p1)) {
4174
-                case 'K':
4175
-                    fsize *= 1024;
4176
-                    break;
4177
-                case 'M':
4178
-                    fsize *= 1024 * 1024;
4179
-                    break;
4180
-                case 'G':
4181
-                    fsize *= 1024 * 1024 * 1024;
4182
-                    break;
4183
-                }
4184
-                feed->feed_max_size = (int64_t)fsize;
4185
-                if (feed->feed_max_size < FFM_PACKET_SIZE*4) {
4186
-                    ERROR("Feed max file size is too small, must be at least %d\n", FFM_PACKET_SIZE*4);
4187
-                }
4188
-            }
4189
-        } else if (!av_strcasecmp(cmd, "</Feed>")) {
4190
-            if (!feed) {
4191
-                ERROR("No corresponding <Feed> for </Feed>\n");
4192
-            }
4193
-            feed = NULL;
4194
-        } else if (!av_strcasecmp(cmd, "<Stream")) {
4195
-            /*********************************************/
4196
-            /* Stream related options */
4197
-            char *q;
4198
-            if (stream || feed) {
4199
-                ERROR("Already in a tag\n");
4200
-            } else {
4201
-                FFStream *s;
4202
-                stream = av_mallocz(sizeof(FFStream));
4203
-                get_arg(stream->filename, sizeof(stream->filename), &p);
4204
-                q = strrchr(stream->filename, '>');
4205
-                if (*q)
4206
-                    *q = '\0';
4207
-
4208
-                for (s = first_stream; s; s = s->next) {
4209
-                    if (!strcmp(stream->filename, s->filename)) {
4210
-                        ERROR("Stream '%s' already registered\n", s->filename);
4211
-                    }
4212
-                }
4213
-
4214
-                stream->fmt = avserver_guess_format(NULL, stream->filename, NULL);
4215
-                avcodec_get_context_defaults3(&video_enc, NULL);
4216
-                avcodec_get_context_defaults3(&audio_enc, NULL);
4217
-                audio_id = AV_CODEC_ID_NONE;
4218
-                video_id = AV_CODEC_ID_NONE;
4219
-                if (stream->fmt) {
4220
-                    audio_id = stream->fmt->audio_codec;
4221
-                    video_id = stream->fmt->video_codec;
4222
-                }
4223
-
4224
-                *last_stream = stream;
4225
-                last_stream = &stream->next;
4226
-            }
4227
-        } else if (!av_strcasecmp(cmd, "Feed")) {
4228
-            get_arg(arg, sizeof(arg), &p);
4229
-            if (stream) {
4230
-                FFStream *sfeed;
4231
-
4232
-                sfeed = first_feed;
4233
-                while (sfeed != NULL) {
4234
-                    if (!strcmp(sfeed->filename, arg))
4235
-                        break;
4236
-                    sfeed = sfeed->next_feed;
4237
-                }
4238
-                if (!sfeed)
4239
-                    ERROR("feed '%s' not defined\n", arg);
4240
-                else
4241
-                    stream->feed = sfeed;
4242
-            }
4243
-        } else if (!av_strcasecmp(cmd, "Format")) {
4244
-            get_arg(arg, sizeof(arg), &p);
4245
-            if (stream) {
4246
-                if (!strcmp(arg, "status")) {
4247
-                    stream->stream_type = STREAM_TYPE_STATUS;
4248
-                    stream->fmt = NULL;
4249
-                } else {
4250
-                    stream->stream_type = STREAM_TYPE_LIVE;
4251
-                    /* jpeg cannot be used here, so use single frame jpeg */
4252
-                    if (!strcmp(arg, "jpeg"))
4253
-                        strcpy(arg, "mjpeg");
4254
-                    stream->fmt = avserver_guess_format(arg, NULL, NULL);
4255
-                    if (!stream->fmt) {
4256
-                        ERROR("Unknown Format: %s\n", arg);
4257
-                    }
4258
-                }
4259
-                if (stream->fmt) {
4260
-                    audio_id = stream->fmt->audio_codec;
4261
-                    video_id = stream->fmt->video_codec;
4262
-                }
4263
-            }
4264
-        } else if (!av_strcasecmp(cmd, "InputFormat")) {
4265
-            get_arg(arg, sizeof(arg), &p);
4266
-            if (stream) {
4267
-                stream->ifmt = av_find_input_format(arg);
4268
-                if (!stream->ifmt) {
4269
-                    ERROR("Unknown input format: %s\n", arg);
4270
-                }
4271
-            }
4272
-        } else if (!av_strcasecmp(cmd, "FaviconURL")) {
4273
-            if (stream && stream->stream_type == STREAM_TYPE_STATUS) {
4274
-                get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4275
-            } else {
4276
-                ERROR("FaviconURL only permitted for status streams\n");
4277
-            }
4278
-        } else if (!av_strcasecmp(cmd, "Author")) {
4279
-            if (stream)
4280
-                get_arg(stream->author, sizeof(stream->author), &p);
4281
-        } else if (!av_strcasecmp(cmd, "Comment")) {
4282
-            if (stream)
4283
-                get_arg(stream->comment, sizeof(stream->comment), &p);
4284
-        } else if (!av_strcasecmp(cmd, "Copyright")) {
4285
-            if (stream)
4286
-                get_arg(stream->copyright, sizeof(stream->copyright), &p);
4287
-        } else if (!av_strcasecmp(cmd, "Title")) {
4288
-            if (stream)
4289
-                get_arg(stream->title, sizeof(stream->title), &p);
4290
-        } else if (!av_strcasecmp(cmd, "Preroll")) {
4291
-            get_arg(arg, sizeof(arg), &p);
4292
-            if (stream)
4293
-                stream->prebuffer = atof(arg) * 1000;
4294
-        } else if (!av_strcasecmp(cmd, "StartSendOnKey")) {
4295
-            if (stream)
4296
-                stream->send_on_key = 1;
4297
-        } else if (!av_strcasecmp(cmd, "AudioCodec")) {
4298
-            get_arg(arg, sizeof(arg), &p);
4299
-            audio_id = opt_audio_codec(arg);
4300
-            if (audio_id == AV_CODEC_ID_NONE) {
4301
-                ERROR("Unknown AudioCodec: %s\n", arg);
4302
-            }
4303
-        } else if (!av_strcasecmp(cmd, "VideoCodec")) {
4304
-            get_arg(arg, sizeof(arg), &p);
4305
-            video_id = opt_video_codec(arg);
4306
-            if (video_id == AV_CODEC_ID_NONE) {
4307
-                ERROR("Unknown VideoCodec: %s\n", arg);
4308
-            }
4309
-        } else if (!av_strcasecmp(cmd, "MaxTime")) {
4310
-            get_arg(arg, sizeof(arg), &p);
4311
-            if (stream)
4312
-                stream->max_time = atof(arg) * 1000;
4313
-        } else if (!av_strcasecmp(cmd, "AudioBitRate")) {
4314
-            get_arg(arg, sizeof(arg), &p);
4315
-            if (stream)
4316
-                audio_enc.bit_rate = lrintf(atof(arg) * 1000);
4317
-        } else if (!av_strcasecmp(cmd, "AudioChannels")) {
4318
-            get_arg(arg, sizeof(arg), &p);
4319
-            if (stream)
4320
-                audio_enc.channels = atoi(arg);
4321
-        } else if (!av_strcasecmp(cmd, "AudioSampleRate")) {
4322
-            get_arg(arg, sizeof(arg), &p);
4323
-            if (stream)
4324
-                audio_enc.sample_rate = atoi(arg);
4325
-        } else if (!av_strcasecmp(cmd, "AudioQuality")) {
4326
-            get_arg(arg, sizeof(arg), &p);
4327
-            if (stream) {
4328
-//                audio_enc.quality = atof(arg) * 1000;
4329
-            }
4330
-        } else if (!av_strcasecmp(cmd, "VideoBitRateRange")) {
4331
-            if (stream) {
4332
-                int minrate, maxrate;
4333
-
4334
-                get_arg(arg, sizeof(arg), &p);
4335
-
4336
-                if (sscanf(arg, "%d-%d", &minrate, &maxrate) == 2) {
4337
-                    video_enc.rc_min_rate = minrate * 1000;
4338
-                    video_enc.rc_max_rate = maxrate * 1000;
4339
-                } else {
4340
-                    ERROR("Incorrect format for VideoBitRateRange -- should be <min>-<max>: %s\n", arg);
4341
-                }
4342
-            }
4343
-        } else if (!av_strcasecmp(cmd, "Debug")) {
4344
-            if (stream) {
4345
-                get_arg(arg, sizeof(arg), &p);
4346
-                video_enc.debug = strtol(arg,0,0);
4347
-            }
4348
-        } else if (!av_strcasecmp(cmd, "Strict")) {
4349
-            if (stream) {
4350
-                get_arg(arg, sizeof(arg), &p);
4351
-                video_enc.strict_std_compliance = atoi(arg);
4352
-            }
4353
-        } else if (!av_strcasecmp(cmd, "VideoBufferSize")) {
4354
-            if (stream) {
4355
-                get_arg(arg, sizeof(arg), &p);
4356
-                video_enc.rc_buffer_size = atoi(arg) * 8*1024;
4357
-            }
4358
-        } else if (!av_strcasecmp(cmd, "VideoBitRateTolerance")) {
4359
-            if (stream) {
4360
-                get_arg(arg, sizeof(arg), &p);
4361
-                video_enc.bit_rate_tolerance = atoi(arg) * 1000;
4362
-            }
4363
-        } else if (!av_strcasecmp(cmd, "VideoBitRate")) {
4364
-            get_arg(arg, sizeof(arg), &p);
4365
-            if (stream) {
4366
-                video_enc.bit_rate = atoi(arg) * 1000;
4367
-            }
4368
-        } else if (!av_strcasecmp(cmd, "VideoSize")) {
4369
-            get_arg(arg, sizeof(arg), &p);
4370
-            if (stream) {
4371
-                av_parse_video_size(&video_enc.width, &video_enc.height, arg);
4372
-                if ((video_enc.width % 16) != 0 ||
4373
-                    (video_enc.height % 16) != 0) {
4374
-                    ERROR("Image size must be a multiple of 16\n");
4375
-                }
4376
-            }
4377
-        } else if (!av_strcasecmp(cmd, "VideoFrameRate")) {
4378
-            get_arg(arg, sizeof(arg), &p);
4379
-            if (stream) {
4380
-                AVRational frame_rate;
4381
-                if (av_parse_video_rate(&frame_rate, arg) < 0) {
4382
-                    ERROR("Incorrect frame rate: %s\n", arg);
4383
-                } else {
4384
-                    video_enc.time_base.num = frame_rate.den;
4385
-                    video_enc.time_base.den = frame_rate.num;
4386
-                }
4387
-            }
4388
-        } else if (!av_strcasecmp(cmd, "VideoGopSize")) {
4389
-            get_arg(arg, sizeof(arg), &p);
4390
-            if (stream)
4391
-                video_enc.gop_size = atoi(arg);
4392
-        } else if (!av_strcasecmp(cmd, "VideoIntraOnly")) {
4393
-            if (stream)
4394
-                video_enc.gop_size = 1;
4395
-        } else if (!av_strcasecmp(cmd, "VideoHighQuality")) {
4396
-            if (stream)
4397
-                video_enc.mb_decision = FF_MB_DECISION_BITS;
4398
-        } else if (!av_strcasecmp(cmd, "Video4MotionVector")) {
4399
-            if (stream) {
4400
-                video_enc.mb_decision = FF_MB_DECISION_BITS; //FIXME remove
4401
-                video_enc.flags |= CODEC_FLAG_4MV;
4402
-            }
4403
-        } else if (!av_strcasecmp(cmd, "AVOptionVideo") ||
4404
-                   !av_strcasecmp(cmd, "AVOptionAudio")) {
4405
-            char arg2[1024];
4406
-            AVCodecContext *avctx;
4407
-            int type;
4408
-            get_arg(arg, sizeof(arg), &p);
4409
-            get_arg(arg2, sizeof(arg2), &p);
4410
-            if (!av_strcasecmp(cmd, "AVOptionVideo")) {
4411
-                avctx = &video_enc;
4412
-                type = AV_OPT_FLAG_VIDEO_PARAM;
4413
-            } else {
4414
-                avctx = &audio_enc;
4415
-                type = AV_OPT_FLAG_AUDIO_PARAM;
4416
-            }
4417
-            if (avserver_opt_default(arg, arg2, avctx, type|AV_OPT_FLAG_ENCODING_PARAM)) {
4418
-                ERROR("AVOption error: %s %s\n", arg, arg2);
4419
-            }
4420
-        } else if (!av_strcasecmp(cmd, "AVPresetVideo") ||
4421
-                   !av_strcasecmp(cmd, "AVPresetAudio")) {
4422
-            AVCodecContext *avctx;
4423
-            int type;
4424
-            get_arg(arg, sizeof(arg), &p);
4425
-            if (!av_strcasecmp(cmd, "AVPresetVideo")) {
4426
-                avctx = &video_enc;
4427
-                video_enc.codec_id = video_id;
4428
-                type = AV_OPT_FLAG_VIDEO_PARAM;
4429
-            } else {
4430
-                avctx = &audio_enc;
4431
-                audio_enc.codec_id = audio_id;
4432
-                type = AV_OPT_FLAG_AUDIO_PARAM;
4433
-            }
4434
-            if (avserver_opt_preset(arg, avctx, type|AV_OPT_FLAG_ENCODING_PARAM, &audio_id, &video_id)) {
4435
-                ERROR("AVPreset error: %s\n", arg);
4436
-            }
4437
-        } else if (!av_strcasecmp(cmd, "VideoTag")) {
4438
-            get_arg(arg, sizeof(arg), &p);
4439
-            if ((strlen(arg) == 4) && stream)
4440
-                video_enc.codec_tag = MKTAG(arg[0], arg[1], arg[2], arg[3]);
4441
-        } else if (!av_strcasecmp(cmd, "BitExact")) {
4442
-            if (stream)
4443
-                video_enc.flags |= CODEC_FLAG_BITEXACT;
4444
-        } else if (!av_strcasecmp(cmd, "DctFastint")) {
4445
-            if (stream)
4446
-                video_enc.dct_algo  = FF_DCT_FASTINT;
4447
-        } else if (!av_strcasecmp(cmd, "IdctSimple")) {
4448
-            if (stream)
4449
-                video_enc.idct_algo = FF_IDCT_SIMPLE;
4450
-        } else if (!av_strcasecmp(cmd, "Qscale")) {
4451
-            get_arg(arg, sizeof(arg), &p);
4452
-            if (stream) {
4453
-                video_enc.flags |= CODEC_FLAG_QSCALE;
4454
-                video_enc.global_quality = FF_QP2LAMBDA * atoi(arg);
4455
-            }
4456
-        } else if (!av_strcasecmp(cmd, "VideoQDiff")) {
4457
-            get_arg(arg, sizeof(arg), &p);
4458
-            if (stream) {
4459
-                video_enc.max_qdiff = atoi(arg);
4460
-                if (video_enc.max_qdiff < 1 || video_enc.max_qdiff > 31) {
4461
-                    ERROR("VideoQDiff out of range\n");
4462
-                }
4463
-            }
4464
-        } else if (!av_strcasecmp(cmd, "VideoQMax")) {
4465
-            get_arg(arg, sizeof(arg), &p);
4466
-            if (stream) {
4467
-                video_enc.qmax = atoi(arg);
4468
-                if (video_enc.qmax < 1 || video_enc.qmax > 31) {
4469
-                    ERROR("VideoQMax out of range\n");
4470
-                }
4471
-            }
4472
-        } else if (!av_strcasecmp(cmd, "VideoQMin")) {
4473
-            get_arg(arg, sizeof(arg), &p);
4474
-            if (stream) {
4475
-                video_enc.qmin = atoi(arg);
4476
-                if (video_enc.qmin < 1 || video_enc.qmin > 31) {
4477
-                    ERROR("VideoQMin out of range\n");
4478
-                }
4479
-            }
4480
-        } else if (!av_strcasecmp(cmd, "LumiMask")) {
4481
-            get_arg(arg, sizeof(arg), &p);
4482
-            if (stream)
4483
-                video_enc.lumi_masking = atof(arg);
4484
-        } else if (!av_strcasecmp(cmd, "DarkMask")) {
4485
-            get_arg(arg, sizeof(arg), &p);
4486
-            if (stream)
4487
-                video_enc.dark_masking = atof(arg);
4488
-        } else if (!av_strcasecmp(cmd, "NoVideo")) {
4489
-            video_id = AV_CODEC_ID_NONE;
4490
-        } else if (!av_strcasecmp(cmd, "NoAudio")) {
4491
-            audio_id = AV_CODEC_ID_NONE;
4492
-        } else if (!av_strcasecmp(cmd, "ACL")) {
4493
-            parse_acl_row(stream, feed, NULL, p, filename, line_num);
4494
-        } else if (!av_strcasecmp(cmd, "DynamicACL")) {
4495
-            if (stream) {
4496
-                get_arg(stream->dynamic_acl, sizeof(stream->dynamic_acl), &p);
4497
-            }
4498
-        } else if (!av_strcasecmp(cmd, "RTSPOption")) {
4499
-            get_arg(arg, sizeof(arg), &p);
4500
-            if (stream) {
4501
-                av_freep(&stream->rtsp_option);
4502
-                stream->rtsp_option = av_strdup(arg);
4503
-            }
4504
-        } else if (!av_strcasecmp(cmd, "MulticastAddress")) {
4505
-            get_arg(arg, sizeof(arg), &p);
4506
-            if (stream) {
4507
-                if (resolve_host(&stream->multicast_ip, arg) != 0) {
4508
-                    ERROR("Invalid host/IP address: %s\n", arg);
4509
-                }
4510
-                stream->is_multicast = 1;
4511
-                stream->loop = 1; /* default is looping */
4512
-            }
4513
-        } else if (!av_strcasecmp(cmd, "MulticastPort")) {
4514
-            get_arg(arg, sizeof(arg), &p);
4515
-            if (stream)
4516
-                stream->multicast_port = atoi(arg);
4517
-        } else if (!av_strcasecmp(cmd, "MulticastTTL")) {
4518
-            get_arg(arg, sizeof(arg), &p);
4519
-            if (stream)
4520
-                stream->multicast_ttl = atoi(arg);
4521
-        } else if (!av_strcasecmp(cmd, "NoLoop")) {
4522
-            if (stream)
4523
-                stream->loop = 0;
4524
-        } else if (!av_strcasecmp(cmd, "</Stream>")) {
4525
-            if (!stream) {
4526
-                ERROR("No corresponding <Stream> for </Stream>\n");
4527
-            } else {
4528
-                if (stream->feed && stream->fmt && strcmp(stream->fmt->name, "ffm") != 0) {
4529
-                    if (audio_id != AV_CODEC_ID_NONE) {
4530
-                        audio_enc.codec_type = AVMEDIA_TYPE_AUDIO;
4531
-                        audio_enc.codec_id = audio_id;
4532
-                        add_codec(stream, &audio_enc);
4533
-                    }
4534
-                    if (video_id != AV_CODEC_ID_NONE) {
4535
-                        video_enc.codec_type = AVMEDIA_TYPE_VIDEO;
4536
-                        video_enc.codec_id = video_id;
4537
-                        add_codec(stream, &video_enc);
4538
-                    }
4539
-                }
4540
-                stream = NULL;
4541
-            }
4542
-        } else if (!av_strcasecmp(cmd, "<Redirect")) {
4543
-            /*********************************************/
4544
-            char *q;
4545
-            if (stream || feed || redirect) {
4546
-                ERROR("Already in a tag\n");
4547
-            } else {
4548
-                redirect = av_mallocz(sizeof(FFStream));
4549
-                *last_stream = redirect;
4550
-                last_stream = &redirect->next;
4551
-
4552
-                get_arg(redirect->filename, sizeof(redirect->filename), &p);
4553
-                q = strrchr(redirect->filename, '>');
4554
-                if (*q)
4555
-                    *q = '\0';
4556
-                redirect->stream_type = STREAM_TYPE_REDIRECT;
4557
-            }
4558
-        } else if (!av_strcasecmp(cmd, "URL")) {
4559
-            if (redirect)
4560
-                get_arg(redirect->feed_filename, sizeof(redirect->feed_filename), &p);
4561
-        } else if (!av_strcasecmp(cmd, "</Redirect>")) {
4562
-            if (!redirect) {
4563
-                ERROR("No corresponding <Redirect> for </Redirect>\n");
4564
-            } else {
4565
-                if (!redirect->feed_filename[0]) {
4566
-                    ERROR("No URL found for <Redirect>\n");
4567
-                }
4568
-                redirect = NULL;
4569
-            }
4570
-        } else if (!av_strcasecmp(cmd, "LoadModule")) {
4571
-            ERROR("Loadable modules no longer supported\n");
4572
-        } else {
4573
-            ERROR("Incorrect keyword: '%s'\n", cmd);
4574
-        }
4575
-    }
4576
-#undef ERROR
4577
-
4578
-    fclose(f);
4579
-    if (errors)
4580
-        return -1;
4581
-    else
4582
-        return 0;
4583
-}
4584
-
4585
-static void handle_child_exit(int sig)
4586
-{
4587
-    pid_t pid;
4588
-    int status;
4589
-
4590
-    while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
4591
-        FFStream *feed;
4592
-
4593
-        for (feed = first_feed; feed; feed = feed->next) {
4594
-            if (feed->pid == pid) {
4595
-                int uptime = time(0) - feed->pid_start;
4596
-
4597
-                feed->pid = 0;
4598
-                fprintf(stderr, "%s: Pid %d exited with status %d after %d seconds\n", feed->filename, pid, status, uptime);
4599
-
4600
-                if (uptime < 30)
4601
-                    /* Turn off any more restarts */
4602
-                    feed->child_argv = 0;
4603
-            }
4604
-        }
4605
-    }
4606
-
4607
-    need_to_start_children = 1;
4608
-}
4609
-
4610
-static void opt_debug(void)
4611
-{
4612
-    avserver_debug = 1;
4613
-    logfilename[0] = '-';
4614
-}
4615
-
4616
-void show_help_default(const char *opt, const char *arg)
4617
-{
4618
-    printf("usage: avserver [options]\n"
4619
-           "Hyper fast multi format Audio/Video streaming server\n");
4620
-    printf("\n");
4621
-    show_help_options(options, "Main options:", 0, 0, 0);
4622
-}
4623
-
4624
-static const OptionDef options[] = {
4625
-#include "cmdutils_common_opts.h"
4626
-    { "n", OPT_BOOL, {(void *)&no_launch }, "enable no-launch mode" },
4627
-    { "d", 0, {(void*)opt_debug}, "enable debug mode" },
4628
-    { "f", HAS_ARG | OPT_STRING, {(void*)&config_filename }, "use configfile instead of /etc/avserver.conf", "configfile" },
4629
-    { NULL },
4630
-};
4631
-
4632
-int main(int argc, char **argv)
4633
-{
4634
-    struct sigaction sigact = { { 0 } };
4635
-
4636
-    config_filename = av_strdup("/etc/avserver.conf");
4637
-
4638
-    parse_loglevel(argc, argv, options);
4639
-    av_register_all();
4640
-    avformat_network_init();
4641
-
4642
-    show_banner();
4643
-
4644
-    my_program_name = argv[0];
4645
-
4646
-    parse_options(NULL, argc, argv, options, NULL);
4647
-
4648
-    unsetenv("http_proxy");             /* Kill the http_proxy */
4649
-
4650
-    av_lfg_init(&random_state, av_get_random_seed());
4651
-
4652
-    sigact.sa_handler = handle_child_exit;
4653
-    sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
4654
-    sigaction(SIGCHLD, &sigact, 0);
4655
-
4656
-    if (parse_ffconfig(config_filename) < 0) {
4657
-        fprintf(stderr, "Incorrect config file - exiting.\n");
4658
-        exit(1);
4659
-    }
4660
-
4661
-    /* open log file if needed */
4662
-    if (logfilename[0] != '\0') {
4663
-        if (!strcmp(logfilename, "-"))
4664
-            logfile = stdout;
4665
-        else
4666
-            logfile = fopen(logfilename, "a");
4667
-        av_log_set_callback(http_av_log);
4668
-    }
4669
-
4670
-    build_file_streams();
4671
-
4672
-    build_feed_streams();
4673
-
4674
-    compute_bandwidth();
4675
-
4676
-    /* signal init */
4677
-    signal(SIGPIPE, SIG_IGN);
4678
-
4679
-    if (http_server() < 0) {
4680
-        http_log("Could not start server\n");
4681
-        exit(1);
4682
-    }
4683
-
4684
-    return 0;
4685
-}
... ...
@@ -108,7 +108,7 @@ Program options:
108 108
   --disable-avconv         disable avconv build
109 109
   --disable-avplay         disable avplay build
110 110
   --disable-avprobe        disable avprobe build
111
-  --disable-avserver       disable avserver build
111
+  --disable-avserver       deprecated, does nothing
112 112
 
113 113
 Component options:
114 114
   --disable-doc            do not build documentation
... ...
@@ -1209,7 +1209,6 @@ PROGRAM_LIST="
1209 1209
     avconv
1210 1210
     avplay
1211 1211
     avprobe
1212
-    avserver
1213 1212
 "
1214 1213
 
1215 1214
 SUBSYSTEM_LIST="
... ...
@@ -2142,8 +2141,6 @@ avplay_deps="avcodec avformat avresample swscale sdl"
2142 2142
 avplay_libs='$sdl_libs'
2143 2143
 avplay_select="rdft"
2144 2144
 avprobe_deps="avcodec avformat"
2145
-avserver_deps="avformat fork !shared"
2146
-avserver_select="ffm_muxer rtp_protocol rtsp_demuxer"
2147 2145
 
2148 2146
 # documentation
2149 2147
 pod2man_deps="doc"
... ...
@@ -2380,6 +2377,10 @@ for opt do
2380 2380
             name=$(echo "${optval}" | sed "s/,/_${thing}|/g")_${thing}
2381 2381
             $action $(filter "$name" $list)
2382 2382
         ;;
2383
+        --enable-avserver|--disable-avserver*)
2384
+            warn "avserver has been removed, the ${opt} option is only"\
2385
+                 "provided for compatibility and will be removed in the future"
2386
+        ;;
2383 2387
         --enable-?*|--disable-?*)
2384 2388
             eval $(echo "$opt" | sed 's/--/action=/;s/-/ option=/;s/-/_/g')
2385 2389
             if is_in $option $COMPONENT_LIST; then
... ...
@@ -3539,7 +3540,6 @@ case $target_os in
3539 3539
         add_compat strtod.o strtod=avpriv_strtod
3540 3540
         network_extralibs='-lbsd'
3541 3541
         exeobjs=compat/plan9/main.o
3542
-        disable avserver
3543 3542
         cp_f='cp'
3544 3543
         ;;
3545 3544
     none)
3546 3545
deleted file mode 100644
... ...
@@ -1,372 +0,0 @@
1
-# Port on which the server is listening. You must select a different
2
-# port from your standard HTTP web server if it is running on the same
3
-# computer.
4
-Port 8090
5
-
6
-# Address on which the server is bound. Only useful if you have
7
-# several network interfaces.
8
-BindAddress 0.0.0.0
9
-
10
-# Number of simultaneous HTTP connections that can be handled. It has
11
-# to be defined *before* the MaxClients parameter, since it defines the
12
-# MaxClients maximum limit.
13
-MaxHTTPConnections 2000
14
-
15
-# Number of simultaneous requests that can be handled. Since AVServer
16
-# is very fast, it is more likely that you will want to leave this high
17
-# and use MaxBandwidth, below.
18
-MaxClients 1000
19
-
20
-# This the maximum amount of kbit/sec that you are prepared to
21
-# consume when streaming to clients.
22
-MaxBandwidth 1000
23
-
24
-# Access log file (uses standard Apache log file format)
25
-# '-' is the standard output.
26
-CustomLog -
27
-
28
-
29
-##################################################################
30
-# Definition of the live feeds. Each live feed contains one video
31
-# and/or audio sequence coming from an avconv encoder or another
32
-# avserver. This sequence may be encoded simultaneously with several
33
-# codecs at several resolutions.
34
-
35
-<Feed feed1.ffm>
36
-
37
-# You must use 'avconv' to send a live feed to avserver. In this
38
-# example, you can type:
39
-#
40
-# avconv http://localhost:8090/feed1.ffm
41
-
42
-# avserver can also do time shifting. It means that it can stream any
43
-# previously recorded live stream. The request should contain:
44
-# "http://xxxx?date=[YYYY-MM-DDT][[HH:]MM:]SS[.m...]".You must specify
45
-# a path where the feed is stored on disk. You also specify the
46
-# maximum size of the feed, where zero means unlimited. Default:
47
-# File=/tmp/feed_name.ffm FileMaxSize=5M
48
-File /tmp/feed1.ffm
49
-FileMaxSize 200K
50
-
51
-# You could specify
52
-# ReadOnlyFile /saved/specialvideo.ffm
53
-# This marks the file as readonly and it will not be deleted or updated.
54
-
55
-# Specify launch in order to start avconv automatically.
56
-# First avconv must be defined with an appropriate path if needed,
57
-# after that options can follow, but avoid adding the http:// field
58
-#Launch avconv
59
-
60
-# Only allow connections from localhost to the feed.
61
-ACL allow 127.0.0.1
62
-
63
-</Feed>
64
-
65
-
66
-##################################################################
67
-# Now you can define each stream which will be generated from the
68
-# original audio and video stream. Each format has a filename (here
69
-# 'test1.mpg'). AVServer will send this stream when answering a
70
-# request containing this filename.
71
-
72
-<Stream test1.mpg>
73
-
74
-# coming from live feed 'feed1'
75
-Feed feed1.ffm
76
-
77
-# Format of the stream : you can choose among:
78
-# mpeg       : MPEG-1 multiplexed video and audio
79
-# mpegvideo  : only MPEG-1 video
80
-# mp2        : MPEG-2 audio (use AudioCodec to select layer 2 and 3 codec)
81
-# ogg        : Ogg format (Vorbis audio codec)
82
-# rm         : RealNetworks-compatible stream. Multiplexed audio and video.
83
-# ra         : RealNetworks-compatible stream. Audio only.
84
-# mpjpeg     : Multipart JPEG (works with Netscape without any plugin)
85
-# jpeg       : Generate a single JPEG image.
86
-# asf        : ASF compatible streaming (Windows Media Player format).
87
-# swf        : Macromedia Flash compatible stream
88
-# avi        : AVI format (MPEG-4 video, MPEG audio sound)
89
-Format mpeg
90
-
91
-# Bitrate for the audio stream. Codecs usually support only a few
92
-# different bitrates.
93
-AudioBitRate 32
94
-
95
-# Number of audio channels: 1 = mono, 2 = stereo
96
-AudioChannels 1
97
-
98
-# Sampling frequency for audio. When using low bitrates, you should
99
-# lower this frequency to 22050 or 11025. The supported frequencies
100
-# depend on the selected audio codec.
101
-AudioSampleRate 44100
102
-
103
-# Bitrate for the video stream
104
-VideoBitRate 64
105
-
106
-# Ratecontrol buffer size
107
-VideoBufferSize 40
108
-
109
-# Number of frames per second
110
-VideoFrameRate 3
111
-
112
-# Size of the video frame: WxH (default: 160x128)
113
-# The following abbreviations are defined: sqcif, qcif, cif, 4cif, qqvga,
114
-# qvga, vga, svga, xga, uxga, qxga, sxga, qsxga, hsxga, wvga, wxga, wsxga,
115
-# wuxga, woxga, wqsxga, wquxga, whsxga, whuxga, cga, ega, hd480, hd720,
116
-# hd1080
117
-VideoSize 160x128
118
-
119
-# Transmit only intra frames (useful for low bitrates, but kills frame rate).
120
-#VideoIntraOnly
121
-
122
-# If non-intra only, an intra frame is transmitted every VideoGopSize
123
-# frames. Video synchronization can only begin at an intra frame.
124
-VideoGopSize 12
125
-
126
-# More MPEG-4 parameters
127
-# VideoHighQuality
128
-# Video4MotionVector
129
-
130
-# Choose your codecs:
131
-#AudioCodec mp2
132
-#VideoCodec mpeg1video
133
-
134
-# Suppress audio
135
-#NoAudio
136
-
137
-# Suppress video
138
-#NoVideo
139
-
140
-#VideoQMin 3
141
-#VideoQMax 31
142
-
143
-# Set this to the number of seconds backwards in time to start. Note that
144
-# most players will buffer 5-10 seconds of video, and also you need to allow
145
-# for a keyframe to appear in the data stream.
146
-#Preroll 15
147
-
148
-# ACL:
149
-
150
-# You can allow ranges of addresses (or single addresses)
151
-#ACL ALLOW <first address> <last address>
152
-
153
-# You can deny ranges of addresses (or single addresses)
154
-#ACL DENY <first address> <last address>
155
-
156
-# You can repeat the ACL allow/deny as often as you like. It is on a per
157
-# stream basis. The first match defines the action. If there are no matches,
158
-# then the default is the inverse of the last ACL statement.
159
-#
160
-# Thus 'ACL allow localhost' only allows access from localhost.
161
-# 'ACL deny 1.0.0.0 1.255.255.255' would deny the whole of network 1 and
162
-# allow everybody else.
163
-
164
-</Stream>
165
-
166
-
167
-##################################################################
168
-# Example streams
169
-
170
-
171
-# Multipart JPEG
172
-
173
-#<Stream test.mjpg>
174
-#Feed feed1.ffm
175
-#Format mpjpeg
176
-#VideoFrameRate 2
177
-#VideoIntraOnly
178
-#NoAudio
179
-#Strict -1
180
-#</Stream>
181
-
182
-
183
-# Single JPEG
184
-
185
-#<Stream test.jpg>
186
-#Feed feed1.ffm
187
-#Format jpeg
188
-#VideoFrameRate 2
189
-#VideoIntraOnly
190
-##VideoSize 352x240
191
-#NoAudio
192
-#Strict -1
193
-#</Stream>
194
-
195
-
196
-# Flash
197
-
198
-#<Stream test.swf>
199
-#Feed feed1.ffm
200
-#Format swf
201
-#VideoFrameRate 2
202
-#VideoIntraOnly
203
-#NoAudio
204
-#</Stream>
205
-
206
-
207
-# ASF compatible
208
-
209
-<Stream test.asf>
210
-Feed feed1.ffm
211
-Format asf
212
-VideoFrameRate 15
213
-VideoSize 352x240
214
-VideoBitRate 256
215
-VideoBufferSize 40
216
-VideoGopSize 30
217
-AudioBitRate 64
218
-StartSendOnKey
219
-</Stream>
220
-
221
-
222
-# MP3 audio
223
-
224
-#<Stream test.mp3>
225
-#Feed feed1.ffm
226
-#Format mp2
227
-#AudioCodec mp3
228
-#AudioBitRate 64
229
-#AudioChannels 1
230
-#AudioSampleRate 44100
231
-#NoVideo
232
-#</Stream>
233
-
234
-
235
-# Ogg Vorbis audio
236
-
237
-#<Stream test.ogg>
238
-#Feed feed1.ffm
239
-#Title "Stream title"
240
-#AudioBitRate 64
241
-#AudioChannels 2
242
-#AudioSampleRate 44100
243
-#NoVideo
244
-#</Stream>
245
-
246
-
247
-# Real with audio only at 32 kbits
248
-
249
-#<Stream test.ra>
250
-#Feed feed1.ffm
251
-#Format rm
252
-#AudioBitRate 32
253
-#NoVideo
254
-#NoAudio
255
-#</Stream>
256
-
257
-
258
-# Real with audio and video at 64 kbits
259
-
260
-#<Stream test.rm>
261
-#Feed feed1.ffm
262
-#Format rm
263
-#AudioBitRate 32
264
-#VideoBitRate 128
265
-#VideoFrameRate 25
266
-#VideoGopSize 25
267
-#NoAudio
268
-#</Stream>
269
-
270
-
271
-##################################################################
272
-# A stream coming from a file: you only need to set the input
273
-# filename and optionally a new format. Supported conversions:
274
-#    AVI -> ASF
275
-
276
-#<Stream file.rm>
277
-#File "/usr/local/httpd/htdocs/tlive.rm"
278
-#NoAudio
279
-#</Stream>
280
-
281
-#<Stream file.asf>
282
-#File "/usr/local/httpd/htdocs/test.asf"
283
-#NoAudio
284
-#Author "Me"
285
-#Copyright "Super MegaCorp"
286
-#Title "Test stream from disk"
287
-#Comment "Test comment"
288
-#</Stream>
289
-
290
-
291
-##################################################################
292
-# RTSP examples
293
-#
294
-# You can access this stream with the RTSP URL:
295
-#   rtsp://localhost:5454/test1-rtsp.mpg
296
-#
297
-# A non-standard RTSP redirector is also created. Its URL is:
298
-#   http://localhost:8090/test1-rtsp.rtsp
299
-
300
-#<Stream test1-rtsp.mpg>
301
-#Format rtp
302
-#File "/usr/local/httpd/htdocs/test1.mpg"
303
-#</Stream>
304
-
305
-
306
-# Transcode an incoming live feed to another live feed,
307
-# using libx264 and video presets
308
-
309
-#<Stream live.h264>
310
-#Format rtp
311
-#Feed feed1.ffm
312
-#VideoCodec libx264
313
-#VideoFrameRate 24
314
-#VideoBitRate 100
315
-#VideoSize 480x272
316
-#AVPresetVideo default
317
-#AVPresetVideo baseline
318
-#AVOptionVideo flags +global_header
319
-#
320
-#AudioCodec libfaac
321
-#AudioBitRate 32
322
-#AudioChannels 2
323
-#AudioSampleRate 22050
324
-#AVOptionAudio flags +global_header
325
-#</Stream>
326
-
327
-##################################################################
328
-# SDP/multicast examples
329
-#
330
-# If you want to send your stream in multicast, you must set the
331
-# multicast address with MulticastAddress. The port and the TTL can
332
-# also be set.
333
-#
334
-# An SDP file is automatically generated by avserver by adding the
335
-# 'sdp' extension to the stream name (here
336
-# http://localhost:8090/test1-sdp.sdp). You should usually give this
337
-# file to your player to play the stream.
338
-#
339
-# The 'NoLoop' option can be used to avoid looping when the stream is
340
-# terminated.
341
-
342
-#<Stream test1-sdp.mpg>
343
-#Format rtp
344
-#File "/usr/local/httpd/htdocs/test1.mpg"
345
-#MulticastAddress 224.124.0.1
346
-#MulticastPort 5000
347
-#MulticastTTL 16
348
-#NoLoop
349
-#</Stream>
350
-
351
-
352
-##################################################################
353
-# Special streams
354
-
355
-# Server status
356
-
357
-<Stream stat.html>
358
-Format status
359
-
360
-# Only allow local people to get the status
361
-ACL allow localhost
362
-ACL allow 192.168.0.0 192.168.255.255
363
-
364
-#FaviconURL http://pond1.gladstonefamily.net:8080/favicon.ico
365
-</Stream>
366
-
367
-
368
-# Redirect index.html to the appropriate site
369
-
370
-<Redirect index.html>
371
-URL http://www.libav.org/
372
-</Redirect>
373 1
deleted file mode 100644
... ...
@@ -1,276 +0,0 @@
1
-\input texinfo @c -*- texinfo -*-
2
-
3
-@settitle avserver Documentation
4
-@titlepage
5
-@center @titlefont{avserver Documentation}
6
-@end titlepage
7
-
8
-@top
9
-
10
-@contents
11
-
12
-@chapter Synopsys
13
-
14
-The generic syntax is:
15
-
16
-@example
17
-@c man begin SYNOPSIS
18
-avserver [options]
19
-@c man end
20
-@end example
21
-
22
-@chapter Description
23
-@c man begin DESCRIPTION
24
-
25
-WARNING: avserver is unmaintained, largely broken and in need of a
26
-complete rewrite. It probably won't work for you. Use at your own
27
-risk.
28
-
29
-avserver is a streaming server for both audio and video. It supports
30
-several live feeds, streaming from files and time shifting on live feeds
31
-(you can seek to positions in the past on each live feed, provided you
32
-specify a big enough feed storage in avserver.conf).
33
-
34
-This documentation covers only the streaming aspects of avserver /
35
-avconv. All questions about parameters for avconv, codec questions,
36
-etc. are not covered here. Read @file{avconv.html} for more
37
-information.
38
-
39
-@section How does it work?
40
-
41
-avserver receives prerecorded files or FFM streams from some avconv
42
-instance as input, then streams them over RTP/RTSP/HTTP.
43
-
44
-An avserver instance will listen on some port as specified in the
45
-configuration file. You can launch one or more instances of avconv and
46
-send one or more FFM streams to the port where avserver is expecting
47
-to receive them. Alternately, you can make avserver launch such avconv
48
-instances at startup.
49
-
50
-Input streams are called feeds, and each one is specified by a <Feed>
51
-section in the configuration file.
52
-
53
-For each feed you can have different output streams in various
54
-formats, each one specified by a <Stream> section in the configuration
55
-file.
56
-
57
-@section Status stream
58
-
59
-avserver supports an HTTP interface which exposes the current status
60
-of the server.
61
-
62
-Simply point your browser to the address of the special status stream
63
-specified in the configuration file.
64
-
65
-For example if you have:
66
-@example
67
-<Stream status.html>
68
-Format status
69
-
70
-# Only allow local people to get the status
71
-ACL allow localhost
72
-ACL allow 192.168.0.0 192.168.255.255
73
-</Stream>
74
-@end example
75
-
76
-then the server will post a page with the status information when
77
-the special stream @file{status.html} is requested.
78
-
79
-@section What can this do?
80
-
81
-When properly configured and running, you can capture video and audio in real
82
-time from a suitable capture card, and stream it out over the Internet to
83
-either Windows Media Player or RealAudio player (with some restrictions).
84
-
85
-It can also stream from files, though that is currently broken. Very often, a
86
-web server can be used to serve up the files just as well.
87
-
88
-It can stream prerecorded video from .ffm files, though it is somewhat tricky
89
-to make it work correctly.
90
-
91
-@section What do I need?
92
-
93
-I use Linux on a 900 MHz Duron with a cheapo Bt848 based TV capture card. I'm
94
-using stock Linux 2.4.17 with the stock drivers. [Actually that isn't true,
95
-I needed some special drivers for my motherboard-based sound card.]
96
-
97
-I understand that FreeBSD systems work just fine as well.
98
-
99
-@section How do I make it work?
100
-
101
-First, build the kit. It *really* helps to have installed LAME first. Then when
102
-you run the avserver ./configure, make sure that you have the
103
-@code{--enable-libmp3lame} flag turned on.
104
-
105
-LAME is important as it allows for streaming audio to Windows Media Player.
106
-Don't ask why the other audio types do not work.
107
-
108
-As a simple test, just run the following two command lines where INPUTFILE
109
-is some file which you can decode with avconv:
110
-
111
-@example
112
-./avserver -f doc/avserver.conf &
113
-./avconv -i INPUTFILE http://localhost:8090/feed1.ffm
114
-@end example
115
-
116
-At this point you should be able to go to your Windows machine and fire up
117
-Windows Media Player (WMP). Go to Open URL and enter
118
-
119
-@example
120
-    http://<linuxbox>:8090/test.asf
121
-@end example
122
-
123
-You should (after a short delay) see video and hear audio.
124
-
125
-WARNING: trying to stream test1.mpg doesn't work with WMP as it tries to
126
-transfer the entire file before starting to play.
127
-The same is true of AVI files.
128
-
129
-@section What happens next?
130
-
131
-You should edit the avserver.conf file to suit your needs (in terms of
132
-frame rates etc). Then install avserver and avconv, write a script to start
133
-them up, and off you go.
134
-
135
-@section Troubleshooting
136
-
137
-@subsection I don't hear any audio, but video is fine.
138
-
139
-Maybe you didn't install LAME, or got your ./configure statement wrong. Check
140
-the avconv output to see if a line referring to MP3 is present. If not, then
141
-your configuration was incorrect. If it is, then maybe your wiring is not
142
-set up correctly. Maybe the sound card is not getting data from the right
143
-input source. Maybe you have a really awful audio interface (like I do)
144
-that only captures in stereo and also requires that one channel be flipped.
145
-If you are one of these people, then export 'AUDIO_FLIP_LEFT=1' before
146
-starting avconv.
147
-
148
-@subsection The audio and video lose sync after a while.
149
-
150
-Yes, they do.
151
-
152
-@subsection After a long while, the video update rate goes way down in WMP.
153
-
154
-Yes, it does. Who knows why?
155
-
156
-@subsection WMP 6.4 behaves differently to WMP 7.
157
-
158
-Yes, it does. Any thoughts on this would be gratefully received. These
159
-differences extend to embedding WMP into a web page. [There are two
160
-object IDs that you can use: The old one, which does not play well, and
161
-the new one, which does (both tested on the same system). However,
162
-I suspect that the new one is not available unless you have installed WMP 7].
163
-
164
-@section What else can it do?
165
-
166
-You can replay video from .ffm files that was recorded earlier.
167
-However, there are a number of caveats, including the fact that the
168
-avserver parameters must match the original parameters used to record the
169
-file. If they do not, then avserver deletes the file before recording into it.
170
-(Now that I write this, it seems broken).
171
-
172
-You can fiddle with many of the codec choices and encoding parameters, and
173
-there are a bunch more parameters that you cannot control. Post a message
174
-to the mailing list if there are some 'must have' parameters. Look in
175
-avserver.conf for a list of the currently available controls.
176
-
177
-It will automatically generate the ASX or RAM files that are often used
178
-in browsers. These files are actually redirections to the underlying ASF
179
-or RM file. The reason for this is that the browser often fetches the
180
-entire file before starting up the external viewer. The redirection files
181
-are very small and can be transferred quickly. [The stream itself is
182
-often 'infinite' and thus the browser tries to download it and never
183
-finishes.]
184
-
185
-@section Tips
186
-
187
-* When you connect to a live stream, most players (WMP, RA, etc) want to
188
-buffer a certain number of seconds of material so that they can display the
189
-signal continuously. However, avserver (by default) starts sending data
190
-in realtime. This means that there is a pause of a few seconds while the
191
-buffering is being done by the player. The good news is that this can be
192
-cured by adding a '?buffer=5' to the end of the URL. This means that the
193
-stream should start 5 seconds in the past -- and so the first 5 seconds
194
-of the stream are sent as fast as the network will allow. It will then
195
-slow down to real time. This noticeably improves the startup experience.
196
-
197
-You can also add a 'Preroll 15' statement into the avserver.conf that will
198
-add the 15 second prebuffering on all requests that do not otherwise
199
-specify a time. In addition, avserver will skip frames until a key_frame
200
-is found. This further reduces the startup delay by not transferring data
201
-that will be discarded.
202
-
203
-* You may want to adjust the MaxBandwidth in the avserver.conf to limit
204
-the amount of bandwidth consumed by live streams.
205
-
206
-@section Why does the ?buffer / Preroll stop working after a time?
207
-
208
-It turns out that (on my machine at least) the number of frames successfully
209
-grabbed is marginally less than the number that ought to be grabbed. This
210
-means that the timestamp in the encoded data stream gets behind realtime.
211
-This means that if you say 'Preroll 10', then when the stream gets 10
212
-or more seconds behind, there is no Preroll left.
213
-
214
-Fixing this requires a change in the internals of how timestamps are
215
-handled.
216
-
217
-@section Does the @code{?date=} stuff work.
218
-
219
-Yes (subject to the limitation outlined above). Also note that whenever you
220
-start avserver, it deletes the ffm file (if any parameters have changed),
221
-thus wiping out what you had recorded before.
222
-
223
-The format of the @code{?date=xxxxxx} is fairly flexible. You should use one
224
-of the following formats (the 'T' is literal):
225
-
226
-@example
227
-* YYYY-MM-DDTHH:MM:SS     (localtime)
228
-* YYYY-MM-DDTHH:MM:SSZ    (UTC)
229
-@end example
230
-
231
-You can omit the YYYY-MM-DD, and then it refers to the current day. However
232
-note that @samp{?date=16:00:00} refers to 16:00 on the current day -- this
233
-may be in the future and so is unlikely to be useful.
234
-
235
-You use this by adding the ?date= to the end of the URL for the stream.
236
-For example:   @samp{http://localhost:8080/test.asf?date=2002-07-26T23:05:00}.
237
-@c man end
238
-
239
-@chapter Options
240
-@c man begin OPTIONS
241
-
242
-@include avtools-common-opts.texi
243
-
244
-@section Main options
245
-
246
-@table @option
247
-@item -f @var{configfile}
248
-Use @file{configfile} instead of @file{/etc/avserver.conf}.
249
-@item -n
250
-Enable no-launch mode. This option disables all the Launch directives
251
-within the various <Stream> sections. Since avserver will not launch
252
-any avconv instances, you will have to launch them manually.
253
-@item -d
254
-Enable debug mode. This option increases log verbosity, directs log
255
-messages to stdout.
256
-@end table
257
-@c man end
258
-
259
-@ignore
260
-
261
-@setfilename avserver
262
-@settitle avserver video server
263
-
264
-@c man begin SEEALSO
265
-
266
-avconv(1), avplay(1), avprobe(1), the @file{avserver.conf}
267
-example and the Libav HTML documentation
268
-@c man end
269
-
270
-@c man begin AUTHORS
271
-The Libav developers
272
-@c man end
273
-
274
-@end ignore
275
-
276
-@bye
... ...
@@ -235,7 +235,6 @@ library:
235 235
 @item Electronic Arts cdata  @tab    @tab X
236 236
 @item Electronic Arts Multimedia  @tab    @tab X
237 237
     @tab Used in various EA games; files have extensions like WVE and UV2.
238
-@item FFM (AVserver live feed)  @tab X @tab X
239 238
 @item Flash (SWF)               @tab X @tab X
240 239
 @item Flash 9 (AVM2)            @tab X @tab X
241 240
     @tab Only embedded audio is decoded.
... ...
@@ -107,8 +107,6 @@ OBJS-$(CONFIG_EA_CDATA_DEMUXER)          += eacdata.o
107 107
 OBJS-$(CONFIG_EA_DEMUXER)                += electronicarts.o
108 108
 OBJS-$(CONFIG_EAC3_DEMUXER)              += ac3dec.o rawdec.o
109 109
 OBJS-$(CONFIG_EAC3_MUXER)                += rawenc.o
110
-OBJS-$(CONFIG_FFM_DEMUXER)               += ffmdec.o
111
-OBJS-$(CONFIG_FFM_MUXER)                 += ffmenc.o
112 110
 OBJS-$(CONFIG_FFMETADATA_DEMUXER)        += ffmetadec.o
113 111
 OBJS-$(CONFIG_FFMETADATA_MUXER)          += ffmetaenc.o
114 112
 OBJS-$(CONFIG_FILMSTRIP_DEMUXER)         += filmstripdec.o
... ...
@@ -100,7 +100,6 @@ void av_register_all(void)
100 100
     REGISTER_DEMUXER (EA_CDATA,         ea_cdata);
101 101
     REGISTER_MUXDEMUX(EAC3,             eac3);
102 102
     REGISTER_MUXER   (F4V,              f4v);
103
-    REGISTER_MUXDEMUX(FFM,              ffm);
104 103
     REGISTER_MUXDEMUX(FFMETADATA,       ffmetadata);
105 104
     REGISTER_MUXDEMUX(FILMSTRIP,        filmstrip);
106 105
     REGISTER_MUXDEMUX(FLAC,             flac);
107 106
deleted file mode 100644
... ...
@@ -1,59 +0,0 @@
1
-/*
2
- * FFM (avserver live feed) common header
3
- * Copyright (c) 2001 Fabrice Bellard
4
- *
5
- * This file is part of Libav.
6
- *
7
- * Libav is free software; you can redistribute it and/or
8
- * modify it under the terms of the GNU Lesser General Public
9
- * License as published by the Free Software Foundation; either
10
- * version 2.1 of the License, or (at your option) any later version.
11
- *
12
- * Libav is distributed in the hope that it will be useful,
13
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
- * Lesser General Public License for more details.
16
- *
17
- * You should have received a copy of the GNU Lesser General Public
18
- * License along with Libav; if not, write to the Free Software
19
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
- */
21
-
22
-#ifndef AVFORMAT_FFM_H
23
-#define AVFORMAT_FFM_H
24
-
25
-#include <stdint.h>
26
-#include "avformat.h"
27
-#include "avio.h"
28
-
29
-/* The FFM file is made of blocks of fixed size */
30
-#define FFM_HEADER_SIZE 14
31
-#define FFM_PACKET_SIZE 4096
32
-#define PACKET_ID       0x666d
33
-
34
-/* each packet contains frames (which can span several packets */
35
-#define FRAME_HEADER_SIZE    16
36
-#define FLAG_KEY_FRAME       0x01
37
-#define FLAG_DTS             0x02
38
-
39
-enum {
40
-    READ_HEADER,
41
-    READ_DATA,
42
-};
43
-
44
-typedef struct FFMContext {
45
-    /* only reading mode */
46
-    int64_t write_index, file_size;
47
-    int read_state;
48
-    uint8_t header[FRAME_HEADER_SIZE+4];
49
-
50
-    /* read and write */
51
-    int first_packet; /* true if first packet, needed to set the discontinuity tag */
52
-    int packet_size;
53
-    int frame_offset;
54
-    int64_t dts;
55
-    uint8_t *packet_ptr, *packet_end;
56
-    uint8_t packet[FFM_PACKET_SIZE];
57
-} FFMContext;
58
-
59
-#endif /* AVFORMAT_FFM_H */
60 1
deleted file mode 100644
... ...
@@ -1,483 +0,0 @@
1
-/*
2
- * FFM (avserver live feed) demuxer
3
- * Copyright (c) 2001 Fabrice Bellard
4
- *
5
- * This file is part of Libav.
6
- *
7
- * Libav is free software; you can redistribute it and/or
8
- * modify it under the terms of the GNU Lesser General Public
9
- * License as published by the Free Software Foundation; either
10
- * version 2.1 of the License, or (at your option) any later version.
11
- *
12
- * Libav is distributed in the hope that it will be useful,
13
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
- * Lesser General Public License for more details.
16
- *
17
- * You should have received a copy of the GNU Lesser General Public
18
- * License along with Libav; if not, write to the Free Software
19
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
- */
21
-
22
-#include <stdint.h>
23
-
24
-#include "libavutil/intreadwrite.h"
25
-#include "libavutil/intfloat.h"
26
-#include "avformat.h"
27
-#include "internal.h"
28
-#include "ffm.h"
29
-
30
-static int ffm_is_avail_data(AVFormatContext *s, int size)
31
-{
32
-    FFMContext *ffm = s->priv_data;
33
-    int64_t pos, avail_size;
34
-    int len;
35
-
36
-    len = ffm->packet_end - ffm->packet_ptr;
37
-    if (size <= len)
38
-        return 1;
39
-    pos = avio_tell(s->pb);
40
-    if (!ffm->write_index) {
41
-        if (pos == ffm->file_size)
42
-            return AVERROR_EOF;
43
-        avail_size = ffm->file_size - pos;
44
-    } else {
45
-    if (pos == ffm->write_index) {
46
-        /* exactly at the end of stream */
47
-        return AVERROR(EAGAIN);
48
-    } else if (pos < ffm->write_index) {
49
-        avail_size = ffm->write_index - pos;
50
-    } else {
51
-        avail_size = (ffm->file_size - pos) + (ffm->write_index - FFM_PACKET_SIZE);
52
-    }
53
-    }
54
-    avail_size = (avail_size / ffm->packet_size) * (ffm->packet_size - FFM_HEADER_SIZE) + len;
55
-    if (size <= avail_size)
56
-        return 1;
57
-    else
58
-        return AVERROR(EAGAIN);
59
-}
60
-
61
-static int ffm_resync(AVFormatContext *s, int state)
62
-{
63
-    av_log(s, AV_LOG_ERROR, "resyncing\n");
64
-    while (state != PACKET_ID) {
65
-        if (s->pb->eof_reached) {
66
-            av_log(s, AV_LOG_ERROR, "cannot find FFM syncword\n");
67
-            return -1;
68
-        }
69
-        state = (state << 8) | avio_r8(s->pb);
70
-    }
71
-    return 0;
72
-}
73
-
74
-/* first is true if we read the frame header */
75
-static int ffm_read_data(AVFormatContext *s,
76
-                         uint8_t *buf, int size, int header)
77
-{
78
-    FFMContext *ffm = s->priv_data;
79
-    AVIOContext *pb = s->pb;
80
-    int len, fill_size, size1, frame_offset, id;
81
-
82
-    size1 = size;
83
-    while (size > 0) {
84
-    redo:
85
-        len = ffm->packet_end - ffm->packet_ptr;
86
-        if (len < 0)
87
-            return -1;
88
-        if (len > size)
89
-            len = size;
90
-        if (len == 0) {
91
-            if (avio_tell(pb) == ffm->file_size)
92
-                avio_seek(pb, ffm->packet_size, SEEK_SET);
93
-    retry_read:
94
-            id = avio_rb16(pb); /* PACKET_ID */
95
-            if (id != PACKET_ID)
96
-                if (ffm_resync(s, id) < 0)
97
-                    return -1;
98
-            fill_size = avio_rb16(pb);
99
-            ffm->dts = avio_rb64(pb);
100
-            frame_offset = avio_rb16(pb);
101
-            avio_read(pb, ffm->packet, ffm->packet_size - FFM_HEADER_SIZE);
102
-            ffm->packet_end = ffm->packet + (ffm->packet_size - FFM_HEADER_SIZE - fill_size);
103
-            if (ffm->packet_end < ffm->packet || frame_offset < 0)
104
-                return -1;
105
-            /* if first packet or resynchronization packet, we must
106
-               handle it specifically */
107
-            if (ffm->first_packet || (frame_offset & 0x8000)) {
108
-                if (!frame_offset) {
109
-                    /* This packet has no frame headers in it */
110
-                    if (avio_tell(pb) >= ffm->packet_size * 3) {
111
-                        avio_seek(pb, -ffm->packet_size * 2, SEEK_CUR);
112
-                        goto retry_read;
113
-                    }
114
-                    /* This is bad, we cannot find a valid frame header */
115
-                    return 0;
116
-                }
117
-                ffm->first_packet = 0;
118
-                if ((frame_offset & 0x7fff) < FFM_HEADER_SIZE)
119
-                    return -1;
120
-                ffm->packet_ptr = ffm->packet + (frame_offset & 0x7fff) - FFM_HEADER_SIZE;
121
-                if (!header)
122
-                    break;
123
-            } else {
124
-                ffm->packet_ptr = ffm->packet;
125
-            }
126
-            goto redo;
127
-        }
128
-        memcpy(buf, ffm->packet_ptr, len);
129
-        buf += len;
130
-        ffm->packet_ptr += len;
131
-        size -= len;
132
-        header = 0;
133
-    }
134
-    return size1 - size;
135
-}
136
-
137
-/* ensure that acutal seeking happens between FFM_PACKET_SIZE
138
-   and file_size - FFM_PACKET_SIZE */
139
-static int64_t ffm_seek1(AVFormatContext *s, int64_t pos1)
140
-{
141
-    FFMContext *ffm = s->priv_data;
142
-    AVIOContext *pb = s->pb;
143
-    int64_t pos;
144
-
145
-    pos = FFMIN(pos1, ffm->file_size - FFM_PACKET_SIZE);
146
-    pos = FFMAX(pos, FFM_PACKET_SIZE);
147
-    av_dlog(s, "seek to %"PRIx64" -> %"PRIx64"\n", pos1, pos);
148
-    return avio_seek(pb, pos, SEEK_SET);
149
-}
150
-
151
-static int64_t get_dts(AVFormatContext *s, int64_t pos)
152
-{
153
-    AVIOContext *pb = s->pb;
154
-    int64_t dts;
155
-
156
-    ffm_seek1(s, pos);
157
-    avio_skip(pb, 4);
158
-    dts = avio_rb64(pb);
159
-    av_dlog(s, "dts=%0.6f\n", dts / 1000000.0);
160
-    return dts;
161
-}
162
-
163
-static void adjust_write_index(AVFormatContext *s)
164
-{
165
-    FFMContext *ffm = s->priv_data;
166
-    AVIOContext *pb = s->pb;
167
-    int64_t pts;
168
-    //int64_t orig_write_index = ffm->write_index;
169
-    int64_t pos_min, pos_max;
170
-    int64_t pts_start;
171
-    int64_t ptr = avio_tell(pb);
172
-
173
-
174
-    pos_min = 0;
175
-    pos_max = ffm->file_size - 2 * FFM_PACKET_SIZE;
176
-
177
-    pts_start = get_dts(s, pos_min);
178
-
179
-    pts = get_dts(s, pos_max);
180
-
181
-    if (pts - 100000 > pts_start)
182
-        goto end;
183
-
184
-    ffm->write_index = FFM_PACKET_SIZE;
185
-
186
-    pts_start = get_dts(s, pos_min);
187
-
188
-    pts = get_dts(s, pos_max);
189
-
190
-    if (pts - 100000 <= pts_start) {
191
-        while (1) {
192
-            int64_t newpos;
193
-            int64_t newpts;
194
-
195
-            newpos = ((pos_max + pos_min) / (2 * FFM_PACKET_SIZE)) * FFM_PACKET_SIZE;
196
-
197
-            if (newpos == pos_min)
198
-                break;
199
-
200
-            newpts = get_dts(s, newpos);
201
-
202
-            if (newpts - 100000 <= pts) {
203
-                pos_max = newpos;
204
-                pts = newpts;
205
-            } else {
206
-                pos_min = newpos;
207
-            }
208
-        }
209
-        ffm->write_index += pos_max;
210
-    }
211
-
212
- end:
213
-    avio_seek(pb, ptr, SEEK_SET);
214
-}
215
-
216
-
217
-static int ffm_close(AVFormatContext *s)
218
-{
219
-    int i;
220
-
221
-    for (i = 0; i < s->nb_streams; i++)
222
-        av_freep(&s->streams[i]->codec->rc_eq);
223
-
224
-    return 0;
225
-}
226
-
227
-
228
-static int ffm_read_header(AVFormatContext *s)
229
-{
230
-    FFMContext *ffm = s->priv_data;
231
-    AVStream *st;
232
-    AVIOContext *pb = s->pb;
233
-    AVCodecContext *codec;
234
-    int i, nb_streams;
235
-    uint32_t tag;
236
-
237
-    /* header */
238
-    tag = avio_rl32(pb);
239
-    if (tag != MKTAG('F', 'F', 'M', '1'))
240
-        goto fail;
241
-    ffm->packet_size = avio_rb32(pb);
242
-    if (ffm->packet_size != FFM_PACKET_SIZE)
243
-        goto fail;
244
-    ffm->write_index = avio_rb64(pb);
245
-    /* get also filesize */
246
-    if (pb->seekable) {
247
-        ffm->file_size = avio_size(pb);
248
-        if (ffm->write_index)
249
-            adjust_write_index(s);
250
-    } else {
251
-        ffm->file_size = (UINT64_C(1) << 63) - 1;
252
-    }
253
-
254
-    nb_streams = avio_rb32(pb);
255
-    avio_rb32(pb); /* total bitrate */
256
-    /* read each stream */
257
-    for(i=0;i<nb_streams;i++) {
258
-        char rc_eq_buf[128];
259
-
260
-        st = avformat_new_stream(s, NULL);
261
-        if (!st)
262
-            goto fail;
263
-
264
-        avpriv_set_pts_info(st, 64, 1, 1000000);
265
-
266
-        codec = st->codec;
267
-        /* generic info */
268
-        codec->codec_id = avio_rb32(pb);
269
-        codec->codec_type = avio_r8(pb); /* codec_type */
270
-        codec->bit_rate = avio_rb32(pb);
271
-        codec->flags = avio_rb32(pb);
272
-        codec->flags2 = avio_rb32(pb);
273
-        codec->debug = avio_rb32(pb);
274
-        /* specific info */
275
-        switch(codec->codec_type) {
276
-        case AVMEDIA_TYPE_VIDEO:
277
-            codec->time_base.num = avio_rb32(pb);
278
-            codec->time_base.den = avio_rb32(pb);
279
-            codec->width = avio_rb16(pb);
280
-            codec->height = avio_rb16(pb);
281
-            codec->gop_size = avio_rb16(pb);
282
-            codec->pix_fmt = avio_rb32(pb);
283
-            codec->qmin = avio_r8(pb);
284
-            codec->qmax = avio_r8(pb);
285
-            codec->max_qdiff = avio_r8(pb);
286
-            codec->qcompress = avio_rb16(pb) / 10000.0;
287
-            codec->qblur = avio_rb16(pb) / 10000.0;
288
-            codec->bit_rate_tolerance = avio_rb32(pb);
289
-            avio_get_str(pb, INT_MAX, rc_eq_buf, sizeof(rc_eq_buf));
290
-            codec->rc_eq = av_strdup(rc_eq_buf);
291
-            codec->rc_max_rate = avio_rb32(pb);
292
-            codec->rc_min_rate = avio_rb32(pb);
293
-            codec->rc_buffer_size = avio_rb32(pb);
294
-            codec->i_quant_factor = av_int2double(avio_rb64(pb));
295
-            codec->b_quant_factor = av_int2double(avio_rb64(pb));
296
-            codec->i_quant_offset = av_int2double(avio_rb64(pb));
297
-            codec->b_quant_offset = av_int2double(avio_rb64(pb));
298
-            codec->dct_algo = avio_rb32(pb);
299
-            codec->strict_std_compliance = avio_rb32(pb);
300
-            codec->max_b_frames = avio_rb32(pb);
301
-            codec->mpeg_quant = avio_rb32(pb);
302
-            codec->intra_dc_precision = avio_rb32(pb);
303
-            codec->me_method = avio_rb32(pb);
304
-            codec->mb_decision = avio_rb32(pb);
305
-            codec->nsse_weight = avio_rb32(pb);
306
-            codec->frame_skip_cmp = avio_rb32(pb);
307
-            codec->rc_buffer_aggressivity = av_int2double(avio_rb64(pb));
308
-            codec->codec_tag = avio_rb32(pb);
309
-            codec->thread_count = avio_r8(pb);
310
-            codec->coder_type = avio_rb32(pb);
311
-            codec->me_cmp = avio_rb32(pb);
312
-            codec->me_subpel_quality = avio_rb32(pb);
313
-            codec->me_range = avio_rb32(pb);
314
-            codec->keyint_min = avio_rb32(pb);
315
-            codec->scenechange_threshold = avio_rb32(pb);
316
-            codec->b_frame_strategy = avio_rb32(pb);
317
-            codec->qcompress = av_int2double(avio_rb64(pb));
318
-            codec->qblur = av_int2double(avio_rb64(pb));
319
-            codec->max_qdiff = avio_rb32(pb);
320
-            codec->refs = avio_rb32(pb);
321
-            break;
322
-        case AVMEDIA_TYPE_AUDIO:
323
-            codec->sample_rate = avio_rb32(pb);
324
-            codec->channels = avio_rl16(pb);
325
-            codec->frame_size = avio_rl16(pb);
326
-            break;
327
-        default:
328
-            goto fail;
329
-        }
330
-        if (codec->flags & CODEC_FLAG_GLOBAL_HEADER) {
331
-            codec->extradata_size = avio_rb32(pb);
332
-            codec->extradata = av_malloc(codec->extradata_size);
333
-            if (!codec->extradata)
334
-                return AVERROR(ENOMEM);
335
-            avio_read(pb, codec->extradata, codec->extradata_size);
336
-        }
337
-    }
338
-
339
-    /* get until end of block reached */
340
-    while ((avio_tell(pb) % ffm->packet_size) != 0)
341
-        avio_r8(pb);
342
-
343
-    /* init packet demux */
344
-    ffm->packet_ptr = ffm->packet;
345
-    ffm->packet_end = ffm->packet;
346
-    ffm->frame_offset = 0;
347
-    ffm->dts = 0;
348
-    ffm->read_state = READ_HEADER;
349
-    ffm->first_packet = 1;
350
-    return 0;
351
- fail:
352
-    ffm_close(s);
353
-    return -1;
354
-}
355
-
356
-/* return < 0 if eof */
357
-static int ffm_read_packet(AVFormatContext *s, AVPacket *pkt)
358
-{
359
-    int size;
360
-    FFMContext *ffm = s->priv_data;
361
-    int duration, ret;
362
-
363
-    switch(ffm->read_state) {
364
-    case READ_HEADER:
365
-        if ((ret = ffm_is_avail_data(s, FRAME_HEADER_SIZE+4)) < 0)
366
-            return ret;
367
-
368
-        av_dlog(s, "pos=%08"PRIx64" spos=%"PRIx64", write_index=%"PRIx64" size=%"PRIx64"\n",
369
-               avio_tell(s->pb), s->pb->pos, ffm->write_index, ffm->file_size);
370
-        if (ffm_read_data(s, ffm->header, FRAME_HEADER_SIZE, 1) !=
371
-            FRAME_HEADER_SIZE)
372
-            return -1;
373
-        if (ffm->header[1] & FLAG_DTS)
374
-            if (ffm_read_data(s, ffm->header+16, 4, 1) != 4)
375
-                return -1;
376
-        ffm->read_state = READ_DATA;
377
-        /* fall thru */
378
-    case READ_DATA:
379
-        size = AV_RB24(ffm->header + 2);
380
-        if ((ret = ffm_is_avail_data(s, size)) < 0)
381
-            return ret;
382
-
383
-        duration = AV_RB24(ffm->header + 5);
384
-
385
-        av_new_packet(pkt, size);
386
-        pkt->stream_index = ffm->header[0];
387
-        if ((unsigned)pkt->stream_index >= s->nb_streams) {
388
-            av_log(s, AV_LOG_ERROR, "invalid stream index %d\n", pkt->stream_index);
389
-            av_free_packet(pkt);
390
-            ffm->read_state = READ_HEADER;
391
-            return -1;
392
-        }
393
-        pkt->pos = avio_tell(s->pb);
394
-        if (ffm->header[1] & FLAG_KEY_FRAME)
395
-            pkt->flags |= AV_PKT_FLAG_KEY;
396
-
397
-        ffm->read_state = READ_HEADER;
398
-        if (ffm_read_data(s, pkt->data, size, 0) != size) {
399
-            /* bad case: desynchronized packet. we cancel all the packet loading */
400
-            av_free_packet(pkt);
401
-            return -1;
402
-        }
403
-        pkt->pts = AV_RB64(ffm->header+8);
404
-        if (ffm->header[1] & FLAG_DTS)
405
-            pkt->dts = pkt->pts - AV_RB32(ffm->header+16);
406
-        else
407
-            pkt->dts = pkt->pts;
408
-        pkt->duration = duration;
409
-        break;
410
-    }
411
-    return 0;
412
-}
413
-
414
-/* seek to a given time in the file. The file read pointer is
415
-   positioned at or before pts. XXX: the following code is quite
416
-   approximative */
417
-static int ffm_seek(AVFormatContext *s, int stream_index, int64_t wanted_pts, int flags)
418
-{
419
-    FFMContext *ffm = s->priv_data;
420
-    int64_t pos_min, pos_max, pos;
421
-    int64_t pts_min, pts_max, pts;
422
-    double pos1;
423
-
424
-    av_dlog(s, "wanted_pts=%0.6f\n", wanted_pts / 1000000.0);
425
-    /* find the position using linear interpolation (better than
426
-       dichotomy in typical cases) */
427
-    pos_min = FFM_PACKET_SIZE;
428
-    pos_max = ffm->file_size - FFM_PACKET_SIZE;
429
-    while (pos_min <= pos_max) {
430
-        pts_min = get_dts(s, pos_min);
431
-        pts_max = get_dts(s, pos_max);
432
-        /* linear interpolation */
433
-        pos1 = (double)(pos_max - pos_min) * (double)(wanted_pts - pts_min) /
434
-            (double)(pts_max - pts_min);
435
-        pos = (((int64_t)pos1) / FFM_PACKET_SIZE) * FFM_PACKET_SIZE;
436
-        if (pos <= pos_min)
437
-            pos = pos_min;
438
-        else if (pos >= pos_max)
439
-            pos = pos_max;
440
-        pts = get_dts(s, pos);
441
-        /* check if we are lucky */
442
-        if (pts == wanted_pts) {
443
-            goto found;
444
-        } else if (pts > wanted_pts) {
445
-            pos_max = pos - FFM_PACKET_SIZE;
446
-        } else {
447
-            pos_min = pos + FFM_PACKET_SIZE;
448
-        }
449
-    }
450
-    pos = (flags & AVSEEK_FLAG_BACKWARD) ? pos_min : pos_max;
451
-
452
- found:
453
-    if (ffm_seek1(s, pos) < 0)
454
-        return -1;
455
-
456
-    /* reset read state */
457
-    ffm->read_state = READ_HEADER;
458
-    ffm->packet_ptr = ffm->packet;
459
-    ffm->packet_end = ffm->packet;
460
-    ffm->first_packet = 1;
461
-
462
-    return 0;
463
-}
464
-
465
-static int ffm_probe(AVProbeData *p)
466
-{
467
-    if (
468
-        p->buf[0] == 'F' && p->buf[1] == 'F' && p->buf[2] == 'M' &&
469
-        p->buf[3] == '1')
470
-        return AVPROBE_SCORE_MAX + 1;
471
-    return 0;
472
-}
473
-
474
-AVInputFormat ff_ffm_demuxer = {
475
-    .name           = "ffm",
476
-    .long_name      = NULL_IF_CONFIG_SMALL("FFM (AVserver live feed)"),
477
-    .priv_data_size = sizeof(FFMContext),
478
-    .read_probe     = ffm_probe,
479
-    .read_header    = ffm_read_header,
480
-    .read_packet    = ffm_read_packet,
481
-    .read_close     = ffm_close,
482
-    .read_seek      = ffm_seek,
483
-};
484 1
deleted file mode 100644
... ...
@@ -1,249 +0,0 @@
1
-/*
2
- * FFM (avserver live feed) muxer
3
- * Copyright (c) 2001 Fabrice Bellard
4
- *
5
- * This file is part of Libav.
6
- *
7
- * Libav is free software; you can redistribute it and/or
8
- * modify it under the terms of the GNU Lesser General Public
9
- * License as published by the Free Software Foundation; either
10
- * version 2.1 of the License, or (at your option) any later version.
11
- *
12
- * Libav is distributed in the hope that it will be useful,
13
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
- * Lesser General Public License for more details.
16
- *
17
- * You should have received a copy of the GNU Lesser General Public
18
- * License along with Libav; if not, write to the Free Software
19
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
- */
21
-
22
-#include <assert.h>
23
-
24
-#include "libavutil/intreadwrite.h"
25
-#include "libavutil/intfloat.h"
26
-#include "avformat.h"
27
-#include "internal.h"
28
-#include "ffm.h"
29
-
30
-static void flush_packet(AVFormatContext *s)
31
-{
32
-    FFMContext *ffm = s->priv_data;
33
-    int fill_size, h;
34
-    AVIOContext *pb = s->pb;
35
-
36
-    fill_size = ffm->packet_end - ffm->packet_ptr;
37
-    memset(ffm->packet_ptr, 0, fill_size);
38
-
39
-    assert(avio_tell(pb) % ffm->packet_size == 0);
40
-
41
-    /* put header */
42
-    avio_wb16(pb, PACKET_ID);
43
-    avio_wb16(pb, fill_size);
44
-    avio_wb64(pb, ffm->dts);
45
-    h = ffm->frame_offset;
46
-    if (ffm->first_packet)
47
-        h |= 0x8000;
48
-    avio_wb16(pb, h);
49
-    avio_write(pb, ffm->packet, ffm->packet_end - ffm->packet);
50
-    avio_flush(pb);
51
-
52
-    /* prepare next packet */
53
-    ffm->frame_offset = 0; /* no key frame */
54
-    ffm->packet_ptr = ffm->packet;
55
-    ffm->first_packet = 0;
56
-}
57
-
58
-/* 'first' is true if first data of a frame */
59
-static void ffm_write_data(AVFormatContext *s,
60
-                           const uint8_t *buf, int size,
61
-                           int64_t dts, int header)
62
-{
63
-    FFMContext *ffm = s->priv_data;
64
-    int len;
65
-
66
-    if (header && ffm->frame_offset == 0) {
67
-        ffm->frame_offset = ffm->packet_ptr - ffm->packet + FFM_HEADER_SIZE;
68
-        ffm->dts = dts;
69
-    }
70
-
71
-    /* write as many packets as needed */
72
-    while (size > 0) {
73
-        len = ffm->packet_end - ffm->packet_ptr;
74
-        if (len > size)
75
-            len = size;
76
-        memcpy(ffm->packet_ptr, buf, len);
77
-
78
-        ffm->packet_ptr += len;
79
-        buf += len;
80
-        size -= len;
81
-        if (ffm->packet_ptr >= ffm->packet_end)
82
-            flush_packet(s);
83
-    }
84
-}
85
-
86
-static int ffm_write_header(AVFormatContext *s)
87
-{
88
-    FFMContext *ffm = s->priv_data;
89
-    AVStream *st;
90
-    AVIOContext *pb = s->pb;
91
-    AVCodecContext *codec;
92
-    int bit_rate, i;
93
-
94
-    ffm->packet_size = FFM_PACKET_SIZE;
95
-
96
-    /* header */
97
-    avio_wl32(pb, MKTAG('F', 'F', 'M', '1'));
98
-    avio_wb32(pb, ffm->packet_size);
99
-    avio_wb64(pb, 0); /* current write position */
100
-
101
-    avio_wb32(pb, s->nb_streams);
102
-    bit_rate = 0;
103
-    for(i=0;i<s->nb_streams;i++) {
104
-        st = s->streams[i];
105
-        bit_rate += st->codec->bit_rate;
106
-    }
107
-    avio_wb32(pb, bit_rate);
108
-
109
-    /* list of streams */
110
-    for(i=0;i<s->nb_streams;i++) {
111
-        st = s->streams[i];
112
-        avpriv_set_pts_info(st, 64, 1, 1000000);
113
-
114
-        codec = st->codec;
115
-        /* generic info */
116
-        avio_wb32(pb, codec->codec_id);
117
-        avio_w8(pb, codec->codec_type);
118
-        avio_wb32(pb, codec->bit_rate);
119
-        avio_wb32(pb, codec->flags);
120
-        avio_wb32(pb, codec->flags2);
121
-        avio_wb32(pb, codec->debug);
122
-        /* specific info */
123
-        switch(codec->codec_type) {
124
-        case AVMEDIA_TYPE_VIDEO:
125
-            avio_wb32(pb, codec->time_base.num);
126
-            avio_wb32(pb, codec->time_base.den);
127
-            avio_wb16(pb, codec->width);
128
-            avio_wb16(pb, codec->height);
129
-            avio_wb16(pb, codec->gop_size);
130
-            avio_wb32(pb, codec->pix_fmt);
131
-            avio_w8(pb, codec->qmin);
132
-            avio_w8(pb, codec->qmax);
133
-            avio_w8(pb, codec->max_qdiff);
134
-            avio_wb16(pb, (int) (codec->qcompress * 10000.0));
135
-            avio_wb16(pb, (int) (codec->qblur * 10000.0));
136
-            avio_wb32(pb, codec->bit_rate_tolerance);
137
-            avio_put_str(pb, codec->rc_eq ? codec->rc_eq : "tex^qComp");
138
-            avio_wb32(pb, codec->rc_max_rate);
139
-            avio_wb32(pb, codec->rc_min_rate);
140
-            avio_wb32(pb, codec->rc_buffer_size);
141
-            avio_wb64(pb, av_double2int(codec->i_quant_factor));
142
-            avio_wb64(pb, av_double2int(codec->b_quant_factor));
143
-            avio_wb64(pb, av_double2int(codec->i_quant_offset));
144
-            avio_wb64(pb, av_double2int(codec->b_quant_offset));
145
-            avio_wb32(pb, codec->dct_algo);
146
-            avio_wb32(pb, codec->strict_std_compliance);
147
-            avio_wb32(pb, codec->max_b_frames);
148
-            avio_wb32(pb, codec->mpeg_quant);
149
-            avio_wb32(pb, codec->intra_dc_precision);
150
-            avio_wb32(pb, codec->me_method);
151
-            avio_wb32(pb, codec->mb_decision);
152
-            avio_wb32(pb, codec->nsse_weight);
153
-            avio_wb32(pb, codec->frame_skip_cmp);
154
-            avio_wb64(pb, av_double2int(codec->rc_buffer_aggressivity));
155
-            avio_wb32(pb, codec->codec_tag);
156
-            avio_w8(pb, codec->thread_count);
157
-            avio_wb32(pb, codec->coder_type);
158
-            avio_wb32(pb, codec->me_cmp);
159
-            avio_wb32(pb, codec->me_subpel_quality);
160
-            avio_wb32(pb, codec->me_range);
161
-            avio_wb32(pb, codec->keyint_min);
162
-            avio_wb32(pb, codec->scenechange_threshold);
163
-            avio_wb32(pb, codec->b_frame_strategy);
164
-            avio_wb64(pb, av_double2int(codec->qcompress));
165
-            avio_wb64(pb, av_double2int(codec->qblur));
166
-            avio_wb32(pb, codec->max_qdiff);
167
-            avio_wb32(pb, codec->refs);
168
-            break;
169
-        case AVMEDIA_TYPE_AUDIO:
170
-            avio_wb32(pb, codec->sample_rate);
171
-            avio_wl16(pb, codec->channels);
172
-            avio_wl16(pb, codec->frame_size);
173
-            break;
174
-        default:
175
-            return -1;
176
-        }
177
-        if (codec->flags & CODEC_FLAG_GLOBAL_HEADER) {
178
-            avio_wb32(pb, codec->extradata_size);
179
-            avio_write(pb, codec->extradata, codec->extradata_size);
180
-        }
181
-    }
182
-
183
-    /* flush until end of block reached */
184
-    while ((avio_tell(pb) % ffm->packet_size) != 0)
185
-        avio_w8(pb, 0);
186
-
187
-    avio_flush(pb);
188
-
189
-    /* init packet mux */
190
-    ffm->packet_ptr = ffm->packet;
191
-    ffm->packet_end = ffm->packet + ffm->packet_size - FFM_HEADER_SIZE;
192
-    assert(ffm->packet_end >= ffm->packet);
193
-    ffm->frame_offset = 0;
194
-    ffm->dts = 0;
195
-    ffm->first_packet = 1;
196
-
197
-    return 0;
198
-}
199
-
200
-static int ffm_write_packet(AVFormatContext *s, AVPacket *pkt)
201
-{
202
-    int64_t dts;
203
-    uint8_t header[FRAME_HEADER_SIZE+4];
204
-    int header_size = FRAME_HEADER_SIZE;
205
-
206
-    dts = pkt->dts;
207
-    /* packet size & key_frame */
208
-    header[0] = pkt->stream_index;
209
-    header[1] = 0;
210
-    if (pkt->flags & AV_PKT_FLAG_KEY)
211
-        header[1] |= FLAG_KEY_FRAME;
212
-    AV_WB24(header+2, pkt->size);
213
-    AV_WB24(header+5, pkt->duration);
214
-    AV_WB64(header+8, pkt->pts);
215
-    if (pkt->pts != pkt->dts) {
216
-        header[1] |= FLAG_DTS;
217
-        AV_WB32(header+16, pkt->pts - pkt->dts);
218
-        header_size += 4;
219
-    }
220
-    ffm_write_data(s, header, header_size, dts, 1);
221
-    ffm_write_data(s, pkt->data, pkt->size, dts, 0);
222
-
223
-    return 0;
224
-}
225
-
226
-static int ffm_write_trailer(AVFormatContext *s)
227
-{
228
-    FFMContext *ffm = s->priv_data;
229
-
230
-    /* flush packets */
231
-    if (ffm->packet_ptr > ffm->packet)
232
-        flush_packet(s);
233
-
234
-    return 0;
235
-}
236
-
237
-AVOutputFormat ff_ffm_muxer = {
238
-    .name              = "ffm",
239
-    .long_name         = NULL_IF_CONFIG_SMALL("FFM (AVserver live feed)"),
240
-    .mime_type         = "",
241
-    .extensions        = "ffm",
242
-    .priv_data_size    = sizeof(FFMContext),
243
-    .audio_codec       = AV_CODEC_ID_MP2,
244
-    .video_codec       = AV_CODEC_ID_MPEG1VIDEO,
245
-    .write_header      = ffm_write_header,
246
-    .write_packet      = ffm_write_packet,
247
-    .write_trailer     = ffm_write_trailer,
248
-    .flags             = AVFMT_TS_NEGATIVE,
249
-};
... ...
@@ -6,7 +6,6 @@ FATE_LAVF-$(call ENCDEC2, MPEG4,      MP2,       AVI)                += avi
6 6
 FATE_LAVF-$(call ENCDEC,  BMP,                   IMAGE2)             += bmp
7 7
 FATE_LAVF-$(call ENCDEC,  DPX,                   IMAGE2)             += dpx
8 8
 FATE_LAVF-$(call ENCDEC2, DVVIDEO,    PCM_S16LE, AVI)                += dv_fmt
9
-FATE_LAVF-$(call ENCDEC2, MPEG1VIDEO, MP2,       FFM)                += ffm
10 9
 FATE_LAVF-$(call ENCDEC,  FLV,                   FLV)                += flv_fmt
11 10
 FATE_LAVF-$(call ENCDEC,  GIF,                   IMAGE2)             += gif
12 11
 FATE_LAVF-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, GXF)                += gxf
... ...
@@ -151,7 +151,6 @@ FATE_SEEK_LAVF-$(call ENCDEC,  PCM_S16BE,             AU)          += au
151 151
 FATE_SEEK_LAVF-$(call ENCDEC2, MPEG4,      MP2,       AVI)         += avi
152 152
 FATE_SEEK_LAVF-$(call ENCDEC,  BMP,                   IMAGE2)      += bmp
153 153
 FATE_SEEK_LAVF-$(call ENCDEC2, DVVIDEO,    PCM_S16LE, AVI)         += dv_fmt
154
-FATE_SEEK_LAVF-$(call ENCDEC2, MPEG1VIDEO, MP2,       FFM)         += ffm
155 154
 FATE_SEEK_LAVF-$(call ENCDEC,  FLV,                   FLV)         += flv_fmt
156 155
 FATE_SEEK_LAVF-$(call ENCDEC,  GIF,                   IMAGE2)      += gif
157 156
 FATE_SEEK_LAVF-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, GXF)         += gxf
... ...
@@ -188,7 +187,6 @@ fate-seek-lavf-au:       SRC = lavf/lavf.au
188 188
 fate-seek-lavf-avi:      SRC = lavf/lavf.avi
189 189
 fate-seek-lavf-bmp:      SRC = images/bmp/%02d.bmp
190 190
 fate-seek-lavf-dv_fmt:   SRC = lavf/lavf.dv
191
-fate-seek-lavf-ffm:      SRC = lavf/lavf.ffm
192 191
 fate-seek-lavf-flv_fmt:  SRC = lavf/lavf.flv
193 192
 fate-seek-lavf-gif:      SRC = lavf/lavf.gif
194 193
 fate-seek-lavf-gxf:      SRC = lavf/lavf.gxf
... ...
@@ -78,10 +78,6 @@ if [ -n "$do_swf" ] ; then
78 78
 do_lavf swf "" "-an"
79 79
 fi
80 80
 
81
-if [ -n "$do_ffm" ] ; then
82
-do_lavf ffm "" "-ar 44100"
83
-fi
84
-
85 81
 if [ -n "$do_flv_fmt" ] ; then
86 82
 do_lavf flv "" "-an"
87 83
 fi
88 84
deleted file mode 100644
... ...
@@ -1,3 +0,0 @@
1
-f3f0c42283b75bc826f499f048085c27 *./tests/data/lavf/lavf.ffm
2
-376832 ./tests/data/lavf/lavf.ffm
3
-./tests/data/lavf/lavf.ffm CRC=0xdd24439e
4 1
deleted file mode 100644
... ...
@@ -1,53 +0,0 @@
1
-ret: 0         st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos:   8192 size: 24664
2
-ret: 0         st:-1 flags:0  ts:-1.000000
3
-ret: 0         st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos:   8192 size: 24664
4
-ret: 0         st:-1 flags:1  ts: 1.894167
5
-ret: 0         st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size:   209
6
-ret: 0         st: 0 flags:0  ts: 0.788334
7
-ret: 0         st: 1 flags:1 dts: 0.772766 pts: 0.772766 pos: 315392 size:   209
8
-ret: 0         st: 0 flags:1  ts:-0.317499
9
-ret: 0         st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos:   8192 size: 24664
10
-ret: 0         st: 1 flags:0  ts: 2.576668
11
-ret: 0         st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size:   209
12
-ret: 0         st: 1 flags:1  ts: 1.470835
13
-ret: 0         st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size:   209
14
-ret: 0         st:-1 flags:0  ts: 0.365002
15
-ret: 0         st: 1 flags:1 dts: 0.328685 pts: 0.328685 pos: 155648 size:   209
16
-ret: 0         st:-1 flags:1  ts:-0.740831
17
-ret: 0         st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos:   8192 size: 24664
18
-ret: 0         st: 0 flags:0  ts: 2.153336
19
-ret: 0         st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size:   209
20
-ret: 0         st: 0 flags:1  ts: 1.047503
21
-ret: 0         st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size:   209
22
-ret: 0         st: 1 flags:0  ts:-0.058330
23
-ret: 0         st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos:   8192 size: 24664
24
-ret: 0         st: 1 flags:1  ts: 2.835837
25
-ret: 0         st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size:   209
26
-ret: 0         st:-1 flags:0  ts: 1.730004
27
-ret: 0         st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size:   209
28
-ret: 0         st:-1 flags:1  ts: 0.624171
29
-ret: 0         st: 1 flags:1 dts: 0.642154 pts: 0.642154 pos: 274432 size:   209
30
-ret: 0         st: 0 flags:0  ts:-0.481662
31
-ret: 0         st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos:   8192 size: 24664
32
-ret: 0         st: 0 flags:1  ts: 2.412505
33
-ret: 0         st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size:   209
34
-ret: 0         st: 1 flags:0  ts: 1.306672
35
-ret: 0         st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size:   209
36
-ret: 0         st: 1 flags:1  ts: 0.200839
37
-ret: 0         st: 1 flags:1 dts: 0.224195 pts: 0.224195 pos: 114688 size:   209
38
-ret: 0         st:-1 flags:0  ts:-0.904994
39
-ret: 0         st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos:   8192 size: 24664
40
-ret: 0         st:-1 flags:1  ts: 1.989173
41
-ret: 0         st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size:   209
42
-ret: 0         st: 0 flags:0  ts: 0.883340
43
-ret: 0         st: 1 flags:1 dts: 0.877256 pts: 0.877256 pos: 339968 size:   209
44
-ret: 0         st: 0 flags:1  ts:-0.222493
45
-ret: 0         st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos:   8192 size: 24664
46
-ret: 0         st: 1 flags:0  ts: 2.671674
47
-ret: 0         st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size:   209
48
-ret: 0         st: 1 flags:1  ts: 1.565841
49
-ret: 0         st: 1 flags:1 dts: 0.929501 pts: 0.929501 pos: 376832 size:   209
50
-ret: 0         st:-1 flags:0  ts: 0.460008
51
-ret: 0         st: 1 flags:1 dts: 0.459297 pts: 0.459297 pos: 204800 size:   209
52
-ret: 0         st:-1 flags:1  ts:-0.645825
53
-ret: 0         st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos:   8192 size: 24664