Skip to content

Commit

Permalink
Merge pull request #34 from Comcast/feature/event_style_updates
Browse files Browse the repository at this point in the history
Adding support for updating Event-style playlists efficiently when they are very large
  • Loading branch information
dcoufal authored Oct 12, 2018
2 parents 3dacfa8 + 7255195 commit c4ece63
Show file tree
Hide file tree
Showing 12 changed files with 612 additions and 46 deletions.
18 changes: 14 additions & 4 deletions mamba.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@
EC03B6731E5CC56B00BF1F97 /* RapidParserStateHandlers.h in Headers */ = {isa = PBXBuildFile; fileRef = EC03B6511E5CC56B00BF1F97 /* RapidParserStateHandlers.h */; };
EC0677DC21641FE500E715D1 /* CMTimeMakeFromStringCTests.m in Sources */ = {isa = PBXBuildFile; fileRef = EC0677DB21641FE500E715D1 /* CMTimeMakeFromStringCTests.m */; };
EC0677DD21641FE500E715D1 /* CMTimeMakeFromStringCTests.m in Sources */ = {isa = PBXBuildFile; fileRef = EC0677DB21641FE500E715D1 /* CMTimeMakeFromStringCTests.m */; };
EC0677DE2165753500E715D1 /* CMTimeMakeFromStringCTests.m in Sources */ = {isa = PBXBuildFile; fileRef = EC0677DB21641FE500E715D1 /* CMTimeMakeFromStringCTests.m */; };
EC0677E02166C7CC00E715D1 /* HLSParser_EventUpdateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC0677DF2166C7CC00E715D1 /* HLSParser_EventUpdateTests.swift */; };
EC0677E12166C7CC00E715D1 /* HLSParser_EventUpdateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC0677DF2166C7CC00E715D1 /* HLSParser_EventUpdateTests.swift */; };
EC0677E22166C7CC00E715D1 /* HLSParser_EventUpdateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC0677DF2166C7CC00E715D1 /* HLSParser_EventUpdateTests.swift */; };
EC073F571FE0572400689228 /* HLSTagCriterionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC073F561FE0572400689228 /* HLSTagCriterionTests.swift */; };
EC073F581FE0572400689228 /* HLSTagCriterionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC073F561FE0572400689228 /* HLSTagCriterionTests.swift */; };
EC073F5A1FE072DC00689228 /* HLSTagCollectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC073F591FE072DC00689228 /* HLSTagCollectionTests.swift */; };
Expand Down Expand Up @@ -636,6 +640,7 @@
EC03B6501E5CC56B00BF1F97 /* RapidParserStateHandlers.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = RapidParserStateHandlers.c; sourceTree = "<group>"; };
EC03B6511E5CC56B00BF1F97 /* RapidParserStateHandlers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RapidParserStateHandlers.h; sourceTree = "<group>"; };
EC0677DB21641FE500E715D1 /* CMTimeMakeFromStringCTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CMTimeMakeFromStringCTests.m; sourceTree = "<group>"; };
EC0677DF2166C7CC00E715D1 /* HLSParser_EventUpdateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HLSParser_EventUpdateTests.swift; sourceTree = "<group>"; };
EC073F561FE0572400689228 /* HLSTagCriterionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HLSTagCriterionTests.swift; sourceTree = "<group>"; };
EC073F591FE072DC00689228 /* HLSTagCollectionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HLSTagCollectionTests.swift; sourceTree = "<group>"; };
EC073F5C1FE0840000689228 /* OutputStreamExtensionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OutputStreamExtensionTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -961,16 +966,17 @@
children = (
EC6C8F821D08C78C007C1C99 /* Fixtures */,
EC6C8F831D08C793007C1C99 /* Helpers */,
43DE4EFE1E564E1500EEE800 /* HLSMediaSpanTests.swift */,
EC0677DF2166C7CC00E715D1 /* HLSParser_EventUpdateTests.swift */,
EC7492351DD29E7300AF4E20 /* HLSParser_Super8DemuxedTests.swift */,
EC7492361DD29E7300AF4E20 /* HLSParser_Super8MuxedTests.swift */,
EC7492371DD29E7300AF4E20 /* HLSParserTest.swift */,
EC6F38911EA95882006BC30E /* HLSPlaylistInterfaceTests.swift */,
EC37A8D61E9C16C7005E8342 /* HLSPlaylistStructureAndEditingTests.swift */,
4367C3721EAE83C000685945 /* HLSPlaylistStructureMasterTests.swift */,
ECC410691EA1687500B4E3C8 /* HLSPlaylistStructureTests.swift */,
EC402B921F7D5A8B00730C74 /* HLSPlaylistTests.swift */,
ECE36DE31F2A9F10005E5DA7 /* HLSPlaylistTimelineAndSequencingTests.swift */,
43DE4EFE1E564E1500EEE800 /* HLSMediaSpanTests.swift */,
EC7492351DD29E7300AF4E20 /* HLSParser_Super8DemuxedTests.swift */,
EC7492361DD29E7300AF4E20 /* HLSParser_Super8MuxedTests.swift */,
EC7492371DD29E7300AF4E20 /* HLSParserTest.swift */,
883290551EA172170064588B /* HLSStringRefExtensionTests.swift */,
EC073F591FE072DC00689228 /* HLSTagCollectionTests.swift */,
EC073F561FE0572400689228 /* HLSTagCriterionTests.swift */,
Expand Down Expand Up @@ -1825,6 +1831,7 @@
EC74928A1DD29F1500AF4E20 /* GenericDictionaryTagValidatorTests.swift in Sources */,
EC073F601FE08F7500689228 /* String+Helio.swift in Sources */,
EC74922C1DD29E4A00AF4E20 /* HLSPlaylist+Convenience.swift in Sources */,
EC0677E02166C7CC00E715D1 /* HLSParser_EventUpdateTests.swift in Sources */,
EC7492B71DD29F8900AF4E20 /* HLSPlaylistTypeTests.swift in Sources */,
ECFBD9101E5CCC2200379FC2 /* ParseArrayTests.m in Sources */,
EC7492B31DD29F8900AF4E20 /* HLSCodecArrayTests.swift in Sources */,
Expand Down Expand Up @@ -1984,6 +1991,7 @@
EC74924B1DD29E7300AF4E20 /* HLSWriterTests.swift in Sources */,
EC073F611FE08F7500689228 /* String+Helio.swift in Sources */,
EC74928B1DD29F1500AF4E20 /* GenericDictionaryTagValidatorTests.swift in Sources */,
EC0677E12166C7CC00E715D1 /* HLSParser_EventUpdateTests.swift in Sources */,
EC74922D1DD29E4A00AF4E20 /* HLSPlaylist+Convenience.swift in Sources */,
ECFBD9111E5CCC2200379FC2 /* ParseArrayTests.m in Sources */,
EC7492B81DD29F8900AF4E20 /* HLSPlaylistTypeTests.swift in Sources */,
Expand Down Expand Up @@ -2117,6 +2125,7 @@
ECE253E1209A509900D388CE /* HLSTagCollectionTests.swift in Sources */,
ECE253DD209A509900D388CE /* HLSParser_Super8DemuxedTests.swift in Sources */,
ECE253DC209A509900D388CE /* HLSMediaSpanTests.swift in Sources */,
EC0677DE2165753500E715D1 /* CMTimeMakeFromStringCTests.m in Sources */,
ECE253E7209A509900D388CE /* HLSWriterTests.swift in Sources */,
ECE253D1209A509000D388CE /* FixtureLoader.swift in Sources */,
ECE253D2209A509000D388CE /* HLSPlaylist+Convenience.swift in Sources */,
Expand All @@ -2142,6 +2151,7 @@
ECE253FE209A50B500D388CE /* CMTimeMakeFromStringTests.swift in Sources */,
ECE253D9209A509900D388CE /* HLSPlaylistStructureTests.swift in Sources */,
ECE253EC209A50A100D388CE /* RapidParserTests.swift in Sources */,
EC0677E22166C7CC00E715D1 /* HLSParser_EventUpdateTests.swift in Sources */,
ECE253FC209A50B500D388CE /* GenericSingleTagWriterTests.swift in Sources */,
ECE253DA209A509900D388CE /* HLSPlaylistTests.swift in Sources */,
ECE253F4209A50B500D388CE /* EXT_X_PROGRAM_DATE_TIMEParserTests.swift in Sources */,
Expand Down
12 changes: 10 additions & 2 deletions mambaSharedFramework/HLS Models/HLSPlaylist.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public extension HLSPlaylistCore where T == HLSPlaylistURLData {
self.init(url: playlist.url, tags: playlist.tags, registeredTags: playlist.registeredTags, hlsData: playlist.hlsData)
}

