[FFmpeg-devel] [PATCH] avformat/smacker: Support seeking to first frame

Timotej Lazar timotej.lazar at araneo.si
Wed Jun 17 22:45:39 EEST 2020


Add .read_seek function to the smacker demuxer for the special case of
seeking to ts=0. This is useful because smacker ā€“ like bink, with a
similar implementation ā€“ was mostly used to encode clips in video
games, where random seeks are rare but looping media are common.

Signed-off-by: Timotej Lazar <timotej.lazar at araneo.si>
---
Unlike the existing bink implementation that always rewinds to start,
regardless of arguments to seek(), this will return EINVAL when seeking
to any timestamp other than 0.

I tried to implement random seeking, but the smacker format is not
very amenable to that. While it supports keyframes, most videos I
could find do not use them. Since any video frame can contain an
incremental palette update, it might be necessary to rewind in any
case and decode all frames up to the target timestamp.

This is the first time I dived into ffmpeg, so Iā€™d appreciate any
feedback or suggestions on how to better approach this. Thanks!

 libavformat/smacker.c | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/libavformat/smacker.c b/libavformat/smacker.c
index 8b1e185817..19df8edc67 100644
--- a/libavformat/smacker.c
+++ b/libavformat/smacker.c
@@ -230,7 +230,7 @@ static int smacker_read_header(AVFormatContext *s)
     }
 
     smk->curstream = -1;
-    smk->nextpos = avio_tell(pb);
+    smk->nextpos = s->internal->data_offset = avio_tell(pb);
 
     return 0;
 }
@@ -373,6 +373,27 @@ static int smacker_read_close(AVFormatContext *s)
     return 0;
 }
 
+static int smacker_read_seek(AVFormatContext *s, int stream_index,
+                             int64_t timestamp, int flags)
+{
+    SmackerContext *smk = s->priv_data;
+
+    /* 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");
+        return AVERROR(EINVAL);
+    }
+
+    smk->cur_frame = 0;
+    smk->curstream = -1;
+    smk->nextpos = s->internal->data_offset;
+    memset(smk->pal, 0, sizeof(smk->pal));
+    memset(smk->aud_pts, 0, sizeof(smk->aud_pts));
+
+    return 0;
+}
+
 AVInputFormat ff_smacker_demuxer = {
     .name           = "smk",
     .long_name      = NULL_IF_CONFIG_SMALL("Smacker"),
@@ -381,4 +402,5 @@ AVInputFormat ff_smacker_demuxer = {
     .read_header    = smacker_read_header,
     .read_packet    = smacker_read_packet,
     .read_close     = smacker_read_close,
+    .read_seek      = smacker_read_seek,
 };
-- 
2.26.2



More information about the ffmpeg-devel mailing list