mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2025-05-30 13:30:22 +02:00
added initial drm support for audio url sources
This commit is contained in:
parent
b4fddbe26a
commit
88c8dbcb7c
@ -357,6 +357,15 @@ class AudioUrlSource {
|
|||||||
this.requestModifier = obj.requestModifier;
|
this.requestModifier = obj.requestModifier;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
class AudioUrlWidevineSource extends AudioUrlSource {
|
||||||
|
constructor(obj) {
|
||||||
|
super(obj);
|
||||||
|
this.plugin_type = "AudioUrlWidevineSource";
|
||||||
|
|
||||||
|
this.bearerToken = obj.bearerToken;
|
||||||
|
this.licenseUri = obj.licenseUri;
|
||||||
|
}
|
||||||
|
}
|
||||||
class AudioUrlRangeSource extends AudioUrlSource {
|
class AudioUrlRangeSource extends AudioUrlSource {
|
||||||
constructor(obj) {
|
constructor(obj) {
|
||||||
super(obj);
|
super(obj);
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
package com.futo.platformplayer.api.media.models.streams.sources
|
||||||
|
|
||||||
|
import com.futo.platformplayer.api.media.models.streams.sources.other.IStreamMetaDataSource
|
||||||
|
import com.futo.platformplayer.api.media.models.streams.sources.other.StreamMetaData
|
||||||
|
import com.futo.platformplayer.others.Language
|
||||||
|
|
||||||
|
class AudioUrlWidevineSource(
|
||||||
|
override val streamMetaData: StreamMetaData?,
|
||||||
|
override val name: String,
|
||||||
|
val url: String,
|
||||||
|
override val bitrate: Int,
|
||||||
|
override val container: String = "",
|
||||||
|
override val codec: String = "",
|
||||||
|
override val language: String = Language.UNKNOWN,
|
||||||
|
override val duration: Long? = null,
|
||||||
|
override var priority: Boolean = false,
|
||||||
|
private val bearerToken: String,
|
||||||
|
private val licenseUri: String
|
||||||
|
) : IAudioUrlWidevineSource, IStreamMetaDataSource {
|
||||||
|
override fun getAudioUrl(): String {
|
||||||
|
return url
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getBearerToken(): String {
|
||||||
|
return bearerToken
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getLicenseUri(): String {
|
||||||
|
return licenseUri
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun fromUrlSource(source: IAudioUrlWidevineSource?): AudioUrlWidevineSource? {
|
||||||
|
if (source == null)
|
||||||
|
return null
|
||||||
|
|
||||||
|
val streamData = if (source is IStreamMetaDataSource)
|
||||||
|
source.streamMetaData else null
|
||||||
|
|
||||||
|
return AudioUrlWidevineSource(
|
||||||
|
streamData,
|
||||||
|
source.name,
|
||||||
|
source.getAudioUrl(),
|
||||||
|
source.bitrate,
|
||||||
|
source.container,
|
||||||
|
source.codec,
|
||||||
|
source.language,
|
||||||
|
source.duration,
|
||||||
|
source.priority,
|
||||||
|
source.getBearerToken(),
|
||||||
|
source.getLicenseUri()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
package com.futo.platformplayer.api.media.models.streams.sources
|
||||||
|
|
||||||
|
interface IAudioUrlWidevineSource : IAudioUrlSource {
|
||||||
|
fun getBearerToken(): String
|
||||||
|
fun getLicenseUri(): String
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package com.futo.platformplayer.api.media.platforms.js.models.sources
|
||||||
|
|
||||||
|
import com.caoccao.javet.values.reference.V8ValueObject
|
||||||
|
import com.futo.platformplayer.api.media.models.streams.sources.IAudioUrlWidevineSource
|
||||||
|
import com.futo.platformplayer.api.media.platforms.js.JSClient
|
||||||
|
import com.futo.platformplayer.getOrThrow
|
||||||
|
|
||||||
|
class JSAudioUrlWidevineSource(plugin: JSClient, obj: V8ValueObject) : IAudioUrlWidevineSource,
|
||||||
|
JSAudioUrlSource(plugin, obj) {
|
||||||
|
private val bearerToken: String
|
||||||
|
private val licenseUri: String
|
||||||
|
|
||||||
|
override fun getBearerToken(): String {
|
||||||
|
return bearerToken
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getLicenseUri(): String {
|
||||||
|
return licenseUri
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
val contextName = "JSAudioUrlWidevineSource"
|
||||||
|
val config = plugin.config
|
||||||
|
bearerToken = _obj.getOrThrow(config, "bearerToken", contextName)
|
||||||
|
licenseUri = _obj.getOrThrow(config, "licenseUri", contextName)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
val url = getAudioUrl()
|
||||||
|
return "(name=$name, container=$container, bitrate=$bitrate, codec=$codec, url=$url, language=$language, duration=$duration, bearerToken=$bearerToken, licenseUri=$licenseUri)"
|
||||||
|
}
|
||||||
|
}
|
@ -66,6 +66,7 @@ abstract class JSSource {
|
|||||||
const val TYPE_VIDEO_WITH_METADATA = "VideoUrlRangeSource";
|
const val TYPE_VIDEO_WITH_METADATA = "VideoUrlRangeSource";
|
||||||
const val TYPE_DASH = "DashSource";
|
const val TYPE_DASH = "DashSource";
|
||||||
const val TYPE_HLS = "HLSSource";
|
const val TYPE_HLS = "HLSSource";
|
||||||
|
private const val TYPE_AUDIO_WIDEVINE = "AudioUrlWidevineSource"
|
||||||
|
|
||||||
fun fromV8VideoNullable(plugin: JSClient, obj: V8Value?) : IVideoSource? = obj.orNull { fromV8Video(plugin, it as V8ValueObject) };
|
fun fromV8VideoNullable(plugin: JSClient, obj: V8Value?) : IVideoSource? = obj.orNull { fromV8Video(plugin, it as V8ValueObject) };
|
||||||
fun fromV8Video(plugin: JSClient, obj: V8ValueObject) : IVideoSource {
|
fun fromV8Video(plugin: JSClient, obj: V8ValueObject) : IVideoSource {
|
||||||
@ -88,6 +89,7 @@ abstract class JSSource {
|
|||||||
return when(type) {
|
return when(type) {
|
||||||
TYPE_HLS -> JSHLSManifestAudioSource.fromV8HLS(plugin, obj);
|
TYPE_HLS -> JSHLSManifestAudioSource.fromV8HLS(plugin, obj);
|
||||||
TYPE_AUDIOURL -> JSAudioUrlSource(plugin, obj);
|
TYPE_AUDIOURL -> JSAudioUrlSource(plugin, obj);
|
||||||
|
TYPE_AUDIO_WIDEVINE -> JSAudioUrlWidevineSource(plugin, obj);
|
||||||
TYPE_AUDIO_WITH_METADATA -> JSAudioUrlRangeSource(plugin, obj);
|
TYPE_AUDIO_WITH_METADATA -> JSAudioUrlRangeSource(plugin, obj);
|
||||||
else -> throw NotImplementedError("Unknown type ${type}");
|
else -> throw NotImplementedError("Unknown type ${type}");
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ import androidx.media3.datasource.DefaultDataSource
|
|||||||
import androidx.media3.datasource.DefaultHttpDataSource
|
import androidx.media3.datasource.DefaultHttpDataSource
|
||||||
import androidx.media3.exoplayer.ExoPlayer
|
import androidx.media3.exoplayer.ExoPlayer
|
||||||
import androidx.media3.exoplayer.dash.DashMediaSource
|
import androidx.media3.exoplayer.dash.DashMediaSource
|
||||||
|
import androidx.media3.exoplayer.drm.DefaultDrmSessionManagerProvider
|
||||||
import androidx.media3.exoplayer.hls.HlsMediaSource
|
import androidx.media3.exoplayer.hls.HlsMediaSource
|
||||||
import androidx.media3.exoplayer.source.MediaSource
|
import androidx.media3.exoplayer.source.MediaSource
|
||||||
import androidx.media3.exoplayer.source.MergingMediaSource
|
import androidx.media3.exoplayer.source.MergingMediaSource
|
||||||
@ -27,6 +28,7 @@ import com.futo.platformplayer.api.media.models.chapters.IChapter
|
|||||||
import com.futo.platformplayer.api.media.models.streams.VideoMuxedSourceDescriptor
|
import com.futo.platformplayer.api.media.models.streams.VideoMuxedSourceDescriptor
|
||||||
import com.futo.platformplayer.api.media.models.streams.sources.IAudioSource
|
import com.futo.platformplayer.api.media.models.streams.sources.IAudioSource
|
||||||
import com.futo.platformplayer.api.media.models.streams.sources.IAudioUrlSource
|
import com.futo.platformplayer.api.media.models.streams.sources.IAudioUrlSource
|
||||||
|
import com.futo.platformplayer.api.media.models.streams.sources.IAudioUrlWidevineSource
|
||||||
import com.futo.platformplayer.api.media.models.streams.sources.IDashManifestSource
|
import com.futo.platformplayer.api.media.models.streams.sources.IDashManifestSource
|
||||||
import com.futo.platformplayer.api.media.models.streams.sources.IHLSManifestAudioSource
|
import com.futo.platformplayer.api.media.models.streams.sources.IHLSManifestAudioSource
|
||||||
import com.futo.platformplayer.api.media.models.streams.sources.IHLSManifestSource
|
import com.futo.platformplayer.api.media.models.streams.sources.IHLSManifestSource
|
||||||
@ -389,6 +391,7 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
|
|||||||
is LocalAudioSource -> swapAudioSourceLocal(audioSource);
|
is LocalAudioSource -> swapAudioSourceLocal(audioSource);
|
||||||
is JSAudioUrlRangeSource -> swapAudioSourceUrlRange(audioSource);
|
is JSAudioUrlRangeSource -> swapAudioSourceUrlRange(audioSource);
|
||||||
is JSHLSManifestAudioSource -> swapAudioSourceHLS(audioSource);
|
is JSHLSManifestAudioSource -> swapAudioSourceHLS(audioSource);
|
||||||
|
is IAudioUrlWidevineSource -> swapAudioSourceUrlWidevine(audioSource)
|
||||||
is IAudioUrlSource -> swapAudioSourceUrl(audioSource);
|
is IAudioUrlSource -> swapAudioSourceUrl(audioSource);
|
||||||
null -> _lastAudioMediaSource = null;
|
null -> _lastAudioMediaSource = null;
|
||||||
else -> throw IllegalArgumentException("Unsupported video source [${audioSource.javaClass.simpleName}]");
|
else -> throw IllegalArgumentException("Unsupported video source [${audioSource.javaClass.simpleName}]");
|
||||||
@ -508,6 +511,31 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
|
|||||||
.createMediaSource(MediaItem.fromUri(audioSource.url));
|
.createMediaSource(MediaItem.fromUri(audioSource.url));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(UnstableApi::class)
|
||||||
|
private fun swapAudioSourceUrlWidevine(audioSource: IAudioUrlWidevineSource) {
|
||||||
|
Logger.i(TAG, "Loading AudioSource [UrlWidevine]")
|
||||||
|
val dataSource = if (audioSource is JSSource && audioSource.hasRequestModifier)
|
||||||
|
audioSource.getHttpDataSourceFactory()
|
||||||
|
else
|
||||||
|
DefaultHttpDataSource.Factory().setUserAgent(DEFAULT_USER_AGENT)
|
||||||
|
|
||||||
|
val httpRequestHeaders = mapOf("Authorization" to "Bearer " + audioSource.getBearerToken())
|
||||||
|
val provider = DefaultDrmSessionManagerProvider()
|
||||||
|
provider.setDrmHttpDataSourceFactory(dataSource)
|
||||||
|
_lastAudioMediaSource = ProgressiveMediaSource.Factory(dataSource)
|
||||||
|
.setDrmSessionManagerProvider(provider)
|
||||||
|
.createMediaSource(
|
||||||
|
MediaItem.Builder()
|
||||||
|
.setUri(audioSource.getAudioUrl()).setDrmConfiguration(
|
||||||
|
MediaItem.DrmConfiguration.Builder(C.WIDEVINE_UUID)
|
||||||
|
.setLicenseUri(audioSource.getLicenseUri())
|
||||||
|
.setMultiSession(true)
|
||||||
|
.setLicenseRequestHeaders(httpRequestHeaders)
|
||||||
|
.build()
|
||||||
|
).build()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//Prefered source selection
|
//Prefered source selection
|
||||||
fun getPreferredVideoSource(video: IPlatformVideoDetails, targetPixels: Int = -1): IVideoSource? {
|
fun getPreferredVideoSource(video: IPlatformVideoDetails, targetPixels: Int = -1): IVideoSource? {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user