无法使用 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 度视频

Android LibVLC,在没有 TextureView 的情况下拍摄 RTSP 流的快照

libVLC 视频缩放

libvlc播放m3u8流 无法获得视频长度问题[记录]

将视频从 Raspberry Pi 流式传输到 Android 应用程序