avidec.c 46.3 KB
Newer Older
Fabrice Bellard's avatar
Fabrice Bellard committed
1
/*
2
 * AVI demuxer
Diego Biurrun's avatar
Diego Biurrun committed
3
 * Copyright (c) 2001 Fabrice Bellard
Fabrice Bellard's avatar
Fabrice Bellard committed
4
 *
5 6 7
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
8 9
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
Fabrice Bellard's avatar
Fabrice Bellard committed
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
Fabrice Bellard's avatar
Fabrice Bellard committed
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
Fabrice Bellard's avatar
Fabrice Bellard committed
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Fabrice Bellard's avatar
Fabrice Bellard committed
20
 */
21

22 23 24
//#define DEBUG
//#define DEBUG_SEEK

25
#include <strings.h>
26
#include "libavutil/intreadwrite.h"
27
#include "libavutil/bswap.h"
28
#include "libavcodec/bytestream.h"
Fabrice Bellard's avatar
Fabrice Bellard committed
29 30
#include "avformat.h"
#include "avi.h"
31
#include "dv.h"
32
#include "riff.h"
Fabrice Bellard's avatar
Fabrice Bellard committed
33

34 35 36
#undef NDEBUG
#include <assert.h>

Fabrice Bellard's avatar
Fabrice Bellard committed
37
typedef struct AVIStream {
38
    int64_t frame_offset; /* current frame (video) or byte (audio) counter
Fabrice Bellard's avatar
Fabrice Bellard committed
39
                         (used to compute the pts) */
40 41 42
    int remaining;
    int packet_size;

Fabrice Bellard's avatar
Fabrice Bellard committed
43
    int scale;
44
    int rate;
45
    int sample_size; /* size of one sample (or packet) (in the rate/scale sense) in bytes */
46

47
    int64_t cum_len; /* temporary storage (used during seek) */
48

49 50
    int prefix;                       ///< normally 'd'<<8 + 'c' or 'w'<<8 + 'b'
    int prefix_count;
51 52
    uint32_t pal[256];
    int has_pal;
53
    int dshow_block_align;            ///< block align variable used to emulate bugs in the MS dshow demuxer
54 55 56 57

    AVFormatContext *sub_ctx;
    AVPacket sub_pkt;
    uint8_t *sub_buffer;
Fabrice Bellard's avatar
Fabrice Bellard committed
58
} AVIStream;
Fabrice Bellard's avatar
Fabrice Bellard committed
59 60

typedef struct {
61 62
    int64_t  riff_end;
    int64_t  movi_end;
63
    int64_t  fsize;
64
    int64_t movi_list;
65
    int64_t last_pkt_pos;
Fabrice Bellard's avatar
Fabrice Bellard committed
66
    int index_loaded;
67
    int is_odml;
68 69
    int non_interleaved;
    int stream_index;
70
    DVDemuxContext* dv_demux;
71 72
    int odml_depth;
#define MAX_ODML_DEPTH 1000
Fabrice Bellard's avatar
Fabrice Bellard committed
73 74
} AVIContext;

75 76 77 78
static const char avi_headers[][8] = {
    { 'R', 'I', 'F', 'F',    'A', 'V', 'I', ' ' },
    { 'R', 'I', 'F', 'F',    'A', 'V', 'I', 'X' },
    { 'R', 'I', 'F', 'F',    'A', 'V', 'I', 0x19},
79
    { 'O', 'N', '2', ' ',    'O', 'N', '2', 'f' },
80
    { 'R', 'I', 'F', 'F',    'A', 'M', 'V', ' ' },
81 82 83
    { 0 }
};

84
static int avi_load_index(AVFormatContext *s);
85
static int guess_ni_flag(AVFormatContext *s);
86

Fabrice Bellard's avatar
Fabrice Bellard committed
87
#ifdef DEBUG
88
static void print_tag(const char *str, unsigned int tag, int size)
Fabrice Bellard's avatar
Fabrice Bellard committed
89
{
90
    dprintf(NULL, "%s: tag=%c%c%c%c size=0x%x\n",
Fabrice Bellard's avatar
Fabrice Bellard committed
91 92 93 94 95 96 97 98
           str, tag & 0xff,
           (tag >> 8) & 0xff,
           (tag >> 16) & 0xff,
           (tag >> 24) & 0xff,
           size);
}
#endif

99 100 101
static inline int get_duration(AVIStream *ast, int len){
    if(ast->sample_size){
        return len;
102 103
    }else if (ast->dshow_block_align){
        return (len + ast->dshow_block_align - 1)/ast->dshow_block_align;
104 105 106 107
    }else
        return 1;
}

108
static int get_riff(AVFormatContext *s, ByteIOContext *pb)
109
{
110
    AVIContext *avi = s->priv_data;
111 112
    char header[8];
    int i;
113

114 115
    /* check RIFF header */
    get_buffer(pb, header, 4);
116 117
    avi->riff_end = get_le32(pb);   /* RIFF chunk size */
    avi->riff_end += url_ftell(pb); /* RIFF chunk end */
118 119 120 121 122 123
    get_buffer(pb, header+4, 4);

    for(i=0; avi_headers[i][0]; i++)
        if(!memcmp(header, avi_headers[i], 8))
            break;
    if(!avi_headers[i][0])
124
        return -1;
125

126
    if(header[7] == 0x19)
127
        av_log(s, AV_LOG_INFO, "This file has been generated by a totally broken muxer.\n");
128

129 130 131
    return 0;
}

132
static int read_braindead_odml_indx(AVFormatContext *s, int frame_num){
133
    AVIContext *avi = s->priv_data;
134
    ByteIOContext *pb = s->pb;
135 136 137 138 139 140 141 142 143 144
    int longs_pre_entry= get_le16(pb);
    int index_sub_type = get_byte(pb);
    int index_type     = get_byte(pb);
    int entries_in_use = get_le32(pb);
    int chunk_id       = get_le32(pb);
    int64_t base       = get_le64(pb);
    int stream_id= 10*((chunk_id&0xFF) - '0') + (((chunk_id>>8)&0xFF) - '0');
    AVStream *st;
    AVIStream *ast;
    int i;
145
    int64_t last_pos= -1;
146
    int64_t filesize= url_fsize(s->pb);
147

148
#ifdef DEBUG_SEEK
149
    av_log(s, AV_LOG_ERROR, "longs_pre_entry:%d index_type:%d entries_in_use:%d chunk_id:%X base:%16"PRIX64"\n",
150 151
        longs_pre_entry,index_type, entries_in_use, chunk_id, base);
#endif
152

153
    if(stream_id >= s->nb_streams || stream_id < 0)
154 155 156 157 158 159 160 161 162 163 164 165 166 167
        return -1;
    st= s->streams[stream_id];
    ast = st->priv_data;

    if(index_sub_type)
        return -1;

    get_le32(pb);

    if(index_type && longs_pre_entry != 2)
        return -1;
    if(index_type>1)
        return -1;

168 169 170 171 172 173 174 175
    if(filesize > 0 && base >= filesize){
        av_log(s, AV_LOG_ERROR, "ODML index invalid\n");
        if(base>>32 == (base & 0xFFFFFFFF) && (base & 0xFFFFFFFF) < filesize && filesize <= 0xFFFFFFFF)
            base &= 0xFFFFFFFF;
        else
            return -1;
    }

176 177
    for(i=0; i<entries_in_use; i++){
        if(index_type){
178
            int64_t pos= get_le32(pb) + base - 8;
179
            int len    = get_le32(pb);
180
            int key= len >= 0;
181 182
            len &= 0x7FFFFFFF;

183
#ifdef DEBUG_SEEK
184
            av_log(s, AV_LOG_ERROR, "pos:%"PRId64", len:%X\n", pos, len);
185
#endif
186 187 188
            if(url_feof(pb))
                return -1;

189 190
            if(last_pos == pos || pos == base - 8)
                avi->non_interleaved= 1;
191
            if(last_pos != pos && (len || !ast->sample_size))
192
                av_add_index_entry(st, pos, ast->cum_len, len, 0, key ? AVINDEX_KEYFRAME : 0);
193

194
            ast->cum_len += get_duration(ast, len);
195
            last_pos= pos;
196
        }else{
Måns Rullgård's avatar
Måns Rullgård committed
197 198 199 200 201
            int64_t offset, pos;
            int duration;
            offset = get_le64(pb);
            get_le32(pb);       /* size */
            duration = get_le32(pb);
202 203 204 205

            if(url_feof(pb))
                return -1;

Måns Rullgård's avatar
Måns Rullgård committed
206
            pos = url_ftell(pb);
207

208 209 210 211 212
            if(avi->odml_depth > MAX_ODML_DEPTH){
                av_log(s, AV_LOG_ERROR, "Too deeply nested ODML indexes\n");
                return -1;
            }

213
            url_fseek(pb, offset+8, SEEK_SET);
214
            avi->odml_depth++;
215
            read_braindead_odml_indx(s, frame_num);
216
            avi->odml_depth--;
217 218 219 220 221
            frame_num += duration;

            url_fseek(pb, pos, SEEK_SET);
        }
    }
222
    avi->index_loaded=1;
223 224 225
    return 0;
}

