Better source swapping for lazily generated sources

This commit is contained in:
Kelvin 2024-08-22 22:47:47 +02:00
commit 721b7dbba0
2 changed files with 52 additions and 32 deletions

View file

@ -338,24 +338,30 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
audioSourceUsed = null; audioSourceUsed = null;
} }
swapSourceInternal(videoSourceUsed); val didSetVideo = swapSourceInternal(videoSourceUsed, play, resume);
swapSourceInternal(audioSourceUsed); val didSetAudio = swapSourceInternal(audioSourceUsed, play, resume);
if(!keepSubtitles) if(!keepSubtitles)
_lastSubtitleMediaSource = null; _lastSubtitleMediaSource = null;
if(didSetVideo && didSetAudio)
return loadSelectedSources(play, resume); return loadSelectedSources(play, resume);
else
return true;
} }
fun swapSource(videoSource: IVideoSource?, resume: Boolean = true, play: Boolean = true): Boolean { fun swapSource(videoSource: IVideoSource?, resume: Boolean = true, play: Boolean = true): Boolean {
var videoSourceUsed = videoSource; var videoSourceUsed = videoSource;
if(videoSource is JSDashManifestRawSource && lastVideoSource is JSDashManifestMergingRawSource) if(videoSource is JSDashManifestRawSource && lastVideoSource is JSDashManifestMergingRawSource)
videoSourceUsed = JSDashManifestMergingRawSource(videoSource, (lastVideoSource as JSDashManifestMergingRawSource).audio); videoSourceUsed = JSDashManifestMergingRawSource(videoSource, (lastVideoSource as JSDashManifestMergingRawSource).audio);
swapSourceInternal(videoSourceUsed); val didSet = swapSourceInternal(videoSourceUsed, play, resume);
if(didSet)
return loadSelectedSources(play, resume); return loadSelectedSources(play, resume);
else
return true;
} }
fun swapSource(audioSource: IAudioSource?, resume: Boolean = true, play: Boolean = true): Boolean { fun swapSource(audioSource: IAudioSource?, resume: Boolean = true, play: Boolean = true): Boolean {
if(audioSource is JSDashManifestRawAudioSource && lastVideoSource is JSDashManifestMergingRawSource) if(audioSource is JSDashManifestRawAudioSource && lastVideoSource is JSDashManifestMergingRawSource)
swapSourceInternal(JSDashManifestMergingRawSource((lastVideoSource as JSDashManifestMergingRawSource).video, audioSource)); swapSourceInternal(JSDashManifestMergingRawSource((lastVideoSource as JSDashManifestMergingRawSource).video, audioSource), play, resume);
else else
swapSourceInternal(audioSource); swapSourceInternal(audioSource, play, resume);
return loadSelectedSources(play, resume); return loadSelectedSources(play, resume);
} }
@ -406,32 +412,34 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
} }
private fun swapSourceInternal(videoSource: IVideoSource?) { private fun swapSourceInternal(videoSource: IVideoSource?, play: Boolean, resume: Boolean): Boolean {
_lastGeneratedDash = null; _lastGeneratedDash = null;
when(videoSource) { val didSet = when(videoSource) {
is LocalVideoSource -> swapVideoSourceLocal(videoSource); is LocalVideoSource -> { swapVideoSourceLocal(videoSource); true; }
is JSVideoUrlRangeSource -> swapVideoSourceUrlRange(videoSource); is JSVideoUrlRangeSource -> { swapVideoSourceUrlRange(videoSource); true; }
is IDashManifestSource -> swapVideoSourceDash(videoSource); is IDashManifestSource -> { swapVideoSourceDash(videoSource); true;}
is JSDashManifestRawSource -> swapVideoSourceDashRaw(videoSource); is JSDashManifestRawSource -> swapVideoSourceDashRaw(videoSource, play, resume);
is IHLSManifestSource -> swapVideoSourceHLS(videoSource); is IHLSManifestSource -> { swapVideoSourceHLS(videoSource); true; }
is IVideoUrlSource -> swapVideoSourceUrl(videoSource); is IVideoUrlSource -> { swapVideoSourceUrl(videoSource); true; }
null -> _lastVideoMediaSource = null; null -> { _lastVideoMediaSource = null; true;}
else -> throw IllegalArgumentException("Unsupported video source [${videoSource.javaClass.simpleName}]"); else -> throw IllegalArgumentException("Unsupported video source [${videoSource.javaClass.simpleName}]");
} }
lastVideoSource = videoSource; lastVideoSource = videoSource;
return didSet;
} }
private fun swapSourceInternal(audioSource: IAudioSource?) { private fun swapSourceInternal(audioSource: IAudioSource?, play: Boolean, resume: Boolean): Boolean {
when(audioSource) { val didSet = when(audioSource) {
is LocalAudioSource -> swapAudioSourceLocal(audioSource); is LocalAudioSource -> {swapAudioSourceLocal(audioSource); true; }
is JSAudioUrlRangeSource -> swapAudioSourceUrlRange(audioSource); is JSAudioUrlRangeSource -> { swapAudioSourceUrlRange(audioSource); true; }
is JSHLSManifestAudioSource -> swapAudioSourceHLS(audioSource); is JSHLSManifestAudioSource -> { swapAudioSourceHLS(audioSource); true; }
is JSDashManifestRawAudioSource -> swapAudioSourceDashRaw(audioSource); is JSDashManifestRawAudioSource -> swapAudioSourceDashRaw(audioSource, play, resume);
is IAudioUrlWidevineSource -> swapAudioSourceUrlWidevine(audioSource) is IAudioUrlWidevineSource -> { swapAudioSourceUrlWidevine(audioSource); true; }
is IAudioUrlSource -> swapAudioSourceUrl(audioSource); is IAudioUrlSource -> { swapAudioSourceUrl(audioSource); true; }
null -> _lastAudioMediaSource = null; null -> { _lastAudioMediaSource = null; true; }
else -> throw IllegalArgumentException("Unsupported video source [${audioSource.javaClass.simpleName}]"); else -> throw IllegalArgumentException("Unsupported video source [${audioSource.javaClass.simpleName}]");
} }
lastAudioSource = audioSource; lastAudioSource = audioSource;
return didSet;
} }
//Video loads //Video loads
@ -486,7 +494,7 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
.createMediaSource(MediaItem.fromUri(videoSource.url)) .createMediaSource(MediaItem.fromUri(videoSource.url))
} }
@OptIn(UnstableApi::class) @OptIn(UnstableApi::class)
private fun swapVideoSourceDashRaw(videoSource: JSDashManifestRawSource) { private fun swapVideoSourceDashRaw(videoSource: JSDashManifestRawSource, play: Boolean, resume: Boolean): Boolean {
Logger.i(TAG, "Loading VideoSource [Dash]"); Logger.i(TAG, "Loading VideoSource [Dash]");
if(videoSource.hasGenerate) { if(videoSource.hasGenerate) {
@ -511,7 +519,8 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
) )
) )
); );
loadSelectedSources(true, false); if(lastVideoSource == videoSource || (videoSource is JSDashManifestMergingRawSource && videoSource.video == lastVideoSource));
loadSelectedSources(play, resume);
} }
} }
} }
@ -519,6 +528,7 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
Logger.e(TAG, "DashRaw generator failed", ex); Logger.e(TAG, "DashRaw generator failed", ex);
} }
} }
return false;
} }
else { else {
val dataSource = if(videoSource is JSSource && (videoSource.requiresCustomDatasource)) val dataSource = if(videoSource is JSSource && (videoSource.requiresCustomDatasource))
@ -531,6 +541,7 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
_lastVideoMediaSource = DashMediaSource.Factory(dataSource) _lastVideoMediaSource = DashMediaSource.Factory(dataSource)
.createMediaSource(DashManifestParser().parse(Uri.parse(videoSource.url), .createMediaSource(DashManifestParser().parse(Uri.parse(videoSource.url),
ByteArrayInputStream(videoSource.manifest?.toByteArray() ?: ByteArray(0)))); ByteArrayInputStream(videoSource.manifest?.toByteArray() ?: ByteArray(0))));
return true;
} }
} }
@OptIn(UnstableApi::class) @OptIn(UnstableApi::class)
@ -597,7 +608,7 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
} }
@OptIn(UnstableApi::class) @OptIn(UnstableApi::class)
private fun swapAudioSourceDashRaw(audioSource: JSDashManifestRawAudioSource) { private fun swapAudioSourceDashRaw(audioSource: JSDashManifestRawAudioSource, play: Boolean, resume: Boolean): Boolean {
Logger.i(TAG, "Loading AudioSource [DashRaw]"); Logger.i(TAG, "Loading AudioSource [DashRaw]");
val dataSource = if(audioSource is JSSource && (audioSource.requiresCustomDatasource)) val dataSource = if(audioSource is JSSource && (audioSource.requiresCustomDatasource))
audioSource.getHttpDataSourceFactory() audioSource.getHttpDataSourceFactory()
@ -611,15 +622,22 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
_lastVideoMediaSource = DashMediaSource.Factory(dataSource) _lastVideoMediaSource = DashMediaSource.Factory(dataSource)
.createMediaSource(DashManifestParser().parse(Uri.parse(audioSource.url), .createMediaSource(DashManifestParser().parse(Uri.parse(audioSource.url),
ByteArrayInputStream(generated?.toByteArray() ?: ByteArray(0)))); ByteArrayInputStream(generated?.toByteArray() ?: ByteArray(0))));
loadSelectedSources(true, false); loadSelectedSources(play, resume);
} }
} }
} }
return false;
} }
else else {
_lastVideoMediaSource = DashMediaSource.Factory(dataSource) _lastVideoMediaSource = DashMediaSource.Factory(dataSource)
.createMediaSource(DashManifestParser().parse(Uri.parse(audioSource.url), .createMediaSource(
ByteArrayInputStream(audioSource.manifest?.toByteArray() ?: ByteArray(0)))); DashManifestParser().parse(
Uri.parse(audioSource.url),
ByteArrayInputStream(audioSource.manifest?.toByteArray() ?: ByteArray(0))
)
);
return true;
}
} }
@OptIn(UnstableApi::class) @OptIn(UnstableApi::class)
private fun swapAudioSourceUrlWidevine(audioSource: IAudioUrlWidevineSource) { private fun swapAudioSourceUrlWidevine(audioSource: IAudioUrlWidevineSource) {

View file

@ -359,7 +359,9 @@ public class JSHttpDataSource extends BaseDataSource implements HttpDataSource {
if(executor != null) { if(executor != null) {
try { try {
Logger.Companion.i(TAG, "Executor for " + dataSpec.uri.toString(), null);
byte[] data = executor.executeRequest(dataSpec.uri.toString(), dataSpec.httpRequestHeaders); byte[] data = executor.executeRequest(dataSpec.uri.toString(), dataSpec.httpRequestHeaders);
Logger.Companion.i(TAG, "Executor result for " + dataSpec.uri.toString() + " : " + data.length, null);
if (data == null) if (data == null)
throw new HttpDataSourceException( throw new HttpDataSourceException(
"No response", "No response",