[FFmpeg-devel] [PATCH] avformat/hls: fix seek accuracy problem

mymoeyard at gmail.com mymoeyard at gmail.com
Tue Jan 2 12:28:25 EET 2018


From: Wu Zhiqiang <mymoeyard at gmail.com>

HLS demuxer seeking use dts instead of pts.
Demuxer skip some frame when dts is before pts in special case.
And it is impossible to re-seek back to start time after playing.
---
 libavformat/hls.c | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/libavformat/hls.c b/libavformat/hls.c
index 950cc4c3bd..069e7b06e9 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -2086,6 +2086,7 @@ static int hls_read_packet(AVFormatContext *s, AVPacket *pkt)
          * stream */
         if (pls->needed && !pls->pkt.data) {
             while (1) {
+                int64_t pkt_ts;
                 int64_t ts_diff;
                 AVRational tb;
                 ret = av_read_frame(pls->ctx, &pls->pkt);
@@ -2101,9 +2102,17 @@ static int hls_read_packet(AVFormatContext *s, AVPacket *pkt)
                         fill_timing_for_id3_timestamped_stream(pls);
                     }
 
+                    if (pls->pkt.pts != AV_NOPTS_VALUE)
+                        pkt_ts =  pls->pkt.pts;
+                    else if (pls->pkt.dts != AV_NOPTS_VALUE)
+                        pkt_ts =  pls->pkt.dts;
+                    else
+                        pkt_ts = AV_NOPTS_VALUE;
+
+
                     if (c->first_timestamp == AV_NOPTS_VALUE &&
-                        pls->pkt.dts       != AV_NOPTS_VALUE)
-                        c->first_timestamp = av_rescale_q(pls->pkt.dts,
+                        pkt_ts       != AV_NOPTS_VALUE)
+                        c->first_timestamp = av_rescale_q(pkt_ts,
                             get_timebase(pls), AV_TIME_BASE_Q);
                 }
 
@@ -2113,15 +2122,16 @@ static int hls_read_packet(AVFormatContext *s, AVPacket *pkt)
                 if (pls->seek_stream_index < 0 ||
                     pls->seek_stream_index == pls->pkt.stream_index) {
 
-                    if (pls->pkt.dts == AV_NOPTS_VALUE) {
+                    if (pkt_ts == AV_NOPTS_VALUE) {
                         pls->seek_timestamp = AV_NOPTS_VALUE;
                         break;
                     }
 
                     tb = get_timebase(pls);
-                    ts_diff = av_rescale_rnd(pls->pkt.dts, AV_TIME_BASE,
+                    ts_diff = av_rescale_rnd(pkt_ts, AV_TIME_BASE,
                                             tb.den, AV_ROUND_DOWN) -
                             pls->seek_timestamp;
+
                     if (ts_diff >= 0 && (pls->seek_flags  & AVSEEK_FLAG_ANY ||
                                         pls->pkt.flags & AV_PKT_FLAG_KEY)) {
                         pls->seek_timestamp = AV_NOPTS_VALUE;
-- 
2.15.0



More information about the ffmpeg-devel mailing list