[FFmpeg-devel,v2] avformat/dashdec: control download speed when in live stream mode

Submitted by Steven Liu on Jan. 11, 2019, 3:45 a.m.

Details

Message ID 20190111034555.59758-1-lq@chinaffmpeg.org
State New
Headers show

Commit Message

Steven Liu Jan. 11, 2019, 3:45 a.m.
fix ticket: 7369
check the duration is less than the fragment duration,
retry when the condition is true.
don't control the download speed when reading header

Signed-off-by: Steven Liu <lq@chinaffmpeg.org>
---
 libavformat/dashdec.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

Patch hide | download patch | download mbox

diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c
index f4f4e935de..473adb9bfb 100644
--- a/libavformat/dashdec.c
+++ b/libavformat/dashdec.c
@@ -108,6 +108,7 @@  struct representation {
     int64_t cur_seg_offset;
     int64_t cur_seg_size;
     struct fragment *cur_seg;
+    int64_t last_load_time;
 
     /* Currently active Media Initialization Section */
     struct fragment *init_section;
@@ -121,6 +122,9 @@  struct representation {
 
 typedef struct DASHContext {
     const AVClass *class;
+
+    int read_init_sections;
+
     char *base_url;
     char *adaptionset_contenttype_val;
     char *adaptionset_par_val;
@@ -1084,6 +1088,8 @@  static int parse_manifest_representation(AVFormatContext *s, const char *url,
         }
     }
 
+    if (rep)
+        rep->last_load_time = get_current_time_in_sec();
     video_rep_idx += type == AVMEDIA_TYPE_VIDEO;
     audio_rep_idx += type == AVMEDIA_TYPE_AUDIO;
     subtitle_rep_idx += type == AVMEDIA_TYPE_SUBTITLE;
@@ -1382,6 +1388,9 @@  static int64_t calc_cur_seg_no(AVFormatContext *s, struct representation *pls)
     } else {
         num = pls->first_seq_no;
     }
+
+    if (pls)
+        pls->last_load_time = get_current_time_in_sec();
     return num;
 }
 
@@ -1461,6 +1470,7 @@  static int refresh_manifest(AVFormatContext *s)
 {
 
     int ret = 0, i;
+    int64_t cur_time = get_current_time_in_sec();
     DASHContext *c = s->priv_data;
 
     // save current context
@@ -1505,6 +1515,11 @@  static int refresh_manifest(AVFormatContext *s)
     for (i = 0; i < n_videos; i++) {
         struct representation *cur_video = videos[i];
         struct representation *ccur_video = c->videos[i];
+        if (cur_video)
+            cur_video->last_load_time = cur_time;
+        if (ccur_video)
+            ccur_video->last_load_time = cur_time;
+
         if (cur_video->timelines) {
             // calc current time
             int64_t currentTime = get_segment_start_time_based_on_timeline(cur_video, cur_video->cur_seq_no) / cur_video->fragment_timescale;
@@ -1521,6 +1536,11 @@  static int refresh_manifest(AVFormatContext *s)
     for (i = 0; i < n_audios; i++) {
         struct representation *cur_audio = audios[i];
         struct representation *ccur_audio = c->audios[i];
+        if (cur_audio)
+            cur_audio->last_load_time = cur_time;
+        if (ccur_audio)
+            ccur_audio->last_load_time = cur_time;
+
         if (cur_audio->timelines) {
             // calc current time
             int64_t currentTime = get_segment_start_time_based_on_timeline(cur_audio, cur_audio->cur_seq_no) / cur_audio->fragment_timescale;
@@ -1629,6 +1649,8 @@  static struct fragment *get_current_fragment(struct representation *pls)
         av_free(tmpfilename);
         seg->size = -1;
     }
+    if (pls)
+        pls->last_load_time = get_current_time_in_sec();
 
     return seg;
 }
@@ -1747,6 +1769,11 @@  static int read_data(void *opaque, uint8_t *buf, int buf_size)
     DASHContext *c = v->parent->priv_data;
 
 restart:
+    if (!c->read_init_sections && c->is_live && v->fragment_duration != 0 && v->fragment_timescale != 0)
+        if (get_current_time_in_sec() - v->last_load_time < (v->fragment_duration / v->fragment_timescale)) {
+            av_usleep(100*1000);
+            goto restart;
+        }
     if (!v->input) {
         free_fragment(&v->cur_seg);
         v->cur_seg = get_current_fragment(v);
@@ -2002,6 +2029,7 @@  static int dash_read_header(AVFormatContext *s)
 
     av_dict_set(&c->avio_opts, "seekable", "0", 0);
 
+    c->read_init_sections = 1;
     if ((ret = parse_manifest(s, s->url, s->pb)) < 0)
         goto fail;
 
@@ -2146,6 +2174,7 @@  static int dash_read_packet(AVFormatContext *s, AVPacket *pkt)
     recheck_discard_flags(s, c->audios, c->n_audios);
     recheck_discard_flags(s, c->subtitles, c->n_subtitles);
 
+    c->read_init_sections = 0;
     for (i = 0; i < c->n_videos; i++) {
         struct representation *pls = c->videos[i];
         if (!pls->ctx)