Skip to content

Commit

Permalink
Merge branch 'release/3.4'
Browse files Browse the repository at this point in the history
  • Loading branch information
defagos committed Sep 11, 2018
2 parents 54b2c38 + 0858522 commit decb749
Show file tree
Hide file tree
Showing 32 changed files with 1,651 additions and 705 deletions.
17 changes: 13 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
Carthage
xcuserdata
.DS_Store
report.xml
test_output

*.xcscmblueprint
xcuserdata

archive
build

Carthage
Cartfile.private
Cartfile.resolved

fastlane/report.xml
fastlane/test_output
4 changes: 2 additions & 2 deletions Cartfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
github "SRGSSR/SRGMediaPlayer-iOS" "2.4.3"
github "SRGSSR/srgdataprovider-ios" "6.1"
github "SRGSSR/srgdataprovider-ios" "6.2"
github "SRGSSR/SRGMediaPlayer-iOS" "2.5"
github "SRGSSR/tagcommander-ios" "4.1.5_4.1.3"
github "comScore/ComScore-iOS-SDK" "92f34897cd7659d56bb5a3e9e85b808cf3758bda"
File renamed without changes.
1 change: 1 addition & 0 deletions Cartfile.private.proprietary
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
github "SRGSSR/srgcontentprotection-ios" "1.0"
9 changes: 0 additions & 9 deletions Cartfile.resolved

This file was deleted.

11 changes: 11 additions & 0 deletions Cartfile.resolved.proprietary
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
github "Mantle/Mantle" "2.1.0"
github "SRGSSR/MAKVONotificationCenter" "120fb5550aee8e9b4c92439bf34533020cc43c44"
github "SRGSSR/SRGMediaPlayer-iOS" "2.5"
github "SRGSSR/libextobjc" "80a882742fea920587df5c9377af68faa22be5d0"
github "SRGSSR/srgcontentprotection-ios" "1.0"
github "SRGSSR/srgdataprovider-ios" "6.2"
github "SRGSSR/srglogger-ios" "1.0.5"
github "SRGSSR/srgnetwork-ios" "0.1"
github "SRGSSR/tagcommander-ios" "4.1.5_4.1.3"
github "comScore/ComScore-iOS-SDK" "92f34897cd7659d56bb5a3e9e85b808cf3758bda"
github "kif-framework/KIF" "v3.6.0"
10 changes: 10 additions & 0 deletions Cartfile.resolved.public
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
github "Mantle/Mantle" "2.1.0"
github "SRGSSR/MAKVONotificationCenter" "120fb5550aee8e9b4c92439bf34533020cc43c44"
github "SRGSSR/SRGMediaPlayer-iOS" "2.5"
github "SRGSSR/libextobjc" "80a882742fea920587df5c9377af68faa22be5d0"
github "SRGSSR/srgdataprovider-ios" "6.2"
github "SRGSSR/srglogger-ios" "1.0.5"
github "SRGSSR/srgnetwork-ios" "0.1"
github "SRGSSR/tagcommander-ios" "4.1.5_4.1.3"
github "comScore/ComScore-iOS-SDK" "92f34897cd7659d56bb5a3e9e85b808cf3758bda"
github "kif-framework/KIF" "v3.6.0"
File renamed without changes.
File renamed without changes.
12 changes: 7 additions & 5 deletions Framework/Sources/Helpers/NSBundle+SRGAnalytics.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ @implementation NSBundle (SRGAnalytics)

