在GSYVideoPlayer中实现VLC 内核

GSYVideoPlayer 是一个比较火的开源框架。其支持Android 系统中的MediaPlayer内核,ExoPlayer 内核, ijkPlayer 内核。 在我使用的过程中发现不支持h265格式的avi 文件播放,所以我实现了一个VLC内核。

1.继承AbstractMediaPlayer,VLCMediaPlayer.java

public class VLCMediaPlayer extends AbstractMediaPlayer {
    private final LibVLC mLibVLC ;
    private final MediaPlayer mInternalMediaPlayer;
    private String mDataSource;
    private final VLCMediaPlayerListenerHolder mInternalListenerAdapter;
    private final Object mInitLock = new Object();

    private static MediaInfo sMediaInfo;
    private Media mCurrentMedia = null;
    //默认设为1,等开始播放后才能获取到正确的视频宽高
    private int videoWidth=1,videoHeight=1;
    public VLCMediaPlayer() {
        synchronized (mInitLock) {
            ArrayList<String> options = new ArrayList<String>();
            options.add("--avcodec-codec=h265,h264");
            options.add("--rtsp-tcp");
            options.add("--aout=opensles");
            options.add("--audio-time-stretch");
            options.add("-vvv");
            mLibVLC = new LibVLC(SYunApplication.getInstance(),options);
            mInternalMediaPlayer = new MediaPlayer(mLibVLC);
        }
       mInternalListenerAdapter= new VLCMediaPlayerListenerHolder(this);
        attachInternalListeners();
    }

    private void attachInternalListeners() {
        mInternalMediaPlayer.setEventListener(mInternalListenerAdapter);
    }

    @Override
    public void setDisplay(SurfaceHolder sh) {
        Timber.e("call setDisplay ");
    }
@Override
    public void setDataSource(Context context, Uri uri) throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
        mCurrentMedia = new Media(mLibVLC, uri);
        mInternalMediaPlayer.setMedia(mCurrentMedia);
    }

    @Override
    public void setDataSource(Context context, Uri uri, Map<String, String> headers) throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
        mCurrentMedia = new Media(mLibVLC, uri);
        mInternalMediaPlayer.setMedia(mCurrentMedia);
    }

    @Override
    public void setDataSource(FileDescriptor fd) throws IOException, IllegalArgumentException, IllegalStateException {
        mCurrentMedia = new Media(mLibVLC, fd);
        mInternalMediaPlayer.setMedia(mCurrentMedia);
    }

 @Override
    public void setDataSource(String path) throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
        mDataSource=path;
        Timber.e(path);
        if(path.startsWith("http")||path.startsWith("rtsp")){
            mCurrentMedia = new Media(mLibVLC, Uri.parse(mDataSource));
        }else {
            mCurrentMedia = new Media(mLibVLC, path);
        }
        mInternalMediaPlayer.setMedia(mCurrentMedia);
    }

    @Override
    public String getDataSource() {
        return mDataSource;
    }
 @Override
    public void prepareAsync() throws IllegalStateException {
        mCurrentMedia.addOption(":video-paused");
        mInternalMediaPlayer.play();
    }

    @Override
    public void start() throws IllegalStateException {
         Timber.e("start");
        mInternalMediaPlayer.play();
    }

    @Override
    public void stop() throws IllegalStateException {
        mInternalMediaPlayer.stop();
    }

    @Override
    public void pause() throws IllegalStateException {
        mInternalMediaPlayer.pause();
    }
 @Override
    public void setScreenOnWhilePlaying(boolean screenOn) {
//        holder.setKeepScreenOn(true);
    }

    @Override
    public int getVideoWidth() {
        return videoWidth;
    }

    @Override
    public int getVideoHeight() {
        return videoHeight;
    }

    @Override
    public boolean isPlaying() {
        return mInternalMediaPlayer.isPlaying();
    }

    @Override
    public void seekTo(long msec) throws IllegalStateException {
        mInternalMediaPlayer.setTime(msec);
    }

@Override
    public long getCurrentPosition() {
        return  mInternalMediaPlayer.getTime();
    }

    @Override
    public long getDuration() {
        return mInternalMediaPlayer.getLength();
    }

    @Override
    public void release() {
        if(mInternalMediaPlayer != null){
            mInternalMediaPlayer.release();
            mLibVLC.release();
        }
    }

    @Override
    public void reset() {

    }
@Override
    public void setVolume(float leftVolume, float rightVolume) {
        mInternalMediaPlayer.setVolume( (int)((leftVolume + rightVolume) * 100/2));
    }

    @Override
    public int getAudioSessionId() {
        return mInternalMediaPlayer.getAudioTrack();
    }

    @Override
    public MediaInfo getMediaInfo() {
        if (sMediaInfo == null) {
            MediaInfo module = new MediaInfo();

            module.mVideoDecoder = "android";
            module.mVideoDecoderImpl = "HW";

            module.mAudioDecoder = "android";
            module.mAudioDecoderImpl = "HW";

            sMediaInfo = module;
        }

        return sMediaInfo;
    }

 @Override
    public void setLogEnabled(boolean enable) {

    }

    @Override
    public boolean isPlayable() {
        return true;
    }

    @Override
    public void setAudioStreamType(int streamtype) {

    }

    @Override
    public void setKeepInBackground(boolean keepInBackground) {

    }
 /**
     * SAR表示Sample Aspect Ratio,含义是采样宽高比。
     * DAR(Display Aspect Ratio)表示显示宽高比,也就是我们经常说的16:9,4:3。
     * @return SAR
     */
    @Override
    public int getVideoSarNum() {
        IMedia.VideoTrack vtrack = mInternalMediaPlayer.getCurrentVideoTrack();
        int sarNum=vtrack!=null?vtrack.sarNum:1;
        getVideoSize(vtrack);
        return sarNum;
    }

    @Override
    public int getVideoSarDen() {
        IMedia.VideoTrack vtrack = mInternalMediaPlayer.getCurrentVideoTrack();
        int sarDen=vtrack!=null?vtrack.sarDen:1;
        return sarDen;
    }
@Override
    public void setWakeMode(Context context, int mode) {

    }

    @Override
    public void setLooping(boolean looping) {
    }

    @Override
    public boolean isLooping() {
        return false;
    }

    @Override
    public ITrackInfo[] getTrackInfo() {
        return new ITrackInfo[0];
    }

 @Override
    public void setSurface(Surface surface) {
        if(surface!=null){
            mInternalMediaPlayer.getVLCVout().setVideoSurface(surface,null);
            mInternalMediaPlayer.getVLCVout().attachViews(new IVLCVout.OnNewVideoLayoutListener() {
                @Override
                public void onNewVideoLayout(IVLCVout vlcVout, int width, int height, int visibleWidth, int visibleHeight, int sarNum, int sarDen) {
                    Timber.e(" width=%1$d, height=%2$d,visibleWidth=%3$d,visibleHeight=%4$d",width,height,visibleWidth,visibleHeight);
                }
            });
            setWindowSize();
        }
    }

    /**
     * 设置窗口大小为全屏,未正式播放拿不到视频帧的宽高,也只能设置成全屏
     */
   private void setWindowSize() {
        Timber.e("setWindowSize ");
        if (GSYVideoType.getShowType() == SCREEN_MATCH_FULL) {
            int screenWidth = ScreenUtil.getScreenWidth(SYunApplication.getInstance());
            int screenHeight = ScreenUtil.getScreenHeight(SYunApplication.getInstance());
            mInternalMediaPlayer.getVLCVout().setWindowSize(screenWidth, screenHeight);
            mInternalMediaPlayer.setScale(0);
            //视频显示比例
            String aspectRatio = String.format("%1$s:%2$s", screenWidth, screenHeight);
            Timber.e("setWindowSize ,aspectRatio=%s", aspectRatio);
            mInternalMediaPlayer.setAspectRatio(aspectRatio);
        } else {
            int screenHeight = ScreenUtil.getScreenHeight(SYunApplication.getInstance());
            mInternalMediaPlayer.getVLCVout().setWindowSize(videoWidth * screenHeight / videoHeight, screenHeight);
            mInternalMediaPlayer.setScale(0);
            //视频显示比例
            String aspectRatio = String.format("%1$s:%2$s", videoWidth, videoHeight);
            Timber.e("getVideoSize ,aspectRatio=%s", aspectRatio);
            mInternalMediaPlayer.setAspectRatio(aspectRatio);
        }
    }


    public MediaPlayer getmInternalMediaPlayer() {
        return mInternalMediaPlayer;
    }

 private static class VLCMediaPlayerListenerHolder implements MediaPlayer.EventListener{
        public final WeakReference<VLCMediaPlayer> mWeakMediaPlayer;

        public VLCMediaPlayerListenerHolder(VLCMediaPlayer mp) {
            mWeakMediaPlayer = new WeakReference<VLCMediaPlayer>(mp);
        }


        @Override
        public void onEvent(MediaPlayer.Event event) {
            try{
                VLCMediaPlayer self = mWeakMediaPlayer.get();
                switch(event.type) {
                    case MediaPlayer.Event.Opening:
                        if (self == null)
                            return;
                        self.pause();
                        self.notifyOnPrepared();
                        break;
                    case MediaPlayer.Event.Playing:
                        Timber.e("Playing");
                        break;
                    case MediaPlayer.Event.Paused:
                        Timber.e("Paused");
                       break;
                    case MediaPlayer.Event.EncounteredError:
                        Timber.e("EncounteredError");
                        if (self == null)
                            return;
                        self.notifyOnError(MediaPlayer.Event.EncounteredError,-1);
                    case  MediaPlayer.Event.Vout:
                        Timber.e("Vout");
                        break;
                    case MediaPlayer.Event.EndReached:
                        if (self == null)
                            return;
                        self.notifyOnCompletion();
                        break;
                    default:
//                        Timber.e("default"+event.type);
                        break;
                }
                if(mWeakMediaPlayer.get().getmInternalMediaPlayer().getPlayerState()==Media.State.Ended){
                    if (self == null)
                        return;
                    self.notifyOnCompletion();
  }
            }catch (Exception e){

            }
        }
    }
/**
     * 读取视频宽高,切换窗口大小时可以触发,获取到视频宽高
     * @param track 流信息
     */
    private void getVideoSize(IMedia.VideoTrack track) {
        if (track!=null) {
            if(track.width>0&&track.height>0){
                videoWidth = track.width;
                videoHeight = track.height;
                Timber.e("getVideoSize w=%1$d,h=%2$d", videoWidth, videoHeight);
                setWindowSize();
            }
        }
    }



}

 2.继承BasePlayerManager实现VLCPlayerManager.java

import android.content.Context;
import android.os.Message;
import android.text.TextUtils;
import android.view.Surface;

import com.shuyu.gsyvideoplayer.cache.ICacheManager;
import com.shuyu.gsyvideoplayer.model.GSYModel;
import com.shuyu.gsyvideoplayer.model.VideoOptionModel;
import com.shuyu.gsyvideoplayer.player.BasePlayerManager;

import java.io.IOException;
import java.util.List;

import tv.danmaku.ijk.media.player.IMediaPlayer;

public class VLCPlayerManager extends BasePlayerManager {

    private VLCMediaPlayer mediaPlayer;
    private Surface surface;

    @Override
    public IMediaPlayer getMediaPlayer() {
        return mediaPlayer;
    }

    @Override
    public void initVideoPlayer(Context context, Message msg, List<VideoOptionModel> optionModelList, ICacheManager cacheManager) {
        mediaPlayer=new VLCMediaPlayer();
        GSYModel gsyModel = (GSYModel) msg.obj;
        String url = gsyModel.getUrl();
        if(!TextUtils.isEmpty(url)){
            try {
                mediaPlayer.setDataSource(url);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    @Override
    public void showDisplay(Message msg) {
        if (msg.obj == null && mediaPlayer != null) {
            mediaPlayer.setSurface(null);
        } else {
            Surface holder = (Surface) msg.obj;
            surface = holder;
            if (mediaPlayer != null && holder.isValid()) {
                mediaPlayer.setSurface(holder);
            }
        }
    }
    @Override
    public void setNeedMute(boolean needMute) {
        if (mediaPlayer != null) {
            if (needMute) {
                mediaPlayer.setVolume(0, 0);
            } else {
                mediaPlayer.setVolume(1, 1);
            }
        }
    }

    @Override
    public void setVolume(float left, float right) {
        if (mediaPlayer != null) {
            mediaPlayer.setVolume(left, right);
        }
    }

    @Override
    public void releaseSurface() {
        if (surface != null) {
            //surface.release();
            surface = null;
        }
    }

    @Override
    public void release() {
        if (mediaPlayer != null) {
            mediaPlayer.release();
            mediaPlayer = null;
        }
    }

    @Override
    public int getBufferedPercentage() {
        return -1;
    }

    @Override
    public long getNetSpeed() {
        return 0;
    }

    @Override
    public void setSpeedPlaying(float speed, boolean soundTouch) {

    }

    @Override
    public boolean isSurfaceSupportLockCanvas() {
        return false;
    }

    @Override
    public void setSpeed(float speed, boolean soundTouch) {

    }


    @Override
    public void start() {
        if (mediaPlayer != null) {
            mediaPlayer.start();
        }
    }

    @Override
    public void stop() {
        if (mediaPlayer != null) {
            mediaPlayer.stop();
        }
    }

    @Override
    public void pause() {
        if (mediaPlayer != null) {
            mediaPlayer.pause();
        }
    }

    @Override
    public int getVideoWidth() {
        if (mediaPlayer != null) {
            return mediaPlayer.getVideoWidth();
        }
        return 0;
    }

    @Override
    public int getVideoHeight() {
        if (mediaPlayer != null) {
            return mediaPlayer.getVideoHeight();
        }
        return 0;
    }

    @Override
    public boolean isPlaying() {
        if (mediaPlayer != null) {
            return mediaPlayer.isPlaying();
        }
        return false;
    }

    @Override
    public void seekTo(long time) {
        if (mediaPlayer != null) {
            mediaPlayer.seekTo(time);
        }
    }

    @Override
    public long getCurrentPosition() {
        if (mediaPlayer != null) {
            return mediaPlayer.getCurrentPosition();
        }
        return 0;
    }

    @Override
    public long getDuration() {
        if (mediaPlayer != null) {
            return mediaPlayer.getDuration();
        }
        return 0;
    }

    @Override
    public int getVideoSarNum() {
        if (mediaPlayer != null) {
            return mediaPlayer.getVideoSarNum();
        }
        return 1;
    }

    @Override
    public int getVideoSarDen() {
        if (mediaPlayer != null) {
            return mediaPlayer.getVideoSarDen();
        }
        return 1;
    }
}

3.使用方法:

1.添加依赖

//gsyVideoPlayer播放器
    implementation 'com.github.CarGuo.GSYVideoPlayer:gsyVideoPlayer-java:v8.1.7-release-jitpack'
    //更多ijk的编码支持
    implementation 'com.github.CarGuo.GSYVideoPlayer:gsyVideoPlayer-ex_so:v8.1.7-release-jitpack'
//VLC
    implementation 'de.mrmaffen:vlc-android-sdk:3.0.0'

2.调用


            PlayerFactory.setPlayManager(VLCPlayerManager.class);
            mVideoPlayer.setUp(url,true,"");
            //设置旋转
            orientationUtils = new OrientationUtils(this, mVideoPlayer);
            //设置全屏按键功能,这是使用的是选择屏幕,而不是全屏
            mVideoPlayer.getFullscreenButton().setOnClickListener(v->{
                orientationUtils.resolveByClick();
            });
            //是否可以滑动调整
            mVideoPlayer.setIsTouchWiget(true);
            //设置返回按键功能
            mVideoPlayer.startPlayLogic();

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值