无法使用 LibVLC 在 android 应用上加载 m3u 播放列表
Posted
技术标签:
【中文标题】无法使用 LibVLC 在 android 应用上加载 m3u 播放列表【英文标题】:Failure to load m3u playlist on android app using LibVLC 【发布时间】:2019-08-08 11:14:01 【问题描述】:我正在使用 LibVLC 测试一个 IPTV 应用程序,我想帮助加载和播放 m3u 播放列表,但不幸的是它没有工作。我通过最初测试在线 mp4 链接确认播放器可以正常运行,但未能运行。
使用库de.mrmaffen:libvlc-android:2.1.12@aar
,我的播放器的代码是:
视频活动:
public class VideoActivity extends Activity implements IVLCVout.Callback
public final static String TAG = "IPTV";
public final static String LOCATION = "com.example.android.tvleanback.ui.VideoActivity.location";
private String mFilePath;
// display surface
private SurfaceView mSurface;
private SurfaceHolder holder;
// media player
private LibVLC libvlc;
private MediaPlayer mMediaPlayer = null;
private int mVideoWidth;
private int mVideoHeight;
private final static int VideoSizeChanged = -1;
/*************
* Activity
*************/
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.sample);
// Receive path to play from intent
Intent intent = getIntent();
mFilePath = intent.getExtras().getString("stream");
Log.d(TAG, "Playing back " + mFilePath);
mSurface = (SurfaceView) findViewById(R.id.surface);
holder = mSurface.getHolder();
//holder.addCallback(this);
@Override
public void onConfigurationChanged(Configuration newConfig)
super.onConfigurationChanged(newConfig);
setSize(mVideoWidth, mVideoHeight);
@Override
protected void onResume()
super.onResume();
createPlayer(mFilePath);
@Override
protected void onPause()
super.onPause();
releasePlayer();
@Override
protected void onDestroy()
super.onDestroy();
releasePlayer();
/*************
* Surface
*************/
private void setSize(int width, int height)
mVideoWidth = width;
mVideoHeight = height;
if (mVideoWidth * mVideoHeight <= 1)
return;
if(holder == null || mSurface == null)
return;
// get screen size
int w = getWindow().getDecorView().getWidth();
int h = getWindow().getDecorView().getHeight();
// getWindow().getDecorView() doesn't always take orientation into
// account, we have to correct the values
boolean isPortrait = getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
if (w > h && isPortrait || w < h && !isPortrait)
int i = w;
w = h;
h = i;
float videoAR = (float) mVideoWidth / (float) mVideoHeight;
float screenAR = (float) w / (float) h;
if (screenAR < videoAR)
h = (int) (w / videoAR);
else
w = (int) (h * videoAR);
// force surface buffer size
holder.setFixedSize(mVideoWidth, mVideoHeight);
// set display size
LayoutParams lp = mSurface.getLayoutParams();
lp.width = w;
lp.height = h;
mSurface.setLayoutParams(lp);
mSurface.invalidate();
/*************
* Player
*************/
private void createPlayer(String media)
releasePlayer();
try
if (media.length() > 0)
Toast toast = Toast.makeText(this, media, Toast.LENGTH_LONG);
toast.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0,
0);
toast.show();
// Create LibVLC
// TODO: make this more robust, and sync with audio demo
ArrayList<String> options = new ArrayList<String>();
//options.add("--subsdec-encoding <encoding>");
options.add("--aout=opensles");
options.add("--audio-time-stretch"); // time stretching
options.add("-vvv"); // verbosity
options.add("--http-reconnect");
options.add("--network-caching="+6*1000);
libvlc = new LibVLC(this, options);
//libvlc.setOnHardwareAccelerationError(this);
holder.setKeepScreenOn(true);
// Create media player
mMediaPlayer = new MediaPlayer(libvlc);
mMediaPlayer.setEventListener(mPlayerListener);
// Set up video output
final IVLCVout vout = mMediaPlayer.getVLCVout();
vout.setVideoView(mSurface);
//vout.setSubtitlesView(mSurfaceSubtitles);
vout.addCallback(this);
vout.attachViews();
Media m = new Media(libvlc, Uri.parse(media));
mMediaPlayer.setMedia(m);
mMediaPlayer.play();
catch (Exception e)
Toast.makeText(this, "Error creating player!", Toast.LENGTH_LONG).show();
mSurface.getRootView().setOnTouchListener(new View.OnTouchListener()
@Override
public boolean onTouch(View view, MotionEvent event)
if (event.getActionMasked() == MotionEvent.ACTION_DOWN)
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
Float p = event.getX()/size.x;
Long pos = (long) (mMediaPlayer.getLength() / p);
if (mMediaPlayer.isSeekable())
//mLibVLC.setTime( pos );
mMediaPlayer.setPosition(p);
else
return true;
);
// TODO: handle this cleaner
private void releasePlayer()
if (libvlc == null)
return;
mMediaPlayer.stop();
final IVLCVout vout = mMediaPlayer.getVLCVout();
vout.removeCallback(this);
vout.detachViews();
holder = null;
libvlc.release();
libvlc = null;
mVideoWidth = 0;
mVideoHeight = 0;
/*************
* Events
*************/
private MediaPlayer.EventListener mPlayerListener = new MyPlayerListener(this);
public void onNewLayout(IVLCVout vout, int width, int height, int visibleWidth, int visibleHeight, int sarNum, int sarDen)
if (width * height == 0)
return;
// store video size
mVideoWidth = width;
mVideoHeight = height;
setSize(mVideoWidth, mVideoHeight);
@Override
public void onSurfacesCreated(IVLCVout vout)
@Override
public void onSurfacesDestroyed(IVLCVout vout)
private static class MyPlayerListener implements MediaPlayer.EventListener
private WeakReference<VideoActivity> mOwner;
public MyPlayerListener(VideoActivity owner)
mOwner = new WeakReference<VideoActivity>(owner);
@Override
public void onEvent(MediaPlayer.Event event)
VideoActivity player = mOwner.get();
Log.d(TAG, "Player EVENT");
switch(event.type)
case MediaPlayer.Event.EndReached:
Log.d(TAG, "MediaPlayerEndReached");
player.releasePlayer();
break;
case MediaPlayer.Event.EncounteredError:
Log.d(TAG, "Media Player Error, re-try");
//player.releasePlayer();
break;
case MediaPlayer.Event.Playing:
case MediaPlayer.Event.Paused:
case MediaPlayer.Event.Stopped:
default:
break;
public void onHardwareAccelerationError(IVLCVout vout)
// Handle errors with hardware acceleration
Log.e(TAG, "Error with hardware acceleration");
this.releasePlayer();
Toast.makeText(this, "Error with hardware acceleration", Toast.LENGTH_LONG).show();
tvActivity
public class tvActivity extends LeanbackActivity
DirectorAdaptor mAdapter;
LibVLC mLibVLC = null;
MediaPlayer mMediaPlayer = null;
boolean mPlayingVideo = false; // Don't destroy libVLC if the video activity is playing.
private void playMediaAtPath(String path)
// To play with LibVLC, we need a media player object.
// Let's get one, if needed.
if(mMediaPlayer == null)
mMediaPlayer = new MediaPlayer(mLibVLC);
// Create a new Media object for the file.
// Each media - a song, video, or stream is represented by a Media object for LibVLC.
Media m = new Media(mLibVLC, path);
// Tell the media player to play the new Media.
mMediaPlayer.setMedia(m);
// Finally, play it!
mMediaPlayer.play();
@Override
protected void onCreate(Bundle savedInstanceState)
try
mLibVLC = new LibVLC(this);
catch(IllegalStateException e)
Toast.makeText(tvActivity.this,
"Error initializing the libVLC multimedia framework!",
Toast.LENGTH_LONG).show();
finish();
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_stream);
Intent intent = new Intent(tvActivity.this, VideoActivity.class);
//intent.putExtra(VideoActivity.LOCATION, "http://dl.strem.io/BigBuckBunny_512kb.mp4");
intent.putExtra("stream", "http://129.205.0.34/twendesmart/tube/testIPTV/IPTVWorld.m3u");
startActivity(intent);
这是播放器的问题,还是需要额外的库来解析 m3u 播放列表?
谢谢
【问题讨论】:
【参考方案1】:要使用 libvlc 播放 m3u,您需要:
-
从你的 m3u 创建一个
Media
(你已经完成了)。
在 Media
上调用 parse,如果 m3u 是远程流,则可能使用 ParseNetwork
选项。
解析完成后从媒体中探索子项。
通过将其中一个子项提供给媒体播放器来播放它。
祝你好运。
【讨论】:
以上是关于无法使用 LibVLC 在 android 应用上加载 m3u 播放列表的主要内容,如果未能解决你的问题,请参考以下文章
使用为 android 编译的 LibVLC 从 MPEG2 流中显示 DVB 字幕
如何在 iOS 中使用 VLC Player 使用 libvlc 播放 360 度视频