+ (instancetype)srg_analyticsBundle
{
static NSBundle *bundle;
static dispatch_once_t once;
dispatch_once(&once, ^{
bundle = [NSBundle bundleForClass:[SRGAnalyticsTracker class]];
static NSBundle *s_bundle;
static dispatch_once_t s_onceToken;
dispatch_once(&s_onceToken, ^{
NSString *bundlePath = [[NSBundle bundleForClass:[SRGAnalyticsTracker class]].bundlePath stringByAppendingPathComponent:@"SRGAnalytics.bundle"];
s_bundle = [NSBundle bundleWithPath:bundlePath];
NSAssert(s_bundle, @"Please add SRGAnalytics.bundle to your project resources");
});
return bundle;
return s_bundle;
}

+ (BOOL)srg_isProductionVersion
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// Copyright (c) SRG SSR. All rights reserved.
//
// License information is available from the LICENSE file.
//

#import <SRGDataProvider/SRGDataProvider.h>

NS_ASSUME_NONNULL_BEGIN

@interface SRGResource (SRGAnalytics_DataProvider)

/**
* Returns `YES` iff the resource requires DRM.
*/
@property (nonatomic, readonly) BOOL srg_requiresDRM;

@end

NS_ASSUME_NONNULL_END
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// Copyright (c) SRG SSR. All rights reserved.
//
// License information is available from the LICENSE file.
//

#import "SRGResource+SRGAnalytics_DataProvider.h"

#import <libextobjc/libextobjc.h>

@implementation SRGResource (SRGAnalytics_DataProvider)

- (BOOL)srg_requiresDRM
{
return self.DRMs.count != 0;
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -5,44 +5,48 @@
//

#import <SRGAnalytics/SRGAnalytics.h>
#import <SRGMediaPlayer/SRGMediaPlayer.h>
#import <SRGDataProvider/SRGDataProvider.h>
#import <SRGMediaPlayer/SRGMediaPlayer.h>

NS_ASSUME_NONNULL_BEGIN

// Completion block signatures.
typedef void (^SRGResourceCompletionBlock)(NSURL * _Nullable tokenizedURL, SRGResource *resource, NSArray<id<SRGSegment>> *segments, NSInteger index, SRGAnalyticsStreamLabels * _Nullable analyticsLabels, NSError * _Nullable error);
typedef void (^SRGPlaybackContextBlock)(NSURL *streamURL, SRGResource *resource, NSArray<id<SRGSegment>> * _Nullable segments, NSInteger index, SRGAnalyticsStreamLabels * _Nullable analyticsLabels);

@interface SRGMediaComposition (SRGAnalytics_DataProvider)

/**
* Return a request to retrieve a playable resource for the receiver, trying to use the specified preferred settings.
* If no exact match can be found for the specified settings, a recommended valid setup will be used instead. A
* readily tokenized URL (playable for a limited time only) is also provided to the completion block.
* Retrieve a playback context for the receiver, trying to use the specified preferred settings. If no exact match can
* be found for the specified settings, a recommended valid setup will be used instead.
*
* @param streamingMethod The streaming method to use. If `SRGStreamingMethodNone` or if the method is not
* found, a recommended method will be used instead.
* @param streamType The stream type to use. If `SRGStreamTypeNone` or not found, the optimal available stream
* type is used.
* @param quality The quality to use. If `SRGQualityNone` or not found, the best available quality
* is used.
* @param DRM Set to `YES` if DRM-protected streams should be favored over non-protected ones. If set
* to `NO`, the first matching resource is used, based on their original order.
* @param startBitRate The bit rate the media should start playing with, in kbps. This parameter is a
* recommendation with no result guarantee, though it should in general be applied. The
* nearest available quality (larger or smaller than the requested size) will be used.
* Usual SRG SSR valid bit ranges vary from 100 to 3000 kbps. Use 0 to start with the
* lowest quality stream.
* @param userInfo Optional dictionary conveying arbitrary information during playback.
* @param completionHandler The completion handler, returning the URL, the associated resource, the segments associated
* with the media, the segment index to start with, as well as consolidated analytics labels.
* @param resultBlock The block called to return the resolved resource context (stream URL, resource, segments
* associated with the media, segment index to start at, as well as consolidated analytics labels).
*
* @return `YES` if a playback context can be resolved, in which case the context block is called. If no context can
* be resolved, the method returns `NO` and the context block is not called.
*
* @return The method might return `nil` if no protocol / quality combination is found. Resource lookup is performed so
* that a matching streaming method is found first, then a matching stream type, and finally a quality.
* @discussion Resource lookup is performed in the order of the parameters (streaming method first, quality last).
*/
- (nullable SRGRequest *)resourceWithPreferredStreamingMethod:(SRGStreamingMethod)streamingMethod
streamType:(SRGStreamType)streamType
quality:(SRGQuality)quality
startBitRate:(NSInteger)startBitRate
completionBlock:(SRGResourceCompletionBlock)completionBlock;
- (BOOL)playbackContextWithPreferredStreamingMethod:(SRGStreamingMethod)streamingMethod
streamType:(SRGStreamType)streamType
quality:(SRGQuality)quality
DRM:(BOOL)DRM
startBitRate:(NSInteger)startBitRate
contextBlock:(NS_NOESCAPE SRGPlaybackContextBlock)contextBlock;

@end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#import "SRGMediaComposition+SRGAnalytics_DataProvider.h"

#import "SRGAnalyticsMediaPlayerLogger.h"
#import "SRGResource+SRGAnalytics_DataProvider.h"
#import "SRGSegment+SRGAnalytics_DataProvider.h"

#import <libextobjc/libextobjc.h>
Expand Down Expand Up @@ -46,11 +47,12 @@ - (SRGAnalyticsStreamLabels *)analyticsLabelsForResource:(SRGResource *)resource
return labels;
}

- (SRGRequest *)resourceWithPreferredStreamingMethod:(SRGStreamingMethod)streamingMethod
streamType:(SRGStreamType)streamType
quality:(SRGQuality)quality
startBitRate:(NSInteger)startBitRate
completionBlock:(SRGResourceCompletionBlock)completionBlock
- (BOOL)playbackContextWithPreferredStreamingMethod:(SRGStreamingMethod)streamingMethod
streamType:(SRGStreamType)streamType
quality:(SRGQuality)quality
DRM:(BOOL)DRM
startBitRate:(NSInteger)startBitRate
contextBlock:(SRGPlaybackContextBlock)contextBlock
{
if (startBitRate < 0) {
startBitRate = 0;
Expand All @@ -67,8 +69,32 @@ - (SRGRequest *)resourceWithPreferredStreamingMethod:(SRGStreamingMethod)streami
resources = [chapter resourcesForStreamingMethod:chapter.recommendedStreamingMethod];
}

// Determine the stream type order to use (start with a default setup, overridden if a preferred type has been set),
// from the lowest to the highest priority.
NSSortDescriptor *URLSchemeSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@keypath(SRGResource.new, URL) ascending:NO comparator:^NSComparisonResult(NSURL * _Nonnull URL1, NSURL * _Nonnull URL2) {
// Only declare ordering for important URL schemes. For other schemes the initial order will be preserved
NSArray<NSString *> *orderedURLSchemes = @[@"http", @"https"];

NSUInteger index1 = [orderedURLSchemes indexOfObject:URL1.scheme];
NSUInteger index2 = [orderedURLSchemes indexOfObject:URL2.scheme];
if (index1 == index2) {
return NSOrderedSame;
}
// Unknown scheme < known scheme
else if (index1 == NSNotFound) {
return NSOrderedAscending;
}
// Known scheme > unknown scheme
else if (index2 == NSNotFound) {
return NSOrderedDescending;
}
else if (index1 < index2) {
return NSOrderedAscending;
}
else {
return NSOrderedDescending;
}
}];

// Determine the stream type order to use (start with a default setup, overridden if a preferred value has been set).
NSArray<NSNumber *> *orderedStreamTypes = @[@(SRGStreamTypeOnDemand), @(SRGStreamTypeLive), @(SRGStreamTypeDVR)];
if (streamType != SRGStreamTypeNone) {
orderedStreamTypes = [[orderedStreamTypes mtl_arrayByRemovingObject:@(streamType)] arrayByAddingObject:@(streamType)];
Expand All @@ -89,46 +115,55 @@ - (SRGRequest *)resourceWithPreferredStreamingMethod:(SRGStreamingMethod)streami
}
}];

