2017-01-29 29 views
1

私はcamera2 apiで週末に遊んでいます。今私は物事がどのように結びついているかを理解し始めるところにいます。 ビデオ録画アプリを実装するためにAPIをテストしている間、私は壁にぶつかった。Androidのcamera2 APIでMediaRecorderのサーフェスを再利用するにはどうすればよいですか?

Android Camera2Video Sampleを私のニーズに変更することから始めました。私の悩みは、各録音プロセスの後にカメラセッションが再現されていることです。さらに悪いことに、レコーディングセッションが開始されると、プレビューセッションが最初に破棄され、レコーディングセッションが作成されます。録音セッションが終了すると、セッションが破棄され、新しいプレビューセッションが作成されます。

ドキュメント明記:セッションの作成

は高価な操作であり、数百ミリ秒を取ることができます... CameraCaptureSession Documentation

を私が打ったときの結果はかなり醜いと画面の吃音記録し、停止する。私はこの振る舞いを改善してコードを手にしたかったのです。私は今何

は、私はすでにそのgetSurfaceメソッドを呼び出すことによってMediaRecorderを作成したから、私のプレビュー表面(TextureView)を追加しても、表面の私の唯一無二のCameraSessionを作成することです。これは最初のビデオでうまく動作しますが、2番目のビデオをキャプチャしようとするとIllegalArgumentException: Bad argument passed to camera serviceとなります。これは、MediaRecorderの表面がCameraSessionに渡されたときに、新しい記録を準備するためにMediaRecorderをリセットしたときに何らかの形で破壊されたり変更されたりしたためです。

この問題を回避する方法はありますか? (setInputSurface(Surface surface))がAPIレベルが高すぎるためテストしなかった可能性があります。

  1. セットアップMediaRecorder

    private void setUpMediaRecorder() throws IOException { 
        if (mMediaRecorder == null) { 
         mMediaRecorder = new MediaRecorder(); 
        } 
        mMediaRecorder.setVideoEncodingBitRate(5000000); 
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); 
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); 
        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); 
        mMediaRecorder.setVideoFrameRate(24); 
        mMediaRecorder.setVideoSize(mVideoSize.getWidth(), mVideoSize.getHeight()); 
        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); 
        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); 
        mMediaRecorder.setOrientationHint(SENSOR_ORIENTATION_DEFAULT_DEGREES); 
        mNextVideoAbsolutePath = getVideoFilePath(); 
        mMediaRecorder.setOutputFile(mNextVideoAbsolutePath); 
        mMediaRecorder.prepare(); 
    } 
    
  2. が記録

    SurfaceTexture texture = mTextureView.getSurfaceTexture(); 
    texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); 
    
    List<Surface> surfaces = new ArrayList<>(); 
    // Set up Surface for the camera preview 
    mPreviewSurface = new Surface(texture); 
    surfaces.add(mPreviewSurface); 
    
    // Set up Surface for the MediaRecorder 
    mRecorderSurface = mMediaRecorder.getSurface(); 
    surfaces.add(mRecorderSurface); 
    
    // create the capture session 
    mCameraDevice.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() { 
    
        @Override 
        public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) { 
         mCameraSession = cameraCaptureSession; 
    
         // now that the session is created, start using it for the preview 
         showPreview(); 
        } 
    
        @Override 
        public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) { 
         .... 
          } 
         } 
        }, mBackgroundHandler); 
    } catch (CameraAccessException) { 
        e.printStackTrace(); 
    } 
    
    void showPreview() { 
        mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 
        mPreviewBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO); 
        mPreviewBuilder.addTarget(mPreviewSurface); 
        mCameraSession.setRepeatingRequest(mPreviewBuilder.build(), null, mBackgroundHandler); 
    } 
    
  3. 開始すべての強大なレコーディングセッションを作成します。ここでは

    は、関連するコード片の上に簡単な概要です動画

    mMediaRecorder.stop(); 
    mMediaRecorder.reset(); 
    showPreview(); 
    setUpMediaRecorder(); // this is key to not get an error from the MediaRecorder 
    

を記録

mVideoBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD); 
mVideoBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO); 
mVideoBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON); 
mVideoBuilder.addTarget(mPreviewSurface); 
mVideoBuilder.addTarget(mRecorderSurface); 
// set the request for the capture 
mCameraSession.setRepeatingRequest(mVideoBuilder.build(), null, mBackgroundHandler); 
// Start recording 
mMediaRecorder.start(); 
  • ストップはこのすべてが完璧に動作し、録画が開始され、任意のしゃっくりせずに停止します!素晴らしいですが、手順3(4の後)に戻ると、私は前述のIllegalArgumentException: Bad argument passed to camera serviceを取得します。私は壁に向かって私の頭を叩いているが、私はこの問題を回避する方法を見つけることができません。

    ご協力いただきありがとうございます。

    ありがとうございます!

  • 答えて

    1

    MediaRecorder#setInputSurface(android.view.Surface)をチェックアウト:

    は、SURFACEのビデオソースを使用した場合、永続的な表面を使用するレコーダーを設定します。

    私は、MediaRecorderキャプチャサーフェスを再利用する方法を見つけようとしているときに遭遇しました。このようにして、永続サーフェスをキャプチャセッションの出力サーフェスの1つに設定できます。新しいprepare()コールから生成されたMediaRecorderサーフェスを変更するだけでキャプチャセッションを再作成する必要はありません。

    Google NexusとPixelのカメラアプリは、プレビューに吃音なくビデオ録画を開始したり停止したりすることができるので、何とかすることは間違いありません。

    関連する問題