Media Module之Camera(四) 拍照 底层分析

Media Module之Camera(四) 拍照 底层分析,第1张

下面主要介绍拍照流程的底层实现。

当指定了Camera的预览类,并开始预览之后,就可以通过takePicture()方法进行拍照了。它将以异步的方式从Camera中获取图像,具有多个回调类作为参数,并且都可以为null,下面分别介绍这些参数的意义:

• shutter:在按下快门的时候回调,这里可以播放一段声音。

• raw:从Camera获取到未经处理的图像。

• postview:从Camera获取一个快速预览的,不是所有设备都支持。

• jpeg:从Camera获取到一个经过压缩的jpeg。

虽然raw、postview、jpeg都是CameraPictureCallback回调,但是一般我们只需要获取jpeg,其他传null即可,CameraPictureCallback里需要实现一个方法onPictureTaken(byte[] data,Camera camera),data及为图像数据。值得注意的是,一般taskPicture()方法拍照完成之后,SurfaceView都会停留在拍照的瞬间,需要重新调用startPreview()才会继续预览。

如果直接使用taskPicture()进行拍照的话,Camera是不会进行自动对焦的,这里需要使用CameraautoFocus()方法进行对焦,它传递一个CameraAutoFocusCallback参数,用于自动对焦完成后回调,一般会在它对焦完成在进行taskPicture()拍照。

首先拍照的流程直接从Camerajava的takePicture开始分析。

可以看出,在方法中对各种回调的值进行了赋值,继续看底层对调函数的处理。

在应用层注册回调。

packages\apps\SnapdragonCamera\src\com\android\camera\AndroidCameraManagerImpljava

在应用层实现回调。

这里就是真正存储数据的地方了,在android系统有四个地方可以存储共同数据区,

ContentProvider,sharedpreference、file、sqlite这几种方式,这里利用的是file方式。

然后调用到JNI层相应方法。

根据之前分析的binder机制,Cameracpp -> ICameracpp -> CameraClientcpp(server端)

此处的takepicture是在CameraHardwareInterfaceh定义的方法。

frameworks/av/services/camera/libcameraservice/device1/CameraHardwareInterfaceh

在CameraClientcpp开始调用到HAL层中进行处理,接下来主要分析在

hardware/qcom/camera/QCamera2/HAL/QCamera2HWIcpp得具体实现。

在此方法中去更新状态机的状态。

hardware/qcom/camera/QCamera2/HAL/QCameraStateMachinecpp

首先调用回QCamera2HWIcpp的prepareHardwareForSnapshot方法。

接着调用到mm_camera_interfacec的mm_camera_intf_prepare_snapshot方法。

hardware/qcom/camera/QCamera2/stack/mm-camera-interface/src/mm_camera_interfacec

接着调用mm_camerac的mm_camera_prepare_snapshot方法,去与V4L2通信,准备拍照。

hardware/qcom/camera/QCamera2/stack/mm-camera-interface/src/mm_camerac

当底层对拍照准备完成之后,会调用到QCamera2HWICallbackscpp里,处理metadata

数据的方法metadata_stream_cb_routine中。

hardware/qcom/camera/QCamera2/HAL/QCamera2HWICallbackscpp

之后返回到QCamera2HWIcpp类里的take_picture方法,继续下面的 *** 作。

此处又返回到QCamera2HWIcpp类里的takePicture()方法中。

首先先停止并删除了preview的channel,然后调用addCaptureChannel()方法。

可以看出,在此方法中创建并初始化了channel,并且添加mediadata,postview,snapshot数据流到channel中。

返回到hardware/qcom/camera/QCamera2/HAL/QCamera2HWIcpp的takePicture()方法中,继续调用到开启capture的channel。

channel的start方法在之前的preview流程中具体介绍过,在此不做分析。

