[FFmpeg-devel] [PATCH] [GSoC v3 7/7] ffplay: fix for unwanted pkts when using abr

Hongcheng Zhong sj.hc_Zhong at sjtu.edu.cn
Sun Aug 23 15:23:55 EEST 2020


From: spartazhc <spartazhc at gmail.com>

HLS use abr may switch streams, ffplay should allow pkt whic same type
(for example: video pkt) but different stream index to queue.

But in the begining, avformat_find_stream_info() will add pkts to
packet_buffer from all streams to find info. This will cause problem
because these unwanted pkts can be added to ffplay's packet_queue now.

The exactly packet number added is depend on stream, but it should be less
than the packet number in the segments which are downloaded during
hls_read_headeri().

So abr_init_duration will be passed to ffplay via abr_initial, pkts
do not needed will be unref as usual.

Signed-off-by: spartazhc <spartazhc at gmail.com>
---
 fftools/ffplay.c | 21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/fftools/ffplay.c b/fftools/ffplay.c
index 30944ba4be..5ec2a8578c 100644
--- a/fftools/ffplay.c
+++ b/fftools/ffplay.c
@@ -2858,6 +2858,7 @@ static int read_thread(void *arg)
     int st_index[AVMEDIA_TYPE_NB];
     AVPacket pkt1, *pkt = &pkt1;
     int64_t stream_start_time;
+    int64_t abr_init_duration = 0;
     int pkt_in_play_range = 0;
     AVDictionaryEntry *t;
     SDL_mutex *wait_mutex = SDL_CreateMutex();
@@ -3018,6 +3019,21 @@ static int read_thread(void *arg)
 
     /* clean packet list filled in hls_read_header if abr is enabled */
     if (abr) {
+        AVDictionary *abr_initial = NULL;
+        AVDictionaryEntry *en = NULL;
+        av_opt_get_dict_val(ic, "abr_initial", AV_OPT_SEARCH_CHILDREN, &abr_initial);
+        en = av_dict_get(abr_initial, "abr_init_duration", NULL, 0);
+        if (en) {
+            if (st_index[AVMEDIA_TYPE_VIDEO] != -1) {
+                abr_init_duration = strtol(en->value, NULL, 10);
+                if (abr_init_duration < 0) {
+                    ret = AVERROR(EINVAL);
+                    goto fail;
+                }
+            }
+            av_log(NULL, AV_LOG_VERBOSE, "[ffplay-abr]: abr_init_duration=%ld\n", abr_init_duration);
+        }
+        av_dict_free(&abr_initial);
         is->abr_list = av_mallocz(sizeof(ABRList));
         if (!is->abr_list) {
             ret = AVERROR(ENOMEM);
@@ -3158,12 +3174,13 @@ static int read_thread(void *arg)
                 av_q2d(ic->streams[pkt->stream_index]->time_base) -
                 (double)(start_time != AV_NOPTS_VALUE ? start_time : 0) / 1000000
                 <= ((double)duration / 1000000);
-        if (abr) {
+        if (abr && pkt_ts >= (stream_start_time + abr_init_duration)) {
+            int test = abr_check_list(is->abr_list, AVMEDIA_TYPE_VIDEO, pkt->stream_index);
             if ((pkt->stream_index == is->audio_stream
                     || abr_check_list(is->abr_list, AVMEDIA_TYPE_AUDIO, pkt->stream_index)) && pkt_in_play_range) {
                 packet_queue_put(&is->audioq, pkt);
             } else if ((pkt->stream_index == is->video_stream
-                    || abr_check_list(is->abr_list, AVMEDIA_TYPE_VIDEO, pkt->stream_index)) && pkt_in_play_range
+                    || (is->video_stream != -1 && abr_check_list(is->abr_list, AVMEDIA_TYPE_VIDEO, pkt->stream_index))) && pkt_in_play_range
                     && !(is->video_st->disposition & AV_DISPOSITION_ATTACHED_PIC)) {
                 packet_queue_put(&is->videoq, pkt);
             } else if ((pkt->stream_index == is->subtitle_stream
-- 
2.28.0



More information about the ffmpeg-devel mailing list