Получение текущего кадра из медиа-плеера Android vlc - PullRequest
0 голосов
/ 10 ноября 2018

Я использую VLC-Android для воспроизведения живого потока H264 RTSP в моем приложении для Android, следующий код успешно отображает потоковое видео на виде поверхности:

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 отображает видео в SurfaceView после вызова play () без какого-либо события, которое помогает вам захватить текущий кадр в представлении, где мне нужно получать текущий кадр каждый интервал времени, чтобы выполнить некоторую обработку изображения на нем.

Так возможно ли использовать vlc-android-sdk для захвата текущего кадра в буферизованное изображение или OpenCV Mat при воспроизведении потокового видео или локальных видеоресурсов?

Обратите внимание, что это возможно с java (desktop vlcj) через класс DirectMediaPlayer .

Заранее спасибо !!

1 Ответ

0 голосов
/ 22 ноября 2018

Я нашел очень простое и очень быстрое решение для этого. Просто используйте 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);
        }
    }
}
...