之后又调用了QCameraChannelcpp的startAdvancedCapture方法,然后是mm-camera-interfacec的process_advanced_capture方法,然后是mm-camerac的mm_camera_channel_advanced_capture方法,这一系列方法设置了当前管道是拍照模式。

通过mm-jpeg-interfacec处理数据流,并且生成jpeg文件,然后在QCamera2HWIcpp中处理从mm-jpeg-interfacec发出的jpeg相关事件。

此处更改了状态机的状态。

然后调用回QCamera2HWIcpp的processJpegNotify方法

此处调用的是QCameraPostProccpp的processJpegEvt方法。

hardware/qcom/camera/QCamera2/HAL/QCameraPostProccpp

接着调用sendDataNotify方法。

可以看出此处在给回调的对象装填数据,并且发出通知notifyCallback回调。并且,类型为CAMERA_MSG_COMPRESSED_IMAGE。

之后的流程与preview的流程相似,将数据向上层抛送,通过JNI返回到java层的回调函数中。

AndroidServerexe是腾讯公司的产品进程。要是安装了腾讯旗下应用宝(原qq手机管家PC版)和电脑管家,并且将安卓手机连接了PC机,该进程就会出现并开机启动,后来在新版QQ中腾讯又加入了此进程。腾讯推出的应用宝会在电脑上启动一个名叫AndroidServerexe的进程,一般人怎么也删除不了,后来官方论坛提供了一个UInsAndroidServerexe 工具,用于卸载和删除AndroidServer统一连接服务。使用方法如下:1、下载并解压缩文件。2、打开UInsAndroidServerexe,提示成功。3、重启计算机即可解决。

\vendor\mediatek\proprietary\hardware\mtkcam\legacy\main\hal\devicemgr\depend

\instancecpp

\vendor\mediatek\proprietary\hardware\mtkcam3\main\hal\devicemgr\depend

vendor/mediatek/proprietary/hardware/mtkcam/main/core/module/drv/

\vendor\mediatek\proprietary\hardware\mtkcam3\main\hal\device\3x\device

logLocked 方法中,会打印已经注册的摄像头信息,包括前置还是后置信息

\vendor\mediatek\proprietary\hardware\mtkcam3\main\hal\devicemgr

\vendor\mediatek\proprietary\hardware\mtkcam3\main\hal\devicemgr\provider\24

系列文章

Camera专题Qcom-你应该掌握的Camera调试技巧1

Camera专题Qcom-你应该掌握的Camera调试技巧2

数量:

adb shell setprop persistvendorcameraispdump_cnt 20

增加性能日志:Tag:[KPI_CAMERA]

日志打印:

kernel/arch/arm/boot/dts/qcom/msm8909dtsi

I2C资料:80-NU767-1,参考68-69页

举个例子:

i2c速率(I2C_FS_CLK ):400k

I2C_CLK:24M

占空比改成:50%

I2C_FS_CLK = I2C_CLK/(fs_div+hs_div+6)

fs_div + hs_div = 24M/400k - 6 = 60-6=54

如果占空比为50%

fs_div=hs_div=54/2=27

kernel/arch/arm/boot/dts/qcom/msm8909dtsi

I2C节点解释:

kernel/Documentation/devicetree/bindings/i2c/i2c-msm-v2txt

git diff > apatch

patch -p1 < apatch

查看pd lib库

adb shell setprop persistvendorcamerapdaf_logging 1

then reset device version will be print out like "PDLib Version: Major: %d Minor: %d Revision: %d"

lib库和校准工具对应关系

PD_lib_version Calibration_Version

33 J

42 J,L3

44 J,L3

45 J,L3,L4

46 J,L3,L4

47 J,L3,L4

50 L3,L4

51 L3,L4

52 L3,L4

53 L3,L4

关键log

注意,如果pdaf版本库在45-53之间,OV的sensor left map和right map 和高通是相反的

即:

op_pixel_clk = (传感器总数据传输速率) / 每个像素的位数

op_pixel_clk = sensor_MIPI_speedlanes/每个像素的位数

传感器总数据传输速率 = sensor_MIPI_speedlanes

vt_pixel_clk= HTS(0x380c/0x380d) VTS(0x380e/0x380f)FPS

op_pixel_clk=sensor_MIPI_speedlanes/bits-per-pixel

adb shell dumpsys window | findstr mCurrentFocus

adb shell dmesg > kernellog

1对焦速度 af_haf_util_end_search

adb root

adb shell setprop persistvendorcamerastatsisdebug 5

关键log: eis2_process

经过odex 的apk ,这样apk 是不完整的。

相机 mk 里加上 LOCAL_DEX_PREOPT := false

module_sensor_load_chromatix_stream_on

1最终的 AF ROI 坐标和大小,如何从 log 中获取?

key word:

0200000f, / H Clip Ratio Normal Light /

0200000f, / V Clip Ratio Normal Light /

0500000f, / H Clip Ratio Lowlight /

0500000f, / V Clip Ratio Lowlight /

1、请问 Calculated new ROI 的大小是怎么计算的?

ctr_x = image_width / 2;

ctr_y = image_height / 2;

dx = image_width h_ratio zoom_factor;

dy = image_height v_ratio zoom_factor;

x = ctr_x < (roi_out->dx / 2) 0 : (ctr_x - (roi_out->dx / 2));

y = ctr_y < (roi_out->dy / 2) 0 : (ctr_y - (roi_out->dy / 2));

2、假设 CAF 默认以中心为 ROI,那么 APP 有接口可以修改 ROI 的位置吗?

As you can see from 1(formula), no parameters are passed to change this value

adb shell setprop persistvendorcameracaldump 1

数据路径:"/data/misc/camera/" 或者"/data/vendor/camera/"

8909:

新:

1开机log里面搜索fdt

OF: fdt:Machine model: Qualcomm Technologies, Inc SDM429 QRD Spyro DVT Overlay

2搜索"Qualcomm Technologies, Inc SDM429 QRD Spyro DVT Overlay"

3打开kernel/msm-49/arch/arm64/boot/dts/qcom/sdm429-spyro-qrd-dvt-overlaydts

adb shell debuggerd -b <camera process PID>

persistvendordebugsetfixedfps

adb logcat -c && adb logcat -G 256M && adb logcat -v threadtime -b main -b crash -b kernel 1 > logtxt

aec_settle

ISO = (analog_gain100)/ISO_100_gain。

效果参数中 ISO_100_gain =1

adb shell dumpsys mediacamera

adb shell setprop persistvendorcameraHAL3enabled 1

当我们用mmm编译时,可能找不到某些依赖,又不想又mmma编译。

比如:

mmm packages/apps/Camera2

再编译 mmm packages/apps/Camera2

<uses-feature android:name="androidhardwaretypewatch" />

adb shell input keyevent 27

//拍照键

关键字:alg_status

01-02 09:02:12920 235 2894 D ae_lib : 2429, ae1_calculateEX: alg_status:146 stab: 0, status: 0, flicker: 0, fps: 107, effect-(s 34464(0935698s), g 128, dmy 0), final to sensor: idx: 271, (3683(0099993s), 0, 581), cur_lum: 133, bv:520, tar_lum [62, 66]

adb shell stop media

adb shell start media

adb shell stop cameraserver

adb shell kill -9 进程ID

frameworks/av/services/camera/libcameraservice/CameraServicecpp

hardware/qcom/camera/QCamera2/HAL/QCamera2HWICallbackscpp

typedef int64_t nsecs_t;

例如:

kernel/drivers/misc/sprd_camera/dcam/dcam_if_r4p0/dcam_ioctrl

要在makefile中添加你要的调用的路径

adb root

adb shell

读: lookat -l 1 0x40388D2C

写: lookat -s 0x00000081 0x40388D2C

