精华内容
参与话题
问答
  • 高通:旨在分享高通系列芯片资料,和工程师们一起学习,讨论! 高通芯片型号分类: 高通芯片型号大全:http://bbs.16rd.com/citiao.html  高通资料下载:...

    高通:旨在分享高通系列芯片资料,和工程师们一起学习,讨论!

    高通芯片型号分类:

    高通芯片型号大全:http://bbs.16rd.com/citiao.html

     高通资料下载:http://bbs.16rd.com/tshuz_attachcenter-tshuz_attachcenter.html

     

     EX:

    MSM8998处理器:MSM8998即骁龙835,是一款于2017年初由高通厂商研发的支持Quick Charge 4.0快速充电技术的手机/超轻薄笔记本电脑处理器,采用10纳米先进设计,其尺寸比以前的设计减小35%,能耗减少25%,能够提供出色的超长电池寿命、逼真的VR和AR体验、尖端摄像头功能和千兆级下载速度。

    资料下载:MSM8998

     MSM8916处理器:MSM8916即骁龙410,是基于Cortex-A53架构的64位处理器,是高通在2013年发布的首款64位处理器。为全球智能手机提供多模多卡功能支持,同时为嵌入式应用程序提供多功能电源效率。

    资料下载:MSM8916

    骁龙625处理器:骁龙625是高通(Qualcomm)首款采用14nm制程打造的八核心处理器,主频高达2GHz,也就是处于和骁龙820一样的工艺节点并且同样支持Quick Charge 3.0快充技术,在为高端智能手机带来优质用户体验的同时,避免了电量的大幅损耗。

    资料下载:骁龙625

    骁龙820处理器:骁龙820处理器专为提供创新用户体验的顶级移动终端而设计,Adreno 530 GPU 、Hexagon 680 DSP和Kryo CPU一起构筑了骁龙820之异构计算“铁三角”;基于骁龙 820 处理器的终端于2016 年上半年上市,主要针对智能手机、平板电脑或虚拟现实设备。目前确定采用 Snapdragon 820 的设备已经超过 60 款。

    资料下载:骁龙820

    MSM8930处理器:MSM8930属于美国高通公司骁龙S4 Plus MSM8x30系列处理器,是一款同时支持UMTS、CDMA、TD-SCDMA和LTE-TDD、LTE-FDD等制式的单一平台处理器,能够服务所有的中国运营商。

    资料下载:MSM8930

    ··························································等等!

    展开全文
  • 本文介绍了 1.高通手机开机流程 2.boot代码深入分析 3.Ui_task的深入分析 让你对手机从按开机键到正常工作有深入的认识
  • 高通Camera整体框架

    千次阅读 2017-11-07 14:33:08
    本文档主要讲解高通Camera整体框架。 部分内容或参考资料可参考个人博客android开发栏目:http://blog.sina.com.cn/betterforlife  2. 高通Camera框架简介 总体框图如下: 下面简要走一下流程,不...

    1.    Introduction

    本文档主要讲解高通Camera整体框架。

    部分内容或参考资料可参考个人博客android开发栏目:http://blog.sina.com.cn/betterforlife 

    2.   高通Camera框架简介

    总体框图如下:

    下面简要走一下流程,不涉及具体代码:

    1、初始化CameraService

    在frameworks/av/media/mediaserver/Main_mediaserver.cpp中会对CameraService进行初始化:

    CameraService::instantiate();

    CameraService的父类BinderService定义了instantiate()函数:

    static void instantiate() { publish(); }

    CameraService的启动发生在init.rc中:

    service media /system/bin/mediaserver

    class main

    user media

    group audio camerainet net_bt net_bt_admin net_bw_acct drmrpc

    在CameraService初始化过程会从hal层获取一些基本信息,如支持的最大camera数目,如下图所示:

    2、连接CameraService

    如下图所示:

    2.1 Hal 1.0版本框架分析

    以设置camera sharpness(锐度)参数为例:

    数据流app parameter->java interface->jni->cameraclient->binder->camera service->hal->daemon->kernel

        如下图所示:

     

    2.2 Hal v3与v1区别与过渡

    2.2.1 简介

    在Android 5.0上,Google正式的将Camera HAL 3.0作为一个标准配置进行了发行,当然Camera HALV1也是作为兼容标准可用。

    HAL V3与V1本质区别是把帧的参数和帧的图像数据绑定到了一起,比如V1的时候一张preview上来的YUV帧,APP是不知道这个 YUV帧采用的Gain和曝光时间究竟是多少,但是在V3

    里面,每一帧都有一个数据结构来描述,其中包括了帧的参数和帧的数据,当APP发送一个request的时候是需要指定使用什么样的参数,到request返回的时候,返回数据中就有图像数据和相关的参数配置。

    2.2.2 HAL 1.0参数设置

    A、V1增加设定参数:增加OIS光学防抖参数设置(ois参数一般不作为设置参数,在本文档仅作实验测试),仅作流程分析对比。

    1)  添加接口函数,参考public void setSaturation(int saturation)设置

    在code/frameworks/base/core/java/android/hardware/Camera.java文件增加接口:

            publicvoid setOis(int saturation){

                  …………

                 set(KEY_QC_OIS, String.valueOf(OIS));

    }

    2)  App设置参数调用,假设设置ois值为1

    参考packages/apps/SnapdragonCamera/src/com/android/camera/PhotoModule.java

    mParameters.setSaturation(saturation);函数调用;

    mParameters.setOis(ois);

    由于HAL V1参数传递是通过字符串来完成的,最后传递到HAL层的字符串里面会有“ois=1”,在HAL层进行解析。

       B、Hal层相关修改:

    1、    添加相关定义

    1.1、 文件:hardware/qcom/camera/QCamera2/HAL/QCameraParameters.h

         static const char KEY_QC_SCE_FACTOR_STEP[];

    +    static const char KEY_QC_OIS[];

         staticconst char KEY_QC_HISTOGRAM[] ;

     

         int32_tsetSharpness(const QCameraParameters& );

    +    int32_t setOis(const QCameraParameters&);

         int32_tsetSaturation(const QCameraParameters& );

     

         int32_tsetSharpness(int sharpness);

    +    int32_t setOis(int ois);

         int32_tsetSaturation(int saturation);

    1.2、 文件:hardware/qcom/camera/QCamera2/stack/common/cam_types.h

                typedef enum {

                    CAM_INTF_PARM_FLASH_BRACKETING,

                    CAM_INTF_PARM_GET_IMG_PROP,

     

                        CAM_INTF_PARM_MAX

    +    CAM_INTF_PARM_OIS

                }cam_intf_parm_type_t;

    1.3、 文件:hardware/qcom/camera/QCamera2/stack/common/cam_intf.h

    typedefstruct{

         cam_af_bracketing_t  mtf_af_bracketing_parm;

         /* Sensor type information */

         cam_sensor_type_t sensor_type;

    +    /*ois default value*/

    +   int32_t ois_default_value;

     } cam_capability_t;

    2、    添加相关设置

    文件:hardware/qcom/camera/QCamera2/HAL/QCameraParameters.cpp

    const charQCameraParameters::KEY_QC_SCE_FACTOR_STEP[] = "sce-factor-step";

    +const char QCameraParameters::KEY_QC_OIS[] = "ois";

     

    //open camera时OIS默认值,该值在vendor中设置

    int32_t QCameraParameters::initDefaultParameters()

    {

           ………

    +   // Set Ois

    +   setOis(m_pCapability->ois_default_value);

    +   ALOGE("the default_ois = %d",m_pCapability->ois_default_value);

         // Set Contrast

        set(KEY_QC_MIN_CONTRAST,m_pCapability->contrast_ctrl.min_value);

        set(KEY_QC_MAX_CONTRAST, m_pCapability->contrast_ctrl.max_value);

        ………

    }

     

    +int32_t QCameraParameters::setOis(constQCameraParameters& params)

    +{

    +    int ois = params.getInt(KEY_QC_OIS);

    +    int prev_ois = getInt(KEY_QC_OIS);

    +    if(params.get(KEY_QC_OIS) == NULL) {

    +       CDBG_HIGH("%s: Ois not set by App",__func__);

    +       return NO_ERROR;

    +    }

    +    ALOGE("haljay ois=%dprev_ois=%d",ois, prev_ois);

    +    if (prev_ois !=  ois) {

    +        if((ois >= 0) && (ois <=2)) {

    +            CDBG(" new ois value : %d", ois);

    +            return setOis(ois);

    +        } else {

    +            ALOGE("%s: invalid value%d",__func__, ois);

    +            return BAD_VALUE;

    +        }

    +    } else {

    +        ALOGE("haljay no valuechange");

    +        CDBG("%s: No value change inois", __func__);

    +        return NO_ERROR;

    +    }

    +}

     

    +int32_t QCameraParameters::setOis(intois)

    +{

    +    charval[16];

    +   sprintf(val, "%d", ois);

    +   updateParamEntry(KEY_QC_OIS, val);

    +   CDBG("%s: Setting ois %s", __func__, val);

    +    ALOGE("haljay%s set ois=%s OIS=%d", __func__, val, CAM_INTF_PARM_OIS);

    +    int32_tvalue = ois;

    +    returnAddSetParmEntryToBatch(m_pParamBuf,

    +                                 CAM_INTF_PARM_OIS,

    +                                 sizeof(value),

    +                                  &value);

    +}

     

    函数int32_tQCameraParameters::updateParameters添加setOis

         if ((rc =setBrightness(params)))                  final_rc = rc;

         if ((rc =setZoom(params)))                        final_rc = rc;

         if ((rc = setSharpness(params)))                    final_rc = rc;

    +    if ((rc = setOis(params)))                          final_rc = rc;

         if ((rc =setSaturation(params)))                   final_rc = rc;

       C、Vendor层相关修改:

    1、    添加相关定义

    1.1、 文件:kernel/include/media/msm_cam_sensor.h

    enum msm_actuator_cfg_type_t {

      CFG_SET_POSITION,

      CFG_ACTUATOR_POWERDOWN,

      CFG_ACTUATOR_POWERUP,

    + CFG_ACTUATOR_OIS,

     };

    struct msm_actuator_cfg_data {

          struct msm_actuator_get_info_t get_info;

          struct msm_actuator_set_position_t setpos;

          enum af_camera_name cam_name;

    +      void*setting;

      } cfg;

    1.2、 文件:vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/mct/pipeline/mct_pipeline.c

          在函数boolean mct_pipeline_populate_query_cap_buffer(mct_pipeline_t*pipeline)中添加:

                    hal_data->sharpness_ctrl.min_value= 0;

                    hal_data->sharpness_ctrl.step= 6;

     

    +  hal_data->ois_default_value= 1;

                    hal_data->contrast_ctrl.def_value= 5;

                    hal_data->contrast_ctrl.max_value= 10;

    1.3、 文件:vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/sensors/module/sensor_common.h

    typedefenum {

       /* End of CSID enums*/

       /* video hdr enums */

       SENSOR_SET_AWB_UPDATE, /*sensor_set_awb_data_t * */

    + ACTUATOR_SET_OIS

     } sensor_submodule_event_type_t;

    2、    添加相关设置

    文件:vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/sensors/module/module_sensor.c

    2.1、 获取hal层参数

    在函数static boolean module_sensor_event_control_set_parm中增加:

    +  case CAM_INTF_PARM_OIS:{

    +    if (!event_control->parm_data) {

    +        SERR("failed parm_dataNULL");

    +        ret = FALSE;

    +        break;

    +      }

    +    module_sensor_params_t        *ois_module_params = NULL;

    +    ois_module_params =s_bundle->module_sensor_params[SUB_MODULE_ACTUATOR];

    +    if (ois_module_params->func_tbl.process != NULL) {

    +      rc =ois_module_params->func_tbl.process(

    +        ois_module_params->sub_module_private,

    +        ACTUATOR_SET_OIS,event_control->parm_data);

    +    }

    +    if (rc < 0) {

    +      SERR("failed");

    +      ret = FALSE;

    +    }

    +     break;

    +  }

    文件:vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/sensors/actuators/actuator.c

    2.2、在函数int32_t actuator_process中增加:

           case ACTUATOR_SET_POSITION:

                rc =actuator_set_position(actuator_ctrl, data);

                break;

    +  /*set ois*/

    +   case ACTUATOR_SET_OIS:

    +   rc = actuator_set_ois(actuator_ctrl,data);

    +   break;

    2.3、将参数通过ioctl方法下至内核

            +staticint actuator_set_ois(void *ptr, void*data) {

    +  int rc = 0;

    +  int32_t *ois_level = (int32_t*)data;

    +  actuator_data_t *ois_actuator_ptr =(actuator_data_t *)ptr;

    +  struct msm_actuator_cfg_data cfg;

    +  if (ois_actuator_ptr->fd <= 0)

    +    return -EINVAL;

    +  cfg.cfgtype = CFG_ACTUATOR_OIS;

    +  cfg.cfg.setting = ois_level;

    +  /* Invoke the IOCTL to set the ois */

    +  rc = ioctl(ois_actuator_ptr->fd,VIDIOC_MSM_ACTUATOR_CFG, &cfg);

    +  if (rc < 0) {

    +    SERR("failed-errno:%s!!!",strerror(errno));

    +  }

    +  return rc;

    +}

    2.2.3 HAL 3.0参数设置

    V3增加设定参数:对于HAL V3,从framework到HAL层的参数传递是通过metadata方式完成的,即每一个设置现在都变成了一个参数对,例如:设置AE mode为auto,V1版本参数可能是“AE mode=auto”字符串;V3版本假设AE mode功能序号是10,参数auto为1,传到HAL层的参数类似(10,1)这样的参数对,在HAL层需要通过10这个参数,获取设置值1;对于在V1版本对ois的设置需要在V3中添加新的处理来实现。

    如何在V3中定义自己特定参数(如ois设置):谷歌考虑到厂商可能需要定义自己特定的参数,因此在metadata里面定义了vendor tag的数据范围来让vendor可以添加自己特定的操作,如ois设置,可以通过vendor tag来实现。

    步骤

    1)  定义自己的vendor tag序号值

    vim system/media/camera/include/system/camera_metadata_tags.h

              typedefenum camera_metadata_tag {

                 ANDROID_SYNC_START,

                 ANDROID_SYNC_MAX_LATENCY,

                 ANDROID_SYNC_END,

    + VENDOR_TAG_OIS =

    + VENDOR_SECTION_START,  //由于参数少,没有重新定义section,使用默认section 0x8000

                    ......................

               } camera_metadata_tag_t;

    2)  所需支持配置

    Vendor Tag都需要在VENDOR_SECTION_START后面添加,此处添加了VENDOR_TAG_OIS。在HAL里面如果需要处理 Vendor Tag,一个是需要camera module的版本是2.2以上,因为Google在这个版本之后才稳定支持vendor tag。一个是需要vendor tag的的operations函数

    vim ./hardware/libhardware/modules/camera/CameraHAL.cpp +186

    版本和操作函数如下图所示:

    vim ./hardware/qcom/camera/QCamera2/HAL3/QCamera3VendorTags.cpp +184

     

               get_tag_count:返回所有vendor tag的个数;

    get_all_tags:把所有vendor tag依次放在service传下来的uint32_t * tag_array里面,这样上层就知道每一个tag对应的序号值了;

    get_section_name:获取vendor tag的section对应的section名称,比如可以把某几个vendor tag放在一个section里面,其它的放在其它的section里面。查看metadata.h里面的定义很好理解,如果你想增加自己的section,就可以在VENDOR_SECTION = 0x8000后面添加自己的section。由于本次只设置ois参数,没有分类的必要,所以就使用默认的VENDOR_SECTION.

    vim system/media/camera/include/system/camera_metadata_tags.h

     

    get_tag_name:用于获取每一个vendor tag的名称,比如我们这个地方返回“VENDOR_TAG_OIS”就可以了;

    get_tag_type:这个函数返回vendor tag对应的设置数据的类型,可以用TYPE_INT32, TYPE_FLOAT等多种数据格式,取决于需求,我们ois参数只要是INT32就行了。

    3)  加载vendor tag

    这样CameraService.cpp在启动的时候就会调用onFirstRef里面的下面代码来加载我们所写的vendor tag

    if (mModule->common.module_api_version >= CAMERA_MODULE_API_VERSION_2_2) {

                           setUpVendorTags();

            }

    4)  V1到V3参数转化

    由于我们这个ois设置是在V1的APP里面使用,因此首先需要实现V1和V3参数的转换,Google在services/camera/libcameraservice/api1/client2/Parameters.cpp实现相应的转换,因此首先需要在如下函数里面获取V1 APP传下来的OIS的值,其中的paramString就是V1的参数设置的字符串

    status_t Parameters::set(const String8& paramString)

    {

        …………

        mOis = newParams.get(CameraParameters::KEY_OIS);

        …………

    }

    由于V3的参数都是在request frame的时候一起下发的,因此需要讲mSaturation的值在Parameters::updateRequest(CameraMetadata *request)里面下发到HAL,即

    +  res = request->update(VENDOR_TAG_SATURATION,&mOis, 1);

     这样就将saturation的vendor tag和其设置值发送到了HAL V3。

    5)  HAL V3获取设置的OIS参数

    使用CameraMetadata::find(uint32_ttag)函数来获取参数:

    oisMapMode =                frame_settings.find(VENDOR_TAG_OIS).data.i32[0];

    通过ADD_SET_PARAM_ENTRY_TO_BATCH函数将设置下到vendor层:

    ADD_SET_PARAM_ENTRY_TO_BATCH(hal_metadata, CAM_INTF_META_OIS,

    oisMapMode);

     

    2.3 Hal 3.0版本框架分析

    2.3.1 Frameworks层总体框架

    Frameworks之CameraService部分架构图如下图所示:

    v3将更多的工作集中在了Framework去完成,将更多的控制权掌握在自己的手里,从而与HAL的交互的数据信息更少,也进一步减轻了一些在旧版本中HAL层所需要做的事情,也更加模块化。

    Camera2Client建立与初始化过程如下图所示:

     

    由上图可知建立好Camera2Client后会进行initialize操作,完成各个处理模块的创建:

    代码目录:frameworks/av/services/camera/libcameraservice/api1/Camera2Client.cpp

    status_tCamera2Client::initialize(CameraModule *module)

    {

        ………

        mStreamingProcessor = new StreamingProcessor(this);//preview和recorder

        threadName =String8::format(C2-%d-StreamProc, mCameraId);

       mStreamingProcessor->run(threadName.string());//预览与录像

     

        mFrameProcessor = new FrameProcessor(mDevice, this);// 3A

        threadName = String8::format(C2-%d-FrameProc,mCameraId);

       mFrameProcessor->run(threadName.string()); //3A

     

        mCaptureSequencer = new CaptureSequencer(this);

        threadName =String8::format(C2-%d-CaptureSeq, mCameraId);

       mCaptureSequencer->run(threadName.string());//录像,拍照

     

       mJpegProcessor = new JpegProcessor(this,mCaptureSequencer);

        threadName =String8::format(C2-%d-JpegProc, mCameraId);

       mJpegProcessor->run(threadName.string());

    ………

        mCallbackProcessor = new CallbackProcessor(this);//回调处理

        threadName = String8::format(C2-%d-CallbkProc,mCameraId);

       mCallbackProcessor->run(threadName.string());

        ………

    }

    依次分别创建了:

    1、StreamingProcessor并启动一个它所属的thread,该模块主要负责处理previews与record两种视频流的处理,用于从hal层获取原始的视频数据

    2、FrameProcessor并启动一个thread,该模块专门用于处理回调回来的每一帧的3A等信息,即每一帧视频除去原始视频数据外,还应该有其他附加的数据信息,如3A值。

    3、CaptureSequencer并启动一个thread,该模块需要和其他模块配合使用,主要用于向APP层告知capture到的picture。

    4、JpegProcessor并启动一个thread,该模块和streamprocessor类似,他启动一个拍照流,一般用于从HAL层获取jpeg编码后的图像照片数据。

    5、另外ZslProcessor模块称之为0秒快拍,其本质是直接从原始的Preview流中获取预存着的最近的几帧,直接编码后返回给APP,而不 需要再经过take picture去请求获取jpeg数据。0秒快拍技术得意于当下处理器CSI2 MIPI性能的提升以及Sensor支持全像素高帧率的实时输出。一般手机拍照在按下快门后都会有一定的延时,是因为需要切换底层Camera以及ISP 等的工作模式,并重新设置参数以及重新对焦等等,都需要花一定时间后才抓取一帧用于编码为jpeg图像。

    以上5个模块整合在一起基本上实现了Camera应用开发所需的基本业务功能。

    2.3.2 Preview模式下的控制流

    代码目录,直接以Camera2Client::startPreview()作为入口来分析整个Framework层中Preview相关的数据流

       1、调用Camera2Client::startPreview函数

    代码目录-1:frameworks/av/services/camera/libcameraservice/api1/Camera2Client.cpp

    status_t Camera2Client::startPreview() {

        ATRACE_CALL();

        ALOGV(%s: E, __FUNCTION__);

        Mutex::Autolockicl(mBinderSerializationLock);

        status_t res;

        if ( (res = checkPid(__FUNCTION__) ) != OK)return res;

        SharedParameters::Lock l(mParameters);

        return startPreviewL(l.mParameters,false);

    }

    startPreview通过startPreviewL提取参数后真正的开始执行Preview相关的控制流。该函数看上去内容虽然较多,但基本采用了同一种处理方式:

    2、    调用Camera2Client::startPreviewL函数

    代码目录-1:frameworks/av/services/camera/libcameraservice/api1/Camera2Client.cpp

    后面会详细介绍2.1-2.6粗体标注部分;

    status_tCamera2Client::startPreviewL(Parameters &params, bool restart){

    ......

    //获取上一层Preview stream id

    intlastPreviewStreamId = mStreamingProcessor->getPreviewStreamId();

    //2.1创建camera3device stream, Camera3OutputStream

        res =mStreamingProcessor->updatePreviewStream(params);

    .....

    intlastJpegStreamId = mJpegProcessor->getStreamId();

    //2.2预览启动时就建立一个jpeg的outstream

    res= updateProcessorStream(mJpegProcessor,params);

    .....

    //2.3回调处理建立一个Camera3outputstream

    res= mCallbackProcessor->updateStream(params);

    ………

    //2.4

    outputStreams.push(getCallbackStreamId());

    ......

    outputStreams.push(getPreviewStreamId());//预览stream

    ......

    if(!params.recordingHint) {

       if (!restart) {

          //2.5 request处理,更新了mPreviewrequest

          res = mStreamingProcessor->updatePreviewRequest(params); 

    ......

        }

            //2.6

            res = mStreamingProcessor->startStream(StreamingProcessor::PREVIEW,

                    outputStreams);//启动stream,传入outputStreams即stream 的id

        }

    ......

    }

    2.1、调用mStreamingProcessor->updatePreviewStream函数

       代码目录-2:

        frameworks/av/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp

    status_t StreamingProcessor::updatePreviewStream (constParameters &params) {

    ......

        sp<cameradevicebase> device =mDevice.promote();//Camera3Device

    ......

        if (mPreviewStreamId != NO_STREAM) {

            // Check if stream parameters have tochange

           uint32_t currentWidth, currentHeight;

            res =device->getStreamInfo(mPreviewStreamId,

                    &tWidth, &tHeight, 0);

        ......

            if (currentWidth !=(uint32_t)params.previewWidth ||

                    currentHeight != (uint32_t)params.previewHeight){

            ......    

                res =device->waitUntilDrained();

            ......   

                res =device->deleteStream(mPreviewStreamId);

                ......

                mPreviewStreamId = NO_STREAM;

            }

        }

    if (mPreviewStreamId == NO_STREAM) {//首次create stream

            //创建一个Camera3OutputStream

            res = device->createStream(mPreviewWindow,

                    params.previewWidth,params.previewHeight,

                   CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, &mPreviewStreamId);

            ......

            }

        }

        res =device->setStreamTransform(mPreviewStreamId,

                params.previewTransform);

        ......

    }

    该函数首先是查看当前StreamingProcessor模块下是否存在Stream,没有的话,则交由Camera3Device创建一个 stream。显然,一个StreamingProcessor只能拥有一个PreviewStream,而一个Camera3Device显然控制着所 有的Stream。

    注意:在Camera2Client中,5大模块的数据交互均以stream作为基础。

    下面我们来重点关注Camera3Device的接口createStream,他是5个模块创建stream的基础:

          代码目录-3:

           frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp

    status_tCamera3Device::createStream(spconsumer,

            uint32_t width, uint32_t height, intformat, int *id) {

        ......

        assert(mStatus != STATUS_ACTIVE);

        sp<camera3outputstream> newStream;

        if (format == HAL_PIXEL_FORMAT_BLOB) {//图片

            ssize_t jpegBufferSize =getJpegBufferSize(width, height);

           ......

            newStream = new Camera3OutputStream(mNextStreamId, consumer,

                    width, height, jpegBufferSize,format);//jpeg 缓存的大小

        } else {

            newStream = new Camera3OutputStream(mNextStreamId, consumer,

                    width, height, format);//Camera3OutputStream

        }

    newStream->setStatusTracker(mStatusTracker);

    //一个streamid与Camera3OutputStream绑定

        res = mOutputStreams.add(mNextStreamId,newStream);

        ......

        *id = mNextStreamId++;//至少一个previewstream 一般还有CallbackStream

        mNeedConfig = true;

        // Continue captures if active at start

        if (wasActive) {

            ALOGV(%s: Restarting activity toreconfigure streams, __FUNCTION__);

            res = configureStreamsLocked();

           ......

            internalResumeLocked();

        }

        ALOGV(Camera %d: Created new stream, mId);

        return OK;

    }

    该函数重点是关注一个new Camera3OutputStream,在Camera3Device主要存在Camera3OutputStream和Camera3InputStream,两种stream,前者主要作为HAL的输出,是请求HAL填充数据的OutPutStream,后者是由Framework将Stream进行填充。无论是Preview、record还是capture均是从HAL层获取数据,故都会以OutPutStream的形式存在,是我们关注的重点,后面在描述Preview的数据流时还会进一步的阐述。

    每当创建一个OutPutStream后,相关的stream信息被push维护在一个mOutputStreams的KeyedVector表中,分别是该stream在Camera3Device中创建时的ID以及Camera3OutputStream的sp值。同时对mNextStreamId记录下一个Stream的ID号。

    上述过程完成StreamingProcessor模块中一个PreviewStream的创建,其中Camera3OutputStream创建时的ID值被返回记录作为mPreviewStreamId的值,此外每个Stream都会有一个对应的ANativeWindow,这里称之为Consumer。

    2.2、调用updateProcessorStream(mJpegProcessor, params)函数

        代码目录-2:

        frameworks/av/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp

           status_tCamera2Client::updateProcessorStream(sp<processort> processor,

                                                 camera2::Parameters params) {

                //No default template arguments until C++11, so we need this overload

                 return updateProcessorStream<processort,processort::updatestream="">(

                    processor,params);

    }

    template <typename const="" parameters=""status_t="">

    status_tCamera2Client::updateProcessorStream(sp<processort> processor,

                                                 Parameters params) {

                status_tres;

                //Get raw pointer since sp<t> doesn't have operator->*

                ProcessorT*processorPtr = processor.get();

                res= (processorPtr->*updateStreamF)(params);

    .......

    }

    该模板函数处理过程最终通过非显示实例到显示实例调用JpegProcessor::updateStream,该函数处理的逻辑基本和Callback 模块处理一致,创建的一个OutPutStream和CaptureWindow相互绑定,同时Stream的ID保存在 mCaptureStreamId中。

    此外需要说明一点:

    在preview模式下,就去创建一个jpeg处理的stream,目的在于启动takepicture时,可以更快的进行capture操作,是通过牺牲内存空间来提升效率。

    2.3、调用mCallbackProcessor->updateStream函数

    代码目录-2:

        frameworks/av/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp

    对比StreamingProcessor模块创建previewstream的过程,很容易定位到Callback模块是需要建立一个 callback流,同样需要创建一个Camera3OutputStream来接收HAL返回的每一帧帧数据,是否需要callback可以通过 callbackenable来控制。一般但预览阶段可能不需要回调每一帧的数据到APP,但涉及到相应的其他业务如视频处理时,就需要进行 callback的enable。

    status_t CallbackProcessor::updateStream(constParameters &params) {

        ………

        sp<cameradevicebase> device =mDevice.promote();

        ………

        // If possible, use the flexible YUV format

        int32_t callbackFormat =params.previewFormat;

        if (mCallbackToApp) {

            // TODO: etalvala: This should use theflexible YUV format as well, but

            // need to reconcile HAL2/HAL3requirements.

            callbackFormat = HAL_PIXEL_FORMAT_YV12;

        } else if(params.fastInfo.useFlexibleYuv&&

                (params.previewFormat ==HAL_PIXEL_FORMAT_YCrCb_420_SP ||

                 params.previewFormat ==HAL_PIXEL_FORMAT_YV12) ) {

            callbackFormat =HAL_PIXEL_FORMAT_YCbCr_420_888;

        }

        if (!mCallbackToApp &&mCallbackConsumer == 0) {

            // Create CPU buffer queue endpoint,since app hasn't given us one

            // Make it async to avoid disconnectdeadlocks

            sp<igraphicbufferproducer>producer;

            sp<igraphicbufferconsumer>consumer;

           //BufferQueueProducer与BufferQueueConsumer

            BufferQueue::createBufferQueue(&producer, &consumer);

            mCallbackConsumer = new CpuConsumer(consumer,kCallbackHeapCount);

    //当前CallbackProcessor继承于CpuConsumer::FrameAvailableListener

            mCallbackConsumer->setFrameAvailableListener(this);

           mCallbackConsumer->setName(String8(Camera2Client::CallbackConsumer));

    //用于queue操作,这里直接进行本地的buffer操作

            mCallbackWindow = new Surface(producer);

        }

        if (mCallbackStreamId != NO_STREAM) {

            // Check if stream parameters have tochange

            uint32_t currentWidth, currentHeight,currentFormat;

            res =device->getStreamInfo(mCallbackStreamId,

                    &tWidth, &tHeight, &tFormat);

           ………

        }

        if (mCallbackStreamId == NO_STREAM) {

            ALOGV(Creating callback stream: %d x%d, format 0x%x, API format 0x%x,

                    params.previewWidth,params.previewHeight,

                    callbackFormat,params.previewFormat);

            res = device->createStream(mCallbackWindow,

                   params.previewWidth, params.previewHeight,

                    callbackFormat,&mCallbackStreamId);//Creating callback stream

            ………

        }

        return OK;

    }

    2.4、整合startPreviewL中所有的stream 到Vector outputStreams

    outputStreams.push(getPreviewStreamId());//预览stream

    outputStreams.push(getCallbackStreamId())//Callback stream

    目前一次Preview构建的stream数目至少为两个。

    2.5、调用mStreamingProcessor->updatePreviewRequest函数

    代码目录-2:

        frameworks/av/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp

    在创建好多路stream后,由StreamingProcessor模块来将所有的stream信息交由Camera3Device去打包成Request请求。

    注意:

    Camera HAL2/3的特点是:将所有stream的请求都转化为几个典型的Request请求,而这些Request需要由HAL去解析,进而处理所需的业务,这也是Camera3数据处理复杂化的原因所在。

    status_t StreamingProcessor::updatePreviewRequest(constParameters &params) {

        ………

        if (mPreviewRequest.entryCount()== 0) {

            sp<camera2client> client =mClient.promote();

            if (client == 0) {

                ALOGE(%s: Camera %d: Client doesnot exist, __FUNCTION__, mId);

                return INVALID_OPERATION;

            }

            // UseCAMERA3_TEMPLATE_ZERO_SHUTTER_LAG for ZSL streaming case.

            if (client->getCameraDeviceVersion()>= CAMERA_DEVICE_API_VERSION_3_0) {

                if (params.zslMode &&!params.recordingHint) {

                    res = device->createDefaultRequest(CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG,

                            &mPreviewRequest);

                } else {

                    res = device->createDefaultRequest(CAMERA3_TEMPLATE_PREVIEW,

                            &mPreviewRequest);

                }

            } else {

              //创建一个Preview相关的request,由底层的hal来完成default创建

                res =device->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,

                        &mPreviewRequest);

            ………

    }

    //根据参数来更新CameraMetadatarequest,用于app设置参数,如antibanding设置

    res= params.updateRequest(&mPreviewRequest);  

        ………

        res = mPreviewRequest.update(ANDROID_REQUEST_ID,

                &mPreviewRequestId,1);//mPreviewRequest的ANDROID_REQUEST_ID

        ………

    }

    a mPreviewRequest是一个CameraMetadata类型数据,用于封装当前previewRequest;

    b 调用device->createDefaultRequest(CAMERA3_TEMPLATE_PREVIEW,&mPreviewRequest)函数

    代码目录-3:

    frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp

    status_t Camera3Device::createDefaultRequest(int templateId, CameraMetadata*request) {

        ………

    const camera_metadata_t *rawRequest;

     ATRACE_BEGIN(camera3->construct_default_request_settings);

     rawRequest = mHal3Device->ops->construct_default_request_settings(

        mHal3Device, templateId);

     ATRACE_END();

     if (rawRequest == NULL) {

        SET_ERR_L(HAL is unable to construct default settings for template %d,

                 templateId);

        return DEAD_OBJECT;

     }

     *request = rawRequest;

     mRequestTemplateCache[templateId] =rawRequest;

    ………

    }

    最终是由hal来实现构建一个rawrequest,即对于Preview,而言是构建了一个CAMERA3_TEMPLATE_PREVIEW类型的 Request。其实对HAL而言,rawrequest本质是用于操作一个camera_metadata_t类型的数据:

    struct camera_metadata {

        metadata_size_t          size;

        uint32_t                 version;

        uint32_t                 flags;

        metadata_size_t          entry_count;

        metadata_size_t          entry_capacity;

        metadata_uptrdiff_t      entries_start; // Offset fromcamera_metadata

        metadata_size_t          data_count;

        metadata_size_t          data_capacity;

        metadata_uptrdiff_t      data_start; // Offset fromcamera_metadata

        uint8_t                 reserved[];

    };

    该数据结构可以存储多种数据,且可以根据entry tag的不同类型来存储数据,同时数据量的大小也可以自动调整;

    c mPreviewRequest.update(ANDROID_REQUEST_ID,&mPreviewRequestId,1)

    将当前的PreviewRequest相应的ID保存到camera metadata。

    2.6、调用mStreamingProcessor->startStream函数启动整个预览的stream流

    代码目录-2:

      frameworks/av/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp

    该函数的处理过程较为复杂,可以说是整个Preview正常工作的核心控制:

    tatus_tStreamingProcessor::startStream(StreamType type,

            const Vector<int32_t>&outputStreams) {

    .....

    CameraMetadata&request = (type == PREVIEW) ?

                mPreviewRequest :mRecordingRequest;//取preview的CameraMetadata request

    //CameraMetadata中添加outputStreams

    res = request.update(ANDROID_REQUEST_OUTPUT_STREAMS,outputStreams);

    res= device->setStreamingRequest(request);//向hal发送request

    .....

    }

    该函数首先是根据当前工作模式来确定StreamingProcessor需要处理的Request,该模块负责Preview和Record两个Request。

    以PreviewRequest就是之前createDefaultRequest构建的,这里先是将这个Request所需要操作的Outputstream打包到一个tag叫ANDROID_REQUEST_OUTPUT_STREAMS的entry当中。

          a 调用setStreamingRequest函数

          代码目录:

           frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp

    真正的请求Camera3Device去处理这个带有多路stream的PreviewRequest。

    a.1 status_t Camera3Device::setStreamingRequest(constCameraMetadata &request,

                                               int64_t* /*lastFrameNumber*/) {

        ATRACE_CALL();

        List<constcamerametadata=""> requests;

        requests.push_back(request);

        return setStreamingRequestList(requests,/*lastFrameNumber*/NULL);

    }

    该函数将mPreviewRequest push到一个list,调用setStreamingRequestList

    a.2 status_t Camera3Device::setStreamingRequestList(constList<const camerametadata=""> &requests, int64_t*lastFrameNumber) {

            ATRACE_CALL();

            returnsubmitRequestsHelper(requests,/*repeating*/true, lastFrameNumber);

    }

    a.3 status_t Camera3Device::submitRequestsHelper(

           const List<const camerametadata=""> &requests, boolrepeating,

           /*out*/

           int64_t *lastFrameNumber) {//repeating = 1;lastFrameNumber = NULL

       ………

       status_t res = checkStatusOkToCaptureLocked();

       ………

        RequestList requestList;

    //返回的是CaptureRequest RequestList

    res = convertMetadataListToRequestListLocked(requests,/*out*/&requestList);   

    ………

       if (repeating) {

    //重复的request存入到RequestThread

    res = mRequestThread->setRepeatingRequests(requestList, lastFrameNumber); 

    }  else {

    //capture模式,拍照单词

           res = mRequestThread->queueRequestList(requestList,lastFrameNumber);  

     }

       if (res == OK) {

           waitUntilStateThenRelock(/*active*/true, kActiveTimeout);

           if (res != OK) {

                SET_ERR_L(Can't transition toactive in %f seconds!,

                        kActiveTimeout/1e9);

           }

           ALOGV(Camera %d: Capture request % PRId32  enqueued, mId,

                 (*(requestList.begin()))->mResultExtras.requestId);

       } else {

           CLOGE(Cannot queue request. Impossible.);

           return BAD_VALUE;

       }

       return res;

    }

    a.4 convertMetadataListToRequestListLocked

    这个函数是需要将Requestlist中保存的CameraMetadata数据转换为List;

    status_tCamera3Device::convertMetadataListToRequestListLocked(

    const List<constcamerametadata=""> &metadataList, RequestList *requestList) {

       ………

       for (List<const camerametadata="">::const_iterator it =metadataList.begin();//CameraMetadata, mPreviewRequest

                it != metadataList.end(); ++it) {

            //新建CaptureRequest由CameraMetadata转化而来

           sp<capturerequest>newRequest = setUpRequestLocked(*it);       

            ………

           // Setup burst Id and request Id

           newRequest->mResultExtras.burstId = burstId++;

           if (it->exists(ANDROID_REQUEST_ID)) {

                if(it->find(ANDROID_REQUEST_ID).count == 0) {

                    CLOGE(RequestID entry exists;but must not be empty in metadata);

                    return BAD_VALUE;

                }

            //设置该request对应的id

            newRequest->mResultExtras.requestId =it->find(ANDROID_REQUEST_ID).data.i32[0];

           } else {

                CLOGE(RequestID does not exist inmetadata);

                return BAD_VALUE;

           }

           requestList->push_back(newRequest);

            ………

       }

       return OK;

    }

    这里是对List进行迭代解析处理,如当前模式下仅存在PreviewRequest这一个CameraMetadata,通过setUpRequestLocked将其转换为一个CaptureRequest。

            a.5 setUpRequestLocked

               sp<camera3device::capturerequest>Camera3Device::setUpRequestLocked(

                    constCameraMetadata &request) {//mPreviewRequest

                    status_tres;

                    if(mStatus == STATUS_UNCONFIGURED || mNeedConfig) {

                    res= configureStreamsLocked();

                    ......

        //CameraMetadata转为CaptureRequest,包含mOutputStreams

       </strong>sp<capturerequest> newRequest = createCaptureRequest(request);

                    return newRequest;

    }

    configureStreamsLocked函数主要是将Camera3Device侧建立的所有Stream包括Output与InPut格式 的交由HAL3层的Device去实现处理的核心接口是configure_streamsregister_stream_buffer

    createCaptureRequest函数是将一个CameraMetadata格式的数据如PreviewRequest转换为一个CaptureRequest:

               a.6 sp<camera3device::capturerequest>Camera3Device::createCaptureRequest(

                    constCameraMetadata &request) {//mPreviewRequest

                    ………

                    sp<capturerequest>newRequest = new CaptureRequest;

                    newRequest->mSettings= request;//CameraMetadata

                    camera_metadata_entry_tinputStreams =

                        newRequest->mSettings.find(ANDROID_REQUEST_INPUT_STREAMS);

                    if(inputStreams.count > 0) {

                        if(mInputStream == NULL ||

                            mInputStream->getId() != inputStreams.data.i32[0]) {

                            CLOGE(Requestreferences unknown input stream %d,

                            inputStreams.data.u8[0]);

                            returnNULL;

                        }

                    ………

                        newRequest->mInputStream= mInputStream;

                        newRequest->mSettings.erase(ANDROID_REQUEST_INPUT_STREAMS);

                    }

    //读取存储在CameraMetadata的stream id信息

                    camera_metadata_entry_tstreams =

                        newRequest->mSettings.find(ANDROID_REQUEST_OUTPUT_STREAMS);

                        ………

    for (size_t i = 0; i < streams.count; i++) {

                        //Camera3OutputStream的id在mOutputStreams中

                        intidx = mOutputStreams.indexOfKey(streams.data.i32[i]);

                        ………

                     }

                    //返回的是Camera3OutputStream,preview/callback等stream

                    sp<camera3outputstreaminterface>stream =

                         mOutputStreams.editValueAt(idx);

                    ………

    //Camera3OutputStream添加到CaptureRequest的mOutputStreams

                    newRequest->mOutputStreams.push(stream);

        }

                    newRequest->mSettings.erase(ANDROID_REQUEST_OUTPUT_STREAMS);

                    returnnewRequest;

    }

    该函数主要处理指定的这个CameraMetadata mPreviewRequest下对应所拥有的Output与Input Stream,对于Preview而言,至少存在OutPutStream包括一路StreamProcessor与一路可选的 CallbackProcessor。

    在构建这个PreviewRequest时,已经将ANDROID_REQUEST_OUTPUT_STREAMS这个Tag进行了初始化,相应的内容为Vector &outputStreams,包含着属于PreviewRequest这个Request所需要的输出stream的ID值,通过这个IDindex值,可以遍历到Camera3Device下所createstream创造的Camera3OutputStream,即说明不同类型的 Request在Camera3Device端存在多个Stream,而每次不同业务下所需要Request的对应的Stream又仅是其中的个别而已。

    idx = mOutputStreams.indexOfKey(streams.data.i32[i])是通过属于PreviewRequest中包含的一个 stream的ID值来查找到mOutputStreams这个KeyedVector中对应的标定值index。注意:两个索引值不一定是一致的。

    mOutputStreams.editValueAt(idx)是获取一个与该ID值(如Previewstream ID、CallbackStream ID等等)相对应的Camera3OutputStream。

    在找到了当前Request中所有的Camera3OutputStream后,将其维护在CaptureRequest中:

    class CaptureRequest : public LightRefBase<capturerequest> {

          public:

            CameraMetadata                      mSettings;

            sp<camera3::camera3stream>          mInputStream;

           Vector<sp<camera3::camera3outputstreaminterface> >

                                                mOutputStreams;

            CaptureResultExtras                 mResultExtras;

        };

    mSettings是保存CameraMetadata PreviewRequest,vectormOutPutStreams保存着当前Request提取出来的Camera3OutputStream,至此构建了一个CaptureRequest。

               回到a.4:convertMetadataListToRequestListLocked

    返回到convertMetadataListToRequestListLocked中,现在已经完成了一个CameraMetadata Request的处理,生产的是一个CaptureRequest。我们将这个ANDROID_REQUEST_ID的ID值,保留在newRequest->mResultExtras.requestId =it->find(ANDROID_REQUEST_ID).data.i32[0]。

    这个值在整个Camera3的架构中,仅存在3大种Request类型,说明了整个和HAL层交互的Request类型是不多的:

    预览RequestmPreviewRequest:mPreviewRequestId(Camera2Client::kPreviewRequestIdStart),

    拍照RequestmCaptureRequest:mCaptureId(Camera2Client::kCaptureRequestIdStart),

    录像RequestmRecordingRequest: mRecordingRequestId(Camera2Client::kRecordingRequestIdStart);

    staticconst int32_t kPreviewRequestIdStart = 10000000;

    staticconst int32_t kPreviewRequestIdEnd   =20000000;

    staticconst int32_t kRecordingRequestIdStart  =20000000;

    staticconst int32_t kRecordingRequestIdEnd    =30000000;

    staticconst int32_t kCaptureRequestIdStart = 30000000;

    staticconst int32_t kCaptureRequestIdEnd   =40000000;

               回到a.3:mRequestThread->setRepeatingRequests(requestList)

    对于Preview来说,一次Preview后底层硬件就该可以连续的工作,而不需要进行过多的切换,故Framework每次向HAL发送的Request均是一种repeat的操作模式,故调用了一个重复的RequestQueue来循环处理每次的Request。

    status_tCamera3Device::RequestThread::setRepeatingRequests(

            const RequestList &requests,

            /*out*/

            int64_t *lastFrameNumber) {

        Mutex::Autolock l(mRequestLock);

        if (lastFrameNumber != NULL) {//第一次进来为null

            *lastFrameNumber =mRepeatingLastFrameNumber;

        }

        mRepeatingRequests.clear();

        mRepeatingRequests.insert(mRepeatingRequests.begin(),

                requests.begin(), requests.end());

       unpauseForNewRequests();//signal request_thread in waitfornextrequest

        mRepeatingLastFrameNumber =NO_IN_FLIGHT_REPEATING_FRAMES;

        return OK;

    }

    将Preview线程提交的Request加入到mRepeatingRequests中后,唤醒RequestThread线程去处理当前新的Request。

    2.7、经过2.6步骤将开启RequestThread 请求处理线程

    RequestThread::threadLoop()函数主要用于响应并处理新加入到Request队列中的请求。

    代码目录-2:

    frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp

    boolCamera3Device::RequestThread::threadLoop(){

    ....

    //返回的是mRepeatingRequests,mPreviewRequest

     sp<capturerequest> nextRequest = waitForNextRequest();  

    ………

        // Create request to HAL

    //CaptureRequest转为给HAL3.0的camera3_capture_request_t

    camera3_capture_request_t request =camera3_capture_request_t();   request.frame_number = nextRequest->mResultExtras.frameNumber;//当前帧号

        Vector<camera3_stream_buffer_t>outputBuffers;

        // Get the request ID, if any

        int requestId;

        camera_metadata_entry_t requestIdEntry =

                nextRequest->mSettings.find(ANDROID_REQUEST_ID);

        if (requestIdEntry.count > 0) {

    //获取requestid,这里是mPreviewRequest的id

            requestId = requestIdEntry.data.i32[0];

        }

             .....

       for (size_t i = 0; i <nextRequest->mOutputStreams.size(); i++) {

             res =nextRequest->mOutputStreams.editItemAt(i)->

                     getBuffer(&outputBuffers.editItemAt(i));

    .....

        // Submit request and block until ready fornext one

        ATRACE_ASYNC_BEGIN(frame capture,request.frame_number);

       ATRACE_BEGIN(camera3->process_capture_request);

       //调用底层hal的process_capture_request,如antibanding参数设置

    res = mHal3Device->ops->process_capture_request(mHal3Device,&request);    ATRACE_END();

         .......

    }

    a.1 waitForNextRequest()

        Camera3Device::RequestThread::waitForNextRequest() {

       ………

        while (mRequestQueue.empty()) {

            if (!mRepeatingRequests.empty()) {

                // Always atomically enqueue allrequests in a repeating request

                // list. Guarantees a completein-sequence set of captures to

                // application.

                const RequestList &requests =mRepeatingRequests;

                RequestList::const_iteratorfirstRequest =

                        requests.begin();

                nextRequest = *firstRequest;

                //把当前的mRepeatingRequests插入到mRequestQueue

               mRequestQueue.insert(mRequestQueue.end(),

                        ++firstRequest,

                        requests.end());

                // No need to wait any longer

                mRepeatingLastFrameNumber = mFrameNumber+ requests.size() - 1;

                break;

            }

            //等待下一个request

            res =mRequestSignal.waitRelative(mRequestLock, kRequestTimeout);

           if ((mRequestQueue.empty() && mRepeatingRequests.empty()) ||

                    exitPending()) {

                Mutex::Autolock pl(mPauseLock);

                if (mPaused == false) {

                    ALOGV(%s: RequestThread: Goingidle, __FUNCTION__);

                    mPaused = true;

                    // Let the tracker know

                    sp<statustracker>statusTracker = mStatusTracker.promote();

                    if (statusTracker != 0) {

                       statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);

                    }

                }

                // Stop waiting for now and letthread management happen

                return NULL;

            }

        }

        if (nextRequest == NULL) {

            // Don't have a repeating requestalready in hand, so queue

            // must have an entry now.

            RequestList::iterator firstRequest =

                    mRequestQueue.begin();

            nextRequest = *firstRequest;

    //取一根mRequestQueue中的CaptureRequest,来自于mRepeatingRequests的next

            mRequestQueue.erase(firstRequest);

        }

        ………

        if (nextRequest != NULL) {

            //对每一个非空的request需要帧号++

    nextRequest->mResultExtras.frameNumber= mFrameNumber++;       nextRequest->mResultExtras.afTriggerId = mCurrentAfTriggerId;

           nextRequest->mResultExtras.precaptureTriggerId = mCurrentPreCaptureTriggerId;

        }

        return nextRequest;

    }

    该函数是响应RequestList的核心,通过不断的轮训休眠等待一旦mRepeatingRequests有Request可处理时,就将他内部所有的CaptureRequest加入到mRequestQueue 中去,理论来说每一个CaptureRequest对应着一帧的请求处理,每次响应时可能会出现mRequestQueue包含了多个 CaptureRequest。

    通过nextRequest->mResultExtras.frameNumber= mFrameNumber++表示当前CaptureRequest在处理的一帧图像号。

    对于mRepeatingRequests而言,只有其非空,在执行完一次queue操作后,在循环进入执行时,会自动对 mRequestQueue进行erase操作,是的mRequestQueue变为empty后再次重新加载mRepeatingRequests中的 内容,从而形成一个队repeatRequest的重复响应过程。

    a.2

    camera_metadata_entry_t requestIdEntry =nextRequest->mSettings.find(ANDROID_REQUEST_ID);提取该CaptureRequest对应的 Request 类型值;

    a.3 getBuffer操作

    a.4 mHal3Device->ops->process_capture_request(mHal3Device,&request)

    这里的request是已经由一个CaptureRequest转换为和HAL3.0交互的camera3_capture_request_t结构。

    3、    总结

    至此已经完成了一次向HAL3.0 Device发送一次完整的Request的请求。从最初Preview启动建立多个OutPutStream,再是将这些Stream打包成一个 mPreviewRequest来启动stream,随后将这个Request又转变为一个CaptureRequest,直到转为Capture list后交由RequestThread来处理这些请求。每一次的Request简单可以说是Camera3Device向HAL3.0请求一帧数据, 当然每一次Request也可以包含各种控制操作,如AutoFocus等内容。

    2.3.3 opencamera过程调用device3 initialize函数

        App至framework流程上面章节已做简要分析,frameworks -> hal初始化框图如下:

     

    2.3.4 frameworks层设置参数流程

        设置参数setParameters流程图如下所示:

        Frameworks层:

     

    2.3.5设置参数下至hal层流程

    由2.3.2节可知,开启并在request线程中--Camera3Device::RequestThread::threadLoop调用hal层接口函数mHal3Device->ops->process_capture_request(mHal3Device, &request),接口函数中会完成参数设置相关工作,如antibanding的设置。

    根据2.3.6节可知,antibanding等相关参数已经更新到requestlist中,hal层参数设置如下图所示:

     


    camera相关优秀 博客 http://www.cnblogs.com/whw19818/p/5766027.html
    展开全文
  • 不知道为什么,大家都喜欢拿华为和高通对比,说最近这5年,华为和高通发展如何如何,可能是因为双方在芯片、通信专利方面的竞争。 其实要我说,这对比本就不公平,毕竟双方是不一样性质的企业,如果大家硬要比,我...

    不知道为什么,大家都喜欢拿华为和高通对比,说最近这5年,华为和高通发展如何如何,可能是因为双方在芯片、通信专利方面的竞争。

    其实要我说,这对比本就不公平,毕竟双方是不一样性质的企业,如果大家硬要比,我可以说,这5年,高通还是那个高通,华为却早已不是当年的华为了。

    5年了,高通还是那个高通,华为却早已不是当年的华为!

    众所周知,2015年2月份,高通因垄断在中国被罚60.88亿。其实这起调查自2013年就开始了,长达14个月之久,直到2015年2月份才正式结束,可以说从启动调查起到现在已经是5年多时间了。

    但我们发现,这5年多以来,高通似乎还是那个高通,没有什么改变,差不多是原地踏步,反观华为,这5年以来,则大步前进,已经产生了翻天覆地的变化。

    5年了,高通还是那个高通,华为却早已不是当年的华为!

    为何说高通没有什么变化?我们看看高通5年前的模式,主要还是两部分,一是芯片,二是专利,这两部分的技术可能有了提升,比如芯片更强悍,专利更多,但没有质变,仅是量变。

    同时高通的商业模式依然没有变化,还是依靠自己在CDMA、WCDMA、LTE无线通信标准上的必要专利数量,来胁迫众手机厂商为专利和芯片买单,真的是没有太多长进。

    以至于最近这几年,高通甚至是一路官司打过来的,最近又被FTC诉讼,又和苹果打起了官司,还不是因为商务模式没变过,和之前一样霸道和惹人嫌。

    5年了,高通还是那个高通,华为却早已不是当年的华为!

    但华为却不一样,2013年时,华为的营收仅为2300多亿,而手机销量仅为5300万台,同时华为在通信专利上建树还非常少,完全称不上通信专利巨头。

    而和高通直接对应的芯片上,当时2012年发布K3V2,这款芯片还不行,制程太差,是40nm工艺的,与GPU也不太兼容,发热大,体验很不好,和高通的芯片完全不是一个档次的,华为自己都不太愿意使用。

    但到现在,华为已是全球第3的手机厂商,销量2亿多台,营收超过了1000亿美元,是原来的3倍多,芯片已经发展到了麒麟980,相比较高通845毫不逊色。专利上,华为5G专利比高通还多。

    5年了,高通还是那个高通,华为却早已不是当年的华为!

    可见,这5年时间,对于华为来讲,真的是蜕变,是一种质的升华。但这5年,对于高通来讲,真的是相当于原地踏步而已。当然正如任正非所言,任何一家企业都会死的,只是时间问题,高通能够原地踏步,能够这么霸道还保持住增长,也算是成功的了。

    展开全文
  • 简介 高通(Qualcomm)

    千次阅读 2016-01-04 17:14:08
    引言持续一年有余的高通反垄断案终于尘埃落定。国家发改委宣布,因违反中国反垄断法律,高通公司将被罚款9.75亿美元,并对智能手机专利授权做出多项调整。这一金额创下了中国反垄断罚款最高纪录。高通公司表示,中国...

    引言

    持续一年有余的高通反垄断案终于尘埃落定。国家发改委宣布,因违反中国反垄断法律,高通公司将被罚款9.75亿美元,并对智能手机专利授权做出多项调整。这一金额创下了中国反垄断罚款最高纪录。高通公司表示,中国国家发改委已经对其公布了一个裁决,即高通违反了中国的反垄断法律,高通将被罚款60.88亿元人民币(9.75亿美元),占其2013年度在中国市场销售额的8%。除此之外,中国国家发改委也针对高通的手机专利授权行为,作出了多项监管要求。高通表示,不会对发改委这一决定提出反驳。

    根据中国发改委的要求,高通将面向中国手机厂商,独立提供3G和4G专利授权,不再和高通其他专利捆绑。另外,高通面向中国手机厂商收取的专利费标准,将和全球其他国家的手机厂商保持大体一致的水平。【1】
    可能很多人都对高通这家公司不太了解,在看到上述新闻时会感到比较疑惑,为什么国家发改委要对这家公司做出如此“高”的处罚呢?高通到底是一家什么样的公司呢?它到底有何能耐呢?下面我就来给大家介绍一下高通。

    高通简介

    高通公司(英语:Qualcomm,NASDAQ:QCOM)是一个位于美国加州圣迭戈的无线电通信技术研发公司,由厄文·马克·雅克布和安德鲁·维特比创建,于1985年成立。【2】高通在以技术创新推动无线通讯向前发展方面扮演着重要的角色,以在CDMA技术方面处于领先地位而闻名,而LTE技术已成为世界上发展最快的无线技术。高通十分重视研究和开发,并已经向100多位制造商提供技术使用授权,涉及了世界上所有电信设备和消费电子设备的品牌。

    美国高通公司正积极倡导全球快速部署3G、4G网络、手机的应用。公司总部驻于美国加利福尼亚圣迭戈市,高通公司业务涵盖技术领先的3G、4G芯片组、系统软件以及开发工具和产品,技术许可的授予,BREW应用开发平台,QChat、BREWChatVoIP解决方案技术,QPoint定位解决方案,Eudora电子邮件软件,包括双向数据通信系统、无线咨询及网络管理服务等的全面无线解决方案,MediaFLO系统和GSM1x技术等。美国高通公司拥有所有3000多项CDMA及其它技术的专利及专利申请。高通已经向全球125家以上电信设备制造商发放了CDMA专利许可。

    高通公司所享有的卓越声誉远不止于CDMA领域。高通公司是标准普尔500指数的成分股、《财富》500强企业之一,并且是美国劳工部“劳工就业机会委员会大奖”(Secretary of Labor’s Opportunity Award)的得主。其卓尔不凡的工作环境、乐于奉献的工作态度和专业精神也令高通公司连续六年荣获《财富》“全美100家最适合工作的公司”,并且在《工业周刊》“100家最佳管理企业”名录中占据了一席之位。《CIO magazine》还将高通公司评选为100大运营和战略顶极优秀的典范企业。【3】

    不一样的科学家

    谈到高通,有一个不得不提的人物他就是高通创始人之一的安德鲁·维特比(Andrew Viterbi)。在通信行业之外的人可能知道他的并不多,不过通信行业的从业者大多知道以他的名字命名的维特比算法(Viterbi Algorithm)。维特比算法是现代数字通信中最常用的算法,同时也是很多自然语言处理采用的解码算法。可以好不夸张的讲维特比是对我们今天生活影响最大的科学家之一,因为基于CDMA的3G移动通信标准主要就是他和厄文·雅各布(Irwin Mark Jocobs)创办的高通公司制定的,并且高通公司在4G时代依然引领移动通信领域的发展。【4】

    维特比算法是一个特殊但应用最广的动态规划算法。利用动态规划,可以解决任何一个图中的最短路径问题。而维特比算法是针对一个特殊的图——篱笆网络(Lattice)的有向图最短路径问题而提出的,它之所以重要,是因为现今常用的技术,包括数字通信、语音识别、机器翻译、拼音转汉字、分词等都要使用它作为解码技术。可以说这个算法在通信领域扮演者举足轻重的作用。

    虽然数字通信和自然语言处理的基础算法并不复杂,甚至通信领域或计算机领域的学生花两个小时就能学会,但是在上世纪60年代能够想到这个快速算法是非常了不起的。凭借这个算法,维特比奠定了他在数字通信领域中不可替代的地位。但是维特比并不满足于停留在算法本身,而是努力的将它推广出去。为此他做了两件事:首先,他放弃了这个算法的专利;第二,他和雅各布博士一起在1968年创办了Linkabit 公司,将这个算法做成芯片卖给其他公司。

    这一步维特比已经比一般科学家走的远得多了。但是,这仅仅是维特比辉煌人生的第一步。上世纪80年代维特比致力于将CDMA技术应用于无线通信领域并创办了高通。【3】 维特比并不满足于仅仅从事科学研究,他有着一颗商人的大脑和思维方式,积极地将科学研究成果投入到商业应用之中。而这也正是维特比和一般科学家不同的地方,或者说这正是维特比超乎常人的魅力所在。
    对于高通的思考

    专利就是竞争力!”这句话在高通公司身上体现得淋漓尽致。在全球通信领域企业中,2013年高通公司市值一度达到历史高点1049.60亿美元,超过一直领先的英特尔公司的1035.01亿美元,站上世界第一。同年,在美国行业协会发布的报告中,全球电子硬件产业领域企业拥有专利排名中,高通公司的专利数量和质量位居世界一。

    一流企业卖专利,二流企业做产品,三流企业卖苦力。”这是在业界流传颇广的一句话:这句话强调了专利的重要性。在高通公司总部,矗立着几面“专利墙”。高通公司将自己拥有的每一件专利证书都挂在墙上。拿高通公司领导者的话来说,“专利墙”上的每一件专利,都是高通的核心资产和利润来源。目前,已挂在墙上的专利超过6000件,而在墙上张贴的一个说明中可以看到,尚有数千件专利申请正在审理中。如今,到高通公司的参观者可以通过这些专利墙,直观地认识到高通公司专利的数量和价值,追寻高通公司“发家”的历史足迹。

    许多人反感高通公司以专利构筑竞争屏障,但从另一个方面却不得不承认其创造和运用知识产权的能力。为了抢先进入3G市场,高通公司多年来积极从事CDMA的专利部署,并推动CDMA成为3G产业的标准协议。这样做的目的,是使得业内从事3G产品制造与销售的企业,几乎都必须与高通公司签订专利许可合同。高通公司掌握的3G基础专利是如此之多,以至于连它的竞争对手都不得不使用它的专利。至今,3G的每一个技术标准,几乎都无法绕开 高通,高通拥有其中主要核心技术的知识产权。

    企业可以用知识产权打造市场竞争的优势,滥用知识产权也会遭遇法律的制裁,而这正反两方面的“典型”,竟然能够被美国高通公司集于一身,不可谓不是一个“奇谈”。 但是人们只要稍加留意或许就能发现,高通公司这一“奇谈”的背后本质,即拥有并且运用好大量高质量的知识产权,这应该也是高通公司给予人们最大的启示。【5】

    总结

    想象力比知识更重要”- 阿尔伯特·爱因斯坦。时至今日,爱因斯坦的这番话依然正确。高通公司坚信想象力和创新能够促进技术进步,使最终用户受益。高通公司的创始人之一兼董事长艾文·马克·雅各布博士(Dr.Irwin Jacobs)表示:“我们用创新思想缔造了高通公司,并希望在创新道路上有所作为。”20多年来,高通公司为研发投入巨资,创造了数以千计的创新性理念、方法和产品,从而改变了无线通信世界。【3】

    创新创造是世界发展的源动力,引领时代潮流的国家往往是最具创新力的国家,同样引领行业发展的企业往往是最具创新的企业。由此我不认为垄断仅仅是对高通的批评,它还包含了对于高通创新创造能力的肯定。


    参考文献
    【1】 潘凌飞. 高通被罚9.75亿人民币 创中国反垄断最大罚单 .华尔街见闻 .2015.02.10
    【2】 维基百科 .高通词条
    【3】 百度百科 .高通词条
    【4】 数学之美(第二版) .吴军 .北京.人民邮电出版社.2014.11
    【5】 高通的前世今生 .中华人民共和国知识产权局(SIPO) .2014.03.06

    展开全文
  • 在本世纪之交,出于各方面的综合考量,高通战略性放弃了无线系统设备与终端业务。但在随后的 20 年中,高通不但成长为千亿美金市值的行业巨头,其开创性的技术与商业模式,也在一定程度上为移动通信产业的发展与...
  • 高通Qualcomm源码下载

    千次阅读 2018-08-21 20:26:35
    1.首先下载repo: a)终端运行 git clone git://codeaurora.org/tools/repo.git b)mkdir ~/bin c)拷贝repo 到~/bin下面,修改repo权限,chmod a+x ~/bin/repo d)修改repo 将REPO_URL='git://android.git....
  • 高通开发者工具集(1)

    千次阅读 2018-09-17 15:40:22
    高通骁龙开发者工具集包含了一系列适用于各开发阶段的工具,覆盖了从编码到产品部署的各个阶段,能够极大提升开发者的开发效率,提高产品质量,缩短开发时间。所有的高通开发工具都可以从 developer.qualcomm.com 处...
  • 高通的生存方式

    千次阅读 2001-09-21 14:43:00
    高通的生存方式作者:孙丽 最近在国内备受关注的高通是一家坐拥标准,靠出售知识产权为生的公司,在一片打压声中扶摇直上,以令人艳羡的生存方式,过上了风光的日子。 中国的企业,除了艳羡之外,还能悟出点什么?...
  • 我们知道一幅图像包含错综复杂的高频与低频部分,这使我们在处理这些图像时较为困难,如果我们把图像中我们要的频率留下,不想要的频率干掉,这样在处理过程中会简化很多。 高低通滤波原理图: ...
  • 下两个滤波器都是切比雪夫I型数字滤波器,不是巴特沃尔滤波器,请使用者注意!1.低通滤波器使用说明:将下列代码幅值然后以m文件保存,文件名要与函数名相同,这里函数名:lowp。function y=lowp(x,f1,f3,rp,rs,Fs) ...
  • 高通滤波器

    千次阅读 2018-06-12 11:59:12
  • 高通滤波器分析

    万次阅读 2018-05-29 21:06:52
    转载自玩转嵌入式公众号--点击打开链接曾经为了学高通滤波器的原理,还亲自用示波器测过信号的波形,自从做了那个实验,从此对高通滤波器有了更深一步的理解。要制作高通滤波器或者低通滤波器,必须要先明白他们呢的...
  • 基本的高通滤波器

    千次阅读 2019-06-09 16:21:55
    文章目录一、一个用于高通滤波的函数二、高通滤波器三、高通滤波 一、一个用于高通滤波的函数 使用函数 lpfilter 构建一个生成高通滤波器的函数:hpfilter function H = hpfilter(type, M, N, D0, n) %HPFIL...
  • matlab设计模拟高通滤波器

    万次阅读 2018-10-24 21:46:06
    简单记录下在matlab上如何设计出模拟的高通滤波器,包括:巴特沃斯滤波器、切比雪夫I型滤波器、切比雪夫II型滤波器、椭圆型滤波器。 %设计高通滤波器 %巴特沃斯、切比雪夫I型、切比雪夫II型、椭圆型滤波器 ...
  • 理想高通滤波器

    万次阅读 2016-07-07 22:17:12
    高通滤波器 首先,对一副图像进行如下二维傅里叶变换。 我们将u=0和v=0带上式,我们可以得到如下式子。 根据上式,可以到F(0,0)的值是非常大的。这里,我们将 F(0,0)称为直流分量,直流分量比其他的成分要...
  • 低通滤波器和高通滤波器的程序实现原理推导

    万次阅读 多人点赞 2018-04-20 15:33:05
    傅立叶变换,拉普拉斯变换和Z变换 对于信号分析而言,傅立叶变换是必不可少的,我们都知道傅立叶变换是把系统从时域变换到频域进行分析,那么拉普拉斯变换和Z变换是干什么的?简单的来说,由于傅里叶变换的收敛有一个...
  • MATLAB高通滤波器程序

    2018-08-29 16:30:56
    本程序是基于MATLAB软件数字高通滤波器
  • 高通滤波器 python实现

    千次阅读 2017-07-28 17:34:39
    # -- coding: utf-8 -- import cv2 import cv2 import numpy as np from scipy import ndimage#这个是滤波器使用的模板矩阵 kernel_3x3 = np.array([[-1, -1, -1], [-1, 8, -1], [-
  • 切比雪夫高通滤波器

    2018-03-08 17:25:45
    fc=0.3KHz,δ=0.8dB,fr=0.2KHz,At=20dB,T=1ms;设计一个切比雪夫高通滤波器,观察其通带损耗和阻带衰减是否满足要求

空空如也

1 2 3 4 5 ... 20
收藏数 44,889
精华内容 17,955
关键字:

高通