1. 程式人生 > >android camera2配置流程

android camera2配置流程

更新camera配置通過CameraAgent.CameraProxy.applySettings()實現
在camera_API1中
AndroidCameraAgentImpl.java

public boolean applySettings(CameraSettings settings) {
    return applySettingsHelper(settings, AndroidCameraStateHolder.CAMERA_IDLE |
        AndroidCameraStateHolder.CAMERA_UNLOCKED);
}

CameraAgent.java

protected boolean applySettingsHelper(CameraSettings settings,
                                      final int statesToAwait) {
    if (settings == null) {
        Log.v(TAG, "null argument in applySettings()");
        return false;
    }
    if (!getCapabilities().supports(settings)) {
        Log.w(TAG, "Unsupported settings in applySettings()"
); return false; } final CameraSettings copyOfSettings = settings.copy(); getDispatchThread().runJob(new Runnable() { @Override public void run() { getCameraState().waitForStates(statesToAwait); getCameraHandler().obtainMessage(CameraActions.APPLY_SETTINGS, copyOfSettings) .sendToTarget(); }}); return
true; }

camera的配置會儲存在CameraSettings,然後通過settings.copy()將它映象出一份,通過CameraActions.APPLY_SETTINGS訊息傳送給
AndroidCameraAgentImpl去接收,

case CameraActions.APPLY_SETTINGS: {
    Parameters parameters = mParameterCache.getBlocking();
    CameraSettings settings = (CameraSettings) msg.obj;
    applySettingsToParameters(settings, parameters);
    mCamera.setParameters(parameters);
    mParameterCache.invalidate();
    break;
}

通過applySettingsToParameters(settings, parameters);進行處理最後通過mCamera.setParameters(parameters);來使它生效。

在最新的camea_API2中,流程會有所不同,具體看如下
AndroidCamera2AgentImpl.java

@Override
public boolean applySettings(CameraSettings settings) {
    if (settings == null) {
        Log.w(TAG, "null parameters in applySettings()");
        return false;
    }
    if (!(settings instanceof AndroidCamera2Settings)) {
        Log.e(TAG, "Provided settings not compatible with the backing framework API");
        return false;
    }

    // Wait for any state that isn't OPENED
    //這裡和API1中一樣呼叫CameraAgent的applySettingsHelper函式
    if (applySettingsHelper(settings, ~AndroidCamera2StateHolder.CAMERA_UNOPENED)) {
        mLastSettings = settings;
        return true;
    }
    return false;
}

case CameraActions.APPLY_SETTINGS: {
    AndroidCamera2Settings settings = (AndroidCamera2Settings) msg.obj;
    applyToRequest(settings);
    break;
}

private void applyToRequest(AndroidCamera2Settings settings) {
    // TODO: If invoked when in PREVIEW_READY state, a new preview size will not take effect

    //將配置資訊儲存到Camera2RequestSettingsSet的mDictionary中
    mPersistentSettings.union(settings.getRequestSettings());
    mPreviewSize = settings.getCurrentPreviewSize();
    mPhotoSize = settings.getCurrentPhotoSize();

    if (mCameraState.getState() >= AndroidCamera2StateHolder.CAMERA_PREVIEW_ACTIVE) {
        // If we're already previewing, reflect most settings immediately
        try {
    //通過這裡將mDictionary中的配置寫入camera硬體中
            mSession.setRepeatingRequest(
                    mPersistentSettings.createRequest(mCamera,
                            CameraDevice.TEMPLATE_PREVIEW, mPreviewSurface),
                    /*listener*/mCameraResultStateCallback, /*handler*/this);
        } catch (CameraAccessException ex) {
            Log.e(TAG, "Failed to apply updated request settings", ex);
        }
    } else if (mCameraState.getState() < AndroidCamera2StateHolder.CAMERA_PREVIEW_READY) {
        // If we're already ready to preview, this doesn't regress our state
        changeState(AndroidCamera2StateHolder.CAMERA_CONFIGURED);
    }
}

Camera2RequestSettingsSet.java

//mPersistentSettings.createRequest函式如下
public CaptureRequest createRequest(CameraDevice camera, int template, Surface... targets)
        throws CameraAccessException {
    if (camera == null) {
        throw new NullPointerException("Tried to create request using null CameraDevice");
    }

    //建立CaptureRequest.Builder
    Builder reqBuilder = camera.createCaptureRequest(template);

    //將儲存在mDictionary中的camera配置資訊儲存到reqBuilder內的CameraMetadataNative中,
    //CameraMetadataNative最後會通過JNI方法CameraMetadata_writeValues更新資料
    for (Key<?> key : mDictionary.keySet()) {
        setRequestFieldIfNonNull(reqBuilder, key);
    }
    for (Surface target : targets) {
        if (target == null) {
            throw new NullPointerException("Tried to add null Surface as request target");
        }
        reqBuilder.addTarget(target);
    }
    return reqBuilder.build();
}

到此java層的基本流程就告一段落。可以通過adb shell dumpsys media.camera檢視camera配置。