comcast / mamba Goto Github PK
View Code? Open in Web Editor NEWMamba is a Swift iOS, tvOS and macOS framework to parse, validate and write HTTP Live Streaming (HLS) data.
License: Apache License 2.0
Mamba is a Swift iOS, tvOS and macOS framework to parse, validate and write HTTP Live Streaming (HLS) data.
License: Apache License 2.0
Right now we only support avc
as a codec, but hevc
is supported in AVFoundation as of iOS 11.
HLSCodec
and HLSCodecArray
to accept avc
and hevc
as codecs, and return true
for containsVideo
if hevc
is present.EVENT style playlists just add fragments onto the end of an existing variant.
This ticket is to implement a special parsing pathway that will take a previous EVENT style variant and update it with a new version. Only a small amount of parsing will have to be done to update the HLSPlaylist
object.
HLSParser
that will take an previously parsed HLSPlaylist
as an argument and will parse this playlist specially to save effort.Parse this variant:
#EXTM3U
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-TARGETDURATION:3
#EXT-X-VERSION:3
#EXTINF:2.96130,
fileSequence0.ts
#EXTINF:2.96130,
fileSequence1.ts
#EXTINF:2.96129,
fileSequence2.ts
#EXTINF:2.96129,
fileSequence3.ts
#EXTINF:2.96130,
fileSequence4.ts
#EXTINF:2.96130,
fileSequence5.ts
#EXTINF:2.96129,
fileSequence6.ts
#EXTINF:2.96129,
fileSequence7.ts
#EXTINF:2.96130,
fileSequence8.ts
#EXTINF:2.96130,
fileSequence9.ts
#EXTINF:2.96129,
fileSequence10.ts
Call playlist.tagIndexes(forMediaSequence: 0)
I would expect to get a range back (namely 4...5, I think, but there should be a range as that media sequence exists)
You get nil back.
Note that if you call playlist.segmentGroup(forMediaSequence: 0)
you do get the correct structure back and that structure has the correct range, so this problem is likely trivial to fix.
(steps are above)
Please add a unit test for this as part of the fix.
(Note: Found in 1.x but should also check 2.x when fixing)
Parsing this playlist:
#EXTM3U
#EXT-X-VERSION:7
#EXT-X-PLAYLIST-TYPE:EVENT
#EXT-X-TARGETDURATION:3
#EXT-X-KEY:METHOD=AES-128,URI="http://myserver.com",IV=0x000102030aaaaccccccccbbbbb0d0e0f
#EXT-X-MAP:URI=\"http://myserver.com/init.mp4\"
#EXT-X-ENDLIST
Parse should succeed
Crash in HLSPlaylistStructure.rebuild()
It's useful to be able to look at a master playlist and figure out if it has:
demuxed video
demuxed audio
muxed audio and video
or some combination of such.
In my head, this would be a function on a MasterPlaylist
and would return an OptionSet
, but there are likely other ways of skinning the cat.
HLSPlaylist
or MasterPlaylist
to return mixed/demuxed status.Comcast has private code that basically does this, so might be best to wait for someone in the company to do the work.
Currently, I can't include it with Swift 5.3.2.
Since Swift 5.1, Apple provide module stability feature in Xcode. This enables a framework to be able to be included in targets with newer Swift versions. But BUILD_LIBRARY_FOR_DISTRIBUTION
build setting has to be enabled.
My current workaround is to add a Podfile post_install
script to do so:
post_install do | installer |
installer.pods_project.targets.each do |target|
if target.name == 'mamba-iOS' || target.name == 'mamba-tvOS'
target.build_configurations.each do |config|
config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
end
end
end
end
BUILD_LIBRARY_FOR_DISTRIBUTION
build setting to Yes
Right now, if you call playlistType
for a playlist, the type is calculated every time from scratch. It's a small calculation, but it's not uncommon in Comcast code to call this a lot.
It should be cached. The cached value should clear if the playlist is edited.
Depends on #5
private
cached version of playlistType
. Calls to public playlistType
should check if there's a cache and return it.PlaylistStructure
since, if the playlist is edited, the cache value should clear.unknown
type anymore since we know we are a variant and therefore have rules about determination of playlistType
that are always applicable.Let's say we are asynchronously parsing a HLS playlist.
The client creates a HLSParser
.
The client starts a parse
with a callback.
The client does not retain a reference to the HLSParser
while parsing happens.
The client should be called back.
The client is not called back.
Why? There is a weak ref between the HLSParseWorker
and the HLSParser
. As soon as the work starts, no one has a strong ref to HLSParser
and it's deleted (along with the callback closure ref!).
I think the fix should be to have a temp strong link between the HLSParseWorker
and the HLSParser
which should be broken when the parse is done (to avoid a circular ref). There might be other fixes as well.
When debugging issues, it's common to look at the playlist, especially if you are editing it in some way.
Current output is basically a dump of the HLSTag array, which is hard to read and put in the context of a actual HL playlist.
This ticket is to have the output of debugDescription
for HLSPlaylist and related classes print out the actual playlist as it would be delivered by HLSWriter
.
HLSPlaylistStructure
so that the tags are not included in output. Instead, we should output the actual manifest. Ideally, we'd reuse some of all of HLSWriter to do this.A number of common types (Int, Float, etc) have the FailableStringLiteralConvertible
interface.
public protocol FailableStringLiteralConvertible {
init?(string: String)
}
This is public since users might want to create custom HLS parsers for their custom tags.
But, it's not clear that these belong to mamba.
Rename the initializer to be more specific to mamba, or at least make it clearer that this is custom and you shouldn't be using it if you don't recognize it.
My first thought is:
public protocol FailableStringLiteralConvertible {
init?(withFailableString: String)
}
FailableStringLiteralConvertible
interface and all the mamba-supplied overrides.Install mamba with CocoaPods. HLSWriter.write should work.
HLSWriter.write gives an error Fatal error: Unable to find framework bundle: file /path/to/project/Pods/mamba/mambaSharedFramework/Mamba.swift, line 29
In Pods/mamba/Support Files/Info.plist
, change the "Bundle identifier" to "com.comcast.mamba".
Hi Mamba Team,
I am exploring the framework and it looks great for parsing custom tags in the HLS Playlists. Is there any existing API to get the time associated with each occurrence of a custom tag relevant to the first ts segment in the playlist?
For example, while parsing the below playlist, the first appearance of MYCUSTOMTAG is at 0 seconds because there are no ts chunks before that and the second appearance is at 10.01 seconds in the playlist after 123.ts and 456.ts, each with 5.005 seconds duration. Is there a way to get this information programmatically?
#EXTM3U
#EXT-X-VERSION:6
#EXT-X-ALLOW-CACHE:YES
#EXT-X-TARGETDURATION:11
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-MYCUSTOMTAG:ID="1", X-CUSTOM-ATTRIBUTE="VAL1"
#EXTINF:5.005,
123.ts
#EXTINF:5.005,
456.ts
#EXT-X-MYCUSTOMTAG:ID="2",X-CUSTOM-ATTRIBUTE="VAL2"
#EXTINF:5.005,
789.ts
#EXT-X-ENDLIST
Integrating mamba
into XCode project through Cocoapods should raise no issue.
Build error with the message mamba/mamba-Swift.h
file not found`. Observed in Xcode 11.6.
Seems like commit 56a03fd fixes this issue, but the podspec is not pointing to the latest commit on the develop
branch. Is it possible for the podspec to be updated?
Latest Version Found on Cocoapods is 1.0.5 while the latest podspec shows 1.0.7. Maybe the pod push failed?
It would be helpful for new users to have a working playground as a demo for what can be done.
The PR with small changes have been merged into develop_1.x
#119
Can you please tag new release 1.5.6
Bug Template:
Carthage build / update works.
Carthage build fails
We've been seeing an intermittent issue with building the Mamba dependency through Carthage. The command that Carthage runs is:
/usr/bin/xcrun xcodebuild -workspace /PATH/TO/CARTFILE/DIRECTORY/Carthage/Checkouts/mamba/mamba.xcworkspace -scheme mamba -configuration Release -derivedDataPath ~/Library/Caches/org.carthage.CarthageKit/DerivedData/10.3_10G8/mamba/1.2.0 -sdk iphoneos ONLY_ACTIVE_ARCH=NO CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY= CARTHAGE=YES archive -archivePath /var/folders/qf/05lm714d1h9fz1r47bsw8xmc0000gp/T/mamba SKIP_INSTALL=YES GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=NO CLANG_ENABLE_CODE_COVERAGE=NO STRIP_INSTALLED_PRODUCT=NO
The error is that occasionally it can't find the <mamba/mamba-Swift.h>
header in mambaSharedFramework/HLS\ Rapid\ Parser/RapidParserError.m
.
The build failure appears to happen more consistently on the newer MacBook Pros (MacBook Pro (15-inch, 2018) 2.9 GHz Intel Core i9, for example). Personally I have not seen this occur on older models (MacBook Pro (15-inch, 2017) 2.8 GHz intel Core i7).
The suspicion is some sort of race condition combined with the new build system and its parallel builds that is exacerbated by the speed of the machine.
As an experiment, we have changed the build system to the legacy one (File > Workspace Settings... > Build System: from Xcode) within the Mamba workspace on, the newer machines, and run the command, and it passes successfully every time.
When changing back to the "New Build System (Default)" it fails consistently with the missing Swift header error.
This ticket is to remove the HLSTagCriteria
and HLSTagCriterion
objects.
I don't think people are using those objects. At Comcast, we use filter/map/reduce to do queries instead, and that seems much more natural and easy to understand.
HLSTagCriteria
and HLSTagCriterion
It's a common task to ask "what time does this tag appear in a variant playlist" or "where does this tag appear in a variant"? This info is available via mamba but it's a little bit of a pain to get and non-obvious.
This ticket is to add a one-liner syntactic sugar function to get this info.
There should be functions that return (1) an array of times (probably CMTime
if feasible) (2) an array of media sequence numbers (3) an array of tag indexes (i.e. indexes into the playlist tag array) and (4) an array of tag group indexes (i.e. indexes into the media groups array). This function should take some kind of predicate (probably a closure that takes a HLSTag
and returns true or false for a match)
This task depends on #5 and should only be added to VariantPlaylist
s. The array of times potentially does not make sense for LIVE playlists, so we'll have to figure out what to do there.
I noticed that when accessing Playlist Tags in iterations on a debug build would work fine, but on a production build it would crash the app.
The way I was able to solve this was by setting
Swift compiler code generation optimize level: None
Which I fear has an impact on performance. Is this known at all?
We updated the 1.x version of the mamba library to iOS 11.0 (from iOS 9.3) in this PR: #61
This is an external implementation of Comcast's internal support matrix, and should not have been made public. This ticket is to revert that change for the 1.x branch.
This will help in debugging.
CustomDebugStringConvertible
for HLSValidationIssue
Install via Swift Package Manager?
Ideally, mamba would support all HLS tags through version 8.
This issue is more of a epic, and each tag would be a specific sub issue. If you decide to peel off a unsupported tag, make a new issue and link back to this one.
For each tag
PantosTag
PantosValue
HLSTagValidator
if needed.Preliminary spec available at https://developer.apple.com/streaming/HLS-WWDC-2017-Preliminary-Spec.pdf
Older HLS specs available at https://tools.ietf.org/html/draft-pantos-http-live-streaming-23
we need more than one owner who can push the podspec in case the owner is out of contact.
I am trying to rewrite a playlist, specifically change the Location
let parser = PlaylistParser()
let result = parser.parse(playlistData: data, url: url)
switch result {
case .parsedMaster(var master):
do {
try master.transform {
(tag: PlaylistTag) -> PlaylistTag in
var mutableTag = tag
case PantosTag.Location:
mutableTag = PlaylistTag(
tagDescriptor: PantosTag.Location,
stringTagData: /* some URL String */,
parsedValues: nil
)
[... other stuff]
But when I do this i get something like this as output
#Location:http://MY-URL
When I compare the incoming tag
and my mutableTag
, I can see some differences that don't seem to be exposed by the API.
For example, tagName
is nil
in the incoming tag
, but it's not possible to set it to nil
using the exposed API AFAICT.
The reason I am creating a new tag is because tagData
is immutable.
To be able to set a PantosTag.Location
while doing .transform
.
A PlaylistTag
with PantosTag.Location
should be written as the string in tagData
, without any decoration.
It's not possible to set a correct PantosTag.Location
during .transform
.
The PlaylistTag
is decorated with #Location:...
when writing it.
#Location
rows, which are not valid HLS.Thanks for all the good work! I hope I am just doing something silly and this can/should be done in a completely different way.
Right now, all HLS playlists are HLSPlaylist
type. You can tell if a playlist is master or variant by inspecting the type
.
However, there are weak typing issues in HLSPlaylist
. The mediaSegmentGroups
and all the HLSPlaylistTimelineTranslator
don't really make sense unless the playlist is a Variant. Also, this situation leads to a lot of:
guard playlist.type == .master else {
// exit with an error, exception and possibly an assert
}
which could be avoided with strong typing.
It's not 100% clear what the correct solution is. Perhaps the HLSParser
could have two success callbacks, one for master and one for variant playlists.
Most functionality should be shared between HLSMasterPlaylist
and HLSVariantPlaylist
. It's only mediaSegmentGroups
and HLSPlaylistTimelineTranslator
that are specific to HLSVariantPlaylist
. I would imagine that HLSMasterPlaylist
could have some specific functionality to deal with #EXT-X-STREAM-INF
tags paired with variant urls (similar to mediaSegmentGroups
).
We should have an agreement about architecture before going forward.
This will be a large architectural change.
We use the prefix HLS
on many mamba objects. This is not required and is just extra typing/old fashioned. Let's remove it.
Notes: I think HLSParser
, HLSWriter
, etc should become PlaylistParser
, PlaylistWriter
etc. HLSPlaylist
will become Playlist
. Use best judgment when updating symbol names.
HLS
prefix on all mamba symbols.Hi! The README states that the library supports XCode 9+ but is using an operator requiring XCode 9.3+.
Seems this was introduced with this commit and changing flatMap to compactMap
Is the intention still to support XCode 9+ or to move to only supporting 9.3+? Would a PR converting compactMap back to flatMap be acceptable?
Currently, it's impossible to have access to properties of HLSResolution struct, because these properties have default access level.
w
, h
, ratio
, is16x9
and is4x3
propertiesDo you guys have any plans on adding SPM support? We're looking to move away from Carthage, now that SPM supports iOS/tvOS
It doesn't seem that Mamba currently supports Low-Latency HLS, is this in the plan, or did I miss something? It claims that this writes HLS playlists, does this mean I can hook up my AV Inputs to this library to write the streams and publish them to an HLS server? I cannot seem to find sufficient information on this.
More than happy to contribute to this project as I am looking for a good solution, I'm just having trouble determining exactly what this library is capable of based on the documentation and lack of examples.
You should be able to "parse" an empty Data
object with HLSParser
HLSParser
will crash if you try to do so.
This ticket is to fix the crash so you get an empty HLSPlaylist
when parsed.
If you parse the playlist
#EXT3MU
#EXTINF:5000
a
You should see the a
line as a Location URL tag.
Parsing such a playlist gives no location. The line is completely skipped.
It's worth noting that this playlist:
#EXT3MU
#EXTINF:5000
aa
does produce the correct, expected Location URL tag with the value aa
HLSParser
to parse a playlist containing a Location URL that has one character.HLSPlaylist
. You will not see that Location URL in the output.Is it possible to get 1.2.0 onto cocoapods? I unfortunately have not been able to move off pods just yet.
comment I ran across in our current implementation:
// mamba validation issues have a poor interface. Best I can do is search in the description field when trying to find a specific issue in a list.
public init(description: IssueDescription, severity: IssueSeverity)
to store the IssueDescription
instead of just the description string public init(description: String, severity: IssueSeverity)
to store the description as a .undefined(String)
within IssueDescription
enumdescription
attribute to an accessor of the string of the stored IssueDescription
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.