Camera显示之Hal层的适配二.docx
- 文档编号:18511773
- 上传时间:2023-08-19
- 格式:DOCX
- 页数:29
- 大小:22.23KB
Camera显示之Hal层的适配二.docx
《Camera显示之Hal层的适配二.docx》由会员分享,可在线阅读,更多相关《Camera显示之Hal层的适配二.docx(29页珍藏版)》请在冰点文库上搜索。
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)
{
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Camera 显示 Hal 适配二