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,會響應命令threadLoop
case 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 & List
if ( 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/cancelPrvOps
IExtImgProc::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); //設置