前言

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

满足一边的算法

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

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

  代码部分:

  /**
* 修改预览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();
}

Android开发 MediaPlayer将视频播放时尺寸适配完美的更多相关文章

  1. Android开发 MediaPlayer入门_播放本地视频

    前言 MediaPlayer,可以播放视频/音频,并且它支持本地和网络文件的播放.本片博客作为入门教程,先以最通俗的方式解释播放文件本地视频.(如果你嫌MediaPlayer还是太麻烦可以试试选择Vi ...

  2. Android开发 海康威视 多路视频播放(同时播放视频)

    原文地址:Android开发 海康视频 多路视频播放 | Stars-One的杂货小窝 最近公司有个项目需要对接到海康监控摄像头来实现对应的实时播放和回放,但这两个不是我们今天要讨论的重点,APP首页 ...

  3. Android开发 MediaPlayer播放本地视频完善的demo(只是代码记录)

    xml <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.w ...

  4. Android开发中使用数据库时出现java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed.

    最近在开发一个 App 的时候用到了数据库,可是在使用数据库的时候就出现了一些问题,在我查询表中的一些信息时出现了一下问题: Caused by: java.lang.IllegalStateExce ...

  5. Android开发学习—— 创建项目时,不是继承activity,而是继承ActionBarActivity

    对于我们新建android项目时, 会 继承ActionBarActivity. 我们在新建项目时, 最小需求的sdk 选择 4.0以上版本.这样 新建的android项目就是继承activity了!

  6. Android开发 MediaPlayer播放raw资源MP3文件

    代码 private MediaPlayer mRingPlayer; /** * 播放铃声 */ private void startRing(){ if (mRingPlayer != null) ...

  7. [安卓开发板]迅为IMX6 四核Android开发板

    工业级核心板-Android开发板 10层高速PCB设计,充分保证电磁兼容 处理器:开发板默认是四核商业扩展级芯片,可根据用户需求更换单核.双核.工业级.汽车级处理器,批量更省成本. 扩展引脚:320 ...

  8. 双非本科Android开发,如何逆袭拿到大厂 Offer?

    从2020年3月18日投出第一份暑期实习简历至今,已经过去400多天.我也尘埃落定,即将去CVTE做Android开发. 休息了很长时间,如今已经能够很平静地回首这段历程,写下这篇文,致敬曾经走过的漫 ...

  9. 【Android 多媒体开发】 MediaPlayer 网络视频播放器

    作者 : 万境绝尘 (octopus_truth@163.com) 转载请著名出处 : http://blog.csdn.net/shulianghan/article/details/3889514 ...

随机推荐

  1. 转:这里有些sscanf()的一些使用说明,都是从论坛,Blog里整理出来的。供大家使用。

    http://www.cnblogs.com/gmh915/archive/2009/09/30/1576995.html 这里有些sscanf()的一些使用说明,都是从论坛,Blog里整理出来的.供 ...

  2. 2019 IEEEXtreme 13.0 题解记录

    比赛时间 2019.10.19 8:00 - 2019.10.20 8:00 比赛网站 https://csacademy.com/ieeextreme13 // 连续24小时做题真的是极限体验 // ...

  3. 你没玩过的全新版本!Win10这些骚操作你知多少

    你没玩过的全新版本!Win10这些骚操作你知多少 [PConline技巧]不知不觉,Win10与我们相伴已经整整四个年头了,从最开始的组团抗拒到现在的默默接受,个中滋味相信谁心里都有个数.近日微软开始 ...

  4. 分享一套高级Java笔试题(实拍高清图)

    分享一套高级Java笔试题 微信群里群友分享的 刚好他在笔试 有些问题不会发到群里求助 如果你最近正好在面试 需要参考需要提升 这套试题或许对你有用 下面是部分分享原图 下面是微信群中群友的热议 非常 ...

  5. 02ubuntu下python环境安装

    原文链接:https://blog.csdn.net/weixin_42549407/article/details/85198460 我安装的是python3.6.9 1.下载python的源码压缩 ...

  6. D3.js坐标轴的绘制方法、添加坐标轴的刻度和各比例尺的坐标轴(V3版本)

    坐标轴(Axis)   坐标轴(Axis)在很多图表中都可见到,例如柱形图.折线图.散点图等.坐标轴由一组线段和文字组成,坐标轴上的点由一个坐标值确定.但是,如果使用SVG的直线和文字一笔一画的绘制坐 ...

  7. Logstash2.3.4趟坑之集成Redis哨兵模式

    最新在使用Lostash2.3.4收集数据的时候,在读取redis数据的时候,报了如下的一个异常: 异常如下 Pipeline aborted due to error {:exception=> ...

  8. [转]C# Eval在asp.net中的用法及作用

    原文链接:http://www.cnblogs.com/Mr_JinRui/archive/2010/07/06/1772129.html Eval( " ")和Bind( &qu ...

  9. kerberos协议介绍

    一.kerberos认证过程: client向kerberos服务请求,希望获取访问server的权限.kerberos得到了这个消息,首先得判断client是否是可信赖的,也就是白名单黑名单的说法. ...

  10. springboot 简单搭建(thymeleaf 视图显示)

    接口访问参考:https://blog.csdn.net/hanjun0612/article/details/81625395 PS:调用接口和跳转网页 主要区别是 1 调用接口是 @RestCon ...