frameworks/av/camera/CameraParameterscpp

adb shell setprop debugcameramf 2

adb shell setprop debugcameramf_pos 100

#define VAR_UNUSED(x) (void)(x)

原因:

so后面多了个空格,吐血了!!!

删掉空格后就ok了:

hardware/qcom/camera/QCamera2/HAL/test

vendor/bin/dual_camera_test

kernel/msm-49/arch/arm64/boot/dts/qcom/msm8937-pinctrldtsi

kernel/msm-49/arch/arm64/boot/dts/qcom/sdm429-spyro-qrd-evt-cameradtsi

        本文之所以有必要编写并作记录,主要原因是因为在工作中开发出一个万能的自定义camera预览控件之后,本是一个提高效率以及提供一个强大能力的控件,但是产品并不能理解这个万能控件存在的意义,产品无法与技术设计相结合的理解使用;并且发现我们的智能业务部Camera自定义预览技术虽然是使用多年,但是我们并没有真正的形成规范,由于产品在不能够理解系统平台(Android/iOS)给产品和研发带来了什么,导致产品可能会出现在不理解系统平台以及系统知识的情况下,臆想产品所谓的形态;当产品设计脱离了系统平台所支持的技术点以及设计的初衷,就会导致回归问题的时候,出现不必要的讨论,其根结就是一点:“信息不同步,知识不同步”。

        所以,为了提高效率,就采用记录和分享的方式,尝试性推动产品、测试、研发三者对工程与架构的同步理解,更深的懂得程序架构设计意义,尝试性通过信息同步的方式,在一个统一的知识储备的平台下,共同完成一个更高效,和高品质的工程产品。(为了能够让非技术:产品设计,以及测试都能够理解,所以,使用了更多的白话解释)

        附:强大灵活的FsCameraTextureView(第一版,自适应截取)( 第二版本版本:自适应展示)

        首先,抛出几个问题,

      1)什么是摄像头支持的previewSize?

      2)什么是视频或者的pictureSize

      3)  如何获取和查看摄像头支持的PreViewSize 和PictureSize ?

      4)手机预览所见的区域SurfaceView(TextureView)与camera 的previewSize的关系是什么?

      5)为什么会设计了两种预览方式view,两种预览方式都会有什么样子的效果呢?

一,概述

通过Android Camera拍摄预览中设置setPreviewCallback实现onPreviewFrame接口,实时截取每一帧视频流数据(简单说来,就是通过设置一个接口,接收系统回调通知我们的每一帧数据)

二,知识点

    1, camera支持的格式:

    2,拍照流程

    3,camera权限

  三,Android Camera中PreviewSize、 PictureSize、 SurfaceView(TextureView)之间的关系

        1,PreviewSize:

          相机预览时候的能支持的尺寸,简单的说一下,就是预览的大小,也就是拍照前能够看到的大小。(通过Android手机相机可以试一下,这个参数设置不同,同样的焦距下,拍摄桌子上一个固定距离的东西,看到的视野会不同)

          相机的预览尺寸,不能随意的设置值,只能通过camera的parameters的getSupportedPreviewSizes方法,获取支持的预览尺寸列表,并从列表中选择一个设置在parameters中。(通俗简单的说就是,获取camera中能够支持的预览大小合集,如果你想要查看某个预览对应的尺寸,就把该尺寸设置到camera的属性中即可,则camera会返回相对应尺寸的预览数据流提供显示)。

        2,PictureSize :

