美文网首页
SimpleExoPlayer 简单使用

SimpleExoPlayer 简单使用

作者: 拉弓的松鼠在旋转 | 来源:发表于2023-01-30 12:27 被阅读0次

前言:
依赖版本:
implementation 'com.google.android.exoplayer:exoplayer-core:2.13.3'
implementation 'com.google.android.exoplayer:exoplayer-ui:2.13.3'

自定义统一接口IPlayer (interface)

interface IPlayer {


    companion object {
        const val PLAYER_NULL = -1
        const val PLAYER_INIT = 0
        const val PLAYER_PREPARE = 1
        const val PLAYER_PLAY = 2
        const val PLAYER_PAUSE = 3
        const val PLAYER_STOP = 4

        const val PLAYER_RELEASE = 7
        const val PLAYER_SET_SURFACE = 8
    }

    fun play()

    fun setRepeatMode(mode: Int) {

    }

    fun getRepeatMode(): Int {
        return 0
    }

    //异步
    fun prepare(url: String)

    fun stop()

    fun pause()

    fun release()


    fun seekTo(time: Long, autoPlay: Boolean = true)


    fun getCurrentPosition(): Long

    fun getDuration(): Long {
        return 0L
    }

    fun getVolume(): Float {
        return 0F
    }

    fun setVolume(value: Float): Boolean {
        return false
    }


}

封装 ExoPlayer
封装参考:SimpleExoPlayer extends BasePlayer

class ExoPlayer(private val context: Context) : IPlayer {


    private var currentPlayerUrl = ""
    private var playStatus = PLAYER_PLAY

    private var exoPlayer: SimpleExoPlayer? = null
    private var contentFrame: AspectRatioFrameLayout? = null
    private var surfaceView: View? = null
    private var textureViewRotation = 0
    private var repeatMode = Player.REPEAT_MODE_ONE
    private var currentVolume = 0F

    private var mComponentListener: ComponentListener? = null
    private var mPlayerEventListener: PlayerEventListener? = null


    init {
//        val extractors = DefaultExtractorsFactory()
//        exoPlayer = SimpleExoPlayer.Builder(
//            context,
//            DefaultRenderersFactory(context),
//            DefaultTrackSelector(context),
//            DefaultMediaSourceFactory(context, extractors),
//            TmpLoadControl(),
//            DefaultBandwidthMeter.getSingletonInstance(context),
//            AnalyticsCollector(Clock.DEFAULT)
//        ).build()
        exoPlayer = SimpleExoPlayer.Builder(context).build()
    }

    fun setVideoTextureView(view: TextureView) {
        surfaceView = view
        mComponentListener = ComponentListener()
        exoPlayer?.let {
            it.setVideoTextureView(view)
            it.videoComponent?.let { component ->
                component.addVideoListener(mComponentListener!!)
            }
            it.addListener(mComponentListener!!)
        }


    }

    fun setAspectRatioFrameLayout(view: AspectRatioFrameLayout?) {
        contentFrame = view
    }

    override fun play() {
        exoPlayer?.let {
            playStatus = PLAYER_PLAY
            it.play()
            currentVolume = it.volume
        }
    }


    /**
     *
     */
    override fun setRepeatMode(mode: Int) {
        var tmp = Player.REPEAT_MODE_ONE
        when (mode) {
            0 -> {
                tmp = Player.REPEAT_MODE_OFF
            }
        }
        this.repeatMode = tmp

    }

    override fun getRepeatMode(): Int {
        var tmp = 0
        exoPlayer?.let {
            when (it.repeatMode) {
                Player.REPEAT_MODE_ONE -> {
                    tmp = 1
                }
                Player.REPEAT_MODE_OFF -> {
                    tmp = 0
                }
            }
        }
        return tmp
    }

    override fun getVolume(): Float {
        return currentVolume
    }

    override fun setVolume(value: Float): Boolean {
        exoPlayer?.volume = value
        return true
    }

    override fun prepare(url: String) {
        currentPlayerUrl = url
        playStatus = PLAYER_PREPARE
        val mediaItem = MediaItem.fromUri(url)
        exoPlayer?.let {
            it.setMediaItem(mediaItem)
            it.repeatMode = repeatMode
            it.playWhenReady = false
            it.prepare()
            IKLog.d("$TAG prepare volume:${it.volume}")
        }
    }

    override fun stop() {
        exoPlayer?.let {
            playStatus = PLAYER_STOP
            it.stop()
        }
    }

    override fun pause() {
        exoPlayer?.let { player ->
            playStatus = PLAYER_PAUSE
            player.pause()
        }
    }

    override fun release() {
        exoPlayer?.let { player ->
            playStatus = PLAYER_RELEASE
            mComponentListener?.let {
                player.removeListener(it)
            }
            player.stop()
            player.release()
            exoPlayer = null
        }
    }

    override fun seekTo(time: Long, autoPlay: Boolean) {
        exoPlayer?.let {
            it.seekTo(time)
            if (autoPlay) {
                it.play()
            }
        }
    }

    override fun getCurrentPosition(): Long {
        return exoPlayer?.contentPosition ?: 0L
    }

    override fun getDuration(): Long {
        return exoPlayer?.duration ?: 0L
    }


