Merge pull request #2879 from fatihergin/feature/update-exoplayer-v2_18_7

Feature/update exoplayer v2.18.7
This commit is contained in:
Tibor Kaputa 2023-06-19 09:43:00 +02:00 committed by GitHub
commit e9ad0227ee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 97 additions and 103 deletions

View file

@ -83,7 +83,7 @@ dependencies {
implementation 'it.sephiroth.android.exif:library:1.0.1' implementation 'it.sephiroth.android.exif:library:1.0.1'
implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.25' implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.25'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'com.google.android.exoplayer:exoplayer-core:2.9.6' implementation 'com.google.android.exoplayer:exoplayer-core:2.18.7'
implementation 'com.google.vr:sdk-panowidget:1.180.0' implementation 'com.google.vr:sdk-panowidget:1.180.0'
implementation 'com.google.vr:sdk-videowidget:1.180.0' implementation 'com.google.vr:sdk-videowidget:1.180.0'
implementation 'org.apache.sanselan:sanselan:0.97-incubator' implementation 'org.apache.sanselan:sanselan:0.97-incubator'

View file

@ -16,16 +16,15 @@ import android.view.*
import android.widget.RelativeLayout import android.widget.RelativeLayout
import android.widget.SeekBar import android.widget.SeekBar
import com.google.android.exoplayer2.* import com.google.android.exoplayer2.*
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory import com.google.android.exoplayer2.audio.AudioAttributes
import com.google.android.exoplayer2.source.ExtractorMediaSource import com.google.android.exoplayer2.source.DefaultMediaSourceFactory
import com.google.android.exoplayer2.source.TrackGroupArray import com.google.android.exoplayer2.source.MediaSource
import com.google.android.exoplayer2.trackselection.TrackSelectionArray import com.google.android.exoplayer2.source.ProgressiveMediaSource
import com.google.android.exoplayer2.upstream.ContentDataSource import com.google.android.exoplayer2.upstream.ContentDataSource
import com.google.android.exoplayer2.upstream.DataSource import com.google.android.exoplayer2.upstream.DataSource
import com.google.android.exoplayer2.upstream.DataSpec import com.google.android.exoplayer2.upstream.DataSpec
import com.google.android.exoplayer2.video.VideoListener import com.google.android.exoplayer2.video.VideoSize
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.gallery.pro.R import com.simplemobiletools.gallery.pro.R
import com.simplemobiletools.gallery.pro.extensions.* import com.simplemobiletools.gallery.pro.extensions.*
import com.simplemobiletools.gallery.pro.helpers.* import com.simplemobiletools.gallery.pro.helpers.*
@ -51,7 +50,7 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen
private var mCloseDownThreshold = 100f private var mCloseDownThreshold = 100f
private var mUri: Uri? = null private var mUri: Uri? = null
private var mExoPlayer: SimpleExoPlayer? = null private var mExoPlayer: ExoPlayer? = null
private var mVideoSize = Point(0, 0) private var mVideoSize = Point(0, 0)
private var mTimerHandler = Handler() private var mTimerHandler = Handler()
private var mPlayWhenReadyHandler = Handler() private var mPlayWhenReadyHandler = Handler()
@ -230,7 +229,7 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen
} }
private fun initExoPlayer() { private fun initExoPlayer() {
val dataSpec = DataSpec(mUri) val dataSpec = DataSpec(mUri!!)
val fileDataSource = ContentDataSource(applicationContext) val fileDataSource = ContentDataSource(applicationContext)
try { try {
fileDataSource.open(dataSpec) fileDataSource.open(dataSpec)
@ -239,60 +238,51 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen
} }
val factory = DataSource.Factory { fileDataSource } val factory = DataSource.Factory { fileDataSource }
val audioSource = ExtractorMediaSource(fileDataSource.uri, factory, DefaultExtractorsFactory(), null, null) val mediaSource: MediaSource = ProgressiveMediaSource.Factory(factory)
mExoPlayer = ExoPlayerFactory.newSimpleInstance(applicationContext).apply { .createMediaSource(MediaItem.fromUri(fileDataSource.uri!!))
seekParameters = SeekParameters.CLOSEST_SYNC
audioStreamType = C.STREAM_TYPE_MUSIC mExoPlayer = ExoPlayer.Builder(this)
.setMediaSourceFactory(DefaultMediaSourceFactory(applicationContext))
.setSeekParameters(SeekParameters.CLOSEST_SYNC)
.build()
.apply {
setMediaSource(mediaSource)
setAudioAttributes(
AudioAttributes
.Builder()
.setContentType(C.AUDIO_CONTENT_TYPE_MUSIC)
.build(), false
)
if (config.loopVideos) { if (config.loopVideos) {
repeatMode = Player.REPEAT_MODE_ONE repeatMode = Player.REPEAT_MODE_ONE
} }
prepare(audioSource) prepare()
initListeners()
} }
initExoPlayerListeners()
} }
private fun initExoPlayerListeners() { private fun ExoPlayer.initListeners() {
mExoPlayer!!.addListener(object : Player.EventListener { addListener(object : Player.Listener {
override fun onPlaybackParametersChanged(playbackParameters: PlaybackParameters?) {} override fun onPositionDiscontinuity(oldPosition: Player.PositionInfo, newPosition: Player.PositionInfo, @Player.DiscontinuityReason reason: Int) {
override fun onSeekProcessed() {}
override fun onTracksChanged(trackGroups: TrackGroupArray?, trackSelections: TrackSelectionArray?) {}
override fun onPlayerError(error: ExoPlaybackException?) {}
override fun onLoadingChanged(isLoading: Boolean) {}
override fun onPositionDiscontinuity(reason: Int) {
// Reset progress views when video loops. // Reset progress views when video loops.
if (reason == Player.DISCONTINUITY_REASON_PERIOD_TRANSITION) { if (reason == Player.DISCONTINUITY_REASON_AUTO_TRANSITION) {
video_seekbar.progress = 0 video_seekbar.progress = 0
video_curr_time.text = 0.getFormattedDuration() video_curr_time.text = 0.getFormattedDuration()
} }
} }
override fun onRepeatModeChanged(repeatMode: Int) {} override fun onPlaybackStateChanged(@Player.State playbackState: Int) {
override fun onShuffleModeEnabledChanged(shuffleModeEnabled: Boolean) {}
override fun onTimelineChanged(timeline: Timeline?, manifest: Any?, reason: Int) {}
override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
when (playbackState) { when (playbackState) {
Player.STATE_READY -> videoPrepared() Player.STATE_READY -> videoPrepared()
Player.STATE_ENDED -> videoCompleted() Player.STATE_ENDED -> videoCompleted()
} }
} }
})
mExoPlayer!!.addVideoListener(object : VideoListener { override fun onVideoSizeChanged(videoSize: VideoSize) {
override fun onVideoSizeChanged(width: Int, height: Int, unappliedRotationDegrees: Int, pixelWidthHeightRatio: Float) { mVideoSize.x = videoSize.width
mVideoSize.x = width mVideoSize.y = videoSize.height
mVideoSize.y = height
setVideoSize() setVideoSize()
} }
override fun onRenderedFirstFrame() {}
}) })
} }
@ -546,6 +536,7 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen
mTouchDownTime = System.currentTimeMillis() mTouchDownTime = System.currentTimeMillis()
mProgressAtDown = mExoPlayer!!.currentPosition mProgressAtDown = mExoPlayer!!.currentPosition
} }
MotionEvent.ACTION_POINTER_DOWN -> mIgnoreCloseDown = true MotionEvent.ACTION_POINTER_DOWN -> mIgnoreCloseDown = true
MotionEvent.ACTION_MOVE -> { MotionEvent.ACTION_MOVE -> {
val diffX = event.rawX - mTouchDownX val diffX = event.rawX - mTouchDownX
@ -570,6 +561,7 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen
resetPlayWhenReady() resetPlayWhenReady()
} }
} }
MotionEvent.ACTION_UP -> { MotionEvent.ACTION_UP -> {
val diffX = mTouchDownX - event.rawX val diffX = mTouchDownX - event.rawX
val diffY = mTouchDownY - event.rawY val diffY = mTouchDownY - event.rawY
@ -624,11 +616,11 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen
} }
private fun releaseExoPlayer() { private fun releaseExoPlayer() {
mExoPlayer?.stop() mExoPlayer?.apply {
ensureBackgroundThread { stop()
mExoPlayer?.release() release()
mExoPlayer = null
} }
mExoPlayer = null
} }
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) { override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
@ -660,10 +652,8 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen
override fun onSurfaceTextureDestroyed(surface: SurfaceTexture) = false override fun onSurfaceTextureDestroyed(surface: SurfaceTexture) = false
override fun onSurfaceTextureAvailable(surface: SurfaceTexture, width: Int, height: Int) { override fun onSurfaceTextureAvailable(surface: SurfaceTexture, width: Int, height: Int) {
ensureBackgroundThread {
mExoPlayer?.setVideoSurface(Surface(video_surface!!.surfaceTexture)) mExoPlayer?.setVideoSurface(Surface(video_surface!!.surfaceTexture))
} }
}
override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture, width: Int, height: Int) {} override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture, width: Int, height: Int) {}
} }