226
static void clean_index(AVFormatContext *s){
227 228
    int i;
    int64_t j;
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246

    for(i=0; i<s->nb_streams; i++){
        AVStream *st = s->streams[i];
        AVIStream *ast = st->priv_data;
        int n= st->nb_index_entries;
        int max= ast->sample_size;
        int64_t pos, size, ts;

        if(n != 1 || ast->sample_size==0)
            continue;

        while(max < 1024) max+=max;

        pos= st->index_entries[0].pos;
        size= st->index_entries[0].size;
        ts= st->index_entries[0].timestamp;

        for(j=0; j<size; j+=max){
247
            av_add_index_entry(st, pos+j, ts+j, FFMIN(max, size-j), 0, AVINDEX_KEYFRAME);
248 249 250 251
        }
    }
}

252
static int avi_read_tag(AVFormatContext *s, AVStream *st, uint32_t tag, uint32_t size)
253
{
254
    ByteIOContext *pb = s->pb;
255
    char key[5] = {0}, *value;
256

257
    size += (size & 1);
258

259 260 261 262 263
    if (size == UINT_MAX)
        return -1;
    value = av_malloc(size+1);
    if (!value)
        return -1;
264 265
    get_buffer(pb, value, size);
    value[size]=0;
266

267 268
    AV_WL32(key, tag);

269 270
    return av_metadata_set2(st ? &st->metadata : &s->metadata, key, value,
                            AV_METADATA_DONT_STRDUP_VAL);
271 272
}

273 274 275 276 277 278 279 280 281
static void avi_read_info(AVFormatContext *s, uint64_t end)
{
    while (url_ftell(s->pb) < end) {
        uint32_t tag  = get_le32(s->pb);
        uint32_t size = get_le32(s->pb);
        avi_read_tag(s, NULL, tag, size);
    }
}

282 283 284 285 286 287 288 289 290
static const char months[12][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
                                    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };

static void avi_metadata_creation_time(AVMetadata **metadata, char *date)
{
    char month[4], time[9], buffer[64];
    int i, day, year;
    /* parse standard AVI date format (ie. "Mon Mar 10 15:04:43 2003") */
    if (sscanf(date, "%*3s%*[ ]%3s%*[ ]%2d%*[ ]%8s%*[ ]%4d",
291
               month, &day, time, &year) == 4) {
292 293 294 295 296 297
        for (i=0; i<12; i++)
            if (!strcasecmp(month, months[i])) {
                snprintf(buffer, sizeof(buffer), "%.4d-%.2d-%.2d %s",
                         year, i+1, day, time);
                av_metadata_set2(metadata, "creation_time", buffer, 0);
            }
298 299 300 301
    } else if (date[4] == '/' && date[7] == '/') {
        date[4] = date[7] = '-';
        av_metadata_set2(metadata, "creation_time", date, 0);
    }
302 303
}

304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339
static void avi_read_nikon(AVFormatContext *s, uint64_t end)
{
    while (url_ftell(s->pb) < end) {
        uint32_t tag  = get_le32(s->pb);
        uint32_t size = get_le32(s->pb);
        switch (tag) {
        case MKTAG('n', 'c', 't', 'g'): {  /* Nikon Tags */
            uint64_t tag_end = url_ftell(s->pb) + size;
            while (url_ftell(s->pb) < tag_end) {
                uint16_t tag  = get_le16(s->pb);
                uint16_t size = get_le16(s->pb);
                const char *name = NULL;
                char buffer[64] = {0};
                size -= get_buffer(s->pb, buffer,
                                   FFMIN(size, sizeof(buffer)-1));
                switch (tag) {
                case 0x03:  name = "maker";  break;
                case 0x04:  name = "model";  break;
                case 0x13:  name = "creation_time";
                    if (buffer[4] == ':' && buffer[7] == ':')
                        buffer[4] = buffer[7] = '-';
                    break;
                }
                if (name)
                    av_metadata_set2(&s->metadata, name, buffer, 0);
                url_fskip(s->pb, size);
            }
            break;
        }
        default:
            url_fskip(s->pb, size);
            break;
        }
    }
}

