From 09c09f3d64c59a351cd28bfe6b198be7f8387d1d Mon Sep 17 00:00:00 2001 From: Kai DeLorenzo Date: Thu, 28 Nov 2024 13:05:53 -0500 Subject: [PATCH] switch to executor structure --- app/src/main/assets/scripts/source.js | 40 +++++++++++----- .../sources/IVideoUrlWidevineSource.kt | 3 ++ .../models/streams/sources/IWidevineSource.kt | 9 ++-- .../platforms/js/models/JSRequestExecutor.kt | 6 +-- .../sources/JSAudioUrlWidevineSource.kt | 27 ++++++++--- .../sources/JSDashManifestWidevineSource.kt | 24 +++++++--- .../platforms/js/models/sources/JSSource.kt | 2 + .../sources/JSVideoUrlWidevineSource.kt | 41 ++++++++++++++++ .../platformplayer/casting/StateCasting.kt | 4 +- .../platformplayer/downloads/VideoDownload.kt | 2 +- .../views/video/FutoVideoPlayerBase.kt | 48 +++++++++++++------ .../video/datasources/JSHttpDataSource.java | 2 +- ...mCallback.kt => PluginMediaDrmCallback.kt} | 11 +++-- 13 files changed, 164 insertions(+), 55 deletions(-) create mode 100644 app/src/main/java/com/futo/platformplayer/api/media/models/streams/sources/IVideoUrlWidevineSource.kt create mode 100644 app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSVideoUrlWidevineSource.kt rename app/src/main/java/com/futo/platformplayer/views/video/datasources/{Base64MediaDrmCallback.kt => PluginMediaDrmCallback.kt} (60%) diff --git a/app/src/main/assets/scripts/source.js b/app/src/main/assets/scripts/source.js index 50831cc6..e8df05a1 100644 --- a/app/src/main/assets/scripts/source.js +++ b/app/src/main/assets/scripts/source.js @@ -367,6 +367,16 @@ class VideoUrlSource { this.requestModifier = obj.requestModifier; } } +class VideoUrlWidevineSource extends VideoUrlSource { + constructor(obj) { + super(obj); + this.plugin_type = "VideoUrlWidevineSource"; + + this.licenseUri = obj.licenseUri; + if(obj.getLicenseExecutor) + this.getLicenseExecutor = obj.getLicenseExecutor; + } +} class VideoUrlRangeSource extends VideoUrlSource { constructor(obj) { super(obj); @@ -399,16 +409,26 @@ class AudioUrlWidevineSource extends AudioUrlSource { super(obj); this.plugin_type = "AudioUrlWidevineSource"; + this.licenseUri = obj.licenseUri; + if(obj.getLicenseExecutor) + this.getLicenseExecutor = obj.getLicenseExecutor; + + // deprecated api conversion if(obj.bearerToken) { - this.licenseHeaders = { - Authorization: `Bearer ${obj.bearerToken}` + this.getLicenseExecutor = () => { + return { + executeRequest: (url, _headers, _method, license_request_data) => { + return http.POST( + url, + license_request_data, + { Authorization: `Bearer ${obj.bearerToken}` }, + false, + true + ).body + } + } } } - this.licenseUri = obj.licenseUri; - if(obj.licenseHeaders) { - this.licenseHeaders = obj.licenseHeaders; - } - this.decodeLicenseResponse = obj.decodeLicenseResponse ?? false } } class AudioUrlRangeSource extends AudioUrlSource { @@ -457,10 +477,8 @@ class DashWidevineSource extends DashSource { this.plugin_type = "DashWidevineSource"; this.licenseUri = obj.licenseUri; - if(obj.licenseHeaders) { - this.licenseHeaders = obj.licenseHeaders; - } - this.decodeLicenseResponse = obj.decodeLicenseResponse + if(obj.getLicenseExecutor) + this.getLicenseExecutor = obj.getLicenseExecutor; } } class DashManifestRawSource { diff --git a/app/src/main/java/com/futo/platformplayer/api/media/models/streams/sources/IVideoUrlWidevineSource.kt b/app/src/main/java/com/futo/platformplayer/api/media/models/streams/sources/IVideoUrlWidevineSource.kt new file mode 100644 index 00000000..073af50a --- /dev/null +++ b/app/src/main/java/com/futo/platformplayer/api/media/models/streams/sources/IVideoUrlWidevineSource.kt @@ -0,0 +1,3 @@ +package com.futo.platformplayer.api.media.models.streams.sources + +interface IVideoUrlWidevineSource : IVideoUrlSource, IWidevineSource diff --git a/app/src/main/java/com/futo/platformplayer/api/media/models/streams/sources/IWidevineSource.kt b/app/src/main/java/com/futo/platformplayer/api/media/models/streams/sources/IWidevineSource.kt index 5fbc410f..111fdd18 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/models/streams/sources/IWidevineSource.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/models/streams/sources/IWidevineSource.kt @@ -1,10 +1,9 @@ package com.futo.platformplayer.api.media.models.streams.sources +import com.futo.platformplayer.api.media.platforms.js.models.JSRequestExecutor + interface IWidevineSource { val licenseUri: String - val licenseHeaders: Map? - /** - * Set this to true if the license response is Base64 encoded - */ - val decodeLicenseResponse: Boolean + val hasLicenseExecutor: Boolean + fun getLicenseExecutor(): JSRequestExecutor? } \ No newline at end of file diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSRequestExecutor.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSRequestExecutor.kt index a9ab2c1a..70dfecfd 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSRequestExecutor.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSRequestExecutor.kt @@ -42,7 +42,7 @@ class JSRequestExecutor { //TODO: Executor properties? @Throws(ScriptException::class) - open fun executeRequest(url: String, headers: Map): ByteArray { + open fun executeRequest(method: String, url: String, body: ByteArray?, headers: Map): ByteArray { if (_executor.isClosed) throw IllegalStateException("Executor object is closed"); @@ -53,7 +53,7 @@ class JSRequestExecutor { "[${_config.name}] JSRequestExecutor", "builder.modifyRequest()" ) { - _executor.invoke("executeRequest", url, headers); + _executor.invoke("executeRequest", url, headers, method, body); } as V8Value; } else V8Plugin.catchScriptErrors( @@ -61,7 +61,7 @@ class JSRequestExecutor { "[${_config.name}] JSRequestExecutor", "builder.modifyRequest()" ) { - _executor.invoke("executeRequest", url, headers); + _executor.invoke("executeRequest", url, headers, method, body); } as V8Value; try { diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSAudioUrlWidevineSource.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSAudioUrlWidevineSource.kt index 569432d6..9ae014ca 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSAudioUrlWidevineSource.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSAudioUrlWidevineSource.kt @@ -3,26 +3,39 @@ 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.getOrDefault +import com.futo.platformplayer.api.media.platforms.js.models.JSRequestExecutor +import com.futo.platformplayer.engine.V8Plugin import com.futo.platformplayer.getOrThrow class JSAudioUrlWidevineSource : JSAudioUrlSource, IAudioUrlWidevineSource { - override val licenseHeaders: Map? override val licenseUri: String - override val decodeLicenseResponse: Boolean + override val hasLicenseExecutor: Boolean @Suppress("ConvertSecondaryConstructorToPrimary") constructor(plugin: JSClient, obj: V8ValueObject) : super(plugin, obj) { val contextName = "JSAudioUrlWidevineSource" val config = plugin.config - licenseHeaders = - obj.getOrDefault>(config, "licenseHeaders", contextName, null) + licenseUri = _obj.getOrThrow(config, "licenseUri", contextName) - decodeLicenseResponse = _obj.getOrThrow(config, "decodeLicenseResponse", contextName) + hasLicenseExecutor = obj.has("getLicenseExecutor") + } + + override fun getLicenseExecutor(): JSRequestExecutor? { + if (!hasLicenseExecutor || _obj.isClosed) + return null + + val result = V8Plugin.catchScriptErrors(_config, "[${_config.name}] JSDashManifestWidevineSource", "obj.getLicenseExecutor()") { + _obj.invoke("getLicenseExecutor", arrayOf()) + } + + if (result !is V8ValueObject) + return null + + return JSRequestExecutor(_plugin, result) } override fun toString(): String { val url = getAudioUrl() - return "(name=$name, container=$container, bitrate=$bitrate, codec=$codec, url=$url, language=$language, duration=$duration, licenseHeaders=${licenseHeaders.toString()}, licenseUri=$licenseUri)" + return "(name=$name, container=$container, bitrate=$bitrate, codec=$codec, url=$url, language=$language, duration=$duration, hasLicenseExecutor=${hasLicenseExecutor}, licenseUri=$licenseUri)" } } diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSDashManifestWidevineSource.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSDashManifestWidevineSource.kt index d9fd3bb6..f039978e 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSDashManifestWidevineSource.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSDashManifestWidevineSource.kt @@ -5,7 +5,8 @@ import com.futo.platformplayer.api.media.models.streams.sources.IDashManifestSou import com.futo.platformplayer.api.media.models.streams.sources.IDashManifestWidevineSource import com.futo.platformplayer.api.media.models.streams.sources.IVideoUrlSource import com.futo.platformplayer.api.media.platforms.js.JSClient -import com.futo.platformplayer.getOrDefault +import com.futo.platformplayer.api.media.platforms.js.models.JSRequestExecutor +import com.futo.platformplayer.engine.V8Plugin import com.futo.platformplayer.getOrNull import com.futo.platformplayer.getOrThrow @@ -22,9 +23,8 @@ class JSDashManifestWidevineSource : IVideoUrlSource, IDashManifestSource, override var priority: Boolean = false - override val licenseHeaders: Map? override val licenseUri: String - override val decodeLicenseResponse: Boolean + override val hasLicenseExecutor: Boolean @Suppress("ConvertSecondaryConstructorToPrimary") constructor(plugin: JSClient, obj: V8ValueObject) : super(TYPE_DASH, plugin, obj) { @@ -36,10 +36,22 @@ class JSDashManifestWidevineSource : IVideoUrlSource, IDashManifestSource, priority = obj.getOrNull(config, "priority", contextName) ?: false - licenseHeaders = - obj.getOrDefault>(config, "licenseHeaders", contextName, null) licenseUri = _obj.getOrThrow(config, "licenseUri", contextName) - decodeLicenseResponse = _obj.getOrThrow(config, "decodeLicenseResponse", contextName) + hasLicenseExecutor = obj.has("getLicenseExecutor") + } + + override fun getLicenseExecutor(): JSRequestExecutor? { + if (!hasLicenseExecutor || _obj.isClosed) + return null + + val result = V8Plugin.catchScriptErrors(_config, "[${_config.name}] JSDashManifestWidevineSource", "obj.getLicenseExecutor()") { + _obj.invoke("getLicenseExecutor", arrayOf()) + } + + if (result !is V8ValueObject) + return null + + return JSRequestExecutor(_plugin, result) } override fun getVideoUrl(): String { diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSSource.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSSource.kt index 54f9d7ea..3c76e23d 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSSource.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSSource.kt @@ -103,12 +103,14 @@ abstract class JSSource { const val TYPE_DASH_RAW_AUDIO = "DashRawAudioSource"; const val TYPE_HLS = "HLSSource"; const val TYPE_AUDIOURL_WIDEVINE = "AudioUrlWidevineSource" + const val TYPE_VIDEOURL_WIDEVINE = "VideoUrlWidevineSource" fun fromV8VideoNullable(plugin: JSClient, obj: V8Value?) : IVideoSource? = obj.orNull { fromV8Video(plugin, it as V8ValueObject) }; fun fromV8Video(plugin: JSClient, obj: V8ValueObject) : IVideoSource? { val type = obj.getString("plugin_type"); return when(type) { TYPE_VIDEOURL -> JSVideoUrlSource(plugin, obj); + TYPE_VIDEOURL_WIDEVINE -> JSVideoUrlWidevineSource(plugin, obj); TYPE_VIDEO_WITH_METADATA -> JSVideoUrlRangeSource(plugin, obj); TYPE_HLS -> fromV8HLS(plugin, obj); TYPE_DASH_WIDEVINE -> JSDashManifestWidevineSource(plugin, obj) diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSVideoUrlWidevineSource.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSVideoUrlWidevineSource.kt new file mode 100644 index 00000000..7c3e0e64 --- /dev/null +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSVideoUrlWidevineSource.kt @@ -0,0 +1,41 @@ +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.IVideoUrlWidevineSource +import com.futo.platformplayer.api.media.platforms.js.JSClient +import com.futo.platformplayer.api.media.platforms.js.models.JSRequestExecutor +import com.futo.platformplayer.engine.V8Plugin +import com.futo.platformplayer.getOrThrow + +class JSVideoUrlWidevineSource : JSVideoUrlSource, IVideoUrlWidevineSource { + override val licenseUri: String + override val hasLicenseExecutor: Boolean + + @Suppress("ConvertSecondaryConstructorToPrimary") + constructor(plugin: JSClient, obj: V8ValueObject) : super(plugin, obj) { + val contextName = "JSAudioUrlWidevineSource" + val config = plugin.config + + licenseUri = _obj.getOrThrow(config, "licenseUri", contextName) + hasLicenseExecutor = obj.has("getLicenseExecutor") + } + + override fun getLicenseExecutor(): JSRequestExecutor? { + if (!hasLicenseExecutor || _obj.isClosed) + return null + + val result = V8Plugin.catchScriptErrors(_config, "[${_config.name}] JSDashManifestWidevineSource", "obj.getLicenseExecutor()") { + _obj.invoke("getLicenseExecutor", arrayOf()) + } + + if (result !is V8ValueObject) + return null + + return JSRequestExecutor(_plugin, result) + } + + override fun toString(): String { + val url = getVideoUrl() + return "(width=$width, height=$height, container=$container, codec=$codec, name=$name, bitrate=$bitrate, duration=$duration, url=$url, hasLicenseExecutor=$hasLicenseExecutor, licenseUri=$licenseUri)" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/futo/platformplayer/casting/StateCasting.kt b/app/src/main/java/com/futo/platformplayer/casting/StateCasting.kt index 23a9c5a5..db2e231b 100644 --- a/app/src/main/java/com/futo/platformplayer/casting/StateCasting.kt +++ b/app/src/main/java/com/futo/platformplayer/casting/StateCasting.kt @@ -1245,7 +1245,7 @@ class StateCasting { val videoExecutor = _videoExecutor; if (videoExecutor != null) { - val data = videoExecutor.executeRequest(originalUrl, httpContext.headers) + val data = videoExecutor.executeRequest("GET", originalUrl, null, httpContext.headers) httpContext.respondBytes(200, HttpHeaders().apply { put("Content-Type", mediaType) }, data); @@ -1263,7 +1263,7 @@ class StateCasting { val audioExecutor = _audioExecutor; if (audioExecutor != null) { - val data = audioExecutor.executeRequest(originalUrl, httpContext.headers) + val data = audioExecutor.executeRequest("GET", originalUrl, null, httpContext.headers) httpContext.respondBytes(200, HttpHeaders().apply { put("Content-Type", mediaType) }, data); diff --git a/app/src/main/java/com/futo/platformplayer/downloads/VideoDownload.kt b/app/src/main/java/com/futo/platformplayer/downloads/VideoDownload.kt index debcd660..e4e9bedb 100644 --- a/app/src/main/java/com/futo/platformplayer/downloads/VideoDownload.kt +++ b/app/src/main/java/com/futo/platformplayer/downloads/VideoDownload.kt @@ -663,7 +663,7 @@ class VideoDownload { val url = foundTemplateUrl.replace("\$Number\$", indexCounter.toString()); val data = if(executor != null) - executor.executeRequest(url, mapOf()); + executor.executeRequest("GET", url, null, mapOf()); else { val resp = client.get(url, mutableMapOf()); if(!resp.isOk) diff --git a/app/src/main/java/com/futo/platformplayer/views/video/FutoVideoPlayerBase.kt b/app/src/main/java/com/futo/platformplayer/views/video/FutoVideoPlayerBase.kt index 4fcf5a3f..c4d94b7d 100644 --- a/app/src/main/java/com/futo/platformplayer/views/video/FutoVideoPlayerBase.kt +++ b/app/src/main/java/com/futo/platformplayer/views/video/FutoVideoPlayerBase.kt @@ -40,6 +40,7 @@ import com.futo.platformplayer.api.media.models.streams.sources.IHLSManifestAudi import com.futo.platformplayer.api.media.models.streams.sources.IHLSManifestSource import com.futo.platformplayer.api.media.models.streams.sources.IVideoSource import com.futo.platformplayer.api.media.models.streams.sources.IVideoUrlSource +import com.futo.platformplayer.api.media.models.streams.sources.IVideoUrlWidevineSource import com.futo.platformplayer.api.media.models.streams.sources.LocalAudioSource import com.futo.platformplayer.api.media.models.streams.sources.LocalVideoSource import com.futo.platformplayer.api.media.models.subtitles.ISubtitleSource @@ -56,7 +57,7 @@ import com.futo.platformplayer.helpers.VideoHelper import com.futo.platformplayer.logging.Logger import com.futo.platformplayer.states.StateApp import com.futo.platformplayer.video.PlayerManager -import com.futo.platformplayer.views.video.datasources.Base64MediaDrmCallback +import com.futo.platformplayer.views.video.datasources.PluginMediaDrmCallback import com.futo.platformplayer.views.video.datasources.JSHttpDataSource import getHttpDataSourceFactory import kotlinx.coroutines.CoroutineScope @@ -415,6 +416,7 @@ abstract class FutoVideoPlayerBase : RelativeLayout { is IDashManifestSource -> { swapVideoSourceDash(videoSource); true;} is JSDashManifestRawSource -> swapVideoSourceDashRaw(videoSource, play, resume); is IHLSManifestSource -> { swapVideoSourceHLS(videoSource); true; } + is IVideoUrlWidevineSource -> { swapVideoSourceUrlWidevine(videoSource); true; } is IVideoUrlSource -> { swapVideoSourceUrl(videoSource); true; } null -> { _lastVideoMediaSource = null; true;} else -> throw IllegalArgumentException("Unsupported video source [${videoSource.javaClass.simpleName}]"); @@ -479,6 +481,32 @@ abstract class FutoVideoPlayerBase : RelativeLayout { .createMediaSource(MediaItem.fromUri(videoSource.getVideoUrl())); } @OptIn(UnstableApi::class) + private fun swapVideoSourceUrlWidevine(videoSource: IVideoUrlWidevineSource) { + Logger.i(TAG, "Loading VideoSource [UrlWidevine]"); + val dataSource = if(videoSource is JSSource && videoSource.requiresCustomDatasource) + videoSource.getHttpDataSourceFactory() + else + DefaultHttpDataSource.Factory().setUserAgent(DEFAULT_USER_AGENT) + + val baseCallback = HttpMediaDrmCallback(videoSource.licenseUri, dataSource) + + val callback = if (videoSource.hasLicenseExecutor) { + PluginMediaDrmCallback(baseCallback, videoSource.getLicenseExecutor()!!, videoSource.licenseUri) + } else { + baseCallback + } + + _lastVideoMediaSource = ProgressiveMediaSource.Factory(dataSource) + .setDrmSessionManagerProvider { + DefaultDrmSessionManager.Builder() + .setMultiSession(true) + .build(callback) + } + .createMediaSource( + MediaItem.fromUri(videoSource.getVideoUrl()) + ) + } + @OptIn(UnstableApi::class) private fun swapVideoSourceDash(videoSource: IDashManifestSource) { Logger.i(TAG, "Loading VideoSource [Dash]"); val dataSource = if(videoSource is JSSource && (videoSource.requiresCustomDatasource)) @@ -497,12 +525,8 @@ abstract class FutoVideoPlayerBase : RelativeLayout { val baseCallback = HttpMediaDrmCallback(videoSource.licenseUri, dataSource) - videoSource.licenseHeaders?.forEach { (key, value) -> - baseCallback.setKeyRequestProperty(key, value) - } - - val callback = if (videoSource.decodeLicenseResponse) { - Base64MediaDrmCallback(baseCallback) + val callback = if (videoSource.hasLicenseExecutor) { + PluginMediaDrmCallback(baseCallback, videoSource.getLicenseExecutor()!!, videoSource.licenseUri) } else { baseCallback } @@ -668,13 +692,9 @@ abstract class FutoVideoPlayerBase : RelativeLayout { val baseCallback = HttpMediaDrmCallback(audioSource.licenseUri, dataSource) - audioSource.licenseHeaders?.forEach { (key, value) -> - baseCallback.setKeyRequestProperty(key, value) - } - - val callback = if(audioSource.decodeLicenseResponse){ - Base64MediaDrmCallback(baseCallback) - }else{ + val callback = if (audioSource.hasLicenseExecutor) { + PluginMediaDrmCallback(baseCallback, audioSource.getLicenseExecutor()!!, audioSource.licenseUri) + } else { baseCallback } diff --git a/app/src/main/java/com/futo/platformplayer/views/video/datasources/JSHttpDataSource.java b/app/src/main/java/com/futo/platformplayer/views/video/datasources/JSHttpDataSource.java index 40e1a503..859c1b2f 100644 --- a/app/src/main/java/com/futo/platformplayer/views/video/datasources/JSHttpDataSource.java +++ b/app/src/main/java/com/futo/platformplayer/views/video/datasources/JSHttpDataSource.java @@ -360,7 +360,7 @@ public class JSHttpDataSource extends BaseDataSource implements HttpDataSource { if(executor != null) { try { Logger.Companion.i(TAG, "Executor for " + dataSpec.uri.toString(), null); - byte[] data = executor.executeRequest(dataSpec.uri.toString(), dataSpec.httpRequestHeaders); + byte[] data = executor.executeRequest("GET", dataSpec.uri.toString(), null, dataSpec.httpRequestHeaders); Logger.Companion.i(TAG, "Executor result for " + dataSpec.uri.toString() + " : " + data.length, null); if (data == null) throw new HttpDataSourceException( diff --git a/app/src/main/java/com/futo/platformplayer/views/video/datasources/Base64MediaDrmCallback.kt b/app/src/main/java/com/futo/platformplayer/views/video/datasources/PluginMediaDrmCallback.kt similarity index 60% rename from app/src/main/java/com/futo/platformplayer/views/video/datasources/Base64MediaDrmCallback.kt rename to app/src/main/java/com/futo/platformplayer/views/video/datasources/PluginMediaDrmCallback.kt index eda67a73..2fa5dbb7 100644 --- a/app/src/main/java/com/futo/platformplayer/views/video/datasources/Base64MediaDrmCallback.kt +++ b/app/src/main/java/com/futo/platformplayer/views/video/datasources/PluginMediaDrmCallback.kt @@ -3,20 +3,21 @@ package com.futo.platformplayer.views.video.datasources import androidx.media3.common.util.UnstableApi import androidx.media3.exoplayer.drm.ExoMediaDrm import androidx.media3.exoplayer.drm.MediaDrmCallback +import com.futo.platformplayer.api.media.platforms.js.models.JSRequestExecutor import java.util.UUID -import kotlin.io.encoding.Base64 import kotlin.io.encoding.ExperimentalEncodingApi @UnstableApi -class Base64MediaDrmCallback( +class PluginMediaDrmCallback( private val delegate: MediaDrmCallback, + private val requestExecutor: JSRequestExecutor, + private val licenseUrl: String ) : MediaDrmCallback by delegate { @ExperimentalEncodingApi override fun executeKeyRequest(uuid: UUID, request: ExoMediaDrm.KeyRequest): ByteArray { - val originalResponse = delegate.executeKeyRequest(uuid, request) - val decodedData: ByteArray = Base64.decode(originalResponse) + val pluginResponse = requestExecutor.executeRequest("POST", licenseUrl, request.data, mapOf()) - return decodedData + return pluginResponse } }