exoplay切换全屏_ExoPlayer播放视频的简单使用及播放视频宽高设置的源码分析
前言
本篇博文主要是对播放视频宽高设置的源码进行分析,为了方便讲解,提前也会对EXOPlayer的使用做简单概述。
使用ExoPlayer播放视频
1.首先我们需要在布局管理器中添加如下xml代码:
android:id="@+id/play_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
复制代码
这是exoPlayer的播放控件。 2.创建一个SimpleExoPlayer对象。并把SimpleExoPlayer与SimpleExoPlayerView关联起来。代码如下:
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory trackFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(trackFactory);
player = ExoPlayerFactory.newSimpleInstance(this, trackSelector);
simpleExoPlayerView.setPlayer(player);复制代码
3.最后来创建MediaSource对象,准备播放。
private void preparePlay() {
DefaultBandwidthMeter defaultBandwidthMeter = new DefaultBandwidthMeter();
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(MainActivity.this
, Util.getUserAgent(MainActivity.this, "exoplayer_sample")
, defaultBandwidthMeter);
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
Uri uri = Uri.parse("http://mvvideo11.meitudata.com/59fd64eac92fb5968_H264_3.mp4?k=b953933ba73a3271c9c7d926a0c54fb4&t=5a0a97c9");
MediaSource mediaSource = new ExtractorMediaSource(uri
, dataSourceFactory, extractorsFactory, null, null);
//player.addListener(this);
player.prepare(mediaSource);
}复制代码
这里的视频Uri是我从网上找的一个mp4格式的视频,通过EXOplayer的开发者文档我们知道,多媒体的格式和MediaSource实现类的对应关系是:
DASH (DashMediaSource),
SmoothStreaming (SsMediaSource),
HLS (HlsMediaSource),
除此之外其他的格式使用 (ExtractorMediaSource).
通过 EXOPLAYER Support Formats 一文我们知道MP4格式应该使用ExtractorMediaSource。
现在我们可以运行程序了(别忘了添加网络权限)。运行效果如下:
控制器是SimpleExoPlayerView自带的一个默认控制器。看到这我们发现一个问题,就是明明我们在布局管理器添加SimpleExoPlayerView控件的时候,设置它的宽高都是match_parent啊,怎么它的宽度并没有填充父布局? 让它充满屏幕的代码很简单,有两种方式。可以用代码实现如下:
simpleExoPlayerView.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FILL);
复制代码
或者通过xml文件的属性设置:
app:resize_mode="fill"复制代码
设置之后,我们再看一下效果:
通过gif图我们看到,确实,变成了全屏。那我们现在就来分析一下为什么会这样。
源码分析
我们看关键语句:
simpleExoPlayerView.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FILL);复制代码
看看setResizeMode的内部实现:
public void setResizeMode(@ResizeMode int resizeMode) {
Assertions.checkState(contentFrame != null);
contentFrame.setResizeMode(resizeMode);
}复制代码
这里调用了contentFrame的setResizeMode方法,contentFrame是AspectRatioFrameLayout对象。我们来看看AspectRatioFrameLayout里面的setResizeMode方法。
public void setResizeMode(@ResizeMode int resizeMode) {
if (this.resizeMode != resizeMode) {
this.resizeMode = resizeMode;
requestLayout();
}
}复制代码
这里是把resizeMode的值传了进来,我们看一下resizeMode值在AspectRatioFrameLayout类中到底起着什么作用吧。
public AspectRatioFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
resizeMode = RESIZE_MODE_FIT;
if (attrs != null) {
TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
R.styleable.AspectRatioFrameLayout, 0, 0);
try {
resizeMode = a.getInt(R.styleable.AspectRatioFrameLayout_resize_mode, RESIZE_MODE_FIT);
} finally {
a.recycle();
}
}
}复制代码
在AspectRatioFrameLayou的构造方法中,我们看到,resizeMode的默认值是RESIZE_MODE_FIT。这里提到了RESIZE_MODE_FIT,我们就谈谈AspectRatioFrameLayou类中的几种计算视频宽高的模式。
RESIZE_MODE_FIT 表示通过减少视频的宽度或者高度,来达到想要的视频宽高比。
RESIZE_MODE_FIXED_WIDTH 表示宽度是固定的,通过减少或者增加高度的值来实现想要的宽高比。
RESIZE_MODE_FIXED_HEIGHT 表示高度是固定的,通过减少或者增加宽度的值来实现想要的宽高比。
RESIZE_MODE_FILL 表示不考虑指定的宽高比。
RESIZE_MODE_ZOOM 表示通过增加宽度或者高度,来达到想要的视频宽高比。
上面呢我演示了设置模式为setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FILL); 的效果,其余的四种效果大家可以自己设置演示,会存在变形的情况哦,所以这玩意还得合理运用。
接下来我们看看resizeMode在哪里使用的,我们看如下代码:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (resizeMode == RESIZE_MODE_FILL || videoAspectRatio <= 0) {
// Aspect ratio not set.
return;
}
int width = getMeasuredWidth();
int height = getMeasuredHeight();
float viewAspectRatio = (float) width / height;
float aspectDeformation = videoAspectRatio / viewAspectRatio - 1;
if (Math.abs(aspectDeformation) <= MAX_ASPECT_RATIO_DEFORMATION_FRACTION) {
// We're within the allowed tolerance.
return;
}
switch (resizeMode) {
case RESIZE_MODE_FIXED_WIDTH:
height = (int) (width / videoAspectRatio);
break;
case RESIZE_MODE_FIXED_HEIGHT:
width = (int) (height * videoAspectRatio);
break;
case RESIZE_MODE_ZOOM:
if (aspectDeformation > 0) {
width = (int) (height * videoAspectRatio);
} else {
height = (int) (width / videoAspectRatio);
}
break;
default:
if (aspectDeformation > 0) {
height = (int) (width / videoAspectRatio);
} else {
width = (int) (height * videoAspectRatio);
}
break;
}
super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
}复制代码
这是AspectRatioFrameLayout的onMeasure方法,我们来分析下。
通过代码,我们看到当resizeMode的值为RESIZE_MODE_FILL或者videoAspectRatio<=0时,就return,也就表示它会执行,外面所设置宽高。videoAspectRatio表示想要的视频宽高比。我们接着看,注意到一个if的判断语句。这里的意思是如果想要的宽高比和视频的宽高比的差值如果小于这个临界值MAX_ASPECT_RATIO_DEFORMATION_FRACTION的话,那AspectRatioFrameLayout不需要从新计算他的宽高。这里MAX_ASPECT_RATIO_DEFORMATION_FRACTION=0.01f。
接着我们看switch语句中,对于不同的resizeMode,宽高做了对应的计算。最后把计算的值通过:
super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));复制代码
设置进去。 那最后我们再看下videoAspectRatio这个想要的宽高比是在哪里设置的呢,我们发现在SimpleExoPlayerView中有设置:
@Override
public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees,
float pixelWidthHeightRatio) {
if (contentFrame != null) {
float aspectRatio = height == 0 ? 1 : (width * pixelWidthHeightRatio) / height;
contentFrame.setAspectRatio(aspectRatio);
}
}复制代码
onVideoSizeChanged方法是在视频渲染期间视频的size值变化的时候会回调,pixelWidthHeightRatio这个参数表示每一个像素的宽高比。
总结
这里对播放视频的宽高设置源码分析到此结束了,后需还有对EXOPlayer的其他分析。
exoplay切换全屏_ExoPlayer播放视频的简单使用及播放视频宽高设置的源码分析相关推荐
- 字节跳动Android三面视频解析:framework+MVP架构+HashMap原理+性能优化+Flutter+源码分析等
前言 对于字节跳动的二面三面而言,Framework+MVP架构+HashMap原理+性能优化+Flutter+源码分析等问题都成高频问点!然而很多的朋友在面试时却答不上或者答不全!今天在这分享下这些 ...
- 音视频开发之旅(67) - 变速不变调之sonic源码分析
目录 基音周期.浊音的概念 Sonic源码分析 资料 收获 上一篇我们学习了音频变速不变调的原理以及WSOLA波形相似叠加算法进行时域压扩处理.其中在寻找相似帧方面,Sonic采用AMDF(平均幅度差 ...
- 红橙Darren视频笔记 view的invalidate调用draw方法的流程(源码分析基于api 29)
问题描述 在界面上的一个控件(比如一个button)调用了invalidate 代码流程是什么样的? 首先一个控件基本要么是View 要么是ViewGroup 因为ViewGroup继承自View 他 ...
- 【LAS】IJK设置OPTION源码分析及播放器传递manifest_string到AVInputFormat
上一篇,提到了要在avinputformat里给定avoption 本节,调试时发现 manifest Json 是空的,也没有看到直接赋值, 那么就是用option的方式传递的. 让las解析jso ...
- Flash全屏播放外部多个Flv视频并且按键进行切换+全屏播放外部Flv视频+指定元件播放外部Flv视频(非全屏)(可以作为遮罩来播放)
目录 一.目的: 1.Flash全屏播放外部多个Flv视频并且按键进行切换+全屏播放外部Flv视频+指定元件播放外部Flv视频(非全屏),所以将其记录下来 二.参考: 1.[AS3编程教学]如何加载并 ...
- MediaPlayer+TextureView,完美切换全屏、小窗口的 Android 视频播放器
NiceVieoPlayer 项目地址:xiaoyanger0825/NiceVieoPlayer 简介:MediaPlayer+TextureView,完美切换全屏.小窗口的 Android 视频 ...
- 原生js实现点击按钮切换全屏!
使用fullScreen API实现全屏 <head><meta charset="UTF-8"><meta name="viewport& ...
- 2022.05.20-电脑切换全屏与非全屏(特别是谷歌浏览器)的时候会发生卡顿黑屏
切换全屏与非全屏的时候会发生卡顿黑屏 可能是自己之前插的两块屏幕,后来一块屏幕断掉了,再将那一块屏幕接上去就好了 这个很有可能是谷歌浏览器造成的,因为往往是谷歌浏览器切屏的时候才会出现这个问题,而其他 ...
- Android 切换全屏,取消全屏
切换全屏,取消全屏 /*** 切换全屏,取消全屏** @param isChecked*/ private void switchFullScreen(boolean isChecked) {if ( ...
- 一步步实现windows版ijkplayer系列文章之二——Ijkplayer播放器源码分析之音视频输出——视频篇...
一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...
最新文章
- C++ 中queue(队列)的用法
- 显示一个屏幕,隐藏其他屏幕
- zcmu-1646 盒子游戏
- 高效地加载图片(一) 高效地加载大图
- Nginx的Gzip模块配置指令(二)
- AOP技术研究 再续
- c语言程序设计的日志,C语言程序设计教学日志.docx
- 为啥你写的代码总是这么复杂?
- 太阳直射点纬度计算公式_全纬度昼夜长短通用公式
- 应届生开40万年薪?OPPO大手笔招揽芯片人才引热议
- CentOS下ELK 7.2生产安全部署
- 抛开当下的迷惘,IT技术人的发展之路该怎么走?
- PPT计算机辅助教学,教学ppt课件制作的几点心得
- 关键路径过程详解、算法及其实现
- 基于微信小程序的培训机构系统
- 设计师必备,6个PNG素材网站
- NetSpeeder V3.70 绿色特别版
- 微信小程序 动态获取图片主色调作为背景
- 秦岚微博之夜喜提热搜第一 优雅公主裙演绎真人版辛德瑞拉
- 卡马克算法(地图重复利用,跑酷类游戏)
热门文章
- “科创赋能 资本助力”2019SIPEF论坛启幕
- Windows2012安装AppFabric失败返回1603错误的解决方案
- Java Swing实现局域网QQ
- 商业杂志图表的经典用色
- 为 昂达 v891 安装上了 remix OS 了
- 关于Ubuntu python程序利用lixb264生成h264格式的视频相关问题
- java拍照搜题软件下载_微信拍照搜答案的小程序 可以拍照搜java题的软件
- 百度日语输入法快捷键(baidu type)
- UG(NX)二次开发 BlockUI 集列表使用方法
- 手机计算机软件删除了怎么恢复,手机卸载的软件怎么恢复?手机卸载的软件恢复方法介绍...