340
static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
Fabrice Bellard's avatar
Fabrice Bellard committed
341
{
Fabrice Bellard's avatar
Fabrice Bellard committed
342
    AVIContext *avi = s->priv_data;
343
    ByteIOContext *pb = s->pb;
344
    unsigned int tag, tag1, handler;
345
    int codec_type, stream_index, frame_period, bit_rate;
Michael Niedermayer's avatar
Michael Niedermayer committed
346
    unsigned int size;
347
    int i;
Fabrice Bellard's avatar
Fabrice Bellard committed
348
    AVStream *st;
Måns Rullgård's avatar
Måns Rullgård committed
349
    AVIStream *ast = NULL;
350 351
    int avih_width=0, avih_height=0;
    int amv_file_format=0;
352
    uint64_t list_end = 0;
Fabrice Bellard's avatar
Fabrice Bellard committed
353

354
    avi->stream_index= -1;
355

356
    if (get_riff(s, pb) < 0)
Fabrice Bellard's avatar
Fabrice Bellard committed
357
        return -1;
358

359 360
    avi->fsize = url_fsize(pb);
    if(avi->fsize<=0)
361
        avi->fsize= avi->riff_end == 8 ? INT64_MAX : avi->riff_end;
362

Fabrice Bellard's avatar
Fabrice Bellard committed
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377
    /* first list tag */
    stream_index = -1;
    codec_type = -1;
    frame_period = 0;
    for(;;) {
        if (url_feof(pb))
            goto fail;
        tag = get_le32(pb);
        size = get_le32(pb);
#ifdef DEBUG
        print_tag("tag", tag, size);
#endif

        switch(tag) {
        case MKTAG('L', 'I', 'S', 'T'):
378
            list_end = url_ftell(pb) + size;
Diego Biurrun's avatar
Diego Biurrun committed
379
            /* Ignored, except at start of video packets. */
Fabrice Bellard's avatar
Fabrice Bellard committed
380 381 382 383 384
            tag1 = get_le32(pb);
#ifdef DEBUG
            print_tag("list", tag1, 0);
#endif
            if (tag1 == MKTAG('m', 'o', 'v', 'i')) {
Fabrice Bellard's avatar
Fabrice Bellard committed
385
                avi->movi_list = url_ftell(pb) - 4;
386
                if(size) avi->movi_end = avi->movi_list + size + (size & 1);
387
                else     avi->movi_end = url_fsize(pb);
388
                dprintf(NULL, "movi end=%"PRIx64"\n", avi->movi_end);
Fabrice Bellard's avatar
Fabrice Bellard committed
389 390
                goto end_of_header;
            }
391 392
            else if (tag1 == MKTAG('I', 'N', 'F', 'O'))
                avi_read_info(s, list_end);
393 394
            else if (tag1 == MKTAG('n', 'c', 'd', 't'))
                avi_read_nikon(s, list_end);
395

Fabrice Bellard's avatar
Fabrice Bellard committed
396
            break;
397 398 399 400 401 402 403 404
        case MKTAG('I', 'D', 'I', 'T'): {
            unsigned char date[64] = {0};
            size += (size & 1);
            size -= get_buffer(pb, date, FFMIN(size, sizeof(date)-1));
            url_fskip(pb, size);
            avi_metadata_creation_time(&s->metadata, date);
            break;
        }
405
        case MKTAG('d', 'm', 'l', 'h'):
406 407 408
            avi->is_odml = 1;
            url_fskip(pb, size + (size & 1));
            break;
409 410
        case MKTAG('a', 'm', 'v', 'h'):
            amv_file_format=1;
Fabrice Bellard's avatar
Fabrice Bellard committed
411
        case MKTAG('a', 'v', 'i', 'h'):
Diego Biurrun's avatar
Diego Biurrun committed
412
            /* AVI header */
413
            /* using frame_period is bad idea */
Fabrice Bellard's avatar
Fabrice Bellard committed
414 415
            frame_period = get_le32(pb);
            bit_rate = get_le32(pb) * 8;
416 417 418 419
            get_le32(pb);
            avi->non_interleaved |= get_le32(pb) & AVIF_MUSTUSEINDEX;

            url_fskip(pb, 2 * 4);
420
            get_le32(pb);
421 422 423
            get_le32(pb);
            avih_width=get_le32(pb);
            avih_height=get_le32(pb);
424

425
            url_fskip(pb, size - 10 * 4);
426 427 428 429 430 431 432 433 434 435 436 437 438
            break;
        case MKTAG('s', 't', 'r', 'h'):
            /* stream header */

            tag1 = get_le32(pb);
            handler = get_le32(pb); /* codec tag */

            if(tag1 == MKTAG('p', 'a', 'd', 's')){
                url_fskip(pb, size - 8);
                break;
            }else{
                stream_index++;
                st = av_new_stream(s, stream_index);
Fabrice Bellard's avatar
Fabrice Bellard committed
439 440
                if (!st)
                    goto fail;
441

Fabrice Bellard's avatar
Fabrice Bellard committed
442 443 444 445
                ast = av_mallocz(sizeof(AVIStream));
                if (!ast)
                    goto fail;
                st->priv_data = ast;
446
            }
447 448
            if(amv_file_format)
                tag1 = stream_index ? MKTAG('a','u','d','s') : MKTAG('v','i','d','s');
449

450
#ifdef DEBUG
451
            print_tag("strh", tag1, -1);
452
#endif
453
            if(tag1 == MKTAG('i', 'a', 'v', 's') || tag1 == MKTAG('i', 'v', 'a', 's')){
454 455
                int64_t dv_dur;

456
                /*
457
                 * After some consideration -- I don't think we
Diego Biurrun's avatar
Diego Biurrun committed
458
                 * have to support anything but DV in type1 AVIs.
459 460 461 462 463 464 465 466 467 468 469
                 */
                if (s->nb_streams != 1)
                    goto fail;

                if (handler != MKTAG('d', 'v', 's', 'd') &&
                    handler != MKTAG('d', 'v', 'h', 'd') &&
                    handler != MKTAG('d', 'v', 's', 'l'))
                   goto fail;

                ast = s->streams[0]->priv_data;
                av_freep(&s->streams[0]->codec->extradata);
470
                av_freep(&s->streams[0]->codec);
471 472
                av_freep(&s->streams[0]);
                s->nb_streams = 0;
473
                if (CONFIG_DV_DEMUXER) {
474 475 476
                    avi->dv_demux = dv_init_demux(s);
                    if (!avi->dv_demux)
                        goto fail;
477
                }
478 479 480 481
                s->streams[0]->priv_data = ast;
                url_fskip(pb, 3 * 4);
                ast->scale = get_le32(pb);
                ast->rate = get_le32(pb);
482 483 484 485 486 487 488 489 490
                url_fskip(pb, 4);  /* start time */

                dv_dur = get_le32(pb);
                if (ast->scale > 0 && ast->rate > 0 && dv_dur > 0) {
                    dv_dur *= AV_TIME_BASE;
                    s->duration = av_rescale(dv_dur, ast->scale, ast->rate);
                }
                /*
                 * else, leave duration alone; timing estimation in utils.c
Diego Biurrun's avatar
Diego Biurrun committed
491
                 *      will make a guess based on bitrate.
492 493
                 */

494
                stream_index = s->nb_streams - 1;
495
                url_fskip(pb, size - 9*4);
496 497
                break;
            }
498

499
            assert(stream_index < s->nb_streams);
500
            st->codec->stream_codec_tag= handler;
501

502 503 504 505 506 507
            get_le32(pb); /* flags */
            get_le16(pb); /* priority */
            get_le16(pb); /* language */
            get_le32(pb); /* initial frame */
            ast->scale = get_le32(pb);
            ast->rate = get_le32(pb);
508
            if(!(ast->scale && ast->rate)){
Diego Biurrun's avatar
Diego Biurrun committed
509
                av_log(s, AV_LOG_WARNING, "scale/rate is %u/%u which is invalid. (This file has been generated by broken software.)\n", ast->scale, ast->rate);
Michael Niedermayer's avatar
Michael Niedermayer committed
510 511 512 513 514 515 516
                if(frame_period){
                    ast->rate = 1000000;
                    ast->scale = frame_period;
                }else{
                    ast->rate = 25;
                    ast->scale = 1;
                }
517
            }
518
            av_set_pts_info(st, 64, ast->scale, ast->rate);
519

Michael Niedermayer's avatar
Michael Niedermayer committed
520
            ast->cum_len=get_le32(pb); /* start */
Michael Niedermayer's avatar
Michael Niedermayer committed
521
            st->nb_frames = get_le32(pb);
522

523 524 525 526
            st->start_time = 0;
            get_le32(pb); /* buffer size */
            get_le32(pb); /* quality */
            ast->sample_size = get_le32(pb); /* sample ssize */
527
            ast->cum_len *= FFMAX(1, ast->sample_size);
528
//            av_log(s, AV_LOG_DEBUG, "%d %d %d %d\n", ast->rate, ast->scale, ast->start, ast->sample_size);
529

530
            switch(tag1) {
531
            case MKTAG('v', 'i', 'd', 's'):
532
                codec_type = AVMEDIA_TYPE_VIDEO;
533

534 535 536
                ast->sample_size = 0;
                break;
            case MKTAG('a', 'u', 'd', 's'):
537
                codec_type = AVMEDIA_TYPE_AUDIO;
538
                break;
539
            case MKTAG('t', 'x', 't', 's'):
540
                codec_type = AVMEDIA_TYPE_SUBTITLE;
541
                break;
Florian Echtler's avatar
Florian Echtler committed
542
            case MKTAG('d', 'a', 't', 's'):
543
                codec_type = AVMEDIA_TYPE_DATA;
Florian Echtler's avatar
Florian Echtler committed
544
                break;
545
            default:
Michael Niedermayer's avatar
Michael Niedermayer committed
546
                av_log(s, AV_LOG_ERROR, "unknown stream type %X\n", tag1);
547
                goto fail;
Fabrice Bellard's avatar
Fabrice Bellard committed
548
            }
549 550
            if(ast->sample_size == 0)
                st->duration = st->nb_frames;
551
            ast->frame_offset= ast->cum_len;
552
            url_fskip(pb, size - 12 * 4);
Fabrice Bellard's avatar
Fabrice Bellard committed
553 554 555
            break;
        case MKTAG('s', 't', 'r', 'f'):
            /* stream header */
556
            if (stream_index >= (unsigned)s->nb_streams || avi->dv_demux) {
Fabrice Bellard's avatar
Fabrice Bellard committed
557 558
                url_fskip(pb, size);
            } else {
559 560 561
                uint64_t cur_pos = url_ftell(pb);
                if (cur_pos < list_end)
                    size = FFMIN(size, list_end - cur_pos);
Fabrice Bellard's avatar
Fabrice Bellard committed
562 563
                st = s->streams[stream_index];
                switch(codec_type) {
564
                case AVMEDIA_TYPE_VIDEO:
565 566 567
                    if(amv_file_format){
                        st->codec->width=avih_width;
                        st->codec->height=avih_height;
568
                        st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
569 570 571 572
                        st->codec->codec_id = CODEC_ID_AMV;
                        url_fskip(pb, size);
                        break;
                    }
Peter Ross's avatar
Peter Ross committed
573
                    tag1 = ff_get_bmp_header(pb, st);
574

Michael Niedermayer's avatar
Michael Niedermayer committed
575
                    if (tag1 == MKTAG('D', 'X', 'S', 'B') || tag1 == MKTAG('D','X','S','A')) {
576
                        st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
577 578 579 580 581
                        st->codec->codec_tag = tag1;
                        st->codec->codec_id = CODEC_ID_XSUB;
                        break;
                    }

582 583 584
                    if(size > 10*4 && size<(1<<30)){
                        st->codec->extradata_size= size - 10*4;
                        st->codec->extradata= av_malloc(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
585 586 587 588
                        if (!st->codec->extradata) {
                            st->codec->extradata_size= 0;
                            return AVERROR(ENOMEM);
                        }
589 590
                        get_buffer(pb, st->codec->extradata, st->codec->extradata_size);
                    }
591

592
                    if(st->codec->extradata_size & 1) //FIXME check if the encoder really did this correctly
593
                        get_byte(pb);
594

Diego Biurrun's avatar
Diego Biurrun committed
595 596 597
                    /* Extract palette from extradata if bpp <= 8. */
                    /* This code assumes that extradata contains only palette. */
                    /* This is true for all paletted codecs implemented in FFmpeg. */
598
                    if (st->codec->extradata_size && (st->codec->bits_per_coded_sample <= 8)) {
599
                        st->codec->palctrl = av_mallocz(sizeof(AVPaletteControl));
600
#if HAVE_BIGENDIAN
601
                        for (i = 0; i < FFMIN(st->codec->extradata_size, AVPALETTE_SIZE)/4; i++)
602
                            st->codec->palctrl->palette[i] = av_bswap32(((uint32_t*)st->codec->extradata)[i]);
603
#else
604 605
                        memcpy(st->codec->palctrl->palette, st->codec->extradata,
                               FFMIN(st->codec->extradata_size, AVPALETTE_SIZE));
606
#endif
607
                        st->codec->palctrl->palette_changed = 1;
608 609
                    }

Fabrice Bellard's avatar
Fabrice Bellard committed
610 611 612
#ifdef DEBUG
                    print_tag("video", tag1, 0);
#endif
613
                    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
614
                    st->codec->codec_tag = tag1;
615
                    st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, tag1);
Diego Biurrun's avatar
Diego Biurrun committed
616
                    st->need_parsing = AVSTREAM_PARSE_HEADERS; // This is needed to get the pict type which is necessary for generating correct pts.
617 618 619 620 621
                    // Support "Resolution 1:1" for Avid AVI Codec
                    if(tag1 == MKTAG('A', 'V', 'R', 'n') &&
                       st->codec->extradata_size >= 31 &&
                       !memcmp(&st->codec->extradata[28], "1:1", 3))
                        st->codec->codec_id = CODEC_ID_RAWVIDEO;
622 623 624 625 626 627 628 629 630

                    if(st->codec->codec_tag==0 && st->codec->height > 0 && st->codec->extradata_size < 1U<<30){
                        st->codec->extradata_size+= 9;
                        st->codec->extradata= av_realloc(st->codec->extradata, st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
                        if(st->codec->extradata)
                            memcpy(st->codec->extradata + st->codec->extradata_size - 9, "BottomUp", 9);
                    }
                    st->codec->height= FFABS(st->codec->height);

631
//                    url_fskip(pb, size - 5 * 4);
Fabrice Bellard's avatar
Fabrice Bellard committed
632
                    break;
633
                case AVMEDIA_TYPE_AUDIO:
634
                    ff_get_wav_header(pb, st->codec, size);
635
                    ast->dshow_block_align= st->codec->block_align;
636
                    if(ast->sample_size && st->codec->block_align && ast->sample_size != st->codec->block_align){
637
                        av_log(s, AV_LOG_WARNING, "sample size (%d) != block align (%d)\n", ast->sample_size, st->codec->block_align);
638 639
                        ast->sample_size= st->codec->block_align;
                    }
640
                    if (size&1) /* 2-aligned (fix for Stargate SG-1 - 3x18 - Shades of Grey.avi) */
641
                        url_fskip(pb, 1);
Diego Biurrun's avatar
Diego Biurrun committed
642
                    /* Force parsing as several audio frames can be in
Diego Biurrun's avatar
Diego Biurrun committed
643
                     * one packet and timestamps refer to packet start. */
644
                    st->need_parsing = AVSTREAM_PARSE_TIMESTAMPS;
Diego Biurrun's avatar
Diego Biurrun committed
645 646 647
                    /* ADTS header is in extradata, AAC without header must be
                     * stored as exact frames. Parser not needed and it will
                     * fail. */
648
                    if (st->codec->codec_id == CODEC_ID_AAC && st->codec->extradata_size)
649
                        st->need_parsing = AVSTREAM_PARSE_NONE;
650 651
                    /* AVI files with Xan DPCM audio (wrongly) declare PCM
                     * audio in the header but have Axan as stream_code_tag. */
652
                    if (st->codec->stream_codec_tag == AV_RL32("Axan")){
653 654 655
                        st->codec->codec_id  = CODEC_ID_XAN_DPCM;
                        st->codec->codec_tag = 0;
                    }
656
                    if (amv_file_format){
657
                        st->codec->codec_id  = CODEC_ID_ADPCM_IMA_AMV;
658 659
                        ast->dshow_block_align = 0;
                    }
Fabrice Bellard's avatar
Fabrice Bellard committed
660
                    break;
661 662 663 664
                case AVMEDIA_TYPE_SUBTITLE:
                    st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
                    st->codec->codec_id   = CODEC_ID_PROBE;
                    break;
Fabrice Bellard's avatar
Fabrice Bellard committed
665
                default:
666
                    st->codec->codec_type = AVMEDIA_TYPE_DATA;
667 668
                    st->codec->codec_id= CODEC_ID_NONE;
                    st->codec->codec_tag= 0;
Fabrice Bellard's avatar
Fabrice Bellard committed
669 670 671 672 673
                    url_fskip(pb, size);
                    break;
                }
            }
            break;
674 675
        case MKTAG('i', 'n', 'd', 'x'):
            i= url_ftell(pb);
676
            if(!url_is_streamed(pb) && !(s->flags & AVFMT_FLAG_IGNIDX)){
677 678
                read_braindead_odml_indx(s, 0);
            }
679 680
            url_fseek(pb, i+size, SEEK_SET);
            break;
681 682 683 684 685 686 687 688 689 690 691 692
        case MKTAG('v', 'p', 'r', 'p'):
            if(stream_index < (unsigned)s->nb_streams && size > 9*4){
                AVRational active, active_aspect;

                st = s->streams[stream_index];
                get_le32(pb);
                get_le32(pb);
                get_le32(pb);
                get_le32(pb);
                get_le32(pb);

                active_aspect.den= get_le16(pb);
Michael Niedermayer's avatar
Michael Niedermayer committed
693
                active_aspect.num= get_le16(pb);
694 695 696 697 698
                active.num       = get_le32(pb);
                active.den       = get_le32(pb);
                get_le32(pb); //nbFieldsPerFrame

                if(active_aspect.num && active_aspect.den && active.num && active.den){
699
                    st->sample_aspect_ratio= av_div_q(active_aspect, active);
700 701 702 703 704 705
//av_log(s, AV_LOG_ERROR, "vprp %d/%d %d/%d\n", active_aspect.num, active_aspect.den, active.num, active.den);
                }
                size -= 9*4;
            }
            url_fseek(pb, size, SEEK_CUR);
            break;
706 707
        case MKTAG('s', 't', 'r', 'n'):
            if(s->nb_streams){
708
                avi_read_tag(s, s->streams[s->nb_streams-1], tag, size);
709 710
                break;
            }
Fabrice Bellard's avatar
Fabrice Bellard committed
711
        default:
712
            if(size > 1000000){
Diego Biurrun's avatar
Diego Biurrun committed
713 714
                av_log(s, AV_LOG_ERROR, "Something went wrong during header parsing, "
                                        "I will ignore it and try to continue anyway.\n");
715 716 717 718
                avi->movi_list = url_ftell(pb) - 4;
                avi->movi_end  = url_fsize(pb);
                goto end_of_header;
            }
Fabrice Bellard's avatar
Fabrice Bellard committed
719 720 721 722 723 724 725 726 727 728 729 730
            /* skip tag */
            size += (size & 1);
            url_fskip(pb, size);
            break;
        }
    }
 end_of_header:
    /* check stream number */
    if (stream_index != s->nb_streams - 1) {
    fail:
        return -1;
    }
731

732
    if(!avi->index_loaded && !url_is_streamed(pb))
733
        avi_load_index(s);
734
    avi->index_loaded = 1;
735
    avi->non_interleaved |= guess_ni_flag(s);
736 737 738 739 740 741 742 743 744 745
    for(i=0; i<s->nb_streams; i++){
        AVStream *st = s->streams[i];
        if(st->nb_index_entries)
            break;
    }
    if(i==s->nb_streams && avi->non_interleaved) {
        av_log(s, AV_LOG_WARNING, "non-interleaved AVI without index, switching to interleaved\n");
        avi->non_interleaved=0;
    }

746
    if(avi->non_interleaved) {
Diego Biurrun's avatar
Diego Biurrun committed
747
        av_log(s, AV_LOG_INFO, "non-interleaved AVI\n");
748
        clean_index(s);
749
    }
750

751 752
    ff_metadata_conv_ctx(s, NULL, ff_avi_metadata_conv);

Fabrice Bellard's avatar
Fabrice Bellard committed
753 754 755
    return 0;
}

756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818
static int read_gab2_sub(AVStream *st, AVPacket *pkt) {
    if (!strcmp(pkt->data, "GAB2") && AV_RL16(pkt->data+5) == 2) {
        uint8_t desc[256], *d = desc;
        uint8_t *end, *ptr = pkt->data+7;
        unsigned int size, desc_len = bytestream_get_le32(&ptr);
        int score = AVPROBE_SCORE_MAX / 2;
        AVIStream *ast = st->priv_data;
        AVInputFormat *sub_demuxer;
        AVRational time_base;
        ByteIOContext *pb;
        AVProbeData pd;

        if (desc_len > FFMAX(pkt->size-17, 0))
            return 0;

        end = ptr + desc_len;
        while (ptr < end-1) {
            uint8_t tmp;
            uint32_t ch;
            GET_UTF16(ch, ptr < end-1 ? bytestream_get_le16(&ptr) : 0, break;);
            PUT_UTF8(ch, tmp, if(d-desc < sizeof(desc)-1)  *d++ = tmp;);
        }
        *d = 0;
        if (*desc)
            av_metadata_set2(&st->metadata, "title", desc, 0);

        ptr = end + 2;
        size = bytestream_get_le32(&ptr);
        size = FFMIN(size, pkt->size+pkt->data-ptr);

        pd = (AVProbeData) { .buf = ptr, .buf_size = size };
        if (!(sub_demuxer = av_probe_input_format2(&pd, 1, &score)))
            return 0;

        pb = av_alloc_put_byte(ptr, size, 0, NULL, NULL, NULL, NULL);
        if (!av_open_input_stream(&ast->sub_ctx, pb, "", sub_demuxer, NULL)) {
            av_read_packet(ast->sub_ctx, &ast->sub_pkt);
            *st->codec = *ast->sub_ctx->streams[0]->codec;
            ast->sub_ctx->streams[0]->codec->extradata = NULL;
            time_base = ast->sub_ctx->streams[0]->time_base;
            av_set_pts_info(st, 64, time_base.num, time_base.den);
        }
        ast->sub_buffer = pkt->data;
        memset(pkt, 0, sizeof(*pkt));
        return 1;
    }
    return 0;
}

static AVStream *get_subtitle_pkt(AVFormatContext *s, AVStream *next_st,
                                  AVPacket *pkt)
{
    AVIStream *ast, *next_ast = next_st->priv_data;
    int64_t ts, next_ts, ts_min = INT64_MAX;
    AVStream *st, *sub_st = NULL;
    int i;

    next_ts = av_rescale_q(next_ast->frame_offset, next_st->time_base,
                           AV_TIME_BASE_Q);

    for (i=0; i<s->nb_streams; i++) {
        st  = s->streams[i];
        ast = st->priv_data;
819
        if (st->discard < AVDISCARD_ALL && ast && ast->sub_pkt.data) {
820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837
            ts = av_rescale_q(ast->sub_pkt.dts, st->time_base, AV_TIME_BASE_Q);
            if (ts <= next_ts && ts < ts_min) {
                ts_min = ts;
                sub_st = st;
            }
        }
    }

    if (sub_st) {
        ast = sub_st->priv_data;
        *pkt = ast->sub_pkt;
        pkt->stream_index = sub_st->index;
        if (av_read_packet(ast->sub_ctx, &ast->sub_pkt) < 0)
            ast->sub_pkt.data = NULL;
    }
    return sub_st;
}

838 839 840 841 842 843 844 845 846
static int get_stream_idx(int *d){
    if(    d[0] >= '0' && d[0] <= '9'
        && d[1] >= '0' && d[1] <= '9'){
        return (d[0] - '0') * 10 + (d[1] - '0');
    }else{
        return 100; //invalid stream ID
    }
}

847
static int avi_read_packet(AVFormatContext *s, AVPacket *pkt)
Fabrice Bellard's avatar
Fabrice Bellard committed
848 849
{
    AVIContext *avi = s->priv_data;
850
    ByteIOContext *pb = s->pb;
851 852
    int n, d[8];
    unsigned int size;
853
    int64_t i, sync;
854
    void* dstr;
855

856
    if (CONFIG_DV_DEMUXER && avi->dv_demux) {
857
        int size = dv_get_packet(avi->dv_demux, pkt);
858 859
        if (size >= 0)
            return size;
860
    }
861

862
    if(avi->non_interleaved){
863
        int best_stream_index = 0;
864 865 866 867
        AVStream *best_st= NULL;
        AVIStream *best_ast;
        int64_t best_ts= INT64_MAX;
        int i;
868

869 870 871 872
        for(i=0; i<s->nb_streams; i++){
            AVStream *st = s->streams[i];
            AVIStream *ast = st->priv_data;
            int64_t ts= ast->frame_offset;
873
            int64_t last_ts;
874

875 876 877
            if(!st->nb_index_entries)
                continue;

878 879 880 881
            last_ts = st->index_entries[st->nb_index_entries - 1].timestamp;
            if(!ast->remaining && ts > last_ts)
                continue;

882
            ts = av_rescale_q(ts, st->time_base, (AVRational){FFMAX(1, ast->sample_size), AV_TIME_BASE});
883

884
//            av_log(s, AV_LOG_DEBUG, "%"PRId64" %d/%d %"PRId64"\n", ts, st->time_base.num, st->time_base.den, ast->frame_offset);
885
            if(ts < best_ts){
886 887 888 889 890
                best_ts= ts;
                best_st= st;
                best_stream_index= i;
            }
        }
891 892 893
        if(!best_st)
            return -1;

894
        best_ast = best_st->priv_data;
895
        best_ts = av_rescale_q(best_ts, (AVRational){FFMAX(1, best_ast->sample_size), AV_TIME_BASE}, best_st->time_base);
896 897
        if(best_ast->remaining)
            i= av_index_search_timestamp(best_st, best_ts, AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD);
898
        else{
899
            i= av_index_search_timestamp(best_st, best_ts, AVSEEK_FLAG_ANY);
900
            if(i>=0)
901
                best_ast->frame_offset= best_st->index_entries[i].timestamp;
902
        }
903

904
//        av_log(s, AV_LOG_DEBUG, "%d\n", i);
905 906
        if(i>=0){
            int64_t pos= best_st->index_entries[i].pos;
907
            pos += best_ast->packet_size - best_ast->remaining;
908
            url_fseek(s->pb, pos + 8, SEEK_SET);
909
//        av_log(s, AV_LOG_DEBUG, "pos=%"PRId64"\n", pos);
910

911 912
            assert(best_ast->remaining <= best_ast->packet_size);

913 914
            avi->stream_index= best_stream_index;
            if(!best_ast->remaining)
915
                best_ast->packet_size=
916
                best_ast->remaining= best_st->index_entries[i].size;
917 918
        }
    }
919

920
resync:
921 922 923
    if(avi->stream_index >= 0){
        AVStream *st= s->streams[ avi->stream_index ];
        AVIStream *ast= st->priv_data;
924
        int size, err;
925

926 927 928
        if(get_subtitle_pkt(s, st, pkt))
            return 0;

929
        if(ast->sample_size <= 1) // minorityreport.AVI block_align=1024 sample_size=1 IMA-ADPCM
930
            size= INT_MAX;
931
        else if(ast->sample_size < 32)
932 933
            // arbitrary multiplier to avoid tiny packets for raw PCM data
            size= 1024*ast->sample_size;
934 935 936 937 938
        else
            size= ast->sample_size;

        if(size > ast->remaining)
            size= ast->remaining;
939
        avi->last_pkt_pos= url_ftell(pb);
940 941 942
        err= av_get_packet(pb, pkt, size);
        if(err<0)
            return err;
943

944
        if(ast->has_pal && pkt->data && pkt->size<(unsigned)INT_MAX/2){
945 946
            void *ptr= av_realloc(pkt->data, pkt->size + 4*256 + FF_INPUT_BUFFER_PADDING_SIZE);
            if(ptr){
947 948
            ast->has_pal=0;
            pkt->size += 4*256;
949
            pkt->data= ptr;
950
                memcpy(pkt->data + pkt->size - 4*256, ast->pal, 4*256);
951 952
            }else
                av_log(s, AV_LOG_ERROR, "Failed to append palette\n");
953 954
        }

955
        if (CONFIG_DV_DEMUXER && avi->dv_demux) {
956 957 958 959
            dstr = pkt->destruct;
            size = dv_produce_packet(avi->dv_demux, pkt,
                                    pkt->data, pkt->size);
            pkt->destruct = dstr;
960
            pkt->flags |= AV_PKT_FLAG_KEY;
961 962
            if (size < 0)
                av_free_packet(pkt);
963 964 965 966 967 968
        } else if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE
                   && !st->codec->codec_tag && read_gab2_sub(st, pkt)) {
            ast->frame_offset++;
            avi->stream_index = -1;
            ast->remaining = 0;
            goto resync;
969
        } else {
Diego Biurrun's avatar
Diego Biurrun committed
970
            /* XXX: How to handle B-frames in AVI? */
971 972 973 974
            pkt->dts = ast->frame_offset;
//                pkt->dts += ast->start;
            if(ast->sample_size)
                pkt->dts /= ast->sample_size;
975
//av_log(s, AV_LOG_DEBUG, "dts:%"PRId64" offset:%"PRId64" %d/%d smpl_siz:%d base:%d st:%d size:%d\n", pkt->dts, ast->frame_offset, ast->scale, ast->rate, ast->sample_size, AV_TIME_BASE, avi->stream_index, size);
976 977
            pkt->stream_index = avi->stream_index;

978
            if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
Michael Niedermayer's avatar
Michael Niedermayer committed
979 980
                AVIndexEntry *e;
                int index;
981
                assert(st->index_entries);
982

983
                index= av_index_search_timestamp(st, ast->frame_offset, 0);
Michael Niedermayer's avatar
Michael Niedermayer committed
984
                e= &st->index_entries[index];
985

Michael Niedermayer's avatar
Michael Niedermayer committed
986 987
                if(index >= 0 && e->timestamp == ast->frame_offset){
                    if (e->flags & AVINDEX_KEYFRAME)
988
                        pkt->flags |= AV_PKT_FLAG_KEY;
Michael Niedermayer's avatar
Michael Niedermayer committed
989
                }
990
            } else {
991
                pkt->flags |= AV_PKT_FLAG_KEY;
992
            }
993
            ast->frame_offset += get_duration(ast, pkt->size);
994 995 996 997 998 999 1000 1001 1002 1003
        }
        ast->remaining -= size;
        if(!ast->remaining){
            avi->stream_index= -1;
            ast->packet_size= 0;
        }

        return size;
    }

