PR #22951 opened by Link Mauve (linkmauve)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22951
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22951.patch

This lets us seek in the video properly, based on the table at the end of the 
files, and has been tested with [Suikoden 
Tierkreis](https://en.wikipedia.org/wiki/Suikoden_Tierkreis) videos.

While at it I’ve also set the duration of the stream, this makes the progress 
bar work correctly in mpv.


From cc0264a1b5c057dd32031f9fbea469991aa3f47e Mon Sep 17 00:00:00 2001
From: Link Mauve <[email protected]>
Date: Tue, 28 Apr 2026 17:49:25 +0200
Subject: [PATCH] avformat/mods: Parse the index entries
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This lets us seek in the video properly, based on the table at the end
of the files, and has been tested with Suikoden Tierkreis videos.

While at it I’ve also set the duration of the stream, this makes the
progress bar work correctly in mpv.
---
 libavformat/mods.c | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/libavformat/mods.c b/libavformat/mods.c
index 7f76124821..2bfea62559 100644
--- a/libavformat/mods.c
+++ b/libavformat/mods.c
@@ -3,6 +3,7 @@
  * Copyright (c) 2015-2016 Florian Nouwt
  * Copyright (c) 2017 Adib Surani
  * Copyright (c) 2020 Paul B Mahol
+ * Copyright (c) 2026 Link Mauve
  *
  * This file is part of FFmpeg.
  *
@@ -45,6 +46,9 @@ static int mods_read_header(AVFormatContext *s)
     AVIOContext *pb = s->pb;
     AVRational fps;
     int64_t pos;
+    int64_t timestamp;
+    int num_keyframes;
+    const AVIndexEntry *e;
 
     AVStream *st = avformat_new_stream(s, NULL);
     if (!st)
@@ -53,6 +57,7 @@ static int mods_read_header(AVFormatContext *s)
     avio_skip(pb, 8);
 
     st->nb_frames            = avio_rl32(pb);
+    st->duration             = st->nb_frames;
     st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
     st->codecpar->codec_id   = AV_CODEC_ID_MOBICLIP;
     st->codecpar->width      = avio_rl32(pb);
@@ -64,11 +69,22 @@ static int mods_read_header(AVFormatContext *s)
 
     avio_skip(pb, 16);
 
-    pos = avio_rl32(pb) + 4;
-    avio_seek(pb, pos, SEEK_SET);
     pos = avio_rl32(pb);
+    num_keyframes = avio_rl32(pb);
     avio_seek(pb, pos, SEEK_SET);
 
+    for (int i = 0; i < num_keyframes; ++i) {
+        timestamp = avio_rl32(pb);
+        pos = avio_rl32(pb);
+        av_add_index_entry(st, pos, timestamp, 0, 0, AVINDEX_KEYFRAME);
+    }
+
+    e = avformat_index_get_entry(st, 0);
+    if (!e)
+        return AVERROR(EINVAL);
+
+    avio_seek(pb, e->pos, SEEK_SET);
+
     return 0;
 }
 
@@ -87,7 +103,6 @@ static int mods_read_packet(AVFormatContext *s, AVPacket 
*pkt)
     ret = av_get_packet(pb, pkt, size);
     pkt->pos = pos;
     pkt->stream_index = 0;
-    pkt->flags |= AV_PKT_FLAG_KEY;
 
     return ret;
 }
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to