NSSortDescriptor *URLSchemeSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@keypath(SRGResource.new, URL) ascending:NO comparator:^NSComparisonResult(NSURL * _Nonnull URL1, NSURL * _Nonnull URL2) {
// Only declare ordering for important URL schemes. For other schemes the initial order will be preserved
NSArray<NSString *> *orderedURLSchemes = @[@"http", @"https"];

NSUInteger index1 = [orderedURLSchemes indexOfObject:URL1.scheme];
NSUInteger index2 = [orderedURLSchemes indexOfObject:URL2.scheme];
// Determine the quality to use (start with a default setup, overridden if a preferred value has been set).
NSArray<NSNumber *> *orderedQualities = @[@(SRGQualitySD), @(SRGQualityHD), @(SRGQualityHQ)];
if (quality != SRGQualityNone) {
orderedQualities = [[orderedQualities mtl_arrayByRemovingObject:@(quality)] arrayByAddingObject:@(quality)];
}

NSSortDescriptor *qualitySortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@keypath(SRGResource.new, quality) ascending:NO comparator:^(NSNumber * _Nonnull quality1, NSNumber * _Nonnull quality2) {
// Don't simply compare enum values as integers since their order might change.
NSUInteger index1 = [orderedQualities indexOfObject:quality1];
NSUInteger index2 = [orderedQualities indexOfObject:quality2];
if (index1 == index2) {
return NSOrderedSame;
}
// Unknown scheme < known scheme
else if (index1 == NSNotFound) {
return NSOrderedAscending;
}
// Known scheme > unknown scheme
else if (index2 == NSNotFound) {
return NSOrderedDescending;
}
else if (index1 < index2) {
return NSOrderedAscending;
}
else {
return NSOrderedDescending;
}
}];
resources = [resources sortedArrayUsingDescriptors:@[streamTypeSortDescriptor, URLSchemeSortDescriptor]];