1004 1005
    memset(d, -1, sizeof(int)*8);
    for(i=sync=url_ftell(pb); !url_feof(pb); i++) {
1006
        int j;
1007

1008 1009 1010
        for(j=0; j<7; j++)
            d[j]= d[j+1];
        d[7]= get_byte(pb);
1011

1012
        size= d[4] + (d[5]<<8) + (d[6]<<16) + (d[7]<<24);
1013

1014
        n= get_stream_idx(d+2);
1015
//av_log(s, AV_LOG_DEBUG, "%X %X %X %X %X %X %X %X %"PRId64" %d %d\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], i, size, n);
1016
        if(i + (uint64_t)size > avi->fsize || d[0]<0)
1017
            continue;
1018

1019 1020
        //parse ix##
        if(  (d[0] == 'i' && d[1] == 'x' && n < s->nb_streams)
1021
        //parse JUNK
1022 1023
           ||(d[0] == 'J' && d[1] == 'U' && d[2] == 'N' && d[3] == 'K')
           ||(d[0] == 'i' && d[1] == 'd' && d[2] == 'x' && d[3] == '1')){
1024
            url_fskip(pb, size);
1025
//av_log(s, AV_LOG_DEBUG, "SKIP\n");
1026
            goto resync;
1027
        }
1028

1029 1030 1031 1032 1033 1034
        //parse stray LIST
        if(d[0] == 'L' && d[1] == 'I' && d[2] == 'S' && d[3] == 'T'){
            url_fskip(pb, 4);
            goto resync;
        }

1035
        n= get_stream_idx(d);
1036

1037 1038 1039
        if(!((i-avi->last_pkt_pos)&1) && get_stream_idx(d+1) < s->nb_streams)
            continue;

1040 1041 1042 1043 1044 1045
        //detect ##ix chunk and skip
        if(d[2] == 'i' && d[3] == 'x' && n < s->nb_streams){
            url_fskip(pb, size);
            goto resync;
        }

1046
        //parse ##dc/##wb
1047
        if(n < s->nb_streams){
Michael Niedermayer's avatar
Michael Niedermayer committed
1048 1049 1050 1051
            AVStream *st;
            AVIStream *ast;
            st = s->streams[n];
            ast = st->priv_data;
1052

1053 1054 1055
            if(s->nb_streams>=2){
                AVStream *st1  = s->streams[1];
                AVIStream *ast1= st1->priv_data;
Michael Niedermayer's avatar
Michael Niedermayer committed
1056 1057 1058
                //workaround for broken small-file-bug402.avi
                if(   d[2] == 'w' && d[3] == 'b'
                   && n==0
1059 1060
                   && st ->codec->codec_type == AVMEDIA_TYPE_VIDEO
                   && st1->codec->codec_type == AVMEDIA_TYPE_AUDIO
Michael Niedermayer's avatar
Michael Niedermayer committed
1061 1062 1063 1064 1065 1066
                   && ast->prefix == 'd'*256+'c'
                   && (d[2]*256+d[3] == ast1->prefix || !ast1->prefix_count)
                  ){
                    n=1;
                    st = st1;
                    ast = ast1;
Diego Biurrun's avatar
Diego Biurrun committed
1067
                    av_log(s, AV_LOG_WARNING, "Invalid stream + prefix combination, assuming audio.\n");
Michael Niedermayer's avatar
Michael Niedermayer committed
1068
                }
1069
            }
1070 1071


Michael Niedermayer's avatar
Michael Niedermayer committed
1072
            if(   (st->discard >= AVDISCARD_DEFAULT && size==0)
1073
               /*|| (st->discard >= AVDISCARD_NONKEY && !(pkt->flags & AV_PKT_FLAG_KEY))*/ //FIXME needs a little reordering
Michael Niedermayer's avatar
Michael Niedermayer committed
1074
               || st->discard >= AVDISCARD_ALL){
1075
                ast->frame_offset += get_duration(ast, size);
1076 1077
                url_fskip(pb, size);
                goto resync;
Michael Niedermayer's avatar
Michael Niedermayer committed
1078
            }
1079

Michael Niedermayer's avatar
Michael Niedermayer committed
1080
            if (d[2] == 'p' && d[3] == 'c' && size<=4*256+4) {
1081 1082 1083 1084 1085 1086 1087 1088 1089
                int k = get_byte(pb);
                int last = (k + get_byte(pb) - 1) & 0xFF;

                get_le16(pb); //flags

                for (; k <= last; k++)
                    ast->pal[k] = get_be32(pb)>>8;// b + (g << 8) + (r << 16);
                ast->has_pal= 1;
                goto resync;
Michael Niedermayer's avatar
Michael Niedermayer committed
1090 1091 1092 1093
            } else if(   ((ast->prefix_count<5 || sync+9 > i) && d[2]<128 && d[3]<128) ||
                         d[2]*256+d[3] == ast->prefix /*||
                         (d[2] == 'd' && d[3] == 'c') ||
                         (d[2] == 'w' && d[3] == 'b')*/) {
1094

1095
//av_log(s, AV_LOG_DEBUG, "OK\n");
Michael Niedermayer's avatar
Michael Niedermayer committed
1096 1097 1098 1099 1100 1101
                if(d[2]*256+d[3] == ast->prefix)
                    ast->prefix_count++;
                else{
                    ast->prefix= d[2]*256+d[3];
                    ast->prefix_count= 0;
                }
1102

Michael Niedermayer's avatar
Michael Niedermayer committed
1103 1104 1105
                avi->stream_index= n;
                ast->packet_size= size + 8;
                ast->remaining= size;
1106

1107
                if(size || !ast->sample_size){
Michael Niedermayer's avatar
Michael Niedermayer committed
1108 1109
                    uint64_t pos= url_ftell(pb) - 8;
                    if(!st->index_entries || !st->nb_index_entries || st->index_entries[st->nb_index_entries - 1].pos < pos){
1110
                        av_add_index_entry(st, pos, ast->frame_offset, size, 0, AVINDEX_KEYFRAME);
Michael Niedermayer's avatar
Michael Niedermayer committed
1111
                    }
1112
                }
Michael Niedermayer's avatar
Michael Niedermayer committed
1113
                goto resync;
1114
            }
1115 1116
        }
    }
