~ubuntu-branches/ubuntu/edgy/gstreamer0.10-ffmpeg/edgy

« back to all changes in this revision

Viewing changes to gst-libs/ext/ffmpeg/ffserver.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Dröge
  • Date: 2006-04-01 16:13:43 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20060401161343-08cyx5z9c530gtrd
Tags: 0.10.1-0ubuntu1
* New upstream release:
  Features since 0.10.0:
    + Parallel installability with 0.8.x series
    + Threadsafe design and API
    + ffvideoscale ported
    + ffdeinterlace ported
    + demuxer wrapper works pull-based
    + disabled mpeg2 video and mp3 audio autoplugging
    + fixes for Indeo3, PNG, smc, H264 HD, H263, FLV1, G2
  Bugs fixed since 0.10.0:
    + [ffdemux_mp3] ffmpeg mp3 decoder miss seeking
    + Reading mpeg-ts stream from standard input does not work
    + configure script doesn't accept --with-pkg-config-path ar...
    + Fails to build under powerpc
    + avcodec_open()/close() aren't thread-safe
    + [ffdec_cinepak] chef.avi causes gstreamer to hang in preroll
    + Indeo AVI files do not play with 0.10
    + [ffdec] Memory leak when joining pcache
    + MS Video 1 palettized AVI doesn't work
    + ffdeinterlace port to 0.10
    + [ffmpegenc] FFMpeg audio encoders do not set caps to buffers
    + gstreamer CVS doesn't work with ffmpeg codecs
    + Wrap the ffmpeg demuxers
    + [ffdec_h264] seeking in " IntoTheBlue_Cin_AVC.mp4 " crashes...
    + Too fast playback of h263p encoded file
    + FFmpeg video scale port to 0.10
    + segfault in ffmpeg enc
    + Memory leak in ffmpegenc
    + [CVE-2005-4048] avcodec_default_get_buffer heap overflow
* debian/patches/32_CVE-2005-4048_avcodec-default-get-buffer-heap-overflow.patch:
  - Dropped, this is upstream now

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
 *
15
15
 * You should have received a copy of the GNU Lesser General Public
16
16
 * License along with this library; if not, write to the Free Software
17
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
17
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
18
 */
19
19
#define HAVE_AV_CONFIG_H
20
20
#include "avformat.h"
50
50
    HTTPSTATE_SEND_DATA_HEADER,
51
51
    HTTPSTATE_SEND_DATA,          /* sending TCP or UDP data */
52
52
    HTTPSTATE_SEND_DATA_TRAILER,
53
 
    HTTPSTATE_RECEIVE_DATA,       
 
53
    HTTPSTATE_RECEIVE_DATA,
54
54
    HTTPSTATE_WAIT_FEED,          /* wait for data from the feed */
55
55
    HTTPSTATE_READY,
56
56
 
135
135
    uint8_t *buffer;
136
136
    int is_packetized; /* if true, the stream is packetized */
137
137
    int packet_stream_index; /* current stream for output in state machine */
138
 
    
 
138
 
139
139
    /* RTSP state specific */
140
140
    uint8_t *pb_buffer; /* XXX: use that in all the code */
141
141
    ByteIOContext *pb;
142
142
    int seq; /* RTSP sequence number */
143
 
    
 
143
 
144
144
    /* RTP state specific */
145
145
    enum RTSPProtocol rtp_protocol;
146
146
    char session_id[32]; /* session id */
218
218
    int readonly;        /* True if writing is prohibited to the file */
219
219
    int conns_served;
220
220
    int64_t bytes_served;
221
 
    int64_t feed_max_size;      /* maximum storage size */
 
221
    int64_t feed_max_size;      /* maximum storage size, zero means unlimited */
222
222
    int64_t feed_write_index;   /* current write position in feed (it wraps round) */
223
223
    int64_t feed_size;          /* current size of feed */
224
224
    struct FFStream *next_feed;
259
259
static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPHeader *h);
260
260
 
261
261
/* SDP handling */
262
 
static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer, 
 
262
static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
263
263
                                   struct in_addr my_ip);
264
264
 
265
265
/* RTP handling */
266
 
static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr, 
 
266
static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
267
267
                                       FFStream *stream, const char *session_id,
268
268
                                       enum RTSPProtocol rtp_protocol);
269
 
