Latest 1.0.3
Homepage https://github.com/Comcast/mamba
License Apache License, Version 2.0 Copyright 2017 Comcast Cable Communications Management, LLC
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.
This product includes software developed at Comcast (http://www.comcast.com/).
Platforms ios 9.0, tvos 10.0, requires ARC
Frameworks CoreMedia

Build Status
Code Coverage from codecov
Carthage compatible
Cocoapod status
GitHub release
License
[Platform]()

Mamba

Mamba is a Swift iOS and tvOS framework to parse, validate and write HTTP Live Streaming (HLS) data.

This framework is used in Comcast applications to parse, validate, edit and write HLS playlists to deliver video to millions of customers. It was written by the Comcast VIPER Player Platform team.

Mamba Project Goals:

  • Simple-to-use parsing, editing and writing of HLS playlists.

  • Maximum performance. We required our parsing library to parse very large HLS playlists (12 hour Video-On-Demand) on low end phones in a few milliseconds. A internal core C library is used for very fast parsing of large playlists.

Requires

  • XCode 9+
  • Swift 3+ (written in Swift 4)
  • iOS 9+ or tvOS 10+

Usage

Parsing a HLS Playlist

Create an HLSParser.

let parser = HLSParser()

Parse your HLS playlist using the parser. Here’s the callback version:

let myPlaylistData: Data = ... // source of HLS data
let myPlaylistURL: URL = ... // the URL of this playlist resource

parser.parse(playlistData: myPlaylistData,
             url: myPlaylistURL,
             success: { playlist in
                  // do something with the parsed HLSPlaylist object
             },
             failure: { parserError in
                  // handle the HLSParserError
             })

And here’s the inline version:

let playlist: HLSPlaylist
do {
    // note: could take several milliseconds for large playlists!
    playlist = try parser.parse(playlistData: myPlaylistData,
                                url: myPlaylistURL)
}
catch {
    // we received an error in parsing this playlist
}
// do something with the parsed HLSPlaylist

You now have an HLS playlist object.

HLSPlaylist

This struct is a in-memory representation of a HLS playlist.

It includes:

  • The URL of the playlist.
  • An array of HLSTags that represent each line in the HLS playlist. This array is editable, so you can make edits to the playlist.
  • Utility functions to tell if a playlist is a master or variant, and if it is a Live, VOD or Event style playlist.
  • Helpful functionality around the structure of a playlist, including calculated references to the "header", "footer" and all the video segments and the metadata around them. This structure is kept up to date behind the scenes as the playlist is edited.

HLSPlaylist objects are highly editable.

Validating a HLS Playlist

Validate your HLS Playlist using the HLSCompletePlaylistValidator.

let issues = try HLSCompletePlaylistValidator.validate(hlsPlaylist: playlist)

It returns an array of HLSValidationIssues found with the HLS Playlist. They each have a description and a severity associated with them.

We currently implement only a subset of the HLS validation rules as described in the HLS specification. Improving our HLS validation coverage would be a most welcome pull request!

Writing a HLS Playlist

Create a HLSWriter.

let writer = HLSWriter()

Write your HLS playlist to a stream.

let stream: OutputStream = ... // stream to receive the HLS Playlist

do {
    try writer.write(hlsPlaylist: playlist, toStream: stream)
}
catch {
    // there was an error severe enough for us to stop writing the data
}

Using Custom Tags

Natively, Mamba only understands HLS tags as defined in the Pantos IETF specification. If you’d like to add support for a custom set of tags, you’ll need to create them as a object implementing HLSTagDescriptor. Please look at PantosTag or one of the examples in the unit tests for sample code.

If you have any custom HLSTagDescriptor collections you’d like to parse alongside the standard Pantos tags, pass them in through this HLSParser initializer:

enum MyCustomTagSet: String {
    // define your custom tags here
    case EXT_MY_CUSTOM_TAG = "EXT-MY-CUSTOM-TAG"
}

extension MyCustomTagSet: HLSTagDescriptor {
    ... // conform to HLSTagDescriptor here
}

let customParser = HLSParser(tagTypes: [MyCustomTagSet.self])

If there is specfic data inside your custom tag that you’d like to access, e.g.

#EXT-MY-CUSTOM-TAG:CUSTOMDATA1="Data1",CUSTOMDATA2="Data1"

you can define that data in an enum that conforms to HLSTagValueIdentifier:

enum MyCustomValueIdentifiers: String {
    // define your custom value identifiers here
    case CUSTOMDATA1 = "CUSTOMDATA1"
    case CUSTOMDATA2 = "CUSTOMDATA2"
}

extension MyCustomValueIdentifiers: HLSTagValueIdentifier {
    ... // conform to HLSTagValueIdentifier here
}

You can now look through HLSTag objects for your custom tag values just as if it were a valuetype defined in the HLS specification.

Important Note About Memory Safety

In order to achieve our performance goals, the internal C parser for HLS had to minimize the amount of heap memory allocated.

This meant that, for each HLSTag object that is included in a HLSPlaylist, instead of using a swift String to represent data, we use a HLSStringRef, which is a object that is a reference into the memory of the original data used to parse the playlist. This greatly speeds parsing, but comes at a cost: these HLSTag objects are unsafe to use beyond the lifetime of their parent HLSPlaylist.

In general, this is no problem. Normal usage of a HLSPlaylist would be (1) Parse the playlist, (2) Edit by manipulating HLSTags (3) Write the playlist.

If you do, for some reason, need to access HLSTag data beyond the lifetime of the parent HLSPlaylist object, you’ll need to make a copy of all HLSStringRef data of interest into a regular swift String. There’s a string conversion function in HLSStringRef to accomplish this.

Latest podspec

{
    "name": "mamba",
    "version": "1.0.3",
    "license": {
        "type": "Apache License, Version 2.0",
        "text": "                            Copyright 2017 Comcast Cable Communications Management, LLCn                            Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file n                            except in compliance with the License. You may obtain a copy of the License atn                                http://www.apache.org/licenses/LICENSE-2.0n                            Unless required by applicable law or agreed to in writing, software distributed under the n                            License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, n                            either express or implied. See the License for the specific language governing permissions n                            and limitations under the License.n                            This product includes software developed at Comcast (http://www.comcast.com/).n"
    },
    "homepage": "https://github.com/Comcast/mamba",
    "summary": "mamba - a library for parsing, validating and editing HLS manifests",
    "authors": "Comcast",
    "platforms": {
        "ios": "9.0",
        "tvos": "10.0"
    },
    "source": {
        "git": "https://github.com/Comcast/mamba.git",
        "tag": "1.0.3"
    },
    "source_files": "mambaSharedFramework/**/*.{h,m,swift,c}",
    "preserve_paths": "mambaSharedFramework/**/*.include",
    "frameworks": "CoreMedia",
    "requires_arc": true
}

Pin It on Pinterest

Share This