1117

1118
    return AVERROR_EOF;
Fabrice Bellard's avatar
Fabrice Bellard committed
1119 1120
}

Diego Biurrun's avatar
Diego Biurrun committed
1121 1122
/* XXX: We make the implicit supposition that the positions are sorted
   for each stream. */
Fabrice Bellard's avatar
Fabrice Bellard committed
1123 1124
static int avi_read_idx1(AVFormatContext *s, int size)
{
1125
    AVIContext *avi = s->priv_data;
1126
    ByteIOContext *pb = s->pb;
Fabrice Bellard's avatar
Fabrice Bellard committed
1127 1128 1129 1130
    int nb_index_entries, i;
    AVStream *st;
    AVIStream *ast;
    unsigned int index, tag, flags, pos, len;
1131
    unsigned last_pos= -1;
1132

Fabrice Bellard's avatar
Fabrice Bellard committed
1133 1134 1135 1136
    nb_index_entries = size / 16;
    if (nb_index_entries <= 0)
        return -1;

Diego Biurrun's avatar
Diego Biurrun committed
1137
    /* Read the entries and sort them in each stream component. */
Fabrice Bellard's avatar
Fabrice Bellard committed
1138 1139 1140 1141 1142
    for(i = 0; i < nb_index_entries; i++) {
        tag = get_le32(pb);
        flags = get_le32(pb);
        pos = get_le32(pb);
        len = get_le32(pb);
1143
#if defined(DEBUG_SEEK)
1144
        av_log(s, AV_LOG_DEBUG, "%d: tag=0x%x flags=0x%x pos=0x%x len=%d/",
Fabrice Bellard's avatar
Fabrice Bellard committed
1145 1146
               i, tag, flags, pos, len);
#endif
1147 1148
        if(i==0 && pos > avi->movi_list)
            avi->movi_list= 0; //FIXME better check
1149
        pos += avi->movi_list;
1150

Fabrice Bellard's avatar
Fabrice Bellard committed
1151 1152 1153 1154 1155 1156
        index = ((tag & 0xff) - '0') * 10;
        index += ((tag >> 8) & 0xff) - '0';
        if (index >= s->nb_streams)
            continue;
        st = s->streams[index];
        ast = st->priv_data;
1157

1158
#if defined(DEBUG_SEEK)
1159
        av_log(s, AV_LOG_DEBUG, "%d cum_len=%"PRId64"\n", len, ast->cum_len);
1160
#endif
1161 1162 1163
        if(url_feof(pb))
            return -1;

1164 1165
        if(last_pos == pos)
            avi->non_interleaved= 1;
1166
        else if(len || !ast->sample_size)
1167
            av_add_index_entry(st, pos, ast->cum_len, len, 0, (flags&AVIIF_INDEX) ? AVINDEX_KEYFRAME : 0);
1168
        ast->cum_len += get_duration(ast, len);
1169
        last_pos= pos;
Fabrice Bellard's avatar
Fabrice Bellard committed
1170 1171 1172 1173
    }
    return 0;
}

