mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
DONT UPDATE TO THIS IF YOU WANT A WORKING APP
extreme player fuckery
This commit is contained in:
parent
9db6206e68
commit
0849bffe49
2 changed files with 146 additions and 72 deletions
|
@ -7,9 +7,13 @@ import android.util.Log
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import com.google.android.exoplayer2.*
|
import com.google.android.exoplayer2.*
|
||||||
import com.google.android.exoplayer2.database.StandaloneDatabaseProvider
|
import com.google.android.exoplayer2.database.StandaloneDatabaseProvider
|
||||||
|
import com.google.android.exoplayer2.extractor.ExtractorsFactory
|
||||||
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory
|
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory
|
||||||
import com.google.android.exoplayer2.source.MergingMediaSource
|
import com.google.android.exoplayer2.source.MergingMediaSource
|
||||||
|
import com.google.android.exoplayer2.source.ProgressiveMediaSource
|
||||||
import com.google.android.exoplayer2.source.SingleSampleMediaSource
|
import com.google.android.exoplayer2.source.SingleSampleMediaSource
|
||||||
|
import com.google.android.exoplayer2.text.SubtitleDecoderFactory
|
||||||
|
import com.google.android.exoplayer2.text.SubtitleExtractor
|
||||||
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector
|
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector
|
||||||
import com.google.android.exoplayer2.trackselection.TrackSelector
|
import com.google.android.exoplayer2.trackselection.TrackSelector
|
||||||
import com.google.android.exoplayer2.ui.SubtitleView
|
import com.google.android.exoplayer2.ui.SubtitleView
|
||||||
|
@ -367,7 +371,7 @@ class CS3IPlayer : IPlayer {
|
||||||
private fun buildExoPlayer(
|
private fun buildExoPlayer(
|
||||||
context: Context,
|
context: Context,
|
||||||
mediaItem: MediaItem,
|
mediaItem: MediaItem,
|
||||||
subSources: List<SingleSampleMediaSource>,
|
subSources: List<ProgressiveMediaSource>,
|
||||||
currentWindow: Int,
|
currentWindow: Int,
|
||||||
playbackPosition: Long,
|
playbackPosition: Long,
|
||||||
playBackSpeed: Float,
|
playBackSpeed: Float,
|
||||||
|
@ -466,7 +470,7 @@ class CS3IPlayer : IPlayer {
|
||||||
private fun loadExo(
|
private fun loadExo(
|
||||||
context: Context,
|
context: Context,
|
||||||
mediaItem: MediaItem,
|
mediaItem: MediaItem,
|
||||||
subSources: List<SingleSampleMediaSource>,
|
subSources: List<ProgressiveMediaSource>,
|
||||||
cacheFactory: CacheDataSource.Factory? = null
|
cacheFactory: CacheDataSource.Factory? = null
|
||||||
) {
|
) {
|
||||||
Log.i(TAG, "loadExo")
|
Log.i(TAG, "loadExo")
|
||||||
|
@ -579,6 +583,39 @@ class CS3IPlayer : IPlayer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://github.com/google/ExoPlayer/blob/029a2b27cbdc27cf9d51d4a73ebeb503968849f6/library/core/src/main/java/com/google/android/exoplayer2/source/DefaultMediaSourceFactory.java
|
||||||
|
* */
|
||||||
|
private fun createProgressiveMediaSources(
|
||||||
|
subSources: List<SingleSampleMediaSource>,
|
||||||
|
factory: DataSource.Factory
|
||||||
|
): List<ProgressiveMediaSource> {
|
||||||
|
val extractorFactory = ExtractorsFactory {
|
||||||
|
subSources.map {
|
||||||
|
val currentSub = it.mediaItem.localConfiguration?.subtitleConfigurations?.firstOrNull()
|
||||||
|
val format = Format.Builder()
|
||||||
|
.setSampleMimeType(currentSub?.mimeType)
|
||||||
|
.setLanguage(currentSub?.language)
|
||||||
|
.setLabel(currentSub?.label)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
SubtitleExtractor(
|
||||||
|
CustomSubtitleDecoderFactory().createDecoder(format), format
|
||||||
|
)
|
||||||
|
}.toTypedArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
return subSources.mapNotNull {
|
||||||
|
val uri = it.mediaItem.localConfiguration?.subtitleConfigurations?.firstOrNull()?.uri ?: return@mapNotNull null
|
||||||
|
if (uri.toString().isBlank()) return@mapNotNull null
|
||||||
|
|
||||||
|
ProgressiveMediaSource.Factory(factory, extractorFactory)
|
||||||
|
.createMediaSource(
|
||||||
|
MediaItem.fromUri(uri)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun loadOfflinePlayer(context: Context, data: ExtractorUri) {
|
private fun loadOfflinePlayer(context: Context, data: ExtractorUri) {
|
||||||
Log.i(TAG, "loadOfflinePlayer")
|
Log.i(TAG, "loadOfflinePlayer")
|
||||||
try {
|
try {
|
||||||
|
@ -591,8 +628,12 @@ class CS3IPlayer : IPlayer {
|
||||||
offlineSourceFactory,
|
offlineSourceFactory,
|
||||||
subtitleHelper
|
subtitleHelper
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val progressiveMediaSources =
|
||||||
|
createProgressiveMediaSources(subSources, offlineSourceFactory)
|
||||||
|
|
||||||
subtitleHelper.setActiveSubtitles(activeSubtitles.toSet())
|
subtitleHelper.setActiveSubtitles(activeSubtitles.toSet())
|
||||||
loadExo(context, mediaItem, subSources)
|
loadExo(context, mediaItem, progressiveMediaSources)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, "loadOfflinePlayer error", e)
|
Log.e(TAG, "loadOfflinePlayer error", e)
|
||||||
playerError?.invoke(e)
|
playerError?.invoke(e)
|
||||||
|
@ -630,6 +671,10 @@ class CS3IPlayer : IPlayer {
|
||||||
offlineSourceFactory,
|
offlineSourceFactory,
|
||||||
subtitleHelper
|
subtitleHelper
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val progressiveMediaSources =
|
||||||
|
createProgressiveMediaSources(subSources, onlineSourceFactory)
|
||||||
|
|
||||||
subtitleHelper.setActiveSubtitles(activeSubtitles.toSet())
|
subtitleHelper.setActiveSubtitles(activeSubtitles.toSet())
|
||||||
|
|
||||||
if (simpleCache == null)
|
if (simpleCache == null)
|
||||||
|
@ -640,7 +685,7 @@ class CS3IPlayer : IPlayer {
|
||||||
setUpstreamDataSourceFactory(onlineSourceFactory)
|
setUpstreamDataSourceFactory(onlineSourceFactory)
|
||||||
}
|
}
|
||||||
|
|
||||||
loadExo(context, mediaItem, subSources, cacheFactory)
|
loadExo(context, mediaItem, progressiveMediaSources, cacheFactory)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, "loadOnlinePlayer error", e)
|
Log.e(TAG, "loadOnlinePlayer error", e)
|
||||||
playerError?.invoke(e)
|
playerError?.invoke(e)
|
||||||
|
|
|
@ -1,49 +1,77 @@
|
||||||
package com.lagradost.cloudstream3.ui.player
|
package com.lagradost.cloudstream3.ui.player
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import com.google.android.exoplayer2.Format
|
import com.google.android.exoplayer2.Format
|
||||||
import com.google.android.exoplayer2.text.*
|
import com.google.android.exoplayer2.text.*
|
||||||
import com.google.android.exoplayer2.util.MimeTypes
|
|
||||||
import com.google.android.exoplayer2.text.webvtt.WebvttDecoder
|
|
||||||
import com.google.android.exoplayer2.text.ssa.SsaDecoder
|
import com.google.android.exoplayer2.text.ssa.SsaDecoder
|
||||||
import com.google.android.exoplayer2.text.webvtt.Mp4WebvttDecoder
|
|
||||||
import com.google.android.exoplayer2.text.ttml.TtmlDecoder
|
|
||||||
import com.google.android.exoplayer2.text.subrip.SubripDecoder
|
import com.google.android.exoplayer2.text.subrip.SubripDecoder
|
||||||
import com.google.android.exoplayer2.text.tx3g.Tx3gDecoder
|
import com.google.android.exoplayer2.text.ttml.TtmlDecoder
|
||||||
import com.google.android.exoplayer2.text.cea.Cea608Decoder
|
import com.google.android.exoplayer2.text.webvtt.WebvttDecoder
|
||||||
import com.google.android.exoplayer2.text.cea.Cea708Decoder
|
import com.google.android.exoplayer2.util.MimeTypes
|
||||||
import com.google.android.exoplayer2.text.dvb.DvbDecoder
|
import okio.ByteString.Companion.toByteString
|
||||||
import com.google.android.exoplayer2.text.pgs.PgsDecoder
|
import java.nio.charset.Charset
|
||||||
import java.lang.IllegalArgumentException
|
|
||||||
|
|
||||||
//class CustomDecoder : SubtitleDecoder {
|
|
||||||
// override fun getName(): String {
|
class CustomDecoder : SubtitleDecoder {
|
||||||
//
|
|
||||||
// }
|
companion object {
|
||||||
//
|
private const val TAG = "CustomDecoder"
|
||||||
// override fun dequeueInputBuffer(): SubtitleInputBuffer? {
|
}
|
||||||
//
|
|
||||||
// }
|
var realDecoder: SimpleSubtitleDecoder? = null
|
||||||
//
|
|
||||||
// override fun queueInputBuffer(inputBuffer: SubtitleInputBuffer) {
|
override fun getName(): String {
|
||||||
//
|
return realDecoder?.name ?: this::class.java.name
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// override fun dequeueOutputBuffer(): SubtitleOutputBuffer? {
|
override fun dequeueInputBuffer(): SubtitleInputBuffer {
|
||||||
//
|
return realDecoder?.dequeueInputBuffer() ?: SubtitleInputBuffer()
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// override fun flush() {
|
override fun queueInputBuffer(inputBuffer: SubtitleInputBuffer) {
|
||||||
//
|
println("STARTTT ${inputBuffer.format?.language}")
|
||||||
// }
|
if (realDecoder == null)
|
||||||
//
|
inputBuffer.data?.let { data ->
|
||||||
// override fun release() {
|
|
||||||
//
|
val pos = data.position()
|
||||||
// }
|
data.position(0)
|
||||||
//
|
val arr = ByteArray(minOf(data.remaining(), 100))
|
||||||
// override fun setPositionUs(positionUs: Long) {
|
data.get(arr)
|
||||||
//
|
data.position(pos)
|
||||||
// }
|
|
||||||
//}
|
val str = arr.decodeToString().trimStart()
|
||||||
|
Log.i(TAG, "Got data from queueInputBuffer")
|
||||||
|
Log.i(TAG, "first string is $str")
|
||||||
|
|
||||||
|
//https://github.com/LagradOst/CloudStream-2/blob/ddd774ee66810137ff7bd65dae70bcf3ba2d2489/CloudStreamForms/CloudStreamForms/Script/MainChrome.cs#L388
|
||||||
|
realDecoder = when {
|
||||||
|
str.startsWith("WEBVTT") -> WebvttDecoder()
|
||||||
|
str.startsWith("<?xml version=\"") -> TtmlDecoder()
|
||||||
|
str.startsWith("[Script Info]") || str.startsWith("Title:") -> SsaDecoder()
|
||||||
|
str.startsWith("1") -> SubripDecoder()
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
realDecoder?.dequeueInputBuffer().also { println("RETURNED ddddd") }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dequeueOutputBuffer(): SubtitleOutputBuffer? {
|
||||||
|
return realDecoder?.dequeueOutputBuffer()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun flush() {
|
||||||
|
realDecoder?.flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun release() {
|
||||||
|
realDecoder?.release()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setPositionUs(positionUs: Long) {
|
||||||
|
realDecoder?.setPositionUs(positionUs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** See https://github.com/google/ExoPlayer/blob/release-v2/library/core/src/main/java/com/google/android/exoplayer2/text/SubtitleDecoderFactory.java */
|
/** See https://github.com/google/ExoPlayer/blob/release-v2/library/core/src/main/java/com/google/android/exoplayer2/text/SubtitleDecoderFactory.java */
|
||||||
class CustomSubtitleDecoderFactory : SubtitleDecoderFactory {
|
class CustomSubtitleDecoderFactory : SubtitleDecoderFactory {
|
||||||
|
@ -55,38 +83,39 @@ class CustomSubtitleDecoderFactory : SubtitleDecoderFactory {
|
||||||
MimeTypes.APPLICATION_TTML,
|
MimeTypes.APPLICATION_TTML,
|
||||||
MimeTypes.APPLICATION_MP4VTT,
|
MimeTypes.APPLICATION_MP4VTT,
|
||||||
MimeTypes.APPLICATION_SUBRIP,
|
MimeTypes.APPLICATION_SUBRIP,
|
||||||
MimeTypes.APPLICATION_TX3G,
|
//MimeTypes.APPLICATION_TX3G,
|
||||||
MimeTypes.APPLICATION_CEA608,
|
//MimeTypes.APPLICATION_CEA608,
|
||||||
MimeTypes.APPLICATION_MP4CEA608,
|
//MimeTypes.APPLICATION_MP4CEA608,
|
||||||
MimeTypes.APPLICATION_CEA708,
|
//MimeTypes.APPLICATION_CEA708,
|
||||||
MimeTypes.APPLICATION_DVBSUBS,
|
//MimeTypes.APPLICATION_DVBSUBS,
|
||||||
MimeTypes.APPLICATION_PGS,
|
//MimeTypes.APPLICATION_PGS,
|
||||||
MimeTypes.TEXT_EXOPLAYER_CUES
|
//MimeTypes.TEXT_EXOPLAYER_CUES
|
||||||
).contains(format.sampleMimeType)
|
).contains(format.sampleMimeType)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createDecoder(format: Format): SubtitleDecoder {
|
override fun createDecoder(format: Format): SubtitleDecoder {
|
||||||
return when (val mimeType = format.sampleMimeType) {
|
return CustomDecoder()
|
||||||
MimeTypes.TEXT_VTT -> WebvttDecoder()
|
//return when (val mimeType = format.sampleMimeType) {
|
||||||
MimeTypes.TEXT_SSA -> SsaDecoder(format.initializationData)
|
// MimeTypes.TEXT_VTT -> WebvttDecoder()
|
||||||
MimeTypes.APPLICATION_MP4VTT -> Mp4WebvttDecoder()
|
// MimeTypes.TEXT_SSA -> SsaDecoder(format.initializationData)
|
||||||
MimeTypes.APPLICATION_TTML -> TtmlDecoder()
|
// MimeTypes.APPLICATION_MP4VTT -> Mp4WebvttDecoder()
|
||||||
MimeTypes.APPLICATION_SUBRIP -> SubripDecoder()
|
// MimeTypes.APPLICATION_TTML -> TtmlDecoder()
|
||||||
MimeTypes.APPLICATION_TX3G -> Tx3gDecoder(format.initializationData)
|
// MimeTypes.APPLICATION_SUBRIP -> SubripDecoder()
|
||||||
MimeTypes.APPLICATION_CEA608, MimeTypes.APPLICATION_MP4CEA608 -> return Cea608Decoder(
|
// MimeTypes.APPLICATION_TX3G -> Tx3gDecoder(format.initializationData)
|
||||||
mimeType,
|
// MimeTypes.APPLICATION_CEA608, MimeTypes.APPLICATION_MP4CEA608 -> return Cea608Decoder(
|
||||||
format.accessibilityChannel,
|
// mimeType,
|
||||||
Cea608Decoder.MIN_DATA_CHANNEL_TIMEOUT_MS
|
// format.accessibilityChannel,
|
||||||
)
|
// Cea608Decoder.MIN_DATA_CHANNEL_TIMEOUT_MS
|
||||||
MimeTypes.APPLICATION_CEA708 -> Cea708Decoder(
|
// )
|
||||||
format.accessibilityChannel,
|
// MimeTypes.APPLICATION_CEA708 -> Cea708Decoder(
|
||||||
format.initializationData
|
// format.accessibilityChannel,
|
||||||
)
|
// format.initializationData
|
||||||
MimeTypes.APPLICATION_DVBSUBS -> DvbDecoder(format.initializationData)
|
// )
|
||||||
MimeTypes.APPLICATION_PGS -> PgsDecoder()
|
// MimeTypes.APPLICATION_DVBSUBS -> DvbDecoder(format.initializationData)
|
||||||
MimeTypes.TEXT_EXOPLAYER_CUES -> ExoplayerCuesDecoder()
|
// MimeTypes.APPLICATION_PGS -> PgsDecoder()
|
||||||
// Default WebVttDecoder
|
// MimeTypes.TEXT_EXOPLAYER_CUES -> ExoplayerCuesDecoder()
|
||||||
else -> WebvttDecoder()
|
// // Default WebVttDecoder
|
||||||
}
|
// else -> WebvttDecoder()
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue