Skip to content

Commit

Permalink
Add support for THEOlive integration on Android
Browse files Browse the repository at this point in the history
  • Loading branch information
tvanlaerhoven authored and wvanhaevre committed Nov 27, 2024
1 parent 8859db7 commit 953a2a4
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.theoplayer.latency

import com.theoplayer.android.api.latency.LatencyConfiguration
import org.json.JSONObject

private const val PROP_MINIMUM_OFFSET = "minimumOffset"
private const val PROP_MAXIMUM_OFFSET = "maximumOffset"
private const val PROP_TARGET_OFFSET = "targetOffset"
private const val PROP_FORCE_SEEK_OFFSET = "forceSeekOffset"
private const val PROP_MINIMUM_PLAYBACK_RATE = "minimumPlaybackRate"
private const val PROP_MAXIMUM_PLAYBACK_RATE = "maximumPlaybackRate"

fun parseLatencyConfiguration(jsonLatency: JSONObject): LatencyConfiguration {
return LatencyConfiguration.Builder().apply {
setMinimumOffset(jsonLatency.optDouble(PROP_MINIMUM_OFFSET))
setMaximumOffset(jsonLatency.optDouble(PROP_MAXIMUM_OFFSET))
setTargetOffset(jsonLatency.optDouble(PROP_TARGET_OFFSET))
setForceSeekOffset(jsonLatency.optDouble(PROP_FORCE_SEEK_OFFSET))
setMinimumPlaybackRate(jsonLatency.optDouble(PROP_MINIMUM_PLAYBACK_RATE))
setMaximumPlaybackRate(jsonLatency.optDouble(PROP_MAXIMUM_PLAYBACK_RATE))
}.build()
}
39 changes: 30 additions & 9 deletions android/src/main/java/com/theoplayer/source/SourceAdapter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ import com.theoplayer.android.api.ads.theoads.TheoAdsLayoutOverride
import com.theoplayer.android.api.error.ErrorCode
import com.theoplayer.android.api.source.AdIntegration
import com.theoplayer.android.api.source.dash.DashPlaybackConfiguration
import com.theoplayer.android.api.theolive.TheoLiveSource
import com.theoplayer.drm.ContentProtectionAdapter
import com.theoplayer.latency.parseLatencyConfiguration
import com.theoplayer.util.BridgeUtils
import org.json.JSONArray
import org.json.JSONException
Expand Down Expand Up @@ -61,6 +63,7 @@ private const val PROP_CUSTOM_ASSET_KEY = "customAssetKey"
private const val PROP_OVERRIDE_LAYOUT = "overrideLayout"
private const val PROP_NETWORK_CODE = "networkCode"
private const val PROP_USE_ID3 = "useId3"
private const val PROP_LATENCY_CONFIGURATION = "latencyConfiguration"

private const val ERROR_IMA_NOT_ENABLED = "Google IMA support not enabled."
private const val ERROR_THEOADS_NOT_ENABLED = "THEOads support not enabled."
Expand All @@ -69,6 +72,8 @@ private const val ERROR_MISSING_CSAI_INTEGRATION = "Missing CSAI integration"

private const val PROP_SSAI_INTEGRATION_GOOGLE_DAI = "google-dai"

private const val INTEGRATION_THEOLIVE = "theolive"

class SourceAdapter {
private val gson = Gson()

Expand Down Expand Up @@ -148,27 +153,43 @@ class SourceAdapter {
return null
}

private fun parseTheoLiveSource(jsonTypedSource: JSONObject): TheoLiveSource {
return TheoLiveSource(
src=jsonTypedSource.optString(PROP_SRC),
headers=jsonTypedSource.optJSONObject(PROP_HEADERS)?.let {
BridgeUtils.fromJSONObjectToMap(it)
},
latencyConfiguration=jsonTypedSource.optJSONObject(PROP_LATENCY_CONFIGURATION)?.let {
parseLatencyConfiguration(it)
}
)
}

@Throws(THEOplayerException::class)
private fun parseTypedSource(jsonTypedSource: JSONObject): TypedSource {
// Some integrations do not support the Builder pattern
return when (jsonTypedSource.optString(PROP_INTEGRATION)) {
INTEGRATION_THEOLIVE -> parseTheoLiveSource(jsonTypedSource)
else -> parseTypedSourceFromBuilder(jsonTypedSource)
}
}

@Throws(THEOplayerException::class)
private fun parseTypedSourceFromBuilder(jsonTypedSource: JSONObject): TypedSource {
try {
var tsBuilder = TypedSource.Builder(jsonTypedSource.optString(PROP_SRC))
val sourceType = parseSourceType(jsonTypedSource)
if (jsonTypedSource.has(PROP_SSAI)) {
val ssaiJson = jsonTypedSource.getJSONObject(PROP_SSAI)
jsonTypedSource.optJSONObject(PROP_SSAI)?.let { ssaiJson ->
tsBuilder = SSAIAdapterRegistry.typedSourceBuilderFromJson(ssaiJson, tsBuilder, sourceType)
}
if (sourceType != null) {
tsBuilder.type(sourceType)
}
if (jsonTypedSource.has(PROP_DASH)) {
tsBuilder.dash(parseDashConfig(jsonTypedSource.getJSONObject(PROP_DASH)))
jsonTypedSource.optJSONObject(PROP_DASH)?.let { dashJson ->
tsBuilder.dash(parseDashConfig(dashJson))
}
jsonTypedSource.optJSONObject(PROP_HEADERS)?.let { headersJson ->
tsBuilder.headers(mutableMapOf<String, String>().apply {
headersJson.keys().forEach { key ->
put(key, headersJson.getString(key))
}
})
tsBuilder.headers(BridgeUtils.fromJSONObjectToMap(headersJson))
}
if (jsonTypedSource.has(PROP_LIVE_OFFSET)) {
tsBuilder.liveOffset(jsonTypedSource.getDouble(PROP_LIVE_OFFSET))
Expand Down
8 changes: 8 additions & 0 deletions android/src/main/java/com/theoplayer/util/BridgeUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ import org.json.JSONException
import org.json.JSONObject

object BridgeUtils {
fun fromJSONObjectToMap(json: JSONObject): Map<String, String> {
return mutableMapOf<String, String>().apply {
json.keys().forEach { key ->
put(key, json.getString(key))
}
}
}

/**
* Convert a JSONObject to bridge data.
*/
Expand Down

0 comments on commit 953a2a4

Please sign in to comment.