Camera2 预览旋转方向、拍照、录像成像旋转

news/2024/9/19 11:08:15/ 标签: 数码相机, Camera2

文章目录

  • 前言
  • 一、思考问题
  • 二、基础补充、资源参考
    • 架构图了解
    • Camera相关专栏
    • 零散知识了解
    • 部分相机源码参考,学习API使用,梳理流程,偏应用层
    • Camera2 系统相关
  • 三、核心问题:预览方向不对【图片、视频】、成像存储不对、拉伸问题
    • 预览
    • 视频保存
    • 预览拉伸
    • 其它
  • 总结


前言

自己在开发MTK相机、RK 相机 Camera2 预览旋转方向、拍照、录像成像旋转问题,简单整理总结,后续相关开发可直接参考

一、思考问题

自己在开发公司MTK平台上Camera2相机过程中,遇到一些问题,对于开发过相机的朋友应该也会遇到各种各种问题,特别是Android系统定制,各种情况很复杂;涉及到不同的平台,核心思想一样,但是实际应用架构,业务就完全不一样了。 下面先抛出几个问题:

  • 相机开发中遇到预览、成像[拍照照片、录像视频] 方向不对、拉伸压缩 怎么办
  • 相机分为几个层 驱动、系统、应用层,相机的流程成像原理怎样的
  • 从常识上看,我们的手机相机拍照、录像都是横竖屏的,人永远是正的,为什么呢?
  • 上面用到了Gsensor 来判断方向,虽然有了Gsonsor 方向+屏幕物理方向,但是系统用到了强制横竖屏,屏幕物理方向是错乱的
  • 屏幕方向问题[存在横屏+竖屏各两个方向],不清楚客户实际机器是横屏、竖屏、横竖屏;
  • 装配方向,实际的装配方向不确定,摄像头本身是有一个方向的,如果摄像头方向不是按照正常装配的,那么肯定预览和成像方向不对
  • 每个平台相机源码不一致,在更改系统源码的过程中,源码不一致,那么相机Camera2 开发流程、预览、成像原理、人脸检测、特效、架构
    又是怎样的? 方便修改问题

二、基础补充、资源参考

相机整个模块确实太专业、复杂了。 无论从硬件外设、驱动【USBCamera免驱】、相机 都比较专业、覆盖面及广,针对思考中的问题 给出自己认为比较好相关博客,方便了解,助于梳理流程、提升认知。

对于上层应用或者Framework 系统应用开发者,只需要了解基本的架构、API、使用方法,当然这些也不简单的
下面提供部分资源,方便快速了解,充电:

架构图了解

MTKCamera2相机架构
Camera2架构
Android Camera架构简析

Camera相关专栏

Camera Framework 专栏
小驰私房菜系列
小驰私房菜MTK系列
小驰Camera 开发系列
Camera 相机开发
展讯平台 Camera
官方文档:谷歌官方 API 描述

零散知识了解

MTK 相机UI介绍
Camera2 相机认知
Camera2学习笔记
camera2关于拍照预览方向旋转90度和拍照图片镜像功能实现
Camera2 预览集成、简单拍照:熟悉预览步骤流程比较有用
Camera镜像上下左右颠倒问题的解决办法
MTK相机成像质量差
Camera应用分析

部分相机源码参考,学习API使用,梳理流程,偏应用层

极客相机 Camera2 API
Camera2 API详解
极客相机源码
Camera2 相机Demo
Camera2 专业相机Demo
拍照、预览、录像Demo
使用Camera2 拍照

Camera2__64">Camera2 系统相关

Camera2 Service 启动

如上资源可能不能解决项目中的实际问题,每个ODM厂家平台的源码不一样,修改问题地方不一样,包名、类 都不一样,但思路、思想一样。当然具体问题具体分析,针对性充电对自己解决问题还是有很大帮助的。

三、核心问题:预览方向不对【图片、视频】、成像存储不对、拉伸问题

当前只给出MTK平台相关解决思路,和代码片段

预览

