Skip to content

Commit

Permalink
Merge pull request #86 from Comcast/release/2.2.0
Browse files Browse the repository at this point in the history
Release/2.2.0
  • Loading branch information
dcoufal authored Apr 20, 2020
2 parents c4abe3e + 6744a84 commit d93cd82
Show file tree
Hide file tree
Showing 13 changed files with 829 additions and 10 deletions.
2 changes: 1 addition & 1 deletion mamba.podspec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|

s.name = "mamba"
s.version = "2.0.3"
s.version = "2.2.0"
s.license = { :type => 'Apache License, Version 2.0',
:text => <<-LICENSE
Copyright 2017 Comcast Cable Communications Management, LLC
Expand Down
36 changes: 30 additions & 6 deletions mamba.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@
43DE4EFD1E564DBE00EEE800 /* EXT_X_MEDIARenditionINSTREAMIDValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43DE4EFC1E564DBE00EEE800 /* EXT_X_MEDIARenditionINSTREAMIDValidator.swift */; };
43DE4F0D1E564FEE00EEE800 /* EXT_X_STARTTimeOffsetValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43DE4EFA1E564DA300EEE800 /* EXT_X_STARTTimeOffsetValidator.swift */; };
43DE4F0E1E564FFE00EEE800 /* EXT_X_MEDIARenditionINSTREAMIDValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43DE4EFC1E564DBE00EEE800 /* EXT_X_MEDIARenditionINSTREAMIDValidator.swift */; };
6DD0A1AD242F85C800FF7AAE /* EXT_X_DATERANGETagValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DD0A1AC242F85C800FF7AAE /* EXT_X_DATERANGETagValidator.swift */; };
6DD0A1AE242F85C800FF7AAE /* EXT_X_DATERANGETagValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DD0A1AC242F85C800FF7AAE /* EXT_X_DATERANGETagValidator.swift */; };
6DD0A1AF242F85C800FF7AAE /* EXT_X_DATERANGETagValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DD0A1AC242F85C800FF7AAE /* EXT_X_DATERANGETagValidator.swift */; };
6DD0A1B1242FADC600FF7AAE /* EXT_X_DATERANGEPlaylistValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DD0A1B0242FADC600FF7AAE /* EXT_X_DATERANGEPlaylistValidator.swift */; };
6DD0A1B2242FADC600FF7AAE /* EXT_X_DATERANGEPlaylistValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DD0A1B0242FADC600FF7AAE /* EXT_X_DATERANGEPlaylistValidator.swift */; };
6DD0A1B3242FADC600FF7AAE /* EXT_X_DATERANGEPlaylistValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DD0A1B0242FADC600FF7AAE /* EXT_X_DATERANGEPlaylistValidator.swift */; };
6DD9C898242CCE4A00B90E1C /* hls_variant_playlist_with_daterange_metadata.m3u8 in Resources */ = {isa = PBXBuildFile; fileRef = 6DD9C897242CCE4A00B90E1C /* hls_variant_playlist_with_daterange_metadata.m3u8 */; };
6DD9C899242CCE5300B90E1C /* hls_variant_playlist_with_daterange_metadata.m3u8 in Resources */ = {isa = PBXBuildFile; fileRef = 6DD9C897242CCE4A00B90E1C /* hls_variant_playlist_with_daterange_metadata.m3u8 */; };
6DD9C89A242CCE5400B90E1C /* hls_variant_playlist_with_daterange_metadata.m3u8 in Resources */ = {isa = PBXBuildFile; fileRef = 6DD9C897242CCE4A00B90E1C /* hls_variant_playlist_with_daterange_metadata.m3u8 */; };
883290561EA172170064588B /* MambaStringRefExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 883290551EA172170064588B /* MambaStringRefExtensionTests.swift */; };
D44E03771E3BAC9F00126B52 /* PlaylistTag+Util.swift in Sources */ = {isa = PBXBuildFile; fileRef = D44E03761E3BAC9F00126B52 /* PlaylistTag+Util.swift */; };
D44E03781E3BAC9F00126B52 /* PlaylistTag+Util.swift in Sources */ = {isa = PBXBuildFile; fileRef = D44E03761E3BAC9F00126B52 /* PlaylistTag+Util.swift */; };
Expand Down Expand Up @@ -634,6 +643,9 @@
3D933C192193367C0029069F /* EXT-X-BITRATETagParserTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "EXT-X-BITRATETagParserTests.swift"; sourceTree = "<group>"; };
43DE4EFA1E564DA300EEE800 /* EXT_X_STARTTimeOffsetValidator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = EXT_X_STARTTimeOffsetValidator.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
43DE4EFC1E564DBE00EEE800 /* EXT_X_MEDIARenditionINSTREAMIDValidator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EXT_X_MEDIARenditionINSTREAMIDValidator.swift; sourceTree = "<group>"; };
6DD0A1AC242F85C800FF7AAE /* EXT_X_DATERANGETagValidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EXT_X_DATERANGETagValidator.swift; sourceTree = "<group>"; };
6DD0A1B0242FADC600FF7AAE /* EXT_X_DATERANGEPlaylistValidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EXT_X_DATERANGEPlaylistValidator.swift; sourceTree = "<group>"; };
6DD9C897242CCE4A00B90E1C /* hls_variant_playlist_with_daterange_metadata.m3u8 */ = {isa = PBXFileReference; lastKnownFileType = text; path = hls_variant_playlist_with_daterange_metadata.m3u8; sourceTree = "<group>"; };
883290551EA172170064588B /* MambaStringRefExtensionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MambaStringRefExtensionTests.swift; sourceTree = "<group>"; };
D44E03761E3BAC9F00126B52 /* PlaylistTag+Util.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "PlaylistTag+Util.swift"; sourceTree = "<group>"; };
D4BB018C1E2EABD500CA006E /* PlaylistTagArray+RenditionGroups.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "PlaylistTagArray+RenditionGroups.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -914,6 +926,8 @@
isa = PBXGroup;
children = (
EC7491F71DD29DD300AF4E20 /* DictionaryTagValueIdentifier.swift */,
6DD0A1B0242FADC600FF7AAE /* EXT_X_DATERANGEPlaylistValidator.swift */,
6DD0A1AC242F85C800FF7AAE /* EXT_X_DATERANGETagValidator.swift */,
EC3B019E1DD4D47900B512E3 /* EXT_X_KEYValidator.swift */,
EC3B019F1DD4D47900B512E3 /* EXT_X_MEDIARenditionGroupAUTOSELECTValidator.swift */,
EC3B01A01DD4D47900B512E3 /* EXT_X_MEDIARenditionGroupDEFAULTValidator.swift */,
Expand Down Expand Up @@ -1234,6 +1248,7 @@
EC7492001DD29E2900AF4E20 /* hls_sampleMediaFile.txt */,
EC7492011DD29E2900AF4E20 /* hls_singleMediaFile.txt */,
1D28F3441EAA9E500010320B /* hls_variant_playlist.m3u8 */,
6DD9C897242CCE4A00B90E1C /* hls_variant_playlist_with_daterange_metadata.m3u8 */,
EC7492021DD29E2900AF4E20 /* hls_writer_parser_roundtrip_tester.txt */,
EC7492061DD29E2900AF4E20 /* super8demuxed1_4242.m3u8 */,
EC7492071DD29E2900AF4E20 /* super8demuxed2_IP_1080p24_51_TS.m3u8 */,
Expand Down Expand Up @@ -1662,6 +1677,7 @@
EC7492201DD29E2900AF4E20 /* ThirdPartyTagsTestFixture.txt in Resources */,
EC74920A1DD29E2900AF4E20 /* bipbopall.m3u8 in Resources */,
EC1705421DFB490A00C969F9 /* linear_ad_insertion_CONTENT_end_ad_forced.m3u8 in Resources */,
6DD9C898242CCE4A00B90E1C /* hls_variant_playlist_with_daterange_metadata.m3u8 in Resources */,
EC74921A1DD29E2900AF4E20 /* super8demuxed1_4242.m3u8 in Resources */,
EC74921E1DD29E2900AF4E20 /* super8demuxed3_1376214110461.m3u8 in Resources */,
EC74920C1DD29E2900AF4E20 /* hls_sampleMasterFile.txt in Resources */,
Expand Down Expand Up @@ -1698,6 +1714,7 @@
EC7492211DD29E2900AF4E20 /* ThirdPartyTagsTestFixture.txt in Resources */,
EC74920B1DD29E2900AF4E20 /* bipbopall.m3u8 in Resources */,
EC1705431DFB490A00C969F9 /* linear_ad_insertion_CONTENT_end_ad_forced.m3u8 in Resources */,
6DD9C899242CCE5300B90E1C /* hls_variant_playlist_with_daterange_metadata.m3u8 in Resources */,
EC74921B1DD29E2900AF4E20 /* super8demuxed1_4242.m3u8 in Resources */,
EC74921F1DD29E2900AF4E20 /* super8demuxed3_1376214110461.m3u8 in Resources */,
EC74920D1DD29E2900AF4E20 /* hls_sampleMasterFile.txt in Resources */,
Expand Down Expand Up @@ -1734,6 +1751,7 @@
ECE253C0209A508700D388CE /* Super8_muxed1_4242.m3u8 in Resources */,
ECE253CE209A508700D388CE /* super8demuxed1_4242.m3u8 in Resources */,
ECE253CB209A508700D388CE /* hls_singleMediaFile.txt in Resources */,
6DD9C89A242CCE5400B90E1C /* hls_variant_playlist_with_daterange_metadata.m3u8 in Resources */,
ECE253C7209A508700D388CE /* hls_master_playlist.m3u8 in Resources */,
ECE253BF209A508700D388CE /* linear_ad_insertion_CONTENT_start_ad.m3u8 in Resources */,
ECE253BD209A508700D388CE /* linear_ad_insertion_CONTENT_end_ad_natural.m3u8 in Resources */,
Expand Down Expand Up @@ -1778,6 +1796,7 @@
EC7491BF1DD29D5C00AF4E20 /* PlaylistTagValueIdentifier.swift in Sources */,
EC3B01C91DD4D49A00B512E3 /* PlaylistRenditionGroupMatchingPROGRAM_IDValidator.swift in Sources */,
EC349AC52236BFF10077432B /* PlaylistInterface.swift in Sources */,
6DD0A1AD242F85C800FF7AAE /* EXT_X_DATERANGETagValidator.swift in Sources */,
F700CD331E78A0B9001C9487 /* MambaStringRef_ConcreteUnownedBytes.m in Sources */,
EC95478B1E5CC86300962535 /* EXTINFValidator.swift in Sources */,
EC9826021DD3A113003BCDA5 /* URLSchemeChangeExtension.swift in Sources */,
Expand All @@ -1791,6 +1810,7 @@
EC03B6541E5CC56B00BF1F97 /* RapidParser.m in Sources */,
F70E9E9A1E8C43C8006022C6 /* PlaylistParserError.swift in Sources */,
EC7491701DD29B5D00AF4E20 /* CollectionType+Safe.swift in Sources */,
6DD0A1B1242FADC600FF7AAE /* EXT_X_DATERANGEPlaylistValidator.swift in Sources */,
EC7491BB1DD29D5C00AF4E20 /* PlaylistTagParser.swift in Sources */,
EC7491C11DD29D5C00AF4E20 /* PlaylistTagWriter.swift in Sources */,
EC3B01CD1DD4D49A00B512E3 /* PlaylistTagCardinalityValidation.swift in Sources */,
Expand Down Expand Up @@ -1948,6 +1968,7 @@
EC9547861E5CC83C00962535 /* NoOpTagParser.swift in Sources */,
EC7491FB1DD29DD300AF4E20 /* GenericSingleTagValidator.swift in Sources */,
EC349AC62236BFF10077432B /* PlaylistInterface.swift in Sources */,
6DD0A1AE242F85C800FF7AAE /* EXT_X_DATERANGETagValidator.swift in Sources */,
F700CD341E78A0B9001C9487 /* MambaStringRef_ConcreteUnownedBytes.m in Sources */,
EC95478C1E5CC86300962535 /* EXTINFValidator.swift in Sources */,
EC7491C01DD29D5C00AF4E20 /* PlaylistTagValueIdentifier.swift in Sources */,
Expand All @@ -1961,6 +1982,7 @@
EC03B65B1E5CC56B00BF1F97 /* MambaStringRef.m in Sources */,
EC7491801DD29C3500AF4E20 /* String+EquatableMambaTypes.swift in Sources */,
F70E9E9B1E8C43C8006022C6 /* PlaylistParserError.swift in Sources */,
6DD0A1B2242FADC600FF7AAE /* EXT_X_DATERANGEPlaylistValidator.swift in Sources */,
EC03B6551E5CC56B00BF1F97 /* RapidParser.m in Sources */,
EC7491711DD29B5D00AF4E20 /* CollectionType+Safe.swift in Sources */,
EC7491BC1DD29D5C00AF4E20 /* PlaylistTagParser.swift in Sources */,
Expand Down Expand Up @@ -2118,6 +2140,7 @@
EC1CCD4D209A2CF9006B59FF /* PlaylistRenditionGroupMatchingPROGRAM_IDValidator.swift in Sources */,
EC1CCD24209A2CF9006B59FF /* CollectionType+Safe.swift in Sources */,
EC1CCCF5209A2CF9006B59FF /* PlaylistTimelineTranslator.swift in Sources */,
6DD0A1AF242F85C800FF7AAE /* EXT_X_DATERANGETagValidator.swift in Sources */,
EC1CCD58209A2CF9006B59FF /* PantosValue.swift in Sources */,
EC349AC72236BFF10077432B /* PlaylistInterface.swift in Sources */,
EC1CCD63209A2CF9006B59FF /* Mamba.swift in Sources */,
Expand All @@ -2131,6 +2154,7 @@
EC1CCD50209A2CF9006B59FF /* PlaylistTagGroupValidator.swift in Sources */,
EC1CCCFE209A2CF9006B59FF /* MambaStringRefFactory.m in Sources */,
EC349AD42236CB860077432B /* PlaylistStructureCore.swift in Sources */,
6DD0A1B3242FADC600FF7AAE /* EXT_X_DATERANGEPlaylistValidator.swift in Sources */,
EC1CCD3A209A2CF9006B59FF /* NoOpTagParser.swift in Sources */,
EC1CCD5D209A2CF9006B59FF /* PlaylistTagValidator.swift in Sources */,
EC1CCD62209A2CF9006B59FF /* PlaylistWriter.swift in Sources */,
Expand Down Expand Up @@ -2300,7 +2324,7 @@
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MARKETING_VERSION = 2.1.0;
MARKETING_VERSION = 2.2.0;
PRODUCT_BUNDLE_IDENTIFIER = com.comcast.mamba;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
Expand All @@ -2327,7 +2351,7 @@
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MARKETING_VERSION = 2.1.0;
MARKETING_VERSION = 2.2.0;
PRODUCT_BUNDLE_IDENTIFIER = com.comcast.mamba;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
Expand Down Expand Up @@ -2391,7 +2415,7 @@
INFOPLIST_FILE = mamba/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MARKETING_VERSION = 2.1.0;
MARKETING_VERSION = 2.2.0;
PRODUCT_BUNDLE_IDENTIFIER = com.comcast.mamba;
PRODUCT_NAME = mamba;
SDKROOT = appletvos;
Expand Down Expand Up @@ -2421,7 +2445,7 @@
INFOPLIST_FILE = mamba/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MARKETING_VERSION = 2.1.0;
MARKETING_VERSION = 2.2.0;
PRODUCT_BUNDLE_IDENTIFIER = com.comcast.mamba;
PRODUCT_NAME = mamba;
SDKROOT = appletvos;
Expand Down Expand Up @@ -2499,7 +2523,7 @@
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 2.1.0;
MARKETING_VERSION = 2.2.0;
PRODUCT_BUNDLE_IDENTIFIER = com.comcast.mamba;
PRODUCT_MODULE_NAME = mamba;
PRODUCT_NAME = mamba;
Expand Down Expand Up @@ -2532,7 +2556,7 @@
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 2.1.0;
MARKETING_VERSION = 2.2.0;
PRODUCT_BUNDLE_IDENTIFIER = com.comcast.mamba;
PRODUCT_MODULE_NAME = mamba;
PRODUCT_NAME = mamba;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
//
// EXT_X_DATERANGEPlaylistValidator.swift
// mamba
//
// Created by Robert Galluccio on 28/03/2020.
// Copyright © 2020 Comcast Corporation.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License. All rights reserved.
//

