Skip to content

Commit b355fb8

Browse files
committed
speedup
Signed-off-by: alperozturk96 <alper_ozturk@proton.me>
1 parent a7e4f98 commit b355fb8

8 files changed

Lines changed: 225 additions & 225 deletions

File tree

app/src/main/java/com/nextcloud/client/player/media3/PlaybackModel.kt

Lines changed: 49 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import android.content.ComponentName
1111
import android.content.Context
1212
import android.view.SurfaceView
1313
import androidx.annotation.OptIn
14-
import androidx.media3.common.Player
1514
import androidx.media3.common.util.UnstableApi
1615
import androidx.media3.session.MediaController
1716
import androidx.media3.session.MediaSession
@@ -35,6 +34,7 @@ import com.nextcloud.client.player.util.PlayerUtil.updateMediaItems
3534
import com.owncloud.android.datamodel.OCFile
3635
import kotlinx.coroutines.CoroutineScope
3736
import kotlinx.coroutines.Dispatchers
37+
import kotlinx.coroutines.Job
3838
import kotlinx.coroutines.SupervisorJob
3939
import kotlinx.coroutines.cancel
4040
import kotlinx.coroutines.flow.Flow
@@ -82,16 +82,20 @@ class PlaybackModel @Inject constructor(
8282
private val controllerListener = object : MediaController.Listener {
8383
override fun onDisconnected(controller: MediaController) {
8484
controller.removeListener(playerListener)
85+
if (this@PlaybackModel.controller === controller) {
86+
this@PlaybackModel.controller = null
87+
}
8588
videoSurfaceView = null
8689
invalidateCurrentFiles()
87-
controllerScope?.cancel()
90+
stopFilesFlow()
8891
checkProgressPeriodicAction.stop()
8992
notifyPlaybackUpdate()
9093
}
9194
}
9295

9396
private var controllerScope: CoroutineScope? = null
94-
private var controller: Player? = null
97+
private var controller: MediaController? = null
98+
private var filesFlowJob: Job? = null
9599

96100
private var mediaSession: MediaSession? = null
97101

@@ -126,6 +130,12 @@ class PlaybackModel @Inject constructor(
126130
}
127131

128132
suspend fun start() {
133+
if (controller?.isConnected == true) {
134+
return
135+
}
136+
137+
releaseController()
138+
129139
videoSurfaceView = null
130140
val sessionToken = SessionToken(context, ComponentName(context, PlaybackService::class.java))
131141
controller = MediaController.Builder(context, sessionToken)
@@ -136,8 +146,26 @@ class PlaybackModel @Inject constructor(
136146
addListener(playerListener)
137147
setRepeatMode(playbackSettings.repeatMode)
138148
shuffleModeEnabled = playbackSettings.isShuffle
139-
controllerScope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
140149
}
150+
controllerScope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
151+
}
152+
153+
private fun releaseController() {
154+
stopFilesFlow()
155+
checkProgressPeriodicAction.stop()
156+
invalidateCurrentFiles()
157+
158+
val current = controller ?: return
159+
controller = null
160+
current.removeListener(playerListener)
161+
current.release()
162+
}
163+
164+
private fun stopFilesFlow() {
165+
filesFlowJob?.cancel()
166+
filesFlowJob = null
167+
controllerScope?.cancel()
168+
controllerScope = null
141169
}
142170

143171
@Suppress("TooGenericExceptionCaught")
@@ -161,7 +189,8 @@ class PlaybackModel @Inject constructor(
161189
}
162190

163191
fun setFilesFlow(filesFlow: Flow<PlaybackFiles>) {
164-
controllerScope?.launch {
192+
filesFlowJob?.cancel()
193+
filesFlowJob = controllerScope?.launch {
165194
filesFlow
166195
.catch {
167196
notifyPlaybackError(it)
@@ -177,21 +206,22 @@ class PlaybackModel @Inject constructor(
177206
return
178207
}
179208

180-
controller?.let { controller ->
181-
val currentFile = controller.currentMediaItem?.mediaMetadata?.playbackFile
182-
val mediaItems = files.list.map { it.toMediaItem() }
183-
184-
if (currentFile == null) {
185-
controller.setMediaItems(mediaItems)
186-
} else if (files.list.any { it.id == currentFile.id }) {
187-
controller.updateMediaItems(mediaItems)
188-
} else {
189-
val nextFileIndex = getNextFileIndex(files, currentFile)
190-
controller.setMediaItems(mediaItems, nextFileIndex, 0)
191-
}
209+
val controller = controller ?: return
210+
val mediaItems = files.list.map { it.toMediaItem() }
211+
212+
if (controller.readMediaIds() == mediaItems.map { it.mediaId }) {
213+
return
214+
}
192215

193-
controller.prepare()
216+
val currentFile = controller.currentMediaItem?.mediaMetadata?.playbackFile
217+
218+
when {
219+
currentFile == null -> controller.setMediaItems(mediaItems)
220+
files.list.any { it.id == currentFile.id } -> controller.updateMediaItems(mediaItems)
221+
else -> controller.setMediaItems(mediaItems, getNextFileIndex(files, currentFile), 0)
194222
}
223+
224+
controller.prepare()
195225
}
196226

197227
private fun getNextFileIndex(files: PlaybackFiles, currentFile: PlaybackFile): Int = (files.list + currentFile)
@@ -201,7 +231,7 @@ class PlaybackModel @Inject constructor(
201231

202232
fun release() {
203233
videoSurfaceView = null
204-
controller?.release()
234+
releaseController()
205235
mediaSession?.player?.release()
206236
mediaSession?.release()
207237
mediaSession = null

app/src/main/java/com/nextcloud/client/player/media3/datasource/PlaybackDataSourceFactory.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,21 @@ import com.nextcloud.client.account.UserAccountManager
1919
import com.nextcloud.client.network.ClientFactory
2020
import com.owncloud.android.MainApp
2121
import com.owncloud.android.datamodel.FileDataStorageManager
22+
import dagger.Lazy
2223
import javax.inject.Inject
2324

2425
@UnstableApi
2526
class PlaybackDataSourceFactory @Inject constructor(
2627
private val context: Context,
27-
private val cache: Cache,
28+
private val cache: Lazy<Cache>,
2829
private val fileDataStorageManager: FileDataStorageManager,
2930
private val clientFactory: ClientFactory,
3031
private val accountManager: UserAccountManager
3132
) : DataSource.Factory {
3233

3334
override fun createDataSource(): DataSource = CacheDataSource.Factory()
3435
.setUpstreamDataSourceFactory(createUpstreamDataSourceFactory())
35-
.setCache(cache)
36+
.setCache(cache.get())
3637
.createDataSource()
3738

3839
private fun createUpstreamDataSourceFactory() = DataSource.Factory {

app/src/main/java/com/nextcloud/client/player/ui/PlayerActivity.kt

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,6 @@ class PlayerActivity :
6969

7070
private var keepPlaybackAliveOnFinish = false
7171

72-
private var configurationChangedInPictureInPicture = false
73-
7472
override fun onCreate(savedInstanceState: Bundle?) {
7573
enableEdgeToEdge()
7674
super.onCreate(savedInstanceState)
@@ -144,19 +142,12 @@ class PlayerActivity :
144142
override fun onConfigurationChanged(newConfig: Configuration) {
145143
super.onConfigurationChanged(newConfig)
146144

145+
val videoPlayerView = playerView as? VideoPlayerView ?: return
147146
if (isInPictureInPictureMode) {
148-
configurationChangedInPictureInPicture = true
149-
(playerView as? VideoPlayerView)?.hideControls()
150-
return
147+
videoPlayerView.hideControls()
148+
} else {
149+
videoPlayerView.showControls()
151150
}
152-
153-
rebuildPlayerViewForCurrentConfiguration()
154-
}
155-
156-
private fun rebuildPlayerViewForCurrentConfiguration() {
157-
configurationChangedInPictureInPicture = false
158-
recreatePlayerView()
159-
(playerView as? VideoPlayerView)?.showControls()
160151
}
161152

162153
override fun onUserLeaveHint() {
@@ -183,8 +174,8 @@ class PlayerActivity :
183174
return
184175
}
185176

186-
if (!isInPictureInPictureMode && configurationChangedInPictureInPicture) {
187-
rebuildPlayerViewForCurrentConfiguration()
177+
if (!isInPictureInPictureMode) {
178+
(playerView as? VideoPlayerView)?.showControls()
188179
}
189180
}
190181

app/src/main/java/com/nextcloud/client/player/ui/video/VideoFileFragment.kt

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ class VideoFileFragment :
5252
private var _binding: PlayerVideoFileFragmentBinding? = null
5353
private val binding get() = checkNotNull(_binding) { "Binding accessed outside of the view lifecycle" }
5454

55+
private var renderedVideoSize: VideoSize? = null
56+
5557
private val file by lazy {
5658
requireNotNull(arguments.getPlaybackFile(ARGUMENT_FILE)) {
5759
"VideoFileFragment requires a $ARGUMENT_FILE argument"
@@ -115,6 +117,7 @@ class VideoFileFragment :
115117
return
116118
}
117119

120+
renderedVideoSize = null
118121
binding.surfaceView.isVisible = false
119122
if (currentItemState == null) {
120123
playerModel.setVideoSurfaceView(null)
@@ -125,11 +128,15 @@ class VideoFileFragment :
125128
if (ownsPlayback(binding.surfaceView)) {
126129
playerModel.setVideoSurfaceView(binding.surfaceView)
127130
}
131+
132+
val size = videoSize ?: renderedVideoSize
133+
renderedVideoSize = size
134+
128135
binding.surfaceView.isVisible = true
129-
binding.surfaceView.alpha = if (videoSize == null) SURFACE_ALPHA_HIDDEN else SURFACE_ALPHA_VISIBLE
136+
binding.surfaceView.alpha = if (size == null) SURFACE_ALPHA_HIDDEN else SURFACE_ALPHA_VISIBLE
130137

131-
if (videoSize == null) return
138+
if (size == null) return
132139

133-
binding.surfaceView.applyVideoSize(videoSize)
140+
binding.surfaceView.applyVideoSize(size)
134141
}
135142
}

0 commit comments

Comments
 (0)