1174 1175 1176 1177
static int guess_ni_flag(AVFormatContext *s){
    int i;
    int64_t last_start=0;
    int64_t first_end= INT64_MAX;
1178
    int64_t oldpos= url_ftell(s->pb);
1179

1180 1181 1182
    for(i=0; i<s->nb_streams; i++){
        AVStream *st = s->streams[i];
        int n= st->nb_index_entries;
1183
        unsigned int size;
1184 1185 1186 1187

        if(n <= 0)
            continue;

1188 1189 1190 1191 1192 1193 1194 1195
        if(n >= 2){
            int64_t pos= st->index_entries[0].pos;
            url_fseek(s->pb, pos + 4, SEEK_SET);
            size= get_le32(s->pb);
            if(pos + size > st->index_entries[1].pos)
                last_start= INT64_MAX;
        }

1196 1197 1198 1199 1200
        if(st->index_entries[0].pos > last_start)
            last_start= st->index_entries[0].pos;
        if(st->index_entries[n-1].pos < first_end)
            first_end= st->index_entries[n-1].pos;
    }
1201
    url_fseek(s->pb, oldpos, SEEK_SET);
1202 1203 1204
    return last_start > first_end;
}

Fabrice Bellard's avatar
Fabrice Bellard committed
1205 1206 1207
static int avi_load_index(AVFormatContext *s)
{
    AVIContext *avi = s->priv_data;
1208
    ByteIOContext *pb = s->pb;
Fabrice Bellard's avatar
Fabrice Bellard committed
1209
    uint32_t tag, size;
1210
    int64_t pos= url_ftell(pb);
1211
    int ret = -1;
1212

1213 1214
    if (url_fseek(pb, avi->movi_end, SEEK_SET) < 0)
        goto the_end; // maybe truncated file
Fabrice Bellard's avatar
Fabrice Bellard committed
1215
#ifdef DEBUG_SEEK
1216
    printf("movi_end=0x%"PRIx64"\n", avi->movi_end);
Fabrice Bellard's avatar
Fabrice Bellard committed
1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234
#endif
    for(;;) {
        if (url_feof(pb))
            break;
        tag = get_le32(pb);
        size = get_le32(pb);
#ifdef DEBUG_SEEK
        printf("tag=%c%c%c%c size=0x%x\n",
               tag & 0xff,
               (tag >> 8) & 0xff,
               (tag >> 16) & 0xff,
               (tag >> 24) & 0xff,
               size);
#endif
        switch(tag) {
        case MKTAG('i', 'd', 'x', '1'):
            if (avi_read_idx1(s, size) < 0)
                goto skip;
1235
            ret = 0;
Fabrice Bellard's avatar
Fabrice Bellard committed
1236 1237 1238 1239 1240
                goto the_end;
            break;
        default:
        skip:
            size += (size & 1);
1241 1242
            if (url_fseek(pb, size, SEEK_CUR) < 0)
                goto the_end; // something is wrong here
Fabrice Bellard's avatar
Fabrice Bellard committed
1243 1244 1245 1246
            break;
        }
    }
 the_end:
1247
    url_fseek(pb, pos, SEEK_SET);
1248
    return ret;
Fabrice Bellard's avatar
Fabrice Bellard committed
1249 1250
}

