Revision 12f996ed libavformat/utils.c

View differences:

libavformat/utils.c
321 321
        err = AVERROR_NOMEM;
322 322
        goto fail;
323 323
    }
324
    ic->duration = AV_NOPTS_VALUE;
325
    ic->start_time = AV_NOPTS_VALUE;
324 326
    pstrcpy(ic->filename, sizeof(ic->filename), filename);
325 327
    pd->filename = ic->filename;
326 328
    pd->buf = buf;
......
439 441
    }
440 442
}
441 443

  
444

  
445
/* return TRUE if the stream has accurate timings for at least one component */
446
static int av_has_timings(AVFormatContext *ic)
447
{
448
    int i;
449
    AVStream *st;
450

  
451
    for(i = 0;i < ic->nb_streams; i++) {
452
        st = ic->streams[i];
453
        if (st->start_time != AV_NOPTS_VALUE &&
454
            st->duration != AV_NOPTS_VALUE)
455
            return 1;
456
    }
457
    return 0;
458
}
459

  
460
/* estimate the stream timings from the one of each components. Also
461
   compute the global bitrate if possible */
462
static void av_update_stream_timings(AVFormatContext *ic)
463
{
464
    int64_t start_time, end_time, end_time1;
465
    int i;
466
    AVStream *st;
467

  
468
    start_time = MAXINT64;
469
    end_time = MININT64;
470
    for(i = 0;i < ic->nb_streams; i++) {
471
        st = ic->streams[i];
472
        if (st->start_time != AV_NOPTS_VALUE) {
473
            if (st->start_time < start_time)
474
                start_time = st->start_time;
475
            if (st->duration != AV_NOPTS_VALUE) {
476
                end_time1 = st->start_time + st->duration;
477
                if (end_time1 > end_time)
478
                    end_time = end_time1;
479
            }
480
        }
481
    }
482
    if (start_time != MAXINT64) {
483
        ic->start_time = start_time;
484
        if (end_time != MAXINT64) {
485
            ic->duration = end_time - start_time;
486
            if (ic->file_size > 0) {
487
                /* compute the bit rate */
488
                ic->bit_rate = (double)ic->file_size * 8.0 * AV_TIME_BASE / 
489
                    (double)ic->duration;
490
            }
491
        }
492
    }
493

  
494
}
495

  
496
static void fill_all_stream_timings(AVFormatContext *ic)
497
{
498
    int i;
499
    AVStream *st;
500

  
501
    av_update_stream_timings(ic);
502
    for(i = 0;i < ic->nb_streams; i++) {
503
        st = ic->streams[i];
504
        if (st->start_time == AV_NOPTS_VALUE) {
505
            st->start_time = ic->start_time;
506
            st->duration = ic->duration;
507
        }
508
    }
509
}
510

  
511
static void av_estimate_timings_from_bit_rate(AVFormatContext *ic)
512
{
513
    int64_t filesize, duration;
514
    int bit_rate, i;
515
    AVStream *st;
516

  
517
    /* if bit_rate is already set, we believe it */
518
    if (ic->bit_rate == 0) {
519
        bit_rate = 0;
520
        for(i=0;i<ic->nb_streams;i++) {
521
            st = ic->streams[i];
522
            bit_rate += st->codec.bit_rate;
523
        }
524
        ic->bit_rate = bit_rate;
525
    }
526

  
527
    /* if duration is already set, we believe it */
528
    if (ic->duration == AV_NOPTS_VALUE && 
529
        ic->bit_rate != 0 && 
530
        ic->file_size != 0)  {
531
        filesize = ic->file_size;
532
        if (filesize > 0) {
533
            duration = (int64_t)((8 * AV_TIME_BASE * (double)filesize) / (double)ic->bit_rate);
534
            for(i = 0; i < ic->nb_streams; i++) {
535
                st = ic->streams[i];
536
                if (st->start_time == AV_NOPTS_VALUE ||
537
                    st->duration == AV_NOPTS_VALUE) {
538
                    st->start_time = 0;
539
                    st->duration = duration;
540
                }
541
            }
542
        }
543
    }
544
}
545

  
546
static void flush_packet_queue(AVFormatContext *s)
547
{
548
    AVPacketList *pktl;
549

  
550
    for(;;) {
551
        pktl = s->packet_buffer;
552
        if (!pktl) 
553
            break;
554
        s->packet_buffer = pktl->next;
555
        av_free(pktl);
556
    }
557
}
558

  
559
#define DURATION_MAX_READ_SIZE 250000
560

  
561
/* only usable for MPEG-PS streams */
562
static void av_estimate_timings_from_pts(AVFormatContext *ic)
563
{
564
    AVPacket pkt1, *pkt = &pkt1;
565
    AVStream *st;
566
    int read_size, i, ret;
567
    int64_t start_time, end_time, end_time1;
568
    int64_t filesize, offset, duration;
569
    
570
    /* we read the first packets to get the first PTS (not fully
571
       accurate, but it is enough now) */
572
    url_fseek(&ic->pb, 0, SEEK_SET);
573
    read_size = 0;
574
    for(;;) {
575
        if (read_size >= DURATION_MAX_READ_SIZE)
576
            break;
577
        /* if all info is available, we can stop */
578
        for(i = 0;i < ic->nb_streams; i++) {
579
            st = ic->streams[i];
580
            if (st->start_time == AV_NOPTS_VALUE)
581
                break;
582
        }
583
        if (i == ic->nb_streams)
584
            break;
585

  
586
        ret = av_read_packet(ic, pkt);
587
        if (ret != 0)
588
            break;
589
        read_size += pkt->size;
590
        st = ic->streams[pkt->stream_index];
591
        if (pkt->pts != AV_NOPTS_VALUE) {
592
            if (st->start_time == AV_NOPTS_VALUE)
593
                st->start_time = (int64_t)((double)pkt->pts * ic->pts_num * (double)AV_TIME_BASE / ic->pts_den);
594
         }
595
         av_free_packet(pkt);
596
     }
597

  
598
    /* we compute the minimum start_time and use it as default */
599
    start_time = MAXINT64;
600
    for(i = 0; i < ic->nb_streams; i++) {
601
        st = ic->streams[i];
602
        if (st->start_time != AV_NOPTS_VALUE &&
603
            st->start_time < start_time)
604
            start_time = st->start_time;
605
    }
606
    printf("start=%lld\n", start_time);
607
    if (start_time != MAXINT64)
608
        ic->start_time = start_time;
609
    
610
    /* estimate the end time (duration) */
611
    /* XXX: may need to support wrapping */
612
    filesize = ic->file_size;
613
    offset = filesize - DURATION_MAX_READ_SIZE;
614
    if (offset < 0)
615
        offset = 0;
616

  
617
    /* flush packet queue */
618
    flush_packet_queue(ic);
619

  
620
    url_fseek(&ic->pb, offset, SEEK_SET);
621
    read_size = 0;
622
    for(;;) {
623
        if (read_size >= DURATION_MAX_READ_SIZE)
624
            break;
625
        /* if all info is available, we can stop */
626
        for(i = 0;i < ic->nb_streams; i++) {
627
            st = ic->streams[i];
628
            if (st->duration == AV_NOPTS_VALUE)
629
                break;
630
        }
631
        if (i == ic->nb_streams)
632
            break;
633
        
634
        ret = av_read_packet(ic, pkt);
635
        if (ret != 0)
636
            break;
637
        read_size += pkt->size;
638
        st = ic->streams[pkt->stream_index];
639
        if (pkt->pts != AV_NOPTS_VALUE) {
640
            end_time = (int64_t)((double)pkt->pts * ic->pts_num * (double)AV_TIME_BASE / ic->pts_den);
641
            duration = end_time - st->start_time;
642
            if (duration > 0) {
643
                if (st->duration == AV_NOPTS_VALUE ||
644
                    st->duration < duration)
645
                    st->duration = duration;
646
            }
647
        }
648
        av_free_packet(pkt);
649
    }
650
    
651
    /* estimate total duration */
652
    end_time = MININT64;
653
    for(i = 0;i < ic->nb_streams; i++) {
654
        st = ic->streams[i];
655
        if (st->duration != AV_NOPTS_VALUE) {
656
            end_time1 = st->start_time + st->duration;
657
            if (end_time1 > end_time)
658
                end_time = end_time1;
659
        }
660
    }
661
    
662
    /* update start_time (new stream may have been created, so we do
663
       it at the end */
664
    if (ic->start_time != AV_NOPTS_VALUE) {
665
        for(i = 0; i < ic->nb_streams; i++) {
666
            st = ic->streams[i];
667
            if (st->start_time == AV_NOPTS_VALUE)
668
                st->start_time = ic->start_time;
669
        }
670
    }
671

  
672
    if (end_time != MININT64) {
673
        /* put dummy values for duration if needed */
674
        for(i = 0;i < ic->nb_streams; i++) {
675
            st = ic->streams[i];
676
            if (st->duration == AV_NOPTS_VALUE && 
677
                st->start_time != AV_NOPTS_VALUE)
678
                st->duration = end_time - st->start_time;
679
        }
680
        ic->duration = end_time - ic->start_time;
681
    }
682

  
683
    url_fseek(&ic->pb, 0, SEEK_SET);
684
}
685

  
686
static void av_estimate_timings(AVFormatContext *ic)
687
{
688
    URLContext *h;
689
    int64_t file_size;
690

  
691
    /* get the file size, if possible */
692
    if (ic->iformat->flags & AVFMT_NOFILE) {
693
        file_size = 0;
694
    } else {
695
        h = url_fileno(&ic->pb);
696
        file_size = url_filesize(h);
697
        if (file_size < 0)
698
            file_size = 0;
699
    }
700
    ic->file_size = file_size;
701

  
702
    if (ic->iformat == &mpegps_demux) {
703
        /* get accurate estimate from the PTSes */
704
        av_estimate_timings_from_pts(ic);
705
    } else if (av_has_timings(ic)) {
706
        /* at least one components has timings - we use them for all
707
           the components */
708
        fill_all_stream_timings(ic);
709
    } else {
710
        /* less precise: use bit rate info */
711
        av_estimate_timings_from_bit_rate(ic);
712
    }
713
    av_update_stream_timings(ic);
714

  
715
#if 0
716
    {
717
        int i;
718
        AVStream *st;
719
        for(i = 0;i < ic->nb_streams; i++) {
720
            st = ic->streams[i];
721
        printf("%d: start_time: %0.3f duration: %0.3f\n", 
722
               i, (double)st->start_time / AV_TIME_BASE, 
723
               (double)st->duration / AV_TIME_BASE);
724
        }
725
        printf("stream: start_time: %0.3f duration: %0.3f bitrate=%d kb/s\n", 
726
               (double)ic->start_time / AV_TIME_BASE, 
727
               (double)ic->duration / AV_TIME_BASE,
728
               ic->bit_rate / 1000);
729
    }
730
#endif
731
}
732

  
442 733
/* state for codec information */
443 734
#define CSTATE_NOTFOUND    0
444 735
#define CSTATE_DECODING    1
......
662 953
        }