View file

@ -15,14 +15,15 @@ import android.widget.SeekBar
import android.widget.TextView import android.widget.TextView
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.google.android.exoplayer2.* import com.google.android.exoplayer2.*
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory import com.google.android.exoplayer2.audio.AudioAttributes
import com.google.android.exoplayer2.source.ExtractorMediaSource import com.google.android.exoplayer2.source.DefaultMediaSourceFactory
import com.google.android.exoplayer2.source.TrackGroupArray import com.google.android.exoplayer2.source.MediaSource
import com.google.android.exoplayer2.trackselection.TrackSelectionArray import com.google.android.exoplayer2.source.ProgressiveMediaSource
import com.google.android.exoplayer2.upstream.ContentDataSource import com.google.android.exoplayer2.upstream.ContentDataSource
import com.google.android.exoplayer2.upstream.DataSource import com.google.android.exoplayer2.upstream.DataSource
import com.google.android.exoplayer2.upstream.DataSpec import com.google.android.exoplayer2.upstream.DataSpec
import com.google.android.exoplayer2.upstream.FileDataSource import com.google.android.exoplayer2.upstream.FileDataSource
import com.google.android.exoplayer2.video.VideoSize
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.gallery.pro.R import com.simplemobiletools.gallery.pro.R
@ -58,7 +59,7 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
private var mPositionAtPause = 0L private var mPositionAtPause = 0L
var mIsPlaying = false var mIsPlaying = false
private var mExoPlayer: SimpleExoPlayer? = null private var mExoPlayer: ExoPlayer? = null
private var mVideoSize = Point(1, 1) private var mVideoSize = Point(1, 1)
private var mTimerHandler = Handler() private var mTimerHandler = Handler()
@ -348,16 +349,15 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
return return
} }
mExoPlayer = ExoPlayerFactory.newSimpleInstance(context)
mExoPlayer!!.seekParameters = SeekParameters.CLOSEST_SYNC
if (mConfig.loopVideos && listener?.isSlideShowActive() == false) {
mExoPlayer?.repeatMode = Player.REPEAT_MODE_ONE
}
val isContentUri = mMedium.path.startsWith("content://") val isContentUri = mMedium.path.startsWith("content://")
val uri = if (isContentUri) Uri.parse(mMedium.path) else Uri.fromFile(File(mMedium.path)) val uri = if (isContentUri) Uri.parse(mMedium.path) else Uri.fromFile(File(mMedium.path))
val dataSpec = DataSpec(uri) val dataSpec = DataSpec(uri)
val fileDataSource = if (isContentUri) ContentDataSource(context) else FileDataSource() val fileDataSource = if (isContentUri) {
ContentDataSource(requireContext())
} else {
FileDataSource()
}
try { try {
fileDataSource.open(dataSpec) fileDataSource.open(dataSpec)
} catch (e: Exception) { } catch (e: Exception) {
@ -366,56 +366,62 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
} }
val factory = DataSource.Factory { fileDataSource } val factory = DataSource.Factory { fileDataSource }
val audioSource = ExtractorMediaSource(fileDataSource.uri, factory, DefaultExtractorsFactory(), null, null) val mediaSource: MediaSource = ProgressiveMediaSource.Factory(factory)
.createMediaSource(MediaItem.fromUri(fileDataSource.uri!!))
mPlayOnPrepared = true mPlayOnPrepared = true
mExoPlayer!!.audioStreamType = C.STREAM_TYPE_MUSIC
mExoPlayer!!.prepare(audioSource) mExoPlayer = ExoPlayer.Builder(requireContext())
.setMediaSourceFactory(DefaultMediaSourceFactory(requireContext()))
.setSeekParameters(SeekParameters.CLOSEST_SYNC)
.build()
.apply {
if (mConfig.loopVideos && listener?.isSlideShowActive() == false) {
repeatMode = Player.REPEAT_MODE_ONE
}
setMediaSource(mediaSource)
setAudioAttributes(
AudioAttributes
.Builder()
.setContentType(C.AUDIO_CONTENT_TYPE_MUSIC)
.build(), false
)
prepare()
if (mTextureView.surfaceTexture != null) { if (mTextureView.surfaceTexture != null) {
mExoPlayer!!.setVideoSurface(Surface(mTextureView.surfaceTexture)) setVideoSurface(Surface(mTextureView.surfaceTexture))
} }
mExoPlayer!!.addListener(object : Player.EventListener { initListeners()
override fun onPlaybackParametersChanged(playbackParameters: PlaybackParameters?) {} }
}
override fun onSeekProcessed() {} private fun ExoPlayer.initListeners() {
addListener(object : Player.Listener {
override fun onTracksChanged(trackGroups: TrackGroupArray?, trackSelections: TrackSelectionArray?) {} override fun onPositionDiscontinuity(
oldPosition: Player.PositionInfo,
override fun onPlayerError(error: ExoPlaybackException?) {} newPosition: Player.PositionInfo,
@Player.DiscontinuityReason reason: Int
override fun onLoadingChanged(isLoading: Boolean) {} ) {
override fun onPositionDiscontinuity(reason: Int) {
// Reset progress views when video loops. // Reset progress views when video loops.
if (reason == Player.DISCONTINUITY_REASON_PERIOD_TRANSITION) { if (reason == Player.DISCONTINUITY_REASON_AUTO_TRANSITION) {
mSeekBar.progress = 0 mSeekBar.progress = 0
mCurrTimeView.text = 0.getFormattedDuration() mCurrTimeView.text = 0.getFormattedDuration()
} }
} }
override fun onRepeatModeChanged(repeatMode: Int) {} override fun onPlaybackStateChanged(@Player.State playbackState: Int) {
override fun onShuffleModeEnabledChanged(shuffleModeEnabled: Boolean) {}
override fun onTimelineChanged(timeline: Timeline?, manifest: Any?, reason: Int) {}
override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
when (playbackState) { when (playbackState) {
Player.STATE_READY -> videoPrepared() Player.STATE_READY -> videoPrepared()
Player.STATE_ENDED -> videoCompleted() Player.STATE_ENDED -> videoCompleted()
} }
} }
})
mExoPlayer!!.addVideoListener(object : SimpleExoPlayer.VideoListener { override fun onVideoSizeChanged(videoSize: VideoSize) {
override fun onVideoSizeChanged(width: Int, height: Int, unappliedRotationDegrees: Int, pixelWidthHeightRatio: Float) { mVideoSize.x = videoSize.width
mVideoSize.x = width mVideoSize.y = (videoSize.height / videoSize.pixelWidthHeightRatio).toInt()
mVideoSize.y = (height / pixelWidthHeightRatio).toInt()
setVideoSize() setVideoSize()
} }
override fun onRenderedFirstFrame() {}
}) })
} }
@ -753,11 +759,11 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
private fun releaseExoPlayer() { private fun releaseExoPlayer() {
mIsPlayerPrepared = false mIsPlayerPrepared = false
mExoPlayer?.stop() mExoPlayer?.apply {
ensureBackgroundThread { stop()
mExoPlayer?.release() release()
mExoPlayer = null
} }
mExoPlayer = null
} }
override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture, width: Int, height: Int) {} override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture, width: Int, height: Int) {}
@ -767,10 +773,8 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
override fun onSurfaceTextureDestroyed(surface: SurfaceTexture) = false override fun onSurfaceTextureDestroyed(surface: SurfaceTexture) = false
override fun onSurfaceTextureAvailable(surface: SurfaceTexture, width: Int, height: Int) { override fun onSurfaceTextureAvailable(surface: SurfaceTexture, width: Int, height: Int) {
ensureBackgroundThread {
mExoPlayer?.setVideoSurface(Surface(mTextureView.surfaceTexture)) mExoPlayer?.setVideoSurface(Surface(mTextureView.surfaceTexture))
} }
}
private fun setVideoSize() { private fun setVideoSize() {
if (activity == null || mConfig.openVideosOnSeparateScreen) { if (activity == null || mConfig.openVideosOnSeparateScreen) {