1251 1252 1253 1254 1255 1256 1257 1258 1259 1260
static void seek_subtitle(AVStream *st, AVStream *st2, int64_t timestamp)
{
    AVIStream *ast2 = st2->priv_data;
    int64_t ts2 = av_rescale_q(timestamp, st->time_base, st2->time_base);
    av_free_packet(&ast2->sub_pkt);
    if (avformat_seek_file(ast2->sub_ctx, 0, INT64_MIN, ts2, ts2, 0) >= 0 ||
        avformat_seek_file(ast2->sub_ctx, 0, ts2, ts2, INT64_MAX, 0) >= 0)
        av_read_packet(ast2->sub_ctx, &ast2->sub_pkt);
}

1261
static int avi_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
Fabrice Bellard's avatar
Fabrice Bellard committed
1262 1263 1264
{
    AVIContext *avi = s->priv_data;
    AVStream *st;
1265
    int i, index;
Fabrice Bellard's avatar
Fabrice Bellard committed
1266
    int64_t pos;
1267
    AVIStream *ast;
Fabrice Bellard's avatar
Fabrice Bellard committed
1268 1269 1270 1271 1272 1273

    if (!avi->index_loaded) {
        /* we only load the index on demand */
        avi_load_index(s);
        avi->index_loaded = 1;
    }
1274
    assert(stream_index>= 0);
Fabrice Bellard's avatar
Fabrice Bellard committed
1275 1276

    st = s->streams[stream_index];
1277 1278
    ast= st->priv_data;
    index= av_index_search_timestamp(st, timestamp * FFMAX(ast->sample_size, 1), flags);
1279
    if(index<0)
Fabrice Bellard's avatar
Fabrice Bellard committed
1280
        return -1;
1281

Fabrice Bellard's avatar
Fabrice Bellard committed
1282
    /* find the position */
1283
    pos = st->index_entries[index].pos;
1284
    timestamp = st->index_entries[index].timestamp / FFMAX(ast->sample_size, 1);
1285

1286
//    av_log(s, AV_LOG_DEBUG, "XX %"PRId64" %d %"PRId64"\n", timestamp, index, st->index_entries[index].timestamp);
Fabrice Bellard's avatar
Fabrice Bellard committed
1287

1288
    if (CONFIG_DV_DEMUXER && avi->dv_demux) {
1289
        /* One and only one real stream for DV in AVI, and it has video  */
1290
        /* offsets. Calling with other stream indexes should have failed */
1291 1292 1293 1294
        /* the av_index_search_timestamp call above.                     */
        assert(stream_index == 0);

        /* Feed the DV video stream version of the timestamp to the */
Diego Biurrun's avatar
Diego Biurrun committed
1295
        /* DV demux so it can synthesize correct timestamps.        */
1296 1297
        dv_offset_reset(avi->dv_demux, timestamp);

1298
        url_fseek(s->pb, pos, SEEK_SET);
1299 1300 1301 1302
        avi->stream_index= -1;
        return 0;
    }

Fabrice Bellard's avatar
Fabrice Bellard committed
1303
    for(i = 0; i < s->nb_streams; i++) {
1304 1305
        AVStream *st2 = s->streams[i];
        AVIStream *ast2 = st2->priv_data;
1306 1307 1308 1309

        ast2->packet_size=
        ast2->remaining= 0;

1310 1311 1312 1313 1314
        if (ast2->sub_ctx) {
            seek_subtitle(st, st2, timestamp);
            continue;
        }

1315 1316
        if (st2->nb_index_entries <= 0)
            continue;
1317

1318
//        assert(st2->codec->block_align);
1319
        assert((int64_t)st2->time_base.num*ast2->rate == (int64_t)st2->time_base.den*ast2->scale);
1320
        index = av_index_search_timestamp(
1321
                st2,
1322
                av_rescale_q(timestamp, st->time_base, st2->time_base) * FFMAX(ast2->sample_size, 1),
1323 1324 1325
                flags | AVSEEK_FLAG_BACKWARD);
        if(index<0)
            index=0;
1326

1327 1328 1329 1330 1331 1332 1333
        if(!avi->non_interleaved){
            while(index>0 && st2->index_entries[index].pos > pos)
                index--;
            while(index+1 < st2->nb_index_entries && st2->index_entries[index].pos < pos)
                index++;
        }

1334
//        av_log(s, AV_LOG_DEBUG, "%"PRId64" %d %"PRId64"\n", timestamp, index, st2->index_entries[index].timestamp);
1335 1336
        /* extract the current frame number */
        ast2->frame_offset = st2->index_entries[index].timestamp;
Fabrice Bellard's avatar
Fabrice Bellard committed
1337
    }
1338

Fabrice Bellard's avatar
Fabrice Bellard committed
1339
    /* do the seek */
1340
    url_fseek(s->pb, pos, SEEK_SET);
1341
    avi->stream_index= -1;
Fabrice Bellard's avatar
Fabrice Bellard committed
1342 1343 1344
    return 0;
}