// care should be taken when constructing `HLSPlaylist` manually. Most users should construct these objects using `HLSParser`
// care should be taken when constructing `HLSPlaylist` manually. Users should construct these objects using `HLSParser`
public init(url: URL, tags: [HLSTag], registeredTags: RegisteredHLSTags, hlsData: Data) {
let customData = HLSPlaylistURLData(url: url)
self.init(tags: tags, registeredTags: registeredTags, hlsData: hlsData, customData: customData)
Expand All @@ -50,12 +50,20 @@ public extension HLSPlaylistCore where T == HLSPlaylistURLData {
}
}

/// The time this playlist was created. Based on `CACurrentMediaTime`, so only comparable with that time system.
public var creationTime: TimeInterval {
get {
return customData.creationTime
}
}

public var debugDescription: String {
return "HLSPlaylist url:\(url)\n\(self.playlistCoreDebugDescription)"
return "HLSPlaylist url:\(url) createTime:\(creationTime)\n\(self.playlistCoreDebugDescription)"
}
}

/// A type used internally by HLSPlaylist
public struct HLSPlaylistURLData {
var url: URL
let creationTime = CACurrentMediaTime()
}
10 changes: 5 additions & 5 deletions mambaSharedFramework/HLS Rapid Parser/HLSRapidParser.m
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ - (void)newEXTINFTagWithStartTagName:(UInt64)startTagName
endTagData:(UInt64)endRemainingTagData;
- (void)newCommentWithStart:(UInt64)startComment
end:(UInt64)endComment;
- (void)newURLWithStart:(UInt64)startURL
- (BOOL)newURLWithStart:(UInt64)startURL
end:(UInt64)endURL;
- (void)parseComplete;
- (void)parseError:(NSString *)errorString
Expand Down Expand Up @@ -83,9 +83,9 @@ void NewCommentCallback(const void *parentparser, const uint64_t startComment, c
[parser newCommentWithStart:startComment end:endComment];
}

