From 63090f77477bd4bfef1b69b3ef348d9b515973fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20De=CC=81fago?= Date: Fri, 11 Dec 2020 11:18:28 +0100 Subject: [PATCH 1/6] Bump version number --- Demo/Demo.xcconfig | 2 +- Package.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Demo/Demo.xcconfig b/Demo/Demo.xcconfig index 6bb620e..dabae3c 100644 --- a/Demo/Demo.xcconfig +++ b/Demo/Demo.xcconfig @@ -1,5 +1,5 @@ // Version information -MARKETING_VERSION = 3.0.2 +MARKETING_VERSION = 3.0.3 // Deployment targets IPHONEOS_DEPLOYMENT_TARGET = 9.0 diff --git a/Package.swift b/Package.swift index e08b037..8e5082d 100644 --- a/Package.swift +++ b/Package.swift @@ -3,7 +3,7 @@ import PackageDescription struct ProjectSettings { - static let marketingVersion: String = "3.0.2" + static let marketingVersion: String = "3.0.3" } let package = Package( From 8c8d790ad19de95f92965af4b1f77c9b06f429f7 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Bertholon Date: Wed, 14 Oct 2020 22:46:09 +0200 Subject: [PATCH 2/6] Add new LSVE test stream url in demo --- Demo/Resources/MediaDemoConfiguration.plist | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Demo/Resources/MediaDemoConfiguration.plist b/Demo/Resources/MediaDemoConfiguration.plist index 5705e63..1cdc604 100644 --- a/Demo/Resources/MediaDemoConfiguration.plist +++ b/Demo/Resources/MediaDemoConfiguration.plist @@ -16,6 +16,12 @@ url https://srgssruni11ch-lh.akamaihd.net/i/enc11uni_ch@191455/master.m3u8 + + name + Akamai LSVE token-protected HLS stream + url + https://srgssr-akaprep.akamaized.net/hls/live/2022085/srf1-test/master.m3u8 + name FairPlay-protected HLS live stream From 46341a8f2048455e308f27dc551479d31eae56ce Mon Sep 17 00:00:00 2001 From: Pierre-Yves Bertholon Date: Wed, 16 Dec 2020 19:47:39 +0100 Subject: [PATCH 3/6] #7 Load the master playlist and use it if a child playlist has a full length url Compatible for all tvOS versions --- .../SRGAkamaiAssetResourceLoaderDelegate.m | 64 +++++++++++-------- 1 file changed, 37 insertions(+), 27 deletions(-) diff --git a/Sources/SRGContentProtection/SRGAkamaiAssetResourceLoaderDelegate.m b/Sources/SRGContentProtection/SRGAkamaiAssetResourceLoaderDelegate.m index a42c15b..5a11411 100644 --- a/Sources/SRGContentProtection/SRGAkamaiAssetResourceLoaderDelegate.m +++ b/Sources/SRGContentProtection/SRGAkamaiAssetResourceLoaderDelegate.m @@ -99,38 +99,48 @@ - (BOOL)shouldProcessResourceLoadingRequest:(AVAssetResourceLoadingRequest *)loa [diagnosticInformation setString:error.localizedDescription forKey:@"errorMessage"]; [diagnosticInformation stopTimeMeasurementForKey:@"duration"]; - // Redirecting to the tokenized URL preserves cookies on iOS 11+ and restores original scheme url. - if (@available(iOS 11, *)) { - NSMutableURLRequest *redirect = loadingRequest.request.mutableCopy; - redirect.URL = URL; - loadingRequest.redirect = redirect.copy; - - loadingRequest.response = [[NSHTTPURLResponse alloc] initWithURL:URL statusCode:303 HTTPVersion:nil headerFields:nil]; - [loadingRequest finishLoading]; - } - // Retrieve the master playlist on iOS 9 and 10 to preserve cookies. - // Known issue if next resource url is relative: it reuses the previous scheme url, host and path, which includes the custom scheme url again. - // See https://github.com/SRGSSR/srgcontentprotection-apple/issues/6 - else { - NSMutableURLRequest *playlistRequest = loadingRequest.request.mutableCopy; - playlistRequest.URL = URL; - SRGRequest *request = [[SRGRequest dataRequestWithURLRequest:playlistRequest session:self.session completionBlock:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { - loadingRequest.response = response; + // Retrieve the master playlist to check if the master playlist is compatible with our "download" implementation. + NSMutableURLRequest *playlistRequest = loadingRequest.request.mutableCopy; + playlistRequest.URL = URL; + SRGRequest *request = [[SRGRequest dataRequestWithURLRequest:playlistRequest session:self.session completionBlock:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { + loadingRequest.response = response; + if (error) { + NSMutableDictionary *userInfo = @{ NSLocalizedDescriptionKey : SRGContentProtectionLocalizedString(@"This content is protected and cannot be played without proper rights.", @"User-facing message displayed proper authorization to play a stream has not been obtained") }.mutableCopy; if (error) { - NSMutableDictionary *userInfo = @{ NSLocalizedDescriptionKey : SRGContentProtectionLocalizedString(@"This content is protected and cannot be played without proper rights.", @"User-facing message displayed proper authorization to play a stream has not been obtained") }.mutableCopy; - if (error) { - userInfo[NSUnderlyingErrorKey] = error; - } - NSError *friendlyError = [NSError errorWithDomain:SRGContentProtectionErrorDomain code:SRGContentProtectionErrorUnauthorized userInfo:userInfo.copy]; - [loadingRequest finishLoadingWithError:friendlyError]; + userInfo[NSUnderlyingErrorKey] = error; } - else { + NSError *friendlyError = [NSError errorWithDomain:SRGContentProtectionErrorDomain code:SRGContentProtectionErrorUnauthorized userInfo:userInfo.copy]; + [loadingRequest finishLoadingWithError:friendlyError]; + } + else { + NSString *masterPlaylistString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + + // If an #EXT-X-STREAM-INF has a full length url, the master playlist is compatible with our "download" implementation for iOS 9 and tvOS 9 + if ([masterPlaylistString containsString:@"\nhttp"]) { [loadingRequest.dataRequest respondWithData:data]; [loadingRequest finishLoading]; } - }] requestWithOptions:SRGRequestOptionBackgroundCompletionEnabled]; - [self.requestQueue addRequest:request resume:YES]; - } + else { + // Redirect to the tokenized url to restores original scheme url and preserves cookies on iOS 11+ and tvOS 11+ + if (@available(iOS 11, *)) { + NSMutableURLRequest *redirect = loadingRequest.request.mutableCopy; + redirect.URL = URL; + loadingRequest.redirect = redirect.copy; + + loadingRequest.response = [[NSHTTPURLResponse alloc] initWithURL:URL statusCode:303 HTTPVersion:nil headerFields:nil]; + [loadingRequest finishLoading]; + } + else { + // Known issue if next resource url is relative: Our "download" implementation reuses the previous scheme url, host and path, which includes the custom scheme url again. + // See https://github.com/SRGSSR/srgcontentprotection-apple/issues/6 + [loadingRequest.dataRequest respondWithData:data]; + [loadingRequest finishLoading]; + } + } + } + }] requestWithOptions:SRGRequestOptionBackgroundCompletionEnabled]; + [self.requestQueue addRequest:request resume:YES]; + }] requestWithOptions:SRGRequestOptionBackgroundCompletionEnabled]; [self.requestQueue addRequest:request resume:YES]; return YES; From d7eebdb740767b9627fdeb1bc2c0f45a9a5244a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20De=CC=81fago?= Date: Thu, 17 Dec 2020 09:19:13 +0100 Subject: [PATCH 4/6] Use redirect when partial URLs are detected No need to respond with data, as playback on iOS 9 and 10 fails for both approaches anyway. --- .../SRGAkamaiAssetResourceLoaderDelegate.m | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/Sources/SRGContentProtection/SRGAkamaiAssetResourceLoaderDelegate.m b/Sources/SRGContentProtection/SRGAkamaiAssetResourceLoaderDelegate.m index 5a11411..8428697 100644 --- a/Sources/SRGContentProtection/SRGAkamaiAssetResourceLoaderDelegate.m +++ b/Sources/SRGContentProtection/SRGAkamaiAssetResourceLoaderDelegate.m @@ -99,7 +99,7 @@ - (BOOL)shouldProcessResourceLoadingRequest:(AVAssetResourceLoadingRequest *)loa [diagnosticInformation setString:error.localizedDescription forKey:@"errorMessage"]; [diagnosticInformation stopTimeMeasurementForKey:@"duration"]; - // Retrieve the master playlist to check if the master playlist is compatible with our "download" implementation. + // Retrieve the master playlist to find how we shopuld respond to the loading request for maximum compatibility. NSMutableURLRequest *playlistRequest = loadingRequest.request.mutableCopy; playlistRequest.URL = URL; SRGRequest *request = [[SRGRequest dataRequestWithURLRequest:playlistRequest session:self.session completionBlock:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { @@ -115,32 +115,36 @@ - (BOOL)shouldProcessResourceLoadingRequest:(AVAssetResourceLoadingRequest *)loa else { NSString *masterPlaylistString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; - // If an #EXT-X-STREAM-INF has a full length url, the master playlist is compatible with our "download" implementation for iOS 9 and tvOS 9 + // If #EXT-X-STREAM-INF are absolute URLs, the master playlist we retrieved can be provided as response + // data to the loading request. This works on all iOS and tvOS versions we support, and also when casting + // to any Apple TV receiver via AirPlay (including old receivers like Apple TV 3rd gen which uses an even + // older version of tvOS). + // + // Remark: Absolute URLs are required for iOS / tvOS 9 and 10 compatibilty, otherwise the stream will + // not play. See https://github.com/SRGSSR/srgcontentprotection-apple/issues/6. Playlists with + // relative URLs will not play correctly. if ([masterPlaylistString containsString:@"\nhttp"]) { [loadingRequest.dataRequest respondWithData:data]; [loadingRequest finishLoading]; } + // If partial URLs are detected, simply redirect to the tokenized URL. This restores original scheme URL and + // preserves cookies on iOS 11+ and tvOS 11+. This does not work on older iOS and tvOS versions, but there + // is nothing else we can do for them. + // + // Remark: The redirect approach also works fine on iOS 11+ and tvOS 11+ if the master playlist contains + // absolute URLs. But still we have to provide the response directly, as an iOS 11+ device can + // cast to an old Apple TV 3rd gen receiver which would not support the redirect. else { - // Redirect to the tokenized url to restores original scheme url and preserves cookies on iOS 11+ and tvOS 11+ - if (@available(iOS 11, *)) { - NSMutableURLRequest *redirect = loadingRequest.request.mutableCopy; - redirect.URL = URL; - loadingRequest.redirect = redirect.copy; - - loadingRequest.response = [[NSHTTPURLResponse alloc] initWithURL:URL statusCode:303 HTTPVersion:nil headerFields:nil]; - [loadingRequest finishLoading]; - } - else { - // Known issue if next resource url is relative: Our "download" implementation reuses the previous scheme url, host and path, which includes the custom scheme url again. - // See https://github.com/SRGSSR/srgcontentprotection-apple/issues/6 - [loadingRequest.dataRequest respondWithData:data]; - [loadingRequest finishLoading]; - } + NSMutableURLRequest *redirect = loadingRequest.request.mutableCopy; + redirect.URL = URL; + loadingRequest.redirect = redirect.copy; + + loadingRequest.response = [[NSHTTPURLResponse alloc] initWithURL:URL statusCode:303 HTTPVersion:nil headerFields:nil]; + [loadingRequest finishLoading]; } } }] requestWithOptions:SRGRequestOptionBackgroundCompletionEnabled]; [self.requestQueue addRequest:request resume:YES]; - }] requestWithOptions:SRGRequestOptionBackgroundCompletionEnabled]; [self.requestQueue addRequest:request resume:YES]; return YES; From d8d9ec67160a5c1e3e004fe592b88ea35b39dddc Mon Sep 17 00:00:00 2001 From: Pierre-Yves Bertholon Date: Thu, 17 Dec 2020 19:53:22 +0100 Subject: [PATCH 5/6] Fix typo --- .../SRGAkamaiAssetResourceLoaderDelegate.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/SRGContentProtection/SRGAkamaiAssetResourceLoaderDelegate.m b/Sources/SRGContentProtection/SRGAkamaiAssetResourceLoaderDelegate.m index 8428697..d5c87a0 100644 --- a/Sources/SRGContentProtection/SRGAkamaiAssetResourceLoaderDelegate.m +++ b/Sources/SRGContentProtection/SRGAkamaiAssetResourceLoaderDelegate.m @@ -99,7 +99,7 @@ - (BOOL)shouldProcessResourceLoadingRequest:(AVAssetResourceLoadingRequest *)loa [diagnosticInformation setString:error.localizedDescription forKey:@"errorMessage"]; [diagnosticInformation stopTimeMeasurementForKey:@"duration"]; - // Retrieve the master playlist to find how we shopuld respond to the loading request for maximum compatibility. + // Retrieve the master playlist to find how we should respond to the loading request for maximum compatibility. NSMutableURLRequest *playlistRequest = loadingRequest.request.mutableCopy; playlistRequest.URL = URL; SRGRequest *request = [[SRGRequest dataRequestWithURLRequest:playlistRequest session:self.session completionBlock:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { @@ -118,10 +118,10 @@ - (BOOL)shouldProcessResourceLoadingRequest:(AVAssetResourceLoadingRequest *)loa // If #EXT-X-STREAM-INF are absolute URLs, the master playlist we retrieved can be provided as response // data to the loading request. This works on all iOS and tvOS versions we support, and also when casting // to any Apple TV receiver via AirPlay (including old receivers like Apple TV 3rd gen which uses an even - // older version of tvOS). + // older version of tvOS). See https://github.com/SRGSSR/srgcontentprotection-apple/issues/7 . // // Remark: Absolute URLs are required for iOS / tvOS 9 and 10 compatibilty, otherwise the stream will - // not play. See https://github.com/SRGSSR/srgcontentprotection-apple/issues/6. Playlists with + // not play. See https://github.com/SRGSSR/srgcontentprotection-apple/issues/6 . Playlists with // relative URLs will not play correctly. if ([masterPlaylistString containsString:@"\nhttp"]) { [loadingRequest.dataRequest respondWithData:data]; From 5c149d814c981ef2c8fd209f8dfe888dd911f0d3 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Bertholon Date: Thu, 17 Dec 2020 23:05:55 +0100 Subject: [PATCH 6/6] Revert "Add new LSVE test stream url in demo" This reverts commit 8c8d790ad19de95f92965af4b1f77c9b06f429f7. --- Demo/Resources/MediaDemoConfiguration.plist | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Demo/Resources/MediaDemoConfiguration.plist b/Demo/Resources/MediaDemoConfiguration.plist index 1cdc604..5705e63 100644 --- a/Demo/Resources/MediaDemoConfiguration.plist +++ b/Demo/Resources/MediaDemoConfiguration.plist @@ -16,12 +16,6 @@ url https://srgssruni11ch-lh.akamaihd.net/i/enc11uni_ch@191455/master.m3u8 - - name - Akamai LSVE token-protected HLS stream - url - https://srgssr-akaprep.akamaized.net/hls/live/2022085/srf1-test/master.m3u8 - name FairPlay-protected HLS live stream