1345
static int avi_read_close(AVFormatContext *s)
Fabrice Bellard's avatar
Fabrice Bellard committed
1346
{
Michael Niedermayer's avatar
Michael Niedermayer committed
1347 1348 1349 1350 1351
    int i;
    AVIContext *avi = s->priv_data;

    for(i=0;i<s->nb_streams;i++) {
        AVStream *st = s->streams[i];
1352
        AVIStream *ast = st->priv_data;
1353
        av_free(st->codec->palctrl);
1354
        if (ast) {
1355 1356 1357 1358 1359 1360
            if (ast->sub_ctx) {
                av_freep(&ast->sub_ctx->pb);
                av_close_input_stream(ast->sub_ctx);
            }
            av_free(ast->sub_buffer);
            av_free_packet(&ast->sub_pkt);
1361
        }
Michael Niedermayer's avatar
Michael Niedermayer committed
1362 1363
    }

1364 1365 1366
    if (avi->dv_demux)
        av_free(avi->dv_demux);

Fabrice Bellard's avatar
Fabrice Bellard committed
1367 1368 1369 1370 1371
    return 0;
}

static int avi_probe(AVProbeData *p)
{
1372 1373
    int i;

Fabrice Bellard's avatar
Fabrice Bellard committed
1374
    /* check file header */
1375 1376 1377 1378 1379 1380
    for(i=0; avi_headers[i][0]; i++)
        if(!memcmp(p->buf  , avi_headers[i]  , 4) &&
           !memcmp(p->buf+8, avi_headers[i]+4, 4))
            return AVPROBE_SCORE_MAX;

    return 0;
Fabrice Bellard's avatar
Fabrice Bellard committed
1381 1382
}

1383
AVInputFormat avi_demuxer = {
Fabrice Bellard's avatar
Fabrice Bellard committed
1384
    "avi",
1385
    NULL_IF_CONFIG_SMALL("AVI format"),
Fabrice Bellard's avatar
Fabrice Bellard committed
1386 1387 1388 1389 1390
    sizeof(AVIContext),
    avi_probe,
    avi_read_header,
    avi_read_packet,
    avi_read_close,
Fabrice Bellard's avatar
Fabrice Bellard committed
1391
    avi_read_seek,
Fabrice Bellard's avatar
Fabrice Bellard committed
1392
};