1.问题:
首先我的应用场景Mediacodec ,使用了摄像头流与录屏流,中间会进行切换,然后录出来一个完整的视频,也就是从摄像到录屏再到摄像再录屏,需求比较。。。因为要录像又要录屏,所以不可能直接用手机屏幕的实际分辨率。所以从camera.getParameters()获取宽高并设置为输出的视频的分辨率。现象是很多手机上看录制好的视频录屏那块被缩小了,其实是因为有黑边造成的。因此问题其实是基于录屏的输出视频分辨率为核心的,其他录屏方案也大多适用。
2.分析
大多数手机获取的camera的分辨率与屏幕的分辨率不一致,重要的是长宽比不一样,比如说。相机获取了1920*1080的分辨率,而你的手机是2340*1080的分辨率,在录屏的时候输出视频,第一录屏要全屏录,也就是宽是2340,第二视频不会裁剪,所以你最后要输出1920*1080,他的宽自然要缩小,高度也就跟着等比缩小,然后上下会有黑边填充。也就是其实视频最后输出的是1920*1080,之所以看起来小了是上下填充了黑边。
所以你要做的就是一个断点一个断点的去看相机支持的分辨率,然后一个一个去算比例,然后发现一些规律,然后换一部手机,然后再执行这一套操作,然后再换一步手机。。。
好在这些我都替你做了。
3.处理
查找camera支持的分辨率中最接近手机实际屏幕比例的值
其实是从手机支持的视频分辨率中找,不过因为也要用摄像头,视频支持的包括摄像头支持且比摄像头支持的多,所以要从摄像头支持的里找。即List<Camera.Size> prviewSizeList = myParameters.getSupportedPreviewSizes();不开摄像头的可以试着从List<Camera.Size> videoSizeList = myParameters.getSupportedVideoSizes();里找。下面是核心代码
public void initCamera() {getScreenSize();//注:摄像头相关的设置不写了,省的看混............Camera.Parameters myParameters = myCamera.getParameters();//获取摄像头支持的分辨率List<Camera.Size> prviewSizeList = myParameters.getSupportedPreviewSizes();//获取手机支持的视频分辨率//List<Camera.Size> videoSizeList = myParameters.getSupportedVideoSizes();//获取最接近的分辨的索引int selectIndex = bestVideoSize(prviewSizeList);............//设置相机预览尺寸//TODO 在你设置视频大小的地方也是用这里计算出来的值,以为我设置录制视频分辨率的地方不在,
//这,不过也是取得这里的值,所以就不写了
myParameters.setPreviewSize(prviewSizeList.get(selectIndex).width,prviewSizeList.get(selectIndex).height);}int mRealSizeWidth;//手机屏幕真实宽度
int mRealSizeHeight;//手机屏幕真实高度/*** 查找最接近屏幕宽高比的参数* @param cameraSizeList* @return*/
public int bestVideoSize(List<Camera.Size> cameraSizeList) {if (cameraSizeList == null) {return -1;}//计算屏幕的实际分辨率的比值float realRatio = ((float) mRealSizeWidth / (float) mRealSizeHeight);int index = 0;//目标索引float outRatio = -1f;for (int i = 0; i < cameraSizeList.size(); i++) {if (cameraSizeList.get(i).height <= mRealSizeHeight) {//取的值高度不能高于屏
//幕真实高度float ratio = (float) (cameraSizeList.get(i).width) / (float) (cameraSizeList.get(i).height);if (outRatio == -1f) {outRatio = Math.abs(ratio / realRatio - 1);index = i;} else {if (outRatio > Math.abs(ratio / realRatio - 1)) {//取绝对值小的值,即选择与屏幕分辨率最接近的值index = i;outRatio = Math.abs(ratio / realRatio - 1);}else if (outRatio == Math.abs(ratio / realRatio - 1)) {//如果有两组长宽比完全一样的,选择height比较大,小的可能会视频模糊if (cameraSizeList.get(i).height >= cameraSizeList.get(index).height) {index = i;outRatio = Math.abs(ratio / realRatio - 1);}}}}}return index;}//计算屏幕真实分辨率
public void getScreenSize() {WindowManager windowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);Display display = windowManager.getDefaultDisplay();Point outPoint = new Point();if (Build.VERSION.SDK_INT >= 19) {// 可能有虚拟按键的情况display.getRealSize(outPoint);} else {// 不可能有虚拟按键display.getSize(outPoint);}mRealSizeHeight = outPoint.y;mRealSizeWidth = outPoint.x;}
注意:我录的是横屏,所以我比较的都是高度height,如果是竖屏,最好是用宽度width。
安卓手机的各种各样的分辨率问题不再多说了,没办法把所有的都测一遍,从我手里的一批手机测过后都是达到了比较完美的效果(除非你手机的相机有支持与屏幕比例一模一样的分辨率,否则几乎不会是完全的全屏,最终的效果也会因手机不同有些许差异),如果有不合适的,可以在bestVideoSize()方法里通过限制你要取值的height的高度范围这个方向考虑。