Camera显示之Hal层的适配二.docx

上传人:b****8 文档编号:30660009 上传时间:2023-08-19 格式:DOCX 页数:29 大小:22.23KB
下载 相关 举报
Camera显示之Hal层的适配二.docx_第1页
第1页 / 共29页
Camera显示之Hal层的适配二.docx_第2页
第2页 / 共29页
Camera显示之Hal层的适配二.docx_第3页
第3页 / 共29页
Camera显示之Hal层的适配二.docx_第4页
第4页 / 共29页
Camera显示之Hal层的适配二.docx_第5页
第5页 / 共29页
点击查看更多>>
下载资源
资源描述

Camera显示之Hal层的适配二.docx

《Camera显示之Hal层的适配二.docx》由会员分享,可在线阅读,更多相关《Camera显示之Hal层的适配二.docx(29页珍藏版)》请在冰豆网上搜索。

Camera显示之Hal层的适配二.docx

Camera显示之Hal层的适配二

Camera显示之Hal层的适配

(二)

Tag标签:

  一.基本关系  1.先来看看KTMhal层大概类图关系:

  大概类图关系就是这样,其中和显示相关的类图关系如红线所圈区域。

  可以猜测到与显示相关的逻辑处理应该都会在DisplayClient这个类去实现。

2.CamDeviceManager和DisplayClient关系的建立:

  以后app下达有关预览显示相关的东西啊在hal层基本上都是这一条先进行传递命令,不过总1中我们可以看到CamDevice还有一些衍生类,这些都是mtk为不同设备做的一些定制,主要的路径还是如上图所示。

  二.接着之前的在CameraClient中的代码:

  //!

++

  elseif(window==0){

  result=mHardware->setPreviewWindow(window);

  }

  1.setPreviewWindow(window)通过CameraHardwareInterface适配:

mDevice->ops->set_preview_window(mDevice,

  buf.get()?

&mHalPreviewWindow.nw:

0);

来实现向hal层下达命令和设置参数。

  在这里我们发现传入的是mHalPreviewWindow.nw,而不是我们之前所讲述的ANativeWindow这是因为mHalPreviewWindow.nw将ANativeWindow的一些流的操作进行封装,使之操作更加简便。

  mHalPreviewWindow.nw的定义:

  structcamera_preview_window{

  structpreview_stream_opsnw;

  void*user;

  };

就是结构体:

struct:

