use libavformats index system instead of the half duplicated mess in avidec.c
[ffmpeg.git] / libavformat / avidec.c
1 /*
2  * AVI decoder.
3  * Copyright (c) 2001 Fabrice Bellard.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
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
18  */
19 #include "avformat.h"
20 #include "avi.h"
21 #include "dv.h"
22
23 #undef NDEBUG
24 #include <assert.h>
25
26 //#define DEBUG
27 //#define DEBUG_SEEK
28
29 typedef struct AVIStream {
30     int frame_offset; /* current frame (video) or byte (audio) counter
31                          (used to compute the pts) */
32     int scale;
33     int rate;    
34     int sample_size; /* audio only data */
35     int start;
36     
37     int cum_len; /* temporary storage (used during seek) */
38     
39     int prefix;                       ///< normally 'd'<<8 + 'c' or 'w'<<8 + 'b'
40     int prefix_count;
41 } AVIStream;
42
43 typedef struct {
44     int64_t  riff_end;
45     int64_t  movi_end;
46     offset_t movi_list;
47     int index_loaded;
48     int is_odml;
49     DVDemuxContext* dv_demux;
50 } AVIContext;
51
52 static int avi_load_index(AVFormatContext *s);
53
54 #ifdef DEBUG
55 static void print_tag(const char *str, unsigned int tag, int size)
56 {
57     printf("%s: tag=%c%c%c%c size=0x%x\n",
58            str, tag & 0xff,
59            (tag >> 8) & 0xff,
60            (tag >> 16) & 0xff,
61            (tag >> 24) & 0xff,
62            size);
63 }
64 #endif
65
66 static int get_riff(AVIContext *avi, ByteIOContext *pb)
67 {
68     uint32_t tag; 
69     /* check RIFF header */
70     tag = get_le32(pb);
71
72     if (tag != MKTAG('R', 'I', 'F', 'F'))
73         return -1;
74     avi->riff_end = get_le32(pb);   /* RIFF chunk size */
75     avi->riff_end += url_ftell(pb); /* RIFF chunk end */
76     tag = get_le32(pb);
77     if (tag != MKTAG('A', 'V', 'I', ' ') && tag != MKTAG('A', 'V', 'I', 'X'))
78         return -1;
79     
80     return 0;
81 }
82
83 static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
84 {
85     AVIContext *avi = s->priv_data;
86     ByteIOContext *pb = &s->pb;
87     uint32_t tag, tag1, handler;
88     int codec_type, stream_index, frame_period, bit_rate, scale, rate;
89     unsigned int size, nb_frames;
90     int i, n;
91     AVStream *st;
92     AVIStream *ast;
93     int xan_video = 0;  /* hack to support Xan A/V */
94
95     if (get_riff(avi, pb) < 0)
96         return -1;
97
98     /* first list tag */
99     stream_index = -1;
100     codec_type = -1;
101     frame_period = 0;
102     for(;;) {
103         if (url_feof(pb))
104             goto fail;
105         tag = get_le32(pb);
106         size = get_le32(pb);
107 #ifdef DEBUG
108         print_tag("tag", tag, size);
109 #endif
110
111         switch(tag) {
112         case MKTAG('L', 'I', 'S', 'T'):
113             /* ignored, except when start of video packets */
114             tag1 = get_le32(pb);
115 #ifdef DEBUG
116             print_tag("list", tag1, 0);
117 #endif
118             if (tag1 == MKTAG('m', 'o', 'v', 'i')) {
119                 avi->movi_list = url_ftell(pb) - 4;
120                 if(size) avi->movi_end = avi->movi_list + size;
121                 else     avi->movi_end = url_filesize(url_fileno(pb));
122 #ifdef DEBUG
123                 printf("movi end=%Lx\n", avi->movi_end);
124 #endif
125                 goto end_of_header;
126             }
127             break;
128         case MKTAG('d', 'm', 'l', 'h'):
129             avi->is_odml = 1;
130             url_fskip(pb, size + (size & 1));
131             break;
132         case MKTAG('a', 'v', 'i', 'h'):
133             /* avi header */
134             /* using frame_period is bad idea */
135             frame_period = get_le32(pb);
136             bit_rate = get_le32(pb) * 8;
137             url_fskip(pb, 4 * 4);
138             n = get_le32(pb);
139             for(i=0;i<n;i++) {
140                 AVIStream *ast;
141                 st = av_new_stream(s, i);
142                 if (!st)
143                     goto fail;
144
145                 ast = av_mallocz(sizeof(AVIStream));
146                 if (!ast)
147                     goto fail;
148                 st->priv_data = ast;
149             }
150             url_fskip(pb, size - 7 * 4);
151             break;
152         case MKTAG('s', 't', 'r', 'h'):
153             /* stream header */
154             stream_index++;
155             tag1 = get_le32(pb);
156             handler = get_le32(pb); /* codec tag */
157 #ifdef DEBUG
158         print_tag("strh", tag1, -1);
159 #endif
160             switch(tag1) {
161             case MKTAG('i', 'a', 'v', 's'):
162             case MKTAG('i', 'v', 'a', 's'):
163                 /* 
164                  * After some consideration -- I don't think we 
165                  * have to support anything but DV in a type1 AVIs.
166                  */
167                 if (s->nb_streams != 1)
168                     goto fail;
169                 
170                 if (handler != MKTAG('d', 'v', 's', 'd') &&
171                     handler != MKTAG('d', 'v', 'h', 'd') &&
172                     handler != MKTAG('d', 'v', 's', 'l'))
173                    goto fail;
174                 
175                 ast = s->streams[0]->priv_data;
176                 av_freep(&s->streams[0]->codec.extradata);
177                 av_freep(&s->streams[0]);
178                 s->nb_streams = 0;
179                 avi->dv_demux = dv_init_demux(s);
180                 if (!avi->dv_demux)
181                     goto fail;
182                 s->streams[0]->priv_data = ast;
183                 url_fskip(pb, 3 * 4);
184                 ast->scale = get_le32(pb);
185                 ast->rate = get_le32(pb);
186                 stream_index = s->nb_streams - 1;
187                 url_fskip(pb, size - 7*4);
188                 break;
189             case MKTAG('v', 'i', 'd', 's'):
190                 codec_type = CODEC_TYPE_VIDEO;
191
192                 if (stream_index >= s->nb_streams) {
193                     url_fskip(pb, size - 8);
194                     break;
195                 } 
196
197                 st = s->streams[stream_index];
198                 ast = st->priv_data;
199                 st->codec.stream_codec_tag= handler;
200                 
201                 get_le32(pb); /* flags */
202                 get_le16(pb); /* priority */
203                 get_le16(pb); /* language */
204                 get_le32(pb); /* XXX: initial frame ? */
205                 scale = get_le32(pb); /* scale */
206                 rate = get_le32(pb); /* rate */
207
208                 if(scale && rate){
209                 }else if(frame_period){
210                     rate = 1000000;
211                     scale = frame_period;
212                 }else{
213                     rate = 25;
214                     scale = 1;
215                 }
216                 ast->rate = rate;
217                 ast->scale = scale;
218                 av_set_pts_info(st, 64, scale, rate);
219                 st->codec.frame_rate = rate;
220                 st->codec.frame_rate_base = scale;
221                 get_le32(pb); /* start */
222                 nb_frames = get_le32(pb);
223                 st->start_time = 0;
224                 st->duration = av_rescale(nb_frames,
225                     st->codec.frame_rate_base * (int64_t)AV_TIME_BASE,
226                     st->codec.frame_rate);
227                 url_fskip(pb, size - 9 * 4);
228                 break;
229             case MKTAG('a', 'u', 'd', 's'):
230                 {
231                     unsigned int length;
232
233                     codec_type = CODEC_TYPE_AUDIO;
234
235                     if (stream_index >= s->nb_streams) {
236                         url_fskip(pb, size - 8);
237                         break;
238                     } 
239                     st = s->streams[stream_index];
240                     ast = st->priv_data;
241                     
242                     get_le32(pb); /* flags */
243                     get_le16(pb); /* priority */
244                     get_le16(pb); /* language */
245                     get_le32(pb); /* initial frame */
246                     ast->scale = get_le32(pb); /* scale */
247                     ast->rate = get_le32(pb);
248                     if(!ast->rate)
249                         ast->rate= 1; //wrong but better then 1/0
250                     if(!ast->scale)
251                         ast->scale= 1; //wrong but better then 1/0
252                     av_set_pts_info(st, 64, ast->scale, ast->rate);
253                     ast->start= get_le32(pb); /* start */
254                     length = get_le32(pb); /* length, in samples or bytes */
255                     get_le32(pb); /* buffer size */
256                     get_le32(pb); /* quality */
257                     ast->sample_size = get_le32(pb); /* sample ssize */
258 //av_log(NULL, AV_LOG_DEBUG, "%d %d %d %d\n", ast->scale, ast->rate, ast->sample_size, ast->start);
259                     st->start_time = 0;
260                     st->duration = av_rescale(length, ast->scale*(int64_t)AV_TIME_BASE, ast->rate);
261                     url_fskip(pb, size - 12 * 4);
262                 }
263                 break;
264             case MKTAG('t', 'x', 't', 's'):
265                 //FIXME 
266                 codec_type = CODEC_TYPE_DATA; //CODEC_TYPE_SUB ?  FIXME
267                 url_fskip(pb, size - 8);
268                 break;
269             case MKTAG('p', 'a', 'd', 's'):
270                 codec_type = CODEC_TYPE_UNKNOWN;
271                 url_fskip(pb, size - 8);
272                 stream_index--;
273                 break;
274             default:
275                 av_log(s, AV_LOG_ERROR, "unknown stream type %X\n", tag1);
276                 goto fail;
277             }
278             break;
279         case MKTAG('s', 't', 'r', 'f'):
280             /* stream header */
281             if (stream_index >= s->nb_streams || avi->dv_demux) {
282                 url_fskip(pb, size);
283             } else {
284                 st = s->streams[stream_index];
285                 switch(codec_type) {
286                 case CODEC_TYPE_VIDEO:
287                     get_le32(pb); /* size */
288                     st->codec.width = get_le32(pb);
289                     st->codec.height = get_le32(pb);
290                     get_le16(pb); /* panes */
291                     st->codec.bits_per_sample= get_le16(pb); /* depth */
292                     tag1 = get_le32(pb);
293                     get_le32(pb); /* ImageSize */
294                     get_le32(pb); /* XPelsPerMeter */
295                     get_le32(pb); /* YPelsPerMeter */
296                     get_le32(pb); /* ClrUsed */
297                     get_le32(pb); /* ClrImportant */
298
299                  if(size > 10*4 && size<(1<<30)){
300                     st->codec.extradata_size= size - 10*4;
301                     st->codec.extradata= av_malloc(st->codec.extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
302                     get_buffer(pb, st->codec.extradata, st->codec.extradata_size);
303                  }
304                     
305                     if(st->codec.extradata_size & 1) //FIXME check if the encoder really did this correctly
306                         get_byte(pb);
307
308                     /* Extract palette from extradata if bpp <= 8 */
309                     /* This code assumes that extradata contains only palette */
310                     /* This is true for all paletted codecs implemented in ffmpeg */
311                     if (st->codec.extradata_size && (st->codec.bits_per_sample <= 8)) {
312                         st->codec.palctrl = av_mallocz(sizeof(AVPaletteControl));
313 #ifdef WORDS_BIGENDIAN
314                         for (i = 0; i < FFMIN(st->codec.extradata_size, AVPALETTE_SIZE)/4; i++)
315                             st->codec.palctrl->palette[i] = bswap_32(((uint32_t*)st->codec.extradata)[i]);
316 #else
317                         memcpy(st->codec.palctrl->palette, st->codec.extradata,
318                                FFMIN(st->codec.extradata_size, AVPALETTE_SIZE));
319 #endif
320                         st->codec.palctrl->palette_changed = 1;
321                     }
322
323 #ifdef DEBUG
324                     print_tag("video", tag1, 0);
325 #endif
326                     st->codec.codec_type = CODEC_TYPE_VIDEO;
327                     st->codec.codec_tag = tag1;
328                     st->codec.codec_id = codec_get_id(codec_bmp_tags, tag1);
329                     if (st->codec.codec_id == CODEC_ID_XAN_WC4)
330                         xan_video = 1;
331 //                    url_fskip(pb, size - 5 * 4);
332                     break;
333                 case CODEC_TYPE_AUDIO:
334                     get_wav_header(pb, &st->codec, size);
335                     if (size%2) /* 2-aligned (fix for Stargate SG-1 - 3x18 - Shades of Grey.avi) */
336                         url_fskip(pb, 1);
337                     /* special case time: To support Xan DPCM, hardcode
338                      * the format if Xxan is the video codec */
339                     st->need_parsing = 1;
340                     /* force parsing as several audio frames can be in
341                        one packet */
342                     if (xan_video)
343                         st->codec.codec_id = CODEC_ID_XAN_DPCM;
344                     break;
345                 default:
346                     st->codec.codec_type = CODEC_TYPE_DATA;
347                     st->codec.codec_id= CODEC_ID_NONE;
348                     st->codec.codec_tag= 0;
349                     url_fskip(pb, size);
350                     break;
351                 }
352             }
353             break;
354         default:
355             /* skip tag */
356             size += (size & 1);
357             url_fskip(pb, size);
358             break;
359         }
360     }
361  end_of_header:
362     /* check stream number */
363     if (stream_index != s->nb_streams - 1) {
364     fail:
365         for(i=0;i<s->nb_streams;i++) {
366             av_freep(&s->streams[i]->codec.extradata);
367             av_freep(&s->streams[i]);
368         }
369         return -1;
370     }
371
372     assert(!avi->index_loaded);
373     avi_load_index(s);
374     avi->index_loaded = 1;
375  
376     return 0;
377 }
378
379 static int avi_read_packet(AVFormatContext *s, AVPacket *pkt)
380 {
381     AVIContext *avi = s->priv_data;
382     ByteIOContext *pb = &s->pb;
383     int n, d[8], size;
384     offset_t i, sync;
385     void* dstr;
386    
387     if (avi->dv_demux) {
388         size = dv_get_packet(avi->dv_demux, pkt);
389         if (size >= 0)
390             return size;
391     }
392
393 resync:
394     memset(d, -1, sizeof(int)*8);
395     for(i=sync=url_ftell(pb); !url_feof(pb); i++) {
396         int j;
397
398         if (i >= avi->movi_end) {
399             if (avi->is_odml) {
400                 url_fskip(pb, avi->riff_end - i);
401                 avi->riff_end = avi->movi_end = url_filesize(url_fileno(pb));
402             } else
403                 break;
404         }
405
406         for(j=0; j<7; j++)
407             d[j]= d[j+1];
408         d[7]= get_byte(pb);
409         
410         size= d[4] + (d[5]<<8) + (d[6]<<16) + (d[7]<<24);
411         
412         if(    d[2] >= '0' && d[2] <= '9'
413             && d[3] >= '0' && d[3] <= '9'){
414             n= (d[2] - '0') * 10 + (d[3] - '0');
415         }else{
416             n= 100; //invalid stream id
417         }
418 //av_log(NULL, AV_LOG_DEBUG, "%X %X %X %X %X %X %X %X %lld %d %d\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], i, size, n);
419         if(i + size > avi->movi_end || d[0]<0)
420             continue;
421         
422         //parse ix##
423         if(  (d[0] == 'i' && d[1] == 'x' && n < s->nb_streams)
424         //parse JUNK
425            ||(d[0] == 'J' && d[1] == 'U' && d[2] == 'N' && d[3] == 'K')){
426             url_fskip(pb, size);
427 //av_log(NULL, AV_LOG_DEBUG, "SKIP\n");
428             goto resync;
429         }
430
431         if(    d[0] >= '0' && d[0] <= '9'
432             && d[1] >= '0' && d[1] <= '9'){
433             n= (d[0] - '0') * 10 + (d[1] - '0');
434         }else{
435             n= 100; //invalid stream id
436         }
437         
438         //parse ##dc/##wb
439         if(n < s->nb_streams){
440           AVStream *st;
441           AVIStream *ast;
442           st = s->streams[n];
443           ast = st->priv_data;
444           
445           if(st->discard){
446                 url_fskip(pb, size);
447                 goto resync;
448           }
449
450           if(   ((ast->prefix_count<5 || sync+9 > i) && d[2]<128 && d[3]<128) || 
451                 d[2]*256+d[3] == ast->prefix /*||
452                 (d[2] == 'd' && d[3] == 'c') || 
453                 (d[2] == 'w' && d[3] == 'b')*/) {
454
455 //av_log(NULL, AV_LOG_DEBUG, "OK\n");
456             if(d[2]*256+d[3] == ast->prefix)
457                 ast->prefix_count++;
458             else{
459                 ast->prefix= d[2]*256+d[3];
460                 ast->prefix_count= 0;
461             }
462
463             av_new_packet(pkt, size);
464             get_buffer(pb, pkt->data, size);
465             if (size & 1) {
466                 get_byte(pb);
467                 size++;
468             }
469         
470             if (avi->dv_demux) {
471                 dstr = pkt->destruct;
472                 size = dv_produce_packet(avi->dv_demux, pkt,
473                                          pkt->data, pkt->size);
474                 pkt->destruct = dstr;
475                 pkt->flags |= PKT_FLAG_KEY;
476             } else {
477                 /* XXX: how to handle B frames in avi ? */
478                 pkt->dts = ast->frame_offset;
479 //                pkt->dts += ast->start;
480                 if(ast->sample_size)
481                     pkt->dts /= ast->sample_size;
482 //av_log(NULL, AV_LOG_DEBUG, "dts:%Ld offset:%d %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, n, size);
483                 pkt->stream_index = n;
484
485                 if (st->codec.codec_type == CODEC_TYPE_VIDEO) {
486                     if(st->index_entries){
487                         AVIndexEntry *e;
488                         int index;
489
490                         index= av_index_search_timestamp(st, pkt->dts, 0);
491                         e= &st->index_entries[index];
492                         
493                         if(e->timestamp == ast->frame_offset){
494                             if (e->flags & AVINDEX_KEYFRAME)
495                                 pkt->flags |= PKT_FLAG_KEY;
496                         }
497                     } else {
498                         /* if no index, better to say that all frames
499                            are key frames */
500                         pkt->flags |= PKT_FLAG_KEY;
501                     }
502                 } else {
503                     pkt->flags |= PKT_FLAG_KEY; 
504                 }
505                 if(ast->sample_size)
506                     ast->frame_offset += pkt->size;
507                 else
508                     ast->frame_offset++;
509             }
510             return size;
511           }
512         }
513         /* palette changed chunk */
514         if (   d[0] >= '0' && d[0] <= '9'
515             && d[1] >= '0' && d[1] <= '9'
516             && ((d[2] == 'p' && d[3] == 'c'))
517             && n < s->nb_streams && i + size <= avi->movi_end) {
518
519             AVStream *st;
520             int first, clr, flags, k, p;
521
522             st = s->streams[n];
523
524             first = get_byte(pb);
525             clr = get_byte(pb);
526             if(!clr) /* all 256 colors used */
527                 clr = 256;
528             flags = get_le16(pb);
529             p = 4;
530             for (k = first; k < clr + first; k++) {
531                 int r, g, b;
532                 r = get_byte(pb);
533                 g = get_byte(pb);
534                 b = get_byte(pb);
535                     get_byte(pb);
536                 st->codec.palctrl->palette[k] = b + (g << 8) + (r << 16);
537             }
538             st->codec.palctrl->palette_changed = 1;
539             goto resync;
540         }
541
542     }
543
544     return -1;
545 }
546
547 /* XXX: we make the implicit supposition that the position are sorted
548    for each stream */
549 static int avi_read_idx1(AVFormatContext *s, int size)
550 {
551     ByteIOContext *pb = &s->pb;
552     int nb_index_entries, i;
553     AVStream *st;
554     AVIStream *ast;
555     unsigned int index, tag, flags, pos, len;
556     
557     nb_index_entries = size / 16;
558     if (nb_index_entries <= 0)
559         return -1;
560
561     /* read the entries and sort them in each stream component */
562     for(i = 0; i < nb_index_entries; i++) {
563         tag = get_le32(pb);
564         flags = get_le32(pb);
565         pos = get_le32(pb);
566         len = get_le32(pb);
567 #if defined(DEBUG_SEEK)
568         av_log(NULL, AV_LOG_DEBUG, "%d: tag=0x%x flags=0x%x pos=0x%x len=%d/", 
569                i, tag, flags, pos, len);
570 #endif
571         index = ((tag & 0xff) - '0') * 10;
572         index += ((tag >> 8) & 0xff) - '0';
573         if (index >= s->nb_streams)
574             continue;
575         st = s->streams[index];
576         ast = st->priv_data;
577         
578         if(ast->sample_size)
579             len /= ast->sample_size;
580         else
581             len = 1;
582 #if defined(DEBUG_SEEK)
583         av_log(NULL, AV_LOG_DEBUG, "%d cum_len=%d\n", len, ast->cum_len);
584 #endif
585         av_add_index_entry(st, pos, ast->cum_len, 0, (flags&AVIIF_INDEX) ? AVINDEX_KEYFRAME : 0);
586         ast->cum_len += len;
587     }
588     return 0;
589 }
590
591 static int avi_load_index(AVFormatContext *s)
592 {
593     AVIContext *avi = s->priv_data;
594     ByteIOContext *pb = &s->pb;
595     uint32_t tag, size;
596     offset_t pos= url_ftell(pb);
597     
598     url_fseek(pb, avi->movi_end, SEEK_SET);
599 #ifdef DEBUG_SEEK
600     printf("movi_end=0x%llx\n", avi->movi_end);
601 #endif
602     for(;;) {
603         if (url_feof(pb))
604             break;
605         tag = get_le32(pb);
606         size = get_le32(pb);
607 #ifdef DEBUG_SEEK
608         printf("tag=%c%c%c%c size=0x%x\n",
609                tag & 0xff,
610                (tag >> 8) & 0xff,
611                (tag >> 16) & 0xff,
612                (tag >> 24) & 0xff,
613                size);
614 #endif
615         switch(tag) {
616         case MKTAG('i', 'd', 'x', '1'):
617             if (avi_read_idx1(s, size) < 0)
618                 goto skip;
619             else
620                 goto the_end;
621             break;
622         default:
623         skip:
624             size += (size & 1);
625             url_fskip(pb, size);
626             break;
627         }
628     }
629  the_end:
630     url_fseek(pb, pos, SEEK_SET);
631     return 0;
632 }
633
634 static int avi_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
635 {
636     AVIContext *avi = s->priv_data;
637     AVStream *st;
638     int i, index;
639     int64_t pos;
640
641     if (!avi->index_loaded) {
642         /* we only load the index on demand */
643         avi_load_index(s);
644         avi->index_loaded = 1;
645     }
646     assert(stream_index>= 0);
647
648     st = s->streams[stream_index];
649     index= av_index_search_timestamp(st, timestamp, flags);
650     if(index<0)
651         return -1;
652     
653     /* find the position */
654     pos = st->index_entries[index].pos;
655     timestamp = st->index_entries[index].timestamp;
656
657 //    av_log(NULL, AV_LOG_DEBUG, "XX %Ld %d %Ld\n", timestamp, index, st->index_entries[index].timestamp);
658
659     for(i = 0; i < s->nb_streams; i++) {
660         AVStream *st2 = s->streams[i];
661         AVIStream *ast2 = st2->priv_data;
662         if (st2->nb_index_entries <= 0)
663             continue;
664         
665 //        assert(st2->codec.block_align);
666         assert(st2->time_base.den == ast2->rate);
667         assert(st2->time_base.num == ast2->scale);
668         index = av_index_search_timestamp(
669                 st2, 
670                 av_rescale(timestamp, st2->time_base.den*(int64_t)st->time_base.num, st->time_base.den * (int64_t)st2->time_base.num),
671                 flags | AVSEEK_FLAG_BACKWARD);
672         if(index<0)
673             index=0;
674 #if 1
675         while(index>0 && st2->index_entries[index].pos > pos)
676             index--;
677         while(index+1 < st2->nb_index_entries && st2->index_entries[index].pos < pos)
678             index++;
679 #endif
680 //        av_log(NULL, AV_LOG_DEBUG, "%Ld %d %Ld\n", timestamp, index, st2->index_entries[index].timestamp);
681         /* extract the current frame number */
682         ast2->frame_offset = st2->index_entries[index].timestamp;
683         if(ast2->sample_size)
684             ast2->frame_offset *=ast2->sample_size;
685     }
686
687     if (avi->dv_demux)
688         dv_flush_audio_packets(avi->dv_demux);
689     /* do the seek */
690     pos += avi->movi_list;
691     url_fseek(&s->pb, pos, SEEK_SET);
692     return 0;
693 }
694
695 static int avi_read_close(AVFormatContext *s)
696 {
697     int i;
698     AVIContext *avi = s->priv_data;
699
700     for(i=0;i<s->nb_streams;i++) {
701         AVStream *st = s->streams[i];
702         AVIStream *ast = st->priv_data;
703         av_free(ast);
704         av_free(st->codec.extradata);
705         av_free(st->codec.palctrl);
706     }
707
708     if (avi->dv_demux)
709         av_free(avi->dv_demux);
710
711     return 0;
712 }
713
714 static int avi_probe(AVProbeData *p)
715 {
716     /* check file header */
717     if (p->buf_size <= 32)
718         return 0;
719     if (p->buf[0] == 'R' && p->buf[1] == 'I' &&
720         p->buf[2] == 'F' && p->buf[3] == 'F' &&
721         p->buf[8] == 'A' && p->buf[9] == 'V' &&
722         p->buf[10] == 'I' && p->buf[11] == ' ')
723         return AVPROBE_SCORE_MAX;
724     else
725         return 0;
726 }
727
728 static AVInputFormat avi_iformat = {
729     "avi",
730     "avi format",
731     sizeof(AVIContext),
732     avi_probe,
733     avi_read_header,
734     avi_read_packet,
735     avi_read_close,
736     avi_read_seek,
737 };
738
739 int avidec_init(void)
740 {
741     av_register_input_format(&avi_iformat);
742     return 0;
743 }