    private inner class ComponentListener : Player.EventListener, VideoListener, View.OnLayoutChangeListener {

        override fun onVideoSizeChanged(width: Int, height: Int, unappliedRotationDegrees: Int, pixelWidthHeightRatio: Float) {
            var videoAspectRatio: Float = if (height == 0 || width == 0) 1F else width * pixelWidthHeightRatio / height
            surfaceView?.let { view ->
                if (view is TextureView) {
                    if (unappliedRotationDegrees == 90 || unappliedRotationDegrees == 270) {
                        videoAspectRatio = 1 / videoAspectRatio
                    }
                    if (textureViewRotation != 0) {
                        view.removeOnLayoutChangeListener(this)
                    }
                    textureViewRotation = unappliedRotationDegrees
                    if (textureViewRotation != 0) {
                        view.addOnLayoutChangeListener(this)
                    }
                    PlayerUtils.applyTextureViewRotation(view, textureViewRotation)
                }
            }
            onContentAspectRatioChanged(videoAspectRatio, contentFrame, surfaceView)

        }

        override fun onLayoutChange(v: View?, left: Int, top: Int, right: Int, bottom: Int, oldLeft: Int, oldTop: Int, oldRight: Int, oldBottom: Int) {
            PlayerUtils.applyTextureViewRotation(v as TextureView, textureViewRotation)
        }

        override fun onEvents(player: Player, events: Player.Events) {
            super.onEvents(player, events)
            IKLog.d(TAG, "onEvents: events:${events} ${events.contains(Player.EVENT_PLAYER_ERROR)} ")
            if (events.contains(Player.EVENT_PLAYER_ERROR)) {
                IKLog.e("$TAG  onEvents: playerError:${player.playerError}")
            }
            mPlayerEventListener?.onEvent(events)
        }

        override fun onRenderedFirstFrame() {
            super.onRenderedFirstFrame()
            IKLog.d("$TAG onRenderedFirstFrame")
            mPlayerEventListener?.onRenderedFirstFrame()
        }

        override fun onPlaybackStateChanged(state: Int) {
            super.onPlaybackStateChanged(state)
            IKLog.e(TAG, "onEvents: events:${state}")
            mPlayerEventListener?.onPlaybackStateChanged(state)
        }
    }

    private fun onContentAspectRatioChanged(
        contentAspectRatio: Float,
        contentFrame: AspectRatioFrameLayout?,
        contentView: View?
    ) {
        contentFrame?.setAspectRatio(
            if (contentView is SphericalGLSurfaceView) 0F else contentAspectRatio
        )
    }


    fun setPlayerEventListener(listener: PlayerEventListener) {
        mPlayerEventListener = listener
    }

    interface PlayerEventListener {
        fun onEvent(events: Player.Events)

        fun onPlaybackStateChanged(state: Int) {

        }

        fun onRenderedFirstFrame() {

        }
    }
}
其中:图像纠正相关
ComponentListener{
  onVideoSizeChanged
  onLayoutChange
}
PlayerUtils
object PlayerUtils {
    fun applyTextureViewRotation(textureView: TextureView, textureViewRotation: Int) {
        val transformMatrix = Matrix()
        val textureViewWidth = textureView.width.toFloat()
        val textureViewHeight = textureView.height.toFloat()
        if (textureViewWidth != 0f && textureViewHeight != 0f && textureViewRotation != 0) {
            val pivotX = textureViewWidth / 2
            val pivotY = textureViewHeight / 2
            transformMatrix.postRotate(textureViewRotation.toFloat(), pivotX, pivotY)

            // After rotation, scale the rotated texture to fit the TextureView size.
            val originalTextureRect = RectF(0F, 0F, textureViewWidth, textureViewHeight)
            val rotatedTextureRect = RectF()
            transformMatrix.mapRect(rotatedTextureRect, originalTextureRect)
            transformMatrix.postScale(
                textureViewWidth / rotatedTextureRect.width(),
                textureViewHeight / rotatedTextureRect.height(),
                pivotX,
                pivotY
            )
        }
        textureView.setTransform(transformMatrix)
    }
}

相关文章

  • 简单使用

    创建模型 过滤器 我们有一些字段和我们想让用户筛选的基础上 名称、价格或release_date。 我们创建一个 ...

  • gorange

    数组中简单使用 map中简单使用

  • 简单使用使用kaggle

    向我这样的条件不好的可以考虑借助云gpu来加速训练,借助kaggle可以在kaggle服务器上训练数据,kaggl...

  • 零碎的小程序笔记

    目录 template的简单使用WXS的简单使用npm的简单使用倒计时js的实现wx:for的使用一些js方法记录...

  • 命令行的简单使用

    Git命令行的简单使用,仅供自己使用 pod命令行的简单使用

  • 单元测试和OCMock

    OCMock使用一、安装及简单使用:使用Cocoapod引入:pod 'OCMock' 简单使用:新建一个单元测试...

  • Alamofire类似AFNetworking的简单使用和封装

    简单的使用。简单的使用。简单的使用。注定该文弱鸡一个,求拍砖。 一、介绍 Alamofire(Swift)的前身是...

  • Android ViewPager 使用总结

    ViewPager 简单使用 ViewPager + PagerAdapter简单的 View 可以使用这个实现,...

  • vuex简单简单使用记录

    1、Vuex有啥用(非官方解释)举例,组件a b 使用了同一个数据源count,当操作a的时候count++,同时...

  • 无标题文章

    iOS 缓存 快速集成环信 技术文档 Masonry简单使用 MJExtension简单使用 GCD基本使用 gi...

网友评论

      本文标题:SimpleExoPlayer 简单使用

      本文链接:https://www.haomeiwen.com/subject/gqcphdtx.html