From 32fe3ed3ea136a61425f315c470f5f244f741896 Mon Sep 17 00:00:00 2001 From: Ramesh Prasad Date: Thu, 11 Jun 2026 15:09:05 +1000 Subject: [PATCH 1/2] Add Android support for ABRConfiguration.preferredMaximumResolution Mirrors the existing iOS behaviour by forwarding the resolution cap to the Android SDK's new Abr.preferredMaximumResolution. (0,0) clears the cap to match the iOS sentinel. Co-Authored-By: Claude Opus 4.7 --- CHANGELOG.md | 6 ++++++ .../theoplayer/abr/ABRConfigurationAdapter.kt | 21 +++++++++++++++++++ doc/abr.md | 8 +++++++ src/api/abr/ABRConfiguration.ts | 4 ++-- 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e5d328b86..13999a625 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.1.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Added + +- Added Android support for `ABRConfiguration.preferredMaximumResolution`, mirroring the existing iOS behaviour. Set to `(0,0)` to remove the cap. + ## [11.2.1] - 26-06-09 ### Fixed diff --git a/android/src/main/java/com/theoplayer/abr/ABRConfigurationAdapter.kt b/android/src/main/java/com/theoplayer/abr/ABRConfigurationAdapter.kt index df7e44505..a4d5c6edb 100644 --- a/android/src/main/java/com/theoplayer/abr/ABRConfigurationAdapter.kt +++ b/android/src/main/java/com/theoplayer/abr/ABRConfigurationAdapter.kt @@ -1,5 +1,6 @@ package com.theoplayer.abr +import android.util.Size import com.facebook.react.bridge.ReadableMap import com.theoplayer.android.api.abr.AbrStrategyConfiguration import com.theoplayer.android.api.abr.AbrStrategyMetadata @@ -12,6 +13,9 @@ object ABRConfigurationAdapter { private const val PROP_METADATA = "metadata" private const val PROP_TYPE = "type" private const val PROP_BITRATE = "bitrate" + private const val PROP_PREFERRED_MAXIMUM_RESOLUTION = "preferredMaximumResolution" + private const val PROP_WIDTH = "width" + private const val PROP_HEIGHT = "height" fun applyABRConfigurationFromProps(player: Player?, abrProps: ReadableMap?) { if (abrProps == null || player == null) { @@ -20,6 +24,11 @@ object ABRConfigurationAdapter { if (abrProps.hasKey(PROP_TARGET_BUFFER)) { player.abr.targetBuffer = abrProps.getInt(PROP_TARGET_BUFFER) } + // (0,0) is the documented sentinel for "no cap" and maps to a null Size on the native SDK. + val preferredMaximumResolutionProps = abrProps.getMap(PROP_PREFERRED_MAXIMUM_RESOLUTION) + if (preferredMaximumResolutionProps != null) { + player.abr.preferredMaximumResolution = preferredMaximumResolutionFromProps(preferredMaximumResolutionProps) + } // Strategy can be either a string or an object try { val abrStrategyPropsString = abrProps.getString(PROP_STRATEGY) @@ -50,6 +59,18 @@ object ABRConfigurationAdapter { } } + private fun preferredMaximumResolutionFromProps(props: ReadableMap?): Size? { + if (props == null || !props.hasKey(PROP_WIDTH) || !props.hasKey(PROP_HEIGHT)) { + return null + } + val width = props.getDouble(PROP_WIDTH).toInt() + val height = props.getDouble(PROP_HEIGHT).toInt() + if (width <= 0 || height <= 0) { + return null + } + return Size(width, height) + } + private fun abrMetadataFromProps(props: ReadableMap?): AbrStrategyMetadata? { if (props == null) { return null diff --git a/doc/abr.md b/doc/abr.md index 13603bfa4..6d81599c4 100644 --- a/doc/abr.md +++ b/doc/abr.md @@ -39,6 +39,7 @@ on the chosen strategy, as well as various parameters of the playback buffer. | `targetBuffer` | The amount that the player should buffer ahead of the current playback position, in seconds. Default is **20**s. | Android & Web | | `bufferLookbackWindow` | The amount of data which the player should keep in its buffer before the current playback position, in seconds. Default is **30**s. | Web | | `maxBufferLength` | The maximum length of the player's buffer, in seconds. | Web | | +| `preferredMaximumResolution` | A preferred upper limit on the resolution of the video to be downloaded. `(0,0)` (the default) removes the cap. | Android & iOS | When specifying the strategy, apart from the values `'performance'`, `'quality'`, `'bandwidth'`, an `ABRStrategyConfiguration` @@ -54,6 +55,13 @@ const strategyConfig: ABRStrategyConfiguration = { player.abr.strategy = strategyConfig; ``` +To cap the resolution of the variant the player downloads, set `preferredMaximumResolution` to a `Resolution` (`{width, height}`). +Pass `(0, 0)` to remove the cap. + +```typescript +player.abr.preferredMaximumResolution = { width: 1280, height: 720 }; +``` + ## Setting Target Video Quality By default, the ABR algorithm will choose, depending on the available bandwidth, diff --git a/src/api/abr/ABRConfiguration.ts b/src/api/abr/ABRConfiguration.ts index 65ba1b70c..a320ceebb 100644 --- a/src/api/abr/ABRConfiguration.ts +++ b/src/api/abr/ABRConfiguration.ts @@ -126,9 +126,9 @@ export interface ABRConfiguration { * A preferred upper limit on the resolution of the video to be downloaded (or otherwise transferred) and rendered by the player. * * The default value is (0,0), which indicates that the client enforces no limit on video resolution. Other values indicate a preferred maximum video resolution. - * It only applies to HTTP Live Streaming asset. + * It only applies to Live Streaming asset. * - * @platform ios + * @platform ios,android */ preferredMaximumResolution?: Resolution; } From b8cda2a672a02843153feb39ef429376772c1d67 Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Mon, 15 Jun 2026 10:46:18 +0200 Subject: [PATCH 2/2] Bump documented sdk ranges --- android/build.gradle | 4 ++-- example/android/gradle.properties | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 88c71ab9e..c76f121db 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -126,8 +126,8 @@ repositories { mavenLocal() } -// The minimum supported THEOplayer version is 11.4.0 -def theoVersion = safeExtGet('THEOplayer_sdk', '[11.4.0, 12.0.0)') +// The minimum supported THEOplayer version is 11.5.0 +def theoVersion = safeExtGet('THEOplayer_sdk', '[11.5.0, 12.0.0)') def theoMediaSessionVersion = safeExtGet('THEOplayer_mediasession', '[11.0.0, 12.0.0)') def theoAdsWrapperVersion = "11.0.0" def coroutinesVersion = safeExtGet('coroutinesVersion', '1.10.2') diff --git a/example/android/gradle.properties b/example/android/gradle.properties index 6de786415..4efa02c59 100644 --- a/example/android/gradle.properties +++ b/example/android/gradle.properties @@ -46,7 +46,7 @@ hermesEnabled=true edgeToEdgeEnabled=false # Version of the THEOplayer SDK, if not specified, the latest available version within bounds is set. -#THEOplayer_sdk=[11.4.0, 12.0.0) +#THEOplayer_sdk=[11.5.0, 12.0.0) # Override Android sdk versions #THEOplayer_compileSdkVersion = 36