Vitamio的小修改及花屏问题的探讨

最近在做安卓视频模块,背景如下:
  视频竖屏播放时,SurfaceView不能对视频进行翻转,采用安卓4.0后的TextureView新控件又会容易受到硬件性能影响(包括TextureView在内试过好几个OpenGL实现的视频播放控件,其性能都更容易收到性能影响,比如播放帧率较大的视频时或者有多个图片资源不断切换时会造成卡顿和丢帧),采用Vitamio后可以解决竖屏播放问题,但其性能还是有待优化。
  
  先奉上Vitamio官方帮助文档地址:Vitamio Android 开发建议
  在近一周的修改后,解决了Vitamio视频框架中以下问题

Vitamio播放逻辑修改

  官方给予的Demo其播放逻辑并不强大,但视频的切换做的很流畅基本不会出现中间黑屏,看了一下,是对MediaPlayer做了处理,在视频将要播放completion的时候(一般是结束前1秒)会发出一个提醒,应该是在so库中封装的吧。为了不每次setDatasource的时候都释放资源并重新初始化为VideoView.java中做了以下修改:
  
1.添加了stop()用于停止播放。

public void stop() {
        if (mMediaPlayer != null) {
            if (isInPlaybackState()) {
                if (mMediaPlayer.isPlaying() || mMediaPlayer.getCurrentPosition()>0) {
                    mMediaPlayer.stop();
                    mCurrentState = STATE_IDLE;
                }
            }
            mMediaPlayer.reset();
            mTargetState = STATE_IDLE;
        }
    }
...

因为在官网提供的MediaPlayer中release()函数如下:

public void release() {
    stayAwake(false);
    updateSurfaceScreenOn();
    mOnPreparedListener = null;
    mOnBufferingUpdateListener = null;
    mOnCompletionListener = null;
    mOnSeekCompleteListener = null;
    mOnErrorListener = null;
    mOnInfoListener = null;
    mOnVideoSizeChangedListener = null;
    mOnCachingUpdateListener = null;
    mOnHWRenderFailedListener = null;
    if (mEventHandler != null)
        mEventHandler.release();
    //mEventHandler = null;
    _release();
    closeFD();
    mInBuffering = false;
    mNeedResume = false;
  }

在设置资源的时候就可以这样进行调用了,可以保证其不会总是创建和释放对象。

/**
     * 设置播放资源,设置播放事件
     */
    private void videoHandles() {
        filePath = this.videos_A.get(curVideoIndex);
        try {
            synchronized ((ADPageActivity) mContext) {
                if(filePath.indexOf("http:")>-1){
                    mUIParser.sfv.setBufferSize(1536 * 1024);
                }else if(filePath.indexOf("/")==0){
                    mUIParser.sfv.setBufferSize(0);
                }

                if(onPreparedListener == null){
                    onPreparedListener = new MediaPlayer.OnPreparedListener() {
                        @Override
                        public void onPrepared(MediaPlayer mediaPlayer) {
                            // optional need Vitamio 4.0
                            mediaPlayer.setPlaybackSpeed(1.0f);
                        }
                    };
                    mUIParser.sfv.setOnPreparedListener(onPreparedListener);
                }
                if(onCompletionListener == null){
                    onCompletionListener = new OnCompletionListener() {
                        @Override
                        public void onCompletion(MediaPlayer arg0) {
                            Log.i(Tag, "MMediaPlayer onCompletion");
                            playNextVideo();
                        }
                    };
                    mUIParser.sfv.setOnCompletionListener(onCompletionListener);
                }
                if(onErrorListener == null){
                    onErrorListener = new OnErrorListener() {
                        @Override
                        public boolean onError(MediaPlayer arg0, int arg1, int arg2) {
                            Log.e(Tag, "MMediaPlayer onError !!");

                            playNextVideo();
                            return true;//返回true,这个回调函数才会起作用,以下为官方解释:
                            //True if the method handled the error, false if it didn't. Returning false, or not having an OnErrorListener at all, will cause the OnCompletionListener to be called.
                        }
                    };
                    mUIParser.sfv.setOnErrorListener(onErrorListener);
                }

                if(filePath.indexOf("http:")>-1){
                    mUIParser.sfv.setVideoURI(Uri.parse(filePath));
                }else if(filePath.indexOf("/")==0){
                    mUIParser.sfv.setVideoPath(filePath);
                }
//              if(mMediaController==null){
//                  mMediaController = new MediaController(mContext);//实例化控制器
//                  mMediaController.show(2000);//控制器显示2s后自动隐藏
//                  mUIParser.sfv.setMediaController(mMediaController);//绑定控制器
//              }
                mUIParser.sfv.setVideoQuality(MediaPlayer.VIDEOQUALITY_HIGH);//设置播放画质 高画质
                mUIParser.sfv.requestFocus();
            }
        } catch (Exception e) {
            e.printStackTrace();

        }
    }

    private void playNextVideo() {
        Log.i(Tag, "curVideoIndex : " + curVideoIndex);
        // 网络播放模式时,播完一条视频上传记录至服务器
        if (sourceMode == 0)
            uploadPlayData(curVideoIndex);

        if (videos_A != null && videos_A.size() > 0) {
            curVideoIndex++;
            if (curVideoIndex >= this.videos_A.size()) {
                curVideoIndex = 0;
                // initAdPlayer();
            }

            filePath = this.videos_A.get(curVideoIndex);
            Log.i(Tag, "filePath : " + filePath);
            if(filePath.indexOf("http:")>-1){
                mUIParser.sfv.setVideoURI(Uri.parse(filePath));
            }else if(filePath.indexOf("/")==0){
                mUIParser.sfv.setVideoPath(filePath);
            }
        }
    }