指的是拍照之后,最终拍摄到的大小,也就是的质量。尺寸同样也只能从支持的列表中选取一个设置。 调用camera的takePicture方法(拍照)后,获得拍照的图像数据,注意picturesize和previewsize的宽高比也要保证一致,否则获取的会将preview时的图像裁剪成picturesize的比例。 previewsize的分辨率,只会影响预览时的分辨率,不会影响获取的分辨率,所以preview只是确定了图像的取景最大范围。最终的分辨率是由picturesize来决定。 所以,最好的设置方法,例如:previewsize为1280720,picturesize为25601440。(由于我们没有拍照业务,目前这个知识,不做深究)

        3,SurfaceView(TextureView)

          用于展示camera预览图像的view,就是将preview获得的数据,放在这个view上。所以如果preview的宽高比和SurfaceView的宽高比不一样,就会导致看到的图像拉伸变形。图像拉伸变形解决的办法:

          (1)就是在确定preview的分辨率后,重新设置SurfaceView宽高;

          (2)如果SurfaceView宽高定死,则需要获取一个比例适合SurfaceView尺寸的PreviewSize 的preview,尽量小的裁剪,然后填充在SurfaceView中。

        4,利用的显示方式,理解Preview与SurfaceView(TextureView)显示关系

          ImageView (UI上面设计的一个控件)与bitmap 的关系,比如限定死一个ImageView的大小,但是与ImageView尺寸不一致,就会有几种方案,首先选取一张长方形19201080的,ImageView就是紫色部分,无论长宽比都比ImageView要大。

适配例1:拉伸填充ScaleTypeFIT_XY :虽然被全部填充,但是整个为了适配已经扭曲,失真,缩放到控件大小,完全填充控件大小展示。

适配例2:等比例裁剪填充ScaleTypeCENTER_CROP ,因为在该模式下,会被等比缩放直到完全填充整个ImageView,并居中显示。该模式也是最常用的模式了。如图可以看到,的高度是能完全展示出来的,但是左右部分被进行了裁剪,并没有完全显示。

适配例3 :  ScaleTypeCENTER_INSIDE,此模式,用以完全展示内容为目的。将被等比缩放到能够完整展示在ImageView中并居中,如果大小,小于控件尺寸,那么就直接居中展示该

            适配ImageView方式还有很多,就不一一列举,这三种已经足够重要,为什么讲解camera预览,却穿插了的适配,其实可以这么理解,camera的preview就是由多张组成,不断的像帧动画一样变化,而SurfaceView就是一个载体,相当于ImageView,业务中定死了SurfaceView的大小之后,被动的承载你选择的previewSize,来展示camera的Preview,你可以选择类似于前面三种例子来理解preview的填充,以下会举例说明preview的填充策略选择有哪几种方式,我们会采用哪种方式:

        1)拉伸填充,自适应view,不可取,比如:手机的SurfaceView是整个手机的屏幕尺寸(全屏填充),或者任意尺寸比例的surfaceView,使用这种方式,就如同(适配例1)的方式,导致视频扭曲,拉伸。

        2)等比例裁剪填充,目前我们项目中,采用的就是这种方式,并且提供给很多三方使用,已经成为一种独立,并且稳定的技术实现自定义view,简单说一下视频的适配策略方式,SurfaceView随便由业务方,自定义宽度大小,比如业务方选择了19001000的SurfaceView, 我们的适配过程是:(1)从PreviewSize列表中选取最接近SurfaceView尺寸的PreviewSize(假设该摄像头,只支持19201080,和320640),19201080最接近,所以被获取;(此处展示一下蹩脚的英文Try to find an size match aspect ratio and size,尝试找到纵横比与view大小比适中的一个尺寸)(2)等比例裁剪填充到SurfaceView,首先我们设计的逻辑是,先选取一个缩放比例,假设等比例1920的按照SurfaceView的宽度等比例缩小到1900,而为了不让Preview失真,则高度1080等比例缩小的值是106875(等比例方程式,这里就不重复初中的知识,请自行计算),所以被压缩成为19001068这个尺寸,依旧保证完整,并且不失真。(3)将等比例缩减的,19001068进行显示在19001000的SurfaceView中,就会有一种效果类似(适配例2),宽度全部展示,高度被裁剪。(如同  适配例2中左右部分裁剪一样的道理)                       

          3)完全展示camera内容的缩放填充(类似适配例3),我们打开任意一部手机的camera,预览图像都没有全屏幕展示,类似拍照功能,所见即所得,PreviewSize是多少,就显示什么样子的比例尺寸,以及最后生产的照片比例就是多少,我们的自定义view,也可以随意设置大小,此模式下,用以完全展示camera内容为目的。Preview将被等比缩放到能够完整展示在SurfaceView中并居中,但是可能会有部分位置无法填充(类似适配例3显示效果)。