663 954
    }
664 955

  
956

  
957
    av_estimate_timings(ic);
665 958
    return ret;
666 959
}
667 960

  
......
725 1018

  
726 1019
    st->index = s->nb_streams;
727 1020
    st->id = id;
1021
    st->start_time = AV_NOPTS_VALUE;
1022
    st->duration = AV_NOPTS_VALUE;
728 1023
    s->streams[s->nb_streams++] = st;
729 1024
    return st;
730 1025
}
......
874 1169
            index, 
875 1170
            is_output ? ic->oformat->name : ic->iformat->name, 
876 1171
            is_output ? "to" : "from", url);
1172
    if (!is_output) {
1173
        printf("  Duration: ");
1174
        if (ic->duration != AV_NOPTS_VALUE) {
1175
            int hours, mins, secs, us;
1176
            secs = ic->duration / AV_TIME_BASE;
1177
            us = ic->duration % AV_TIME_BASE;
1178
            mins = secs / 60;
1179
            secs %= 60;
1180
            hours = mins / 60;
1181
            mins %= 60;
1182
            printf("%02d:%02d:%02d.%01d", hours, mins, secs, 
1183
                   (10 * us) / AV_TIME_BASE);
1184
        } else {
1185
            printf("N/A");
1186
        }
1187
        printf(", bitrate: ");
1188
        if (ic->bit_rate) {
1189
            printf("%d kb/s", ic->bit_rate / 1000);
1190
        } else {
1191
            printf("N/A");
1192
        }
1193
        printf("\n");
1194
    }
877 1195
    for(i=0;i<ic->nb_streams;i++) {
878 1196
        AVStream *st = ic->streams[i];
879 1197
        avcodec_string(buf, sizeof(buf), &st->codec, is_output);

Also available in: Unified diff