aboutsummaryrefslogtreecommitdiffstats
path: root/libavformat
diff options
context:
space:
mode:
authorPaul B Mahol <onemda@gmail.com>2022-04-06 22:25:05 +0200
committerPaul B Mahol <onemda@gmail.com>2022-04-08 10:02:33 +0200
commit9d20f64f9c511302bb6f827206798c343a8c1ea2 (patch)
treeb6292043d577f3782f5b5bffdc6afa4ac71b8a8e /libavformat
parentb2dd3e844d9e4d16cdd336157e07d3b2c9240017 (diff)
downloadffmpeg-9d20f64f9c511302bb6f827206798c343a8c1ea2.tar.gz
avformat/smacker: add better seeking support
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/smacker.c35
1 files changed, 26 insertions, 9 deletions
diff --git a/libavformat/smacker.c b/libavformat/smacker.c
index 80d36f2f40..eac50040d7 100644
--- a/libavformat/smacker.c
+++ b/libavformat/smacker.c
@@ -94,6 +94,7 @@ static int smacker_read_header(AVFormatContext *s)
AVStream *st;
AVCodecParameters *par;
uint32_t magic, width, height, flags, treesize;
+ int64_t pos;
int i, ret, pts_inc;
int tbase;
@@ -211,8 +212,13 @@ static int smacker_read_header(AVFormatContext *s)
smk->frm_flags = (void*)(smk->frm_size + smk->frames);
/* read frame info */
+ pos = 0;
for (i = 0; i < smk->frames; i++) {
smk->frm_size[i] = avio_rl32(pb);
+ if ((ret = av_add_index_entry(st, pos, i, smk->frm_size[i], 0,
+ (i == 0 || (smk->frm_size[i] & 1)) ? AVINDEX_KEYFRAME : 0)) < 0)
+ return ret;
+ pos += smk->frm_size[i];
}
if ((ret = ffio_read_size(pb, smk->frm_flags, smk->frames)) < 0 ||
/* load trees to extradata, they will be unpacked by decoder */
@@ -335,7 +341,7 @@ static int smacker_read_packet(AVFormatContext *s, AVPacket *pkt)
if ((ret = av_new_packet(pkt, smk->frame_size + 769)) < 0)
goto next_frame;
flags = smk->new_palette;
- if (smk->frm_size[smk->cur_frame] & 1)
+ if ((smk->frm_size[smk->cur_frame] & 1) || smk->cur_frame == 0)
flags |= 2;
pkt->data[0] = flags;
memcpy(pkt->data + 1, smk->pal, 768);
@@ -344,6 +350,9 @@ static int smacker_read_packet(AVFormatContext *s, AVPacket *pkt)
goto next_frame;
pkt->stream_index = smk->videoindex;
pkt->pts = smk->cur_frame;
+ pkt->duration = 1;
+ if (flags & 2)
+ pkt->flags |= AV_PKT_FLAG_KEY;
smk->next_audio_index = 0;
smk->new_palette = 0;
smk->cur_frame++;
@@ -359,20 +368,28 @@ next_frame:
static int smacker_read_seek(AVFormatContext *s, int stream_index,
int64_t timestamp, int flags)
{
+ AVStream *st = s->streams[stream_index];
SmackerContext *smk = s->priv_data;
- int64_t ret;
+ int64_t pos;
+ int ret;
- /* only rewinding to start is supported */
- if (timestamp != 0) {
- av_log(s, AV_LOG_ERROR,
- "Random seeks are not supported (can only seek to start).\n");
+ if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL))
+ return -1;
+
+ if (timestamp < 0 || timestamp >= smk->frames)
return AVERROR(EINVAL);
- }
- if ((ret = avio_seek(s->pb, ffformatcontext(s)->data_offset, SEEK_SET)) < 0)
+ ret = av_index_search_timestamp(st, timestamp, flags);
+ if (ret < 0)
return ret;
- smk->cur_frame = 0;
+ pos = ffformatcontext(s)->data_offset;
+ pos += ffstream(st)->index_entries[ret].pos;
+ pos = avio_seek(s->pb, pos, SEEK_SET);
+ if (pos < 0)
+ return pos;
+
+ smk->cur_frame = ret;
smk->next_audio_index = 0;
smk->new_palette = 0;
memset(smk->pal, 0, sizeof(smk->pal));