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>
30
31 #define INITIAL_BUFFER_SIZE 32768
32
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 * */
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 * */
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 * */
64 /* duration: Element or Attribute Name
65 * specifies the Segment duration, in units of the value of the @timescale.
66 * */
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 */
85
91
94
97
100 int64_t
start_number;
/* used in case when we have dynamic list of segment to know which segments are new one*/
101
104
106
111
112 /* Currently active Media Initialization Section */
120 };
121
125
130
131 /* MediaPresentationDescription Attribute */
139
140 /* Period Attribute */
143
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
153
155 {
158 }
159
161 {
162 return ((val + 0x3F) >> 6) << 6;
163 }
164
166 {
168 }
169
171 {
172 struct tm timeinfo;
173 int year = 0;
174 int month = 0;
175 int day = 0;
176 int hour = 0;
177 int minute = 0;
178 int ret = 0;
179 float second = 0.0;
180
181 /* ISO-8601 date parser */
182 if (!datetime)
183 return 0;
184
185 ret = sscanf(datetime, "%d-%d-%dT%d:%d:%fZ", &year, &month, &day, &hour, &minute, &second);
186 /* year, month, day, hour, minute, second 6 arguments */
187 if (ret != 6) {
189 }
190 timeinfo.tm_year = year - 1900;
191 timeinfo.tm_mon = month - 1;
192 timeinfo.tm_mday = day;
193 timeinfo.tm_hour = hour;
194 timeinfo.tm_min = minute;
195 timeinfo.tm_sec = (
int)second;
196
198 }
199
201 {
202 /* ISO-8601 duration parser */
203 uint32_t days = 0;
204 uint32_t hours = 0;
205 uint32_t mins = 0;
206 uint32_t secs = 0;
211
212 while (*ptr) {
213 if (*ptr == 'P' || *ptr == 'T') {
214 ptr++;
215 continue;
216 }
217
218 if (sscanf(ptr, "%f%c%n", &value, &type, &size) != 2) {
220 return 0; /* parser error */
221 }
222 switch (type) {
223 case 'D':
224 days = (uint32_t)value;
225 break;
226 case 'H':
227 hours = (uint32_t)value;
228 break;
229 case 'M':
230 mins = (uint32_t)value;
231 break;
232 case 'S':
233 secs = (uint32_t)value;
234 break;
235 default:
236 // handle invalid type
237 break;
238 }
240 }
241 return ((days * 24 + hours) * 60 + mins) * 60 + secs;
242 }
243
245 {
247 int64_t i = 0;
248 int64_t j = 0;
249 int64_t num = 0;
250
255 }
256 if (num == cur_seq_no)
258
261 num++;
262 if (num == cur_seq_no)
265 }
266 num++;
267 }
268 }
271 }
272
274 {
275 int64_t i = 0;
276 int64_t j = 0;
277 int64_t num = 0;
279
283 }
284 if (start_time > cur_time)
286
289 num++;
290 if (start_time > cur_time)
293 }
294 num++;
295 }
296
297 return -1;
298
300 return num;
301 }
302
304 {
305 if (!(*seg)) {
306 return;
307 }
310 }
311
313 {
314 int i;
315
318 }
321 }
322
324 {
325 int i;
326
329 }
332 }
333
335 {
347 }
348
351 }
352
354 {
355 int i;
359 }
362 }
363
365 {
366 int i;
370 }
373 }
374
376 {
377 // broker prior HTTP options that should be consistent across requests
383 }
384 }
386 {
389 if (*dest)
391 }
392
395 {
398 const char *proto_name =
NULL;
399 int ret;
400
403
405 if (url[6] == '+' || url[6] == ':')
407 }
408
409 if (!proto_name)
411
412 if (!proto_name)
414
415 // only http(s) & file are allowed
419 "Filename extension of \'%s\' is not a common multimedia extension, blocked for security reasons.\n"
420 "If you wish to override this adjust allowed_extensions, you can set it to \'ALL\' to allow all\n",
421 url);
423 }
425 ;
426 } else
428
429 if (!strncmp(proto_name, url, strlen(proto_name)) && url[strlen(proto_name)] == ':')
430 ;
431 else if (
av_strstart(url,
"crypto",
NULL) && !strncmp(proto_name, url + 7, strlen(proto_name)) && url[7 + strlen(proto_name)] ==
':')
432 ;
433 else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5))
435
438 if (ret >= 0) {
439 // update cookies on http response with setcookies.
440 char *new_cookies =
NULL;
441
444
445 if (new_cookies) {
448 }
449
451 }
452
454
455 if (is_http)
457
458 return ret;
459 }
460
462 int n_baseurl_nodes,
463 int max_url_size,
464 char *rep_id_val,
465 char *rep_bandwidth_val,
467 {
468 int i;
469 char *text;
473
474 if (!tmp_str || !tmp_str_2) {
476 }
477
478 for (i = 0; i < n_baseurl_nodes; ++i) {
479 if (baseurl_nodes[i] &&
480 baseurl_nodes[i]->children &&
481 baseurl_nodes[i]->children->type == XML_TEXT_NODE) {
482 text = xmlNodeGetContent(baseurl_nodes[i]->children);
483 if (text) {
484 memset(tmp_str, 0, max_url_size);
485 memset(tmp_str_2, 0, max_url_size);
488 xmlFree(text);
489 }
490 }
491 }
492
493 if (val)
494 av_strlcat(tmp_str, (
const char*)val, max_url_size);
495
496 if (rep_id_val) {
497 url =
av_strireplace(tmp_str,
"$RepresentationID$", (
const char*)rep_id_val);
498 if (!url) {
500 }
502 }
503 if (rep_bandwidth_val && tmp_str[0] != '0円') {
504 // free any previously assigned url before reassigning
506 url =
av_strireplace(tmp_str,
"$Bandwidth$", (
const char*)rep_bandwidth_val);
507 if (!url) {
509 }
510 }
514 return url;
515 }
516
518 {
519 int i;
521
522 for (i = 0; i < n_nodes; ++i) {
523 if (nodes[i]) {
524 val = xmlGetProp(nodes[i], attrname);
525 if (val)
527 }
528 }
529
531 }
532
534 {
535 xmlNodePtr node = rootnode;
536 if (!node) {
538 }
539
540 node = xmlFirstElementChild(node);
541 while (node) {
543 return node;
544 }
545 node = xmlNextElementSibling(node);
546 }
548 }
549
551 {
553 int i = 0;
554 const char *attr;
556
557 if (node) {
558 for (i = 0; i < 2; i++) {
559 attr = i ? "mimeType" : "contentType";
560 val = xmlGetProp(node, attr);
561 if (val) {
564 }
else if (
av_stristr((
const char *)val,
"audio")) {
566 }
567 xmlFree(val);
568 }
569 }
570 }
572 }
573
575 {
577
578 if (!seg)
580
582 if (range) {
583 char *str_end_offset;
584 char *str_offset =
av_strtok(range,
"-", &str_end_offset);
587 }
588
589 return seg;
590 }
591
593 xmlNodePtr fragmenturl_node,
594 xmlNodePtr *baseurl_nodes,
595 char *rep_id_val,
596 char *rep_bandwidth_val)
597 {
599 char *initialization_val =
NULL;
600 char *media_val =
NULL;
601 char *range_val =
NULL;
603
604 if (!
av_strcasecmp(fragmenturl_node->name, (
const char *)
"Initialization")) {
605 initialization_val = xmlGetProp(fragmenturl_node, "sourceURL");
606 range_val = xmlGetProp(fragmenturl_node, "range");
607 if (initialization_val || range_val) {
610 xmlFree(initialization_val);
611 xmlFree(range_val);
613 }
615 max_url_size,
616 rep_id_val,
617 rep_bandwidth_val,
618 initialization_val);
619
622 xmlFree(initialization_val);
623 xmlFree(range_val);
625 }
626 xmlFree(initialization_val);
627 xmlFree(range_val);
628 }
629 }
else if (!
av_strcasecmp(fragmenturl_node->name, (
const char *)
"SegmentURL")) {
630 media_val = xmlGetProp(fragmenturl_node, "media");
631 range_val = xmlGetProp(fragmenturl_node, "mediaRange");
632 if (media_val || range_val) {
634 if (!seg) {
635 xmlFree(media_val);
636 xmlFree(range_val);
638 }
640 max_url_size,
641 rep_id_val,
642 rep_bandwidth_val,
643 media_val);
646 xmlFree(media_val);
647 xmlFree(range_val);
649 }
651 xmlFree(media_val);
652 xmlFree(range_val);
653 }
654 }
655
656 return 0;
657 }
658
660 xmlNodePtr fragment_timeline_node)
661 {
662 xmlAttrPtr attr =
NULL;
664
665 if (!
av_strcasecmp(fragment_timeline_node->name, (
const char *)
"S")) {
667 if (!tml) {
669 }
670 attr = fragment_timeline_node->properties;
671 while (attr) {
672 val = xmlGetProp(fragment_timeline_node, attr->name);
673
674 if (!val) {
675 av_log(s,
AV_LOG_WARNING,
"parse_manifest_segmenttimeline attr->name = %s val is NULL\n", attr->name);
676 continue;
677 }
678
682 tml->
repeat =(int64_t) strtoll(val,
NULL, 10);
685 }
686 attr = attr->next;
687 xmlFree(val);
688 }
690 }
691
692 return 0;
693 }
694
696
697 char *tmp_str =
NULL;
699 char *mpdName =
NULL;
700 xmlNodePtr node =
NULL;
701 char *baseurl =
NULL;
702 char *root_url =
NULL;
704
705 int isRootHttp = 0;
706 char token ='/';
708 int rootId = 0;
709 int updated = 0;
711 int i;
712 int tmp_max_url_size = strlen(url);
713
714 for (i = n_baseurl_nodes-1; i >= 0 ; i--) {
715 text = xmlNodeGetContent(baseurl_nodes[i]);
716 if (!text)
717 continue;
718 tmp_max_url_size += strlen(text);
720 xmlFree(text);
721 break;
722 }
723 xmlFree(text);
724 }
725
726 tmp_max_url_size =
aligned(tmp_max_url_size);
728 if (!text) {
731 }
733 while (mpdName =
av_strtok(text,
"/", &text)) {
734 size = strlen(mpdName);
735 }
736
739 if (!tmp_str || !path) {
742 }
743
744 av_strlcpy (path, url, strlen(url) - size + 1);
745 for (rootId = n_baseurl_nodes - 1; rootId > 0; rootId --) {
746 if (!(node = baseurl_nodes[rootId])) {
747 continue;
748 }
749 if (
ishttp(xmlNodeGetContent(node))) {
750 break;
751 }
752 }
753
754 node = baseurl_nodes[rootId];
755 baseurl = xmlNodeGetContent(node);
757 if (node) {
758 xmlNodeSetContent(node, root_url);
759 updated = 1;
760 }
761
762 size = strlen(root_url);
763 isRootHttp =
ishttp(root_url);
764
765 if (root_url[size - 1] != token) {
767 size += 2;
768 }
769
770 for (i = 0; i < n_baseurl_nodes; ++i) {
771 if (i == rootId) {
772 continue;
773 }
774 text = xmlNodeGetContent(baseurl_nodes[i]);
775 if (text) {
776 memset(tmp_str, 0, strlen(tmp_str));
777 if (!
ishttp(text) && isRootHttp) {
779 }
780 start = (text[0] == token);
781 av_strlcat(tmp_str, text + start, tmp_max_url_size);
782 xmlNodeSetContent(baseurl_nodes[i], tmp_str);
783 updated = 1;
784 xmlFree(text);
785 }
786 }
787
789 if (tmp_max_url_size > *max_url_size) {
790 *max_url_size = tmp_max_url_size;
791 }
794 return updated;
795
796 }
797
799 xmlNodePtr node,
800 xmlNodePtr adaptionset_node,
801 xmlNodePtr mpd_baseurl_node,
802 xmlNodePtr period_baseurl_node,
803 xmlNodePtr period_segmenttemplate_node,
804 xmlNodePtr period_segmentlist_node,
805 xmlNodePtr fragment_template_node,
806 xmlNodePtr content_component_node,
807 xmlNodePtr adaptionset_baseurl_node,
808 xmlNodePtr adaptionset_segmentlist_node,
809 xmlNodePtr adaptionset_supplementalproperty_node)
810 {
817 xmlNodePtr representation_segmenttemplate_node =
NULL;
818 xmlNodePtr representation_baseurl_node =
NULL;
819 xmlNodePtr representation_segmentlist_node =
NULL;
820 xmlNodePtr segmentlists_tab[2];
821 xmlNodePtr fragment_timeline_node =
NULL;
822 xmlNodePtr fragment_templates_tab[5];
823 char *duration_val =
NULL;
824 char *presentation_timeoffset_val =
NULL;
825 char *startnumber_val =
NULL;
826 char *timescale_val =
NULL;
827 char *initialization_val =
NULL;
828 char *media_val =
NULL;
830 xmlNodePtr baseurl_nodes[4];
831 xmlNodePtr representation_node = node;
832 char *rep_id_val = xmlGetProp(representation_node, "id");
833 char *rep_bandwidth_val = xmlGetProp(representation_node, "bandwidth");
834 char *rep_framerate_val = xmlGetProp(representation_node, "frameRate");
836
837 // try get information from representation
840 // try get information from contentComponen
843 // try get information from adaption set
849 // convert selected representation to our internal struct
851 if (!rep) {
854 }
858
859 baseurl_nodes[0] = mpd_baseurl_node;
860 baseurl_nodes[1] = period_baseurl_node;
861 baseurl_nodes[2] = adaptionset_baseurl_node;
862 baseurl_nodes[3] = representation_baseurl_node;
863
866 if (ret ==
AVERROR(ENOMEM) || ret == 0) {
868 }
869 if (representation_segmenttemplate_node || fragment_template_node || period_segmenttemplate_node) {
870 fragment_timeline_node =
NULL;
871 fragment_templates_tab[0] = representation_segmenttemplate_node;
872 fragment_templates_tab[1] = adaptionset_segmentlist_node;
873 fragment_templates_tab[2] = fragment_template_node;
874 fragment_templates_tab[3] = period_segmenttemplate_node;
875 fragment_templates_tab[4] = period_segmentlist_node;
876
877 presentation_timeoffset_val =
get_val_from_nodes_tab(fragment_templates_tab, 4,
"presentationTimeOffset");
883
884 if (initialization_val) {
890 }
898 }
900 xmlFree(initialization_val);
901 }
902
903 if (media_val) {
906 xmlFree(media_val);
907 }
908
909 if (presentation_timeoffset_val) {
911 xmlFree(presentation_timeoffset_val);
912 }
913 if (duration_val) {
915 xmlFree(duration_val);
916 }
917 if (timescale_val) {
919 xmlFree(timescale_val);
920 }
921 if (startnumber_val) {
923 xmlFree(startnumber_val);
924 }
925 if (adaptionset_supplementalproperty_node) {
926 if (!
av_strcasecmp(xmlGetProp(adaptionset_supplementalproperty_node,
"schemeIdUri"),
"http://dashif.org/guidelines/last-segment-number")) {
927 val = xmlGetProp(adaptionset_supplementalproperty_node,"value");
928 if (!val) {
929 av_log(s,
AV_LOG_ERROR,
"Missing value attribute in adaptionset_supplementalproperty_node\n");
930 } else {
932 xmlFree(val);
933 }
934 }
935 }
936
938
939 if (!fragment_timeline_node)
941 if (!fragment_timeline_node)
943 if (!fragment_timeline_node)
945 if (fragment_timeline_node) {
946 fragment_timeline_node = xmlFirstElementChild(fragment_timeline_node);
947 while (fragment_timeline_node) {
949 if (ret < 0) {
950 return ret;
951 }
952 fragment_timeline_node = xmlNextElementSibling(fragment_timeline_node);
953 }
954 }
955 } else if (representation_baseurl_node && !representation_segmentlist_node) {
957 if (!seg) {
960 }
966 }
969 } else if (representation_segmentlist_node) {
970 // TODO: https://www.brendanlong.com/the-structure-of-an-mpeg-dash-mpd.html
971 // http://www-itec.uni-klu.ac.at/dash/ddash/mpdGenerator.php?fragmentlength=15&type=full
972 xmlNodePtr fragmenturl_node =
NULL;
973 segmentlists_tab[0] = representation_segmentlist_node;
974 segmentlists_tab[1] = adaptionset_segmentlist_node;
975
978 if (duration_val) {
980 xmlFree(duration_val);
981 }
982 if (timescale_val) {
984 xmlFree(timescale_val);
985 }
986 fragmenturl_node = xmlFirstElementChild(representation_segmentlist_node);
987 while (fragmenturl_node) {
989 baseurl_nodes,
990 rep_id_val,
991 rep_bandwidth_val);
992 if (ret < 0) {
993 return ret;
994 }
995 fragmenturl_node = xmlNextElementSibling(fragmenturl_node);
996 }
997
999
1000 if (!fragment_timeline_node)
1002 if (!fragment_timeline_node)
1004 if (!fragment_timeline_node)
1006 if (fragment_timeline_node) {
1007 fragment_timeline_node = xmlFirstElementChild(fragment_timeline_node);
1008 while (fragment_timeline_node) {
1010 if (ret < 0) {
1011 return ret;
1012 }
1013 fragment_timeline_node = xmlNextElementSibling(fragment_timeline_node);
1014 }
1015 }
1016 } else {
1019 av_log(s,
AV_LOG_ERROR,
"Unknown format of Representation node id[%s] \n", (
const char *)rep_id_val);
1020 }
1021
1022 if (rep) {
1025 rep->
bandwidth = rep_bandwidth_val ? atoi(rep_bandwidth_val) : 0;
1026 strncpy(rep->
id, rep_id_val ? rep_id_val :
"",
sizeof(rep->
id));
1030 if (ret < 0)
1032 }
1033
1037 } else {
1040 }
1041 }
1042 }
1043
1046
1048 if (rep_id_val)
1049 xmlFree(rep_id_val);
1050 if (rep_bandwidth_val)
1051 xmlFree(rep_bandwidth_val);
1052 if (rep_framerate_val)
1053 xmlFree(rep_framerate_val);
1054
1055 return ret;
1056 }
1057
1059 xmlNodePtr adaptionset_node,
1060 xmlNodePtr mpd_baseurl_node,
1061 xmlNodePtr period_baseurl_node,
1062 xmlNodePtr period_segmenttemplate_node,
1063 xmlNodePtr period_segmentlist_node)
1064 {
1065 int ret = 0;
1066 xmlNodePtr fragment_template_node =
NULL;
1067 xmlNodePtr content_component_node =
NULL;
1068 xmlNodePtr adaptionset_baseurl_node =
NULL;
1069 xmlNodePtr adaptionset_segmentlist_node =
NULL;
1070 xmlNodePtr adaptionset_supplementalproperty_node =
NULL;
1071 xmlNodePtr node =
NULL;
1072
1073 node = xmlFirstElementChild(adaptionset_node);
1074 while (node) {
1075 if (!
av_strcasecmp(node->name, (
const char *)
"SegmentTemplate")) {
1076 fragment_template_node = node;
1077 }
else if (!
av_strcasecmp(node->name, (
const char *)
"ContentComponent")) {
1078 content_component_node = node;
1079 }
else if (!
av_strcasecmp(node->name, (
const char *)
"BaseURL")) {
1080 adaptionset_baseurl_node = node;
1081 }
else if (!
av_strcasecmp(node->name, (
const char *)
"SegmentList")) {
1082 adaptionset_segmentlist_node = node;
1083 }
else if (!
av_strcasecmp(node->name, (
const char *)
"SupplementalProperty")) {
1084 adaptionset_supplementalproperty_node = node;
1085 }
else if (!
av_strcasecmp(node->name, (
const char *)
"Representation")) {
1087 adaptionset_node,
1088 mpd_baseurl_node,
1089 period_baseurl_node,
1090 period_segmenttemplate_node,
1091 period_segmentlist_node,
1092 fragment_template_node,
1093 content_component_node,
1094 adaptionset_baseurl_node,
1095 adaptionset_segmentlist_node,
1096 adaptionset_supplementalproperty_node);
1097 if (ret < 0) {
1098 return ret;
1099 }
1100 }
1101 node = xmlNextElementSibling(node);
1102 }
1103 return 0;
1104 }
1105
1107 {
1109 int ret = 0;
1110 int close_in = 0;
1112 int64_t filesize = 0;
1116 xmlNodePtr root_element =
NULL;
1117 xmlNodePtr node =
NULL;
1118 xmlNodePtr period_node =
NULL;
1119 xmlNodePtr mpd_baseurl_node =
NULL;
1120 xmlNodePtr period_baseurl_node =
NULL;
1121 xmlNodePtr period_segmenttemplate_node =
NULL;
1122 xmlNodePtr period_segmentlist_node =
NULL;
1123 xmlNodePtr adaptionset_node =
NULL;
1124 xmlAttrPtr attr =
NULL;
1126 uint32_t period_duration_sec = 0;
1127 uint32_t period_start_sec = 0;
1128
1129 if (!in) {
1130 close_in = 1;
1131
1135 if (ret < 0)
1136 return ret;
1137 }
1138
1141 } else {
1143 }
1144
1146 if (filesize <= 0) {
1147 filesize = 8 * 1024;
1148 }
1149
1151 if (!buffer) {
1154 }
1155
1156 filesize =
avio_read(in, buffer, filesize);
1157 if (filesize <= 0) {
1160 } else {
1161 LIBXML_TEST_VERSION
1162
1163 doc = xmlReadMemory(buffer, filesize, c->
base_url,
NULL, 0);
1164 root_element = xmlDocGetRootElement(doc);
1165 node = root_element;
1166
1167 if (!node) {
1171 }
1172
1173 if (node->type != XML_ELEMENT_NODE ||
1176 av_log(s,
AV_LOG_ERROR,
"Unable to parse '%s' - wrong root node name[%s] type[%d]\n", url, node->name, (
int)node->type);
1178 }
1179
1180 val = xmlGetProp(node, "type");
1181 if (!val) {
1185 }
1188 xmlFree(val);
1189
1190 attr = node->properties;
1191 while (attr) {
1192 val = xmlGetProp(node, attr->name);
1193
1194 if (!
av_strcasecmp(attr->name, (
const char *)
"availabilityStartTime")) {
1196 }
else if (!
av_strcasecmp(attr->name, (
const char *)
"publishTime")) {
1198 }
else if (!
av_strcasecmp(attr->name, (
const char *)
"minimumUpdatePeriod")) {
1200 }
else if (!
av_strcasecmp(attr->name, (
const char *)
"timeShiftBufferDepth")) {
1202 }
else if (!
av_strcasecmp(attr->name, (
const char *)
"minBufferTime")) {
1204 }
else if (!
av_strcasecmp(attr->name, (
const char *)
"suggestedPresentationDelay")) {
1206 }
else if (!
av_strcasecmp(attr->name, (
const char *)
"mediaPresentationDuration")) {
1208 }
1209 attr = attr->next;
1210 xmlFree(val);
1211 }
1212
1214 if (!mpd_baseurl_node) {
1215 mpd_baseurl_node = xmlNewNode(
NULL,
"BaseURL");
1216 }
1217
1218 // at now we can handle only one period, with the longest duration
1219 node = xmlFirstElementChild(node);
1220 while (node) {
1222 period_duration_sec = 0;
1223 period_start_sec = 0;
1224 attr = node->properties;
1225 while (attr) {
1226 val = xmlGetProp(node, attr->name);
1229 }
else if (!
av_strcasecmp(attr->name, (
const char *)
"start")) {
1231 }
1232 attr = attr->next;
1233 xmlFree(val);
1234 }
1236 period_node = node;
1241 }
1242 }
1243 node = xmlNextElementSibling(node);
1244 }
1245 if (!period_node) {
1249 }
1250
1251 adaptionset_node = xmlFirstElementChild(period_node);
1252 while (adaptionset_node) {
1253 if (!
av_strcasecmp(adaptionset_node->name, (
const char *)
"BaseURL")) {
1254 period_baseurl_node = adaptionset_node;
1255 }
else if (!
av_strcasecmp(adaptionset_node->name, (
const char *)
"SegmentTemplate")) {
1256 period_segmenttemplate_node = adaptionset_node;
1257 }
else if (!
av_strcasecmp(adaptionset_node->name, (
const char *)
"SegmentList")) {
1258 period_segmentlist_node = adaptionset_node;
1259 }
else if (!
av_strcasecmp(adaptionset_node->name, (
const char *)
"AdaptationSet")) {
1260 parse_manifest_adaptationset(s, url, adaptionset_node, mpd_baseurl_node, period_baseurl_node, period_segmenttemplate_node, period_segmentlist_node);
1261 }
1262 adaptionset_node = xmlNextElementSibling(adaptionset_node);
1263 }
1265 /*free the document */
1266 xmlFreeDoc(doc);
1267 xmlCleanupParser();
1268 }
1269
1272 if (close_in) {
1274 }
1275 return ret;
1276 }
1277
1279 {
1281 int64_t num = 0;
1282 int64_t start_time_offset = 0;
1283
1290 if (num == -1)
1292 else
1299 } else {
1301 }
1302 }
1303 } else {
1305 }
1306 return num;
1307 }
1308
1310 {
1312 int64_t num = 0;
1313
1316 } else {
1318 }
1319 return num;
1320 }
1321
1323 {
1324 int64_t num = 0;
1325
1329 int i = 0;
1333 }
1338 }
1339
1340 return num;
1341 }
1342
1344 {
1345 if (rep_dest && rep_src ) {
1354 }
1355 }
1356
1358 {
1359 if (rep_dest && rep_src ) {
1363 else
1371 }
1372 }
1373
1374
1376 {
1377
1378 int ret = 0, i;
1380
1381 // save current context
1387
1394 if (ret)
1396
1399 "new manifest has mismatched no. of video representations, %d -> %d\n",
1402 }
1405 "new manifest has mismatched no. of audio representations, %d -> %d\n",
1408 }
1409
1410 for (i = 0; i < n_videos; i++) {
1414 // calc current time
1416 // update segments
1420 }
1421 }
1424 }
1425 }
1426 for (i = 0; i < n_audios; i++) {
1430 // calc current time
1432 // update segments
1436 }
1437 }
1440 }
1441 }
1442
1444 // restore context
1447 else
1457 return ret;
1458 }
1459
1461 {
1462 int64_t min_seq_no = 0;
1463 int64_t max_seq_no = 0;
1467
1472 if (!seg) {
1474 }
1479 }
1482 return seg;
1485 } else {
1486 break;
1487 }
1488 }
1492
1495 }
1501 }
1503 if (!seg) {
1505 }
1508 if (!seg) {
1510 }
1511 }
1512 if (seg) {
1514 if (!tmpfilename) {
1516 }
1526 }
1527 }
1530 }
1531
1532 return seg;
1533 }
1534
1538 };
1539
1543 {
1544 int ret;
1545
1546 /* limit read if the fragment was only a part of a file */
1549
1552 if (ret < buf_size) {
1554 }
1555 } else {
1557 }
1558 if (ret > 0)
1560
1561 return ret;
1562 }
1563
1565 {
1568 int ret = 0;
1569
1571 if (!url) {
1573 }
1575 if (seg->
size >= 0) {
1576 /* try to restrict the HTTP request to the part we want
1577 * (if this is in fact a HTTP request) */
1580 }
1581
1586 if (ret < 0) {
1588 }
1589
1595 return ret;
1596 }
1597
1599 {
1600 static const int max_init_section_size = 1024 * 1024;
1602 int64_t sec_size;
1603 int64_t urlsize;
1604 int ret;
1605
1607 return 0;
1608
1610 if (ret < 0) {
1612 "Failed to open an initialization section in playlist %d\n",
1614 return ret;
1615 }
1616
1620 sec_size = urlsize;
1621 else
1622 sec_size = max_init_section_size;
1623
1625 "Downloading an initialization section of size %"PRId64"\n",
1626 sec_size);
1627
1628 sec_size =
FFMIN(sec_size, max_init_section_size);
1629
1631
1635
1636 if (ret < 0)
1637 return ret;
1638
1641
1642 return 0;
1643 }
1644
1646 {
1650 }
1651
1653 }
1654
1656 {
1657 int ret = 0;
1660
1661 restart:
1668 }
1669
1670 /* load/update Media Initialization Section, if any */
1672 if (ret)
1674
1676 if (ret < 0) {
1680 }
1683 goto restart;
1684 }
1685 }
1686
1688 /* Push init section out first before first actual fragment */
1692 ret = copy_size;
1694 }
1695
1696 /* check the v->cur_seg, if it is null, get current and double check if the new v->cur_seg*/
1699 }
1703 }
1705 if (ret > 0)
1707
1712 }
1713
1715 return ret;
1716 }
1717
1719 {
1721 const char *
opts[] = {
"headers",
"user_agent",
"user-agent",
"cookies",
NULL }, **opt =
opts;
1723 int ret = 0;
1724
1725 while (*opt) {
1727 if (buf[0] != '0円') {
1729 if (ret < 0) {
1731 return ret;
1732 }
1733 } else {
1735 }
1736 }
1737 opt++;
1738 }
1739
1740 return ret;
1741 }
1742
1745 {
1747 "A DASH playlist item '%s' referred to an external file '%s'. "
1748 "Opening this file was forbidden for security reasons\n",
1749 s->filename, url);
1751 }
1752
1754 {
1755 /* note: the internal buffer could have changed */
1761 }
1762
1764 {
1769 int ret = 0, i;
1770
1773 }
1777 }
1778
1780 if (!avio_ctx_buffer ) {
1785 }
1788 } else {
1790 }
1792
1795
1800 if (ret < 0) {
1805 }
1806
1809
1810 // provide additional information from mpd if available
1813 if (ret < 0)
1816 #if FF_API_R_FRAME_RATE
1820 }
1821 #endif
1822
1824 if (ret < 0)
1826 }
1827
1829 return ret;
1830 }
1831
1833 {
1834 int ret = 0;
1835 int i;
1836
1839
1842 }
1843
1845 if (ret < 0) {
1847 }
1851 if (!st) {
1854 }
1858 }
1859
1860 return 0;
1862 return ret;
1863 }
1864
1866 {
1869 int ret = 0;
1871 int i;
1872
1874 // if the URL context is good, read important options we must broker later
1879 }
1880
1883
1886
1887 /* If this isn't a live stream, fill the total duration of the
1888 * stream. */
1891 }
1892
1893 /* Open the demuxer for video and audio components if available */
1894 for (i = 0; i <
c->n_videos; i++) {
1897 if (ret)
1901 }
1902
1903 for (i = 0; i <
c->n_audios; i++) {
1906 if (ret)
1910 }
1911
1915 }
1916
1917 /* Create a program */
1918 if (!ret) {
1921 if (!program) {
1923 }
1924
1925 for (i = 0; i <
c->n_videos; i++) {
1927
1934 }
1935 for (i = 0; i <
c->n_audios; i++) {
1937
1944 }
1945 }
1946
1947 return 0;
1949 return ret;
1950 }
1951
1953 {
1954 int i, j;
1955
1956 for (i = 0; i <
n; i++) {
1958
1960 if (needed && !pls->
ctx) {
1963 /* Catch up */
1964 for (j = 0; j <
n; j++) {
1966 }
1969 }
else if (!needed && pls->
ctx) {
1974 }
1975 }
1976 }
1977
1979 {
1981 int ret = 0, i;
1982 int64_t mints = 0;
1984
1987
1988 for (i = 0; i < c->
n_videos; i++) {
1991 continue;
1993 cur = pls;
1995 }
1996 }
1997 for (i = 0; i < c->
n_audios; i++) {
2000 continue;
2002 cur = pls;
2004 }
2005 }
2006
2007 if (!cur) {
2009 }
2012 if (ret >= 0) {
2013 /* If we got a packet, return it */
2016 return 0;
2017 }
2025 }
2026 }
2028 }
2029
2031 {
2035
2040 return 0;
2041 }
2042
2044 {
2045 int ret = 0;
2046 int i = 0;
2047 int j = 0;
2049
2051 seek_pos_msec, pls->
rep_idx, dry_run ?
" (dry)" :
"");
2052
2053 // single fragment mode
2057 if (dry_run)
2058 return 0;
2061 }
2062
2065
2066 // find the nearest fragment
2070 "last_seq_no[%"PRId64"], playlist %d.\n",
2075 }
2078 goto set_seq_num;
2079 }
2082 num++;
2084 goto set_seq_num;
2085 }
2086 }
2087 num++;
2088 }
2089
2090 set_seq_num:
2096 } else {
2099 }
2104
2105 return ret;
2106 }
2107
2109 {
2110 int ret = 0, i;
2118
2119 /* Seek in discarded streams with dry_run=1 to avoid reopening them */
2120 for (i = 0; i < c->
n_videos; i++) {
2121 if (!ret)
2123 }
2124 for (i = 0; i < c->
n_audios; i++) {
2125 if (!ret)
2127 }
2128
2129 return ret;
2130 }
2131
2133 {
2135 return 0;
2136
2137 if (
av_stristr(p->
buf,
"dash:profile:isoff-on-demand:2011") ||
2142 }
2145 }
2146
2147 return 0;
2148 }
2149
2150 #define OFFSET(x) offsetof(DASHContext, x)
2151 #define FLAGS AV_OPT_FLAG_DECODING_PARAM
2153 {"allowed_extensions", "List of file extensions that dash is allowed to access",
2155 {.str = "aac,m4a,m4s,m4v,mov,mp4"},
2156 INT_MIN, INT_MAX,
FLAGS},
2158 };
2159
2165 };
2166
2178 };
time_t av_timegm(struct tm *tm)
Convert the decomposed UTC time in tm to a time_t value.
int64_t probesize
Maximum size of the data read from input for determining the input container format.
const char const char void * val
void ff_make_absolute_url(char *buf, int size, const char *base, const char *rel)
Convert a relative url into an absolute url, given a base url.
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
int64_t avio_size(AVIOContext *s)
Get the filesize.
char * allowed_extensions
int av_parse_video_rate(AVRational *rate, const char *arg)
Parse str and store the detected values in *rate.
AVIOInterruptCB interrupt_callback
Custom interrupt callbacks for the I/O layer.
static int64_t get_segment_start_time_based_on_timeline(struct representation *pls, int64_t cur_seq_no)
#define AV_LOG_WARNING
Something somehow does not look correct.
#define LIBAVUTIL_VERSION_INT
static int read_data(void *opaque, uint8_t *buf, int buf_size)
char * av_stristr(const char *s1, const char *s2)
Locate the first case-independent occurrence in the string haystack of the string needle...
static int read_seek(AVFormatContext *ctx, int stream_index, int64_t timestamp, int flags)
static int ishttp(char *url)
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
const char * av_default_item_name(void *ptr)
Return the context name.
#define AVIO_FLAG_READ
read-only
unsigned char * buffer
Start of the buffer.
static struct fragment * get_current_fragment(struct representation *pls)
int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
Copy entries from one AVDictionary struct into another.
static const AVOption dash_options[]
static int64_t seek_data(void *opaque, int64_t offset, int whence)
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
char * headers
holds HTTP headers set as an AVOption to the HTTP protocol context
static int parse_manifest_segmenturlnode(AVFormatContext *s, struct representation *rep, xmlNodePtr fragmenturl_node, xmlNodePtr *baseurl_nodes, char *rep_id_val, char *rep_bandwidth_val)
static void free_fragment(struct fragment **seg)
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
struct fragment * init_section
uint32_t init_sec_buf_read_offset
static uint64_t get_utc_date_time_insec(AVFormatContext *s, const char *datetime)
static int64_t start_time
uint64_t suggested_presentation_delay
uint64_t media_presentation_duration
static void set_httpheader_options(DASHContext *c, AVDictionary **opts)
static av_cold int end(AVCodecContext *avctx)
int64_t presentation_timeoffset
int id
Format-specific stream ID.
static int dash_close(AVFormatContext *s)
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
#define u(width, name, range_min, range_max)
AVStream ** streams
A list of all streams in the file.
AVFormatContext * avformat_alloc_context(void)
Allocate an AVFormatContext.
int flags
Flags modifying the (de)muxer behaviour.
AVProgram * av_new_program(AVFormatContext *s, int id)
struct timeline ** timelines
#define AVERROR_EOF
End of file.
static av_cold int read_close(AVFormatContext *ctx)
#define AV_LOG_VERBOSE
Detailed information.
int av_match_ext(const char *filename, const char *extensions)
Return a positive value if the given filename has one of the given extensions, 0 otherwise.
static void recheck_discard_flags(AVFormatContext *s, struct representation **p, int n)
uint64_t availability_start_time
static enum AVMediaType get_content_type(xmlNodePtr node)
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
struct representation ** audios
#define INITIAL_BUFFER_SIZE
static xmlNodePtr find_child_node_by_name(xmlNodePtr rootnode, const char *nodename)
static int aligned(int val)
Callback for checking whether to abort blocking functions.
int av_probe_input_buffer(AVIOContext *pb, AVInputFormat **fmt, const char *url, void *logctx, unsigned int offset, unsigned int max_probe_size)
Like av_probe_input_buffer2() but returns 0 on success.
int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src)
Copy the contents of src to dst.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
uint32_t init_sec_data_len
static void free_timelines_list(struct representation *pls)
static void move_segments(struct representation *rep_src, struct representation *rep_dest, DASHContext *c)
static int64_t calc_max_seg_no(struct representation *pls, DASHContext *c)
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
static int64_t calc_cur_seg_no(AVFormatContext *s, struct representation *pls)
int avio_close(AVIOContext *s)
Close the resource accessed by the AVIOContext s and free it.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values. ...
static int dash_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
char * av_strireplace(const char *str, const char *from, const char *to)
Locale-independent strings replace.
static const uint8_t offset[127][2]
New fields can be added to the end with minor version bumps.
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
static int read_from_url(struct representation *pls, struct fragment *seg, uint8_t *buf, int buf_size, enum ReadFromURLMode mode)
void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size)
Allocate a buffer, reusing the given one if large enough.
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
uint64_t minimum_update_period
struct fragment ** fragments
static void free_representation(struct representation *pls)
AVIOInterruptCB * interrupt_callback
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
static void free_audio_list(DASHContext *c)
char * user_agent
holds HTTP user agent set as an AVOption to the HTTP protocol context
int seekable
A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable.
int64_t av_rescale(int64_t a, int64_t b, int64_t c)
Rescale a 64-bit integer with rounding to nearest.
#define AV_TIME_BASE
Internal time base represented as integer.
void av_program_add_stream_index(AVFormatContext *ac, int progid, unsigned int idx)
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
static void free_fragment_list(struct representation *pls)
#define AV_OPT_SEARCH_CHILDREN
Search in possible children of the given object first.
#define AV_DICT_DONT_STRDUP_VAL
Take ownership of a value that's been allocated with av_malloc() or another memory allocation functio...
GLsizei GLboolean const GLfloat * value
static void move_timelines(struct representation *rep_src, struct representation *rep_dest, DASHContext *c)
static uint32_t get_duration_insec(AVFormatContext *s, const char *duration)
static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url, AVDictionary *opts, AVDictionary *opts2, int *is_http)
static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in)
Usually treated as AVMEDIA_TYPE_DATA.
static int save_avio_options(AVFormatContext *s)
#define AVERROR_EXIT
Immediate exit was requested; the called function should not be restarted.
int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd)
Rescale a 64-bit integer with specified rounding.
int64_t max_analyze_duration
Maximum duration (in AV_TIME_BASE units) of the data read from input in avformat_find_stream_info().
static char * get_val_from_nodes_tab(xmlNodePtr *nodes, const int n_nodes, const char *attrname)
static int nested_io_open(AVFormatContext *s, AVIOContext **pb, const char *url, int flags, AVDictionary **opts)
static int read_header(FFV1Context *f)
int64_t av_gettime(void)
Get the current time in microseconds.
static int dash_probe(AVProbeData *p)
void ff_dash_fill_tmpl_params(char *dst, size_t buffer_size, const char *template, int rep_id, int number, int bit_rate, int64_t time)
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
#define AV_LOG_INFO
Standard information.
char * av_strdup(const char *s)
Duplicate a string.
int ff_check_interrupt(AVIOInterruptCB *cb)
Check if the user has requested to interrupt a blocking function associated with cb.
AVIOContext * pb
I/O context.
static AVRational av_make_q(int num, int den)
Create an AVRational.
uint32_t init_sec_buf_size
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(constint16_t *) pi >>8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(constint32_t *) pi >>24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(constfloat *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(constfloat *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(constfloat *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(constdouble *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(constdouble *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(constdouble *) pi *(1U<< 31))))#defineSET_CONV_FUNC_GROUP(ofmt, ifmt) staticvoidset_generic_function(AudioConvert *ac){}voidff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enumAVSampleFormatout_fmt, enumAVSampleFormatin_fmt, intchannels, intsample_rate, intapply_map){AudioConvert *ac;intin_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) returnNULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method!=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt)>2){ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc){av_free(ac);returnNULL;}returnac;}in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar){ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar?ac->channels:1;}elseif(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;elseac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);returnac;}intff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){intuse_generic=1;intlen=in->nb_samples;intp;if(ac->dc){av_log(ac->avr, AV_LOG_TRACE,"%dsamples-audio_convert:%sto%s(dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));returnff_convert_dither(ac-> in
static int dash_read_header(AVFormatContext *s)
uint64_t time_shift_buffer_depth
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Describe the class of an AVClass context structure.
static void update_options(char **dest, const char *name, void *src)
static int open_input(DASHContext *c, struct representation *pls, struct fragment *seg)
static int dash_read_packet(AVFormatContext *s, AVPacket *pkt)
Rational number (pair of numerator and denominator).
static int resolve_content_path(AVFormatContext *s, const char *url, int *max_url_size, xmlNodePtr *baseurl_nodes, int n_baseurl_nodes)
static struct fragment * get_Fragment(char *range)
static int parse_manifest_segmenttimeline(AVFormatContext *s, struct representation *rep, xmlNodePtr fragment_timeline_node)
int avio_open2(AVIOContext **s, const char *url, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options)
Create and initialize a AVIOContext for accessing the resource indicated by url.
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
This structure contains the data a format has to probe a file.
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
Return the next frame of a stream.
size_t av_strlcat(char *dst, const char *src, size_t size)
Append the string src to the string dst, but to a total length of no more than size - 1 bytes...
const char * avio_find_protocol_name(const char *url)
Return the name of the protocol that will handle the passed URL.
AVInputFormat ff_dash_demuxer
static int dash_seek(AVFormatContext *s, struct representation *pls, int64_t seek_pos_msec, int flags, int dry_run)
int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
Seek to the keyframe at timestamp.
char * av_strtok(char *s, const char *delim, char **saveptr)
Split the string into several tokens which can be accessed by successive calls to av_strtok()...
static int update_init_section(struct representation *pls)
char * cookies
holds HTTP cookie values set in either the initial response or as an AVOption to the HTTP protocol co...
int av_strstart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str.
int ffio_init_context(AVIOContext *s, unsigned char *buffer, int buffer_size, int write_flag, void *opaque, int(*read_packet)(void *opaque, uint8_t *buf, int buf_size), int(*write_packet)(void *opaque, uint8_t *buf, int buf_size), int64_t(*seek)(void *opaque, int64_t offset, int whence))
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
Read packets of a media file to get stream information.
static const AVClass dash_class
int64_t fragment_duration
int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags)
Convenience wrapper for av_dict_set that converts the value to a string and stores it...
struct fragment * cur_seg
int pts_wrap_bits
number of bits in pts (used for wrapping control)
void avformat_close_input(AVFormatContext **s)
Close an opened input AVFormatContext.
int64_t fragment_timescale
static void close_demux_for_component(struct representation *pls)
int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val)
static int parse_manifest_adaptationset(AVFormatContext *s, const char *url, xmlNodePtr adaptionset_node, xmlNodePtr mpd_baseurl_node, xmlNodePtr period_baseurl_node, xmlNodePtr period_segmenttemplate_node, xmlNodePtr period_segmentlist_node)
static char * get_content_url(xmlNodePtr *baseurl_nodes, int n_baseurl_nodes, int max_url_size, char *rep_id_val, char *rep_bandwidth_val, char *val)
void * priv_data
Format private data.
static uint64_t get_current_time_in_sec(void)
int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options)
Open an input stream and read the header.
static int parse_manifest_representation(AVFormatContext *s, const char *url, xmlNodePtr node, xmlNodePtr adaptionset_node, xmlNodePtr mpd_baseurl_node, xmlNodePtr period_baseurl_node, xmlNodePtr period_segmenttemplate_node, xmlNodePtr period_segmentlist_node, xmlNodePtr fragment_template_node, xmlNodePtr content_component_node, xmlNodePtr adaptionset_baseurl_node, xmlNodePtr adaptionset_segmentlist_node, xmlNodePtr adaptionset_supplementalproperty_node)
static int64_t calc_min_seg_no(AVFormatContext *s, struct representation *pls)
struct representation ** videos
int64_t duration
Duration of the stream, in AV_TIME_BASE fractional seconds.
static void free_video_list(DASHContext *c)
AVCodecParameters * codecpar
Codec parameters associated with this stream.
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
static int reopen_demux_for_component(AVFormatContext *s, struct representation *pls)
enum AVDiscard discard
Selects which packets can be discarded at will and do not need to be demuxed.
AVRational r_frame_rate
Real base framerate of the stream.
int(* io_open)(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags, AVDictionary **options)
A callback for opening new IO streams.
This structure stores compressed data.
mode
Use these values in ebur128_init (or'ed).
static int64_t calc_next_seg_no_from_timelines(struct representation *pls, int64_t cur_time)
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
static int open_demux_for_component(AVFormatContext *s, struct representation *pls)
static av_cold void cleanup(FlashSV2Context *s)
static int refresh_manifest(AVFormatContext *s)