From 1aaef5c514b73d16d5f293ca4dc2f53c21604ea0 Mon Sep 17 00:00:00 2001 From: Raffi Date: Tue, 17 Dec 2024 16:08:26 +0100 Subject: [PATCH 1/3] adjust player item reflection --- Code/Conviva/Source/Utilities/Utilities.swift | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Code/Conviva/Source/Utilities/Utilities.swift b/Code/Conviva/Source/Utilities/Utilities.swift index 9aa5b97..0e87e01 100644 --- a/Code/Conviva/Source/Utilities/Utilities.swift +++ b/Code/Conviva/Source/Utilities/Utilities.swift @@ -36,7 +36,10 @@ enum Utilities { extension THEOplayer { var currentItem: AVPlayerItem? { - ((Mirror(reflecting: self).descendant("theoplayer") as? NSObject).map {Mirror(reflecting: $0).superclassMirror?.descendant("mainContentPlayer", "avPlayer")} as? AVPlayer)?.currentItem + let basePlayer = (Mirror(reflecting: self).descendant("theoplayer") as? NSObject).map { Mirror(reflecting: $0).superclassMirror?.descendant("basePlayer") } as? AnyObject + let basePlayerMirror = basePlayer.map { Mirror(reflecting: $0) } + let avPlayer = basePlayerMirror?.superclassMirror?.superclassMirror?.descendant("player", "avPlayer") as? AVPlayer + return avPlayer?.currentItem } var renderedFramerate: Float? { From 9f62873d5c254909f5aa2afaa13544711f757975 Mon Sep 17 00:00:00 2001 From: Raffi Date: Tue, 17 Dec 2024 16:08:40 +0100 Subject: [PATCH 2/3] post bitrate change notification --- .../AppEventConvivaReporter.swift | 22 ++++++++++++++----- .../Events/Observers/AppEventForwarder.swift | 19 +++++++++++++++- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/Code/Conviva/Source/Events/ConvivaReporters/AppEventConvivaReporter.swift b/Code/Conviva/Source/Events/ConvivaReporters/AppEventConvivaReporter.swift index e0a48e3..3cb49bc 100644 --- a/Code/Conviva/Source/Events/ConvivaReporters/AppEventConvivaReporter.swift +++ b/Code/Conviva/Source/Events/ConvivaReporters/AppEventConvivaReporter.swift @@ -21,15 +21,25 @@ struct AppEventConvivaReporter: AppEventProcessor { func appGotNewAccessLogEntry(event: AVPlayerItemAccessLogEvent, isPlayingAd: Bool) { let endpoint = isPlayingAd ? self.adAnalytics : self.videoAnalytics - - if event.indicatedBitrate >= 0 { - let bitrateValue = NSNumber(value: event.indicatedBitrate / 1000) - endpoint.reportPlaybackMetric(CIS_SSDK_PLAYBACK_METRIC_BITRATE, value: bitrateValue) - self.storage.storeKeyValuePair(key: CIS_SSDK_PLAYBACK_METRIC_BITRATE, value: bitrateValue) - } + + self.handleBitrateChange(bitrate: event.indicatedBitrate, endpoint: endpoint) if event.numberOfDroppedVideoFrames >= 0 { endpoint.reportPlaybackMetric(CIS_SSDK_PLAYBACK_METRIC_DROPPED_FRAMES_TOTAL, value: NSNumber(value: event.numberOfDroppedVideoFrames)) } } + + func appGotBitrateChangeEvent(bitrate: Double, isPlayingAd: Bool) { + let endpoint = isPlayingAd ? self.adAnalytics : self.videoAnalytics + self.handleBitrateChange(bitrate: bitrate, endpoint: endpoint) + } + + private func handleBitrateChange(bitrate: Double, endpoint: CISStreamAnalyticsProtocol) { + guard bitrate >= 0 else { return } + + let bitrateValue = NSNumber(value: bitrate / 1000) + + endpoint.reportPlaybackMetric(CIS_SSDK_PLAYBACK_METRIC_BITRATE, value: bitrateValue) + self.storage.storeKeyValuePair(key: CIS_SSDK_PLAYBACK_METRIC_BITRATE, value: bitrateValue) + } } diff --git a/Code/Conviva/Source/Events/Observers/AppEventForwarder.swift b/Code/Conviva/Source/Events/Observers/AppEventForwarder.swift index 189a0a5..890579b 100644 --- a/Code/Conviva/Source/Events/Observers/AppEventForwarder.swift +++ b/Code/Conviva/Source/Events/Observers/AppEventForwarder.swift @@ -13,10 +13,11 @@ fileprivate let didEnterBackground = UIApplication.didEnterBackgroundNotificatio // Both `AVPlayerItem.newAccessLogEntryNotification` and `Notification.Name.AVPlayerItemNewAccessLogEntry` are mapped to `Notification.Name("AVPlayerItemNewAccessLogEntry")`, hence we use that. // Once we drop support for older versions (below Xcode 15 and Swift 5.9) we can switch from `Notification.Name("AVPlayerItemNewAccessLogEntry")` to `AVPlayerItem.newAccessLogEntryNotification`. fileprivate let newAccessLogEntry = Notification.Name("AVPlayerItemNewAccessLogEntry") +fileprivate let bitrateChangeEvent = Notification.Name("THEOliveBitrateChangeEvent") class AppEventForwarder { let center = NotificationCenter.default - let foregroundObserver, backgroundObserver, accessLogObserver: Any + let foregroundObserver, backgroundObserver, accessLogObserver, bitrateChangeObserver: Any let player: THEOplayer init(player: THEOplayer, eventProcessor: AppEventProcessor) { @@ -46,12 +47,27 @@ class AppEventForwarder { eventProcessor.appGotNewAccessLogEntry(event: event, isPlayingAd: player.ads.playing) } ) + // Temporary workaround for THEOlive bitrate change events + // TODO: Refactor this with active quality switch event dispatched from THEOplayer. This needs a videoTrack property exposed on THEOlive SDK which is currently missing. + // NOTE: accessLogObserver can also be removed once the active quality switch event is implemented. + bitrateChangeObserver = center.addObserver( + forName: bitrateChangeEvent, + object: .none, + queue: .none, + using: { notification in + guard let userInfo = notification.userInfo else { return } + guard let bitrate = userInfo["bitrate"] as? Double else { return } + + eventProcessor.appGotBitrateChangeEvent(bitrate: bitrate, isPlayingAd: player.ads.playing) + } + ) } deinit { center.removeObserver(foregroundObserver, name: willEnterForeground, object: nil) center.removeObserver(backgroundObserver, name: didEnterBackground, object: nil) center.removeObserver(accessLogObserver, name: newAccessLogEntry, object: nil) + center.removeObserver(accessLogObserver, name: bitrateChangeEvent, object: nil) } } @@ -59,4 +75,5 @@ protocol AppEventProcessor { func appWillEnterForeground(notification: Notification) func appDidEnterBackground(notification: Notification) func appGotNewAccessLogEntry(event: AVPlayerItemAccessLogEvent, isPlayingAd: Bool) + func appGotBitrateChangeEvent(bitrate: Double, isPlayingAd: Bool) } From f3ba4539ca5b50ad4dfd42d4a0c547dac71517c2 Mon Sep 17 00:00:00 2001 From: Raffi Date: Tue, 17 Dec 2024 16:08:54 +0100 Subject: [PATCH 3/3] add changelog --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e88634..f9c6cbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Added + +- Conviva + - Added compatibility for reporting playback bitrate metrics with THEOlive sources. + +### Fixed + +- Conviva + - Fixed an issue where the playback bitrate metrics were not reported. + ## [8.0.1.1] - 2024-09-18 ### Fixed