Revision 0e7eed09

View differences:

libav/mov.c
103 103
    { CODEC_ID_SVQ1, MKTAG('S', 'V', 'Q', '1') }, /* Sorenson Video v1 */
104 104
    { CODEC_ID_SVQ1, MKTAG('s', 'v', 'q', '1') }, /* Sorenson Video v1 */
105 105
    { CODEC_ID_SVQ1, MKTAG('s', 'v', 'q', 'i') }, /* Sorenson Video v1 (from QT specs)*/
106
    { CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') }, /* OpenDiVX *//* yeah ! */
106
    { CODEC_ID_MPEG4, MKTAG('m', 'p', '4', 'v') },
107 107
    { CODEC_ID_MPEG4, MKTAG('D', 'I', 'V', 'X') }, /* OpenDiVX *//* sample files at http://heroinewarrior.com/xmovie.php3 use this tag */
108 108
/*    { CODEC_ID_, MKTAG('I', 'V', '5', '0') }, *//* Indeo 5.0 */
109 109
    { CODEC_ID_H263, MKTAG('h', '2', '6', '3') }, /* H263 */
......
158 158
    long time_scale;
159 159
    long current_sample;
160 160
    long left_in_chunk; /* how many samples before next chunk */
161
    /* specific MPEG4 header which is added at the beginning of the stream */
162
    int header_len;
163
    uint8_t *header_data;
161 164
} MOVStreamContext;
162 165

  
163 166
typedef struct MOVContext {
......
580 583
    return 0;
581 584
}
582 585

  
586
static int mp4_read_descr_len(ByteIOContext *pb)
587
{
588
    int c, len, count;
589

  
590
    len = 0;
591
    count = 0;
592
    for(;;) {
593
        c = get_byte(pb);
594
        len = (len << 7) | (c & 0x7f);
595
        if ((c & 0x80) == 0)
596
            break;
597
        if (++count == 4)
598
            break;
599
    }
600
    return len;
601
}
602

  
603
static int mp4_read_descr(ByteIOContext *pb, int *tag)
604
{
605
    int len;
606
    *tag = get_byte(pb);
607
    len = mp4_read_descr_len(pb);
608
#ifdef DEBUG
609
    printf("MPEG4 description: tag=0x%02x len=%d\n", *tag, len);
610
#endif
611
    return len;
612
}
613

  
583 614
static int parse_stsd(const MOVParseTableEntry *parse_table, ByteIOContext *pb, UINT32 atom_type, INT64 atom_offset, INT64 atom_size, void *param)
584 615
{
585 616
    MOVContext *c;
586
    int entries, size, samp_sz, frames_per_sample;
617
    int entries, size, samp_sz, frames_per_sample, id;
587 618
    UINT32 format;
588 619
    AVStream *st;
620
    MOVStreamContext *sc;
589 621
#ifdef DEBUG
590 622
    print_atom("stsd", atom_type, atom_offset, atom_size);
591 623
#endif
592 624
    c = (MOVContext *)param;
593 625
    st = c->fc->streams[c->fc->nb_streams-1];
626
    sc = (MOVStreamContext *)st->priv_data;
594 627

  
595 628
    get_byte(pb); /* version */
596 629
    get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
597 630

  
598

  
599 631
    entries = get_be32(pb);
600 632

  
601 633
    while(entries--) {
......
605 637
        get_be32(pb); /* reserved */
606 638
        get_be16(pb); /* reserved */
607 639
        get_be16(pb); /* index */
608
/*        if(format == MKTAG('m', 'p', '4', 'v')) */
609
/*            st->codec.codec_type=CODEC_TYPE_VIDEO; *//* force things (XXX: was this for .mp4 ?) */
640

  
641
        /* for MPEG4: set codec type by looking for it */
642
        id = codec_get_id(mov_video_tags, format);
643
        if (id >= 0) {
644
            AVCodec *codec;
645
            codec = avcodec_find_decoder(id);
646
            if (codec)
647
                st->codec.codec_type = codec->type;
648
        }
649
#ifdef DEBUG
650
        printf("size=%d 4CC= %c%c%c%c codec_type=%d\n", 
651
               size, 
652
               (format >> 0) & 0xff,
653
               (format >> 8) & 0xff,
654
               (format >> 16) & 0xff,
655
               (format >> 24) & 0xff,
656
               st->codec.codec_type);
657
#endif
610 658
        if(st->codec.codec_type==CODEC_TYPE_VIDEO) {
611 659
            st->codec.codec_tag = format;
612 660
            st->codec.codec_id = codec_get_id(mov_video_tags, format);
......
617 665
            get_be32(pb); /* spacial quality */
618 666
            st->codec.width = get_be16(pb); /* width */
619 667
            st->codec.height = get_be16(pb); /* height */
668
#if 1
669
            if (st->codec.codec_id == CODEC_ID_MPEG4) {
670
                /* in some MPEG4 the width/height are not correct, so
671
                   we ignore this info */
672
                st->codec.width = 0;
673
                st->codec.height = 0;
674
            }
675
#endif
620 676
            get_be32(pb); /* horiz resolution */
621 677
            get_be32(pb); /* vert resolution */
622 678
            get_be32(pb); /* data size, always 0 */
......
628 684

  
629 685
            get_be16(pb); /* depth */
630 686
            get_be16(pb); /* colortable id */
631
            get_be16(pb); /*  */
632
            get_be16(pb); /*  */
633 687
            
634
            st->codec.sample_rate = 25 * FRAME_RATE_BASE;
688
            st->codec.frame_rate = 25 * FRAME_RATE_BASE;
635 689
            
636
            if(size > 16)
637
                url_fskip(pb, size-(16+24+18+32));
690
            size -= (16+8*4+2+32+2*2);
691
            while (size >= 8) {
692
                int atom_size, atom_type;
693
                INT64 start_pos;
694
                
695
                atom_size = get_be32(pb);
696
                atom_type = get_le32(pb);
697
                size -= 8;
698
#ifdef DEBUG
699
                printf("VIDEO: atom_type=%c%c%c%c atom_size=%d size_left=%d\n", 
700
                       (atom_type >> 0) & 0xff,
701
                       (atom_type >> 8) & 0xff,
702
                       (atom_type >> 16) & 0xff,
703
                       (atom_type >> 24) & 0xff,
704
                       atom_size, size);
705
#endif
706
                start_pos = url_ftell(pb);
707

  
708
                switch(atom_type) {
709
                case MKTAG('e', 's', 'd', 's'):
710
                    {
711
                        int tag, len;
712
                        /* Well, broken but suffisant for some MP4 streams */
713
                        get_be32(pb); /* version + flags */
714
                        len = mp4_read_descr(pb, &tag);
715
                        if (tag == 0x03) {
716
                            /* MP4ESDescrTag */
717
                            get_be16(pb); /* ID */
718
                            get_byte(pb); /* priority */
719
                            len = mp4_read_descr(pb, &tag);
720
                            if (tag != 0x04)
721
                                goto fail;
722
                            /* MP4DecConfigDescrTag */
723
                            get_byte(pb); /* objectTypeId */
724
                            get_be32(pb); /* streamType + buffer size */
725
                            get_be32(pb); /* max bit rate */
726
                            get_be32(pb); /* avg bit rate */
727
                            len = mp4_read_descr(pb, &tag);
728
                            if (tag != 0x05)
729
                                goto fail;
730
                            /* MP4DecSpecificDescrTag */
731
#ifdef DEBUG
732
                            printf("Specific MPEG4 header len=%d\n", len);
733
#endif
734
                            sc->header_data = av_mallocz(len);
735
                            if (sc->header_data) {
736
                                get_buffer(pb, sc->header_data, len);
737
                                sc->header_len = len;
738
                            }
739
                        }
740
                        /* in any case, skip garbage */
741
                    }
742
                    break;
743
                default:
744
                    break;
745
                }
746
            fail:
747
                url_fskip(pb, (atom_size - 8) - 
748
                          ((url_ftell(pb) - start_pos)));
749
                size -= atom_size - 8;
750
            }
751
            if (size > 0) {
752
                /* unknown extension */
753
                url_fskip(pb, size);
754
            }
638 755
        } else {
639 756
            st->codec.codec_tag = format;
640 757

  
......
658 775
            
659 776
            st->codec.sample_rate = ((get_be32(pb) >> 16));
660 777
            st->codec.bit_rate = 0;
661

  
662
            /* this is for .mp4 files */
663
            if(format == MKTAG('m', 'p', '4', 'v')) { /* XXX */
664
                st->codec.codec_type=CODEC_TYPE_VIDEO; /* force things */
665
                st->codec.codec_id = CODEC_ID_MPEG4;
666
                st->codec.frame_rate = 25 * FRAME_RATE_BASE;
667
                st->codec.bit_rate = 100000;
668
            }
669
//            if(format == MKTAG('m', 'p', '4', 'a')) { /* XXX */
670
//                st->codec.codec_type=CODEC_TYPE_AUDIO; /* force things */
671
//                st->codec.codec_id = CODEC_ID_AAC;
672
////                st->codec.frame_rate = 25 * FRAME_RATE_BASE;
673
////                st->codec.bit_rate = 100000;
674
//            }
675

  
676 778
#if 0
677 779

  
678 780
            get_be16(pb); get_be16(pb); /*  */
......
684 786
            if(size > 16)
685 787
                url_fskip(pb, size-(16+20));
686 788
        }
687
#ifdef DEBUG
688
        printf("4CC= %c%c%c%c\n", *((char *)&format), ((char *)&format)[1], ((char *)&format)[2], ((char *)&format)[3]);
689
#endif
690 789
    }
691 790
/*
692 791
    if(len) {
......
722 821
    if(atom_type == MKTAG('s', 't', 'c', 'o')) {
723 822
        for(i=0; i<entries; i++) {
724 823
            sc->chunk_offsets[i] = get_be32(pb);
725
            /*printf("chunk offset=%ld\n", sc->chunk_offsets[i]);*/
726 824
        }
