c710e567278bbc5c681dd12e37bfdea0e5e4a675
[ffmpeg.git] / libavformat / dashdec.c
1 /*
2  * Dynamic Adaptive Streaming over HTTP demux
3  * Copyright (c) 2017 samsamsam@o2.pl based on HLS demux
4  * Copyright (c) 2017 Steven Liu
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 #include <libxml/parser.h>
23 #include "libavutil/intreadwrite.h"
24 #include "libavutil/opt.h"
25 #include "libavutil/time.h"
26 #include "libavutil/parseutils.h"
27 #include "internal.h"
28 #include "avio_internal.h"
29 #include "dash.h"
30
31 #define INITIAL_BUFFER_SIZE 32768
32
33 struct fragment {
34     int64_t url_offset;
35     int64_t size;
36     char *url;
37 };
38
39 /*
40  * reference to : ISO_IEC_23009-1-DASH-2012
41  * Section: 5.3.9.6.2
42  * Table: Table 17 — Semantics of SegmentTimeline element
43  * */
44 struct timeline {
45     /* starttime: Element or Attribute Name
46      * specifies the MPD start time, in @timescale units,
47      * the first Segment in the series starts relative to the beginning of the Period.
48      * The value of this attribute must be equal to or greater than the sum of the previous S
49      * element earliest presentation time and the sum of the contiguous Segment durations.
50      * If the value of the attribute is greater than what is expressed by the previous S element,
51      * it expresses discontinuities in the timeline.
52      * If not present then the value shall be assumed to be zero for the first S element
53      * and for the subsequent S elements, the value shall be assumed to be the sum of
54      * the previous S element's earliest presentation time and contiguous duration
55      * (i.e. previous S@starttime + @duration * (@repeat + 1)).
56      * */
57     int64_t starttime;
58     /* repeat: Element or Attribute Name
59      * specifies the repeat count of the number of following contiguous Segments with
60      * the same duration expressed by the value of @duration. This value is zero-based
61      * (e.g. a value of three means four Segments in the contiguous series).
62      * */
63     int64_t repeat;
64     /* duration: Element or Attribute Name
65      * specifies the Segment duration, in units of the value of the @timescale.
66      * */
67     int64_t duration;
68 };
69
70 /*
71  * Each playlist has its own demuxer. If it is currently active,
72  * it has an opened AVIOContext too, and potentially an AVPacket
73  * containing the next packet from this stream.
74  */
75 struct representation {
76     char *url_template;
77     AVIOContext pb;
78     AVIOContext *input;
79     AVFormatContext *parent;
80     AVFormatContext *ctx;
81     AVPacket pkt;
82     int rep_idx;
83     int rep_count;
84     int stream_index;
85
86     enum AVMediaType type;
87     char id[20];
88     int bandwidth;
89     AVRational framerate;
90     AVStream *assoc_stream; /* demuxer stream associated with this representation */
91
92     int n_fragments;
93     struct fragment **fragments; /* VOD list of fragment for profile */
94
95     int n_timelines;
96     struct timeline **timelines;
97
98     int64_t first_seq_no;
99     int64_t last_seq_no;
100     int64_t start_number; /* used in case when we have dynamic list of segment to know which segments are new one*/
101
102     int64_t fragment_duration;
103     int64_t fragment_timescale;
104
105     int64_t presentation_timeoffset;
106
107     int64_t cur_seq_no;
108     int64_t cur_seg_offset;
109     int64_t cur_seg_size;
110     struct fragment *cur_seg;
111
112     /* Currently active Media Initialization Section */
113     struct fragment *init_section;
114     uint8_t *init_sec_buf;
115     uint32_t init_sec_buf_size;
116     uint32_t init_sec_data_len;
117     uint32_t init_sec_buf_read_offset;
118     int64_t cur_timestamp;
119     int is_restart_needed;
120 };
121
122 typedef struct DASHContext {
123     const AVClass *class;
124     char *base_url;
125
126     int n_videos;
127     struct representation **videos;
128     int n_audios;
129     struct representation **audios;
130
131     /* MediaPresentationDescription Attribute */
132     uint64_t media_presentation_duration;
133     uint64_t suggested_presentation_delay;
134     uint64_t availability_start_time;
135     uint64_t publish_time;
136     uint64_t minimum_update_period;
137     uint64_t time_shift_buffer_depth;
138     uint64_t min_buffer_time;
139
140     /* Period Attribute */
141     uint64_t period_duration;
142     uint64_t period_start;
143
144     int is_live;
145     AVIOInterruptCB *interrupt_callback;
146     char *user_agent;                    ///< holds HTTP user agent set as an AVOption to the HTTP protocol context
147     char *cookies;                       ///< holds HTTP cookie values set in either the initial response or as an AVOption to the HTTP protocol context
148     char *headers;                       ///< holds HTTP headers set as an AVOption to the HTTP protocol context
149     char *allowed_extensions;
150     AVDictionary *avio_opts;
151     int max_url_size;
152
153     /* Flags for init section*/
154     int is_init_section_common_video;
155     int is_init_section_common_audio;
156
157 } DASHContext;
158
159 static int ishttp(char *url)
160 {
161     const char *proto_name = avio_find_protocol_name(url);
162     return av_strstart(proto_name, "http", NULL);
163 }
164
165 static int aligned(int val)
166 {
167     return ((val + 0x3F) >> 6) << 6;
168 }
169
170 static uint64_t get_current_time_in_sec(void)
171 {
172     return  av_gettime() / 1000000;
173 }
174
175 static uint64_t get_utc_date_time_insec(AVFormatContext *s, const char *datetime)
176 {
177     struct tm timeinfo;
178     int year = 0;
179     int month = 0;
180     int day = 0;
181     int hour = 0;
182     int minute = 0;
183     int ret = 0;
184     float second = 0.0;
185
186     /* ISO-8601 date parser */
187     if (!datetime)
188         return 0;
189
190     ret = sscanf(datetime, "%d-%d-%dT%d:%d:%fZ", &year, &month, &day, &hour, &minute, &second);
191     /* year, month, day, hour, minute, second  6 arguments */
192     if (ret != 6) {
193         av_log(s, AV_LOG_WARNING, "get_utc_date_time_insec get a wrong time format\n");
194     }
195     timeinfo.tm_year = year - 1900;
196     timeinfo.tm_mon  = month - 1;
197     timeinfo.tm_mday = day;
198     timeinfo.tm_hour = hour;
199     timeinfo.tm_min  = minute;
200     timeinfo.tm_sec  = (int)second;
201
202     return av_timegm(&timeinfo);
203 }
204
205 static uint32_t get_duration_insec(AVFormatContext *s, const char *duration)
206 {
207     /* ISO-8601 duration parser */
208     uint32_t days = 0;
209     uint32_t hours = 0;
210     uint32_t mins = 0;
211     uint32_t secs = 0;
212     int size = 0;
213     float value = 0;
214     char type = '\0';
215     const char *ptr = duration;
216
217     while (*ptr) {
218         if (*ptr == 'P' || *ptr == 'T') {
219             ptr++;
220             continue;
221         }
222
223         if (sscanf(ptr, "%f%c%n", &value, &type, &size) != 2) {
224             av_log(s, AV_LOG_WARNING, "get_duration_insec get a wrong time format\n");
225             return 0; /* parser error */
226         }
227         switch (type) {
228             case 'D':
229                 days = (uint32_t)value;
230                 break;
231             case 'H':
232                 hours = (uint32_t)value;
233                 break;
234             case 'M':
235                 mins = (uint32_t)value;
236                 break;
237             case 'S':
238                 secs = (uint32_t)value;
239                 break;
240             default:
241                 // handle invalid type
242                 break;
243         }
244         ptr += size;
245     }
246     return  ((days * 24 + hours) * 60 + mins) * 60 + secs;
247 }
248
249 static int64_t get_segment_start_time_based_on_timeline(struct representation *pls, int64_t cur_seq_no)
250 {
251     int64_t start_time = 0;
252     int64_t i = 0;
253     int64_t j = 0;
254     int64_t num = 0;
255
256     if (pls->n_timelines) {
257         for (i = 0; i < pls->n_timelines; i++) {
258             if (pls->timelines[i]->starttime > 0) {
259                 start_time = pls->timelines[i]->starttime;
260             }
261             if (num == cur_seq_no)
262                 goto finish;
263
264             start_time += pls->timelines[i]->duration;
265             for (j = 0; j < pls->timelines[i]->repeat; j++) {
266                 num++;
267                 if (num == cur_seq_no)
268                     goto finish;
269                 start_time += pls->timelines[i]->duration;
270             }
271             num++;
272         }
273     }
274 finish:
275     return start_time;
276 }
277
278 static int64_t calc_next_seg_no_from_timelines(struct representation *pls, int64_t cur_time)
279 {
280     int64_t i = 0;
281     int64_t j = 0;
282     int64_t num = 0;
283     int64_t start_time = 0;
284
285     for (i = 0; i < pls->n_timelines; i++) {
286         if (pls->timelines[i]->starttime > 0) {
287             start_time = pls->timelines[i]->starttime;
288         }
289         if (start_time > cur_time)
290             goto finish;
291
292         start_time += pls->timelines[i]->duration;
293         for (j = 0; j < pls->timelines[i]->repeat; j++) {
294             num++;
295             if (start_time > cur_time)
296                 goto finish;
297             start_time += pls->timelines[i]->duration;
298         }
299         num++;
300     }
301
302     return -1;
303
304 finish:
305     return num;
306 }
307
308 static void free_fragment(struct fragment **seg)
309 {
310     if (!(*seg)) {
311         return;
312     }
313     av_freep(&(*seg)->url);
314     av_freep(seg);
315 }
316
317 static void free_fragment_list(struct representation *pls)
318 {
319     int i;
320
321     for (i = 0; i < pls->n_fragments; i++) {
322         free_fragment(&pls->fragments[i]);
323     }
324     av_freep(&pls->fragments);
325     pls->n_fragments = 0;
326 }
327
328 static void free_timelines_list(struct representation *pls)
329 {
330     int i;
331
332     for (i = 0; i < pls->n_timelines; i++) {
333         av_freep(&pls->timelines[i]);
334     }
335     av_freep(&pls->timelines);
336     pls->n_timelines = 0;
337 }
338
339 static void free_representation(struct representation *pls)
340 {
341     free_fragment_list(pls);
342     free_timelines_list(pls);
343     free_fragment(&pls->cur_seg);
344     free_fragment(&pls->init_section);
345     av_freep(&pls->init_sec_buf);
346     av_freep(&pls->pb.buffer);
347     if (pls->input)
348         ff_format_io_close(pls->parent, &pls->input);
349     if (pls->ctx) {
350         pls->ctx->pb = NULL;
351         avformat_close_input(&pls->ctx);
352     }
353
354     av_freep(&pls->url_template);
355     av_freep(&pls);
356 }
357
358 static void free_video_list(DASHContext *c)
359 {
360     int i;
361     for (i = 0; i < c->n_videos; i++) {
362         struct representation *pls = c->videos[i];
363         free_representation(pls);
364     }
365     av_freep(&c->videos);
366     c->n_videos = 0;
367 }
368
369 static void free_audio_list(DASHContext *c)
370 {
371     int i;
372     for (i = 0; i < c->n_audios; i++) {
373         struct representation *pls = c->audios[i];
374         free_representation(pls);
375     }
376     av_freep(&c->audios);
377     c->n_audios = 0;
378 }
379
380 static void set_httpheader_options(DASHContext *c, AVDictionary **opts)
381 {
382     // broker prior HTTP options that should be consistent across requests
383     av_dict_set(opts, "user_agent", c->user_agent, 0);
384     av_dict_set(opts, "cookies", c->cookies, 0);
385     av_dict_set(opts, "headers", c->headers, 0);
386     if (c->is_live) {
387         av_dict_set(opts, "seekable", "0", 0);
388     }
389 }
390 static void update_options(char **dest, const char *name, void *src)
391 {
392     av_freep(dest);
393     av_opt_get(src, name, AV_OPT_SEARCH_CHILDREN, (uint8_t**)dest);
394     if (*dest)
395         av_freep(dest);
396 }
397
398 static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url,
399                     AVDictionary *opts, AVDictionary *opts2, int *is_http)
400 {
401     DASHContext *c = s->priv_data;
402     AVDictionary *tmp = NULL;
403     const char *proto_name = NULL;
404     int ret;
405
406     av_dict_copy(&tmp, opts, 0);
407     av_dict_copy(&tmp, opts2, 0);
408
409     if (av_strstart(url, "crypto", NULL)) {
410         if (url[6] == '+' || url[6] == ':')
411             proto_name = avio_find_protocol_name(url + 7);
412     }
413
414     if (!proto_name)
415         proto_name = avio_find_protocol_name(url);
416
417     if (!proto_name)
418         return AVERROR_INVALIDDATA;
419
420     // only http(s) & file are allowed
421     if (av_strstart(proto_name, "file", NULL)) {
422         if (strcmp(c->allowed_extensions, "ALL") && !av_match_ext(url, c->allowed_extensions)) {
423             av_log(s, AV_LOG_ERROR,
424                    "Filename extension of \'%s\' is not a common multimedia extension, blocked for security reasons.\n"
425                    "If you wish to override this adjust allowed_extensions, you can set it to \'ALL\' to allow all\n",
426                    url);
427             return AVERROR_INVALIDDATA;
428         }
429     } else if (av_strstart(proto_name, "http", NULL)) {
430         ;
431     } else
432         return AVERROR_INVALIDDATA;
433
434     if (!strncmp(proto_name, url, strlen(proto_name)) && url[strlen(proto_name)] == ':')
435         ;
436     else if (av_strstart(url, "crypto", NULL) && !strncmp(proto_name, url + 7, strlen(proto_name)) && url[7 + strlen(proto_name)] == ':')
437         ;
438     else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5))
439         return AVERROR_INVALIDDATA;
440
441     av_freep(pb);
442     ret = avio_open2(pb, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp);
443     if (ret >= 0) {
444         // update cookies on http response with setcookies.
445         char *new_cookies = NULL;
446
447         if (!(s->flags & AVFMT_FLAG_CUSTOM_IO))
448             av_opt_get(*pb, "cookies", AV_OPT_SEARCH_CHILDREN, (uint8_t**)&new_cookies);
449
450         if (new_cookies) {
451             av_free(c->cookies);
452             c->cookies = new_cookies;
453         }
454
455         av_dict_set(&opts, "cookies", c->cookies, 0);
456     }
457
458     av_dict_free(&tmp);
459
460     if (is_http)
461         *is_http = av_strstart(proto_name, "http", NULL);
462
463     return ret;
464 }
465
466 static char *get_content_url(xmlNodePtr *baseurl_nodes,
467                              int n_baseurl_nodes,
468                              int max_url_size,
469                              char *rep_id_val,
470                              char *rep_bandwidth_val,
471                              char *val)
472 {
473     int i;
474     char *text;
475     char *url = NULL;
476     char *tmp_str = av_mallocz(max_url_size);
477     char *tmp_str_2 = av_mallocz(max_url_size);
478
479     if (!tmp_str || !tmp_str_2) {
480         return NULL;
481     }
482
483     for (i = 0; i < n_baseurl_nodes; ++i) {
484         if (baseurl_nodes[i] &&
485             baseurl_nodes[i]->children &&
486             baseurl_nodes[i]->children->type == XML_TEXT_NODE) {
487             text = xmlNodeGetContent(baseurl_nodes[i]->children);
488             if (text) {
489                 memset(tmp_str, 0, max_url_size);
490                 memset(tmp_str_2, 0, max_url_size);
491                 ff_make_absolute_url(tmp_str_2, max_url_size, tmp_str, text);
492                 av_strlcpy(tmp_str, tmp_str_2, max_url_size);
493                 xmlFree(text);
494             }
495         }
496     }
497
498     if (val)
499         av_strlcat(tmp_str, (const char*)val, max_url_size);
500
501     if (rep_id_val) {
502         url = av_strireplace(tmp_str, "$RepresentationID$", (const char*)rep_id_val);
503         if (!url) {
504             goto end;
505         }
506         av_strlcpy(tmp_str, url, max_url_size);
507     }
508     if (rep_bandwidth_val && tmp_str[0] != '\0') {
509         // free any previously assigned url before reassigning
510         av_free(url);
511         url = av_strireplace(tmp_str, "$Bandwidth$", (const char*)rep_bandwidth_val);
512         if (!url) {
513             goto end;
514         }
515     }
516 end:
517     av_free(tmp_str);
518     av_free(tmp_str_2);
519     return url;
520 }
521
522 static char *get_val_from_nodes_tab(xmlNodePtr *nodes, const int n_nodes, const char *attrname)
523 {
524     int i;
525     char *val;
526
527     for (i = 0; i < n_nodes; ++i) {
528         if (nodes[i]) {
529             val = xmlGetProp(nodes[i], attrname);
530             if (val)
531                 return val;
532         }
533     }
534
535     return NULL;
536 }
537
538 static xmlNodePtr find_child_node_by_name(xmlNodePtr rootnode, const char *nodename)
539 {
540     xmlNodePtr node = rootnode;
541     if (!node) {
542         return NULL;
543     }
544
545     node = xmlFirstElementChild(node);
546     while (node) {
547         if (!av_strcasecmp(node->name, nodename)) {
548             return node;
549         }
550         node = xmlNextElementSibling(node);
551     }
552     return NULL;
553 }
554
555 static enum AVMediaType get_content_type(xmlNodePtr node)
556 {
557     enum AVMediaType type = AVMEDIA_TYPE_UNKNOWN;
558     int i = 0;
559     const char *attr;
560     char *val = NULL;
561
562     if (node) {
563         for (i = 0; i < 2; i++) {
564             attr = i ? "mimeType" : "contentType";
565             val = xmlGetProp(node, attr);
566             if (val) {
567                 if (av_stristr((const char *)val, "video")) {
568                     type = AVMEDIA_TYPE_VIDEO;
569                 } else if (av_stristr((const char *)val, "audio")) {
570                     type = AVMEDIA_TYPE_AUDIO;
571                 }
572                 xmlFree(val);
573             }
574         }
575     }
576     return type;
577 }
578
579 static struct fragment * get_Fragment(char *range)
580 {
581     struct fragment * seg =  av_mallocz(sizeof(struct fragment));
582
583     if (!seg)
584         return NULL;
585
586     seg->size = -1;
587     if (range) {
588         char *str_end_offset;
589         char *str_offset = av_strtok(range, "-", &str_end_offset);
590         seg->url_offset = strtoll(str_offset, NULL, 10);
591         seg->size = strtoll(str_end_offset, NULL, 10) - seg->url_offset;
592     }
593
594     return seg;
595 }
596
597 static int parse_manifest_segmenturlnode(AVFormatContext *s, struct representation *rep,
598                                          xmlNodePtr fragmenturl_node,
599                                          xmlNodePtr *baseurl_nodes,
600                                          char *rep_id_val,
601                                          char *rep_bandwidth_val)
602 {
603     DASHContext *c = s->priv_data;
604     char *initialization_val = NULL;
605     char *media_val = NULL;
606     char *range_val = NULL;
607     int max_url_size = c ? c->max_url_size: MAX_URL_SIZE;
608
609     if (!av_strcasecmp(fragmenturl_node->name, (const char *)"Initialization")) {
610         initialization_val = xmlGetProp(fragmenturl_node, "sourceURL");
611         range_val = xmlGetProp(fragmenturl_node, "range");
612         if (initialization_val || range_val) {
613             rep->init_section = get_Fragment(range_val);
614             if (!rep->init_section) {
615                 xmlFree(initialization_val);
616                 xmlFree(range_val);
617                 return AVERROR(ENOMEM);
618             }
619             rep->init_section->url = get_content_url(baseurl_nodes, 4,
620                                                      max_url_size,
621                                                      rep_id_val,
622                                                      rep_bandwidth_val,
623                                                      initialization_val);
624
625             if (!rep->init_section->url) {
626                 av_free(rep->init_section);
627                 xmlFree(initialization_val);
628                 xmlFree(range_val);
629                 return AVERROR(ENOMEM);
630             }
631             xmlFree(initialization_val);
632             xmlFree(range_val);
633         }
634     } else if (!av_strcasecmp(fragmenturl_node->name, (const char *)"SegmentURL")) {
635         media_val = xmlGetProp(fragmenturl_node, "media");
636         range_val = xmlGetProp(fragmenturl_node, "mediaRange");
637         if (media_val || range_val) {
638             struct fragment *seg = get_Fragment(range_val);
639             if (!seg) {
640                 xmlFree(media_val);
641                 xmlFree(range_val);
642                 return AVERROR(ENOMEM);
643             }
644             seg->url = get_content_url(baseurl_nodes, 4,
645                                        max_url_size,
646                                        rep_id_val,
647                                        rep_bandwidth_val,
648                                        media_val);
649             if (!seg->url) {
650                 av_free(seg);
651                 xmlFree(media_val);
652                 xmlFree(range_val);
653                 return AVERROR(ENOMEM);
654             }
655             dynarray_add(&rep->fragments, &rep->n_fragments, seg);
656             xmlFree(media_val);
657             xmlFree(range_val);
658         }
659     }
660
661     return 0;
662 }
663
664 static int parse_manifest_segmenttimeline(AVFormatContext *s, struct representation *rep,
665                                           xmlNodePtr fragment_timeline_node)
666 {
667     xmlAttrPtr attr = NULL;
668     char *val  = NULL;
669
670     if (!av_strcasecmp(fragment_timeline_node->name, (const char *)"S")) {
671         struct timeline *tml = av_mallocz(sizeof(struct timeline));
672         if (!tml) {
673             return AVERROR(ENOMEM);
674         }
675         attr = fragment_timeline_node->properties;
676         while (attr) {
677             val = xmlGetProp(fragment_timeline_node, attr->name);
678
679             if (!val) {
680                 av_log(s, AV_LOG_WARNING, "parse_manifest_segmenttimeline attr->name = %s val is NULL\n", attr->name);
681                 continue;
682             }
683
684             if (!av_strcasecmp(attr->name, (const char *)"t")) {
685                 tml->starttime = (int64_t)strtoll(val, NULL, 10);
686             } else if (!av_strcasecmp(attr->name, (const char *)"r")) {
687                 tml->repeat =(int64_t) strtoll(val, NULL, 10);
688             } else if (!av_strcasecmp(attr->name, (const char *)"d")) {
689                 tml->duration = (int64_t)strtoll(val, NULL, 10);
690             }
691             attr = attr->next;
692             xmlFree(val);
693         }
694         dynarray_add(&rep->timelines, &rep->n_timelines, tml);
695     }
696
697     return 0;
698 }
699
700 static int resolve_content_path(AVFormatContext *s, const char *url, int *max_url_size, xmlNodePtr *baseurl_nodes, int n_baseurl_nodes) {
701
702     char *tmp_str = NULL;
703     char *path = NULL;
704     char *mpdName = NULL;
705     xmlNodePtr node = NULL;
706     char *baseurl = NULL;
707     char *root_url = NULL;
708     char *text = NULL;
709     char *tmp = NULL;
710
711     int isRootHttp = 0;
712     char token ='/';
713     int start =  0;
714     int rootId = 0;
715     int updated = 0;
716     int size = 0;
717     int i;
718     int tmp_max_url_size = strlen(url);
719
720     for (i = n_baseurl_nodes-1; i >= 0 ; i--) {
721         text = xmlNodeGetContent(baseurl_nodes[i]);
722         if (!text)
723             continue;
724         tmp_max_url_size += strlen(text);
725         if (ishttp(text)) {
726             xmlFree(text);
727             break;
728         }
729         xmlFree(text);
730     }
731
732     tmp_max_url_size = aligned(tmp_max_url_size);
733     text = av_mallocz(tmp_max_url_size);
734     if (!text) {
735         updated = AVERROR(ENOMEM);
736         goto end;
737     }
738     av_strlcpy(text, url, strlen(url)+1);
739     tmp = text;
740     while (mpdName = av_strtok(tmp, "/", &tmp))  {
741         size = strlen(mpdName);
742     }
743     av_free(text);
744
745     path = av_mallocz(tmp_max_url_size);
746     tmp_str = av_mallocz(tmp_max_url_size);
747     if (!tmp_str || !path) {
748         updated = AVERROR(ENOMEM);
749         goto end;
750     }
751
752     av_strlcpy (path, url, strlen(url) - size + 1);
753     for (rootId = n_baseurl_nodes - 1; rootId > 0; rootId --) {
754         if (!(node = baseurl_nodes[rootId])) {
755             continue;
756         }
757         text = xmlNodeGetContent(node);
758         if (ishttp(text)) {
759             xmlFree(text);
760             break;
761         }
762         xmlFree(text);
763     }
764
765     node = baseurl_nodes[rootId];
766     baseurl = xmlNodeGetContent(node);
767     root_url = (av_strcasecmp(baseurl, "")) ? baseurl : path;
768     if (node) {
769         xmlNodeSetContent(node, root_url);
770         updated = 1;
771     }
772
773     size = strlen(root_url);
774     isRootHttp = ishttp(root_url);
775
776     if (root_url[size - 1] != token) {
777         av_strlcat(root_url, "/", size + 2);
778         size += 2;
779     }
780
781     for (i = 0; i < n_baseurl_nodes; ++i) {
782         if (i == rootId) {
783             continue;
784         }
785         text = xmlNodeGetContent(baseurl_nodes[i]);
786         if (text) {
787             memset(tmp_str, 0, strlen(tmp_str));
788             if (!ishttp(text) && isRootHttp) {
789                 av_strlcpy(tmp_str, root_url, size + 1);
790             }
791             start = (text[0] == token);
792             av_strlcat(tmp_str, text + start, tmp_max_url_size);
793             xmlNodeSetContent(baseurl_nodes[i], tmp_str);
794             updated = 1;
795             xmlFree(text);
796         }
797     }
798
799 end:
800     if (tmp_max_url_size > *max_url_size) {
801         *max_url_size = tmp_max_url_size;
802     }
803     av_free(path);
804     av_free(tmp_str);
805     xmlFree(baseurl);
806     return updated;
807
808 }
809
810 static int parse_manifest_representation(AVFormatContext *s, const char *url,
811                                          xmlNodePtr node,
812                                          xmlNodePtr adaptionset_node,
813                                          xmlNodePtr mpd_baseurl_node,
814                                          xmlNodePtr period_baseurl_node,
815                                          xmlNodePtr period_segmenttemplate_node,
816                                          xmlNodePtr period_segmentlist_node,
817                                          xmlNodePtr fragment_template_node,
818                                          xmlNodePtr content_component_node,
819                                          xmlNodePtr adaptionset_baseurl_node,
820                                          xmlNodePtr adaptionset_segmentlist_node,
821                                          xmlNodePtr adaptionset_supplementalproperty_node)
822 {
823     int32_t ret = 0;
824     int32_t audio_rep_idx = 0;
825     int32_t video_rep_idx = 0;
826     DASHContext *c = s->priv_data;
827     struct representation *rep = NULL;
828     struct fragment *seg = NULL;
829     xmlNodePtr representation_segmenttemplate_node = NULL;
830     xmlNodePtr representation_baseurl_node = NULL;
831     xmlNodePtr representation_segmentlist_node = NULL;
832     xmlNodePtr segmentlists_tab[2];
833     xmlNodePtr fragment_timeline_node = NULL;
834     xmlNodePtr fragment_templates_tab[5];
835     char *duration_val = NULL;
836     char *presentation_timeoffset_val = NULL;
837     char *startnumber_val = NULL;
838     char *timescale_val = NULL;
839     char *initialization_val = NULL;
840     char *media_val = NULL;
841     char *val = NULL;
842     xmlNodePtr baseurl_nodes[4];
843     xmlNodePtr representation_node = node;
844     char *rep_id_val = xmlGetProp(representation_node, "id");
845     char *rep_bandwidth_val = xmlGetProp(representation_node, "bandwidth");
846     char *rep_framerate_val = xmlGetProp(representation_node, "frameRate");
847     enum AVMediaType type = AVMEDIA_TYPE_UNKNOWN;
848
849     // try get information from representation
850     if (type == AVMEDIA_TYPE_UNKNOWN)
851         type = get_content_type(representation_node);
852     // try get information from contentComponen
853     if (type == AVMEDIA_TYPE_UNKNOWN)
854         type = get_content_type(content_component_node);
855     // try get information from adaption set
856     if (type == AVMEDIA_TYPE_UNKNOWN)
857         type = get_content_type(adaptionset_node);
858     if (type == AVMEDIA_TYPE_UNKNOWN) {
859         av_log(s, AV_LOG_VERBOSE, "Parsing '%s' - skipp not supported representation type\n", url);
860     } else if (type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_AUDIO) {
861         // convert selected representation to our internal struct
862         rep = av_mallocz(sizeof(struct representation));
863         if (!rep) {
864             ret = AVERROR(ENOMEM);
865             goto end;
866         }
867         representation_segmenttemplate_node = find_child_node_by_name(representation_node, "SegmentTemplate");
868         representation_baseurl_node = find_child_node_by_name(representation_node, "BaseURL");
869         representation_segmentlist_node = find_child_node_by_name(representation_node, "SegmentList");
870
871         baseurl_nodes[0] = mpd_baseurl_node;
872         baseurl_nodes[1] = period_baseurl_node;
873         baseurl_nodes[2] = adaptionset_baseurl_node;
874         baseurl_nodes[3] = representation_baseurl_node;
875
876         ret = resolve_content_path(s, url, &c->max_url_size, baseurl_nodes, 4);
877         c->max_url_size = aligned(c->max_url_size  + strlen(rep_id_val) + strlen(rep_bandwidth_val));
878         if (ret == AVERROR(ENOMEM) || ret == 0) {
879             goto end;
880         }
881         if (representation_segmenttemplate_node || fragment_template_node || period_segmenttemplate_node) {
882             fragment_timeline_node = NULL;
883             fragment_templates_tab[0] = representation_segmenttemplate_node;
884             fragment_templates_tab[1] = adaptionset_segmentlist_node;
885             fragment_templates_tab[2] = fragment_template_node;
886             fragment_templates_tab[3] = period_segmenttemplate_node;
887             fragment_templates_tab[4] = period_segmentlist_node;
888
889             presentation_timeoffset_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "presentationTimeOffset");
890             duration_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "duration");
891             startnumber_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "startNumber");
892             timescale_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "timescale");
893             initialization_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "initialization");
894             media_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "media");
895
896             if (initialization_val) {
897                 rep->init_section = av_mallocz(sizeof(struct fragment));
898                 if (!rep->init_section) {
899                     av_free(rep);
900                     ret = AVERROR(ENOMEM);
901                     goto end;
902                 }
903                 c->max_url_size = aligned(c->max_url_size  + strlen(initialization_val));
904                 rep->init_section->url = get_content_url(baseurl_nodes, 4,  c->max_url_size, rep_id_val, rep_bandwidth_val, initialization_val);
905                 if (!rep->init_section->url) {
906                     av_free(rep->init_section);
907                     av_free(rep);
908                     ret = AVERROR(ENOMEM);
909                     goto end;
910                 }
911                 rep->init_section->size = -1;
912                 xmlFree(initialization_val);
913             }
914
915             if (media_val) {
916                 c->max_url_size = aligned(c->max_url_size  + strlen(media_val));
917                 rep->url_template = get_content_url(baseurl_nodes, 4, c->max_url_size, rep_id_val, rep_bandwidth_val, media_val);
918                 xmlFree(media_val);
919             }
920
921             if (presentation_timeoffset_val) {
922                 rep->presentation_timeoffset = (int64_t) strtoll(presentation_timeoffset_val, NULL, 10);
923                 xmlFree(presentation_timeoffset_val);
924             }
925             if (duration_val) {
926                 rep->fragment_duration = (int64_t) strtoll(duration_val, NULL, 10);
927                 xmlFree(duration_val);
928             }
929             if (timescale_val) {
930                 rep->fragment_timescale = (int64_t) strtoll(timescale_val, NULL, 10);
931                 xmlFree(timescale_val);
932             }
933             if (startnumber_val) {
934                 rep->first_seq_no = (int64_t) strtoll(startnumber_val, NULL, 10);
935                 xmlFree(startnumber_val);
936             }
937             if (adaptionset_supplementalproperty_node) {
938                 if (!av_strcasecmp(xmlGetProp(adaptionset_supplementalproperty_node,"schemeIdUri"), "http://dashif.org/guidelines/last-segment-number")) {
939                     val = xmlGetProp(adaptionset_supplementalproperty_node,"value");
940                     if (!val) {
941                         av_log(s, AV_LOG_ERROR, "Missing value attribute in adaptionset_supplementalproperty_node\n");
942                     } else {
943                         rep->last_seq_no =(int64_t) strtoll(val, NULL, 10) - 1;
944                         xmlFree(val);
945                     }
946                 }
947             }
948
949             fragment_timeline_node = find_child_node_by_name(representation_segmenttemplate_node, "SegmentTimeline");
950
951             if (!fragment_timeline_node)
952                 fragment_timeline_node = find_child_node_by_name(fragment_template_node, "SegmentTimeline");
953             if (!fragment_timeline_node)
954                 fragment_timeline_node = find_child_node_by_name(adaptionset_segmentlist_node, "SegmentTimeline");
955             if (!fragment_timeline_node)
956                 fragment_timeline_node = find_child_node_by_name(period_segmentlist_node, "SegmentTimeline");
957             if (fragment_timeline_node) {
958                 fragment_timeline_node = xmlFirstElementChild(fragment_timeline_node);
959                 while (fragment_timeline_node) {
960                     ret = parse_manifest_segmenttimeline(s, rep, fragment_timeline_node);
961                     if (ret < 0) {
962                         return ret;
963                     }
964                     fragment_timeline_node = xmlNextElementSibling(fragment_timeline_node);
965                 }
966             }
967         } else if (representation_baseurl_node && !representation_segmentlist_node) {
968             seg = av_mallocz(sizeof(struct fragment));
969             if (!seg) {
970                 ret = AVERROR(ENOMEM);
971                 goto end;
972             }
973             seg->url = get_content_url(baseurl_nodes, 4, c->max_url_size, rep_id_val, rep_bandwidth_val, NULL);
974             if (!seg->url) {
975                 av_free(seg);
976                 ret = AVERROR(ENOMEM);
977                 goto end;
978             }
979             seg->size = -1;
980             dynarray_add(&rep->fragments, &rep->n_fragments, seg);
981         } else if (representation_segmentlist_node) {
982             // TODO: https://www.brendanlong.com/the-structure-of-an-mpeg-dash-mpd.html
983             // http://www-itec.uni-klu.ac.at/dash/ddash/mpdGenerator.php?fragmentlength=15&type=full
984             xmlNodePtr fragmenturl_node = NULL;
985             segmentlists_tab[0] = representation_segmentlist_node;
986             segmentlists_tab[1] = adaptionset_segmentlist_node;
987
988             duration_val = get_val_from_nodes_tab(segmentlists_tab, 2, "duration");
989             timescale_val = get_val_from_nodes_tab(segmentlists_tab, 2, "timescale");
990             if (duration_val) {
991                 rep->fragment_duration = (int64_t) strtoll(duration_val, NULL, 10);
992                 xmlFree(duration_val);
993             }
994             if (timescale_val) {
995                 rep->fragment_timescale = (int64_t) strtoll(timescale_val, NULL, 10);
996                 xmlFree(timescale_val);
997             }
998             fragmenturl_node = xmlFirstElementChild(representation_segmentlist_node);
999             while (fragmenturl_node) {
1000                 ret = parse_manifest_segmenturlnode(s, rep, fragmenturl_node,
1001                                                     baseurl_nodes,
1002                                                     rep_id_val,
1003                                                     rep_bandwidth_val);
1004                 if (ret < 0) {
1005                     return ret;
1006                 }
1007                 fragmenturl_node = xmlNextElementSibling(fragmenturl_node);
1008             }
1009
1010             fragment_timeline_node = find_child_node_by_name(representation_segmenttemplate_node, "SegmentTimeline");
1011
1012             if (!fragment_timeline_node)
1013                 fragment_timeline_node = find_child_node_by_name(fragment_template_node, "SegmentTimeline");
1014             if (!fragment_timeline_node)
1015                 fragment_timeline_node = find_child_node_by_name(adaptionset_segmentlist_node, "SegmentTimeline");
1016             if (!fragment_timeline_node)
1017                 fragment_timeline_node = find_child_node_by_name(period_segmentlist_node, "SegmentTimeline");
1018             if (fragment_timeline_node) {
1019                 fragment_timeline_node = xmlFirstElementChild(fragment_timeline_node);
1020                 while (fragment_timeline_node) {
1021                     ret = parse_manifest_segmenttimeline(s, rep, fragment_timeline_node);
1022                     if (ret < 0) {
1023                         return ret;
1024                     }
1025                     fragment_timeline_node = xmlNextElementSibling(fragment_timeline_node);
1026                 }
1027             }
1028         } else {
1029             free_representation(rep);
1030             rep = NULL;
1031             av_log(s, AV_LOG_ERROR, "Unknown format of Representation node id[%s] \n", (const char *)rep_id_val);
1032         }
1033
1034         if (rep) {
1035             if (rep->fragment_duration > 0 && !rep->fragment_timescale)
1036                 rep->fragment_timescale = 1;
1037             rep->bandwidth = rep_bandwidth_val ? atoi(rep_bandwidth_val) : 0;
1038             strncpy(rep->id, rep_id_val ? rep_id_val : "", sizeof(rep->id));
1039             rep->framerate = av_make_q(0, 0);
1040             if (type == AVMEDIA_TYPE_VIDEO && rep_framerate_val) {
1041                 ret = av_parse_video_rate(&rep->framerate, rep_framerate_val);
1042                 if (ret < 0)
1043                     av_log(s, AV_LOG_VERBOSE, "Ignoring invalid frame rate '%s'\n", rep_framerate_val);
1044             }
1045
1046             if (type == AVMEDIA_TYPE_VIDEO) {
1047                 rep->rep_idx = video_rep_idx;
1048                 dynarray_add(&c->videos, &c->n_videos, rep);
1049             } else {
1050                 rep->rep_idx = audio_rep_idx;
1051                 dynarray_add(&c->audios, &c->n_audios, rep);
1052             }
1053         }
1054     }
1055
1056     video_rep_idx += type == AVMEDIA_TYPE_VIDEO;
1057     audio_rep_idx += type == AVMEDIA_TYPE_AUDIO;
1058
1059 end:
1060     if (rep_id_val)
1061         xmlFree(rep_id_val);
1062     if (rep_bandwidth_val)
1063         xmlFree(rep_bandwidth_val);
1064     if (rep_framerate_val)
1065         xmlFree(rep_framerate_val);
1066
1067     return ret;
1068 }
1069
1070 static int parse_manifest_adaptationset(AVFormatContext *s, const char *url,
1071                                         xmlNodePtr adaptionset_node,
1072                                         xmlNodePtr mpd_baseurl_node,
1073                                         xmlNodePtr period_baseurl_node,
1074                                         xmlNodePtr period_segmenttemplate_node,
1075                                         xmlNodePtr period_segmentlist_node)
1076 {
1077     int ret = 0;
1078     xmlNodePtr fragment_template_node = NULL;
1079     xmlNodePtr content_component_node = NULL;
1080     xmlNodePtr adaptionset_baseurl_node = NULL;
1081     xmlNodePtr adaptionset_segmentlist_node = NULL;
1082     xmlNodePtr adaptionset_supplementalproperty_node = NULL;
1083     xmlNodePtr node = NULL;
1084
1085     node = xmlFirstElementChild(adaptionset_node);
1086     while (node) {
1087         if (!av_strcasecmp(node->name, (const char *)"SegmentTemplate")) {
1088             fragment_template_node = node;
1089         } else if (!av_strcasecmp(node->name, (const char *)"ContentComponent")) {
1090             content_component_node = node;
1091         } else if (!av_strcasecmp(node->name, (const char *)"BaseURL")) {
1092             adaptionset_baseurl_node = node;
1093         } else if (!av_strcasecmp(node->name, (const char *)"SegmentList")) {
1094             adaptionset_segmentlist_node = node;
1095         } else if (!av_strcasecmp(node->name, (const char *)"SupplementalProperty")) {
1096             adaptionset_supplementalproperty_node = node;
1097         } else if (!av_strcasecmp(node->name, (const char *)"Representation")) {
1098             ret = parse_manifest_representation(s, url, node,
1099                                                 adaptionset_node,
1100                                                 mpd_baseurl_node,
1101                                                 period_baseurl_node,
1102                                                 period_segmenttemplate_node,
1103                                                 period_segmentlist_node,
1104                                                 fragment_template_node,
1105                                                 content_component_node,
1106                                                 adaptionset_baseurl_node,
1107                                                 adaptionset_segmentlist_node,
1108                                                 adaptionset_supplementalproperty_node);
1109             if (ret < 0) {
1110                 return ret;
1111             }
1112         }
1113         node = xmlNextElementSibling(node);
1114     }
1115     return 0;
1116 }
1117
1118 static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in)
1119 {
1120     DASHContext *c = s->priv_data;
1121     int ret = 0;
1122     int close_in = 0;
1123     uint8_t *new_url = NULL;
1124     int64_t filesize = 0;
1125     char *buffer = NULL;
1126     AVDictionary *opts = NULL;
1127     xmlDoc *doc = NULL;
1128     xmlNodePtr root_element = NULL;
1129     xmlNodePtr node = NULL;
1130     xmlNodePtr period_node = NULL;
1131     xmlNodePtr tmp_node = NULL;
1132     xmlNodePtr mpd_baseurl_node = NULL;
1133     xmlNodePtr period_baseurl_node = NULL;
1134     xmlNodePtr period_segmenttemplate_node = NULL;
1135     xmlNodePtr period_segmentlist_node = NULL;
1136     xmlNodePtr adaptionset_node = NULL;
1137     xmlAttrPtr attr = NULL;
1138     char *val  = NULL;
1139     uint32_t period_duration_sec = 0;
1140     uint32_t period_start_sec = 0;
1141
1142     if (!in) {
1143         close_in = 1;
1144
1145         set_httpheader_options(c, &opts);
1146         ret = avio_open2(&in, url, AVIO_FLAG_READ, c->interrupt_callback, &opts);
1147         av_dict_free(&opts);
1148         if (ret < 0)
1149             return ret;
1150     }
1151
1152     if (av_opt_get(in, "location", AV_OPT_SEARCH_CHILDREN, &new_url) >= 0) {
1153         c->base_url = av_strdup(new_url);
1154     } else {
1155         c->base_url = av_strdup(url);
1156     }
1157
1158     filesize = avio_size(in);
1159     if (filesize <= 0) {
1160         filesize = 8 * 1024;
1161     }
1162
1163     buffer = av_mallocz(filesize);
1164     if (!buffer) {
1165         av_free(c->base_url);
1166         return AVERROR(ENOMEM);
1167     }
1168
1169     filesize = avio_read(in, buffer, filesize);
1170     if (filesize <= 0) {
1171         av_log(s, AV_LOG_ERROR, "Unable to read to offset '%s'\n", url);
1172         ret = AVERROR_INVALIDDATA;
1173     } else {
1174         LIBXML_TEST_VERSION
1175
1176             doc = xmlReadMemory(buffer, filesize, c->base_url, NULL, 0);
1177         root_element = xmlDocGetRootElement(doc);
1178         node = root_element;
1179
1180         if (!node) {
1181             ret = AVERROR_INVALIDDATA;
1182             av_log(s, AV_LOG_ERROR, "Unable to parse '%s' - missing root node\n", url);
1183             goto cleanup;
1184         }
1185
1186         if (node->type != XML_ELEMENT_NODE ||
1187             av_strcasecmp(node->name, (const char *)"MPD")) {
1188             ret = AVERROR_INVALIDDATA;
1189             av_log(s, AV_LOG_ERROR, "Unable to parse '%s' - wrong root node name[%s] type[%d]\n", url, node->name, (int)node->type);
1190             goto cleanup;
1191         }
1192
1193         val = xmlGetProp(node, "type");
1194         if (!val) {
1195             av_log(s, AV_LOG_ERROR, "Unable to parse '%s' - missing type attrib\n", url);
1196             ret = AVERROR_INVALIDDATA;
1197             goto cleanup;
1198         }
1199         if (!av_strcasecmp(val, (const char *)"dynamic"))
1200             c->is_live = 1;
1201         xmlFree(val);
1202
1203         attr = node->properties;
1204         while (attr) {
1205             val = xmlGetProp(node, attr->name);
1206
1207             if (!av_strcasecmp(attr->name, (const char *)"availabilityStartTime")) {
1208                 c->availability_start_time = get_utc_date_time_insec(s, (const char *)val);
1209             } else if (!av_strcasecmp(attr->name, (const char *)"publishTime")) {
1210                 c->publish_time = get_utc_date_time_insec(s, (const char *)val);
1211             } else if (!av_strcasecmp(attr->name, (const char *)"minimumUpdatePeriod")) {
1212                 c->minimum_update_period = get_duration_insec(s, (const char *)val);
1213             } else if (!av_strcasecmp(attr->name, (const char *)"timeShiftBufferDepth")) {
1214                 c->time_shift_buffer_depth = get_duration_insec(s, (const char *)val);
1215             } else if (!av_strcasecmp(attr->name, (const char *)"minBufferTime")) {
1216                 c->min_buffer_time = get_duration_insec(s, (const char *)val);
1217             } else if (!av_strcasecmp(attr->name, (const char *)"suggestedPresentationDelay")) {
1218                 c->suggested_presentation_delay = get_duration_insec(s, (const char *)val);
1219             } else if (!av_strcasecmp(attr->name, (const char *)"mediaPresentationDuration")) {
1220                 c->media_presentation_duration = get_duration_insec(s, (const char *)val);
1221             }
1222             attr = attr->next;
1223             xmlFree(val);
1224         }
1225
1226         tmp_node = find_child_node_by_name(node, "BaseURL");
1227         if (tmp_node) {
1228             mpd_baseurl_node = xmlCopyNode(tmp_node,1);
1229         } else {
1230             mpd_baseurl_node = xmlNewNode(NULL, "BaseURL");
1231         }
1232
1233         // at now we can handle only one period, with the longest duration
1234         node = xmlFirstElementChild(node);
1235         while (node) {
1236             if (!av_strcasecmp(node->name, (const char *)"Period")) {
1237                 period_duration_sec = 0;
1238                 period_start_sec = 0;
1239                 attr = node->properties;
1240                 while (attr) {
1241                     val = xmlGetProp(node, attr->name);
1242                     if (!av_strcasecmp(attr->name, (const char *)"duration")) {
1243                         period_duration_sec = get_duration_insec(s, (const char *)val);
1244                     } else if (!av_strcasecmp(attr->name, (const char *)"start")) {
1245                         period_start_sec = get_duration_insec(s, (const char *)val);
1246                     }
1247                     attr = attr->next;
1248                     xmlFree(val);
1249                 }
1250                 if ((period_duration_sec) >= (c->period_duration)) {
1251                     period_node = node;
1252                     c->period_duration = period_duration_sec;
1253                     c->period_start = period_start_sec;
1254                     if (c->period_start > 0)
1255                         c->media_presentation_duration = c->period_duration;
1256                 }
1257             }
1258             node = xmlNextElementSibling(node);
1259         }
1260         if (!period_node) {
1261             av_log(s, AV_LOG_ERROR, "Unable to parse '%s' - missing Period node\n", url);
1262             ret = AVERROR_INVALIDDATA;
1263             goto cleanup;
1264         }
1265
1266         adaptionset_node = xmlFirstElementChild(period_node);
1267         while (adaptionset_node) {
1268             if (!av_strcasecmp(adaptionset_node->name, (const char *)"BaseURL")) {
1269                 period_baseurl_node = adaptionset_node;
1270             } else if (!av_strcasecmp(adaptionset_node->name, (const char *)"SegmentTemplate")) {
1271                 period_segmenttemplate_node = adaptionset_node;
1272             } else if (!av_strcasecmp(adaptionset_node->name, (const char *)"SegmentList")) {
1273                 period_segmentlist_node = adaptionset_node;
1274             } else if (!av_strcasecmp(adaptionset_node->name, (const char *)"AdaptationSet")) {
1275                 parse_manifest_adaptationset(s, url, adaptionset_node, mpd_baseurl_node, period_baseurl_node, period_segmenttemplate_node, period_segmentlist_node);
1276             }
1277             adaptionset_node = xmlNextElementSibling(adaptionset_node);
1278         }
1279 cleanup:
1280         /*free the document */
1281         xmlFreeDoc(doc);
1282         xmlCleanupParser();
1283         xmlFreeNode(mpd_baseurl_node);
1284     }
1285
1286     av_free(new_url);
1287     av_free(buffer);
1288     if (close_in) {
1289         avio_close(in);
1290     }
1291     return ret;
1292 }
1293
1294 static int64_t calc_cur_seg_no(AVFormatContext *s, struct representation *pls)
1295 {
1296     DASHContext *c = s->priv_data;
1297     int64_t num = 0;
1298     int64_t start_time_offset = 0;
1299
1300     if (c->is_live) {
1301         if (pls->n_fragments) {
1302             num = pls->first_seq_no;
1303         } else if (pls->n_timelines) {
1304             start_time_offset = get_segment_start_time_based_on_timeline(pls, 0xFFFFFFFF) - 60 * pls->fragment_timescale; // 60 seconds before end
1305             num = calc_next_seg_no_from_timelines(pls, start_time_offset);
1306             if (num == -1)
1307                 num = pls->first_seq_no;
1308             else
1309                 num += pls->first_seq_no;
1310         } else if (pls->fragment_duration){
1311             if (pls->presentation_timeoffset) {
1312                 num = pls->presentation_timeoffset * pls->fragment_timescale / pls->fragment_duration;
1313             } else if (c->publish_time > 0 && !c->availability_start_time) {
1314                 num = pls->first_seq_no + (((c->publish_time - c->availability_start_time) - c->suggested_presentation_delay) * pls->fragment_timescale) / pls->fragment_duration;
1315             } else {
1316                 num = pls->first_seq_no + (((get_current_time_in_sec() - c->availability_start_time) - c->suggested_presentation_delay) * pls->fragment_timescale) / pls->fragment_duration;
1317             }
1318         }
1319     } else {
1320         num = pls->first_seq_no;
1321     }
1322     return num;
1323 }
1324
1325 static int64_t calc_min_seg_no(AVFormatContext *s, struct representation *pls)
1326 {
1327     DASHContext *c = s->priv_data;
1328     int64_t num = 0;
1329
1330     if (c->is_live && pls->fragment_duration) {
1331         num = pls->first_seq_no + (((get_current_time_in_sec() - c->availability_start_time) - c->time_shift_buffer_depth) * pls->fragment_timescale) / pls->fragment_duration;
1332     } else {
1333         num = pls->first_seq_no;
1334     }
1335     return num;
1336 }
1337
1338 static int64_t calc_max_seg_no(struct representation *pls, DASHContext *c)
1339 {
1340     int64_t num = 0;
1341
1342     if (pls->n_fragments) {
1343         num = pls->first_seq_no + pls->n_fragments - 1;
1344     } else if (pls->n_timelines) {
1345         int i = 0;
1346         num = pls->first_seq_no + pls->n_timelines - 1;
1347         for (i = 0; i < pls->n_timelines; i++) {
1348             num += pls->timelines[i]->repeat;
1349         }
1350     } else if (c->is_live && pls->fragment_duration) {
1351         num = pls->first_seq_no + (((get_current_time_in_sec() - c->availability_start_time)) * pls->fragment_timescale)  / pls->fragment_duration;
1352     } else if (pls->fragment_duration) {
1353         num = pls->first_seq_no + (c->media_presentation_duration * pls->fragment_timescale) / pls->fragment_duration;
1354     }
1355
1356     return num;
1357 }
1358
1359 static void move_timelines(struct representation *rep_src, struct representation *rep_dest, DASHContext *c)
1360 {
1361     if (rep_dest && rep_src ) {
1362         free_timelines_list(rep_dest);
1363         rep_dest->timelines    = rep_src->timelines;
1364         rep_dest->n_timelines  = rep_src->n_timelines;
1365         rep_dest->first_seq_no = rep_src->first_seq_no;
1366         rep_dest->last_seq_no = calc_max_seg_no(rep_dest, c);
1367         rep_src->timelines = NULL;
1368         rep_src->n_timelines = 0;
1369         rep_dest->cur_seq_no = rep_src->cur_seq_no;
1370     }
1371 }
1372
1373 static void move_segments(struct representation *rep_src, struct representation *rep_dest, DASHContext *c)
1374 {
1375     if (rep_dest && rep_src ) {
1376         free_fragment_list(rep_dest);
1377         if (rep_src->start_number > (rep_dest->start_number + rep_dest->n_fragments))
1378             rep_dest->cur_seq_no = 0;
1379         else
1380             rep_dest->cur_seq_no += rep_src->start_number - rep_dest->start_number;
1381         rep_dest->fragments    = rep_src->fragments;
1382         rep_dest->n_fragments  = rep_src->n_fragments;
1383         rep_dest->parent  = rep_src->parent;
1384         rep_dest->last_seq_no = calc_max_seg_no(rep_dest, c);
1385         rep_src->fragments = NULL;
1386         rep_src->n_fragments = 0;
1387     }
1388 }
1389
1390
1391 static int refresh_manifest(AVFormatContext *s)
1392 {
1393
1394     int ret = 0, i;
1395     DASHContext *c = s->priv_data;
1396
1397     // save current context
1398     int n_videos = c->n_videos;
1399     struct representation **videos = c->videos;
1400     int n_audios = c->n_audios;
1401     struct representation **audios = c->audios;
1402     char *base_url = c->base_url;
1403
1404     c->base_url = NULL;
1405     c->n_videos = 0;
1406     c->videos = NULL;
1407     c->n_audios = 0;
1408     c->audios = NULL;
1409     ret = parse_manifest(s, s->url, NULL);
1410     if (ret)
1411         goto finish;
1412
1413     if (c->n_videos != n_videos) {
1414         av_log(c, AV_LOG_ERROR,
1415                "new manifest has mismatched no. of video representations, %d -> %d\n",
1416                n_videos, c->n_videos);
1417         return AVERROR_INVALIDDATA;
1418     }
1419     if (c->n_audios != n_audios) {
1420         av_log(c, AV_LOG_ERROR,
1421                "new manifest has mismatched no. of audio representations, %d -> %d\n",
1422                n_audios, c->n_audios);
1423         return AVERROR_INVALIDDATA;
1424     }
1425
1426     for (i = 0; i < n_videos; i++) {
1427         struct representation *cur_video = videos[i];
1428         struct representation *ccur_video = c->videos[i];
1429         if (cur_video->timelines) {
1430             // calc current time
1431             int64_t currentTime = get_segment_start_time_based_on_timeline(cur_video, cur_video->cur_seq_no) / cur_video->fragment_timescale;
1432             // update segments
1433             ccur_video->cur_seq_no = calc_next_seg_no_from_timelines(ccur_video, currentTime * cur_video->fragment_timescale - 1);
1434             if (ccur_video->cur_seq_no >= 0) {
1435                 move_timelines(ccur_video, cur_video, c);
1436             }
1437         }
1438         if (cur_video->fragments) {
1439             move_segments(ccur_video, cur_video, c);
1440         }
1441     }
1442     for (i = 0; i < n_audios; i++) {
1443         struct representation *cur_audio = audios[i];
1444         struct representation *ccur_audio = c->audios[i];
1445         if (cur_audio->timelines) {
1446             // calc current time
1447             int64_t currentTime = get_segment_start_time_based_on_timeline(cur_audio, cur_audio->cur_seq_no) / cur_audio->fragment_timescale;
1448             // update segments
1449             ccur_audio->cur_seq_no = calc_next_seg_no_from_timelines(ccur_audio, currentTime * cur_audio->fragment_timescale - 1);
1450             if (ccur_audio->cur_seq_no >= 0) {
1451                 move_timelines(ccur_audio, cur_audio, c);
1452             }
1453         }
1454         if (cur_audio->fragments) {
1455             move_segments(ccur_audio, cur_audio, c);
1456         }
1457     }
1458
1459 finish:
1460     // restore context
1461     if (c->base_url)
1462         av_free(base_url);
1463     else
1464         c->base_url  = base_url;
1465     if (c->audios)
1466         free_audio_list(c);
1467     if (c->videos)
1468         free_video_list(c);
1469     c->n_audios = n_audios;
1470     c->audios = audios;
1471     c->n_videos = n_videos;
1472     c->videos = videos;
1473     return ret;
1474 }
1475
1476 static struct fragment *get_current_fragment(struct representation *pls)
1477 {
1478     int64_t min_seq_no = 0;
1479     int64_t max_seq_no = 0;
1480     struct fragment *seg = NULL;
1481     struct fragment *seg_ptr = NULL;
1482     DASHContext *c = pls->parent->priv_data;
1483
1484     while (( !ff_check_interrupt(c->interrupt_callback)&& pls->n_fragments > 0)) {
1485         if (pls->cur_seq_no < pls->n_fragments) {
1486             seg_ptr = pls->fragments[pls->cur_seq_no];
1487             seg = av_mallocz(sizeof(struct fragment));
1488             if (!seg) {
1489                 return NULL;
1490             }
1491             seg->url = av_strdup(seg_ptr->url);
1492             if (!seg->url) {
1493                 av_free(seg);
1494                 return NULL;
1495             }
1496             seg->size = seg_ptr->size;
1497             seg->url_offset = seg_ptr->url_offset;
1498             return seg;
1499         } else if (c->is_live) {
1500             refresh_manifest(pls->parent);
1501         } else {
1502             break;
1503         }
1504     }
1505     if (c->is_live) {
1506         min_seq_no = calc_min_seg_no(pls->parent, pls);
1507         max_seq_no = calc_max_seg_no(pls, c);
1508
1509         if (pls->timelines || pls->fragments) {
1510             refresh_manifest(pls->parent);
1511         }
1512         if (pls->cur_seq_no <= min_seq_no) {
1513             av_log(pls->parent, AV_LOG_VERBOSE, "old fragment: cur[%"PRId64"] min[%"PRId64"] max[%"PRId64"], playlist %d\n", (int64_t)pls->cur_seq_no, min_seq_no, max_seq_no, (int)pls->rep_idx);
1514             pls->cur_seq_no = calc_cur_seg_no(pls->parent, pls);
1515         } else if (pls->cur_seq_no > max_seq_no) {
1516             av_log(pls->parent, AV_LOG_VERBOSE, "new fragment: min[%"PRId64"] max[%"PRId64"], playlist %d\n", min_seq_no, max_seq_no, (int)pls->rep_idx);
1517         }
1518         seg = av_mallocz(sizeof(struct fragment));
1519         if (!seg) {
1520             return NULL;
1521         }
1522     } else if (pls->cur_seq_no <= pls->last_seq_no) {
1523         seg = av_mallocz(sizeof(struct fragment));
1524         if (!seg) {
1525             return NULL;
1526         }
1527     }
1528     if (seg) {
1529         char *tmpfilename= av_mallocz(c->max_url_size);
1530         if (!tmpfilename) {
1531             return NULL;
1532         }
1533         ff_dash_fill_tmpl_params(tmpfilename, c->max_url_size, pls->url_template, 0, pls->cur_seq_no, 0, get_segment_start_time_based_on_timeline(pls, pls->cur_seq_no));
1534         seg->url = av_strireplace(pls->url_template, pls->url_template, tmpfilename);
1535         if (!seg->url) {
1536             av_log(pls->parent, AV_LOG_WARNING, "Unable to resolve template url '%s', try to use origin template\n", pls->url_template);
1537             seg->url = av_strdup(pls->url_template);
1538             if (!seg->url) {
1539                 av_log(pls->parent, AV_LOG_ERROR, "Cannot resolve template url '%s'\n", pls->url_template);
1540                 av_free(tmpfilename);
1541                 return NULL;
1542             }
1543         }
1544         av_free(tmpfilename);
1545         seg->size = -1;
1546     }
1547
1548     return seg;
1549 }
1550
1551 enum ReadFromURLMode {
1552     READ_NORMAL,
1553     READ_COMPLETE,
1554 };
1555
1556 static int read_from_url(struct representation *pls, struct fragment *seg,
1557                          uint8_t *buf, int buf_size,
1558                          enum ReadFromURLMode mode)
1559 {
1560     int ret;
1561
1562     /* limit read if the fragment was only a part of a file */
1563     if (seg->size >= 0)
1564         buf_size = FFMIN(buf_size, pls->cur_seg_size - pls->cur_seg_offset);
1565
1566     if (mode == READ_COMPLETE) {
1567         ret = avio_read(pls->input, buf, buf_size);
1568         if (ret < buf_size) {
1569             av_log(pls->parent, AV_LOG_WARNING, "Could not read complete fragment.\n");
1570         }
1571     } else {
1572         ret = avio_read(pls->input, buf, buf_size);
1573     }
1574     if (ret > 0)
1575         pls->cur_seg_offset += ret;
1576
1577     return ret;
1578 }
1579
1580 static int open_input(DASHContext *c, struct representation *pls, struct fragment *seg)
1581 {
1582     AVDictionary *opts = NULL;
1583     char *url = NULL;
1584     int ret = 0;
1585
1586     url = av_mallocz(c->max_url_size);
1587     if (!url) {
1588         goto cleanup;
1589     }
1590     set_httpheader_options(c, &opts);
1591     if (seg->size >= 0) {
1592         /* try to restrict the HTTP request to the part we want
1593          * (if this is in fact a HTTP request) */
1594         av_dict_set_int(&opts, "offset", seg->url_offset, 0);
1595         av_dict_set_int(&opts, "end_offset", seg->url_offset + seg->size, 0);
1596     }
1597
1598     ff_make_absolute_url(url, c->max_url_size, c->base_url, seg->url);
1599     av_log(pls->parent, AV_LOG_VERBOSE, "DASH request for url '%s', offset %"PRId64", playlist %d\n",
1600            url, seg->url_offset, pls->rep_idx);
1601     ret = open_url(pls->parent, &pls->input, url, c->avio_opts, opts, NULL);
1602     if (ret < 0) {
1603         goto cleanup;
1604     }
1605
1606 cleanup:
1607     av_free(url);
1608     av_dict_free(&opts);
1609     pls->cur_seg_offset = 0;
1610     pls->cur_seg_size = seg->size;
1611     return ret;
1612 }
1613
1614 static int update_init_section(struct representation *pls)
1615 {
1616     static const int max_init_section_size = 1024 * 1024;
1617     DASHContext *c = pls->parent->priv_data;
1618     int64_t sec_size;
1619     int64_t urlsize;
1620     int ret;
1621
1622     if (!pls->init_section || pls->init_sec_buf)
1623         return 0;
1624
1625     ret = open_input(c, pls, pls->init_section);
1626     if (ret < 0) {
1627         av_log(pls->parent, AV_LOG_WARNING,
1628                "Failed to open an initialization section in playlist %d\n",
1629                pls->rep_idx);
1630         return ret;
1631     }
1632
1633     if (pls->init_section->size >= 0)
1634         sec_size = pls->init_section->size;
1635     else if ((urlsize = avio_size(pls->input)) >= 0)
1636         sec_size = urlsize;
1637     else
1638         sec_size = max_init_section_size;
1639
1640     av_log(pls->parent, AV_LOG_DEBUG,
1641            "Downloading an initialization section of size %"PRId64"\n",
1642            sec_size);
1643
1644     sec_size = FFMIN(sec_size, max_init_section_size);
1645
1646     av_fast_malloc(&pls->init_sec_buf, &pls->init_sec_buf_size, sec_size);
1647
1648     ret = read_from_url(pls, pls->init_section, pls->init_sec_buf,
1649                         pls->init_sec_buf_size, READ_COMPLETE);
1650     ff_format_io_close(pls->parent, &pls->input);
1651
1652     if (ret < 0)
1653         return ret;
1654
1655     pls->init_sec_data_len = ret;
1656     pls->init_sec_buf_read_offset = 0;
1657
1658     return 0;
1659 }
1660
1661 static int64_t seek_data(void *opaque, int64_t offset, int whence)
1662 {
1663     struct representation *v = opaque;
1664     if (v->n_fragments && !v->init_sec_data_len) {
1665         return avio_seek(v->input, offset, whence);
1666     }
1667
1668     return AVERROR(ENOSYS);
1669 }
1670
1671 static int read_data(void *opaque, uint8_t *buf, int buf_size)
1672 {
1673     int ret = 0;
1674     struct representation *v = opaque;
1675     DASHContext *c = v->parent->priv_data;
1676
1677 restart:
1678     if (!v->input) {
1679         free_fragment(&v->cur_seg);
1680         v->cur_seg = get_current_fragment(v);
1681         if (!v->cur_seg) {
1682             ret = AVERROR_EOF;
1683             goto end;
1684         }
1685
1686         /* load/update Media Initialization Section, if any */
1687         ret = update_init_section(v);
1688         if (ret)
1689             goto end;
1690
1691         ret = open_input(c, v, v->cur_seg);
1692         if (ret < 0) {
1693             if (ff_check_interrupt(c->interrupt_callback)) {
1694                 goto end;
1695                 ret = AVERROR_EXIT;
1696             }
1697             av_log(v->parent, AV_LOG_WARNING, "Failed to open fragment of playlist %d\n", v->rep_idx);
1698             v->cur_seq_no++;
1699             goto restart;
1700         }
1701     }
1702
1703     if (v->init_sec_buf_read_offset < v->init_sec_data_len) {
1704         /* Push init section out first before first actual fragment */
1705         int copy_size = FFMIN(v->init_sec_data_len - v->init_sec_buf_read_offset, buf_size);
1706         memcpy(buf, v->init_sec_buf, copy_size);
1707         v->init_sec_buf_read_offset += copy_size;
1708         ret = copy_size;
1709         goto end;
1710     }
1711
1712     /* check the v->cur_seg, if it is null, get current and double check if the new v->cur_seg*/
1713     if (!v->cur_seg) {
1714         v->cur_seg = get_current_fragment(v);
1715     }
1716     if (!v->cur_seg) {
1717         ret = AVERROR_EOF;
1718         goto end;
1719     }
1720     ret = read_from_url(v, v->cur_seg, buf, buf_size, READ_NORMAL);
1721     if (ret > 0)
1722         goto end;
1723
1724     if (c->is_live || v->cur_seq_no < v->last_seq_no) {
1725         if (!v->is_restart_needed)
1726             v->cur_seq_no++;
1727         v->is_restart_needed = 1;
1728     }
1729
1730 end:
1731     return ret;
1732 }
1733
1734 static int save_avio_options(AVFormatContext *s)
1735 {
1736     DASHContext *c = s->priv_data;
1737     const char *opts[] = { "headers", "user_agent", "user_agent", "cookies", NULL }, **opt = opts;
1738     uint8_t *buf = NULL;
1739     int ret = 0;
1740
1741     while (*opt) {
1742         if (av_opt_get(s->pb, *opt, AV_OPT_SEARCH_CHILDREN, &buf) >= 0) {
1743             if (buf[0] != '\0') {
1744                 ret = av_dict_set(&c->avio_opts, *opt, buf, AV_DICT_DONT_STRDUP_VAL);
1745                 if (ret < 0) {
1746                     av_freep(&buf);
1747                     return ret;
1748                 }
1749             } else {
1750                 av_freep(&buf);
1751             }
1752         }
1753         opt++;
1754     }
1755
1756     return ret;
1757 }
1758
1759 static int nested_io_open(AVFormatContext *s, AVIOContext **pb, const char *url,
1760                           int flags, AVDictionary **opts)
1761 {
1762     av_log(s, AV_LOG_ERROR,
1763            "A DASH playlist item '%s' referred to an external file '%s'. "
1764            "Opening this file was forbidden for security reasons\n",
1765            s->url, url);
1766     return AVERROR(EPERM);
1767 }
1768
1769 static void close_demux_for_component(struct representation *pls)
1770 {
1771     /* note: the internal buffer could have changed */
1772     av_freep(&pls->pb.buffer);
1773     memset(&pls->pb, 0x00, sizeof(AVIOContext));
1774     pls->ctx->pb = NULL;
1775     avformat_close_input(&pls->ctx);
1776     pls->ctx = NULL;
1777 }
1778
1779 static int reopen_demux_for_component(AVFormatContext *s, struct representation *pls)
1780 {
1781     DASHContext *c = s->priv_data;
1782     AVInputFormat *in_fmt = NULL;
1783     AVDictionary  *in_fmt_opts = NULL;
1784     uint8_t *avio_ctx_buffer  = NULL;
1785     int ret = 0, i;
1786
1787     if (pls->ctx) {
1788         close_demux_for_component(pls);
1789     }
1790     if (!(pls->ctx = avformat_alloc_context())) {
1791         ret = AVERROR(ENOMEM);
1792         goto fail;
1793     }
1794
1795     avio_ctx_buffer  = av_malloc(INITIAL_BUFFER_SIZE);
1796     if (!avio_ctx_buffer ) {
1797         ret = AVERROR(ENOMEM);
1798         avformat_free_context(pls->ctx);
1799         pls->ctx = NULL;
1800         goto fail;
1801     }
1802     if (c->is_live) {
1803         ffio_init_context(&pls->pb, avio_ctx_buffer , INITIAL_BUFFER_SIZE, 0, pls, read_data, NULL, NULL);
1804     } else {
1805         ffio_init_context(&pls->pb, avio_ctx_buffer , INITIAL_BUFFER_SIZE, 0, pls, read_data, NULL, seek_data);
1806     }
1807     pls->pb.seekable = 0;
1808
1809     if ((ret = ff_copy_whiteblacklists(pls->ctx, s)) < 0)
1810         goto fail;
1811
1812     pls->ctx->flags = AVFMT_FLAG_CUSTOM_IO;
1813     pls->ctx->probesize = 1024 * 4;
1814     pls->ctx->max_analyze_duration = 4 * AV_TIME_BASE;
1815     ret = av_probe_input_buffer(&pls->pb, &in_fmt, "", NULL, 0, 0);
1816     if (ret < 0) {
1817         av_log(s, AV_LOG_ERROR, "Error when loading first fragment, playlist %d\n", (int)pls->rep_idx);
1818         avformat_free_context(pls->ctx);
1819         pls->ctx = NULL;
1820         goto fail;
1821     }
1822
1823     pls->ctx->pb = &pls->pb;
1824     pls->ctx->io_open  = nested_io_open;
1825
1826     // provide additional information from mpd if available
1827     ret = avformat_open_input(&pls->ctx, "", in_fmt, &in_fmt_opts); //pls->init_section->url
1828     av_dict_free(&in_fmt_opts);
1829     if (ret < 0)
1830         goto fail;
1831     if (pls->n_fragments) {
1832 #if FF_API_R_FRAME_RATE
1833         if (pls->framerate.den) {
1834             for (i = 0; i < pls->ctx->nb_streams; i++)
1835                 pls->ctx->streams[i]->r_frame_rate = pls->framerate;
1836         }
1837 #endif
1838
1839         ret = avformat_find_stream_info(pls->ctx, NULL);
1840         if (ret < 0)
1841             goto fail;
1842     }
1843
1844 fail:
1845     return ret;
1846 }
1847
1848 static int open_demux_for_component(AVFormatContext *s, struct representation *pls)
1849 {
1850     int ret = 0;
1851     int i;
1852
1853     pls->parent = s;
1854     pls->cur_seq_no  = calc_cur_seg_no(s, pls);
1855
1856     if (!pls->last_seq_no) {
1857         pls->last_seq_no = calc_max_seg_no(pls, s->priv_data);
1858     }
1859
1860     ret = reopen_demux_for_component(s, pls);
1861     if (ret < 0) {
1862         goto fail;
1863     }
1864     for (i = 0; i < pls->ctx->nb_streams; i++) {
1865         AVStream *st = avformat_new_stream(s, NULL);
1866         AVStream *ist = pls->ctx->streams[i];
1867         if (!st) {
1868             ret = AVERROR(ENOMEM);
1869             goto fail;
1870         }
1871         st->id = i;
1872         avcodec_parameters_copy(st->codecpar, pls->ctx->streams[i]->codecpar);
1873         avpriv_set_pts_info(st, ist->pts_wrap_bits, ist->time_base.num, ist->time_base.den);
1874     }
1875
1876     return 0;
1877 fail:
1878     return ret;
1879 }
1880
1881 static int is_common_init_section_exist(struct representation **pls, int n_pls)
1882 {
1883     struct fragment *first_init_section = pls[0]->init_section;
1884     char *url =NULL;
1885     int64_t url_offset = -1;
1886     int64_t size = -1;
1887     int i = 0;
1888
1889     if (first_init_section == NULL || n_pls == 0)
1890         return 0;
1891
1892     url = first_init_section->url;
1893     url_offset = first_init_section->url_offset;
1894     size = pls[0]->init_section->size;
1895     for (i=0;i<n_pls;i++) {
1896         if (av_strcasecmp(pls[i]->init_section->url,url) || pls[i]->init_section->url_offset != url_offset || pls[i]->init_section->size != size) {
1897             return 0;
1898         }
1899     }
1900     return 1;
1901 }
1902
1903 static void copy_init_section(struct representation *rep_dest, struct representation *rep_src)
1904 {
1905     *rep_dest->init_section = *rep_src->init_section;
1906     rep_dest->init_sec_buf = av_mallocz(rep_src->init_sec_buf_size);
1907     memcpy(rep_dest->init_sec_buf, rep_src->init_sec_buf, rep_src->init_sec_data_len);
1908     rep_dest->init_sec_buf_size = rep_src->init_sec_buf_size;
1909     rep_dest->init_sec_data_len = rep_src->init_sec_data_len;
1910     rep_dest->cur_timestamp = rep_src->cur_timestamp;
1911 }
1912
1913
1914 static int dash_read_header(AVFormatContext *s)
1915 {
1916     void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb;
1917     DASHContext *c = s->priv_data;
1918     int ret = 0;
1919     int stream_index = 0;
1920     int i;
1921
1922     c->interrupt_callback = &s->interrupt_callback;
1923     // if the URL context is good, read important options we must broker later
1924     if (u) {
1925         update_options(&c->user_agent, "user_agent", u);
1926         update_options(&c->cookies, "cookies", u);
1927         update_options(&c->headers, "headers", u);
1928     }
1929
1930     if ((ret = parse_manifest(s, s->url, s->pb)) < 0)
1931         goto fail;
1932
1933     if ((ret = save_avio_options(s)) < 0)
1934         goto fail;
1935
1936     /* If this isn't a live stream, fill the total duration of the
1937      * stream. */
1938     if (!c->is_live) {
1939         s->duration = (int64_t) c->media_presentation_duration * AV_TIME_BASE;
1940     }
1941
1942     if(c->n_videos)
1943         c->is_init_section_common_video = is_common_init_section_exist(c->videos, c->n_videos);
1944
1945     /* Open the demuxer for video and audio components if available */
1946     for (i = 0; i < c->n_videos; i++) {
1947         struct representation *cur_video = c->videos[i];
1948         if (i > 0 && c->is_init_section_common_video) {
1949             copy_init_section(cur_video,c->videos[0]);
1950         }
1951         ret = open_demux_for_component(s, cur_video);
1952
1953         if (ret)
1954             goto fail;
1955         cur_video->stream_index = stream_index;
1956         ++stream_index;
1957     }
1958
1959     if(c->n_audios)
1960         c->is_init_section_common_audio = is_common_init_section_exist(c->audios, c->n_audios);
1961
1962     for (i = 0; i < c->n_audios; i++) {
1963         struct representation *cur_audio = c->audios[i];
1964         if (i > 0 && c->is_init_section_common_audio) {
1965             copy_init_section(cur_audio,c->audios[0]);
1966         }
1967         ret = open_demux_for_component(s, cur_audio);
1968
1969         if (ret)
1970             goto fail;
1971         cur_audio->stream_index = stream_index;
1972         ++stream_index;
1973     }
1974
1975     if (!stream_index) {
1976         ret = AVERROR_INVALIDDATA;
1977         goto fail;
1978     }
1979
1980     /* Create a program */
1981     if (!ret) {
1982         AVProgram *program;
1983         program = av_new_program(s, 0);
1984         if (!program) {
1985             goto fail;
1986         }
1987
1988         for (i = 0; i < c->n_videos; i++) {
1989             struct representation *pls = c->videos[i];
1990
1991             av_program_add_stream_index(s, 0, pls->stream_index);
1992             pls->assoc_stream = s->streams[pls->stream_index];
1993             if (pls->bandwidth > 0)
1994                 av_dict_set_int(&pls->assoc_stream->metadata, "variant_bitrate", pls->bandwidth, 0);
1995             if (pls->id[0])
1996                 av_dict_set(&pls->assoc_stream->metadata, "id", pls->id, 0);
1997         }
1998         for (i = 0; i < c->n_audios; i++) {
1999             struct representation *pls = c->audios[i];
2000
2001             av_program_add_stream_index(s, 0, pls->stream_index);
2002             pls->assoc_stream = s->streams[pls->stream_index];
2003             if (pls->bandwidth > 0)
2004                 av_dict_set_int(&pls->assoc_stream->metadata, "variant_bitrate", pls->bandwidth, 0);
2005             if (pls->id[0])
2006                 av_dict_set(&pls->assoc_stream->metadata, "id", pls->id, 0);
2007         }
2008     }
2009
2010     return 0;
2011 fail:
2012     return ret;
2013 }
2014
2015 static void recheck_discard_flags(AVFormatContext *s, struct representation **p, int n)
2016 {
2017     int i, j;
2018
2019     for (i = 0; i < n; i++) {
2020         struct representation *pls = p[i];
2021
2022         int needed = !pls->assoc_stream || pls->assoc_stream->discard < AVDISCARD_ALL;
2023         if (needed && !pls->ctx) {
2024             pls->cur_seg_offset = 0;
2025             pls->init_sec_buf_read_offset = 0;
2026             /* Catch up */
2027             for (j = 0; j < n; j++) {
2028                 pls->cur_seq_no = FFMAX(pls->cur_seq_no, p[j]->cur_seq_no);
2029             }
2030             reopen_demux_for_component(s, pls);
2031             av_log(s, AV_LOG_INFO, "Now receiving stream_index %d\n", pls->stream_index);
2032         } else if (!needed && pls->ctx) {
2033             close_demux_for_component(pls);
2034             if (pls->input)
2035                 ff_format_io_close(pls->parent, &pls->input);
2036             av_log(s, AV_LOG_INFO, "No longer receiving stream_index %d\n", pls->stream_index);
2037         }
2038     }
2039 }
2040
2041 static int dash_read_packet(AVFormatContext *s, AVPacket *pkt)
2042 {
2043     DASHContext *c = s->priv_data;
2044     int ret = 0, i;
2045     int64_t mints = 0;
2046     struct representation *cur = NULL;
2047
2048     recheck_discard_flags(s, c->videos, c->n_videos);
2049     recheck_discard_flags(s, c->audios, c->n_audios);
2050
2051     for (i = 0; i < c->n_videos; i++) {
2052         struct representation *pls = c->videos[i];
2053         if (!pls->ctx)
2054             continue;
2055         if (!cur || pls->cur_timestamp < mints) {
2056             cur = pls;
2057             mints = pls->cur_timestamp;
2058         }
2059     }
2060     for (i = 0; i < c->n_audios; i++) {
2061         struct representation *pls = c->audios[i];
2062         if (!pls->ctx)
2063             continue;
2064         if (!cur || pls->cur_timestamp < mints) {
2065             cur = pls;
2066             mints = pls->cur_timestamp;
2067         }
2068     }
2069
2070     if (!cur) {
2071         return AVERROR_INVALIDDATA;
2072     }
2073     while (!ff_check_interrupt(c->interrupt_callback) && !ret) {
2074         ret = av_read_frame(cur->ctx, pkt);
2075         if (ret >= 0) {
2076             /* If we got a packet, return it */
2077             cur->cur_timestamp = av_rescale(pkt->pts, (int64_t)cur->ctx->streams[0]->time_base.num * 90000, cur->ctx->streams[0]->time_base.den);
2078             pkt->stream_index = cur->stream_index;
2079             return 0;
2080         }
2081         if (cur->is_restart_needed) {
2082             cur->cur_seg_offset = 0;
2083             cur->init_sec_buf_read_offset = 0;
2084             if (cur->input)
2085                 ff_format_io_close(cur->parent, &cur->input);
2086             ret = reopen_demux_for_component(s, cur);
2087             cur->is_restart_needed = 0;
2088         }
2089     }
2090     return AVERROR_EOF;
2091 }
2092
2093 static int dash_close(AVFormatContext *s)
2094 {
2095     DASHContext *c = s->priv_data;
2096     free_audio_list(c);
2097     free_video_list(c);
2098
2099     av_freep(&c->cookies);
2100     av_freep(&c->user_agent);
2101     av_dict_free(&c->avio_opts);
2102     av_freep(&c->base_url);
2103     return 0;
2104 }
2105
2106 static int dash_seek(AVFormatContext *s, struct representation *pls, int64_t seek_pos_msec, int flags, int dry_run)
2107 {
2108     int ret = 0;
2109     int i = 0;
2110     int j = 0;
2111     int64_t duration = 0;
2112
2113     av_log(pls->parent, AV_LOG_VERBOSE, "DASH seek pos[%"PRId64"ms], playlist %d%s\n",
2114            seek_pos_msec, pls->rep_idx, dry_run ? " (dry)" : "");
2115
2116     // single fragment mode
2117     if (pls->n_fragments == 1) {
2118         pls->cur_timestamp = 0;
2119         pls->cur_seg_offset = 0;
2120         if (dry_run)
2121             return 0;
2122         ff_read_frame_flush(pls->ctx);
2123         return av_seek_frame(pls->ctx, -1, seek_pos_msec * 1000, flags);
2124     }
2125
2126     if (pls->input)
2127         ff_format_io_close(pls->parent, &pls->input);
2128
2129     // find the nearest fragment
2130     if (pls->n_timelines > 0 && pls->fragment_timescale > 0) {
2131         int64_t num = pls->first_seq_no;
2132         av_log(pls->parent, AV_LOG_VERBOSE, "dash_seek with SegmentTimeline start n_timelines[%d] "
2133                "last_seq_no[%"PRId64"], playlist %d.\n",
2134                (int)pls->n_timelines, (int64_t)pls->last_seq_no, (int)pls->rep_idx);
2135         for (i = 0; i < pls->n_timelines; i++) {
2136             if (pls->timelines[i]->starttime > 0) {
2137                 duration = pls->timelines[i]->starttime;
2138             }
2139             duration += pls->timelines[i]->duration;
2140             if (seek_pos_msec < ((duration * 1000) /  pls->fragment_timescale)) {
2141                 goto set_seq_num;
2142             }
2143             for (j = 0; j < pls->timelines[i]->repeat; j++) {
2144                 duration += pls->timelines[i]->duration;
2145                 num++;
2146                 if (seek_pos_msec < ((duration * 1000) /  pls->fragment_timescale)) {
2147                     goto set_seq_num;
2148                 }
2149             }
2150             num++;
2151         }
2152
2153 set_seq_num:
2154         pls->cur_seq_no = num > pls->last_seq_no ? pls->last_seq_no : num;
2155         av_log(pls->parent, AV_LOG_VERBOSE, "dash_seek with SegmentTimeline end cur_seq_no[%"PRId64"], playlist %d.\n",
2156                (int64_t)pls->cur_seq_no, (int)pls->rep_idx);
2157     } else if (pls->fragment_duration > 0) {
2158         pls->cur_seq_no = pls->first_seq_no + ((seek_pos_msec * pls->fragment_timescale) / pls->fragment_duration) / 1000;
2159     } else {
2160         av_log(pls->parent, AV_LOG_ERROR, "dash_seek missing timeline or fragment_duration\n");
2161         pls->cur_seq_no = pls->first_seq_no;
2162     }
2163     pls->cur_timestamp = 0;
2164     pls->cur_seg_offset = 0;
2165     pls->init_sec_buf_read_offset = 0;
2166     ret = dry_run ? 0 : reopen_demux_for_component(s, pls);
2167
2168     return ret;
2169 }
2170
2171 static int dash_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
2172 {
2173     int ret = 0, i;
2174     DASHContext *c = s->priv_data;
2175     int64_t seek_pos_msec = av_rescale_rnd(timestamp, 1000,
2176                                            s->streams[stream_index]->time_base.den,
2177                                            flags & AVSEEK_FLAG_BACKWARD ?
2178                                            AV_ROUND_DOWN : AV_ROUND_UP);
2179     if ((flags & AVSEEK_FLAG_BYTE) || c->is_live)
2180         return AVERROR(ENOSYS);
2181
2182     /* Seek in discarded streams with dry_run=1 to avoid reopening them */
2183     for (i = 0; i < c->n_videos; i++) {
2184         if (!ret)
2185             ret = dash_seek(s, c->videos[i], seek_pos_msec, flags, !c->videos[i]->ctx);
2186     }
2187     for (i = 0; i < c->n_audios; i++) {
2188         if (!ret)
2189             ret = dash_seek(s, c->audios[i], seek_pos_msec, flags, !c->audios[i]->ctx);
2190     }
2191
2192     return ret;
2193 }
2194
2195 static int dash_probe(AVProbeData *p)
2196 {
2197     if (!av_stristr(p->buf, "<MPD"))
2198         return 0;
2199
2200     if (av_stristr(p->buf, "dash:profile:isoff-on-demand:2011") ||
2201         av_stristr(p->buf, "dash:profile:isoff-live:2011") ||
2202         av_stristr(p->buf, "dash:profile:isoff-live:2012") ||
2203         av_stristr(p->buf, "dash:profile:isoff-main:2011")) {
2204         return AVPROBE_SCORE_MAX;
2205     }
2206     if (av_stristr(p->buf, "dash:profile")) {
2207         return AVPROBE_SCORE_MAX;
2208     }
2209
2210     return 0;
2211 }
2212
2213 #define OFFSET(x) offsetof(DASHContext, x)
2214 #define FLAGS AV_OPT_FLAG_DECODING_PARAM
2215 static const AVOption dash_options[] = {
2216     {"allowed_extensions", "List of file extensions that dash is allowed to access",
2217         OFFSET(allowed_extensions), AV_OPT_TYPE_STRING,
2218         {.str = "aac,m4a,m4s,m4v,mov,mp4"},
2219         INT_MIN, INT_MAX, FLAGS},
2220     {NULL}
2221 };
2222
2223 static const AVClass dash_class = {
2224     .class_name = "dash",
2225     .item_name  = av_default_item_name,
2226     .option     = dash_options,
2227     .version    = LIBAVUTIL_VERSION_INT,
2228 };
2229
2230 AVInputFormat ff_dash_demuxer = {
2231     .name           = "dash",
2232     .long_name      = NULL_IF_CONFIG_SMALL("Dynamic Adaptive Streaming over HTTP"),
2233     .priv_class     = &dash_class,
2234     .priv_data_size = sizeof(DASHContext),
2235     .read_probe     = dash_probe,
2236     .read_header    = dash_read_header,
2237     .read_packet    = dash_read_packet,
2238     .read_close     = dash_close,
2239     .read_seek      = dash_read_seek,
2240     .flags          = AVFMT_NO_BYTE_SEEK,
2241 };