diff --git a/android/src/main/java/dev/zoriya/omni/OmniView.kt b/android/src/main/java/dev/zoriya/omni/OmniView.kt index 3398e4d..ebd514a 100755 --- a/android/src/main/java/dev/zoriya/omni/OmniView.kt +++ b/android/src/main/java/dev/zoriya/omni/OmniView.kt @@ -4,6 +4,7 @@ import android.app.PictureInPictureParams import android.graphics.Rect import android.os.Build import android.util.Rational +import android.view.Gravity import android.view.SurfaceHolder import android.view.SurfaceView import android.view.View @@ -11,6 +12,10 @@ import android.view.ViewGroup import android.widget.FrameLayout import androidx.core.view.isVisible import androidx.media3.common.Player +import androidx.media3.common.VideoSize +import androidx.media3.common.text.CueGroup +import androidx.media3.ui.AspectRatioFrameLayout +import androidx.media3.ui.SubtitleView import com.facebook.react.bridge.LifecycleEventListener import com.facebook.react.uimanager.ThemedReactContext import com.margelo.nitro.omni.HybridOmniPlayerSpec @@ -68,6 +73,16 @@ class OmniView(val context: ThemedReactContext) : } } + private val contentFrame = AspectRatioFrameLayout(context).apply { + setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FIT) + layoutParams = FrameLayout.LayoutParams( + FrameLayout.LayoutParams.MATCH_PARENT, + FrameLayout.LayoutParams.MATCH_PARENT, + Gravity.CENTER + ) + view.addView(this) + } + private val surfaceView = SurfaceView(context).apply { layoutParams = FrameLayout.LayoutParams( FrameLayout.LayoutParams.MATCH_PARENT, @@ -75,8 +90,19 @@ class OmniView(val context: ThemedReactContext) : ) holder.addCallback(this@OmniView) addOnLayoutChangeListener(this@OmniView) + contentFrame.addView(this) + } + + private val subtitleView = SubtitleView(context).apply { + layoutParams = FrameLayout.LayoutParams( + FrameLayout.LayoutParams.MATCH_PARENT, + FrameLayout.LayoutParams.MATCH_PARENT + ) + setUserDefaultStyle() + setUserDefaultTextSize() view.addView(this) } + private var surfaceReady = false private var boundPlayer: OmniPlayer? = null private var rootContent: ViewGroup? = null @@ -94,6 +120,20 @@ class OmniView(val context: ThemedReactContext) : context.addLifecycleEventListener(this) } + override fun onVideoSizeChanged(videoSize: VideoSize) { + contentFrame.setAspectRatio( + if (videoSize.width > 0 && videoSize.height > 0) { + videoSize.width * videoSize.pixelWidthHeightRatio / videoSize.height + } else { + 0f + } + ) + } + + override fun onCues(cueGroup: CueGroup) { + subtitleView.setCues(cueGroup.cues) + } + override fun onLayoutChange( view: View?, left: Int, @@ -307,7 +347,7 @@ class OmniView(val context: ThemedReactContext) : child.visibility = View.GONE } - view.removeView(surfaceView) + contentFrame.removeView(surfaceView) root.addView( surfaceView, FrameLayout.LayoutParams( @@ -331,7 +371,7 @@ class OmniView(val context: ThemedReactContext) : } rootContentViews = emptyList() - view.addView(surfaceView, FrameLayout.LayoutParams( + contentFrame.addView(surfaceView, FrameLayout.LayoutParams( FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT )) diff --git a/android/src/main/java/dev/zoriya/omni/VlcPlayer.kt b/android/src/main/java/dev/zoriya/omni/VlcPlayer.kt index a314377..e4314c3 100644 --- a/android/src/main/java/dev/zoriya/omni/VlcPlayer.kt +++ b/android/src/main/java/dev/zoriya/omni/VlcPlayer.kt @@ -525,36 +525,43 @@ class VlcPlayer(ctx: Context) : val selectedAudio = player.getSelectedTrack(IMedia.Track.Type.Audio) val selectedSubtitle = player.getSelectedTrack(IMedia.Track.Type.Text) - val videoTracks = player.getTracks(IMedia.Track.Type.Video) - if (!videoTracks.isNullOrEmpty()) { - val videoFormats = videoTracks.map { track -> - Format.Builder() - .setId(track.id) - .setLabel(track.name) - .setLanguage(track.language) - .setSampleMimeType("video/x-unknown") - .build() + player.getTracks(IMedia.Track.Type.Video).orEmpty() + .groupBy { listOf(it.language, it.name, it.description) } + .values.forEach { videoTracks -> + val videoFormats = videoTracks.map { track -> + Format.Builder() + .setId(track.id) + .setLabel(track.name) + .setLanguage(track.language) + .setSampleMimeType("video/x-unknown") + .build() + } + val group = TrackGroup("vlc-video-${videoTracks.minOf { it.id }}", *videoFormats.toTypedArray()) + val selected = BooleanArray(videoFormats.size) { idx -> + selectedVideo != null && selectedVideo.id == videoTracks[idx].id + } + val support = IntArray(videoFormats.size) { FORMAT_HANDLED } + result.add(Group(group, videoFormats.size > 1, support, selected)) } - val group = TrackGroup("vlc-video", *videoFormats.toTypedArray()) - val selected = BooleanArray(videoFormats.size) { idx -> - selectedVideo != null && selectedVideo.id == videoTracks[idx].id - } - val support = IntArray(videoFormats.size) { FORMAT_HANDLED } - result.add(Group(group, videoFormats.size > 1, support, selected)) - } - player.getTracks(IMedia.Track.Type.Audio)?.forEach { track -> - val format = Format.Builder() - .setId(track.id) - .setLabel(track.name) - .setLanguage(track.language) - .setSampleMimeType("audio/x-unknown") - .build() - val group = TrackGroup("vlc-audio-${track.id}", format) - val selected = booleanArrayOf(selectedAudio != null && selectedAudio.id == track.id) - val support = intArrayOf(FORMAT_HANDLED) - result.add(Group(group, false, support, selected)) - } + player.getTracks(IMedia.Track.Type.Audio).orEmpty() + .groupBy { listOf(it.language, it.name, it.description) } + .values.forEach { audioTracks -> + val audioFormats = audioTracks.map { track -> + Format.Builder() + .setId(track.id) + .setLabel(track.name) + .setLanguage(track.language) + .setSampleMimeType("audio/x-unknown") + .build() + } + val group = TrackGroup("vlc-audio-${audioTracks.minOf { it.id }}", *audioFormats.toTypedArray()) + val selected = BooleanArray(audioFormats.size) { idx -> + selectedAudio != null && selectedAudio.id == audioTracks[idx].id + } + val support = IntArray(audioFormats.size) { FORMAT_HANDLED } + result.add(Group(group, audioFormats.size > 1, support, selected)) + } player.getTracks(IMedia.Track.Type.Text)?.forEach { track -> val format = Format.Builder()