X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fflic.c;h=efd9e5430878232c0bc017be6824d4d2e16979d6;hb=bc70684e74a185d7b80c8b80bdedda659cb581b8;hp=7c62cb423c8a68250cd14ee5af1e2425bd8fc5a5;hpb=5ca7eb36b7353f9e6af05a5a952eead5f6d326dd;p=ffmpeg diff --git a/libavformat/flic.c b/libavformat/flic.c index 7c62cb423c8..efd9e543087 100644 --- a/libavformat/flic.c +++ b/libavformat/flic.c @@ -57,7 +57,7 @@ typedef struct FlicDemuxContext { int frame_number; } FlicDemuxContext; -static int flic_probe(AVProbeData *p) +static int flic_probe(const AVProbeData *p) { int magic_number; @@ -89,7 +89,7 @@ static int flic_read_header(AVFormatContext *s) AVIOContext *pb = s->pb; unsigned char header[FLIC_HEADER_SIZE]; AVStream *st, *ast; - int speed; + int speed, ret; int magic_number; unsigned char preamble[FLIC_PREAMBLE_SIZE]; @@ -125,8 +125,8 @@ static int flic_read_header(AVFormatContext *s) } /* send over the whole 128-byte FLIC header */ - if (ff_alloc_extradata(st->codecpar, FLIC_HEADER_SIZE)) - return AVERROR(ENOMEM); + if ((ret = ff_alloc_extradata(st->codecpar, FLIC_HEADER_SIZE)) < 0) + return ret; memcpy(st->codecpar->extradata, header, FLIC_HEADER_SIZE); /* peek at the preamble to detect TFTD videos - they seem to always start with an audio chunk */ @@ -175,9 +175,8 @@ static int flic_read_header(AVFormatContext *s) avio_seek(pb, 12, SEEK_SET); /* send over abbreviated FLIC header chunk */ - av_freep(&st->codecpar->extradata); - if (ff_alloc_extradata(st->codecpar, 12)) - return AVERROR(ENOMEM); + if ((ret = ff_alloc_extradata(st->codecpar, 12)) < 0) + return ret; memcpy(st->codecpar->extradata, header, 12); } else if (magic_number == FLIC_FILE_MAGIC_1) { @@ -203,6 +202,7 @@ static int flic_read_packet(AVFormatContext *s, int magic; int ret = 0; unsigned char preamble[FLIC_PREAMBLE_SIZE]; + int64_t pos = avio_tell(pb); while (!packet_read && !avio_feof(pb)) { @@ -216,37 +216,38 @@ static int flic_read_packet(AVFormatContext *s, magic = AV_RL16(&preamble[4]); if (((magic == FLIC_CHUNK_MAGIC_1) || (magic == FLIC_CHUNK_MAGIC_2)) && size > FLIC_PREAMBLE_SIZE) { - if (av_new_packet(pkt, size)) { - ret = AVERROR(EIO); - break; - } + if ((ret = av_new_packet(pkt, size)) < 0) + return ret; + pkt->stream_index = flic->video_stream_index; - pkt->pts = flic->frame_number++; - pkt->pos = avio_tell(pb); + pkt->pos = pos; memcpy(pkt->data, preamble, FLIC_PREAMBLE_SIZE); ret = avio_read(pb, pkt->data + FLIC_PREAMBLE_SIZE, size - FLIC_PREAMBLE_SIZE); if (ret != size - FLIC_PREAMBLE_SIZE) { - av_packet_unref(pkt); ret = AVERROR(EIO); } + pkt->flags = flic->frame_number == 0 ? AV_PKT_FLAG_KEY : 0; + pkt->pts = flic->frame_number; + if (flic->frame_number == 0) + av_add_index_entry(s->streams[flic->video_stream_index], pkt->pos, pkt->pts, pkt->size, 0, AVINDEX_KEYFRAME); packet_read = 1; + flic->frame_number++; } else if (magic == FLIC_TFTD_CHUNK_AUDIO) { - if (av_new_packet(pkt, size)) { - ret = AVERROR(EIO); - break; - } + if ((ret = av_new_packet(pkt, size)) < 0) + return ret; /* skip useless 10B sub-header (yes, it's not accounted for in the chunk header) */ avio_skip(pb, 10); pkt->stream_index = flic->audio_stream_index; - pkt->pos = avio_tell(pb); + pkt->pos = pos; + pkt->flags = AV_PKT_FLAG_KEY; ret = avio_read(pb, pkt->data, size); if (ret != size) { - av_packet_unref(pkt); ret = AVERROR(EIO); + break; } packet_read = 1; @@ -259,11 +260,37 @@ static int flic_read_packet(AVFormatContext *s, return avio_feof(pb) ? AVERROR_EOF : ret; } -AVInputFormat ff_flic_demuxer = { +static int flic_read_seek(AVFormatContext *s, int stream_index, + int64_t pts, int flags) +{ + FlicDemuxContext *flic = s->priv_data; + AVStream *st = s->streams[stream_index]; + int64_t pos, ts; + int index; + + if (!st->internal->index_entries || stream_index != flic->video_stream_index) + return -1; + + index = av_index_search_timestamp(st, pts, flags); + + if (index < 0) + index = av_index_search_timestamp(st, pts, flags ^ AVSEEK_FLAG_BACKWARD); + if (index < 0) + return -1; + + pos = st->internal->index_entries[index].pos; + ts = st->internal->index_entries[index].timestamp; + flic->frame_number = ts; + avio_seek(s->pb, pos, SEEK_SET); + return 0; +} + +const AVInputFormat ff_flic_demuxer = { .name = "flic", .long_name = NULL_IF_CONFIG_SMALL("FLI/FLC/FLX animation"), .priv_data_size = sizeof(FlicDemuxContext), .read_probe = flic_probe, .read_header = flic_read_header, .read_packet = flic_read_packet, + .read_seek = flic_read_seek, };