static int rtp_new_av_stream(HTTPContext *c, 
 
269
static int rtp_new_av_stream(HTTPContext *c,
270
270
                             int stream_index, struct sockaddr_in *dest_addr,
271
271
                             HTTPContext *rtsp_c);
272
272
 
296
296
 
297
297
static FILE *logfile = NULL;
298
298
 
299
 
static void __attribute__ ((format (printf, 1, 2))) http_log(const char *fmt, ...) 
 
299
static void __attribute__ ((format (printf, 1, 2))) http_log(const char *fmt, ...)
300
300
{
301
301
    va_list ap;
302
302
    va_start(ap, fmt);
303
 
    
 
303
 
304
304
    if (logfile) {
305
305
        vfprintf(logfile, fmt, ap);
306
306
        fflush(logfile);
326
326
{
327
327
    char buf2[32];
328
328
 
329
 
    if (c->suppress_log) 
 
329
    if (c->suppress_log)
330
330
        return;
331
331
 
332
 
    http_log("%s - - [%s] \"%s %s %s\" %d %lld\n", 
333
 
             inet_ntoa(c->from_addr.sin_addr), 
334
 
             ctime1(buf2), c->method, c->url, 
 
332
    http_log("%s - - [%s] \"%s %s %s\" %d %"PRId64"\n",
 
333
             inet_ntoa(c->from_addr.sin_addr),
 
334
             ctime1(buf2), c->method, c->url,
335
335
             c->protocol, (c->http_error ? c->http_error : 200), c->data_count);
336
336
}
337
337
 
355
355
{
356
356
    if (cur_time == drd->time1)
357
357
        return 0;
358
 
    
 
358
 
359
359
    return ((count - drd->count1) * 1000) / (cur_time - drd->time1);
360
360
}
361
361
 
362
 
static int get_longterm_datarate(DataRateData *drd, int64_t count)
363
 
{
364
 
    /* You get the first 3 seconds flat out */
365
 
    if (cur_time - drd->time1 < 3000)
366
 
        return 0;
367
 
    return compute_datarate(drd, count);
368
 
}
369
 
 
370
362
 
371
363
static void start_children(FFStream *feed)
372
364
{
436
428
        perror ("socket");
437
429
        return -1;
438
430
    }
439
 
        
 
431
 
440
432
    tmp = 1;
441
433
    setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp));
442
434
 
447
439
        close(server_fd);
448
440
        return -1;
449
441
    }
450
 
  
 
442
 
451
443
    if (listen (server_fd, 5) < 0) {
452
444
        perror ("listen");
453
445
        close(server_fd);
471
463
    for(stream = first_stream; stream != NULL; stream = stream->next) {
472
464
        if (stream->is_multicast) {
473
465
            /* open the RTP connection */
474
 
            snprintf(session_id, sizeof(session_id), 
 
466
            snprintf(session_id, sizeof(session_id),
475
467
                     "%08x%08x", (int)random(), (int)random());
476
468
 
477
469
            /* choose a port if none given */
484
476
            dest_addr.sin_addr = stream->multicast_ip;
485
477
            dest_addr.sin_port = htons(stream->multicast_port);
486
478
 
487
 
            rtp_c = rtp_new_connection(&dest_addr, stream, session_id, 
 
479
            rtp_c = rtp_new_connection(&dest_addr, stream, session_id,
488
480
                                       RTSP_PROTOCOL_RTP_UDP_MULTICAST);
489
481
            if (!rtp_c) {
490
482
                continue;
491
483
            }
492
484
            if (open_input_stream(rtp_c, "") < 0) {
493
 
                fprintf(stderr, "Could not open input stream for stream '%s'\n", 
 
485
                fprintf(stderr, "Could not open input stream for stream '%s'\n",
494
486
                        stream->filename);
495
487
                continue;
496
488
            }
497
489
 
498
490
            /* open each RTP stream */
499
 
            for(stream_index = 0; stream_index < stream->nb_streams; 
 
491
            for(stream_index = 0; stream_index < stream->nb_streams;
500
492
                stream_index++) {
501
 
                dest_addr.sin_port = htons(stream->multicast_port + 
 
493
                dest_addr.sin_port = htons(stream->multicast_port +
502
494
                                           2 * stream_index);
503
495
                if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, NULL) < 0) {
504
 
                    fprintf(stderr, "Could not open output stream '%s/streamid=%d'\n", 
 
496
                    fprintf(stderr, "Could not open output stream '%s/streamid=%d'\n",
505
497
                            stream->filename, stream_index);
506
498
                    exit(1);
507
499
                }
527
519
    rtsp_server_fd = socket_open_listen(&my_rtsp_addr);
528
520
    if (rtsp_server_fd < 0)
529
521
        return -1;
530
 
    
 
522
 
531
523
    http_log("ffserver started.\n");
532
524
 
533
525
    start_children(first_feed);
604
596
            if (ret < 0 && errno != EAGAIN && errno != EINTR)
605
597
                return -1;
606
598
        } while (ret <= 0);
607
 
        
 
599
 
608
600
        cur_time = gettime_ms();
609
601
 
610
602
        if (need_to_start_children) {
657
649
    HTTPContext *c = NULL;
658
650
 
659
651
    len = sizeof(from_addr);
660
 
    fd = accept(server_fd, (struct sockaddr *)&from_addr, 
 
652
    fd = accept(server_fd, (struct sockaddr *)&from_addr,
661
653
                &len);
662
654
    if (fd < 0)
663
655
        return;
667
659
       close to the connection limit */
668
660
    if (nb_connections >= nb_max_connections)
669
661
        goto fail;
670
 
    
 
662
 
671
663
    /* add a new connection */
672
664
    c = av_mallocz(sizeof(HTTPContext));
673
665
    if (!c)
674
666
        goto fail;
675
 
    
 
667
 
676
668
    c->fd = fd;
677
669
    c->poll_entry = NULL;
678
670
    c->from_addr = from_addr;
684
676
    c->next = first_http_ctx;
685
677
    first_http_ctx = c;
686
678
    nb_connections++;
687
 
    
 
679
 
688
680
    start_wait_request(c, is_rtsp);
689
681
 
690
682
    return;
738
730
 
739
731
    /* free RTP output streams if any */
740
732
    nb_streams = 0;
741
 
    if (c->stream) 
 
733
    if (c->stream)
742
734
        nb_streams = c->stream->nb_streams;
743
 
    
 
735
 
744
736
    for(i=0;i<nb_streams;i++) {
745
737
        ctx = c->rtp_ctx[i];
746
738
        if (ctx) {
752
744
            url_close(h);
753
745
        }
754
746
    }
755
 
    
 
747
 
756
748
    ctx = &c->fmt_ctx;
757
749
 
758
750
    if (!c->last_packet_sent) {
765
757
        }
766
758
    }
767
759
 
768
 
    for(i=0; i<ctx->nb_streams; i++) 
769
 
        av_free(ctx->streams[i]) ; 
 
760
    for(i=0; i<ctx->nb_streams; i++)
 
761
        av_free(ctx->streams[i]) ;
770
762
 
771
763
    if (c->stream && !c->post && c->stream->stream_type == STREAM_TYPE_LIVE)
772
764
        current_bandwidth -= c->stream->bandwidth;
780
772
static int handle_connection(HTTPContext *c)
781
773
{
782
774
    int len, ret;
783
 
    
 
775
 
784
776
    switch(c->state) {
785
777
    case HTTPSTATE_WAIT_REQUEST:
786
778
    case RTSPSTATE_WAIT_REQUEST:
864
856
        if (!c->is_packetized) {
865
857
            if (c->poll_entry->revents & (POLLERR | POLLHUP))
866
858
                return -1;
867
 
            
 
859
 
868
860
            /* no need to read if no events */
869
861
            if (!(c->poll_entry->revents & POLLOUT))
870
862
                return 0;
922
914
        /* no need to write if no events */
923
915
        if (!(c->poll_entry->revents & POLLOUT))
924
916
            return 0;
925
 
        len = write(c->fd, c->packet_buffer_ptr, 
 
917
        len = write(c->fd, c->packet_buffer_ptr,
926
918
                    c->packet_buffer_end - c->packet_buffer_ptr);
927
919
        if (len < 0) {
928
920
            if (errno != EAGAIN && errno != EINTR) {
1014
1006
 
1015
1007
        /* Potential stream */
1016
1008
 
1017
 
        /* We want the fastest stream less than bit_rate, or the slowest 
 
1009
        /* We want the fastest stream less than bit_rate, or the slowest
1018
1010
         * faster than bit_rate
1019
1011
         */
1020
1012
 
1076
1068
static void do_switch_stream(HTTPContext *c, int i)
1077
1069
{
1078
1070
    if (c->switch_feed_streams[i] >= 0) {
1079
 
#ifdef PHILIP        
 
1071
#ifdef PHILIP
1080
1072
        c->feed_streams[i] = c->switch_feed_streams[i];
1081
1073
#endif
1082
1074
 
1202
1194
        return -1;
1203
1195
 
1204
1196
    pstrcpy(c->protocol, sizeof(c->protocol), protocol);
1205
 
    
 
1197
 
 
1198
    if (ffserver_debug)
 
1199
        http_log("New connection: %s %s\n", cmd, url);
 
1200
 
1206
1201
    /* find the filename and the optional info string in the request */
1207
1202
    p = url;
1208
1203
    if (*p == '/')
1248
1243
        redir_type = REDIR_SDP;
1249
1244
        compute_real_filename(filename, sizeof(url) - 1);
1250
1245
    }
1251
 
    
 
1246
 
1252
1247
    stream = first_stream;
1253
1248
    while (stream != NULL) {
1254
1249
        if (!strcmp(stream->filename, filename) && validate_acl(stream, c))
1295
1290
    if (c->post == 0 && stream->stream_type == STREAM_TYPE_LIVE) {
1296
1291
        current_bandwidth += stream->bandwidth;
1297
1292
    }
1298
 
    
 
1293
 
1299
1294
    if (c->post == 0 && max_bandwidth < current_bandwidth) {
1300
1295
        c->http_error = 200;
1301
1296
        q = c->buffer;
1314
1309
        c->state = HTTPSTATE_SEND_HEADER;
1315
1310
        return 0;
1316
1311
    }
1317
 
    
 
1312
 
1318
1313
    if (redir_type != REDIR_NONE) {
1319
1314
        char *hostinfo = 0;
1320
 
        
 
1315
 
1321
1316
        for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1322
1317
            if (strncasecmp(p, "Host:", 5) == 0) {
1323
1318
                hostinfo = p + 5;
1355
1350
                        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
1356
1351
                        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<ASX Version=\"3\">\r\n");
1357
1352
                        //q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<!-- Autogenerated by ffserver -->\r\n");
1358
 
                        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n", 
 
1353
                        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n",
1359
1354
                                hostbuf, filename, info);
1360
1355
                        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "</ASX>\r\n");
1361
1356
                        break;
1364
1359
                        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: audio/x-pn-realaudio\r\n");
1365
1360
                        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
1366
1361
                        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "# Autogenerated by ffserver\r\n");
1367
 
                        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "http://%s/%s%s\r\n", 
 
1362
                        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "http://%s/%s%s\r\n",
1368
1363
                                hostbuf, filename, info);
1369
1364
                        break;
1370
1365
                    case REDIR_ASF:
1372
1367
                        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: video/x-ms-asf\r\n");
1373
1368
                        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
1374
1369
                        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "[Reference]\r\n");
1375
 
                        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Ref1=http://%s/%s%s\r\n", 
 
1370
                        q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Ref1=http://%s/%s%s\r\n",
1376
1371
                                hostbuf, filename, info);
1377
1372
                        break;
1378
1373
                    case REDIR_RTSP:
1387
1382
                            /* XXX: incorrect mime type ? */
1388
1383
                            q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-type: application/x-rtsp\r\n");
1389
1384
                            q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
1390
 
                            q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "rtsp://%s:%d/%s\r\n", 
1391
 
                                         hostname, ntohs(my_rtsp_addr.sin_port), 
 
1385
                            q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "rtsp://%s:%d/%s\r\n",
 
1386
                                         hostname, ntohs(my_rtsp_addr.sin_port),
1392
1387
                                         filename);
1393
1388
                        }
1394
1389
                        break;
1404
1399
 
1405
1400
                            len = sizeof(my_addr);
1406
1401
                            getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
1407
 
                            
 
1402
 
1408
1403
                            /* XXX: should use a dynamic buffer */
1409
 
                            sdp_data_size = prepare_sdp_description(stream, 
1410
 
                                                                    &sdp_data, 
 
1404
                            sdp_data_size = prepare_sdp_description(stream,
 
1405
                                                                    &sdp_data,
1411
1406
                                                                    my_addr.sin_addr);
1412
1407
                            if (sdp_data_size > 0) {
1413
1408
                                memcpy(q, sdp_data, sdp_data_size);
1447
1442
             */
1448
1443
            char *logline = 0;
1449
1444
            int client_id = 0;
1450
 
            
 
1445
 
1451
1446
            for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1452
1447
                if (strncasecmp(p, "Pragma: log-line=", 17) == 0) {
1453
1448
                    logline = p;
1495
1490
                    }
1496
1491
                }
1497
1492
            }
1498
 
            
 
1493
 
1499
1494
            snprintf(msg, sizeof(msg), "POST command not handled");
1500
1495
            c->stream = 0;
1501
1496
            goto send_error;
1542
1537
    }
1543
1538
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "Content-Type: %s\r\n", mime_type);
1544
1539
    q += snprintf(q, q - (char *) c->buffer + c->buffer_size, "\r\n");
1545
 
    
 
1540
 
1546
1541
    /* prepare output buffer */
1547
1542
    c->http_error = 0;
1548
1543
    c->buffer_ptr = c->buffer;
1581
1576
    for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++) {
1582
1577
    }
1583
1578
 
1584
 
    url_fprintf(pb, "%lld%c", count, *s);
 
1579
    url_fprintf(pb, "%"PRId64"%c", count, *s);
1585
1580
}
1586
1581
 
1587
1582
static void compute_stats(HTTPContext *c)
1604
1599
    url_fprintf(pb, "Content-type: %s\r\n", "text/html");
1605
1600
    url_fprintf(pb, "Pragma: no-cache\r\n");
1606
1601
    url_fprintf(pb, "\r\n");
1607
 
    
 
1602
 
1608
1603
    url_fprintf(pb, "<HEAD><TITLE>FFServer Status</TITLE>\n");
1609
1604
    if (c->stream->feed_filename) {
1610
1605
        url_fprintf(pb, "<link rel=\"shortcut icon\" href=\"%s\">\n", c->stream->feed_filename);
1641
1636
                        strcpy(eosf, ".rtsp");
1642
1637
                }
1643
1638
            }
1644
 
            
1645
 
            url_fprintf(pb, "<TR><TD><A HREF=\"/%s\">%s</A> ", 
 
1639
 
 
1640
            url_fprintf(pb, "<TR><TD><A HREF=\"/%s\">%s</A> ",
1646
1641
                         sfilename, stream->filename);
1647
1642
            url_fprintf(pb, "<td align=right> %d <td align=right> ",
1648
1643
                        stream->conns_served);
1684
1679
                            av_abort();
1685
1680
                        }
1686
1681
                    }
1687
 
                    url_fprintf(pb, "<TD align=center> %s <TD align=right> %d <TD align=right> %d <TD> %s %s <TD align=right> %d <TD> %s %s", 
 
1682
                    url_fprintf(pb, "<TD align=center> %s <TD align=right> %d <TD align=right> %d <TD> %s %s <TD align=right> %d <TD> %s %s",
1688
1683
                                 stream->fmt->name,
1689
1684
                                 stream->bandwidth,
1690
1685
                                 video_bit_rate / 1000, video_codec_name, video_codec_name_extra,
1719
1714
                    char ps_cmd[64];
1720
1715
 
1721
1716
                    /* This is somewhat linux specific I guess */
1722
 
                    snprintf(ps_cmd, sizeof(ps_cmd), 
1723
 
                             "ps -o \"%%cpu,cputime\" --no-headers %d", 
 
1717
                    snprintf(ps_cmd, sizeof(ps_cmd),
 
1718
                             "ps -o \"%%cpu,cputime\" --no-headers %d",
1724
1719
                             stream->pid);
1725
 
                    
 
1720
 
1726
1721
                    pid_stat = popen(ps_cmd, "r");
1727
1722
                    if (pid_stat) {
1728
1723
                        char cpuperc[10];
1729
1724
                        char cpuused[64];
1730
 
                        
1731
 
                        if (fscanf(pid_stat, "%10s %64s", cpuperc, 
 
1725
 
 
1726
                        if (fscanf(pid_stat, "%10s %64s", cpuperc,
1732
1727
                                   cpuused) == 2) {
1733
1728
                            url_fprintf(pb, "Currently using %s%% of the cpu. Total time used %s.\n",
1734
1729
                                         cpuperc, cpuused);
1767
1762
            }
1768
1763
            url_fprintf(pb, "</table>\n");
1769
1764
 
1770
 
        }       
 
1765
        }
1771
1766
        stream = stream->next;
1772
1767
    }
1773
 
    
 
1768
 
1774
1769
#if 0
1775
1770
    {
1776
1771
        float avg;
1777
1772
        AVCodecContext *enc;
1778
1773
        char buf[1024];
1779
 
        
 
1774
 
1780
1775
        /* feed status */
1781
1776
        stream = first_feed;
1782
1777
        while (stream != NULL) {
1787
1782
                AVStream *st = stream->streams[i];
1788
1783
                FeedData *fdata = st->priv_data;
1789
1784
                enc = st->codec;
1790
 
            
 
1785
 
1791
1786
                avcodec_string(buf, sizeof(buf), enc);
1792
1787
                avg = fdata->avg_frame_size * (float)enc->rate * 8.0;
1793
1788
                if (enc->codec->type == CODEC_TYPE_AUDIO && enc->frame_size > 0)
1794
1789
                    avg /= enc->frame_size;
1795
 
                url_fprintf(pb, "<TR><TD>%s <TD> %d <TD> %Ld <TD> %0.1f\n", 
 
1790
                url_fprintf(pb, "<TR><TD>%s <TD> %d <TD> %Ld <TD> %0.1f\n",
1796
1791
                             buf, enc->frame_number, fdata->data_count, avg / 1000.0);
1797
1792
            }
1798
1793
            url_fprintf(pb, "</TABLE>\n");
1833
1828
 
1834
1829
        i++;
1835
1830
        p = inet_ntoa(c1->from_addr.sin_addr);
1836
 
        url_fprintf(pb, "<TR><TD><B>%d</B><TD>%s%s<TD>%s<TD>%s<TD>%s<td align=right>", 
1837
 
                    i, 
1838
 
                    c1->stream ? c1->stream->filename : "", 
 
1831
        url_fprintf(pb, "<TR><TD><B>%d</B><TD>%s%s<TD>%s<TD>%s<TD>%s<td align=right>",
 
1832
                    i,
 
1833
                    c1->stream ? c1->stream->filename : "",
1839
1834
                    c1->state == HTTPSTATE_RECEIVE_DATA ? "(input)" : "",
1840
 
                    p, 
 
1835
                    p,
1841
1836
                    c1->protocol,
1842
1837
                    http_state[c1->state]);
1843
1838
        fmt_bytecount(pb, bitrate);
1849
1844
        c1 = c1->next;
1850
1845
    }
1851
1846
    url_fprintf(pb, "</TABLE>\n");
1852
 
    
 
1847
 
1853
1848
    /* date */
1854
1849
    ti = time(NULL);
1855
1850
    p = ctime(&ti);
1919
1914
#endif
1920
1915
 
1921
1916
    /* open stream */
1922
 
    if (av_open_input_file(&s, input_filename, c->stream->ifmt, 
 
1917
    if (av_open_input_file(&s, input_filename, c->stream->ifmt,
1923
1918
                           buf_size, c->stream->ap_in) < 0) {
1924
1919
        http_log("%s not found", input_filename);
1925
1920
        return -1;
1926
1921
    }
1927
1922
    c->fmt_in = s;
1928
 
    
 
1923
 
1929
1924
    /* open each parser */
1930
1925
    for(i=0;i<s->nb_streams;i++)
1931
1926
        open_parser(s, i);
1934
1929
       present) for packet sending */
1935
1930
    c->pts_stream_index = 0;
1936
1931
    for(i=0;i<c->stream->nb_streams;i++) {
1937
 
        if (c->pts_stream_index == 0 && 
 
1932
        if (c->pts_stream_index == 0 &&
1938
1933
            c->stream->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO) {
1939
1934
            c->pts_stream_index = i;
1940
1935
        }
1963
1958
static int64_t get_packet_send_clock(HTTPContext *c)
1964
1959
{
1965
1960
    int bytes_left, bytes_sent, frame_bytes;
1966
 
    
 
1961
 
1967
1962
    frame_bytes = c->cur_frame_bytes;
1968
1963
    if (frame_bytes <= 0) {
1969
1964
        return c->cur_pts;
1984
1979
    switch(c->state) {
1985
1980
    case HTTPSTATE_SEND_DATA_HEADER:
1986
1981
        memset(&c->fmt_ctx, 0, sizeof(c->fmt_ctx));
1987
 
        pstrcpy(c->fmt_ctx.author, sizeof(c->fmt_ctx.author), 
 
1982
        pstrcpy(c->fmt_ctx.author, sizeof(c->fmt_ctx.author),
1988
1983
                c->stream->author);
1989
 
        pstrcpy(c->fmt_ctx.comment, sizeof(c->fmt_ctx.comment), 
 
1984
        pstrcpy(c->fmt_ctx.comment, sizeof(c->fmt_ctx.comment),
1990
1985
                c->stream->comment);
1991
 
        pstrcpy(c->fmt_ctx.copyright, sizeof(c->fmt_ctx.copyright), 
 
1986
        pstrcpy(c->fmt_ctx.copyright, sizeof(c->fmt_ctx.copyright),
1992
1987
                c->stream->copyright);
1993
 
        pstrcpy(c->fmt_ctx.title, sizeof(c->fmt_ctx.title), 
 
1988
        pstrcpy(c->fmt_ctx.title, sizeof(c->fmt_ctx.title),
1994
1989
                c->stream->title);
1995
1990
 
1996
1991
        /* open output stream by using specified codecs */
1998
1993
        c->fmt_ctx.nb_streams = c->stream->nb_streams;
1999
1994
        for(i=0;i<c->fmt_ctx.nb_streams;i++) {
2000
1995
            AVStream *st;
2001
 
            AVStream *src;
 
1996
            AVStream *src;
2002
1997
            st = av_mallocz(sizeof(AVStream));
2003
1998
            st->codec= avcodec_alloc_context();
2004
1999
            c->fmt_ctx.streams[i] = st;
2005
2000
            /* if file or feed, then just take streams from FFStream struct */
2006
 
            if (!c->stream->feed || 
 
2001
            if (!c->stream->feed ||
2007
2002
                c->stream->feed == c->stream)
2008
2003
                src = c->stream->streams[i];
2009
2004
            else
2010
2005
                src = c->stream->feed->streams[c->stream->feed_streams[i]];
2011
2006
 
2012
 
            *st = *src;
2013
 
            st->priv_data = 0;
 
2007
            *st = *src;
 
2008
            st->priv_data = 0;
2014
2009
            st->codec->frame_number = 0; /* XXX: should be done in
2015
2010
                                           AVStream, not in codec */
2016
2011
            /* I'm pretty sure that this is not correct...
2041
2036
        /* find a new packet */
2042
2037
        {
2043
2038
            AVPacket pkt;
2044
 
            
 
2039
 
2045
2040
            /* read a packet from the input stream */
2046
2041
            if (c->stream->feed) {
2047
 
                ffm_set_write_index(c->fmt_in, 
 
2042
                ffm_set_write_index(c->fmt_in,
2048
2043
                                    c->stream->feed->feed_write_index,
2049
2044
                                    c->stream->feed->feed_size);
2050
2045
            }
2051
2046
 
2052
 
            if (c->stream->max_time && 
 
2047
            if (c->stream->max_time &&
2053
2048
                c->stream->max_time + c->start_time - cur_time < 0) {
2054
2049
                /* We have timed out */
2055
2050
                c->state = HTTPSTATE_SEND_DATA_TRAILER;
2102
2097
                                if (pkt.flags & PKT_FLAG_KEY) {
2103
2098
                                    c->got_key_frame |= 1 << i;
2104
2099
                                }
2105
 
                                /* See if we have all the key frames, then 
 
2100
                                /* See if we have all the key frames, then
2106
2101
                                 * we start to send. This logic is not quite
2107
 
                                 * right, but it works for the case of a 
 
2102
                                 * right, but it works for the case of a
2108
2103
                                 * single video stream with one or more
2109
 
                                 * audio streams (for which every frame is 
2110
 
                                 * typically a key frame). 
 
2104
                                 * audio streams (for which every frame is
 
2105
                                 * typically a key frame).
2111
2106
                                 */
2112
 
                                if (!c->stream->send_on_key || 
 
2107
                                if (!c->stream->send_on_key ||
2113
2108
                                    ((c->got_key_frame + 1) >> c->stream->nb_streams)) {
2114
2109
                                    goto send_it;
2115
2110
                                }
2117
2112
                        }
2118
2113
                    } else {
2119
2114
                        AVCodecContext *codec;
2120
 
                        
 
2115
 
2121
2116
                    send_it:
2122
2117
                        /* specific handling for RTP: we use several
2123
2118
                           output stream (one for each RTP
2133
2128
#if 0
2134
2129
                            printf("index=%d pts=%0.3f duration=%0.6f\n",
2135
2130
                                   pkt.stream_index,
2136
 
                                   (double)c->cur_pts / 
 
2131
                                   (double)c->cur_pts /
2137
2132
                                   AV_TIME_BASE,
2138
 
                                   (double)c->cur_frame_duration / 
 
2133
                                   (double)c->cur_frame_duration /
2139
2134
                                   AV_TIME_BASE);
2140
2135
#endif
2141
2136
                            /* find RTP context */
2153
2148
                            /* Fudge here */
2154
2149
                            codec = ctx->streams[pkt.stream_index]->codec;
2155
2150
                        }
2156
 
                        
 
2151
 
2157
2152
                        codec->coded_frame->key_frame = ((pkt.flags & PKT_FLAG_KEY) != 0);
2158
2153
                        if (c->is_packetized) {
2159
2154
                            int max_packet_size;
2172
2167
                        if (av_write_frame(ctx, &pkt)) {
2173
2168
                            c->state = HTTPSTATE_SEND_DATA_TRAILER;
2174
2169
                        }
2175
 
                        
 
2170
 
2176
2171
                        len = url_close_dyn_buf(&ctx->pb, &c->pb_buffer);
2177
2172
                        c->cur_frame_bytes = len;
2178
2173
                        c->buffer_ptr = c->pb_buffer;
2179
2174
                        c->buffer_end = c->pb_buffer + len;
2180
 
                        
 
2175
 
2181
2176
                        codec->frame_number++;
2182
2177
                        if (len == 0)
2183
2178
                            goto redo;
2260
2255
                    int interleaved_index, size;
2261
2256
                    uint8_t header[4];
2262
2257
                    HTTPContext *rtsp_c;
2263
 
                    
 
2258
 
2264
2259
                    rtsp_c = c->rtsp_c;
2265
2260
                    /* if no RTSP connection left, error */
2266
2261
                    if (!rtsp_c)
2289
2284
                    rtsp_c->packet_buffer_ptr = c->packet_buffer;
2290
2285
                    rtsp_c->packet_buffer_end = c->packet_buffer + size;
2291
2286
                    c->buffer_ptr += len;
2292
 
                    
 
2287
 
2293
2288
                    /* send everything we can NOW */
2294
 
                    len = write(rtsp_c->fd, rtsp_c->packet_buffer_ptr, 
 
2289
                    len = write(rtsp_c->fd, rtsp_c->packet_buffer_ptr,
2295
2290
                                rtsp_c->packet_buffer_end - rtsp_c->packet_buffer_ptr);
2296
2291
                    if (len > 0) {
2297
2292
                        rtsp_c->packet_buffer_ptr += len;
2309
2304
                } else {
2310
2305
                    /* send RTP packet directly in UDP */
2311
2306
                    c->buffer_ptr += 4;
2312
 
                    url_write(c->rtp_handles[c->packet_stream_index], 
 
2307
                    url_write(c->rtp_handles[c->packet_stream_index],
2313
2308
                              c->buffer_ptr, len);
2314
2309
                    c->buffer_ptr += len;
2315
2310
                    /* here we continue as we can send several packets per 10 ms slot */
2354
2349
    if (fd < 0)
2355
2350
        return -1;
2356
2351
    c->feed_fd = fd;
2357
 
    
 
2352
 
2358
2353
    c->stream->feed_write_index = ffm_read_write_index(fd);
2359
2354
    c->stream->feed_size = lseek(fd, 0, SEEK_END);
2360
2355
    lseek(fd, 0, SEEK_SET);
2365
2360
    c->stream->feed_opened = 1;
2366
2361
    return 0;
2367
2362
}
2368
 
    
 
2363
 
2369
2364
static int http_receive_data(HTTPContext *c)
2370
2365
{
2371
2366
    HTTPContext *c1;
2402
2397
        /* a packet has been received : write it in the store, except
2403
2398
           if header */
2404
2399
        if (c->data_count > FFM_PACKET_SIZE) {
2405
 
            
 
2400
 
2406
2401
            //            printf("writing pos=0x%Lx size=0x%Lx\n", feed->feed_write_index, feed->feed_size);
2407
2402
            /* XXX: use llseek or url_seek */
2408
2403
            lseek(c->feed_fd, feed->feed_write_index, SEEK_SET);
2409
2404
            write(c->feed_fd, c->buffer, FFM_PACKET_SIZE);
2410
 
            
 
2405
 
2411
2406
            feed->feed_write_index += FFM_PACKET_SIZE;
2412
2407
            /* update file size */
2413
2408
            if (feed->feed_write_index > c->stream->feed_size)
2414
2409
                feed->feed_size = feed->feed_write_index;
2415
2410
 
2416
2411
            /* handle wrap around if max file size reached */
2417
 
            if (feed->feed_write_index >= c->stream->feed_max_size)
 
2412
            if (c->stream->feed_max_size && feed->feed_write_index >= c->stream->feed_max_size)
2418
2413
                feed->feed_write_index = FFM_PACKET_SIZE;
2419
2414
 
2420
2415
            /* write index */
2422
2417
 
2423
2418
            /* wake up any waiting connections */
2424
2419
            for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
2425
 
                if (c1->state == HTTPSTATE_WAIT_FEED && 
 
2420
                if (c1->state == HTTPSTATE_WAIT_FEED &&
2426
2421
                    c1->stream->feed == c->stream->feed) {
2427
2422
                    c1->state = HTTPSTATE_SEND_DATA;
2428
2423
                }
2449
2444
                s.priv_data = av_mallocz(fmt_in->priv_data_size);
2450
2445
                if (!s.priv_data)
2451
2446
                    goto fail;
2452
 
            } else
2453
 
                s.priv_data = NULL;
 
2447
            } else
 
2448
                s.priv_data = NULL;
2454
2449
 
2455
2450
            if (fmt_in->read_header(&s, 0) < 0) {
2456
2451
                av_freep(&s.priv_data);
2463
2458
                goto fail;
2464
2459
            }
2465
2460
            for (i = 0; i < s.nb_streams; i++) {
2466
 
                memcpy(feed->streams[i]->codec, 
 
2461
                memcpy(feed->streams[i]->codec,
2467
2462
                       s.streams[i]->codec, sizeof(AVCodecContext));
2468
 
            } 
 
2463
            }
2469
2464
            av_freep(&s.priv_data);
2470
2465
        }
2471
2466
        c->buffer_ptr = c->buffer;
2489
2484
    char buf2[32];
2490
2485
 
2491
2486
    switch(error_number) {
2492
 
#define DEF(n, c, s) case c: str = s; break; 
 
2487
#define DEF(n, c, s) case c: str = s; break;
2493
2488
#include "rtspcodes.h"
2494
2489
#undef DEF
2495
2490
    default:
2496
2491
        str = "Unknown Error";
2497
2492
        break;
2498
2493
    }
2499
 
     
 
2494
 
2500
2495
    url_fprintf(c->pb, "RTSP/1.0 %d %s\r\n", error_number, str);
2501
2496
    url_fprintf(c->pb, "CSeq: %d\r\n", c->seq);
2502
2497
 
2526
2521
    ByteIOContext pb1;
2527
2522
    int len;
2528
2523
    RTSPHeader header1, *header = &header1;
2529
 
    
 
2524
 
2530
2525
    c->buffer_ptr[0] = '\0';
2531
2526
    p = c->buffer;
2532
 
    
 
2527
 
2533
2528
    get_word(cmd, sizeof(cmd), &p);
2534
2529
    get_word(url, sizeof(url), &p);
2535
2530
    get_word(protocol, sizeof(protocol), &p);
2610
2605
 
2611
2606
/* XXX: move that to rtsp.c, but would need to replace FFStream by
2612
2607
   AVFormatContext */
2613
 
static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer, 
 
2608
static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
2614
2609
                                   struct in_addr my_ip)
2615
2610
{
2616
2611
    ByteIOContext pb1, *pb = &pb1;
2617
2612
    int i, payload_type, port, private_payload_type, j;
2618
2613
    const char *ipstr, *title, *mediatype;
2619
2614
    AVStream *st;
2620
 
    
 
2615
 
2621
2616
    if (url_open_dyn_buf(pb) < 0)
2622
2617
        return -1;
2623
 
    
 
2618
 
2624
2619
    /* general media info */
2625
2620
 
2626
2621
    url_fprintf(pb, "v=0\n");
2664
2659
        } else {
2665
2660
            port = 0;
2666
2661
        }
2667
 
        url_fprintf(pb, "m=%s %d RTP/AVP %d\n", 
 
2662
        url_fprintf(pb, "m=%s %d RTP/AVP %d\n",
2668
2663
                    mediatype, port, payload_type);
2669
2664
        if (payload_type >= RTP_PT_PRIVATE) {
2670
2665
            /* for private payload type, we need to give more info */
2672
2667
            case CODEC_ID_MPEG4:
2673
2668
                {
2674
2669
                    uint8_t *data;
2675
 
                    url_fprintf(pb, "a=rtpmap:%d MP4V-ES/%d\n", 
 
2670
                    url_fprintf(pb, "a=rtpmap:%d MP4V-ES/%d\n",
2676
2671
                                payload_type, 90000);
2677
2672
                    /* we must also add the mpeg4 header */
2678
2673
                    data = st->codec->extradata;
2716
2711
    uint8_t *content;
2717
2712
    int content_length, len;
2718
2713
    struct sockaddr_in my_addr;
2719
 
    
 
2714
 
2720
2715
    /* find which url is asked */
2721
2716
    url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
2722
2717
    path = path1;
2778
2773
    return NULL;
2779
2774
}
2780
2775
 
2781
 
static void rtsp_cmd_setup(HTTPContext *c, const char *url, 
 
2776
static void rtsp_cmd_setup(HTTPContext *c, const char *url,
2782
2777
                           RTSPHeader *h)
2783
2778
{
2784
2779
    FFStream *stream;
2790
2785
    RTSPTransportField *th;
2791
2786
    struct sockaddr_in dest_addr;
2792
2787
    RTSPActionServerSetup setup;
2793
 
    
 
2788
 
2794
2789
    /* find which url is asked */
2795
2790
    url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
2796
2791
    path = path1;
2809
2804
                stream_index = 0;
2810
2805
                goto found;
2811
2806
            }
2812
 
                
 
2807
 
2813
2808
            for(stream_index = 0; stream_index < stream->nb_streams;
2814
2809
                stream_index++) {
2815
 
                snprintf(buf, sizeof(buf), "%s/streamid=%d", 
 
2810
                snprintf(buf, sizeof(buf), "%s/streamid=%d",
2816
2811
                         stream->filename, stream_index);
2817
2812
                if (!strcmp(path, buf))
2818
2813
                    goto found;
2826
2821
 
2827
2822
    /* generate session id if needed */
2828
2823
    if (h->session_id[0] == '\0') {
2829
 
        snprintf(h->session_id, sizeof(h->session_id), 
 
2824
        snprintf(h->session_id, sizeof(h->session_id),
2830
2825
                 "%08x%08x", (int)random(), (int)random());
2831
2826
    }
2832
2827
 
2856
2851
            return;
2857
2852
        }
2858
2853
    }
2859
 
    
 
2854
 
2860
2855
    /* test if stream is OK (test needed because several SETUP needs
2861
2856
       to be done for a given file) */
2862
2857
    if (rtp_c->stream != stream) {
2863
2858
        rtsp_reply_error(c, RTSP_STATUS_SERVICE);
2864
2859
        return;
2865
2860
    }
2866
 
    
 
2861
 
2867
2862
    /* test if stream is already set up */
2868
2863
    if (rtp_c->rtp_ctx[stream_index]) {
2869
2864
        rtsp_reply_error(c, RTSP_STATUS_STATE);
2872
2867
 
2873
2868
    /* check transport */
2874
2869
    th = find_transport(h, rtp_c->rtp_protocol);
2875
 
    if (!th || (th->protocol == RTSP_PROTOCOL_RTP_UDP && 
 
2870
    if (!th || (th->protocol == RTSP_PROTOCOL_RTP_UDP &&
2876
2871
                th->client_port_min <= 0)) {
2877
2872
        rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
2878
2873
        return;
2882
2877
    setup.transport_option[0] = '\0';
2883
2878
    dest_addr = rtp_c->from_addr;
2884
2879
    dest_addr.sin_port = htons(th->client_port_min);
2885
 
    
 
2880
 
2886
2881
    /* add transport option if needed */
2887
2882
    if (ff_rtsp_callback) {
2888
2883
        setup.ipaddr = ntohl(dest_addr.sin_addr.s_addr);
2889
 
        if (ff_rtsp_callback(RTSP_ACTION_SERVER_SETUP, rtp_c->session_id, 
 
2884
        if (ff_rtsp_callback(RTSP_ACTION_SERVER_SETUP, rtp_c->session_id,
2890
2885
                             (char *)&setup, sizeof(setup),
2891
2886
                             stream->rtsp_option) < 0) {
2892
2887
            rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
2894
2889
        }
2895
2890
        dest_addr.sin_addr.s_addr = htonl(setup.ipaddr);
2896
2891
    }
2897
 
    
 
2892
 
2898
2893
    /* setup stream */
2899
2894
    if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, c) < 0) {
2900
2895
        rtsp_reply_error(c, RTSP_STATUS_TRANSPORT);
2925
2920
        url_fprintf(c->pb, ";%s", setup.transport_option);
2926
2921
    }
2927
2922
    url_fprintf(c->pb, "\r\n");
2928
 
    
 
2923
 
2929
2924
 
2930
2925
    url_fprintf(c->pb, "\r\n");
2931
2926
}
2933
2928
 
2934
2929
/* find an rtp connection by using the session ID. Check consistency
2935
2930
   with filename */
2936
 
static HTTPContext *find_rtp_session_with_url(const char *url, 
 
2931
static HTTPContext *find_rtp_session_with_url(const char *url,
2937
2932
                                              const char *session_id)
2938
2933
{
2939
2934
    HTTPContext *rtp_c;
2972
2967
        rtsp_reply_error(c, RTSP_STATUS_SESSION);
2973
2968
        return;
2974
2969
    }
2975
 
    
 
2970
 
2976
2971
    if (rtp_c->state != HTTPSTATE_SEND_DATA &&
2977
2972
        rtp_c->state != HTTPSTATE_WAIT_FEED &&
2978
2973
        rtp_c->state != HTTPSTATE_READY) {
2989
2984
#endif
2990
2985
 
2991
2986
    rtp_c->state = HTTPSTATE_SEND_DATA;
2992
 
    
 
2987
 
2993
2988
    /* now everything is OK, so we can send the connection parameters */
2994
2989
    rtsp_reply_header(c, RTSP_STATUS_OK);
2995
2990
    /* session ID */
3006
3001
        rtsp_reply_error(c, RTSP_STATUS_SESSION);
3007
3002
        return;
3008
3003
    }
3009
 
    
 
3004
 
3010
3005
    if (rtp_c->state != HTTPSTATE_SEND_DATA &&
3011
3006
        rtp_c->state != HTTPSTATE_WAIT_FEED) {
3012
3007
        rtsp_reply_error(c, RTSP_STATUS_STATE);
3013
3008
        return;
3014
3009
    }
3015
 
    
 
3010
 
3016
3011
    rtp_c->state = HTTPSTATE_READY;
3017
3012
    rtp_c->first_pts = AV_NOPTS_VALUE;
3018
3013
    /* now everything is OK, so we can send the connection parameters */
3031
3026
        rtsp_reply_error(c, RTSP_STATUS_SESSION);
3032
3027
        return;
3033
3028
    }
3034
 
    
 
3029
 
3035
3030
    /* abort the session */
3036
3031
    close_connection(rtp_c);
3037
3032
 
3038
3033
    if (ff_rtsp_callback) {
3039
 
        ff_rtsp_callback(RTSP_ACTION_SERVER_TEARDOWN, rtp_c->session_id, 
 
3034
        ff_rtsp_callback(RTSP_ACTION_SERVER_TEARDOWN, rtp_c->session_id,
3040
3035
                         NULL, 0,
3041
3036
                         rtp_c->stream->rtsp_option);
3042
3037
    }
3052
3047
/********************************************************************/
3053
3048
/* RTP handling */
3054
3049
 
3055
 
static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr, 
 
3050
static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
3056
3051
                                       FFStream *stream, const char *session_id,
3057
3052
                                       enum RTSPProtocol rtp_protocol)
3058
3053
{
3059
3054
    HTTPContext *c = NULL;
3060
3055
    const char *proto_str;
3061
 
    
 
3056
 
3062
3057
    /* XXX: should output a warning page when coming
3063
3058
       close to the connection limit */
3064
3059
    if (nb_connections >= nb_max_connections)
3065
3060
        goto fail;
3066
 
    
 
3061
 
3067
3062
    /* add a new connection */
3068
3063
    c = av_mallocz(sizeof(HTTPContext));
3069
3064
    if (!c)
3070
3065
        goto fail;
3071
 
    
 
3066
 
3072
3067
    c->fd = -1;
3073
3068
    c->poll_entry = NULL;
3074
3069
    c->from_addr = *from_addr;
3106
3101
    c->next = first_http_ctx;
3107
3102
    first_http_ctx = c;
3108
3103
    return c;
3109
 
        
 
3104
 
3110
3105
 fail:
3111
3106
    if (c) {
3112
3107
        av_free(c->buffer);
3118
3113
/* add a new RTP stream in an RTP connection (used in RTSP SETUP
3119
3114
   command). If RTP/TCP protocol is used, TCP connection 'rtsp_c' is
3120
3115
   used. */
3121
 
static int rtp_new_av_stream(HTTPContext *c, 
 
3116
static int rtp_new_av_stream(HTTPContext *c,
3122
3117
                             int stream_index, struct sockaddr_in *dest_addr,
3123
3118
                             HTTPContext *rtsp_c)
3124
3119
{
3129
3124
    uint8_t *dummy_buf;
3130
3125
    char buf2[32];
3131
3126
    int max_packet_size;
3132
 
    
 
3127
 
3133
3128
    /* now we can open the relevant output stream */
3134
3129
    ctx = av_alloc_format_context();
3135
3130
    if (!ctx)
3143
3138
    ctx->nb_streams = 1;
3144
3139
    ctx->streams[0] = st;
3145
3140
 
3146
 
    if (!c->stream->feed || 
 
3141
    if (!c->stream->feed ||
3147
3142
        c->stream->feed == c->stream) {
3148
3143
        memcpy(st, c->stream->streams[stream_index], sizeof(AVStream));
3149
3144
    } else {
3150
 
        memcpy(st, 
 
3145
        memcpy(st,
3151
3146
               c->stream->feed->streams[c->stream->feed_streams[stream_index]],
3152
3147
               sizeof(AVStream));
3153
3148
    }
3154
 
    
 
3149
 
3155
3150
    /* build destination RTP address */
3156
3151
    ipaddr = inet_ntoa(dest_addr->sin_addr);
3157
3152
 
3159
3154
    case RTSP_PROTOCOL_RTP_UDP:
3160
3155
    case RTSP_PROTOCOL_RTP_UDP_MULTICAST:
3161
3156
        /* RTP/UDP case */
3162
 
        
 
3157
 
3163
3158
        /* XXX: also pass as parameter to function ? */
3164
3159
        if (c->stream->is_multicast) {
3165
3160
            int ttl;
3167
3162
            if (!ttl)
3168
3163
                ttl = 16;
3169
3164
            snprintf(ctx->filename, sizeof(ctx->filename),
3170
 
                     "rtp://%s:%d?multicast=1&ttl=%d", 
 
3165
                     "rtp://%s:%d?multicast=1&ttl=%d",
3171
3166
                     ipaddr, ntohs(dest_addr->sin_port), ttl);
3172
3167
        } else {
3173
3168
            snprintf(ctx->filename, sizeof(ctx->filename),
3189
3184
    }
3190
3185
 
3191
3186
    http_log("%s:%d - - [%s] \"PLAY %s/streamid=%d %s\"\n",
3192
 
             ipaddr, ntohs(dest_addr->sin_port), 
3193
 
             ctime1(buf2), 
 
3187
             ipaddr, ntohs(dest_addr->sin_port),
 
3188
             ctime1(buf2),
3194
3189
             c->stream->filename, stream_index, c->protocol);
3195
3190
 
3196
3191
    /* normally, no packets should be output here, but the packet size may be checked */
3208
3203
    }
3209
3204
    url_close_dyn_buf(&ctx->pb, &dummy_buf);
3210
3205
    av_free(dummy_buf);
3211
 
    
 
3206
 
3212
3207
    c->rtp_ctx[stream_index] = ctx;
3213
3208
    return 0;
3214
3209
}
3267
3262
            }
3268
3263
        }
3269
3264
    }
3270
 
    
 
3265
 
3271
3266
    fst = add_av_stream1(feed, av);
3272
3267
    if (!fst)
3273
3268
        return -1;
3321
3316
            p = pkt.data;
3322
3317
            while (p < pkt.data + pkt.size - 4) {
3323
3318
                /* stop when vop header is found */
3324
 
                if (p[0] == 0x00 && p[1] == 0x00 && 
 
3319
                if (p[0] == 0x00 && p[1] == 0x00 &&
3325
3320
                    p[2] == 0x01 && p[3] == 0xb6) {
3326
3321
                    size = p - pkt.data;
3327
3322
                    //                    av_hex_dump(pkt.data, size);
3360
3355
                stream->ap_in->mpeg2ts_raw = 1;
3361
3356
                stream->ap_in->mpeg2ts_compute_pcr = 1;
3362
3357
            }
3363
 
            
3364
 
            if (av_open_input_file(&infile, stream->feed_filename, 
 
3358
 
 
3359
            if (av_open_input_file(&infile, stream->feed_filename,
3365
3360
                                   stream->ifmt, 0, stream->ap_in) < 0) {
3366
3361
                http_log("%s not found", stream->feed_filename);
3367
3362
                /* remove stream (no need to spend more time on it) */
3371
3366
                /* find all the AVStreams inside and reference them in
3372
3367
                   'stream' */
3373
3368
                if (av_find_stream_info(infile) < 0) {
3374
 
                    http_log("Could not find codec parameters from '%s'", 
 
3369
                    http_log("Could not find codec parameters from '%s'",
3375
3370
                             stream->feed_filename);
3376
3371
                    av_close_input_file(infile);
3377
3372
                    goto fail;
3438
3433
 
3439
3434
                        if (sf->index != ss->index ||
3440
3435
                            sf->id != ss->id) {
3441
 
                            printf("Index & Id do not match for stream %d (%s)\n", 
 
3436
                            printf("Index & Id do not match for stream %d (%s)\n",
3442
3437
                                   i, feed->feed_filename);
3443
3438
                            matches = 0;
3444
3439
                        } else {
3536
3531
        feed->feed_write_index = ffm_read_write_index(fd);
3537
3532
        feed->feed_size = lseek(fd, 0, SEEK_END);
3538
3533
        /* ensure that we do not wrap before the end of file */
3539
 
        if (feed->feed_max_size < feed->feed_size)
 
3534
        if (feed->feed_max_size && feed->feed_max_size < feed->feed_size)
3540
3535
            feed->feed_max_size = feed->feed_size;
3541
3536
 
3542
3537
        close(fd);
3548
3543
{
3549
3544
    int bandwidth, i;
3550
3545
    FFStream *stream;
3551
 
    
 
3546
 
3552
3547
    for(stream = first_stream; stream != NULL; stream = stream->next) {
3553
3548
        bandwidth = 0;
3554
3549
        for(i=0;i<stream->nb_streams;i++) {
3636
3631
        av->qcompress = 0.5;
3637
3632
        av->qblur = 0.5;
3638
3633
 
3639
 
        if (!av->nsse_weight) 
 
3634
        if (!av->nsse_weight)
3640
3635
            av->nsse_weight = 8;
3641
3636
 
3642
3637
        av->frame_skip_cmp = FF_CMP_DCTMAX;
3719
3714
                filename, dlerror());
3720
3715
        return;
3721
3716
    }
3722
 
    
 
3717
 
3723
3718
    init_func = dlsym(dll, "ffserver_module_init");
3724
3719
    if (!init_func) {
3725
 
        fprintf(stderr, 
 
3720
        fprintf(stderr,
3726
3721
                "%s: init function 'ffserver_module_init()' not found\n",
3727
3722
                filename);
3728
3723
        dlclose(dll);
3750
3745
        perror(filename);
3751
3746
        return -1;
3752
3747
    }
3753
 
    
 
3748
 
3754
3749
    errors = 0;
3755
3750
    line_num = 0;
3756
3751
    first_stream = NULL;
3767
3762
            break;
3768
3763
        line_num++;
3769
3764
        p = line;
3770
 
        while (isspace(*p)) 
 
3765
        while (isspace(*p))
3771
3766
            p++;
3772
3767
        if (*p == '\0' || *p == '#')
3773
3768
            continue;
3774
3769
 
3775
3770
        get_arg(cmd, sizeof(cmd), &p);
3776
 
        
 
3771
 
3777
3772
        if (!strcasecmp(cmd, "Port")) {
3778
3773
            get_arg(arg, sizeof(arg), &p);
3779
3774
            my_http_addr.sin_port = htons (atoi(arg));
3780
3775
        } else if (!strcasecmp(cmd, "BindAddress")) {
3781
3776
            get_arg(arg, sizeof(arg), &p);
3782
3777
            if (!inet_aton(arg, &my_http_addr.sin_addr)) {
3783
 
                fprintf(stderr, "%s:%d: Invalid IP address: %s\n", 
 
3778
                fprintf(stderr, "%s:%d: Invalid IP address: %s\n",
3784
3779
                        filename, line_num, arg);
3785
3780
                errors++;
3786
3781
            }
3792
3787
        } else if (!strcasecmp(cmd, "RTSPBindAddress")) {
3793
3788
            get_arg(arg, sizeof(arg), &p);
3794
3789
            if (!inet_aton(arg, &my_rtsp_addr.sin_addr)) {
3795
 
                fprintf(stderr, "%s:%d: Invalid IP address: %s\n", 
 
3790
                fprintf(stderr, "%s:%d: Invalid IP address: %s\n",
3796
3791
                        filename, line_num, arg);
3797
3792
                errors++;
3798
3793
            }
3800
3795
            get_arg(arg, sizeof(arg), &p);
3801
3796
            val = atoi(arg);
3802
3797
            if (val < 1 || val > HTTP_MAX_CONNECTIONS) {
3803
 
                fprintf(stderr, "%s:%d: Invalid MaxClients: %s\n", 
 
3798
                fprintf(stderr, "%s:%d: Invalid MaxClients: %s\n",
3804
3799
                        filename, line_num, arg);
3805
3800
                errors++;
3806
3801
            } else {
3810
3805
            get_arg(arg, sizeof(arg), &p);
3811
3806
            val = atoi(arg);
3812
3807
            if (val < 10 || val > 100000) {
3813
 
                fprintf(stderr, "%s:%d: Invalid MaxBandwidth: %s\n", 
 
3808
                fprintf(stderr, "%s:%d: Invalid MaxBandwidth: %s\n",
3814
3809
                        filename, line_num, arg);
3815
3810
                errors++;
3816
3811
            } else {
3833
3828
                /* add in feed list */
3834
3829
                *last_feed = feed;
3835
3830
                last_feed = &feed->next_feed;
3836
 
                
 
3831
 
3837
3832
                get_arg(feed->filename, sizeof(feed->filename), &p);
3838
3833
                q = strrchr(feed->filename, '>');
3839
3834
                if (*q)
3852
3847
 
3853
3848
                feed->child_argv = (char **) av_mallocz(64 * sizeof(char *));
3854
3849
 
3855
 
                feed->child_argv[0] = av_malloc(7);
3856
 
                strcpy(feed->child_argv[0], "ffmpeg");
3857
 
 
3858
 
                for (i = 1; i < 62; i++) {
 
3850
                for (i = 0; i < 62; i++) {
3859
3851
                    char argbuf[256];
3860
3852
 
3861
3853
                    get_arg(argbuf, sizeof(argbuf), &p);
3868
3860
 
3869
3861
                feed->child_argv[i] = av_malloc(30 + strlen(feed->filename));
3870
3862
 
3871
 
                snprintf(feed->child_argv[i], 256, "http://127.0.0.1:%d/%s", 
 
3863
                snprintf(feed->child_argv[i], 30+strlen(feed->filename),
 
3864
                    "http://%s:%d/%s",
 
3865
                        (my_http_addr.sin_addr.s_addr == INADDR_ANY) ? "127.0.0.1" :
 
3866
                    inet_ntoa(my_http_addr.sin_addr),
3872
3867
                    ntohs(my_http_addr.sin_port), feed->filename);
 
3868
 
 
3869
                if (ffserver_debug)
 
3870
                {
 
3871
                    int j;
 
3872
                    fprintf(stdout, "Launch commandline: ");
 
3873
                    for (j = 0; j <= i; j++)
 
3874
                        fprintf(stdout, "%s ", feed->child_argv[j]);
 
3875
                    fprintf(stdout, "\n");
 
3876
                }
3873
3877
            }
3874
3878
        } else if (!strcasecmp(cmd, "ReadOnlyFile")) {
3875
3879
            if (feed) {
3913
3917
#if 0
3914
3918
            } else {
3915
3919
                /* Make sure that we start out clean */
3916
 
                if (unlink(feed->feed_filename) < 0 
 
3920
                if (unlink(feed->feed_filename) < 0
3917
3921
                    && errno != ENOENT) {
3918
3922
                    fprintf(stderr, "%s:%d: Unable to clean old feed file '%s': %s\n",
3919
3923
                        filename, line_num, feed->feed_filename, strerror(errno));
3952
3956
            get_arg(arg, sizeof(arg), &p);
3953
3957
            if (stream) {
3954
3958
                FFStream *sfeed;
3955
 
                
 
3959
 
3956
3960
                sfeed = first_feed;
3957
3961
                while (sfeed != NULL) {
3958
3962
                    if (!strcmp(sfeed->filename, arg))
3978
3982
                    strcpy(arg, "mjpeg");
3979
3983
                stream->fmt = guess_stream_format(arg, NULL, NULL);
3980
3984
                if (!stream->fmt) {
3981
 
                    fprintf(stderr, "%s:%d: Unknown Format: %s\n", 
 
3985
                    fprintf(stderr, "%s:%d: Unknown Format: %s\n",
3982
3986
                            filename, line_num, arg);
3983
3987
                    errors++;
3984
3988
                }
3990
3994
        } else if (!strcasecmp(cmd, "InputFormat")) {
3991
3995
            stream->ifmt = av_find_input_format(arg);
3992
3996
            if (!stream->ifmt) {
3993
 
                fprintf(stderr, "%s:%d: Unknown input format: %s\n", 
 
3997
                fprintf(stderr, "%s:%d: Unknown input format: %s\n",
3994
3998
                        filename, line_num, arg);
3995
3999
            }
3996
4000
        } else if (!strcasecmp(cmd, "FaviconURL")) {
3997
4001
            if (stream && stream->stream_type == STREAM_TYPE_STATUS) {
3998
4002
                get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
3999
4003
            } else {
4000
 
                fprintf(stderr, "%s:%d: FaviconURL only permitted for status streams\n", 
 
4004
                fprintf(stderr, "%s:%d: FaviconURL only permitted for status streams\n",
4001
4005
                            filename, line_num);
4002
4006
                errors++;
4003
4007
            }
4030
4034
            get_arg(arg, sizeof(arg), &p);
4031
4035
            audio_id = opt_audio_codec(arg);
4032
4036
            if (audio_id == CODEC_ID_NONE) {
4033
 
                fprintf(stderr, "%s:%d: Unknown AudioCodec: %s\n", 
 
4037
                fprintf(stderr, "%s:%d: Unknown AudioCodec: %s\n",
4034
4038
                        filename, line_num, arg);
4035
4039
                errors++;
4036
4040
            }
4038
4042
            get_arg(arg, sizeof(arg), &p);
4039
4043
            video_id = opt_video_codec(arg);
4040
4044
            if (video_id == CODEC_ID_NONE) {
4041
 
                fprintf(stderr, "%s:%d: Unknown VideoCodec: %s\n", 
 
4045
                fprintf(stderr, "%s:%d: Unknown VideoCodec: %s\n",
4042
4046
                        filename, line_num, arg);
4043
4047
                errors++;
4044
4048
            }
4062
4066
            if (stream) {
4063
4067
                audio_enc.sample_rate = atoi(arg);
4064
4068
            }
4065
 
        } else if (!strcasecmp(cmd, "AudioQuality")) {
4066
 
            get_arg(arg, sizeof(arg), &p);
 
4069
        } else if (!strcasecmp(cmd, "AudioQuality")) {
 
4070
            get_arg(arg, sizeof(arg), &p);
4067
4071
            if (stream) {
4068
4072
//                audio_enc.quality = atof(arg) * 1000;
4069
4073
            }
4077
4081
                    video_enc.rc_min_rate = minrate * 1000;
4078
4082
                    video_enc.rc_max_rate = maxrate * 1000;
4079
4083
                } else {
4080
 
                    fprintf(stderr, "%s:%d: Incorrect format for VideoBitRateRange -- should be <min>-<max>: %s\n", 
 
4084
                    fprintf(stderr, "%s:%d: Incorrect format for VideoBitRateRange -- should be <min>-<max>: %s\n",
4081
4085
                            filename, line_num, arg);
4082
4086
                    errors++;
4083
4087
                }
4276
4280
            get_arg(arg, sizeof(arg), &p);
4277
4281
            if (stream) {
4278
4282
                if (!inet_aton(arg, &stream->multicast_ip)) {
4279
 
                    fprintf(stderr, "%s:%d: Invalid IP address: %s\n", 
 
4283
                    fprintf(stderr, "%s:%d: Invalid IP address: %s\n",
4280
4284
                            filename, line_num, arg);
4281
4285
                    errors++;
4282
4286
                }
4355
4359
#ifdef CONFIG_HAVE_DLOPEN
4356
4360
            load_module(arg);
4357
4361
#else
4358
 
            fprintf(stderr, "%s:%d: Module support not compiled into this version: '%s'\n", 
 
4362
            fprintf(stderr, "%s:%d: Module support not compiled into this version: '%s'\n",
4359
4363
                    filename, line_num, arg);
4360
4364
            errors++;
4361
4365
#endif
4362
4366
        } else {
4363
 
            fprintf(stderr, "%s:%d: Incorrect keyword: '%s'\n", 
 
4367
            fprintf(stderr, "%s:%d: Incorrect keyword: '%s'\n",
4364
4368
                    filename, line_num, cmd);
4365
4369
            errors++;
4366
4370
        }
4425
4429
    "\n"
4426
4430
    "You should have received a copy of the GNU Lesser General Public\n"
4427
4431
    "License along with this library; if not, write to the Free Software\n"
4428
 
    "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n"
 
4432
    "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n"
4429
4433
    );
4430
4434
}
4431
4435
 
4447
4451
                if (uptime < 30) {
4448
4452
                    /* Turn off any more restarts */
4449
4453
                    feed->child_argv = 0;
4450
 
                }    
 
4454
                }
4451
4455
            }
4452
4456
        }
4453
4457
    }
4468
4472
    my_program_name = argv[0];
4469
4473
    my_program_dir = getcwd(0, 0);
4470
4474
    ffserver_daemon = 1;
4471
 
    
 
4475
 
4472
4476
    for(;;) {
4473
4477
        c = getopt(argc, argv, "ndLh?f:");
4474
4478
        if (c == -1)
4509
4513
    my_rtsp_addr.sin_family = AF_INET;
4510
4514
    my_rtsp_addr.sin_port = htons (5454);
4511
4515
    my_rtsp_addr.sin_addr.s_addr = htonl (INADDR_ANY);
4512
 
    
 
4516
 
4513
4517
    nb_max_connections = 5;
4514
4518
    max_bandwidth = 1000;
4515
4519
    first_stream = NULL;