]> git.sesse.net Git - ffmpeg/commitdiff
avformat/hlsenc: compute video_keyframe_size after write keyframe
authorSteven Liu <lq@chinaffmpeg.org>
Fri, 18 Sep 2020 01:53:27 +0000 (09:53 +0800)
committerliuqi05 <liuqi05@kuaishou.com>
Tue, 20 Oct 2020 03:41:44 +0000 (11:41 +0800)
fix ticket: 8636
When write keyframe and the keyframe is the frist packet of the segment,
then compute the size of the keyframe which have been write into segment
first packet. and set the start position of the segment, should not use
avio_tell(vs->out) to get the keyframe position, because it can be set
to 0 if close at above of the workflow, that maybe inaccurate, but the
start_pos can be used here, because start_pos is set after write
the previous packet.

Signed-off-by: Steven Liu <lq@chinaffmpeg.org>
Signed-off-by: liuqi05 <liuqi05@kuaishou.com>
libavformat/hlsenc.c

index 4471858222e5ec9636dacb6af5b5a53b0c1ef460..f7eb2411b0750e3308939691d2844527fde6898a 100644 (file)
@@ -2572,13 +2572,14 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
 
     vs->packets_written++;
     if (oc->pb) {
+        int64_t keyframe_pre_pos = avio_tell(oc->pb);
         ret = ff_write_chained(oc, stream_index, pkt, s, 0);
-        vs->video_keyframe_size += pkt->size;
-        if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) && (pkt->flags & AV_PKT_FLAG_KEY)) {
-            vs->video_keyframe_size = avio_tell(oc->pb);
-        } else {
-            vs->video_keyframe_pos = avio_tell(vs->out);
+        if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) &&
+            (pkt->flags & AV_PKT_FLAG_KEY) && !keyframe_pre_pos) {
+            av_write_frame(oc, NULL); /* Flush any buffered data */
+            vs->video_keyframe_size = avio_tell(oc->pb) - keyframe_pre_pos;
         }
+        vs->video_keyframe_pos = vs->start_pos;
         if (hls->ignore_io_errors)
             ret = 0;
     }