[FFmpeg-devel] avformat/matroskadec.c: Fix support seek to non keyframes

Submitted by Seokjin Hong on Oct. 5, 2018, 1:08 p.m.

Details

Message ID CAF32h+nq6e=78ayX1V7bEEwQ-FeeCAYzb=YDwp=95XW9i5r88A@mail.gmail.com
State New
Headers show

Commit Message

Seokjin Hong Oct. 5, 2018, 1:08 p.m.
Hi.
I finally figured out the reason why all videos on matroska format can't
get last packet.

When I tried to get last video stream packet by seeking, I can't get any
packet.
Please check my example code as below:
// timestamp is bigger than last key_frame timestamp
// for example, if nb_index_entries is equal to 100
// and index_entries[nb_index_entries - 1].timestamp is equal to 1000
// and timestamp is equal to 1010. (please assume that last packet
(non-keyframe) pts is 1040)
av_seek_frame(fmt_ctx, stream_idx, timestamp, AVSEEK_FLAG_ANY |
AVSEEK_FLAG_BACKWORD);
while(av_read_frame(fmt_ctx, &packet) >=0) {
...
}

av_seek_frame works fine, but matroska_read_seek function always sets
'matroska->skip_to_keyframe = 1' without considering 'flags &
AVSEEK_FLAG_ANY'.

After call av_seek_frame(..., AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWORD) and
call av_read_frame, matroska_parse_block function always ends line 3364
(see below)

if (matroska->skip_to_keyframe && track->type !=
MATROSKA_TRACK_TYPE_SUBTITLE) {
    if ((int64_t)timecode < (int64_t)matroska->skip_to_timecode)
        return res; // line 3364
    ...
}

It means that matroska_parse_block can't call matroska_parse_frame.
matroska_parse_frame is important because it manufactures packet and puts
packet in packet list by calling ff_packet_list_put function.

So that, I attached patch to fix this bug.
Please check it.

Regards.


------------------------------------------------------------------------------------------

From 0b35c837ce61d87a4e74865c0d968b258a7c76c3 Mon Sep 17 00:00:00 2001
From: Seokjin Hong <seokjin.hong.kr@gmail.com>
Date: Sun, 2 Sep 2018 21:37:06 +0900
Subject: [PATCH] avformat/matroskadec.c: Fix support seek to non keyframes

---
 libavformat/matroskadec.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

     ff_update_cur_dts(s, st, st->index_entries[index].timestamp);
--
2.17.1

Patch hide | download patch | download mbox

diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index e6793988e1..b66fcec4a5 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -3590,12 +3590,13 @@  static int matroska_read_seek(AVFormatContext *s,
int stream_index,
     matroska->current_id       = 0;
     if (flags & AVSEEK_FLAG_ANY) {
         st->skip_to_keyframe = 0;
+        matroska->skip_to_keyframe = 0;
         matroska->skip_to_timecode = timestamp;
     } else {
         st->skip_to_keyframe = 1;
+        matroska->skip_to_keyframe = 1;
         matroska->skip_to_timecode = st->index_entries[index].timestamp;
     }
-    matroska->skip_to_keyframe = 1;
     matroska->done             = 0;
     matroska->num_levels       = 0;