@@ -249,22 +249,22 @@ - (NSString *)hls_restoreOriginalUrl:(NSURL *)URL; // 将路径转换为原始ur
249249
250250@implementation NSString (HLS)
251251- (nullable NSString *)hls_findValueForAttribute : (NSString *)name startPos : (NSUInteger *)startPosPtr {
252- NSArray <NSString *> *attributePairs = [self componentsSeparatedByString: @" ," ];
253- NSString *prefix = [name stringByAppendingString: @" =" ];
254- __block NSUInteger startPos = 0 ;
255- NSString *pair = [attributePairs mcs_firstOrNull: ^BOOL (NSString * _Nonnull obj) {
256- if ( [obj hasPrefix: prefix] ) return YES ;
257- startPos += obj.length + 1 ; // + @",".length();
258- return NO ;
252+ NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern: @" ([A-Z0-9\\ -]+)=((?:\" [^\" ]+\" )|(?:[^,]+))" options: kNilOptions error: NULL ];
253+ NSArray <NSTextCheckingResult *> *results = [regex matchesInString: self options: kNilOptions range: NSMakeRange (0 , self .length)];
254+ NSTextCheckingResult *result = [results mcs_firstOrNull: ^BOOL (NSTextCheckingResult * _Nonnull obj) {
255+ NSString *matchedName = obj.numberOfRanges == 3 ? [self substringWithRange: [obj rangeAtIndex: 1 ]] : nil ;
256+ return matchedName && [matchedName isEqualToString: name];
259257 }];
260- if ( pair != nil ) {
261- startPos += prefix.length ;
262- NSString *value = [pair substringFromIndex: name.length + 1 ];
258+
259+ if ( result != nil ) {
260+ NSRange valueRange = [result rangeAtIndex: 2 ];
261+ NSUInteger valuePos = valueRange.location ;
262+ NSString *value = [self substringWithRange: valueRange];
263263 if ( [value hasPrefix: @" \" " ] ) { // 移除双引号;
264- startPos += 1 ; // @"\"".length();
265- value = [value stringByTrimmingCharactersInSet: [ NSCharacterSet characterSetWithCharactersInString: @" \" " ] ];
264+ valuePos += 1 ; // @"\"".length();
265+ value = [value substringWithRange: NSMakeRange ( 1 , value.length - 2 ) ];
266266 }
267- if ( startPosPtr != NULL ) *startPosPtr = startPos ;
267+ if ( startPosPtr != NULL ) *startPosPtr = valuePos ;
268268 return value;
269269 }
270270 return nil ;
@@ -285,53 +285,14 @@ - (BOOL)hls_toBOOL {
285285}
286286
287287- (NSString *)hls_restoreOriginalUrl : (NSURL *)resourceURL {
288- static NSString *const HLS_PREFIX_LOCALHOST = @" http://localhost" ;
289- static NSString *const HLS_PREFIX_DIR_ROOT = @" /" ;
290- static NSString *const HLS_PREFIX_DIR_PARENT = @" ../" ;
291- static NSString *const HLS_PREFIX_DIR_CURRENT = @" ./" ;
292-
293- NSString *url = nil ;
294- // / /video/name.m3u8
295- // /
296- if ( [self hasPrefix: HLS_PREFIX_DIR_ROOT] ) {
297- NSURL *rootDir = [NSURL URLWithString: [NSString stringWithFormat: @" %@ ://%@ " , resourceURL.scheme, resourceURL.host]];
298- NSString *subpath = self;
299- url = [rootDir mcs_URLByAppendingPathComponent: subpath].absoluteString ;
300- }
301- // / ../video/name.m3u8
302- // / ../../video/name.m3u8
303- // /
304- else if ( [self hasPrefix: HLS_PREFIX_DIR_PARENT] ) {
305- NSURL *curDir = resourceURL.mcs_URLByRemovingLastPathComponentAndQuery ;
306- NSURL *parentDir = curDir;
307- NSString *subpath = self;
308- while ( [subpath hasPrefix: HLS_PREFIX_DIR_PARENT] ) {
309- parentDir = parentDir.mcs_URLByRemovingLastPathComponentAndQuery ;
310- subpath = [subpath substringFromIndex: HLS_PREFIX_DIR_PARENT.length];
288+ if ( [self containsString: @" ://" ] ) {
289+ NSString *localhost = @" http://localhost" ;
290+ if ( [self hasPrefix: localhost] ) {
291+ return [NSURL URLWithString: [self substringFromIndex: localhost.length] relativeToURL: resourceURL].absoluteString ;
311292 }
312- url = [parentDir mcs_URLByAppendingPathComponent: subpath].absoluteString ;
313- }
314- // / ./video/name.m3u8
315- else if ( [self hasPrefix: HLS_PREFIX_DIR_CURRENT] ) {
316- NSURL *curDir = resourceURL.mcs_URLByRemovingLastPathComponentAndQuery ;
317- NSString *subpath = [self substringFromIndex: HLS_PREFIX_DIR_CURRENT.length];
318- url = [curDir mcs_URLByAppendingPathComponent: subpath].absoluteString ;
293+ return self;
319294 }
320- // / http://localhost
321- else if ( [self hasPrefix: HLS_PREFIX_LOCALHOST] ) {
322- NSURL *rootDir = [NSURL URLWithString: [NSString stringWithFormat: @" %@ ://%@ " , resourceURL.scheme, resourceURL.host]];
323- NSString *subpath = [self substringFromIndex: HLS_PREFIX_LOCALHOST.length];
324- url = [rootDir mcs_URLByAppendingPathComponent: subpath].absoluteString ;
325- }
326- else if ( [self containsString: @" ://" ] ) {
327- url = self;
328- }
329- else {
330- NSURL *curDir = resourceURL.mcs_URLByRemovingLastPathComponentAndQuery ;
331- NSString *subpath = self;
332- url = [curDir mcs_URLByAppendingPathComponent: subpath].absoluteString ;
333- }
334- return url;
295+ return [NSURL URLWithString: self relativeToURL: resourceURL].absoluteString ;
335296}
336297@end
337298
@@ -394,6 +355,7 @@ + (nullable NSString *)proxyPlaylistWithAsset:(NSString *)assetName
394355 HLSRenditionGroup *group = renditionGroups[key];
395356 if ( group == nil ) {
396357 group = [HLSRenditionGroup.alloc init ];
358+ group.renditionType = rendition.renditionType ;
397359 renditionGroups[key] = group;
398360 }
399361 [group addRendition: rendition];
@@ -493,13 +455,19 @@ + (NSString *)parse:(NSString *)playlist shouldTrim:(BOOL)shouldTrim parsingItem
493455 NSInteger lastLineIndex = lines.count - 1 ;
494456 __block NSUInteger offset = 0 ;
495457 [lines enumerateObjectsUsingBlock: ^(NSString *line, NSUInteger idx, BOOL * _Nonnull stop) {
458+ if ( shouldTrim && trimmedPlaylist.length != 0 ) [trimmedPlaylist appendString: @" \n " ];
459+
496460 // 去除行首尾的空白字符; 每一行要么是一个标签(以 #EXT 开头), 要么是一个 URI
497- NSString *trimmedLine = shouldTrim ? [line stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet ]] : line;
461+ NSString *curLine = shouldTrim ? [line stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet ]] : line;
498462 // 跳过空行和注释
499- if ( [trimmedLine hasPrefix: @" #EXT" ] ) [self handleTag: trimmedLine offset: offset parsingItems: parsingItems context: ctx]; // 这是一个标签行
500- else if ( ![trimmedLine isEqualToString: @" " ] ) [self handleURI: trimmedLine offset: offset context: ctx]; // 这是一个 URI 行
501- if ( shouldTrim ) idx != lastLineIndex ? [trimmedPlaylist appendFormat: @" %@ \n " , trimmedLine] : [trimmedPlaylist appendString: trimmedLine];
502- offset += trimmedLine.length + 1 ; // + @"\n"
463+ BOOL isTag = [curLine hasPrefix: @" #EXT" ];
464+ BOOL isComments = !isTag && [curLine hasPrefix: @" #" ];
465+ BOOL isUri = !isTag && !isComments && curLine.length > 0 ;
466+ if ( isTag ) [self handleTag: curLine offset: offset parsingItems: parsingItems context: ctx]; // 这是一个标签行
467+ else if ( isUri ) [self handleURI: curLine offset: offset context: ctx]; // 这是一个 URI 行
468+
469+ if ( shouldTrim && !isComments ) [trimmedPlaylist appendString: curLine];
470+ offset = (shouldTrim ? trimmedPlaylist.length : (offset + curLine.length )) + 1 ; // + @"\n"
503471 }];
504472 return shouldTrim ? trimmedPlaylist : playlist;
505473}
@@ -520,7 +488,7 @@ + (void)handleTag:(NSString *)tagLine offset:(NSUInteger)offset parsingItems:(NS
520488 // / #EXTINF:8.766667,
521489 // / #EXT-X-BYTERANGE:9194528@9662832
522490 // / segment.ts
523- else if ( [tagLine hasPrefix: EXT_X_BYTERANGE] ) {
491+ else if ( [tagLine hasPrefix: EXT_X_BYTERANGE] ) {
524492 HLSSegment *segment = ctx[HLS_CTX_LAST_ITEM];
525493 NSParameterAssert ([segment isKindOfClass: HLSSegment.class]);
526494 NSString *byteRange = [tagLine substringFromIndex: EXT_X_BYTERANGE.length];
0 commit comments