ExoPlayer实现截图功能和设置画面比例功能
来源:互联网 发布:网络统考英语过不去 编辑:程序博客网 时间:2024/05/17 03:08
最近公司项目里又在做播放器相关的功能了,本次鄙人收获的是截图功能和设置画面比例的功能。
截图功能
首先说说截图功能吧,一开始想到的是截取视频某一帧的画面,可是这么做并不能实现实时截图的效果。后来网上看到一个仿bilibli的开源播放器IjkPlayerView,大家应该都有所耳闻吧,话说这个例子写的还真不错,简单使用,于是我参考这个例子的源码终于找到了方法,其实本身TextureView已经给我们提供一个方法:public Bitmap getBitmap();这个方法就可以获取视频画面截图了。
getBitmap()
Returns a Bitmap representation of the content of the associated surface texture.
The bitmap returned by this method uses the ARGB_8888 pixel format and its dimensions are the same as this view’s.
意思是这个方法将返回一个和播放器view大小相同的一个位图。
最近还没有研究TextureView的源码和使用方法,这里先给大家放一篇入门教程TextureView简易教程,大致了解下TextureView的用法,后续我会再放一个详细的讲解博文。
最后放上踩坑历程,跟这个大兄弟的经历差不多,大家可以参考下,留个心眼。Android播放网络视频截图
设置视频画面比例
之前用的EXOplayer1.0版本的,是GitHub上面别人修改过的一个开源demo,里面直接就集成了画面比例的方法,叫做setScaleType,最近播放器要升级发现原来Exoplayer1.0版本的setScaleType方法对于EXOplayer2.0并不适用后来参考IjkPlayerView的方法,找到了一个叫做setMeasuredDimension()的方法,这个方法相信大家并不陌生哦。这里做下简单介绍吧:setMeasuredDimension(width,height)接受width和height两个参数用于设置当前view的大小。其实说白了设置视频画面比例不就是重新设置view的大小吗?对吧。下面直接贴上设置画面比例的逻辑吧,核心就是如何计算view的宽和高,完了就调用上面的setMeasuredDimension(width,height)方法设置一下即可。
详细讲解参考博客:
Android自定义视图(一)——onMeasure,MeasureSpec源码 流程 思路详解
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { Log.i(TAG, "onMeasure " + " [" + this.hashCode() + "] "); int mVideoRotationDegree = (int) getRotation(); int mVideoWidth = mVideoSize.x; int mVideoHeight = mVideoSize.y; Log.i(TAG, "videoWidth = " + mVideoWidth + ", videoHeight = " + mVideoHeight + ", " + "viewRotation = " + mVideoRotationDegree); // 如果旋转了90°或270°则宽高测量值进行互换 if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270) { int tempMeasureSpec = widthMeasureSpec; widthMeasureSpec = heightMeasureSpec; heightMeasureSpec = tempMeasureSpec; } // 获取默认的测量宽高值 int width = getDefaultSize(mVideoWidth, widthMeasureSpec); int height = getDefaultSize(mVideoHeight, heightMeasureSpec); if (mCurrentAspectRatio == AR_MATCH_PARENT) { // 在 AR_MATCH_PARENT 模式下直接用原始测量值 width = widthMeasureSpec; height = heightMeasureSpec; } else if (mVideoWidth > 0 && mVideoHeight > 0) { int widthSpecMode = View.MeasureSpec.getMode(widthMeasureSpec); int widthSpecSize = View.MeasureSpec.getSize(widthMeasureSpec); int heightSpecMode = View.MeasureSpec.getMode(heightMeasureSpec); int heightSpecSize = View.MeasureSpec.getSize(heightMeasureSpec); // modify,把&&操作符换为|| if (widthSpecMode == View.MeasureSpec.AT_MOST || heightSpecMode == View.MeasureSpec .AT_MOST) { // 测量宽高比,对应的视图的宽高比 float specAspectRatio = (float) widthSpecSize / (float) heightSpecSize; // 显示宽高比,要显示的视频宽高比 float displayAspectRatio; // 这里计算显示宽高比 switch (mCurrentAspectRatio) { case AR_16_9_FIT_PARENT: // 16:9 displayAspectRatio = 16.0f / 9.0f; if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270) displayAspectRatio = 1.0f / displayAspectRatio; break; case AR_4_3_FIT_PARENT: // 4:3 displayAspectRatio = 4.0f / 3.0f; if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270) displayAspectRatio = 1.0f / displayAspectRatio; break; case AR_ASPECT_FIT_PARENT: case AR_ASPECT_FILL_PARENT: case AR_ASPECT_WRAP_CONTENT: default: // 按视频来源宽高比 displayAspectRatio = (float) mVideoWidth / (float) mVideoHeight;// if (mVideoSarNum > 0 && mVideoSarDen > 0)// displayAspectRatio = displayAspectRatio * mVideoSarNum / mVideoSarDen; break; } // 是否要显示视频宽度比例较大 boolean shouldBeWider = displayAspectRatio > specAspectRatio; // 这里确定最终宽高 switch (mCurrentAspectRatio) { case AR_ASPECT_FIT_PARENT: case AR_16_9_FIT_PARENT: case AR_4_3_FIT_PARENT: if (shouldBeWider) { // too wide, fix width;宽度比较大,固定宽度,使用测量宽度,按显示比例缩放高度 width = widthSpecSize; height = (int) (width / displayAspectRatio); } else { // too high, fix height;高度比较大,固定高度,使用测量高度,按显示比例缩放宽度 height = heightSpecSize; width = (int) (height * displayAspectRatio); } break; case AR_ASPECT_FILL_PARENT: // 填充满控件模式 if (shouldBeWider) { // not high enough, fix height;宽度比较大,固定高度,缩放宽度 height = heightSpecSize; width = (int) (height * displayAspectRatio); } else { // not wide enough, fix width;高度比较大,固定宽度,缩放高度 width = widthSpecSize; height = (int) (width / displayAspectRatio); } break; case AR_ASPECT_WRAP_CONTENT: default: if (shouldBeWider) { // too wide, fix width;和第一个类似,这里取 (mVideoWidth, widthSpecSize) 最小的值 width = Math.min(mVideoWidth, widthSpecSize); height = (int) (width / displayAspectRatio); } else { // too high, fix height height = Math.min(mVideoHeight, heightSpecSize); width = (int) (height * displayAspectRatio); } break; } } else if (widthSpecMode == View.MeasureSpec.EXACTLY && heightSpecMode == View .MeasureSpec.EXACTLY) { // the size is fixed width = widthSpecSize; height = heightSpecSize; // for compatibility, we adjust size based on aspect ratio // 这里做的是缩小某一边的大小以达到和视频原始尺寸的比例 if (mVideoWidth * height < width * mVideoHeight) { width = height * mVideoWidth / mVideoHeight; } else if (mVideoWidth * height > width * mVideoHeight) { height = width * mVideoHeight / mVideoWidth; } } else if (widthSpecMode == View.MeasureSpec.EXACTLY) { // only the width is fixed, adjust the height to match aspect ratio if possible width = widthSpecSize; height = width * mVideoHeight / mVideoWidth; if (heightSpecMode == View.MeasureSpec.AT_MOST && height > heightSpecSize) { // couldn't match aspect ratio within the constraints,不让高度超出测量高度 height = heightSpecSize; } } else if (heightSpecMode == View.MeasureSpec.EXACTLY) { // only the height is fixed, adjust the width to match aspect ratio if possible height = heightSpecSize; width = height * mVideoWidth / mVideoHeight; if (widthSpecMode == View.MeasureSpec.AT_MOST && width > widthSpecSize) { // couldn't match aspect ratio within the constraints,不让宽度超出测量宽度 width = widthSpecSize; } } else { // neither the width nor the height are fixed, try to use actual video size width = mVideoWidth; height = mVideoHeight; if (heightSpecMode == View.MeasureSpec.AT_MOST && height > heightSpecSize) { // too tall, decrease both width and height height = heightSpecSize; width = height * mVideoWidth / mVideoHeight; } if (widthSpecMode == View.MeasureSpec.AT_MOST && width > widthSpecSize) { // too wide, decrease both width and height width = widthSpecSize; height = width * mVideoHeight / mVideoWidth; } } } else { // no size yet, just adopt the given spec sizes } setMeasuredDimension(width, height); }
好了,简单吧。下面我还是要强烈安利一下IjkPlayerView。
目前集成的主要功能:
沉浸式全屏播放,隐藏状态栏和虚拟键如果有的话,用的时候有些需要注意的地方放后面说;
弹幕功能,包括发射弹幕和弹幕基本样式设置:大小、颜色和类型(顶部、底部和滚动弹幕),效果同Bilibili;
竖屏和横屏的切换,其实就是小屏和全屏的切换,提供了重力感应来切换竖横屏功能;
触屏控制,竖直方向左边控制亮度,右边控制声音,水平方向控制播放进度;
三指旋转缩放,当三个手指触屏时就可以进行视频界面的旋转缩放,效果同Bilibili;
视频源切换,可设置流畅、清晰、高清、超清和1080p等5种视频源;
视频宽高比例设置,包括16:9、4:3、视频内嵌填充界面和填充屏幕等4种;
记录上次播放进度的跳转功能;
其它的如截屏功能,电池电量显示,时间显示,播放常亮,跑马灯标题和锁屏处理;
怎么样?还是很全面的吧,应该就差个gif动图截取的功能了,有兴趣的好好学习下吧,O(∩_∩)O~
- ExoPlayer实现截图功能和设置画面比例功能
- 图片实现缩放功能,设置缩放比例
- 截图功能的实现
- winform实现截图功能
- 简单截图功能实现
- Android截图功能实现
- winform实现截图功能
- android实现截图功能
- android实现截图功能
- 截图功能实现
- 屏幕截图功能实现
- Android实现截图功能
- ExoPlayer实现4G网络下暂停缓存功能
- gentoo设置最简单的截图和图片浏览功能
- khtml2png 实现网站截图功能
- C#实现网页截图功能
- Android-屏幕截图功能实现
- COCOS2D中实现截图功能
- Java 基础语法笔记
- 操作系统位数与数据字节数的关系
- 为什么商业智能和设计理论必须统一
- javascript: ; & javascript:void(0);
- git 生成公钥和私钥
- ExoPlayer实现截图功能和设置画面比例功能
- jvm内存模型
- pwm预习报告
- Popular Cows
- js查找字符串中出现次数最多的字符
- Android图表控件MPAndroidChart——曲线图+柱状图 CombinedChart的使用
- #学志#[js]获得当前日期并格式化
- 锐浪报表C#_web
- 环信聊天界面的修改(基于官方easeui库)