(该方式只是进行了技术储备,由于没有业务场景设计,所以没有使用,目前只是储备了这样的自定义控件)

四,灵活的自定义TextureView预览控件       

        FsCameraTextureView(第一版,自适应截取):等比例裁剪填充,方式(适配方式2),采用前面说的适配方式2,而产出的一种自定义view,2019年5月产出至今,在金融APP,以及商城的app中使用,经过逐步优化,和多版本检验,目前该控件,拥有以下特点:  1)稳定:目前各个使用场景,均无逻辑崩溃,内存泄漏,线程等任意问题; 2)灵活:随意设置预览view的尺寸大小,自适应任意业务设计;不仅仅满足刷脸业务,并且满足任意相机预览业务方使用; 3)提高效率,减轻工作量:使用简单, *** 作步骤简洁,接入只需要两步;减轻接入端,或者想要使用相机预览的业务的工作量,不需要重复造车,并且安全稳定。

      输出的业务方有(经不完全统计):(目前业务为保密进行公网保密处理)1)创新科技业务部-区块链部门 2)泰国人脸识别业务SDK3)S DBank 人脸业务4)核验身份z业务5)HTBank 人脸业务 6)云,商业平台部门

      FsAllPreviewCameraTextureView(技术储备版,全预览模式显示):完全展示camera内容的缩放填充,采用前面说的(适配方式3)适合拍照相关的业务使用,优点同样是,外部业务随意改变view大小,可以自适应view,由于目前没有业务方使用,暂时做储备,不深入讲解。

如果可以控件开源成功,后期,我将开源这两个控件,让更多的使用方使用,我们也希望共同技术进步,提高工程产出的使用能力。

预计下一次分享内容是(临时命名)

1)人脸核验内存和线程爆表到泄漏为零

2)分享七年前参于的Scrum(如何提高岗位间效率所定制的敏捷开发过程)

本文参考:

>

上图是画的是针对Camera的Grpahic Buffer基本流向图

从图中可以看出,camera架构主要拥有三个进程:

1、Camera App

2、CameraServer

3、CameraProvider

在研究Grpahic Buffer流向时,Camera App作为一个系统app,不免俗的要和SurfaceFlinger

进程打交道,可以认为Camera App的整个GUI的合成显示是交给SurfaceFlinger的。

而除了GUI的surface,camera还拥有一个用来显示preview的surface,这个surface的graphic

buffer是在当前进程分配,填充是camera provider进程填充的,具体步骤如上图所示,不在赘述。

mm qcamera daemon 是一种摄像守护程序,从字面上猜测有可能是‍美国高通公司研发的。守护

是一种计算机进程,采纳了Clerk Maxwell(著名物理学家)的著名物理思想,守护程序是一种计算机进程,它的工作就是"监听"想要更多特殊网络服务的连接,处理所有被除数认为是套接字尝试的临时连接的合法尝试可以守护一个或多个程序,保证其不被终止。可以看出,这个程序作为守护程序在系统中运行,执行保护任务,需要一定能量维持,而你的机子电量有限,就会觉得很费电了。

以上就是关于Media Module之Camera(四) 拍照 底层分析全部的内容,包括:Media Module之Camera(四) 拍照 底层分析、androidserver.exe是什么程序、MTK camerahalserver 层初始化流程等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/10125849.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-05
下一篇 2023-05-05

发表评论

登录后才能评论

评论列表(0条)

保存