我尝试在 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
了选项。
感谢您的帮助