-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
16 changed files
with
424 additions
and
268 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
github "SRGSSR/SRGMediaPlayer-iOS" "2.2.1" | ||
github "SRGSSR/srgdataprovider-ios" "5.5.2" | ||
github "SRGSSR/SRGMediaPlayer-iOS" "2.2.2" | ||
github "SRGSSR/srgdataprovider-ios" "5.6" | ||
github "SRGSSR/tagcommander-ios" "4.1.5_4.1.3" | ||
github "comScore/ComScore-iOS-SDK" "92f34897cd7659d56bb5a3e9e85b808cf3758bda" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
49 changes: 49 additions & 0 deletions
49
Framework_DataProvider/Sources/SRGMediaComposition+SRGAnalytics_DataProvider.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// | ||
// Copyright (c) SRG SSR. All rights reserved. | ||
// | ||
// License information is available from the LICENSE file. | ||
// | ||
|
||
#import <SRGAnalytics/SRGAnalytics.h> | ||
#import <SRGMediaPlayer/SRGMediaPlayer.h> | ||
#import <SRGDataProvider/SRGDataProvider.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); | ||
|
||
@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. | ||
* | ||
* @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 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. | ||
* | ||
* @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. | ||
*/ | ||
- (nullable SRGRequest *)resourceWithPreferredStreamingMethod:(SRGStreamingMethod)streamingMethod | ||
streamType:(SRGStreamType)streamType | ||
quality:(SRGQuality)quality | ||
startBitRate:(NSInteger)startBitRate | ||
completionBlock:(SRGResourceCompletionBlock)completionBlock; | ||
|
||
@end | ||
|
||
NS_ASSUME_NONNULL_END |
154 changes: 154 additions & 0 deletions
154
Framework_DataProvider/Sources/SRGMediaComposition+SRGAnalytics_DataProvider.m
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
// | ||
// Copyright (c) SRG SSR. All rights reserved. | ||
// | ||
// License information is available from the LICENSE file. | ||
// | ||
|
||
#import "SRGMediaComposition+SRGAnalytics_DataProvider.h" | ||
|
||
#import "SRGAnalyticsMediaPlayerLogger.h" | ||
#import "SRGSegment+SRGAnalytics_DataProvider.h" | ||
|
||
#import <libextobjc/libextobjc.h> | ||
|
||
@implementation SRGMediaComposition (SRGAnalytics_DataProvider) | ||
|
||
- (SRGAnalyticsStreamLabels *)analyticsLabelsForResource:(SRGResource *)resource | ||
{ | ||
NSAssert([self.mainChapter.resources containsObject:resource], @"The specified resource must be associated with the current context"); | ||
|
||
SRGAnalyticsStreamLabels *labels = [[SRGAnalyticsStreamLabels alloc] init]; | ||
|
||
NSMutableDictionary<NSString *, NSString *> *customInfo = [NSMutableDictionary dictionary]; | ||
if (self.analyticsLabels) { | ||
[customInfo addEntriesFromDictionary:self.analyticsLabels]; | ||
} | ||
if (self.mainChapter.analyticsLabels) { | ||
[customInfo addEntriesFromDictionary:self.mainChapter.analyticsLabels]; | ||
} | ||
if (resource.analyticsLabels) { | ||
[customInfo addEntriesFromDictionary:resource.analyticsLabels]; | ||
} | ||
labels.customInfo = [customInfo copy]; | ||
|
||
NSMutableDictionary<NSString *, NSString *> *comScoreCustomInfo = [NSMutableDictionary dictionary]; | ||
if (self.comScoreAnalyticsLabels) { | ||
[comScoreCustomInfo addEntriesFromDictionary:self.comScoreAnalyticsLabels]; | ||
} | ||
if (self.mainChapter.comScoreAnalyticsLabels) { | ||
[comScoreCustomInfo addEntriesFromDictionary:self.mainChapter.comScoreAnalyticsLabels]; | ||
} | ||
if (resource.comScoreAnalyticsLabels) { | ||
[comScoreCustomInfo addEntriesFromDictionary:resource.comScoreAnalyticsLabels]; | ||
} | ||
labels.comScoreCustomInfo = [comScoreCustomInfo copy]; | ||
|
||
return labels; | ||
} | ||
|
||
- (SRGRequest *)resourceWithPreferredStreamingMethod:(SRGStreamingMethod)streamingMethod | ||
streamType:(SRGStreamType)streamType | ||
quality:(SRGQuality)quality | ||
startBitRate:(NSInteger)startBitRate | ||
completionBlock:(SRGResourceCompletionBlock)completionBlock | ||
{ | ||
if (startBitRate < 0) { | ||
startBitRate = 0; | ||
} | ||
|
||
SRGChapter *chapter = self.mainChapter; | ||
|
||
if (streamingMethod == SRGStreamingMethodNone) { | ||
streamingMethod = chapter.recommendedStreamingMethod; | ||
} | ||
|
||
NSArray<SRGResource *> *resources = [chapter resourcesForStreamingMethod:streamingMethod]; | ||
if (resources.count == 0) { | ||
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. | ||
NSArray<NSNumber *> *orderedStreamTypes = @[@(SRGStreamTypeOnDemand), @(SRGStreamTypeLive), @(SRGStreamTypeDVR)]; | ||
if (streamType != SRGStreamTypeNone) { | ||
orderedStreamTypes = [[orderedStreamTypes mtl_arrayByRemovingObject:@(streamType)] arrayByAddingObject:@(streamType)]; | ||
} | ||
|
||
NSSortDescriptor *streamTypeSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@keypath(SRGResource.new, streamType) ascending:NO comparator:^(NSNumber * _Nonnull streamType1, NSNumber * _Nonnull streamType2) { | ||
// Don't simply compare enum values as integers since their order might change. | ||
NSUInteger index1 = [orderedStreamTypes indexOfObject:streamType1]; | ||
NSUInteger index2 = [orderedStreamTypes indexOfObject:streamType2]; | ||
if (index1 == index2) { | ||
return NSOrderedSame; | ||
} | ||
else if (index1 < index2) { | ||
return NSOrderedAscending; | ||
} | ||
else { | ||
return NSOrderedDescending; | ||
} | ||
}]; | ||
|
||
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; | ||
} | ||
}]; | ||
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; | ||
if (! resource) { | ||
SRGAnalyticsMediaPlayerLogError(@"mediaplayer", @"No valid resource could be retrieved"); | ||
return nil; | ||
} | ||
|
||
// 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) | ||
NSURL *URL = resource.URL; | ||
if (startBitRate != 0 && [URL.host containsString:@"akamai"]) { | ||
NSURLComponents *URLComponents = [NSURLComponents componentsWithURL:URL resolvingAgainstBaseURL:NO]; | ||
|
||
NSMutableArray<NSURLQueryItem *> *queryItems = [URLComponents.queryItems mutableCopy] ?: [NSMutableArray array]; | ||
[queryItems addObject:[NSURLQueryItem queryItemWithName:@"__b__" value:@(startBitRate).stringValue]]; | ||
URLComponents.queryItems = [queryItems copy]; | ||
|
||
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; | ||
} | ||
|
||
@end |
23 changes: 23 additions & 0 deletions
23
Framework_DataProvider/Sources/SRGMediaComposition+SRGAnalytics_DataProvider_Private.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// | ||
// Copyright (c) SRG SSR. All rights reserved. | ||
// | ||
// License information is available from the LICENSE file. | ||
// | ||
|
||
#import <SRGAnalytics/SRGAnalytics.h> | ||
#import <SRGDataProvider/SRGDataProvider.h> | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
|
||
@interface SRGMediaComposition (SRGAnalytics_DataProvider_Private) | ||
|
||
/** | ||
* Return the consolidated analytics stream labels associated for with the specified resource of the receiver. | ||
* | ||
* @discussion An exception is thrown in debug builds if the resource is not associated with the receiver. | ||
*/ | ||
- (SRGAnalyticsStreamLabels *)analyticsLabelsForResource:(SRGResource *)resource; | ||
|
||
@end | ||
|
||
NS_ASSUME_NONNULL_END |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.