00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "libavutil/intreadwrite.h"
00023 #include "libavutil/bswap.h"
00024 #include "avformat.h"
00025 #include "avi.h"
00026 #include "dv.h"
00027 #include "riff.h"
00028
00029 #undef NDEBUG
00030 #include <assert.h>
00031
00032
00033
00034
00035 typedef struct AVIStream {
00036 int64_t frame_offset;
00037
00038 int remaining;
00039 int packet_size;
00040
00041 int scale;
00042 int rate;
00043 int sample_size;
00044
00045 int64_t cum_len;
00046
00047 int prefix;
00048 int prefix_count;
00049 uint32_t pal[256];
00050 int has_pal;
00051 } AVIStream;
00052
00053 typedef struct {
00054 int64_t riff_end;
00055 int64_t movi_end;
00056 int64_t fsize;
00057 int64_t movi_list;
00058 int64_t last_pkt_pos;
00059 int index_loaded;
00060 int is_odml;
00061 int non_interleaved;
00062 int stream_index;
00063 DVDemuxContext* dv_demux;
00064 } AVIContext;
00065
00066 static const char avi_headers[][8] = {
00067 { 'R', 'I', 'F', 'F', 'A', 'V', 'I', ' ' },
00068 { 'R', 'I', 'F', 'F', 'A', 'V', 'I', 'X' },
00069 { 'R', 'I', 'F', 'F', 'A', 'V', 'I', 0x19},
00070 { 'O', 'N', '2', ' ', 'O', 'N', '2', 'f' },
00071 { 'R', 'I', 'F', 'F', 'A', 'M', 'V', ' ' },
00072 { 0 }
00073 };
00074
00075 static int avi_load_index(AVFormatContext *s);
00076 static int guess_ni_flag(AVFormatContext *s);
00077
00078 #ifdef DEBUG
00079 static void print_tag(const char *str, unsigned int tag, int size)
00080 {
00081 printf("%s: tag=%c%c%c%c size=0x%x\n",
00082 str, tag & 0xff,
00083 (tag >> 8) & 0xff,
00084 (tag >> 16) & 0xff,
00085 (tag >> 24) & 0xff,
00086 size);
00087 }
00088 #endif
00089
00090 static int get_riff(AVFormatContext *s, ByteIOContext *pb)
00091 {
00092 AVIContext *avi = s->priv_data;
00093 char header[8];
00094 int i;
00095
00096
00097 get_buffer(pb, header, 4);
00098 avi->riff_end = get_le32(pb);
00099 avi->riff_end += url_ftell(pb);
00100 get_buffer(pb, header+4, 4);
00101
00102 for(i=0; avi_headers[i][0]; i++)
00103 if(!memcmp(header, avi_headers[i], 8))
00104 break;
00105 if(!avi_headers[i][0])
00106 return -1;
00107
00108 if(header[7] == 0x19)
00109 av_log(s, AV_LOG_INFO, "This file has been generated by a totally broken muxer.\n");
00110
00111 return 0;
00112 }
00113
00114 static int read_braindead_odml_indx(AVFormatContext *s, int frame_num){
00115 AVIContext *avi = s->priv_data;
00116 ByteIOContext *pb = s->pb;
00117 int longs_pre_entry= get_le16(pb);
00118 int index_sub_type = get_byte(pb);
00119 int index_type = get_byte(pb);
00120 int entries_in_use = get_le32(pb);
00121 int chunk_id = get_le32(pb);
00122 int64_t base = get_le64(pb);
00123 int stream_id= 10*((chunk_id&0xFF) - '0') + (((chunk_id>>8)&0xFF) - '0');
00124 AVStream *st;
00125 AVIStream *ast;
00126 int i;
00127 int64_t last_pos= -1;
00128 int64_t filesize= url_fsize(s->pb);
00129
00130 #ifdef DEBUG_SEEK
00131 av_log(s, AV_LOG_ERROR, "longs_pre_entry:%d index_type:%d entries_in_use:%d chunk_id:%X base:%16"PRIX64"\n",
00132 longs_pre_entry,index_type, entries_in_use, chunk_id, base);
00133 #endif
00134
00135 if(stream_id > s->nb_streams || stream_id < 0)
00136 return -1;
00137 st= s->streams[stream_id];
00138 ast = st->priv_data;
00139
00140 if(index_sub_type)
00141 return -1;
00142
00143 get_le32(pb);
00144
00145 if(index_type && longs_pre_entry != 2)
00146 return -1;
00147 if(index_type>1)
00148 return -1;
00149
00150 if(filesize > 0 && base >= filesize){
00151 av_log(s, AV_LOG_ERROR, "ODML index invalid\n");
00152 if(base>>32 == (base & 0xFFFFFFFF) && (base & 0xFFFFFFFF) < filesize && filesize <= 0xFFFFFFFF)
00153 base &= 0xFFFFFFFF;
00154 else
00155 return -1;
00156 }
00157
00158 for(i=0; i<entries_in_use; i++){
00159 if(index_type){
00160 int64_t pos= get_le32(pb) + base - 8;
00161 int len = get_le32(pb);
00162 int key= len >= 0;
00163 len &= 0x7FFFFFFF;
00164
00165 #ifdef DEBUG_SEEK
00166 av_log(s, AV_LOG_ERROR, "pos:%"PRId64", len:%X\n", pos, len);
00167 #endif
00168 if(url_feof(pb))
00169 return -1;
00170
00171 if(last_pos == pos || pos == base - 8)
00172 avi->non_interleaved= 1;
00173 if(last_pos != pos)
00174 av_add_index_entry(st, pos, ast->cum_len / FFMAX(1, ast->sample_size), len, 0, key ? AVINDEX_KEYFRAME : 0);
00175
00176 if(ast->sample_size)
00177 ast->cum_len += len;
00178 else
00179 ast->cum_len ++;
00180 last_pos= pos;
00181 }else{
00182 int64_t offset, pos;
00183 int duration;
00184 offset = get_le64(pb);
00185 get_le32(pb);
00186 duration = get_le32(pb);
00187
00188 if(url_feof(pb))
00189 return -1;
00190
00191 pos = url_ftell(pb);
00192
00193 url_fseek(pb, offset+8, SEEK_SET);
00194 read_braindead_odml_indx(s, frame_num);
00195 frame_num += duration;
00196
00197 url_fseek(pb, pos, SEEK_SET);
00198 }
00199 }
00200 avi->index_loaded=1;
00201 return 0;
00202 }
00203
00204 static void clean_index(AVFormatContext *s){
00205 int i;
00206 int64_t j;
00207
00208 for(i=0; i<s->nb_streams; i++){
00209 AVStream *st = s->streams[i];
00210 AVIStream *ast = st->priv_data;
00211 int n= st->nb_index_entries;
00212 int max= ast->sample_size;
00213 int64_t pos, size, ts;
00214
00215 if(n != 1 || ast->sample_size==0)
00216 continue;
00217
00218 while(max < 1024) max+=max;
00219
00220 pos= st->index_entries[0].pos;
00221 size= st->index_entries[0].size;
00222 ts= st->index_entries[0].timestamp;
00223
00224 for(j=0; j<size; j+=max){
00225 av_add_index_entry(st, pos+j, ts + j/ast->sample_size, FFMIN(max, size-j), 0, AVINDEX_KEYFRAME);
00226 }
00227 }
00228 }
00229
00230 static int avi_read_tag(AVFormatContext *s, const char *key, unsigned int size)
00231 {
00232 ByteIOContext *pb = s->pb;
00233 uint8_t value[1024];
00234
00235 int64_t i = url_ftell(pb);
00236 size += (size & 1);
00237 get_strz(pb, value, sizeof(value));
00238 url_fseek(pb, i+size, SEEK_SET);
00239
00240 return av_metadata_set(&s->metadata, key, value);
00241 }
00242
00243 static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
00244 {
00245 AVIContext *avi = s->priv_data;
00246 ByteIOContext *pb = s->pb;
00247 unsigned int tag, tag1, handler;
00248 int codec_type, stream_index, frame_period, bit_rate;
00249 unsigned int size, nb_frames;
00250 int i;
00251 AVStream *st;
00252 AVIStream *ast = NULL;
00253 int avih_width=0, avih_height=0;
00254 int amv_file_format=0;
00255
00256 avi->stream_index= -1;
00257
00258 if (get_riff(s, pb) < 0)
00259 return -1;
00260
00261 avi->fsize = url_fsize(pb);
00262 if(avi->fsize<=0)
00263 avi->fsize= avi->riff_end;
00264
00265
00266 stream_index = -1;
00267 codec_type = -1;
00268 frame_period = 0;
00269 for(;;) {
00270 if (url_feof(pb))
00271 goto fail;
00272 tag = get_le32(pb);
00273 size = get_le32(pb);
00274 #ifdef DEBUG
00275 print_tag("tag", tag, size);
00276 #endif
00277
00278 switch(tag) {
00279 case MKTAG('L', 'I', 'S', 'T'):
00280
00281 tag1 = get_le32(pb);
00282 #ifdef DEBUG
00283 print_tag("list", tag1, 0);
00284 #endif
00285 if (tag1 == MKTAG('m', 'o', 'v', 'i')) {
00286 avi->movi_list = url_ftell(pb) - 4;
00287 if(size) avi->movi_end = avi->movi_list + size + (size & 1);
00288 else avi->movi_end = url_fsize(pb);
00289 #ifdef DEBUG
00290 printf("movi end=%"PRIx64"\n", avi->movi_end);
00291 #endif
00292 goto end_of_header;
00293 }
00294 break;
00295 case MKTAG('d', 'm', 'l', 'h'):
00296 avi->is_odml = 1;
00297 url_fskip(pb, size + (size & 1));
00298 break;
00299 case MKTAG('a', 'm', 'v', 'h'):
00300 amv_file_format=1;
00301 case MKTAG('a', 'v', 'i', 'h'):
00302
00303
00304 frame_period = get_le32(pb);
00305 bit_rate = get_le32(pb) * 8;
00306 get_le32(pb);
00307 avi->non_interleaved |= get_le32(pb) & AVIF_MUSTUSEINDEX;
00308
00309 url_fskip(pb, 2 * 4);
00310 get_le32(pb);
00311 get_le32(pb);
00312 avih_width=get_le32(pb);
00313 avih_height=get_le32(pb);
00314
00315 url_fskip(pb, size - 10 * 4);
00316 break;
00317 case MKTAG('s', 't', 'r', 'h'):
00318
00319
00320 tag1 = get_le32(pb);
00321 handler = get_le32(pb);
00322
00323 if(tag1 == MKTAG('p', 'a', 'd', 's')){
00324 url_fskip(pb, size - 8);
00325 break;
00326 }else{
00327 stream_index++;
00328 st = av_new_stream(s, stream_index);
00329 if (!st)
00330 goto fail;
00331
00332 ast = av_mallocz(sizeof(AVIStream));
00333 if (!ast)
00334 goto fail;
00335 st->priv_data = ast;
00336 }
00337 if(amv_file_format)
00338 tag1 = stream_index ? MKTAG('a','u','d','s') : MKTAG('v','i','d','s');
00339
00340 #ifdef DEBUG
00341 print_tag("strh", tag1, -1);
00342 #endif
00343 if(tag1 == MKTAG('i', 'a', 'v', 's') || tag1 == MKTAG('i', 'v', 'a', 's')){
00344 int64_t dv_dur;
00345
00346
00347
00348
00349
00350 if (s->nb_streams != 1)
00351 goto fail;
00352
00353 if (handler != MKTAG('d', 'v', 's', 'd') &&
00354 handler != MKTAG('d', 'v', 'h', 'd') &&
00355 handler != MKTAG('d', 'v', 's', 'l'))
00356 goto fail;
00357
00358 ast = s->streams[0]->priv_data;
00359 av_freep(&s->streams[0]->codec->extradata);
00360 av_freep(&s->streams[0]);
00361 s->nb_streams = 0;
00362 if (CONFIG_DV_DEMUXER) {
00363 avi->dv_demux = dv_init_demux(s);
00364 if (!avi->dv_demux)
00365 goto fail;
00366 }
00367 s->streams[0]->priv_data = ast;
00368 url_fskip(pb, 3 * 4);
00369 ast->scale = get_le32(pb);
00370 ast->rate = get_le32(pb);
00371 url_fskip(pb, 4);
00372
00373 dv_dur = get_le32(pb);
00374 if (ast->scale > 0 && ast->rate > 0 && dv_dur > 0) {
00375 dv_dur *= AV_TIME_BASE;
00376 s->duration = av_rescale(dv_dur, ast->scale, ast->rate);
00377 }
00378
00379
00380
00381
00382
00383 stream_index = s->nb_streams - 1;
00384 url_fskip(pb, size - 9*4);
00385 break;
00386 }
00387
00388 assert(stream_index < s->nb_streams);
00389 st->codec->stream_codec_tag= handler;
00390
00391 get_le32(pb);
00392 get_le16(pb);
00393 get_le16(pb);
00394 get_le32(pb);
00395 ast->scale = get_le32(pb);
00396 ast->rate = get_le32(pb);
00397 if(!(ast->scale && ast->rate)){
00398 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);
00399 if(frame_period){
00400 ast->rate = 1000000;
00401 ast->scale = frame_period;
00402 }else{
00403 ast->rate = 25;
00404 ast->scale = 1;
00405 }
00406 }
00407 av_set_pts_info(st, 64, ast->scale, ast->rate);
00408
00409 ast->cum_len=get_le32(pb);
00410 nb_frames = get_le32(pb);
00411
00412 st->start_time = 0;
00413 st->duration = nb_frames;
00414 get_le32(pb);
00415 get_le32(pb);
00416 ast->sample_size = get_le32(pb);
00417 ast->cum_len *= FFMAX(1, ast->sample_size);
00418
00419
00420 switch(tag1) {
00421 case MKTAG('v', 'i', 'd', 's'):
00422 codec_type = CODEC_TYPE_VIDEO;
00423
00424 ast->sample_size = 0;
00425 break;
00426 case MKTAG('a', 'u', 'd', 's'):
00427 codec_type = CODEC_TYPE_AUDIO;
00428 break;
00429 case MKTAG('t', 'x', 't', 's'):
00430
00431 codec_type = CODEC_TYPE_DATA;
00432 break;
00433 case MKTAG('d', 'a', 't', 's'):
00434 codec_type = CODEC_TYPE_DATA;
00435 break;
00436 default:
00437 av_log(s, AV_LOG_ERROR, "unknown stream type %X\n", tag1);
00438 goto fail;
00439 }
00440 ast->frame_offset= ast->cum_len;
00441 url_fskip(pb, size - 12 * 4);
00442 break;
00443 case MKTAG('s', 't', 'r', 'f'):
00444
00445 if (stream_index >= (unsigned)s->nb_streams || avi->dv_demux) {
00446 url_fskip(pb, size);
00447 } else {
00448 st = s->streams[stream_index];
00449 switch(codec_type) {
00450 case CODEC_TYPE_VIDEO:
00451 if(amv_file_format){
00452 st->codec->width=avih_width;
00453 st->codec->height=avih_height;
00454 st->codec->codec_type = CODEC_TYPE_VIDEO;
00455 st->codec->codec_id = CODEC_ID_AMV;
00456 url_fskip(pb, size);
00457 break;
00458 }
00459 get_le32(pb);
00460 st->codec->width = get_le32(pb);
00461 st->codec->height = (int32_t)get_le32(pb);
00462 get_le16(pb);
00463 st->codec->bits_per_coded_sample= get_le16(pb);
00464 tag1 = get_le32(pb);
00465 get_le32(pb);
00466 get_le32(pb);
00467 get_le32(pb);
00468 get_le32(pb);
00469 get_le32(pb);
00470
00471 if (tag1 == MKTAG('D', 'X', 'S', 'B')) {
00472 st->codec->codec_type = CODEC_TYPE_SUBTITLE;
00473 st->codec->codec_tag = tag1;
00474 st->codec->codec_id = CODEC_ID_XSUB;
00475 break;
00476 }
00477
00478 if(size > 10*4 && size<(1<<30)){
00479 st->codec->extradata_size= size - 10*4;
00480 st->codec->extradata= av_malloc(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
00481 get_buffer(pb, st->codec->extradata, st->codec->extradata_size);
00482 }
00483
00484 if(st->codec->extradata_size & 1)
00485 get_byte(pb);
00486
00487
00488
00489
00490 if (st->codec->extradata_size && (st->codec->bits_per_coded_sample <= 8)) {
00491 st->codec->palctrl = av_mallocz(sizeof(AVPaletteControl));
00492 #ifdef WORDS_BIGENDIAN
00493 for (i = 0; i < FFMIN(st->codec->extradata_size, AVPALETTE_SIZE)/4; i++)
00494 st->codec->palctrl->palette[i] = bswap_32(((uint32_t*)st->codec->extradata)[i]);
00495 #else
00496 memcpy(st->codec->palctrl->palette, st->codec->extradata,
00497 FFMIN(st->codec->extradata_size, AVPALETTE_SIZE));
00498 #endif
00499 st->codec->palctrl->palette_changed = 1;
00500 }
00501
00502 #ifdef DEBUG
00503 print_tag("video", tag1, 0);
00504 #endif
00505 st->codec->codec_type = CODEC_TYPE_VIDEO;
00506 st->codec->codec_tag = tag1;
00507 st->codec->codec_id = codec_get_id(codec_bmp_tags, tag1);
00508 st->need_parsing = AVSTREAM_PARSE_HEADERS;
00509
00510 if(st->codec->codec_tag==0 && st->codec->height > 0 && st->codec->extradata_size < 1U<<30){
00511 st->codec->extradata_size+= 9;
00512 st->codec->extradata= av_realloc(st->codec->extradata, st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
00513 if(st->codec->extradata)
00514 memcpy(st->codec->extradata + st->codec->extradata_size - 9, "BottomUp", 9);
00515 }
00516 st->codec->height= FFABS(st->codec->height);
00517
00518
00519 break;
00520 case CODEC_TYPE_AUDIO:
00521 get_wav_header(pb, st->codec, size);
00522 if(ast->sample_size && st->codec->block_align && ast->sample_size != st->codec->block_align){
00523 av_log(s, AV_LOG_WARNING, "sample size (%d) != block align (%d)\n", ast->sample_size, st->codec->block_align);
00524 ast->sample_size= st->codec->block_align;
00525 }
00526 if (size%2)
00527 url_fskip(pb, 1);
00528
00529
00530 st->need_parsing = AVSTREAM_PARSE_TIMESTAMPS;
00531
00532
00533
00534 if (st->codec->codec_id == CODEC_ID_AAC && st->codec->extradata_size)
00535 st->need_parsing = AVSTREAM_PARSE_NONE;
00536
00537
00538 if (st->codec->stream_codec_tag == AV_RL32("Axan")){
00539 st->codec->codec_id = CODEC_ID_XAN_DPCM;
00540 st->codec->codec_tag = 0;
00541 }
00542 if (amv_file_format)
00543 st->codec->codec_id = CODEC_ID_ADPCM_IMA_AMV;
00544 break;
00545 default:
00546 st->codec->codec_type = CODEC_TYPE_DATA;
00547 st->codec->codec_id= CODEC_ID_NONE;
00548 st->codec->codec_tag= 0;
00549 url_fskip(pb, size);
00550 break;
00551 }
00552 }
00553 break;
00554 case MKTAG('i', 'n', 'd', 'x'):
00555 i= url_ftell(pb);
00556 if(!url_is_streamed(pb) && !(s->flags & AVFMT_FLAG_IGNIDX)){
00557 read_braindead_odml_indx(s, 0);
00558 }
00559 url_fseek(pb, i+size, SEEK_SET);
00560 break;
00561 case MKTAG('v', 'p', 'r', 'p'):
00562 if(stream_index < (unsigned)s->nb_streams && size > 9*4){
00563 AVRational active, active_aspect;
00564
00565 st = s->streams[stream_index];
00566 get_le32(pb);
00567 get_le32(pb);
00568 get_le32(pb);
00569 get_le32(pb);
00570 get_le32(pb);
00571
00572 active_aspect.den= get_le16(pb);
00573 active_aspect.num= get_le16(pb);
00574 active.num = get_le32(pb);
00575 active.den = get_le32(pb);
00576 get_le32(pb);
00577
00578 if(active_aspect.num && active_aspect.den && active.num && active.den){
00579 st->sample_aspect_ratio= av_div_q(active_aspect, active);
00580
00581 }
00582 size -= 9*4;
00583 }
00584 url_fseek(pb, size, SEEK_CUR);
00585 break;
00586 case MKTAG('I', 'N', 'A', 'M'):
00587 avi_read_tag(s, "Title", size);
00588 break;
00589 case MKTAG('I', 'A', 'R', 'T'):
00590 avi_read_tag(s, "Artist", size);
00591 break;
00592 case MKTAG('I', 'C', 'O', 'P'):
00593 avi_read_tag(s, "Copyright", size);
00594 break;
00595 case MKTAG('I', 'C', 'M', 'T'):
00596 avi_read_tag(s, "Comment", size);
00597 break;
00598 case MKTAG('I', 'G', 'N', 'R'):
00599 avi_read_tag(s, "Genre", size);
00600 break;
00601 case MKTAG('I', 'P', 'R', 'D'):
00602 avi_read_tag(s, "Album", size);
00603 break;
00604 case MKTAG('I', 'P', 'R', 'T'):
00605 avi_read_tag(s, "Track", size);
00606 break;
00607 default:
00608 if(size > 1000000){
00609 av_log(s, AV_LOG_ERROR, "Something went wrong during header parsing, "
00610 "I will ignore it and try to continue anyway.\n");
00611 avi->movi_list = url_ftell(pb) - 4;
00612 avi->movi_end = url_fsize(pb);
00613 goto end_of_header;
00614 }
00615
00616 size += (size & 1);
00617 url_fskip(pb, size);
00618 break;
00619 }
00620 }
00621 end_of_header:
00622
00623 if (stream_index != s->nb_streams - 1) {
00624 fail:
00625 return -1;
00626 }
00627
00628 if(!avi->index_loaded && !url_is_streamed(pb))
00629 avi_load_index(s);
00630 avi->index_loaded = 1;
00631 avi->non_interleaved |= guess_ni_flag(s);
00632 if(avi->non_interleaved) {
00633 av_log(s, AV_LOG_INFO, "non-interleaved AVI\n");
00634 clean_index(s);
00635 }
00636
00637 return 0;
00638 }
00639
00640 static int get_stream_idx(int *d){
00641 if( d[0] >= '0' && d[0] <= '9'
00642 && d[1] >= '0' && d[1] <= '9'){
00643 return (d[0] - '0') * 10 + (d[1] - '0');
00644 }else{
00645 return 100;
00646 }
00647 }
00648
00649 static int avi_read_packet(AVFormatContext *s, AVPacket *pkt)
00650 {
00651 AVIContext *avi = s->priv_data;
00652 ByteIOContext *pb = s->pb;
00653 int n, d[8];
00654 unsigned int size;
00655 int64_t i, sync;
00656 void* dstr;
00657
00658 if (CONFIG_DV_DEMUXER && avi->dv_demux) {
00659 int size = dv_get_packet(avi->dv_demux, pkt);
00660 if (size >= 0)
00661 return size;
00662 }
00663
00664 if(avi->non_interleaved){
00665 int best_stream_index = 0;
00666 AVStream *best_st= NULL;
00667 AVIStream *best_ast;
00668 int64_t best_ts= INT64_MAX;
00669 int i;
00670
00671 for(i=0; i<s->nb_streams; i++){
00672 AVStream *st = s->streams[i];
00673 AVIStream *ast = st->priv_data;
00674 int64_t ts= ast->frame_offset;
00675
00676 if(ast->sample_size)
00677 ts /= ast->sample_size;
00678 ts= av_rescale(ts, AV_TIME_BASE * (int64_t)st->time_base.num, st->time_base.den);
00679
00680
00681 if(ts < best_ts && st->nb_index_entries){
00682 best_ts= ts;
00683 best_st= st;
00684 best_stream_index= i;
00685 }
00686 }
00687 if(!best_st)
00688 return -1;
00689
00690 best_ast = best_st->priv_data;
00691 best_ts= av_rescale(best_ts, best_st->time_base.den, AV_TIME_BASE * (int64_t)best_st->time_base.num);
00692 if(best_ast->remaining)
00693 i= av_index_search_timestamp(best_st, best_ts, AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD);
00694 else{
00695 i= av_index_search_timestamp(best_st, best_ts, AVSEEK_FLAG_ANY);
00696 if(i>=0)
00697 best_ast->frame_offset= best_st->index_entries[i].timestamp
00698 * FFMAX(1, best_ast->sample_size);
00699 }
00700
00701
00702 if(i>=0){
00703 int64_t pos= best_st->index_entries[i].pos;
00704 pos += best_ast->packet_size - best_ast->remaining;
00705 url_fseek(s->pb, pos + 8, SEEK_SET);
00706
00707
00708 assert(best_ast->remaining <= best_ast->packet_size);
00709
00710 avi->stream_index= best_stream_index;
00711 if(!best_ast->remaining)
00712 best_ast->packet_size=
00713 best_ast->remaining= best_st->index_entries[i].size;
00714 }
00715 }
00716
00717 resync:
00718 if(avi->stream_index >= 0){
00719 AVStream *st= s->streams[ avi->stream_index ];
00720 AVIStream *ast= st->priv_data;
00721 int size, err;
00722
00723 if(ast->sample_size <= 1)
00724 size= INT_MAX;
00725 else if(ast->sample_size < 32)
00726 size= 64*ast->sample_size;
00727 else
00728 size= ast->sample_size;
00729
00730 if(size > ast->remaining)
00731 size= ast->remaining;
00732 avi->last_pkt_pos= url_ftell(pb);
00733 err= av_get_packet(pb, pkt, size);
00734 if(err<0)
00735 return err;
00736
00737 if(ast->has_pal && pkt->data && pkt->size<(unsigned)INT_MAX/2){
00738 void *ptr= av_realloc(pkt->data, pkt->size + 4*256 + FF_INPUT_BUFFER_PADDING_SIZE);
00739 if(ptr){
00740 ast->has_pal=0;
00741 pkt->size += 4*256;
00742 pkt->data= ptr;
00743 memcpy(pkt->data + pkt->size - 4*256, ast->pal, 4*256);
00744 }else
00745 av_log(s, AV_LOG_ERROR, "Failed to append palette\n");
00746 }
00747
00748 if (CONFIG_DV_DEMUXER && avi->dv_demux) {
00749 dstr = pkt->destruct;
00750 size = dv_produce_packet(avi->dv_demux, pkt,
00751 pkt->data, pkt->size);
00752 pkt->destruct = dstr;
00753 pkt->flags |= PKT_FLAG_KEY;
00754 } else {
00755
00756 pkt->dts = ast->frame_offset;
00757
00758 if(ast->sample_size)
00759 pkt->dts /= ast->sample_size;
00760
00761 pkt->stream_index = avi->stream_index;
00762
00763 if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
00764 AVIndexEntry *e;
00765 int index;
00766 assert(st->index_entries);
00767
00768 index= av_index_search_timestamp(st, pkt->dts, 0);
00769 e= &st->index_entries[index];
00770
00771 if(index >= 0 && e->timestamp == ast->frame_offset){
00772 if (e->flags & AVINDEX_KEYFRAME)
00773 pkt->flags |= PKT_FLAG_KEY;
00774 }
00775 } else {
00776 pkt->flags |= PKT_FLAG_KEY;
00777 }
00778 if(ast->sample_size)
00779 ast->frame_offset += pkt->size;
00780 else
00781 ast->frame_offset++;
00782 }
00783 ast->remaining -= size;
00784 if(!ast->remaining){
00785 avi->stream_index= -1;
00786 ast->packet_size= 0;
00787 }
00788
00789 return size;
00790 }
00791
00792 memset(d, -1, sizeof(int)*8);
00793 for(i=sync=url_ftell(pb); !url_feof(pb); i++) {
00794 int j;
00795
00796 for(j=0; j<7; j++)
00797 d[j]= d[j+1];
00798 d[7]= get_byte(pb);
00799
00800 size= d[4] + (d[5]<<8) + (d[6]<<16) + (d[7]<<24);
00801
00802 n= get_stream_idx(d+2);
00803
00804 if(i + (uint64_t)size > avi->fsize || d[0]<0)
00805 continue;
00806
00807
00808 if( (d[0] == 'i' && d[1] == 'x' && n < s->nb_streams)
00809
00810 ||(d[0] == 'J' && d[1] == 'U' && d[2] == 'N' && d[3] == 'K')
00811 ||(d[0] == 'i' && d[1] == 'd' && d[2] == 'x' && d[3] == '1')){
00812 url_fskip(pb, size);
00813
00814 goto resync;
00815 }
00816
00817 n= get_stream_idx(d);
00818
00819 if(!((i-avi->last_pkt_pos)&1) && get_stream_idx(d+1) < s->nb_streams)
00820 continue;
00821
00822
00823 if(n < s->nb_streams){
00824 AVStream *st;
00825 AVIStream *ast;
00826 st = s->streams[n];
00827 ast = st->priv_data;
00828
00829 if(s->nb_streams>=2){
00830 AVStream *st1 = s->streams[1];
00831 AVIStream *ast1= st1->priv_data;
00832
00833 if( d[2] == 'w' && d[3] == 'b'
00834 && n==0
00835 && st ->codec->codec_type == CODEC_TYPE_VIDEO
00836 && st1->codec->codec_type == CODEC_TYPE_AUDIO
00837 && ast->prefix == 'd'*256+'c'
00838 && (d[2]*256+d[3] == ast1->prefix || !ast1->prefix_count)
00839 ){
00840 n=1;
00841 st = st1;
00842 ast = ast1;
00843 av_log(s, AV_LOG_WARNING, "Invalid stream + prefix combination, assuming audio.\n");
00844 }
00845 }
00846
00847
00848 if( (st->discard >= AVDISCARD_DEFAULT && size==0)
00849
00850 || st->discard >= AVDISCARD_ALL){
00851 if(ast->sample_size) ast->frame_offset += pkt->size;
00852 else ast->frame_offset++;
00853 url_fskip(pb, size);
00854 goto resync;
00855 }
00856
00857 if (d[2] == 'p' && d[3] == 'c' && size<=4*256+4) {
00858 int k = get_byte(pb);
00859 int last = (k + get_byte(pb) - 1) & 0xFF;
00860
00861 get_le16(pb);
00862
00863 for (; k <= last; k++)
00864 ast->pal[k] = get_be32(pb)>>8;
00865 ast->has_pal= 1;
00866 goto resync;
00867 } else if( ((ast->prefix_count<5 || sync+9 > i) && d[2]<128 && d[3]<128) ||
00868 d[2]*256+d[3] == ast->prefix
00869
00870 ) {
00871
00872
00873 if(d[2]*256+d[3] == ast->prefix)
00874 ast->prefix_count++;
00875 else{
00876 ast->prefix= d[2]*256+d[3];
00877 ast->prefix_count= 0;
00878 }
00879
00880 avi->stream_index= n;
00881 ast->packet_size= size + 8;
00882 ast->remaining= size;
00883
00884 {
00885 uint64_t pos= url_ftell(pb) - 8;
00886 if(!st->index_entries || !st->nb_index_entries || st->index_entries[st->nb_index_entries - 1].pos < pos){
00887 av_add_index_entry(st, pos, ast->frame_offset / FFMAX(1, ast->sample_size), size, 0, AVINDEX_KEYFRAME);
00888 }
00889 }
00890 goto resync;
00891 }
00892 }
00893 }
00894
00895 return AVERROR_EOF;
00896 }
00897
00898
00899
00900 static int avi_read_idx1(AVFormatContext *s, int size)
00901 {
00902 AVIContext *avi = s->priv_data;
00903 ByteIOContext *pb = s->pb;
00904 int nb_index_entries, i;
00905 AVStream *st;
00906 AVIStream *ast;
00907 unsigned int index, tag, flags, pos, len;
00908 unsigned last_pos= -1;
00909
00910 nb_index_entries = size / 16;
00911 if (nb_index_entries <= 0)
00912 return -1;
00913
00914
00915 for(i = 0; i < nb_index_entries; i++) {
00916 tag = get_le32(pb);
00917 flags = get_le32(pb);
00918 pos = get_le32(pb);
00919 len = get_le32(pb);
00920 #if defined(DEBUG_SEEK)
00921 av_log(s, AV_LOG_DEBUG, "%d: tag=0x%x flags=0x%x pos=0x%x len=%d/",
00922 i, tag, flags, pos, len);
00923 #endif
00924 if(i==0 && pos > avi->movi_list)
00925 avi->movi_list= 0;
00926 pos += avi->movi_list;
00927
00928 index = ((tag & 0xff) - '0') * 10;
00929 index += ((tag >> 8) & 0xff) - '0';
00930 if (index >= s->nb_streams)
00931 continue;
00932 st = s->streams[index];
00933 ast = st->priv_data;
00934
00935 #if defined(DEBUG_SEEK)
00936 av_log(s, AV_LOG_DEBUG, "%d cum_len=%"PRId64"\n", len, ast->cum_len);
00937 #endif
00938 if(url_feof(pb))
00939 return -1;
00940
00941 if(last_pos == pos)
00942 avi->non_interleaved= 1;
00943 else
00944 av_add_index_entry(st, pos, ast->cum_len / FFMAX(1, ast->sample_size), len, 0, (flags&AVIIF_INDEX) ? AVINDEX_KEYFRAME : 0);
00945 if(ast->sample_size)
00946 ast->cum_len += len;
00947 else
00948 ast->cum_len ++;
00949 last_pos= pos;
00950 }
00951 return 0;
00952 }
00953
00954 static int guess_ni_flag(AVFormatContext *s){
00955 int i;
00956 int64_t last_start=0;
00957 int64_t first_end= INT64_MAX;
00958
00959 for(i=0; i<s->nb_streams; i++){
00960 AVStream *st = s->streams[i];
00961 int n= st->nb_index_entries;
00962
00963 if(n <= 0)
00964 continue;
00965
00966 if(st->index_entries[0].pos > last_start)
00967 last_start= st->index_entries[0].pos;
00968 if(st->index_entries[n-1].pos < first_end)
00969 first_end= st->index_entries[n-1].pos;
00970 }
00971 return last_start > first_end;
00972 }
00973
00974 static int avi_load_index(AVFormatContext *s)
00975 {
00976 AVIContext *avi = s->priv_data;
00977 ByteIOContext *pb = s->pb;
00978 uint32_t tag, size;
00979 int64_t pos= url_ftell(pb);
00980
00981 url_fseek(pb, avi->movi_end, SEEK_SET);
00982 #ifdef DEBUG_SEEK
00983 printf("movi_end=0x%"PRIx64"\n", avi->movi_end);
00984 #endif
00985 for(;;) {
00986 if (url_feof(pb))
00987 break;
00988 tag = get_le32(pb);
00989 size = get_le32(pb);
00990 #ifdef DEBUG_SEEK
00991 printf("tag=%c%c%c%c size=0x%x\n",
00992 tag & 0xff,
00993 (tag >> 8) & 0xff,
00994 (tag >> 16) & 0xff,
00995 (tag >> 24) & 0xff,
00996 size);
00997 #endif
00998 switch(tag) {
00999 case MKTAG('i', 'd', 'x', '1'):
01000 if (avi_read_idx1(s, size) < 0)
01001 goto skip;
01002 else
01003 goto the_end;
01004 break;
01005 default:
01006 skip:
01007 size += (size & 1);
01008 url_fskip(pb, size);
01009 break;
01010 }
01011 }
01012 the_end:
01013 url_fseek(pb, pos, SEEK_SET);
01014 return 0;
01015 }
01016
01017 static int avi_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
01018 {
01019 AVIContext *avi = s->priv_data;
01020 AVStream *st;
01021 int i, index;
01022 int64_t pos;
01023
01024 if (!avi->index_loaded) {
01025
01026 avi_load_index(s);
01027 avi->index_loaded = 1;
01028 }
01029 assert(stream_index>= 0);
01030
01031 st = s->streams[stream_index];
01032 index= av_index_search_timestamp(st, timestamp, flags);
01033 if(index<0)
01034 return -1;
01035
01036
01037 pos = st->index_entries[index].pos;
01038 timestamp = st->index_entries[index].timestamp;
01039
01040
01041
01042 if (CONFIG_DV_DEMUXER && avi->dv_demux) {
01043
01044
01045
01046 assert(stream_index == 0);
01047
01048
01049
01050 dv_offset_reset(avi->dv_demux, timestamp);
01051
01052 url_fseek(s->pb, pos, SEEK_SET);
01053 avi->stream_index= -1;
01054 return 0;
01055 }
01056
01057 for(i = 0; i < s->nb_streams; i++) {
01058 AVStream *st2 = s->streams[i];
01059 AVIStream *ast2 = st2->priv_data;
01060
01061 ast2->packet_size=
01062 ast2->remaining= 0;
01063
01064 if (st2->nb_index_entries <= 0)
01065 continue;
01066
01067
01068 assert((int64_t)st2->time_base.num*ast2->rate == (int64_t)st2->time_base.den*ast2->scale);
01069 index = av_index_search_timestamp(
01070 st2,
01071 av_rescale(timestamp, st2->time_base.den*(int64_t)st->time_base.num, st->time_base.den * (int64_t)st2->time_base.num),
01072 flags | AVSEEK_FLAG_BACKWARD);
01073 if(index<0)
01074 index=0;
01075
01076 if(!avi->non_interleaved){
01077 while(index>0 && st2->index_entries[index].pos > pos)
01078 index--;
01079 while(index+1 < st2->nb_index_entries && st2->index_entries[index].pos < pos)
01080 index++;
01081 }
01082
01083
01084
01085 ast2->frame_offset = st2->index_entries[index].timestamp;
01086 if(ast2->sample_size)
01087 ast2->frame_offset *=ast2->sample_size;
01088 }
01089
01090
01091 url_fseek(s->pb, pos, SEEK_SET);
01092 avi->stream_index= -1;
01093 return 0;
01094 }
01095
01096 static int avi_read_close(AVFormatContext *s)
01097 {
01098 int i;
01099 AVIContext *avi = s->priv_data;
01100
01101 for(i=0;i<s->nb_streams;i++) {
01102 AVStream *st = s->streams[i];
01103 av_free(st->codec->palctrl);
01104 }
01105
01106 if (avi->dv_demux)
01107 av_free(avi->dv_demux);
01108
01109 return 0;
01110 }
01111
01112 static int avi_probe(AVProbeData *p)
01113 {
01114 int i;
01115
01116
01117 for(i=0; avi_headers[i][0]; i++)
01118 if(!memcmp(p->buf , avi_headers[i] , 4) &&
01119 !memcmp(p->buf+8, avi_headers[i]+4, 4))
01120 return AVPROBE_SCORE_MAX;
01121
01122 return 0;
01123 }
01124
01125 AVInputFormat avi_demuxer = {
01126 "avi",
01127 NULL_IF_CONFIG_SMALL("AVI format"),
01128 sizeof(AVIContext),
01129 avi_probe,
01130 avi_read_header,
01131 avi_read_packet,
01132 avi_read_close,
01133 avi_read_seek,
01134 };