天天看點

Android Camera提升幀率的方法

最近在做項目的時候,需要将Android camera的幀率盡可能提升到30幀/s,測試的過程發現一些特别的情況,camera api 1和camera api2,在不同手機平台上的表現還不相同。

Camera api 1

camera api1主要有以下兩種提升幀率的方法:

通過Camera.Parameters進行設定,主要有以下方法

setPreviewFpsRange(或setPreviewFrameRate)

Camera.Parameters parameters = camera.getParameters();

···

List<int[]> fpsList = parameters.getSupportedPreviewFpsRange();

if(fpsList != null && fpsList.size() > 0) {

    int[] maxFps = fpsList.get(0);

    for (int[] fps: fpsList) {

        if(maxFps[0] * maxFps[1] < fps[0] * fps[1]) {

            maxFps = fps;

        }

    }

    //注意setPreviewFpsRange的輸入參數是幀率*1000,如30幀/s則參數為30*1000

    parameters.setPreviewFpsRange(maxFps[0] , maxFps[1]);

    //setPreviewFrameRate的參數是實際的幀率

    //parameters.setPreviewFrameRate(MAX_FPS);

}      

測試發現,不進行任何幀率相關設定的時候,960P以上的分辨率已經會導緻輸出幀率降低,最低的時候僅有10幀/s,480P的輸出幀率還是接近30幀/s。這種情況下, 如果想要達到更大的幀率,例如960P的時候需要将幀率提高至30幀/s,采用setPreviewFpsRange(或setPreviewFrameRate)的方法已經不起作用了,這種方法隻能起到限制幀率的效果,如果需要将幀率提到最大,需要采用以下方法

setRecordingHint

Camera.Parameters parameters = camera.getParameters();

···

parameters.setRecordingHint(true);      

官方文檔對該api的注釋如下:

Sets recording mode hint. This tells the camera that the intent of the application is to record videos MediaRecorder.start(), not to take still pictures Camera.takePicture(Camera.ShutterCallback, Camera.PictureCallback, Camera.PictureCallback, Camera.PictureCallback). Using this hint can allow MediaRecorder.start() to start faster or with fewer glitches on output. This should be called before starting preview for the best result, but can be changed while the preview is active. The default value is false. The app can still call takePicture() when the hint is true or call MediaRecorder.start() when the hint is false. But the performance may be worse.

大緻的意思就是讓相機一直運作在視訊采集的狀态下,由于視訊采集的時候一般需要高幀率才能保證資料的完整,是以該狀态下的輸出幀率會保持在能達到的最大幀率

Camera api 2

使用Camera api 2之前要注意,檢視下裝置對于Camera api的支援級别

characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);

//CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY = 2

//CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_3 = 3

//CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED = 0

//CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL = 1

//LEGACY < LIMITED < FULL < LEVEL_3      
Range<Integer>[] fpsRange = characteristics.get(

    CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES);

    if(fpsRange != null && fpsRange.length > 0) {

    Range<Integer> maxFps = fpsRange[0];

    for (Range<Integer> aFpsRange : fpsRange) {

        if (maxFps.getLower() * maxFps.getUpper() < aFpsRange.getLower() * aFpsRange.getUpper()) {

            maxFps = aFpsRange;

        }

    }

    mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, maxFps);

}      

繼續閱讀