這可能是全網(wǎng)關(guān)于Camera慢動作錄像(SlowMotion)介紹最全的文章了

這是一篇關(guān)于慢動作錄像(slowmotion)的文章,看完后相信你對慢動作錄像不會再感到陌生了~

這篇文章針對下面幾點來展開:

1)寫這篇文章的原由?
2)什么是慢動作錄像(SlowMotionRecord)?
3)Android上如何實現(xiàn)慢動作錄像?
4)調(diào)試demo下載地址?
5)調(diào)試遇到的問題及解決?

一、寫這篇文章的原由?

2月份的時候,在一個音視頻開發(fā)的學(xué)習(xí)交流群里,有位網(wǎng)友問到"Android相機有啥設(shè)置可以做到slow motion?",我認(rèn)真的想了下,然后又簡單看了下高通的曉龍相機源碼,大概知道是怎么實現(xiàn)后,給了下思路。

后面我還一直在想這個事情,覺的自己給的思路太簡單了,有時間還是得再研究研究,自己得敲下代碼跑通下才好,于是就有了這篇文章。

二、什么是慢動作錄像(SlowMotionRecord)?

通常我們?nèi)搜勰軌蚪邮艿淖詈玫囊曨l幀速率是24幀/每秒左右。那如果我們用120幀/秒拍攝一個動作,再用24幀每秒來播放的話,視頻就放慢了5倍,這個就是慢動作錄像了。

慢動作錄像,又叫高幀率錄像(HFR),也就是以高fps(運行速率)捕獲、編碼并保存為30 fps(目標(biāo)速率),這種情況運行速率大于目標(biāo)速率。

還有一種模式叫做高速錄制(HSR) : 即以高fps(運行速率)捕獲、編碼并保存為高 fps(目標(biāo)速率),運行速率等于目標(biāo)速率。

這篇文章只介紹慢動作錄像。(調(diào)試環(huán)境基于高通曉龍865芯片 Android9.0)

三、Android上如何實現(xiàn)視頻慢動作?

有了上面關(guān)于慢動作的概念后,那在Android上如何用代碼來實現(xiàn)呢?說到錄像,那我們應(yīng)該要想到MediaRecorder了。慢動作,也就是高幀率錄像,那肯定得調(diào)用mediaRecorder設(shè)置高幀率了。

好了,我們還得再有一個概念,數(shù)據(jù)是從攝像頭sensor出來的,那我們需要120fps,總得攝像頭支持才行吧。所以呢,就有一個先決條件了,硬件得支持才行,下面會講如何查詢當(dāng)前硬件是否支持。

假設(shè)硬件支持的情況下,我們來看下軟件上應(yīng)用的調(diào)用情況。

1、新類CameraConstrainedHighSpeedCaptureSession

查看Android的開發(fā)文檔,我們可以看到,從Android 6.0開始,Camera相關(guān)的,添加了一個新的類CameraConstrainedHighSpeedCaptureSession,從描述上看,我們就可以知道,這個是專門為高速、高幀率錄像準(zhǔn)備的。換一句話說,也就是Android 6.0以上,Android本身才支持這個高速、高幀率錄像。(我在自己早年用的nubiya手機上看了下,Android 5.1的系統(tǒng),系統(tǒng)相機也帶了慢動作功能,不過它這個慢動作應(yīng)該是廠家自己定制開發(fā)的,那會Android還沒提供相關(guān)接口)

https://developer.android.google.cn/reference/android/hardware/camera2/package-summary.html

2、查詢當(dāng)前硬件是否支持高幀率錄像

通過CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS來獲取available size。如果存在available,則判斷為支持。

 public static boolean hasHighSpeedVideoConfigs(Context context, String cameraId) {
        try {
            CameraManager cameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
            CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
            HighSpeedVideoConfiguration[] highSpeedVideoConfigs = characteristics.get(
                    CameraCharacteristics.CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS);
            return highSpeedVideoConfigs != null && highSpeedVideoConfigs.length > 0;
        } catch (Exception e) {
     
        }
        return false;
    }
3、獲取支持的高幀率錄像videoSize