727 825
    } else if(atom_type == MKTAG('c', 'o', '6', '4')) {
728 826
        for(i=0; i<entries; i++) {
729 827
            sc->chunk_offsets[i] = get_be64(pb);
730
            /*printf("chunk offset=%ld\n", sc->chunk_offsets[i]);*/
731 828
        }
732 829
    } else
733 830
        return -1;
831
#ifdef DEBUG
832
    for(i=0; i<entries; i++) {
833
        printf("chunk offset=0x%Lx\n", sc->chunk_offsets[i]);
834
    }
835
#endif
734 836
    return 0;
735 837
}
736 838

  
......
971 1073
    if(sc) {
972 1074
        av_free(sc->chunk_offsets);
973 1075
        av_free(sc->sample_to_chunk);
1076
        av_free(sc->header_data);
974 1077
        av_free(sc);
975 1078
    }
976 1079
}
977 1080

  
1081
static uint32_t to_tag(uint8_t *buf)
1082
{
1083
    return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
1084
}
1085

  
1086
static uint32_t to_be32(uint8_t *buf)
1087
{
1088
    return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
1089
}
1090

  
978 1091
/* XXX: is it suffisant ? */
979 1092
static int mov_probe(AVProbeData *p)
980 1093
{
981
    int offset;
1094
    unsigned int offset;
1095
    uint32_t tag;
982 1096

  
983 1097
    /* check file header */
984 1098
    if (p->buf_size <= 12)
985 1099
        return 0;
986
    if ((p->buf[4] == 'm' && p->buf[5] == 'o' &&
987
         p->buf[6] == 'o' && p->buf[7] == 'v') ||
988
        (p->buf[4] == 'w' && p->buf[5] == 'i' &&
989
         p->buf[6] == 'd' && p->buf[7] == 'e') ||
990
        (p->buf[4] == 'f' && p->buf[5] == 'r' &&
991
         p->buf[6] == 'e' && p->buf[7] == 'e') ||
992
        (p->buf[4] == 'm' && p->buf[5] == 'd' &&
993
         p->buf[6] == 'a' && p->buf[7] == 't'))
994
        return AVPROBE_SCORE_MAX;
995
    if (p->buf[4] == 'f' && p->buf[5] == 't' &&
996
        p->buf[6] == 'y' && p->buf[7] == 'p') {
997
        offset = p->buf[0]; offset <<= 8;
998
        offset |= p->buf[1]; offset <<= 8;
999
        offset |= p->buf[2]; offset <<= 8;
1000
        offset |= p->buf[3];
1001
        if (offset > p->buf_size)
1100
    offset = 0;
1101
    for(;;) {
1102
        /* ignore invalid offset */
1103
        if ((offset + 8) > (unsigned int)p->buf_size)
1002 1104
            return 0;
1003
        if ((p->buf[offset+4] == 'm' && p->buf[offset+5] == 'o' &&
1004
             p->buf[offset+6] == 'o' && p->buf[offset+7] == 'v') ||
1005
            (p->buf[offset+4] == 'w' && p->buf[offset+5] == 'i' &&
1006
             p->buf[offset+6] == 'd' && p->buf[offset+7] == 'e') ||
1007
            (p->buf[offset+4] == 'm' && p->buf[offset+5] == 'd' &&
1008
             p->buf[offset+6] == 'a' && p->buf[offset+7] == 't'))
1105
        tag = to_tag(p->buf + offset + 4);
1106
        switch(tag) {
1107
        case MKTAG( 'm', 'o', 'o', 'v' ):
1108
        case MKTAG( 'w', 'i', 'd', 'e' ):
1109
        case MKTAG( 'f', 'r', 'e', 'e' ):
1110
        case MKTAG( 'm', 'd', 'a', 't'):
1009 1111
            return AVPROBE_SCORE_MAX;
1010

  
1112
        case MKTAG( 'f', 't', 'y', 'p' ):
1113
        case MKTAG( 's', 'k', 'i', 'p' ):            
1114
            offset = to_be32(p->buf) + offset;
1115
            break;
1116
        default:
1117
            /* unrecognized tag */
1118
            return 0;
1119
        }
1011 1120
    }
1012 1121
    return 0;
1013 1122
}
......
1086 1195
static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
1087 1196
{
1088 1197
    MOVContext *mov = s->priv_data;
1198
    MOVStreamContext *sc;
1089 1199
    INT64 offset = 0x0FFFFFFFFFFFFFFF;
1090 1200
    int i;
1091 1201
    int st_id = 0, size;
1092 1202
    size = 0x0FFFFFFF;
1093

  
1203
    
1094 1204
#ifdef MOV_SPLIT_CHUNKS
1095 1205
    if (mov->partial) {
1096 1206
        
......
1167 1277
#endif
1168 1278

  
1169 1279
readchunk:
1170

  
1171 1280
//printf("chunk: [%i] %lli -> %lli (%i)\n", st_id, offset, offset + size, size);
1172 1281
    if(size == 0x0FFFFFFF)
1173 1282
        size = mov->mdat_size + mov->mdat_offset - offset;
......
1175 1284
        return -1;
1176 1285
    if(size == 0)
1177 1286
        return -1;
1178
    av_new_packet(pkt, size);
1179
    pkt->stream_index = mov->streams[st_id]->ffindex;
1180

  
1181
    get_buffer(&s->pb, pkt->data, pkt->size);
1287
    url_fseek(&s->pb, offset, SEEK_SET);
1288
    sc = mov->streams[st_id];
1289
    if (sc->header_len > 0) {
1290
        av_new_packet(pkt, size + sc->header_len);
1291
        memcpy(pkt->data, sc->header_data, sc->header_len);
1292
        get_buffer(&s->pb, pkt->data + sc->header_len, size);
1293
        /* free header */
1294
        av_freep(&sc->header_data);
1295
        sc->header_len = 0;
1296
    } else {
1297
        av_new_packet(pkt, size);
1298
        get_buffer(&s->pb, pkt->data, pkt->size);
1299
    }
1300
    pkt->stream_index = sc->ffindex;
1182 1301

  
1183 1302
#ifdef DEBUG
1184 1303
/*

Also available in: Unified diff