1

我尝试在 Android Box 中通过 LibVLC 播放 UDP 流,但我遇到了一些问题。在某些高清频道中,视频滞后并停止,但声音正常并继续。我尝试了很多选项,但没有奏效。

这是我的 Vlc 控制器类:

class VideoController(activity: AppCompatActivity, context: Context) : IVLCVout.Callback ,
    MediaPlayer.EventListener {

// create TAG for logging
companion object {
    var TAG = "VideoController"
}

// declare media player object
var mediaPlayer: MediaPlayer? = null
// declare surface view object
var mSurface: SurfaceView? = null
// declare surface holder object
var holder: SurfaceHolder? = null

// declare libvlc object
private var libvlc: LibVLC? = null

// declare/initialize activity
var activity: Activity? = null
var context: Context? = null

init {
    this.activity = activity
    this.context = context
}

/////////////////////


/////////////////////
fun createPlayer(media: String) {

    if (mediaPlayer != null && libvlc != null) {
        releasePlayer()
    }
    Log.i(TAG, "Creating vlc player")

    try {
        // create arraylist to assign option to create libvlc object
        val options = ArrayList<String>()
        options.add("--audio-time-stretch"); // time stretching
        options.add("-vvv") // verbosity
        options.add("--no-sub-autodetect-file")
        options.add("--swscale-mode=0")
        options.add("--network-caching=5000")
        options.add("--drop-late-frames")
        options.add("--skip-frames")
        options.add("--avcodec-skip-frame")
        options.add("--avcodec-hw=any")
        options.add("--aout=opensles")
        options.add("--rtsp-tcp")
        options.add("--http-reconnect")
        options.add("--sout-display")
        options.add("--sout=any")
        options.add("--packetizer=any")
        options.add("--packetizer-mpegvideo-sync-iframe")
        options.add("--avcodec-skip-frame=4")
        options.add("--network-synchronisation")
        options.add("--sout-x264-lookahead=60")
        options.add("--avcodec-hurry-up")
        options.add("--audio-desync=1")
        options.add("--no-hdtv-fix")
        options.add("--udp-buffer=5000")
        options.add("--sout-rtp-proto=udp")


        // create libvlc object
        libvlc = LibVLC(activity, options)

        // get surface view holder to display video
        this.holder = mSurface!!.holder
        holder!!.setKeepScreenOn(true)

        // Creating media player
        mediaPlayer = MediaPlayer(libvlc)

        // Setting up video output
        val vout = mediaPlayer!!.vlcVout
        vout.setVideoView(mSurface)
        vout.addCallback(this)
        vout.attachViews()
        val m = Media(libvlc, Uri.parse(media))
        m.setHWDecoderEnabled(true, false)
        m.addOption(":network-caching=5000")
        m.addOption(":clock-jitter=1")
        m.addOption(":clock-synchro=1")
        m.addOption(":access=udp")
        m.addOption(":drop-late-frames")
//            m.addOption(":codec=all")  //---  I tried this option too, but it lagging at all

        mediaPlayer!!.isSeekable
        mediaPlayer!!.setMedia(m)
        mediaPlayer!!.play()


        mediaPlayer!!.setEventListener { event: MediaPlayer.Event? ->
            when(event?.type) {
                MediaPlayer.Event.Opening -> {
                    Log.i(TAG, "Event Opening")
                }
                MediaPlayer.Event.Buffering -> {
                    Log.i(TAG, "Event Buffering=" + event.getBuffering());
                }
                MediaPlayer.Event.Stopped -> {
                Log.i(TAG , "Event Stopped")
                }

                MediaPlayer.Event.EncounteredError -> {
                    Log.i(TAG , "Hadi paused")

                }
            }
        }


        val cm =
            context?.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        val progressThread = Thread(
            Runnable {
                kotlin.run {
                    try {
                        while (mediaPlayer!=null && !mediaPlayer!!.isPlaying()){}

                        var temp = 0
                        while (mediaPlayer!!.isPlaying()) {

                            val activeNetwork: NetworkInfo? = cm.activeNetworkInfo
                            val isConnected: Boolean? = activeNetwork?.isConnectedOrConnecting
                            if (isConnected == false ) {
                                activity?.runOnUiThread {                                        
                                }
                                temp = 1
                            } else if (isConnected==true && temp == 1) {
                                activity?.runOnUiThread {
                                }
                                //releasePlayer()
                                mSurface!!.requestFocus()
                                mSurface!!.refreshDrawableState()
                                mediaPlayer!!.setMedia(m)
                                mediaPlayer!!.play()
                                temp=0
                                while (!mediaPlayer!!.isPlaying()){}

                            }

                        }
                    } catch (e: java.lang.Exception) {

                    }
                }
            })

        progressThread.start()

    } catch (e: Exception) {
        Toast.makeText(
            activity, "Error in creating player!", Toast
                .LENGTH_LONG
        ).show()
    }

}

fun getWifiLevel(): Int {
    val wifiManager =
        context!!.getSystemService(Context.WIFI_SERVICE) as WifiManager
    val linkSpeed = wifiManager.connectionInfo.rssi
    return WifiManager.calculateSignalLevel(linkSpeed, 5)
}


fun stopAll() {
    mediaPlayer?.stop()
    mediaPlayer = null
    holder = null
    libvlc = null
}

/*
* release player
* */
fun releasePlayer() {
    Log.i(TAG, "releasing player started")
    if (libvlc == null)
        return
    mediaPlayer!!.stop()
    var vout: IVLCVout = mediaPlayer!!.vlcVout
    vout.removeCallback(this)
    vout.detachViews()
    mediaPlayer!!.release()
    mediaPlayer = null
    holder = null
    libvlc!!.release()
    libvlc = null

    Log.i(TAG, "released player")
}

override fun onEvent(event: MediaPlayer.Event) {

    when (event.type) {
        MediaPlayer.Event.EndReached -> {
            this.releasePlayer()
        }

        MediaPlayer.Event.EncounteredError -> {
            Log.i("vlc-lib", "Error Play Video")
            mediaPlayer?.play()
        }

        MediaPlayer.Event.Playing -> Log.i("playing", "playing")
        MediaPlayer.Event.Paused -> {
            Log.i("paused", "paused")
            mediaPlayer?.play()
        }
        MediaPlayer.Event.Stopped -> {
            Log.i("stopped", "stopped")
            mediaPlayer?.play()
        }
        else -> Log.i("nothing", "nothing")
    }
}

override fun onSurfacesCreated(vlcVout: IVLCVout?) {
    val sw = mSurface!!.width
    val sh = mSurface!!.height

    if (sw * sh == 0) {
        Log.e(TAG, "Invalid surface size")
        return
    }

    mediaPlayer!!.vlcVout.setWindowSize(sw, sh)

    mediaPlayer!!.aspectRatio = "Wide-Screen"
    mediaPlayer!!.setScale(0f)
}

override fun onSurfacesDestroyed(vlcVout: IVLCVout?) {
    releasePlayer()
}

}

任何时候我想玩我都会使用它createPlayer

videoController!!.createPlayer("udp://@239.255.2.1:1234")

这是我的活动:

    <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

<SurfaceView
    android:id="@+id/video_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:keepScreenOn="true"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    />

</androidx.constraintlayout.widget.ConstraintLayout>

我尝试了很多选项,但没有成功,我也添加--skip-late-frames了选项。

感谢您的帮助

4

0 回答 0