void NewURLCallback(const void *parentparser, const uint64_t startURL, const uint64_t endURL) {
bool NewURLCallback(const void *parentparser, const uint64_t startURL, const uint64_t endURL) {
HLSRapidParser *parser = (__bridge HLSRapidParser *)(parentparser);
[parser newURLWithStart:startURL end:endURL];
return [parser newURLWithStart:startURL end:endURL] == YES;
}

void ParseComplete(const void *parentparser) {
Expand Down Expand Up @@ -186,12 +186,12 @@ - (void)newCommentWithStart:(UInt64)startComment
[self.callback addedCommentLine:comment];
}

- (void)newURLWithStart:(UInt64)startURL
- (BOOL)newURLWithStart:(UInt64)startURL
end:(UInt64)endURL {

HLSStringRef *url = [[HLSStringRef alloc] initWithBytesNoCopy:[self.data bytes] + startURL length:(NSUInteger)(endURL - startURL + 1)];

[self.callback addedURLLine:url];
return [self.callback addedURLLine:url];
}

- (void)parseComplete {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
@protocol HLSRapidParserCallback <NSObject>

- (void)addedCommentLine:(HLSStringRef * _Nonnull)comment;
- (void)addedURLLine:(HLSStringRef * _Nonnull)url;
- (BOOL)addedURLLine:(HLSStringRef * _Nonnull)url;
- (void)addedNoValueTagWithName:(HLSStringRef * _Nonnull)tagName;
- (void)addedTagWithName:(HLSStringRef * _Nonnull)tagName
value:(HLSStringRef * _Nonnull)value;
Expand Down
9 changes: 5 additions & 4 deletions mambaSharedFramework/HLS Rapid Parser/RapidParser.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,24 +35,25 @@ void parseHLS(const void *parentparser, const unsigned char *bytes, const uint64

rapid_parser_debug_print("Begining parse of hls data with length %llu\n", length);

while (index > 0 && state != ErrorEarlyExit) {
while (index > 0 && state < numberOfScanningParseStates) {

index -= 1;

state = (*masterParseArray[state][bytes[index]]) (parentparser, bytes[index], index, state, &lineState);

rapid_parser_debug_print("State %i after processing character %c at index %llu\n", (int)state, bytes[index], index);

}

if (index == 0 && state != ErrorEarlyExit) {
// if we are in ErrorEarlyExit or EarlyExit we do not have to handle the final line
if (index == 0 && state < numberOfScanningParseStates) {
// handle the final line, force a line completion
// note that we pass "-1" as the index, because we are pretending that there is a newline at position -1
(*masterParseArray[state]['\n']) (parentparser, '\n', -1, state, &lineState);
}

// if we are in ErrorEarlyExit another part of the code already called ParseError to exit out
if (state != ErrorEarlyExit) {
// if we are in EarlyExit, its because the client has asked us to exit and they know that parsing is complete
if (state < numberOfScanningParseStates) {

rapid_parser_debug_print("Ending parse of hls data with length %llu\n", length);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,14 @@
#ifndef RapidParserCallback_h
#define RapidParserCallback_h

#include <stdbool.h>

void NewTagCallback(const void *parentparser, const uint64_t startTagName, const uint64_t endTagName, const uint64_t startTagData, const uint64_t endTagData);
void NewTagNoDataCallback(const void *parentparser, const uint64_t startTagName, const uint64_t endTagName);
void NewEXTINFTagNoDataCallback(const void *parentparser, const uint64_t startTagName, const uint64_t endTagName, const uint64_t startDuration, const uint64_t endDuration, const uint64_t startTagData, const uint64_t endTagData);
void NewCommentCallback(const void *parentparser, const uint64_t startComment, const uint64_t endComment);
void NewURLCallback(const void *parentparser, const uint64_t startURL, const uint64_t endURL);
// return true to NewURLCallback to continue scanning, false to trigger an early exit and stop the parse
bool NewURLCallback(const void *parentparser, const uint64_t startURL, const uint64_t endURL);
void ParseComplete(const void *parentparser);
void ParseError(const void *parentparser, const uint32_t errorNum, const char *errorString);

Expand Down
2 changes: 2 additions & 0 deletions mambaSharedFramework/HLS Rapid Parser/RapidParserState.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ enum ParseState {
LookingForHashForEXTINF,
// when we find a #, we start looking for a newline to possibly complete a #EXTINF and make a tag
LookingForNewlineForEXTINF,
// signal an early exit (not an error, but the client has requested a stop scanning) (THIS NEEDS TO BE SECOND TO LAST IN THE PARSE STATE LIST)
EarlyExit,
// when we encounter an error, signal an early exit (THIS NEEDS TO BE LAST IN THE PARSE STATE LIST)
ErrorEarlyExit
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ uint8_t endOfLineForURLAndContinueScanning(const void *parentparser, const unsig
lineState->end = index - 1;
return Scanning;
}
NewURLCallback(parentparser, lineState->start, lineState->end);
bool shouldContinue = NewURLCallback(parentparser, lineState->start, lineState->end);
initializeLineState(lineState);
lineState->end = index - 1;
return Scanning;
return shouldContinue ? Scanning : EarlyExit;
}

// Scanning Handlers for LookingForX state
Expand Down Expand Up @@ -195,6 +195,5 @@ uint8_t foundNewlineCompletingEXTINFBeginAndContinueScanning(const void *parentp
initializeLineState(lineState);
lineState->end = index - 1;
return Scanning;

}

Loading

0 comments on commit c4ece63

Please sign in to comment.