Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ 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 `abr` property to `TypedSource`, supporting `preferredVideoCodecs` and `preferredAudioCodecs` on Android and Web.

### Fixed

- Fixed an issue on Android where `preferredKeySystems` in the content protection configuration was ignored.

## [11.4.1] - 26-07-22

### Changed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ const val PROP_MULTISESSION: String = "multiSession"
const val PROP_KEYS: String = "keys"
const val PROP_ID: String = "id"
const val PROP_VALUE: String = "value"
const val PROP_PREFERRED_KEY_SYSTEMS: String = "preferredKeySystems"

object ContentProtectionAdapter {

Expand Down Expand Up @@ -108,6 +109,12 @@ object ContentProtectionAdapter {
if (jsonConfig.has(PROP_MULTISESSION)) {
multiSession(jsonConfig.getBoolean(PROP_MULTISESSION))
}
if (jsonConfig.has(PROP_PREFERRED_KEY_SYSTEMS)) {
val jsonKeySystems = jsonConfig.getJSONArray(PROP_PREFERRED_KEY_SYSTEMS)
preferredKeySystems((0 until jsonKeySystems.length()).mapNotNull {
KeySystemAdapter.fromString(jsonKeySystems.getString(it))
})
}
queryParameters(fromJSONObjectToMap(jsonConfig.optJSONObject(PROP_QUERY_PARAMETERS)))
}.build()
}
Expand Down
23 changes: 23 additions & 0 deletions android/src/main/java/com/theoplayer/source/SourceAdapter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.theoplayer.android.api.ads.theoads.TheoAdDescription
import com.theoplayer.android.api.error.THEOplayerException
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.WritableMap
import com.theoplayer.android.api.source.SourceAbrConfiguration
import com.theoplayer.android.api.source.SourceDescription
import com.theoplayer.android.api.source.TypedSource
import com.theoplayer.android.api.source.metadata.MetadataDescription
Expand Down Expand Up @@ -41,6 +42,9 @@ import java.util.ArrayList
import java.util.HashMap

private const val TAG = "SourceAdapter"
private const val PROP_ABR = "abr"
private const val PROP_PREFERRED_VIDEO_CODECS = "preferredVideoCodecs"
private const val PROP_PREFERRED_AUDIO_CODECS = "preferredAudioCodecs"
private const val PROP_CONTENT_PROTECTION = "contentProtection"
private const val PROP_LIVE_OFFSET = "liveOffset"
private const val PROP_HLS_DATERANGE = "hlsDateRange"
Expand Down Expand Up @@ -179,6 +183,9 @@ class SourceAdapter {
.poster(poster)
.ads(*ads.toTypedArray())
.textTracks(*sideLoadedTextTracks.toTypedArray())
parseAbrConfigurationFromSources(jsonSources, jsonSourceObject.optJSONObject(PROP_SOURCES))?.let {
builder.abr(it)
}
if (metadataDescription != null) {
builder.metadata(metadataDescription)
}
Expand All @@ -194,6 +201,22 @@ class SourceAdapter {
return null
}

private fun parseAbrConfigurationFromSources(jsonSources: JSONArray?, jsonSource: JSONObject?): SourceAbrConfiguration? {
// The SDK applies the ABR configuration per source description: take it from the first typed source specifying one.
val jsonAbr = if (jsonSources != null) {
(0 until jsonSources.length()).firstNotNullOfOrNull { (jsonSources[it] as JSONObject).optJSONObject(PROP_ABR) }
} else {
jsonSource?.optJSONObject(PROP_ABR)
} ?: return null
return SourceAbrConfiguration(
maxBitrate = null,
preferredVideoCodecs = jsonAbr.optJSONArray(PROP_PREFERRED_VIDEO_CODECS)?.toStringList(),
preferredAudioCodecs = jsonAbr.optJSONArray(PROP_PREFERRED_AUDIO_CODECS)?.toStringList()
)
}

private fun JSONArray.toStringList(): List<String> = (0 until length()).map { getString(it) }

private fun parseTheoLiveSource(jsonTypedSource: JSONObject): TheoLiveSource {
return TheoLiveSource(
src=jsonTypedSource.optString(PROP_SRC),
Expand Down
8 changes: 8 additions & 0 deletions src/api/source/SourceDescription.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type { ServerSideAdInsertionConfiguration } from './ads/ssai/ServerSideAd
import type { AnalyticsDescription } from './analytics/AnalyticsDescription';
import { CmcdSourceConfiguration } from '../cmcd/CmcdConfiguration';
import { SourceLatencyConfiguration } from './latency/SourceLatencyConfiguration';
import type { SourceAbrConfiguration } from './abr/SourceAbrConfiguration';

/**
* A type alias for a {@link TypedSource} media resource.
Expand Down Expand Up @@ -344,6 +345,13 @@ export interface BaseSource {
* <br/> - Ignored for non-HLS streams.
*/
hls?: HlsPlaybackConfiguration;

/**
* The source's ABR configuration.
*
* @platform web,android
*/
abr?: SourceAbrConfiguration;
}

/**
Expand Down
27 changes: 27 additions & 0 deletions src/api/source/abr/SourceAbrConfiguration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* Describes the ABR configuration for a specific source.
*
* @category Source
* @public
*/
export interface SourceAbrConfiguration {
/**
* A list of preferred audio codecs which will be used by the ABR algorithm for track selection, if the codec is supported.
*
* @platform web,android
*
* @remarks
* <br/> - Codecs are specified by their RFC 6381 name, e.g. `"ec-3"` or `"mp4a.40.2"`.
*/
preferredAudioCodecs?: string[];

/**
* A list of preferred video codecs which will be used by the ABR algorithm for track selection, if the codec is supported.
*
* @platform web,android
*
* @remarks
* <br/> - Codecs are specified by their RFC 6381 name, e.g. `"hvc1"`, `"dvh1"` or `"avc1"`.
*/
preferredVideoCodecs?: string[];
}
1 change: 1 addition & 0 deletions src/api/source/abr/barrel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './SourceAbrConfiguration';
1 change: 1 addition & 0 deletions src/api/source/barrel.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './abr/barrel';
export * from './ads/barrel';
export * from './analytics/barrel';
export * from './drm/barrel';
Expand Down
Loading