GsyVideoPlayer视频分析(二)------------列表视频播放视频

思考以下几个问题:

1.视频窗口的大小和位置是如何匹配ListView的item大小和位置的?

2.视频播放画面是如何显示出来的?

3.视频播放的声音如何显示出来的?


通过代码分析;


 @Override
  public View getView(final int position, View convertView, ViewGroup parent) {

      ....

      ....

     listVideoUtil.addVideoPlayer(position, holder.imageView, TAG, holder.videoContainer, holder.playerBtn);

     holder.playerBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                notifyDataSetChanged();
                //listVideoUtil.setLoop(true);
                listVideoUtil.setPlayPositionAndTag(position, TAG);
//                final String url = "https://tv.miguvideo.com/?from=singlemessage&isappinstalled=0#video/live/761358370/room201706301600304971_R1";
                //listVideoUtil.setCachePath(new File(FileUtils.getPath()));
                final String url = "http://baobab.wdjcdn.com/14564977406580.mp4";
                listVideoUtil.startPlay(url);
            }
        });

       ........

      .......

}

listview的adapter的getview方法每次都会走一次listVideoUtil.addVideoPlayer(position, holder.imageView, TAG, holder.videoContainer, holder.playerBtn);

/**
     * 动态添加视频播放
     *
     * @param position  位置
     * @param imgView   封面
     * @param tag       TAG类型
     * @param container player的容器
     * @param playBtn   播放按键
     */
    public void addVideoPlayer(final int position, View imgView, String tag,
                               ViewGroup container, View playBtn) {
        container.removeAllViews();
        if (isCurrentViewPlaying(position, tag)) {
            if (!isFull) {
                ViewGroup viewGroup = (ViewGroup) gsyVideoPlayer.getParent();
                if (viewGroup != null)
                    viewGroup.removeAllViews();
                container.addView(gsyVideoPlayer);
                playBtn.setVisibility(View.INVISIBLE);
            }
        } else {
            playBtn.setVisibility(View.VISIBLE);
            container.removeAllViews();   //增加封面
            container.addView(imgView);
        }
    }

 代码可以看出addVideoPlayer方法的意思是,如果当前的position等于listVideoUtil中获取到的position,videoContainer中就显示gsyVideoPlayer,否则显示视频封面;

 点击播放按钮的作用:

1.向listVideoUtil中设置position,并通过notifyDataSetChanged方法使重新走getview(),重新走getview方法时,会重新进入addVideoPlayer方法判断;

   至此第一个疑问已经解决:视频显示在哪个item就是这个position决定的;视频窗口的大小由videoContainer的大小决定;

2.执行代码listVideoUtil.startPlay(url);


下面开始分析startPlay(url)中做了哪些操作?

  /**
     * 开始播放
     *
     * @param url 播放的URL
     */
    public void startPlay(String url) {

        if (isSmall()) {
            smallVideoToNormal();//如果是小窗口,就转为正常窗口播放,这个问题后面再说
        }

        this.url = url;

        gsyVideoPlayer.release();

        gsyVideoPlayer.setLooping(isLoop);//视频是否循环播放

        gsyVideoPlayer.setSpeed(speed);//视频播放速度

        gsyVideoPlayer.setNeedShowWifiTip(needShowWifiTip);//非wifi环境下,显示流量提醒

        gsyVideoPlayer.setNeedLockFull(needLockFull);//是否需要全屏锁屏

        gsyVideoPlayer.setUp(url, true, cachePath, mapHeadData, objects);//设置边缓存边播放

        //增加title
        gsyVideoPlayer.getTitleTextView().setVisibility(View.GONE);

        //设置返回键
        gsyVideoPlayer.getBackButton().setVisibility(View.GONE);

        //设置全屏按键功能
        gsyVideoPlayer.getFullscreenButton().setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                resolveFullBtn();
            }
        });

        gsyVideoPlayer.startPlayLogic();
    }


