Small changes to allow for blocking seek in GaplessExoPlayerWrapper.

This commit is contained in:
casey langen 2018-01-19 15:59:30 -08:00
parent cce2dbdb18
commit 486bc9c96d
4 changed files with 16 additions and 10 deletions

View File

@ -69,7 +69,7 @@ abstract class PlayerWrapper {
} }
} }
abstract fun play(uri: String, metadata: ITrack) abstract fun play(uri: String, metadata: ITrack, offsetMs: Int = 0)
abstract fun prefetch(uri: String, metadata: ITrack) abstract fun prefetch(uri: String, metadata: ITrack)
abstract fun pause() abstract fun pause()
abstract fun resume() abstract fun resume()

View File

@ -54,13 +54,14 @@ class ExoPlayerWrapper : PlayerWrapper() {
this.transcoding = this.prefs.getInt(Prefs.Key.TRANSCODER_BITRATE_INDEX, 0) != 0 this.transcoding = this.prefs.getInt(Prefs.Key.TRANSCODER_BITRATE_INDEX, 0) != 0
} }
override fun play(uri: String, metadata: ITrack) { override fun play(uri: String, metadata: ITrack, offsetMs: Int) {
Preconditions.throwIfNotOnMainThread() Preconditions.throwIfNotOnMainThread()
if (!dead()) { if (!dead()) {
this.metadata = metadata this.metadata = metadata
this.originalUri = uri this.originalUri = uri
this.proxyUri = streamProxy.getProxyUrl(uri) this.proxyUri = streamProxy.getProxyUrl(uri)
Log.d("ExoPlayerWrapper", "originalUri: ${this.originalUri} proxyUri: ${this.proxyUri}") Log.d("ExoPlayerWrapper", "originalUri: ${this.originalUri} proxyUri: ${this.proxyUri}")
addCacheListener() addCacheListener()

View File

@ -15,19 +15,18 @@ import com.google.android.exoplayer2.trackselection.DefaultTrackSelector
import com.google.android.exoplayer2.trackselection.TrackSelectionArray import com.google.android.exoplayer2.trackselection.TrackSelectionArray
import com.google.android.exoplayer2.upstream.DataSource import com.google.android.exoplayer2.upstream.DataSource
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory
import com.google.android.exoplayer2.util.Util import com.google.android.exoplayer2.util.Util
import io.casey.musikcube.remote.Application import io.casey.musikcube.remote.Application
import io.casey.musikcube.remote.service.playback.PlayerWrapper import io.casey.musikcube.remote.service.playback.PlayerWrapper
import io.casey.musikcube.remote.service.playback.impl.streaming.StreamProxy
import io.casey.musikcube.remote.service.websocket.model.ITrack import io.casey.musikcube.remote.service.websocket.model.ITrack
import io.casey.musikcube.remote.ui.settings.constants.Prefs import io.casey.musikcube.remote.ui.settings.constants.Prefs
import io.casey.musikcube.remote.util.Preconditions import io.casey.musikcube.remote.util.Preconditions
import java.io.File import java.io.File
class GaplessExoPlayerWrapper : PlayerWrapper() { class GaplessExoPlayerWrapper : PlayerWrapper() {
private var sourceFactory: DataSource.Factory = private var sourceFactory: DataSource.Factory = DefaultHttpDataSourceFactory(
DefaultDataSourceFactory(context, Util.getUserAgent(context, "musikdroid")) Util.getUserAgent(context, "musikdroid"), null, TIMEOUT, TIMEOUT, true)
private val extractorsFactory = DefaultExtractorsFactory() private val extractorsFactory = DefaultExtractorsFactory()
private var source: MediaSource? = null private var source: MediaSource? = null
@ -38,12 +37,13 @@ class GaplessExoPlayerWrapper : PlayerWrapper() {
private var originalUri: String? = null private var originalUri: String? = null
private var proxyUri: String? = null private var proxyUri: String? = null
private val transcoding: Boolean private val transcoding: Boolean
private var initialOffsetMs: Int = 0
init { init {
this.transcoding = prefs.getInt(Prefs.Key.TRANSCODER_BITRATE_INDEX, 0) != 0 this.transcoding = prefs.getInt(Prefs.Key.TRANSCODER_BITRATE_INDEX, 0) != 0
} }
override fun play(uri: String, metadata: ITrack) { override fun play(uri: String, metadata: ITrack, offsetMs: Int) {
Preconditions.throwIfNotOnMainThread() Preconditions.throwIfNotOnMainThread()
if (!dead()) { if (!dead()) {
@ -52,6 +52,7 @@ class GaplessExoPlayerWrapper : PlayerWrapper() {
this.metadata = metadata this.metadata = metadata
this.originalUri = uri this.originalUri = uri
this.proxyUri = streamProxy.getProxyUrl(uri) this.proxyUri = streamProxy.getProxyUrl(uri)
this.initialOffsetMs = offsetMs
addCacheListener() addCacheListener()
@ -125,11 +126,13 @@ class GaplessExoPlayerWrapper : PlayerWrapper() {
if (gaplessPlayer?.playbackState != ExoPlayer.STATE_IDLE) { if (gaplessPlayer?.playbackState != ExoPlayer.STATE_IDLE) {
if (gaplessPlayer?.isCurrentWindowSeekable == true) { if (gaplessPlayer?.isCurrentWindowSeekable == true) {
var offset = millis.toLong() var offset = millis.toLong()
val isInitialSeek = initialOffsetMs > 0 && (position == initialOffsetMs)
/* if we're transcoding we don't want to seek arbitrarily because it may put /* if we're transcoding we don't want to seek arbitrarily because it may put
a lot of pressure on the backend. just allow seeking up to what we currently a lot of pressure on the backend. just allow seeking up to what we currently
have buffered! */ have buffered! one exception: if we transfer playback context from the backend
if (transcoding && percentAvailable != 100) { to here, we want to wait until we are able to pickup where we left off. */
if (!isInitialSeek && transcoding && percentAvailable != 100) {
/* give ourselves 2% wiggle room! */ /* give ourselves 2% wiggle room! */
val percent = Math.max(0, percentAvailable - 2).toFloat() / 100.0f val percent = Math.max(0, percentAvailable - 2).toFloat() / 100.0f
val totalMs = gaplessPlayer?.duration val totalMs = gaplessPlayer?.duration
@ -137,6 +140,7 @@ class GaplessExoPlayerWrapper : PlayerWrapper() {
offset = Math.min(millis.toLong(), available) offset = Math.min(millis.toLong(), available)
} }
initialOffsetMs = 0
gaplessPlayer?.seekTo(offset) gaplessPlayer?.seekTo(offset)
} }
} }
@ -287,6 +291,7 @@ class GaplessExoPlayerWrapper : PlayerWrapper() {
} }
companion object { companion object {
const val TIMEOUT = 1000 * 60 * 2 /* 2 minutes; makes seeking an incomplete transcode work most of the time */
private val prefs: SharedPreferences by lazy { Application.instance!!.getSharedPreferences(Prefs.NAME, Context.MODE_PRIVATE) } private val prefs: SharedPreferences by lazy { Application.instance!!.getSharedPreferences(Prefs.NAME, Context.MODE_PRIVATE) }
private val context: Context by lazy { Application.instance!! } private val context: Context by lazy { Application.instance!! }
private val trackSelector = DefaultTrackSelector(AdaptiveTrackSelection.Factory(DefaultBandwidthMeter())) private val trackSelector = DefaultTrackSelector(AdaptiveTrackSelection.Factory(DefaultBandwidthMeter()))

View File

@ -32,7 +32,7 @@ class MediaPlayerWrapper : PlayerWrapper() {
this.prefs = context!!.getSharedPreferences(Prefs.NAME, Context.MODE_PRIVATE) this.prefs = context!!.getSharedPreferences(Prefs.NAME, Context.MODE_PRIVATE)
} }
override fun play(uri: String, metadata: ITrack) { override fun play(uri: String, metadata: ITrack, offsetMs: Int) {
Preconditions.throwIfNotOnMainThread() Preconditions.throwIfNotOnMainThread()
try { try {