camera打开流程(preview)(APP->hal)
Cam1DeviceBase.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\device)
Cam1DeviceBase::onCam1Device_NotifyCb
接上章的 mpCamClient->startPreview() //开始使能Preview
Camera.java (packages\apps\legacycamera\src\com\android\camera)
onCreate
mCameraPreviewThread.start(); //执行
Thread里面的run函数
Thread mCameraPreviewThread = new Thread(new Runnable() {
public void run() {
initializeCapabilities(); //单独分析1
startPreview(); //单独分析2
}
});
initializeCapabilities //单独分析1
//获取摄像头的一些参数,private android.hardware.Camera mCameraDevice;,所以这里会直接调用jni
mInitialParams = mCameraDevice.getParameters();
//Camera.java (frameworks\base\core\java\android\hardware)
Parameters p = new Parameters();
String s = native_getParameters();
//android_hardware_Camera.cpp (frameworks\base\core\jni)
{ "native_getParameters", "()Ljava/lang/String;", (void *)android_hardware_Camera_getParameters },
sp<Camera> camera = get_native_camera(env, thiz, NULL);
sp<Camera> camera = get_native_camera(env, thiz, NULL); //得到Camera的引用,Camera.cpp (frameworks\av\camera)
String8 params8 = camera->getParameters(); //这里通过引用调用Camera.cpp里面相应的函数
//在Camera.cpp (frameworks\av\camera)
params = mCamera->getParameters(); //这里的mCamera就是open摄像头的时候得到camera的引用
//调用这里ICamera.cpp (frameworks\av\camera)
remote()->transact(GET_PARAMETERS, data, &reply); //通过binder从服务器端获取,单独分析3
mFocusManager.initializeParameters(mInitialParams);
//开始预览,单独分析2
startPreview();
setPreviewDisplay(mSurfaceHolder); //设置预览的画布
setDisplayOrientation(); //设置显示方向
mDisplayRotation = Util.getDisplayRotation(this); //获得屏幕旋转值
mDisplayOrientation = Util.getDisplayOrientation(mDisplayRotation, mCameraId); //获得屏幕方向
mCameraDevice.setDisplayOrientation(mDisplayOrientation); //设置摄像头的屏幕方向
mFaceView.setDisplayOrientation(mDisplayOrientation); //设置面对面的方向
mFaceView.setDisplayOrientation(mDisplayOrientation); //设置面对面的方向
setCameraParameters(UPDATE_PARAM_ALL); //设置摄像头参数
mParameters = mCameraDevice.getParameters(); //获取参数,单独分析1
updateCameraParametersInitialize(); //更新参数
mParameters.setPreviewFrameRate(max);
// Inform the mainthread to go on the UI initialization.
mCameraPreviewThread.notify(); //启动主线程进行UI初始化
mCameraDevice.startPreview();
//android_hardware_Camera.cpp (frameworks\base\core\jni)
sp<Camera> camera = get_native_camera(env, thiz, NULL);
camera->startPreview()
//Camera.cpp (frameworks\av\camera)
sp <ICamera> c = mCamera;
return c->startPreview(); //这里和get_parameters一个路径, 单独分析5
单独分析3:获取参数的服务端分析
CameraHardwareInterface.h (frameworks\av\services\camera\libcameraservice\device1)
char *temp = mDevice->ops->get_parameters(mDevice); //这里会调用到Cam1Device.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\device)的函数
//Cam1Device.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\device)mtk_camera_device_ops数组中的get_parameters,加个一个前缀camera_get_parameters
camera_get_parameters
Cam1Device*const pDev = Cam1Device::getDevice(device); //获取设备
param = pDev->getParameters(); //调用Cam1DeviceBase.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\device)
String8 params_str8 = mpParamsMgr->flatten(); //获取参数 ,mutable MtkCameraParameters mParameters;
//ParamsManager.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\common\paramsmgr\params)的flatten
mParameters.flatten(); //调用这个来获得参数
CameraParameters.cpp (frameworks\av\camera) //获取参数键值对,赋值给字符串,返回
size_t size = mMap.size(); //map的值的来源,单独分析4
k = mMap.keyAt(i);
v = mMap.valueAt(i);
strcpy(params_string, params_str8.string()); //把获得的参数拷贝到params_string
单独分析4:map的值的来源
ParamsManager.update.cpp(vendor\mediatek\proprietary\hardware\mtkcam\legacy\platform\mt6735\v1\common\paramsmgr\params)
updateDefaultParams1_ByDefaultS函数中设置默认的参数值,
mParameters.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, "5000,30000");
updatePreviewFpsParams函数中设置设置的参数值
//s8FpsRangeDefault.string());这个值从config.ftbl.common_raw.h得到,具体分析看config.ftbl.common_raw.h分析这章
mParameters.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, s8FpsRangeDefault.string()); /
//CameraParameters.cpp (frameworks\av\camera)中
mMap.replaceValueFor(String8(key), String8(value));
单独分析5:开始预览的服务端分析
CameraHardwareInterface.h (frameworks\av\services\camera\libcameraservice\device1)
startPreview
return mDevice->ops->start_preview(mDevice);
//Cam1Device.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\device)mtk_camera_device_ops数组中的get_parameters,加个一个前缀camera_get_parameters
camera_start_preview
Cam1Device*const pDev = Cam1Device::getDevice(device);
err = pDev->startPreview();
//Cam1DeviceBase.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\device)
if ( mpCamAdapter != 0 && mpCamAdapter->isTakingPicture() ) //判读是不是在拍照中
//MtkDefaultCamAdapter.Capture.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\platform\mt6735\v1\adapter\mtkdefault)
isTakingPicture
//IState::eState_PreCapture,IState::eState_Capture, IState::eState_PreviewCapture, IState::eState_VideoSnapshot,如果是这些状态就返回
if ( previewEnabled() ) //判断是否使能了preview,如果已经使能了,就返回
if ( ! onStartPreview() ) //开始预览,单独分析6
enableDisplayClient() //使能显示客户端,单独分析7
mpCamClient->startPreview() //客户端开始使能预览,单独分析10
// forward to registered clients
Vector<sp<ICamClient> >::const_iterator it;
for (it = vmpCamClient.begin(); it != vmpCamClient.end(); ++it)
(*it)->startPreview();
// startPreview in Camera Adapter.
status = mpCamAdapter->startPreview();
MtkDefaultCamAdapter.Preview.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\platform\mt6735\v1\adapter\mtkdefault)
mpStateManager->getCurrentState()->onStartPreview(this);
//StateManager.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\platform\mt6735\v1\adapter\mtkdefault\state)
return mpCurrState;
State.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\platform\mt6735\v1\adapter\mtkdefault\state)
onStartPreview
IStateManager::StateObserver stateWaiter(getStateManager());
getStateManager()->registerOneShotObserver(&stateWaiter);
status = pHandler->onHandleStopPreview();
// MtkDefaultCamAdapter.Preview.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\platform\mt6735\v1\adapter\mtkdefault)
return forceStopAndCleanPreview();
enableMsgType(CAMERA_MSG_PREVIEW_METADATA); //Enable a message, or set of messages.
单独分析6:开始预览
if ( ! onStartPreview() ) //开始预览,单独分析6
//DefaultCam1Device.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\platform\mt6735\v1\device)
(0) wait for thread
waitThreadInitDone() //等待初始化线程完成
// (1) Check Permission.
pCamMgr->getPermission() //检查权限
// (2) Update Hal App Mode.
//ParamsManager.update.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\common\paramsmgr\params)
evaluateHalAppMode(s8HalAppMode)
return evaluateHalAppModeUtility(mode);
i4CamMode = mParameters.getInt(MtkCameraParameters::KEY_CAMERA_MODE); //获取模式,现在应该是CAMERA_MODE_MTK_PRV
pszZsdMode = mParameters.get(MtkCameraParameters::KEY_ZSD_MODE //获取是否是ZSD模式,如果是就
mode = MtkCameraParameters::APP_MODE_NAME_MTK_ZSD;
(3) Initialize Camera Adapter.
initCameraAdapter()
// (1) Check to see if CamAdapter has existed or not. //如果不存在就创建一个
// (2) Create & init a new CamAdapter.
mpCamAdapter = ICamAdapter::createInstance(mDevName, mi4OpenId, mpParamsMgr); //创建一个mpCamAdapter
//BaseCamAdapter.Instance.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\platform\mt6735\v1\adapter)
s8AppMode = PARAMSMANAGER_MAP_INST(eMapAppMode)->stringFor(pParamsMgr->getHalAppMode()); //获得APP的模式
if ( s8AppMode == MtkCameraParameters::APP_MODE_NAME_MTK_PHOTO ) //根据不同模式,生成不同的Adapter,这里以预览为例,后面又表格会说明什么情况生成什么Adapter
return createMtkDefaultCamAdapter(s8AppMode, i4OpenId, pParamsMgr); //单独分析7,生成Adapter,下章分析
单独分析7:使能显示客户端
enableDisplayClient()
[1] Get preview size.
queryPreviewSize(previewSize.width, previewSize.height) //获取预览大小
mpParamsMgr->getPreviewSize(&ri4Width, &ri4Height);
mParameters.getPreviewSize(width, height);
// [2] Enable
mpDisplayClient->enableDisplay(previewSize.width, previewSize.height, queryDisplayBufCount(), mpCamAdapter)
DisplayClient.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\client\displayclient)
preview_stream_ops* pStreamOps = mpStreamOps; //获取数据流的操作函数
// [.1] uninitialize //先清除
uninit();
disableDisplay();
destroyDisplayThread();
destroyImgBufQueue();
// [.2] initialize
init() //初始化
createDisplayThread
ret = createDisplayThread()
//DisplayClient.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\client\displayclient)
return new DisplayThread(pHandler);
DisplayThread::DisplayThread(IDisplayThreadHandler*const pHandler) : IDisplayThread()
, mpThreadHandler(pHandler) //线程执行函数, mi4Tid(0), miLogLevel(1), mCmdQue() //数据流的操作命令, mCmdQueMtx(), mCmdQueCond()mpDisplayThread->run() //运行线程,关注threadLoop,会响应命令threadLoopcase Command::eID_WAKEUP:mpThreadHandler->onThreadLoop(cmd); //单独分析8,onThreadLoop
createImgBufQueue()
mpImgBufQueue = new ImgBufQueue(IImgBufProvider::eID_DISPLAY, "CameraDisplay@ImgBufQue"); //创建缓存队列
mpExtImgProc = ExtImgProc::createInstance();
// [.3] set related window info.
setWindow(pStreamOps, i4Width, i4Height, i4BufCount) //后续分析
set_preview_stream_ops(window, wndWidth, wndHeight, i4MaxImgBufCount);
// [.4] set Image Buffer Provider Client.
// [2] Enable.
enableDisplay() //使能输出
// (2) Check to see if it has been enabled.
isDisplayEnabled()
// (3) Check to see if thread is alive.
if ( mpDisplayThread == 0 )
// (4) Enable the flag.
::android_atomic_write(1, &mIsDisplayEnabled);
// (5) Post a command to wake up the thread.
mpDisplayThread->postCommand(Command(Command::eID_WAKEUP)); //这就是执行onThreadLoop 单独分析8
//单独分析8,onThreadLoop
//DisplayClient.BufOps.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\client\displayclient)
// (1) Prepare all TODO buffers.
prepareAllTodoBuffers(pImgBufQueue) //准备buf,单独分析9
// (2) Start
pImgBufQueue->startProcessor()
//ImgBufQueue.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\common\camutils)
mbIsProcessorRunning = true;
mDoneImgBufQueCond.broadcast(); //发送广播开始运行
// (3) Do until disabled.
// (.1)
waitAndHandleReturnBuffers(pImgBufQueue);
// (1) deque buffers from processor.
rpBufQueue->dequeProcessor(vQueNode);
// (2) handle buffers dequed from processor.
ret = handleReturnBuffers(vQueNode); //获得返回的BUf
/*
* Notes:* For 30 fps, we just enque (display) the latest frame,* and cancel the others.* For frame rate > 30 fps, we should judge the timestamp here or source.*/// (1) determine the latest DONE buffer index to display; otherwise CANCEL.if ( rvQueNode[idxToDisp].isDONE() ) //如果是30帧的数据break; //跳出// (3) Remove from List and enquePrvOps/cancelPrvOps, one by one.// (.1) Check valid pointers to image buffers in Queue & Listif ( rpQueImgBuf == 0 || pStreamImgBuf == 0 )continue;// (.2) Check the equality of image buffers between Queue & List.if ( rpQueImgBuf->getVirAddr() != pStreamImgBuf->getVirAddr() )continue;// (.3) Every check is ok. Now remove the node from the list.mStreamBufList.erase(mStreamBufList.begin());// (.4) enquePrvOps/cancelPrvOpsIExtImgProc::ImgInfo img; //赋值图片的信息img.bufType = ExtImgProc::BufType_Display;img.format = pStreamImgBuf->getImgFormat();mpExtImgProc->doImgProc(img);// For Display Rotationif(rvQueNode[i].getOrientation() != 0)pStreamImgBuf->setNeedDisplayRotation(true); //旋转enquePrvOps(pStreamImgBuf); //放入buf
单独分析9:准备buf
prepareOneTodoBuffer(rpBufQueue)
// (2) deque it from PrvOps
sp<StreamImgBuf> pStreamImgBuf;
dequePrvOps(pStreamImgBuf)
//DisplayClient.BufOps.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\client\displayclient)
// [1] dequeue_buffer
mpStreamOps->dequeue_buffer(mpStreamOps, &phBuffer, &stride);
// [3] Now let the graphics framework to lock the buffer, and provide us with the framebuffer data address.
GraphicBufferMapper::get().lock(*phBuffer, CAMERA_GRALLOC_USAGE, bounds, &address);
// [4] Get the ion fd of gralloc buffer.
err = ::gralloc_extra_query(*phBuffer, GRALLOC_EXTRA_GET_ION_FD, &fdIon);
// [5] Setup the output to return.
rpImgBuf = new StreamImgBuf(mpStreamImgInfo, stride, address, phBuffer, fdIon);
void* virtAddr = pStreamImgBuf->getVirAddr(); //得到虚拟地址
if(pStreamImgBuf->getOrientation() & HAL_TRANSFORM_ROT_90) //如果是旋转90
pStreamImgBuf->setNeedDisplayRotation(true);
memset((void*)virtAddr, iFirstFrameColor, pStreamImgBuf->getBufSize());
enquePrvOps(pStreamImgBuf); //放入bug
// [3] set timestamp.
err = mpStreamOps->set_timestamp(mpStreamOps, rpImgBuf->getTimestamp());
// [5] unlocks and post the buffer to display.
err = mpStreamOps->enqueue_buffer(mpStreamOps, rpImgBuf->getBufHndlPtr());
// (3) enque it into Processor
ret = rpBufQueue->enqueProcessor(
ImgBufQueNode(pStreamImgBuf, ImgBufQueNode::eSTATUS_TODO, 0, 0, 0, (uint32_t)mi4Orientation)
);
// (4) enque it into List & increment the list size.
mStreamBufList.push_back(pStreamImgBuf);
单独分析10,//客户端开始使能预览
mpCamClient->startPreview()
mpFDClient->startPreview(); //启动人脸检测预览,没有什么工作
//FDClient.h (vendor\mediatek\proprietary\hardware\mtkcam\legacy\platform\mt6735\v1\client\camclient\fd)
return true;
mpPreviewClient->startPreview()
PreviewClient.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\client\camclient\previewcallback)
:android_atomic_write(1, &mIsPrvStarted);
ms8PrvTgtFmt = mpParamsMgr->getPreviewFormat(); //获取格式
//ParamsManager.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\common\paramsmgr\params)
getStr(CameraParameters::KEY_PREVIEW_FORMAT);
mpParamsMgr->getPreviewSize(&mi4PrvWidth, &mi4PrvHeight); //得到预览尺寸
mParameters.getPreviewSize(width, height);
initBuffers();
//PreviewClient.BufOps.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\client\camclient\previewcallback)
//分配buf
mpImgBufMgr = ImgBufManager::alloc(ms8PrvTgtFmt, mi4PrvWidth, mi4PrvHeight, eMAX_PREVIEW_BUFFER_NUM, "PreviewClientCb", mpCamMsgCbInfo->mRequestMemory, 0, 0);
mpExtImgProc = ExtImgProc::createInstance(); //创建IMG信息结构体,
//ExtImgProcImp.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\common\extimgproc)
return ExtImgProcImp::getInstance();
static ExtImgProcImp Singleton;
//Set which img buf you want to process.
//For example: mImgMask = BufType_Display|BufType_Record;mImgMask = 0; //这里表示哪种BUFmpExtImgProc->init();mUser = 0; //user的个数
//ExtImgProcImp.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\common\extimgproc)
android_atomic_inc(&mUser); //用户加一
onStateChanged();
//// enable if both preview started && message enabled; otherwise disable.
if ( isEnabledState() )
0 != ::android_atomic_release_load(&mIsMsgEnabled) && 0 != ::android_atomic_release_load(&mIsPrvStarted)
postCommand(Command(Command::eID_WAKEUP)); //启动线程PreviewClient.Thread.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\client\camclient\previewcallback)
threadLoop()
case Command::eID_WAKEUP:
onClientThreadLoop //单独分析11
//单独分析11:onClientThreadLoop
onClientThreadLoop
// (1) Get references to pool/queue before starting, so that nothing will be free during operations.
// (2) stop & clear all buffers so that we won't deque any undefined buffer.
pBufQueue->stopProcessor();
// (3) Prepare all TODO buffers.
prepareAllTodoBuffers(pBufQueue, pBufMgr)
//PreviewClient.BufOps.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\client\camclient\previewcallback)
// For better performance, we should enque all TODO buffers before starting.// In that case, we could deque more than one buffers, and should enque // them in the loop.
// (1) Determine how many buffers to enque.
// all buffers = callback buffers + enq buffers (in list) + not-enq buffers (others)
// Assumption:
// (1) callback is returned in order.
// (2) all callback are returned within this function,
// ==> not-enq buffers (others) = eMAX_PREVIEW_BUFFER_NUM - mImgBufList.size()
iEnqCount = eMAX_PREVIEW_BUFFER_NUM - mImgBufList.size();
// (.1) Determine which buffer to enque.
pCameraImgBuf = rpBufMgr->getBuf(muImgBufIdx);
muImgBufIdx = (muImgBufIdx+1) % eMAX_PREVIEW_BUFFER_NUM;
// (.2) enque it into Processor
ret = rpBufQueue->enqueProcessor( ImgBufQueNode(pCameraImgBuf, ImgBufQueNode::eSTATUS_TODO));
// (.3) enque it into List & increment the list size.
mImgBufList.push_back(pCameraImgBuf);
// (4) Start
pBufQueue->startProcessor()
// (5) Do until all wanted messages are disabled.
::android_atomic_write(1, &mIsWaitBufBack);
// (.1)
waitAndHandleReturnBuffers(pBufQueue); //等待BUF完成
//PreviewClient.BufOps.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\client\camclient\previewcallback)
// (1) deque buffers from processor.
rpBufQueue->dequeProcessor(vQueNode);
// (2) handle buffers dequed from processor.
ret = handleReturnBuffers(vQueNode); //这个和//单独分析8,onThreadLoop一样
mpRecordClient->startPreview()
RecordClient.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\v1\client\camclient\record)
if(mpParamsMgr->getInt(CameraParameters::KEY_PREVIEW_FRAME_RATE) > 30)
mRecBufNum = 5 + (mpParamsMgr->getInt(CameraParameters::KEY_PREVIEW_FRAME_RATE)/30)*2 + 2; //获得buf的数量
mpParamsMgr->set(MtkCameraParameters::KEY_VR_BUFFER_COUNT, mRecBufNum); //设置