就是一些简单设置项,其中gsyVideoPlayer.setUp(url, true, cachePath, mapHeadData, objects);会把url改为全局的mUrl;


    @Override
    public void startPlayLogic() {
        if (mStandardVideoAllCallBack != null) {
            Debuger.printfLog("onClickStartThumb");
            mStandardVideoAllCallBack.onClickStartThumb(mUrl, mObjects);
        }
        prepareVideo();
        startDismissControlViewTimer();
    }

  


    /**
     * 开始状态视频播放
     */
    protected void prepareVideo() {
        if (GSYVideoManager.instance().listener() != null) {
            GSYVideoManager.instance().listener().onCompletion();
        }
        GSYVideoManager.instance().setListener(this);
        GSYVideoManager.instance().setPlayTag(mPlayTag);
        GSYVideoManager.instance().setPlayPosition(mPlayPosition);
        addTextureView();//动态添加TextureView
        mAudioManager.requestAudioFocus(onAudioFocusChangeListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);//暂时获取音频焦点
        ((Activity) getContext()).getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);//保持屏幕常亮不灭屏
        GSYVideoManager.instance().prepare(mUrl, mMapHeadData, mLooping, mSpeed);
        setStateAndUi(CURRENT_STATE_PREPAREING);
    }

    科普1,音频焦点分类:

    AudioManager.AUDIOFOCUS_REQUEST_GRANTED------------永久获取音频焦点

    AudioManager.AUDIOFOCUS_GAIN_TRANSIENT-------------暂时获取音频焦点,比如音乐后台播放,当前视频播放会抢夺音频焦点,视频播放完成,音乐自动播放;

   AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK--------提示类型获取音频焦点,比如听音乐的时候来短信,音乐声音降低


   /**
     * 添加播放的view
     */
    protected void addTextureView() {
        if (mTextureViewContainer.getChildCount() > 0) {
            mTextureViewContainer.removeAllViews();
        }
        mTextureView = null;
        mTextureView = new GSYTextureView(getContext());
        mTextureView.setSurfaceTextureListener(this);
        mTextureView.setRotation(mRotate);

        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
        mTextureViewContainer.addView(mTextureView, layoutParams);
    }

    构造了一个TextureView,并添加到gsyVideoPlayer布局中。

    TextureView设置了SurfaceTextureListener;

     科普2:SurfaceTextureListener回调方法:

 1.onSurfaceTextureAvailable(SurfaceTexture arg0, int arg1, int arg2)-------------TextureView可用时调用

 2.onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height)

 3.onSurfaceTextureDestroyed(SurfaceTexture surface)------------TextureView销毁时调用

 4.onSurfaceTextureUpdated(SurfaceTexture surface)

   回到代码:

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        mSurface = new Surface(surface);
        GSYVideoManager.instance().setDisplay(mSurface);
        //显示暂停切换显示的图片
        showPauseCover();
    }

    意思是:在TextureView可以使用时,将surface交给GSYVideoManager,用于显示视频的画面,至此第二个问题已经解决,当然此时还没有开始播放视频, 真正播放视频是在

GSYVideoManager.instance().prepare(mUrl, mMapHeadData, mLooping, mSpeed)中,此处的mUrl就是上面保存的url;

  

public void prepare(final String url, final Map<String, String> mapHeadData, boolean loop, float speed) {
    if (TextUtils.isEmpty(url)) return;
    Message msg = new Message();
    msg.what = HANDLER_PREPARE;
    GSYModel fb = new GSYModel(url, mapHeadData, loop, speed);
    msg.obj = fb;
    mMediaHandler.sendMessage(msg);
}


      

public class MediaHandler extends Handler {
    public MediaHandler(Looper looper) {
        super(looper);
    }

    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        switch (msg.what) {
            case HANDLER_PREPARE:
                initVideo(msg);
                break;


private void initVideo(Message msg) {
    try {
        currentVideoWidth = 0;
        currentVideoHeight = 0;
        mediaPlayer.release();

        if (videoType == GSYVideoType.IJKPLAYER) {
            initIJKPlayer(msg);
        } else if (videoType == GSYVideoType.IJKEXOPLAYER) {
            initEXOPlayer(msg);
        }
        setNeedMute(needMute);
        mediaPlayer.setOnCompletionListener(GSYVideoManager.this);
        mediaPlayer.setOnBufferingUpdateListener(GSYVideoManager.this);
        mediaPlayer.setScreenOnWhilePlaying(true);
        mediaPlayer.setOnPreparedListener(GSYVideoManager.this);
        mediaPlayer.setOnSeekCompleteListener(GSYVideoManager.this);
        mediaPlayer.setOnErrorListener(GSYVideoManager.this);
        mediaPlayer.setOnInfoListener(GSYVideoManager.this);
        mediaPlayer.setOnVideoSizeChangedListener(GSYVideoManager.this);
        mediaPlayer.prepareAsync();

    } catch (Exception e) {
        e.printStackTrace();
    }
}
根据videoType的类型,创建不同的播放器,initIJKPlayer(msg)或者initEXOPlayer(msg);

不管哪种播放器,msg中有视频播放的url,用于播放器播放视频使用;

最后调用mediaPlayer.prepareAsync()播放视频;




 




 



 

   


  


  




        





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值