Vitamio播放界面自动匹配视频大小修改为固定视频控件大小

不论你xml或者设置的播放控件多大,其播放画面大小会根据视频实际进行匹配,与以下代码有关:

setVideoLayout(mVideoLayout, mAspectRatio);
...
public void setVideoLayout(int layout, float aspectRatio) {
        LayoutParams lp = getLayoutParams();
        Pair<Integer, Integer> res = ScreenResolution.getResolution(mContext);
        int windowWidth = res.first.intValue(), windowHeight = res.second
                .intValue();
        float windowRatio = windowWidth / (float) windowHeight;
        float videoRatio = aspectRatio <= 0.01f ? mVideoAspectRatio
                : aspectRatio;
        mSurfaceHeight = mVideoHeight;
        mSurfaceWidth = mVideoWidth;
        if (VIDEO_LAYOUT_ORIGIN == layout && mSurfaceWidth < windowWidth
                && mSurfaceHeight < windowHeight) {
            lp.width = (int) (mSurfaceHeight * videoRatio);
            lp.height = mSurfaceHeight;
        } else if (layout == VIDEO_LAYOUT_ZOOM) {
            lp.width = windowRatio > videoRatio ? windowWidth
                    : (int) (videoRatio * windowHeight);
            lp.height = windowRatio < videoRatio ? windowHeight
                    : (int) (windowWidth / videoRatio);
        } else if (layout == VIDEO_LAYOUT_FIT_PARENT) {
            ViewGroup parent = (ViewGroup) getParent();
            float parentRatio = ((float) parent.getWidth())
                    / ((float) parent.getHeight());
            lp.width = (parentRatio < videoRatio) ? parent.getWidth() : Math
                    .round(((float) parent.getHeight()) * videoRatio);
            lp.height = (parentRatio > videoRatio) ? parent.getHeight() : Math
                    .round(((float) parent.getWidth()) / videoRatio);
        } else {
            boolean full = layout == VIDEO_LAYOUT_STRETCH;
            lp.width = (full || windowRatio < videoRatio) ? windowWidth
                    : (int) (videoRatio * windowHeight);
            lp.height = (full || windowRatio > videoRatio) ? windowHeight
                    : (int) (windowWidth / videoRatio);
        }
        setLayoutParams(lp);
        getHolder().setFixedSize(mSurfaceWidth, mSurfaceHeight);
        Log.d("VIDEO: %dx%dx%f, Surface: %dx%d, LP: %dx%d, Window: %dx%dx%f",
                mVideoWidth, mVideoHeight, mVideoAspectRatio, mSurfaceWidth,
                mSurfaceHeight, lp.width, lp.height, windowWidth, windowHeight,
                windowRatio);
        mVideoLayout = layout;
        mAspectRatio = aspectRatio;
    }

还有一些修改,我做了个Demo,供大家参考。目前还有个问题是:
在硬件环境不够强大的情况下
1.尽管在public void surfaceCreated(SurfaceHolder holder)中设置了mSurfaceHolder.setFormat(PixelFormat.RGBX_8888),但在个别机型上,播放一些视频还是会有很明显的花屏现象。应该跟Vitamio的底层so库有关系。
2.播放帧率较大视频还是会丢帧,卡顿。
以下是在我修改的基础上,省去了一些重要修改的Demo
http://download.csdn.net/detail/mengjiangyue/9577932

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值