// Resources are initially ordered by quality (see `-resourcesForStreamingMethod:` documentation), and this order
// is kept stable by the stream type sort descriptor above. We therefore attempt to find a proper match for the specified
// quality, otherwise we just use the first resource available.
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K == %@", @keypath(SRGResource.new, quality), @(quality)];
SRGResource *resource = [resources filteredArrayUsingPredicate:predicate].firstObject ?: resources.firstObject;
NSMutableArray<NSSortDescriptor *> *sortDescriptors = [@[URLSchemeSortDescriptor, streamTypeSortDescriptor, qualitySortDescriptor] mutableCopy];

// Favor DRM resources if desired, otherwise preserve the original order
if (DRM) {
NSSortDescriptor *DRMSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@keypath(SRGResource.new, srg_requiresDRM) ascending:! DRM comparator:^NSComparisonResult(NSNumber * _Nonnull requiresDRM1, NSNumber * _Nonnull requiresDRM2) {
if (requiresDRM1.boolValue == requiresDRM2.boolValue) {
return NSOrderedSame;
}
else if (requiresDRM2.boolValue) {
return NSOrderedAscending;
}
else {
return NSOrderedDescending;
}
}];
[sortDescriptors addObject:DRMSortDescriptor];
}
resources = [resources sortedArrayUsingDescriptors:sortDescriptors];

SRGResource *resource = resources.firstObject;
if (! resource) {
SRGAnalyticsMediaPlayerLogError(@"mediaplayer", @"No valid resource could be retrieved");
return nil;
return NO;
}

// Use the preferrred start bit rate is set. Currrently only supported by Akamai via a __b__ parameter (the actual
// bitrate will be rounded to the nearest available quality)
// Use the preferrred start bit rate is set. Currrently only supported for HLS streams by Akamai, via a __b__ parameter
// (the actual bitrate will be rounded to the nearest available quality)
NSURL *URL = resource.URL;
if (startBitRate != 0 && [URL.host containsString:@"akamai"]) {
if (startBitRate != 0 && [URL.host containsString:@"akamai"] && [URL.path.pathExtension isEqualToString:@"m3u8"]) {
NSURLComponents *URLComponents = [NSURLComponents componentsWithURL:URL resolvingAgainstBaseURL:NO];

NSMutableArray<NSURLQueryItem *> *queryItems = [URLComponents.queryItems mutableCopy] ?: [NSMutableArray array];
Expand All @@ -138,17 +173,10 @@ - (SRGRequest *)resourceWithPreferredStreamingMethod:(SRGStreamingMethod)streami
URL = URLComponents.URL;
}

SRGRequest *request = [SRGDataProvider tokenizeURL:URL withCompletionBlock:^(NSURL * _Nullable URL, NSError * _Nullable error) {
// Bypass token server response, if an error occurred. We don't want to block the media player here
if (error) {
URL = resource.URL;
}

SRGAnalyticsStreamLabels *labels = [self analyticsLabelsForResource:resource];
NSInteger index = [chapter.segments indexOfObject:self.mainSegment];
completionBlock(URL, resource, chapter.segments, index, labels, nil);
}];
return request;
SRGAnalyticsStreamLabels *labels = [self analyticsLabelsForResource:resource];
NSInteger index = [chapter.segments indexOfObject:self.mainSegment];
contextBlock(URL, resource, chapter.segments, index, labels);
return YES;
}

@end
Loading

0 comments on commit decb749

Please sign in to comment.