import Foundation

/// This class provides the validation for EXT-X-DATERANGE tags for rules which require the whole playlist information.
///
/// All validation issues for EXT-X-DATERANGE are treated as `.warning` due to this comment in the HLS specification:
///
/// Clients SHOULD ignore EXT-X-DATERANGE tags with illegal syntax.
///
class EXT_X_DATERANGEPlaylistValidator: VariantPlaylistValidator {

static func validate(variantPlaylist: VariantPlaylistInterface) -> [PlaylistValidationIssue] {

var programDateTimeTagsCount = 0
var daterangeTags = [PlaylistTag]()
for tag in variantPlaylist.tags {
if tag.tagDescriptor == PantosTag.EXT_X_PROGRAM_DATE_TIME {
programDateTimeTagsCount += 1
} else if tag.tagDescriptor == PantosTag.EXT_X_DATERANGE {
daterangeTags.append(tag)
}
}

var validationIssues = [PlaylistValidationIssue]()
validationIssues.append(contentsOf: validateProgramDateTime(programDateTimeTagsCount: programDateTimeTagsCount, daterangeTagsCount: daterangeTags.count))
validationIssues.append(contentsOf: validateMultipleTags(daterangeTags: daterangeTags))

return validationIssues
}

// If a Playlist contains an EXT-X-DATERANGE tag, it MUST also contain
// at least one EXT-X-PROGRAM-DATE-TIME tag.
private static func validateProgramDateTime(programDateTimeTagsCount: Int, daterangeTagsCount: Int) -> [PlaylistValidationIssue] {

guard daterangeTagsCount > 0, programDateTimeTagsCount == 0 else {
return []
}
return [PlaylistValidationIssue(description: .EXT_X_DATERANGEExistsWithNoEXT_X_PROGRAM_DATE_TIME, severity: .warning)]
}

// If a Playlist contains two EXT-X-DATERANGE tags with the same ID
// attribute value, then any AttributeName that appears in both tags
// MUST have the same AttributeValue.
private static func validateMultipleTags(daterangeTags: [PlaylistTag]) -> [PlaylistValidationIssue] {

// first fill out a map of ID to tags to group tags with matching ID
var idTagMap = [String: [PlaylistTag]]()
for tag in daterangeTags {
guard let id = tag.value(forValueIdentifier: PantosValue.id) else {
// This should not happen, but if it does, this is a validation issue that will be caught by the tag validator
continue
}
if let matchingTags = idTagMap[id] {
idTagMap[id] = matchingTags + [tag]
} else {
idTagMap[id] = [tag]
}
}
// next we pick out ID values with multiple tags and validate the attributes match between them
var validationIssues = [PlaylistValidationIssue]()
for (_, tags) in idTagMap {
guard tags.count > 1 else {
continue
}
// make a map of attributes to values to ensure any matching attributes also match value
var attributeToValueMap = [String: String]()
for tag in tags {
for attribute in tag.keys {
guard let attributeValue = tag.value(forKey: attribute) else {
assertionFailure("tag.keys gave us a key that had no value in the tag - key: \(attribute), tag: \(tag), tag.keys: \(tag.keys)")
continue
}
if let matchingAttributeValue = attributeToValueMap[attribute] {
if attributeValue != matchingAttributeValue {
validationIssues.append(PlaylistValidationIssue(description: .EXT_X_DATERANGEAttributeMismatchForTagsWithSameID, severity: .warning))
}
} else {
attributeToValueMap[attribute] = attributeValue
}
}
}
}

return validationIssues
}
}
Loading

0 comments on commit d93cd82

Please sign in to comment.