typedefstructpreview_stream_ops{

  int(*dequeue_buffer)(structpreview_stream_ops*w,

  buffer_handle_t**buffer,int*stride);

  int(*enqueue_buffer)(structpreview_stream_ops*w,

  buffer_handle_t*buffer);

  int(*cancel_buffer)(structpreview_stream_ops*w,

  buffer_handle_t*buffer);

  int(*set_buffer_count)(structpreview_stream_ops*w,intcount);

  int(*set_buffers_geometry)(structpreview_stream_ops*pw,

  intw,inth,intformat);

  int(*set_crop)(structpreview_stream_ops*w,

  intleft,inttop,intright,intbottom);

  int(*set_usage)(structpreview_stream_ops*w,intusage);

  int(*set_swap_interval)(structpreview_stream_ops*w,intinterval);

  int(*get_min_undequeued_buffer_count)(conststructpreview_stream_ops*w,

  int*count);

  int(*lock_buffer)(structpreview_stream_ops*w,

  buffer_handle_t*buffer);

  //Timestampsaremeasuredinnanoseconds,andmustbecomparable

  //andmonotonicallyincreasingbetweentwoframesinthesame

  //previewstream.Theydonotneedtobecomparablebetween

  //consecutiveorparallelpreviewstreams,cameras,orappruns.

  int(*set_timestamp)(structpreview_stream_ops*w,int64_ttimestamp);

对显示流的操作都是通过这些函数实现的,而mHalPreviewWindow中实现了具体操的方法,在这些方法的实现中实现对作ANativeWindow的操作。

而在hal端就是通过mHalPreviewWindow.nw进行对ANativeWindow的具体操作。

  基本类图关系:

  2.继续1中的:

mDevice->ops->set_preview_window(mDevice,

  buf.get()?

&mHalPreviewWindow.nw:

0);

我已经知道了mHalPreviewWindow.nw为传入的一个重要参数mHalPreviewWindow.nw为preview_stream_ops。

  继续看看set_preview_window这个方法。

我们有上篇文章知道ops是ICamDevice的一个成员gCameraDevOps,类型为camera_device_ops_t:

  可以看到:

staticcamera_device_ops_tconstgCameraDevOps={

  set_preview_window:

camera_set_preview_window,

  set_callbacks:

camera_set_callbacks,

  enable_msg_type:

camera_enable_msg_type,

  disable_msg_type:

camera_disable_msg_type,

  msg_type_enabled:

camera_msg_type_enabled,

  start_preview:

camera_start_preview,

  stop_preview:

camera_stop_preview,

  preview_enabled:

camera_preview_enabled,

  store_meta_data_in_buffers:

camera_store_meta_data_in_buffers,

  start_recording:

camera_start_recording,

  stop_recording:

camera_stop_recording,

  recording_enabled:

camera_recording_enabled,

  release_recording_frame:

camera_release_recording_frame,

  auto_focus:

camera_auto_focus,

  cancel_auto_focus:

camera_cancel_auto_focus,

  take_picture:

camera_take_picture,

  cancel_picture:

camera_cancel_picture,

  set_parameters:

camera_set_parameters,

  get_parameters:

camera_get_parameters,

  put_parameters:

camera_put_parameters,

  send_command:

camera_send_command,

  release:

camera_release,

  dump:

camera_dump,

};

  gCameraDevOps中的函数地址映射到ICamDevice中的函数实现。

  所以:

ops->set_preview_window(mDevice,buf.get()?

&mHalPreviewWindow.nw:

0)就对应到ICamDevice:

:

camera_set_preview_window的发发调用。

staticintcamera_set_preview_window(

  structcamera_device*device,

  structpreview_stream_ops*window

{

  interr=-EINVAL;

  //

  ICamDevice*constpDev=ICamDevice:

:

getIDev(device);

  if(pDev)

  {

  err=pDev->setPreviewWindow(window);

  }

  //

  returnerr;

}

staticinlineICamDevice*getIDev(camera_device*constdevice)

  {

  return(NULL==device)

  NULL

  :

reinterpret_cast(device->priv);//得到device->priv

由上篇文章:

  知道device->pri实际上是在创建实例的时候指向的自己:

  ICamDevice:

:

  ICamDevice()

  :

camera_device_t()

  ,RefBase()

  ,mDevOps()

  //

  ,mMtxLock()

  //

  {

  MY_LOGD('ctor');

  :

:

memset(static_cast(this),0,sizeof(camera_device_t));

  this->priv=this;//用priv指针保存自己。

  this->ops=&mDevOps;//ops指向了mDevOps

  mDevOps=gCameraDevOps;//mDevOps为gCameraDevOps指向的结构体

  }

  继续回到pDev->setPreviewWindow(window);  在ICamDevice中没有对setPreviewWindow具体的实现,而是在其子类CamDevice对ICamDevice进行了具体的实现;  随意代码定位到CamDevice:

status_t

CamDevice:

:

setPreviewWindow(preview_stream_ops*window)

{

  MY_LOGI('+window(%p)',window);

  //

  status_tstatus=initDisplayClient(window);//开始初始化DisplayClient

  if(OK==status&&previewEnabled()&&mpDisplayClient!

=0)

  {

  status=enableDisplayClient();//时能DisplayClient端

  }

  //

  returnstatus;

}

status_t

CamDevice:

:

initDisplayClient(preview_stream_ops*window)

{

#if'1'!

=MTKCAM_HAVE_DISPLAY_CLIENT

  #warning'NotBuildDisplayClient'

  MY_LOGD('NotBuildDisplayClient');

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

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

/[3.1]createaDisplayClient.

  mpDisplayClient=IDisplayClient:

:

createInstance();

  if(mpDisplayClient==0)

  {

  MY_LOGE('CannotcreatempDisplayClient');

  status=NO_MEMORY;

  gotolbExit;

  }

  //[3.2]initializethenewly-createdDisplayClient.

  if(!

mpDisplayClient->init())

  {

  MY_LOGE('mpDisplayClientinit()failed');

  mpDisplayClient->uninit();

  mpDisplayClient.clear();

  status=NO_MEMORY;

  gotolbExit;

  }

  //[3.3]setpreview_stream_ops&relatedwindowinfo.

  if(!

mpDisplayClient->setWindow(window,previewSize.width,previewSize.height,queryDisplayBufCount()))//绑定window

  {

  status=INVALID_OPERATION;

  gotolbExit;

  }

  //[3.4]setImageBufferProviderClientifitexist.

  if(mpCamAdapter!

=0&&!

mpDisplayClient->setImgBufProviderClient(mpCamAdapter))//重要!

设置流数据的Buffer提供者。

  {

  status=INVALID_OPERATION;

  gotolbExit;

  }

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

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

status_t

CamDevice:

:

enableDisplayClient()

{

  status_tstatus=OK;

  SizepreviewSize;

  //

  //[1]Getpreviewsize.

  if(!

queryPreviewSize(previewSize.width,previewSize.height))

  {

  MY_LOGE('queryPreviewSize');

  status=DEAD_OBJECT;

  gotolbExit;

  }

  //

  //[2]Enable

  if(!

mpDisplayClient->enableDisplay(previewSize.width,previewSize.height,queryDisplayBufCount(),mpCamAdapter))//设置了预览数据的尺寸和Buffer提供者相关的数据

  {

  MY_LOGE('mpDisplayClient(%p)->enableDisplay()',mpDisplayClient.get());

  status=INVALID_OPERATION;

  gotolbExit;

  }

  //

  status=OK;

lbExit:

  returnstatus;

}

  3.定位到DisplayClient中:

enableDisplay(

  int32_tconsti4Width,

  int32_tconsti4Height,

  int32_tconsti4BufCount,

  spconst&rpClient

{

  boolret=false;

  preview_stream_ops*pStreamOps=mpStreamOps;

  //

  //[1]Re-configuratethisinstanceifanysettingchanges.

  if(!

checkConfig(i4Width,i4Height,i4BufCount,rpClient))

  {

  MY_LOGW('UninitthecurrentDisplayClient(%p)andre-config...',this);

  //

  //[.1]uninitialize

  uninit();

  //

  //[.2]initialize

  if(!

init())

  {

  MY_LOGE('re-init()failed');

  gotolbExit;

  }

  //

  //[.3]setrelatedwindowinfo.

  if(!

setWindow(pStreamOps,i4Width,i4Height,i4BufCount))//window的尺寸和预览数据的大小一致

  {

  gotolbExit;

  }

  //

  //[.4]setImageBufferProviderClient.

  if(!

setImgBufProviderClient(rpClient))//Buffer的数据提供者为mpCamAdapter,就是CamAdapter,后面的预览数据元都是通过它来提供。

  {

  gotolbExit;

  }

  }

  //

  //[2]Enable.

  if(!

enableDisplay())//开始进行数据的获取和显示

  {

  gotolbExit;

  }

  //

  ret=true;

lbExit:

  returnret;

}

先来看看第一个关键函数:

setWindow(pStreamOps,i4Width,i4Height,i4BufCount)

bool

DisplayClient:

:

setWindow(

  preview_stream_ops*constwindow,

  int32_tconstwndWidth,

  int32_tconstwndHeight,

  int32_tconsti4MaxImgBufCount

{

  MY_LOGI('+window(%p),WxH=%dx%d,count(%d)',window,wndWidth,wndHeight,i4MaxImgBufCount);

  //

  if(!

window)

  {

  MY_LOGE('NULLwindowpassedinto');

  returnfalse;

  }

  //

  if(0>=wndWidth||0>=wndHeight||0>=i4MaxImgBufCount)

  {

  MY_LOGE('badarguments-WxH=%dx%d,count(%d)',wndWidth,wndHeight,i4MaxImgBufCount);

  returnfalse;

  }

  //

  //

  Mutex:

:

Autolock_l(mModuleMtx);

  returnset_preview_stream_ops(window,wndWidth,wndHeight,i4MaxImgBufCount);//

}

ool

DisplayClient:

:

set_preview_stream_ops(

  preview_stream_ops*constwindow,

  int32_tconstwndWidth,

  int32_tconstwndHeight,

  int32_tconsti4MaxImgBufCount

{

  CamProfileprofile(__FUNCTION__,'DisplayClient');

  //

  boolret=false;

  status_terr=0;

  int32_tmin_undequeued_buf_count=0;

  //

  //

(2)Check

  if(!

mStreamBufList.empty())

  {

  MY_LOGE(

  'lockedbuffercount(%d)!

=0,'

  'callersmustreturnalldequeuedbuffers,'

//'andthencallcleanupQueue()'

  ,mStreamBufList.size()

  );

  dumpDebug(mStreamBufList,__FUNCTION__);

  gotolbExit;

  }

  //

  //(3)Savainfo.

  mpStreamImgInfo.clear();//mpStreamImgInfo封装的视屏数据流的基本信息。

  mpStreamImgInfo=newImgInfo(wndWidth,wndHeight,CAMERA_DISPLAY_FORMAT,CAMERA_DISPLAY_FORMAT_HAL,'Camera@Display');//设置了Stream的宽高和显示类型。

  mpStreamOps=window;//mpStreamOps保存了上层传进来的对象指针。

后面就通过它和显示方进行交互。

  mi4MaxImgBufCount=i4MaxImgBufCount;

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

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

  err=mpStreamOps->set_buffer_count(mpStreamOps,mi4MaxImgBufCount+min_undequeued_buf_count);

  if(err)

  {

 

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 解决方案 > 营销活动策划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1