zoukankan      html  css  js  c++  java
  • Android开发 MediaPlayer将视频播放时尺寸适配完美

    前言

        视频播放有一个较为蛋疼的问题,那就是尺寸适配.如果不做尺寸适配视频将会变形拉伸或者压缩.下面我就介绍个人实现的算法.

    满足一边的算法

      满足一边?你可能是疑问是什么意思.意思是就是始终将视频的高度或者宽度的其中一个铺满对应屏幕的高度或者宽度.然后在将另外一个高或宽按比例求出合适的尺寸,其实这跟与摄像头的求出合适的分辨率预览思想是类似的.

      另外,在视频高大于宽且屏幕是竖屏情况下,铺满高度,但是会计算宽度,但是计算后多多少少视频宽度与屏幕宽度不一致,但是其实已经很接近比例了.我们可以接受视频的轻微拉伸,来满足视频铺满屏幕的情况,下面的算法就是做了这种优化.

      代码部分:

      /**
         * 修改预览View的大小,以用来适配屏幕
         */
        public void changeVideoSize() {
            int videoWidth = mMediaPlayer.getVideoWidth();
            int videoHeight = mMediaPlayer.getVideoHeight();
            int deviceWidth = getResources().getDisplayMetrics().widthPixels;
            int deviceHeight = getResources().getDisplayMetrics().heightPixels;
            Log.e(TAG, "changeVideoSize: deviceHeight="+deviceHeight+"deviceWidth="+deviceWidth);
            float devicePercent = 0;
            //下面进行求屏幕比例,因为横竖屏会改变屏幕宽度值,所以为了保持更小的值除更大的值.
            if (getResources().getConfiguration().orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) { //竖屏
                devicePercent = (float) deviceWidth / (float) deviceHeight; //竖屏状态下宽度小与高度,求比
            }else { //横屏
                devicePercent = (float) deviceHeight / (float) deviceWidth; //横屏状态下高度小与宽度,求比
            }
    
            if (videoWidth > videoHeight){ //判断视频的宽大于高,那么我们就优先满足视频的宽度铺满屏幕的宽度,然后在按比例求出合适比例的高度
                videoWidth = deviceWidth;//将视频宽度等于设备宽度,让视频的宽铺满屏幕
                 videoHeight = (int)(deviceWidth*devicePercent);//设置了视频宽度后,在按比例算出视频高度
    
            }else {  //判断视频的高大于宽,那么我们就优先满足视频的高度铺满屏幕的高度,然后在按比例求出合适比例的宽度
                if (getResources().getConfiguration().orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {//竖屏
                    videoHeight = deviceHeight;
                    /**
                     * 接受在宽度的轻微拉伸来满足视频铺满屏幕的优化
                     */
                    float videoPercent = (float) videoWidth / (float) videoHeight;//求视频比例 注意是宽除高 与 上面的devicePercent 保持一致
                    float differenceValue = Math.abs(videoPercent - devicePercent);//相减求绝对值
                    L.e("devicePercent="+devicePercent);
                    L.e("videoPercent="+videoPercent);
                    L.e("differenceValue="+differenceValue);
                    if (differenceValue < 0.3){ //如果小于0.3比例,那么就放弃按比例计算宽度直接使用屏幕宽度
                        videoWidth = deviceWidth;
                    }else {
                        videoWidth = (int)(videoWidth/devicePercent);//注意这里是用视频宽度来除
                    }
    
                }else { //横屏
                    videoHeight = deviceHeight;
                    videoWidth = (int)(deviceHeight*devicePercent);
    
                }
    
            }
    
            ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) mVideoPlaySurfaceview.getLayoutParams();
            layoutParams.width = videoWidth;
            layoutParams.height = videoHeight;
            layoutParams.verticalBias = 0.5f;
            layoutParams.horizontalBias = 0.5f;
            mVideoPlaySurfaceview.setLayoutParams(layoutParams);
    
        }

    最后调用这个方法的地方

    mMediaPlayer.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener() { //尺寸变化回调
                    @Override
                    public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
                        Log.e(TAG, "onVideoSizeChanged: 触发 width=" + width + "height=" + height);
                        changeVideoSize();
    
                    }
                });

    求最正方形算法

    其实这个算法不是我的,但是一开始看到的这个别人的算法的时候,突然发现这算法跟我相机预览求正方形有异曲同工之妙(基本原理就是高宽比除宽高,或者宽高比除高宽,两个不同的边相除或者相乘会得到近似正方形的尺寸).但是个人觉得,并不合适在视频播放的时候使用,因为在横屏情况下会将视频变得很小.但是搬过来也是一个参考:

    public void changeVideoSize() {
            int videoWidth = mediaPlayer.getVideoWidth();
            int videoHeight = mediaPlayer.getVideoHeight();
    
            //根据视频尺寸去计算->视频可以在sufaceView中放大的最大倍数。
            float max;
            if (getResources().getConfiguration().orientation==ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
                //竖屏模式下按视频宽度计算放大倍数值
                max = Math.max((float) videoWidth / (float) surfaceWidth,(float) videoHeight / (float) surfaceHeight);
            } else{
                //横屏模式下按视频高度计算放大倍数值
                max = Math.max(((float) videoWidth/(float) surfaceHeight),(float) videoHeight/(float) surfaceWidth);
            }
            
            //视频宽高分别/最大倍数值 计算出放大后的视频尺寸
            videoWidth = (int) Math.ceil((float) videoWidth / max);
            videoHeight = (int) Math.ceil((float) videoHeight / max);
    
            //无法直接设置视频尺寸,将计算出的视频尺寸设置到surfaceView 让视频自动填充。
            surfaceView.setLayoutParams(new RelativeLayout.LayoutParams(videoWidth, videoHeight));
        }
    
        @Override
        public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
            changeVideoSize();
        }
  • 相关阅读:
    SD_WebImage-03-多线程+下载任务放入非主线程执行
    NSOperationQueue_管理NSOperation-02-多线程
    CALayer小结-基本使用00-UI进阶
    XMPP-UI进阶-01
    XMPP总结-UI进阶-00
    UI控件总结-UI初级
    转场动画-01-day4
    暂停-开始动画-核心动画-08-day4
    核心动画-04-CALayer隐式动画
    Android开发技术周报 Issue#71
  • 原文地址:https://www.cnblogs.com/guanxinjing/p/11019939.html
Copyright © 2011-2022 走看看