【Android RTMP】NV21 图像旋转处理 ( 问题描述 | 图像顺时针旋转 90 度方案 | YUV 图像旋转细节 | 手机屏幕旋转方向 )
文章目录
一、 NV21 图像格式与 Camera图像传感器方向问题
1. Camera 采集画面并预览推流 : 这里注意 , 之前图像被逆时针旋转了 90 度 , 设置了图像传感器角度后 , 预览图片纠正过来了 , 但是 Camera 的图像传感器采集的 NV21 格式的图像还是被旋转了 90 度 ;
2 . 电脑端观看直播效果展示 : 屏幕画面被逆时针旋转了 90 度 , 这是因为之前摄像头传感器只设置了将预览画面纠正过来 , 但是 NV21 格式的图像数据还是被逆时针旋转了 90 度的数据 ;
具体涉及到的图像格式 , 以及图像传感器方向 , 屏幕方向的关系 , 参考博客 【Android RTMP】Android Camera 视频数据采集预览 ( 图像传感器方向设置 | Camera 使用流程 | 动态权限申请 )
二、 NV21 图像格式视频旋转
1. 图像旋转问题及解决方案 ( 顺时针旋转 90 度 )
图像旋转问题及解决方案 :
① 问题描述 : 分析上面的画面 , 可以看到视频被逆时针旋转了 90 度 , 即画面图像被逆时针旋转了 90 度 ;
② 解决方案 : 将 Camera 采集的 NV21 格式的图像顺时针旋转 90 度 , 即可解决上述问题 ;
2. NV21 图像格式数旋转方案
NV21 图像格式数据排列 : 以
像素的图片为例 , 其有
个 Y 数据 , UV 数据只有
组 , 共
个 ;
1 . 数据的排列格式如下矩阵 :
个 Y 数据在前 , 然后
组 (
个 ) VU 数据交替存放 ;
2 . 旋转像素灰度值 Y : 像素值顺时针 90 度旋转后的样式 ;
① 旋转矩阵 :
② 旋转后的最终 Y 灰度值 矩阵 :
3. 旋转图像的 饱和度 色彩值 UV
旋转图像的 饱和度 色彩值 UV : UV 数据旋转后 , 只是给出了 UV 数据的位置 , 还需要将 UV 数据按照顺序排列 :
① 旋转 UV 数据矩阵 : 该旋转后只能代表 UV 数据组的位置 , 即 第一组 UV 数据 (
) 在左上角 , 第二组 UV 数据 (
) 在右上角 , 第三组 UV 数据 (
) 在左下角 , 第四组 UV 数据 (
) 在右下角 ;
② 旋转后的最终 UV 色彩值 饱和度 矩阵 :
4. 旋转后的 NV21 格式
NV21 格式的图像的 YUV 值顺时针旋转 90 度后的 YUV 矩阵为 :
三、 Android 手机端屏幕旋转方向
1. 获取手机屏幕方向
获取手机屏幕方向 : 调用下面的方法 , 可以获取到
个手机屏幕方向 ;
mRotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
调用上述方法 , 获取的手机屏幕方向是 Surface.ROTATION_0 , Surface.ROTATION_90 , Surface.ROTATION_180 , Surface.ROTATION_270 , 四个常量中的一个
2. Surface.ROTATION_0 正常竖屏方向
Surface.ROTATION_0 正常竖屏方向 :
① 常量含义 : ROTATION_0 常量代表手机自然方向逆时针旋转 0 度, 竖屏 ;
② 方向说明 :
- 头部 ( 摄像头的一边 ) 在上边
- 尾部 ( Home / 返回 键的一边 ) 在下边
一般的竖屏操作方式, 也是最常用的方式 ;
3. Surface.ROTATION_90 正常竖屏方向
Surface.ROTATION_90 正常竖屏方向 :
① 常量含义 : ROTATION_90 常量代表手机自然方向逆时针旋转 90 度, 横屏 ;
② 方向说明 :
- 头部 ( 摄像头的一边 ) 在左边
- 尾部 ( Home / 返回 键的一边 ) 在右边
一般横屏操作方式 ;
4. Surface.ROTATION_180 正常竖屏方向
Surface.ROTATION_180 正常竖屏方向 :
① 常量含义 : ROTATION_180 常量代表手机自然方向逆时针旋转 180 度, 竖屏 ;
② 方向说明 :
- 头部 ( 摄像头的一边 ) 在下边
- 尾部 ( Home / 返回 键的一边 ) 在上边
一般很少这样操作 ;
5. Surface.ROTATION_270 正常竖屏方向
Surface.ROTATION_270 正常竖屏方向 :
① 常量含义 : ROTATION_270 常量代表手机自然方向逆时针旋转 270 度, 横屏 ;
② 方向说明 :
- 头部 ( 摄像头的一边 ) 在右边
- 尾部 ( Home / 返回 键的一边 ) 在左边
一般横屏操作方式 ;
四、 Android 手机端屏幕方向获取代码示例
Android 手机端屏幕方向获取代码示例 :
/**
* 设置 Camera 预览方向
* 如果不设置, 视频是颠倒的
* 该方法内容拷贝自 {@link Camera#setDisplayOrientation} 注释, 这是 Google Docs 提供的
* @param parameters
*/
private void setCameraPreviewOrientation(Camera.Parameters parameters) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(mCameraFacing, info);
/*
获取屏幕相对于自然方向的角度
自然方向就是正常的竖屏方向, 摄像头在上, Home 键在下, 对应 Surface.ROTATION_0
ROTATION_0 是自然方向逆时针旋转 0 度, 竖屏
头部 ( 摄像头的一边 ) 在上边
尾部 ( Home / 返回 键的一边 ) 在下边
一般竖屏操作方式, 也是最常用的方式
ROTATION_90 是自然方向逆时针旋转 90 度, 横屏
头部 ( 摄像头的一边 ) 在左边
尾部 ( Home / 返回 键的一边 ) 在右边
一般横屏操作方式
ROTATION_180 是自然方向逆时针旋转 180 度, 竖屏
头部 ( 摄像头的一边 ) 在下边
尾部 ( Home / 返回 键的一边 ) 在上边
一般很少这样操作
ROTATION_270 是自然方向逆时针旋转 270 度, 横屏
头部 ( 摄像头的一边 ) 在右边
尾部 ( Home / 返回 键的一边 ) 在左边
一般很少这样操作
博客中配合截图说明这些方向
*/
mRotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
switch (mRotation) {
case Surface.ROTATION_0:
degrees = 0;
/*
Camera 图像传感器采集的数据是按照竖屏采集的
原来设置的图像的宽高是 800 x 400
如果屏幕竖过来, 其宽高就变成 400 x 800, 宽高需要交换一下
这里需要通知 Native 层的 x264 编码器, 修改编码参数 , 按照 400 x 800 的尺寸进行编码
需要重新设置 x264 的编码参数
*/
mOnChangedSizeListener.onChanged(mHeight, mWidth);
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
mCamera.setDisplayOrientation(result);
}
相关文章
- 2017年Android SDK下载安装及配置教程
- android studio usb连接手机_android studio怎么用真机调试
- Android Toast的立即取消与显示「建议收藏」
- Android平台实现系统内录(捕获播放的音频)并推送RTMP服务技术方案探究
- Android通知监听服务之NotificationListenerService使用篇
- 【ijkplayer】编译 Android 版本的 ijkplayer ③ ( 执行 compile-ffmpeg.sh clean 命令 | 下载并配置 android-ndk-r10e )
- 【ijkplayer】编译 Android 版本的 ijkplayer ⑥ ( 进入 ijkplayer-android/android 目录 | 执行 compile-ijk.sh 脚本完成编译 )
- Android常见输入inputType类型详解手机开发
- 基于Android官方Paging Library的RecyclerView分页加载框架详解手机开发
- Android控制文字水平间距android:letterSpacing详解手机开发
- Android开发中遇到的问题(二)——新建android工程的时候eclipse没有生成MainActivity和layout布局详解手机开发
- 苹果iOS系统在美市场份额持续增长 Android系统份额有所下滑详解手机开发
- [android] 天气app布局练习(四)详解手机开发
- [android] 手机卫士黑名单功能(ListView优化)详解手机开发
- [android] 手机卫士手机定位的原理详解手机开发
- [android] 显示意图激活另外一个activity详解手机开发
- android 减少图片出现oom错误详解手机开发
- 介绍几个好用的android自定义控件详解手机开发
- 再谈Android Binder跨进程通信原理详解手机开发
- android MVP框架详解手机开发
- 深入理解Android插件化技术详解手机开发
- Android NDk环境配置详解手机开发
- Android——打造万能适配器(CommonAdapter)详解手机开发
- app:showAsAction 和android:showAsAction详解手机开发
- Android 拨打电话的代码详解编程语言
- android开发中获取手机分辨率大小的方法
- Android顶部工具栏和底部工具栏的简单实现代码
- android获取手机唯一标识的方法
- android检查手机和无线是否连接的方法