From b70be46655f8c09b0df91fd0d12157c63ecc11b6 Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Thu, 8 Jan 2026 18:35:16 +0100 Subject: [PATCH 1/4] Process encodingType for HLS by storing the calculated type before the sourcechange and for HESP after the sourceChange using a pending flag. --- .../ConvivaHandlers/PlayerHandler.swift | 32 +++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/Code/Conviva/Source/Base/Events/ConvivaHandlers/PlayerHandler.swift b/Code/Conviva/Source/Base/Events/ConvivaHandlers/PlayerHandler.swift index 8b4b7b0..1359be6 100644 --- a/Code/Conviva/Source/Base/Events/ConvivaHandlers/PlayerHandler.swift +++ b/Code/Conviva/Source/Base/Events/ConvivaHandlers/PlayerHandler.swift @@ -35,6 +35,9 @@ class PlayerHandler { private weak var endpoints: ConvivaEndpoints? private weak var storage: ConvivaStorage? private var playerState: PlayerState = .CONVIVA_UNKNOWN + + private var unreportedEncodingType: String? + private var encodingTypeIsPending = false init(endpoints: ConvivaEndpoints, storage: ConvivaStorage, convivaMetadata: [String:Any]) { self.endpoints = endpoints @@ -189,23 +192,29 @@ class PlayerHandler { func currentSourceChange(event: CurrentSourceChangeEvent) { log("handling currentSourceChange") guard let sourceType = event.currentSource?.type else { + log("not processing currentSourceChange") return } - var encodingType: String? + self.unreportedEncodingType = nil switch sourceType.lowercased() { case "application/vnd.theo.hesp+json": - encodingType = "HESP" + self.unreportedEncodingType = "HESP" case "application/x-mpegurl", "application/vnd.apple.mpegurl", "video/mp2t": - encodingType = "HLS" + self.unreportedEncodingType = "HLS" default: - encodingType = nil + self.unreportedEncodingType = nil } + log("self.unreportedEncodingType updated to \(self.unreportedEncodingType ?? "nil")") - if self.storage?.metadataEntryForKey(ENCODING_TYPE) == nil, - let encodingType = encodingType { + if self.encodingTypeIsPending, + let encodingType = self.storage?.metadataEntryForKey(ENCODING_TYPE) as? String ?? self.unreportedEncodingType { + // report the pending encodingType and reset the pending state self.setContentInfo([ENCODING_TYPE:encodingType]) + self.unreportedEncodingType = nil + self.encodingTypeIsPending = false + log("unreportedEncodingType was reset to nil after processing pending encodingtype") } } @@ -251,6 +260,17 @@ class PlayerHandler { let adDescriptionMetadata: [String: Any] = collectAdDescriptionMetadata(from: convivaSessionSource.description) metadata.merge(adDescriptionMetadata) { (_, new) in new } + + // Do not override `encoding_type` value if already set by the customer. + if let encodingType = self.storage?.metadataEntryForKey(ENCODING_TYPE) as? String ?? self.unreportedEncodingType { + log("processing encodingType based on unreportedEncodingType \(self.unreportedEncodingType ?? "nil")") + metadata[ENCODING_TYPE] = encodingType + self.unreportedEncodingType = nil + log("reset unreportedEncodingType to nil after processing it") + } else { + self.encodingTypeIsPending = true + log("mark encodingType as pending") + } self.setContentInfo(metadata) } From b823397c09b8c070978b9f84675b8505cf35ddbb Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Fri, 9 Jan 2026 11:42:58 +0100 Subject: [PATCH 2/4] improve logging --- .../Source/Base/Events/ConvivaHandlers/PlayerHandler.swift | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Code/Conviva/Source/Base/Events/ConvivaHandlers/PlayerHandler.swift b/Code/Conviva/Source/Base/Events/ConvivaHandlers/PlayerHandler.swift index 1359be6..fa43e11 100644 --- a/Code/Conviva/Source/Base/Events/ConvivaHandlers/PlayerHandler.swift +++ b/Code/Conviva/Source/Base/Events/ConvivaHandlers/PlayerHandler.swift @@ -206,7 +206,6 @@ class PlayerHandler { default: self.unreportedEncodingType = nil } - log("self.unreportedEncodingType updated to \(self.unreportedEncodingType ?? "nil")") if self.encodingTypeIsPending, let encodingType = self.storage?.metadataEntryForKey(ENCODING_TYPE) as? String ?? self.unreportedEncodingType { @@ -214,7 +213,7 @@ class PlayerHandler { self.setContentInfo([ENCODING_TYPE:encodingType]) self.unreportedEncodingType = nil self.encodingTypeIsPending = false - log("unreportedEncodingType was reset to nil after processing pending encodingtype") + log("unreportedEncodingType reset after processing pending encodingtype") } } @@ -263,10 +262,10 @@ class PlayerHandler { // Do not override `encoding_type` value if already set by the customer. if let encodingType = self.storage?.metadataEntryForKey(ENCODING_TYPE) as? String ?? self.unreportedEncodingType { - log("processing encodingType based on unreportedEncodingType \(self.unreportedEncodingType ?? "nil")") + log("reporting encodingType \(self.unreportedEncodingType ?? "nil")") metadata[ENCODING_TYPE] = encodingType self.unreportedEncodingType = nil - log("reset unreportedEncodingType to nil after processing it") + log("unreportedEncodingType reset") } else { self.encodingTypeIsPending = true log("mark encodingType as pending") From c284e6d8e12034eb704cc4455277b96785fa348b Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Fri, 9 Jan 2026 12:30:34 +0100 Subject: [PATCH 3/4] Add changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 67eb1a9..4a86618 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Conviva - Fixed an issue where the initial metadata passed to the convivaConnector was not persistent across Conviva sessions. - Fixed an issue where the session's assetName was not configurable by setContentInfo, which has higher precedence than source.metadata.title. + - Fixed an issue with the encodingType, where sometimes the encodingType of the previous session was reported ## [10.7.0] - 2025-12-18 From 33c5142bda7b7ac31a6985720ca86bbb69eceff7 Mon Sep 17 00:00:00 2001 From: William Van Haevre Date: Mon, 12 Jan 2026 15:22:51 +0100 Subject: [PATCH 4/4] Add comments to explain encodingType reporting flows for HLS and HESP based streams --- .../ConvivaHandlers/PlayerHandler.swift | 38 ++++++++++++------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/Code/Conviva/Source/Base/Events/ConvivaHandlers/PlayerHandler.swift b/Code/Conviva/Source/Base/Events/ConvivaHandlers/PlayerHandler.swift index fa43e11..2518ca5 100644 --- a/Code/Conviva/Source/Base/Events/ConvivaHandlers/PlayerHandler.swift +++ b/Code/Conviva/Source/Base/Events/ConvivaHandlers/PlayerHandler.swift @@ -195,25 +195,32 @@ class PlayerHandler { log("not processing currentSourceChange") return } - self.unreportedEncodingType = nil + + /* EncodingType reporting: The currentSourceChange event is used to extract the encoding type of the internally selected source. For HLS, this event is dispatched right before the sourceChange event. For HESP sources, it is dispatched after the play event, when a valid endpoint has been selected.*/ + + var calculatedEncodingType: String? = nil switch sourceType.lowercased() { case "application/vnd.theo.hesp+json": - self.unreportedEncodingType = "HESP" + calculatedEncodingType = "HESP" case "application/x-mpegurl", "application/vnd.apple.mpegurl", "video/mp2t": - self.unreportedEncodingType = "HLS" + calculatedEncodingType = "HLS" default: - self.unreportedEncodingType = nil + calculatedEncodingType = nil } - if self.encodingTypeIsPending, - let encodingType = self.storage?.metadataEntryForKey(ENCODING_TYPE) as? String ?? self.unreportedEncodingType { - // report the pending encodingType and reset the pending state - self.setContentInfo([ENCODING_TYPE:encodingType]) - self.unreportedEncodingType = nil - self.encodingTypeIsPending = false - log("unreportedEncodingType reset after processing pending encodingtype") + if let encodingType = self.storage?.metadataEntryForKey(ENCODING_TYPE) as? String ?? calculatedEncodingType { + /* For HESP sources the encodingType is not available at session startup (play event) and encodingType will have been marked as pending. Once the currentSourceChange event is dispatched, this mark indicates the calculated encodingType can be pushed immediately to conviva and the mark can be reset. */ + if self.encodingTypeIsPending { + self.setContentInfo([ENCODING_TYPE:encodingType]) + self.unreportedEncodingType = nil + self.encodingTypeIsPending = false + } + /* For HLS sources we cache the encoding type till the play event (Conviva session creation), at which the cached value will be pushed to conviva and the caching is reset to prevent further reporting. */ + else { + self.unreportedEncodingType = encodingType + } } } @@ -260,15 +267,18 @@ class PlayerHandler { let adDescriptionMetadata: [String: Any] = collectAdDescriptionMetadata(from: convivaSessionSource.description) metadata.merge(adDescriptionMetadata) { (_, new) in new } - // Do not override `encoding_type` value if already set by the customer. + /* EncodingType reporting: + 1. A customer set encodingType always has precedence over the calculated encodingtype + 2. For HLS sources (unreportedEncodingType is set on earlier currentSourceChange event) we can now report the encodingType. + 3. For HESP sources (unreportedEncodingType is still nil) we mark the encodingType as pending, because the currentSourceChange event will be dispatched after the play event). + */ if let encodingType = self.storage?.metadataEntryForKey(ENCODING_TYPE) as? String ?? self.unreportedEncodingType { log("reporting encodingType \(self.unreportedEncodingType ?? "nil")") metadata[ENCODING_TYPE] = encodingType self.unreportedEncodingType = nil - log("unreportedEncodingType reset") } else { self.encodingTypeIsPending = true - log("mark encodingType as pending") + log("marked encodingType as pending") } self.setContentInfo(metadata)