react-native-theoplayer 11.2.1 → 11.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/android/build.gradle +2 -2
- package/android/src/main/java/com/theoplayer/PlayerConfigAdapter.kt +30 -0
- package/android/src/main/java/com/theoplayer/abr/ABRConfigurationAdapter.kt +21 -0
- package/android/src/main/java/com/theoplayer/source/SourceAdapter.kt +38 -1
- package/android/src/main/java/com/theoplayer/theolive/EndpointAdapter.kt +4 -0
- package/android/src/main/java/com/theoplayer/theolive/THEOliveEventAdapter.kt +2 -0
- package/android/src/main/java/com/theoplayer/track/TrackListAdapter.kt +2 -0
- package/ios/THEOplayerRCTMainEventHandler.swift +6 -0
- package/ios/THEOplayerRCTSourceDescriptionBuilder.swift +31 -6
- package/ios/THEOplayerRCTTrackMetadataAggregator.swift +3 -0
- package/ios/THEOplayerRCTView.swift +3 -0
- package/ios/cmcd/THEOplayerRCTView+CmcdConfig.swift +36 -0
- package/ios/theolive/THEOplayerRCTTHEOliveEventAdapter.swift +12 -0
- package/lib/commonjs/api/barrel.js +36 -25
- package/lib/commonjs/api/barrel.js.map +1 -1
- package/lib/commonjs/api/cmcd/CmcdConfiguration.js +67 -0
- package/lib/commonjs/api/cmcd/CmcdConfiguration.js.map +1 -0
- package/lib/commonjs/api/cmcd/barrel.js.map +1 -0
- package/lib/commonjs/api/source/barrel.js +5 -16
- package/lib/commonjs/api/source/barrel.js.map +1 -1
- package/lib/commonjs/api/track/TextTrack.js.map +1 -1
- package/lib/commonjs/internal/adapter/THEOplayerWebAdapter.js +13 -4
- package/lib/commonjs/internal/adapter/THEOplayerWebAdapter.js.map +1 -1
- package/lib/commonjs/internal/adapter/web/TrackUtils.js +2 -0
- package/lib/commonjs/internal/adapter/web/TrackUtils.js.map +1 -1
- package/lib/commonjs/manifest.json +1 -1
- package/lib/module/api/barrel.js +1 -0
- package/lib/module/api/barrel.js.map +1 -1
- package/lib/module/api/cmcd/CmcdConfiguration.js +67 -0
- package/lib/module/api/cmcd/CmcdConfiguration.js.map +1 -0
- package/lib/module/api/cmcd/barrel.js.map +1 -0
- package/lib/module/api/source/barrel.js +0 -1
- package/lib/module/api/source/barrel.js.map +1 -1
- package/lib/module/api/track/TextTrack.js.map +1 -1
- package/lib/module/internal/adapter/THEOplayerWebAdapter.js +13 -4
- package/lib/module/internal/adapter/THEOplayerWebAdapter.js.map +1 -1
- package/lib/module/internal/adapter/web/TrackUtils.js +2 -0
- package/lib/module/internal/adapter/web/TrackUtils.js.map +1 -1
- package/lib/module/manifest.json +1 -1
- package/lib/typescript/api/abr/ABRConfiguration.d.ts +8 -5
- package/lib/typescript/api/abr/ABRConfiguration.d.ts.map +1 -1
- package/lib/typescript/api/barrel.d.ts +1 -0
- package/lib/typescript/api/barrel.d.ts.map +1 -1
- package/lib/typescript/api/cmcd/CmcdConfiguration.d.ts +166 -0
- package/lib/typescript/api/cmcd/CmcdConfiguration.d.ts.map +1 -0
- package/lib/typescript/api/cmcd/barrel.d.ts.map +1 -0
- package/lib/typescript/api/config/PlayerConfiguration.d.ts +10 -0
- package/lib/typescript/api/config/PlayerConfiguration.d.ts.map +1 -1
- package/lib/typescript/api/source/SourceDescription.d.ts +2 -2
- package/lib/typescript/api/source/SourceDescription.d.ts.map +1 -1
- package/lib/typescript/api/source/barrel.d.ts +0 -1
- package/lib/typescript/api/source/barrel.d.ts.map +1 -1
- package/lib/typescript/api/theolive/TheoLiveDistribution.d.ts +1 -0
- package/lib/typescript/api/theolive/TheoLiveDistribution.d.ts.map +1 -1
- package/lib/typescript/api/theolive/TheoLiveEndpoint.d.ts +38 -1
- package/lib/typescript/api/theolive/TheoLiveEndpoint.d.ts.map +1 -1
- package/lib/typescript/api/track/TextTrack.d.ts +4 -0
- package/lib/typescript/api/track/TextTrack.d.ts.map +1 -1
- package/lib/typescript/internal/adapter/THEOplayerWebAdapter.d.ts.map +1 -1
- package/lib/typescript/internal/adapter/web/TrackUtils.d.ts.map +1 -1
- package/package.json +1 -1
- package/react-native-theoplayer.podspec +1 -1
- package/src/api/abr/ABRConfiguration.ts +8 -5
- package/src/api/barrel.ts +1 -0
- package/src/api/cmcd/CmcdConfiguration.ts +175 -0
- package/src/api/config/PlayerConfiguration.ts +11 -0
- package/src/api/source/SourceDescription.ts +2 -2
- package/src/api/source/barrel.ts +0 -1
- package/src/api/theolive/TheoLiveDistribution.ts +1 -0
- package/src/api/theolive/TheoLiveEndpoint.ts +45 -1
- package/src/api/track/TextTrack.ts +5 -0
- package/src/internal/adapter/THEOplayerWebAdapter.ts +9 -4
- package/src/internal/adapter/web/TrackUtils.ts +2 -1
- package/src/manifest.json +1 -1
- package/lib/commonjs/api/source/cmcd/CmcdConfiguration.js +0 -27
- package/lib/commonjs/api/source/cmcd/CmcdConfiguration.js.map +0 -1
- package/lib/commonjs/api/source/cmcd/barrel.js.map +0 -1
- package/lib/module/api/source/cmcd/CmcdConfiguration.js +0 -24
- package/lib/module/api/source/cmcd/CmcdConfiguration.js.map +0 -1
- package/lib/module/api/source/cmcd/barrel.js.map +0 -1
- package/lib/typescript/api/source/cmcd/CmcdConfiguration.d.ts +0 -83
- package/lib/typescript/api/source/cmcd/CmcdConfiguration.d.ts.map +0 -1
- package/lib/typescript/api/source/cmcd/barrel.d.ts.map +0 -1
- package/src/api/source/cmcd/CmcdConfiguration.ts +0 -88
- /package/lib/commonjs/api/{source/cmcd → cmcd}/barrel.js +0 -0
- /package/lib/module/api/{source/cmcd → cmcd}/barrel.js +0 -0
- /package/lib/typescript/api/{source/cmcd → cmcd}/barrel.d.ts +0 -0
- /package/src/api/{source/cmcd → cmcd}/barrel.ts +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,33 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.1.0/)
|
|
6
6
|
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [11.4.0] - 26-07-06
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Fixed an issue on iOS where the `volumeChange` listener was not correctly removed on player desctruction.
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- Added `externalId` property to `TheoLiveDistribution` on Android and iOS.
|
|
19
|
+
- Added `hlsMpegTsSrc` and `daiAssetKey` properties to `TheoLiveEndpoint` on Android and iOS.
|
|
20
|
+
- Added `targetLatency` property to `TheoLiveEndpoint` on Android.
|
|
21
|
+
- Added V3 discovery response properties (`src`, `srcType`, `provider`, `distribution`) to `TheoLiveEndpoint` on Web.
|
|
22
|
+
|
|
23
|
+
## [11.3.0] - 26-06-18
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
|
|
27
|
+
- Added Android support for `ABRConfiguration.preferredMaximumResolution`, mirroring the existing iOS behaviour. Set to `(0,0)` to remove the cap.
|
|
28
|
+
- Added basic support for CMCD event mode reporting of DRM and ad events.
|
|
29
|
+
- Added bridging of the `hlsDateRange` property from `PlayerConfiguration` to Android's `THEOplayerConfig`.
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
|
|
33
|
+
- Fixed an issue on Android where `GoogleImaConfiguration.sessionId` was not properly passed.
|
|
34
|
+
|
|
8
35
|
## [11.2.1] - 26-06-09
|
|
9
36
|
|
|
10
37
|
### Fixed
|
package/android/build.gradle
CHANGED
|
@@ -126,8 +126,8 @@ repositories {
|
|
|
126
126
|
mavenLocal()
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
-
// The minimum supported THEOplayer version is 11.
|
|
130
|
-
def theoVersion = safeExtGet('THEOplayer_sdk', '[11.
|
|
129
|
+
// The minimum supported THEOplayer version is 11.5.0
|
|
130
|
+
def theoVersion = safeExtGet('THEOplayer_sdk', '[11.5.0, 12.0.0)')
|
|
131
131
|
def theoMediaSessionVersion = safeExtGet('THEOplayer_mediasession', '[11.0.0, 12.0.0)')
|
|
132
132
|
def theoAdsWrapperVersion = "11.0.0"
|
|
133
133
|
def coroutinesVersion = safeExtGet('coroutinesVersion', '1.10.2')
|
|
@@ -8,6 +8,8 @@ import com.theoplayer.android.api.THEOplayerConfig
|
|
|
8
8
|
import com.theoplayer.android.api.THEOplayerGlobal
|
|
9
9
|
import com.theoplayer.android.api.cast.CastStrategy
|
|
10
10
|
import com.theoplayer.android.api.cast.CastConfiguration
|
|
11
|
+
import com.theoplayer.android.api.cmcd.CMCDConfiguration
|
|
12
|
+
import com.theoplayer.android.api.cmcd.CMCDEndpointConfiguration
|
|
11
13
|
import com.theoplayer.android.api.pip.PipConfiguration
|
|
12
14
|
import com.theoplayer.android.api.player.NetworkConfiguration
|
|
13
15
|
import com.theoplayer.android.api.theolive.THEOLiveConfig
|
|
@@ -42,9 +44,15 @@ private const val PROP_THEOLIVE_CONFIG = "theoLive"
|
|
|
42
44
|
private const val PROP_THEOLIVE_EXTERNAL_SESSION_ID = "externalSessionId"
|
|
43
45
|
private const val PROP_THEOLIVE_ANALYTICS_DISABLED = "analyticsDisabled"
|
|
44
46
|
private const val PROP_THEOLIVE_DISCOVERY_URL = "discoveryUrl"
|
|
47
|
+
private const val PROP_HLS_DATERANGE = "hlsDateRange"
|
|
45
48
|
private const val PROP_MULTIMEDIA_TUNNELING_ENABLED = "tunnelingEnabled"
|
|
46
49
|
private const val PROP_DEBUG_LOGS_ENABLED = "debugLogsEnabled"
|
|
47
50
|
private const val PROP_SYSTEM_CAPTION_STYLE = "useSystemCaptionStyle"
|
|
51
|
+
private const val PROP_CMCD = "cmcd"
|
|
52
|
+
private const val PROP_CMCD_EXTERNAL_SESSION_ID = "externalSessionId"
|
|
53
|
+
private const val PROP_CMCD_USER_ID = "userId"
|
|
54
|
+
private const val PROP_CMCD_EVENT_ENDPOINTS = "eventEndpoints"
|
|
55
|
+
private const val PROP_CMCD_ENDPOINT_URL = "url"
|
|
48
56
|
|
|
49
57
|
|
|
50
58
|
class PlayerConfigAdapter(private val configProps: ReadableMap?) {
|
|
@@ -82,12 +90,18 @@ class PlayerConfigAdapter(private val configProps: ReadableMap?) {
|
|
|
82
90
|
pip(PipConfiguration.Builder().build())
|
|
83
91
|
// Opt-out for auto-integrations for now
|
|
84
92
|
autoIntegrations(false)
|
|
93
|
+
if (hasKey(PROP_HLS_DATERANGE)) {
|
|
94
|
+
hlsDateRange(getBoolean(PROP_HLS_DATERANGE))
|
|
95
|
+
}
|
|
85
96
|
if (hasKey(PROP_MULTIMEDIA_TUNNELING_ENABLED)) {
|
|
86
97
|
tunnelingEnabled(getBoolean(PROP_MULTIMEDIA_TUNNELING_ENABLED))
|
|
87
98
|
}
|
|
88
99
|
if (hasKey(PROP_SYSTEM_CAPTION_STYLE)) {
|
|
89
100
|
useSystemCaptionStyle(getBoolean(PROP_SYSTEM_CAPTION_STYLE))
|
|
90
101
|
}
|
|
102
|
+
if (hasKey(PROP_CMCD)) {
|
|
103
|
+
cmcd(cmcdConfig())
|
|
104
|
+
}
|
|
91
105
|
}
|
|
92
106
|
}.build()
|
|
93
107
|
}
|
|
@@ -241,6 +255,22 @@ class PlayerConfigAdapter(private val configProps: ReadableMap?) {
|
|
|
241
255
|
return MediaSessionConfigAdapter.fromProps(configProps?.getMap(PROP_MEDIA_CONTROL))
|
|
242
256
|
}
|
|
243
257
|
|
|
258
|
+
private fun cmcdConfig(): CMCDConfiguration {
|
|
259
|
+
val config = configProps?.getMap(PROP_CMCD)
|
|
260
|
+
val endpoints = config?.getArray(PROP_CMCD_EVENT_ENDPOINTS)?.let { arr ->
|
|
261
|
+
(0 until arr.size()).mapNotNull { i ->
|
|
262
|
+
arr.getMap(i)?.getString(PROP_CMCD_ENDPOINT_URL)?.let { url ->
|
|
263
|
+
CMCDEndpointConfiguration(url = url)
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return CMCDConfiguration(
|
|
268
|
+
externalSessionId = config?.getString(PROP_CMCD_EXTERNAL_SESSION_ID),
|
|
269
|
+
userId = config?.getString(PROP_CMCD_USER_ID),
|
|
270
|
+
eventEndpoints = endpoints
|
|
271
|
+
)
|
|
272
|
+
}
|
|
273
|
+
|
|
244
274
|
private fun theoLiveConfig (): THEOLiveConfig {
|
|
245
275
|
val config = configProps?.getMap(PROP_THEOLIVE_CONFIG)
|
|
246
276
|
return THEOLiveConfig.Builder(
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
package com.theoplayer.abr
|
|
2
2
|
|
|
3
|
+
import android.util.Size
|
|
3
4
|
import com.facebook.react.bridge.ReadableMap
|
|
4
5
|
import com.theoplayer.android.api.abr.AbrStrategyConfiguration
|
|
5
6
|
import com.theoplayer.android.api.abr.AbrStrategyMetadata
|
|
@@ -12,6 +13,9 @@ object ABRConfigurationAdapter {
|
|
|
12
13
|
private const val PROP_METADATA = "metadata"
|
|
13
14
|
private const val PROP_TYPE = "type"
|
|
14
15
|
private const val PROP_BITRATE = "bitrate"
|
|
16
|
+
private const val PROP_PREFERRED_MAXIMUM_RESOLUTION = "preferredMaximumResolution"
|
|
17
|
+
private const val PROP_WIDTH = "width"
|
|
18
|
+
private const val PROP_HEIGHT = "height"
|
|
15
19
|
|
|
16
20
|
fun applyABRConfigurationFromProps(player: Player?, abrProps: ReadableMap?) {
|
|
17
21
|
if (abrProps == null || player == null) {
|
|
@@ -20,6 +24,11 @@ object ABRConfigurationAdapter {
|
|
|
20
24
|
if (abrProps.hasKey(PROP_TARGET_BUFFER)) {
|
|
21
25
|
player.abr.targetBuffer = abrProps.getInt(PROP_TARGET_BUFFER)
|
|
22
26
|
}
|
|
27
|
+
// (0,0) is the documented sentinel for "no cap" and maps to a null Size on the native SDK.
|
|
28
|
+
val preferredMaximumResolutionProps = abrProps.getMap(PROP_PREFERRED_MAXIMUM_RESOLUTION)
|
|
29
|
+
if (preferredMaximumResolutionProps != null) {
|
|
30
|
+
player.abr.preferredMaximumResolution = preferredMaximumResolutionFromProps(preferredMaximumResolutionProps)
|
|
31
|
+
}
|
|
23
32
|
// Strategy can be either a string or an object
|
|
24
33
|
try {
|
|
25
34
|
val abrStrategyPropsString = abrProps.getString(PROP_STRATEGY)
|
|
@@ -50,6 +59,18 @@ object ABRConfigurationAdapter {
|
|
|
50
59
|
}
|
|
51
60
|
}
|
|
52
61
|
|
|
62
|
+
private fun preferredMaximumResolutionFromProps(props: ReadableMap?): Size? {
|
|
63
|
+
if (props == null || !props.hasKey(PROP_WIDTH) || !props.hasKey(PROP_HEIGHT)) {
|
|
64
|
+
return null
|
|
65
|
+
}
|
|
66
|
+
val width = props.getDouble(PROP_WIDTH).toInt()
|
|
67
|
+
val height = props.getDouble(PROP_HEIGHT).toInt()
|
|
68
|
+
if (width <= 0 || height <= 0) {
|
|
69
|
+
return null
|
|
70
|
+
}
|
|
71
|
+
return Size(width, height)
|
|
72
|
+
}
|
|
73
|
+
|
|
53
74
|
private fun abrMetadataFromProps(props: ReadableMap?): AbrStrategyMetadata? {
|
|
54
75
|
if (props == null) {
|
|
55
76
|
return null
|
|
@@ -20,6 +20,8 @@ import com.theoplayer.android.api.player.track.texttrack.TextTrackKind
|
|
|
20
20
|
import com.theoplayer.android.api.source.metadata.ChromecastMetadataImage
|
|
21
21
|
import com.theoplayer.BuildConfig
|
|
22
22
|
import com.theoplayer.android.api.ads.theoads.TheoAdsLayoutOverride
|
|
23
|
+
import com.theoplayer.android.api.cmcd.CMCDEndpointConfiguration
|
|
24
|
+
import com.theoplayer.android.api.cmcd.CMCDSourceConfiguration
|
|
23
25
|
import com.theoplayer.android.api.cmcd.CMCDTransmissionMode
|
|
24
26
|
import com.theoplayer.android.api.error.ErrorCode
|
|
25
27
|
import com.theoplayer.android.api.source.AdIntegration
|
|
@@ -94,6 +96,11 @@ private const val TYPE_MILLICAST = "millicast"
|
|
|
94
96
|
|
|
95
97
|
private const val PROP_CMCD = "cmcd"
|
|
96
98
|
private const val CMCD_TRANSMISSION_MODE = "transmissionMode"
|
|
99
|
+
private const val CMCD_SESSION_ID = "sessionID"
|
|
100
|
+
private const val CMCD_EXTERNAL_SESSION_ID = "externalSessionId"
|
|
101
|
+
private const val CMCD_USER_ID = "userId"
|
|
102
|
+
private const val CMCD_EVENT_ENDPOINTS = "eventEndpoints"
|
|
103
|
+
private const val CMCD_ENDPOINT_URL = "url"
|
|
97
104
|
|
|
98
105
|
class SourceAdapter {
|
|
99
106
|
private val gson = Gson()
|
|
@@ -175,6 +182,11 @@ class SourceAdapter {
|
|
|
175
182
|
if (metadataDescription != null) {
|
|
176
183
|
builder.metadata(metadataDescription)
|
|
177
184
|
}
|
|
185
|
+
if (jsonSourceObject.has(PROP_CMCD)) {
|
|
186
|
+
parseCmcdSourceConfiguration(jsonSourceObject.getJSONObject(PROP_CMCD))?.let {
|
|
187
|
+
builder.cmcd(it)
|
|
188
|
+
}
|
|
189
|
+
}
|
|
178
190
|
return builder.build()
|
|
179
191
|
} catch (e: JSONException) {
|
|
180
192
|
e.printStackTrace()
|
|
@@ -464,7 +476,10 @@ class SourceAdapter {
|
|
|
464
476
|
return BridgeUtils.fromJSONObjectToBridge(JSONObject(gson.toJson(typedSource)))
|
|
465
477
|
}
|
|
466
478
|
|
|
467
|
-
private fun parseCmcdTransmissionMode(cmcdConfiguration : JSONObject) : CMCDTransmissionMode {
|
|
479
|
+
private fun parseCmcdTransmissionMode(cmcdConfiguration : JSONObject) : CMCDTransmissionMode? {
|
|
480
|
+
if (!cmcdConfiguration.has(CMCD_TRANSMISSION_MODE)) {
|
|
481
|
+
return null
|
|
482
|
+
}
|
|
468
483
|
try {
|
|
469
484
|
val transmissionMode = cmcdConfiguration.optInt(CMCD_TRANSMISSION_MODE)
|
|
470
485
|
if (transmissionMode == CmcdTransmissionMode.QUERY_ARGUMENT.ordinal) {
|
|
@@ -476,4 +491,26 @@ class SourceAdapter {
|
|
|
476
491
|
return CMCDTransmissionMode.HTTP_HEADER
|
|
477
492
|
}
|
|
478
493
|
}
|
|
494
|
+
|
|
495
|
+
private fun parseCmcdSourceConfiguration(cmcdJson: JSONObject): CMCDSourceConfiguration? {
|
|
496
|
+
val sessionId = cmcdJson.optString(CMCD_SESSION_ID, null)
|
|
497
|
+
val externalSessionId = cmcdJson.optString(CMCD_EXTERNAL_SESSION_ID, null)
|
|
498
|
+
val userId = cmcdJson.optString(CMCD_USER_ID, null)
|
|
499
|
+
val endpoints = cmcdJson.optJSONArray(CMCD_EVENT_ENDPOINTS)?.let { arr ->
|
|
500
|
+
(0 until arr.length()).mapNotNull { i ->
|
|
501
|
+
arr.optJSONObject(i)?.optString(CMCD_ENDPOINT_URL)?.let { url ->
|
|
502
|
+
CMCDEndpointConfiguration(url = url)
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
if (sessionId == null && externalSessionId == null && userId == null && endpoints == null) {
|
|
507
|
+
return null
|
|
508
|
+
}
|
|
509
|
+
return CMCDSourceConfiguration(
|
|
510
|
+
sessionId = sessionId,
|
|
511
|
+
externalSessionId = externalSessionId,
|
|
512
|
+
userId = userId,
|
|
513
|
+
eventEndpoints = endpoints
|
|
514
|
+
)
|
|
515
|
+
}
|
|
479
516
|
}
|
|
@@ -15,7 +15,9 @@ private const val PROP_MILLICAST_SUBSCRIBER_TOKEN ="subscriberToken"
|
|
|
15
15
|
private const val PROP_MILLICAST_DIRECTOR_URL = "directorUrl"
|
|
16
16
|
private const val PROP_HESP_SRC = "hespSrc"
|
|
17
17
|
private const val PROP_HLS_SRC = "hlsSrc"
|
|
18
|
+
private const val PROP_HLS_MPEG_TS_SRC = "hlsMpegTsSrc"
|
|
18
19
|
private const val PROP_AD_SRC = "adSrc"
|
|
20
|
+
private const val PROP_DAI_ASSET_KEY = "daiAssetKey"
|
|
19
21
|
private const val PROP_CDN = "cdn"
|
|
20
22
|
private const val PROP_TARGET_LATENCY = "targetLatency"
|
|
21
23
|
private const val PROP_WEIGHT = "weight"
|
|
@@ -44,7 +46,9 @@ object EndpointAdapter {
|
|
|
44
46
|
endPoint.millicastSrc?.let { putMap(PROP_MILLICAST_SRC, fromEndPointMillicastSource(it)) }
|
|
45
47
|
endPoint.hespSrc?.let { putString(PROP_HESP_SRC, it) }
|
|
46
48
|
endPoint.hlsSrc?.let { putString(PROP_HLS_SRC, it) }
|
|
49
|
+
endPoint.hlsMpegTsSrc?.let { putString(PROP_HLS_MPEG_TS_SRC, it) }
|
|
47
50
|
endPoint.adSrc?.let { putString(PROP_AD_SRC, it) }
|
|
51
|
+
endPoint.daiAssetKey?.let { putString(PROP_DAI_ASSET_KEY, it) }
|
|
48
52
|
endPoint.cdn?.let { putString(PROP_CDN, it) }
|
|
49
53
|
endPoint.targetLatency?.let { putDouble(PROP_TARGET_LATENCY, it) }
|
|
50
54
|
putInt(PROP_WEIGHT, endPoint.weight)
|
|
@@ -19,6 +19,7 @@ private const val EVENT_PROP_ENDPOINT = "endpoint"
|
|
|
19
19
|
private const val EVENT_PROP_REASON = "reason"
|
|
20
20
|
private const val EVENT_PROP_NAME = "name"
|
|
21
21
|
private const val EVENT_PROP_ID = "id"
|
|
22
|
+
private const val EVENT_PROP_EXTERNAL_ID = "externalId"
|
|
22
23
|
|
|
23
24
|
class THEOliveEventAdapter(private val theoLiveApi: TheoLive, private val emitter: Emitter) {
|
|
24
25
|
|
|
@@ -68,6 +69,7 @@ class THEOliveEventAdapter(private val theoLiveApi: TheoLive, private val emitte
|
|
|
68
69
|
putString(EVENT_PROP_TYPE, "distributionloaded")
|
|
69
70
|
putMap(EVENT_PROP_DISTRIBUTION, Arguments.createMap().apply {
|
|
70
71
|
putString(EVENT_PROP_ID, event.getDistribution().id)
|
|
72
|
+
event.getDistribution().externalId?.let { putString(EVENT_PROP_EXTERNAL_ID, it) }
|
|
71
73
|
putString(EVENT_PROP_NAME, event.getDistribution().name)
|
|
72
74
|
})
|
|
73
75
|
})
|
|
@@ -26,6 +26,7 @@ private const val PROP_NAME = "name"
|
|
|
26
26
|
private const val PROP_ENABLED = "enabled"
|
|
27
27
|
private const val PROP_SRC = "src"
|
|
28
28
|
private const val PROP_FORCED = "forced"
|
|
29
|
+
private const val PROP_IN_BAND_METADATA_TRACK_DISPATCH_TYPE = "inBandMetadataTrackDispatchType"
|
|
29
30
|
private const val PROP_CAPTION_CHANNEL = "captionChannel"
|
|
30
31
|
private const val PROP_AUDIO_SAMPLING_RATE = "audioSamplingRate"
|
|
31
32
|
private const val PROP_BANDWIDTH = "bandwidth"
|
|
@@ -71,6 +72,7 @@ object TrackListAdapter {
|
|
|
71
72
|
textTrackPayload.putBoolean(PROP_FORCED, textTrack.isForced)
|
|
72
73
|
|
|
73
74
|
// THEOplayer v10.13+
|
|
75
|
+
textTrackPayload.putString(PROP_IN_BAND_METADATA_TRACK_DISPATCH_TYPE, textTrack.inBandMetadataTrackDispatchType ?: "")
|
|
74
76
|
textTrack.captionChannel?.let { textTrackPayload.putInt(PROP_CAPTION_CHANNEL, it) }
|
|
75
77
|
|
|
76
78
|
// Optionally pass cue list.
|
|
@@ -403,6 +403,12 @@ public class THEOplayerRCTMainEventHandler {
|
|
|
403
403
|
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] DurationChange listener dettached from THEOplayer") }
|
|
404
404
|
}
|
|
405
405
|
|
|
406
|
+
// VOLUME_CHANGE
|
|
407
|
+
if let volumeChangeListener = self.volumeChangeListener {
|
|
408
|
+
player.removeEventListener(type: PlayerEventTypes.VOLUME_CHANGE, listener: volumeChangeListener)
|
|
409
|
+
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] VolumeChange listener dettached from THEOplayer") }
|
|
410
|
+
}
|
|
411
|
+
|
|
406
412
|
// PROGRESS
|
|
407
413
|
if let progressListener = self.progressListener {
|
|
408
414
|
player.removeEventListener(type: PlayerEventTypes.PROGRESS, listener: progressListener)
|
|
@@ -64,6 +64,7 @@ let SD_PROP_INITIALIZATION_DELAY: String = "initializationDelay"
|
|
|
64
64
|
let SD_PROP_HLS_DATE_RANGE: String = "hlsDateRange"
|
|
65
65
|
let SD_PROP_BREAK_MANIFEST_URL: String = "breakManifestUrl"
|
|
66
66
|
let SD_PROP_CMCD: String = "cmcd"
|
|
67
|
+
let SD_PROP_TRANSMISSION_MODE: String = "transmissionMode"
|
|
67
68
|
let SD_PROP_QUERY_PARAMETERS: String = "queryParameters"
|
|
68
69
|
|
|
69
70
|
let EXTENSION_HLS: String = ".m3u8"
|
|
@@ -167,11 +168,15 @@ class THEOplayerRCTSourceDescriptionBuilder {
|
|
|
167
168
|
}
|
|
168
169
|
|
|
169
170
|
// 6. configure CMCD
|
|
170
|
-
|
|
171
|
-
if cmcd
|
|
172
|
-
|
|
173
|
-
|
|
171
|
+
var cmcdSourceConfig: CMCDSourceConfiguration? = nil
|
|
172
|
+
if let cmcd = sourceData[SD_PROP_CMCD] as? [String:Any] {
|
|
173
|
+
let requestModeEnabled = cmcd[SD_PROP_TRANSMISSION_MODE] != nil
|
|
174
|
+
if requestModeEnabled {
|
|
175
|
+
typedSources.forEach { typedSource in
|
|
176
|
+
typedSource.cmcd = true
|
|
177
|
+
}
|
|
174
178
|
}
|
|
179
|
+
cmcdSourceConfig = THEOplayerRCTSourceDescriptionBuilder.buildCmcdSourceConfiguration(cmcd)
|
|
175
180
|
}
|
|
176
181
|
|
|
177
182
|
// 7. construct the SourceDescription
|
|
@@ -179,13 +184,33 @@ class THEOplayerRCTSourceDescriptionBuilder {
|
|
|
179
184
|
textTracks: textTrackDescriptions,
|
|
180
185
|
ads: adsDescriptions,
|
|
181
186
|
poster: poster,
|
|
182
|
-
metadata: metadataDescription
|
|
183
|
-
|
|
187
|
+
metadata: metadataDescription,
|
|
188
|
+
cmcdConfiguration: cmcdSourceConfig)
|
|
189
|
+
|
|
184
190
|
return (sourceDescription, metadataAndChapterTrackDescriptions)
|
|
185
191
|
}
|
|
186
192
|
|
|
187
193
|
// MARK: Private build methods
|
|
188
194
|
|
|
195
|
+
private static func buildCmcdSourceConfiguration(_ cmcdData: [String:Any]) -> CMCDSourceConfiguration? {
|
|
196
|
+
let sessionId = cmcdData["sessionID"] as? String
|
|
197
|
+
let externalSessionId = cmcdData["externalSessionId"] as? String
|
|
198
|
+
let userId = cmcdData["userId"] as? String
|
|
199
|
+
let endpoints: [CMCDEndpointConfiguration]? = (cmcdData["eventEndpoints"] as? [[String: Any]])?.compactMap { dict in
|
|
200
|
+
guard let url = dict["url"] as? String else { return nil }
|
|
201
|
+
return CMCDEndpointConfiguration(url: url)
|
|
202
|
+
}
|
|
203
|
+
if sessionId == nil && externalSessionId == nil && userId == nil && endpoints == nil {
|
|
204
|
+
return nil
|
|
205
|
+
}
|
|
206
|
+
return CMCDSourceConfiguration(
|
|
207
|
+
sessionId: sessionId,
|
|
208
|
+
externalSessionId: externalSessionId,
|
|
209
|
+
userId: userId,
|
|
210
|
+
eventEndpoints: endpoints
|
|
211
|
+
)
|
|
212
|
+
}
|
|
213
|
+
|
|
189
214
|
/**
|
|
190
215
|
Creates a THEOplayer TypedSource. This requires a source property for non SSAI strreams (either as a string or as an object contiaining a src property). For SSAI streams the TypeSource can be created from the ssai property.
|
|
191
216
|
- returns: a THEOplayer TypedSource. In case of SSAI we support GoogleDAITypedSource with GoogleDAIVodConfiguration or GoogleDAILiveConfiguration
|
|
@@ -29,6 +29,7 @@ let PROP_CUE_CONTENT: String = "content"
|
|
|
29
29
|
let PROP_CUE_CUSTOM_ATTRIBUTES: String = "customAttributes"
|
|
30
30
|
let PROP_SRC: String = "src"
|
|
31
31
|
let PROP_FORCED: String = "forced"
|
|
32
|
+
let PROP_IN_BAND_METADATA_TRACK_DISPATCH_TYPE: String = "inBandMetadataTrackDispatchType"
|
|
32
33
|
let PROP_START_DATE: String = "startDate"
|
|
33
34
|
let PROP_END_DATE: String = "endDate"
|
|
34
35
|
let PROP_ATTRIBUTE_CLASS: String = "class"
|
|
@@ -80,6 +81,7 @@ class THEOplayerRCTTrackMetadataAggregator {
|
|
|
80
81
|
entry[PROP_TYPE] = textTrack.type
|
|
81
82
|
entry[PROP_SRC] = textTrack.src
|
|
82
83
|
entry[PROP_FORCED] = textTrack.forced
|
|
84
|
+
entry[PROP_IN_BAND_METADATA_TRACK_DISPATCH_TYPE] = textTrack.inBandMetadataTrackDispatchType
|
|
83
85
|
// process cues when texttrack contains them
|
|
84
86
|
if !textTrack.cues.isEmpty {
|
|
85
87
|
var cueList: [[String:Any]] = []
|
|
@@ -327,6 +329,7 @@ class THEOplayerRCTTrackMetadataAggregator {
|
|
|
327
329
|
track[PROP_LABEL] = trackDescription.label ?? "no label"
|
|
328
330
|
track[PROP_TYPE] = "webvtt"
|
|
329
331
|
track[PROP_SRC] = trackDescription.src.absoluteString
|
|
332
|
+
track[PROP_IN_BAND_METADATA_TRACK_DISPATCH_TYPE] = ""
|
|
330
333
|
var cueList: [[String:Any]] = []
|
|
331
334
|
var cueIndex = 0
|
|
332
335
|
for c in cues {
|
|
@@ -48,6 +48,7 @@ public class THEOplayerRCTView: UIView {
|
|
|
48
48
|
var castConfig = CastConfig()
|
|
49
49
|
var uiConfig = UIConfig()
|
|
50
50
|
var theoliveConfig = THEOliveConfig()
|
|
51
|
+
var cmcdConfig = CmcdConfig()
|
|
51
52
|
|
|
52
53
|
public var bypassDropInstanceOnReactLifecycle = false // controls superView detaching behaviour
|
|
53
54
|
|
|
@@ -232,6 +233,7 @@ public class THEOplayerRCTView: UIView {
|
|
|
232
233
|
config.hlsDateRange = self.hlsDateRange
|
|
233
234
|
config.license = self.license
|
|
234
235
|
config.licenseUrl = self.licenseUrl
|
|
236
|
+
config.cmcd = self.playerCmcdConfiguration()
|
|
235
237
|
self.player = THEOplayer(configuration: config.build())
|
|
236
238
|
|
|
237
239
|
self.initAdsIntegration()
|
|
@@ -322,6 +324,7 @@ public class THEOplayerRCTView: UIView {
|
|
|
322
324
|
self.parseUIConfig(configDict: configDict)
|
|
323
325
|
self.parseMediaControlConfig(configDict: configDict)
|
|
324
326
|
self.parseTHEOliveConfig(configDict: configDict)
|
|
327
|
+
self.parseCmcdConfig(configDict: configDict)
|
|
325
328
|
if DEBUG_VIEW { PrintUtils.printLog(logText: "[NATIVE] config prop updated.") }
|
|
326
329
|
|
|
327
330
|
// Given the bridged config, create the initial THEOplayer instance
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// THEOplayerRCTView+CmcdConfig.swift
|
|
2
|
+
|
|
3
|
+
import Foundation
|
|
4
|
+
import THEOplayerSDK
|
|
5
|
+
|
|
6
|
+
struct CmcdConfig {
|
|
7
|
+
var externalSessionId: String?
|
|
8
|
+
var userId: String?
|
|
9
|
+
var eventEndpoints: [CMCDEndpointConfiguration]?
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
extension THEOplayerRCTView {
|
|
13
|
+
|
|
14
|
+
func parseCmcdConfig(configDict: NSDictionary) {
|
|
15
|
+
if let cmcdDict = configDict["cmcd"] as? NSDictionary {
|
|
16
|
+
self.cmcdConfig.externalSessionId = cmcdDict["externalSessionId"] as? String
|
|
17
|
+
self.cmcdConfig.userId = cmcdDict["userId"] as? String
|
|
18
|
+
self.cmcdConfig.eventEndpoints = (cmcdDict["eventEndpoints"] as? [[String: Any]])?.compactMap { dict -> CMCDEndpointConfiguration? in
|
|
19
|
+
guard let url = dict["url"] as? String else { return nil }
|
|
20
|
+
return CMCDEndpointConfiguration(url: url)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
func playerCmcdConfiguration() -> CMCDConfiguration? {
|
|
26
|
+
let config = self.cmcdConfig
|
|
27
|
+
if config.externalSessionId == nil && config.userId == nil && config.eventEndpoints == nil {
|
|
28
|
+
return nil
|
|
29
|
+
}
|
|
30
|
+
return CMCDConfiguration(
|
|
31
|
+
externalSessionId: config.externalSessionId,
|
|
32
|
+
userId: config.userId,
|
|
33
|
+
eventEndpoints: config.eventEndpoints
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -9,15 +9,18 @@ import THEOplayerTHEOliveIntegration
|
|
|
9
9
|
|
|
10
10
|
let PROP_ENDPOINT_HESP_SRC: String = "hespSrc"
|
|
11
11
|
let PROP_ENDPOINT_HLS_SRC: String = "hlsSrc"
|
|
12
|
+
let PROP_ENDPOINT_HLS_MPEG_TS_SRC: String = "hlsMpegTsSrc"
|
|
12
13
|
let PROP_ENDPOINT_MILLICAST_SRC: String = "millicastSrc"
|
|
13
14
|
let PROP_ENDPOINT_CDN: String = "cdn"
|
|
14
15
|
let PROP_ENDPOINT_AD_SRC: String = "adSrc"
|
|
16
|
+
let PROP_ENDPOINT_DAI_ASSET_KEY: String = "daiAssetKey"
|
|
15
17
|
let PROP_ENDPOINT_WEIGHT: String = "weight"
|
|
16
18
|
let PROP_ENDPOINT_PRIORITY: String = "priority"
|
|
17
19
|
let PROP_ENDPOINT_CONTENT_PROTECTION: String = "contentProtection"
|
|
18
20
|
let PROP_REASON_ERROR_CODE: String = "errorCode"
|
|
19
21
|
let PROP_REASON_ERROR_MESSAGE: String = "errorMessage"
|
|
20
22
|
let PROP_DISTRIBUTION_ID: String = "id"
|
|
23
|
+
let PROP_DISTRIBUTION_EXTERNAL_ID: String = "externalId"
|
|
21
24
|
let PROP_DISTRIBUTION_NAME: String = "name"
|
|
22
25
|
|
|
23
26
|
let PROP_CONTENTPROTECTION_INTEGRATION: String = "integration"
|
|
@@ -46,6 +49,9 @@ class THEOplayerRCTTHEOliveEventAdapter {
|
|
|
46
49
|
if let hlsSrc = endpoint.hlsSrc {
|
|
47
50
|
endpointData[PROP_ENDPOINT_HLS_SRC] = hlsSrc
|
|
48
51
|
}
|
|
52
|
+
if let hlsMpegTsSrc = endpoint.hlsMpegTsSrc {
|
|
53
|
+
endpointData[PROP_ENDPOINT_HLS_MPEG_TS_SRC] = hlsMpegTsSrc
|
|
54
|
+
}
|
|
49
55
|
if let millicastSrc = endpoint.millicastSrc {
|
|
50
56
|
endpointData[PROP_ENDPOINT_MILLICAST_SRC] = millicastSrc.toJSONEncodableDictionary()
|
|
51
57
|
}
|
|
@@ -55,6 +61,9 @@ class THEOplayerRCTTHEOliveEventAdapter {
|
|
|
55
61
|
if let adSrc = endpoint.adSrc {
|
|
56
62
|
endpointData[PROP_ENDPOINT_AD_SRC] = adSrc
|
|
57
63
|
}
|
|
64
|
+
if let daiAssetKey = endpoint.daiAssetKey {
|
|
65
|
+
endpointData[PROP_ENDPOINT_DAI_ASSET_KEY] = daiAssetKey
|
|
66
|
+
}
|
|
58
67
|
if let contentProtection = endpoint.channelContentProtection {
|
|
59
68
|
endpointData[PROP_ENDPOINT_CONTENT_PROTECTION] = THEOplayerRCTTHEOliveEventAdapter.fromContentProtection(contentProtection: contentProtection)
|
|
60
69
|
}
|
|
@@ -122,6 +131,9 @@ class THEOplayerRCTTHEOliveEventAdapter {
|
|
|
122
131
|
|
|
123
132
|
var distributionData: [String:Any] = [:]
|
|
124
133
|
distributionData[PROP_DISTRIBUTION_ID] = distribution.id
|
|
134
|
+
if let externalId = distribution.externalId {
|
|
135
|
+
distributionData[PROP_DISTRIBUTION_EXTERNAL_ID] = externalId
|
|
136
|
+
}
|
|
125
137
|
distributionData[PROP_DISTRIBUTION_NAME] = distribution.name
|
|
126
138
|
|
|
127
139
|
return distributionData
|