根据gsensor 方向,适配需要旋转的方向,来解决视频、图片预览方向问题
vendor\mediatek\proprietary\packages\apps\Camera2\host\src\com\mediatek\camera\ui\preview\TextureViewController.java
updatePreviewSize 方法中 最终通过gsenmsor 方向来

    考虑旋转方向: Log.d(MYTAG,"6666666666  setAspectRatio  mPreviewAspectRatio :"+mPreviewAspectRatio +"    mTextureView:"+mTextureView);int  gSensorOrientation= mApp.getGSensorOrientation();int rotationNum= 360-gSensorOrientation;mTextureView.setRotation(rotationNum);Log.d(MYTAG,"6666666666 genju  sensor fangxiang  xuanzhuan   gSensorOrientation:"+gSensorOrientation+"  rotate dushu:"+rotationNum);Log.d(MYTAG,"6666666666   rotation 90");mTextureView.setAspectRatio(mPreviewAspectRatio);   

视频保存

遇到视频保存,方向不对问题
视频保存倒置问题,竖屏录像保存的视频会倒置180度。 修改文件:vendor/mediatek/proprietary/packages/apps/Camera2/common/src/com/mediatek/camera/common/mode/video/VideoHelper.java

configRecorderSpec 方法中,recorderSpec.orientationHint 值 根据gsensor 方向,动态适配两种不同的竖屏方向的视频保存方向public IRecorder.RecorderSpec configRecorderSpec(CamcorderProfile profile, String cameraId,CameraDeviceManagerFactory.CameraApi api, ISettingManager settingManager) {sProfile = profile;IRecorder.RecorderSpec recorderSpec = new IRecorder.RecorderSpec();recorderSpec.videoSource = MediaRecorder.VideoSource.SURFACE;int gSensorOrientation=mApp.getGSensorOrientation();int testDirection =	getRecordingRotation(mApp.getGSensorOrientation(),getCameraCharacteristics(mApp.getActivity(), cameraId));recorderSpec.orientationHint = getRecordingRotation(mApp.getGSensorOrientation(),getCameraCharacteristics(mApp.getActivity(), cameraId));switch (testDirection){case 0:    //dao li zhuang taiLog.d(MYTAG,"port dao li zhuang tai");recorderSpec.orientationHint=180;break;case  270:Log.d(MYTAG,"land zhuang tai");break;case  180: //zheng lirecorderSpec.orientationHint=0;Log.d(MYTAG,"port zhengli zhuang tai");break;default:break;}		recorderSpec.isHEVC = VIDEO_FORMAT_HEVC.equals(settingManager.getSettingController().queryValue("key_video_format"));LogHelper.d(TAG, "[configRecorderSpec] recorderSpec.isHEVC = " + recorderSpec.isHEVC);if (VALUE_ON.equals(settingManager.getSettingController().queryValue("key_microphone"))) {recorderSpec.isRecordAudio = true;recorderSpec.audioSource = MediaRecorder.AudioSource.CAMCORDER;} else {recorderSpec.isRecordAudio = false;}recorderSpec.profile = sProfile;recorderSpec.maxDurationMs = 0;recorderSpec.maxFileSizeBytes = getRecorderMaxSize();recorderSpec.location = mCameraContext.getLocation();Log.d(MYTAG,"configRecorderSpec  gSensorOrientation:"+gSensorOrientation+"   testDirection:"+testDirection);return recorderSpec;}

预览拉伸


PreviewManager,这个地方修改,强制写死横竖屏状态下预览分辨率,如果横屏状态下不写,调试发现自动设置情况下会导致预览变形import java.util.concurrent.CopyOnWriteArrayList;
+import android.util.Log;
+import android.content.res.Configuration;
+import android.view.WindowManager;+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import android.content.Context;/*** A manager for camera preview module, now it support surfaceview or textureview.*/
@@ -222,8 +227,18 @@ public class PreviewManager {@Overridepublic void run() {notifyPreviewAreaChanged();
-                    mPreviewFrameLayout.setPreviewSize((int) mPreviewArea.width(),
-                            (int) mPreviewArea.height());
+            Configuration newConfig = mApp.getActivity().getResources().getConfiguration();
+                       if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
+                                mPreviewFrameLayout.setPreviewSize(1080,
+                            1920);
+                 WindowManager wm = (WindowManager) mApp.getActivity().getSystemService(Context.WINDOW_SERVICE);
+                 int width = wm.getDefaultDisplay().getWidth();
+                 int height = wm.getDefaultDisplay().getHeight();
+                 int gOrientation= mApp.getGSensorOrientation();
+             } else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
+                       mPreviewFrameLayout.setPreviewSize(1920,
+                            1080);
+             }}});}PreviewTextureView,这个地方修改,横竖屏状态下Measure区分,且横屏状态下 width 和 height 相反,解决镜像变形问题@@ -43,12 +43,15 @@ import android.util.AttributeSet;import android.view.Display;import android.view.TextureView;import android.view.WindowManager;
+import android.util.Log;
+import android.content.res.Configuration;/*** A {@link TextureView} that can be adjusted to a specified aspect ratio.*/public class PreviewTextureView extends TextureView {
+    private static final String MYTAG = "PreviewTextureView";private static final double ASPECT_TOLERANCE = 0.03;private double mAspectRatio = 0.0;
@@ -131,7 +134,15 @@ public class PreviewTextureView extends TextureView {previewWidth = shortSide;previewHeight = longSide;}
+               Log.d(MYTAG," onMeasure previewWidth:"+previewWidth+"  previewHeight:"+previewHeight);
+             Configuration config =  getResources().getConfiguration();
+        if (config.orientation == Configuration.ORIENTATION_PORTRAIT) {
+                 Log.d(MYTAG," portscreen onMeasure previewWidth:"+previewWidth+"  previewHeight:"+previewHeight);setMeasuredDimension(previewWidth, previewHeight);
+        } else if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
+                 Log.d(MYTAG," landscreen onMeasure previewWidth:"+previewHeight+"  previewHeight:"+previewWidth);
+          setMeasuredDimension(previewHeight, previewWidth);
+        }}

