📄 avidec.c
字号:
memset(d, -1, sizeof(int)*8); if (avi->dv_demux) { size = dv_get_packet(avi->dv_demux, pkt); if (size >= 0) return size; } for(i=url_ftell(pb); !url_feof(pb); i++) { int j; if (i >= avi->movi_end) { /* Let's see if it's an OpenDML AVI */ uint32_t tag, size, tag2; url_fskip(pb, avi->riff_end - url_ftell(pb)); if (get_riff(avi, pb) < 0) return -1; tag = get_le32(pb); size = get_le32(pb); tag2 = get_le32(pb); if (tag == MKTAG('L','I','S','T') && tag2 == MKTAG('m','o','v','i')) avi->movi_end = url_ftell(pb) + size - 4; else return -1; } for(j=0; j<7; j++) d[j]= d[j+1]; d[7]= get_byte(pb); size= d[4] + (d[5]<<8) + (d[6]<<16) + (d[7]<<24); //parse ix## n= (d[2] - '0') * 10 + (d[3] - '0'); if( d[2] >= '0' && d[2] <= '9' && d[3] >= '0' && d[3] <= '9' && d[0] == 'i' && d[1] == 'x' && n < s->nb_streams && i + size <= avi->movi_end){ url_fskip(pb, size); } //parse ##dc/##wb n= (d[0] - '0') * 10 + (d[1] - '0'); if( d[0] >= '0' && d[0] <= '9' && d[1] >= '0' && d[1] <= '9' && ((d[2] == 'd' && d[3] == 'c') || (d[2] == 'w' && d[3] == 'b') || (d[2] == 'd' && d[3] == 'b') || (d[2] == '_' && d[3] == '_')) && n < s->nb_streams && i + size <= avi->movi_end) { av_new_packet(pkt, size); get_buffer(pb, pkt->data, size); if (size & 1) { get_byte(pb); size++; } if (avi->dv_demux) { dstr = pkt->destruct; size = dv_produce_packet(avi->dv_demux, pkt, pkt->data, pkt->size); pkt->destruct = dstr; pkt->flags |= PKT_FLAG_KEY; } else { AVStream *st; AVIStream *ast; st = s->streams[n]; ast = st->priv_data; /* XXX: how to handle B frames in avi ? */ pkt->dts = ast->frame_offset;// pkt->dts += ast->start; if(ast->sample_size) pkt->dts /= ast->sample_size;//av_log(NULL, AV_LOG_DEBUG, "dts:%Ld offset:%d %d/%d %d st:%d size:%d\n", pkt->dts, ast->frame_offset, ast->scale, ast->rate, AV_TIME_BASE, n, size); pkt->stream_index = n; /* FIXME: We really should read index for that */ if (st->codec.codec_type == CODEC_TYPE_VIDEO) { if (ast->frame_offset < ast->nb_index_entries) { if (ast->index_entries[ast->frame_offset].flags & AVIIF_INDEX) pkt->flags |= PKT_FLAG_KEY; } else { /* if no index, better to say that all frames are key frames */ pkt->flags |= PKT_FLAG_KEY; } } else { pkt->flags |= PKT_FLAG_KEY; } if(ast->sample_size) ast->frame_offset += pkt->size; else ast->frame_offset++; } return size; } } return -1;}/* XXX: we make the implicit supposition that the position are sorted for each stream */static int avi_read_idx1(AVFormatContext *s, int size){ ByteIOContext *pb = &s->pb; int nb_index_entries, i; AVStream *st; AVIStream *ast; AVIIndexEntry *ie, *entries; unsigned int index, tag, flags, pos, len; nb_index_entries = size / 16; if (nb_index_entries <= 0) return -1; /* read the entries and sort them in each stream component */ for(i = 0; i < nb_index_entries; i++) { tag = get_le32(pb); flags = get_le32(pb); pos = get_le32(pb); len = get_le32(pb);#if defined(DEBUG_SEEK) && 0 printf("%d: tag=0x%x flags=0x%x pos=0x%x len=%d\n", i, tag, flags, pos, len);#endif index = ((tag & 0xff) - '0') * 10; index += ((tag >> 8) & 0xff) - '0'; if (index >= s->nb_streams) continue; st = s->streams[index]; ast = st->priv_data; entries = av_fast_realloc(ast->index_entries, &ast->index_entries_allocated_size, (ast->nb_index_entries + 1) * sizeof(AVIIndexEntry)); if (entries) { ast->index_entries = entries; ie = &entries[ast->nb_index_entries++]; ie->flags = flags; ie->pos = pos; ie->cum_len = ast->cum_len; ast->cum_len += len; } } return 0;}static int avi_load_index(AVFormatContext *s){ AVIContext *avi = s->priv_data; ByteIOContext *pb = &s->pb; uint32_t tag, size; offset_t pos= url_ftell(pb); url_fseek(pb, avi->movi_end, SEEK_SET);#ifdef DEBUG_SEEK printf("movi_end=0x%llx\n", avi->movi_end);#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; else goto the_end; break; default: skip: size += (size & 1); url_fskip(pb, size); break; } } the_end: url_fseek(pb, pos, SEEK_SET); return 0;}/* return the index entry whose position is immediately >= 'wanted_pos' */static int locate_frame_in_index(AVIIndexEntry *entries, int nb_entries, int wanted_pos){ int a, b, m, pos; a = 0; b = nb_entries - 1; while (a <= b) { m = (a + b) >> 1; pos = entries[m].pos; if (pos == wanted_pos) goto found; else if (pos > wanted_pos) { b = m - 1; } else { a = m + 1; } } m = a; if (m > 0) m--; found: return m;}static int avi_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp){ AVIContext *avi = s->priv_data; AVStream *st; AVIStream *ast; int frame_number, i; int64_t pos; if (!avi->index_loaded) { /* we only load the index on demand */ avi_load_index(s); avi->index_loaded = 1; } if (stream_index < 0) { for(i = 0; i < s->nb_streams; i++) { st = s->streams[i]; if (st->codec.codec_type == CODEC_TYPE_VIDEO) goto found; } return -1; found: stream_index = i; } st = s->streams[stream_index]; if (st->codec.codec_type != CODEC_TYPE_VIDEO) return -1; ast = st->priv_data; /* compute the frame number */ frame_number = timestamp;#ifdef DEBUG_SEEK printf("timestamp=%0.3f nb_indexes=%d frame_number=%d\n", (double)timestamp / AV_TIME_BASE, ast->nb_index_entries, frame_number);#endif /* find a closest key frame before */ if (frame_number >= ast->nb_index_entries) return -1; while (frame_number >= 0 && !(ast->index_entries[frame_number].flags & AVIIF_INDEX)) frame_number--; if (frame_number < 0) return -1; ast->new_frame_offset = frame_number; /* find the position */ pos = ast->index_entries[frame_number].pos;#ifdef DEBUG_SEEK printf("key_frame_number=%d pos=0x%llx\n", frame_number, pos);#endif /* update the frame counters for all the other stream by looking at the positions just after the one found */ for(i = 0; i < s->nb_streams; i++) { int j; if (i != stream_index) { st = s->streams[i]; ast = st->priv_data; if (ast->nb_index_entries <= 0) return -1; j = locate_frame_in_index(ast->index_entries, ast->nb_index_entries, pos); /* get next frame */ if ((j + 1) < ast->nb_index_entries) j++; /* extract the current frame number */ if (ast->sample_size==0) ast->new_frame_offset = j; else ast->new_frame_offset = ast->index_entries[j].cum_len; } } /* everything is OK now. We can update the frame offsets */ for(i = 0; i < s->nb_streams; i++) { st = s->streams[i]; ast = st->priv_data; ast->frame_offset = ast->new_frame_offset;#ifdef DEBUG_SEEK printf("%d: frame_offset=%d\n", i, ast->frame_offset);#endif } /* do the seek */ pos += avi->movi_list; url_fseek(&s->pb, pos, SEEK_SET); return 0;}static int avi_read_close(AVFormatContext *s){ int i; AVIContext *avi = s->priv_data; for(i=0;i<s->nb_streams;i++) { AVStream *st = s->streams[i]; AVIStream *ast = st->priv_data; if(ast){ av_free(ast->index_entries); av_free(ast); } av_free(st->codec.extradata); av_free(st->codec.palctrl); } if (avi->dv_demux) av_free(avi->dv_demux); return 0;}static int avi_probe(AVProbeData *p){ /* check file header */ if (p->buf_size <= 32) return 0; if (p->buf[0] == 'R' && p->buf[1] == 'I' && p->buf[2] == 'F' && p->buf[3] == 'F' && p->buf[8] == 'A' && p->buf[9] == 'V' && p->buf[10] == 'I' && p->buf[11] == ' ') return AVPROBE_SCORE_MAX; else return 0;}static AVInputFormat avi_iformat = { "avi", "avi format", sizeof(AVIContext), avi_probe, avi_read_header, avi_read_packet, avi_read_close, avi_read_seek,};int avidec_init(void){ av_register_input_format(&avi_iformat); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -