gsyVideoPlayer直播短视频回放,集成腾讯播放器

前言

gsyVideoPlayer是一个很棒的播放器,也可以当成是对ijkPlayer的封装库。
在初始化时,可以写如下代码。当然这是默认的,可以不写。

PlayerFactory.setPlayManager(IjkPlayerManager.class);

默认选择ijkplayer播放,那么像使用其他播放器怎么办,gsyVideoPlayer提供了如下选择:

PlayerFactory.setPlayManager(IjkPlayerManager.class);//ijk内核,默认模式
PlayerFactory.setPlayManager(SystemPlayerManager.class);//系统内核模式
PlayerFactory.setPlayManager(Exo2PlayerManager.class);//EXOPlayer内核

但是这三种都不是自己想用的怎么办,如果使用腾讯播放器如何集成进去?
翻看PlayerFactory的源码,在 getPlayManager 方法会返回一个IPlayerManager对象,那么我只要写一个QQPlayerManager,然后在这样初始化就行了。

PlayerFactory.setPlayManager(QQPlayerManager.class);//使用腾讯播放器

集成腾讯播放器

在写QQPlayerManager前,需要去腾讯播放器网站 下载SDK。然后如下方式集成:

compile(name: 'LiteAVSDK_Player', ext: 'aar')
//compile(name: 'libsuperplayer', ext: 'aar')//使用gsyVideoPlayer,这个就可以不要了

接着就可以直接写了,QQPlayerManager要实现IPlayerManager,那么写起来只要将接口IPlayerManager的方法实现既可以,此处就直接贴代码了。
QQPlayerManager.java

package com.shopshops.cn.player;

import android.content.Context;
import android.media.AudioManager;
import android.os.Message;
import android.view.Surface;

import com.shopshops.cn.BuildConfig;
import com.shuyu.gsyvideoplayer.cache.ICacheManager;
import com.shuyu.gsyvideoplayer.model.GSYModel;
import com.shuyu.gsyvideoplayer.model.VideoOptionModel;
import com.shuyu.gsyvideoplayer.player.IPlayerManager;

import java.util.List;

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

public class QQPlayerManager implements IPlayerManager {
    private QQMediaPlayer mediaPlayer;
    private boolean release;
    private Surface surface;

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

    @Override
    public void initVideoPlayer(Context context, Message message, List<VideoOptionModel> optionModelList, ICacheManager cacheManager) {
        boolean enableHardware = true;
        /*GSYVideoManager videoManager = GSYVideoManager.instance();
        String playTag = videoManager.getPlayTag();
        if (!TextUtils.isEmpty(playTag))
            enableHardware = playTag.startsWith("m3u8Speed");*/

        mediaPlayer = new QQMediaPlayer(context, enableHardware);
        mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        release = false;
        GSYModel gsyModel = (GSYModel) message.obj;
        try {
            if (gsyModel.isCache() && cacheManager != null) {
                cacheManager.doCacheLogic(context, mediaPlayer, gsyModel.getUrl(), gsyModel.getMapHeadData(), gsyModel.getCachePath());
            } else mediaPlayer.setDataSource(gsyModel.getUrl());
            mediaPlayer.setLooping(gsyModel.isLooping());
            if (gsyModel.getSpeed() != 1 && gsyModel.getSpeed() > 0) {
                setSpeed(gsyModel.getSpeed());
            }
        } catch (Exception e) {
            if (BuildConfig.DEBUG) e.printStackTrace();
        }
    }

    @Override
    public void showDisplay(Message msg) {
        Surface holder = (Surface) msg.obj;
        if (holder == null && mediaPlayer != null && !release) {
            mediaPlayer.setSurface(null);
        } else if (holder != null) {
            if (mediaPlayer != null && holder.isValid() && !release) {
                mediaPlayer.setSurface(holder);
            }
            //if (surface != null) surface.release();
            surface = holder;
        }
    }

    @Override
    public void setNeedMute(boolean needMute) {//是否静音
        if (mediaPlayer != null && !release) {
            if (needMute) {
                mediaPlayer.setVolume(0, 0);
            } else mediaPlayer.setVolume(1, 1);
        }
    }

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

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

    @Override
    public int getBufferedPercentage() {
        if (mediaPlayer == null) return -1;
        else return (int) mediaPlayer.getMediaPlayer().getBufferDuration();
    }

    @Override
    public long getNetSpeed() {
        //if (mediaPlayer == null)
        return 0;
    }

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

    }

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

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

    private void setSpeed(float speed) {
        if (release) {
            return;
        }
        if (mediaPlayer != null && mediaPlayer.getMediaPlayer() != null && mediaPlayer.isPlayable()) {
            mediaPlayer.getMediaPlayer().setRate(speed);
        }
    }

    @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 0;
        else return mediaPlayer.getVideoWidth();
    }

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

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

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

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

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

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

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

initVideoPlayer用于初始化mediaPlayer ,mediaPlayer 是视频播放的核心,那么这儿也就少不了使用腾讯的mediaPlayer 。
QQMediaPlayer.java

package com.shopshops.cn.player;

import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import android.text.TextUtils;
import android.view.Surface;
import android.view.SurfaceHolder;

import com.shopshops.cn.BuildConfig;
import com.shopshops.cn.base.AppConstant;
import com.shopshops.mylibrary.Logger;
import com.tencent.rtmp.ITXVodPlayListener;
import com.tencent.rtmp.TXLiveConstants;
import com.tencent.rtmp.TXVodPlayer;

import java.io.FileDescriptor;
import java.io.IOException;
import java.util.Map;

import tv.danmaku.ijk.media.player.AbstractMediaPlayer;
import tv.danmaku.ijk.media.player.MediaInfo;
import tv.danmaku.ijk.media.player.misc.ITrackInfo;

public class QQMediaPlayer extends AbstractMediaPlayer {
    private TXVodPlayer txVodPlayer;
    private MediaInfo mediaInfo;
    private boolean mIsReleased;
    private boolean isPause;
    private String url;
    private Surface surface;
    private boolean canStart;
    private long progress_ms;//播放进度
    private long duration_ms_total;//视频总长
    private Context mContext;
    //notifyOnError

    public QQMediaPlayer(Context context, boolean enableHardware) {
        this.mContext = context;
        txVodPlayer = new TXVodPlayer(context);
        txVodPlayer.enableHardwareDecode(enableHardware);
        txVodPlayer.setVodListener(new ITXVodPlayListener() {
            @Override
            public void onPlayEvent(TXVodPlayer txVodPlayer, int event, Bundle param) {
                if (BuildConfig.DEBUG) Logger.i("--xcc--QQMediaPlayer", "--event--" + event);
                if (event == TXLiveConstants.PLAY_EVT_PLAY_BEGIN) {//视频播放开始
                    notifyOnPrepared();
                    if (BuildConfig.DEBUG) Logger.i("--xcc--QQMediaPlayer", "视频播放开始");
                } else if (event == TXLiveConstants.PLAY_EVT_VOD_LOADING_END) {//loadingEnd
                    if (BuildConfig.DEBUG) Logger.i("--xcc--QQMediaPlayer", "loadingEnd");
                    //没有这个事件,发一个广播出去
                    LocalBroadcastManager.getInstance(mContext).sendBroadcast(new Intent(AppConstant.PLAY_EVT_VOD_LOADING_END));
                } else if (event == TXLiveConstants.PLAY_EVT_PLAY_PROGRESS) {//视频播放进度
                    // 加载进度, 单位是毫秒
                    int duration_ms = param.getInt(TXLiveConstants.EVT_PLAYABLE_DURATION_MS);
                    // 播放进度, 单位是毫秒
                    progress_ms = param.getInt(TXLiveConstants.EVT_PLAY_PROGRESS_MS);
                    // 视频总长, 单位是毫秒
                    duration_ms_total = param.getInt(TXLiveConstants.EVT_PLAY_DURATION_MS);
                    if (BuildConfig.DEBUG) {
                        Logger.i("--xcc--QQMediaPlayer", "播放进度:" + param.getInt(TXLiveConstants.EVT_PLAY_PROGRESS_MS));
                    }
                    notifyOnBufferingUpdate(duration_ms);
                } else if (event == TXLiveConstants.PLAY_EVT_PLAY_END) {//视频播放结束
                    notifyOnCompletion();
                    if (BuildConfig.DEBUG) Logger.i("--xcc--QQMediaPlayer", "视频播放结束");
                } else if (event == TXLiveConstants.PLAY_ERR_NET_DISCONNECT || event == TXLiveConstants.PLAY_WARNING_RECONNECT) {//网络断连
                    notifyOnError(event, 1);
                    if (BuildConfig.DEBUG) Logger.i("--xcc--QQMediaPlayer", "网络断连");
                } else if (event == TXLiveConstants.PLAY_WARNING_VIDEO_DECODE_FAIL) {//当前视频帧解码失败
                    notifyOnError(event, 1);
                    if (BuildConfig.DEBUG) Logger.i("--xcc--QQMediaPlayer", "当前视频帧解码失败");
                } else if (event == TXLiveConstants.PLAY_WARNING_AUDIO_DECODE_FAIL) {//当前音频帧解码失败
                    notifyOnError(event, 1);
                    if (BuildConfig.DEBUG) Logger.i("--xcc--QQMediaPlayer", "当前音频帧解码失败");
                } else if (event == TXLiveConstants.PLAY_WARNING_HW_ACCELERATION_FAIL) {//硬解失败
                    if (BuildConfig.DEBUG) Logger.i("--xcc--QQMediaPlayer", "硬解失败");
                } else if (event == TXLiveConstants.PLAY_EVT_CHANGE_RESOLUTION) {//视频分辨率改变
                    notifyOnVideoSizeChanged(param.getInt(TXLiveConstants.EVT_PARAM1), param.getInt(TXLiveConstants.EVT_PARAM2), getVideoSarNum(), getVideoSarNum());
                    if (BuildConfig.DEBUG) Logger.i("--xcc--QQMediaPlayer", "视频分辨率改变");
                }
            }

            @Override
            public void onNetStatus(TXVodPlayer txVodPlayer, Bundle bundle) {

            }
        });
    }

    @Override
    public void setDisplay(SurfaceHolder sh) {
        Surface surface = sh.getSurface();
        setSurface(surface);
    }

    @Override
    public void setDataSource(Context context, Uri uri) throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
        this.url = uri.getPath();
    }

    @Override
    public void setDataSource(Context context, Uri uri, Map<String, String> map) throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
        this.url = uri.toString();
    }

    @Override
    public void setDataSource(FileDescriptor fileDescriptor) throws IOException, IllegalArgumentException, IllegalStateException {
    }

    @Override
    public void setDataSource(String url) throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
        this.url = url;
    }

    @Override
    public String getDataSource() {
        return url;
    }

    @Override
    public void prepareAsync() throws IllegalStateException {
        notifyOnPrepared();
    }

    @Override
    public void start() throws IllegalStateException {
        if (isPause) {//暂停后恢复播放
            isPause = false;
            txVodPlayer.resume();
        } else {
            if (TextUtils.isEmpty(url) || surface == null) {
                canStart = true;
                return;
            }
            this.txVodPlayer.startPlay(url);
        }
    }

    @Override
    public void stop() throws IllegalStateException {
        isPause = false;
        this.txVodPlayer.stopPlay(false);
    }

    @Override
    public void pause() throws IllegalStateException {
        isPause = true;
        this.txVodPlayer.pause();
    }

    @Override
    public void setScreenOnWhilePlaying(boolean screenOn) {
        //txVodPlayer.setScreenOnWhilePlaying(screenOn);
    }

    @Override
    public int getVideoWidth() {
        return txVodPlayer.getWidth();
    }

    @Override
    public int getVideoHeight() {
        return txVodPlayer.getHeight();
    }

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

    @Override
    public void seekTo(long msec) throws IllegalStateException {
        float v = msec / 1000.0f;
        this.txVodPlayer.seek(v);//腾讯这儿是百分比
    }

    @Override
    public long getCurrentPosition() {
        return progress_ms;
        //return (long) txVodPlayer.getCurrentPlaybackTime();
    }

    @Override
    public long getDuration() {
        return duration_ms_total;
        //float duration = txVodPlayer.getDuration();
        //return (long) duration;
    }

    @Override
    public void release() {
        txVodPlayer.stopPlay(true);
        this.mIsReleased = true;
        this.resetListeners();
    }

    @Override
    public void reset() {
        //txVodPlayer.resume();//这个是恢复播放的
        this.resetListeners();
    }

    @Override
    public void setVolume(float leftVolume, float rightVolume) {
        txVodPlayer.setMute(leftVolume + rightVolume == 0);
    }

    @Override
    public int getAudioSessionId() {
        return 0;
    }

    @Override
    public MediaInfo getMediaInfo() {
        if (mediaInfo == null) {
            MediaInfo module = new MediaInfo();
            module.mVideoDecoder = "QQMediaPlayer";
            module.mVideoDecoderImpl = "HW";
            module.mAudioDecoder = "QQMediaPlayer";
            module.mAudioDecoderImpl = "HW";
            mediaInfo = module;
        }
        return mediaInfo;
    }

    @Override
    public void setLogEnabled(boolean b) {
    }

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

    @Override
    public void setAudioStreamType(int streamtype) {
    }

    @Override
    public void setKeepInBackground(boolean keepInBackground) {

    }

    @Override
    public int getVideoSarNum() {
        return 1;
    }

    @Override
    public int getVideoSarDen() {
        return 1;
    }

    @Override
    public void setWakeMode(Context context, int mode) {
    }

    @Override
    public void setLooping(boolean b) {
        txVodPlayer.setLoop(b);
    }

    @Override
    public boolean isLooping() {
        return txVodPlayer.isLoop();
    }

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

    @Override
    public void setSurface(Surface surface) {
        if (surface == this.surface) return;
        this.surface = surface;
        /*if (surface == null) {
            if (!isPause) pause();
        }*/
        txVodPlayer.setSurface(surface);
        if (surface == null) return;
        if (TextUtils.isEmpty(url)) return;
        if (canStart) {
            canStart = false;
            start();
        /*} else if (isPause) {
            start();*/
        }
    }

    public TXVodPlayer getMediaPlayer() {
        return txVodPlayer;
    }
}

QQMediaPlayer需要继承AbstractMediaPlayer,实现里面抽象方法即可,同时TXVodPlayer是腾讯播放器的核心。这样做就可以让原先使用gsyVideoPlayer的项目,更快的切换到QQMediaPlayer。下一篇讲为什么要使用腾讯播放器,原先的播放器为什么不可以,以及如何同时使用两个播放器。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章