Так что я играл все выходные с помощью камеры2 api. Теперь я нахожусь в точке, где я начинаю понимать, как вещи связаны друг с другом. При тестировании api для реализации приложения для записи видео я ударил стену.Как повторно использовать поверхность MediaRecorder в Camera2 API на Android?
Я начал с изменения Android Camera2Video Sample в соответствии с моими потребностями. Меня беспокоит то, что после каждого процесса записи воссоздается сеанс камеры. Хуже того, когда начинается сеанс записи, происходит то, что сначала будет уничтожен сеанс предварительного просмотра, и будет создан сеанс записи. После завершения сеанса записи он уничтожается и создается новый сеанс предварительного просмотра.
В документации четко сказано:
Создание сессии является дорогостоящей операцией и может занять несколько сотен миллисекунд ... CameraCaptureSession Documentation
Результат выглядит довольно уродливо и экран заикается, когда я ударил запись и остановка. Я хотел улучшить это поведение, поэтому я возился с кодом.
Что я делаю сейчас я создаю мой один и только CameraSession
, где я добавить мой просмотр поверхности (TextureView
), а также поверхность с уже создана MediaRecorder
путем вызова метода getSurface
. Это отлично работает для первого видео, но когда я пытаюсь захватить второе видео, я получаю IllegalArgumentException: Bad argument passed to camera service
. Я думаю, что это связано с тем, что поверхность MediaRecorder
, которую я перехожу на CameraSession
на его создание, каким-то образом разрушена или изменена, когда я сброшу MediaRecorder
, чтобы подготовить новую запись.
Мой вопрос сейчас в том, есть ли какой-либо путь вокруг этой проблемы? (setInputSurface(Surface surface)
) может быть, но уровень api слишком высок, поэтому я не тестировал его.
Вот краткий обзор над соответствующими кодовыми частей:
настроить
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(); }
создать сеанс все могучее записи
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); }
начать запись видео
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();
остановка записи
mMediaRecorder.stop(); mMediaRecorder.reset(); showPreview(); setUpMediaRecorder(); // this is key to not get an error from the MediaRecorder
Все это работает отлично, и начнется запись видео и останавливается без икоты! Это потрясающе, но когда я возвращаюсь к шагу 3 (после 4), я получаю вышеупомянутый IllegalArgumentException: Bad argument passed to camera service
. Я продолжаю стучать головой о стену, но не могу найти пути решения этой проблемы.
Любая помощь очень ценится!
Спасибо!