从android vlc媒体播放器获取当前帧

时间:2018-11-10 12:18:57

标签: android vlc libvlc vlc-android

我正在使用VLC-Android来在我的android应用程序中播放H264 RTSP实时流,以下代码成功地将流视频呈现到了表面视图上:

MediaPlayer mMediaPlayer = new MediaPlayer(VLCInstance.get());
SurfaceView mSurfaceView = (SurfaceView) findViewById(R.id.player);

final IVLCVout vlcVout = Constants.mMediaPlayer.getVLCVout();
vlcVout.detachViews();
vlcVout.setVideoView(mSurfaceView);
vlcVout.setWindowSize(mSurfaceDims.getWidth(), mSurfaceDims.getHeight());
vlcVout.attachViews();
mSurfaceView.setKeepScreenOn(true);

Media media = new Media(VLCInstance.get(), Uri.parse(path));
mMediaPlayer.setMedia(media);
mMediaPlayer.play();

VLCInstance.java:

package bi.anpr.vlc;

import android.content.Context;
import android.util.Log;

import org.videolan.libvlc.LibVLC;
import org.videolan.libvlc.util.VLCUtil;

public class VLCInstance {
    public final static String TAG = "VLC/Util/VLCInstance";

    private static LibVLC sLibVLC = null;

    /** A set of utility functions for the VLC application */
    public synchronized static LibVLC get() throws IllegalStateException {
        if (sLibVLC == null) {
            final Context context = VLCApplication.getAppContext();
            if(!VLCUtil.hasCompatibleCPU(context)) {
                Log.e(TAG, VLCUtil.getErrorMsg());
                throw new IllegalStateException("LibVLC initialisation failed: " + VLCUtil.getErrorMsg());
            }

            try{
                sLibVLC = new LibVLC(context);
            }catch (Throwable e){
                e.printStackTrace();
            }

        }
        return sLibVLC;
    }

    public static synchronized void restart(Context context) throws IllegalStateException {
        if (sLibVLC != null) {
            sLibVLC.release();
            sLibVLC = new LibVLC(context);
        }
    }
}

问题在于,org.videolan.libvlc.MediaPlayer在调用play()之后在SurfaceView上呈现视频,而没有任何事件可帮助您在视图上捕获当前帧,在此我需要获取每个间隔的当前帧是时候对它执行一些图像处理了。

在播放实时流或本地视频资源时,是否可以使用vlc-android-sdk将当前帧捕获到缓冲的图像或OpenCV Mat中?

请注意,对于Java(桌面vlcj),可以通过 DirectMediaPlayer 类实现。

提前谢谢!

1 个答案:

答案 0 :(得分:0)

我找到了一个非常简单,非常快速的解决方案。只需使用 TextureView 而不是 SurfaceView ,然后在播放时随时使用getBitmap()函数检索图像,如下所示。

public class MainActivity extends AppCompatActivity implements TextureView.SurfaceTextureListener,
        org.videolan.libvlc.media.MediaPlayer.OnBufferingUpdateListener,
        org.videolan.libvlc.media.MediaPlayer.OnCompletionListener,
        org.videolan.libvlc.media.MediaPlayer.OnPreparedListener,
        org.videolan.libvlc.media.MediaPlayer.OnVideoSizeChangedListener {

    private AppCompatActivity me = this;    
    private MediaPlayer mMediaPlayer;    
    private TextureView mTextureViewmTextureView;
    private String mUrl = "/storage/emulated/0/videos/test.mp4";
    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.content_main);

        mMediaPlayer = new MediaPlayer(VLCInstance.get());
        mTextureViewmTextureView = (TextureView) findViewById(R.id.player);
        mTextureView.setSurfaceTextureListener(this);
    }

    private void attachViewSurface() {
            final IVLCVout vlcVout = mMediaPlayer.getVLCVout();
            mMediaPlayer.setScale(0);
            vlcVout.detachViews();
            vlcVout.setVideoView(mTextureView);
            vlcVout.setWindowSize(mTextureView.getWidth(), mTextureView.getHeight());
            vlcVout.attachViews();
            mTextureView.setKeepScreenOn(true);
    }


    private void play(String path) {
       try {
            Media media;
            if (new File(path).exists()) {
                media = new Media(VLCInstance.get(), path);
            } else {
                media = new Media(VLCInstance.get(), Uri.parse(path));
            }

            mMediaPlayer.setMedia(media);
            mMediaPlayer.play();
        } catch (Exception e) {
            Log.e(TAG, e.getMessage());
        }
   }

   @Override
   public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
       attachViewSurface();

       if (mMediaPlayer.hasMedia())
           mMediaPlayer.play();
       else
           play(mUrl);
   }

   public Bitmap getImage() {
       return mTextureView.getBitmap();
   }

}

VLCInstance.java:

import android.content.Context;
import android.util.Log;

import org.videolan.libvlc.LibVLC;
import org.videolan.libvlc.util.VLCUtil;

public class VLCInstance {
    public final static String TAG = "VLC/Util/VLCInstance";

    private static LibVLC sLibVLC = null;

    /** A set of utility functions for the VLC application */
    public synchronized static LibVLC get() throws IllegalStateException {
        if (sLibVLC == null) {
            final Context context = VLCApplication.getAppContext();
            if(!VLCUtil.hasCompatibleCPU(context)) {
                Log.e(TAG, VLCUtil.getErrorMsg());
                throw new IllegalStateException("LibVLC initialisation failed: " + VLCUtil.getErrorMsg());
            }

            try{
                sLibVLC = new LibVLC(context);
            }catch (Throwable e){
                e.printStackTrace();
            }

        }
        return sLibVLC;
    }

    public static synchronized void restart(Context context) throws IllegalStateException {
        if (sLibVLC != null) {
            sLibVLC.release();
            sLibVLC = new LibVLC(context);
        }
    }
}