Skip to content

Commit

Permalink
fix(HLS): Ignore DATERANGE with errors instead of fire an error (#7499)
Browse files Browse the repository at this point in the history
  • Loading branch information
avelad authored Oct 25, 2024
1 parent b9f3992 commit b2b4238
Showing 1 changed file with 105 additions and 97 deletions.
202 changes: 105 additions & 97 deletions lib/hls/hls_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -3970,117 +3970,125 @@ shaka.hls.HlsParser = class {
});
for (let i = 0; i < dateRangeTags.length; i++) {
const tag = dateRangeTags[i];
const id = tag.getRequiredAttrValue('ID');
if (this.dateRangeIdsEmitted_.has(id)) {
continue;
}
const startDateValue = tag.getRequiredAttrValue('START-DATE');
const startDate = shaka.util.TXml.parseDate(startDateValue);
if (isNaN(startDate)) {
// Invalid START-DATE
continue;
}
goog.asserts.assert(startDate != null, 'Start date should not be null!');
const startTime = Math.max(0, startDate - initialProgramDateTime);

let endTime = null;
const endDateValue = tag.getAttributeValue('END-DATE');
if (endDateValue) {
const endDate = shaka.util.TXml.parseDate(endDateValue);
if (!isNaN(endDate)) {
goog.asserts.assert(endDate != null, 'End date should not be null!');
endTime = endDate - initialProgramDateTime;
if (endTime < 0) {
// Date range in the past
continue;
}
try {
const id = tag.getRequiredAttrValue('ID');
if (this.dateRangeIdsEmitted_.has(id)) {
continue;
}
}
if (endTime == null) {
const durationValue = tag.getAttributeValue('DURATION') ||
tag.getAttributeValue('PLANNED-DURATION');
if (durationValue) {
const duration = parseFloat(durationValue);
if (!isNaN(duration)) {
endTime = startTime + duration;
const startDateValue = tag.getRequiredAttrValue('START-DATE');
const startDate = shaka.util.TXml.parseDate(startDateValue);
if (isNaN(startDate)) {
// Invalid START-DATE
continue;
}
goog.asserts.assert(startDate != null,
'Start date should not be null!');
const startTime = Math.max(0, startDate - initialProgramDateTime);

let endTime = null;
const endDateValue = tag.getAttributeValue('END-DATE');
if (endDateValue) {
const endDate = shaka.util.TXml.parseDate(endDateValue);
if (!isNaN(endDate)) {
goog.asserts.assert(endDate != null,
'End date should not be null!');
endTime = endDate - initialProgramDateTime;
if (endTime < 0) {
// Date range in the past
continue;
}
}
const realEndTime = startDate - initialProgramDateTime + duration;
if (realEndTime < 0) {
// Date range in the past
continue;
}
if (endTime == null) {
const durationValue = tag.getAttributeValue('DURATION') ||
tag.getAttributeValue('PLANNED-DURATION');
if (durationValue) {
const duration = parseFloat(durationValue);
if (!isNaN(duration)) {
endTime = startTime + duration;
}
const realEndTime = startDate - initialProgramDateTime + duration;
if (realEndTime < 0) {
// Date range in the past
continue;
}
}
}
}
const type = tag.getAttributeValue('CLASS') || 'com.apple.quicktime.HLS';

const endOnNext = tag.getAttributeValue('END-ON-NEXT') == 'YES';
if (endTime == null && endOnNext) {
for (let j = i + 1; j < dateRangeTags.length; j++) {
const otherDateRangeType =
dateRangeTags[j].getAttributeValue('CLASS') ||
'com.apple.quicktime.HLS';
if (type != otherDateRangeType) {
const type =
tag.getAttributeValue('CLASS') || 'com.apple.quicktime.HLS';

const endOnNext = tag.getAttributeValue('END-ON-NEXT') == 'YES';
if (endTime == null && endOnNext) {
for (let j = i + 1; j < dateRangeTags.length; j++) {
const otherDateRangeType =
dateRangeTags[j].getAttributeValue('CLASS') ||
'com.apple.quicktime.HLS';
if (type != otherDateRangeType) {
continue;
}
const otherDateRangeStartDateValue =
dateRangeTags[j].getRequiredAttrValue('START-DATE');
const otherDateRangeStartDate =
shaka.util.TXml.parseDate(otherDateRangeStartDateValue);
if (isNaN(otherDateRangeStartDate)) {
// Invalid START-DATE
continue;
}
if (otherDateRangeStartDate &&
otherDateRangeStartDate > startDate) {
endTime = Math.max(0,
otherDateRangeStartDate - initialProgramDateTime);
break;
}
}
if (endTime == null) {
// Since we cannot know when it ends, we omit it for now and in the
// future with an update we will be able to have more information.
continue;
}
const otherDateRangeStartDateValue =
dateRangeTags[j].getRequiredAttrValue('START-DATE');
const otherDateRangeStartDate =
shaka.util.TXml.parseDate(otherDateRangeStartDateValue);
if (isNaN(otherDateRangeStartDate)) {
// Invalid START-DATE
}

// Exclude these attributes from the metadata since they already go into
// other fields (eg: startTime or endTime) or are not necessary..
const excludedAttributes = [
'CLASS',
'START-DATE',
'END-DATE',
'DURATION',
'END-ON-NEXT',
];

/* @type {!Array.<shaka.extern.MetadataFrame>} */
const values = [];
for (const attribute of tag.attributes) {
if (excludedAttributes.includes(attribute.name)) {
continue;
}
if (otherDateRangeStartDate && otherDateRangeStartDate > startDate) {
endTime = Math.max(0,
otherDateRangeStartDate - initialProgramDateTime);
break;
let data = Utils.variableSubstitution(attribute.value, variables);
if (attribute.name == 'X-ASSET-URI' ||
attribute.name == 'X-ASSET-LIST') {
data = Utils.constructSegmentUris(
getUris(), attribute.value, variables)[0];
}
const metadataFrame = {
key: attribute.name,
description: '',
data,
mimeType: null,
pictureType: null,
};
values.push(metadataFrame);
}
if (endTime == null) {
// Since we cannot know when it ends, we omit it for now and in the
// future with an update we will be able to have more information.
continue;
}
}

// Exclude these attributes from the metadata since they already go into
// other fields (eg: startTime or endTime) or are not necessary..
const excludedAttributes = [
'CLASS',
'START-DATE',
'END-DATE',
'DURATION',
'END-ON-NEXT',
];

/* @type {!Array.<shaka.extern.MetadataFrame>} */
const values = [];
for (const attribute of tag.attributes) {
if (excludedAttributes.includes(attribute.name)) {
continue;
}
let data = Utils.variableSubstitution(attribute.value, variables);
if (attribute.name == 'X-ASSET-URI' ||
attribute.name == 'X-ASSET-LIST') {
data = Utils.constructSegmentUris(
getUris(), attribute.value, variables)[0];
// ID is always required. So we need more than 1 value.
if (values.length > 1) {
this.playerInterface_.onMetadata(type, startTime, endTime, values);
}
const metadataFrame = {
key: attribute.name,
description: '',
data,
mimeType: null,
pictureType: null,
};
values.push(metadataFrame);
}

// ID is always required. So we need more than 1 value.
if (values.length > 1) {
this.playerInterface_.onMetadata(type, startTime, endTime, values);
this.dateRangeIdsEmitted_.add(id);
} catch (e) {
shaka.log.warning('Ignorando DATERANGE con errores', tag.toString());
}

this.dateRangeIdsEmitted_.add(id);
}
}

Expand Down

0 comments on commit b2b4238

Please sign in to comment.