從map.getHighSpeedVideoSizes()中獲取支持的videoSize,然后選擇個合適的size,注意這里的previewSize需要和videoSize保持一致。

  CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
            StreamConfigurationMap map = characteristics
                    .get(SCALER_STREAM_CONFIGURATION_MAP);

  mVideoSize = chooseVideoSize(map.getHighSpeedVideoSizes());
  mPreviewSize = mVideoSize;//這里需要保持previewSize 和videoSize一致
4、CONTROL_AE_TARGET_FPS_RANGE設(shè)置為高幀率范圍(120,120)
   Range aeFps = new Range(120, 120);
   mPreviewBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, aeFps);
5、創(chuàng)建session采用createConstrainedHighSpeedCaptureSession

高幀率錄像創(chuàng)建session,使用專門提供的api接口。

 // Start a capture session
   mCameraDevice.createConstrainedHighSpeedCaptureSession(surfaces, new CameraCaptureSession.StateCallback() {
      @Override
      public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
         ......
      }

     @Override
     public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
          ......
     }
   }, mBackgroundHandler);
6、采用setRepeatingBurst

session configure成功后,調(diào)用setRepeatingBurst不停的request,這個和正常模式有點區(qū)別,正常模式是調(diào)用的setRepeatingRequest。

   CaptureRequest request = mPreviewBuilder.build();
   List<CaptureRequest> slowMoRequests = ((CameraConstrainedHighSpeedCaptureSession) mPreviewSession)
                       .createHighSpeedRequestList(request);

    mPreviewSession.setRepeatingBurst(slowMoRequests, null,
                     mBackgroundHandler);
7、MediaRecorder相關(guān)參數(shù)設(shè)置為對應(yīng)的高幀率參數(shù)

相對應(yīng)的,mediaRecorder的一些參數(shù)也需要設(shè)置為高幀率參數(shù)。

    mProfile = getProfile();
    int bitRate = getHighSpeedVideoEncoderBitRate(mProfile, 
    mProfile.videoFrameRate,
               VEDIO_HIGH_SPEED_FRAME_RATE);

    mMediaRecorder.setVideoEncodingBitRate(bitRate);
    mMediaRecorder.setVideoFrameRate(mProfile.videoFrameRate);
    mMediaRecorder.setCaptureRate(VEDIO_HIGH_SPEED_FRAME_RATE);
五、調(diào)試遇到的問題及解決方法
》》》》問題1:
Process: com.xcbj.camera, PID: 21818
   java.lang.IllegalArgumentException: Surface size 1440x1080 is not part of the high speed supported size list [1280x720, 720x480, 640x480, 1920x1080]
       at android.hardware.camera2.utils.SurfaceUtils.checkConstrainedHighSpeedSurfaces(SurfaceUtils.java:193)
       at android.hardware.camera2.impl.CameraDeviceImpl.createCaptureSessionInternal(CameraDeviceImpl.java:881)
       at android.hardware.camera2.impl.CameraDeviceImpl.createConstrainedHighSpeedCaptureSession(CameraDeviceImpl.java:627)
[分析]
》》》》問題2: Fps rang[30,30] in the request is not a supported hight speed fps range...
 Process: com.xcbj.camera, PID: 27138
   java.lang.IllegalArgumentException: Fps range [30, 30] in the request is not a supported 
high speed fps range [[120, 120], [240, 240], [480, 480], [30, 120], [30, 240], [30, 480]]
       at android.hardware.camera2.utils.SurfaceUtils.checkConstrainedHighSpeedSurfaces(SurfaceUtils.java:180)
       at android.hardware.camera2.impl.CameraConstrainedHighSpeedCaptureSessionImpl.createHighSpeedRequestList(CameraConstrainedHighSpeedCaptureSessionImpl.java:89)
[分析]

*本人從事Android Camera相關(guān)開發(fā)已有5年,
*目前在深圳上班,
*小伙伴記得點我頭像,看【個人介紹】進(jìn)行關(guān)注哦,希望和更多的小伙伴一起交流 ~

-------- 2021.03.25 深圳 00:53

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容