其它

增强缩略图质量,部分客户反馈缩略图显示不清晰   BitmapCreator.java FaceViewCtrl.java  showView 方法, 屏蔽人脸检测框导致在强制横竖屏情况下 人脸检测方框显示异常。private void showView() {if (mFaceView != null && mFaceView.getVisibility() != View.VISIBLE) {LogHelper.d(TAG, "[showView]");
-            mFaceView.setVisibility(View.VISIBLE);
+           // mFaceView.setVisibility(View.VISIBLE);}}

总结

1)在布局、预览镜像和Activity及对应控制管理的方法中对布局和镜像旋转、设置预览分辨率等来解决
2)Manifest.xml 配置修改,规避窗体变化导致布局镜像异常
3)预览、拉伸、成像异常在对应的文件中修改

部分源码参考片段


http://www.ppmy.cn/news/1525638.html

相关文章

类型参数传值问题

一、基本数据类型传参问题 public static void main(String[] args) throws Exception {Integer number null;method01(number);}private static void method01(int number){System.out.println("number " number);}Ps: 基于int基本数据类型传参的时候&#xff0c…

Linux操作系统入门(二)

完成了前篇所进行的VMware下载安装,并在其内配置了CentOS7的linux操作系统之后,我们得以正式进入了Linux的世界。 一.安装FinalShell 在本篇中,为了更好的在Windows系统上对虚拟机中的linux操作系统进行操作,我们需要下载一款新…

基于I2S的音频ADC_DAC的_FPGA的驱动

前言 这是博主自己原创的成果,如要转载或者引用,请标明出处,具体的视频讲解见我的bili视频讲解,先附链接 引出目的 课题项目需求做一个基于FPGA的相控扬声器后面进行数字滤波器的设计与实现后期FPGA算法的实现 整体模块框图 驱…

java重点学习-线程池的使用和项目案例

十一 线程池的使用场景 你们项目哪里用到了多线程 批量导入:使用了线程池CountDownLatch批量把数据库中的数据导入到了ES(任意)中,避免OOM数据汇总:调用多个接口来汇总数据,如果所有接口(或部分接口)的没有依赖关系,就可以使用线程池future来…

基于APISIX实现API网关案例分享

一、APISIX介绍 1、定义 Apache APISIX 是一个动态、实时、高性能的云原生 API 网关。它构建于 NGINX + ngx_lua 的技术基础之上,充分利用了 LuaJIT 所提供的强大性能。 2、软件架构 2.1、架构图 APISIX 主要分为两个部分: APISIX 核心:包括 Lua 插件、多语言插件运行时…

Opencv实现提取卡号(数字识别)

直接开始 实行方法 解析命令行参数:使用argparse库来解析命令行输入,确保用户提供了输入图像和模板图像的路径。 读取模板图像:使用cv2.imread()函数读取模板图像的路径,并显示原始图像。 图像预处理: 将图像转换为…

Java面试篇基础部分-Java中的集合类

Java集合是面试中经常被问到的一块内容,很多人在这个地方被面试官吊打。Java集合类被定义在java.util包中,主要有四种集合,分别是List、Queue、Set和Map,每种集合分类如下图所示 List集合 List是一种在开发中比较常用的集合类,作为有序的Collection的典范,分别有如下的…

