]> git.sesse.net Git - ffmpeg/commitdiff
dashdec: Search for segment timeline inside AdaptionSets too
authorsfan5 <sfan5@live.de>
Sun, 14 Jan 2018 14:35:31 +0000 (22:35 +0800)
committerSteven Liu <lq@chinaffmpeg.org>
Sun, 14 Jan 2018 14:35:31 +0000 (22:35 +0800)
libavformat/dashdec.c

index 0ac3c6778591841323e02de126411e5453b155f1..f1012d51b5b5426f700f5a54af97baf75b7388b5 100644 (file)
@@ -648,7 +648,8 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url,
                                          xmlNodePtr period_baseurl_node,
                                          xmlNodePtr fragment_template_node,
                                          xmlNodePtr content_component_node,
-                                         xmlNodePtr adaptionset_baseurl_node)
+                                         xmlNodePtr adaptionset_baseurl_node,
+                                         xmlNodePtr adaptionset_segmentlist_node)
 {
     int32_t ret = 0;
     int32_t audio_rep_idx = 0;
@@ -659,8 +660,9 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url,
     xmlNodePtr representation_segmenttemplate_node = NULL;
     xmlNodePtr representation_baseurl_node = NULL;
     xmlNodePtr representation_segmentlist_node = NULL;
+    xmlNodePtr segmentlists_tab[2];
     xmlNodePtr fragment_timeline_node = NULL;
-    xmlNodePtr fragment_templates_tab[2];
+    xmlNodePtr fragment_templates_tab[3];
     char *duration_val = NULL;
     char *presentation_timeoffset_val = NULL;
     char *startnumber_val = NULL;
@@ -703,14 +705,15 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url,
         if (representation_segmenttemplate_node || fragment_template_node) {
             fragment_timeline_node = NULL;
             fragment_templates_tab[0] = representation_segmenttemplate_node;
-            fragment_templates_tab[1] = fragment_template_node;
+            fragment_templates_tab[1] = adaptionset_segmentlist_node;
+            fragment_templates_tab[2] = fragment_template_node;
 
-            presentation_timeoffset_val = get_val_from_nodes_tab(fragment_templates_tab, 2, "presentationTimeOffset");
-            duration_val = get_val_from_nodes_tab(fragment_templates_tab, 2, "duration");
-            startnumber_val = get_val_from_nodes_tab(fragment_templates_tab, 2, "startNumber");
-            timescale_val = get_val_from_nodes_tab(fragment_templates_tab, 2, "timescale");
-            initialization_val = get_val_from_nodes_tab(fragment_templates_tab, 2, "initialization");
-            media_val = get_val_from_nodes_tab(fragment_templates_tab, 2, "media");
+            presentation_timeoffset_val = get_val_from_nodes_tab(fragment_templates_tab, 3, "presentationTimeOffset");
+            duration_val = get_val_from_nodes_tab(fragment_templates_tab, 3, "duration");
+            startnumber_val = get_val_from_nodes_tab(fragment_templates_tab, 3, "startNumber");
+            timescale_val = get_val_from_nodes_tab(fragment_templates_tab, 3, "timescale");
+            initialization_val = get_val_from_nodes_tab(fragment_templates_tab, 3, "initialization");
+            media_val = get_val_from_nodes_tab(fragment_templates_tab, 3, "media");
 
             if (initialization_val) {
                 rep->init_section = av_mallocz(sizeof(struct fragment));
@@ -756,6 +759,8 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url,
 
             if (!fragment_timeline_node)
                 fragment_timeline_node = find_child_node_by_name(fragment_template_node, "SegmentTimeline");
+            if (!fragment_timeline_node)
+                fragment_timeline_node = find_child_node_by_name(adaptionset_segmentlist_node, "SegmentTimeline");
             if (fragment_timeline_node) {
                 fragment_timeline_node = xmlFirstElementChild(fragment_timeline_node);
                 while (fragment_timeline_node) {
@@ -784,8 +789,11 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url,
             // TODO: https://www.brendanlong.com/the-structure-of-an-mpeg-dash-mpd.html
             // http://www-itec.uni-klu.ac.at/dash/ddash/mpdGenerator.php?fragmentlength=15&type=full
             xmlNodePtr fragmenturl_node = NULL;
-            duration_val = xmlGetProp(representation_segmentlist_node, "duration");
-            timescale_val = xmlGetProp(representation_segmentlist_node, "timescale");
+            segmentlists_tab[0] = representation_segmentlist_node;
+            segmentlists_tab[1] = adaptionset_segmentlist_node;
+
+            duration_val = get_val_from_nodes_tab(segmentlists_tab, 2, "duration");
+            timescale_val = get_val_from_nodes_tab(segmentlists_tab, 2, "timescale");
             if (duration_val) {
                 rep->fragment_duration = (int64_t) strtoll(duration_val, NULL, 10);
                 xmlFree(duration_val);
@@ -810,6 +818,8 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url,
 
             if (!fragment_timeline_node)
                 fragment_timeline_node = find_child_node_by_name(fragment_template_node, "SegmentTimeline");
+            if (!fragment_timeline_node)
+                fragment_timeline_node = find_child_node_by_name(adaptionset_segmentlist_node, "SegmentTimeline");
             if (fragment_timeline_node) {
                 fragment_timeline_node = xmlFirstElementChild(fragment_timeline_node);
                 while (fragment_timeline_node) {
@@ -862,6 +872,7 @@ static int parse_manifest_adaptationset(AVFormatContext *s, const char *url,
     xmlNodePtr fragment_template_node = NULL;
     xmlNodePtr content_component_node = NULL;
     xmlNodePtr adaptionset_baseurl_node = NULL;
+    xmlNodePtr adaptionset_segmentlist_node = NULL;
     xmlNodePtr node = NULL;
 
     node = xmlFirstElementChild(adaptionset_node);
@@ -872,6 +883,8 @@ static int parse_manifest_adaptationset(AVFormatContext *s, const char *url,
             content_component_node = node;
         } else if (!av_strcasecmp(node->name, (const char *)"BaseURL")) {
             adaptionset_baseurl_node = node;
+        } else if (!av_strcasecmp(node->name, (const char *)"SegmentList")) {
+            adaptionset_segmentlist_node = node;
         } else if (!av_strcasecmp(node->name, (const char *)"Representation")) {
             ret = parse_manifest_representation(s, url, node,
                                                 adaptionset_node,
@@ -879,7 +892,8 @@ static int parse_manifest_adaptationset(AVFormatContext *s, const char *url,
                                                 period_baseurl_node,
                                                 fragment_template_node,
                                                 content_component_node,
-                                                adaptionset_baseurl_node);
+                                                adaptionset_baseurl_node,
+                                                adaptionset_segmentlist_node);
             if (ret < 0) {
                 return ret;
             }
@@ -1863,7 +1877,7 @@ set_seq_num:
     } else if (pls->fragment_duration > 0) {
         pls->cur_seq_no = pls->first_seq_no + ((seek_pos_msec * pls->fragment_timescale) / pls->fragment_duration) / 1000;
     } else {
-        av_log(pls->parent, AV_LOG_ERROR, "dash_seek missing fragment_duration\n");
+        av_log(pls->parent, AV_LOG_ERROR, "dash_seek missing timeline or fragment_duration\n");
         pls->cur_seq_no = pls->first_seq_no;
     }
     pls->cur_timestamp = 0;