X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Favidec.c;h=6a5d1e7a455a973185ba6d4b7a9e085fc7781365;hb=ffdc49df25ec275c17e7f3e0ae5893185e3d9b93;hp=d8d4726ae94327e9b717be4a307f41d212939fd3;hpb=dfd2a005eb29e4b9f2fdb97036eb7d5c38ae4bd4;p=ffmpeg diff --git a/libavformat/avidec.c b/libavformat/avidec.c index d8d4726ae94..6a5d1e7a455 100644 --- a/libavformat/avidec.c +++ b/libavformat/avidec.c @@ -25,7 +25,7 @@ #include #include "libavutil/intreadwrite.h" #include "libavutil/bswap.h" -#include "libavcodec/bytestream.h" +#include "libavutil/opt.h" #include "avformat.h" #include "avi.h" #include "dv.h" @@ -55,9 +55,12 @@ typedef struct AVIStream { AVFormatContext *sub_ctx; AVPacket sub_pkt; uint8_t *sub_buffer; + + int64_t seek_pos; } AVIStream; typedef struct { + const AVClass *class; int64_t riff_end; int64_t movi_end; int64_t fsize; @@ -69,9 +72,24 @@ typedef struct { int stream_index; DVDemuxContext* dv_demux; int odml_depth; + int use_odml; #define MAX_ODML_DEPTH 1000 } AVIContext; + +static const AVOption options[] = { + { "use_odml", "use odml index", offsetof(AVIContext, use_odml), FF_OPT_TYPE_INT, 1, -1, 1, AV_OPT_FLAG_DECODING_PARAM}, + { NULL }, +}; + +static const AVClass demuxer_class = { + "AVI demuxer", + av_default_item_name, + options, + LIBAVUTIL_VERSION_INT, +}; + + static const char avi_headers[][8] = { { 'R', 'I', 'F', 'F', 'A', 'V', 'I', ' ' }, { 'R', 'I', 'F', 'F', 'A', 'V', 'I', 'X' }, @@ -101,17 +119,17 @@ static inline int get_duration(AVIStream *ast, int len){ return 1; } -static int get_riff(AVFormatContext *s, ByteIOContext *pb) +static int get_riff(AVFormatContext *s, AVIOContext *pb) { AVIContext *avi = s->priv_data; char header[8]; int i; /* check RIFF header */ - get_buffer(pb, header, 4); - avi->riff_end = get_le32(pb); /* RIFF chunk size */ - avi->riff_end += url_ftell(pb); /* RIFF chunk end */ - get_buffer(pb, header+4, 4); + avio_read(pb, header, 4); + avi->riff_end = avio_rl32(pb); /* RIFF chunk size */ + avi->riff_end += avio_tell(pb); /* RIFF chunk end */ + avio_read(pb, header+4, 4); for(i=0; avi_headers[i][0]; i++) if(!memcmp(header, avi_headers[i], 8)) @@ -127,19 +145,19 @@ static int get_riff(AVFormatContext *s, ByteIOContext *pb) static int read_braindead_odml_indx(AVFormatContext *s, int frame_num){ AVIContext *avi = s->priv_data; - ByteIOContext *pb = s->pb; - 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); + AVIOContext *pb = s->pb; + int longs_pre_entry= avio_rl16(pb); + int index_sub_type = avio_r8(pb); + int index_type = avio_r8(pb); + int entries_in_use = avio_rl32(pb); + int chunk_id = avio_rl32(pb); + int64_t base = avio_rl64(pb); int stream_id= 10*((chunk_id&0xFF) - '0') + (((chunk_id>>8)&0xFF) - '0'); AVStream *st; AVIStream *ast; int i; int64_t last_pos= -1; - int64_t filesize= url_fsize(s->pb); + int64_t filesize= avio_size(s->pb); #ifdef DEBUG_SEEK av_log(s, AV_LOG_ERROR, "longs_pre_entry:%d index_type:%d entries_in_use:%d chunk_id:%X base:%16"PRIX64"\n", @@ -154,7 +172,7 @@ static int read_braindead_odml_indx(AVFormatContext *s, int frame_num){ if(index_sub_type) return -1; - get_le32(pb); + avio_rl32(pb); if(index_type && longs_pre_entry != 2) return -1; @@ -171,8 +189,8 @@ static int read_braindead_odml_indx(AVFormatContext *s, int frame_num){ for(i=0; i= 0; len &= 0x7FFFFFFF; @@ -192,27 +210,27 @@ static int read_braindead_odml_indx(AVFormatContext *s, int frame_num){ }else{ int64_t offset, pos; int duration; - offset = get_le64(pb); - get_le32(pb); /* size */ - duration = get_le32(pb); + offset = avio_rl64(pb); + avio_rl32(pb); /* size */ + duration = avio_rl32(pb); if(url_feof(pb)) return -1; - pos = url_ftell(pb); + pos = avio_tell(pb); if(avi->odml_depth > MAX_ODML_DEPTH){ av_log(s, AV_LOG_ERROR, "Too deeply nested ODML indexes\n"); return -1; } - url_fseek(pb, offset+8, SEEK_SET); + avio_seek(pb, offset+8, SEEK_SET); avi->odml_depth++; read_braindead_odml_indx(s, frame_num); avi->odml_depth--; frame_num += duration; - url_fseek(pb, pos, SEEK_SET); + avio_seek(pb, pos, SEEK_SET); } } avi->index_loaded=1; @@ -247,7 +265,7 @@ static void clean_index(AVFormatContext *s){ static int avi_read_tag(AVFormatContext *s, AVStream *st, uint32_t tag, uint32_t size) { - ByteIOContext *pb = s->pb; + AVIOContext *pb = s->pb; char key[5] = {0}, *value; size += (size & 1); @@ -257,7 +275,7 @@ static int avi_read_tag(AVFormatContext *s, AVStream *st, uint32_t tag, uint32_t value = av_malloc(size+1); if (!value) return -1; - get_buffer(pb, value, size); + avio_read(pb, value, size); value[size]=0; AV_WL32(key, tag); @@ -268,9 +286,9 @@ static int avi_read_tag(AVFormatContext *s, AVStream *st, uint32_t tag, uint32_t 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); + while (avio_tell(s->pb) < end) { + uint32_t tag = avio_rl32(s->pb); + uint32_t size = avio_rl32(s->pb); avi_read_tag(s, NULL, tag, size); } } @@ -299,18 +317,18 @@ static void avi_metadata_creation_time(AVMetadata **metadata, char *date) 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); + while (avio_tell(s->pb) < end) { + uint32_t tag = avio_rl32(s->pb); + uint32_t size = avio_rl32(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); + uint64_t tag_end = avio_tell(s->pb) + size; + while (avio_tell(s->pb) < tag_end) { + uint16_t tag = avio_rl16(s->pb); + uint16_t size = avio_rl16(s->pb); const char *name = NULL; char buffer[64] = {0}; - size -= get_buffer(s->pb, buffer, + size -= avio_read(s->pb, buffer, FFMIN(size, sizeof(buffer)-1)); switch (tag) { case 0x03: name = "maker"; break; @@ -322,12 +340,12 @@ static void avi_read_nikon(AVFormatContext *s, uint64_t end) } if (name) av_metadata_set2(&s->metadata, name, buffer, 0); - url_fskip(s->pb, size); + avio_skip(s->pb, size); } break; } default: - url_fskip(s->pb, size); + avio_skip(s->pb, size); break; } } @@ -336,7 +354,7 @@ static void avi_read_nikon(AVFormatContext *s, uint64_t end) static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) { AVIContext *avi = s->priv_data; - ByteIOContext *pb = s->pb; + AVIOContext *pb = s->pb; unsigned int tag, tag1, handler; int codec_type, stream_index, frame_period, bit_rate; unsigned int size; @@ -346,13 +364,16 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) int avih_width=0, avih_height=0; int amv_file_format=0; uint64_t list_end = 0; + int ret; avi->stream_index= -1; if (get_riff(s, pb) < 0) return -1; - avi->fsize = url_fsize(pb); + av_log(avi, AV_LOG_DEBUG, "use odml:%d\n", avi->use_odml); + + avi->fsize = avio_size(pb); if(avi->fsize<=0) avi->fsize= avi->riff_end == 8 ? INT64_MAX : avi->riff_end; @@ -363,23 +384,23 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) for(;;) { if (url_feof(pb)) goto fail; - tag = get_le32(pb); - size = get_le32(pb); + tag = avio_rl32(pb); + size = avio_rl32(pb); print_tag("tag", tag, size); switch(tag) { case MKTAG('L', 'I', 'S', 'T'): - list_end = url_ftell(pb) + size; + list_end = avio_tell(pb) + size; /* Ignored, except at start of video packets. */ - tag1 = get_le32(pb); + tag1 = avio_rl32(pb); print_tag("list", tag1, 0); if (tag1 == MKTAG('m', 'o', 'v', 'i')) { - avi->movi_list = url_ftell(pb) - 4; + avi->movi_list = avio_tell(pb) - 4; if(size) avi->movi_end = avi->movi_list + size + (size & 1); - else avi->movi_end = url_fsize(pb); + else avi->movi_end = avio_size(pb); av_dlog(NULL, "movi end=%"PRIx64"\n", avi->movi_end); goto end_of_header; } @@ -392,41 +413,41 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) 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); + size -= avio_read(pb, date, FFMIN(size, sizeof(date)-1)); + avio_skip(pb, size); avi_metadata_creation_time(&s->metadata, date); break; } case MKTAG('d', 'm', 'l', 'h'): avi->is_odml = 1; - url_fskip(pb, size + (size & 1)); + avio_skip(pb, size + (size & 1)); break; case MKTAG('a', 'm', 'v', 'h'): amv_file_format=1; case MKTAG('a', 'v', 'i', 'h'): /* AVI header */ /* using frame_period is bad idea */ - frame_period = get_le32(pb); - bit_rate = get_le32(pb) * 8; - get_le32(pb); - avi->non_interleaved |= get_le32(pb) & AVIF_MUSTUSEINDEX; - - url_fskip(pb, 2 * 4); - get_le32(pb); - get_le32(pb); - avih_width=get_le32(pb); - avih_height=get_le32(pb); - - url_fskip(pb, size - 10 * 4); + frame_period = avio_rl32(pb); + bit_rate = avio_rl32(pb) * 8; + avio_rl32(pb); + avi->non_interleaved |= avio_rl32(pb) & AVIF_MUSTUSEINDEX; + + avio_skip(pb, 2 * 4); + avio_rl32(pb); + avio_rl32(pb); + avih_width=avio_rl32(pb); + avih_height=avio_rl32(pb); + + avio_skip(pb, size - 10 * 4); break; case MKTAG('s', 't', 'r', 'h'): /* stream header */ - tag1 = get_le32(pb); - handler = get_le32(pb); /* codec tag */ + tag1 = avio_rl32(pb); + handler = avio_rl32(pb); /* codec tag */ if(tag1 == MKTAG('p', 'a', 'd', 's')){ - url_fskip(pb, size - 8); + avio_skip(pb, size - 8); break; }else{ stream_index++; @@ -470,12 +491,12 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) goto fail; } s->streams[0]->priv_data = ast; - url_fskip(pb, 3 * 4); - ast->scale = get_le32(pb); - ast->rate = get_le32(pb); - url_fskip(pb, 4); /* start time */ + avio_skip(pb, 3 * 4); + ast->scale = avio_rl32(pb); + ast->rate = avio_rl32(pb); + avio_skip(pb, 4); /* start time */ - dv_dur = get_le32(pb); + dv_dur = avio_rl32(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); @@ -486,19 +507,19 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) */ stream_index = s->nb_streams - 1; - url_fskip(pb, size - 9*4); + avio_skip(pb, size - 9*4); break; } assert(stream_index < s->nb_streams); st->codec->stream_codec_tag= handler; - 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); + avio_rl32(pb); /* flags */ + avio_rl16(pb); /* priority */ + avio_rl16(pb); /* language */ + avio_rl32(pb); /* initial frame */ + ast->scale = avio_rl32(pb); + ast->rate = avio_rl32(pb); if(!(ast->scale && ast->rate)){ 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); if(frame_period){ @@ -511,13 +532,13 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) } av_set_pts_info(st, 64, ast->scale, ast->rate); - ast->cum_len=get_le32(pb); /* start */ - st->nb_frames = get_le32(pb); + ast->cum_len=avio_rl32(pb); /* start */ + st->nb_frames = avio_rl32(pb); st->start_time = 0; - get_le32(pb); /* buffer size */ - get_le32(pb); /* quality */ - ast->sample_size = get_le32(pb); /* sample ssize */ + avio_rl32(pb); /* buffer size */ + avio_rl32(pb); /* quality */ + ast->sample_size = avio_rl32(pb); /* sample ssize */ ast->cum_len *= FFMAX(1, ast->sample_size); // av_log(s, AV_LOG_DEBUG, "%d %d %d %d\n", ast->rate, ast->scale, ast->start, ast->sample_size); @@ -543,14 +564,14 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) if(ast->sample_size == 0) st->duration = st->nb_frames; ast->frame_offset= ast->cum_len; - url_fskip(pb, size - 12 * 4); + avio_skip(pb, size - 12 * 4); break; case MKTAG('s', 't', 'r', 'f'): /* stream header */ if (stream_index >= (unsigned)s->nb_streams || avi->dv_demux) { - url_fskip(pb, size); + avio_skip(pb, size); } else { - uint64_t cur_pos = url_ftell(pb); + uint64_t cur_pos = avio_tell(pb); if (cur_pos < list_end) size = FFMIN(size, list_end - cur_pos); st = s->streams[stream_index]; @@ -561,7 +582,7 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) st->codec->height=avih_height; st->codec->codec_type = AVMEDIA_TYPE_VIDEO; st->codec->codec_id = CODEC_ID_AMV; - url_fskip(pb, size); + avio_skip(pb, size); break; } tag1 = ff_get_bmp_header(pb, st); @@ -580,25 +601,28 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) st->codec->extradata_size= 0; return AVERROR(ENOMEM); } - get_buffer(pb, st->codec->extradata, st->codec->extradata_size); + avio_read(pb, st->codec->extradata, st->codec->extradata_size); } if(st->codec->extradata_size & 1) //FIXME check if the encoder really did this correctly - get_byte(pb); + avio_r8(pb); /* 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. */ if (st->codec->extradata_size && (st->codec->bits_per_coded_sample <= 8)) { - st->codec->palctrl = av_mallocz(sizeof(AVPaletteControl)); + int pal_size = (1 << st->codec->bits_per_coded_sample) << 2; + const uint8_t *pal_src; + + pal_size = FFMIN(pal_size, st->codec->extradata_size); + pal_src = st->codec->extradata + st->codec->extradata_size - pal_size; #if HAVE_BIGENDIAN - for (i = 0; i < FFMIN(st->codec->extradata_size, AVPALETTE_SIZE)/4; i++) - st->codec->palctrl->palette[i] = av_bswap32(((uint32_t*)st->codec->extradata)[i]); + for (i = 0; i < pal_size/4; i++) + ast->pal[i] = AV_RL32(pal_src+4*i); #else - memcpy(st->codec->palctrl->palette, st->codec->extradata, - FFMIN(st->codec->extradata_size, AVPALETTE_SIZE)); + memcpy(ast->pal, pal_src, pal_size); #endif - st->codec->palctrl->palette_changed = 1; + ast->has_pal = 1; } print_tag("video", tag1, 0); @@ -621,17 +645,19 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) } st->codec->height= FFABS(st->codec->height); -// url_fskip(pb, size - 5 * 4); +// avio_skip(pb, size - 5 * 4); break; case AVMEDIA_TYPE_AUDIO: - ff_get_wav_header(pb, st->codec, size); + ret = ff_get_wav_header(pb, st->codec, size); + if (ret < 0) + return ret; ast->dshow_block_align= st->codec->block_align; if(ast->sample_size && st->codec->block_align && ast->sample_size != st->codec->block_align){ av_log(s, AV_LOG_WARNING, "sample size (%d) != block align (%d)\n", ast->sample_size, st->codec->block_align); ast->sample_size= st->codec->block_align; } if (size&1) /* 2-aligned (fix for Stargate SG-1 - 3x18 - Shades of Grey.avi) */ - url_fskip(pb, 1); + avio_skip(pb, 1); /* Force parsing as several audio frames can be in * one packet and timestamps refer to packet start. */ st->need_parsing = AVSTREAM_PARSE_TIMESTAMPS; @@ -653,40 +679,40 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) break; case AVMEDIA_TYPE_SUBTITLE: st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; - st->codec->codec_id = CODEC_ID_PROBE; + st->request_probe= 1; break; default: st->codec->codec_type = AVMEDIA_TYPE_DATA; st->codec->codec_id= CODEC_ID_NONE; st->codec->codec_tag= 0; - url_fskip(pb, size); + avio_skip(pb, size); break; } } break; case MKTAG('i', 'n', 'd', 'x'): - i= url_ftell(pb); - if(!url_is_streamed(pb) && !(s->flags & AVFMT_FLAG_IGNIDX)){ + i= avio_tell(pb); + if(pb->seekable && !(s->flags & AVFMT_FLAG_IGNIDX) && avi->use_odml){ read_braindead_odml_indx(s, 0); } - url_fseek(pb, i+size, SEEK_SET); + avio_seek(pb, i+size, SEEK_SET); break; 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); - active_aspect.num= get_le16(pb); - active.num = get_le32(pb); - active.den = get_le32(pb); - get_le32(pb); //nbFieldsPerFrame + avio_rl32(pb); + avio_rl32(pb); + avio_rl32(pb); + avio_rl32(pb); + avio_rl32(pb); + + active_aspect.den= avio_rl16(pb); + active_aspect.num= avio_rl16(pb); + active.num = avio_rl32(pb); + active.den = avio_rl32(pb); + avio_rl32(pb); //nbFieldsPerFrame if(active_aspect.num && active_aspect.den && active.num && active.den){ st->sample_aspect_ratio= av_div_q(active_aspect, active); @@ -694,7 +720,7 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) } size -= 9*4; } - url_fseek(pb, size, SEEK_CUR); + avio_skip(pb, size); break; case MKTAG('s', 't', 'r', 'n'): if(s->nb_streams){ @@ -705,13 +731,13 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) if(size > 1000000){ av_log(s, AV_LOG_ERROR, "Something went wrong during header parsing, " "I will ignore it and try to continue anyway.\n"); - avi->movi_list = url_ftell(pb) - 4; - avi->movi_end = url_fsize(pb); + avi->movi_list = avio_tell(pb) - 4; + avi->movi_end = avio_size(pb); goto end_of_header; } /* skip tag */ size += (size & 1); - url_fskip(pb, size); + avio_skip(pb, size); break; } } @@ -722,15 +748,19 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) return -1; } - if(!avi->index_loaded && !url_is_streamed(pb)) + if(!avi->index_loaded && pb->seekable) avi_load_index(s); avi->index_loaded = 1; - avi->non_interleaved |= guess_ni_flag(s); + avi->non_interleaved |= guess_ni_flag(s) | (s->flags & AVFMT_FLAG_SORT_DTS); for(i=0; inb_streams; i++){ AVStream *st = s->streams[i]; if(st->nb_index_entries) break; } + // DV-in-AVI cannot be non-interleaved, if set this must be + // a mis-detection. + if(avi->dv_demux) + avi->non_interleaved=0; 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; @@ -748,39 +778,32 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) 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; + uint8_t desc[256]; + int score = AVPROBE_SCORE_MAX / 2, ret; AVIStream *ast = st->priv_data; AVInputFormat *sub_demuxer; AVRational time_base; - ByteIOContext *pb; + AVIOContext *pb = avio_alloc_context( pkt->data + 7, + pkt->size - 7, + 0, NULL, NULL, NULL, NULL); AVProbeData pd; + unsigned int desc_len = avio_rl32(pb); - if (desc_len > FFMAX(pkt->size-17, 0)) - return 0; + if (desc_len > pb->buf_end - pb->buf_ptr) + goto error; - 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; + ret = avio_get_str16le(pb, desc_len, desc, sizeof(desc)); + avio_skip(pb, desc_len - ret); 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); + avio_rl16(pb); /* flags? */ + avio_rl32(pb); /* data size */ - pd = (AVProbeData) { .buf = ptr, .buf_size = size }; + pd = (AVProbeData) { .buf = pb->buf_ptr, .buf_size = pb->buf_end - pb->buf_ptr }; if (!(sub_demuxer = av_probe_input_format2(&pd, 1, &score))) - return 0; + goto error; - 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; @@ -791,6 +814,8 @@ static int read_gab2_sub(AVStream *st, AVPacket *pkt) { ast->sub_buffer = pkt->data; memset(pkt, 0, sizeof(*pkt)); return 1; +error: + av_freep(&pb); } return 0; } @@ -840,7 +865,7 @@ static int get_stream_idx(int *d){ static int avi_read_packet(AVFormatContext *s, AVPacket *pkt) { AVIContext *avi = s->priv_data; - ByteIOContext *pb = s->pb; + AVIOContext *pb = s->pb; int n, d[8]; unsigned int size; int64_t i, sync; @@ -898,7 +923,7 @@ static int avi_read_packet(AVFormatContext *s, AVPacket *pkt) if(i>=0){ int64_t pos= best_st->index_entries[i].pos; pos += best_ast->packet_size - best_ast->remaining; - url_fseek(s->pb, pos + 8, SEEK_SET); + avio_seek(s->pb, pos + 8, SEEK_SET); // av_log(s, AV_LOG_DEBUG, "pos=%"PRId64"\n", pos); assert(best_ast->remaining <= best_ast->packet_size); @@ -929,20 +954,20 @@ resync: if(size > ast->remaining) size= ast->remaining; - avi->last_pkt_pos= url_ftell(pb); + avi->last_pkt_pos= avio_tell(pb); err= av_get_packet(pb, pkt, size); if(err<0) return err; if(ast->has_pal && pkt->data && pkt->size<(unsigned)INT_MAX/2){ - void *ptr= av_realloc(pkt->data, pkt->size + 4*256 + FF_INPUT_BUFFER_PADDING_SIZE); - if(ptr){ - ast->has_pal=0; - pkt->size += 4*256; - pkt->data= ptr; - memcpy(pkt->data + pkt->size - 4*256, ast->pal, 4*256); - }else - av_log(s, AV_LOG_ERROR, "Failed to append palette\n"); + uint8_t *pal; + pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE); + if(!pal){ + av_log(s, AV_LOG_ERROR, "Failed to allocate data for palette\n"); + }else{ + memcpy(pal, ast->pal, AVPALETTE_SIZE); + ast->has_pal = 0; + } } if (CONFIG_DV_DEMUXER && avi->dv_demux) { @@ -991,16 +1016,22 @@ resync: ast->packet_size= 0; } + if(!avi->non_interleaved && ast->seek_pos > pkt->pos){ + av_free_packet(pkt); + goto resync; + } + ast->seek_pos= 0; + return size; } memset(d, -1, sizeof(int)*8); - for(i=sync=url_ftell(pb); !url_feof(pb); i++) { + for(i=sync=avio_tell(pb); !url_feof(pb); i++) { int j; for(j=0; j<7; j++) d[j]= d[j+1]; - d[7]= get_byte(pb); + d[7]= avio_r8(pb); size= d[4] + (d[5]<<8) + (d[6]<<16) + (d[7]<<24); @@ -1014,14 +1045,14 @@ resync: //parse JUNK ||(d[0] == 'J' && d[1] == 'U' && d[2] == 'N' && d[3] == 'K') ||(d[0] == 'i' && d[1] == 'd' && d[2] == 'x' && d[3] == '1')){ - url_fskip(pb, size); + avio_skip(pb, size); //av_log(s, AV_LOG_DEBUG, "SKIP\n"); goto resync; } //parse stray LIST if(d[0] == 'L' && d[1] == 'I' && d[2] == 'S' && d[3] == 'T'){ - url_fskip(pb, 4); + avio_skip(pb, 4); goto resync; } @@ -1032,7 +1063,7 @@ resync: //detect ##ix chunk and skip if(d[2] == 'i' && d[3] == 'x' && n < s->nb_streams){ - url_fskip(pb, size); + avio_skip(pb, size); goto resync; } @@ -1066,18 +1097,18 @@ resync: /*|| (st->discard >= AVDISCARD_NONKEY && !(pkt->flags & AV_PKT_FLAG_KEY))*/ //FIXME needs a little reordering || st->discard >= AVDISCARD_ALL){ ast->frame_offset += get_duration(ast, size); - url_fskip(pb, size); + avio_skip(pb, size); goto resync; } if (d[2] == 'p' && d[3] == 'c' && size<=4*256+4) { - int k = get_byte(pb); - int last = (k + get_byte(pb) - 1) & 0xFF; + int k = avio_r8(pb); + int last = (k + avio_r8(pb) - 1) & 0xFF; - get_le16(pb); //flags + avio_rl16(pb); //flags for (; k <= last; k++) - ast->pal[k] = get_be32(pb)>>8;// b + (g << 8) + (r << 16); + ast->pal[k] = avio_rb32(pb)>>8;// b + (g << 8) + (r << 16); ast->has_pal= 1; goto resync; } else if( ((ast->prefix_count<5 || sync+9 > i) && d[2]<128 && d[3]<128) || @@ -1098,7 +1129,7 @@ resync: ast->remaining= size; if(size || !ast->sample_size){ - uint64_t pos= url_ftell(pb) - 8; + uint64_t pos= avio_tell(pb) - 8; if(!st->index_entries || !st->nb_index_entries || st->index_entries[st->nb_index_entries - 1].pos < pos){ av_add_index_entry(st, pos, ast->frame_offset, size, 0, AVINDEX_KEYFRAME); } @@ -1116,7 +1147,7 @@ resync: static int avi_read_idx1(AVFormatContext *s, int size) { AVIContext *avi = s->priv_data; - ByteIOContext *pb = s->pb; + AVIOContext *pb = s->pb; int nb_index_entries, i; AVStream *st; AVIStream *ast; @@ -1129,10 +1160,10 @@ static int avi_read_idx1(AVFormatContext *s, int size) /* 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); + tag = avio_rl32(pb); + flags = avio_rl32(pb); + pos = avio_rl32(pb); + len = avio_rl32(pb); #if defined(DEBUG_SEEK) av_log(s, AV_LOG_DEBUG, "%d: tag=0x%x flags=0x%x pos=0x%x len=%d/", i, tag, flags, pos, len); @@ -1168,7 +1199,7 @@ static int guess_ni_flag(AVFormatContext *s){ int i; int64_t last_start=0; int64_t first_end= INT64_MAX; - int64_t oldpos= url_ftell(s->pb); + int64_t oldpos= avio_tell(s->pb); for(i=0; inb_streams; i++){ AVStream *st = s->streams[i]; @@ -1180,8 +1211,8 @@ static int guess_ni_flag(AVFormatContext *s){ if(n >= 2){ int64_t pos= st->index_entries[0].pos; - url_fseek(s->pb, pos + 4, SEEK_SET); - size= get_le32(s->pb); + avio_seek(s->pb, pos + 4, SEEK_SET); + size= avio_rl32(s->pb); if(pos + size > st->index_entries[1].pos) last_start= INT64_MAX; } @@ -1191,19 +1222,19 @@ static int guess_ni_flag(AVFormatContext *s){ if(st->index_entries[n-1].pos < first_end) first_end= st->index_entries[n-1].pos; } - url_fseek(s->pb, oldpos, SEEK_SET); + avio_seek(s->pb, oldpos, SEEK_SET); return last_start > first_end; } static int avi_load_index(AVFormatContext *s) { AVIContext *avi = s->priv_data; - ByteIOContext *pb = s->pb; + AVIOContext *pb = s->pb; uint32_t tag, size; - int64_t pos= url_ftell(pb); + int64_t pos= avio_tell(pb); int ret = -1; - if (url_fseek(pb, avi->movi_end, SEEK_SET) < 0) + if (avio_seek(pb, avi->movi_end, SEEK_SET) < 0) goto the_end; // maybe truncated file #ifdef DEBUG_SEEK printf("movi_end=0x%"PRIx64"\n", avi->movi_end); @@ -1211,8 +1242,8 @@ static int avi_load_index(AVFormatContext *s) for(;;) { if (url_feof(pb)) break; - tag = get_le32(pb); - size = get_le32(pb); + tag = avio_rl32(pb); + size = avio_rl32(pb); #ifdef DEBUG_SEEK printf("tag=%c%c%c%c size=0x%x\n", tag & 0xff, @@ -1231,13 +1262,13 @@ static int avi_load_index(AVFormatContext *s) default: skip: size += (size & 1); - if (url_fseek(pb, size, SEEK_CUR) < 0) + if (avio_skip(pb, size) < 0) goto the_end; // something is wrong here break; } } the_end: - url_fseek(pb, pos, SEEK_SET); + avio_seek(pb, pos, SEEK_SET); return ret; } @@ -1256,7 +1287,7 @@ static int avi_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp AVIContext *avi = s->priv_data; AVStream *st; int i, index; - int64_t pos; + int64_t pos, pos_min; AVIStream *ast; if (!avi->index_loaded) { @@ -1288,11 +1319,12 @@ static int avi_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp /* DV demux so it can synthesize correct timestamps. */ dv_offset_reset(avi->dv_demux, timestamp); - url_fseek(s->pb, pos, SEEK_SET); + avio_seek(s->pb, pos, SEEK_SET); avi->stream_index= -1; return 0; } + pos_min= pos; for(i = 0; i < s->nb_streams; i++) { AVStream *st2 = s->streams[i]; AVIStream *ast2 = st2->priv_data; @@ -1316,21 +1348,13 @@ static int avi_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp flags | AVSEEK_FLAG_BACKWARD); if(index<0) index=0; - - 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++; - } - -// av_log(s, AV_LOG_DEBUG, "%"PRId64" %d %"PRId64"\n", timestamp, index, st2->index_entries[index].timestamp); - /* extract the current frame number */ + ast2->seek_pos= st2->index_entries[index].pos; + pos_min= FFMIN(pos_min,ast2->seek_pos); ast2->frame_offset = st2->index_entries[index].timestamp; } /* do the seek */ - url_fseek(s->pb, pos, SEEK_SET); + avio_seek(s->pb, pos_min, SEEK_SET); avi->stream_index= -1; return 0; } @@ -1343,7 +1367,6 @@ static int avi_read_close(AVFormatContext *s) for(i=0;inb_streams;i++) { AVStream *st = s->streams[i]; AVIStream *ast = st->priv_data; - av_free(st->codec->palctrl); if (ast) { if (ast->sub_ctx) { av_freep(&ast->sub_ctx->pb); @@ -1354,8 +1377,7 @@ static int avi_read_close(AVFormatContext *s) } } - if (avi->dv_demux) - av_free(avi->dv_demux); + av_free(avi->dv_demux); return 0; } @@ -1382,4 +1404,5 @@ AVInputFormat ff_avi_demuxer = { avi_read_packet, avi_read_close, avi_read_seek, + .priv_class = &demuxer_class, };