ubuntu20.4安装Qt5.15.2

ubantu20.4镜像下载地址: https://releases.ubuntu.com/focal/ubuntu-20.04.6-desktop-amd64.iso Qt5.15.2下载地址: https://download.qt.io/official_releases/online_installers/ 安装步骤 1、进入地址后选择对应安装包,我这是ubuntu…

redis基本数据结构-string

文章目录 1. redis的string数据结构2. 常见的业务场景2.1 缓存功能案例讲解背景优势解决方案代码实现 2.2 计数器案例讲解背景优势解决方案代码实现 2.3 分布式锁案例讲解背景优势解决方案代码实现 2.4 限流案例讲解背景优势解决方案代码实现 2.5 共享session案例讲解背景优势解…

HarmonyOS开发之路由跳转

文章目录 一、路由跳转模式与实例1.router.pushUrl2.router.replaceUrl3.router.back 一、路由跳转模式与实例 跳转模式 有点类似于vue的路由跳转 router.pushUrl 保留路由栈,保留当前的页面;router.replaceUrl 销毁当前页面,跳转一个新的页…

Go语言现代web开发08 if和switch分支语句

if语句 If is the most common conditional statement in programming languages. If the result of the condition caculation is positive(true), the code inside if statement will be executed. In the next example, value a will be incremented if it is less than 10…

opencv学习:信用卡卡号识别

该代码用于从信用卡图像中自动识别和提取数字信息。该系统将识别信用卡类型,并输出信用卡上的数字序列。 1.创建命令行参数 数字模板 信用卡 # 创建命令行参数解析器 ap argparse.ArgumentParser() # 添加命令行参数 -i/--image,指定输入图像路径 ap.…

饿了么基于Flink+Paimon+StarRocks的实时湖仓探索

摘要:本文整理自饿了么大数据架构师、Apache Flink Contributor 王沛斌老师在8月3日 Streaming Lakehouse Meetup Online(Paimon x StarRocks,共话实时湖仓架构)上的分享。主要分为以下三个内容: 饿了么实时数仓演进之…

python-游戏自动化(一)(实战-自动刷视频点赞)

前提准备 什么是游戏自动化? 游戏自动化是指通过对游戏的界面结构的解析或界面图像的处理与识别,再模拟人工对软件进行的各种操作,从而实现自动化,达到解放双手,节约时间,提高效率的目标。 在本教程中&am…

房产销售系统开发:SpringBoot技术要点

摘 要 随着科学技术的飞速发展,各行各业都在努力与现代先进技术接轨,通过科技手段提高自身的优势;对于房产销售系统当然也不能排除在外,随着网络技术的不断成熟,带动了房产销售系统,它彻底改变了过去传统的…

RDMA应用场景及效果

GPU Direct 参考:网络架构如何支持超万卡的大规模 AI 训练?| AICon_芯片与网络_InfoQ精选文章 GPU 网络的情况已经发生了很大变化。每个 GPU 都有自己的内部互联,例如 NVIDIA 的 A100 或 H800,它们内部的 NVLink 互联可以达到 6…

【网络安全】空字节绕过:URL回调+XSS+SQL绕WAF

未经许可,不得转载。 文章目录 空字节URL回调XSSSQL空字节 \0,也称为null字节,是一个值为零的特殊字符。在编程中,通常用来表示字符串的结束。攻击者可以利用null字节注入来绕过一些验证或过滤机制。 以下三个漏洞,空字节功不可没。 URL回调 密码重置功能,发起请求后…

如何找到UI5 Tooling-UI5命令

文章目录 UI5 Tooling第一步:首先找找到UI5 的官网如下:第二步:找到get started, 学习UI5 Demo第三步:开发环境--搭建安装UI5 命令行界面Global installation to have the command availableAdditional local install …

学习平台|基于java的移动学习平台系统小程序(源码+数据库+文档)

学习平台|学习平台系统|在线学习平台系统小程序 目录 基于java的移动学习平台系统小程序 一、前言 二、系统设计 三、系统功能设计 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取: 博主介绍:✌️大厂码…

基于大数据的科研热点分析与挖掘系统

温馨提示:文末有 CSDN 平台官方提供的学长 QQ 名片 :) 1. 项目简介 科研活动的快速发展产生了大量的学术文献,如何从这些文献中提炼出有价值的科研热点和趋势成为了一个重要的问题。本项目旨在开发一个基于大数据的科研热点分析可视化系统,采…